Merge branch 'release/3.0.0-RC1'
diff --git a/.gitignore b/.gitignore
index 9a8a6de..0fa55ee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,3 +16,7 @@
 .nb-gradle
 .gradletasknamecache
 private/cache
+node_modules
+gradle-user-home
+profile-out*
+npm-debug.log
\ No newline at end of file
diff --git a/KEYS b/KEYS
index 1aa2d38..8eca70e 100644
--- a/KEYS
+++ b/KEYS
@@ -1,4 +1,4 @@
-This file contains the GPG keys of Apache Zest developers.
+This file contains the GPG keys of Apache Polygene developers.
 
 Users:    gpg --import KEYS
 
@@ -24,9 +24,9 @@
 ********************************* PLEASE NOTE **********************************
 
   Releases will be signed using one of the keys present in this file. This file
-  will be available with the distributed Apache Zest releases at:
+  will be available with the distributed Apache Polygene releases at:
 
-      https://dist.apache.org/repos/dist/zest/KEYS
+      https://dist.apache.org/repos/dist/release/polygene/KEYS
 
 ********************************************************************************
 
@@ -156,11 +156,13 @@
 -----END PGP PUBLIC KEY BLOCK-----
 
 
-pub   8192R/7D0391AC 2015-04-27
-uid                  Paul Merlin (Apache) <paulmerlin@apache.org>
-sig 3        7D0391AC 2015-04-27  Paul Merlin (Apache) <paulmerlin@apache.org>
-sub   8192R/091BA717 2015-04-27
-sig          7D0391AC 2015-04-27  Paul Merlin (Apache) <paulmerlin@apache.org>
+pub   rsa8192 2015-04-27 [SC]
+      2E8933D9CBD2C88991E7B186D79DEC497D0391AC
+uid           [  full  ] Paul Merlin (Apache) <paulmerlin@apache.org>
+sig 3        D79DEC497D0391AC 2015-04-27  Paul Merlin (Apache) <paulmerlin@apache.org>
+sig          995ADEF432D40AD6 2017-04-12  Niclas Hedhman <niclas@hedhman.org>
+sub   rsa8192 2015-04-27 [E]
+sig          D79DEC497D0391AC 2015-04-27  Paul Merlin (Apache) <paulmerlin@apache.org>
 
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: GnuPG/MacGPG2 v2.0.22 (Darwin)
diff --git a/LICENSE.txt b/LICENSE.txt
index 83c4864..1840437 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -178,9 +178,9 @@
 
 =======================================================================
 
-Apache Zest™ subcomponents:
+Apache Polygene™ subcomponents:
 
-The Apache Zest™ project contains subcomponents with separate copyright
+The Apache Polygene™ project contains subcomponents with separate copyright
 notices and license terms. Your use of the source code for the these
 subcomponents is subject to the terms and conditions of the following
 licenses.
@@ -189,7 +189,7 @@
  The MIT License
 -----------------------------------------------------------------------
 
-The Apache Zest™ project bundles the following files under the MIT License:
+The Apache Polygene™ project bundles the following files under the MIT License:
 
 - jQuery v1.6.4 (https://jquery.com/)
   Bundled in the documentation minisite.
@@ -225,14 +225,14 @@
  The BSD 3-Clauses License
 -----------------------------------------------------------------------
 
-The Apache Zest™ project bundles the following files under the BSD
+The Apache Polygene™ project bundles the following files under the BSD
 3-Clauses License:
 
 -----------------------------------------------------------------------
  The W3C Software License
 -----------------------------------------------------------------------
 
-The Apache Zest™ project bundles the following files under the W3C Software
+The Apache Polygene™ project bundles the following files under the W3C Software
 License:
 
 - The "xml:" Namespace (http://www.w3.org/XML/1998/namespace)
diff --git a/NOTICE.txt b/NOTICE.txt
index abdd654..de8a58e 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -1,5 +1,31 @@
-Apache Zest™ (Java Edition) SDK
-Copyright 2015 The Apache Software Foundation.
+Apache Polygene™ (Java Edition) SDK
+Copyright 2015-2016 The Apache Software Foundation.
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
+
+IMPORTANT:
+This distribution may include cryptographic software. The country in which you
+currently reside may have restrictions on the import, possession, use, and/or
+re-export to another country, of encryption software. BEFORE using any
+encryption software, please check your country's laws, regulations and
+policies concerning the import, possession, or use, and re-export of encryption
+software, to see if this is permitted. See <http://www.wassenaar.org/> for more
+information.
+
+The U.S. Government Department of Commerce, Bureau of Industry and Security
+(BIS), has classified this software as Export Commodity Control Number (ECCN)
+5D002.C.1, which includes information security software using or performing
+cryptographic functions with asymmetric algorithms. The form and manner of this
+Apache Software Foundation distribution makes it eligible for export under the
+License Exception ENC Technology Software Unrestricted (TSU) exception (see the
+BIS Export Administration Regulations, Section 740.13) for both object code and
+source code.
+
+The following provides more details on the included cryptographic software:
+libraries/http               - has a dependency on Bouncy Castle
+libraries/restlet            - has a dependency on Apache HttpComponents Core
+libraries/shiro-core         - has a dependency on Apache Shiro
+libraries/shiro-web          - has a dependency on Apache Shiro
+extensions/entitystore-geode - has a dependency on Apache Geode
+extensions/indexing-solr     - has a dependency on Apache Lucene
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..73dafff
--- /dev/null
+++ b/README.md
@@ -0,0 +1,87 @@
+# Apache Polygene™ (Java Edition)
+
+> Composite Oriented Programming on the Java platform
+
+[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
+[![Build Status](https://builds.apache.org/buildStatus/icon?job=Polygene(JavaEdition)-develop-java8-checkDists)](https://builds.apache.org/view/P/view/Polygene/job/Polygene(JavaEdition)-develop-java8-checkDists/)
+
+## What is Apache Polygene™
+
+The short answer is that **Apache Polygene™** is a community based effort exploring Composite Oriented Programming for
+domain centric application development. This includes evolved concepts from
+[Aspect Oriented Programming](https://en.wikipedia.org/wiki/Aspect-oriented_programming),
+[Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection)
+and [Domain Driven Design](https://en.wikipedia.org/wiki/Domain-driven_design).
+
+**Composite Oriented Programming** allows developers to work with _fragments_, smaller than classes, and _compose_
+fragments into larger _composites_ which acts like the regular objects. Apache Polygene™ also tackles the enforcement
+of _application_ composition, i.e. composites are declared in _modules_, modules are contained in _layers_ and access
+between layers are controlled/enforced.
+
+**Apache Polygene™ (Java Edition)**, first Apache Polygene sub-project, is an implementation of Composite Oriented
+Programming, using the standard Java platform, without the use of any pre-processors or new language elements.
+Everything you know from Java still applies and you can leverage both your experience and toolkits to become more
+productive with Composite Oriented Programming today.
+
+The Apache Polygene™ community welcomes any effort exploring Composite Oriented Programming for domain centric
+application development using any technology.
+
+Please see https://polygene.apache.org for more information.
+
+## Downloading
+
+You can download released versions from: https://polygene.apache.org/download.html
+
+## Building
+
+Build instructions can be found here: http://polygene.apache.org/java/latest/build-system.html
+
+## Contributing
+
+Polygene™ started in 2007, and is still in heavy development under the umbrella of
+the Apache Polygene™ project at the Apache Software Foundation. We would like
+developers around the world to participate in the advancement of this
+cool, new and challenging technology. We are especially interested in
+people willing to help improve the SDK, samples, tutorials, documentation
+and other supporting material.
+
+Please see http://polygene.apache.org/community/participate.html and http://zest.apache.org/community/playing_field.html
+for more information.
+
+## Opening in your IDE
+
+### IntelliJ IDEA
+
+IntelliJ IDEA Community Edition has everything you need to open Apache Polygene™.
+To open the project in IDEA, simply open this repository as a project.
+During import, make sure *"Create separate module per source set"* is checked.
+
+### Netbeans
+
+To open Apache Polygene™ in Netbeans you need to install the _Gradle Support_ plugin.
+It is directly available via the Update Center (Tools/Plugins: Look for _Gradle Support_).
+Then, to open the project in Netbeans, simply open this repository as a project.
+
+### Eclipse
+
+Eclipse supports Gradle based projects out of the box thanks to the Buildship project.
+To open the project in Eclipse, simply import this repository as a Gradle project.
+
+## Licensing
+
+    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.
+
+
diff --git a/README.txt b/README.txt
deleted file mode 100644
index dcbe6df..0000000
--- a/README.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-
-Welcome to the world of Apache Zest
-   - Composite Oriented Programming on the Java platform.
-
-
-This Apache Zest™ Source Distribution contains everything you need to
-create Zest™ applications.
-
-
-Zest™ started in 2007, and is still in heavy development under the umbrella of
-the Apache Zest™ project at the Apache Software Foundation. We would like
-developers around the world to participate in the advancement of this
-cool, new and challenging technology. We are especially interested in
-people willing to help improve the SDK, samples, tutorials, documentation
-and other supporting material.
-
-Please see https://zest.apache.org for more information.
-
-
-Licensing
----------
-All Zest™ code is licensed under an Apache License.
-
-Third-Party Dependencies may be licensed under other terms. The only
-required dependencies are SLF4J (MIT Licence), ASM (BSD Licence) and
-Joda-Time (Apache Licence).
-
-Finally, Zest™ TestSupport depends on JUnit 4.x and its dependencies, which
-is also not included in the SDK itself, as it is present among most Java
-developers.
-
-
-Dependencies not included
--------------------------
-The source distribution contains Zest™ sources only to keep the download
-size small. The Gradle build automatically downloads needed dependencies.
-If you need to go offline type `./gradlew goOffline` to ensure all needed
-dependencies are cached by Gradle.
-
-If you prefer to use a dependency management system, go to:
-https://zest.apache.org/java/latest/howto-depend-on-zest.html
-
-
-Building Apache Zest
----------------------
-To build Zest™ from sources you only need to have a valid Java JDK >= 7
-installation.
-
-If you want to build the Zest™ manual, then you also need valid Asciidoc
-(http://www.methods.co.nz/asciidoc/) and Docbook-XSL installations.
-
-Here is how to run a full build with checks:
-
-    ./gradlew check assemble
-
-Read the Zest™ Build System tutorial for more details:
-https://zest.apache.org/java/latest/build-system.html
-
-
-Thank you for trying out Apache Zest™ and Composite Oriented Programming.
-
-
--- Apache Zest™ Team
-
diff --git a/build.gradle b/build.gradle
index d7666e6..ff63c21 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,1034 +1,21 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
  */
 
-project.ext {
-  title = "Apache Zest™ (Java Edition) SDK"
-  description = "Apache Zest™ (Java Edition) is a framework for domain centric application development, including evolved concepts from AOP, DI and DDD."
-  testFailures = [ ]
-  mainClassName = 'org.qi4j.container.Main'
-  groovycMain_mx = "700m"
-  groovycMain_permSize = "512m"
-  groovycMain_maxPermSize = "512m"
-}
-
-buildscript {
-  repositories {
-    maven { url "https://plugins.gradle.org/m2/" }
-    jcenter()
-  }
-  dependencies {
-    classpath 'gradle.plugin.org.nosphere.apache:creadur-rat-gradle:0.1.2'
-    classpath 'gradle.plugin.org.nosphere.honker:honker-gradle:0.2.1'
-    classpath 'org.hibernate.build.gradle:gradle-maven-publish-auth:2.0.1'
-  }
-}
-
-
-apply plugin: 'java'
-apply plugin: 'idea'
-apply plugin: 'signing'
-apply plugin: 'maven'
-apply plugin: 'maven-publish-auth'
-apply plugin: 'project-report'
-apply from: 'libraries.gradle'
-apply plugin: 'org.nosphere.apache.rat'
-
-targetCompatibility = "1.7"
-sourceCompatibility = "1.7"
-
-// Collect the modules that fulfills the Release Criteria.
-project.ext {
-  releaseSpec = new org.qi4j.gradle.plugin.ModuleReleaseSpecification()
-  releaseApprovedProjects = allprojects.findAll( { p -> rootProject.releaseSpec.satisfiedBy( p ) } )
-}
-
-// Toggle signing, used by the source distribution by setting the skipSigning property in gradle.properties
-project.ext.skipSigning = rootProject.hasProperty( 'skipSigning' ) ? rootProject.skipSigning : false
-
-rat {
-    onlyIf { version != '0' }
-    excludes = [
-        '**/.DS_Store/**', '**/._*',
-        // Git Files
-        '**/.git/**', '**/.gitignore',
-        // Gradle Files
-        'gradle/wrapper/**', '**/gradlew', '**/gradlew.bat', '**/.gradle/**',
-        // Build Output
-        '**/build/**', '**/derby.log', 'out/**',
-        // IDE Files
-        '**/.idea/**', '**/*.iml', '**/*.ipr', '**/*.iws',
-        '**/.settings/**', '**/.classpath', '**/.project',
-        '**/.gradletasknamecache', '**/private/cache/**',
-        '**/.nb-gradle-properties', '**/.nb-gradle/**',
-        // JSON files are not allowed to have comments, according to http://www.json.org/ and http://www.ietf.org/rfc/rfc4627.txt
-        '**/*.json',
-        // Various Text Resources
-        '**/README.*','**/README*.*', '**/TODO',
-        '**/src/main/resources/**/*.txt',
-        '**/src/test/resources/**/*.txt',
-        'libraries/rest-server/src/main/resources/**/*.htm',
-        'libraries/rest-server/src/main/resources/**/*.atom',
-        'tools/qidea/src/main/resources/**/*.ft',
-        'tools/qidea/src/main/resources/**/*.template',
-        // Graphic Resources
-        '**/*.svg', '**/*.gif', '**/*.png', '**/*.jpg', '**/*.psd',
-        // Keystores
-        '**/*.jceks',
-        // Syntax Highlighter - MIT
-        'manual/**/sh*.css', 'manual/**/sh*.js',
-        // jQuery & plugins - MIT
-        'manual/**/jquery*.js',
-        // W3C XML Schemas - W3C Software License
-        'samples/rental/src/main/resources/*.xsd',
-    ]
-}
-
-
-// External tools BEGIN ---------------------------------------------------
-
-// IDEA plugin configuration
-idea.project.ipr {
-  withXml { provider ->
-    provider.node.component.find { it.@name == 'VcsDirectoryMappings' }.mapping.@vcs = 'Git'
-  }
-}
-
-// External tools END -----------------------------------------------------
-
-// Define repositories URLs here so we can reuse them in the build script
-// Needed as Gradle forbid access to declared repositories URLs by design
-// Releasable submodules should not declare repositories in their own build files
-def repos_urls = [
-  mavenCentral: "http://repo1.maven.org/maven2/",
-  ops4j: "http://repository.ops4j.org/maven2/",
-  restlet: 'http://maven.restlet.org/',
-  clojars: "http://clojars.org/repo/",
-]
-
-allprojects {
-
-  apply plugin: 'eclipse'
-  apply plugin: 'idea'
-  apply plugin: 'signing'
-  apply plugin: 'java'
-//  apply plugin: 'checkstyle'
-  apply plugin: 'project-report'
-  apply plugin: 'maven'
-  apply plugin: 'org.nosphere.honker'
-
-
-  defaultTasks 'classes', 'test'
-
-  group = name == 'org.qi4j' ? 'org.qi4j' : name.substring( 0, name.lastIndexOf( '.' ) )
-  if( version == 'unspecified' ) {
-    version = System.properties.version ?: "0"
-  }
-  
-  // UTF-8 For all compilations and javadocs
-  // Deprecation warnings for all compilations
-  // Unchecked warnings for non-test core compilations
-  tasks.withType(JavaCompile) {
-    options.encoding = 'UTF-8'
-    options.compilerArgs << "-Xlint:deprecation"
-  }
-  if("core".equals(group)) {
-    tasks.matching({ task -> task instanceof JavaCompile && !task.name.contains('test') }).
-        each({ task -> task.options.compilerArgs << "-Xlint:unchecked" })
-  }
-  tasks.withType(Javadoc) {
-    options.encoding = 'UTF-8'
-    options.docEncoding = 'UTF-8'
-    options.charSet = 'UTF-8'
-    options.noTimestamp = true
-    options.links = [
-      'http://docs.oracle.com/javase/7/docs/api/',
-      'http://www.joda.org/joda-time/apidocs/',
-      'http://www.json.org/javadoc/',
-      'http://junit.org/javadoc/latest/'
-    ]
-    // exclude '**/internal/**'
-  }
-
-  repositories {
-    mavenCentral()
-    maven { name 'ops4j-repo'; url repos_urls.ops4j }
-    maven { name 'restlet-repo'; url repos_urls.restlet }
-    maven { name 'clojars-repo'; url repos_urls.clojars }
-  }
-
-  // Artifact upload global configuration BEGIN -----------------------------
-
-  def uploadSnapshots = version.contains("SNAPSHOT")
-  def uploadReleases = ! uploadSnapshots
-  // By default RELEASES are signed, SNAPSHOTS are not
-  // Signing can be turned on or off by setting the uploadSigned property
-  def uploadSigned = rootProject.hasProperty('uploadSigned') \
-                        ? rootProject.uploadSigned : uploadReleases \
-                        ? true : false
-  // By default RELEASES must satisfy ReleaseSpecification, SNAPSHOT don't
-  // ReleaseSpecification usage can be turned on or off by setting the uploadReleaseSpec property
-  def uploadReleaseSpec = rootProject.hasProperty('uploadReleaseSpec') \
-                             ? rootProject.uploadReleaseSpec : uploadReleases \
-                             ? true : false
-  // By default RELEASES and SNAPSHOTS are uploaded using HTTP
-  // Used Wagon can be overriden by setting the uploadWagon property
-  // def wagonSSH = "org.apache.maven.wagon:wagon-ssh:2.2"
-  // def wagonWEBDAV = "org.apache.maven.wagon:wagon-webdav:1.0-beta-2"
-  def wagonHTTP = "org.apache.maven.wagon:wagon-http:2.2"
-  def uploadWagon = rootProject.hasProperty('uploadWagon') \
-                        ? rootProject.uploadWagon : wagonHTTP
-  // By default RELEASES and SNAPSHOTS are uploaded to Apache Nexus
-  // Target repository can be overriden by setting the uploadRepository property
-  def releasesRepositoryName = "apache.releases.https"
-  def releasesRepository = "https://repository.apache.org/service/local/staging/deploy/maven2"
-  def snapshotsRepositoryName = "apache.snapshots.https"
-  def snapshotsRepository = "https://repository.apache.org/content/repositories/snapshots"
-  def uploadRepositoryName = rootProject.hasProperty('uploadRepositoryName') \
-                            ? rootProject.uploadRepositoryName \
-                            : uploadReleases ? releasesRepositoryName : snapshotsRepositoryName
-  def uploadRepository = rootProject.hasProperty('uploadRepository') \
-                            ? rootProject.uploadRepository \
-                            : uploadReleases ? releasesRepository : snapshotsRepository
-  // No username/password is provided by default
-  // If needed set them using the uploadUsername and uploadPassword properties
-  def uploadUsername = rootProject.hasProperty('uploadUsername') ? rootProject.uploadUsername : null
-  def uploadPassword = rootProject.hasProperty('uploadPassword') ? rootProject.uploadPassword : null
-
-  // Artifact upload global configuration END -------------------------------
-
-
-  configurations {
-    archives
-    deployerJars
-    provided
-    compile.extendsFrom provided
-    runtime.extendsFrom compile
-  }
-
-  dependencies {
-    testCompile( libraries.ant )
-    testCompile( libraries.ant_junit )
-    testCompile( libraries.junit )
-    testRuntime( libraries.asm, libraries.asm_commons, libraries.asm_util )
-    deployerJars( uploadWagon )
-  }
-
-  test.onlyIf { !project.hasProperty( 'skipTests' ) }
-  test {
-      testLogging {
-          info {
-              exceptionFormat "full"
-          }
-      }
-  }
-
-  sourceSets {
-    main {
-      output.dir( honkerGenDependencies.outputDir, builtBy: honkerGenDependencies )
-      output.dir( honkerGenLicense.outputDir, builtBy: honkerGenLicense )
-      output.dir( honkerGenNotice.outputDir, builtBy: honkerGenNotice )
-    }
-    docs {
-      resources {
-        srcDir 'src/docs'
-      }
-    }
-  }
-
-  honker {
-    // Project License, applied to all submodules
-    license 'Apache 2'
-    // Dependencies (transitive or not) with no license information, overriding them
-    licenseOverride { candidate ->
-      if( candidate.group == 'asm' || candidate.module == 'prefuse-core' ) {
-        candidate.license = 'BSD 3-Clause'
-      }
-      if( candidate.group == 'org.apache.httpcomponents'
-          || candidate.group == 'jdbm'
-          || candidate.group == 'org.osgi'
-          || candidate.group.startsWith( 'org.restlet' ) ) {
-        candidate.license = 'Apache 2'
-      }
-    }
-  }
-  honkerGenNotice {
-    header = 'Apache Zest'
-    footer = 'This product includes software developed at\nThe Apache Software Foundation (http://www.apache.org/).\n'
-  }
-  check.dependsOn honkerCheck
-
-  project.ext {
-    javaDir = new File( "$projectDir/src/main/java" )
-    scalaDir = new File( "$projectDir/src/main/scala" )
-    groovyDir = new File( "$projectDir/src/main/groovy")
-    documentationDir = new File( "$projectDir/src/docs" )
-    testJavaDir = new File( "$projectDir/src/tests/java" )
-    testScalaDir = new File( "$projectDir/src/tests/scala" )
-    testGroovyDir = new File( "$projectDir/src/tests/groovy")
-  }
-
-  // Actual code projects BEGIN -------------------------------------------
-  if( ext.javaDir.isDirectory() || ext.scalaDir.isDirectory() || ext.groovyDir.isDirectory() ||
-      ext.testJavaDir.isDirectory() || ext.testScalaDir.isDirectory() || ext.testGroovyDir.isDirectory() )
-  {
-    apply plugin: 'jacoco'
-    apply plugin: 'osgi'
-    apply plugin: VersionClass
-    apply plugin: AsciidocBuildInfo
-
-//    if( name == "org.qi4j.core.runtime" )
-//    {
-//      checkstyleMain {
-//        configFile = new File( "$rootProject.projectDir.absolutePath/etc/qi4j-runtime-checkstyle.xml" )
-//        ignoreFailures = true
-//      }
-//    }
-//    else
-//    {
-//      checkstyleMain {
-//        configFile = new File( rootProject.projectDir.absolutePath.toString() + '/etc/qi4j-api-checkstyle.xml' )
-//        ignoreFailures = true
-//        reporting.baseDir = "$rootProject.reporting.baseDir/checkstyle"
-//      }
-//    }
-//    checkstyleTest {
-//      configFile = new File( "$rootProject.projectDir.absolutePath/etc/qi4j-tests-checkstyle.xml" )
-//      ignoreFailures = true
-//    }
-//
-//    checkstyleVersion {
-//      configFile = new File( "$rootProject.projectDir.absolutePath/etc/qi4j-tests-checkstyle.xml" )
-//      ignoreFailures = true
-//    }
-
-    jar {
-      manifest {
-        license = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
-        docURL = 'https://zest.apache.org'
-        description = project.description ?: 'Apache Zest™ (Java Edition) is a platform for Composite Oriented Programming'
-        vendor = 'The Apache Software Foundation, https://www.apache.org'
-        instruction '-debug', 'true'
-      }
-    }
-
-    signing {
-      required { rootProject.version != '0' && uploadSigned }
-      sign configurations.archives
-    }
-    signArchives.onlyIf { !rootProject.skipSigning }
-
-    task sourceJar( type: Jar ) {
-      classifier = "sources"
-      from sourceSets.main.allSource
-    }
-
-    task testSourceJar( type: Jar ) {
-      classifier = "testsources"
-      from sourceSets.test.allSource
-    }
-
-    task javadocJar( type: Jar ) {
-      classifier = "javadoc"
-      from javadoc.destinationDir
-      dependsOn javadoc
-    }
-
-    artifacts {
-      archives sourceJar, testSourceJar, javadocJar
-    }
-
-    def testProperties = [
-            'proxySet': System.properties[ 'proxySet' ],
-            'proxyHost': System.properties[ 'proxyHost' ],
-            'proxyPort': System.properties[ 'proxyPort' ] ]
-
-    test {
-      maxHeapSize = "1024m"
-      systemProperties = testProperties
-      systemProperties['user.dir'] = workingDir // GRADLE-2859
-      ignoreFailures = true
-      reports.html.enabled(true)
-      afterSuite { descriptor, result ->
-        if( result.resultType == TestResult.ResultType.FAILURE )
-        {
-          rootProject.ext.testFailures << project
-        }
-      }
-    }
-    jacoco {
-      toolVersion = '0.7.2.201409121644'
-    }
-
-//    // Create checkstyle report
-//    task checkstyleReport( type: Xslt, dependsOn: check ) {
-//      source project.checkstyle.reportsDir
-//      include '*.xml'
-//      destDir = file( "build/reports/checkstyle/" )
-//      extension = 'html'
-//      stylesheetFile = file( "$rootProject.projectDir/etc/checkstyle-noframes.xsl" )
-//    }
-//
-
-    // Dependency Report generate only the runtime configuration
-    // The report is packaged in the SDK distributions
-    dependencyReport {
-        configurations = [ project.configurations.runtime ]
-    }
-
-    task minBuild {
-      dependsOn classes
-      dependsOn test
-    }
-
-  }
-  // Actual code projects END ---------------------------------------------
-
-  // Upload Archives - Artifact Deployment
-  uploadArchives.doFirst {
-    if( version == "0" )
-    {
-      throw new GradleException( "'version' must be given as a system property to perform a release." )
-    }
-  }
-
-  uploadArchives.onlyIf { ( !uploadReleaseSpec || ( releaseApprovedProjects.contains( project ) || project == rootProject ) ) && !project.hasProperty( 'skipUpload' ) }
-  uploadArchives {
-    dependsOn check
-    repositories.mavenDeployer {
-      if( uploadSigned )
-        beforeDeployment { MavenDeployment deployment -> signing.signPom( deployment ) }
-      configuration = configurations.deployerJars
-      repository(id: uploadRepositoryName, url: uploadRepository) {
-        if( uploadUsername )
-          authentication(userName: uploadUsername, password: uploadPassword)
-      }
-      snapshotRepository(id: uploadRepositoryName, url: uploadRepository) {
-        if( uploadUsername )
-          authentication(userName: uploadUsername, password: uploadPassword)
-      }
-    }
-  }
-  apply from: "$rootProject.projectDir/maven-compat.gradle"
-  apply plugin: 'maven-publish-auth' // Bug in maven-publish-auth require apply after uploadArchives setup
-
-  idea.module.iml {
-    whenMerged { module ->
-      module.dependencies*.exported = true
-    }
-  }
-} // allprojects END -------------------------------------------------------
-
-// Allow easy download of all dependencies to go offline
-// ./gradlew goOffline
-task goOffline {
-  doLast {
-    allprojects.configurations.flatten()*.resolvedConfiguration
-  }
-}
-
-gradle.taskGraph.whenReady {taskGraph ->
-  taskGraph.allTasks.last().doLast {
-    if( rootProject.ext.testFailures )
-    {
-      println "\nTest failures in:"
-      rootProject.ext.testFailures.unique().each { project -> println "  " + project.name }
-      println ""
-      throw new RuntimeException( "There was TEST FAILURES!! See list above." )
-    }
-  }
-}
-
-task globalTestReport( type: TestReport ) {
-  destinationDir = file("$buildDir/reports/tests")
-  reportOn subprojects*.test
-}
-
-test {
-  dependsOn subprojects*.test, globalTestReport
-  reports.html.enabled = false
-}
-
-// Jacoco
-configurations {
-  jacoco
-}
-dependencies {
-  jacoco 'org.jacoco:org.jacoco.ant:0.7.2.201409121644'
-}
-// Generate a global code codeverage report
-task coverageReport {
-  dependsOn subprojects*.test
-  def outputPath = "build/reports/coverage"
-  def coveredProjects = subprojects.findAll { p -> new File( "${p.buildDir.path}/jacoco" ).exists() }
-  def coreProjects = coveredProjects.findAll { p -> p.name.startsWith('org.qi4j.core' ) }
-  def libProjects = coveredProjects.findAll { p -> p.name.startsWith( 'org.qi4j.lib' ) }
-  def extProjects = coveredProjects.findAll { p -> p.name.startsWith( 'org.qi4j.ext' ) }
-  def toolsProjects = coveredProjects.findAll { p -> p.name.startsWith( 'org.qi4j.tool' ) }
-  def tutoProjects = coveredProjects.findAll { p -> p.name.startsWith( 'org.qi4j.tuto' ) }
-  def samplesProjects = coveredProjects.findAll { p -> p.name.startsWith( 'org.qi4j.sample' ) }
-  ant {
-    taskdef name:'jacocoreport', classname: 'org.jacoco.ant.ReportTask', classpath: configurations.jacoco.asPath
-    mkdir dir: outputPath
-    jacocoreport {
-      executiondata {
-        coveredProjects.collect { p -> fileset( dir: "${p.buildDir.path}/jacoco" ) { include( name: '*.exec' ) } }
-      }
-      structure( name: "Apache Zest™ (Java Edition) SDK" ) {
-        group( name: "Core" ) {
-          classfiles { coreProjects.collect { p -> fileset dir: "${p.buildDir.path}/classes/main" } }
-          sourcefiles { coreProjects.collect { p -> fileset dir: "${p.projectDir.path}/src/main/java" } }
-        }
-        group( name: "Libraries" ) {
-          classfiles { libProjects.collect { p -> fileset dir: "${p.buildDir.path}/classes/main" } }
-          sourcefiles { libProjects.collect { p -> fileset dir: "${p.projectDir.path}/src/main/java" } }
-        }
-        group( name: "Extensions" ) {
-          classfiles { extProjects.collect { p -> fileset dir: "${p.buildDir.path}/classes/main" } }
-          sourcefiles { extProjects.collect { p -> fileset dir: "${p.projectDir.path}/src/main/java" } }
-        }
-        group( name: "Tools" ) {
-          classfiles { toolsProjects.collect { p -> fileset dir: "${p.buildDir.path}/classes/main" } }
-          sourcefiles { toolsProjects.collect { p -> fileset dir: "${p.projectDir.path}/src/main/java" } }
-        }
-        group( name: "Tutorials" ) {
-          classfiles { tutoProjects.collect { p -> fileset dir: "${p.buildDir.path}/classes/main" } }
-          sourcefiles { tutoProjects.collect { p -> fileset dir: "${p.projectDir.path}/src/main/java" } }
-        }
-        group( name: "Samples" ) {
-          classfiles { samplesProjects.collect { p -> fileset dir: "${p.buildDir.path}/classes/main" } }
-          sourcefiles { samplesProjects.collect { p -> fileset dir: "${p.projectDir.path}/src/main/java" } }
-        }
-      }
-      csv  destfile: "${outputPath}/jacoco.csv", encoding: "UTF-8"
-      xml  destfile: "${outputPath}/jacoco.xml", encoding: "UTF-8"
-      html destdir:  outputPath, encoding: "UTF-8", locale: "en", footer: "Apache Zest™ (Java Edition) SDK"
-    }
-  }
-  inputs.dir subprojects.collect { p -> "${p.buildDir.path}/jacoco" }
-  outputs.dir outputPath
-}
-
-
-// Build the whole SDK public Javadoc
-task javadocs( type: Javadoc ) {
-
-  options.docFilesSubDirs = true
-  options.encoding = "UTF-8"
-  options.overview = "${rootProject.projectDir}/src/javadoc/overview.html"
-  title = "${rootProject.title} ${version}"
-  def apiSources = releaseApprovedProjects.findAll( { project ->
-    ( project.name.startsWith( 'org.qi4j.core' ) && !project.name.startsWith( 'org.qi4j.core.runtime' ) ) ||
-    project.name.startsWith( 'org.qi4j.library' ) ||
-    project.name.startsWith( 'org.qi4j.extension' ) ||
-    project.name.startsWith( 'org.qi4j.tool' )
-  } )
-  source apiSources.collect { project ->
-    project.sourceSets.main.allJava
-  }
-  destinationDir = project.file( "$project.docsDir/javadocs" )
-  // Might need a classpath
-  classpath = files( apiSources.collect { project ->
-    project.sourceSets.main.compileClasspath
-  } )
-  options.group( [ "Core API": [ "org.qi4j.api", "org.qi4j.api.*", "org.qi4j.io", "org.qi4j.functional" ],
-                         "Core Bootstrap": [ "org.qi4j.bootstrap", "org.qi4j.bootstrap.*" ],
-                         "Core SPI": [ "org.qi4j.spi", "org.qi4j.spi.*" ],
-                         "Libraries": [ "org.qi4j.library.*", "org.qi4j.logging", "org.qi4j.logging.*", "org.qi4j.lang.*" ],
-                         "Extensions": [ "org.qi4j.valueserialization.*", "org.qi4j.entitystore.*", "org.qi4j.index.*", "org.qi4j.metrics.*", "org.qi4j.cache.*", "org.qi4j.migration", "org.qi4j.migration.*" ],
-                         "Tools": [ "org.qi4j.tools.*", "org.qi4j.envisage", "org.qi4j.envisage.*", "org.qi4j.library.swing.entityviewer" ],
-                         "Test Support": [ "org.qi4j.test", "org.qi4j.test.*" ]
-                 ] )
-
-}
-
-task archiveJavadocs(type: Copy ) {
-  dependsOn javadocs
-
-  if( rootProject.version == '0' || rootProject.version.contains( "SNAPSHOT" ) )
-  {
-    into( "$rootProject.projectDir/../zest-web/site/content/java/develop/javadocs/" )
-  }
-  else
-  {
-    into( "$rootProject.projectDir/../zest-web/site/content/java/$version/javadocs/" )
-  }
-  from( 'build/docs/javadoc/' )
-}
-
-
-// Build All
-task buildAll( dependsOn: [
-    javadocs,
-    check,
-    jar,
-    subprojects*.dependencyReport,
-    subprojects*.assemble,
-    ':org.qi4j.manual:website'
-] ) { }
-
-// Generate license headers with comment styles
-def licenseHeader_wrap( base, top, left, bottom ) {
-  ( top ? "$top\n" : '' ) + base.readLines().collect{ "${left}${it}" }.join( '\n' ) + '\n' + ( bottom ? "$bottom\n" : '' )
-}
-def licenseHeader( flavour ) {
-  def base = project.file( 'etc/header.txt' ).text
-  def header
-  switch( flavour ) {
-    case 'java': case 'groovy': case 'scala': case 'js':
-      header = licenseHeader_wrap( base, '/*', ' * ', ' */' ) ; break
-    case 'xml': case 'html':
-      header = licenseHeader_wrap( base, '<!--', '  ', '-->' ) ; break
-    case 'txt': case 'shell': case 'python': case 'ruby':
-      header = licenseHeader_wrap( base, null, '# ', null ) ; break
-    case 'adoc': case 'asciidoc':
-      header = licenseHeader_wrap( base, null, '// ', null ) ; break
-    default:
-      header = base
-  }
-  header
-}
-
-task generateBinDistGoOfflineHelpers {
-  def goOfflineGradleFile = file( 'build/go-offline-helpers/go-offline.gradle' )
-  def goOfflinePomFile = file( 'build/go-offline-helpers/go-offline.pom')
-  outputs.files goOfflineGradleFile
-  outputs.files goOfflinePomFile
-  doLast {
-
-    def goOfflineGradle = licenseHeader( 'java' )
-    goOfflineGradle += '// This gradle build file has the sole purpose of downloading all dependencies in a directory relative to this file named \'dependencies\'.\n'
-    goOfflineGradle += '// Use the following command: gradle -b go-offline.gradle download\n'
-    goOfflineGradle += 'apply plugin: \'java\'\nconfigurations { download }\nrepositories {\n'
-    def goOfflinePom = licenseHeader( 'xml' )
-    goOfflinePom += '<project>\n  <modelVersion>4.0.0</modelVersion>\n'
-    goOfflinePom += "  <groupId>org.qi4j</groupId>\n  <artifactId>go-offline-helper</artifactId>\n  <version>$version</version>\n"
-    goOfflinePom += '  <packaging>pom</packaging>\n'
-    goOfflinePom += '  <!--\n  This pom has the sole purpose of downloading all dependencies in a directory relative to this file named \'dependencies\'.\n'
-    goOfflinePom += '  Use the following command:\n\n  mvn -f go-offline.pom validate\n  -->\n  <repositories>\n'
-
-    def repoCount = 1
-    repos_urls.each { repo_url ->
-      goOfflineGradle += "  maven { url '${repo_url.value}' }\n"
-      goOfflinePom += "    <repository><id>go-offline-repo-$repoCount</id><url>${repo_url.value}</url></repository>\n"
-      repoCount++
-    }
-
-    goOfflineGradle += '}\ndependencies {\n'
-    goOfflinePom += '  </repositories>\n  <dependencies>\n'
-
-    // Do the global dependency resolution here so there won't be any suprise when using the helpers
-    // This also allow to apply the resolution strategy defined in libraries.gradle
-    // WARN some of our modules depends on != versions of some artifacts, this resolution flatten this using the most up to date
-    def allRuntimeDeps = releaseApprovedProjects.collect{ it.configurations.runtime.allDependencies }.flatten()
-    rootProject.configurations.create( 'goOfflineHelpers' )
-    rootProject.dependencies { allRuntimeDeps.each{ goOfflineHelpers it } }
-    rootProject.configurations.goOfflineHelpers.incoming.resolutionResult.allComponents.each { comp ->
-      def depCoords = "${comp.moduleVersion.group}:${comp.moduleVersion.name}:${comp.moduleVersion.version}"
-      if( !comp.moduleVersion.group.startsWith( 'org.qi4j' ) ) {
-        goOfflineGradle += "  download( '$depCoords' ) { transitive = false }\n"
-        goOfflinePom += "    <dependency><groupId>${comp.moduleVersion.group}</groupId><artifactId>${comp.moduleVersion.name}</artifactId><version>${comp.moduleVersion.version}</version></dependency>\n"
-      }
-    }
-
-    goOfflineGradle += """}
-task download( type: Copy ) {
-  def sources = configurations.download.resolvedConfiguration.resolvedArtifacts.collect { artifact ->
-    project.dependencies.create( [ group: artifact.moduleVersion.id.group, name: artifact.moduleVersion.id.name, version: artifact.moduleVersion.id.version, classifier: 'sources' ] )
-  }
-  def javadocs = configurations.download.resolvedConfiguration.resolvedArtifacts.collect { artifact ->
-    project.dependencies.create( [ group: artifact.moduleVersion.id.group, name: artifact.moduleVersion.id.name, version: artifact.moduleVersion.id.version, classifier: 'javadoc' ] )
-  }
-  from configurations.download
-  from configurations.detachedConfiguration( sources as Dependency[] ).resolvedConfiguration.lenientConfiguration.getFiles( Specs.SATISFIES_ALL )
-  from configurations.detachedConfiguration( javadocs as Dependency[] ).resolvedConfiguration.lenientConfiguration.getFiles( Specs.SATISFIES_ALL )
-  into file( 'dependencies/' )
-}
-"""
-
-    goOfflinePom += """  </dependencies>\n  <build><plugins><plugin>
-    <groupId>org.apache.maven.plugins</groupId>
-    <artifactId>maven-dependency-plugin</artifactId>
-    <version>2.10</version>
-    <executions>
-      <execution>
-        <id>go-offline-jars</id><phase>validate</phase>
-        <goals><goal>copy-dependencies</goal></goals>
-        <configuration>
-          <outputDirectory>\${project.basedir}/dependencies</outputDirectory>
-          <excludeTransitive>true</excludeTransitive>
-        </configuration>
-      </execution>
-      <execution>
-        <id>go-offline-sources</id><phase>validate</phase>
-        <goals><goal>copy-dependencies</goal></goals>
-        <configuration>
-          <classifier>sources</classifier><failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
-          <outputDirectory>\${project.basedir}/dependencies</outputDirectory>
-          <excludeTransitive>true</excludeTransitive>
-        </configuration>
-      </execution>
-      <execution>
-        <id>go-offline-javadocs</id><phase>validate</phase>
-        <goals><goal>copy-dependencies</goal></goals>
-        <configuration>
-          <classifier>javadoc</classifier><failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
-          <outputDirectory>\${project.basedir}/dependencies</outputDirectory>
-          <excludeTransitive>true</excludeTransitive>
-        </configuration>
-      </execution>
-    </executions>
-  </plugin></plugins></build>
-</project>
-"""
-
-    goOfflineGradleFile.parentFile.mkdirs()
-    goOfflinePomFile.parentFile.mkdirs()
-
-    goOfflineGradleFile.text = goOfflineGradle
-    goOfflinePomFile.text = goOfflinePom
-  }
-}
-
-
-def srcDistFilesImages = copySpec {
-  from '.'
-  include '*.txt'
-  include 'doap.rdf'
-  include '*.gradle'
-  include 'gradlew*'
-  include 'gradle/**'
-  include 'etc/**'
-  include 'buildSrc/**'
-  include 'src/**'
-  releaseApprovedProjects.each { p ->
-    def relPath = new File( project.projectDir.toURI().relativize( p.projectDir.toURI() ).toString() )
-    include "$relPath/**"
-  }
-  include 'manual/**'
-  include 'samples/**'
-  include 'tests/**'
-  include 'tutorials/**'
-  // Filtered, see below
-  exclude 'settings.gradle'
-  exclude 'gradle.properties'
-  // Excludes
-  exclude '**/build/'               // Build output
-  exclude 'derby.log'               // Derby test garbage
-  exclude '**/*.iml'                // IDEA files
-  exclude '**/*.ipr'                // IDEA files
-  exclude '**/*.iws'                // IDEA files
-  exclude '**/.idea'                // IDEA files
-  exclude '**/out/*'                // IDEA build output
-  exclude '**/.classpath'           // Eclipse files
-  exclude '**/.project'             // Eclipse files
-  exclude '**/.settings'            // Eclipse files
-  exclude '**/.nb-gradle/'          // Netbeans files
-  exclude '**/.nb-gradle*'          // Netbeans files
-  exclude '**/.git/'                // Git directories
-  exclude '**/.git*'                // Git files
-  exclude '**/.gradle/'             // Gradle management files
-  exclude '**/.gradletasknamecache' // Gradle cache
-  into '.'
-}
-
-task srcDistFilteredFiles() {
-  // Generates various files for the source distribution
-  // - settings.gradle
-  // - gradle.properties to set version !
-  def filteredDir = new File( "$project.buildDir/tmp/srcDistFilteredFiles")
-  outputs.file filteredDir
-  doLast {
-    // Settings
-    def settingsFile = new File( filteredDir,  'settings.gradle' )
-    settingsFile.parentFile.mkdirs()
-    def filteredSettings = ''
-    project.file( 'settings.gradle' ).readLines().each { line ->
-      if( line.contains( '\'libraries:' ) || line.contains( '\'extensions:' ) || line.contains( '\'tools:' ) ) {
-        def accepted = false
-        releaseApprovedProjects.collect{it.projectDir}.each { acceptedProjectDir ->
-          if( line.contains( "'${acceptedProjectDir.parentFile.name}:${acceptedProjectDir.name}'" ) ) {
-            accepted = true
-          }
-        }
-        if( accepted ) {
-          filteredSettings += "$line\n"
-        }
-      } else {
-        filteredSettings += "$line\n"
-      }
-    }
-    settingsFile.text = filteredSettings
-    // gradle.properties
-    def gradlePropsFile = new File( filteredDir, 'gradle.properties' )
-    gradlePropsFile.parentFile.mkdirs()
-    gradlePropsFile.text = project.file( 'gradle.properties' ).text + "\nskipSigning=true\nskipAsciidocIfAbsent=true\n\nversion=$version\n"
-  }
-}
-
-def srcDistFilteredFilesImage = copySpec {
-  from srcDistFilteredFiles
-  into '.'
-}
-
-def srcDistImage = copySpec {
-  into "apache-zest-java-$version-src"
-  with srcDistFilesImages
-  with srcDistFilteredFilesImage
-}
-
-def reportsDistImage = copySpec {
-  from "$buildDir/reports"
-  into( "docs/reports" )
-}
-
-def docsImage = copySpec {
-  from "build/docs"
-  from "manual/build/docs/website"
-  into( "docs" )
-}
-
-def runtimeDependenciesListImage = copySpec {
-  releaseApprovedProjects.collect { p ->
-    into( "libs/" ) {
-      from "$p.buildDir/reports/project/dependencies.txt"
-      rename 'dependencies.txt', "${p.name}-${p.version}-runtime-deps.txt"
-    }
-  }
-  into( '.' ) {
-    from generateBinDistGoOfflineHelpers.outputs
-  }
-}
-
-def libsImage = copySpec {
-  releaseApprovedProjects.collect { proj ->
-    into( "libs/" ) {
-      from proj.configurations.archives.artifacts.files
-      exclude '**-testsources.jar'
-      exclude '**/*.asc'
-    }
-  }
-}
-
-def binDistNoticesImage = copySpec {
-  from( "$projectDir/LICENSE.txt")
-  from( "$projectDir/src/bin-dist" )
-  into( "." )
-}
-
-def binDistImage = copySpec {
-  into "apache-zest-java-$version-bin"
-  with binDistNoticesImage
-  with docsImage
-  with reportsDistImage
-  with runtimeDependenciesListImage
-  with libsImage
-}
-
-task zipSources( type: Zip ) {
-  baseName = 'apache-zest-java'
-  with srcDistImage
-  classifier = 'src'
-}
-
-task tarSources( type: Tar ) {
-  baseName = 'apache-zest-java'
-  with srcDistImage
-  compression = Compression.GZIP
-  classifier = 'src'
-}
-
-task zipBinaries( type: Zip, dependsOn: buildAll ) {
-  baseName = 'apache-zest-java'
-  classifier = 'bin'
-  with binDistImage
-}
-
-task tarBinaries( type: Tar, dependsOn: buildAll ) {
-  baseName = 'apache-zest-java'
-  classifier = 'bin'
-  compression = Compression.GZIP
-  with binDistImage
-}
-
-// Checksum distributions
-tasks.withType( Zip ) { task ->
-  task.doLast {
-    ant.checksum file: task.archivePath, algorithm: 'MD5'
-    ant.checksum file: task.archivePath, algorithm: 'SHA-512'
-  }
-}
-tasks.withType( Tar ) { task ->
-  task.doLast {
-    ant.checksum file: task.archivePath, algorithm: 'MD5'
-    ant.checksum file: task.archivePath, algorithm: 'SHA-512'
-  }
-}
-
-artifacts {
-  archives zipSources, tarSources, zipBinaries, tarBinaries
-}
-
-signing {
-  required { rootProject.version != '0' && !rootProject.version.contains( 'SNAPSHOT' ) }
-  sign configurations.archives
-}
-signArchives.onlyIf { !rootProject.skipSigning }
-
-task dist( type: Copy, dependsOn: install ) {
-  description "Unpack the binary distribution"
-  group = "distributions"
-  with binDistImage
-  into "$buildDir/dist"
-}
-
-// Tasks for source and binary distributions checks
-def unpackedSrcDistDir = file( "build/unpacked-distributions/src/apache-zest-java-$version-src" )
-def unpackedBinDistDir = file( "build/unpacked-distributions/bin/apache-zest-java-$version-bin" )
-task unpackSrcDist( type: Copy ) {
-  description "Unpack the source distribution"
-  group = "distributions"
-  with srcDistImage
-  into 'build/unpacked-distributions/src'
-}
-task checkSrcDist( type: GradleBuild, dependsOn: unpackSrcDist ) {
-  description = "Check the source distribution by running the 'check' and 'assemble' tasks inside"
-  group = "distributions"
-  buildFile = "$unpackedSrcDistDir/build.gradle"
-  tasks = [ 'check', 'assemble' ]
-}
-task unpackBinDist( type: Copy, dependsOn: buildAll ) {
-  description "Unpack the binary distribution"
-  group = "distributions"
-  with binDistImage
-  into 'build/unpacked-distributions/bin'
-}
-task checkBinDist_rat( type: org.apache.rat.gradle.RatTask, dependsOn: unpackBinDist ) {
-  description "Check the binary distribution using Apache RAT"
-  group = "distributions"
-  inputDir = unpackedBinDistDir
-  reportDir = file( 'build/reports/rat-bin-dist' )
-  excludes = []
-}
-task checkBinDist_goOfflineGradle( type: GradleBuild, dependsOn: unpackBinDist ) {
-  description "Check the binary distribution Gradle go-offline helper"
-  group = "distributions"
-  def dependenciesDir = new File( unpackedBinDistDir, 'dependencies' )
-  doFirst { dependenciesDir.deleteDir() }
-  buildFile = "$unpackedBinDistDir/go-offline.gradle"
-  tasks = [ 'download' ]
-  doLast {
-    releaseApprovedProjects*.configurations.runtime.allDependencies.findAll({it.name}).each { dep ->
-      def jarArtifactId = dep.name instanceof String ? dep.name : dep.name.last()
-      def jarVersion = dep.version instanceof String ? dep.version : dep.version.last()
-      if( !jarArtifactId.startsWith( 'org.qi4j' ) ) {
-        def jarName = "${jarArtifactId}-${jarVersion}.jar"
-        if( !new File( dependenciesDir, jarName ).exists() ) {
-          throw new GradleException( "Binary distribution go-offline.gradle failed! Missing: $jarName" );
-        }
-      }
-    }
-  }
-}
-task checkBinDist_goOfflineMaven( type: Exec, dependsOn: unpackBinDist ) {
-  description "Check the binary distribution Maven go-offline helper"
-  group = "distributions"
-  onlyIf {
-    def pathDirs = System.getenv( 'PATH' ).split( File.pathSeparator )
-    pathDirs.collect( { new File( it, 'mvn') } ).flatten().findAll( { it.isFile() } )
-  }
-  def dependenciesDir = new File( unpackedBinDistDir, 'dependencies' )
-  doFirst { dependenciesDir.deleteDir() }
-  workingDir unpackedBinDistDir
-  commandLine 'mvn', '-e', '-f', 'go-offline.pom', 'validate'
-  doLast {
-    releaseApprovedProjects*.configurations.runtime.allDependencies.findAll({it.name}).each { dep ->
-      def jarArtifactId = dep.name instanceof String ? dep.name : dep.name.last()
-      def jarVersion = dep.version instanceof String ? dep.version : dep.version.last()
-      if( !jarArtifactId.startsWith( 'org.qi4j' ) ) {
-        def jarName = "${jarArtifactId}-${jarVersion}.jar"
-        if( !new File( dependenciesDir, jarName ).exists() ) {
-          throw new GradleException( "Binary distribution go-offline.pom failed! Missing: $jarName" );
-        }
-      }
-    }
-  }
-}
-task checkBinDist {
-  description "Check the binary distribution"
-  group = "distributions"
-  dependsOn /*checkBinDist_rat,*/ checkBinDist_goOfflineGradle, checkBinDist_goOfflineMaven
-}
-task checkDists {
-  description "Check the souce and binary distributions"
-  group = "distributions"
-  dependsOn checkSrcDist, checkBinDist
-}
-
-task checkReleaseSpec {
-  description = "Ensure that no releasable module depend on module(s) that don't fit the release criteria."
-  group = 'release'
-  dependsOn releaseApprovedProjects*.configurations.runtime
-  doFirst {
-    def notReleasable = [:]
-    releaseApprovedProjects*.configurations.runtime.allDependencies.findAll({ it instanceof ProjectDependency }).each { dep ->
-      def depNotReleaseApproved = releaseApprovedProjects.findAll { rp ->
-        rp.group == dep.dependencyProject.group && rp.name == dep.dependencyProject.name 
-      }.isEmpty()
-      if( depNotReleaseApproved )
-      {
-        if( !notReleasable[p] ) notReleasable[p] = []
-        notReleasable[p] << dep
-      }
-    }
-    if(!notReleasable.isEmpty()) {
-      def errorMessage = new StringBuilder()
-      errorMessage << "At least one releasable module depends on module(s) that don't fit the release criteria!\n"
-      errorMessage << "\tOffending module -> Non releasable dependencies\n"
-      notReleasable.each { k,v ->
-        def noRlsDeps = v.collect{d -> ':'+d.dependencyProject.group+':'+d.dependencyProject.name}
-        errorMessage << "\t$k -> ${noRlsDeps})\n"
-      }
-      errorMessage << "Check the dev-status.xml file content in each modules directory."
-      throw new GradleException( errorMessage.toString() )
-    }
-  }
-}
-
-task release {
-  description = 'Builds, tests and uploads the release artifacts'
-  group = 'release'
-  doFirst {
-    if( System.properties[ 'version' ] == null || System.properties[ 'version' ].contains( 'SNAPSHOT' ) )
-    {
-      throw new GradleException( "'version' must be given as a system property to perform a release." )
-    }
-  }
-  dependsOn checkReleaseSpec, rat, archiveJavadocs, ':org.qi4j.manual:copyWebsite', allprojects*.uploadArchives, dist
-}
-
-//
-// This is a task that generates the gradlew scripts, allowing users to run gradle without having gradle installed
-// on their system.
-// This task should be run by "build master" and the resulting ouput committed to source control.  Its outputs include:
-//  1) /gradlew which is the *NIX shell script for executing builds
-//  2) /gradlew.bat which is the windows bat script for for executing builds
-//  3) /gradle/wrapper which is a directory named by the "jarPath" config which contains other needed files.
-task wrapper( type: Wrapper ) {
-  gradleVersion = '2.5'
-}
+apply plugin: 'polygene-dependencies-declaration'
+apply from: 'dependencies.gradle'
+apply plugin: 'polygene-root'
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
index 042f3ce..b5ac8d6 100644
--- a/buildSrc/build.gradle
+++ b/buildSrc/build.gradle
@@ -1,18 +1,41 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
  */
+
+plugins {
+  id 'groovy'
+}
+
+repositories {
+  maven { url "https://plugins.gradle.org/m2/" }
+  mavenCentral()
+}
+
+dependencies {
+  compile gradleApi()
+  compile localGroovy()
+  compile 'gradle.plugin.org.nosphere.apache:creadur-rat-gradle:0.3.0'
+  compile 'gradle.plugin.org.nosphere.honker:honker-gradle:0.3.0'
+  compile 'org.hibernate.build.gradle:gradle-maven-publish-auth:2.0.1'
+  compile 'org.apache.httpcomponents:httpclient:4.5.2'
+  compile 'org.apache.httpcomponents:httpmime:4.5.2'
+  compile 'com.bmuschko:gradle-docker-plugin:3.0.5'
+  compile 'com.moowork.gradle:gradle-node-plugin:1.1.1'
+
+  testCompile 'junit:junit:4.12'
+  testCompile( 'org.spockframework:spock-core:1.0-groovy-2.4' ) { exclude module: 'groovy-all' }
+}
diff --git a/buildSrc/src/bin/devstatus.conf b/buildSrc/src/asciidoc/filters/devstatus/devstatus.conf
similarity index 100%
rename from buildSrc/src/bin/devstatus.conf
rename to buildSrc/src/asciidoc/filters/devstatus/devstatus.conf
diff --git a/buildSrc/src/asciidoc/filters/devstatus/devstatus.py b/buildSrc/src/asciidoc/filters/devstatus/devstatus.py
new file mode 100755
index 0000000..11abfa4
--- /dev/null
+++ b/buildSrc/src/asciidoc/filters/devstatus/devstatus.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+# -*- mode: Python; coding: utf-8 -*-
+# 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.
+"""
+source=ignored
+tag=self-test
+"""
+
+import sys
+import xml.dom.minidom
+
+PATH_PATTERN="%(source)s"
+NS="http://polygene.apache.org/schemas/2008/dev-status/1"
+
+def configuration(indata):
+    config = {}
+    for line in indata:
+        line = line.strip()
+        if not line: continue
+        try:
+            key, value = line.split('=',1)
+        except:
+            raise ValueError('invalid config line: "%s"' % (line,))
+        config[key] = value
+    return config
+
+def devstatus(source=None,  **other):
+    for key in other:
+        sys.stderr.write("WARNING: unknown config key: '%s'\n" % key)
+    if not source: raise ValueError("'source' must be specified")
+
+    tablength = '    '
+    sourceFile = open(PATH_PATTERN % locals())
+    xmlDoc = xml.dom.minidom.parse(sourceFile)
+    mindent = 1<<32 # a large number - no indentation is this long
+
+    try:
+        docs = xmlDoc.getElementsByTagNameNS(NS, "documentation")[0].childNodes[0].nodeValue
+        code = xmlDoc.getElementsByTagNameNS(NS, "codebase")[0].childNodes[0].nodeValue
+        tests = xmlDoc.getElementsByTagNameNS(NS, "unittests")[0].childNodes[0].nodeValue
+        buff = []
+
+        buff.append( "<para role=\"devstatus-code-"+code+"\">")
+        buff.append( "code")
+        buff.append( "</para>\n")
+
+        buff.append( "<para role=\"devstatus-docs-"+docs+"\">")
+        buff.append( "docs")
+        buff.append( "</para>\n")
+
+        buff.append( "<para role=\"devstatus-tests-"+tests+"\">")
+        buff.append( "tests")
+        buff.append( "</para>\n")
+
+    finally:
+        sourceFile.close()
+
+    for line in buff:
+        if line:
+            yield line
+        else:
+            yield '\n'
+
+
+if __name__ == '__main__':
+    import traceback
+    indata = sys.stdin
+    if len(sys.argv) == 2 and sys.argv[1] == '--self-test':
+        PATH_PATTERN = __file__
+        indata = __doc__.split('\n')
+    try:
+        for line in devstatus(**configuration(indata)):
+            sys.stdout.write(line)
+    except:
+        traceback.print_exc(file=sys.stdout)
+        raise
diff --git a/buildSrc/src/bin/snippet.conf b/buildSrc/src/asciidoc/filters/snippet/snippet.conf
similarity index 100%
rename from buildSrc/src/bin/snippet.conf
rename to buildSrc/src/asciidoc/filters/snippet/snippet.conf
diff --git a/buildSrc/src/asciidoc/filters/snippet/snippet.py b/buildSrc/src/asciidoc/filters/snippet/snippet.py
new file mode 100755
index 0000000..0202ae4
--- /dev/null
+++ b/buildSrc/src/asciidoc/filters/snippet/snippet.py
@@ -0,0 +1,109 @@
+#!/usr/bin/env python
+# -*- mode: Python; coding: utf-8 -*-
+# 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.
+"""
+source=ignored
+tag=self-test
+"""
+
+import sys
+
+PATH_PATTERN="%(source)s"
+
+def configuration(indata):
+    config = {}
+    for line in indata:
+        line = line.strip()
+        if not line: continue
+        try:
+            key, value = line.split('=',1)
+        except:
+            raise ValueError('invalid config line: "%s"' % (line,))
+        config[key] = value
+    return config
+
+def snippet(source=None, tag=None, tablength="4", snipMarker="  [...snip...]\n\n", **other):
+    for key in other:
+        sys.stderr.write("WARNING: unknown config key: '%s'\n" % key)
+    if not tag: raise ValueError("'tag' must be specified")
+    if not source: raise ValueError("'source' must be specified")
+    try:
+        tablength = ' ' * int(tablength)
+    except:
+        raise ValueError("'tablength' must be specified as an integer")
+
+    START = "START SNIPPET: %s" % tag
+    END = "END SNIPPET: %s" % tag
+
+    sourceFile = open(PATH_PATTERN % locals())
+
+    try:
+        # START SNIPPET: self-test
+        buff = []
+        mindent = 1<<32 # a large number - no indentation is this long
+        emit = False
+        emitted = False
+
+        for line in sourceFile:
+            if line.strip().endswith(END): emit = False
+            if emit:
+                emitted = True
+                if not "SNIPPET" in line:
+                    line = line.replace(']]>',']]>]]&gt;<![CDATA[')
+                    meat = line.lstrip()
+                    if meat:
+                        indent = line[:-len(meat)].replace('\t', tablength)
+                        mindent = min(mindent, len(indent))
+                        buff.append(indent + meat)
+                    else:
+                        buff.append('')
+            if line.strip().endswith(START):
+                if emitted:
+                    buff.append(indent + snipMarker)
+                emit = True
+        # END SNIPPET: self-test
+
+    finally:
+        sourceFile.close()
+
+    if not buff:
+        raise ValueError('Missing snippet for tag "' + tag + '" in file "' + source + '".')
+    for line in buff:
+        if line:
+            yield line[mindent:]
+        else:
+            yield '\n'
+
+
+if __name__ == '__main__':
+    import traceback
+    indata = sys.stdin
+    if len(sys.argv) == 2 and sys.argv[1] == '--self-test':
+        PATH_PATTERN = __file__
+        indata = __doc__.split('\n')
+    try:
+        # START SNIPPET: self-test
+        sys.stdout.write("<![CDATA[")
+        for line in snippet(**configuration(indata)):
+            sys.stdout.write(line)
+        # END SNIPPET: self-test
+    except:
+        traceback.print_exc(file=sys.stdout)
+        raise
+    finally:
+        # START SNIPPET: self-test
+        sys.stdout.write("]]>")
+        # END SNIPPET: self-test
diff --git a/buildSrc/src/bin/devstatus.py b/buildSrc/src/bin/devstatus.py
deleted file mode 100755
index aa4a106..0000000
--- a/buildSrc/src/bin/devstatus.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/usr/bin/env python
-# -*- mode: Python; coding: utf-8 -*-
-# 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.
-"""
-source=ignored
-tag=self-test
-"""
-
-import sys
-import xml.dom.minidom
-
-PATH_PATTERN="%(source)s"
-NS="http://www.qi4j.org/schemas/2008/dev-status/1"
-
-def configuration(indata):
-    config = {}
-    for line in indata:
-        line = line.strip()
-        if not line: continue
-        try:
-            key, value = line.split('=',1)
-        except:
-            raise ValueError('invalid config line: "%s"' % (line,))
-        config[key] = value
-    return config
-
-def devstatus(source=None,  **other):
-    for key in other:
-        sys.stderr.write("WARNING: unknown config key: '%s'\n" % key)
-    if not source: raise ValueError("'source' must be specified")
-
-    tablength = '    '
-    sourceFile = open(PATH_PATTERN % locals())
-    xmlDoc = xml.dom.minidom.parse(sourceFile)
-    mindent = 1<<32 # a large number - no indentation is this long
-
-    try:
-        docs = xmlDoc.getElementsByTagNameNS(NS, "documentation")[0].childNodes[0].nodeValue
-        code = xmlDoc.getElementsByTagNameNS(NS, "codebase")[0].childNodes[0].nodeValue
-        tests = xmlDoc.getElementsByTagNameNS(NS, "unittests")[0].childNodes[0].nodeValue
-        buff = []
-
-        buff.append( "<para role=\"devstatus-code-"+code+"\">")
-        buff.append( "code")
-        buff.append( "</para>\n")
-
-        buff.append( "<para role=\"devstatus-docs-"+docs+"\">")
-        buff.append( "docs")
-        buff.append( "</para>\n")
-
-        buff.append( "<para role=\"devstatus-tests-"+tests+"\">")
-        buff.append( "tests")
-        buff.append( "</para>\n")
-
-    finally:
-        sourceFile.close()
-
-    for line in buff:
-        if line:
-            yield line
-        else:
-            yield '\n'
-
-
-if __name__ == '__main__':
-    import traceback
-    indata = sys.stdin
-    if len(sys.argv) == 2 and sys.argv[1] == '--self-test':
-        PATH_PATTERN = __file__
-        indata = __doc__.split('\n')
-    try:
-        for line in devstatus(**configuration(indata)):
-            sys.stdout.write(line)
-    except:
-        traceback.print_exc(file=sys.stdout)
-        raise
diff --git a/buildSrc/src/bin/snippet.py b/buildSrc/src/bin/snippet.py
deleted file mode 100755
index 9cb0bfb..0000000
--- a/buildSrc/src/bin/snippet.py
+++ /dev/null
@@ -1,109 +0,0 @@
-#!/usr/bin/env python
-# -*- mode: Python; coding: utf-8 -*-
-# 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.
-"""
-source=ignored
-tag=self-test
-"""
-
-import sys
-
-PATH_PATTERN="%(source)s"
-
-def configuration(indata):
-    config = {}
-    for line in indata:
-        line = line.strip()
-        if not line: continue
-        try:
-            key, value = line.split('=',1)
-        except:
-            raise ValueError('invalid config line: "%s"' % (line,))
-        config[key] = value
-    return config
-
-def snippet(source=None, tag=None, tablength="4", snipMarker="  [...snip...]\n\n", **other):
-    for key in other:
-        sys.stderr.write("WARNING: unknown config key: '%s'\n" % key)
-    if not tag: raise ValueError("'tag' must be specified")
-    if not source: raise ValueError("'source' must be specified")
-    try:
-        tablength = ' ' * int(tablength)
-    except:
-        raise ValueError("'tablength' must be specified as an integer")
-
-    START = "START SNIPPET: %s" % tag
-    END = "END SNIPPET: %s" % tag
-
-    sourceFile = open(PATH_PATTERN % locals())
-
-    try:
-        # START SNIPPET: self-test
-        buff = []
-        mindent = 1<<32 # a large number - no indentation is this long
-        emit = False
-        emitted = False
-
-        for line in sourceFile:
-            if END in line: emit = False
-            if emit:
-                emitted = True
-                if not "SNIPPET" in line:
-                    line = line.replace(']]>',']]>]]&gt;<![CDATA[')
-                    meat = line.lstrip()
-                    if meat:
-                        indent = line[:-len(meat)].replace('\t', tablength)
-                        mindent = min(mindent, len(indent))
-                        buff.append(indent + meat)
-                    else:
-                        buff.append('')
-            if START in line:
-                if emitted:
-                    buff.append(indent + snipMarker)
-                emit = True
-        # END SNIPPET: self-test
-
-    finally:
-        sourceFile.close()
-
-    if not buff:
-        raise ValueError('Missing snippet for tag "' + tag + '" in file "' + source + '".')
-    for line in buff:
-        if line:
-            yield line[mindent:]
-        else:
-            yield '\n'
-
-
-if __name__ == '__main__':
-    import traceback
-    indata = sys.stdin
-    if len(sys.argv) == 2 and sys.argv[1] == '--self-test':
-        PATH_PATTERN = __file__
-        indata = __doc__.split('\n')
-    try:
-        # START SNIPPET: self-test
-        sys.stdout.write("<![CDATA[")
-        for line in snippet(**configuration(indata)):
-            sys.stdout.write(line)
-        # END SNIPPET: self-test
-    except:
-        traceback.print_exc(file=sys.stdout)
-        raise
-    finally:
-        # START SNIPPET: self-test
-        sys.stdout.write("]]>")
-        # END SNIPPET: self-test
diff --git a/buildSrc/src/main/groovy/AsciidocBuildInfo.groovy b/buildSrc/src/main/groovy/AsciidocBuildInfo.groovy
deleted file mode 100644
index a57eec3..0000000
--- a/buildSrc/src/main/groovy/AsciidocBuildInfo.groovy
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.
- */
-
-import org.gradle.api.Project
-import org.gradle.api.Plugin
-
-class AsciidocBuildInfo implements Plugin<Project>
-{
-
-    final static TASK_NAME = 'makeAsciidocBuildInfo'
-
-    AsciidocBuildInfo()
-    {
-    }
-
-    def void apply( Project project )
-    {
-        def buildInfoDir = new File( project.buildDir, "docs/buildinfo" );
-
-        def makeAsciidocBuildInfoTask = project.task( TASK_NAME ) << {
-            buildInfoDir.mkdirs()
-
-            // GroupID, ArtifactID, Version table in artifact.txt
-            def artifactTableFile = new File( buildInfoDir, "artifact.txt" )
-            def artifactTable = """
-                |.Artifact
-                |[role="artifact", options="header,autowidth"]
-                ||===================================================
-                ||Group ID|Artifact ID|Version
-                ||${project.group}|${project.name}|${project.version}
-                ||===================================================
-                """.stripMargin()
-            artifactTableFile.withWriter { out -> out.println( artifactTable ) }
-        }
-
-        // Declare inputs/outputs
-        if( project.getBuildFile() != null && project.getBuildFile().exists() )
-        {
-            makeAsciidocBuildInfoTask.getInputs().files(project.getBuildFile())
-        }
-        makeAsciidocBuildInfoTask.getOutputs().files( buildInfoDir )
-    }
-
-}
diff --git a/buildSrc/src/main/groovy/VersionClass.groovy b/buildSrc/src/main/groovy/VersionClass.groovy
deleted file mode 100644
index 94c690e..0000000
--- a/buildSrc/src/main/groovy/VersionClass.groovy
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2010, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.
- */
-
-import org.gradle.api.Project
-import org.gradle.api.Plugin
-import org.gradle.api.plugins.JavaPlugin
-
-class VersionClass implements Plugin<Project>
-{
-
-  VersionClass()
-  {
-  }
-
-  def void apply(Project project)
-  {
-    project.getPlugins().apply(JavaPlugin.class)
-    def genSrc = 'generated-src/version'
-    def generatedSrcDir = new File(project.buildDir, genSrc)
-
-    def makeVersionClassTask = project.task('makeVersionClass') << {
-      def now = new Date()
-      def tmpGroup = project.name
-      if( tmpGroup.startsWith("org.qi4j.core"))
-      {
-        tmpGroup = tmpGroup - ".core"
-      }
-      tmpGroup = tmpGroup.replace('-','_')
-      def outFilename = "java/" + tmpGroup.replace('.', '/') + "/BuildVersion.java"
-      def outFile = new File(generatedSrcDir, outFilename)
-      outFile.getParentFile().mkdirs()
-      def f = new FileWriter(outFile)
-      f.write('package ' + tmpGroup + ';\n')
-      f.write("""
-/**
- * Simple class for storing the version derived from the build system.
- *
- */
-public interface BuildVersion
-{
-    /** The version of the project from the gradle build.gradle file. */
-    String VERSION = \"""" + project.version + """\";
-
-    /** The name of the project from the gradle build.gradle file. */
-    String NAME = \"""" + project.name + """\";
-
-    /** The group of the project from the gradle build.gradle file. */
-    String GROUP = \"""" + project.group + """\";
-
-    /** The date this file was generated, usually the last date that the project was modified. */
-    String DATE = \"""" + now + """\";
-
-    /** The full details of the version, including the build date. */
-    String DETAILED_VERSION = GROUP + ":" + NAME + ":" + VERSION + " " + DATE;
-}\n
-""")
-      f.close()
-    }
-    project.sourceSets {
-      version {
-        java {
-          srcDir project.buildDir.name + '/' + genSrc + '/java'
-        }
-      }
-    }
-    makeVersionClassTask.getInputs().files(project.sourceSets.main.getAllSource())
-    makeVersionClassTask.getOutputs().files(generatedSrcDir)
-    if( project.getBuildFile() != null && project.getBuildFile().exists() )
-    {
-      makeVersionClassTask.getInputs().files(project.getBuildFile())
-    }
-    project.getTasks().getByName('compileJava').dependsOn('compileVersionJava')
-    project.getTasks().getByName('compileVersionJava').dependsOn('makeVersionClass')
-    project.getTasks().getByName('jar') {
-      from project.sourceSets.version.output
-    }
-  }
-}
-
-
diff --git a/buildSrc/src/main/groovy/Xslt.groovy b/buildSrc/src/main/groovy/Xslt.groovy
deleted file mode 100644
index 70bd263..0000000
--- a/buildSrc/src/main/groovy/Xslt.groovy
+++ /dev/null
@@ -1,104 +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.
- */
-
-/**
- *  Gradle plug-in for running a set of one or more
- *  files through an XSLT transform.  A styleSheet
- *  file must be specified.  The source file(s) are
- *  configured just like any other source task:
- *     source <file>
- *       ...or...
- *     source <directory>
- *       ...and then optionally...
- *     include '*.xml'
- *     exclude, etc.
- *
- *  One of destDir or destFile must be specified, though if
- *  there are multiple source files then destFile will just
- *  keep getting rewritten.
- *
- *  The extension is stripped from the source files and the
- *  specified extension is appended (whether it is set or not)
- *  it defaults to no extension.
- *
- *  Example task formatting a check style report:
- *
- *  task checkstyleReport(type: Xslt, dependsOn: check) {*      source project.checkstyleResultsDir
- *      include '*.xml'
- *
- *      destDir = project.checkstyleResultsDir
- *      extension = 'html'
- *
- *      stylesheetFile = file( 'config/checkstyle/checkstyle-noframes.xsl' )
- *}*
- *  The above definition requires that the specified XSL file be
- *  copied in with the other checkstyle configuration files.  (The
- *  file in the example is part of the checkstyle distribution.)
- *
- */
-
-import org.gradle.api.InvalidUserDataException
-import org.gradle.api.tasks.SourceTask
-import org.gradle.api.tasks.OutputFile
-import org.gradle.api.tasks.OutputDirectory
-import org.gradle.api.tasks.Optional
-import org.gradle.api.tasks.InputFile
-import org.gradle.api.tasks.TaskAction
-import org.gradle.api.file.FileVisitDetails
-
-import javax.xml.transform.TransformerFactory
-import javax.xml.transform.stream.StreamResult
-import javax.xml.transform.stream.StreamSource
-
-class Xslt extends SourceTask
-{
-
-  @OutputDirectory @Optional
-  File destDir
-
-  @Optional
-  String extension
-
-  @InputFile
-  File stylesheetFile
-
-  @TaskAction
-  def transform()
-  {
-    def factory = TransformerFactory.newInstance()
-    def transformer = factory.newTransformer(new StreamSource(stylesheetFile));
-
-    source.visit { FileVisitDetails fvd ->
-      if( fvd.isDirectory() )
-      {
-        return
-      }
-      // Remove the extension from the file name
-      name = fvd.file.name.replaceAll('[.][^\\.]*$', '')
-      if( extension == null )
-      {
-        extension = 'html'
-      }
-      name += '.' + extension
-      def destFile = new File(destDir, name)
-      transformer.transform(new StreamSource(fvd.file), new StreamResult(destFile))
-
-    }
-  }
-}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/BasePlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/BasePlugin.groovy
new file mode 100644
index 0000000..6ba4f17
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/BasePlugin.groovy
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.gradle
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.dependencies.PolygeneExtension
+import org.apache.polygene.gradle.structure.release.ReleaseSpecPlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.language.base.plugins.LifecycleBasePlugin
+
+/**
+ * Plugin applied to all Polygene projects.
+ */
+@CompileStatic
+class BasePlugin implements Plugin<Project>
+{
+  @Override
+  void apply( Project project )
+  {
+    applyGroup project
+    applyVersion project
+    project.plugins.apply ReleaseSpecPlugin
+    applyPolygeneExtension project
+    project.plugins.apply LifecycleBasePlugin
+    project.defaultTasks 'classes', 'test'
+  }
+
+  private static void applyGroup( Project project )
+  {
+    project.group = project.path == ':' ?
+                    'org.apache.polygene' :
+                    "org.apache.polygene.${ project.path.split( ':' ).drop( 1 ).dropRight( 1 ).join( '.' ) }"
+  }
+
+  private static void applyVersion( Project project )
+  {
+    if( project.version == 'unspecified' )
+    {
+      project.version = System.properties.version ?: '0'
+    }
+  }
+
+  private static void applyPolygeneExtension( Project project )
+  {
+    project.extensions.create 'polygene', PolygeneExtension, project
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/TaskGroups.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/TaskGroups.groovy
new file mode 100644
index 0000000..bf435a7
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/TaskGroups.groovy
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.gradle
+
+import groovy.transform.CompileStatic
+import org.gradle.api.plugins.BasePlugin
+import org.gradle.api.plugins.HelpTasksPlugin
+import org.gradle.api.plugins.JavaBasePlugin
+import org.gradle.language.base.plugins.LifecycleBasePlugin
+
+@CompileStatic
+class TaskGroups
+{
+  static final String HELP = HelpTasksPlugin.HELP_GROUP
+  static final String BUILD = LifecycleBasePlugin.BUILD_GROUP
+  static final String VERIFICATION = LifecycleBasePlugin.VERIFICATION_GROUP
+  static final String DOCUMENTATION = JavaBasePlugin.DOCUMENTATION_GROUP
+  static final String DISTRIBUTION = 'distribution'
+  static final String DISTRIBUTION_VERIFICATION = 'distribution verification'
+  static final String PERFORMANCE = 'performance'
+  static final String PERFORMANCE_VERIFICATION = 'performance verification'
+  static final String RELEASE = 'release'
+  static final String RELEASE_VERIFICATION = 'release verification'
+  static final String UPLOAD = BasePlugin.UPLOAD_GROUP
+  static final String SAMPLES = 'samples'
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/CodePlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/CodePlugin.groovy
new file mode 100644
index 0000000..eb605c9
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/CodePlugin.groovy
@@ -0,0 +1,221 @@
+/*
+ *  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.polygene.gradle.code
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.BasePlugin
+import org.apache.polygene.gradle.TaskGroups
+import org.apache.polygene.gradle.dependencies.DependenciesDeclarationExtension
+import org.apache.polygene.gradle.dependencies.DependenciesPlugin
+import org.gradle.api.Action
+import org.gradle.api.JavaVersion
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.plugins.JavaPluginConvention
+import org.gradle.api.plugins.osgi.OsgiManifest
+import org.gradle.api.tasks.bundling.AbstractArchiveTask
+import org.gradle.api.tasks.compile.JavaCompile
+import org.gradle.api.tasks.testing.Test
+import org.gradle.api.tasks.testing.logging.TestExceptionFormat
+import org.gradle.jvm.tasks.Jar
+import org.gradle.testing.jacoco.plugins.JacocoPluginExtension
+import org.gradle.testing.jacoco.tasks.JacocoReport
+
+@CompileStatic
+class CodePlugin implements Plugin<Project>
+{
+  public static final String DOCKER_DISABLED_EXTRA_PROPERTY = 'dockerDisabled'
+
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply BasePlugin
+    applyJava project
+    project.plugins.apply DependenciesPlugin
+    configureDefaultDependencies project
+    configureTest project
+    configureJar project
+    configureArchivesBaseName project
+    configureJacoco project
+    configureCheckstyle project
+  }
+
+  private static void applyJava( Project project )
+  {
+    project.plugins.apply 'java-library'
+    def javaConvention = project.convention.getPlugin JavaPluginConvention
+    javaConvention.targetCompatibility = JavaVersion.VERSION_1_8
+    javaConvention.sourceCompatibility = JavaVersion.VERSION_1_8
+    project.tasks.withType( JavaCompile ) { JavaCompile task ->
+      task.options.encoding = 'UTF-8'
+      task.options.compilerArgs << '-Xlint:deprecation'
+      task.options.incremental = true
+    }
+  }
+
+  private static void configureDefaultDependencies( Project project )
+  {
+    def declaration = project.rootProject.extensions.getByType DependenciesDeclarationExtension
+    declaration.defaultDependencies.each { String configuration, List<Object> dependencies ->
+      dependencies.each { dependency ->
+        if( dependency instanceof Collection )
+        {
+          dependency.each { subdep ->
+            project.dependencies.add configuration, subdep
+          }
+        }
+        else
+        {
+          project.dependencies.add configuration, dependency
+        }
+      }
+    }
+  }
+
+  private static void configureTest( Project project )
+  {
+    // Match --max-workers and Test maxParallelForks, use 1 if parallel is disabled
+    def parallel = project.gradle.startParameter.parallelProjectExecutionEnabled
+    def maxTestWorkers = ( parallel ? project.gradle.startParameter.maxWorkerCount : 1 ) as int
+    // The space in the directory name is intentional
+    def allTestsDir = project.file "$project.buildDir/tmp/test files"
+    def testTasks = project.tasks.withType( Test ) { Test testTask ->
+      testTask.onlyIf { !project.hasProperty( 'skipTests' ) }
+      testTask.testLogging.info.exceptionFormat = TestExceptionFormat.FULL
+      testTask.maxHeapSize = '1g'
+      testTask.maxParallelForks = maxTestWorkers
+      testTask.systemProperties = [ 'proxySet' : System.properties[ 'proxySet' ],
+                                    'proxyHost': System.properties[ 'proxyHost' ],
+                                    'proxyPort': System.properties[ 'proxyPort' ] ]
+      testTask.reports.html.enabled = true
+      def testDir = new File( allTestsDir, testTask.name )
+      def workDir = new File( testDir, 'work' )
+      def tmpDir = new File( testDir, 'tmp' )
+      def homeDir = new File( testDir, 'home' )
+      testTask.workingDir = workDir
+      testTask.systemProperties << ( [
+        'user.dir'      : workDir.absolutePath,
+        'java.io.tmpdir': tmpDir.absolutePath,
+        'home.dir'      : homeDir.absolutePath
+      ] as Map<String, Object> )
+      testTask.environment << ( [
+        'HOME'       : homeDir.absolutePath,
+        'USERPROFILE': homeDir.absolutePath
+      ] as Map<String, Object> )
+      testTask.doFirst { Test task ->
+        [ workDir, tmpDir, homeDir ]*.mkdirs()
+      }
+      testTask.doLast { Test task ->
+        if( !task.state.failure )
+        {
+          project.delete testDir
+        }
+      }
+    }
+    // Configuration task to honor disabling Docker when unavailable
+    project.tasks.create( 'configureDockerForTest', { Task task ->
+      // TODO Untangle docker connectivity check & test task configuration
+      task.dependsOn ':internals:testsupport-internal:checkDockerConnectivity'
+      testTasks.each { it.dependsOn task }
+      task.inputs.property 'polygeneTestSupportDockerDisabled',
+                           { project.findProperty( DOCKER_DISABLED_EXTRA_PROPERTY ) }
+      task.doLast {
+        boolean dockerDisabled = project.findProperty( DOCKER_DISABLED_EXTRA_PROPERTY )
+        testTasks.each { testTask ->
+          testTask.inputs.property 'polygeneTestSupportDockerDisabled', dockerDisabled
+          testTask.systemProperty 'DOCKER_DISABLED', dockerDisabled
+        }
+      }
+    } as Action<Task> )
+  }
+
+  private static void configureJar( Project project )
+  {
+    project.plugins.apply 'osgi'
+    def jar = project.tasks.getByName( 'jar' ) as Jar
+    def manifest = jar.manifest as OsgiManifest
+    manifest.attributes( [
+      license    : 'http://www.apache.org/licenses/LICENSE-2.0.txt',
+      docURL     : 'https://polygene.apache.org/',
+      description: project.description ?:
+                   'Apache Polygene™ (Java Edition) is a platform for Composite Oriented Programming',
+      vendor     : 'The Apache Software Foundation, https://www.apache.org',
+    ] )
+    manifest.instruction '-debug', 'true'
+  }
+
+
+  private static void configureArchivesBaseName( Project project )
+  {
+    def publishedName = PublishNaming.publishedNameFor( project.path )
+    project.tasks.withType( AbstractArchiveTask ) { AbstractArchiveTask task ->
+      task.baseName = publishedName
+    }
+  }
+
+  private static void configureJacoco( Project project )
+  {
+    def dependencies = project.rootProject.extensions.getByType DependenciesDeclarationExtension
+    project.plugins.apply 'jacoco'
+    def jacoco = project.extensions.getByType JacocoPluginExtension
+    jacoco.toolVersion = dependencies.buildToolsVersions.jacoco
+    project.tasks.withType( JacocoReport ) { JacocoReport task ->
+      task.group = TaskGroups.VERIFICATION
+      task.description = 'Generates test coverage report.'
+    }
+  }
+
+  private static void configureCheckstyle( Project project )
+  {
+    // project.plugins.apply 'checkstyle'
+    //    if( name == "org.apache.polygene.core.runtime" )
+    //    {
+    //      checkstyleMain {
+    //        configFile = new File( "$rootProject.projectDir.absolutePath/etc/polygene-runtime-checkstyle.xml" )
+    //        ignoreFailures = true
+    //      }
+    //    }
+    //    else
+    //    {
+    //      checkstyleMain {
+    //        configFile = new File( rootProject.projectDir.absolutePath.toString() + '/etc/polygene-api-checkstyle.xml' )
+    //        ignoreFailures = true
+    //        reporting.baseDir = "$rootProject.reporting.baseDir/checkstyle"
+    //      }
+    //    }
+    //    checkstyleTest {
+    //      configFile = new File( "$rootProject.projectDir.absolutePath/etc/polygene-tests-checkstyle.xml" )
+    //      ignoreFailures = true
+    //    }
+    //
+    //    checkstyleVersion {
+    //      configFile = new File( "$rootProject.projectDir.absolutePath/etc/polygene-tests-checkstyle.xml" )
+    //      ignoreFailures = true
+    //    }
+    //    // Create checkstyle report
+    //    task checkstyleReport( type: XsltTask, dependsOn: check ) {
+    //      source project.checkstyle.reportsDir
+    //      include '*.xml'
+    //      destDir = file( "build/reports/checkstyle/" )
+    //      extension = 'html'
+    //      stylesheetFile = file( "$rootProject.projectDir/etc/checkstyle-noframes.xsl" )
+    //    }
+    //
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/MavenMetadata.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/MavenMetadata.groovy
new file mode 100644
index 0000000..c10ccda
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/MavenMetadata.groovy
@@ -0,0 +1,281 @@
+/*
+ *  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.polygene.gradle.code
+
+import org.gradle.api.artifacts.maven.MavenDeployer
+
+class MavenMetadata
+{
+  static void applyTo( MavenDeployer mavenDeployer )
+  {
+    mavenDeployer.pom {
+      project {
+        url 'https://polygene.apache.org/'
+        organization {
+          name 'The Apache Software Foundation'
+          url 'https://apache.org/'
+        }
+        inceptionYear '2007'
+        issueManagement {
+          system 'jira'
+          url 'https://issues.apache.org/jira/browse/POLYGENE'
+        }
+        scm {
+          url "https://github.com/apache/polygene-java"
+          connection "scm:git:https://git-wip-us.apache.org/repos/asf/polygene-java.git"
+          developerConnection "scm:git:https://git-wip-us.apache.org/repos/asf/polygene-java.git"
+        }
+        licenses {
+          license {
+            name 'Apache License, version 2.0.'
+            url 'http://www.apache.org/licenses/LICENSE-2.0'
+          }
+        }
+        mailingLists {
+          mailingList {
+            name 'Users List'
+            subscribe 'users-subscribe@polygene.apache.org'
+            unsubscribe 'users-unsubscribe@polygene.apache.org'
+            post 'users@polygene.apache.org'
+            archive 'https://mail-archives.apache.org/mod_mbox/polygene-users/'
+            otherArchives {
+              otherArchive 'https://www.apache.org/foundation/mailinglists.html#archives'
+            }
+          }
+          mailingList {
+            name 'Development List'
+            subscribe 'dev-subscribe@polygene.apache.org'
+            unsubscribe 'dev-unsubscribe@polygene.apache.org'
+            post 'dev@polygene.apache.org'
+            archive 'https://mail-archives.apache.org/mod_mbox/polygene-dev/'
+            otherArchives {
+              otherArchive 'https://www.apache.org/foundation/mailinglists.html#archives'
+            }
+          }
+          mailingList {
+            name 'Commits List'
+            subscribe 'commits-subscribe@polygene.apache.org'
+            unsubscribe 'commits-unsubscribe@polygene.apache.org'
+            post 'commits@polygene.apache.org'
+            archive 'https://mail-archives.apache.org/mod_mbox/polygene-commits/'
+            otherArchives {
+              otherArchive 'https://www.apache.org/foundation/mailinglists.html#archives'
+            }
+          }
+        }
+        developers {
+          developer {
+            id 'niclas@hedhman.org'
+            name 'Niclas Hedhman'
+            email 'niclas@hedhman.org'
+            roles {
+              role 'Core Team'
+            }
+            organizationUrl 'http://polygene.apache.org'
+            timezone 'UTC+8'
+          }
+          developer {
+            id 'rickardoberg'
+            name 'Rickard \u00F6berg'
+            email 'rickard.oberg@jayway.se'
+            roles {
+              role 'Core Team'
+            }
+            url 'http://www.neotechnology.com'
+            organization 'Neo Technology AB'
+            organizationUrl 'http://www.neotechnology.com'
+            timezone 'UTC+8'
+          }
+          developer {
+            id 'edward.yakop@gmail.com'
+            name 'Edward Yakop'
+            email 'efy@codedragons.com'
+            roles {
+              role 'Core Team'
+            }
+            organizationUrl 'http://polygene.apache.org'
+            timezone 'UTC+8'
+          }
+          developer {
+            id 'adreghiciu@gmail.com'
+            name 'Alin Dreghiciu'
+            email 'adreghiciu@codedragons.com'
+            roles {
+              role 'Core Team'
+            }
+            organizationUrl 'http://polygene.apache.org'
+            timezone 'UTC+2'
+          }
+          developer {
+            id 'mesirii'
+            name 'Michael Hunger'
+            email 'qi4j@jexp.de'
+            roles {
+              role 'Core Team'
+            }
+            timezone 'CET'
+          }
+
+          developer {
+            id "muhdkamil"
+            name "Muhd Kamil bin Mohd Baki"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "UTC+8"
+          }
+
+          developer {
+            id "ops4j@leangen.net"
+            name "David Leangen"
+            organization "Bioscene"
+            email "ops4j@leangen.net"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "UTC+9"
+          }
+
+          developer {
+            id "sonny.gill@jayway.net"
+            name "Sonny Gill"
+            email "sonny.public@gmail.com"
+            roles {
+              role 'Community Team'
+            }
+            timezone "UTC+8"
+          }
+
+          developer {
+            id "taowen"
+            name "Tao Wen"
+            organization ""
+            email "taowen@gmail.com"
+            roles {
+              role 'Community Team'
+            }
+            timezone "UTC+8"
+          }
+
+          developer {
+            id "thobe"
+            name "Tobias Ivarsson"
+            email "tobias@neotechnology.com"
+            url "http://www.neotechnology.com"
+            organization "NeoTechnology"
+            organizationUrl "http://www.neotechnology.com"
+            roles {
+              role "Platform Team"
+            }
+            timezone "CET"
+          }
+
+          developer {
+            id "boon"
+            name "Lan Boon Ping"
+            email "boonping81@gmail.com"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "UTC+8"
+          }
+
+          developer {
+            id "jan.kronquist@gmail.com"
+            name "Jan Kronquist"
+            email "jan.kronquist@gmail.com"
+            organization "Jayway"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "CET"
+          }
+
+          developer {
+            id "nmwael"
+            name "Nino Saturnino Martinez Vazquez Wael"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "CET"
+          }
+
+          developer {
+            id "peter@neubauer.se"
+            name "Peter Neubauer"
+            email "peter@neubauer.se"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "CET"
+          }
+
+          developer {
+            id "rwallace"
+            name "Richard Wallace"
+            email "rwallace@thewallacepack.net"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "UTC-7"
+          }
+
+          developer {
+            id "siannyhalim@gmail.com"
+            name "Sianny Halim"
+            email "siannyhalim@gmail.com"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "UTC+8"
+          }
+
+          developer {
+            id "paul@nosphere.org"
+            name "Paul Merlin"
+            email "paul@nosphere.org"
+            roles {
+              role 'Core Team'
+            }
+            timezone "CET"
+          }
+
+          developer {
+            id "stas.dev+qi4j@gmail.com"
+            name "Stanislav Muhametsin"
+            email "stas.dev+qi4j@gmail.com"
+            roles {
+              role 'Platform Team'
+            }
+            timezone "UTC+2"
+          }
+
+          developer {
+            id "tonny"
+            name "Tonny Kohar"
+            roles {
+              role "Community Team"
+            }
+            email "tonny.kohar@gmail.com"
+            timezone "UTC+7"
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/PublishNaming.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/PublishNaming.groovy
new file mode 100644
index 0000000..2347329
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/PublishNaming.groovy
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.gradle.code
+
+class PublishNaming
+{
+  static String publishedNameFor( String projectPath )
+  {
+    def toName = { List<String> path -> path.drop( 1 ).join( '.' ) }
+    def path = projectPath.split( ':' ).drop( 1 ) as List<String>
+    if( path[ 0 ] == 'libraries' )
+    {
+      return "org.apache.polygene.library.${ toName( path ) }"
+    }
+    else if( path[ 0 ].endsWith( 's' ) )
+    {
+      return "org.apache.polygene.${ path[ 0 ].substring( 0, path[ 0 ].length() - 1 ) }.${ toName( path ) }"
+    }
+    else if( path.size() > 1 )
+    {
+      return "org.apache.polygene.${ path[ 0 ] }.${ toName( path ) }"
+    }
+    return "org.apache.polygene.${ path[ 0 ] }"
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/PublishedCodePlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/PublishedCodePlugin.groovy
new file mode 100644
index 0000000..813c3da
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/PublishedCodePlugin.groovy
@@ -0,0 +1,155 @@
+/*
+ *  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.polygene.gradle.code
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.structure.manual.AsciidocBuildInfoPlugin
+import org.apache.polygene.gradle.structure.release.ReleaseSpecExtension
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.plugins.JavaPluginConvention
+import org.gradle.api.tasks.javadoc.Javadoc
+import org.gradle.external.javadoc.StandardJavadocDocletOptions
+import org.gradle.jvm.tasks.Jar
+import org.nosphere.honker.gradle.HonkerCheckTask
+import org.nosphere.honker.gradle.HonkerExtension
+import org.nosphere.honker.gradle.HonkerGenDependenciesTask
+import org.nosphere.honker.gradle.HonkerGenLicenseTask
+import org.nosphere.honker.gradle.HonkerGenNoticeTask
+import org.nosphere.honker.gradle.HonkerLicenseOverrideCandidate
+
+@CompileStatic
+class PublishedCodePlugin implements Plugin<Project>
+{
+  @Override
+  void apply( final Project project )
+  {
+    project.plugins.apply CodePlugin
+    configureJavadoc project
+    configureHonker( project )
+    project.plugins.apply VersionClassPlugin
+    project.plugins.apply AsciidocBuildInfoPlugin
+    applySupplementaryArchives project
+    project.plugins.apply PublishingPlugin
+  }
+
+  static void configureJavadoc( Project project )
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    project.tasks.withType( Javadoc ) { Javadoc task ->
+      task.onlyIf { !releaseSpec.developmentVersion }
+      def options = task.options as StandardJavadocDocletOptions
+      options.encoding = 'UTF-8'
+      options.docEncoding = 'UTF-8'
+      options.charSet = 'UTF-8'
+      options.noTimestamp = true
+      options.links = [
+        'http://docs.oracle.com/javase/8/docs/api/',
+        'https://stleary.github.io/JSON-java/',
+        'http://junit.org/junit4/javadoc/latest/'
+      ]
+      // exclude '**/internal/**'
+    }
+  }
+
+  private static void configureHonker( Project project )
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    if( releaseSpec.developmentVersion )
+    {
+      return
+    }
+    project.plugins.apply 'org.nosphere.honker'
+    def honkerGenDependencies = project.tasks.getByName( 'honkerGenDependencies' ) as HonkerGenDependenciesTask
+    def honkerGenLicense = project.tasks.getByName( 'honkerGenLicense' ) as HonkerGenLicenseTask
+    def honkerGenNotice = project.tasks.getByName( 'honkerGenNotice' ) as HonkerGenNoticeTask
+    def honkerCheck = project.tasks.getByName( 'honkerCheck' ) as HonkerCheckTask
+    [ honkerGenDependencies, honkerGenLicense, honkerGenNotice, honkerCheck ].group = null
+    def javaConvention = project.convention.getPlugin JavaPluginConvention
+    def mainSourceSet = javaConvention.sourceSets.getByName 'main'
+    mainSourceSet.output.dir( [ builtBy: honkerGenDependencies ] as Map<String, Object>,
+                              honkerGenDependencies.outputDir )
+    mainSourceSet.output.dir( [ builtBy: honkerGenLicense ] as Map<String, Object>,
+                              honkerGenLicense.outputDir )
+    mainSourceSet.output.dir( [ builtBy: honkerGenNotice ] as Map<String, Object>,
+                              honkerGenNotice.outputDir )
+    def honker = project.extensions.getByType HonkerExtension
+    // Project License, applied to all submodules
+    honker.license 'Apache 2'
+    // Dependencies (transitive or not) with no license information, overriding them
+    honker.licenseOverride { HonkerLicenseOverrideCandidate candidate ->
+      if( candidate.group == 'asm' || candidate.module == 'prefuse-core' )
+      {
+        candidate.license = 'BSD 3-Clause'
+      }
+      if( candidate.group == 'com.github.jnr' ) {
+        candidate.license = 'EPL'
+      }
+      if( candidate.group == 'javax.json'
+        || candidate.group == 'javax.websocket'
+        || candidate.group == 'javax.xml.bind' )
+      {
+        candidate.license = 'CDDL'
+      }
+      if( candidate.group == 'org.apache.httpcomponents'
+        || candidate.group == 'net.java.dev.jna'
+        || candidate.group == 'lucene'
+        || candidate.group == 'jdbm'
+        || candidate.group == 'org.osgi'
+        || candidate.group.startsWith( 'org.restlet' ) )
+      {
+        candidate.license = 'Apache 2'
+      }
+    }
+    honkerGenNotice.header = 'Apache Polygene'
+    honkerGenNotice.footer = 'This product includes software developed at\n' +
+                             'The Apache Software Foundation (http://www.apache.org/).\n'
+    project.tasks.getByName( 'check' ).dependsOn honkerCheck
+  }
+
+  private static void applySupplementaryArchives( Project project )
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    def javaConvention = project.convention.getPlugin JavaPluginConvention
+    def sourceJar = project.tasks.create( 'sourceJar', Jar ) { Jar task ->
+      task.description = 'Builds -sources.jar'
+      task.classifier = 'sources'
+      task.from javaConvention.sourceSets.getByName( 'main' ).allSource
+    }
+    def testSourceJar = project.tasks.create( 'testSourceJar', Jar ) { Jar task ->
+      task.description = 'Builds -testsources.jar'
+      task.classifier = 'testsources'
+      task.onlyIf { !releaseSpec.developmentVersion }
+      task.from javaConvention.sourceSets.getByName( 'test' ).allSource
+    }
+    def javadoc = project.tasks.getByName( 'javadoc' ) as Javadoc
+    def javadocJar = project.tasks.create( 'javadocJar', Jar ) { Jar task ->
+      task.description = 'Builds -javadoc.jar'
+      task.classifier = 'javadoc'
+      task.onlyIf { !releaseSpec.developmentVersion }
+      task.from javadoc.destinationDir
+      task.dependsOn javadoc
+    }
+    project.artifacts.add 'archives', sourceJar
+    if( !releaseSpec.developmentVersion )
+    {
+      project.artifacts.add 'archives', testSourceJar
+      project.artifacts.add 'archives', javadocJar
+    }
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/PublishingPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/PublishingPlugin.groovy
new file mode 100644
index 0000000..fbbb42e
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/PublishingPlugin.groovy
@@ -0,0 +1,214 @@
+/*
+ *  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.polygene.gradle.code
+
+import groovy.transform.CompileStatic
+import groovy.transform.TypeCheckingMode
+import org.apache.polygene.gradle.structure.release.ReleaseSpecExtension
+import org.gradle.api.GradleException
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.artifacts.maven.MavenDeployer
+import org.gradle.api.artifacts.maven.MavenDeployment
+import org.gradle.api.internal.plugins.DslObject
+import org.gradle.api.plugins.MavenRepositoryHandlerConvention
+import org.gradle.api.publication.maven.internal.deployer.DefaultGroovyMavenDeployer
+import org.gradle.api.publication.maven.internal.deployer.MavenRemoteRepository
+import org.gradle.api.tasks.Upload
+import org.gradle.plugins.signing.Sign
+import org.gradle.plugins.signing.SigningExtension
+
+/**
+ * Publishing.
+ *
+ * <strong>Configuration</strong>
+ *
+ * By default RELEASES are signed, SNAPSHOTS are not.
+ * Signing can be turned on or off by setting the {@literal uploadSigned} property.
+ *
+ * By default RELEASES must satisfy {@link org.apache.polygene.gradle.structure.release.ModuleReleaseSpec}, SNAPSHOT don't.
+ * This can be turned on or off by setting the {@literal uploadReleaseSpec} property.
+ *
+ * By default RELEASES and SNAPSHOTS are uploaded using HTTP.
+ * Used Wagon can be overridden by setting the {@literal uploadWagon} property.
+ *
+ * By default RELEASES and SNAPSHOTS are uploaded to Apache Nexus.
+ * Target repository can be overridden by setting the {@literal uploadRepository} property.
+ *
+ * No username/password is provided by default.
+ * If needed set them using the uploadUsername and {@literal uploadPassword} properties.
+ */
+@CompileStatic
+class PublishingPlugin implements Plugin<Project>
+{
+  static final String WAGON_HTTP = 'org.apache.maven.wagon:wagon-http:2.2'
+  static final String WAGON_SSH = 'org.apache.maven.wagon:wagon-ssh:2.2'
+  static final String WAGON_WEBDAV = 'org.apache.maven.wagon:wagon-webdav:1.0-beta-2'
+
+  static final String RELEASES_REPOSITORY_NAME = 'apache.releases.https'
+  static final String RELEASES_REPOSITORY_URL = 'https://repository.apache.org/service/local/staging/deploy/maven2'
+  static final String SNAPSHOTS_REPOSITORY_NAME = 'apache.snapshots.https'
+  static final String SNAPSHOTS_REPOSITORY_URL = 'https://repository.apache.org/content/repositories/snapshots'
+
+  static class Config
+  {
+    boolean snapshots
+    boolean releases
+    boolean signed
+    boolean releaseSpec
+    String wagon
+    String repositoryName
+    String repositoryUrl
+    String username
+    String password
+  }
+
+  @Override
+  void apply( final Project project )
+  {
+    Config config = configFor project
+    applyWagonConfiguration project, config
+    configureSigning project, config
+    configureUploadArchives project, config
+    configureStageArchives project
+    configureMavenMetadata project
+    applyMavenPublishAuth project
+  }
+
+  private static Config configFor( Project project )
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    def config = new Config()
+    config.snapshots = releaseSpec.snapshotVersion
+    config.releases = releaseSpec.releaseVersion
+    config.signed = project.findProperty( 'uploadSigned' ) ?: config.releases
+    config.releaseSpec = project.findProperty( 'uploadReleaseSpec' ) ?: config.releases
+    config.wagon = project.findProperty( 'uploadWagon' ) ?: WAGON_HTTP
+    config.repositoryName = project.findProperty( 'uploadRepositoryName' ) ?:
+                            config.releases ? RELEASES_REPOSITORY_NAME : SNAPSHOTS_REPOSITORY_NAME
+    config.repositoryUrl = project.findProperty( 'uploadRepository' ) ?:
+                           config.releases ? RELEASES_REPOSITORY_URL : SNAPSHOTS_REPOSITORY_URL
+    config.username = project.findProperty( 'uploadUsername' )
+    config.password = project.findProperty( 'uploadPassword' )
+    return config
+  }
+
+  private static void applyWagonConfiguration( Project project, Config config )
+  {
+    project.configurations.create( 'deployersJars' )
+    project.dependencies.add( 'deployersJars', config.wagon )
+  }
+
+  private static void configureSigning( Project project, Config config )
+  {
+    project.plugins.apply 'signing'
+    def signing = project.extensions.getByType SigningExtension
+    signing.required = config.signed && !project.findProperty( 'skipSigning' )
+    signing.sign project.configurations.getByName( 'archives' )
+    def signArchives = project.tasks.getByName( 'signArchives' ) as Sign
+    signArchives.enabled = config.signed && !project.findProperty( 'skipSigning' )
+    signArchives.onlyIf { !project.findProperty( 'skipSigning' ) }
+  }
+
+  @CompileStatic( TypeCheckingMode.SKIP )
+  private static void configureUploadArchives( Project project, Config config )
+  {
+    project.plugins.apply 'maven'
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    def uploadArchives = project.tasks.getByName( 'uploadArchives' ) as Upload
+    uploadArchives.doFirst {
+      if( !config.snapshots && !config.releases )
+      {
+        throw new GradleException( "'version' must be given as a system property to perform a release." )
+      }
+    }
+    uploadArchives.onlyIf {
+      def notSkipped = !project.hasProperty( 'skipUpload' )
+      def approvedProject = releaseSpec.publishedProjects.contains project
+      return notSkipped && ( !config.releaseSpec || ( approvedProject || project == project.rootProject ) )
+    }
+    uploadArchives.dependsOn project.tasks.getByName( 'check' )
+    def mavenDeployer = getMavenDeployer uploadArchives
+    if( config.signed )
+    {
+      mavenDeployer.beforeDeployment { MavenDeployment deployment ->
+        project.extensions.getByType( SigningExtension ).signPom deployment
+      }
+    }
+    mavenDeployer.configuration = project.configurations.getByName( 'deployersJars' )
+    def repoCoordinates = [ id: config.repositoryName, url: config.repositoryUrl ] as Map
+    def repoCredentials = [ userName: config.username, password: config.password ] as Map
+    def repo = mavenDeployer.createRepository(repoCoordinates)
+    if( config.username )
+    {
+      ( repo as MavenRemoteRepository ).authentication( repoCredentials )
+    }
+    if( config.releases )
+    {
+      mavenDeployer.repository = repo
+    }
+    else
+    {
+      mavenDeployer.snapshotRepository = repo
+    }
+  }
+
+  private static void configureStageArchives( Project project )
+  {
+    def stageConfiguration = project.configurations.create 'stageArchives'
+    stageConfiguration.extendsFrom project.configurations.getByName( 'archives' )
+
+    def stageTask = project.tasks.getByName( 'uploadStageArchives' ) as Upload
+    stageTask.uploadDescriptor = true
+    def mavenDeployer = getMavenDeployer stageTask
+    def repository = new MavenRemoteRepository()
+    repository.id = 'stageArchives'
+    repository.url = "file://${ project.buildDir.absolutePath }/stage/archives"
+    mavenDeployer.repository = repository
+    mavenDeployer.snapshotRepository = repository
+  }
+
+  private static void configureMavenMetadata( Project project )
+  {
+    project.tasks.withType( Upload ) { Upload task ->
+      def mavenDeployer = task.repositories.findByName( 'mavenDeployer' ) as MavenDeployer
+      if( mavenDeployer )
+      {
+        MavenMetadata.applyTo mavenDeployer
+        mavenDeployer.pom.artifactId = PublishNaming.publishedNameFor( project.path )
+      }
+    }
+  }
+
+  private static void applyMavenPublishAuth( final Project project )
+  {
+    // Bug in maven-publish-auth require apply after uploadArchives setup
+    project.plugins.apply 'maven-publish-auth'
+  }
+
+  private static DefaultGroovyMavenDeployer getMavenDeployer( Upload uploadTask )
+  {
+    // TODO Remove use of Gradle internals
+    // DslObject to get the Upload task convention
+    // MavenRepositoryHandlerConvention & DefaultGroovyMavenDeployer to configure Wagon, Authentication and Signing
+    def repositoriesConvention = new DslObject( uploadTask.repositories )
+      .getConvention()
+      .getPlugin( MavenRepositoryHandlerConvention )
+    return repositoriesConvention.mavenDeployer() as DefaultGroovyMavenDeployer
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/VersionClassPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/VersionClassPlugin.groovy
new file mode 100644
index 0000000..345f25f
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/code/VersionClassPlugin.groovy
@@ -0,0 +1,94 @@
+/*
+ *  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.polygene.gradle.code
+
+import groovy.transform.CompileStatic
+import java.nio.file.Files
+import org.apache.polygene.gradle.util.Licensing
+import org.gradle.api.Project
+import org.gradle.api.Plugin
+import org.gradle.api.Task
+import org.gradle.api.file.SourceDirectorySet
+import org.gradle.api.plugins.JavaPlugin
+import org.gradle.api.plugins.JavaPluginConvention
+import org.gradle.api.tasks.SourceSet
+import org.gradle.api.tasks.bundling.Jar
+
+// TODO Add build date, placeholder for dev versions
+// TODO Add git data, placeholders for dev versions
+@CompileStatic
+class VersionClassPlugin implements Plugin<Project>
+{
+  @Override
+  void apply( Project project )
+  {
+    project.getPlugins().apply JavaPlugin.class
+    def genSrc = 'generated-src/version'
+    project.task( 'generateVersionClass' ) { Task task ->
+      def headerFile = project.rootProject.file 'etc/header.txt'
+      def generatedSrcDir = new File( project.buildDir, genSrc )
+      task.inputs.file headerFile
+      task.inputs.property 'projectVersion', project.version
+      task.inputs.property 'projectName', project.name
+      task.inputs.property 'projectGroup', project.group
+      task.outputs.file generatedSrcDir
+      task.doLast {
+        def publishedName = PublishNaming.publishedNameFor project.path
+        def packageName = "${ publishedName }".replace '-', '_'
+        def outFilename = "java/" + packageName.replace( '.', '/' ) + "/BuildVersion.java"
+        def outFile = new File( generatedSrcDir, outFilename )
+        Files.createDirectories outFile.parentFile.toPath()
+        outFile.withWriter( 'UTF-8' ) { BufferedWriter out ->
+          out.write Licensing.withLicenseHeader( headerFile.text, 'java' )
+          out.writeLine """
+        package ${ packageName };
+
+        /**
+         * Build version.
+         */
+        public interface BuildVersion
+        {
+            /** {@literal ${ project.group }}. */
+            String GROUP = \"${ project.group }\";
+        
+            /** {@literal ${ publishedName }}. */
+            String NAME = \"${ publishedName }\";
+        
+            /** {@literal ${ project.version }}. */
+            String VERSION = \"${ project.version }\";
+        
+            /** {@literal ${ project.group }:${ publishedName }:${ project.version }}. */
+            String GAV = GROUP + ':' + NAME + ':' + VERSION;
+        }
+        """.stripIndent().trim()
+        }
+      }
+    }
+    def sourceSets = project.convention.getPlugin( JavaPluginConvention ).sourceSets
+    sourceSets.create( "version" ) { SourceSet sourceSet ->
+      sourceSet.java { SourceDirectorySet dirSet ->
+        dirSet.srcDir project.buildDir.name + '/' + genSrc + '/java'
+      }
+    }
+    project.tasks.getByName( 'compileJava' ).dependsOn 'compileVersionJava'
+    project.tasks.getByName( 'compileVersionJava' ).dependsOn 'generateVersionClass'
+    project.tasks.getByName( 'jar' ) { Jar task ->
+      task.from sourceSets.getByName( 'version' ).output
+    }
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesDeclarationExtension.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesDeclarationExtension.groovy
new file mode 100644
index 0000000..9277e62
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesDeclarationExtension.groovy
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.gradle.dependencies
+
+import groovy.transform.CompileStatic
+import java.util.function.BiConsumer
+import org.gradle.api.artifacts.DependencySubstitution
+import org.gradle.api.artifacts.component.ModuleComponentSelector
+
+@CompileStatic
+class DependenciesDeclarationExtension
+{
+  final Map<String, String> repositoriesUrls = [ : ]
+  final Map<String, Object> libraries = [ : ]
+  final Map<String, List<Object>> defaultDependencies = [ : ]
+  BiConsumer<DependencySubstitution, ModuleComponentSelector> dependencySubstitutionSpec
+  final Map<String, String> buildToolsVersions = [ : ]
+  final Map<String, String> dockerImagesVersions = [ : ]
+  final Map<String, String> nodeVersions = [ : ]
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesDeclarationPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesDeclarationPlugin.groovy
new file mode 100644
index 0000000..73cb4d5
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesDeclarationPlugin.groovy
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.gradle.dependencies
+
+import groovy.transform.CompileStatic
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+@CompileStatic
+class DependenciesDeclarationPlugin implements Plugin<Project>
+{
+  @Override
+  void apply( Project project )
+  {
+    project.extensions.create( 'dependenciesDeclaration', DependenciesDeclarationExtension )
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesDownloadTask.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesDownloadTask.groovy
new file mode 100644
index 0000000..6a24cee
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesDownloadTask.groovy
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.gradle.dependencies
+
+import groovy.transform.CompileStatic
+import org.gradle.api.DefaultTask
+import org.gradle.api.artifacts.Configuration
+import org.gradle.api.tasks.TaskAction
+
+@CompileStatic
+class DependenciesDownloadTask extends DefaultTask
+{
+  @TaskAction
+  void downloadAllDependencies()
+  {
+    def allConfigurations = project.allprojects.collect { it.configurations }.flatten() as Set<Configuration>
+    allConfigurations.findAll { it.canBeResolved }*.resolvedConfiguration
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesPlugin.groovy
new file mode 100644
index 0000000..dc6efcf
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/DependenciesPlugin.groovy
@@ -0,0 +1,92 @@
+/*
+ *  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.polygene.gradle.dependencies
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.TaskGroups
+import org.gradle.api.Action
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.artifacts.Configuration
+import org.gradle.api.artifacts.DependencySubstitution
+import org.gradle.api.artifacts.component.ModuleComponentSelector
+import org.gradle.api.artifacts.repositories.MavenArtifactRepository
+
+@CompileStatic
+class DependenciesPlugin implements Plugin<Project>
+{
+  static class TaskNames
+  {
+    static final String DOWNLOAD_DEPENDENCIES = 'downloadDependencies'
+  }
+
+  @Override
+  void apply( final Project project )
+  {
+    def dependenciesDeclaration = project.rootProject.extensions.getByType DependenciesDeclarationExtension
+    applyRepositories project, dependenciesDeclaration
+    applyLibraries project, dependenciesDeclaration
+    applyDependencyResolutionRules project, dependenciesDeclaration
+    applyDependenciesDownloadTask project
+  }
+
+  private static void applyRepositories( Project project, DependenciesDeclarationExtension declaration )
+  {
+    declaration.repositoriesUrls.each { name, url ->
+      project.repositories.maven { MavenArtifactRepository repo ->
+        repo.name = name
+        repo.url = url
+      }
+    }
+  }
+
+  private static void applyLibraries( Project project, DependenciesDeclarationExtension declaration )
+  {
+    project.extensions.extraProperties.set 'libraries', declaration.libraries
+  }
+
+  static void applyDependencyResolutionRules( Project project, DependenciesDeclarationExtension declaration )
+  {
+    project.configurations.all(
+      { Configuration configuration ->
+        applyDependencyResolutionRules configuration, declaration
+      } as Action<Configuration> )
+  }
+
+  static void applyDependencyResolutionRules( Configuration configuration,
+                                              DependenciesDeclarationExtension declaration )
+  {
+    configuration.resolutionStrategy.dependencySubstitution.all(
+      { DependencySubstitution dep ->
+        if( dep.requested instanceof ModuleComponentSelector )
+        {
+          def selector = dep.requested as ModuleComponentSelector
+          declaration.dependencySubstitutionSpec.accept dep, selector
+        }
+      } as Action<DependencySubstitution> )
+  }
+
+  private static void applyDependenciesDownloadTask( Project project )
+  {
+    project.tasks.create( TaskNames.DOWNLOAD_DEPENDENCIES, DependenciesDownloadTask ) { Task task ->
+      task.group = TaskGroups.HELP
+      task.description = 'Download all dependencies'
+    }
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/PolygeneExtension.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/PolygeneExtension.groovy
new file mode 100644
index 0000000..e08a4ab
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/dependencies/PolygeneExtension.groovy
@@ -0,0 +1,81 @@
+/*
+ *  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.polygene.gradle.dependencies
+
+import groovy.transform.CompileStatic
+import org.gradle.api.Project
+import org.gradle.api.artifacts.Dependency
+
+@CompileStatic
+class PolygeneExtension
+{
+  private final Project project
+  final Core core
+  final Internals internals
+
+  PolygeneExtension( Project project )
+  {
+    this.project = project
+    this.core = new Core()
+    this.internals = new Internals()
+  }
+
+  class Core
+  {
+    Dependency api = core( 'api' )
+    Dependency spi = core( 'spi' )
+    Dependency runtime = core( 'runtime' )
+    Dependency bootstrap = core( 'bootstrap' )
+    Dependency testsupport = core( 'testsupport' )
+  }
+
+  class Internals
+  {
+    Dependency testsupport = internal( 'testsupport-internal' )
+  }
+
+  private Dependency core( String name )
+  {
+    return dependency( 'core', name )
+  }
+
+  Dependency library( String name )
+  {
+    return dependency( 'libraries', name )
+  }
+
+  Dependency extension( String name )
+  {
+    return dependency( 'extensions', name )
+  }
+
+  Dependency tool( String name )
+  {
+    return dependency( 'tools', name )
+  }
+
+  Dependency internal( String name )
+  {
+    return dependency( 'internals', name )
+  }
+
+  private Dependency dependency( String group, String name )
+  {
+    project.dependencies.project( path: ":$group:$name" )
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/RootPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/RootPlugin.groovy
new file mode 100644
index 0000000..5b0c497
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/RootPlugin.groovy
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.gradle.structure
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.BasePlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+@CompileStatic
+class RootPlugin implements Plugin<Project>
+{
+  static final String PROJECT_TITLE = 'Apache Polygene™ (Java Edition) SDK'
+  static final String PROJECT_DESCRIPTION = 'Apache Polygene™ (Java Edition) is a framework for domain centric ' +
+                                            'application development, including evolved concepts from AOP, DI and DDD.'
+
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply BasePlugin
+    applyProjectMetadata( project )
+  }
+
+  private static void applyProjectMetadata( Project project )
+  {
+    def extraProperties = project.extensions.extraProperties
+    extraProperties.set 'title', PROJECT_TITLE
+    extraProperties.set 'description', PROJECT_DESCRIPTION
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/SettingsPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/SettingsPlugin.groovy
new file mode 100644
index 0000000..f252055
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/SettingsPlugin.groovy
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.gradle.structure
+
+import org.gradle.api.Plugin
+import org.gradle.api.initialization.Settings
+import org.gradle.api.JavaVersion
+
+class SettingsPlugin implements Plugin<Settings>
+{
+  @Override
+  void apply( Settings settings )
+  {
+    checkPreconditions settings
+  }
+
+  static void checkPreconditions( Settings setting )
+  {
+    def java = JavaVersion.current()
+    def mini = JavaVersion.VERSION_1_8
+    if( java < mini )
+    {
+      throw new Exception( "Cannot build using Java ${ java }, please use ${ JavaVersion.VERSION_1_8 } or greater." )
+    }
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/core/CorePlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/core/CorePlugin.groovy
new file mode 100644
index 0000000..a07d88f
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/core/CorePlugin.groovy
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.gradle.structure.core
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.code.PublishedCodePlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.tasks.compile.JavaCompile
+
+@CompileStatic
+class CorePlugin implements Plugin<Project>
+{
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply PublishedCodePlugin
+    configureJava( project )
+  }
+
+  private static void configureJava( Project project )
+  {
+    project.tasks.withType( JavaCompile ) { JavaCompile task ->
+      // Unchecked warnings for non-test compilations
+      if( !task.name.toLowerCase( Locale.US ).contains( 'test' ) )
+      {
+        task.options.compilerArgs << '-Xlint:unchecked'
+      }
+    }
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/distributions/DistributionsPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/distributions/DistributionsPlugin.groovy
new file mode 100644
index 0000000..46233ce
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/distributions/DistributionsPlugin.groovy
@@ -0,0 +1,573 @@
+/*
+ *  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.polygene.gradle.structure.distributions
+
+import groovy.transform.CompileStatic
+import groovy.transform.TypeCheckingMode
+import org.apache.commons.io.FileUtils
+import org.apache.polygene.gradle.BasePlugin
+import org.apache.polygene.gradle.TaskGroups
+import org.apache.polygene.gradle.code.PublishedCodePlugin
+import org.apache.polygene.gradle.dependencies.DependenciesDeclarationExtension
+import org.apache.polygene.gradle.dependencies.DependenciesPlugin
+import org.apache.polygene.gradle.structure.release.ReleaseSpecExtension
+import org.apache.polygene.gradle.tasks.ExecLogged
+import org.apache.rat.gradle.RatTask
+import org.apache.tools.ant.filters.ReplaceTokens
+import org.gradle.api.Action
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.artifacts.Dependency
+import org.gradle.api.artifacts.component.ModuleComponentIdentifier
+import org.gradle.api.artifacts.result.ComponentArtifactsResult
+import org.gradle.api.artifacts.result.ResolvedArtifactResult
+import org.gradle.api.artifacts.result.ResolvedDependencyResult
+import org.gradle.api.file.CopySpec
+import org.gradle.api.file.FileCopyDetails
+import org.gradle.api.tasks.Copy
+import org.gradle.api.tasks.Sync
+import org.gradle.api.tasks.bundling.Compression
+import org.gradle.api.tasks.bundling.Tar
+import org.gradle.api.tasks.bundling.Zip
+import org.gradle.language.base.plugins.LifecycleBasePlugin
+import org.gradle.maven.MavenModule
+import org.gradle.maven.MavenPomArtifact
+import org.gradle.plugins.ide.internal.IdeDependenciesExtractor
+import org.gradle.plugins.ide.internal.resolver.model.IdeExtendedRepoFileDependency
+import org.gradle.plugins.signing.Sign
+import org.gradle.plugins.signing.SigningExtension
+
+import java.nio.file.Files
+import java.nio.file.Path
+
+// TODO Split each distribution as a separate plugin
+// TODO Expose all project outputs into configurations
+@CompileStatic
+class DistributionsPlugin implements Plugin<Project>
+{
+  static class TaskNames
+  {
+    static final String STAGE_SOURCE_DIST = 'stageSourceDistribution'
+    static final String ZIP_SOURCE_DIST = 'zipSourceDistribution'
+    static final String TAR_SOURCE_DIST = 'tarSourceDistribution'
+
+    static final String STAGE_MAVEN_BINARIES = 'stageBinariesMavenRepository'
+    static final String STAGE_BINARY_DIST = 'stageBinaryDistribution'
+    static final String ZIP_BINARY_DIST = 'zipBinaryDistribution'
+    static final String TAR_BINARY_DIST = 'tarBinaryDistribution'
+
+    private static final String STAGE_MAVEN_DEPENDENCIES = 'stageDependenciesMavenRepository'
+    static final String ZIP_DEPENDENCIES_DIST = 'zipDependenciesDistribution'
+
+    static final String CHECK_DISTRIBUTIONS = 'checkDistributions'
+    static final String CHECK_SOURCE_DIST = 'checkSourceDistribution'
+    static final String CHECK_BINARY_DIST = 'checkBinaryDistribution'
+    private static final String RAT_SOURCE_DIST = 'ratSourceDistribution'
+    private static final String INSPECT_SOURCE_DIST = 'inspectSourceDistribution'
+    private static final String BUILD_SOURCE_DIST = 'buildSourceDistribution'
+    private static final String RAT_BINARY_DIST = 'ratBinaryDistribution'
+  }
+
+  @Override
+  void apply( final Project project )
+  {
+    project.plugins.apply BasePlugin
+    project.plugins.apply org.gradle.api.plugins.BasePlugin
+    project.plugins.apply DependenciesPlugin
+    applyStageBinariesMavenRepository project
+    applyStageLibrariesMavenRepository project
+    applyAssembleDistributions project
+    applyCheckDistributions project
+    configureDistributionChecksums project
+    configureSigning project
+  }
+
+  private static void applyAssembleDistributions( Project project )
+  {
+    applySourceDistribution project
+    applyBinaryDistribution project
+  }
+
+  private static void applyCheckDistributions( Project project )
+  {
+    def distChecks = [ applySourceDistributionCheck( project ),
+                       applyBinaryDistributionCheck( project ) ]
+    project.tasks.create( TaskNames.CHECK_DISTRIBUTIONS ) { Task task ->
+      task.group = TaskGroups.DISTRIBUTION_VERIFICATION
+      task.description = 'Run all distribution checks.'
+      task.dependsOn distChecks
+    }
+  }
+
+  private static void applySourceDistribution( Project project )
+  {
+    def releaseSpec = project.extensions.getByType( ReleaseSpecExtension )
+    def srcDistFilesCopySpec = project.copySpec { CopySpec spec ->
+      spec.from project.rootProject.projectDir
+      spec.include '*.txt'
+      spec.include 'doap.rdf'
+      spec.include '*.gradle'
+      spec.include 'gradle/**'
+      spec.include 'etc/**'
+      spec.include 'buildSrc/**'
+      spec.include 'src/**'
+      releaseSpec.publishedProjects.each { p ->
+        def relPath = new File( project.rootProject.projectDir.toURI().relativize( p.projectDir.toURI() ).toString() )
+        spec.include "$relPath/**"
+      }
+      spec.include 'distributions/**'
+      spec.include 'reports/**'
+      spec.include 'release/**'
+      spec.include 'internals/**'
+      spec.include 'manual/**'
+      spec.include 'samples/**'
+      spec.include 'tests/**'
+      spec.include 'tutorials/**'
+      // Filtered, see below
+      spec.exclude 'settings.gradle'
+      spec.exclude 'gradle.properties'
+      // Excludes
+      spec.exclude '**/.git/**'              // Git directories
+      spec.exclude '**/.git*'                // Git files
+      spec.exclude '**/build/**'             // Build output
+      spec.exclude 'gradlew*'                // Gradle wrapper scripts
+      spec.exclude 'gradle/wrapper/*.jar'    // Gradle wrapper JAR
+      spec.exclude '**/.gradle/**'           // Gradle caches
+      spec.exclude '**/.gradletasknamecache' // Gradle shell completion cache
+      spec.exclude '**/node_modules/**'      // Node's node_module dir
+      spec.exclude 'derby.log'               // Derby test garbage
+      spec.exclude '**/*.iml'                // IDEA files
+      spec.exclude '**/*.ipr'                // IDEA files
+      spec.exclude '**/*.iws'                // IDEA files
+      spec.exclude '**/.idea'                // IDEA files
+      spec.exclude '**/out/**'               // IDEA build output
+      spec.exclude '**/.classpath'           // Eclipse files
+      spec.exclude '**/.project'             // Eclipse files
+      spec.exclude '**/.settings'            // Eclipse files
+      spec.exclude '**/.nb-gradle/**'        // Netbeans files
+      spec.exclude '**/.nb-gradle*'          // Netbeans files
+
+      spec.into '.'
+    }
+    def srcDistSupplementaryFilesCopySpec = project.copySpec { CopySpec spec ->
+      spec.from project.file( 'src/src-dist' )
+      spec.into '.'
+    }
+    def srcDistFilteredFilesTask = project.tasks.create 'srcDistFilteredFiles'
+    srcDistFilteredFilesTask.description = 'Apply release specification to source distribution build scripts'
+    // Generates various files for the source distribution
+    // - settings.gradle
+    // - gradle.properties to set version !
+    def filteredDir = new File( "$project.buildDir/tmp/srcDistFilteredFiles" )
+    srcDistFilteredFilesTask.outputs.file filteredDir
+    srcDistFilteredFilesTask.doLast {
+      // Settings
+      def settingsFile = new File( filteredDir, 'settings.gradle' )
+      settingsFile.parentFile.mkdirs()
+      if( releaseSpec.releaseVersion )
+      {
+        def filteredSettings = ''
+        def unapprovedProjectPaths = releaseSpec.unapprovedProjects.collect { p -> p.path.substring( 1 ) }
+        project.rootProject.file( 'settings.gradle' ).readLines().each { line ->
+          if( !unapprovedProjectPaths.find { p -> line.contains p } )
+          {
+            filteredSettings += "$line\n"
+          }
+        }
+        settingsFile.text = filteredSettings
+      }
+      else
+      {
+        settingsFile.text = project.rootProject.file( 'settings.gradle' ).text
+      }
+      // gradle.properties
+      def gradlePropsFile = new File( filteredDir, 'gradle.properties' )
+      gradlePropsFile.parentFile.mkdirs()
+      gradlePropsFile.text = project.rootProject.file( 'gradle.properties' ).text +
+                             "\nskipSigning=true\nskipAsciidocIfAbsent=true\n\nversion=$project.version\n"
+    }
+    def srcDistFilteredFilesCopySpec = project.copySpec { CopySpec spec ->
+      spec.from srcDistFilteredFilesTask
+      spec.into '.'
+    }
+    def srcDistCopySpec = project.copySpec { CopySpec spec ->
+      spec.into "apache-polygene-java-$project.version-src"
+      spec.with srcDistFilesCopySpec
+      spec.with srcDistSupplementaryFilesCopySpec
+      spec.with srcDistFilteredFilesCopySpec
+    }
+
+    def zipSources = project.tasks.create( TaskNames.ZIP_SOURCE_DIST, Zip ) { Zip task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = 'Assembles .zip source distribution.'
+      task.baseName = 'apache-polygene-java'
+      task.with srcDistCopySpec
+      task.classifier = 'src'
+    }
+    def tarSources = project.tasks.create( TaskNames.TAR_SOURCE_DIST, Tar ) { Tar task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = 'Assembles .tar.gz source distribution.'
+      task.baseName = 'apache-polygene-java'
+      task.with srcDistCopySpec
+      task.compression = Compression.GZIP
+      task.classifier = 'src'
+    }
+    project.artifacts.add( 'archives', zipSources )
+    project.artifacts.add( 'archives', tarSources )
+
+    project.tasks.create( TaskNames.STAGE_SOURCE_DIST, Copy ) { Copy task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = "Stages the source distribution in the build directory."
+      task.with srcDistCopySpec
+      task.into 'build/stage/source-distribution'
+    }
+  }
+
+  private static Task applySourceDistributionCheck( Project project )
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    project.plugins.apply 'org.nosphere.apache.rat-base'
+    def unpackedSrcDistDir = project.file( "build/stage/source-distribution/apache-polygene-java-$project.version-src" )
+    project.tasks.create( TaskNames.RAT_SOURCE_DIST, RatTask, { RatTask task ->
+      task.group = TaskGroups.DISTRIBUTION_VERIFICATION
+      task.description = 'Checks the source distribution using Apache RAT.'
+      task.dependsOn TaskNames.STAGE_SOURCE_DIST
+      task.setInputDir unpackedSrcDistDir.absolutePath
+      task.onlyIf { !releaseSpec.developmentVersion }
+      task.excludes = [
+        '**/.DS_Store/**', '**/._*',
+        // Git Files
+        '**/.git/**', '**/.gitignore',
+        // Gradle Files
+        'gradle/wrapper/**', '**/gradlew', '**/gradlew.bat', '**/.gradle/**',
+        // Build Output
+        '**/build/**', '**/derby.log', 'out/**',
+        // IDE Files
+        '**/.idea/**', '**/*.iml', '**/*.ipr', '**/*.iws',
+        '**/.settings/**', '**/.classpath', '**/.project',
+        '**/.gradletasknamecache', '**/private/cache/**',
+        '**/.nb-gradle-properties', '**/.nb-gradle/**',
+        // JSON files are not allowed to have comments, according to http://www.json.org/ and http://www.ietf.org/rfc/rfc4627.txt
+        '**/*.json',
+        // Various Text Resources
+        '**/README.*', '**/README*.*', '**/TODO',
+        '**/src/main/resources/**/*.txt',
+        '**/src/test/resources/**/*.txt',
+        'libraries/rest-server/src/main/resources/**/*.htm',
+        'libraries/rest-server/src/main/resources/**/*.atom',
+        'tools/generator-polygene/app/templates/**/*.tmpl',
+        'tools/generator-polygene/app/templates/**/*.*_',
+        'tools/qidea/src/main/resources/**/*.ft',
+        'tools/qidea/src/main/resources/**/*.template',
+        // Graphic Resources
+        '**/*.svg', '**/*.gif', '**/*.png', '**/*.jpg', '**/*.psd',
+        // Keystores
+        '**/*.jceks',
+        // Syntax Highlighter - MIT
+        'manual/**/sh*.css', 'manual/**/sh*.js',
+        // jQuery & plugins - MIT
+        'manual/**/jquery*.js',
+        // W3C XML Schemas - W3C Software License
+        'samples/rental/src/main/resources/*.xsd',
+        // Polygene Generator Heroes Templates - MIT
+        'tools/generator-polygene/app/templates/Heroes/**',
+      ]
+    } as Action<RatTask> )
+    project.tasks.create( TaskNames.INSPECT_SOURCE_DIST ) { Task task ->
+      task.group = TaskGroups.DISTRIBUTION_VERIFICATION
+      task.description = 'Inspects various aspects of the source distribution.'
+      task.dependsOn TaskNames.STAGE_SOURCE_DIST
+      task.onlyIf { !releaseSpec.developmentVersion }
+      task.doLast {
+        // ad-hoc checks to the source distribution -----------------------
+        def assertFilePresent = { String path -> assert new File( unpackedSrcDistDir, path ).isFile() }
+        def assertFileAbsent = { String path -> assert !new File( unpackedSrcDistDir, path ).isFile() }
+
+        assertFileAbsent 'gradlew'
+        assertFileAbsent 'gradlew.bat'
+        assertFileAbsent 'gradle/wrapper/gradle-wrapper.jar'
+        assertFilePresent 'gradle/wrapper/gradle-wrapper.properties'
+      }
+    }
+    project.tasks.create( TaskNames.BUILD_SOURCE_DIST, ExecLogged, { ExecLogged task ->
+      task.group = TaskGroups.DISTRIBUTION_VERIFICATION
+      task.description = 'Checks the source distribution by running `gradle build` inside.'
+      task.dependsOn TaskNames.STAGE_SOURCE_DIST
+      task.mustRunAfter TaskNames.RAT_SOURCE_DIST
+      task.mustRunAfter TaskNames.INSPECT_SOURCE_DIST
+      def workDir = project.file( "$project.buildDir/tmp/${ TaskNames.BUILD_SOURCE_DIST }" )
+      task.inputs.dir unpackedSrcDistDir
+      task.workingDir = workDir
+      def gradlew = new File( project.rootDir, 'gradlew' ).absolutePath
+      def settings = new File( workDir, 'settings.gradle' ).absolutePath
+      task.commandLine = [ gradlew, '-c', settings, 'build', '-u', '-s', /* '-g', workDir */ ]
+      task.doFirst {
+        project.copy { CopySpec spec ->
+          spec.from unpackedSrcDistDir
+          spec.into workDir
+        }
+      }
+      task.doLast {
+        if( workDir.exists() )
+        {
+          workDir.deleteDir()
+        }
+      }
+    } as Action<ExecLogged> )
+    project.tasks.create( TaskNames.CHECK_SOURCE_DIST ) { Task task ->
+      task.description = "Checks the source distribution."
+      task.dependsOn TaskNames.RAT_SOURCE_DIST, TaskNames.INSPECT_SOURCE_DIST, TaskNames.BUILD_SOURCE_DIST
+    }
+  }
+
+  private static void applyBinaryDistribution( Project project )
+  {
+    def releaseSpec = project.extensions.getByType( ReleaseSpecExtension )
+    def docsCopySpec = project.copySpec { CopySpec spec ->
+      spec.from "$project.rootProject.projectDir/reports/build/docs"
+      spec.from "$project.rootProject.projectDir/manual/build/docs/website"
+      spec.into 'docs'
+    }
+    def libsCopySpec = project.copySpec { CopySpec spec ->
+      spec.from project.tasks.getByName( TaskNames.STAGE_MAVEN_BINARIES )
+      spec.into 'libs/'
+      spec.exclude '**-testsources.jar'
+      spec.exclude '**/*.asc'
+    }
+    def extraDistTextCopySpec = project.copySpec { CopySpec spec ->
+      releaseSpec.publishedProjects.collect { p ->
+        spec.from project.fileTree( dir: "$p.projectDir/src/dist/", include: '**', exclude: "**/*.jar*" )
+        spec.eachFile { FileCopyDetails fcd ->
+          fcd.filter( ReplaceTokens, tokens: [ version: project.version ] )
+        }
+      }
+      spec.into '.'
+    }
+    def extraDistBinCopySpec = project.copySpec { CopySpec spec ->
+      releaseSpec.publishedProjects.collect { p ->
+        spec.from "$p.projectDir/src/dist/"
+        spec.include '**/*.jar'
+        spec.include '**/*.jar_'
+      }
+      spec.into '.'
+    }
+    def binDistNoticesCopySpec = project.copySpec { CopySpec spec ->
+      spec.from "$project.projectDir/LICENSE.txt"
+      spec.from "$project.projectDir/src/bin-dist"
+      spec.into '.'
+    }
+    def binDistImage = project.copySpec { CopySpec spec ->
+      spec.into "apache-polygene-java-$project.version-bin"
+      spec.with binDistNoticesCopySpec
+      spec.with docsCopySpec
+      spec.with extraDistTextCopySpec
+      spec.with extraDistBinCopySpec
+      spec.with libsCopySpec
+    }
+
+    def binariesBuildDependencies = {
+      project.rootProject.allprojects
+             .findAll { p -> p.plugins.hasPlugin( PublishedCodePlugin ) }
+             .collect { p -> "${ p.path }:${ LifecycleBasePlugin.ASSEMBLE_TASK_NAME }" as String } +
+             ( releaseSpec.developmentVersion ? [] as List<String> : [ ':manual:website', ':reports:javadocs' ] )
+    }
+
+    def zipBinaries = project.tasks.create( TaskNames.ZIP_BINARY_DIST, Zip ) { Zip task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = 'Assembles .zip binary distribution.'
+      task.dependsOn binariesBuildDependencies
+      task.baseName = 'apache-polygene-java'
+      task.classifier = 'bin'
+      task.with binDistImage
+    }
+    def tarBinaries = project.tasks.create( TaskNames.TAR_BINARY_DIST, Tar ) { Tar task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = 'Assembles .tar.gz binary distribution.'
+      task.dependsOn binariesBuildDependencies
+      task.baseName = 'apache-polygene-java'
+      task.classifier = 'bin'
+      task.compression = Compression.GZIP
+      task.with binDistImage
+    }
+    project.artifacts.add( 'archives', zipBinaries )
+    project.artifacts.add( 'archives', tarBinaries )
+
+    project.tasks.create( TaskNames.STAGE_BINARY_DIST, Copy ) { Copy task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = "Stages the binary distribution in the build directory."
+      task.with binDistImage
+      task.into 'build/stage/binary-distribution'
+    }
+  }
+
+  private static Task applyBinaryDistributionCheck( Project project )
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    project.plugins.apply 'org.nosphere.apache.rat-base'
+    def unpackedBinDistDir = project.file( "build/stage/binary-distribution/apache-polygene-java-$project.version-bin" )
+    project.tasks.create( TaskNames.RAT_BINARY_DIST, RatTask, { RatTask task ->
+      task.group = TaskGroups.DISTRIBUTION_VERIFICATION
+      task.description = "Checks the binary distribution using Apache RAT."
+      task.onlyIf { !releaseSpec.developmentVersion }
+      task.dependsOn TaskNames.STAGE_BINARY_DIST
+      task.inputDir = unpackedBinDistDir.absolutePath
+      task.reportDir = project.file( 'build/reports/rat-bin-dist' )
+      task.excludes = [
+        '.gradle/**',
+        'docs/**',
+        'etc/templates/**',
+        'libs/**'
+      ]
+    } as Action<RatTask> )
+    project.tasks.create( TaskNames.CHECK_BINARY_DIST ) { Task task ->
+      task.description = 'Checks the binary distribution.'
+      task.dependsOn TaskNames.RAT_BINARY_DIST
+    }
+  }
+
+  @CompileStatic( TypeCheckingMode.SKIP )
+  private static void configureDistributionChecksums( Project project )
+  {
+    project.tasks.withType( Zip ) { Zip task ->
+      task.doLast {
+        project.ant.checksum file: task.archivePath, algorithm: 'MD5'
+        project.ant.checksum file: task.archivePath, algorithm: 'SHA-512'
+      }
+    }
+    project.tasks.withType( Tar ) { Tar task ->
+      task.doLast {
+        project.ant.checksum file: task.archivePath, algorithm: 'MD5'
+        project.ant.checksum file: task.archivePath, algorithm: 'SHA-512'
+      }
+    }
+  }
+
+  private static void configureSigning( Project project )
+  {
+    def releaseSpec = project.extensions.getByType( ReleaseSpecExtension )
+    project.plugins.apply 'signing'
+    def signing = project.extensions.getByType SigningExtension
+    signing.required = !releaseSpec.developmentVersion && !project.findProperty( 'skipSigning' )
+    def distTasks = [ TaskNames.ZIP_SOURCE_DIST, TaskNames.TAR_SOURCE_DIST,
+                      TaskNames.ZIP_BINARY_DIST, TaskNames.TAR_BINARY_DIST ]
+                     .collect { taskName -> project.tasks.getByName( taskName ) }
+    distTasks.each { distTask ->
+      distTask.finalizedBy signing.sign( distTask )
+    }
+    project.tasks.withType( Sign ) { Sign task ->
+      task.enabled = !releaseSpec.developmentVersion && !project.findProperty( 'skipSigning' )
+      task.onlyIf { !project.findProperty( 'skipSigning' ) }
+    }
+  }
+
+  private static void applyStageBinariesMavenRepository( Project project )
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    project.tasks.create( TaskNames.STAGE_MAVEN_BINARIES, Sync, { Sync task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = 'Stages published binaries as a maven repository in the build directory.'
+      releaseSpec.publishedProjects.each { p ->
+        p.afterEvaluate { evaluatedProject ->
+          if( p.plugins.hasPlugin( PublishedCodePlugin ) )
+          {
+            task.dependsOn "${ p.path }:uploadStageArchives"
+            task.from "${ p.buildDir }/stage/archives"
+          }
+        }
+      }
+      task.into project.file( "$project.buildDir/stage/maven-binaries" )
+    } as Action<Sync> )
+  }
+
+  private static void applyStageLibrariesMavenRepository( Project project )
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    def dependenciesDeclaration = project.rootProject.extensions.getByType DependenciesDeclarationExtension
+    def stageTask = project.tasks.create( TaskNames.STAGE_MAVEN_DEPENDENCIES ) { Task task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = 'Stages dependencies of published binaries as a maven repository in the build directory. (BIG)'
+      def output = project.file "$project.buildDir/stage/dependencies"
+      task.inputs.property 'libraries', dependenciesDeclaration.libraries
+      task.outputs.dir output
+      task.doLast {
+        // Resolve runtime dependencies across all staged projects
+        def libraries = [ ] as Set<Dependency>
+        releaseSpec.publishedProjects.each { p ->
+          libraries += p.configurations.getByName( 'runtime' ).allDependencies
+        }
+        def configuration = project.configurations.detachedConfiguration( libraries as Dependency[] )
+        DependenciesPlugin.applyDependencyResolutionRules configuration, dependenciesDeclaration
+        // Copy Maven POMs
+        def allDependencies = configuration.incoming.resolutionResult.allDependencies as Set<ResolvedDependencyResult>
+        def componentIds = allDependencies.collect { it.selected.id }
+        def result = project.dependencies.createArtifactResolutionQuery()
+                            .forComponents( componentIds )
+                            .withArtifacts( MavenModule, MavenPomArtifact )
+                            .execute()
+        result.resolvedComponents.each { ComponentArtifactsResult component ->
+          def id = component.id
+          if( id instanceof ModuleComponentIdentifier )
+          {
+            def artifact = component.getArtifacts( MavenPomArtifact )[ 0 ]
+            if( artifact instanceof ResolvedArtifactResult )
+            {
+              def groupDir = new File( output, id.getGroup().split( "\\." ).join( '/' ) )
+              File moduleDir = new File( groupDir, "${ id.getModule() }/${ id.getVersion() }" )
+              Files.createDirectories moduleDir.toPath()
+              def destination = new File( moduleDir, artifact.getFile().getName() ).toPath()
+              Files.exists( destination ) ?: Files.copy( artifact.getFile().toPath(), destination )
+            }
+          }
+        }
+        // Copy Maven artifacts using the Gradle IDE Model
+        // Include sources if available, otherwise include javadoc if available
+        IdeDependenciesExtractor dependenciesExtractor = new IdeDependenciesExtractor()
+        def ideDependencies = dependenciesExtractor.extractRepoFileDependencies project.dependencies,
+                                                                                [ configuration ], [ ],
+                                                                                true, true
+        ideDependencies.each { IdeExtendedRepoFileDependency ideDependency ->
+          def id = ideDependency.id
+          def groupDir = new File( output, id.group.split( "\\." ).join( '/' ) )
+          File moduleDir = new File( groupDir, "${ id.name }/${ id.version }" )
+          Files.createDirectories moduleDir.toPath()
+          Path destination = new File( moduleDir, ideDependency.file.name ).toPath()
+          Files.exists( destination ) ?: Files.copy( ideDependency.file.toPath(), destination )
+          if( ideDependency.sourceFile )
+          {
+            def sourceDestination = new File( moduleDir, ideDependency.sourceFile.name ).toPath()
+            Files.exists( sourceDestination ) ?: Files.copy( ideDependency.sourceFile.toPath(), sourceDestination )
+          }
+          else if( ideDependency.javadocFile )
+          {
+            def javadocDestination = new File( moduleDir, ideDependency.javadocFile.name ).toPath()
+            Files.exists( javadocDestination ) ?: Files.copy( ideDependency.javadocFile.toPath(), javadocDestination )
+          }
+        }
+      }
+    }
+    project.tasks.create( TaskNames.ZIP_DEPENDENCIES_DIST, Zip ) { Zip task ->
+      task.group = TaskGroups.DISTRIBUTION
+      task.description = 'Assemble .zip dependencies distribution (BIG)'
+      task.baseName = 'apache-polygene-java'
+      task.classifier = 'dependencies'
+      task.from stageTask
+      task.into "apache-polygene-java-$project.version-dependencies"
+    }
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/extensions/ExtensionPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/extensions/ExtensionPlugin.groovy
new file mode 100644
index 0000000..735952c
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/extensions/ExtensionPlugin.groovy
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.gradle.structure.extensions
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.code.PublishedCodePlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+@CompileStatic
+class ExtensionPlugin implements Plugin<Project>
+{
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply PublishedCodePlugin
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/internals/InternalDockerPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/internals/InternalDockerPlugin.groovy
new file mode 100644
index 0000000..d9dfa93
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/internals/InternalDockerPlugin.groovy
@@ -0,0 +1,151 @@
+/*
+ *  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.polygene.gradle.structure.internals
+
+import com.bmuschko.gradle.docker.DockerExtension
+import com.bmuschko.gradle.docker.DockerRemoteApiPlugin
+import com.bmuschko.gradle.docker.tasks.DockerVersion
+import com.bmuschko.gradle.docker.tasks.image.DockerBuildImage
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.BasePlugin
+import org.apache.polygene.gradle.code.CodePlugin
+import org.apache.polygene.gradle.code.PublishNaming
+import org.apache.polygene.gradle.dependencies.DependenciesDeclarationExtension
+import org.apache.polygene.gradle.dependencies.DependenciesPlugin
+import org.apache.tools.ant.filters.ReplaceTokens
+import org.gradle.api.Action
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.file.CopySpec
+import org.gradle.api.logging.LogLevel
+
+@CompileStatic
+class InternalDockerPlugin implements Plugin<Project>
+{
+  static class TaskNames
+  {
+    static final String CHECK_DOCKER_CONNECTIVITY = 'checkDockerConnectivity'
+  }
+
+  private final String dockerMachineName = System.getenv( 'DOCKER_MACHINE_NAME' )
+  private final String dockerHost = System.getenv( 'DOCKER_HOST' )
+  private final String dockerCertPath = System.getenv( 'DOCKER_CERT_PATH' )
+
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply BasePlugin
+    project.plugins.apply DependenciesPlugin
+    applyDockerPlugin( project )
+    applyDockerSwitch( project )
+    applyDockerBuildImage( project )
+  }
+
+  private void applyDockerPlugin( Project project )
+  {
+    project.plugins.apply DockerRemoteApiPlugin
+    def dockerExtension = project.extensions.getByType DockerExtension
+    // TLS support
+    if( dockerCertPath )
+    {
+      dockerExtension.certPath = new File( dockerCertPath )
+    }
+  }
+
+  private void applyDockerSwitch( Project project )
+  {
+    project.tasks.create( TaskNames.CHECK_DOCKER_CONNECTIVITY, DockerVersion, { DockerVersion task ->
+      task.onError = { ex ->
+        // Disable Docker for this build
+        project.rootProject.extensions.extraProperties.set( CodePlugin.DOCKER_DISABLED_EXTRA_PROPERTY, true )
+        if( project.hasProperty( 'skipDocker' ) )
+        {
+            project.logger.lifecycle 'skipDocker property is set, all Docker tasks will be SKIPPED'
+        }
+        else if( project.logger.isEnabled( LogLevel.INFO ) )
+        {
+          project.logger.info 'Unable to connect to Docker, all Docker tasks will be SKIPPED', ex
+        }
+        else
+        {
+          project.logger.lifecycle "Unable to connect to Docker, all Docker tasks will be SKIPPED\n  ${ ( ( Exception ) ex ).message }"
+        }
+      }
+      task.onComplete = {
+        if( project.hasProperty( 'skipDocker' ) )
+        {
+          // Disable Docker for this build
+          project.rootProject.extensions.extraProperties.set( CodePlugin.DOCKER_DISABLED_EXTRA_PROPERTY, true )
+          project.logger.lifecycle 'skipDocker property is set, all Docker tasks will be SKIPPED'
+        }
+      }
+    } as Action<DockerVersion> )
+  }
+
+  private void applyDockerBuildImage( Project project )
+  {
+    def classesTask = project.tasks.getByName 'classes'
+    def dockers = project.file( 'src/main/docker' )
+    def dependencies = project.rootProject.extensions.getByType( DependenciesDeclarationExtension )
+    dockers.eachDir { File dockerDir ->
+      def dockerName = dockerDir.name
+      def buildDockerfileTaskName = "build${ dockerName.capitalize() }Dockerfile"
+      def buildImageTaskName = "build${ dockerName.capitalize() }DockerImage"
+      def tmpDir = project.file "${ project.buildDir }/tmp/docker/${ dockerName }"
+      tmpDir.mkdirs()
+      def buildDockerfileTask = project.tasks.create( buildDockerfileTaskName ) { Task task ->
+        task.description = "Build $dockerName Dockerfile"
+        task.inputs.property 'dockerImagesVersions', dependencies.dockerImagesVersions
+        task.inputs.dir dockerDir
+        task.outputs.dir tmpDir
+        // Filter Dockerfile for image versions from dependencies declaration
+        task.doFirst {
+          project.copy { CopySpec spec ->
+            spec.from( dockerDir ) { CopySpec unfiltered ->
+              unfiltered.exclude 'Dockerfile'
+            }
+            spec.from( dockerDir ) { CopySpec filtered ->
+              filtered.include 'Dockerfile'
+              filtered.filter ReplaceTokens, tokens: dependencies.dockerImagesVersions
+            }
+            spec.into tmpDir
+          }
+        }
+      }
+      def buildImageTask = project.tasks.create( buildImageTaskName, DockerBuildImage, { DockerBuildImage task ->
+        task.description = "Build $dockerName Docker image"
+        task.inputDir = tmpDir
+        task.dockerFile = new File( tmpDir, 'Dockerfile' )
+        task.tag = "org.apache.polygene:${ PublishNaming.publishedNameFor ":internals:docker-$dockerName" }"
+      } as Action<DockerBuildImage> )
+      [ buildDockerfileTask, buildImageTask ].each { Task task ->
+        task.group = 'docker'
+        task.dependsOn TaskNames.CHECK_DOCKER_CONNECTIVITY
+        task.onlyIf { !project.rootProject.findProperty( CodePlugin.DOCKER_DISABLED_EXTRA_PROPERTY ) }
+        task.inputs.property 'dockerMachineName', dockerMachineName
+        task.inputs.property 'dockerHostEnv', dockerHost
+        task.inputs.property 'dockerCertPath', dockerCertPath
+      }
+      buildImageTask.dependsOn buildDockerfileTask
+      // Ensure that all Docker images are built alongside this project
+      // This is a bit of a stretch but works for now
+      classesTask.dependsOn buildImageTask
+    }
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/internals/InternalPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/internals/InternalPlugin.groovy
new file mode 100644
index 0000000..baa8842
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/internals/InternalPlugin.groovy
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.gradle.structure.internals
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.code.CodePlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+@CompileStatic
+class InternalPlugin implements Plugin<Project>
+{
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply CodePlugin
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/libraries/LibraryPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/libraries/LibraryPlugin.groovy
new file mode 100644
index 0000000..7603e8b
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/libraries/LibraryPlugin.groovy
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.gradle.structure.libraries
+
+import org.apache.polygene.gradle.code.PublishedCodePlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+class LibraryPlugin implements Plugin<Project>
+{
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply PublishedCodePlugin
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/AsciidocBuildInfoPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/AsciidocBuildInfoPlugin.groovy
new file mode 100644
index 0000000..3a9216c
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/AsciidocBuildInfoPlugin.groovy
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.gradle.structure.manual
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.TaskGroups
+import org.apache.polygene.gradle.code.PublishNaming
+import org.gradle.api.Project
+import org.gradle.api.Plugin
+
+@CompileStatic
+class AsciidocBuildInfoPlugin implements Plugin<Project>
+{
+  final static String TASK_NAME = 'makeAsciidocBuildInfo'
+
+  void apply( Project project )
+  {
+    def buildInfoDir = new File( project.buildDir, "docs/buildinfo" );
+
+    def task = project.tasks.create( TASK_NAME )
+    task.group = TaskGroups.DOCUMENTATION
+    task.description = 'Generates asciidoc artifact snippet'
+    task.inputs.properties.put 'artifactId', PublishNaming.publishedNameFor( project.path )
+    task.doLast {
+      buildInfoDir.mkdirs()
+
+      // GroupID, ArtifactID, Version table in artifact.txt
+      def artifactTableFile = new File( buildInfoDir, "artifact.txt" )
+      def artifactTable = """
+        |.Artifact
+        |[role="artifact", options="header,autowidth"]
+        ||===================================================
+        ||Group ID|Artifact ID|Version
+        ||${ project.group }|${ PublishNaming.publishedNameFor( project.path ) }|${ project.version }
+        ||===================================================
+        """.stripMargin()
+      artifactTableFile.withWriter { out -> out.println( artifactTable ) }
+    }
+
+    // Declare inputs/outputs
+    if( project.getBuildFile() != null && project.getBuildFile().exists() )
+    {
+      task.getInputs().file( project.getBuildFile() )
+    }
+    task.getOutputs().file( buildInfoDir )
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/DocumentationTask.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/DocumentationTask.groovy
new file mode 100644
index 0000000..7a58a14
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/DocumentationTask.groovy
@@ -0,0 +1,321 @@
+/*
+ *  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.polygene.gradle.structure.manual
+
+import groovy.io.FileType
+import groovy.transform.CompileStatic
+import groovy.transform.TypeCheckingMode
+import java.security.MessageDigest
+import org.apache.polygene.gradle.structure.release.ReleaseSpecExtension
+import org.apache.polygene.gradle.tasks.ExecLogged
+import org.gradle.api.Action
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.CopySpec
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.InputDirectory
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.Internal
+import org.gradle.api.tasks.OutputDirectory
+import org.gradle.api.tasks.TaskAction
+import org.gradle.process.ExecSpec
+
+// TODO: try to use dependencies for FOP and execute within the same JVM.
+// TODO: move the bulk of resources into this plugin, instead of sitting in the project.
+@CompileStatic
+class DocumentationTask extends DefaultTask
+{
+  @Input
+  String docName
+  @Input
+  String docType
+
+  @InputDirectory
+  File getCommonResourcesDir()
+  { project.file( 'src/resources' ) }
+
+  @InputDirectory
+  File getConfigDir()
+  { project.file( 'src/conf' ) }
+
+  @InputDirectory
+  File getDocsDir()
+  { project.file( 'src/docs' ) }
+
+  @InputDirectory
+  File getSrcMainDir()
+  { project.file( 'src/main' ) }
+
+  @InputDirectory
+  File getXslDir()
+  { project.file( 'src/xsl' ) }
+
+  @InputDirectory
+  File getBuildSrcDir()
+  { project.rootProject.file( 'buildSrc/src' ) }
+
+  @InputFiles
+  getSubProjectsDocsDirs()
+  { project.rootProject.subprojects.collect { p -> p.file( 'src/docs' ) } }
+
+  @InputFiles
+  def getSubProjectsTestDirs()
+  { project.rootProject.subprojects.collect { p -> p.file( 'src/test' ) } }
+
+  @OutputDirectory
+  File getOutputDir()
+  { project.file( "${ project.buildDir }/docs/${ docName }/" ) }
+
+  @Internal
+  File getTempAsciidocDir()
+  { project.file( "${ project.buildDir }/tmp-asciidoc" ) }
+
+  @Internal
+  File getTempDir()
+  { project.file( "${ project.buildDir }/tmp/docs/${ docName }" ) }
+
+  @TaskAction
+  void generate()
+  {
+    installAsciidocFilters()
+
+    [ outputDir, tempAsciidocDir, tempDir ].each { it.deleteDir() }
+    [ outputDir, tempAsciidocDir, tempDir ].each { it.mkdirs() }
+
+    copySubProjectsDocsResources()
+    generateAsciidocAccordingToReleaseSpecification()
+    generateXDoc()
+    generateChunkedHtml()
+    // generateSingleHtml()
+    // generatePdf()
+  }
+
+  void installAsciidocFilters()
+  {
+    def digester = MessageDigest.getInstance( 'SHA' )
+    def filtersDir = project.rootProject.file( 'buildSrc/src/asciidoc/filters' )
+    def userHome = new File( System.getProperty( 'user.home' ) )
+    def dotAsciidocFiltersDir = new File( userHome, '.asciidoc/filters' )
+    def installSnippets = false
+    filtersDir.eachFileRecurse( FileType.FILES ) { originalFile ->
+      def targetFile = new File( dotAsciidocFiltersDir,
+                                 ( originalFile.toURI() as String ) - ( filtersDir.toURI() as String ) )
+      if( !targetFile.exists() )
+      {
+        installSnippets = true
+      }
+      else
+      {
+        def originalDigest = digester.digest( originalFile.bytes )
+        def targetDigest = digester.digest( targetFile.bytes )
+        if( originalDigest != targetDigest )
+        {
+          installSnippets = true
+        }
+      }
+    }
+    if( installSnippets )
+    {
+      dotAsciidocFiltersDir.mkdirs()
+      project.rootProject.copy { CopySpec spec ->
+        spec.from filtersDir
+        spec.into dotAsciidocFiltersDir
+      }
+      dotAsciidocFiltersDir.eachFileRecurse( FileType.FILES ) { file ->
+        if( file.name.endsWith( '.py' ) )
+        {
+          chmod( file, '755' )
+        }
+      }
+      println "Polygene Asciidoc Filters Installed!"
+    }
+  }
+
+  @CompileStatic( TypeCheckingMode.SKIP )
+  void chmod( File file, String permissions )
+  {
+    ant.chmod( file: file.absolutePath, perm: permissions )
+  }
+
+  def void copySubProjectsDocsResources()
+  {
+    project.rootProject.subprojects.each { p ->
+      p.copy { CopySpec spec ->
+        spec.from p.file( 'src/docs/resources' )
+        spec.into outputDir
+        spec.include '**'
+      }
+    }
+  }
+
+  void generateAsciidocAccordingToReleaseSpecification()
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    project.copy { CopySpec spec ->
+      spec.from docsDir
+      spec.into tempAsciidocDir
+      spec.include '**'
+    }
+    if( releaseSpec.releaseVersion )
+    {
+      def licenseFile = new File( tempAsciidocDir, 'userguide/libraries.txt' )
+      def extensionsFile = new File( tempAsciidocDir, 'userguide/extensions.txt' )
+      def toolsFile = new File( tempAsciidocDir, 'userguide/tools.txt' )
+      [ licenseFile, extensionsFile, toolsFile ].each { asciidocFile ->
+        def filteredFileContent = ''
+        asciidocFile.readLines().each { line ->
+          if( line.startsWith( 'include::' ) )
+          {
+            def approved = false
+            releaseSpec.approvedProjects.collect { it.projectDir }.each { approvedProjectDir ->
+              if( line.contains( "${ approvedProjectDir.parentFile.name }/${ approvedProjectDir.name }" ) )
+              {
+                approved = true
+              }
+            }
+            if( approved )
+            {
+              filteredFileContent += "$line\n"
+            }
+          }
+          else
+          {
+            filteredFileContent += "$line\n"
+          }
+        }
+        asciidocFile.text = filteredFileContent
+      }
+    }
+  }
+
+  void generateXDoc()
+  {
+    def outLog = getLogFile( 'adoc-2-docbook', 'stdout' )
+    def errLog = getLogFile( 'adoc-2-docbook', 'stderr' )
+    ExecLogged.execLogged( project, outLog, errLog, { ExecSpec spec ->
+      spec.executable = 'asciidoc'
+      spec.workingDir = project.rootProject.projectDir
+      def commonResourcesPath = relativePath( project.rootDir, commonResourcesDir )
+      def asciidocConfigPath = relativePath( project.rootDir, new File( configDir, 'asciidoc.conf' ) )
+      def docbookConfigPath = relativePath( project.rootDir, new File( configDir, 'docbook45.conf' ) )
+      def linkimagesConfigPath = relativePath( project.rootDir, new File( configDir, 'linkedimages.conf' ) )
+      def xdocOutputPath = relativePath( project.rootDir, new File( tempDir, 'xdoc-temp.xml' ) )
+      def asciidocIndexPath = relativePath( project.rootDir, new File( tempAsciidocDir, "$docName/index.txt" ) )
+      spec.args = [
+        '--verbose',
+        '--attribute', 'revnumber=' + project.version.toString(),
+        '--attribute', 'level1=' + ( docType == 'article' ? 1 : 0 ),
+        '--attribute', 'level2=' + ( docType == 'article' ? 2 : 1 ),
+        '--attribute', 'level3=' + ( docType == 'article' ? 3 : 2 ),
+        '--attribute', 'level4=' + ( docType == 'article' ? 4 : 3 ),
+        '--attribute', 'importdir=' + commonResourcesPath,
+        '--backend', 'docbook',
+        '--attribute', 'docinfo1',
+        '--doctype', docType,
+        '--conf-file=' + asciidocConfigPath,
+        '--conf-file=' + docbookConfigPath,
+        '--conf-file=' + linkimagesConfigPath,
+        '--out-file', xdocOutputPath,
+        asciidocIndexPath
+      ]
+    } as Action<? super ExecSpec> )
+  }
+
+  void generateChunkedHtml()
+  {
+    project.copy { CopySpec spec ->
+      spec.from commonResourcesDir
+      spec.into outputDir
+      spec.include '**'
+    }
+    project.copy { CopySpec spec ->
+      spec.from "$docsDir/$docName/resources"
+      spec.into outputDir
+      spec.include '**'
+    }
+    def outLog = getLogFile( 'docbook-2-chunked-html', 'stdout' )
+    def errLog = getLogFile( 'docbook-2-chunked-html', 'stderr' )
+    ExecLogged.execLogged( project, outLog, errLog, { ExecSpec spec ->
+      def xsltFile = "$docsDir/$docName/xsl/chunked.xsl"
+      def outputPath = relativePath( project.projectDir, outputDir ) + '/'
+      spec.executable = 'xsltproc'
+      spec.args = [
+        '--nonet',
+        '--noout',
+        '--output', outputPath,
+        xsltFile.toString(),
+        "$tempDir/xdoc-temp.xml".toString()
+      ]
+    } as Action<? super ExecSpec> )
+  }
+
+  void generateSingleHtml()
+  {
+    def outLog = getLogFile( 'docbook-2-html', 'stdout' )
+    def errLog = getLogFile( 'docbook-2-html', 'stderr' )
+    ExecLogged.execLogged( project, outLog, errLog, { ExecSpec spec ->
+      // XML_CATALOG_FILES=
+      String xsltFile = "$xslDir/xhtml.xsl"
+      spec.executable = 'xsltproc'
+      spec.args = [
+        '--nonet',
+        '--noout',
+        '--output', "$outputDir/${ docName }.html".toString(),
+        xsltFile.toString(),
+        "$tempDir/xdoc-temp.xml".toString()
+      ]
+    } as Action<? super ExecSpec> )
+  }
+
+  void generatePdf()
+  {
+    // $ xsltproc --nonet ../docbook-xsl/fo.xsl article.xml > article.fo
+    def outLog = getLogFile( 'docbook-2-fo', 'stdout' )
+    def errLog = getLogFile( 'docbook-2-fo', 'stderr' )
+    ExecLogged.execLogged( project, outLog, errLog, { ExecSpec spec ->
+      String xsltFile = "$xslDir/fo.xsl"
+      spec.executable = 'xsltproc'
+      spec.args = [
+        '--nonet',
+        '--output', "$tempDir/${ docName }.fo".toString(),
+        xsltFile,
+        "$tempDir/xdoc-temp.xml".toString()
+      ]
+    } as Action<? super ExecSpec> )
+
+    // $ fop article.fo article.pdf
+    outLog = getLogFile( 'fo-2-pdf', 'stdout' )
+    errLog = getLogFile( 'fo-2-pdf', 'stderr' )
+    ExecLogged.execLogged( project, outLog, errLog, { ExecSpec spec ->
+      spec.executable = 'fop'
+      spec.args = [
+        "$tempDir/${ docName }.fo".toString(),
+        "$outputDir/${ docName }.pdf".toString()
+      ]
+    } as Action<? super ExecSpec> )
+  }
+
+  private File getLogFile( String step, String stream )
+  {
+    return project.file( "${ project.buildDir }/tmp/${ name }/${ step }-${ stream }.log" )
+  }
+
+  private static String relativePath( File root, File target )
+  {
+    new File( root.toURI().relativize( target.toURI() ).toString() ).path
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/ManualPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/ManualPlugin.groovy
new file mode 100644
index 0000000..69dfefe
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/ManualPlugin.groovy
@@ -0,0 +1,99 @@
+/*
+ *  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.polygene.gradle.structure.manual
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.TaskGroups
+import org.apache.polygene.gradle.code.CodePlugin
+import org.apache.polygene.gradle.structure.release.ReleaseSpecExtension
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.language.base.plugins.LifecycleBasePlugin
+
+// TODO Expose project output into configurations
+@CompileStatic
+class ManualPlugin implements Plugin<Project>
+{
+  static class TaskNames
+  {
+    static final String WEBSITE = "website"
+    static final String MANUALS = "manuals"
+  }
+
+  @Override
+  void apply( final Project project )
+  {
+    project.plugins.apply CodePlugin
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    def websiteTask = project.tasks.create( TaskNames.WEBSITE, DocumentationTask ) { DocumentationTask task ->
+      task.group = TaskGroups.DOCUMENTATION
+      task.description = 'Generates documentation website'
+      project.rootProject.allprojects.findResults { Project p ->
+        // TODO Remove project.afterEvaluate
+        p.afterEvaluate {
+          if( p.tasks.findByName( AsciidocBuildInfoPlugin.TASK_NAME ) )
+          {
+            task.dependsOn p.tasks.findByName( AsciidocBuildInfoPlugin.TASK_NAME )
+          }
+        }
+      }
+      task.onlyIf { isAsciidocInstalled( project, releaseSpec ) }
+      task.docName = 'website'
+      task.docType = 'article'
+    }
+    def manualsTask = project.tasks.create( TaskNames.MANUALS ) { Task task ->
+      task.group = TaskGroups.DOCUMENTATION
+      task.description = 'Generates all documentation'
+      task.dependsOn websiteTask
+    }
+    project.tasks.getByName( LifecycleBasePlugin.BUILD_TASK_NAME ).dependsOn manualsTask
+  }
+
+  private static Boolean asciidocInstalled = null
+
+  // Force when building a release version
+  // Skip if skipAsciidocIfAbsent property is set
+  // Skip if asciidoc is not found in PATH when building a development version
+  private static boolean isAsciidocInstalled( Project project, ReleaseSpecExtension releaseSpec )
+  {
+    if( asciidocInstalled == null )
+    {
+      def skipAsciidocIfAbsent = project.findProperty 'skipAsciidocIfAbsent'
+      if( !skipAsciidocIfAbsent && releaseSpec.releaseVersion )
+      {
+        project.logger.info 'Asciidoc tasks forced for building a release version, hope you have Asciidoc installed'
+        asciidocInstalled = true
+      }
+      else
+      {
+        def pathDirs = System.getenv( 'PATH' ).split( File.pathSeparator )
+        def asciidocCandidates = pathDirs.collect( { String path ->
+          new File( path, 'asciidoc' )
+        } ).flatten() as List<File>
+        asciidocInstalled = asciidocCandidates.findAll( { it.isFile() } )
+        if( !asciidocInstalled )
+        {
+          project.logger.lifecycle 'WARNING Asciidoc not found in PATH, manual tasks will skip\n' +
+                                   '        Please install http://www.methods.co.nz/asciidoc/'
+        }
+      }
+    }
+    return asciidocInstalled
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/XsltTask.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/XsltTask.groovy
new file mode 100644
index 0000000..18af2bd
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/manual/XsltTask.groovy
@@ -0,0 +1,100 @@
+/*
+ *  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.polygene.gradle.structure.manual
+
+import groovy.transform.CompileStatic
+import org.gradle.api.file.EmptyFileVisitor
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.SourceTask
+import org.gradle.api.tasks.OutputDirectory
+import org.gradle.api.tasks.InputFile
+import org.gradle.api.tasks.TaskAction
+import org.gradle.api.file.FileVisitDetails
+import javax.xml.transform.TransformerFactory
+import javax.xml.transform.stream.StreamResult
+import javax.xml.transform.stream.StreamSource
+
+/**
+ *  Gradle task for running a set of one or more
+ *  files through an XSLT transform.  A styleSheet
+ *  file must be specified.  The source file(s) are
+ *  configured just like any other source task:
+ *     source <file>
+ *       ...or...
+ *     source <directory>
+ *       ...and then optionally...
+ *     include '*.xml'
+ *     exclude, etc.
+ *
+ *  One of destDir or destFile must be specified, though if
+ *  there are multiple source files then destFile will just
+ *  keep getting rewritten.
+ *
+ *  The extension is stripped from the source files and the
+ *  specified extension is appended (whether it is set or not)
+ *  it defaults to no extension.
+ *
+ *  Example task formatting a check style report:
+ *
+ *  task checkstyleReport(type: XsltTask, dependsOn: check) {
+ *      source project.checkstyleResultsDir
+ *      include '*.xml'
+ *
+ *      destDir = project.checkstyleResultsDir
+ *      extension = 'html'
+ *
+ *      stylesheetFile = file( 'config/checkstyle/checkstyle-noframes.xsl' )
+ * }
+ *
+ *  The above definition requires that the specified XSL file be
+ *  copied in with the other checkstyle configuration files.  (The
+ *  file in the example is part of the checkstyle distribution.)
+ *
+ */
+@CompileStatic
+class XsltTask extends SourceTask
+{
+
+  @OutputDirectory
+  File destDir
+
+  @Input
+  String extension = 'html'
+
+  @InputFile
+  File stylesheetFile
+
+  @TaskAction
+  def transform()
+  {
+    def factory = TransformerFactory.newInstance()
+    def transformer = factory.newTransformer( new StreamSource( stylesheetFile ) );
+
+    getSource().visit( new EmptyFileVisitor() {
+      @Override
+      void visitFile( FileVisitDetails fvd )
+      {
+        // Remove the extension from the file name
+        def name = fvd.file.name.replaceAll( '[.][^\\.]*$', '' )
+        name += '.' + extension
+        def destFile = new File( destDir, name )
+        transformer.transform( new StreamSource( fvd.file ), new StreamResult( destFile ) )
+      }
+    } )
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/CheckReleaseSpecTask.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/CheckReleaseSpecTask.groovy
new file mode 100644
index 0000000..a0e0d6e
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/CheckReleaseSpecTask.groovy
@@ -0,0 +1,75 @@
+/*
+ *  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.polygene.gradle.structure.release
+
+import groovy.transform.CompileStatic
+import org.gradle.api.DefaultTask
+import org.gradle.api.GradleException
+import org.gradle.api.Project
+import org.gradle.api.artifacts.ProjectDependency
+import org.gradle.api.tasks.TaskAction
+
+@CompileStatic
+class CheckReleaseSpecTask extends DefaultTask
+{
+  CheckReleaseSpecTask()
+  {
+    description = 'Ensure that no releasable module depend on module(s) that don\'t fit the release criteria.'
+    dependsOn {
+      project.extensions.getByType( ReleaseSpecExtension ).approvedProjects
+             .collect { each -> each.configurations.getByName( 'runtime' ) }
+    }
+  }
+
+  @TaskAction
+  void check()
+  {
+    Map<Project, Set<ProjectDependency>> notReleasable = [ : ]
+    def approvedProjects = project.extensions.getByType( ReleaseSpecExtension ).approvedProjects
+    approvedProjects.each { approvedProject ->
+      def projectDependencies = approvedProject.configurations.getByName( 'runtime' ).allDependencies.findAll {
+        it instanceof ProjectDependency
+      } as Set<ProjectDependency>
+      projectDependencies.each { dep ->
+        def depNotReleaseApproved = approvedProjects.findAll { rp ->
+          rp.group == dep.dependencyProject.group && rp.name == dep.dependencyProject.name
+        }.isEmpty()
+        if( depNotReleaseApproved )
+        {
+          if( !notReleasable[ approvedProject ] )
+          {
+            notReleasable[ approvedProject ] = [ ] as Set
+          }
+          notReleasable[ approvedProject ] << dep
+        }
+      }
+    }
+    if( !notReleasable.isEmpty() )
+    {
+      def errorMessage = new StringBuilder()
+      errorMessage << "At least one releasable module depends on module(s) that don't fit the release criteria!\n"
+      errorMessage << "\tOffending module -> Non releasable dependencies\n"
+      notReleasable.each { k, v ->
+        def noRlsDeps = v.collect { d -> ':' + d.dependencyProject.group + ':' + d.dependencyProject.name }
+        errorMessage << "\t$k -> ${ noRlsDeps })\n"
+      }
+      errorMessage << "Check the dev-status.xml file content in each modules directory."
+      throw new GradleException( errorMessage.toString() )
+    }
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ModuleReleaseSpec.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ModuleReleaseSpec.groovy
new file mode 100644
index 0000000..fb1665c
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ModuleReleaseSpec.groovy
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.gradle.structure.release;
+
+import org.gradle.api.Project
+
+class ModuleReleaseSpec
+{
+  boolean satisfiedBy( Project project )
+  {
+    def devStatusFile = new File( project.projectDir, "dev-status.xml" )
+    if( !devStatusFile.exists() )
+    {
+      return false
+    }
+    def module = new XmlSlurper().parse( devStatusFile )
+    def codebase = module.status.codebase.text() as String
+    def docs = module.status.documentation.text() as String
+    def tests = module.status.unittests.text() as String
+    return satisfiedBy( codebase, docs, tests )
+  }
+
+  boolean satisfiedBy( String codebase, String docs, String tests )
+  {
+    def satisfied = ( codebase == 'none' && docs == 'complete' )
+    satisfied |= ( codebase == 'early'
+            && ( docs == 'complete' || docs == 'good' )
+            && ( tests == 'complete' || tests == 'good' ) )
+    satisfied |= ( codebase == 'beta'
+            && ( docs == 'complete' || docs == 'good' || docs == 'brief' )
+            && ( tests == 'complete' || tests == 'good' || tests == 'some' ) )
+    satisfied |= ( codebase == 'stable' )
+    satisfied |= ( codebase == 'mature' )
+    return satisfied
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ReleaseApprovedProjectsTask.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ReleaseApprovedProjectsTask.groovy
new file mode 100644
index 0000000..e95e405
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ReleaseApprovedProjectsTask.groovy
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.gradle.structure.release
+
+import groovy.json.JsonBuilder
+import groovy.transform.CompileStatic
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.FileCollection
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.TaskAction
+
+/**
+ * Write paths of release approved projects to a JSON file.
+ *
+ * This task sole purpose is proper up-do-date behaviour when changing {@literal dev-status.xml} files.
+ */
+@CompileStatic
+class ReleaseApprovedProjectsTask extends DefaultTask
+{
+  ReleaseApprovedProjectsTask()
+  {
+    description = 'Apply release specification to projects in the build'
+  }
+
+  @InputFiles
+  FileCollection getDevStatusFiles()
+  {
+    return project.files( project.allprojects
+                                 .collect( { project -> project.file( 'dev-status.xml' ) } )
+                                 .findAll( { it.exists() } ) )
+  }
+
+  @OutputFile
+  File getJsonApprovedProjects()
+  {
+    return new File( new File( project.buildDir, 'release' ), 'approved-projects.json' )
+  }
+
+  @TaskAction
+  void approveProjects()
+  {
+    def releaseSpec = project.extensions.getByType( ReleaseSpecExtension )
+    jsonApprovedProjects.parentFile.mkdirs()
+    jsonApprovedProjects.text = new JsonBuilder( releaseSpec.approvedProjects.collect( { it.path } ) ).toPrettyString()
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ReleasePlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ReleasePlugin.groovy
new file mode 100644
index 0000000..a0ef741
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ReleasePlugin.groovy
@@ -0,0 +1,277 @@
+/*
+ *  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.polygene.gradle.structure.release
+
+import groovy.transform.CompileStatic
+import org.apache.http.client.methods.CloseableHttpResponse
+import org.apache.http.client.methods.HttpPost
+import org.apache.http.entity.ContentType
+import org.apache.http.entity.mime.MultipartEntityBuilder
+import org.apache.http.impl.client.CloseableHttpClient
+import org.apache.http.impl.client.HttpClients
+import org.apache.polygene.gradle.BasePlugin
+import org.apache.polygene.gradle.TaskGroups
+import org.apache.polygene.gradle.structure.distributions.DistributionsPlugin
+import org.apache.polygene.gradle.structure.manual.ManualPlugin
+import org.apache.polygene.gradle.structure.reports.ReportsPlugin
+import org.gradle.api.GradleException
+import org.gradle.api.InvalidUserDataException
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.execution.TaskExecutionGraph
+import org.gradle.api.file.CopySpec
+import org.gradle.api.tasks.Copy
+import org.gradle.api.tasks.bundling.Zip
+import org.gradle.language.base.plugins.LifecycleBasePlugin
+
+@CompileStatic
+class ReleasePlugin implements Plugin<Project>
+{
+  static class TaskNames
+  {
+    static final String RELEASE_ASF = 'releaseAsf'
+    static final String PUBLISH_ASF_MAVEN = 'publishAsfMavenArtifacts'
+    private static final String PREPARE_ASF_MAVEN = 'prepareAsfMavenBundle'
+    private static final String UPLOAD_ASF_MAVEN = 'uploadAsfMavenBundle'
+    private static final String CLOSE_ASF_MAVEN = 'closeAsfMavenRepository'
+    private static final String CHECK_ASF_MAVEN = 'checkAsfMavenArtifacts'
+    private static final String PROMOTE_ASF_MAVEN = 'promoteAsfMavenRepository'
+    static final String PUBLISH_ASF_DIST = 'publishAsfDistributions'
+    private static final String CHECKOUT_ASF_DIST = 'checkoutAsfDistributions'
+    private static final String COPY_ASF_DIST = 'copyAsfDistributions'
+    private static final String COMMIT_ASF_DIST = 'commitAsfDistributions'
+    static final String PUBLISH_ASF_DOC = 'publishAsfDocumentation'
+    private static final String CHECKOUT_ASF_DOC = 'checkoutAsfDocumentation'
+    private static final String COPY_ASF_DOC = 'copyAsfDocumentation'
+    private static final String COPY_ASF_DOC_LATEST = 'copyAsfDocumentationAsLatest'
+    private static final String COMMIT_ASF_DOC = 'commitAsfDocumentation'
+  }
+
+  @Override
+  void apply( final Project project )
+  {
+    project.plugins.apply BasePlugin
+    project.gradle.taskGraph.whenReady { TaskExecutionGraph taskGraph ->
+      def check = taskGraph.allTasks.any { task -> task.name.contains( 'Asf' ) }
+      if( check )
+      {
+        checkAsfPreconditions( project )
+      }
+    }
+    applyAsfRelease project
+  }
+
+  static void checkAsfPreconditions( Project project )
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    if( releaseSpec.developmentVersion )
+    {
+      throw new InvalidUserDataException(
+        'Development version is unreleasable, please clean and retry with a -Dversion=' )
+    }
+    def polygeneWeb = new File( project.rootProject.projectDir.parentFile, 'polygene-website' )
+    if( !polygeneWeb.exists() )
+    {
+      throw new InvalidUserDataException(
+        'To perform ASF releases you need to clone the `polygene-website` repository under ../polygene-website' )
+    }
+    def polygeneDist = new File( project.rootProject.projectDir.parentFile, 'polygene-dist' )
+    if( !polygeneDist.exists() )
+    {
+      throw new InvalidUserDataException(
+        'To perform ASF releases you need to checkout the SVN dist directory under ../polygene-dist' )
+    }
+    // TODO Check Nexus credentials availability
+    // TODO Check svn command line availability
+  }
+
+  static void applyAsfRelease( Project project )
+  {
+    Task releaseTask = project.tasks.create( TaskNames.RELEASE_ASF ) { Task task ->
+      task.group = TaskGroups.RELEASE
+      task.description = 'Rolls out an Apache Software Foundation release.'
+    }
+    def subTasks = [
+      applyPublishAsfMavenArtifacts( project ),
+      applyPublishAsfDistributions( project ),
+      applyPublishAsfDocumentation( project )
+    ]
+    // Two upload strategies for now
+    if( project.findProperty( 'useMavenBundle' ) )
+    {
+      // Use maven artifact bundle
+      releaseTask.dependsOn subTasks
+    }
+    else
+    {
+      // Use :**:uploadArchives for now
+      // TODO Remove this once the bundle strategy is done
+      def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+      releaseSpec.publishedProjects.each { p ->
+        releaseTask.dependsOn "${ p.path }:uploadArchives"
+      }
+      releaseTask.dependsOn subTasks.drop( 1 )
+    }
+  }
+
+  static Task applyPublishAsfMavenArtifacts( Project project )
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    def distributions = project.rootProject.project ':distributions'
+    def prepare = project.tasks.create( TaskNames.PREPARE_ASF_MAVEN, Zip ) { Zip task ->
+      // TODO Consume distributions through configurations
+      task.dependsOn "${ distributions.path }:${ DistributionsPlugin.TaskNames.STAGE_MAVEN_BINARIES }"
+      task.from "${ distributions.buildDir }/stage/maven-binaries"
+      task.into '.'
+      task.destinationDir = project.file( "$project.buildDir/asf/maven" )
+      task.baseName = "apache-polygene-${ project.version }-maven-artifacts"
+      task.exclude '**/maven-metadata*.*'
+    }
+    def upload = project.tasks.create( TaskNames.UPLOAD_ASF_MAVEN ) { Task task ->
+      task.dependsOn prepare
+      // ASF Nexus instance is a Nexus Pro so has the Unpack Plugin that allow uploading
+      // artifacts "en masse" as a ZIP file
+      // TODO Ensure that we have the 'Unpack' privilege in ASF Nexus
+      // Looks like we can upload 'Artifact Bundles' using Nexus UI
+      task.doLast {
+        def uploadUrl = releaseSpec.releaseVersion ?
+                        'https://repository.apache.org/service/local/staging/deploy/maven2' :
+                        'https://repository.apache.org/content/repositories/snapshots'
+        CloseableHttpClient httpClient = HttpClients.createDefault()
+        try
+        {
+          // TODO Add Nexus Authentication
+          HttpPost post = new HttpPost( "$uploadUrl/content-compressed" )
+          MultipartEntityBuilder builder = MultipartEntityBuilder.create();
+          builder.addBinaryBody( 'fieldname',
+                                 prepare.archivePath,
+                                 ContentType.APPLICATION_OCTET_STREAM,
+                                 prepare.archivePath.getName() )
+          post.setEntity( builder.build() )
+          CloseableHttpResponse response = httpClient.execute( post )
+          if( response.statusLine.statusCode != 200 )
+          {
+            throw new GradleException( "Unable to upload maven artifacts to ASF Nexus, got ${ response.statusLine }" )
+          }
+        }
+        finally
+        {
+          httpClient.close()
+        }
+      }
+    }
+    def close = project.tasks.create( TaskNames.CLOSE_ASF_MAVEN ) { Task task ->
+      task.mustRunAfter upload
+      // TODO Close Nexus repository
+      task.enabled = false
+    }
+    def check = project.tasks.create( TaskNames.CHECK_ASF_MAVEN ) { Task task ->
+      task.mustRunAfter close
+      // TODO Run tests against binaries from Nexus staged repository
+      task.enabled = false
+    }
+    def promote = project.tasks.create( TaskNames.PROMOTE_ASF_MAVEN ) { Task task ->
+      task.mustRunAfter check
+      // TODO Promote Nexus repository
+      task.enabled = false
+    }
+    def publish = project.tasks.create( TaskNames.PUBLISH_ASF_MAVEN ) { Task task ->
+      task.group = TaskGroups.RELEASE
+      task.description = 'Publishes maven artifacts to ASF Nexus.'
+      task.dependsOn upload, close, check, promote
+    }
+    return publish
+  }
+
+  static Task applyPublishAsfDistributions( Project project )
+  {
+    def distributions = project.rootProject.project ':distributions'
+    def checkout = project.tasks.create( TaskNames.CHECKOUT_ASF_DIST ) { Task task ->
+      // TODO SVN checkout ASF distribution directory
+      task.enabled = false
+    }
+    def copy = project.tasks.create( TaskNames.COPY_ASF_DIST, Copy ) { Copy task ->
+      task.mustRunAfter checkout
+      // TODO Consume distributions through configurations
+      task.dependsOn "${ distributions.path }:${ LifecycleBasePlugin.ASSEMBLE_TASK_NAME }"
+      task.from new File( distributions.buildDir, 'distributions' )
+      task.into new File( project.rootProject.projectDir.parentFile, 'polygene-dist/dev/polygene' )
+    }
+    def commit = project.tasks.create( TaskNames.COMMIT_ASF_DIST ) { Task task ->
+      task.mustRunAfter copy
+      // TODO SVN commit ASF distribution directory
+      task.enabled = false
+    }
+    def publish = project.tasks.create( TaskNames.PUBLISH_ASF_DIST ) { Task task ->
+      task.group = TaskGroups.RELEASE
+      task.description = 'Publishes distributions to ASF SVN.'
+      task.dependsOn checkout, copy, commit
+    }
+    // TODO SVN Upload DISTRIBUTIONS using svn command line so credentials are handled outside of the build
+    return publish
+  }
+
+  static Task applyPublishAsfDocumentation( Project project )
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    def manual = project.rootProject.project ':manual'
+    def reports = project.rootProject.project ':reports'
+    def checkout = project.tasks.create( TaskNames.CHECKOUT_ASF_DOC ) { Task task ->
+      // TODO SVN checkout ASF distribution directory
+      task.enabled = false
+    }
+    def copy = project.tasks.create( TaskNames.COPY_ASF_DOC, Copy ) { Copy task ->
+      task.mustRunAfter checkout
+      // TODO Consume documentation and reports through configurations
+      task.dependsOn "${ manual.path }:${ ManualPlugin.TaskNames.WEBSITE }"
+      task.dependsOn "${ reports.path }:${ ReportsPlugin.TaskNames.JAVADOCS }"
+      def webRoot = new File( project.rootProject.projectDir.parentFile, 'polygene-website' )
+      def dirName = releaseSpec.releaseVersion ? project.version : 'develop'
+      task.destinationDir = webRoot
+      task.from( new File( manual.buildDir, 'docs/website' ) ) { CopySpec spec ->
+        spec.into "content/java/$dirName"
+      }
+      task.from( new File( reports.buildDir, 'docs/javadocs' ) ) { CopySpec spec ->
+        spec.into "content/java/$dirName/javadocs"
+      }
+    }
+    project.tasks.create( TaskNames.COPY_ASF_DOC_LATEST, Copy ) { Copy task ->
+      def webRoot = new File( project.rootProject.projectDir.parentFile, 'polygene-website' )
+      task.from new File( webRoot, "content/java/$project.version" )
+      task.into new File( webRoot, "content/java/latest" )
+      task.doFirst {
+        if( !releaseSpec.releaseVersion )
+        {
+          throw new InvalidUserDataException( 'Development version cannot be `latest`.' )
+        }
+      }
+    }
+    def commit = project.tasks.create( TaskNames.COMMIT_ASF_DOC ) { Task task ->
+      task.mustRunAfter copy
+      // TODO SVN commit ASF documentation directory
+      task.enabled = false
+    }
+    def publish = project.tasks.create( TaskNames.PUBLISH_ASF_DOC ) { Task task ->
+      task.group = TaskGroups.RELEASE
+      task.description = 'Publishes documentation to ASF HTTP.'
+      task.dependsOn checkout, copy, commit
+    }
+    return publish
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ReleaseSpecExtension.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ReleaseSpecExtension.groovy
new file mode 100644
index 0000000..5051400
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ReleaseSpecExtension.groovy
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.gradle.structure.release
+
+import groovy.transform.CompileStatic
+import org.gradle.api.Project
+
+/**
+ * Provide release approved projects.
+ *
+ * There's no up-to-date checking on Gradle extensions.
+ * Depend on {@link ReleaseApprovedProjectsTask} to get a good up-to-date behavior.
+ */
+@CompileStatic
+class ReleaseSpecExtension
+{
+  static final String NAME = 'releaseSpec'
+
+  private final Project project
+
+  final Set<Project> approvedProjects
+  final Set<Project> unapprovedProjects
+  final Set<Project> publishedProjects
+
+  ReleaseSpecExtension( Project project )
+  {
+    this.project = project
+    def spec = new ModuleReleaseSpec()
+    def candidateProjects = project.allprojects.findAll { p -> p.file( 'dev-status.xml' ).exists() }
+    approvedProjects = candidateProjects.findAll { p -> spec.satisfiedBy p }
+    unapprovedProjects = candidateProjects.minus approvedProjects
+    publishedProjects = releaseVersion ? approvedProjects : candidateProjects
+  }
+
+  boolean isDevelopmentVersion()
+  {
+    return project.version == '0'
+  }
+
+  boolean isSnapshotVersion()
+  {
+    return project.version.toString().contains( 'SNAPSHOT' )
+  }
+
+  boolean isReleaseVersion()
+  {
+    return !snapshotVersion && !developmentVersion
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ReleaseSpecPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ReleaseSpecPlugin.groovy
new file mode 100644
index 0000000..fd2d35a
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ReleaseSpecPlugin.groovy
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.gradle.structure.release
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.TaskGroups
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.Task
+
+@CompileStatic
+class ReleaseSpecPlugin implements Plugin<Project>
+{
+  static class TaskNames
+  {
+    static final String RELEASE_APPROVED_PROJECTS = 'releaseSpecApprovedProjects'
+    static final String REPORT_RELEASE_SPEC = 'reportReleaseSpec'
+    static final String CHECK_RELEASE_SPEC = 'checkReleaseSpec'
+  }
+
+  @Override
+  void apply( final Project project )
+  {
+    applyReleaseSpecExtension project
+    if( project == project.rootProject )
+    {
+      configureReleaseSpecTasks project
+    }
+  }
+
+  private static void applyReleaseSpecExtension( Project project )
+  {
+    project.extensions.create( ReleaseSpecExtension.NAME, ReleaseSpecExtension, project.rootProject )
+  }
+
+  private static void configureReleaseSpecTasks( Project project )
+  {
+    project.tasks.create( TaskNames.RELEASE_APPROVED_PROJECTS, ReleaseApprovedProjectsTask ) { Task task ->
+      task.group = TaskGroups.RELEASE
+    }
+    project.tasks.create( TaskNames.REPORT_RELEASE_SPEC, ReleaseSpecReportTask ) { Task task ->
+      task.group = TaskGroups.RELEASE
+    }
+    project.tasks.create( TaskNames.CHECK_RELEASE_SPEC, CheckReleaseSpecTask ) { Task task ->
+      task.group = TaskGroups.RELEASE_VERIFICATION
+    }
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ReleaseSpecReportTask.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ReleaseSpecReportTask.groovy
new file mode 100644
index 0000000..3ecd8f5
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/release/ReleaseSpecReportTask.groovy
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.gradle.structure.release
+
+import groovy.transform.CompileStatic
+import org.gradle.api.DefaultTask
+import org.gradle.api.tasks.TaskAction
+
+@CompileStatic
+class ReleaseSpecReportTask extends DefaultTask
+{
+  ReleaseSpecReportTask()
+  {
+    description = 'Report module(s) that do or don\'t fit the release criteria.'
+    dependsOn {
+      project.extensions.getByType( ReleaseSpecExtension ).approvedProjects
+             .collect { each -> each.configurations.getByName( 'runtime' ) }
+    }
+  }
+
+  @TaskAction
+  void report()
+  {
+    def releaseSpec = project.extensions.getByType( ReleaseSpecExtension )
+    println 'Approved Projects'
+    releaseSpec.approvedProjects.each { println "\t${ it.path }" }
+    println 'NOT Approved Projects'
+    releaseSpec.unapprovedProjects.each { println "\t${ it.path }" }
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/reports/AggregatedJacocoReportTask.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/reports/AggregatedJacocoReportTask.groovy
new file mode 100644
index 0000000..ba1b8f2
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/reports/AggregatedJacocoReportTask.groovy
@@ -0,0 +1,117 @@
+/*
+ *  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.polygene.gradle.structure.reports
+
+import groovy.transform.CompileStatic
+import groovy.transform.TypeCheckingMode
+import org.gradle.api.DefaultTask
+import org.gradle.api.Project
+import org.gradle.api.file.FileCollection
+import org.gradle.api.plugins.JavaPluginConvention
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.OutputDirectory
+import org.gradle.api.tasks.SourceSet
+import org.gradle.api.tasks.TaskAction
+
+@CompileStatic
+class AggregatedJacocoReportTask extends DefaultTask
+{
+  public static final String JACOCO_CONFIGURATION = 'jacoco'
+
+  @InputFiles
+  FileCollection getJacocoExecDataDirectories()
+  {
+    return project.files( project.rootProject.subprojects
+                                 .collect( { Project p -> "${ p.buildDir.absolutePath }/jacoco" } ) )
+  }
+
+  @OutputDirectory
+  File getOutputDirectory()
+  {
+    return project.file( "$project.buildDir/reports/coverage" )
+  }
+
+  @CompileStatic( TypeCheckingMode.SKIP )
+  @TaskAction
+  void report()
+  {
+    def classpath = project.configurations.getByName( JACOCO_CONFIGURATION ).asPath
+
+    def coveredProjects = project.rootProject.subprojects.findAll { p -> new File( p.buildDir, 'jacoco' ).exists() }
+
+    def allExecutionData = coveredProjects.collect { "${ it.buildDir.absolutePath }/jacoco" }
+
+    def sourceSetsOf = { String projectPathPrefix, Set<Project> projects ->
+      projects.findAll { p -> p.path.startsWith( projectPathPrefix ) }
+              .collect { it.convention.getPlugin( JavaPluginConvention ).sourceSets }
+              .flatten() as List<SourceSet>
+    }
+    def sourceDirsOf = { List<SourceSet> sourceSets ->
+      def sourceDirs = sourceSets.collect { it.allSource.srcDirs }.flatten() as List<File>
+      sourceDirs.findAll { it.directory }.collect { it.absolutePath }
+    }
+    def classesDirsOf = { List<SourceSet> sourceSets ->
+      def classesDirs = sourceSets.collect { it.output.classesDir } as List<File>
+      classesDirs.findAll { it.directory }.collect { it.absolutePath }
+    }
+
+    def coreSourceSets = sourceSetsOf( ':core', coveredProjects )
+    def libSourceSets = sourceSetsOf( ':libraries', coveredProjects )
+    def extSourceSets = sourceSetsOf( ':extensions', coveredProjects )
+    def toolsSourceSets = sourceSetsOf( ':tools', coveredProjects )
+    def tutoSourceSets = sourceSetsOf( ':tutorials', coveredProjects )
+    def samplesSourceSets = sourceSetsOf( ':samples', coveredProjects )
+
+    project.ant {
+      taskdef name: 'jacocoreport', classname: 'org.jacoco.ant.ReportTask', classpath: classpath
+      mkdir dir: outputDirectory
+      jacocoreport {
+        executiondata { allExecutionData.collect { fileset( dir: it ) { include name: '*.exec' } } }
+        structure( name: 'Apache Polygene™ (Java Edition) SDK' ) {
+          group( name: 'Core' ) {
+            classfiles { classesDirsOf(coreSourceSets).collect { fileset( dir: it ) } }
+            sourcefiles { sourceDirsOf(coreSourceSets).collect { fileset( dir: it ) } }
+          }
+          group( name: 'Libraries' ) {
+            classfiles { classesDirsOf(libSourceSets).collect { fileset( dir: it ) } }
+            sourcefiles { sourceDirsOf(libSourceSets).collect { fileset( dir: it ) } }
+          }
+          group( name: 'Extensions' ) {
+            classfiles { classesDirsOf(extSourceSets).collect { fileset( dir: it ) } }
+            sourcefiles { sourceDirsOf(extSourceSets).collect { fileset( dir: it ) } }
+          }
+          group( name: 'Tools' ) {
+            classfiles { classesDirsOf(toolsSourceSets).collect { fileset( dir: it ) } }
+            sourcefiles { sourceDirsOf(toolsSourceSets).collect { fileset( dir: it ) } }
+          }
+          group( name: 'Tutorials' ) {
+            classfiles { classesDirsOf(tutoSourceSets).collect { fileset( dir: it ) } }
+            sourcefiles { sourceDirsOf(tutoSourceSets).collect { fileset( dir: it ) } }
+          }
+          group( name: 'Samples' ) {
+            classfiles { classesDirsOf(samplesSourceSets).collect { fileset( dir: it ) } }
+            sourcefiles { sourceDirsOf(samplesSourceSets).collect { fileset( dir: it ) } }
+          }
+        }
+        csv destfile: "${ outputDirectory }/jacoco.csv", encoding: 'UTF-8'
+        xml destfile: "${ outputDirectory }/jacoco.xml", encoding: 'UTF-8'
+        html destdir: outputDirectory, encoding: 'UTF-8', locale: 'en', footer: 'Apache Polygene™ (Java Edition) SDK'
+      }
+    }
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/reports/ReportsPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/reports/ReportsPlugin.groovy
new file mode 100644
index 0000000..7b9dd21
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/reports/ReportsPlugin.groovy
@@ -0,0 +1,162 @@
+/*
+ *  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.polygene.gradle.structure.reports
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.BasePlugin
+import org.apache.polygene.gradle.TaskGroups
+import org.apache.polygene.gradle.code.CodePlugin
+import org.apache.polygene.gradle.code.PublishedCodePlugin
+import org.apache.polygene.gradle.dependencies.DependenciesDeclarationExtension
+import org.apache.polygene.gradle.dependencies.DependenciesPlugin
+import org.apache.polygene.gradle.structure.RootPlugin
+import org.apache.polygene.gradle.structure.release.ReleaseSpecExtension
+import org.apache.polygene.gradle.structure.release.ReleaseSpecPlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.plugins.JavaPlugin
+import org.gradle.api.plugins.JavaPluginConvention
+import org.gradle.api.plugins.ReportingBasePlugin
+import org.gradle.api.tasks.javadoc.Javadoc
+import org.gradle.api.tasks.testing.TestReport
+import org.gradle.external.javadoc.StandardJavadocDocletOptions
+import org.gradle.language.base.plugins.LifecycleBasePlugin
+
+// TODO Expose project output into configurations
+@CompileStatic
+class ReportsPlugin implements Plugin<Project>
+{
+  static class TaskNames
+  {
+    static final String COVERAGE = 'coverage'
+    static final String TEST = 'test'
+    static final String JAVADOCS = 'javadocs'
+  }
+
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply BasePlugin
+    project.plugins.apply org.gradle.api.plugins.BasePlugin
+    project.plugins.apply ReportingBasePlugin
+    project.plugins.apply DependenciesPlugin
+    applyTest project
+    applyCoverage project
+    applyJavadocs project
+    PublishedCodePlugin.configureJavadoc project
+  }
+
+  private static void applyTest( Project project )
+  {
+    def task = project.tasks.create( TaskNames.TEST, TestReport ) { TestReport task ->
+      task.group = TaskGroups.VERIFICATION
+      task.description = 'Generates global test report'
+      task.destinationDir = project.file( "$project.buildDir/reports/tests" )
+      task.reportOn {
+        project.rootProject.subprojects
+               .findAll { p -> p.plugins.hasPlugin CodePlugin }
+               .collect { it.tasks.getByName( 'test' ) }
+      }
+    }
+    project.tasks.getByName( LifecycleBasePlugin.CHECK_TASK_NAME ).dependsOn task
+  }
+
+  private static void applyCoverage( Project project )
+  {
+    def dependencies = project.rootProject.extensions.getByType DependenciesDeclarationExtension
+    project.configurations.create AggregatedJacocoReportTask.JACOCO_CONFIGURATION
+    project.dependencies.add AggregatedJacocoReportTask.JACOCO_CONFIGURATION,
+                             "org.jacoco:org.jacoco.ant:${ dependencies.buildToolsVersions.jacoco }"
+    def task = project.tasks.create( TaskNames.COVERAGE, AggregatedJacocoReportTask )
+      { AggregatedJacocoReportTask task ->
+        task.group = TaskGroups.VERIFICATION
+        task.description = 'Generates global coverage report'
+        task.dependsOn {
+          project.rootProject.subprojects
+                 .findAll { p -> p.plugins.hasPlugin CodePlugin }
+                 .collect( { p -> p.tasks.getByName JavaPlugin.TEST_TASK_NAME } )
+        }
+      }
+    project.tasks.getByName( LifecycleBasePlugin.CHECK_TASK_NAME ).dependsOn task
+  }
+
+  private static void applyJavadocs( Project project )
+  {
+    def releaseSpec = project.extensions.getByType ReleaseSpecExtension
+    def javadocsTask = project.tasks.create( TaskNames.JAVADOCS, Javadoc ) { Javadoc task ->
+      task.onlyIf { !releaseSpec.developmentVersion }
+      task.group = TaskGroups.DOCUMENTATION
+      task.description = 'Builds the whole SDK public Javadoc'
+      task.dependsOn { project.rootProject.tasks.getByName ReleaseSpecPlugin.TaskNames.RELEASE_APPROVED_PROJECTS }
+      task.destinationDir = project.file "$project.buildDir/docs/javadocs"
+      def options = task.options as StandardJavadocDocletOptions
+      options.docFilesSubDirs = true
+      options.encoding = 'UTF-8'
+      options.docEncoding = 'UTF-8'
+      options.charSet = 'UTF-8'
+      options.noTimestamp = true
+      options.overview = "${ project.projectDir }/src/javadoc/overview.html"
+      task.title = "${ RootPlugin.PROJECT_TITLE } ${ project.version }"
+      options.group( [
+        "Core API"      : [ "org.apache.polygene.api",
+                            "org.apache.polygene.api.*" ],
+        "Core Bootstrap": [ "org.apache.polygene.bootstrap",
+                            "org.apache.polygene.bootstrap.*" ],
+        "Core SPI"      : [ "org.apache.polygene.spi",
+                            "org.apache.polygene.spi.*" ],
+        "Libraries"     : [ "org.apache.polygene.library.*" ],
+        "Extensions"    : [ "org.apache.polygene.serialization.*",
+                            "org.apache.polygene.entitystore.*",
+                            "org.apache.polygene.index.*",
+                            "org.apache.polygene.metrics.*",
+                            "org.apache.polygene.cache.*",
+                            "org.apache.polygene.migration",
+                            "org.apache.polygene.migration.*" ],
+        "Tools"         : [ "org.apache.polygene.tools.*",
+                            "org.apache.polygene.envisage",
+                            "org.apache.polygene.envisage.*" ],
+        "Test Support"  : [ "org.apache.polygene.test",
+                            "org.apache.polygene.test.*" ]
+      ] )
+      options.links = [
+        'http://docs.oracle.com/javase/8/docs/api/',
+        'https://stleary.github.io/JSON-java/',
+        'http://junit.org/junit4/javadoc/latest/'
+      ]
+    }
+    project.tasks.getByName( LifecycleBasePlugin.CHECK_TASK_NAME ).dependsOn javadocsTask
+    project.tasks.withType( Javadoc ) { Javadoc task ->
+      def apiSources = releaseSpec.publishedProjects.findAll { approved ->
+        ( approved.path.startsWith( ':core' ) && !approved.path.startsWith( ':core:runtime' ) ) ||
+        approved.path.startsWith( ':libraries' ) ||
+        approved.path.startsWith( ':extensions' ) ||
+        approved.path.startsWith( ':tools' )
+      }
+      apiSources.each { Project apiProject ->
+        apiProject.afterEvaluate { Project evaluatedApiProject ->
+          def javaConvention = evaluatedApiProject.convention.findPlugin( JavaPluginConvention )
+          if(javaConvention) {
+              def mainSourceSet = javaConvention.sourceSets.getByName( 'main' )
+              task.source mainSourceSet.allJava
+              task.classpath += mainSourceSet.compileClasspath
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/samples/SamplePlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/samples/SamplePlugin.groovy
new file mode 100644
index 0000000..6970463
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/samples/SamplePlugin.groovy
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.gradle.structure.samples
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.code.CodePlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+@CompileStatic
+class SamplePlugin implements Plugin<Project>
+{
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply CodePlugin
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/tests/PerformanceTestsPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/tests/PerformanceTestsPlugin.groovy
new file mode 100644
index 0000000..3b10b2f
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/tests/PerformanceTestsPlugin.groovy
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.gradle.structure.tests
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.TaskGroups
+import org.gradle.api.Action
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.plugins.JavaPluginConvention
+import org.gradle.api.tasks.bundling.Jar
+import org.gradle.api.tasks.testing.Test
+import org.gradle.language.base.plugins.LifecycleBasePlugin
+
+// TODO Add profiling tasks (jfr or honest? flamegraphs?)
+// TODO Add simple regression assertions, how? testing against a previous version?
+@CompileStatic
+class PerformanceTestsPlugin implements Plugin<Project>
+{
+  static class TaskNames
+  {
+    static final String PERFORMANCE_TEST = 'performanceTest'
+    static final String PERFORMANCE_PROFILE = 'performanceProfile'
+    static final String PERFORMANCE_CHECK = 'performanceCheck'
+  }
+
+  @Override
+  void apply( final Project project )
+  {
+    def sourceSets = project.convention.getPlugin( JavaPluginConvention ).sourceSets
+    sourceSets.create 'perf'
+    project.dependencies.add 'perfImplementation', sourceSets.getByName( 'main' ).output
+    project.dependencies.add 'perfImplementation', sourceSets.getByName( 'test' ).output
+    project.dependencies.add 'perfImplementation', project.configurations.getByName( 'testImplementation' )
+    project.dependencies.add 'perfRuntimeOnly', project.configurations.getByName( 'testRuntimeOnly' )
+    project.tasks.getByName( LifecycleBasePlugin.CHECK_TASK_NAME ).dependsOn 'compilePerfJava'
+    project.tasks.create( TaskNames.PERFORMANCE_TEST, Test, { Test task ->
+      task.group = TaskGroups.PERFORMANCE
+      task.description = 'Runs performance tests.'
+      task.maxParallelForks = 1
+      task.forkEvery = 1L
+      task.testClassesDir = sourceSets.getByName( 'perf' ).output.classesDir
+      task.classpath = sourceSets.getByName( 'perf' ).runtimeClasspath
+      task.systemProperty 'jar.path', ( project.tasks.getByName( 'jar' ) as Jar ).archivePath
+    } as Action<Test> )
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/tests/TestPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/tests/TestPlugin.groovy
new file mode 100644
index 0000000..5f91dfe
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/tests/TestPlugin.groovy
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.gradle.structure.tests
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.code.CodePlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+@CompileStatic
+class TestPlugin implements Plugin<Project>
+{
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply CodePlugin
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/tools/NpmToolPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/tools/NpmToolPlugin.groovy
new file mode 100644
index 0000000..48c4f19
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/tools/NpmToolPlugin.groovy
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.gradle.structure.tools
+
+import com.moowork.gradle.node.NodeExtension
+import com.moowork.gradle.node.NodePlugin
+import com.moowork.gradle.node.npm.NpmTask
+import org.apache.polygene.gradle.BasePlugin
+import org.apache.polygene.gradle.dependencies.DependenciesDeclarationExtension
+import org.apache.polygene.gradle.dependencies.DependenciesPlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+class NpmToolPlugin implements Plugin<Project>
+{
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply BasePlugin
+    project.plugins.apply DependenciesPlugin
+    project.plugins.apply NodePlugin
+    def dependencies = project.rootProject.extensions.getByType( DependenciesDeclarationExtension )
+    def node = project.extensions.getByType NodeExtension
+    node.download = true
+    node.version = dependencies.nodeVersions.node
+    node.npmVersion = dependencies.nodeVersions.npm
+    project.tasks.withType( NpmTask ) { NpmTask task ->
+      task.group = 'node'
+      task.workingDir = project.projectDir
+    }
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/tools/ToolPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/tools/ToolPlugin.groovy
new file mode 100644
index 0000000..a57a129
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/tools/ToolPlugin.groovy
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.gradle.structure.tools
+
+import org.apache.polygene.gradle.code.PublishedCodePlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+class ToolPlugin implements Plugin<Project>
+{
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply PublishedCodePlugin
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/tutorials/TutorialPlugin.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/tutorials/TutorialPlugin.groovy
new file mode 100644
index 0000000..a831fd8
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/structure/tutorials/TutorialPlugin.groovy
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.gradle.structure.tutorials
+
+import groovy.transform.CompileStatic
+import org.apache.polygene.gradle.code.CodePlugin
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+@CompileStatic
+class TutorialPlugin implements Plugin<Project>
+{
+  @Override
+  void apply( Project project )
+  {
+    project.plugins.apply CodePlugin
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/tasks/ExecLogged.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/tasks/ExecLogged.groovy
new file mode 100644
index 0000000..b3ba57d
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/tasks/ExecLogged.groovy
@@ -0,0 +1,139 @@
+/*
+ *  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.polygene.gradle.tasks
+
+import groovy.transform.CompileStatic
+import java.nio.file.Files
+import java.util.function.BiConsumer
+import org.gradle.api.Action
+import org.gradle.api.GradleException
+import org.gradle.api.Project
+import org.gradle.api.tasks.AbstractExecTask
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.TaskAction
+import org.gradle.internal.logging.ConsoleRenderer
+import org.gradle.process.ExecSpec
+
+/**
+ * Execute command and log standard output and error to files.
+ *
+ * See the {@literal stdoutFile} and {@literal stderrFile} properties.
+ */
+@CompileStatic
+class ExecLogged extends AbstractExecTask<ExecLogged>
+{
+  @OutputFile
+  File stdoutFile = project.file "$project.buildDir/log/${ getName() }/${ getName() }-stdout.log"
+
+  @OutputFile
+  File stderrFile = project.file "$project.buildDir/log/${ getName() }/${ getName() }-stderr.log"
+
+  ExecLogged()
+  {
+    super( ExecLogged.class )
+  }
+
+  @TaskAction
+  protected void exec()
+  {
+    doExecLogged stdoutFile, stderrFile, { OutputStream outStream, OutputStream errStream ->
+      standardOutput = outStream
+      errorOutput = errStream
+      super.exec()
+    }
+  }
+
+  /**
+   * Execute command and log standard output and error to files.
+   *
+   * @param project Project reference
+   * @param stdoutFile Standard output log file
+   * @param stderrFile Standard error log file
+   * @param specAction Execution specification
+   */
+  static void execLogged( Project project, File stdoutFile, File stderrFile, Action<? super ExecSpec> specAction )
+  {
+    doExecLogged stdoutFile, stderrFile, { OutputStream outStream, OutputStream errStream ->
+      project.exec { ExecSpec spec ->
+        spec.standardOutput = outStream
+        spec.errorOutput = errStream
+        specAction.execute spec
+      }
+    }
+  }
+
+  private static void doExecLogged( File stdoutFile, File stderrFile,
+                                    BiConsumer<OutputStream, OutputStream> exec )
+  {
+    [ stdoutFile, stderrFile ].each { Files.createDirectories( it.parentFile.toPath() ) }
+    def outStream, errStream
+    if( stdoutFile.absolutePath == stderrFile.absolutePath )
+    {
+      outStream = stdoutFile.newOutputStream()
+      errStream = outStream
+    }
+    else
+    {
+      outStream = stdoutFile.newOutputStream()
+      errStream = stderrFile.newOutputStream()
+    }
+    try
+    {
+      exec.accept( outStream, errStream )
+    }
+    catch( Exception ex )
+    {
+      throw new GradleException( errorMessage( ex, stdoutFile, stderrFile ), ex )
+    }
+    finally
+    {
+      close outStream, errStream
+    }
+  }
+
+  private static void close( Closeable... closeables )
+    throws IOException
+  {
+    def errors = [ ] as List<IOException>
+    closeables.each { Closeable closeable ->
+      try
+      {
+        closeable.close()
+      }
+      catch( IOException ex )
+      {
+        errors.add( ex )
+      }
+    }
+    if( !errors.empty )
+    {
+      def ex = new IOException( 'Failed to close some stream(s)' )
+      errors.each { ex.addSuppressed it }
+      throw ex
+    }
+  }
+
+  private static String errorMessage( Exception ex, File stdoutFile, File stderrFile )
+  {
+    // TODO Remove use of Gradle internals
+    def consoleRenderer = new ConsoleRenderer()
+    return "${ ex.message }\n" +
+           "\tSTDOUT ${ consoleRenderer.asClickableFileUrl( stdoutFile ) }\n" +
+           "\tSTDERR ${ consoleRenderer.asClickableFileUrl( stderrFile ) }"
+  }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/util/Environment.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/util/Environment.groovy
new file mode 100644
index 0000000..1362821
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/util/Environment.groovy
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.gradle.util
+
+class Environment
+{
+  static boolean isExecutableInPath( String executable )
+  {
+    def pathDirs = System.getenv( 'PATH' ).split( File.pathSeparator )
+    def flattened = pathDirs.collect( { String pathDir -> new File( pathDir, 'executable' ) } ).flatten() as List<File>
+    return flattened.find( { File pathDir -> pathDir.isFile() } ) != null
+  }
+
+  private Environment() {}
+}
diff --git a/buildSrc/src/main/groovy/org/apache/polygene/gradle/util/Licensing.groovy b/buildSrc/src/main/groovy/org/apache/polygene/gradle/util/Licensing.groovy
new file mode 100644
index 0000000..319ea20
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/polygene/gradle/util/Licensing.groovy
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.gradle.util
+
+class Licensing
+{
+  static String withLicenseHeader( String base, String flavour )
+  {
+    def header
+    switch( flavour )
+    {
+      case 'java': case 'groovy': case 'js':
+        header = licenseHeader_wrap( base, '/*', ' * ', ' */' ); break
+      case 'xml': case 'html':
+        header = licenseHeader_wrap( base, '<!--', '  ', '-->' ); break
+      case 'txt': case 'shell': case 'python': case 'ruby':
+        header = licenseHeader_wrap( base, null, '# ', null ); break
+      case 'adoc': case 'asciidoc':
+        header = licenseHeader_wrap( base, null, '// ', null ); break
+      default:
+        header = base
+    }
+    header
+  }
+
+  private static String licenseHeader_wrap( String base, String top, String left, String bottom )
+  {
+    ( top ? "$top\n" : '' ) +
+    base.readLines().collect { "${ left }${ it }" }.join( '\n' ) + '\n' +
+    ( bottom ? "$bottom\n" : '' )
+  }
+
+  private Licensing() {}
+}
diff --git a/buildSrc/src/main/groovy/org/qi4j/gradle/plugin/Documentation.groovy b/buildSrc/src/main/groovy/org/qi4j/gradle/plugin/Documentation.groovy
deleted file mode 100644
index ad8ca04..0000000
--- a/buildSrc/src/main/groovy/org/qi4j/gradle/plugin/Documentation.groovy
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (c) 2011, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.gradle.plugin;
-
-
-import org.gradle.api.DefaultTask
-import org.gradle.api.tasks.TaskAction
-import org.gradle.api.tasks.Input
-import org.gradle.api.tasks.InputDirectory
-import org.gradle.api.tasks.InputFile
-import org.gradle.api.tasks.InputFiles
-import org.gradle.api.tasks.OutputDirectory
-
-// TODO: try to use dependencies for FOP and execute within the same JVM.
-// TODO: move the bulk of resources into this plugin, instead of sitting in the project.
-class Documentation extends DefaultTask
-{
-  @Input def String docName
-  @Input def String docType
-  void setDocName( String docName ) { this.docName = docName }
-  void setDocType( String docType ) { this.docType = docType }
-
-  @InputDirectory def File getCommonResourcesDir() { project.file( 'src/resources' ) }
-  @InputDirectory def File getConfigDir() { project.file( 'src/conf' ) }
-  @InputDirectory def File getDocsDir() { project.file( 'src/docs') }
-  @InputDirectory def File getSrcMainDir() { project.file( 'src/main') }
-  @InputDirectory def File getXslDir() { project.file( 'src/xsl') }
-  @InputDirectory def File getBuildSrcDir() { project.rootProject.file( 'buildSrc/src' ) }
-
-  @InputFiles def getSubProjectsDocsDirs() { project.rootProject.subprojects.collect { p -> p.file( 'src/docs' ) } }
-  @InputFiles def getSubProjectsTestDirs() { project.rootProject.subprojects.collect { p -> p.file( 'src/test' ) } }
-
-  @OutputDirectory def File getOutputDir() { project.file( "${project.buildDir}/docs/${docName}/" ) }
-
-  def File getTempAsciidocDir() { project.file( "${project.buildDir}/tmp-asciidoc" ) }
-  def File getTempDir() { project.file( "${project.buildDir}/tmp/docs/${docName}") }
-
-  @TaskAction
-  def void generate()
-  {
-    installAsciidocFilters()
-
-    [ outputDir, tempAsciidocDir, tempDir ]*.deleteDir()
-    [ outputDir, tempAsciidocDir, tempDir ]*.mkdirs()
-
-    copySubProjectsDocsResources()
-    generateAsciidocAccordingToReleaseSpecification()
-    generateXDoc()
-    generateChunkedHtml()
-    // generateSingleHtml()
-    // generatePdf()
-  }
-
-  def void installAsciidocFilters()
-  {
-    def userHome = new File( System.getProperty( 'user.home' ) )
-    def snippetDir = new File( userHome, '.asciidoc/filters/snippet' ).absoluteFile
-    if( !snippetDir.exists() )
-    {
-      println "Installing [snippet] into $snippetDir"
-      snippetDir.mkdirs()
-      project.copy {
-        from "${project.rootDir}/buildSrc/src/bin"
-        into snippetDir
-        include 'snippet.*'
-      }
-      ant.chmod( dir: snippetDir, perm: '755', includes: 'snippet.py' )
-    }
-
-    def devstatusDir = new File( userHome, '.asciidoc/filters/devstatus' ).absoluteFile
-    if( !devstatusDir.exists() )
-    {
-      println "Installing [devstatus] into $devstatusDir"
-      snippetDir.mkdirs()
-      project.copy {
-        from "${project.rootDir}/buildSrc/src/bin"
-        into devstatusDir
-        include 'devstatus.*'
-      }
-      ant.chmod( dir: devstatusDir, perm: '755', includes: 'devstatus.py' )
-    }
-  }
-
-  def void copySubProjectsDocsResources()
-  {
-    project.rootProject.subprojects.each { p ->
-      p.copy {
-        from p.file( 'src/docs/resources' )
-        into outputDir
-        include '**'
-      }
-    }
-  }
-
-  def void generateAsciidocAccordingToReleaseSpecification()
-  {
-    project.copy {
-      from docsDir
-      into tempAsciidocDir
-      include '**'
-    }
-    if( project.version != '0' && !project.version.contains( 'SNAPSHOT' ) ) {
-      def licenseFile = new File( tempAsciidocDir, 'userguide/libraries.txt' )
-      def extensionsFile = new File( tempAsciidocDir, 'userguide/extensions.txt' )
-      def toolsFile = new File( tempAsciidocDir, 'userguide/tools.txt' )
-      [ licenseFile, extensionsFile, toolsFile ].each { asciidocFile ->
-        def filteredFileContent = ''
-        asciidocFile.readLines().each { line ->
-          if( line.startsWith( 'include::' ) ) {
-            def approved = false
-            project.rootProject.releaseApprovedProjects.collect{it.projectDir}.each { approvedProjectDir ->
-              if( line.contains( "${approvedProjectDir.parentFile.name}/${approvedProjectDir.name}" ) ) {
-                approved = true
-              }
-            }
-            if( approved ) {
-              filteredFileContent += "$line\n"
-            }
-          } else {
-            filteredFileContent += "$line\n"
-          }
-        }
-        asciidocFile.text = filteredFileContent
-      }
-    }
-  }
-
-  def void generateXDoc()
-  {
-    project.exec {
-      executable = 'asciidoc'
-      workingDir = '..'
-      def commonResourcesPath = relativePath( project.rootDir, commonResourcesDir )
-      def asciidocConfigPath = relativePath( project.rootDir, new File( configDir, 'asciidoc.conf' ) )
-      def docbookConfigPath = relativePath( project.rootDir, new File( configDir, 'docbook45.conf' ) )
-      def linkimagesConfigPath = relativePath( project.rootDir, new File( configDir, 'linkedimages.conf' ) )
-      def xdocOutputPath =  relativePath( project.rootDir, new File( tempDir, 'xdoc-temp.xml' ) )
-      def asciidocIndexPath = relativePath( project.rootDir, new File( tempAsciidocDir, "$docName/index.txt" ) )
-      args = [
-              '--attribute', 'revnumber=' + project.version,
-              '--attribute', 'level1=' + (docType.equals('article') ? 1 : 0),
-              '--attribute', 'level2=' + (docType.equals('article') ? 2 : 1),
-              '--attribute', 'level3=' + (docType.equals('article') ? 3 : 2),
-              '--attribute', 'level4=' + (docType.equals('article') ? 4 : 3),
-              '--attribute', 'importdir=' + commonResourcesPath,
-              '--backend', 'docbook',
-              '--attribute', 'docinfo1',
-              '--doctype', docType,
-              '--conf-file=' + asciidocConfigPath,
-              '--conf-file=' + docbookConfigPath,
-              '--conf-file=' + linkimagesConfigPath,
-              '--out-file', xdocOutputPath,
-              asciidocIndexPath
-      ]
-    }
-  }
-
-  def void generateChunkedHtml()
-  {
-    project.copy {
-      from commonResourcesDir
-      into outputDir
-      include '**'
-    }
-    project.copy {
-      from "$docsDir/$docName/resources"
-      into outputDir
-      include '**'
-    }
-
-    project.exec {
-      def xsltFile = "$docsDir/$docName/xsl/chunked.xsl"
-      def outputPath = relativePath( project.projectDir, outputDir ) + '/'
-      executable = 'xsltproc'
-      args = [
-              '--nonet',
-              '--noout',
-              '--output', outputPath,
-              xsltFile,
-              "$tempDir/xdoc-temp.xml"
-      ]
-    }
-  }
-
-  def void generateSingleHtml()
-  {
-    project.exec {
-      // XML_CATALOG_FILES=
-      String xsltFile = "$xslDir/xhtml.xsl"
-      executable = 'xsltproc'
-      args = [
-              '--nonet',
-              '--noout',
-              '--output', "$outputDir/${docName}.html",
-              xsltFile,
-              "$tempDir/xdoc-temp.xml"
-      ]
-    }
-  }
-
-  def void generatePdf()
-  {
-    // $ xsltproc --nonet ../docbook-xsl/fo.xsl article.xml > article.fo
-    // $ fop article.fo article.pdf
-    project.exec {
-      String xsltFile = "$xslDir/fo.xsl"
-      executable = 'xsltproc'
-      args = [
-        '--nonet',
-        '--output', "$tempDir/${docName}.fo",
-        xsltFile,
-        "$tempDir/xdoc-temp.xml"
-      ]
-    }
-    project.exec {
-      executable = 'fop'
-      args = [
-        "$tempDir/${docName}.fo",
-        "$outputDir/${docName}.pdf"
-      ]
-    }
-  }
-
-  def String relativePath( File root, File target )
-  {
-    new File( root.toURI().relativize( target.toURI() ).toString() ).path
-  }
-}
diff --git a/buildSrc/src/main/groovy/org/qi4j/gradle/plugin/ModuleReleaseSpecification.groovy b/buildSrc/src/main/groovy/org/qi4j/gradle/plugin/ModuleReleaseSpecification.groovy
deleted file mode 100644
index 1a3e180..0000000
--- a/buildSrc/src/main/groovy/org/qi4j/gradle/plugin/ModuleReleaseSpecification.groovy
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2011, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.gradle.plugin;
-
-import org.gradle.api.Project
-
-class ModuleReleaseSpecification
-{
-  def boolean satisfiedBy( Project project )
-  {
-    def devStatusFile = new File( project.projectDir, "dev-status.xml" )
-    if( !devStatusFile.exists() )
-    {
-      return false
-    }
-    def module = new XmlSlurper().parse( devStatusFile )
-    def codebase = module.status.codebase.text()
-    def docs = module.status.documentation.text()
-    def tests = module.status.unittests.text()
-    def satisfied = ( codebase == 'none' && docs == 'complete' && tests != 'complete' )
-    satisfied |= ( codebase == 'early' && ( docs == 'complete' || docs == 'good') && (tests == 'complete' || tests == 'good' ) )
-    satisfied |= ( codebase == 'beta' && (docs == 'complete' || docs == 'good' || docs == 'brief') && (tests == 'complete' || tests == 'good' || tests == 'some') )
-    satisfied |= ( codebase == 'stable' )
-    satisfied |= ( codebase == 'mature' )
-    println "$project.name($satisfied) -> $codebase, $docs, $tests"
-    return satisfied
-  }
-}
\ No newline at end of file
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-core.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-core.properties
new file mode 100644
index 0000000..d6a8da2
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-core.properties
@@ -0,0 +1,18 @@
+#
+#  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.
+#
+implementation-class=org.apache.polygene.gradle.structure.core.CorePlugin
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-dependencies-declaration.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-dependencies-declaration.properties
new file mode 100644
index 0000000..eb710e6
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-dependencies-declaration.properties
@@ -0,0 +1,18 @@
+#
+#  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.
+#
+implementation-class=org.apache.polygene.gradle.dependencies.DependenciesDeclarationPlugin
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-distributions.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-distributions.properties
new file mode 100644
index 0000000..143746f
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-distributions.properties
@@ -0,0 +1,18 @@
+#
+#  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.
+#
+implementation-class=org.apache.polygene.gradle.structure.distributions.DistributionsPlugin
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-extension.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-extension.properties
new file mode 100644
index 0000000..449ac1a
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-extension.properties
@@ -0,0 +1,18 @@
+#
+#  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.
+#
+implementation-class=org.apache.polygene.gradle.structure.extensions.ExtensionPlugin
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-internal-docker.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-internal-docker.properties
new file mode 100644
index 0000000..60290a5
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-internal-docker.properties
@@ -0,0 +1,18 @@
+#
+#  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.
+#
+implementation-class=org.apache.polygene.gradle.structure.internals.InternalDockerPlugin
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-internal.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-internal.properties
new file mode 100644
index 0000000..2749ce9
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-internal.properties
@@ -0,0 +1,18 @@
+#
+#  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.
+#
+implementation-class=org.apache.polygene.gradle.structure.internals.InternalPlugin
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-library.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-library.properties
new file mode 100644
index 0000000..da861fc
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-library.properties
@@ -0,0 +1,18 @@
+#
+#  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.
+#
+implementation-class=org.apache.polygene.gradle.structure.libraries.LibraryPlugin
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-manual.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-manual.properties
new file mode 100644
index 0000000..7e53bce
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-manual.properties
@@ -0,0 +1,18 @@
+#
+#  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.
+#
+implementation-class=org.apache.polygene.gradle.structure.manual.ManualPlugin
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-release.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-release.properties
new file mode 100644
index 0000000..a3db27b
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-release.properties
@@ -0,0 +1,18 @@
+#
+#  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.
+#
+implementation-class=org.apache.polygene.gradle.structure.release.ReleasePlugin
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-reports.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-reports.properties
new file mode 100644
index 0000000..a6371c9
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-reports.properties
@@ -0,0 +1,18 @@
+#
+#  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.
+#
+implementation-class=org.apache.polygene.gradle.structure.reports.ReportsPlugin
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-root.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-root.properties
new file mode 100644
index 0000000..a4fd101
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-root.properties
@@ -0,0 +1,18 @@
+#
+#  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.
+#
+implementation-class=org.apache.polygene.gradle.structure.RootPlugin
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-sample.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-sample.properties
new file mode 100644
index 0000000..ab50e44
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-sample.properties
@@ -0,0 +1,18 @@
+#
+#  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.
+#
+implementation-class=org.apache.polygene.gradle.structure.samples.SamplePlugin
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-settings.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-settings.properties
new file mode 100644
index 0000000..d1714ba
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-settings.properties
@@ -0,0 +1,18 @@
+#
+#  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.
+#
+implementation-class=org.apache.polygene.gradle.structure.SettingsPlugin
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-test.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-test.properties
new file mode 100644
index 0000000..eb5bada
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-test.properties
@@ -0,0 +1,18 @@
+#
+#  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.
+#
+implementation-class=org.apache.polygene.gradle.structure.tests.TestPlugin
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-tool-npm.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-tool-npm.properties
new file mode 100644
index 0000000..497a480
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-tool-npm.properties
@@ -0,0 +1,18 @@
+#
+#  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.
+#
+implementation-class=org.apache.polygene.gradle.structure.tools.NpmToolPlugin
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-tool.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-tool.properties
new file mode 100644
index 0000000..1457955
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-tool.properties
@@ -0,0 +1,18 @@
+#
+#  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.
+#
+implementation-class=org.apache.polygene.gradle.structure.tools.ToolPlugin
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-tutorial.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-tutorial.properties
new file mode 100644
index 0000000..00780ce
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/polygene-tutorial.properties
@@ -0,0 +1,18 @@
+#
+#  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.
+#
+implementation-class=org.apache.polygene.gradle.structure.tutorials.TutorialPlugin
diff --git a/buildSrc/src/test/groovy/org/apache/polygene/gradle/release/ModuleReleaseSpecTest.groovy b/buildSrc/src/test/groovy/org/apache/polygene/gradle/release/ModuleReleaseSpecTest.groovy
new file mode 100644
index 0000000..203d79b
--- /dev/null
+++ b/buildSrc/src/test/groovy/org/apache/polygene/gradle/release/ModuleReleaseSpecTest.groovy
@@ -0,0 +1,119 @@
+/*
+ *  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.polygene.gradle.release
+
+import org.apache.polygene.gradle.structure.release.ModuleReleaseSpec
+import spock.lang.Specification
+import spock.lang.Unroll
+
+class ModuleReleaseSpecTest extends Specification
+{
+  @Unroll
+  def "codebase(#code) docs(#docs) tests(#tests) -> #expected"()
+  {
+    expect:
+    new ModuleReleaseSpec().satisfiedBy( code, docs, tests ) == expected
+
+    where:
+    code     | docs       | tests      | expected
+    'none'   | 'none'     | 'none'     | false
+    'none'   | 'none'     | 'some'     | false
+    'none'   | 'none'     | 'good'     | false
+    'none'   | 'none'     | 'complete' | false
+    'none'   | 'brief'    | 'none'     | false
+    'none'   | 'brief'    | 'some'     | false
+    'none'   | 'brief'    | 'good'     | false
+    'none'   | 'brief'    | 'complete' | false
+    'none'   | 'good'     | 'none'     | false
+    'none'   | 'good'     | 'some'     | false
+    'none'   | 'good'     | 'good'     | false
+    'none'   | 'good'     | 'complete' | false
+    'none'   | 'complete' | 'none'     | true
+    'none'   | 'complete' | 'some'     | true
+    'none'   | 'complete' | 'good'     | true
+    'none'   | 'complete' | 'complete' | true
+
+    'early'  | 'none'     | 'none'     | false
+    'early'  | 'none'     | 'some'     | false
+    'early'  | 'none'     | 'good'     | false
+    'early'  | 'none'     | 'complete' | false
+    'early'  | 'brief'    | 'none'     | false
+    'early'  | 'brief'    | 'some'     | false
+    'early'  | 'brief'    | 'good'     | false
+    'early'  | 'brief'    | 'complete' | false
+    'early'  | 'good'     | 'none'     | false
+    'early'  | 'good'     | 'some'     | false
+    'early'  | 'good'     | 'good'     | true
+    'early'  | 'good'     | 'complete' | true
+    'early'  | 'complete' | 'none'     | false
+    'early'  | 'complete' | 'some'     | false
+    'early'  | 'complete' | 'good'     | true
+    'early'  | 'complete' | 'complete' | true
+
+    'beta'   | 'none'     | 'none'     | false
+    'beta'   | 'none'     | 'some'     | false
+    'beta'   | 'none'     | 'good'     | false
+    'beta'   | 'none'     | 'complete' | false
+    'beta'   | 'brief'    | 'none'     | false
+    'beta'   | 'brief'    | 'some'     | true
+    'beta'   | 'brief'    | 'good'     | true
+    'beta'   | 'brief'    | 'complete' | true
+    'beta'   | 'good'     | 'none'     | false
+    'beta'   | 'good'     | 'some'     | true
+    'beta'   | 'good'     | 'good'     | true
+    'beta'   | 'good'     | 'complete' | true
+    'beta'   | 'complete' | 'none'     | false
+    'beta'   | 'complete' | 'some'     | true
+    'beta'   | 'complete' | 'good'     | true
+    'beta'   | 'complete' | 'complete' | true
+
+    'stable' | 'none'     | 'none'     | true
+    'stable' | 'none'     | 'some'     | true
+    'stable' | 'none'     | 'good'     | true
+    'stable' | 'none'     | 'complete' | true
+    'stable' | 'brief'    | 'none'     | true
+    'stable' | 'brief'    | 'some'     | true
+    'stable' | 'brief'    | 'good'     | true
+    'stable' | 'brief'    | 'complete' | true
+    'stable' | 'good'     | 'none'     | true
+    'stable' | 'good'     | 'some'     | true
+    'stable' | 'good'     | 'good'     | true
+    'stable' | 'good'     | 'complete' | true
+    'stable' | 'complete' | 'none'     | true
+    'stable' | 'complete' | 'some'     | true
+    'stable' | 'complete' | 'good'     | true
+    'stable' | 'complete' | 'complete' | true
+
+    'mature' | 'none'     | 'none'     | true
+    'mature' | 'none'     | 'some'     | true
+    'mature' | 'none'     | 'good'     | true
+    'mature' | 'none'     | 'complete' | true
+    'mature' | 'brief'    | 'none'     | true
+    'mature' | 'brief'    | 'some'     | true
+    'mature' | 'brief'    | 'good'     | true
+    'mature' | 'brief'    | 'complete' | true
+    'mature' | 'good'     | 'none'     | true
+    'mature' | 'good'     | 'some'     | true
+    'mature' | 'good'     | 'good'     | true
+    'mature' | 'good'     | 'complete' | true
+    'mature' | 'complete' | 'none'     | true
+    'mature' | 'complete' | 'some'     | true
+    'mature' | 'complete' | 'good'     | true
+    'mature' | 'complete' | 'complete' | true
+  }
+}
diff --git a/buildSrc/src/test/groovy/org/apache/polygene/gradle/tasks/ExecLoggedTest.groovy b/buildSrc/src/test/groovy/org/apache/polygene/gradle/tasks/ExecLoggedTest.groovy
new file mode 100644
index 0000000..aca2f72
--- /dev/null
+++ b/buildSrc/src/test/groovy/org/apache/polygene/gradle/tasks/ExecLoggedTest.groovy
@@ -0,0 +1,84 @@
+/*
+ *  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.polygene.gradle.tasks
+
+import org.gradle.internal.os.OperatingSystem
+import org.gradle.process.ExecSpec
+import org.gradle.testfixtures.ProjectBuilder
+import org.junit.Rule
+import org.junit.rules.TemporaryFolder
+import spock.lang.IgnoreIf
+import spock.lang.Specification
+
+@IgnoreIf( { OperatingSystem.current().isWindows() } )
+class ExecLoggedTest extends Specification
+{
+  @Rule
+  final TemporaryFolder tmpDir = new TemporaryFolder();
+  File script
+
+  def setup()
+  {
+    script = tmpDir.newFile( 'script.sh' ) << '''
+      #!/bin/sh
+      echo STDOUT
+      echo STDERR 1>&2
+    '''.stripIndent().trim()
+  }
+
+  def "ExecLogged.execLogged()"()
+  {
+    given:
+    def project = ProjectBuilder.builder().build()
+    def out = tmpDir.newFile 'out.txt'
+    def err = tmpDir.newFile 'err.txt'
+
+    when:
+    ExecLogged.execLogged project, out, err, { ExecSpec spec ->
+      spec.workingDir = tmpDir.root
+      spec.commandLine 'sh', script.absolutePath
+    }
+
+    then:
+    out.text == 'STDOUT\n'
+    err.text == 'STDERR\n'
+  }
+
+  def "ExecLogged Task"()
+  {
+    given:
+    def project = ProjectBuilder.builder().build()
+    def out = tmpDir.newFile 'out.txt'
+    def err = tmpDir.newFile 'err.txt'
+    def task = project.tasks.create( 'test', ExecLogged ) { ExecLogged task ->
+      task.workingDir = tmpDir.root
+      task.stdoutFile = out
+      task.stderrFile = err
+      task.commandLine 'sh', script.absolutePath
+    }
+
+    when:
+    // WARN ProjectBuilder is not meant to run tasks, should use TestKit instead
+    // But that's enough for testing ExecLogged and much more faster
+    task.execute()
+
+    then:
+    out.text == 'STDOUT\n'
+    err.text == 'STDERR\n'
+  }
+}
\ No newline at end of file
diff --git a/core/api/build.gradle b/core/api/build.gradle
index ab89613..67c5f96 100644
--- a/core/api/build.gradle
+++ b/core/api/build.gradle
@@ -1,33 +1,30 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-jar { manifest { name = "Apache Zest™ Core API"}}
+apply plugin: 'polygene-core'
+
+jar { manifest { name = "Apache Polygene™ Core API" } }
 
 dependencies {
+  testImplementation polygene.core.testsupport
+  testImplementation polygene.library( 'constraints' )
 
-  compile project( ':org.qi4j.core:org.qi4j.core.io' )
-  compile libraries.jodatime
-
-  testCompile project( ':org.qi4j.core:org.qi4j.core.testsupport' )
-  testCompile project( ':org.qi4j.libraries:org.qi4j.library.constraints' )
-  testCompile project( ':org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson' )
-
-  testRuntime project( ':org.qi4j.core:org.qi4j.core.runtime' )
-
+  testRuntimeOnly polygene.core.runtime
 }
diff --git a/core/api/dev-status.xml b/core/api/dev-status.xml
index a17ec6f..3703137 100644
--- a/core/api/dev-status.xml
+++ b/core/api/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <codebase>stable</codebase>
     <!--none,early,beta,stable,mature-->
diff --git a/core/api/src/docs/api.txt b/core/api/src/docs/api.txt
index e3825b8..fa7188e 100644
--- a/core/api/src/docs/api.txt
+++ b/core/api/src/docs/api.txt
@@ -1,6 +1,4 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
  * Licensed 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
@@ -21,7 +19,7 @@
 source=core/api/dev-status.xml
 --------------
 
-The Zest™ Core API is the primary interface for client application code during the main execution phase, i.e. after the
+The Polygene™ Core API is the primary interface for client application code during the main execution phase, i.e. after the
 application has been activated.
 
 include::../../build/docs/buildinfo/artifact.txt[]
@@ -60,6 +58,10 @@
 
 :leveloffset: {level3}
 
+include::objects.txt[]
+
+:leveloffset: {level3}
+
 // include::dependency-injection.txt[]
 
 :leveloffset: {level3}
@@ -92,6 +94,10 @@
 
 :leveloffset: {level3}
 
+include::serialization.txt[]
+
+:leveloffset: {level3}
+
 // include::indexing.txt[]
 
 :leveloffset: {level3}
diff --git a/core/api/src/docs/application.txt b/core/api/src/docs/application.txt
index bf97b53..19a4649 100644
--- a/core/api/src/docs/application.txt
+++ b/core/api/src/docs/application.txt
@@ -1,6 +1,4 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
  * Licensed 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
@@ -15,13 +13,13 @@
 
 [[core-api-application,Application]]
 = Application =
-There is one and only one Application instance per Zest™ runtime instance. But there is nothing preventing code to
-create additional Zest™ Runtime instances inside the same JVM. However, these runtimes are isolated from each other.
+There is one and only one Application instance per Polygene™ runtime instance. But there is nothing preventing code to
+create additional Polygene™ Runtime instances inside the same JVM. However, these runtimes are isolated from each other.
 
 The main purpose of the Application structure artifact is to keep everything in the same box, and allowing us to
 navigate the Structure. So, from a client code perspective, the Application is of no use, other than being part of
-bring Zest™ to life. Zest™ doesn't start automatically and can be run in most environments, by requiring that the
-bootstrapping of Zest™ is done by client code. We call this the Bootstrap Phase. The code in the custom bootstrapper
+bring Polygene™ to life. Polygene™ doesn't start automatically and can be run in most environments, by requiring that the
+bootstrapping of Polygene™ is done by client code. We call this the Bootstrap Phase. The code in the custom bootstrapper
 will need to access additional Jars from the regular domain code, and we strongly recommend that you make this
 separation in your project as well.
 
@@ -49,7 +47,7 @@
 
     * Create, obtain or lookup Assemblers.
     * Establish the application structures.
-    * Create a Zest™ Runtime instance.
+    * Create a Polygene™ Runtime instance.
     * Create an ApplicationAssemblyFactory.
     * Create an ApplicationFactory.
     * Call ApplicationFactory.newApplication() to create an ApplicationContext.
@@ -65,25 +63,25 @@
 
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/docsupport/ApplicationDocs.java
+source=core/api/src/test/java/org/apache/polygene/api/docsupport/ApplicationDocs.java
 tag=application1
 -----------
 
 = Single Module Layering =
 
 Behind the scenes of the SingletonAssembler a little bit more elaborate bootstrap sequence is happening. The code below
-shows what is the actual required sequence to start up Zest.
+shows what is the actual required sequence to start up Polygene.
 
 [snippet,java]
 -----------
-source=core/bootstrap/src/main/java/org/qi4j/bootstrap/SingletonAssembler.java
+source=core/bootstrap/src/main/java/org/apache/polygene/bootstrap/SingletonAssembler.java
 tag=actual
 -----------
 
 In the above example we are only creating an Application with a single Layer and a single Module in that Layer. This is
 derived from the fact that the factory.newApplicationAssembly() method takes a single Assembler argument.
 
-The Assembler.assemble( ModuleAssembly assembly ) method is called when the Zest™ Runtime needs to populate the
+The Assembler.assemble( ModuleAssembly assembly ) method is called when the Polygene™ Runtime needs to populate the
 ModuleAssembly with its Composites, Objects, Services and other information.
 
 == "Pancake" Layering ==
@@ -94,7 +92,7 @@
 
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/docsupport/ApplicationDocs.java
+source=core/api/src/test/java/org/apache/polygene/api/docsupport/ApplicationDocs.java
 tag=application2
 -----------
 
@@ -109,7 +107,7 @@
 
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/docsupport/ApplicationDocs.java
+source=core/api/src/test/java/org/apache/polygene/api/docsupport/ApplicationDocs.java
 tag=application3
 -----------
 
diff --git a/core/api/src/docs/composition.txt b/core/api/src/docs/composition.txt
index 467fd7a..1a60a3a 100644
--- a/core/api/src/docs/composition.txt
+++ b/core/api/src/docs/composition.txt
@@ -1,6 +1,4 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
  * Licensed 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
@@ -20,14 +18,14 @@
 1. the ability to assemble (compose) objects from smaller pieces, called Fragments.
 2. the construction of applications by assembling Composites into Modules and Modules into Layers.
 
-In Zest, we use the term Assembly for the second case of composition. See separate chapter.
+In Polygene, we use the term Assembly for the second case of composition. See separate chapter.
 
 Composition will allow library authors a new level of flexibility in how functionality is provided to client code. More
 on that later.
 
 == Fragments ==
 
-There are 4 types of Fragments in Zest;
+There are 4 types of Fragments in Polygene;
 
     * <<core-api-mixin>> - The state carrying part of a Composite.
     * <<core-api-constraint>> - Rules for in and out arguments, typically used for validation.
@@ -47,18 +45,18 @@
     * Service - Service is injectable to other composites and java objects. They are not persistable, but if
       referenced from an Entity or Value, a new reference to the Service will be injected when the Entity/Value is
       deserialized. Services are singletons. There are 'hosted' and 'imported' Services. The 'hosted' Service has
-      Configuration and its life cycle controlled by the Zest™ runtime, whereas the 'imported' Services are external
+      Configuration and its life cycle controlled by the Polygene™ runtime, whereas the 'imported' Services are external
       references.
     * Transient - Short-lived composites that are not persistable. Equals/hashCode/toString are forwarded to the
       Mixin Type declaring those methods explicitly.
 
-In versions of Zest™ prior to 2.0 (then Qi4j), composite types had to extend one of these 4 meta types, but in 2.0 and later, the
+In versions of Polygene™ prior to 2.0 (then Qi4j), composite types had to extend one of these 4 meta types, but in 2.0 and later, the
 meta type interface is added dynamically during <<core-bootstrap-assembly>>.
-We can therefor get rid of a lot of additional types, and use Zest-free interfaces directly;
+We can therefor get rid of a lot of additional types, and use Polygene-free interfaces directly;
 
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/docsupport/CompositionDocs.java
+source=core/api/src/test/java/org/apache/polygene/api/docsupport/CompositionDocs.java
 tag=comp1
 -----------
 
@@ -66,7 +64,7 @@
 
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/docsupport/CompositionDocs.java
+source=core/api/src/test/java/org/apache/polygene/api/docsupport/CompositionDocs.java
 tag=comp2
 -----------
 
diff --git a/core/api/src/docs/concern.txt b/core/api/src/docs/concern.txt
index 3d6e36f..bd6f5dd 100644
--- a/core/api/src/docs/concern.txt
+++ b/core/api/src/docs/concern.txt
@@ -1,6 +1,4 @@
 //////////////////////
- * Copyright (c) 2007-2013, Niclas Hedhman. All Rights Reserved.
- *
  * Licensed 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
@@ -28,18 +26,27 @@
 You are allowed to modify both the in-arguments as well as the returned value, including throw exceptions if that is
 suitable, perhaps for post condition checks.
 
+== Applicability ==
+Concerns are applied to composite types in several ways;
+
+    * @Concerns annotation on the Mixin Type.
+    * withConcerns() assembly instruction at bootstrap.
+    * In custom annotations to be applied to either Mixin Types or methods on Mixin Types.
+    * @Concerns annotation directly on a method.
+
+
 == Typed Concern ==
-As mentioned above, concerns that implements the _Mixin Type_ are called *Typed Mixins*. They are more common in the
+As mentioned above, concerns that implements the _Mixin Type_ are called *Typed Concerns*. They are more common in the
 business domain, and can be used for many important things in the domain model, such as checking post conditions (i.e.
 ensure that the state in the entire composite is valid), coordinating services, handling events and much more.
 
 Typed Concerns doesn't have to implement all the methods in the Mixin Type. By making the class abstract and only
-implementing the methods of interest, Zest™ runtime will subclass the concern (otherwise not valid for the JVM), but the
+implementing the methods of interest, Polygene™ runtime will subclass the concern (otherwise not valid for the JVM), but the
 generated methods will never be invoked.
 
 == Generic Concern ==
 In classic AOP, all advice are effectively _generic_. There is no type information in the advice implementation and the
-pointcut can be defined anywhere in the code, and the implementation uses proxy InvocationHandlers. Zest™ supports this
+pointcut can be defined anywhere in the code, and the implementation uses proxy InvocationHandlers. Polygene™ supports this
 construct as well, and we call it *Generic Concern*.
 
 Generic Concerns will be added to all methods that the AppliesToFilter evaluates to true. By default, that is all methods.
@@ -53,6 +60,8 @@
         * an annotation type that must be given on the method.
     * Concerns are added only to composites that declares the Concern, either in
         * the Composite Type, or
+        * on any method of the Composite Type, or
+        * on an annotation that is in turn declared on a Composite Type method
         * during assembly in the withConcerns() method.
 
 This means that we can make the following three samples of concerns. First the generic concern that is added to the methods
@@ -60,21 +69,21 @@
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/concern/DocumentationSupport.java
+source=core/api/src/test/java/org/apache/polygene/api/concern/DocumentationSupport.java
 tag=class
 --------------
 
 We can also use an AppliesToFilter to define which methods should be wrapped with the concern, like this;
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/concern/DocumentationSupport.java
+source=core/api/src/test/java/org/apache/polygene/api/concern/DocumentationSupport.java
 tag=filter
 --------------
 
 And finally an example of how to use annotations to mark indvidual methods for being wrapped by the concern.
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/concern/DocumentationSupport.java
+source=core/api/src/test/java/org/apache/polygene/api/concern/DocumentationSupport.java
 tag=annotation
 --------------
 
diff --git a/core/api/src/docs/configuration.txt b/core/api/src/docs/configuration.txt
index 75ce54d..9f14b62 100644
--- a/core/api/src/docs/configuration.txt
+++ b/core/api/src/docs/configuration.txt
@@ -1,6 +1,4 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
  * Licensed 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
@@ -15,17 +13,24 @@
 
 [[core-api-service-configuration,Service Configuration]]
 = Service Configuration =
-Configuration in Zest™ is for Zest™ <<core-api-service>> only. The Configuration is stored in a visible Entity
+Configuration in Polygene™ is for Polygene™ <<core-api-service>> only. The Configuration is stored in a visible Entity
 Store and is therefor runtime modifiable and not static in properties or XML files as in most other dependency
 injection frameworks.
 
 The Configuration system itself will handle all the details with interfacing with reading and writing the configuration.
 The normal UnitOfWork management is used, but handled internally by the configuration system.
 
-In Zest, Configuration are strongly typed and refactoring-friendly. Configuration is read from the entity store, but if
-it can not be found, then it will try to bootstrap it from a properties file, with the same name as the
+In Polygene, Configuration are strongly typed and refactoring-friendly. Configuration is read from the entity store, but if
+it can not be found, then it will try to bootstrap it from the file system, with the same name as the
 ServiceDescriptor.identifiedBy(), which is set during <<core-bootstrap-assembly>> and defaults to the fully qualified
-classname of the <<core-api-service>> type.
+classname of the <<core-api-service>> type, followed by an extension dependent on the file type.
+
+The following file types for default configuration is supported (listed in read priority order);
+
+1. Java Properties
+2. JSON
+3. YAML
+4. XML
 
 == Defining a Configuration Type ==
 The Configuration type is simply listing the properties that are available. The standard rules on @UseDefaults and
@@ -34,10 +39,27 @@
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/configuration/MailServiceConfiguration.java
+source=core/api/src/test/java/org/apache/polygene/api/configuration/MailServiceConfiguration.java
 tag=configuration
 --------------
 
+== Default Configuration formats ==
+The default configuration read will happen if the Entity Store backing the Configuration system does not contain the
+identifiable configuration. That will trigger the reading attempts of the supported configuration formats. Once the
+configuration is parsed from the file system it is written to the Entity Store, and if the Entity Store is not
+ephemeral, then on the next start, any changes to the configuration will NOT be detected, and will simply be ignored.
+
+To be able to read JSON, YAML and XML configuration, you must configure a Serialization system that supports
+the configuration format that you want to use.
+
+* extension/serialization-javaxjson supports JSON
+* extension/serialization-javaxxml supports XML
+
+== Support for Complex Types ==
+Since the regular Value Serialization platform is used, for JSON, YAML and XML, the configuration can contain
+arbitrary composite types. This is not true for the Java properties file format.
+
+
 == Using a Configuration Type ==
 It is important to remember that Configuration is not static values that are set prior to application start-up and
 therefor applications should not cache the values retrieved forever, but consciously know when the configuration should
@@ -49,7 +71,7 @@
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/configuration/MailService.java
+source=core/api/src/test/java/org/apache/polygene/api/configuration/MailService.java
 tag=read
 --------------
 
@@ -59,7 +81,6 @@
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/configuration/MailService.java
+source=core/api/src/test/java/org/apache/polygene/api/configuration/MailService.java
 tag=write
 --------------
-
diff --git a/core/api/src/docs/constraint.txt b/core/api/src/docs/constraint.txt
index 3fe8869..5ec8c34 100644
--- a/core/api/src/docs/constraint.txt
+++ b/core/api/src/docs/constraint.txt
@@ -1,6 +1,4 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
  * Licensed 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
diff --git a/core/api/src/docs/decoratormixin.txt b/core/api/src/docs/decoratormixin.txt
index 548ae24..6bfae61 100644
--- a/core/api/src/docs/decoratormixin.txt
+++ b/core/api/src/docs/decoratormixin.txt
@@ -1,6 +1,4 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
  * Licensed 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
@@ -32,7 +30,7 @@
 We start with the FooModel interface;
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/FooModel.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/FooModel.java
 tag=plain
 --------------
 
@@ -41,7 +39,7 @@
 Each of the views looks like this;
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/View1.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/View1.java
 tag=decorator
 --------------
 
@@ -53,7 +51,7 @@
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/FooModel.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/FooModel.java
 tag=decorator
 --------------
 
@@ -62,7 +60,7 @@
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/DecoratorMixinTest.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/DecoratorMixinTest.java
 tag=create
 --------------
 
@@ -70,7 +68,7 @@
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/DecoratorMixinTest.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/DecoratorMixinTest.java
 tag=assembly
 --------------
 
@@ -78,6 +76,6 @@
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/DecoratorMixinTest.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/DecoratorMixinTest.java
 tag=test
 --------------
diff --git a/core/api/src/docs/entitycomposite.txt b/core/api/src/docs/entitycomposite.txt
index b445f4b..d614b6f 100644
--- a/core/api/src/docs/entitycomposite.txt
+++ b/core/api/src/docs/entitycomposite.txt
@@ -1,6 +1,4 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
  * Licensed 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
@@ -22,7 +20,7 @@
 creating objects that survives over long periods of time is a difficult one.
 
 Eric Evans points out in his book that Entities is a very definite and distinct concept that needs to be handled
-explicitly. Composite Oriented Programming in general, and Zest™ in particular, takes this point very seriously and
+explicitly. Composite Oriented Programming in general, and Polygene™ in particular, takes this point very seriously and
 makes Entities a central part of the whole system. And likewise, we are convinced that it is not possible to develop
 domain-knowledge-rich applications without a conscious and well-defined strategy on Entities. So, instead of spending
 endless hours trying to get Hibernate mapping to do the right thing, we introduce a Composite meta type called
diff --git a/core/api/src/docs/fragment.txt b/core/api/src/docs/fragment.txt
index 020fd15..3edbf3b 100644
--- a/core/api/src/docs/fragment.txt
+++ b/core/api/src/docs/fragment.txt
@@ -1,6 +1,4 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
  * Licensed 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
diff --git a/core/api/src/docs/metrics.txt b/core/api/src/docs/metrics.txt
index 65f80a7..9b164ab 100644
--- a/core/api/src/docs/metrics.txt
+++ b/core/api/src/docs/metrics.txt
@@ -1,6 +1,4 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
  * Licensed 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
@@ -15,7 +13,7 @@
 
 [[core-api-metrics, Metrics API]]
 = Metrics API =
-The Zest™ platform defines an advanced Metrics SPI to capture runtime metrics of Zest's internals as well be used by
+The Polygene™ platform defines an advanced Metrics SPI to capture runtime metrics of Polygene's internals as well be used by
 application code (via this API) to provide production metrics for operations personnel, ensuring healthy state of
 the applications.
 
@@ -25,12 +23,12 @@
 factory for each component type, to allow for additional components to be created in the future without breaking
 compatibility in the existing implementations.
 
-The MetricsProvider is a standard Zest™ Service and simply acquired via the @Service annotation on a field or
+The MetricsProvider is a standard Polygene™ Service and simply acquired via the @Service annotation on a field or
 constructor argument.
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/metrics/DocumentationSupport.java
+source=core/api/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java
 tag=common
 --------------
 
@@ -41,37 +39,50 @@
 
 A Gauge can represent anything, for instance, thread pool levels, queue sizes and other resource allocations. It is
 useful to have separate gauges for percentage (%) and absolute numbers of the same resource. Operations are mainly
-interested in being alerted when threshold are reach as a percentage, as it is otherwise too many numbers to keep
+interested in being alerted when threshold are reached as a percentage, as it is otherwise too many numbers to keep
 track of.
 
 To create a Gauge, you do something like;
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/metrics/DocumentationSupport.java
+source=core/api/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java
 tag=gauge
 --------------
 
 == Counter ==
+Often we want to track the many counters in a system. This might be "number of HTTP requests" or
+"filesystem access frequency". By creating a _Counter_ metrics, it is simply a matter of calling the _increment_
+or _decrement_ on that metric. This will track both number of counts/steps as well as the rate (per second), and
+many visualization platforms. such as Kibana, Graphite and Grafana, are made to handle this particular metric very well.
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/metrics/DocumentationSupport.java
+source=core/api/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java
 tag=counter
 --------------
 
 == Histogram ==
+Histograms is about computing the running standard deviations and variances. Please see
+http://www.johndcook.com/standard_deviation.html["Accurately computing running variance"] for more detailed information.
+
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/metrics/DocumentationSupport.java
+source=core/api/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java
 tag=histogram
 --------------
 
 == Meter ==
+The _Meter_ is a more advanced _Counter_, which measures mean throughput and one-, five-, and fifteen-minute
+exponentially-weighted moving average throughputs.
+
+Wikipedia has a section
+http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average["Exponential moving average"] in the
+"Moving Average" article.
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/metrics/DocumentationSupport.java
+source=core/api/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java
 tag=meter
 --------------
 
@@ -81,14 +92,60 @@
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/metrics/DocumentationSupport.java
+source=core/api/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java
 tag=timer
 --------------
 
 == HealthCheck ==
+HealthCheck is a metric to report the health of a system or component. The HealthCheck metric will be called upon
+regularly to report its status, which is then forwarded to the monitoring system.
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/metrics/DocumentationSupport.java
+source=core/api/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java
 tag=healthcheck
 --------------
+
+
+= Timing Capture =
+A lot of metrics are around the time it takes to execute something and Polygene supports this at its core.
+
+== Usage ==
+There are currently the following possibilities available;
+
+    * @TimingCapture - capture timing on a single method
+    * TimingCaptureAll - capture timing on all methods of a composite
+
+Before looking at the details of these, we need to point out that there are some pre-conditions for Metrics to be
+working. First of all, you need to install a Metrics Extensions, most likely the
+<<extension-metrics-codahale, Codahale Metrics Extension>>. See your chosen extension for details on how to do that.
+
+Once the Metrics extension is installed, you will also need a suitable backend to gather all the data out of a
+production plant and likewise a good front-end to view this. See your chosen Metrics Extension for this as well.
+
+== TimingCaptureAll ==
+There is a TimingCaptureAllConcern, which when added to a composite will install a _Timer_ for every method call
+in the composite.
+
+== @TimingCapture ==
+The +@TimingCapture+ annotation can be placed on any method of the composite, to indicate that
+a Timer is wanted on that method.
+
+Example;
+
+[snippet,java]
+----
+source=core/api/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java
+tag=capture
+----
+
+== Which method? ==
+It is valid to annotate either the composite interface methods or the mixin implementation methods.
+Any of the method declarations should work. From the testcases we have the following example;
+
+[snippet,java]
+----
+source=core/testsupport/src/main/java/org/apache/polygene/test/metrics/AbstractTimingCaptureTest.java
+tag=complex-capture
+----
+
diff --git a/core/api/src/docs/mixin.txt b/core/api/src/docs/mixin.txt
index 625f894..cd7241c 100644
--- a/core/api/src/docs/mixin.txt
+++ b/core/api/src/docs/mixin.txt
@@ -1,6 +1,4 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
  * Licensed 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
@@ -25,7 +23,7 @@
 Mixin Type can be very simple, like;
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/mixin/BankAccount.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/BankAccount.java
 tag=mixinType
 -----------
 
@@ -68,12 +66,12 @@
 
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/mixin/Something.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/Something.java
 tag=something
 -----------
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/mixin/SomethingMixin.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/SomethingMixin.java
 tag=something
 -----------
 In the above sample, the SomethingMixin will be made part of the Something composite.
@@ -83,17 +81,17 @@
 
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/mixin/Car.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/Car.java
 tag=mixin
 -----------
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/mixin/Startable.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/Startable.java
 tag=mixin
 -----------
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/mixin/Vehicle.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/Vehicle.java
 tag=mixin
 -----------
 
@@ -103,35 +101,35 @@
 
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/mixin/partial/Car.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/partial/Car.java
 tag=partial
 -----------
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/mixin/partial/Vehicle.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/partial/Vehicle.java
 tag=partial
 -----------
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/mixin/partial/SpeedLocation.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/partial/SpeedLocation.java
 tag=partial
 -----------
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/mixin/partial/SpeedMixin.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/partial/SpeedMixin.java
 tag=partial
 -----------
 
-Above the SpeedMixin only implements the accelerate() method, and Zest™ will only map that method to this mixin. The
+Above the SpeedMixin only implements the accelerate() method, and Polygene™ will only map that method to this mixin. The
 other method of the SpeedLocation interface is not satisfied as the example is written and will generate a runtime
 exception.
 
 == Private Mixins ==
-Public mixins expose their methods in the composite interface, and this is not always desirable. Zest™ supports
+Public mixins expose their methods in the composite interface, and this is not always desirable. Polygene™ supports
 _Private Mixins_, which are only visible within the composite itself. That means that other fragments in the composite
 can see/use it, but it is not visible to the clients of the composite.
 
-Private Mixins are handled automatically. When Zest™ detects a +@This+ annotation referring to a type that is not defined
+Private Mixins are handled automatically. When Polygene™ detects a +@This+ annotation referring to a type that is not defined
 in the Composite interface, then that is a Private Mixin. The Mixin implementation class, however, must exist in the
 list of Mixins in the @Mixins annotation. But often, the Private Mixin only list internal Property methods in the Mixin
 Type, which will be satisfied by the standard PropertyMixin and hence always available.
@@ -142,7 +140,7 @@
 
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/mixin/privateMixin/Cargo.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/privateMixin/Cargo.java
 tag=private
 -----------
 
@@ -152,12 +150,12 @@
 
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/mixin/privateMixin/CargoMixin.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/privateMixin/CargoMixin.java
 tag=private
 -----------
 [snippet,java]
 -----------
-source=core/api/src/test/java/org/qi4j/api/mixin/privateMixin/CargoState.java
+source=core/api/src/test/java/org/apache/polygene/api/mixin/privateMixin/CargoState.java
 tag=private
 -----------
 
@@ -172,14 +170,14 @@
 and sometimes Generic Mixin implementations are "last resort".
 
 Experience shows that Generic Mixin implementations are rare, and should only be used in extreme cases. They are
-less frequent than Generic Concern or Generic SideEffect implementations, but inside the Zest™ API are a couple of
+less frequent than Generic Concern or Generic SideEffect implementations, but inside the Polygene™ API are a couple of
 Generic Mixin implementations that are always present to make the life of the developer easier, such as PropertyMixin,
 AssociationMixin, ManyAssociationMixin, NoopMixin. The first 3 are declared on the Composite and EntityComposite
 interfaces and automatically included if needed. They also serve as excellent example of what they can be used for.
 
 [snippet,java]
 -----------
-source=core/api/src/main/java/org/qi4j/api/property/PropertyMixin.java
+source=core/api/src/main/java/org/apache/polygene/api/property/PropertyMixin.java
 tag=actual
 -----------
 
@@ -193,6 +191,6 @@
 
 Typed Mixin implementations are much preferred in general business logic, as they will be first-class citizens of
 the IDE as well, for navigation, find usage, refactoring and many other common tasks. This is one of the main
-advantages of the Zest™ way of doing AOP compared to AspectJ et al, where "weaving" is something bolted onto an
+advantages of the Polygene™ way of doing AOP compared to AspectJ et al, where "weaving" is something bolted onto an
 application's classes via regular expressions and known naming conventions, which can change in an instance by a
 developer being unaware of which PointCuts applies to his code.
diff --git a/core/api/src/docs/module.txt b/core/api/src/docs/module.txt
index 97a7aef..eb191a9 100644
--- a/core/api/src/docs/module.txt
+++ b/core/api/src/docs/module.txt
@@ -1,6 +1,4 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
  * Licensed 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
diff --git a/core/api/src/docs/objects.txt b/core/api/src/docs/objects.txt
new file mode 100644
index 0000000..4b5d546
--- /dev/null
+++ b/core/api/src/docs/objects.txt
@@ -0,0 +1,41 @@
+//////////////////////
+ * Licensed 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.
+//////////////////////
+
+[[core-api-object,Objects]]
+= Objects =
+There are times when Apache Polygene needs to interoperate with other systems, which
+does not have interfaces as their abstraction. Polygene has a notion of
+Objects, which are Polygene-managed classes and can still be injected with
+the Polygene runtime model, such as @Structure and @Service.
+
+
+The characteristics of an Object compared to Composite meta types are;
+
+    * It is a Class, not an interface.
+    * It can have injections applied to it after it has been created.
+    * No Mixins, Concerns or SideEffects.
+    * No Constraints.
+    * Can not have Property instances managed by the Polygene runtime.
+
+== Serialization ==
+Objects can be serialized and deserialized using the Serialization API, if and only
+if they are used as types in Properties in Values or Entities. It depends on the
+Serialization implementation on how the objects are serialized, and
+what the requirements are to allow for deserialization. In general, the Spring
+POJO setter/getter approach will always work, a default constructor is needed, and
+to be safe, make it into +java.io.Serializable+.
+
+== Usage ==
+Objects are instantiated either by calling +ObjectFactory.newObject( type, ... )+ or
+instantiating it in some other fashion and then call +ObjectFactory.injectInto(...)+
+to populate the fields.
diff --git a/core/api/src/docs/reference/ref-api.txt b/core/api/src/docs/reference/ref-api.txt
index eec16ce..b27268d 100644
--- a/core/api/src/docs/reference/ref-api.txt
+++ b/core/api/src/docs/reference/ref-api.txt
@@ -1,23 +1,26 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
+ *  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
  *
- * Licensed 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.
+ *       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.
 //////////////////////
 
 [[ref-core-api, Core API]]
-= Zest™ Core API =
+= Polygene™ Core API =
 
-The Zest™ Core API is main API that Zest™ developers interact with. In fact, if you need to use classes/interfaces
-in the Zest™ Core SPI or Zest™ Core Runtime, then please contact the Zest™ Community and explain your use-case.
+The Polygene™ Core API is main API that Polygene™ developers interact with. In fact, if you need to use classes/interfaces
+in the Polygene™ Core SPI or Polygene™ Core Runtime, then please contact the Polygene™ Community and explain your use-case.
 
 The Core API is strictly layered, with no _spaghetti_ cross packages. The package list is fairly long, and
 we will look at each one in detail further down.
diff --git a/core/api/src/docs/serialization.txt b/core/api/src/docs/serialization.txt
new file mode 100644
index 0000000..07b2459
--- /dev/null
+++ b/core/api/src/docs/serialization.txt
@@ -0,0 +1,102 @@
+//////////////////////
+ * Licensed 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.
+//////////////////////
+
+[[core-api-serialization,Serialization]]
+= Serialization =
+
+State can be serialized and deserialized using the Serialization API which is a Service API implemented
+by SPI and extensions.
+
+TIP: +Serialization extends Serializer, Deserializer+. See the <<javadocs>> for interfaces detail.
+
+The Serialization mechanism apply to the following object types :
+
+    * ValueComposite,
+    * EntityReference & Identity,
+    * Array, Iterable & Stream,
+    * Map,
+    * Plain Values.
+
+Nested Plain Values, EntityReferences, Identities, Arrays, Iterables, Streams, Maps, ValueComposites are supported.
+EntityComposites and EntityReferences are serialized as their identity string.
+
+Plain Values can be one of :
+
+    * String,
+    * Character or char,
+    * Boolean or boolean,
+    * Integer or int,
+    * Long or long,
+    * Short or short,
+    * Byte or byte,
+    * Float or float,
+    * Double or double,
+    * BigInteger,
+    * BigDecimal,
+    * java.time types.
+
+TIP: Serialization behaviour can be tuned with options.
+Every +Serializer+ methods can take a +Serializer.Options+ object that contains flags to change how some
+values are serialized. See the <<javadocs>> for more details.
+
+Values of unknown types and all arrays are considered as +java.io.Serializable+ and by so are (de)serialized to (from)
+base64 encoded bytes using pure Java serialization. If it happens that the value is not Serializable or the input to
+deserialize is invalid, a +SerializationException+ is thrown.
+
+Methods of +Serializer+ allow to specify if the serialized state should contain extra type information about the
+serialized value. Having type information in the serialized payload allows to keep actual ValueComposite types and by so
+circumvent +AmbiguousTypeException+ when deserializing.
+
+Core Runtime provides a default Serialization system based on `javax.json` types.
+
+Let's see how it works in practice.
+
+[snippet,java]
+----
+source=core/api/src/test/java/org/apache/polygene/api/value/DocumentationSupport.java
+tag=default
+----
+
+Reading this first example step by step we ;
+
+    . declare a ValueComposite,
+    . assemble it,
+    . create a new Value instance,
+    . use the +ValueComposite#toString()+ method to get a JSON representation of the Value,
+    . and finally, use the +Module#newValueFromSerializedState()+ method to create a new Value instance from the JSON
+      state.
+
++ValueComposite#toString()+ method leverage Value Serialization and by so provide JSON based representation. The Module
+API allows to create new Value instances from serialized state.
+
+On top of that, Application assemblies can register different implementation of Serialization as Services to
+support more formats, see the <<extensions>> section. Note that the default behaviour described above is overriden if a
+Serialization Service is visible.
+
+Let's see how to use the Serialization Services.
+
+[snippet,java]
+----
+source=core/api/src/test/java/org/apache/polygene/api/value/DocumentationSupport.java
+tag=service
+----
+
+In this second example, we ;
+
+    . declare a ValueComposite,
+    . assemble it,
+    . assemble a Serialization Service backed by the +javax.json+ types,
+    . get the +Serializer+ and +Deserializer+ Services injected,
+    . create a new Value instance,
+    . use the +Serializer#serialize()+ method to get a JSON representation of the Value,
+    . and finally, use the +Deserializer#deserialize()+ method to create a new Value instance from the JSON state.
diff --git a/core/api/src/docs/servicecomposite.txt b/core/api/src/docs/servicecomposite.txt
index 0736d90..26c0d4f 100644
--- a/core/api/src/docs/servicecomposite.txt
+++ b/core/api/src/docs/servicecomposite.txt
@@ -1,6 +1,4 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
  * Licensed 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
@@ -16,7 +14,7 @@
 [[core-api-service,ServiceComposite]]
 = Service Composite =
 Any service added, via the ModuleAssembly.addServices(), ModuleAssembly.services() and ModuleAssembly.importServices()
-methods, will have the ServiceComposite meta type added to it. In Zest, when we speak of _Services_ we mean instances
+methods, will have the ServiceComposite meta type added to it. In Polygene, when we speak of _Services_ we mean instances
 of _ServiceComposite_.
 
 Most programmers are familiar with the term "Service", and after the failure of Object Oriented Programming's promise
@@ -24,8 +22,8 @@
 decoupling and re-use was to make the objects into data containers and deploy services that acted upon those data
 containers. Very much what functions did on structs back in the C and Pascal days.
 
-Zest™ will bring a lot of the behavior back to the Composite itself, but we still need Services for cross-composite
-functionality. The Zest™ Service model is fairly simple, yet powerful and flexible enough to accommodate most
+Polygene™ will bring a lot of the behavior back to the Composite itself, but we still need Services for cross-composite
+functionality. The Polygene™ Service model is fairly simple, yet powerful and flexible enough to accommodate most
 service-oriented patterns and ability to integrate well with external systems whether they are in-JVM or remote,
 such as Spring, OSGi, WS-*, Rest and others.
 
@@ -37,7 +35,7 @@
     * It has an optional Configuration.
 
 
-_Services_ in Zest™ are _singletons_, one instance per definition. That means that there may exist multiple instances
+_Services_ in Polygene™ are _singletons_, one instance per definition. That means that there may exist multiple instances
 of the same service type, but they can not be created on the fly in runtime, but has to be explicitly defined during
 <<core-bootstrap-assembly>>.
 
@@ -46,7 +44,7 @@
 need to declare/call the instantiateOnStartup() method on the _ServiceDescriptor_ during the bootstrap.
 
 == Service Configuration ==
-The configuration for a service is well supported in Zest. See the <<core-api-service-configuration>> chapter for details.
+The configuration for a service is well supported in Polygene. See the <<core-api-service-configuration>> chapter for details.
 
 == Service Activation ==
 Services are activated (injected and instantiated) either on application start-up, or upon first use. This is controlled
@@ -54,7 +52,7 @@
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/service/DocumentationSupport.java
+source=core/api/src/test/java/org/apache/polygene/api/service/DocumentationSupport.java
 tag=instantiateOnStartup
 --------------
 
@@ -69,7 +67,7 @@
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/service/DocumentationSupport.java
+source=core/api/src/test/java/org/apache/polygene/api/service/DocumentationSupport.java
 tag=activation1
 --------------
 
@@ -77,7 +75,7 @@
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/service/DocumentationSupport.java
+source=core/api/src/test/java/org/apache/polygene/api/service/DocumentationSupport.java
 tag=activation2
 --------------
 
@@ -85,7 +83,7 @@
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/service/DocumentationSupport.java
+source=core/api/src/test/java/org/apache/polygene/api/service/DocumentationSupport.java
 tag=activation3
 --------------
 
@@ -102,7 +100,7 @@
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/service/DocumentationSupport.java
+source=core/api/src/test/java/org/apache/polygene/api/service/DocumentationSupport.java
 tag=tag
 --------------
 
@@ -110,6 +108,6 @@
 
 [snippet,java]
 --------------
-source=core/api/src/test/java/org/qi4j/api/service/DocumentationSupport.java
+source=core/api/src/test/java/org/apache/polygene/api/service/DocumentationSupport.java
 tag=UseTag
 --------------
diff --git a/core/api/src/docs/sideeffect.txt b/core/api/src/docs/sideeffect.txt
index 0f68c28..ba12387 100644
--- a/core/api/src/docs/sideeffect.txt
+++ b/core/api/src/docs/sideeffect.txt
@@ -1,6 +1,4 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
  * Licensed 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
@@ -14,4 +12,59 @@
 //////////////////////
 
 [[core-api-sideeffect,SideEffect]]
-= SideEffect =
\ No newline at end of file
+= SideEffect =
+
+SideEffects have no equivalent in Aspect Oriented Programming. They are executed AFTER the method invocation, and
+they are potentially concurrent with the method invocation itself. The SideEffect receives the incoming method arguments
+and can query the result of the method call by accessing the +next+ field. SideEffects can NOT influence the method
+call in any way, and both return values from the SideEffect, as well as any exceptions thrown, will be ignored.
+
+To create a sideeffect, you need to create a class that,
+
+    * implements the Mixin Type (Typed SideEffects) or java.lang.reflect.InvocationHandler (Generic SideEffects),
+    * extend SideEffectOf (Typed Concerns) or GenericSideEffect (Generic SideEffects) [1]
+
+You are allowed to modify both the in-arguments as well as the returned value, including throw exceptions if that is
+suitable, perhaps for post condition checks.
+
+== Applicability ==
+SideEffects are applied to composite types in several ways;
+
+    * @SideEffects annotation on the Mixin Type.
+    * withSideEffects() assembly instruction at bootstrap.
+    * @SideEffects annotation of custom annotations to be applied to either Mixin Types or methods on Mixin Types.
+    * @SideEffects annotation directly on a method.
+
+== Typed SideEffect ==
+As mentioned above, side effects that implements the _Mixin Type_ are called *Typed SideEffects*.
+
+A Typed SideEffect doesn't have to implement all the methods in the Mixin Type. By making the class abstract and only
+implementing the methods of interest, Polygene™ runtime will subclass the side effect (otherwise not valid for the
+JVM/compiler), but the generated methods will never be invoked.
+
+== Generic SideEffect ==
+Generic SideEffects implement the +java.lang.reflect.InvocationHandler+ and can potentially serve any method it is
+applied to. Generic SideEffects will be added to all methods that the AppliesToFilter evaluates to true. By default,
+that is all methods.
+
+AppliesToFilters is a mechanism to limit, or direct, which methods that the concern should be added to. You have full
+control over this selection process, via several mechanisms.
+
+    * @AppliesTo annotation can be put on the side effect, with either;
+        * an interface for which the methods should be wrapped, or
+        * an AppliesToFilter implementation that is consulted during building the invocation stack, or
+        * an annotation type that must be given on the method.
+    * SideEffects are added only to composites that declares the SideEffect, either in
+        * the Composite Type, or
+        * on any method of the Composite Type, or
+        * on an annotation that is in turn declared on a Composite Type method
+        * during assembly in the withSideEffects() method.
+
+== Invocation Order ==
+The invocation order of SideEffects is UNDEFINED, and one MUST NOT rely on SideEffects executing in any particular order.
+They MAY be concurrent and outside the thread that executed the method, so the SideEffect can also not depend on
+the UnitOfWork that may be observed as present.
+
+To be clear; the method call to the SideEffect is NOT its own Polygene-controlled invocation stack, and any annotations
+on the SideEffect methods will be ignored (or it is a bug). That means that IF the SideEffect needs a UnitOfWork it
+either needs to manage one explicitly or call out to a service that has the @UnitOfWorkPropagation annotation.
diff --git a/core/api/src/docs/structure.txt b/core/api/src/docs/structure.txt
index ac4d81e..04952fe 100644
--- a/core/api/src/docs/structure.txt
+++ b/core/api/src/docs/structure.txt
@@ -1,6 +1,4 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
  * Licensed 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
@@ -15,17 +13,17 @@
 
 [[core-api-structure,Structure]]
 = Structure =
-Zest™ promotes a conventional view of application structure, that computer science has been using for decades.
+Polygene™ promotes a conventional view of application structure, that computer science has been using for decades.
 
 The definition is as follows;
 
-    * One Application per Zest™ runtime instance.
+    * One Application per Polygene™ runtime instance.
     * One or more Layers per Application.
     * Zero, one or more Modules per Layer.
     * Zero, one or more Assemblies per Module.
 
 The principle of this Structure is to assist the programmer to create well modularized applications, that are easily
-extended and maintained. Zest™ will restrict access between Modules, so that code can only reach Composites and Objects
+extended and maintained. Polygene™ will restrict access between Modules, so that code can only reach Composites and Objects
 in Modules (including itself) of the same or lower Layers.
 
 Each Layer has to be declared which lower Layer(s) it uses, and it is not allowed that a lower Layer uses a higher
@@ -33,20 +31,20 @@
 
 [[core-api-application,Application]]
 = Application =
-Every Zest™ runtime has _one and only one_ Application in it. It is possible to run multiple Zest™ runtimes in the same
-JVM, and it is even possible to embed a Zest™ runtime within a Zest™ Application, but there can only be one Application
-in a Zest™ runtime.
+Every Polygene™ runtime has _one and only one_ Application in it. It is possible to run multiple Polygene™ runtimes in the same
+JVM, and it is even possible to embed a Polygene™ runtime within a Polygene™ Application, but there can only be one Application
+in a Polygene™ runtime.
 
 An Application is then broken into layers and modules are placed within those layers. Composites are placed within
-modules. This forms the Application Structure and is enforced by the Zest™ runtime.
+modules. This forms the Application Structure and is enforced by the Polygene™ runtime.
 
 [[core-api-layer,Layer]]
 = Layer =
-A Zest™ Application must consist of at least one layer. More layers are common, often dividing the application along the
+A Polygene™ Application must consist of at least one layer. More layers are common, often dividing the application along the
 common architectural diagrams used on whiteboards, perhaps with a UI layer at the top, followed by a service or application
 layer, then with a domain layer and finally some persistence layer at the bottom.
 
-Zest™ enforces this layering by requiring the <<core-bootstrap-assembly>> to declare which layer uses which other layer. And
+Polygene™ enforces this layering by requiring the <<core-bootstrap-assembly>> to declare which layer uses which other layer. And
 <<core-api-visibility>> rules define that layers below can not locate composites in layers above. Also, defining that
 "Layer1 uses Layer2" and "Layer2 uses Layer3" does NOT imply that Layer1 has <<core-api-visibility>> to Layer3. If that
 is wanted, then it must be declared explicitly.
@@ -60,7 +58,7 @@
     * Composites from Modules in the same Layer, with Visibility set to Visibility.layer
     * Composites from Modules in Layers below, with Visibility set to Visibility.application
 
-Modules contains a lot of the Zest™ infrastructure, which are the enforcers of these wise modularization principles.
+Modules contains a lot of the Polygene™ infrastructure, which are the enforcers of these wise modularization principles.
 
 It is not possible to modify the Modules, their resolution nor binding in any way after the application starts.
 
diff --git a/core/api/src/docs/transientcomposite.txt b/core/api/src/docs/transientcomposite.txt
index 1e59731..af05ff1 100644
--- a/core/api/src/docs/transientcomposite.txt
+++ b/core/api/src/docs/transientcomposite.txt
@@ -1,6 +1,4 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
  * Licensed 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
diff --git a/core/api/src/docs/type-lookup.txt b/core/api/src/docs/type-lookup.txt
index 2340fab..23be160 100644
--- a/core/api/src/docs/type-lookup.txt
+++ b/core/api/src/docs/type-lookup.txt
@@ -23,7 +23,7 @@
 Composite Types Lookup can occurs when you explicitely lookup for a Composite by Type
 (ex. ServiceFinder.findService(..) methods), when you ask for an injection or when you create a new composite instance.
 
-All theses type lookup start from a Module, are lazy, cached and obey the Zest™ Visibility rules. Type Lookup works
+All theses type lookup start from a Module, are lazy, cached and obey the Polygene™ Visibility rules. Type Lookup works
 equally accross Composite Types with some subtle differences when it comes to Services and Entities.
 
 
diff --git a/core/api/src/docs/unitofwork.txt b/core/api/src/docs/unitofwork.txt
index d8ad3bc..e432cf2 100644
--- a/core/api/src/docs/unitofwork.txt
+++ b/core/api/src/docs/unitofwork.txt
@@ -1,6 +1,4 @@
 //////////////////////
- * Copyright (c) 2013, Niclas Hedhman. All Rights Reserved.
- *
  * Licensed 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
@@ -19,7 +17,7 @@
 to other threads until the UnitOfWork is completed. It is also possible to discard these operations, as if they were
 never executed.
 
-NOTE: UnitOfWork has many similarities with the Transaction concept used with RDBMSes. But since Zest™ introduced several deviations to the common definitions of Transactions, we chose to use a different term.
+NOTE: UnitOfWork has many similarities with the Transaction concept used with RDBMSes. But since Polygene™ introduced several deviations to the common definitions of Transactions, we chose to use a different term.
 
 There are several key characteristics of UnitOfWork;
 
@@ -44,5 +42,5 @@
 <<core-api-layer>>)
 
 Since it is very common to have all, or nearly all, methods in the _transaction boundary_ to handle the creation and
-completion, possibly with retry, in the same class, module or even layer, Zest™ provides annotations to easily declare
+completion, possibly with retry, in the same class, module or even layer, Polygene™ provides annotations to easily declare
 UnitOfWork concern: @UnitOfWorkPropagation, @UnitOfWorkDiscardOn and @UnitOfWorkRetry
diff --git a/core/api/src/docs/valuecomposite.txt b/core/api/src/docs/valuecomposite.txt
index 7f06ec7..1903c2c 100644
--- a/core/api/src/docs/valuecomposite.txt
+++ b/core/api/src/docs/valuecomposite.txt
@@ -1,7 +1,4 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2013, Paul Merlin. All Rights Reserved.
- *
  * Licensed 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
@@ -21,7 +18,7 @@
 the value exists or it doesn't, no need for synchronization. Values are typically very easy to test and very robust to
 refactoring.
 
-Zest™ defines values as a primary meta type through the ValueComposite, as we think the benefits of values are great.
+Polygene™ defines values as a primary meta type through the ValueComposite, as we think the benefits of values are great.
 The ValueComposite is very light-weight compared to the EntityComposite, and its value can still be persisted as part
 of an EntityComposite via a Property.
 
@@ -30,127 +27,4 @@
     * It is Immutable.
     * Its equals/hashCode works on both the descriptor and the values of the ValueComposite.
     * Can be used as Property types.
-    * Can be serialized and deserialized.
-
-== Value Serialization ==
-Value objects can be serialized and deserialized using the ValueSerialization API which is a Service API implemented
-by SPI and extensions.
-
-TIP: +ValueSerialization extends ValueSerializer, ValueDeserializer+. See the <<javadocs>> for interfaces detail.
-
-The ValueSerialization mechanism apply to the following object types :
-
-    * ValueComposite,
-    * EntityReference,
-    * Iterable,
-    * Map,
-    * Plain Value.
-
-Nested Plain Values, EntityReferences, Iterables, Maps, ValueComposites are supported.
-EntityComposites and EntityReferences are serialized as their identity string.
-
-Plain Values can be one of :
-
-    * String,
-    * Character or char,
-    * Boolean or boolean,
-    * Integer or int,
-    * Long or long,
-    * Short or short,
-    * Byte or byte,
-    * Float or float,
-    * Double or double,
-    * BigInteger,
-    * BigDecimal,
-    * Date,
-    * DateTime (JodaTime),
-    * LocalDateTime (JodaTime),
-    * LocalDate (JodaTime).
-
-TIP: Serialization behaviour can be tuned with options.
-Every +ValueSerializer+ methods can take a +ValueSerializer.Options+ object that contains flags to change how some
-values are serialized. See the <<javadocs>> for more details.
-
-Values of unknown types and all arrays are considered as +java.io.Serializable+ and by so are (de)serialized to (from)
-base64 encoded bytes using pure Java serialization. If it happens that the value is not Serializable or the input to
-deserialize is invalid, a +ValueSerializationException+ is thrown.
-
-Methods of +ValueSerializer+ allow to specify if the serialized state should contain extra type information about the
-serialized value. Having type information in the serialized payload allows to keep actual ValueComposite types and by so
-circumvent +AmbiguousTypeException+ when deserializing.
-
-Core Runtime provides a default ValueSerialization system based on the
-https://github.com/douglascrockford/JSON-java[org.json] Java library producing and consuming JSON.
-
-Let's see how it works in practice.
-
-[snippet,java]
-----
-source=core/api/src/test/java/org/qi4j/api/value/DocumentationSupport.java
-tag=default
-----
-
-Reading this first example step by step we ;
-
-    . declare a ValueComposite,
-    . assemble it,
-    . create a new Value instance,
-    . use the +ValueComposite#toString()+ method to get a JSON representation of the Value,
-    . and finally, use the +Module#newValueFromSerializedState()+ method to create a new Value instance from the JSON
-      state.
-
-+ValueComposite#toString()+ method leverage Value Serialization and by so provide JSON based representation. The Module
-API allows to create new Value instances from serialized state.
-
-On top of that, Application assemblies can register different implementation of ValueSerialization as Services to
-support more formats, see the <<extensions>> section. Note that the default behaviour described above is overriden if a
-ValueSerialization Service is visible.
-
-Let's see how to use the ValueSerialization Services.
-
-[snippet,java]
-----
-source=core/api/src/test/java/org/qi4j/api/value/DocumentationSupport.java
-tag=service
-----
-
-In this second example, we ;
-
-    . declare a ValueComposite,
-    . assemble it,
-    . assemble a ValueSerialization Service backed by the +org.json+ package,
-    . get the +ValueSerializer+ and +ValueDeserializer+ Services injected,
-    . create a new Value instance,
-    . use the +ValueSerializer#serialize()+ method to get a JSON representation of the Value,
-    . and finally, use the +ValueDeserializer#eserialize()+ method to create a new Value instance from the JSON state.
-
-Many applications need to stream data. The ValueSerialization API support such use cases in two ways.
-
-The first one use classic streams.
-
-[snippet,java]
-----
-source=core/api/src/test/java/org/qi4j/api/value/DocumentationSupport.java
-tag=stream
-----
-
-    . get a handle on a source of values and an +OutputStream+,
-    . serialize data into the +OutputStream+,
-    . get a handle on an +InputStream+,
-    . deserialize data from the +InputStream+.
-
-The second one use the <<core-io>>:
-
-[snippet,java]
-----
-source=core/api/src/test/java/org/qi4j/api/value/DocumentationSupport.java
-tag=io
-----
-
-    . get a handle on a source of values and a +Writer+,
-    . prepare the serialization +Function+,
-    . serialize a collection of values, one serialized value per line,
-    . get a handle on a serialized values +Reader+ and create a new empty +List+ of values,
-    . prepare the deserialization +Function+,
-    . deserialize a collection of values from read lines.
-
+    * Can be serialized and deserialized, see <<core-api-serialization>>.
diff --git a/core/api/src/main/java/org/apache/polygene/api/PolygeneAPI.java b/core/api/src/main/java/org/apache/polygene/api/PolygeneAPI.java
new file mode 100644
index 0000000..a9958a6
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/PolygeneAPI.java
@@ -0,0 +1,167 @@
+/*
+ *  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.polygene.api;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.util.function.Function;
+import org.apache.polygene.api.association.AbstractAssociation;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.composite.InvalidCompositeException;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.value.ValueDescriptor;
+
+/**
+ * Encapsulation of the Polygene API.
+ */
+public interface PolygeneAPI
+{
+    /**
+     * If a Modifier gets a reference to the Composite using @This,
+     * then that reference must be dereferenced using this method
+     * before handing it out for others to use.
+     *
+     * @param <T>       Parameterized type of the Composite
+     * @param composite instance reference injected in Modified using @This
+     *
+     * @return the dereferenced Composite
+     */
+    <T> T dereference( T composite );
+
+    /**
+     * Returns the Module where the Composite, ServiceReference or UnitOfWork belongs.
+     *
+     * @param compositeOrServiceReferenceOrUow The Composite (Service, Value, Entity or Transient) or ServiceReference
+     *                                         or UnitOfWork to lookup the Module it belongs to
+     *
+     * @return The Module instance where the Composite, ServiceReference or UnitOfWork belongs to
+     */
+    ModuleDescriptor moduleOf( Object compositeOrServiceReferenceOrUow );
+
+    /**
+     * Returns the ModelDescriptor of the Composite or ServiceReference.
+     *
+     * @param compositeOrServiceReference The Composite (Service, Value, Entity or Transient) of ServiceReference
+     *                                    for which to lookup the ModelDescriptor
+     *
+     * @return The ModelDescriptor of the Composite or ServiceReference
+     */
+    ModelDescriptor modelDescriptorFor( Object compositeOrServiceReference );
+
+    /**
+     * Returns the CompositeDescriptor of the Composite or ServiceReference.
+     *
+     * @param compositeOrServiceReference The Composite (Service, Value, Entity or Transient)  or ServiceReference
+     *                                    for which to lookup the CompositeDescriptor
+     *
+     * @return The CompositeDescriptor of the Composite or ServiceReference
+     */
+    CompositeDescriptor compositeDescriptorFor( Object compositeOrServiceReference );
+
+    /**
+     * Returns the TransientDescriptor of the TransientComposite.
+     *
+     * @param transsient The TransientComposite for which to lookup the TransientDescriptor
+     *
+     * @return The TransientDescriptor of the TransientComposite
+     */
+    TransientDescriptor transientDescriptorFor( Object transsient );
+
+    /**
+     * Returns the EntityDescriptor of the EntityComposite.
+     *
+     * @param entity The EntityComposite for which to lookup the EntityDescriptor
+     *
+     * @return The EntityDescriptor of the EntityComposite
+     */
+    EntityDescriptor entityDescriptorFor( Object entity );
+
+    /**
+     * Returns the ValueDescriptor of the ValueComposite.
+     *
+     * @param value The ValueComposite for which to lookup the ValueDescriptor
+     *
+     * @return The ValueDescriptor of the ValueComposite
+     */
+    ValueDescriptor valueDescriptorFor( Object value );
+
+    /**
+     * Returns the ServiceDescriptor of the ServiceComposite.
+     *
+     * @param service The ServiceComposite for which to lookup the ServiceDescriptor
+     *
+     * @return The ServiceDescriptor of the ServiceComposite
+     */
+    ServiceDescriptor serviceDescriptorFor( Object service );
+
+    /**
+     * Returns the PropertyDescriptor of the Property.
+     *
+     * @param property The Property for which to lookup the PropertyDescriptor
+     *
+     * @return The PropertyDescriptor of the Property
+     */
+    PropertyDescriptor propertyDescriptorFor( Property<?> property );
+
+    /**
+     * Returns the AssociationDescriptor of the Association.
+     *
+     * @param association The Association for which to lookup the AssociationDescriptor
+     *
+     * @return The AssociationDescriptor of the Association
+     */
+    AssociationDescriptor associationDescriptorFor( AbstractAssociation association );
+
+    /**
+     * Function that returns the CompositeInstance of a Composite.
+     */
+    Function<Composite, CompositeInstance> FUNCTION_COMPOSITE_INSTANCE_OF = composite -> {
+        if( composite instanceof Proxy )
+        {
+            return ( (CompositeInstance) Proxy.getInvocationHandler( composite ) );
+        }
+        try
+        {
+            Class<? extends Composite> compositeClass = composite.getClass();
+            Field instanceField = compositeClass.getField( "_instance" );
+            Object instance = instanceField.get( composite );
+            return (CompositeInstance) instance;
+        }
+        catch( Exception e )
+        {
+            throw new InternalError( "Could not get _instance field. This field should have been automatically generated by the Polygene runtime.", e );
+        }
+    };
+
+    /**
+     * Function that returns the CompositeDescriptor of a Composite.
+     */
+    Function<Composite, CompositeDescriptor> FUNCTION_DESCRIPTOR_FOR = FUNCTION_COMPOSITE_INSTANCE_OF.andThen( CompositeInstance::descriptor );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/activation/Activation.java b/core/api/src/main/java/org/apache/polygene/api/activation/Activation.java
new file mode 100644
index 0000000..3b03d82
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/activation/Activation.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.api.activation;
+
+/**
+ * Interface used by Structure elements and Services that can be activated and passivated.
+ * <p>Application and Layer expose this interface so you can activate and passivate them.</p>
+ * <p>Module and ServiceComposite activation/passivation is handled by the Polygene runtime.</p>
+ */
+@SuppressWarnings("JavaDoc")
+public interface Activation
+{
+    /**
+     * Activate.
+     * <p>Fail fast execution order is:</p>
+     * <ul>
+     *   <li>Fire {@link ActivationEvent.EventType#ACTIVATING}</li>
+     *   <li>Call {@link Activator#beforeActivation(java.lang.Object)} on each Activator</li>
+     *   <li>Call {@link #activate()} children</li>
+     *   <li>Call {@link Activator#afterActivation(java.lang.Object)} on each Activator</li>
+     *   <li>Fire {@link ActivationEvent.EventType#ACTIVATED}</li>
+     * </ul>
+     * <p>If an Exception is thrown, already activated nodes are passivated.</p>
+     * @throws ActivationException with first Exception of activation plus the PassivationException if any
+     */
+    void activate()
+        throws ActivationException;
+
+    /**
+     * Passivate.
+     * <p>Fail safe execution order is:</p>
+     * <ul>
+     *   <li>Fire {@link ActivationEvent.EventType#PASSIVATING}</li>
+     *   <li>Call {@link Activator#beforePassivation(java.lang.Object)} on each Activator</li>
+     *   <li>Call {@link #passivate()} children</li>
+     *   <li>Call {@link Activator#afterPassivation(java.lang.Object)} on each Activator</li>
+     *   <li>Fire {@link ActivationEvent.EventType#PASSIVATED}</li>
+     * </ul>
+     * @throws PassivationException after passivation with all Exceptions of passivation if any
+     */
+    void passivate()
+        throws PassivationException;
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/activation/ActivationEvent.java b/core/api/src/main/java/org/apache/polygene/api/activation/ActivationEvent.java
new file mode 100644
index 0000000..f40488f
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/activation/ActivationEvent.java
@@ -0,0 +1,99 @@
+/*
+ *  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.polygene.api.activation;
+
+import java.time.Instant;
+import org.apache.polygene.api.time.SystemTime;
+
+/**
+ * ActivationEvents are fired during activation and passivation of instances in Polygene.
+ */
+public final class ActivationEvent
+{
+    public enum EventType
+    {
+        ACTIVATING, ACTIVATED, PASSIVATING, PASSIVATED
+    }
+
+    private final Instant timestamp;
+    private final Object source;
+    private final EventType type;
+
+    public ActivationEvent( Object source, EventType type )
+    {
+        this.timestamp = SystemTime.now();
+        this.source = source;
+        this.type = type;
+    }
+
+    /**
+     * @return the source of the Activation event
+     */
+    public Object source()
+    {
+        return source;
+    }
+
+    /**
+     * @return the type of the Activation event
+     */
+    public EventType type()
+    {
+        return type;
+    }
+
+
+    /**
+     *
+     * @return The instant that this event was created.
+     */
+    public Instant eventTime()
+    {
+        return timestamp;
+    }
+
+    /**
+     * @return an informative message describing the event
+     */
+    public String message()
+    {
+        switch( type )
+        {
+        case ACTIVATING:
+            return "Activating " + source;
+        case ACTIVATED:
+            return "Activated " + source;
+        case PASSIVATING:
+            return "Passivating " + source;
+        case PASSIVATED:
+            return "Passivated " + source;
+        }
+        return "";
+    }
+
+    /**
+     * @see #message()
+     */
+    @Override
+    public String toString()
+    {
+        return message() + "@" + timestamp;
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/activation/ActivationEventListener.java b/core/api/src/main/java/org/apache/polygene/api/activation/ActivationEventListener.java
new file mode 100644
index 0000000..108ebc6
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/activation/ActivationEventListener.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.api.activation;
+
+/**
+ * Listener for ActivationEvent events
+ */
+public interface ActivationEventListener
+{
+    void onEvent( ActivationEvent event )
+        throws Exception;
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/activation/ActivationEventListenerRegistration.java b/core/api/src/main/java/org/apache/polygene/api/activation/ActivationEventListenerRegistration.java
new file mode 100644
index 0000000..2e7d83a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/activation/ActivationEventListenerRegistration.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.api.activation;
+
+/**
+ * Use this to register listeners for ActivationEvents.
+ *
+ * This is implemented by Application, Layer, Module, for example.
+ */
+public interface ActivationEventListenerRegistration
+{
+    /**
+     * @param listener will be notified when Activation events occur
+     */
+    void registerActivationEventListener( ActivationEventListener listener );
+
+    /**
+     * @param listener will not be notified when Activation events occur anymore
+     */
+    void deregisterActivationEventListener( ActivationEventListener listener );
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/activation/ActivationException.java b/core/api/src/main/java/org/apache/polygene/api/activation/ActivationException.java
new file mode 100644
index 0000000..b4e6e29
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/activation/ActivationException.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.api.activation;
+
+/**
+ * Thrown when unable to activate.
+ */
+public class ActivationException extends Exception
+{
+    public ActivationException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/activation/Activator.java b/core/api/src/main/java/org/apache/polygene/api/activation/Activator.java
new file mode 100644
index 0000000..90a68b5
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/activation/Activator.java
@@ -0,0 +1,72 @@
+/*
+ *  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.polygene.api.activation;
+
+/**
+ * Assemble Activators to hook Services Activation.
+ *
+ * @param <ActivateeType> Type of the activatee.
+ *
+ * @see ActivatorAdapter
+ * @see org.apache.polygene.api.service.ServiceActivation
+ */
+public interface Activator<ActivateeType>
+{
+
+    /**
+     * Called before activatee activation.
+     *
+     * @param activating The instance that is about to be activated.
+     *
+     * @throws Exception Allowed to throw Exception which will be wrapped in an ActivationException
+     */
+    void beforeActivation( ActivateeType activating )
+        throws Exception;
+
+    /**
+     * Called after activatee activation.
+     *
+     * @param activated The instance that has just been activated.
+     *
+     * @throws Exception Allowed to throw Exception which will be wrapped in an ActivationException
+     */
+    void afterActivation( ActivateeType activated )
+        throws Exception;
+
+    /**
+     * Called before activatee passivation.
+     *
+     * @param passivating The instance that is about to be passivated.
+     *
+     * @throws Exception Allowed to throw Exception which will be wrapped in an PassivationException
+     */
+    void beforePassivation( ActivateeType passivating )
+        throws Exception;
+
+    /**
+     * Called after activatee passivation.
+     *
+     * @param passivated The instance that has just been passivated.
+     *
+     * @throws Exception Allowed to throw Exception which will be wrapped in an PassivationException
+     */
+    void afterPassivation( ActivateeType passivated )
+        throws Exception;
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/activation/ActivatorAdapter.java b/core/api/src/main/java/org/apache/polygene/api/activation/ActivatorAdapter.java
new file mode 100644
index 0000000..208e492
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/activation/ActivatorAdapter.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.api.activation;
+
+/**
+ * Adapter for Activator.
+ * <p>If you are thinking about Service activation, see {@link org.apache.polygene.api.service.ServiceActivatorAdapter}.</p>
+ *
+ * @param <ActivateeType> Type of the activatee.
+ */
+public class ActivatorAdapter<ActivateeType>
+    implements Activator<ActivateeType>
+{
+    /**
+     * Called before activatee activation.
+     * @param activating Activating activatee
+     */
+    @Override
+    public void beforeActivation( ActivateeType activating )
+        throws Exception
+    {
+    }
+
+    /**
+     * Called after activatee activation.
+     * @param activated Activating activatee
+     */
+    @Override
+    public void afterActivation( ActivateeType activated )
+        throws Exception
+    {
+    }
+
+    /**
+     * Called before activatee passivation.
+     * @param passivating Passivating activatee
+     */
+    @Override
+    public void beforePassivation( ActivateeType passivating )
+        throws Exception
+    {
+    }
+
+    /**
+     * Called after activatee passivation.
+     * @param passivated Passivated activatee
+     */
+    @Override
+    public void afterPassivation( ActivateeType passivated )
+        throws Exception
+    {
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/activation/ActivatorDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/activation/ActivatorDescriptor.java
new file mode 100644
index 0000000..75b482f
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/activation/ActivatorDescriptor.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.api.activation;
+
+/**
+ * Activator Descriptor.
+ */
+public interface ActivatorDescriptor
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/activation/Activators.java b/core/api/src/main/java/org/apache/polygene/api/activation/Activators.java
new file mode 100644
index 0000000..912760a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/activation/Activators.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.api.activation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation is used in ServiceComposites to declare Activator implementation classes.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( ElementType.TYPE )
+@Documented
+public @interface Activators
+{
+
+    /**
+     * @return Activator implementation classes.
+     */
+    Class<? extends Activator<?>>[] value();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/activation/ApplicationPassivationThread.java b/core/api/src/main/java/org/apache/polygene/api/activation/ApplicationPassivationThread.java
new file mode 100644
index 0000000..c758d04
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/activation/ApplicationPassivationThread.java
@@ -0,0 +1,113 @@
+/*
+ *  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.polygene.api.activation;
+
+import java.io.PrintStream;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.polygene.api.structure.Application;
+
+/**
+ * Application Passivation Thread to use as a Shutdown Hook.
+ * <pre>Runtime.getRuntime().addShutdownHook( new ApplicationPassivationThread( application ) );</pre>
+ */
+public final class ApplicationPassivationThread
+    extends Thread
+{
+    /**
+     * Create a new Application Passivation Thread that output errors to STDERR.
+     * @param application The Application to passivate
+     */
+    @SuppressWarnings("unused")
+    public ApplicationPassivationThread(final Application application )
+    {
+        this( application, null, null );
+    }
+
+    /**
+     * Create a new Application Passivation Thread that output errors to a Logger.
+     * @param application The Application to passivate
+     * @param logger Logger for errors
+     */
+    @SuppressWarnings("unused")
+    public ApplicationPassivationThread(Application application, Logger logger )
+    {
+        this( application, null, logger );
+    }
+
+    /**
+     * Create a new Application Passivation Thread that output errors to a PrintStream.
+     * @param application The Application to passivate
+     * @param output PrintStream for errors
+     */
+    public ApplicationPassivationThread( Application application, PrintStream output )
+    {
+        this( application, output, null );
+    }
+
+    private ApplicationPassivationThread( Application application, PrintStream output, Logger logger )
+    {
+        super( new ApplicationPassivation( application, output, logger ),
+               application.name() + " Passivation Thread" );
+    }
+
+    private static class ApplicationPassivation
+        implements Runnable
+    {
+        private final Application application;
+        private final PrintStream output;
+        private final Logger logger;
+
+        private ApplicationPassivation( Application application, PrintStream output, Logger logger )
+        {
+            this.application = application;
+            this.output = output;
+            this.logger = logger;
+        }
+
+        @Override
+        public void run()
+        {
+            try
+            {
+                application.passivate();
+            }
+            catch( PassivationException ex )
+            {
+                String message = application.name() + " " + ex.getMessage();
+                if( logger != null )
+                {
+                    logger.log( Level.SEVERE, message, ex );
+                }
+                else if( output != null )
+                {
+                    output.println( message );
+                    ex.printStackTrace( output );
+                }
+                else
+                {
+                    ex.printStackTrace();
+                }
+            }
+        }
+
+    }
+
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/activation/PassivationException.java b/core/api/src/main/java/org/apache/polygene/api/activation/PassivationException.java
new file mode 100644
index 0000000..a4f8540
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/activation/PassivationException.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.api.activation;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Thrown when unable to passivate.
+ *
+ * Printed StackTrace contains all causes in order as suppressed exceptions.
+ */
+public final class PassivationException
+    extends Exception
+{
+    private final List<Exception> causes;
+
+    /**
+     * Create new PassivationException.
+     * @param exceptions All exceptions encountered during passivation, in order
+     */
+    public PassivationException( Collection<Exception> exceptions )
+    {
+        super( "Passivation Exception - [has " + exceptions.size() + " cause(s)]" );
+        exceptions.forEach( this::addSuppressed );
+        this.causes = new ArrayList<>( exceptions );
+    }
+
+    /**
+     * @return All exceptions encountered during passivation, in order
+     */
+    public List<Exception> causes()
+    {
+        return causes;
+    }
+
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/activation/package.html b/core/api/src/main/java/org/apache/polygene/api/activation/package.html
new file mode 100644
index 0000000..c11d85f
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/activation/package.html
@@ -0,0 +1,29 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Activation API.</h2>
+        <p>
+            The Activation API package contains types used by client code to integrate with the Polygene™ Runtime activation
+            mechanism. In assembly, client code can easily listen to Structure (Application, Layers and Modules) and
+            Services activation events, or, declare Structure and Service Activators.
+        </p>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/association/AbstractAssociation.java b/core/api/src/main/java/org/apache/polygene/api/association/AbstractAssociation.java
new file mode 100644
index 0000000..55ec7d8
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/association/AbstractAssociation.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.api.association;
+
+/**
+ * Base interface for all associations.
+ */
+public interface AbstractAssociation
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/association/Association.java b/core/api/src/main/java/org/apache/polygene/api/association/Association.java
new file mode 100644
index 0000000..5e458ce
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/association/Association.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.polygene.api.association;
+
+import org.apache.polygene.api.entity.EntityReference;
+
+/**
+ * Association to a single EntityComposite.
+ */
+public interface Association<T> extends AbstractAssociation
+{
+    /**
+     * Get the associated entity.
+     *
+     * @return the associated entity
+     */
+    T get();
+
+    /**
+     * Set the associated entity.
+     *
+     * @param associated the entity
+     *
+     * @throws IllegalArgumentException thrown if the entity is not a valid reference for this association
+     * @throws IllegalStateException    thrown if association is immutable
+     */
+    void set( T associated )
+        throws IllegalArgumentException, IllegalStateException;
+
+    /**
+     * @return the the reference of the associated entity.
+     */
+    EntityReference reference();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/association/AssociationDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/association/AssociationDescriptor.java
new file mode 100644
index 0000000..e7a1c01
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/association/AssociationDescriptor.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.api.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Type;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.structure.MetaInfoHolder;
+
+/**
+ * Association Descriptor.
+ */
+public interface AssociationDescriptor extends MetaInfoHolder
+{
+    /**
+     * Get the qualified name of the association. This is constructed by
+     * concatenating the name of the declaring interface with the name
+     * of the method, using ":" as separator.
+     * <p>
+     * Example:
+     * </p>
+     * <p>
+     * com.somecompany.MyInterface with association method
+     * </p>
+     * <pre><code>
+     * Association&lt;String&gt; someAssociation();
+     * </code></pre>
+     * will have the qualified name:
+     * <pre><code>
+     * com.somecompany.MyInterface:someAssociation
+     * </code></pre>
+     *
+     * @return the qualified name of the association
+     */
+    QualifiedName qualifiedName();
+
+    /**
+     * Get the type of the associated Entities
+     *
+     * @return the type of the associated Entities
+     */
+    Type type();
+
+    boolean isImmutable();
+
+    boolean isAggregated();
+
+    AccessibleObject accessor();
+
+    boolean queryable();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/association/AssociationMixin.java b/core/api/src/main/java/org/apache/polygene/api/association/AssociationMixin.java
new file mode 100644
index 0000000..e26d324
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/association/AssociationMixin.java
@@ -0,0 +1,58 @@
+/*
+ *  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.polygene.api.association;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.AppliesToFilter;
+import org.apache.polygene.api.injection.scope.State;
+
+/**
+ * Generic mixin for associations.
+ */
+@AppliesTo( { AssociationMixin.AssociationFilter.class } )
+public final class AssociationMixin
+    implements InvocationHandler
+{
+    @State
+    private AssociationStateHolder associations;
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        return associations.associationFor( method );
+    }
+
+    /**
+     * Associations generic mixin AppliesToFilter.
+     */
+    static class AssociationFilter
+        implements AppliesToFilter
+    {
+        @Override
+        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> modifierClass )
+        {
+            return Association.class.isAssignableFrom( method.getReturnType() );
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/association/AssociationStateDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/association/AssociationStateDescriptor.java
new file mode 100644
index 0000000..dbee470
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/association/AssociationStateDescriptor.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.api.association;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.composite.StateDescriptor;
+
+/**
+ * Associations State Descriptor.
+ */
+public interface AssociationStateDescriptor extends StateDescriptor
+{
+    AssociationDescriptor getAssociationByName( String name )
+        throws IllegalArgumentException;
+
+    AssociationDescriptor getAssociationByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException;
+
+    AssociationDescriptor getManyAssociationByName( String name )
+        throws IllegalArgumentException;
+
+    AssociationDescriptor getManyAssociationByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException;
+
+    AssociationDescriptor getNamedAssociationByName( String name )
+        throws IllegalArgumentException;
+
+    AssociationDescriptor getNamedAssociationByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException;
+
+    Stream<? extends AssociationDescriptor> associations();
+
+    Stream<? extends AssociationDescriptor> manyAssociations();
+
+    Stream<? extends AssociationDescriptor> namedAssociations();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/association/AssociationStateHolder.java b/core/api/src/main/java/org/apache/polygene/api/association/AssociationStateHolder.java
new file mode 100644
index 0000000..ed68517
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/association/AssociationStateHolder.java
@@ -0,0 +1,81 @@
+/*
+ *  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.polygene.api.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.util.stream.Stream;
+import org.apache.polygene.api.property.StateHolder;
+
+/**
+ * This represents the state of a entity (properties+associations).
+ */
+public interface AssociationStateHolder extends StateHolder
+{
+    /**
+     * Get an association for a specific accessor method.
+     *
+     * @param <T> Association type
+     * @param associationMethod for the association
+     *
+     * @return the association
+     */
+    <T> Association<T> associationFor( AccessibleObject associationMethod );
+
+    /**
+     * Get all associations.
+     *
+     * @return stream of associations
+     */
+    Stream<? extends Association<?>> allAssociations();
+
+    /**
+     * Get a many-association for a specific accessor method.
+     *
+     * @param <T> Association type
+     * @param manyassociationMethod for the many-association
+     *
+     * @return the association
+     */
+    <T> ManyAssociation<T> manyAssociationFor( AccessibleObject manyassociationMethod );
+
+    /**
+     * Get all ManyAssociations.
+     *
+     * @return stream of many-associations
+     */
+    Stream<? extends ManyAssociation<?>> allManyAssociations();
+
+    /**
+     * Get a named-association for a specific accessor method.
+     *
+     * @param <T> Association type
+     * @param namedassociationMethod for the named-association
+     *
+     * @return the association
+     */
+    <T> NamedAssociation<T> namedAssociationFor( AccessibleObject namedassociationMethod );
+
+    /**
+     * Get all named-associations.
+     *
+     * @return stream of named-associations
+     */
+    Stream<? extends NamedAssociation<?>> allNamedAssociations();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/association/AssociationWrapper.java b/core/api/src/main/java/org/apache/polygene/api/association/AssociationWrapper.java
new file mode 100644
index 0000000..b41b41f
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/association/AssociationWrapper.java
@@ -0,0 +1,81 @@
+/*
+ *  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.polygene.api.association;
+
+import org.apache.polygene.api.entity.EntityReference;
+
+/**
+ * If you want to catch getting and setting association, then create a GenericConcern
+ * that wraps the Polygene-supplied Association instance with AssociationWrappers. Override
+ * get() and/or set() to perform your custom code.
+ */
+public class AssociationWrapper
+    implements Association<Object>
+{
+    protected Association<Object> next;
+
+    public AssociationWrapper( Association<Object> next )
+    {
+        this.next = next;
+    }
+
+    public Association<Object> next()
+    {
+        return next;
+    }
+
+    @Override
+    public Object get()
+    {
+        return next.get();
+    }
+
+    @Override
+    public void set( Object associated )
+        throws IllegalArgumentException
+    {
+        next.set( associated );
+    }
+
+    @Override
+    public EntityReference reference()
+    {
+        return next.reference();
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return next.hashCode();
+    }
+
+    @Override
+    @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
+    public boolean equals( Object obj )
+    {
+        return next.equals( obj );
+    }
+
+    @Override
+    public String toString()
+    {
+        return next.toString();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/association/GenericAssociationInfo.java b/core/api/src/main/java/org/apache/polygene/api/association/GenericAssociationInfo.java
new file mode 100644
index 0000000..c42f172
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/association/GenericAssociationInfo.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.api.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+import static org.apache.polygene.api.util.Classes.typeOf;
+
+/**
+ * Generic Association info.
+ */
+public final class GenericAssociationInfo
+{
+    public static Type associationTypeOf( AccessibleObject accessor )
+    {
+        return toAssociationType( typeOf( accessor ) );
+    }
+
+    public static Type toAssociationType( Type methodReturnType )
+    {
+        if( methodReturnType instanceof ParameterizedType )
+        {
+            ParameterizedType parameterizedType = (ParameterizedType) methodReturnType;
+            if( AbstractAssociation.class.isAssignableFrom( (Class<?>) parameterizedType.getRawType() ) )
+            {
+                return parameterizedType.getActualTypeArguments()[ 0 ];
+            }
+        }
+        if (!(methodReturnType instanceof Class))
+        {
+            throw new IllegalArgumentException( "Unable to make an association with " + methodReturnType );
+        }
+        Type[] interfaces = ((Class<?>) methodReturnType).getGenericInterfaces();
+        for (Type anInterface : interfaces)
+        {
+            Type associationType = toAssociationType(anInterface);
+            if (associationType != null)
+            {
+                return associationType;
+            }
+        }
+        return null;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/association/ManyAssociation.java b/core/api/src/main/java/org/apache/polygene/api/association/ManyAssociation.java
new file mode 100644
index 0000000..b7b7f7f
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/association/ManyAssociation.java
@@ -0,0 +1,120 @@
+/*
+ *  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.polygene.api.association;
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.Identity;
+
+/**
+ * Association to a collection of entities.
+ */
+public interface ManyAssociation<T> extends Iterable<T>, AbstractAssociation
+{
+    /**
+     * Check is the entity is part of this {@code ManyAssociation}.
+     *
+     * @param entity The entity to be checking for.
+     * @return true if there is an entity in this ManyAssociation with the same {@link Identity} as the given
+     * entity , otherwise false.
+     */
+    boolean contains( T entity );
+
+    /** Adds an entity reference representing the given entity to the {@code index} slot of this collection.
+     * <p>
+     *     {@code index=0} represents the beginning of the collection and if the {@code index} is equal or larger
+     *     than the length of the collection, the entity reference will be added to the end.
+     * </p>
+     * @param entity The entity whose entity reference is to be added to this collection.
+     * @param index the position for the entity to be inserted at.
+     * @return true if the entity reference has been added, false otherwise.
+     */
+    boolean add( int index, T entity );
+
+    /** Adds an entity reference representing the given entity to the end of this collection.
+     *
+     * @param entity The entity whose entity reference is to be added to this collection.
+     * @return true if the entity reference has been added, false otherwise.
+     */
+    boolean add( T entity );
+
+    /**
+     * Removes the given entity from this {@code ManyAssociation}.
+     * <p>
+     *     The entity reference representing the given entity is removed from this collection.
+     * </p>
+     * @param entity The entity reference to be removed.
+     * @return true if an entity reference was removed, otherwise false
+     */
+    boolean remove( T entity );
+
+    /**
+     * Clear all entities from this {@code ManyAssociation}.
+     * <p>
+     *     All entity references present is removed from this collection.
+     * </p>
+     * @return true if any entity reference was removed, otherwise false
+     */
+    boolean clear();
+
+    /** Fetch the entity refrence at the given index and fetch the entity from the entity store.
+     *
+     * @param index The index location in the collection of the entity reference to be fetched.
+     * @return The retrieved entity that the entity reference of this collection represents.
+     */
+    T get( int index );
+
+    /**
+     * Returns the number of references in this association.
+     * @return the number of references in this association.
+     */
+    int count();
+
+    /**
+     * Fetches all entities represented by entity references in this collection and returns a List of such
+     * entities.
+     * <p>
+     *     Multiple references to the same entity will be present multiple times in the List, unlike {@link #toSet()}.
+     *     The order in which the entities were added to this collection is preserved.
+     * </p>
+     * @return a List of entities represented by the entity references in this collection.
+     */
+    List<T> toList();
+
+    /**
+     * Fetches all entities represented by entity references in this collection and returns a Set of such
+     * entities.
+     * <p>
+     *     Multiple references to the same entity will NOT be present, unlike {@link #toList()}. Sets are defined
+     *     to only contain any particular object once. Order is not preserved.
+     * </p>
+     * @return a Set of entities represented by the entity references in this collection.
+     */
+    Set<T> toSet();
+
+    /**
+     * Returns a stream of the references to the associated entities.
+     * @return the references to the associated entities.
+     */
+    Stream<EntityReference> references();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/association/ManyAssociationMixin.java b/core/api/src/main/java/org/apache/polygene/api/association/ManyAssociationMixin.java
new file mode 100644
index 0000000..0ed4db1
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/association/ManyAssociationMixin.java
@@ -0,0 +1,58 @@
+/*
+ *  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.polygene.api.association;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.AppliesToFilter;
+import org.apache.polygene.api.injection.scope.State;
+
+/**
+ * Generic mixin for associations.
+ */
+@AppliesTo( { ManyAssociationMixin.AssociationFilter.class } )
+public final class ManyAssociationMixin
+    implements InvocationHandler
+{
+    @State
+    private AssociationStateHolder associations;
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        return associations.manyAssociationFor( method );
+    }
+
+    /**
+     * ManyAssociations generic mixin AppliesToFilter.
+     */
+    static class AssociationFilter
+        implements AppliesToFilter
+    {
+        @Override
+        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> modifierClass )
+        {
+            return ManyAssociation.class.isAssignableFrom( method.getReturnType() );
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/association/ManyAssociationWrapper.java b/core/api/src/main/java/org/apache/polygene/api/association/ManyAssociationWrapper.java
new file mode 100644
index 0000000..e2f95e1
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/association/ManyAssociationWrapper.java
@@ -0,0 +1,132 @@
+/*
+ *  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.polygene.api.association;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+import org.apache.polygene.api.entity.EntityReference;
+
+/**
+ * If you want to catch calls to ManyAssociations, then create a GenericConcern
+ * that wraps the Polygene-supplied ManyAssociation instance with ManyAssociationWrappers. Override
+ * methods to perform your custom code.
+ */
+public class ManyAssociationWrapper
+    implements ManyAssociation<Object>
+{
+    protected ManyAssociation<Object> next;
+
+    public ManyAssociationWrapper( ManyAssociation<Object> next )
+    {
+        this.next = next;
+    }
+
+    public ManyAssociation<Object> next()
+    {
+        return next;
+    }
+
+    @Override
+    public int count()
+    {
+        return next.count();
+    }
+
+    @Override
+    public boolean contains( Object entity )
+    {
+        return next.contains( entity );
+    }
+
+    @Override
+    public boolean add( int i, Object entity )
+    {
+        return next.add( i, entity );
+    }
+
+    @Override
+    public boolean add( Object entity )
+    {
+        return next.add( entity );
+    }
+
+    @Override
+    public boolean remove( Object entity )
+    {
+        return next.remove( entity );
+    }
+
+    @Override
+    public boolean clear()
+    {
+        return next.clear();
+    }
+
+    @Override
+    public Object get( int i )
+    {
+        return next.get( i );
+    }
+
+    @Override
+    public List<Object> toList()
+    {
+        return next.toList();
+    }
+
+    @Override
+    public Set<Object> toSet()
+    {
+        return next.toSet();
+    }
+
+    @Override
+    public Stream<EntityReference> references()
+    {
+        return next.references();
+    }
+
+    @Override
+    public Iterator<Object> iterator()
+    {
+        return next.iterator();
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return next.hashCode();
+    }
+
+    @Override
+    @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
+    public boolean equals( Object obj )
+    {
+        return next.equals( obj );
+    }
+
+    @Override
+    public String toString()
+    {
+        return next.toString();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/association/NamedAssociation.java b/core/api/src/main/java/org/apache/polygene/api/association/NamedAssociation.java
new file mode 100644
index 0000000..b8a62da
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/association/NamedAssociation.java
@@ -0,0 +1,99 @@
+/*
+ *  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.polygene.api.association;
+
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.entity.EntityReference;
+
+/**
+ * Association to named Entities.
+ * The Iterable&lt;String&gt; returns the names in the association set.
+ * @param <T> Parameterized associatee type
+ */
+public interface NamedAssociation<T>
+    extends Iterable<String>, AbstractAssociation
+{
+    /**
+     * @return The number of named associations in this NamedAssociation.
+     */
+    int count();
+
+    /**
+     * Checks if there is an association with the given name.
+     * @param name The name of the association we are checking if it exists.
+     * @return true if it exists, false otherwise
+     */
+    boolean containsName( String name );
+
+    /**
+     * Adds a named association.
+     * @param name The name of the association.
+     * @param entity The entity for this named association.
+     * @return true if putted, false otherwise
+     */
+    boolean put( String name, T entity );
+
+    /**
+     * Remove a named association.
+     * @param name The name of the association.
+     * @return true if removed, false otherwise
+     */
+    boolean remove( String name );
+
+    /**
+     * Clear all named associations.
+     * @return true if cleared, false otherwise
+     */
+    boolean clear();
+
+    /**
+     * Retrieves a named association.
+     * @param name The name of the association.
+     * @return The entity that has previously been associated.
+     */
+    T get( String name );
+
+    /**
+     * Checks if the entity is present.
+     * Note that this is potentially a very slow operation, depending on the size of the NamedAssociation.
+     * @param entity The entity to look for.
+     * @return The name of the entity if found, otherwise null.
+     */
+    String nameOf( T entity );
+
+    /**
+     * @return A fully populated Map with the content of this NamedAssociation.
+     */
+    Map<String, T> toMap();
+
+    /**
+     * Returns a stream of the references to the associated entities.
+     * @return the references to the associated entities.
+     */
+    Stream<Map.Entry<String, EntityReference>> references();
+
+    /** Returns the EntityReference for the Association with the given name.
+     *
+     * @param name The name of the association to return the EntityReference for
+     * @return The EntityReference of the association.
+     */
+    EntityReference referenceOf( String name );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/association/NamedAssociationMixin.java b/core/api/src/main/java/org/apache/polygene/api/association/NamedAssociationMixin.java
new file mode 100644
index 0000000..ea1ed12
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/association/NamedAssociationMixin.java
@@ -0,0 +1,58 @@
+/*
+ *  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.polygene.api.association;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.AppliesToFilter;
+import org.apache.polygene.api.injection.scope.State;
+
+/**
+ * Generic mixin for NamedAssociations.
+ */
+@AppliesTo( NamedAssociationMixin.AssociationFilter.class )
+public final class NamedAssociationMixin
+    implements InvocationHandler
+{
+    @State
+    private AssociationStateHolder associations;
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        return associations.namedAssociationFor( method );
+    }
+
+    /**
+     * NamedAssociations generic mixin AppliesToFilter.
+     */
+    static class AssociationFilter
+        implements AppliesToFilter
+    {
+        @Override
+        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> modifierClass )
+        {
+            return NamedAssociation.class.isAssignableFrom( method.getReturnType() );
+        }
+    }
+
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/association/NamedAssociationWrapper.java b/core/api/src/main/java/org/apache/polygene/api/association/NamedAssociationWrapper.java
new file mode 100644
index 0000000..1f92767
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/association/NamedAssociationWrapper.java
@@ -0,0 +1,131 @@
+/*
+ *  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.polygene.api.association;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.entity.EntityReference;
+
+/**
+ * If you want to catch calls to NamedAssociations, then create a GenericConcern
+ * that wraps the Polygene-supplied NamedAssociations instance with NamedAssociationsWrapper. Override
+ * methods to perform your custom code.
+ */
+public class NamedAssociationWrapper
+    implements NamedAssociation<Object>
+{
+    protected NamedAssociation<Object> next;
+
+    public NamedAssociationWrapper( NamedAssociation<Object> next )
+    {
+        this.next = next;
+    }
+
+    public NamedAssociation<Object> next()
+    {
+        return next;
+    }
+
+    @Override
+    public Iterator<String> iterator()
+    {
+        return next.iterator();
+    }
+
+    @Override
+    public int count()
+    {
+        return next.count();
+    }
+
+    @Override
+    public boolean containsName( String name )
+    {
+        return next.containsName( name );
+    }
+
+    @Override
+    public boolean put( String name, Object entity )
+    {
+        return next.put( name, entity );
+    }
+
+    @Override
+    public boolean remove( String name )
+    {
+        return next.remove( name );
+    }
+
+    @Override
+    public boolean clear()
+    {
+        return next.clear();
+    }
+
+    @Override
+    public Object get( String name )
+    {
+        return next.get( name );
+    }
+
+    @Override
+    public String nameOf( Object entity )
+    {
+        return next.nameOf( entity );
+    }
+
+    @Override
+    public Map<String, Object> toMap()
+    {
+        return next.toMap();
+    }
+
+    @Override
+    public Stream<Map.Entry<String, EntityReference>> references()
+    {
+        return next.references();
+    }
+
+    @Override
+    public EntityReference referenceOf( String name )
+    {
+        return next.referenceOf( name );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return next.hashCode();
+    }
+
+    @Override
+    @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
+    public boolean equals( Object obj )
+    {
+        return next.equals( obj );
+    }
+
+    @Override
+    public String toString()
+    {
+        return next.toString();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/association/package.html b/core/api/src/main/java/org/apache/polygene/api/association/package.html
new file mode 100644
index 0000000..d478216
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/association/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Association API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/cache/CacheOptions.java b/core/api/src/main/java/org/apache/polygene/api/cache/CacheOptions.java
new file mode 100644
index 0000000..92d087b
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/cache/CacheOptions.java
@@ -0,0 +1,93 @@
+/*
+ *  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.polygene.api.cache;
+
+/**
+ * CacheOptions is a metaInfo class for the Cache system for Entity persistence.
+ * <p>
+ * CacheOptions should be assigned to the Usecase of the UnitOfWork, to give hint on caching to entity stores.
+ * See {@link org.apache.polygene.api.usecase.UsecaseBuilder} on how to set the metaInfo on Usecases.
+ * </p>
+ * <p>
+ * Note that EntityStore implementations are not required to support caching.
+ * </p>
+ */
+public final class CacheOptions
+{
+    public static final CacheOptions ALWAYS = new CacheOptions( true, true, true );
+    public static final CacheOptions NEVER = new CacheOptions( false, false, false );
+
+    private final boolean cacheOnRead;
+    private final boolean cacheOnWrite;
+    private final boolean cacheOnNew;
+
+    /**
+     * Constructor for CacheOptions.
+     *
+     * @param cacheOnRead  if true, give the hint to the Cache system that it may not be a good idea to cache the
+     *                     read values. This is useful when it is known that the read will be over a large set and
+     *                     shouldn't affect the existing cached entities. For instance, when traversing the EntityStore
+     *                     this option is set to false.
+     * @param cacheOnWrite if true, give the hint to the Cache system that it may not be a good idea to cache the
+     *                     entity when the value is updated. If this is false, the cache should be emptied from any
+     *                     cached entity instead of updated. There are few cases when this is useful, and if this is
+     *                     false, it makes sense that the <i>cacheOnRead</i> is also false.
+     * @param cacheOnNew   if true, give the hint to the Cache system that it may not be a good idea to cache a newly
+     *                     created Entity, as it is not likely to be read in the near future. This is useful when
+     *                     batch inserts are being made.
+     */
+    public CacheOptions( boolean cacheOnRead, boolean cacheOnWrite, boolean cacheOnNew )
+    {
+        this.cacheOnRead = cacheOnRead;
+        this.cacheOnWrite = cacheOnWrite;
+        this.cacheOnNew = cacheOnNew;
+    }
+
+    /**
+     * @return if true, give the hint to the Cache system that it may not be a good idea to cache the
+     *         read values. This is useful when it is known that the read will be over a large set and
+     *         shouldn't affect the existing cached entities. For instance, when traversing the EntityStore
+     */
+    public boolean cacheOnRead()
+    {
+        return cacheOnRead;
+    }
+
+    /**
+     * @return if true, give the hint to the Cache system that it may not be a good idea to cache the
+     *         entity when the value is updated. If this is false, the cache should be emptied from any
+     *         cached entity instead of updated. There are few cases when this is useful, and if this is
+     *         false, it makes sense that the <i>cacheOnRead</i> is also false.
+     */
+    public boolean cacheOnWrite()
+    {
+        return cacheOnWrite;
+    }
+
+    /**
+     * @return if true, give the hint to the Cache system that it may not be a good idea to cache a newly
+     *         created Entity, as it is not likely to be read in the near future. This is useful when
+     *         batch inserts are being made.
+     */
+    public boolean cacheOnNew()
+    {
+        return cacheOnNew;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/cache/package.html b/core/api/src/main/java/org/apache/polygene/api/cache/package.html
new file mode 100644
index 0000000..a2109c1
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/cache/package.html
@@ -0,0 +1,43 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Cache API.</h2>
+        <p>
+            The Cache API/SPI is an extension point for Entity Store caching.
+        </p>
+        <p>
+            The API part is only to allow caching options to be passed to the underlying extension in a uniform and
+            standard way. CacheOptions are to be passed as meta info on the optional Cache extension that is specified
+            during assembly phase. Example;
+        </p>
+<pre><code>
+public void assemble( ModuleAssembly module )
+{
+    CacheOptions options = new CacheOptions( true, true, false );
+    module.addServices( EhCacheService.class ).setMetaInfo( options );
+}
+</code></pre>
+        <p>
+            Not all EntityStore implementations use the Cache extension, so check the implementation details of the
+            EntityStore whether the cache extension can bring any benefits or not.
+        </p>
+    </body>
+</html>
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/common/AppliesTo.java b/core/api/src/main/java/org/apache/polygene/api/common/AppliesTo.java
new file mode 100644
index 0000000..9e88103
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/common/AppliesTo.java
@@ -0,0 +1,111 @@
+/*
+ *  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.polygene.api.common;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Fragments that implement InvocationHandler and which should only be applied to methods that have a particular
+ * annotation or implement a known interface should use this annotation.
+ * <p>
+ * &#64;AppliesTo can specify one of;
+ * </p>
+ * <ul>
+ * <li>An annotation,</li>
+ * <li>An interface,</li>
+ * <li>An AppliesToFilter implementation.</li>
+ * </ul>
+ * <p>
+ * Example with annotation:
+ * </p>
+ * <pre><code>
+ *
+ * &#64;AppliesTo( Sessional.class )   // Tells Polygene to apply this concern on methods with &#64;Sessional annotation
+ * public class SessionConcern extends GenericConcern
+ * {
+ *     public Object invoke( Object proxy, Method method, Object[] args )
+ *         throws Throwable
+ *     {
+ *         ... do session stuff ...
+ *     }
+ * }
+ *
+ * &#64;Retention( RetentionPolicy.RUNTIME )
+ * &#64;Target( ElementType.METHOD )
+ * &#64;Documented
+ * &#64;Inherited
+ * public @interface Sessional
+ * {
+ * }
+ *
+ * public class MyMixin
+ *     implements My
+ * {
+ *     &#64;Sessional
+ *     public void doSomethingSessional()
+ *     {
+ *        // ... do your logic wrapped in a session
+ *     }
+ *
+ *     public void doSomethingWithoutSession()
+ *     {
+ *        // ... do stuff that are not wrapped in session.
+ *     }
+ * }
+ *
+ * public interface My
+ * {
+ *     void doSomethingSessional();
+ *
+ *     void doSomethingWithoutSession();
+ * }
+ *
+ * &#64;Concerns( SessionConcern.class )
+ * &#64;Mixins( MyMixin.class )
+ * public interface MyComposite extends My, TransientComposite
+ * {}
+ * </code></pre>
+ * <p>
+ * The doSomethingWithoutSession method do not have the &#64;Sessional annotation, therefore the SessionConcern will
+ * not be placed into the call sequence of these methods, and
+ * vice-versa. The &#64;Sessional annotation can be placed either on the interface method or the implementation
+ * method, depending on whether it is a contract or implementation detail.
+ * </p>
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.TYPE, ElementType.METHOD } )
+@Documented
+public @interface AppliesTo
+{
+    /**
+     * List of interfaces, annotations or AppliesToFilter
+     * implementation classes.
+     * If one of them matches the current element it will be
+     * accepted, so this list can be considered an "or".
+     *
+     * @return array of classes or interfaces to be used by the filter
+     */
+    Class<?>[] value();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/common/AppliesToFilter.java b/core/api/src/main/java/org/apache/polygene/api/common/AppliesToFilter.java
new file mode 100644
index 0000000..8509d14
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/common/AppliesToFilter.java
@@ -0,0 +1,82 @@
+/*
+ *  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.polygene.api.common;
+
+import java.lang.reflect.Method;
+
+/**
+ * Implementations of this interface can be specified in the &#64;AppliesTo.
+ * <p>
+ * AppliesTo filters are one of the driving technologies in Polygene. They allow you to apply fragments (Mixins,
+ * Concerns, SideEffects), often generic ones, depending on the context that they are evaluated under. This
+ * mechanism is heavily used internally in Polygene to achieve many other features.
+ * </p>
+ * <p>
+ * The starting point is the basic use of AppliesToFilter, where the &#64;AppliesTo annotation is given an
+ * AppliesToFilter implementation as an argument, for instance at a Mixin implementation;
+ * </p>
+ * <pre><code>
+ * &#64;AppliesTo( MyAppliesToFilter.class )
+ * public class SomeMixin
+ *     implements InvocationHandler
+ * {
+ *
+ * }
+ *
+ * public class MyAppliesToFilter
+ *     implements AppliesToFilter
+ * {
+ *     public boolean appliesTo( Method method, Class&lt;?&gt; mixin, Class&lt;?&gt; compositeType, Class&lt;?&gt; fragmentClass )
+ *     {
+ *         return method.getName().startsWith( "my" );
+ *     }
+ * }
+ * </code></pre>
+ * <p>
+ * In the case above, the generic mixin will only be applied to the methods that that is defined by the
+ * AppliesToFilter. This is the primary way to define limits on the application of generic fragments, since
+ * especially mixins are rarely applied to all methods.
+ * </p>
+ */
+public interface AppliesToFilter
+{
+    /**
+     * This is an internal AppliesToFilter which is assigned if no other AppliesToFilters are found for a given
+     * fragment.
+     * <p>
+     * There is no reason for user code to use this AppliesToFilter directly, and should be perceived as an
+     * internal class in Polygene.
+     * </p>
+     */
+    AppliesToFilter ALWAYS = ( method, mixin, compositeType, fragmentClass ) -> true;
+
+    /**
+     * Check if the Fragment should be applied or not. Will be call when applied to Mixins, Concerns, SideEffects.
+     *
+     * @param method        method that is invoked
+     * @param mixin         mixin implementation for the method
+     * @param compositeType composite type
+     * @param fragmentClass fragment that is being applies
+     *
+     * @return true if the filter passes, otherwise false
+     */
+    boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/common/ConstructionException.java b/core/api/src/main/java/org/apache/polygene/api/common/ConstructionException.java
new file mode 100644
index 0000000..9697284
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/common/ConstructionException.java
@@ -0,0 +1,58 @@
+/*
+ *  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.polygene.api.common;
+
+/**
+ * Thrown when a Fragment or object could not be instantiated.
+ * This includes, but not be limited to;
+ * <ul>
+ * <li>private constructor.</li>
+ * <li>abstract class for Constraints.</li>
+ * <li>interface instead of a class.</li>
+ * <li>useful constructor missing.</li>
+ * <li>exception thrown in the constructor.</li>
+ * <li>Subclassing of org.apache.polygene.api.property.Property</li>
+ * </ul>
+ * <p>
+ * See the nested exception for additional details.
+ * </p>
+ */
+public class ConstructionException
+    extends RuntimeException
+{
+    public ConstructionException()
+    {
+    }
+
+    public ConstructionException( String message )
+    {
+        super( message );
+    }
+
+    public ConstructionException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+
+    public ConstructionException( Throwable cause )
+    {
+        super( cause );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/common/InvalidApplicationException.java b/core/api/src/main/java/org/apache/polygene/api/common/InvalidApplicationException.java
new file mode 100644
index 0000000..80df92a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/common/InvalidApplicationException.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.api.common;
+
+/**
+ * Thrown when an application is considered to not be constructed properly.
+ * This happens primarily when client code tries to instantiate Composites
+ * and objects which have not been registered in the ModuleAssembly.
+ */
+public class InvalidApplicationException extends RuntimeException
+{
+    public InvalidApplicationException( String string )
+    {
+        super( string );
+    }
+
+    public InvalidApplicationException( String string, Throwable cause )
+    {
+        super( string, cause );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/common/MetaInfo.java b/core/api/src/main/java/org/apache/polygene/api/common/MetaInfo.java
new file mode 100644
index 0000000..c3f3a11
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/common/MetaInfo.java
@@ -0,0 +1,154 @@
+/*
+ *  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.polygene.api.common;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.sideeffect.SideEffects;
+import org.apache.polygene.api.util.Classes;
+
+import static java.util.Arrays.asList;
+import static org.apache.polygene.api.util.Classes.typesOf;
+
+/**
+ * Used to declare and access meta-info.
+ * <p>
+ * <strong>This is effectively an internal class and should not be used directly.</strong>
+ * </p>
+ * <p>
+ * MetaInfo can be set on composites during the assembly phase, a.k.a the bootstrap
+ * process. MetaInfo is any additional data that one wishes to associate at the 'class level' instead of instance
+ * level of a composite declaration.
+ * </p>
+ * <p>
+ * To set the MetaInfo on a Composite, call the {@code setMetaInfo()} methods on the various composite declaration
+ * types, such as;
+ * </p>
+ * <pre><code>
+ * public void assemble( ModuleAssembly module )
+ *     throws AssemblyException
+ * {
+ *     Map&lt;String,String&gt; properties = ...;
+ *     module.services( MyService.class ).setMetaInfo( properties );
+ * }
+ * </code></pre>
+ * <p>
+ * which can later be retrieved by calling the {@code metaInfo()} method on the composite itself. For the example
+ * above that would be;
+ * </p>
+ * <pre><code>
+ * &#64;Mixins(MyServiceMixin.class)
+ * public interface MyService extends ServiceComposite
+ * {
+ *
+ * }
+ *
+ * public abstract class MyServiceMixin
+ *     implements MyService
+ * {
+ *     private Properties props;
+ *
+ *     public MyServiceMixin()
+ *     {
+ *         props = metaInfo( Map.class );
+ *     }
+ * }
+ * </code></pre>
+ */
+public final class MetaInfo
+{
+    private final static Collection<Class> ignored;
+
+    static
+    {
+        ignored = new HashSet<>( 4, 0.8f ); // Optimize size used.
+        ignored.addAll( asList( Mixins.class, Concerns.class, SideEffects.class ) );
+    }
+
+    private final Map<Class<?>, Object> metaInfoMap;
+
+    public MetaInfo()
+    {
+        metaInfoMap = new LinkedHashMap<>();
+    }
+
+    public MetaInfo( MetaInfo metaInfo )
+    {
+        metaInfoMap = new LinkedHashMap<>();
+        metaInfoMap.putAll( metaInfo.metaInfoMap );
+    }
+
+    public void set( Object metaInfo )
+    {
+        if( metaInfo instanceof Annotation )
+        {
+            Annotation annotation = (Annotation) metaInfo;
+            metaInfoMap.put( annotation.annotationType(), metaInfo );
+        }
+        else
+        {
+            Class<?> metaInfoclass = metaInfo.getClass();
+            typesOf( metaInfoclass )
+                .map( Classes.RAW_CLASS )
+                .forEach( type -> metaInfoMap.put( type, metaInfo ) );
+        }
+    }
+
+    public <T> T get( Class<T> metaInfoType )
+    {
+        return metaInfoType.cast( metaInfoMap.get( metaInfoType ) );
+    }
+
+    public <T> void add( Class<T> infoType, T info )
+    {
+        metaInfoMap.put( infoType, info );
+    }
+
+    public MetaInfo withAnnotations( AnnotatedElement annotatedElement )
+    {
+        for( Annotation annotation : annotatedElement.getAnnotations() )
+        {
+            if( !ignored.contains( annotation.annotationType() )
+                && get( annotation.annotationType() ) == null )
+            {
+                set( annotation );
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public String toString()
+    {
+        return metaInfoMap.toString();
+    }
+
+    public void remove( Class serviceFinderClass )
+    {
+        metaInfoMap.remove( serviceFinderClass );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/common/Optional.java b/core/api/src/main/java/org/apache/polygene/api/common/Optional.java
new file mode 100644
index 0000000..049417e
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/common/Optional.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.api.common;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to denote that something is optional.
+ * <ul>
+ * <li>
+ * If applied to a method parameter, then the value is allowed to be null. Default
+ * is that method parameters have to be non-null.
+ * </li>
+ * <li>
+ * If applied to a Property declaration, then the value may be null after construction of
+ * the instance, or may be set to null at a later time.
+ * </li>
+ * <li>
+ * If applied to an injected member field, it is allowed tha none get injected. For instance, an <code>&#64;Optional
+ * &#64;Service</code> would allow a service to not have been declared and the field will be null.
+ * </li>
+ * </ul>
+ * <p>
+ * Optionality is not the default in Polygene, and if injections, property values and parameters in methods are not
+ * non-null, the Polygene runtime will throw an {@link org.apache.polygene.api.constraint.ConstraintViolationException}, indicating
+ * which field/property/parameter in which composite and mixin the problem has been detected.
+ * </p>
+ * <p>
+ * Example;
+ * </p>
+ * <pre><code>
+ * &#64;Optional &#64;Service
+ * MyService service;   // If no MyService instance is declared and visible to this service injection point
+ *                      // the 'service' field will be null.
+ *
+ * &#64;Service
+ * YourService other;   // If no YourService instance is declared and visible to this service injection point
+ *                      // the Polygene runtime will throw a ConstraintViolationException.
+ *
+ * </code></pre>
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD } )
+@Documented
+public @interface Optional
+{
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/common/QualifiedName.java b/core/api/src/main/java/org/apache/polygene/api/common/QualifiedName.java
new file mode 100644
index 0000000..36bf86a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/common/QualifiedName.java
@@ -0,0 +1,263 @@
+/*
+ *  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.polygene.api.common;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.util.Objects;
+
+/**
+ * QualifiedName is a representation of Property names to their full declaration.
+ * <p>
+ * A QualifiedName is created by combining the name of a method and the name of the type that declares the method.
+ * This class also contains many static utility methods to manage QualifiedName instances.
+ * </p>
+ * <p>
+ * <strong>NOTE: Unless you do very generic libraries, entity stores and other extensions that is deeply coupled into
+ * the Polygene runtime, it is very unlikely you will need to use this class directly.</strong>
+ * </p>
+ * <p>
+ * It is also important to notice that the QualifiedName needs to be long-term stable, as the names are written
+ * to persistent storage. So any changes in the formatting <strong>must be made in a backward-compatible manner
+ * </strong>.
+ * </p>
+ * <p>
+ * The QualifiedName has two intrinsic parts, one being the {@code type} and the other the {@code name}. The
+ * {@code type} comes from the class where the QualifiedName originates from and internally kept as a {@link TypeName}
+ * instance. The name is the name from the method name. When the QualifiedName instance is converted to an external
+ * string representation, via the offical and formal {@link #toString()} method, the {@code type} is normalized, i.e.
+ * any dollar characters ($) in the name are replaced by dashes (-), to make them URI friendly.
+ * </p>
+ * <p>
+ * QualifiedName instances are immutable, implements {@link #hashCode()} and {@link #equals(Object)} as a value
+ * object and can safely be used as keys in {@link java.util.Map}.
+ */
+public final class QualifiedName
+    implements Comparable<QualifiedName>
+{
+    private final TypeName typeName;
+    private final String name;
+
+    /**
+     * Creates a QualifiedName from a method.
+     * <p>
+     * This factory method will create a QualifiedName from the Method itself.
+     *
+     * </p>
+     *
+     * @param method Type method that returns a Property, for which the QualifiedName will be representing.
+     *
+     * @return A QualifiedName representing this method.
+     *
+     * @throws NullPointerException If the {@code method} argument passed is null.
+     */
+    public static QualifiedName fromAccessor( AccessibleObject method )
+    {
+        Objects.requireNonNull( method, "method" );
+        return fromClass( ( (Member) method ).getDeclaringClass(), ( (Member) method ).getName() );
+    }
+
+    /**
+     * Creates a QualifiedName instance from the Class and a given name.
+     * <p>
+     * This factory method converts the {@code type} to a {@link TypeName} and appends the given {@code name}.
+     *
+     * @param type The Class that is the base of the QualifiedName.
+     * @param name The qualifier name which will be appended to the base name derived from the {@code type} argument.
+     *
+     * @return A QualifiedName instance representing the {@code type} and {@code name} arguments.
+     *
+     * @throws NullPointerException if any of the two arguments are {@code null}
+     * @throws IllegalArgumentException  if the name string is empty.
+     */
+    public static QualifiedName fromClass( Class type, String name )
+    {
+        return new QualifiedName( TypeName.nameOf( type ), name );
+    }
+
+    /**
+     * Creates a Qualified name from a type as string and a name qualifier.
+     *
+     * @param type The type name as a a string, which must be properly formatted. No checks for correctly formatted
+     *             type name is performed.
+     * @param name The qualifier name which will be appended to the base name derived from the {@code type} argument.
+     *
+     * @return A QualifiedName instance representing the {@code type} and {@code name} arguments.
+     *
+     * @throws NullPointerException if any of the two arguments are {@code null}
+     * @throws IllegalArgumentException  if the name string is empty.
+     */
+    public static QualifiedName fromName( String type, String name )
+    {
+        return new QualifiedName( TypeName.nameOf( type ), name );
+    }
+
+    /**
+     * Creates a QualifiedName from the external string format of QualifiedName.
+     * <p>
+     * This factory method is the reverse of {@link QualifiedName#toString() }  method, and creates a new QualifiedName
+     * instance from the string representation of the QualifiedName.
+     * </p>
+     *
+     * @param fullQualifiedName The QualifiedName external string representation to be converted back into a QualifiedName
+     *                      instance.
+     *
+     * @return The QualifiedName instance represented by the {@code qualifiedName} argument.
+     *
+     * @throws NullPointerException If the {@code qualifiedName} argument is null
+     * @throws IllegalArgumentException If the {@code qualifiedName} argument has wrong format.
+     */
+    public static QualifiedName fromFQN( String fullQualifiedName )
+    {
+        Objects.requireNonNull( fullQualifiedName, "qualifiedName" );
+        int idx = fullQualifiedName.lastIndexOf( ":" );
+        if( idx == -1 )
+        {
+            throw new IllegalArgumentException( "Name '" + fullQualifiedName + "' is not a qualified name" );
+        }
+        final String type = fullQualifiedName.substring( 0, idx );
+        final String name = fullQualifiedName.substring( idx + 1 );
+        return new QualifiedName( TypeName.nameOf( type ), name );
+    }
+
+    QualifiedName( TypeName typeName, String name )
+    {
+        Objects.requireNonNull( typeName, "typeName" );
+        Objects.requireNonNull( name, "name" );
+        if( name.isEmpty() ){
+            throw new IllegalArgumentException( "name" );
+        }
+        this.typeName = typeName;
+        this.name = name;
+    }
+
+    /**
+     * Returns the normalized string of the type part of the QualifiedName.
+     *
+     * <p>
+     * The normalized type name means that all dollar ($) characters have been replaced by dashes (-).
+     * </p>
+     *
+     * @return the normalized string of the type part of the QualifiedName.
+     */
+    public String type()
+    {
+        return typeName.normalized();
+    }
+
+    /**
+     * Returns the name component of the QualifiedName.
+     *
+     * @return the name component of the QualifiedName.
+     */
+    public String name()
+    {
+        return name;
+    }
+
+    /**
+     * Returns the URI of the QualifiedName.
+     *
+     * <p>
+     * The URI is the {@link #toNamespace()} followed by the {@code name} component.
+     * <p>
+     *
+     * @return the URI of the QualifiedName.
+     *
+     * @see #toNamespace()
+     */
+    public String toURI()
+    {
+        return toNamespace() + name;
+    }
+
+    /**
+     * Return the URI of the {@link TypeName} component of the QualifiedName.
+     * <p>
+     * The URI of the {@link TypeName} component is in the form of;
+     * </p>
+     * <pre>
+     * "urn:polygene:type:" normalizedClassName
+     * </pre>
+     * <p>
+     * where {@code normalizedClassName} is the fully-qualified class name having had any dollar ($) characters replaced
+     * by URI friendly dashes (-), with a trailing hash (#). Examples;
+     * </p>
+     * <pre>
+     * urn:polygene:type:org.apache.polygene.api.common.QualifiedName#
+     * urn:polygene:type:org.apache.polygene.samples.MyClass-MyInnerClass#
+     * </pre>
+     *
+     * @return the URI of the {@link TypeName} component of the QualifiedName.
+     */
+    public String toNamespace()
+    {
+        return typeName.toURI() + "#";
+    }
+
+    /**
+     * Return the formal and official, long-term stable, external string representation of a QualifiedName.
+     * <p>
+     * This returns the {@link org.apache.polygene.api.common.TypeName#toString()} followed by the {@code name} component.
+     * </p>
+     *
+     * @return the formal and official, long-term stable, external string representation of a QualifiedName.
+     */
+    @Override
+    public String toString()
+    {
+        return typeName + ":" + name;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        QualifiedName that = (QualifiedName) o;
+
+        return name.equals( that.name ) && typeName.equals( that.typeName );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return 31 * typeName.hashCode() + name.hashCode();
+    }
+
+    @Override
+    public int compareTo( QualifiedName other )
+    {
+        final int result = typeName.compareTo( other.typeName );
+        if( result != 0 )
+        {
+            return result;
+        }
+        return name.compareTo( other.name );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/common/TypeName.java b/core/api/src/main/java/org/apache/polygene/api/common/TypeName.java
new file mode 100644
index 0000000..65b935e
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/common/TypeName.java
@@ -0,0 +1,115 @@
+/*
+ *  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.polygene.api.common;
+
+import java.lang.reflect.Type;
+import java.util.Objects;
+import org.apache.polygene.api.util.Classes;
+
+/**
+ * Represents a Type name.
+ */
+public final class TypeName
+    implements Comparable<TypeName>
+{
+    private final String name;
+
+    public static TypeName nameOf( Class type )
+    {
+        Objects.requireNonNull( type, "type" );
+        return new TypeName( type.getName() );
+    }
+
+    public static TypeName nameOf( Type type )
+    {
+        return nameOf( Classes.RAW_CLASS.apply( type ) );
+    }
+
+    public static TypeName nameOf( String typeName )
+    {
+        return new TypeName( typeName );
+    }
+
+    private TypeName( String name )
+    {
+        Objects.requireNonNull( name, "name" );
+        if( name.isEmpty() )
+        {
+            throw new IllegalArgumentException( "name was empty" );
+        }
+        this.name = name;
+    }
+
+    public String normalized()
+    {
+        return Classes.normalizeClassToURI( name );
+    }
+
+    public String toURI()
+    {
+        return Classes.toURI( name );
+    }
+
+    public String name()
+    {
+        return name;
+    }
+
+    @Override
+    public String toString()
+    {
+        return name;
+    }
+
+    public boolean isClass( final Class<?> type )
+    {
+        return type.getName().equals( name );
+    }
+
+    @Override
+    public boolean equals( final Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        final TypeName other = (TypeName) o;
+
+        return name.equals( other.name );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return name.hashCode();
+    }
+
+    @Override
+    public int compareTo( final TypeName typeName )
+    {
+        return this.name.compareTo( typeName.name );
+    }
+}
+
diff --git a/core/api/src/main/java/org/apache/polygene/api/common/UseDefaults.java b/core/api/src/main/java/org/apache/polygene/api/common/UseDefaults.java
new file mode 100644
index 0000000..bf8f5eb
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/common/UseDefaults.java
@@ -0,0 +1,92 @@
+/*
+ *  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.polygene.api.common;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to denote that the initial value of a Property will be the default value for the type if none is
+ * specified during construction.
+ * <p>
+ * These are the default values used for various types:
+ * </p>
+ * <pre>
+ * Byte: 0
+ * Short: 0
+ * Character: 0
+ * Integer: 0
+ * Long: 0L
+ * Double: 0.0d
+ * Float: 0.0f
+ * Boolean: false
+ * String: ""
+ * List: empty java.util.ArrayList
+ * Set: empty java.util.HashSet
+ * Collection: empty java.util.ArrayList
+ * enum: first declared value
+ * </pre>
+ * <p>
+ * If this annotation is not used, the property will be set to null, and unless {@code &#64;Optional} is declared
+ * is not allowed.
+ * </p>
+ * <p>
+ * The <code>&#64;UseDefaults</code> annotation can also have a value in its declaration. This value is used,
+ * unless it is overridden in the assembly (see below). Java does not support generic types of annotation values,
+ * so it accepts String values, which are deserialized from JSON using the Serialization SPI. This allows
+ * for (albeit somewhat tedious) any object type to have a default value declared on it. If the property type is
+ * String, then no value deserialization is done.
+ * </p>
+ * <p>
+ * It is also possible to change the default values for Composites during the assembly. This is done by calling the
+ * {@code org.apache.polygene.bootstrap.ModuleAssembly#forMixin(Class)} method.
+ * </p>
+ * <p>
+ * Example;
+ * Let's assume that we have the following mixin type;
+ *
+ * <pre><code>
+ * public interface SomeType
+ * {
+ *     &#64;UseDefaults
+ *     Property&lt;String&gt; someValue();
+ * }
+ * </code></pre>
+ * And that we want to have {@code someValue()} to be initialized to "&lt;unknown&gt;" instead of the empty string.
+ * Then we need to declare the default for that with the following in the assembler.
+ * <pre><code>
+ * public void assemble( ModuleAssembly module )
+ * {
+ *     module.forMixin( SomeType.class ).declareDefaults().someValue().set( "&lt;unknown&gt;" );
+ * }
+ * }
+ * </code></pre>
+ */
+@SuppressWarnings( "JavadocReference" )
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.METHOD, ElementType.FIELD } )
+@Documented
+public @interface UseDefaults
+{
+    String value() default "";
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/common/Visibility.java b/core/api/src/main/java/org/apache/polygene/api/common/Visibility.java
new file mode 100644
index 0000000..6120143
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/common/Visibility.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.api.common;
+
+/**
+ * Visibility is a core concept in the Polygene structure system. It defines the locale of composites and objects, i.e.
+ * how far they can be 'seen' and therefor be used.
+ * <p>
+ * When a Composite or Object is declared in the assembly phase, and no visibility is set, only other
+ * composites/objects within the same module can use that declaration. For a declared composite/object to be usable
+ * from other modules a higher visibility must be set, either that the Composite/Object can be used by others within
+ * the same Layer, or even to be used by those in the layer above.
+ * </p>
+ */
+public enum Visibility
+{
+    /**
+     * Artifact is visible only in the declaring module (default)
+     */
+    module,
+    /**
+     * Artifact is visible to all modules in the same layer
+     */
+    layer,
+    /**
+     * Artifact is visible to other modules in the same layer and any modules in extending layers
+     */
+    application
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/common/package.html b/core/api/src/main/java/org/apache/polygene/api/common/package.html
new file mode 100644
index 0000000..38a7a39
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/common/package.html
@@ -0,0 +1,84 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Common API.</h2>
+        <p>
+            The Common API package is a collection of really low-level types needed at the core of the Polygene™ Runtime. It is also
+            a collection of types that are not particularly cohesive, and effectively this package contains the loose ends
+            that does not belong elsewhere.
+        </p>
+        <p>
+            In this package, you can safely ignore the following classes;
+        </p>
+        <ul>
+            <li>MetaInfo</li>
+            <li>QualifiedName</li>
+            <li>TypeName</li>
+        </ul>
+        <p>UNLESS you are into deep integration into the Polygene™ Runtime.</p>
+
+        <h3>&#64;AppliesTo and AppliesToFilter</h3>
+        <p>
+            This tandem of interface + annotation are primarily used for Generic Fragments, to indicate which methods on the
+            interface the fragment should be applied to.
+        </p>
+
+        <h3>&#64;Optional</h3>
+        <p>
+            In Polygene™, method arguments, property values and injected fields are not allowed to be null by default. To allow
+            any of these to be null, i.e. undeclared, it is required that the argument, field or method is marked with the
+            &#64;Optional annotation.
+        </p>
+
+        <h3>&#64;UseDefaults</h3>
+        <p>
+            Since null is not allowed without the &#64;Optional annotation, it can sometimes by tedious to initialize all
+            the property values. And the &#64;UseDefaults annotation allows us to declare that Polygene™ should set the Property
+            to a default value. These are either the pre-defined ones, or can be set per property declaration during the
+            assembly.
+        </p>
+
+        <h3>&#64;Visibility</h3>
+        <p>
+            Visibility is another innovative concept in Polygene™, which leverage the structure system (Application, Layer, Module)
+            to limit the 'reach' when requesting composites and objects. The Visibility is declared per Composite/Object,
+            preferably in the most restrictive mode possible, and the visibility resolver will ensure a predictable resolution
+            algorithm;
+        </p>
+        <ol>
+            <li>Search the module of the caller first. If one and only one composite type fulfilling the request is available
+                return that to the caller. If two or more are found, throw an AmbiguousTypeException. If no composite found
+                continue to the next step.
+            </li>
+            <li>Search all modules in the Layer of the caller for composite that has a declaration other than
+                <code>Visibility.module</code>. If one and only one composite type fulfilling the request is available
+                return that to the caller. If two or more are found, throw an AmbiguousTypeException. If no composite found
+                continue to the next step.
+            </li>
+            <li>Search all modules in the Layer(s) (if any) directly below of the caller for composite that has a declaration of
+                <code>Visibility.application</code>. If one and only one composite type fulfilling the request is available
+                return that to the caller. If two or more are found, throw an AmbiguousTypeException. If no composite found
+                continue to the next step.
+            </li>
+            <li>Throw an NoSuchCompositeException (or related) exception.</li>
+        </ol>
+    </body>
+</html>
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/AmbiguousTypeException.java b/core/api/src/main/java/org/apache/polygene/api/composite/AmbiguousTypeException.java
new file mode 100644
index 0000000..e84bf44
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/AmbiguousTypeException.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.api.composite;
+
+/**
+ * This Exception is thrown when more than one Composite implements a MixinType
+ * that one tries to use to create a Composite instance from.
+ * <p>
+ * For instance;
+ * </p>
+ * <pre><code>
+ * public interface AbcComposite extends TransientComposite, Abc
+ * {}
+ *
+ * public interface DefComposite extends TransientComposite, Def
+ * {}
+ *
+ * public interface Abc
+ * {}
+ *
+ * public interface Def extends Abc
+ * {}
+ *
+ *
+ * TransientBuilder cb = factory.newTransientBuilder( Abc.class );
+ * </code></pre>
+ * <p>
+ * In the code above, both the AbcComposite and DefComposite implement Abc, and therefore
+ * the <code>newTransientBuilder</code> method can not unambiguously figure out which
+ * one is intended.
+ * </p>
+ */
+public class AmbiguousTypeException extends RuntimeException
+{
+    public AmbiguousTypeException( String message )
+    {
+        super( message );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/Composite.java b/core/api/src/main/java/org/apache/polygene/api/composite/Composite.java
new file mode 100644
index 0000000..42f5e77
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/Composite.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.api.composite;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.PropertyMixin;
+
+/**
+ * Base Composite interface.
+ * <p>
+ * All Composite objects must implement this interface. Let the
+ * Composite interface extend this one. An implementation will be provided
+ * by the framework.
+ * </p>
+ * <p>
+ * Properties and associations are handled by default.
+ * </p>
+ */
+@Mixins( { PropertyMixin.class } )
+public interface Composite
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/CompositeContext.java b/core/api/src/main/java/org/apache/polygene/api/composite/CompositeContext.java
new file mode 100644
index 0000000..6c32c81
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/CompositeContext.java
@@ -0,0 +1,84 @@
+/*
+ *  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.polygene.api.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.stream.Stream;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+
+/**
+ * Thread-associated composites. This is basically a ThreadLocal which maintains a reference
+ * to a TransientComposite instance for each thread. This can be used to implement various context
+ * patterns without having to pass the context explicitly as a parameter to methods.
+ */
+public class CompositeContext<T extends TransientComposite>
+    extends ThreadLocal<T>
+{
+    private ModuleDescriptor module;
+    private Class<T> type;
+
+    public CompositeContext( ModuleDescriptor module, Class<T> type )
+    {
+        this.module = module;
+        this.type = type;
+    }
+
+    @Override
+    protected T initialValue()
+    {
+        return module.instance().newTransient( type );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    public T proxy()
+    {
+        TransientComposite composite = get();
+
+        Stream<Class<?>> types = PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF.apply( composite ).types();
+        return (T) Proxy.newProxyInstance(
+            composite.getClass().getClassLoader(),
+            types.toArray( Class[]::new ),
+            new ContextInvocationhandler() );
+    }
+
+    private class ContextInvocationhandler
+        implements InvocationHandler
+    {
+
+        @Override
+        public Object invoke( Object object, Method method, Object[] objects )
+            throws Throwable
+        {
+            try
+            {
+                return method.invoke( get(), objects );
+            }
+            catch( InvocationTargetException e )
+            {
+                throw e.getTargetException();
+            }
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/CompositeDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/composite/CompositeDescriptor.java
new file mode 100644
index 0000000..bd5d65e
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/CompositeDescriptor.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.api.composite;
+
+import java.util.stream.Stream;
+
+/**
+ * Composite Descriptor.
+ */
+public interface CompositeDescriptor
+    extends ModelDescriptor
+{
+    Class<?> primaryType();
+
+    Stream<Class<?>> mixinTypes();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/CompositeInstance.java b/core/api/src/main/java/org/apache/polygene/api/composite/CompositeInstance.java
new file mode 100644
index 0000000..52e8759
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/CompositeInstance.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.api.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.structure.MetaInfoHolder;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.HasTypes;
+
+/**
+ * Composite Instance.
+ */
+public interface CompositeInstance
+    extends InvocationHandler, CompositeInvoker, HasTypes, MetaInfoHolder
+{
+    <T> T proxy();
+
+    <T> T newProxy( Class<T> mixinType )
+        throws IllegalArgumentException;
+
+    ModuleDescriptor module();
+
+    CompositeDescriptor descriptor();
+
+    StateHolder state();
+
+    static CompositeInstance compositeInstanceOf( Composite composite )
+    {
+        InvocationHandler handler = Proxy.getInvocationHandler( composite );
+        return (CompositeInstance) handler;
+    }
+
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/CompositeInvoker.java b/core/api/src/main/java/org/apache/polygene/api/composite/CompositeInvoker.java
new file mode 100644
index 0000000..7cf6fe5
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/CompositeInvoker.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.api.composite;
+
+import java.lang.reflect.Method;
+
+/**
+ * Composite method invoker.
+ * <p>
+ * All composites must implement this interface. Methods that are invoked
+ * may reside either in the public Composite interface or in any internal mixins.
+ * </p>
+ * <p>
+ * <strong><i>NOTE:</i></strong>Client code should never use method in this class. We have not been able to hide this
+ * from client code, but IF we find a way to do, this interface may disappear.
+ * </p>
+ */
+public interface CompositeInvoker
+{
+
+    Object invokeComposite( Method method, Object[] args )
+        throws Throwable;
+
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/ConstructorDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/composite/ConstructorDescriptor.java
new file mode 100644
index 0000000..dd09eae
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/ConstructorDescriptor.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.api.composite;
+
+import java.lang.reflect.Constructor;
+
+/**
+ * Composite constructor descriptor.
+ */
+public interface ConstructorDescriptor
+{
+    Constructor<?> constructor();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/DecoratorMixin.java b/core/api/src/main/java/org/apache/polygene/api/composite/DecoratorMixin.java
new file mode 100644
index 0000000..1707f3e
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/DecoratorMixin.java
@@ -0,0 +1,106 @@
+/*
+ *  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.polygene.api.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import org.apache.polygene.api.injection.scope.Uses;
+
+/**
+ * Generic decorator mixin that allows a Composite to wrap
+ * any other Composite as long as they share an interface.
+ * <p>
+ * Can be used to effectively implement
+ * singleton mixins, since the decorated object can be shared between
+ * many instances.
+ * </p>
+ */
+public class DecoratorMixin
+    implements InvocationHandler
+{
+    private Object delegate;
+
+    public DecoratorMixin( @Uses Object delegate )
+    {
+        if( delegate instanceof Class )
+        {
+            Thread.dumpStack();
+        }
+        this.delegate = delegate;
+    }
+
+    @Override
+    public Object invoke( Object object, Method method, Object[] args )
+        throws Throwable
+    {
+        if( delegate instanceof InvocationHandler )
+        {
+            InvocationHandler handler = (InvocationHandler) delegate;
+            return handler.invoke( object, method, args );
+        }
+        else
+        {
+            try
+            {
+                return method.invoke( delegate, args );
+            }
+            catch( InvocationTargetException e )
+            {
+                throw e.getCause();
+            }
+            catch( IllegalArgumentException e )
+            {
+                String message = constructMessage( method, args );
+                throw new IllegalArgumentException( message, e );
+            }
+        }
+    }
+
+    private String constructMessage( Method method, Object[] args )
+    {
+        StringBuilder builder = new StringBuilder();
+        builder.append( "\nmethod: " );
+        builder.append( method.getDeclaringClass().getName() );
+        builder.append( "." );
+        builder.append( method.getName() );
+        builder.append( "\ndelegate: " );
+        builder.append( delegate );
+        builder.append( "\ndelegateType: " );
+        builder.append( delegate == null ? "n/a" : delegate.getClass().getName() );
+        builder.append( "\narguments: \n" );
+        for( Object arg : args )
+        {
+            builder.append( "    " );
+            Class argClass = arg.getClass();
+            if( Proxy.isProxyClass( argClass ) )
+            {
+                builder.append( Proxy.getInvocationHandler( arg ).getClass().getName() );
+            }
+            else
+            {
+                builder.append( argClass.getName() );
+            }
+            builder.append( '\n' );
+        }
+        return builder.toString();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/DefaultMethodsFilter.java b/core/api/src/main/java/org/apache/polygene/api/composite/DefaultMethodsFilter.java
new file mode 100644
index 0000000..5c6a299
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/DefaultMethodsFilter.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.api.composite;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesToFilter;
+
+/**
+ * Filter Default Interface Methods to apply a generic fragment.
+ */
+public class DefaultMethodsFilter
+    implements AppliesToFilter
+{
+    @Override
+    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> modifierClass )
+    {
+        return method.isDefault();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/DependencyDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/composite/DependencyDescriptor.java
new file mode 100644
index 0000000..ec87e2c
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/DependencyDescriptor.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.api.composite;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+/**
+ * Composite dependency descriptor.
+ */
+public interface DependencyDescriptor
+{
+    Annotation injectionAnnotation();
+
+    Type injectionType();
+
+    Class<?> injectedClass();
+
+    Class<?> rawInjectionType();
+
+    boolean optional();
+
+    Annotation[] annotations();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/InjectedFieldDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/composite/InjectedFieldDescriptor.java
new file mode 100644
index 0000000..ce88a68
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/InjectedFieldDescriptor.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.api.composite;
+
+import java.lang.reflect.Field;
+
+/**
+ * Composite injected field descriptor.
+ */
+public interface InjectedFieldDescriptor
+{
+    Field field();
+
+    DependencyDescriptor dependency();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/InjectedMethodDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/composite/InjectedMethodDescriptor.java
new file mode 100644
index 0000000..0ad4f70
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/InjectedMethodDescriptor.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.api.composite;
+
+import java.lang.reflect.Method;
+
+/**
+ * Composite injected method descriptor.
+ */
+public interface InjectedMethodDescriptor
+{
+    Method method();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/InjectedParametersDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/composite/InjectedParametersDescriptor.java
new file mode 100644
index 0000000..5361575
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/InjectedParametersDescriptor.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.api.composite;
+
+/**
+ * Composite constructors and method injected parameters descriptor.
+ */
+public interface InjectedParametersDescriptor
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/InvalidCompositeException.java b/core/api/src/main/java/org/apache/polygene/api/composite/InvalidCompositeException.java
new file mode 100644
index 0000000..c7657b3
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/InvalidCompositeException.java
@@ -0,0 +1,136 @@
+/*
+ *  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.polygene.api.composite;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+
+/**
+ * This exception is thrown if a Composite is invalid.
+ */
+public class InvalidCompositeException extends RuntimeException
+{
+    private static boolean aggregateProblems = true;
+    private static ThreadLocal<ArrayList<InvalidCompositeException>> report = ThreadLocal.withInitial( ArrayList::new );
+    private ModuleDescriptor module;
+    private Class<?> primaryType;
+    private Class<?> fragmentClass;
+    private Type valueType;
+    private Member member;
+    private List<Class<?>> types;
+
+    public static void handleInvalidCompositeType( String message, ModuleDescriptor module, Class<?> primaryType,
+                                                   Class<?> fragmentClass, Type valueType, Member member,
+                                                   List<Class<?>> types )
+    {
+        InvalidCompositeException exception = new InvalidCompositeException( message, module, primaryType,
+                                                                             fragmentClass, valueType, member, types );
+        if( aggregateProblems )
+        {
+            report.get().add( exception );
+            return;
+        }
+        throw exception;
+    }
+
+    private InvalidCompositeException( String message, ModuleDescriptor module, Class<?> primaryType,
+                                       Class<?> fragmentClass, Type valueType, Member member, List<Class<?>> types )
+    {
+        super( message );
+        this.module = module;
+        this.primaryType = primaryType;
+        this.fragmentClass = fragmentClass;
+        this.valueType = valueType;
+        this.member = member;
+        this.types = types;
+    }
+
+    @Override
+    public String getMessage()
+    {
+        String typeNames = typesString();
+        String primary = primaryType == null ? "" : "    primary: " + primaryType.toGenericString() + "\n";
+        String methodName = memberString();
+        String message = super.getMessage() == null ? "" : "    message: " + super.getMessage() + "\n";
+        String fragment = fragmentClass == null ? "" : "    fragmentClass: " + fragmentClass.getName() + "\n";
+        String valueType = this.valueType == null ? "" : "    valueType: " + this.valueType.getTypeName() + "\n";
+        String module = this.module == null ? "" : "    layer: " + this.module.layer().name() + "\n    module: "
+                                                   + this.module.name() + "\n";
+        return message + module + primary + fragment + methodName + valueType + typeNames;
+    }
+
+    private String typesString()
+    {
+        if( types == null || types.size() == 0 )
+        {
+            return "";
+        }
+        return "    types: "
+               + types.stream()
+                      .map( Class::getSimpleName )
+                      .collect( Collectors.joining( ",", "[", "]" ) )
+               + "\n";
+    }
+
+    private String memberString()
+    {
+        if( member == null )
+        {
+            return "";
+        }
+        if( member instanceof Method )
+        {
+            Method method = (Method) member;
+            String parameters = Arrays.stream( method.getParameters() )
+                                      .map( p -> p.getType().getSimpleName() + " " + p.getName() )
+                                      .collect( Collectors.joining( ", ", "(", ")" ) );
+            return "    method: " + method.getReturnType().getSimpleName() + " " + method.getName() + parameters + "\n";
+        }
+        if( member instanceof Field )
+        {
+            Field field = (Field) member;
+            return "    field: " + field.getType().getSimpleName() + " " + field.getName() + "\n";
+        }
+        return member.toString();
+    }
+
+    public static String modelReport()
+    {
+        if( report.get().size() > 0 )
+        {
+            String reportText = "\nComposition Problems Report:\n"
+                                + report.get().stream()
+                                        .map( Throwable::getMessage )
+                                        .map( m -> m + "\n--\n" )
+                                        .collect( Collectors.joining() );
+            report.set( new ArrayList<>() );
+            return reportText;
+        }
+        aggregateProblems = false;
+        return null;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/InvalidValueCompositeException.java b/core/api/src/main/java/org/apache/polygene/api/composite/InvalidValueCompositeException.java
new file mode 100644
index 0000000..8c03fb4
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/InvalidValueCompositeException.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.api.composite;
+
+/**
+ * This exception is thrown if a ValueComposite is invalid.
+ */
+public class InvalidValueCompositeException extends RuntimeException
+{
+    public InvalidValueCompositeException( String message )
+    {
+        super( message );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/MethodDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/composite/MethodDescriptor.java
new file mode 100644
index 0000000..f0a991d
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/MethodDescriptor.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.api.composite;
+
+import java.lang.reflect.Method;
+
+/**
+ * Composite Method Descriptor.
+ */
+public interface MethodDescriptor
+{
+    Method method();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/MissingMethodException.java b/core/api/src/main/java/org/apache/polygene/api/composite/MissingMethodException.java
new file mode 100644
index 0000000..a6e5998
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/MissingMethodException.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.api.composite;
+
+/**
+ * This exception is thrown if client code tries to invoke a non-existing Composite method.
+ */
+public class MissingMethodException
+    extends RuntimeException
+{
+    public MissingMethodException( String message )
+    {
+        super( message );
+    }
+
+    public MissingMethodException( String message, NoSuchMethodException e )
+    {
+        super(message,e);
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/ModelDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/composite/ModelDescriptor.java
new file mode 100644
index 0000000..cd7ddcf
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/ModelDescriptor.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.api.composite;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.structure.MetaInfoHolder;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.HasTypes;
+
+/**
+ * Composite ModelDescriptor.
+ */
+public interface ModelDescriptor extends HasTypes, MetaInfoHolder
+{
+    Visibility visibility();
+
+    /** The Module that the Model is declared in.
+     *
+     * @return The Module that this Model was declared in.
+     */
+    ModuleDescriptor module();
+
+    boolean isAssignableTo( Class<?> type );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/NoSuchCompositeException.java b/core/api/src/main/java/org/apache/polygene/api/composite/NoSuchCompositeException.java
new file mode 100644
index 0000000..c3f51bb
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/NoSuchCompositeException.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.api.composite;
+
+import org.apache.polygene.api.common.InvalidApplicationException;
+
+/**
+ * This exception is thrown if client code tries to create a non-existing Composite type.
+ */
+public class NoSuchCompositeException extends InvalidApplicationException
+{
+    private final String compositeType;
+    private final String moduleName;
+    private final String visibleTypes;
+
+    protected NoSuchCompositeException( String metaType, String compositeType, String moduleName, String visibleTypes )
+    {
+        super( "Could not find any visible " + metaType + " of type [" + compositeType + "] in module [" +
+               moduleName + "].\n" + visibleTypes );
+        this.compositeType = compositeType;
+        this.moduleName = moduleName;
+        this.visibleTypes = visibleTypes;
+    }
+
+    public String compositeType()
+    {
+        return compositeType;
+    }
+
+    public String moduleName()
+    {
+        return moduleName;
+    }
+
+    public String visibleTypes()
+    {
+        return visibleTypes;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/NoSuchTransientException.java b/core/api/src/main/java/org/apache/polygene/api/composite/NoSuchTransientException.java
new file mode 100644
index 0000000..6f6bfd7
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/NoSuchTransientException.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.api.composite;
+
+import java.util.stream.Collectors;
+import org.apache.polygene.api.structure.TypeLookup;
+
+/**
+ * This exception is thrown if client code tries to create a non-existing TransientComposite type.
+ */
+public class NoSuchTransientException extends NoSuchCompositeException
+{
+    public NoSuchTransientException( String typeName, String moduleName, TypeLookup typeLookup )
+    {
+        super( "TransientComposite", typeName, moduleName, formatVisibleTypes( typeLookup ) );
+    }
+
+    private static String formatVisibleTypes( TypeLookup typeLookup )
+    {
+        return typeLookup.allTransients()
+            .map(descriptor -> descriptor.primaryType().getName())
+            .collect( Collectors.joining( "\n", "Visible transient types are:\n", "" ) );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/PropertyMapper.java b/core/api/src/main/java/org/apache/polygene/api/composite/PropertyMapper.java
new file mode 100644
index 0000000..acff127
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/PropertyMapper.java
@@ -0,0 +1,633 @@
+/*
+ *  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.polygene.api.composite;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.Period;
+import java.time.ZonedDateTime;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.property.GenericPropertyInfo;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * Transfer java.util.Properties to Composite properties
+ */
+public final class PropertyMapper
+{
+
+    private final static Map<Type, MappingStrategy> STRATEGY;
+
+    static
+    {
+        STRATEGY = new HashMap<>();
+        STRATEGY.put( Integer.class, new IntegerMapper() );
+        STRATEGY.put( Long.class, new LongMapper() );
+        STRATEGY.put( Short.class, new ShortMapper() );
+        STRATEGY.put( Byte.class, new ByteMapper() );
+        STRATEGY.put( String.class, new StringMapper() );
+        STRATEGY.put( Character.class, new CharMapper() );
+        STRATEGY.put( Float.class, new FloatMapper() );
+        STRATEGY.put( Double.class, new DoubleMapper() );
+        STRATEGY.put( LocalDate.class, new LocalDateMapper() );
+        STRATEGY.put( LocalDateTime.class, new LocalDateTimeMapper() );
+        STRATEGY.put( ZonedDateTime.class, new ZonedDateTimeMapper() );
+        STRATEGY.put( OffsetDateTime.class, new OffsetDateTimeMapper() );
+        STRATEGY.put( Instant.class, new InstantMapper() );
+        STRATEGY.put( Duration.class, new DurationMapper() );
+        STRATEGY.put( Period.class, new PeriodMapper() );
+        STRATEGY.put( Boolean.class, new BooleanMapper() );
+        STRATEGY.put( BigDecimal.class, new BigDecimalMapper() );
+        STRATEGY.put( BigInteger.class, new BigIntegerMapper() );
+        STRATEGY.put( Enum.class, new EnumMapper() );
+        STRATEGY.put( Array.class, new ArrayMapper() );
+        STRATEGY.put( Map.class, new MapMapper() );
+        STRATEGY.put( List.class, new ListMapper() );
+        STRATEGY.put( Set.class, new SetMapper() );
+        STRATEGY.put( ValueComposite.class, new ValueCompositeMapper() );
+    }
+
+    /**
+     * Populate the Composite with properties from the given properties object.
+     *
+     * @param props     properties object
+     * @param composite the composite instance
+     *
+     * @throws IllegalArgumentException if properties could not be transferred to composite
+     */
+    public static void map( Properties props, Composite composite )
+        throws IllegalArgumentException
+    {
+        for( Map.Entry<Object, Object> objectObjectEntry : props.entrySet() )
+        {
+            try
+            {
+                String methodName = objectObjectEntry.getKey().toString();
+                Method propertyMethod = composite.getClass().getInterfaces()[ 0 ].getMethod( methodName );
+                Object value = objectObjectEntry.getValue();
+                Type propertyType = GenericPropertyInfo.propertyTypeOf( propertyMethod );
+
+                value = mapToType( composite, propertyType, value.toString() );
+
+                @SuppressWarnings( "unchecked" )
+                Property<Object> property = (Property<Object>) propertyMethod.invoke( composite );
+                property.set( value );
+            }
+            catch( NoSuchMethodException e )
+            {
+                throw new IllegalArgumentException( "Could not find any property named " + objectObjectEntry.getKey() );
+            }
+            catch( IllegalAccessException e )
+            {
+                //noinspection ThrowableInstanceNeverThrown
+                throw new IllegalArgumentException( "Could not populate property named " + objectObjectEntry.getKey(), e );
+            }
+            catch( InvocationTargetException e )
+            {
+                //noinspection ThrowableInstanceNeverThrown
+                String message = "Could not populate property named " + objectObjectEntry.getKey();
+                throw new IllegalArgumentException( message, e );
+            }
+        }
+    }
+
+    @SuppressWarnings( "raw" )
+    private static Object mapToType( Composite composite, Type propertyType, Object value )
+    {
+        final String stringValue = value.toString();
+        MappingStrategy strategy;
+        if( propertyType instanceof Class )
+        {
+            Class type = (Class) propertyType;
+            if( type.isArray() )
+            {
+                strategy = STRATEGY.get( Array.class );
+            }
+            else if( Enum.class.isAssignableFrom( Classes.RAW_CLASS.apply( propertyType ) ) )
+            {
+                strategy = STRATEGY.get( Enum.class );
+            }
+            else
+            {
+                strategy = STRATEGY.get( type );
+            }
+            if( strategy == null ) // If null, try with the ValueComposite Mapper...
+            {
+                strategy = STRATEGY.get( ValueComposite.class );
+            }
+        }
+        else if( propertyType instanceof ParameterizedType )
+        {
+            ParameterizedType type = ( (ParameterizedType) propertyType );
+
+            if( type.getRawType() instanceof Class )
+            {
+                Class clazz = (Class) type.getRawType();
+                if( List.class.isAssignableFrom( clazz ) )
+                {
+                    strategy = STRATEGY.get( List.class );
+                }
+                else if( Set.class.isAssignableFrom( clazz ) )
+                {
+                    strategy = STRATEGY.get( Set.class );
+                }
+                else if( Map.class.isAssignableFrom( clazz ) )
+                {
+                    strategy = STRATEGY.get( Map.class );
+                }
+                else
+                {
+                    throw new IllegalArgumentException( propertyType + " is not supported." );
+                }
+            }
+            else
+            {
+                throw new IllegalArgumentException( propertyType + " is not supported." );
+            }
+        }
+        else
+        {
+            throw new IllegalArgumentException( propertyType + " is not supported." );
+        }
+
+        if( strategy == null )
+        {
+            throw new IllegalArgumentException( propertyType + " is not supported." );
+        }
+
+        return strategy.map( composite, propertyType, stringValue );
+    }
+
+    /**
+     * Load a Properties object from the given stream, close it, and then populate
+     * the Composite with the properties.
+     *
+     * @param propertyInputStream properties input stream
+     * @param composite           the instance
+     *
+     * @throws IOException if the stream could not be read
+     */
+
+    public static void map( InputStream propertyInputStream, Composite composite )
+        throws IOException
+    {
+        if( propertyInputStream != null )
+        {
+            Properties configProps = new Properties();
+            try
+            {
+                configProps.load( propertyInputStream );
+            }
+            finally
+            {
+                propertyInputStream.close();
+            }
+            map( configProps, composite );
+        }
+    }
+
+    /**
+     * Create Properties object which is backed by the given Composite.
+     *
+     * @param composite the instance
+     *
+     * @return properties instance
+     */
+    public static Properties toJavaProperties( final Composite composite )
+    {
+        return new Properties()
+        {
+            private static final long serialVersionUID = 3550125427530538865L;
+
+            @Override
+            public Object get( Object o )
+            {
+                try
+                {
+                    Method propertyMethod = composite.getClass().getMethod( o.toString() );
+                    Property<?> property = (Property<?>) propertyMethod.invoke( composite );
+                    return property.get();
+                }
+                catch( NoSuchMethodException | IllegalAccessException | InvocationTargetException e )
+                {
+                    return null;
+                }
+            }
+
+            @Override
+            public Object put( Object o, Object o1 )
+            {
+                Object oldValue = get( o );
+
+                try
+                {
+                    Method propertyMethod = composite.getClass().getMethod( o.toString(), Object.class );
+                    propertyMethod.invoke( composite, o1 );
+                }
+                catch( NoSuchMethodException | IllegalAccessException | InvocationTargetException e )
+                {
+                    e.printStackTrace();
+                }
+
+                return oldValue;
+            }
+        };
+    }
+
+    private static void tokenize( String valueString, boolean mapSyntax, TokenizerCallback callback )
+    {
+        char[] data = valueString.toCharArray();
+
+        int oldPos = 0;
+        for( int pos = 0; pos < data.length; pos++ )
+        {
+            char ch = data[ pos ];
+            if( ch == '\"' )
+            {
+                pos = resolveQuotes( valueString, callback, data, pos, '\"' );
+                oldPos = pos;
+            }
+            if( ch == '\'' )
+            {
+                pos = resolveQuotes( valueString, callback, data, pos, '\'' );
+                oldPos = pos;
+            }
+            if( ch == ',' || ( mapSyntax && ch == ':' ) )
+            {
+                String token = new String( data, oldPos, pos - oldPos );
+                callback.token( token );
+                oldPos = pos + 1;
+            }
+        }
+        String token = new String( data, oldPos, data.length - oldPos );
+        callback.token( token );
+    }
+
+    private static int resolveQuotes( String valueString,
+                                      TokenizerCallback callback,
+                                      char[] data,
+                                      int pos, char quote
+    )
+    {
+        boolean found = false;
+        for( int j = pos + 1; j < data.length; j++ )
+        {
+            if( !found )
+            {
+                if( data[ j ] == quote )
+                {
+                    String token = new String( data, pos + 1, j - pos - 1 );
+                    callback.token( token );
+                    found = true;
+                }
+            }
+            else
+            {
+                if( data[ j ] == ',' )
+                {
+                    return j + 1;
+                }
+            }
+        }
+        if( !found )
+        {
+            throw new IllegalArgumentException( "String is not quoted correctly: " + valueString );
+        }
+        return data.length;
+    }
+
+    private interface TokenizerCallback
+    {
+        void token( String token );
+    }
+
+    private interface MappingStrategy
+    {
+        Object map( Composite composite, Type type, String value );
+    }
+
+    private static class StringMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( Composite composite, Type type, String value )
+        {
+            return value;
+        }
+    }
+
+    private static class IntegerMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( Composite composite, Type type, String value )
+        {
+            return new Integer( value.trim() );
+        }
+    }
+
+    private static class FloatMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( Composite composite, Type type, String value )
+        {
+            return new Float( value.trim() );
+        }
+    }
+
+    private static class DoubleMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( Composite composite, Type type, String value )
+        {
+            return new Double( value.trim() );
+        }
+    }
+
+    private static class LongMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( Composite composite, Type type, String value )
+        {
+            return new Long( value.trim() );
+        }
+    }
+
+    private static class ShortMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( Composite composite, Type type, String value )
+        {
+            return new Short( value.trim() );
+        }
+    }
+
+    private static class ByteMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( Composite composite, Type type, String value )
+        {
+            return new Byte( value.trim() );
+        }
+    }
+
+    private static class CharMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( Composite composite, Type type, String value )
+        {
+            return value.trim().charAt( 0 );
+        }
+    }
+
+    private static class BigDecimalMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( Composite composite, Type type, String value )
+        {
+            return new BigDecimal( value.trim() );
+        }
+    }
+
+    private static class BigIntegerMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( Composite composite, Type type, String value )
+        {
+            return new BigInteger( value.trim() );
+        }
+    }
+
+    private static class EnumMapper
+        implements MappingStrategy
+    {
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public Object map( Composite composite, Type type, String value )
+        {
+            return Enum.valueOf( (Class<Enum>) type, value );
+        }
+    }
+
+    private static class LocalDateMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( Composite composite, Type type, String value )
+        {
+            return LocalDate.parse( value.trim() );
+        }
+    }
+
+    private static class LocalDateTimeMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( Composite composite, Type type, String value )
+        {
+            return LocalDateTime.parse( value.trim() );
+        }
+    }
+
+    private static class ZonedDateTimeMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( Composite composite, Type type, String value )
+        {
+            return ZonedDateTime.parse( value.trim() );
+        }
+    }
+
+    private static class OffsetDateTimeMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( Composite composite, Type type, String value )
+        {
+            return OffsetDateTime.parse( value.trim() );
+        }
+    }
+
+    private static class InstantMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( Composite composite, Type type, String value )
+        {
+            return Instant.parse( value.trim() );
+        }
+    }
+
+    private static class DurationMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( Composite composite, Type type, String value )
+        {
+            return Duration.parse( value.trim() );
+        }
+    }
+
+    private static class PeriodMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( Composite composite, Type type, String value )
+        {
+            return Period.parse( value.trim() );
+        }
+    }
+
+    private static class ValueCompositeMapper
+        implements MappingStrategy
+    {
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public Object map( Composite composite, Type type, String value )
+        {
+            return PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF.apply( composite )
+                .module()
+                .instance()
+                .newValueFromSerializedState( (Class<Object>) type, value );
+        }
+    }
+
+    private static class ArrayMapper
+        implements MappingStrategy
+    {
+        @Override
+        @SuppressWarnings( { "raw", "unchecked" } )
+        public Object map( final Composite composite, Type type, String value )
+        {
+            final Class arrayType = ( (Class) type ).getComponentType();
+            final ArrayList result = new ArrayList();
+            tokenize( value, false, token -> result.add( mapToType( composite, arrayType, token ) ) );
+            return result.toArray( (Object[]) Array.newInstance( arrayType, result.size() ) );
+        }
+    }
+
+    private static class BooleanMapper
+        implements MappingStrategy
+    {
+        @Override
+        public Object map( final Composite composite, Type type, String value )
+        {
+            return Boolean.valueOf( value.trim() );
+        }
+    }
+
+    private static class ListMapper
+        implements MappingStrategy
+    {
+        @Override
+        @SuppressWarnings( { "raw", "unchecked" } )
+        public Object map( final Composite composite, Type type, String value )
+        {
+            final Type dataType = ( (ParameterizedType) type ).getActualTypeArguments()[ 0 ];
+            final Collection result = new ArrayList();
+            tokenize( value, false, token -> result.add( mapToType( composite, dataType, token ) ) );
+            return result;
+        }
+    }
+
+    private static class SetMapper
+        implements MappingStrategy
+    {
+        @Override
+        @SuppressWarnings( { "raw", "unchecked" } )
+        public Object map( final Composite composite, Type type, String value )
+        {
+            final Type dataType = ( (ParameterizedType) type ).getActualTypeArguments()[ 0 ];
+            final Collection result = new HashSet();
+            tokenize( value, false, token -> result.add( mapToType( composite, dataType, token ) ) );
+            return result;
+        }
+    }
+
+    private static class MapMapper
+        implements MappingStrategy
+    {
+        @Override
+        @SuppressWarnings( { "raw", "unchecked" } )
+        public Object map( final Composite composite, Type generictype, String value )
+        {
+            ParameterizedType type = (ParameterizedType) generictype;
+            final Type keyType = type.getActualTypeArguments()[ 0 ];
+            final Type valueType = type.getActualTypeArguments()[ 0 ];
+            final Map result = new HashMap();
+            tokenize( value, true, new TokenizerCallback()
+            {
+                boolean keyArrivingNext = true;
+                String key;
+
+                @Override
+                public void token( String token )
+                {
+                    if( keyArrivingNext )
+                    {
+                        key = token;
+                        keyArrivingNext = false;
+                    }
+                    else
+                    {
+                        result.put( mapToType( composite, keyType, key ), mapToType( composite, valueType, token ) );
+                        keyArrivingNext = true;
+                    }
+                }
+            } );
+            return result;
+        }
+    }
+
+    private PropertyMapper()
+    {
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/StateDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/composite/StateDescriptor.java
new file mode 100644
index 0000000..20c07c2
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/StateDescriptor.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.api.composite;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.property.PropertyDescriptor;
+
+/**
+ * Composite State Descriptor.
+ */
+public interface StateDescriptor
+{
+    PropertyDescriptor findPropertyModelByName( String name )
+        throws IllegalArgumentException;
+
+    PropertyDescriptor findPropertyModelByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException;
+
+    Stream<? extends PropertyDescriptor> properties();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/StatefulAssociationCompositeDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/composite/StatefulAssociationCompositeDescriptor.java
new file mode 100644
index 0000000..88a1bf1
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/StatefulAssociationCompositeDescriptor.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.api.composite;
+
+import org.apache.polygene.api.association.AssociationStateDescriptor;
+import org.apache.polygene.api.type.StatefulAssociationValueType;
+
+/**
+ * Stateful Association Composite Descriptor.
+ */
+public interface StatefulAssociationCompositeDescriptor extends StatefulCompositeDescriptor
+{
+    StatefulAssociationValueType<?> valueType();
+
+    @Override
+    AssociationStateDescriptor state();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/StatefulCompositeDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/composite/StatefulCompositeDescriptor.java
new file mode 100644
index 0000000..42cdcb3
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/StatefulCompositeDescriptor.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.api.composite;
+
+/**
+ * Stateful Composite Descriptor.
+ */
+public interface StatefulCompositeDescriptor
+{
+    StateDescriptor state();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/TransientBuilder.java b/core/api/src/main/java/org/apache/polygene/api/composite/TransientBuilder.java
new file mode 100644
index 0000000..76e755a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/TransientBuilder.java
@@ -0,0 +1,74 @@
+/*
+ *  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.polygene.api.composite;
+
+import org.apache.polygene.api.common.ConstructionException;
+
+/**
+ * TransientBuilders are used to instantiate TransientComposites. They can be acquired from
+ * {@link TransientBuilderFactory#newTransientBuilder(Class)} and allows the client
+ * to provide additional settings before instantiating the TransientComposite.
+ *
+ * @param <T> Transient type
+ */
+public interface TransientBuilder<T>
+{
+    /**
+     * Provide objects that can be injected into mixins that has the @Uses
+     * dependency injection annotation.
+     *
+     * @param usedObjects The objects that can be injected into mixins.
+     *
+     * @return the transient builder instance
+     *
+     * @see org.apache.polygene.api.injection.scope.Uses
+     */
+    TransientBuilder<T> use( Object... usedObjects );
+
+    /**
+     * Get a representation of the state for the new Composite.
+     * It is possible to access and update properties and associations,
+     * even immutable ones since the builder represents the initial state.
+     *
+     * @return a proxy implementing the Composite type
+     */
+    T prototype();
+
+    /**
+     * Get a representation of the state of the given type for the new Composite.
+     * This is primarily used if you want to provide state for a private mixin type.
+     *
+     * @param <K> Mixin type
+     * @param mixinType the mixin which you want to provide state for
+     *
+     * @return a proxy implementing the given mixin type
+     */
+    <K> K prototypeFor( Class<K> mixinType );
+
+    /**
+     * Create a new Composite instance.
+     *
+     * @return a new Composite instance
+     *
+     * @throws ConstructionException thrown if it was not possible to instantiate the Composite
+     */
+    T newInstance()
+        throws ConstructionException;
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/TransientBuilderFactory.java b/core/api/src/main/java/org/apache/polygene/api/composite/TransientBuilderFactory.java
new file mode 100644
index 0000000..5656c71
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/TransientBuilderFactory.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.api.composite;
+
+import org.apache.polygene.api.common.ConstructionException;
+
+/**
+ * This factory creates TransientComposites and the TransientBuilders.
+ *
+ * TransientComposite instances are very flexible in what it can reference, but are restricted in where they
+ * can be used. So, TransientComposites are mainly recommended where Values, Entities and Services can not be used,
+ * but they can also not be used to store state, be serialized across a network or have automatic equals/hashCode
+ * calculations.
+ */
+public interface TransientBuilderFactory
+{
+    /**
+     * Create a builder for creating new TransientComposites that implements the given TransientComposite type.
+     *
+     * @param <T> Transient type
+     * @param mixinType an interface that describes the TransientComposite to be instantiated
+     *
+     * @return a TransientBuilder for creation of TransientComposites implementing the interface
+     *
+     * @throws NoSuchTransientException if no composite extending the mixinType has been registered
+     */
+    <T> TransientBuilder<T> newTransientBuilder( Class<T> mixinType )
+        throws NoSuchTransientException;
+
+    /**
+     * Instantiate a TransientComposite of the given type.
+     *
+     * @param <T> Transient type
+     * @param mixinType the TransientComposite type to instantiate
+     * @param uses The objects that can be injected into mixins
+     *
+     * @return a new TransientComposite instance
+     *
+     * @throws NoSuchTransientException if no composite extending the mixinType has been registered
+     * @throws org.apache.polygene.api.common.ConstructionException
+     *                                  if the composite could not be instantiated
+     */
+    <T> T newTransient( Class<T> mixinType, Object... uses )
+        throws NoSuchTransientException, ConstructionException;
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/TransientComposite.java b/core/api/src/main/java/org/apache/polygene/api/composite/TransientComposite.java
new file mode 100644
index 0000000..bcf86fd
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/TransientComposite.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.api.composite;
+
+/**
+ * Transient Composite Type.
+ *
+ * TransientComposites have the following criteria;
+ * <ul>
+ * <li>Does not persist its state, and is not serializable</li>
+ * <li>Can not be referenced from Properties, Associations, ValueComposites nor Entities</li>
+ * <li>Can reference all types</li>
+ * <li>No lifecycle</li>
+ * <li>equals/hashCode is delegated to a single Mixin implementing the methods, like any other method</li>
+ * </ul>
+ */
+public interface TransientComposite
+    extends Composite
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/TransientDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/composite/TransientDescriptor.java
new file mode 100644
index 0000000..e4ce21a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/TransientDescriptor.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.api.composite;
+
+/**
+ * TransientComposite Descriptor.
+ */
+public interface TransientDescriptor
+    extends CompositeDescriptor, StatefulCompositeDescriptor
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/composite/package.html b/core/api/src/main/java/org/apache/polygene/api/composite/package.html
new file mode 100644
index 0000000..4c79ac8
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/composite/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Composite API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/concern/ConcernDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/concern/ConcernDescriptor.java
new file mode 100644
index 0000000..4986bec
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/concern/ConcernDescriptor.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.api.concern;
+
+/**
+ * Concern descriptor.
+ */
+public interface ConcernDescriptor
+{
+    Class modifierClass();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/concern/ConcernOf.java b/core/api/src/main/java/org/apache/polygene/api/concern/ConcernOf.java
new file mode 100644
index 0000000..e872308
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/concern/ConcernOf.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.api.concern;
+
+import org.apache.polygene.api.concern.internal.ConcernFor;
+
+/**
+ * Base class for Concerns. It introduces a typed "next" pointer
+ * that Concerns can use to invoke the next Concern (or mixin) in
+ * the chain.
+ * <p>
+ * Generic Concerns should subclass {@link GenericConcern} instead.
+ * </p>
+ * <p>
+ * Concerns implementations must be thread-safe in their implementation,
+ * as multiple threads may share instances.
+ * </p>
+ */
+public abstract class ConcernOf<T>
+{
+    /**
+     * The "next" pointer. This points to
+     * the next concern in the chain or the mixin
+     * to be invoked.
+     */
+    final
+    @ConcernFor
+    protected T next = null;
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/concern/Concerns.java b/core/api/src/main/java/org/apache/polygene/api/concern/Concerns.java
new file mode 100644
index 0000000..9c43e0f
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/concern/Concerns.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.api.concern;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation is used by composites and mixins to declare what Concerns
+ * should be applied to the type or specific method.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.TYPE, ElementType.METHOD } )
+@Documented
+public @interface Concerns
+{
+    Class<?>[] value();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/concern/ConcernsDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/concern/ConcernsDescriptor.java
new file mode 100644
index 0000000..7a5ee07
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/concern/ConcernsDescriptor.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.api.concern;
+
+/**
+ * Concerns descriptor.
+ */
+public interface ConcernsDescriptor
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/concern/GenericConcern.java b/core/api/src/main/java/org/apache/polygene/api/concern/GenericConcern.java
new file mode 100644
index 0000000..f96aec0
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/concern/GenericConcern.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.api.concern;
+
+import java.lang.reflect.InvocationHandler;
+
+/**
+ * Base class for generic Concerns. Subclass
+ * and implement the "invoke" method. Use the
+ * "next" field in {@link ConcernOf} to continue the invocation
+ * chain.
+ */
+public abstract class GenericConcern
+    extends ConcernOf<InvocationHandler>
+    implements InvocationHandler
+{
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/concern/internal/ConcernFor.java b/core/api/src/main/java/org/apache/polygene/api/concern/internal/ConcernFor.java
new file mode 100644
index 0000000..1db879c
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/concern/internal/ConcernFor.java
@@ -0,0 +1,67 @@
+/*
+ *  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.polygene.api.concern.internal;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.injection.InjectionScope;
+
+/**
+ * This annotation is required once in each Concern, to mark the
+ * field where the next element in the call sequence should be
+ * injected.
+ * <p>
+ * The type of the field must be of the same type as the Concern
+ * itself, or an InvocationHandler.
+ * </p>
+ * <p>
+ * Example;
+ * </p>
+ * <pre><code>
+ * public interface MyStuff
+ * {
+ *     void doSomething();
+ * }
+ *
+ * public class MyStuffConcern
+ *     implements MyStuff
+ * {
+ *     &#64;ConcernFor MyStuff next;
+ *
+ *     public void doSomething()
+ *     {
+ *         // HERE DO THE MODIFIER STUFF.
+ *
+ *         // Delegate to the underlying mixin/modifier.
+ *         next.doSomething();
+ *     }
+ * }
+ * </code></pre>
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.FIELD, ElementType.PARAMETER } )
+@Documented
+@InjectionScope
+public @interface ConcernFor
+{
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/concern/internal/package.html b/core/api/src/main/java/org/apache/polygene/api/concern/internal/package.html
new file mode 100644
index 0000000..7dcd3b6
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/concern/internal/package.html
@@ -0,0 +1,28 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h1>Internal/Private package for the Concern API.</h1>
+        <p>
+            This is an internal package, and no classes in this package is part of the API and compatibility
+            with these classes will not be attempted.
+        </p>
+    </body>
+</html>
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/concern/package.html b/core/api/src/main/java/org/apache/polygene/api/concern/package.html
new file mode 100644
index 0000000..f9d5d0c
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/concern/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Concern API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/configuration/Configuration.java b/core/api/src/main/java/org/apache/polygene/api/configuration/Configuration.java
new file mode 100644
index 0000000..a7c4dd1
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/configuration/Configuration.java
@@ -0,0 +1,420 @@
+/*
+ *  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.polygene.api.configuration;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.PropertyMapper;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.service.qualifier.ServiceTags;
+import org.apache.polygene.api.serialization.Deserializer;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+/**
+ * Provide Configurations for Services. A Service that wants to be configurable
+ * should inject a reference to Configuration with the Configuration type:
+ * <pre><code>
+ *  * &#64;This Configuration&#60;MyServiceConfiguration&#62; config;
+ * </code></pre>
+ * <p>
+ * where MyServiceConfiguration extends {@link ConfigurationComposite}, which itself is an ordinary
+ * {@link org.apache.polygene.api.entity.EntityComposite}. The Configuration implementation
+ * will either locate an instance of the given Configuration type in the
+ * persistent store using the reference of the Service, or create a new such instance
+ * if one doesn't already exist.
+ * </p>
+ * <p>
+ * If a new Configuration instance is created then it will be populated with properties
+ * from the properties file whose filesystem name is the same as the reference (e.g. "MyService.properties").
+ * If a service is not given a name via the {@code org.apache.polygene.bootstrap.ServiceDeclaration#identifiedBy(String)}, the
+ * name will default to the FQCN of the ServiceComposite type.
+ * </p>
+ * <p>
+ * The Configuration instance can be modified externally just like any other EntityComposite, but
+ * its values will not be updated in the Service until {@link #refresh()} is called. This allows
+ * safe reloads of Configuration state to ensure that it is not reloaded while the Service is handling
+ * a request.
+ * </p>
+ * <p>
+ * The Configuration will be automatically refreshed when the Service is activated by the Polygene runtime.
+ * Any refreshes at other points will have to be done manually or triggered through some other
+ * mechanism.
+ * </p>
+ * <p>
+ * The user configuration entity is part of a long running {@link UnitOfWork}, and to persist changes to it the
+ * {@link #save()} method must be called. No other actions are required. Example;
+ * </p>
+ * <pre><code>
+ *
+ * public interface MyConfiguration extends ConfigurationComposite
+ * {
+ *     Property&lt;Long&gt; timeout();
+ * }
+ *
+ * :
+ *
+ * &#64;This Configuration&lt;MyConfiguration&gt; config;
+ * :
+ * private void setTimeoutConfiguration( long timeout )
+ * {
+ *     config.get().timeout().set( timeout );
+ *     config.save();
+ * }
+ * </code></pre>
+ * <p>
+ * And even if a separate thread is using the {@code timeout()} configuration when this is happening, the
+ * {@link UnitOfWork} isolation will ensure that the other thread is not affected. That thread, on the other hand
+ * will need to do a {@link #refresh()} at an appropriate time to pick up the timeout change. For instance;
+ * </p>
+ * <pre><code>
+ *
+ * &#64;Service InventoryService remoteInventoryService;
+ *
+ * public void restockInventoryItem( InventoryItemId id, int itemCount )
+ * {
+ *     config.refresh();
+ *     long timeout = config.get().timeout().get();
+ *
+ *     remoteInventoryService.restock( id, itemCount, timeout );
+ *
+ *     :
+ *     :
+ * }
+ * </code></pre>
+ *
+ * @param <T> Configuration type
+ */
+@SuppressWarnings( "JavadocReference" )
+@Mixins( Configuration.ConfigurationMixin.class )
+public interface Configuration<T>
+{
+    /**
+     * Retrieves the user configuration instance managed by this Configuration.
+     * <p>
+     * Even if the user configuration is initialized from properties file, the consistency rules of Polygene composites
+     * still applies. If the the properties file is missing a value, then the initialization will fail with a
+     * RuntimeException. If Constraints has been defined, those will need to be satisfied as well. The user
+     * configuration instance returned will fulfill the constraints and consistency normal to all composites, and
+     * can therefor safely be used with additional checks.
+     * </p>
+     *
+     * @return The fully initialized and ready-to-use user configuration instance.
+     */
+    T get();
+
+    /**
+     * Updates the values of the managed user ConfigurationComposite instance from the underlying
+     * {@code org.apache.polygene.spi.entitystore.EntityStore}.  Any modified values in the current user configuration that
+     * has not been saved, via {@link #save()} method, will be lost.
+     */
+    void refresh();
+
+    /**
+     * Persists the modified values in the user configuration instance to the underlying store.
+     */
+    void save();
+
+    /**
+     * Implementation of Configuration.
+     * <p>
+     * This is effectively an internal class in Polygene and should never be used directly by user code.
+     * </p>
+     *
+     * @param <T> Configuration type
+     */
+    class ConfigurationMixin<T>
+        implements Configuration<T>
+    {
+        private T configuration;
+        private UnitOfWork uow;
+
+        @Structure
+        private PolygeneAPI api;
+
+        @This
+        private ServiceComposite me;
+
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @Service
+        private Iterable<ServiceReference<Deserializer>> stateDeserializers;
+
+        public ConfigurationMixin()
+        {
+        }
+
+        @Override
+        public synchronized T get()
+        {
+            if( configuration == null )
+            {
+                Usecase usecase = UsecaseBuilder.newUsecase( "Configuration:" + me.identity().get() );
+                uow = uowf.newUnitOfWork( usecase );
+                try
+                {
+                    configuration = this.findConfigurationInstanceFor( me, uow );
+                }
+                catch( InstantiationException e )
+                {
+                    throw new IllegalStateException( e );
+                }
+            }
+
+            return configuration;
+        }
+
+        @Override
+        public synchronized void refresh()
+        {
+            if( configuration != null )
+            {
+                configuration = null;
+                uow.discard();
+                uow = null;
+            }
+        }
+
+        @Override
+        public void save()
+        {
+            if( uow != null )
+            {
+                try
+                {
+                    uow.complete();
+                    uow = null;
+                }
+                catch( UnitOfWorkCompletionException e )
+                {
+                    // Should be impossible
+                    e.printStackTrace();
+                }
+
+                configuration = null; // Force refresh
+            }
+        }
+
+        @SuppressWarnings( "unchecked" )
+        public <V> V findConfigurationInstanceFor( ServiceComposite serviceComposite, UnitOfWork uow )
+            throws InstantiationException
+        {
+            ServiceDescriptor serviceModel = api.serviceDescriptorFor( serviceComposite );
+
+            V configuration;
+            try
+            {
+                configuration = uow.get( serviceModel.<V>configurationType(), serviceComposite.identity().get() );
+                uow.pause();
+            }
+            catch( NoSuchEntityException | NoSuchEntityTypeException e )
+            {
+                return (V) initializeConfigurationInstance( serviceComposite, uow, serviceModel,
+                                                            serviceComposite.identity().get() );
+            }
+            return configuration;
+        }
+
+        @SuppressWarnings( "unchecked" )
+        private <V extends HasIdentity> V initializeConfigurationInstance( ServiceComposite serviceComposite,
+                                                                           UnitOfWork uow,
+                                                                           ServiceDescriptor serviceModel,
+                                                                           Identity identity
+        )
+            throws InstantiationException
+        {
+            Module module = api.moduleOf( serviceComposite ).instance();
+            Usecase usecase = UsecaseBuilder.newUsecase( "Configuration:" + me.identity().get() );
+            UnitOfWork buildUow = module.unitOfWorkFactory().newUnitOfWork( usecase );
+
+            Class<?> type = api.serviceDescriptorFor( serviceComposite ).types().findFirst().orElse( null );
+            Class<V> configType = serviceModel.configurationType();
+
+            // Check for defaults
+            V config = tryLoadPropertiesFile( buildUow, type, configType, identity );
+            if( config == null )
+            {
+                config = tryLoadJsonFile( buildUow, type, configType, identity );
+                if( config == null )
+                {
+                    config = tryLoadYamlFile( buildUow, type, configType, identity );
+                    if( config == null )
+                    {
+                        config = tryLoadXmlFile( buildUow, type, configType, identity );
+                        if( config == null )
+                        {
+                            try
+                            {
+                                EntityBuilder<V> configBuilder = buildUow.newEntityBuilder(
+                                    serviceModel.<V>configurationType(), identity );
+                                configBuilder.newInstance();
+                            }
+                            catch( ConstraintViolationException e )
+                            {
+                                throw new NoSuchConfigurationException( configType, identity, e );
+                            }
+                        }
+                    }
+                }
+            }
+
+            try
+            {
+                buildUow.complete();
+
+                // Try again
+                return (V) findConfigurationInstanceFor( serviceComposite, uow );
+            }
+            catch( Exception e1 )
+            {
+                InstantiationException ex = new InstantiationException(
+                    "Could not instantiate configuration, and no configuration initialization file was found ("
+                    + identity + ")" );
+                ex.initCause( e1 );
+                throw ex;
+            }
+        }
+
+        private <C, V> V tryLoadPropertiesFile( UnitOfWork buildUow,
+                                                Class<C> compositeType,
+                                                Class<V> configType,
+                                                Identity identity
+        )
+            throws InstantiationException
+        {
+            EntityBuilder<V> configBuilder = buildUow.newEntityBuilder( configType, identity );
+            String resourceName = identity + ".properties";
+            try( InputStream asStream = getResource( compositeType, resourceName ) )
+            {
+                if( asStream != null )
+                {
+                    try
+                    {
+                        PropertyMapper.map( asStream, (Composite) configBuilder.instance() );
+                        return configBuilder.newInstance();
+                    }
+                    catch( IOException e1 )
+                    {
+                        InstantiationException exception = new InstantiationException(
+                            "Could not read underlying Properties file." );
+                        exception.initCause( e1 );
+                        throw exception;
+                    }
+                }
+                return null;
+            }
+            catch( IOException ignored )
+            {
+                return null;
+            }
+        }
+
+        private InputStream getResource( Class<?> type, String resourceName )
+        {
+            // Load defaults from classpath root if available
+            if( type.getResource( resourceName ) == null && type.getResource( "/" + resourceName ) != null )
+            {
+                resourceName = "/" + resourceName;
+            }
+            return type.getResourceAsStream( resourceName );
+        }
+
+        private <C, V extends HasIdentity> V tryLoadJsonFile( UnitOfWork uow,
+                                                              Class<C> compositeType,
+                                                              Class<V> configType,
+                                                              Identity identity
+        )
+        {
+            return readConfig( uow, compositeType, configType, identity, Serialization.Format.JSON, ".json" );
+        }
+
+        private <C, V extends HasIdentity> V tryLoadYamlFile( UnitOfWork uow,
+                                                              Class<C> compositeType,
+                                                              Class<V> configType,
+                                                              Identity identity
+        )
+        {
+            return readConfig( uow, compositeType, configType, identity, Serialization.Format.YAML, ".yaml" );
+        }
+
+        private <C, V extends HasIdentity> V tryLoadXmlFile( UnitOfWork uow,
+                                                             Class<C> compositeType,
+                                                             Class<V> configType,
+                                                             Identity identity
+        )
+        {
+            return readConfig( uow, compositeType, configType, identity, Serialization.Format.XML, ".xml" );
+        }
+
+        private <C, V extends HasIdentity> V readConfig( UnitOfWork uow,
+                                                         Class<C> compositeType,
+                                                         Class<V> configType,
+                                                         Identity identity,
+                                                         String format,
+                                                         String extension
+        )
+        {
+            for( ServiceReference<Deserializer> serializerRef : stateDeserializers )
+            {
+                ServiceTags serviceTags = serializerRef.metaInfo( ServiceTags.class );
+                if( serviceTags.hasTag( format ) )
+                {
+                    String resourceName = identity + extension;
+                    try( InputStream asStream = getResource( compositeType, resourceName ) )
+                    {
+                        if( asStream != null )
+                        {
+                            Deserializer deserializer = serializerRef.get();
+                            V configObject = deserializer.deserialize( uow.module(), configType,
+                                                                       new InputStreamReader( asStream, UTF_8 ) );
+                            return uow.toEntity( configType, configObject );
+                        }
+                    }
+                    catch( IOException ignored ) {}
+                }
+            }
+            return null;
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/configuration/ConfigurationComposite.java b/core/api/src/main/java/org/apache/polygene/api/configuration/ConfigurationComposite.java
new file mode 100644
index 0000000..726664f
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/configuration/ConfigurationComposite.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.api.configuration;
+
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.entity.Queryable;
+
+/**
+ * Services that want to be configurable should have a ConfigurationComposite that contains all the settings.
+ * They are treated as EntityComposites, and are therefore stored in an EntityStore. There will be one instance
+ * per service instance that uses each ConfigurationComposite, and the reference of the entity is the same as that
+ * of the service.
+ */
+@Queryable( false )
+public interface ConfigurationComposite
+    extends HasIdentity, Composite
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/configuration/Enabled.java b/core/api/src/main/java/org/apache/polygene/api/configuration/Enabled.java
new file mode 100644
index 0000000..764ef4e
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/configuration/Enabled.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.api.configuration;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Common configuration for setting whether a service is enabled or not. A disabled service
+ * is not considered to be available. Let your own ConfigurationComposite extend this interface to use.
+ */
+public interface Enabled
+{
+    @UseDefaults
+    Property<Boolean> enabled();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/configuration/NoSuchConfigurationException.java b/core/api/src/main/java/org/apache/polygene/api/configuration/NoSuchConfigurationException.java
new file mode 100644
index 0000000..ed2b3a0
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/configuration/NoSuchConfigurationException.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.api.configuration;
+
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+
+public class NoSuchConfigurationException extends RuntimeException
+{
+    private final Class<? extends HasIdentity> configType;
+    private final Identity identity;
+
+    public NoSuchConfigurationException( Class<? extends HasIdentity> configType,
+                                         Identity identity,
+                                         Exception cause
+    )
+    {
+        super( "No configuration found for '" + identity + "' and configuration " + configType.getName() + " has one or more non-Optional properties.", cause );
+        this.configType = configType;
+        this.identity = identity;
+    }
+
+    public Class<? extends HasIdentity> configType()
+    {
+        return configType;
+    }
+
+    public Identity identity()
+    {
+        return identity;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/configuration/package.html b/core/api/src/main/java/org/apache/polygene/api/configuration/package.html
new file mode 100644
index 0000000..b923bc3
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/configuration/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Configuration API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/constraint/Constraint.java b/core/api/src/main/java/org/apache/polygene/api/constraint/Constraint.java
new file mode 100644
index 0000000..17df997
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/constraint/Constraint.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.api.constraint;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * All Constraints must implement this interface, which is used for each
+ * value validation.
+ */
+public interface Constraint<ANNOTATION extends Annotation, TYPE>
+{
+    /**
+     * For each value or parameter which should be checked this method will be invoked.
+     * If the method returns true the value is valid. If it returns false the value
+     * is considered invalid. When all constraints have been checked a ConstraintViolationException
+     * will be thrown with all the constraint violations that were found.
+     *
+     * @param annotation the annotation to match
+     * @param value      the value to be checked
+     *
+     * @return true if valid, false if invalid
+     */
+    boolean isValid( ANNOTATION annotation, TYPE value );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/constraint/ConstraintDeclaration.java b/core/api/src/main/java/org/apache/polygene/api/constraint/ConstraintDeclaration.java
new file mode 100644
index 0000000..36988ee
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/constraint/ConstraintDeclaration.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.api.constraint;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * All annotations that are used to trigger Constraints must have this annotation.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( ElementType.ANNOTATION_TYPE )
+@Documented
+public @interface ConstraintDeclaration
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/constraint/ConstraintDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/constraint/ConstraintDescriptor.java
new file mode 100644
index 0000000..9c929ef
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/constraint/ConstraintDescriptor.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.api.constraint;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Constraint Descriptor.
+ */
+public interface ConstraintDescriptor
+{
+    Annotation annotation();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/constraint/ConstraintViolation.java b/core/api/src/main/java/org/apache/polygene/api/constraint/ConstraintViolation.java
new file mode 100644
index 0000000..75bbecb
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/constraint/ConstraintViolation.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.api.constraint;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * When a constraint violation has occurred (ie Constraint.isValid has returned false) it
+ * is put in a collection of all violations that have occurred for this value check.
+ */
+public final class ConstraintViolation
+{
+    private String name;
+    private final Annotation constraint;
+    private final Object value;
+
+    public ConstraintViolation( String name, Annotation constraint, Object value )
+    {
+        this.name = name;
+        this.constraint = constraint;
+        this.value = value;
+    }
+
+    public String name()
+    {
+        return name;
+    }
+
+    public Annotation constraint()
+    {
+        return constraint;
+    }
+
+    public Object value()
+    {
+        return value;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/constraint/ConstraintViolationException.java b/core/api/src/main/java/org/apache/polygene/api/constraint/ConstraintViolationException.java
new file mode 100644
index 0000000..a007a11
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/constraint/ConstraintViolationException.java
@@ -0,0 +1,258 @@
+/*
+ *  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.polygene.api.constraint;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Member;
+import java.lang.reflect.Type;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.util.Classes;
+
+import static java.util.stream.Collectors.joining;
+
+/**
+ * This Exception is thrown when there is one or more Constraint Violations in a method
+ * call.
+ * <p>
+ * The Constraint Violations are aggregated per method, and this exception will contain those
+ * violations, together with the Composite instance it happened on as well as the Method that
+ * was invoked. The Exception also has support for localized messages of these violations.
+ * </p>
+ */
+public class ConstraintViolationException extends IllegalArgumentException
+{
+    private final Collection<ConstraintViolation> constraintViolations;
+    private String methodName;
+    private String mixinTypeName;
+    private String instanceToString;
+    private List<? extends Type> instanceTypes;
+
+    public ConstraintViolationException( Composite instance, Member method,
+                                         Collection<ConstraintViolation> constraintViolations
+    )
+    {
+        this( instance.toString(), Classes.interfacesOf( instance.getClass() ), method, constraintViolations );
+    }
+
+    public ConstraintViolationException( String instanceToString,
+                                         Stream<? extends Type> instanceTypes,
+                                         Member method,
+                                         Collection<ConstraintViolation> violations
+    )
+    {
+        this.instanceToString = instanceToString;
+        this.instanceTypes = instanceTypes.collect( Collectors.toList() );
+        mixinTypeName = method.getDeclaringClass().getName();
+        methodName = method.getName();
+        this.constraintViolations = violations;
+    }
+
+    public ConstraintViolationException( Identity identity,
+                                         List<? extends Type> instanceTypes,
+                                         String mixinTypeName,
+                                         String methodName,
+                                         Collection<ConstraintViolation> violations
+    )
+    {
+        this.instanceToString = identity.toString();
+        this.instanceTypes = instanceTypes;
+        this.mixinTypeName = mixinTypeName;
+        this.methodName = methodName;
+        this.constraintViolations = violations;
+    }
+
+    public Collection<ConstraintViolation> constraintViolations()
+    {
+        return constraintViolations;
+    }
+
+    /**
+     * Creates localized messages of all the constraint violations that has occured.
+     * <p>
+     * The key "<code>polygene.constraint.<i><strong>CompositeType</strong></i>.<i><strong>methodName</strong></i></code>"
+     * will be used to lookup the text formatting
+     * pattern from the ResourceBundle, where <strong><code><i>CompositeType</i></code></strong> is the
+     * class name of the Composite where the constraint was violated. If such key does not exist, then the
+     * key &nbsp;"<code>polygene.constraint</code>" will be used, and if that one also doesn't exist, or
+     * the resourceBundle argument is null, then the default patterns will be used;
+     * </p>
+     * <table summary="Localization of constraint vioations.">
+     * <tr><th>Type of Composite</th><th>Pattern used</th></tr>
+     * <tr><td>Composite</td>
+     * <td><code>Constraint Violation in {2}.{3} with constraint {4}, in composite \n{0} of type {1}</code></td>
+     * </tr>
+     * <tr><td>EntityComposite</td>
+     * <td><code>Constraint Violation in {2}.{3} with constraint {4}, in entity {1}[id={0}]</code></td>
+     * </tr>
+     * <tr><td>ServiceComposite</td>
+     * <td><code>Constraint Violation in {2}.{3} with constraint {4}, in service {0}</code></td>
+     * </tr>
+     * </table>
+     * Then format each ConstraintViolation according to such pattern, where the following argument are passed;
+     * <table summary="List of arguments available."><tr><th>Arg</th><th>Value</th></tr>
+     * <tr>
+     * <td>{0}</td>
+     * <td>Composite instance toString()</td>
+     * </tr>
+     * <tr>
+     * <td>{1}</td>
+     * <td>CompositeType class name</td>
+     * </tr>
+     * <tr>
+     * <td>{2}</td>
+     * <td>MixinType class name</td>
+     * </tr>
+     * <tr>
+     * <td>{3}</td>
+     * <td>MixinType method name</td>
+     * </tr>
+     * <tr>
+     * <td>{4}</td>
+     * <td>Annotation toString()</td>
+     * </tr>
+     * <tr>
+     * <td>{5}</td>
+     * <td>toString() of value passed as the argument, or "null" text if argument was null.</td>
+     * </tr>
+     * </table>
+     * <p>
+     * <b>NOTE!!!</b> This class is still under construction and will be modified further.
+     * </p>
+     *
+     * @param bundle The ResourceBundle for Localization, or null if default formatting and locale to be used.
+     *
+     * @return An array of localized messages of the violations incurred.
+     */
+    public String[] localizedMessagesFrom( ResourceBundle bundle )
+    {
+        String pattern = "Constraint violation in {0}.{1} for method ''{3}'' with constraint \"{4}({6})\", for value ''{5}''";
+
+        ArrayList<String> list = new ArrayList<>();
+        for( ConstraintViolation violation : constraintViolations )
+        {
+            Locale locale;
+            if( bundle != null )
+            {
+                try
+                {
+                    pattern = bundle.getString( "polygene.constraint." + mixinTypeName + "." + methodName );
+                }
+                catch( MissingResourceException e1 )
+                {
+                    try
+                    {
+                        pattern = bundle.getString( "polygene.constraint" );
+                    }
+                    catch( MissingResourceException e2 )
+                    {
+                        // ignore. The default pattern will be used.
+                    }
+                }
+                locale = bundle.getLocale();
+            }
+            else
+            {
+                locale = Locale.getDefault();
+            }
+            MessageFormat format = new MessageFormat( pattern, locale );
+
+            Annotation annotation = violation.constraint();
+            String name = violation.name();
+            Object value = violation.value();
+            String classes;
+            if( instanceTypes.size() == 1 )
+            {
+                Type type = instanceTypes.stream().findFirst().get();
+                classes = Classes.RAW_CLASS.apply( type ).getSimpleName();
+            }
+            else
+            {
+                classes = "[" + instanceTypes.stream()
+                    .map( Classes.RAW_CLASS )
+                    .map( Class::getSimpleName ).collect( joining( "," ) ) + "]";
+            }
+            Object[] args = new Object[]
+                {
+                    instanceToString,
+                    classes,
+                    mixinTypeName,
+                    methodName,
+                    annotation.toString(),
+                    "" + value,
+                    name
+                };
+            StringBuffer text = new StringBuffer();
+            format.format( args, text, null );
+            list.add( text.toString() );
+        }
+        String[] result = new String[ list.size() ];
+        list.toArray( result );
+        return result;
+    }
+
+    public String localizedMessage()
+    {
+        String[] messages = localizedMessagesFrom( null );
+        StringBuilder result = new StringBuilder();
+        boolean first = true;
+        for( String message : messages )
+        {
+            if( !first )
+            {
+                result.append( ',' );
+            }
+            first = false;
+            result.append( message );
+        }
+        return result.toString();
+    }
+
+    @Override
+    public String getLocalizedMessage()
+    {
+        return localizedMessage();
+    }
+
+    @Override
+    public String getMessage()
+    {
+        return localizedMessage();
+    }
+
+    public String methodName()
+    {
+        return methodName;
+    }
+
+    public String mixinTypeName()
+    {
+        return mixinTypeName;
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/constraint/Constraints.java b/core/api/src/main/java/org/apache/polygene/api/constraint/Constraints.java
new file mode 100644
index 0000000..e5516a3
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/constraint/Constraints.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.api.constraint;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation is used by composites and mixins to declare what Constraints
+ * can be applied in the Composite.
+ * <p>
+ * Constraints implement the {@link Constraint} interface
+ * </p>
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.TYPE } )
+@Documented
+public @interface Constraints
+{
+    Class<? extends Constraint<?, ?>>[] value();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/constraint/ConstraintsDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/constraint/ConstraintsDescriptor.java
new file mode 100644
index 0000000..8637abe
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/constraint/ConstraintsDescriptor.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.api.constraint;
+
+/**
+ * Constraints Descriptor.
+ */
+public interface ConstraintsDescriptor
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/constraint/Name.java b/core/api/src/main/java/org/apache/polygene/api/constraint/Name.java
new file mode 100644
index 0000000..1ef59c8
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/constraint/Name.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.api.constraint;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation for parameter names. This is used to add extra information for constraint exception.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.PARAMETER } )
+@Documented
+public @interface Name
+{
+    String value();
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/constraint/package.html b/core/api/src/main/java/org/apache/polygene/api/constraint/package.html
new file mode 100644
index 0000000..87e14b7
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/constraint/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Constraint API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/entity/Aggregated.java b/core/api/src/main/java/org/apache/polygene/api/entity/Aggregated.java
new file mode 100644
index 0000000..7db81cd
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/entity/Aggregated.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.api.entity;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks an association as aggregating the referenced Entities
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.METHOD } )
+@Documented
+public @interface Aggregated
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/entity/EntityBuilder.java b/core/api/src/main/java/org/apache/polygene/api/entity/EntityBuilder.java
new file mode 100644
index 0000000..2e31766
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/entity/EntityBuilder.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.api.entity;
+
+import org.apache.polygene.api.common.ConstructionException;
+
+/**
+ * EntityBuilders are used to instantiate EntityComposites. They can be acquired from
+ * {@link org.apache.polygene.api.unitofwork.UnitOfWork#newEntityBuilder(Class)} and allows the client
+ * to provide additional settings before instantiating the Composite.
+ *
+ * After calling newInstance() the builder becomes invalid, and may not be called again.
+ *
+ * @param <T> Entity type
+ */
+public interface EntityBuilder<T>
+{
+    /**
+     * Get a representation of the state for the new Composite.
+     * It is possible to access and update properties and associations,
+     * even immutable ones since the builder represents the initial state.
+     *
+     * @return a proxy implementing the Composite type
+     */
+    T instance();
+
+    /**
+     * Get a representation of the state of the given type for the new Composite.
+     * This is primarily used if you want to provide state for a private mixin type.
+     *
+     * @param <K> Mixin type
+     * @param mixinType the mixin which you want to provide state for
+     *
+     * @return a proxy implementing the given mixin type
+     */
+    <K> K instanceFor( Class<K> mixinType );
+
+    /**
+     * Create a new Entity instance.
+     *
+     * @return a new Entity instance
+     *
+     * @throws org.apache.polygene.api.common.ConstructionException
+     *                            thrown if it was not possible to instantiate the Composite
+     * @throws LifecycleException if the entity could not be created
+     */
+    T newInstance()
+        throws ConstructionException, LifecycleException;
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/entity/EntityBuilderTemplate.java b/core/api/src/main/java/org/apache/polygene/api/entity/EntityBuilderTemplate.java
new file mode 100644
index 0000000..00daed2
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/entity/EntityBuilderTemplate.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.api.entity;
+
+import org.apache.polygene.api.structure.Module;
+
+/**
+ * EntityBuilderTemplate.
+ */
+public abstract class EntityBuilderTemplate<T>
+{
+    Class<T> type;
+
+    protected EntityBuilderTemplate( Class<T> type )
+    {
+        this.type = type;
+    }
+
+    protected abstract void build( T prototype );
+
+    public T newInstance( Module module )
+    {
+        EntityBuilder<T> builder = module.unitOfWorkFactory().currentUnitOfWork().newEntityBuilder( type );
+        build( builder.instance() );
+        return builder.newInstance();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/entity/EntityComposite.java b/core/api/src/main/java/org/apache/polygene/api/entity/EntityComposite.java
new file mode 100644
index 0000000..4fa9cb9
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/entity/EntityComposite.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.api.entity;
+
+import org.apache.polygene.api.association.AssociationMixin;
+import org.apache.polygene.api.association.ManyAssociationMixin;
+import org.apache.polygene.api.association.NamedAssociationMixin;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.mixin.Mixins;
+
+/**
+ * EntityComposites are Composites that has mutable state persisted in EntityStores and equality defined from its
+ * reference.
+ */
+@Mixins( { AssociationMixin.class, ManyAssociationMixin.class, NamedAssociationMixin.class } )
+public interface EntityComposite extends HasIdentity, Composite
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/entity/EntityDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/entity/EntityDescriptor.java
new file mode 100644
index 0000000..83f5f5d
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/entity/EntityDescriptor.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.api.entity;
+
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.StatefulAssociationCompositeDescriptor;
+import org.apache.polygene.api.type.EntityCompositeType;
+
+/**
+ * Entity Descriptor.
+ */
+public interface EntityDescriptor
+    extends CompositeDescriptor, StatefulAssociationCompositeDescriptor
+{
+    @Override
+    EntityCompositeType valueType();
+
+    boolean queryable();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/entity/EntityReference.java b/core/api/src/main/java/org/apache/polygene/api/entity/EntityReference.java
new file mode 100644
index 0000000..98d1003
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/entity/EntityReference.java
@@ -0,0 +1,118 @@
+/*
+ *  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.polygene.api.entity;
+
+import java.util.Objects;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+
+/**
+ * An EntityReference is reference of a specific Entity instance.
+ * <p>When stringified, the reference is used as-is. Example:</p>
+ * <pre>123456-abcde</pre>
+ */
+public final class EntityReference
+{
+    /**
+     * Parse an Entity reference string to an EntityReference.
+     *
+     * @param identityString the EntityReference reference
+     * @return the EntityReference represented by the given reference
+     */
+    public static EntityReference parseEntityReference(String identityString)
+    {
+        return new EntityReference( new StringIdentity( identityString ) );
+    }
+
+    /**
+     * @param object an EntityComposite
+     * @return the EntityReference for the given EntityComposite
+     */
+    public static EntityReference entityReferenceFor(Object object)
+    {
+        return new EntityReference(((EntityComposite) object).identity().get());
+    }
+
+    public static EntityReference create(Identity identity)
+    {
+        if (identity == null)
+        {
+            return null;
+        }
+        return new EntityReference(identity);
+    }
+
+    private Identity identity;
+
+    /**
+     * @param identity reference reference
+     * @throws NullPointerException if reference is null
+     */
+    private EntityReference( Identity identity )
+    {
+        Objects.requireNonNull(identity,"reference must not be null");
+        this.identity = identity;
+    }
+
+    /**
+     *
+     * @return The reference of the Entity that this EntityReference.is referring to
+     */
+    public Identity identity()
+    {
+        return identity;
+    }
+
+    /**
+     * @return An URI representation of this EntityReference.
+     */
+    public String toURI()
+    {
+        return "urn:polygene:entity:" + identity;
+    }
+
+    @Override
+    public boolean equals(Object o)
+    {
+        if (this == o)
+        {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass())
+        {
+            return false;
+        }
+        EntityReference that = (EntityReference) o;
+        return identity.equals(that.identity);
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return identity.hashCode();
+    }
+
+    @Override
+    public String toString()
+    {
+        return identity.toString();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/entity/Lifecycle.java b/core/api/src/main/java/org/apache/polygene/api/entity/Lifecycle.java
new file mode 100644
index 0000000..f5d84f2
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/entity/Lifecycle.java
@@ -0,0 +1,87 @@
+/*
+ *  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.polygene.api.entity;
+
+/**
+ * Lifecycle interface for all Composites.
+ * <p>
+ * This Lifecycle interface is a built-in feature of the Polygene runtime, similar to the Initializable interface.
+ * Any Mixin that implements this interface AND is part of an EntityComposite will have these two methods called
+ * upon creation/removal of the EntityComposite instance to/from the EntityStore. Meaning, the create method is called
+ * only when the identifiable EntityComposite is created the first time, and not when it is read from its persisted
+ * state and created into memory.
+ * </p>
+ * <p>
+ * Example;
+ * </p>
+ * <pre><code>
+ * public interface System
+ * {
+ *     Property&lt;User&gt; admin();
+ * }
+ *
+ * public class SystemAdminMixin&lt;LifeCycle&gt;
+ *     implements System, Lifecyle, ...
+ * {
+ *      &#64;Structure private UnitOfWork uow;
+ *      &#64;This private Identity meAsIdentity;
+ *
+ *      public void create()
+ *      {
+ *          String thisId = meAsIdentity.reference().get();
+ *          EntityBuilder builder = uow.newEntityBuilder( thisId + ":1", UserComposite.class );
+ *          User admin = builder.newInstance();
+ *          admin().set( admin );
+ *      }
+ *
+ *      public void remove()
+ *      {
+ *          uow.remove( admin().get() );
+ *      }
+ * }
+ *
+ * &#64;Mixins( SystemAdminMixin.class )
+ * public interface SystemEntity extends System, EntityComposite
+ * {}
+ *
+ * </code></pre>
+ */
+public interface Lifecycle
+{
+    /**
+     * Creation callback method.
+     * <p>
+     * Called by the Polygene runtime before the newInstance of the entity completes, before the constraints are checked,
+     * allowing for additional initialization.
+     * </p>
+     * @throws Exception if the entity could not be created
+     */
+    void create() throws Exception;
+
+    /**
+     * Removal callback method.
+     * <p>
+     * Called by the Polygene runtime before the entity is removed from the system, allowing
+     * for clean-up operations.
+     * </p>
+     * @throws Exception if the entity could not be removed
+     */
+    void remove() throws Exception;
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/entity/LifecycleException.java b/core/api/src/main/java/org/apache/polygene/api/entity/LifecycleException.java
new file mode 100644
index 0000000..2878538
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/entity/LifecycleException.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.api.entity;
+
+/**
+ * Thrown if Lifecycle invocation fails
+ */
+public class LifecycleException extends RuntimeException
+{
+    public LifecycleException()
+    {
+    }
+
+    public LifecycleException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/entity/Queryable.java b/core/api/src/main/java/org/apache/polygene/api/entity/Queryable.java
new file mode 100644
index 0000000..4a3f563
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/entity/Queryable.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.api.entity;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation is used to mark entity types or properties/associations that are indexable.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.TYPE, ElementType.METHOD } )
+@Documented
+public @interface Queryable
+{
+    boolean value() default true;
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/entity/package.html b/core/api/src/main/java/org/apache/polygene/api/entity/package.html
new file mode 100644
index 0000000..39a3223
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/entity/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Entity API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/event/package.html b/core/api/src/main/java/org/apache/polygene/api/event/package.html
new file mode 100644
index 0000000..4972ae6
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/event/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Event API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/identity/HasIdentity.java b/core/api/src/main/java/org/apache/polygene/api/identity/HasIdentity.java
new file mode 100644
index 0000000..cbed394
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/identity/HasIdentity.java
@@ -0,0 +1,75 @@
+/*
+ *  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.polygene.api.identity;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Immutable;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * This interface provides the identity of the object which may be used
+ * to store the state in a database. It is not the responsibility of the
+ * framework to come up with a good identity string.
+ */
+@Mixins( HasIdentity.HasIdentityMixin.class )
+public interface HasIdentity
+{
+    Method IDENTITY_METHOD = HasIdentityMixin.identityMethod();
+    QualifiedName IDENTITY_STATE_NAME = HasIdentityMixin.stateName();
+
+    @Immutable
+    Property<Identity> identity();
+
+    /**
+     * Default Identity implementation.
+     */
+    class HasIdentityMixin
+        implements HasIdentity
+    {
+        @State
+        private Property<Identity> identity;
+
+        @Override
+        public Property<Identity> identity()
+        {
+            return identity;
+        }
+
+        private static QualifiedName stateName()
+        {
+            return QualifiedName.fromAccessor( identityMethod() );
+        }
+
+        private static Method identityMethod()
+        {
+            try
+            {
+                return HasIdentity.class.getMethod( "identity" );
+            }
+            catch( NoSuchMethodException e )
+            {
+                throw new InternalError( "Polygene Core Runtime codebase is corrupted." );
+            }
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/identity/Identifiable.java b/core/api/src/main/java/org/apache/polygene/api/identity/Identifiable.java
new file mode 100644
index 0000000..001ce7e
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/identity/Identifiable.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.api.identity;
+
+public interface Identifiable
+{
+    Identity identity();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/identity/Identity.java b/core/api/src/main/java/org/apache/polygene/api/identity/Identity.java
new file mode 100644
index 0000000..1db6d6d
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/identity/Identity.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.api.identity;
+
+/**
+ * Representation of an Identity.
+ * Identity is an opaque, immutable data type.
+ * Identity is a very central concept in any domain model.
+ *
+ */
+public interface Identity
+{
+    String toString();
+
+    byte[] toBytes();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/identity/IdentityGenerator.java b/core/api/src/main/java/org/apache/polygene/api/identity/IdentityGenerator.java
new file mode 100644
index 0000000..d407b0e
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/identity/IdentityGenerator.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.api.identity;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+/**
+ * Generator for identities of EntityComposite's.
+ */
+@Mixins( UuidGeneratorMixin.class )
+public interface IdentityGenerator
+{
+    /**
+     * Generate a new id for the given Composite type
+     *
+     * @param compositeType the type of composite
+     *
+     * @return a new reference
+     */
+    Identity generate( Class<?> compositeType );
+
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/identity/StringIdentity.java b/core/api/src/main/java/org/apache/polygene/api/identity/StringIdentity.java
new file mode 100644
index 0000000..d5c43f9
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/identity/StringIdentity.java
@@ -0,0 +1,86 @@
+/*
+ *  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.polygene.api.identity;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+
+public class StringIdentity
+    implements Identity
+{
+    private final String value;
+
+    public StringIdentity(String value)
+    {
+        Objects.requireNonNull( value, "Identity can not be null." );
+        this.value = value;
+    }
+
+    public StringIdentity(byte[] bytes)
+    {
+        value = new String(bytes, StandardCharsets.UTF_8);
+    }
+
+    public String value()
+    {
+        return value;
+    }
+
+    @Override
+    public byte[] toBytes()
+    {
+        return value.getBytes(StandardCharsets.UTF_8);
+    }
+
+    @Override
+    public String toString()
+    {
+        return value;
+    }
+
+    public static Identity fromString(String serializedState)
+    {
+        return new StringIdentity( serializedState );
+    }
+
+    @Override
+    public boolean equals(Object o)
+    {
+        if (this == o)
+        {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass())
+        {
+            return false;
+        }
+
+        StringIdentity that = (StringIdentity) o;
+
+        return value.equals(that.value);
+
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return value.hashCode();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/identity/UuidGeneratorMixin.java b/core/api/src/main/java/org/apache/polygene/api/identity/UuidGeneratorMixin.java
new file mode 100644
index 0000000..0add4c6
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/identity/UuidGeneratorMixin.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.api.identity;
+
+import java.util.UUID;
+
+public class UuidGeneratorMixin
+        implements IdentityGenerator
+{
+    @Override
+    public Identity generate(Class<?> compositeType)
+    {
+        return StringIdentity.fromString(UUID.randomUUID().toString());
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/injection/InjectionScope.java b/core/api/src/main/java/org/apache/polygene/api/injection/InjectionScope.java
new file mode 100644
index 0000000..cc7b3a4
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/injection/InjectionScope.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.api.injection;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This is used to annotate annotation types which are used for injection.
+ * Each scope signifies a particular scope from which the injection value should be taken.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.ANNOTATION_TYPE } )
+@Documented
+public @interface InjectionScope
+{
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/injection/package.html b/core/api/src/main/java/org/apache/polygene/api/injection/package.html
new file mode 100644
index 0000000..155a5e4
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/injection/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Dependency Injection API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/injection/scope/Invocation.java b/core/api/src/main/java/org/apache/polygene/api/injection/scope/Invocation.java
new file mode 100644
index 0000000..4305532
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/injection/scope/Invocation.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.api.injection.scope;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.injection.InjectionScope;
+
+/**
+ * Annotation to denote the injection of a
+ * invocation specific resource.
+ * These include:
+ * <pre><code>
+ *  - The Method being invoked.
+ *
+ *  - An AnnotationElement with annotations
+ *    from both mixin type, mixin
+ *    implementation.
+ *
+ *  - An Annotation of a specific type
+ * </code></pre>
+ * Examples:
+ * <pre><code>
+ * &#64;Invocation Method theInvokedMethod
+ * &#64;Invocation AnnotationElement annotations
+ * &#64;Invocation Matches matchesAnnotation
+ * </code></pre>
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.FIELD, ElementType.PARAMETER } )
+@Documented
+@InjectionScope
+public @interface Invocation
+{
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/injection/scope/Service.java b/core/api/src/main/java/org/apache/polygene/api/injection/scope/Service.java
new file mode 100644
index 0000000..3fb344a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/injection/scope/Service.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.api.injection.scope;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.injection.InjectionScope;
+
+/**
+ * Annotation to denote the injection of a service dependency into a Fragment.
+ * <p>
+ * Examples:
+ * </p>
+ * <pre><code>
+ * &#64;Service MyService service
+ * &#64;Service Iterable&lt;MyService&gt; services
+ * &#64;Service ServiceReference&lt;MyService&gt; serviceRef
+ * &#64;Service Iterable&lt;ServiceReference&lt;MyService&gt;&gt; serviceRefs
+ * </code></pre>
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.FIELD, ElementType.PARAMETER } )
+@Documented
+@InjectionScope
+public @interface Service
+{
+}
+
diff --git a/core/api/src/main/java/org/apache/polygene/api/injection/scope/State.java b/core/api/src/main/java/org/apache/polygene/api/injection/scope/State.java
new file mode 100644
index 0000000..e326969
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/injection/scope/State.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.api.injection.scope;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.injection.InjectionScope;
+
+/**
+ * Annotation to denote the injection of a property, association or
+ * StateHolder.
+ * <pre><code>
+ * &#64;State Property&lt;StringState propertyName;
+ * &#64;State Association&lt;MyEntityState associationName;
+ * &#64;State ManyAssociation&lt;MyEntityState manyAssociationName;
+ * &#64;State NamedAssociation&lt;MyEntityState namedAssociationName;
+ * &#64;State StateHolder state;
+ * &#64;State AssociationStateHolder associationState;
+ * </code></pre>
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.FIELD, ElementType.PARAMETER } )
+@Documented
+@InjectionScope
+public @interface State
+{
+    /**
+     * Name of the property or association.
+     * If not set then name will be name of field.
+     *
+     * @return the name
+     */
+    String value() default "";
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/injection/scope/Structure.java b/core/api/src/main/java/org/apache/polygene/api/injection/scope/Structure.java
new file mode 100644
index 0000000..b2114ab
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/injection/scope/Structure.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.api.injection.scope;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.injection.InjectionScope;
+
+/**
+ * Annotation to denote the injection of a
+ * resource specific for the module which the
+ * injected object/fragment is instantiated in.
+ * <p>
+ * Valid types are:
+ * </p>
+ * <pre><code>
+ * - TransientBuilderFactory
+ * - ObjectBuilderFactory
+ * - UnitOfWorkFactory
+ * - ServiceFinder
+ * - Module
+ * - Layer
+ * - Application
+ * - PolygeneAPI
+ * - PolygeneSPI
+ * </code></pre>
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.FIELD, ElementType.PARAMETER } )
+@Documented
+@InjectionScope
+public @interface Structure
+{
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/injection/scope/This.java b/core/api/src/main/java/org/apache/polygene/api/injection/scope/This.java
new file mode 100644
index 0000000..1816ac5
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/injection/scope/This.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.api.injection.scope;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.injection.InjectionScope;
+
+/**
+ * Annotation to denote the injection of a reference to the same Composite
+ * as the fragment is a part of.
+ * <p>
+ * If the Composite type does not implement the type of the field or parameter
+ * then it will be referencing a private mixin.
+ * </p>
+ * <p>
+ * Calls to the reference will have the same semantics as calls to the Composite itself.
+ * Specifically the same set of Modifiers will be used.
+ * </p>
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.FIELD, ElementType.PARAMETER } )
+@Documented
+@InjectionScope
+public @interface This
+{
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/injection/scope/Uses.java b/core/api/src/main/java/org/apache/polygene/api/injection/scope/Uses.java
new file mode 100644
index 0000000..ea590e4
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/injection/scope/Uses.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.api.injection.scope;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.injection.InjectionScope;
+
+/**
+ * Annotation to denote the injection of a dependency to be used by a Mixin. The injected
+ * object is provided either by the TransientBuilder.uses() declarations, or if an instance of the appropriate types is not
+ * found, then a new Transient or Object is instantiated.
+ * Call {@link org.apache.polygene.api.composite.TransientBuilder#use} to provide the instance
+ * to be injected.
+ *
+ * Example:
+ * <pre>@Uses SomeType someInstance</pre>
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.PARAMETER, ElementType.FIELD } )
+@Documented
+@InjectionScope
+public @interface Uses
+{
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/injection/scope/package.html b/core/api/src/main/java/org/apache/polygene/api/injection/scope/package.html
new file mode 100644
index 0000000..10f4f1c
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/injection/scope/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Dependency Injection Scopes.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/Metric.java b/core/api/src/main/java/org/apache/polygene/api/metrics/Metric.java
new file mode 100644
index 0000000..46cd3f5
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/Metric.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.api.metrics;
+
+/**
+ * Marker interface for all Metric types.
+ */
+public interface Metric
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/MetricNames.java b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricNames.java
new file mode 100644
index 0000000..d24bd8e
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricNames.java
@@ -0,0 +1,95 @@
+/*
+ *  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.polygene.api.metrics;
+
+import org.apache.polygene.api.structure.Module;
+
+import java.lang.reflect.Method;
+import java.util.StringJoiner;
+
+/**
+ * Metric names utilities.
+ */
+public class MetricNames
+{
+    /**
+     * Build a Metric name for the given fragments.
+     *
+     * @param fragments Name fragments
+     * @return Metric name
+     */
+    public static String nameFor( String... fragments )
+    {
+        StringJoiner joiner = new StringJoiner( "." );
+        for( String fragment : fragments )
+        {
+            joiner.add( fragment );
+        }
+        return joiner.toString();
+    }
+
+    /**
+     * Build a Metric name for the given Module, Type and optional fragments.
+     *
+     * @param module Module
+     * @param type Type
+     * @param fragments Name fragments
+     * @return Metric name
+     */
+    public static String nameFor( Module module, Class<?> type, String... fragments )
+    {
+        StringJoiner joiner = new StringJoiner( "." )
+                .add( module.layer().name() )
+                .add( module.name() )
+                .add( className( type ) );
+        for( String fragment : fragments )
+        {
+            joiner.add( fragment );
+        }
+        return joiner.toString();
+    }
+
+    /**
+     * Build a Metric name for the given Module, Method and optional fragments.
+     *
+     * @param module Module
+     * @param method Method
+     * @param fragments Name fragments
+     * @return Metric name
+     */
+    public static String nameFor( Module module, Method method, String... fragments )
+    {
+        StringJoiner joiner = new StringJoiner( "." )
+                .add( module.layer().name() )
+                .add( module.name() )
+                .add( className( method.getDeclaringClass() ) )
+                .add( method.getName() );
+        for( String fragment : fragments )
+        {
+            joiner.add( fragment );
+        }
+        return joiner.toString();
+    }
+
+    private static String className( Class<?> clazz )
+    {
+        return clazz.getName().substring( clazz.getName().lastIndexOf( '.' ) + 1 ).replace( '$', '.' );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsCounter.java b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsCounter.java
new file mode 100644
index 0000000..9b9b9df
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsCounter.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.api.metrics;
+
+/**
+ * Metrics Counter.
+ */
+public interface MetricsCounter extends Metric
+{
+    void increment();
+
+    void increment( int steps );
+
+    void decrement();
+
+    void decrement( int steps );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsCounterFactory.java b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsCounterFactory.java
new file mode 100644
index 0000000..45959a3
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsCounterFactory.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.api.metrics;
+
+/**
+ * Create MetricsCounter instances.
+ */
+public interface MetricsCounterFactory extends MetricsFactory
+{
+    /**
+     * Create a MetricsCounter instance.
+     * If the same arguments are given twice, the same instance must be returned.
+     *
+     * @param name   A human readable, short name of the metric.
+     *
+     * @return A Metric instance to be used, OR org.apache.polygene.spi.metrics.DefaultMetric.NULL if not supported.
+     */
+    MetricsCounter createCounter( String name );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsFactory.java b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsFactory.java
new file mode 100644
index 0000000..af85ea9
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsFactory.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.api.metrics;
+
+import java.util.stream.Stream;
+
+/**
+ * Metrics Factory.
+ */
+public interface MetricsFactory
+{
+    Stream<Metric> registered();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsGauge.java b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsGauge.java
new file mode 100644
index 0000000..cf34fe6
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsGauge.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.api.metrics;
+
+/**
+ * MetricsGauge is the most basic Metric type, and is completely flexible and therefor handled slightly differently in
+ * the MetricsFactory than all other Gauges. It needs to pass on custom code, so the implementation is typically
+ * an anonymous class, inlined at the implementation.
+ *
+ * @param <T> Any type holding the MetricsGauge's current value.
+ */
+public interface MetricsGauge<T> extends Metric
+{
+    /**
+     * Returns the metric's current value.
+     *
+     * @return the metric's current value
+     */
+    T value();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsGaugeFactory.java b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsGaugeFactory.java
new file mode 100644
index 0000000..9af3d19
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsGaugeFactory.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.api.metrics;
+
+/**
+ * Register MetricsGauge with the underlying Metrics system.
+ */
+public interface MetricsGaugeFactory extends MetricsFactory
+{
+    /**
+     * Register a MetricsGauge with the underlying Metrics system.
+     *
+     * @param name   A human readable, short name of the metric.
+     * @param gauge  The implementation of the MetricsGauge.
+     * @param <T>    Any type holding the MetricsGauge's current value.
+     *
+     * @return The same MetricsGauge or the DefaultMetric.NULL MetricsGauge instance.
+     */
+    <T> MetricsGauge<T> registerGauge( String name, MetricsGauge<T> gauge );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsHealthCheck.java b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsHealthCheck.java
new file mode 100644
index 0000000..b3ee0d8
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsHealthCheck.java
@@ -0,0 +1,86 @@
+/*
+ *  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.polygene.api.metrics;
+
+/**
+ * Metrics Health Check.
+ */
+public interface MetricsHealthCheck extends Metric
+{
+    Result check()
+        throws Exception;
+
+    final class Result
+    {
+        private final boolean healthy;
+        private final String message;
+        private final Throwable exception;
+
+        private Result( boolean isHealthy, String message, Throwable exception )
+        {
+            healthy = isHealthy;
+            this.message = message;
+            this.exception = exception;
+        }
+
+        /** Factory method for reporting an Ok health.
+         *
+         * @return A healthy result.
+         */
+        public static Result healthOk() {
+            return new Result( true, "", null );
+        }
+
+        /** Factory method for reporting an unhealthy state.
+         *
+         * @param message The message to relay in the result.
+         * @return An unhealthy result.
+         */
+        public static Result unhealthy(String message) {
+            return new Result( false, message, null );
+        }
+
+        /** Factory method for reporting a state where an exception has occurred.
+         *
+         * @param message The message to relay in the result.
+         * @param exception the exception that has occurred.
+         * @return A failing health state.
+         */
+        public static Result exception(String message, Throwable exception) {
+            return new Result( false, message, exception );
+        }
+
+        public boolean isHealthy()
+        {
+            return healthy;
+        }
+
+        public String getMessage()
+        {
+            return message;
+        }
+
+        public Throwable getException()
+        {
+            return exception;
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsHealthCheckFactory.java b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsHealthCheckFactory.java
new file mode 100644
index 0000000..ff31d02
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsHealthCheckFactory.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.api.metrics;
+
+/**
+ * Create MetricsHealthCheck instances.
+ */
+public interface MetricsHealthCheckFactory extends MetricsFactory
+{
+    /**
+     * Create a MetricsHealthCheck instance.
+     * If the same arguments are given twice, the same instance must be returned.
+     *
+     * @param name   A human readable, short name of the metric.
+     * @param check  The health check to be performed regularly.
+     *
+     * @return A MetricsHealthCheck instance to be used, OR org.apache.polygene.spi.metrics.DefaultMetric.NULL if not supported.
+     *
+     */
+    MetricsHealthCheck registerHealthCheck( String name, MetricsHealthCheck check );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsHistogram.java b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsHistogram.java
new file mode 100644
index 0000000..a61ee1f
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsHistogram.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.api.metrics;
+
+/**
+ * A metric which calculates the distribution of a value.
+ *
+ * @see <a href="http://www.johndcook.com/standard_deviation.html">Accurately computing running variance</a>
+ */
+public interface MetricsHistogram extends Metric
+{
+    void update( long newValue );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsHistogramFactory.java b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsHistogramFactory.java
new file mode 100644
index 0000000..3ca7bbd
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsHistogramFactory.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.api.metrics;
+
+/**
+ * Create MetricsHistogram instances.
+ */
+public interface MetricsHistogramFactory extends MetricsFactory
+{
+    /**
+     * Create a MetricsHistogram instance.
+     * If the same arguments are given twice, the same instance must be returned.
+     *
+     * @param name   A human readable, short name of the metric.
+     *
+     * @return A Metric instance to be used, OR org.apache.polygene.spi.metrics.DefaultMetric.NULL if not supported.
+     *
+     */
+    MetricsHistogram createHistogram( String name );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsMeter.java b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsMeter.java
new file mode 100644
index 0000000..e6f4df8
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsMeter.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.api.metrics;
+
+/**
+ * A meter metric which measures mean throughput and one-, five-, and fifteen-minute
+ * exponentially-weighted moving average throughputs.
+ *
+ * @see <a href="http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average">EMA</a>
+ */
+public interface MetricsMeter extends Metric
+{
+    void mark();
+
+    /**
+     * Mark the occurrence of a given number of events.
+     *
+     * @param numberOfEvents the number of events
+     */
+    void mark( int numberOfEvents );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsMeterFactory.java b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsMeterFactory.java
new file mode 100644
index 0000000..209ba3b
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsMeterFactory.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.api.metrics;
+
+/**
+ * Create MetricsMeter instances.
+ */
+public interface MetricsMeterFactory extends MetricsFactory
+{
+    /**
+     * Create a MetricsMeter instance.
+     * If the same arguments are given twice, the same instance must be returned.
+     *
+     * @param name      A human readable, short name of the metric.
+     *
+     * @return A Metric instance to be used, OR org.apache.polygene.spi.metrics.DefaultMetric.NULL if not supported.
+     */
+    MetricsMeter createMeter( String name );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsNotSupportedException.java b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsNotSupportedException.java
new file mode 100644
index 0000000..4a47f45
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsNotSupportedException.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.api.metrics;
+
+/**
+ * Thrown when the underlying MetricsProvider do not support a Metric type.
+ */
+public class MetricsNotSupportedException extends RuntimeException
+{
+    public MetricsNotSupportedException( Class<? extends MetricsFactory> factoryType,
+                                         Class<? extends MetricsProvider> providerType
+    )
+    {
+        super( "Metrics [" + factoryType.getName() + "] is not supported by MetricsProvider [" + providerType.getName() + "]." );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsProvider.java b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsProvider.java
new file mode 100644
index 0000000..f3fd5c7
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsProvider.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.api.metrics;
+
+/**
+ * Metrics Provider SPI.
+ * <p>
+ * The Polygene Runtime will automatically look for a service that implements the MetricsProvider interface
+ * and use it for internal Runtime metrics, such as the UnitOfWork measuring the time from creation to close.
+ * </p>
+ * <p>
+ * The Metrics Library is available to add metric functionality to applications in the same way, and
+ * will use the same MetricsProvider.
+ * </p>
+ * <p>
+ * Note that the usual visibility rules applies, so you might have more than one MetricsProvider server,
+ * perhaps per layer.
+ * </p>
+ */
+public interface MetricsProvider
+{
+    /**
+     * Creates a new factory instance.
+     *
+     * The instantiation is done by providing a Metric type, which is one of
+     * <ul>
+     * <li>{@link MetricsCounter}</li>
+     * <li>{@link MetricsGauge}</li>
+     * <li>{@link MetricsHealthCheck}</li>
+     * <li>{@link MetricsHistogram}</li>
+     * <li>{@link MetricsMeter}</li>
+     * <li>{@link MetricsTimer}</li>
+     * </ul>
+     *
+     * @param factoryType The class of the metric type needed.
+     * @param <T>         The metric type requested.
+     *
+     * @return A factory instance
+     *
+     * @throws MetricsNotSupportedException when the MetricsProvider is not supporting the factory type requested.
+     */
+    <T extends MetricsFactory> T createFactory( Class<T> factoryType )
+        throws MetricsNotSupportedException;
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsTimer.java b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsTimer.java
new file mode 100644
index 0000000..1a2cc2c
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsTimer.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.api.metrics;
+
+/**
+ * Timer Metrics.
+ */
+public interface MetricsTimer extends Metric
+{
+    /**
+     * Start the Timer Metrics.
+     *
+     * @return the timer context
+     */
+    Context start();
+
+    /**
+     * Timer Metrics Context.
+     */
+    interface Context
+    {
+        /**
+         * Stop the Timer Metrics.
+         */
+        void stop();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsTimerFactory.java b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsTimerFactory.java
new file mode 100644
index 0000000..e672d5b
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/MetricsTimerFactory.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.api.metrics;
+
+/**
+ * Create MetricsTimer instances.
+ */
+public interface MetricsTimerFactory extends MetricsFactory
+{
+    /**
+     * Create a MetricsTimer instance.
+     * If the same arguments are given twice, the same instance must be returned.
+     *
+     * @param name     A human readable, short name of the metric.
+     *
+     * @return A Metric instance to be used, OR org.apache.polygene.spi.metrics.DefaultMetric.NULL if not supported.
+     *
+     */
+    MetricsTimer createTimer( String name );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCapture.java b/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCapture.java
new file mode 100644
index 0000000..8c9007a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCapture.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.api.metrics;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.injection.InjectionScope;
+
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.METHOD } )
+@Documented
+@InjectionScope
+public @interface TimingCapture
+{
+    String value() default "";
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCaptureAllConcern.java b/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCaptureAllConcern.java
new file mode 100644
index 0000000..da11550
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCaptureAllConcern.java
@@ -0,0 +1,84 @@
+/*
+ *  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.polygene.api.metrics;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.injection.scope.Invocation;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.structure.Module;
+
+public class TimingCaptureAllConcern extends ConcernOf<InvocationHandler>
+    implements InvocationHandler
+{
+    private final MetricsTimer timer;
+
+    public TimingCaptureAllConcern( @Structure Module module,
+                                    @Service @Optional MetricsProvider metrics,
+                                    @Invocation Method method
+    )
+    {
+        if( metrics == null )
+        {
+            timer = null;
+        }
+        else
+        {
+            MetricsTimerFactory factory = metrics.createFactory( MetricsTimerFactory.class );
+            TimingCapture capture = method.getAnnotation( TimingCapture.class );
+            String timerName;
+            if( capture == null || "".equals( capture.value() ) )
+            {
+                timerName = MetricNames.nameFor( module, method );
+            }
+            else
+            {
+                timerName = capture.value();
+            }
+            timer = factory.createTimer( timerName );
+        }
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        MetricsTimer.Context timing = null;
+        if( timer != null )
+        {
+            timing = timer.start();
+        }
+        try
+        {
+            return next.invoke( proxy, method, args );
+        }
+        finally
+        {
+            if( timing != null )
+            {
+                timing.stop();
+            }
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCaptureConcern.java b/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCaptureConcern.java
new file mode 100644
index 0000000..b94daea
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/TimingCaptureConcern.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.api.metrics;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.injection.scope.Invocation;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.structure.Module;
+
+@AppliesTo( TimingCapture.class )
+public class TimingCaptureConcern extends TimingCaptureAllConcern
+{
+
+    public TimingCaptureConcern( @Structure Module module,
+                                 @Service @Optional MetricsProvider metrics,
+                                 @Invocation Method method
+    )
+    {
+        super( module, metrics, method );
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        return super.invoke( proxy, method, args );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/metrics/package.html b/core/api/src/main/java/org/apache/polygene/api/metrics/package.html
new file mode 100644
index 0000000..3657fe5
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/metrics/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Metrics API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/mixin/Initializable.java b/core/api/src/main/java/org/apache/polygene/api/mixin/Initializable.java
new file mode 100644
index 0000000..60136f7
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/mixin/Initializable.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.api.mixin;
+
+/**
+ * Fragments which want to be initialized can implement
+ * this callback interface. It will be invoked after
+ * the fragment has bee instantiated and all injections have been done.
+ */
+public interface Initializable
+{
+    /**
+     * Initialize the fragment
+     *
+     * @throws Exception if something went wrong
+     */
+    void initialize() throws Exception;
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/mixin/InitializationException.java b/core/api/src/main/java/org/apache/polygene/api/mixin/InitializationException.java
new file mode 100644
index 0000000..254a2b7
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/mixin/InitializationException.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.api.mixin;
+
+/**
+ * Thrown when a Fragment or object could not be initialized.
+ */
+public class InitializationException extends RuntimeException
+{
+    public InitializationException()
+    {
+    }
+
+    public InitializationException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/mixin/MixinDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/mixin/MixinDescriptor.java
new file mode 100644
index 0000000..261e7bc
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/mixin/MixinDescriptor.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.api.mixin;
+
+/**
+ * Mixin Descriptor.
+ */
+public interface MixinDescriptor
+{
+    Class<?> mixinClass();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/mixin/Mixins.java b/core/api/src/main/java/org/apache/polygene/api/mixin/Mixins.java
new file mode 100644
index 0000000..e81989c
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/mixin/Mixins.java
@@ -0,0 +1,84 @@
+/*
+ *  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.polygene.api.mixin;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation is used in composites to declare mixin implementation classes.
+ * <p>
+ * Mixins tells the runtime which implementation class of a Mixin should be
+ * used. The &#64;Mixins annotation can occur at any level in the composite hierarchy
+ * and the runtime will match each found Mixin implementation against a Mixins annotation.
+ * All mixin interfaces must have a Mixin implementation in the composite hierarchy or
+ * a runtime exception will occur.
+ * </p>
+ * <p>
+ * Example;
+ * </p>
+ * <pre><code>
+ *
+ * &#64;Mixins( MyBeerOrder.class )
+ * public interface BeerOrderComposite extends BeerOrder, Composite
+ * {
+ * }
+ *
+ * public class MyBeerOrder
+ * implements BeerOrder
+ * {
+ * :
+ * }
+ * </code></pre>
+ * <p>
+ * Many implementations can be listed,
+ * </p>
+ * <pre><code>
+ * &#64;Mixins( { MyBeerOrder.class, DescriptionImpl.class } )
+ * public interface BeerOrderComposite extends BeerOrder, Description, Composite
+ * {
+ * }
+ * </code></pre>
+ * <p>
+ * If the Mixins is a class that implements InvocationHandler, it will be
+ * used for all mixins. To avoid that an invocation handler based implementation
+ * not service all mixin, use the AppliesTo annotation.
+ * </p>
+ *
+ * <p>
+ * It is valid to have multiple Mixins for a mixin. The first one found
+ * will be used. The search order is in the order they are written in the Mixins
+ * annotation left-to-right, and depth-first recursive search of the super-interfaces again
+ * left-to-right.
+ * </p>
+ *
+ * @see org.apache.polygene.api.common.AppliesTo
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( ElementType.TYPE )
+@Documented
+public @interface Mixins
+{
+    Class<?>[] value();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/mixin/NoopMixin.java b/core/api/src/main/java/org/apache/polygene/api/mixin/NoopMixin.java
new file mode 100644
index 0000000..f0a226c
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/mixin/NoopMixin.java
@@ -0,0 +1,89 @@
+/*
+ *  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.polygene.api.mixin;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * Generic mixin that is a no-op. Can be useful if the functionality
+ * of a method is mainly provided by concerns and side-effects.
+ */
+public final class NoopMixin
+    implements InvocationHandler
+{
+    private static final Boolean BOOLEAN_DEFAULT = Boolean.FALSE;
+    private static final Short SHORT_DEFAULT = 0;
+    private static final Character CHARACTER_DEFAULT = 0;
+    private static final Integer INTEGER_DEFAULT = 0;
+    private static final Byte BYTE_DEFAULT = 0;
+    private static final Long LONG_DEFAULT = 0L;
+    private static final Float FLOAT_DEFAULT = 0f;
+    private static final Double DOUBLE_DEFAULT = 0.0;
+
+    @Override
+    public Object invoke( Object object, Method method, Object[] args )
+        throws Throwable
+    {
+        Class<?> retType = method.getReturnType();
+        if( !retType.isPrimitive() )
+        {
+            return null;
+        }
+        if( Void.TYPE == retType )
+        {
+            return null;
+        }
+        if( Boolean.TYPE == retType )
+        {
+            return BOOLEAN_DEFAULT;
+        }
+        if( Short.TYPE == retType )
+        {
+            return SHORT_DEFAULT;
+        }
+        if( Character.TYPE == retType )
+        {
+            return CHARACTER_DEFAULT;
+        }
+        if( Integer.TYPE == retType )
+        {
+            return INTEGER_DEFAULT;
+        }
+        if( Byte.TYPE == retType )
+        {
+            return BYTE_DEFAULT;
+        }
+        if( Long.TYPE == retType )
+        {
+            return LONG_DEFAULT;
+        }
+        if( Float.TYPE == retType )
+        {
+            return FLOAT_DEFAULT;
+        }
+        if( Double.TYPE == retType )
+        {
+            return DOUBLE_DEFAULT;
+        }
+        return null;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/mixin/package.html b/core/api/src/main/java/org/apache/polygene/api/mixin/package.html
new file mode 100644
index 0000000..7c916a3
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/mixin/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Mixin API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/object/NoSuchObjectException.java b/core/api/src/main/java/org/apache/polygene/api/object/NoSuchObjectException.java
new file mode 100644
index 0000000..82b63bd
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/object/NoSuchObjectException.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.api.object;
+
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.InvalidApplicationException;
+
+/**
+ * This exception is thrown if no visible Object of the requested type can be found.
+ */
+public class NoSuchObjectException
+    extends InvalidApplicationException
+{
+    private static final long serialVersionUID = -1121690536365682511L;
+
+    private final String objectType;
+    private final String moduleName;
+
+    public NoSuchObjectException( String type, String moduleName, Stream<Class<?>> visible )
+    {
+        super( "Could not find any visible Object of type [" + type + "] in module ["
+               + moduleName
+               + "]. The visible types are: \n"
+               + visible.map( Class::getName ).collect( Collectors.joining("\n") )
+        );
+        this.objectType = type;
+        this.moduleName = moduleName;
+    }
+
+    public String objectType()
+    {
+        return objectType;
+    }
+
+    public String moduleName()
+    {
+        return moduleName;
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/object/ObjectDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/object/ObjectDescriptor.java
new file mode 100644
index 0000000..81ee90b
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/object/ObjectDescriptor.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.api.object;
+
+import org.apache.polygene.api.composite.ModelDescriptor;
+
+/**
+ * Object Descriptor.
+ */
+public interface ObjectDescriptor
+    extends ModelDescriptor
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/object/ObjectFactory.java b/core/api/src/main/java/org/apache/polygene/api/object/ObjectFactory.java
new file mode 100644
index 0000000..fddeeb1
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/object/ObjectFactory.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.api.object;
+
+import org.apache.polygene.api.common.ConstructionException;
+
+/**
+ * This factory creates and injects POJO's.
+ */
+public interface ObjectFactory
+{
+    /**
+     * Create new objects of the given type.
+     *
+     * @param <T> Object type
+     * @param type an object class which will be instantiated
+     * @param uses objects that can be injected into mixins
+     *
+     * @return new objects.
+     *
+     * @throws ConstructionException Thrown if instantiation fails.
+     * @throws NoSuchObjectException Thrown if {@code type} class is not an object.
+     */
+    <T> T newObject( Class<T> type, Object... uses )
+        throws NoSuchObjectException, ConstructionException;
+
+    /**
+     * Inject an existing instance. Only fields and methods will be called.
+     *
+     * @param instance instance
+     * @param uses dependencies
+     *
+     * @throws ConstructionException if it was not possible to construct the Object dependencies
+     */
+    void injectTo( Object instance, Object... uses )
+        throws ConstructionException;
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/object/package.html b/core/api/src/main/java/org/apache/polygene/api/object/package.html
new file mode 100644
index 0000000..6956f39
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/object/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Object API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/package.html b/core/api/src/main/java/org/apache/polygene/api/package.html
new file mode 100644
index 0000000..1964935
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Apache Polygene™ API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/property/DefaultValues.java b/core/api/src/main/java/org/apache/polygene/api/property/DefaultValues.java
new file mode 100644
index 0000000..848cbc0
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/property/DefaultValues.java
@@ -0,0 +1,93 @@
+/*
+ *  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.polygene.api.property;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Default values for various property types
+ */
+public final class DefaultValues
+{
+    private static final Map<Type, Object> DEFAULT_VALUES = new HashMap<>();
+
+    static
+    {
+        DEFAULT_VALUES.put( Byte.class, 0 );
+        DEFAULT_VALUES.put( Short.class, 0 );
+        DEFAULT_VALUES.put( Character.class, 0 );
+        DEFAULT_VALUES.put( Integer.class, 0 );
+        DEFAULT_VALUES.put( Long.class, 0L );
+        DEFAULT_VALUES.put( Double.class, 0D );
+        DEFAULT_VALUES.put( Float.class, 0F );
+        DEFAULT_VALUES.put( Boolean.class, false );
+        DEFAULT_VALUES.put( String.class, "" );
+    }
+
+    public static Object getDefaultValueOf( Type type )
+    {
+        Object value = DEFAULT_VALUES.get( type );
+        if( value != null )
+        {
+            return value;
+        }
+        if( type instanceof ParameterizedType )
+        {
+            // List<Foo> -> List
+            type = ( (ParameterizedType) type ).getRawType();
+        }
+
+        if( type instanceof Class )
+        {
+            Class typeAsClass = (Class) type;
+            if( Set.class.isAssignableFrom( typeAsClass ) )
+            {
+                return new HashSet();
+            }
+            else if( Map.class.isAssignableFrom( typeAsClass ) )
+            {
+                return new LinkedHashMap();
+            }
+            else if( Collection.class.isAssignableFrom( typeAsClass ) )
+            {
+                return new ArrayList();
+            }
+            else if( typeAsClass.isEnum() )
+            {
+                return ( (Class) type ).getEnumConstants()[ 0 ];
+            }
+            else if( typeAsClass.isArray() )
+            {
+                return Array.newInstance( typeAsClass.getComponentType(), 0 );
+            }
+        }
+        throw new IllegalArgumentException( "Cannot use @UseDefaults with type " + type.toString() );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/property/GenericPropertyInfo.java b/core/api/src/main/java/org/apache/polygene/api/property/GenericPropertyInfo.java
new file mode 100644
index 0000000..0b3dd9b
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/property/GenericPropertyInfo.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.api.property;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+import static org.apache.polygene.api.util.Classes.typeOf;
+
+/**
+ * Generic Property info utility class.
+ */
+public final class GenericPropertyInfo
+{
+    public static Type propertyTypeOf( AccessibleObject accessor )
+    {
+        return toPropertyType( typeOf( accessor ) );
+    }
+
+    public static Type toPropertyType( Type methodReturnType )
+    {
+        if( methodReturnType instanceof ParameterizedType )
+        {
+            ParameterizedType parameterizedType = (ParameterizedType) methodReturnType;
+            if( Property.class.isAssignableFrom( (Class<?>) parameterizedType.getRawType() ) )
+            {
+                return parameterizedType.getActualTypeArguments()[ 0 ];
+            }
+        }
+
+        if( methodReturnType instanceof Class<?> )
+        {
+            Type[] interfaces = ( (Class<?>) methodReturnType ).getGenericInterfaces();
+            for( Type anInterface : interfaces )
+            {
+                Type propertyType = toPropertyType( anInterface );
+                if( propertyType != null )
+                {
+                    return propertyType;
+                }
+            }
+        }
+        return null;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/property/Immutable.java b/core/api/src/main/java/org/apache/polygene/api/property/Immutable.java
new file mode 100644
index 0000000..dee1d2f
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/property/Immutable.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.api.property;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation adds Immutability to Types, Properties and Associations
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.TYPE, ElementType.METHOD } )
+@Documented
+public @interface Immutable
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/property/InitialValueProvider.java b/core/api/src/main/java/org/apache/polygene/api/property/InitialValueProvider.java
new file mode 100644
index 0000000..cd32a3a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/property/InitialValueProvider.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.api.property;
+
+import java.util.function.BiFunction;
+import org.apache.polygene.api.structure.Module;
+
+public interface InitialValueProvider extends BiFunction<Module, PropertyDescriptor, Object>
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/property/InvalidPropertyTypeException.java b/core/api/src/main/java/org/apache/polygene/api/property/InvalidPropertyTypeException.java
new file mode 100644
index 0000000..c566011
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/property/InvalidPropertyTypeException.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.api.property;
+
+import java.lang.reflect.AccessibleObject;
+import org.apache.polygene.api.common.ConstructionException;
+
+/**
+ * Thrown when attempting to subclass Property.
+ */
+public class InvalidPropertyTypeException extends ConstructionException
+{
+    public InvalidPropertyTypeException( String message )
+    {
+        super(message);
+    }
+
+    public InvalidPropertyTypeException( AccessibleObject accessor )
+    {
+        super( createMessage( accessor ) );
+    }
+
+    private static String createMessage( AccessibleObject accessor )
+    {
+        return "Not allowed to subclass " + Property.class.getName() + ". Property accessor " +
+               accessor + " is returning a Property subclass.";
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/property/Numbers.java b/core/api/src/main/java/org/apache/polygene/api/property/Numbers.java
new file mode 100644
index 0000000..779485c
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/property/Numbers.java
@@ -0,0 +1,162 @@
+/*
+ *  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.polygene.api.property;
+
+import java.math.BigDecimal;
+
+/**
+ * Convenience class for mathematical operations on numerical properties.
+ * <pre>import static org.apache.polygene.api.property.Numbers.*;
+ * ...
+ * add( object.numberProperty(), 5 );</pre>
+ */
+public final class Numbers
+{
+    // Integer operations
+
+    public static Property<Integer> add( Property<Integer> property, int amount )
+    {
+        property.set( property.get() + amount );
+        return property;
+    }
+
+    public static Property<Integer> mult( Property<Integer> property, int amount )
+    {
+        property.set( property.get() * amount );
+        return property;
+    }
+
+    public static Property<Integer> sub( Property<Integer> property, int amount )
+    {
+        property.set( property.get() - amount );
+        return property;
+    }
+
+    public static Property<Integer> div( Property<Integer> property, int amount )
+    {
+        property.set( property.get() / amount );
+        return property;
+    }
+
+    // Long operations
+
+    public static Property<Long> add( Property<Long> property, long amount )
+    {
+        property.set( property.get() + amount );
+        return property;
+    }
+
+    public static Property<Long> mult( Property<Long> property, long amount )
+    {
+        property.set( property.get() * amount );
+        return property;
+    }
+
+    public static Property<Long> sub( Property<Long> property, long amount )
+    {
+        property.set( property.get() - amount );
+        return property;
+    }
+
+    public static Property<Long> div( Property<Long> property, long amount )
+    {
+        property.set( property.get() / amount );
+        return property;
+    }
+
+    // Double operations
+
+    public static Property<Double> add( Property<Double> property, double amount )
+    {
+        property.set( property.get() + amount );
+        return property;
+    }
+
+    public static Property<Double> mult( Property<Double> property, double amount )
+    {
+        property.set( property.get() * amount );
+        return property;
+    }
+
+    public static Property<Double> sub( Property<Double> property, double amount )
+    {
+        property.set( property.get() - amount );
+        return property;
+    }
+
+    public static Property<Double> div( Property<Double> property, double amount )
+    {
+        property.set( property.get() / amount );
+        return property;
+    }
+
+    // Float operations
+
+    public static Property<Float> add( Property<Float> property, float amount )
+    {
+        property.set( property.get() + amount );
+        return property;
+    }
+
+    public static Property<Float> mult( Property<Float> property, float amount )
+    {
+        property.set( property.get() * amount );
+        return property;
+    }
+
+    public static Property<Float> sub( Property<Float> property, float amount )
+    {
+        property.set( property.get() - amount );
+        return property;
+    }
+
+    public static Property<Float> div( Property<Float> property, float amount )
+    {
+        property.set( property.get() / amount );
+        return property;
+    }
+
+    // BigDecimal operations
+
+    public static Property<BigDecimal> add( Property<BigDecimal> property, BigDecimal amount )
+    {
+        property.set( property.get().add( amount ) );
+        return property;
+    }
+
+    public static Property<BigDecimal> mult( Property<BigDecimal> property, BigDecimal amount )
+    {
+        property.set( property.get().multiply( amount ) );
+        return property;
+    }
+
+    public static Property<BigDecimal> sub( Property<BigDecimal> property, BigDecimal amount )
+    {
+        property.set( property.get().subtract( amount ) );
+        return property;
+    }
+
+    public static Property<BigDecimal> div( Property<BigDecimal> property, BigDecimal amount )
+    {
+        property.set( property.get().divide( amount ) );
+        return property;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/property/Property.java b/core/api/src/main/java/org/apache/polygene/api/property/Property.java
new file mode 100644
index 0000000..2cb2497
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/property/Property.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.api.property;
+
+/**
+ * Properties are declared in Composite interfaces by using this interface.
+ * <p>
+ * It creates a first-class object for the property from which you can get and set the value, and access any
+ * metadata about it.
+ * </p>
+ * <p>The type of the Property can be one of the following:</p>
+ * <ul>
+ * <li> A boxed primitive (Long,Integer,Boolean, etc.)</li>
+ * <li> String</li>
+ * <li> BigInteger</li>
+ * <li> BigDecimal</li>
+ * <li> Java Time API</li>
+ * <li> A serializable</li>
+ * <li> A ValueComposite</li>
+ * <li> A List, Set or Collection of any of the above</li>
+ * </ul>
+ *
+ * @param <T> Parameterized type of the Property
+ */
+public interface Property<T>
+{
+    /**
+     * Get the value of the property.
+     *
+     * @return the value
+     */
+    T get();
+
+    /**
+     * Set the value of the property
+     *
+     * @param newValue the new value
+     *
+     * @throws IllegalArgumentException if the value has an invalid value
+     * @throws IllegalStateException    if the property is immutable
+     */
+    void set( T newValue )
+        throws IllegalArgumentException, IllegalStateException;
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/property/PropertyDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/property/PropertyDescriptor.java
new file mode 100644
index 0000000..47a8db1
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/property/PropertyDescriptor.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.api.property;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Type;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.structure.MetaInfoHolder;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ValueType;
+
+/**
+ * Property Descriptor.
+ */
+public interface PropertyDescriptor extends MetaInfoHolder
+{
+    boolean isImmutable();
+
+    /**
+     * Get the qualified name of the property which is equal to:
+     * <pre><code>
+     * &lt;interface name&gt;:&lt;method name&gt;
+     * </code></pre>
+     *
+     * @return the qualified name of the property
+     */
+    QualifiedName qualifiedName();
+
+    /**
+     * Get the type of the property. If the property is declared
+     * as Property&lt;X&gt; then X is returned.
+     *
+     * @return the property type
+     */
+    Type type();
+
+    AccessibleObject accessor();
+
+    InitialValueProvider initialValueProvider();
+
+    Object resolveInitialValue(ModuleDescriptor moduleDescriptor);
+
+    ValueType valueType();
+
+    boolean queryable();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/property/PropertyMixin.java b/core/api/src/main/java/org/apache/polygene/api/property/PropertyMixin.java
new file mode 100644
index 0000000..1be3155
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/property/PropertyMixin.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.api.property;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.AppliesToFilter;
+import org.apache.polygene.api.injection.scope.State;
+
+/**
+ * Generic mixin for properties.
+ */
+// START SNIPPET: actual
+@AppliesTo( { PropertyMixin.PropertyFilter.class } )
+public final class PropertyMixin
+    implements InvocationHandler
+{
+    @State
+    private StateHolder state;
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        return state.propertyFor( method );
+    }
+
+    /**
+     * Filter Property methods to apply generic Property Mixin.
+     */
+    public static class PropertyFilter
+        implements AppliesToFilter
+    {
+        @Override
+        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> modifierClass )
+        {
+            return Property.class.isAssignableFrom( method.getReturnType() );
+        }
+    }
+}
+// END SNIPPET: actual
diff --git a/core/api/src/main/java/org/apache/polygene/api/property/PropertyWrapper.java b/core/api/src/main/java/org/apache/polygene/api/property/PropertyWrapper.java
new file mode 100644
index 0000000..85e703c
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/property/PropertyWrapper.java
@@ -0,0 +1,72 @@
+/*
+ *  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.polygene.api.property;
+
+/**
+ * If you want to catch getting and setting properties, then create a GenericConcern
+ * that wraps the Polygene-supplied Property instance with PropertyWrappers. Override
+ * get() and/or set() to perform your custom code.
+ */
+public class PropertyWrapper
+    implements Property<Object>
+{
+    protected Property<Object> next;
+
+    public PropertyWrapper( Property<Object> next )
+    {
+        this.next = next;
+    }
+
+    public Property<Object> next()
+    {
+        return next;
+    }
+
+    @Override
+    public Object get()
+    {
+        return next.get();
+    }
+
+    @Override
+    public void set( Object newValue )
+        throws IllegalArgumentException, IllegalStateException
+    {
+        next.set( newValue );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return next.hashCode();
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        return next.equals( obj );
+    }
+
+    @Override
+    public String toString()
+    {
+        return next.toString();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/property/StateHolder.java b/core/api/src/main/java/org/apache/polygene/api/property/StateHolder.java
new file mode 100644
index 0000000..bd80f13
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/property/StateHolder.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.api.property;
+
+import java.lang.reflect.AccessibleObject;
+import java.util.stream.Stream;
+
+/**
+ * This represents the state of a composite (properties).
+ */
+public interface StateHolder
+{
+    /**
+     * Get a property for a specific accessor
+     *
+     * @param <T> Property type
+     * @param accessor of the property
+     *
+     * @return the property
+     *
+     * @throws IllegalArgumentException if no property for given accessor exists
+     */
+    <T> Property<T> propertyFor( AccessibleObject accessor )
+        throws IllegalArgumentException;
+
+    Stream<? extends Property<?>> properties();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/property/package.html b/core/api/src/main/java/org/apache/polygene/api/property/package.html
new file mode 100644
index 0000000..95d7f77
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/property/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Property API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/MissingIndexingSystemException.java b/core/api/src/main/java/org/apache/polygene/api/query/MissingIndexingSystemException.java
new file mode 100644
index 0000000..e15cbee
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/MissingIndexingSystemException.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.api.query;
+
+/**
+ * This Exception is thrown in <code>QueryBuilderFactory.newQueryBuilder()</code> method if
+ * no indexing subsystem has been declared in the assembly.
+ */
+public final class MissingIndexingSystemException
+    extends QueryException
+{
+    private static final long serialVersionUID = 5147421865890379209L;
+
+    public MissingIndexingSystemException()
+    {
+        super( "No EntityFinder has been declared in the assembly of the application." );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/NotQueryableException.java b/core/api/src/main/java/org/apache/polygene/api/query/NotQueryableException.java
new file mode 100644
index 0000000..fc6c2a4
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/NotQueryableException.java
@@ -0,0 +1,87 @@
+/*
+ *  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.polygene.api.query;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.GenericPropertyInfo;
+import org.apache.polygene.api.util.Classes;
+
+/**
+ * Thrown in case that a non queryable type or accessor (marked with @Queriable(false)) is used during query building,
+ * or when non-Property, non-Associations are trying to be queried (possibly can not happen).
+ */
+public class NotQueryableException extends QueryException
+{
+    /**
+     * Constructor.
+     *
+     * @param message exception message
+     */
+    public NotQueryableException( final String message )
+    {
+        super( message );
+    }
+
+    /**
+     * Verify that the provided accessor method has not been marked with a Queryable(false).
+     *
+     * @param accessor accessor method
+     *
+     * @throws NotQueryableException - If accessor method has been marked as not queryable
+     */
+    public static void throwIfNotQueryable( final AccessibleObject accessor )
+    {
+        Queryable queryable = accessor.getAnnotation( Queryable.class );
+        if( queryable != null && !queryable.value() )
+        {
+            throw new NotQueryableException(
+                String.format(
+                    "%1$s \"%2$s\" (%3$s) is not queryable as has been marked with @Queryable(false)",
+                    Classes.RAW_CLASS.apply( GenericPropertyInfo.propertyTypeOf( accessor ) ).getSimpleName(),
+                    ( (Member) accessor ).getName(),
+                    ( (Member) accessor ).getDeclaringClass().getName()
+                )
+            );
+        }
+    }
+
+    /**
+     * Verify that the provided type has not been marked with a Queryable(false).
+     *
+     * @param type a type
+     *
+     * @throws NotQueryableException - If type has been marked as not queryable
+     */
+    public static void throwIfNotQueryable( final Class<?> type )
+    {
+        Queryable queryable = type.getAnnotation( Queryable.class );
+        if( queryable != null && !queryable.value() )
+        {
+            throw new NotQueryableException(
+                String.format(
+                    "Type \"%1$s\" is not queryable as has been marked with @Queryable(false)",
+                    type.getName()
+                )
+            );
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/Query.java b/core/api/src/main/java/org/apache/polygene/api/query/Query.java
new file mode 100644
index 0000000..2c43da7
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/Query.java
@@ -0,0 +1,144 @@
+/*
+ *  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.polygene.api.query;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.grammar.OrderBy;
+
+/**
+ * This represents a Query in an indexing system. It is created from a
+ * {@link QueryBuilder}, which decides the "where" clause in the query.
+ * <p>
+ * Additional limitations, such as paging, ordering, and variables, can be set on
+ * a Query before it is executed by calling one of find(), iterator(),
+ * or count().
+ * </p>
+ * <p>
+ * DDD tip: typically Queries are created in the Domain Model and passed to the UI,
+ * which sets the order and paging before executing it.
+ * </p>
+ *
+ * @param <T> Entity type
+ */
+public interface Query<T> extends Iterable<T>
+{
+    /**
+     * Set the ordering rules. If many segments are used for ordering
+     * then they will be applied in order.
+     *
+     * @param segments the segments to order by
+     *
+     * @return the Query
+     */
+    Query<T> orderBy( OrderBy... segments );
+
+    /**
+     * Append an ordering rule to the existing segments.
+     *
+     * @param property the property to order by
+     * @param order the order to apply
+     *
+     * @return the Query
+     */
+    Query<T> orderBy( final Property<?> property, final OrderBy.Order order );
+
+    /**
+     * Append an ascending ordering rule to the existing segments.
+     *
+     * @param property the property to order by
+     *
+     * @return the Query
+     */
+    Query<T> orderBy( Property<?> property );
+
+    /**
+     * Set the index of the first result. Default is 0 (zero).
+     *
+     * @param firstResult which index to use as the first one
+     *
+     * @return the Query
+     */
+    Query<T> firstResult( int firstResult );
+
+    /**
+     * Set how many results should be returned. Default is that
+     * there is no limit set.
+     *
+     * @param maxResults that shouldbe returned
+     *
+     * @return the query
+     */
+    Query<T> maxResults( int maxResults );
+
+    /**
+     * Get the first Entity that matches the criteria. This
+     * executes the Query.
+     *
+     * @return the first found Entity or null if none were found
+     *
+     * @throws QueryExecutionException if the query fails
+     */
+    T find()
+        throws QueryExecutionException;
+
+    /**
+     * Set the value of a named variable.
+     *
+     * @param name  of the variable
+     * @param value of the variable
+     *
+     * @return the query
+     */
+    Query<T> setVariable( String name, Object value );
+
+    /**
+     * Get the value of a named variable.
+     *
+     * @param <V> Variable type
+     * @param name of the variable
+     *
+     * @return value of the variable
+     */
+    <V> V getVariable( String name );
+
+    /**
+     * Get the result type of this Query
+     *
+     * @return the result type
+     */
+    Class<T> resultType();
+
+    /**
+     * Count how many results would be returned by this Query.
+     * This executes the Query.
+     *
+     * @return result count
+     *
+     * @throws QueryExecutionException if the query fails
+     */
+    long count()
+        throws QueryExecutionException;
+
+    /**
+     * @return Stream results
+     */
+    Stream<T> stream();
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/QueryBuilder.java b/core/api/src/main/java/org/apache/polygene/api/query/QueryBuilder.java
new file mode 100644
index 0000000..b130e13
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/QueryBuilder.java
@@ -0,0 +1,58 @@
+/*
+ *  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.polygene.api.query;
+
+import java.util.function.Predicate;
+import org.apache.polygene.api.composite.Composite;
+
+/**
+ * QueryBuilders are used to create {@link Query} instances.
+ * Iteratively add where() clauses to the query, and then use
+ * {@link org.apache.polygene.api.unitofwork.UnitOfWork#newQuery(QueryBuilder)}  to instantiate the Query.
+ * QueryBuilders are immutable, so when adding new where-clauses you get new instances. This
+ *
+ * DDD tip: Query objects are not executed immediately, so they
+ * should be constructed in the domain model and handed over to
+ * the UI, which can then further constrain it before actual
+ * execution.
+ *
+ * @param <T> Entity type
+ */
+public interface QueryBuilder<T>
+{
+    /**
+     * Add a where-clause to the Query. Use {@link QueryExpressions}
+     * to create the expression.
+     *
+     * @param specification the where clause
+     *
+     * @return a new builder with the added where-clause
+     */
+    QueryBuilder<T> where( Predicate<Composite> specification );
+
+    /**
+     * Create a new query with the declared where-clauses that will be evaluated against the iterable entries.
+     *
+     * @param iterable collection of objects (composites?)
+     *
+     * @return a new Query instance
+     */
+    Query<T> newQuery( Iterable<T> iterable );
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/QueryBuilderFactory.java b/core/api/src/main/java/org/apache/polygene/api/query/QueryBuilderFactory.java
new file mode 100644
index 0000000..19ee958
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/QueryBuilderFactory.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.api.query;
+
+/**
+ * This is used to create QueryBuilders.
+ *
+ * @see QueryBuilder
+ */
+public interface QueryBuilderFactory
+{
+    /**
+     * Create a new QueryBuilder.
+     *
+     * @param <T> Result type
+     * @param resultType the type of the result that you want
+     *
+     * @return a QueryBuilder
+     *
+     * @throws MissingIndexingSystemException if there is no EntityFinder service available
+     */
+    <T> QueryBuilder<T> newQueryBuilder( Class<T> resultType )
+        throws MissingIndexingSystemException;
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/QueryException.java b/core/api/src/main/java/org/apache/polygene/api/query/QueryException.java
new file mode 100644
index 0000000..f4cd2a6
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/QueryException.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.api.query;
+
+/**
+ * Base class for Query exceptions.
+ */
+public abstract class QueryException extends RuntimeException
+{
+    public QueryException()
+    {
+    }
+
+    public QueryException( final String message )
+    {
+        super( message );
+    }
+
+    public QueryException( final String message, final Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/QueryExecutionException.java b/core/api/src/main/java/org/apache/polygene/api/query/QueryExecutionException.java
new file mode 100644
index 0000000..bbed7f7
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/QueryExecutionException.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.api.query;
+
+/**
+ * Throw this exception if a query could not be executed
+ */
+public final class QueryExecutionException
+    extends QueryException
+{
+    private static final long serialVersionUID = 5147421865890379209L;
+
+    public QueryExecutionException( String message )
+    {
+        super( message );
+    }
+
+    public QueryExecutionException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/QueryExpressionException.java b/core/api/src/main/java/org/apache/polygene/api/query/QueryExpressionException.java
new file mode 100644
index 0000000..7b7731f
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/QueryExpressionException.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.api.query;
+
+/**
+ * Throw this exception if a QueryExpression is invalid.
+ */
+public class QueryExpressionException
+    extends QueryException
+{
+    public QueryExpressionException( String message )
+    {
+        super( message );
+    }
+
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/QueryExpressions.java b/core/api/src/main/java/org/apache/polygene/api/query/QueryExpressions.java
new file mode 100644
index 0000000..945b176
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/QueryExpressions.java
@@ -0,0 +1,964 @@
+/*
+ *  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.polygene.api.query;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Predicate;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.GenericAssociationInfo;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.property.GenericPropertyInfo;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.grammar.AndPredicate;
+import org.apache.polygene.api.query.grammar.AssociationFunction;
+import org.apache.polygene.api.query.grammar.AssociationNotNullPredicate;
+import org.apache.polygene.api.query.grammar.AssociationNullPredicate;
+import org.apache.polygene.api.query.grammar.ContainsAllPredicate;
+import org.apache.polygene.api.query.grammar.ContainsPredicate;
+import org.apache.polygene.api.query.grammar.EqPredicate;
+import org.apache.polygene.api.query.grammar.GePredicate;
+import org.apache.polygene.api.query.grammar.GtPredicate;
+import org.apache.polygene.api.query.grammar.LePredicate;
+import org.apache.polygene.api.query.grammar.LtPredicate;
+import org.apache.polygene.api.query.grammar.ManyAssociationContainsPredicate;
+import org.apache.polygene.api.query.grammar.ManyAssociationFunction;
+import org.apache.polygene.api.query.grammar.MatchesPredicate;
+import org.apache.polygene.api.query.grammar.NamedAssociationContainsNamePredicate;
+import org.apache.polygene.api.query.grammar.NamedAssociationContainsPredicate;
+import org.apache.polygene.api.query.grammar.NamedAssociationFunction;
+import org.apache.polygene.api.query.grammar.NePredicate;
+import org.apache.polygene.api.query.grammar.Notpredicate;
+import org.apache.polygene.api.query.grammar.OrPredicate;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.api.query.grammar.PropertyFunction;
+import org.apache.polygene.api.query.grammar.PropertyNotNullPredicate;
+import org.apache.polygene.api.query.grammar.PropertyNullPredicate;
+import org.apache.polygene.api.query.grammar.PropertyReference;
+import org.apache.polygene.api.query.grammar.Variable;
+
+import static org.apache.polygene.api.identity.HasIdentity.IDENTITY_METHOD;
+
+/**
+ * Static factory methods for query expressions and operators.
+ */
+public final class QueryExpressions
+{
+    // This is used for eq(Association,Composite)
+
+    // Templates and variables -----------------------------------------------|
+
+    /**
+     * Create a Query Template using the given type.
+     *
+     * @param <T> the type of the template
+     * @param clazz a class declaring the type of the template
+     *
+     * @return a new Query Template
+     */
+    public static <T> T templateFor( Class<T> clazz )
+    {
+        Objects.requireNonNull( clazz,"Template class" );
+
+        if( clazz.isInterface() )
+        {
+            return clazz.cast( Proxy.newProxyInstance( clazz.getClassLoader(),
+                                                       array( clazz ),
+                                                       new TemplateHandler<T>( null, null, null, null ) ) );
+        }
+        else
+        {
+            try
+            {
+                T mixin = clazz.newInstance();
+                for( Field field : clazz.getFields() )
+                {
+                    if( field.getAnnotation( State.class ) != null )
+                    {
+                        if( field.getType().equals( Property.class ) )
+                        {
+                            field.set( mixin,
+                                       Proxy.newProxyInstance( field.getType().getClassLoader(),
+                                                               array( field.getType() ),
+                                                               new PropertyReferenceHandler<>( new PropertyFunction<T>( null, null, null, null, field ) ) ) );
+                        }
+                        else if( field.getType().equals( Association.class ) )
+                        {
+                            field.set( mixin,
+                                       Proxy.newProxyInstance( field.getType().getClassLoader(),
+                                                               array( field.getType() ),
+                                                               new AssociationReferenceHandler<>( new AssociationFunction<T>( null, null, null, field ) ) ) );
+                        }
+                        else if( field.getType().equals( ManyAssociation.class ) )
+                        {
+                            field.set( mixin,
+                                       Proxy.newProxyInstance( field.getType().getClassLoader(),
+                                                               array( field.getType() ),
+                                                               new ManyAssociationReferenceHandler<>( new ManyAssociationFunction<T>( null, null, null, field ) ) ) );
+                        }
+                        else if( field.getType().equals( NamedAssociation.class ) )
+                        {
+                            field.set( mixin,
+                                       Proxy.newProxyInstance( field.getType().getClassLoader(),
+                                                               array( field.getType() ),
+                                                               new NamedAssociationReferenceHandler<>( new NamedAssociationFunction<T>( null, null, null, field ) ) ) );
+                        }
+                    }
+                }
+                return mixin;
+            }
+            catch( IllegalAccessException | IllegalArgumentException | InstantiationException | SecurityException e )
+            {
+                throw new IllegalArgumentException( "Cannot use class as template", e );
+            }
+        }
+    }
+
+    /**
+     * Create a Query Template using the given mixin class and association.
+     *
+     * @param <T> the type of the template
+     * @param mixinType  a class declaring the type of the template
+     * @param association an association
+     *
+     * @return a new Query Template
+     */
+    public static <T> T templateFor( final Class<T> mixinType, Association<?> association )
+    {
+        Objects.requireNonNull( mixinType, "Mixin class" );
+        Objects.requireNonNull( association, "Association" );
+        return mixinType.cast( Proxy.newProxyInstance( mixinType.getClassLoader(),
+                                                       array( mixinType ),
+                                                       new TemplateHandler<T>( null,
+                                                                               association( association ),
+                                                                               null,
+                                                                               null ) ) );
+    }
+
+    public static <T> T oneOf( final ManyAssociation<T> association )
+    {
+        Objects.requireNonNull( association, "association" );
+        return association.get( 0 );
+    }
+
+    public static <T> T oneOf( final NamedAssociation<T> association )
+    {
+        Objects.requireNonNull(  association, "Association" );
+        Iterator<String> iterator = association.iterator();
+        return association.get( iterator.hasNext() ? iterator.next() : null );
+    }
+
+    /**
+     * Create a new Query Variable.
+     *
+     * @param name a name for the Variable
+     *
+     * @return a new Query Variable.
+     */
+    public static Variable variable( String name )
+    {
+        Objects.requireNonNull(  name, "Variable name" );
+        return new Variable( name );
+    }
+
+    /**
+     * Create a new Query Template PropertyFunction.
+     *
+     * @param <T> type of the Property
+     * @param property a Property
+     *
+     * @return a new Query Template PropertyFunction
+     */
+    @SuppressWarnings( "unchecked" )
+    public static <T> PropertyFunction<T> property( Property<T> property )
+    {
+        return ( (PropertyReferenceHandler<T>) Proxy.getInvocationHandler( property ) ).property();
+    }
+
+    /**
+     * Create a new Query Property instance.
+     *
+     * @param <T> type of the Property
+     * @param mixinClass mixin of the Property
+     * @param fieldName name of the Property field
+     *
+     * @return a new Query Property instance for the given mixin and property name.
+     */
+    @SuppressWarnings( "unchecked" )
+    public static <T> Property<T> property( Class<?> mixinClass, String fieldName )
+    {
+        try
+        {
+            Field field = mixinClass.getField( fieldName );
+            if( !Property.class.isAssignableFrom( field.getType() ) )
+            {
+                throw new IllegalArgumentException( "Field must be of type Property<?>" );
+            }
+            return (Property<T>) Proxy.newProxyInstance(
+                mixinClass.getClassLoader(),
+                array( field.getType() ),
+                new PropertyReferenceHandler<>( new PropertyFunction<T>( null, null, null, null, field ) ) );
+        }
+        catch( NoSuchFieldException e )
+        {
+            throw new IllegalArgumentException( "No such field '" + fieldName + "' in mixin " + mixinClass.getName() );
+        }
+    }
+
+    /**
+     * Create a new Query Template AssociationFunction.
+     *
+     * @param <T> type of the Association
+     * @param association an Association
+     *
+     * @return a new Query Template AssociationFunction
+     */
+    @SuppressWarnings( "unchecked" )
+    public static <T> AssociationFunction<T> association( Association<T> association )
+    {
+        return ( (AssociationReferenceHandler<T>) Proxy.getInvocationHandler( association ) ).association();
+    }
+
+    /**
+     * Create a new Query Template ManyAssociationFunction.
+     *
+     * @param <T> type of the ManyAssociation
+     * @param association a ManyAssociation
+     *
+     * @return a new Query Template ManyAssociationFunction
+     */
+    @SuppressWarnings( "unchecked" )
+    public static <T> ManyAssociationFunction<T> manyAssociation( ManyAssociation<T> association )
+    {
+        return ( (ManyAssociationReferenceHandler<T>) Proxy.getInvocationHandler( association ) ).manyAssociation();
+    }
+
+    /**
+     * Create a new Query Template NamedAssociationFunction.
+     *
+     * @param <T> type of the NamedAssociation
+     * @param association a NamedAssociation
+     *
+     * @return a new Query Template NamedAssociationFunction
+     */
+    @SuppressWarnings( "unchecked" )
+    public static <T> NamedAssociationFunction<T> namedAssociation( NamedAssociation<T> association )
+    {
+        return ( (NamedAssociationReferenceHandler<T>) Proxy.getInvocationHandler( association ) ).namedAssociation();
+    }
+
+    // And/Or/Not ------------------------------------------------------------|
+    /**
+     * Create a new AND specification.
+     *
+     * @param left first operand
+     * @param right second operand
+     * @param optionalRight optional operands
+     *
+     * @return a new AND specification
+     */
+    @SafeVarargs
+    public static AndPredicate and( Predicate<Composite> left,
+                                    Predicate<Composite> right,
+                                    Predicate<Composite>... optionalRight
+    )
+    {
+        List<Predicate<Composite>> predicates = new ArrayList<>( 2 + optionalRight.length );
+        predicates.add( left );
+        predicates.add( right );
+        Collections.addAll( predicates, optionalRight );
+        return new AndPredicate( predicates );
+    }
+
+    /**
+     * Create a new OR specification.
+     *
+     * @param specs operands
+     *
+     * @return a new OR specification
+     */
+    @SafeVarargs
+    public static OrPredicate or( Predicate<Composite>... specs )
+    {
+        return new OrPredicate( Arrays.asList( specs ) );
+    }
+
+    /**
+     * Create a new NOT specification.
+     *
+     * @param operand specification to be negated
+     *
+     * @return a new NOT specification
+     */
+    public static Notpredicate not( Predicate<Composite> operand )
+    {
+        return new Notpredicate( operand );
+    }
+
+    // Comparisons -----------------------------------------------------------|
+
+    /**
+     * Create a new EQUALS specification for a Property.
+     *
+     * @param <T> Property type
+     * @param property a Property
+     * @param value its value
+     *
+     * @return a new EQUALS specification for a Property.
+     */
+    public static <T> EqPredicate<T> eq( Property<T> property, T value )
+    {
+        return new EqPredicate<>( property( property ), value );
+    }
+
+    /**
+     * Create a new EQUALS specification for a Property using a named Variable.
+     *
+     * @param <T> Property type
+     * @param property a Property
+     * @param variable a Query Variable
+     *
+     * @return a new EQUALS specification for a Property using a named Variable.
+     */
+    @SuppressWarnings( {"raw", "unchecked"} )
+    public static <T> EqPredicate<T> eq( Property<T> property, Variable variable )
+    {
+        return new EqPredicate( property( property ), variable );
+    }
+
+    /**
+     * Create a new EQUALS specification for an Association.
+     *
+     * @param <T> Association type
+     * @param association an Association
+     * @param value its value
+     *
+     * @return a new EQUALS specification for an Association.
+     */
+    public static <T> EqPredicate<Identity> eq( Association<T> association, T value )
+    {
+        return new EqPredicate<>(
+                new PropertyFunction<>(
+                        null,
+                        association(association),
+                        null,
+                        null,
+                        IDENTITY_METHOD),
+                ((HasIdentity) value).identity().get());
+    }
+
+    /**
+     * Create a new GREATER OR EQUALS specification for a Property.
+     *
+     * @param <T> Property type
+     * @param property a Property
+     * @param value its value
+     *
+     * @return a new GREATER OR EQUALS specification for a Property.
+     */
+    public static <T> GePredicate<T> ge( Property<T> property, T value )
+    {
+        return new GePredicate<>( property( property ), value );
+    }
+
+    /**
+     * Create a new GREATER OR EQUALS specification for a Property using a named Variable.
+     *
+     * @param <T> Property type
+     * @param property a Property
+     * @param variable a Query Variable
+     *
+     * @return a new GREATER OR EQUALS specification for a Property using a named Variable.
+     */
+    @SuppressWarnings( {"raw", "unchecked"} )
+    public static <T> GePredicate<T> ge( Property<T> property, Variable variable )
+    {
+        return new GePredicate( property( property ), variable );
+    }
+
+    /**
+     * Create a new GREATER THAN specification for a Property.
+     *
+     * @param <T> Property type
+     * @param property a Property
+     * @param value its value
+     *
+     * @return a new GREATER THAN specification for a Property.
+     */
+    public static <T> GtPredicate<T> gt( Property<T> property, T value )
+    {
+        return new GtPredicate<>( property( property ), value );
+    }
+
+    /**
+     * Create a new GREATER THAN specification for a Property using a named Variable.
+     *
+     * @param <T> Property type
+     * @param property a Property
+     * @param variable a Query Variable
+     *
+     * @return a new GREATER THAN specification for a Property using a named Variable.
+     */
+    @SuppressWarnings( {"raw", "unchecked"} )
+    public static <T> GtPredicate<T> gt( Property<T> property, Variable variable )
+    {
+        return new GtPredicate( property( property ), variable );
+    }
+
+    /**
+     * Create a new LESS OR EQUALS specification for a Property.
+     *
+     * @param <T> Property type
+     * @param property a Property
+     * @param value its value
+     *
+     * @return a new LESS OR EQUALS specification for a Property.
+     */
+    public static <T> LePredicate<T> le( Property<T> property, T value )
+    {
+        return new LePredicate<>( property( property ), value );
+    }
+
+    /**
+     * Create a new LESS OR EQUALS specification for a Property using a named Variable.
+     *
+     * @param <T> Property type
+     * @param property a Property
+     * @param variable a Query Variable
+     *
+     * @return a new LESS OR EQUALS specification for a Property using a named Variable.
+     */
+    @SuppressWarnings( {"raw", "unchecked"} )
+    public static <T> LePredicate<T> le( Property<T> property, Variable variable )
+    {
+        return new LePredicate( property( property ), variable );
+    }
+
+    /**
+     * Create a new LESSER THAN specification for a Property.
+     *
+     * @param <T> Property type
+     * @param property a Property
+     * @param value its value
+     *
+     * @return a new LESSER THAN specification for a Property.
+     */
+    public static <T> LtPredicate<T> lt( Property<T> property, T value )
+    {
+        return new LtPredicate<>( property( property ), value );
+    }
+
+    /**
+     * Create a new LESSER THAN specification for a Property using a named Variable.
+     *
+     * @param <T> Property type
+     * @param property a Property
+     * @param variable a Query Variable
+     *
+     * @return a new LESSER THAN specification for a Property using a named Variable.
+     */
+    @SuppressWarnings( {"raw", "unchecked"} )
+    public static <T> LtPredicate<T> lt( Property<T> property, Variable variable )
+    {
+        return new LtPredicate( property( property ), variable );
+    }
+
+    /**
+     * Create a new NOT EQUALS specification for a Property.
+     *
+     * @param <T> Property type
+     * @param property a Property
+     * @param value its value
+     *
+     * @return a new NOT EQUALS specification for a Property.
+     */
+    public static <T> NePredicate<T> ne( Property<T> property, T value )
+    {
+        return new NePredicate<>( property( property ), value );
+    }
+
+    /**
+     * Create a new NOT EQUALS specification for a Property using a named Variable.
+     *
+     * @param <T> Property type
+     * @param property a Property
+     * @param variable a Query Variable
+     *
+     * @return a new NOT EQUALS specification for a Property using a named Variable.
+     */
+    @SuppressWarnings( {"raw", "unchecked"} )
+    public static <T> NePredicate<T> ne( Property<T> property, Variable variable )
+    {
+        return new NePredicate( property( property ), variable );
+    }
+
+    /**
+     * Create a new REGULAR EXPRESSION specification for a Property.
+     *
+     * @param property a Property
+     * @param regexp its value
+     *
+     * @return a new REGULAR EXPRESSION specification for a Property.
+     */
+    public static MatchesPredicate matches( Property<String> property, String regexp )
+    {
+        return new MatchesPredicate( property( property ), regexp );
+    }
+
+    /**
+     * Create a new REGULAR EXPRESSION specification for a Property using a named Variable.
+     *
+     * @param property a Property
+     * @param variable a Query Variable
+     *
+     * @return a new REGULAR EXPRESSION specification for a Property using a named Variable.
+     */
+    public static MatchesPredicate matches( Property<String> property, Variable variable )
+    {
+        return new MatchesPredicate( property( property ), variable );
+    }
+
+    // Null checks -----------------------------------------------------------|
+
+    /**
+     * Create a new NOT NULL specification for a Property.
+     *
+     * @param <T> Property type
+     * @param property a Property
+     *
+     * @return a new NOT NULL specification for a Property.
+     */
+    public static <T> PropertyNotNullPredicate<T> isNotNull( Property<T> property )
+    {
+        return new PropertyNotNullPredicate<>( property( property ) );
+    }
+
+    /**
+     * Create a new NULL specification for a Property.
+     *
+     * @param <T> Property type
+     * @param property a Property
+     *
+     * @return a new NULL specification for a Property.
+     */
+    public static <T> PropertyNullPredicate<T> isNull( Property<T> property )
+    {
+        return new PropertyNullPredicate<>( property( property ) );
+    }
+
+    /**
+     * Create a new NOT NULL specification for an Association.
+     *
+     * @param <T> Association type
+     * @param association an Association
+     *
+     * @return a new NOT NULL specification for an Association.
+     */
+    public static <T> AssociationNotNullPredicate<T> isNotNull( Association<T> association )
+    {
+        return new AssociationNotNullPredicate<>( association( association ) );
+    }
+
+    /**
+     * Create a new NULL specification for an Association.
+     *
+     * @param <T> Association type
+     * @param association an Association
+     *
+     * @return a new NULL specification for an Association.
+     */
+    public static <T> AssociationNullPredicate<T> isNull( Association<T> association )
+    {
+        return new AssociationNullPredicate<>( association( association ) );
+    }
+
+    // Collections -----------------------------------------------------------|
+
+    /**
+     * Create a new CONTAINS ALL specification for a Collection Property.
+     *
+     * @param <T> Collection property type
+     * @param collectionProperty a Collection Property
+     * @param values its values
+     *
+     * @return a new CONTAINS ALL specification for a Collection Property.
+     */
+    public static <T> ContainsAllPredicate<T> containsAll( Property<? extends Collection<T>> collectionProperty,
+                                                           Collection<T> values )
+    {
+        Objects.requireNonNull( values, "Values" );
+        return new ContainsAllPredicate<>( property( collectionProperty ), values );
+    }
+
+    /**
+     * Create a new CONTAINS ALL specification for a Collection Property using named Variables.
+     *
+     * @param <T> Collection property type
+     * @param collectionProperty a Collection Property
+     * @param variables named Variables
+     *
+     * @return a new CONTAINS ALL specification for a Collection Property using named Variables.
+     */
+    @SuppressWarnings( {"raw", "unchecked"} )
+    public static <T> ContainsAllPredicate<T> containsAllVariables(
+        Property<? extends Collection<T>> collectionProperty,
+        Collection<Variable> variables )
+    {
+        Objects.requireNonNull( variables, "Variables" );
+        return new ContainsAllPredicate( property( collectionProperty ), variables );
+    }
+
+    /**
+     * Create a new CONTAINS specification for a Collection Property.
+     *
+     * @param <T> Collection property type
+     * @param collectionProperty a Collection Property
+     * @param value the value
+     *
+     * @return a new CONTAINS specification for a Collection Property.
+     */
+    public static <T> ContainsPredicate<T> contains( Property<? extends Collection<T>> collectionProperty,
+                                                         T value )
+    {
+        Objects.requireNonNull( value, "Value" );
+        return new ContainsPredicate<>( property( collectionProperty ), value );
+    }
+
+    /**
+     * Create a new CONTAINS specification for a Collection Property using named Variables.
+     *
+     * @param <T> Collection property type
+     * @param collectionProperty a Collection Property
+     * @param variable named Variable
+     *
+     * @return a new CONTAINS specification for a Collection Property using named Variables.
+     */
+    @SuppressWarnings( {"raw", "unchecked"} )
+    public static <T> ContainsPredicate<T> contains( Property<? extends Collection<T>> collectionProperty,
+                                                         Variable variable )
+    {
+        Objects.requireNonNull( variable, "Variable" );
+        return new ContainsPredicate( property( collectionProperty ), variable );
+    }
+
+    /**
+     * Create a new CONTAINS specification for a ManyAssociation.
+     *
+     * @param <T> ManyAssociation type
+     * @param manyAssoc  a ManyAssociation
+     * @param value the value
+     *
+     * @return a new CONTAINS specification for a ManyAssociation.
+     */
+    public static <T> ManyAssociationContainsPredicate<T> contains( ManyAssociation<T> manyAssoc, T value )
+    {
+        return new ManyAssociationContainsPredicate<>( manyAssociation( manyAssoc ), value );
+    }
+
+    /**
+     * Create a new CONTAINS specification for a NamedAssociation.
+     *
+     * @param <T> NamedAssociation type
+     * @param namedAssoc  a NamedAssociation
+     * @param value the value
+     *
+     * @return a new CONTAINS specification for a NamedAssociation.
+     */
+    public static <T> NamedAssociationContainsPredicate<T> contains( NamedAssociation<T> namedAssoc, T value )
+    {
+        return new NamedAssociationContainsPredicate<>( namedAssociation( namedAssoc ), value );
+    }
+
+    /**
+     * Create a new CONTAINS NAME specification for a NamedAssociation.
+     *
+     * @param <T> NamedAssociation type
+     * @param namedAssoc  a NamedAssociation
+     * @param name the name
+     *
+     * @return a new CONTAINS NAME specification for a NamedAssociation.
+     */
+    public static <T> NamedAssociationContainsNamePredicate<T> containsName( NamedAssociation<T> namedAssoc,
+                                                                                 String name )
+    {
+        return new NamedAssociationContainsNamePredicate<>( namedAssociation( namedAssoc ), name );
+    }
+
+    // Ordering --------------------------------------------------------------|
+    /**
+     * Create a new Query ascending order segment for a Property.
+     *
+     * @param <T> type of the Property
+     * @param property a Property
+     *
+     * @return a new Query ascending order segment for a Property.
+     */
+    public static <T> OrderBy orderBy( final Property<T> property )
+    {
+        return orderBy( property, OrderBy.Order.ASCENDING );
+    }
+
+    /**
+     * Create a new Query ordering segment for a Property.
+     *
+     * @param <T> type of the Property
+     * @param property a Property
+     * @param order ascending or descending
+     *
+     * @return a new Query ordering segment for a Property.
+     */
+    public static <T> OrderBy orderBy( final Property<T> property, final OrderBy.Order order )
+    {
+        return new OrderBy( property( property ), order );
+    }
+
+    // Query Templates InvocationHandlers ------------------------------------|
+
+    private static class TemplateHandler<T>
+        implements InvocationHandler
+    {
+        private final PropertyFunction<?> compositeProperty;
+        private final AssociationFunction<?> compositeAssociation;
+        private final ManyAssociationFunction<?> compositeManyAssociation;
+        private final NamedAssociationFunction<?> compositeNamedAssociation;
+
+        private TemplateHandler( PropertyFunction<?> compositeProperty,
+                                 AssociationFunction<?> compositeAssociation,
+                                 ManyAssociationFunction<?> compositeManyAssociation,
+                                 NamedAssociationFunction<?> compositeNamedAssociation
+        )
+        {
+            this.compositeProperty = compositeProperty;
+            this.compositeAssociation = compositeAssociation;
+            this.compositeManyAssociation = compositeManyAssociation;
+            this.compositeNamedAssociation = compositeNamedAssociation;
+        }
+
+        @Override
+        public Object invoke( Object o, Method method, Object[] objects )
+            throws Throwable
+        {
+            if( Property.class.isAssignableFrom( method.getReturnType() ) )
+            {
+                return Proxy.newProxyInstance(
+                    method.getReturnType().getClassLoader(),
+                    array( method.getReturnType() ),
+                    new PropertyReferenceHandler<>( new PropertyFunction<T>( compositeProperty,
+                                                                             compositeAssociation,
+                                                                             compositeManyAssociation,
+                                                                             compositeNamedAssociation,
+                                                                             method ) ) );
+            }
+            else if( Association.class.isAssignableFrom( method.getReturnType() ) )
+            {
+                return Proxy.newProxyInstance(
+                    method.getReturnType().getClassLoader(),
+                    array( method.getReturnType() ),
+                    new AssociationReferenceHandler<>( new AssociationFunction<T>( compositeAssociation,
+                                                                                   compositeManyAssociation,
+                                                                                   compositeNamedAssociation,
+                                                                                   method ) ) );
+            }
+            else if( ManyAssociation.class.isAssignableFrom( method.getReturnType() ) )
+            {
+                return Proxy.newProxyInstance(
+                    method.getReturnType().getClassLoader(),
+                    array( method.getReturnType() ),
+                    new ManyAssociationReferenceHandler<>( new ManyAssociationFunction<T>( compositeAssociation,
+                                                                                           compositeManyAssociation,
+                                                                                           compositeNamedAssociation,
+                                                                                           method ) ) );
+            }
+            else if( NamedAssociation.class.isAssignableFrom( method.getReturnType() ) )
+            {
+                return Proxy.newProxyInstance(
+                    method.getReturnType().getClassLoader(),
+                    array( method.getReturnType() ),
+                    new NamedAssociationReferenceHandler<>( new NamedAssociationFunction<T>( compositeAssociation,
+                                                                                             compositeManyAssociation,
+                                                                                             compositeNamedAssociation,
+                                                                                             method ) ) );
+            }
+
+            return null;
+        }
+    }
+
+    private static class PropertyReferenceHandler<T>
+        implements InvocationHandler
+    {
+        private final PropertyFunction<T> property;
+
+        private PropertyReferenceHandler( PropertyFunction<T> property )
+        {
+            this.property = property;
+        }
+
+        private PropertyFunction<T> property()
+        {
+            return property;
+        }
+
+        @Override
+        public Object invoke( Object o, final Method method, Object[] objects )
+            throws Throwable
+        {
+            if( method.equals( Property.class.getMethod( "get" ) ) )
+            {
+                Type propertyType = GenericPropertyInfo.propertyTypeOf( property.accessor() );
+                if( propertyType.getClass().equals( Class.class ) )
+                {
+                    return Proxy.newProxyInstance( method.getDeclaringClass().getClassLoader(),
+                                                   array( (Class<?>) propertyType, PropertyReference.class ),
+                                                   new TemplateHandler<T>( property, null, null, null ) );
+                }
+            }
+
+            return null;
+        }
+    }
+
+    private static class AssociationReferenceHandler<T>
+        implements InvocationHandler
+    {
+        private final AssociationFunction<T> association;
+
+        private AssociationReferenceHandler( AssociationFunction<T> association )
+        {
+            this.association = association;
+        }
+
+        private AssociationFunction<T> association()
+        {
+            return association;
+        }
+
+        @Override
+        public Object invoke( Object o, final Method method, Object[] objects )
+            throws Throwable
+        {
+            if( method.equals( Association.class.getMethod( "get" ) ) )
+            {
+                Type associationType = GenericAssociationInfo.associationTypeOf( association.accessor() );
+                if( associationType.getClass().equals( Class.class ) )
+                {
+                    return Proxy.newProxyInstance( method.getDeclaringClass().getClassLoader(),
+                                                   array( (Class) associationType, PropertyReference.class ),
+                                                   new TemplateHandler<T>( null, association, null, null ) );
+                }
+            }
+
+            return null;
+        }
+    }
+
+    private static class ManyAssociationReferenceHandler<T>
+        implements InvocationHandler
+    {
+        private final ManyAssociationFunction<T> manyAssociation;
+
+        private ManyAssociationReferenceHandler( ManyAssociationFunction<T> manyAssociation )
+        {
+            this.manyAssociation = manyAssociation;
+        }
+
+        public ManyAssociationFunction<T> manyAssociation()
+        {
+            return manyAssociation;
+        }
+
+        @Override
+        public Object invoke( Object o, final Method method, Object[] objects )
+            throws Throwable
+        {
+            if( method.equals( ManyAssociation.class.getMethod( "get", Integer.TYPE ) ) )
+            {
+                Type manyAssociationType = GenericAssociationInfo.associationTypeOf( manyAssociation.accessor() );
+                if( manyAssociationType.getClass().equals( Class.class ) )
+                {
+                    return Proxy.newProxyInstance( method.getDeclaringClass().getClassLoader(),
+                                                   array( (Class) manyAssociationType, PropertyReference.class ),
+                                                   new TemplateHandler<T>( null, null, manyAssociation, null ) );
+                }
+            }
+
+            return null;
+        }
+    }
+
+    private static class NamedAssociationReferenceHandler<T>
+        implements InvocationHandler
+    {
+        private final NamedAssociationFunction<T> namedAssociation;
+
+        private NamedAssociationReferenceHandler( NamedAssociationFunction<T> namedAssociation )
+        {
+            this.namedAssociation = namedAssociation;
+        }
+
+        public NamedAssociationFunction<T> namedAssociation()
+        {
+            return namedAssociation;
+        }
+
+        @Override
+        public Object invoke( Object o, final Method method, Object[] objects )
+            throws Throwable
+        {
+            if( method.equals( NamedAssociation.class.getMethod( "get", String.class ) ) )
+            {
+                Type namedAssociationType = GenericAssociationInfo.associationTypeOf( namedAssociation.accessor() );
+                if( namedAssociationType.getClass().equals( Class.class ) )
+                {
+                    return Proxy.newProxyInstance( method.getDeclaringClass().getClassLoader(),
+                                                   array( (Class) namedAssociationType, PropertyReference.class ),
+                                                   new TemplateHandler<T>( null, null, null, namedAssociation ) );
+                }
+            }
+
+            return null;
+        }
+    }
+
+    @SafeVarargs
+    private static <T> T[] array( T... array )
+    {
+        return array;
+    }
+
+    private QueryExpressions()
+    {
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/AndPredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/AndPredicate.java
new file mode 100644
index 0000000..5e9c0bf
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/AndPredicate.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import java.util.Collection;
+import java.util.function.Predicate;
+import org.apache.polygene.api.composite.Composite;
+
+/**
+ * AND Specification.
+ */
+public class AndPredicate
+    extends BinaryPredicate
+{
+    public AndPredicate( Collection<Predicate<Composite>> operands )
+    {
+        super( operands );
+    }
+
+    @Override
+    public boolean test( Composite item )
+    {
+        Predicate<Composite> master = t -> true;
+        for( Predicate<Composite> p : operands )
+        {
+            master = master.and( p );
+        }
+        return master.test( item );
+    }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder( "(" );
+        String and = "";
+        for( Predicate<Composite> operand : operands )
+        {
+            sb.append( and ).append( operand );
+            and = " and ";
+        }
+        return sb.append( ")" ).toString();
+    }
+
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/AssociationFunction.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/AssociationFunction.java
new file mode 100644
index 0000000..1a77c69
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/AssociationFunction.java
@@ -0,0 +1,149 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.util.function.Function;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.association.GenericAssociationInfo;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.query.QueryExpressionException;
+import org.apache.polygene.api.util.Classes;
+
+import static org.apache.polygene.api.util.Classes.typeOf;
+
+/**
+ * Function to get Entity Associations
+ */
+public class AssociationFunction<T>
+    implements Function<Composite, Association<T>>
+{
+    private final AssociationFunction<?> traversedAssociation;
+    private final ManyAssociationFunction<?> traversedManyAssociation;
+    private final NamedAssociationFunction<?> traversedNamedAssociation;
+    private final AccessibleObject accessor;
+
+    public AssociationFunction( AssociationFunction<?> traversedAssociation,
+                                ManyAssociationFunction<?> traversedManyAssociation,
+                                NamedAssociationFunction<?> traversedNamedAssociation,
+                                AccessibleObject accessor
+    )
+    {
+        this.traversedAssociation = traversedAssociation;
+        this.traversedManyAssociation = traversedManyAssociation;
+        this.traversedNamedAssociation = traversedNamedAssociation;
+        this.accessor = accessor;
+
+        Type returnType = typeOf( accessor );
+        if( !Association.class.isAssignableFrom( Classes.RAW_CLASS.apply( returnType ) )
+            && !ManyAssociation.class.isAssignableFrom( Classes.RAW_CLASS.apply( returnType ) )
+            && !NamedAssociation.class.isAssignableFrom( Classes.RAW_CLASS.apply( returnType ) ) )
+        {
+            throw new QueryExpressionException( "Unsupported association type:" + returnType );
+        }
+        Type associationTypeAsType = GenericAssociationInfo.toAssociationType( returnType );
+        if( !( associationTypeAsType instanceof Class ) )
+        {
+            throw new QueryExpressionException( "Unsupported association type:" + associationTypeAsType );
+        }
+    }
+
+    public AssociationFunction<?> traversedAssociation()
+    {
+        return traversedAssociation;
+    }
+
+    public ManyAssociationFunction<?> traversedManyAssociation()
+    {
+        return traversedManyAssociation;
+    }
+
+    public NamedAssociationFunction<?> traversedNamedAssociation()
+    {
+        return traversedNamedAssociation;
+    }
+
+    public AccessibleObject accessor()
+    {
+        return accessor;
+    }
+
+    @Override
+    public Association<T> apply( Composite entity )
+    {
+        try
+        {
+            Object target = entity;
+            if( traversedAssociation != null )
+            {
+                Association<?> association = traversedAssociation.apply( entity );
+                if( association == null )
+                {
+                    return null;
+                }
+                target = association.get();
+            }
+            else if( traversedManyAssociation != null )
+            {
+                throw new IllegalArgumentException( "Cannot evaluate a ManyAssociation" );
+            }
+            else if( traversedNamedAssociation != null )
+            {
+                throw new IllegalArgumentException( "Cannot evaluate a NamedAssociation" );
+            }
+
+            if( target == null )
+            {
+                return null;
+            }
+
+            CompositeInstance handler = (CompositeInstance) Proxy.getInvocationHandler( target );
+            return ( (AssociationStateHolder) handler.state() ).associationFor( accessor );
+        }
+        catch( IllegalArgumentException e )
+        {
+            throw e;
+        }
+        catch( Throwable e )
+        {
+            throw new IllegalArgumentException( e );
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        if( traversedAssociation != null )
+        {
+            return traversedAssociation.toString() + "." + ( (Member) accessor ).getName();
+        }
+        else
+        {
+            return ( (Member) accessor ).getName();
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/AssociationNotNullPredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/AssociationNotNullPredicate.java
new file mode 100644
index 0000000..b4f1f64
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/AssociationNotNullPredicate.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.composite.Composite;
+
+/**
+ * Association not null Specification.
+ */
+public class AssociationNotNullPredicate<T>
+    extends ExpressionPredicate
+{
+    private AssociationFunction<T> association;
+
+    public AssociationNotNullPredicate( AssociationFunction<T> association )
+    {
+        this.association = association;
+    }
+
+    public AssociationFunction<T> association()
+    {
+        return association;
+    }
+
+    @Override
+    public boolean test( Composite item )
+    {
+        try
+        {
+            Association<T> assoc = association.apply( item );
+
+            if( assoc == null )
+            {
+                return false;
+            }
+
+            return assoc.get() != null;
+        }
+        catch( IllegalArgumentException e )
+        {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        return association.toString() + " is not null";
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/AssociationNullPredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/AssociationNullPredicate.java
new file mode 100644
index 0000000..ba1ec40
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/AssociationNullPredicate.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.composite.Composite;
+
+/**
+ * Association null Specification.
+ */
+public class AssociationNullPredicate<T>
+    extends ExpressionPredicate
+{
+    private AssociationFunction<T> association;
+
+    public AssociationNullPredicate( AssociationFunction<T> association )
+    {
+        this.association = association;
+    }
+
+    public AssociationFunction<T> association()
+    {
+        return association;
+    }
+
+    @Override
+    public boolean test( Composite item )
+    {
+        try
+        {
+            Association<T> assoc = association.apply( item );
+
+            if( assoc == null )
+            {
+                return true;
+            }
+
+            return assoc.get() == null;
+        }
+        catch( IllegalArgumentException e )
+        {
+            return true;
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        return association.toString() + " is null";
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/BinaryPredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/BinaryPredicate.java
new file mode 100644
index 0000000..cdc6919
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/BinaryPredicate.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.function.Predicate;
+import org.apache.polygene.api.composite.Composite;
+
+/**
+ * Base binary Specification, used for AND and OR Specifications..
+ */
+public abstract class BinaryPredicate
+    extends ExpressionPredicate
+{
+    protected final Collection<Predicate<Composite>> operands;
+
+    protected BinaryPredicate( Collection<Predicate<Composite>> operands )
+    {
+        this.operands = Collections.unmodifiableCollection( operands );
+    }
+
+    public Collection<Predicate<Composite>> operands()
+    {
+        return operands;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/ComparisonPredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/ComparisonPredicate.java
new file mode 100644
index 0000000..955f3ae
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/ComparisonPredicate.java
@@ -0,0 +1,77 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Base comparison Specification.
+ */
+public abstract class ComparisonPredicate<T>
+    extends ExpressionPredicate
+{
+    protected final PropertyFunction<T> property;
+    protected final T value;
+
+    public ComparisonPredicate( PropertyFunction<T> property, T value )
+    {
+        this.property = property;
+        this.value = value;
+    }
+
+    public PropertyFunction<T> property()
+    {
+        return property;
+    }
+
+    @Override
+    public final boolean test( Composite item )
+    {
+        try
+        {
+            Property<T> prop = property.apply( item );
+
+            if( prop == null )
+            {
+                return false;
+            }
+
+            T propValue = prop.get();
+            if( propValue == null )
+            {
+                return false;
+            }
+
+            return compare( propValue );
+        }
+        catch( IllegalArgumentException e )
+        {
+            return false;
+        }
+    }
+
+    protected abstract boolean compare( T value );
+
+    public T value()
+    {
+        return value;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/ContainsAllPredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/ContainsAllPredicate.java
new file mode 100644
index 0000000..b06c6f8
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/ContainsAllPredicate.java
@@ -0,0 +1,79 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import java.util.Collection;
+import java.util.Collections;
+import org.apache.polygene.api.composite.Composite;
+
+/**
+ * Contains All Specification.
+ */
+public class ContainsAllPredicate<T>
+    extends ExpressionPredicate
+{
+    private PropertyFunction<? extends Collection<T>> collectionProperty;
+    private Collection<T> valueCollection;
+
+    public ContainsAllPredicate( PropertyFunction<? extends Collection<T>> collectionProperty,
+                                 Collection<T> valueCollection
+    )
+    {
+        this.collectionProperty = collectionProperty;
+        this.valueCollection = Collections.unmodifiableCollection( valueCollection );
+    }
+
+    public PropertyFunction<? extends Collection<T>> collectionProperty()
+    {
+        return collectionProperty;
+    }
+
+    public Collection<T> containedValues()
+    {
+        return valueCollection;
+    }
+
+    @Override
+    public boolean test( Composite item )
+    {
+        Collection<T> collection = collectionProperty.apply( item ).get();
+
+        if( collection == null )
+        {
+            return false;
+        }
+
+        for( T value : valueCollection )
+        {
+            if( !collection.contains( value ) )
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    public String toString()
+    {
+        return collectionProperty + " contains " + valueCollection;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/ContainsPredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/ContainsPredicate.java
new file mode 100644
index 0000000..a277307
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/ContainsPredicate.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import java.util.Collection;
+import org.apache.polygene.api.composite.Composite;
+
+/**
+ * Contains Specification.
+ */
+public class ContainsPredicate<T>
+    extends ExpressionPredicate
+{
+    private PropertyFunction<? extends Collection<T>> collectionProperty;
+    private T value;
+
+    public ContainsPredicate( PropertyFunction<? extends Collection<T>> collectionProperty, T value )
+    {
+        this.collectionProperty = collectionProperty;
+        this.value = value;
+    }
+
+    public PropertyFunction<? extends Collection<T>> collectionProperty()
+    {
+        return collectionProperty;
+    }
+
+    public T value()
+    {
+        return value;
+    }
+
+    @Override
+    public boolean test( Composite item )
+    {
+        Collection<T> collection = collectionProperty.apply( item ).get();
+
+        if( collection == null )
+        {
+            return false;
+        }
+
+        return collection.contains( value );
+    }
+
+    @Override
+    public String toString()
+    {
+        return collectionProperty + " contains " + value;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/EqPredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/EqPredicate.java
new file mode 100644
index 0000000..84eb77a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/EqPredicate.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+/**
+ * Equals Specification.
+ */
+public class EqPredicate<T>
+    extends ComparisonPredicate<T>
+{
+    public EqPredicate( PropertyFunction<T> property, T value )
+    {
+        super( property, value );
+    }
+
+    @Override
+    protected boolean compare( T value )
+    {
+        return value.equals( this.value );
+    }
+
+    @Override
+    public String toString()
+    {
+        return property.toString() + "=" + value.toString();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/ExpressionPredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/ExpressionPredicate.java
new file mode 100644
index 0000000..94ec810
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/ExpressionPredicate.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import java.util.function.Predicate;
+import org.apache.polygene.api.composite.Composite;
+
+/**
+ * Base expression Specification.
+ */
+public abstract class ExpressionPredicate
+    implements Predicate<Composite>
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/GePredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/GePredicate.java
new file mode 100644
index 0000000..a9e7923
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/GePredicate.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+/**
+ * Greater or equals Specification.
+ */
+public class GePredicate<T>
+    extends ComparisonPredicate<T>
+{
+    public GePredicate( PropertyFunction<T> property, T value )
+    {
+        super( property, value );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    protected boolean compare( T value )
+    {
+        return ( (Comparable) value ).compareTo( this.value ) >= 0;
+    }
+
+    @Override
+    public String toString()
+    {
+        return property.toString() + ">=" + value.toString();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/GtPredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/GtPredicate.java
new file mode 100644
index 0000000..7558c8b
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/GtPredicate.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+/**
+ * Greater than Specification.
+ */
+public class GtPredicate<T>
+    extends ComparisonPredicate<T>
+{
+    public GtPredicate( PropertyFunction<T> property, T value )
+    {
+        super( property, value );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    protected boolean compare( T value )
+    {
+        return ( (Comparable) value ).compareTo( this.value ) > 0;
+    }
+
+    @Override
+    public String toString()
+    {
+        return property.toString() + ">" + value.toString();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/LePredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/LePredicate.java
new file mode 100644
index 0000000..a2ff287
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/LePredicate.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+/**
+ * Less or equals Specification.
+ */
+public class LePredicate<T>
+    extends ComparisonPredicate<T>
+{
+    public LePredicate( PropertyFunction<T> property, T value )
+    {
+        super( property, value );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    protected boolean compare( T value )
+    {
+        return ( (Comparable) value ).compareTo( this.value ) <= 0;
+    }
+
+    @Override
+    public String toString()
+    {
+        return property.toString() + "<=" + value.toString();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/LtPredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/LtPredicate.java
new file mode 100644
index 0000000..da2fb04
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/LtPredicate.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+/**
+ * Lesser than Specification.
+ */
+public class LtPredicate<T>
+    extends ComparisonPredicate<T>
+{
+    public LtPredicate( PropertyFunction<T> property, T value )
+    {
+        super( property, value );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    protected boolean compare( T value )
+    {
+        return ( (Comparable) value ).compareTo( this.value ) < 0;
+    }
+
+    @Override
+    public String toString()
+    {
+        return property.toString() + "<" + value.toString();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/ManyAssociationContainsPredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/ManyAssociationContainsPredicate.java
new file mode 100644
index 0000000..34c3161
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/ManyAssociationContainsPredicate.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.composite.Composite;
+
+/**
+ * ManyAssociation Contains Specification.
+ */
+public class ManyAssociationContainsPredicate<T>
+    extends ExpressionPredicate
+{
+    private final ManyAssociationFunction<T> manyAssociationFunction;
+    private final T value;
+
+    public ManyAssociationContainsPredicate( ManyAssociationFunction<T> manyAssociationFunction, T value )
+    {
+        this.manyAssociationFunction = manyAssociationFunction;
+        this.value = value;
+    }
+
+    public ManyAssociationFunction<T> manyAssociation()
+    {
+        return manyAssociationFunction;
+    }
+
+    public T value()
+    {
+        return value;
+    }
+
+    @Override
+    public boolean test( Composite item )
+    {
+        ManyAssociation<T> collection = manyAssociationFunction.apply( item );
+        if( collection == null )
+        {
+            return false;
+        }
+        return collection.contains( value );
+    }
+
+    @Override
+    public String toString()
+    {
+        return manyAssociationFunction + " contains:" + value;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/ManyAssociationFunction.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/ManyAssociationFunction.java
new file mode 100644
index 0000000..4d91a24
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/ManyAssociationFunction.java
@@ -0,0 +1,118 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.lang.reflect.Proxy;
+import java.util.function.Function;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.CompositeInstance;
+
+/**
+ * Function to get Entity ManyAssociations.
+ */
+public class ManyAssociationFunction<T>
+    implements Function<Composite, ManyAssociation<T>>
+{
+    private final AssociationFunction<?> traversedAssociation;
+    private final ManyAssociationFunction<?> traversedManyAssociation;
+    private final NamedAssociationFunction<?> traversedNamedAssociation;
+    private final AccessibleObject accessor;
+
+    public ManyAssociationFunction( AssociationFunction<?> traversedAssociation,
+                                    ManyAssociationFunction<?> traversedManyAssociation,
+                                    NamedAssociationFunction<?> traversedNamedAssociation,
+                                    AccessibleObject accessor
+    )
+    {
+        this.traversedAssociation = traversedAssociation;
+        this.traversedManyAssociation = traversedManyAssociation;
+        this.traversedNamedAssociation = traversedNamedAssociation;
+        this.accessor = accessor;
+    }
+
+    public AssociationFunction<?> traversedAssociation()
+    {
+        return traversedAssociation;
+    }
+
+    public ManyAssociationFunction<?> traversedManyAssociation()
+    {
+        return traversedManyAssociation;
+    }
+
+    public NamedAssociationFunction<?> traversedNamedAssociation()
+    {
+        return traversedNamedAssociation;
+    }
+
+    public AccessibleObject accessor()
+    {
+        return accessor;
+    }
+
+    @Override
+    public ManyAssociation<T> apply( Composite entity )
+    {
+        try
+        {
+            Object target = entity;
+            if( traversedAssociation != null )
+            {
+                target = traversedAssociation.apply( entity ).get();
+            }
+            if( traversedManyAssociation != null )
+            {
+                throw new IllegalArgumentException( "Cannot traverse ManyAssociations" );
+            }
+            if( traversedNamedAssociation != null )
+            {
+                throw new IllegalArgumentException( "Cannot traverse NamedAssociations" );
+            }
+
+            CompositeInstance handler = (CompositeInstance) Proxy.getInvocationHandler( target );
+            return ( (AssociationStateHolder) handler.state() ).manyAssociationFor( accessor );
+        }
+        catch( IllegalArgumentException e )
+        {
+            throw e;
+        }
+        catch( Throwable e )
+        {
+            throw new IllegalArgumentException( e );
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        if( traversedAssociation != null )
+        {
+            return traversedAssociation.toString() + "." + ( (Member) accessor ).getName();
+        }
+        else
+        {
+            return ( (Member) accessor ).getName();
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/MatchesPredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/MatchesPredicate.java
new file mode 100644
index 0000000..bf050c0
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/MatchesPredicate.java
@@ -0,0 +1,86 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Regular expression match Specification.
+ */
+public class MatchesPredicate
+    extends ExpressionPredicate
+{
+    private PropertyFunction<String> property;
+    private Object value;
+
+    public MatchesPredicate( PropertyFunction<String> property, String regexp )
+    {
+        this.property = property;
+        this.value = regexp;
+    }
+
+    public MatchesPredicate( PropertyFunction<String> property, Variable variable )
+    {
+        this.property = property;
+        this.value = variable;
+    }
+
+    public PropertyFunction<String> property()
+    {
+        return property;
+    }
+
+    public Object value()
+    {
+        return value;
+    }
+
+    public String regexp()
+    {
+        return ( String ) value;
+    }
+
+    @Override
+    public boolean test( Composite item )
+    {
+        Property<String> prop = property.apply( item );
+
+        if( prop == null )
+        {
+            return false;
+        }
+
+        String val = prop.get();
+
+        if( val == null )
+        {
+            return false;
+        }
+
+        return val.matches( ( String ) value );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "( " + property + " matches " + "\"" + value + "\"" + " )";
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/NamedAssociationContainsNamePredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/NamedAssociationContainsNamePredicate.java
new file mode 100644
index 0000000..b5d2f64
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/NamedAssociationContainsNamePredicate.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.composite.Composite;
+
+/**
+ * NamedAssociation Contains Specification.
+ */
+public class NamedAssociationContainsNamePredicate<T>
+    extends ExpressionPredicate
+{
+    private final NamedAssociationFunction<T> namedAssociationFunction;
+    private final String name;
+
+    public NamedAssociationContainsNamePredicate( NamedAssociationFunction<T> namedAssociationFunction, String name )
+    {
+        this.namedAssociationFunction = namedAssociationFunction;
+        this.name = name;
+    }
+
+    public NamedAssociationFunction<T> namedAssociation()
+    {
+        return namedAssociationFunction;
+    }
+
+    public String name()
+    {
+        return name;
+    }
+
+    @Override
+    public boolean test( Composite item )
+    {
+        NamedAssociation<T> collection = namedAssociationFunction.apply( item );
+        if( collection == null )
+        {
+            return false;
+        }
+        return collection.containsName( name );
+    }
+
+    @Override
+    public String toString()
+    {
+        return namedAssociationFunction + " contains name:" + name;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/NamedAssociationContainsPredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/NamedAssociationContainsPredicate.java
new file mode 100644
index 0000000..6d13fb6
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/NamedAssociationContainsPredicate.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.composite.Composite;
+
+/**
+ * NamedAssociation Contains Specification.
+ */
+public class NamedAssociationContainsPredicate<T>
+    extends ExpressionPredicate
+{
+    private final NamedAssociationFunction<T> namedAssociationFunction;
+    private final T value;
+
+    public NamedAssociationContainsPredicate( NamedAssociationFunction<T> namedAssociationFunction, T value )
+    {
+        this.namedAssociationFunction = namedAssociationFunction;
+        this.value = value;
+    }
+
+    public NamedAssociationFunction<T> namedAssociation()
+    {
+        return namedAssociationFunction;
+    }
+
+    public T value()
+    {
+        return value;
+    }
+
+    @Override
+    public boolean test( Composite item )
+    {
+        NamedAssociation<T> collection = namedAssociationFunction.apply( item );
+        if( collection == null )
+        {
+            return false;
+        }
+        return collection.nameOf( value ) != null;
+    }
+
+    @Override
+    public String toString()
+    {
+        return namedAssociationFunction + " contains:" + value;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/NamedAssociationFunction.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/NamedAssociationFunction.java
new file mode 100644
index 0000000..9631612
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/NamedAssociationFunction.java
@@ -0,0 +1,118 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.lang.reflect.Proxy;
+import java.util.function.Function;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.CompositeInstance;
+
+/**
+ * Function to get Entity NamedAssociations.
+ */
+public class NamedAssociationFunction<T>
+    implements Function<Composite, NamedAssociation<T>>
+{
+    private final AssociationFunction<?> traversedAssociation;
+    private final ManyAssociationFunction<?> traversedManyAssociation;
+    private final NamedAssociationFunction<?> traversedNamedAssociation;
+    private final AccessibleObject accessor;
+
+    public NamedAssociationFunction( AssociationFunction<?> traversedAssociation,
+                                     ManyAssociationFunction<?> traversedManyAssociation,
+                                     NamedAssociationFunction<?> traversedNamedAssociation,
+                                     AccessibleObject accessor
+    )
+    {
+        this.traversedAssociation = traversedAssociation;
+        this.traversedManyAssociation = traversedManyAssociation;
+        this.traversedNamedAssociation = traversedNamedAssociation;
+        this.accessor = accessor;
+    }
+
+    public AssociationFunction<?> traversedAssociation()
+    {
+        return traversedAssociation;
+    }
+
+    public ManyAssociationFunction<?> traversedManyAssociation()
+    {
+        return traversedManyAssociation;
+    }
+
+    public NamedAssociationFunction<?> traversedNamedAssociation()
+    {
+        return traversedNamedAssociation;
+    }
+
+    public AccessibleObject accessor()
+    {
+        return accessor;
+    }
+
+    @Override
+    public NamedAssociation<T> apply( Composite entity )
+    {
+        try
+        {
+            Object target = entity;
+            if( traversedAssociation != null )
+            {
+                target = traversedAssociation.apply( entity ).get();
+            }
+            if( traversedManyAssociation != null )
+            {
+                throw new IllegalArgumentException( "Cannot traverse ManyAssociations" );
+            }
+            if( traversedNamedAssociation != null )
+            {
+                throw new IllegalArgumentException( "Cannot traverse NamedAssociations" );
+            }
+
+            CompositeInstance handler = (CompositeInstance) Proxy.getInvocationHandler( target );
+            return ( (AssociationStateHolder) handler.state() ).namedAssociationFor( accessor );
+        }
+        catch( IllegalArgumentException e )
+        {
+            throw e;
+        }
+        catch( Throwable e )
+        {
+            throw new IllegalArgumentException( e );
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        if( traversedAssociation != null )
+        {
+            return traversedAssociation.toString() + "." + ( (Member) accessor ).getName();
+        }
+        else
+        {
+            return ( (Member) accessor ).getName();
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/NePredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/NePredicate.java
new file mode 100644
index 0000000..eb6fd41
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/NePredicate.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+/**
+ * Not equals Specification.
+ */
+public class NePredicate<T>
+    extends ComparisonPredicate<T>
+{
+    public NePredicate( PropertyFunction<T> property, T value )
+    {
+        super( property, value );
+    }
+
+    @Override
+    protected boolean compare( T value )
+    {
+        return !value.equals( this.value );
+    }
+
+    @Override
+    public String toString()
+    {
+        return property.toString() + "!=" + value.toString();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/Notpredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/Notpredicate.java
new file mode 100644
index 0000000..59b3fcc
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/Notpredicate.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import java.util.function.Predicate;
+import org.apache.polygene.api.composite.Composite;
+
+/**
+ * NOT Specification.
+ */
+public class Notpredicate implements Predicate<Composite>
+{
+    private Predicate<Composite> operand;
+
+    public Notpredicate( Predicate<Composite> operand )
+    {
+        this.operand = operand;
+    }
+
+    public Predicate<Composite> operand()
+    {
+        return operand;
+    }
+
+    @Override
+    public boolean test( Composite item )
+    {
+        return operand.negate().test( item );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "!" + operand.toString();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/OrPredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/OrPredicate.java
new file mode 100644
index 0000000..400d415
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/OrPredicate.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import java.util.Collection;
+import java.util.function.Predicate;
+import org.apache.polygene.api.composite.Composite;
+
+/**
+ * OR Specification.
+ */
+public class OrPredicate
+    extends BinaryPredicate
+{
+
+    public OrPredicate( Collection<Predicate<Composite>> operands )
+    {
+        super( operands );
+    }
+
+    @Override
+    public boolean test( Composite item )
+    {
+        Predicate<Composite> master = t -> false;
+        for( Predicate<Composite> p : operands )
+        {
+            master = master.or( p );
+        }
+        return master.test( item );
+    }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder( "(" );
+        String or = "";
+        for( Predicate<Composite> operand : operands )
+        {
+            sb.append( or ).append( operand );
+            or = " or ";
+        }
+        return sb.append( ")" ).toString();
+    }
+
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/OrderBy.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/OrderBy.java
new file mode 100644
index 0000000..7e9e39a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/OrderBy.java
@@ -0,0 +1,89 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+/**
+ * Query sorting segment.
+ */
+public class OrderBy
+{
+    /**
+     * Order direction.
+     */
+    public enum Order
+    {
+        ASCENDING, DESCENDING
+    }
+
+    /**
+     * Order.
+     */
+    private final PropertyFunction<?> propertyReference;
+    /**
+     * Direction.
+     */
+    private final Order order;
+
+    /**
+     * Constructor.
+     *
+     * @param propertyReference property that determines the order; cannot be null
+     * @param order             direction
+     *
+     * @throws IllegalArgumentException - If property is null
+     */
+    public OrderBy( final PropertyFunction<?> propertyReference,
+                    final Order order
+    )
+    {
+        if( propertyReference == null )
+        {
+            throw new IllegalArgumentException( "Ordering property cannot be null" );
+        }
+        this.propertyReference = propertyReference;
+        this.order = order;
+    }
+
+    /**
+     * Getter.
+     *
+     * @return property; cannot be null
+     */
+    public PropertyFunction<?> property()
+    {
+        return propertyReference;
+    }
+
+    /**
+     * Getter.
+     *
+     * @return direction; cannot be null
+     */
+    public Order order()
+    {
+        return order;
+    }
+
+    @Override
+    public String toString()
+    {
+        return String.valueOf( propertyReference ) + " " + order;
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/PropertyFunction.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/PropertyFunction.java
new file mode 100644
index 0000000..f37e2c1
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/PropertyFunction.java
@@ -0,0 +1,180 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.util.function.Function;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.property.GenericPropertyInfo;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.NotQueryableException;
+import org.apache.polygene.api.query.QueryExpressionException;
+import org.apache.polygene.api.util.Classes;
+
+import static org.apache.polygene.api.util.Classes.typeOf;
+
+/**
+ * Function to get Entity Properties.
+ */
+public class PropertyFunction<T>
+    implements Function<Composite, Property<T>>
+{
+    private final PropertyFunction<?> traversedProperty;
+    private final AssociationFunction<?> traversedAssociation;
+    private final ManyAssociationFunction<?> traversedManyAssociation;
+    private final NamedAssociationFunction<?> traversedNamedAssociation;
+    private final AccessibleObject accessor;
+
+    public PropertyFunction( PropertyFunction<?> traversedProperty,
+                             AssociationFunction<?> traversedAssociation,
+                             ManyAssociationFunction<?> traversedManyAssociation,
+                             NamedAssociationFunction<?> traversedNamedAssociation,
+                             AccessibleObject accessor
+    )
+    {
+        this.traversedProperty = traversedProperty;
+        this.traversedAssociation = traversedAssociation;
+        this.traversedManyAssociation = traversedManyAssociation;
+        this.traversedNamedAssociation = traversedNamedAssociation;
+        this.accessor = accessor;
+
+        // Verify that the property accessor is not marked as non queryable
+        NotQueryableException.throwIfNotQueryable( accessor );
+        // Verify that the property type itself (value composites) is not marked as non queryable
+
+        Type returnType = typeOf( accessor );
+        if( !Property.class.isAssignableFrom( Classes.RAW_CLASS.apply( returnType ) ) )
+        {
+            throw new QueryExpressionException( "Not a property type:" + returnType );
+        }
+        Type propertyTypeAsType = GenericPropertyInfo.toPropertyType( returnType );
+        if( propertyTypeAsType instanceof ParameterizedType )
+        {
+            propertyTypeAsType = ( (ParameterizedType) propertyTypeAsType ).getRawType();
+        }
+
+        if( !( propertyTypeAsType instanceof Class ) )
+        {
+            throw new QueryExpressionException( "Unsupported property type:" + propertyTypeAsType );
+        }
+        @SuppressWarnings( "unchecked" )
+        Class<T> type = (Class<T>) propertyTypeAsType;
+        NotQueryableException.throwIfNotQueryable( type );
+    }
+
+    public PropertyFunction<?> traversedProperty()
+    {
+        return traversedProperty;
+    }
+
+    public AssociationFunction<?> traversedAssociation()
+    {
+        return traversedAssociation;
+    }
+
+    public ManyAssociationFunction<?> traversedManyAssociation()
+    {
+        return traversedManyAssociation;
+    }
+
+    public NamedAssociationFunction<?> traversedNamedAssociation()
+    {
+        return traversedNamedAssociation;
+    }
+
+    public AccessibleObject accessor()
+    {
+        return accessor;
+    }
+
+    @Override
+    public Property<T> apply( Composite entity )
+    {
+        try
+        {
+            Object target = entity;
+            if( traversedProperty != null )
+            {
+                Property<?> property = traversedProperty.apply( entity );
+                if( property == null )
+                {
+                    return null;
+                }
+                target = property.get();
+            }
+            else if( traversedAssociation != null )
+            {
+                Association<?> association = traversedAssociation.apply( entity );
+                if( association == null )
+                {
+                    return null;
+                }
+                target = association.get();
+            }
+            else if( traversedManyAssociation != null )
+            {
+                throw new IllegalArgumentException( "Cannot evaluate a ManyAssociation" );
+            }
+            else if( traversedNamedAssociation != null )
+            {
+                throw new IllegalArgumentException( "Cannot evaluate a NamedAssociation" );
+            }
+
+            if( target == null )
+            {
+                return null;
+            }
+
+            CompositeInstance handler = (CompositeInstance) Proxy.getInvocationHandler( target );
+            return handler.state().propertyFor( accessor );
+        }
+        catch( IllegalArgumentException e )
+        {
+            throw e;
+        }
+        catch( Throwable e )
+        {
+            throw new IllegalArgumentException( e );
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        if( traversedProperty != null )
+        {
+            return traversedProperty.toString() + "." + ( (Member) accessor ).getName();
+        }
+        else if( traversedAssociation != null )
+        {
+            return traversedAssociation.toString() + "." + ( (Member) accessor ).getName();
+        }
+        else
+        {
+            return ( (Member) accessor ).getName();
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/PropertyNotNullPredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/PropertyNotNullPredicate.java
new file mode 100644
index 0000000..b029a5b
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/PropertyNotNullPredicate.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Property not null Specification.
+ */
+public class PropertyNotNullPredicate<T>
+    extends ExpressionPredicate
+{
+    private PropertyFunction<T> property;
+
+    public PropertyNotNullPredicate( PropertyFunction<T> property )
+    {
+        this.property = property;
+    }
+
+    public PropertyFunction<T> property()
+    {
+        return property;
+    }
+
+    @Override
+    public boolean test( Composite item )
+    {
+        Property<T> prop = property.apply( item );
+
+        if( prop == null )
+        {
+            return false;
+        }
+
+        return prop.get() != null;
+    }
+
+    @Override
+    public String toString()
+    {
+        return property.toString() + "is not null";
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/PropertyNullPredicate.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/PropertyNullPredicate.java
new file mode 100644
index 0000000..8de2630
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/PropertyNullPredicate.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Property null Specification.
+ */
+public class PropertyNullPredicate<T>
+    extends ExpressionPredicate
+{
+    private PropertyFunction<T> property;
+
+    public PropertyNullPredicate( PropertyFunction<T> property )
+    {
+        this.property = property;
+    }
+
+    public PropertyFunction<T> property()
+    {
+        return property;
+    }
+
+    @Override
+    public boolean test( Composite item )
+    {
+        Property<T> prop = property.apply( item );
+
+        if( prop == null )
+        {
+            return true;
+        }
+
+        return prop.get() == null;
+    }
+
+    @Override
+    public String toString()
+    {
+        return property.toString() + "is null";
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/PropertyReference.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/PropertyReference.java
new file mode 100644
index 0000000..45a9476
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/PropertyReference.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import java.util.function.Function;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Property Reference.
+ */
+public interface PropertyReference
+{
+    <T> Function<Composite, Property<T>> reference();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/QuerySpecification.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/QuerySpecification.java
new file mode 100644
index 0000000..6e30aea
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/QuerySpecification.java
@@ -0,0 +1,72 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+import java.util.function.Predicate;
+import org.apache.polygene.api.composite.Composite;
+
+/**
+ * This should be used when doing native queries, such as SQL, SPARQL or similar. EntityFinders can choose
+ * what type of query languages they can understand by checking the language property of a QuerySpecification
+ */
+public class QuerySpecification
+    implements Predicate<Composite>
+{
+    public static boolean isQueryLanguage( String language, Predicate<Composite> specification )
+    {
+        if( !( specification instanceof QuerySpecification ) )
+        {
+            return false;
+        }
+
+        return ( (QuerySpecification) specification ).language().equals( language );
+    }
+
+    private String language;
+    private String query;
+
+    public QuerySpecification( String language, String query )
+    {
+        this.language = language;
+        this.query = query;
+    }
+
+    public String language()
+    {
+        return language;
+    }
+
+    public String query()
+    {
+        return query;
+    }
+
+    @Override
+    public boolean test( Composite item )
+    {
+        return false;
+    }
+
+    @Override
+    public String toString()
+    {
+        return language + ":" + query;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/Variable.java b/core/api/src/main/java/org/apache/polygene/api/query/grammar/Variable.java
new file mode 100644
index 0000000..a5cfe78
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/Variable.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.api.query.grammar;
+
+/**
+ * Query Variable name.
+ */
+public class Variable
+{
+    private String name;
+
+    public Variable( String name )
+    {
+        this.name = name;
+    }
+
+    public String variableName()
+    {
+        return name;
+    }
+
+    @Override
+    public String toString()
+    {
+        return name;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/grammar/package.html b/core/api/src/main/java/org/apache/polygene/api/query/grammar/package.html
new file mode 100644
index 0000000..4a3e2f1
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/grammar/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Query Grammar.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/query/package.html b/core/api/src/main/java/org/apache/polygene/api/query/package.html
new file mode 100644
index 0000000..c3ee7ad
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/query/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Query API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/serialization/ConvertedBy.java b/core/api/src/main/java/org/apache/polygene/api/serialization/ConvertedBy.java
new file mode 100644
index 0000000..15c77f6
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/serialization/ConvertedBy.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.api.serialization;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Convert this type or Property with the given {@link Converter}.
+ *
+ * {@link Converter}s must have a no-args constructor and will be instantiated by the serialization SPI.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.TYPE, ElementType.METHOD } )
+@Documented
+public @interface ConvertedBy
+{
+    /**
+     * The serialization converter type.
+     *
+     * @return the serialization converter type
+     */
+    Class<? extends Converter> value();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/serialization/Converter.java b/core/api/src/main/java/org/apache/polygene/api/serialization/Converter.java
new file mode 100644
index 0000000..2acfd93
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/serialization/Converter.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.api.serialization;
+
+/**
+ * Converter for (de)serialization.
+ *
+ * Convert instances of {@code T} to String and the other way around.
+ *
+ * @param <T> the converted type
+ */
+public interface Converter<T>
+{
+    /**
+     * @return the converted type
+     */
+    Class<T> type();
+
+    /**
+     * Convert.
+     *
+     * @param object the {@code T} to convert to String, never null
+     * @return the String representation of the given object
+     */
+    String toString( T object );
+
+    /**
+     * Revert.
+     *
+     * @param string the String to convert back to {@code T}
+     * @return the {@code T}
+     */
+    T fromString( String string );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/serialization/Converters.java b/core/api/src/main/java/org/apache/polygene/api/serialization/Converters.java
new file mode 100644
index 0000000..44a1232
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/serialization/Converters.java
@@ -0,0 +1,213 @@
+/*
+ *  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.polygene.api.serialization;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.structure.MetaInfoHolder;
+import org.apache.polygene.api.type.HasTypes;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.api.util.Annotations;
+
+import static org.apache.polygene.api.type.HasTypesCollectors.closestType;
+
+/**
+ * Serialization Converters.
+ */
+@Mixins( Converters.Mixin.class )
+public interface Converters
+{
+    /**
+     * Register a converter for a value type.
+     *
+     * @param valueType the value type
+     * @param converter the converter
+     */
+    void registerConverter( ValueType valueType, Converter<?> converter );
+
+    /**
+     * Find a matching converter amongst registered ones.
+     *
+     * See {@link org.apache.polygene.api.type.HasTypesCollectors#closestType(HasTypes)}.
+     *
+     * @param valueType the value type
+     * @param <T> the converted type
+     * @return the closest matching registered converter, or {@literal null} if none
+     */
+    <T> Converter<T> converterFor( ValueType valueType );
+
+    /**
+     * Find a matching converter amongst registered ones.
+     *
+     * See {@link org.apache.polygene.api.type.HasTypesCollectors#closestType(HasTypes)}.
+     *
+     * @param type the value type
+     * @param <T> the converted type
+     * @return the closest matching registered converter, or {@literal null} if none
+     */
+    default <T> Converter<T> converterFor( Class<? extends T> type )
+    {
+        return converterFor( ValueType.of( type ) );
+    }
+
+    /**
+     * Find converter registered as meta-info.
+     *
+     * Meta-info converters are registered either using {@link ConvertedBy} annotation or at assembly time.
+     * The latter takes precedence over the former.
+     *
+     * @param metaInfoHolder the meta-info holder, e.g. a property descriptor
+     * @param <T> the converted type
+     * @return the registered converted, or {@literal null} if none
+     */
+    <T> Converter<T> converterFor( MetaInfoHolder metaInfoHolder );
+
+    /**
+     * Serialization Converters default Mixin.
+     */
+    class Mixin implements Converters
+    {
+        private final Map<ValueType, Converter<?>> converters = new LinkedHashMap<>();
+        private final Map<ValueType, Converter<?>> resolvedConvertersCache = new HashMap<>();
+        private final Map<Class<? extends Converter>, Converter<?>> convertersInstancesCache = new HashMap<>();
+
+        @Override
+        public void registerConverter( ValueType valueType, Converter<?> converter )
+        {
+            converters.put( valueType, converter );
+            resolvedConvertersCache.put( valueType, converter );
+        }
+
+        @Override
+        public <T> Converter<T> converterFor( ValueType valueType )
+        {
+            if( resolvedConvertersCache.containsKey( valueType ) )
+            {
+                return castConverter( resolvedConvertersCache.get( valueType ) );
+            }
+            Converter<T> converter = lookupConverter( valueType );
+            resolvedConvertersCache.put( valueType, converter );
+            return converter;
+        }
+
+        @SuppressWarnings( "unchecked" )
+        private <T> Converter<T> lookupConverter( ValueType valueType )
+        {
+            Converter<T> converter = lookupConvertedByConverter( valueType );
+            if( converter == null )
+            {
+                converter = castConverter( converters.keySet().stream()
+                                                     .collect( closestType( valueType ) )
+                                                     .map( converters::get )
+                                                     .orElse( null ) );
+            }
+            if( converter == null && valueType.primaryType().isEnum() )
+            {
+                converter = new EnumConverter( valueType.primaryType() );
+            }
+            return converter;
+        }
+
+        @Override
+        public <T> Converter<T> converterFor( MetaInfoHolder metaInfoHolder )
+        {
+            Converter converter = metaInfoHolder.metaInfo( Converter.class );
+            if( converter != null )
+            {
+                return castConverter( converter );
+            }
+            ConvertedBy convertedBy = metaInfoHolder.metaInfo( ConvertedBy.class );
+            if( convertedBy != null )
+            {
+                return converterInstanceOf( convertedBy.value() );
+            }
+            return null;
+        }
+
+        private <T> Converter<T> lookupConvertedByConverter( ValueType valueType )
+        {
+            ConvertedBy convertedBy = Annotations.annotationOn( valueType.primaryType(), ConvertedBy.class );
+            if( convertedBy != null )
+            {
+                return converterInstanceOf( convertedBy.value() );
+            }
+            return null;
+        }
+
+        private <T> Converter<T> converterInstanceOf( Class<? extends Converter> converterClass )
+        {
+            if( convertersInstancesCache.containsKey( converterClass ) )
+            {
+                return castConverter( convertersInstancesCache.get( converterClass ) );
+            }
+            try
+            {
+                Converter<T> converter = castConverter( converterClass.newInstance() );
+                convertersInstancesCache.put( converterClass, converter );
+                return converter;
+            }
+            catch( InstantiationException | IllegalAccessException ex )
+            {
+                throw new SerializationException( "Unable to instantiate Converter: " + converterClass.getName(), ex );
+            }
+        }
+
+        @SuppressWarnings( "unchecked" )
+        private <T> Converter<T> castConverter( Converter<?> converter )
+        {
+            return (Converter<T>) converter;
+        }
+
+        private static class EnumConverter<E extends Enum<E>> implements Converter<E>
+        {
+            private final Class<E> enumType;
+            private final Map<String, E> values;
+
+            private EnumConverter( final Class<E> enumType )
+            {
+                this.enumType = enumType;
+                E[] enumValues = enumType.getEnumConstants();
+                this.values = new HashMap<>( enumValues.length );
+                for( E enumValue : enumValues )
+                {
+                    values.put( enumValue.name(), enumValue );
+                }
+            }
+
+            @Override
+            public Class<E> type()
+            {
+                return enumType;
+            }
+
+            @Override
+            public String toString( E object )
+            {
+                return object.name();
+            }
+
+            @Override
+            public E fromString( String string )
+            {
+                return values.get( string );
+            }
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/serialization/Deserializer.java b/core/api/src/main/java/org/apache/polygene/api/serialization/Deserializer.java
new file mode 100644
index 0000000..0b633dd
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/serialization/Deserializer.java
@@ -0,0 +1,73 @@
+/*
+ *  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.polygene.api.serialization;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ValueType;
+
+/**
+ * Deserializer.
+ *
+ * Provides methods and functions to deserialize objects and set of objects.
+ */
+public interface Deserializer
+{
+    <T> T deserialize( ModuleDescriptor module, ValueType valueType, InputStream state );
+
+    <T> T deserialize( ModuleDescriptor module, ValueType valueType, Reader state );
+
+    <T> T deserialize( ModuleDescriptor module, ValueType valueType, String state );
+
+    <T> Function<String, T> deserializeFunction( ModuleDescriptor module, ValueType valueType );
+
+    <T> Stream<T> deserializeEach( ModuleDescriptor module, ValueType valueType, Iterable<String> states );
+
+    <T> Stream<T> deserializeEach( ModuleDescriptor module, ValueType valueType, String... states );
+
+    <T> T fromBytes( ModuleDescriptor module, ValueType valueType, byte[] bytes );
+
+    <T> Function<byte[], T> fromBytesFunction( ModuleDescriptor module, ValueType valueType );
+
+    <T> Stream<T> fromBytesEach( ModuleDescriptor module, ValueType valueType, Iterable<byte[]> states );
+
+    <T> Stream<T> fromBytesEach( ModuleDescriptor module, ValueType valueType, byte[]... states );
+
+    <T> T deserialize( ModuleDescriptor module, Class<T> type, InputStream state );
+
+    <T> T deserialize( ModuleDescriptor module, Class<T> type, Reader state );
+
+    <T> T deserialize( ModuleDescriptor module, Class<T> type, String state );
+
+    <T> Function<String, T> deserializeFunction( ModuleDescriptor module, Class<T> type );
+
+    <T> Stream<T> deserializeEach( ModuleDescriptor module, Class<T> type, Iterable<String> states );
+
+    <T> Stream<T> deserializeEach( ModuleDescriptor module, Class<T> type, String... states );
+
+    <T> T fromBytes( ModuleDescriptor module, Class<T> type, byte[] bytes );
+
+    <T> Function<byte[], T> fromBytesFunction( ModuleDescriptor module, Class<T> type );
+
+    <T> Stream<T> fromBytesEach( ModuleDescriptor module, Class<T> type, Iterable<byte[]> states );
+
+    <T> Stream<T> fromBytesEach( ModuleDescriptor module, Class<T> type, byte[]... states );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/serialization/JavaSerializationConverter.java b/core/api/src/main/java/org/apache/polygene/api/serialization/JavaSerializationConverter.java
new file mode 100644
index 0000000..792ec99
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/serialization/JavaSerializationConverter.java
@@ -0,0 +1,88 @@
+/*
+ *  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.polygene.api.serialization;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Base64;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+/**
+ * A Converter based on Java Serialization.
+ *
+ * Note that this Converter works with String representations.
+ * The serialized payload is encoded using Base64.
+ * This is suitable for text based formats, if you are using a binary format, see the serialization extension.
+ *
+ * Prefer using it with the {@link ConvertedBy} annotation.
+ * If you register it as a serialization converter, it will catch all types.
+ * Or you could extend it and override {@link #type()}.
+ */
+public class JavaSerializationConverter implements Converter<Object>
+{
+    @Override
+    public Class<Object> type()
+    {
+        return Object.class;
+    }
+
+    @Override
+    public String toString( Object object )
+    {
+        byte[] bytes = Base64.getEncoder().encode( serializeJava( object ) );
+        return new String( bytes, UTF_8 );
+    }
+
+    @Override
+    public Object fromString( String string )
+    {
+        byte[] bytes = Base64.getDecoder().decode( string );
+        return deserializeJava( bytes );
+    }
+
+    protected byte[] serializeJava( Object object )
+    {
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        try( ObjectOutputStream out = new ObjectOutputStream( bout ) )
+        {
+            out.writeUnshared( object );
+            out.flush();
+            return bout.toByteArray();
+        }
+        catch( IOException ex )
+        {
+            throw new SerializationException( "Unable to serialize using Java serialization", ex );
+        }
+    }
+
+    protected Object deserializeJava( byte[] bytes )
+    {
+        try( ObjectInputStream oin = new ObjectInputStream( new ByteArrayInputStream( bytes ) ) )
+        {
+            return oin.readObject();
+        }
+        catch( IOException | ClassNotFoundException ex )
+        {
+            throw new SerializationException( "Unable to deserialize using Java serialization", ex );
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/serialization/Serialization.java b/core/api/src/main/java/org/apache/polygene/api/serialization/Serialization.java
new file mode 100644
index 0000000..74b7330
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/serialization/Serialization.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.api.serialization;
+
+/**
+ * Serialization extends {@link Serializer} and {@link Deserializer}.
+ */
+public interface Serialization extends Serializer, Deserializer
+{
+    /**
+     * Serialization format {@literal @Service} tags.
+     *
+     * Serialization implementations should be tagged with theses at assembly time so that consumers can
+     * specify which format they need.
+     */
+    interface Format
+    {
+        /**
+         * Tag a Serialization service that support the JSON format.
+         */
+        String JSON = "json";
+        /**
+         * Tag a Serialization service that support the XML format.
+         */
+        String XML = "xml";
+        /**
+         * Tag a Serialization service that support the YAML format.
+         */
+        String YAML = "yaml";
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/serialization/SerializationException.java b/core/api/src/main/java/org/apache/polygene/api/serialization/SerializationException.java
new file mode 100644
index 0000000..aeb0bfa
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/serialization/SerializationException.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.api.serialization;
+
+/**
+ * Serialization Exception.
+ */
+public class SerializationException extends RuntimeException
+{
+    public SerializationException( String message )
+    {
+        super( message );
+    }
+
+    public SerializationException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/serialization/Serializer.java b/core/api/src/main/java/org/apache/polygene/api/serialization/Serializer.java
new file mode 100644
index 0000000..0ece5a1
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/serialization/Serializer.java
@@ -0,0 +1,279 @@
+/*
+ *  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.polygene.api.serialization;
+
+import java.io.OutputStream;
+import java.io.Writer;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.Optional;
+
+/**
+ * Serializer.
+ *
+ * All implementations must handle all {@link Options}, they might extend them to provide more control.
+ * See their respective documentation for the details.
+ */
+public interface Serializer
+{
+    void serialize( Options options, Writer writer, @Optional Object object );
+
+    void serialize( Options options, OutputStream output, @Optional Object object );
+
+    void serialize( Writer writer, @Optional Object object );
+
+    void serialize( OutputStream output, @Optional Object object );
+
+    String serialize( Options options, @Optional Object object );
+
+    String serialize( @Optional Object object );
+
+    <T> Function<T, String> serializeFunction( Options options );
+
+    <T> Function<T, String> serializeFunction();
+
+    Stream<String> serializeEach( Options options, Iterable<Object> objects );
+
+    Stream<String> serializeEach( Iterable<Object> objects );
+
+    Stream<String> serializeEach( Options options, Object... objects );
+
+    Stream<String> serializeEach( Object... objects );
+
+    byte[] toBytes( Options options, @Optional Object object );
+
+    byte[] toBytes( @Optional Object object );
+
+    <T> Function<T, byte[]> toBytesFunction( Options options );
+
+    <T> Function<T, byte[]> toBytesFunction();
+
+    Stream<byte[]> toBytesEach( Options options, Iterable<Object> objects );
+
+    Stream<byte[]> toBytesEach( Iterable<Object> objects );
+
+    Stream<byte[]> toBytesEach( Options options, Object... objects );
+
+    Stream<byte[]> toBytesEach( Object... objects );
+
+    /**
+     * State serializer options.
+     *
+     * Use {@link #builder()} to create new instances.
+     *
+     * All options provided by the builder are safe to use with all serialization extensions. Serialization extensions
+     * might provide more options, see {@link #option(String)} and the respective extension documentation.
+     */
+    interface Options
+    {
+        /**
+         * Default state serializer options.
+         *
+         * {@link #rootTypeInfo()} set to {@literal false}.
+         * {@link #nestedTypeInfo()} set to {@literal true}.
+         */
+        Options DEFAULT = builder().withoutRootTypeInfo().withNestedTypeInfo().build();
+
+        /**
+         * State serializer options with both {@link #rootTypeInfo()} and {@link #nestedTypeInfo()}
+         * set to {@literal false}.
+         */
+        Options NO_TYPE_INFO = builder().withoutRootTypeInfo().withoutNestedTypeInfo().build();
+
+        /**
+         * State serializer options with both {@link #rootTypeInfo()} and {@link #nestedTypeInfo()}
+         * set to {@literal true}.
+         */
+        Options ALL_TYPE_INFO = builder().withRootTypeInfo().withNestedTypeInfo().build();
+
+        boolean rootTypeInfo();
+
+        /**
+         * Include type information in the serialized form of nested values.
+         *
+         * Boolean flag to include type information in the serialized form of nested values types.
+         * Each serialization extension is free to chose how to represent this type information.
+         *
+         * This is enabled by default to allow for polymorphic deserialization.
+         *
+         * Let's say you have a type hierarchy of values as follows ;
+         * <code>
+         *     interface Parent { Property&lt;String&gt; something(); }
+         *     interface Child1 { Property&lt;Long&gt; number(); }
+         *     interface Child2 { Property&lt;Duration&gt; duration(); }
+         * </code>
+         * and want to serialize and deserialize a set of values like this one ;
+         * <code>
+         *     interface MyValue { Property&lt;Parent&gt; polymorphicValue(); }
+         * </code>
+         * that is a view of a value composite that also has the following fragments ;
+         * <code>
+         *     interface MyValueWithNumber { Property&lt;Child1&gt; polymorphicValue(); }
+         *     interface MyValueWithDuration { Property&lt;Child2&gt; polymorphicValue(); }
+         * </code>
+         * when deserializing, the {@link Deserializer} needs a way to know which specialization
+         * type to use to deserialize the value state, {@literal Child1} or {@literal Child2} in our example.
+         *
+         * If the deserializer can't know it use the type information from the
+         * {@link org.apache.polygene.api.type.ValueType} provided at deserialization time.
+         *
+         * Disable it using {@link Builder#withoutNestedTypeInfo()} if you are sure you don't need this.
+         *
+         * @return {@literal true} if type information must be included in the serialized form of nested values,
+         *         {@literal false} otherwise
+         */
+        boolean nestedTypeInfo();
+
+        /**
+         * Query for an option's value.
+         *
+         * @param option the option
+         * @return the option's value, {@literal} null if absent
+         */
+        String option( String option );
+
+        /**
+         * Create a new builder of {@link Options}
+         *
+         * @return a new builder
+         */
+        static Builder builder()
+        {
+            return new Builder();
+        }
+
+        /**
+         * Builder for {@link Options}.
+         *
+         * This builder is mutable, built instances are not.
+         */
+        final class Builder
+        {
+            private static final String ROOT_TYPE_INFO = "rootTypeInfo";
+            private static final String NESTED_TYPE_INFO = "nestedTypeInfo";
+
+            private static class Instance implements Options
+            {
+                private final Map<String, String> options;
+
+                private Instance( Map<String, String> options )
+                {
+                    this.options = options;
+                }
+
+                @Override
+                public boolean rootTypeInfo()
+                {
+                    return "true".equals( options.get( ROOT_TYPE_INFO ) );
+                }
+
+                @Override
+                public boolean nestedTypeInfo()
+                {
+                    return "true".equals( options.get( NESTED_TYPE_INFO ) );
+                }
+
+                @Override
+                public String option( String option )
+                {
+                    return options.get( option );
+                }
+            }
+
+            private final Map<String, String> options = new HashMap<String, String>()
+            {{
+                put( ROOT_TYPE_INFO, "false" );
+                put( NESTED_TYPE_INFO, "true" );
+            }};
+
+            public Builder withRootTypeInfo()
+            {
+                return withOption( ROOT_TYPE_INFO, "true" );
+            }
+
+            public Builder withoutRootTypeInfo()
+            {
+                return withOption( ROOT_TYPE_INFO, "false" );
+            }
+
+            /**
+             * Include type information in the serialized form of nested values.
+             *
+             * @return this builder
+             */
+            public Builder withNestedTypeInfo()
+            {
+                return withOption( NESTED_TYPE_INFO, "true" );
+            }
+
+            /**
+             * Do not include type information in the serialized form of nested values.
+             *
+             * <strong>WARNING</strong>
+             * Without this, {@link Deserializer}s will use the provided
+             * {@link org.apache.polygene.api.type.ValueType} for instantiation potentially breaking polymorphism,
+             * see {@link Options#nestedTypeInfo()}.
+             *
+             * @return this builder
+             * @see Builder#withNestedTypeInfo()
+             */
+            public Builder withoutNestedTypeInfo()
+            {
+                return withOption( NESTED_TYPE_INFO, "false" );
+            }
+
+            /**
+             * Set extension specific option.
+             *
+             * @param option the option to add
+             * @param value it's value
+             * @return this builder
+             */
+            public Builder withOption( String option, String value )
+            {
+                options.put( option, value );
+                return this;
+            }
+
+            /**
+             * Remove extension specific option.
+             *
+             * @param option the option to remove
+             * @return this builder
+             */
+            public Builder withoutOption( String option )
+            {
+                options.remove( option );
+                return this;
+            }
+
+            /**
+             * Build the options.
+             *
+             * @return a new immutable instance of {@link Options}.
+             */
+            public Options build()
+            {
+                return new Instance( Collections.unmodifiableMap( options ) );
+            }
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/serialization/package.html b/core/api/src/main/java/org/apache/polygene/api/serialization/package.html
new file mode 100644
index 0000000..9f2886c
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/serialization/package.html
@@ -0,0 +1,47 @@
+<!--
+  ~  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.
+  -->
+<html>
+<body>
+<h2>Serialization API.</h2>
+<p>
+    {@link org.apache.polygene.api.serialization.Serialization}
+    extends {@link org.apache.polygene.api.serialization.Serializer}
+    and {@link org.apache.polygene.api.serialization.Deserializer}.
+    <br/>
+    {@link org.apache.polygene.api.serialization.SerializationException}
+    is thrown when something goes wrong.
+</p>
+<p>
+    Serialization implementations should be tagged with
+    {@link org.apache.polygene.api.serialization.Serialization.Format}
+    at assembly time so that consumers can specify which format they need:
+</p>
+<pre><code>@Service @Tagged( Serialization.Format.JSON ) Serialization serialization;</code></pre>
+<p>
+    {@literal Serializer}s and {@literal Deserializer}s provides methods and functions to (de)serialize objects
+    and set of objects.
+</p>
+<p>
+    Serialized representations might be textual (e.g. {@literal JSON} and {@literal XML}) or binary.
+    Implementations are free to use any codec to encode/decode from/to text and bytes but it must be bi-directional.
+</p>
+<p>
+    The serialization behavior can be influenced using {@link org.apache.polygene.api.serialization.Serializer.Options}.
+</p>
+</body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/Availability.java b/core/api/src/main/java/org/apache/polygene/api/service/Availability.java
new file mode 100644
index 0000000..974a32e
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/Availability.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.api.service;
+
+/**
+ * Services can implement this interface in order to allow Polygene to ask
+ * it whether it is currently available for use or not. This is accessed
+ * by clients through the ServiceReference of the service. Services that do not
+ * implement this are always considered to be available.
+ */
+public interface Availability
+{
+    /**
+     * Implementations should return true if the underlying service is currently available for use.
+     *
+     * Reasons why a service might not be available is either if it has been configured not to be (see
+     * the Enabled interface), or if an underlying resource is currently unavailable.
+     *
+     * @return true if the service is available, false otherwise.
+     */
+    boolean isAvailable();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/DuplicateServiceIdentityException.java b/core/api/src/main/java/org/apache/polygene/api/service/DuplicateServiceIdentityException.java
new file mode 100644
index 0000000..e404666
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/DuplicateServiceIdentityException.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.api.service;
+
+import org.apache.polygene.api.common.InvalidApplicationException;
+
+/**
+ * Thrown when a duplicate service reference is detected.
+ */
+public class DuplicateServiceIdentityException
+    extends InvalidApplicationException
+{
+    public DuplicateServiceIdentityException( String string )
+    {
+        super( string );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/ImportedServiceDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/service/ImportedServiceDescriptor.java
new file mode 100644
index 0000000..558b7ed
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/ImportedServiceDescriptor.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.api.service;
+
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.identity.Identifiable;
+
+/**
+ * {@code ServiceDescriptor} provides meta information of a service.
+ */
+public interface ImportedServiceDescriptor
+    extends ModelDescriptor, Identifiable
+{
+    Class<? extends ServiceImporter> serviceImporter();
+
+    Class<?> type();
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/NoSuchServiceException.java b/core/api/src/main/java/org/apache/polygene/api/service/NoSuchServiceException.java
new file mode 100644
index 0000000..31523b5
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/NoSuchServiceException.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.api.service;
+
+import java.util.stream.Collectors;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.composite.NoSuchCompositeException;
+import org.apache.polygene.api.structure.TypeLookup;
+
+/**
+ * Thrown when no visible service of the requested type is found.
+ */
+public class NoSuchServiceException extends NoSuchCompositeException
+{
+    public NoSuchServiceException( String typeName, String moduleName, TypeLookup typeLookup )
+    {
+        super( "ServiceComposite", typeName, moduleName, formatVisibleTypes( typeLookup ) );
+    }
+
+    private static String formatVisibleTypes( TypeLookup typeLookup )
+    {
+        return typeLookup.allServices()
+            .map( NoSuchServiceException::typeOf )
+            .collect( Collectors.joining( "\n", "Visible service types are:\n", "" ) );
+    }
+
+    private static String typeOf( ModelDescriptor descriptor )
+    {
+        if( descriptor instanceof CompositeDescriptor )
+        {
+            return ( (CompositeDescriptor) descriptor ).primaryType().getName();
+        }
+        return descriptor.types().map( Class::getName ).collect( Collectors.joining( ",", "[", "]") );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/ServiceActivation.java b/core/api/src/main/java/org/apache/polygene/api/service/ServiceActivation.java
new file mode 100644
index 0000000..33ac055
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/ServiceActivation.java
@@ -0,0 +1,73 @@
+/*
+ *  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.polygene.api.service;
+
+import org.apache.polygene.api.activation.Activators;
+
+/**
+ * Convenience interface for simple Service Activation.
+ *
+ * Let your ServiceComposite extends ServiceActivation and implement it in one of its Mixins.
+ * A corresponding Activator is automatically registered.
+ */
+@Activators( ServiceActivation.ServiceActivator.class )
+public interface ServiceActivation
+{
+
+    /**
+     * Called after ServiceComposite Activation.
+     *
+     * @throws Exception if unable to activate
+     */
+    void activateService()
+        throws Exception;
+
+    /**
+     * Called before ServiceComposite Passivation.
+     *
+     * @throws Exception if unable to passivate
+     */
+    void passivateService()
+        throws Exception;
+
+    /**
+     * Service Activator.
+     */
+    class ServiceActivator
+        extends ServiceActivatorAdapter<ServiceActivation>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<ServiceActivation> activated )
+            throws Exception
+        {
+            activated.get().activateService();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<ServiceActivation> passivating )
+            throws Exception
+        {
+            passivating.get().passivateService();
+        }
+
+    }
+
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/ServiceActivatorAdapter.java b/core/api/src/main/java/org/apache/polygene/api/service/ServiceActivatorAdapter.java
new file mode 100644
index 0000000..032064a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/ServiceActivatorAdapter.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.api.service;
+
+import org.apache.polygene.api.activation.Activator;
+
+/**
+ * Adapter for Service Activator.
+ *
+ * @param <ServiceType> Type of the service.
+ */
+public class ServiceActivatorAdapter<ServiceType>
+    implements Activator<ServiceReference<ServiceType>>
+{
+    /**
+     * Called before Service activation.
+     * @param activating Activating Service
+     */
+    @Override
+    public void beforeActivation( ServiceReference<ServiceType> activating )
+        throws Exception
+    {
+    }
+
+    /**
+     * Called after Service activation.
+     * @param activated Activated Service
+     */
+    @Override
+    public void afterActivation( ServiceReference<ServiceType> activated )
+        throws Exception
+    {
+    }
+
+    /**
+     * Called before Service passivation.
+     * @param passivating Passivating Service
+     */
+    @Override
+    public void beforePassivation( ServiceReference<ServiceType> passivating )
+        throws Exception
+    {
+    }
+
+    /**
+     * Called after Service passivation.
+     * @param passivated Passivated Service
+     */
+    @Override
+    public void afterPassivation( ServiceReference<ServiceType> passivated )
+        throws Exception
+    {
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/ServiceComposite.java b/core/api/src/main/java/org/apache/polygene/api/service/ServiceComposite.java
new file mode 100644
index 0000000..f6e2b6e
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/ServiceComposite.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.api.service;
+
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.identity.HasIdentity;
+
+/**
+ * All Composites being used to implement Services
+ * must extend this interface.
+ */
+public interface ServiceComposite
+    extends HasIdentity, Composite
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/ServiceDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/service/ServiceDescriptor.java
new file mode 100644
index 0000000..7bfafc9
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/ServiceDescriptor.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.api.service;
+
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.StatefulCompositeDescriptor;
+import org.apache.polygene.api.identity.Identifiable;
+
+/**
+ * {@code ServiceDescriptor} provides meta informations of a service.
+ */
+public interface ServiceDescriptor
+    extends CompositeDescriptor, StatefulCompositeDescriptor, Identifiable
+{
+    boolean isInstantiateOnStartup();
+
+    <T> Class<T> configurationType();
+
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/ServiceFinder.java b/core/api/src/main/java/org/apache/polygene/api/service/ServiceFinder.java
new file mode 100644
index 0000000..8e7e9d5
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/ServiceFinder.java
@@ -0,0 +1,98 @@
+/*
+ *  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.polygene.api.service;
+
+import java.lang.reflect.Type;
+import java.util.stream.Stream;
+
+/**
+ * Interface used to query for ServiceReferences.
+ * <p>
+ * Each ServiceFinder is
+ * obtained from a specific Module, and the lookup rules are the following:
+ * </p>
+ * <ol>
+ * <li>First look in the same Module as the ServiceFinder</li>
+ * <li>Then look in the same Layer as the ServiceFinder. Any Services declared
+ * with Visibility Layer and Application should be included</li>
+ * <li>Then look in the used Layers. Any Services declared with Visibility Application
+ * should be included</li>
+ * </ol>
+ * <p>
+ * Both native Polygene services and imported services are considered, with preference to native services.
+ * </p>
+ */
+public interface ServiceFinder
+{
+    /**
+     * Find a ServiceReference that implements the given type.
+     *
+     * @param <T> Service type
+     * @param serviceType the type that the Service must implement
+     *
+     * @return a ServiceReference if one is found
+     *
+     * @throws NoSuchServiceException if no service of serviceType is found
+     */
+    <T> ServiceReference<T> findService( Class<T> serviceType )
+        throws NoSuchServiceException;
+
+    /**
+     * Find a ServiceReference that implements the given type.
+     *
+     * @param <T> Service type
+     * @param serviceType the type that the Service must implement
+     *
+     * @return a ServiceReference if one is found
+     *
+     * @throws NoSuchServiceException if no service of serviceType is found
+     */
+    <T> ServiceReference<T> findService( Type serviceType )
+        throws NoSuchServiceException;
+
+    /**
+     * Find ServiceReferences that implements the given type.
+     * <p>
+     * The order of the references is such that Services more local to the querying
+     * Module is earlier in the list.
+     * </p>
+     *
+     * @param <T> Service type
+     * @param serviceType the type that the Services must implement
+     *
+     * @return a stream of ServiceReferences for the given type. It is empty if none exist
+     */
+    <T> Stream<ServiceReference<T>> findServices( Class<T> serviceType );
+
+    /**
+     * Find ServiceReferences that implements the given type.
+     * <p>
+     * The order of the references is such that Services more local to the querying
+     * Module is earlier in the list.
+     * </p>
+     *
+     * @param <T> Service type
+     * @param serviceType the type that the Services must implement
+     *
+     * @return a stream of ServiceReferences for the given type. It is empty if none exist
+     */
+    <T> Stream<ServiceReference<T>> findServices( Type serviceType );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/ServiceImporter.java b/core/api/src/main/java/org/apache/polygene/api/service/ServiceImporter.java
new file mode 100644
index 0000000..2cbc6cf
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/ServiceImporter.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.api.service;
+
+/**
+ * Import a service from some external source.
+ */
+public interface ServiceImporter<T>
+{
+    /**
+     * Imports an instance of the service type described in the service descriptor.
+     *
+     * @param serviceDescriptor The service descriptor.
+     *
+     * @return The imported service instance.
+     *
+     * @throws ServiceImporterException if import failed.
+     */
+    T importService( ImportedServiceDescriptor serviceDescriptor )
+        throws ServiceImporterException;
+
+    /**
+     * Ask if the service is available or not.
+     *
+     * @param instance the instance to be checked
+     *
+     * @return true if the service is available, false if not
+     */
+    boolean isAvailable( T instance );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/ServiceImporterException.java b/core/api/src/main/java/org/apache/polygene/api/service/ServiceImporterException.java
new file mode 100644
index 0000000..db02796
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/ServiceImporterException.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.api.service;
+
+/**
+ * If a ServiceImporter could not import a service
+ * instance it must throw this exception.
+ */
+public class ServiceImporterException
+    extends RuntimeException
+{
+    public ServiceImporterException()
+    {
+    }
+
+    public ServiceImporterException( String string )
+    {
+        super( string );
+    }
+
+    public ServiceImporterException( String string, Throwable throwable )
+    {
+        super( string, throwable );
+    }
+
+    public ServiceImporterException( Throwable throwable )
+    {
+        super( throwable );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/ServiceReference.java b/core/api/src/main/java/org/apache/polygene/api/service/ServiceReference.java
new file mode 100644
index 0000000..6b01b69
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/ServiceReference.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.api.service;
+
+import org.apache.polygene.api.activation.ActivationEventListenerRegistration;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.identity.Identifiable;
+import org.apache.polygene.api.structure.MetaInfoHolder;
+import org.apache.polygene.api.type.HasTypes;
+
+/**
+ * From a ServiceReference you can access and modify metadata about a service.
+ * You can also access the actual service through get(), that can then be invoked.
+ */
+public interface ServiceReference<T>
+    extends HasTypes, ActivationEventListenerRegistration, MetaInfoHolder, Identifiable
+{
+    /**
+     * @return the actual service
+     */
+    T get();
+
+    /**
+     * @return TRUE if the service is active, otherwise return FALSE
+     */
+    boolean isActive();
+
+    /**
+     * @return TRUE if the service is available, otherwise return FALSE
+     */
+    boolean isAvailable();
+
+    /**
+     * @return the ServiceModel of the service referenced by this ServiceReference.
+     */
+     ModelDescriptor model();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/ServiceUnavailableException.java b/core/api/src/main/java/org/apache/polygene/api/service/ServiceUnavailableException.java
new file mode 100644
index 0000000..a479e6f
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/ServiceUnavailableException.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.api.service;
+
+/**
+ * Thrown when no available service is found.
+ */
+public class ServiceUnavailableException
+    extends RuntimeException
+{
+    public ServiceUnavailableException( String message )
+    {
+        super( message );
+    }
+
+    public ServiceUnavailableException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/importer/InstanceImporter.java b/core/api/src/main/java/org/apache/polygene/api/service/importer/InstanceImporter.java
new file mode 100644
index 0000000..0cab1fd
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/importer/InstanceImporter.java
@@ -0,0 +1,65 @@
+/*
+ *  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.polygene.api.service.importer;
+
+import java.util.Objects;
+import java.util.stream.Stream;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.ServiceImporterException;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.Module;
+
+/**
+ * Return a predefined service instance that was provided as meta-info. Search for meta-info in the following order:
+ * the service itself, the module of the service, the layer of the service, the whole application.
+ */
+public final class InstanceImporter<T>
+    implements ServiceImporter<T>
+{
+    @Structure
+    private Application application;
+
+    @Structure
+    private Layer layer;
+
+    @Structure
+    private Module module;
+
+    @SuppressWarnings( "unchecked" )
+    @Override
+    public T importService( final ImportedServiceDescriptor serviceDescriptor )
+        throws ServiceImporterException
+    {
+        return Stream.of( serviceDescriptor, module, layer, application )
+            .flatMap( holder -> serviceDescriptor.types().map( type -> (T) holder.metaInfo( type ) ) )
+            .filter( Objects::nonNull )
+            .findFirst().orElse( null );
+    }
+
+    @Override
+    public boolean isAvailable( T instance )
+    {
+        return true;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/importer/NewObjectImporter.java b/core/api/src/main/java/org/apache/polygene/api/service/importer/NewObjectImporter.java
new file mode 100644
index 0000000..11df2fd
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/importer/NewObjectImporter.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.api.service.importer;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.ServiceImporterException;
+
+/**
+ * Import Services using a new registered Object instance.
+ */
+public final class NewObjectImporter<T>
+    implements ServiceImporter<T>
+{
+    @Structure
+    private ObjectFactory obf;
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public T importService( ImportedServiceDescriptor serviceDescriptor )
+        throws ServiceImporterException
+    {
+        return obf.newObject( (Class<T>) serviceDescriptor.types().findFirst().orElse( null ));
+    }
+
+    @Override
+    public boolean isAvailable( T instance )
+    {
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/importer/ServiceInstanceImporter.java b/core/api/src/main/java/org/apache/polygene/api/service/importer/ServiceInstanceImporter.java
new file mode 100644
index 0000000..b0abf1b
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/importer/ServiceInstanceImporter.java
@@ -0,0 +1,79 @@
+/*
+ *  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.polygene.api.service.importer;
+
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.ServiceImporterException;
+import org.apache.polygene.api.service.ServiceReference;
+
+/**
+ * Use a registered service that implements ServiceImporter to do the actual
+ * import. The service id of the service that this importer should delegate to must
+ * be set as meta-info on this service. Example:
+ * <pre><code>
+ * module.services(MyServiceImporterService.class).identifiedBy("someid");
+ * module.importedServices(OtherService.class).importedBy(ServiceInstanceImporter.class).setMetaInfo("someid");
+ * </code></pre>
+ */
+public class ServiceInstanceImporter<T>
+    implements ServiceImporter<T>
+{
+    @Structure
+    ServiceFinder finder;
+
+    ServiceImporter<T> service;
+
+    Identity serviceId;
+
+    @Override
+    public T importService( ImportedServiceDescriptor importedServiceDescriptor )
+        throws ServiceImporterException
+    {
+        serviceId = importedServiceDescriptor.metaInfo( Identity.class );
+
+        return serviceImporter().importService( importedServiceDescriptor );
+    }
+
+    @Override
+    public boolean isAvailable( T instance )
+    {
+        return serviceImporter().isAvailable( instance );
+    }
+
+    @SuppressWarnings( {"raw", "unchecked"} )
+    private ServiceImporter<T> serviceImporter()
+    {
+        if( service == null )
+        {
+            service = finder.findServices( ServiceImporter.class )
+                            .filter( ref -> ref.identity().equals( serviceId ) )
+                            .findFirst().map( ServiceReference::get )
+                            .orElseThrow( () -> new ServiceImporterException(
+                                "No service importer with id '" + serviceId + "' was found" )
+                            );
+        }
+        return service;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/importer/ServiceSelectorImporter.java b/core/api/src/main/java/org/apache/polygene/api/service/importer/ServiceSelectorImporter.java
new file mode 100644
index 0000000..929b814
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/importer/ServiceSelectorImporter.java
@@ -0,0 +1,75 @@
+/*
+ *  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.polygene.api.service.importer;
+
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.service.Availability;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.ServiceImporterException;
+import org.apache.polygene.api.service.ServiceReference;
+
+/**
+ * If several services are available with a given type, and you want to constrain
+ * the current module to use a specific one, then use this importer. Specify a
+ * Specification&lt;ServiceReference&lt;T&gt;&gt; criteria as meta-info for the service, which will be applied
+ * to the list of available services, and the first match will be chosen.
+ *
+ * This importer will avoid selecting itself, as could be possible if the ServiceQualifier.first()
+ * filter is used.
+ */
+public final class ServiceSelectorImporter<T>
+    implements ServiceImporter<T>
+{
+    @Structure
+    private ServiceFinder locator;
+
+    @Override
+    @SuppressWarnings( { "raw", "unchecked" } )
+    public T importService( ImportedServiceDescriptor serviceDescriptor )
+        throws ServiceImporterException
+    {
+        Predicate<ServiceReference<?>> selector = serviceDescriptor.metaInfo( Predicate.class );
+        Class serviceType = serviceDescriptor.types().findFirst().orElse( null );
+
+        Stream<ServiceReference<T>> services = locator.findServices( serviceType );
+        Predicate<ServiceReference<T>> filter = ref ->
+        {
+            Predicate selector1 = ref.metaInfo( Predicate.class );
+            return selector1 == null || selector == selector1;
+        };
+        return services.filter( filter.and( selector ) )
+                       .findFirst().map( ServiceReference::get )
+                       .orElseThrow(
+                           () -> new ServiceImporterException(
+                               "Could not find any service to import that matches the given specification for "
+                               + serviceDescriptor.identity() ) );
+    }
+
+    @Override
+    public boolean isAvailable( T instance )
+    {
+        return !( instance instanceof Availability ) || ( (Availability) instance ).isAvailable();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/importer/package.html b/core/api/src/main/java/org/apache/polygene/api/service/importer/package.html
new file mode 100644
index 0000000..be1d382
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/importer/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Service Importers.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/package.html b/core/api/src/main/java/org/apache/polygene/api/service/package.html
new file mode 100644
index 0000000..c217c9c
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Service API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/qualifier/Active.java b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/Active.java
new file mode 100644
index 0000000..8043a7b
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/Active.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.api.service.qualifier;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.function.Predicate;
+import org.apache.polygene.api.service.ServiceReference;
+
+/**
+ * Filter services based on whether they are active or not.
+ * <p>
+ * At an injection point you can do this:
+ * </p>
+ * <pre><code>
+ * &#64;Service &#64;Active MyService service;
+ * </code></pre>
+ * <p>
+ * to get only a service that is currently active.
+ * </p>
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Qualifier( Active.ActiveQualifier.class )
+public @interface Active
+{
+    /**
+     * Active Annotation Qualifier.
+     * See {@link Active}.
+     */
+    final class ActiveQualifier
+        implements AnnotationQualifier<Active>
+    {
+        @Override
+        public <T> Predicate<ServiceReference<?>> qualifier( Active active )
+        {
+            return ServiceQualifier.whereActive();
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/qualifier/AnnotationQualifier.java b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/AnnotationQualifier.java
new file mode 100644
index 0000000..926fde8
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/AnnotationQualifier.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.api.service.qualifier;
+
+import java.lang.annotation.Annotation;
+import java.util.function.Predicate;
+import org.apache.polygene.api.service.ServiceReference;
+
+/**
+ * Constructs a Specification for a given qualifier annotation
+ */
+public interface AnnotationQualifier<QUALIFIER extends Annotation>
+{
+    <T> Predicate<ServiceReference<?>> qualifier( QUALIFIER qualifier );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/qualifier/Available.java b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/Available.java
new file mode 100644
index 0000000..f8b955c
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/Available.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.api.service.qualifier;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.function.Predicate;
+import org.apache.polygene.api.service.ServiceReference;
+
+/**
+ * Filter services based on whether they are available or not.
+ *
+ * At an injection point you can do this:
+ *
+ * <pre><code>
+ * &#64;Service &#64;Available MyService service;
+ * </code></pre>
+ * to get only a service that is currently available.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Qualifier( Available.AvailableQualifier.class )
+public @interface Available
+{
+    /**
+     * Available Annotation Qualifier.
+     * See {@link Available}.
+     */
+    final class AvailableQualifier
+        implements AnnotationQualifier<Available>
+    {
+        @Override
+        public <T> Predicate<ServiceReference<?>> qualifier( Available active )
+        {
+            return ServiceQualifier.whereAvailable();
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/qualifier/HasMetaInfo.java b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/HasMetaInfo.java
new file mode 100644
index 0000000..7881968
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/HasMetaInfo.java
@@ -0,0 +1,104 @@
+/*
+ *  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.polygene.api.service.qualifier;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.function.Predicate;
+import org.apache.polygene.api.service.ServiceReference;
+
+/**
+ * Filter services based on Meta Info being declared on the Service.
+ * <p>
+ * Meta Info of any type can be set on the service during assembly, e.g.;
+ * </p>
+ * <pre><code>
+ * module.addService( MyService.class ).setMetaInfo( new MyCustomInfo(someData) );
+ * </code></pre>
+ * <p>
+ * and then at an injection point you can do this:
+ * </p>
+ * <pre><code>
+ * &#64;Service &#64;HasMetaInfo(MyCustomInfo.class) MyService service;
+ * </code></pre>
+ * <p>
+ * to get only a service that has a MyCustomInfo instance set as meta info.
+ * </p>
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Qualifier( HasMetaInfo.HasMetaInfoQualifier.class )
+@Documented
+public @interface HasMetaInfo
+{
+    /**
+     * The Class(es) needed to have been defined in the Service meta info for a qualifier to evaluate true.
+     *
+     * @return One or more classes that should be defined in the service's meta info for the service to be considered
+     *         qualified. If more than one class is defined, the {@code anded()} parameter will define if they must be
+     *         AND'ed or OR'ed together.
+     */
+    Class[] value();
+
+    /**
+     * True if the Classes defined in the value() field should be AND'ed instead of OR'ed.
+     *
+     * @return If true, all the Class types defined in {@code value()} must be defined for the service for it to be
+     *         qualified. If false, if any of the Class types defined in {@code value()} is defined for the service
+     *         the service is qualified.
+     */
+    boolean anded() default false;
+
+    /**
+     * HasMetaInfo Annotation Qualifier.
+     * See {@link HasMetaInfo}.
+     */
+    class HasMetaInfoQualifier
+        implements AnnotationQualifier<HasMetaInfo>
+    {
+        @Override
+        public Predicate<ServiceReference<?>> qualifier( final HasMetaInfo hasMetaInfo )
+        {
+            return service ->
+            {
+                for( Class metaInfoType : hasMetaInfo.value() )
+                {
+                    @SuppressWarnings( "unchecked" )
+                    Object metaInfo = service.metaInfo( metaInfoType );
+                    if( hasMetaInfo.anded() )
+                    {
+                        if( metaInfo == null )
+                        {
+                            return false;
+                        }
+                    }
+                    else
+                    {
+                        if( metaInfo != null )
+                        {
+                            return true;
+                        }
+                    }
+                }
+                return false;
+            };
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/qualifier/IdentifiedBy.java b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/IdentifiedBy.java
new file mode 100644
index 0000000..343f4cb
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/IdentifiedBy.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.api.service.qualifier;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.function.Predicate;
+import org.apache.polygene.api.service.ServiceReference;
+
+/**
+ * Filter services based on identity. Identity can be set during assembly, like so:
+ * <pre><code>
+ * module.addService(MyService.class).identifiedBy("myservice1");
+ * </code></pre>
+ *
+ * and then at an injection point you can do this:
+ * <pre><code>
+ * &#64;Service @IdentifiedBy("myservice1") MyService service;
+ * </code></pre>
+ * to get only a service identified "myservice1".
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Qualifier( IdentifiedBy.IdentifiedByQualifier.class )
+public @interface IdentifiedBy
+{
+    String value();
+
+    /**
+     * IdentifiedBy Annotation Qualifier.
+     * See {@link IdentifiedBy}.
+     */
+    final class IdentifiedByQualifier
+        implements AnnotationQualifier<IdentifiedBy>
+    {
+        @Override
+        public <T> Predicate<ServiceReference<?>> qualifier( IdentifiedBy identifiedBy )
+        {
+            return ServiceQualifier.withId( identifiedBy.value() );
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/qualifier/Qualifier.java b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/Qualifier.java
new file mode 100644
index 0000000..ca47474
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/Qualifier.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.api.service.qualifier;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Annotation used to declare Qualifiers annotations.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+public @interface Qualifier
+{
+    Class<? extends AnnotationQualifier> value();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/qualifier/ServiceQualifier.java b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/ServiceQualifier.java
new file mode 100644
index 0000000..bcc95d4
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/ServiceQualifier.java
@@ -0,0 +1,83 @@
+/*
+ *  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.polygene.api.service.qualifier;
+
+import java.util.function.Predicate;
+import org.apache.polygene.api.service.ServiceReference;
+
+/**
+ * This class helps you select a particular service
+ * from a list.
+ * <p>
+ * Provide a Selector which does the actual
+ * selection from the list. A common case is to select
+ * based on reference of the service, which you can do this way:
+ * </p>
+ *
+ * <pre><code>
+ * new ServiceQualifier&lt;MyService&gt;(services, ServiceQualifier.withId("someId"))
+ * </code></pre>
+ * <p>
+ * Many selectors can be combined by using firstOf. Example:
+ * </p>
+ * <pre><code>
+ * new ServiceQualifier&lt;MyService&gt;(services, firstOf(withTags("sometag"), firstActive(), first()))
+ * </code></pre>
+ * <p>
+ * This will pick a service that has the tag "sometag", or if none is found take the first active one. If no
+ * service is active, then the first service will be picked.
+ * </p>
+ */
+public abstract class ServiceQualifier
+{
+    public static Predicate<ServiceReference<?>> withId( final String anId )
+    {
+        return service -> service.identity().toString().equals( anId );
+    }
+
+    public static Predicate<ServiceReference<?>> whereMetaInfoIs( final Object metaInfo )
+    {
+        return service ->
+        {
+            Object metaObject = service.metaInfo( metaInfo.getClass() );
+            return metaObject != null && metaInfo.equals( metaObject );
+        };
+    }
+
+    public static Predicate<ServiceReference<?>> whereActive()
+    {
+        return ServiceReference::isActive;
+    }
+
+    public static Predicate<ServiceReference<?>> whereAvailable()
+    {
+        return ServiceReference::isAvailable;
+    }
+
+    public static Predicate<ServiceReference<?>> withTags( final String... tags )
+    {
+        return service ->
+        {
+            ServiceTags serviceTags = service.metaInfo( ServiceTags.class );
+            return serviceTags != null && serviceTags.hasTags( tags );
+        };
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/qualifier/ServiceTags.java b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/ServiceTags.java
new file mode 100644
index 0000000..a0055bf
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/ServiceTags.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.api.service.qualifier;
+
+/**
+ * Use this as metainfo about a Service to specify tags. Easiest way to set them on a service
+ * is to use the <code>ServiceDeclaration.taggedWith(String...)</code> method.
+ *
+ * These can be used in conjunction with the withTags() Service
+ * Selector.
+ */
+public final class ServiceTags
+{
+    private String[] tags;
+
+    public ServiceTags( String... tags )
+    {
+        this.tags = tags;
+    }
+
+    public String[] tags()
+    {
+        return tags;
+    }
+
+    public boolean hasTag( String tag )
+    {
+        for( String serviceTag : tags )
+        {
+            if( serviceTag.equals( tag ) )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public boolean hasTags( String... aTags )
+    {
+        for( String tag : aTags )
+        {
+            if( !hasTag( tag ) )
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/qualifier/Tagged.java b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/Tagged.java
new file mode 100644
index 0000000..3df0780
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/Tagged.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.api.service.qualifier;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.function.Predicate;
+import org.apache.polygene.api.service.ServiceReference;
+
+/**
+ * Filter services based on tags. Tags can be set using the ServiceTags meta-info, like so:
+ * <pre><code>
+ * module.addService(MyService.class).taggedWith(new ServiceTags("onetag","twotag"));
+ * </code></pre>
+ *
+ * and then at an injection point you can do this:
+ *
+ * <pre><code>
+ * &#64;Service &#64;Tagged("onetag") MyService service;
+ * </code></pre>
+ * to get only a service tagged with MyService. If several match only the first match is used.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Qualifier( Tagged.TaggedQualifier.class )
+public @interface Tagged
+{
+    String[] value();
+
+    /**
+     * Tagged Annotation Qualifier.
+     * See {@link Tagged}.
+     */
+    final class TaggedQualifier
+        implements AnnotationQualifier<Tagged>
+    {
+        @Override
+        public Predicate<ServiceReference<?>> qualifier( Tagged tagged )
+        {
+            return ServiceQualifier.withTags( tagged.value() );
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/service/qualifier/package.html b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/package.html
new file mode 100644
index 0000000..d37dc22
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/service/qualifier/package.html
@@ -0,0 +1,62 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Service Qualifiers.</h2>
+        <p>
+            The @Service injection is only able to specify the type of the service to be injected. If any other type of
+            qualification has to be done it has to be done manually but for common cases it's more convenient to use
+            annotations to do this filtering. This package contains annotations to perform this qualification.
+        </p>
+        <p>Example:</p>
+        <blockquote>
+            <pre>@Service @Tagged( "sometag" ) MyService service;</pre>
+        </blockquote>
+        <p>
+            This will only inject instances of MyService that have been tagged with "sometag". If none exist an
+            exception will occur at injection time since it is not optional.
+        </p>
+        <p>It also works with iterables:</p>
+        <blockquote>
+            <pre>@Service @Tagged( "sometag" ) Iterable&lt;MyService&gt; services;</pre>
+        </blockquote>
+        <p>
+            The qualification will be evaluated upon each call to iterator(), and since the qualifier has access to a
+            ServiceReference, which contains the isActive() method, it can even provide some dynamicity.
+        </p>
+        <blockquote>
+            <pre>@Service @Active Iterable&lt;SomeImportedService&gt; importedServices;</pre>
+        </blockquote>
+        <p>
+            Let's say these SomeImportedService are only sometimes available. Then whenever iterator() is called the
+            {@link org.apache.polygene.api.service.qualifier.Active} tag can kick in and filter out those whose
+            ServiceReference.isActive() returns false.
+        </p>
+        <p>Standard ones defined in the API are:</p>
+        <ul>
+            <li>{@link org.apache.polygene.api.service.qualifier.Active}</li>
+            <li>{@link org.apache.polygene.api.service.qualifier.Available}</li>
+            <li>{@link org.apache.polygene.api.service.qualifier.HasMetaInfo}</li>
+            <li>{@link org.apache.polygene.api.service.qualifier.IdentifiedBy}</li>
+            <li>{@link org.apache.polygene.api.service.qualifier.Tagged}</li>
+        </ul>
+        <p>See tests and API for more examples, and how to implement your own qualifiers.</p>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/sideeffect/GenericSideEffect.java b/core/api/src/main/java/org/apache/polygene/api/sideeffect/GenericSideEffect.java
new file mode 100644
index 0000000..7d9119e
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/sideeffect/GenericSideEffect.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.api.sideeffect;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * Base class for generic SideEffects.
+ */
+public abstract class GenericSideEffect
+    extends SideEffectOf<InvocationHandler>
+    implements InvocationHandler
+{
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Object invoke( final Object proxy, final Method method, final Object[] args )
+        throws Throwable
+    {
+        invoke( method, args );
+        return null;
+    }
+
+    /**
+     * Convenience method to be overridden by subclasses in order to avoid returning null, as returned value from side
+     * effects is not taken in consideration.
+     *
+     * @param method the method that was invoked
+     * @param args   the arguments of the method invocation
+     *
+     * @throws Throwable - the exception to throw from the method invocation on the proxy instance. The exception's type
+     *                   must be assignable either to any of the exception types declared in the throws clause of the
+     *                   interface method or to the unchecked exception types {code}java.lang.RuntimeException{code}
+     *                   or {code}java.lang.Error{code}. If a checked exception is thrown by this method that is not
+     *                   assignable to any of the exception types declared in the throws clause of the interface method,
+     *                   then an UndeclaredThrowableException containing the exception that was thrown by this method
+     *                   will be thrown by the method invocation on the proxy instance.
+     */
+    protected void invoke( final Method method, final Object[] args )
+        throws Throwable
+    {
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/sideeffect/SideEffectDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/sideeffect/SideEffectDescriptor.java
new file mode 100644
index 0000000..85a2842
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/sideeffect/SideEffectDescriptor.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.api.sideeffect;
+
+/**
+ * SideEffect Descriptor.
+ */
+public interface SideEffectDescriptor
+{
+    Class<?> modifierClass();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/sideeffect/SideEffectOf.java b/core/api/src/main/java/org/apache/polygene/api/sideeffect/SideEffectOf.java
new file mode 100644
index 0000000..eca348f
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/sideeffect/SideEffectOf.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.api.sideeffect;
+
+import org.apache.polygene.api.sideeffect.internal.SideEffectFor;
+
+/**
+ * Base class for SideEffects. It introduces a typed "next" pointer
+ * that SideEffects can use to get the result of the original invocation.
+ * <p>
+ * Generic SideEffects should subclass {@link GenericSideEffect} instead.
+ * </p>
+ * <p>
+ * SideEffects implementations must be thread-safe in their implementation,
+ * as multiple threads may share instances.
+ * </p>
+ */
+public abstract class SideEffectOf<T>
+{
+    final
+    @SideEffectFor
+    protected T result = null;
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/sideeffect/SideEffects.java b/core/api/src/main/java/org/apache/polygene/api/sideeffect/SideEffects.java
new file mode 100644
index 0000000..af1ab3f
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/sideeffect/SideEffects.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.api.sideeffect;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation is used by composites and mixins to declare what SideEffects
+ * should apply to the type or specific method.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.TYPE, ElementType.METHOD } )
+@Documented
+public @interface SideEffects
+{
+    Class<?>[] value();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/sideeffect/SideEffectsDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/sideeffect/SideEffectsDescriptor.java
new file mode 100644
index 0000000..55bbcf4
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/sideeffect/SideEffectsDescriptor.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.api.sideeffect;
+
+/**
+ * SideEffects Descriptor.
+ */
+public interface SideEffectsDescriptor
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/sideeffect/internal/SideEffectFor.java b/core/api/src/main/java/org/apache/polygene/api/sideeffect/internal/SideEffectFor.java
new file mode 100644
index 0000000..59617c8
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/sideeffect/internal/SideEffectFor.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.api.sideeffect.internal;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.injection.InjectionScope;
+
+/**
+ * This annotation is required once in each SideEffect, to mark the
+ * field where the element providing the invocation result should be
+ * injected.
+ * <p>
+ * The type of the field must be of the same type as the SideEffect
+ * itself, or an InvocationHandler.
+ * </p>
+ * <p>
+ * Example;
+ * </p>
+ * <pre><code>
+ * public interface MyStuff
+ * {
+ *     SomeResult doSomething();
+ * }
+ *
+ * public class MyStuffSideEffect
+ *     implements MyStuff
+ * {
+ *     &#64;SideEffectFor MyStuff next;
+ *
+ *     public SomeResult doSomething()
+ *     {
+ *          SomeResult result = next.doSomething();
+ *
+ *         // HERE DO THE SIDEEFFECT STUFF.
+ *
+ *          return result; // Result value is ignored, null would work too.
+ *     }
+ * }
+ * </code></pre>
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.FIELD, ElementType.PARAMETER })
+@Documented
+@InjectionScope
+public @interface SideEffectFor
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/sideeffect/internal/package.html b/core/api/src/main/java/org/apache/polygene/api/sideeffect/internal/package.html
new file mode 100644
index 0000000..9f70396
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/sideeffect/internal/package.html
@@ -0,0 +1,28 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h1>Internal/Private package for the API.</h1>
+        <p>
+            This is an internal package, and no classes in this package is part of the API and compatibility
+            with these classes will not be attempted.
+        </p>
+    </body>
+</html>
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/sideeffect/package.html b/core/api/src/main/java/org/apache/polygene/api/sideeffect/package.html
new file mode 100644
index 0000000..4f14cc1
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/sideeffect/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SideEffect API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/structure/Application.java b/core/api/src/main/java/org/apache/polygene/api/structure/Application.java
new file mode 100644
index 0000000..0d44678
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/structure/Application.java
@@ -0,0 +1,101 @@
+/*
+ *  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.polygene.api.structure;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivationEventListenerRegistration;
+
+/**
+ * The Application represents a whole Polygene application.
+ */
+public interface Application
+    extends ActivationEventListenerRegistration, Activation, MetaInfoHolder
+{
+    /**
+     * Application modes.
+     */
+    enum Mode
+    {
+        /**
+         * Should be used for unit test runs. Created files etc. should be cleaned up between runs.
+         */
+        test,
+        /**
+         * Should be used during development. Typically create in-memory databases etc.
+         */
+        development,
+        /**
+         * Should be used in QA environments, and other production-like settings where different set of external
+         * resources are utilized.
+         */
+        staging,
+        /**
+         * Should be used in production. All databases are persistent on disk etc.
+         */
+        production
+    }
+
+    /**
+     * @return Application name
+     */
+    String name();
+
+    /**
+     * The version of the application. This can be in any format, but
+     * most likely will follow the Dewey format, i.e. x.y.z.
+     *
+     * @return the version of the application
+     */
+    String version();
+
+    /**
+     * @return Application Mode
+     */
+    Mode mode();
+
+    /**
+     * Find a Layer.
+     *
+     * @param layerName Layer name
+     * @return Found Layer, never returns null
+     * @throws IllegalArgumentException if there's no such Layer
+     */
+    Layer findLayer( String layerName )
+        throws IllegalArgumentException;
+
+    /**
+     * Find a Module.
+     *
+     * @param layerName Layer name
+     * @param moduleName Module name
+     * @return Found Module, never returns null
+     * @throws IllegalArgumentException if there's no such Module
+     */
+    Module findModule( String layerName, String moduleName )
+        throws IllegalArgumentException;
+
+    /**
+     * @return Application Descriptor
+     */
+    ApplicationDescriptor descriptor();
+
+    Stream<? extends Layer> layers();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/structure/ApplicationDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/structure/ApplicationDescriptor.java
new file mode 100644
index 0000000..82d01e0
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/structure/ApplicationDescriptor.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.api.structure;
+
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * Application Descriptor.
+ */
+public interface ApplicationDescriptor
+    extends VisitableHierarchy<Object, Object>
+{
+    /**
+     * Create a new instance of the Application.
+     * @param runtime Polygene Runtime
+     * @param importedServiceInstances Imported Services instances
+     * @return a new instance of the Application.
+     */
+    Application newInstance( PolygeneAPI runtime, Object... importedServiceInstances );
+
+    /**
+     * @return the Application's name
+     */
+    String name();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/structure/Layer.java b/core/api/src/main/java/org/apache/polygene/api/structure/Layer.java
new file mode 100644
index 0000000..2271047
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/structure/Layer.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.api.structure;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivationEventListenerRegistration;
+
+/**
+ * The Layer represents a single layer in a Polygene application.
+ */
+public interface Layer
+    extends ActivationEventListenerRegistration, Activation, MetaInfoHolder
+{
+    /**
+     * @return the Layer's name
+     */
+    String name();
+
+    Application application();
+
+    Stream<? extends Module> modules();
+
+    LayerDescriptor descriptor();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/structure/LayerDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/structure/LayerDescriptor.java
new file mode 100644
index 0000000..e8270ae
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/structure/LayerDescriptor.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.api.structure;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.value.ValueDescriptor;
+
+/**
+ * Layer Descriptor.
+ */
+public interface LayerDescriptor
+{
+
+    /**
+     * @return the Layer's name
+     */
+    String name();
+
+    Layer instance();
+
+    /**
+     * @return Layers used by this Layer
+     */
+    UsedLayersDescriptor usedLayers();
+
+    Stream<? extends ObjectDescriptor> visibleObjects( Visibility visibility );
+
+    Stream<? extends TransientDescriptor> visibleTransients( Visibility visibility );
+
+    Stream<? extends EntityDescriptor> visibleEntities( Visibility visibility );
+
+    Stream<? extends ValueDescriptor> visibleValues( Visibility visibility );
+
+    Stream<? extends ModelDescriptor> visibleServices( Visibility visibility );
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/structure/MetaInfoHolder.java b/core/api/src/main/java/org/apache/polygene/api/structure/MetaInfoHolder.java
new file mode 100644
index 0000000..acfd747
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/structure/MetaInfoHolder.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.api.structure;
+
+/**
+ * MetaInfo holder.
+ */
+public interface MetaInfoHolder
+{
+
+    /**
+     * Get metadata that implements the given type.
+     * The info is registered during assembly of the application.
+     *
+     * @param <T> metadata type
+     * @param infoType the type of metadata to be returned
+     *
+     * @return the metadata for the given type, or <code>null</code> if
+     *         no such metadata has been registered
+     */
+    <T> T metaInfo( Class<T> infoType );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/structure/Module.java b/core/api/src/main/java/org/apache/polygene/api/structure/Module.java
new file mode 100644
index 0000000..635615f
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/structure/Module.java
@@ -0,0 +1,94 @@
+/*
+ *  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.polygene.api.structure;
+
+import org.apache.polygene.api.activation.ActivationEventListenerRegistration;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+/**
+ * API for interacting with a Module. Instances
+ * of this can be accessed by using the {@link Structure}
+ * injection scope.
+ */
+public interface Module
+    extends ActivationEventListenerRegistration,
+            MetaInfoHolder,
+            ObjectFactory,
+            TransientBuilderFactory,
+            ValueBuilderFactory,
+            QueryBuilderFactory,
+            ServiceFinder
+{
+
+    /**
+     * @return the Module's name
+     */
+    String name();
+
+    ModuleDescriptor descriptor();
+
+    /**
+     * @return the Layer that the Module is declared in.
+     */
+    LayerDescriptor layer();
+
+    /** Returns the TypeLookup for the Module.
+     * TypeLookup handles all the types visible from within this Module.
+     *
+     * @return TypeLookup for this Module
+     */
+    TypeLookup typeLookup();
+
+    /** Returns the UnitOfWorkFactory for this Module.
+     *
+     * @return the UnitOfWorkFactory of this Module.
+     */
+    UnitOfWorkFactory unitOfWorkFactory();
+
+    /** Returns the ServiceFinder for this Module.
+     *
+     * @return the ServiceFinder for this Module.
+     */
+    ServiceFinder serviceFinder();
+
+    /** Returns the ValueBuilderFactory for this Module.
+     *
+     * @return the ValueBuilderFactory for this Module.
+     */
+    ValueBuilderFactory valueBuilderFactory();
+
+    /** Returns the TransientBuilderFactory for this Module.
+     *
+     * @return the TransientBuilderFactory for this Module.
+     */
+    TransientBuilderFactory transientBuilderFactory();
+
+    /** Returns the ObjectFactory for this Module.
+     *
+     * @return the ObjectFactory for this Module.
+     */
+    ObjectFactory objectFactory();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/structure/ModuleDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/structure/ModuleDescriptor.java
new file mode 100644
index 0000000..006ab06
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/structure/ModuleDescriptor.java
@@ -0,0 +1,96 @@
+/*
+ *  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.polygene.api.structure;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.value.ValueDescriptor;
+
+/**
+ * Module Descriptor.
+ */
+public interface ModuleDescriptor
+{
+    String name();
+
+    LayerDescriptor layer();
+
+    /**
+     * @return the Module's ClassLoader
+     */
+    ClassLoader classLoader();
+
+    /**
+     * @param typeName name of a transient composite type
+     *
+     * @return the descriptor for a transient composite or null if the class could not be found or the transient composite is not visible
+     */
+    TransientDescriptor transientDescriptor( String typeName );
+
+    /**
+     * @param typeName name of an entity composite type
+     *
+     * @return the descriptor for an entity composite or null if the class could not be found or the entity composite is not visible
+     */
+    EntityDescriptor entityDescriptor( String typeName );
+
+    /**
+     * @param typeName name of an object type
+     *
+     * @return the descriptor for an object or null if the class could not be found or the object is not visible
+     */
+    ObjectDescriptor objectDescriptor( String typeName );
+
+    /**
+     * @param typeName name of a value composite type
+     *
+     * @return the descriptor for a value composite or null if the class could not be found or the value composite is not visible
+     */
+    ValueDescriptor valueDescriptor( String typeName );
+
+    Stream<? extends TransientDescriptor> findVisibleTransientTypes();
+
+    Stream<? extends ValueDescriptor> findVisibleValueTypes();
+
+    Stream<? extends EntityDescriptor> findVisibleEntityTypes();
+
+    Stream<? extends ObjectDescriptor> findVisibleObjectTypes();
+
+    Stream<? extends TransientDescriptor> transientComposites();
+
+    Stream<? extends ValueDescriptor> valueComposites();
+
+    Stream<? extends EntityDescriptor> entityComposites();
+
+    Stream<? extends ObjectDescriptor> objects();
+
+    Stream<? extends ImportedServiceDescriptor> importedServices();
+
+    Stream<? extends ServiceDescriptor> serviceComposites();
+
+    Module instance();
+
+    TypeLookup typeLookup();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/structure/TypeLookup.java b/core/api/src/main/java/org/apache/polygene/api/structure/TypeLookup.java
new file mode 100644
index 0000000..ceafc20
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/structure/TypeLookup.java
@@ -0,0 +1,195 @@
+/*
+ *  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.polygene.api.structure;
+
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.AmbiguousTypeException;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.value.ValueDescriptor;
+
+public interface TypeLookup
+{
+    /**
+     * Lookup first Object Model matching the given Type.
+     *
+     * <p>First, if Object Models exactly match the given type, the closest one (Visibility then Assembly order) is returned.
+     * Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+     *
+     * <p>Second, if Object Models match a type assignable to the given type, the closest one (Visibility then Assembly order) is returned.
+     * Multiple <b>assignable</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+     *
+     * <p>Type lookup is done lazily and cached.</p>
+     *
+     * @param type Looked up Type
+     *
+     * @return First matching Object Model
+     * @throws AmbiguousTypeException when a type ambiguity is found
+     */
+    ObjectDescriptor lookupObjectModel( Class<?> type ) throws AmbiguousTypeException;
+
+    /**
+     * Lookup first Transient Model matching the given Type.
+     *
+     * <p>First, if Transient Models exactly match the given type, the closest one (Visibility then Assembly order) is returned.
+     * Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+     *
+     * <p>Second, if Transient Models match a type assignable to the given type, the closest one (Visibility then Assembly order) is returned.
+     * Multiple <b>assignable</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+     *
+     * <p>Type lookup is done lazily and cached.</p>
+     *
+     * @param type Looked up Type
+     *
+     * @return First matching Transient Model
+     * @throws AmbiguousTypeException when a type ambiguity is found
+     */
+    TransientDescriptor lookupTransientModel( Class<?> type ) throws AmbiguousTypeException;
+
+    /**
+     * Lookup first Value Model matching the given Type.
+     *
+     * <p>First, if Value Models exactly match the given type, the closest one (Visibility then Assembly order) is returned.
+     * Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+     *
+     * <p>Second, if Value Models match a type assignable to the given type, the closest one (Visibility then Assembly order) is returned.
+     * Multiple <b>assignable</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+     *
+     * <p>Type lookup is done lazily and cached.</p>
+     *
+     * @param type Looked up Type
+     *
+     * @return First matching Value Model
+     * @throws AmbiguousTypeException when a type ambiguity is found
+     */
+    ValueDescriptor lookupValueModel( Class<?> type ) throws AmbiguousTypeException;
+
+    /**
+     * Lookup first Entity Model matching the given Type.
+     *
+     * <p>First, if Entity Models exactly match the given type, the closest one (Visibility then Assembly order) is returned.
+     * Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+     *
+     * <p>Second, if Entity Models match a type assignable to the given type, the closest one (Visibility then Assembly order) is returned.
+     * Multiple <b>assignable</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+     *
+     * <p>Type lookup is done lazily and cached.</p>
+     *
+     * <p><b>Should be used for creational use cases only.</b> For non-creational use cases see
+     * {@link #lookupEntityModels(Class)}.</p>
+     *
+     * @param type Looked up Type
+     *
+     * @return First matching Entity Model
+     * @throws AmbiguousTypeException when a type ambiguity is found
+     */
+    EntityDescriptor lookupEntityModel( Class<?> type ) throws AmbiguousTypeException;
+
+    /**
+     * Lookup all Entity Models matching the given Type.
+     *
+     * <p>Returned List contains, in order, Entity Models that: </p>
+     *
+     * <ul>
+     * <li>exactly match the given type, in Visibility then Assembly order ;</li>
+     * <li>match a type assignable to the given type, in Visibility then Assembly order.</li>
+     * </ul>
+     *
+     * <p>Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+     * <p>Multiple <b>assignable</b> matches are <b>allowed</b> to enable polymorphic fetches and queries.</p>
+     *
+     * <p>Type lookup is done lazily and cached.</p>
+     *
+     * <p><b>Should be used for non-creational use cases only.</b> For creational use cases see
+     * {@link #lookupEntityModel(Class)}.</p>
+     *
+     * @param type Looked up Type
+     *
+     * @return All matching Entity Models
+     * @throws AmbiguousTypeException when a type ambiguity is found
+     */
+    List<EntityDescriptor> lookupEntityModels( Class<?> type ) throws AmbiguousTypeException;
+
+    /**
+     * Lookup first ServiceDescriptor/ImportedServiceDescriptor matching the given Type.
+     *
+     * <p>Type lookup is done lazily and cached.</p>
+     *
+     * <p>See {@link #lookupServiceModels(Type)}.</p>
+     *
+     * @param serviceType Looked up Type
+     *
+     * @return First matching Service
+     * @throws AmbiguousTypeException when a type ambiguity is found
+     */
+    ModelDescriptor lookupServiceModel( Type serviceType ) throws AmbiguousTypeException;
+
+    /**
+     * Lookup all ServiceDescriptors matching the given Type.
+     *
+     * <p>Returned List contains, in order, ServiceReferences that: </p>
+     *
+     * <ul>
+     * <li>exactly match the given type, in Visibility then Assembly order ;</li>
+     * <li>match a type assignable to the given type, in Visibility then Assembly order.</li>
+     * </ul>
+     *
+     * <p>Multiple <b>exact</b> matches with the same Visibility are <b>allowed</b> to enable polymorphic lookup/injection.</p>
+     * <p>Multiple <b>assignable</b> matches with the same Visibility are <b>allowed</b> for the very same reason.</p>
+     *
+     * <p>Type lookup is done lazily and cached.</p>
+     *
+     * @param type Looked up Type
+     *
+     * @return All matching ServiceReferences
+     * @throws AmbiguousTypeException when a type ambiguity is found
+     */
+    List<? extends ModelDescriptor> lookupServiceModels( Type type ) throws AmbiguousTypeException;
+
+    /**
+     * @return All visible Objects, in visibility order
+     */
+    Stream<ObjectDescriptor> allObjects();
+
+    /**
+     * @return All visible Transients, in visibility order
+     */
+    Stream<TransientDescriptor> allTransients();
+
+    /**
+     * @return All visible Values, in visibility order
+     */
+    Stream<ValueDescriptor> allValues();
+
+    /**
+     * @return All visible Entities, in visibility order
+     */
+    Stream<EntityDescriptor> allEntities();
+
+    /**
+     * @return All visible Services, in visibility order
+     */
+    Stream<? extends ModelDescriptor> allServices();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/structure/UsedLayersDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/structure/UsedLayersDescriptor.java
new file mode 100644
index 0000000..37ad6b2
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/structure/UsedLayersDescriptor.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.api.structure;
+
+import java.util.stream.Stream;
+
+/**
+ * Used Layers Descriptor.
+ */
+public interface UsedLayersDescriptor
+{
+    Stream<? extends LayerDescriptor> layers();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/structure/package.html b/core/api/src/main/java/org/apache/polygene/api/structure/package.html
new file mode 100644
index 0000000..c44c4ad
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/structure/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Application Structure API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/time/SystemTime.java b/core/api/src/main/java/org/apache/polygene/api/time/SystemTime.java
new file mode 100644
index 0000000..a469001
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/time/SystemTime.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.api.time;
+
+import java.time.Clock;
+import java.time.Instant;
+
+public class SystemTime
+{
+    private static Clock defaultClock = Clock.systemUTC();
+
+    public static Clock getDefaultClock()
+    {
+        return defaultClock;
+    }
+
+    public static void setDefaultClock(Clock defaultClock)
+    {
+        SystemTime.defaultClock = defaultClock;
+    }
+
+    public static Instant now()
+    {
+        return Instant.now(defaultClock);
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/ArrayType.java b/core/api/src/main/java/org/apache/polygene/api/type/ArrayType.java
new file mode 100644
index 0000000..29834ce
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/ArrayType.java
@@ -0,0 +1,97 @@
+/*
+ *  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.polygene.api.type;
+
+import java.lang.reflect.Type;
+import java.util.Objects;
+import org.apache.polygene.api.util.Classes;
+
+/**
+ * Array ValueType.
+ * <p>This handles arrays of primitives and values</p>
+ */
+public class ArrayType extends ValueType
+{
+    public static boolean isArray( Type type )
+    {
+        return Classes.RAW_CLASS.apply( type ).isArray();
+    }
+
+    public static ArrayType of( Class<?> arrayType )
+    {
+        return new ArrayType( arrayType, ValueType.of( arrayType.getComponentType() ) );
+    }
+
+    private ValueType collectedType;
+
+    public ArrayType( Class<?> type, ValueType collectedType )
+    {
+        super( type );
+        this.collectedType = collectedType;
+        if( !isArray( type ) )
+        {
+            throw new IllegalArgumentException( type + " is not an array" );
+        }
+    }
+
+    public ValueType collectedType()
+    {
+        return collectedType;
+    }
+
+    public boolean isArrayOfPrimitives()
+    {
+        return hasType( boolean[].class )
+               || hasType( char[].class )
+               || hasType( short[].class )
+               || hasType( int[].class )
+               || hasType( byte[].class )
+               || hasType( long[].class )
+               || hasType( float[].class )
+               || hasType( double[].class );
+    }
+
+    public boolean isArrayOfPrimitiveBytes()
+    {
+        return hasType( byte[].class );
+    }
+
+    @Override
+    public boolean equals( final Object o )
+    {
+        if( this == o ) { return true; }
+        if( o == null || getClass() != o.getClass() ) { return false; }
+        if( !super.equals( o ) ) { return false; }
+        ArrayType that = (ArrayType) o;
+        return Objects.equals( collectedType, that.collectedType );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return Objects.hash( super.hashCode(), collectedType );
+    }
+
+    @Override
+    public String toString()
+    {
+        return collectedType + "[]";
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/CollectionType.java b/core/api/src/main/java/org/apache/polygene/api/type/CollectionType.java
new file mode 100644
index 0000000..09a0aeb
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/CollectionType.java
@@ -0,0 +1,130 @@
+/*
+ *  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.polygene.api.type;
+
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import org.apache.polygene.api.util.Classes;
+
+/**
+ * Collection ValueType.
+ * <p>This handles Collection, List and Set types.</p>
+ */
+public final class CollectionType
+    extends ValueType
+{
+    public static boolean isCollection( Type type )
+    {
+        Class<?> cl = Classes.RAW_CLASS.apply( type );
+        return Collection.class.isAssignableFrom( cl );
+    }
+
+    public static CollectionType of( Class<?> type, ValueType collectedType )
+    {
+        return new CollectionType( type, collectedType );
+    }
+
+    public static CollectionType of( Class<?> type, Class<?> collectedType )
+    {
+        return of( type, ValueType.of( collectedType ) );
+    }
+
+    public static CollectionType collectionOf( ValueType collectedType )
+    {
+        return of( Collection.class, collectedType );
+    }
+
+    public static CollectionType collectionOf( Class<?> collectedType )
+    {
+        return of( Collection.class, collectedType );
+    }
+
+    public static CollectionType listOf( ValueType collectedType )
+    {
+        return of( List.class, collectedType );
+    }
+
+    public static CollectionType listOf( Class<?> collectedType )
+    {
+        return of( List.class, collectedType );
+    }
+
+    public static CollectionType setOf( ValueType collectedType )
+    {
+        return of( Set.class, collectedType );
+    }
+
+    public static CollectionType setOf( Class<?> collectedType )
+    {
+        return of( Set.class, collectedType );
+    }
+
+    private ValueType collectedType;
+
+    public CollectionType( Class<?> type, ValueType collectedType )
+    {
+        super( type );
+        this.collectedType = collectedType;
+        if( !isCollection( type ) )
+        {
+            throw new IllegalArgumentException( type + " is not a Collection, List or Set." );
+        }
+    }
+
+    public ValueType collectedType()
+    {
+        return collectedType;
+    }
+
+    public boolean isSet()
+    {
+        return Set.class.isAssignableFrom( primaryType() );
+    }
+
+    public boolean isList()
+    {
+        return List.class.isAssignableFrom( primaryType() );
+    }
+
+    @Override
+    public boolean equals( final Object o )
+    {
+        if( this == o ) { return true; }
+        if( o == null || getClass() != o.getClass() ) { return false; }
+        if( !super.equals( o ) ) { return false; }
+        CollectionType that = (CollectionType) o;
+        return Objects.equals( collectedType, that.collectedType );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return Objects.hash( super.hashCode(), collectedType );
+    }
+
+    @Override
+    public String toString()
+    {
+        return super.toString() + "<" + collectedType + ">";
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/EntityCompositeType.java b/core/api/src/main/java/org/apache/polygene/api/type/EntityCompositeType.java
new file mode 100644
index 0000000..27e5c2d
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/EntityCompositeType.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.api.type;
+
+import java.lang.reflect.Type;
+import java.util.Objects;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.util.Classes;
+
+/**
+ * EntityComposite ValueType.
+ */
+public class EntityCompositeType extends StatefulAssociationValueType<EntityDescriptor>
+{
+    public static EntityCompositeType of( EntityDescriptor model )
+    {
+        return new EntityCompositeType( model );
+    }
+
+    public static boolean isEntityComposite( Type type )
+    {
+        return EntityComposite.class.isAssignableFrom( Classes.RAW_CLASS.apply( type ) );
+    }
+
+    public EntityCompositeType( EntityDescriptor model )
+    {
+        super( model );
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o ) { return true; }
+        if( o == null || getClass() != o.getClass() ) { return false; }
+        if( !super.equals( o ) ) { return false; }
+        EntityCompositeType that = (EntityCompositeType) o;
+        return Objects.equals( model, that.model );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return Objects.hash( super.hashCode(), model );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/EnumType.java b/core/api/src/main/java/org/apache/polygene/api/type/EnumType.java
new file mode 100644
index 0000000..9ae6feb
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/EnumType.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.api.type;
+
+import java.lang.reflect.Type;
+
+/**
+ * Enum ValueType.
+ */
+public final class EnumType
+    extends ValueType
+{
+    public static boolean isEnum( Type type )
+    {
+        if( type instanceof Class )
+        {
+            Class<?> typeClass = (Class) type;
+            return typeClass.isEnum();
+        }
+        return false;
+    }
+
+    public static EnumType of( Class<?> type )
+    {
+        return new EnumType( type );
+    }
+
+    private EnumType( Class<?> type )
+    {
+        super( type );
+        if( !isEnum( type ) )
+        {
+            throw new IllegalArgumentException( type + " is not an Enum." );
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/HasAssignableFromType.java b/core/api/src/main/java/org/apache/polygene/api/type/HasAssignableFromType.java
new file mode 100644
index 0000000..68c2b81
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/HasAssignableFromType.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.polygene.api.type;
+
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.function.Predicate;
+
+import static java.util.stream.Collectors.toList;
+
+public class HasAssignableFromType<T extends HasTypes> extends HasTypesPredicate<T>
+{
+    public HasAssignableFromType( Type type )
+    {
+        super( Collections.singletonList( type ) );
+    }
+
+    public HasAssignableFromType( T hasTypes )
+    {
+        super( hasTypes.types().collect( toList() ) );
+    }
+
+    @Override
+    protected Predicate<Type> matchPredicate( Type candidate )
+    {
+        // TODO; what to do if there is ParameterizedType here??
+        // Now set to ClassCastException and see if anything surfaces
+        //if( candidate instanceof Class )
+        {
+            Class<?> clazz = (Class<?>) candidate;
+            return input -> !input.equals( candidate ) && clazz.isAssignableFrom( (Class<?>) input );
+        }
+        //return input -> input.equals( candidate );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/HasAssignableToType.java b/core/api/src/main/java/org/apache/polygene/api/type/HasAssignableToType.java
new file mode 100644
index 0000000..2d14581
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/HasAssignableToType.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.api.type;
+
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.function.Predicate;
+
+import static java.util.stream.Collectors.toList;
+
+public class HasAssignableToType<T extends HasTypes> extends HasTypesPredicate<T>
+{
+    public HasAssignableToType( Type type )
+    {
+        super( Collections.singletonList( type ) );
+    }
+
+    public HasAssignableToType( T hasTypes )
+    {
+        super( hasTypes.types().collect( toList() ) );
+    }
+
+    @Override
+    protected Predicate<Type> matchPredicate( Type candidate )
+    {
+        // TODO; what to do if there is ParameterizedType here??
+        // Now set to ClassCastException and see if anything surfaces
+        Class<?> clazz = (Class<?>) candidate;
+        return input -> !input.equals( candidate ) && ( (Class<?>) input ).isAssignableFrom( clazz );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/HasEqualOrAssignableFromType.java b/core/api/src/main/java/org/apache/polygene/api/type/HasEqualOrAssignableFromType.java
new file mode 100644
index 0000000..233096b
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/HasEqualOrAssignableFromType.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.api.type;
+
+import java.lang.reflect.Type;
+import java.util.function.Predicate;
+
+public class HasEqualOrAssignableFromType<T extends HasTypes> implements Predicate<T>
+{
+    private final Predicate<T> composedPredicate;
+
+    public HasEqualOrAssignableFromType( Type type )
+    {
+        composedPredicate = new HasEqualType<T>( type ).or( new HasAssignableFromType<>( type ) );
+    }
+
+    public HasEqualOrAssignableFromType( T hasTypes )
+    {
+        composedPredicate = new HasEqualType<>( hasTypes ).or( new HasAssignableFromType<>( hasTypes ) );
+    }
+
+    @Override
+    public boolean test( T hasTypes )
+    {
+        return composedPredicate.test( hasTypes );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/HasEqualOrAssignableToType.java b/core/api/src/main/java/org/apache/polygene/api/type/HasEqualOrAssignableToType.java
new file mode 100644
index 0000000..19911db
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/HasEqualOrAssignableToType.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.api.type;
+
+import java.lang.reflect.Type;
+import java.util.function.Predicate;
+
+public class HasEqualOrAssignableToType<T extends HasTypes> implements Predicate<T>
+{
+    private final Predicate<T> composedPredicate;
+
+    public HasEqualOrAssignableToType( Type type )
+    {
+        composedPredicate = new HasEqualType<T>( type ).or( new HasAssignableToType<>( type ) );
+    }
+
+    public HasEqualOrAssignableToType( T hasTypes )
+    {
+        composedPredicate = new HasEqualType<>( hasTypes ).or( new HasAssignableToType<>( hasTypes ) );
+    }
+
+    @Override
+    public boolean test( T hasTypes )
+    {
+        return composedPredicate.test( hasTypes );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/HasEqualType.java b/core/api/src/main/java/org/apache/polygene/api/type/HasEqualType.java
new file mode 100644
index 0000000..a6f93f7
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/HasEqualType.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.api.type;
+
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.function.Predicate;
+
+import static java.util.stream.Collectors.toList;
+
+public class HasEqualType<T extends HasTypes> extends HasTypesPredicate<T>
+{
+    public HasEqualType( Type type )
+    {
+        super( Collections.singletonList( type ) );
+    }
+
+    public HasEqualType( T hasTypes )
+    {
+        super( hasTypes.types().collect( toList() ) );
+    }
+
+    @Override
+    protected Predicate<Type> matchPredicate( Type candidate )
+    {
+        return candidate::equals;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/HasTypes.java b/core/api/src/main/java/org/apache/polygene/api/type/HasTypes.java
new file mode 100644
index 0000000..ae1f3c9
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/HasTypes.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.api.type;
+
+import java.lang.reflect.Type;
+import java.util.stream.Stream;
+import org.apache.polygene.api.util.Classes;
+
+/**
+ * Has types.
+ */
+public interface HasTypes
+{
+    Stream<Class<?>> types();
+
+    default boolean hasType( Type type )
+    {
+        Class<?> rawType = Classes.RAW_CLASS.apply( type );
+        return types().map( Classes.RAW_CLASS ).anyMatch( rawType::isAssignableFrom );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/HasTypesCollectors.java b/core/api/src/main/java/org/apache/polygene/api/type/HasTypesCollectors.java
new file mode 100644
index 0000000..4829f41
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/HasTypesCollectors.java
@@ -0,0 +1,427 @@
+/*
+ *  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.polygene.api.type;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.stream.Collector;
+
+/**
+ * Collectors for HasTypes.
+ */
+public class HasTypesCollectors
+{
+    private static final String EQUAL_KEY = "equal";
+    private static final String EQUAL_TYPE_KEY = "equalType";
+    private static final String ASSIGNABLE_TYPE_KEY = "assignableType";
+
+    public static <T extends HasTypes> Collector<T, ?, Optional<T>> matchingType( T hasTypes )
+    {
+        return hasTypesFindFirstCollector( hasTypes, new HasAssignableFromType<>( hasTypes ) );
+    }
+
+    public static <T extends HasTypes> Collector<T, ?, Optional<T>> closestType( T hasTypes )
+    {
+        return hasTypesFindFirstCollector( hasTypes, new HasAssignableToType<>( hasTypes ) );
+    }
+
+    private static <T extends HasTypes> Collector<T, ?, Optional<T>>
+    hasTypesFindFirstCollector( T hasTypes, Predicate<T> assignableTypePredicate )
+    {
+        Predicate<T> equalPredicate = o -> Objects.equals( o, hasTypes );
+        Predicate<T> equalTypePredicate = new HasEqualType<>( hasTypes );
+        return new Collector<T, Map<String, Set<T>>, Optional<T>>()
+        {
+            @Override
+            public Supplier<Map<String, Set<T>>> supplier()
+            {
+                return () -> new HashMap<String, Set<T>>( 3 )
+                {{
+                    put( EQUAL_KEY, new LinkedHashSet<>( 1 ) );
+                    put( EQUAL_TYPE_KEY, new LinkedHashSet<>( 1 ) );
+                    put( ASSIGNABLE_TYPE_KEY, new LinkedHashSet<>() );
+                }};
+            }
+
+            @Override
+            public BiConsumer<Map<String, Set<T>>, T> accumulator()
+            {
+                return ( map, candidate ) ->
+                {
+                    Set<T> equalObjects = map.get( EQUAL_KEY );
+                    if( equalObjects.isEmpty() )
+                    {
+                        if( equalPredicate.test( candidate ) )
+                        {
+                            equalObjects.add( candidate );
+                        }
+                        else
+                        {
+                            Set<T> equalTypes = map.get( EQUAL_TYPE_KEY );
+                            if( equalTypes.isEmpty() )
+                            {
+                                if( equalTypePredicate.test( candidate ) )
+                                {
+                                    equalTypes.add( candidate );
+                                }
+                                else if( assignableTypePredicate.test( candidate ) )
+                                {
+                                    map.get( ASSIGNABLE_TYPE_KEY ).add( candidate );
+                                }
+                            }
+                        }
+                    }
+                };
+            }
+
+            @Override
+            public BinaryOperator<Map<String, Set<T>>> combiner()
+            {
+                return ( left, right ) ->
+                {
+                    left.get( EQUAL_KEY ).addAll( right.get( EQUAL_KEY ) );
+                    left.get( EQUAL_TYPE_KEY ).addAll( right.get( EQUAL_TYPE_KEY ) );
+                    left.get( ASSIGNABLE_TYPE_KEY ).addAll( right.get( ASSIGNABLE_TYPE_KEY ) );
+                    return left;
+                };
+            }
+
+            @Override
+            public Function<Map<String, Set<T>>, Optional<T>> finisher()
+            {
+                return map ->
+                {
+                    Set<T> equalObjects = map.get( EQUAL_KEY );
+                    if( !equalObjects.isEmpty() )
+                    {
+                        return Optional.of( equalObjects.iterator().next() );
+                    }
+                    Set<T> equalTypes = map.get( EQUAL_TYPE_KEY );
+                    if( !equalTypes.isEmpty() )
+                    {
+                        return Optional.of( equalTypes.iterator().next() );
+                    }
+                    Set<T> assignableTypes = map.get( ASSIGNABLE_TYPE_KEY );
+                    if( !assignableTypes.isEmpty() )
+                    {
+                        return Optional.of( assignableTypes.iterator().next() );
+                    }
+                    return Optional.empty();
+                };
+            }
+
+            @Override
+            public Set<Characteristics> characteristics()
+            {
+                return Collections.emptySet();
+            }
+        };
+    }
+
+
+    public static <T extends HasTypes> Collector<T, ?, List<T>> matchingTypes( T hasTypes )
+    {
+        return hasTypesToListCollector( hasTypes, new HasAssignableFromType<>( hasTypes ) );
+    }
+
+    public static <T extends HasTypes> Collector<T, ?, List<T>> closestTypes( T hasTypes )
+    {
+        return hasTypesToListCollector( hasTypes, new HasAssignableToType<>( hasTypes ) );
+    }
+
+    private static <T extends HasTypes> Collector<T, ?, List<T>>
+    hasTypesToListCollector( T hasTypes, Predicate<T> assignableTypePredicate )
+    {
+        Predicate<T> equalPredicate = o -> Objects.equals( o, hasTypes );
+        Predicate<T> equalTypePredicate = new HasEqualType<>( hasTypes );
+        return new Collector<T, Map<String, Set<T>>, List<T>>()
+        {
+            @Override
+            public Supplier<Map<String, Set<T>>> supplier()
+            {
+                return () -> new HashMap<String, Set<T>>( 3 )
+                {{
+                    put( EQUAL_KEY, new LinkedHashSet<>() );
+                    put( EQUAL_TYPE_KEY, new LinkedHashSet<>() );
+                    put( ASSIGNABLE_TYPE_KEY, new LinkedHashSet<>() );
+                }};
+            }
+
+            @Override
+            public BiConsumer<Map<String, Set<T>>, T> accumulator()
+            {
+                return ( map, candidate ) ->
+                {
+                    Set<T> equalObjects = map.get( EQUAL_KEY );
+                    if( equalObjects.isEmpty() )
+                    {
+                        if( equalPredicate.test( candidate ) )
+                        {
+                            equalObjects.add( candidate );
+                        }
+                        else
+                        {
+                            Set<T> equalTypes = map.get( EQUAL_TYPE_KEY );
+                            if( equalTypes.isEmpty() )
+                            {
+                                if( equalTypePredicate.test( candidate ) )
+                                {
+                                    equalTypes.add( candidate );
+                                }
+                                else if( assignableTypePredicate.test( candidate ) )
+                                {
+                                    map.get( ASSIGNABLE_TYPE_KEY ).add( candidate );
+                                }
+                            }
+                        }
+                    }
+                };
+            }
+
+            @Override
+            public BinaryOperator<Map<String, Set<T>>> combiner()
+            {
+                return ( left, right ) ->
+                {
+                    left.get( EQUAL_KEY ).addAll( right.get( EQUAL_KEY ) );
+                    left.get( EQUAL_TYPE_KEY ).addAll( right.get( EQUAL_TYPE_KEY ) );
+                    left.get( ASSIGNABLE_TYPE_KEY ).addAll( right.get( ASSIGNABLE_TYPE_KEY ) );
+                    return left;
+                };
+            }
+
+            @Override
+            public Function<Map<String, Set<T>>, List<T>> finisher()
+            {
+                return map ->
+                {
+                    Set<T> equalObjects = map.get( EQUAL_KEY );
+                    Set<T> equalSet = map.get( EQUAL_TYPE_KEY );
+                    Set<T> assignableSet = map.get( ASSIGNABLE_TYPE_KEY );
+                    List<T> list = new ArrayList<>( equalObjects.size() + equalSet.size() + assignableSet.size() );
+                    list.addAll( equalObjects );
+                    list.addAll( equalSet );
+                    list.addAll( assignableSet );
+                    return list;
+                };
+            }
+
+            @Override
+            public Set<Characteristics> characteristics()
+            {
+                return Collections.emptySet();
+            }
+        };
+    }
+
+
+    /**
+     * Collect a single matching HasTypes.
+     *
+     * TODO Detail
+     *
+     * @param type type to match
+     * @param <T> type of HasTypes
+     * @return an optional best matching HasTypes
+     */
+    public static <T extends HasTypes> Collector<T, ?, Optional<T>> matchingType( Type type )
+    {
+        return typeFindFirstCollector( type, new HasAssignableFromType<>( type ) );
+    }
+
+    public static <T extends HasTypes> Collector<T, ?, Optional<T>> closestType( Type type )
+    {
+        return typeFindFirstCollector( type, new HasAssignableToType<T>( type ) );
+    }
+
+    private static <T extends HasTypes> Collector<T, ?, Optional<T>>
+    typeFindFirstCollector( Type type, Predicate<T> assignableTypePredicate )
+    {
+        Predicate<T> equalTypePredicate = new HasEqualType<>( type );
+        return new Collector<T, Map<String, Set<T>>, Optional<T>>()
+        {
+            @Override
+            public Supplier<Map<String, Set<T>>> supplier()
+            {
+                return () -> new HashMap<String, Set<T>>( 2 )
+                {{
+                    put( EQUAL_TYPE_KEY, new LinkedHashSet<>( 1 ) );
+                    put( ASSIGNABLE_TYPE_KEY, new LinkedHashSet<>() );
+                }};
+            }
+
+            @Override
+            public BiConsumer<Map<String, Set<T>>, T> accumulator()
+            {
+                return ( map, candidate ) ->
+                {
+                    Set<T> equalSet = map.get( EQUAL_TYPE_KEY );
+                    if( equalSet.isEmpty() )
+                    {
+                        if( equalTypePredicate.test( candidate ) )
+                        {
+                            equalSet.add( candidate );
+                        }
+                        else if( assignableTypePredicate.test( candidate ) )
+                        {
+                            map.get( ASSIGNABLE_TYPE_KEY ).add( candidate );
+                        }
+                    }
+                };
+            }
+
+            @Override
+            public BinaryOperator<Map<String, Set<T>>> combiner()
+            {
+                return ( left, right ) ->
+                {
+                    left.get( EQUAL_TYPE_KEY ).addAll( right.get( EQUAL_TYPE_KEY ) );
+                    left.get( ASSIGNABLE_TYPE_KEY ).addAll( right.get( ASSIGNABLE_TYPE_KEY ) );
+                    return left;
+                };
+            }
+
+            @Override
+            public Function<Map<String, Set<T>>, Optional<T>> finisher()
+            {
+                return map ->
+                {
+                    Set<T> equalSet = map.get( EQUAL_TYPE_KEY );
+                    if( !equalSet.isEmpty() )
+                    {
+                        return Optional.of( equalSet.iterator().next() );
+                    }
+                    Set<T> assignableSet = map.get( ASSIGNABLE_TYPE_KEY );
+                    if( !assignableSet.isEmpty() )
+                    {
+                        return Optional.of( assignableSet.iterator().next() );
+                    }
+                    return Optional.empty();
+                };
+            }
+
+            @Override
+            public final Set<Characteristics> characteristics()
+            {
+                return Collections.emptySet();
+            }
+        };
+    }
+
+    /**
+     * Collect all matching HasTypes.
+     *
+     * First the ones with at least on equal type.
+     * Then the ones with at least one type assignable from {@literal type}.
+     *
+     * @param type type to match
+     * @param <T> type of HasTypes
+     * @return an optional best matching HasTypes
+     */
+    public static <T extends HasTypes> Collector<T, ?, List<T>> matchingTypes( Type type )
+    {
+        return typeToListCollector( type, new HasAssignableFromType<>( type ) );
+    }
+
+    public static <T extends HasTypes> Collector<T, ?, List<T>> closestTypes( Type type )
+    {
+        return typeToListCollector( type, new HasAssignableToType<>( type ) );
+    }
+
+    private static <T extends HasTypes> Collector<T, ?, List<T>>
+    typeToListCollector( Type type, Predicate<T> assignableTypePredicate )
+    {
+        Predicate<T> equalTypePredicate = new HasEqualType<>( type );
+        return new Collector<T, Map<String, Set<T>>, List<T>>()
+        {
+            @Override
+            public Supplier<Map<String, Set<T>>> supplier()
+            {
+                return () -> new HashMap<String, Set<T>>( 2 )
+                {{
+                    put( EQUAL_TYPE_KEY, new LinkedHashSet<>() );
+                    put( ASSIGNABLE_TYPE_KEY, new LinkedHashSet<>() );
+                }};
+            }
+
+            @Override
+            public BiConsumer<Map<String, Set<T>>, T> accumulator()
+            {
+                return ( map, candidate ) ->
+                {
+                    if( equalTypePredicate.test( candidate ) )
+                    {
+                        map.get( EQUAL_TYPE_KEY ).add( candidate );
+                    }
+                    else if( assignableTypePredicate.test( candidate ) )
+                    {
+                        map.get( ASSIGNABLE_TYPE_KEY ).add( candidate );
+                    }
+                };
+            }
+
+            @Override
+            public BinaryOperator<Map<String, Set<T>>> combiner()
+            {
+                return ( left, right ) ->
+                {
+                    left.get( EQUAL_TYPE_KEY ).addAll( right.get( EQUAL_TYPE_KEY ) );
+                    left.get( ASSIGNABLE_TYPE_KEY ).addAll( right.get( ASSIGNABLE_TYPE_KEY ) );
+                    return left;
+                };
+            }
+
+            @Override
+            public Function<Map<String, Set<T>>, List<T>> finisher()
+            {
+                return map ->
+                {
+                    Set<T> equalSet = map.get( EQUAL_TYPE_KEY );
+                    Set<T> assignableSet = map.get( ASSIGNABLE_TYPE_KEY );
+                    List<T> list = new ArrayList<>( equalSet.size() + assignableSet.size() );
+                    list.addAll( equalSet );
+                    list.addAll( assignableSet );
+                    return list;
+                };
+            }
+
+            @Override
+            public final Set<Characteristics> characteristics()
+            {
+                return Collections.emptySet();
+            }
+        };
+    }
+
+    private HasTypesCollectors() {}
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/HasTypesPredicate.java b/core/api/src/main/java/org/apache/polygene/api/type/HasTypesPredicate.java
new file mode 100644
index 0000000..da1f87a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/HasTypesPredicate.java
@@ -0,0 +1,79 @@
+/*
+ *  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.polygene.api.type;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.WildcardType;
+import java.util.List;
+import java.util.function.Predicate;
+
+import static org.apache.polygene.api.util.Classes.interfacesOf;
+
+public abstract class HasTypesPredicate<T extends HasTypes> implements Predicate<T>
+{
+    protected final List<Type> matchTypes;
+
+    protected HasTypesPredicate( List<Type> types )
+    {
+        matchTypes = types;
+    }
+
+    @Override
+    public final boolean test( T hasTypes )
+    {
+        for( Type matchType : matchTypes )
+        {
+            if( matchType instanceof Class )
+            {
+                if( hasTypes.types().anyMatch( matchPredicate( matchType ) ) )
+                {
+                    return true;
+                }
+            }
+            else
+            {
+                if( matchType instanceof ParameterizedType )
+                {
+                    // Foo<Bar> check
+                    // First check Foo
+                    ParameterizedType parameterizedType = (ParameterizedType) matchType;
+                    Type rawType = parameterizedType.getRawType();
+
+                    if( hasTypes.types().anyMatch( matchPredicate( rawType ) ) )
+                    {
+                        // Then check Bar
+                        if( interfacesOf( hasTypes.types() ).anyMatch( intf -> intf.equals( matchType ) ) )
+                        {
+                            return true;
+                        }
+                    }
+                }
+                else if( matchType instanceof WildcardType )
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    protected abstract Predicate<Type> matchPredicate( Type candidate );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/MapType.java b/core/api/src/main/java/org/apache/polygene/api/type/MapType.java
new file mode 100644
index 0000000..23124eb
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/MapType.java
@@ -0,0 +1,106 @@
+/*
+ *  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.polygene.api.type;
+
+import java.lang.reflect.Type;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.polygene.api.util.Classes;
+
+/**
+ * Map ValueType.
+ * <p>This handles instances of Map.</p>
+ */
+public final class MapType
+    extends ValueType
+{
+    public static boolean isMap( Type type )
+    {
+        Class<?> cl = Classes.RAW_CLASS.apply( type );
+        return Map.class.isAssignableFrom( cl );
+    }
+
+    public static MapType of( Class<?> mapType, ValueType keyType, ValueType valueType )
+    {
+        return new MapType( mapType, keyType, valueType );
+    }
+
+    public static MapType of( Class<?> mapType, Class<?> keyType, Class<?> valueType )
+    {
+        return of( mapType, ValueType.of( keyType ), ValueType.of( valueType ) );
+    }
+
+    public static MapType of( ValueType keyType, ValueType valueType )
+    {
+        return new MapType( Map.class, keyType, valueType );
+    }
+
+    public static MapType of( Class<?> keyType, Class<?> valueType )
+    {
+        return of( ValueType.of( keyType ), ValueType.of( valueType ) );
+    }
+
+    private ValueType keyType;
+    private ValueType valueType;
+
+    public MapType( Class<?> type, ValueType keyType, ValueType valueType )
+    {
+        super( type );
+        this.keyType = keyType;
+        this.valueType = valueType;
+        if( !isMap( type ) )
+        {
+            throw new IllegalArgumentException( type + " is not a Map." );
+        }
+    }
+
+    public ValueType keyType()
+    {
+        return keyType;
+    }
+
+    public ValueType valueType()
+    {
+        return valueType;
+    }
+
+    @Override
+    public boolean equals( final Object o )
+    {
+        if( this == o ) { return true; }
+        if( o == null || getClass() != o.getClass() ) { return false; }
+        if( !super.equals( o ) ) { return false; }
+        MapType mapType = (MapType) o;
+        return Objects.equals( keyType, mapType.keyType ) &&
+               Objects.equals( valueType, mapType.valueType );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return Objects.hash( super.hashCode(), keyType, valueType );
+    }
+
+    @Override
+    public String toString()
+    {
+        return super.toString() + "<" + keyType + "," + valueType + ">";
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/StatefulAssociationValueType.java b/core/api/src/main/java/org/apache/polygene/api/type/StatefulAssociationValueType.java
new file mode 100644
index 0000000..ae2a2d9
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/StatefulAssociationValueType.java
@@ -0,0 +1,75 @@
+/*
+ *  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.polygene.api.type;
+
+import java.lang.reflect.Type;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.StatefulAssociationCompositeDescriptor;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.value.ValueComposite;
+
+public abstract class StatefulAssociationValueType<M extends StatefulAssociationCompositeDescriptor & CompositeDescriptor>
+    extends ValueType
+{
+    public static boolean isStatefulAssociationValue( Type type )
+    {
+        Class<?> rawClass = Classes.RAW_CLASS.apply( type );
+        return ValueComposite.class.isAssignableFrom( rawClass ) || EntityComposite.class.isAssignableFrom( rawClass );
+    }
+
+    protected final M model;
+
+    protected StatefulAssociationValueType( M model )
+    {
+        super( model.types().collect( Collectors.toList() ) );
+        this.model = model;
+    }
+
+    public ModuleDescriptor module()
+    {
+        return model.module();
+    }
+
+    public Stream<? extends PropertyDescriptor> properties()
+    {
+        return model.state().properties();
+    }
+
+    public Stream<? extends AssociationDescriptor> associations()
+    {
+        return model.state().associations();
+    }
+
+    public Stream<? extends AssociationDescriptor> manyAssociations()
+    {
+        return model.state().manyAssociations();
+    }
+
+    public Stream<? extends AssociationDescriptor> namedAssociations()
+    {
+        return model.state().namedAssociations();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/ValueCompositeType.java b/core/api/src/main/java/org/apache/polygene/api/type/ValueCompositeType.java
new file mode 100644
index 0000000..648a4d3
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/ValueCompositeType.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.api.type;
+
+import java.lang.reflect.Type;
+import java.util.Objects;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.api.value.ValueDescriptor;
+
+/**
+ * ValueComposite ValueType.
+ */
+public final class ValueCompositeType extends StatefulAssociationValueType<ValueDescriptor>
+{
+    public static ValueCompositeType of( ValueDescriptor model )
+    {
+        return new ValueCompositeType( model );
+    }
+
+    public static boolean isValueComposite( Type type )
+    {
+        return ValueComposite.class.isAssignableFrom( Classes.RAW_CLASS.apply( type ) );
+    }
+
+    public ValueCompositeType( ValueDescriptor model )
+    {
+        super( model );
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o ) { return true; }
+        if( o == null || getClass() != o.getClass() ) { return false; }
+        if( !super.equals( o ) ) { return false; }
+        ValueCompositeType that = (ValueCompositeType) o;
+        return Objects.equals( model, that.model );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return Objects.hash( super.hashCode(), model );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/ValueType.java b/core/api/src/main/java/org/apache/polygene/api/type/ValueType.java
new file mode 100644
index 0000000..6c45db2
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/ValueType.java
@@ -0,0 +1,172 @@
+/*
+ *  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.polygene.api.type;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.Period;
+import java.time.ZonedDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Stream;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.Identity;
+
+import static java.util.stream.Collectors.joining;
+
+/**
+ * Base class for types of values in ValueComposites and Properties.
+ */
+public class ValueType implements HasTypes
+{
+    public static final ValueType OBJECT = ValueType.of( Object.class );
+    public static final ValueType STRING = ValueType.of( String.class );
+    public static final ValueType CHARACTER = ValueType.of( Character.class, char.class );
+    public static final ValueType BOOLEAN = ValueType.of( Boolean.class, boolean.class );
+    public static final ValueType INTEGER = ValueType.of( Integer.class, int.class );
+    public static final ValueType SHORT = ValueType.of( Short.class, short.class );
+    public static final ValueType LONG = ValueType.of( Long.class, long.class );
+    public static final ValueType BYTE = ValueType.of( Byte.class, byte.class );
+    public static final ValueType FLOAT = ValueType.of( Float.class, float.class );
+    public static final ValueType DOUBLE = ValueType.of( Double.class, double.class );
+    public static final ValueType BIG_DECIMAL = ValueType.of( BigDecimal.class );
+    public static final ValueType BIG_INTEGER = ValueType.of( BigInteger.class );
+    public static final ValueType INSTANT = ValueType.of( Instant.class );
+    public static final ValueType ZONED_DATE_TIME = ValueType.of( ZonedDateTime.class );
+    public static final ValueType OFFSET_DATE_TIME = ValueType.of( OffsetDateTime.class );
+    public static final ValueType LOCAL_DATE_TIME = ValueType.of( LocalDateTime.class );
+    public static final ValueType LOCAL_DATE = ValueType.of( LocalDate.class );
+    public static final ValueType LOCAL_TIME = ValueType.of( LocalTime.class );
+    public static final ValueType DURATION = ValueType.of( Duration.class );
+    public static final ValueType PERIOD = ValueType.of( Period.class );
+    public static final ValueType IDENTITY = ValueType.of( Identity.class );
+    public static final ValueType ENTITY_REFERENCE = ValueType.of( EntityReference.class );
+
+    public static ValueType of( Class<?>... types )
+    {
+        return new ValueType( types );
+    }
+
+    protected final List<Class<?>> types;
+
+    protected ValueType( Class<?>... types )
+    {
+        this( Arrays.asList( types ) );
+    }
+
+    protected ValueType( List<Class<?>> types )
+    {
+        this.types = applyPrimitiveAndBoxedTypes( types );
+    }
+
+    private List<Class<?>> applyPrimitiveAndBoxedTypes( List<Class<?>> types )
+    {
+        int charPrimitiveIndex = types.indexOf( char.class );
+        int charBoxedIndex = types.indexOf( Character.class );
+        int boolPrimitiveIndex = types.indexOf( boolean.class );
+        int boolBoxedIndex = types.indexOf( Boolean.class );
+        int intPrimitiveIndex = types.indexOf( int.class );
+        int intBoxedIndex = types.indexOf( Integer.class );
+        int shortPrimitiveIndex = types.indexOf( short.class );
+        int shortBoxedIndex = types.indexOf( Short.class );
+        int longPrimitiveIndex = types.indexOf( long.class );
+        int longBoxedIndex = types.indexOf( Long.class );
+        int bytePrimitiveIndex = types.indexOf( byte.class );
+        int byteBoxedIndex = types.indexOf( Byte.class );
+        int floatPrimitiveIndex = types.indexOf( float.class );
+        int floatBoxedIndex = types.indexOf( Float.class );
+        int doublePrimitiveIndex = types.indexOf( double.class );
+        int doubleBoxedIndex = types.indexOf( Double.class );
+        if( charPrimitiveIndex == -1 && charBoxedIndex == -1
+            && boolPrimitiveIndex == -1 && boolBoxedIndex == -1
+            && intPrimitiveIndex == -1 && intBoxedIndex == -1
+            && shortPrimitiveIndex == -1 && shortBoxedIndex == -1
+            && longPrimitiveIndex == -1 && longBoxedIndex == -1
+            && bytePrimitiveIndex == -1 && byteBoxedIndex == -1
+            && floatPrimitiveIndex == -1 && floatBoxedIndex == -1
+            && doublePrimitiveIndex == -1 && doubleBoxedIndex == -1 )
+        {
+            return types;
+        }
+        List<Class<?>> allTypes = new ArrayList<>( types );
+        if( charPrimitiveIndex >= 0 && charBoxedIndex == -1 ) { allTypes.add( Character.class ); }
+        if( charPrimitiveIndex == -1 && charBoxedIndex >= 0 ) { allTypes.add( char.class ); }
+        if( boolPrimitiveIndex >= 0 && boolBoxedIndex == -1 ) { allTypes.add( Boolean.class ); }
+        if( boolPrimitiveIndex == -1 && boolBoxedIndex >= 0 ) { allTypes.add( boolean.class ); }
+        if( intPrimitiveIndex >= 0 && intBoxedIndex == -1 ) { allTypes.add( Integer.class ); }
+        if( intPrimitiveIndex == -1 && intBoxedIndex >= 0 ) { allTypes.add( int.class ); }
+        if( shortPrimitiveIndex >= 0 && shortBoxedIndex == -1 ) { allTypes.add( Short.class ); }
+        if( shortPrimitiveIndex == -1 && shortBoxedIndex >= 0 ) { allTypes.add( short.class ); }
+        if( longPrimitiveIndex >= 0 && longBoxedIndex == -1 ) { allTypes.add( Long.class ); }
+        if( longPrimitiveIndex == -1 && longBoxedIndex >= 0 ) { allTypes.add( long.class ); }
+        if( bytePrimitiveIndex >= 0 && byteBoxedIndex == -1 ) { allTypes.add( Byte.class ); }
+        if( bytePrimitiveIndex == -1 && byteBoxedIndex >= 0 ) { allTypes.add( byte.class ); }
+        if( floatPrimitiveIndex >= 0 && floatBoxedIndex == -1 ) { allTypes.add( Float.class ); }
+        if( floatPrimitiveIndex == -1 && floatBoxedIndex >= 0 ) { allTypes.add( float.class ); }
+        if( doublePrimitiveIndex >= 0 && doubleBoxedIndex == -1 ) { allTypes.add( Double.class ); }
+        if( doublePrimitiveIndex == -1 && doubleBoxedIndex >= 0 ) { allTypes.add( double.class ); }
+        return allTypes;
+    }
+
+    public Class<?> primaryType()
+    {
+        return types.stream().findFirst().orElse( null );
+    }
+
+    @Override
+    public Stream<Class<?>> types()
+    {
+        return types.stream();
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o ) { return true; }
+        if( o == null || getClass() != o.getClass() ) { return false; }
+        ValueType valueType = (ValueType) o;
+        return Objects.equals( types, valueType.types );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return Objects.hash( types );
+    }
+
+    @Override
+    public String toString()
+    {
+        String name = types.stream().map( Class::getName ).collect( joining( "," ) );
+        if( name.contains( "," ) )
+        {
+            name = '{' + name + '}';
+        }
+        return name;
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/package.html b/core/api/src/main/java/org/apache/polygene/api/type/package.html
new file mode 100644
index 0000000..c0c3eca
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Type API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/ConcurrentEntityModificationException.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/ConcurrentEntityModificationException.java
new file mode 100644
index 0000000..7d439b0
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/ConcurrentEntityModificationException.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.api.unitofwork;
+
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.type.HasTypes;
+import org.apache.polygene.api.usecase.Usecase;
+
+/**
+ * This exception is thrown by UnitOfWork.complete() if any entities that are being committed
+ * had been changed while the UnitOfWork was being executed.
+ */
+public class ConcurrentEntityModificationException
+    extends UnitOfWorkCompletionException
+{
+    private static final long serialVersionUID = 3872723845064767689L;
+
+    private final Map<EntityComposite, HasTypes> concurrentlyModifiedEntities;
+
+    public ConcurrentEntityModificationException( Map<EntityComposite, HasTypes> concurrentlyModifiedEntities,
+                                                  Usecase usecase
+    )
+    {
+        super( "Entities changed concurrently, and detected in usecase '" + usecase + "'\nModified entities : " + format( concurrentlyModifiedEntities ) );
+        this.concurrentlyModifiedEntities = concurrentlyModifiedEntities;
+    }
+
+    private static String format( Map<EntityComposite, HasTypes> concurrentlyModifiedEntities )
+    {
+        return concurrentlyModifiedEntities.entrySet().stream()
+            .map( entry ->
+                      entry.getKey()
+                      + " : "
+                      + entry.getValue().types().map( Class::getSimpleName )
+                          .collect( Collectors.joining( "," ) )
+            )
+            .collect( Collectors.joining( "\n" ) );
+    }
+
+    public Map<EntityComposite, HasTypes> concurrentlyModifiedEntities()
+    {
+        return concurrentlyModifiedEntities;
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/EntityCompositeAlreadyExistsException.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/EntityCompositeAlreadyExistsException.java
new file mode 100644
index 0000000..dec6965
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/EntityCompositeAlreadyExistsException.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.api.unitofwork;
+
+import org.apache.polygene.api.entity.EntityReference;
+
+/**
+ * If you try to create an EntityComposite whose reference already exists,
+ * then this exception will be thrown.
+ */
+public class EntityCompositeAlreadyExistsException
+    extends UnitOfWorkException
+{
+    private static final long serialVersionUID = -7297710939536508481L;
+
+    private final EntityReference reference;
+
+    public EntityCompositeAlreadyExistsException( EntityReference reference)
+    {
+        super( "EntityComposite (" + reference + ") already exists." );
+        this.reference = reference;
+    }
+
+    public EntityReference reference()
+    {
+        return reference;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/NoSuchEntityException.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/NoSuchEntityException.java
new file mode 100644
index 0000000..7b31427
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/NoSuchEntityException.java
@@ -0,0 +1,80 @@
+/*
+ *  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.polygene.api.unitofwork;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.usecase.Usecase;
+
+import static java.util.Arrays.stream;
+
+/**
+ * This exception indicates that the requested Entity with the given
+ * reference does not exist.
+ */
+public class NoSuchEntityException
+    extends UnitOfWorkException
+{
+    private final EntityReference reference;
+    private final Usecase usecase;
+    private final Class<?>[] mixinTypes;
+
+    public NoSuchEntityException(EntityReference reference, Class<?> mixinType, Usecase usecase )
+    {
+        super( "Could not find entity (" + reference + ") of type " + mixinType.getName() + " in usecase '" + usecase.name() + "'" );
+        this.reference = reference;
+        this.usecase = usecase;
+        this.mixinTypes = new Class<?>[]{ mixinType };
+    }
+
+    public NoSuchEntityException(EntityReference reference, Class<?>[] mixinTypes, Usecase usecase )
+    {
+        super( "Could not find entity (" + reference + ") of type " + toString( mixinTypes ) + " in usecase '" + usecase.name() + "'" );
+        this.reference = reference;
+        this.mixinTypes = mixinTypes;
+        this.usecase = usecase;
+    }
+
+    public NoSuchEntityException(EntityReference reference, Stream<Class<?>> types, Usecase usecase )
+    {
+        this(reference, types.toArray( Class[]::new ), usecase );
+    }
+
+    public EntityReference reference()
+    {
+        return reference;
+    }
+
+    public Class<?>[] mixinTypes()
+    {
+        return mixinTypes;
+    }
+
+    public Usecase usecase()
+    {
+        return usecase;
+    }
+
+    private static String toString( Class<?>[] mixinTypes )
+    {
+        String reduced = stream( mixinTypes ).map( Class::getName ).reduce( "", ( ret, name ) -> ret + "," + name );
+        return "[" + reduced.substring( 1 ) + "]";
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/NoSuchEntityTypeException.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/NoSuchEntityTypeException.java
new file mode 100644
index 0000000..bd038f2
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/NoSuchEntityTypeException.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.api.unitofwork;
+
+import java.util.stream.Collectors;
+import org.apache.polygene.api.composite.NoSuchCompositeException;
+import org.apache.polygene.api.structure.TypeLookup;
+
+/**
+ * Polygene exception to be thrown in case that an entity composite
+ * was not found during a lookup call.
+ */
+public class NoSuchEntityTypeException
+    extends NoSuchCompositeException
+{
+    public NoSuchEntityTypeException( String typeName, String moduleName, TypeLookup typeLookup )
+    {
+        super( "EntityComposite", typeName, moduleName, formatVisibleTypes( typeLookup ) );
+    }
+
+    private static String formatVisibleTypes( TypeLookup typeLookup )
+    {
+        return typeLookup.allEntities()
+            .map( descriptor -> descriptor.primaryType().getName() )
+            .collect( Collectors.joining( "\n", "Visible entity types are:\n", "" ) );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/ToEntityConverter.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/ToEntityConverter.java
new file mode 100644
index 0000000..22096d6
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/ToEntityConverter.java
@@ -0,0 +1,105 @@
+/*
+ *  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.polygene.api.unitofwork;
+
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.usecase.Usecase;
+
+/**
+ * MetaInfo holder for value-to-entity conversion in {@link UnitOfWork#toEntity(Class, HasIdentity)}.
+ * <p>
+ * The implementation of this interface should be registered as metaInfo on the {@link Usecase}
+ * of the {@link UnitOfWork} where the conversion should take place. It is also possible to register
+ * the implementation to the {@link UnitOfWork}'s metaInfo.
+ * </p>
+ * <p>Example;</p>
+ * <pre><code>
+ *     private static final Usecase USECASE_GET_USER_DETAILS = UseCaseBuilder
+ *                                                                 .buildUseCase("get user details")
+ *                                                                 .withMetaInfo( new UserToEntityConverter() )
+ *                                                                 .newUsecase();
+ *
+ *     &#64;Structure
+ *     private UnitOfWorkFactory uowf;
+ *     :
+ *     :
+ *     try( UnitOfWork uow = uowf.newUnitOfWork( USECASE_GET_USER_DETAILS ) )
+ *     {
+ *         :
+ *         User value = ...;
+ *         User entity = uow.toEntity( User.class, value );
+ *         :
+ *     }
+ *     :
+ *     :
+ * </code></pre>
+ */
+public interface ToEntityConverter
+{
+    /**
+     * Returns the Function to convert each of the properties of the entities into the value.
+     *
+     * @param entityComposite the entity that is to be converted.
+     * @param defaultFn       The default converter function. This can be used to delegate non-special cases, or simply
+     *                        return to do all the conversions
+     * @return The function to do the conversion. It MUST NOT return null, and if no conversion is wanted, return the defaultFn.
+     */
+    Function<PropertyDescriptor, Object> properties( Object entityComposite,
+                                                     Function<PropertyDescriptor, Object> defaultFn );
+
+    /**
+     * Returns the Function to convert each of the associations of the entities into the value.
+     *
+     * @param entityComposite the entity that is to be converted.
+     * @param defaultFn       The default converter function. This can be used to delegate non-special cases, or simply
+     *                        return to do all the conversions
+     * @return The function to do the conversion. It MUST NOT return null, and if no conversion is wanted, return the defaultFn.
+     */
+    Function<AssociationDescriptor, EntityReference> associations( Object entityComposite,
+                                                                   Function<AssociationDescriptor, EntityReference> defaultFn );
+
+    /**
+     * Returns the Function to convert each of the manyAssociations of the entities into the value.
+     *
+     * @param entityComposite the entity that is to be converted.
+     * @param defaultFn       The default converter function. This can be used to delegate non-special cases, or simply
+     *                        return to do all the conversions
+     * @return The function to do the conversion. It MUST NOT return null, and if no conversion is wanted, return the defaultFn.
+     */
+    Function<AssociationDescriptor, Stream<EntityReference>> manyAssociations( Object entityComposite,
+                                                                               Function<AssociationDescriptor, Stream<EntityReference>> defaultFn );
+
+    /**
+     * Returns the Function to convert each of the NamedAssociations of the entities into the value.
+     *
+     * @param entityComposite the entity that is to be converted.
+     * @param defaultFn       The default converter function. This can be used to delegate non-special cases, or simply
+     *                        return to do all the conversions
+     * @return The function to do the conversion. It MUST NOT return null, and if no conversion is wanted, return the defaultFn.
+     */
+    Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociations( Object entityComposite,
+                                                                                                   Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> defaultFn );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/ToValueConverter.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/ToValueConverter.java
new file mode 100644
index 0000000..4afeda7
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/ToValueConverter.java
@@ -0,0 +1,102 @@
+/*
+ *  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.polygene.api.unitofwork;
+
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.usecase.Usecase;
+
+/**
+ * MetaInfo holder for entity-to-value conversion in {@link UnitOfWork#toValue(Class, HasIdentity)}
+ * <p>
+ * The implementation of this interface should be registered as metaInfo on the {@link Usecase}
+ * of the {@link UnitOfWork} where the conversion should take place.
+ * </p>
+ * <pre><code>
+ *     private static final Usecase USECASE_GET_USER_DETAILS = UseCaseBuilder
+ *                                                                 .buildUseCase("get user details")
+ *                                                                 .withMetaInfo( new MyToValueConverter() )
+ *                                                                 .newUsecase();
+ *     &#64;Structure
+ *     private UnitOfWorkFactory uowf;
+ *     :
+ *     :
+ *     try( UnitOfWork uow = uowf.newUnitOfWork( USECASE_GET_USER_DETAILS ) )
+ *     {
+ *         :
+ *         User entity = ...;
+ *         User value = uow.toValue( User.class, value );
+ *         :
+ *     }
+ *     :
+ *     :
+ * </code></pre>
+ */
+public interface ToValueConverter
+{
+    /**
+     * Returns the Function to convert each of the properties of the entities into the value.
+     *
+     * @param entityComposite the entity that is to be converted.
+     * @param defaultFn       The default converter function. This can be used to delegate non-special cases, or simply
+     *                        return to do all the conversions
+     * @return The function to do the conversion. It MUST NOT return null, and if no conversion is wanted, return the defaultFn.
+     */
+    Function<PropertyDescriptor, Object> properties( Object entityComposite,
+                                                     Function<PropertyDescriptor, Object> defaultFn );
+
+    /**
+     * Returns the Function to convert each of the associations of the entities into the value.
+     *
+     * @param entityComposite the entity that is to be converted.
+     * @param defaultFn       The default converter function. This can be used to delegate non-special cases, or simply
+     *                        return to do all the conversions
+     * @return The function to do the conversion. It MUST NOT return null, and if no conversion is wanted, return the defaultFn.
+     */
+    Function<AssociationDescriptor, EntityReference> associations( Object entityComposite,
+                                                                   Function<AssociationDescriptor, EntityReference> defaultFn );
+
+    /**
+     * Returns the Function to convert each of the manyAssociations of the entities into the value.
+     *
+     * @param entityComposite the entity that is to be converted.
+     * @param defaultFn       The default converter function. This can be used to delegate non-special cases, or simply
+     *                        return to do all the conversions
+     * @return The function to do the conversion. It MUST NOT return null, and if no conversion is wanted, return the defaultFn.
+     */
+    Function<AssociationDescriptor, Stream<EntityReference>> manyAssociations( Object entityComposite,
+                                                                               Function<AssociationDescriptor, Stream<EntityReference>> defaultFn );
+
+    /**
+     * Returns the Function to convert each of the NamedAssociations of the entities into the value.
+     *
+     * @param entityComposite the entity that is to be converted.
+     * @param defaultFn       The default converter function. This can be used to delegate non-special cases, or simply
+     *                        return to do all the conversions
+     * @return The function to do the conversion. It MUST NOT return null, and if no conversion is wanted, return the defaultFn.
+     */
+    Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociations( Object entityComposite,
+                                                                                                   Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> defaultFn );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWork.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWork.java
new file mode 100644
index 0000000..badbe4c
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWork.java
@@ -0,0 +1,528 @@
+/*
+ *  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.polygene.api.unitofwork;
+
+import java.time.Instant;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.AmbiguousTypeException;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.entity.LifecycleException;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.structure.MetaInfoHolder;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.api.value.ValueBuilder;
+
+/**
+ * All operations on entities goes through an UnitOfWork.
+ * <p>
+ * A UnitOfWork allows you to access
+ * Entities and work with them. All modifications to Entities are recorded by the UnitOfWork,
+ * and at the end they may be sent to the underlying EntityStore by calling complete(). If the
+ * UoW was read-only you may instead simply discard() it.
+ * </p>
+ * <p>
+ * A UoW differs from a traditional Transaction in the sense that it is not tied at all to the underlying
+ * storage resource. Because of this there is no timeout on a UoW. It can be very short or very long.
+ * Another difference is that if a call to complete() fails, and the cause is validation errors in the
+ * Entities of the UoW, then these can be corrected and the UoW retried. By contrast, when a Transaction
+ * commit fails, then the whole transaction has to be done from the beginning again.
+ * </p>
+ * <p>
+ * A UoW can be associated with a Usecase. A Usecase describes the metainformation about the process
+ * to be performed by the UoW.
+ * </p>
+ * <p>
+ * If a code block that uses a UoW throws an exception you need to ensure that this is handled properly,
+ * and that the UoW is closed before returning. Because discard() is a no-op if the UoW is closed, we therefore
+ * recommend the following template to be used:
+ * </p>
+ * <pre>
+ *     UnitOfWork uow = module.newUnitOfWork();
+ *     try
+ *     {
+ *         ...
+ *         uow.complete();
+ *     }
+ *     finally
+ *     {
+ *         uow.discard();
+ *     }
+ * </pre>
+ * <p>
+ * This ensures that in the happy case the UoW is completed, and if any exception is thrown the UoW is discarded. After
+ * the UoW has completed the discard() method doesn't do anything, and so has no effect. You can choose to either add
+ * catch blocks for any exceptions, including exceptions from complete(), or skip them.
+ * </p>
+ * <p>
+ * Since 2.1 you can leverage Java 7 Automatic Resource Management (ie. Try With Resources) and use the following
+ * template instead:
+ * </p>
+ * <pre>
+ *     try( UnitOfWork uow = module.newUnitOfWork() )
+ *     {
+ *         ...
+ *         uow.complete();
+ *     }
+ * </pre>
+ * <p>
+ * It has the very same effect as the template above but is shorter.</p>
+ */
+public interface UnitOfWork extends MetaInfoHolder, AutoCloseable
+{
+
+    /**
+     * Get the UnitOfWorkFactory that this UnitOfWork was created from.
+     *
+     * @return The UnitOfWorkFactory instance that was used to create this UnitOfWork.
+     */
+    UnitOfWorkFactory unitOfWorkFactory();
+
+    /**
+     * Current Time is a relative concept in systems capable of event sourcing and other
+     * history-capable systems. Current time is always expected to be read from here, and
+     * history-capable systems will set the current time for each {@link UnitOfWorkFactory#newUnitOfWork(Instant)}
+     *
+     * @return the current time, either actual real time or historical time being part of some playback.
+     */
+    Instant currentTime();
+
+    /**
+     * Get the Usecase for this UnitOfWork
+     *
+     * @return the Usecase
+     */
+    Usecase usecase();
+
+    /**
+     * Sets an arbitrary metaInfo object on this {@code UnitOfWork} which can be used for application-specific
+     * information.
+     * <p>
+     * The metaInfo object is retrieved by the {@link UnitOfWork#metaInfo(Class)} method on the same UnitOfWork
+     * instance.
+     * </p>
+     *
+     * @param metaInfo The metaInfo object that can be retrieved with {@link UnitOfWork#metaInfo(Class)}.
+     */
+    void setMetaInfo( Object metaInfo );
+
+    /**
+     * Creates a {@link Query} from the given {@link QueryBuilder} on this {@code UnitOfWork}.
+     *
+     * @param queryBuilder The QueryBuilder holding the query specification/expression
+     * @param <T>          The resulting type of the query.
+     * @return A Query against this {@code UnitOfWork}
+     */
+    <T> Query<T> newQuery( QueryBuilder<T> queryBuilder );
+
+    /**
+     * Create a new Entity which implements the given mixin type.
+     * <p>
+     * An EntityComposite
+     * will be chosen according to what has been registered and the visibility rules
+     * for Modules and Layers will be considered. If several
+     * EntityComposites implement the type then an AmbiguousTypeException will be thrown.
+     * </p>
+     * <p>
+     * The reference of the Entity will be generated by the IdentityGenerator of the Module of the EntityComposite.
+     * </p>
+     *
+     * @param <T>  Entity type
+     * @param type the mixin type that the EntityComposite must implement
+     * @return a new Entity
+     * @throws NoSuchEntityTypeException if no EntityComposite type of the given mixin type has been registered
+     * @throws AmbiguousTypeException    If several mixins implement the given type
+     * @throws LifecycleException        if the entity cannot be created
+     */
+    <T> T newEntity( Class<T> type )
+        throws NoSuchEntityTypeException, AmbiguousTypeException, LifecycleException;
+
+    /**
+     * Create a new Entity which implements the given mixin type. An EntityComposite
+     * will be chosen according to what has been registered and the visibility rules
+     * for Modules and Layers will be considered. If several
+     * EntityComposites implement the type then an AmbiguousTypeException will be thrown.
+     *
+     * @param <T>      Entity type
+     * @param type     the mixin type that the EntityComposite must implement
+     * @param identity the reference of the new Entity
+     * @return a new Entity
+     * @throws NoSuchEntityTypeException if no EntityComposite type of the given mixin type has been registered
+     * @throws AmbiguousTypeException    If several mixins implement the given type
+     * @throws LifecycleException        if the entity cannot be created
+     */
+    <T> T newEntity( Class<T> type, @Optional Identity identity )
+        throws NoSuchEntityTypeException, AmbiguousTypeException, LifecycleException;
+
+    /**
+     * Create a new EntityBuilder for an EntityComposite which implements the given mixin type. An EntityComposite
+     * will be chosen according to what has been registered and the visibility rules
+     * for Modules and Layers will be considered. If several
+     * EntityComposites implement the type then an AmbiguousTypeException will be thrown.
+     *
+     * @param <T>  Entity type
+     * @param type the mixin type that the EntityComposite must implement
+     * @return a new EntityBuilder
+     * @throws NoSuchEntityTypeException if no EntityComposite type of the given mixin type has been registered
+     * @throws AmbiguousTypeException    If several mixins implement the given type
+     */
+    <T> EntityBuilder<T> newEntityBuilder( Class<T> type )
+        throws NoSuchEntityTypeException, AmbiguousTypeException;
+
+    /**
+     * Create a new EntityBuilder for an EntityComposite which implements the given mixin type. An EntityComposite
+     * will be chosen according to what has been registered and the visibility rules
+     * for Modules and Layers will be considered. If several
+     * mixins implement the type then an AmbiguousTypeException will be thrown.
+     *
+     * @param <T>      Entity type
+     * @param type     the mixin type that the EntityComposite must implement
+     * @param identity the reference of the new Entity
+     * @return a new EntityBuilder
+     * @throws NoSuchEntityTypeException if no EntityComposite type of the given mixin type has been registered
+     * @throws AmbiguousTypeException    If several mixins implement the given type
+     */
+    <T> EntityBuilder<T> newEntityBuilder( Class<T> type, @Optional Identity identity )
+        throws NoSuchEntityTypeException, AmbiguousTypeException;
+
+    /**
+     * Create a new EntityBuilder for an EntityComposite wich implements the given mixin type starting with the given
+     * state.
+     * <p>
+     * An EntityComposite will be chosen according to what has been registered and the visibility rules for Modules and
+     * Layers will be considered.
+     *
+     * @param <T>                      Entity type
+     * @param type                     Entity type
+     * @param propertyFunction         a function providing the state of properties
+     * @param associationFunction      a function providing the state of associations
+     * @param manyAssociationFunction  a function providing the state of many associations
+     * @param namedAssociationFunction a function providing the state of named associations
+     * @return a new EntityBuilder starting with the given state
+     * @throws NoSuchEntityTypeException if no EntityComposite type of the given mixin type has been registered
+     * @throws AmbiguousTypeException    If several mixins implement the given type
+     */
+    <T> EntityBuilder<T> newEntityBuilderWithState( Class<T> type,
+                                                    Function<PropertyDescriptor, Object> propertyFunction,
+                                                    Function<AssociationDescriptor, EntityReference> associationFunction,
+                                                    Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction,
+                                                    Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction
+                                                  )
+        throws NoSuchEntityTypeException, AmbiguousTypeException;
+
+    /**
+     * Create a new EntityBuilder for an EntityComposite wich implements the given mixin type starting with the given
+     * state.
+     * <p>
+     * An EntityComposite will be chosen according to what has been registered and the visibility rules for Modules and
+     * Layers will be considered.
+     *
+     * @param <T>                      Entity type
+     * @param type                     Entity type
+     * @param identity                 the reference of the new Entity
+     * @param propertyFunction         a function providing the state of properties
+     * @param associationFunction      a function providing the state of associations
+     * @param manyAssociationFunction  a function providing the state of many associations
+     * @param namedAssociationFunction a function providing the state of named associations
+     * @return a new EntityBuilder starting with the given state
+     * @throws NoSuchEntityTypeException If no mixins implements the given type
+     * @throws AmbiguousTypeException    If several mixins implement the given type
+     */
+    <T> EntityBuilder<T> newEntityBuilderWithState( Class<T> type, @Optional Identity identity,
+                                                    Function<PropertyDescriptor, Object> propertyFunction,
+                                                    Function<AssociationDescriptor, EntityReference> associationFunction,
+                                                    Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction,
+                                                    Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction
+                                                  )
+        throws NoSuchEntityTypeException, AmbiguousTypeException;
+
+    /**
+     * Find an Entity of the given mixin type with the give reference. This
+     * method verifies that it exists by asking the underlying EntityStore.
+     *
+     * @param <T>      Entity type
+     * @param type     of the entity
+     * @param identity of the entity
+     * @return the entity
+     * @throws NoSuchEntityTypeException if no entity type could be found
+     * @throws NoSuchEntityException     if the entity could not be found
+     */
+    <T> T get( Class<T> type, Identity identity )
+        throws NoSuchEntityTypeException, NoSuchEntityException;
+
+    /**
+     * If you have a reference to an Entity from another
+     * UnitOfWork and want to create a reference to it in this
+     * UnitOfWork, then call this method.
+     *
+     * @param <T>    Entity type
+     * @param entity the Entity to be dereferenced
+     * @return an Entity from this UnitOfWork
+     * @throws NoSuchEntityTypeException if no entity type could be found
+     */
+    <T> T get( T entity )
+        throws NoSuchEntityTypeException;
+
+    /**
+     * Remove the given Entity.
+     *
+     * @param entity the Entity to be removed.
+     * @throws LifecycleException if the entity could not be removed
+     */
+    void remove( Object entity )
+        throws LifecycleException;
+
+    /**
+     * Complete this UnitOfWork. This will send all the changes down to the underlying
+     * EntityStore's.
+     *
+     * @throws UnitOfWorkCompletionException         if the UnitOfWork could not be completed
+     * @throws ConcurrentEntityModificationException if entities have been modified by others
+     */
+    void complete()
+        throws UnitOfWorkCompletionException, ConcurrentEntityModificationException;
+
+    /**
+     * Discard this UnitOfWork. Use this if a failure occurs that you cannot handle,
+     * or if the usecase was of a read-only character. This is a no-op of the UnitOfWork
+     * is already closed.
+     */
+    void discard();
+
+    /**
+     * Discard this UnitOfWork. Use this if a failure occurs that you cannot handle,
+     * or if the usecase was of a read-only character. This is a no-op of the UnitOfWork
+     * is already closed. This simply call the {@link #discard()} method and is an
+     * implementation of the {@link AutoCloseable} interface providing Try With Resources
+     * support for UnitOfWork.
+     */
+    @Override
+    void close();
+
+    /**
+     * Check if the UnitOfWork is open. It is closed after either complete() or discard()
+     * methods have been called successfully.
+     *
+     * @return true if the UnitOfWork is open.
+     */
+    boolean isOpen();
+
+    /**
+     * Check if the UnitOfWork is paused. It is not paused after it has been create through the
+     * UnitOfWorkFactory, and it can be paused by calling {@link #pause()} and then resumed by calling
+     * {@link #resume()}.
+     *
+     * @return true if this UnitOfWork has been paused.
+     */
+    boolean isPaused();
+
+    /**
+     * Pauses this UnitOfWork.
+     * <p>
+     * Calling this method will cause the underlying UnitOfWork to become the current UnitOfWork until the
+     * the resume() method is called. It is the client's responsibility not to drop the reference to this
+     * UnitOfWork while being paused.
+     * </p>
+     */
+    void pause();
+
+    /**
+     * Resumes this UnitOfWork to again become the current UnitOfWork.
+     */
+    void resume();
+
+    /**
+     * Register a callback. Callbacks are invoked when the UnitOfWork
+     * is completed or discarded.
+     *
+     * @param callback a callback to be registered with this UnitOfWork
+     */
+    void addUnitOfWorkCallback( UnitOfWorkCallback callback );
+
+    /**
+     * Unregister a callback. Callbacks are invoked when the UnitOfWork
+     * is completed or discarded.
+     *
+     * @param callback a callback to be unregistered with this UnitOfWork
+     */
+    void removeUnitOfWorkCallback( UnitOfWorkCallback callback );
+
+    /**
+     * Converts the provided Entity to a Value of the same type.
+     * This is a convenience method to convert an EntityComposite to a ValueComposite.
+     * <p>
+     * All Property values are transferred across as-is, and the Association, ManyAssociation
+     * and NamedAssociatino values are kept in the ValueComposite as EntityReferences
+     * until they are dereferenced (get() and other methods), and IF a UnitOfWork is
+     * present at dereferencing the corresponding EntityCompoiste is retrieved from the
+     * EntityStore. If there is not an UnitOfWork present, an exception is thrown.
+     * </p>
+     * <p>
+     * For this to work, the Composites (both Entity and Value) must not declare the
+     * EntityComposite and ValueComposite super types, but rely on the declaration in
+     * the assembly, and also extend the Identity supertype.
+     * </p>
+     * Example;
+     * <pre><code>
+     *     public interface Person extends Identity { ... };
+     *     public class MyAssembler
+     *     {
+     *         public void assemble( ModuleAssembly module )
+     *         {
+     *             module.values( Person.class );
+     *             module.entities( Person.class );
+     *         }
+     *     }
+     * </code></pre>
+     *
+     * @param <T>             The generic shared type
+     * @param primaryType     The shared type for which the properties and associations will
+     *                        be converted. Properties outside this type will be ignored.
+     * @param entityComposite The entity to be convered.
+     * @return The Value
+     */
+    <T extends HasIdentity> T toValue( Class<T> primaryType, T entityComposite );
+
+    /**
+     * Converts all the entities referenced in the ManyAssociation into a List of values of the same type.
+     * <p>
+     * All the referenced entities inside the association will be fetched from the underlying entity store,
+     * which is potentially very expensive operation. Each of the fetched entities will be passed to
+     * {@link #toValue(Class, HasIdentity)}, and its associations will NOT be converted into values, but remain
+     * {@link EntityReference} values. Hence there is no problem with circular references.
+     * </p>
+     * <p>
+     * For this to work, the type &lt;T&gt; must be registered at bootstrap as both an Entity and a Value, and
+     * as seen in the method signature, also be sub-type of {@link HasIdentity}.
+     * </p>
+     *
+     * @param association The association of entities to be converted into values.
+     * @param <T>         The primary type of the association.
+     * @return A List of ValueComposites that has been converted from EntityComposites referenced by the Associations.
+     * @see #toValue(Class, HasIdentity)
+     */
+    <T extends HasIdentity> List<T> toValueList( ManyAssociation<T> association );
+
+    /**
+     * Converts all the entities referenced in the ManyAssociation into a Set of values of the same type.
+     * <p>
+     * All the referenced entities inside the association will be fetched from the underlying entity store,
+     * which is potentially very expensive operation. However, any duplicate EntityReferences in the association
+     * will be dropped before the fetch occurs. Each of the fetched entities will be passed to
+     * {@link #toValue(Class, HasIdentity)}, and its associations will NOT be converted into values, but remain
+     * {@link EntityReference} values. Hence there is no problem with circular references.
+     * </p>
+     * <p>
+     * For this to work, the type &lt;T&gt; must be registered at bootstrap as both an Entity and a Value, and
+     * as seen in the method signature, also be sub-type of {@link HasIdentity}.
+     * </p>
+     *
+     * @param association The association of entities to be converted into values.
+     * @param <T>         The primary type of the association.
+     * @return A List of ValueComposites that has been converted from EntityComposites referenced by the Associations.
+     * @see #toValue(Class, HasIdentity)
+     */
+    <T extends HasIdentity> Set<T> toValueSet( ManyAssociation<T> association );
+
+    /**
+     * Converts the {@link NamedAssociation} into a Map with a String key and a ValueComposite as the value.
+     * <p>
+     * A {@link NamedAssociation} is effectively a Map with a String key and an EntityReference as the value. The
+     * EntityReference is fetched from the entity store and converted into a value of the same type.Each of the fetched
+     * entities will be passed to {@link #toValue(Class, HasIdentity)}, and its associations will NOT be converted into
+     * values, but remain {@link EntityReference} values. Hence there is no problem with circular references.
+     * </p>
+     * <p>
+     * For this to work, the type &lt;T&gt; must be registered at bootstrap as both an Entity and a Value, and
+     * as seen in the method signature, also be sub-type of {@link HasIdentity}.
+     * </p>
+     *
+     * @param association The association of entities to be converted into values.
+     * @param <T>         The primary type of the association.
+     * @return A List of ValueComposites that has been converted from EntityComposites referenced by the Associations.
+     * @see #toValue(Class, HasIdentity)
+     */
+    <T extends HasIdentity> Map<String, T> toValueMap( NamedAssociation<T> association );
+
+    /**
+     * Converts the provided Value to an Entity of the same type.
+     * This is a convenience method to convert a ValueComposite to an EntityComposite.
+     * <p>
+     * All Property values are transferred across as-is (no deep copy in case mutable
+     * types (DISCOURAGED!) are used), and the Association, ManyAssociation
+     * and NamedAssociatino that were in the ValueComposite as EntityReferences are
+     * transferred into the EntityComposite correctly, and can be dereferenced.
+     * </p>
+     * <p>
+     * This method MUST be called within a UnitOfWork.
+     * </p>
+     * <p>
+     * If an Entity with the Identity in the ValueComposite already exists, then that
+     * Entity is updated with the values from the ValueComposite. If an Entity of
+     * that Identity doesn't exist a new one is created.
+     * </p>
+     * <p>
+     * For this to work, the Composites (both Entity and Value) must not declare the
+     * EntityComposite and ValueComposite super types, but rely on the declaration in
+     * the assembly, and also extend the Identity supertype.
+     * </p>
+     * Example;
+     * <pre><code>
+     *     public interface Person extends Identity { ... };
+     *     public class MyAssembler
+     *     {
+     *         public void assemble( ModuleAssembly module )
+     *         {
+     *             module.values( Person.class );
+     *             module.entities( Person.class );
+     *         }
+     *     }
+     * </code></pre>
+     *
+     * @param <T>            The generic shared type
+     * @param primaryType    The shared type for which the properties and associations will
+     *                       be converted. Properties outside this type will be ignored.
+     * @param valueComposite The Value to be convered into an Entity.
+     * @return The new or updated Entity
+     */
+    <T extends HasIdentity> T toEntity( Class<T> primaryType, T valueComposite );
+
+    /**
+     * The Module of the UnitOfWork is defined as the Module the UnitOfWorkFactory belonged to from where the
+     * UnitOfWork was created.
+     *
+     * @return the Module where this UnitOfWork was initialized.
+     */
+    ModuleDescriptor module();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkCallback.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkCallback.java
new file mode 100644
index 0000000..b52ddce
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkCallback.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.api.unitofwork;
+
+/**
+ * Callback interface for UnitOfWork completion or discard. Implementations
+ * of this interface can be registered through {@link UnitOfWork#addUnitOfWorkCallback(UnitOfWorkCallback)}.
+ *
+ * If Entities implement this interface they will also receive invocations of this callback interface.
+ */
+public interface UnitOfWorkCallback
+{
+    /**
+     * This is called before the completion of the UnitOfWork.
+     * The callback may do any validation checks.
+     *
+     * @throws UnitOfWorkCompletionException if there is any reason why the UnitOfWork is not in a valid state to be
+     *                                       completed
+     */
+    void beforeCompletion()
+        throws UnitOfWorkCompletionException;
+
+    /**
+     * This is called after the completion or discarding
+     * of the UnitOfWork. The callback may do any cleanup
+     * necessary related to the UnitOfWork. Note that the
+     * UnitOfWork is no longer active when this method is
+     * called, so no methods on it may be invoked.
+     *
+     * @param status the UnitOfWork status
+     */
+    void afterCompletion( UnitOfWorkStatus status );
+
+    enum UnitOfWorkStatus
+    {
+        COMPLETED, DISCARDED
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkCompletionException.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkCompletionException.java
new file mode 100644
index 0000000..0fd8335
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkCompletionException.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.api.unitofwork;
+
+/**
+ * When an attempt to {@link UnitOfWork#complete()} an UnitOfWork
+ * fails, this exception will be thrown.
+ */
+public class UnitOfWorkCompletionException
+    extends RuntimeException
+{
+    private static final long serialVersionUID = 6531642131384516904L;
+
+    public UnitOfWorkCompletionException()
+    {
+    }
+
+    public UnitOfWorkCompletionException( String string )
+    {
+        super( string );
+    }
+
+    public UnitOfWorkCompletionException( String string, Throwable throwable )
+    {
+        super( string, throwable );
+    }
+
+    public UnitOfWorkCompletionException( Throwable throwable )
+    {
+        super( throwable );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkException.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkException.java
new file mode 100644
index 0000000..fdf6903
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkException.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.api.unitofwork;
+
+/**
+ * Base Exception for UnitOfWork related concerns.
+ */
+public class UnitOfWorkException
+    extends RuntimeException
+{
+    private static final long serialVersionUID = -8544178439804058558L;
+
+    public UnitOfWorkException()
+    {
+    }
+
+    public UnitOfWorkException( String message )
+    {
+        super( message );
+    }
+
+    public UnitOfWorkException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+
+    public UnitOfWorkException( Throwable cause )
+    {
+        super( cause );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkFactory.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkFactory.java
new file mode 100644
index 0000000..c59e154
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkFactory.java
@@ -0,0 +1,102 @@
+/*
+ *  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.polygene.api.unitofwork;
+
+import java.time.Instant;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.time.SystemTime;
+import org.apache.polygene.api.usecase.Usecase;
+
+/**
+ * Factory for UnitOfWork.
+ */
+public interface UnitOfWorkFactory
+{
+    /**
+     * Create a new UnitOfWork and associate it with the current thread.
+     * <p>
+     * The UnitOfWork will use the default Usecase settings.
+     * </p>
+     * <p>
+     * Current time will be set to {@link SystemTime#now()}
+     * </p>
+     * @return a new UnitOfWork
+     */
+    UnitOfWork newUnitOfWork();
+
+    /**
+     * Create a new UnitOfWork and associate it with the current thread.
+     * <p>
+     * The UnitOfWork will use the default Usecase settings.
+     * </p>
+     *
+     * @param currentTime the current time for this UnitOfWork
+     *
+     * @return a new UnitOfWork
+     */
+    UnitOfWork newUnitOfWork( Instant currentTime );
+
+    /**
+     * Create a new UnitOfWork for the given Usecase and associate it with the current thread.
+     * <p>
+     * Current time will be set to {@link SystemTime#now()}
+     * </p>
+     * @param usecase the Usecase for this UnitOfWork
+     *
+     * @return a new UnitOfWork
+     */
+    UnitOfWork newUnitOfWork( Usecase usecase );
+
+    /**
+     * Create a new UnitOfWork for the given Usecase and associate it with the current thread.
+     *
+     * @param usecase the Usecase for this UnitOfWork
+     * @param currentTime the current time for this UnitOfWork
+     *
+     *
+     * @return a new UnitOfWork
+     */
+    UnitOfWork newUnitOfWork( Usecase usecase, Instant currentTime );
+
+    /**
+     * @return true if there is an active UnitOfWork associated with the executing thread
+     */
+    boolean isUnitOfWorkActive();
+
+    /**
+     * Returns the UnitOfWork that is currently associated with the executing thread.
+     *
+     * @return The current UnitOfWork associated with the executing thread
+     *
+     * @throws IllegalStateException if no current UnitOfWork is active
+     */
+    UnitOfWork currentUnitOfWork()
+        throws IllegalStateException;
+
+    /**
+     * Returns the UnitOfWork that the EntityComposite is bound to.
+     *
+     * @param entity the entity to be checked.
+     *
+     * @return The UnitOfWork instance that the Entity is bound to, or null if the entity is not associated with
+     *         any UnitOfWork.
+     */
+    UnitOfWork getUnitOfWork( EntityComposite entity );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkOptions.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkOptions.java
new file mode 100644
index 0000000..02c6d5a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkOptions.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.api.unitofwork;
+
+/**
+ * Set instances of this in MetaInfo on UnitOfWork or the associated Usecase.
+ *  <p>
+ * Options:
+ *  </p>
+ * <p>
+ * "pruneOnPause": if true, then clear out all instances that have been loaded in the UoW but not modified
+ * </p>
+ */
+public class UnitOfWorkOptions
+{
+    private boolean pruneOnPause = false;
+
+    public UnitOfWorkOptions( boolean pruneOnPause )
+    {
+        this.pruneOnPause = pruneOnPause;
+    }
+
+    public boolean isPruneOnPause()
+    {
+        return pruneOnPause;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkTemplate.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkTemplate.java
new file mode 100644
index 0000000..1c821c3
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkTemplate.java
@@ -0,0 +1,94 @@
+/*
+ *  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.polygene.api.unitofwork;
+
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.usecase.Usecase;
+
+/**
+ * UnitOfWork Template.
+ */
+public abstract class UnitOfWorkTemplate<RESULT, ThrowableType extends Throwable>
+{
+    private Usecase usecase = Usecase.DEFAULT;
+    private int retries = 10;
+    private boolean complete = true;
+
+    protected UnitOfWorkTemplate()
+    {
+    }
+
+    protected UnitOfWorkTemplate( int retries, boolean complete )
+    {
+        this.retries = retries;
+        this.complete = complete;
+    }
+
+    protected UnitOfWorkTemplate( Usecase usecase, int retries, boolean complete )
+    {
+        this.usecase = usecase;
+        this.retries = retries;
+        this.complete = complete;
+    }
+
+    protected abstract RESULT withUnitOfWork( UnitOfWork uow )
+        throws ThrowableType;
+
+    @SuppressWarnings( "unchecked" )
+    public RESULT withModule( Module module )
+        throws ThrowableType, UnitOfWorkCompletionException
+    {
+        int loop = 0;
+        ThrowableType ex = null;
+        do
+        {
+            UnitOfWork uow = module.unitOfWorkFactory().newUnitOfWork( usecase );
+
+            try
+            {
+                RESULT result = withUnitOfWork( uow );
+                if( complete )
+                {
+                    try
+                    {
+                        uow.complete();
+                        return result;
+                    }
+                    catch( ConcurrentEntityModificationException e )
+                    {
+                        // Retry?
+                        ex = (ThrowableType) e;
+                    }
+                }
+            }
+            catch( Throwable e )
+            {
+                ex = (ThrowableType) e;
+            }
+            finally
+            {
+                uow.discard();
+            }
+        }
+        while( loop++ < retries );
+
+        throw ex;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkConcern.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkConcern.java
new file mode 100644
index 0000000..b07cb46
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkConcern.java
@@ -0,0 +1,224 @@
+/*
+ *  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.polygene.api.unitofwork.concern;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.UndeclaredThrowableException;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.concern.GenericConcern;
+import org.apache.polygene.api.injection.scope.Invocation;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.api.usecase.UsecaseFactory;
+
+/**
+ * {@code UnitOfWorkConcern} manages the unit of work complete, discard and retry policy.
+ *
+ * @see UnitOfWorkPropagation
+ * @see UnitOfWorkDiscardOn
+ */
+@AppliesTo( UnitOfWorkPropagation.class )
+public class UnitOfWorkConcern
+    extends GenericConcern
+{
+    private static final Class<?>[] DEFAULT_DISCARD_CLASSES = new Class[]{ Throwable.class };
+
+    @Structure
+    private UnitOfWorkFactory uowf;
+
+    @Invocation
+    private UnitOfWorkPropagation propagation;
+
+    @Optional
+    @Service
+    private UsecaseFactory usecaseFactory;
+
+    /**
+     * Handles method with {@code UnitOfWorkPropagation} annotation.
+     *
+     * @param proxy  The object.
+     * @param method The invoked method.
+     * @param args   The method arguments.
+     * @return The returned value of method invocation.
+     * @throws Throwable Thrown if the method invocation throw exception.
+     */
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        UnitOfWorkPropagation.Propagation propagationPolicy = propagation.value();
+        if( propagationPolicy == UnitOfWorkPropagation.Propagation.REQUIRED )
+        {
+            if( uowf.isUnitOfWorkActive() )
+            {
+                //noinspection ConstantConditions
+                return next.invoke( proxy, method, args );
+            }
+            else
+            {
+                Usecase usecase = usecase();
+                return invokeWithCommit( proxy, method, args, uowf.newUnitOfWork( usecase ) );
+            }
+        }
+        else if( propagationPolicy == UnitOfWorkPropagation.Propagation.MANDATORY )
+        {
+            if( !uowf.isUnitOfWorkActive() )
+            {
+                throw new IllegalStateException( "UnitOfWork was required but there is no available unit of work." );
+            }
+        }
+        else if( propagationPolicy == UnitOfWorkPropagation.Propagation.REQUIRES_NEW )
+        {
+            Usecase usecase = usecase();
+            return invokeWithCommit( proxy, method, args, uowf.newUnitOfWork( usecase ) );
+        }
+        //noinspection ConstantConditions
+        return next.invoke( proxy, method, args );
+    }
+
+    private Usecase usecase()
+    {
+        String usecaseName = propagation.usecase();
+        Usecase usecase;
+        if( usecaseFactory == null )
+        {
+            if( usecaseName.length() == 0 )
+            {
+                usecase = Usecase.DEFAULT;
+            }
+            else
+            {
+                usecase = UsecaseBuilder.newUsecase( usecaseName );
+            }
+        }
+        else
+        {
+            usecase = usecaseFactory.createUsecase( usecaseName );
+        }
+        return usecase;
+    }
+
+    protected Object invokeWithCommit( Object proxy, Method method, Object[] args, UnitOfWork currentUnitOfWork )
+        throws Throwable
+    {
+        try
+        {
+            UnitOfWorkRetry retryAnnot = method.getAnnotation( UnitOfWorkRetry.class );
+            int maxTries = 0;
+            long delayFactor = 0;
+            long initialDelay = 0;
+            if( retryAnnot != null )
+            {
+                maxTries = retryAnnot.retries();
+                initialDelay = retryAnnot.initialDelay();
+                delayFactor = retryAnnot.delayFactor();
+            }
+            int retry = 0;
+            while( true )
+            {
+                //noinspection ConstantConditions
+                Object result = next.invoke( proxy, method, args );
+                try
+                {
+                    currentUnitOfWork.complete();
+                    return result;
+                }
+                catch( UndeclaredThrowableException e )
+                {
+                    Throwable undeclared = e.getUndeclaredThrowable();
+                    if( undeclared instanceof ConcurrentEntityModificationException )
+                    {
+                        ConcurrentEntityModificationException ceme = (ConcurrentEntityModificationException) undeclared;
+                        currentUnitOfWork = checkRetry( maxTries, delayFactor, initialDelay, retry, ceme );
+                        retry++;
+                    }
+                    else
+                    {
+                        throw e;
+                    }
+                }
+                catch( ConcurrentEntityModificationException e )
+                {
+                    currentUnitOfWork = checkRetry( maxTries, delayFactor, initialDelay, retry, e );
+                    retry++;
+                }
+            }
+        }
+        catch( Throwable throwable )
+        {
+            // Discard only if this concern create a unit of work
+            discardIfRequired( method, currentUnitOfWork, throwable );
+            throw throwable;
+        }
+    }
+
+    private UnitOfWork checkRetry( int maxTries,
+                                   long delayFactor,
+                                   long initialDelay,
+                                   int retry,
+                                   ConcurrentEntityModificationException e
+                                 )
+        throws ConcurrentEntityModificationException, InterruptedException
+    {
+        if( retry >= maxTries )
+        {
+            throw e;
+        }
+        uowf.currentUnitOfWork().discard();
+        Thread.sleep( initialDelay + retry * delayFactor );
+        return uowf.newUnitOfWork( usecase() );
+    }
+
+    /**
+     * Discard unit of work if the discard policy match.
+     *
+     * @param aMethod     The invoked method. This argument must not be {@code null}.
+     * @param aUnitOfWork The current unit of work. This argument must not be {@code null}.
+     * @param aThrowable  The exception thrown. This argument must not be {@code null}.
+     */
+    protected void discardIfRequired( Method aMethod, UnitOfWork aUnitOfWork, Throwable aThrowable )
+    {
+        UnitOfWorkDiscardOn discardPolicy = aMethod.getAnnotation( UnitOfWorkDiscardOn.class );
+        Class<?>[] discardClasses;
+        if( discardPolicy != null )
+        {
+            discardClasses = discardPolicy.value();
+        }
+        else
+        {
+            discardClasses = DEFAULT_DISCARD_CLASSES;
+        }
+
+        Class<? extends Throwable> aThrowableClass = aThrowable.getClass();
+        for( Class<?> discardClass : discardClasses )
+        {
+            if( discardClass.isAssignableFrom( aThrowableClass ) )
+            {
+                aUnitOfWork.discard();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkDiscardOn.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkDiscardOn.java
new file mode 100644
index 0000000..aec32d4
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkDiscardOn.java
@@ -0,0 +1,73 @@
+/*
+ *  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.polygene.api.unitofwork.concern;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Annotation to denote the unit of work discard policy.
+ * <p>
+ * By default, discard is applied on any method that has {@link UnitOfWorkPropagation} and any exception is thrown.
+ * </p>
+ * <p>
+ * Apply {@code UnitOfWorkDiscardOn} to override the default settings.
+ * </p>
+ * <p>
+ * Usage example:
+ * </p>
+ * <pre>
+ * <code>
+ *
+ * &#64;Concerns( UnitOfWorkConcern.class )
+ * public class MyBusinessServiceMixin implements BusinessService
+ * {
+ *   &#64;Structure UnitOfWorkFactory uowf;
+ *
+ *   &#64;UnitOfWorkDiscardOn( MyBusinessException.class )
+ *   public void myBusinessMethod()
+ *   {
+ *     // Must invoke current unit of work.
+ *     UnitOfWork uow = uowf.currentUnitOfWork();
+ *
+ *     // Perform business logic
+ *   }
+ * }
+ * </code>
+ * </pre>
+ *
+ * <p>
+ * The unit of work will be discarded iff {@code MyBusinessException} exceptions or its subclass is thrown from within
+ * {@code myBusinessMethod} method.
+ * </p>
+ */
+@Retention( RUNTIME )
+@Target( METHOD )
+@Inherited
+@Documented
+public @interface UnitOfWorkDiscardOn
+{
+    Class<? extends Throwable>[] value() default { Throwable.class };
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkPropagation.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkPropagation.java
new file mode 100644
index 0000000..b29a355
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkPropagation.java
@@ -0,0 +1,92 @@
+/*
+ *  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.polygene.api.unitofwork.concern;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Annotation to denote the unit of work propagation.
+ * <p>
+ * Usage example:
+ * </p>
+ * <pre>
+ * <code>
+ *
+ * &#64;Concerns( UnitOfWorkConcern.class )
+ * public class MyBusinessServiceMixin implements BusinessService
+ * {
+ *   &#64;Structure UnitOfWorkFactory uowf;
+ *
+ *   &#64;UnitOfWorkPropagation
+ *   public void myBusinessMethod()
+ *   {
+ *     // Must invoke current unit of work.
+ *     UnitOfWork uow = uowf.currentUnitOfWork();
+ *
+ *     // Perform business logic
+ *   }
+ * }
+ * </code>
+ * </pre>
+ */
+@Retention( RUNTIME )
+@Target( METHOD )
+@Inherited
+@Documented
+public @interface UnitOfWorkPropagation
+{
+    Propagation value() default Propagation.REQUIRED;
+
+    String usecase() default "";
+
+    /**
+     * Propagation behaviors.
+     */
+    enum Propagation
+    {
+        /**
+         * Default propagation behavior.
+         * Behavior: <br>
+         * If no current transaction: creates a new UnitOfWork <br>
+         * If there is a current UnitOfWork: use the current UnitOfWork.
+         */
+        REQUIRED,
+
+        /**
+         * Behavior: <br>
+         * If no current UnitOfWork: throw an exception <br>
+         * If there is a current UnitOfWork: use the current UnitOfWork.
+         */
+        MANDATORY,
+
+        /**
+         * Behavior: <br>
+         * If no current UnitOfWork: creates a new UnitOfWork <br>
+         * If there is a current UnitOfWork: suspend the current UnitOfWork and create a new UnitOfWork.
+         */
+        REQUIRES_NEW
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkRetry.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkRetry.java
new file mode 100644
index 0000000..9f2d481
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkRetry.java
@@ -0,0 +1,81 @@
+/*
+ *  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.polygene.api.unitofwork.concern;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * This annotation describes the retries that should occur in case of
+ * {@link org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException}
+ * occurs.
+ */
+@Retention( RUNTIME )
+@Target( METHOD )
+@Inherited
+@Documented
+public @interface UnitOfWorkRetry
+{
+    /**
+     * Number of times that the UnitOfWork should be tried in total.
+     * The default value is 1, which means that the UnitOfWork will execute only one time. It is also the minimum
+     * value allowed.
+     *
+     * @return Number of times that the UnitOfWork will be executed. Must be 1 or higher. If a value of 0 or lower is
+     * given, the UnitOfWork is still executed one time.
+     */
+    int retries() default 1;
+
+    /**
+     * Number of milliseconds to wait before executing the second UnitOfOfWork.
+     * The default value is 0, which means that there is no delay and it is tried immediately.
+     *
+     * @return Number of milliseconds to wait before executing the second UnitOfOfWork.
+     */
+    long initialDelay() default 0;
+
+    /**
+     * Number of milliseconds to be added for each additional retry, beyond the second one.
+     * The default value is 10.
+     *
+     * The delay is defined as;
+     *
+     * <pre><code>
+     *
+     * Thread.sleep( initialDelay + retry * delayFactor );
+     * </code></pre>
+     * where retry will be 0 after first UnitOfWork had a {@link ConcurrentEntityModificationException} and is 1 after
+     * the first retry and so forth.
+     * <p>
+     * So, with the {@code retries=4, initialDelay=5, delayFactor=20} the 3 delays between the UnitOfWorks will be
+     * {@code 5ms, 25ms, 45ms}
+     * </p>
+     *
+     * @return The number of milliseconds per retry, except the first one, that should be added to the delay between
+     * tries.
+     */
+    long delayFactor() default 10;
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/package.html b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/package.html
new file mode 100644
index 0000000..20aa625
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/package.html
@@ -0,0 +1,27 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>UnitOfWork Concerns.</h2>
+        <p>
+            UnitOfWork Concerns allow declarative UnitOfWork propagation, discard wrt. exceptions and automatic retry.
+        </p>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/package.html b/core/api/src/main/java/org/apache/polygene/api/unitofwork/package.html
new file mode 100644
index 0000000..70ff9e9
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>UnitOfWork API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/usecase/Usecase.java b/core/api/src/main/java/org/apache/polygene/api/usecase/Usecase.java
new file mode 100644
index 0000000..d730394
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/usecase/Usecase.java
@@ -0,0 +1,73 @@
+/*
+ *  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.polygene.api.usecase;
+
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.structure.MetaInfoHolder;
+
+/**
+ * A Usecase. A Usecase is used as a model for UnitOfWork, and helps
+ * implementations decide what to do in certain circumstances.
+ */
+public final class Usecase
+    implements MetaInfoHolder
+{
+    public static final Usecase DEFAULT = new Usecase( "Default", new MetaInfo() );
+
+    private final String name;
+    private final MetaInfo metaInfo;
+
+    Usecase( String name, MetaInfo metaInfo )
+    {
+        this.name = name;
+        this.metaInfo = metaInfo;
+    }
+
+    /**
+     * Name of the usecase.
+     *
+     * @return the name
+     */
+    public String name()
+    {
+        return name;
+    }
+
+    /**
+     * Meta-info for the usecase. This can be of any type, and is typically set when creating the usecase
+     * and read during the execution of the usecase.
+     *
+     * @param infoType the MetaInfo type to retrieve.
+     *
+     * @return the previously stored metaInfo of the given type for the usecase.
+     */
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return metaInfo.get( infoType );
+    }
+
+    @Override
+    public String toString()
+    {
+        return name + ", meta info:" + metaInfo;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/usecase/UsecaseBuilder.java b/core/api/src/main/java/org/apache/polygene/api/usecase/UsecaseBuilder.java
new file mode 100644
index 0000000..ae89aad
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/usecase/UsecaseBuilder.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.api.usecase;
+
+import org.apache.polygene.api.common.MetaInfo;
+
+/**
+ * Builder for Usecases.
+ */
+public final class UsecaseBuilder
+{
+    public static UsecaseBuilder buildUsecase( String aName )
+    {
+        return new UsecaseBuilder( aName );
+    }
+
+    public static Usecase newUsecase( String aName )
+    {
+        return new UsecaseBuilder( aName ).newUsecase();
+    }
+
+    private MetaInfo metaInfo = new MetaInfo();
+
+    private String name;
+
+    private UsecaseBuilder( String name )
+    {
+        this.name = name;
+    }
+
+    public UsecaseBuilder withMetaInfo( Object metaInfo )
+    {
+        this.metaInfo.set( metaInfo );
+        return this;
+    }
+
+    public Usecase newUsecase()
+    {
+        return new Usecase( name, metaInfo );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/usecase/UsecaseFactory.java b/core/api/src/main/java/org/apache/polygene/api/usecase/UsecaseFactory.java
new file mode 100644
index 0000000..b26129e
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/usecase/UsecaseFactory.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.api.usecase;
+
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkConcern;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation;
+import org.apache.polygene.api.usecase.Usecase;
+
+/** An optional service that if implemented and available to the {@link UnitOfWorkConcern}
+ * will use to create the named {@link Usecase} of the {@link UnitOfWorkPropagation} annotation.
+ *
+ */
+public interface UsecaseFactory
+{
+    Usecase createUsecase( String name );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/usecase/package.html b/core/api/src/main/java/org/apache/polygene/api/usecase/package.html
new file mode 100644
index 0000000..1d55001
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/usecase/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Usecase API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/AccessibleObjects.java b/core/api/src/main/java/org/apache/polygene/api/util/AccessibleObjects.java
new file mode 100644
index 0000000..73bb6ff
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/AccessibleObjects.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.api.util;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.lang.reflect.Modifier;
+
+public final class AccessibleObjects
+{
+    /**
+     * Ensure that a Method, Field, Constructor is accessible.
+     *
+     * If it is public, do nothing.
+     * Otherwise, use {@link AccessibleObject#setAccessible(boolean)} if it hasn't already been done.
+     *
+     * @param accessibleObject The AccessibleObject
+     * @param <T> AccessibleObject type
+     * @return The given AccessibleObject, accessible
+     */
+    public static <T extends AccessibleObject> T accessible( T accessibleObject )
+    {
+        if( accessibleObject instanceof Member )
+        {
+            Member member = (Member) accessibleObject;
+            if( Modifier.isPublic( member.getModifiers() )
+                && Modifier.isPublic( member.getDeclaringClass().getModifiers() ) )
+            {
+                return accessibleObject;
+            }
+        }
+        if( !accessibleObject.isAccessible() )
+        {
+            accessibleObject.setAccessible( true );
+        }
+        return accessibleObject;
+    }
+
+    private AccessibleObjects() {}
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/Annotations.java b/core/api/src/main/java/org/apache/polygene/api/util/Annotations.java
new file mode 100644
index 0000000..b172945
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/Annotations.java
@@ -0,0 +1,79 @@
+/*
+ *  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.polygene.api.util;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.apache.polygene.api.util.Classes.interfacesOf;
+import static org.apache.polygene.api.util.Classes.typeOf;
+
+/**
+ * Useful methods for handling Annotations.
+ */
+public final class Annotations
+{
+    public static final Function<Type, Stream<Annotation>> ANNOTATIONS_OF =
+        Classes.forTypes( type -> Arrays.stream( Classes.RAW_CLASS.apply( type ).getAnnotations() ) );
+
+    public static Predicate<Annotation> typeHasAnnotation( Class<? extends Annotation> annotationType )
+    {
+        return element -> hasAnnotation( annotationType ).test( type().apply( element ) );
+    }
+
+    public static Predicate<AnnotatedElement> hasAnnotation( final Class<? extends Annotation> annotationType )
+    {
+        return element -> element.getAnnotation( annotationType ) != null;
+    }
+
+    public static Function<Annotation, Class<? extends Annotation>> type()
+    {
+        return Annotation::annotationType;
+    }
+
+    public static Predicate<Annotation> isType( final Class<? extends Annotation> annotationType )
+    {
+        return annotation -> annotation.annotationType().equals( annotationType );
+    }
+
+    public static <T extends Annotation> T annotationOn( Type type, Class<T> annotationType )
+    {
+        return annotationType.cast( Classes.RAW_CLASS.apply( type ).getAnnotation( annotationType ) );
+    }
+
+    public static List<Annotation> findAccessorAndTypeAnnotationsIn(AccessibleObject accessor) {
+        Stream<Annotation> stream = Stream.concat(
+                Arrays.stream(accessor.getAnnotations()),
+                interfacesOf(typeOf(accessor)).flatMap(ANNOTATIONS_OF)
+        );
+        Collector<Annotation, ?, List<Annotation>> collector = Collectors.toList();
+        return stream.collect(collector);
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/Classes.java b/core/api/src/main/java/org/apache/polygene/api/util/Classes.java
new file mode 100644
index 0000000..8cbce1e
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/Classes.java
@@ -0,0 +1,541 @@
+/*
+ *  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.polygene.api.util;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.ModelDescriptor;
+
+import static java.util.stream.Stream.concat;
+import static java.util.stream.StreamSupport.stream;
+
+/**
+ * Useful methods for handling Classes.
+ */
+public final class Classes
+{
+    private final static Map<Type, Type> WRAPPER_CLASSES = new HashMap<>();
+
+    static
+    {
+        WRAPPER_CLASSES.put( boolean.class, Boolean.class );
+        WRAPPER_CLASSES.put( byte.class, Byte.class );
+        WRAPPER_CLASSES.put( short.class, Short.class );
+        WRAPPER_CLASSES.put( char.class, Character.class );
+        WRAPPER_CLASSES.put( int.class, Integer.class );
+        WRAPPER_CLASSES.put( long.class, Long.class );
+        WRAPPER_CLASSES.put( float.class, Float.class );
+        WRAPPER_CLASSES.put( double.class, Double.class );
+    }
+
+    private final static Map<Type, Type> PRIMITIVE_CLASSES = new HashMap<>();
+
+    static
+    {
+        PRIMITIVE_CLASSES.put( boolean.class, Boolean.class );
+        PRIMITIVE_CLASSES.put( byte.class, Byte.class );
+        PRIMITIVE_CLASSES.put( short.class, Short.class );
+        PRIMITIVE_CLASSES.put( char.class, Character.class );
+        PRIMITIVE_CLASSES.put( int.class, Integer.class );
+        PRIMITIVE_CLASSES.put( long.class, Long.class );
+        PRIMITIVE_CLASSES.put( float.class, Float.class );
+        PRIMITIVE_CLASSES.put( double.class, Double.class );
+    }
+
+    /**
+     * Convert from primitive class (int, short, double, etc.) to wrapper class (Integer, Short, Double, etc.).
+     * Return the same class if it's not a primitive class. This can therefore safely be used on all types
+     * to ensure that they are not primitives.
+     */
+    private static final Function<Type, Type> WRAPPER_CLASS = clazz -> {
+        Type wrapperClass = WRAPPER_CLASSES.get( clazz );
+        return wrapperClass == null ? clazz : wrapperClass;
+    };
+
+    /**
+     * Convert from wrapper class (Integer, Short, Double, etc.) to primitive class (int, short, double, etc.).
+     * Return the same class if it's not a wrapper class. This can therefore safely be used on all types
+     * to ensure that they are primitives if possible.
+     */
+    @SuppressWarnings( "UnusedDeclaration" )
+    private static final Function<Type, Type> PRIMITIVE_CLASS = aClass -> {
+        Type primitiveClass = PRIMITIVE_CLASSES.get( aClass );
+        return primitiveClass == null ? aClass : primitiveClass;
+    };
+
+    /**
+     * Function that extract the raw class of a type.
+     */
+    public static final Function<Type, Class<?>> RAW_CLASS = genericType -> {
+        // Calculate raw type
+        if( genericType instanceof Class )
+        {
+            return (Class<?>) genericType;
+        }
+        else if( genericType instanceof ParameterizedType )
+        {
+            return (Class<?>) ( (ParameterizedType) genericType ).getRawType();
+        }
+        else if( genericType instanceof TypeVariable )
+        {
+            return (Class<?>) ( (TypeVariable) genericType ).getGenericDeclaration();
+        }
+        else if( genericType instanceof WildcardType )
+        {
+            return (Class<?>) ( (WildcardType) genericType ).getUpperBounds()[ 0 ];
+        }
+        else if( genericType instanceof GenericArrayType )
+        {
+            Object temp = Array.newInstance( (Class<?>) ( (GenericArrayType) genericType ).getGenericComponentType(), 0 );
+            return temp.getClass();
+        }
+        throw new IllegalArgumentException( "Could not extract the raw class of " + genericType );
+    };
+
+    private static final Function<AccessibleObject, Type> TYPE_OF = accessor -> {
+        if( accessor instanceof Method )
+        {
+            return ( (Method) accessor ).getGenericReturnType();
+        }
+        return ( (Field) accessor ).getGenericType();
+    };
+
+    private static final Function<Type, Stream<Class<?>>> CLASS_HIERARCHY = new Function<Type, Stream<Class<?>>>()
+    {
+        @Override
+        public Stream<Class<?>> apply( Type type )
+        {
+            if( type == null )
+            {
+                return Stream.empty();
+            }
+            if( type.equals( Object.class ) )
+            {
+                return Stream.of( (Class<?>) type );
+            }
+            else
+            {
+                type = RAW_CLASS.apply( type );
+                Class superclass = ( (Class) type ).getSuperclass();
+                return concat( Stream.of( (Class<?>) type ), apply( superclass ) );
+            }
+        }
+    };
+
+    @SuppressWarnings( "raw" )
+    private static final Function<Type, Stream<? extends Type>> INTERFACES_OF = new Function<Type, Stream<? extends Type>>()
+    {
+        @Override
+        public Stream<? extends Type> apply( Type type )
+        {
+            Class clazz = RAW_CLASS.apply( type );
+
+            if( clazz.isInterface() )
+            {
+                Stream<? extends Type> genericInterfaces = Arrays.stream( clazz.getGenericInterfaces() );
+                Stream<? extends Type> intfaces = genericInterfaces.flatMap( INTERFACES_OF );
+                return concat( Stream.of( type ), intfaces );
+            }
+            else
+            {
+                if( type.equals( Object.class ) )
+                {
+                    return Arrays.stream( clazz.getGenericInterfaces() );
+                }
+                else
+                {
+                    return concat( Stream.of( clazz.getGenericInterfaces() ).flatMap( INTERFACES_OF ),
+                                   Stream.of( clazz.getSuperclass() ).flatMap( INTERFACES_OF ) );
+
+                }
+            }
+        }
+    };
+
+    private static final Function<Type, Stream<? extends Type>> TYPES_OF = type -> {
+        Class clazz = RAW_CLASS.apply( type );
+
+        if( clazz.isInterface() )
+        {
+            Stream<Type> intfaces = Arrays.stream( clazz.getGenericInterfaces() ).flatMap( INTERFACES_OF );
+            return concat( Stream.of( clazz ), intfaces );
+        }
+        else
+        {
+            return concat( Stream.of( clazz ),
+                           Stream.of( type ).flatMap( CLASS_HIERARCHY ).flatMap( INTERFACES_OF ) );
+        }
+    };
+
+    public static Type typeOf( AccessibleObject from )
+    {
+        return TYPE_OF.apply( from );
+    }
+
+    public static Stream<Type> typesOf( Stream<? extends Type> types )
+    {
+        return types.flatMap( TYPES_OF );
+    }
+
+    public static Stream<? extends Type> typesOf( Type type )
+    {
+        return TYPES_OF.apply( type );
+    }
+
+    public static Stream<? extends Type> interfacesOf( Stream<? extends Type> types )
+    {
+        return types.flatMap( INTERFACES_OF );
+    }
+
+    public static Stream<? extends Type> interfacesOf( Type type )
+    {
+        return Stream.of( type ).flatMap( INTERFACES_OF );
+    }
+
+    public static Stream<Class<?>> classHierarchy( Class<?> type )
+    {
+        return Stream.of( type ).flatMap( CLASS_HIERARCHY );
+    }
+
+    public static Type wrapperClass( Type type )
+    {
+        return WRAPPER_CLASS.apply( type );
+    }
+
+    public static Predicate<Class<?>> isAssignableFrom( final Class<?> clazz )
+    {
+        return clazz::isAssignableFrom;
+    }
+
+    public static Predicate<Object> instanceOf( final Class<?> clazz )
+    {
+        return clazz::isInstance;
+    }
+
+    public static Predicate<Class<?>> hasModifier( final int classModifier )
+    {
+        return item -> ( item.getModifiers() & classModifier ) != 0;
+    }
+
+    public static <T> Function<Type, Stream<T>> forClassHierarchy( final Function<Class<?>, Stream<T>> function )
+    {
+        return type -> Stream.of( type ).flatMap( CLASS_HIERARCHY ).flatMap( function );
+    }
+
+    public static <T> Function<Type, Stream<T>> forTypes( final Function<Type, Stream<T>> function )
+    {
+        return type -> Stream.of( type ).flatMap( TYPES_OF ).flatMap( function );
+    }
+
+    @SuppressWarnings( "raw" )
+    public static Set<Class<?>> interfacesWithMethods( Set<Class<?>> interfaces )
+    {
+        Set<Class<?>> newSet = new LinkedHashSet<>();
+        for( Class type : interfaces )
+        {
+            if( type.isInterface() && type.getDeclaredMethods().length > 0 )
+            {
+                newSet.add( type );
+            }
+        }
+
+        return newSet;
+    }
+
+    public static String simpleGenericNameOf( Type type )
+    {
+        StringBuilder sb = new StringBuilder();
+        simpleGenericNameOf( sb, type );
+        return sb.toString();
+    }
+
+    @SuppressWarnings( "raw" )
+    private static void simpleGenericNameOf( StringBuilder sb, Type type )
+    {
+        if( type instanceof Class )
+        {
+            sb.append( ( (Class) type ).getSimpleName() );
+        }
+        else if( type instanceof ParameterizedType )
+        {
+            ParameterizedType pt = (ParameterizedType) type;
+            simpleGenericNameOf( sb, pt.getRawType() );
+            sb.append( "<" );
+            boolean atLeastOne = false;
+            for( Type typeArgument : pt.getActualTypeArguments() )
+            {
+                if( atLeastOne )
+                {
+                    sb.append( ", " );
+                }
+                simpleGenericNameOf( sb, typeArgument );
+                atLeastOne = true;
+            }
+            sb.append( ">" );
+        }
+        else if( type instanceof GenericArrayType )
+        {
+            GenericArrayType gat = (GenericArrayType) type;
+            simpleGenericNameOf( sb, gat.getGenericComponentType() );
+            sb.append( "[]" );
+        }
+        else if( type instanceof TypeVariable )
+        {
+            TypeVariable tv = (TypeVariable) type;
+            sb.append( tv.getName() );
+        }
+        else if( type instanceof WildcardType )
+        {
+            WildcardType wt = (WildcardType) type;
+            sb.append( "? extends " );
+            boolean atLeastOne = false;
+            for( Type typeArgument : wt.getUpperBounds() )
+            {
+                if( atLeastOne )
+                {
+                    sb.append( ", " );
+                }
+                simpleGenericNameOf( sb, typeArgument );
+                atLeastOne = true;
+            }
+        }
+        else
+        {
+            throw new IllegalArgumentException( "Don't know how to deal with type:" + type );
+        }
+    }
+
+    @SuppressWarnings( "UnusedDeclaration" )
+    public static <AnnotationType extends Annotation>
+    AnnotationType findAnnotationOfTypeOrAnyOfSuperTypes( Class<?> type, Class<AnnotationType> annotationClass )
+    {
+        return Stream.of( type )
+            .flatMap( TYPES_OF )
+            .map( RAW_CLASS )
+            .map( clazz -> clazz.getAnnotation( annotationClass ) )
+            .filter( Objects::nonNull )
+            .findAny().orElse( null );
+    }
+
+    public static Predicate<Member> memberNamed( final String name )
+    {
+        return item -> item.getName().equals( name );
+    }
+
+    /**
+     * Given a type variable, find what it resolves to given the declaring class where type
+     * variable was found and a top class that extends the declaring class.
+     *
+     * @param name           The TypeVariable name.
+     * @param declaringClass The class where the TypeVariable is declared.
+     * @param topClass       The top class that extends the declaringClass
+     *
+     * @return The Type instance of the given TypeVariable
+     */
+    @SuppressWarnings( "raw" )
+    public static Type resolveTypeVariable( TypeVariable name, Class declaringClass, Class topClass )
+    {
+        Type type = resolveTypeVariable( name, declaringClass, new HashMap<>(), topClass );
+        if( type == null )
+        {
+            type = Object.class;
+        }
+        return type;
+    }
+
+    private static Type resolveTypeVariable( TypeVariable name,
+                                             Class declaringClass,
+                                             Map<TypeVariable, Type> mappings,
+                                             Class current
+    )
+    {
+        if( current.equals( declaringClass ) )
+        {
+            Type resolvedType = name;
+            while( resolvedType instanceof TypeVariable )
+            {
+                resolvedType = mappings.get( resolvedType );
+            }
+            return resolvedType;
+        }
+
+        Stream<? extends Type> stream = Arrays.stream( current.getGenericInterfaces() )
+            .flatMap( INTERFACES_OF )
+            .distinct();
+
+        Type genericSuperclass = current.getGenericSuperclass();
+        if( genericSuperclass != null )
+        {
+            stream = concat( stream, Stream.of( genericSuperclass ) );
+        }
+        return stream.map( type -> {
+            Class subClass;
+            if( type instanceof ParameterizedType )
+            {
+                subClass = extractTypeVariables( mappings, (ParameterizedType) type );
+            }
+            else
+            {
+                subClass = (Class) type;
+            }
+            return subClass;
+        } )
+            .map( subClass -> resolveTypeVariable( name, declaringClass, mappings, subClass ) )
+            .filter( Objects::nonNull )
+            .findAny().orElse( null );
+    }
+
+    private static Class extractTypeVariables( Map<TypeVariable, Type> mappings, ParameterizedType type )
+    {
+        Class subClass;
+        Type[] args = type.getActualTypeArguments();
+        Class clazz = (Class) type.getRawType();
+        TypeVariable[] vars = clazz.getTypeParameters();
+        for( int i = 0; i < vars.length; i++ )
+        {
+            TypeVariable var = vars[ i ];
+            Type mappedType = args[ i ];
+            mappings.put( var, mappedType );
+        }
+        subClass = (Class) type.getRawType();
+        return subClass;
+    }
+
+    /**
+     * Get URI for a class.
+     *
+     * @param clazz class
+     *
+     * @return URI
+     *
+     * @throws NullPointerException if clazz is null
+     */
+    @SuppressWarnings( "raw" )
+    public static String toURI( final Class clazz )
+        throws NullPointerException
+    {
+        return toURI( clazz.getName() );
+    }
+
+    /**
+     * Get URI for a class name.
+     * <p>
+     * Example:
+     * </p>
+     * <p>
+     * Class name com.example.Foo$Bar is converted to URI urn:polygene:com.example.Foo-Bar
+     * </p>
+     *
+     * @param className class name
+     *
+     * @return URI
+     *
+     * @throws NullPointerException if className is null
+     */
+    public static String toURI( String className )
+        throws NullPointerException
+    {
+        className = normalizeClassToURI( className );
+        return "urn:polygene:type:" + className;
+    }
+
+    /**
+     * Get class name from a URI
+     *
+     * @param uri URI
+     *
+     * @return class name
+     *
+     * @throws NullPointerException if uri is null
+     */
+    public static String toClassName( String uri )
+        throws NullPointerException
+    {
+        uri = uri.substring( "urn:polygene:type:".length() );
+        uri = denormalizeURIToClass( uri );
+        return uri;
+    }
+
+    public static String normalizeClassToURI( String className )
+    {
+        return className.replace( '$', '-' );
+    }
+
+    public static String denormalizeURIToClass( String uriPart )
+    {
+        return uriPart.replace( '-', '$' );
+    }
+
+    public static Predicate<ModelDescriptor> modelTypeSpecification( final String className )
+    {
+        return item ->
+            stream( item.types().spliterator(), false )
+                .map( Class::getName ).anyMatch( typeName -> typeName.equals( className ) );
+    }
+
+    @SuppressWarnings( "raw" )
+    public static Predicate<ModelDescriptor> exactTypeSpecification( final Class type )
+    {
+        return item -> item.types().anyMatch( clazz -> clazz.equals( type ) );
+    }
+
+    @SuppressWarnings( "raw" )
+    public static Predicate<ModelDescriptor> assignableTypeSpecification( final Class<?> type )
+    {
+        return item ->
+            item.types().anyMatch(
+                itemType -> !type.equals( itemType ) && type.isAssignableFrom( itemType )
+            );
+    }
+
+    @SuppressWarnings( "raw" )
+    public static String toString( Stream<? extends Class> types )
+    {
+        return "[" + types.map( Class::getSimpleName ).collect( Collectors.joining( "," ) ) + "]";
+    }
+
+    public static Function<Type, String> toClassName()
+    {
+        return type -> RAW_CLASS.apply( type ).getName();
+    }
+
+    private Classes()
+    {
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/Collectors.java b/core/api/src/main/java/org/apache/polygene/api/util/Collectors.java
new file mode 100644
index 0000000..c3045cc
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/Collectors.java
@@ -0,0 +1,234 @@
+/*
+ *  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.polygene.api.util;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collector;
+
+/**
+ * Implementations of {@link Collector} missing from the JDK.
+ */
+public class Collectors
+{
+    /**
+     * Collect a single element.
+     *
+     * The Collector throws {@link IllegalArgumentException} if no or more than one element.
+     *
+     * @param <T> Element type
+     * @return The single element collector
+     */
+    public static <T>
+    Collector<T, ?, T> single()
+        throws IllegalArgumentException
+    {
+        Supplier<T> thrower = () ->
+        {
+            throw new IllegalArgumentException( "No or more than one element in stream" );
+        };
+        return java.util.stream.Collectors.collectingAndThen( java.util.stream.Collectors.reducing( ( a, b ) -> null ),
+                                                              optional -> optional.orElseGet( thrower ) );
+    }
+
+    /**
+     * Eventually collect a single element.
+     *
+     * The Collector throws {@link IllegalArgumentException} if more than one element.
+     *
+     * @param <T> Element type
+     * @return The optional single element collector
+     */
+    public static <T>
+    Collector<T, ?, Optional<T>> singleOrEmpty()
+    {
+        return java.util.stream.Collectors.reducing(
+            ( left, right ) ->
+            {
+                if( left != null && right != null )
+                {
+                    throw new IllegalArgumentException( "More than one element in stream" );
+                }
+                if( left != null )
+                {
+                    return left;
+                }
+                return right;
+            } );
+    }
+
+    /**
+     * Collect map entries into a {@link HashMap}.
+     *
+     * The Collector throws {@link NullPointerException} if one entry has a {@literal null} value.
+     * The Collector throws {@link IllegalStateException} if duplicate keys are found.
+     *
+     * @param <T> the Map entry type
+     * @param <K> the collected map key type
+     * @param <U> the collected map value type
+     * @return a {@code Collector} which collects elements into a {@code Map}
+     */
+    public static <T extends Map.Entry<K, U>, K, U>
+    Collector<T, ?, Map<K, U>> toMap()
+    {
+        return toMap( Map.Entry::getKey, Map.Entry::getValue, HashMap::new );
+    }
+
+    /**
+     * Collect map entries into a map.
+     *
+     * The Collector throws {@link NullPointerException} if one entry has a {@literal null} value.
+     * The Collector throws {@link IllegalStateException} if duplicate keys are found.
+     *
+     * @param <M> the type of the resulting {@code Map}
+     * @param <T> the Map entry type
+     * @param <K> the collected map key type
+     * @param <U> the collected map value type
+     * @param mapSupplier a function which returns a new, empty {@code Map} into
+     *                    which the results will be inserted
+     * @return The map collector
+     */
+    public static <T extends Map.Entry<K, U>, K, U, M extends Map<K, U>>
+    Collector<T, ?, M> toMap( Supplier<M> mapSupplier )
+    {
+        return toMap( Map.Entry::getKey, Map.Entry::getValue, mapSupplier );
+    }
+
+    /**
+     * Collect map entries into a map.
+     *
+     * The Collector throws {@link NullPointerException} if one entry has a {@literal null} value.
+     * The Collector throws {@link IllegalStateException} if duplicate keys are found.
+     *
+     * @param <M> the type of the resulting {@code Map}
+     * @param <T> the Map entry type
+     * @param <K> the collected map key type
+     * @param <U> the collected map value type
+     * @param keyMapper a mapping function to produce keys
+     * @param valueMapper a mapping function to produce values
+     * @param mapSupplier a function which returns a new, empty {@code Map} into
+     *                    which the results will be inserted
+     * @return The map collector
+     */
+    public static <T, K, U, M extends Map<K, U>>
+    Collector<T, ?, M> toMap( Function<? super T, ? extends K> keyMapper,
+                              Function<? super T, ? extends U> valueMapper,
+                              Supplier<M> mapSupplier )
+    {
+        return java.util.stream.Collectors.toMap( keyMapper,
+                                                  valueMapper,
+                                                  throwingMerger(),
+                                                  mapSupplier );
+    }
+
+    /**
+     * Collect map entries into a {@link HashMap}, allowing null values.
+     *
+     * The Collector throws {@link IllegalStateException} if duplicate keys are found.
+     *
+     * See https://bugs.openjdk.java.net/browse/JDK-8148463
+     *
+     * @param <T> the Map entry type
+     * @param <K> the collected map key type
+     * @param <U> the collected map value type
+     * @return The map collector
+     */
+    public static <T extends Map.Entry<K, U>, K, U>
+    Collector<T, ?, Map<K, U>> toMapWithNullValues()
+    {
+        return toMapWithNullValues( Map.Entry::getKey, Map.Entry::getValue, HashMap::new );
+    }
+
+    /**
+     * Collect map entries into a map, allowing null values.
+     *
+     * The Collector throws {@link IllegalStateException} if duplicate keys are found.
+     *
+     * See https://bugs.openjdk.java.net/browse/JDK-8148463
+     *
+     * @param <M> the type of the resulting {@code Map}
+     * @param <T> the Map entry type
+     * @param <K> the collected map key type
+     * @param <U> the collected map value type
+     * @param mapSupplier a function which returns a new, empty {@code Map} into
+     *                    which the results will be inserted
+     * @return The map collector
+     */
+    public static <T extends Map.Entry<K, U>, K, U, M extends Map<K, U>>
+    Collector<T, ?, M> toMapWithNullValues( Supplier<M> mapSupplier )
+    {
+        return toMapWithNullValues( Map.Entry::getKey, Map.Entry::getValue, mapSupplier );
+    }
+
+    /**
+     * Collect map entries into a map, allowing null values.
+     *
+     * The Collector throws {@link IllegalStateException} if duplicate keys are found.
+     *
+     * See https://bugs.openjdk.java.net/browse/JDK-8148463
+     *
+     * @param <M> the type of the resulting {@code Map}
+     * @param <T> the Map entry type
+     * @param <K> the collected map key type
+     * @param <U> the collected map value type
+     * @param keyMapper a mapping function to produce keys
+     * @param valueMapper a mapping function to produce values
+     * @param mapSupplier a function which returns a new, empty {@code Map} into
+     *                    which the results will be inserted
+     * @return The map collector
+     */
+    public static <T, K, U, M extends Map<K, U>>
+    Collector<T, ?, M> toMapWithNullValues( Function<? super T, ? extends K> keyMapper,
+                                            Function<? super T, ? extends U> valueMapper,
+                                            Supplier<M> mapSupplier )
+    {
+        return Collector
+            .of( mapSupplier,
+                 ( map, entry ) -> map.put( keyMapper.apply( entry ),
+                                            valueMapper.apply( entry ) ),
+                 ( left, right ) ->
+                 {
+                     M result = mapSupplier.get();
+                     result.putAll( left );
+                     for( Map.Entry<K, U> entry : right.entrySet() )
+                     {
+                         K key = entry.getKey();
+                         if( result.containsKey( key ) )
+                         {
+                             throw new IllegalStateException( String.format( "Duplicate key %s", key ) );
+                         }
+                         result.put( key, entry.getValue() );
+                     }
+                     return result;
+                 } );
+    }
+
+    private static <T> BinaryOperator<T> throwingMerger()
+    {
+        return ( left, right ) ->
+        {
+            throw new IllegalStateException( String.format( "Duplicate key %s", left ) );
+        };
+    }
+
+    private Collectors() {}
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/Constructors.java b/core/api/src/main/java/org/apache/polygene/api/util/Constructors.java
new file mode 100644
index 0000000..12f2e01
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/Constructors.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.api.util;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+/**
+ * Useful methods for handling Constructors.
+ */
+public final class Constructors
+{
+    public static final Function<Type, Stream<Constructor<?>>> CONSTRUCTORS_OF =
+        Classes.forClassHierarchy( type -> Arrays.stream( type.getDeclaredConstructors() ) );
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/Fields.java b/core/api/src/main/java/org/apache/polygene/api/util/Fields.java
new file mode 100644
index 0000000..c29c3bf
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/Fields.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.api.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+/**
+ * Useful methods for handling Fields.
+ */
+public final class Fields
+{
+    public static final Function<Type, Stream<Field>> FIELDS_OF =
+        Classes.forClassHierarchy( type -> Arrays.stream( type.getDeclaredFields() ) );
+
+    public static final BiFunction<Class<?>, String, Field> FIELD_NAMED = ( clazz, name ) ->
+        FIELDS_OF.apply( clazz ).filter( Classes.memberNamed( name ) ).findFirst().orElse( null );
+
+    public static Stream<Field> fieldsOf( Type type )
+    {
+        return Stream.of( type ).flatMap( FIELDS_OF );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/HierarchicalVisitor.java b/core/api/src/main/java/org/apache/polygene/api/util/HierarchicalVisitor.java
new file mode 100644
index 0000000..33fcb40
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/HierarchicalVisitor.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.api.util;
+
+/**
+ * Visitor to visit hierarchies.
+ */
+public interface HierarchicalVisitor<NODE, LEAF, ThrowableType extends Throwable> extends Visitor<LEAF, ThrowableType>
+{
+    /**
+     * Enter an instance of T
+     *
+     * @param visited the visited instance which is now entered
+     *
+     * @return true if the visitor pattern should continue, false if it should be aborted for this level
+     *
+     * @throws ThrowableType if an exception occurred during processing. Any client call that initiated the visiting should
+     *                       get the exception in order to handle it properly.
+     */
+    boolean visitEnter( NODE visited )
+        throws ThrowableType;
+
+    /**
+     * Leave an instance of T
+     *
+     * @param visited the visited instance which is now left
+     *
+     * @return true if the visitor pattern should continue, false if it should be aborted for the level of this node
+     *
+     * @throws ThrowableType if an exception occurred during processing. Any client call that initiated the visiting should
+     *                       get the exception in order to handle it properly.
+     */
+    boolean visitLeave( NODE visited )
+        throws ThrowableType;
+
+    @Override
+    boolean visit( LEAF visited )
+        throws ThrowableType;
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/HierarchicalVisitorAdapter.java b/core/api/src/main/java/org/apache/polygene/api/util/HierarchicalVisitorAdapter.java
new file mode 100644
index 0000000..4756b3c
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/HierarchicalVisitorAdapter.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.api.util;
+
+/**
+ * Generic Hierarchical Visitor interface.
+ */
+public class HierarchicalVisitorAdapter<NODE, LEAF, ThrowableType extends Throwable>
+    implements HierarchicalVisitor<NODE, LEAF, ThrowableType>
+{
+    @Override
+    public boolean visitEnter( NODE visited )
+        throws ThrowableType
+    {
+        return true;
+    }
+
+    @Override
+    public boolean visitLeave( NODE visited )
+        throws ThrowableType
+    {
+        return true;
+    }
+
+    @Override
+    public boolean visit( LEAF visited )
+        throws ThrowableType
+    {
+        return true;
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/Methods.java b/core/api/src/main/java/org/apache/polygene/api/util/Methods.java
new file mode 100644
index 0000000..bf0d4dd
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/Methods.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.api.util;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+/**
+ * Useful methods for handling Methods.
+ */
+public class Methods
+{
+    public static final Predicate<Type> HAS_METHODS =
+        item -> Classes.RAW_CLASS.apply( item ).getDeclaredMethods().length > 0;
+
+    public static final Function<Type, Stream<Method>> METHODS_OF = Classes.forTypes( type ->
+        Stream.of( type ).map( Classes.RAW_CLASS ).flatMap( clazz -> Arrays.stream( clazz.getDeclaredMethods() ) )
+    );
+
+    public static final BiFunction<Class<?>, String, Method> METHOD_NAMED = ( clazz, name ) ->
+        METHODS_OF.apply( clazz ).filter( Classes.memberNamed( name ) ).findFirst().orElse( null );
+
+
+    public static Stream<Method> methodsOf( Type type )
+    {
+        return Stream.of(type).flatMap( METHODS_OF );
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/Visitable.java b/core/api/src/main/java/org/apache/polygene/api/util/Visitable.java
new file mode 100644
index 0000000..8d163a3
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/Visitable.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.api.util;
+
+/**
+ * Interface that visitable objects should implement.
+ */
+public interface Visitable<T>
+{
+    <ThrowableType extends Throwable> boolean accept( Visitor<? super T, ThrowableType> visitor )
+        throws ThrowableType;
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/VisitableHierarchy.java b/core/api/src/main/java/org/apache/polygene/api/util/VisitableHierarchy.java
new file mode 100644
index 0000000..33015db
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/VisitableHierarchy.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.api.util;
+
+/**
+ * Interface that visitable hierarchies of objects should implement.
+ */
+public interface VisitableHierarchy<NODE, LEAF>
+{
+    <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super NODE, ? super LEAF, ThrowableType> visitor )
+        throws ThrowableType;
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/Visitor.java b/core/api/src/main/java/org/apache/polygene/api/util/Visitor.java
new file mode 100644
index 0000000..80f45a0
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/Visitor.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.api.util;
+
+/**
+ * Generic Visitor interface.
+ */
+public interface Visitor<T, ThrowableType extends Throwable>
+{
+    /**
+     * Visit an instance of T
+     *
+     * @param visited the visited instance
+     *
+     * @return true if the visitor pattern should continue, false if it should be aborted
+     *
+     * @throws ThrowableType if an exception occurred during processing. Any client call that initiated the visiting should
+     *                       get the exception in order to handle it properly.
+     */
+    boolean visit( T visited )
+        throws ThrowableType;
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/package.html b/core/api/src/main/java/org/apache/polygene/api/util/package.html
new file mode 100644
index 0000000..cc0b40b
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>API Utilities.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/NoSuchValueException.java b/core/api/src/main/java/org/apache/polygene/api/value/NoSuchValueException.java
new file mode 100644
index 0000000..4e5cb30
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/value/NoSuchValueException.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.api.value;
+
+import java.util.stream.Collectors;
+import org.apache.polygene.api.composite.NoSuchCompositeException;
+import org.apache.polygene.api.structure.TypeLookup;
+
+/**
+ * Thrown when no visible value of the requested type is found.
+ */
+public class NoSuchValueException
+    extends NoSuchCompositeException
+{
+    public NoSuchValueException( String valueType, String moduleName, TypeLookup typeLookup )
+    {
+        super( "ValueComposite", valueType, moduleName, formatVisibleTypes(typeLookup) );
+    }
+
+    private static String formatVisibleTypes( TypeLookup typeLookup )
+    {
+        return typeLookup.allValues()
+            .map(descriptor -> descriptor.primaryType().getName())
+            .collect( Collectors.joining( "\n", "Visible value types are:\n", "" ) );
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilder.java b/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilder.java
new file mode 100644
index 0000000..09105aa
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilder.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.api.value;
+
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.common.ConstructionException;
+
+/**
+ * Builder for Values.
+ *
+ * @param <T> Value type
+ */
+public interface ValueBuilder<T>
+{
+    AssociationStateHolder state();
+
+    /**
+     * Get a representation of the state for the new Value.
+     * It is possible to access and update properties and associations,
+     * even immutable ones since the builder represents the initial state.
+     *
+     * @return a mutable instance of the Value type
+     */
+    T prototype();
+
+    /**
+     * Get a representation of the state of the given type for the new ValueComposite.
+     * This is primarily used if you want to provide state for a private mixin type.
+     *
+     * @param <K> Mixin type
+     * @param mixinType the mixin which you want to provide state for
+     *
+     * @return a proxy implementing the given mixin type
+     */
+    <K> K prototypeFor( Class<K> mixinType );
+
+    /**
+     * Create a new Composite instance.
+     *
+     * @return a new Composite instance
+     *
+     * @throws org.apache.polygene.api.common.ConstructionException
+     *          thrown if it was not possible to instantiate the Composite
+     */
+    T newInstance()
+        throws ConstructionException;
+
+    /** Returns the primaryType that this builder is configured to build.
+     *
+     * @return the primaryType to be built.
+     */
+    Class<T> primaryType();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilderFactory.java b/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilderFactory.java
new file mode 100644
index 0000000..510c373
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilderFactory.java
@@ -0,0 +1,112 @@
+/*
+ *  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.polygene.api.value;
+
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.property.PropertyDescriptor;
+
+/**
+ * Factory for Values and ValueBuilders.
+ */
+public interface ValueBuilderFactory
+{
+
+    /**
+     * Instantiate a Value of the given type.
+     *
+     * @param <T> Value type
+     * @param valueType the Value type to instantiate
+     *
+     * @return a new Value instance
+     *
+     * @throws NoSuchValueException if no value extending the mixinType has been registered
+     * @throws ConstructionException if the value could not be instantiated
+     */
+    <T> T newValue( Class<T> valueType )
+        throws NoSuchValueException, ConstructionException;
+
+    /**
+     * Create a builder for creating new Values that implements the given Value type.
+     * <p>The returned ValueBuilder can be reused to create several Values instances.</p>
+     *
+     * @param <T> Value type
+     * @param valueType an interface that describes the Composite to be instantiated
+     *
+     * @return a ValueBuilder for creation of ValueComposites implementing the interface
+     *
+     * @throws NoSuchValueException if no value extending the mixinType has been registered
+     */
+    <T> ValueBuilder<T> newValueBuilder( Class<T> valueType )
+        throws NoSuchValueException;
+
+    /**
+     * Create a builder for creating a new Value starting with the given prototype.
+     * <p>The returned ValueBuilder can only be used ONCE.</p>
+     *
+     * @param <T> Value type
+     * @param prototype a prototype the builder will use
+     *
+     * @return a ValueBuilder for creation of ValueComposites implementing the interface of the prototype
+     *
+     * @throws NoSuchValueException if no value extending the mixinType has been registered
+     */
+    <T> ValueBuilder<T> newValueBuilderWithPrototype( T prototype );
+
+    /**
+     * Create a builder for creating a new Value starting with the given state.
+     * <p>The returned ValueBuilder can only be used ONCE.</p>
+     *
+     * @param <T> Value type
+     * @param mixinType an interface that describes the Composite to be instantiated
+     * @param propertyFunction a function providing the state of properties
+     * @param associationFunction a function providing the state of associations
+     * @param manyAssociationFunction a function providing the state of many associations
+     * @param namedAssociationFunction a function providing the state of named associations
+     *
+     * @return a ValueBuilder for creation of ValueComposites implementing the interface
+     *
+     * @throws NoSuchValueException if no value extending the mixinType has been registered
+     */
+    <T> ValueBuilder<T> newValueBuilderWithState( Class<T> mixinType,
+                                                  Function<PropertyDescriptor, Object> propertyFunction,
+                                                  Function<AssociationDescriptor, EntityReference> associationFunction,
+                                                  Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction,
+                                                  Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction );
+
+    /**
+     * Instantiate a Value of the given type using the serialized state given as String.
+     *
+     * @param <T> Value type
+     * @param valueType the Value type to instantiate
+     * @param serializedState  the state of the Value
+     *
+     * @return a new Value instance
+     *
+     * @throws NoSuchValueException if no value extending the mixinType has been registered
+     * @throws ConstructionException if the value could not be instantiated
+     */
+    <T> T newValueFromSerializedState( Class<T> valueType, String serializedState );
+
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilderTemplate.java b/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilderTemplate.java
new file mode 100644
index 0000000..59fd667
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilderTemplate.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.api.value;
+
+import org.apache.polygene.api.structure.ModuleDescriptor;
+
+/**
+ * Builder template for Values.
+ */
+public abstract class ValueBuilderTemplate<T>
+{
+    Class<T> type;
+
+    protected ValueBuilderTemplate( Class<T> type )
+    {
+        this.type = type;
+    }
+
+    protected abstract void build( T prototype );
+
+    public T newInstance( ModuleDescriptor module )
+    {
+        ValueBuilder<T> builder = module.instance().newValueBuilder( type );
+        build( builder.prototype() );
+        return builder.newInstance();
+    }
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/ValueComposite.java b/core/api/src/main/java/org/apache/polygene/api/value/ValueComposite.java
new file mode 100644
index 0000000..be0b54a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/value/ValueComposite.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.api.value;
+
+import org.apache.polygene.api.association.AssociationMixin;
+import org.apache.polygene.api.association.ManyAssociationMixin;
+import org.apache.polygene.api.association.NamedAssociationMixin;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Immutable;
+
+/**
+ * ValueComposites are Composites that has state, and equality is defined from its values and not any reference nor
+ * instance references.
+ *
+ * <ul>
+ * <li>No Identity</li>
+ * <li>No Lifecycle</li>
+ * <li>Immutable</li>
+ * <li>equals()/hashCode() operates on the Properties</li>
+ * <li>Can have property and associations methods.</li>
+ * <li>Can not reference Services</li>
+ * <li>Can not have @Uses</li>
+ * </ul>
+ */
+@Immutable
+@Mixins( { AssociationMixin.class, ManyAssociationMixin.class, NamedAssociationMixin.class } )
+public interface ValueComposite
+    extends Composite
+{
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/ValueDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/value/ValueDescriptor.java
new file mode 100644
index 0000000..c96340d
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/value/ValueDescriptor.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.api.value;
+
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.StatefulAssociationCompositeDescriptor;
+import org.apache.polygene.api.type.ValueCompositeType;
+
+/**
+ * Descriptor for ValueComposites.
+ */
+public interface ValueDescriptor
+    extends CompositeDescriptor, StatefulAssociationCompositeDescriptor
+{
+    @Override
+    ValueCompositeType valueType();
+}
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/package.html b/core/api/src/main/java/org/apache/polygene/api/value/package.html
new file mode 100644
index 0000000..def90fa
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/value/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Value API.</h2>
+    </body>
+</html>
diff --git a/core/api/src/main/java/org/qi4j/api/Qi4j.java b/core/api/src/main/java/org/qi4j/api/Qi4j.java
deleted file mode 100644
index cfd8a89..0000000
--- a/core/api/src/main/java/org/qi4j/api/Qi4j.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Proxy;
-import org.qi4j.api.association.AbstractAssociation;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.api.composite.InvalidCompositeException;
-import org.qi4j.api.composite.ModelDescriptor;
-import org.qi4j.api.composite.TransientDescriptor;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.functional.Function;
-
-/**
- * Encapsulation of the Zest API.
- */
-public interface Qi4j
-{
-    /**
-     * If a Modifier gets a reference to the Composite using @This,
-     * then that reference must be dereferenced using this method
-     * before handing it out for others to use.
-     *
-     * @param <T>       Parameterized type of the Composite
-     * @param composite instance reference injected in Modified using @This
-     *
-     * @return the dereferenced Composite
-     */
-    <T> T dereference( T composite );
-
-    /**
-     * Returns the Module or UnitOfWork where the Composite belongs.
-     *
-     * @param compositeOrUow The Composite (Service, Value, Entity or Transient) or UnitOfWork to lookup the Module it
-     *                       belongs to.
-     *
-     * @return The Module instance where the Composite or UnitOfWork belongs to.
-     */
-    Module moduleOf( Object compositeOrUow );
-
-    /**
-     * Returns the ModelDescriptor of the Composite.
-     *
-     * @param compositeOrServiceReference The Composite (Service, Value, Entity or Transient) for which to lookup the
-     *                                    ModelDescriptor
-     *
-     * @return The ModelDescriptor of the Composite
-     */
-    ModelDescriptor modelDescriptorFor( Object compositeOrServiceReference );
-
-    /**
-     * Returns the CompositeDescriptor of the Composite.
-     *
-     * @param compositeOrServiceReference The Composite (Service, Value, Entity or Transient) for which to lookup the
-     *                                    CompositeDescriptor
-     *
-     * @return The CompositeDescriptor of the Composite
-     */
-    CompositeDescriptor compositeDescriptorFor( Object compositeOrServiceReference );
-
-    /**
-     * Returns the TransientDescriptor of the TransientComposite.
-     *
-     * @param transsient The TransientComposite for which to lookup the TransientDescriptor
-     *
-     * @return The TransientDescriptor of the TransientComposite
-     */
-    TransientDescriptor transientDescriptorFor( Object transsient );
-
-    /**
-     * Returns the EntityDescriptor of the EntityComposite.
-     *
-     * @param entity The EntityComposite for which to lookup the EntityDescriptor
-     *
-     * @return The EntityDescriptor of the EntityComposite
-     */
-    EntityDescriptor entityDescriptorFor( Object entity );
-
-    /**
-     * Returns the ValueDescriptor of the ValueComposite.
-     *
-     * @param value The ValueComposite for which to lookup the ValueDescriptor
-     *
-     * @return The ValueDescriptor of the ValueComposite
-     */
-    ValueDescriptor valueDescriptorFor( Object value );
-
-    /**
-     * Returns the ServiceDescriptor of the ServiceComposite.
-     *
-     * @param service The ServiceComposite for which to lookup the ServiceDescriptor
-     *
-     * @return The ServiceDescriptor of the ServiceComposite
-     */
-    ServiceDescriptor serviceDescriptorFor( Object service );
-
-    /**
-     * Returns the PropertyDescriptor of the Property.
-     *
-     * @param property The Property for which to lookup the PropertyDescriptor
-     *
-     * @return The PropertyDescriptor of the Property
-     */
-    PropertyDescriptor propertyDescriptorFor( Property<?> property );
-
-    /**
-     * Returns the AssociationDescriptor of the Association.
-     *
-     * @param association The Association for which to lookup the AssociationDescriptor
-     *
-     * @return The AssociationDescriptor of the Association
-     */
-    AssociationDescriptor associationDescriptorFor( AbstractAssociation association );
-
-    /**
-     * Function that returns the CompositeDescriptor of a Composite.
-     */
-    Function<Composite, CompositeDescriptor> FUNCTION_DESCRIPTOR_FOR = new Function<Composite, CompositeDescriptor>()
-    {
-        @Override
-        public CompositeDescriptor map( Composite composite )
-        {
-            if( composite instanceof Proxy )
-            {
-                InvocationHandler invocationHandler = Proxy.getInvocationHandler( composite );
-                return ( (CompositeInstance) invocationHandler ).descriptor();
-            }
-            try
-            {
-                Class<? extends Composite> compositeClass = composite.getClass();
-                Field instanceField = compositeClass.getField( "_instance" );
-                Object instance = instanceField.get( composite );
-                return ( (CompositeInstance) instance ).descriptor();
-            }
-            catch( Exception e )
-            {
-                InvalidCompositeException exception = new InvalidCompositeException( "Could not get _instance field" );
-                exception.initCause( e );
-                throw exception;
-            }
-        }
-    };
-
-    /**
-     * Function that returns the CompositeInstance of a Composite.
-     */
-    Function<Composite, CompositeInstance> FUNCTION_COMPOSITE_INSTANCE_OF = new Function<Composite, CompositeInstance>()
-    {
-        @Override
-        public CompositeInstance map( Composite composite )
-        {
-            if( composite instanceof Proxy )
-            {
-                return ( (CompositeInstance) Proxy.getInvocationHandler( composite ) );
-            }
-            try
-            {
-                Class<? extends Composite> compositeClass = composite.getClass();
-                Field instanceField = compositeClass.getField( "_instance" );
-                Object instance = instanceField.get( composite );
-                return (CompositeInstance) instance;
-            }
-            catch( Exception e )
-            {
-                InvalidCompositeException exception = new InvalidCompositeException( "Could not get _instance field" );
-                exception.initCause( e );
-                throw exception;
-            }
-        }
-    };
-}
diff --git a/core/api/src/main/java/org/qi4j/api/activation/Activation.java b/core/api/src/main/java/org/qi4j/api/activation/Activation.java
deleted file mode 100644
index 32f26e4..0000000
--- a/core/api/src/main/java/org/qi4j/api/activation/Activation.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg.
- * Copyright (c) 2012, Niclas Hedhman.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.api.activation;
-
-/**
- * Interface used by Structure elements and Services that can be activated and passivated.
- * <p>Application and Layer expose this interface so you can activate and passivate them.</p>
- * <p>Module and ServiceComposite activation/passivation is handled by the Zest runtime.</p>
- */
-public interface Activation
-{
-    /**
-     * Activate.
-     * <p>Fail fast execution order is:</p>
-     * <ul>
-     *   <li>Fire {@link ActivationEvent.EventType#ACTIVATING}</li>
-     *   <li>Call {@link Activator#beforeActivation(java.lang.Object)} on each Activator</li>
-     *   <li>Call {@link #activate()} children</li>
-     *   <li>Call {@link Activator#afterActivation(java.lang.Object)} on each Activator</li>
-     *   <li>Fire {@link ActivationEvent.EventType#ACTIVATED}</li>
-     * </ul>
-     * <p>If an Exception is thrown, already activated nodes are passivated.</p>
-     * @throws ActivationException with first Exception of activation plus the PassivationException if any
-     */
-    void activate()
-        throws ActivationException;
-
-    /**
-     * Passivate.
-     * <p>Fail safe execution order is:</p>
-     * <ul>
-     *   <li>Fire {@link ActivationEvent.EventType#PASSIVATING}</li>
-     *   <li>Call {@link Activator#beforePassivation(java.lang.Object)} on each Activator</li>
-     *   <li>Call {@link #passivate()} children</li>
-     *   <li>Call {@link Activator#afterPassivation(java.lang.Object)} on each Activator</li>
-     *   <li>Fire {@link ActivationEvent.EventType#PASSIVATED}</li>
-     * </ul>
-     * @throws PassivationException after passivation with all Exceptions of passivation if any
-     */
-    void passivate()
-        throws PassivationException;
-}
diff --git a/core/api/src/main/java/org/qi4j/api/activation/ActivationEvent.java b/core/api/src/main/java/org/qi4j/api/activation/ActivationEvent.java
deleted file mode 100644
index 1852251..0000000
--- a/core/api/src/main/java/org/qi4j/api/activation/ActivationEvent.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed 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.qi4j.api.activation;
-
-/**
- * ActivationEvents are fired during activation and passivation of instances in Zest.
- */
-public final class ActivationEvent
-{
-    public enum EventType
-    {
-        ACTIVATING, ACTIVATED, PASSIVATING, PASSIVATED
-    }
-
-    private final long timestamp;
-    private final Object source;
-    private final EventType type;
-
-    public ActivationEvent( Object source, EventType type )
-    {
-        this.timestamp = System.currentTimeMillis();
-        this.source = source;
-        this.type = type;
-    }
-
-    /**
-     * @return the source of the Activation event
-     */
-    public Object source()
-    {
-        return source;
-    }
-
-    /**
-     * @return the type of the Activation event
-     */
-    public EventType type()
-    {
-        return type;
-    }
-
-    /**
-     * @return an informative message describing the event
-     */
-    public String message()
-    {
-        switch( type )
-        {
-        case ACTIVATING:
-            return "Activating " + source;
-        case ACTIVATED:
-            return "Activated " + source;
-        case PASSIVATING:
-            return "Passivating " + source;
-        case PASSIVATED:
-            return "Passivated " + source;
-        }
-        return "";
-    }
-
-    /**
-     * @see #message()
-     */
-    @Override
-    public String toString()
-    {
-        return message();
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/activation/ActivationEventListener.java b/core/api/src/main/java/org/qi4j/api/activation/ActivationEventListener.java
deleted file mode 100644
index 3562c6e..0000000
--- a/core/api/src/main/java/org/qi4j/api/activation/ActivationEventListener.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed 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.qi4j.api.activation;
-
-/**
- * Listener for ActivationEvent events
- */
-public interface ActivationEventListener
-{
-    void onEvent( ActivationEvent event )
-        throws Exception;
-}
diff --git a/core/api/src/main/java/org/qi4j/api/activation/ActivationEventListenerRegistration.java b/core/api/src/main/java/org/qi4j/api/activation/ActivationEventListenerRegistration.java
deleted file mode 100644
index 41e3b5e..0000000
--- a/core/api/src/main/java/org/qi4j/api/activation/ActivationEventListenerRegistration.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed 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.qi4j.api.activation;
-
-/**
- * Use this to register listeners for ActivationEvents.
- *
- * This is implemented by Application, Layer, Module, for example.
- */
-public interface ActivationEventListenerRegistration
-{
-    /**
-     * @param listener will be notified when Activation events occur
-     */
-    void registerActivationEventListener( ActivationEventListener listener );
-
-    /**
-     * @param listener will not be notified when Activation events occur anymore
-     */
-    void deregisterActivationEventListener( ActivationEventListener listener );
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/activation/ActivationException.java b/core/api/src/main/java/org/qi4j/api/activation/ActivationException.java
deleted file mode 100644
index 30d06be..0000000
--- a/core/api/src/main/java/org/qi4j/api/activation/ActivationException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2013 Niclas Hedhman.
- *
- * Licensed  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.qi4j.api.activation;
-
-/**
- * Thrown when unable to activate.
- */
-public class ActivationException extends Exception
-{
-    private static final long serialVersionUID = 1L;
-    public ActivationException( String message, Throwable cause )
-    {
-        super( message, cause );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/activation/Activator.java b/core/api/src/main/java/org/qi4j/api/activation/Activator.java
deleted file mode 100644
index 2cba184..0000000
--- a/core/api/src/main/java/org/qi4j/api/activation/Activator.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.api.activation;
-
-/**
- * Assemble Activators to hook Services Activation.
- *
- * @param <ActivateeType> Type of the activatee.
- *
- * @see ActivatorAdapter
- * @see org.qi4j.api.service.ServiceActivation
- */
-public interface Activator<ActivateeType>
-{
-
-    /**
-     * Called before activatee activation.
-     */
-    void beforeActivation( ActivateeType activating )
-        throws Exception;
-
-    /**
-     * Called after activatee activation.
-     */
-    void afterActivation( ActivateeType activated )
-        throws Exception;
-
-    /**
-     * Called before activatee passivation.
-     */
-    void beforePassivation( ActivateeType passivating )
-        throws Exception;
-
-    /**
-     * Called after activatee passivation.
-     */
-    void afterPassivation( ActivateeType passivated )
-        throws Exception;
-}
diff --git a/core/api/src/main/java/org/qi4j/api/activation/ActivatorAdapter.java b/core/api/src/main/java/org/qi4j/api/activation/ActivatorAdapter.java
deleted file mode 100644
index 59652b9..0000000
--- a/core/api/src/main/java/org/qi4j/api/activation/ActivatorAdapter.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.api.activation;
-
-/**
- * Adapter for Activator.
- * <p>If you are thinking about Service activation, see {@link org.qi4j.api.service.ServiceActivatorAdapter}.</p>
- *
- * @param <ActivateeType> Type of the activatee.
- */
-public class ActivatorAdapter<ActivateeType>
-    implements Activator<ActivateeType>
-{
-    /**
-     * Called before activatee activation.
-     * @param activating Activating activatee
-     */
-    @Override
-    public void beforeActivation( ActivateeType activating )
-        throws Exception
-    {
-    }
-
-    /**
-     * Called after activatee activation.
-     * @param activated Activating activatee
-     */
-    @Override
-    public void afterActivation( ActivateeType activated )
-        throws Exception
-    {
-    }
-
-    /**
-     * Called before activatee passivation.
-     * @param passivating Passivating activatee
-     */
-    @Override
-    public void beforePassivation( ActivateeType passivating )
-        throws Exception
-    {
-    }
-
-    /**
-     * Called after activatee passivation.
-     * @param passivated Passivated activatee
-     */
-    @Override
-    public void afterPassivation( ActivateeType passivated )
-        throws Exception
-    {
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/activation/ActivatorDescriptor.java b/core/api/src/main/java/org/qi4j/api/activation/ActivatorDescriptor.java
deleted file mode 100644
index bfe3fee..0000000
--- a/core/api/src/main/java/org/qi4j/api/activation/ActivatorDescriptor.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.api.activation;
-
-/**
- * Activator Descriptor.
- */
-public interface ActivatorDescriptor
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/activation/Activators.java b/core/api/src/main/java/org/qi4j/api/activation/Activators.java
deleted file mode 100644
index 8d0f7e6..0000000
--- a/core/api/src/main/java/org/qi4j/api/activation/Activators.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.api.activation;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This annotation is used in ServiceComposites to declare Activator implementation classes.
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( ElementType.TYPE )
-@Documented
-public @interface Activators
-{
-
-    /**
-     * @return Activator implementation classes.
-     */
-    Class<? extends Activator<?>>[] value();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/activation/ApplicationPassivationThread.java b/core/api/src/main/java/org/qi4j/api/activation/ApplicationPassivationThread.java
deleted file mode 100644
index 62b1f67..0000000
--- a/core/api/src/main/java/org/qi4j/api/activation/ApplicationPassivationThread.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2013 Paul Merlin.
- *
- * Licensed  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.qi4j.api.activation;
-
-import java.io.PrintStream;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import org.qi4j.api.structure.Application;
-
-/**
- * Application Passivation Thread to use as a Shutdown Hook.
- * <pre>Runtime.getRuntime().addShutdownHook( new ApplicationPassivationThread( application ) );</pre>
- * <p>Constructors to control where errors are logged are provided. They support PrintStream (STDOUT/STDERR) and SLF4J
- * Loggers. Defaults to STDERR.</p>
- */
-public final class ApplicationPassivationThread
-    extends Thread
-{
-    /**
-     * Create a new Application Passivation Thread that output errors to STDERR.
-     * @param application The Application to passivate
-     */
-    public ApplicationPassivationThread( final Application application )
-    {
-        this( application, null, null );
-    }
-
-    /**
-     * Create a new Application Passivation Thread that output errors to a Logger.
-     * @param application The Application to passivate
-     * @param logger Logger for errors
-     */
-    public ApplicationPassivationThread( Application application, Logger logger )
-    {
-        this( application, null, logger );
-    }
-
-    /**
-     * Create a new Application Passivation Thread that output errors to a PrintStream.
-     * @param application The Application to passivate
-     * @param output PrintStream for errors
-     */
-    public ApplicationPassivationThread( Application application, PrintStream output )
-    {
-        this( application, output, null );
-    }
-
-    private ApplicationPassivationThread( Application application, PrintStream output, Logger logger )
-    {
-        super( new ApplicationPassivation( application, output, logger ),
-               application.name() + " Passivation Thread" );
-    }
-
-    private static class ApplicationPassivation
-        implements Runnable
-    {
-
-        private final Application application;
-        private final PrintStream output;
-        private final Logger logger;
-
-        private ApplicationPassivation( Application application, PrintStream output, Logger logger )
-        {
-            this.application = application;
-            this.output = output;
-            this.logger = logger;
-        }
-
-        @Override
-        public void run()
-        {
-            try
-            {
-                application.passivate();
-            }
-            catch( PassivationException ex )
-            {
-                String message = application.name() + " " + ex.getMessage();
-                if( logger != null )
-                {
-                    logger.log( Level.SEVERE, message, ex );
-                }
-                else if( output != null )
-                {
-                    output.println( message );
-                    ex.printStackTrace( output );
-                }
-                else
-                {
-                    ex.printStackTrace();
-                }
-            }
-        }
-
-    }
-
-}
diff --git a/core/api/src/main/java/org/qi4j/api/activation/PassivationException.java b/core/api/src/main/java/org/qi4j/api/activation/PassivationException.java
deleted file mode 100644
index c3f33fe..0000000
--- a/core/api/src/main/java/org/qi4j/api/activation/PassivationException.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- * Copyright 2013 Paul Merlin.
- *
- * Licensed  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.qi4j.api.activation;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * Thrown when unable to passivate.
- *
- * Printed StackTrace contains all causes in order as suppressed exceptions.
- */
-public final class PassivationException
-    extends Exception
-{
-
-    private static final long serialVersionUID = 1L;
-    private final List<Exception> causes;
-
-    /**
-     * Create new PassivationException.
-     * @param exceptions All exceptions encountered during passivation, in order
-     */
-    public PassivationException( Collection<Exception> exceptions )
-    {
-        super( "Passivation Exception - [has " + exceptions.size() + " cause(s)]" );
-        for( Throwable cause : exceptions )
-        {
-            addSuppressed( cause );
-        }
-        this.causes = new ArrayList<>( exceptions );
-    }
-
-    /**
-     * @return All exceptions encountered during passivation, in order
-     */
-    public List<Exception> causes()
-    {
-        return causes;
-    }
-
-}
diff --git a/core/api/src/main/java/org/qi4j/api/activation/package.html b/core/api/src/main/java/org/qi4j/api/activation/package.html
deleted file mode 100644
index 47b333a..0000000
--- a/core/api/src/main/java/org/qi4j/api/activation/package.html
+++ /dev/null
@@ -1,26 +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.
--->
-<html>
-    <body>
-        <h2>Activation API.</h2>
-        <p>
-            The Activation API package contains types used by client code to integrate with the Zest™ Runtime activation
-            mechanism. In assembly, client code can easily listen to Structure (Application, Layers and Modules) and
-            Services activation events, or, declare Structure and Service Activators.
-        </p>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/association/AbstractAssociation.java b/core/api/src/main/java/org/qi4j/api/association/AbstractAssociation.java
deleted file mode 100644
index 60afce2..0000000
--- a/core/api/src/main/java/org/qi4j/api/association/AbstractAssociation.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.association;
-
-/**
- * Base interface for all associations.
- */
-public interface AbstractAssociation
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/association/Association.java b/core/api/src/main/java/org/qi4j/api/association/Association.java
deleted file mode 100644
index acd406f..0000000
--- a/core/api/src/main/java/org/qi4j/api/association/Association.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.association;
-
-import org.qi4j.api.entity.EntityReference;
-
-/**
- * Association to a single EntityComposite.
- */
-public interface Association<T> extends AbstractAssociation
-{
-    /**
-     * Get the associated entity.
-     *
-     * @return the associated entity
-     */
-    T get();
-
-    /**
-     * Set the associated entity.
-     *
-     * @param associated the entity
-     *
-     * @throws IllegalArgumentException thrown if the entity is not a valid reference for this association
-     * @throws IllegalStateException    thrown if association is immutable
-     */
-    void set( T associated )
-        throws IllegalArgumentException, IllegalStateException;
-
-    /**
-     * @return the the reference of the associated entity.
-     */
-    EntityReference reference();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/association/AssociationDescriptor.java b/core/api/src/main/java/org/qi4j/api/association/AssociationDescriptor.java
deleted file mode 100644
index 9f7576a..0000000
--- a/core/api/src/main/java/org/qi4j/api/association/AssociationDescriptor.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.association;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Type;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.structure.MetaInfoHolder;
-
-/**
- * Association Descriptor.
- */
-public interface AssociationDescriptor extends MetaInfoHolder
-{
-    /**
-     * Get the qualified name of the association. This is constructed by
-     * concatenating the name of the declaring interface with the name
-     * of the method, using ":" as separator.
-     * <p>
-     * Example:
-     * </p>
-     * <p>
-     * com.somecompany.MyInterface with association method
-     * </p>
-     * <pre><code>
-     * Association&lt;String&gt; someAssociation();
-     * </code></pre>
-     * will have the qualified name:
-     * <pre><code>
-     * com.somecompany.MyInterface:someAssociation
-     * </code></pre>
-     *
-     * @return the qualified name of the association
-     */
-    QualifiedName qualifiedName();
-
-    /**
-     * Get the type of the associated Entities
-     *
-     * @return the type of the associated Entities
-     */
-    Type type();
-
-    boolean isImmutable();
-
-    boolean isAggregated();
-
-    AccessibleObject accessor();
-
-    boolean queryable();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/association/AssociationMixin.java b/core/api/src/main/java/org/qi4j/api/association/AssociationMixin.java
deleted file mode 100644
index ac26de3..0000000
--- a/core/api/src/main/java/org/qi4j/api/association/AssociationMixin.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.association;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.AppliesToFilter;
-import org.qi4j.api.injection.scope.State;
-
-/**
- * Generic mixin for associations.
- */
-@AppliesTo( { AssociationMixin.AssociationFilter.class } )
-public final class AssociationMixin
-    implements InvocationHandler
-{
-    @State
-    private AssociationStateHolder associations;
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        return associations.associationFor( method );
-    }
-
-    /**
-     * Associations generic mixin AppliesToFilter.
-     */
-    public static class AssociationFilter
-        implements AppliesToFilter
-    {
-        @Override
-        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> modifierClass )
-        {
-            return Association.class.isAssignableFrom( method.getReturnType() );
-        }
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/association/AssociationStateDescriptor.java b/core/api/src/main/java/org/qi4j/api/association/AssociationStateDescriptor.java
deleted file mode 100644
index 83c04a4..0000000
--- a/core/api/src/main/java/org/qi4j/api/association/AssociationStateDescriptor.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.api.association;
-
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.composite.StateDescriptor;
-
-/**
- * Associations State Descriptor.
- */
-public interface AssociationStateDescriptor extends StateDescriptor
-{
-    AssociationDescriptor getAssociationByName( String name )
-        throws IllegalArgumentException;
-
-    AssociationDescriptor getAssociationByQualifiedName( QualifiedName name )
-        throws IllegalArgumentException;
-
-    AssociationDescriptor getManyAssociationByName( String name )
-        throws IllegalArgumentException;
-
-    AssociationDescriptor getManyAssociationByQualifiedName( QualifiedName name )
-        throws IllegalArgumentException;
-
-    AssociationDescriptor getNamedAssociationByName( String name )
-        throws IllegalArgumentException;
-
-    AssociationDescriptor getNamedAssociationByQualifiedName( QualifiedName name )
-        throws IllegalArgumentException;
-
-    Iterable<? extends AssociationDescriptor> associations();
-
-    Iterable<? extends AssociationDescriptor> manyAssociations();
-
-    Iterable<? extends AssociationDescriptor> namedAssociations();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/association/AssociationStateHolder.java b/core/api/src/main/java/org/qi4j/api/association/AssociationStateHolder.java
deleted file mode 100644
index e33ff7f..0000000
--- a/core/api/src/main/java/org/qi4j/api/association/AssociationStateHolder.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.api.association;
-
-import java.lang.reflect.AccessibleObject;
-import org.qi4j.api.property.StateHolder;
-
-/**
- * This represents the state of a entity (properties+associations).
- */
-public interface AssociationStateHolder
-    extends StateHolder
-{
-    /**
-     * Get an association for a specific accessor method
-     *
-     * @param associationMethod for the association
-     *
-     * @return the association
-     */
-    <T> Association<T> associationFor( AccessibleObject associationMethod );
-
-    /**
-     * Get all associations
-     *
-     * @return iterable of associations
-     */
-    Iterable<? extends Association<?>> allAssociations();
-
-    /**
-     * Get a many-association for a specific accessor method
-     *
-     * @param manyassociationMethod for the many-association
-     *
-     * @return the association
-     */
-    <T> ManyAssociation<T> manyAssociationFor( AccessibleObject manyassociationMethod );
-
-    /**
-     * Get all ManyAssociations
-     *
-     * @return iterable of many-associations
-     */
-    Iterable<? extends ManyAssociation<?>> allManyAssociations();
-
-    /**
-     * Get a named-association for a specific accessor method
-     *
-     * @param namedassociationMethod for the named-association
-     *
-     * @return the association
-     */
-    <T> NamedAssociation<T> namedAssociationFor( AccessibleObject namedassociationMethod );
-
-    /**
-     * Get all NmaedAssociations
-     *
-     * @return iterable of named-associations
-     */
-    Iterable<? extends NamedAssociation<?>> allNamedAssociations();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/association/AssociationWrapper.java b/core/api/src/main/java/org/qi4j/api/association/AssociationWrapper.java
deleted file mode 100644
index 68777b3..0000000
--- a/core/api/src/main/java/org/qi4j/api/association/AssociationWrapper.java
+++ /dev/null
@@ -1,79 +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.qi4j.api.association;
-
-import org.qi4j.api.entity.EntityReference;
-
-/**
- * If you want to catch getting and setting association, then create a GenericConcern
- * that wraps the Zest-supplied Association instance with AssociationWrappers. Override
- * get() and/or set() to perform your custom code.
- */
-public class AssociationWrapper
-    implements Association<Object>
-{
-    protected Association<Object> next;
-
-    public AssociationWrapper( Association<Object> next )
-    {
-        this.next = next;
-    }
-
-    public Association<Object> next()
-    {
-        return next;
-    }
-
-    @Override
-    public Object get()
-    {
-        return next.get();
-    }
-
-    @Override
-    public void set( Object associated )
-        throws IllegalArgumentException
-    {
-        next.set( associated );
-    }
-
-    @Override
-    public EntityReference reference()
-    {
-        return next.reference();
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return next.hashCode();
-    }
-
-    @Override
-    public boolean equals( Object obj )
-    {
-        return next.equals( obj );
-    }
-
-    @Override
-    public String toString()
-    {
-        return next.toString();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/association/GenericAssociationInfo.java b/core/api/src/main/java/org/qi4j/api/association/GenericAssociationInfo.java
deleted file mode 100644
index 7173547..0000000
--- a/core/api/src/main/java/org/qi4j/api/association/GenericAssociationInfo.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.api.association;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-
-import static org.qi4j.api.util.Classes.typeOf;
-
-/**
- * Generic Association info.
- */
-public final class GenericAssociationInfo
-{
-    public static Type associationTypeOf( AccessibleObject accessor )
-    {
-        return toAssociationType( typeOf( accessor ) );
-    }
-
-    public static Type toAssociationType( Type methodReturnType )
-    {
-        if( methodReturnType instanceof ParameterizedType )
-        {
-            ParameterizedType parameterizedType = (ParameterizedType) methodReturnType;
-            if( AbstractAssociation.class.isAssignableFrom( (Class<?>) parameterizedType.getRawType() ) )
-            {
-                return parameterizedType.getActualTypeArguments()[ 0 ];
-            }
-        }
-
-        Type[] interfaces = ( (Class<?>) methodReturnType ).getGenericInterfaces();
-        for( Type anInterface : interfaces )
-        {
-            Type associationType = toAssociationType( anInterface );
-            if( associationType != null )
-            {
-                return associationType;
-            }
-        }
-        return null;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/association/ManyAssociation.java b/core/api/src/main/java/org/qi4j/api/association/ManyAssociation.java
deleted file mode 100644
index 37d7211..0000000
--- a/core/api/src/main/java/org/qi4j/api/association/ManyAssociation.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.association;
-
-import java.util.List;
-import java.util.Set;
-import org.qi4j.api.entity.EntityReference;
-
-/**
- * Association to a collection of entities.
- */
-public interface ManyAssociation<T> extends Iterable<T>, AbstractAssociation
-{
-    /**
-     * Returns the number of references in this association.
-     * @return the number of references in this association.
-     */
-    int count();
-
-    boolean contains( T entity );
-
-    boolean add( int i, T entity );
-
-    boolean add( T entity );
-
-    boolean remove( T entity );
-
-    T get( int i );
-
-    List<T> toList();
-
-    Set<T> toSet();
-
-    /**
-     * Returns an unmodifiable Iterable of the references to the associated entities.
-     * @return the references to the associated entities.
-     */
-    Iterable<EntityReference> references();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/association/ManyAssociationMixin.java b/core/api/src/main/java/org/qi4j/api/association/ManyAssociationMixin.java
deleted file mode 100644
index 5b2177d..0000000
--- a/core/api/src/main/java/org/qi4j/api/association/ManyAssociationMixin.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.association;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.AppliesToFilter;
-import org.qi4j.api.injection.scope.State;
-
-/**
- * Generic mixin for associations.
- */
-@AppliesTo( { ManyAssociationMixin.AssociationFilter.class } )
-public final class ManyAssociationMixin
-    implements InvocationHandler
-{
-    @State
-    private AssociationStateHolder associations;
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        return associations.manyAssociationFor( method );
-    }
-
-    /**
-     * ManyAssociations generic mixin AppliesToFilter.
-     */
-    public static class AssociationFilter
-        implements AppliesToFilter
-    {
-        @Override
-        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> modifierClass )
-        {
-            return ManyAssociation.class.isAssignableFrom( method.getReturnType() );
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/association/ManyAssociationWrapper.java b/core/api/src/main/java/org/qi4j/api/association/ManyAssociationWrapper.java
deleted file mode 100644
index aee7804..0000000
--- a/core/api/src/main/java/org/qi4j/api/association/ManyAssociationWrapper.java
+++ /dev/null
@@ -1,123 +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.qi4j.api.association;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import org.qi4j.api.entity.EntityReference;
-
-/**
- * If you want to catch calls to ManyAssociations, then create a GenericConcern
- * that wraps the Zest-supplied ManyAssociation instance with ManyAssociationWrappers. Override
- * methods to perform your custom code.
- */
-public class ManyAssociationWrapper
-    implements ManyAssociation<Object>
-{
-    protected ManyAssociation<Object> next;
-
-    public ManyAssociationWrapper( ManyAssociation<Object> next )
-    {
-        this.next = next;
-    }
-
-    public ManyAssociation<Object> next()
-    {
-        return next;
-    }
-
-    @Override
-    public int count()
-    {
-        return next.count();
-    }
-
-    @Override
-    public boolean contains( Object entity )
-    {
-        return next.contains( entity );
-    }
-
-    @Override
-    public boolean add( int i, Object entity )
-    {
-        return next.add( i, entity );
-    }
-
-    @Override
-    public boolean add( Object entity )
-    {
-        return next.add( entity );
-    }
-
-    @Override
-    public boolean remove( Object entity )
-    {
-        return next.remove( entity );
-    }
-
-    @Override
-    public Object get( int i )
-    {
-        return next.get( i );
-    }
-
-    @Override
-    public List<Object> toList()
-    {
-        return next.toList();
-    }
-
-    @Override
-    public Set<Object> toSet()
-    {
-        return next.toSet();
-    }
-
-    @Override
-    public Iterable<EntityReference> references()
-    {
-        return next.references();
-    }
-
-    @Override
-    public Iterator<Object> iterator()
-    {
-        return next.iterator();
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return next.hashCode();
-    }
-
-    @Override
-    public boolean equals( Object obj )
-    {
-        return next.equals( obj );
-    }
-
-    @Override
-    public String toString()
-    {
-        return next.toString();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/association/NamedAssociation.java b/core/api/src/main/java/org/qi4j/api/association/NamedAssociation.java
deleted file mode 100644
index 61c9c9a..0000000
--- a/core/api/src/main/java/org/qi4j/api/association/NamedAssociation.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2011-2012, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.api.association;
-
-import java.util.Map;
-import org.qi4j.api.entity.EntityReference;
-
-/**
- * Association to named Entities.
- * The Iterable&lt;String&gt; returns the names in the association set.
- * @param <T> Parameterized associatee type
- */
-public interface NamedAssociation<T>
-    extends Iterable<String>, AbstractAssociation
-{
-    /**
-     * @return The number of named associations in this NamedAssociation.
-     */
-    int count();
-
-    /**
-     * Checks if there is an association with the given name.
-     * @param name The name of the association we are checking if it exists.
-     * @return true if it exists, false otherwise
-     */
-    boolean containsName( String name );
-
-    /**
-     * Adds a named assocation.
-     * @param name The name of the association.
-     * @param entity The entity for this named association.
-     * @return true if putted, false otherwise
-     */
-    boolean put( String name, T entity );
-
-    /**
-     * Remove a named association.
-     * @param name The name of the association.
-     * @return true if removed, false otherwise
-     */
-    boolean remove( String name );
-
-    /**
-     * Retrieves a named association.
-     * @param name The name of the association.
-     * @return The entity that has previously been associated.
-     */
-    T get( String name );
-
-    /**
-     * Checks if the entity is present.
-     * Note that this is potentially a very slow operation, depending on the size of the NamedAssociation.
-     * @param entity The entity to look for.
-     * @return The name of the entity if found, otherwise null.
-     */
-    String nameOf( T entity );
-
-    /**
-     * @return A fully populated Map with the content of this NamedAssociation.
-     */
-    Map<String, T> toMap();
-
-    /**
-     * Returns an unmodifiable Iterable of the references to the associated entities.
-     * @return the references to the associated entities.
-     */
-    Iterable<EntityReference> references();
-
-    /** Returns the EntityReference for the Association with the given name.
-     *
-     * @param name The name of the association to return the EntityReference for
-     * @return The EntityReference of the association.
-     */
-    EntityReference referenceOf( String name );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/association/NamedAssociationMixin.java b/core/api/src/main/java/org/qi4j/api/association/NamedAssociationMixin.java
deleted file mode 100644
index d612ed6..0000000
--- a/core/api/src/main/java/org/qi4j/api/association/NamedAssociationMixin.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2011-2012, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.api.association;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.AppliesToFilter;
-import org.qi4j.api.injection.scope.State;
-
-/**
- * Generic mixin for NamedAssociations.
- */
-@AppliesTo( NamedAssociationMixin.AssociationFilter.class )
-public final class NamedAssociationMixin
-    implements InvocationHandler
-{
-    @State
-    private AssociationStateHolder associations;
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        return associations.namedAssociationFor( method );
-    }
-
-    /**
-     * NamedAssociations generic mixin AppliesToFilter.
-     */
-    public static class AssociationFilter
-        implements AppliesToFilter
-    {
-        @Override
-        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> modifierClass )
-        {
-            return NamedAssociation.class.isAssignableFrom( method.getReturnType() );
-        }
-    }
-
-}
diff --git a/core/api/src/main/java/org/qi4j/api/association/NamedAssociationWrapper.java b/core/api/src/main/java/org/qi4j/api/association/NamedAssociationWrapper.java
deleted file mode 100644
index 814644a..0000000
--- a/core/api/src/main/java/org/qi4j/api/association/NamedAssociationWrapper.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2011-2012, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.api.association;
-
-import java.util.Iterator;
-import java.util.Map;
-import org.qi4j.api.entity.EntityReference;
-
-/**
- * If you want to catch calls to NamedAssociations, then create a GenericConcern
- * that wraps the Zest-supplied NamedAssociations instance with NamedAssociationsWrapper. Override
- * methods to perform your custom code.
- */
-public class NamedAssociationWrapper
-    implements NamedAssociation<Object>
-{
-    protected NamedAssociation<Object> next;
-
-    public NamedAssociationWrapper( NamedAssociation<Object> next )
-    {
-        this.next = next;
-    }
-
-    public NamedAssociation<Object> next()
-    {
-        return next;
-    }
-
-    @Override
-    public Iterator<String> iterator()
-    {
-        return next.iterator();
-    }
-
-    @Override
-    public int count()
-    {
-        return next.count();
-    }
-
-    @Override
-    public boolean containsName( String name )
-    {
-        return next.containsName( name );
-    }
-
-    @Override
-    public boolean put( String name, Object entity )
-    {
-        return next.put( name, entity );
-    }
-
-    @Override
-    public boolean remove( String name )
-    {
-        return next.remove( name );
-    }
-
-    @Override
-    public Object get( String name )
-    {
-        return next.get( name );
-    }
-
-    @Override
-    public String nameOf( Object entity )
-    {
-        return next.nameOf( entity );
-    }
-
-    @Override
-    public Map<String, Object> toMap()
-    {
-        return next.toMap();
-    }
-
-    @Override
-    public Iterable<EntityReference> references()
-    {
-        return next.references();
-    }
-
-    @Override
-    public EntityReference referenceOf( String name )
-    {
-        return next.referenceOf( name );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return next.hashCode();
-    }
-
-    @Override
-    public boolean equals( Object obj )
-    {
-        return next.equals( obj );
-    }
-
-    @Override
-    public String toString()
-    {
-        return next.toString();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/association/package.html b/core/api/src/main/java/org/qi4j/api/association/package.html
deleted file mode 100644
index cf48596..0000000
--- a/core/api/src/main/java/org/qi4j/api/association/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Association API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/cache/CacheOptions.java b/core/api/src/main/java/org/qi4j/api/cache/CacheOptions.java
deleted file mode 100644
index ccfc286..0000000
--- a/core/api/src/main/java/org/qi4j/api/cache/CacheOptions.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2010 Niclas Hedhman.
- *
- * Licensed  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.qi4j.api.cache;
-
-/**
- * CacheOptions is a metaInfo class for the Cache system for Entity persistence.
- * CacheOptions should be assigned to the Usecase of the UnitOfWork, to give hint on caching to entity stores.
- * See {@link org.qi4j.api.usecase.UsecaseBuilder} on how to set the metaInfo on Usecases.
- */
-public final class CacheOptions
-{
-    public static final CacheOptions ALWAYS = new CacheOptions( true, true, true );
-    public static final CacheOptions NEVER = new CacheOptions( false, false, false );
-
-    private final boolean cacheOnRead;
-    private final boolean cacheOnWrite;
-    private final boolean cacheOnNew;
-
-    /**
-     * Constructor for CacheOptions.
-     *
-     * @param cacheOnRead  if true, give the hint to the Cache system that it may not be a good idea to cache the
-     *                     read values. This is useful when it is known that the read will be over a large set and
-     *                     shouldn't affect the existing cached entities. For instance, when traversing the EntityStore
-     *                     this option is set to false.
-     * @param cacheOnWrite if true, give the hint to the Cache system that it may not be a good idea to cache the
-     *                     entity when the value is updated. If this is false, the cache should be emptied from any
-     *                     cached entity instead of updated. There are few cases when this is useful, and if this is
-     *                     false, it makes sense that the <i>cacheOnRead</i> is also false.
-     * @param cacheOnNew   if true, give the hint to the Cache system that it may not be a good idea to cache a newly
-     *                     created Entity, as it is not likely to be read in the near future. This is useful when
-     *                     batch inserts are being made.
-     */
-    public CacheOptions( boolean cacheOnRead, boolean cacheOnWrite, boolean cacheOnNew )
-    {
-        this.cacheOnRead = cacheOnRead;
-        this.cacheOnWrite = cacheOnWrite;
-        this.cacheOnNew = cacheOnNew;
-    }
-
-    /**
-     * @return if true, give the hint to the Cache system that it may not be a good idea to cache the
-     *         read values. This is useful when it is known that the read will be over a large set and
-     *         shouldn't affect the existing cached entities. For instance, when traversing the EntityStore
-     */
-    public boolean cacheOnRead()
-    {
-        return cacheOnRead;
-    }
-
-    /**
-     * @return if true, give the hint to the Cache system that it may not be a good idea to cache the
-     *         entity when the value is updated. If this is false, the cache should be emptied from any
-     *         cached entity instead of updated. There are few cases when this is useful, and if this is
-     *         false, it makes sense that the <i>cacheOnRead</i> is also false.
-     */
-    public boolean cacheOnWrite()
-    {
-        return cacheOnWrite;
-    }
-
-    /**
-     * @return if true, give the hint to the Cache system that it may not be a good idea to cache a newly
-     *         created Entity, as it is not likely to be read in the near future. This is useful when
-     *         batch inserts are being made.
-     */
-    public boolean cacheOnNew()
-    {
-        return cacheOnNew;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/cache/package.html b/core/api/src/main/java/org/qi4j/api/cache/package.html
deleted file mode 100644
index a62da34..0000000
--- a/core/api/src/main/java/org/qi4j/api/cache/package.html
+++ /dev/null
@@ -1,40 +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.
--->
-<html>
-    <body>
-        <h2>Cache API.</h2>
-        <p>
-            The Cache API/SPI is an extension point for Entity Store caching.
-        </p>
-        <p>
-            The API part is only to allow caching options to be passed to the underlying extension in a uniform and
-            standard way. CacheOptions are to be passed as meta info on the optional Cache extension that is specified
-            during assembly phase. Example;
-        </p>
-<pre><code>
-public void assemble( ModuleAssembly module )
-{
-    CacheOptions options = new CacheOptions( true, true, false );
-    module.addServices( EhCacheService.class ).setMetaInfo( options );
-}
-</code></pre>
-        <p>
-            Not all EntityStore implementations use the Cache extension, so check the implementation details of the
-            EntityStore whether the cache extension can bring any benefits or not.
-        </p>
-    </body>
-</html>
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/common/AppliesTo.java b/core/api/src/main/java/org/qi4j/api/common/AppliesTo.java
deleted file mode 100644
index b23f204..0000000
--- a/core/api/src/main/java/org/qi4j/api/common/AppliesTo.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- * 
- * Licensed 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.qi4j.api.common;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Fragments that implement InvocationHandler and which should only be applied to methods that have a particular
- * annotation or implement a known interface should use this annotation.
- * <p>
- * &#64;AppliesTo can specify one of;
- * </p>
- * <ul>
- * <li>An annotation,</li>
- * <li>An interface,</li>
- * <li>An AppliesToFilter implementation.</li>
- * </ul>
- * <p>
- * Example with annotation:
- * </p>
- * <pre><code>
- *
- * &#64;AppliesTo( Sessional.class )   // Tells Zest to apply this concern on methods with &#64;Sessional annotation
- * public class SessionConcern extends GenericConcern
- * {
- *     public Object invoke( Object proxy, Method method, Object[] args )
- *         throws Throwable
- *     {
- *         ... do session stuff ...
- *     }
- * }
- *
- * &#64;Retention( RetentionPolicy.RUNTIME )
- * &#64;Target( ElementType.METHOD )
- * &#64;Documented
- * &#64;Inherited
- * public @interface Sessional
- * {
- * }
- *
- * public class MyMixin
- *     implements My
- * {
- *     &#64;Sessional
- *     public void doSomethingSessional()
- *     {
- *        // ... do your logic wrapped in a session
- *     }
- *
- *     public void doSomethingWithoutSession()
- *     {
- *        // ... do stuff that are not wrapped in session.
- *     }
- * }
- *
- * public interface My
- * {
- *     void doSomethingSessional();
- *
- *     void doSomethingWithoutSession();
- * }
- *
- * &#64;Concerns( SessionConcern.class )
- * &#64;Mixins( MyMixin.class )
- * public interface MyComposite extends My, TransientComposite
- * {}
- * </code></pre>
- * <p>
- * The doSomethingWithoutSession method do not have the &#64;Sessional annotation, therefore the SessionConcern will
- * not be placed into the call sequence of these methods, and
- * vice-versa. The &#64;Sessional annotation can be placed either on the interface method or the implementation
- * method, depending on whether it is a contract or implementation detail.
- * </p>
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.TYPE, ElementType.METHOD } )
-@Documented
-public @interface AppliesTo
-{
-    /**
-     * List of interfaces, annotations or AppliesToFilter
-     * implementation classes.
-     * If one of them matches the current element it will be
-     * accepted, so this list can be considered an "or".
-     *
-     * @return array of classes or interfaces to be used by the filter
-     */
-    Class<?>[] value();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/common/AppliesToFilter.java b/core/api/src/main/java/org/qi4j/api/common/AppliesToFilter.java
deleted file mode 100644
index f356cf4..0000000
--- a/core/api/src/main/java/org/qi4j/api/common/AppliesToFilter.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.common;
-
-import java.lang.reflect.Method;
-
-/**
- * Implementations of this interface can be specified in the &#64;AppliesTo.
- * <p>
- * AppliesTo filters are one of the driving technologies in Zest. They allow you to apply fragments (Mixins,
- * Concerns, SideEffects), often generic ones, depending on the context that they are evaluated under. This
- * mechanism is heavily used internally in Zest to achieve many other features.
- * </p>
- * <p>
- * The starting point is the basic use of AppliesToFilter, where the &#64;AppliesTo annotation is given an
- * AppliesToFilter implementation as an argument, for instance at a Mixin implementation;
- * </p>
- * <pre><code>
- * &#64;AppliesTo( MyAppliesToFilter.class )
- * public class SomeMixin
- *     implements InvocationHandler
- * {
- *
- * }
- *
- * public class MyAppliesToFilter
- *     implements AppliesToFilter
- * {
- *     public boolean appliesTo( Method method, Class&lt;?&gt; mixin, Class&lt;?&gt; compositeType, Class&lt;?&gt; fragmentClass )
- *     {
- *         return method.getName().startsWith( "my" );
- *     }
- * }
- * </code></pre>
- * <p>
- * In the case above, the generic mixin will only be applied to the methods that that is defined by the
- * AppliesToFilter. This is the primary way to define limits on the application of generic fragments, since
- * especially mixins are rarely applied to all methods.
- * </p>
- */
-public interface AppliesToFilter
-{
-    /**
-     * This is an internal AppliesToFilter which is assigned if no other AppliesToFilters are found for a given
-     * fragment.
-     * <p>
-     * There is no reason for user code to use this AppliesToFilter directly, and should be perceived as an
-     * internal class in Zest.
-     * </p>
-     */
-    AppliesToFilter ALWAYS = new AppliesToFilter()
-    {
-        @Override
-        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
-        {
-            return true;
-        }
-    };
-
-    /**
-     * Check if the Fragment should be applied or not. Will be call when applied to Mixins, Concerns, SideEffects.
-     *
-     * @param method        method that is invoked
-     * @param mixin         mixin implementation for the method
-     * @param compositeType composite type
-     * @param fragmentClass fragment that is being applies
-     *
-     * @return true if the filter passes, otherwise false
-     */
-    boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/common/ConstructionException.java b/core/api/src/main/java/org/qi4j/api/common/ConstructionException.java
deleted file mode 100644
index 9957e63..0000000
--- a/core/api/src/main/java/org/qi4j/api/common/ConstructionException.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.common;
-
-/**
- * Thrown when a Fragment or object could not be instantiated.
- * This includes, but not be limited to;
- * <ul>
- * <li>private constructor.</li>
- * <li>abstract class for Constraints.</li>
- * <li>interface instead of a class.</li>
- * <li>useful constructor missing.</li>
- * <li>exception thrown in the constructor.</li>
- * <li>Subclassing of org.qi4j.api.property.Property</li>
- * </ul>
- * <p>
- * See the nested exception for additional details.
- * </p>
- */
-public class ConstructionException
-    extends RuntimeException
-{
-    private static final long serialVersionUID = 1L;
-
-    public ConstructionException()
-    {
-    }
-
-    public ConstructionException( String message )
-    {
-        super( message );
-    }
-
-    public ConstructionException( String message, Throwable cause )
-    {
-        super( message, cause );
-    }
-
-    public ConstructionException( Throwable cause )
-    {
-        super( cause );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/common/InvalidApplicationException.java b/core/api/src/main/java/org/qi4j/api/common/InvalidApplicationException.java
deleted file mode 100644
index 5769fad..0000000
--- a/core/api/src/main/java/org/qi4j/api/common/InvalidApplicationException.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.common;
-
-/**
- * Thrown when an application is considered to not be constructed properly.
- * This happens primarily when client code tries to instantiate Composites
- * and objects which have not been registered in the ModuleAssembly.
- */
-public class InvalidApplicationException
-    extends RuntimeException
-{
-    private static final long serialVersionUID = 1L;
-
-    public InvalidApplicationException( String string )
-    {
-        super( string );
-    }
-
-    public InvalidApplicationException( String string, Throwable cause )
-    {
-        super( string, cause );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/common/MetaInfo.java b/core/api/src/main/java/org/qi4j/api/common/MetaInfo.java
deleted file mode 100644
index b746711..0000000
--- a/core/api/src/main/java/org/qi4j/api/common/MetaInfo.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.common;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Type;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.sideeffect.SideEffects;
-import org.qi4j.api.util.Classes;
-
-import static java.util.Arrays.asList;
-import static org.qi4j.api.util.Classes.typesOf;
-
-/**
- * Used to declare and access meta-info.
- * <p>
- * <strong>This is effectively an internal class and should not be used directly.</strong>
- * </p>
- * <p>
- * MetaInfo can be set on composites during the assembly phase, a.k.a the bootstrap
- * process. MetaInfo is any additional data that one wishes to associate at the 'class level' instead of instance
- * level of a composite declaration.
- * </p>
- * <p>
- * To set the MetaInfo on a Composite, call the {@code setMetaInfo()} methods on the various composite declaration
- * types, such as;
- * </p>
- * <pre><code>
- * public void assemble( ModuleAssembly module )
- *     throws AssemblyException
- * {
- *     Map&lt;String,String&gt; properties = ...;
- *     module.services( MyService.class ).setMetaInfo( properties );
- * }
- * </code></pre>
- * <p>
- * which can later be retrieved by calling the {@code metaInfo()} method on the composite itself. For the example
- * above that would be;
- * </p>
- * <pre><code>
- * &#64;Mixins(MyServiceMixin.class)
- * public interface MyService extends ServiceComposite
- * {
- *
- * }
- *
- * public abstract class MyServiceMixin
- *     implements MyService
- * {
- *     private Properties props;
- *
- *     public MyServiceMixin()
- *     {
- *         props = metaInfo( Map.class );
- *     }
- * }
- * </code></pre>
- */
-public final class MetaInfo
-{
-    private final static Collection<Class> ignored;
-
-    static
-    {
-        ignored = new HashSet<Class>( 4, 0.8f ); // Optimize size used.
-        ignored.addAll( asList( Mixins.class, Concerns.class, SideEffects.class ) );
-    }
-
-    private final Map<Class<?>, Object> metaInfoMap;
-
-    public MetaInfo()
-    {
-        metaInfoMap = new LinkedHashMap<Class<?>, Object>();
-    }
-
-    public MetaInfo( MetaInfo metaInfo )
-    {
-        metaInfoMap = new LinkedHashMap<Class<?>, Object>();
-        metaInfoMap.putAll( metaInfo.metaInfoMap );
-    }
-
-    public void set( Object metaInfo )
-    {
-        if( metaInfo instanceof Annotation )
-        {
-            Annotation annotation = (Annotation) metaInfo;
-            metaInfoMap.put( annotation.annotationType(), metaInfo );
-        }
-        else
-        {
-            Class<?> metaInfoclass = metaInfo.getClass();
-            Iterable<Type> types = typesOf( metaInfoclass );
-            for( Type type : types )
-            {
-                metaInfoMap.put( Classes.RAW_CLASS.map( type ), metaInfo );
-            }
-        }
-    }
-
-    public <T> T get( Class<T> metaInfoType )
-    {
-        return metaInfoType.cast( metaInfoMap.get( metaInfoType ) );
-    }
-
-    public <T> void add( Class<T> infoType, T info )
-    {
-        metaInfoMap.put( infoType, info );
-    }
-
-    public MetaInfo withAnnotations( AnnotatedElement annotatedElement )
-    {
-        for( Annotation annotation : annotatedElement.getAnnotations() )
-        {
-            if( !ignored.contains( annotation.annotationType() )
-                && get( annotation.annotationType() ) == null )
-            {
-                set( annotation );
-            }
-        }
-        return this;
-    }
-
-    @Override
-    public String toString()
-    {
-        return metaInfoMap.toString();
-    }
-
-    public void remove( Class serviceFinderClass )
-    {
-        metaInfoMap.remove( serviceFinderClass );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/common/Optional.java b/core/api/src/main/java/org/qi4j/api/common/Optional.java
deleted file mode 100644
index 3a070c3..0000000
--- a/core/api/src/main/java/org/qi4j/api/common/Optional.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.common;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation to denote that something is optional.
- * <ul>
- * <li>
- * If applied to a method parameter, then the value is allowed to be null. Default
- * is that method parameters have to be non-null.
- * </li>
- * <li>
- * If applied to a Property declaration, then the value may be null after construction of
- * the instance, or may be set to null at a later time.
- * </li>
- * <li>
- * If applied to an injected member field, it is allowed tha none get injected. For instance, an <code>&#64;Optional
- * &#64;Service</code> would allow a service to not have been declared and the field will be null.
- * </li>
- * </ul>
- * <p>
- * Optionality is not the default in Zest, and if injections, property values and parameters in methods are not
- * non-null, the Zest runtime will throw an {@link org.qi4j.api.constraint.ConstraintViolationException}, indicating
- * which field/property/parameter in which composite and mixin the problem has been detected.
- * </p>
- * <p>
- * Example;
- * </p>
- * <pre><code>
- * &#64;Optional &#64;Service
- * MyService service;   // If no MyService instance is declared and visible to this service injection point
- *                      // the 'service' field will be null.
- *
- * &#64;Service
- * YourService other;   // If no YourService instance is declared and visible to this service injection point
- *                      // the Zest runtime will throw a ConstraintViolationException.
- *
- * </code></pre>
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD } )
-@Documented
-public @interface Optional
-{
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/common/QualifiedName.java b/core/api/src/main/java/org/qi4j/api/common/QualifiedName.java
deleted file mode 100644
index a869791..0000000
--- a/core/api/src/main/java/org/qi4j/api/common/QualifiedName.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.common;
-
-import java.io.Serializable;
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Member;
-import org.qi4j.api.util.NullArgumentException;
-
-/**
- * QualifiedName is a representation of Property names to their full declaration.
- * <p>
- * A QualifiedName is created by combining the name of a method and the name of the type that declares the method.
- * This class also contains many static utility methods to manage QualifiedName instances.
- * </p>
- * <p>
- * <strong>NOTE: Unless you do very generic libraries, entity stores and other extensions that is deeply coupled into
- * the Zest runtime, it is very unlikely you will need to use this class directly.</strong>
- * </p>
- * <p>
- * It is also important to notice that the QualifiedName needs to be long-term stable, as the names are written
- * to persistent storage. So any changes in the formatting <strong>must be made in a backward-compatible manner
- * </strong>.
- * </p>
- * <p>
- * The QualifiedName has two intrinsic parts, one being the {@code type} and the other the {@code name}. The
- * {@code type} comes from the class where the QualifiedName originates from and internally kept as a {@link TypeName}
- * instance. The name is the name from the method name. When the QualifiedName instance is converted to an external
- * string representation, via the offical and formal {@link #toString()} method, the {@code type} is normalized, i.e.
- * any dollar characters ($) in the name are replaced by dashes (-), to make them URI friendly.
- * </p>
- * <p>
- * QualifiedName instances are immutable, implements {@link #hashCode()} and {@link #equals(Object)} as a value
- * object and can safely be used as keys in {@link java.util.Map}.
- */
-public final class QualifiedName
-    implements Comparable<QualifiedName>, Serializable
-{
-    private final TypeName typeName;
-    private final String name;
-
-    /**
-     * Creates a QualifiedName from a method.
-     * <p>
-     * This factory method will create a QualifiedName from the Method itself.
-     *
-     * </p>
-     *
-     * @param method Type method that returns a Property, for which the QualifiedName will be representing.
-     *
-     * @return A QualifiedName representing this method.
-     *
-     * @throws NullArgumentException If the {@code method} argument passed is null.
-     */
-    public static QualifiedName fromAccessor( AccessibleObject method )
-    {
-        NullArgumentException.validateNotNull( "method", method );
-        return fromClass( ( (Member) method ).getDeclaringClass(), ( (Member) method ).getName() );
-    }
-
-    /**
-     * Creates a QualifiedName instance from the Class and a given name.
-     * <p>
-     * This factory method converts the {@code type} to a {@link TypeName} and appends the given {@code name}.
-     *
-     * @param type The Class that is the base of the QualifiedName.
-     * @param name The qualifier name which will be appended to the base name derived from the {@code type} argument.
-     *
-     * @return A QualifiedName instance representing the {@code type} and {@code name} arguments.
-     *
-     * @throws NullArgumentException if any of the two arguments are {@code null}, or if the name string is empty.
-     */
-    public static QualifiedName fromClass( Class type, String name )
-    {
-        return new QualifiedName( TypeName.nameOf( type ), name );
-    }
-
-    /**
-     * Creates a Qualified name from a type as string and a name qualifier.
-     *
-     * @param type The type name as a a string, which must be properly formatted. No checks for correctly formatted
-     *             type name is performed.
-     * @param name The qualifier name which will be appended to the base name derived from the {@code type} argument.
-     *
-     * @return A QualifiedName instance representing the {@code type} and {@code name} arguments.
-     *
-     * @throws NullArgumentException if any of the two arguments are {@code null} or either string is empty.
-     */
-    public static QualifiedName fromName( String type, String name )
-    {
-        return new QualifiedName( TypeName.nameOf( type ), name );
-    }
-
-    /**
-     * Creates a QualifiedName from the external string format of QualifiedName.
-     * <p>
-     * This factory method is the reverse of {@link QualifiedName#toString() }  method, and creates a new QualifiedName
-     * instance from the string representation of the QualifiedName.
-     * </p>
-     *
-     * @param fullQualifiedName The QualifiedName external string representation to be converted back into a QualifiedName
-     *                      instance.
-     *
-     * @return The QualifiedName instance represented by the {@code qualifiedName} argument.
-     *
-     * @throws IllegalArgumentException If the {@code qualifiedName} argument has wrong format.
-     */
-    public static QualifiedName fromFQN( String fullQualifiedName )
-    {
-        NullArgumentException.validateNotEmpty( "qualifiedName", fullQualifiedName );
-        int idx = fullQualifiedName.lastIndexOf( ":" );
-        if( idx == -1 )
-        {
-            throw new IllegalArgumentException( "Name '" + fullQualifiedName + "' is not a qualified name" );
-        }
-        final String type = fullQualifiedName.substring( 0, idx );
-        final String name = fullQualifiedName.substring( idx + 1 );
-        return new QualifiedName( TypeName.nameOf( type ), name );
-    }
-
-    QualifiedName( TypeName typeName, String name )
-    {
-        NullArgumentException.validateNotNull( "typeName", typeName );
-        NullArgumentException.validateNotEmpty( "name", name );
-        this.typeName = typeName;
-        this.name = name;
-    }
-
-    /**
-     * Returns the normalized string of the type part of the QualifiedName.
-     *
-     * <p>
-     * The normalized type name means that all dollar ($) characters have been replaced by dashes (-).
-     * </p>
-     *
-     * @return the normalized string of the type part of the QualifiedName.
-     */
-    public String type()
-    {
-        return typeName.normalized();
-    }
-
-    /**
-     * Returns the name component of the QualifiedName.
-     *
-     * @return the name component of the QualifiedName.
-     */
-    public String name()
-    {
-        return name;
-    }
-
-    /**
-     * Returns the URI of the QualifiedName.
-     *
-     * <p>
-     * The URI is the {@link #toNamespace()} followed by the {@code name} component.
-     * <p>
-     *
-     * @return the URI of the QualifiedName.
-     *
-     * @see #toNamespace()
-     */
-    public String toURI()
-    {
-        return toNamespace() + name;
-    }
-
-    /**
-     * Return the URI of the {@link TypeName} component of the QualifiedName.
-     * <p>
-     * The URI of the {@link TypeName} component is in the form of;
-     * </p>
-     * <pre>
-     * "urn:qi4j:type:" normalizedClassName
-     * </pre>
-     * <p>
-     * where {@code normalizedClassName} is the fully-qualified class name having had any dollar ($) characters replaced
-     * by URI friendly dashes (-), with a trailing hash (#). Examples;
-     * </p>
-     * <pre>
-     * urn:qi4j:type:org.qi4j.api.common.QualifiedName#
-     * urn:qi4j:type:org.qi4j.samples.MyClass-MyInnerClass#
-     * </pre>
-     *
-     * @return the URI of the {@link TypeName} component of the QualifiedName.
-     */
-    public String toNamespace()
-    {
-        return typeName.toURI() + "#";
-    }
-
-    /**
-     * Return the formal and official, long-term stable, external string representation of a QualifiedName.
-     * <p>
-     * This returns the {@link org.qi4j.api.common.TypeName#toString()} followed by the {@code name} component.
-     * </p>
-     *
-     * @return the formal and official, long-term stable, external string representation of a QualifiedName.
-     */
-    @Override
-    public String toString()
-    {
-        return typeName + ":" + name;
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-
-        QualifiedName that = (QualifiedName) o;
-
-        return name.equals( that.name ) && typeName.equals( that.typeName );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return 31 * typeName.hashCode() + name.hashCode();
-    }
-
-    @Override
-    public int compareTo( QualifiedName other )
-    {
-        final int result = typeName.compareTo( other.typeName );
-        if( result != 0 )
-        {
-            return result;
-        }
-        return name.compareTo( other.name );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/common/TypeName.java b/core/api/src/main/java/org/qi4j/api/common/TypeName.java
deleted file mode 100644
index 6a485e6..0000000
--- a/core/api/src/main/java/org/qi4j/api/common/TypeName.java
+++ /dev/null
@@ -1,111 +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.qi4j.api.common;
-
-import java.io.Serializable;
-import java.lang.reflect.Type;
-import org.qi4j.api.util.Classes;
-import org.qi4j.api.util.NullArgumentException;
-
-/**
- * Represents a Type name.
- */
-public final class TypeName
-    implements Serializable, Comparable<TypeName>
-{
-    private final String name;
-
-    public static TypeName nameOf( Class type )
-    {
-        NullArgumentException.validateNotNull( "type", type );
-        return new TypeName( type.getName() );
-    }
-
-    public static TypeName nameOf( Type type )
-    {
-        return nameOf( Classes.RAW_CLASS.map( type ) );
-    }
-
-    public static TypeName nameOf( String typeName )
-    {
-        return new TypeName( typeName );
-    }
-
-    private TypeName( String name )
-    {
-        NullArgumentException.validateNotEmpty( "name", name );
-        this.name = name;
-    }
-
-    public String normalized()
-    {
-        return Classes.normalizeClassToURI( name );
-    }
-
-    public String toURI()
-    {
-        return Classes.toURI( name );
-    }
-
-    public String name()
-    {
-        return name;
-    }
-
-    @Override
-    public String toString()
-    {
-        return name;
-    }
-
-    public boolean isClass( final Class<?> type )
-    {
-        return type.getName().equals( name );
-    }
-
-    @Override
-    public boolean equals( final Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-
-        final TypeName other = (TypeName) o;
-
-        return name.equals( other.name );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return name.hashCode();
-    }
-
-    @Override
-    public int compareTo( final TypeName typeName )
-    {
-        return this.name.compareTo( typeName.name );
-    }
-}
-
diff --git a/core/api/src/main/java/org/qi4j/api/common/UseDefaults.java b/core/api/src/main/java/org/qi4j/api/common/UseDefaults.java
deleted file mode 100644
index 94f4446..0000000
--- a/core/api/src/main/java/org/qi4j/api/common/UseDefaults.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.common;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation to denote that the initial value of a Property will be the default value for the type if none is
- * specified during construction.
- * <p>
- * These are the default values used for various types:
- * </p>
- * <pre>
- * Byte: 0
- * Short: 0
- * Character: 0
- * Integer: 0
- * Long: 0L
- * Double: 0.0d
- * Float: 0.0f
- * Boolean: false
- * String: ""
- * List: empty java.util.ArrayList
- * Set: empty java.util.HashSet
- * Collection: empty java.util.ArrayList
- * enum: first declared value
- * </pre>
- * <p>
- * If this annotation is not used, the property will be set to null, and unless {@code &#64;Optional} is declared
- * is not allowed.
- * </p>
- * <p>
- * It is also possible to change the default values for Composites during the assembly. This is done by calling the
- * {@code org.qi4j.bootstrap.ModuleAssembly#forMixin(Class)} method.
- * </p>
- * <p>
- * Example;
- * Let's assume that we have the following mixin type;
- *
- * <pre><code>
- * public interface SomeType
- * {
- *     &#64;UseDefaults
- *     Property&lt;String&gt; someValue();
- * }
- * </code></pre>
- * And that we want to have {@code someValue()} to be initialized to "&lt;unknown&gt;" instead of the empty string.
- * Then we need to declare the default for that with the following in the assembler.
- * <pre><code>
- * public void assemble( ModuleAssembly module )
- * {
- *     module.forMixin( SomeType.class ).declareDefaults().someValue().set( "&lt;unknown&gt;" );
- * }
- * }
- * </code></pre>
- */
-@SuppressWarnings( "JavadocReference" )
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.METHOD, ElementType.FIELD } )
-@Documented
-public @interface UseDefaults
-{
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/common/Visibility.java b/core/api/src/main/java/org/qi4j/api/common/Visibility.java
deleted file mode 100644
index 0f38f36..0000000
--- a/core/api/src/main/java/org/qi4j/api/common/Visibility.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.common;
-
-/**
- * Visibility is a core concept in the Zest structure system. It defines the locale of composites and objects, i.e.
- * how far they can be 'seen' and therefor be used.
- * <p>
- * When a Composite or Object is declared in the assembly phase, and no visibility is set, only other
- * composites/objects within the same module can use that declaration. For a declared composite/object to be usable
- * from other modules a higher visibility must be set, either that the Composite/Object can be used by others within
- * the same Layer, or even to be used by those in the layer above.
- * </p>
- */
-public enum Visibility
-{
-    /**
-     * Artifact is visible only in the declaring module (default)
-     */
-    module,
-    /**
-     * Artifact is visible to all modules in the same layer
-     */
-    layer,
-    /**
-     * Artifact is visible to other modules in the same layer and any modules in extending layers
-     */
-    application
-}
diff --git a/core/api/src/main/java/org/qi4j/api/common/package.html b/core/api/src/main/java/org/qi4j/api/common/package.html
deleted file mode 100644
index f29de5d..0000000
--- a/core/api/src/main/java/org/qi4j/api/common/package.html
+++ /dev/null
@@ -1,81 +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.
--->
-<html>
-    <body>
-        <h2>Common API.</h2>
-        <p>
-            The Common API package is a collection of really low-level types needed at the core of the Zest™ Runtime. It is also
-            a collection of types that are not particularly cohesive, and effectively this package contains the loose ends
-            that does not belong elsewhere.
-        </p>
-        <p>
-            In this package, you can safely ignore the following classes;
-        </p>
-        <ul>
-            <li>MetaInfo</li>
-            <li>QualifiedName</li>
-            <li>TypeName</li>
-        </ul>
-        <p>UNLESS you are into deep integration into the Zest™ Runtime.</p>
-
-        <h3>&#64;AppliesTo and AppliesToFilter</h3>
-        <p>
-            This tandem of interface + annotation are primarily used for Generic Fragments, to indicate which methods on the
-            interface the fragment should be applied to.
-        </p>
-
-        <h3>&#64;Optional</h3>
-        <p>
-            In Zest™, method arguments, property values and injected fields are not allowed to be null by default. To allow
-            any of these to be null, i.e. undeclared, it is required that the argument, field or method is marked with the
-            &#64;Optional annotation.
-        </p>
-
-        <h3>&#64;UseDefaults</h3>
-        <p>
-            Since null is not allowed without the &#64;Optional annotation, it can sometimes by tedious to initialize all
-            the property values. And the &#64;UseDefaults annotation allows us to declare that Zest™ should set the Property
-            to a default value. These are either the pre-defined ones, or can be set per property declaration during the
-            assembly.
-        </p>
-
-        <h3>&#64;Visibility</h3>
-        <p>
-            Visibility is another innovative concept in Zest™, which leverage the structure system (Application, Layer, Module)
-            to limit the 'reach' when requesting composites and objects. The Visibility is declared per Composite/Object,
-            preferably in the most restrictive mode possible, and the visibility resolver will ensure a predictable resolution
-            algorithm;
-        </p>
-        <ol>
-            <li>Search the module of the caller first. If one and only one composite type fulfilling the request is available
-                return that to the caller. If two or more are found, throw an AmbiguousTypeException. If no composite found
-                continue to the next step.
-            </li>
-            <li>Search all modules in the Layer of the caller for composite that has a declaration other than
-                <code>Visibility.module</code>. If one and only one composite type fulfilling the request is available
-                return that to the caller. If two or more are found, throw an AmbiguousTypeException. If no composite found
-                continue to the next step.
-            </li>
-            <li>Search all modules in the Layer(s) (if any) directly below of the caller for composite that has a declaration of
-                <code>Visibility.application</code>. If one and only one composite type fulfilling the request is available
-                return that to the caller. If two or more are found, throw an AmbiguousTypeException. If no composite found
-                continue to the next step.
-            </li>
-            <li>Throw an NoSuchCompositeException (or related) exception.</li>
-        </ol>
-    </body>
-</html>
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/composite/AmbiguousTypeException.java b/core/api/src/main/java/org/qi4j/api/composite/AmbiguousTypeException.java
deleted file mode 100644
index 34f3653..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/AmbiguousTypeException.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.api.composite;
-
-/**
- * This Exception is thrown when more than one Composite implements a MixinType
- * that one tries to use to create a Composite instance from.
- * <p>
- * For instance;
- * </p>
- * <pre><code>
- * public interface AbcComposite extends TransientComposite, Abc
- * {}
- *
- * public interface DefComposite extends TransientComposite, Def
- * {}
- *
- * public interface Abc
- * {}
- *
- * public interface Def extends Abc
- * {}
- *
- *
- * TransientBuilder cb = factory.newTransientBuilder( Abc.class );
- * </code></pre>
- * <p>
- * In the code above, both the AbcComposite and DefComposite implement Abc, and therefore
- * the <code>newTransientBuilder</code> method can not unambiguously figure out which
- * one is intended.
- * </p>
- */
-public class AmbiguousTypeException
-    extends RuntimeException
-{
-    private static final long serialVersionUID = 1L;
-
-    public AmbiguousTypeException( String message )
-    {
-        super( message );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/Composite.java b/core/api/src/main/java/org/qi4j/api/composite/Composite.java
deleted file mode 100644
index 91662fb..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/Composite.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.composite;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.PropertyMixin;
-
-/**
- * Base Composite interface.
- * <p>
- * All Composite objects must implement this interface. Let the
- * Composite interface extend this one. An implementation will be provided
- * by the framework.
- * </p>
- * <p>
- * Properties and associations are handled by default.
- * </p>
- */
-@Mixins( { PropertyMixin.class } )
-public interface Composite
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/CompositeContext.java b/core/api/src/main/java/org/qi4j/api/composite/CompositeContext.java
deleted file mode 100644
index d8a2aa7..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/CompositeContext.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.composite;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.structure.Module;
-import org.qi4j.functional.Iterables;
-
-import static org.qi4j.functional.Iterables.toArray;
-
-/**
- * Thread-associated composites. This is basically a ThreadLocal which maintains a reference
- * to a TransientComposite instance for each thread. This can be used to implement various context
- * patterns without having to pass the context explicitly as a parameter to methods.
- */
-public class CompositeContext<T extends TransientComposite>
-    extends ThreadLocal<T>
-{
-    private Module module;
-    private Class<T> type;
-
-    public CompositeContext( Module module, Class<T> type )
-    {
-        this.module = module;
-        this.type = type;
-    }
-
-    @Override
-    protected T initialValue()
-    {
-        return module.newTransient( type );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public T proxy()
-    {
-        TransientComposite composite = get();
-
-        Iterable<Class<?>> types = Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF.map( composite ).types();
-        return (T) Proxy.newProxyInstance(
-            composite.getClass().getClassLoader(),
-            toArray( Class.class, Iterables.<Class>cast( types ) ),
-            new ContextInvocationhandler() );
-    }
-
-    private class ContextInvocationhandler
-        implements InvocationHandler
-    {
-
-        @Override
-        public Object invoke( Object object, Method method, Object[] objects )
-            throws Throwable
-        {
-            try
-            {
-                return method.invoke( get(), objects );
-            }
-            catch( InvocationTargetException e )
-            {
-                throw e.getTargetException();
-            }
-        }
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/CompositeDescriptor.java b/core/api/src/main/java/org/qi4j/api/composite/CompositeDescriptor.java
deleted file mode 100644
index 40b4462..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/CompositeDescriptor.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.composite;
-
-/**
- * Composite Descriptor.
- */
-public interface CompositeDescriptor
-    extends ModelDescriptor
-{
-    Class<?> primaryType();
-
-    Iterable<Class<?>> mixinTypes();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/CompositeInstance.java b/core/api/src/main/java/org/qi4j/api/composite/CompositeInstance.java
deleted file mode 100644
index 79f8d62..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/CompositeInstance.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.composite;
-
-import java.lang.reflect.InvocationHandler;
-import org.qi4j.api.property.StateHolder;
-import org.qi4j.api.structure.MetaInfoHolder;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.type.HasTypes;
-
-/**
- * Composite Instance.
- */
-public interface CompositeInstance
-    extends InvocationHandler, CompositeInvoker, HasTypes, MetaInfoHolder
-{
-    <T> T proxy();
-
-    <T> T newProxy( Class<T> mixinType )
-        throws IllegalArgumentException;
-
-    Module module();
-
-    CompositeDescriptor descriptor();
-
-    StateHolder state();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/CompositeInvoker.java b/core/api/src/main/java/org/qi4j/api/composite/CompositeInvoker.java
deleted file mode 100644
index 5bd8d11..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/CompositeInvoker.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.composite;
-
-import java.lang.reflect.Method;
-
-/**
- * Composite method invoker.
- * <p>
- * All composites must implement this interface. Methods that are invoked
- * may reside either in the public Composite interface or in any internal mixins.
- * </p>
- * <p>
- * <strong><i>NOTE:</i></strong>Client code should never use method in this class. We have not been able to hide this
- * from client code, but IF we find a way to do, this interface may disappear.
- * </p>
- */
-public interface CompositeInvoker
-{
-
-    Object invokeComposite( Method method, Object[] args )
-        throws Throwable;
-
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/ConstructorDescriptor.java b/core/api/src/main/java/org/qi4j/api/composite/ConstructorDescriptor.java
deleted file mode 100644
index 6e74dd9..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/ConstructorDescriptor.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.composite;
-
-import java.lang.reflect.Constructor;
-
-/**
- * Composite constructor descriptor.
- */
-public interface ConstructorDescriptor
-{
-    Constructor<?> constructor();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/DecoratorMixin.java b/core/api/src/main/java/org/qi4j/api/composite/DecoratorMixin.java
deleted file mode 100644
index 6b81844..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/DecoratorMixin.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.api.composite;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import org.qi4j.api.injection.scope.Uses;
-
-/**
- * Generic decorator mixin that allows a Composite to wrap
- * any other Composite as long as they share an interface.
- * <p>
- * Can be used to effectively implement
- * singleton mixins, since the decorated object can be shared between
- * many instances.
- * </p>
- */
-public class DecoratorMixin
-    implements InvocationHandler
-{
-    private Object delegate;
-
-    public DecoratorMixin( @Uses Object delegate )
-    {
-        if( delegate instanceof Class )
-        {
-            Thread.dumpStack();
-        }
-        this.delegate = delegate;
-    }
-
-    @Override
-    public Object invoke( Object object, Method method, Object[] args )
-        throws Throwable
-    {
-        if( delegate instanceof InvocationHandler )
-        {
-            InvocationHandler handler = (InvocationHandler) delegate;
-            return handler.invoke( object, method, args );
-        }
-        else
-        {
-            try
-            {
-                return method.invoke( delegate, args );
-            }
-            catch( InvocationTargetException e )
-            {
-                throw e.getCause();
-            }
-            catch( IllegalArgumentException e )
-            {
-                String message = constructMessage( method, args );
-                throw new IllegalArgumentException( message, e );
-            }
-        }
-    }
-
-    private String constructMessage( Method method, Object[] args )
-    {
-        StringBuilder builder = new StringBuilder();
-        builder.append( "\nmethod: " );
-        builder.append( method.getDeclaringClass().getName() );
-        builder.append( "." );
-        builder.append( method.getName() );
-        builder.append( "\ndelegate: " );
-        builder.append( delegate );
-        builder.append( "\ndelegateType: " );
-        builder.append( delegate == null ? "n/a" : delegate.getClass().getName() );
-        builder.append( "\narguments: \n" );
-        for( Object arg : args )
-        {
-            builder.append( "    " );
-            Class argClass = arg.getClass();
-            if( Proxy.isProxyClass( argClass ) )
-            {
-                builder.append( Proxy.getInvocationHandler( arg ).getClass().getName() );
-            }
-            else
-            {
-                builder.append( argClass.getName() );
-            }
-            builder.append( '\n' );
-        }
-        return builder.toString();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/DependencyDescriptor.java b/core/api/src/main/java/org/qi4j/api/composite/DependencyDescriptor.java
deleted file mode 100644
index 70d7d06..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/DependencyDescriptor.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.api.composite;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-
-/**
- * Composite dependency descriptor.
- */
-public interface DependencyDescriptor
-{
-    Annotation injectionAnnotation();
-
-    Type injectionType();
-
-    Class<?> injectedClass();
-
-    Class<?> rawInjectionType();
-
-    boolean optional();
-
-    Annotation[] annotations();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/InjectedFieldDescriptor.java b/core/api/src/main/java/org/qi4j/api/composite/InjectedFieldDescriptor.java
deleted file mode 100644
index 2f7297e..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/InjectedFieldDescriptor.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.composite;
-
-import java.lang.reflect.Field;
-
-/**
- * Composite injected field descriptor.
- */
-public interface InjectedFieldDescriptor
-{
-    Field field();
-
-    DependencyDescriptor dependency();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/InjectedMethodDescriptor.java b/core/api/src/main/java/org/qi4j/api/composite/InjectedMethodDescriptor.java
deleted file mode 100644
index 8888d32..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/InjectedMethodDescriptor.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.composite;
-
-import java.lang.reflect.Method;
-
-/**
- * Composite injected method descriptor.
- */
-public interface InjectedMethodDescriptor
-{
-    Method method();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/InjectedParametersDescriptor.java b/core/api/src/main/java/org/qi4j/api/composite/InjectedParametersDescriptor.java
deleted file mode 100644
index 301c56d..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/InjectedParametersDescriptor.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.composite;
-
-/**
- * Composite constructors and method injected parameters descriptor.
- */
-public interface InjectedParametersDescriptor
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/InvalidCompositeException.java b/core/api/src/main/java/org/qi4j/api/composite/InvalidCompositeException.java
deleted file mode 100644
index e5b86c0..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/InvalidCompositeException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*  Copyright 2007 Niclas Hedhman.
- *
- * Licensed 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.qi4j.api.composite;
-
-/**
- * This exception is thrown if a Composite is invalid.
- */
-public class InvalidCompositeException
-    extends RuntimeException
-{
-    public InvalidCompositeException( String message )
-    {
-        super( message );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/InvalidValueCompositeException.java b/core/api/src/main/java/org/qi4j/api/composite/InvalidValueCompositeException.java
deleted file mode 100644
index 60a48dd..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/InvalidValueCompositeException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.api.composite;
-
-/**
- * This exception is thrown if a ValueComposite is invalid.
- */
-public class InvalidValueCompositeException
-    extends RuntimeException
-{
-    public InvalidValueCompositeException( String message )
-    {
-        super( message );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/MethodDescriptor.java b/core/api/src/main/java/org/qi4j/api/composite/MethodDescriptor.java
deleted file mode 100644
index 2f88f35..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/MethodDescriptor.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.composite;
-
-import java.lang.reflect.Method;
-
-/**
- * Composite Method Descriptor.
- */
-public interface MethodDescriptor
-{
-    Method method();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/MissingMethodException.java b/core/api/src/main/java/org/qi4j/api/composite/MissingMethodException.java
deleted file mode 100644
index ae362cb..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/MissingMethodException.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.api.composite;
-
-/**
- * This exception is thrown if client code tries to invoke a non-existing Composite method.
- */
-public class MissingMethodException
-    extends RuntimeException
-{
-    public MissingMethodException( String message )
-    {
-        super( message );
-    }
-
-    public MissingMethodException( String message, NoSuchMethodException e )
-    {
-        super(message,e);
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/ModelDescriptor.java b/core/api/src/main/java/org/qi4j/api/composite/ModelDescriptor.java
deleted file mode 100644
index b0651f0..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/ModelDescriptor.java
+++ /dev/null
@@ -1,33 +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.qi4j.api.composite;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.structure.MetaInfoHolder;
-import org.qi4j.api.type.HasTypes;
-
-/**
- * Composite ModelDescriptor.
- */
-public interface ModelDescriptor extends HasTypes, MetaInfoHolder
-{
-    Visibility visibility();
-
-    boolean isAssignableTo( Class<?> type );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/NoSuchCompositeException.java b/core/api/src/main/java/org/qi4j/api/composite/NoSuchCompositeException.java
deleted file mode 100644
index b404779..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/NoSuchCompositeException.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.composite;
-
-import org.qi4j.api.common.InvalidApplicationException;
-
-/**
- * This exception is thrown if client code tries to create a non-existing Composite type.
- */
-public class NoSuchCompositeException
-    extends InvalidApplicationException
-{
-    private static final long serialVersionUID = 1L;
-
-    private final String compositeType;
-    private final String moduleName;
-
-    protected NoSuchCompositeException( String metaType, String compositeType, String moduleName )
-    {
-        super( "Could not find any visible " + metaType + " of type [" + compositeType + "] in module [" +
-               moduleName + "]." );
-        this.compositeType = compositeType;
-        this.moduleName = moduleName;
-    }
-
-    public String compositeType()
-    {
-        return compositeType;
-    }
-
-    public String moduleName()
-    {
-        return moduleName;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/NoSuchTransientException.java b/core/api/src/main/java/org/qi4j/api/composite/NoSuchTransientException.java
deleted file mode 100644
index e6a6f61..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/NoSuchTransientException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.composite;
-
-/**
- * This exception is thrown if client code tries to create a non-existing TransientComposite type.
- */
-public class NoSuchTransientException extends NoSuchCompositeException
-{
-    public NoSuchTransientException( String typeName, String moduleName )
-    {
-        super( "TransientComposite", typeName, moduleName );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/PropertyMapper.java b/core/api/src/main/java/org/qi4j/api/composite/PropertyMapper.java
deleted file mode 100644
index 054a369..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/PropertyMapper.java
+++ /dev/null
@@ -1,580 +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.qi4j.api.composite;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.Array;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.property.GenericPropertyInfo;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.util.Classes;
-import org.qi4j.api.util.Dates;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * Transfer java.util.Properties to Composite properties
- */
-public final class PropertyMapper
-{
-
-    private final static Map<Type, MappingStrategy> STRATEGY;
-
-    static
-    {
-        STRATEGY = new HashMap<>();
-        STRATEGY.put( Integer.class, new IntegerMapper() );
-        STRATEGY.put( Long.class, new LongMapper() );
-        STRATEGY.put( Short.class, new ShortMapper() );
-        STRATEGY.put( Byte.class, new ByteMapper() );
-        STRATEGY.put( String.class, new StringMapper() );
-        STRATEGY.put( Character.class, new CharMapper() );
-        STRATEGY.put( Float.class, new FloatMapper() );
-        STRATEGY.put( Double.class, new DoubleMapper() );
-        STRATEGY.put( Date.class, new DateMapper() );
-        STRATEGY.put( Boolean.class, new BooleanMapper() );
-        STRATEGY.put( BigDecimal.class, new BigDecimalMapper() );
-        STRATEGY.put( BigInteger.class, new BigIntegerMapper() );
-        STRATEGY.put( Enum.class, new EnumMapper() );
-        STRATEGY.put( Array.class, new ArrayMapper() );
-        STRATEGY.put( Map.class, new MapMapper() );
-        STRATEGY.put( List.class, new ListMapper() );
-        STRATEGY.put( Set.class, new SetMapper() );
-        STRATEGY.put( ValueComposite.class, new ValueCompositeMapper() );
-    }
-
-    /**
-     * Populate the Composite with properties from the given properties object.
-     *
-     * @param props     properties object
-     * @param composite the composite instance
-     *
-     * @throws IllegalArgumentException if properties could not be transferred to composite
-     */
-    public static void map( Properties props, Composite composite )
-        throws IllegalArgumentException
-    {
-        for( Map.Entry<Object, Object> objectObjectEntry : props.entrySet() )
-        {
-            try
-            {
-                String methodName = objectObjectEntry.getKey().toString();
-                Method propertyMethod = composite.getClass().getInterfaces()[ 0 ].getMethod( methodName );
-                propertyMethod.setAccessible( true );
-                Object value = objectObjectEntry.getValue();
-                Type propertyType = GenericPropertyInfo.propertyTypeOf( propertyMethod );
-
-                value = mapToType( composite, propertyType, value.toString() );
-
-                @SuppressWarnings( "unchecked" )
-                Property<Object> property = (Property<Object>) propertyMethod.invoke( composite );
-                property.set( value );
-            }
-            catch( NoSuchMethodException e )
-            {
-                throw new IllegalArgumentException( "Could not find any property named " + objectObjectEntry.getKey() );
-            }
-            catch( IllegalAccessException e )
-            {
-                //noinspection ThrowableInstanceNeverThrown
-                throw new IllegalArgumentException( "Could not populate property named " + objectObjectEntry.getKey(), e );
-            }
-            catch( InvocationTargetException e )
-            {
-                //noinspection ThrowableInstanceNeverThrown
-                String message = "Could not populate property named " + objectObjectEntry.getKey();
-                throw new IllegalArgumentException( message, e );
-            }
-        }
-    }
-
-    @SuppressWarnings( "raw" )
-    private static Object mapToType( Composite composite, Type propertyType, Object value )
-    {
-        final String stringValue = value.toString();
-        MappingStrategy strategy;
-        if( propertyType instanceof Class )
-        {
-            Class type = (Class) propertyType;
-            if( type.isArray() )
-            {
-                strategy = STRATEGY.get( Array.class );
-            }
-            else if( Enum.class.isAssignableFrom( Classes.RAW_CLASS.map( propertyType ) ) )
-            {
-                strategy = STRATEGY.get( Enum.class );
-            }
-            else
-            {
-                strategy = STRATEGY.get( type );
-            }
-            if( strategy == null  ) // If null, try with the ValueComposite Mapper...
-            {
-                strategy = STRATEGY.get( ValueComposite.class );
-            }
-        }
-        else if( propertyType instanceof ParameterizedType )
-        {
-            ParameterizedType type = ( (ParameterizedType) propertyType );
-
-            if( type.getRawType() instanceof Class )
-            {
-                Class clazz = (Class) type.getRawType();
-                if( List.class.isAssignableFrom( clazz ) )
-                {
-                    strategy = STRATEGY.get( List.class );
-                }
-                else if( Set.class.isAssignableFrom( clazz ) )
-                {
-                    strategy = STRATEGY.get( Set.class );
-                }
-                else if( Map.class.isAssignableFrom( clazz ) )
-                {
-                    strategy = STRATEGY.get( Map.class );
-                }
-                else
-                {
-                    throw new IllegalArgumentException( propertyType + " is not supported." );
-                }
-            }
-            else
-            {
-                throw new IllegalArgumentException( propertyType + " is not supported." );
-            }
-        }
-        else
-        {
-            throw new IllegalArgumentException( propertyType + " is not supported." );
-        }
-
-        if( strategy == null )
-        {
-            throw new IllegalArgumentException( propertyType + " is not supported." );
-        }
-
-        return strategy.map( composite, propertyType, stringValue );
-    }
-
-    /**
-     * Load a Properties object from the given stream, close it, and then populate
-     * the Composite with the properties.
-     *
-     * @param propertyInputStream properties input stream
-     * @param composite           the instance
-     *
-     * @throws IOException if the stream could not be read
-     */
-
-    public static void map( InputStream propertyInputStream, Composite composite )
-        throws IOException
-    {
-        if( propertyInputStream != null )
-        {
-            Properties configProps = new Properties();
-            try
-            {
-                configProps.load( propertyInputStream );
-            }
-            finally
-            {
-                propertyInputStream.close();
-            }
-            map( configProps, composite );
-        }
-    }
-
-    /**
-     * Create Properties object which is backed by the given Composite.
-     *
-     * @param composite the instance
-     *
-     * @return properties instance
-     */
-    public static Properties toJavaProperties( final Composite composite )
-    {
-        return new Properties()
-        {
-            private static final long serialVersionUID = 3550125427530538865L;
-
-            @Override
-            public Object get( Object o )
-            {
-                try
-                {
-                    Method propertyMethod = composite.getClass().getMethod( o.toString() );
-                    Property<?> property = (Property<?>) propertyMethod.invoke( composite );
-                    return property.get();
-                }
-                catch( NoSuchMethodException | IllegalAccessException | InvocationTargetException e )
-                {
-                    return null;
-                }
-            }
-
-            @Override
-            public Object put( Object o, Object o1 )
-            {
-                Object oldValue = get( o );
-
-                try
-                {
-                    Method propertyMethod = composite.getClass().getMethod( o.toString(), Object.class );
-                    propertyMethod.invoke( composite, o1 );
-                }
-                catch( NoSuchMethodException | IllegalAccessException | InvocationTargetException e )
-                {
-                    e.printStackTrace();
-                }
-
-                return oldValue;
-            }
-        };
-    }
-
-    private static void tokenize( String valueString, boolean mapSyntax, TokenizerCallback callback )
-    {
-        char[] data = valueString.toCharArray();
-
-        int oldPos = 0;
-        for( int pos = 0; pos < data.length; pos++ )
-        {
-            char ch = data[ pos ];
-            if( ch == '\"' )
-            {
-                pos = resolveQuotes( valueString, callback, data, pos, '\"' );
-                oldPos = pos;
-            }
-            if( ch == '\'' )
-            {
-                pos = resolveQuotes( valueString, callback, data, pos, '\'' );
-                oldPos = pos;
-            }
-            if( ch == ',' || ( mapSyntax && ch == ':' ) )
-            {
-                String token = new String( data, oldPos, pos - oldPos );
-                callback.token( token );
-                oldPos = pos + 1;
-            }
-        }
-        String token = new String( data, oldPos, data.length - oldPos );
-        callback.token( token );
-    }
-
-    private static int resolveQuotes( String valueString,
-                                      TokenizerCallback callback,
-                                      char[] data,
-                                      int pos, char quote
-    )
-    {
-        boolean found = false;
-        for( int j = pos + 1; j < data.length; j++ )
-        {
-            if( !found )
-            {
-                if( data[ j ] == quote )
-                {
-                    String token = new String( data, pos + 1, j - pos - 1 );
-                    callback.token( token );
-                    found = true;
-                }
-            }
-            else
-            {
-                if( data[ j ] == ',' )
-                {
-                    return j + 1;
-                }
-            }
-        }
-        if( !found )
-        {
-            throw new IllegalArgumentException( "String is not quoted correctly: " + valueString );
-        }
-        return data.length;
-    }
-
-    private interface TokenizerCallback
-    {
-        void token( String token );
-    }
-
-    private interface MappingStrategy
-    {
-        Object map( Composite composite, Type type, String value );
-    }
-
-    private static class StringMapper
-        implements MappingStrategy
-    {
-        @Override
-        public Object map( Composite composite, Type type, String value )
-        {
-            return value;
-        }
-    }
-
-    private static class IntegerMapper
-        implements MappingStrategy
-    {
-        @Override
-        public Object map( Composite composite, Type type, String value )
-        {
-            return new Integer( value.trim() );
-        }
-    }
-
-    private static class FloatMapper
-        implements MappingStrategy
-    {
-        @Override
-        public Object map( Composite composite, Type type, String value )
-        {
-            return new Float( value.trim() );
-        }
-    }
-
-    private static class DoubleMapper
-        implements MappingStrategy
-    {
-        @Override
-        public Object map( Composite composite, Type type, String value )
-        {
-            return new Double( value.trim() );
-        }
-    }
-
-    private static class LongMapper
-        implements MappingStrategy
-    {
-        @Override
-        public Object map( Composite composite, Type type, String value )
-        {
-            return new Long( value.trim() );
-        }
-    }
-
-    private static class ShortMapper
-        implements MappingStrategy
-    {
-        @Override
-        public Object map( Composite composite, Type type, String value )
-        {
-            return new Short( value.trim() );
-        }
-    }
-
-    private static class ByteMapper
-        implements MappingStrategy
-    {
-        @Override
-        public Object map( Composite composite, Type type, String value )
-        {
-            return new Byte( value.trim() );
-        }
-    }
-
-    private static class CharMapper
-        implements MappingStrategy
-    {
-        @Override
-        public Object map( Composite composite, Type type, String value )
-        {
-            return value.trim().charAt( 0 );
-        }
-    }
-
-    private static class BigDecimalMapper
-        implements MappingStrategy
-    {
-        @Override
-        public Object map( Composite composite, Type type, String value )
-        {
-            return new BigDecimal( value.trim() );
-        }
-    }
-
-    private static class BigIntegerMapper
-        implements MappingStrategy
-    {
-        @Override
-        public Object map( Composite composite, Type type, String value )
-        {
-            return new BigInteger( value.trim() );
-        }
-    }
-
-    private static class EnumMapper
-        implements MappingStrategy
-    {
-        @Override
-        @SuppressWarnings( "unchecked" )
-        public Object map( Composite composite, Type type, String value )
-        {
-            return Enum.valueOf( (Class<Enum>) type, value );
-        }
-    }
-
-    private static class DateMapper
-        implements MappingStrategy
-    {
-        @Override
-        public Object map( Composite composite, Type type, String value )
-        {
-            return Dates.fromString( value.trim() );
-        }
-    }
-
-    private static class ValueCompositeMapper
-        implements MappingStrategy
-    {
-        @Override
-        @SuppressWarnings( "unchecked" )
-        public Object map( Composite composite, Type type, String value )
-        {
-            return Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF.map( composite ).module().newValueFromSerializedState( (Class<Object>) type, value );
-        }
-    }
-
-    private static class ArrayMapper
-        implements MappingStrategy
-    {
-        @Override
-        @SuppressWarnings( {"raw", "unchecked"} )
-        public Object map( final Composite composite, Type type, String value )
-        {
-            final Class arrayType = ( (Class) type ).getComponentType();
-            final ArrayList result = new ArrayList();
-            tokenize( value, false, new TokenizerCallback()
-            {
-                @Override
-                public void token( String token )
-                {
-                    result.add( mapToType( composite, arrayType, token ) );
-                }
-            } );
-            return result.toArray( (Object[]) Array.newInstance( arrayType, result.size() ) );
-        }
-    }
-
-    private static class BooleanMapper
-        implements MappingStrategy
-    {
-        @Override
-        public Object map( final Composite composite, Type type, String value )
-        {
-            return Boolean.valueOf( value.trim() );
-        }
-    }
-
-    private static class ListMapper
-        implements MappingStrategy
-    {
-        @Override
-        @SuppressWarnings( {"raw", "unchecked"} )
-        public Object map( final Composite composite, Type type, String value )
-        {
-            final Type dataType = ( (ParameterizedType) type ).getActualTypeArguments()[ 0 ];
-            final Collection result = new ArrayList();
-            tokenize( value, false, new TokenizerCallback()
-            {
-                @Override
-                public void token( String token )
-                {
-                    result.add( mapToType( composite, dataType, token ) );
-                }
-            } );
-            return result;
-        }
-    }
-
-    private static class SetMapper
-        implements MappingStrategy
-    {
-        @Override
-        @SuppressWarnings( {"raw", "unchecked"} )
-        public Object map( final Composite composite, Type type, String value )
-        {
-            final Type dataType = ( (ParameterizedType) type ).getActualTypeArguments()[ 0 ];
-            final Collection result = new HashSet();
-            tokenize( value, false, new TokenizerCallback()
-            {
-                @Override
-                public void token( String token )
-                {
-                    result.add( mapToType( composite, dataType, token ) );
-                }
-            } );
-            return result;
-        }
-    }
-
-    private static class MapMapper
-        implements MappingStrategy
-    {
-        @Override
-        @SuppressWarnings( {"raw", "unchecked"} )
-        public Object map( final Composite composite, Type generictype, String value )
-        {
-            ParameterizedType type = (ParameterizedType) generictype;
-            final Type keyType = type.getActualTypeArguments()[ 0 ];
-            final Type valueType = type.getActualTypeArguments()[ 0 ];
-            final Map result = new HashMap();
-            tokenize( value, true, new TokenizerCallback()
-            {
-                boolean keyArrivingNext = true;
-                String key;
-
-                @Override
-                public void token( String token )
-                {
-                    if( keyArrivingNext )
-                    {
-                        key = token;
-                        keyArrivingNext = false;
-                    }
-                    else
-                    {
-                        result.put( mapToType( composite, keyType, key ), mapToType( composite, valueType, token ) );
-                        keyArrivingNext = true;
-                    }
-                }
-            } );
-            return result;
-        }
-    }
-
-    private PropertyMapper()
-    {
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/StateDescriptor.java b/core/api/src/main/java/org/qi4j/api/composite/StateDescriptor.java
deleted file mode 100644
index 3eebcd4..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/StateDescriptor.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.composite;
-
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.property.PropertyDescriptor;
-
-/**
- * Composite State Descriptor.
- */
-public interface StateDescriptor
-{
-    PropertyDescriptor findPropertyModelByName( String name )
-        throws IllegalArgumentException;
-
-    PropertyDescriptor findPropertyModelByQualifiedName( QualifiedName name )
-        throws IllegalArgumentException;
-
-    Iterable<? extends PropertyDescriptor> properties();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/StatefulCompositeDescriptor.java b/core/api/src/main/java/org/qi4j/api/composite/StatefulCompositeDescriptor.java
deleted file mode 100644
index ba44494..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/StatefulCompositeDescriptor.java
+++ /dev/null
@@ -1,27 +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.qi4j.api.composite;
-
-/**
- * Stateful Composite Descriptor.
- */
-public interface StatefulCompositeDescriptor
-{
-    StateDescriptor state();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/TransientBuilder.java b/core/api/src/main/java/org/qi4j/api/composite/TransientBuilder.java
deleted file mode 100644
index 58b4ef6..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/TransientBuilder.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*  Copyright 2007 Niclas Hedhman.
- *
- * Licensed 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.qi4j.api.composite;
-
-import org.qi4j.api.common.ConstructionException;
-
-/**
- * TransientBuilders are used to instantiate TransientComposites. They can be acquired from
- * {@link TransientBuilderFactory#newTransientBuilder(Class)} and allows the client
- * to provide additional settings before instantiating the TransientComposite.
- */
-public interface TransientBuilder<T>
-{
-    /**
-     * Provide objects that can be injected into mixins that has the @Uses
-     * dependency injection annotation.
-     *
-     * @param usedObjects The objects that can be injected into mixins.
-     *
-     * @return the transient builder instance
-     *
-     * @see org.qi4j.api.injection.scope.Uses
-     */
-    TransientBuilder<T> use( Object... usedObjects );
-
-    /**
-     * Get a representation of the state for the new Composite.
-     * It is possible to access and update properties and associations,
-     * even immutable ones since the builder represents the initial state.
-     *
-     * @return a proxy implementing the Composite type
-     */
-    T prototype();
-
-    /**
-     * Get a representation of the state of the given type for the new Composite.
-     * This is primarily used if you want to provide state for a private mixin type.
-     *
-     * @param mixinType the mixin which you want to provide state for
-     *
-     * @return a proxy implementing the given mixin type
-     */
-    <K> K prototypeFor( Class<K> mixinType );
-
-    /**
-     * Create a new Composite instance.
-     *
-     * @return a new Composite instance
-     *
-     * @throws ConstructionException thrown if it was not possible to instantiate the Composite
-     */
-    T newInstance()
-        throws ConstructionException;
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/TransientBuilderFactory.java b/core/api/src/main/java/org/qi4j/api/composite/TransientBuilderFactory.java
deleted file mode 100644
index b06c58f..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/TransientBuilderFactory.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.composite;
-
-import org.qi4j.api.common.ConstructionException;
-
-/**
- * This factory creates TransientComposites and the TransientBuilders.
- *
- * TransientComposite instances are very flexible in what it can reference, but are restricted in where they
- * can be used. So, TransientComposites are mainly recommended where Values, Entities and Services can not be used,
- * but they can also not be used to store state, be serialized across a network or have automatic equals/hashCode
- * calculations.
- */
-public interface TransientBuilderFactory
-{
-    /**
-     * Create a builder for creating new TransientComposites that implements the given TransientComposite type.
-     *
-     * @param mixinType an interface that describes the TransientComposite to be instantiated
-     *
-     * @return a TransientBuilder for creation of TransientComposites implementing the interface
-     *
-     * @throws NoSuchTransientException if no composite extending the mixinType has been registered
-     */
-    <T> TransientBuilder<T> newTransientBuilder( Class<T> mixinType )
-        throws NoSuchTransientException;
-
-    /**
-     * Instantiate a TransientComposite of the given type.
-     *
-     * @param mixinType the TransientComposite type to instantiate
-     *
-     * @return a new TransientComposite instance
-     *
-     * @throws NoSuchTransientException if no composite extending the mixinType has been registered
-     * @throws org.qi4j.api.common.ConstructionException
-     *                                  if the composite could not be instantiated
-     */
-    <T> T newTransient( Class<T> mixinType, Object... uses )
-        throws NoSuchTransientException, ConstructionException;
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/TransientComposite.java b/core/api/src/main/java/org/qi4j/api/composite/TransientComposite.java
deleted file mode 100644
index 8b21e88..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/TransientComposite.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.api.composite;
-
-/**
- * Transient Composite Type.
- *
- * TransientComposites have the following criteria;
- * <ul>
- * <li>Does not persist its state, and is not serializable</li>
- * <li>Can not be referenced from Properties, Associations, ValueComposites nor Entities</li>
- * <li>Can reference all types</li>
- * <li>No lifecycle</li>
- * <li>equals/hashCode is delegated to a single Mixin implementing the methods, like any other method</li>
- * </ul>
- */
-public interface TransientComposite
-    extends Composite
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/TransientDescriptor.java b/core/api/src/main/java/org/qi4j/api/composite/TransientDescriptor.java
deleted file mode 100644
index 0df706c..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/TransientDescriptor.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.composite;
-
-/**
- * TransientComposite Descriptor.
- */
-public interface TransientDescriptor
-    extends CompositeDescriptor, StatefulCompositeDescriptor
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/composite/package.html b/core/api/src/main/java/org/qi4j/api/composite/package.html
deleted file mode 100644
index 00feaed..0000000
--- a/core/api/src/main/java/org/qi4j/api/composite/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Composite API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/concern/ConcernDescriptor.java b/core/api/src/main/java/org/qi4j/api/concern/ConcernDescriptor.java
deleted file mode 100644
index a98adf7..0000000
--- a/core/api/src/main/java/org/qi4j/api/concern/ConcernDescriptor.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.concern;
-
-/**
- * Concern descriptor.
- */
-public interface ConcernDescriptor
-{
-    Class modifierClass();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/concern/ConcernOf.java b/core/api/src/main/java/org/qi4j/api/concern/ConcernOf.java
deleted file mode 100644
index 33cdd01..0000000
--- a/core/api/src/main/java/org/qi4j/api/concern/ConcernOf.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.api.concern;
-
-import org.qi4j.api.concern.internal.ConcernFor;
-
-/**
- * Base class for Concerns. It introduces a typed "next" pointer
- * that Concerns can use to invoke the next Concern (or mixin) in
- * the chain.
- * <p>
- * Generic Concerns should subclass {@link GenericConcern} instead.
- * </p>
- * <p>
- * Concerns implementations must be thread-safe in their implementation,
- * as multiple threads may share instances.
- * </p>
- */
-public abstract class ConcernOf<T>
-{
-    /**
-     * The "next" pointer. This points to
-     * the next concern in the chain or the mixin
-     * to be invoked.
-     */
-    final
-    @ConcernFor
-    protected T next = null;
-}
diff --git a/core/api/src/main/java/org/qi4j/api/concern/Concerns.java b/core/api/src/main/java/org/qi4j/api/concern/Concerns.java
deleted file mode 100644
index 9213035..0000000
--- a/core/api/src/main/java/org/qi4j/api/concern/Concerns.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.concern;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This annotation is used by composites and mixins to declare what Concerns
- * should be applied to the type or specific method.
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.TYPE, ElementType.METHOD } )
-@Documented
-public @interface Concerns
-{
-    Class<?>[] value();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/concern/ConcernsDescriptor.java b/core/api/src/main/java/org/qi4j/api/concern/ConcernsDescriptor.java
deleted file mode 100644
index dd9a91b..0000000
--- a/core/api/src/main/java/org/qi4j/api/concern/ConcernsDescriptor.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.api.concern;
-
-/**
- * Concerns descriptor.
- */
-public interface ConcernsDescriptor
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/concern/GenericConcern.java b/core/api/src/main/java/org/qi4j/api/concern/GenericConcern.java
deleted file mode 100644
index 2986ff8..0000000
--- a/core/api/src/main/java/org/qi4j/api/concern/GenericConcern.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.api.concern;
-
-import java.lang.reflect.InvocationHandler;
-
-/**
- * Base class for generic Concerns. Subclass
- * and implement the "invoke" method. Use the
- * "next" field in {@link ConcernOf} to continue the invocation
- * chain.
- */
-public abstract class GenericConcern
-    extends ConcernOf<InvocationHandler>
-    implements InvocationHandler
-{
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/concern/internal/ConcernFor.java b/core/api/src/main/java/org/qi4j/api/concern/internal/ConcernFor.java
deleted file mode 100644
index de3e1b4..0000000
--- a/core/api/src/main/java/org/qi4j/api/concern/internal/ConcernFor.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.concern.internal;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.qi4j.api.injection.InjectionScope;
-
-/**
- * This annotation is required once in each Concern, to mark the
- * field where the next element in the call sequence should be
- * injected.
- * <p>
- * The type of the field must be of the same type as the Concern
- * itself, or an InvocationHandler.
- * </p>
- * <p>
- * Example;
- * </p>
- * <pre><code>
- * public interface MyStuff
- * {
- *     void doSomething();
- * }
- *
- * public class MyStuffConcern
- *     implements MyStuff
- * {
- *     &#64;ConcernFor MyStuff next;
- *
- *     public void doSomething()
- *     {
- *         // HERE DO THE MODIFIER STUFF.
- *
- *         // Delegate to the underlying mixin/modifier.
- *         next.doSomething();
- *     }
- * }
- * </code></pre>
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.FIELD, ElementType.PARAMETER } )
-@Documented
-@InjectionScope
-public @interface ConcernFor
-{
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/concern/internal/package.html b/core/api/src/main/java/org/qi4j/api/concern/internal/package.html
deleted file mode 100644
index 9351f10..0000000
--- a/core/api/src/main/java/org/qi4j/api/concern/internal/package.html
+++ /dev/null
@@ -1,25 +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.
--->
-<html>
-    <body>
-        <h1>Internal/Private package for the Concern API.</h1>
-        <p>
-            This is an internal package, and no classes in this package is part of the API and compatibility
-            with these classes will not be attempted.
-        </p>
-    </body>
-</html>
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/concern/package.html b/core/api/src/main/java/org/qi4j/api/concern/package.html
deleted file mode 100644
index fcc7ef7..0000000
--- a/core/api/src/main/java/org/qi4j/api/concern/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Concern API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/configuration/Configuration.java b/core/api/src/main/java/org/qi4j/api/configuration/Configuration.java
deleted file mode 100644
index 77c373d..0000000
--- a/core/api/src/main/java/org/qi4j/api/configuration/Configuration.java
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.api.configuration;
-
-import java.io.IOException;
-import java.io.InputStream;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.composite.PropertyMapper;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.service.qualifier.ServiceTags;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.EntityTypeNotFoundException;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.api.value.ValueSerialization;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Provide Configurations for Services. A Service that wants to be configurable
- * should inject a reference to Configuration with the Configuration type:
- * <pre><code>
- *  * &#64;This Configuration&#60;MyServiceConfiguration&#62; config;
- * </code></pre>
- * <p>
- * where MyServiceConfiguration extends {@link ConfigurationComposite}, which itself is an ordinary
- * {@link org.qi4j.api.entity.EntityComposite}. The Configuration implementation
- * will either locate an instance of the given Configuration type in the
- * persistent store using the identity of the Service, or create a new such instance
- * if one doesn't already exist.
- * </p>
- * <p>
- * If a new Configuration instance is created then it will be populated with properties
- * from the properties file whose filesystem name is the same as the identity (e.g. "MyService.properties").
- * If a service is not given a name via the {@code org.qi4j.bootstrap.ServiceDeclaration#identifiedBy(String)}, the
- * name will default to the FQCN of the ServiceComposite type.
- * </p>
- * <p>
- * The Configuration instance can be modified externally just like any other EntityComposite, but
- * its values will not be updated in the Service until {@link #refresh()} is called. This allows
- * safe reloads of Configuration state to ensure that it is not reloaded while the Service is handling
- * a request.
- * </p>
- * <p>
- * The Configuration will be automatically refreshed when the Service is activated by the Zest runtime.
- * Any refreshes at other points will have to be done manually or triggered through some other
- * mechanism.
- * </p>
- * <p>
- * The user configuration entity is part of a long running {@link UnitOfWork}, and to persist changes to it the
- * {@link #save()} method must be called. No other actions are required. Example;
- * </p>
- * <pre><code>
- *
- * public interface MyConfiguration extends ConfigurationComposite
- * {
- *     Property&lt;Long&gt; timeout();
- * }
- *
- * :
- *
- * &#64;This Configuration&lt;MyConfiguration&gt; config;
- * :
- * private void setTimeoutConfiguration( long timeout )
- * {
- *     config.get().timeout().set( timeout );
- *     config.save();
- * }
- * </code></pre>
- * <p>
- * And even if a separate thread is using the {@code timeout()} configuration when this is happening, the
- * {@link UnitOfWork} isolation will ensure that the other thread is not affected. That thread, on the other hand
- * will need to do a {@link #refresh()} at an appropriate time to pick up the timeout change. For instance;
- * </p>
- * <pre><code>
- *
- * &#64;Service InventoryService remoteInventoryService;
- *
- * public void restockInventoryItem( InventoryItemId id, int itemCount )
- * {
- *     config.refresh();
- *     long timeout = config.get().timeout().get();
- *
- *     remoteInventoryService.restock( id, itemCount, timeout );
- *
- *     :
- *     :
- * }
- * </code></pre>
- */
-@SuppressWarnings( "JavadocReference" )
-@Mixins( Configuration.ConfigurationMixin.class )
-public interface Configuration<T>
-{
-    /**
-     * Retrieves the user configuration instance managed by this Configuration.
-     * <p>
-     * Even if the user configuration is initialized from properties file, the consistency rules of Zest composites
-     * still applies. If the the properties file is missing a value, then the initialization will fail with a
-     * RuntimeException. If Constraints has been defined, those will need to be satisfied as well. The user
-     * configuration instance returned will fulfill the constraints and consistency normal to all composites, and
-     * can therefor safely be used with additional checks.
-     * </p>
-     *
-     * @return The fully initialized and ready-to-use user configuration instance.
-     */
-    T get();
-
-    /**
-     * Updates the values of the managed user ConfigurationComposite instance from the underlying
-     * {@code org.qi4j.spi.entitystore.EntityStore}.  Any modified values in the current user configuration that
-     * has not been saved, via {@link #save()} method, will be lost.
-     */
-    void refresh();
-
-    /**
-     * Persists the modified values in the user configuration instance to the underlying store.
-     */
-    void save();
-
-    /**
-     * Implementation of Configuration.
-     * <p>
-     * This is effectively an internal class in Zest and should never be used directly by user code.
-     * </p>
-     *
-     * @param <T>
-     */
-    public class ConfigurationMixin<T>
-        implements Configuration<T>
-    {
-        private T configuration;
-        private UnitOfWork uow;
-
-        @Structure
-        private Qi4j api;
-
-        @This
-        private ServiceComposite me;
-
-        @Structure
-        private Module module;
-
-        @Service
-        private Iterable<ServiceReference<ValueSerialization>> valueSerialization;
-
-        public ConfigurationMixin()
-        {
-        }
-
-        @Override
-        public synchronized T get()
-        {
-            if( configuration == null )
-            {
-                Usecase usecase = UsecaseBuilder.newUsecase( "Configuration:" + me.identity().get() );
-                uow = module.newUnitOfWork( usecase );
-                try
-                {
-                    configuration = this.findConfigurationInstanceFor( me, uow );
-                }
-                catch( InstantiationException e )
-                {
-                    throw new IllegalStateException( e );
-                }
-            }
-
-            return configuration;
-        }
-
-        @Override
-        public synchronized void refresh()
-        {
-            if( configuration != null )
-            {
-                configuration = null;
-                uow.discard();
-                uow = null;
-            }
-        }
-
-        @Override
-        public void save()
-        {
-            if( uow != null )
-            {
-                try
-                {
-                    uow.complete();
-                    uow = null;
-                }
-                catch( UnitOfWorkCompletionException e )
-                {
-                    // Should be impossible
-                    e.printStackTrace();
-                }
-
-                configuration = null; // Force refresh
-            }
-        }
-
-        @SuppressWarnings( "unchecked" )
-        public <V> V findConfigurationInstanceFor( ServiceComposite serviceComposite, UnitOfWork uow )
-            throws InstantiationException
-        {
-            ServiceDescriptor serviceModel = api.serviceDescriptorFor( serviceComposite );
-
-            String identity = serviceComposite.identity().get();
-            V configuration;
-            try
-            {
-                configuration = uow.get( serviceModel.<V>configurationType(), identity );
-                uow.pause();
-            }
-            catch( NoSuchEntityException | EntityTypeNotFoundException e )
-            {
-                return (V) initializeConfigurationInstance( serviceComposite, uow, serviceModel, identity );
-            }
-            return configuration;
-        }
-
-        @SuppressWarnings( "unchecked" )
-        private <V extends Identity> V initializeConfigurationInstance( ServiceComposite serviceComposite,
-                                                                        UnitOfWork uow,
-                                                                        ServiceDescriptor serviceModel,
-                                                                        String identity
-        )
-            throws InstantiationException
-        {
-            Module module = api.moduleOf( serviceComposite );
-            Usecase usecase = UsecaseBuilder.newUsecase( "Configuration:" + me.identity().get() );
-            UnitOfWork buildUow = module.newUnitOfWork( usecase );
-
-            Class<?> type = first( api.serviceDescriptorFor( serviceComposite ).types() );
-            Class<V> configType = serviceModel.configurationType();
-
-            // Check for defaults
-            V config = tryLoadPropertiesFile( buildUow, type, configType, identity );
-            if( config == null )
-            {
-                config = tryLoadJsonFile( buildUow, type, configType, identity );
-                if( config == null )
-                {
-                    config = tryLoadYamlFile( buildUow, type, configType, identity );
-                    if( config == null )
-                    {
-                        config = tryLoadXmlFile( buildUow, type, configType, identity );
-                        if( config == null )
-                        {
-                            try
-                            {
-                                EntityBuilder<V> configBuilder = buildUow.newEntityBuilder( serviceModel.<V>configurationType(), identity );
-                                configBuilder.newInstance();
-                            }
-                            catch( ConstraintViolationException e )
-                            {
-                                throw new NoSuchConfigurationException( configType, identity, e );
-                            }
-                        }
-                    }
-                }
-            }
-
-            try
-            {
-                buildUow.complete();
-
-                // Try again
-                return (V) findConfigurationInstanceFor( serviceComposite, uow );
-            }
-            catch( Exception e1 )
-            {
-                InstantiationException ex = new InstantiationException(
-                    "Could not instantiate configuration, and no configuration initialization file was found (" + identity + ")" );
-                ex.initCause( e1 );
-                throw ex;
-            }
-        }
-
-        private <C, V> V tryLoadPropertiesFile( UnitOfWork buildUow,
-                                                Class<C> compositeType,
-                                                Class<V> configType,
-                                                String identity
-        )
-            throws InstantiationException
-        {
-            EntityBuilder<V> configBuilder = buildUow.newEntityBuilder( configType, identity );
-            String resourceName = identity + ".properties";
-            InputStream asStream = getResource( compositeType, resourceName );
-            if( asStream != null )
-            {
-                try
-                {
-                    PropertyMapper.map( asStream, (Composite) configBuilder.instance() );
-                    return configBuilder.newInstance();
-                }
-                catch( IOException e1 )
-                {
-                    InstantiationException exception = new InstantiationException(
-                        "Could not read underlying Properties file." );
-                    exception.initCause( e1 );
-                    throw exception;
-                }
-            }
-            return null;
-        }
-
-        private InputStream getResource( Class<?> type, String resourceName )
-        {
-            // Load defaults from classpath root if available
-            if( type.getResource( resourceName ) == null && type.getResource( "/" + resourceName ) != null )
-            {
-                resourceName = "/" + resourceName;
-            }
-            return type.getResourceAsStream( resourceName );
-        }
-
-        private <C, V extends Identity> V tryLoadJsonFile( UnitOfWork uow,
-                                                           Class<C> compositeType,
-                                                           Class<V> configType,
-                                                           String identity
-        )
-        {
-            return readConfig( uow, compositeType, configType, identity, ValueSerialization.Formats.JSON, ".json" );
-        }
-
-        private <C, V extends Identity> V tryLoadYamlFile( UnitOfWork uow,
-                                                           Class<C> compositeType,
-                                                           Class<V> configType,
-                                                           String identity
-        )
-        {
-            return readConfig( uow, compositeType, configType, identity, ValueSerialization.Formats.YAML, ".yaml" );
-        }
-
-        private <C, V extends Identity> V tryLoadXmlFile( UnitOfWork uow,
-                                                          Class<C> compositeType,
-                                                          Class<V> configType,
-                                                          String identity
-        )
-        {
-            return readConfig( uow, compositeType, configType, identity, ValueSerialization.Formats.XML, ".xml" );
-        }
-
-        private <C, V extends Identity> V readConfig( UnitOfWork uow,
-                                                      Class<C> compositeType,
-                                                      Class<V> configType,
-                                                      String identity,
-                                                      String format,
-                                                      String extension
-        )
-        {
-            for( ServiceReference<ValueSerialization> serializerRef : valueSerialization )
-            {
-                ServiceTags serviceTags = serializerRef.metaInfo( ServiceTags.class );
-                if( serviceTags.hasTag( format ) )
-                {
-                    String resourceName = identity + extension;
-                    InputStream asStream = getResource( compositeType, resourceName );
-                    if( asStream != null )
-                    {
-                        V configObject = serializerRef.get().deserialize( configType, asStream );
-                        return uow.toEntity( configType, configObject );
-                    }
-                }
-            }
-            return null;
-        }
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/configuration/ConfigurationComposite.java b/core/api/src/main/java/org/qi4j/api/configuration/ConfigurationComposite.java
deleted file mode 100644
index 39fb149..0000000
--- a/core/api/src/main/java/org/qi4j/api/configuration/ConfigurationComposite.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.configuration;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.entity.Queryable;
-
-/**
- * Services that want to be configurable should have a ConfigurationComposite that contains all the settings.
- * They are treated as EntityComposites, and are therefore stored in an EntityStore. There will be one instance
- * per service instance that uses each ConfigurationComposite, and the identity of the entity is the same as that
- * of the service.
- */
-@Queryable( false )
-public interface ConfigurationComposite
-    extends Identity, Composite
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/configuration/Enabled.java b/core/api/src/main/java/org/qi4j/api/configuration/Enabled.java
deleted file mode 100644
index 19a2c29..0000000
--- a/core/api/src/main/java/org/qi4j/api/configuration/Enabled.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.configuration;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-
-/**
- * Common configuration for setting whether a service is enabled or not. A disabled service
- * is not considered to be available. Let your own ConfigurationComposite extend this interface to use.
- */
-public interface Enabled
-{
-    @UseDefaults
-    Property<Boolean> enabled();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/configuration/NoSuchConfigurationException.java b/core/api/src/main/java/org/qi4j/api/configuration/NoSuchConfigurationException.java
deleted file mode 100644
index b3d3ed1..0000000
--- a/core/api/src/main/java/org/qi4j/api/configuration/NoSuchConfigurationException.java
+++ /dev/null
@@ -1,48 +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.qi4j.api.configuration;
-
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.entity.Identity;
-
-public class NoSuchConfigurationException extends RuntimeException
-{
-    private final Class<? extends Identity> configType;
-    private final String identity;
-
-    public NoSuchConfigurationException( Class<? extends Identity> configType,
-                                         String identity,
-                                         ConstraintViolationException cause
-    )
-    {
-        super( "No configuration found for '" + identity + "' and configuration " + configType.getName() + " has one or more non-Optional properties.", cause );
-        this.configType = configType;
-        this.identity = identity;
-    }
-
-    public Class<? extends Identity> configType()
-    {
-        return configType;
-    }
-
-    public String identity()
-    {
-        return identity;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/configuration/package.html b/core/api/src/main/java/org/qi4j/api/configuration/package.html
deleted file mode 100644
index 7f8a892..0000000
--- a/core/api/src/main/java/org/qi4j/api/configuration/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Configuration API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/constraint/Constraint.java b/core/api/src/main/java/org/qi4j/api/constraint/Constraint.java
deleted file mode 100644
index 8e53e0e..0000000
--- a/core/api/src/main/java/org/qi4j/api/constraint/Constraint.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.constraint;
-
-import java.io.Serializable;
-import java.lang.annotation.Annotation;
-
-/**
- * All Constraints must implement this interface, which is used for each
- * value validation.
- */
-public interface Constraint<ANNOTATION extends Annotation, TYPE>
-    extends Serializable
-{
-    /**
-     * For each value or parameter which should be checked this method will be invoked.
-     * If the method returns true the value is valid. If it returns false the value
-     * is considered invalid. When all constraints have been checked a ConstraintViolationException
-     * will be thrown with all the constraint violations that were found.
-     *
-     * @param annotation the annotation to match
-     * @param value      the value to be checked
-     *
-     * @return true if valid, false if invalid
-     */
-    boolean isValid( ANNOTATION annotation, TYPE value );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintDeclaration.java b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintDeclaration.java
deleted file mode 100644
index 7ca9249..0000000
--- a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintDeclaration.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.constraint;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * All annotations that are used to trigger Constraints must have this annotation.
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( ElementType.ANNOTATION_TYPE )
-@Documented
-public @interface ConstraintDeclaration
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintDescriptor.java b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintDescriptor.java
deleted file mode 100644
index ff5e5a6..0000000
--- a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintDescriptor.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.constraint;
-
-import java.lang.annotation.Annotation;
-
-/**
- * Constraint Descriptor.
- */
-public interface ConstraintDescriptor
-{
-    Annotation annotation();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintImplementationNotFoundException.java b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintImplementationNotFoundException.java
deleted file mode 100644
index e27ef94..0000000
--- a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintImplementationNotFoundException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.constraint;
-
-import org.qi4j.api.common.InvalidApplicationException;
-
-/**
- * This exception is thrown if a Constraint implementation can not be found.
- */
-public class ConstraintImplementationNotFoundException
-    extends InvalidApplicationException
-{
-    public ConstraintImplementationNotFoundException( String message )
-    {
-        super( message );
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintViolation.java b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintViolation.java
deleted file mode 100644
index 09c4be0..0000000
--- a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintViolation.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.constraint;
-
-import java.io.Serializable;
-import java.lang.annotation.Annotation;
-
-/**
- * When a constraint violation has occurred (ie Constraint.isValid has returned false) it
- * is put in a collection of all violations that have occurred for this value check.
- */
-public final class ConstraintViolation
-    implements Serializable
-{
-    private String name;
-    private final Annotation constraint;
-    private final Object value;
-
-    public ConstraintViolation( String name, Annotation constraint, Object value )
-    {
-        this.name = name;
-        this.constraint = constraint;
-        this.value = value;
-    }
-
-    public String name()
-    {
-        return name;
-    }
-
-    public Annotation constraint()
-    {
-        return constraint;
-    }
-
-    public Object value()
-    {
-        return value;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintViolationException.java b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintViolationException.java
deleted file mode 100644
index 28e41b3..0000000
--- a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintViolationException.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.api.constraint;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Member;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-
-/**
- * This Exception is thrown when there is one or more Constraint Violations in a method
- * call.
- * <p>
- * The Constraint Violations are aggregated per method, and this exception will contain those
- * violations, together with the Composite instance it happened on as well as the Method that
- * was invoked. The Exception also has support for localized messages of these violations.
- * </p>
- */
-public class ConstraintViolationException
-    extends IllegalArgumentException
-{
-    private static final long serialVersionUID = 1L;
-
-    private final Collection<ConstraintViolation> constraintViolations;
-    private String methodName;
-    private String mixinTypeName;
-    private String instanceToString;
-    private Iterable<Class<?>> instanceTypes;
-
-    public ConstraintViolationException( Composite instance, Member method,
-                                         Collection<ConstraintViolation> constraintViolations
-    )
-    {
-        this( instance.toString(), Qi4j.FUNCTION_DESCRIPTOR_FOR.map( instance ).types(), method, constraintViolations );
-    }
-
-    public ConstraintViolationException( String instanceToString,
-                                         Iterable<Class<?>> instanceTypes,
-                                         Member method,
-                                         Collection<ConstraintViolation> violations
-    )
-    {
-        this.instanceToString = instanceToString;
-        this.instanceTypes = instanceTypes;
-        mixinTypeName = method.getDeclaringClass().getName();
-        methodName = method.getName();
-        this.constraintViolations = violations;
-    }
-
-    public ConstraintViolationException( String instanceToString,
-                                         Iterable<Class<?>> instanceTypes,
-                                         String mixinTypeName,
-                                         String methodName,
-                                         Collection<ConstraintViolation> violations
-    )
-    {
-        this.instanceToString = instanceToString;
-        this.instanceTypes = instanceTypes;
-        this.mixinTypeName = mixinTypeName;
-        this.methodName = methodName;
-        this.constraintViolations = violations;
-    }
-
-    public Collection<ConstraintViolation> constraintViolations()
-    {
-        return constraintViolations;
-    }
-
-    /**
-     * Creates localized messages of all the constraint violations that has occured.
-     * <p>
-     * The key "<code>Qi4j_ConstraintViolation_<i><strong>CompositeType</strong></i></code>" will be used to lookup the text formatting
-     * pattern from the ResourceBundle, where <strong><code><i>CompositeType</i></code></strong> is the
-     * class name of the Composite where the constraint was violated. If such key does not exist, then the
-     * key &nbsp;"<code>Qi4j_ConstraintViolation</code>" will be used, and if that one also doesn't exist, or
-     * the resourceBundle argument is null, then the default patterns will be used;
-     * </p>
-     * <table summary="Localization of constraint vioations.">
-     * <tr><th>Type of Composite</th><th>Pattern used</th></tr>
-     * <tr><td>Composite</td>
-     * <td><code>Constraint Violation in {2}.{3} with constraint {4}, in composite \n{0} of type {1}</code></td>
-     * </tr>
-     * <tr><td>EntityComposite</td>
-     * <td><code>Constraint Violation in {2}.{3} with constraint {4}, in entity {1}[id={0}]</code></td>
-     * </tr>
-     * <tr><td>ServiceComposite</td>
-     * <td><code>Constraint Violation in {2}.{3} with constraint {4}, in service {0}</code></td>
-     * </tr>
-     * </table>
-     * Then format each ConstraintViolation according to such pattern, where the following argument are passed;
-     * <table summary="List of arguments available."><tr><th>Arg</th><th>Value</th></tr>
-     * <tr>
-     * <td>{0}</td>
-     * <td>Composite instance toString()</td>
-     * </tr>
-     * <tr>
-     * <td>{1}</td>
-     * <td>CompositeType class name</td>
-     * </tr>
-     * <tr>
-     * <td>{2}</td>
-     * <td>MixinType class name</td>
-     * </tr>
-     * <tr>
-     * <td>{3}</td>
-     * <td>MixinType method name</td>
-     * </tr>
-     * <tr>
-     * <td>{4}</td>
-     * <td>Annotation toString()</td>
-     * </tr>
-     * <tr>
-     * <td>{5}</td>
-     * <td>toString() of value passed as the argument, or "null" text if argument was null.</td>
-     * </tr>
-     * </table>
-     * <p>
-     * <b>NOTE!!!</b> This class is still under construction and will be modified further.
-     * </p>
-     *
-     * @param bundle The ResourceBundle for Localization, or null if default formatting and locale to be used.
-     *
-     * @return An array of localized messages of the violations incurred.
-     */
-    public String[] localizedMessagesFrom( ResourceBundle bundle )
-    {
-        String pattern = "Constraint violation in {0}.{1} for method ''{3}'' with constraint \"{4}({6})\", for value ''{5}''";
-
-        ArrayList<String> list = new ArrayList<String>();
-        for( ConstraintViolation violation : constraintViolations )
-        {
-            Locale locale;
-            if( bundle != null )
-            {
-                try
-                {
-                    pattern = bundle.getString( "qi4j.constraint." + mixinTypeName + "." + methodName );
-                }
-                catch( MissingResourceException e1 )
-                {
-                    try
-                    {
-                        pattern = bundle.getString( "qi4j.constraint" );
-                    }
-                    catch( MissingResourceException e2 )
-                    {
-                        // ignore. The default pattern will be used.
-                    }
-                }
-                locale = bundle.getLocale();
-            }
-            else
-            {
-                locale = Locale.getDefault();
-            }
-            MessageFormat format = new MessageFormat( pattern, locale );
-
-            Annotation annotation = violation.constraint();
-            String name = violation.name();
-            Object value = violation.value();
-            String classes;
-            if( Iterables.count( instanceTypes ) == 1 )
-            {
-                classes = Iterables.first( instanceTypes ).getSimpleName();
-            }
-            else
-            {
-                classes = "[" + Iterables.<Class<?>>toString( instanceTypes, new Function<Class<?>, String>()
-                {
-                    @Override
-                    public String map( Class<?> from )
-                    {
-                        return from.getSimpleName();
-                    }
-                }, "," ) + "]";
-            }
-            Object[] args = new Object[]
-                {
-                    instanceToString,
-                    classes,
-                    mixinTypeName,
-                    methodName,
-                    annotation.toString(),
-                    "" + value,
-                    name
-                };
-            StringBuffer text = new StringBuffer();
-            format.format( args, text, null );
-            list.add( text.toString() );
-        }
-        String[] result = new String[ list.size() ];
-        list.toArray( result );
-        return result;
-    }
-
-    public String localizedMessage()
-    {
-        String[] messages = localizedMessagesFrom( null );
-        StringBuilder result = new StringBuilder();
-        boolean first = true;
-        for( String message : messages )
-        {
-            if( !first )
-            {
-                result.append( ',' );
-            }
-            first = false;
-            result.append( message );
-        }
-        return result.toString();
-    }
-
-    @Override
-    public String getLocalizedMessage()
-    {
-        return localizedMessage();
-    }
-
-    @Override
-    public String getMessage()
-    {
-        return localizedMessage();
-    }
-
-    public String methodName()
-    {
-        return methodName;
-    }
-
-    public String mixinTypeName()
-    {
-        return mixinTypeName;
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/constraint/Constraints.java b/core/api/src/main/java/org/qi4j/api/constraint/Constraints.java
deleted file mode 100644
index b42701c..0000000
--- a/core/api/src/main/java/org/qi4j/api/constraint/Constraints.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.constraint;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This annotation is used by composites and mixins to declare what Constraints
- * can be applied in the Composite.
- * <p>
- * Constraints implement the {@link Constraint} interface
- * </p>
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.TYPE } )
-@Documented
-public @interface Constraints
-{
-    Class<? extends Constraint<?, ?>>[] value();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintsDescriptor.java b/core/api/src/main/java/org/qi4j/api/constraint/ConstraintsDescriptor.java
deleted file mode 100644
index bea1115..0000000
--- a/core/api/src/main/java/org/qi4j/api/constraint/ConstraintsDescriptor.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.constraint;
-
-/**
- * Constraints Descriptor.
- */
-public interface ConstraintsDescriptor
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/constraint/Name.java b/core/api/src/main/java/org/qi4j/api/constraint/Name.java
deleted file mode 100644
index fc4c79e..0000000
--- a/core/api/src/main/java/org/qi4j/api/constraint/Name.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.constraint;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation for parameter names. This is used to add extra information for constraint exception.
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.PARAMETER } )
-@Documented
-public @interface Name
-{
-    String value();
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/constraint/package.html b/core/api/src/main/java/org/qi4j/api/constraint/package.html
deleted file mode 100644
index 2e4d340..0000000
--- a/core/api/src/main/java/org/qi4j/api/constraint/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Constraint API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/dataset/DataSet.java b/core/api/src/main/java/org/qi4j/api/dataset/DataSet.java
deleted file mode 100644
index 2e4bdc3..0000000
--- a/core/api/src/main/java/org/qi4j/api/dataset/DataSet.java
+++ /dev/null
@@ -1,36 +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.qi4j.api.dataset;
-
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Specification;
-
-/**
- * definition.constrain(entity(Person.class))
- * builder.from(path(Person.class,Movie.))
- * TODO
- */
-public interface DataSet<T>
-{
-    DataSet<T> constrain( Specification<T> selection );
-
-    <U> DataSet<U> project( Function<T, U> conversion );
-
-    Query<T> newQuery();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/dataset/DataSetSource.java b/core/api/src/main/java/org/qi4j/api/dataset/DataSetSource.java
deleted file mode 100644
index 4cf68f1..0000000
--- a/core/api/src/main/java/org/qi4j/api/dataset/DataSetSource.java
+++ /dev/null
@@ -1,27 +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.qi4j.api.dataset;
-
-/**
- * TODO
- */
-public interface DataSetSource
-{
-    <T> DataSet<T> newDataSet( Class<T> type );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/dataset/Query.java b/core/api/src/main/java/org/qi4j/api/dataset/Query.java
deleted file mode 100644
index 61edd73..0000000
--- a/core/api/src/main/java/org/qi4j/api/dataset/Query.java
+++ /dev/null
@@ -1,64 +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.qi4j.api.dataset;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.QueryException;
-import org.qi4j.api.query.QueryExecutionException;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.Visitor;
-
-/**
- * TODO
- */
-public interface Query<T>
-{
-    public enum Order
-    {
-        ASCENDING, DESCENDING
-    }
-
-    Query filter( Specification<T> filter );
-
-    Query orderBy( final Property<?> property, final Order order );
-
-    Query skip( int skipNrOfResults );
-
-    Query limit( int maxNrOfResults );
-
-    // Variables
-    Query<T> setVariable( String name, Object value );
-
-    Object getVariable( String name );
-
-    long count()
-        throws QueryExecutionException;
-
-    T first()
-        throws QueryExecutionException;
-
-    T single()
-        throws QueryException;
-
-    <ThrowableType extends Throwable> boolean execute( Visitor<T, ThrowableType> resultVisitor )
-        throws ThrowableType, QueryExecutionException;
-
-    Iterable<T> toIterable()
-        throws QueryExecutionException;
-}
diff --git a/core/api/src/main/java/org/qi4j/api/dataset/iterable/IterableDataSet.java b/core/api/src/main/java/org/qi4j/api/dataset/iterable/IterableDataSet.java
deleted file mode 100644
index 3300ea4..0000000
--- a/core/api/src/main/java/org/qi4j/api/dataset/iterable/IterableDataSet.java
+++ /dev/null
@@ -1,57 +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.qi4j.api.dataset.iterable;
-
-import org.qi4j.api.dataset.DataSet;
-import org.qi4j.api.dataset.Query;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-
-/**
- * TODO
- */
-public class IterableDataSet<T>
-    implements DataSet<T>
-{
-    private Iterable<T> iterable;
-
-    public IterableDataSet( Iterable<T> iterable )
-    {
-        this.iterable = iterable;
-    }
-
-    @Override
-    public DataSet<T> constrain( Specification<T> selection )
-    {
-        return new IterableDataSet<T>( Iterables.filter( selection, iterable ) );
-    }
-
-    @Override
-    public <U> DataSet<U> project( Function<T, U> conversion )
-    {
-        return new IterableDataSet<U>( Iterables.map( conversion, iterable ) );
-    }
-
-    @Override
-    public Query<T> newQuery()
-    {
-        return new IterableQuery<T>( iterable );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/dataset/iterable/IterableQuery.java b/core/api/src/main/java/org/qi4j/api/dataset/iterable/IterableQuery.java
deleted file mode 100644
index b816a25..0000000
--- a/core/api/src/main/java/org/qi4j/api/dataset/iterable/IterableQuery.java
+++ /dev/null
@@ -1,127 +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.qi4j.api.dataset.iterable;
-
-import java.util.HashMap;
-import java.util.Map;
-import org.qi4j.api.dataset.Query;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.QueryException;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.Visitor;
-
-/**
- * TODO
- */
-public class IterableQuery<T> implements Query<T>
-{
-    private Iterable<T> iterable;
-    private int skip;
-    private int limit;
-    private Map<String, Object> variables = new HashMap<String, Object>();
-
-    public IterableQuery( Iterable<T> iterable )
-    {
-        this.iterable = iterable;
-    }
-
-    @Override
-    public Query filter( Specification<T> filter )
-    {
-        iterable = Iterables.filter( filter, iterable );
-
-        return this;
-    }
-
-    @Override
-    public Query orderBy( Property<?> property, Order order )
-    {
-        return this;
-    }
-
-    @Override
-    public Query skip( int skipNrOfResults )
-    {
-        this.skip = skipNrOfResults;
-
-        return this;
-    }
-
-    @Override
-    public Query limit( int maxNrOfResults )
-    {
-        this.limit = maxNrOfResults;
-        return this;
-    }
-
-    @Override
-    public Query<T> setVariable( String name, Object value )
-    {
-        variables.put( name, value );
-        return this;
-    }
-
-    @Override
-    public Object getVariable( String name )
-    {
-        return variables.get( name );
-    }
-
-    @Override
-    public long count()
-    {
-        return Iterables.count( Iterables.limit( limit, Iterables.skip( skip, iterable ) ) );
-    }
-
-    @Override
-    public T first()
-    {
-        return Iterables.first( Iterables.limit( limit, Iterables.skip( skip, iterable ) ) );
-    }
-
-    @Override
-    public T single()
-        throws QueryException
-    {
-        return Iterables.single( Iterables.limit( limit, Iterables.skip( skip, iterable ) ) );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean execute( Visitor<T, ThrowableType> resultVisitor )
-        throws ThrowableType
-    {
-        for( T t : toIterable() )
-        {
-            if( !resultVisitor.visit( t ) )
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    @Override
-    public Iterable<T> toIterable()
-        throws QueryException
-    {
-        return Iterables.limit( limit, Iterables.skip( skip, iterable ) );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/dataset/iterable/package.html b/core/api/src/main/java/org/qi4j/api/dataset/iterable/package.html
deleted file mode 100644
index 9874cb5..0000000
--- a/core/api/src/main/java/org/qi4j/api/dataset/iterable/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Iterable DataSets.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/dataset/package.html b/core/api/src/main/java/org/qi4j/api/dataset/package.html
deleted file mode 100644
index f324682..0000000
--- a/core/api/src/main/java/org/qi4j/api/dataset/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>DataSet API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/entity/Aggregated.java b/core/api/src/main/java/org/qi4j/api/entity/Aggregated.java
deleted file mode 100644
index 11e4ba5..0000000
--- a/core/api/src/main/java/org/qi4j/api/entity/Aggregated.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.entity;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Marks an association as aggregating the referenced Entities
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.METHOD } )
-@Documented
-public @interface Aggregated
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/entity/EntityBuilder.java b/core/api/src/main/java/org/qi4j/api/entity/EntityBuilder.java
deleted file mode 100644
index 7020253..0000000
--- a/core/api/src/main/java/org/qi4j/api/entity/EntityBuilder.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*  Copyright 2007 Niclas Hedhman.

- *

- * Licensed 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.qi4j.api.entity;

-

-import org.qi4j.api.common.ConstructionException;

-

-/**

- * EntityBuilders are used to instantiate EntityComposites. They can be acquired from

- * {@link org.qi4j.api.unitofwork.UnitOfWork#newEntityBuilder(Class)} and allows the client

- * to provide additional settings before instantiating the Composite.

- *

- * After calling newInstance() the builder becomes invalid, and may not be called again.

- */

-public interface EntityBuilder<T>

-{

-    /**

-     * Get a representation of the state for the new Composite.

-     * It is possible to access and update properties and associations,

-     * even immutable ones since the builder represents the initial state.

-     *

-     * @return a proxy implementing the Composite type

-     */

-    T instance();

-

-    /**

-     * Get a representation of the state of the given type for the new Composite.

-     * This is primarily used if you want to provide state for a private mixin type.

-     *

-     * @param mixinType the mixin which you want to provide state for

-     *

-     * @return a proxy implementing the given mixin type

-     */

-    <K> K instanceFor( Class<K> mixinType );

-

-    /**

-     * Create a new Entity instance.

-     *

-     * @return a new Entity instance

-     *

-     * @throws org.qi4j.api.common.ConstructionException

-     *                            thrown if it was not possible to instantiate the Composite

-     * @throws LifecycleException if the entity could not be created

-     */

-    T newInstance()

-        throws ConstructionException, LifecycleException;

-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/entity/EntityBuilderTemplate.java b/core/api/src/main/java/org/qi4j/api/entity/EntityBuilderTemplate.java
deleted file mode 100644
index 4473844..0000000
--- a/core/api/src/main/java/org/qi4j/api/entity/EntityBuilderTemplate.java
+++ /dev/null
@@ -1,43 +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.qi4j.api.entity;
-
-import org.qi4j.api.structure.Module;
-
-/**
- * EntityBuilderTemplate.
- */
-public abstract class EntityBuilderTemplate<T>
-{
-    Class<T> type;
-
-    protected EntityBuilderTemplate( Class<T> type )
-    {
-        this.type = type;
-    }
-
-    protected abstract void build( T prototype );
-
-    public T newInstance( Module module )
-    {
-        EntityBuilder<T> builder = module.currentUnitOfWork().newEntityBuilder( type );
-        build( builder.instance() );
-        return builder.newInstance();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/entity/EntityComposite.java b/core/api/src/main/java/org/qi4j/api/entity/EntityComposite.java
deleted file mode 100644
index 93089b8..0000000
--- a/core/api/src/main/java/org/qi4j/api/entity/EntityComposite.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.entity;
-
-import org.qi4j.api.association.AssociationMixin;
-import org.qi4j.api.association.ManyAssociationMixin;
-import org.qi4j.api.association.NamedAssociationMixin;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.mixin.Mixins;
-
-/**
- * EntityComposites are Composites that has mutable state persisted in EntityStores and equality defined from its
- * identity.
- */
-@Mixins( { AssociationMixin.class, ManyAssociationMixin.class, NamedAssociationMixin.class } )
-public interface EntityComposite
-    extends Identity, Composite
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/entity/EntityDescriptor.java b/core/api/src/main/java/org/qi4j/api/entity/EntityDescriptor.java
deleted file mode 100644
index 6ce2500..0000000
--- a/core/api/src/main/java/org/qi4j/api/entity/EntityDescriptor.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.entity;
-
-import org.qi4j.api.association.AssociationStateDescriptor;
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.composite.StatefulCompositeDescriptor;
-
-/**
- * Entity Descriptor.
- */
-public interface EntityDescriptor
-    extends CompositeDescriptor, StatefulCompositeDescriptor
-{
-    @Override
-    AssociationStateDescriptor state();
-
-    boolean queryable();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/entity/EntityReference.java b/core/api/src/main/java/org/qi4j/api/entity/EntityReference.java
deleted file mode 100644
index 967647c..0000000
--- a/core/api/src/main/java/org/qi4j/api/entity/EntityReference.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.entity;
-
-import java.io.Serializable;
-import org.qi4j.api.util.NullArgumentException;
-
-/**
- * An EntityReference is identity of a specific Entity instance.
- * <p>When stringified, the identity is used as-is. Example:</p>
- * <pre>123456-abcde</pre>
- */
-public final class EntityReference
-    implements Serializable
-{
-    /**
-     * Parse an URI to an EntityReference.
-     * @param uri the URI to parse
-     * @return the EntityReference represented by the given URI
-     */
-    public static EntityReference parseURI( String uri )
-    {
-        String identity = uri.substring( "urn:qi4j:entity:".length() );
-        return new EntityReference( identity );
-    }
-
-    /**
-     * Parse an Entity identity to an EntityReference.
-     * @param identity the EntityReference identity
-     * @return the EntityReference represented by the given identity
-     */
-    public static EntityReference parseEntityReference( String identity )
-    {
-        return new EntityReference( identity );
-    }
-
-    /**
-     * @param object an EntityComposite
-     * @return the EntityReference for the given EntityComposite
-     */
-    public static EntityReference entityReferenceFor( Object object )
-    {
-        return new EntityReference( (EntityComposite) object );
-    }
-
-    public static EntityReference create( Identity identity )
-    {
-        if( identity == null )
-            return null;
-        return new EntityReference( identity.identity().get() );
-    }
-
-    private static final long serialVersionUID = 1L;
-
-    private String identity;
-
-    /**
-     * @param entityComposite a non-null EntityComposite
-     * @throws NullPointerException if entityComposite is null
-     */
-    public EntityReference( EntityComposite entityComposite )
-    {
-        this( entityComposite.identity().get() );
-    }
-
-    /**
-     * @param identity reference identity
-     * @throws NullArgumentException if identity is null or empty
-     */
-    public EntityReference( String identity )
-    {
-        NullArgumentException.validateNotEmpty( "identity", identity );
-        this.identity = identity;
-    }
-
-    /**
-     * @return This EntityReference identity.
-     */
-    public final String identity()
-    {
-        return identity;
-    }
-
-    /**
-     * @return An URI representation of this EntityReference.
-     */
-    public String toURI()
-    {
-        return "urn:qi4j:entity:" + identity;
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-        EntityReference that = (EntityReference) o;
-        return identity.equals( that.identity );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return identity.hashCode();
-    }
-
-    /**
-     * @return This EntityReference identity.
-     */
-    @Override
-    public String toString()
-    {
-        return identity;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/entity/Identity.java b/core/api/src/main/java/org/qi4j/api/entity/Identity.java
deleted file mode 100644
index b4adbc5..0000000
--- a/core/api/src/main/java/org/qi4j/api/entity/Identity.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.entity;
-
-import org.qi4j.api.injection.scope.State;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-
-/**
- * This interface provides the identity of the object which may be used
- * to store the state in a database. It is not the responsibility of the
- * framework to come up with a good identity string.
- */
-@Mixins( Identity.IdentityMixin.class )
-public interface Identity
-{
-    /**
-     * Returns the client view of the identity.
-     * <p>
-     * It is unique within the owning repository, but potentially not unique globally and between
-     * types.
-     * </p>
-     * @return The Identity of 'this' composite.
-     */
-    @Immutable
-    Property<String> identity();
-
-    /**
-     * Default Identity implementation.
-     */
-    class IdentityMixin
-        implements Identity
-    {
-        @State
-        private Property<String> identity;
-
-        @Override
-        public Property<String> identity()
-        {
-            return identity;
-        }
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/entity/IdentityGenerator.java b/core/api/src/main/java/org/qi4j/api/entity/IdentityGenerator.java
deleted file mode 100644
index 8d076e5..0000000
--- a/core/api/src/main/java/org/qi4j/api/entity/IdentityGenerator.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*  Copyright 2007 Niclas Hedhman.
- *
- * Licensed 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.qi4j.api.entity;
-
-/**
- * Generator for identities of EntityComposite's.
- */
-public interface IdentityGenerator
-{
-    /**
-     * Generate a new id for the given Composite type
-     *
-     * @param compositeType the type of composite
-     *
-     * @return a new identity
-     */
-    String generate( Class<?> compositeType );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/entity/Lifecycle.java b/core/api/src/main/java/org/qi4j/api/entity/Lifecycle.java
deleted file mode 100644
index 3eabd78..0000000
--- a/core/api/src/main/java/org/qi4j/api/entity/Lifecycle.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*

- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.

- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.

- *

- * Licensed 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.qi4j.api.entity;

-

-/**

- * Lifecycle interface for all Composites.

- * <p>

- * This Lifecycle interface is a built-in feature of the Zest runtime, similar to the Initializable interface.

- * Any Mixin that implements this interface AND is part of an EntityComposite will have these two methods called

- * upon creation/removal of the EntityComposite instance to/from the EntityStore. Meaning, the create method is called

- * only when the identifiable EntityComposite is created the first time, and not when it is read from its persisted

- * state and created into memory.

- * </p>

- * <p>

- * Example;

- * </p>

- * <pre><code>

- * public interface System

- * {

- *     Property&lt;User&gt; admin();

- * }

- *

- * public class SystemAdminMixin&lt;LifeCycle&gt;

- *     implements System, Lifecyle, ...

- * {

- *      &#64;Structure private UnitOfWork uow;

- *      &#64;This private Identity meAsIdentity;

- *

- *      public void create()

- *      {

- *          String thisId = meAsIdentity.identity().get();

- *          EntityBuilder builder = uow.newEntityBuilder( thisId + ":1", UserComposite.class );

- *          User admin = builder.newInstance();

- *          admin.set( admin );

- *      }

- *

- *      public void remove()

- *      {

- *          uow.remove( admin.get() );

- *      }

- * }

- *

- * &#64;Mixins( SystemAdminMixin.class )

- * public interface SystemEntity extends System, EntityComposite

- * {}

- *

- * </code></pre>

- */

-public interface Lifecycle

-{

-

-    /**

-     * Creation callback method.

-     * <p>

-     * Called by the Zest runtime before the newInstance of the entity completes, before the constraints are checked,

-     * allowing for additional initialization.

-     * </p>

-     * @throws LifecycleException if the entity could not be created

-     */

-    void create()

-        throws LifecycleException;

-

-    /**

-     * Removal callback method.

-     * <p>

-     * Called by the Zest runtime before the entity is removed from the system, allowing

-     * for clean-up operations.

-     * </p>

-     * @throws LifecycleException if the entity could not be removed

-     */

-    void remove()

-        throws LifecycleException;

-}

diff --git a/core/api/src/main/java/org/qi4j/api/entity/LifecycleException.java b/core/api/src/main/java/org/qi4j/api/entity/LifecycleException.java
deleted file mode 100644
index b358fa1..0000000
--- a/core/api/src/main/java/org/qi4j/api/entity/LifecycleException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.entity;
-
-/**
- * Thrown by methods of Lifecycle if invocation fails
- */
-public class LifecycleException
-    extends RuntimeException
-{
-    public LifecycleException( String s )
-    {
-        super( s );
-    }
-
-    public LifecycleException( String s, Throwable throwable )
-    {
-        super( s, throwable );
-    }
-
-    public LifecycleException( Throwable throwable )
-    {
-        super( throwable );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/entity/Queryable.java b/core/api/src/main/java/org/qi4j/api/entity/Queryable.java
deleted file mode 100644
index 768e17d..0000000
--- a/core/api/src/main/java/org/qi4j/api/entity/Queryable.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2008, Alin Dreghiciu. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.entity;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This annotation is used to mark entity types or properties/associations that are indexable.
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.TYPE, ElementType.METHOD } )
-@Documented
-public @interface Queryable
-{
-    boolean value() default true;
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/entity/package.html b/core/api/src/main/java/org/qi4j/api/entity/package.html
deleted file mode 100644
index 0386d8c..0000000
--- a/core/api/src/main/java/org/qi4j/api/entity/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Entity API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/event/package.html b/core/api/src/main/java/org/qi4j/api/event/package.html
deleted file mode 100644
index a5ed0a7..0000000
--- a/core/api/src/main/java/org/qi4j/api/event/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Event API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/injection/InjectionScope.java b/core/api/src/main/java/org/qi4j/api/injection/InjectionScope.java
deleted file mode 100644
index 7ada2e6..0000000
--- a/core/api/src/main/java/org/qi4j/api/injection/InjectionScope.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.injection;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This is used to annotate annotation types which are used for injection.
- * Each scope signifies a particular scope from which the injection value should be taken.
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.ANNOTATION_TYPE } )
-@Documented
-public @interface InjectionScope
-{
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/injection/package.html b/core/api/src/main/java/org/qi4j/api/injection/package.html
deleted file mode 100644
index c41b495..0000000
--- a/core/api/src/main/java/org/qi4j/api/injection/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Dependency Injection API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/injection/scope/Invocation.java b/core/api/src/main/java/org/qi4j/api/injection/scope/Invocation.java
deleted file mode 100644
index 230e5c9..0000000
--- a/core/api/src/main/java/org/qi4j/api/injection/scope/Invocation.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.injection.scope;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.qi4j.api.injection.InjectionScope;
-
-/**
- * Annotation to denote the injection of a
- * invocation specific resource.
- * These include:
- * <pre><code>
- *  - The Method being invoked.
- *
- *  - An AnnotationElement with annotations
- *    from both mixin type, mixin
- *    implementation.
- *
- *  - An Annotation of a specific type
- * </code></pre>
- * Examples:
- * <pre><code>
- * &#64;Invocation Method theInvokedMethod
- * &#64;Invocation AnnotationElement annotations
- * &#64;Invocation Matches matchesAnnotation
- * </code></pre>
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.FIELD, ElementType.PARAMETER } )
-@Documented
-@InjectionScope
-public @interface Invocation
-{
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/injection/scope/Service.java b/core/api/src/main/java/org/qi4j/api/injection/scope/Service.java
deleted file mode 100644
index 6116cc1..0000000
--- a/core/api/src/main/java/org/qi4j/api/injection/scope/Service.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.injection.scope;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.qi4j.api.injection.InjectionScope;
-
-/**
- * Annotation to denote the injection of a service dependency into a Fragment.
- * <p>
- * Examples:
- * </p>
- * <pre><code>
- * &#64;Service MyService service
- * &#64;Service Iterable&lt;MyService&gt; services
- * &#64;Service ServiceReference&lt;MyService&gt; serviceRef
- * &#64;Service Iterable&lt;ServiceReference&lt;MyService&gt;&gt; serviceRefs
- * </code></pre>
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.FIELD, ElementType.PARAMETER } )
-@Documented
-@InjectionScope
-public @interface Service
-{
-}
-
diff --git a/core/api/src/main/java/org/qi4j/api/injection/scope/State.java b/core/api/src/main/java/org/qi4j/api/injection/scope/State.java
deleted file mode 100644
index ec3c52a..0000000
--- a/core/api/src/main/java/org/qi4j/api/injection/scope/State.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.injection.scope;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.qi4j.api.injection.InjectionScope;
-
-/**
- * Annotation to denote the injection of a property, association or
- * StateHolder.
- * <pre><code>
- * &#64;State Property&lt;StringState propertyName;
- * &#64;State Association&lt;MyEntityState associationName;
- * &#64;State ManyAssociation&lt;MyEntityState manyAssociationName;
- * &#64;State NamedAssociation&lt;MyEntityState namedAssociationName;
- * &#64;State StateHolder state;
- * &#64;State AssociationStateHolder associationState;
- * </code></pre>
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.FIELD, ElementType.PARAMETER } )
-@Documented
-@InjectionScope
-public @interface State
-{
-    /**
-     * Name of the property or association.
-     * If not set then name will be name of field.
-     *
-     * @return the name
-     */
-    public abstract String value() default "";
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/injection/scope/Structure.java b/core/api/src/main/java/org/qi4j/api/injection/scope/Structure.java
deleted file mode 100644
index 252af5e..0000000
--- a/core/api/src/main/java/org/qi4j/api/injection/scope/Structure.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.injection.scope;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.qi4j.api.injection.InjectionScope;
-
-/**
- * Annotation to denote the injection of a
- * resource specific for the module which the
- * injected object/fragment is instantiated in.
- * <p>
- * Valid types are:
- * </p>
- * <pre><code>
- * - TransientBuilderFactory
- * - ObjectBuilderFactory
- * - UnitOfWorkFactory
- * - ServiceFinder
- * - Module
- * - Layer
- * - Application
- * - Qi4j
- * - Qi4jSPI
- * </code></pre>
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.FIELD, ElementType.PARAMETER } )
-@Documented
-@InjectionScope
-public @interface Structure
-{
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/injection/scope/This.java b/core/api/src/main/java/org/qi4j/api/injection/scope/This.java
deleted file mode 100644
index 4d806d0..0000000
--- a/core/api/src/main/java/org/qi4j/api/injection/scope/This.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.injection.scope;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.qi4j.api.injection.InjectionScope;
-
-/**
- * Annotation to denote the injection of a reference to the same Composite
- * as the fragment is a part of.
- * <p>
- * If the Composite type does not implement the type of the field or parameter
- * then it will be referencing a private mixin.
- * </p>
- * <p>
- * Calls to the reference will have the same semantics as calls to the Composite itself.
- * Specifically the same set of Modifiers will be used.
- * </p>
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.FIELD, ElementType.PARAMETER } )
-@Documented
-@InjectionScope
-public @interface This
-{
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/injection/scope/Uses.java b/core/api/src/main/java/org/qi4j/api/injection/scope/Uses.java
deleted file mode 100644
index d5b4080..0000000
--- a/core/api/src/main/java/org/qi4j/api/injection/scope/Uses.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.injection.scope;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.qi4j.api.injection.InjectionScope;
-
-/**
- * Annotation to denote the injection of a dependency to be used by a Mixin. The injected
- * object is provided either by the TransientBuilder.uses() declarations, or if an instance of the appropriate types is not
- * found, then a new Transient or Object is instantiated.
- * Call {@link org.qi4j.api.composite.TransientBuilder#use} to provide the instance
- * to be injected.
- *
- * Example:
- * <pre>@Uses SomeType someInstance</pre>
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.PARAMETER, ElementType.FIELD } )
-@Documented
-@InjectionScope
-public @interface Uses
-{
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/injection/scope/package.html b/core/api/src/main/java/org/qi4j/api/injection/scope/package.html
deleted file mode 100644
index b0ec496..0000000
--- a/core/api/src/main/java/org/qi4j/api/injection/scope/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Dependency Injection Scopes.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/metrics/Metric.java b/core/api/src/main/java/org/qi4j/api/metrics/Metric.java
deleted file mode 100644
index 775ab5d..0000000
--- a/core/api/src/main/java/org/qi4j/api/metrics/Metric.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.metrics;
-
-/**
- * Marker interface for all Metric types.
- */
-public interface Metric
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/metrics/MetricsCounter.java b/core/api/src/main/java/org/qi4j/api/metrics/MetricsCounter.java
deleted file mode 100644
index 67404b3..0000000
--- a/core/api/src/main/java/org/qi4j/api/metrics/MetricsCounter.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.metrics;
-
-/**
- * Metrics Counter.
- */
-public interface MetricsCounter extends Metric
-{
-    void increment();
-
-    void increment( int steps );
-
-    void decrement();
-
-    void decrement( int steps );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/metrics/MetricsCounterFactory.java b/core/api/src/main/java/org/qi4j/api/metrics/MetricsCounterFactory.java
deleted file mode 100644
index caa2915..0000000
--- a/core/api/src/main/java/org/qi4j/api/metrics/MetricsCounterFactory.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.metrics;
-
-/**
- * Create MetricsCounter instances.
- */
-public interface MetricsCounterFactory extends MetricsFactory
-{
-    /**
-     * Create a MetricsCounter instance.
-     * If the same arguments are given twice, the same instance must be returned.
-     *
-     * @param origin The class that instantiate the metric
-     * @param name   A human readable, short name of the metric.
-     *
-     * @return A Metric instance to be used, OR org.qi4j.spi.metrics.DefaultMetric.NULL if not supported.
-     */
-    MetricsCounter createCounter( Class<?> origin, String name );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/metrics/MetricsFactory.java b/core/api/src/main/java/org/qi4j/api/metrics/MetricsFactory.java
deleted file mode 100644
index 0813dde..0000000
--- a/core/api/src/main/java/org/qi4j/api/metrics/MetricsFactory.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.metrics;
-
-/**
- * Metrics Factory.
- */
-public interface MetricsFactory
-{
-    Iterable<Metric> registered();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/metrics/MetricsGauge.java b/core/api/src/main/java/org/qi4j/api/metrics/MetricsGauge.java
deleted file mode 100644
index 1dd293b..0000000
--- a/core/api/src/main/java/org/qi4j/api/metrics/MetricsGauge.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.metrics;
-
-/**
- * MetricsGauge is the most basic Metric type, and is completely flexible and therefor handled slightly differently in
- * the MetricsFactory than all other Gauges. It needs to pass on custom code, so the implementation is typically
- * an anonymous class, inlined at the implementation.
- *
- * @param <T> Any type holding the MetricsGauge's current value.
- */
-public interface MetricsGauge<T> extends Metric
-{
-    /**
-     * Returns the metric's current value.
-     *
-     * @return the metric's current value
-     */
-    T value();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/metrics/MetricsGaugeFactory.java b/core/api/src/main/java/org/qi4j/api/metrics/MetricsGaugeFactory.java
deleted file mode 100644
index a469ac2..0000000
--- a/core/api/src/main/java/org/qi4j/api/metrics/MetricsGaugeFactory.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.metrics;
-
-/**
- * Register MetricsGauge with the underlying Metrics system.
- */
-public interface MetricsGaugeFactory extends MetricsFactory
-{
-    /**
-     * Register a MetricsGauge with the underlying Metrics system.
-     *
-     * @param origin The class where the MetricsGauge is created.
-     * @param name   A human readable, short name of the metric.
-     * @param gauge  The implementation of the MetricsGauge.
-     * @param <T>    Any type holding the MetricsGauge's current value.
-     *
-     * @return The same MetricsGauge or the DefaultMetric.NULL MetricsGauge instance.
-     */
-    <T> MetricsGauge<T> registerGauge( Class<?> origin, String name, MetricsGauge<T> gauge );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/metrics/MetricsHealthCheck.java b/core/api/src/main/java/org/qi4j/api/metrics/MetricsHealthCheck.java
deleted file mode 100644
index 18bb151..0000000
--- a/core/api/src/main/java/org/qi4j/api/metrics/MetricsHealthCheck.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.metrics;
-
-/**
- * Metrics Health Check.
- */
-public interface MetricsHealthCheck extends Metric
-{
-    Result check()
-        throws Exception;
-
-    public final class Result
-    {
-        private final boolean healthy;
-        private final String message;
-        private final Throwable exception;
-
-        public Result( boolean isHealthy, String message, Throwable exception )
-        {
-            healthy = isHealthy;
-            this.message = message;
-            this.exception = exception;
-        }
-
-        public boolean isHealthy()
-        {
-            return healthy;
-        }
-
-        public String getMessage()
-        {
-            return message;
-        }
-
-        public Throwable getException()
-        {
-            return exception;
-        }
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/metrics/MetricsHealthCheckFactory.java b/core/api/src/main/java/org/qi4j/api/metrics/MetricsHealthCheckFactory.java
deleted file mode 100644
index 12decc5..0000000
--- a/core/api/src/main/java/org/qi4j/api/metrics/MetricsHealthCheckFactory.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.metrics;
-
-/**
- * Create MetricsHealthCheck instances.
- */
-public interface MetricsHealthCheckFactory extends MetricsFactory
-{
-    /**
-     * Create a MetricsHealthCheck instance.
-     * If the same arguments are given twice, the same instance must be returned.
-     *
-     * @param origin The class that instantiate the metric
-     * @param name   A human readable, short name of the metric.
-     * @param check  The health check to be performed regularly.
-     *
-     * @return A MetricsHealthCheck instance to be used, OR org.qi4j.spi.metrics.DefaultMetric.NULL if not supported.
-     *
-     */
-    MetricsHealthCheck registerHealthCheck( Class<?> origin, String name, MetricsHealthCheck check );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/metrics/MetricsHistogram.java b/core/api/src/main/java/org/qi4j/api/metrics/MetricsHistogram.java
deleted file mode 100644
index fe38869..0000000
--- a/core/api/src/main/java/org/qi4j/api/metrics/MetricsHistogram.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.metrics;
-
-/**
- * A metric which calculates the distribution of a value.
- *
- * @see <a href="http://www.johndcook.com/standard_deviation.html">Accurately computing running
- *      variance</a>
- */
-public interface MetricsHistogram extends Metric
-{
-    void update( long newValue );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/metrics/MetricsHistogramFactory.java b/core/api/src/main/java/org/qi4j/api/metrics/MetricsHistogramFactory.java
deleted file mode 100644
index ab62508..0000000
--- a/core/api/src/main/java/org/qi4j/api/metrics/MetricsHistogramFactory.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.metrics;
-
-/**
- * Create MetricsHistogram instances.
- */
-public interface MetricsHistogramFactory extends MetricsFactory
-{
-    /**
-     * Create a MetricsHistogram instance.
-     * If the same arguments are given twice, the same instance must be returned.
-     *
-     * @param origin The class that instantiate the metric
-     * @param name   A human readable, short name of the metric.
-     *
-     * @return A Metric instance to be used, OR org.qi4j.spi.metrics.DefaultMetric.NULL if not supported.
-     *
-     */
-    MetricsHistogram createHistogram( Class<?> origin, String name );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/metrics/MetricsMeter.java b/core/api/src/main/java/org/qi4j/api/metrics/MetricsMeter.java
deleted file mode 100644
index acbb73d..0000000
--- a/core/api/src/main/java/org/qi4j/api/metrics/MetricsMeter.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.metrics;
-
-/**
- * A meter metric which measures mean throughput and one-, five-, and fifteen-minute
- * exponentially-weighted moving average throughputs.
- *
- * @see <a href="http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average">EMA</a>
- */
-public interface MetricsMeter extends Metric
-{
-    void mark();
-
-    /**
-     * Mark the occurrence of a given number of events.
-     *
-     * @param numberOfEvents the number of events
-     */
-    void mark( int numberOfEvents );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/metrics/MetricsMeterFactory.java b/core/api/src/main/java/org/qi4j/api/metrics/MetricsMeterFactory.java
deleted file mode 100644
index 53928bd..0000000
--- a/core/api/src/main/java/org/qi4j/api/metrics/MetricsMeterFactory.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.metrics;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * Create MetricsMeter instances.
- */
-public interface MetricsMeterFactory extends MetricsFactory
-{
-    /**
-     * Create a MetricsMeter instance.
-     * If the same arguments are given twice, the same instance must be returned.
-     *
-     * @param origin    The class that instantiate the metric
-     * @param name      A human readable, short name of the metric.
-     * @param eventType the plural name of the event the meter is measuring (e.g., {@code "requests"})
-     * @param rate      the scale unit for this timer's rate metrics
-     *
-     * @return A Metric instance to be used, OR org.qi4j.spi.metrics.DefaultMetric.NULL if not supported.
-     */
-    MetricsMeter createMeter( Class<?> origin, String name, String eventType, TimeUnit rate );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/metrics/MetricsNotSupportedException.java b/core/api/src/main/java/org/qi4j/api/metrics/MetricsNotSupportedException.java
deleted file mode 100644
index aec7859..0000000
--- a/core/api/src/main/java/org/qi4j/api/metrics/MetricsNotSupportedException.java
+++ /dev/null
@@ -1,32 +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.qi4j.api.metrics;
-
-/**
- * Thrown when the underlying MetricsProvider do not support a Metric type.
- */
-public class MetricsNotSupportedException extends RuntimeException
-{
-    public MetricsNotSupportedException( Class<? extends MetricsFactory> factoryType,
-                                         Class<? extends MetricsProvider> providerType
-    )
-    {
-        super( "Metrics [" + factoryType.getName() + "] is not supported by MetricsProvider [" + providerType.getName() + "]." );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/metrics/MetricsProvider.java b/core/api/src/main/java/org/qi4j/api/metrics/MetricsProvider.java
deleted file mode 100644
index c11996b..0000000
--- a/core/api/src/main/java/org/qi4j/api/metrics/MetricsProvider.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.metrics;
-
-/**
- * Metrics Provider SPI.
- * <p>
- * The Zest Runtime will automatically ook for a service that implements the MetricsProvider interdace
- * and use it for internal Runtime metrics, such as the UnitOfWork measuring the time from creation to close.
- * </p>
- * <p>
- * The Metrics Library is available to add metric functionality to applications in the same way, and
- * will use the same MetricsProvider.
- * </p>
- * <p>
- * Note that the usual visibitlity rules applies, so you might have more than one MetricsProvider server,
- * perhaps per layer.
- * </p>
- */
-public interface MetricsProvider
-{
-    /**
-     * Creates a new factory instance.
-     *
-     * The instanctiation is done by providing a Metric type, which is one of
-     * <ul>
-     * <li>{@link MetricsCounter}</li>
-     * <li>{@link MetricsGauge}</li>
-     * <li>{@link MetricsHealthCheck}</li>
-     * <li>{@link MetricsHistogram}</li>
-     * <li>{@link MetricsMeter}</li>
-     * <li>{@link MetricsTimer}</li>
-     * </ul>
-     *
-     * @param factoryType The class of the metric type needed.
-     * @param <T>         The metric type requested.
-     *
-     * @return A factory instance
-     *
-     * @throws MetricsNotSupportedException when the MetricsProvider is not supporting the factory type requested.
-     */
-    <T extends MetricsFactory> T createFactory( Class<T> factoryType )
-        throws MetricsNotSupportedException;
-}
diff --git a/core/api/src/main/java/org/qi4j/api/metrics/MetricsTimer.java b/core/api/src/main/java/org/qi4j/api/metrics/MetricsTimer.java
deleted file mode 100644
index 6de4714..0000000
--- a/core/api/src/main/java/org/qi4j/api/metrics/MetricsTimer.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.metrics;
-
-/**
- * Timer Metrics.
- */
-public interface MetricsTimer extends Metric
-{
-    /**
-     * Start the Timer Metrics.
-     */
-    Context start();
-
-    /**
-     * Timer Metrics Context.
-     */
-    public interface Context
-    {
-        /**
-         * Stop the Timer Metrics.
-         */
-        void stop();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/metrics/MetricsTimerFactory.java b/core/api/src/main/java/org/qi4j/api/metrics/MetricsTimerFactory.java
deleted file mode 100644
index 18d3e38..0000000
--- a/core/api/src/main/java/org/qi4j/api/metrics/MetricsTimerFactory.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.metrics;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * Create MetricsTimer instances.
- */
-public interface MetricsTimerFactory extends MetricsFactory
-{
-    /**
-     * Create a MetricsTimer instance.
-     * If the same arguments are given twice, the same instance must be returned.
-     *
-     * @param origin   The class that instantiate the metric
-     * @param name     A human readable, short name of the metric.
-     * @param duration the scale unit for this timer's duration metrics
-     * @param rate     the scale unit for this timer's rate metrics
-     *
-     * @return A Metric instance to be used, OR org.qi4j.spi.metrics.DefaultMetric.NULL if not supported.
-     *
-     */
-    MetricsTimer createTimer( Class<?> origin, String name, TimeUnit duration, TimeUnit rate );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/metrics/package.html b/core/api/src/main/java/org/qi4j/api/metrics/package.html
deleted file mode 100644
index d0280bd..0000000
--- a/core/api/src/main/java/org/qi4j/api/metrics/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Metrics API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/mixin/Initializable.java b/core/api/src/main/java/org/qi4j/api/mixin/Initializable.java
deleted file mode 100644
index 53314e9..0000000
--- a/core/api/src/main/java/org/qi4j/api/mixin/Initializable.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.mixin;
-
-/**
- * Fragments which want to be initialized can implement
- * this callback interface. It will be invoked after
- * the fragment has bee instantiated and all injections have been done.
- */
-public interface Initializable
-{
-    /**
-     * Initialize the fragment
-     *
-     * @throws org.qi4j.api.mixin.InitializationException
-     *          if something went wrong
-     */
-    void initialize()
-        throws InitializationException;
-}
diff --git a/core/api/src/main/java/org/qi4j/api/mixin/InitializationException.java b/core/api/src/main/java/org/qi4j/api/mixin/InitializationException.java
deleted file mode 100644
index 4a42da6..0000000
--- a/core/api/src/main/java/org/qi4j/api/mixin/InitializationException.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.mixin;
-
-/**
- * Thrown when a Fragment or object could not be instantiated.
- */
-public class InitializationException
-    extends RuntimeException
-{
-    private static final long serialVersionUID = 1L;
-
-    public InitializationException()
-    {
-    }
-
-    public InitializationException( String message )
-    {
-        super( message );
-    }
-
-    public InitializationException( String message, Throwable cause )
-    {
-        super( message, cause );
-    }
-
-    public InitializationException( Throwable cause )
-    {
-        super( cause );
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/mixin/InvalidMixinException.java b/core/api/src/main/java/org/qi4j/api/mixin/InvalidMixinException.java
deleted file mode 100644
index 967c6b6..0000000
--- a/core/api/src/main/java/org/qi4j/api/mixin/InvalidMixinException.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.api.mixin;
-
-import java.lang.reflect.Method;
-
-/**
- * This exception is thrown if a Mixin is invalid (missing method implementation).
- */
-public class InvalidMixinException
-    extends RuntimeException
-{
-    public InvalidMixinException( Class mixinClass, Method method )
-    {
-        super( mixinClass.getName() + "does not have a method implementation for " + method );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/mixin/MixinDescriptor.java b/core/api/src/main/java/org/qi4j/api/mixin/MixinDescriptor.java
deleted file mode 100644
index 288aac3..0000000
--- a/core/api/src/main/java/org/qi4j/api/mixin/MixinDescriptor.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.mixin;
-
-/**
- * Mixin Descriptor.
- */
-public interface MixinDescriptor
-{
-    Class<?> mixinClass();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/mixin/MixinMappingException.java b/core/api/src/main/java/org/qi4j/api/mixin/MixinMappingException.java
deleted file mode 100644
index 4bd3a8a..0000000
--- a/core/api/src/main/java/org/qi4j/api/mixin/MixinMappingException.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.api.mixin;
-
-/**
- * This Exception is thrown when it is not possible to map the MixinType to a valid
- * CompositeType.
- */
-public class MixinMappingException
-    extends RuntimeException
-{
-    private static final long serialVersionUID = 6843167709252705294L;
-
-    public MixinMappingException( String message )
-    {
-        super( message );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/mixin/Mixins.java b/core/api/src/main/java/org/qi4j/api/mixin/Mixins.java
deleted file mode 100644
index e308381..0000000
--- a/core/api/src/main/java/org/qi4j/api/mixin/Mixins.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.mixin;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This annotation is used in composites to declare mixin implementation classes.
- * <p>
- * Mixins tells the runtime which implementation class of a Mixin should be
- * used. The &#64;Mixins annotation can occur at any level in the composite hierarchy
- * and the runtime will match each found Mixin implementation against a Mixins annotation.
- * All mixin interfaces must have a Mixin implementation in the composite hierarchy or
- * a runtime exception will occur.
- * </p>
- * <p>
- * Example;
- * </p>
- * <pre><code>
- *
- * &#64;Mixins( MyBeerOrder.class )
- * public interface BeerOrderComposite extends BeerOrder, Composite
- * {
- * }
- *
- * public class MyBeerOrder
- * implements BeerOrder
- * {
- * :
- * }
- * </code></pre>
- * <p>
- * Many implementations can be listed,
- * </p>
- * <pre><code>
- * &#64;Mixins( { MyBeerOrder.class, DescriptionImpl.class } )
- * public interface BeerOrderComposite extends BeerOrder, Description, Composite
- * {
- * }
- * </code></pre>
- * <p>
- * If the Mixins is a class that implements InvocationHandler, it will be
- * used for all mixins. To avoid that an invocation handler based implementation
- * not service all mixin, use the AppliesTo annotation.
- * </p>
- *
- * <p>
- * It is valid to have multiple Mixins for a mixin. The first one found
- * will be used. The search order is in the order they are written in the Mixins
- * annotation left-to-right, and depth-first recursive search of the super-interfaces again
- * left-to-right.
- * </p>
- *
- * @see org.qi4j.api.common.AppliesTo
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( ElementType.TYPE )
-@Documented
-public @interface Mixins
-{
-    Class<?>[] value();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/mixin/NoopMixin.java b/core/api/src/main/java/org/qi4j/api/mixin/NoopMixin.java
deleted file mode 100644
index 948018e..0000000
--- a/core/api/src/main/java/org/qi4j/api/mixin/NoopMixin.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.mixin;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-
-/**
- * Generic mixin that is a no-op. Can be useful if the functionality
- * of a method is mainly provided by concerns and side-effects.
- */
-public final class NoopMixin
-    implements InvocationHandler
-{
-    private static final Boolean BOOLEAN_DEFAULT = Boolean.FALSE;
-    private static final Short SHORT_DEFAULT = 0;
-    private static final Character CHARACTER_DEFAULT = 0;
-    private static final Integer INTEGER_DEFAULT = 0;
-    private static final Long LONG_DEFAULT = 0L;
-    private static final Float FLOAT_DEFAULT = 0f;
-    private static final Double DOUBLE_DEFAULT = 0.0;
-
-    @Override
-    public Object invoke( Object object, Method method, Object[] args )
-        throws Throwable
-    {
-        Class<?> retType = method.getReturnType();
-        if( !retType.isPrimitive() )
-        {
-            return null;
-        }
-        if( Void.TYPE == retType )
-        {
-            return null;
-        }
-        if( Boolean.TYPE == retType )
-        {
-            return BOOLEAN_DEFAULT;
-        }
-        if( Short.TYPE == retType )
-        {
-            return SHORT_DEFAULT;
-        }
-        if( Character.TYPE == retType )
-        {
-            return CHARACTER_DEFAULT;
-        }
-        if( Integer.TYPE == retType )
-        {
-            return INTEGER_DEFAULT;
-        }
-        if( Long.TYPE == retType )
-        {
-            return LONG_DEFAULT;
-        }
-        if( Float.TYPE == retType )
-        {
-            return FLOAT_DEFAULT;
-        }
-        if( Double.TYPE == retType )
-        {
-            return DOUBLE_DEFAULT;
-        }
-        return null;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/mixin/package.html b/core/api/src/main/java/org/qi4j/api/mixin/package.html
deleted file mode 100644
index a0ebe07..0000000
--- a/core/api/src/main/java/org/qi4j/api/mixin/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Mixin API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/object/NoSuchObjectException.java b/core/api/src/main/java/org/qi4j/api/object/NoSuchObjectException.java
deleted file mode 100644
index 71a4cb7..0000000
--- a/core/api/src/main/java/org/qi4j/api/object/NoSuchObjectException.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.object;
-
-import org.qi4j.api.common.InvalidApplicationException;
-
-/**
- * This exception is thrown if no visible Object of the requested type can be found.
- */
-public class NoSuchObjectException
-    extends InvalidApplicationException
-{
-    private static final long serialVersionUID = -1121690536365682511L;
-
-    private final String objectType;
-    private final String moduleName;
-
-    public NoSuchObjectException( String type, String moduleName )
-    {
-        super( "Could not find any visible Object of type [" + type + "] in module [" +
-               moduleName + "]." );
-        this.objectType = type;
-        this.moduleName = moduleName;
-    }
-
-    public String objectType()
-    {
-        return objectType;
-    }
-
-    public String moduleName()
-    {
-        return moduleName;
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/object/ObjectDescriptor.java b/core/api/src/main/java/org/qi4j/api/object/ObjectDescriptor.java
deleted file mode 100644
index 115c52e..0000000
--- a/core/api/src/main/java/org/qi4j/api/object/ObjectDescriptor.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.object;
-
-import org.qi4j.api.composite.ModelDescriptor;
-
-/**
- * Object Descriptor.
- */
-public interface ObjectDescriptor
-    extends ModelDescriptor
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/object/ObjectFactory.java b/core/api/src/main/java/org/qi4j/api/object/ObjectFactory.java
deleted file mode 100644
index 9b8ec47..0000000
--- a/core/api/src/main/java/org/qi4j/api/object/ObjectFactory.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.object;
-
-import org.qi4j.api.common.ConstructionException;
-
-/**
- * This factory creates and injects POJO's.
- */
-public interface ObjectFactory
-{
-    /**
-     * Create new objects of the given type.
-     *
-     * @param type an object class which will be instantiated.
-     *
-     * @return new objects.
-     *
-     * @throws ConstructionException Thrown if instantiation fails.
-     * @throws NoSuchObjectException Thrown if {@code type} class is not an object.
-     */
-    <T> T newObject( Class<T> type, Object... uses )
-        throws NoSuchObjectException, ConstructionException;
-
-    /**
-     * Inject an existing instance. Only fields and methods will be called.
-     *
-     * @param instance
-     *
-     * @throws ConstructionException
-     */
-    void injectTo( Object instance, Object... uses )
-        throws ConstructionException;
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/object/package.html b/core/api/src/main/java/org/qi4j/api/object/package.html
deleted file mode 100644
index 1e06504..0000000
--- a/core/api/src/main/java/org/qi4j/api/object/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Object API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/package.html b/core/api/src/main/java/org/qi4j/api/package.html
deleted file mode 100644
index ff7d9af..0000000
--- a/core/api/src/main/java/org/qi4j/api/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Apache Zest™ API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/property/DefaultValues.java b/core/api/src/main/java/org/qi4j/api/property/DefaultValues.java
deleted file mode 100644
index 3d0dbff..0000000
--- a/core/api/src/main/java/org/qi4j/api/property/DefaultValues.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2008, Michael Hunger. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.property;
-
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Default values for various property types
- */
-public final class DefaultValues
-{
-    private static final Map<Type, Object> DEFAULT_VALUES = new HashMap<Type, Object>();
-
-    static
-    {
-        DEFAULT_VALUES.put( Byte.class, 0 );
-        DEFAULT_VALUES.put( Short.class, 0 );
-        DEFAULT_VALUES.put( Character.class, 0 );
-        DEFAULT_VALUES.put( Integer.class, 0 );
-        DEFAULT_VALUES.put( Long.class, 0L );
-        DEFAULT_VALUES.put( Double.class, 0D );
-        DEFAULT_VALUES.put( Float.class, 0F );
-        DEFAULT_VALUES.put( Boolean.class, false );
-        DEFAULT_VALUES.put( String.class, "" );
-    }
-
-    public static Object getDefaultValueOf( Type type )
-    {
-        Object value = DEFAULT_VALUES.get( type );
-        if( value != null )
-        {
-            return value;
-        }
-        if( type instanceof ParameterizedType )
-        {
-            // List<Foo> -> List
-            type = ( (ParameterizedType) type ).getRawType();
-        }
-
-        if( type instanceof Class )
-        {
-            Class typeAsClass = (Class) type;
-            if( Set.class.isAssignableFrom( typeAsClass ) )
-            {
-                return new HashSet();
-            }
-            else if( Map.class.isAssignableFrom( typeAsClass ) )
-            {
-                return new LinkedHashMap();
-            }
-            else if( Collection.class.isAssignableFrom( typeAsClass ) )
-            {
-                return new ArrayList();
-            }
-            else if( typeAsClass.isEnum() )
-            {
-                return ( (Class) type ).getEnumConstants()[ 0 ];
-            }
-        }
-        throw new IllegalArgumentException( "Cannot use @UseDefaults with type " + type.toString() );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/property/GenericPropertyInfo.java b/core/api/src/main/java/org/qi4j/api/property/GenericPropertyInfo.java
deleted file mode 100644
index b8b9467..0000000
--- a/core/api/src/main/java/org/qi4j/api/property/GenericPropertyInfo.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2007,2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.api.property;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-
-import static org.qi4j.api.util.Classes.typeOf;
-
-/**
- * Generic Property info utility class.
- */
-public final class GenericPropertyInfo
-{
-    public static Type propertyTypeOf( AccessibleObject accessor )
-    {
-        return toPropertyType( typeOf( accessor ) );
-    }
-
-    public static Type toPropertyType( Type methodReturnType )
-    {
-        if( methodReturnType instanceof ParameterizedType )
-        {
-            ParameterizedType parameterizedType = (ParameterizedType) methodReturnType;
-            if( Property.class.isAssignableFrom( (Class<?>) parameterizedType.getRawType() ) )
-            {
-                return parameterizedType.getActualTypeArguments()[ 0 ];
-            }
-        }
-
-        if( methodReturnType instanceof Class<?> )
-        {
-            Type[] interfaces = ( (Class<?>) methodReturnType ).getGenericInterfaces();
-            for( Type anInterface : interfaces )
-            {
-                Type propertyType = toPropertyType( anInterface );
-                if( propertyType != null )
-                {
-                    return propertyType;
-                }
-            }
-        }
-        return null;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/property/Immutable.java b/core/api/src/main/java/org/qi4j/api/property/Immutable.java
deleted file mode 100644
index 39e3cf9..0000000
--- a/core/api/src/main/java/org/qi4j/api/property/Immutable.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.property;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This annotation adds Immutability to Types, Properties and Associations
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.TYPE, ElementType.METHOD } )
-@Documented
-public @interface Immutable
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/property/InvalidPropertyTypeException.java b/core/api/src/main/java/org/qi4j/api/property/InvalidPropertyTypeException.java
deleted file mode 100644
index 6afee4d..0000000
--- a/core/api/src/main/java/org/qi4j/api/property/InvalidPropertyTypeException.java
+++ /dev/null
@@ -1,40 +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.qi4j.api.property;
-
-import java.lang.reflect.AccessibleObject;
-import org.qi4j.api.common.ConstructionException;
-
-/**
- * Thrown when attempting to subclass Property.
- */
-public class InvalidPropertyTypeException extends ConstructionException
-{
-    public InvalidPropertyTypeException( AccessibleObject accessor )
-    {
-        super( createMessage(accessor) );
-    }
-
-    private static String createMessage( AccessibleObject accessor )
-    {
-        StringBuilder builder = new StringBuilder();
-        builder.append( "Not allowed to subclass " + Property.class.getName() + ". Property accessor " + accessor + " is returning a Property subclass." );
-        return builder.toString();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/property/Numbers.java b/core/api/src/main/java/org/qi4j/api/property/Numbers.java
deleted file mode 100644
index 00c0e5f..0000000
--- a/core/api/src/main/java/org/qi4j/api/property/Numbers.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.property;
-
-import java.math.BigDecimal;
-
-/**
- * Convenience class for mathematical operations on numerical properties.
- * <pre>import static org.qi4j.api.property.Numbers.*;
- * ...
- * add( object.numberProperty(), 5 );</pre>
- */
-public final class Numbers
-{
-    // Integer operations
-
-    public static Property<Integer> add( Property<Integer> property, int amount )
-    {
-        property.set( property.get() + amount );
-        return property;
-    }
-
-    public static Property<Integer> mult( Property<Integer> property, int amount )
-    {
-        property.set( property.get() * amount );
-        return property;
-    }
-
-    public static Property<Integer> sub( Property<Integer> property, int amount )
-    {
-        property.set( property.get() - amount );
-        return property;
-    }
-
-    public static Property<Integer> div( Property<Integer> property, int amount )
-    {
-        property.set( property.get() / amount );
-        return property;
-    }
-
-    // Long operations
-
-    public static Property<Long> add( Property<Long> property, long amount )
-    {
-        property.set( property.get() + amount );
-        return property;
-    }
-
-    public static Property<Long> mult( Property<Long> property, long amount )
-    {
-        property.set( property.get() * amount );
-        return property;
-    }
-
-    public static Property<Long> sub( Property<Long> property, long amount )
-    {
-        property.set( property.get() - amount );
-        return property;
-    }
-
-    public static Property<Long> div( Property<Long> property, long amount )
-    {
-        property.set( property.get() / amount );
-        return property;
-    }
-
-    // Double operations
-
-    public static Property<Double> add( Property<Double> property, double amount )
-    {
-        property.set( property.get() + amount );
-        return property;
-    }
-
-    public static Property<Double> mult( Property<Double> property, double amount )
-    {
-        property.set( property.get() * amount );
-        return property;
-    }
-
-    public static Property<Double> sub( Property<Double> property, double amount )
-    {
-        property.set( property.get() - amount );
-        return property;
-    }
-
-    public static Property<Double> div( Property<Double> property, double amount )
-    {
-        property.set( property.get() / amount );
-        return property;
-    }
-
-    // Float operations
-
-    public static Property<Float> add( Property<Float> property, float amount )
-    {
-        property.set( property.get() + amount );
-        return property;
-    }
-
-    public static Property<Float> mult( Property<Float> property, float amount )
-    {
-        property.set( property.get() * amount );
-        return property;
-    }
-
-    public static Property<Float> sub( Property<Float> property, float amount )
-    {
-        property.set( property.get() - amount );
-        return property;
-    }
-
-    public static Property<Float> div( Property<Float> property, float amount )
-    {
-        property.set( property.get() / amount );
-        return property;
-    }
-
-    // BigDecimal operations
-
-    public static Property<BigDecimal> add( Property<BigDecimal> property, BigDecimal amount )
-    {
-        property.set( property.get().add( amount ) );
-        return property;
-    }
-
-    public static Property<BigDecimal> mult( Property<BigDecimal> property, BigDecimal amount )
-    {
-        property.set( property.get().multiply( amount ) );
-        return property;
-    }
-
-    public static Property<BigDecimal> sub( Property<BigDecimal> property, BigDecimal amount )
-    {
-        property.set( property.get().subtract( amount ) );
-        return property;
-    }
-
-    public static Property<BigDecimal> div( Property<BigDecimal> property, BigDecimal amount )
-    {
-        property.set( property.get().divide( amount ) );
-        return property;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/property/Property.java b/core/api/src/main/java/org/qi4j/api/property/Property.java
deleted file mode 100644
index 9c9cfa8..0000000
--- a/core/api/src/main/java/org/qi4j/api/property/Property.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2007-2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed  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.qi4j.api.property;
-
-/**
- * Properties are declared in Composite interfaces by using this interface.
- * <p>
- * It creates a first-class object for the property from which you can get and set the value, and access any
- * metadata about it.
- * </p>
- * <p>The type of the Property can be one of the following:</p>
- * <ul>
- * <li> A boxed primitive (Long,Integer,Boolean, etc.)</li>
- * <li> String</li>
- * <li> BigInteger</li>
- * <li> BigDecimal</li>
- * <li> Date</li>
- * <li> DateTime (Joda Time)</li>
- * <li> LocalDateTime (Joda Time)</li>
- * <li> A serializable</li>
- * <li> A ValueComposite</li>
- * <li> A List, Set or Collection of any of the above</li>
- * </ul>
- *
- * @param <T> Parameterized type of the Property
- */
-public interface Property<T>
-{
-    /**
-     * Get the value of the property.
-     *
-     * @return the value
-     */
-    T get();
-
-    /**
-     * Set the value of the property
-     *
-     * @param newValue the new value
-     *
-     * @throws IllegalArgumentException if the value has an invalid value
-     * @throws IllegalStateException    if the property is immutable
-     */
-    void set( T newValue )
-        throws IllegalArgumentException, IllegalStateException;
-}
diff --git a/core/api/src/main/java/org/qi4j/api/property/PropertyDescriptor.java b/core/api/src/main/java/org/qi4j/api/property/PropertyDescriptor.java
deleted file mode 100644
index aa986b1..0000000
--- a/core/api/src/main/java/org/qi4j/api/property/PropertyDescriptor.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.property;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Type;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.structure.MetaInfoHolder;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.type.ValueType;
-
-/**
- * Property Descriptor.
- */
-public interface PropertyDescriptor extends MetaInfoHolder
-{
-    boolean isImmutable();
-
-    /**
-     * Get the qualified name of the property which is equal to:
-     * <pre><code>
-     * &lt;interface name&gt;:&lt;method name&gt;
-     * </code></pre>
-     *
-     * @return the qualified name of the property
-     */
-    QualifiedName qualifiedName();
-
-    /**
-     * Get the type of the property. If the property is declared
-     * as Property&lt;X&gt; then X is returned.
-     *
-     * @return the property type
-     */
-    Type type();
-
-    AccessibleObject accessor();
-
-    Object initialValue( Module module );
-
-    ValueType valueType();
-
-    boolean queryable();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/property/PropertyMixin.java b/core/api/src/main/java/org/qi4j/api/property/PropertyMixin.java
deleted file mode 100644
index 26f8bd5..0000000
--- a/core/api/src/main/java/org/qi4j/api/property/PropertyMixin.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.property;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.AppliesToFilter;
-import org.qi4j.api.injection.scope.State;
-
-/**
- * Generic mixin for properties.
- */
-// START SNIPPET: actual
-@AppliesTo( { PropertyMixin.PropertyFilter.class } )
-public final class PropertyMixin
-    implements InvocationHandler
-{
-    @State
-    private StateHolder state;
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        return state.propertyFor( method );
-    }
-
-    /**
-     * Filter Property methods to apply generic Property Mixin.
-     */
-    public static class PropertyFilter
-        implements AppliesToFilter
-    {
-        @Override
-        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> modifierClass )
-        {
-            return Property.class.isAssignableFrom( method.getReturnType() );
-        }
-    }
-}
-// END SNIPPET: actual
diff --git a/core/api/src/main/java/org/qi4j/api/property/PropertyWrapper.java b/core/api/src/main/java/org/qi4j/api/property/PropertyWrapper.java
deleted file mode 100644
index dc2259d..0000000
--- a/core/api/src/main/java/org/qi4j/api/property/PropertyWrapper.java
+++ /dev/null
@@ -1,71 +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.qi4j.api.property;
-
-/**
- * If you want to catch getting and setting properties, then create a GenericConcern
- * that wraps the Zest-supplied Property instance with PropertyWrappers. Override
- * get() and/or set() to perform your custom code.
- */
-public class PropertyWrapper
-    implements Property<Object>
-{
-    protected Property<Object> next;
-
-    public PropertyWrapper( Property<Object> next )
-    {
-        this.next = next;
-    }
-
-    public Property<Object> next()
-    {
-        return next;
-    }
-
-    @Override
-    public Object get()
-    {
-        return next.get();
-    }
-
-    @Override
-    public void set( Object newValue )
-        throws IllegalArgumentException, IllegalStateException
-    {
-        next.set( newValue );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return next.hashCode();
-    }
-
-    @Override
-    public boolean equals( Object obj )
-    {
-        return next.equals( obj );
-    }
-
-    @Override
-    public String toString()
-    {
-        return next.toString();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/property/StateHolder.java b/core/api/src/main/java/org/qi4j/api/property/StateHolder.java
deleted file mode 100644
index dfd0b29..0000000
--- a/core/api/src/main/java/org/qi4j/api/property/StateHolder.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.property;
-
-import java.lang.reflect.AccessibleObject;
-
-/**
- * This represents the state of a composite (properties).
- */
-public interface StateHolder
-{
-    /**
-     * Get a property for a specific accessor
-     *
-     * @param accessor of the property
-     *
-     * @return the property
-     *
-     * @throws IllegalArgumentException if no property for given accessor exists
-     */
-    <T> Property<T> propertyFor( AccessibleObject accessor )
-        throws IllegalArgumentException;
-
-    Iterable<? extends Property<?>> properties();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/property/package.html b/core/api/src/main/java/org/qi4j/api/property/package.html
deleted file mode 100644
index 8fc2a93..0000000
--- a/core/api/src/main/java/org/qi4j/api/property/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Property API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/query/MissingIndexingSystemException.java b/core/api/src/main/java/org/qi4j/api/query/MissingIndexingSystemException.java
deleted file mode 100644
index 6bfd216..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/MissingIndexingSystemException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.query;
-
-/**
- * This Exception is thrown in <code>QueryBuilderFactory.newQueryBuilder()</code> method if
- * no indexing subsystem has been declared in the assembly.
- */
-public final class MissingIndexingSystemException
-    extends QueryException
-{
-    private static final long serialVersionUID = 5147421865890379209L;
-
-    public MissingIndexingSystemException()
-    {
-        super( "No EntityFinder has been declared in the assembly of the application." );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/NotQueryableException.java b/core/api/src/main/java/org/qi4j/api/query/NotQueryableException.java
deleted file mode 100644
index 74737eb..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/NotQueryableException.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2009 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.api.query;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Member;
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.api.property.GenericPropertyInfo;
-import org.qi4j.api.util.Classes;
-
-/**
- * Thrown in case that a non queryable type or accessor (marked with @Queriable(false)) is used during query building,
- * or when non-Property, non-Associations are trying to be queried (possibly can not happen).
- */
-public class NotQueryableException
-    extends QueryException
-{
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * Constructor.
-     *
-     * @param message exception message
-     */
-    public NotQueryableException( final String message )
-    {
-        super( message );
-    }
-
-    /**
-     * Verify that the provided accessor method has not been marked with a Queryable(false).
-     *
-     * @param accessor accessor method
-     *
-     * @throws NotQueryableException - If accessor method has been marked as not queryable
-     */
-    public static void throwIfNotQueryable( final AccessibleObject accessor )
-    {
-        Queryable queryable = accessor.getAnnotation( Queryable.class );
-        if( queryable != null && !queryable.value() )
-        {
-            throw new NotQueryableException(
-                String.format(
-                    "%1$s \"%2$s\" (%3$s) is not queryable as has been marked with @Queryable(false)",
-                    Classes.RAW_CLASS.map( GenericPropertyInfo.propertyTypeOf( accessor ) ).getSimpleName(),
-                    ( (Member) accessor ).getName(),
-                    ( (Member) accessor ).getDeclaringClass().getName()
-                )
-            );
-        }
-    }
-
-    /**
-     * Verify that the provided type has not been marked with a Queryable(false).
-     *
-     * @param type a type
-     *
-     * @throws NotQueryableException - If type has been marked as not queryable
-     */
-    public static void throwIfNotQueryable( final Class<?> type )
-    {
-        Queryable queryable = type.getAnnotation( Queryable.class );
-        if( queryable != null && !queryable.value() )
-        {
-            throw new NotQueryableException(
-                String.format(
-                    "Type \"%1$s\" is not queryable as has been marked with @Queryable(false)",
-                    type.getName()
-                )
-            );
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/query/Query.java b/core/api/src/main/java/org/qi4j/api/query/Query.java
deleted file mode 100644
index 504b2e2..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/Query.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg.
- * Copyright 2007 Niclas Hedhman.
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed 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.qi4j.api.query;
-
-import java.io.Serializable;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.grammar.OrderBy;
-
-/**
- * This represents a Query in an indexing system. It is created from a
- * {@link QueryBuilder}, which decides the "where" clause in the query.
- * <p>
- * Additional limitations, such as paging, ordering, and variables, can be set on
- * a Query before it is executed by calling one of find(), iterator(),
- * or count().
- * </p>
- * <p>
- * DDD tip: typically Queries are created in the Domain Model and passed to the UI,
- * which sets the order and paging before executing it.
- * </p>
- */
-public interface Query<T>
-    extends Iterable<T>, Serializable
-{
-    /**
-     * Set the ordering rules. If many segments are used for ordering
-     * then they will be applied in order.
-     *
-     * @param segments the segments to order by
-     *
-     * @return the Query
-     */
-    Query<T> orderBy( OrderBy... segments );
-
-    /**
-     * Append an ordering rule to the existing segments.
-     *
-     * @param property the property to order by
-     * @param order the order to apply
-     *
-     * @return the Query
-     */
-    Query<T> orderBy( final Property<?> property, final OrderBy.Order order );
-
-    /**
-     * Append an ascending ordering rule to the existing segments.
-     *
-     * @param property the property to order by
-     *
-     * @return the Query
-     */
-    Query<T> orderBy( Property<?> property );
-
-    /**
-     * Set the index of the first result. Default is 0 (zero).
-     *
-     * @param firstResult which index to use as the first one
-     *
-     * @return the Query
-     */
-    Query<T> firstResult( int firstResult );
-
-    /**
-     * Set how many results should be returned. Default is that
-     * there is no limit set.
-     *
-     * @param maxResults that shouldbe returned
-     *
-     * @return the query
-     */
-    Query<T> maxResults( int maxResults );
-
-    /**
-     * Get the first Entity that matches the criteria. This
-     * executes the Query.
-     *
-     * @return the first found Entity or null if none were found
-     *
-     * @throws QueryExecutionException if the query fails
-     */
-    T find()
-        throws QueryExecutionException;
-
-    /**
-     * Set the value of a named variable.
-     *
-     * @param name  of the variable
-     * @param value of the variable
-     *
-     * @return the query
-     */
-    Query<T> setVariable( String name, Object value );
-
-    /**
-     * Get the value of a named variable.
-     *
-     * @param name of the variable
-     *
-     * @return value of the variable
-     */
-    <V> V getVariable( String name );
-
-    /**
-     * Get the result type of this Query
-     *
-     * @return the result type
-     */
-    Class<T> resultType();
-
-    /**
-     * Count how many results would be returned by this Query.
-     * This executes the Query.
-     *
-     * @return result count
-     *
-     * @throws QueryExecutionException if the query fails
-     */
-    long count()
-        throws QueryExecutionException;
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/query/QueryBuilder.java b/core/api/src/main/java/org/qi4j/api/query/QueryBuilder.java
deleted file mode 100644
index c07552c..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/QueryBuilder.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg.
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed 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.qi4j.api.query;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.functional.Specification;
-
-/**
- * QueryBuilders are used to create {@link Query} instances.
- * Iteratively add where() clauses to the query, and then use
- * {@link org.qi4j.api.unitofwork.UnitOfWork#newQuery(QueryBuilder)}  to instantiate the Query.
- * QueryBuilders are immutable, so when adding new where-clauses you get new instances. This
- *
- * DDD tip: Query objects are not executed immediately, so they
- * should be constructed in the domain model and handed over to
- * the UI, which can then further constrain it before actual
- * execution.
- */
-public interface QueryBuilder<T>
-{
-    /**
-     * Add a where-clause to the Query. Use {@link QueryExpressions}
-     * to create the expression.
-     *
-     * @param specification the where clause
-     *
-     * @return a new builder with the added where-clause
-     */
-    QueryBuilder<T> where( Specification<Composite> specification );
-
-    /**
-     * Create a new query with the declared where-clauses that will be evaluated against the iterable entries.
-     *
-     * @param iterable collection of objects (composites?)
-     *
-     * @return a new Query instance
-     */
-    Query<T> newQuery( Iterable<T> iterable );
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/query/QueryBuilderFactory.java b/core/api/src/main/java/org/qi4j/api/query/QueryBuilderFactory.java
deleted file mode 100644
index 8841030..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/QueryBuilderFactory.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2007 Niclas Hedhman.
- *
- * Licensed 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.qi4j.api.query;
-
-/**
- * This is used to create QueryBuilders.
- *
- * @see QueryBuilder
- */
-public interface QueryBuilderFactory
-{
-    /**
-     * Create a new QueryBuilder.
-     *
-     * @param resultType the type of the result that you want
-     *
-     * @return a QueryBuilder
-     *
-     * @throws MissingIndexingSystemException if there is no EntityFinder service available
-     */
-    <T> QueryBuilder<T> newQueryBuilder( Class<T> resultType )
-        throws MissingIndexingSystemException;
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/query/QueryException.java b/core/api/src/main/java/org/qi4j/api/query/QueryException.java
deleted file mode 100644
index 6caca4c..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/QueryException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.query;
-
-/**
- * Base class for Query exceptions.
- */
-public abstract class QueryException
-    extends RuntimeException
-{
-    private static final long serialVersionUID = -3602596752342902060L;
-
-    public QueryException()
-    {
-    }
-
-    public QueryException( final String message )
-    {
-        super( message );
-    }
-
-    public QueryException( final String message, final Throwable cause )
-    {
-        super( message, cause );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/QueryExecutionException.java b/core/api/src/main/java/org/qi4j/api/query/QueryExecutionException.java
deleted file mode 100644
index f8cad23..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/QueryExecutionException.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.query;
-
-/**
- * Throw this exception if a query could not be executed
- */
-public final class QueryExecutionException
-    extends QueryException
-{
-    private static final long serialVersionUID = 5147421865890379209L;
-
-    public QueryExecutionException( String message )
-    {
-        super( message );
-    }
-
-    public QueryExecutionException( String message, Throwable cause )
-    {
-        super( message, cause );
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/query/QueryExpressionException.java b/core/api/src/main/java/org/qi4j/api/query/QueryExpressionException.java
deleted file mode 100644
index f0a7f8e..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/QueryExpressionException.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.api.query;
-
-/**
- * Throw this exception if a QueryExpression is invalid.
- */
-public class QueryExpressionException
-    extends QueryException
-{
-
-    private static final long serialVersionUID = 1L;
-
-    public QueryExpressionException( String message )
-    {
-        super( message );
-    }
-
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/QueryExpressions.java b/core/api/src/main/java/org/qi4j/api/query/QueryExpressions.java
deleted file mode 100644
index 45501ee..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/QueryExpressions.java
+++ /dev/null
@@ -1,944 +0,0 @@
-/*
- * Copyright 2007-2011 Rickard Öberg.
- * Copyright 2007-2010 Niclas Hedhman.
- * Copyright 2008 Alin Dreghiciu.
- * Copyright 2012 Stanislav Muhametsin.
- * Copyright 2012-2014 Paul Merlin.
- *
- * Licensed 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
- * ied.
- *
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.qi4j.api.query;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.lang.reflect.Type;
-import java.util.Arrays;
-import java.util.Collection;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.GenericAssociationInfo;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.State;
-import org.qi4j.api.property.GenericPropertyInfo;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.grammar.AndSpecification;
-import org.qi4j.api.query.grammar.AssociationFunction;
-import org.qi4j.api.query.grammar.AssociationNotNullSpecification;
-import org.qi4j.api.query.grammar.AssociationNullSpecification;
-import org.qi4j.api.query.grammar.ContainsAllSpecification;
-import org.qi4j.api.query.grammar.ContainsSpecification;
-import org.qi4j.api.query.grammar.EqSpecification;
-import org.qi4j.api.query.grammar.GeSpecification;
-import org.qi4j.api.query.grammar.GtSpecification;
-import org.qi4j.api.query.grammar.LeSpecification;
-import org.qi4j.api.query.grammar.LtSpecification;
-import org.qi4j.api.query.grammar.ManyAssociationContainsSpecification;
-import org.qi4j.api.query.grammar.ManyAssociationFunction;
-import org.qi4j.api.query.grammar.MatchesSpecification;
-import org.qi4j.api.query.grammar.NamedAssociationContainsNameSpecification;
-import org.qi4j.api.query.grammar.NamedAssociationContainsSpecification;
-import org.qi4j.api.query.grammar.NamedAssociationFunction;
-import org.qi4j.api.query.grammar.NeSpecification;
-import org.qi4j.api.query.grammar.NotSpecification;
-import org.qi4j.api.query.grammar.OrSpecification;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.api.query.grammar.PropertyFunction;
-import org.qi4j.api.query.grammar.PropertyNotNullSpecification;
-import org.qi4j.api.query.grammar.PropertyNullSpecification;
-import org.qi4j.api.query.grammar.PropertyReference;
-import org.qi4j.api.query.grammar.Variable;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.functional.Specification;
-
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.prepend;
-
-/**
- * Static factory methods for query expressions and operators.
- */
-public final class QueryExpressions
-{
-    // This is used for eq(Association,Composite)
-    private static final Method IDENTITY_METHOD;
-
-    static
-    {
-        try
-        {
-            IDENTITY_METHOD = Identity.class.getMethod( "identity" );
-        }
-        catch( NoSuchMethodException e )
-        {
-            throw new InternalError( "Zest Core API codebase is corrupted. Contact Zest team: QueryExpressions" );
-        }
-    }
-
-    // Templates and variables -----------------------------------------------|
-
-    /**
-     * Create a Query Template using the given type.
-     *
-     * @param <T> the type of the template
-     * @param clazz a class declaring the type of the template
-     *
-     * @return a new Query Template
-     */
-    public static <T> T templateFor( Class<T> clazz )
-    {
-        NullArgumentException.validateNotNull( "Template class", clazz );
-
-        if( clazz.isInterface() )
-        {
-            return clazz.cast( Proxy.newProxyInstance( clazz.getClassLoader(),
-                                                       array( clazz ),
-                                                       new TemplateHandler<T>( null, null, null, null ) ) );
-        }
-        else
-        {
-            try
-            {
-                T mixin = clazz.newInstance();
-                for( Field field : clazz.getFields() )
-                {
-                    if( field.getAnnotation( State.class ) != null )
-                    {
-                        if( field.getType().equals( Property.class ) )
-                        {
-                            field.set( mixin,
-                                       Proxy.newProxyInstance( field.getType().getClassLoader(),
-                                                               array( field.getType() ),
-                                                               new PropertyReferenceHandler<>( new PropertyFunction<T>( null, null, null, null, field ) ) ) );
-                        }
-                        else if( field.getType().equals( Association.class ) )
-                        {
-                            field.set( mixin,
-                                       Proxy.newProxyInstance( field.getType().getClassLoader(),
-                                                               array( field.getType() ),
-                                                               new AssociationReferenceHandler<>( new AssociationFunction<T>( null, null, null, field ) ) ) );
-                        }
-                        else if( field.getType().equals( ManyAssociation.class ) )
-                        {
-                            field.set( mixin,
-                                       Proxy.newProxyInstance( field.getType().getClassLoader(),
-                                                               array( field.getType() ),
-                                                               new ManyAssociationReferenceHandler<>( new ManyAssociationFunction<T>( null, null, null, field ) ) ) );
-                        }
-                        else if( field.getType().equals( NamedAssociation.class ) )
-                        {
-                            field.set( mixin,
-                                       Proxy.newProxyInstance( field.getType().getClassLoader(),
-                                                               array( field.getType() ),
-                                                               new NamedAssociationReferenceHandler<>( new NamedAssociationFunction<T>( null, null, null, field ) ) ) );
-                        }
-                    }
-                }
-                return mixin;
-            }
-            catch( IllegalAccessException | IllegalArgumentException | InstantiationException | SecurityException e )
-            {
-                throw new IllegalArgumentException( "Cannot use class as template", e );
-            }
-        }
-    }
-
-    /**
-     * Create a Query Template using the given mixin class and association.
-     *
-     * @param <T> the type of the template
-     * @param mixinType  a class declaring the type of the template
-     * @param association an association
-     *
-     * @return a new Query Template
-     */
-    public static <T> T templateFor( final Class<T> mixinType, Association<?> association )
-    {
-        NullArgumentException.validateNotNull( "Mixin class", mixinType );
-        NullArgumentException.validateNotNull( "Association", association );
-        return mixinType.cast( Proxy.newProxyInstance( mixinType.getClassLoader(),
-                                                       array( mixinType ),
-                                                       new TemplateHandler<T>( null,
-                                                                               association( association ),
-                                                                               null,
-                                                                               null ) ) );
-    }
-
-    public static <T> T oneOf( final ManyAssociation<T> association )
-    {
-        NullArgumentException.validateNotNull( "Association", association );
-        return association.get( 0 );
-    }
-
-    public static <T> T oneOf( final NamedAssociation<T> association )
-    {
-        NullArgumentException.validateNotNull( "Association", association );
-        return association.get( first( association ) );
-    }
-
-    /**
-     * Create a new Query Variable.
-     *
-     * @param name a name for the Variable
-     *
-     * @return a new Query Variable.
-     */
-    public static Variable variable( String name )
-    {
-        NullArgumentException.validateNotNull( "Variable name", name );
-        return new Variable( name );
-    }
-
-    /**
-     * Create a new Query Template PropertyFunction.
-     *
-     * @param <T> type of the Property
-     * @param property a Property
-     *
-     * @return a new Query Template PropertyFunction
-     */
-    @SuppressWarnings( "unchecked" )
-    public static <T> PropertyFunction<T> property( Property<T> property )
-    {
-        return ( (PropertyReferenceHandler<T>) Proxy.getInvocationHandler( property ) ).property();
-    }
-
-    /**
-     * Create a new Query Property instance.
-     *
-     * @param <T> type of the Property
-     * @param mixinClass mixin of the Property
-     * @param fieldName name of the Property field
-     *
-     * @return a new Query Property instance for the given mixin and property name.
-     */
-    @SuppressWarnings( "unchecked" )
-    public static <T> Property<T> property( Class<?> mixinClass, String fieldName )
-    {
-        try
-        {
-            Field field = mixinClass.getField( fieldName );
-            if( !Property.class.isAssignableFrom( field.getType() ) )
-            {
-                throw new IllegalArgumentException( "Field must be of type Property<?>" );
-            }
-            return (Property<T>) Proxy.newProxyInstance(
-                mixinClass.getClassLoader(),
-                array( field.getType() ),
-                new PropertyReferenceHandler<>( new PropertyFunction<T>( null, null, null, null, field ) ) );
-        }
-        catch( NoSuchFieldException e )
-        {
-            throw new IllegalArgumentException( "No such field '" + fieldName + "' in mixin " + mixinClass.getName() );
-        }
-    }
-
-    /**
-     * Create a new Query Template AssociationFunction.
-     *
-     * @param <T> type of the Association
-     * @param association an Association
-     *
-     * @return a new Query Template AssociationFunction
-     */
-    @SuppressWarnings( "unchecked" )
-    public static <T> AssociationFunction<T> association( Association<T> association )
-    {
-        return ( (AssociationReferenceHandler<T>) Proxy.getInvocationHandler( association ) ).association();
-    }
-
-    /**
-     * Create a new Query Template ManyAssociationFunction.
-     *
-     * @param <T> type of the ManyAssociation
-     * @param association a ManyAssociation
-     *
-     * @return a new Query Template ManyAssociationFunction
-     */
-    @SuppressWarnings( "unchecked" )
-    public static <T> ManyAssociationFunction<T> manyAssociation( ManyAssociation<T> association )
-    {
-        return ( (ManyAssociationReferenceHandler<T>) Proxy.getInvocationHandler( association ) ).manyAssociation();
-    }
-
-    /**
-     * Create a new Query Template NamedAssociationFunction.
-     *
-     * @param <T> type of the NamedAssociation
-     * @param association a NamedAssociation
-     *
-     * @return a new Query Template NamedAssociationFunction
-     */
-    @SuppressWarnings( "unchecked" )
-    public static <T> NamedAssociationFunction<T> namedAssociation( NamedAssociation<T> association )
-    {
-        return ( (NamedAssociationReferenceHandler<T>) Proxy.getInvocationHandler( association ) ).namedAssociation();
-    }
-
-    // And/Or/Not ------------------------------------------------------------|
-    /**
-     * Create a new AND specification.
-     *
-     * @param left first operand
-     * @param right second operand
-     * @param optionalRight optional operands
-     *
-     * @return a new AND specification
-     */
-    @SafeVarargs
-    public static AndSpecification and( Specification<Composite> left,
-                                        Specification<Composite> right,
-                                        Specification<Composite>... optionalRight
-    )
-    {
-        return new AndSpecification( prepend( left, prepend( right, Arrays.asList( optionalRight ) ) ) );
-    }
-
-    /**
-     * Create a new OR specification.
-     *
-     * @param specs operands
-     *
-     * @return a new OR specification
-     */
-    @SafeVarargs
-    public static OrSpecification or( Specification<Composite>... specs )
-    {
-        return new OrSpecification( Arrays.asList( specs ) );
-    }
-
-    /**
-     * Create a new NOT specification.
-     *
-     * @param operand specification to be negated
-     *
-     * @return a new NOT specification
-     */
-    public static NotSpecification not( Specification<Composite> operand )
-    {
-        return new NotSpecification( operand );
-    }
-
-    // Comparisons -----------------------------------------------------------|
-
-    /**
-     * Create a new EQUALS specification for a Property.
-     *
-     * @param property a Property
-     * @param value its value
-     *
-     * @return a new EQUALS specification for a Property.
-     */
-    public static <T> EqSpecification<T> eq( Property<T> property, T value )
-    {
-        return new EqSpecification<>( property( property ), value );
-    }
-
-    /**
-     * Create a new EQUALS specification for a Property using a named Variable.
-     *
-     * @param property a Property
-     * @param variable a Query Variable
-     *
-     * @return a new EQUALS specification for a Property using a named Variable.
-     */
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public static <T> EqSpecification<T> eq( Property<T> property, Variable variable )
-    {
-        return new EqSpecification( property( property ), variable );
-    }
-
-    /**
-     * Create a new EQUALS specification for an Association.
-     *
-     * @param association an Association
-     * @param value its value
-     *
-     * @return a new EQUALS specification for an Association.
-     */
-    public static <T> EqSpecification<String> eq( Association<T> association, T value )
-    {
-        return new EqSpecification<>( new PropertyFunction<String>( null,
-                                                                    association( association ),
-                                                                    null,
-                                                                    null,
-                                                                    IDENTITY_METHOD ),
-                                      value.toString() );
-    }
-
-    /**
-     * Create a new GREATER OR EQUALS specification for a Property.
-     *
-     * @param property a Property
-     * @param value its value
-     *
-     * @return a new GREATER OR EQUALS specification for a Property.
-     */
-    public static <T> GeSpecification<T> ge( Property<T> property, T value )
-    {
-        return new GeSpecification<>( property( property ), value );
-    }
-
-    /**
-     * Create a new GREATER OR EQUALS specification for a Property using a named Variable.
-     *
-     * @param property a Property
-     * @param variable a Query Variable
-     *
-     * @return a new GREATER OR EQUALS specification for a Property using a named Variable.
-     */
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public static <T> GeSpecification<T> ge( Property<T> property, Variable variable )
-    {
-        return new GeSpecification( property( property ), variable );
-    }
-
-    /**
-     * Create a new GREATER THAN specification for a Property.
-     *
-     * @param property a Property
-     * @param value its value
-     *
-     * @return a new GREATER THAN specification for a Property.
-     */
-    public static <T> GtSpecification<T> gt( Property<T> property, T value )
-    {
-        return new GtSpecification<>( property( property ), value );
-    }
-
-    /**
-     * Create a new GREATER THAN specification for a Property using a named Variable.
-     *
-     * @param property a Property
-     * @param variable a Query Variable
-     *
-     * @return a new GREATER THAN specification for a Property using a named Variable.
-     */
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public static <T> GtSpecification<T> gt( Property<T> property, Variable variable )
-    {
-        return new GtSpecification( property( property ), variable );
-    }
-
-    /**
-     * Create a new LESS OR EQUALS specification for a Property.
-     *
-     * @param property a Property
-     * @param value its value
-     *
-     * @return a new LESS OR EQUALS specification for a Property.
-     */
-    public static <T> LeSpecification<T> le( Property<T> property, T value )
-    {
-        return new LeSpecification<>( property( property ), value );
-    }
-
-    /**
-     * Create a new LESS OR EQUALS specification for a Property using a named Variable.
-     *
-     * @param property a Property
-     * @param variable a Query Variable
-     *
-     * @return a new LESS OR EQUALS specification for a Property using a named Variable.
-     */
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public static <T> LeSpecification<T> le( Property<T> property, Variable variable )
-    {
-        return new LeSpecification( property( property ), variable );
-    }
-
-    /**
-     * Create a new LESSER THAN specification for a Property.
-     *
-     * @param property a Property
-     * @param value its value
-     *
-     * @return a new LESSER THAN specification for a Property.
-     */
-    public static <T> LtSpecification<T> lt( Property<T> property, T value )
-    {
-        return new LtSpecification<>( property( property ), value );
-    }
-
-    /**
-     * Create a new LESSER THAN specification for a Property using a named Variable.
-     *
-     * @param property a Property
-     * @param variable a Query Variable
-     *
-     * @return a new LESSER THAN specification for a Property using a named Variable.
-     */
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public static <T> LtSpecification<T> lt( Property<T> property, Variable variable )
-    {
-        return new LtSpecification( property( property ), variable );
-    }
-
-    /**
-     * Create a new NOT EQUALS specification for a Property.
-     *
-     * @param property a Property
-     * @param value its value
-     *
-     * @return a new NOT EQUALS specification for a Property.
-     */
-    public static <T> NeSpecification<T> ne( Property<T> property, T value )
-    {
-        return new NeSpecification<>( property( property ), value );
-    }
-
-    /**
-     * Create a new NOT EQUALS specification for a Property using a named Variable.
-     *
-     * @param property a Property
-     * @param variable a Query Variable
-     *
-     * @return a new NOT EQUALS specification for a Property using a named Variable.
-     */
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public static <T> NeSpecification<T> ne( Property<T> property, Variable variable )
-    {
-        return new NeSpecification( property( property ), variable );
-    }
-
-    /**
-     * Create a new REGULAR EXPRESSION specification for a Property.
-     *
-     * @param property a Property
-     * @param regexp its value
-     *
-     * @return a new REGULAR EXPRESSION specification for a Property.
-     */
-    public static MatchesSpecification matches( Property<String> property, String regexp )
-    {
-        return new MatchesSpecification( property( property ), regexp );
-    }
-
-    /**
-     * Create a new REGULAR EXPRESSION specification for a Property using a named Variable.
-     *
-     * @param property a Property
-     * @param variable a Query Variable
-     *
-     * @return a new REGULAR EXPRESSION specification for a Property using a named Variable.
-     */
-    public static MatchesSpecification matches( Property<String> property, Variable variable )
-    {
-        return new MatchesSpecification( property( property ), variable );
-    }
-
-    // Null checks -----------------------------------------------------------|
-
-    /**
-     * Create a new NOT NULL specification for a Property.
-     *
-     * @param property a Property
-     *
-     * @return a new NOT NULL specification for a Property.
-     */
-    public static <T> PropertyNotNullSpecification<T> isNotNull( Property<T> property )
-    {
-        return new PropertyNotNullSpecification<>( property( property ) );
-    }
-
-    /**
-     * Create a new NULL specification for a Property.
-     *
-     * @param property a Property
-     *
-     * @return a new NULL specification for a Property.
-     */
-    public static <T> PropertyNullSpecification<T> isNull( Property<T> property )
-    {
-        return new PropertyNullSpecification<>( property( property ) );
-    }
-
-    /**
-     * Create a new NOT NULL specification for an Association.
-     *
-     * @param association an Association
-     *
-     * @return a new NOT NULL specification for an Association.
-     */
-    public static <T> AssociationNotNullSpecification<T> isNotNull( Association<T> association )
-    {
-        return new AssociationNotNullSpecification<>( association( association ) );
-    }
-
-    /**
-     * Create a new NULL specification for an Association.
-     *
-     * @param association an Association
-     *
-     * @return a new NULL specification for an Association.
-     */
-    public static <T> AssociationNullSpecification<T> isNull( Association<T> association )
-    {
-        return new AssociationNullSpecification<>( association( association ) );
-    }
-
-    // Collections -----------------------------------------------------------|
-
-    /**
-     * Create a new CONTAINS ALL specification for a Collection Property.
-     *
-     * @param collectionProperty a Collection Property
-     * @param values its values
-     *
-     * @return a new CONTAINS ALL specification for a Collection Property.
-     */
-    public static <T> ContainsAllSpecification<T> containsAll( Property<? extends Collection<T>> collectionProperty,
-                                                               Iterable<T> values )
-    {
-        NullArgumentException.validateNotNull( "Values", values );
-        return new ContainsAllSpecification<>( property( collectionProperty ), values );
-    }
-
-    /**
-     * Create a new CONTAINS ALL specification for a Collection Property using named Variables.
-     *
-     * @param collectionProperty a Collection Property
-     * @param variables named Variables
-     *
-     * @return a new CONTAINS ALL specification for a Collection Property using named Variables.
-     */
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public static <T> ContainsAllSpecification<T> containsAllVariables(
-        Property<? extends Collection<T>> collectionProperty,
-        Iterable<Variable> variables )
-    {
-        NullArgumentException.validateNotNull( "Variables", variables );
-        return new ContainsAllSpecification( property( collectionProperty ), variables );
-    }
-
-    /**
-     * Create a new CONTAINS specification for a Collection Property.
-     *
-     * @param collectionProperty a Collection Property
-     * @param value the value
-     *
-     * @return a new CONTAINS specification for a Collection Property.
-     */
-    public static <T> ContainsSpecification<T> contains( Property<? extends Collection<T>> collectionProperty,
-                                                         T value )
-    {
-        NullArgumentException.validateNotNull( "Value", value );
-        return new ContainsSpecification<>( property( collectionProperty ), value );
-    }
-
-    /**
-     * Create a new CONTAINS specification for a Collection Property using named Variables.
-     *
-     * @param collectionProperty a Collection Property
-     * @param variable named Variable
-     *
-     * @return a new CONTAINS specification for a Collection Property using named Variables.
-     */
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public static <T> ContainsSpecification<T> contains( Property<? extends Collection<T>> collectionProperty,
-                                                         Variable variable )
-    {
-        NullArgumentException.validateNotNull( "Variable", variable );
-        return new ContainsSpecification( property( collectionProperty ), variable );
-    }
-
-    /**
-     * Create a new CONTAINS specification for a ManyAssociation.
-     *
-     * @param manyAssoc  a ManyAssociation
-     * @param value the value
-     *
-     * @return a new CONTAINS specification for a ManyAssociation.
-     */
-    public static <T> ManyAssociationContainsSpecification<T> contains( ManyAssociation<T> manyAssoc, T value )
-    {
-        return new ManyAssociationContainsSpecification<>( manyAssociation( manyAssoc ), value );
-    }
-
-    /**
-     * Create a new CONTAINS specification for a NamedAssociation.
-     *
-     * @param namedAssoc  a NamedAssociation
-     * @param value the value
-     *
-     * @return a new CONTAINS specification for a NamedAssociation.
-     */
-    public static <T> NamedAssociationContainsSpecification<T> contains( NamedAssociation<T> namedAssoc, T value )
-    {
-        return new NamedAssociationContainsSpecification<>( namedAssociation( namedAssoc ), value );
-    }
-
-    /**
-     * Create a new CONTAINS NAME specification for a NamedAssociation.
-     *
-     * @param namedAssoc  a NamedAssociation
-     * @param name the name
-     *
-     * @return a new CONTAINS NAME specification for a NamedAssociation.
-     */
-    public static <T> NamedAssociationContainsNameSpecification<T> containsName( NamedAssociation<T> namedAssoc,
-                                                                                 String name )
-    {
-        return new NamedAssociationContainsNameSpecification<>( namedAssociation( namedAssoc ), name );
-    }
-
-    // Ordering --------------------------------------------------------------|
-    /**
-     * Create a new Query ascending order segment for a Property.
-     *
-     * @param <T> type of the Property
-     * @param property a Property
-     *
-     * @return a new Query ascending order segment for a Property.
-     */
-    public static <T> OrderBy orderBy( final Property<T> property )
-    {
-        return orderBy( property, OrderBy.Order.ASCENDING );
-    }
-
-    /**
-     * Create a new Query ordering segment for a Property.
-     *
-     * @param <T> type of the Property
-     * @param property a Property
-     * @param order ascending or descending
-     *
-     * @return a new Query ordering segment for a Property.
-     */
-    public static <T> OrderBy orderBy( final Property<T> property, final OrderBy.Order order )
-    {
-        return new OrderBy( property( property ), order );
-    }
-
-    // Query Templates InvocationHandlers ------------------------------------|
-
-    private static class TemplateHandler<T>
-        implements InvocationHandler
-    {
-        private final PropertyFunction<?> compositeProperty;
-        private final AssociationFunction<?> compositeAssociation;
-        private final ManyAssociationFunction<?> compositeManyAssociation;
-        private final NamedAssociationFunction<?> compositeNamedAssociation;
-
-        private TemplateHandler( PropertyFunction<?> compositeProperty,
-                                 AssociationFunction<?> compositeAssociation,
-                                 ManyAssociationFunction<?> compositeManyAssociation,
-                                 NamedAssociationFunction<?> compositeNamedAssociation
-        )
-        {
-            this.compositeProperty = compositeProperty;
-            this.compositeAssociation = compositeAssociation;
-            this.compositeManyAssociation = compositeManyAssociation;
-            this.compositeNamedAssociation = compositeNamedAssociation;
-        }
-
-        @Override
-        public Object invoke( Object o, Method method, Object[] objects )
-            throws Throwable
-        {
-            if( Property.class.isAssignableFrom( method.getReturnType() ) )
-            {
-                return Proxy.newProxyInstance(
-                    method.getReturnType().getClassLoader(),
-                    array( method.getReturnType() ),
-                    new PropertyReferenceHandler<>( new PropertyFunction<T>( compositeProperty,
-                                                                             compositeAssociation,
-                                                                             compositeManyAssociation,
-                                                                             compositeNamedAssociation,
-                                                                             method ) ) );
-            }
-            else if( Association.class.isAssignableFrom( method.getReturnType() ) )
-            {
-                return Proxy.newProxyInstance(
-                    method.getReturnType().getClassLoader(),
-                    array( method.getReturnType() ),
-                    new AssociationReferenceHandler<>( new AssociationFunction<T>( compositeAssociation,
-                                                                                   compositeManyAssociation,
-                                                                                   compositeNamedAssociation,
-                                                                                   method ) ) );
-            }
-            else if( ManyAssociation.class.isAssignableFrom( method.getReturnType() ) )
-            {
-                return Proxy.newProxyInstance(
-                    method.getReturnType().getClassLoader(),
-                    array( method.getReturnType() ),
-                    new ManyAssociationReferenceHandler<>( new ManyAssociationFunction<T>( compositeAssociation,
-                                                                                           compositeManyAssociation,
-                                                                                           compositeNamedAssociation,
-                                                                                           method ) ) );
-            }
-            else if( NamedAssociation.class.isAssignableFrom( method.getReturnType() ) )
-            {
-                return Proxy.newProxyInstance(
-                    method.getReturnType().getClassLoader(),
-                    array( method.getReturnType() ),
-                    new NamedAssociationReferenceHandler<>( new NamedAssociationFunction<T>( compositeAssociation,
-                                                                                             compositeManyAssociation,
-                                                                                             compositeNamedAssociation,
-                                                                                             method ) ) );
-            }
-
-            return null;
-        }
-    }
-
-    private static class PropertyReferenceHandler<T>
-        implements InvocationHandler
-    {
-        private final PropertyFunction<T> property;
-
-        private PropertyReferenceHandler( PropertyFunction<T> property )
-        {
-            this.property = property;
-        }
-
-        private PropertyFunction<T> property()
-        {
-            return property;
-        }
-
-        @Override
-        public Object invoke( Object o, final Method method, Object[] objects )
-            throws Throwable
-        {
-            if( method.equals( Property.class.getMethod( "get" ) ) )
-            {
-                Type propertyType = GenericPropertyInfo.propertyTypeOf( property.accessor() );
-                if( propertyType.getClass().equals( Class.class ) )
-                {
-                    return Proxy.newProxyInstance( method.getDeclaringClass().getClassLoader(),
-                                                   array( (Class<?>) propertyType, PropertyReference.class ),
-                                                   new TemplateHandler<T>( property, null, null, null ) );
-                }
-            }
-
-            return null;
-        }
-    }
-
-    private static class AssociationReferenceHandler<T>
-        implements InvocationHandler
-    {
-        private final AssociationFunction<T> association;
-
-        private AssociationReferenceHandler( AssociationFunction<T> association )
-        {
-            this.association = association;
-        }
-
-        private AssociationFunction<T> association()
-        {
-            return association;
-        }
-
-        @Override
-        public Object invoke( Object o, final Method method, Object[] objects )
-            throws Throwable
-        {
-            if( method.equals( Association.class.getMethod( "get" ) ) )
-            {
-                Type associationType = GenericAssociationInfo.associationTypeOf( association.accessor() );
-                if( associationType.getClass().equals( Class.class ) )
-                {
-                    return Proxy.newProxyInstance( method.getDeclaringClass().getClassLoader(),
-                                                   array( (Class) associationType, PropertyReference.class ),
-                                                   new TemplateHandler<T>( null, association, null, null ) );
-                }
-            }
-
-            return null;
-        }
-    }
-
-    private static class ManyAssociationReferenceHandler<T>
-        implements InvocationHandler
-    {
-        private final ManyAssociationFunction<T> manyAssociation;
-
-        private ManyAssociationReferenceHandler( ManyAssociationFunction<T> manyAssociation )
-        {
-            this.manyAssociation = manyAssociation;
-        }
-
-        public ManyAssociationFunction<T> manyAssociation()
-        {
-            return manyAssociation;
-        }
-
-        @Override
-        public Object invoke( Object o, final Method method, Object[] objects )
-            throws Throwable
-        {
-            if( method.equals( ManyAssociation.class.getMethod( "get", Integer.TYPE ) ) )
-            {
-                Type manyAssociationType = GenericAssociationInfo.associationTypeOf( manyAssociation.accessor() );
-                if( manyAssociationType.getClass().equals( Class.class ) )
-                {
-                    return Proxy.newProxyInstance( method.getDeclaringClass().getClassLoader(),
-                                                   array( (Class) manyAssociationType, PropertyReference.class ),
-                                                   new TemplateHandler<T>( null, null, manyAssociation, null ) );
-                }
-            }
-
-            return null;
-        }
-    }
-
-    private static class NamedAssociationReferenceHandler<T>
-        implements InvocationHandler
-    {
-        private final NamedAssociationFunction<T> namedAssociation;
-
-        private NamedAssociationReferenceHandler( NamedAssociationFunction<T> namedAssociation )
-        {
-            this.namedAssociation = namedAssociation;
-        }
-
-        public NamedAssociationFunction<T> namedAssociation()
-        {
-            return namedAssociation;
-        }
-
-        @Override
-        public Object invoke( Object o, final Method method, Object[] objects )
-            throws Throwable
-        {
-            if( method.equals( NamedAssociation.class.getMethod( "get", String.class ) ) )
-            {
-                Type namedAssociationType = GenericAssociationInfo.associationTypeOf( namedAssociation.accessor() );
-                if( namedAssociationType.getClass().equals( Class.class ) )
-                {
-                    return Proxy.newProxyInstance( method.getDeclaringClass().getClassLoader(),
-                                                   array( (Class) namedAssociationType, PropertyReference.class ),
-                                                   new TemplateHandler<T>( null, null, null, namedAssociation ) );
-                }
-            }
-
-            return null;
-        }
-    }
-
-    @SafeVarargs
-    private static <T> T[] array( T... array )
-    {
-        return array;
-    }
-
-    private QueryExpressions()
-    {
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/AndSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/AndSpecification.java
deleted file mode 100644
index 138ad00..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/AndSpecification.java
+++ /dev/null
@@ -1,56 +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.qi4j.api.query.grammar;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.Specifications;
-
-/**
- * AND Specification.
- */
-public class AndSpecification
-    extends BinarySpecification
-{
-
-    public AndSpecification( Iterable<Specification<Composite>> operands )
-    {
-        super( operands );
-    }
-
-    @Override
-    public boolean satisfiedBy( Composite item )
-    {
-        return Specifications.and( operands ).satisfiedBy( item );
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder( "(" );
-        String and = "";
-        for( Specification<Composite> operand : operands )
-        {
-            sb.append( and ).append( operand );
-            and = " and ";
-        }
-        return sb.append( ")" ).toString();
-    }
-
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/AssociationFunction.java b/core/api/src/main/java/org/qi4j/api/query/grammar/AssociationFunction.java
deleted file mode 100644
index ee423a0..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/AssociationFunction.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright 2007-2011 Rickard Öberg.
- * Copyright 2007-2010 Niclas Hedhman.
- *
- * Licensed 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
- * ied.
- *
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.qi4j.api.query.grammar;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Member;
-import java.lang.reflect.Proxy;
-import java.lang.reflect.Type;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.association.GenericAssociationInfo;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.api.query.QueryExpressionException;
-import org.qi4j.api.util.Classes;
-import org.qi4j.functional.Function;
-
-import static org.qi4j.api.util.Classes.typeOf;
-
-/**
- * Function to get Entity Associations
- */
-public class AssociationFunction<T>
-    implements Function<Composite, Association<T>>
-{
-    private final AssociationFunction<?> traversedAssociation;
-    private final ManyAssociationFunction<?> traversedManyAssociation;
-    private final NamedAssociationFunction<?> traversedNamedAssociation;
-    private final AccessibleObject accessor;
-
-    public AssociationFunction( AssociationFunction<?> traversedAssociation,
-                                ManyAssociationFunction<?> traversedManyAssociation,
-                                NamedAssociationFunction<?> traversedNamedAssociation,
-                                AccessibleObject accessor
-    )
-    {
-        this.traversedAssociation = traversedAssociation;
-        this.traversedManyAssociation = traversedManyAssociation;
-        this.traversedNamedAssociation = traversedNamedAssociation;
-        this.accessor = accessor;
-
-        Type returnType = typeOf( accessor );
-        if( !Association.class.isAssignableFrom( Classes.RAW_CLASS.map( returnType ) )
-            && !ManyAssociation.class.isAssignableFrom( Classes.RAW_CLASS.map( returnType ) )
-            && !NamedAssociation.class.isAssignableFrom( Classes.RAW_CLASS.map( returnType ) ) )
-        {
-            throw new QueryExpressionException( "Unsupported association type:" + returnType );
-        }
-        Type associationTypeAsType = GenericAssociationInfo.toAssociationType( returnType );
-        if( !( associationTypeAsType instanceof Class ) )
-        {
-            throw new QueryExpressionException( "Unsupported association type:" + associationTypeAsType );
-        }
-    }
-
-    public AssociationFunction<?> traversedAssociation()
-    {
-        return traversedAssociation;
-    }
-
-    public ManyAssociationFunction<?> traversedManyAssociation()
-    {
-        return traversedManyAssociation;
-    }
-
-    public NamedAssociationFunction<?> traversedNamedAssociation()
-    {
-        return traversedNamedAssociation;
-    }
-
-    public AccessibleObject accessor()
-    {
-        return accessor;
-    }
-
-    @Override
-    public Association<T> map( Composite entity )
-    {
-        try
-        {
-            Object target = entity;
-            if( traversedAssociation != null )
-            {
-                Association<?> association = traversedAssociation.map( entity );
-                if( association == null )
-                {
-                    return null;
-                }
-                target = association.get();
-            }
-            else if( traversedManyAssociation != null )
-            {
-                throw new IllegalArgumentException( "Cannot evaluate a ManyAssociation" );
-            }
-            else if( traversedNamedAssociation != null )
-            {
-                throw new IllegalArgumentException( "Cannot evaluate a NamedAssociation" );
-            }
-
-            if( target == null )
-            {
-                return null;
-            }
-
-            CompositeInstance handler = (CompositeInstance) Proxy.getInvocationHandler( target );
-            return ( (AssociationStateHolder) handler.state() ).associationFor( accessor );
-        }
-        catch( IllegalArgumentException e )
-        {
-            throw e;
-        }
-        catch( Throwable e )
-        {
-            throw new IllegalArgumentException( e );
-        }
-    }
-
-    @Override
-    public String toString()
-    {
-        if( traversedAssociation != null )
-        {
-            return traversedAssociation.toString() + "." + ( (Member) accessor ).getName();
-        }
-        else
-        {
-            return ( (Member) accessor ).getName();
-        }
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/AssociationNotNullSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/AssociationNotNullSpecification.java
deleted file mode 100644
index 64d6def..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/AssociationNotNullSpecification.java
+++ /dev/null
@@ -1,67 +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.qi4j.api.query.grammar;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.composite.Composite;
-
-/**
- * Association not null Specification.
- */
-public class AssociationNotNullSpecification<T>
-    extends ExpressionSpecification
-{
-    private AssociationFunction<T> association;
-
-    public AssociationNotNullSpecification( AssociationFunction<T> association )
-    {
-        this.association = association;
-    }
-
-    public AssociationFunction<T> association()
-    {
-        return association;
-    }
-
-    @Override
-    public boolean satisfiedBy( Composite item )
-    {
-        try
-        {
-            Association<T> assoc = association.map( item );
-
-            if( assoc == null )
-            {
-                return false;
-            }
-
-            return assoc.get() != null;
-        }
-        catch( IllegalArgumentException e )
-        {
-            return false;
-        }
-    }
-
-    @Override
-    public String toString()
-    {
-        return association.toString() + "is not null";
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/AssociationNullSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/AssociationNullSpecification.java
deleted file mode 100644
index 9f06b98..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/AssociationNullSpecification.java
+++ /dev/null
@@ -1,67 +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.qi4j.api.query.grammar;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.composite.Composite;
-
-/**
- * Association null Specification.
- */
-public class AssociationNullSpecification<T>
-    extends ExpressionSpecification
-{
-    private AssociationFunction<T> association;
-
-    public AssociationNullSpecification( AssociationFunction<T> association )
-    {
-        this.association = association;
-    }
-
-    public AssociationFunction<T> association()
-    {
-        return association;
-    }
-
-    @Override
-    public boolean satisfiedBy( Composite item )
-    {
-        try
-        {
-            Association<T> assoc = association.map( item );
-
-            if( assoc == null )
-            {
-                return true;
-            }
-
-            return assoc.get() == null;
-        }
-        catch( IllegalArgumentException e )
-        {
-            return true;
-        }
-    }
-
-    @Override
-    public String toString()
-    {
-        return association.toString() + "is null";
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/BinarySpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/BinarySpecification.java
deleted file mode 100644
index 07c5d99..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/BinarySpecification.java
+++ /dev/null
@@ -1,41 +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.qi4j.api.query.grammar;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.functional.Specification;
-
-/**
- * Base binary Specification, used for AND and OR Specifications..
- */
-public abstract class BinarySpecification
-    extends ExpressionSpecification
-{
-    protected final Iterable<Specification<Composite>> operands;
-
-    protected BinarySpecification( Iterable<Specification<Composite>> operands )
-    {
-        this.operands = operands;
-    }
-
-    public Iterable<Specification<Composite>> operands()
-    {
-        return operands;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/ComparisonSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/ComparisonSpecification.java
deleted file mode 100644
index f855054..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/ComparisonSpecification.java
+++ /dev/null
@@ -1,76 +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.qi4j.api.query.grammar;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.property.Property;
-
-/**
- * Base comparison Specification.
- */
-public abstract class ComparisonSpecification<T>
-    extends ExpressionSpecification
-{
-    protected final PropertyFunction<T> property;
-    protected final T value;
-
-    public ComparisonSpecification( PropertyFunction<T> property, T value )
-    {
-        this.property = property;
-        this.value = value;
-    }
-
-    public PropertyFunction<T> property()
-    {
-        return property;
-    }
-
-    @Override
-    public final boolean satisfiedBy( Composite item )
-    {
-        try
-        {
-            Property<T> prop = property.map( item );
-
-            if( prop == null )
-            {
-                return false;
-            }
-
-            T propValue = prop.get();
-            if( propValue == null )
-            {
-                return false;
-            }
-
-            return compare( propValue );
-        }
-        catch( IllegalArgumentException e )
-        {
-            return false;
-        }
-    }
-
-    protected abstract boolean compare( T value );
-
-    public T value()
-    {
-        return value;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/ContainsAllSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/ContainsAllSpecification.java
deleted file mode 100644
index 7ff3e1b..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/ContainsAllSpecification.java
+++ /dev/null
@@ -1,78 +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.qi4j.api.query.grammar;
-
-import java.util.Collection;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.functional.Iterables;
-
-/**
- * Contains All Specification.
- */
-public class ContainsAllSpecification<T>
-    extends ExpressionSpecification
-{
-    private PropertyFunction<? extends Collection<T>> collectionProperty;
-    private Iterable<T> valueCollection;
-
-    public ContainsAllSpecification( PropertyFunction<? extends Collection<T>> collectionProperty,
-                                     Iterable<T> valueCollection
-    )
-    {
-        this.collectionProperty = collectionProperty;
-        this.valueCollection = valueCollection;
-    }
-
-    public PropertyFunction<? extends Collection<T>> collectionProperty()
-    {
-        return collectionProperty;
-    }
-
-    public Iterable<T> containedValues()
-    {
-        return valueCollection;
-    }
-
-    @Override
-    public boolean satisfiedBy( Composite item )
-    {
-        Collection<T> collection = collectionProperty.map( item ).get();
-
-        if( collection == null )
-        {
-            return false;
-        }
-
-        for( T value : valueCollection )
-        {
-            if( !collection.contains( value ) )
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    @Override
-    public String toString()
-    {
-        return collectionProperty + " contains " + Iterables.toList( valueCollection );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/ContainsSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/ContainsSpecification.java
deleted file mode 100644
index ea049de..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/ContainsSpecification.java
+++ /dev/null
@@ -1,67 +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.qi4j.api.query.grammar;
-
-import java.util.Collection;
-import org.qi4j.api.composite.Composite;
-
-/**
- * Contains Specification.
- */
-public class ContainsSpecification<T>
-    extends ExpressionSpecification
-{
-    private PropertyFunction<? extends Collection<T>> collectionProperty;
-    private T value;
-
-    public ContainsSpecification( PropertyFunction<? extends Collection<T>> collectionProperty, T value )
-    {
-        this.collectionProperty = collectionProperty;
-        this.value = value;
-    }
-
-    public PropertyFunction<? extends Collection<T>> collectionProperty()
-    {
-        return collectionProperty;
-    }
-
-    public T value()
-    {
-        return value;
-    }
-
-    @Override
-    public boolean satisfiedBy( Composite item )
-    {
-        Collection<T> collection = collectionProperty.map( item ).get();
-
-        if( collection == null )
-        {
-            return false;
-        }
-
-        return collection.contains( value );
-    }
-
-    @Override
-    public String toString()
-    {
-        return collectionProperty + " contains " + value;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/EqSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/EqSpecification.java
deleted file mode 100644
index b4c1d90..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/EqSpecification.java
+++ /dev/null
@@ -1,43 +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.qi4j.api.query.grammar;
-
-/**
- * Equals Specification.
- */
-public class EqSpecification<T>
-    extends ComparisonSpecification<T>
-{
-    public EqSpecification( PropertyFunction<T> property, T value )
-    {
-        super( property, value );
-    }
-
-    @Override
-    protected boolean compare( T value )
-    {
-        return value.equals( this.value );
-    }
-
-    @Override
-    public String toString()
-    {
-        return property.toString() + "=" + value.toString();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/ExpressionSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/ExpressionSpecification.java
deleted file mode 100644
index 9886ca9..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/ExpressionSpecification.java
+++ /dev/null
@@ -1,60 +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.qi4j.api.query.grammar;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.functional.Specification;
-
-import static org.qi4j.functional.Iterables.append;
-import static org.qi4j.functional.Iterables.iterable;
-
-/**
- * Base expression Specification.
- */
-public abstract class ExpressionSpecification
-    implements Specification<Composite>
-{
-
-    @SuppressWarnings( "unchecked" )
-    public AndSpecification and( Specification<Composite> specification )
-    {
-        if( this instanceof AndSpecification )
-        {
-            return new AndSpecification( append( specification, ( (AndSpecification) this ).operands() ) );
-        }
-        else
-        {
-            return new AndSpecification( iterable( this, specification ) );
-        }
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public OrSpecification or( Specification<Composite> specification )
-    {
-        if( this instanceof OrSpecification )
-        {
-            return new OrSpecification( append( specification, ( (OrSpecification) this ).operands() ) );
-        }
-        else
-        {
-            return new OrSpecification( iterable( this, specification ) );
-        }
-    }
-
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/GeSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/GeSpecification.java
deleted file mode 100644
index 82e9e38..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/GeSpecification.java
+++ /dev/null
@@ -1,44 +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.qi4j.api.query.grammar;
-
-/**
- * Greater or equals Specification.
- */
-public class GeSpecification<T>
-    extends ComparisonSpecification<T>
-{
-    public GeSpecification( PropertyFunction<T> property, T value )
-    {
-        super( property, value );
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    protected boolean compare( T value )
-    {
-        return ( (Comparable) value ).compareTo( this.value ) >= 0;
-    }
-
-    @Override
-    public String toString()
-    {
-        return property.toString() + ">=" + value.toString();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/GtSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/GtSpecification.java
deleted file mode 100644
index 883120b..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/GtSpecification.java
+++ /dev/null
@@ -1,44 +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.qi4j.api.query.grammar;
-
-/**
- * Greater than Specification.
- */
-public class GtSpecification<T>
-    extends ComparisonSpecification<T>
-{
-    public GtSpecification( PropertyFunction<T> property, T value )
-    {
-        super( property, value );
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    protected boolean compare( T value )
-    {
-        return ( (Comparable) value ).compareTo( this.value ) > 0;
-    }
-
-    @Override
-    public String toString()
-    {
-        return property.toString() + ">" + value.toString();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/LeSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/LeSpecification.java
deleted file mode 100644
index 3715ffd..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/LeSpecification.java
+++ /dev/null
@@ -1,44 +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.qi4j.api.query.grammar;
-
-/**
- * Less or equals Specification.
- */
-public class LeSpecification<T>
-    extends ComparisonSpecification<T>
-{
-    public LeSpecification( PropertyFunction<T> property, T value )
-    {
-        super( property, value );
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    protected boolean compare( T value )
-    {
-        return ( (Comparable) value ).compareTo( this.value ) <= 0;
-    }
-
-    @Override
-    public String toString()
-    {
-        return property.toString() + "<=" + value.toString();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/LtSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/LtSpecification.java
deleted file mode 100644
index 6d3002a..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/LtSpecification.java
+++ /dev/null
@@ -1,44 +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.qi4j.api.query.grammar;
-
-/**
- * Lesser than Specification.
- */
-public class LtSpecification<T>
-    extends ComparisonSpecification<T>
-{
-    public LtSpecification( PropertyFunction<T> property, T value )
-    {
-        super( property, value );
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    protected boolean compare( T value )
-    {
-        return ( (Comparable) value ).compareTo( this.value ) < 0;
-    }
-
-    @Override
-    public String toString()
-    {
-        return property.toString() + "<" + value.toString();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/ManyAssociationContainsSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/ManyAssociationContainsSpecification.java
deleted file mode 100644
index d8a6b2e..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/ManyAssociationContainsSpecification.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2007-2011 Rickard Öberg.
- * Copyright 2007-2010 Niclas Hedhman.
- *
- * Licensed 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
- * ied.
- *
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.qi4j.api.query.grammar;
-
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.composite.Composite;
-
-/**
- * ManyAssociation Contains Specification.
- */
-public class ManyAssociationContainsSpecification<T>
-    extends ExpressionSpecification
-{
-    private final ManyAssociationFunction<T> manyAssociationFunction;
-    private final T value;
-
-    public ManyAssociationContainsSpecification( ManyAssociationFunction<T> manyAssociationFunction, T value )
-    {
-        this.manyAssociationFunction = manyAssociationFunction;
-        this.value = value;
-    }
-
-    public ManyAssociationFunction<T> manyAssociation()
-    {
-        return manyAssociationFunction;
-    }
-
-    public T value()
-    {
-        return value;
-    }
-
-    @Override
-    public boolean satisfiedBy( Composite item )
-    {
-        ManyAssociation<T> collection = manyAssociationFunction.map( item );
-        if( collection == null )
-        {
-            return false;
-        }
-        return collection.contains( value );
-    }
-
-    @Override
-    public String toString()
-    {
-        return manyAssociationFunction + " contains:" + value;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/ManyAssociationFunction.java b/core/api/src/main/java/org/qi4j/api/query/grammar/ManyAssociationFunction.java
deleted file mode 100644
index e91cdeb..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/ManyAssociationFunction.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2007-2011 Rickard Öberg.
- * Copyright 2007-2010 Niclas Hedhman.
- *
- * Licensed 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
- * ied.
- *
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.qi4j.api.query.grammar;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Member;
-import java.lang.reflect.Proxy;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.functional.Function;
-
-/**
- * Function to get Entity ManyAssociations.
- */
-public class ManyAssociationFunction<T>
-    implements Function<Composite, ManyAssociation<T>>
-{
-    private final AssociationFunction<?> traversedAssociation;
-    private final ManyAssociationFunction<?> traversedManyAssociation;
-    private final NamedAssociationFunction<?> traversedNamedAssociation;
-    private final AccessibleObject accessor;
-
-    public ManyAssociationFunction( AssociationFunction<?> traversedAssociation,
-                                    ManyAssociationFunction<?> traversedManyAssociation,
-                                    NamedAssociationFunction<?> traversedNamedAssociation,
-                                    AccessibleObject accessor
-    )
-    {
-        this.traversedAssociation = traversedAssociation;
-        this.traversedManyAssociation = traversedManyAssociation;
-        this.traversedNamedAssociation = traversedNamedAssociation;
-        this.accessor = accessor;
-    }
-
-    public AssociationFunction<?> traversedAssociation()
-    {
-        return traversedAssociation;
-    }
-
-    public ManyAssociationFunction<?> traversedManyAssociation()
-    {
-        return traversedManyAssociation;
-    }
-
-    public NamedAssociationFunction<?> traversedNamedAssociation()
-    {
-        return traversedNamedAssociation;
-    }
-
-    public AccessibleObject accessor()
-    {
-        return accessor;
-    }
-
-    @Override
-    public ManyAssociation<T> map( Composite entity )
-    {
-        try
-        {
-            Object target = entity;
-            if( traversedAssociation != null )
-            {
-                target = traversedAssociation.map( entity ).get();
-            }
-            if( traversedManyAssociation != null )
-            {
-                throw new IllegalArgumentException( "Cannot traverse ManyAssociations" );
-            }
-            if( traversedNamedAssociation != null )
-            {
-                throw new IllegalArgumentException( "Cannot traverse NamedAssociations" );
-            }
-
-            CompositeInstance handler = (CompositeInstance) Proxy.getInvocationHandler( target );
-            return ( (AssociationStateHolder) handler.state() ).manyAssociationFor( accessor );
-        }
-        catch( IllegalArgumentException e )
-        {
-            throw e;
-        }
-        catch( Throwable e )
-        {
-            throw new IllegalArgumentException( e );
-        }
-    }
-
-    @Override
-    public String toString()
-    {
-        if( traversedAssociation != null )
-        {
-            return traversedAssociation.toString() + "." + ( (Member) accessor ).getName();
-        }
-        else
-        {
-            return ( (Member) accessor ).getName();
-        }
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/MatchesSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/MatchesSpecification.java
deleted file mode 100644
index 6cde577..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/MatchesSpecification.java
+++ /dev/null
@@ -1,93 +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.qi4j.api.query.grammar;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.property.Property;
-
-/**
- * Regular expression match Specification.
- */
-public class MatchesSpecification
-    extends ExpressionSpecification
-{
-    private PropertyFunction<String> property;
-    private Object value;
-
-    public MatchesSpecification( PropertyFunction<String> property, String regexp )
-    {
-        this.property = property;
-        this.value = regexp;
-    }
-
-    public MatchesSpecification( PropertyFunction<String> property, Variable variable )
-    {
-        this.property = property;
-        this.value = variable;
-    }
-
-    public PropertyFunction<String> property()
-    {
-        return property;
-    }
-
-    public Object value()
-    {
-        return value;
-    }
-
-    public String regexp()
-    {
-        return ( String ) value;
-    }
-
-    @Override
-    public boolean satisfiedBy( Composite item )
-    {
-        Property<String> prop = property.map( item );
-
-        if( prop == null )
-        {
-            return false;
-        }
-
-        String val = prop.get();
-
-        if( val == null )
-        {
-            return false;
-        }
-
-        return val.matches( ( String ) value );
-    }
-
-    @Override
-    public String toString()
-    {
-        return new StringBuilder()
-            .append( "( " )
-            .append( property )
-            .append( " matches " )
-            .append( "\"" )
-            .append( value )
-            .append( "\"" )
-            .append( " )" )
-            .toString();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/NamedAssociationContainsNameSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/NamedAssociationContainsNameSpecification.java
deleted file mode 100644
index c20987e..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/NamedAssociationContainsNameSpecification.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2011-2012 Niclas Hedhman.
- * Copyright 2014 Paul Merlin.
- *
- * Licensed 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
- * ied.
- *
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.qi4j.api.query.grammar;
-
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.composite.Composite;
-
-/**
- * NamedAssociation Contains Specification.
- */
-public class NamedAssociationContainsNameSpecification<T>
-    extends ExpressionSpecification
-{
-    private final NamedAssociationFunction<T> namedAssociationFunction;
-    private final String name;
-
-    public NamedAssociationContainsNameSpecification( NamedAssociationFunction<T> namedAssociationFunction, String name )
-    {
-        this.namedAssociationFunction = namedAssociationFunction;
-        this.name = name;
-    }
-
-    public NamedAssociationFunction<T> namedAssociation()
-    {
-        return namedAssociationFunction;
-    }
-
-    public String name()
-    {
-        return name;
-    }
-
-    @Override
-    public boolean satisfiedBy( Composite item )
-    {
-        NamedAssociation<T> collection = namedAssociationFunction.map( item );
-        if( collection == null )
-        {
-            return false;
-        }
-        return collection.containsName( name );
-    }
-
-    @Override
-    public String toString()
-    {
-        return namedAssociationFunction + " contains name:" + name;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/NamedAssociationContainsSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/NamedAssociationContainsSpecification.java
deleted file mode 100644
index 22079aa..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/NamedAssociationContainsSpecification.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2011-2012 Niclas Hedhman.
- * Copyright 2014 Paul Merlin.
- *
- * Licensed 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
- * ied.
- *
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.qi4j.api.query.grammar;
-
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.composite.Composite;
-
-/**
- * NamedAssociation Contains Specification.
- */
-public class NamedAssociationContainsSpecification<T>
-    extends ExpressionSpecification
-{
-    private final NamedAssociationFunction<T> namedAssociationFunction;
-    private final T value;
-
-    public NamedAssociationContainsSpecification( NamedAssociationFunction<T> namedAssociationFunction, T value )
-    {
-        this.namedAssociationFunction = namedAssociationFunction;
-        this.value = value;
-    }
-
-    public NamedAssociationFunction<T> namedAssociation()
-    {
-        return namedAssociationFunction;
-    }
-
-    public T value()
-    {
-        return value;
-    }
-
-    @Override
-    public boolean satisfiedBy( Composite item )
-    {
-        NamedAssociation<T> collection = namedAssociationFunction.map( item );
-        if( collection == null )
-        {
-            return false;
-        }
-        return collection.nameOf( value ) != null;
-    }
-
-    @Override
-    public String toString()
-    {
-        return namedAssociationFunction + " contains:" + value;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/NamedAssociationFunction.java b/core/api/src/main/java/org/qi4j/api/query/grammar/NamedAssociationFunction.java
deleted file mode 100644
index 3f7b8e3..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/NamedAssociationFunction.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2011-2012 Niclas Hedhman.
- * Copyright 2014 Paul Merlin.
- *
- * Licensed 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
- * ied.
- *
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.qi4j.api.query.grammar;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Member;
-import java.lang.reflect.Proxy;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.functional.Function;
-
-/**
- * Function to get Entity NamedAssociations.
- */
-public class NamedAssociationFunction<T>
-    implements Function<Composite, NamedAssociation<T>>
-{
-    private final AssociationFunction<?> traversedAssociation;
-    private final ManyAssociationFunction<?> traversedManyAssociation;
-    private final NamedAssociationFunction<?> traversedNamedAssociation;
-    private final AccessibleObject accessor;
-
-    public NamedAssociationFunction( AssociationFunction<?> traversedAssociation,
-                                     ManyAssociationFunction<?> traversedManyAssociation,
-                                     NamedAssociationFunction<?> traversedNamedAssociation,
-                                     AccessibleObject accessor
-    )
-    {
-        this.traversedAssociation = traversedAssociation;
-        this.traversedManyAssociation = traversedManyAssociation;
-        this.traversedNamedAssociation = traversedNamedAssociation;
-        this.accessor = accessor;
-    }
-
-    public AssociationFunction<?> traversedAssociation()
-    {
-        return traversedAssociation;
-    }
-
-    public ManyAssociationFunction<?> traversedManyAssociation()
-    {
-        return traversedManyAssociation;
-    }
-
-    public NamedAssociationFunction<?> traversedNamedAssociation()
-    {
-        return traversedNamedAssociation;
-    }
-
-    public AccessibleObject accessor()
-    {
-        return accessor;
-    }
-
-    @Override
-    public NamedAssociation<T> map( Composite entity )
-    {
-        try
-        {
-            Object target = entity;
-            if( traversedAssociation != null )
-            {
-                target = traversedAssociation.map( entity ).get();
-            }
-            if( traversedManyAssociation != null )
-            {
-                throw new IllegalArgumentException( "Cannot traverse ManyAssociations" );
-            }
-            if( traversedNamedAssociation != null )
-            {
-                throw new IllegalArgumentException( "Cannot traverse NamedAssociations" );
-            }
-
-            CompositeInstance handler = (CompositeInstance) Proxy.getInvocationHandler( target );
-            return ( (AssociationStateHolder) handler.state() ).namedAssociationFor( accessor );
-        }
-        catch( IllegalArgumentException e )
-        {
-            throw e;
-        }
-        catch( Throwable e )
-        {
-            throw new IllegalArgumentException( e );
-        }
-    }
-
-    @Override
-    public String toString()
-    {
-        if( traversedAssociation != null )
-        {
-            return traversedAssociation.toString() + "." + ( (Member) accessor ).getName();
-        }
-        else
-        {
-            return ( (Member) accessor ).getName();
-        }
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/NeSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/NeSpecification.java
deleted file mode 100644
index e864184..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/NeSpecification.java
+++ /dev/null
@@ -1,43 +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.qi4j.api.query.grammar;
-
-/**
- * Not equals Specification.
- */
-public class NeSpecification<T>
-    extends ComparisonSpecification<T>
-{
-    public NeSpecification( PropertyFunction<T> property, T value )
-    {
-        super( property, value );
-    }
-
-    @Override
-    protected boolean compare( T value )
-    {
-        return !value.equals( this.value );
-    }
-
-    @Override
-    public String toString()
-    {
-        return property.toString() + "!=" + value.toString();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/NotSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/NotSpecification.java
deleted file mode 100644
index a85500d..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/NotSpecification.java
+++ /dev/null
@@ -1,53 +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.qi4j.api.query.grammar;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.Specifications;
-
-/**
- * NOT Specification.
- */
-public class NotSpecification implements Specification<Composite>
-{
-    private Specification<Composite> operand;
-
-    public NotSpecification( Specification<Composite> operand )
-    {
-        this.operand = operand;
-    }
-
-    public Specification<Composite> operand()
-    {
-        return operand;
-    }
-
-    @Override
-    public boolean satisfiedBy( Composite item )
-    {
-        return Specifications.not( operand ).satisfiedBy( item );
-    }
-
-    @Override
-    public String toString()
-    {
-        return "!" + operand.toString();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/OrSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/OrSpecification.java
deleted file mode 100644
index ac775d6..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/OrSpecification.java
+++ /dev/null
@@ -1,56 +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.qi4j.api.query.grammar;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.Specifications;
-
-/**
- * OR Specification.
- */
-public class OrSpecification
-    extends BinarySpecification
-{
-
-    public OrSpecification( Iterable<Specification<Composite>> operands )
-    {
-        super( operands );
-    }
-
-    @Override
-    public boolean satisfiedBy( Composite item )
-    {
-        return Specifications.or( operands ).satisfiedBy( item );
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder( "(" );
-        String or = "";
-        for( Specification<Composite> operand : operands )
-        {
-            sb.append( or ).append( operand );
-            or = " or ";
-        }
-        return sb.append( ")" ).toString();
-    }
-
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/OrderBy.java b/core/api/src/main/java/org/qi4j/api/query/grammar/OrderBy.java
deleted file mode 100644
index 097171b..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/OrderBy.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2007 Niclas Hedhman.
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.api.query.grammar;
-
-/**
- * Query sorting segment.
- */
-public class OrderBy
-{
-    /**
-     * Order direction.
-     */
-    public enum Order
-    {
-        ASCENDING, DESCENDING
-    }
-
-    /**
-     * Order.
-     */
-    private final PropertyFunction<?> propertyReference;
-    /**
-     * Direction.
-     */
-    private final Order order;
-
-    /**
-     * Constructor.
-     *
-     * @param propertyReference property that determines the order; cannot be null
-     * @param order             direction
-     *
-     * @throws IllegalArgumentException - If property is null
-     */
-    public OrderBy( final PropertyFunction<?> propertyReference,
-                    final Order order
-    )
-    {
-        if( propertyReference == null )
-        {
-            throw new IllegalArgumentException( "Ordering property cannot be null" );
-        }
-        this.propertyReference = propertyReference;
-        this.order = order;
-    }
-
-    /**
-     * Getter.
-     *
-     * @return property; cannot be null
-     */
-    public PropertyFunction<?> property()
-    {
-        return propertyReference;
-    }
-
-    /**
-     * Getter.
-     *
-     * @return direction; cannot be null
-     */
-    public Order order()
-    {
-        return order;
-    }
-
-    @Override
-    public String toString()
-    {
-        return new StringBuilder()
-            .append( propertyReference )
-            .append( " " )
-            .append( order )
-            .toString();
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/PropertyFunction.java b/core/api/src/main/java/org/qi4j/api/query/grammar/PropertyFunction.java
deleted file mode 100644
index b3f4c37..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/PropertyFunction.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright 2007-2011 Rickard Öberg.
- * Copyright 2007-2010 Niclas Hedhman.
- *
- * Licensed 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
- * ied.
- *
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.qi4j.api.query.grammar;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Member;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Proxy;
-import java.lang.reflect.Type;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.api.property.GenericPropertyInfo;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.NotQueryableException;
-import org.qi4j.api.query.QueryExpressionException;
-import org.qi4j.api.util.Classes;
-import org.qi4j.functional.Function;
-
-import static org.qi4j.api.util.Classes.typeOf;
-
-/**
- * Function to get Entity Properties.
- */
-public class PropertyFunction<T>
-    implements Function<Composite, Property<T>>
-{
-    private final PropertyFunction<?> traversedProperty;
-    private final AssociationFunction<?> traversedAssociation;
-    private final ManyAssociationFunction<?> traversedManyAssociation;
-    private final NamedAssociationFunction<?> traversedNamedAssociation;
-    private final AccessibleObject accessor;
-
-    public PropertyFunction( PropertyFunction<?> traversedProperty,
-                             AssociationFunction<?> traversedAssociation,
-                             ManyAssociationFunction<?> traversedManyAssociation,
-                             NamedAssociationFunction<?> traversedNamedAssociation,
-                             AccessibleObject accessor
-    )
-    {
-        this.traversedProperty = traversedProperty;
-        this.traversedAssociation = traversedAssociation;
-        this.traversedManyAssociation = traversedManyAssociation;
-        this.traversedNamedAssociation = traversedNamedAssociation;
-        this.accessor = accessor;
-
-        // Verify that the property accessor is not marked as non queryable
-        NotQueryableException.throwIfNotQueryable( accessor );
-        // Verify that the property type itself (value composites) is not marked as non queryable
-
-        Type returnType = typeOf( accessor );
-        if( !Property.class.isAssignableFrom( Classes.RAW_CLASS.map( returnType ) ) )
-        {
-            throw new QueryExpressionException( "Not a property type:" + returnType );
-        }
-        Type propertyTypeAsType = GenericPropertyInfo.toPropertyType( returnType );
-        if( propertyTypeAsType instanceof ParameterizedType )
-        {
-            propertyTypeAsType = ( (ParameterizedType) propertyTypeAsType ).getRawType();
-        }
-
-        if( !( propertyTypeAsType instanceof Class ) )
-        {
-            throw new QueryExpressionException( "Unsupported property type:" + propertyTypeAsType );
-        }
-        @SuppressWarnings( "unchecked" )
-        Class<T> type = (Class<T>) propertyTypeAsType;
-        NotQueryableException.throwIfNotQueryable( type );
-    }
-
-    public PropertyFunction<?> traversedProperty()
-    {
-        return traversedProperty;
-    }
-
-    public AssociationFunction<?> traversedAssociation()
-    {
-        return traversedAssociation;
-    }
-
-    public ManyAssociationFunction<?> traversedManyAssociation()
-    {
-        return traversedManyAssociation;
-    }
-
-    public NamedAssociationFunction<?> traversedNamedAssociation()
-    {
-        return traversedNamedAssociation;
-    }
-
-    public AccessibleObject accessor()
-    {
-        return accessor;
-    }
-
-    @Override
-    public Property<T> map( Composite entity )
-    {
-        try
-        {
-            Object target = entity;
-            if( traversedProperty != null )
-            {
-                Property<?> property = traversedProperty.map( entity );
-                if( property == null )
-                {
-                    return null;
-                }
-                target = property.get();
-            }
-            else if( traversedAssociation != null )
-            {
-                Association<?> association = traversedAssociation.map( entity );
-                if( association == null )
-                {
-                    return null;
-                }
-                target = association.get();
-            }
-            else if( traversedManyAssociation != null )
-            {
-                throw new IllegalArgumentException( "Cannot evaluate a ManyAssociation" );
-            }
-            else if( traversedNamedAssociation != null )
-            {
-                throw new IllegalArgumentException( "Cannot evaluate a NamedAssociation" );
-            }
-
-            if( target == null )
-            {
-                return null;
-            }
-
-            CompositeInstance handler = (CompositeInstance) Proxy.getInvocationHandler( target );
-            return handler.state().propertyFor( accessor );
-        }
-        catch( IllegalArgumentException e )
-        {
-            throw e;
-        }
-        catch( Throwable e )
-        {
-            throw new IllegalArgumentException( e );
-        }
-    }
-
-    @Override
-    public String toString()
-    {
-        if( traversedProperty != null )
-        {
-            return traversedProperty.toString() + "." + ( (Member) accessor ).getName();
-        }
-        else if( traversedAssociation != null )
-        {
-            return traversedAssociation.toString() + "." + ( (Member) accessor ).getName();
-        }
-        else
-        {
-            return ( (Member) accessor ).getName();
-        }
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/PropertyNotNullSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/PropertyNotNullSpecification.java
deleted file mode 100644
index c73afa8..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/PropertyNotNullSpecification.java
+++ /dev/null
@@ -1,60 +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.qi4j.api.query.grammar;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.property.Property;
-
-/**
- * Property not null Specification.
- */
-public class PropertyNotNullSpecification<T>
-    extends ExpressionSpecification
-{
-    private PropertyFunction<T> property;
-
-    public PropertyNotNullSpecification( PropertyFunction<T> property )
-    {
-        this.property = property;
-    }
-
-    public PropertyFunction<T> property()
-    {
-        return property;
-    }
-
-    @Override
-    public boolean satisfiedBy( Composite item )
-    {
-        Property<T> prop = property.map( item );
-
-        if( prop == null )
-        {
-            return false;
-        }
-
-        return prop.get() != null;
-    }
-
-    @Override
-    public String toString()
-    {
-        return property.toString() + "is not null";
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/PropertyNullSpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/PropertyNullSpecification.java
deleted file mode 100644
index 7f7908f..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/PropertyNullSpecification.java
+++ /dev/null
@@ -1,60 +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.qi4j.api.query.grammar;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.property.Property;
-
-/**
- * Property null Specification.
- */
-public class PropertyNullSpecification<T>
-    extends ExpressionSpecification
-{
-    private PropertyFunction<T> property;
-
-    public PropertyNullSpecification( PropertyFunction<T> property )
-    {
-        this.property = property;
-    }
-
-    public PropertyFunction<T> property()
-    {
-        return property;
-    }
-
-    @Override
-    public boolean satisfiedBy( Composite item )
-    {
-        Property<T> prop = property.map( item );
-
-        if( prop == null )
-        {
-            return true;
-        }
-
-        return prop.get() == null;
-    }
-
-    @Override
-    public String toString()
-    {
-        return property.toString() + "is null";
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/PropertyReference.java b/core/api/src/main/java/org/qi4j/api/query/grammar/PropertyReference.java
deleted file mode 100644
index 7b865de..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/PropertyReference.java
+++ /dev/null
@@ -1,31 +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.qi4j.api.query.grammar;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.property.Property;
-import org.qi4j.functional.Function;
-
-/**
- * Property Reference.
- */
-public interface PropertyReference
-{
-    <T> Function<Composite, Property<T>> reference();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/QuerySpecification.java b/core/api/src/main/java/org/qi4j/api/query/grammar/QuerySpecification.java
deleted file mode 100644
index 3c033d7..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/QuerySpecification.java
+++ /dev/null
@@ -1,71 +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.qi4j.api.query.grammar;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.functional.Specification;
-
-/**
- * This should be used when doing native queries, such as SQL, SPARQL or similar. EntityFinders can choose
- * what type of query languages they can understand by checking the language property of a QuerySpecification
- */
-public class QuerySpecification
-    implements Specification<Composite>
-{
-    public static boolean isQueryLanguage( String language, Specification<Composite> specification )
-    {
-        if( !( specification instanceof QuerySpecification ) )
-        {
-            return false;
-        }
-
-        return ( (QuerySpecification) specification ).language().equals( language );
-    }
-
-    private String language;
-    private String query;
-
-    public QuerySpecification( String language, String query )
-    {
-        this.language = language;
-        this.query = query;
-    }
-
-    public String language()
-    {
-        return language;
-    }
-
-    public String query()
-    {
-        return query;
-    }
-
-    @Override
-    public boolean satisfiedBy( Composite item )
-    {
-        return false;
-    }
-
-    @Override
-    public String toString()
-    {
-        return language + ":" + query;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/Variable.java b/core/api/src/main/java/org/qi4j/api/query/grammar/Variable.java
deleted file mode 100644
index 205347b..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/Variable.java
+++ /dev/null
@@ -1,43 +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.qi4j.api.query.grammar;
-
-/**
- * Query Variable name.
- */
-public class Variable
-{
-    private String name;
-
-    public Variable( String name )
-    {
-        this.name = name;
-    }
-
-    public String variableName()
-    {
-        return name;
-    }
-
-    @Override
-    public String toString()
-    {
-        return name;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/query/grammar/package.html b/core/api/src/main/java/org/qi4j/api/query/grammar/package.html
deleted file mode 100644
index e0b80f6..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/grammar/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Query Grammar.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/query/package.html b/core/api/src/main/java/org/qi4j/api/query/package.html
deleted file mode 100644
index 27e4455..0000000
--- a/core/api/src/main/java/org/qi4j/api/query/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Query API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/service/Availability.java b/core/api/src/main/java/org/qi4j/api/service/Availability.java
deleted file mode 100644
index 3905a1d..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/Availability.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service;
-
-/**
- * Services can implement this interface in order to allow Zest to ask
- * it whether it is currently available for use or not. This is accessed
- * by clients through the ServiceReference of the service. Services that do not
- * implement this are always considered to be available.
- */
-public interface Availability
-{
-    /**
-     * Implementations should return true if the underlying service is currently available for use.
-     *
-     * Reasons why a service might not be available is either if it has been configured not to be (see
-     * the Enabled interface), or if an underlying resource is currently unavailable.
-     *
-     * @return true if the service is available, false otherwise.
-     */
-    boolean isAvailable();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/DuplicateServiceIdentityException.java b/core/api/src/main/java/org/qi4j/api/service/DuplicateServiceIdentityException.java
deleted file mode 100644
index fffa42a..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/DuplicateServiceIdentityException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service;
-
-import org.qi4j.api.common.InvalidApplicationException;
-
-/**
- * Thrown when a duplicate service identity is detected.
- */
-public class DuplicateServiceIdentityException
-    extends InvalidApplicationException
-{
-    public DuplicateServiceIdentityException( String string )
-    {
-        super( string );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/IdentityDescriptor.java b/core/api/src/main/java/org/qi4j/api/service/IdentityDescriptor.java
deleted file mode 100644
index 13e0ee5..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/IdentityDescriptor.java
+++ /dev/null
@@ -1,27 +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.qi4j.api.service;
-
-/**
- * Identity Descriptor.
- */
-public interface IdentityDescriptor
-{
-    String identity();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/ImportedServiceDescriptor.java b/core/api/src/main/java/org/qi4j/api/service/ImportedServiceDescriptor.java
deleted file mode 100644
index 6590049..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/ImportedServiceDescriptor.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service;
-
-import org.qi4j.api.composite.ModelDescriptor;
-
-/**
- * {@code ServiceDescriptor} provides meta information of a service.
- */
-public interface ImportedServiceDescriptor
-    extends ModelDescriptor, IdentityDescriptor
-{
-    Class<? extends ServiceImporter> serviceImporter();
-
-    Class<?> type();
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/service/NoSuchServiceException.java b/core/api/src/main/java/org/qi4j/api/service/NoSuchServiceException.java
deleted file mode 100644
index 9ce08ae..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/NoSuchServiceException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service;
-
-import org.qi4j.api.composite.NoSuchCompositeException;
-
-/**
- * Thrown when no visible service of the requested type is found.
- */
-public class NoSuchServiceException extends NoSuchCompositeException
-{
-    public NoSuchServiceException( String typeName, String moduleName )
-    {
-        super( "ServiceComposite", typeName, moduleName );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/ServiceActivation.java b/core/api/src/main/java/org/qi4j/api/service/ServiceActivation.java
deleted file mode 100644
index 87a7cad..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/ServiceActivation.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.api.service;
-
-import org.qi4j.api.activation.Activators;
-
-/**
- * Convenience interface for simple Service Activation.
- *
- * Let your ServiceComposite extends ServiceActivation and implement it in one of its Mixins.
- * A corresponding Activator is automatically registered.
- */
-@Activators( ServiceActivation.ServiceActivator.class )
-public interface ServiceActivation
-{
-
-    /**
-     * Called after ServiceComposite Activation.
-     */
-    void activateService()
-        throws Exception;
-
-    /**
-     * Called before ServiceComposite Passivation.
-     */
-    void passivateService()
-        throws Exception;
-
-    /**
-     * Service Activator.
-     */
-    class ServiceActivator
-        extends ServiceActivatorAdapter<ServiceActivation>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<ServiceActivation> activated )
-            throws Exception
-        {
-            activated.get().activateService();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<ServiceActivation> passivating )
-            throws Exception
-        {
-            passivating.get().passivateService();
-        }
-
-    }
-
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/ServiceActivatorAdapter.java b/core/api/src/main/java/org/qi4j/api/service/ServiceActivatorAdapter.java
deleted file mode 100644
index 966226e..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/ServiceActivatorAdapter.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.api.service;
-
-import org.qi4j.api.activation.Activator;
-
-/**
- * Adapter for Service Activator.
- *
- * @param <ServiceType> Type of the service.
- */
-public class ServiceActivatorAdapter<ServiceType>
-    implements Activator<ServiceReference<ServiceType>>
-{
-    /**
-     * Called before Service activation.
-     * @param activating Activating Service
-     */
-    @Override
-    public void beforeActivation( ServiceReference<ServiceType> activating )
-        throws Exception
-    {
-    }
-
-    /**
-     * Called after Service activation.
-     * @param activated Activated Service
-     */
-    @Override
-    public void afterActivation( ServiceReference<ServiceType> activated )
-        throws Exception
-    {
-    }
-
-    /**
-     * Called before Service passivation.
-     * @param passivating Passivating Service
-     */
-    @Override
-    public void beforePassivation( ServiceReference<ServiceType> passivating )
-        throws Exception
-    {
-    }
-
-    /**
-     * Called after Service passivation.
-     * @param passivated Passivated Service
-     */
-    @Override
-    public void afterPassivation( ServiceReference<ServiceType> passivated )
-        throws Exception
-    {
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/ServiceComposite.java b/core/api/src/main/java/org/qi4j/api/service/ServiceComposite.java
deleted file mode 100644
index f27b994..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/ServiceComposite.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.Identity;
-
-/**
- * All Composites being used to implement Services
- * must extend this interface.
- */
-public interface ServiceComposite
-    extends Identity, Composite
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/ServiceDescriptor.java b/core/api/src/main/java/org/qi4j/api/service/ServiceDescriptor.java
deleted file mode 100644
index d6a55ee..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/ServiceDescriptor.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service;
-
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.composite.StatefulCompositeDescriptor;
-
-/**
- * {@code ServiceDescriptor} provides meta informations of a service.
- */
-public interface ServiceDescriptor
-    extends CompositeDescriptor, IdentityDescriptor, StatefulCompositeDescriptor
-{
-    boolean isInstantiateOnStartup();
-
-    <T> Class<T> configurationType();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/ServiceFinder.java b/core/api/src/main/java/org/qi4j/api/service/ServiceFinder.java
deleted file mode 100644
index 3ffb213..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/ServiceFinder.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service;
-
-import java.lang.reflect.Type;
-
-/**
- * Interface used to query for ServiceReferences.
- * <p>
- * Each ServiceFinder is
- * obtained from a specific Module, and the lookup rules are the following:
- * </p>
- * <ol>
- * <li>First look in the same Module as the ServiceFinder</li>
- * <li>Then look in the same Layer as the ServiceFinder. Any Services declared
- * with Visibility Layer and Application should be included</li>
- * <li>Then look in the used Layers. Any Services declared with Visibility Application
- * should be included</li>
- * </ol>
- * <p>
- * Both native Zest services and imported services are considered, with preference to native services.
- * </p>
- */
-public interface ServiceFinder
-{
-    /**
-     * Find a ServiceReference that implements the given type.
-     *
-     * @param serviceType the type that the Service must implement
-     *
-     * @return a ServiceReference if one is found
-     *
-     * @throws NoSuchServiceException if no service of serviceType is found
-     */
-    <T> ServiceReference<T> findService( Class<T> serviceType )
-        throws NoSuchServiceException;
-
-    /**
-     * Find a ServiceReference that implements the given type.
-     *
-     * @param serviceType the type that the Service must implement
-     *
-     * @return a ServiceReference if one is found
-     *
-     * @throws NoSuchServiceException if no service of serviceType is found
-     */
-    <T> ServiceReference<T> findService( Type serviceType )
-        throws NoSuchServiceException;
-
-    /**
-     * Find ServiceReferences that implements the given type.
-     * <p>
-     * The order of the references is such that Services more local to the querying
-     * Module is earlier in the list.
-     * </p>
-     *
-     * @param serviceType the type that the Services must implement
-     *
-     * @return an iterable of ServiceReferences for the given type. It is empty if none exist
-     */
-    <T> Iterable<ServiceReference<T>> findServices( Class<T> serviceType );
-
-    /**
-     * Find ServiceReferences that implements the given type.
-     * <p>
-     * The order of the references is such that Services more local to the querying
-     * Module is earlier in the list.
-     * </p>
-     *
-     * @param serviceType the type that the Services must implement
-     *
-     * @return an iterable of ServiceReferences for the given type. It is empty if none exist
-     */
-    <T> Iterable<ServiceReference<T>> findServices( Type serviceType );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/ServiceImporter.java b/core/api/src/main/java/org/qi4j/api/service/ServiceImporter.java
deleted file mode 100644
index ee3d6e5..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/ServiceImporter.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service;
-
-/**
- * Import a service from some external source.
- */
-public interface ServiceImporter<T>
-{
-    /**
-     * Imports an instance of the service type described in the service descriptor.
-     *
-     * @param serviceDescriptor The service descriptor.
-     *
-     * @return The imported service instance.
-     *
-     * @throws ServiceImporterException if import failed.
-     */
-    T importService( ImportedServiceDescriptor serviceDescriptor )
-        throws ServiceImporterException;
-
-    /**
-     * Ask if the service is available or not.
-     *
-     * @param instance the instance to be checked
-     *
-     * @return true if the service is available, false if not
-     */
-    boolean isAvailable( T instance );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/ServiceImporterException.java b/core/api/src/main/java/org/qi4j/api/service/ServiceImporterException.java
deleted file mode 100644
index c8c8fc7..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/ServiceImporterException.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service;
-
-/**
- * If a ServiceImporter could not import a service
- * instance it must throw this exception.
- */
-public class ServiceImporterException
-    extends RuntimeException
-{
-    public ServiceImporterException()
-    {
-    }
-
-    public ServiceImporterException( String string )
-    {
-        super( string );
-    }
-
-    public ServiceImporterException( String string, Throwable throwable )
-    {
-        super( string, throwable );
-    }
-
-    public ServiceImporterException( Throwable throwable )
-    {
-        super( throwable );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/ServiceReference.java b/core/api/src/main/java/org/qi4j/api/service/ServiceReference.java
deleted file mode 100644
index 7c616c2..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/ServiceReference.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service;
-
-import org.qi4j.api.activation.ActivationEventListenerRegistration;
-import org.qi4j.api.structure.MetaInfoHolder;
-import org.qi4j.api.type.HasTypes;
-
-/**
- * From a ServiceReference you can access and modify metadata about a service.
- * You can also access the actual service through get(), that can then be invoked.
- */
-public interface ServiceReference<T>
-    extends HasTypes, ActivationEventListenerRegistration, MetaInfoHolder
-{
-    /**
-     * @return the service's identity
-     */
-    String identity();
-
-    /**
-     * @return the actual service
-     */
-    T get();
-
-    /**
-     * @return TRUE if the service is active, otherwise return FALSE
-     */
-    boolean isActive();
-
-    /**
-     * @return TRUE if the service is available, otherwise return FALSE
-     */
-    boolean isAvailable();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/ServiceUnavailableException.java b/core/api/src/main/java/org/qi4j/api/service/ServiceUnavailableException.java
deleted file mode 100644
index 465c945..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/ServiceUnavailableException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.api.service;
-
-/**
- * Thrown when no available service is found.
- */
-public class ServiceUnavailableException
-    extends RuntimeException
-{
-    public ServiceUnavailableException( String message )
-    {
-        super( message );
-    }
-
-    public ServiceUnavailableException( String message, Throwable cause )
-    {
-        super( message, cause );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/importer/InstanceImporter.java b/core/api/src/main/java/org/qi4j/api/service/importer/InstanceImporter.java
deleted file mode 100644
index 38901fb..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/importer/InstanceImporter.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service.importer;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.service.ServiceImporterException;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Layer;
-import org.qi4j.api.structure.MetaInfoHolder;
-import org.qi4j.api.structure.Module;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.map;
-import static org.qi4j.functional.Specifications.notNull;
-
-/**
- * Return a predefined service instance that was provided as meta-info. Search for meta-info in the following order:
- * the service itself, the module of the service, the layer of the service, the whole application.
- */
-public final class InstanceImporter<T>
-    implements ServiceImporter<T>
-{
-    @Structure
-    private Application application;
-
-    @Structure
-    private Layer layer;
-
-    @Structure
-    private Module module;
-
-    @Override
-    public T importService( final ImportedServiceDescriptor serviceDescriptor )
-        throws ServiceImporterException
-    {
-        T instance = null;
-        Iterable<MetaInfoHolder> holders = Iterables.iterable( serviceDescriptor, module, layer, application );
-        for( final MetaInfoHolder metaInfoHolder : holders )
-        {
-            Function<Class<?>, T> metaFinder = new Function<Class<?>, T>()
-            {
-                @Override
-                @SuppressWarnings( "unchecked" )
-                public T map( Class<?> type )
-                {
-                    return (T) metaInfoHolder.metaInfo( type );
-                }
-            };
-            instance = first( filter( notNull(), map( metaFinder, serviceDescriptor.types() ) ) );
-            if( instance != null )
-            {
-                break;
-            }
-        }
-        return instance;
-    }
-
-    @Override
-    public boolean isAvailable( T instance )
-    {
-        return true;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/importer/NewObjectImporter.java b/core/api/src/main/java/org/qi4j/api/service/importer/NewObjectImporter.java
deleted file mode 100644
index d29b1ce..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/importer/NewObjectImporter.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service.importer;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.object.ObjectFactory;
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.service.ServiceImporterException;
-import org.qi4j.functional.Iterables;
-
-/**
- * Import Services using a new registered Object instance.
- */
-public final class NewObjectImporter<T>
-    implements ServiceImporter<T>
-{
-    @Structure
-    private ObjectFactory obf;
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public T importService( ImportedServiceDescriptor serviceDescriptor )
-        throws ServiceImporterException
-    {
-        return obf.newObject( (Class<T>) Iterables.first( serviceDescriptor.types() ) );
-    }
-
-    @Override
-    public boolean isAvailable( T instance )
-    {
-        return true;
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/service/importer/ServiceInstanceImporter.java b/core/api/src/main/java/org/qi4j/api/service/importer/ServiceInstanceImporter.java
deleted file mode 100644
index 7910228..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/importer/ServiceInstanceImporter.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service.importer;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceFinder;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.service.ServiceImporterException;
-import org.qi4j.api.service.ServiceReference;
-
-/**
- * Use a registered service that implements ServiceImporter to do the actual
- * import. The service id of the service that this importer should delegate to must
- * be set as meta-info on this service. Example:
- * <pre><code>
- * module.services(MyServiceImporterService.class).identifiedBy("someid");
- * module.importedServices(OtherService.class).importedBy(ServiceInstanceImporter.class).setMetaInfo("someid");
- * </code></pre>
- */
-public class ServiceInstanceImporter<T>
-    implements ServiceImporter<T>
-{
-    @Structure
-    ServiceFinder finder;
-
-    ServiceImporter<T> service;
-
-    String serviceId;
-
-    @Override
-    public T importService( ImportedServiceDescriptor importedServiceDescriptor )
-        throws ServiceImporterException
-    {
-        serviceId = importedServiceDescriptor.metaInfo( String.class );
-
-        return serviceImporter().importService( importedServiceDescriptor );
-    }
-
-    @Override
-    public boolean isAvailable( T instance )
-    {
-        return serviceImporter().isAvailable( instance );
-    }
-
-    @SuppressWarnings( {"raw", "unchecked"} )
-    private ServiceImporter<T> serviceImporter()
-    {
-        if( service == null )
-        {
-            for( ServiceReference<ServiceImporter> reference : finder.<ServiceImporter>findServices( ServiceImporter.class ) )
-            {
-                if( reference.identity().equals( serviceId ) )
-                {
-                    service = reference.get();
-                    break;
-                }
-            }
-        }
-
-        if( service == null )
-        {
-            throw new ServiceImporterException( "No service importer with id '" + serviceId + "' was found" );
-        }
-
-        return service;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/importer/ServiceSelectorImporter.java b/core/api/src/main/java/org/qi4j/api/service/importer/ServiceSelectorImporter.java
deleted file mode 100644
index ad3c757..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/importer/ServiceSelectorImporter.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service.importer;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.service.Availability;
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceFinder;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.service.ServiceImporterException;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.service.qualifier.ServiceQualifier;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-
-/**
- * If several services are available with a given type, and you want to constrain
- * the current module to use a specific one, then use this importer. Specify a
- * Specification&lt;ServiceReference&lt;T&gt;&gt; criteria as meta-info for the service, which will be applied
- * to the list of available services, and the first match will be chosen.
- *
- * This importer will avoid selecting itself, as could be possible if the ServiceQualifier.first()
- * filter is used.
- */
-public final class ServiceSelectorImporter<T>
-    implements ServiceImporter<T>
-{
-    @Structure
-    private ServiceFinder locator;
-
-    @Override
-    @SuppressWarnings( { "raw", "unchecked" } )
-    public T importService( ImportedServiceDescriptor serviceDescriptor )
-        throws ServiceImporterException
-    {
-        Specification<ServiceReference<?>> selector = serviceDescriptor.metaInfo( Specification.class );
-        Class serviceType = Iterables.first( serviceDescriptor.types() );
-        Iterable<ServiceReference<T>> services = locator.findServices( serviceType );
-        List<ServiceReference<T>> filteredServices = new ArrayList<>();
-        for( ServiceReference<T> service : services )
-        {
-            Specification selector1 = service.metaInfo( Specification.class );
-            if( selector1 != null && selector1 == selector )
-            {
-                continue;
-            }
-
-            filteredServices.add( service );
-        }
-        T service = ServiceQualifier.firstService( selector, filteredServices );
-        if( service == null )
-        {
-            throw new ServiceImporterException( "Could not find any service to import that matches the given specification for " + serviceDescriptor
-                .identity() );
-        }
-        return service;
-    }
-
-    @Override
-    public boolean isAvailable( T instance )
-    {
-        return !( instance instanceof Availability ) || ( (Availability) instance ).isAvailable();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/importer/package.html b/core/api/src/main/java/org/qi4j/api/service/importer/package.html
deleted file mode 100644
index d960b3d..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/importer/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Service Importers.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/service/package.html b/core/api/src/main/java/org/qi4j/api/service/package.html
deleted file mode 100644
index 587937c..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Service API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/service/qualifier/Active.java b/core/api/src/main/java/org/qi4j/api/service/qualifier/Active.java
deleted file mode 100644
index d06a749..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/qualifier/Active.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service.qualifier;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.functional.Specification;
-
-/**
- * Filter services based on whether they are active or not.
- * <p>
- * At an injection point you can do this:
- * </p>
- * <pre><code>
- * &#64;Service &#64;Active MyService service;
- * </code></pre>
- * <p>
- * to get only a service that is currently active.
- * </p>
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Qualifier( Active.ActiveQualifier.class )
-public @interface Active
-{
-    /**
-     * Active Annotation Qualifier.
-     * See {@link Active}.
-     */
-    public final class ActiveQualifier
-        implements AnnotationQualifier<Active>
-    {
-        @Override
-        public <T> Specification<ServiceReference<?>> qualifier( Active active )
-        {
-            return ServiceQualifier.whereActive();
-        }
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/qualifier/AnnotationQualifier.java b/core/api/src/main/java/org/qi4j/api/service/qualifier/AnnotationQualifier.java
deleted file mode 100644
index 7187ed1..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/qualifier/AnnotationQualifier.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service.qualifier;
-
-import java.lang.annotation.Annotation;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.functional.Specification;
-
-/**
- * Constructs a Specification for a given qualifier annotation
- */
-public interface AnnotationQualifier<QUALIFIER extends Annotation>
-{
-    public <T> Specification<ServiceReference<?>> qualifier( QUALIFIER qualifier );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/qualifier/Available.java b/core/api/src/main/java/org/qi4j/api/service/qualifier/Available.java
deleted file mode 100644
index 894451d..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/qualifier/Available.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service.qualifier;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.functional.Specification;
-
-/**
- * Filter services based on whether they are available or not.
- *
- * At an injection point you can do this:
- *
- * <pre><code>
- * &#64;Service &#64;Available MyService service;
- * </code></pre>
- * to get only a service that is currently available.
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Qualifier( Available.AvailableQualifier.class )
-public @interface Available
-{
-    /**
-     * Available Annotation Qualifier.
-     * See {@link Available}.
-     */
-    public final class AvailableQualifier
-        implements AnnotationQualifier<Available>
-    {
-        @Override
-        public <T> Specification<ServiceReference<?>> qualifier( Available active )
-        {
-            return ServiceQualifier.whereAvailable();
-        }
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/qualifier/HasMetaInfo.java b/core/api/src/main/java/org/qi4j/api/service/qualifier/HasMetaInfo.java
deleted file mode 100644
index aac0702..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/qualifier/HasMetaInfo.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service.qualifier;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.functional.Specification;
-
-/**
- * Filter services based on Meta Info being declared on the Service.
- * <p>
- * Meta Info of any type can be set on the service during assembly, e.g.;
- * </p>
- * <pre><code>
- * module.addService( MyService.class ).setMetaInfo( new MyCustomInfo(someData) );
- * </code></pre>
- * <p>
- * and then at an injection point you can do this:
- * </p>
- * <pre><code>
- * &#64;Service &#64;HasMetaInfo(MyCustomInfo.class) MyService service;
- * </code></pre>
- * <p>
- * to get only a service that has a MyCustomInfo instance set as meta info.
- * </p>
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Qualifier( HasMetaInfo.HasMetaInfoQualifier.class )
-@Documented
-public @interface HasMetaInfo
-{
-    /**
-     * The Class(es) needed to have been defined in the Service meta info for a qualifier to evaluate true.
-     *
-     * @return One or more classes that should be defined in the service's meta info for the service to be considered
-     *         qualified. If more than one class is defined, the {@code anded()} parameter will define if they must be
-     *         AND'ed or OR'ed together.
-     */
-    Class[] value();
-
-    /**
-     * True if the Classes defined in the value() field should be AND'ed instead of OR'ed.
-     *
-     * @return If true, all the Class types defined in {@code value()} must be defined for the service for it to be
-     *         qualified. If false, if any of the Class types defined in {@code value()} is defined for the service
-     *         the service is qualified.
-     */
-    boolean anded() default false;
-
-    /**
-     * HasMetaInfo Annotation Qualifier.
-     * See {@link HasMetaInfo}.
-     */
-    public static class HasMetaInfoQualifier
-        implements AnnotationQualifier<HasMetaInfo>
-    {
-        @Override
-        public <T> Specification<ServiceReference<?>> qualifier( final HasMetaInfo hasMetaInfo )
-        {
-            return new Specification<ServiceReference<?>>()
-            {
-                @Override
-                @SuppressWarnings( {"raw", "unchecked"} )
-                public boolean satisfiedBy( ServiceReference<?> service )
-                {
-                    for( Class metaInfoType : hasMetaInfo.value() )
-                    {
-                        Object metaInfo = service.metaInfo( metaInfoType );
-                        if( hasMetaInfo.anded() )
-                        {
-                            if( metaInfo == null )
-                            {
-                                return false;
-                            }
-                        }
-                        else
-                        {
-                            if( metaInfo != null )
-                            {
-                                return true;
-                            }
-                        }
-                    }
-                    return false;
-                }
-            };
-        }
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/qualifier/IdentifiedBy.java b/core/api/src/main/java/org/qi4j/api/service/qualifier/IdentifiedBy.java
deleted file mode 100644
index 2c715d7..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/qualifier/IdentifiedBy.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service.qualifier;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.functional.Specification;
-
-/**
- * Filter services based on identity. Identity can be set during assembly, like so:
- * <pre><code>
- * module.addService(MyService.class).identifiedBy("myservice1");
- * </code></pre>
- *
- * and then at an injection point you can do this:
- * <pre><code>
- * &#64;Service @IdentifiedBy("myservice1") MyService service;
- * </code></pre>
- * to get only a service identified "myservice1".
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Qualifier( IdentifiedBy.IdentifiedByQualifier.class )
-public @interface IdentifiedBy
-{
-    public abstract String value();
-
-    /**
-     * IdentifiedBy Annotation Qualifier.
-     * See {@link IdentifiedBy}.
-     */
-    public final class IdentifiedByQualifier
-        implements AnnotationQualifier<IdentifiedBy>
-    {
-        @Override
-        public <T> Specification<ServiceReference<?>> qualifier( IdentifiedBy identifiedBy )
-        {
-            return ServiceQualifier.withId( identifiedBy.value() );
-        }
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/qualifier/Qualifier.java b/core/api/src/main/java/org/qi4j/api/service/qualifier/Qualifier.java
deleted file mode 100644
index 50efb1c..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/qualifier/Qualifier.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service.qualifier;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Annotation used to declare Qualifiers annotations.
- */
-@Retention( RetentionPolicy.RUNTIME )
-public @interface Qualifier
-{
-    public abstract Class<? extends AnnotationQualifier> value();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/qualifier/ServiceQualifier.java b/core/api/src/main/java/org/qi4j/api/service/qualifier/ServiceQualifier.java
deleted file mode 100644
index 75410d6..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/qualifier/ServiceQualifier.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service.qualifier;
-
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.functional.Specification;
-
-/**
- * This class helps you select a particular service
- * from a list.
- * <p>
- * Provide a Selector which does the actual
- * selection from the list. A common case is to select
- * based on identity of the service, which you can do this way:
- * </p>
- *
- * <pre><code>
- * new ServiceQualifier&lt;MyService&gt;(services, ServiceQualifier.withId("someId"))
- * </code></pre>
- * <p>
- * Many selectors can be combined by using firstOf. Example:
- * </p>
- * <pre><code>
- * new ServiceQualifier&lt;MyService&gt;(services, firstOf(withTags("sometag"), firstActive(), first()))
- * </code></pre>
- * <p>
- * This will pick a service that has the tag "sometag", or if none is found take the first active one. If no
- * service is active, then the first service will be picked.
- * </p>
- */
-public abstract class ServiceQualifier
-{
-    public static <T> T firstService( Specification<ServiceReference<?>> qualifier,
-                                      Iterable<ServiceReference<T>> services
-    )
-    {
-        for( ServiceReference<T> service : services )
-        {
-            if( qualifier.satisfiedBy( service ) )
-            {
-                return service.get();
-            }
-        }
-        return null;
-    }
-
-    public static Specification<ServiceReference<?>> withId( final String anId )
-    {
-        return new Specification<ServiceReference<?>>()
-        {
-            @Override
-            public boolean satisfiedBy( ServiceReference<?> service )
-            {
-                return service.identity().equals( anId );
-            }
-        };
-    }
-
-    public static Specification<ServiceReference<?>> whereMetaInfoIs( final Object metaInfo )
-    {
-        return new Specification<ServiceReference<?>>()
-        {
-            @Override
-            public boolean satisfiedBy( ServiceReference<?> service )
-            {
-                Object metaObject = service.metaInfo( metaInfo.getClass() );
-                return metaObject != null && metaInfo.equals( metaObject );
-            }
-        };
-    }
-
-    public static Specification<ServiceReference<?>> whereActive()
-    {
-        return new Specification<ServiceReference<?>>()
-        {
-            @Override
-            public boolean satisfiedBy( ServiceReference<?> service )
-            {
-                return service.isActive();
-            }
-        };
-    }
-
-    public static Specification<ServiceReference<?>> whereAvailable()
-    {
-        return new Specification<ServiceReference<?>>()
-        {
-            @Override
-            public boolean satisfiedBy( ServiceReference<?> service )
-            {
-                return service.isAvailable();
-            }
-        };
-    }
-
-    public static Specification<ServiceReference<?>> withTags( final String... tags )
-    {
-        return new Specification<ServiceReference<?>>()
-        {
-            @Override
-            public boolean satisfiedBy( ServiceReference<?> service )
-            {
-                ServiceTags serviceTags = service.metaInfo( ServiceTags.class );
-
-                return serviceTags != null && serviceTags.hasTags( tags );
-            }
-        };
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/qualifier/ServiceTags.java b/core/api/src/main/java/org/qi4j/api/service/qualifier/ServiceTags.java
deleted file mode 100644
index 5ee8cb5..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/qualifier/ServiceTags.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service.qualifier;
-
-import java.io.Serializable;
-
-/**
- * Use this as metainfo about a Service to specify tags. Easiest way to set them on a service
- * is to use the <code>ServiceDeclaration.taggedWith(String...)</code> method.
- *
- * These can be used in conjunction with the withTags() Service
- * Selector.
- */
-public final class ServiceTags
-    implements Serializable
-{
-    private String[] tags;
-
-    public ServiceTags( String... tags )
-    {
-        this.tags = tags;
-    }
-
-    public String[] tags()
-    {
-        return tags;
-    }
-
-    public boolean hasTag( String tag )
-    {
-        for( String serviceTag : tags )
-        {
-            if( serviceTag.equals( tag ) )
-            {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    public boolean hasTags( String... aTags )
-    {
-        for( String tag : aTags )
-        {
-            if( !hasTag( tag ) )
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/qualifier/Tagged.java b/core/api/src/main/java/org/qi4j/api/service/qualifier/Tagged.java
deleted file mode 100644
index 3c8c0b7..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/qualifier/Tagged.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service.qualifier;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.functional.Specification;
-
-/**
- * Filter services based on tags. Tags can be set using the ServiceTags meta-info, like so:
- * <pre><code>
- * module.addService(MyService.class).taggedWith(new ServiceTags("onetag","twotag"));
- * </code></pre>
- *
- * and then at an injection point you can do this:
- *
- * <pre><code>
- * &#64;Service &#64;Tagged("onetag") MyService service;
- * </code></pre>
- * to get only a service tagged with MyService. If several match only the first match is used.
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Qualifier( Tagged.TaggedQualifier.class )
-public @interface Tagged
-{
-    public abstract String[] value();
-
-    /**
-     * Tagged Annotation Qualifier.
-     * See {@link Tagged}.
-     */
-    public final class TaggedQualifier
-        implements AnnotationQualifier<Tagged>
-    {
-        @Override
-        public Specification<ServiceReference<?>> qualifier( Tagged tagged )
-        {
-            return ServiceQualifier.withTags( tagged.value() );
-        }
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/service/qualifier/package.html b/core/api/src/main/java/org/qi4j/api/service/qualifier/package.html
deleted file mode 100644
index ec0edd3..0000000
--- a/core/api/src/main/java/org/qi4j/api/service/qualifier/package.html
+++ /dev/null
@@ -1,59 +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.
--->
-<html>
-    <body>
-        <h2>Service Qualifiers.</h2>
-        <p>
-            The @Service injection is only able to specify the type of the service to be injected. If any other type of
-            qualification has to be done it has to be done manually but for common cases it's more convenient to use
-            annotations to do this filtering. This package contains annotations to perform this qualification.
-        </p>
-        <p>Example:</p>
-        <blockquote>
-            <pre>@Service @Tagged( "sometag" ) MyService service;</pre>
-        </blockquote>
-        <p>
-            This will only inject instances of MyService that have been tagged with "sometag". If none exist an
-            exception will occur at injection time since it is not optional.
-        </p>
-        <p>It also works with iterables:</p>
-        <blockquote>
-            <pre>@Service @Tagged( "sometag" ) Iterable&lt;MyService&gt; services;</pre>
-        </blockquote>
-        <p>
-            The qualification will be evaluated upon each call to iterator(), and since the qualifier has access to a
-            ServiceReference, which contains the isActive() method, it can even provide some dynamicity.
-        </p>
-        <blockquote>
-            <pre>@Service @Active Iterable&lt;SomeImportedService&gt; importedServices;</pre>
-        </blockquote>
-        <p>
-            Let's say these SomeImportedService are only sometimes available. Then whenever iterator() is called the
-            {@link org.qi4j.api.service.qualifier.Active} tag can kick in and filter out those whose
-            ServiceReference.isActive() returns false.
-        </p>
-        <p>Standard ones defined in the API are:</p>
-        <ul>
-            <li>{@link org.qi4j.api.service.qualifier.Active}</li>
-            <li>{@link org.qi4j.api.service.qualifier.Available}</li>
-            <li>{@link org.qi4j.api.service.qualifier.HasMetaInfo}</li>
-            <li>{@link org.qi4j.api.service.qualifier.IdentifiedBy}</li>
-            <li>{@link org.qi4j.api.service.qualifier.Tagged}</li>
-        </ul>
-        <p>See tests and API for more examples, and how to implement your own qualifiers.</p>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/sideeffect/GenericSideEffect.java b/core/api/src/main/java/org/qi4j/api/sideeffect/GenericSideEffect.java
deleted file mode 100644
index 167c1ef..0000000
--- a/core/api/src/main/java/org/qi4j/api/sideeffect/GenericSideEffect.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.api.sideeffect;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-
-/**
- * Base class for generic SideEffects.
- */
-public abstract class GenericSideEffect
-    extends SideEffectOf<InvocationHandler>
-    implements InvocationHandler
-{
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Object invoke( final Object proxy, final Method method, final Object[] args )
-        throws Throwable
-    {
-        invoke( method, args );
-        return null;
-    }
-
-    /**
-     * Convenience method to be overridden by subclasses in order to avoid returning null, as returned value from side
-     * effects is not taken in consideration.
-     *
-     * @param method the method that was invoked
-     * @param args   the arguments of the method invocation
-     *
-     * @throws Throwable - the exception to throw from the method invocation on the proxy instance. The exception's type
-     *                   must be assignable either to any of the exception types declared in the throws clause of the
-     *                   interface method or to the unchecked exception types {code}java.lang.RuntimeException{code}
-     *                   or {code}java.lang.Error{code}. If a checked exception is thrown by this method that is not
-     *                   assignable to any of the exception types declared in the throws clause of the interface method,
-     *                   then an UndeclaredThrowableException containing the exception that was thrown by this method
-     *                   will be thrown by the method invocation on the proxy instance.
-     */
-    protected void invoke( final Method method, final Object[] args )
-        throws Throwable
-    {
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/sideeffect/SideEffectDescriptor.java b/core/api/src/main/java/org/qi4j/api/sideeffect/SideEffectDescriptor.java
deleted file mode 100644
index 85e8610..0000000
--- a/core/api/src/main/java/org/qi4j/api/sideeffect/SideEffectDescriptor.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.sideeffect;
-
-/**
- * SideEffect Descriptor.
- */
-public interface SideEffectDescriptor
-{
-    Class<?> modifierClass();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/sideeffect/SideEffectOf.java b/core/api/src/main/java/org/qi4j/api/sideeffect/SideEffectOf.java
deleted file mode 100644
index 39113cc..0000000
--- a/core/api/src/main/java/org/qi4j/api/sideeffect/SideEffectOf.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.api.sideeffect;
-
-import org.qi4j.api.sideeffect.internal.SideEffectFor;
-
-/**
- * Base class for SideEffects. It introduces a typed "next" pointer
- * that SideEffects can use to get the result of the original invocation.
- * <p>
- * Generic SideEffects should subclass {@link GenericSideEffect} instead.
- * </p>
- * <p>
- * SideEffects implementations must be thread-safe in their implementation,
- * as multiple threads may share instances.
- * </p>
- */
-public abstract class SideEffectOf<T>
-{
-    final
-    @SideEffectFor
-    protected T result = null;
-}
diff --git a/core/api/src/main/java/org/qi4j/api/sideeffect/SideEffects.java b/core/api/src/main/java/org/qi4j/api/sideeffect/SideEffects.java
deleted file mode 100644
index bd2e525..0000000
--- a/core/api/src/main/java/org/qi4j/api/sideeffect/SideEffects.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.sideeffect;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * This annotation is used by composites and mixins to declare what SideEffects
- * should apply to the type or specific method.
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.TYPE, ElementType.METHOD } )
-@Documented
-public @interface SideEffects
-{
-    Class<?>[] value();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/sideeffect/SideEffectsDescriptor.java b/core/api/src/main/java/org/qi4j/api/sideeffect/SideEffectsDescriptor.java
deleted file mode 100644
index 9f569ea..0000000
--- a/core/api/src/main/java/org/qi4j/api/sideeffect/SideEffectsDescriptor.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.api.sideeffect;
-
-/**
- * SideEffects Descriptor.
- */
-public interface SideEffectsDescriptor
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/sideeffect/internal/SideEffectFor.java b/core/api/src/main/java/org/qi4j/api/sideeffect/internal/SideEffectFor.java
deleted file mode 100644
index 1ab3383..0000000
--- a/core/api/src/main/java/org/qi4j/api/sideeffect/internal/SideEffectFor.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.sideeffect.internal;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.qi4j.api.injection.InjectionScope;
-
-/**
- * This annotation is required once in each SideEffect, to mark the
- * field where the element providing the invocation result should be
- * injected.
- * <p>
- * The type of the field must be of the same type as the SideEffect
- * itself, or an InvocationHandler.
- * </p>
- * <p>
- * Example;
- * </p>
- * <pre><code>
- * public interface MyStuff
- * {
- *     SomeResult doSomething();
- * }
- *
- * public class MyStuffSideEffect
- *     implements MyStuff
- * {
- *     &#64;SideEffectFor MyStuff next;
- *
- *     public SomeResult doSomething()
- *     {
- *          SomeResult result = next.doSomething();
- *
- *         // HERE DO THE SIDEEFFECT STUFF.
- *
- *          return result; // Result value is ignored, null would work too.
- *     }
- * }
- * </code></pre>
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ ElementType.FIELD, ElementType.PARAMETER })
-@Documented
-@InjectionScope
-public @interface SideEffectFor
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/sideeffect/internal/package.html b/core/api/src/main/java/org/qi4j/api/sideeffect/internal/package.html
deleted file mode 100644
index 269774e..0000000
--- a/core/api/src/main/java/org/qi4j/api/sideeffect/internal/package.html
+++ /dev/null
@@ -1,25 +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.
--->
-<html>
-    <body>
-        <h1>Internal/Private package for the API.</h1>
-        <p>
-            This is an internal package, and no classes in this package is part of the API and compatibility
-            with these classes will not be attempted.
-        </p>
-    </body>
-</html>
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/sideeffect/package.html b/core/api/src/main/java/org/qi4j/api/sideeffect/package.html
deleted file mode 100644
index a658adb..0000000
--- a/core/api/src/main/java/org/qi4j/api/sideeffect/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SideEffect API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/structure/Application.java b/core/api/src/main/java/org/qi4j/api/structure/Application.java
deleted file mode 100644
index 6023942..0000000
--- a/core/api/src/main/java/org/qi4j/api/structure/Application.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008, Niclas Hedhman.
- *
- * Licensed 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.qi4j.api.structure;
-
-import org.qi4j.api.activation.Activation;
-import org.qi4j.api.activation.ActivationEventListenerRegistration;
-
-/**
- * The Application represents a whole Zest application.
- */
-public interface Application
-    extends ActivationEventListenerRegistration, Activation, MetaInfoHolder
-{
-    /**
-     * Application modes.
-     */
-    public enum Mode
-    {
-        /**
-         * Should be used for unit test runs. Created files etc. should be cleaned up between runs.
-         */
-        test,
-        /**
-         * Should be used during development. Typically create in-memory databases etc.
-         */
-        development,
-        /**
-         * Should be used in QA environments, and other production-like settings where different set of external
-         * resources are utilized.
-         */
-        staging,
-        /**
-         * Should be used in production. All databases are persistent on disk etc.
-         */
-        production
-    }
-
-    /**
-     * @return Application name
-     */
-    String name();
-
-    /**
-     * The version of the application. This can be in any format, but
-     * most likely will follow the Dewey format, i.e. x.y.z.
-     *
-     * @return the version of the application
-     */
-    String version();
-
-    /**
-     * @return Application Mode
-     */
-    Mode mode();
-
-    /**
-     * Find a Layer.
-     *
-     * @param layerName Layer name
-     * @return Found Layer, never returns null
-     * @throws IllegalArgumentException if there's no such Layer
-     */
-    Layer findLayer( String layerName )
-        throws IllegalArgumentException;
-
-    /**
-     * Find a Module.
-     *
-     * @param layerName Layer name
-     * @param moduleName Module name
-     * @return Found Module, never returns null
-     * @throws IllegalArgumentException if there's no such Module
-     */
-    Module findModule( String layerName, String moduleName )
-        throws IllegalArgumentException;
-
-    /**
-     * @return Application Descriptor
-     */
-    ApplicationDescriptor descriptor();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/structure/ApplicationDescriptor.java b/core/api/src/main/java/org/qi4j/api/structure/ApplicationDescriptor.java
deleted file mode 100644
index b33f134..0000000
--- a/core/api/src/main/java/org/qi4j/api/structure/ApplicationDescriptor.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.structure;
-
-import org.qi4j.api.Qi4j;
-import org.qi4j.functional.VisitableHierarchy;
-
-/**
- * Application Descriptor.
- */
-public interface ApplicationDescriptor
-    extends VisitableHierarchy<Object, Object>
-{
-    /**
-     * Create a new instance of the Application.
-     * @param runtime Zest Runtime
-     * @param importedServiceInstances Imported Services instances
-     * @return a new instance of the Application.
-     */
-    Application newInstance( Qi4j runtime, Object... importedServiceInstances );
-
-    /**
-     * @return the Application's name
-     */
-    String name();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/structure/Layer.java b/core/api/src/main/java/org/qi4j/api/structure/Layer.java
deleted file mode 100644
index 4268764..0000000
--- a/core/api/src/main/java/org/qi4j/api/structure/Layer.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008, Niclas Hedhman.
- *
- * Licensed 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.qi4j.api.structure;
-
-import org.qi4j.api.activation.Activation;
-import org.qi4j.api.activation.ActivationEventListenerRegistration;
-
-/**
- * The Layer represents a single layer in a Zest application.
- */
-public interface Layer
-    extends ActivationEventListenerRegistration, Activation, MetaInfoHolder
-{
-    /**
-     * @return the Layer's name
-     */
-    String name();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/structure/LayerDescriptor.java b/core/api/src/main/java/org/qi4j/api/structure/LayerDescriptor.java
deleted file mode 100644
index db0c56a..0000000
--- a/core/api/src/main/java/org/qi4j/api/structure/LayerDescriptor.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.structure;
-
-/**
- * Layer Descriptor.
- */
-public interface LayerDescriptor
-{
-
-    /**
-     * @return the Layer's name
-     */
-    String name();
-
-    /**
-     * @return Layers used by this Layer
-     */
-    UsedLayersDescriptor usedLayers();
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/structure/MetaInfoHolder.java b/core/api/src/main/java/org/qi4j/api/structure/MetaInfoHolder.java
deleted file mode 100644
index f497a75..0000000
--- a/core/api/src/main/java/org/qi4j/api/structure/MetaInfoHolder.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.structure;
-
-/**
- * MetaInfo holder.
- */
-public interface MetaInfoHolder
-{
-
-    /**
-     * Get metadata that implements the given type.
-     * The info is registered during assembly of the application.
-     *
-     * @param infoType the type of metadata to be returned
-     *
-     * @return the metadata for the given type, or <code>null</code> if
-     *         no such metadata has been registered
-     */
-    <T> T metaInfo( Class<T> infoType );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/structure/Module.java b/core/api/src/main/java/org/qi4j/api/structure/Module.java
deleted file mode 100644
index 47ffab8..0000000
--- a/core/api/src/main/java/org/qi4j/api/structure/Module.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008, Niclas Hedhman.
- *
- * Licensed 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.qi4j.api.structure;
-
-import org.qi4j.api.activation.ActivationEventListenerRegistration;
-import org.qi4j.api.composite.TransientBuilderFactory;
-import org.qi4j.api.composite.TransientDescriptor;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.object.ObjectDescriptor;
-import org.qi4j.api.object.ObjectFactory;
-import org.qi4j.api.query.QueryBuilderFactory;
-import org.qi4j.api.service.ServiceFinder;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Visitable;
-import org.qi4j.functional.Visitor;
-
-/**
- * API for interacting with a Module. Instances
- * of this can be accessed by using the {@link Structure}
- * injection scope.
- */
-public interface Module
-    extends ActivationEventListenerRegistration,
-            MetaInfoHolder,
-            ObjectFactory,
-            TransientBuilderFactory,
-            ValueBuilderFactory,
-            UnitOfWorkFactory,
-            QueryBuilderFactory,
-            ServiceFinder
-{
-
-    /**
-     * @return the Module's name
-     */
-    String name();
-
-    /**
-     * @return the Module's ClassLoader
-     */
-    ClassLoader classLoader();
-
-    /**
-     * @param typeName name of a transient composite type
-     * @return the descriptor for a transient composite or null if the class could not be found or the transient composite is not visible
-     */
-    TransientDescriptor transientDescriptor( String typeName );
-
-    /**
-     * @param typeName name of an entity composite type
-     * @return the descriptor for an entity composite or null if the class could not be found or the entity composite is not visible
-     */
-    EntityDescriptor entityDescriptor( String typeName );
-
-    /**
-     * @param typeName name of an object type
-     * @return the descriptor for an object or null if the class could not be found or the object is not visible
-     */
-    ObjectDescriptor objectDescriptor( String typeName );
-
-    /**
-     * @param typeName name of a value composite type
-     * @return the descriptor for a value composite or null if the class could not be found or the value composite is not visible
-     */
-    ValueDescriptor valueDescriptor( String typeName );
-
-}
diff --git a/core/api/src/main/java/org/qi4j/api/structure/ModuleDescriptor.java b/core/api/src/main/java/org/qi4j/api/structure/ModuleDescriptor.java
deleted file mode 100644
index ffb7b9b..0000000
--- a/core/api/src/main/java/org/qi4j/api/structure/ModuleDescriptor.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.structure;
-
-/**
- * Module Descriptor.
- */
-public interface ModuleDescriptor
-{
-    String name();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/structure/UsedLayersDescriptor.java b/core/api/src/main/java/org/qi4j/api/structure/UsedLayersDescriptor.java
deleted file mode 100644
index ee530b7..0000000
--- a/core/api/src/main/java/org/qi4j/api/structure/UsedLayersDescriptor.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.structure;
-
-/**
- * Used Layers Descriptor.
- */
-public interface UsedLayersDescriptor
-{
-    Iterable<? extends LayerDescriptor> layers();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/structure/package.html b/core/api/src/main/java/org/qi4j/api/structure/package.html
deleted file mode 100644
index 3134a90..0000000
--- a/core/api/src/main/java/org/qi4j/api/structure/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Application Structure API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/type/CollectionType.java b/core/api/src/main/java/org/qi4j/api/type/CollectionType.java
deleted file mode 100644
index 1b85b5f..0000000
--- a/core/api/src/main/java/org/qi4j/api/type/CollectionType.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.type;
-
-import java.lang.reflect.Type;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-import org.qi4j.api.util.Classes;
-
-/**
- * Collection ValueType.
- * <p>This handles Collection, List and Set types.</p>
- */
-public final class CollectionType
-    extends ValueType
-{
-
-    public static boolean isCollection( Type type )
-    {
-        Class<?> cl = Classes.RAW_CLASS.map( type );
-        return cl.equals( Collection.class ) || cl.equals( List.class ) || cl.equals( Set.class );
-    }
-
-    public static CollectionType collectionOf( Class<?> collectedType )
-    {
-        return new CollectionType( Collection.class, ValueType.of( collectedType ) );
-    }
-
-    public static CollectionType listOf( Class<?> collectedType )
-    {
-        return new CollectionType( List.class, ValueType.of( collectedType ) );
-    }
-
-    public static CollectionType setOf( Class<?> collectedType )
-    {
-        return new CollectionType( Set.class, ValueType.of( collectedType ) );
-    }
-    private ValueType collectedType;
-
-    public CollectionType( Class<?> type, ValueType collectedType )
-    {
-        super( type );
-        this.collectedType = collectedType;
-        if( !isCollection( type ) )
-        {
-            throw new IllegalArgumentException( type + " is not a Collection, List or Set." );
-        }
-    }
-
-    public ValueType collectedType()
-    {
-        return collectedType;
-    }
-
-    @Override
-    public String toString()
-    {
-        return super.toString() + "<" + collectedType + ">";
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/type/EnumType.java b/core/api/src/main/java/org/qi4j/api/type/EnumType.java
deleted file mode 100644
index aa4ff31..0000000
--- a/core/api/src/main/java/org/qi4j/api/type/EnumType.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.type;
-
-import java.lang.reflect.Type;
-
-/**
- * Enum ValueType.
- */
-public final class EnumType
-    extends ValueType
-{
-
-    public static boolean isEnum( Type type )
-    {
-        if( type instanceof Class )
-        {
-            Class<?> typeClass = (Class) type;
-            return ( typeClass.isEnum() );
-        }
-        return false;
-    }
-
-    public static EnumType of( Class<?> type )
-    {
-        return new EnumType( type );
-    }
-
-    public EnumType( Class<?> type )
-    {
-        super( type );
-        if( !isEnum( type ) )
-        {
-            throw new IllegalArgumentException( type + " is not an Enum." );
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/type/HasTypes.java b/core/api/src/main/java/org/qi4j/api/type/HasTypes.java
deleted file mode 100644
index 0ad36a4..0000000
--- a/core/api/src/main/java/org/qi4j/api/type/HasTypes.java
+++ /dev/null
@@ -1,27 +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.qi4j.api.type;
-
-/**
- * Has types.
- */
-public interface HasTypes
-{
-    Iterable<Class<?>> types();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/type/MapType.java b/core/api/src/main/java/org/qi4j/api/type/MapType.java
deleted file mode 100644
index 1cb1700..0000000
--- a/core/api/src/main/java/org/qi4j/api/type/MapType.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.type;
-
-import java.lang.reflect.Type;
-import java.util.Map;
-import org.qi4j.api.util.Classes;
-
-/**
- * Map ValueType.
- * <p>This handles instances of Map.</p>
- */
-public final class MapType
-    extends ValueType
-{
-
-    private ValueType keyType;
-    private ValueType valueType;
-    private final Serialization.Variant variant;
-
-    public static boolean isMap( Type type )
-    {
-        Class<?> cl = Classes.RAW_CLASS.map( type );
-        return Map.class.isAssignableFrom( cl );
-    }
-
-    public static MapType of( Class<?> keyType, Class<?> valueType )
-    {
-        return new MapType( Map.class, ValueType.of( keyType ), ValueType.of( valueType ) );
-    }
-
-    public static MapType of( Class<?> keyType, Class<?> valueType, Serialization.Variant variant )
-    {
-        return new MapType( Map.class, ValueType.of( keyType ), ValueType.of( valueType ), variant );
-    }
-
-    public MapType( Class<?> type, ValueType keyType, ValueType valueType )
-    {
-        this( type, keyType, valueType, Serialization.Variant.entry );
-    }
-
-    public MapType( Class<?> type, ValueType keyType, ValueType valueType, Serialization.Variant variant )
-    {
-        super( type );
-        this.keyType = keyType;
-        this.valueType = valueType;
-        this.variant = variant;
-        if( !isMap( type ) )
-        {
-            throw new IllegalArgumentException( type + " is not a Map." );
-        }
-    }
-
-    public ValueType keyType()
-    {
-        return keyType;
-    }
-
-    public ValueType valueType()
-    {
-        return valueType;
-    }
-
-    public Serialization.Variant variant()
-    {
-        return variant;
-    }
-
-    @Override
-    public String toString()
-    {
-        return super.toString() + "<" + keyType + "," + valueType + ">";
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/type/MatchTypeSpecification.java b/core/api/src/main/java/org/qi4j/api/type/MatchTypeSpecification.java
deleted file mode 100644
index ff7e8e5..0000000
--- a/core/api/src/main/java/org/qi4j/api/type/MatchTypeSpecification.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.type;
-
-import org.qi4j.functional.Specification;
-
-/**
- * Match Type Specification for HasTypes.
- */
-public class MatchTypeSpecification
-    implements Specification<HasTypes>
-{
-    private final Class<?> matchType;
-
-    public MatchTypeSpecification( Class<?> matchType )
-    {
-        this.matchType = matchType;
-    }
-
-    @Override
-    public boolean satisfiedBy( HasTypes item )
-    {
-        for( Class<?> type : item.types() )
-        {
-            if( matchType.isAssignableFrom( type ) )
-            {
-                return true;
-            }
-        }
-        return false;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/type/Serialization.java b/core/api/src/main/java/org/qi4j/api/type/Serialization.java
deleted file mode 100644
index 57184a0..0000000
--- a/core/api/src/main/java/org/qi4j/api/type/Serialization.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.type;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Serialization options for Property intstances.
- * <p>
- * The {@code entry} type represents the explicit key=keyValue, value=valueValue. For JSON serialization;
- * </p>
- * <pre>
- *     [
- *         { "key1" : "value1" },
- *         { "key2" : "value2" }
- *     ]
- * </pre>
- * <p>
- * For XML serialization;
- * </p>
- * <pre>
- *     &lt;object&gt;
- *         &lt;
- *     &lt;/object&gt;
- * </pre>
- * <p>
- * The {@code object} type represents the explicit keyValue=valueValue.
- * </p>
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.TYPE, ElementType.METHOD } )
-@Documented
-public @interface Serialization
-{
-    Variant value();
-
-    enum Variant
-    {
-        entry, object
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/type/ValueCompositeType.java b/core/api/src/main/java/org/qi4j/api/type/ValueCompositeType.java
deleted file mode 100644
index c546625..0000000
--- a/core/api/src/main/java/org/qi4j/api/type/ValueCompositeType.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.type;
-
-import java.lang.reflect.Type;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.util.Classes;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.api.value.ValueDescriptor;
-
-/**
- * ValueComposite ValueType.
- */
-public final class ValueCompositeType
-    extends ValueType
-{
-    private final ValueDescriptor model;
-
-    public static boolean isValueComposite( Type type )
-    {
-        return ValueComposite.class.isAssignableFrom( Classes.RAW_CLASS.map( type ) );
-    }
-
-    public ValueCompositeType( ValueDescriptor model )
-    {
-        super( model.types() );
-        this.model = model;
-    }
-
-    public Iterable<? extends PropertyDescriptor> properties()
-    {
-        return model.state().properties();
-    }
-
-    public Iterable<? extends AssociationDescriptor> associations()
-    {
-        return model.state().associations();
-    }
-
-    public Iterable<? extends AssociationDescriptor> manyAssociations()
-    {
-        return model.state().manyAssociations();
-    }
-
-    public Iterable<? extends AssociationDescriptor> namedAssociations()
-    {
-        return model.state().namedAssociations();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/type/ValueType.java b/core/api/src/main/java/org/qi4j/api/type/ValueType.java
deleted file mode 100644
index ede914c..0000000
--- a/core/api/src/main/java/org/qi4j/api/type/ValueType.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2013, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.type;
-
-import java.util.Collections;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Base class for types of values in ValueComposites and Properties.
- */
-public class ValueType
-    implements HasTypes
-{
-
-    public static ValueType of( Class<?> type )
-    {
-        return new ValueType( type );
-    }
-
-    /**
-     * Check if a non-null object is of any of the Primitive Value Types or an array of them.
-     * <p>
-     *     String, Boolean, Integer, Double, Float, Long, Byte, Short and Character and their Java primitive types
-     *     counterparts are considered as Primitive Value Types.
-     * </p>
-     * <p>
-     *     Date, BigInteger, BigDecimal and JodaTime types are not considered as Primitive Value Types.
-     * </p>
-     *
-     * @return true if object is a primitive value or an array of primitive values
-     * @throws IllegalArgumentException if object is null
-     */
-    public static boolean isPrimitiveValue( Object object )
-    {
-        NullArgumentException.validateNotNull( "object", object );
-        if( object instanceof String
-            || object instanceof Character
-            || object instanceof Boolean
-            || object instanceof Integer
-            || object instanceof Double
-            || object instanceof Float
-            || object instanceof Long
-            || object instanceof Byte
-            || object instanceof Short )
-        {
-            return true;
-        }
-        if( object.getClass().isArray() )
-        {
-            return isArrayOfPrimitiveValues( object );
-        }
-        return false;
-    }
-
-    private static boolean isArrayOfPrimitiveValues( Object array )
-    {
-        if( array instanceof String[]
-            || array instanceof char[] || array instanceof Character[]
-            || array instanceof boolean[] || array instanceof Boolean[]
-            || array instanceof int[] || array instanceof Integer[]
-            || array instanceof double[] || array instanceof Double[]
-            || array instanceof float[] || array instanceof Float[]
-            || array instanceof long[] || array instanceof Long[]
-            || array instanceof byte[] || array instanceof Byte[]
-            || array instanceof short[] || array instanceof Short[] )
-        {
-            return true;
-        }
-        return false;
-    }
-
-    public static boolean isPrimitiveValueType( ValueType valueType )
-    {
-        return isPrimitiveValueType( valueType.mainType() );
-    }
-
-    /**
-     * @see ValueType#isPrimitiveValue(java.lang.Object) 
-     */
-    public static boolean isPrimitiveValueType( Class<?> type )
-    {
-        NullArgumentException.validateNotNull( "type", type );
-        if( String.class.isAssignableFrom( type ) )
-        {
-            return true;
-        }
-        if( type.isArray() )
-        {
-            return isPrimitiveValueType( type.getComponentType() );
-        }
-        return false;
-    }
-    protected final Iterable<Class<?>> types;
-
-    public ValueType( Class<?> type )
-    {
-        this( Collections.singleton( type ) );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public ValueType( Iterable<? extends Class<?>> types )
-    {
-        this.types = (Iterable<Class<?>>) types;
-    }
-
-    public Class<?> mainType()
-    {
-        return first( types );
-    }
-
-    @Override
-    public Iterable<Class<?>> types()
-    {
-        return types;
-    }
-
-    @Override
-    public String toString()
-    {
-        String name = Iterables.toString(
-            types,
-            new Function<Class<?>, String>()
-            {
-                @Override
-                public String map( Class<?> item )
-                {
-                    return item.getName();
-                }
-            },
-            "," );
-        if( name.contains( "," ) )
-        {
-            name = "{" + name + "}";
-        }
-        return name;
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/type/package.html b/core/api/src/main/java/org/qi4j/api/type/package.html
deleted file mode 100644
index d42baa3..0000000
--- a/core/api/src/main/java/org/qi4j/api/type/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Type API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/ConcurrentEntityModificationException.java b/core/api/src/main/java/org/qi4j/api/unitofwork/ConcurrentEntityModificationException.java
deleted file mode 100644
index 7745b5a..0000000
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/ConcurrentEntityModificationException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.unitofwork;
-
-import org.qi4j.api.entity.EntityComposite;
-
-/**
- * This exception is thrown by UnitOfWork.complete() if any entities that are being committed
- * had been changed while the UnitOfWork was being executed.
- */
-public class ConcurrentEntityModificationException
-    extends UnitOfWorkCompletionException
-{
-    private static final long serialVersionUID = 3872723845064767689L;
-
-    private final Iterable<EntityComposite> concurrentlyModifiedEntities;
-
-    public ConcurrentEntityModificationException( Iterable<EntityComposite> concurrentlyModifiedEntities )
-    {
-        super("Entities changed concurrently :" + concurrentlyModifiedEntities);
-        this.concurrentlyModifiedEntities = concurrentlyModifiedEntities;
-    }
-
-    public Iterable<EntityComposite> concurrentlyModifiedEntities()
-    {
-        return concurrentlyModifiedEntities;
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/EntityCompositeAlreadyExistsException.java b/core/api/src/main/java/org/qi4j/api/unitofwork/EntityCompositeAlreadyExistsException.java
deleted file mode 100644
index 66e388d..0000000
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/EntityCompositeAlreadyExistsException.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.api.unitofwork;
-
-import org.qi4j.api.entity.EntityReference;
-
-/**
- * If you try to create an EntityComposite whose identity already exists,
- * then this exception will be thrown.
- */
-public class EntityCompositeAlreadyExistsException
-    extends UnitOfWorkException
-{
-    private static final long serialVersionUID = -7297710939536508481L;
-
-    private final EntityReference identity;
-
-    public EntityCompositeAlreadyExistsException( EntityReference identity )
-    {
-        super( "EntityComposite (" + identity + ") already exists." );
-        this.identity = identity;
-    }
-
-    public EntityReference identity()
-    {
-        return identity;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/EntityTypeNotFoundException.java b/core/api/src/main/java/org/qi4j/api/unitofwork/EntityTypeNotFoundException.java
deleted file mode 100644
index 39765fd..0000000
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/EntityTypeNotFoundException.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007-2008, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2007, Alin Dreghiciu. All Rights Reserved. 
- *
- * Licensed 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.qi4j.api.unitofwork;
-
-import org.qi4j.functional.Function;
-
-import static org.qi4j.functional.Iterables.fold;
-
-/**
- * Zest exception to be thrown in case that an entity composite
- * was not found during a lookup call.
- */
-public class EntityTypeNotFoundException
-    extends UnitOfWorkException
-{
-    private final String compositeType;
-
-    public EntityTypeNotFoundException( String entityType, String moduleName, Iterable<String> visibility )
-    {
-        super( "Could not find an EntityComposite of type " + entityType + " in module [" + moduleName + "].\n" +
-               "\tThe following entity types are visible:\n" + join(visibility) );
-        this.compositeType = entityType;
-    }
-
-    private static String join( Iterable<String> visibility )
-    {
-        return fold( new Function<String, String>()
-        {
-            StringBuilder result;
-            {
-                result = new StringBuilder();
-            }
-
-            @Override
-            public String map( String type )
-            {
-                result.append( type );
-                result.append( "\n" );
-                return result.toString();
-            }
-        }, visibility );
-    }
-
-    public String compositeType()
-    {
-        return compositeType;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/NoSuchEntityException.java b/core/api/src/main/java/org/qi4j/api/unitofwork/NoSuchEntityException.java
deleted file mode 100644
index cbffe9d..0000000
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/NoSuchEntityException.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.unitofwork;
-
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-
-/**
- * This exception indicates that the requested Entity with the given
- * identity does not exist.
- */
-public class NoSuchEntityException
-    extends UnitOfWorkException
-{
-    private final EntityReference identity;
-    private final Usecase usecase;
-    private final Class<?>[] mixinTypes;
-
-    public NoSuchEntityException( EntityReference identity, Class<?> mixinType, Usecase usecase )
-    {
-        super( "Could not find entity (" + identity + ") of type " + mixinType.getName() + " in usecase '" + usecase.name() + "'" );
-        this.identity = identity;
-        this.usecase = usecase;
-        this.mixinTypes = new Class<?>[]{ mixinType };
-    }
-
-    public NoSuchEntityException( EntityReference identity, Class<?>[] mixinTypes, Usecase usecase )
-    {
-        super( "Could not find entity (" + identity + ") of type " + toString( mixinTypes ) + " in usecase '" + usecase.name() + "'" );
-        this.identity = identity;
-        this.mixinTypes = mixinTypes;
-        this.usecase = usecase;
-    }
-
-    public NoSuchEntityException( EntityReference identity, Iterable<Class<?>> types, Usecase usecase )
-    {
-        this( identity, castToArray( types ), usecase );
-    }
-
-    public EntityReference identity()
-    {
-        return identity;
-    }
-
-    public Class<?>[] mixinTypes()
-    {
-        return mixinTypes;
-    }
-
-    public Usecase usecase()
-    {
-        return usecase;
-    }
-
-    private static Class<?>[] castToArray( Iterable<Class<?>> iterableClasses )
-    {
-        Iterable<Class> types = Iterables.cast( iterableClasses );
-        return Iterables.toArray( Class.class, types );
-    }
-
-    private static String toString( Class<?>[] mixinTypes )
-    {
-        Iterable<String> map = Iterables.map( new Function<Class<?>, String>()
-        {
-            @Override
-            public String map( Class<?> item )
-            {
-                return item.getName();
-            }
-        }, Iterables.iterable( mixinTypes ) );
-        return Iterables.fold( new Function<String, String>()
-        {
-            StringBuilder result;
-            boolean first = true;
-
-            {
-                result = new StringBuilder();
-                result.append( "[" );
-            }
-
-            @Override
-            public String map( String strings )
-            {
-                if( !first )
-                {
-                    result.append( ',' );
-                }
-                first = false;
-                result.append( strings );
-                return result.toString() + "]";
-            }
-        }, map );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWork.java b/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWork.java
deleted file mode 100644
index 2ce6855..0000000
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWork.java
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * Copyright (c) 2007-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2013-2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.unitofwork;
-
-import java.util.Map;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.composite.AmbiguousTypeException;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.entity.LifecycleException;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.structure.MetaInfoHolder;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.functional.Function;
-
-/**
- * All operations on entities goes through an UnitOfWork.
- * <p>
- * A UnitOfWork allows you to access
- * Entities and work with them. All modifications to Entities are recorded by the UnitOfWork,
- * and at the end they may be sent to the underlying EntityStore by calling complete(). If the
- * UoW was read-only you may instead simply discard() it.
- * </p>
- * <p>
- * A UoW differs from a traditional Transaction in the sense that it is not tied at all to the underlying
- * storage resource. Because of this there is no timeout on a UoW. It can be very short or very long.
- * Another difference is that if a call to complete() fails, and the cause is validation errors in the
- * Entities of the UoW, then these can be corrected and the UoW retried. By contrast, when a Transaction
- * commit fails, then the whole transaction has to be done from the beginning again.
- * </p>
- * <p>
- * A UoW can be associated with a Usecase. A Usecase describes the metainformation about the process
- * to be performed by the UoW.
- * </p>
- * <p>
- * If a code block that uses a UoW throws an exception you need to ensure that this is handled properly,
- * and that the UoW is closed before returning. Because discard() is a no-op if the UoW is closed, we therefore
- * recommend the following template to be used:
- * </p>
- * <pre>
- *     UnitOfWork uow = module.newUnitOfWork();
- *     try
- *     {
- *         ...
- *         uow.complete();
- *     }
- *     finally
- *     {
- *         uow.discard();
- *     }
- * </pre>
- * <p>
- * This ensures that in the happy case the UoW is completed, and if any exception is thrown the UoW is discarded. After
- * the UoW has completed the discard() method doesn't do anything, and so has no effect. You can choose to either add
- * catch blocks for any exceptions, including exceptions from complete(), or skip them.
- * </p>
- * <p>
- * Since 2.1 you can leverage Java 7 Automatic Resource Management (ie. Try With Resources) and use the following
- * template instead:
- * </p>
- * <pre>
- *     try( UnitOfWork uow = module.newUnitOfWork() )
- *     {
- *         ...
- *         uow.complete();
- *     }
- * </pre>
- * <p>
- * It has the very same effect than the template above but is shorter.</p>
- */
-public interface UnitOfWork extends MetaInfoHolder, AutoCloseable
-{
-
-    /**
-     * Get the UnitOfWorkFactory that this UnitOfWork was created from.
-     *
-     * @return The UnitOfWorkFactory instance that was used to create this UnitOfWork.
-     */
-    UnitOfWorkFactory unitOfWorkFactory();
-
-    long currentTime();
-
-    /**
-     * Get the Usecase for this UnitOfWork
-     *
-     * @return the Usecase
-     */
-    Usecase usecase();
-
-    void setMetaInfo( Object metaInfo );
-
-    <T> Query<T> newQuery( QueryBuilder<T> queryBuilder );
-
-//    DataSet newDataSetBuilder(Specification<?>... constraints);
-
-    /**
-     * Create a new Entity which implements the given mixin type.
-     * <p>
-     * An EntityComposite
-     * will be chosen according to what has been registered and the visibility rules
-     * for Modules and Layers will be considered. If several
-     * EntityComposites implement the type then an AmbiguousTypeException will be thrown.
-     * </p>
-     * <p>
-     * The identity of the Entity will be generated by the IdentityGenerator of the Module of the EntityComposite.
-     * </p>
-     *
-     * @param type the mixin type that the EntityComposite must implement
-     *
-     * @return a new Entity
-     *
-     * @throws EntityTypeNotFoundException if no EntityComposite type of the given mixin type has been registered
-     * @throws AmbiguousTypeException      If several mixins implement the given type
-     * @throws LifecycleException          if the entity cannot be created
-     */
-    <T> T newEntity( Class<T> type )
-        throws EntityTypeNotFoundException, AmbiguousTypeException, LifecycleException;
-
-    /**
-     * Create a new Entity which implements the given mixin type. An EntityComposite
-     * will be chosen according to what has been registered and the visibility rules
-     * for Modules and Layers will be considered. If several
-     * EntityComposites implement the type then an AmbiguousTypeException will be thrown.
-     *
-     * @param type     the mixin type that the EntityComposite must implement
-     * @param identity the identity of the new Entity
-     *
-     * @return a new Entity
-     *
-     * @throws EntityTypeNotFoundException if no EntityComposite type of the given mixin type has been registered
-     * @throws AmbiguousTypeException      If several mixins implement the given type
-     * @throws LifecycleException          if the entity cannot be created
-     */
-    <T> T newEntity( Class<T> type, String identity )
-        throws EntityTypeNotFoundException, AmbiguousTypeException, LifecycleException;
-
-    /**
-     * Create a new EntityBuilder for an EntityComposite which implements the given mixin type. An EntityComposite
-     * will be chosen according to what has been registered and the visibility rules
-     * for Modules and Layers will be considered. If several
-     * EntityComposites implement the type then an AmbiguousTypeException will be thrown.
-     *
-     * @param type the mixin type that the EntityComposite must implement
-     *
-     * @return a new EntityBuilder
-     *
-     * @throws EntityTypeNotFoundException if no EntityComposite type of the given mixin type has been registered
-     * @throws AmbiguousTypeException      If several mixins implement the given type
-     */
-    <T> EntityBuilder<T> newEntityBuilder( Class<T> type )
-        throws EntityTypeNotFoundException, AmbiguousTypeException;
-
-    /**
-     * Create a new EntityBuilder for an EntityComposite which implements the given mixin type. An EntityComposite
-     * will be chosen according to what has been registered and the visibility rules
-     * for Modules and Layers will be considered. If several
-     * mixins implement the type then an AmbiguousTypeException will be thrown.
-     *
-     * @param type     the mixin type that the EntityComposite must implement
-     * @param identity the identity of the new Entity
-     *
-     * @return a new EntityBuilder
-     *
-     * @throws EntityTypeNotFoundException if no EntityComposite type of the given mixin type has been registered
-     * @throws AmbiguousTypeException      If several mixins implement the given type
-     */
-    <T> EntityBuilder<T> newEntityBuilder( Class<T> type, String identity )
-        throws EntityTypeNotFoundException, AmbiguousTypeException;
-
-    /**
-     * Create a new EntityBuilder for an EntityComposite wich implements the given mixin type starting with the given
-     * state.
-     * <p>
-     * An EntityComposite will be chosen according to what has been registered and the visibility rules for Modules and
-     * Layers will be considered.
-     *
-     * @param <T>                      Entity type
-     * @param type                     Entity type
-     * @param propertyFunction         a function providing the state of properties
-     * @param associationFunction      a function providing the state of associations
-     * @param manyAssociationFunction  a function providing the state of many associations
-     * @param namedAssociationFunction a function providing the state of named associations
-     *
-     * @return a new EntityBuilder starting with the given state
-     *
-     * @throws EntityTypeNotFoundException if no EntityComposite type of the given mixin type has been registered
-     * @throws AmbiguousTypeException      If several mixins implement the given type
-     */
-    <T> EntityBuilder<T> newEntityBuilderWithState( Class<T> type,
-                                                    Function<PropertyDescriptor, Object> propertyFunction,
-                                                    Function<AssociationDescriptor, EntityReference> associationFunction,
-                                                    Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction,
-                                                    Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction )
-        throws EntityTypeNotFoundException, AmbiguousTypeException;
-
-    /**
-     * Create a new EntityBuilder for an EntityComposite wich implements the given mixin type starting with the given
-     * state.
-     * <p>
-     * An EntityComposite will be chosen according to what has been registered and the visibility rules for Modules and
-     * Layers will be considered.
-     *
-     * @param <T>                      Entity type
-     * @param type                     Entity type
-     * @param identity                 the identity of the new Entity
-     * @param propertyFunction         a function providing the state of properties
-     * @param associationFunction      a function providing the state of associations
-     * @param manyAssociationFunction  a function providing the state of many associations
-     * @param namedAssociationFunction a function providing the state of named associations
-     *
-     * @return a new EntityBuilder starting with the given state
-     *
-     * @throws EntityTypeNotFoundException If no mixins implements the given type
-     * @throws AmbiguousTypeException      If several mixins implement the given type
-     */
-    <T> EntityBuilder<T> newEntityBuilderWithState( Class<T> type, String identity,
-                                                    Function<PropertyDescriptor, Object> propertyFunction,
-                                                    Function<AssociationDescriptor, EntityReference> associationFunction,
-                                                    Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction,
-                                                    Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction )
-        throws EntityTypeNotFoundException, AmbiguousTypeException;
-
-    /**
-     * Find an Entity of the given mixin type with the give identity. This
-     * method verifies that it exists by asking the underlying EntityStore.
-     *
-     * @param type     of the entity
-     * @param identity of the entity
-     *
-     * @return the entity
-     *
-     * @throws EntityTypeNotFoundException if no entity type could be found
-     * @throws NoSuchEntityException       if the entity could not be found
-     */
-    <T> T get( Class<T> type, String identity )
-        throws EntityTypeNotFoundException, NoSuchEntityException;
-
-    /**
-     * If you have a reference to an Entity from another
-     * UnitOfWork and want to create a reference to it in this
-     * UnitOfWork, then call this method.
-     *
-     * @param entity the Entity to be dereferenced
-     *
-     * @return an Entity from this UnitOfWork
-     *
-     * @throws EntityTypeNotFoundException if no entity type could be found
-     */
-    <T> T get( T entity )
-        throws EntityTypeNotFoundException;
-
-    /**
-     * Remove the given Entity.
-     *
-     * @param entity the Entity to be removed.
-     *
-     * @throws LifecycleException if the entity could not be removed
-     */
-    void remove( Object entity )
-        throws LifecycleException;
-
-    /**
-     * Complete this UnitOfWork. This will send all the changes down to the underlying
-     * EntityStore's.
-     *
-     * @throws UnitOfWorkCompletionException         if the UnitOfWork could not be completed
-     * @throws ConcurrentEntityModificationException if entities have been modified by others
-     */
-    void complete()
-        throws UnitOfWorkCompletionException, ConcurrentEntityModificationException;
-
-    /**
-     * Discard this UnitOfWork. Use this if a failure occurs that you cannot handle,
-     * or if the usecase was of a read-only character. This is a no-op of the UnitOfWork
-     * is already closed.
-     */
-    void discard();
-
-    /**
-     * Discard this UnitOfWork. Use this if a failure occurs that you cannot handle,
-     * or if the usecase was of a read-only character. This is a no-op of the UnitOfWork
-     * is already closed. This simply call the {@link #discard()} method and is an
-     * implementation of the {@link AutoCloseable} interface providing Try With Resources
-     * support for UnitOfWork.
-     */
-    @Override
-    public void close();
-
-    /**
-     * Check if the UnitOfWork is open. It is closed after either complete() or discard()
-     * methods have been called successfully.
-     *
-     * @return true if the UnitOfWork is open.
-     */
-    boolean isOpen();
-
-    /**
-     * Check if the UnitOfWork is paused. It is not paused after it has been create through the
-     * UnitOfWorkFactory, and it can be paused by calling {@link #pause()} and then resumed by calling
-     * {@link #resume()}.
-     *
-     * @return true if this UnitOfWork has been paused.
-     */
-    boolean isPaused();
-
-    /**
-     * Pauses this UnitOfWork.
-     * <p>
-     * Calling this method will cause the underlying UnitOfWork to become the current UnitOfWork until the
-     * the resume() method is called. It is the client's responsibility not to drop the reference to this
-     * UnitOfWork while being paused.
-     * </p>
-     */
-    void pause();
-
-    /**
-     * Resumes this UnitOfWork to again become the current UnitOfWork.
-     */
-    void resume();
-
-    /**
-     * Register a callback. Callbacks are invoked when the UnitOfWork
-     * is completed or discarded.
-     *
-     * @param callback a callback to be registered with this UnitOfWork
-     */
-    void addUnitOfWorkCallback( UnitOfWorkCallback callback );
-
-    /**
-     * Unregister a callback. Callbacks are invoked when the UnitOfWork
-     * is completed or discarded.
-     *
-     * @param callback a callback to be unregistered with this UnitOfWork
-     */
-    void removeUnitOfWorkCallback( UnitOfWorkCallback callback );
-
-    /**
-     * Converts the provided Entity to a Value of the same type.
-     * This is a convenience method to convert an EntityComposite to a ValueComposite.
-     * <p>
-     * All Property values are transferred across as-is, and the Association, ManyAssociation
-     * and NamedAssociatino values are kept in the ValueComposite as EntityReferences
-     * until they are dereferenced (get() and other methods), and IF a UnitOfWork is
-     * present at dereferencing the corresponding EntityCompoiste is retrieved from the
-     * EntityStore. If there is not an UnitOfWork present, an exception is thrown.
-     * </p>
-     * <p>
-     * For this to work, the Composites (both Entity and Value) must not declare the
-     * EntityComposite and ValueComposite super types, but rely on the declaration in
-     * the assembly, and also extend the Identity supertype.
-     * </p>
-     * Example;
-     * <pre><code>
-     *     public interface Person extends Identity { ... };
-     *     public class MyAssembler
-     *     {
-     *         public void assemble( ModuleAssembly module )
-     *         {
-     *             module.values( Person.class );
-     *             module.entities( Person.class );
-     *         }
-     *     }
-     * </code></pre>
-     *
-     * @param primaryType The shared type for which the properties and associations will
-     *                    be converted. Properties outside this type will be ignored.
-     * @param entityComposite The entity to be convered.
-     */
-    <T extends Identity> T toValue( Class<T> primaryType, T entityComposite );
-
-    /**
-     * Converts the provided Value to an Entity of the same type.
-     * This is a convenience method to convert a ValueComposite to an EntityComposite.
-     * <p>
-     * All Property values are transferred across as-is (no deep copy in case mutable
-     * types (DISCOURAGED!) are used), and the Association, ManyAssociation
-     * and NamedAssociatino that were in the ValueComposite as EntityReferences are
-     * transferred into the EntityComposite correctly, and can be dereferenced.
-     * </p>
-     * <p>
-     * This method MUST be called within a UnitOfWork.
-     * </p>
-     * <p>
-     * If an Entity with the Identity in the ValueComposite already exists, then that
-     * Entity is updated with the values from the ValueComposite. If an Entity of
-     * that Identity doesn't exist and new one is created.
-     * </p>
-     * <p>
-     * For this to work, the Composites (both Entity and Value) must not declare the
-     * EntityComposite and ValueComposite super types, but rely on the declaration in
-     * the assembly, and also extend the Identity supertype.
-     * </p>
-     * Example;
-     * <pre><code>
-     *     public interface Person extends Identity { ... };
-     *     public class MyAssembler
-     *     {
-     *         public void assemble( ModuleAssembly module )
-     *         {
-     *             module.values( Person.class );
-     *             module.entities( Person.class );
-     *         }
-     *     }
-     * </code></pre>
-     *
-     * @param primaryType The shared type for which the properties and associations will
-     *                    be converted. Properties outside this type will be ignored.
-     * @param valueComposite The Value to be convered into an Entity.
-     */
-    <T extends Identity> T toEntity( Class<T> primaryType, T valueComposite );
-
-
-}
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkCallback.java b/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkCallback.java
deleted file mode 100644
index 77a78e9..0000000
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkCallback.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.unitofwork;
-
-/**
- * Callback interface for UnitOfWork completion or discard. Implementations
- * of this interface can be registered through {@link UnitOfWork#addUnitOfWorkCallback(UnitOfWorkCallback)}.
- *
- * If Entities implement this interface they will also receive invocations of this callback interface.
- */
-public interface UnitOfWorkCallback
-{
-    /**
-     * This is called before the completion of the UnitOfWork.
-     * The callback may do any validation checks and throw
-     * UnitOfWorkCompletionException if there is any reason
-     * why the UnitOfWork is not in a valid state to be completed.
-     *
-     * @throws UnitOfWorkCompletionException
-     */
-    void beforeCompletion()
-        throws UnitOfWorkCompletionException;
-
-    /**
-     * This is called after the completion or discarding
-     * of the UnitOfWork. The callback may do any cleanup
-     * necessary related to the UnitOfWork. Note that the
-     * UnitOfWork is no longer active when this method is
-     * called, so no methods on it may be invoked.
-     *
-     * @param status
-     */
-    void afterCompletion( UnitOfWorkStatus status );
-
-    enum UnitOfWorkStatus
-    {
-        COMPLETED, DISCARDED
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkCompletionException.java b/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkCompletionException.java
deleted file mode 100644
index 54f6c72..0000000
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkCompletionException.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.unitofwork;
-
-/**
- * When an attempt to {@link UnitOfWork#complete()} an UnitOfWork
- * fails, this exception will be thrown.
- */
-public class UnitOfWorkCompletionException
-    extends Exception
-{
-    private static final long serialVersionUID = 6531642131384516904L;
-
-    public UnitOfWorkCompletionException()
-    {
-    }
-
-    public UnitOfWorkCompletionException( String string )
-    {
-        super( string );
-    }
-
-    public UnitOfWorkCompletionException( String string, Throwable throwable )
-    {
-        super( string, throwable );
-    }
-
-    public UnitOfWorkCompletionException( Throwable throwable )
-    {
-        super( throwable );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkException.java b/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkException.java
deleted file mode 100644
index 03b15d7..0000000
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkException.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*  Copyright 2007 Niclas Hedhman.
- *
- * Licensed 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.qi4j.api.unitofwork;
-
-/**
- * Base Exception for UnitOfWork related concerns.
- */
-public class UnitOfWorkException
-    extends RuntimeException
-{
-    private static final long serialVersionUID = -8544178439804058558L;
-
-    public UnitOfWorkException()
-    {
-    }
-
-    public UnitOfWorkException( String message )
-    {
-        super( message );
-    }
-
-    public UnitOfWorkException( String message, Throwable cause )
-    {
-        super( message, cause );
-    }
-
-    public UnitOfWorkException( Throwable cause )
-    {
-        super( cause );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkFactory.java b/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkFactory.java
deleted file mode 100644
index a8755d4..0000000
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkFactory.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.unitofwork;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.usecase.Usecase;
-
-/**
- * Factory for UnitOfWork.
- */
-public interface UnitOfWorkFactory
-{
-    /**
-     * Create a new UnitOfWork and associate it with the current thread.
-     * <p>
-     * The UnitOfWork will use the default Usecase settings.
-     * </p>
-     * <p>
-     * Current time will be set to System.currentTimeMillis();
-     * </p>
-     * @return a new UnitOfWork
-     */
-    UnitOfWork newUnitOfWork();
-
-    /**
-     * Create a new UnitOfWork and associate it with the current thread.
-     * <p>
-     * The UnitOfWork will use the default Usecase settings.
-     * </p>
-     * @return a new UnitOfWork
-     */
-    UnitOfWork newUnitOfWork( long currentTime );
-
-    /**
-     * Create a new UnitOfWork for the given Usecase and associate it with the current thread.
-     * <p>
-     * Current time will be set to System.currentTimeMillis();
-     * </p>
-     * @param usecase the Usecase for this UnitOfWork
-     *
-     * @return a new UnitOfWork
-     */
-    UnitOfWork newUnitOfWork( Usecase usecase );
-
-    /**
-     * Create a new UnitOfWork for the given Usecase and associate it with the current thread.
-     *
-     * @param usecase the Usecase for this UnitOfWork
-     *
-     * @return a new UnitOfWork
-     */
-    UnitOfWork newUnitOfWork( Usecase usecase, long currentTime );
-
-    /**
-     * @return true if there is an active UnitOfWork associated with the executing thread
-     */
-    boolean isUnitOfWorkActive();
-
-    /**
-     * Returns the UnitOfWork that is currently associated with the executing thread.
-     *
-     * @return The current UnitOfWork associated with the executing thread
-     *
-     * @throws IllegalStateException if no current UnitOfWork is active
-     */
-    UnitOfWork currentUnitOfWork()
-        throws IllegalStateException;
-
-    /**
-     * Returns the UnitOfWork that the EntityComposite is bound to.
-     *
-     * @param entity the entity to be checked.
-     *
-     * @return The UnitOfWork instance that the Entity is bound to, or null if the entity is not associated with
-     *         any UnitOfWork.
-     */
-    UnitOfWork getUnitOfWork( EntityComposite entity );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkOptions.java b/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkOptions.java
deleted file mode 100644
index 33e544d..0000000
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkOptions.java
+++ /dev/null
@@ -1,43 +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.qi4j.api.unitofwork;
-
-/**
- * Set instances of this in MetaInfo on UnitOfWork or the associated Usecase.
- *  <p>
- * Options:
- *  </p>
- * <p>
- * "pruneOnPause": if true, then clear out all instances that have been loaded in the UoW but not modified
- * </p>
- */
-public class UnitOfWorkOptions
-{
-    private boolean pruneOnPause = false;
-
-    public UnitOfWorkOptions( boolean pruneOnPause )
-    {
-        this.pruneOnPause = pruneOnPause;
-    }
-
-    public boolean isPruneOnPause()
-    {
-        return pruneOnPause;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkTemplate.java b/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkTemplate.java
deleted file mode 100644
index e8663b4..0000000
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/UnitOfWorkTemplate.java
+++ /dev/null
@@ -1,93 +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.qi4j.api.unitofwork;
-
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.usecase.Usecase;
-
-/**
- * UnitOfWork Template.
- */
-public abstract class UnitOfWorkTemplate<RESULT, ThrowableType extends Throwable>
-{
-    private Usecase usecase = Usecase.DEFAULT;
-    private int retries = 10;
-    private boolean complete = true;
-
-    protected UnitOfWorkTemplate()
-    {
-    }
-
-    protected UnitOfWorkTemplate( int retries, boolean complete )
-    {
-        this.retries = retries;
-        this.complete = complete;
-    }
-
-    protected UnitOfWorkTemplate( Usecase usecase, int retries, boolean complete )
-    {
-        this.usecase = usecase;
-        this.retries = retries;
-        this.complete = complete;
-    }
-
-    protected abstract RESULT withUnitOfWork( UnitOfWork uow )
-        throws ThrowableType;
-
-    @SuppressWarnings( "unchecked" )
-    public RESULT withModule( Module module )
-        throws ThrowableType, UnitOfWorkCompletionException
-    {
-        int loop = 0;
-        ThrowableType ex = null;
-        do
-        {
-            UnitOfWork uow = module.newUnitOfWork( usecase );
-
-            try
-            {
-                RESULT result = withUnitOfWork( uow );
-                if( complete )
-                {
-                    try
-                    {
-                        uow.complete();
-                        return result;
-                    }
-                    catch( ConcurrentEntityModificationException e )
-                    {
-                        // Retry?
-                        ex = (ThrowableType) e;
-                    }
-                }
-            }
-            catch( Throwable e )
-            {
-                ex = (ThrowableType) e;
-            }
-            finally
-            {
-                uow.discard();
-            }
-        }
-        while( loop++ < retries );
-
-        throw ex;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/concern/UnitOfWorkConcern.java b/core/api/src/main/java/org/qi4j/api/unitofwork/concern/UnitOfWorkConcern.java
deleted file mode 100644
index c684385..0000000
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/concern/UnitOfWorkConcern.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *  Copyright 2009 Niclas Hedhman.
- *
- * Licensed 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.qi4j.api.unitofwork.concern;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.concern.GenericConcern;
-import org.qi4j.api.injection.scope.Invocation;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.ConcurrentEntityModificationException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.usecase.UsecaseBuilder;
-
-/**
- * {@code UnitOfWorkConcern} manages the unit of work complete, discard and retry policy.
- *
- * @see UnitOfWorkPropagation
- * @see UnitOfWorkDiscardOn
- */
-@AppliesTo( UnitOfWorkPropagation.class )
-public class UnitOfWorkConcern
-    extends GenericConcern
-{
-    private static final Class<?>[] DEFAULT_DISCARD_CLASSES = new Class[]{ Throwable.class };
-
-    @Structure
-    Module module;
-
-    @Invocation
-    UnitOfWorkPropagation propagation;
-
-    /**
-     * Handles method with {@code UnitOfWorkPropagation} annotation.
-     *
-     * @param proxy  The object.
-     * @param method The invoked method.
-     * @param args   The method arguments.
-     *
-     * @return The returned value of method invocation.
-     *
-     * @throws Throwable Thrown if the method invocation throw exception.
-     */
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        UnitOfWorkPropagation.Propagation propagationPolicy = propagation.value();
-        if( propagationPolicy == UnitOfWorkPropagation.Propagation.REQUIRED )
-        {
-            if( module.isUnitOfWorkActive() )
-            {
-                return next.invoke( proxy, method, args );
-            }
-            else
-            {
-                Usecase usecase = usecase();
-                return invokeWithCommit( proxy, method, args, module.newUnitOfWork( usecase ) );
-            }
-        }
-        else if( propagationPolicy == UnitOfWorkPropagation.Propagation.MANDATORY )
-        {
-            if( !module.isUnitOfWorkActive() )
-            {
-                throw new IllegalStateException( "UnitOfWork was required but there is no available unit of work." );
-            }
-        }
-        else if( propagationPolicy == UnitOfWorkPropagation.Propagation.REQUIRES_NEW )
-        {
-            Usecase usecase = usecase();
-            return invokeWithCommit( proxy, method, args, module.newUnitOfWork( usecase ) );
-        }
-        return next.invoke( proxy, method, args );
-    }
-
-    private Usecase usecase()
-    {
-        String usecaseName = propagation.usecase();
-        Usecase usecase;
-        if( usecaseName == null )
-        {
-            usecase = Usecase.DEFAULT;
-        }
-        else
-        {
-            usecase = UsecaseBuilder.newUsecase( usecaseName );
-        }
-        return usecase;
-    }
-
-    protected Object invokeWithCommit( Object proxy, Method method, Object[] args, UnitOfWork currentUnitOfWork )
-        throws Throwable
-    {
-        try
-        {
-            UnitOfWorkRetry retryAnnot = method.getAnnotation( UnitOfWorkRetry.class );
-            int maxTries = 0;
-            long delayFactor = 0;
-            long initialDelay = 0;
-            if( retryAnnot != null )
-            {
-                maxTries = retryAnnot.retries();
-                initialDelay = retryAnnot.initialDelay();
-                delayFactor = retryAnnot.delayFactory();
-            }
-            int retry = 0;
-            while( true )
-            {
-                Object result = next.invoke( proxy, method, args );
-                try
-                {
-                    currentUnitOfWork.complete();
-                    return result;
-                }
-                catch( ConcurrentEntityModificationException e )
-                {
-                    if( retry >= maxTries )
-                    {
-                        throw e;
-                    }
-                    module.currentUnitOfWork().discard();
-                    Thread.sleep( initialDelay + retry * delayFactor );
-                    retry++;
-                    currentUnitOfWork = module.newUnitOfWork( usecase() );
-                }
-            }
-        }
-        catch( Throwable throwable )
-        {
-            // Discard only if this concern create a unit of work
-            discardIfRequired( method, currentUnitOfWork, throwable );
-            throw throwable;
-        }
-    }
-
-    /**
-     * Discard unit of work if the discard policy match.
-     *
-     * @param aMethod     The invoked method. This argument must not be {@code null}.
-     * @param aUnitOfWork The current unit of work. This argument must not be {@code null}.
-     * @param aThrowable  The exception thrown. This argument must not be {@code null}.
-     */
-    protected void discardIfRequired( Method aMethod, UnitOfWork aUnitOfWork, Throwable aThrowable )
-    {
-        UnitOfWorkDiscardOn discardPolicy = aMethod.getAnnotation( UnitOfWorkDiscardOn.class );
-        Class<?>[] discardClasses;
-        if( discardPolicy != null )
-        {
-            discardClasses = discardPolicy.value();
-        }
-        else
-        {
-            discardClasses = DEFAULT_DISCARD_CLASSES;
-        }
-
-        Class<? extends Throwable> aThrowableClass = aThrowable.getClass();
-        for( Class<?> discardClass : discardClasses )
-        {
-            if( discardClass.isAssignableFrom( aThrowableClass ) )
-            {
-                aUnitOfWork.discard();
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/concern/UnitOfWorkDiscardOn.java b/core/api/src/main/java/org/qi4j/api/unitofwork/concern/UnitOfWorkDiscardOn.java
deleted file mode 100644
index 3668736..0000000
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/concern/UnitOfWorkDiscardOn.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.unitofwork.concern;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-/**
- * Annotation to denote the unit of work discard policy.
- * <p>
- * By default, discard is applied on any method that has {@link UnitOfWorkPropagation} and any exception is thrown.
- * </p>
- * <p>
- * Apply {@code UnitOfWorkDiscardOn} to override the default settings.
- * </p>
- * <p>
- * Usage example:
- * </p>
- * <pre>
- * <code>
- *
- * &#64;Concerns( UnitOfWorkConcern.class )
- * public class MyBusinessServiceMixin implements BusinessService
- * {
- *   &#64;Structure UnitOfWorkFactory uowf;
- *
- *   &#64;UnitOfWorkDiscardOn( MyBusinessException.class )
- *   public void myBusinessMethod()
- *   {
- *     // Must invoke current unit of work.
- *     UnitOfWork uow = uowf.currentUnitOfWork();
- *
- *     // Perform business logic
- *   }
- * }
- * </code>
- * </pre>
- *
- * <p>
- * The unit of work will be discarded iff {@code MyBusinessException} exceptions or its subclass is thrown from within
- * {@code myBusinessMethod} method.
- * </p>
- */
-@Retention( RUNTIME )
-@Target( METHOD )
-@Inherited
-@Documented
-public @interface UnitOfWorkDiscardOn
-{
-    Class<? extends Throwable>[] value() default { Throwable.class };
-}
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/concern/UnitOfWorkPropagation.java b/core/api/src/main/java/org/qi4j/api/unitofwork/concern/UnitOfWorkPropagation.java
deleted file mode 100644
index 4fe78b7..0000000
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/concern/UnitOfWorkPropagation.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.unitofwork.concern;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-/**
- * Annotation to denote the unit of work propagation.
- * <p>
- * Usage example:
- * </p>
- * <pre>
- * <code>
- *
- * &#64;Concerns( UnitOfWorkConcern.class )
- * public class MyBusinessServiceMixin implements BusinessService
- * {
- *   &#64;Structure UnitOfWorkFactory uowf;
- *
- *   &#64;UnitOfWorkPropagation
- *   public void myBusinessMethod()
- *   {
- *     // Must invoke current unit of work.
- *     UnitOfWork uow = uowf.currentUnitOfWork();
- *
- *     // Perform business logic
- *   }
- * }
- * </code>
- * </pre>
- */
-@Retention( RUNTIME )
-@Target( METHOD )
-@Inherited
-@Documented
-public @interface UnitOfWorkPropagation
-{
-    Propagation value() default Propagation.REQUIRED;
-
-    String usecase() default "";
-
-    /**
-     * Propagation behaviors.
-     */
-    enum Propagation
-    {
-        /**
-         * Default propagation behavior.
-         * Behavior: <br>
-         * If no current transaction: creates a new UnitOfWork <br>
-         * If there is a current UnitOfWork: use the current UnitOfWork.
-         */
-        REQUIRED,
-
-        /**
-         * Behavior: <br>
-         * If no current UnitOfWork: throw an exception <br>
-         * If there is a current UnitOfWork: use the current UnitOfWork.
-         */
-        MANDATORY,
-
-        /**
-         * Behavior: <br>
-         * If no current UnitOfWork: creates a new UnitOfWork <br>
-         * If there is a current UnitOfWork: suspend the current UnitOfWork and create a new UnitOfWork.
-         */
-        REQUIRES_NEW
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/concern/UnitOfWorkRetry.java b/core/api/src/main/java/org/qi4j/api/unitofwork/concern/UnitOfWorkRetry.java
deleted file mode 100644
index de386f9..0000000
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/concern/UnitOfWorkRetry.java
+++ /dev/null
@@ -1,44 +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.qi4j.api.unitofwork.concern;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-/**
- * This annotation describes the retries that should occur in case of {@link org.qi4j.api.unitofwork.ConcurrentEntityModificationException}
- * occurs.
- */
-@Retention( RUNTIME )
-@Target( METHOD )
-@Inherited
-@Documented
-public @interface UnitOfWorkRetry
-{
-    int retries() default 1;
-
-    long initialDelay() default 0;
-
-    long delayFactory() default 10;
-}
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/concern/package.html b/core/api/src/main/java/org/qi4j/api/unitofwork/concern/package.html
deleted file mode 100644
index 68cbe0e..0000000
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/concern/package.html
+++ /dev/null
@@ -1,24 +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.
--->
-<html>
-    <body>
-        <h2>UnitOfWork Concerns.</h2>
-        <p>
-            UnitOfWork Concerns allow declarative UnitOfWork propagation, discard wrt. exceptions and automatic retry.
-        </p>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/unitofwork/package.html b/core/api/src/main/java/org/qi4j/api/unitofwork/package.html
deleted file mode 100644
index 1bc08fa..0000000
--- a/core/api/src/main/java/org/qi4j/api/unitofwork/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>UnitOfWork API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/usecase/Usecase.java b/core/api/src/main/java/org/qi4j/api/usecase/Usecase.java
deleted file mode 100644
index 415672a..0000000
--- a/core/api/src/main/java/org/qi4j/api/usecase/Usecase.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.usecase;
-
-import java.io.Serializable;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.structure.MetaInfoHolder;
-
-/**
- * A Usecase. A Usecase is used as a model for UnitOfWork, and helps
- * implementations decide what to do in certain circumstances.
- */
-public final class Usecase
-    implements Serializable, MetaInfoHolder
-{
-    public static final Usecase DEFAULT = new Usecase( "Default", new MetaInfo() );
-
-    private static final long serialVersionUID = 1L;
-    private final String name;
-    private final MetaInfo metaInfo;
-
-    Usecase( String name, MetaInfo metaInfo )
-    {
-        this.name = name;
-        this.metaInfo = metaInfo;
-    }
-
-    /**
-     * Name of the usecase.
-     *
-     * @return the name
-     */
-    public String name()
-    {
-        return name;
-    }
-
-    /**
-     * Meta-info for the usecase. This can be of any type, and is typically set when creating the usecase
-     * and read during the execution of the usecase.
-     *
-     * @param infoType the MetaInfo type to retrieve.
-     *
-     * @return the previously stored metaInfo of the given type for the usecase.
-     */
-    @Override
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return metaInfo.get( infoType );
-    }
-
-    @Override
-    public String toString()
-    {
-        return name + ", meta info:" + metaInfo;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/usecase/UsecaseBuilder.java b/core/api/src/main/java/org/qi4j/api/usecase/UsecaseBuilder.java
deleted file mode 100644
index 118b72d..0000000
--- a/core/api/src/main/java/org/qi4j/api/usecase/UsecaseBuilder.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.usecase;
-
-import org.qi4j.api.common.MetaInfo;
-
-/**
- * Builder for Usecases.
- */
-public final class UsecaseBuilder
-{
-    public static UsecaseBuilder buildUsecase( String aName )
-    {
-        return new UsecaseBuilder( aName );
-    }
-
-    public static Usecase newUsecase( String aName )
-    {
-        return new UsecaseBuilder( aName ).newUsecase();
-    }
-
-    private MetaInfo metaInfo = new MetaInfo();
-
-    private String name;
-
-    private UsecaseBuilder( String name )
-    {
-        this.name = name;
-    }
-
-    public UsecaseBuilder withMetaInfo( Object metaInfo )
-    {
-        this.metaInfo.set( metaInfo );
-        return this;
-    }
-
-    public Usecase newUsecase()
-    {
-        return new Usecase( name, metaInfo );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/usecase/package.html b/core/api/src/main/java/org/qi4j/api/usecase/package.html
deleted file mode 100644
index 71c696a..0000000
--- a/core/api/src/main/java/org/qi4j/api/usecase/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Usecase API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/util/Annotations.java b/core/api/src/main/java/org/qi4j/api/util/Annotations.java
deleted file mode 100644
index 8adc5ff..0000000
--- a/core/api/src/main/java/org/qi4j/api/util/Annotations.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.util;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Type;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-
-import static org.qi4j.api.util.Classes.interfacesOf;
-import static org.qi4j.api.util.Classes.typeOf;
-import static org.qi4j.functional.Iterables.flatten;
-import static org.qi4j.functional.Iterables.flattenIterables;
-import static org.qi4j.functional.Iterables.iterable;
-import static org.qi4j.functional.Iterables.map;
-
-/**
- * Useful methods for handling Annotations.
- */
-public final class Annotations
-{
-    public static Function<Type, Iterable<Annotation>> ANNOTATIONS_OF = Classes.forTypes( new Function<Type, Iterable<Annotation>>()
-    {
-        @Override
-        public Iterable<Annotation> map( Type type )
-        {
-            return Iterables.iterable( Classes.RAW_CLASS.map( type ).getAnnotations() );
-        }
-    } );
-
-    public static Specification<AnnotatedElement> hasAnnotation( final Class<? extends Annotation> annotationType )
-    {
-        return new Specification<AnnotatedElement>()
-        {
-            @Override
-            public boolean satisfiedBy( AnnotatedElement element )
-            {
-                return element.getAnnotation( annotationType ) != null;
-            }
-        };
-    }
-
-    public static Function<Annotation, Class<? extends Annotation>> type()
-    {
-        return new Function<Annotation, Class<? extends Annotation>>()
-        {
-            @Override
-            public Class<? extends Annotation> map( Annotation annotation )
-            {
-                return annotation.annotationType();
-            }
-        };
-    }
-
-    public static Specification<Annotation> isType( final Class<? extends Annotation> annotationType )
-    {
-        return new Specification<Annotation>()
-        {
-            @Override
-            public boolean satisfiedBy( Annotation annotation )
-            {
-                return annotation.annotationType().equals( annotationType );
-            }
-        };
-    }
-
-    public static <T extends Annotation> T annotationOn( Type type, Class<T> annotationType )
-    {
-        return annotationType.cast( Classes.RAW_CLASS.map( type ).getAnnotation( annotationType ) );
-    }
-
-    public static Iterable<Annotation> findAccessorAndTypeAnnotationsIn( AccessibleObject accessor )
-    {
-        return flatten( iterable( accessor.getAnnotations() ),
-                        flattenIterables( map( Annotations.ANNOTATIONS_OF, interfacesOf( typeOf( accessor ) ) ) ) );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/util/Base64Encoder.java b/core/api/src/main/java/org/qi4j/api/util/Base64Encoder.java
deleted file mode 100644
index 9246b13..0000000
--- a/core/api/src/main/java/org/qi4j/api/util/Base64Encoder.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright 2009 Alin Dreghiciu.
- *
- * Licensed 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.qi4j.api.util;
-
-/**
- * Base64Encoder.
- */
-public final class Base64Encoder
-{
-
-    /**
-     * Utility class. ment to be used via static methods.
-     */
-    private Base64Encoder()
-    {
-        // utility class
-    }
-
-    /**
-     * Encodes a String into a base 64 String. The resulting encoding is chunked at 76 bytes.
-     *
-     * @param s String to encode.
-     *
-     * @return encoded string.
-     */
-    public static String encode( String s, boolean includePadding )
-    {
-        byte[] sBytes = s.getBytes();
-        sBytes = encode( sBytes, includePadding );
-        s = new String( sBytes );
-        return s;
-    }
-
-    /**
-     * Decodes a base 64 String into a String.
-     *
-     * @param s String to decode.
-     *
-     * @return encoded string.
-     *
-     * @throws java.lang.IllegalArgumentException
-     *          _ If the given byte array was not valid base64 encoding.
-     */
-    public static String decode( String s )
-        throws IllegalArgumentException
-    {
-        s = s.replaceAll( "\n", "" );
-        s = s.replaceAll( "\r", "" );
-        byte[] sBytes = s.getBytes();
-        sBytes = decode( sBytes );
-        s = new String( sBytes );
-        return s;
-    }
-
-    private static final byte[] ALPHASET =
-        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".getBytes();
-
-    private static final int I6O2 = 255 - 3;
-    private static final int O6I2 = 3;
-    private static final int I4O4 = 255 - 15;
-    private static final int O4I4 = 15;
-    private static final int I2O6 = 255 - 63;
-    private static final int O2I6 = 63;
-
-    /**
-     * Encodes a byte array into a base 64 byte array.
-     *
-     * @param dData byte array to encode.
-     *
-     * @return encoded byte array.
-     */
-    public static byte[] encode( byte[] dData, boolean includePadding )
-    {
-        if( dData == null )
-        {
-            throw new IllegalArgumentException( "Cannot encode null" );
-        }
-        byte[] eData = new byte[ ( ( dData.length + 2 ) / 3 ) * 4 ];
-
-        int eIndex = 0;
-        for( int i = 0; i < dData.length; i += 3 )
-        {
-            int d1;
-            int d2 = 0;
-            int d3 = 0;
-            int e1;
-            int e2;
-            int e3;
-            int e4;
-            int pad = 0;
-
-            d1 = dData[ i ];
-            if( ( i + 1 ) < dData.length )
-            {
-                d2 = dData[ i + 1 ];
-                if( ( i + 2 ) < dData.length )
-                {
-                    d3 = dData[ i + 2 ];
-                }
-                else
-                {
-                    pad = 1;
-                }
-            }
-            else
-            {
-                pad = 2;
-            }
-
-            e1 = ALPHASET[ ( d1 & I6O2 ) >> 2 ];
-            e2 = ALPHASET[ ( d1 & O6I2 ) << 4 | ( d2 & I4O4 ) >> 4 ];
-            e3 = ALPHASET[ ( d2 & O4I4 ) << 2 | ( d3 & I2O6 ) >> 6 ];
-            e4 = ALPHASET[ ( d3 & O2I6 ) ];
-
-            eData[ eIndex++ ] = (byte) e1;
-            eData[ eIndex++ ] = (byte) e2;
-            eData[ eIndex++ ] = ( pad < 2 ) ? (byte) e3 : (byte) '=';
-            eData[ eIndex++ ] = ( pad < 1 ) ? (byte) e4 : (byte) '=';
-
-            if( pad > 0 && !includePadding )
-            {
-                byte[] neweData = new byte[ eData.length - pad ];
-                System.arraycopy( eData, 0, neweData, 0, eIndex - pad );
-                eData = neweData;
-            }
-        }
-
-        return eData;
-    }
-
-    private final static int[] CODES = new int[ 256 ];
-
-    static
-    {
-        for( int i = 0; i < CODES.length; i++ )
-        {
-            CODES[ i ] = 64;
-        }
-        for( int i = 0; i < ALPHASET.length; i++ )
-        {
-            CODES[ ALPHASET[ i ] ] = i;
-        }
-    }
-
-    /**
-     * Decodes a base64 byte array into a byte array.
-     * <p>
-     *
-     * @param eData byte array to decode.
-     *
-     * @return decoded byte array.
-     *
-     * @throws java.lang.IllegalArgumentException
-     *          thrown if the given byte array was not valid com.sun.syndication.io.impl.Base64 encoding.
-     */
-    public static byte[] decode( byte[] eData )
-    {
-        if( eData == null )
-        {
-            throw new IllegalArgumentException( "Cannot decode null" );
-        }
-        byte[] cleanEData = eData.clone();
-        int cleanELength = 0;
-        for( byte anEData : eData )
-        {
-            if( anEData < 256 && CODES[ anEData ] < 64 )
-            {
-                cleanEData[ cleanELength++ ] = anEData;
-            }
-        }
-
-        int dLength = ( cleanELength / 4 ) * 3;
-        switch( cleanELength % 4 )
-        {
-        case 3:
-            dLength += 2;
-            break;
-        case 2:
-            dLength++;
-            break;
-        }
-
-        byte[] dData = new byte[ dLength ];
-        int dIndex = 0;
-        for( int i = 0; i < eData.length; i += 4 )
-        {
-            if( ( i + 3 ) > eData.length )
-            {
-                throw new IllegalArgumentException(
-                    "byte array is not a valid base64 encoding"
-                );
-            }
-            int e1 = CODES[ cleanEData[ i ] ];
-            int e2 = CODES[ cleanEData[ i + 1 ] ];
-            int e3 = CODES[ cleanEData[ i + 2 ] ];
-            int e4 = CODES[ cleanEData[ i + 3 ] ];
-            dData[ dIndex++ ] = (byte) ( ( e1 << 2 ) | ( e2 >> 4 ) );
-            if( dIndex < dData.length )
-            {
-                dData[ dIndex++ ] = (byte) ( ( e2 << 4 ) | ( e3 >> 2 ) );
-            }
-            if( dIndex < dData.length )
-            {
-                dData[ dIndex++ ] = (byte) ( ( e3 << 6 ) | ( e4 ) );
-            }
-        }
-        return dData;
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/util/Classes.java b/core/api/src/main/java/org/qi4j/api/util/Classes.java
deleted file mode 100644
index 34f4b05..0000000
--- a/core/api/src/main/java/org/qi4j/api/util/Classes.java
+++ /dev/null
@@ -1,699 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.util;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Array;
-import java.lang.reflect.Field;
-import java.lang.reflect.GenericArrayType;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.lang.reflect.WildcardType;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.qi4j.api.composite.ModelDescriptor;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-
-import static org.qi4j.functional.Iterables.cast;
-import static org.qi4j.functional.Iterables.empty;
-import static org.qi4j.functional.Iterables.flatten;
-import static org.qi4j.functional.Iterables.flattenIterables;
-import static org.qi4j.functional.Iterables.iterable;
-import static org.qi4j.functional.Iterables.map;
-import static org.qi4j.functional.Iterables.matchesAny;
-import static org.qi4j.functional.Iterables.prepend;
-
-/**
- * Useful methods for handling Classes.
- */
-public final class Classes
-{
-    private final static Map<Type, Type> wrapperClasses = new HashMap<>();
-
-    static
-    {
-        wrapperClasses.put( boolean.class, Boolean.class );
-        wrapperClasses.put( byte.class, Byte.class );
-        wrapperClasses.put( short.class, Short.class );
-        wrapperClasses.put( char.class, Character.class );
-        wrapperClasses.put( int.class, Integer.class );
-        wrapperClasses.put( long.class, Long.class );
-        wrapperClasses.put( float.class, Float.class );
-        wrapperClasses.put( double.class, Double.class );
-    }
-
-    private final static Map<Type, Type> primitiveClasses = new HashMap<>();
-
-    static
-    {
-        primitiveClasses.put( boolean.class, Boolean.class );
-        primitiveClasses.put( byte.class, Byte.class );
-        primitiveClasses.put( short.class, Short.class );
-        primitiveClasses.put( char.class, Character.class );
-        primitiveClasses.put( int.class, Integer.class );
-        primitiveClasses.put( long.class, Long.class );
-        primitiveClasses.put( float.class, Float.class );
-        primitiveClasses.put( double.class, Double.class );
-    }
-
-    /**
-     * Convert from primitive class (int, short, double, etc.) to wrapper class (Integer, Short, Double, etc.).
-     * Return the same class if it's not a primitive class. This can therefore safely be used on all types
-     * to ensure that they are not primitives.
-     */
-    private static final Function<Type, Type> WRAPPER_CLASS = new Function<Type, Type>()
-    {
-        @Override
-        public Type map( Type aClass )
-        {
-            Type wrapperClass = wrapperClasses.get( aClass );
-            return wrapperClass == null ? aClass : wrapperClass;
-        }
-    };
-
-    /**
-     * Convert from wrapper class (Integer, Short, Double, etc.) to primitive class (int, short, double, etc.).
-     * Return the same class if it's not a wrapper class. This can therefore safely be used on all types
-     * to ensure that they are primitives if possible.
-     */
-    @SuppressWarnings( "UnusedDeclaration" )
-    private static final Function<Type, Type> PRIMITIVE_CLASS = new Function<Type, Type>()
-    {
-        @Override
-        public Type map( Type aClass )
-        {
-            Type primitiveClass = primitiveClasses.get( aClass );
-            return primitiveClass == null ? aClass : primitiveClass;
-        }
-    };
-
-    /**
-     * Function that extract the raw class of a type.
-     */
-    public static final Function<Type, Class<?>> RAW_CLASS = new Function<Type, Class<?>>()
-    {
-        @Override
-        public Class<?> map( Type genericType )
-        {
-            // Calculate raw type
-            if( genericType instanceof Class )
-            {
-                return (Class<?>) genericType;
-            }
-            else if( genericType instanceof ParameterizedType )
-            {
-                return (Class<?>) ( (ParameterizedType) genericType ).getRawType();
-            }
-            else if( genericType instanceof TypeVariable )
-            {
-                return (Class<?>) ( (TypeVariable) genericType ).getGenericDeclaration();
-            }
-            else if( genericType instanceof WildcardType )
-            {
-                return (Class<?>) ( (WildcardType) genericType ).getUpperBounds()[ 0];
-            }
-            else if( genericType instanceof GenericArrayType )
-            {
-                Object temp = Array.newInstance( (Class<?>) ( (GenericArrayType) genericType ).getGenericComponentType(), 0 );
-                return temp.getClass();
-            }
-            throw new IllegalArgumentException( "Could not extract the raw class of " + genericType );
-        }
-    };
-
-    private static final Function<AccessibleObject, Type> TYPE_OF = new Function<AccessibleObject, Type>()
-    {
-        @Override
-        public Type map( AccessibleObject accessor )
-        {
-            return accessor instanceof Method ? ( (Method) accessor ).getGenericReturnType() : ( (Field) accessor ).getGenericType();
-        }
-    };
-
-    private static final Function<Type, Iterable<Class<?>>> CLASS_HIERARCHY = new Function<Type, Iterable<Class<?>>>()
-    {
-        @Override
-        @SuppressWarnings( {"raw", "unchecked"} )
-        public Iterable<Class<?>> map( Type type )
-        {
-            if( type == null )
-            {
-                return empty();
-            }
-            if( type.equals( Object.class ) )
-            {
-                Class<?> aClass = (Class<?>) type;
-                return cast( iterable( aClass ) );
-            }
-            else
-            {
-                type = RAW_CLASS.map( type );
-                Class superclass = ( (Class) type ).getSuperclass();
-                return prepend( (Class<?>) type, map( superclass ) );
-            }
-        }
-    };
-
-    @SuppressWarnings( "raw" )
-    private static final Function<Type, Iterable<Type>> INTERFACES_OF = new Function<Type, Iterable<Type>>()
-    {
-        @Override
-        public Iterable<Type> map( Type type )
-        {
-            Class clazz = RAW_CLASS.map( type );
-
-            if( clazz.isInterface() )
-            {
-                Iterable<Type> genericInterfaces = iterable( clazz.getGenericInterfaces() );
-                Iterable<Type> flattenIterables = flattenIterables( Iterables.map( INTERFACES_OF, genericInterfaces ) );
-                return prepend( type, flattenIterables );
-            }
-            else
-            {
-                if( type.equals( Object.class ) )
-                {
-                    return iterable( clazz.getGenericInterfaces() );
-                }
-                else
-                {
-                    return flatten( flattenIterables( Iterables.map( INTERFACES_OF,
-                                                                     iterable( clazz.getGenericInterfaces() ) ) ),
-                                    INTERFACES_OF.map( RAW_CLASS.map( type ).getSuperclass() ) );
-                }
-            }
-        }
-    };
-
-    @SuppressWarnings( "raw" )
-    private static final Function<Type, Iterable<Type>> TYPES_OF = new Function<Type, Iterable<Type>>()
-    {
-        @Override
-        public Iterable<Type> map( Type type )
-        {
-            Class clazz = RAW_CLASS.map( type );
-
-            if( clazz.isInterface() )
-            {
-                Iterable<Type> genericInterfaces = iterable( clazz.getGenericInterfaces() );
-                Iterable<Type> flattenIterables = flattenIterables( Iterables.map( INTERFACES_OF, genericInterfaces ) );
-                return prepend( clazz, flattenIterables );
-            }
-            else
-            {
-                return flatten( CLASS_HIERARCHY.map( type ),
-                                flattenIterables( Iterables.map( INTERFACES_OF, CLASS_HIERARCHY.map( type ) ) ) );
-            }
-        }
-    };
-
-    public static Type typeOf( AccessibleObject from )
-    {
-        return TYPE_OF.map( from );
-    }
-
-    public static Iterable<Type> typesOf( Iterable<Type> types )
-    {
-        Iterable<Type> result = empty();
-        for( Type type : types )
-        {
-            result = flatten( result, typesOf( type ) );
-        }
-        return result;
-    }
-
-    public static Iterable<Type> typesOf( Type type )
-    {
-        return TYPES_OF.map( type );
-    }
-
-    public static Iterable<? extends Type> interfacesOf( Iterable<? extends Type> types )
-    {
-        Iterable<Type> result = empty();
-        for( Type type : types )
-        {
-            result = flatten( result, interfacesOf( type ) );
-        }
-        return result;
-    }
-
-    public static Iterable<Type> interfacesOf( Type type )
-    {
-        return INTERFACES_OF.map( type );
-    }
-
-    public static Iterable<Class<?>> classHierarchy( Class<?> type )
-    {
-        return CLASS_HIERARCHY.map( type );
-    }
-
-    public static Type wrapperClass( Type type )
-    {
-        return WRAPPER_CLASS.map( type );
-    }
-
-    public static Specification<Class<?>> isAssignableFrom( final Class clazz )
-    {
-        return new Specification<Class<?>>()
-        {
-            @Override
-            @SuppressWarnings( "unchecked" )
-            public boolean satisfiedBy( Class<?> item )
-            {
-                return clazz.isAssignableFrom( item );
-            }
-        };
-    }
-
-    @SuppressWarnings( "raw" )
-    public static Specification<Object> instanceOf( final Class clazz )
-    {
-        return new Specification<Object>()
-        {
-            @Override
-            public boolean satisfiedBy( Object item )
-            {
-                return clazz.isInstance( item );
-            }
-        };
-    }
-
-    public static Specification<Class<?>> hasModifier( final int classModifier )
-    {
-        return new Specification<Class<?>>()
-        {
-            @Override
-            public boolean satisfiedBy( Class<?> item )
-            {
-                return ( item.getModifiers() & classModifier ) != 0;
-            }
-        };
-    }
-
-    public static <T> Function<Type, Iterable<T>> forClassHierarchy( final Function<Class<?>, Iterable<T>> function )
-    {
-        return new Function<Type, Iterable<T>>()
-        {
-            @Override
-            public Iterable<T> map( Type type )
-            {
-                return flattenIterables( Iterables.map( function, CLASS_HIERARCHY.map( type ) ) );
-            }
-        };
-    }
-
-    public static <T> Function<Type, Iterable<T>> forTypes( final Function<Type, Iterable<T>> function )
-    {
-        return new Function<Type, Iterable<T>>()
-        {
-            @Override
-            public Iterable<T> map( Type type )
-            {
-                return flattenIterables( Iterables.map( function, TYPES_OF.map( type ) ) );
-            }
-        };
-    }
-
-    @SuppressWarnings( "raw" )
-    public static Set<Class<?>> interfacesWithMethods( Set<Class<?>> interfaces )
-    {
-        Set<Class<?>> newSet = new LinkedHashSet<>();
-        for( Class type : interfaces )
-        {
-            if( type.isInterface() && type.getDeclaredMethods().length > 0 )
-            {
-                newSet.add( type );
-            }
-        }
-
-        return newSet;
-    }
-
-    public static String simpleGenericNameOf( Type type )
-    {
-        StringBuilder sb = new StringBuilder();
-        simpleGenericNameOf( sb, type );
-        return sb.toString();
-    }
-
-    @SuppressWarnings( "raw" )
-    private static void simpleGenericNameOf( StringBuilder sb, Type type )
-    {
-        if( type instanceof Class )
-        {
-            sb.append( ( (Class) type ).getSimpleName() );
-        }
-        else if( type instanceof ParameterizedType )
-        {
-            ParameterizedType pt = (ParameterizedType) type;
-            simpleGenericNameOf( sb, pt.getRawType() );
-            sb.append( "<" );
-            boolean atLeastOne = false;
-            for( Type typeArgument : pt.getActualTypeArguments() )
-            {
-                if( atLeastOne )
-                {
-                    sb.append( ", " );
-                }
-                simpleGenericNameOf( sb, typeArgument );
-                atLeastOne = true;
-            }
-            sb.append( ">" );
-        }
-        else if( type instanceof GenericArrayType )
-        {
-            GenericArrayType gat = (GenericArrayType) type;
-            simpleGenericNameOf( sb, gat.getGenericComponentType() );
-            sb.append( "[]" );
-        }
-        else if( type instanceof TypeVariable )
-        {
-            TypeVariable tv = (TypeVariable) type;
-            sb.append( tv.getName() );
-        }
-        else if( type instanceof WildcardType )
-        {
-            WildcardType wt = (WildcardType) type;
-            sb.append( "? extends " );
-            boolean atLeastOne = false;
-            for( Type typeArgument : wt.getUpperBounds() )
-            {
-                if( atLeastOne )
-                {
-                    sb.append( ", " );
-                }
-                simpleGenericNameOf( sb, typeArgument );
-                atLeastOne = true;
-            }
-        }
-        else
-        {
-            throw new IllegalArgumentException( "Don't know how to deal with type:" + type );
-        }
-    }
-
-    @SuppressWarnings( "UnusedDeclaration" )
-    public static <AnnotationType extends Annotation>
-        AnnotationType findAnnotationOfTypeOrAnyOfSuperTypes( Class<?> type, Class<AnnotationType> annotationClass )
-    {
-        AnnotationType result = null;
-        for( Type clazz : Classes.TYPES_OF.map( type ) )
-        {
-            result = Classes.RAW_CLASS.map( clazz ).getAnnotation( annotationClass );
-            if( result != null )
-            {
-                break;
-            }
-        }
-
-        return result;
-    }
-
-    public static Specification<Member> memberNamed( final String name )
-    {
-        return new Specification<Member>()
-        {
-            @Override
-            public boolean satisfiedBy( Member item )
-            {
-                return item.getName().equals( name );
-            }
-        };
-    }
-
-    /**
-     * Given a type variable, find what it resolves to given the declaring class where type
-     * variable was found and a top class that extends the declaring class.
-     *
-     * @param name The TypeVariable name.
-     * @param declaringClass The class where the TypeVariable is declared.
-     * @param topClass The top class that extends the declaringClass
-     *
-     * @return The Type instance of the given TypeVariable
-     */
-    @SuppressWarnings( "raw" )
-    public static Type resolveTypeVariable( TypeVariable name, Class declaringClass, Class topClass )
-    {
-        Type type = resolveTypeVariable( name, declaringClass, new HashMap<TypeVariable, Type>(), topClass );
-        if( type == null )
-        {
-            type = Object.class;
-        }
-        return type;
-    }
-
-    @SuppressWarnings( "raw" )
-    private static Type resolveTypeVariable( TypeVariable name,
-                                             Class declaringClass,
-                                             Map<TypeVariable, Type> mappings,
-                                             Class current
-    )
-    {
-        if( current.equals( declaringClass ) )
-        {
-            Type resolvedType = name;
-            while( resolvedType instanceof TypeVariable )
-            {
-                resolvedType = mappings.get( resolvedType );
-            }
-            return resolvedType;
-        }
-
-        List<Type> types = new ArrayList<>();
-        for( Type type : current.getGenericInterfaces() )
-        {
-            Iterable<Type> interfaces = Classes.INTERFACES_OF.map( type );
-            for( Type anInterface : interfaces )
-            {
-                if( !types.contains( anInterface ) )
-                {
-                    types.add( anInterface );
-                }
-            }
-            types.add( type );
-        }
-
-        if( current.getGenericSuperclass() != null )
-        {
-            types.add( current.getGenericSuperclass() );
-        }
-
-        for( Type type : types )
-        {
-            Class subClass;
-            if( type instanceof ParameterizedType )
-            {
-                ParameterizedType pt = (ParameterizedType) type;
-                Type[] args = pt.getActualTypeArguments();
-                Class clazz = (Class) pt.getRawType();
-                TypeVariable[] vars = clazz.getTypeParameters();
-                for( int i = 0; i < vars.length; i++ )
-                {
-                    TypeVariable var = vars[ i];
-                    Type mappedType = args[ i];
-                    mappings.put( var, mappedType );
-                }
-                subClass = (Class) pt.getRawType();
-            }
-            else
-            {
-                subClass = (Class) type;
-            }
-
-            Type resolvedType = resolveTypeVariable( name, declaringClass, mappings, subClass );
-            if( resolvedType != null )
-            {
-                return resolvedType;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Get URI for a class.
-     *
-     * @param clazz class
-     *
-     * @return URI
-     *
-     * @throws NullPointerException if clazz is null
-     */
-    @SuppressWarnings( "raw" )
-    public static String toURI( final Class clazz )
-        throws NullPointerException
-    {
-        return toURI( clazz.getName() );
-    }
-
-    /**
-     * Get URI for a class name.
-     * <p>
-     * Example:
-     * </p>
-     * <p>
-     * Class name com.example.Foo$Bar is converted to URI urn:qi4j:com.example.Foo-Bar
-     * </p>
-     *
-     * @param className class name
-     *
-     * @return URI
-     *
-     * @throws NullPointerException if className is null
-     */
-    public static String toURI( String className )
-        throws NullPointerException
-    {
-        className = normalizeClassToURI( className );
-        return "urn:qi4j:type:" + className;
-    }
-
-    /**
-     * Get class name from a URI
-     *
-     * @param uri URI
-     *
-     * @return class name
-     *
-     * @throws NullPointerException if uri is null
-     */
-    public static String toClassName( String uri )
-        throws NullPointerException
-    {
-        uri = uri.substring( "urn:qi4j:type:".length() );
-        uri = denormalizeURIToClass( uri );
-        return uri;
-    }
-
-    public static String normalizeClassToURI( String className )
-    {
-        return className.replace( '$', '-' );
-    }
-
-    public static String denormalizeURIToClass( String uriPart )
-    {
-        return uriPart.replace( '-', '$' );
-    }
-
-    public static Specification<ModelDescriptor> modelTypeSpecification( final String className )
-    {
-        return new Specification<ModelDescriptor>()
-        {
-            @Override
-            public boolean satisfiedBy( ModelDescriptor item )
-            {
-                return matchesAny( new Specification<String>()
-                {
-                    @Override
-                    public boolean satisfiedBy( String item )
-                    {
-                        return item.equals( className );
-                    }
-                }, map( new Function<Class<?>, String>()
-                {
-                    @Override
-                    public String map( Class<?> item )
-                    {
-                        return item.getName();
-                    }
-                }, item.types() ) );
-            }
-        };
-    }
-
-    @SuppressWarnings( "raw" )
-    public static Specification<ModelDescriptor> exactTypeSpecification( final Class type )
-    {
-        return new Specification<ModelDescriptor>()
-        {
-            @Override
-            public boolean satisfiedBy( ModelDescriptor item )
-            {
-                return matchesAny( new Specification<Class<?>>()
-                {
-                    @Override
-                    public boolean satisfiedBy( Class<?> item )
-                    {
-                        return item.equals( type );
-                    }
-                }, item.types() );
-            }
-        };
-    }
-
-    @SuppressWarnings( "raw" )
-    public static Specification<ModelDescriptor> assignableTypeSpecification( final Class type )
-    {
-        return new Specification<ModelDescriptor>()
-        {
-            @Override
-            public boolean satisfiedBy( ModelDescriptor item )
-            {
-                return matchesAny( new Specification<Class<?>>()
-                {
-                    @Override
-                    @SuppressWarnings( "unchecked" )
-                    public boolean satisfiedBy( Class<?> itemType )
-                    {
-                        return !type.equals( itemType ) && type.isAssignableFrom( itemType );
-                    }
-                }, item.types() );
-            }
-        };
-    }
-
-    @SuppressWarnings( "raw" )
-    public static String toString( Iterable<? extends Class> type )
-    {
-        StringBuilder builder = new StringBuilder();
-        builder.append( "[" );
-        boolean first = true;
-        for( Class c : type )
-        {
-            if( !first )
-            {
-                builder.append( "," );
-            }
-            first = false;
-            builder.append( c.getSimpleName() );
-        }
-        builder.append( "]" );
-        return builder.toString();
-    }
-
-    public static Function<Type, String> toClassName()
-    {
-        return new Function<Type, String>()
-        {
-            @Override
-            public String map( Type type )
-            {
-                return RAW_CLASS.map( type ).getName();
-            }
-        };
-    }
-
-    private Classes()
-    {
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/util/Constructors.java b/core/api/src/main/java/org/qi4j/api/util/Constructors.java
deleted file mode 100644
index 17062ca..0000000
--- a/core/api/src/main/java/org/qi4j/api/util/Constructors.java
+++ /dev/null
@@ -1,40 +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.qi4j.api.util;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Type;
-import org.qi4j.functional.Function;
-
-import static org.qi4j.functional.Iterables.iterable;
-
-/**
- * Useful methods for handling Constructors.
- */
-public final class Constructors
-{
-    public static final Function<Type, Iterable<Constructor<?>>> CONSTRUCTORS_OF = Classes.forClassHierarchy( new Function<Class<?>, Iterable<Constructor<?>>>()
-    {
-        @Override
-        public Iterable<Constructor<?>> map( Class<?> type )
-        {
-            return iterable( type.getDeclaredConstructors() );
-        }
-    } );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/util/Dates.java b/core/api/src/main/java/org/qi4j/api/util/Dates.java
deleted file mode 100644
index 3324df2..0000000
--- a/core/api/src/main/java/org/qi4j/api/util/Dates.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.api.util;
-
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.TimeZone;
-
-/**
- * Useful methods for handling Dates.
- */
-public final class Dates
-{
-    // Formatters are not thread-safe. Create one per thread
-    private static final ThreadLocal<DateFormat> ISO8601 = new ThreadLocal<DateFormat>()
-    {
-        @Override
-        protected DateFormat initialValue()
-        {
-            return new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss.SSSZ" );
-        }
-    };
-
-    private static final ThreadLocal<DateFormat> ISO8601_UTC = new ThreadLocal<DateFormat>()
-    {
-        @Override
-        protected DateFormat initialValue()
-        {
-            SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" );
-            dateFormat.setTimeZone( TimeZone.getTimeZone( "UTC" ) );
-            return dateFormat;
-        }
-    };
-
-    /**
-     * @param stringDate a string representing a date as either ISO8601, @millis@ or /Date() formats
-     * @return a Date
-     */
-    public static Date fromString( String stringDate )
-    {
-        try
-        {
-            Date date = ISO8601_UTC.get().parse( stringDate );
-            return date;
-        }
-        catch( ParseException e )
-        {
-            try
-            {
-                Date date = ISO8601.get().parse( stringDate );
-                return date;
-            }
-            catch( ParseException e1 )
-            {
-                // @millis@ format
-                if( stringDate.startsWith( "@" ) && stringDate.endsWith( "@" ) )
-                {
-                    long time = Long.parseLong( stringDate.substring( 1, stringDate.length() - 1 ) );
-                    Date date = new Date( time );
-                    return date;
-                }
-                else if( stringDate.startsWith( "/Date(" ) && stringDate.endsWith( ")/" ) ) // Microsoft format
-                {
-                    long time = Long.parseLong( stringDate.substring( 6, stringDate.length() - 2 ) );
-                    Date date = new Date( time );
-                    return date;
-                }
-                throw new IllegalStateException( "Illegal date:" + stringDate );
-            }
-        }
-    }
-
-    /**
-     * @param date a Date
-     * @return String representation in ISO8601 UTC
-     */
-    public static String toUtcString( Date date )
-    {
-        return ISO8601_UTC.get().format( date );
-    }
-
-    private Dates()
-    {
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/util/Fields.java b/core/api/src/main/java/org/qi4j/api/util/Fields.java
deleted file mode 100644
index c68d131..0000000
--- a/core/api/src/main/java/org/qi4j/api/util/Fields.java
+++ /dev/null
@@ -1,51 +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.qi4j.api.util;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Type;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Function2;
-import org.qi4j.functional.Iterables;
-
-import static org.qi4j.functional.Iterables.iterable;
-
-/**
- * Useful methods for handling Fields.
- */
-public final class Fields
-{
-    public static final Function2<Class<?>, String, Field> FIELD_NAMED = new Function2<Class<?>, String, Field>()
-    {
-        @Override
-        public Field map( Class<?> aClass, String name )
-        {
-            return Iterables.first( Iterables.filter( Classes.memberNamed( name ), FIELDS_OF.map( aClass ) ) );
-        }
-    };
-
-    public static final Function<Type, Iterable<Field>> FIELDS_OF = Classes.forClassHierarchy( new Function<Class<?>, Iterable<Field>>()
-    {
-        @Override
-        public Iterable<Field> map( Class<?> type )
-        {
-            return iterable( type.getDeclaredFields() );
-        }
-    } );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/util/ListMap.java b/core/api/src/main/java/org/qi4j/api/util/ListMap.java
deleted file mode 100644
index 56778b8..0000000
--- a/core/api/src/main/java/org/qi4j/api/util/ListMap.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.util;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Map whose values are Lists of things. Create
- * one ArrayList for each key that is added. The list does not allow
- * duplicates.
- */
-public final class ListMap<K, V>
-    extends HashMap<K, List<V>>
-{
-    public void add( K key, V value )
-    {
-        List<V> list = get( key );
-        if( list == null )
-        {
-            list = new ArrayList<V>();
-            put( key, list );
-        }
-        if( !list.contains( value ) )
-        {
-            list.add( value );
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/util/Methods.java b/core/api/src/main/java/org/qi4j/api/util/Methods.java
deleted file mode 100644
index 93b78cf..0000000
--- a/core/api/src/main/java/org/qi4j/api/util/Methods.java
+++ /dev/null
@@ -1,50 +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.qi4j.api.util;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Specification;
-
-import static org.qi4j.functional.Iterables.iterable;
-
-/**
- * Useful methods for handling Methods.
- */
-public class Methods
-{
-    public static final Specification<Type> HAS_METHODS = new Specification<Type>()
-    {
-        @Override
-        public boolean satisfiedBy( Type item )
-        {
-            return Classes.RAW_CLASS.map( item ).getDeclaredMethods().length > 0;
-        }
-    };
-
-    public static final Function<Type, Iterable<Method>> METHODS_OF = Classes.forTypes( new Function<Type, Iterable<Method>>()
-    {
-        @Override
-        public Iterable<Method> map( Type type )
-        {
-            return iterable( Classes.RAW_CLASS.map( type ).getDeclaredMethods() );
-        }
-    } );
-}
diff --git a/core/api/src/main/java/org/qi4j/api/util/NullArgumentException.java b/core/api/src/main/java/org/qi4j/api/util/NullArgumentException.java
deleted file mode 100644
index 58e514f..0000000
--- a/core/api/src/main/java/org/qi4j/api/util/NullArgumentException.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*  Copyright 2007 Niclas Hedhman.
- *
- * Licensed 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.qi4j.api.util;
-
-/**
- * Thrown if an argument to a method was null, and the method required
- * it to be non-null.
- */
-public class NullArgumentException
-    extends IllegalArgumentException
-{
-    private static final long serialVersionUID = 4815431779868729780L;
-
-    private NullArgumentException( String message )
-    {
-        super( message );
-    }
-
-    public static void validateNotNull( String parameterName, Object value )
-    {
-        if( value != null )
-        {
-            return;
-        }
-        String message = parameterName + " was null.";
-        throw new NullArgumentException( message );
-    }
-
-    public static void validateNotEmpty( String parameterName, String value )
-    {
-        if( value == null )
-        {
-            String message = parameterName + " was null.";
-            throw new NullArgumentException( message );
-        }
-        if( value.length() == 0 )
-        {
-            String message = parameterName + " was empty.";
-            throw new NullArgumentException( message );
-        }
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/util/package.html b/core/api/src/main/java/org/qi4j/api/util/package.html
deleted file mode 100644
index ea75db3..0000000
--- a/core/api/src/main/java/org/qi4j/api/util/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>API Utilities.</h2>
-    </body>
-</html>
diff --git a/core/api/src/main/java/org/qi4j/api/value/NoSuchValueException.java b/core/api/src/main/java/org/qi4j/api/value/NoSuchValueException.java
deleted file mode 100644
index 256e9fc..0000000
--- a/core/api/src/main/java/org/qi4j/api/value/NoSuchValueException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.value;
-
-import org.qi4j.api.composite.NoSuchCompositeException;
-
-/**
- * Thrown when no visible value of the requested type is found.
- */
-public class NoSuchValueException
-    extends NoSuchCompositeException
-{
-    public NoSuchValueException( String valueType, String moduleName )
-    {
-        super( "ValueComposite", valueType, moduleName );
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueBuilder.java b/core/api/src/main/java/org/qi4j/api/value/ValueBuilder.java
deleted file mode 100644
index 1073a0d..0000000
--- a/core/api/src/main/java/org/qi4j/api/value/ValueBuilder.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.value;
-
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.common.ConstructionException;
-
-/**
- * Builder for Values.
- */
-public interface ValueBuilder<T>
-{
-    AssociationStateHolder state();
-
-    /**
-     * Get a representation of the state for the new Value.
-     * It is possible to access and update properties and associations,
-     * even immutable ones since the builder represents the initial state.
-     *
-     * @return a mutable instance of the Value type
-     */
-    T prototype();
-
-    /**
-     * Get a representation of the state of the given type for the new ValueComposite.
-     * This is primarily used if you want to provide state for a private mixin type.
-     *
-     * @param mixinType the mixin which you want to provide state for
-     *
-     * @return a proxy implementing the given mixin type
-     */
-    <K> K prototypeFor( Class<K> mixinType );
-
-    /**
-     * Create a new Composite instance.
-     *
-     * @return a new Composite instance
-     *
-     * @throws org.qi4j.api.common.ConstructionException
-     *          thrown if it was not possible to instantiate the Composite
-     */
-    T newInstance()
-        throws ConstructionException;
-}
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueBuilderFactory.java b/core/api/src/main/java/org/qi4j/api/value/ValueBuilderFactory.java
deleted file mode 100644
index 57c4e29..0000000
--- a/core/api/src/main/java/org/qi4j/api/value/ValueBuilderFactory.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.value;
-
-import java.util.Map;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.functional.Function;
-
-/**
- * Factory for Values and ValueBuilders.
- */
-public interface ValueBuilderFactory
-{
-
-    /**
-     * Instantiate a Value of the given type.
-     *
-     * @param valueType the Value type to instantiate
-     *
-     * @return a new Value instance
-     *
-     * @throws NoSuchValueException if no value extending the mixinType has been registered
-     * @throws ConstructionException if the value could not be instantiated
-     */
-    <T> T newValue( Class<T> valueType )
-        throws NoSuchValueException, ConstructionException;
-
-    /**
-     * Create a builder for creating new Values that implements the given Value type.
-     * <p>The returned ValueBuilder can be reused to create several Values instances.</p>
-     *
-     * @param valueType an interface that describes the Composite to be instantiated
-     *
-     * @return a ValueBuilder for creation of ValueComposites implementing the interface
-     *
-     * @throws NoSuchValueException if no value extending the mixinType has been registered
-     */
-    <T> ValueBuilder<T> newValueBuilder( Class<T> valueType )
-        throws NoSuchValueException;
-
-    /**
-     * Create a builder for creating a new Value starting with the given prototype.
-     * <p>The returned ValueBuilder can only be used ONCE.</p>
-     *
-     * @param prototype a prototype the builder will use
-     *
-     * @return a ValueBuilder for creation of ValueComposites implementing the interface of the prototype
-     *
-     * @throws NoSuchValueException if no value extending the mixinType has been registered
-     */
-    <T> ValueBuilder<T> newValueBuilderWithPrototype( T prototype );
-
-    /**
-     * Create a builder for creating a new Value starting with the given state.
-     * <p>The returned ValueBuilder can only be used ONCE.</p>
-     *
-     * @param mixinType an interface that describes the Composite to be instantiated
-     * @param propertyFunction a function providing the state of properties
-     * @param associationFunction a function providing the state of associations
-     * @param manyAssociationFunction a function providing the state of many associations
-     * @param namedAssociationFunction a function providing the state of named associations
-     *
-     * @return a ValueBuilder for creation of ValueComposites implementing the interface
-     *
-     * @throws NoSuchValueException if no value extending the mixinType has been registered
-     */
-    <T> ValueBuilder<T> newValueBuilderWithState( Class<T> mixinType,
-                                                  Function<PropertyDescriptor, Object> propertyFunction,
-                                                  Function<AssociationDescriptor, EntityReference> associationFunction,
-                                                  Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction,
-                                                  Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction );
-
-    /**
-     * Instantiate a Value of the given type using the serialized state given as String.
-     *
-     * @param valueType the Value type to instantiate
-     * @param serializedState  the state of the Value
-     *
-     * @return a new Value instance
-     *
-     * @throws NoSuchValueException if no value extending the mixinType has been registered
-     * @throws ConstructionException if the value could not be instantiated
-     */
-    <T> T newValueFromSerializedState( Class<T> valueType, String serializedState );
-
-}
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueBuilderTemplate.java b/core/api/src/main/java/org/qi4j/api/value/ValueBuilderTemplate.java
deleted file mode 100644
index 11cbddb..0000000
--- a/core/api/src/main/java/org/qi4j/api/value/ValueBuilderTemplate.java
+++ /dev/null
@@ -1,43 +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.qi4j.api.value;
-
-import org.qi4j.api.structure.Module;
-
-/**
- * Builder template for Values.
- */
-public abstract class ValueBuilderTemplate<T>
-{
-    Class<T> type;
-
-    protected ValueBuilderTemplate( Class<T> type )
-    {
-        this.type = type;
-    }
-
-    protected abstract void build( T prototype );
-
-    public T newInstance( Module module )
-    {
-        ValueBuilder<T> builder = module.newValueBuilder( type );
-        build( builder.prototype() );
-        return builder.newInstance();
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueComposite.java b/core/api/src/main/java/org/qi4j/api/value/ValueComposite.java
deleted file mode 100644
index 7d5f48f..0000000
--- a/core/api/src/main/java/org/qi4j/api/value/ValueComposite.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.value;
-
-import org.qi4j.api.association.AssociationMixin;
-import org.qi4j.api.association.ManyAssociationMixin;
-import org.qi4j.api.association.NamedAssociationMixin;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Immutable;
-
-/**
- * ValueComposites are Composites that has state, and equality is defined from its values and not any identity nor
- * instance references.
- *
- * <ul>
- * <li>No Identity</li>
- * <li>No Lifecycle</li>
- * <li>Immutable</li>
- * <li>equals()/hashCode() operates on the Properties</li>
- * <li>Can have property and associations methods.</li>
- * <li>Can not reference Services</li>
- * <li>Can not have @Uses</li>
- * </ul>
- */
-@Immutable
-@Mixins( { AssociationMixin.class, ManyAssociationMixin.class, NamedAssociationMixin.class } )
-public interface ValueComposite
-    extends Composite
-{
-}
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueDescriptor.java b/core/api/src/main/java/org/qi4j/api/value/ValueDescriptor.java
deleted file mode 100644
index 710de89..0000000
--- a/core/api/src/main/java/org/qi4j/api/value/ValueDescriptor.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.value;
-
-import org.qi4j.api.association.AssociationStateDescriptor;
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.composite.StatefulCompositeDescriptor;
-import org.qi4j.api.type.ValueCompositeType;
-
-/**
- * Descriptor for ValueComposites.
- */
-public interface ValueDescriptor
-    extends CompositeDescriptor, StatefulCompositeDescriptor
-{
-    ValueCompositeType valueType();
-
-    @Override
-    AssociationStateDescriptor state();
-}
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueDeserializer.java b/core/api/src/main/java/org/qi4j/api/value/ValueDeserializer.java
deleted file mode 100644
index 175b176..0000000
--- a/core/api/src/main/java/org/qi4j/api/value/ValueDeserializer.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.value;
-
-import java.io.InputStream;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Function2;
-
-/**
- * Use a ValueDeserializer to create new values instances from serialized state.
- *
- * <p>
- *     Serialized state must be one of:
- * </p>
- * <ul>
- *     <li>a ValueComposite,</li>
- *     <li>an EntityReference,</li>
- *     <li>a Collection,</li>
- *     <li>a Map,</li>
- *     <li>a Plain Value.</li>
- * </ul>
- * <p>
- *     Nested plain values, EntityReferences, Collections, Maps, ValueComposites are supported.
- *     EntityReferences are deserialized as their identity string.
- * </p>
- * <p>
- *     Plain values can be one of:
- * </p>
- * <ul>
- *     <li>String,</li>
- *     <li>Character or char,</li>
- *     <li>Boolean or boolean,</li>
- *     <li>Integer or int,</li>
- *     <li>Long or long,</li>
- *     <li>Short or short,</li>
- *     <li>Byte or byte,</li>
- *     <li>Float or float,</li>
- *     <li>Double or double,</li>
- *     <li>BigInteger,</li>
- *     <li>BigDecimal,</li>
- *     <li>Date,</li>
- *     <li>DateTime (JodaTime),</li>
- *     <li>LocalDateTime (JodaTime),</li>
- *     <li>LocalDate (JodaTime).</li>
- * </ul>
- * <p>
- *     Values of unknown types and all arrays are considered as {@link java.io.Serializable} and by so are deserialized
- *     from base64 encoded bytes using pure Java serialization. If it happens that the input is invalid, a
- *     ValueSerializationException is thrown.
- * </p>
- * <p>
- *     Having type information in the serialized payload allows to keep actual ValueComposite types and by so
- *     circumvent {@link org.qi4j.api.composite.AmbiguousTypeException} when deserializing.
- * </p>
- */
-public interface ValueDeserializer
-{
-
-    /**
-     * Factory method for a typed deserialize function.
-     *
-     * <p>The returned Function may throw {@link ValueSerializationException}.</p>
-     *
-     * @param type the value type
-     * @param <T> the parametrized function return type
-     * @return a deserialization function
-     */
-    <T> Function<String, T> deserialize( Class<T> type );
-
-    /**
-     * Factory method for a typed deserialize function.
-     *
-     * <p>The returned Function may throw {@link ValueSerializationException}.</p>
-     *
-     * @param valueType the value type
-     * @param <T> the parametrized function return type
-     * @return a deserialization function
-     */
-    <T> Function<String, T> deserialize( ValueType valueType );
-
-    /**
-     * Factory method for an untyped deserialize function.
-     *
-     * <p>The returned Function may throw {@link ValueSerializationException}.</p>
-     *
-     * @param <T> the parametrized function return type
-     * @return a deserialization function
-     */
-    <T> Function2<ValueType, String, T> deserialize();
-
-    /**
-     * Deserialize a value from a state.
-     *
-     * @param <T> the parametrized returned type
-     * @param type the value type
-     * @param input the state
-     * @return the value
-     * @throws ValueSerializationException if the deserialization failed
-     */
-    <T> T deserialize( Class<?> type, String input )
-        throws ValueSerializationException;
-
-    /**
-     * Deserialize a value from a state.
-     *
-     * @param <T> the parametrized returned type
-     * @param valueType the value type
-     * @param input the state
-     * @return the value
-     * @throws ValueSerializationException if the deserialization failed
-     */
-    <T> T deserialize( ValueType valueType, String input )
-        throws ValueSerializationException;
-
-    /**
-     * Deserialize a value from a state.
-     *
-     * @param <T> the parametrized returned type
-     * @param type the value type
-     * @param input the state stream
-     * @return the value
-     * @throws ValueSerializationException if the deserialization failed
-     */
-    <T> T deserialize( Class<?> type, InputStream input )
-        throws ValueSerializationException;
-
-    /**
-     * Deserialize a value from a state.
-     *
-     * @param <T> the parametrized returned type
-     * @param valueType the value type
-     * @param input the state stream
-     * @return the value
-     * @throws ValueSerializationException if the deserialization failed
-     */
-    <T> T deserialize( ValueType valueType, InputStream input )
-        throws ValueSerializationException;
-}
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueSerialization.java b/core/api/src/main/java/org/qi4j/api/value/ValueSerialization.java
deleted file mode 100644
index 31a4af0..0000000
--- a/core/api/src/main/java/org/qi4j/api/value/ValueSerialization.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.value;
-
-/**
- * ValueSerialization API.
- *
- * See {@link ValueSerializer} and {@link ValueDeserializer}.
- */
-public interface ValueSerialization
-    extends ValueSerializer, ValueDeserializer
-{
-
-    /**
-     * Serialization format @Service tags.
-     *
-     * <p>
-     *     ValueSerialization implementations should be tagged with theses at assembly time so that consumers can
-     *     specify which format they need.
-     * </p>
-     */
-    interface Formats
-    {
-
-        /**
-         * Tag a ValueSerialization service that support the JSON format.
-         */
-        String JSON = "json";
-        /**
-         * Tag a ValueSerialization service that support the XML format.
-         */
-        String XML = "xml";
-        /**
-         * Tag a ValueSerialization service that support the YAML format.
-         */
-        String YAML = "yaml";
-    }
-
-}
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueSerializationException.java b/core/api/src/main/java/org/qi4j/api/value/ValueSerializationException.java
deleted file mode 100644
index e1f3d44..0000000
--- a/core/api/src/main/java/org/qi4j/api/value/ValueSerializationException.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.value;
-
-/**
- * Thrown when an error occur during value state (de)serialization.
- */
-public class ValueSerializationException
-    extends RuntimeException
-{
-
-    private static final long serialVersionUID = 1L;
-
-    public ValueSerializationException()
-    {
-        super();
-    }
-
-    public ValueSerializationException( String message )
-    {
-        super( message );
-    }
-
-    public ValueSerializationException( String message, Throwable cause )
-    {
-        super( message, cause );
-    }
-
-    public ValueSerializationException( Throwable cause )
-    {
-        super( cause.getClass().getName() + ": " + cause.getMessage(), cause );
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueSerializer.java b/core/api/src/main/java/org/qi4j/api/value/ValueSerializer.java
deleted file mode 100644
index 337c37e..0000000
--- a/core/api/src/main/java/org/qi4j/api/value/ValueSerializer.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.value;
-
-import java.io.OutputStream;
-import java.util.HashMap;
-import java.util.Map;
-import org.qi4j.api.composite.AmbiguousTypeException;
-import org.qi4j.functional.Function;
-
-/**
- * Use a ValueSerializer to serialize values state.
- *
- * <p>
- *     Serialized object must be one of:
- * </p>
- * <ul>
- *     <li>a ValueComposite,</li>
- *     <li>an EntityComposite or EntityReference,</li>
- *     <li>an Iterable,</li>
- *     <li>a Map,</li>
- *     <li>a Plain Value.</li>
- * </ul>
- * <p>
- *     Nested plain values, EntityReferences, Iterables, Maps, ValueComposites and EntityComposites are supported.
- *     EntityComposites and EntityReferences are serialized as their identity string.
- * </p>
- * <p>
- *     Plain values can be one of:
- * </p>
- * <ul>
- *     <li>String,</li>
- *     <li>Character or char,</li>
- *     <li>Boolean or boolean,</li>
- *     <li>Integer or int,</li>
- *     <li>Long or long,</li>
- *     <li>Short or short,</li>
- *     <li>Byte or byte,</li>
- *     <li>Float or float,</li>
- *     <li>Double or double,</li>
- *     <li>BigInteger,</li>
- *     <li>BigDecimal,</li>
- *     <li>Date,</li>
- *     <li>DateTime (JodaTime),</li>
- *     <li>LocalDateTime (JodaTime),</li>
- *     <li>LocalDate (JodaTime).</li>
- * </ul>
- * <p>
- *     Values of unknown types and all arrays are considered as {@link java.io.Serializable} and by so are serialized to
- *     base64 encoded bytes using pure Java serialization. If it happens that the value is not Serializable, a
- *     ValueSerializationException is thrown.
- * </p>
- * <p>
- *     Having type information in the serialized payload allows to keep actual ValueComposite types and by so
- *     circumvent {@link AmbiguousTypeException} when deserializing.
- * </p>
- */
-public interface ValueSerializer
-{
-
-    /**
-     * Factory method for a serialize function.
-     *
-     * @param <T> the parametrized function input type
-     * @return a serialization function.
-     */
-    <T> Function<T, String> serialize();
-
-    /**
-     * Factory method for a serialize function.
-     *
-     * @param <T> the parametrized function input type
-     * @param options ValueSerializer Options
-     * @return a serialization function.
-     */
-    <T> Function<T, String> serialize( Options options );
-
-    /**
-     * Factory method for a serialize function.
-     *
-     * @param <T> the parametrized function input type
-     * @param includeTypeInfo if type information should be included in the output
-     * @return a serialization function.
-     */
-    @Deprecated
-    <T> Function<T, String> serialize( boolean includeTypeInfo );
-
-    /**
-     * Serialize the state of a value with type information.
-     *
-     * @param object an Object to serialize
-     * @return the state
-     * @throws ValueSerializationException if the Value serialization failed
-     */
-    String serialize( Object object )
-        throws ValueSerializationException;
-
-    /**
-     * Serialize the state of a value.
-     *
-     * @param options ValueSerializer Options
-     * @param object an Object to serialize
-     * @return the state
-     * @throws ValueSerializationException if the Value serialization failed
-     */
-    String serialize( Options options, Object object )
-        throws ValueSerializationException;
-
-    /**
-     * Serialize the state of a value.
-     *
-     * @param object an Object to serialize
-     * @param includeTypeInfo if type information should be included in the output
-     * @return the state
-     * @throws ValueSerializationException if the Value serialization failed
-     */
-    @Deprecated
-    String serialize( Object object, boolean includeTypeInfo )
-        throws ValueSerializationException;
-
-    /**
-     * Serialize the state of a value with type information.
-     *
-     * @param object an Object to serialize
-     * @param output that will be used as output
-     * @throws ValueSerializationException if the Value serialization failed
-     */
-    void serialize( Object object, OutputStream output )
-        throws ValueSerializationException;
-
-    /**
-     * Serialize the state of a value.
-     *
-     * @param options ValueSerializer Options
-     * @param object an Object to serialize
-     * @param output that will be used as output
-     * @throws ValueSerializationException if the Value serialization failed
-     */
-    void serialize( Options options, Object object, OutputStream output )
-        throws ValueSerializationException;
-
-    /**
-     * Serialize the state of a value.
-     *
-     * @param object an Object to serialize
-     * @param output that will be used as output
-     * @param includeTypeInfo if type information should be included in the output
-     * @throws ValueSerializationException if the Value serialization failed
-     */
-    @Deprecated
-    void serialize( Object object, OutputStream output, boolean includeTypeInfo )
-        throws ValueSerializationException;
-
-    /**
-     * Serialization options.
-     */
-    final class Options
-    {
-        /**
-         * Boolean flag to include type information.
-         * Default to TRUE.
-         */
-        public static final String INCLUDE_TYPE_INFO = "includeTypeInfo";
-        public static final String MAP_ENTRIES_AS_OBJECTS = "mapentriesasobjects";
-        private final Map<String, String> options = new HashMap<>();
-
-        /**
-         * Create new default ValueSerializer Options.
-         */
-        public Options()
-        {
-            this.options.put( INCLUDE_TYPE_INFO, "true" );
-            this.options.put( MAP_ENTRIES_AS_OBJECTS, "false" );
-        }
-
-        /**
-         * Set {@link #INCLUDE_TYPE_INFO} option to TRUE.
-         * @return This
-         */
-        public Options withTypeInfo()
-        {
-            return put( INCLUDE_TYPE_INFO, true );
-        }
-
-        /**
-         * Set {@link #INCLUDE_TYPE_INFO} option to FALSE.
-         * @return This
-         */
-        public Options withoutTypeInfo()
-        {
-            return put( INCLUDE_TYPE_INFO, false );
-        }
-
-        public Options withMapEntriesAsObjects()
-        {
-            return put( MAP_ENTRIES_AS_OBJECTS, true );
-        }
-
-        public Options withMapEntriesAsKeyValuePairs()
-        {
-            return put( MAP_ENTRIES_AS_OBJECTS, false );
-        }
-
-        /**
-         * Get Boolean option value.
-         * @param option The option
-         * @return The boolean value of the option, or null if absent
-         */
-        public Boolean getBoolean( String option )
-        {
-            if( !options.containsKey( option ) )
-            {
-                return null;
-            }
-            return Boolean.valueOf( options.get( option ) );
-        }
-
-        /**
-         * Get Integer option value.
-         * @param option The option
-         * @return The integer value of the option, or null if absent
-         */
-        public Integer getInteger( String option )
-        {
-            if( !options.containsKey( option ) )
-            {
-                return null;
-            }
-            return Integer.valueOf( options.get( option ) );
-        }
-
-        /**
-         * Get String option value.
-         * @param option The option
-         * @return The string value of the option, or null if absent
-         */
-        public String getString( String option )
-        {
-            return options.get( option );
-        }
-
-        /**
-         * Put an option String value.
-         * @param option The option
-         * @param value The value
-         * @return This Options instance
-         */
-        public Options put( String option, String value )
-        {
-            if( value == null )
-            {
-                return remove( option );
-            }
-            options.put( option, value );
-            return this;
-        }
-
-        /**
-         * Put an option boolean value.
-         * @param option The option
-         * @param value The value
-         * @return This Options instance
-         */
-        public Options put( String option, Boolean value )
-        {
-            if( value == null )
-            {
-                return remove( option );
-            }
-            options.put( option, Boolean.toString( value ) );
-            return this;
-        }
-
-        /**
-         * Put an option Integer value.
-         * @param option The option
-         * @param value The value
-         * @return This Options instance
-         */
-        public Options put( String option, Integer value )
-        {
-            if( value == null )
-            {
-                return remove( option );
-            }
-            options.put( option, value.toString() );
-            return this;
-        }
-
-        /**
-         * Remove an option value.
-         * @param option The option
-         * @return This Options instance
-         */
-        public Options remove( String option )
-        {
-            options.remove( option );
-            return this;
-        }
-
-        /**
-         * Get all defined options as a Map.
-         * @return All defined options in a new Map
-         */
-        public Map<String, String> toMap()
-        {
-            return new HashMap<>( options );
-        }
-    }
-}
diff --git a/core/api/src/main/java/org/qi4j/api/value/package.html b/core/api/src/main/java/org/qi4j/api/value/package.html
deleted file mode 100644
index 540b3f6..0000000
--- a/core/api/src/main/java/org/qi4j/api/value/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Value API.</h2>
-    </body>
-</html>
diff --git a/core/api/src/test/java/org/apache/polygene/api/OperatorsTest.java b/core/api/src/test/java/org/apache/polygene/api/OperatorsTest.java
new file mode 100644
index 0000000..123e726
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/OperatorsTest.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.polygene.api;
+
+import java.util.Collections;
+import java.util.function.Predicate;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryExpressions;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * TODO
+ */
+public class OperatorsTest
+{
+    @Test
+    public void testOperators()
+        throws UnitOfWorkCompletionException, ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                new EntityTestAssembler().assemble( module );
+
+                module.entities( TestEntity.class );
+                module.values( TestValue.class );
+                module.forMixin( TestEntity.class ).declareDefaults().foo().set( "Bar" );
+                module.forMixin( TestValue.class ).declareDefaults().bar().set( "Xyz" );
+                new DefaultUnitOfWorkAssembler().assemble( module );
+            }
+        };
+
+        UnitOfWorkFactory uowf = assembler.module().unitOfWorkFactory();
+        UnitOfWork uow = uowf.newUnitOfWork();
+
+        try
+        {
+            EntityBuilder<TestEntity> entityBuilder = uow.newEntityBuilder( TestEntity.class, new StringIdentity( "123" ) );
+            entityBuilder.instance().value().set( assembler.module().newValue( TestValue.class ) );
+            TestEntity testEntity = entityBuilder.newInstance();
+
+            uow.complete();
+            uow = uowf.newUnitOfWork();
+
+            Iterable<TestEntity> entities = Collections.singleton( testEntity = uow.get( testEntity ) );
+
+            QueryBuilder<TestEntity> builder = assembler.module().newQueryBuilder( TestEntity.class );
+
+            {
+                Predicate<Composite> where = QueryExpressions.eq( QueryExpressions.templateFor( TestEntity.class )
+                                                                          .foo(), "Bar" );
+                Assert.assertTrue( where.test( testEntity ) );
+                System.out.println( where );
+            }
+            {
+                Predicate<Composite> where = QueryExpressions.eq( QueryExpressions.templateFor( TestEntity.class )
+                                                                          .value()
+                                                                          .get()
+                                                                          .bar(), "Xyz" );
+                Assert.assertTrue( where.test( testEntity ) );
+                System.out.println( where );
+
+                Assert.assertTrue( builder.where( where ).newQuery( entities ).find().equals( testEntity ) );
+            }
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    public interface TestEntity
+        extends EntityComposite
+    {
+        Property<String> foo();
+
+        Property<TestValue> value();
+    }
+
+    public interface TestValue
+        extends ValueComposite
+    {
+        Property<String> bar();
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/activation/ActivationEventsTest.java b/core/api/src/test/java/org/apache/polygene/api/activation/ActivationEventsTest.java
new file mode 100644
index 0000000..b5c09f7
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/activation/ActivationEventsTest.java
@@ -0,0 +1,294 @@
+/*
+ *  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.polygene.api.activation;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivationEvent.EventType;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+import static org.junit.Assert.*;
+import static org.apache.polygene.api.activation.ActivationEvent.EventType.*;
+
+public class ActivationEventsTest
+{
+
+    public static interface TestService
+    {
+        void test();
+    }
+
+    public static class TestServiceInstance
+            implements TestService
+    {
+
+        @Override
+        public void test()
+        {
+        }
+
+    }
+
+    @Mixins( TestServiceInstance.class )
+    public static interface TestServiceComposite
+        extends TestService, ServiceComposite
+    {
+    }
+
+    @Test
+    public void testSingleModuleSingleService()
+        throws Exception
+    {
+        final List<ActivationEvent> events = new ArrayList<>();
+
+        new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.services( TestServiceComposite.class ).instantiateOnStartup();
+            }
+
+            @Override
+            protected void beforeActivation( Application application )
+            {
+                application.registerActivationEventListener( new EventsRecorder( events ) );
+            }
+
+
+        }.application().passivate();
+
+        Iterator<ActivationEvent> it = events.iterator();
+
+        // Activation
+        assertEvent( it.next(), ACTIVATING, "Application" );
+        assertEvent( it.next(), ACTIVATING, "Layer" );
+        assertEvent( it.next(), ACTIVATING, "Module" );
+        assertEvent( it.next(), ACTIVATING, "TestService" );
+        assertEvent( it.next(), ACTIVATED, "TestService" );
+        assertEvent( it.next(), ACTIVATED, "Module" );
+        assertEvent( it.next(), ACTIVATED, "Layer" );
+        assertEvent( it.next(), ACTIVATED, "Application" );
+
+        // Passivation
+        assertEvent( it.next(), PASSIVATING, "Application" );
+        assertEvent( it.next(), PASSIVATING, "Layer" );
+        assertEvent( it.next(), PASSIVATING, "Module" );
+        assertEvent( it.next(), PASSIVATING, "TestService" );
+        assertEvent( it.next(), PASSIVATED, "TestService" );
+        assertEvent( it.next(), PASSIVATED, "Module" );
+        assertEvent( it.next(), PASSIVATED, "Layer" );
+        assertEvent( it.next(), PASSIVATED, "Application" );
+
+        assertFalse( it.hasNext() );
+    }
+
+    @Test
+    public void testSingleModuleSingleImportedService()
+            throws Exception
+    {
+        final List<ActivationEvent> events = new ArrayList<>();
+
+        new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.importedServices( TestService.class ).
+                        setMetaInfo( new TestServiceInstance() ).
+                        importOnStartup();
+            }
+
+            @Override
+            protected void beforeActivation( Application application )
+            {
+                application.registerActivationEventListener( new EventsRecorder( events ) );
+            }
+
+
+        }.application().passivate();
+
+        Iterator<ActivationEvent> it = events.iterator();
+
+        // Activation
+        assertEvent( it.next(), ACTIVATING, "Application" );
+        assertEvent( it.next(), ACTIVATING, "Layer" );
+        assertEvent( it.next(), ACTIVATING, "Module" );
+        assertEvent( it.next(), ACTIVATING, "TestService" );
+        assertEvent( it.next(), ACTIVATED, "TestService" );
+        assertEvent( it.next(), ACTIVATED, "Module" );
+        assertEvent( it.next(), ACTIVATED, "Layer" );
+        assertEvent( it.next(), ACTIVATED, "Application" );
+
+        // Passivation
+        assertEvent( it.next(), PASSIVATING, "Application" );
+        assertEvent( it.next(), PASSIVATING, "Layer" );
+        assertEvent( it.next(), PASSIVATING, "Module" );
+        assertEvent( it.next(), PASSIVATING, "TestService" );
+        assertEvent( it.next(), PASSIVATED, "TestService" );
+        assertEvent( it.next(), PASSIVATED, "Module" );
+        assertEvent( it.next(), PASSIVATED, "Layer" );
+        assertEvent( it.next(), PASSIVATED, "Application" );
+
+        assertFalse( it.hasNext() );
+    }
+
+    @Test
+    public void testSingleModuleSingleLazyService()
+            throws Exception
+    {
+        final List<ActivationEvent> events = new ArrayList<>();
+
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                module.services( TestServiceComposite.class );
+            }
+
+            @Override
+            protected void beforeActivation( Application application )
+            {
+                application.registerActivationEventListener( new EventsRecorder( events ) );
+            }
+
+        };
+        Application application = assembler.application();
+        application.passivate();
+
+        Iterator<ActivationEvent> it = events.iterator();
+
+        // Activation
+        assertEvent( it.next(), ACTIVATING, "Application" );
+        assertEvent( it.next(), ACTIVATING, "Layer" );
+        assertEvent( it.next(), ACTIVATING, "Module" );
+        // Lazy Service NOT activated
+        assertEvent( it.next(), ACTIVATED, "Module" );
+        assertEvent( it.next(), ACTIVATED, "Layer" );
+        assertEvent( it.next(), ACTIVATED, "Application" );
+
+        // Passivation
+        assertEvent( it.next(), PASSIVATING, "Application" );
+        assertEvent( it.next(), PASSIVATING, "Layer" );
+        assertEvent( it.next(), PASSIVATING, "Module" );
+        // Lazy Service NOT passivated
+        assertEvent( it.next(), PASSIVATED, "Module" );
+        assertEvent( it.next(), PASSIVATED, "Layer" );
+        assertEvent( it.next(), PASSIVATED, "Application" );
+
+        assertFalse( it.hasNext() );
+
+        events.clear();
+        application.activate();
+        Module module = assembler.module();
+        module.findService( TestService.class ).get().test();
+        application.passivate();
+
+        for( ActivationEvent event : events ) {
+            System.out.println( event );
+        }
+
+        it = events.iterator();
+
+        // Activation
+        assertEvent( it.next(), ACTIVATING, "Application" );
+        assertEvent( it.next(), ACTIVATING, "Layer" );
+        assertEvent( it.next(), ACTIVATING, "Module" );
+        assertEvent( it.next(), ACTIVATED, "Module" );
+        assertEvent( it.next(), ACTIVATED, "Layer" );
+        assertEvent( it.next(), ACTIVATED, "Application" );
+
+        // Lazy Service Activation
+        assertEvent( it.next(), ACTIVATING, "TestService" );
+        assertEvent( it.next(), ACTIVATED, "TestService" );
+
+        // Passivation
+        assertEvent( it.next(), PASSIVATING, "Application" );
+        assertEvent( it.next(), PASSIVATING, "Layer" );
+        assertEvent( it.next(), PASSIVATING, "Module" );
+        assertEvent( it.next(), PASSIVATING, "TestService" );
+        assertEvent( it.next(), PASSIVATED, "TestService" );
+        assertEvent( it.next(), PASSIVATED, "Module" );
+        assertEvent( it.next(), PASSIVATED, "Layer" );
+        assertEvent( it.next(), PASSIVATED, "Application" );
+
+        assertFalse( it.hasNext() );
+    }
+
+    private static class EventsRecorder
+            implements ActivationEventListener
+    {
+
+        private final List<ActivationEvent> events;
+
+        private EventsRecorder( List<ActivationEvent> events )
+        {
+            this.events = events;
+        }
+
+        @Override
+        public void onEvent( ActivationEvent event )
+        {
+            events.add( event );
+        }
+
+    }
+
+    // WARN This assertion depends on ApplicationInstance, LayerInstance, ModuleInstance and ServiceReferenceInstance toString() method.
+    private static void assertEvent( ActivationEvent event, EventType expectedType, String expected )
+    {
+        boolean wrongEvent = expectedType != event.type();
+        boolean wrongMessage = ! event.message().contains( expected );
+        if( wrongEvent || wrongMessage )
+        {
+            StringBuilder sb = new StringBuilder();
+            sb.append("Event (").append( event ).append( ") has");
+            if( wrongEvent )
+            {
+                sb.append( " wrong type (expected:'" ).append( expectedType ).
+                        append( "' but was:'" ).append( event.type() ).append( "')" );
+                if( wrongMessage )
+                {
+                    sb.append( ";" );
+                }
+            }
+            if( wrongMessage )
+            {
+                sb.append( " wrong message (expected:'" ).append( expected ).
+                        append( "' but was:'" ).append( event.message() ).append( "')" );
+            }
+            fail( sb.toString() );
+        }
+    }
+
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/activation/PassivationExceptionTest.java b/core/api/src/test/java/org/apache/polygene/api/activation/PassivationExceptionTest.java
new file mode 100644
index 0000000..ba7bca9
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/activation/PassivationExceptionTest.java
@@ -0,0 +1,214 @@
+/*
+ *  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.polygene.api.activation;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.Collections;
+import org.junit.Test;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.builder.ApplicationBuilder;
+
+import static org.hamcrest.core.StringContains.containsString;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class PassivationExceptionTest
+{
+    private static String stack( Exception ex )
+    {
+        StringWriter writer = new StringWriter();
+        ex.printStackTrace( new PrintWriter( writer ) );
+        return writer.toString();
+    }
+
+    @Test
+    public void testEmptyPassivationException()
+    {
+        PassivationException empty = new PassivationException( Collections.emptyList() );
+        assertThat( empty.getMessage(), containsString( "has 0 cause" ) );
+    }
+
+    @Test
+    public void testSinglePassivationException()
+    {
+        PassivationException single = new PassivationException( Collections.singletonList( new Exception( "single" ) ) );
+        String stack = stack( single );
+        assertThat( single.getMessage(), containsString( "has 1 cause" ) );
+        assertThat( stack, containsString( "Suppressed: java.lang.Exception: single" ) );
+    }
+
+    @Test
+    public void testMultiplePassivationException()
+    {
+        PassivationException multi = new PassivationException( Arrays.asList( new Exception( "one" ),
+                                                                              new Exception( "two" ),
+                                                                              new Exception( "three" ) ) );
+        String stack = stack( multi );
+        assertThat( multi.getMessage(), containsString( "has 3 cause(s)" ) );
+        assertThat( stack, containsString( "Suppressed: java.lang.Exception: one" ) );
+        assertThat( stack, containsString( "Suppressed: java.lang.Exception: two" ) );
+        assertThat( stack, containsString( "Suppressed: java.lang.Exception: three" ) );
+    }
+
+    @Test
+    public void testPassivationExceptionsAccrossStructure()
+        throws AssemblyException, ActivationException
+    {
+        ApplicationBuilder appBuilder = new ApplicationBuilder( "TestApplication" );
+        appBuilder.withLayer( "Layer 1" ).withModule( "Module A" ).withAssembler( new Assembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.services( TestService.class ).
+                    identifiedBy( "TestService_Module.A" ).
+                    withActivators( FailBeforePassivationServiceActivator.class ).
+                    instantiateOnStartup();
+            }
+        } );
+        appBuilder.withLayer( "Layer 2" ).withModule( "Module B" ).withAssembler( new Assembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.services( TestService.class ).
+                    identifiedBy( "TestService_Module.B" ).
+                    withActivators( FailAfterPassivationServiceActivator.class ).
+                    instantiateOnStartup();
+            }
+        } );
+        appBuilder.registerActivationEventListener( new TestActivationEventListener() );
+
+        Application app = appBuilder.newApplication();
+
+        try
+        {
+            Module moduleA = app.findModule( "Layer 1", "Module A" );
+            TestService service = moduleA.findService( TestService.class ).get();
+            assertThat( service.hello(), equalTo( "Hello Polygene!" ) );
+        }
+        finally
+        {
+            try
+            {
+                app.passivate();
+                fail( "No PassivationException" );
+            }
+            catch( PassivationException ex )
+            {
+                ex.printStackTrace();
+                String stack = stack( ex );
+                assertThat( ex.getMessage(), containsString( "has 12 cause(s)" ) );
+                assertThat( stack, containsString( "EVENT: FAIL BEFORE PASSIVATION for TestApplication" ) );
+                assertThat( stack, containsString( "EVENT: FAIL BEFORE PASSIVATION for Layer 2" ) );
+                assertThat( stack, containsString( "EVENT: FAIL BEFORE PASSIVATION for Module B" ) );
+                assertThat( stack, containsString( "ACTIVATOR: FAIL AFTER PASSIVATION for TestService_Module.B(active=false,module='Module B')" ) );
+                assertThat( stack, containsString( "EVENT: FAIL AFTER PASSIVATION for Module B" ) );
+                assertThat( stack, containsString( "EVENT: FAIL AFTER PASSIVATION for Layer 2" ) );
+                assertThat( stack, containsString( "EVENT: FAIL BEFORE PASSIVATION for Layer 1" ) );
+                assertThat( stack, containsString( "EVENT: FAIL BEFORE PASSIVATION for Module A" ) );
+                assertThat( stack, containsString( "ACTIVATOR: FAIL BEFORE PASSIVATION for TestService_Module.A(active=true,module='Module A')" ) );
+                assertThat( stack, containsString( "EVENT: FAIL AFTER PASSIVATION for Module A" ) );
+                assertThat( stack, containsString( "EVENT: FAIL AFTER PASSIVATION for Layer 1" ) );
+                assertThat( stack, containsString( "EVENT: FAIL AFTER PASSIVATION for TestApplication" ) );
+            }
+        }
+    }
+
+    @Mixins( TestService.Mixin.class )
+    public interface TestService
+    {
+        String hello();
+
+        static class Mixin
+            implements TestService
+        {
+            @Structure
+            private Module module;
+
+            @Override
+            public String hello()
+            {
+                module.name();
+                return "Hello Polygene!";
+            }
+        }
+
+    }
+
+    public static class FailBeforePassivationServiceActivator
+        extends ActivatorAdapter<ServiceReference<TestService>>
+    {
+        @Override
+        public void beforePassivation( ServiceReference<TestService> passivated )
+            throws Exception
+        {
+            throw new Exception( "ACTIVATOR: FAIL BEFORE PASSIVATION for " + passivated );
+        }
+    }
+
+    public static class FailAfterPassivationServiceActivator
+        extends ActivatorAdapter<ServiceReference<TestService>>
+    {
+        @Override
+        public void afterPassivation( ServiceReference<TestService> passivated )
+            throws Exception
+        {
+            throw new Exception( "ACTIVATOR: FAIL AFTER PASSIVATION for " + passivated );
+        }
+    }
+
+    public static class TestActivationEventListener
+        implements ActivationEventListener
+    {
+        @Override
+        public void onEvent( ActivationEvent event )
+            throws Exception
+        {
+            if( !( event.source() instanceof Application )
+                && !( event.source() instanceof Layer )
+                && !( event.source() instanceof Module ) )
+            {
+                return;
+            }
+            switch( event.type() )
+            {
+                case PASSIVATING:
+                    throw new Exception( "EVENT: FAIL BEFORE PASSIVATION for " + event.source() );
+                case PASSIVATED:
+                    throw new Exception( "EVENT: FAIL AFTER PASSIVATION for " + event.source() );
+            }
+        }
+    }
+
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/annotation/MixinsTest.java b/core/api/src/test/java/org/apache/polygene/api/annotation/MixinsTest.java
new file mode 100644
index 0000000..ffffffb
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/annotation/MixinsTest.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.api.annotation;
+
+import java.lang.annotation.Annotation;
+import org.junit.Test;
+import org.apache.polygene.api.mixin.Mixins;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Tests public api exposed by Mixins annotation.
+ * This will ensure that the public api does not get changed by mistake.
+ */
+public class MixinsTest
+{
+
+    @Test
+    public void retention()
+    {
+        Annotation[] annotations = Annotated.class.getDeclaredAnnotations();
+        assertNotNull( "annotations should not be null", annotations );
+        assertEquals( "number of annotations", 1, annotations.length );
+        assertEquals( "annotation type", Mixins.class, annotations[ 0 ].annotationType() );
+    }
+
+    @Mixins( Object.class )
+    private static class Annotated
+    {
+
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/annotation/ModifiedByTest.java b/core/api/src/test/java/org/apache/polygene/api/annotation/ModifiedByTest.java
new file mode 100644
index 0000000..8c8064d
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/annotation/ModifiedByTest.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.api.annotation;
+
+import java.lang.annotation.Annotation;
+import org.junit.Test;
+import org.apache.polygene.api.concern.Concerns;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Tests public api exposed by Concerns annotation.
+ * This will ensure that the public api does not get changed by mistake.
+ */
+public class ModifiedByTest
+{
+
+    @Test
+    public void retention()
+    {
+        Annotation[] annotations = Annotated.class.getDeclaredAnnotations();
+        assertNotNull( "annotations should not be null", annotations );
+        assertEquals( "number of annotations", 1, annotations.length );
+        assertEquals( "annotation type", Concerns.class, annotations[ 0 ].annotationType() );
+    }
+
+    @Concerns( Object.class )
+    private static class Annotated
+    {
+
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/annotation/scope/ModifiesTest.java b/core/api/src/test/java/org/apache/polygene/api/annotation/scope/ModifiesTest.java
new file mode 100644
index 0000000..a1d037e
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/annotation/scope/ModifiesTest.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.api.annotation.scope;
+
+import java.lang.annotation.Annotation;
+import org.junit.Test;
+import org.apache.polygene.api.concern.internal.ConcernFor;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Tests public api exposed by Modified annotation.
+ * This will ensure that the public api does not get changed by mistake.
+ */
+public class ModifiesTest
+{
+
+    @Test
+    public void retention()
+        throws NoSuchFieldException
+    {
+        Annotation[] annotations = Annotated.class.getDeclaredField( "modified" ).getDeclaredAnnotations();
+        assertNotNull( "annotations should not be null", annotations );
+        assertEquals( "number of annotations", 1, annotations.length );
+        assertEquals( "annotation type", ConcernFor.class, annotations[ 0 ].annotationType() );
+    }
+
+    private static class Annotated
+    {
+        @ConcernFor
+        String modified;
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/common/AppliesToTest.java b/core/api/src/test/java/org/apache/polygene/api/common/AppliesToTest.java
new file mode 100644
index 0000000..500544c
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/common/AppliesToTest.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.api.common;
+
+import java.lang.annotation.Annotation;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Tests public api exposed by AppliesTo annotation.
+ * This will ensure that the public api does not get changed by mistake.
+ */
+public class AppliesToTest
+{
+
+    @Test
+    public void retention()
+    {
+        Annotation[] annotations = Annotated.class.getDeclaredAnnotations();
+        assertNotNull( "annotations should not be null", annotations );
+        assertEquals( "number of annotations", 1, annotations.length );
+        assertEquals( "annotation type", AppliesTo.class, annotations[ 0 ].annotationType() );
+    }
+
+    @AppliesTo( Object.class )
+    private static class Annotated
+    {
+
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/common/QualifiedNameTest.java b/core/api/src/test/java/org/apache/polygene/api/common/QualifiedNameTest.java
new file mode 100644
index 0000000..d1f9086
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/common/QualifiedNameTest.java
@@ -0,0 +1,83 @@
+/*
+ *  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.polygene.api.common;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class QualifiedNameTest
+{
+    @Test
+    public void testQualifiedNameWithDollar()
+    {
+        assertEquals( "Name containing dollar is modified", "Test-Test",
+                      new QualifiedName( TypeName.nameOf( "Test$Test" ), "satisfiedBy" ).type() );
+    }
+
+    @Test
+    public void testQualifiedNameFromQNWithDollar()
+    {
+        assertEquals( "Name containing dollar is cleaned up", "Test-Test",
+                      QualifiedName.fromFQN( "Test$Test:satisfiedBy" ).type() );
+    }
+
+    @Test( expected = NullPointerException.class )
+    public void nonNullArguments1()
+    {
+        new QualifiedName( TypeName.nameOf( "Test" ), null );
+    }
+
+    @Test( expected = NullPointerException.class )
+    public void nonNullArguments2()
+    {
+        new QualifiedName( null, "satisfiedBy" );
+    }
+
+    @Test( expected = NullPointerException.class )
+    public void nonNullArguments3()
+    {
+        new QualifiedName( null, null );
+    }
+
+    @Test( expected = NullPointerException.class )
+    public void nonNullArguments4()
+    {
+        QualifiedName.fromFQN( null );
+    }
+
+    @Test( expected = NullPointerException.class )
+    public void nonNullArguments5()
+    {
+        QualifiedName.fromAccessor( null );
+    }
+
+    @Test( expected = NullPointerException.class )
+    public void nonNullArguments6()
+    {
+        QualifiedName.fromClass( null, "satisfiedBy" );
+    }
+
+    @Test( expected = NullPointerException.class )
+    public void nonNullArguments7()
+    {
+        QualifiedName.fromClass( null, null );
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/composite/PropertyMapperTest.java b/core/api/src/test/java/org/apache/polygene/api/composite/PropertyMapperTest.java
new file mode 100644
index 0000000..d285102
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/composite/PropertyMapperTest.java
@@ -0,0 +1,238 @@
+/*
+ *  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.polygene.api.composite;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class PropertyMapperTest
+{
+    private final static Method MAP_TO_TYPE;
+
+    static
+    {
+        try
+        {
+            MAP_TO_TYPE = PropertyMapper.class.getDeclaredMethod( "mapToType", Composite.class, Type.class, Object.class );
+            MAP_TO_TYPE.setAccessible( true );
+        }
+        catch( NoSuchMethodException e )
+        {
+            throw new InternalError( e );
+        }
+    }
+
+    @Test
+    public void testMappingOfInteger()
+        throws Exception
+    {
+        assertEquals( 5, mapToType( null, Integer.class, "5" ) );
+        assertEquals( -5, mapToType( null, Integer.class, "-5" ) );
+        assertEquals( Integer.class, mapToType( null, Integer.class, "5" ).getClass() );
+    }
+
+    @Test
+    public void testMappingOfLong()
+        throws Exception
+    {
+        assertEquals( 5L, mapToType( null, Long.class, "5" ) );
+        assertEquals( 5876328476238746238L, mapToType( null, Long.class, "5876328476238746238" ) );
+        assertEquals( Long.class, mapToType( null, Long.class, "5" ).getClass() );
+    }
+
+    @Test
+    public void testMappingOfBoolean()
+        throws Exception
+    {
+        assertEquals( false, mapToType( null, Boolean.class, "false" ) );
+        assertEquals( true, mapToType( null, Boolean.class, "true" ) );
+        assertEquals( Boolean.class, mapToType( null, Boolean.class, "false" ).getClass() );
+    }
+
+    @Test
+    public void testMappingOfFloat()
+        throws Exception
+    {
+        assertEquals( 5.1234f, mapToType( null, Float.class, "5.1234" ) );
+        assertEquals( 5876328476.6238f, mapToType( null, Float.class, "5876328476.6238" ) );
+        assertEquals( Float.class, mapToType( null, Float.class, "5" ).getClass() );
+    }
+
+    @Test
+    public void testMappingOfDouble()
+        throws Exception
+    {
+        assertEquals( 5.1234, mapToType( null, Double.class, "5.1234" ) );
+        assertEquals( 5876328476.623823, mapToType( null, Double.class, "5876328476.623823" ) );
+        assertEquals( Double.class, mapToType( null, Double.class, "5" ).getClass() );
+    }
+
+    @Test
+    public void testMappingOfBigDecimal()
+        throws Exception
+    {
+        assertEquals( new BigDecimal( 3 ), mapToType( null, BigDecimal.class, "3" ) );
+        assertEquals( new BigDecimal( "12345.67891011" ), mapToType( null, BigDecimal.class, "12345.67891011" ) );
+        assertEquals( BigDecimal.class, mapToType( null, BigDecimal.class, "5" ).getClass() );
+    }
+
+    @Test
+    public void testMappingOfBigInteger()
+        throws Exception
+    {
+        assertEquals( new BigInteger( "20", 16 ), mapToType( null, BigInteger.class, "32" ) );
+        assertEquals( new BigInteger( "1234567891011" ), mapToType( null, BigInteger.class, "1234567891011" ) );
+        assertEquals( BigInteger.class, mapToType( null, BigInteger.class, "5" ).getClass() );
+    }
+
+    @Test
+    public void testMappingOfEnum()
+        throws Exception
+    {
+        assertEquals( TestEnum.FIRST, mapToType( null, TestEnum.class, "FIRST" ) );
+        assertEquals( TestEnum.SECOND, mapToType( null, TestEnum.class, "SECOND" ) );
+        assertEquals( TestEnum.class, mapToType( null, TestEnum.class, "SECOND" ).getClass() );
+    }
+
+    @Test
+    public void testMappingOfIntegerArray()
+        throws Exception
+    {
+        Object[] value = (Object[]) mapToType( null, Integer[].class, "5,4 , 3   ,2,1" );
+        assertEquals( 5, value.length );
+        assertEquals( 5, value[ 0 ] );
+        assertEquals( 4, value[ 1 ] );
+        assertEquals( 3, value[ 2 ] );
+        assertEquals( 2, value[ 3 ] );
+        assertEquals( 1, value[ 4 ] );
+    }
+
+    @Test
+    public void testMappingOfStringArray()
+        throws Exception
+    {
+        {
+            Object[] value = (Object[]) mapToType( null, String[].class, "5,4 , 3   ,2,1" );
+            assertEquals( 5, value.length );
+            assertEquals( "5", value[ 0 ] );
+            assertEquals( "4 ", value[ 1 ] );
+            assertEquals( " 3   ", value[ 2 ] );
+            assertEquals( "2", value[ 3 ] );
+            assertEquals( "1", value[ 4 ] );
+        }
+        {
+            Object[] value = (Object[]) mapToType( null, String[].class, "5,4 ,\" 3,   \",  \" 2\" ,1" );
+            assertEquals( "5", value[ 0 ] );
+            assertEquals( "4 ", value[ 1 ] );
+            assertEquals( " 3,   ", value[ 2 ] );
+            assertEquals( " 2", value[ 3 ] );
+            assertEquals( "1", value[ 4 ] );
+            assertEquals( 5, value.length );
+        }
+    }
+
+    @Test
+    public void testMappingOfBooleanArray()
+        throws Exception
+    {
+        Object[] value = (Object[]) mapToType( null, Boolean[].class, " true,false,  false, true ,true,false" );
+        assertEquals( true, value[ 0 ] );
+        assertEquals( false, value[ 1 ] );
+        assertEquals( false, value[ 2 ] );
+        assertEquals( true, value[ 3 ] );
+        assertEquals( true, value[ 4 ] );
+        assertEquals( false, value[ 5 ] );
+        assertEquals( 6, value.length );
+    }
+
+    @Test
+    public void testMappingOfList()
+        throws Exception
+    {
+        Type type = Testing.class.getDeclaredMethod( "list" ).getGenericReturnType();
+        List<String> value = (List<String>) mapToType( null, type, "5,4 ,\" 3,   \",  \" 2\" ,1" );
+        assertEquals( "5", value.get( 0 ) );
+        assertEquals( "4 ", value.get( 1 ) );
+        assertEquals( " 3,   ", value.get( 2 ) );
+        assertEquals( " 2", value.get( 3 ) );
+        assertEquals( "1", value.get( 4 ) );
+        assertEquals( 5, value.size() );
+    }
+
+    @Test
+    public void testMappingOfSet()
+        throws Exception
+    {
+        Type type = Testing.class.getDeclaredMethod( "set" ).getGenericReturnType();
+        Set<String> value = (Set<String>) mapToType( null, type, "5,4 ,\" 3,   \",  \" 2\" ,1" );
+        assertTrue( value.contains( "5" ) );
+        assertTrue( value.contains( "4 " ) );
+        assertTrue( value.contains( " 3,   " ) );
+        assertTrue( value.contains( " 2" ) );
+        assertTrue( value.contains( "1" ) );
+        assertEquals( 5, value.size() );
+    }
+
+    @Test
+    public void testMappingOfMap()
+        throws Exception
+    {
+        Type type = Testing.class.getDeclaredMethod( "map" ).getGenericReturnType();
+        Map<String, String> value = (Map<String, String>) mapToType( null, type, "first:5,second:4 , third:\" 3,   \", fourth:  \" 2\" ,fifth : 1" );
+        assertEquals( "5", value.get( "first" ) );
+        assertEquals( "4 ", value.get( "second" ) );
+        assertEquals( " 3,   ", value.get( " third" ) );
+        assertEquals( " 2", value.get( " fourth" ) );
+        assertEquals( " 1", value.get( "fifth " ) );
+        assertEquals( 5, value.size() );
+    }
+
+    private Object mapToType( Composite composite, Type propertyType, Object value )
+        throws IllegalAccessException, InvocationTargetException
+    {
+        return MAP_TO_TYPE.invoke( null, composite, propertyType, value );
+    }
+
+    interface Testing
+    {
+        List<String> list();
+
+        Set<String> set();
+
+        Map<String, String> map();
+    }
+
+    enum TestEnum
+    {
+        FIRST,
+        SECOND
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/concern/DocumentationSupport.java b/core/api/src/test/java/org/apache/polygene/api/concern/DocumentationSupport.java
new file mode 100644
index 0000000..4f2339b
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/concern/DocumentationSupport.java
@@ -0,0 +1,101 @@
+/*
+ *  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.polygene.api.concern;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.AppliesToFilter;
+import org.apache.polygene.api.injection.InjectionScope;
+
+public class DocumentationSupport
+{
+// START SNIPPET: class
+    @AppliesTo( java.sql.Connection.class )
+    public class CacheConcern extends GenericConcern
+        implements InvocationHandler
+    {
+// END SNIPPET: class
+        @Override
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            return null;
+        }
+    }
+
+// START SNIPPET: filter
+    @AppliesTo( BusinessAppliesToFilter.class )
+    public class BusinessConcern extends GenericConcern
+        implements InvocationHandler
+    {
+// END SNIPPET: filter
+        @Override
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            return null;
+        }
+    }
+
+// START SNIPPET: filter
+    public class BusinessAppliesToFilter
+        implements AppliesToFilter
+    {
+
+        @Override
+        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass
+        )
+        {
+            return true; // Some criteria for when a method is wrapped with the concern.
+        }
+    }
+// END SNIPPET: filter
+
+
+// START SNIPPET: annotation
+    @AppliesTo( Audited.class )
+    public class AuditConcern extends GenericConcern
+        implements InvocationHandler
+    {
+// START SNIPPET: annotation
+        @Override
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            return null;
+        }
+    }
+
+// START SNIPPET: annotation
+    @Retention( RetentionPolicy.RUNTIME )
+    @Target( { ElementType.METHOD } )
+    @Documented
+    @InjectionScope
+    public @interface Audited
+    {
+    }
+// END SNIPPET: annotation
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/configuration/ConfigurationTest.java b/core/api/src/test/java/org/apache/polygene/api/configuration/ConfigurationTest.java
new file mode 100644
index 0000000..81cdc14
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/configuration/ConfigurationTest.java
@@ -0,0 +1,110 @@
+/*
+ *  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.polygene.api.configuration;
+
+import org.junit.Test;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class ConfigurationTest extends AbstractPolygeneTest
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( MyService.class ).instantiateOnStartup();
+        module.entities( MyConfig.class );
+        module.values( PersonDetails.class, Address.class, City.class, Country.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Test
+    public void testConfiguration()
+        throws Exception
+    {
+        MyService service = serviceFinder.findService( MyService.class ).get();
+        PersonDetails details = service.details();
+        assertThat(details.name().get(), equalTo( "Niclas" ) );
+        assertThat(details.address().get().street1().get(), equalTo( "Henan Lu 555" ) );
+        assertThat(details.address().get().street2().get(), equalTo( "Block 15" ) );
+        assertThat(details.address().get().city().get().cityName().get(), equalTo( "Shanghai" ) );
+        assertThat(details.address().get().city().get().country().get().countryName().get(), equalTo( "China" ) );
+    }
+
+    @Mixins(MyServiceMixin.class)
+    public interface MyService extends ServiceComposite
+    {
+        PersonDetails details();
+    }
+
+    public abstract class MyServiceMixin
+        implements MyService
+    {
+        @This
+        Configuration<MyConfig> myconf;
+
+        @Override
+        public PersonDetails details()
+        {
+            return myconf.get().me().get();
+        }
+    }
+
+    public interface MyConfig extends ConfigurationComposite
+    {
+        Property<PersonDetails> me();
+    }
+
+    public interface PersonDetails extends ValueComposite
+    {
+        Property<String> name();
+        Property<Address> address();
+
+    }
+
+    public interface Address extends ValueComposite
+    {
+        Property<String> street1();
+        Property<String> street2();
+        Property<City> city();
+    }
+
+    public interface City extends ValueComposite
+    {
+        Property<String> cityName();
+        Property<Country> country();
+    }
+
+    public interface Country extends ValueComposite
+    {
+        Property<String> countryName();
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/configuration/DeclareConfigurationDefaultsTest.java b/core/api/src/test/java/org/apache/polygene/api/configuration/DeclareConfigurationDefaultsTest.java
new file mode 100644
index 0000000..d0384a8
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/configuration/DeclareConfigurationDefaultsTest.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.api.configuration;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+public class DeclareConfigurationDefaultsTest
+    extends AbstractPolygeneTest
+{
+
+    @Mixins( FooServiceMixin.class )
+    public static interface FooServiceComposite
+            extends ServiceComposite
+    {
+
+        String configuredFoo();
+
+    }
+
+    public static abstract class FooServiceMixin
+            implements FooServiceComposite
+    {
+
+        @This
+        private Configuration<FooConfigurationComposite> config;
+
+        public String configuredFoo()
+        {
+            return config.get().foo().get();
+        }
+
+    }
+
+    public static interface FooConfigurationComposite
+            extends ConfigurationComposite
+    {
+
+        Property<String> foo();
+
+    }
+
+    public void assemble( ModuleAssembly module )
+            throws AssemblyException
+    {
+        module.services( FooServiceComposite.class ).identifiedBy( "bazar" );
+        module.entities( FooConfigurationComposite.class );
+        new EntityTestAssembler().assemble( module );
+        FooConfigurationComposite config = module.forMixin( FooConfigurationComposite.class ).declareDefaults();
+        config.foo().set( "bar" );
+    }
+
+    @Test
+    public void testConfigurationDefaults()
+    {
+        FooServiceComposite fooService = serviceFinder.findService( FooServiceComposite.class ).get();
+        Assert.assertEquals( "bar", fooService.configuredFoo() );
+    }
+
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/configuration/MailService.java b/core/api/src/test/java/org/apache/polygene/api/configuration/MailService.java
new file mode 100644
index 0000000..aa955dc
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/configuration/MailService.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.api.configuration;
+
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.library.constraints.annotation.Email;
+import org.apache.polygene.library.constraints.annotation.MinLength;
+
+// Documentation Support
+@Mixins( MailService.MailServiceMixin.class )
+public interface MailService
+{
+    void sendMail( @Email String to, @MinLength( 8 ) String subject, String body );
+    
+    // START SNIPPET: write
+    void changeExternalMailService( String hostName, int port );
+    // END SNIPPET: write
+    
+    public class MailServiceMixin
+        implements MailService
+    {
+        // START SNIPPET: read        
+        @This
+        private Configuration<MailServiceConfiguration> config;
+
+        @Override
+        public void sendMail( @Email String to, @MinLength( 8 ) String subject, String body )
+        {
+            config.refresh();
+            MailServiceConfiguration conf = config.get();
+            String hostName = conf.hostName().get();
+            int port = conf.port().get();
+            // END SNIPPET: read
+
+            // START SNIPPET: read        
+        }
+        // END SNIPPET: read        
+
+        // START SNIPPET: write        
+        @Override
+        public void changeExternalMailService( String hostName, int port )
+        {
+            MailServiceConfiguration conf = config.get();
+            conf.hostName().set( hostName );
+            conf.port().set( port );
+            config.save();
+        }
+        // START SNIPPET: write        
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/configuration/MailServiceConfiguration.java b/core/api/src/test/java/org/apache/polygene/api/configuration/MailServiceConfiguration.java
new file mode 100644
index 0000000..5bbf563
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/configuration/MailServiceConfiguration.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.api.configuration;
+
+import org.apache.polygene.api.property.Property;
+
+// Documentation Support class
+// START SNIPPET: configuration
+public interface MailServiceConfiguration extends ConfigurationComposite
+{
+    Property<String> hostName();
+
+    Property<Integer> port();
+}
+// END SNIPPET: configuration
diff --git a/core/api/src/test/java/org/apache/polygene/api/docsupport/ApplicationDocs.java b/core/api/src/test/java/org/apache/polygene/api/docsupport/ApplicationDocs.java
new file mode 100644
index 0000000..c6a6e78
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/docsupport/ApplicationDocs.java
@@ -0,0 +1,275 @@
+/*
+ *  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.polygene.api.docsupport;
+
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+public class ApplicationDocs
+{
+    public static void someMethod( String[] args )
+        throws Exception
+    {
+        {
+// START SNIPPET: application1
+            SingletonAssembler polygene = new SingletonAssembler()
+            {
+                public void assemble( ModuleAssembly assembly )
+                    throws AssemblyException
+                {
+                    assembly.values( MyStuffValueComposite.class );
+                }
+            };
+// END SNIPPET: application1
+        }
+        {
+            Assembler customerListEditAssembler = new DummyAssembler();
+            Assembler customerEditAssembler = new DummyAssembler();
+            Assembler customerSearchAssembler = new DummyAssembler();
+            Assembler accountsListEditAssembler = new DummyAssembler();
+            Assembler accountsEditAssembler = new DummyAssembler();
+            Assembler accountsSearchAssembler = new DummyAssembler();
+            Assembler customerDomainAssembler = new DummyAssembler();
+            Assembler accountsDomainAssembler = new DummyAssembler();
+// START SNIPPET: application2
+            final Assembler[][][] assemblers =
+                {
+                    { // web layer
+                      { // Customer Module
+                        customerListEditAssembler,
+                        customerEditAssembler,
+                        customerSearchAssembler
+                      },
+                      { // Accounts Module
+                        accountsListEditAssembler,
+                        accountsEditAssembler,
+                        accountsSearchAssembler
+                      }
+                    },
+                    { // domain layer
+                      { // Customer Module
+                        customerDomainAssembler,
+                      },
+                      { // Accounts Module
+                        accountsDomainAssembler,
+                      }
+                    }
+                };
+            Energy4Java polygene = new Energy4Java();
+            Application app = polygene.newApplication( new ApplicationAssembler()
+            {
+
+                @Override
+                public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+                    throws AssemblyException
+                {
+                    return applicationFactory.newApplicationAssembly( assemblers );
+                }
+            } );
+            app.activate();
+// END SNIPPET: application2
+        }
+    }
+
+    public interface MyStuffValueComposite
+    {
+    }
+
+    private static class DummyAssembler implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+
+        }
+    }
+
+    // START SNIPPET: application3
+    private static Energy4Java polygene;
+
+    public static void main( String[] args )
+        throws Exception
+    {
+        polygene = new Energy4Java();
+        ApplicationDescriptor model = polygene.newApplicationModel( new ApplicationAssembler()
+        {
+            @Override
+            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+                throws AssemblyException
+            {
+                return createAssembly( applicationFactory );
+            }
+        } );
+        Application application = model.newInstance( polygene.spi() );
+    }
+
+    private static ApplicationAssembly createAssembly( ApplicationAssemblyFactory factory )
+        throws AssemblyException
+    {
+        String applicationName = "Example Application";
+        ApplicationAssembly app = factory.newApplicationAssembly();
+        app.setName( applicationName );
+        LayerAssembly webLayer = createWebLayer( app );
+        LayerAssembly domainLayer = createDomainLayer( app );
+        LayerAssembly infraLayer = createInfrastructureLayer( app );
+        webLayer.uses( domainLayer );
+        webLayer.uses( infraLayer );  // Accesses the WebService
+        domainLayer.uses( infraLayer ); // For persistence
+        return app;
+    }
+
+    private static LayerAssembly createWebLayer(
+        ApplicationAssembly application
+    )
+    {
+        LayerAssembly layer = application.layer( "Web Layer" );
+        createCustomerWebModule( layer );
+        return layer;
+    }
+
+    private static LayerAssembly createDomainLayer(
+        ApplicationAssembly application
+    )
+    {
+        LayerAssembly layer = application.layer( "Domain Layer" );
+        createCustomerDomainModule( layer );
+        // :
+        // :
+        return layer;
+    }
+
+    private static LayerAssembly createInfrastructureLayer(
+        ApplicationAssembly application
+    )
+        throws AssemblyException
+    {
+        LayerAssembly layer = application.layer( "Infrastructure Layer" );
+        createWebServiceModule( layer );
+        createPersistenceModule( layer );
+        return layer;
+    }
+
+    private static void createCustomerWebModule( LayerAssembly layer )
+    {
+        ModuleAssembly assembly = layer.module( "Customer Web Module" );
+        assembly.transients( CustomerViewComposite.class );
+        assembly.transients( CustomerEditComposite.class );
+        assembly.transients( CustomerListViewComposite.class );
+        assembly.transients( CustomerSearchComposite.class );
+    }
+
+    private static void createCustomerDomainModule( LayerAssembly layer )
+    {
+        ModuleAssembly assembly = layer.module( "Customer Domain Module" );
+        assembly.entities( CustomerEntity.class );
+        assembly.entities( CountryEntity.class );
+        assembly.transients( AddressComposite.class );
+    }
+
+    private static void createWebServiceModule( LayerAssembly layer )
+        throws AssemblyException
+    {
+        ModuleAssembly assembly = layer.module( "Web Service Module" );
+        // Someone has created an assembler for a Jetty Web Service.
+        JettyAssembler jetty = new JettyAssembler( 8080 );
+        jetty.assemble( assembly );
+    }
+
+    private static void createPersistenceModule( LayerAssembly layer )
+        throws AssemblyException
+    {
+        ModuleAssembly assembly = layer.module( "Persistence Module" );
+        // Someone has created an assembler for the Neo EntityStore
+        NeoAssembler neo = new NeoAssembler( "./neostore" );
+        neo.assemble( assembly );
+    }
+// START SNIPPET: application3
+
+    public static class CustomerViewComposite
+    {
+
+    }
+    public static class CustomerEditComposite
+    {
+
+    }
+    public static class CustomerListViewComposite
+    {
+
+    }
+    public static class CustomerSearchComposite
+    {
+
+    }
+
+
+    public static class CustomerEntity
+    {
+
+    }
+    public static class CountryEntity
+    {
+
+    }
+    public static class AddressComposite
+    {
+
+    }
+
+    public static class JettyAssembler
+        implements Assembler
+    {
+
+        public JettyAssembler( int port )
+        {
+        }
+
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+        }
+    }
+    public static class NeoAssembler
+        implements Assembler
+    {
+
+        public NeoAssembler( String s )
+        {
+        }
+
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+        }
+    }
+}
+
diff --git a/core/api/src/test/java/org/apache/polygene/api/docsupport/CompositionDocs.java b/core/api/src/test/java/org/apache/polygene/api/docsupport/CompositionDocs.java
new file mode 100644
index 0000000..defa286
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/docsupport/CompositionDocs.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.api.docsupport;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+public class CompositionDocs
+{
+// START SNIPPET: comp1
+    @Mixins( { BalanceCheckMixin.class } )
+    public interface BankAccount
+    {
+        Money checkBalance();
+// END SNIPPET: comp1
+// START SNIPPET: comp1
+    }
+// END SNIPPET: comp1
+
+// START SNIPPET: comp2
+    public void assemble( ModuleAssembly module )
+    {
+        module.entities( BankAccount.class );
+    }
+// END SNIPPET: comp2
+
+    public static class BalanceCheckMixin
+        implements BankAccount
+    {
+        @Override
+        public Money checkBalance()
+        {
+            return null;
+        }
+    }
+
+    public static class Money
+    {
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/docsupport/package.html b/core/api/src/test/java/org/apache/polygene/api/docsupport/package.html
new file mode 100644
index 0000000..6fbef81
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/docsupport/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+<body>
+This package exists to contain snippets for documentation.
+</body>
+</html>
\ No newline at end of file
diff --git a/core/api/src/test/java/org/apache/polygene/api/injection/scope/StateFieldTest.java b/core/api/src/test/java/org/apache/polygene/api/injection/scope/StateFieldTest.java
new file mode 100644
index 0000000..a4b8b30
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/injection/scope/StateFieldTest.java
@@ -0,0 +1,149 @@
+/*
+ *  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.polygene.api.injection.scope;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+/**
+ * Define a field to be a Property
+ */
+public class StateFieldTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( PersonEntity.class );
+    }
+
+    @Test
+    public void givenEntityWithFieldPropertiesWhenUpdatedThenReturnCorrect()
+        throws Exception
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            PersonEntity charles = unitOfWork.newEntity( PersonEntity.class );
+            charles.changeName( "Charles" );
+            Assert.assertEquals( charles.getName(), "Charles" );
+
+            PersonEntity daniel = unitOfWork.newEntity( PersonEntity.class );
+            daniel.changeName( "Daniel" );
+            Assert.assertEquals( daniel.getName(), "Daniel" );
+
+            PersonEntity lisa = unitOfWork.newEntity( PersonEntity.class );
+            lisa.changeName( "Lisa" );
+            Assert.assertEquals( lisa.getName(), "Lisa" );
+
+            charles.befriend( daniel );
+            charles.befriend( lisa );
+            charles.marry( lisa );
+
+            unitOfWork.complete();
+
+            unitOfWork = unitOfWorkFactory.newUnitOfWork();
+
+            charles = unitOfWork.get( charles );
+            daniel = unitOfWork.get( daniel );
+            Assert.assertTrue( charles.isFriend( daniel ) );
+
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    @Mixins( PersonEntity.Mixin.class )
+    public interface PersonEntity
+        extends EntityComposite
+    {
+        void changeName( String newName );
+
+        void marry( PersonEntity entity );
+
+        void befriend( PersonEntity entity );
+
+        boolean isFriend( PersonEntity entity );
+
+        String getName();
+
+        abstract class Mixin
+            implements PersonEntity
+        {
+            @State
+            @UseDefaults
+            public Property<String> name;
+
+            @State
+            @Optional
+            public Association<PersonEntity> spouse;
+
+            @State
+            public ManyAssociation<PersonEntity> friends;
+
+            @Override
+            public void changeName( String newName )
+            {
+                name.set( newName );
+            }
+
+            @Override
+            public void marry( PersonEntity entity )
+            {
+                spouse.set( entity );
+            }
+
+            @Override
+            public void befriend( PersonEntity entity )
+            {
+                friends.add( entity );
+            }
+
+            @Override
+            public String getName()
+            {
+                return name.get();
+            }
+
+            @Override
+            public boolean isFriend( PersonEntity entity )
+            {
+                return friends.contains( entity );
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/test/java/org/apache/polygene/api/injection/scope/ThisTest.java b/core/api/src/test/java/org/apache/polygene/api/injection/scope/ThisTest.java
new file mode 100644
index 0000000..a26d434
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/injection/scope/ThisTest.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.api.injection.scope;
+
+import java.lang.annotation.Annotation;
+import org.junit.Test;
+import org.apache.polygene.api.common.Optional;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Tests public api exposed by This annotation.
+ * This will ensure that the public api does not get changed by mistake.
+ */
+public class ThisTest
+{
+
+    @Test
+    public void retention()
+        throws NoSuchFieldException
+    {
+        Annotation[] annotations = Annotated.class.getDeclaredField( "uses" ).getDeclaredAnnotations();
+        assertNotNull( "annotations should not be null", annotations );
+        assertEquals( "number of annotations", 1, annotations.length );
+        assertEquals( "annotation type", This.class, annotations[ 0 ].annotationType() );
+    }
+
+    private static class Annotated
+    {
+        @This
+        String uses;
+        @Optional
+        @This
+        String usesOptional;
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java b/core/api/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java
new file mode 100644
index 0000000..aaaa052
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/metrics/DocumentationSupport.java
@@ -0,0 +1,164 @@
+/*
+ *  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.polygene.api.metrics;
+
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+public class DocumentationSupport
+{
+    // START SNIPPET: common
+    @Service
+    private MetricsProvider provider;
+    // END SNIPPET: common
+
+    public void forDocumentationOnly()
+    {
+        // START SNIPPET: gauge
+        final BlockingQueue queue = new LinkedBlockingQueue( 20 );
+        // END SNIPPET: gauge
+        // START SNIPPET: gauge
+        MetricsGaugeFactory gaugeFactory = provider.createFactory( MetricsGaugeFactory.class );
+        MetricsGauge<Integer> gauge = gaugeFactory.registerGauge( "Sample Gauge", () -> queue.size() );
+        // END SNIPPET: gauge
+
+        // START SNIPPET: counter
+        MetricsCounterFactory counterFactory = provider.createFactory( MetricsCounterFactory.class );
+        MetricsCounter counter = counterFactory.createCounter( "Sample Counter" );
+        // END SNIPPET: counter
+
+        // START SNIPPET: histogram
+        MetricsHistogramFactory histoFactory = provider.createFactory( MetricsHistogramFactory.class );
+        MetricsHistogram histogram = histoFactory.createHistogram( "Sample Histogram" );
+        // END SNIPPET: histogram
+
+        // START SNIPPET: meter
+        MetricsMeterFactory meterFactory = provider.createFactory( MetricsMeterFactory.class );
+        MetricsMeter meter = meterFactory.createMeter( "Sample Meter" );
+        // END SNIPPET: meter
+
+        // START SNIPPET: timer
+        MetricsTimerFactory timerFactory = provider.createFactory( MetricsTimerFactory.class );
+        MetricsTimer timer = timerFactory.createTimer( "Sample Timer" );
+        // END SNIPPET: timer
+
+        // START SNIPPET: healthcheck
+        MetricsHealthCheckFactory healthFactory = provider.createFactory( MetricsHealthCheckFactory.class );
+        MetricsHealthCheck healthCheck = healthFactory.registerHealthCheck( "Sample Healthcheck", () ->
+        {
+            ServiceStatus status = pingMyService();
+            if( status.isOk() )
+                return MetricsHealthCheck.Result.healthOk();
+            String message = status.getErrorMessage();
+            Exception error = status.getException();
+            if( error != null )
+            {
+                return MetricsHealthCheck.Result.exception(message, error);
+            }
+            return MetricsHealthCheck.Result.unhealthy(message);
+        } );
+        // END SNIPPET: healthcheck
+
+    }
+
+    private ServiceStatus pingMyService()
+    {
+        return new ServiceStatus();
+    }
+
+    private static class ServiceStatus
+    {
+        String errorMessage;
+        Exception exception;
+
+        public String getErrorMessage()
+        {
+            return errorMessage;
+        }
+
+        public Exception getException()
+        {
+            return exception;
+        }
+
+        public boolean isOk()
+        {
+            return errorMessage.equals( "OK" );
+        }
+    }
+
+
+    // START SNIPPET: capture
+    public interface Router
+    {
+        @TimingCapture
+        List<Coordinate> route( String source, String destination );
+    }
+
+    public class RouterAlgorithm1
+        implements Router
+    {
+        @Override
+        public List<Coordinate> route( String source, String destination )
+        {
+// END SNIPPET: capture
+            return null;
+// START SNIPPET: capture
+        }
+    }
+
+    public class RouterAlgorithm2
+        implements Router
+    {
+        @Override
+        public List<Coordinate> route( String source, String destination )
+        {
+// END SNIPPET: capture
+            return null;
+// START SNIPPET: capture
+        }
+
+        // END SNIPPET: capture
+        public class MyAssembler implements Assembler
+        {
+            // START SNIPPET: capture
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.addServices( Router.class ).identifiedBy( "router1" ).withMixins( RouterAlgorithm1.class );
+                module.addServices( Router.class ).identifiedBy( "router2" ).withMixins( RouterAlgorithm2.class );
+// END SNIPPET: capture
+// START SNIPPET: capture
+            }
+        }
+    }
+// END SNIPPET: capture
+
+    public class Coordinate
+    {
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/BankAccount.java b/core/api/src/test/java/org/apache/polygene/api/mixin/BankAccount.java
new file mode 100644
index 0000000..c0f6d6e
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/BankAccount.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.api.mixin;
+
+
+// START SNIPPET: mixinType
+public interface BankAccount
+{
+    Money checkBalance();
+}
+// END SNIPPET: mixinType
+
+class Money {}
+
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/Car.java b/core/api/src/test/java/org/apache/polygene/api/mixin/Car.java
new file mode 100644
index 0000000..eb927a8
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/Car.java
@@ -0,0 +1,26 @@
+/*
+ *  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.polygene.api.mixin;
+
+// START SNIPPET: mixin
+@Mixins( { StartMixin.class, VehicleMixin.class } )
+public interface Car extends Startable, Vehicle
+{}
+// END SNIPPET: mixin
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/Something.java b/core/api/src/test/java/org/apache/polygene/api/mixin/Something.java
new file mode 100644
index 0000000..df65eb1
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/Something.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.api.mixin;
+
+// START SNIPPET: something
+@Mixins( SomethingMixin.class )
+public interface Something
+{}
+// END SNIPPET: something
+
+
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/SomethingMixin.java b/core/api/src/test/java/org/apache/polygene/api/mixin/SomethingMixin.java
new file mode 100644
index 0000000..e5aa474
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/SomethingMixin.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.api.mixin;
+
+// START SNIPPET: something
+public class SomethingMixin
+        implements Something
+{
+    // State is allowed.
+
+    public void doSomething()
+    {
+        // do stuff...
+    }
+}
+// END SNIPPET: something
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/StartMixin.java b/core/api/src/test/java/org/apache/polygene/api/mixin/StartMixin.java
new file mode 100644
index 0000000..2f6fbeb
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/StartMixin.java
@@ -0,0 +1,23 @@
+/*
+ *  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.polygene.api.mixin;
+
+public abstract class StartMixin implements Startable
+{}
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/Startable.java b/core/api/src/test/java/org/apache/polygene/api/mixin/Startable.java
new file mode 100644
index 0000000..7230742
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/Startable.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.api.mixin;
+
+// START SNIPPET: mixin
+public interface Startable
+{
+    boolean start();
+    void stop();
+}
+
+// END SNIPPET: mixin
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/Vehicle.java b/core/api/src/test/java/org/apache/polygene/api/mixin/Vehicle.java
new file mode 100644
index 0000000..7545687
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/Vehicle.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.api.mixin;
+
+// START SNIPPET: mixin
+public interface Vehicle
+{
+    void turn(float angle);
+
+    void accelerate(float acceleration);
+
+    // more methods
+}
+
+// END SNIPPET: mixin
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/VehicleMixin.java b/core/api/src/test/java/org/apache/polygene/api/mixin/VehicleMixin.java
new file mode 100644
index 0000000..16d4cfd
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/VehicleMixin.java
@@ -0,0 +1,23 @@
+/*
+ *  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.polygene.api.mixin;
+
+public abstract class VehicleMixin
+{}
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/DecoratorMixinTest.java b/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/DecoratorMixinTest.java
new file mode 100644
index 0000000..40f59d3
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/DecoratorMixinTest.java
@@ -0,0 +1,92 @@
+/*
+ *  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.polygene.api.mixin.decoratorMixin;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class DecoratorMixinTest extends AbstractPolygeneTest
+{
+    // START SNIPPET: assembly
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( View1.class );
+        module.transients( View2.class );
+        module.transients( FooModel.class );
+    }
+// END SNIPPET: assembly
+
+// START SNIPPET: test
+
+    @Test
+    public void testDecoration()
+    {
+        FooModelImpl model = new FooModelImpl( "Init" );
+        View1 view1 = createView1( model );
+        View2 view2 = createView2( model );
+        assertThat( view1.bar(), equalTo( "Init" ) );
+        assertThat( view2.bar(), equalTo( "Init" ) );
+        model.setBar( "New Value" );
+        assertThat( view1.bar(), equalTo( "New Value" ) );
+        assertThat( view2.bar(), equalTo( "New Value" ) );
+    }
+// END SNIPPET: test
+
+    @Test
+    public void testDecorationWithGenericMixin()
+    {
+        InvocationHandler handler = new FooModelInvocationHandler("Init");
+        ClassLoader cl = getClass().getClassLoader();
+        FooModel model = (FooModel) Proxy.newProxyInstance( cl, new Class[]{ FooModel.class }, handler );
+        View1 view1 = createView1( model );
+        View2 view2 = createView2( model );
+        assertThat( view1.bar(), equalTo( "Init" ) );
+        assertThat( view2.bar(), equalTo( "Init" ) );
+        model.setBar( "New Value" );
+        assertThat( view1.bar(), equalTo( "New Value" ) );
+        assertThat( view2.bar(), equalTo( "New Value" ) );
+    }
+
+    // START SNIPPET: create
+    public View1 createView1( FooModel model )
+    {
+        TransientBuilder<View1> builder = transientBuilderFactory.newTransientBuilder( View1.class );
+        builder.use( model );
+        return builder.newInstance();
+    }
+// END SNIPPET: create
+
+    public View2 createView2( FooModel model )
+    {
+        TransientBuilder<View2> builder = transientBuilderFactory.newTransientBuilder( View2.class );
+        builder.use( model );
+        return builder.newInstance();
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/FooModel.java b/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/FooModel.java
new file mode 100644
index 0000000..f777279
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/FooModel.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.api.mixin.decoratorMixin;
+
+import org.apache.polygene.api.composite.DecoratorMixin;
+import org.apache.polygene.api.mixin.Mixins;
+
+// START SNIPPET: decorator
+@Mixins(DecoratorMixin.class)
+// START SNIPPET: plain
+public interface FooModel
+// END SNIPPET: decorator
+{
+    String getBar();
+    void setBar(String value);
+// END SNIPPET: plain
+
+// START SNIPPET: plain
+}
+// END SNIPPET: plain
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/FooModelImpl.java b/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/FooModelImpl.java
new file mode 100644
index 0000000..5da835e
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/FooModelImpl.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.api.mixin.decoratorMixin;
+
+public class FooModelImpl
+    implements FooModel
+{
+    private String bar;
+
+    public FooModelImpl( String bar )
+    {
+        this.bar = bar;
+    }
+
+    @Override
+    public String getBar()
+    {
+        return bar;
+    }
+
+    public void setBar( String bar )
+    {
+        this.bar = bar;
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/FooModelInvocationHandler.java b/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/FooModelInvocationHandler.java
new file mode 100644
index 0000000..856799b
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/FooModelInvocationHandler.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.api.mixin.decoratorMixin;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+public class FooModelInvocationHandler
+    implements InvocationHandler
+{
+    private String value;
+
+    public FooModelInvocationHandler( String value )
+    {
+        this.value = value;
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        if(method.getName().equals( "hashCode" ))
+            return hashCode();
+        if(method.getName().equals( "equals" ))
+            return equals(args[0]);
+        if(args==null || args.length==0)
+            return value;
+        value = (String) args[0];
+        return null;
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/View1.java b/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/View1.java
new file mode 100644
index 0000000..5cb9293
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/View1.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.api.mixin.decoratorMixin;
+
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+
+// START SNIPPET: decorator
+@Mixins(View1.Mixin.class)
+public interface View1
+{
+    String bar();
+
+    public class Mixin
+        implements View1
+    {
+        @This
+        FooModel model;
+
+        @Override
+        public String bar()
+        {
+            return model.getBar();
+        }
+    }
+}
+// END SNIPPET: decorator
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/View2.java b/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/View2.java
new file mode 100644
index 0000000..517940f
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/decoratorMixin/View2.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.api.mixin.decoratorMixin;
+
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+
+@Mixins(View2.Mixin.class)
+public interface View2
+{
+    String bar();
+    public class Mixin
+        implements View2
+    {
+        @This
+        FooModel model;
+
+        @Override
+        public String bar()
+        {
+            return model.getBar();
+        }
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/partial/Car.java b/core/api/src/test/java/org/apache/polygene/api/mixin/partial/Car.java
new file mode 100644
index 0000000..ea1198e
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/partial/Car.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.api.mixin.partial;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.mixin.StartMixin;
+import org.apache.polygene.api.mixin.Startable;
+
+// START SNIPPET: partial
+@Mixins( { StartMixin.class, SpeedMixin.class, CrashResultMixin.class } )
+public interface Car extends Startable, Vehicle
+{}
+
+// END SNIPPET: partial
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/partial/CrashResultMixin.java b/core/api/src/test/java/org/apache/polygene/api/mixin/partial/CrashResultMixin.java
new file mode 100644
index 0000000..9dbb130
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/partial/CrashResultMixin.java
@@ -0,0 +1,24 @@
+/*
+ *  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.polygene.api.mixin.partial;
+
+public class CrashResultMixin implements Crashable
+{
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/partial/Crashable.java b/core/api/src/test/java/org/apache/polygene/api/mixin/partial/Crashable.java
new file mode 100644
index 0000000..e83c78a
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/partial/Crashable.java
@@ -0,0 +1,24 @@
+/*
+ *  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.polygene.api.mixin.partial;
+
+public interface Crashable
+{
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/partial/SpeedLocation.java b/core/api/src/test/java/org/apache/polygene/api/mixin/partial/SpeedLocation.java
new file mode 100644
index 0000000..21f3620
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/partial/SpeedLocation.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.api.mixin.partial;
+
+// START SNIPPET: partial
+public interface SpeedLocation
+{
+    void turn(float angle);
+
+    void accelerate(float acceleration);
+}
+// END SNIPPET: partial
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/partial/SpeedMixin.java b/core/api/src/test/java/org/apache/polygene/api/mixin/partial/SpeedMixin.java
new file mode 100644
index 0000000..7273441
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/partial/SpeedMixin.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.api.mixin.partial;
+
+// START SNIPPET: partial
+public abstract class SpeedMixin
+        implements SpeedLocation
+{
+    // state for speed
+
+    public void accelerate( float acceleration )
+    {
+        // logic
+    }
+}
+
+// END SNIPPET: partial
\ No newline at end of file
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/partial/Vehicle.java b/core/api/src/test/java/org/apache/polygene/api/mixin/partial/Vehicle.java
new file mode 100644
index 0000000..4372398
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/partial/Vehicle.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.api.mixin.partial;
+
+// START SNIPPET: partial
+public interface Vehicle extends SpeedLocation, Crashable
+{
+}
+
+// END SNIPPET: partial
\ No newline at end of file
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/privateMixin/Cargo.java b/core/api/src/test/java/org/apache/polygene/api/mixin/privateMixin/Cargo.java
new file mode 100644
index 0000000..6c61ac2
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/privateMixin/Cargo.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.api.mixin.privateMixin;
+
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.mixin.Mixins;
+
+// START SNIPPET: private
+@Mixins( CargoMixin.class )
+public interface Cargo extends EntityComposite
+{
+    String origin();
+
+    String destination();
+
+    void changeDestination( String newDestination );
+
+}
+
+// END SNIPPET: private
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/privateMixin/CargoMixin.java b/core/api/src/test/java/org/apache/polygene/api/mixin/privateMixin/CargoMixin.java
new file mode 100644
index 0000000..9629161
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/privateMixin/CargoMixin.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.api.mixin.privateMixin;
+
+import org.apache.polygene.api.injection.scope.This;
+
+// START SNIPPET: private
+public abstract class CargoMixin
+        implements Cargo
+{
+    @This
+    private CargoState state;
+
+    public String origin()
+    {
+        return state.origin().get();
+    }
+
+    public String destination()
+    {
+        return state.destination().get();
+    }
+
+    public void changeDestination( String newDestination )
+    {
+        state.destination().set( newDestination );
+    }
+}
+
+// END SNIPPET: private
\ No newline at end of file
diff --git a/core/api/src/test/java/org/apache/polygene/api/mixin/privateMixin/CargoState.java b/core/api/src/test/java/org/apache/polygene/api/mixin/privateMixin/CargoState.java
new file mode 100644
index 0000000..e93b561
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/mixin/privateMixin/CargoState.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.api.mixin.privateMixin;
+
+import org.apache.polygene.api.property.Property;
+
+// START SNIPPET: private
+public interface CargoState
+{
+    Property<String> origin();
+    Property<String> destination();
+}
+
+// END SNIPPET: private
\ No newline at end of file
diff --git a/core/api/src/test/java/org/apache/polygene/api/object/ObjectBuilderTest.java b/core/api/src/test/java/org/apache/polygene/api/object/ObjectBuilderTest.java
new file mode 100644
index 0000000..265d086
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/object/ObjectBuilderTest.java
@@ -0,0 +1,75 @@
+/*
+ *  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.polygene.api.object;
+
+import org.junit.Test;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * JAVADOC
+ */
+public class ObjectBuilderTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.objects( A.class, B.class, C.class, D.class );
+    }
+
+    @Test
+    public void testNotProvidedUses()
+    {
+        A a = objectFactory.newObject( A.class );
+        assertNotNull( a );
+        assertNotNull( a.b );
+        assertNotNull( a.b.c );
+        assertNotNull( a.b.c.d );
+    }
+
+    public static class A
+    {
+        @Uses
+        B b;
+    }
+
+    public static class B
+    {
+        @Uses
+        C c;
+    }
+
+    public static class C
+    {
+        @Uses
+        D d;
+    }
+
+    public static class D
+    {
+
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/property/PropertyErrorTest.java b/core/api/src/test/java/org/apache/polygene/api/property/PropertyErrorTest.java
new file mode 100644
index 0000000..c299300
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/property/PropertyErrorTest.java
@@ -0,0 +1,67 @@
+/*
+ *  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.polygene.api.property;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+/**
+ * Error messages for Properties
+ */
+public class PropertyErrorTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( PersonEntity.class );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void givenEntityWithNonOptionPropertyWhenInstantiatedThenException()
+        throws Exception
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            PersonEntity person = unitOfWork.newEntity( PersonEntity.class );
+
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    interface PersonEntity
+        extends EntityComposite
+    {
+        Property<String> foo();
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/test/java/org/apache/polygene/api/service/DocumentationSupport.java b/core/api/src/test/java/org/apache/polygene/api/service/DocumentationSupport.java
new file mode 100644
index 0000000..c612d0b
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/service/DocumentationSupport.java
@@ -0,0 +1,139 @@
+/*
+ *  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.polygene.api.service;
+
+import java.util.List;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.qualifier.ServiceTags;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+
+public class DocumentationSupport
+    implements Assembler
+{
+    // START SNIPPET: tag
+    // START SNIPPET: instantiateOnStartup
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration service = module.addServices( MyDemoService.class );
+        // END SNIPPET: tag
+        service.instantiateOnStartup();
+        // END SNIPPET: instantiateOnStartup
+        // START SNIPPET: tag
+        service.taggedWith( "Important", "Drain" );
+        // END SNIPPET: tag
+    }
+
+    private static class MyDemoService
+    {
+    }
+
+    private static class MyOtherDemoService
+    {
+        // START SNIPPET: UseTag
+        @Service
+        private List<ServiceReference<MyDemoService>> services;
+
+        public MyDemoService locateImportantService()
+        {
+            for( ServiceReference<MyDemoService> ref : services )
+            {
+                ServiceTags serviceTags = ref.metaInfo( ServiceTags.class );
+                if( serviceTags.hasTag( "Important" ) )
+                {
+                    return ref.get();
+                }
+            }
+            return null;
+        }
+        // END SNIPPET: UseTag
+    }
+
+    // START SNIPPET: activation1
+    @Mixins( MyActivationMixin.class )
+    public static interface MyActivationDemoService
+        extends ServiceComposite, ServiceActivation
+    {
+    }
+
+    public static class MyActivationMixin
+        implements ServiceActivation
+    {
+        @Override
+        public void activateService()
+            throws Exception
+        {
+            // Activation code
+        }
+
+        @Override
+        public void passivateService()
+            throws Exception
+        {
+            // Passivation code
+        }
+    }
+    // END SNIPPET: activation1
+
+    // START SNIPPET: activation2
+    @Activators( MyActivator.class )
+    public static interface MyOtherActivationDemoService
+        extends ServiceComposite
+    {
+    }
+
+    public static class MyActivator
+        extends ServiceActivatorAdapter<MyOtherActivationDemoService>
+    {
+        @Override
+        public void afterActivation( ServiceReference<MyOtherActivationDemoService> activated )
+            throws Exception
+        {
+            // Activation code
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<MyOtherActivationDemoService> passivating )
+            throws Exception
+        {
+            // Passivation code
+        }
+    }
+    // END SNIPPET: activation2
+
+    static class Activation3
+        implements Assembler
+    {
+        // START SNIPPET: activation3
+        @Override
+        public void assemble( ModuleAssembly module )
+        {
+            module.services( MyDemoService.class ).withActivators( MyActivator.class );
+        }
+        // END SNIPPET: activation3
+    }
+
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/type/HasTypesCollectorsTest.java b/core/api/src/test/java/org/apache/polygene/api/type/HasTypesCollectorsTest.java
new file mode 100644
index 0000000..b5f3381
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/type/HasTypesCollectorsTest.java
@@ -0,0 +1,150 @@
+/*
+ *  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.polygene.api.type;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public class HasTypesCollectorsTest
+{
+    @Test
+    public void selectMatchingTypes()
+    {
+        List<ValueType> valueTypes = Arrays.asList(
+            ValueType.of( String.class ),
+            ValueType.of( Integer.class ),
+            ValueType.of( Number.class )
+        );
+
+        List<ValueType> number = valueTypes.stream().collect( HasTypesCollectors.matchingTypes( Number.class ) );
+        assertThat( number.size(), is( 2 ) );
+        assertThat( number.get( 0 ), equalTo( ValueType.of( Number.class ) ) );
+        assertThat( number.get( 1 ), equalTo( ValueType.of( Integer.class ) ) );
+
+        List<ValueType> integer = valueTypes.stream().collect( HasTypesCollectors.matchingTypes( Integer.class ) );
+        assertThat( integer.size(), is( 1 ) );
+        assertThat( integer.get( 0 ), equalTo( ValueType.of( Integer.class ) ) );
+    }
+
+    @Test
+    public void selectMatchingType()
+    {
+        List<ValueType> valueTypes = Arrays.asList(
+            ValueType.of( String.class ),
+            ValueType.of( Double.class ),
+            ValueType.of( Integer.class )
+        );
+
+        Optional<ValueType> number = valueTypes.stream()
+                                               .collect( HasTypesCollectors.matchingType( Number.class ) );
+        assertTrue( number.isPresent() );
+        assertThat( number.get(), equalTo( ValueType.of( Double.class ) ) );
+
+        Optional<ValueType> integer = valueTypes.stream()
+                                                .collect( HasTypesCollectors.matchingType( Integer.class ) );
+        assertTrue( integer.isPresent() );
+        assertThat( integer.get(), equalTo( ValueType.of( Integer.class ) ) );
+    }
+
+    @Test
+    public void selectMatchingValueTypes()
+    {
+        List<ValueType> valueTypes = Arrays.asList(
+            ValueType.of( String.class ),
+            ValueType.of( Number.class, Integer.class ),
+            ValueType.of( Integer.class ),
+            ValueType.of( Number.class )
+        );
+
+        List<ValueType> number = valueTypes.stream()
+                                           .collect( HasTypesCollectors.matchingTypes( ValueType.of( Number.class ) ) );
+        System.out.println( number );
+        assertThat( number.size(), is( 2 ) );
+        assertThat( number.get( 0 ), equalTo( ValueType.of( Number.class ) ) );
+        assertThat( number.get( 1 ), equalTo( ValueType.of( Number.class, Integer.class ) ) );
+
+        List<ValueType> integer = valueTypes.stream()
+                                            .collect(
+                                                HasTypesCollectors.matchingTypes( ValueType.of( Integer.class ) ) );
+        assertThat( integer.size(), is( 2 ) );
+        assertThat( integer.get( 0 ), equalTo( ValueType.of( Integer.class ) ) );
+        assertThat( integer.get( 1 ), equalTo( ValueType.of( Number.class, Integer.class ) ) );
+
+        List<ValueType> both = valueTypes.stream()
+                                         .collect( HasTypesCollectors.matchingTypes( ValueType.of( Number.class,
+                                                                                                   Integer.class ) ) );
+        assertThat( both.size(), is( 1 ) );
+        assertThat( both.get( 0 ), equalTo( ValueType.of( Number.class, Integer.class ) ) );
+    }
+
+    @Test
+    public void selectMatchingValueType()
+    {
+        List<ValueType> valueTypes = Arrays.asList(
+            ValueType.of( String.class ),
+            ValueType.of( Number.class, Integer.class ),
+            ValueType.of( Integer.class ),
+            ValueType.of( Number.class )
+        );
+
+        Optional<ValueType> number = valueTypes.stream()
+                                               .collect(
+                                                   HasTypesCollectors.matchingType( ValueType.of( Number.class ) ) );
+        assertTrue( number.isPresent() );
+        assertThat( number.get(), equalTo( ValueType.of( Number.class ) ) );
+
+        Optional<ValueType> integer = valueTypes.stream()
+                                                .collect(
+                                                    HasTypesCollectors.matchingType( ValueType.of( Integer.class ) ) );
+        assertTrue( integer.isPresent() );
+        assertThat( integer.get(), equalTo( ValueType.of( Integer.class ) ) );
+
+        Optional<ValueType> both = valueTypes.stream()
+                                             .collect( HasTypesCollectors.matchingType( ValueType.of( Number.class,
+                                                                                                      Integer.class ) ) );
+        assertTrue( both.isPresent() );
+        assertThat( both.get(), equalTo( ValueType.of( Number.class, Integer.class ) ) );
+    }
+
+    @Test
+    public void selectClosestValueTypes()
+    {
+        List<ValueType> list = new ArrayList<ValueType>()
+        {{
+            add( ValueType.of( String.class ) );
+            add( ValueType.of( Identity.class ) );
+        }};
+
+        List<ValueType> result = list.stream()
+                                     .collect( HasTypesCollectors.closestTypes( StringIdentity.class ) );
+        assertThat( result.size(), is( 1 ) );
+        assertThat( result.get( 0 ), equalTo( ValueType.of( Identity.class ) ) );
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/type/HasTypesPredicatesTest.java b/core/api/src/test/java/org/apache/polygene/api/type/HasTypesPredicatesTest.java
new file mode 100644
index 0000000..8e8bf5d
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/type/HasTypesPredicatesTest.java
@@ -0,0 +1,73 @@
+/*
+ *  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.polygene.api.type;
+
+import java.time.LocalDate;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class HasTypesPredicatesTest
+{
+    @Test
+    public void hasEqualTypePredicate()
+    {
+        assertTrue( new HasEqualType<>( Integer.class )
+                        .test( ValueType.of( Integer.class ) ) );
+        assertTrue( new HasEqualType<>( Integer.class )
+                        .test( ValueType.of( String.class, Integer.class ) ) );
+        assertFalse( new HasEqualType<>( Number.class )
+                         .test( ValueType.of( String.class, Integer.class ) ) );
+        assertFalse( new HasEqualType<>( String.class )
+                         .test( ValueType.of( LocalDate.class, Integer.class ) ) );
+
+        assertTrue( new HasEqualType<>( ValueType.of( Integer.class ) )
+                        .test( ValueType.of( Integer.class ) ) );
+        assertTrue( new HasEqualType<>( ValueType.of( Integer.class ) )
+                        .test( ValueType.of( String.class, Integer.class ) ) );
+        assertFalse( new HasEqualType<>( ValueType.of( Number.class ) )
+                         .test( ValueType.of( String.class, Integer.class ) ) );
+        assertFalse( new HasEqualType<>( ValueType.of( String.class ) )
+                         .test( ValueType.of( LocalDate.class, Integer.class ) ) );
+    }
+
+    @Test
+    public void hasAssignableTypePredicate()
+    {
+        assertTrue( new HasAssignableFromType<>( Number.class )
+                        .test( ValueType.of( String.class, Integer.class ) ) );
+        assertFalse( new HasAssignableFromType<>( Integer.class )
+                         .test( ValueType.of( Integer.class ) ) );
+        assertFalse( new HasAssignableFromType<>( String.class )
+                         .test( ValueType.of( LocalDate.class, Integer.class ) ) );
+    }
+
+    @Test
+    public void hasEqualOrAssignablePredicate()
+    {
+        assertTrue( new HasEqualOrAssignableFromType<>( Number.class )
+                        .test( ValueType.of( String.class, Integer.class ) ) );
+        assertTrue( new HasEqualOrAssignableFromType<>( Integer.class )
+                        .test( ValueType.of( Integer.class ) ) );
+        assertFalse( new HasEqualOrAssignableFromType<>( String.class )
+                         .test( ValueType.of( LocalDate.class, Integer.class ) ) );
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/type/ValueTypeFactoryTest.java b/core/api/src/test/java/org/apache/polygene/api/type/ValueTypeFactoryTest.java
new file mode 100644
index 0000000..7f093af
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/type/ValueTypeFactoryTest.java
@@ -0,0 +1,142 @@
+/*
+ *  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.polygene.api.type;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.TimeUnit;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.spi.module.ModuleSpi;
+import org.apache.polygene.spi.type.ValueTypeFactory;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.junit.Assert.assertThat;
+
+public class ValueTypeFactoryTest extends AbstractPolygeneTest
+{
+    private ValueTypeFactory valueTypeFactory;
+
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        module.values( SomeState.class );
+        module.entities( SomeState.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    interface SomeState
+    {
+        @UseDefaults
+        Property<List<String>> list();
+
+        @UseDefaults
+        Property<Map<String, Integer>> map();
+    }
+
+    @Before
+    public void setup()
+    {
+        valueTypeFactory = ( (ModuleSpi) module.instance() ).valueTypeFactory();
+    }
+
+    @Test
+    public void plainValues()
+    {
+        assertThat( valueTypeFactory.valueTypeOf( module, String.class ), equalTo( ValueType.STRING ) );
+        assertThat( valueTypeFactory.valueTypeOf( module, "" ), equalTo( ValueType.STRING ) );
+    }
+
+    @Test
+    public void enums()
+    {
+        assertThat( valueTypeFactory.valueTypeOf( module, TimeUnit.class ), instanceOf( EnumType.class ) );
+        assertThat( valueTypeFactory.valueTypeOf( module, TimeUnit.DAYS ), instanceOf( EnumType.class ) );
+    }
+
+    @Test
+    public void collections()
+    {
+        assertThat( valueTypeFactory.valueTypeOf( module, LinkedHashSet.class ),
+                    instanceOf( CollectionType.class ) );
+
+        List<String> list = new ArrayList<>();
+        ValueType listValueType = valueTypeFactory.valueTypeOf( module, list );
+        assertThat( listValueType, instanceOf( CollectionType.class ) );
+        assertThat( ( (CollectionType) listValueType ).collectedType(), equalTo( ValueType.OBJECT ) );
+    }
+
+    @Test
+    public void maps()
+    {
+        assertThat( valueTypeFactory.valueTypeOf( module, TreeMap.class ), instanceOf( MapType.class ) );
+
+        HashMap<String, Integer> map = new HashMap<>();
+        ValueType mapValueType = valueTypeFactory.valueTypeOf( module, map );
+        assertThat( mapValueType, instanceOf( MapType.class ) );
+        assertThat( ( (MapType) mapValueType ).keyType(), equalTo( ValueType.OBJECT ) );
+        assertThat( ( (MapType) mapValueType ).valueType(), equalTo( ValueType.OBJECT ) );
+    }
+
+    @Test
+    public void valueComposites()
+    {
+        assertThat( valueTypeFactory.valueTypeOf( module, SomeState.class ),
+                    instanceOf( ValueCompositeType.class ) );
+        assertThat( valueTypeFactory.valueTypeOf( module, valueBuilderFactory.newValue( SomeState.class ) ),
+                    instanceOf( ValueCompositeType.class ) );
+    }
+
+    @Test
+    public void entityComposites()
+    {
+        assertThat( valueTypeFactory.valueTypeOf( module, SomeState.class ),
+                    instanceOf( StatefulAssociationValueType.class ) );
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            assertThat(
+                valueTypeFactory.valueTypeOf( module, uow.newEntity( SomeState.class, new StringIdentity( "abc" ) ) ),
+                instanceOf( EntityCompositeType.class ) );
+        }
+    }
+
+    @Test
+    public void genericsAreResolvedOnValueCompositeProperties()
+    {
+        ValueDescriptor descriptor = module.typeLookup().lookupValueModel( SomeState.class );
+        assertThat( descriptor.state().findPropertyModelByName( "list" ).valueType(),
+                    equalTo( CollectionType.listOf( ValueType.STRING ) ) );
+        assertThat( descriptor.state().findPropertyModelByName( "map" ).valueType(),
+                    equalTo( MapType.of( ValueType.STRING, ValueType.INTEGER ) ) );
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/unitofwork/RemovalTest.java b/core/api/src/test/java/org/apache/polygene/api/unitofwork/RemovalTest.java
new file mode 100644
index 0000000..87d609c
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/unitofwork/RemovalTest.java
@@ -0,0 +1,133 @@
+/*
+ *  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.polygene.api.unitofwork;
+
+import org.apache.polygene.api.identity.StringIdentity;
+import org.junit.Test;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+public class RemovalTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( TestEntity.class );
+        module.entities( PidRegulator.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Test
+    public void givenEntityIsCreatedAndUnitOfWorkIsNotCompletedWhenEntityIsRemoveThenSuccessfulRemoval()
+        throws Exception
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            EntityBuilder<TestEntity> builder = uow.newEntityBuilder( TestEntity.class, new StringIdentity( "123" ) );
+            builder.instance().test().set( "habba" );
+            TestEntity test = builder.newInstance();
+            uow.remove( test );
+            uow.complete();
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void givenStandardPidRegulatorWhenNoChangeInInputExpectOutputToGoTowardsMinimum()
+        throws Exception
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        PidRegulator regulator = null;
+        try
+        {
+            regulator = createPidRegulator( uow );
+        }
+        finally
+        {
+            if( regulator != null )
+            {
+                uow.remove( regulator );
+            }
+            // TODO: This problem is related to that uow.remove() has a bug.
+            // If the Entity is both created and removed in the same session, then the remove() should simply remove
+            // the entity from the internal UoW holding area, and not set the REMOVED status.
+
+            // Probably that UnitOfWorkInstance.remove() should also call instanceCache.remove(), but the question is
+            // then what is an InstanceKey vs EntityReference
+            uow.complete();
+        }
+    }
+
+    public interface TestEntity
+        extends EntityComposite
+    {
+        @Optional
+        Property<String> test();
+    }
+
+    private PidRegulator createPidRegulator( UnitOfWork uow )
+        throws UnitOfWorkCompletionException
+    {
+        EntityBuilder<PidRegulator> builder = uow.newEntityBuilder( PidRegulator.class );
+        PidRegulator prototype = builder.instance();
+        prototype.p().set( 1.0f );
+        prototype.i().set( 10f );
+        prototype.d().set( 0.1f );
+        prototype.maxD().set( 10f );
+        prototype.maximum().set( 100f );
+        prototype.minimum().set( 0f );
+        PidRegulator regulator = builder.newInstance();
+
+        return regulator;
+    }
+
+    //    @Mixins( { PidRegulatorAlgorithmMixin.class } )
+    public interface PidRegulator
+        extends PidParameters, EntityComposite
+    {
+    }
+
+    public interface PidParameters
+    {
+        Property<Float> p();
+
+        Property<Float> i();
+
+        Property<Float> d();
+
+        Property<Float> maxD();
+
+        Property<Float> minimum();
+
+        Property<Float> maximum();
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/unitofwork/ToEntityConversionTest.java b/core/api/src/test/java/org/apache/polygene/api/unitofwork/ToEntityConversionTest.java
new file mode 100644
index 0000000..5f5a5b5
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/unitofwork/ToEntityConversionTest.java
@@ -0,0 +1,140 @@
+/*
+ *  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.polygene.api.unitofwork;
+
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Test;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class ToEntityConversionTest
+    extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( SomeType.class );
+        module.values( SomeType.class );
+    }
+
+    @Test
+    public void testPropertyConversionToEntity()
+        throws Exception
+    {
+        Identity identity = new StringIdentity( "Niclas" );
+        ValueBuilder<SomeType> vb = valueBuilderFactory.newValueBuilder( SomeType.class );
+        SomeType prototype = vb.prototype();
+        prototype.identity().set( identity );
+        prototype.name().set( "Niclas" );
+        SomeType value = vb.newInstance();
+
+        Usecase usecase = UsecaseBuilder.buildUsecase( "test case" )
+                                        .withMetaInfo( new SomeEntityConverter() )
+                                        .newUsecase();
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork(usecase) )
+        {
+            SomeType entity = uow.toEntity( SomeType.class, value );
+            assertThat( entity.identity().get(), equalTo( identity ) );
+            assertThat( entity.name().get(), equalTo( "[Niclas]" ) );
+            uow.complete();
+        }
+    }
+
+    interface SomeType extends HasIdentity
+    {
+        Property<String> name();
+
+        @Optional
+        Association<String> assoc();
+
+        @UseDefaults
+        ManyAssociation<String> many();
+
+        @UseDefaults
+        NamedAssociation<String> named();
+    }
+
+    private static class SomeEntityConverter
+        implements ToEntityConverter
+    {
+        @Structure
+        private PolygeneSPI spi;
+
+        @Override
+        public Function<PropertyDescriptor, Object> properties( Object entityComposite, Function<PropertyDescriptor, Object> defaultFn )
+        {
+            return descriptor ->
+            {
+                QualifiedName name = QualifiedName.fromClass( SomeType.class, "name" );
+                Object value = defaultFn.apply( descriptor );
+                if( descriptor.qualifiedName().equals( name ) )
+                {
+                    return "[" + value + "]";
+                }
+                return value;
+            };
+        }
+
+        @Override
+        public Function<AssociationDescriptor, EntityReference> associations( Object entityComposite, Function<AssociationDescriptor, EntityReference> defaultFn )
+        {
+            return defaultFn;
+        }
+
+        @Override
+        public Function<AssociationDescriptor, Stream<EntityReference>> manyAssociations( Object entityComposite, Function<AssociationDescriptor, Stream<EntityReference>> defaultFn )
+        {
+            return defaultFn;
+        }
+
+        @Override
+        public Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociations( Object entityComposite, Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> defaultFn )
+        {
+            return defaultFn;
+        }
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/unitofwork/ToValueConversionTest.java b/core/api/src/test/java/org/apache/polygene/api/unitofwork/ToValueConversionTest.java
new file mode 100644
index 0000000..08751d4
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/unitofwork/ToValueConversionTest.java
@@ -0,0 +1,165 @@
+/*
+ *  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.polygene.api.unitofwork;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Test;
+
+import static org.hamcrest.core.AnyOf.anyOf;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class ToValueConversionTest
+    extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( SomeType.class );
+        module.values( SomeType.class );
+    }
+
+    @Test
+    public void testConversionToValue()
+        throws Exception
+    {
+        Usecase usecase = UsecaseBuilder.buildUsecase( "test case" )
+                                        .withMetaInfo( new SomeValueConverter() )
+                                        .newUsecase();
+        SomeType value;
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork(usecase) )
+        {
+            SomeType entity1 = createEntity( uow, new StringIdentity( "Niclas" ) );
+            SomeType entity2 = createEntity( uow, new StringIdentity( "Paul" ) );
+            SomeType entity3 = createEntity( uow, new StringIdentity( "Jiri" ) );
+            SomeType entity4 = createEntity( uow, new StringIdentity( "Kent" ) );
+            SomeType entity5 = createEntity( uow, new StringIdentity( "Stan" ) );
+            entity1.assoc().set( entity2 );
+            entity1.many().add( entity3 );
+            entity1.named().put( "kent", entity4 );
+            entity1.named().put( "stan", entity5 );
+
+            value = uow.toValue( SomeType.class, entity1 );
+            uow.complete();
+
+        }
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork(usecase) )
+        {
+            assertThat( value.identity().get(), equalTo( new StringIdentity( "Niclas" ) ) );
+            assertThat( value.name().get(), equalTo( "[Niclas]" ) );
+
+            assertThat( uow.toValue( SomeType.class, value.assoc().get()).name().get(), equalTo( "[Paul]" ));
+            assertThat( uow.toValueList( value.many() ).get(0).name().get(), equalTo( "[Jiri]" ));
+            assertThat( uow.toValueSet( value.many() ).iterator().next().name().get(), equalTo( "[Jiri]" ));
+            Set<Map.Entry<String, SomeType>> actual = uow.toValueMap( value.named() ).entrySet();
+            assertThat( actual.iterator().next().getKey(), anyOf(equalTo( "stan" ), equalTo( "kent" )) );
+            assertThat( actual.iterator().next().getValue().name().get(), anyOf(equalTo( "[Stan]" ), equalTo( "[Kent]" )) );
+        }
+
+    }
+
+    private SomeType createEntity( UnitOfWork uow, Identity identity )
+    {
+        EntityBuilder<SomeType> builder = uow.newEntityBuilder( SomeType.class, identity );
+        builder.instance().name().set( identity.toString() );
+        return builder.newInstance();
+    }
+
+    interface SomeType extends HasIdentity
+    {
+        Property<String> name();
+
+        @Optional
+        Association<SomeType> assoc();
+
+        @UseDefaults
+        ManyAssociation<SomeType> many();
+
+        @UseDefaults
+        NamedAssociation<SomeType> named();
+    }
+
+    private static class SomeValueConverter
+        implements ToValueConverter
+    {
+        @Structure
+        private PolygeneSPI spi;
+
+        @Override
+        public Function<PropertyDescriptor, Object> properties( Object entityComposite, Function<PropertyDescriptor, Object> defaultFn )
+        {
+            return descriptor ->
+            {
+                Object value = defaultFn.apply( descriptor );
+                QualifiedName name = QualifiedName.fromClass( SomeType.class, "name" );
+                if( name.equals( descriptor.qualifiedName() ) )
+                {
+                    return "[" + value + "]";
+                }
+                return value;
+            };
+        }
+
+        @Override
+        public Function<AssociationDescriptor, EntityReference> associations( Object entityComposite, Function<AssociationDescriptor, EntityReference> defaultFn )
+        {
+            return defaultFn;
+        }
+
+        @Override
+        public Function<AssociationDescriptor, Stream<EntityReference>> manyAssociations( Object entityComposite, Function<AssociationDescriptor, Stream<EntityReference>> defaultFn )
+        {
+            return defaultFn;
+        }
+
+        @Override
+        public Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociations( Object entityComposite, Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> defaultFn )
+        {
+            return defaultFn;
+        }
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/unitofwork/UnitOfWorkTemplateTest.java b/core/api/src/test/java/org/apache/polygene/api/unitofwork/UnitOfWorkTemplateTest.java
new file mode 100644
index 0000000..43bd5b7
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/unitofwork/UnitOfWorkTemplateTest.java
@@ -0,0 +1,74 @@
+/*
+ *  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.polygene.api.unitofwork;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.entity.EntityBuilderTemplate;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+/**
+ * TODO
+ */
+public class UnitOfWorkTemplateTest
+    extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( TestEntity.class );
+    }
+
+    @Test
+    public void testTemplate()
+        throws UnitOfWorkCompletionException
+    {
+        new UnitOfWorkTemplate<Void, RuntimeException>()
+        {
+            @Override
+            protected Void withUnitOfWork( UnitOfWork uow )
+                throws RuntimeException
+            {
+                new EntityBuilderTemplate<TestEntity>( TestEntity.class )
+                {
+                    @Override
+                    protected void build( TestEntity prototype )
+                    {
+                        prototype.name().set( "Rickard" );
+                    }
+                }.newInstance( module.instance() );
+
+                return null;
+            }
+        }.withModule( module.instance() );
+    }
+
+    interface TestEntity
+        extends EntityComposite
+    {
+        Property<String> name();
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/util/ClassesTest.java b/core/api/src/test/java/org/apache/polygene/api/util/ClassesTest.java
new file mode 100644
index 0000000..834cc97
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/util/ClassesTest.java
@@ -0,0 +1,211 @@
+/*
+ *  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.polygene.api.util;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.HashSet;
+import java.util.Set;
+import org.junit.Test;
+
+import static org.apache.polygene.api.util.Classes.interfacesOf;
+import static org.apache.polygene.api.util.Classes.interfacesWithMethods;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Tests for Classes
+ */
+public class ClassesTest
+{
+
+    @Test
+    public void givenClassWithInterfacesWhenInterfacesOfThenGetCorrectSet()
+    {
+        assertThat( "one interface returned", interfacesOf( A.class ).count(), equalTo( 1L ) );
+        assertThat( "two interface returned", interfacesOf( B.class ).count(), equalTo( 2L ) );
+        assertThat( "tree interface returned", interfacesOf( C.class ).count(), equalTo( 4L ) );
+    }
+
+    @Test
+    public void givenClassWithInterfacesWhenGetInterfacesWithMethodsThenGetCorrectSet()
+    {
+        HashSet<Class<?>> interfaces = new HashSet<Class<?>>();
+        interfaces.add( B.class );
+        Set<Class<?>> types = interfacesWithMethods( interfaces );
+        assertThat( "one interface returned", types.size(), equalTo( 1 ) );
+        assertThat( "correct interface returned", types.contains( B.class ), is( true ) );
+    }
+
+    @Test
+    public void givenClassesWithInterfacesWhenGetInterfacesWithMethodsThenGetCorrectSet()
+    {
+        assertThat( "one interface returned", interfacesOf( C.class ).filter( Methods.HAS_METHODS )
+            .count(), equalTo( 1L ) );
+        boolean isIn = interfacesOf( C.class ).filter( Methods.HAS_METHODS )
+            .anyMatch( B.class::equals );
+        assertThat( "correct interface returned", isIn, is( true ) );
+    }
+
+    @Test
+    public void givenClassNameWhenToUriThenUriIsReturned()
+    {
+        assertThat( "URI is correct", Classes.toURI( A.class ), equalTo( "urn:polygene:type:org.apache.polygene.api.util.ClassesTest-A" ) );
+    }
+
+    @Test
+    public void givenUriWhenToClassNameThenClassNameIsReturned()
+    {
+        assertThat( "Class name is correct", Classes.toClassName( "urn:polygene:type:org.apache.polygene.api.util.ClassesTest-A" ), equalTo( "org.apache.polygene.api.util.ClassesTest$A" ) );
+    }
+
+    @Test
+    public void givenGenericTypeWithWildCardWhenGetRawClassThenCorrectTypeIsReturned()
+        throws NoSuchMethodException
+    {
+        Type returnType = Generics.class.getMethod( "wildcard" ).getGenericReturnType();
+        Type wildcardType = ( (ParameterizedType) returnType ).getActualTypeArguments()[ 0 ];
+        assertThat( "Return type is A", Classes.RAW_CLASS.apply( wildcardType ), equalTo( (Class) A.class ) );
+    }
+
+    @Test
+    public void givenTypeVariableWhenResolveThenResolved()
+    {
+        for( Method method : Type1.class.getMethods() )
+        {
+            Type type = method.getGenericReturnType();
+            TypeVariable typeVariable = (TypeVariable) type;
+            Type resolvedType = Classes.resolveTypeVariable( typeVariable, method.getDeclaringClass(), Type1.class );
+            System.out.println( type + "=" + resolvedType );
+            switch( method.getName() )
+            {
+            case "type":
+                assertThat( resolvedType, equalTo( String.class ) );
+                break;
+            case "type1":
+                assertThat( resolvedType, equalTo( String.class ) );
+                break;
+            case "type2":
+                assertThat( resolvedType, equalTo( Long.class ) );
+                break;
+            }
+        }
+    }
+
+    @Test
+    public void givenGenericTypeWhenGetSimpleGenericNameThenCorrectStringIsReturned()
+        throws NoSuchMethodException
+    {
+        assertThat( "Simple Generic Name is 'A'",
+                    Classes.simpleGenericNameOf( A.class ),
+                    equalTo( "A" ) );
+        assertThat( "Simple Generic Name is 'B'",
+                    Classes.simpleGenericNameOf( B.class ),
+                    equalTo( "B" ) );
+        assertThat( "Simple Generic Name is 'C'",
+                    Classes.simpleGenericNameOf( C.class ),
+                    equalTo( "C" ) );
+
+        assertThat( "Simple Generic Name is 'Generics'",
+                    Classes.simpleGenericNameOf( Generics.class ),
+                    equalTo( "Generics" ) );
+        assertThat( "Simple Generic Name is 'Iterable<? extends A>'",
+                    Classes.simpleGenericNameOf( Generics.class.getMethod( "wildcard" ).getGenericReturnType() ),
+                    equalTo( "Iterable<? extends A>" ) );
+
+        assertThat( "Simple Generic Name is 'Type1'",
+                    Classes.simpleGenericNameOf( Type1.class ),
+                    equalTo( "Type1" ) );
+        assertThat( "Simple Generic Name is 'TYPE'",
+                    Classes.simpleGenericNameOf( Type1.class.getMethod( "type" ).getGenericReturnType() ),
+                    equalTo( "TYPE" ) );
+        assertThat( "Simple Generic Name is 'TYPE1'",
+                    Classes.simpleGenericNameOf( Type1.class.getMethod( "type1" ).getGenericReturnType() ),
+                    equalTo( "TYPE1" ) );
+        assertThat( "Simple Generic Name is 'TYPE2'",
+                    Classes.simpleGenericNameOf( Type1.class.getMethod( "type2" ).getGenericReturnType() ),
+                    equalTo( "TYPE2" ) );
+
+        assertThat( "Simple Generic Name is 'Type2'",
+                    Classes.simpleGenericNameOf( Type2.class ),
+                    equalTo( "Type2" ) );
+        assertThat( "Simple Generic Name is 'TYPE'",
+                    Classes.simpleGenericNameOf( Type2.class.getMethod( "type" ).getGenericReturnType() ),
+                    equalTo( "TYPE" ) );
+        assertThat( "Simple Generic Name is 'TYPE1'",
+                    Classes.simpleGenericNameOf( Type2.class.getMethod( "type1" ).getGenericReturnType() ),
+                    equalTo( "TYPE1" ) );
+        assertThat( "Simple Generic Name is 'TYPE2'",
+                    Classes.simpleGenericNameOf( Type2.class.getMethod( "type2" ).getGenericReturnType() ),
+                    equalTo( "TYPE2" ) );
+
+        assertThat( "Simple Generic Name is 'Type3'",
+                    Classes.simpleGenericNameOf( Type3.class ),
+                    equalTo( "Type3" ) );
+        assertThat( "Simple Generic Name is 'TYPE'",
+                    Classes.simpleGenericNameOf( Type3.class.getMethod( "type" ).getGenericReturnType() ),
+                    equalTo( "TYPE" ) );
+    }
+
+    interface A
+    {
+    }
+
+    interface B
+        extends A
+    {
+
+        public void doStuff();
+    }
+
+    interface C
+        extends A, B
+    {
+    }
+
+    interface Generics
+    {
+
+        Iterable<? extends A> wildcard();
+    }
+
+    interface Type1
+        extends Type2<String, Long>
+    {
+    }
+
+    interface Type2<TYPE1, TYPE2>
+        extends Type3<TYPE1>
+    {
+
+        TYPE1 type1();
+
+        TYPE2 type2();
+    }
+
+    interface Type3<TYPE>
+    {
+
+        TYPE type();
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/util/CollectorsTest.java b/core/api/src/test/java/org/apache/polygene/api/util/CollectorsTest.java
new file mode 100644
index 0000000..1beb26a
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/util/CollectorsTest.java
@@ -0,0 +1,115 @@
+/*
+ *  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.polygene.api.util;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Stream;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class CollectorsTest
+{
+@Test
+public void single()
+{
+    assertThat( Stream.of( 1L ).collect( Collectors.single() ), is( 1L ) );
+
+    try
+    {
+        Stream.of().collect( Collectors.single() );
+        fail( "Should have failed" );
+    }
+    catch( IllegalArgumentException ex ) {}
+    try
+    {
+        Stream.of( 1, 1 ).collect( Collectors.single() );
+        fail( "Should have failed" );
+    }
+    catch( IllegalArgumentException ex ) {}
+    try
+    {
+        Stream.of( 1, 1, 1 ).collect( Collectors.single() );
+        fail( "Should have failed" );
+    }
+    catch( IllegalArgumentException ex ) {}
+}
+
+@Test
+public void singleOrEmpty()
+{
+    assertEquals( Optional.empty(), Stream.of().collect( Collectors.singleOrEmpty() ) );
+    assertEquals( Optional.of( 1 ), Stream.of( 1 ).collect( Collectors.singleOrEmpty() ) );
+
+    try
+    {
+        Stream.of( 1, 1 ).collect( Collectors.singleOrEmpty() );
+        fail( "Should have failed" );
+    }
+    catch( IllegalArgumentException ex ) {}
+    try
+    {
+        Stream.of( 1, 1, 1 ).collect( Collectors.singleOrEmpty() );
+        fail( "Should have failed" );
+    }
+    catch( IllegalArgumentException ex ) {}
+}
+
+    @Test
+    public void toMap()
+    {
+        Map<String, String> input = new LinkedHashMap<>();
+        input.put( "foo", "bar" );
+        input.put( "bazar", "cathedral" );
+        Map<String, String> output = input.entrySet().stream().collect( Collectors.toMap() );
+        assertThat( output.get( "foo" ), equalTo( "bar" ) );
+        assertThat( output.get( "bazar" ), equalTo( "cathedral" ) );
+    }
+
+    @Test
+    public void toMapRejectNullValues()
+    {
+        Map<String, String> input = new LinkedHashMap<>();
+        input.put( "foo", "bar" );
+        input.put( "bazar", null );
+        try
+        {
+            input.entrySet().stream().collect( Collectors.toMap() );
+            fail( "Should have failed, that's the default Map::merge behaviour" );
+        }
+        catch( NullPointerException expected ) {}
+    }
+
+    @Test
+    public void toMapWithNullValues()
+    {
+        Map<String, String> input = new LinkedHashMap<>();
+        input.put( "foo", "bar" );
+        input.put( "bazar", null );
+        Map<String, String> output = input.entrySet().stream().collect( Collectors.toMapWithNullValues() );
+        assertThat( output.get( "foo" ), equalTo( "bar" ) );
+        assertThat( output.get( "bazar" ), nullValue() );
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/value/DocumentationSupport.java b/core/api/src/test/java/org/apache/polygene/api/value/DocumentationSupport.java
new file mode 100644
index 0000000..245cc16
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/value/DocumentationSupport.java
@@ -0,0 +1,163 @@
+/*
+ *  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.polygene.api.value;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.serialization.Deserializer;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static java.util.stream.Collectors.toList;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Snippets:
+ * - default : default Serialization
+ * - service : assembled service Serialization
+ * - io : i/o usage
+ */
+public class DocumentationSupport extends AbstractPolygeneTest
+{
+    // START SNIPPET: default
+    // START SNIPPET: service
+    public interface SomeValue // (1)
+    {
+        Property<String> foo();
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        module.values( SomeValue.class ); // (2)
+    }
+    // END SNIPPET: default
+    // END SNIPPET: service
+
+    @Test
+    // START SNIPPET: default
+    public void defaultSerialization()
+    {
+        SomeValue someValue = someNewValueInstance(); // (3)
+        String json = someValue.toString(); // (4)
+        SomeValue someNewValue = valueBuilderFactory.newValueFromSerializedState( SomeValue.class, json ); // (5)
+        // END SNIPPET: default
+
+        assertThat( json, equalTo( "{\"foo\":\"bar\"}" ) );
+        assertThat( someNewValue, equalTo( someValue ) );
+
+        // START SNIPPET: default
+    }
+
+    // END SNIPPET: default
+    // START SNIPPET: service
+    @Service
+    private Serializer serializer; // (4)
+    @Service
+    private Deserializer deserializer; // (4)
+
+    // END SNIPPET: service
+    @Test
+    // START SNIPPET: service
+    public void assembledDefaultServiceSerialization()
+    {
+        SomeValue someValue = someNewValueInstance(); // (5)
+        String json = serializer.serialize( someValue ); // (6)
+        SomeValue someNewValue = deserializer.deserialize( module, SomeValue.class, json ); // (7)
+        // END SNIPPET: service
+
+        assertThat( json, equalTo( "{\"foo\":\"bar\"}" ) );
+        assertThat( someNewValue, equalTo( someValue ) );
+
+        // START SNIPPET: service
+    }
+    // END SNIPPET: service
+
+    static enum AcmeValue
+    {
+        foo,
+        bar
+    }
+
+    @Test
+    // START SNIPPET: io
+    public void assembledServiceIOSerialization()
+        throws IOException
+    {
+        // END SNIPPET: io
+
+        List<AcmeValue> dataSource = Arrays.asList( AcmeValue.values() );
+        StringWriter stringOutput = new StringWriter();
+        PrintWriter output = new PrintWriter( stringOutput );
+
+
+        // START SNIPPET: io
+        // (1)
+        // Eg. Entities converted to Values
+        Stream<AcmeValue> queryResult = dataSource.stream();
+
+        // (2)
+        Function<AcmeValue, String> serialize = serializer.serializeFunction();
+
+        // (3)
+        // Eg. pipe data to another process or to a file
+        queryResult.map( serialize ).forEach( output::println );
+        // END SNIPPET: io
+
+        output.flush();
+        String string = stringOutput.toString();
+        List<String> input = Arrays.asList( string.split( System.lineSeparator() ) );
+
+        // START SNIPPET: io
+        // (4)
+        Stream<String> lines = input.stream();
+
+        // (5)
+        Function<String, AcmeValue> deserialize = deserializer.deserializeFunction( module, AcmeValue.class );
+
+        // Deserialization of a collection of AcmeValue from a String.
+        // One serialized AcmeValue per line.
+        // (6)
+        List<AcmeValue> values = lines.map( deserialize ).collect( toList() );
+        // END SNIPPET: io
+
+        assertThat( dataSource, equalTo( values ) );
+
+        // START SNIPPET: io
+    }
+    // END SNIPPET: io
+
+    private SomeValue someNewValueInstance()
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        builder.prototype().foo().set( "bar" );
+        return builder.newInstance();
+    }
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/value/ValueBuilderTemplateTest.java b/core/api/src/test/java/org/apache/polygene/api/value/ValueBuilderTemplateTest.java
new file mode 100644
index 0000000..f52d103
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/value/ValueBuilderTemplateTest.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.api.value;
+
+import org.junit.Test;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+/**
+ * TODO
+ */
+public class ValueBuilderTemplateTest
+    extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.values( TestValue.class );
+    }
+
+    @Test
+    public void testTemplate()
+    {
+        new TestBuilder( "Rickard" ).newInstance( module );
+    }
+
+    @Test
+    public void testAnonymousTemplate()
+    {
+        new ValueBuilderTemplate<TestValue>( TestValue.class )
+        {
+            @Override
+            protected void build( TestValue prototype )
+            {
+                prototype.name().set( "Rickard" );
+            }
+        }.newInstance( module );
+    }
+
+    interface TestValue
+        extends ValueComposite
+    {
+        Property<String> name();
+    }
+
+    class TestBuilder
+        extends ValueBuilderTemplate<TestValue>
+    {
+        String name;
+
+        TestBuilder( String name )
+        {
+            super( TestValue.class );
+            this.name = name;
+        }
+
+        @Override
+        protected void build( TestValue prototype )
+        {
+            prototype.name().set( name );
+        }
+    }
+
+    ;
+}
diff --git a/core/api/src/test/java/org/apache/polygene/api/value/ValueCompositeTest.java b/core/api/src/test/java/org/apache/polygene/api/value/ValueCompositeTest.java
new file mode 100644
index 0000000..f925623
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/value/ValueCompositeTest.java
@@ -0,0 +1,333 @@
+/*
+ *  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.polygene.api.value;
+
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.constraints.annotation.MaxLength;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+/**
+ * Tests for ValueComposites
+ */
+public class ValueCompositeTest
+    extends AbstractPolygeneTest
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.values( SomeValue.class, AnotherValue.class, AssociationValue.class );
+        module.entities( SomeEntity.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Test( expected = IllegalStateException.class )
+    public void testImmutabilityOfValueComposite()
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        SomeValue some = builder.prototype();
+        some.other().set( "test" );
+        some = builder.newInstance();
+        some.other().set( "test2" );
+    }
+
+    @Test
+    public void testCreationOfValueComposite()
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        SomeValue some = builder.prototype();
+        some.other().set( "test" );
+        builder.newInstance();
+
+        // Check that @UseDefaults works for ValueComposites
+        assertEquals( "{\"val1\":\"\"}", some.another().get().toString() );
+    }
+
+    @Test
+    public void testEqualityOfValueComposite()
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        SomeValue prototype = builder.prototype();
+        prototype.other().set( "test" );
+        SomeValue instance = builder.newInstance();
+        SomeValue other = builder.newInstance();
+        Assert.assertFalse( "Instances should not be the same.", instance == other );
+        Assert.assertEquals( "Equal values.", instance, other );
+    }
+
+    @Test
+    public void testHashcodeOfValueComposite()
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        SomeValue prototype = builder.prototype();
+        prototype.other().set( "test" );
+        SomeValue instance = builder.newInstance();
+        SomeValue other = builder.newInstance();
+        Assert.assertFalse( "Instances should not be the same.", instance == other );
+        Assert.assertEquals( "Equal values.", instance.hashCode(), other.hashCode() );
+    }
+
+    @Test
+    public void testModifyValue()
+    {
+        ValueBuilder<AnotherValue> anotherBuilder = valueBuilderFactory.newValueBuilder( AnotherValue.class );
+        anotherBuilder.prototype().val1().set( "Val1" );
+        AnotherValue anotherValue = anotherBuilder.newInstance();
+
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        SomeValue prototype = builder.prototype();
+        prototype.some().set( "foo" );
+        prototype.other().set( "test" );
+        prototype.xyzzyList().get().add( "blah" );
+        prototype.another().set( anotherValue );
+        SomeValue instance = builder.newInstance();
+
+        assertThat( "List has value blah", instance.xyzzyList().get().get( 0 ), equalTo( "blah" ) );
+
+        // Modify value
+        builder = valueBuilderFactory.newValueBuilderWithPrototype( instance );
+        builder.prototype().some().set( "bar" );
+        instance = builder.newInstance();
+
+        assertThat( "Other is set to test", instance.other().get(), equalTo( "test" ) );
+        assertThat( "List has value blah", instance.xyzzyList().get().get( 0 ), equalTo( "blah" ) );
+        assertThat( "AnotherValue.val1 has value Val1", instance.another().get().val1().get(), equalTo( "Val1" ) );
+
+        // Modify value again using method 2
+        builder = valueBuilderFactory.newValueBuilderWithPrototype( instance );
+        builder.prototype().other().set( "test2" );
+        instance = builder.newInstance();
+
+        assertThat( "Other is set to test2", instance.other().get(), equalTo( "test2" ) );
+        assertThat( "Some is set to bar", instance.some().get(), equalTo( "bar" ) );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void givenValueWhenModifyToIncorrectValueThenThrowConstraintException()
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        SomeValue prototype = builder.prototype();
+        prototype.some().set( "foo" );
+        SomeValue instance = builder.newInstance();
+
+        builder = valueBuilderFactory.newValueBuilderWithPrototype( instance );
+        builder.prototype().some().set( "123456" );
+    }
+
+    @Test
+    public void givenValueWithListOfValueWhenPrototypeThenListedValuesAreEditable()
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        builder.prototype().anotherList().get().add( valueBuilderFactory.newValue( AnotherValue.class ) );
+        SomeValue some = builder.newInstance();
+
+        builder = valueBuilderFactory.newValueBuilderWithPrototype( some );
+        builder.prototype().anotherList().get().get( 0 ).val1().set( "Foo" );
+        builder.prototype().anotherList().get().add( valueBuilderFactory.newValue( AnotherValue.class ) );
+        some = builder.newInstance();
+
+        assertThat( "Val1 has been set", some.anotherList().get().get( 0 ).val1().get(), equalTo( "Foo" ) );
+
+        try
+        {
+            some.anotherList().get().get( 0 ).val1().set( "Bar" );
+            Assert.fail( "Should not be allowed to modify value" );
+        }
+        catch( IllegalStateException e )
+        {
+            // Ok
+        }
+    }
+
+    @Test
+    public void givenEntityWhenUpdateValueThenValueIsSet()
+        throws UnitOfWorkCompletionException
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        builder.prototype().anotherList().get().add( valueBuilderFactory.newValue( AnotherValue.class ) );
+        ValueBuilder<AnotherValue> valueBuilder = valueBuilderFactory.newValueBuilder( AnotherValue.class );
+        valueBuilder.prototype().val1().set( "Foo" );
+        builder.prototype().another().set( valueBuilder.newInstance() );
+        builder.prototype().number().set( 42L );
+        SomeValue some = builder.newInstance();
+
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            EntityBuilder<SomeEntity> entityBuilder = unitOfWork.newEntityBuilder( SomeEntity.class );
+            entityBuilder.instance().someValue().set( some );
+            SomeEntity entity = entityBuilder.newInstance();
+
+            assertThat( "Value has been set", entity.someValue().get().another().get().val1().get(), equalTo( "Foo" ) );
+
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    @Test
+    public void givenValueWithAssociationsWhenNewUoWThenCanRead()
+        throws UnitOfWorkCompletionException
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        builder.prototype().anotherList().get().add( valueBuilderFactory.newValue( AnotherValue.class ) );
+        ValueBuilder<AnotherValue> valueBuilder = valueBuilderFactory.newValueBuilder( AnotherValue.class );
+        valueBuilder.prototype().val1().set( "Foo" );
+        builder.prototype().another().set( valueBuilder.newInstance() );
+        builder.prototype().number().set( 42L );
+        SomeValue some = builder.newInstance();
+
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        AssociationValue associationValue;
+        try
+        {
+            EntityBuilder<SomeEntity> entityBuilder = unitOfWork.newEntityBuilder( SomeEntity.class );
+            entityBuilder.instance().someValue().set( some );
+            SomeEntity entity = entityBuilder.newInstance();
+
+            ValueBuilder<AssociationValue> associationBuilder = valueBuilderFactory.newValueBuilder(
+                AssociationValue.class );
+            associationBuilder.prototype().some().set( entity );
+            associationValue = associationBuilder.newInstance();
+
+            String json = associationValue.toString();
+
+            unitOfWork.complete();
+
+            unitOfWork = unitOfWorkFactory.newUnitOfWork();
+
+            AssociationValue newAssociationValue = valueBuilderFactory.newValueFromSerializedState(
+                AssociationValue.class, json );
+
+            Assert.assertEquals( associationValue.some().get(), newAssociationValue.some().get() );
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+
+        // Should allow the toString() to print the entityRefs.
+        System.out.println( associationValue.toString() );
+        try
+        {
+            associationValue.some().get();
+            fail( "Should have thrown an exception" );
+        }
+        catch( Exception e )
+        {
+            // Ok
+        }
+    }
+
+    @Test
+    public void givenValueWhenToStringThenNoTypeInfo()
+    {
+        ValueBuilder<AnotherValue> anotherBuilder = valueBuilderFactory.newValueBuilder( AnotherValue.class );
+        anotherBuilder.prototype().val1().set( "foo" );
+        AnotherValue another = anotherBuilder.newInstance();
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        builder.prototype().another().set( another );
+        SomeValue some = builder.newInstance();
+        String toString = some.toString();
+        System.out.println( toString );
+        assertThat( toString, not( containsString( "_type" ) ) );
+    }
+
+    public enum TestEnum
+    {
+        somevalue,
+        anothervalue
+    }
+
+    public interface SomeValue
+        extends ValueComposite
+    {
+        @UseDefaults
+        @MaxLength( 5 )
+        Property<String> some();
+
+        @UseDefaults
+        Property<String> other();
+
+        @UseDefaults
+        Property<Long> number();
+
+        @UseDefaults
+        Property<List<String>> xyzzyList();
+
+        @UseDefaults
+        Property<AnotherValue> another();
+
+        @UseDefaults
+        Property<List<AnotherValue>> anotherList();
+
+        @UseDefaults
+        Property<TestEnum> testEnum();
+    }
+
+    public interface AnotherValue
+        extends ValueComposite
+    {
+        @UseDefaults
+        Property<String> val1();
+    }
+
+    public interface AssociationValue
+        extends ValueComposite
+    {
+        @Optional
+        Association<SomeEntity> some();
+
+        ManyAssociation<SomeEntity> manySome();
+    }
+
+    public interface SomeEntity
+        extends EntityComposite
+    {
+        Property<SomeValue> someValue();
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/test/java/org/qi4j/api/OperatorsTest.java b/core/api/src/test/java/org/qi4j/api/OperatorsTest.java
deleted file mode 100644
index 6f467e5..0000000
--- a/core/api/src/test/java/org/qi4j/api/OperatorsTest.java
+++ /dev/null
@@ -1,115 +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.qi4j.api;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.QueryExpressions;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.test.EntityTestAssembler;
-
-/**
- * TODO
- */
-public class OperatorsTest
-{
-    @Test
-    public void testOperators()
-        throws UnitOfWorkCompletionException, ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                new EntityTestAssembler().assemble( module );
-
-                module.entities( TestEntity.class );
-                module.values( TestValue.class );
-                module.forMixin( TestEntity.class ).declareDefaults().foo().set( "Bar" );
-                module.forMixin( TestValue.class ).declareDefaults().bar().set( "Xyz" );
-            }
-        };
-
-        UnitOfWork uow = assembler.module().newUnitOfWork();
-
-        try
-        {
-            EntityBuilder<TestEntity> entityBuilder = uow.newEntityBuilder( TestEntity.class, "123" );
-            entityBuilder.instance().value().set( assembler.module().newValue( TestValue.class ) );
-            TestEntity testEntity = entityBuilder.newInstance();
-
-            uow.complete();
-            uow = assembler.module().newUnitOfWork();
-
-            Iterable<TestEntity> entities = Iterables.iterable( testEntity = uow.get( testEntity ) );
-
-            QueryBuilder<TestEntity> builder = assembler.module().newQueryBuilder( TestEntity.class );
-
-            {
-                Specification<Composite> where = QueryExpressions.eq( QueryExpressions.templateFor( TestEntity.class )
-                                                                          .foo(), "Bar" );
-                Assert.assertTrue( where.satisfiedBy( testEntity ) );
-                System.out.println( where );
-            }
-            {
-                Specification<Composite> where = QueryExpressions.eq( QueryExpressions.templateFor( TestEntity.class )
-                                                                          .value()
-                                                                          .get()
-                                                                          .bar(), "Xyz" );
-                Assert.assertTrue( where.satisfiedBy( testEntity ) );
-                System.out.println( where );
-
-                Assert.assertTrue( builder.where( where ).newQuery( entities ).find().equals( testEntity ) );
-            }
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    public interface TestEntity
-        extends EntityComposite
-    {
-        Property<String> foo();
-
-        Property<TestValue> value();
-    }
-
-    public interface TestValue
-        extends ValueComposite
-    {
-        Property<String> bar();
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/activation/ActivationEventsTest.java b/core/api/src/test/java/org/qi4j/api/activation/ActivationEventsTest.java
deleted file mode 100644
index acc5340..0000000
--- a/core/api/src/test/java/org/qi4j/api/activation/ActivationEventsTest.java
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg.
- * Copyright (c) 2012, Niclas Hedhman.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.api.activation;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationEvent.EventType;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-import static org.junit.Assert.*;
-import static org.qi4j.api.activation.ActivationEvent.EventType.*;
-
-public class ActivationEventsTest
-{
-
-    public static interface TestService
-    {
-        void test();
-    }
-
-    public static class TestServiceInstance
-            implements TestService
-    {
-
-        @Override
-        public void test()
-        {
-        }
-
-    }
-
-    @Mixins( TestServiceInstance.class )
-    public static interface TestServiceComposite
-        extends TestService, ServiceComposite
-    {
-    }
-
-    @Test
-    public void testSingleModuleSingleService()
-        throws Exception
-    {
-        final List<ActivationEvent> events = new ArrayList<>();
-
-        new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.services( TestServiceComposite.class ).instantiateOnStartup();
-            }
-
-            @Override
-            protected void beforeActivation( Application application )
-            {
-                application.registerActivationEventListener( new EventsRecorder( events ) );
-            }
-
-
-        }.application().passivate();
-
-        Iterator<ActivationEvent> it = events.iterator();
-
-        // Activation
-        assertEvent( it.next(), ACTIVATING, "Application" );
-        assertEvent( it.next(), ACTIVATING, "Layer" );
-        assertEvent( it.next(), ACTIVATING, "Module" );
-        assertEvent( it.next(), ACTIVATING, "TestService" );
-        assertEvent( it.next(), ACTIVATED, "TestService" );
-        assertEvent( it.next(), ACTIVATED, "Module" );
-        assertEvent( it.next(), ACTIVATED, "Layer" );
-        assertEvent( it.next(), ACTIVATED, "Application" );
-
-        // Passivation
-        assertEvent( it.next(), PASSIVATING, "Application" );
-        assertEvent( it.next(), PASSIVATING, "Layer" );
-        assertEvent( it.next(), PASSIVATING, "Module" );
-        assertEvent( it.next(), PASSIVATING, "TestService" );
-        assertEvent( it.next(), PASSIVATED, "TestService" );
-        assertEvent( it.next(), PASSIVATED, "Module" );
-        assertEvent( it.next(), PASSIVATED, "Layer" );
-        assertEvent( it.next(), PASSIVATED, "Application" );
-
-        assertFalse( it.hasNext() );
-    }
-
-    @Test
-    public void testSingleModuleSingleImportedService()
-            throws Exception
-    {
-        final List<ActivationEvent> events = new ArrayList<>();
-
-        new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.importedServices( TestService.class ).
-                        setMetaInfo( new TestServiceInstance() ).
-                        importOnStartup();
-            }
-
-            @Override
-            protected void beforeActivation( Application application )
-            {
-                application.registerActivationEventListener( new EventsRecorder( events ) );
-            }
-
-
-        }.application().passivate();
-
-        Iterator<ActivationEvent> it = events.iterator();
-
-        // Activation
-        assertEvent( it.next(), ACTIVATING, "Application" );
-        assertEvent( it.next(), ACTIVATING, "Layer" );
-        assertEvent( it.next(), ACTIVATING, "Module" );
-        assertEvent( it.next(), ACTIVATING, "TestService" );
-        assertEvent( it.next(), ACTIVATED, "TestService" );
-        assertEvent( it.next(), ACTIVATED, "Module" );
-        assertEvent( it.next(), ACTIVATED, "Layer" );
-        assertEvent( it.next(), ACTIVATED, "Application" );
-
-        // Passivation
-        assertEvent( it.next(), PASSIVATING, "Application" );
-        assertEvent( it.next(), PASSIVATING, "Layer" );
-        assertEvent( it.next(), PASSIVATING, "Module" );
-        assertEvent( it.next(), PASSIVATING, "TestService" );
-        assertEvent( it.next(), PASSIVATED, "TestService" );
-        assertEvent( it.next(), PASSIVATED, "Module" );
-        assertEvent( it.next(), PASSIVATED, "Layer" );
-        assertEvent( it.next(), PASSIVATED, "Application" );
-
-        assertFalse( it.hasNext() );
-    }
-
-    @Test
-    public void testSingleModuleSingleLazyService()
-            throws Exception
-    {
-        final List<ActivationEvent> events = new ArrayList<>();
-
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                module.services( TestServiceComposite.class );
-            }
-
-            @Override
-            protected void beforeActivation( Application application )
-            {
-                application.registerActivationEventListener( new EventsRecorder( events ) );
-            }
-
-        };
-        Application application = assembler.application();
-        application.passivate();
-
-        Iterator<ActivationEvent> it = events.iterator();
-
-        // Activation
-        assertEvent( it.next(), ACTIVATING, "Application" );
-        assertEvent( it.next(), ACTIVATING, "Layer" );
-        assertEvent( it.next(), ACTIVATING, "Module" );
-        // Lazy Service NOT activated
-        assertEvent( it.next(), ACTIVATED, "Module" );
-        assertEvent( it.next(), ACTIVATED, "Layer" );
-        assertEvent( it.next(), ACTIVATED, "Application" );
-
-        // Passivation
-        assertEvent( it.next(), PASSIVATING, "Application" );
-        assertEvent( it.next(), PASSIVATING, "Layer" );
-        assertEvent( it.next(), PASSIVATING, "Module" );
-        // Lazy Service NOT passivated
-        assertEvent( it.next(), PASSIVATED, "Module" );
-        assertEvent( it.next(), PASSIVATED, "Layer" );
-        assertEvent( it.next(), PASSIVATED, "Application" );
-
-        assertFalse( it.hasNext() );
-
-        events.clear();
-        application.activate();
-        Module module = assembler.module();
-        module.findService( TestService.class ).get().test();
-        application.passivate();
-
-        for( ActivationEvent event : events ) {
-            System.out.println( event );
-        }
-
-        it = events.iterator();
-
-        // Activation
-        assertEvent( it.next(), ACTIVATING, "Application" );
-        assertEvent( it.next(), ACTIVATING, "Layer" );
-        assertEvent( it.next(), ACTIVATING, "Module" );
-        assertEvent( it.next(), ACTIVATED, "Module" );
-        assertEvent( it.next(), ACTIVATED, "Layer" );
-        assertEvent( it.next(), ACTIVATED, "Application" );
-
-        // Lazy Service Activation
-        assertEvent( it.next(), ACTIVATING, "TestService" );
-        assertEvent( it.next(), ACTIVATED, "TestService" );
-
-        // Passivation
-        assertEvent( it.next(), PASSIVATING, "Application" );
-        assertEvent( it.next(), PASSIVATING, "Layer" );
-        assertEvent( it.next(), PASSIVATING, "Module" );
-        assertEvent( it.next(), PASSIVATING, "TestService" );
-        assertEvent( it.next(), PASSIVATED, "TestService" );
-        assertEvent( it.next(), PASSIVATED, "Module" );
-        assertEvent( it.next(), PASSIVATED, "Layer" );
-        assertEvent( it.next(), PASSIVATED, "Application" );
-
-        assertFalse( it.hasNext() );
-    }
-
-    private static class EventsRecorder
-            implements ActivationEventListener
-    {
-
-        private final List<ActivationEvent> events;
-
-        private EventsRecorder( List<ActivationEvent> events )
-        {
-            this.events = events;
-        }
-
-        @Override
-        public void onEvent( ActivationEvent event )
-        {
-            events.add( event );
-        }
-
-    }
-
-    // WARN This assertion depends on ApplicationInstance, LayerInstance, ModuleInstance and ServiceReferenceInstance toString() method.
-    private static void assertEvent( ActivationEvent event, EventType expectedType, String expected )
-    {
-        boolean wrongEvent = expectedType != event.type();
-        boolean wrongMessage = ! event.message().contains( expected );
-        if( wrongEvent || wrongMessage )
-        {
-            StringBuilder sb = new StringBuilder();
-            sb.append("Event (").append( event ).append( ") has");
-            if( wrongEvent )
-            {
-                sb.append( " wrong type (expected:'" ).append( expectedType ).
-                        append( "' but was:'" ).append( event.type() ).append( "')" );
-                if( wrongMessage )
-                {
-                    sb.append( ";" );
-                }
-            }
-            if( wrongMessage )
-            {
-                sb.append( " wrong message (expected:'" ).append( expected ).
-                        append( "' but was:'" ).append( event.message() ).append( "')" );
-            }
-            fail( sb.toString() );
-        }
-    }
-
-}
diff --git a/core/api/src/test/java/org/qi4j/api/activation/PassivationExceptionTest.java b/core/api/src/test/java/org/qi4j/api/activation/PassivationExceptionTest.java
deleted file mode 100644
index 348e32d..0000000
--- a/core/api/src/test/java/org/qi4j/api/activation/PassivationExceptionTest.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (c) 2013-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.api.activation;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.Arrays;
-import java.util.Collections;
-import org.junit.Test;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Layer;
-import org.qi4j.api.structure.Module;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.builder.ApplicationBuilder;
-
-import static org.hamcrest.core.StringContains.containsString;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-public class PassivationExceptionTest
-{
-    private static String stack( Exception ex )
-    {
-        StringWriter writer = new StringWriter();
-        ex.printStackTrace( new PrintWriter( writer ) );
-        return writer.toString();
-    }
-
-    @Test
-    public void testEmptyPassivationException()
-    {
-        PassivationException empty = new PassivationException( Collections.<Exception>emptyList() );
-        assertThat( empty.getMessage(), containsString( "has 0 cause" ) );
-    }
-
-    @Test
-    public void testSinglePassivationException()
-    {
-        PassivationException single = new PassivationException( Collections.singletonList( new Exception( "single" ) ) );
-        String stack = stack( single );
-        assertThat( single.getMessage(), containsString( "has 1 cause" ) );
-        assertThat( stack, containsString( "Suppressed: java.lang.Exception: single" ) );
-    }
-
-    @Test
-    public void testMultiplePassivationException()
-    {
-        PassivationException multi = new PassivationException( Arrays.asList( new Exception( "one" ),
-                                                                              new Exception( "two" ),
-                                                                              new Exception( "three" ) ) );
-        String stack = stack( multi );
-        assertThat( multi.getMessage(), containsString( "has 3 cause(s)" ) );
-        assertThat( stack, containsString( "Suppressed: java.lang.Exception: one" ) );
-        assertThat( stack, containsString( "Suppressed: java.lang.Exception: two" ) );
-        assertThat( stack, containsString( "Suppressed: java.lang.Exception: three" ) );
-    }
-
-    @Test
-    public void testPassivationExceptionsAccrossStructure()
-        throws AssemblyException, ActivationException
-    {
-        ApplicationBuilder appBuilder = new ApplicationBuilder( "TestApplication" );
-        appBuilder.withLayer( "Layer 1" ).withModule( "Module A" ).withAssembler( new Assembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.services( TestService.class ).
-                    identifiedBy( "TestService_Module.A" ).
-                    withActivators( FailBeforePassivationServiceActivator.class ).
-                    instantiateOnStartup();
-            }
-        } );
-        appBuilder.withLayer( "Layer 2" ).withModule( "Module B" ).withAssembler( new Assembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.services( TestService.class ).
-                    identifiedBy( "TestService_Module.B" ).
-                    withActivators( FailAfterPassivationServiceActivator.class ).
-                    instantiateOnStartup();
-            }
-        } );
-        appBuilder.registerActivationEventListener( new TestActivationEventListener() );
-
-        Application app = appBuilder.newApplication();
-
-        try
-        {
-            Module moduleA = app.findModule( "Layer 1", "Module A" );
-            TestService service = moduleA.findService( TestService.class ).get();
-            assertThat( service.hello(), equalTo( "Hello Zest!" ) );
-        }
-        finally
-        {
-            try
-            {
-                app.passivate();
-                fail( "No PassivationException" );
-            }
-            catch( PassivationException ex )
-            {
-                ex.printStackTrace();
-                String stack = stack( ex );
-                assertThat( ex.getMessage(), containsString( "has 12 cause(s)" ) );
-                assertThat( stack, containsString( "EVENT: FAIL BEFORE PASSIVATION for TestApplication" ) );
-                assertThat( stack, containsString( "EVENT: FAIL BEFORE PASSIVATION for Layer 2" ) );
-                assertThat( stack, containsString( "EVENT: FAIL BEFORE PASSIVATION for Module B" ) );
-                assertThat( stack, containsString( "ACTIVATOR: FAIL AFTER PASSIVATION for TestService_Module.B(active=false,module='Module B')" ) );
-                assertThat( stack, containsString( "EVENT: FAIL AFTER PASSIVATION for Module B" ) );
-                assertThat( stack, containsString( "EVENT: FAIL AFTER PASSIVATION for Layer 2" ) );
-                assertThat( stack, containsString( "EVENT: FAIL BEFORE PASSIVATION for Layer 1" ) );
-                assertThat( stack, containsString( "EVENT: FAIL BEFORE PASSIVATION for Module A" ) );
-                assertThat( stack, containsString( "ACTIVATOR: FAIL BEFORE PASSIVATION for TestService_Module.A(active=true,module='Module A')" ) );
-                assertThat( stack, containsString( "EVENT: FAIL AFTER PASSIVATION for Module A" ) );
-                assertThat( stack, containsString( "EVENT: FAIL AFTER PASSIVATION for Layer 1" ) );
-                assertThat( stack, containsString( "EVENT: FAIL AFTER PASSIVATION for TestApplication" ) );
-            }
-        }
-    }
-
-    @Mixins( TestService.Mixin.class )
-    public interface TestService
-    {
-        String hello();
-
-        static class Mixin
-            implements TestService
-        {
-            @Structure
-            private Module module;
-
-            @Override
-            public String hello()
-            {
-                module.name();
-                return "Hello Zest!";
-            }
-        }
-
-    }
-
-    public static class FailBeforePassivationServiceActivator
-        extends ActivatorAdapter<ServiceReference<TestService>>
-    {
-        @Override
-        public void beforePassivation( ServiceReference<TestService> passivated )
-            throws Exception
-        {
-            throw new Exception( "ACTIVATOR: FAIL BEFORE PASSIVATION for " + passivated );
-        }
-    }
-
-    public static class FailAfterPassivationServiceActivator
-        extends ActivatorAdapter<ServiceReference<TestService>>
-    {
-        @Override
-        public void afterPassivation( ServiceReference<TestService> passivated )
-            throws Exception
-        {
-            throw new Exception( "ACTIVATOR: FAIL AFTER PASSIVATION for " + passivated );
-        }
-    }
-
-    public static class TestActivationEventListener
-        implements ActivationEventListener
-    {
-        @Override
-        public void onEvent( ActivationEvent event )
-            throws Exception
-        {
-            if( !( event.source() instanceof Application )
-                && !( event.source() instanceof Layer )
-                && !( event.source() instanceof Module ) )
-            {
-                return;
-            }
-            switch( event.type() )
-            {
-                case PASSIVATING:
-                    throw new Exception( "EVENT: FAIL BEFORE PASSIVATION for " + event.source() );
-                case PASSIVATED:
-                    throw new Exception( "EVENT: FAIL AFTER PASSIVATION for " + event.source() );
-            }
-        }
-    }
-
-}
diff --git a/core/api/src/test/java/org/qi4j/api/annotation/MixinsTest.java b/core/api/src/test/java/org/qi4j/api/annotation/MixinsTest.java
deleted file mode 100644
index 475ad75..0000000
--- a/core/api/src/test/java/org/qi4j/api/annotation/MixinsTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2007 Alin Dreghiciu. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.annotation;
-
-import java.lang.annotation.Annotation;
-import org.junit.Test;
-import org.qi4j.api.mixin.Mixins;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-/**
- * Tests public api exposed by Mixins annotation.
- * This will ensure that the public api does not get changed by mistake.
- */
-public class MixinsTest
-{
-
-    @Test
-    public void retention()
-    {
-        Annotation[] annotations = Annotated.class.getDeclaredAnnotations();
-        assertNotNull( "annotations should not be null", annotations );
-        assertEquals( "number of annotations", 1, annotations.length );
-        assertEquals( "annotation type", Mixins.class, annotations[ 0 ].annotationType() );
-    }
-
-    @Mixins( Object.class )
-    private static class Annotated
-    {
-
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/annotation/ModifiedByTest.java b/core/api/src/test/java/org/qi4j/api/annotation/ModifiedByTest.java
deleted file mode 100644
index 50227c4..0000000
--- a/core/api/src/test/java/org/qi4j/api/annotation/ModifiedByTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2007 Alin Dreghiciu. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.annotation;
-
-import java.lang.annotation.Annotation;
-import org.junit.Test;
-import org.qi4j.api.concern.Concerns;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-/**
- * Tests public api exposed by Concerns annotation.
- * This will ensure that the public api does not get changed by mistake.
- */
-public class ModifiedByTest
-{
-
-    @Test
-    public void retention()
-    {
-        Annotation[] annotations = Annotated.class.getDeclaredAnnotations();
-        assertNotNull( "annotations should not be null", annotations );
-        assertEquals( "number of annotations", 1, annotations.length );
-        assertEquals( "annotation type", Concerns.class, annotations[ 0 ].annotationType() );
-    }
-
-    @Concerns( Object.class )
-    private static class Annotated
-    {
-
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/annotation/scope/ModifiesTest.java b/core/api/src/test/java/org/qi4j/api/annotation/scope/ModifiesTest.java
deleted file mode 100644
index d984105..0000000
--- a/core/api/src/test/java/org/qi4j/api/annotation/scope/ModifiesTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2007 Alin Dreghiciu. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.annotation.scope;
-
-import java.lang.annotation.Annotation;
-import org.junit.Test;
-import org.qi4j.api.concern.internal.ConcernFor;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-/**
- * Tests public api exposed by Modified annotation.
- * This will ensure that the public api does not get changed by mistake.
- */
-public class ModifiesTest
-{
-
-    @Test
-    public void retention()
-        throws NoSuchFieldException
-    {
-        Annotation[] annotations = Annotated.class.getDeclaredField( "modified" ).getDeclaredAnnotations();
-        assertNotNull( "annotations should not be null", annotations );
-        assertEquals( "number of annotations", 1, annotations.length );
-        assertEquals( "annotation type", ConcernFor.class, annotations[ 0 ].annotationType() );
-    }
-
-    private static class Annotated
-    {
-        @ConcernFor
-        String modified;
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/common/AppliesToTest.java b/core/api/src/test/java/org/qi4j/api/common/AppliesToTest.java
deleted file mode 100644
index a2093f8..0000000
--- a/core/api/src/test/java/org/qi4j/api/common/AppliesToTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2007 Alin Dreghiciu. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.common;
-
-import java.lang.annotation.Annotation;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-/**
- * Tests public api exposed by AppliesTo annotation.
- * This will ensure that the public api does not get changed by mistake.
- */
-public class AppliesToTest
-{
-
-    @Test
-    public void retention()
-    {
-        Annotation[] annotations = Annotated.class.getDeclaredAnnotations();
-        assertNotNull( "annotations should not be null", annotations );
-        assertEquals( "number of annotations", 1, annotations.length );
-        assertEquals( "annotation type", AppliesTo.class, annotations[ 0 ].annotationType() );
-    }
-
-    @AppliesTo( Object.class )
-    private static class Annotated
-    {
-
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/common/QualifiedNameTest.java b/core/api/src/test/java/org/qi4j/api/common/QualifiedNameTest.java
deleted file mode 100644
index 44015e0..0000000
--- a/core/api/src/test/java/org/qi4j/api/common/QualifiedNameTest.java
+++ /dev/null
@@ -1,83 +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.qi4j.api.common;
-
-import org.junit.Test;
-import org.qi4j.api.util.NullArgumentException;
-
-import static org.junit.Assert.assertEquals;
-
-public class QualifiedNameTest
-{
-    @Test
-    public void testQualifiedNameWithDollar()
-    {
-        assertEquals( "Name containing dollar is modified", "Test-Test",
-                      new QualifiedName( TypeName.nameOf( "Test$Test" ), "satisfiedBy" ).type() );
-    }
-
-    @Test
-    public void testQualifiedNameFromQNWithDollar()
-    {
-        assertEquals( "Name containing dollar is cleaned up", "Test-Test",
-                      QualifiedName.fromFQN( "Test$Test:satisfiedBy" ).type() );
-    }
-
-    @Test( expected = NullArgumentException.class )
-    public void nonNullArguments1()
-    {
-        new QualifiedName( TypeName.nameOf( "Test" ), null );
-    }
-
-    @Test( expected = NullArgumentException.class )
-    public void nonNullArguments2()
-    {
-        new QualifiedName( null, "satisfiedBy" );
-    }
-
-    @Test( expected = NullArgumentException.class )
-    public void nonNullArguments3()
-    {
-        new QualifiedName( null, null );
-    }
-
-    @Test( expected = NullArgumentException.class )
-    public void nonNullArguments4()
-    {
-        QualifiedName.fromFQN( null );
-    }
-
-    @Test( expected = NullArgumentException.class )
-    public void nonNullArguments5()
-    {
-        QualifiedName.fromAccessor( null );
-    }
-
-    @Test( expected = NullArgumentException.class )
-    public void nonNullArguments6()
-    {
-        QualifiedName.fromClass( null, "satisfiedBy" );
-    }
-
-    @Test( expected = NullArgumentException.class )
-    public void nonNullArguments7()
-    {
-        QualifiedName.fromClass( null, null );
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/composite/PropertyMapperTest.java b/core/api/src/test/java/org/qi4j/api/composite/PropertyMapperTest.java
deleted file mode 100644
index 1a10440..0000000
--- a/core/api/src/test/java/org/qi4j/api/composite/PropertyMapperTest.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.api.composite;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.junit.Test;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class PropertyMapperTest
-{
-    private final static Method MAP_TO_TYPE;
-
-    static
-    {
-        try
-        {
-            MAP_TO_TYPE = PropertyMapper.class.getDeclaredMethod( "mapToType", Composite.class, Type.class, Object.class );
-            MAP_TO_TYPE.setAccessible( true );
-        }
-        catch( NoSuchMethodException e )
-        {
-            InternalError error = new InternalError();
-            error.initCause( e );
-            throw error;
-        }
-    }
-
-    @Test
-    public void testMappingOfInteger()
-        throws Exception
-    {
-        assertEquals( 5, mapToType( null, Integer.class, "5" ) );
-        assertEquals( -5, mapToType( null, Integer.class, "-5" ) );
-        assertEquals( Integer.class, mapToType( null, Integer.class, "5" ).getClass() );
-    }
-
-    @Test
-    public void testMappingOfLong()
-        throws Exception
-    {
-        assertEquals( 5L, mapToType( null, Long.class, "5" ) );
-        assertEquals( 5876328476238746238L, mapToType( null, Long.class, "5876328476238746238" ) );
-        assertEquals( Long.class, mapToType( null, Long.class, "5" ).getClass() );
-    }
-
-    @Test
-    public void testMappingOfBoolean()
-        throws Exception
-    {
-        assertEquals( false, mapToType( null, Boolean.class, "false" ) );
-        assertEquals( true, mapToType( null, Boolean.class, "true" ) );
-        assertEquals( Boolean.class, mapToType( null, Boolean.class, "false" ).getClass() );
-    }
-
-    @Test
-    public void testMappingOfFloat()
-        throws Exception
-    {
-        assertEquals( 5.1234f, mapToType( null, Float.class, "5.1234" ) );
-        assertEquals( 5876328476.6238f, mapToType( null, Float.class, "5876328476.6238" ) );
-        assertEquals( Float.class, mapToType( null, Float.class, "5" ).getClass() );
-    }
-
-    @Test
-    public void testMappingOfDouble()
-        throws Exception
-    {
-        assertEquals( 5.1234, mapToType( null, Double.class, "5.1234" ) );
-        assertEquals( 5876328476.623823, mapToType( null, Double.class, "5876328476.623823" ) );
-        assertEquals( Double.class, mapToType( null, Double.class, "5" ).getClass() );
-    }
-
-    @Test
-    public void testMappingOfBigDecimal()
-        throws Exception
-    {
-        assertEquals( new BigDecimal( 3 ), mapToType( null, BigDecimal.class, "3" ) );
-        assertEquals( new BigDecimal( "12345.67891011" ), mapToType( null, BigDecimal.class, "12345.67891011" ) );
-        assertEquals( BigDecimal.class, mapToType( null, BigDecimal.class, "5" ).getClass() );
-    }
-
-    @Test
-    public void testMappingOfBigInteger()
-        throws Exception
-    {
-        assertEquals( new BigInteger( "20", 16 ), mapToType( null, BigInteger.class, "32" ) );
-        assertEquals( new BigInteger( "1234567891011" ), mapToType( null, BigInteger.class, "1234567891011" ) );
-        assertEquals( BigInteger.class, mapToType( null, BigInteger.class, "5" ).getClass() );
-    }
-
-    @Test
-    public void testMappingOfEnum()
-        throws Exception
-    {
-        assertEquals( TestEnum.FIRST, mapToType( null, TestEnum.class, "FIRST" ) );
-        assertEquals( TestEnum.SECOND, mapToType( null, TestEnum.class, "SECOND" ) );
-        assertEquals( TestEnum.class, mapToType( null, TestEnum.class, "SECOND" ).getClass() );
-    }
-
-    @Test
-    public void testMappingOfIntegerArray()
-        throws Exception
-    {
-        Object[] value = (Object[]) mapToType( null, Integer[].class, "5,4 , 3   ,2,1" );
-        assertEquals( 5, value.length );
-        assertEquals( 5, value[ 0 ] );
-        assertEquals( 4, value[ 1 ] );
-        assertEquals( 3, value[ 2 ] );
-        assertEquals( 2, value[ 3 ] );
-        assertEquals( 1, value[ 4 ] );
-    }
-
-    @Test
-    public void testMappingOfStringArray()
-        throws Exception
-    {
-        {
-            Object[] value = (Object[]) mapToType( null, String[].class, "5,4 , 3   ,2,1" );
-            assertEquals( 5, value.length );
-            assertEquals( "5", value[ 0 ] );
-            assertEquals( "4 ", value[ 1 ] );
-            assertEquals( " 3   ", value[ 2 ] );
-            assertEquals( "2", value[ 3 ] );
-            assertEquals( "1", value[ 4 ] );
-        }
-        {
-            Object[] value = (Object[]) mapToType( null, String[].class, "5,4 ,\" 3,   \",  \" 2\" ,1" );
-            assertEquals( "5", value[ 0 ] );
-            assertEquals( "4 ", value[ 1 ] );
-            assertEquals( " 3,   ", value[ 2 ] );
-            assertEquals( " 2", value[ 3 ] );
-            assertEquals( "1", value[ 4 ] );
-            assertEquals( 5, value.length );
-        }
-    }
-
-    @Test
-    public void testMappingOfBooleanArray()
-        throws Exception
-    {
-        Object[] value = (Object[]) mapToType( null, Boolean[].class, " true,false,  false, true ,true,false" );
-        assertEquals( true, value[ 0 ] );
-        assertEquals( false, value[ 1 ] );
-        assertEquals( false, value[ 2 ] );
-        assertEquals( true, value[ 3 ] );
-        assertEquals( true, value[ 4 ] );
-        assertEquals( false, value[ 5 ] );
-        assertEquals( 6, value.length );
-    }
-
-    @Test
-    public void testMappingOfList()
-        throws Exception
-    {
-        Type type = Testing.class.getDeclaredMethod( "list" ).getGenericReturnType();
-        List<String> value = (List<String>) mapToType( null, type, "5,4 ,\" 3,   \",  \" 2\" ,1" );
-        assertEquals( "5", value.get( 0 ) );
-        assertEquals( "4 ", value.get( 1 ) );
-        assertEquals( " 3,   ", value.get( 2 ) );
-        assertEquals( " 2", value.get( 3 ) );
-        assertEquals( "1", value.get( 4 ) );
-        assertEquals( 5, value.size() );
-    }
-
-    @Test
-    public void testMappingOfSet()
-        throws Exception
-    {
-        Type type = Testing.class.getDeclaredMethod( "set" ).getGenericReturnType();
-        Set<String> value = (Set<String>) mapToType( null, type, "5,4 ,\" 3,   \",  \" 2\" ,1" );
-        assertTrue( value.contains( "5" ) );
-        assertTrue( value.contains( "4 " ) );
-        assertTrue( value.contains( " 3,   " ) );
-        assertTrue( value.contains( " 2" ) );
-        assertTrue( value.contains( "1" ) );
-        assertEquals( 5, value.size() );
-    }
-
-    @Test
-    public void testMappingOfMap()
-        throws Exception
-    {
-        Type type = Testing.class.getDeclaredMethod( "map" ).getGenericReturnType();
-        Map<String, String> value = (Map<String, String>) mapToType( null, type, "first:5,second:4 , third:\" 3,   \", fourth:  \" 2\" ,fifth : 1" );
-        assertEquals( "5", value.get( "first" ) );
-        assertEquals( "4 ", value.get( "second" ) );
-        assertEquals( " 3,   ", value.get( " third" ) );
-        assertEquals( " 2", value.get( " fourth" ) );
-        assertEquals( " 1", value.get( "fifth " ) );
-        assertEquals( 5, value.size() );
-    }
-
-    private Object mapToType( Composite composite, Type propertyType, Object value )
-        throws IllegalAccessException, InvocationTargetException
-    {
-        return MAP_TO_TYPE.invoke( null, composite, propertyType, value );
-    }
-
-    interface Testing
-    {
-        List<String> list();
-
-        Set<String> set();
-
-        Map<String, String> map();
-    }
-
-    enum TestEnum
-    {
-        FIRST,
-        SECOND
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/concern/DocumentationSupport.java b/core/api/src/test/java/org/qi4j/api/concern/DocumentationSupport.java
deleted file mode 100644
index 69cfc5c..0000000
--- a/core/api/src/test/java/org/qi4j/api/concern/DocumentationSupport.java
+++ /dev/null
@@ -1,100 +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.qi4j.api.concern;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.AppliesToFilter;
-import org.qi4j.api.injection.InjectionScope;
-
-public class DocumentationSupport
-{
-// START SNIPPET: class
-    @AppliesTo( java.sql.Connection.class )
-    public class CacheConcern extends GenericConcern
-        implements InvocationHandler
-    {
-// END SNIPPET: class
-        @Override
-        public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-        {
-            return null;
-        }
-    }
-
-// START SNIPPET: filter
-    @AppliesTo( BusinessAppliesToFilter.class )
-    public class BusinessConcern extends GenericConcern
-        implements InvocationHandler
-    {
-// END SNIPPET: filter
-        @Override
-        public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-        {
-            return null;
-        }
-    }
-
-// START SNIPPET: filter
-    public class BusinessAppliesToFilter
-        implements AppliesToFilter
-    {
-
-        @Override
-        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass
-        )
-        {
-            return true; // Some criteria for when a method is wrapped with the concern.
-        }
-    }
-// END SNIPPET: filter
-
-
-// START SNIPPET: annotation
-    @AppliesTo( Audited.class )
-    public class AuditConcern extends GenericConcern
-        implements InvocationHandler
-    {
-// START SNIPPET: annotation
-        @Override
-        public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-        {
-            return null;
-        }
-    }
-
-// START SNIPPET: annotation
-    @Retention( RetentionPolicy.RUNTIME )
-    @Target( { ElementType.METHOD } )
-    @Documented
-    @InjectionScope
-    public @interface Audited
-    {
-    }
-// END SNIPPET: annotation
-}
diff --git a/core/api/src/test/java/org/qi4j/api/configuration/ConfigurationTest.java b/core/api/src/test/java/org/qi4j/api/configuration/ConfigurationTest.java
deleted file mode 100644
index c72afe7..0000000
--- a/core/api/src/test/java/org/qi4j/api/configuration/ConfigurationTest.java
+++ /dev/null
@@ -1,109 +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.qi4j.api.configuration;
-
-import org.junit.Test;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-public class ConfigurationTest extends AbstractQi4jTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( MyService.class ).instantiateOnStartup();
-        module.entities( MyConfig.class );
-        module.values( PersonDetails.class, Address.class, City.class, Country.class );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Test
-    public void testConfiguration()
-        throws Exception
-    {
-        MyService service = module.findService( MyService.class ).get();
-        PersonDetails details = service.details();
-        assertThat(details.name().get(), equalTo( "Niclas" ) );
-        assertThat(details.address().get().street1().get(), equalTo( "Henan Lu 555" ) );
-        assertThat(details.address().get().street2().get(), equalTo( "Block 15" ) );
-        assertThat(details.address().get().city().get().cityName().get(), equalTo( "Shanghai" ) );
-        assertThat(details.address().get().city().get().country().get().countryName().get(), equalTo( "China" ) );
-    }
-
-    @Mixins(MyServiceMixin.class)
-    public interface MyService extends ServiceComposite
-    {
-        PersonDetails details();
-    }
-
-    public abstract class MyServiceMixin
-        implements MyService
-    {
-        @This
-        Configuration<MyConfig> myconf;
-
-        @Override
-        public PersonDetails details()
-        {
-            return myconf.get().me().get();
-        }
-    }
-
-    public interface MyConfig extends ConfigurationComposite
-    {
-        Property<PersonDetails> me();
-    }
-
-    public interface PersonDetails extends ValueComposite
-    {
-        Property<String> name();
-        Property<Address> address();
-
-    }
-
-    public interface Address extends ValueComposite
-    {
-        Property<String> street1();
-        Property<String> street2();
-        Property<City> city();
-    }
-
-    public interface City extends ValueComposite
-    {
-        Property<String> cityName();
-        Property<Country> country();
-    }
-
-    public interface Country extends ValueComposite
-    {
-        Property<String> countryName();
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/configuration/DeclareConfigurationDefaultsTest.java b/core/api/src/test/java/org/qi4j/api/configuration/DeclareConfigurationDefaultsTest.java
deleted file mode 100644
index 404f126..0000000
--- a/core/api/src/test/java/org/qi4j/api/configuration/DeclareConfigurationDefaultsTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.api.configuration;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-public class DeclareConfigurationDefaultsTest
-        extends AbstractQi4jTest
-{
-
-    @Mixins( FooServiceMixin.class )
-    public static interface FooServiceComposite
-            extends ServiceComposite
-    {
-
-        String configuredFoo();
-
-    }
-
-    public static abstract class FooServiceMixin
-            implements FooServiceComposite
-    {
-
-        @This
-        private Configuration<FooConfigurationComposite> config;
-
-        public String configuredFoo()
-        {
-            return config.get().foo().get();
-        }
-
-    }
-
-    public static interface FooConfigurationComposite
-            extends ConfigurationComposite
-    {
-
-        Property<String> foo();
-
-    }
-
-    public void assemble( ModuleAssembly module )
-            throws AssemblyException
-    {
-        module.services( FooServiceComposite.class ).identifiedBy( "bazar" );
-        module.entities( FooConfigurationComposite.class );
-        new EntityTestAssembler().assemble( module );
-        FooConfigurationComposite config = module.forMixin( FooConfigurationComposite.class ).declareDefaults();
-        config.foo().set( "bar" );
-    }
-
-    @Test
-    public void testConfigurationDefaults()
-    {
-        FooServiceComposite fooService = module.findService( FooServiceComposite.class ).get();
-        Assert.assertEquals( "bar", fooService.configuredFoo() );
-    }
-
-}
diff --git a/core/api/src/test/java/org/qi4j/api/configuration/MailService.java b/core/api/src/test/java/org/qi4j/api/configuration/MailService.java
deleted file mode 100644
index 18817cf..0000000
--- a/core/api/src/test/java/org/qi4j/api/configuration/MailService.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.api.configuration;
-
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.library.constraints.annotation.Email;
-import org.qi4j.library.constraints.annotation.MinLength;
-
-// Documentation Support
-@Mixins( MailService.MailServiceMixin.class )
-public interface MailService
-{
-    void sendMail( @Email String to, @MinLength( 8 ) String subject, String body );
-    
-    // START SNIPPET: write
-    void changeExternalMailService( String hostName, int port );
-    // END SNIPPET: write
-    
-    public class MailServiceMixin
-        implements MailService
-    {
-        // START SNIPPET: read        
-        @This
-        private Configuration<MailServiceConfiguration> config;
-
-        @Override
-        public void sendMail( @Email String to, @MinLength( 8 ) String subject, String body )
-        {
-            config.refresh();
-            MailServiceConfiguration conf = config.get();
-            String hostName = conf.hostName().get();
-            int port = conf.port().get();
-            // END SNIPPET: read
-
-            // START SNIPPET: read        
-        }
-        // END SNIPPET: read        
-
-        // START SNIPPET: write        
-        @Override
-        public void changeExternalMailService( String hostName, int port )
-        {
-            MailServiceConfiguration conf = config.get();
-            conf.hostName().set( hostName );
-            conf.port().set( port );
-            config.save();
-        }
-        // START SNIPPET: write        
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/configuration/MailServiceConfiguration.java b/core/api/src/test/java/org/qi4j/api/configuration/MailServiceConfiguration.java
deleted file mode 100644
index 698fadf..0000000
--- a/core/api/src/test/java/org/qi4j/api/configuration/MailServiceConfiguration.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.configuration;
-
-import org.qi4j.api.property.Property;
-
-// Documentation Support class
-// START SNIPPET: configuration
-public interface MailServiceConfiguration extends ConfigurationComposite
-{
-    Property<String> hostName();
-
-    Property<Integer> port();
-}
-// END SNIPPET: configuration
diff --git a/core/api/src/test/java/org/qi4j/api/dataset/iterable/IterableDataSetTest.java b/core/api/src/test/java/org/qi4j/api/dataset/iterable/IterableDataSetTest.java
deleted file mode 100644
index 6a6c3b8..0000000
--- a/core/api/src/test/java/org/qi4j/api/dataset/iterable/IterableDataSetTest.java
+++ /dev/null
@@ -1,61 +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.qi4j.api.dataset.iterable;
-
-import org.junit.Before;
-import org.junit.Ignore;
-import org.qi4j.api.dataset.DataSet;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Iterables;
-import org.qi4j.test.AbstractQi4jTest;
-
-/**
- * TODO
- */
-@Ignore( "Not implemented yet" )
-public class IterableDataSetTest
-    extends AbstractQi4jTest
-{
-    DataSet<TestValue> dataSet;
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.values( TestValue.class );
-    }
-
-    @Before
-    public void setUp()
-    {
-        dataSet = new IterableDataSet<TestValue>( Iterables.iterable( newTestValue( "Rickard" ), newTestValue( "Niclas" ), newTestValue( "Paul" ) ) );
-    }
-
-    private TestValue newTestValue( String name )
-    {
-        return module.newValueFromSerializedState( TestValue.class, "{name:'" + name + "'}" );
-    }
-
-    interface TestValue
-    {
-        Property<String> name();
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/docsupport/ApplicationDocs.java b/core/api/src/test/java/org/qi4j/api/docsupport/ApplicationDocs.java
deleted file mode 100644
index 0db8620..0000000
--- a/core/api/src/test/java/org/qi4j/api/docsupport/ApplicationDocs.java
+++ /dev/null
@@ -1,274 +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.qi4j.api.docsupport;
-
-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.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-public class ApplicationDocs
-{
-    public static void someMethod( String[] args )
-        throws Exception
-    {
-        {
-// START SNIPPET: application1
-            SingletonAssembler qi4j = new SingletonAssembler()
-            {
-                public void assemble( ModuleAssembly assembly )
-                    throws AssemblyException
-                {
-                    assembly.values( MyStuffValueComposite.class );
-                }
-            };
-// END SNIPPET: application1
-        }
-        {
-            Assembler customerListEditAssembler = new DummyAssembler();
-            Assembler customerEditAssembler = new DummyAssembler();
-            Assembler customerSearchAssembler = new DummyAssembler();
-            Assembler accountsListEditAssembler = new DummyAssembler();
-            Assembler accountsEditAssembler = new DummyAssembler();
-            Assembler accountsSearchAssembler = new DummyAssembler();
-            Assembler customerDomainAssembler = new DummyAssembler();
-            Assembler accountsDomainAssembler = new DummyAssembler();
-// START SNIPPET: application2
-            final Assembler[][][] assemblers =
-                {
-                    { // web layer
-                      { // Customer Module
-                        customerListEditAssembler,
-                        customerEditAssembler,
-                        customerSearchAssembler
-                      },
-                      { // Accounts Module
-                        accountsListEditAssembler,
-                        accountsEditAssembler,
-                        accountsSearchAssembler
-                      }
-                    },
-                    { // domain layer
-                      { // Customer Module
-                        customerDomainAssembler,
-                      },
-                      { // Accounts Module
-                        accountsDomainAssembler,
-                      }
-                    }
-                };
-            Energy4Java qi4j = new Energy4Java();
-            Application app = qi4j.newApplication( new ApplicationAssembler()
-            {
-
-                @Override
-                public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-                    throws AssemblyException
-                {
-                    return applicationFactory.newApplicationAssembly( assemblers );
-                }
-            } );
-            app.activate();
-// END SNIPPET: application2
-        }
-    }
-
-    public interface MyStuffValueComposite
-    {
-    }
-
-    private static class DummyAssembler implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-
-        }
-    }
-
-    // START SNIPPET: application3
-    private static Energy4Java qi4j;
-
-    public static void main( String[] args )
-        throws Exception
-    {
-        qi4j = new Energy4Java();
-        ApplicationDescriptor model = qi4j.newApplicationModel( new ApplicationAssembler()
-        {
-            @Override
-            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-                throws AssemblyException
-            {
-                return createAssembly( applicationFactory );
-            }
-        } );
-        Application application = model.newInstance( qi4j.spi() );
-    }
-
-    private static ApplicationAssembly createAssembly( ApplicationAssemblyFactory factory )
-        throws AssemblyException
-    {
-        String applicationName = "Example Application";
-        ApplicationAssembly app = factory.newApplicationAssembly();
-        app.setName( applicationName );
-        LayerAssembly webLayer = createWebLayer( app );
-        LayerAssembly domainLayer = createDomainLayer( app );
-        LayerAssembly infraLayer = createInfrastructureLayer( app );
-        webLayer.uses( domainLayer );
-        webLayer.uses( infraLayer );  // Accesses the WebService
-        domainLayer.uses( infraLayer ); // For persistence
-        return app;
-    }
-
-    private static LayerAssembly createWebLayer(
-        ApplicationAssembly application
-    )
-    {
-        LayerAssembly layer = application.layer( "Web Layer" );
-        createCustomerWebModule( layer );
-        return layer;
-    }
-
-    private static LayerAssembly createDomainLayer(
-        ApplicationAssembly application
-    )
-    {
-        LayerAssembly layer = application.layer( "Domain Layer" );
-        createCustomerDomainModule( layer );
-        // :
-        // :
-        return layer;
-    }
-
-    private static LayerAssembly createInfrastructureLayer(
-        ApplicationAssembly application
-    )
-        throws AssemblyException
-    {
-        LayerAssembly layer = application.layer( "Infrastructure Layer" );
-        createWebServiceModule( layer );
-        createPersistenceModule( layer );
-        return layer;
-    }
-
-    private static void createCustomerWebModule( LayerAssembly layer )
-    {
-        ModuleAssembly assembly = layer.module( "Customer Web Module" );
-        assembly.transients( CustomerViewComposite.class );
-        assembly.transients( CustomerEditComposite.class );
-        assembly.transients( CustomerListViewComposite.class );
-        assembly.transients( CustomerSearchComposite.class );
-    }
-
-    private static void createCustomerDomainModule( LayerAssembly layer )
-    {
-        ModuleAssembly assembly = layer.module( "Customer Domain Module" );
-        assembly.entities( CustomerEntity.class );
-        assembly.entities( CountryEntity.class );
-        assembly.transients( AddressComposite.class );
-    }
-
-    private static void createWebServiceModule( LayerAssembly layer )
-        throws AssemblyException
-    {
-        ModuleAssembly assembly = layer.module( "Web Service Module" );
-        // Someone has created an assembler for a Jetty Web Service.
-        JettyAssembler jetty = new JettyAssembler( 8080 );
-        jetty.assemble( assembly );
-    }
-
-    private static void createPersistenceModule( LayerAssembly layer )
-        throws AssemblyException
-    {
-        ModuleAssembly assembly = layer.module( "Persistence Module" );
-        // Someone has created an assembler for the Neo EntityStore
-        NeoAssembler neo = new NeoAssembler( "./neostore" );
-        neo.assemble( assembly );
-    }
-// START SNIPPET: application3
-
-    public static class CustomerViewComposite
-    {
-
-    }
-    public static class CustomerEditComposite
-    {
-
-    }
-    public static class CustomerListViewComposite
-    {
-
-    }
-    public static class CustomerSearchComposite
-    {
-
-    }
-
-
-    public static class CustomerEntity
-    {
-
-    }
-    public static class CountryEntity
-    {
-
-    }
-    public static class AddressComposite
-    {
-
-    }
-
-    public static class JettyAssembler
-        implements Assembler
-    {
-
-        public JettyAssembler( int port )
-        {
-        }
-
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-        }
-    }
-    public static class NeoAssembler
-        implements Assembler
-    {
-
-        public NeoAssembler( String s )
-        {
-        }
-
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-        }
-    }
-}
-
diff --git a/core/api/src/test/java/org/qi4j/api/docsupport/CompositionDocs.java b/core/api/src/test/java/org/qi4j/api/docsupport/CompositionDocs.java
deleted file mode 100644
index a6a366c..0000000
--- a/core/api/src/test/java/org/qi4j/api/docsupport/CompositionDocs.java
+++ /dev/null
@@ -1,56 +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.qi4j.api.docsupport;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-public class CompositionDocs
-{
-// START SNIPPET: comp1
-    @Mixins( { BalanceCheckMixin.class } )
-    public interface BankAccount
-    {
-        Money checkBalance();
-// END SNIPPET: comp1
-// START SNIPPET: comp1
-    }
-// END SNIPPET: comp1
-
-// START SNIPPET: comp2
-    public void assemble( ModuleAssembly module )
-    {
-        module.entities( BankAccount.class );
-    }
-// END SNIPPET: comp2
-
-    public static class BalanceCheckMixin
-        implements BankAccount
-    {
-        @Override
-        public Money checkBalance()
-        {
-            return null;
-        }
-    }
-
-    public static class Money
-    {
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/docsupport/package.html b/core/api/src/test/java/org/qi4j/api/docsupport/package.html
deleted file mode 100644
index f6fa115..0000000
--- a/core/api/src/test/java/org/qi4j/api/docsupport/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-<body>
-This package exists to contain snippets for documentation.
-</body>
-</html>
\ No newline at end of file
diff --git a/core/api/src/test/java/org/qi4j/api/injection/scope/StateFieldTest.java b/core/api/src/test/java/org/qi4j/api/injection/scope/StateFieldTest.java
deleted file mode 100644
index 38dcc52..0000000
--- a/core/api/src/test/java/org/qi4j/api/injection/scope/StateFieldTest.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.injection.scope;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-/**
- * Define a field to be a Property
- */
-public class StateFieldTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.entities( PersonEntity.class );
-    }
-
-    @Test
-    public void givenEntityWithFieldPropertiesWhenUpdatedThenReturnCorrect()
-        throws Exception
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            PersonEntity charles = unitOfWork.newEntity( PersonEntity.class );
-            charles.changeName( "Charles" );
-            Assert.assertEquals( charles.getName(), "Charles" );
-
-            PersonEntity daniel = unitOfWork.newEntity( PersonEntity.class );
-            daniel.changeName( "Daniel" );
-            Assert.assertEquals( daniel.getName(), "Daniel" );
-
-            PersonEntity lisa = unitOfWork.newEntity( PersonEntity.class );
-            lisa.changeName( "Lisa" );
-            Assert.assertEquals( lisa.getName(), "Lisa" );
-
-            charles.befriend( daniel );
-            charles.befriend( lisa );
-            charles.marry( lisa );
-
-            unitOfWork.complete();
-
-            unitOfWork = module.newUnitOfWork();
-
-            charles = unitOfWork.get( charles );
-            daniel = unitOfWork.get( daniel );
-            Assert.assertTrue( charles.isFriend( daniel ) );
-
-            unitOfWork.complete();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    @Mixins( PersonEntity.Mixin.class )
-    public interface PersonEntity
-        extends EntityComposite
-    {
-        void changeName( String newName );
-
-        void marry( PersonEntity entity );
-
-        void befriend( PersonEntity entity );
-
-        boolean isFriend( PersonEntity entity );
-
-        String getName();
-
-        abstract class Mixin
-            implements PersonEntity
-        {
-            @State
-            @UseDefaults
-            public Property<String> name;
-
-            @State
-            @Optional
-            public Association<PersonEntity> spouse;
-
-            @State
-            public ManyAssociation<PersonEntity> friends;
-
-            @Override
-            public void changeName( String newName )
-            {
-                name.set( newName );
-            }
-
-            @Override
-            public void marry( PersonEntity entity )
-            {
-                spouse.set( entity );
-            }
-
-            @Override
-            public void befriend( PersonEntity entity )
-            {
-                friends.add( entity );
-            }
-
-            @Override
-            public String getName()
-            {
-                return name.get();
-            }
-
-            @Override
-            public boolean isFriend( PersonEntity entity )
-            {
-                return friends.contains( entity );
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/test/java/org/qi4j/api/injection/scope/ThisTest.java b/core/api/src/test/java/org/qi4j/api/injection/scope/ThisTest.java
deleted file mode 100644
index cae4e3b..0000000
--- a/core/api/src/test/java/org/qi4j/api/injection/scope/ThisTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2007 Alin Dreghiciu. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.injection.scope;
-
-import java.lang.annotation.Annotation;
-import org.junit.Test;
-import org.qi4j.api.common.Optional;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-/**
- * Tests public api exposed by This annotation.
- * This will ensure that the public api does not get changed by mistake.
- */
-public class ThisTest
-{
-
-    @Test
-    public void retention()
-        throws NoSuchFieldException
-    {
-        Annotation[] annotations = Annotated.class.getDeclaredField( "uses" ).getDeclaredAnnotations();
-        assertNotNull( "annotations should not be null", annotations );
-        assertEquals( "number of annotations", 1, annotations.length );
-        assertEquals( "annotation type", This.class, annotations[ 0 ].annotationType() );
-    }
-
-    private static class Annotated
-    {
-        @This
-        String uses;
-        @Optional
-        @This
-        String usesOptional;
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/metrics/DocumentationSupport.java b/core/api/src/test/java/org/qi4j/api/metrics/DocumentationSupport.java
deleted file mode 100644
index 4d9a139..0000000
--- a/core/api/src/test/java/org/qi4j/api/metrics/DocumentationSupport.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.metrics;
-
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-import org.qi4j.api.injection.scope.Service;
-
-public class DocumentationSupport
-{
-    // START SNIPPET: common
-    @Service
-    private MetricsProvider provider;
-    // END SNIPPET: common
-
-    public void forDocumentationOnly()
-    {
-        // START SNIPPET: gauge
-        final BlockingQueue queue = new LinkedBlockingQueue( 20 );
-        // END SNIPPET: gauge
-        // START SNIPPET: gauge
-        MetricsGaugeFactory gaugeFactory = provider.createFactory( MetricsGaugeFactory.class );
-        MetricsGauge<Integer> gauge = gaugeFactory.registerGauge( getClass(), "Sample Gauge", new MetricsGauge<Integer>()
-        {
-            @Override
-            public Integer value()
-            {
-                return queue.size();
-            }
-        } );
-        // END SNIPPET: gauge
-
-        // START SNIPPET: counter
-        MetricsCounterFactory counterFactory = provider.createFactory( MetricsCounterFactory.class );
-        MetricsCounter counter = counterFactory.createCounter( getClass(), "Sample Counter" );
-        // END SNIPPET: counter
-
-        // START SNIPPET: histogram
-        MetricsHistogramFactory histoFactory = provider.createFactory( MetricsHistogramFactory.class );
-        MetricsHistogram histogram = histoFactory.createHistogram( getClass(), "Sample Histogram" );
-        // END SNIPPET: histogram
-
-        // START SNIPPET: meter
-        MetricsMeterFactory meterFactory = provider.createFactory( MetricsMeterFactory.class );
-        MetricsMeter meter = meterFactory.createMeter( getClass(), "Sample Meter", "requests", TimeUnit.MINUTES );
-        // END SNIPPET: meter
-
-        // START SNIPPET: timer
-        MetricsTimerFactory timerFactory = provider.createFactory( MetricsTimerFactory.class );
-        MetricsTimer timer = timerFactory.createTimer( getClass(), "Sample Timer", TimeUnit.SECONDS, TimeUnit.HOURS );
-        // END SNIPPET: timer
-
-        // START SNIPPET: healthcheck
-        MetricsHealthCheckFactory healthFactory = provider.createFactory( MetricsHealthCheckFactory.class );
-        MetricsHealthCheck healthCheck = healthFactory.registerHealthCheck(
-            getClass(),
-            "Sample Healthcheck",
-            new MetricsHealthCheck()
-            {
-                @Override
-                public Result check()
-                    throws Exception
-                {
-                    ServiceStatus status = pingMyService();
-                    return new Result( status.isOk(), status.getErrorMessage(), status.getException() );
-                }
-            } );
-        // END SNIPPET: healthcheck
-
-    }
-
-    private ServiceStatus pingMyService()
-    {
-        return new ServiceStatus();
-    }
-
-    private static class ServiceStatus
-    {
-        String errorMessage;
-        Exception exception;
-
-        public String getErrorMessage()
-        {
-            return errorMessage;
-        }
-
-        public Exception getException()
-        {
-            return exception;
-        }
-
-        public boolean isOk()
-        {
-            return errorMessage.equals( "OK" );
-        }
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/BankAccount.java b/core/api/src/test/java/org/qi4j/api/mixin/BankAccount.java
deleted file mode 100644
index 218a79c..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/BankAccount.java
+++ /dev/null
@@ -1,30 +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.qi4j.api.mixin;
-
-
-// START SNIPPET: mixinType
-public interface BankAccount
-{
-    Money checkBalance();
-}
-// END SNIPPET: mixinType
-
-class Money {}
-
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/Car.java b/core/api/src/test/java/org/qi4j/api/mixin/Car.java
deleted file mode 100644
index 434952b..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/Car.java
+++ /dev/null
@@ -1,26 +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.qi4j.api.mixin;
-
-// START SNIPPET: mixins
-@Mixins( { StartMixin.class, VehicleMixin.class } )
-public interface Car extends Startable, Vehicle
-{}
-// END SNIPPET: mixins
-
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/Something.java b/core/api/src/test/java/org/qi4j/api/mixin/Something.java
deleted file mode 100644
index 027404f..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/Something.java
+++ /dev/null
@@ -1,27 +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.qi4j.api.mixin;
-
-// START SNIPPET: something
-@Mixins( SomethingMixin.class )
-public interface Something
-{}
-// END SNIPPET: something
-
-
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/SomethingMixin.java b/core/api/src/test/java/org/qi4j/api/mixin/SomethingMixin.java
deleted file mode 100644
index 63153c4..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/SomethingMixin.java
+++ /dev/null
@@ -1,32 +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.qi4j.api.mixin;
-
-// START SNIPPET: something
-public class SomethingMixin
-        implements Something
-{
-    // State is allowed.
-
-    public void doSomething()
-    {
-        // do stuff...
-    }
-}
-// END SNIPPET: something
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/StartMixin.java b/core/api/src/test/java/org/qi4j/api/mixin/StartMixin.java
deleted file mode 100644
index dbe1076..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/StartMixin.java
+++ /dev/null
@@ -1,22 +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.qi4j.api.mixin;
-
-public abstract class StartMixin implements Startable
-{}
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/Startable.java b/core/api/src/test/java/org/qi4j/api/mixin/Startable.java
deleted file mode 100644
index 3603ca2..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/Startable.java
+++ /dev/null
@@ -1,28 +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.qi4j.api.mixin;
-
-// START SNIPPET: mixins
-public interface Startable
-{
-    boolean start();
-    void stop();
-}
-
-// END SNIPPET: mixins
\ No newline at end of file
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/Vehicle.java b/core/api/src/test/java/org/qi4j/api/mixin/Vehicle.java
deleted file mode 100644
index 22705b6..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/Vehicle.java
+++ /dev/null
@@ -1,31 +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.qi4j.api.mixin;
-
-// START SNIPPET: mixins
-public interface Vehicle
-{
-    void turn(float angle);
-
-    void accelerate(float acceleration);
-
-    // more methods
-}
-
-// END SNIPPET: mixins
\ No newline at end of file
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/VehicleMixin.java b/core/api/src/test/java/org/qi4j/api/mixin/VehicleMixin.java
deleted file mode 100644
index ad19d46..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/VehicleMixin.java
+++ /dev/null
@@ -1,22 +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.qi4j.api.mixin;
-
-public abstract class VehicleMixin
-{}
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/DecoratorMixinTest.java b/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/DecoratorMixinTest.java
deleted file mode 100644
index d761d1a..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/DecoratorMixinTest.java
+++ /dev/null
@@ -1,91 +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.qi4j.api.mixin.decoratorMixin;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Proxy;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
-
-public class DecoratorMixinTest extends AbstractQi4jTest
-{
-    // START SNIPPET: assembly
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( View1.class );
-        module.transients( View2.class );
-        module.transients( FooModel.class );
-    }
-// END SNIPPET: assembly
-
-// START SNIPPET: test
-
-    @Test
-    public void testDecoration()
-    {
-        FooModelImpl model = new FooModelImpl( "Init" );
-        View1 view1 = createView1( model );
-        View2 view2 = createView2( model );
-        assertThat( view1.bar(), equalTo( "Init" ) );
-        assertThat( view2.bar(), equalTo( "Init" ) );
-        model.setBar( "New Value" );
-        assertThat( view1.bar(), equalTo( "New Value" ) );
-        assertThat( view2.bar(), equalTo( "New Value" ) );
-    }
-// END SNIPPET: test
-
-    @Test
-    public void testDecorationWithGenericMixin()
-    {
-        InvocationHandler handler = new FooModelInvocationHandler("Init");
-        ClassLoader cl = getClass().getClassLoader();
-        FooModel model = (FooModel) Proxy.newProxyInstance( cl, new Class[]{ FooModel.class }, handler );
-        View1 view1 = createView1( model );
-        View2 view2 = createView2( model );
-        assertThat( view1.bar(), equalTo( "Init" ) );
-        assertThat( view2.bar(), equalTo( "Init" ) );
-        model.setBar( "New Value" );
-        assertThat( view1.bar(), equalTo( "New Value" ) );
-        assertThat( view2.bar(), equalTo( "New Value" ) );
-    }
-
-    // START SNIPPET: create
-    public View1 createView1( FooModel model )
-    {
-        TransientBuilder<View1> builder = module.newTransientBuilder( View1.class );
-        builder.use( model );
-        return builder.newInstance();
-    }
-// END SNIPPET: create
-
-    public View2 createView2( FooModel model )
-    {
-        TransientBuilder<View2> builder = module.newTransientBuilder( View2.class );
-        builder.use( model );
-        return builder.newInstance();
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/FooModel.java b/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/FooModel.java
deleted file mode 100644
index bf74db4..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/FooModel.java
+++ /dev/null
@@ -1,36 +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.qi4j.api.mixin.decoratorMixin;
-
-import org.qi4j.api.composite.DecoratorMixin;
-import org.qi4j.api.mixin.Mixins;
-
-// START SNIPPET: decorator
-@Mixins(DecoratorMixin.class)
-// START SNIPPET: plain
-public interface FooModel
-// END SNIPPET: decorator
-{
-    String getBar();
-    void setBar(String value);
-// END SNIPPET: plain
-
-// START SNIPPET: plain
-}
-// END SNIPPET: plain
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/FooModelImpl.java b/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/FooModelImpl.java
deleted file mode 100644
index 1ad5aee..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/FooModelImpl.java
+++ /dev/null
@@ -1,41 +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.qi4j.api.mixin.decoratorMixin;
-
-public class FooModelImpl
-    implements FooModel
-{
-    private String bar;
-
-    public FooModelImpl( String bar )
-    {
-        this.bar = bar;
-    }
-
-    @Override
-    public String getBar()
-    {
-        return bar;
-    }
-
-    public void setBar( String bar )
-    {
-        this.bar = bar;
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/FooModelInvocationHandler.java b/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/FooModelInvocationHandler.java
deleted file mode 100644
index eca17f3..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/FooModelInvocationHandler.java
+++ /dev/null
@@ -1,47 +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.qi4j.api.mixin.decoratorMixin;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-
-public class FooModelInvocationHandler
-    implements InvocationHandler
-{
-    private String value;
-
-    public FooModelInvocationHandler( String value )
-    {
-        this.value = value;
-    }
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        if(method.getName().equals( "hashCode" ))
-            return hashCode();
-        if(method.getName().equals( "equals" ))
-            return equals(args[0]);
-        if(args==null || args.length==0)
-            return value;
-        value = (String) args[0];
-        return null;
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/View1.java b/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/View1.java
deleted file mode 100644
index a890433..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/View1.java
+++ /dev/null
@@ -1,43 +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.qi4j.api.mixin.decoratorMixin;
-
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-
-// START SNIPPET: decorator
-@Mixins(View1.Mixin.class)
-public interface View1
-{
-    String bar();
-
-    public class Mixin
-        implements View1
-    {
-        @This
-        FooModel model;
-
-        @Override
-        public String bar()
-        {
-            return model.getBar();
-        }
-    }
-}
-// END SNIPPET: decorator
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/View2.java b/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/View2.java
deleted file mode 100644
index 4033072..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/decoratorMixin/View2.java
+++ /dev/null
@@ -1,40 +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.qi4j.api.mixin.decoratorMixin;
-
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-
-@Mixins(View2.Mixin.class)
-public interface View2
-{
-    String bar();
-    public class Mixin
-        implements View2
-    {
-        @This
-        FooModel model;
-
-        @Override
-        public String bar()
-        {
-            return model.getBar();
-        }
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/partial/Car.java b/core/api/src/test/java/org/qi4j/api/mixin/partial/Car.java
deleted file mode 100644
index cd2a668..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/partial/Car.java
+++ /dev/null
@@ -1,30 +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.qi4j.api.mixin.partial;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.mixin.StartMixin;
-import org.qi4j.api.mixin.Startable;
-
-// START SNIPPET: partial
-@Mixins( { StartMixin.class, SpeedMixin.class, CrashResultMixin.class } )
-public interface Car extends Startable, Vehicle
-{}
-
-// END SNIPPET: partial
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/partial/CrashResultMixin.java b/core/api/src/test/java/org/qi4j/api/mixin/partial/CrashResultMixin.java
deleted file mode 100644
index 830cb74..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/partial/CrashResultMixin.java
+++ /dev/null
@@ -1,23 +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.qi4j.api.mixin.partial;
-
-public class CrashResultMixin implements Crashable
-{
-}
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/partial/Crashable.java b/core/api/src/test/java/org/qi4j/api/mixin/partial/Crashable.java
deleted file mode 100644
index 7ca07d0..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/partial/Crashable.java
+++ /dev/null
@@ -1,23 +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.qi4j.api.mixin.partial;
-
-public interface Crashable
-{
-}
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/partial/SpeedLocation.java b/core/api/src/test/java/org/qi4j/api/mixin/partial/SpeedLocation.java
deleted file mode 100644
index e8119da..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/partial/SpeedLocation.java
+++ /dev/null
@@ -1,28 +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.qi4j.api.mixin.partial;
-
-// START SNIPPET: partial
-public interface SpeedLocation
-{
-    void turn(float angle);
-
-    void accelerate(float acceleration);
-}
-// END SNIPPET: partial
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/partial/SpeedMixin.java b/core/api/src/test/java/org/qi4j/api/mixin/partial/SpeedMixin.java
deleted file mode 100644
index 3f2cf6d..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/partial/SpeedMixin.java
+++ /dev/null
@@ -1,33 +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.qi4j.api.mixin.partial;
-
-// START SNIPPET: partial
-public abstract class SpeedMixin
-        implements SpeedLocation
-{
-    // state for speed
-
-    public void accelerate( float acceleration )
-    {
-        // logic
-    }
-}
-
-// END SNIPPET: partial
\ No newline at end of file
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/partial/Vehicle.java b/core/api/src/test/java/org/qi4j/api/mixin/partial/Vehicle.java
deleted file mode 100644
index 4fa3597..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/partial/Vehicle.java
+++ /dev/null
@@ -1,26 +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.qi4j.api.mixin.partial;
-
-// START SNIPPET: partial
-public interface Vehicle extends SpeedLocation, Crashable
-{
-}
-
-// END SNIPPET: partial
\ No newline at end of file
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/privateMixin/Cargo.java b/core/api/src/test/java/org/qi4j/api/mixin/privateMixin/Cargo.java
deleted file mode 100644
index d8a8dcc..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/privateMixin/Cargo.java
+++ /dev/null
@@ -1,36 +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.qi4j.api.mixin.privateMixin;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.mixin.Mixins;
-
-// START SNIPPET: private
-@Mixins( CargoMixin.class )
-public interface Cargo extends EntityComposite
-{
-    String origin();
-
-    String destination();
-
-    void changeDestination( String newDestination );
-
-}
-
-// END SNIPPET: private
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/privateMixin/CargoMixin.java b/core/api/src/test/java/org/qi4j/api/mixin/privateMixin/CargoMixin.java
deleted file mode 100644
index 4bb059a..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/privateMixin/CargoMixin.java
+++ /dev/null
@@ -1,46 +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.qi4j.api.mixin.privateMixin;
-
-import org.qi4j.api.injection.scope.This;
-
-// START SNIPPET: private
-public abstract class CargoMixin
-        implements Cargo
-{
-    @This
-    private CargoState state;
-
-    public String origin()
-    {
-        return state.origin().get();
-    }
-
-    public String destination()
-    {
-        return state.destination().get();
-    }
-
-    public void changeDestination( String newDestination )
-    {
-        state.destination().set( newDestination );
-    }
-}
-
-// END SNIPPET: private
\ No newline at end of file
diff --git a/core/api/src/test/java/org/qi4j/api/mixin/privateMixin/CargoState.java b/core/api/src/test/java/org/qi4j/api/mixin/privateMixin/CargoState.java
deleted file mode 100644
index f348aee..0000000
--- a/core/api/src/test/java/org/qi4j/api/mixin/privateMixin/CargoState.java
+++ /dev/null
@@ -1,30 +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.qi4j.api.mixin.privateMixin;
-
-import org.qi4j.api.property.Property;
-
-// START SNIPPET: private
-public interface CargoState
-{
-    Property<String> origin();
-    Property<String> destination();
-}
-
-// END SNIPPET: private
\ No newline at end of file
diff --git a/core/api/src/test/java/org/qi4j/api/object/ObjectBuilderTest.java b/core/api/src/test/java/org/qi4j/api/object/ObjectBuilderTest.java
deleted file mode 100644
index 56cdcec..0000000
--- a/core/api/src/test/java/org/qi4j/api/object/ObjectBuilderTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.object;
-
-import org.junit.Test;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertNotNull;
-
-/**
- * JAVADOC
- */
-public class ObjectBuilderTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.objects( A.class, B.class, C.class, D.class );
-    }
-
-    @Test
-    public void testNotProvidedUses()
-    {
-        A a = module.newObject( A.class );
-        assertNotNull( a );
-        assertNotNull( a.b );
-        assertNotNull( a.b.c );
-        assertNotNull( a.b.c.d );
-    }
-
-    public static class A
-    {
-        @Uses
-        B b;
-    }
-
-    public static class B
-    {
-        @Uses
-        C c;
-    }
-
-    public static class C
-    {
-        @Uses
-        D d;
-    }
-
-    public static class D
-    {
-
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/property/PropertyErrorTest.java b/core/api/src/test/java/org/qi4j/api/property/PropertyErrorTest.java
deleted file mode 100644
index bd0e8e9..0000000
--- a/core/api/src/test/java/org/qi4j/api/property/PropertyErrorTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.property;
-
-import org.junit.Test;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-/**
- * Error messages for Properties
- */
-public class PropertyErrorTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.entities( PersonEntity.class );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void givenEntityWithNonOptionPropertyWhenInstantiatedThenException()
-        throws Exception
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            PersonEntity person = unitOfWork.newEntity( PersonEntity.class );
-
-            unitOfWork.complete();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    interface PersonEntity
-        extends EntityComposite
-    {
-        Property<String> foo();
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/test/java/org/qi4j/api/service/DocumentationSupport.java b/core/api/src/test/java/org/qi4j/api/service/DocumentationSupport.java
deleted file mode 100644
index 7042639..0000000
--- a/core/api/src/test/java/org/qi4j/api/service/DocumentationSupport.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.service;
-
-import java.util.List;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.qualifier.ServiceTags;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-
-public class DocumentationSupport
-    implements Assembler
-{
-    // START SNIPPET: tag
-    // START SNIPPET: instantiateOnStartup
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ServiceDeclaration service = module.addServices( MyDemoService.class );
-        // END SNIPPET: tag
-        service.instantiateOnStartup();
-        // END SNIPPET: instantiateOnStartup
-        // START SNIPPET: tag
-        service.taggedWith( "Important", "Drain" );
-        // END SNIPPET: tag
-    }
-
-    private static class MyDemoService
-    {
-    }
-
-    private static class MyOtherDemoService
-    {
-        // START SNIPPET: UseTag
-        @Service
-        private List<ServiceReference<MyDemoService>> services;
-
-        public MyDemoService locateImportantService()
-        {
-            for( ServiceReference<MyDemoService> ref : services )
-            {
-                ServiceTags serviceTags = ref.metaInfo( ServiceTags.class );
-                if( serviceTags.hasTag( "Important" ) )
-                {
-                    return ref.get();
-                }
-            }
-            return null;
-        }
-        // END SNIPPET: UseTag
-    }
-
-    // START SNIPPET: activation1
-    @Mixins( MyActivationMixin.class )
-    public static interface MyActivationDemoService
-        extends ServiceComposite, ServiceActivation
-    {
-    }
-
-    public static class MyActivationMixin
-        implements ServiceActivation
-    {
-        @Override
-        public void activateService()
-            throws Exception
-        {
-            // Activation code
-        }
-
-        @Override
-        public void passivateService()
-            throws Exception
-        {
-            // Passivation code
-        }
-    }
-    // END SNIPPET: activation1
-
-    // START SNIPPET: activation2
-    @Activators( MyActivator.class )
-    public static interface MyOtherActivationDemoService
-        extends ServiceComposite
-    {
-    }
-
-    public static class MyActivator
-        extends ServiceActivatorAdapter<MyOtherActivationDemoService>
-    {
-        @Override
-        public void afterActivation( ServiceReference<MyOtherActivationDemoService> activated )
-            throws Exception
-        {
-            // Activation code
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<MyOtherActivationDemoService> passivating )
-            throws Exception
-        {
-            // Passivation code
-        }
-    }
-    // END SNIPPET: activation2
-
-    static class Activation3
-        implements Assembler
-    {
-        // START SNIPPET: activation3
-        @Override
-        public void assemble( ModuleAssembly module )
-        {
-            module.services( MyDemoService.class ).withActivators( MyActivator.class );
-        }
-        // END SNIPPET: activation3
-    }
-
-}
diff --git a/core/api/src/test/java/org/qi4j/api/unitofwork/RemovalTest.java b/core/api/src/test/java/org/qi4j/api/unitofwork/RemovalTest.java
deleted file mode 100644
index 991ff73..0000000
--- a/core/api/src/test/java/org/qi4j/api/unitofwork/RemovalTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.api.unitofwork;
-
-import org.junit.Test;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-public class RemovalTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( TestEntity.class );
-        module.entities( PidRegulator.class );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Test
-    public void givenEntityIsCreatedAndUnitOfWorkIsNotCompletedWhenEntityIsRemoveThenSuccessfulRemoval()
-        throws Exception
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            EntityBuilder<TestEntity> builder = uow.newEntityBuilder( TestEntity.class, "123" );
-            builder.instance().test().set( "habba" );
-            TestEntity test = builder.newInstance();
-            uow.remove( test );
-            uow.complete();
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void givenStandardPidRegulatorWhenNoChangeInInputExpectOutputToGoTowardsMinimum()
-        throws Exception
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        PidRegulator regulator = null;
-        try
-        {
-            regulator = createPidRegulator( uow );
-        }
-        finally
-        {
-            if( regulator != null )
-            {
-                uow.remove( regulator );
-            }
-            // TODO: This problem is related to that uow.remove() has a bug.
-            // If the Entity is both created and removed in the same session, then the remove() should simply remove
-            // the entity from the internal UoW holding area, and not set the REMOVED status.
-
-            // Probably that UnitOfWorkInstance.remove() should also call instanceCache.remove(), but the question is
-            // then what is an InstanceKey vs EntityReference
-            uow.complete();
-        }
-    }
-
-    public interface TestEntity
-        extends EntityComposite
-    {
-        @Optional
-        Property<String> test();
-    }
-
-    private PidRegulator createPidRegulator( UnitOfWork uow )
-        throws UnitOfWorkCompletionException
-    {
-        EntityBuilder<PidRegulator> builder = uow.newEntityBuilder( PidRegulator.class );
-        PidRegulator prototype = builder.instance();
-        prototype.p().set( 1.0f );
-        prototype.i().set( 10f );
-        prototype.d().set( 0.1f );
-        prototype.maxD().set( 10f );
-        prototype.maximum().set( 100f );
-        prototype.minimum().set( 0f );
-        PidRegulator regulator = builder.newInstance();
-
-        return regulator;
-    }
-
-    //    @Mixins( { PidRegulatorAlgorithmMixin.class } )
-    public interface PidRegulator
-        extends PidParameters, EntityComposite
-    {
-    }
-
-    public interface PidParameters
-    {
-        Property<Float> p();
-
-        Property<Float> i();
-
-        Property<Float> d();
-
-        Property<Float> maxD();
-
-        Property<Float> minimum();
-
-        Property<Float> maximum();
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/unitofwork/UnitOfWorkTemplateTest.java b/core/api/src/test/java/org/qi4j/api/unitofwork/UnitOfWorkTemplateTest.java
deleted file mode 100644
index 21212ae..0000000
--- a/core/api/src/test/java/org/qi4j/api/unitofwork/UnitOfWorkTemplateTest.java
+++ /dev/null
@@ -1,73 +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.qi4j.api.unitofwork;
-
-import org.junit.Test;
-import org.qi4j.api.entity.EntityBuilderTemplate;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-/**
- * TODO
- */
-public class UnitOfWorkTemplateTest
-    extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.entities( TestEntity.class );
-    }
-
-    @Test
-    public void testTemplate()
-        throws UnitOfWorkCompletionException
-    {
-        new UnitOfWorkTemplate<Void, RuntimeException>()
-        {
-            @Override
-            protected Void withUnitOfWork( UnitOfWork uow )
-                throws RuntimeException
-            {
-                new EntityBuilderTemplate<TestEntity>( TestEntity.class )
-                {
-                    @Override
-                    protected void build( TestEntity prototype )
-                    {
-                        prototype.name().set( "Rickard" );
-                    }
-                }.newInstance( module );
-
-                return null;
-            }
-        }.withModule( module );
-    }
-
-    interface TestEntity
-        extends EntityComposite
-    {
-        Property<String> name();
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/util/ClassesTest.java b/core/api/src/test/java/org/qi4j/api/util/ClassesTest.java
deleted file mode 100644
index 85be327..0000000
--- a/core/api/src/test/java/org/qi4j/api/util/ClassesTest.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.api.util;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.util.HashSet;
-import java.util.Set;
-import org.junit.Test;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.Specifications;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.api.util.Classes.interfacesOf;
-import static org.qi4j.api.util.Classes.interfacesWithMethods;
-import static org.qi4j.functional.Iterables.count;
-
-/**
- * Tests for Classes
- */
-public class ClassesTest
-{
-
-    @Test
-    public void givenClassWithInterfacesWhenInterfacesOfThenGetCorrectSet()
-    {
-        assertThat( "one interface returned", count( interfacesOf( A.class ) ), equalTo( 1L ) );
-        assertThat( "two interface returned", count( interfacesOf( B.class ) ), equalTo( 2L ) );
-        assertThat( "tree interface returned", count( interfacesOf( C.class ) ), equalTo( 4L ) );
-    }
-
-    @Test
-    public void givenClassWithInterfacesWhenGetInterfacesWithMethodsThenGetCorrectSet()
-    {
-        HashSet<Class<?>> interfaces = new HashSet<Class<?>>();
-        interfaces.add( B.class );
-        Set<Class<?>> types = interfacesWithMethods( interfaces );
-        assertThat( "one interface returned", types.size(), equalTo( 1 ) );
-        assertThat( "correct interface returned", types.contains( B.class ), is( true ) );
-    }
-
-    @Test
-    public void givenClassesWithInterfacesWhenGetInterfacesWithMethodsThenGetCorrectSet()
-    {
-        Iterable<Type> types = Iterables.filter( Methods.HAS_METHODS, interfacesOf( C.class ) );
-        assertThat( "one interface returned", count( types ), equalTo( 1L ) );
-        assertThat( "correct interface returned", Iterables.matchesAny( (Specification) Specifications.in( B.class ), Iterables
-            .<Class<?>>cast( types ) ), is( true ) );
-    }
-
-    @Test
-    public void givenClassNameWhenToUriThenUriIsReturned()
-    {
-        assertThat( "URI is correct", Classes.toURI( A.class ), equalTo( "urn:qi4j:type:org.qi4j.api.util.ClassesTest-A" ) );
-    }
-
-    @Test
-    public void givenUriWhenToClassNameThenClassNameIsReturned()
-    {
-        assertThat( "Class name is correct", Classes.toClassName( "urn:qi4j:type:org.qi4j.api.util.ClassesTest-A" ), equalTo( "org.qi4j.api.util.ClassesTest$A" ) );
-    }
-
-    @Test
-    public void givenGenericTypeWithWildCardWhenGetRawClassThenCorrectTypeIsReturned()
-        throws NoSuchMethodException
-    {
-        Type returnType = Generics.class.getMethod( "wildcard" ).getGenericReturnType();
-        Type wildcardType = ( (ParameterizedType) returnType ).getActualTypeArguments()[ 0];
-        assertThat( "Return type is A", Classes.RAW_CLASS.map( wildcardType ), equalTo( (Class) A.class ) );
-    }
-
-    @Test
-    public void givenTypeVariableWhenResolveThenResolved()
-    {
-        for( Method method : Type1.class.getMethods() )
-        {
-            Type type = method.getGenericReturnType();
-            TypeVariable typeVariable = (TypeVariable) type;
-            Type resolvedType = Classes.resolveTypeVariable( typeVariable, method.getDeclaringClass(), Type1.class );
-            System.out.println( type + "=" + resolvedType );
-            switch( method.getName() )
-            {
-                case "type":
-                    assertThat( resolvedType, equalTo( (Type) String.class ) );
-                    break;
-                case "type1":
-                    assertThat( resolvedType, equalTo( (Type) String.class ) );
-                    break;
-                case "type2":
-                    assertThat( resolvedType, equalTo( (Type) Long.class ) );
-                    break;
-            }
-        }
-    }
-
-    @Test
-    public void givenGenericTypeWhenGetSimpleGenericNameThenCorrectStringIsReturned()
-        throws NoSuchMethodException
-    {
-        assertThat( "Simple Generic Name is 'A'",
-                    Classes.simpleGenericNameOf( A.class ),
-                    equalTo( "A" ) );
-        assertThat( "Simple Generic Name is 'B'",
-                    Classes.simpleGenericNameOf( B.class ),
-                    equalTo( "B" ) );
-        assertThat( "Simple Generic Name is 'C'",
-                    Classes.simpleGenericNameOf( C.class ),
-                    equalTo( "C" ) );
-
-        assertThat( "Simple Generic Name is 'Generics'",
-                    Classes.simpleGenericNameOf( Generics.class ),
-                    equalTo( "Generics" ) );
-        assertThat( "Simple Generic Name is 'Iterable<? extends A>'",
-                    Classes.simpleGenericNameOf( Generics.class.getMethod( "wildcard" ).getGenericReturnType() ),
-                    equalTo( "Iterable<? extends A>" ) );
-
-        assertThat( "Simple Generic Name is 'Type1'",
-                    Classes.simpleGenericNameOf( Type1.class ),
-                    equalTo( "Type1" ) );
-        assertThat( "Simple Generic Name is 'TYPE'",
-                    Classes.simpleGenericNameOf( Type1.class.getMethod( "type" ).getGenericReturnType() ),
-                    equalTo( "TYPE" ) );
-        assertThat( "Simple Generic Name is 'TYPE1'",
-                    Classes.simpleGenericNameOf( Type1.class.getMethod( "type1" ).getGenericReturnType() ),
-                    equalTo( "TYPE1" ) );
-        assertThat( "Simple Generic Name is 'TYPE2'",
-                    Classes.simpleGenericNameOf( Type1.class.getMethod( "type2" ).getGenericReturnType() ),
-                    equalTo( "TYPE2" ) );
-
-        assertThat( "Simple Generic Name is 'Type2'",
-                    Classes.simpleGenericNameOf( Type2.class ),
-                    equalTo( "Type2" ) );
-        assertThat( "Simple Generic Name is 'TYPE'",
-                    Classes.simpleGenericNameOf( Type2.class.getMethod( "type" ).getGenericReturnType() ),
-                    equalTo( "TYPE" ) );
-        assertThat( "Simple Generic Name is 'TYPE1'",
-                    Classes.simpleGenericNameOf( Type2.class.getMethod( "type1" ).getGenericReturnType() ),
-                    equalTo( "TYPE1" ) );
-        assertThat( "Simple Generic Name is 'TYPE2'",
-                    Classes.simpleGenericNameOf( Type2.class.getMethod( "type2" ).getGenericReturnType() ),
-                    equalTo( "TYPE2" ) );
-
-        assertThat( "Simple Generic Name is 'Type3'",
-                    Classes.simpleGenericNameOf( Type3.class ),
-                    equalTo( "Type3" ) );
-        assertThat( "Simple Generic Name is 'TYPE'",
-                    Classes.simpleGenericNameOf( Type3.class.getMethod( "type" ).getGenericReturnType() ),
-                    equalTo( "TYPE" ) );
-    }
-
-    interface A
-    {
-    }
-
-    interface B
-        extends A
-    {
-
-        public void doStuff();
-
-    }
-
-    interface C
-        extends A, B
-    {
-    }
-
-    interface Generics
-    {
-
-        Iterable<? extends A> wildcard();
-
-    }
-
-    interface Type1
-        extends Type2<String, Long>
-    {
-    }
-
-    interface Type2<TYPE1, TYPE2>
-        extends Type3<TYPE1>
-    {
-
-        TYPE1 type1();
-
-        TYPE2 type2();
-
-    }
-
-    interface Type3<TYPE>
-    {
-
-        TYPE type();
-
-    }
-
-}
diff --git a/core/api/src/test/java/org/qi4j/api/value/DocumentationSupport.java b/core/api/src/test/java/org/qi4j/api/value/DocumentationSupport.java
deleted file mode 100644
index 32595b2..0000000
--- a/core/api/src/test/java/org/qi4j/api/value/DocumentationSupport.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (c) 2013, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.value;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.type.CollectionType;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.ApplicationAssemblyFactory;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Function;
-import org.qi4j.io.Inputs;
-import org.qi4j.io.Outputs;
-import org.qi4j.io.Transforms;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-/**
- * Snippets:
- * - default : default ValueSerialization
- * - service : assembled service ValueSerialization
- * - lookup  : ValueSerialization values module finder
- */
-public class DocumentationSupport
-    extends AbstractQi4jTest
-{
-
-    @Before
-    public void injectToThis()
-    {
-        module.injectTo( this );
-    }
-
-    // START SNIPPET: default
-    // START SNIPPET: service
-    public interface SomeValue // (1)
-    {
-
-        Property<String> foo();
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.values( SomeValue.class ); // (2)
-        // END SNIPPET: default
-        new OrgJsonValueSerializationAssembler().assemble( module ); // (3)
-        // START SNIPPET: default
-    }
-    // END SNIPPET: default
-    // END SNIPPET: service
-
-    @Test
-    // START SNIPPET: default
-    public void defaultValueSerialization()
-    {
-        SomeValue someValue = someNewValueInstance( module ); // (3)
-        String json = someValue.toString(); // (4)
-        SomeValue someNewValue = module.newValueFromSerializedState( SomeValue.class, json ); // (5)
-        // END SNIPPET: default
-
-        assertThat( json, equalTo( "{\"foo\":\"bar\"}" ) );
-        assertThat( someNewValue, equalTo( someValue ) );
-
-        // START SNIPPET: default
-    }
-    // END SNIPPET: default
-    // START SNIPPET: service
-    @Service
-    private ValueSerializer valueSerializer; // (4)
-    @Service
-    private ValueDeserializer valueDeserializer; // (4)
-
-    // END SNIPPET: service
-    @Test
-    // START SNIPPET: service
-    public void assembledDefaultServiceSerialization()
-    {
-        SomeValue someValue = someNewValueInstance( module ); // (5)
-        String json = valueSerializer.serialize( someValue ); // (6)
-        SomeValue someNewValue = valueDeserializer.deserialize( SomeValue.class, json ); // (7)
-        // END SNIPPET: service
-
-        assertThat( json, equalTo( "{\"foo\":\"bar\"}" ) );
-        assertThat( someNewValue, equalTo( someValue ) );
-
-        // START SNIPPET: service
-    }
-    // END SNIPPET: service
-
-    static enum AcmeValue
-    {
-
-        foo, bar
-    }
-
-    @Test
-    // START SNIPPET: stream
-    public void assembledServiceStreamingSerialization()
-    {
-        // END SNIPPET: stream
-
-        List<AcmeValue> dataSource = Arrays.asList( AcmeValue.values() );
-        ByteArrayOutputStream targetStream = new ByteArrayOutputStream();
-
-        // START SNIPPET: stream
-        // (1)
-        Iterable<AcmeValue> data = dataSource; // Eg. Entities converted to Values
-        OutputStream output = targetStream; // Eg. streaming JSON over HTTP
-
-        // (2)
-        valueSerializer.serialize( data, output );
-        // END SNIPPET: stream
-
-        byte[] serialized = targetStream.toByteArray();
-        ByteArrayInputStream sourceStream = new ByteArrayInputStream( serialized );
-
-        // START SNIPPET: stream
-        // (3)
-        InputStream input = sourceStream; // Eg. reading incoming JSON
-
-        // (4)
-        List<AcmeValue> values = valueDeserializer.deserialize( CollectionType.listOf( AcmeValue.class ), input );
-        // END SNIPPET: stream
-
-        assertThat( values, equalTo( dataSource ) );
-
-        // START SNIPPET: stream
-    }
-    // END SNIPPET: stream
-
-    @Test
-    // START SNIPPET: io
-    public void assembledServiceIOSerialization()
-        throws IOException
-    {
-        // END SNIPPET: io
-
-        List<AcmeValue> dataSource = Arrays.asList( AcmeValue.values() );
-        StringWriter outputWriter = new StringWriter();
-
-        // START SNIPPET: io
-        // (1)
-        Iterable<AcmeValue> queryResult = dataSource; // Eg. Entities converted to Values
-        Writer writer = outputWriter; // Eg. to pipe data to another process or to a file
-
-        // (2)
-        Function<AcmeValue, String> serialize = valueSerializer.serialize();
-
-        // (3)
-        Inputs.iterable( queryResult ).transferTo( Transforms.map( serialize, Outputs.text( writer ) ) );
-        // END SNIPPET: io
-
-        String string = writer.toString();
-        StringReader inputReader = new StringReader( string );
-
-        // START SNIPPET: io
-        // (4)
-        Reader reader = inputReader;
-        List<AcmeValue> values = new ArrayList<AcmeValue>();
-
-        // (5)
-        Function<String, AcmeValue> deserialize = valueDeserializer.deserialize( AcmeValue.class );
-
-        // Deserialization of a collection of AcmeValue from a String.
-        // One serialized AcmeValue per line.
-        // (6)
-        Inputs.text( reader ).transferTo( Transforms.map( deserialize, Outputs.collection( values ) ) );
-        // END SNIPPET: io
-
-        assertThat( dataSource, equalTo( values ) );
-
-        // START SNIPPET: io
-    }
-    // END SNIPPET: io
-
-    @Test
-    // TODO Move to SPI !
-    // TODO Include in each ValueSerialization extensions documentation
-    public void assembledWithValuesModuleSerialization()
-        throws Exception
-    {
-        Application app = new Energy4Java().newApplication( new ApplicationAssembler()
-        {
-            @Override
-            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-                throws AssemblyException
-            {
-                Assembler[][][] pancakes = new Assembler[][][]
-                {
-                    {
-                        {
-                            new Assembler()
-                            {
-                                @Override
-                                public void assemble( ModuleAssembly valuesModule )
-                                    throws AssemblyException
-                                {
-                                    valuesModule.layer().setName( "SINGLE-Layer" );
-                                    valuesModule.setName( "VALUES-Module" );
-
-                                    valuesModule.values( SomeValue.class );
-                                }
-                            }
-                        },
-                        {
-                            new Assembler()
-                            {
-                                @Override
-                                public void assemble( ModuleAssembly servicesModule )
-                                    throws AssemblyException
-                                {
-                                    servicesModule.setName( "SERVICES-Module" );
-
-                                    Function<Application, Module> valuesModuleFinder = new Function<Application, Module>()
-                                    {
-                                        @Override
-                                        public Module map( Application app )
-                                        {
-                                            return app.findModule( "SINGLE-Layer", "VALUES-Module" );
-                                        }
-                                    };
-                                    new OrgJsonValueSerializationAssembler().
-                                        withValuesModuleFinder( valuesModuleFinder ).
-                                        assemble( servicesModule );
-                                }
-                            }
-                        }
-                    }
-                };
-                return applicationFactory.newApplicationAssembly( pancakes );
-            }
-        } );
-        app.activate();
-        try
-        {
-            Module valuesModule = app.findModule( "SINGLE-Layer", "VALUES-Module" );
-            SomeValue someValue = someNewValueInstance( valuesModule );
-
-            Module servicesModule = app.findModule( "SINGLE-Layer", "SERVICES-Module" );
-            ValueSerialization valueSerialization = servicesModule.findService( ValueSerialization.class ).get();
-
-            String json = valueSerialization.serialize( someValue );
-            assertThat( json, equalTo( "{\"foo\":\"bar\"}" ) );
-
-            SomeValue someNewValue = valueSerialization.deserialize( SomeValue.class, json );
-            assertThat( someNewValue, equalTo( someValue ) );
-        }
-        finally
-        {
-            app.passivate();
-        }
-    }
-
-    private SomeValue someNewValueInstance( Module module )
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        builder.prototype().foo().set( "bar" );
-        return builder.newInstance();
-    }
-}
diff --git a/core/api/src/test/java/org/qi4j/api/value/ValueBuilderTemplateTest.java b/core/api/src/test/java/org/qi4j/api/value/ValueBuilderTemplateTest.java
deleted file mode 100644
index 420d48e..0000000
--- a/core/api/src/test/java/org/qi4j/api/value/ValueBuilderTemplateTest.java
+++ /dev/null
@@ -1,84 +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.qi4j.api.value;
-
-import org.junit.Test;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-/**
- * TODO
- */
-public class ValueBuilderTemplateTest
-    extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.values( TestValue.class );
-    }
-
-    @Test
-    public void testTemplate()
-    {
-        new TestBuilder( "Rickard" ).newInstance( module );
-    }
-
-    @Test
-    public void testAnonymousTemplate()
-    {
-        new ValueBuilderTemplate<TestValue>( TestValue.class )
-        {
-            @Override
-            protected void build( TestValue prototype )
-            {
-                prototype.name().set( "Rickard" );
-            }
-        }.newInstance( module );
-    }
-
-    interface TestValue
-        extends ValueComposite
-    {
-        Property<String> name();
-    }
-
-    class TestBuilder
-        extends ValueBuilderTemplate<TestValue>
-    {
-        String name;
-
-        TestBuilder( String name )
-        {
-            super( TestValue.class );
-            this.name = name;
-        }
-
-        @Override
-        protected void build( TestValue prototype )
-        {
-            prototype.name().set( name );
-        }
-    }
-
-    ;
-}
diff --git a/core/api/src/test/java/org/qi4j/api/value/ValueCompositeTest.java b/core/api/src/test/java/org/qi4j/api/value/ValueCompositeTest.java
deleted file mode 100644
index 1c545a4..0000000
--- a/core/api/src/test/java/org/qi4j/api/value/ValueCompositeTest.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.value;
-
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.constraints.annotation.MaxLength;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-/**
- * Tests for ValueComposites
- */
-public class ValueCompositeTest
-    extends AbstractQi4jTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.values( SomeValue.class, AnotherValue.class, AssociationValue.class );
-        module.entities( SomeEntity.class );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Test( expected = IllegalStateException.class )
-    public void testImmutabilityOfValueComposite()
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        SomeValue some = builder.prototype();
-        some.other().set( "test" );
-        some = builder.newInstance();
-        some.other().set( "test2" );
-    }
-
-    @Test
-    public void testCreationOfValueComposite()
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        SomeValue some = builder.prototype();
-        some.other().set( "test" );
-        builder.newInstance();
-
-        // Check that @UseDefaults works for ValueComposites
-        assertEquals( "{\"val1\":\"\"}", some.another().get().toString() );
-    }
-
-    @Test
-    public void testEqualityOfValueComposite()
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        SomeValue prototype = builder.prototype();
-        prototype.other().set( "test" );
-        SomeValue instance = builder.newInstance();
-        SomeValue other = builder.newInstance();
-        Assert.assertFalse( "Instances should not be the same.", instance == other );
-        Assert.assertEquals( "Equal values.", instance, other );
-    }
-
-    @Test
-    public void testHashcodeOfValueComposite()
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        SomeValue prototype = builder.prototype();
-        prototype.other().set( "test" );
-        SomeValue instance = builder.newInstance();
-        SomeValue other = builder.newInstance();
-        Assert.assertFalse( "Instances should not be the same.", instance == other );
-        Assert.assertEquals( "Equal values.", instance.hashCode(), other.hashCode() );
-    }
-
-    @Test
-    public void testModifyValue()
-    {
-        ValueBuilder<AnotherValue> anotherBuilder = module.newValueBuilder( AnotherValue.class );
-        anotherBuilder.prototype().val1().set( "Val1" );
-        AnotherValue anotherValue = anotherBuilder.newInstance();
-
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        SomeValue prototype = builder.prototype();
-        prototype.some().set( "foo" );
-        prototype.other().set( "test" );
-        prototype.xyzzyList().get().add( "blah" );
-        prototype.another().set( anotherValue );
-        SomeValue instance = builder.newInstance();
-
-        assertThat( "List has value blah", instance.xyzzyList().get().get( 0 ), equalTo( "blah" ) );
-
-        // Modify value
-        builder = module.newValueBuilderWithPrototype( instance );
-        builder.prototype().some().set( "bar" );
-        instance = builder.newInstance();
-
-        assertThat( "Other is set to test", instance.other().get(), equalTo( "test" ) );
-        assertThat( "List has value blah", instance.xyzzyList().get().get( 0 ), equalTo( "blah" ) );
-        assertThat( "AnotherValue.val1 has value Val1", instance.another().get().val1().get(), equalTo( "Val1" ) );
-
-        // Modify value again using method 2
-        builder = module.newValueBuilderWithPrototype( instance );
-        builder.prototype().other().set( "test2" );
-        instance = builder.newInstance();
-
-        assertThat( "Other is set to test2", instance.other().get(), equalTo( "test2" ) );
-        assertThat( "Some is set to bar", instance.some().get(), equalTo( "bar" ) );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void givenValueWhenModifyToIncorrectValueThenThrowConstraintException()
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        SomeValue prototype = builder.prototype();
-        prototype.some().set( "foo" );
-        SomeValue instance = builder.newInstance();
-
-        builder = module.newValueBuilderWithPrototype( instance );
-        builder.prototype().some().set( "123456" );
-    }
-
-    @Test
-    public void givenValueWithListOfValueWhenPrototypeThenListedValuesAreEditable()
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        builder.prototype().anotherList().get().add( module.newValue( AnotherValue.class ) );
-        SomeValue some = builder.newInstance();
-
-        builder = module.newValueBuilderWithPrototype( some );
-        builder.prototype().anotherList().get().get( 0 ).val1().set( "Foo" );
-        builder.prototype().anotherList().get().add( module.newValue( AnotherValue.class ) );
-        some = builder.newInstance();
-
-        assertThat( "Val1 has been set", some.anotherList().get().get( 0 ).val1().get(), equalTo( "Foo" ) );
-
-        try
-        {
-            some.anotherList().get().get( 0 ).val1().set( "Bar" );
-            Assert.fail( "Should not be allowed to modify value" );
-        }
-        catch( IllegalStateException e )
-        {
-            // Ok
-        }
-    }
-
-    @Test
-    public void givenEntityWhenUpdateValueThenValueIsSet()
-        throws UnitOfWorkCompletionException
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        builder.prototype().anotherList().get().add( module.newValue( AnotherValue.class ) );
-        ValueBuilder<AnotherValue> valueBuilder = module.newValueBuilder( AnotherValue.class );
-        valueBuilder.prototype().val1().set( "Foo" );
-        builder.prototype().another().set( valueBuilder.newInstance() );
-        builder.prototype().number().set( 42L );
-        SomeValue some = builder.newInstance();
-
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            EntityBuilder<SomeEntity> entityBuilder = unitOfWork.newEntityBuilder( SomeEntity.class );
-            entityBuilder.instance().someValue().set( some );
-            SomeEntity entity = entityBuilder.newInstance();
-
-            assertThat( "Value has been set", entity.someValue().get().another().get().val1().get(), equalTo( "Foo" ) );
-
-            unitOfWork.complete();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    @Test
-    public void givenValueWithAssociationsWhenNewUoWThenCanRead()
-        throws UnitOfWorkCompletionException
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        builder.prototype().anotherList().get().add( module.newValue( AnotherValue.class ) );
-        ValueBuilder<AnotherValue> valueBuilder = module.newValueBuilder( AnotherValue.class );
-        valueBuilder.prototype().val1().set( "Foo" );
-        builder.prototype().another().set( valueBuilder.newInstance() );
-        builder.prototype().number().set( 42L );
-        SomeValue some = builder.newInstance();
-
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        AssociationValue associationValue;
-        try
-        {
-            EntityBuilder<SomeEntity> entityBuilder = unitOfWork.newEntityBuilder( SomeEntity.class );
-            entityBuilder.instance().someValue().set( some );
-            SomeEntity entity = entityBuilder.newInstance();
-
-            ValueBuilder<AssociationValue> associationBuilder = module.newValueBuilder( AssociationValue.class );
-            associationBuilder.prototype().some().set( entity );
-            associationValue = associationBuilder.newInstance();
-
-            String json = associationValue.toString();
-
-            unitOfWork.complete();
-
-            unitOfWork = module.newUnitOfWork();
-
-            AssociationValue newAssociationValue = module.newValueFromSerializedState( AssociationValue.class, json );
-
-            Assert.assertEquals( associationValue.some().get(), newAssociationValue.some().get() );
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-
-        // Should allow the toString() to print the entityRefs.
-        System.out.println( associationValue.toString() );
-        try
-        {
-            associationValue.some().get();
-            fail( "Should have thrown an exception" );
-        }
-        catch( Exception e )
-        {
-            // Ok
-        }
-    }
-
-    public enum TestEnum
-    {
-        somevalue, anothervalue
-    }
-
-    public interface SomeValue
-        extends ValueComposite
-    {
-        @UseDefaults
-        @MaxLength( 5 )
-        Property<String> some();
-
-        @UseDefaults
-        Property<String> other();
-
-        @UseDefaults
-        Property<Long> number();
-
-        @UseDefaults
-        Property<List<String>> xyzzyList();
-
-        @UseDefaults
-        Property<AnotherValue> another();
-
-        @UseDefaults
-        Property<List<AnotherValue>> anotherList();
-
-        @UseDefaults
-        Property<TestEnum> testEnum();
-    }
-
-    public interface AnotherValue
-        extends ValueComposite
-    {
-        @UseDefaults
-        Property<String> val1();
-    }
-
-    public interface AssociationValue
-        extends ValueComposite
-    {
-        @Optional
-        Association<SomeEntity> some();
-
-        ManyAssociation<SomeEntity> manySome();
-    }
-
-    public interface SomeEntity
-        extends EntityComposite
-    {
-        Property<SomeValue> someValue();
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/test/resources/org/apache/polygene/api/configuration/MyService.properties b/core/api/src/test/resources/org/apache/polygene/api/configuration/MyService.properties
new file mode 100644
index 0000000..c0639c1
--- /dev/null
+++ b/core/api/src/test/resources/org/apache/polygene/api/configuration/MyService.properties
@@ -0,0 +1,21 @@
+#
+#  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.
+#
+#
+#
+
+me = { "name" : "Niclas", "address" : { "street1" : "Henan Lu 555", "street2" : "Block 15", "city" : { "cityName" : "Shanghai", "country" : { "countryName" : "China" } } } }
\ No newline at end of file
diff --git a/core/api/src/test/resources/org/qi4j/api/configuration/MyService.properties b/core/api/src/test/resources/org/qi4j/api/configuration/MyService.properties
deleted file mode 100644
index 6ed5ff6..0000000
--- a/core/api/src/test/resources/org/qi4j/api/configuration/MyService.properties
+++ /dev/null
@@ -1,16 +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.
-
-me = { name : Niclas, address={ street1 : "Henan Lu 555", street2 : "Block 15", city : { cityName : "Shanghai", country : { countryName : "China" } } } }
\ No newline at end of file
diff --git a/core/bootstrap/build.gradle b/core/bootstrap/build.gradle
index 7f43cdc..594c1e2 100644
--- a/core/bootstrap/build.gradle
+++ b/core/bootstrap/build.gradle
@@ -1,28 +1,29 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-jar { manifest { name = "Apache Zest™ Core Bootstrap"}}
+apply plugin: 'polygene-core'
+
+jar { manifest { name = "Apache Polygene™ Core Bootstrap" } }
 
 dependencies {
+  api polygene.core.spi
 
-  compile project( ':org.qi4j.core:org.qi4j.core.spi' )
-
-  testRuntime project( ':org.qi4j.core:org.qi4j.core.runtime' )
-
+  testRuntimeOnly polygene.core.runtime
 }
diff --git a/core/bootstrap/dev-status.xml b/core/bootstrap/dev-status.xml
index 4f034dc..ba367e6 100644
--- a/core/bootstrap/dev-status.xml
+++ b/core/bootstrap/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <codebase>stable</codebase>
     <!--none,early,beta,stable,mature-->
diff --git a/core/bootstrap/src/docs/bootstrap.txt b/core/bootstrap/src/docs/bootstrap.txt
index 56be2d0..e20b995 100644
--- a/core/bootstrap/src/docs/bootstrap.txt
+++ b/core/bootstrap/src/docs/bootstrap.txt
@@ -1,17 +1,19 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
+ *  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
  *
- * Licensed 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.
+ *       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.
 //////////////////////
 
 [[core-bootstrap-assembly,Assembly]]
@@ -22,12 +24,12 @@
 source=core/bootstrap/dev-status.xml
 --------------
 
-Zest™ has a distinct bootstrap phase, also known as the _Assembly_ of an application, where the applications structure
+Polygene™ has a distinct bootstrap phase, also known as the _Assembly_ of an application, where the applications structure
 is defined programmatically. Once all the layers, modules and all the composite types in each module have been defined
-the model is instantiated into an application. This enables the entire _structure_ system in Zest, where types "belongs"
+the model is instantiated into an application. This enables the entire _structure_ system in Polygene, where types "belongs"
 to a module and visibility rules define default behaviors, enforcement of architectural integrity and much more.
 
-The _assembly_ is preceeded by the creation of the _Qi4j Runtime_. The _assembly_ can be declared fully by defining
+The _assembly_ is preceeded by the creation of the _Polygene 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. The +bootstrap+ system has several ways to acheive
@@ -43,7 +45,7 @@
     * Add additional interfaces to composites dynamically.
     * Add concerns, mixins, constraints and side effects dynamically.
     * Set _meta information_ on defined types.
-    * Import external services to be available as Zest™ services.
+    * Import external services to be available as Polygene™ services.
     * Tag services with markers
 
 include::../../build/docs/buildinfo/artifact.txt[]
@@ -53,7 +55,7 @@
 
 [snippet,java]
 --------------
-source=core/bootstrap/src/test/java/org/qi4j/bootstrap/DocumentationSupport.java
+source=core/bootstrap/src/test/java/org/apache/polygene/bootstrap/DocumentationSupport.java
 tag=objects
 --------------
 
@@ -62,7 +64,7 @@
 
 [snippet,java]
 --------------
-source=core/bootstrap/src/test/java/org/qi4j/bootstrap/DocumentationSupport.java
+source=core/bootstrap/src/test/java/org/apache/polygene/bootstrap/DocumentationSupport.java
 tag=transients
 --------------
 
@@ -71,7 +73,7 @@
 
 [snippet,java]
 --------------
-source=core/bootstrap/src/test/java/org/qi4j/bootstrap/DocumentationSupport.java
+source=core/bootstrap/src/test/java/org/apache/polygene/bootstrap/DocumentationSupport.java
 tag=values
 --------------
 
@@ -80,7 +82,7 @@
 
 [snippet,java]
 --------------
-source=core/bootstrap/src/test/java/org/qi4j/bootstrap/DocumentationSupport.java
+source=core/bootstrap/src/test/java/org/apache/polygene/bootstrap/DocumentationSupport.java
 tag=entities
 --------------
 
@@ -89,7 +91,7 @@
 
 [snippet,java]
 --------------
-source=core/bootstrap/src/test/java/org/qi4j/bootstrap/DocumentationSupport.java
+source=core/bootstrap/src/test/java/org/apache/polygene/bootstrap/DocumentationSupport.java
 tag=services
 --------------
 
@@ -97,7 +99,7 @@
 
 [snippet,java]
 --------------
-source=core/bootstrap/src/test/java/org/qi4j/bootstrap/DocumentationSupport.java
+source=core/bootstrap/src/test/java/org/apache/polygene/bootstrap/DocumentationSupport.java
 tag=tagged-services
 --------------
 
@@ -105,7 +107,7 @@
 
 [snippet,java]
 --------------
-source=core/bootstrap/src/test/java/org/qi4j/bootstrap/DocumentationSupport.java
+source=core/bootstrap/src/test/java/org/apache/polygene/bootstrap/DocumentationSupport.java
 tag=imported-services
 --------------
 
@@ -113,7 +115,7 @@
 
 [snippet,java]
 --------------
-source=core/bootstrap/src/test/java/org/qi4j/bootstrap/DocumentationSupport.java
+source=core/bootstrap/src/test/java/org/apache/polygene/bootstrap/DocumentationSupport.java
 tag=properties-defaults
 --------------
 
@@ -136,7 +138,7 @@
 
 [snippet,java]
 --------------
-source=libraries/rest-server/src/test/java/org/qi4j/library/rest/server/DocumentationSupport.java
+source=libraries/rest-server/src/test/java/org/apache/polygene/library/rest/server/DocumentationSupport.java
 tag=UsingAssembler
 --------------
 
@@ -160,7 +162,7 @@
 
 [snippet,java]
 --------------
-source=extensions/entitystore-jdbm/src/test/java/org/qi4j/entitystore/jdbm/DocumentationSupport.java
+source=extensions/entitystore-jdbm/src/test/java/org/apache/polygene/entitystore/jdbm/DocumentationSupport.java
 tag=UsingAssembler
 --------------
 
@@ -168,7 +170,7 @@
 [[core-bootstrap-assembly-layered,Layered Application Assembler]]
 == Layered Application Assembler (RECOMMENDED!) ==
 
-In 2.1, a new way to instantiate Zest™ applications was introduced. It starts with subclassing the
+In 2.1, a new way to instantiate Polygene™ 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
@@ -206,7 +208,7 @@
 
 
 == Singleton Assembler ==
-Every Zest™ runtime instance consist of One Application, with one or more Layers and one or more Modules in each Layer.
+Every Polygene™ runtime instance consist of One Application, with one or more Layers and one or more Modules in each Layer.
 So the minimal application is still one layer with one module. This is not recommended other than for testing purposes
 and really trivial applications.
 
@@ -214,11 +216,11 @@
 
 [snippet,java]
 --------------
-source=core/bootstrap/src/test/java/org/qi4j/bootstrap/DocumentationSupport.java
+source=core/bootstrap/src/test/java/org/apache/polygene/bootstrap/DocumentationSupport.java
 tag=singleton
 --------------
 
-Once the SingletonAssembler constructor returns, the Zest™ application is up and running.
+Once the SingletonAssembler constructor returns, the Polygene™ application is up and running.
 
 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.
@@ -268,23 +270,22 @@
 
 [snippet,java]
 --------------
-source=core/bootstrap/src/test/java/org/qi4j/bootstrap/DocumentationSupport.java
+source=core/bootstrap/src/test/java/org/apache/polygene/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
-Zest™ runtime. It requires more support in your code to be useful, and the example below is by no means a recommended way
+Polygene™ runtime. It requires more support in your code to be useful, and the example below is by no means a recommended way
 to organize large application assemblies.
 
-In principle, you first start the Zest™ runtime, call newApplication with an ApplicationAssembler instance and call
+In principle, you first start the Polygene™ runtime, call newApplication with an ApplicationAssembler instance and call
 activate() on the returned application. The ApplicationAssembler instance will be called with an
 ApplicationAssemblyFactory, which is used to create an ApplicationAssembly describing the application structure.
 
 [snippet,java]
 --------------
-source=core/bootstrap/src/test/java/org/qi4j/bootstrap/DocumentationSupport.java
+source=core/bootstrap/src/test/java/org/apache/polygene/bootstrap/DocumentationSupport.java
 tag=full
 --------------
 
-
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationAssembler.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationAssembler.java
new file mode 100644
index 0000000..37f4f5b
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationAssembler.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.bootstrap;
+
+/**
+ * Implement this interface to create the root class that
+ * is responsible for assembling your entire application.
+ *
+ * Model introspectors will instantiate this class and call assemble
+ * to create the application, which will then be visited to get
+ * information about its structure.
+ *
+ * Application deployment servers will instantiate this, call assemble,
+ * and then activate the created application, which will be the runtime
+ * instance that forms your application.
+ */
+public interface ApplicationAssembler
+{
+    ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+        throws AssemblyException;
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationAssemblerAdapter.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationAssemblerAdapter.java
new file mode 100644
index 0000000..22fe614
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationAssemblerAdapter.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.bootstrap;
+
+/**
+ * Helper base class for application assemblers that
+ * want to either create applications using only one layer/module,
+ * or that wants to create pancake-layered applications.
+ */
+public class ApplicationAssemblerAdapter
+    implements ApplicationAssembler
+{
+    private final Assembler[][][] assemblers;
+
+    protected ApplicationAssemblerAdapter( Assembler assembler )
+    {
+        this.assemblers = new Assembler[][][]{ { { assembler } } };
+    }
+
+    protected ApplicationAssemblerAdapter( Assembler[][][] assemblers )
+    {
+        this.assemblers = assemblers;
+    }
+
+    @Override
+    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+        throws AssemblyException
+    {
+        return applicationFactory.newApplicationAssembly( assemblers );
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationAssembly.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationAssembly.java
new file mode 100644
index 0000000..5a93c81
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationAssembly.java
@@ -0,0 +1,118 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.structure.Application;
+
+/**
+ * An application assembly. This can be used by Assemblers to programmatically
+ * set the name of the application and create new layers.
+ */
+public interface ApplicationAssembly
+{
+    /**
+     * Create a new layer assembly
+     *
+     * @param name of the new layer
+     *
+     * @return a LayerAssembly instance
+     */
+    LayerAssembly layer( String name );
+
+    /**
+     * Get an assembly for a particular Module. If this is called many times with the same names, then the same module
+     * is affected.
+     *
+     * @param layerName The name of the Layer
+     * @param moduleName The name of the Module to retrieve or create.
+     * @return The ModuleAssembly for the Module.
+     */
+    ModuleAssembly module( String layerName, String moduleName );
+    
+    /**
+     * Get the currently set name of the application
+     *
+     * @return the name of the application
+     */
+    String name();
+
+    /**
+     * Get the currently set version of the application
+     *
+     * @return the version of the application
+     */
+    String version();
+
+    /**
+     * Get the currently set mode of the application
+     *
+     * @return the application mode
+     */
+    Application.Mode mode();
+
+    /**
+     * Set the name of the application
+     *
+     * @param name of the application
+     *
+     * @return the assembly
+     */
+    ApplicationAssembly setName( String name );
+
+    /**
+     * Set the version of the application. This can be in any format, but
+     * most likely will follow the Dewey format, i.e. x.y.z.
+     *
+     * @param version of the application
+     *
+     * @return the assembly
+     */
+    ApplicationAssembly setVersion( String version );
+
+    /**
+     * Set the application mode. This will be set to "production" by default. You can
+     * set the system property "mode" to either "development", "satisfiedBy" or "production"
+     * to explicitly set the mode. If that is not an option, then call this method
+     * during assembly to set the mode. The mode may then be queried by assemblers,
+     * and they may assemble the application differentlly depending on this setting.
+     *
+     * @param mode the application mode
+     *
+     * @return the assembly
+     */
+    ApplicationAssembly setMode( Application.Mode mode );
+
+    ApplicationAssembly setMetaInfo( Object info );
+
+    /**
+     * Set the application activators. Activators are executed in order around the
+     * Application activation and passivation.
+     *
+     * @param activators the application activators
+     * @return the assembly
+     */
+    @SuppressWarnings( { "unchecked","varargs" } )
+    ApplicationAssembly withActivators( Class<? extends Activator<Application>>... activators );
+
+    <ThrowableType extends Throwable> void visit( AssemblyVisitor<ThrowableType> visitor )
+        throws ThrowableType;
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationAssemblyFactory.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationAssemblyFactory.java
new file mode 100644
index 0000000..1622686
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationAssemblyFactory.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.bootstrap;
+
+/**
+ * Factory for creating new Polygene application assemblies. Typically
+ * you will implement one or more Assemblers, wrap them in an ApplicationAssembler,
+ * which then uses this factory to assemble and create applications.
+ */
+public interface ApplicationAssemblyFactory
+{
+    /**
+     * Create a new application with one layer and one module.
+     *
+     * @param assembler the assembler for the single module
+     *
+     * @return the application instance
+     *
+     * @throws AssemblyException if the application could not be assembled
+     */
+    ApplicationAssembly newApplicationAssembly( Assembler assembler )
+        throws AssemblyException;
+
+    /**
+     * Create a new application with the same amount of layers
+     * as the first array size, with modules according to the second array size,
+     * and then use the third array for assemblers of each module. This gives you
+     * a simple way to create "pancake" layered applications.
+     *
+     * @param assemblers the set of assemblers for the application
+     *
+     * @return the application instance
+     *
+     * @throws AssemblyException if the application could not be assembled
+     */
+    ApplicationAssembly newApplicationAssembly( Assembler[][][] assemblers )
+        throws AssemblyException;
+
+    /**
+     * Create a new ApplicationAssembly that can be used for the above method.
+     *
+     * @return a new ApplicationAssembly
+     */
+    ApplicationAssembly newApplicationAssembly();
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationModelFactory.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationModelFactory.java
new file mode 100644
index 0000000..6d7c32d
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationModelFactory.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+
+/**
+ * Factory for ApplicationModelSPI's. Takes an ApplicationAssembly, executes it,
+ * and builds an application model from it, which can then be instantiated and activated.
+ */
+public interface ApplicationModelFactory
+{
+    ApplicationDescriptor newApplicationModel( ApplicationAssembly assembly )
+        throws AssemblyException;
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationName.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationName.java
new file mode 100644
index 0000000..2e1e553
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ApplicationName.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.bootstrap;
+
+/**
+ * Set the name of the application
+ */
+public final class ApplicationName
+    implements Assembler
+{
+    private String name;
+
+    public ApplicationName( String name )
+    {
+        this.name = name;
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.layer().application().setName( name );
+    }
+}
\ No newline at end of file
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/Assembler.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/Assembler.java
new file mode 100644
index 0000000..901f8d9
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/Assembler.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.bootstrap;
+
+/**
+ * ModuleAssemblies are configured by Assemblers. This
+ * is the interface you would implement in order to provide
+ * all configuration and additional metainfo that is needed
+ * to instantiate a Polygene application.
+ */
+public interface Assembler
+{
+    /**
+     * Assemblers receive a callback to the ModuleAssembly
+     * they are supposed to configure. They can use this
+     * to register objects, composites, services etc. and
+     * the additional metadata that may exist for these
+     * artifacts.
+     * <p>
+     * An Assembler may create new Modules by calling
+     * {@link org.apache.polygene.bootstrap.ModuleAssembly#layer()} and
+     * then {@link LayerAssembly#module(String)} (String)}.
+     * This allows an Assembler to bootstrap an entire Layer with
+     * more Modules.
+     * </p>
+     * @param module the Module to assemble
+     *
+     * @throws AssemblyException thrown if the assembler tries to do something illegal
+     */
+    void assemble( ModuleAssembly module )
+        throws AssemblyException;
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblerCollection.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblerCollection.java
new file mode 100644
index 0000000..8bee7cb
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblerCollection.java
@@ -0,0 +1,76 @@
+/*
+ *  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.polygene.bootstrap;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * Assembler that delegates to a collection of Assemblers.
+ * <p>
+ * Makes it easy to collect and compose assemblers into bigger assemblers.
+ * </p>
+ */
+public final class AssemblerCollection
+    implements Assembler
+{
+    Collection<Assembler> assemblers;
+
+    public AssemblerCollection( Assembler... assemblers )
+    {
+        this.assemblers = Arrays.asList( assemblers );
+    }
+
+    @SafeVarargs
+    public AssemblerCollection( Class<? extends Assembler>... assemblyClasses )
+        throws AssemblyException
+    {
+        assemblers = new ArrayList<>();
+        for( Class<? extends Assembler> assemblyClass : assemblyClasses )
+        {
+            try
+            {
+                Assembler assembler = assemblyClass.newInstance();
+                assemblers.add( assembler );
+            }
+            catch( Exception e )
+            {
+                throw new AssemblyException( "Could not instantiate assembly with class " + assemblyClass.getName(), e );
+            }
+        }
+    }
+
+    public AssemblerCollection( Collection<Assembler> assemblers )
+    {
+        this.assemblers = assemblers;
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        for( Assembler assembler : assemblers )
+        {
+            assembler.assemble( module );
+        }
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/Assemblers.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/Assemblers.java
new file mode 100644
index 0000000..b24a5e6
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/Assemblers.java
@@ -0,0 +1,448 @@
+/*
+ *  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.polygene.bootstrap;
+
+/**
+ * Assembler adapters for common use cases (visibility, reference, configuration).
+ */
+public class Assemblers
+{
+    private Assemblers()
+    {
+    }
+
+    /**
+     * Assembler with Visibility interface.
+     * @param <AssemblerType> Parameterized type of Assembler
+     */
+    public interface Visible<AssemblerType>
+        extends Assembler
+    {
+        /**
+         * Set Visibility.
+         * @param visibility Visibility
+         * @return This Assembler instance
+         */
+        AssemblerType visibleIn( org.apache.polygene.api.common.Visibility visibility );
+
+        /**
+         * Get Visibility.
+         * <p>Default to {@link org.apache.polygene.api.common.Visibility#module}.</p>
+         * @return Visibility
+         */
+        org.apache.polygene.api.common.Visibility visibility();
+    }
+
+    /**
+     * Assembler with Identity interface.
+     * @param <AssemblerType> Parameterized type of Assembler
+     */
+    public interface Identifiable<AssemblerType>
+        extends Assembler
+    {
+        /**
+         * Set Identity.
+         * @param identity Identity
+         * @return This Assembler instance
+         */
+        AssemblerType identifiedBy( String identity );
+
+        /**
+         * @return {@literal true} if {@link #identity()} do not return null, {@literal false} otherwise
+         */
+        boolean hasIdentity();
+
+        /**
+         * Get Identity.
+         * <p>Default to {@literal null}.</p>
+         * @return Identity
+         */
+        String identity();
+    }
+
+    /**
+     * Assembler with Configuration interface.
+     * @param <AssemblerType> Parameterized type of Assembler
+     */
+    public interface Configurable<AssemblerType>
+        extends Assembler
+    {
+        /**
+         * Set Configuration Module and Visibility.
+         * @param configModule Configuration Module
+         * @param configVisibility Configuration Visiblity
+         * @return This Assembler instance
+         */
+        AssemblerType withConfig( ModuleAssembly configModule,
+                                  org.apache.polygene.api.common.Visibility configVisibility );
+
+        /**
+         * @return {@literal true} if {@link #configModule() ()} do not return null, {@literal false} otherwise
+         */
+        boolean hasConfig();
+
+        /**
+         * Get Configuration Module.
+         * <p>Default to {@literal null}.</p>
+         * @return Configuration Module
+         */
+        ModuleAssembly configModule();
+
+        /**
+         * Get Configuration Visibility.
+         * <p>Default to {@link org.apache.polygene.api.common.Visibility#module}.</p>
+         * @return Configuration Visibility
+         */
+        org.apache.polygene.api.common.Visibility configVisibility();
+    }
+
+    /**
+     * Assembler with Visibility adapter.
+     * @param <AssemblerType> Parameterized type of Assembler
+     */
+    public static abstract class Visibility<AssemblerType>
+        implements Visible<AssemblerType>
+    {
+        private org.apache.polygene.api.common.Visibility visibility = org.apache.polygene.api.common.Visibility.module;
+
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public final AssemblerType visibleIn( org.apache.polygene.api.common.Visibility visibility )
+        {
+            this.visibility = visibility;
+            return (AssemblerType) this;
+        }
+
+        @Override
+        public final org.apache.polygene.api.common.Visibility visibility()
+        {
+            return visibility;
+        }
+    }
+
+    /**
+     * Assembler with Identity adapter.
+     * @param <AssemblerType> Parameterized type of Assembler
+     */
+    public static abstract class Identity<AssemblerType>
+        implements Identifiable<AssemblerType>
+    {
+        private String identity;
+
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public final AssemblerType identifiedBy( String identity )
+        {
+            this.identity = identity;
+            return (AssemblerType) this;
+        }
+
+        @Override
+        public final boolean hasIdentity()
+        {
+            return identity != null;
+        }
+
+        @Override
+        public final String identity()
+        {
+            return identity;
+        }
+    }
+
+    /**
+     * Assembler with Configuration adapter.
+     * @param <AssemblerType> Parameterized type of Assembler
+     */
+    public static abstract class Config<AssemblerType>
+        implements Configurable<AssemblerType>
+    {
+        private ModuleAssembly configModule = null;
+        private org.apache.polygene.api.common.Visibility configVisibility = org.apache.polygene.api.common.Visibility.module;
+
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public final AssemblerType withConfig( ModuleAssembly configModule,
+                                               org.apache.polygene.api.common.Visibility configVisibility )
+        {
+            this.configModule = configModule;
+            this.configVisibility = configVisibility;
+            return (AssemblerType) this;
+        }
+
+        @Override
+        public final boolean hasConfig()
+        {
+            return configModule != null;
+        }
+
+        @Override
+        public final ModuleAssembly configModule()
+        {
+            return configModule;
+        }
+
+        @Override
+        public final org.apache.polygene.api.common.Visibility configVisibility()
+        {
+            return configVisibility;
+        }
+    }
+
+    /**
+     * Assembler with Visibility and Identity adapter.
+     * @param <AssemblerType> Parameterized type of Assembler
+     */
+    public static abstract class VisibilityIdentity<AssemblerType>
+        implements Visible<AssemblerType>,
+                   Identifiable<AssemblerType>
+    {
+        private org.apache.polygene.api.common.Visibility visibility = org.apache.polygene.api.common.Visibility.module;
+        private String identity;
+
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public final AssemblerType visibleIn( org.apache.polygene.api.common.Visibility visibility )
+        {
+            this.visibility = visibility;
+            return (AssemblerType) this;
+        }
+
+        @Override
+        public final org.apache.polygene.api.common.Visibility visibility()
+        {
+            return visibility;
+        }
+
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public final AssemblerType identifiedBy( String identityString )
+        {
+            this.identity = identityString;
+            return (AssemblerType) this;
+        }
+
+        @Override
+        public final boolean hasIdentity()
+        {
+            return identity != null;
+        }
+
+        @Override
+        public final String identity()
+        {
+            return identity;
+        }
+    }
+
+    /**
+     * Assembler with Visibility and Configuration adapter.
+     * @param <AssemblerType> Parameterized type of Assembler
+     */
+    public static abstract class VisibilityConfig<AssemblerType>
+        implements Visible<AssemblerType>,
+                   Configurable<AssemblerType>
+    {
+        private org.apache.polygene.api.common.Visibility visibility = org.apache.polygene.api.common.Visibility.module;
+        private ModuleAssembly configModule = null;
+        private org.apache.polygene.api.common.Visibility configVisibility = org.apache.polygene.api.common.Visibility.module;
+
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public final AssemblerType visibleIn( org.apache.polygene.api.common.Visibility visibility )
+        {
+            this.visibility = visibility;
+            return (AssemblerType) this;
+        }
+
+        @Override
+        public final org.apache.polygene.api.common.Visibility visibility()
+        {
+            return visibility;
+        }
+
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public final AssemblerType withConfig( ModuleAssembly configModule,
+                                               org.apache.polygene.api.common.Visibility configVisibility )
+        {
+            this.configModule = configModule;
+            this.configVisibility = configVisibility;
+            return (AssemblerType) this;
+        }
+
+        @Override
+        public final boolean hasConfig()
+        {
+            return configModule != null;
+        }
+
+        @Override
+        public final ModuleAssembly configModule()
+        {
+            return configModule;
+        }
+
+        @Override
+        public final org.apache.polygene.api.common.Visibility configVisibility()
+        {
+            return configVisibility;
+        }
+    }
+
+    /**
+     * Assembler with Identity and Configuration adapter.
+     * @param <AssemblerType> Parameterized type of Assembler
+     */
+    public static abstract class IdentityConfig<AssemblerType>
+        implements Identifiable<AssemblerType>,
+                   Configurable<AssemblerType>
+    {
+        private String identity;
+        private ModuleAssembly configModule = null;
+        private org.apache.polygene.api.common.Visibility configVisibility = org.apache.polygene.api.common.Visibility.module;
+
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public final AssemblerType identifiedBy( String identity )
+        {
+            this.identity = identity;
+            return (AssemblerType) this;
+        }
+
+        @Override
+        public final boolean hasIdentity()
+        {
+            return identity != null;
+        }
+
+        @Override
+        public final String identity()
+        {
+            return identity;
+        }
+
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public final AssemblerType withConfig( ModuleAssembly configModule,
+                                               org.apache.polygene.api.common.Visibility configVisibility )
+        {
+            this.configModule = configModule;
+            this.configVisibility = configVisibility;
+            return (AssemblerType) this;
+        }
+
+        @Override
+        public final boolean hasConfig()
+        {
+            return configModule != null;
+        }
+
+        @Override
+        public final ModuleAssembly configModule()
+        {
+            return configModule;
+        }
+
+        @Override
+        public final org.apache.polygene.api.common.Visibility configVisibility()
+        {
+            return configVisibility;
+        }
+    }
+
+    /**
+     * Assembler with Visibility, Identity and Configuation adapter.
+     * @param <AssemblerType> Parameterized type of Assembler
+     */
+    public static abstract class VisibilityIdentityConfig<AssemblerType>
+        implements Visible<AssemblerType>,
+                   Identifiable<AssemblerType>,
+                   Configurable<AssemblerType>
+    {
+        private org.apache.polygene.api.common.Visibility visibility = org.apache.polygene.api.common.Visibility.module;
+        private String identity;
+        private ModuleAssembly configModule = null;
+        private org.apache.polygene.api.common.Visibility configVisibility = org.apache.polygene.api.common.Visibility.module;
+
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public final AssemblerType visibleIn( org.apache.polygene.api.common.Visibility visibility )
+        {
+            this.visibility = visibility;
+            return (AssemblerType) this;
+        }
+
+        @Override
+        public final org.apache.polygene.api.common.Visibility visibility()
+        {
+            return visibility;
+        }
+
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public final AssemblerType identifiedBy( String identity )
+        {
+            this.identity = identity;
+            return (AssemblerType) this;
+        }
+
+        @Override
+        public final boolean hasIdentity()
+        {
+            return identity != null;
+        }
+
+        @Override
+        public final String identity()
+        {
+            return identity;
+        }
+
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public final AssemblerType withConfig( ModuleAssembly configModule,
+                                               org.apache.polygene.api.common.Visibility configVisibility )
+        {
+            this.configModule = configModule;
+            this.configVisibility = configVisibility;
+            return (AssemblerType) this;
+        }
+
+        @Override
+        public final boolean hasConfig()
+        {
+            return configModule != null;
+        }
+
+        @Override
+        public final ModuleAssembly configModule()
+        {
+            return configModule;
+        }
+
+        @Override
+        public final org.apache.polygene.api.common.Visibility configVisibility()
+        {
+            return configVisibility;
+        }
+    }
+
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblyException.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblyException.java
new file mode 100644
index 0000000..0f88b72
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblyException.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.bootstrap;
+
+/**
+ * Thrown by ModuleAssembly if the Assembler tries to make an invalid assembly.
+ */
+public class AssemblyException extends RuntimeException
+{
+    public AssemblyException()
+    {
+    }
+
+    public AssemblyException( String string )
+    {
+        super( string );
+    }
+
+    public AssemblyException( String string, Throwable throwable )
+    {
+        super( string, throwable );
+    }
+
+    public AssemblyException( Throwable throwable )
+    {
+        super( throwable );
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblyReportException.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblyReportException.java
new file mode 100644
index 0000000..f3c933c
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblyReportException.java
@@ -0,0 +1,84 @@
+/*
+ *  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.polygene.bootstrap;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Thrown when one or more assembly problems has occurred.
+ */
+public class AssemblyReportException extends AssemblyException
+{
+    private List<Throwable> problems;
+    private String modelReport;
+
+    public AssemblyReportException( List<Throwable> problems )
+    {
+        this.problems = problems;
+    }
+
+    @Override
+    public String getMessage()
+    {
+        String message;
+        if( modelReport == null )
+        {
+            message = "\nComposition Problems Report:\n";
+        }
+        else
+        {
+            message = modelReport;
+        }
+        return message + problems.stream()
+                                 .map( this::composeMessage )
+                                 .map( m -> m + "\n--\n" )
+                                 .collect( Collectors.joining() );
+    }
+
+    public void attacheModelReport( String modelReport )
+    {
+        this.modelReport = modelReport;
+    }
+
+    private String composeMessage( Throwable exception )
+    {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        PrintStream ps = new PrintStream( baos );
+        if( Boolean.getBoolean( "polygene.report.exceptions" ) )
+        {
+            exception.printStackTrace( ps );
+        }
+        else
+        {
+            StringBuilder indent = new StringBuilder();
+            while( exception != null )
+            {
+                indent = indent.append( "  " );
+                ps.println( indent.toString() + exception.getMessage() );
+                ps.println( "---" );
+                exception = exception.getCause();
+            }
+        }
+        return baos.toString();
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblySpecifications.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblySpecifications.java
new file mode 100644
index 0000000..756d496
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblySpecifications.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.bootstrap;
+
+import java.util.Arrays;
+import java.util.function.Predicate;
+import org.apache.polygene.api.type.HasTypes;
+
+/**
+ * Utility specifications for Assemblies.
+ */
+public class AssemblySpecifications
+{
+    public static Predicate<HasTypes> ofAnyType( final Class... types )
+    {
+        return item -> item.types().anyMatch( a -> Arrays.stream( types ).anyMatch( a::equals ) );
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblyVisitor.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblyVisitor.java
new file mode 100644
index 0000000..0617974
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblyVisitor.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.bootstrap;
+
+/**
+ * Visitor interface to visit the whole or parts of an assembly.
+ * <p>
+ * Implement this interface and call visit() on ApplicationAssembly, LayerAssembly or ModuleAssembly.
+ * </p>
+ * <p>
+ * This can be used to, for example, add metadata to all entities, add concerns on composites, or similar.
+ * </p>
+ */
+public interface AssemblyVisitor<ThrowableType extends Throwable>
+{
+    void visitApplication( ApplicationAssembly assembly )
+        throws ThrowableType;
+
+    void visitLayer( LayerAssembly assembly )
+        throws ThrowableType;
+
+    void visitModule( ModuleAssembly assembly )
+        throws ThrowableType;
+
+    void visitComposite( TransientDeclaration declaration )
+        throws ThrowableType;
+
+    void visitEntity( EntityDeclaration declaration )
+        throws ThrowableType;
+
+    void visitService( ServiceDeclaration declaration )
+        throws ThrowableType;
+
+    void visitImportedService( ImportedServiceDeclaration declaration )
+        throws ThrowableType;
+
+    void visitValue( ValueDeclaration declaration )
+        throws ThrowableType;
+
+    void visitObject( ObjectDeclaration declaration )
+        throws ThrowableType;
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblyVisitorAdapter.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblyVisitorAdapter.java
new file mode 100644
index 0000000..019f4ad
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssemblyVisitorAdapter.java
@@ -0,0 +1,83 @@
+/*
+ *  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.polygene.bootstrap;
+
+/**
+ * Base class for assembly visitors. Subclass and override
+ * the particular methods you are interested in.
+ */
+public class AssemblyVisitorAdapter<ThrowableType extends Throwable>
+    implements AssemblyVisitor<ThrowableType>
+{
+    @Override
+    public void visitApplication( ApplicationAssembly assembly )
+        throws ThrowableType
+    {
+    }
+
+    @Override
+    public void visitLayer( LayerAssembly assembly )
+        throws ThrowableType
+    {
+    }
+
+    @Override
+    public void visitModule( ModuleAssembly assembly )
+        throws ThrowableType
+    {
+    }
+
+    @Override
+    public void visitComposite( TransientDeclaration declaration )
+        throws ThrowableType
+    {
+    }
+
+    @Override
+    public void visitEntity( EntityDeclaration declaration )
+        throws ThrowableType
+    {
+    }
+
+    @Override
+    public void visitService( ServiceDeclaration declaration )
+        throws ThrowableType
+    {
+    }
+
+    @Override
+    public void visitImportedService( ImportedServiceDeclaration declaration )
+        throws ThrowableType
+    {
+    }
+
+    @Override
+    public void visitValue( ValueDeclaration declaration )
+        throws ThrowableType
+    {
+    }
+
+    @Override
+    public void visitObject( ObjectDeclaration declaration )
+        throws ThrowableType
+    {
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssociationDeclarations.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssociationDeclarations.java
new file mode 100644
index 0000000..b7a6d8d
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/AssociationDeclarations.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.bootstrap;
+
+import java.lang.reflect.AccessibleObject;
+import org.apache.polygene.api.common.MetaInfo;
+
+/**
+ * This provides declared {@link org.apache.polygene.api.association.Association} information that the runtime can use.
+ */
+public interface AssociationDeclarations
+{
+    MetaInfo metaInfoFor( AccessibleObject accessor );
+}
\ No newline at end of file
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/BindingException.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/BindingException.java
new file mode 100644
index 0000000..bbd2dd1
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/BindingException.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.bootstrap;
+
+/**
+ * Thrown by the Polygene runtime if a dependency can not be bound.
+ */
+public class BindingException
+    extends Exception
+{
+    public BindingException( String s )
+    {
+        super( s );
+    }
+
+    public BindingException( String s, InvalidInjectionException ex )
+    {
+        super( s, ex );
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/BootstrapException.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/BootstrapException.java
new file mode 100644
index 0000000..e590d0a
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/BootstrapException.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.bootstrap;
+
+/**
+ * This exception is thrown if no ApplicationFactory provider can be found
+ */
+public class BootstrapException
+    extends RuntimeException
+{
+    public BootstrapException( String message )
+    {
+        super( message );
+    }
+
+    public BootstrapException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ClassScanner.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ClassScanner.java
new file mode 100644
index 0000000..5850e95
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ClassScanner.java
@@ -0,0 +1,182 @@
+/*
+ *  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.polygene.bootstrap;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.security.CodeSource;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
+/**
+ * Scan classpath for classes that matches given criteria. Useful for automated assemblies with lots of similar classes.
+ */
+public class ClassScanner
+{
+    private static final ValidClass VALID_CLASS_PREDICATE = new ValidClass();
+
+    /**
+     * Get all classes from the same package of the given class, and recursively in all subpackages.
+     * <p>
+     * This only works if the seed class is loaded from a file: URL. Jar files are possible as well. Abstract classes
+     * are not included in the results. For further filtering use e.g. Stream.filter.
+     * </p>
+     * @param seedClass starting point for classpath scanning
+     *
+     * @return Stream of all concrete classes in the same package as the seedclass, and also all classes in subpackages.
+     */
+    public static Stream<? extends Class<?>> findClasses( final Class<?> seedClass )
+    {
+        CodeSource codeSource = seedClass.getProtectionDomain().getCodeSource();
+        if( codeSource == null )
+        {
+            return Stream.of();
+        }
+
+        URL location = codeSource.getLocation();
+
+        if( !location.getProtocol().equals( "file" ) )
+        {
+            throw new IllegalArgumentException(
+                "Can only enumerate classes from file system locations. URL is:" + location );
+        }
+
+        final File file;
+        try
+        {
+            file = new File( location.toURI().getPath() );
+        }
+        catch( URISyntaxException e )
+        {
+            throw new IllegalArgumentException(
+                "The file location of codebase is invalid. Can not convert to URI. URL is:" + location );
+        }
+
+        if( file.getName().endsWith( ".jar" ) )
+        {
+            try
+            {
+                final String packageName = seedClass.getPackage().getName().replace( '.', '/' );
+
+                JarFile jarFile = new JarFile( file );
+                List<JarEntry> entries = Collections.list( jarFile.entries() );
+                try
+                {
+                    return entries.stream()
+                                  .filter( jarEntry -> jarEntry.getName().startsWith( packageName )
+                                                       && jarEntry.getName().endsWith( ".class" ) )
+                                  .map( jarEntry ->
+                                        {
+                                            String name = jarEntry.getName();
+                                            name = name.substring( 0, name.length() - 6 );
+                                            name = name.replace( '/', '.' );
+                                            try
+                                            {
+                                                return seedClass.getClassLoader().loadClass( name );
+                                            }
+                                            catch( ClassNotFoundException e )
+                                            {
+                                                return null;
+                                            }
+                                        } )
+                                  .filter( VALID_CLASS_PREDICATE );
+                }
+                finally
+                {
+                    jarFile.close();
+                }
+            }
+            catch( IOException e )
+            {
+                throw new IllegalArgumentException( "Could not open jar file " + file, e );
+            }
+        }
+        else
+        {
+            final File path = new File( file, seedClass.getPackage().getName().replace( '.', File.separatorChar ) );
+            Stream<File> classFiles = findFiles( path, candidate -> candidate.getName().endsWith( ".class" ) );
+            return classFiles
+                .map( classFile ->
+                      {
+                          String fileName = classFile.getAbsolutePath().substring( file.toString().length() + 1 );
+                          fileName = fileName.replace( File.separatorChar, '.' ).substring( 0, fileName.length() - 6 );
+                          try
+                          {
+                              return seedClass.getClassLoader().loadClass( fileName );
+                          }
+                          catch( ClassNotFoundException e )
+                          {
+                              return null;
+                          }
+                      } )
+                .filter( VALID_CLASS_PREDICATE );
+        }
+    }
+
+    /**
+     * Useful specification for filtering classes based on a regular expression matching the class names.
+     * <p>
+     * Example: matches(".*Model") -&gt; match only class names that end with Model
+     * </p>
+     *
+     * @param regex The regular expression to be matched.
+     *
+     * @return regex class name specification
+     */
+    public static Predicate<Class<?>> matches( String regex )
+    {
+        final Pattern pattern = Pattern.compile( regex );
+        return aClass -> pattern.matcher( aClass.getName() ).matches();
+    }
+
+    private static Stream<File> findFiles( File directory, final Predicate<File> filter )
+    {
+        File[] listedFiles = directory.listFiles();
+        if( listedFiles == null )
+        {
+            return Stream.of();
+        }
+        return Stream.concat( Stream.of( listedFiles ).filter( filter ),
+                              Stream.of( listedFiles )
+                                    .filter( File::isDirectory )
+                                    .map( dir -> findFiles( dir, filter ) )
+                                    .flatMap( Function.identity() ) );
+    }
+
+    private static class ValidClass
+        implements Predicate<Class<?>>
+    {
+        @Override
+        public boolean test( Class<?> item )
+        {
+            return ( item.isInterface() || !Modifier.isAbstract( item.getModifiers() ) )
+                   && ( !item.isEnum() && !item.isAnonymousClass() );
+        }
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ConfigurationDeclaration.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ConfigurationDeclaration.java
new file mode 100644
index 0000000..080cbb7
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ConfigurationDeclaration.java
@@ -0,0 +1,89 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.common.Visibility;
+
+/**
+ * Fluent API for declaring configurations. Instances
+ * of this API are acquired by calling {@link ModuleAssembly#configurations(Class[])}.
+ */
+public interface ConfigurationDeclaration
+{
+    /**
+     * Set additional metainfo for this configuration declaration.
+     *
+     * @param info metainfo that can be retrieved from the CompositeDescriptor.
+     *
+     * @return This instance for a fluid DSL
+     */
+    ConfigurationDeclaration setMetaInfo( Object info );
+
+    /**
+     * Set visibility for declared entities.
+     *
+     * @param visibility The {@link Visibility} that this ConfigurationComposite will have.
+     *
+     * @return This instance for a fluid DSL
+     */
+    ConfigurationDeclaration visibleIn( Visibility visibility );
+
+    /**
+     * Declare additional concerns for these configurations.
+     *
+     * @param concerns The concerns that are to be added to the ConfigurationComposite beyond the statically declared ones.
+     *
+     * @return This instance for a fluid DSL
+     */
+    ConfigurationDeclaration withConcerns( Class<?>... concerns );
+
+    /**
+     * Declare additional side-effects for these configurations.
+     *
+     * @param sideEffects The sideeffects that are to be added to the ConfigurationComposite beyond the statically declared ones.
+     *
+     * @return This instance for a fluid DSL
+     */
+    ConfigurationDeclaration withSideEffects( Class<?>... sideEffects );
+
+    /**
+     * Declare additional mixins for these configurations.
+     * <p>
+     * This can be useful to override any default mixins from the configuration interface.
+     * </p>
+     * @param mixins The mixins that are to be added to the ConfigurationComposite beyond the statically declared ones.
+     *
+     * @return This instance for a fluid DSL
+     */
+    ConfigurationDeclaration withMixins( Class<?>... mixins );
+
+    /**
+     * Declare additional interfaces for these declared interfaces.
+     * <p>
+     * This can be useful to add types that the Configuration should implement, but
+     * which you do not want to include in the entity interface itself.
+     * </p>
+     * @param types list of interfaces to add
+     *
+     * @return This instance for a fluid DSL
+     */
+    ConfigurationDeclaration withTypes( Class<?>... types );
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/Energy4Java.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/Energy4Java.java
new file mode 100644
index 0000000..a4cf0c3
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/Energy4Java.java
@@ -0,0 +1,114 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.InvalidCompositeException;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.spi.PolygeneSPI;
+
+/**
+ * Main bootstrap class for starting Polygene and creating new applications.
+ * <p>
+ * Instantiate this and call one of the factory methods to get started.
+ * </p>
+ * <p>
+ * This class will use the Service Loader mechanism in Java to try to locate a runtime that implements
+ * the PolygeneRuntime interface. This avoids a direct dependency from the bootstrap to the runtime.
+ * </p>
+ */
+public final class Energy4Java
+{
+    private PolygeneRuntime runtime;
+
+    public Energy4Java( RuntimeFactory runtimeFactory )
+    {
+        this( runtimeFactory.createRuntime() );
+    }
+
+    public Energy4Java()
+    {
+        this( new RuntimeFactory.StandaloneApplicationRuntimeFactory().createRuntime() );
+    }
+
+    public Energy4Java( PolygeneRuntime runtime )
+    {
+        if( runtime == null )
+        {
+            throw new BootstrapException( "Can not create Polygene without a Polygene Runtime." );
+        }
+        this.runtime = runtime;
+    }
+
+    public ApplicationDescriptor newApplicationModel( ApplicationAssembler assembler )
+        throws AssemblyException
+    {
+        ApplicationAssembly assembly = assembler.assemble( runtime.applicationAssemblyFactory() );
+
+        if( assembly == null )
+        {
+            throw new AssemblyException( "Application assembler did not return any ApplicationAssembly" );
+        }
+
+        try
+        {
+            ApplicationModelFactory modelFactory = runtime.applicationModelFactory();
+            ApplicationDescriptor model = modelFactory.newApplicationModel( assembly );
+            String modelReport = InvalidCompositeException.modelReport();
+            if( modelReport != null )
+            {
+                throw new AssemblyException( "Composition problems\n\n" + modelReport );
+            }
+            return model;
+        }
+        catch( AssemblyReportException e )
+        {
+            e.attacheModelReport( InvalidCompositeException.modelReport() );
+            throw e;
+        }
+        catch( AssemblyException e )
+        {
+            throw e;
+        }
+        catch( RuntimeException e )
+        {
+            throw new AssemblyException( "Unable to create Application Model.", e );
+        }
+    }
+
+    public Application newApplication( ApplicationAssembler assembler, Object... importedServiceInstances )
+        throws AssemblyException
+    {
+        ApplicationDescriptor model = newApplicationModel( assembler );
+        return model.newInstance( runtime.spi(), importedServiceInstances );
+    }
+
+    public PolygeneSPI spi()
+    {
+        return runtime.spi();
+    }
+
+    public PolygeneAPI api()
+    {
+        return runtime.spi();
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/EntityAssembly.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/EntityAssembly.java
new file mode 100644
index 0000000..7a3ce0a
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/EntityAssembly.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.type.HasTypes;
+
+/**
+ * This represents the assembly information of a single EntityComposite in a Module.
+ */
+public interface EntityAssembly
+    extends HasTypes
+{
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/EntityDeclaration.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/EntityDeclaration.java
new file mode 100644
index 0000000..32f7e60
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/EntityDeclaration.java
@@ -0,0 +1,89 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.common.Visibility;
+
+/**
+ * Fluent API for declaring entities. Instances
+ * of this API are acquired by calling {@link ModuleAssembly#entities(Class[])}.
+ */
+public interface EntityDeclaration
+{
+    /**
+     * Set additional metainfo for this entity declaration.
+     *
+     * @param info metainfo that can be retrieved from the EntityDescriptor.
+     *
+     * @return This instance for a fluid DSL
+     */
+    EntityDeclaration setMetaInfo( Object info );
+
+    /**
+     * Set visibility for declared entities.
+     *
+     * @param visibility The {@link Visibility} that this EntityComposite will have.
+     *
+     * @return This instance for a fluid DSL
+     */
+    EntityDeclaration visibleIn( Visibility visibility );
+
+    /**
+     * Declare additional concerns for these entities.
+     *
+     * @param concerns The concerns that are to be added to the EntityComposite beyond the statically declared ones.
+     *
+     * @return This instance for a fluid DSL
+     */
+    EntityDeclaration withConcerns( Class<?>... concerns );
+
+    /**
+     * Declare additional side-effects for these entitites.
+     *
+     * @param sideEffects The sideeffects that are to be added to the EntityComposite beyond the statically declared ones.
+     *
+     * @return This instance for a fluid DSL
+     */
+    EntityDeclaration withSideEffects( Class<?>... sideEffects );
+
+    /**
+     * Declare additional mixins for these entities.
+     * <p>
+     * This can be useful to override any default mixins from the entity interface.
+     * </p>
+     * @param mixins The mixins that are to be added to the EntityComposite beyond the statically declared ones.
+     *
+     * @return This instance for a fluid DSL
+     */
+    EntityDeclaration withMixins( Class<?>... mixins );
+
+    /**
+     * Declare additional interfaces for these declared interfaces.
+     * <p>
+     * This can be useful to add types that the entities should implement, but
+     * which you do not want to include in the entity interface itself.
+     * </p>
+     * @param types list of interfaces to add
+     *
+     * @return This instance for a fluid DSL
+     */
+    EntityDeclaration withTypes( Class<?>... types );
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ImportedServiceAssembly.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ImportedServiceAssembly.java
new file mode 100644
index 0000000..057c179
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ImportedServiceAssembly.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.type.HasTypes;
+
+/**
+ * This represents the assembly information of a single imported service in a Module.
+ */
+public interface ImportedServiceAssembly
+    extends HasTypes
+{
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ImportedServiceDeclaration.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ImportedServiceDeclaration.java
new file mode 100644
index 0000000..33a77f9
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ImportedServiceDeclaration.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.importer.InstanceImporter;
+import org.apache.polygene.api.service.importer.NewObjectImporter;
+import org.apache.polygene.api.service.importer.ServiceInstanceImporter;
+import org.apache.polygene.api.service.importer.ServiceSelectorImporter;
+
+/**
+ * Fluent API for declaring imported services. Instances
+ * of this API are acquired by calling {@link ModuleAssembly#importedServices(Class[])}.
+ */
+public interface ImportedServiceDeclaration
+{
+    // Convenience constants for common service importers
+    Class<? extends ServiceImporter> INSTANCE = InstanceImporter.class;
+    Class<? extends ServiceImporter> NEW_OBJECT = NewObjectImporter.class;
+    Class<? extends ServiceImporter> SERVICE_SELECTOR = ServiceSelectorImporter.class;
+    Class<? extends ServiceImporter> SERVICE_IMPORTER = ServiceInstanceImporter.class;
+
+    ImportedServiceDeclaration visibleIn( Visibility visibility );
+
+    ImportedServiceDeclaration importedBy( Class<? extends ServiceImporter> serviceImporterClass );
+
+    ImportedServiceDeclaration identifiedBy( String identity );
+
+    ImportedServiceDeclaration taggedWith( String... tags );
+
+    ImportedServiceDeclaration setMetaInfo( Object serviceAttribute );
+    
+    ImportedServiceDeclaration importOnStartup();
+
+    /**
+     * Set the imported service activators. Activators are executed in order around
+     * the ServiceReference activation and passivation.
+     *
+     * @param activators the imported service activators
+     * @return the assembly
+     */    
+    @SuppressWarnings( { "unchecked","varargs" } )
+    ImportedServiceDeclaration withActivators( Class<? extends Activator<?>>... activators );
+}
\ No newline at end of file
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/InjectionException.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/InjectionException.java
new file mode 100644
index 0000000..47d88ca
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/InjectionException.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.bootstrap;
+
+/**
+ * Thrown by the Polygene runtime if a dependency can not be injected.
+ */
+public class InjectionException
+    extends RuntimeException
+{
+    public InjectionException( String s )
+    {
+        super( s );
+    }
+
+    public InjectionException( String s, Throwable throwable )
+    {
+        super( s, throwable );
+    }
+
+    public InjectionException( Throwable throwable )
+    {
+        super( throwable );
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/InvalidInjectionException.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/InvalidInjectionException.java
new file mode 100644
index 0000000..4b9c3cb
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/InvalidInjectionException.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.bootstrap;
+
+/**
+ * Thrown by the Polygene runtime if a dependency injection declaration is invalid.
+ */
+public class InvalidInjectionException
+    extends Exception
+{
+    public InvalidInjectionException( String s )
+    {
+        super( s );
+    }
+
+    public InvalidInjectionException( String s, Throwable throwable )
+    {
+        super( s, throwable );
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/LayerAssembly.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/LayerAssembly.java
new file mode 100644
index 0000000..f5c3b09
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/LayerAssembly.java
@@ -0,0 +1,166 @@
+/*
+ *  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.polygene.bootstrap;
+
+import java.util.function.Predicate;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.structure.Layer;
+
+/**
+ * Fluid API for declaring a layer in an application. This is obtained by calling {@link ApplicationAssembly#layer(String)}.
+ */
+public interface LayerAssembly
+{
+    /**
+     * Get an assembly for a particular Module. If this is called many times with the same name, then the same module
+     * is affected.
+     *
+     * @param name The name of the Module to retrieve or create.
+     *
+     * @return The ModuleAssembly for the Module.
+     */
+    ModuleAssembly module( String name );
+
+    /**
+     *
+     * @return the {@link ApplicationAssembly} that this {@code LayerAssembly} belongs to.
+     */
+    ApplicationAssembly application();
+
+    /**
+     *
+     * @return the name of the {@code Layer} that is being assembled.
+     */
+    String name();
+
+    /**
+     * Sets the name of the {@code Layer} being assembled.
+     * By convention, a {@code Layer} should include the word "Layer" as the suffix, e.g "DomainLayer", so tooling
+     * can use camel-case detection and present the name and not require it to explicitly say that it is a layer.
+     *
+     * @param name The name that the Layer should have.
+     * @return this {@code LayerAssembly} instance to support fluent APIs
+     */
+    LayerAssembly setName( String name );
+
+    /** Set metadata for the {@code Layer}.
+     * Any arbitrary object can be attached as metainfo on a {@code Layer} that is available in runtime, by calling
+     * {@link org.apache.polygene.api.structure.Layer#metaInfo(Class)}. Multiple registrations of the same type is
+     * not possible, and the lookup will search registered meta-info objects against the lookup type, prioritizing
+     * interfaces over classes and the most sub-typed nterface first.
+     *
+     * @param info The meta-info type to be looked up. Typically a type that is explicitly used for meta-info.
+     * @return this {@code LayerAssembly} instance to support fluent APIs
+     */
+    LayerAssembly setMetaInfo( Object info );
+
+    /** Declaration of which other {@code Layers} that this {@code Layer} is able to use.
+     * This is how architecture reinforcement works. Any composites that are declared
+     * {@link org.apache.polygene.api.common.Visibility#application} in a "used" layer can be reached from this Layer.
+     *
+     * @param layerAssembly The {@code Layer(s)} that this {@code Layer} can reach/see.
+     * @return this {@code LayerAssembly} instance to support fluent APIs
+     */
+    LayerAssembly uses( LayerAssembly... layerAssembly );
+
+    /**
+     * Set the layer activators. Activators are executed in order around the
+     * Layer activation and passivation.
+     *
+     * @param activators the layer activators
+     * @return the assembly
+     */    
+    @SuppressWarnings( { "unchecked","varargs" } )
+    LayerAssembly withActivators( Class<? extends Activator<Layer>>... activators );
+
+    /**
+     * The visitor pattern to inspect the entire pre-instantiated model.
+     *
+     * @deprecated New mechanism is considered, using Java 8 Stream API.
+     *
+     * @param visitor The visitor to be called.
+     * @param <ThrowableType> The exceptions that may be thrown.
+     * @throws ThrowableType when there is an underlying problem in the model.
+     */
+    @Deprecated
+    <ThrowableType extends Throwable> void visit( AssemblyVisitor<ThrowableType> visitor )
+        throws ThrowableType;
+
+    /**
+     * Given a Specification for EntityAssembly's, returns a EntityDeclaration that can
+     * be used to work with all of the assemblies in this Layer matched by the specification.
+     *
+     * @param specification The Specification that specifies the EntityComposite types of interest.
+     *
+     * @return An EntityDeclaration for the specified EntityComposite types.
+     */
+    EntityDeclaration entities( Predicate<? super EntityAssembly> specification );
+
+    /**
+     * Given a Specification for ServiceAssembly's, returns a ServiceDeclaration that can
+     * be used to work with all of the assemblies in this Layer matched by the specification.
+     *
+     * @param specification The Specification that specifies the ServiceComposite types of interest.
+     *
+     * @return An ServiceDeclaration for the specified ServiceComposite types.
+     */
+    ServiceDeclaration services( Predicate<? super ServiceAssembly> specification );
+
+    /**
+     * Given a Specification for TransientAssembly's, returns a TransientDeclaration that can
+     * be used to work with all of the assemblies in this Layer matched by the specification.
+     *
+     * @param specification The Specification that specifies the TransientComposite types of interest.
+     *
+     * @return An TransientDeclaration for the specified TransientComposite types.
+     */
+    TransientDeclaration transients( Predicate<? super TransientAssembly> specification );
+
+    /**
+     * Given a Specification for ValueAssembly's, returns a ValueDeclaration that can
+     * be used to work with all of the assemblies in this Layer matched by the specification.
+     *
+     * @param specification The Specification that specifies the ValueComposite types of interest.
+     *
+     * @return An ValueDeclaration for the specified ValueComposite types.
+     */
+    ValueDeclaration values( Predicate<? super ValueAssembly> specification );
+
+    /**
+     * Given a Specification for ObjectAssembly's, returns a ObjectDeclaration that can
+     * be used to work with all of the assemblies in this Layer matched by the specification.
+     *
+     * @param specification The Specification that specifies the Object types of interest.
+     *
+     * @return An ObjectDeclaration for the specified Object types.
+     */
+    ObjectDeclaration objects( Predicate<? super ObjectAssembly> specification );
+
+    /**
+     * Given a Specification for ImportedServiceAssembly's, returns a ImportedServiceDeclaration that can
+     * be used to work with all of the assemblies in this Layer matched by the specification.
+     *
+     * @param specification The Specification that specifies the Imported Service types of interest.
+     *
+     * @return An ImportedServiceDeclaration for the specified Imported Service types.
+     */
+    ImportedServiceDeclaration importedServices( Predicate<? super ImportedServiceAssembly> specification );
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/LayerName.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/LayerName.java
new file mode 100644
index 0000000..36e6435
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/LayerName.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.bootstrap;
+
+/**
+ * Set the name of the layer
+ */
+public final class LayerName
+    implements Assembler
+{
+    private final String name;
+
+    public LayerName( String name )
+    {
+        this.name = name;
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.layer().setName( name );
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ManyAssociationDeclarations.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ManyAssociationDeclarations.java
new file mode 100644
index 0000000..4c39a99
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ManyAssociationDeclarations.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.bootstrap;
+
+import java.lang.reflect.AccessibleObject;
+import org.apache.polygene.api.common.MetaInfo;
+
+/**
+ * This provides declared {@link org.apache.polygene.api.association.ManyAssociation} information that the runtime can use.
+ */
+public interface ManyAssociationDeclarations
+{
+    MetaInfo metaInfoFor( AccessibleObject accessor );
+}
\ No newline at end of file
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/MetaInfoDeclaration.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/MetaInfoDeclaration.java
new file mode 100644
index 0000000..348ac10
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/MetaInfoDeclaration.java
@@ -0,0 +1,229 @@
+/*
+ *  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.polygene.bootstrap;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.property.InitialValueProvider;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Declaration of a Property or Association.
+ */
+public final class MetaInfoDeclaration
+    implements StateDeclarations, AssociationDeclarations, ManyAssociationDeclarations, NamedAssociationDeclarations
+{
+    Map<Class<?>, InfoHolder<?>> mixinPropertyDeclarations = new HashMap<>();
+
+    public MetaInfoDeclaration()
+    {
+    }
+
+    public <T> MixinDeclaration<T> on( Class<T> mixinType )
+    {
+        @SuppressWarnings( "unchecked" )
+        InfoHolder<T> propertyDeclarationHolder = (InfoHolder<T>) mixinPropertyDeclarations.get( mixinType );
+        if( propertyDeclarationHolder == null )
+        {
+            propertyDeclarationHolder = new InfoHolder<>( mixinType );
+            mixinPropertyDeclarations.put( mixinType, propertyDeclarationHolder );
+        }
+        return propertyDeclarationHolder;
+    }
+
+    @Override
+    public MetaInfo metaInfoFor( AccessibleObject accessor )
+    {
+        for( Map.Entry<Class<?>, InfoHolder<?>> entry : mixinPropertyDeclarations.entrySet() )
+        {
+            InfoHolder<?> holder = entry.getValue();
+            MetaInfo metaInfo = holder.metaInfoFor( accessor );
+            if( metaInfo != null )
+            {
+                Class<?> mixinType = entry.getKey();
+                return metaInfo.withAnnotations( mixinType )
+                    .withAnnotations( accessor )
+                    .withAnnotations( accessor instanceof Method ? ( (Method) accessor ).getReturnType() : ( (Field) accessor )
+                        .getType() );
+            }
+        }
+        // TODO is this code reached at all??
+        Class<?> declaringType = ( (Member) accessor ).getDeclaringClass();
+        return new MetaInfo().withAnnotations( declaringType )
+            .withAnnotations( accessor )
+            .withAnnotations( accessor instanceof Method ? ( (Method) accessor ).getReturnType() : ( (Field) accessor ).getType() );
+    }
+
+    @Override
+    public Object initialValueOf( AccessibleObject accessor )
+    {
+        for( InfoHolder<?> propertyDeclarationHolder : mixinPropertyDeclarations.values() )
+        {
+            final Object initialValue = propertyDeclarationHolder.initialValueOf( accessor );
+            if( initialValue != null )
+            {
+                return initialValue;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public boolean useDefaults( AccessibleObject accessor )
+    {
+        for( InfoHolder<?> propertyDeclarationHolder : mixinPropertyDeclarations.values() )
+        {
+            final boolean useDefaults = propertyDeclarationHolder.useDefaults( accessor );
+            if( useDefaults )
+            {
+                return useDefaults;
+            }
+        }
+        return false;
+    }
+
+    private static class InfoHolder<T>
+        implements InvocationHandler, StateDeclarations, MixinDeclaration<T>
+    {
+        private final static class MethodInfo
+        {
+            Object initialValue;
+            boolean useDefaults;
+            MetaInfo metaInfo;
+
+            private MethodInfo( MetaInfo metaInfo )
+            {
+                this.metaInfo = metaInfo;
+            }
+        }
+
+        private final Class<T> mixinType;
+        private final Map<AccessibleObject, MethodInfo> methodInfos = new HashMap<>();
+        // temporary holder
+        private MetaInfo metaInfo = null;
+
+        private InfoHolder( Class<T> mixinType )
+        {
+            this.mixinType = mixinType;
+        }
+
+        @Override
+        @SuppressWarnings( "raw" )
+        public Object invoke( Object o, Method method, Object[] objects )
+            throws Throwable
+        {
+            final MethodInfo methodInfo = new MethodInfo( metaInfo );
+            methodInfo.useDefaults = true;
+            methodInfos.put( method, methodInfo );
+            metaInfo = null; // reset
+            final Class<?> returnType = method.getReturnType();
+            try
+            {
+                return Proxy.newProxyInstance( returnType.getClassLoader(), new Class[]{ returnType },
+                                               ( o1, method1, objects1 ) -> {
+                                                   if( method1.getName().equals( "set" ) )
+                                                   {
+                                                       methodInfo.initialValue = objects1[ 0 ];
+                                                   }
+                                                   return null;
+                                               } );
+            }
+            catch( IllegalArgumentException e )
+            {
+                throw new IllegalArgumentException(
+                    "Only methods with " + Property.class.getName() + " as return type can have declareDefaults()" );
+            }
+        }
+
+        public MethodInfo matches( AccessibleObject accessor )
+        {
+            return methodInfos.get( accessor );
+        }
+
+        @Override
+        public MetaInfo metaInfoFor( AccessibleObject accessor )
+        {
+            final MethodInfo methodInfo = matches( accessor );
+            if( methodInfo == null )
+            {
+                return null;
+            }
+            return methodInfo.metaInfo;
+        }
+
+        @Override
+        public Object initialValueOf( AccessibleObject accessor )
+        {
+            final MethodInfo methodInfo = matches( accessor );
+            if( methodInfo == null )
+            {
+                return null;
+            }
+            return methodInfo.initialValue;
+        }
+
+        @Override
+        public boolean useDefaults( AccessibleObject accessor )
+        {
+            final MethodInfo methodInfo = matches( accessor );
+            if( methodInfo == null )
+            {
+                return false;
+            }
+            return methodInfo.useDefaults;
+        }
+
+        // DSL Interface
+
+        @Override
+        @SuppressWarnings( "raw" )
+        public T declareDefaults()
+        {
+            return mixinType.cast(
+                Proxy.newProxyInstance( mixinType.getClassLoader(), new Class[]{ mixinType }, this ) );
+        }
+
+        @Override
+        public MixinDeclaration<T> setMetaInfo( Object info )
+        {
+            if( metaInfo == null )
+            {
+                metaInfo = new MetaInfo();
+            }
+            metaInfo.set( info );
+            return this;
+        }
+
+        @Override
+        public MixinDeclaration<T> declareInitialValueProvider(InitialValueProvider provider)
+        {
+            metaInfo.add( InitialValueProvider.class, provider);
+            return this;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/MixinDeclaration.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/MixinDeclaration.java
new file mode 100644
index 0000000..a50f305
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/MixinDeclaration.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.property.InitialValueProvider;
+
+/**
+ * Fluent API for declaring information about properties
+ *
+ * @param <T> Parameterized mixin type
+ */
+public interface MixinDeclaration<T>
+{
+    T declareDefaults();
+
+    MixinDeclaration<T> setMetaInfo( Object info );
+
+    MixinDeclaration<T> declareInitialValueProvider(InitialValueProvider provider);
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ModuleAssembly.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ModuleAssembly.java
new file mode 100644
index 0000000..988ab94
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ModuleAssembly.java
@@ -0,0 +1,242 @@
+/*
+ *  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.polygene.bootstrap;
+
+import java.util.function.Predicate;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.type.HasTypes;
+
+/**
+ * The ModuleAssembly is used to register any information about * what the module should contain, such as composites,
+ * entities and services.
+ * <p>
+ * Use the methods and the fluent API's to declare how the module should be constructed.
+ * </p>
+ */
+public interface ModuleAssembly
+{
+    /**
+     * Access the layer assembly for this module.
+     *
+     * @return The Layer containing this Module.
+     */
+    LayerAssembly layer();
+
+    /**
+     * Get an assembly for a particular Module. If this is called many times with the same names, then the same module
+     * is affected.
+     *
+     * @param layerName  The name of the Layer
+     * @param moduleName The name of the Module to retrieve or create.
+     *
+     * @return The ModuleAssembly for the Module.
+     */
+    ModuleAssembly module( String layerName, String moduleName );
+
+    /**
+     * Set the name of this module.
+     *
+     * @param name The name that this Module should have.
+     *
+     * @return This instance to support the fluid DSL of bootstrap.
+     */
+    ModuleAssembly setName( String name );
+
+    /**
+     * Access the currently set name for this module.
+     *
+     * @return The name of this Module.
+     */
+    String name();
+
+    ModuleAssembly setMetaInfo( Object info );
+
+    /**
+     * Set the module activators. Activators are executed in order around the
+     * Module activation and passivation.
+     *
+     * @param activators the module activators
+     *
+     * @return the assembly
+     */
+    @SuppressWarnings( { "unchecked", "varargs" } )
+    ModuleAssembly withActivators( Class<? extends Activator<Module>>... activators );
+
+    /**
+     * Declare a list of TransientComposites for this Module. Use the TransientDeclaration that is returned to
+     * declare further settings. Note that the TransientDeclaration works on all of the types specified.
+     *
+     * @param transientTypes The types that specifies the Transient types.
+     *
+     * @return An TransientDeclaration for the specified Transient types.
+     */
+    TransientDeclaration transients( Class<?>... transientTypes );
+
+    /**
+     * Given a Specification for TransientAssembly's, returns a TransientDeclaration that can
+     * be used to work with all of the assemblies matched by the specification.
+     *
+     * @param specification The Specification that specifies the TransientComposite types of interest.
+     *
+     * @return An TransientDeclaration for the specified TransientComposite types.
+     */
+    TransientDeclaration transients( Predicate<? super TransientAssembly> specification );
+
+    /**
+     * Declare a list of ValueComposites for this Module. Use the ValueDeclaration that is returned to
+     * declare further settings. Note that the ValueDeclaration works on all of the types specified.
+     *
+     * @param valueTypes The types that specifies the Value types.
+     *
+     * @return An ValueDeclaration for the specified Value types.
+     */
+    ValueDeclaration values( Class<?>... valueTypes );
+
+    /**
+     * Given a Specification for ValueAssembly's, returns a ValueDeclaration that can
+     * be used to work with all of the assemblies matched by the specification.
+     *
+     * @param specification The Specification that specifies the ValueComposite types of interest.
+     *
+     * @return An ValueDeclaration for the specified ValueComposite types.
+     */
+    ValueDeclaration values( Predicate<? super ValueAssembly> specification );
+
+    /**
+     * Declare a list of EntityComposites for this Module. Use the EntityDeclaration that is returned to
+     * declare further settings. Note that the EntityDeclaration works on all of the types specified.
+     *
+     * @param entityTypes The types that specifies the Entity types.
+     *
+     * @return An EntityDeclaration for the specified Entity types.
+     */
+    EntityDeclaration entities( Class<?>... entityTypes );
+
+    /**
+     * Given a Specification for EntityAssembly's, returns a EntityDeclaration that can
+     * be used to work with all of the assemblies matched by the specification.
+     *
+     * @param specification The Specification that specifies the EntityComposite types of interest.
+     *
+     * @return An EntityDeclaration for the specified EntityComposite types.
+     */
+    EntityDeclaration entities( Predicate<? super EntityAssembly> specification );
+
+    /**
+     * Declare a list of Configuration Composites for this Module. Use the ConfigurationDeclaration that is returned to
+     * declare further settings. Note that the ConfigurationDeclaration works on all of the types specified.
+     *
+     * @param configurationTypes The types that specifies the Configuration types.
+     *
+     * @return An ConfigurationDeclaration for the specified Configuration types.
+     */
+    ConfigurationDeclaration configurations( Class<?>... configurationTypes );
+
+    /**
+     * Given a Specification for Configuration, returns a ConfigurationDeclaration that can be used to work with all
+     * of the assemblies matched by the specification.
+     *
+     * @param specification The Specification that specifies the ConfigurationComposite types of interest.
+     *
+     * @return An ConfigurationDeclaration for the specified EntityComposite types.
+     */
+    ConfigurationDeclaration configurations( Predicate<HasTypes> specification );
+
+    /**
+     * Declare a list of object classes for this Module. Use the ObjectDeclaration that is returned to
+     * declare further settings. Note that the ObjectDeclaration works on all of the types specified.
+     *
+     * @param objectTypes The types that specifies the Object types.
+     *
+     * @return An ObjectDeclaration for the specified Object types.
+     *
+     * @throws AssemblyException on invalid assembly
+     */
+    ObjectDeclaration objects( Class<?>... objectTypes )
+        throws AssemblyException;
+
+    /**
+     * Given a Specification for ObjectAssembly's, returns a ObjectDeclaration that can
+     * be used to work with all of the assemblies matched by the specification.
+     *
+     * @param specification The Specification that specifies the Object types of interest.
+     *
+     * @return An ObjectDeclaration for the specified Object types.
+     */
+    ObjectDeclaration objects( Predicate<? super ObjectAssembly> specification );
+
+    /**
+     * Create a list of ServiceComposites for this Module. Use the ServiceDeclaration that is returned to
+     * declare further settings. This will always create new assemblies for the specified types, instead
+     * of potentially working on already declared types like the services(...) method.
+     *
+     * @param serviceTypes The types that specifies the Service types.
+     *
+     * @return An ServiceDeclaration for the specified Service types.
+     */
+    ServiceDeclaration addServices( Class<?>... serviceTypes );
+
+    /**
+     * Declare a list of ServiceComposites for this Module. Use the ServiceDeclaration that is returned to
+     * declare further settings. Note that the ServiceDeclaration works on all of the types specified.
+     *
+     * @param serviceTypes The types that specifies the Service types.
+     *
+     * @return An ServiceDeclaration for the specified Service types.
+     */
+    ServiceDeclaration services( Class<?>... serviceTypes );
+
+    /**
+     * Given a Specification for ServiceAssembly's, returns a ServiceDeclaration that can
+     * be used to work with all of the assemblies matched by the specification.
+     *
+     * @param specification The Specification that specifies the ServiceComposite types of interest.
+     *
+     * @return An ServiceDeclaration for the specified ServiceComposite types.
+     */
+    ServiceDeclaration services( Predicate<? super ServiceAssembly> specification );
+
+    /**
+     * Declare a list of imported services for this Module. Use the ImportedServiceDeclaration that is returned to
+     * declare further settings. Note that the ImportedServiceDeclaration works on all of the types specified.
+     *
+     * @param serviceTypes The types that specifies the Imported Service types.
+     *
+     * @return An ImportedServiceDeclaration for the specified Imported Service types.
+     */
+    ImportedServiceDeclaration importedServices( Class<?>... serviceTypes );
+
+    /**
+     * Given a Specification for ImportedServiceAssembly's, returns a ImportedServiceDeclaration that can
+     * be used to work with all of the assemblies matched by the specification.
+     *
+     * @param specification The Specification that specifies the Imported Service types of interest.
+     *
+     * @return An ImportedServiceDeclaration for the specified Imported Service types.
+     */
+    ImportedServiceDeclaration importedServices( Predicate<? super ImportedServiceAssembly> specification );
+
+    <T> MixinDeclaration<T> forMixin( Class<T> mixinType );
+
+    <ThrowableType extends Throwable> void visit( AssemblyVisitor<ThrowableType> visitor )
+        throws ThrowableType;
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ModuleName.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ModuleName.java
new file mode 100644
index 0000000..72ba9ce
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ModuleName.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.bootstrap;
+
+/**
+ * Set the name of the module
+ */
+public final class ModuleName
+    implements Assembler
+{
+    private final String name;
+
+    public ModuleName( String name )
+    {
+        this.name = name;
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.setName( name );
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/NamedAssociationDeclarations.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/NamedAssociationDeclarations.java
new file mode 100644
index 0000000..bc8a8ea
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/NamedAssociationDeclarations.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.bootstrap;
+
+import java.lang.reflect.AccessibleObject;
+import org.apache.polygene.api.common.MetaInfo;
+
+/**
+ * This provides declared {@link org.apache.polygene.api.association.NamedAssociation} information that the runtime can use.
+ */
+public interface NamedAssociationDeclarations
+{
+    MetaInfo metaInfoFor( AccessibleObject accessor );
+}
\ No newline at end of file
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ObjectAssembly.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ObjectAssembly.java
new file mode 100644
index 0000000..281fd6e
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ObjectAssembly.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.type.HasTypes;
+
+/**
+ * This represents the assembly information of a single object type in a Module.
+ */
+public interface ObjectAssembly
+    extends HasTypes
+{
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ObjectDeclaration.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ObjectDeclaration.java
new file mode 100644
index 0000000..3587443
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ObjectDeclaration.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.common.Visibility;
+
+/**
+ * Fluent API for declaring objects.Instances
+ * of this API are acquired by calling {@link ModuleAssembly#objects(Class[])}.
+ */
+public interface ObjectDeclaration
+{
+    ObjectDeclaration setMetaInfo( Object info );
+
+    ObjectDeclaration visibleIn( Visibility visibility )
+        throws IllegalStateException;
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/PolygeneRuntime.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/PolygeneRuntime.java
new file mode 100644
index 0000000..c5c5386
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/PolygeneRuntime.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.spi.PolygeneSPI;
+
+/**
+ * This interface has to be implemented by Polygene runtimes.
+ */
+public interface PolygeneRuntime
+{
+    ApplicationAssemblyFactory applicationAssemblyFactory();
+
+    ApplicationModelFactory applicationModelFactory();
+
+    PolygeneAPI api();
+
+    PolygeneSPI spi();
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/RuntimeFactory.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/RuntimeFactory.java
new file mode 100644
index 0000000..6aec6f9
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/RuntimeFactory.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.bootstrap;
+
+/**
+ * Polygene runtime factory.
+ */
+public interface RuntimeFactory
+{
+    PolygeneRuntime createRuntime();
+
+    /**
+     * Standalone application Polygene runtime factory.
+     */
+    final class StandaloneApplicationRuntimeFactory
+        implements RuntimeFactory
+    {
+        @Override
+        public PolygeneRuntime createRuntime()
+        {
+            ClassLoader loader = getClass().getClassLoader();
+            try
+            {
+                Class<? extends PolygeneRuntime> runtimeClass = loadRuntimeClass( loader );
+                return runtimeClass.newInstance();
+            }
+            catch( ClassNotFoundException e )
+            {
+                System.err.println( "Polygene Runtime jar is not present in the classpath." );
+            }
+            catch( InstantiationException | IllegalAccessException e )
+            {
+                System.err.println( "Invalid Polygene Runtime class. If you are providing your own Polygene Runtime, please " +
+                                    "contact dev@polygene.apache.org mailing list for assistance." );
+            }
+            return null;
+        }
+
+        @SuppressWarnings( { "unchecked" } )
+        private Class<? extends PolygeneRuntime> loadRuntimeClass( ClassLoader loader )
+            throws ClassNotFoundException
+        {
+            return (Class<? extends PolygeneRuntime>) loader.loadClass( "org.apache.polygene.runtime.PolygeneRuntimeImpl" );
+        }
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ServiceAssembly.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ServiceAssembly.java
new file mode 100644
index 0000000..5a889de
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ServiceAssembly.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.identity.Identifiable;
+import org.apache.polygene.api.type.HasTypes;
+
+/**
+ * This represents the assembly information of a single ServiceComposite in a Module.
+ */
+public interface ServiceAssembly extends HasTypes, Identifiable
+{
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ServiceDeclaration.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ServiceDeclaration.java
new file mode 100644
index 0000000..8dad610
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ServiceDeclaration.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.common.Visibility;
+
+/**
+ * Fluent API for declaring services hosted in Polygene. Instances
+ * of this API are acquired by calling {@link ModuleAssembly#services(Class[])}.
+ */
+public interface ServiceDeclaration
+{
+    ServiceDeclaration setMetaInfo( Object serviceAttribute );
+
+    ServiceDeclaration visibleIn( Visibility visibility );
+
+    ServiceDeclaration withConcerns( Class<?>... concerns );
+
+    ServiceDeclaration withSideEffects( Class<?>... sideEffects );
+
+    ServiceDeclaration withMixins( Class<?>... mixins );
+
+    ServiceDeclaration withTypes( Class<?>... types );
+
+    ServiceDeclaration identifiedBy( String identity );
+
+    ServiceDeclaration taggedWith( String... tags );
+
+    ServiceDeclaration instantiateOnStartup();
+
+    /**
+     * Set the service activators. Activators are executed in order around the
+     * ServiceReference activation and passivation.
+     *
+     * @param activators the service activators
+     * @return the assembly
+     */    
+    @SuppressWarnings( { "unchecked","varargs" } )
+    ServiceDeclaration withActivators( Class<? extends Activator<?>>... activators );
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/SingletonAssembler.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/SingletonAssembler.java
new file mode 100644
index 0000000..01673f8
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/SingletonAssembler.java
@@ -0,0 +1,183 @@
+/*
+ *  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.polygene.bootstrap;
+
+import java.util.function.Consumer;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+/**
+ * Base class for Assembler that creates an Application
+ * with one Layer and one Module. Create a subclass of this
+ * and implement the {@link Assembler#assemble(ModuleAssembly)} method.
+ * Once the SingletonAssembler is instantiated it will have created and activated
+ * an Application which can be accessed from {@link org.apache.polygene.bootstrap.SingletonAssembler#application()}.
+ * You can also easily access any resources specific for the single Module, such as the TransientBuilderFactory.
+ */
+public class SingletonAssembler
+    implements Assembler
+{
+    private final Energy4Java polygene;
+    private final Application applicationInstance;
+    private final Module moduleInstance;
+    private Consumer<ModuleAssembly> assemble;
+
+    /**
+     * Creates a Polygene Runtime instance containing one Layer with one Module.
+     * The Layer will be named "Layer 1" and the Module will be named "Module 1". It is possible to add
+     * additional layers and modules via the Assembler interface that must be implemented in the subclass of this
+     * class.
+     *
+     * @param assemble An Assembler lambda containing the module assembly.
+     * @throws AssemblyException   Either if the model can not be created from the disk, or some inconsistency in
+     *                             the programming model makes it impossible to create it.
+     * @throws ActivationException If the automatic {@code activate()} method is throwing this Exception..
+     */
+    public SingletonAssembler( Consumer<ModuleAssembly> assemble )
+        throws ActivationException
+    {
+        this.assemble = assemble;
+        polygene = new Energy4Java();
+        applicationInstance = createApplicationInstance();
+        activateApplication();
+        moduleInstance = applicationInstance.findModule( layerName(), moduleName() );
+    }
+
+    /**
+     * Creates a Polygene Runtime instance containing one Layer with one Module.
+     * The Layer will be named "Layer 1" and the Module will be named "Module 1". It is possible to add
+     * additional layers and modules via the Assembler interface that must be implemented in the subclass of this
+     * class.
+     *
+     * @throws AssemblyException   Either if the model can not be created from the disk, or some inconsistency in
+     *                             the programming model makes it impossible to create it.
+     * @throws ActivationException If the automatic {@code activate()} method is throwing this Exception..
+     */
+    public SingletonAssembler()
+        throws AssemblyException, ActivationException
+    {
+// START SNIPPET: actual
+        polygene = new Energy4Java();
+        applicationInstance = createApplicationInstance();
+        activateApplication();
+// END SNIPPET: actual
+        moduleInstance = applicationInstance.findModule( layerName(), moduleName() );
+    }
+
+    // START SNIPPET: actual
+    private Application createApplicationInstance()
+    {
+        return polygene.newApplication(
+            applicationFactory -> applicationFactory.newApplicationAssembly( SingletonAssembler.this )
+        );
+    }
+
+    private void activateApplication()
+        throws ActivationException
+    {
+        try
+        {
+            beforeActivation( applicationInstance );
+            applicationInstance.activate();
+        }
+        catch( Exception e )
+        {
+            if( e instanceof ActivationException )
+            {
+                throw ( (ActivationException) e );
+            }
+            throw new ActivationException( "Could not activate application", e );
+        }
+    }
+// END SNIPPET: actual
+
+    public final PolygeneAPI runtime()
+    {
+        return polygene.spi();
+    }
+
+    public final Application application()
+    {
+        return applicationInstance;
+    }
+
+    public final Module module()
+    {
+        return moduleInstance;
+    }
+
+    protected String layerName()
+    {
+        return "Layer 1";
+    }
+
+    protected String moduleName()
+    {
+        return "Module 1";
+    }
+
+    protected void beforeActivation( Application application )
+        throws Exception
+    {
+    }
+
+    protected UnitOfWorkFactory unitOfWorkFactory()
+    {
+        return moduleInstance.unitOfWorkFactory();
+    }
+
+    protected ServiceFinder serviceFinder()
+    {
+        return moduleInstance.serviceFinder();
+    }
+
+    protected ValueBuilderFactory valueBuilderFactory()
+    {
+        return moduleInstance.valueBuilderFactory();
+    }
+
+    protected TransientBuilderFactory transientBuilderFactory()
+    {
+        return moduleInstance.transientBuilderFactory();
+    }
+
+    protected ObjectFactory objectFactory()
+    {
+        return moduleInstance.objectFactory();
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        if( assemble != null )
+        {
+            assemble.accept( module );
+        }
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/StateDeclarations.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/StateDeclarations.java
new file mode 100644
index 0000000..79d2834
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/StateDeclarations.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.bootstrap;
+
+import java.lang.reflect.AccessibleObject;
+import org.apache.polygene.api.common.MetaInfo;
+
+/**
+ * This provides declared {@link org.apache.polygene.api.property.Property} information that the runtime can use.
+ */
+public interface StateDeclarations
+{
+    MetaInfo metaInfoFor( AccessibleObject accessor );
+
+    Object initialValueOf( AccessibleObject accessor );
+
+    boolean useDefaults( AccessibleObject accessor );
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/TransientAssembly.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/TransientAssembly.java
new file mode 100644
index 0000000..42aab6d
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/TransientAssembly.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.type.HasTypes;
+
+/**
+ * This represents the assembly information of a single TransientComposite in a Module.
+ */
+public interface TransientAssembly
+    extends HasTypes
+{
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/TransientDeclaration.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/TransientDeclaration.java
new file mode 100644
index 0000000..04a1942
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/TransientDeclaration.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.common.Visibility;
+
+/**
+ * Fluent API for declaring TransientComposites. Instances
+ * of this API are acquired by calling {@link ModuleAssembly#transients(Class[])}.
+ */
+public interface TransientDeclaration
+{
+    TransientDeclaration setMetaInfo( Object info );
+
+    TransientDeclaration visibleIn( Visibility visibility );
+
+    TransientDeclaration withConcerns( Class<?>... concerns );
+
+    TransientDeclaration withSideEffects( Class<?>... sideEffects );
+
+    TransientDeclaration withMixins( Class<?>... mixins );
+
+    TransientDeclaration withTypes( Class<?>... roles );
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ValueAssembly.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ValueAssembly.java
new file mode 100644
index 0000000..83352d0
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ValueAssembly.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.type.HasTypes;
+
+/**
+ * This represents the assembly information of a single ValueComposite in a Module.
+ */
+public interface ValueAssembly
+    extends HasTypes
+{
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ValueDeclaration.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ValueDeclaration.java
new file mode 100644
index 0000000..415335d
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/ValueDeclaration.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.common.Visibility;
+
+/**
+ * Fluent API for declaring values
+ */
+public interface ValueDeclaration
+{
+    ValueDeclaration setMetaInfo( Object info );
+
+    ValueDeclaration visibleIn( Visibility visibility );
+
+    ValueDeclaration withConcerns( Class<?>... concerns );
+
+    ValueDeclaration withSideEffects( Class<?>... sideEffects );
+
+    ValueDeclaration withMixins( Class<?>... mixins );
+
+    ValueDeclaration withTypes( Class<?>... roles );
+}
\ No newline at end of file
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/builder/ApplicationBuilder.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/builder/ApplicationBuilder.java
new file mode 100644
index 0000000..6159686
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/builder/ApplicationBuilder.java
@@ -0,0 +1,300 @@
+/*
+ *  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.polygene.bootstrap.builder;
+
+import java.io.InputStream;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonValue;
+import org.apache.polygene.api.activation.ActivationEventListener;
+import org.apache.polygene.api.activation.ActivationEventListenerRegistration;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.ApplicationPassivationThread;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.LayerAssembly;
+
+/**
+ * Application Builder.
+ */
+public class ApplicationBuilder
+    implements ActivationEventListenerRegistration
+{
+    private final String applicationName;
+    private String applicationVersion;
+    private Application.Mode applicationMode;
+    private final List<Object> metaInfos = new ArrayList<>();
+    private boolean passivationShutdownHook;
+    private final Map<String, LayerDeclaration> layers = new HashMap<>();
+    private final List<ActivationEventListener> activationListeners = new ArrayList<>();
+
+    public ApplicationBuilder( String applicationName )
+    {
+        this.applicationName = applicationName;
+    }
+
+    public ApplicationBuilder version( String version )
+    {
+        applicationVersion = version;
+        return this;
+    }
+
+    public ApplicationBuilder mode( Application.Mode mode )
+    {
+        applicationMode = mode;
+        return this;
+    }
+
+    public ApplicationBuilder metaInfo( Object... metaInfos )
+    {
+        Collections.addAll( this.metaInfos, metaInfos );
+        return this;
+    }
+
+    /**
+     * Register a JVM shutdown hook that passivate the Application.
+     *
+     * The hook is registered after activating the Application and before {@link #afterActivation()}.
+     *
+     * @return This builder
+     */
+    public ApplicationBuilder withPassivationShutdownHook()
+    {
+        this.passivationShutdownHook = true;
+        return this;
+    }
+
+    /**
+     * Create and activate a new Application.
+     * @return Activated Application
+     * @throws AssemblyException if the assembly failed
+     * @throws ActivationException if the activation failed
+     */
+    public Application newApplication()
+        throws AssemblyException, ActivationException
+    {
+        Energy4Java polygene = new Energy4Java();
+        ApplicationDescriptor model = polygene.newApplicationModel( new ApplicationAssembler()
+        {
+            @Override
+            public ApplicationAssembly assemble( ApplicationAssemblyFactory factory )
+                throws AssemblyException
+            {
+                ApplicationAssembly assembly = factory.newApplicationAssembly();
+                assembly.setName( applicationName );
+                if( applicationVersion != null )
+                {
+                    assembly.setVersion( applicationVersion );
+                }
+                if( applicationMode != null )
+                {
+                    assembly.setMode( applicationMode );
+                }
+                for( Object metaInfo : metaInfos )
+                {
+                    assembly.setMetaInfo( metaInfo );
+                }
+                HashMap<String, LayerAssembly> createdLayers = new HashMap<>();
+                for( Map.Entry<String, LayerDeclaration> entry : layers.entrySet() )
+                {
+                    LayerAssembly layer = entry.getValue().createLayer( assembly );
+                    createdLayers.put( entry.getKey(), layer );
+                }
+                for( LayerDeclaration layer : layers.values() )
+                {
+                    layer.initialize( createdLayers );
+                }
+                return assembly;
+            }
+        } );
+        Application application = model.newInstance( polygene.api() );
+        for( ActivationEventListener activationListener : activationListeners )
+        {
+            application.registerActivationEventListener( activationListener );
+        }
+        beforeActivation();
+        application.activate();
+        if( passivationShutdownHook )
+        {
+            Runtime.getRuntime().addShutdownHook( new ApplicationPassivationThread( application ) );
+        }
+        afterActivation();
+        return application;
+    }
+
+    /**
+     * Called before application activation.
+     */
+    protected void beforeActivation()
+    {
+    }
+
+    /**
+     * Called after application activation.
+     */
+    protected void afterActivation()
+    {
+    }
+
+    @Override
+    public void registerActivationEventListener( ActivationEventListener listener )
+    {
+        activationListeners.add( listener );
+    }
+
+    @Override
+    public void deregisterActivationEventListener( ActivationEventListener listener )
+    {
+        activationListeners.remove( listener );
+    }
+
+    /**
+     * Declare Layer.
+     * @param layerName Name of the Layer
+     * @return Layer declaration for the given name, new if did not already exists
+     */
+    public LayerDeclaration withLayer( String layerName )
+    {
+        LayerDeclaration layerDeclaration = layers.get( layerName );
+        if( layerDeclaration != null )
+        {
+            return layerDeclaration;
+        }
+        layerDeclaration = new LayerDeclaration( layerName );
+        layers.put( layerName, layerDeclaration );
+        return layerDeclaration;
+    }
+
+    /**
+     * Load an ApplicationBuilder from a JSON String.
+     * @param json JSON String
+     * @return Application Builder loaded from JSON
+     * @throws AssemblyException if unable to declare the assembly
+     */
+    public static ApplicationBuilder fromJson( String json )
+    {
+        JsonObject root = Json.createReader( new StringReader( json ) ).readObject();
+        return fromJson( root );
+    }
+
+    /**
+     * Load an ApplicationBuilder from a JSON InputStream.
+     * @param json JSON input
+     * @return Application Builder loaded from JSON
+     * @throws AssemblyException if unable to declare the assembly
+     */
+    public static ApplicationBuilder fromJson( InputStream json )
+        throws AssemblyException
+    {
+        JsonObject root = Json.createReader( json ).readObject();
+        return fromJson( root );
+    }
+
+    /**
+     * Load an ApplicationBuilder from a JSONObject.
+     * @param root JSON object
+     * @return Application Builder loaded from JSON
+     * @throws AssemblyException if unable to declare the assembly
+     */
+    public static ApplicationBuilder fromJson( JsonObject root )
+        throws AssemblyException
+    {
+        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 AssemblyException if probelms in the Assemblers provided in the JSON document.
+     */
+    protected void configureWithJson( JsonObject root )
+        throws AssemblyException
+    {
+        JsonValue optLayers = root.get( "layers" );
+        if( optLayers != null && optLayers.getValueType() == JsonValue.ValueType.ARRAY )
+        {
+            JsonArray layers = (JsonArray) optLayers;
+            for( int i = 0; i < layers.size(); i++ )
+            {
+                JsonObject layerObject = layers.getJsonObject( i );
+                String layerName = layerObject.getString( "name" );
+                LayerDeclaration layerDeclaration = withLayer( layerName );
+                JsonValue optUsing = layerObject.get( "uses" );
+                if( optUsing != null && optUsing.getValueType() == JsonValue.ValueType.ARRAY )
+                {
+                    JsonArray using = (JsonArray) optUsing;
+                    for( int j = 0; j < using.size(); j++ )
+                    {
+                        layerDeclaration.using( using.getString( j ) );
+                    }
+                }
+                JsonValue optModules = layerObject.get( "modules" );
+                if( optModules != null && optModules.getValueType() == JsonValue.ValueType.ARRAY )
+                {
+                    JsonArray modules = (JsonArray) optModules;
+                    for( int k = 0; k < modules.size(); k++ )
+                    {
+                        JsonObject moduleObject = modules.getJsonObject( k );
+                        String moduleName = moduleObject.getString( "name" );
+                        ModuleDeclaration moduleDeclaration = layerDeclaration.withModule( moduleName );
+                        JsonValue optAssemblers = moduleObject.get( "assemblers" );
+                        if( optAssemblers != null && optAssemblers.getValueType() == JsonValue.ValueType.ARRAY )
+                        {
+                            JsonArray assemblers = (JsonArray) optAssemblers;
+                            for( int m = 0; m < assemblers.size(); m++ )
+                            {
+                                String string = assemblers.getString( m );
+                                moduleDeclaration.withAssembler( string );
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * {@literal main} method that read JSON from STDIN.
+     * <p>Passivation exceptions are written to STDERR if any.</p>
+     * @param args Unused
+     * @throws AssemblyException if the assembly failed
+     * @throws ActivationException if the activation failed
+     */
+    public static void main( String[] args )
+        throws ActivationException, AssemblyException
+    {
+        fromJson( System.in ).withPassivationShutdownHook().newApplication();
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/builder/LayerDeclaration.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/builder/LayerDeclaration.java
new file mode 100644
index 0000000..2bc14f0
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/builder/LayerDeclaration.java
@@ -0,0 +1,111 @@
+/*
+ *  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.polygene.bootstrap.builder;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+/**
+ * Provides declared {@link org.apache.polygene.api.structure.Layer} information that the {@link ApplicationBuilder} can use.
+ */
+public class LayerDeclaration
+{
+    private final String layerName;
+    private final List<String> using = new ArrayList<>();
+    private final Map<String, ModuleDeclaration> modules = new HashMap<>();
+    private LayerAssembly layer;
+
+    LayerDeclaration( String layerName )
+    {
+        this.layerName = layerName;
+    }
+
+    /**
+     * Declare using layer.
+     * @param layerName Used layer name
+     * @return This Layer declaration
+     */
+    public LayerDeclaration using( String layerName )
+    {
+        this.using.add( layerName );
+        return this;
+    }
+
+    /**
+     * Declare using layers.
+     * @param layerNames Used layers names
+     * @return This Layer declaration
+     */
+    public LayerDeclaration using( Iterable<String> layerNames )
+    {
+        StreamSupport.stream( layerNames.spliterator(), false )
+                     .forEach( using::add );
+        return this;
+    }
+
+    /**
+     * Declare Module.
+     * @param moduleName Name of the Module
+     * @return Module declaration for the given name, new if did not already exists
+     */
+    public ModuleDeclaration withModule( String moduleName )
+    {
+        ModuleDeclaration module = modules.get( moduleName );
+        if( module != null )
+        {
+            return module;
+        }
+        module = new ModuleDeclaration( moduleName );
+        modules.put( moduleName, module );
+        return module;
+    }
+
+    LayerAssembly createLayer( ApplicationAssembly application )
+    {
+        layer = application.layer( layerName );
+        layer.setName( layerName );
+        for( ModuleDeclaration module : modules.values() )
+        {
+            ModuleAssembly assembly = module.createModule( layer );
+        }
+        return layer;
+    }
+
+    void initialize( HashMap<String, LayerAssembly> createdLayers )
+        throws AssemblyException
+    {
+        for( String uses : using )
+        {
+            LayerAssembly usedLayer = createdLayers.get( uses );
+            layer.uses( usedLayer );
+        }
+        for( ModuleDeclaration module : modules.values() )
+        {
+            module.initialize();
+        }
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/builder/ModuleDeclaration.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/builder/ModuleDeclaration.java
new file mode 100644
index 0000000..fb20c26
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/builder/ModuleDeclaration.java
@@ -0,0 +1,168 @@
+/*
+ *  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.polygene.bootstrap.builder;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.polygene.api.util.Classes.isAssignableFrom;
+
+/**
+ * Provides declared {@link org.apache.polygene.api.structure.Module} information that the {@link ApplicationBuilder} can use.
+ */
+public class ModuleDeclaration
+{
+    private final String moduleName;
+    private final List<Assembler> assemblers = new ArrayList<>();
+    private ModuleAssembly module;
+
+    public ModuleDeclaration( String moduleName )
+    {
+        this.moduleName = moduleName;
+    }
+
+    /**
+     * Declare Assembler.
+     * @param assembler Assembler instance
+     * @return This Module declaration
+     */
+    public ModuleDeclaration withAssembler( Assembler assembler )
+    {
+        assemblers.add( assembler );
+        return this;
+    }
+
+    /**
+     * Declare Assembler.
+     * @param classname Assembler class name
+     * @return This Module declaration
+     * @throws AssemblyException if unable to load class, not an Assembler or unable to instanciate
+     */
+    public ModuleDeclaration withAssembler( String classname )
+        throws AssemblyException
+    {
+        Class<? extends Assembler> clazz = loadClass( classname );
+        return withAssembler( clazz );
+    }
+
+    /**
+     * Declare Assembler.
+     * @param assemblerClass Assembler class
+     * @return This Module declaration
+     * @throws AssemblyException not an Assembler or if unable to instanciate
+     */
+    public ModuleDeclaration withAssembler( Class<?> assemblerClass )
+        throws AssemblyException
+    {
+        Assembler assembler = createAssemblerInstance( assemblerClass );
+        assemblers.add( assembler );
+        return this;
+    }
+
+    /**
+     * Declare Assemblers.
+     * <p>Declare several Assemblers from an Iterable of Class objects.</p>
+     * <p>Typically used along {@link org.apache.polygene.bootstrap.ClassScanner}.</p>
+     * @param assemblerClasses Assembler classes
+     * @return This Module declaration
+     * @throws AssemblyException if one of the Class is not an Assembler or unable to instantiate
+     */
+    public ModuleDeclaration withAssemblers( Iterable<Class<?>> assemblerClasses )
+        throws AssemblyException
+    {
+        List<Class<?>> notAssemblers = StreamSupport.stream( assemblerClasses.spliterator(), false )
+                                                    .filter( isAssignableFrom( Assembler.class ).negate() )
+                                                    .collect( toList() );
+        if( !notAssemblers.isEmpty() )
+        {
+            throw new AssemblyException(
+                "Classes " + notAssemblers + " are not implementing " + Assembler.class.getName()
+            );
+        }
+        for( Class<?> assemblerClass : assemblerClasses )
+        {
+            withAssembler( assemblerClass );
+        }
+        return this;
+    }
+
+    ModuleAssembly createModule( LayerAssembly layer )
+    {
+        module = layer.module( moduleName );
+        return module;
+    }
+
+    void initialize()
+        throws AssemblyException
+    {
+        for( Assembler assembler : assemblers )
+        {
+            assembler.assemble( module );
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private Class<? extends Assembler> loadClass( String classname )
+        throws AssemblyException
+    {
+        Class<?> clazz;
+        try
+        {
+            clazz = getClass().getClassLoader().loadClass( classname );
+        }
+        catch( Exception e )
+        {
+            throw new AssemblyException( "Unable to load class " + classname, e );
+        }
+        if( !Assembler.class.isAssignableFrom( clazz ) )
+        {
+            throw new AssemblyException(
+                "Class " + classname + " is not implementing " + Assembler.class.getName()
+            );
+        }
+        //noinspection unchecked
+        return (Class<? extends Assembler>) clazz;
+    }
+
+    private Assembler createAssemblerInstance( Class<?> assemblerClass )
+        throws AssemblyException
+    {
+        if( !Assembler.class.isAssignableFrom( assemblerClass ) )
+        {
+            throw new AssemblyException(
+                "Class " + assemblerClass + " is not implementing " + Assembler.class.getName()
+            );
+        }
+        try
+        {
+            return (Assembler) assemblerClass.newInstance();
+        }
+        catch( Exception e )
+        {
+            throw new AssemblyException( "Unable to instantiate " + assemblerClass, e );
+        }
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/builder/package.html b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/builder/package.html
new file mode 100644
index 0000000..6c1ff92
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/builder/package.html
@@ -0,0 +1,28 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Application Builder.</h2>
+        <p>
+            Generic ApplicationBuilder, which simplifies the creation of Application Structure, either by a fluid DSL
+            or from a JSON file.
+        </p>
+    </body>
+</html>
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/identity/DefaultIdentityGeneratorAssembler.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/identity/DefaultIdentityGeneratorAssembler.java
new file mode 100644
index 0000000..e50ec45
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/identity/DefaultIdentityGeneratorAssembler.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.bootstrap.identity;
+
+import org.apache.polygene.api.identity.IdentityGenerator;
+import org.apache.polygene.api.identity.UuidGeneratorMixin;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+public class DefaultIdentityGeneratorAssembler
+    implements Assembler
+{
+
+    @Override
+    public void assemble(ModuleAssembly module)
+            throws AssemblyException
+    {
+        module.services(IdentityGenerator.class).withMixins(UuidGeneratorMixin.class);
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/IllegalLayerAssemblerException.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/IllegalLayerAssemblerException.java
new file mode 100644
index 0000000..9c843d1
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/IllegalLayerAssemblerException.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.bootstrap.layered;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+
+public class IllegalLayerAssemblerException extends AssemblyException
+{
+    public IllegalLayerAssemblerException( String message )
+    {
+        super( message );
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/LayerAssembler.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/LayerAssembler.java
new file mode 100644
index 0000000..4e60170
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/LayerAssembler.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.bootstrap.layered;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+
+@FunctionalInterface
+public interface LayerAssembler
+{
+    LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException;
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/LayeredApplicationAssembler.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/LayeredApplicationAssembler.java
new file mode 100644
index 0000000..d5edba0
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/LayeredApplicationAssembler.java
@@ -0,0 +1,297 @@
+/*
+ *  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.polygene.bootstrap.layered;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.LayerAssembly;
+
+public abstract class LayeredApplicationAssembler
+    implements ApplicationAssembler
+{
+    protected final Energy4Java polygene;
+    protected final String name;
+    protected final String version;
+
+    private final Application.Mode mode;
+    private final HashMap<Class<? extends LayerAssembler>, LayerAssembler> assemblers = new HashMap<>();
+
+    private ApplicationAssembly assembly;
+    protected ApplicationDescriptor model;
+    protected Application application;
+
+    public LayeredApplicationAssembler( String name, String version, Application.Mode mode )
+        throws AssemblyException
+    {
+        this.name = name;
+        this.version = version;
+        this.mode = mode;
+        polygene = new Energy4Java();
+    }
+
+    public void initialize()
+        throws AssemblyException
+    {
+        model = polygene.newApplicationModel( this );
+        onModelCreated( model );
+        instantiateApplication( polygene, model );
+    }
+
+    public ApplicationAssembly assembly()
+    {
+        return assembly;
+    }
+
+    /**
+     * This method is called from the <code>initialize</code> method to instantiate the Polygene application from the
+     * application model.
+     *
+     * <p>
+     * The default implementation simply calls;
+     * </p>
+     * <pre><code>
+     *   application = model.newInstance( polygene.spi() );
+     * </code></pre>
+     *
+     * @param polygene  The Polygene runtime engine.
+     * @param model The application model descriptor.
+     */
+    protected void instantiateApplication( Energy4Java polygene, ApplicationDescriptor model )
+    {
+        application = model.newInstance( polygene.spi() );
+    }
+
+    /**
+     * This method is called after the Application Model has been created, before the instantiation of the Polygene
+     * 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 The model that has just been created.
+     */
+    protected void onModelCreated( ApplicationDescriptor model )
+    {
+    }
+
+    public ApplicationDescriptor model()
+    {
+        return 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 = instantiateLayerAssembler( layerAssemblerClass, layer );
+            assemblers.put( layerAssemblerClass, layerAssembler );
+            assembleLayer( layerAssembler, layer );
+            return layer;
+        }
+        catch( Exception e )
+        {
+            throw new IllegalArgumentException( "Unable to instantiate layer with " + layerAssemblerClass.getSimpleName(), e );
+        }
+    }
+
+    protected void assembleLayer( LayerAssembler layerAssembler, LayerAssembly layer )
+        throws AssemblyException
+    {
+        layerAssembler.assemble( layer );
+    }
+
+    protected <T extends LayerAssembler> LayerAssembler instantiateLayerAssembler( Class<T> layerAssemblerClass,
+                                                                                   LayerAssembly layer
+    )
+        throws InstantiationException, IllegalAccessException, InvocationTargetException, IllegalLayerAssemblerException
+    {
+        LayerAssembler assembler = createWithFactoryMethod( layerAssemblerClass, layer );
+        if( assembler != null )
+        {
+            return assembler;
+        }
+        assembler = createWithConstructor( layerAssemblerClass, layer );
+        if( assembler != null )
+        {
+            return assembler;
+        }
+        throw new IllegalLayerAssemblerException( "No matching factory method nor constructor found in " + layerAssemblerClass );
+    }
+
+    private LayerAssembler createWithFactoryMethod( Class<? extends LayerAssembler> layerAssemblerClass,
+                                                    LayerAssembly layer
+    )
+        throws InvocationTargetException, IllegalAccessException
+    {
+        try
+        {
+            Method factoryMethod = layerAssemblerClass.getDeclaredMethod( "create", LayerAssembly.class );
+            factoryMethod.setAccessible( true );
+            int modifiers = factoryMethod.getModifiers();
+            if( Modifier.isStatic( modifiers ) && LayerAssembler.class.isAssignableFrom( factoryMethod.getReturnType() ) )
+            {
+                return (LayerAssembler) factoryMethod.invoke( null, layer );
+            }
+        }
+        catch( NoSuchMethodException e )
+        {
+            try
+            {
+                Method factoryMethod = layerAssemblerClass.getDeclaredMethod( "create" );
+                factoryMethod.setAccessible( true );
+                int modifiers = factoryMethod.getModifiers();
+                if( Modifier.isStatic( modifiers ) && LayerAssembler.class.isAssignableFrom( factoryMethod.getReturnType() ) )
+                {
+                    return (LayerAssembler) factoryMethod.invoke( null );
+                }
+            }
+            catch( NoSuchMethodException e1 )
+            {
+            }
+        }
+        return null;
+    }
+
+    private LayerAssembler createWithConstructor( Class<? extends LayerAssembler> layerAssemblerClass,
+                                                  LayerAssembly assembly
+    )
+        throws IllegalAccessException, InvocationTargetException, InstantiationException
+    {
+        try
+        {
+            Constructor<? extends LayerAssembler> constructor = layerAssemblerClass.getConstructor( LayerAssembly.class );
+            if( constructor != null )
+            {
+                constructor.setAccessible( true );
+                return constructor.newInstance( assembly );
+            }
+        }
+        catch( NoSuchMethodException e )
+        {
+            try
+            {
+                Constructor<? extends LayerAssembler> constructor = layerAssemblerClass.getDeclaredConstructor();
+                if( constructor != null )
+                {
+                    constructor.setAccessible( true );
+                    System.out.println(constructor);
+                    return constructor.newInstance();
+                }
+            }
+            catch( NoSuchMethodException e1 )
+            {
+                return null;
+            }
+        }
+        return null;
+    }
+
+    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 <code>assemble</code> method to assemble the layers in the application.
+     *
+     * <p>
+     * This method must be implemented, and is typically a list of LayerAssembler instantiations, followed
+     * by {@link LayerAssembly#uses(LayerAssembly...)} declarations.
+     * </p>
+     *
+     * @param assembly Application assembly
+     * @throws AssemblyException on invalid assembly
+     */
+    protected abstract void assembleLayers( ApplicationAssembly assembly )
+        throws AssemblyException;
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/LayeredLayerAssembler.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/LayeredLayerAssembler.java
new file mode 100644
index 0000000..9783de5
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/LayeredLayerAssembler.java
@@ -0,0 +1,90 @@
+/*
+ *  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.polygene.bootstrap.layered;
+
+import java.lang.reflect.Constructor;
+import java.util.HashMap;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.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> moduleAssemblerClass )
+    {
+        try
+        {
+            ModuleAssembler moduleAssembler = instantiateAssembler( layer, moduleAssemblerClass );
+            String moduleName = createModuleName( moduleAssemblerClass );
+            LayeredApplicationAssembler.setNameIfPresent( moduleAssemblerClass, moduleName );
+            ModuleAssembly module = layer.module( moduleName );
+            assemblers.put( moduleAssemblerClass, 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 " + moduleAssemblerClass.getSimpleName(), e );
+        }
+    }
+
+    protected String createModuleName( Class<? extends ModuleAssembler> modulerAssemblerClass )
+    {
+        String moduleName = modulerAssemblerClass.getSimpleName();
+        if( moduleName.endsWith( "Module" ) )
+        {
+            moduleName = moduleName.substring( 0, moduleName.length() - 6 ) + " Module";
+        }
+        return moduleName;
+    }
+
+    protected ModuleAssembler instantiateAssembler( LayerAssembly layer,
+                                                  Class<? extends ModuleAssembler> modulerAssemblerClass
+    )
+        throws InstantiationException, IllegalAccessException, java.lang.reflect.InvocationTargetException, NoSuchMethodException
+    {
+        ModuleAssembler moduleAssembler;
+        try
+        {
+            Constructor<? extends ModuleAssembler> assemblyConstructor = modulerAssemblerClass.getDeclaredConstructor( ModuleAssembly.class );
+            assemblyConstructor.setAccessible( true );
+            moduleAssembler = assemblyConstructor.newInstance( layer );
+        }
+        catch( NoSuchMethodException e )
+        {
+            Constructor<? extends ModuleAssembler> assemblyConstructor = modulerAssemblerClass.getDeclaredConstructor();
+            assemblyConstructor.setAccessible( true );
+            moduleAssembler = assemblyConstructor.newInstance();
+        }
+        return moduleAssembler;
+    }
+
+    @SuppressWarnings( "unchecked" )
+    protected <T extends ModuleAssembler> T assemblerOf( Class<T> moduleAssemblerType )
+    {
+        return (T) assemblers.get( moduleAssemblerType );
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/ModuleAssembler.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/ModuleAssembler.java
new file mode 100644
index 0000000..e04321e
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/ModuleAssembler.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.bootstrap.layered;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+@FunctionalInterface
+public interface ModuleAssembler
+{
+    ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException;
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/package.html b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/package.html
new file mode 100644
index 0000000..0b8300b
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/layered/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Layered Assembly.</h2>
+    </body>
+</html>
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/package.html b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/package.html
new file mode 100644
index 0000000..7c867b8
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Assembly and Bootstrap API.</h2>
+    </body>
+</html>
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/serialization/DefaultSerializationAssembler.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/serialization/DefaultSerializationAssembler.java
new file mode 100644
index 0000000..db9d0a6
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/serialization/DefaultSerializationAssembler.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.bootstrap.serialization;
+
+import org.apache.polygene.api.serialization.Converters;
+import org.apache.polygene.api.serialization.Deserializer;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonAdapters;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonSerialization;
+import org.apache.polygene.spi.serialization.JsonDeserializer;
+import org.apache.polygene.spi.serialization.JsonSerialization;
+import org.apache.polygene.spi.serialization.JsonSerializer;
+
+public class DefaultSerializationAssembler
+    implements Assembler
+{
+    @Override
+    public void assemble( ModuleAssembly module ) throws AssemblyException
+    {
+        module.services( JavaxJsonSerialization.class )
+              .withTypes( Serialization.class,
+                          Serializer.class, Deserializer.class,
+                          Converters.class,
+                          JsonSerialization.class,
+                          JsonSerializer.class, JsonDeserializer.class,
+                          JavaxJsonAdapters.class,
+                          JavaxJsonFactories.class )
+              .taggedWith( Serialization.Format.JSON );
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/unitofwork/DefaultUnitOfWorkAssembler.java b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/unitofwork/DefaultUnitOfWorkAssembler.java
new file mode 100644
index 0000000..6383b75
--- /dev/null
+++ b/core/bootstrap/src/main/java/org/apache/polygene/bootstrap/unitofwork/DefaultUnitOfWorkAssembler.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.bootstrap.unitofwork;
+
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+public class DefaultUnitOfWorkAssembler
+    implements Assembler
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        Class factoryMixin = loadMixinClass( "org.apache.polygene.runtime.unitofwork.UnitOfWorkFactoryMixin" );
+        module.services( UnitOfWorkFactory.class ).withMixins( factoryMixin );
+
+        Class uowMixin = loadMixinClass( "org.apache.polygene.runtime.unitofwork.ModuleUnitOfWork" );
+        module.transients( UnitOfWork.class ).withMixins( uowMixin );
+    }
+
+    private Class<?> loadMixinClass( String name )
+        throws AssemblyException
+    {
+        try
+        {
+            return getClass().getClassLoader().loadClass( name );
+        }
+        catch( ClassNotFoundException e )
+        {
+            throw new AssemblyException( "Default UnitOfWorkFactory mixin is not present in the system." );
+        }
+    }
+}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationAssembler.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationAssembler.java
deleted file mode 100644
index cb5dfda..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationAssembler.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-/**
- * Implement this interface to create the root class that
- * is responsible for assembling your entire application.
- *
- * Model introspectors will instantiate this class and call assemble
- * to create the application, which will then be visited to get
- * information about its structure.
- *
- * Application deployment servers will instantiate this, call assemble,
- * and then activate the created application, which will be the runtime
- * instance that forms your application.
- */
-public interface ApplicationAssembler
-{
-    ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-        throws AssemblyException;
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationAssemblerAdapter.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationAssemblerAdapter.java
deleted file mode 100644
index 1025f7a..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationAssemblerAdapter.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-/**
- * Helper base class for application assemblers that
- * want to either create applications using only one layer/module,
- * or that wants to create pancake-layered applications.
- */
-public class ApplicationAssemblerAdapter
-    implements ApplicationAssembler
-{
-    private final Assembler[][][] assemblers;
-
-    protected ApplicationAssemblerAdapter( Assembler assembler )
-    {
-        this.assemblers = new Assembler[][][]{ { { assembler } } };
-    }
-
-    protected ApplicationAssemblerAdapter( Assembler[][][] assemblers )
-    {
-        this.assemblers = assemblers;
-    }
-
-    @Override
-    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-        throws AssemblyException
-    {
-        return applicationFactory.newApplicationAssembly( assemblers );
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationAssembly.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationAssembly.java
deleted file mode 100644
index b14d554..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationAssembly.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.bootstrap;
-
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.structure.Application;
-
-/**
- * An application assembly. This can be used by Assemblers to programmatically
- * set the name of the application and create new layers.
- */
-public interface ApplicationAssembly
-{
-    /**
-     * Create a new layer assembly
-     *
-     * @param name of the new layer
-     *
-     * @return a LayerAssembly instance
-     */
-    LayerAssembly layer( String name );
-
-    /**
-     * Get an assembly for a particular Module. If this is called many times with the same names, then the same module
-     * is affected.
-     *
-     * @param layerName The name of the Layer
-     * @param moduleName The name of the Module to retrieve or create.
-     * @return The ModuleAssembly for the Module.
-     */
-    ModuleAssembly module( String layerName, String moduleName );
-    
-    /**
-     * Get the currently set name of the application
-     *
-     * @return the name of the application
-     */
-    String name();
-
-    /**
-     * Get the currently set mode of the application
-     *
-     * @return the application mode
-     */
-    Application.Mode mode();
-
-    /**
-     * Set the name of the application
-     *
-     * @param name of the application
-     *
-     * @return the assembly
-     */
-    ApplicationAssembly setName( String name );
-
-    /**
-     * Set the version of the application. This can be in any format, but
-     * most likely will follow the Dewey format, i.e. x.y.z.
-     *
-     * @param version of the application
-     *
-     * @return the assembly
-     */
-    ApplicationAssembly setVersion( String version );
-
-    /**
-     * Set the application mode. This will be set to "production" by default. You can
-     * set the system property "mode" to either "development", "satisfiedBy" or "production"
-     * to explicitly set the mode. If that is not an option, then call this method
-     * during assembly to set the mode. The mode may then be queried by assemblers,
-     * and they may assemble the application differentlly depending on this setting.
-     *
-     * @param mode the application mode
-     *
-     * @return the assembly
-     */
-    ApplicationAssembly setMode( Application.Mode mode );
-
-    ApplicationAssembly setMetaInfo( Object info );
-
-    /**
-     * Set the application activators. Activators are executed in order around the
-     * Application activation and passivation.
-     *
-     * @param activators the application activators
-     * @return the assembly
-     */
-    @SuppressWarnings( { "unchecked","varargs" } )
-    ApplicationAssembly withActivators( Class<? extends Activator<Application>>... activators );
-
-    <ThrowableType extends Throwable> void visit( AssemblyVisitor<ThrowableType> visitor )
-        throws ThrowableType;
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationAssemblyFactory.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationAssemblyFactory.java
deleted file mode 100644
index 5d86bf9..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationAssemblyFactory.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.bootstrap;
-
-/**
- * Factory for creating new Zest application assemblies. Typically
- * you will implement one or more Assemblers, wrap them in an ApplicationAssembler,
- * which then uses this factory to assemble and create applications.
- */
-public interface ApplicationAssemblyFactory
-{
-    /**
-     * Create a new application with one layer and one module.
-     *
-     * @param assembler the assembler for the single module
-     *
-     * @return the application instance
-     *
-     * @throws AssemblyException if the application could not be assembled
-     */
-    ApplicationAssembly newApplicationAssembly( Assembler assembler )
-        throws AssemblyException;
-
-    /**
-     * Create a new application with the same amount of layers
-     * as the first array size, with modules according to the second array size,
-     * and then use the third array for assemblers of each module. This gives you
-     * a simple way to create "pancake" layered applications.
-     *
-     * @param assemblers the set of assemblers for the application
-     *
-     * @return the application instance
-     *
-     * @throws AssemblyException if the application could not be assembled
-     */
-    ApplicationAssembly newApplicationAssembly( Assembler[][][] assemblers )
-        throws AssemblyException;
-
-    /**
-     * Create a new ApplicationAssembly that can be used for the above method.
-     *
-     * @return a new ApplicationAssembly
-     */
-    ApplicationAssembly newApplicationAssembly();
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationModelFactory.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationModelFactory.java
deleted file mode 100644
index c8ea46f..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationModelFactory.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-import org.qi4j.api.structure.ApplicationDescriptor;
-
-/**
- * Factory for ApplicationModelSPI's. Takes an ApplicationAssembly, executes it,
- * and builds an application model from it, which can then be instantiated and activated.
- */
-public interface ApplicationModelFactory
-{
-    ApplicationDescriptor newApplicationModel( ApplicationAssembly assembly )
-        throws AssemblyException;
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationName.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationName.java
deleted file mode 100644
index d2ca628..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ApplicationName.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-/**
- * Set the name of the application
- */
-public final class ApplicationName
-    implements Assembler
-{
-    private String name;
-
-    public ApplicationName( String name )
-    {
-        this.name = name;
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.layer().application().setName( name );
-    }
-}
\ No newline at end of file
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/Assembler.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/Assembler.java
deleted file mode 100644
index b2ffe34..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/Assembler.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-/**
- * ModuleAssemblies are configured by Assemblers. This
- * is the interface you would implement in order to provide
- * all configuration and additional metainfo that is needed
- * to instantiate a Zest application.
- */
-public interface Assembler
-{
-    /**
-     * Assemblers receive a callback to the ModuleAssembly
-     * they are supposed to configure. They can use this
-     * to register objects, composites, services etc. and
-     * the additional metadata that may exist for these
-     * artifacts.
-     * <p>
-     * An Assembler may create new Modules by calling
-     * {@link org.qi4j.bootstrap.ModuleAssembly#layer()} and
-     * then {@link LayerAssembly#module(String)} (String)}.
-     * This allows an Assembler to bootstrap an entire Layer with
-     * more Modules.
-     * </p>
-     * @param module the Module to assemble
-     *
-     * @throws AssemblyException thrown if the assembler tries to do something illegal
-     */
-    void assemble( ModuleAssembly module )
-        throws AssemblyException;
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssemblerCollection.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssemblerCollection.java
deleted file mode 100644
index 670d88b..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssemblerCollection.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-
-/**
- * Assembler that delegates to a collection of Assemblers.
- * <p>
- * Makes it easy to collect and compose assemblers into bigger assemblers.
- * </p>
- */
-public final class AssemblerCollection
-    implements Assembler
-{
-    Collection<Assembler> assemblers;
-
-    public AssemblerCollection( Assembler... assemblers )
-    {
-        this.assemblers = Arrays.asList( assemblers );
-    }
-
-    @SafeVarargs
-    public AssemblerCollection( Class<? extends Assembler>... assemblyClasses )
-        throws AssemblyException
-    {
-        assemblers = new ArrayList<>();
-        for( Class<? extends Assembler> assemblyClass : assemblyClasses )
-        {
-            try
-            {
-                Assembler assembler = assemblyClass.newInstance();
-                assemblers.add( assembler );
-            }
-            catch( Exception e )
-            {
-                throw new AssemblyException( "Could not instantiate assembly with class " + assemblyClass.getName(), e );
-            }
-        }
-    }
-
-    public AssemblerCollection( Collection<Assembler> assemblers )
-    {
-        this.assemblers = assemblers;
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        for( Assembler assembler : assemblers )
-        {
-            assembler.assemble( module );
-        }
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/Assemblers.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/Assemblers.java
deleted file mode 100644
index 6fdcd80..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/Assemblers.java
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.bootstrap;
-
-/**
- * Assembler adapters for common use cases (visibility, identity, configuration).
- */
-public class Assemblers
-{
-    private Assemblers()
-    {
-    }
-
-    /**
-     * Assembler with Visibility interface.
-     * @param <AssemblerType> Parameterized type of Assembler
-     */
-    public interface Visible<AssemblerType>
-        extends Assembler
-    {
-        /**
-         * Set Visibility.
-         * @param visibility Visibility
-         * @return This Assembler instance
-         */
-        AssemblerType visibleIn( org.qi4j.api.common.Visibility visibility );
-
-        /**
-         * Get Visibility.
-         * <p>Default to {@link org.qi4j.api.common.Visibility#module}.</p>
-         * @return Visibility
-         */
-        org.qi4j.api.common.Visibility visibility();
-    }
-
-    /**
-     * Assembler with Identity interface.
-     * @param <AssemblerType> Parameterized type of Assembler
-     */
-    public interface Identifiable<AssemblerType>
-        extends Assembler
-    {
-        /**
-         * Set Identity.
-         * @param identity Identity
-         * @return This Assembler instance
-         */
-        AssemblerType identifiedBy( String identity );
-
-        /**
-         * @return {@literal true} if {@link #identity()} do not return null, {@literal false} otherwise
-         */
-        boolean hasIdentity();
-
-        /**
-         * Get Identity.
-         * <p>Default to {@literal null}.</p>
-         * @return Identity
-         */
-        String identity();
-    }
-
-    /**
-     * Assembler with Configuration interface.
-     * @param <AssemblerType> Parameterized type of Assembler
-     */
-    public interface Configurable<AssemblerType>
-        extends Assembler
-    {
-        /**
-         * Set Configuration Module and Visibility.
-         * @param configModule Configuration Module
-         * @param configVisibility Configuration Visiblity
-         * @return This Assembler instance
-         */
-        AssemblerType withConfig( ModuleAssembly configModule,
-                                  org.qi4j.api.common.Visibility configVisibility );
-
-        /**
-         * @return {@literal true} if {@link #configModule() ()} do not return null, {@literal false} otherwise
-         */
-        boolean hasConfig();
-
-        /**
-         * Get Configuration Module.
-         * <p>Default to {@literal null}.</p>
-         * @return Configuration Module
-         */
-        ModuleAssembly configModule();
-
-        /**
-         * Get Configuration Visibility.
-         * <p>Default to {@link org.qi4j.api.common.Visibility#module}.</p>
-         * @return Configuration Visibility
-         */
-        org.qi4j.api.common.Visibility configVisibility();
-    }
-
-    /**
-     * Assembler with Visibility adapter.
-     * @param <AssemblerType> Parameterized type of Assembler
-     */
-    public static abstract class Visibility<AssemblerType>
-        implements Visible<AssemblerType>
-    {
-        private org.qi4j.api.common.Visibility visibility = org.qi4j.api.common.Visibility.module;
-
-        @Override
-        @SuppressWarnings( "unchecked" )
-        public final AssemblerType visibleIn( org.qi4j.api.common.Visibility visibility )
-        {
-            this.visibility = visibility;
-            return (AssemblerType) this;
-        }
-
-        @Override
-        public final org.qi4j.api.common.Visibility visibility()
-        {
-            return visibility;
-        }
-    }
-
-    /**
-     * Assembler with Identity adapter.
-     * @param <AssemblerType> Parameterized type of Assembler
-     */
-    public static abstract class Identity<AssemblerType>
-        implements Identifiable<AssemblerType>
-    {
-        private String identity;
-
-        @Override
-        @SuppressWarnings( "unchecked" )
-        public final AssemblerType identifiedBy( String identity )
-        {
-            this.identity = identity;
-            return (AssemblerType) this;
-        }
-
-        @Override
-        public final boolean hasIdentity()
-        {
-            return identity != null;
-        }
-
-        @Override
-        public final String identity()
-        {
-            return identity;
-        }
-    }
-
-    /**
-     * Assembler with Configuration adapter.
-     * @param <AssemblerType> Parameterized type of Assembler
-     */
-    public static abstract class Config<AssemblerType>
-        implements Configurable<AssemblerType>
-    {
-        private ModuleAssembly configModule = null;
-        private org.qi4j.api.common.Visibility configVisibility = org.qi4j.api.common.Visibility.module;
-
-        @Override
-        @SuppressWarnings( "unchecked" )
-        public final AssemblerType withConfig( ModuleAssembly configModule,
-                                               org.qi4j.api.common.Visibility configVisibility )
-        {
-            this.configModule = configModule;
-            this.configVisibility = configVisibility;
-            return (AssemblerType) this;
-        }
-
-        @Override
-        public final boolean hasConfig()
-        {
-            return configModule != null;
-        }
-
-        @Override
-        public final ModuleAssembly configModule()
-        {
-            return configModule;
-        }
-
-        @Override
-        public final org.qi4j.api.common.Visibility configVisibility()
-        {
-            return configVisibility;
-        }
-    }
-
-    /**
-     * Assembler with Visibility and Identity adapter.
-     * @param <AssemblerType> Parameterized type of Assembler
-     */
-    public static abstract class VisibilityIdentity<AssemblerType>
-        implements Visible<AssemblerType>,
-                   Identifiable<AssemblerType>
-    {
-        private org.qi4j.api.common.Visibility visibility = org.qi4j.api.common.Visibility.module;
-        private String identity;
-
-        @Override
-        @SuppressWarnings( "unchecked" )
-        public final AssemblerType visibleIn( org.qi4j.api.common.Visibility visibility )
-        {
-            this.visibility = visibility;
-            return (AssemblerType) this;
-        }
-
-        @Override
-        public final org.qi4j.api.common.Visibility visibility()
-        {
-            return visibility;
-        }
-
-        @Override
-        @SuppressWarnings( "unchecked" )
-        public final AssemblerType identifiedBy( String identity )
-        {
-            this.identity = identity;
-            return (AssemblerType) this;
-        }
-
-        @Override
-        public final boolean hasIdentity()
-        {
-            return identity != null;
-        }
-
-        @Override
-        public final String identity()
-        {
-            return identity;
-        }
-    }
-
-    /**
-     * Assembler with Visibility and Configuration adapter.
-     * @param <AssemblerType> Parameterized type of Assembler
-     */
-    public static abstract class VisibilityConfig<AssemblerType>
-        implements Visible<AssemblerType>,
-                   Configurable<AssemblerType>
-    {
-        private org.qi4j.api.common.Visibility visibility = org.qi4j.api.common.Visibility.module;
-        private ModuleAssembly configModule = null;
-        private org.qi4j.api.common.Visibility configVisibility = org.qi4j.api.common.Visibility.module;
-
-        @Override
-        @SuppressWarnings( "unchecked" )
-        public final AssemblerType visibleIn( org.qi4j.api.common.Visibility visibility )
-        {
-            this.visibility = visibility;
-            return (AssemblerType) this;
-        }
-
-        @Override
-        public final org.qi4j.api.common.Visibility visibility()
-        {
-            return visibility;
-        }
-
-        @Override
-        @SuppressWarnings( "unchecked" )
-        public final AssemblerType withConfig( ModuleAssembly configModule,
-                                               org.qi4j.api.common.Visibility configVisibility )
-        {
-            this.configModule = configModule;
-            this.configVisibility = configVisibility;
-            return (AssemblerType) this;
-        }
-
-        @Override
-        public final boolean hasConfig()
-        {
-            return configModule != null;
-        }
-
-        @Override
-        public final ModuleAssembly configModule()
-        {
-            return configModule;
-        }
-
-        @Override
-        public final org.qi4j.api.common.Visibility configVisibility()
-        {
-            return configVisibility;
-        }
-    }
-
-    /**
-     * Assembler with Identity and Configuration adapter.
-     * @param <AssemblerType> Parameterized type of Assembler
-     */
-    public static abstract class IdentityConfig<AssemblerType>
-        implements Identifiable<AssemblerType>,
-                   Configurable<AssemblerType>
-    {
-        private String identity;
-        private ModuleAssembly configModule = null;
-        private org.qi4j.api.common.Visibility configVisibility = org.qi4j.api.common.Visibility.module;
-
-        @Override
-        @SuppressWarnings( "unchecked" )
-        public final AssemblerType identifiedBy( String identity )
-        {
-            this.identity = identity;
-            return (AssemblerType) this;
-        }
-
-        @Override
-        public final boolean hasIdentity()
-        {
-            return identity != null;
-        }
-
-        @Override
-        public final String identity()
-        {
-            return identity;
-        }
-
-        @Override
-        @SuppressWarnings( "unchecked" )
-        public final AssemblerType withConfig( ModuleAssembly configModule,
-                                               org.qi4j.api.common.Visibility configVisibility )
-        {
-            this.configModule = configModule;
-            this.configVisibility = configVisibility;
-            return (AssemblerType) this;
-        }
-
-        @Override
-        public final boolean hasConfig()
-        {
-            return configModule != null;
-        }
-
-        @Override
-        public final ModuleAssembly configModule()
-        {
-            return configModule;
-        }
-
-        @Override
-        public final org.qi4j.api.common.Visibility configVisibility()
-        {
-            return configVisibility;
-        }
-    }
-
-    /**
-     * Assembler with Visibility, Identity and Configuation adapter.
-     * @param <AssemblerType> Parameterized type of Assembler
-     */
-    public static abstract class VisibilityIdentityConfig<AssemblerType>
-        implements Visible<AssemblerType>,
-                   Identifiable<AssemblerType>,
-                   Configurable<AssemblerType>
-    {
-        private org.qi4j.api.common.Visibility visibility = org.qi4j.api.common.Visibility.module;
-        private String identity;
-        private ModuleAssembly configModule = null;
-        private org.qi4j.api.common.Visibility configVisibility = org.qi4j.api.common.Visibility.module;
-
-        @Override
-        @SuppressWarnings( "unchecked" )
-        public final AssemblerType visibleIn( org.qi4j.api.common.Visibility visibility )
-        {
-            this.visibility = visibility;
-            return (AssemblerType) this;
-        }
-
-        @Override
-        public final org.qi4j.api.common.Visibility visibility()
-        {
-            return visibility;
-        }
-
-        @Override
-        @SuppressWarnings( "unchecked" )
-        public final AssemblerType identifiedBy( String identity )
-        {
-            this.identity = identity;
-            return (AssemblerType) this;
-        }
-
-        @Override
-        public final boolean hasIdentity()
-        {
-            return identity != null;
-        }
-
-        @Override
-        public final String identity()
-        {
-            return identity;
-        }
-
-        @Override
-        @SuppressWarnings( "unchecked" )
-        public final AssemblerType withConfig( ModuleAssembly configModule,
-                                               org.qi4j.api.common.Visibility configVisibility )
-        {
-            this.configModule = configModule;
-            this.configVisibility = configVisibility;
-            return (AssemblerType) this;
-        }
-
-        @Override
-        public final boolean hasConfig()
-        {
-            return configModule != null;
-        }
-
-        @Override
-        public final ModuleAssembly configModule()
-        {
-            return configModule;
-        }
-
-        @Override
-        public final org.qi4j.api.common.Visibility configVisibility()
-        {
-            return configVisibility;
-        }
-    }
-
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssemblyException.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssemblyException.java
deleted file mode 100644
index 1c75cd9..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssemblyException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-/**
- * Thrown by ModuleAssembly if the Assembler tries to make an invalid assembly.
- */
-public class AssemblyException
-    extends Exception
-{
-    public AssemblyException()
-    {
-    }
-
-    public AssemblyException( String string )
-    {
-        super( string );
-    }
-
-    public AssemblyException( String string, Throwable throwable )
-    {
-        super( string, throwable );
-    }
-
-    public AssemblyException( Throwable throwable )
-    {
-        super( throwable );
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssemblySpecifications.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssemblySpecifications.java
deleted file mode 100644
index 66fafc7..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssemblySpecifications.java
+++ /dev/null
@@ -1,49 +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.qi4j.bootstrap;
-
-import org.qi4j.api.type.HasTypes;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.Specifications;
-
-/**
- * Utility specifications for Assemblies.
- */
-public class AssemblySpecifications
-{
-    public static Specification<HasTypes> types( final Class... types )
-    {
-        return new Specification<HasTypes>()
-        {
-            @Override
-            public boolean satisfiedBy( HasTypes item )
-            {
-
-                for( Class<?> type : item.types() )
-                {
-                    if( Specifications.in( types ).satisfiedBy( type ) )
-                    {
-                        return true;
-                    }
-                }
-                return false;
-            }
-        };
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssemblyVisitor.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssemblyVisitor.java
deleted file mode 100644
index c1afb59..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssemblyVisitor.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-/**
- * Visitor interface to visit the whole or parts of an assembly.
- * <p>
- * Implement this interface and call visit() on ApplicationAssembly, LayerAssembly or ModuleAssembly.
- * </p>
- * <p>
- * This can be used to, for example, add metadata to all entities, add concerns on composites, or similar.
- * </p>
- */
-public interface AssemblyVisitor<ThrowableType extends Throwable>
-{
-    public void visitApplication( ApplicationAssembly assembly )
-        throws ThrowableType;
-
-    public void visitLayer( LayerAssembly assembly )
-        throws ThrowableType;
-
-    public void visitModule( ModuleAssembly assembly )
-        throws ThrowableType;
-
-    public void visitComposite( TransientDeclaration declaration )
-        throws ThrowableType;
-
-    public void visitEntity( EntityDeclaration declaration )
-        throws ThrowableType;
-
-    public void visitService( ServiceDeclaration declaration )
-        throws ThrowableType;
-
-    public void visitImportedService( ImportedServiceDeclaration declaration )
-        throws ThrowableType;
-
-    public void visitValue( ValueDeclaration declaration )
-        throws ThrowableType;
-
-    public void visitObject( ObjectDeclaration declaration )
-        throws ThrowableType;
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssemblyVisitorAdapter.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssemblyVisitorAdapter.java
deleted file mode 100644
index 904bb5e..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssemblyVisitorAdapter.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-/**
- * Base class for assembly visitors. Subclass and override
- * the particular methods you are interested in.
- */
-public class AssemblyVisitorAdapter<ThrowableType extends Throwable>
-    implements AssemblyVisitor<ThrowableType>
-{
-    @Override
-    public void visitApplication( ApplicationAssembly assembly )
-        throws ThrowableType
-    {
-    }
-
-    @Override
-    public void visitLayer( LayerAssembly assembly )
-        throws ThrowableType
-    {
-    }
-
-    @Override
-    public void visitModule( ModuleAssembly assembly )
-        throws ThrowableType
-    {
-    }
-
-    @Override
-    public void visitComposite( TransientDeclaration declaration )
-        throws ThrowableType
-    {
-    }
-
-    @Override
-    public void visitEntity( EntityDeclaration declaration )
-        throws ThrowableType
-    {
-    }
-
-    @Override
-    public void visitService( ServiceDeclaration declaration )
-        throws ThrowableType
-    {
-    }
-
-    @Override
-    public void visitImportedService( ImportedServiceDeclaration declaration )
-        throws ThrowableType
-    {
-    }
-
-    @Override
-    public void visitValue( ValueDeclaration declaration )
-        throws ThrowableType
-    {
-    }
-
-    @Override
-    public void visitObject( ObjectDeclaration declaration )
-        throws ThrowableType
-    {
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssociationDeclarations.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssociationDeclarations.java
deleted file mode 100644
index 59724ca..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/AssociationDeclarations.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-import java.lang.reflect.AccessibleObject;
-import org.qi4j.api.common.MetaInfo;
-
-/**
- * This provides declared {@link org.qi4j.api.association.Association} information that the runtime can use.
- */
-public interface AssociationDeclarations
-{
-    MetaInfo metaInfoFor( AccessibleObject accessor );
-}
\ No newline at end of file
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/BindingException.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/BindingException.java
deleted file mode 100644
index dbadbfd..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/BindingException.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-/**
- * Thrown by the Zest runtime if a dependency can not be bound.
- */
-public class BindingException
-    extends Exception
-{
-    public BindingException( String s )
-    {
-        super( s );
-    }
-
-    public BindingException( String s, InvalidInjectionException ex )
-    {
-        super( s, ex );
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/BootstrapException.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/BootstrapException.java
deleted file mode 100644
index f1f1cfd..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/BootstrapException.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.bootstrap;
-
-/**
- * This exception is thrown if no ApplicationFactory provider can be found
- */
-public class BootstrapException
-    extends RuntimeException
-{
-    public BootstrapException( String message )
-    {
-        super( message );
-    }
-
-    public BootstrapException( String message, Throwable cause )
-    {
-        super( message, cause );
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ClassScanner.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ClassScanner.java
deleted file mode 100644
index 70c2946..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ClassScanner.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright 2008-2011 Rickard Öberg. All rights Reserved.
- *
- * Licensed  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.qi4j.bootstrap;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Modifier;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.security.CodeSource;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.regex.Pattern;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.flatten;
-import static org.qi4j.functional.Iterables.flattenIterables;
-import static org.qi4j.functional.Iterables.iterable;
-import static org.qi4j.functional.Iterables.map;
-
-/**
- * Scan classpath for classes that matches given criteria. Useful for automated assemblies with lots of similar classes.
- */
-public class ClassScanner
-{
-    /**
-     * Get all classes from the same package of the given class, and recursively in all subpackages.
-     * <p>
-     * This only works if the seed class is loaded from a file: URL. Jar files are possible as well. Abstract classes
-     * are not included in the results. For further filtering use e.g. Iterables.filter.
-     * </p>
-     * @param seedClass starting point for classpath scanning
-     *
-     * @return iterable of all concrete classes in the same package as the seedclass, and also all classes in subpackages.
-     */
-    public static Iterable<Class<?>> findClasses( final Class<?> seedClass )
-    {
-        CodeSource codeSource = seedClass.getProtectionDomain().getCodeSource();
-        if( codeSource == null )
-        {
-            return Iterables.empty();
-        }
-
-        URL location = codeSource.getLocation();
-
-        if( !location.getProtocol().equals( "file" ) )
-        {
-            throw new IllegalArgumentException( "Can only enumerate classes from file system locations. URL is:" + location );
-        }
-
-        final File file;
-        try
-        {
-            file = new File( location.toURI().getPath() );
-        }
-        catch( URISyntaxException e )
-        {
-            throw new IllegalArgumentException( "The file location of codebase is invalid. Can not convert to URI. URL is:" + location );
-        }
-
-        if( file.getName().endsWith( ".jar" ) )
-        {
-            try
-            {
-                final String packageName = seedClass.getPackage().getName().replace( '.', '/' );
-
-                JarFile jarFile = new JarFile( file );
-                Iterable<JarEntry> entries = Iterables.iterable( jarFile.entries() );
-                try
-                {
-                    return Iterables.toList( filter( new ValidClass(),
-                                                     map( new Function<JarEntry, Class<?>>()
-                                                     {
-                                                         @Override
-                                                         public Class map( JarEntry jarEntry )
-                                                         {
-                                                             String name = jarEntry.getName();
-                                                             name = name.substring( 0, name.length() - 6 );
-                                                             name = name.replace( '/', '.' );
-                                                             try
-                                                             {
-                                                                 return seedClass.getClassLoader().loadClass( name );
-                                                             }
-                                                             catch( ClassNotFoundException e )
-                                                             {
-                                                                 return null;
-                                                             }
-                                                         }
-                                                     }
-                                                         , filter( new Specification<JarEntry>()
-                                                     {
-                                                         @Override
-                                                         public boolean satisfiedBy( JarEntry jarEntry )
-                                                         {
-                                                             return jarEntry.getName()
-                                                                        .startsWith( packageName ) && jarEntry.getName()
-                                                                 .endsWith( ".class" );
-                                                         }
-                                                     }, entries ) ) ) );
-                }
-                finally
-                {
-                    jarFile.close();
-                }
-            }
-            catch( IOException e )
-            {
-                throw new IllegalArgumentException( "Could not open jar file " + file, e );
-            }
-        }
-        else
-        {
-            final File path = new File( file, seedClass.getPackage().getName().replace( '.', File.separatorChar ) );
-            Iterable<File> files = findFiles( path, new Specification<File>()
-            {
-                @Override
-                public boolean satisfiedBy( File file )
-                {
-                    return file.getName().endsWith( ".class" );
-                }
-            } );
-
-            return filter( new ValidClass(),
-                           map( new Function<File, Class<?>>()
-                           {
-                               @Override
-                               public Class<?> map( File f )
-                               {
-                                   String fileName = f.getAbsolutePath().substring( file.toString().length() + 1 );
-                                   fileName = fileName.replace( File.separatorChar, '.' )
-                                       .substring( 0, fileName.length() - 6 );
-                                   try
-                                   {
-                                       return seedClass.getClassLoader().loadClass( fileName );
-                                   }
-                                   catch( ClassNotFoundException e )
-                                   {
-                                       return null;
-                                   }
-                               }
-                           }, files ) );
-        }
-    }
-
-    /**
-     * Useful specification for filtering classes based on a regular expression matching the class names.
-     * <p>
-     * Example: matches(".*Model") -&gt; match only class names that end with Model
-     * </p>
-     *
-     * @param regex The regular expression to be matched.
-     *
-     * @return regex class name specification
-     */
-    public static Specification<Class<?>> matches( String regex )
-    {
-        final Pattern pattern = Pattern.compile( regex );
-
-        return new Specification<Class<?>>()
-        {
-            @Override
-            public boolean satisfiedBy( Class<?> aClass )
-            {
-                return pattern.matcher( aClass.getName() ).matches();
-            }
-        };
-    }
-
-    private static Iterable<File> findFiles( File directory, final Specification<File> filter )
-    {
-        return flatten( filter( filter, iterable( directory.listFiles() ) ),
-                        flattenIterables( map( new Function<File, Iterable<File>>()
-                        {
-                            @Override
-                            public Iterable<File> map( File file )
-                            {
-                                return findFiles( file, filter );
-                            }
-                        }, filter( new Specification<File>()
-                        {
-                            @Override
-                            public boolean satisfiedBy( File file )
-                            {
-                                return file.isDirectory();
-                            }
-                        }, iterable( directory.listFiles() ) ) ) ) );
-    }
-
-    private static class ValidClass
-        implements Specification<Class<?>>
-    {
-        @Override
-        public boolean satisfiedBy( Class<?> item )
-        {
-            return ( item.isInterface() || !Modifier.isAbstract( item.getModifiers() ) ) && ( !item.isEnum() && !item.isAnonymousClass() );
-        }
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ConfigurationAssembly.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ConfigurationAssembly.java
deleted file mode 100644
index 8f45332..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ConfigurationAssembly.java
+++ /dev/null
@@ -1,28 +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.qi4j.bootstrap;
-
-import org.qi4j.api.type.HasTypes;
-
-/**
- * This represents the assembly information of a single ConfigurationComposite in a Module.
- */
-public interface ConfigurationAssembly
-    extends HasTypes
-{
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ConfigurationDeclaration.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ConfigurationDeclaration.java
deleted file mode 100644
index ef10c35..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ConfigurationDeclaration.java
+++ /dev/null
@@ -1,87 +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.qi4j.bootstrap;
-
-import org.qi4j.api.common.Visibility;
-
-/**
- * Fluent API for declaring configurations. Instances
- * of this API are acquired by calling {@link ModuleAssembly#configurations(Class[])}.
- */
-public interface ConfigurationDeclaration
-{
-    /**
-     * Set additional metainfo for this configuration declaration.
-     *
-     * @param info metainfo that can be retrieved from the CompositeDescriptor.
-     *
-     * @return This instance for a fluid DSL
-     */
-    ConfigurationDeclaration setMetaInfo( Object info );
-
-    /**
-     * Set visibility for declared entities.
-     *
-     * @param visibility The {@link Visibility} that this ConfigurationComposite will have.
-     *
-     * @return This instance for a fluid DSL
-     */
-    ConfigurationDeclaration visibleIn( Visibility visibility );
-
-    /**
-     * Declare additional concerns for these configurations.
-     *
-     * @param concerns The concerns that are to be added to the ConfigurationComposite beyond the statically declared ones.
-     *
-     * @return This instance for a fluid DSL
-     */
-    ConfigurationDeclaration withConcerns( Class<?>... concerns );
-
-    /**
-     * Declare additional side-effects for these configurations.
-     *
-     * @param sideEffects The sideeffects that are to be added to the ConfigurationComposite beyond the statically declared ones.
-     *
-     * @return This instance for a fluid DSL
-     */
-    ConfigurationDeclaration withSideEffects( Class<?>... sideEffects );
-
-    /**
-     * Declare additional mixins for these configurations.
-     * <p>
-     * This can be useful to override any default mixins from the configuration interface.
-     * </p>
-     * @param mixins The mixins that are to be added to the ConfigurationComposite beyond the statically declared ones.
-     *
-     * @return This instance for a fluid DSL
-     */
-    ConfigurationDeclaration withMixins( Class<?>... mixins );
-
-    /**
-     * Declare additional interfaces for these declared interfaces.
-     * <p>
-     * This can be useful to add types that the Configuration should implement, but
-     * which you do not want to include in the entity interface itself.
-     * </p>
-     * @param types list of interfaces to add
-     *
-     * @return This instance for a fluid DSL
-     */
-    ConfigurationDeclaration withTypes( Class<?>... types );
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/Energy4Java.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/Energy4Java.java
deleted file mode 100644
index d9cdc18..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/Energy4Java.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2008-2011 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.bootstrap;
-
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.spi.Qi4jSPI;
-
-/**
- * Main bootstrap class for starting Zest and creating new applications.
- * <p>
- * Instantiate this and call one of the factory methods to get started.
- * </p>
- * <p>
- * This class will use the Service Loader mechanism in Java to try to locate a runtime that implements
- * the Qi4jRuntime interface. This avoids a direct dependency from the bootstrap to the runtime.
- * </p>
- */
-public final class Energy4Java
-{
-    private Qi4jRuntime runtime;
-
-    public Energy4Java( RuntimeFactory runtimeFactory )
-    {
-        this( runtimeFactory.createRuntime() );
-    }
-
-    public Energy4Java()
-    {
-        this( new RuntimeFactory.StandaloneApplicationRuntimeFactory().createRuntime() );
-    }
-
-    public Energy4Java( Qi4jRuntime runtime )
-    {
-        if( runtime == null )
-        {
-            throw new BootstrapException( "Can not create Zest without a Zest Runtime." );
-        }
-        this.runtime = runtime;
-    }
-
-    public ApplicationDescriptor newApplicationModel( ApplicationAssembler assembler )
-        throws AssemblyException
-    {
-        ApplicationAssembly assembly = assembler.assemble( runtime.applicationAssemblyFactory() );
-
-        if( assembly == null )
-        {
-            throw new AssemblyException( "Application assembler did not return any ApplicationAssembly" );
-        }
-
-        try
-        {
-            ApplicationModelFactory modelFactory = runtime.applicationModelFactory();
-            return modelFactory.newApplicationModel( assembly );
-        }
-        catch( RuntimeException e )
-        {
-            throw new AssemblyException( "Unable to create Application Model.", e );
-        }
-    }
-
-    public Application newApplication( ApplicationAssembler assembler, Object... importedServiceInstances )
-        throws AssemblyException
-    {
-        ApplicationDescriptor model = newApplicationModel( assembler );
-        return model.newInstance( runtime.spi(), importedServiceInstances );
-    }
-
-    public Qi4jSPI spi()
-    {
-        return runtime.spi();
-    }
-
-    public Qi4j api()
-    {
-        return runtime.spi();
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/EntityAssembly.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/EntityAssembly.java
deleted file mode 100644
index ef608ed..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/EntityAssembly.java
+++ /dev/null
@@ -1,29 +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.qi4j.bootstrap;
-
-import org.qi4j.api.type.HasTypes;
-
-/**
- * This represents the assembly information of a single EntityComposite in a Module.
- */
-public interface EntityAssembly
-    extends HasTypes
-{
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/EntityDeclaration.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/EntityDeclaration.java
deleted file mode 100644
index fb00745..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/EntityDeclaration.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.bootstrap;
-
-import org.qi4j.api.common.Visibility;
-
-/**
- * Fluent API for declaring entities. Instances
- * of this API are acquired by calling {@link ModuleAssembly#entities(Class[])}.
- */
-public interface EntityDeclaration
-{
-    /**
-     * Set additional metainfo for this entity declaration.
-     *
-     * @param info metainfo that can be retrieved from the EntityDescriptor.
-     *
-     * @return This instance for a fluid DSL
-     */
-    EntityDeclaration setMetaInfo( Object info );
-
-    /**
-     * Set visibility for declared entities.
-     *
-     * @param visibility The {@link Visibility} that this EntityComposite will have.
-     *
-     * @return This instance for a fluid DSL
-     */
-    EntityDeclaration visibleIn( Visibility visibility );
-
-    /**
-     * Declare additional concerns for these entities.
-     *
-     * @param concerns The concerns that are to be added to the EntityComposite beyond the statically declared ones.
-     *
-     * @return This instance for a fluid DSL
-     */
-    EntityDeclaration withConcerns( Class<?>... concerns );
-
-    /**
-     * Declare additional side-effects for these entitites.
-     *
-     * @param sideEffects The sideeffects that are to be added to the EntityComposite beyond the statically declared ones.
-     *
-     * @return This instance for a fluid DSL
-     */
-    EntityDeclaration withSideEffects( Class<?>... sideEffects );
-
-    /**
-     * Declare additional mixins for these entities.
-     * <p>
-     * This can be useful to override any default mixins from the entity interface.
-     * </p>
-     * @param mixins The mixins that are to be added to the EntityComposite beyond the statically declared ones.
-     *
-     * @return This instance for a fluid DSL
-     */
-    EntityDeclaration withMixins( Class<?>... mixins );
-
-    /**
-     * Declare additional interfaces for these declared interfaces.
-     * <p>
-     * This can be useful to add types that the entities should implement, but
-     * which you do not want to include in the entity interface itself.
-     * </p>
-     * @param types list of interfaces to add
-     *
-     * @return This instance for a fluid DSL
-     */
-    EntityDeclaration withTypes( Class<?>... types );
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ImportedServiceAssembly.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ImportedServiceAssembly.java
deleted file mode 100644
index 2d9320e..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ImportedServiceAssembly.java
+++ /dev/null
@@ -1,29 +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.qi4j.bootstrap;
-
-import org.qi4j.api.type.HasTypes;
-
-/**
- * This represents the assembly information of a single imported service in a Module.
- */
-public interface ImportedServiceAssembly
-    extends HasTypes
-{
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ImportedServiceDeclaration.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ImportedServiceDeclaration.java
deleted file mode 100644
index 2d4b0a9..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ImportedServiceDeclaration.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- * Copyright 2012, Paul Merlin.
- *
- * Licensed  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.qi4j.bootstrap;
-
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.service.importer.InstanceImporter;
-import org.qi4j.api.service.importer.NewObjectImporter;
-import org.qi4j.api.service.importer.ServiceInstanceImporter;
-import org.qi4j.api.service.importer.ServiceSelectorImporter;
-
-/**
- * Fluent API for declaring imported services. Instances
- * of this API are acquired by calling {@link ModuleAssembly#importedServices(Class[])}.
- */
-public interface ImportedServiceDeclaration
-{
-    // Convenience constants for common service importers
-    public static final Class<? extends ServiceImporter> INSTANCE = InstanceImporter.class;
-    public static final Class<? extends ServiceImporter> NEW_OBJECT = NewObjectImporter.class;
-    public static final Class<? extends ServiceImporter> SERVICE_SELECTOR = ServiceSelectorImporter.class;
-    public static final Class<? extends ServiceImporter> SERVICE_IMPORTER = ServiceInstanceImporter.class;
-
-    ImportedServiceDeclaration visibleIn( Visibility visibility );
-
-    ImportedServiceDeclaration importedBy( Class<? extends ServiceImporter> serviceImporterClass );
-
-    ImportedServiceDeclaration identifiedBy( String identity );
-
-    ImportedServiceDeclaration taggedWith( String... tags );
-
-    ImportedServiceDeclaration setMetaInfo( Object serviceAttribute );
-    
-    ImportedServiceDeclaration importOnStartup();
-
-    /**
-     * Set the imported service activators. Activators are executed in order around
-     * the ServiceReference activation and passivation.
-     *
-     * @param activators the imported service activators
-     * @return the assembly
-     */    
-    @SuppressWarnings( { "unchecked","varargs" } )
-    ImportedServiceDeclaration withActivators( Class<? extends Activator<?>>... activators );
-}
\ No newline at end of file
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/InjectionException.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/InjectionException.java
deleted file mode 100644
index bb0d782..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/InjectionException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-/**
- * Thrown by the Zest runtime if a dependency can not be injected.
- */
-public class InjectionException
-    extends RuntimeException
-{
-    public InjectionException( String s )
-    {
-        super( s );
-    }
-
-    public InjectionException( String s, Throwable throwable )
-    {
-        super( s, throwable );
-    }
-
-    public InjectionException( Throwable throwable )
-    {
-        super( throwable );
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/InvalidInjectionException.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/InvalidInjectionException.java
deleted file mode 100644
index d3f18d9..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/InvalidInjectionException.java
+++ /dev/null
@@ -1,36 +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.qi4j.bootstrap;
-
-/**
- * Thrown by the Zest runtime if a dependency injection declaration is invalid.
- */
-public class InvalidInjectionException
-    extends Exception
-{
-    public InvalidInjectionException( String s )
-    {
-        super( s );
-    }
-
-    public InvalidInjectionException( String s, Throwable throwable )
-    {
-        super( s, throwable );
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/LayerAssembly.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/LayerAssembly.java
deleted file mode 100644
index 5880b3e..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/LayerAssembly.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.bootstrap;
-
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.structure.Layer;
-import org.qi4j.functional.Specification;
-
-/**
- * Fluid API for declaring a layer in an application. This is obtained by calling {@link ApplicationAssembly#layer(String)}.
- */
-public interface LayerAssembly
-{
-    /**
-     * Get an assembly for a particular Module. If this is called many times with the same name, then the same module
-     * is affected.
-     *
-     * @param name The name of the Module to retrieve or create.
-     *
-     * @return The ModuleAssembly for the Module.
-     */
-    ModuleAssembly module( String name );
-
-    ApplicationAssembly application();
-
-    String name();
-
-    LayerAssembly setName( String name );
-
-    LayerAssembly setMetaInfo( Object info );
-
-    LayerAssembly uses( LayerAssembly... layerAssembly );
-
-    /**
-     * Set the layer activators. Activators are executed in order around the
-     * Layer activation and passivation.
-     *
-     * @param activators the layer activators
-     * @return the assembly
-     */    
-    @SuppressWarnings( { "unchecked","varargs" } )
-    LayerAssembly withActivators( Class<? extends Activator<Layer>>... activators );
-
-    <ThrowableType extends Throwable> void visit( AssemblyVisitor<ThrowableType> visitor )
-        throws ThrowableType;
-
-    /**
-     * Given a Specification for EntityAssembly's, returns a EntityDeclaration that can
-     * be used to work with all of the assemblies in this Layer matched by the specification.
-     *
-     * @param specification The Specification that specifies the EntityComposite types of interest.
-     *
-     * @return An EntityDeclaration for the specified EntityComposite types.
-     */
-    EntityDeclaration entities( Specification<? super EntityAssembly> specification );
-
-    /**
-     * Given a Specification for ServiceAssembly's, returns a ServiceDeclaration that can
-     * be used to work with all of the assemblies in this Layer matched by the specification.
-     *
-     * @param specification The Specification that specifies the ServiceComposite types of interest.
-     *
-     * @return An ServiceDeclaration for the specified ServiceComposite types.
-     */
-    ServiceDeclaration services( Specification<? super ServiceAssembly> specification );
-
-    /**
-     * Given a Specification for TransientAssembly's, returns a TransientDeclaration that can
-     * be used to work with all of the assemblies in this Layer matched by the specification.
-     *
-     * @param specification The Specification that specifies the TransientComposite types of interest.
-     *
-     * @return An TransientDeclaration for the specified TransientComposite types.
-     */
-    TransientDeclaration transients( Specification<? super TransientAssembly> specification );
-
-    /**
-     * Given a Specification for ValueAssembly's, returns a ValueDeclaration that can
-     * be used to work with all of the assemblies in this Layer matched by the specification.
-     *
-     * @param specification The Specification that specifies the ValueComposite types of interest.
-     *
-     * @return An ValueDeclaration for the specified ValueComposite types.
-     */
-    ValueDeclaration values( Specification<? super ValueAssembly> specification );
-
-    /**
-     * Given a Specification for ObjectAssembly's, returns a ObjectDeclaration that can
-     * be used to work with all of the assemblies in this Layer matched by the specification.
-     *
-     * @param specification The Specification that specifies the Object types of interest.
-     *
-     * @return An ObjectDeclaration for the specified Object types.
-     */
-    ObjectDeclaration objects( Specification<? super ObjectAssembly> specification );
-
-    /**
-     * Given a Specification for ImportedServiceAssembly's, returns a ImportedServiceDeclaration that can
-     * be used to work with all of the assemblies in this Layer matched by the specification.
-     *
-     * @param specification The Specification that specifies the Imported Service types of interest.
-     *
-     * @return An ImportedServiceDeclaration for the specified Imported Service types.
-     */
-    ImportedServiceDeclaration importedServices( Specification<? super ImportedServiceAssembly> specification );
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/LayerName.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/LayerName.java
deleted file mode 100644
index 8d1b8bf..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/LayerName.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-/**
- * Set the name of the layer
- */
-public final class LayerName
-    implements Assembler
-{
-    private final String name;
-
-    public LayerName( String name )
-    {
-        this.name = name;
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.layer().setName( name );
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ManyAssociationDeclarations.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ManyAssociationDeclarations.java
deleted file mode 100644
index f95a6ac..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ManyAssociationDeclarations.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-import java.lang.reflect.AccessibleObject;
-import org.qi4j.api.common.MetaInfo;
-
-/**
- * This provides declared {@link org.qi4j.api.association.ManyAssociation} information that the runtime can use.
- */
-public interface ManyAssociationDeclarations
-{
-    MetaInfo metaInfoFor( AccessibleObject accessor );
-}
\ No newline at end of file
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/MetaInfoDeclaration.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/MetaInfoDeclaration.java
deleted file mode 100644
index 0e55aba..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/MetaInfoDeclaration.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (c) 2008, Michael Hunger All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.HashMap;
-import java.util.Map;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.property.Property;
-
-/**
- * Declaration of a Property or Association.
- */
-public final class MetaInfoDeclaration
-    implements StateDeclarations, AssociationDeclarations, ManyAssociationDeclarations, NamedAssociationDeclarations
-{
-    Map<Class<?>, InfoHolder<?>> mixinPropertyDeclarations = new HashMap<>();
-
-    public MetaInfoDeclaration()
-    {
-    }
-
-    public <T> MixinDeclaration<T> on( Class<T> mixinType )
-    {
-        @SuppressWarnings( "unchecked" )
-        InfoHolder<T> propertyDeclarationHolder = (InfoHolder<T>) mixinPropertyDeclarations.get( mixinType );
-        if( propertyDeclarationHolder == null )
-        {
-            propertyDeclarationHolder = new InfoHolder<>( mixinType );
-            mixinPropertyDeclarations.put( mixinType, propertyDeclarationHolder );
-        }
-        return propertyDeclarationHolder;
-    }
-
-    @Override
-    public MetaInfo metaInfoFor( AccessibleObject accessor )
-    {
-        for( Map.Entry<Class<?>, InfoHolder<?>> entry : mixinPropertyDeclarations.entrySet() )
-        {
-            InfoHolder<?> holder = entry.getValue();
-            MetaInfo metaInfo = holder.metaInfoFor( accessor );
-            if( metaInfo != null )
-            {
-                Class<?> mixinType = entry.getKey();
-                return metaInfo.withAnnotations( mixinType )
-                    .withAnnotations( accessor )
-                    .withAnnotations( accessor instanceof Method ? ( (Method) accessor ).getReturnType() : ( (Field) accessor )
-                        .getType() );
-            }
-        }
-        // TODO is this code reached at all??
-        Class<?> declaringType = ( (Member) accessor ).getDeclaringClass();
-        return new MetaInfo().withAnnotations( declaringType )
-            .withAnnotations( accessor )
-            .withAnnotations( accessor instanceof Method ? ( (Method) accessor ).getReturnType() : ( (Field) accessor ).getType() );
-    }
-
-    @Override
-    public Object initialValueOf( AccessibleObject accessor )
-    {
-        for( InfoHolder<?> propertyDeclarationHolder : mixinPropertyDeclarations.values() )
-        {
-            final Object initialValue = propertyDeclarationHolder.initialValueOf( accessor );
-            if( initialValue != null )
-            {
-                return initialValue;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public boolean useDefaults( AccessibleObject accessor )
-    {
-        for( InfoHolder<?> propertyDeclarationHolder : mixinPropertyDeclarations.values() )
-        {
-            final boolean useDefaults = propertyDeclarationHolder.useDefaults( accessor );
-            if( useDefaults )
-            {
-                return useDefaults;
-            }
-        }
-        return false;
-    }
-
-    private static class InfoHolder<T>
-        implements InvocationHandler, StateDeclarations, MixinDeclaration<T>
-    {
-        private final static class MethodInfo
-        {
-            Object initialValue;
-            boolean useDefaults;
-            MetaInfo metaInfo;
-
-            private MethodInfo( MetaInfo metaInfo )
-            {
-                this.metaInfo = metaInfo;
-            }
-        }
-
-        private final Class<T> mixinType;
-        private final Map<AccessibleObject, MethodInfo> methodInfos = new HashMap<>();
-        // temporary holder
-        private MetaInfo metaInfo = null;
-
-        private InfoHolder( Class<T> mixinType )
-        {
-            this.mixinType = mixinType;
-        }
-
-        @Override
-        @SuppressWarnings( "raw" )
-        public Object invoke( Object o, Method method, Object[] objects )
-            throws Throwable
-        {
-            final MethodInfo methodInfo = new MethodInfo( metaInfo );
-            methodInfo.useDefaults = true;
-            methodInfos.put( method, methodInfo );
-            metaInfo = null; // reset
-            final Class<?> returnType = method.getReturnType();
-            try
-            {
-                return Proxy.newProxyInstance( returnType.getClassLoader(), new Class[]{ returnType },
-                                               new InvocationHandler()
-                                               {
-                                                   @Override
-                                                   public Object invoke( Object o, Method method, Object[] objects )
-                                                       throws Throwable
-                                                   {
-                                                       if( method.getName().equals( "set" ) )
-                                                       {
-                                                           methodInfo.initialValue = objects[ 0 ];
-                                                       }
-                                                       return null;
-                                                   }
-                                               } );
-            }
-            catch( IllegalArgumentException e )
-            {
-                throw new IllegalArgumentException(
-                    "Only methods with " + Property.class.getName() + " as return type can have declareDefaults()" );
-            }
-        }
-
-        public MethodInfo matches( AccessibleObject accessor )
-        {
-            return methodInfos.get( accessor );
-        }
-
-        @Override
-        public MetaInfo metaInfoFor( AccessibleObject accessor )
-        {
-            final MethodInfo methodInfo = matches( accessor );
-            if( methodInfo == null )
-            {
-                return null;
-            }
-            return methodInfo.metaInfo;
-        }
-
-        @Override
-        public Object initialValueOf( AccessibleObject accessor )
-        {
-            final MethodInfo methodInfo = matches( accessor );
-            if( methodInfo == null )
-            {
-                return null;
-            }
-            return methodInfo.initialValue;
-        }
-
-        @Override
-        public boolean useDefaults( AccessibleObject accessor )
-        {
-            final MethodInfo methodInfo = matches( accessor );
-            if( methodInfo == null )
-            {
-                return false;
-            }
-            return methodInfo.useDefaults;
-        }
-
-        // DSL Interface
-
-        @Override
-        @SuppressWarnings( "raw" )
-        public T declareDefaults()
-        {
-            return mixinType.cast(
-                Proxy.newProxyInstance( mixinType.getClassLoader(), new Class[]{ mixinType }, this ) );
-        }
-
-        @Override
-        public MixinDeclaration<T> setMetaInfo( Object info )
-        {
-            if( metaInfo == null )
-            {
-                metaInfo = new MetaInfo();
-            }
-            metaInfo.set( info );
-            return this;
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/MixinDeclaration.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/MixinDeclaration.java
deleted file mode 100644
index 719600a..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/MixinDeclaration.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2008, Michael Hunger. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-/**
- * Fluent API for declaring information about properties
- *
- * @param <T>
- */
-public interface MixinDeclaration<T>
-{
-    T declareDefaults();
-
-    MixinDeclaration<T> setMetaInfo( Object info );
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ModuleAssembly.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ModuleAssembly.java
deleted file mode 100644
index 4e473b4..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ModuleAssembly.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.bootstrap;
-
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.type.HasTypes;
-import org.qi4j.functional.Specification;
-
-/**
- * The ModuleAssembly is used to register any information about * what the module should contain, such as composites,
- * entities and services.
- * <p>
- * Use the methods and the fluent API's to declare how the module should be constructed.
- * </p>
- */
-public interface ModuleAssembly
-{
-    /**
-     * Access the layer assembly for this module.
-     *
-     * @return The Layer containing this Module.
-     */
-    LayerAssembly layer();
-
-    /**
-     * Get an assembly for a particular Module. If this is called many times with the same names, then the same module
-     * is affected.
-     *
-     * @param layerName  The name of the Layer
-     * @param moduleName The name of the Module to retrieve or create.
-     *
-     * @return The ModuleAssembly for the Module.
-     */
-    ModuleAssembly module( String layerName, String moduleName );
-
-    /**
-     * Set the name of this module.
-     *
-     * @param name The name that this Module should have.
-     *
-     * @return This instance to support the fluid DSL of bootstrap.
-     */
-    ModuleAssembly setName( String name );
-
-    /**
-     * Access the currently set name for this module.
-     *
-     * @return The name of this Module.
-     */
-    String name();
-
-    ModuleAssembly setMetaInfo( Object info );
-
-    /**
-     * Set the module activators. Activators are executed in order around the
-     * Module activation and passivation.
-     *
-     * @param activators the module activators
-     *
-     * @return the assembly
-     */
-    @SuppressWarnings({ "unchecked", "varargs" })
-    ModuleAssembly withActivators( Class<? extends Activator<Module>>... activators );
-
-    /**
-     * Declare a list of TransientComposites for this Module. Use the TransientDeclaration that is returned to
-     * declare further settings. Note that the TransientDeclaration works on all of the types specified.
-     *
-     * @param transientTypes The types that specifies the Transient types.
-     *
-     * @return An TransientDeclaration for the specified Transient types.
-     */
-    TransientDeclaration transients( Class<?>... transientTypes );
-
-    /**
-     * Given a Specification for TransientAssembly's, returns a TransientDeclaration that can
-     * be used to work with all of the assemblies matched by the specification.
-     *
-     * @param specification The Specification that specifies the TransientComposite types of interest.
-     *
-     * @return An TransientDeclaration for the specified TransientComposite types.
-     */
-    TransientDeclaration transients( Specification<? super TransientAssembly> specification );
-
-    /**
-     * Declare a list of ValueComposites for this Module. Use the ValueDeclaration that is returned to
-     * declare further settings. Note that the ValueDeclaration works on all of the types specified.
-     *
-     * @param valueTypes The types that specifies the Value types.
-     *
-     * @return An ValueDeclaration for the specified Value types.
-     */
-    ValueDeclaration values( Class<?>... valueTypes );
-
-    /**
-     * Given a Specification for ValueAssembly's, returns a ValueDeclaration that can
-     * be used to work with all of the assemblies matched by the specification.
-     *
-     * @param specification The Specification that specifies the ValueComposite types of interest.
-     *
-     * @return An ValueDeclaration for the specified ValueComposite types.
-     */
-    ValueDeclaration values( Specification<? super ValueAssembly> specification );
-
-    /**
-     * Declare a list of EntityComposites for this Module. Use the EntityDeclaration that is returned to
-     * declare further settings. Note that the EntityDeclaration works on all of the types specified.
-     *
-     * @param entityTypes The types that specifies the Entity types.
-     *
-     * @return An EntityDeclaration for the specified Entity types.
-     */
-    EntityDeclaration entities( Class<?>... entityTypes );
-
-    /**
-     * Given a Specification for EntityAssembly's, returns a EntityDeclaration that can
-     * be used to work with all of the assemblies matched by the specification.
-     *
-     * @param specification The Specification that specifies the EntityComposite types of interest.
-     *
-     * @return An EntityDeclaration for the specified EntityComposite types.
-     */
-    EntityDeclaration entities( Specification<? super EntityAssembly> specification );
-
-    /**
-     * Declare a list of Configuration Composites for this Module. Use the ConfigurationDeclaration that is returned to
-     * declare further settings. Note that the ConfigurationDeclaration works on all of the types specified.
-     *
-     * @param configurationTypes The types that specifies the Configuration types.
-     *
-     * @return An ConfigurationDeclaration for the specified Configuration types.
-     */
-    ConfigurationDeclaration configurations( Class<?>... configurationTypes );
-
-    /**
-     * Given a Specification for ConfigurationAssembly's, returns a ConfigurationDeclaration that can
-     * be used to work with all of the assemblies matched by the specification.
-     *
-     * @param specification The Specification that specifies the ConfigurationComposite types of interest.
-     *
-     * @return An ConfigurationDeclaration for the specified EntityComposite types.
-     */
-    ConfigurationDeclaration configurations( Specification<HasTypes> specification );
-
-
-    /**
-     * Declare a list of object classes for this Module. Use the ObjectDeclaration that is returned to
-     * declare further settings. Note that the ObjectDeclaration works on all of the types specified.
-     *
-     * @param objectTypes The types that specifies the Object types.
-     *
-     * @return An ObjectDeclaration for the specified Object types.
-     */
-    ObjectDeclaration objects( Class<?>... objectTypes )
-        throws AssemblyException;
-
-    /**
-     * Given a Specification for ObjectAssembly's, returns a ObjectDeclaration that can
-     * be used to work with all of the assemblies matched by the specification.
-     *
-     * @param specification The Specification that specifies the Object types of interest.
-     *
-     * @return An ObjectDeclaration for the specified Object types.
-     */
-    ObjectDeclaration objects( Specification<? super ObjectAssembly> specification );
-
-    /**
-     * Create a list of ServiceComposites for this Module. Use the ServiceDeclaration that is returned to
-     * declare further settings. This will always create new assemblies for the specified types, instead
-     * of potentially working on already declared types like the services(...) method.
-     *
-     * @param serviceTypes The types that specifies the Service types.
-     *
-     * @return An ServiceDeclaration for the specified Service types.
-     */
-    ServiceDeclaration addServices( Class<?>... serviceTypes );
-
-    /**
-     * Declare a list of ServiceComposites for this Module. Use the ServiceDeclaration that is returned to
-     * declare further settings. Note that the ServiceDeclaration works on all of the types specified.
-     *
-     * @param serviceTypes The types that specifies the Service types.
-     *
-     * @return An ServiceDeclaration for the specified Service types.
-     */
-    ServiceDeclaration services( Class<?>... serviceTypes );
-
-    /**
-     * Given a Specification for ServiceAssembly's, returns a ServiceDeclaration that can
-     * be used to work with all of the assemblies matched by the specification.
-     *
-     * @param specification The Specification that specifies the ServiceComposite types of interest.
-     *
-     * @return An ServiceDeclaration for the specified ServiceComposite types.
-     */
-    ServiceDeclaration services( Specification<? super ServiceAssembly> specification );
-
-    /**
-     * Declare a list of imported services for this Module. Use the ImportedServiceDeclaration that is returned to
-     * declare further settings. Note that the ImportedServiceDeclaration works on all of the types specified.
-     *
-     * @param serviceTypes The types that specifies the Imported Service types.
-     *
-     * @return An ImportedServiceDeclaration for the specified Imported Service types.
-     */
-    ImportedServiceDeclaration importedServices( Class<?>... serviceTypes );
-
-    /**
-     * Given a Specification for ImportedServiceAssembly's, returns a ImportedServiceDeclaration that can
-     * be used to work with all of the assemblies matched by the specification.
-     *
-     * @param specification The Specification that specifies the Imported Service types of interest.
-     *
-     * @return An ImportedServiceDeclaration for the specified Imported Service types.
-     */
-    ImportedServiceDeclaration importedServices( Specification<? super ImportedServiceAssembly> specification );
-
-    <T> MixinDeclaration<T> forMixin( Class<T> mixinType );
-
-    public <ThrowableType extends Throwable> void visit( AssemblyVisitor<ThrowableType> visitor )
-        throws ThrowableType;
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ModuleName.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ModuleName.java
deleted file mode 100644
index e8a9a20..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ModuleName.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-/**
- * Set the name of the module
- */
-public final class ModuleName
-    implements Assembler
-{
-    private final String name;
-
-    public ModuleName( String name )
-    {
-        this.name = name;
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.setName( name );
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/NamedAssociationDeclarations.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/NamedAssociationDeclarations.java
deleted file mode 100644
index 54a4257..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/NamedAssociationDeclarations.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2011-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.bootstrap;
-
-import java.lang.reflect.AccessibleObject;
-import org.qi4j.api.common.MetaInfo;
-
-/**
- * This provides declared {@link org.qi4j.api.association.NamedAssociation} information that the runtime can use.
- */
-public interface NamedAssociationDeclarations
-{
-    MetaInfo metaInfoFor( AccessibleObject accessor );
-}
\ No newline at end of file
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ObjectAssembly.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ObjectAssembly.java
deleted file mode 100644
index e424cf6..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ObjectAssembly.java
+++ /dev/null
@@ -1,29 +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.qi4j.bootstrap;
-
-import org.qi4j.api.type.HasTypes;
-
-/**
- * This represents the assembly information of a single object type in a Module.
- */
-public interface ObjectAssembly
-    extends HasTypes
-{
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ObjectDeclaration.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ObjectDeclaration.java
deleted file mode 100644
index 278d6ff..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ObjectDeclaration.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.bootstrap;
-
-import org.qi4j.api.common.Visibility;
-
-/**
- * Fluent API for declaring objects.Instances
- * of this API are acquired by calling {@link ModuleAssembly#objects(Class[])}.
- */
-public interface ObjectDeclaration
-{
-    ObjectDeclaration setMetaInfo( Object info );
-
-    ObjectDeclaration visibleIn( Visibility visibility )
-        throws IllegalStateException;
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/Qi4jRuntime.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/Qi4jRuntime.java
deleted file mode 100644
index 76e6130..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/Qi4jRuntime.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-import org.qi4j.api.Qi4j;
-import org.qi4j.spi.Qi4jSPI;
-
-/**
- * This interface has to be implemented by Zest runtimes.
- */
-public interface Qi4jRuntime
-{
-    ApplicationAssemblyFactory applicationAssemblyFactory();
-
-    ApplicationModelFactory applicationModelFactory();
-
-    Qi4j api();
-
-    Qi4jSPI spi();
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/RuntimeFactory.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/RuntimeFactory.java
deleted file mode 100644
index b4efd24..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/RuntimeFactory.java
+++ /dev/null
@@ -1,62 +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.qi4j.bootstrap;
-
-/**
- * Zest runtime factory.
- */
-public interface RuntimeFactory
-{
-    Qi4jRuntime createRuntime();
-
-    /**
-     * Standalone application Zest runtime factory.
-     */
-    public final class StandaloneApplicationRuntimeFactory
-        implements RuntimeFactory
-    {
-        @Override
-        public Qi4jRuntime createRuntime()
-        {
-            ClassLoader loader = getClass().getClassLoader();
-            try
-            {
-                Class<? extends Qi4jRuntime> runtimeClass = loadRuntimeClass( loader );
-                return runtimeClass.newInstance();
-            }
-            catch( ClassNotFoundException e )
-            {
-                System.err.println( "Zest Runtime jar is not present in the classpath." );
-            }
-            catch( InstantiationException | IllegalAccessException e )
-            {
-                System.err.println( "Invalid Zest Runtime class. If you are providing your own Zest Runtime, please " +
-                                    "contact qi4j-dev at Google Groups for assistance." );
-            }
-            return null;
-        }
-
-        @SuppressWarnings( { "unchecked" } )
-        private Class<? extends Qi4jRuntime> loadRuntimeClass( ClassLoader loader )
-            throws ClassNotFoundException
-        {
-            return (Class<? extends Qi4jRuntime>) loader.loadClass( "org.qi4j.runtime.Qi4jRuntimeImpl" );
-        }
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ServiceAssembly.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ServiceAssembly.java
deleted file mode 100644
index 27ce698..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ServiceAssembly.java
+++ /dev/null
@@ -1,29 +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.qi4j.bootstrap;
-
-import org.qi4j.api.type.HasTypes;
-
-/**
- * This represents the assembly information of a single ServiceComposite in a Module.
- */
-public interface ServiceAssembly extends HasTypes
-{
-    String identity();
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ServiceDeclaration.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ServiceDeclaration.java
deleted file mode 100644
index c566c59..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ServiceDeclaration.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.bootstrap;
-
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.common.Visibility;
-
-/**
- * Fluent API for declaring services hosted in Zest. Instances
- * of this API are acquired by calling {@link ModuleAssembly#services(Class[])}.
- */
-public interface ServiceDeclaration
-{
-    ServiceDeclaration setMetaInfo( Object serviceAttribute );
-
-    ServiceDeclaration visibleIn( Visibility visibility );
-
-    ServiceDeclaration withConcerns( Class<?>... concerns );
-
-    ServiceDeclaration withSideEffects( Class<?>... sideEffects );
-
-    ServiceDeclaration withMixins( Class<?>... mixins );
-
-    ServiceDeclaration withTypes( Class<?>... types );
-
-    ServiceDeclaration identifiedBy( String identity );
-
-    ServiceDeclaration taggedWith( String... tags );
-
-    ServiceDeclaration instantiateOnStartup();
-
-    /**
-     * Set the service activators. Activators are executed in order around the
-     * ServiceReference activation and passivation.
-     *
-     * @param activators the service activators
-     * @return the assembly
-     */    
-    @SuppressWarnings( { "unchecked","varargs" } )
-    ServiceDeclaration withActivators( Class<? extends Activator<?>>... activators );
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/SingletonAssembler.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/SingletonAssembler.java
deleted file mode 100644
index 7d2542d..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/SingletonAssembler.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-
-/**
- * Base class for Assembler that creates an Application
- * with one Layer and one Module. Create a subclass of this
- * and implement the {@link Assembler#assemble(ModuleAssembly)} method.
- * Once the SingletonAssembler is instantiated it will have created and activated
- * an Application which can be accessed from {@link org.qi4j.bootstrap.SingletonAssembler#application()}.
- * You can also easily access any resources specific for the single Module, such as the TransientBuilderFactory.
- */
-public abstract class SingletonAssembler
-    implements Assembler
-{
-    private Energy4Java qi4j;
-    private Application applicationInstance;
-    private final Module moduleInstance;
-
-    /**
-     * Creates a Zest Runtime instance containing one Layer with one Module.
-     * The Layer will be named "Layer 1" and the Module will be named "Module 1". It is possible to add
-     * additional layers and modules via the Assembler interface that must be implemented in the subclass of this
-     * class.
-     *
-     * @throws AssemblyException Either if the model can not be created from the disk, or some inconsistency in
-     *                           the programming model makes it impossible to create it.
-     * @throws ActivationException If the automatic {@code activate()} method is throwing this Exception..
-     */
-    public SingletonAssembler()
-        throws AssemblyException, ActivationException
-    {
-// START SNIPPET: actual
-        qi4j = new Energy4Java();
-        applicationInstance = qi4j.newApplication( new ApplicationAssembler()
-        {
-            @Override
-            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-                throws AssemblyException
-            {
-                return applicationFactory.newApplicationAssembly( SingletonAssembler.this );
-            }
-        } );
-
-        try
-        {
-            beforeActivation( applicationInstance );
-            applicationInstance.activate();
-        }
-        catch( Exception e )
-        {
-            if( e instanceof ActivationException )
-            {
-                throw ( (ActivationException) e );
-            }
-            throw new ActivationException( "Could not activate application", e );
-        }
-// START SNIPPET: actual
-
-        moduleInstance = applicationInstance.findModule( "Layer 1", "Module 1" );
-    }
-
-    public final Qi4j runtime()
-    {
-        return qi4j.spi();
-    }
-
-    public final Application application()
-    {
-        return applicationInstance;
-    }
-
-    public final Module module()
-    {
-        return moduleInstance;
-    }
-
-    protected void beforeActivation( Application application )
-        throws Exception
-    {
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/StateDeclarations.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/StateDeclarations.java
deleted file mode 100644
index 39a69b8..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/StateDeclarations.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.bootstrap;
-
-import java.lang.reflect.AccessibleObject;
-import org.qi4j.api.common.MetaInfo;
-
-/**
- * This provides declared {@link org.qi4j.api.property.Property} information that the runtime can use.
- */
-public interface StateDeclarations
-{
-    MetaInfo metaInfoFor( AccessibleObject accessor );
-
-    Object initialValueOf( AccessibleObject accessor );
-
-    boolean useDefaults( AccessibleObject accessor );
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/TransientAssembly.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/TransientAssembly.java
deleted file mode 100644
index f3e2a58..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/TransientAssembly.java
+++ /dev/null
@@ -1,29 +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.qi4j.bootstrap;
-
-import org.qi4j.api.type.HasTypes;
-
-/**
- * This represents the assembly information of a single TransientComposite in a Module.
- */
-public interface TransientAssembly
-    extends HasTypes
-{
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/TransientDeclaration.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/TransientDeclaration.java
deleted file mode 100644
index a974f73..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/TransientDeclaration.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.bootstrap;
-
-import org.qi4j.api.common.Visibility;
-
-/**
- * Fluent API for declaring TransientComposites. Instances
- * of this API are acquired by calling {@link ModuleAssembly#transients(Class[])}.
- */
-public interface TransientDeclaration
-{
-    TransientDeclaration setMetaInfo( Object info );
-
-    TransientDeclaration visibleIn( Visibility visibility );
-
-    TransientDeclaration withConcerns( Class<?>... concerns );
-
-    TransientDeclaration withSideEffects( Class<?>... sideEffects );
-
-    TransientDeclaration withMixins( Class<?>... mixins );
-
-    TransientDeclaration withTypes( Class<?>... roles );
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ValueAssembly.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ValueAssembly.java
deleted file mode 100644
index 9f98406..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ValueAssembly.java
+++ /dev/null
@@ -1,29 +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.qi4j.bootstrap;
-
-import org.qi4j.api.type.HasTypes;
-
-/**
- * This represents the assembly information of a single ValueComposite in a Module.
- */
-public interface ValueAssembly
-    extends HasTypes
-{
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ValueDeclaration.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/ValueDeclaration.java
deleted file mode 100644
index 490ae87..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/ValueDeclaration.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.bootstrap;
-
-import org.qi4j.api.common.Visibility;
-
-/**
- * Fluent API for declaring values
- */
-public interface ValueDeclaration
-{
-    ValueDeclaration setMetaInfo( Object info );
-
-    ValueDeclaration visibleIn( Visibility visibility );
-
-    ValueDeclaration withConcerns( Class<?>... concerns );
-
-    ValueDeclaration withSideEffects( Class<?>... sideEffects );
-
-    ValueDeclaration withMixins( Class<?>... mixins );
-
-    ValueDeclaration withTypes( Class<?>... roles );
-}
\ No newline at end of file
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
deleted file mode 100644
index d68a3d5..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/builder/ApplicationBuilder.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright 2014 Niclas Hedhman.
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.bootstrap.builder;
-
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Scanner;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.api.activation.ActivationEventListener;
-import org.qi4j.api.activation.ActivationEventListenerRegistration;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.activation.ApplicationPassivationThread;
-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;
-
-/**
- * Application Builder.
- */
-public class ApplicationBuilder
-    implements ActivationEventListenerRegistration
-{
-    private final String applicationName;
-    private final Map<String, LayerDeclaration> layers = new HashMap<>();
-    private final List<ActivationEventListener> activationListeners = new ArrayList<>();
-
-    public ApplicationBuilder( String applicationName )
-    {
-        this.applicationName = applicationName;
-    }
-
-    /**
-     * Create and activate a new Application.
-     * @return Activated Application
-     * @throws AssemblyException if the assembly failed
-     * @throws ActivationException if the activation failed
-     */
-    public Application newApplication()
-        throws AssemblyException, ActivationException
-    {
-        Energy4Java qi4j = new Energy4Java();
-        ApplicationDescriptor model = qi4j.newApplicationModel( new ApplicationAssembler()
-        {
-            @Override
-            public ApplicationAssembly assemble( ApplicationAssemblyFactory factory )
-                throws AssemblyException
-            {
-                ApplicationAssembly assembly = factory.newApplicationAssembly();
-                assembly.setName( applicationName );
-                HashMap<String, LayerAssembly> createdLayers = new HashMap<>();
-                for( Map.Entry<String, LayerDeclaration> entry : layers.entrySet() )
-                {
-                    LayerAssembly layer = entry.getValue().createLayer( assembly );
-                    createdLayers.put( entry.getKey(), layer );
-                }
-                for( LayerDeclaration layer : layers.values() )
-                {
-                    layer.initialize( createdLayers );
-                }
-                return assembly;
-            }
-        } );
-        Application application = model.newInstance( qi4j.api() );
-        for( ActivationEventListener activationListener : activationListeners )
-        {
-            application.registerActivationEventListener( activationListener );
-        }
-        beforeActivation();
-        application.activate();
-        afterActivation();
-        return application;
-    }
-
-    /**
-     * Called before application activation.
-     */
-    protected void beforeActivation()
-    {
-    }
-
-    /**
-     * Called after application activation.
-     */
-    protected void afterActivation()
-    {
-    }
-
-    @Override
-    public void registerActivationEventListener( ActivationEventListener listener )
-    {
-        activationListeners.add( listener );
-    }
-
-    @Override
-    public void deregisterActivationEventListener( ActivationEventListener listener )
-    {
-        activationListeners.remove( listener );
-    }
-
-    /**
-     * Declare Layer.
-     * @param layerName Name of the Layer
-     * @return Layer declaration for the given name, new if did not already exists
-     */
-    public LayerDeclaration withLayer( String layerName )
-    {
-        LayerDeclaration layerDeclaration = layers.get( layerName );
-        if( layerDeclaration != null )
-        {
-            return layerDeclaration;
-        }
-        layerDeclaration = new LayerDeclaration( layerName );
-        layers.put( layerName, layerDeclaration );
-        return layerDeclaration;
-    }
-
-    /**
-     * Load an ApplicationBuilder from a JSON String.
-     * @param json JSON String
-     * @return Application Builder loaded from JSON
-     * @throws JSONException if unable to read JSON
-     * @throws AssemblyException if unable to declare the assembly
-     */
-    public static ApplicationBuilder fromJson( String json )
-        throws JSONException, AssemblyException
-    {
-        JSONObject root = new JSONObject( json );
-        return fromJson( root );
-    }
-
-    /**
-     * Load an ApplicationBuilder from a JSON InputStream.
-     * @param json JSON input
-     * @return Application Builder loaded from JSON
-     * @throws JSONException if unable to read JSON
-     * @throws AssemblyException if unable to declare the assembly
-     */
-    public static ApplicationBuilder fromJson( InputStream json )
-        throws JSONException, AssemblyException
-    {
-        String jsonString = new Scanner( json, "UTF-8" ).useDelimiter( "\\A" ).next();
-        return fromJson( jsonString );
-    }
-
-    /**
-     * Load an ApplicationBuilder from a JSONObject.
-     * @param root JSON object
-     * @return Application Builder loaded from JSON
-     * @throws JSONException if unable to read JSON
-     * @throws AssemblyException if unable to declare the assembly
-     */
-    public static ApplicationBuilder fromJson( JSONObject root )
-        throws JSONException, AssemblyException
-    {
-        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 )
-        {
-            for( int i = 0; i < layers.length(); i++ )
-            {
-                JSONObject layerObject = layers.getJSONObject( i );
-                String layerName = layerObject.getString( "name" );
-                LayerDeclaration layerDeclaration = withLayer( layerName );
-                JSONArray using = layerObject.optJSONArray( "uses" );
-                if( using != null )
-                {
-                    for( int j = 0; j < using.length(); j++ )
-                    {
-                        layerDeclaration.using( using.getString( j ) );
-                    }
-                }
-                JSONArray modules = layerObject.optJSONArray( "modules" );
-                if( modules != null )
-                {
-                    for( int k = 0; k < modules.length(); k++ )
-                    {
-                        JSONObject moduleObject = modules.getJSONObject( k );
-                        String moduleName = moduleObject.getString( "name" );
-                        ModuleDeclaration moduleDeclaration = layerDeclaration.withModule( moduleName );
-                        JSONArray assemblers = moduleObject.optJSONArray( "assemblers" );
-                        if( assemblers != null )
-                        {
-                            for( int m = 0; m < assemblers.length(); m++ )
-                            {
-                                String string = assemblers.getString( m );
-                                moduleDeclaration.withAssembler( string );
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * {@literal main} method that read JSON from STDIN.
-     * <p>Passivation exceptions are written to STDERR if any.</p>
-     * @param args Unused
-     * @throws JSONException if unable to read JSON
-     * @throws AssemblyException if the assembly failed
-     * @throws ActivationException if the activation failed
-     */
-    public static void main( String[] args )
-        throws JSONException, ActivationException, AssemblyException
-    {
-        ApplicationBuilder builder = fromJson( System.in );
-        Application application = builder.newApplication();
-        Runtime.getRuntime().addShutdownHook( new ApplicationPassivationThread( application, System.err ) );
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/builder/LayerDeclaration.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/builder/LayerDeclaration.java
deleted file mode 100644
index 0a30bbe..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/builder/LayerDeclaration.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2014 Niclas Hedhman.
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.bootstrap.builder;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Iterables;
-
-/**
- * Provides declared {@link org.qi4j.api.structure.Layer} information that the {@link ApplicationBuilder} can use.
- */
-public class LayerDeclaration
-{
-    private final String layerName;
-    private final List<String> using = new ArrayList<>();
-    private final Map<String, ModuleDeclaration> modules = new HashMap<>();
-    private LayerAssembly layer;
-
-    LayerDeclaration( String layerName )
-    {
-        this.layerName = layerName;
-    }
-
-    /**
-     * Declare using layer.
-     * @param layerName Used layer name
-     * @return This Layer declaration
-     */
-    public LayerDeclaration using( String layerName )
-    {
-        this.using.add( layerName );
-        return this;
-    }
-
-    /**
-     * Declare using layers.
-     * @param layerNames Used layers names
-     * @return This Layer declaration
-     */
-    public LayerDeclaration using( Iterable<String> layerNames )
-    {
-        Iterables.addAll( using, layerNames );
-        return this;
-    }
-
-    /**
-     * Declare Module.
-     * @param moduleName Name of the Module
-     * @return Module declaration for the given name, new if did not already exists
-     */
-    public ModuleDeclaration withModule( String moduleName )
-    {
-        ModuleDeclaration module = modules.get( moduleName );
-        if( module != null )
-        {
-            return module;
-        }
-        module = new ModuleDeclaration( moduleName );
-        modules.put( moduleName, module );
-        return module;
-    }
-
-    LayerAssembly createLayer( ApplicationAssembly application )
-    {
-        layer = application.layer( layerName );
-        layer.setName( layerName );
-        for( ModuleDeclaration module : modules.values() )
-        {
-            ModuleAssembly assembly = module.createModule( layer );
-        }
-        return layer;
-    }
-
-    void initialize( HashMap<String, LayerAssembly> createdLayers )
-        throws AssemblyException
-    {
-        for( String uses : using )
-        {
-            LayerAssembly usedLayer = createdLayers.get( uses );
-            layer.uses( usedLayer );
-        }
-        for( ModuleDeclaration module : modules.values() )
-        {
-            module.initialize();
-        }
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/builder/ModuleDeclaration.java b/core/bootstrap/src/main/java/org/qi4j/bootstrap/builder/ModuleDeclaration.java
deleted file mode 100644
index 6ac63d9..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/builder/ModuleDeclaration.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright 2014 Niclas Hedhman.
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.bootstrap.builder;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-import static org.qi4j.api.util.Classes.isAssignableFrom;
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.toList;
-import static org.qi4j.functional.Specifications.not;
-
-/**
- * Provides declared {@link org.qi4j.api.structure.Module} information that the {@link ApplicationBuilder} can use.
- */
-public class ModuleDeclaration
-{
-    private final String moduleName;
-    private final List<Assembler> assemblers = new ArrayList<>();
-    private ModuleAssembly module;
-
-    public ModuleDeclaration( String moduleName )
-    {
-        this.moduleName = moduleName;
-    }
-
-    /**
-     * Declare Assembler.
-     * @param assembler Assembler instance
-     * @return This Module declaration
-     */
-    public ModuleDeclaration withAssembler( Assembler assembler )
-    {
-        assemblers.add( assembler );
-        return this;
-    }
-
-    /**
-     * Declare Assembler.
-     * @param classname Assembler class name
-     * @return This Module declaration
-     * @throws AssemblyException if unable to load class, not an Assembler or unable to instanciate
-     */
-    public ModuleDeclaration withAssembler( String classname )
-        throws AssemblyException
-    {
-        Class<? extends Assembler> clazz = loadClass( classname );
-        return withAssembler( clazz );
-    }
-
-    /**
-     * Declare Assembler.
-     * @param assemblerClass Assembler class
-     * @return This Module declaration
-     * @throws AssemblyException not an Assembler or if unable to instanciate
-     */
-    public ModuleDeclaration withAssembler( Class<?> assemblerClass )
-        throws AssemblyException
-    {
-        Assembler assembler = createAssemblerInstance( assemblerClass );
-        assemblers.add( assembler );
-        return this;
-    }
-
-    /**
-     * Declare Assemblers.
-     * <p>Declare several Assemblers from an Iterable of Class objects.</p>
-     * <p>Typically used along {@link org.qi4j.bootstrap.ClassScanner}.</p>
-     * @param assemblerClasses Assembler classes
-     * @return This Module declaration
-     * @throws AssemblyException if one of the Class is not an Assembler or unable to instanciate
-     */
-    public ModuleDeclaration withAssemblers( Iterable<Class<?>> assemblerClasses )
-        throws AssemblyException
-    {
-        List<Class<?>> notAssemblers = toList(
-            filter( not( isAssignableFrom( Assembler.class ) ),
-                    assemblerClasses )
-        );
-        if( !notAssemblers.isEmpty() )
-        {
-            throw new AssemblyException(
-                "Classes " + notAssemblers + " are not implementing " + Assembler.class.getName()
-            );
-        }
-        for( Class<?> assemblerClass : assemblerClasses )
-        {
-            withAssembler( assemblerClass );
-        }
-        return this;
-    }
-
-    ModuleAssembly createModule( LayerAssembly layer )
-    {
-        module = layer.module( moduleName );
-        return module;
-    }
-
-    void initialize()
-        throws AssemblyException
-    {
-        for( Assembler assembler : assemblers )
-        {
-            assembler.assemble( module );
-        }
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private Class<? extends Assembler> loadClass( String classname )
-        throws AssemblyException
-    {
-        Class<?> clazz;
-        try
-        {
-            clazz = getClass().getClassLoader().loadClass( classname );
-        }
-        catch( Exception e )
-        {
-            throw new AssemblyException( "Unable to load class " + classname, e );
-        }
-        if( !Assembler.class.isAssignableFrom( clazz ) )
-        {
-            throw new AssemblyException(
-                "Class " + classname + " is not implementing " + Assembler.class.getName()
-            );
-        }
-        //noinspection unchecked
-        return (Class<? extends Assembler>) clazz;
-    }
-
-    private Assembler createAssemblerInstance( Class<?> assemblerClass )
-        throws AssemblyException
-    {
-        if( !Assembler.class.isAssignableFrom( assemblerClass ) )
-        {
-            throw new AssemblyException(
-                "Class " + assemblerClass + " is not implementing " + Assembler.class.getName()
-            );
-        }
-        try
-        {
-            return (Assembler) assemblerClass.newInstance();
-        }
-        catch( Exception e )
-        {
-            throw new AssemblyException( "Unable to instantiate " + assemblerClass, e );
-        }
-    }
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/builder/package.html b/core/bootstrap/src/main/java/org/qi4j/bootstrap/builder/package.html
deleted file mode 100644
index 663b016..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/builder/package.html
+++ /dev/null
@@ -1,25 +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.
--->
-<html>
-    <body>
-        <h2>Application Builder.</h2>
-        <p>
-            Generic ApplicationBuilder, which simplifies the creation of Application Structure, either by a fluid DSL
-            or from a JSON file.
-        </p>
-    </body>
-</html>
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
deleted file mode 100644
index c8a7b88..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/LayerAssembler.java
+++ /dev/null
@@ -1,29 +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.qi4j.bootstrap.layered;
-
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.LayerAssembly;
-
-public interface LayerAssembler
-{
-    LayerAssembly assemble( LayerAssembly layer )
-        throws AssemblyException;
-}
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
deleted file mode 100644
index b399711..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/LayeredApplicationAssembler.java
+++ /dev/null
@@ -1,212 +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.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 );
-    }
-
-    public ApplicationAssembly assembly()
-    {
-        return assembly;
-    }
-
-    /**
-     * This method is called from the constructor to instantiate the Zest application from the application model.
-     *
-     * <p>
-     * The default implementation simply calls;
-     * </p>
-     * <pre><code>
-     *   application = model.newInstance( qi4j.spi() );
-     * </code></pre>
-     *
-     * @param qi4j  The Zest 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 Zest
-     * 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.
-     * </p>
-     * <pre><code>
-     *
-     * </code></pre>
-     */
-    protected abstract void assembleLayers( ApplicationAssembly assembly )
-        throws AssemblyException;
-}
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
deleted file mode 100644
index def4a46..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/LayeredLayerAssembler.java
+++ /dev/null
@@ -1,86 +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.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 moduleName = createModuleName( modulerAssemblerClass );
-            LayeredApplicationAssembler.setNameIfPresent( modulerAssemblerClass, moduleName );
-            ModuleAssembly module = layer.module( moduleName );
-            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 );
-        }
-    }
-
-    protected String createModuleName( Class<? extends ModuleAssembler> modulerAssemblerClass )
-    {
-        String moduleName = modulerAssemblerClass.getSimpleName();
-        if( moduleName.endsWith( "Module" ) )
-        {
-            moduleName = moduleName.substring( 0, moduleName.length() - 6 ) + " Module";
-        }
-        return moduleName;
-    }
-
-    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 );
-    }
-}
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
deleted file mode 100644
index 17c8765..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/ModuleAssembler.java
+++ /dev/null
@@ -1,29 +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.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;
-}
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/package.html b/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/package.html
deleted file mode 100644
index 60cdec2..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Layered Assembly.</h2>
-    </body>
-</html>
diff --git a/core/bootstrap/src/main/java/org/qi4j/bootstrap/package.html b/core/bootstrap/src/main/java/org/qi4j/bootstrap/package.html
deleted file mode 100644
index 0458761..0000000
--- a/core/bootstrap/src/main/java/org/qi4j/bootstrap/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Assembly and Bootstrap API.</h2>
-    </body>
-</html>
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/AssemblySpecificationTest.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/AssemblySpecificationTest.java
new file mode 100644
index 0000000..a107af2
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/AssemblySpecificationTest.java
@@ -0,0 +1,99 @@
+/*
+ *  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.polygene.bootstrap;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.type.HasTypes;
+import org.junit.Test;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class AssemblySpecificationTest
+{
+    @Test
+    public void givenSingleMatchingTypeWhenFilteringExpectTrue()
+    {
+        Predicate<HasTypes> underTest = AssemblySpecifications.ofAnyType( String.class );
+        HasTypes hasTypes = new MockedHasTyoes( String.class );
+        assertThat( underTest.test( hasTypes ), equalTo(true) );
+    }
+
+    @Test
+    public void givenMultipleMatchingTypeWhenFilteringExpectTrue()
+    {
+        Predicate<HasTypes> underTest = AssemblySpecifications.ofAnyType( Long.class, BigDecimal.class, String.class );
+        HasTypes hasTypes = new MockedHasTyoes( String.class );
+        assertThat( underTest.test( hasTypes ), equalTo(true) );
+    }
+
+    @Test
+    public void givenSingleNonMatchingTypeWhenFilteringExpectFalse()
+    {
+        Predicate<HasTypes> underTest = AssemblySpecifications.ofAnyType( Long.class );
+        HasTypes hasTypes = new MockedHasTyoes( Integer.class );
+        assertThat( underTest.test( hasTypes ), equalTo(false) );
+    }
+
+    @Test
+    public void givenMultipleMatchingTypeWhenFilteringAgainstMultipleExpectTrue()
+    {
+        Predicate<HasTypes> underTest = AssemblySpecifications.ofAnyType( Long.class, Integer.class, BigDecimal.class );
+        HasTypes hasTypes = new MockedHasTyoes( String.class, Integer.class );
+        assertThat( underTest.test( hasTypes ), equalTo(true) );
+    }
+
+    @Test
+    public void givenMultipleNonMatchingTypeWhenFilteringAgainstSingleExpectFalse()
+    {
+        Predicate<HasTypes> underTest = AssemblySpecifications.ofAnyType( Long.class, BigDecimal.class, String.class );
+        HasTypes hasTypes = new MockedHasTyoes( Integer.class );
+        assertThat( underTest.test( hasTypes ), equalTo(false) );
+    }
+
+    @Test
+    public void givenMultipleNonMatchingTypeWhenFilteringAgainstMultipleExpectFalse()
+    {
+        Predicate<HasTypes> underTest = AssemblySpecifications.ofAnyType( Long.class, BigDecimal.class );
+        HasTypes hasTypes = new MockedHasTyoes( String.class, Integer.class );
+        assertThat( underTest.test( hasTypes ), equalTo(false) );
+    }
+
+    private static class MockedHasTyoes
+        implements HasTypes
+    {
+        private final Class[] types;
+
+        public MockedHasTyoes( Class... types)
+        {
+            this.types = types;
+        }
+
+        @Override
+        public Stream<Class<?>> types()
+        {
+            return Arrays.stream(types);
+        }
+    }
+}
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/ClassScannerTest.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/ClassScannerTest.java
new file mode 100644
index 0000000..f257aad
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/ClassScannerTest.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.bootstrap.somepackage.Test2Value;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.apache.polygene.bootstrap.ClassScanner.findClasses;
+import static org.apache.polygene.bootstrap.ClassScanner.matches;
+
+/**
+ * Test and showcase of the ClassScanner assembly utility.
+ */
+public class ClassScannerTest
+{
+    @Test
+    public void testClassScannerFiles()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler singleton = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                new DefaultUnitOfWorkAssembler().assemble( module );
+
+                // Find all classes starting from TestValue, but include only the ones that are named *Value
+                findClasses( TestValue.class ).filter( matches( ".*Value" ) )
+                                              .forEach( module::values );
+            }
+        };
+
+        singleton.module().newValueBuilder( TestValue.class );
+        singleton.module().newValueBuilder( Test2Value.class );
+    }
+
+    @Test
+    public void testClassScannerJar()
+    {
+        Assert.assertEquals( 185, findClasses( Test.class ).count() );
+    }
+}
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/DocumentationSupport.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/DocumentationSupport.java
new file mode 100644
index 0000000..a89629a
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/DocumentationSupport.java
@@ -0,0 +1,442 @@
+/*
+ *  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.polygene.bootstrap;
+
+import java.util.function.Predicate;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.importer.InstanceImporter;
+import org.apache.polygene.api.service.importer.NewObjectImporter;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.Module;
+
+@SuppressWarnings( "ALL" )
+public class DocumentationSupport
+{
+
+    public static Predicate<ObjectAssembly> hasMyTypeSpecification = new Predicate<ObjectAssembly>()
+    {
+
+        public boolean test( ObjectAssembly item )
+        {
+            return item.types().anyMatch( type -> type.equals(String.class) );
+        }
+
+    };
+
+    public static class objects
+            implements Assembler
+    {
+
+        public static class MyObject {}
+
+        // START SNIPPET: objects
+        @Override
+        public void assemble( ModuleAssembly module )
+                throws AssemblyException
+        {
+            module.objects( MyObject.class ).visibleIn( Visibility.layer );
+        }
+        // END SNIPPET: objects
+
+    }
+
+    public static class transients
+            implements Assembler
+    {
+
+        public static interface MyTransient {}
+
+        // START SNIPPET: transients
+        @Override
+        public void assemble( ModuleAssembly module )
+                throws AssemblyException
+        {
+            module.transients( MyTransient.class ).visibleIn( Visibility.layer );
+        }
+        // END SNIPPET: transients
+
+    }
+
+    public static class values
+            implements Assembler
+    {
+
+        public static interface MyValue {}
+
+        // START SNIPPET: values
+        @Override
+        public void assemble( ModuleAssembly module )
+                throws AssemblyException
+        {
+            module.values( MyValue.class ).visibleIn( Visibility.layer );
+        }
+        // END SNIPPET: values
+
+    }
+
+    public static class entities
+            implements Assembler
+    {
+
+        public static interface MyEntity {}
+
+        // START SNIPPET: entities
+        @Override
+        public void assemble( ModuleAssembly module )
+                throws AssemblyException
+        {
+            module.entities( MyEntity.class ).visibleIn( Visibility.layer );
+        }
+        // END SNIPPET: entities
+
+    }
+
+    public static class services
+            implements Assembler
+    {
+
+        public static interface MyService {}
+
+        // START SNIPPET: services
+        @Override
+        public void assemble( ModuleAssembly module )
+                throws AssemblyException
+        {
+            module.services( MyService.class ).visibleIn( Visibility.layer );
+        }
+        // END SNIPPET: services
+
+    }
+
+    public static class taggedServices
+        implements Assembler
+    {
+
+        public static interface MyService {}
+
+        // START SNIPPET: tagged-services
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.services( MyService.class ).taggedWith( "foo", "bar" );
+        }
+        // END SNIPPET: tagged-services
+    }
+
+    public static class importedServices
+        implements Assembler
+    {
+
+        public static class MyService {}
+
+        // START SNIPPET: imported-services
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.importedServices( MyService.class ).
+                importedBy( InstanceImporter.class ).
+                setMetaInfo( new MyService() );
+
+            // OR
+
+            module.objects( MyService.class );
+            module.importedServices( MyService.class ).
+                importedBy( NewObjectImporter.class );
+        }
+        // END SNIPPET: imported-services
+    }
+
+    public static class defaultPropertyValues
+        implements Assembler
+    {
+
+        public interface MyValue { Property<String> foo(); }
+        public interface MyEntity { Property<String> cathedral(); }
+
+        // START SNIPPET: properties-defaults
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.values( MyValue.class );
+            MyValue myValueDefaults = module.forMixin( MyValue.class ).declareDefaults();
+            myValueDefaults.foo().set( "bar" );
+
+            module.entities( MyEntity.class );
+            MyEntity myEntityDefaults = module.forMixin( MyEntity.class ).declareDefaults();
+            myEntityDefaults.cathedral().set( "bazar" );
+        }
+        // END SNIPPET: properties-defaults
+    }
+
+    public static class singleton
+    {
+
+        public interface MyService { }
+        public interface Stuff { }
+
+        void singleton()
+            throws ActivationException, AssemblyException
+        {
+            // START SNIPPET: singleton
+            SingletonAssembler assembler = new SingletonAssembler()
+            {
+
+                @Override
+                public void assemble( ModuleAssembly module )
+                        throws AssemblyException
+                {
+                    module.services( MyService.class ).identifiedBy( "Foo" );
+                    module.services( MyService.class ).identifiedBy( "Bar" );
+                    module.objects( Stuff.class );
+                }
+
+            };
+            Module module = assembler.module();
+            Stuff stuff = module.newObject( Stuff.class );
+            // END SNIPPET: singleton
+        }
+
+    }
+
+    public static class pancake
+    {
+
+        public static class LoginAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
+        public static class MenuAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
+        public static class PerspectivesAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
+        public static class ViewsAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
+        public static class ReportingAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
+        public static class PdfAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
+        public static class BookkeepingAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
+        public static class CashFlowAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
+        public static class BalanceSheetAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
+        public static class PricingAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
+        public static class ProductAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
+
+        private static Energy4Java polygene;
+
+        // START SNIPPET: pancake
+        public static void main( String[] args )
+                throws Exception
+        {
+            polygene = new Energy4Java();
+            Assembler[][][] assemblers = new Assembler[][][]{
+                { // View Layer
+                    { // Login Module
+                        new LoginAssembler()
+                    // :
+                    },
+                    { // Main Workbench Module
+                        new MenuAssembler(),
+                        new PerspectivesAssembler(),
+                        new ViewsAssembler()
+                    // :
+                    },
+                    { // Printing Module
+                        new ReportingAssembler(),
+                        new PdfAssembler()
+                    // :
+                    }
+                },
+                { // Application Layer
+                    { // Accounting Module
+                        new BookkeepingAssembler(),
+                        new CashFlowAssembler(),
+                        new BalanceSheetAssembler()
+                    // :
+                    },
+                    { // Inventory Module
+                        new PricingAssembler(),
+                        new ProductAssembler()
+                    // :
+                    }
+                },
+                { // Domain Layer
+                // :
+                },
+                { // Infrastructure Layer
+                // :
+                }
+            };
+            ApplicationDescriptor model = newApplication( assemblers );
+            Application runtime = model.newInstance( polygene.spi() );
+            runtime.activate();
+        }
+
+        private static ApplicationDescriptor newApplication( final Assembler[][][] assemblers )
+                throws AssemblyException
+        {
+            return polygene.newApplicationModel( new ApplicationAssembler()
+            {
+
+                @Override
+                public ApplicationAssembly assemble( ApplicationAssemblyFactory appFactory )
+                        throws AssemblyException
+                {
+                    return appFactory.newApplicationAssembly( assemblers );
+                }
+
+            } );
+        }
+        // END SNIPPET: pancake
+
+    }
+
+    public static class full
+    {
+
+        public static class CustomerViewComposite{}
+        public static class CustomerEditComposite{}
+        public static class CustomerListViewComposite{}
+        public static class CustomerSearchComposite{}
+        public static class CustomerEntity{}
+        public static class CountryEntity{}
+        public static class AddressValue{}
+        public static class LdapAuthenticationAssembler implements Assembler{ public void assemble( ModuleAssembly module ) throws AssemblyException { } }
+        public static class ThrinkAuthorizationAssembler implements Assembler{ public void assemble( ModuleAssembly module ) throws AssemblyException { } }
+        public static class UserTrackingAuditAssembler implements Assembler{ public void assemble( ModuleAssembly module ) throws AssemblyException { } }
+        public static class NeoAssembler implements Assembler{ NeoAssembler( String path ) {} public void assemble( ModuleAssembly module ) throws AssemblyException { } }
+
+        // START SNIPPET: full
+        private static Energy4Java polygene;
+
+        private static Application application;
+
+        public static void main( String[] args )
+                throws Exception
+        {
+            // Create a Polygene Runtime
+            polygene = new Energy4Java();
+            application = polygene.newApplication( new ApplicationAssembler()
+            {
+
+                @Override
+                public ApplicationAssembly assemble( ApplicationAssemblyFactory appFactory )
+                        throws AssemblyException
+                {
+                    ApplicationAssembly assembly = appFactory.newApplicationAssembly();
+                    buildAssembly( assembly );
+                    return assembly;
+                }
+
+            } );
+            // activate the application
+            application.activate();
+        }
+
+        static void buildAssembly( ApplicationAssembly app ) throws AssemblyException
+        {
+            LayerAssembly webLayer = createWebLayer( app );
+            LayerAssembly domainLayer = createDomainLayer( app );
+            LayerAssembly persistenceLayer = createInfrastructureLayer( app );
+            LayerAssembly authLayer = createAuth2Layer( app );
+            LayerAssembly messagingLayer = createMessagingLayer( app );
+
+            webLayer.uses( domainLayer );
+            domainLayer.uses( authLayer );
+            domainLayer.uses( persistenceLayer );
+            domainLayer.uses( messagingLayer );
+        }
+
+        static LayerAssembly createWebLayer( ApplicationAssembly app ) throws AssemblyException
+        {
+            LayerAssembly layer = app.layer( "web-layer" );
+            createCustomerWebModule( layer );
+            return layer;
+        }
+
+        static LayerAssembly createDomainLayer( ApplicationAssembly app ) throws AssemblyException
+        {
+            LayerAssembly layer = app.layer( "domain-layer" );
+            createCustomerDomainModule( layer );
+            // :
+            // :
+            return layer;
+        }
+
+        static LayerAssembly createInfrastructureLayer( ApplicationAssembly app ) throws AssemblyException
+        {
+            LayerAssembly layer = app.layer( "infrastructure-layer" );
+            createPersistenceModule( layer );
+            return layer;
+        }
+
+        static LayerAssembly createMessagingLayer( ApplicationAssembly app ) throws AssemblyException
+        {
+            LayerAssembly layer = app.layer( "messaging-layer" );
+            createWebServiceModule( layer );
+            createMessagingPersistenceModule( layer );
+            return layer;
+        }
+
+        static LayerAssembly createAuth2Layer( ApplicationAssembly application ) throws AssemblyException
+        {
+            LayerAssembly layer = application.layer( "auth2-layer" );
+            createAuthModule( layer );
+            return layer;
+        }
+
+        static void createCustomerWebModule( LayerAssembly layer ) throws AssemblyException
+        {
+            ModuleAssembly assembly = layer.module( "customer-web-module" );
+            assembly.transients( CustomerViewComposite.class, CustomerEditComposite.class,
+                                 CustomerListViewComposite.class, CustomerSearchComposite.class );
+        }
+
+        static void createCustomerDomainModule( LayerAssembly layer ) throws AssemblyException
+        {
+            ModuleAssembly assembly = layer.module( "customer-domain-module" );
+            assembly.entities( CustomerEntity.class, CountryEntity.class );
+            assembly.values( AddressValue.class );
+        }
+
+        static void createAuthModule( LayerAssembly layer ) throws AssemblyException
+        {
+            ModuleAssembly assembly = layer.module( "auth-module" );
+            new LdapAuthenticationAssembler().assemble( assembly );
+            new ThrinkAuthorizationAssembler().assemble( assembly );
+            new UserTrackingAuditAssembler().assemble( assembly );
+        }
+
+        static void createPersistenceModule( LayerAssembly layer ) throws AssemblyException
+        {
+            ModuleAssembly assembly = layer.module( "persistence-module" );
+            // Someone has created an assembler for the Neo EntityStore
+            new NeoAssembler( "./neostore" ).assemble( assembly );
+        }
+
+        // END SNIPPET: full
+        private static void createWebServiceModule( LayerAssembly layer ) throws AssemblyException
+        {
+        }
+
+        private static void createMessagingPersistenceModule( LayerAssembly layer ) throws AssemblyException
+        {
+        }
+
+    }
+
+}
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/TestValue.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/TestValue.java
new file mode 100644
index 0000000..74274b0
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/TestValue.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ */
+public interface TestValue
+    extends ValueComposite
+{
+}
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/LayeredApplicationAssemblerTest.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/LayeredApplicationAssemblerTest.java
new file mode 100644
index 0000000..484d3e2
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/LayeredApplicationAssemblerTest.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.bootstrap.assembly;
+
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.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.initialize();
+        assembler.start();
+
+        assertThat( assembler.application().name(), equalTo("Test Application") );
+        assertThat( assembler.application().version(), equalTo("1.0.1") );
+    }
+}
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/TestApplication.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/TestApplication.java
new file mode 100644
index 0000000..ef5ca60
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/TestApplication.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.bootstrap.assembly;
+
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.layered.LayeredApplicationAssembler;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.assembly.config.ConfigurationLayer;
+import org.apache.polygene.bootstrap.assembly.connectivity.ConnectivityLayer;
+import org.apache.polygene.bootstrap.assembly.domain.DomainLayer;
+import org.apache.polygene.bootstrap.assembly.infrastructure.InfrastructureLayer;
+import org.apache.polygene.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
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/config/ConfigurationLayer.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/config/ConfigurationLayer.java
new file mode 100644
index 0000000..77e8d05
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/config/ConfigurationLayer.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.bootstrap.assembly.config;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.layered.LayerAssembler;
+import org.apache.polygene.bootstrap.LayerAssembly;
+
+public class ConfigurationLayer implements LayerAssembler
+{
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        return layer;
+    }
+}
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/connectivity/ConnectivityLayer.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/connectivity/ConnectivityLayer.java
new file mode 100644
index 0000000..0b657b2
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/connectivity/ConnectivityLayer.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.bootstrap.assembly.connectivity;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.layered.LayerAssembler;
+import org.apache.polygene.bootstrap.LayerAssembly;
+
+public class ConnectivityLayer implements LayerAssembler
+{
+    public static final String NAME = "Connectivity";
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        return null;
+    }
+}
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/domain/DomainLayer.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/domain/DomainLayer.java
new file mode 100644
index 0000000..5e585dd
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/domain/DomainLayer.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.bootstrap.assembly.domain;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.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;
+    }
+}
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/domain/InvoicingModule.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/domain/InvoicingModule.java
new file mode 100644
index 0000000..ecc83f9
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/domain/InvoicingModule.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.bootstrap.assembly.domain;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+
+public class InvoicingModule
+    implements ModuleAssembler
+{
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        return module;
+    }
+}
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/domain/OrderModule.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/domain/OrderModule.java
new file mode 100644
index 0000000..49a6348
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/domain/OrderModule.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.bootstrap.assembly.domain;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.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
+    {
+    }
+}
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/infrastructure/IndexingModule.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/infrastructure/IndexingModule.java
new file mode 100644
index 0000000..7f3e689
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/infrastructure/IndexingModule.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.bootstrap.assembly.infrastructure;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.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;
+    }
+}
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/infrastructure/InfrastructureLayer.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/infrastructure/InfrastructureLayer.java
new file mode 100644
index 0000000..1507555
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/infrastructure/InfrastructureLayer.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.bootstrap.assembly.infrastructure;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.LayerAssembler;
+import org.apache.polygene.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;
+    }
+}
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/infrastructure/SerializationModule.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/infrastructure/SerializationModule.java
new file mode 100644
index 0000000..44cb35a
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/infrastructure/SerializationModule.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.bootstrap.assembly.infrastructure;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+
+public class SerializationModule
+    implements ModuleAssembler
+{
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module
+    )
+        throws AssemblyException
+    {
+        return null;
+    }
+}
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/infrastructure/StorageModule.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/infrastructure/StorageModule.java
new file mode 100644
index 0000000..b59e2e9
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/infrastructure/StorageModule.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.bootstrap.assembly.infrastructure;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.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;
+    }
+}
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/service/ServiceLayer.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/service/ServiceLayer.java
new file mode 100644
index 0000000..5e55350
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/assembly/service/ServiceLayer.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.bootstrap.assembly.service;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.layered.LayerAssembler;
+import org.apache.polygene.bootstrap.LayerAssembly;
+
+public class ServiceLayer implements LayerAssembler
+{
+    public static final String NAME = "Service";
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        return null;
+    }
+}
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/builder/ApplicationBuilderTest.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/builder/ApplicationBuilderTest.java
new file mode 100644
index 0000000..c7c1e6c
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/builder/ApplicationBuilderTest.java
@@ -0,0 +1,135 @@
+/*
+ *  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.polygene.bootstrap.builder;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.junit.Test;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.polygene.bootstrap.ClassScanner.findClasses;
+import static org.apache.polygene.bootstrap.ClassScanner.matches;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class ApplicationBuilderTest
+{
+    @Test
+    public void givenBuilderUseWhenBuildingApplicationExpectSuccess()
+        throws AssemblyException, ActivationException
+    {
+        ApplicationBuilder builder = new ApplicationBuilder( "Build from API test." );
+        builder.withLayer( "layer1" ).using( "layer2" ).using( "layer3" );
+        builder.withLayer( "layer2" );
+        builder.withLayer( "layer3" )
+               .withModule( "test module" )
+               .withAssemblers( findClasses( getClass() ).filter( matches( ".*ServiceAssembler" ) )
+                                                         .collect( toList() ) );
+        Application application = builder.newApplication();
+        Module module = application.findModule( "layer3", "test module" );
+        TestService service = module.findService( TestService.class ).get();
+        assertThat( service.sayHello(), equalTo( "Hello Polygene!" ) );
+    }
+
+    @Test
+    public void givenJsonWhenBuildingApplicationExpectSuccess()
+        throws ActivationException, AssemblyException
+    {
+        ApplicationBuilder builder = ApplicationBuilder.fromJson( APPLICATION );
+        Application application = builder.newApplication();
+        Module module = application.findModule( "layer3", "test module" );
+        TestService service = module.findService( TestService.class ).get();
+        assertThat( service.sayHello(), equalTo( "Hello Polygene!" ) );
+    }
+
+    @Test
+    public void givenJsonInputStreamWhenBuildingApplicationExpectSuccess()
+        throws IOException, ActivationException, AssemblyException
+    {
+        InputStream input = new ByteArrayInputStream( APPLICATION.getBytes( "UTF-8" ) );
+        ApplicationBuilder builder = ApplicationBuilder.fromJson( input );
+        Application application = builder.newApplication();
+        Module module = application.findModule( "layer3", "test module" );
+        TestService service = module.findService( TestService.class ).get();
+        assertThat( service.sayHello(), equalTo( "Hello Polygene!" ) );
+    }
+
+
+    private static final String APPLICATION =
+        "{\n" +
+        "    \"name\": \"Build from JSON test.\",\n" +
+        "    \"layers\": [\n" +
+        "        {\n" +
+        "            \"name\": \"layer1\",\n" +
+        "            \"uses\": [ \"layer2\", \"layer3\"]\n" +
+        "        },\n" +
+        "        {\n" +
+        "            \"name\": \"layer2\"\n" +
+        "        },\n" +
+        "        {\n" +
+        "            \"name\": \"layer3\",\n" +
+        "            \"modules\" : [\n" +
+        "                {\n" +
+        "                    \"name\" : \"test module\",\n" +
+        "                    \"assemblers\" : [\n" +
+        "                            \"org.apache.polygene.bootstrap.builder.ApplicationBuilderTest$TestServiceAssembler\"\n" +
+        "                    ]\n" +
+        "                }\n" +
+        "            ]\n" +
+        "        }\n" +
+        "    ]\n" +
+        "}";
+
+    public static class TestServiceAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.addServices( TestService.class );
+        }
+    }
+
+    @Mixins( TestService.TestMixin.class )
+    public interface TestService
+    {
+        String sayHello();
+
+        class TestMixin
+            implements TestService
+        {
+
+            @Override
+            public String sayHello()
+            {
+                return "Hello Polygene!";
+            }
+        }
+    }
+}
diff --git a/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/somepackage/Test2Value.java b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/somepackage/Test2Value.java
new file mode 100644
index 0000000..3902d92
--- /dev/null
+++ b/core/bootstrap/src/test/java/org/apache/polygene/bootstrap/somepackage/Test2Value.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.bootstrap.somepackage;
+
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ */
+public interface Test2Value
+    extends ValueComposite
+{
+}
diff --git a/core/bootstrap/src/test/java/org/qi4j/bootstrap/ClassScannerTest.java b/core/bootstrap/src/test/java/org/qi4j/bootstrap/ClassScannerTest.java
deleted file mode 100644
index 33c9e21..0000000
--- a/core/bootstrap/src/test/java/org/qi4j/bootstrap/ClassScannerTest.java
+++ /dev/null
@@ -1,64 +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.qi4j.bootstrap;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.bootstrap.somepackage.Test2Value;
-import org.qi4j.functional.Iterables;
-
-import static org.qi4j.bootstrap.ClassScanner.findClasses;
-import static org.qi4j.bootstrap.ClassScanner.matches;
-import static org.qi4j.functional.Iterables.filter;
-
-/**
- * Test and showcase of the ClassScanner assembly utility.
- */
-public class ClassScannerTest
-{
-    @Test
-    public void testClassScannerFiles()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler singleton = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                // Find all classes starting from TestValue, but include only the ones that are named *Value
-
-                for( Class aClass : filter( matches( ".*Value" ), findClasses( TestValue.class ) ) )
-                {
-                    module.values( aClass );
-                }
-            }
-        };
-
-        singleton.module().newValueBuilder( TestValue.class );
-        singleton.module().newValueBuilder( Test2Value.class );
-    }
-
-    @Test
-    public void testClassScannerJar()
-    {
-        Assert.assertEquals( 138, Iterables.count( findClasses( Test.class ) ) );
-    }
-}
diff --git a/core/bootstrap/src/test/java/org/qi4j/bootstrap/DocumentationSupport.java b/core/bootstrap/src/test/java/org/qi4j/bootstrap/DocumentationSupport.java
deleted file mode 100644
index ae57305..0000000
--- a/core/bootstrap/src/test/java/org/qi4j/bootstrap/DocumentationSupport.java
+++ /dev/null
@@ -1,441 +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.qi4j.bootstrap;
-
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.service.importer.InstanceImporter;
-import org.qi4j.api.service.importer.NewObjectImporter;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.api.structure.Module;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-
-public class DocumentationSupport
-{
-
-    public static Specification<ObjectAssembly> hasMyTypeSpecification = new Specification<ObjectAssembly>()
-    {
-
-        public boolean satisfiedBy( ObjectAssembly item )
-        {
-            return Iterables.toList( item.types() ).contains( String.class );
-        }
-
-    };
-
-    public static class objects
-            implements Assembler
-    {
-
-        public static class MyObject {}
-
-        // START SNIPPET: objects
-        @Override
-        public void assemble( ModuleAssembly module )
-                throws AssemblyException
-        {
-            module.objects( MyObject.class ).visibleIn( Visibility.layer );
-        }
-        // END SNIPPET: objects
-
-    }
-
-    public static class transients
-            implements Assembler
-    {
-
-        public static interface MyTransient {}
-
-        // START SNIPPET: transients
-        @Override
-        public void assemble( ModuleAssembly module )
-                throws AssemblyException
-        {
-            module.transients( MyTransient.class ).visibleIn( Visibility.layer );
-        }
-        // END SNIPPET: transients
-
-    }
-
-    public static class values
-            implements Assembler
-    {
-
-        public static interface MyValue {}
-
-        // START SNIPPET: values
-        @Override
-        public void assemble( ModuleAssembly module )
-                throws AssemblyException
-        {
-            module.values( MyValue.class ).visibleIn( Visibility.layer );
-        }
-        // END SNIPPET: values
-
-    }
-
-    public static class entities
-            implements Assembler
-    {
-
-        public static interface MyEntity {}
-
-        // START SNIPPET: entities
-        @Override
-        public void assemble( ModuleAssembly module )
-                throws AssemblyException
-        {
-            module.entities( MyEntity.class ).visibleIn( Visibility.layer );
-        }
-        // END SNIPPET: entities
-
-    }
-
-    public static class services
-            implements Assembler
-    {
-
-        public static interface MyService {}
-
-        // START SNIPPET: services
-        @Override
-        public void assemble( ModuleAssembly module )
-                throws AssemblyException
-        {
-            module.services( MyService.class ).visibleIn( Visibility.layer );
-        }
-        // END SNIPPET: services
-
-    }
-
-    public static class taggedServices
-        implements Assembler
-    {
-
-        public static interface MyService {}
-
-        // START SNIPPET: tagged-services
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.services( MyService.class ).taggedWith( "foo", "bar" );
-        }
-        // END SNIPPET: tagged-services
-    }
-
-    public static class importedServices
-        implements Assembler
-    {
-
-        public static class MyService {}
-
-        // START SNIPPET: imported-services
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.importedServices( MyService.class ).
-                importedBy( InstanceImporter.class ).
-                setMetaInfo( new MyService() );
-
-            // OR
-
-            module.objects( MyService.class );
-            module.importedServices( MyService.class ).
-                importedBy( NewObjectImporter.class );
-        }
-        // END SNIPPET: imported-services
-    }
-
-    public static class defaultPropertyValues
-        implements Assembler
-    {
-
-        public interface MyValue { Property<String> foo(); }
-        public interface MyEntity { Property<String> cathedral(); }
-
-        // START SNIPPET: properties-defaults
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.values( MyValue.class );
-            MyValue myValueDefaults = module.forMixin( MyValue.class ).declareDefaults();
-            myValueDefaults.foo().set( "bar" );
-
-            module.entities( MyEntity.class );
-            MyEntity myEntityDefaults = module.forMixin( MyEntity.class ).declareDefaults();
-            myEntityDefaults.cathedral().set( "bazar" );
-        }
-        // END SNIPPET: properties-defaults
-    }
-
-    public static class singleton
-    {
-
-        public interface MyService { }
-        public interface Stuff { }
-
-        void singleton()
-            throws ActivationException, AssemblyException
-        {
-            // START SNIPPET: singleton
-            SingletonAssembler assembler = new SingletonAssembler()
-            {
-
-                @Override
-                public void assemble( ModuleAssembly module )
-                        throws AssemblyException
-                {
-                    module.services( MyService.class ).identifiedBy( "Foo" );
-                    module.services( MyService.class ).identifiedBy( "Bar" );
-                    module.objects( Stuff.class );
-                }
-
-            };
-            Module module = assembler.module();
-            Stuff stuff = module.newObject( Stuff.class );
-            // END SNIPPET: singleton
-        }
-
-    }
-
-    public static class pancake
-    {
-
-        public static class LoginAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
-        public static class MenuAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
-        public static class PerspectivesAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
-        public static class ViewsAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
-        public static class ReportingAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
-        public static class PdfAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
-        public static class BookkeepingAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
-        public static class CashFlowAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
-        public static class BalanceSheetAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
-        public static class PricingAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
-        public static class ProductAssembler implements Assembler { public void assemble( ModuleAssembly module ) throws AssemblyException { } }
-
-        private static Energy4Java qi4j;
-
-        // START SNIPPET: pancake
-        public static void main( String[] args )
-                throws Exception
-        {
-            qi4j = new Energy4Java();
-            Assembler[][][] assemblers = new Assembler[][][]{
-                { // View Layer
-                    { // Login Module
-                        new LoginAssembler()
-                    // :
-                    },
-                    { // Main Workbench Module
-                        new MenuAssembler(),
-                        new PerspectivesAssembler(),
-                        new ViewsAssembler()
-                    // :
-                    },
-                    { // Printing Module
-                        new ReportingAssembler(),
-                        new PdfAssembler()
-                    // :
-                    }
-                },
-                { // Application Layer
-                    { // Accounting Module
-                        new BookkeepingAssembler(),
-                        new CashFlowAssembler(),
-                        new BalanceSheetAssembler()
-                    // :
-                    },
-                    { // Inventory Module
-                        new PricingAssembler(),
-                        new ProductAssembler()
-                    // :
-                    }
-                },
-                { // Domain Layer
-                // :
-                },
-                { // Infrastructure Layer
-                // :
-                }
-            };
-            ApplicationDescriptor model = newApplication( assemblers );
-            Application runtime = model.newInstance( qi4j.spi() );
-            runtime.activate();
-        }
-
-        private static ApplicationDescriptor newApplication( final Assembler[][][] assemblers )
-                throws AssemblyException
-        {
-            return qi4j.newApplicationModel( new ApplicationAssembler()
-            {
-
-                @Override
-                public ApplicationAssembly assemble( ApplicationAssemblyFactory appFactory )
-                        throws AssemblyException
-                {
-                    return appFactory.newApplicationAssembly( assemblers );
-                }
-
-            } );
-        }
-        // END SNIPPET: pancake
-
-    }
-
-    public static class full
-    {
-
-        public static class CustomerViewComposite{}
-        public static class CustomerEditComposite{}
-        public static class CustomerListViewComposite{}
-        public static class CustomerSearchComposite{}
-        public static class CustomerEntity{}
-        public static class CountryEntity{}
-        public static class AddressValue{}
-        public static class LdapAuthenticationAssembler implements Assembler{ public void assemble( ModuleAssembly module ) throws AssemblyException { } }
-        public static class ThrinkAuthorizationAssembler implements Assembler{ public void assemble( ModuleAssembly module ) throws AssemblyException { } }
-        public static class UserTrackingAuditAssembler implements Assembler{ public void assemble( ModuleAssembly module ) throws AssemblyException { } }
-        public static class NeoAssembler implements Assembler{ NeoAssembler( String path ) {} public void assemble( ModuleAssembly module ) throws AssemblyException { } }
-
-        // START SNIPPET: full
-        private static Energy4Java qi4j;
-
-        private static Application application;
-
-        public static void main( String[] args )
-                throws Exception
-        {
-            // Create a Zest Runtime
-            qi4j = new Energy4Java();
-            application = qi4j.newApplication( new ApplicationAssembler()
-            {
-
-                @Override
-                public ApplicationAssembly assemble( ApplicationAssemblyFactory appFactory )
-                        throws AssemblyException
-                {
-                    ApplicationAssembly assembly = appFactory.newApplicationAssembly();
-                    buildAssembly( assembly );
-                    return assembly;
-                }
-
-            } );
-            // activate the application
-            application.activate();
-        }
-
-        static void buildAssembly( ApplicationAssembly app ) throws AssemblyException
-        {
-            LayerAssembly webLayer = createWebLayer( app );
-            LayerAssembly domainLayer = createDomainLayer( app );
-            LayerAssembly persistenceLayer = createInfrastructureLayer( app );
-            LayerAssembly authLayer = createAuth2Layer( app );
-            LayerAssembly messagingLayer = createMessagingLayer( app );
-
-            webLayer.uses( domainLayer );
-            domainLayer.uses( authLayer );
-            domainLayer.uses( persistenceLayer );
-            domainLayer.uses( messagingLayer );
-        }
-
-        static LayerAssembly createWebLayer( ApplicationAssembly app ) throws AssemblyException
-        {
-            LayerAssembly layer = app.layer( "web-layer" );
-            createCustomerWebModule( layer );
-            return layer;
-        }
-
-        static LayerAssembly createDomainLayer( ApplicationAssembly app ) throws AssemblyException
-        {
-            LayerAssembly layer = app.layer( "domain-layer" );
-            createCustomerDomainModule( layer );
-            // :
-            // :
-            return layer;
-        }
-
-        static LayerAssembly createInfrastructureLayer( ApplicationAssembly app ) throws AssemblyException
-        {
-            LayerAssembly layer = app.layer( "infrastructure-layer" );
-            createPersistenceModule( layer );
-            return layer;
-        }
-
-        static LayerAssembly createMessagingLayer( ApplicationAssembly app ) throws AssemblyException
-        {
-            LayerAssembly layer = app.layer( "messaging-layer" );
-            createWebServiceModule( layer );
-            createMessagingPersistenceModule( layer );
-            return layer;
-        }
-
-        static LayerAssembly createAuth2Layer( ApplicationAssembly application ) throws AssemblyException
-        {
-            LayerAssembly layer = application.layer( "auth2-layer" );
-            createAuthModule( layer );
-            return layer;
-        }
-
-        static void createCustomerWebModule( LayerAssembly layer ) throws AssemblyException
-        {
-            ModuleAssembly assembly = layer.module( "customer-web-module" );
-            assembly.transients( CustomerViewComposite.class, CustomerEditComposite.class,
-                                 CustomerListViewComposite.class, CustomerSearchComposite.class );
-        }
-
-        static void createCustomerDomainModule( LayerAssembly layer ) throws AssemblyException
-        {
-            ModuleAssembly assembly = layer.module( "customer-domain-module" );
-            assembly.entities( CustomerEntity.class, CountryEntity.class );
-            assembly.values( AddressValue.class );
-        }
-
-        static void createAuthModule( LayerAssembly layer ) throws AssemblyException
-        {
-            ModuleAssembly assembly = layer.module( "auth-module" );
-            new LdapAuthenticationAssembler().assemble( assembly );
-            new ThrinkAuthorizationAssembler().assemble( assembly );
-            new UserTrackingAuditAssembler().assemble( assembly );
-        }
-
-        static void createPersistenceModule( LayerAssembly layer ) throws AssemblyException
-        {
-            ModuleAssembly assembly = layer.module( "persistence-module" );
-            // Someone has created an assembler for the Neo EntityStore
-            new NeoAssembler( "./neostore" ).assemble( assembly );
-        }
-
-        // END SNIPPET: full
-        private static void createWebServiceModule( LayerAssembly layer ) throws AssemblyException
-        {
-        }
-
-        private static void createMessagingPersistenceModule( LayerAssembly layer ) throws AssemblyException
-        {
-        }
-
-    }
-
-}
diff --git a/core/bootstrap/src/test/java/org/qi4j/bootstrap/TestValue.java b/core/bootstrap/src/test/java/org/qi4j/bootstrap/TestValue.java
deleted file mode 100644
index c94b1ff..0000000
--- a/core/bootstrap/src/test/java/org/qi4j/bootstrap/TestValue.java
+++ /dev/null
@@ -1,28 +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.qi4j.bootstrap;
-
-import org.qi4j.api.value.ValueComposite;
-
-/**
- */
-public interface TestValue
-    extends ValueComposite
-{
-}
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
deleted file mode 100644
index b1212ae..0000000
--- a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/LayeredApplicationAssemblerTest.java
+++ /dev/null
@@ -1,41 +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.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") );
-    }
-}
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
deleted file mode 100644
index 03422cc..0000000
--- a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/TestApplication.java
+++ /dev/null
@@ -1,61 +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.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
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
deleted file mode 100644
index 1a35879..0000000
--- a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/config/ConfigurationLayer.java
+++ /dev/null
@@ -1,33 +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.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;
-    }
-}
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
deleted file mode 100644
index 1002d37..0000000
--- a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/connectivity/ConnectivityLayer.java
+++ /dev/null
@@ -1,35 +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.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;
-    }
-}
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
deleted file mode 100644
index 8eac88b..0000000
--- a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/domain/DomainLayer.java
+++ /dev/null
@@ -1,35 +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.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;
-    }
-}
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
deleted file mode 100644
index 62a4640..0000000
--- a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/domain/InvoicingModule.java
+++ /dev/null
@@ -1,35 +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.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;
-    }
-}
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
deleted file mode 100644
index 9e506e3..0000000
--- a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/domain/OrderModule.java
+++ /dev/null
@@ -1,56 +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.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
-    {
-    }
-}
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
deleted file mode 100644
index 437f4f9..0000000
--- a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/IndexingModule.java
+++ /dev/null
@@ -1,44 +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.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;
-    }
-}
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
deleted file mode 100644
index a75ef35..0000000
--- a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/InfrastructureLayer.java
+++ /dev/null
@@ -1,47 +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.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;
-    }
-}
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
deleted file mode 100644
index ad33c16..0000000
--- a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/SerializationModule.java
+++ /dev/null
@@ -1,36 +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.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;
-    }
-}
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
deleted file mode 100644
index 0b51230..0000000
--- a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/StorageModule.java
+++ /dev/null
@@ -1,44 +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.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;
-    }
-}
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
deleted file mode 100644
index 85e29a1..0000000
--- a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/service/ServiceLayer.java
+++ /dev/null
@@ -1,35 +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.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;
-    }
-}
diff --git a/core/bootstrap/src/test/java/org/qi4j/bootstrap/builder/ApplicationBuilderTest.java b/core/bootstrap/src/test/java/org/qi4j/bootstrap/builder/ApplicationBuilderTest.java
deleted file mode 100644
index 56f17f7..0000000
--- a/core/bootstrap/src/test/java/org/qi4j/bootstrap/builder/ApplicationBuilderTest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright 2014 Niclas Hedhman.
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.bootstrap.builder;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import org.json.JSONException;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.bootstrap.ClassScanner.findClasses;
-import static org.qi4j.bootstrap.ClassScanner.matches;
-import static org.qi4j.functional.Iterables.filter;
-
-public class ApplicationBuilderTest
-{
-    @Test
-    public void givenBuilderUseWhenBuildingApplicationExpectSuccess()
-        throws AssemblyException, ActivationException
-    {
-        ApplicationBuilder builder = new ApplicationBuilder( "Build from API test." );
-        builder.withLayer( "layer1" ).using( "layer2" ).using( "layer3" );
-        builder.withLayer( "layer2" );
-        builder.withLayer( "layer3" ).withModule( "test module" ).
-            withAssemblers( filter( matches( ".*ServiceAssembler" ), findClasses( getClass() ) ) );
-        Application application = builder.newApplication();
-        Module module = application.findModule( "layer3", "test module" );
-        TestService service = module.findService( TestService.class ).get();
-        assertThat( service.sayHello(), equalTo( "Hello Zest!" ) );
-    }
-
-    @Test
-    public void givenJsonWhenBuildingApplicationExpectSuccess()
-        throws JSONException, ActivationException, AssemblyException
-    {
-        ApplicationBuilder builder = ApplicationBuilder.fromJson( APPLICATION );
-        Application application = builder.newApplication();
-        Module module = application.findModule( "layer3", "test module" );
-        TestService service = module.findService( TestService.class ).get();
-        assertThat( service.sayHello(), equalTo( "Hello Zest!" ) );
-    }
-
-    @Test
-    public void givenJsonInputStreamWhenBuildingApplicationExpectSuccess()
-        throws IOException, JSONException, ActivationException, AssemblyException
-    {
-        InputStream input = new ByteArrayInputStream( APPLICATION.getBytes( "UTF-8" ) );
-        ApplicationBuilder builder = ApplicationBuilder.fromJson( input );
-        Application application = builder.newApplication();
-        Module module = application.findModule( "layer3", "test module" );
-        TestService service = module.findService( TestService.class ).get();
-        assertThat( service.sayHello(), equalTo( "Hello Zest!" ) );
-    }
-
-
-    private static final String APPLICATION =
-        "{\n" +
-        "    \"name\": \"Build from JSON test.\",\n" +
-        "    \"layers\": [\n" +
-        "        {\n" +
-        "            \"name\": \"layer1\",\n" +
-        "            \"uses\": [ \"layer2\", \"layer3\"]\n" +
-        "        },\n" +
-        "        {\n" +
-        "            \"name\": \"layer2\"\n" +
-        "        },\n" +
-        "        {\n" +
-        "            \"name\": \"layer3\",\n" +
-        "            \"modules\" : [\n" +
-        "                {\n" +
-        "                    \"name\" : \"test module\",\n" +
-        "                    \"assemblers\" : [\n" +
-        "                            \"org.qi4j.bootstrap.builder.ApplicationBuilderTest$TestServiceAssembler\"\n" +
-        "                    ]\n" +
-        "                }\n" +
-        "            ]\n" +
-        "        }\n" +
-        "    ]\n" +
-        "}";
-
-    public static class TestServiceAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.addServices( TestService.class );
-        }
-    }
-
-    @Mixins( TestService.TestMixin.class )
-    public interface TestService
-    {
-        String sayHello();
-
-        class TestMixin
-            implements TestService
-        {
-
-            @Override
-            public String sayHello()
-            {
-                return "Hello Zest!";
-            }
-        }
-    }
-}
diff --git a/core/bootstrap/src/test/java/org/qi4j/bootstrap/somepackage/Test2Value.java b/core/bootstrap/src/test/java/org/qi4j/bootstrap/somepackage/Test2Value.java
deleted file mode 100644
index 5b0d6c9..0000000
--- a/core/bootstrap/src/test/java/org/qi4j/bootstrap/somepackage/Test2Value.java
+++ /dev/null
@@ -1,28 +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.qi4j.bootstrap.somepackage;
-
-import org.qi4j.api.value.ValueComposite;
-
-/**
- */
-public interface Test2Value
-    extends ValueComposite
-{
-}
diff --git a/core/functional/build.gradle b/core/functional/build.gradle
deleted file mode 100644
index e8408b3..0000000
--- a/core/functional/build.gradle
+++ /dev/null
@@ -1,24 +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.
- */
-
-jar { manifest { name = "Apache Zest™ Functional"}}
-
-dependencies {
-
-}
diff --git a/core/functional/dev-status.xml b/core/functional/dev-status.xml
deleted file mode 100644
index ed93800..0000000
--- a/core/functional/dev-status.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
-  <status>
-    <codebase>beta</codebase>
-    <!--none,early,beta,stable,mature-->
-    <documentation>good</documentation>
-    <!-- none, brief, good, complete -->
-    <unittests>good</unittests>
-    <!-- none, some, good, complete -->
-  </status>
-  <licenses>
-    <license>ALv2</license>
-  </licenses>
-</module>
diff --git a/core/functional/src/docs/functional.txt b/core/functional/src/docs/functional.txt
deleted file mode 100644
index 461e091..0000000
--- a/core/functional/src/docs/functional.txt
+++ /dev/null
@@ -1,79 +0,0 @@
-//////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.
-//////////////////////
-
-[[core-functional,Function]]
-= Core Functional API =
-
-[devstatus]
---------------
-source=core/functional/dev-status.xml
---------------
-
-The Zest™ Core Functional API is a generic package to work with Iterables in a "functional programming language" style.
-
-This package is completely independent of everything else in Zest™ and may be used on its own in any kind of environment
-such as Spring or Java EE applications.
-
-include::../../build/docs/buildinfo/artifact.txt[]
-
-== First Example ==
-Let's say that you have an Iterable of Integers and you want to sum them all up. Most people would create a loop and
-sum it all up in something like this;
-
-[snippet,java]
------------
-source=core/functional/src/test/java/org/qi4j/functional/docsupport/FunctionalDocs.java
-tag=func1
------------
-
-With the Zest™ Core Functional API, you go about it in a different way. The code ends up looking like this;
-
-[snippet,java]
------------
-source=core/functional/src/test/java/org/qi4j/functional/docsupport/FunctionalDocs.java
-tag=func2
------------
-
-And this is just the tip of the iceberg.
-
-== The Big Picture ==
-
-The Zest™ Core Functional API are divided a handful of powerful concepts, especially when used together;
-
-   * *Iterables* - many methods to deal with Iterable data, so that the loops in your programs can largely be removed.
-
-   * *Functions* - f(x) and f(x,y) are well-know from mathematics and used in functional programming languages. Zest™ is
-     not capable of introducing lambda calculus due to limitations in Java itself, but we can simulate a lot to allow
-     people to create more readable code.
-
-   * *Specification* - A simple concept to define the bounds of data. This is used for filtering, query and many other
-     higher level abstractions.
-
-   * *Visitor* pattern - A way to be handed the items in a collection, without having the loops. This could be for
-     end result handling, distribution of intermediary values, and many other things.
-
-
-== Specification ==
-TODO
-
-== Function ==
-TODO
-
-== Visitor Pattern ==
-TODO
-
-== Iterables ==
-TODO
-
diff --git a/core/functional/src/docs/reference/ref-functional.txt b/core/functional/src/docs/reference/ref-functional.txt
deleted file mode 100644
index fc7aac6..0000000
--- a/core/functional/src/docs/reference/ref-functional.txt
+++ /dev/null
@@ -1,18 +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.
-///////////////////////////////////////////////////////////////
diff --git a/core/functional/src/main/java/org/qi4j/functional/ForEach.java b/core/functional/src/main/java/org/qi4j/functional/ForEach.java
deleted file mode 100644
index c2bbe3e..0000000
--- a/core/functional/src/main/java/org/qi4j/functional/ForEach.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.functional;
-
-import java.util.Iterator;
-
-/**
- * When using Iterables with map() and filter() the code often reads "in reverse", with the first item last in the code.
- * Example: Iterables.map(function,Iterables.filter(specification, iterable))
- * <p>
- * This ForEach class reverses that order and makes the code more readable, and allows easy application of visitors on iterables.
- * </p>
- * <p>
- * Example: forEach(iterable).filter(specification).map(function).visit(visitor)
- * </p>
- */
-public final class ForEach<T>
-    implements Iterable<T>
-{
-    public static <T> ForEach<T> forEach( Iterable<T> iterable )
-    {
-        return new ForEach<>( iterable );
-    }
-
-    private final Iterable<T> iterable;
-
-    public ForEach( Iterable<T> iterable )
-    {
-        this.iterable = iterable;
-    }
-
-    @Override
-    public Iterator<T> iterator()
-    {
-        return iterable.iterator();
-    }
-
-    public ForEach<T> filter( Specification<? super T> specification )
-    {
-        return new ForEach<>( Iterables.filter( specification, iterable ) );
-    }
-
-    public <TO> ForEach<TO> map( Function<? /* super T */, TO> function )
-    {
-        return new ForEach<>( Iterables.map( function, iterable ) );
-    }
-
-    public <TO> ForEach<TO> flatten()
-    {
-        Iterable<Iterable<TO>> original = iterable();
-        Iterable<TO> iterable1 = Iterables.flattenIterables( original );
-        return new ForEach<>( iterable1 );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private <TO> Iterable<Iterable<TO>> iterable()
-    {
-        return (Iterable<Iterable<TO>>) iterable;
-    }
-
-    public T last()
-    {
-        T lastItem = null;
-        for( T item : iterable )
-        {
-            lastItem = item;
-        }
-        return lastItem;
-    }
-
-    public <ThrowableType extends Throwable> boolean visit( final Visitor<T, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        for( T item : iterable )
-        {
-            if( !visitor.visit( item ) )
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-}
diff --git a/core/functional/src/main/java/org/qi4j/functional/Function.java b/core/functional/src/main/java/org/qi4j/functional/Function.java
deleted file mode 100644
index 3edd3f1..0000000
--- a/core/functional/src/main/java/org/qi4j/functional/Function.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.functional;
-
-/**
- * Generic function interface to map from one type to another.
- *
- * This can be used with the Iterables methods to transform lists of objects.
- *
- * @param <From>
- * @param <To>
- */
-public interface Function<From, To>
-{
-    /**
-     * Map a single item from one type to another
-     *
-     * @param from the input item
-     *
-     * @return the mapped item
-     */
-    To map( From from );
-}
diff --git a/core/functional/src/main/java/org/qi4j/functional/Function2.java b/core/functional/src/main/java/org/qi4j/functional/Function2.java
deleted file mode 100644
index 7803965..0000000
--- a/core/functional/src/main/java/org/qi4j/functional/Function2.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.functional;
-
-/**
- * Generic function interface to map from two parameters to a third.
- *
- * This can be used with the Iterables methods to transform lists of objects.
- */
-public interface Function2<First, Second, To>
-{
-    /**
-     * Map a single item from one type to another
-     *
-     * @param first
-     * @param second
-     *
-     * @return the mapped item
-     */
-    To map( First first, Second second );
-}
diff --git a/core/functional/src/main/java/org/qi4j/functional/Functions.java b/core/functional/src/main/java/org/qi4j/functional/Functions.java
deleted file mode 100644
index bf86845..0000000
--- a/core/functional/src/main/java/org/qi4j/functional/Functions.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.functional;
-
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Utility functions. Combine these with methods in Iterables, for example. See FunctionsTest for usages.
- */
-public final class Functions
-{
-    public static <A, B, C> Function2<Function<? super B, C>, Function<A, B>, Function<A, C>> compose()
-    {
-        return new Function2<Function<? super B, C>, Function<A, B>, Function<A, C>>()
-        {
-            @Override
-            public Function<A, C> map( Function<? super B, C> bcFunction, Function<A, B> abFunction )
-            {
-                return compose( bcFunction, abFunction );
-            }
-        };
-    }
-
-    /**
-     * compose(F1(M,T),F2(F,M)) = F1(F2(F)) -&gt; T
-     *
-     * @param outer The outer/encapsulating function
-     * @param inner The inner/encapsulated function
-     *
-     * @return A function that is a composition of an outer and inner function.
-     */
-    public static <FROM, MIDDLE, TO> Function<FROM, TO> compose( final Function<? super MIDDLE, TO> outer,
-                                                                 final Function<FROM, MIDDLE> inner
-    )
-    {
-        return new Function<FROM, TO>()
-        {
-            @Override
-            public TO map( FROM from )
-            {
-                return outer.map( inner.map( from ) );
-            }
-        };
-    }
-
-    public static <TO, FROM extends TO> Function<FROM, TO> identity()
-    {
-        return new Function<FROM, TO>()
-        {
-            @Override
-            public TO map( FROM from )
-            {
-                return from;
-            }
-        };
-    }
-
-    public static <FROM, TO> Function<FROM, TO> fromMap( final Map<FROM, TO> map )
-    {
-        return new Function<FROM, TO>()
-        {
-            @Override
-            public TO map( FROM from )
-            {
-                return map.get( from );
-            }
-        };
-    }
-
-    public static <T> Function<T, T> withDefault( final T defaultValue )
-    {
-        return new Function<T, T>()
-        {
-            @Override
-            public T map( T from )
-            {
-                if( from == null )
-                {
-                    return defaultValue;
-                }
-                else
-                {
-                    return from;
-                }
-            }
-        };
-    }
-
-    public static Function<Number, Long> longSum()
-    {
-        return new Function<Number, Long>()
-        {
-            long sum;
-
-            @Override
-            public Long map( Number number )
-            {
-                sum += number.longValue();
-                return sum;
-            }
-        };
-    }
-
-    public static Function<Number, Integer> intSum()
-    {
-        return new Function<Number, Integer>()
-        {
-            int sum;
-
-            @Override
-            public Integer map( Number number )
-            {
-                sum += number.intValue();
-                return sum;
-            }
-        };
-    }
-
-    /**
-     * Count the number of items in an iterable that matches a given specification.
-     *
-     * Sample usage: last( map( count( in( "X" ) ), iterable( "X","Y","X","X","Y" ) ) )
-     * Returns: 3
-     *
-     * @param specification The items that adhere to the Specification is counted.
-     * @param <T> The type of the items.
-     *
-     * @return A Function that can count items adhering to a Specification.
-     */
-    public static <T> Function<T, Integer> count( final Specification<T> specification )
-    {
-        return new Function<T, Integer>()
-        {
-            int count;
-
-            @Override
-            public Integer map( T item )
-            {
-                if( specification.satisfiedBy( item ) )
-                {
-                    count++;
-                }
-
-                return count;
-            }
-        };
-    }
-
-    /**
-     * Find out the index of an item matching a given specification in an iterable.
-     * Returns -1 if it is not found.
-     *
-     * @param specification The Specification that specifies what to look for.
-     * @param <T> The type of the items.
-     *
-     * @return A Function that will provide the 'index' where the Specifcation is fulfilled. The Function will
-     * return -1 if the current item doesn't fulfill the Specification.
-     */
-    public static <T> Function<T, Integer> indexOf( final Specification<T> specification )
-    {
-        return new Function<T, Integer>()
-        {
-            int index = -1;
-            int current = 0;
-
-            @Override
-            public Integer map( T item )
-            {
-                if( index == -1 && specification.satisfiedBy( item ) )
-                {
-                    index = current;
-                }
-
-                current++;
-
-                return index;
-            }
-        };
-    }
-
-    /**
-     * Find out the index of an item in an iterable.
-     *
-     * @param item The item to look for.
-     * @param iterable The Iterable to search.
-     * @param <T> The type of the items.
-     *
-     * @return The index in the Iterable where the item is located.
-     */
-    @SuppressWarnings( "unchecked" )
-    public static <T> int indexOf( T item, Iterable<T> iterable )
-    {
-        return Iterables.first( Iterables.filter( Specifications.not( Specifications.in( -1 ) ),
-                                                  Iterables.map( indexOf( Specifications.in( item ) ), iterable ) ) );
-    }
-
-    /**
-     * Only apply given function on objects that satisfies the given specification.
-     *
-     * @param specification A Specification that specifies what should be included in the filtered result.
-     * @param function The function to be applied to items that fulfills the Specification
-     * @param <T> The type of the items.
-     *
-     * @return A Function that performs the filter operation when applied to Iterables.
-     */
-    public static <T> Function<T, T> filteredMap( final Specification<T> specification, final Function<T, T> function )
-    {
-        return new Function<T, T>()
-        {
-            @Override
-            public T map( T from )
-            {
-                return specification.satisfiedBy( from ) ? function.map( from ) : from;
-            }
-        };
-    }
-
-    /**
-     * Creates a comparator that takes a function as input. The returned comparator will use the
-     * function once for each item in the list to be sorted by Collections.sort.
-     *
-     * This should be used if the function to generate the sort key from an object is expensive, so
-     * that it is not done many times for each item in a list.
-     *
-     * @param comparableFunction The Function that the Comparator will delegate to.
-     * @param <T>                The generic type to be used.
-     *
-     * @return A comparator that uses a Function for the compare operation.
-     */
-    @SuppressWarnings( "raw" )
-    public static <T> Comparator<T> comparator( final Function<T, Comparable> comparableFunction )
-    {
-        return new Comparator<T>()
-        {
-            Map<T, Comparable> compareKeys = new HashMap<>();
-
-            @Override
-            @SuppressWarnings( "unchecked" )
-            public int compare( T o1, T o2 )
-            {
-                Comparable key1 = compareKeys.get( o1 );
-                if( key1 == null )
-                {
-                    key1 = comparableFunction.map( o1 );
-                    compareKeys.put( o1, key1 );
-                }
-
-                Comparable key2 = compareKeys.get( o2 );
-                if( key2 == null )
-                {
-                    key2 = comparableFunction.map( o2 );
-                    compareKeys.put( o2, key2 );
-                }
-
-                return key1.compareTo( key2 );
-            }
-        };
-    }
-
-    private Functions()
-    {
-    }
-}
diff --git a/core/functional/src/main/java/org/qi4j/functional/HierarchicalVisitor.java b/core/functional/src/main/java/org/qi4j/functional/HierarchicalVisitor.java
deleted file mode 100644
index 1d328cb..0000000
--- a/core/functional/src/main/java/org/qi4j/functional/HierarchicalVisitor.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.functional;
-
-/**
- * Visitor to visit hierarchies.
- */
-public interface HierarchicalVisitor<NODE, LEAF, ThrowableType extends Throwable> extends Visitor<LEAF, ThrowableType>
-{
-    /**
-     * Enter an instance of T
-     *
-     * @param visited the visited instance which is now entered
-     *
-     * @return true if the visitor pattern should continue, false if it should be aborted for this level
-     *
-     * @throws ThrowableType if an exception occurred during processing. Any client call that initiated the visiting should
-     *                       get the exception in order to handle it properly.
-     */
-    boolean visitEnter( NODE visited )
-        throws ThrowableType;
-
-    /**
-     * Leave an instance of T
-     *
-     * @param visited the visited instance which is now left
-     *
-     * @return true if the visitor pattern should continue, false if it should be aborted for the level of this node
-     *
-     * @throws ThrowableType if an exception occurred during processing. Any client call that initiated the visiting should
-     *                       get the exception in order to handle it properly.
-     */
-    boolean visitLeave( NODE visited )
-        throws ThrowableType;
-
-    @Override
-    boolean visit( LEAF visited )
-        throws ThrowableType;
-}
diff --git a/core/functional/src/main/java/org/qi4j/functional/HierarchicalVisitorAdapter.java b/core/functional/src/main/java/org/qi4j/functional/HierarchicalVisitorAdapter.java
deleted file mode 100644
index 2023655..0000000
--- a/core/functional/src/main/java/org/qi4j/functional/HierarchicalVisitorAdapter.java
+++ /dev/null
@@ -1,47 +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.qi4j.functional;
-
-/**
- * Generic Hierarchical Visitor interface.
- */
-public class HierarchicalVisitorAdapter<NODE, LEAF, ThrowableType extends Throwable>
-    implements HierarchicalVisitor<NODE, LEAF, ThrowableType>
-{
-    @Override
-    public boolean visitEnter( NODE visited )
-        throws ThrowableType
-    {
-        return true;
-    }
-
-    @Override
-    public boolean visitLeave( NODE visited )
-        throws ThrowableType
-    {
-        return true;
-    }
-
-    @Override
-    public boolean visit( LEAF visited )
-        throws ThrowableType
-    {
-        return true;
-    }
-}
diff --git a/core/functional/src/main/java/org/qi4j/functional/Iterables.java b/core/functional/src/main/java/org/qi4j/functional/Iterables.java
deleted file mode 100644
index ec5ae43..0000000
--- a/core/functional/src/main/java/org/qi4j/functional/Iterables.java
+++ /dev/null
@@ -1,939 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.functional;
-
-import java.lang.reflect.Array;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-/**
- * Utility methods for working with Iterables. See test for examples of how to use.
- */
-public final class Iterables
-{
-    @SuppressWarnings( "raw" )
-    private static final Iterable EMPTY = new Iterable()
-    {
-        Iterator iterator = new Iterator()
-        {
-            @Override
-            public boolean hasNext()
-            {
-                return false;
-            }
-
-            @Override
-            public Object next()
-            {
-                throw new NoSuchElementException();
-            }
-
-            @Override
-            public void remove()
-            {
-            }
-        };
-
-        @Override
-        public Iterator iterator()
-        {
-            return iterator;
-        }
-    };
-
-    @SuppressWarnings( "unchecked" )
-    public static <T> Iterable<T> empty()
-    {
-        return EMPTY;
-    }
-
-    public static <T> Iterable<T> constant( final T item )
-    {
-        return new Iterable<T>()
-        {
-            @Override
-            public Iterator<T> iterator()
-            {
-                return new Iterator<T>()
-                {
-                    @Override
-                    public boolean hasNext()
-                    {
-                        return true;
-                    }
-
-                    @Override
-                    public T next()
-                    {
-                        return item;
-                    }
-
-                    @Override
-                    public void remove()
-                    {
-                    }
-                };
-            }
-        };
-    }
-
-    public static <T> Iterable<T> limit( final int limitItems, final Iterable<T> iterable )
-    {
-        return new Iterable<T>()
-        {
-            @Override
-            public Iterator<T> iterator()
-            {
-                final Iterator<T> iterator = iterable.iterator();
-
-                return new Iterator<T>()
-                {
-                    int count;
-
-                    @Override
-                    public boolean hasNext()
-                    {
-                        return count < limitItems && iterator.hasNext();
-                    }
-
-                    @Override
-                    public T next()
-                    {
-                        count++;
-                        return iterator.next();
-                    }
-
-                    @Override
-                    public void remove()
-                    {
-                        iterator.remove();
-                    }
-                };
-            }
-        };
-    }
-
-    public static <T> Iterable<T> unique( final Iterable<T> iterable )
-    {
-        return new Iterable<T>()
-        {
-            @Override
-            public Iterator<T> iterator()
-            {
-                final Iterator<T> iterator = iterable.iterator();
-
-                return new Iterator<T>()
-                {
-                    private final Set<T> items = new HashSet<>();
-                    private T nextItem;
-
-                    @Override
-                    public boolean hasNext()
-                    {
-                        while( iterator.hasNext() )
-                        {
-                            nextItem = iterator.next();
-                            if( items.add( nextItem ) )
-                            {
-                                return true;
-                            }
-                        }
-
-                        return false;
-                    }
-
-                    @Override
-                    public T next()
-                    {
-                        if( nextItem == null && !hasNext() )
-                        {
-                            throw new NoSuchElementException();
-                        }
-
-                        return nextItem;
-                    }
-
-                    @Override
-                    public void remove()
-                    {
-                    }
-                };
-            }
-        };
-    }
-
-    public static <T, C extends Collection<T>> C addAll( C collection, Iterable<? extends T> iterable )
-    {
-        for( T item : iterable )
-        {
-            collection.add( item );
-        }
-        return collection;
-    }
-
-    public static long count( Iterable<?> iterable )
-    {
-        long c = 0;
-        for( Object anIterable : iterable )
-        {
-            c++;
-        }
-        return c;
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public static <X> Iterable<X> filter( Specification<? /* super X*/> specification, Iterable<X> i )
-    {
-        return new FilterIterable<>( i, (Specification<? super X>) specification );
-    }
-
-    public static <X> X first( Iterable<X> i )
-    {
-        Iterator<X> iter = i.iterator();
-        if( iter.hasNext() )
-        {
-            return iter.next();
-        }
-        else
-        {
-            return null;
-        }
-    }
-
-    public static <X> X single( Iterable<X> i )
-    {
-        Iterator<X> iter = i.iterator();
-        if( iter.hasNext() )
-        {
-            X result = iter.next();
-
-            if( iter.hasNext() )
-            {
-                throw new IllegalArgumentException( "More than one element in iterable" );
-            }
-
-            return result;
-        }
-        else
-        {
-            throw new IllegalArgumentException( "No elements in iterable" );
-        }
-    }
-
-    public static <X> Iterable<X> skip( final int skip, final Iterable<X> iterable )
-    {
-        return new Iterable<X>()
-        {
-            @Override
-            public Iterator<X> iterator()
-            {
-                Iterator<X> iterator = iterable.iterator();
-
-                for( int i = 0; i < skip; i++ )
-                {
-                    if( iterator.hasNext() )
-                    {
-                        iterator.next();
-                    }
-                    else
-                    {
-                        return Iterables.<X>empty().iterator();
-                    }
-                }
-
-                return iterator;
-            }
-        };
-    }
-
-    public static <X> X last( Iterable<X> i )
-    {
-        Iterator<X> iter = i.iterator();
-        X item = null;
-        while( iter.hasNext() )
-        {
-            item = iter.next();
-        }
-
-        return item;
-    }
-
-    public static <X> Iterable<X> reverse( Iterable<X> iterable )
-    {
-        List<X> list = toList( iterable );
-        Collections.reverse( list );
-        return list;
-    }
-
-    public static <T> boolean matchesAny( Specification<? super T> specification, Iterable<T> iterable )
-    {
-        boolean result = false;
-
-        for( T item : iterable )
-        {
-            if( ( (Specification<? super T>) specification ).satisfiedBy( item ) )
-            {
-                result = true;
-                break;
-            }
-        }
-
-        return result;
-    }
-
-    public static <T> boolean matchesAll( Specification<? super T> specification, Iterable<T> iterable )
-    {
-        boolean result = true;
-        for( T item : iterable )
-        {
-            if( !specification.satisfiedBy( item ) )
-            {
-                result = false;
-            }
-        }
-
-        return result;
-    }
-
-    public static <X> Iterable<X> flatten( Iterable<?>... multiIterator )
-    {
-        return new FlattenIterable<>( Iterables.<Iterable<X>>cast( Arrays.asList( multiIterator ) ) );
-    }
-
-    public static <X, I extends Iterable<? extends X>> Iterable<X> flattenIterables( Iterable<I> multiIterator )
-    // public static <X> Iterable<X> flattenIterables( Iterable<Iterable<?>> multiIterator )
-    {
-        return new FlattenIterable<>( Iterables.<Iterable<X>>cast( multiIterator ) );
-    }
-
-    @SafeVarargs
-    public static <T> Iterable<T> mix( final Iterable<T>... iterables )
-    {
-        return new Iterable<T>()
-        {
-            @Override
-            public Iterator<T> iterator()
-            {
-                final Iterable<Iterator<T>> iterators = toList( map( new Function<Iterable<T>, Iterator<T>>()
-                {
-                    @Override
-                    public Iterator<T> map( Iterable<T> iterable )
-                    {
-                        return iterable.iterator();
-                    }
-                }, Iterables.iterable( iterables ) ) );
-
-                return new Iterator<T>()
-                {
-                    Iterator<Iterator<T>> iterator;
-
-                    Iterator<T> iter;
-
-                    @Override
-                    public boolean hasNext()
-                    {
-                        for( Iterator<T> iterator : iterators )
-                        {
-                            if( iterator.hasNext() )
-                            {
-                                return true;
-                            }
-                        }
-
-                        return false;
-                    }
-
-                    @Override
-                    public T next()
-                    {
-                        if( iterator == null )
-                        {
-                            iterator = iterators.iterator();
-                        }
-
-                        while( iterator.hasNext() )
-                        {
-                            iter = iterator.next();
-
-                            if( iter.hasNext() )
-                            {
-                                return iter.next();
-                            }
-                        }
-
-                        iterator = null;
-
-                        return next();
-                    }
-
-                    @Override
-                    public void remove()
-                    {
-                        if( iter != null )
-                        {
-                            iter.remove();
-                        }
-                    }
-                };
-            }
-        };
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public static <FROM, TO> Iterable<TO> map( Function<? /* super FROM */, TO> function, Iterable<FROM> from )
-    {
-        return new MapIterable<>( from, (Function<FROM, TO>) function );
-    }
-
-    public static <T> Iterable<T> iterable( Enumeration<T> enumeration )
-    {
-        List<T> list = new ArrayList<>();
-        while( enumeration.hasMoreElements() )
-        {
-            T item = enumeration.nextElement();
-            list.add( item );
-        }
-
-        return list;
-    }
-
-    @SafeVarargs
-    public static <T> Iterable<T> iterable( T... items )
-    {
-        return Arrays.asList( items );
-    }
-
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public static <T> Iterable<T> cast( Iterable<?> iterable )
-    {
-        Iterable iter = iterable;
-        return iter;
-    }
-
-    public static <FROM, TO> Function<FROM, TO> cast()
-    {
-        return new Function<FROM, TO>()
-        {
-            @Override
-            @SuppressWarnings( "unchecked" )
-            public TO map( FROM from )
-            {
-                return (TO) from;
-            }
-        };
-    }
-
-    public static <FROM, TO> TO fold( Function<? super FROM, TO> function, Iterable<? extends FROM> i )
-    {
-        return last( map( function, i ) );
-    }
-
-    public static <T> Iterable<T> prepend( final T item, final Iterable<T> iterable )
-    {
-        return new Iterable<T>()
-        {
-            @Override
-            public Iterator<T> iterator()
-            {
-                return new Iterator<T>()
-                {
-                    T first = item;
-                    Iterator<T> iterator;
-
-                    @Override
-                    public boolean hasNext()
-                    {
-                        if( first != null )
-                        {
-                            return true;
-                        }
-                        else
-                        {
-                            if( iterator == null )
-                            {
-                                iterator = iterable.iterator();
-                            }
-                        }
-
-                        return iterator.hasNext();
-                    }
-
-                    @Override
-                    public T next()
-                    {
-                        if( first != null )
-                        {
-                            try
-                            {
-                                return first;
-                            }
-                            finally
-                            {
-                                first = null;
-                            }
-                        }
-                        else
-                        {
-                            return iterator.next();
-                        }
-                    }
-
-                    @Override
-                    public void remove()
-                    {
-                    }
-                };
-            }
-        };
-    }
-
-    public static <T> Iterable<T> append( final T item, final Iterable<T> iterable )
-    {
-        return new Iterable<T>()
-        {
-            @Override
-            public Iterator<T> iterator()
-            {
-                final Iterator<T> iterator = iterable.iterator();
-
-                return new Iterator<T>()
-                {
-                    T last = item;
-
-                    @Override
-                    public boolean hasNext()
-                    {
-                        if( iterator.hasNext() )
-                        {
-                            return true;
-                        }
-                        else
-                        {
-                            return last != null;
-                        }
-                    }
-
-                    @Override
-                    public T next()
-                    {
-                        if( iterator.hasNext() )
-                        {
-                            return iterator.next();
-                        }
-                        else
-                        {
-                            try
-                            {
-                                return last;
-                            }
-                            finally
-                            {
-                                last = null;
-                            }
-                        }
-                    }
-
-                    @Override
-                    public void remove()
-                    {
-                    }
-                };
-            }
-        };
-    }
-
-    @SafeVarargs
-    public static <T> Iterable<T> debug( String format,
-                                         final Iterable<T> iterable,
-                                         final Function<T, String>... functions
-    )
-    {
-        final MessageFormat msgFormat = new MessageFormat( format );
-
-        return map( new Function<T, T>()
-        {
-            @Override
-            public T map( T t )
-            {
-                if( functions.length != 0 )
-                {
-                    String[] mapped = new String[ functions.length ];
-                    for( int i = 0; i < functions.length; i++ )
-                    {
-                        Function<T, String> function = functions[i];
-                        mapped[i] = function.map( t );
-                    }
-                }
-                return t;
-            }
-        }, iterable );
-    }
-
-    public static <T> Iterable<T> cache( Iterable<T> iterable )
-    {
-        return new CacheIterable<>( iterable );
-    }
-
-    public static <T> String toString( Iterable<T> iterable )
-    {
-        return toString( iterable, new Function<T, String>()
-        {
-            @Override
-            public String map( T t )
-            {
-                return t == null ? "[null]" : t.toString();
-            }
-        }, "," );
-    }
-
-    public static <T> String toString( Iterable<T> iterable, Function<T, String> toStringFunction, String separator )
-    {
-        StringBuilder builder = new StringBuilder();
-        boolean first = true;
-        for( T item : iterable )
-        {
-            if( !first )
-            {
-                builder.append( separator );
-            }
-            builder.append( toStringFunction.map( item ) );
-            first = false;
-        }
-        return builder.toString();
-    }
-
-    public static <T> List<T> toList( Iterable<T> iterable )
-    {
-        return addAll( new ArrayList<T>(), iterable );
-    }
-
-    public static Object[] toArray( Iterable<Object> iterable )
-    {
-        return toArray( Object.class, iterable );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public static <T> T[] toArray( Class<T> componentType, Iterable<T> iterable )
-    {
-        if( iterable == null )
-        {
-            return null;
-        }
-        List<T> list = toList( iterable );
-        return list.toArray( (T[]) Array.newInstance( componentType, list.size() ) );
-    }
-
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public static <X extends Comparable> Iterable<X> sort( Iterable<X> iterable )
-    {
-        List<X> list = toList( iterable );
-        Collections.sort( list );
-        return list;
-    }
-
-    public static <X> Iterable<X> sort( Comparator<? super X> comparator, Iterable<X> iterable )
-    {
-        List<X> list = toList( iterable );
-        Collections.sort( list, comparator );
-        return list;
-    }
-
-    private static class MapIterable<FROM, TO>
-        implements Iterable<TO>
-    {
-        private final Iterable<FROM> from;
-        private final Function<? super FROM, TO> function;
-
-        private MapIterable( Iterable<FROM> from, Function<? super FROM, TO> function )
-        {
-            this.from = from;
-            this.function = function;
-        }
-
-        @Override
-        public Iterator<TO> iterator()
-        {
-            return new MapIterator<>( from.iterator(), function );
-        }
-
-        static class MapIterator<FROM, TO>
-            implements Iterator<TO>
-        {
-            private final Iterator<FROM> fromIterator;
-            private final Function<? super FROM, TO> function;
-
-            private MapIterator( Iterator<FROM> fromIterator, Function<? super FROM, TO> function )
-            {
-                this.fromIterator = fromIterator;
-                this.function = function;
-            }
-
-            @Override
-            public boolean hasNext()
-            {
-                return fromIterator.hasNext();
-            }
-
-            @Override
-            public TO next()
-            {
-                FROM from = fromIterator.next();
-                return function.map( from );
-            }
-
-            @Override
-            public void remove()
-            {
-                fromIterator.remove();
-            }
-        }
-
-    }
-
-    private static class FilterIterable<T>
-        implements Iterable<T>
-    {
-        private final Iterable<T> iterable;
-
-        private final Specification<? super T> specification;
-
-        private FilterIterable( Iterable<T> iterable, Specification<? super T> specification )
-        {
-            this.iterable = iterable;
-            this.specification = specification;
-        }
-
-        @Override
-        public Iterator<T> iterator()
-        {
-            return new FilterIterator<>( iterable.iterator(), specification );
-        }
-
-        private static class FilterIterator<T>
-            implements Iterator<T>
-        {
-            private final Iterator<T> iterator;
-
-            private final Specification<? super T> specification;
-
-            private T currentValue;
-            boolean finished = false;
-            boolean nextConsumed = true;
-
-            private FilterIterator( Iterator<T> iterator, Specification<? super T> specification )
-            {
-                this.specification = specification;
-                this.iterator = iterator;
-            }
-
-            public boolean moveToNextValid()
-            {
-                boolean found = false;
-                while( !found && iterator.hasNext() )
-                {
-                    T currentValue = iterator.next();
-                    boolean satisfies = specification.satisfiedBy( currentValue );
-
-                    if( satisfies )
-                    {
-                        found = true;
-                        this.currentValue = currentValue;
-                        nextConsumed = false;
-                    }
-                }
-                if( !found )
-                {
-                    finished = true;
-                }
-                return found;
-            }
-
-            @Override
-            public T next()
-            {
-                if( !nextConsumed )
-                {
-                    nextConsumed = true;
-                    return currentValue;
-                }
-                else
-                {
-                    if( !finished )
-                    {
-                        if( moveToNextValid() )
-                        {
-                            nextConsumed = true;
-                            return currentValue;
-                        }
-                    }
-                }
-                return null;
-            }
-
-            @Override
-            public boolean hasNext()
-            {
-                return !finished
-                       && ( !nextConsumed || moveToNextValid() );
-            }
-
-            @Override
-            public void remove()
-            {
-            }
-        }
-
-    }
-
-    private static class FlattenIterable<T, I extends Iterable<? extends T>>
-        implements Iterable<T>
-    {
-        private final Iterable<I> iterable;
-
-        private FlattenIterable( Iterable<I> iterable )
-        {
-            this.iterable = iterable;
-        }
-
-        @Override
-        public Iterator<T> iterator()
-        {
-            return new FlattenIterator<>( iterable.iterator() );
-        }
-
-        static class FlattenIterator<T, I extends Iterable<? extends T>>
-            implements Iterator<T>
-        {
-            private final Iterator<I> iterator;
-            private Iterator<? extends T> currentIterator;
-
-            private FlattenIterator( Iterator<I> iterator )
-            {
-                this.iterator = iterator;
-                currentIterator = null;
-            }
-
-            @Override
-            public boolean hasNext()
-            {
-                if( currentIterator == null )
-                {
-                    if( iterator.hasNext() )
-                    {
-                        I next = iterator.next();
-                        currentIterator = next.iterator();
-                    }
-                    else
-                    {
-                        return false;
-                    }
-                }
-
-                while( !currentIterator.hasNext()
-                       && iterator.hasNext() )
-                {
-                    currentIterator = iterator.next().iterator();
-                }
-
-                return currentIterator.hasNext();
-            }
-
-            @Override
-            public T next()
-            {
-                return currentIterator.next();
-            }
-
-            @Override
-            public void remove()
-            {
-                if( currentIterator == null )
-                {
-                    throw new IllegalStateException();
-                }
-
-                currentIterator.remove();
-            }
-        }
-
-    }
-
-    private static class CacheIterable<T>
-        implements Iterable<T>
-    {
-        private final Iterable<T> iterable;
-        private Iterable<T> cache;
-
-        private CacheIterable( Iterable<T> iterable )
-        {
-            this.iterable = iterable;
-        }
-
-        @Override
-        public Iterator<T> iterator()
-        {
-            if( cache != null )
-            {
-                return cache.iterator();
-            }
-
-            final Iterator<T> source = iterable.iterator();
-
-            return new Iterator<T>()
-            {
-                List<T> iteratorCache = new ArrayList<>();
-
-                @Override
-                public boolean hasNext()
-                {
-                    boolean hasNext = source.hasNext();
-                    if( !hasNext )
-                    {
-                        cache = iteratorCache;
-                    }
-                    return hasNext;
-                }
-
-                @Override
-                public T next()
-                {
-                    T next = source.next();
-                    iteratorCache.add( next );
-                    return next;
-                }
-
-                @Override
-                public void remove()
-                {
-
-                }
-            };
-        }
-    }
-
-    private Iterables()
-    {
-    }
-
-}
diff --git a/core/functional/src/main/java/org/qi4j/functional/Specification.java b/core/functional/src/main/java/org/qi4j/functional/Specification.java
deleted file mode 100644
index 93c61a9..0000000
--- a/core/functional/src/main/java/org/qi4j/functional/Specification.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.functional;
-
-/**
- * Generic specification interface.
- *
- * @param <T>
- */
-// START SNIPPET: specification
-public interface Specification<T>
-{
-// END SNIPPET: specification
-
-    /**
-     * Test whether an item matches the given specification
-     *
-     * @param item the item to be tested
-     *
-     * @return true if the item matches, false otherwise
-     */
-// START SNIPPET: specification
-    boolean satisfiedBy( T item );
-}
-// END SNIPPET: specification
diff --git a/core/functional/src/main/java/org/qi4j/functional/Specifications.java b/core/functional/src/main/java/org/qi4j/functional/Specifications.java
deleted file mode 100644
index 7635579..0000000
--- a/core/functional/src/main/java/org/qi4j/functional/Specifications.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.functional;
-
-/**
- * Common generic specification expressions
- */
-public class Specifications
-{
-    public static <T> Specification<T> TRUE()
-    {
-        return new Specification<T>()
-        {
-            @Override
-            public boolean satisfiedBy( T instance )
-            {
-                return true;
-            }
-        };
-    }
-
-    public static <T> Specification<T> not( final Specification<T> specification )
-    {
-        return new Specification<T>()
-        {
-            @Override
-            public boolean satisfiedBy( T instance )
-            {
-                return !specification.satisfiedBy( instance );
-            }
-        };
-    }
-
-    @SafeVarargs
-    public static <T> AndSpecification<T> and( final Specification<T>... specifications )
-    {
-        return and( Iterables.iterable( specifications ) );
-    }
-
-    public static <T> AndSpecification<T> and( final Iterable<Specification<T>> specifications )
-    {
-        return new AndSpecification<>( specifications );
-    }
-
-    @SafeVarargs
-    public static <T> OrSpecification<T> or( final Specification<T>... specifications )
-    {
-        return or( Iterables.iterable( specifications ) );
-    }
-
-    public static <T> OrSpecification<T> or( final Iterable<Specification<T>> specifications )
-    {
-        return new OrSpecification<>( specifications );
-    }
-
-    @SafeVarargs
-    public static <T> Specification<T> in( final T... allowed )
-    {
-        return in( Iterables.iterable( allowed ) );
-    }
-
-    public static <T> Specification<T> in( final Iterable<T> allowed )
-    {
-        return new Specification<T>()
-        {
-            @Override
-            public boolean satisfiedBy( T item )
-            {
-                for( T allow : allowed )
-                {
-                    if( allow.equals( item ) )
-                    {
-                        return true;
-                    }
-                }
-                return false;
-            }
-        };
-    }
-
-    public static <T> Specification<T> notNull()
-    {
-        return new Specification<T>()
-        {
-            @Override
-            public boolean satisfiedBy( T item )
-            {
-                return item != null;
-            }
-        };
-    }
-
-    public static <FROM, TO> Specification<FROM> translate( final Function<FROM, TO> function,
-                                                            final Specification<? super TO> specification
-    )
-    {
-        return new Specification<FROM>()
-        {
-            @Override
-            public boolean satisfiedBy( FROM item )
-            {
-                return specification.satisfiedBy( function.map( item ) );
-            }
-        };
-    }
-
-    /**
-     * AND Specification.
-     */
-    public static class AndSpecification<T>
-        implements Specification<T>
-    {
-        private final Iterable<Specification<T>> specifications;
-
-        private AndSpecification( Iterable<Specification<T>> specifications )
-        {
-            this.specifications = specifications;
-        }
-
-        @Override
-        public boolean satisfiedBy( T instance )
-        {
-            for( Specification<T> specification : specifications )
-            {
-                if( !specification.satisfiedBy( instance ) )
-                {
-                    return false;
-                }
-            }
-
-            return true;
-        }
-
-        @SafeVarargs
-        public final AndSpecification<T> and( Specification<T>... specifications )
-        {
-            Iterable<Specification<T>> iterable = Iterables.iterable( specifications );
-            Iterable<Specification<T>> flatten = Iterables.flatten( this.specifications, iterable );
-            return Specifications.and( flatten );
-        }
-
-        @SafeVarargs
-        public final OrSpecification<T> or( Specification<T>... specifications )
-        {
-            return Specifications.or( Iterables.prepend( this, Iterables.iterable( specifications ) ) );
-        }
-    }
-
-    /**
-     * OR Specification.
-     */
-    public static class OrSpecification<T>
-        implements Specification<T>
-    {
-        private final Iterable<Specification<T>> specifications;
-
-        private OrSpecification( Iterable<Specification<T>> specifications )
-        {
-            this.specifications = specifications;
-        }
-
-        @Override
-        public boolean satisfiedBy( T instance )
-        {
-            for( Specification<T> specification : specifications )
-            {
-                if( specification.satisfiedBy( instance ) )
-                {
-                    return true;
-                }
-            }
-
-            return false;
-        }
-
-        @SafeVarargs
-        public final AndSpecification<T> and( Specification<T>... specifications )
-        {
-            return Specifications.and( Iterables.prepend( this, Iterables.iterable( specifications ) ) );
-        }
-
-        @SafeVarargs
-        public final OrSpecification<T> or( Specification<T>... specifications )
-        {
-            Iterable<Specification<T>> iterable = Iterables.iterable( specifications );
-            Iterable<Specification<T>> flatten = Iterables.flatten( this.specifications, iterable );
-            return Specifications.or( flatten );
-        }
-    }
-
-    private Specifications()
-    {
-    }
-
-}
diff --git a/core/functional/src/main/java/org/qi4j/functional/Visitable.java b/core/functional/src/main/java/org/qi4j/functional/Visitable.java
deleted file mode 100644
index b1ed8ba..0000000
--- a/core/functional/src/main/java/org/qi4j/functional/Visitable.java
+++ /dev/null
@@ -1,28 +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.qi4j.functional;
-
-/**
- * Interface that visitable objects should implement.
- */
-public interface Visitable<T>
-{
-    <ThrowableType extends Throwable> boolean accept( Visitor<? super T, ThrowableType> visitor )
-        throws ThrowableType;
-}
diff --git a/core/functional/src/main/java/org/qi4j/functional/VisitableHierarchy.java b/core/functional/src/main/java/org/qi4j/functional/VisitableHierarchy.java
deleted file mode 100644
index fe37d1f..0000000
--- a/core/functional/src/main/java/org/qi4j/functional/VisitableHierarchy.java
+++ /dev/null
@@ -1,28 +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.qi4j.functional;
-
-/**
- * Interface that visitable hierarchies of objects should implement.
- */
-public interface VisitableHierarchy<NODE, LEAF>
-{
-    <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super NODE, ? super LEAF, ThrowableType> visitor )
-        throws ThrowableType;
-}
diff --git a/core/functional/src/main/java/org/qi4j/functional/Visitor.java b/core/functional/src/main/java/org/qi4j/functional/Visitor.java
deleted file mode 100644
index 3cf6005..0000000
--- a/core/functional/src/main/java/org/qi4j/functional/Visitor.java
+++ /dev/null
@@ -1,38 +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.qi4j.functional;
-
-/**
- * Generic Visitor interface.
- */
-public interface Visitor<T, ThrowableType extends Throwable>
-{
-    /**
-     * Visit an instance of T
-     *
-     * @param visited the visited instance
-     *
-     * @return true if the visitor pattern should continue, false if it should be aborted
-     *
-     * @throws ThrowableType if an exception occurred during processing. Any client call that initiated the visiting should
-     *                       get the exception in order to handle it properly.
-     */
-    boolean visit( T visited )
-        throws ThrowableType;
-}
diff --git a/core/functional/src/main/java/org/qi4j/functional/package.html b/core/functional/src/main/java/org/qi4j/functional/package.html
deleted file mode 100644
index 920a9ef..0000000
--- a/core/functional/src/main/java/org/qi4j/functional/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Functional API.</h2>
-    </body>
-</html>
diff --git a/core/functional/src/test/java/org/qi4j/functional/FunctionsTest.java b/core/functional/src/test/java/org/qi4j/functional/FunctionsTest.java
deleted file mode 100644
index a5e1956..0000000
--- a/core/functional/src/test/java/org/qi4j/functional/FunctionsTest.java
+++ /dev/null
@@ -1,143 +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.qi4j.functional;
-
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.junit.Test;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.functional.ForEach.forEach;
-import static org.qi4j.functional.Functions.compose;
-import static org.qi4j.functional.Functions.count;
-import static org.qi4j.functional.Functions.indexOf;
-import static org.qi4j.functional.Functions.intSum;
-import static org.qi4j.functional.Functions.longSum;
-import static org.qi4j.functional.Iterables.iterable;
-import static org.qi4j.functional.Iterables.last;
-import static org.qi4j.functional.Iterables.map;
-import static org.qi4j.functional.Specifications.in;
-
-/**
- * Test of utility functions
- */
-public class FunctionsTest
-{
-    Function<Object, String> stringifier = new Function<Object, String>()
-    {
-        @Override
-        public String map( Object s )
-        {
-            return s.toString();
-        }
-    };
-
-    Function<String, Integer> length = new Function<String, Integer>()
-    {
-        @Override
-        public Integer map( String s )
-        {
-            return s.length();
-        }
-    };
-
-    @Test
-    public void testCompose()
-    {
-        assertThat( Functions.<Object, String, Integer>compose()
-                        .map( length, stringifier )
-                        .map( 12345L ), equalTo( 5 ) );
-        assertThat( compose( length, stringifier ).map( 12345L ), equalTo( 5 ) );
-    }
-
-    @Test
-    public void testFromMap()
-    {
-        Map<String, String> map = new HashMap<String, String>();
-        map.put( "A", "1" );
-        map.put( "B", "2" );
-        map.put( "C", "3" );
-        assertThat( Iterables.toList( Iterables.filter( Specifications.notNull(), Iterables.map( Functions.fromMap( map ), Iterables
-            .iterable( "A", "B", "D" ) ) ) ).toString(), equalTo( "[1, 2]" ) );
-    }
-
-    @Test
-    public void testWithDefault()
-    {
-        assertThat( Iterables.toList( Iterables.map( Functions.withDefault( "DEFAULT" ), Iterables.iterable( "123", null, "456" ) ) )
-                        .toString(), equalTo( "[123, DEFAULT, 456]" ) );
-    }
-
-    @Test
-    public void testLongSum()
-    {
-        assertThat( last( map( longSum(), iterable( 1, 2L, 3F, 4D ) ) ), equalTo( 10L ) );
-    }
-
-    @Test
-    public void testLongSum2()
-    {
-        assertThat( forEach( iterable( 1, 2, 3, 4 ) ).map( longSum() ).last(), equalTo( 10L ) );
-    }
-
-    @Test
-    public void testIntSum()
-    {
-        assertThat( last( map( intSum(), iterable( 1, 2L, 3F, 4D ) ) ), equalTo( 10 ) );
-    }
-
-    @Test
-    public void testCount()
-    {
-        assertThat( last( map( count( in( "X" ) ), iterable( "X", "Y", "X", "X", "Y" ) ) ), equalTo( 3 ) );
-    }
-
-    @Test
-    public void testIndexOf()
-    {
-        assertThat( last( map( indexOf( in( "D" ) ), iterable( "A", "B", "C", "D", "D" ) ) ), equalTo( 3 ) );
-    }
-
-    @Test
-    public void testIndexOf2()
-    {
-        assertThat( indexOf( "D", iterable( "A", "B", "C", "D", "D" ) ), equalTo( 3 ) );
-    }
-
-    @Test
-    public void testComparator()
-    {
-        Comparator<Integer> comparator = Functions.comparator( new Function<Integer, Comparable>()
-        {
-            @Override
-            public Comparable map( Integer integer )
-            {
-                return integer.toString();
-            }
-        } );
-        Iterable<Integer> iterable = Iterables.iterable( 1, 5, 3, 6, 8 );
-        List<Integer> integers = Iterables.toList( iterable );
-        Collections.sort( integers, comparator );
-        assertThat( integers.toString(), equalTo( "[1, 3, 5, 6, 8]" ) );
-    }
-}
diff --git a/core/functional/src/test/java/org/qi4j/functional/IntegerRangeSpecificationTest.java b/core/functional/src/test/java/org/qi4j/functional/IntegerRangeSpecificationTest.java
deleted file mode 100644
index d29b24b..0000000
--- a/core/functional/src/test/java/org/qi4j/functional/IntegerRangeSpecificationTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.functional;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-// This test exist primarily for the documentation. Don't remove.
-public class IntegerRangeSpecificationTest
-{
-    @Test
-    public void test1()
-    {
-        Specification<Integer> spec = new IntegerRangeSpecification( 10, 12 );
-        assertTrue( spec.satisfiedBy( 10 ) );
-        assertTrue( spec.satisfiedBy( 11 ) );
-        assertTrue( spec.satisfiedBy( 12 ) );
-        assertFalse( spec.satisfiedBy( 9 ) );
-        assertFalse( spec.satisfiedBy( 13 ) );
-    }
-
-    // START SNIPPET: specification
-    public static class IntegerRangeSpecification
-        implements Specification<Integer>
-    {
-
-        private int lower;
-        private int higher;
-
-        public IntegerRangeSpecification( int lower, int higher )
-        {
-            this.lower = lower;
-            this.higher = higher;
-        }
-
-        @Override
-        public boolean satisfiedBy( Integer item )
-        {
-            return item >= lower && item <= higher;
-        }
-    }
-    // END SNIPPET: specification
-}
diff --git a/core/functional/src/test/java/org/qi4j/functional/IterablesTest.java b/core/functional/src/test/java/org/qi4j/functional/IterablesTest.java
deleted file mode 100644
index 6aee556..0000000
--- a/core/functional/src/test/java/org/qi4j/functional/IterablesTest.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.functional;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Enumeration;
-import java.util.List;
-import org.hamcrest.CoreMatchers;
-import org.junit.Test;
-
-import static java.util.Collections.*;
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test of Iterables utility methods
- */
-public class IterablesTest
-{
-
-    private List<String> numbers = Arrays.asList( "1", "2", "3" );
-    private Iterable<Long> numberLongs = Arrays.asList( 1L, 2L, 3L );
-    private Iterable<Integer> numberIntegers = Arrays.asList( 1, 2, 3 );
-
-    @Test
-    public void testConstant()
-    {
-        String str = "";
-
-        for( String string : Iterables.limit( 3, Iterables.constant( "123" ) ) )
-        {
-            str += string;
-        }
-
-        assertThat( str, CoreMatchers.equalTo( "123123123" ) );
-    }
-
-    @Test
-    public void testUnique()
-    {
-        String str = "";
-
-        for( String string : Iterables.unique( Iterables.<String>flatten( numbers, numbers, numbers ) ) )
-        {
-            str += string;
-        }
-        assertThat( str, CoreMatchers.equalTo( "123" ) );
-    }
-
-    @Test
-    public void testAddAll()
-    {
-        List<String> strings = Iterables.toList( numbers );
-        assertThat( strings.toString(), equalTo( "[1, 2, 3]" ) );
-        assertThat( Iterables.toList( numberLongs ).toString(), equalTo( "[1, 2, 3]" ) );
-    }
-
-    @Test
-    public void testCount()
-    {
-        assertThat( Iterables.count( numbers ), equalTo( 3L ) );
-    }
-
-    @Test
-    public void testFilter()
-    {
-        assertThat( Iterables.first( Iterables.filter( Specifications.in( "2" ), numbers ) ), equalTo( "2" ) );
-    }
-
-    @Test
-    public void testFirst()
-    {
-        assertThat( Iterables.first( numbers ), equalTo( "1" ) );
-        assertThat( Iterables.first( emptyList() ), nullValue() );
-    }
-
-    @Test
-    public void testLast()
-    {
-        assertThat( Iterables.last( numbers ), equalTo( "3" ) );
-        assertThat( Iterables.last( emptyList() ), nullValue() );
-    }
-
-    @Test
-    public void testFolding()
-    {
-        assertThat( Iterables.fold( new Function<Integer, Integer>()
-        {
-
-            int sum = 0;
-
-            @Override
-            public Integer map( Integer number )
-            {
-                return sum += number;
-            }
-
-        }, numberIntegers ), equalTo( 6 ) );
-    }
-
-    @Test
-    public void testAppend()
-    {
-        assertThat( Iterables.toList( Iterables.append( "C", Iterables.iterable( "A", "B" ) ) ).toString(),
-                    equalTo( "[A, B, C]" ) );
-    }
-
-    @Test
-    public void testReverse()
-    {
-        assertThat( Iterables.reverse( numbers ).toString(), equalTo( "[3, 2, 1]" ) );
-        assertThat( Iterables.reverse( emptyList() ), equalTo( (Object) emptyList() ) );
-    }
-
-    @Test
-    public void testMatchesAny()
-    {
-        assertThat( Iterables.matchesAny( Specifications.in( "2" ), numbers ), equalTo( true ) );
-        assertThat( Iterables.matchesAny( Specifications.in( "4" ), numbers ), equalTo( false ) );
-    }
-
-    @Test
-    public void testMatchesAll()
-    {
-        assertThat( Iterables.matchesAll( Specifications.in( "1", "2", "3" ), numbers ), equalTo( true ) );
-        assertThat( Iterables.matchesAll( Specifications.in( "2", "3", "4" ), numbers ), equalTo( false ) );
-    }
-
-    @Test
-    public void testFlatten()
-    {
-        assertThat( Iterables.toList( Iterables.flatten( numbers, numbers ) ).toString(),
-                    equalTo( "[1, 2, 3, 1, 2, 3]" ) );
-
-        Iterable<? extends Number> flatten = Iterables.flatten( numberIntegers, numberLongs );
-        assertThat( Iterables.toList( flatten ).toString(), equalTo( "[1, 2, 3, 1, 2, 3]" ) );
-    }
-
-    @Test
-    public void testFlattenIterables()
-    {
-        Iterable<List<String>> iterable = Iterables.iterable( numbers, numbers );
-        assertThat( Iterables.toList( Iterables.flattenIterables( iterable ) ).toString(),
-                    equalTo( "[1, 2, 3, 1, 2, 3]" ) );
-    }
-
-    @Test
-    public void testMix()
-    {
-        assertThat( Iterables.toList( Iterables.mix( Iterables.iterable( "A", "B", "C" ),
-                                                     Iterables.iterable( "1", "2", "3", "4", "5" ),
-                                                     Iterables.iterable( "X", "Y", "Z" ) ) ).toString(),
-                    equalTo( "[A, 1, X, B, 2, Y, C, 3, Z, 4, 5]" ) );
-    }
-
-    @Test
-    public void testMap()
-    {
-        assertThat( Iterables.toList( Iterables.map( new Function<String, String>()
-        {
-
-            public String map( String s )
-            {
-                return s + s;
-            }
-
-        }, numbers ) ).toString(), equalTo( "[11, 22, 33]" ) );
-
-        Iterable<List<String>> numberIterable = Iterables.iterable( numbers, numbers, numbers );
-        assertThat( Iterables.toList( Iterables.map( new Function<Collection, Integer>()
-        {
-
-            @Override
-            public Integer map( Collection collection )
-            {
-                return collection.size();
-            }
-
-        }, numberIterable ) ).toString(), equalTo( "[3, 3, 3]" ) );
-    }
-
-    @Test
-    public void testIterableEnumeration()
-    {
-
-        Enumeration<String> enumeration = enumeration( numbers );
-        assertThat( Iterables.toList( Iterables.iterable( enumeration ) ).toString(),
-                    equalTo( "[1, 2, 3]" ) );
-    }
-
-    @Test
-    public void testIterableVarArg()
-    {
-        assertThat( Iterables.toList( Iterables.iterable( "1", "2", "3" ) ).toString(),
-                    equalTo( "[1, 2, 3]" ) );
-    }
-
-    @Test
-    public void testCast()
-    {
-        Iterable<Long> values = numberLongs;
-        Iterable<Number> numbers = Iterables.cast( values );
-    }
-
-    @Test
-    public void testDebug()
-    {
-        assertThat( Iterables.first( Iterables.debug( "Filtered number:{0}",
-                                                      Iterables.filter( Specifications.in( "2" ),
-                                                                        Iterables.debug( "Number:{0}", numbers ) ) ) ),
-                    equalTo( "2" ) );
-    }
-
-    @Test
-    public void testDebugWithFunctions()
-    {
-        Function<String, String> fun = new Function<String, String>()
-        {
-
-            @Override
-            public String map( String s )
-            {
-                return s + ":" + s.length();
-            }
-
-        };
-        assertThat( Iterables.first( Iterables.debug( "Filtered number:{0}",
-                                                      Iterables.filter( Specifications.in( "2" ),
-                                                                        Iterables.debug( "Number:{0}", numbers, fun ) ) ) ),
-                    equalTo( "2" ) );
-    }
-
-    @Test
-    public void testCache()
-    {
-        final int[] count = new int[ 1 ];
-
-        Iterable<String> b = Iterables.cache( Iterables.filter( Specifications.and( new Specification<String>()
-        {
-
-            @Override
-            public boolean satisfiedBy( String item )
-            {
-                count[ 0] = count[ 0] + 1;
-                return true;
-            }
-
-        }, Specifications.in( "B" ) ), Iterables.iterable( "A", "B", "C" ) ) );
-
-        assertThat( count[ 0], equalTo( 0 ) );
-
-        Iterables.toList( b );
-
-        assertThat( count[ 0], equalTo( 3 ) );
-
-        Iterables.toList( b );
-
-        assertThat( count[ 0], equalTo( 3 ) );
-    }
-
-    @Test
-    public void testSort()
-    {
-        assertThat( Iterables.sort( Iterables.reverse( numberLongs ) ).toString(), equalTo( "[1, 2, 3]" ) );
-
-        Comparator<Long> inverseLongComparator = new Comparator<Long>()
-        {
-
-            @Override
-            public int compare( Long left, Long right )
-            {
-                return left.compareTo( right ) * -1;
-            }
-
-        };
-        assertThat( Iterables.sort( inverseLongComparator, numberLongs ).toString(), equalTo( "[3, 2, 1]" ) );
-    }
-
-}
diff --git a/core/functional/src/test/java/org/qi4j/functional/SpecificationsTest.java b/core/functional/src/test/java/org/qi4j/functional/SpecificationsTest.java
deleted file mode 100644
index 98b893e..0000000
--- a/core/functional/src/test/java/org/qi4j/functional/SpecificationsTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.functional;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-
-/**
- * JAVADOC
- */
-public class SpecificationsTest
-{
-    @Test
-    public void testTRUE()
-    {
-        Assert.assertThat( Specifications.<Object>TRUE().satisfiedBy( new Object() ), equalTo( true ) );
-    }
-
-    @Test
-    public void testNot()
-    {
-        Assert.assertThat( Specifications.not( Specifications.<Object>TRUE() )
-                               .satisfiedBy( new Object() ), equalTo( false ) );
-    }
-
-    @Test
-    public void testAnd()
-    {
-        Specification<Object> trueSpec = Specifications.<Object>TRUE();
-        Specification<Object> falseSpec = Specifications.not( Specifications.<Object>TRUE() );
-
-        Assert.assertThat( Specifications.and( falseSpec, falseSpec ).satisfiedBy( new Object() ), equalTo( false ) );
-        Assert.assertThat( Specifications.and( trueSpec, falseSpec ).satisfiedBy( new Object() ), equalTo( false ) );
-        Assert.assertThat( Specifications.and( falseSpec, trueSpec ).satisfiedBy( new Object() ), equalTo( false ) );
-        Assert.assertThat( Specifications.and( trueSpec, trueSpec ).satisfiedBy( new Object() ), equalTo( true ) );
-    }
-
-    @Test
-    public void testOr()
-    {
-        Specification<Object> trueSpec = Specifications.<Object>TRUE();
-        Specification<Object> falseSpec = Specifications.not( Specifications.<Object>TRUE() );
-
-        Assert.assertThat( Specifications.or( falseSpec, falseSpec ).satisfiedBy( new Object() ), equalTo( false ) );
-        Assert.assertThat( Specifications.or( trueSpec, falseSpec ).satisfiedBy( new Object() ), equalTo( true ) );
-        Assert.assertThat( Specifications.or( falseSpec, trueSpec ).satisfiedBy( new Object() ), equalTo( true ) );
-        Assert.assertThat( Specifications.or( trueSpec, trueSpec ).satisfiedBy( new Object() ), equalTo( true ) );
-    }
-
-    @Test
-    public void testIn()
-    {
-        Assert.assertThat( Specifications.in( "1", "2", "3" ).satisfiedBy( "2" ), equalTo( true ) );
-        Assert.assertThat( Specifications.in( "1", "2", "3" ).satisfiedBy( "4" ), equalTo( false ) );
-    }
-
-    @Test
-    public void testTranslate()
-    {
-        Function<Object, String> stringifier = new Function<Object, String>()
-        {
-            @Override
-            public String map( Object s )
-            {
-                return s.toString();
-            }
-        };
-
-        Assert.assertTrue( Specifications.translate( stringifier, Specifications.in( "3" ) ).satisfiedBy( 3L ) );
-    }
-}
diff --git a/core/functional/src/test/java/org/qi4j/functional/docsupport/FunctionalDocs.java b/core/functional/src/test/java/org/qi4j/functional/docsupport/FunctionalDocs.java
deleted file mode 100644
index 7110a21..0000000
--- a/core/functional/src/test/java/org/qi4j/functional/docsupport/FunctionalDocs.java
+++ /dev/null
@@ -1,55 +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.qi4j.functional.docsupport;
-
-import java.util.ArrayList;
-
-// START SNIPPET: func2
-import static org.qi4j.functional.ForEach.forEach;
-import static org.qi4j.functional.Functions.longSum;
-// END SNIPPET: func2
-
-public class FunctionalDocs
-{
-    public static void main( String[] args )
-    {
-        {
-// START SNIPPET: func1
-            Iterable<Long> data = new ArrayList<Long>();
-// END SNIPPET: func1
-// START SNIPPET: func1
-
-            long sum = 0;
-            for( Long point : data )
-            {
-                sum = sum + point;
-            }
-            System.out.println( "The sum is " + sum );
-// END SNIPPET: func1
-        }
-        {
-// START SNIPPET: func2
-            Iterable<Number> data = new ArrayList<Number>();
-            Long sum = forEach( data ).map( longSum() ).last();
-            System.out.println( "The sum is " + sum );
-
-// END SNIPPET: func2
-        }
-    }
-}
diff --git a/core/io/build.gradle b/core/io/build.gradle
deleted file mode 100644
index e67866f..0000000
--- a/core/io/build.gradle
+++ /dev/null
@@ -1,28 +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.
- */
-
-jar { manifest { name = "Apache Zest™ I/O"}}
-
-dependencies {
-
-  compile project( ':org.qi4j.core:org.qi4j.core.functional' )
-
-  testCompile project( ':org.qi4j.core:org.qi4j.core.testsupport' )
-
-}
diff --git a/core/io/dev-status.xml b/core/io/dev-status.xml
deleted file mode 100644
index ed93800..0000000
--- a/core/io/dev-status.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
-  <status>
-    <codebase>beta</codebase>
-    <!--none,early,beta,stable,mature-->
-    <documentation>good</documentation>
-    <!-- none, brief, good, complete -->
-    <unittests>good</unittests>
-    <!-- none, some, good, complete -->
-  </status>
-  <licenses>
-    <license>ALv2</license>
-  </licenses>
-</module>
diff --git a/core/io/src/docs/io.txt b/core/io/src/docs/io.txt
deleted file mode 100644
index d8ffef8..0000000
--- a/core/io/src/docs/io.txt
+++ /dev/null
@@ -1,223 +0,0 @@
-//////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.
-//////////////////////
-
-[[core-io,I/O API]]
-= Core I/O API =
-
-[devstatus]
---------------
-source=core/io/dev-status.xml
---------------
-
-The Zest™ Core I/O API is completely generic and not tied to the Zest™ programming model as a whole. It can be used
-independently of Zest, together with the Zest™ Core Functional API, which the Core I/O API depends on.
-
-The Zest™ Core I/O API tries to address the problem around shuffling data around from various I/O inputs and outputs,
-possibly with transformations and filtering along the way. It was identified that there is a general mix-up of concerns
-in the stereotypical I/O handling codebases that people deal with all the time. The reasoning around this, can be found
-in the <<howto-use-io>>, and is recommended reading.
-
-include::../../build/docs/buildinfo/artifact.txt[]
-
-== The Problem ==
-Why does I/O operations in Java have to be so complicated, with nested try/catch/finally and loops? Don't you wish
-that the operations could be expressed in a more natural way, such as;
-
-[source,java]
--------------
-File source = ...
-File destination = ...
-source.copyTo( destination );
--------------
-
-It seems natural to do, yet it is not present for us. We need to involve FileInputStream/FileOutputStream, wrap them
-in Buffered versions of it, do our own looping, close the streams afterwards and what not. So, the java.io.File does
-not have this simple feature and in the Zest™ Core API, we need to work around this limitation. We also want to
-make the abstraction a little bit more encompassing than "just" files. So how does that look like then?
-
-== First Examples ==
-The most common inputs and outputs are collected in the org.qi4j.io.Inputs and org.qi4j.io.Outputs classes as static
-factory methods, but you can create your (more about that later).
-
-So, we want to read a text file and write the content into another text file, right? This is how it is done;
-
-[snippet,java]
------------
-source=core/io/src/test/java/org/qi4j/io/docsupport/IoDocs.java
-tag=io1
------------
-
-Pretty much self-explanatory, wouldn't you say? But what happened to the handling of exceptions and closing of
-resources? It is all handled inside the Zest™ Core I/O API. There is nothing you can forget to do.
-
-Another simple example, where we want to count the number of lines in the text;
-
-[snippet,java]
------------
-source=core/io/src/test/java/org/qi4j/io/docsupport/IoDocs.java
-tag=io2
------------
-
-The Counter is a <<core-functional>> which gets injected into the transfer.
-
-== The 3 Parts ==
-Ok, so we have seen that the end result can become pretty compelling. How does it work?
-
-I/O is defined as a process of moving data from an Input, via one or more Transforms to an Output. The Input could
-be a File or a String, the transformation could be a filter, conversion or a function and finally the Output
-destination could be a File, String or an OutputStream. It is important to note that there is a strong separation of
-concern between them. Let's look at the on at a time.
-
-== org.qi4j.io.Input ==
-This interface simply has a transferTo() method, which takes an Output. The formal definition is;
-
-[snippet,java]
---------------
-source=core/io/src/main/java/org/qi4j/io/Input.java
-tag=input
---------------
-
-What on earth is all this genericized Exceptions? Well, it abstracts away the explicit Exception that implementations
-may throw (or not). So instead of demanding that all I/O must throw the java.io.IOException, as is the case in the
-JDK classes, it is up to the implementation to declare what it may throw. That is found in the SenderThrowable generic
-of the interface.
-
-But hold on a second. Why is an Input throwing a "sender" exception? Well, think again. The Input is feeding "something"
-with data. It takes it from some source and "sends it" to the downstream chain, eventually reaching an Output, which
-likewise is the ultimate "receiver".
-
-So, then, the method transferTo() contains the declaration of the downstream receiver's possible Exception
-(ReceiverThrowable) which the transferTo() method may also throw as the data may not be accepted and such exception
-will bubble up to the transferTo() method (the client's view of the transfer).
-
-== org.qi4j.io.Output ==
-The output interface is likewise fairly simple;
-
-[snippet,java]
---------------
-source=core/io/src/main/java/org/qi4j/io/Output.java
-tag=output
---------------
-
-It can simply receive data from a org.qi4j.io.Sender.
-
-Hey, hold on! Why is it not receiving from an Input? Because the Input is the client's entry point and of no use to
-the Output as such. Instead, the Output will tell the Sender (which is handed to from the Input or an transformation)
-to which Receiver the content should be sent to.
-
-Complicated? Perhaps not trivial to get your head around it at first, but the chain is;
-
-Input passes a Sender to the Output which tells the Sender which Receiver the data should be sent to.
-
-The reason for this is that we need to separate the concerns properly. Input is a starting point, but it emits something
-which is represented by the Sender. Likewise the destination is an Output, but it receives the data via its Receiver
-interface. For O/S resources, they are handled purely inside the Input and Output implementations, where are the
-Sender/Receiver are effectively dealing with the data itself.
-
-== org.qi4j.io.Transforms ==
-The 3 component in the Zest™ Core I/O API is the transformations that are possible. Interestingly enough, with the
-above separation of concerns, we don't need an InputOutput type that can both receive and send data. Instead, we
-simply need to prepare easy to use static factory methods, which are found in the org.qi4j.io.Transforms class. Again,
-it is fairly straight forward to create your own Transforms if you need something not provided here.
-
-The current transformations available are;
-
-   * filter - takes a Specification and only forwards data items conforming to the Specification.
-   * map - takes a org.qi4j.functional.Function to convert an item from one type to (potentially) another, and any
-     possible change along the way.
-   * filteredMap - is a combination of a filter and a map. If the Specification is satisfied, the map function is
-     applied, otherwise the item is passed through unaffected.
-   * lock - A wrapper which protects the Input or Output from simultaneous access. Not a transformation by itself,
-     but implemented in the same fashion.
-
-There are also a couple of handy map functions available, such as
-
-   * Log
-   * ProgressLog
-   * Counter
-   * ByteBuffer2String
-   * Object2String
-   * String2Bytes
-
-== Writing a Map Function? ==
-Let us take a closer look at the implementation of a map function, namely Counter mentioned above and also used in
-the section First Example above.
-
-The implementation is very straight forward.
-
-[snippet,java]
---------------
-source=core/io/src/main/java/org/qi4j/io/Transforms.java
-tag=counter
---------------
-
-On each call to the map() method, increment the counter field. The client can then retrieve that value after the
-transfer is complete, or in a separate thread to show progress.
-
-Speaking of "progress", so how is the ProgressLog implemented? Glad you asked;
-
-[snippet,java]
---------------
-source=core/io/src/main/java/org/qi4j/io/Transforms.java
-tag=progress
---------------
-
-It combines the Counter and the Log implementations, so that the count is forwarded to the Log at a given interval, such
-as every 1000 items. This may not be what you think a ProgressLog should look like, but it serves as a good example on
-how you can combine the general principles found in the Zest™ Core API package.
-
-== How to write a filter specification? ==
-The filter transform takes a specification implementation which has a very simple method, isSatisfiedBy() (read more
-about that in <<core-functional>>.
-
-[snippet,java]
---------------
-source=core/functional/src/main/java/org/qi4j/functional/Specification.java
-tag=specification
---------------
-
-The only thing that the implementation need to do is return *true* or *false* for whether the item passed in is within
-the limits of the Specification. Let's say that you have a IntegerRangeSpecification, which could then be implemented
-as
-
-[snippet,java]
---------------
-source=core/functional/src/test/java/org/qi4j/functional/IntegerRangeSpecificationTest.java
-tag=specification
---------------
-
-== Ready-to-use components ==
-Input and Output implementations at first glance look quite scary. Taking a closer look and it can be followed. But to
-simplify for users, the org.qi4j.io.Inputs and org.qi4h.io.Outputs contains static factory methods for many useful
-sources and destinations.
-
-== org.qi4j.io.Inputs ==
-The current set of ready-to-use Input implementations are;
-
-[snippet,java]
---------------
-source=core/io/src/main/java/org/qi4j/io/Inputs.java
-tag=method
---------------
-
-== org.qi4j.io.Outputs ==
-The current set of ready-to-use Input implementations are;
-
-[snippet,java]
---------------
-source=core/io/src/main/java/org/qi4j/io/Outputs.java
-tag=method
---------------
-
diff --git a/core/io/src/docs/reference/ref-io.txt b/core/io/src/docs/reference/ref-io.txt
deleted file mode 100644
index fc7aac6..0000000
--- a/core/io/src/docs/reference/ref-io.txt
+++ /dev/null
@@ -1,18 +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.
-///////////////////////////////////////////////////////////////
diff --git a/core/io/src/main/java/org/qi4j/io/Files.java b/core/io/src/main/java/org/qi4j/io/Files.java
deleted file mode 100644
index 562d03c..0000000
--- a/core/io/src/main/java/org/qi4j/io/Files.java
+++ /dev/null
@@ -1,35 +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.qi4j.io;
-
-import java.io.File;
-import java.util.Random;
-
-/**
- * Utility class for files.
- */
-public class Files
-{
-    private static Random random = new Random();
-
-    public static File createTemporayFileOf( File file )
-    {
-        return new File(  file.getAbsolutePath() + "_" + Math.abs( random.nextLong() ) );
-    }
-}
diff --git a/core/io/src/main/java/org/qi4j/io/Input.java b/core/io/src/main/java/org/qi4j/io/Input.java
deleted file mode 100644
index bde80e5..0000000
--- a/core/io/src/main/java/org/qi4j/io/Input.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.io;
-
-/**
- * Input source of data.
- * <p>
- * Invoke transferTo to send data from this input to given output. transferTo can be invoked
- * as many times as you want. The transferTo implementation must ensure that any exceptions thrown
- * by the Input or the Output which transferred data is sent to is handled properly, i.e. that resources
- * are closed. Any client code to transferTo calls should not have to bother with resource management,
- * but may catch exceptions anyway for logging and similar purposes.
- * </p>
- */
-// START SNIPPET: input
-public interface Input<T, SenderThrowableType extends Throwable>
-{
-    <ReceiverThrowableType extends Throwable> void transferTo( Output<? super T, ReceiverThrowableType> output )
-        throws SenderThrowableType, ReceiverThrowableType;
-}
-// END SNIPPET: input
diff --git a/core/io/src/main/java/org/qi4j/io/Inputs.java b/core/io/src/main/java/org/qi4j/io/Inputs.java
deleted file mode 100644
index eb2001f..0000000
--- a/core/io/src/main/java/org/qi4j/io/Inputs.java
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.io;
-
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.net.URL;
-import java.net.URLConnection;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.util.Scanner;
-import java.util.zip.GZIPInputStream;
-import org.qi4j.functional.Visitor;
-
-/**
- * Common inputs
- */
-public class Inputs
-{
-    // START SNIPPET: method
-
-    /**
-     * Read lines from a String.
-     *
-     * @param source lines
-     *
-     * @return Input that provides lines from the string as strings
-     */
-    public static Input<String, RuntimeException> text( final String source )
-    // END SNIPPET: method
-    {
-        return new Input<String, RuntimeException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super String, ReceiverThrowableType> output )
-                throws RuntimeException, ReceiverThrowableType
-            {
-
-                output.receiveFrom( new Sender<String, RuntimeException>()
-                {
-                    @Override
-                    public <Receiver2ThrowableType extends Throwable> void sendTo( Receiver<? super String, Receiver2ThrowableType> receiver )
-                        throws Receiver2ThrowableType, RuntimeException
-                    {
-                        Scanner scanner = new Scanner( source );
-                        while( scanner.hasNextLine() )
-                        {
-                            receiver.receive( scanner.nextLine() );
-                        }
-                    }
-                } );
-            }
-        };
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Read lines from a Reader.
-     *
-     * @param source lines
-     *
-     * @return Input that provides lines from the string as strings
-     */
-    public static Input<String, RuntimeException> text( final Reader source )
-    // END SNIPPET: method
-    {
-        return new Input<String, RuntimeException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super String, ReceiverThrowableType> output )
-                throws RuntimeException, ReceiverThrowableType
-            {
-
-                output.receiveFrom( new Sender<String, RuntimeException>()
-                {
-                    @Override
-                    public <Receiver2ThrowableType extends Throwable> void sendTo( Receiver<? super String, Receiver2ThrowableType> receiver )
-                        throws Receiver2ThrowableType, RuntimeException
-                    {
-                        Scanner scanner = new Scanner( source );
-                        while( scanner.hasNextLine() )
-                        {
-                            receiver.receive( scanner.nextLine() );
-                        }
-                    }
-                } );
-            }
-        };
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Read lines from a UTF-8 encoded textfile.
-     *
-     * If the filename ends with .gz, then the data is automatically unzipped when read.
-     *
-     * @param source textfile with lines separated by \n character
-     *
-     * @return Input that provides lines from the textfiles as strings
-     */
-    public static Input<String, IOException> text( final File source )
-    // END SNIPPET: method
-    {
-        return text( source, "UTF-8" );
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Read lines from a textfile with the given encoding.
-     *
-     * If the filename ends with .gz, then the data is automatically unzipped when read.
-     *
-     * @param source   textfile with lines separated by \n character
-     * @param encoding encoding of file, e.g. "UTF-8"
-     *
-     * @return Input that provides lines from the textfiles as strings
-     */
-    public static Input<String, IOException> text( final File source, final String encoding )
-    // END SNIPPET: method
-    {
-        return new Input<String, IOException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super String, ReceiverThrowableType> output )
-                throws IOException, ReceiverThrowableType
-            {
-                InputStream stream = new FileInputStream( source );
-
-                // If file is gzipped, unzip it automatically
-                if( source.getName().endsWith( ".gz" ) )
-                {
-                    stream = new GZIPInputStream( stream );
-                }
-
-                try (BufferedReader reader = new BufferedReader( new InputStreamReader( stream, encoding ) ))
-                {
-                    output.receiveFrom( new Sender<String, IOException>()
-                    {
-                        @Override
-                        public <Receiver2ThrowableType extends Throwable> void sendTo( Receiver<? super String, Receiver2ThrowableType> receiver )
-                            throws Receiver2ThrowableType, IOException
-                        {
-                            String line;
-                            while( ( line = reader.readLine() ) != null )
-                            {
-                                receiver.receive( line );
-                            }
-                        }
-                    } );
-                }
-            }
-        };
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Read lines from a textfile at a given URL.
-     *
-     * If the content support gzip encoding, then the data is automatically unzipped when read.
-     *
-     * The charset in the content-type of the URL will be used for parsing. Default is UTF-8.
-     *
-     * @param source textfile with lines separated by \n character
-     *
-     * @return Input that provides lines from the textfiles as strings
-     */
-    public static Input<String, IOException> text( final URL source )
-    // END SNIPPET: method
-    {
-        return new Input<String, IOException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super String, ReceiverThrowableType> output )
-                throws IOException, ReceiverThrowableType
-            {
-                URLConnection urlConnection = source.openConnection();
-                urlConnection.setRequestProperty( "Accept-Encoding", "gzip" );
-                InputStream stream = urlConnection.getInputStream();
-
-                // If file is gzipped, unzip it automatically
-                if( "gzip".equals( urlConnection.getContentEncoding() ) )
-                {
-                    stream = new GZIPInputStream( stream );
-                }
-
-                // Figure out charset given content-type
-                String contentType = urlConnection.getContentType();
-                String charSet = "UTF-8";
-                if( contentType.contains( "charset=" ) )
-                {
-                    charSet = contentType.substring( contentType.indexOf( "charset=" ) + "charset=".length() );
-                }
-
-                try (BufferedReader reader = new BufferedReader( new InputStreamReader( stream, charSet ) ))
-                {
-                    output.receiveFrom( new Sender<String, IOException>()
-                    {
-                        @Override
-                        public <Receiver2ThrowableType extends Throwable> void sendTo( Receiver<? super String, Receiver2ThrowableType> receiver )
-                            throws Receiver2ThrowableType, IOException
-                        {
-                            String line;
-                            while( ( line = reader.readLine() ) != null )
-                            {
-                                receiver.receive( line );
-                            }
-                        }
-                    } );
-                }
-            }
-        };
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Read a file using ByteBuffer of a given size. Useful for transferring raw data.
-     *
-     * @param source The file to be read.
-     * @param bufferSize The size of the byte array.
-     *
-     * @return An Input instance to be applied to streaming operations.
-     */
-    public static Input<ByteBuffer, IOException> byteBuffer( final File source, final int bufferSize )
-    // END SNIPPET: method
-    {
-        return new Input<ByteBuffer, IOException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super ByteBuffer, ReceiverThrowableType> output )
-                throws IOException, ReceiverThrowableType
-            {
-                final FileInputStream stream = new FileInputStream( source );
-                final FileChannel fci = stream.getChannel();
-
-                final ByteBuffer buffer = ByteBuffer.allocate( bufferSize );
-
-                try
-                {
-                    output.receiveFrom( new Sender<ByteBuffer, IOException>()
-                    {
-                        @Override
-                        public <Receiver2ThrowableType extends Throwable> void sendTo( Receiver<? super ByteBuffer, Receiver2ThrowableType> receiver )
-                            throws Receiver2ThrowableType, IOException
-                        {
-                            while( fci.read( buffer ) != -1 )
-                            {
-                                buffer.flip();
-                                receiver.receive( buffer );
-                                buffer.clear();
-                            }
-                        }
-                    } );
-                }
-                finally
-                {
-                    stream.close();
-                }
-            }
-        };
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Read an inputstream using ByteBuffer of a given size.
-     *
-     * @param source The InputStream to be read.
-     * @param bufferSize The size of the byte array.
-     *
-     * @return An Input instance to be applied to streaming operations.
-     */
-    public static Input<ByteBuffer, IOException> byteBuffer( final InputStream source, final int bufferSize )
-    // END SNIPPET: method
-    {
-        return new Input<ByteBuffer, IOException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super ByteBuffer, ReceiverThrowableType> output )
-                throws IOException, ReceiverThrowableType
-            {
-                try
-                {
-                    output.receiveFrom( new Sender<ByteBuffer, IOException>()
-                    {
-                        @Override
-                        public <Receiver2ThrowableType extends Throwable> void sendTo( Receiver<? super ByteBuffer, Receiver2ThrowableType> receiver )
-                            throws Receiver2ThrowableType, IOException
-                        {
-                            byte[] buffer = new byte[ bufferSize ];
-
-                            int len;
-                            while( ( len = source.read( buffer ) ) != -1 )
-                            {
-                                ByteBuffer byteBuffer = ByteBuffer.wrap( buffer, 0, len );
-                                receiver.receive( byteBuffer );
-                            }
-                        }
-                    } );
-                }
-                finally
-                {
-                    source.close();
-                }
-            }
-        };
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Combine many Input into one single Input. When a transfer is initiated from it all items from all inputs will be transferred
-     * to the given Output.
-     *
-     * @param inputs An Iterable of Input instances to be combined.
-     * @param <T> The item type of the Input
-     * @param <SenderThrowableType> The Throwable that might be thrown by the Inputs.
-     *
-     * @return A combined Input, allowing for easy aggregation of many Input sources.
-     */
-    public static <T, SenderThrowableType extends Throwable> Input<T, SenderThrowableType> combine( final Iterable<Input<T, SenderThrowableType>> inputs )
-    // END SNIPPET: method
-    {
-        return new Input<T, SenderThrowableType>()
-        {
-            @Override
-            public <Receiver2ThrowableType extends Throwable> void transferTo( Output<? super T, Receiver2ThrowableType> output )
-                throws SenderThrowableType, Receiver2ThrowableType
-            {
-                output.receiveFrom( new Sender<T, SenderThrowableType>()
-                {
-                    @Override
-                    public <ReceiverThrowableType extends Throwable> void sendTo( final Receiver<? super T, ReceiverThrowableType> receiver )
-                        throws ReceiverThrowableType, SenderThrowableType
-                    {
-                        for( Input<T, SenderThrowableType> input : inputs )
-                        {
-                            input.transferTo( new Output<T, ReceiverThrowableType>()
-                            {
-                                @Override
-                                public <Sender2ThrowableType extends Throwable> void receiveFrom( Sender<? extends T, Sender2ThrowableType> sender )
-                                    throws ReceiverThrowableType, Sender2ThrowableType
-                                {
-                                    sender.sendTo( new Receiver<T, ReceiverThrowableType>()
-                                    {
-                                        @Override
-                                        public void receive( T item )
-                                            throws ReceiverThrowableType
-                                        {
-                                            receiver.receive( item );
-                                        }
-                                    } );
-                                }
-                            } );
-                        }
-                    }
-                } );
-            }
-        };
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Create an Input that takes its items from the given Iterable.
-     *
-     * @param iterable The Iterable to be used as an Input.
-     * @param <T> The item type of the Input
-     *
-     * @return An Input instance that is backed by the Iterable.
-     */
-    public static <T> Input<T, RuntimeException> iterable( final Iterable<T> iterable )
-    // END SNIPPET: method
-    {
-        return new Input<T, RuntimeException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super T, ReceiverThrowableType> output )
-                throws RuntimeException, ReceiverThrowableType
-            {
-                output.receiveFrom( new Sender<T, RuntimeException>()
-                {
-                    @Override
-                    public <Receiver2ThrowableType extends Throwable> void sendTo( Receiver<? super T, Receiver2ThrowableType> receiver )
-                        throws Receiver2ThrowableType, RuntimeException
-                    {
-                        for( T item : iterable )
-                        {
-                            receiver.receive( item );
-                        }
-                    }
-                } );
-            }
-        };
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Create an Input that allows a Visitor to write to an OutputStream. The stream is a BufferedOutputStream, so when enough
-     * data has been gathered it will send this in chunks of the given size to the Output it is transferred to. The Visitor does not have to call
-     * close() on the OutputStream, but should ensure that any wrapper streams or writers are flushed so that all data is sent.
-     *
-     * @param outputVisitor The OutputStream Visitor that will be backing the Input ByteBuffer.
-     * @param bufferSize The buffering size.
-     *
-     * @return An Input instance of ByteBuffer, that is backed by an Visitor to an OutputStream.
-     */
-    public static Input<ByteBuffer, IOException> output( final Visitor<OutputStream, IOException> outputVisitor,
-                                                         final int bufferSize
-    )
-    // END SNIPPET: method
-    {
-        return new Input<ByteBuffer, IOException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super ByteBuffer, ReceiverThrowableType> output )
-                throws IOException, ReceiverThrowableType
-            {
-                output.receiveFrom( new Sender<ByteBuffer, IOException>()
-                {
-                    @Override
-                    @SuppressWarnings( "unchecked" )
-                    public <Receiver2ThrowableType extends Throwable> void sendTo( final Receiver<? super ByteBuffer, Receiver2ThrowableType> receiver )
-                        throws Receiver2ThrowableType, IOException
-                    {
-                        try (OutputStream out = new BufferedOutputStream( new OutputStream()
-                        {
-                            @Override
-                            public void write( int b )
-                                throws IOException
-                            {
-                                // Ignore
-                            }
-
-                            @SuppressWarnings( "NullableProblems" )
-                            @Override
-                            public void write( byte[] b, int off, int len )
-                                throws IOException
-                            {
-                                try
-                                {
-                                    ByteBuffer byteBuffer = ByteBuffer.wrap( b, 0, len );
-                                    receiver.receive( byteBuffer );
-                                }
-                                catch( Throwable ex )
-                                {
-                                    throw new IOException( ex );
-                                }
-                            }
-                        }, bufferSize ))
-                        {
-                            outputVisitor.visit( out );
-                        }
-                        catch( IOException ex )
-                        {
-                            throw (Receiver2ThrowableType) ex.getCause();
-                        }
-                    }
-                } );
-            }
-        };
-    }
-
-    private Inputs()
-    {
-    }
-}
diff --git a/core/io/src/main/java/org/qi4j/io/Output.java b/core/io/src/main/java/org/qi4j/io/Output.java
deleted file mode 100644
index 3dcd207..0000000
--- a/core/io/src/main/java/org/qi4j/io/Output.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.io;
-
-/**
- * Output for data.
- */
-// START SNIPPET: output
-public interface Output<T, ReceiverThrowableType extends Throwable>
-{
-// END SNIPPET: output
-
-    /**
-     * This initiates a transfer from an Input. Implementations should open any resources to be written to
-     * and then call sender.sendTo() when it is ready to receive data. When sendTo() returns the resource should be
-     * closed properly. Make sure to handle any exceptions from sendTo.
-     *
-     * @param sender                the sender of data to this output
-     * @param <SenderThrowableType> the exception that sendTo can throw
-     *
-     * @throws SenderThrowableType   the exception that the sender can throw
-     * @throws ReceiverThrowableType the exception that this output can throw from receiveItem()
-     */
-// START SNIPPET: output
-    <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends T, SenderThrowableType> sender )
-        throws ReceiverThrowableType, SenderThrowableType;
-}
-// END SNIPPET: output
diff --git a/core/io/src/main/java/org/qi4j/io/Outputs.java b/core/io/src/main/java/org/qi4j/io/Outputs.java
deleted file mode 100644
index 2508788..0000000
--- a/core/io/src/main/java/org/qi4j/io/Outputs.java
+++ /dev/null
@@ -1,528 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.io;
-
-import java.io.BufferedOutputStream;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.util.Collection;
-import java.util.zip.GZIPOutputStream;
-
-/**
- * Utility methods for creating standard Outputs
- */
-public class Outputs
-{
-    // START SNIPPET: method
-
-    /**
-     * Write lines to a text file with UTF-8 encoding. Separate each line with a newline ("\n" character). If the writing or sending fails,
-     * the file is deleted.
-     * <p>
-     * If the filename ends with .gz, then the data is automatically GZipped.
-     * </p>
-     * @param file the file to save the text to
-     *
-     * @return an Output for storing text in a file
-     */
-    public static Output<String, IOException> text( final File file )
-    // END SNIPPET: method
-    {
-        return text( file, "UTF-8" );
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Write lines to a text file. Separate each line with a newline ("\n" character). If the writing or sending fails,
-     * the file is deleted.
-     * <p>
-     * If the filename ends with .gz, then the data is automatically GZipped.
-     * </p>
-     * @param file the file to save the text to
-     *
-     * @return an Output for storing text in a file
-     */
-    public static Output<String, IOException> text( final File file, final String encoding )
-    // END SNIPPET: method
-    {
-        return new Output<String, IOException>()
-        {
-            @Override
-            @SuppressWarnings( "unchecked" )
-            public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends String, SenderThrowableType> sender )
-                throws IOException, SenderThrowableType
-            {
-                File tmpFile = Files.createTemporayFileOf( file );
-
-                OutputStream stream = new FileOutputStream( tmpFile );
-
-                // If file should be gzipped, do that automatically
-                if( file.getName().endsWith( ".gz" ) )
-                {
-                    stream = new GZIPOutputStream( stream );
-                }
-
-                final BufferedWriter writer = new BufferedWriter( new OutputStreamWriter( stream, encoding ) );
-
-                try
-                {
-                    sender.sendTo( new Receiver<String, IOException>()
-                    {
-                        @Override
-                        public void receive( String item )
-                            throws IOException
-                        {
-                            writer.append( item ).append( '\n' );
-                        }
-                    } );
-                    writer.close();
-
-                    // Replace file with temporary file
-                    if( !file.exists() || file.delete() )
-                    {
-                        if( ! tmpFile.renameTo( file ) )
-                        {
-                            // TODO: What?? Throw an Exception?
-                            System.err.println( "Unable to rename file: " + tmpFile + " to " + file );
-                        }
-                    }
-                }
-                catch( IOException e )
-                {
-                    // We failed writing - close and delete
-                    writer.close();
-                    if( ! tmpFile.delete() )
-                    {
-                        System.err.println("Unable to delete temporary file." );
-                        tmpFile.deleteOnExit();
-                    }
-                }
-                catch( Throwable senderThrowableType )
-                {
-                    // We failed writing - close and delete
-                    writer.close();
-                    if( ! tmpFile.delete() )
-                    {
-                        System.err.println("Unable to delete temporary file." );
-                        tmpFile.deleteOnExit();
-                    }
-                    throw (SenderThrowableType) senderThrowableType;
-                }
-            }
-        };
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Write lines to a Writer. Separate each line with a newline ("\n" character).
-     *
-     * @param writer the Writer to write the text to
-     * @return an Output for storing text in a Writer
-     */
-    public static Output<String, IOException> text( final Writer writer )
-    // END SNIPPET: method
-    {
-        return new Output<String, IOException>()
-        {
-
-            @Override
-            public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends String, SenderThrowableType> sender )
-                throws IOException, SenderThrowableType
-            {
-                sender.sendTo( new Receiver<String, IOException>()
-                {
-
-                    @Override
-                    public void receive( String item )
-                        throws IOException
-                    {
-                        writer.append( item ).append( "\n" );
-                    }
-
-                } );
-            }
-
-        };
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Write lines to a StringBuilder. Separate each line with a newline ("\n" character).
-     *
-     * @param builder the StringBuilder to append the text to
-     * @return an Output for storing text in a StringBuilder
-     */
-    public static Output<String, IOException> text( final StringBuilder builder )
-    // END SNIPPET: method
-    {
-        return new Output<String, IOException>()
-        {
-
-            @Override
-            public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends String, SenderThrowableType> sender )
-                throws IOException, SenderThrowableType
-            {
-                sender.sendTo( new Receiver<String, IOException>()
-                {
-
-                    @Override
-                    public void receive( String item )
-                        throws IOException
-                    {
-                        builder.append( item ).append( "\n" );
-                    }
-
-                } );
-            }
-
-        };
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Write ByteBuffer data to a file. If the writing or sending of data fails the file will be deleted.
-     *
-     * @param file The destination file.
-     *
-     * @return The Output ByteBuffer instance backed by a File.
-     */
-    public static Output<ByteBuffer, IOException> byteBuffer( final File file )
-    // END SNIPPET: method
-    {
-        return new Output<ByteBuffer, IOException>()
-        {
-            @Override
-            @SuppressWarnings( "unchecked" )
-            public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends ByteBuffer, SenderThrowableType> sender )
-                throws IOException, SenderThrowableType
-            {
-                File tmpFile = Files.createTemporayFileOf( file );
-                FileOutputStream stream = new FileOutputStream( tmpFile );
-                final FileChannel fco = stream.getChannel();
-
-                try
-                {
-                    sender.sendTo( new Receiver<ByteBuffer, IOException>()
-                    {
-                        @Override
-                        public void receive( ByteBuffer item )
-                            throws IOException
-                        {
-                            fco.write( item );
-                        }
-                    } );
-                    stream.close();
-
-                    // Replace file with temporary file
-                    if( !file.exists() || file.delete() )
-                    {
-                        if( ! tmpFile.renameTo( file ) )
-                        {
-                            // TODO: What can be done in this case?
-                            System.err.println( "Unable to rename file: " + tmpFile + " to " + file );
-                        }
-                    }
-                }
-                catch( IOException e )
-                {
-                    // We failed writing - close and delete
-                    stream.close();
-                    if( ! tmpFile.delete() )
-                    {
-                        System.err.println("Unable to delete temporary file." );
-                        tmpFile.deleteOnExit();
-                    }
-
-                }
-                catch( Throwable senderThrowableType )
-                {
-                    // We failed writing - close and delete
-                    stream.close();
-                    if( ! tmpFile.delete() )
-                    {
-                        System.err.println("Unable to delete temporary file." );
-                        tmpFile.deleteOnExit();
-                    }
-                    throw (SenderThrowableType) senderThrowableType;
-                }
-            }
-        };
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Write ByteBuffer data to an OutputStream.
-     *
-     * @param stream Destination OutputStream
-     *
-     * @return The Output of ByteBuffer that will be backed by the OutputStream.
-     */
-    public static Output<ByteBuffer, IOException> byteBuffer( final OutputStream stream )
-    // END SNIPPET: method
-    {
-        return new Output<ByteBuffer, IOException>()
-        {
-            @Override
-            public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends ByteBuffer, SenderThrowableType> sender )
-                throws IOException, SenderThrowableType
-            {
-                try
-                {
-                    sender.sendTo( new Receiver<ByteBuffer, IOException>()
-                    {
-                        @Override
-                        public void receive( ByteBuffer item )
-                            throws IOException
-                        {
-                            if( item.hasArray() )
-                            {
-                                stream.write( item.array(), item.arrayOffset(), item.limit() );
-                            }
-                            else
-                            {
-                                for( int i = 0; i < item.limit(); i++ )
-                                {
-                                    stream.write( item.get( i ) );
-                                }
-                            }
-                        }
-                    } );
-                }
-                finally
-                {
-                    stream.close();
-                }
-            }
-        };
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Write byte array data to a file. If the writing or sending of data fails the file will be deleted.
-     *
-     * @param file The File to be written to.
-     * @param bufferSize The size of the ByteBuffer.
-     *
-     * @return An Output instance that will write to the given File.
-     */
-    public static Output<byte[], IOException> bytes( final File file, final int bufferSize )
-    // END SNIPPET: method
-    {
-        return new Output<byte[], IOException>()
-        {
-            @Override
-            @SuppressWarnings( "unchecked" )
-            public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends byte[], SenderThrowableType> sender )
-                throws IOException, SenderThrowableType
-            {
-                File tmpFile = Files.createTemporayFileOf( file );
-                final OutputStream stream = new BufferedOutputStream( new FileOutputStream( tmpFile ), bufferSize );
-
-                try
-                {
-                    sender.sendTo( new Receiver<byte[], IOException>()
-                    {
-                        @Override
-                        public void receive( byte[] item )
-                            throws IOException
-                        {
-                            stream.write( item );
-                        }
-                    } );
-                    stream.close();
-
-                    // Replace file with temporary file
-                    if( !file.exists() || file.delete() )
-                    {
-                        if( ! tmpFile.renameTo( file ) )
-                        {
-                            // TODO: WHAT???
-                            System.err.println( "Unable to rename " + tmpFile + " to " + file );
-                        }
-                    }
-                }
-                catch( IOException e )
-                {
-                    // We failed writing - close and delete
-                    stream.close();
-                    if( ! tmpFile.delete() )
-                    {
-                        System.err.println("Unable to delete temporary file." );
-                        tmpFile.deleteOnExit();
-                    }
-                }
-                catch( Throwable senderThrowableType )
-                {
-                    // We failed writing - close and delete
-                    stream.close();
-                    if( ! tmpFile.delete() )
-                    {
-                        System.err.println("Unable to delete temporary file." );
-                        tmpFile.deleteOnExit();
-                    }
-                    throw (SenderThrowableType) senderThrowableType;
-                }
-            }
-        };
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Do nothing. Use this if you have all logic in filters and/or specifications
-     *
-     * @param <T> The item type.
-     *
-     * @return An Output instance that ignores all data.
-     */
-    public static <T> Output<T, RuntimeException> noop()
-    // END SNIPPET: method
-    {
-        return withReceiver( new Receiver<T, RuntimeException>()
-        {
-            @Override
-            public void receive( T item )
-                throws RuntimeException
-            {
-                // Do nothing
-            }
-        } );
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Use given receiver as Output. Use this if there is no need to create a "transaction" for each transfer, and no need
-     * to do batch writes or similar.
-     *
-     * @param <T> The item type
-     * @param receiver receiver for this Output
-     *
-     * @return An Output instance backed by a Receiver of items.
-     */
-    public static <T, ReceiverThrowableType extends Throwable> Output<T, ReceiverThrowableType> withReceiver( final Receiver<T, ReceiverThrowableType> receiver )
-    // END SNIPPET: method
-    {
-        return new Output<T, ReceiverThrowableType>()
-        {
-            @Override
-            public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends T, SenderThrowableType> sender )
-                throws ReceiverThrowableType, SenderThrowableType
-            {
-                sender.sendTo( receiver );
-            }
-        };
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Write objects to System.out.println.
-     *
-     * @return An Output instance that is backed by System.out
-     */
-    public static Output<Object, RuntimeException> systemOut()
-    // END SNIPPET: method
-    {
-        return new Output<Object, RuntimeException>()
-        {
-            @Override
-            public <SenderThrowableType extends Throwable> void receiveFrom( Sender<?, SenderThrowableType> sender )
-                throws RuntimeException, SenderThrowableType
-            {
-                sender.sendTo( new Receiver<Object, RuntimeException>()
-                {
-                    @Override
-                    public void receive( Object item )
-                    {
-                        System.out.println( item );
-                    }
-                } );
-            }
-        };
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Write objects to System.err.println.
-     *
-     * @return An Output instance backed by System.in
-     */
-    @SuppressWarnings( "UnusedDeclaration" )
-    public static Output<Object, RuntimeException> systemErr()
-    // END SNIPPET: method
-    {
-        return new Output<Object, RuntimeException>()
-        {
-            @Override
-            public <SenderThrowableType extends Throwable> void receiveFrom( Sender<?, SenderThrowableType> sender )
-                throws RuntimeException, SenderThrowableType
-            {
-                sender.sendTo( new Receiver<Object, RuntimeException>()
-                {
-                    @Override
-                    public void receive( Object item )
-                    {
-                        System.err.println( item );
-                    }
-                } );
-            }
-        };
-    }
-
-    // START SNIPPET: method
-
-    /**
-     * Add items to a collection
-     */
-    public static <T> Output<T, RuntimeException> collection( final Collection<T> collection )
-    // END SNIPPET: method
-    {
-        return new Output<T, RuntimeException>()
-        {
-            @Override
-            public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends T, SenderThrowableType> sender )
-                throws RuntimeException, SenderThrowableType
-            {
-                sender.sendTo( new Receiver<T, RuntimeException>()
-                {
-                    @Override
-                    public void receive( T item )
-                        throws RuntimeException
-                    {
-                        collection.add( item );
-                    }
-                } );
-            }
-        };
-    }
-
-    private Outputs()
-    {
-    }
-}
diff --git a/core/io/src/main/java/org/qi4j/io/Receiver.java b/core/io/src/main/java/org/qi4j/io/Receiver.java
deleted file mode 100644
index 6318cdf..0000000
--- a/core/io/src/main/java/org/qi4j/io/Receiver.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.io;
-
-/**
- * Receiver of items during a specific transfer from an Input to an Output.
- */
-// START SNIPPET: receiver
-public interface Receiver<T, ReceiverThrowableType extends Throwable>
-{
-// END SNIPPET: receiver
-    /**
-     * Receive a single item of the given type. The receiver should process it
-     * and optionally throw an exception if it fails.
-     *
-     * @param item
-     *
-     * @throws ReceiverThrowableType
-     */
-// START SNIPPET: receiver
-    void receive( T item )
-        throws ReceiverThrowableType;
-}
-// END SNIPPET: receiver
diff --git a/core/io/src/main/java/org/qi4j/io/Sender.java b/core/io/src/main/java/org/qi4j/io/Sender.java
deleted file mode 100644
index 05ac007..0000000
--- a/core/io/src/main/java/org/qi4j/io/Sender.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.io;
-
-/**
- * Sender of items for a particular transfer from an Input to an Output
- */
-// START SNIPPET: sender
-public interface Sender<T, SenderThrowableType extends Throwable>
-{
-// END SNIPPET: sender
-    /**
-     * The sender should send all items it holds to the receiver by invoking receiveItem for each item.
-     *
-     * If the receive fails it should properly close any open resources.
-     *
-     * @param receiver
-     * @param <ReceiverThrowableType>
-     *
-     * @throws ReceiverThrowableType
-     * @throws SenderThrowableType
-     */
-// START SNIPPET: sender
-    <ReceiverThrowableType extends Throwable> void sendTo( Receiver<? super T, ReceiverThrowableType> receiver )
-        throws ReceiverThrowableType, SenderThrowableType;
-}
-// END SNIPPET: sender
diff --git a/core/io/src/main/java/org/qi4j/io/Transforms.java b/core/io/src/main/java/org/qi4j/io/Transforms.java
deleted file mode 100644
index a5d0040..0000000
--- a/core/io/src/main/java/org/qi4j/io/Transforms.java
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.io;
-
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
-import java.text.MessageFormat;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Lock;
-import java.util.logging.Logger;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Specification;
-
-/**
- * Utility class for I/O transforms
- */
-public class Transforms
-{
-    /**
-     * Filter items in a transfer by applying the given Specification to each item.
-     *
-     * @param specification            The Specification defining the items to not filter away.
-     * @param output                   The Output instance to receive to result.
-     * @param <T>                      The item type
-     * @param <Receiver2ThrowableType> Exception type that might be thrown by the Receiver.
-     *
-     * @return And Output encapsulation the filter operation.
-     */
-    public static <T, Receiver2ThrowableType extends Throwable> Output<T, Receiver2ThrowableType> filter( final Specification<? super T> specification,
-                                                                                                          final Output<T, Receiver2ThrowableType> output
-    )
-    {
-        return new Output<T, Receiver2ThrowableType>()
-        {
-            @Override
-            public <SenderThrowableType extends Throwable> void receiveFrom( final Sender<? extends T, SenderThrowableType> sender )
-                throws Receiver2ThrowableType, SenderThrowableType
-            {
-                output.receiveFrom( new Sender<T, SenderThrowableType>()
-                {
-                    @Override
-                    public <ReceiverThrowableType extends Throwable> void sendTo( final Receiver<? super T, ReceiverThrowableType> receiver )
-                        throws ReceiverThrowableType, SenderThrowableType
-                    {
-                        sender.sendTo( new Receiver<T, ReceiverThrowableType>()
-                        {
-                            @Override
-                            public void receive( T item )
-                                throws ReceiverThrowableType
-                            {
-                                if( specification.satisfiedBy( item ) )
-                                {
-                                    receiver.receive( item );
-                                }
-                            }
-                        } );
-                    }
-                } );
-            }
-        };
-    }
-
-    /**
-     * Map items in a transfer from one type to another by applying the given function.
-     *
-     * @param function                 The transformation function to apply to the streaming items.
-     * @param output                   The output to receive the transformed items.
-     * @param <From>                   The type of the incoming items.
-     * @param <To>                     The type of the transformed items.
-     * @param <Receiver2ThrowableType> The exception type that the Receiver might throw.
-     *
-     * @return An Output instance that encapsulates the map transformation.
-     */
-    public static <From, To, Receiver2ThrowableType extends Throwable> Output<From, Receiver2ThrowableType> map( final Function<? super From, ? extends To> function,
-                                                                                                                 final Output<To, Receiver2ThrowableType> output
-    )
-    {
-        return new Output<From, Receiver2ThrowableType>()
-        {
-            @Override
-            public <SenderThrowableType extends Throwable> void receiveFrom( final Sender<? extends From, SenderThrowableType> sender )
-                throws Receiver2ThrowableType, SenderThrowableType
-            {
-                output.receiveFrom( new Sender<To, SenderThrowableType>()
-                {
-                    @Override
-                    public <ReceiverThrowableType extends Throwable> void sendTo( final Receiver<? super To, ReceiverThrowableType> receiver )
-                        throws ReceiverThrowableType, SenderThrowableType
-                    {
-                        sender.sendTo( new Receiver<From, ReceiverThrowableType>()
-                        {
-                            @Override
-                            public void receive( From item )
-                                throws ReceiverThrowableType
-                            {
-                                receiver.receive( function.map( item ) );
-                            }
-                        } );
-                    }
-                } );
-            }
-        };
-    }
-
-    /**
-     * Apply the given function to items in the transfer that match the given specification. Other items will pass
-     * through directly.
-     *
-     * @param specification            The Specification defining which items should be transformed.
-     * @param function                 The transformation function.
-     * @param output                   The Output that will receive the resulting items.
-     * @param <T>                      The item type. Items can not be transformed to a new type.
-     * @param <Receiver2ThrowableType> The exception that the Receiver might throw.
-     *
-     * @return An Output instance that encapsulates the operation.
-     */
-    public static <T, Receiver2ThrowableType extends Throwable> Output<T, Receiver2ThrowableType> filteredMap( final Specification<? super T> specification,
-                                                                                                               final Function<? super T, ? extends T> function,
-                                                                                                               final Output<T, Receiver2ThrowableType> output
-    )
-    {
-        return new Output<T, Receiver2ThrowableType>()
-        {
-            @Override
-            public <SenderThrowableType extends Throwable> void receiveFrom( final Sender<? extends T, SenderThrowableType> sender )
-                throws Receiver2ThrowableType, SenderThrowableType
-            {
-                output.receiveFrom( new Sender<T, SenderThrowableType>()
-                {
-                    @Override
-                    public <ReceiverThrowableType extends Throwable> void sendTo( final Receiver<? super T, ReceiverThrowableType> receiver )
-                        throws ReceiverThrowableType, SenderThrowableType
-                    {
-                        sender.sendTo( new Receiver<T, ReceiverThrowableType>()
-                        {
-                            @Override
-                            public void receive( T item )
-                                throws ReceiverThrowableType
-                            {
-                                if( specification.satisfiedBy( item ) )
-                                {
-                                    receiver.receive( function.map( item ) );
-                                }
-                                else
-                                {
-                                    receiver.receive( item );
-                                }
-                            }
-                        } );
-                    }
-                } );
-            }
-        };
-    }
-
-    /**
-     * Wrapper for Outputs that uses a lock whenever a transfer is instantiated. Typically a read-lock would be used on
-     * the sending side and a write-lock would be used on the receiving side. Inputs can use this as well to create a
-     * wrapper on the send side when transferTo is invoked.
-     *
-     * @param lock                    the lock to be used for transfers
-     * @param output                  output to be wrapped
-     * @param <T>                     The Item type
-     * @param <Receiver2ThrowableType> The Exception type that the Receiver might throw.
-     *
-     * @return Output wrapper that uses the given lock during transfers.
-     */
-    public static <T, Receiver2ThrowableType extends Throwable> Output<T, Receiver2ThrowableType> lock( final Lock lock,
-                                                                                                      final Output<T, Receiver2ThrowableType> output
-    )
-    {
-        return new Output<T, Receiver2ThrowableType>()
-        {
-            @Override
-            public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends T, SenderThrowableType> sender )
-                throws Receiver2ThrowableType, SenderThrowableType
-            {
-                /**
-                 * Fix for this bug:
-                 * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6822370
-                 */
-                while( true )
-                {
-                    try
-                    {
-                        //noinspection StatementWithEmptyBody
-                        while( !lock.tryLock( 1000, TimeUnit.MILLISECONDS ) )
-                        {
-                            // On timeout, try again
-                        }
-                        break; // Finally got a lock
-                    }
-                    catch( InterruptedException e )
-                    {
-                        // Try again
-                    }
-                }
-
-                try
-                {
-                    output.receiveFrom( sender );
-                }
-                finally
-                {
-                    lock.unlock();
-                }
-            }
-        };
-    }
-
-    /**
-     * Wrapper for Outputs that uses a lock whenever a transfer is instantiated. Typically a read-lock would be used on the sending side and a write-lock
-     * would be used on the receiving side.
-     *
-     * @param lock                  the lock to be used for transfers
-     * @param input                 input to be wrapped
-     * @param <T>                   The item type.
-     * @param <SenderThrowableType> The Exception type that the Sender might throw.
-     *
-     * @return Input wrapper that uses the given lock during transfers.
-     */
-    public static <T, SenderThrowableType extends Throwable> Input<T, SenderThrowableType> lock( final Lock lock,
-                                                                                                 final Input<T, SenderThrowableType> input
-    )
-    {
-        return new Input<T, SenderThrowableType>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super T, ReceiverThrowableType> output )
-                throws SenderThrowableType, ReceiverThrowableType
-            {
-                /**
-                 * Fix for this bug:
-                 * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6822370
-                 */
-                while( true )
-                {
-                    try
-                    {
-                        //noinspection StatementWithEmptyBody
-                        while( !( lock.tryLock() || lock.tryLock( 1000, TimeUnit.MILLISECONDS ) ) )
-                        {
-                            // On timeout, try again
-                        }
-                        break; // Finally got a lock
-                    }
-                    catch( InterruptedException e )
-                    {
-                        // Try again
-                    }
-                }
-
-                try
-                {
-                    input.transferTo( output );
-                }
-                finally
-                {
-                    lock.unlock();
-                }
-            }
-        };
-    }
-
-    /**
-     * Count the number of items in the transfer.
-     *
-     * @param <T>
-     */
-    // START SNIPPET: counter
-    public static class Counter<T>
-        implements Function<T, T>
-    {
-        private volatile long count = 0;
-
-        public long count()
-        {
-            return count;
-        }
-
-        @Override
-        public T map( T t )
-        {
-            count++;
-            return t;
-        }
-    }
-    // END SNIPPET: counter
-
-    /**
-     * Convert strings to bytes using the given CharSet
-     */
-    @SuppressWarnings( "UnusedDeclaration" )
-    public static class String2Bytes
-        implements Function<String, byte[]>
-    {
-        private Charset charSet;
-
-        public String2Bytes( Charset charSet )
-        {
-            this.charSet = charSet;
-        }
-
-        @Override
-        public byte[] map( String s )
-        {
-            return s.getBytes( charSet );
-        }
-    }
-
-    /**
-     * Convert ByteBuffers to Strings using the given CharSet
-     */
-    public static class ByteBuffer2String
-        implements Function<ByteBuffer, String>
-    {
-        private Charset charSet;
-
-        public ByteBuffer2String( Charset charSet )
-        {
-            this.charSet = charSet;
-        }
-
-        @Override
-        public String map( ByteBuffer buffer )
-        {
-            return new String( buffer.array(), charSet );
-        }
-    }
-
-    /**
-     * Convert objects to Strings using .toString()
-     */
-    @SuppressWarnings( "UnusedDeclaration" )
-    public static class ObjectToString
-        implements Function<Object, String>
-    {
-        @Override
-        public String map( Object o )
-        {
-            return o.toString();
-        }
-    }
-
-    /**
-     * Log the toString() representation of transferred items to the given log. The string is first formatted using MessageFormat
-     * with the given format.
-     *
-     * @param <T>
-     */
-    public static class Log<T>
-        implements Function<T, T>
-    {
-        private Logger logger;
-        private MessageFormat format;
-
-        public Log( Logger logger, String format )
-        {
-            this.logger = logger;
-            this.format = new MessageFormat( format );
-        }
-
-        @Override
-        public T map( T item )
-        {
-            logger.info( format.format( new String[]{ item.toString() } ) );
-            return item;
-        }
-    }
-
-    /**
-     * Track progress of transfer by emitting a log message in given intervals.
-     *
-     * If logger or format is null, then you need to override the logProgress to do something
-     *
-     * @param <T> type of items to be transferred
-     */
-    // START SNIPPET: progress
-    public static class ProgressLog<T>
-        implements Function<T, T>
-    {
-        private Counter<T> counter;
-        private Log<String> log;
-        private final long interval;
-
-        public ProgressLog( Logger logger, String format, long interval )
-        {
-            this.interval = interval;
-            if( logger != null && format != null )
-            {
-                log = new Log<>( logger, format );
-            }
-            counter = new Counter<>();
-        }
-
-        public ProgressLog( long interval )
-        {
-            this.interval = interval;
-            counter = new Counter<>();
-        }
-
-        @Override
-        public T map( T t )
-        {
-            counter.map( t );
-            if( counter.count % interval == 0 )
-            {
-                logProgress();
-            }
-            return t;
-        }
-
-        // Override this to do something other than logging the progress
-        protected void logProgress()
-        {
-            if( log != null )
-            {
-                log.map( counter.count + "" );
-            }
-        }
-    }
-    // END SNIPPET: progress
-}
diff --git a/core/io/src/main/java/org/qi4j/io/package.html b/core/io/src/main/java/org/qi4j/io/package.html
deleted file mode 100644
index aac8a54..0000000
--- a/core/io/src/main/java/org/qi4j/io/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>I/O API.</h2>
-    </body>
-</html>
diff --git a/core/io/src/test/java/org/qi4j/io/InputOutputTest.java b/core/io/src/test/java/org/qi4j/io/InputOutputTest.java
deleted file mode 100644
index 220e856..0000000
--- a/core/io/src/test/java/org/qi4j/io/InputOutputTest.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.io;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.io.Writer;
-import java.net.URL;
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
-import java.rmi.RemoteException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-import java.util.logging.Logger;
-import org.hamcrest.CoreMatchers;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Visitor;
-
-import static java.util.Arrays.asList;
-import static org.qi4j.functional.Iterables.iterable;
-import static org.qi4j.io.Inputs.text;
-import static org.qi4j.io.Transforms.lock;
-import static org.qi4j.test.util.Assume.assumeConnectivity;
-
-/**
- * Test Input/Output.
- */
-public class InputOutputTest
-{
-    @Test
-    public void testCopyFileNoAPI()
-        throws IOException
-    {
-        File source = sourceFile();
-        File destination = File.createTempFile( "test", ".txt" );
-        destination.deleteOnExit();
-
-        BufferedReader reader = new BufferedReader( new FileReader( source ) );
-        long count = 0;
-        try
-        {
-            BufferedWriter writer = new BufferedWriter( new FileWriter( destination ) );
-            try
-            {
-                String line;
-                while( ( line = reader.readLine() ) != null )
-                {
-                    count++;
-                    writer.append( line ).append( '\n' );
-                }
-                writer.close();
-            }
-            catch( IOException e )
-            {
-                writer.close();
-                destination.delete();
-            }
-        }
-        finally
-        {
-            reader.close();
-        }
-        System.out.println( count );
-    }
-
-    @Test
-    public void testInputOutput()
-        throws IOException
-    {
-        URL source = getClass().getResource( "/iotest.txt" );
-        File destination = File.createTempFile( "test", ".txt" );
-        destination.deleteOnExit();
-        text( source ).transferTo( Outputs.text( destination ) );
-    }
-
-    @Test
-    public void testCopyFile()
-        throws IOException
-    {
-        File source = sourceFile();
-        File tempFile = File.createTempFile( "test", ".txt" );
-        tempFile.deleteOnExit();
-
-        Inputs.byteBuffer( source, 1024 ).transferTo( Outputs.byteBuffer( tempFile ) );
-
-        Assert.assertThat( tempFile.length(), CoreMatchers.equalTo( source.length() ) );
-    }
-
-    @Test
-    public void testCopyURL()
-        throws IOException
-    {
-        assumeConnectivity( "www.google.com", 80 );
-
-        File tempFile = File.createTempFile( "test", ".txt" );
-        tempFile.deleteOnExit();
-
-        Inputs.text( new URL( "http://www.google.com" ) ).transferTo( Outputs.text( tempFile ) );
-
-// Uncomment to check output        Inputs.text( tempFile ).transferTo( Outputs.systemOut() );
-    }
-
-    @Test
-    public void testCopyFileStreams()
-        throws IOException
-    {
-        File source = sourceFile();
-        File tempFile = File.createTempFile( "test", ".txt" );
-        tempFile.deleteOnExit();
-
-        Inputs.byteBuffer( new FileInputStream( source ), 1024 ).transferTo(
-            Outputs.byteBuffer( new FileOutputStream( tempFile ) ) );
-
-        Assert.assertThat( tempFile.length(), CoreMatchers.equalTo( source.length() ) );
-    }
-
-    @Test
-    public void testLog()
-        throws IOException
-    {
-        File source = sourceFile();
-
-        text( source ).transferTo(
-            Transforms.map( new Transforms.Log<String>( Logger.getLogger( getClass().getName() ), "Line: {0}" ),
-                            Outputs.<String>noop() ) );
-    }
-
-    @Test
-    public void testProgressLog()
-        throws Throwable
-    {
-        Integer[] data = new Integer[ 105 ];
-        Arrays.fill( data, 42 );
-
-        Inputs.iterable( iterable( data ) ).transferTo(
-            Transforms.map(
-                new Transforms.ProgressLog<Integer>(
-                    Logger.getLogger( InputOutputTest.class.getName() ), "Data transferred: {0}", 10 ),
-                Outputs.<Integer>noop() ) );
-    }
-
-    @Test
-    public void testTextInputsOutputs()
-        throws IOException
-    {
-        File tempFile = File.createTempFile( "test", ".txt" );
-        tempFile.deleteOnExit();
-        File sourceFile = sourceFile();
-        Transforms.Counter<String> stringCounter = new Transforms.Counter<>();
-        text( sourceFile ).transferTo(
-            Transforms.map(
-                stringCounter,
-                Transforms.map( new Function<String, String>()
-                {
-                    public String map( String s )
-                    {
-                        System.out.println( s );
-                        return s;
-                    }
-                }, Outputs.text( tempFile ) )
-            )
-        );
-
-        Assert.assertThat( tempFile.length(), CoreMatchers.equalTo( sourceFile.length() ) );
-        Assert.assertThat( stringCounter.count(), CoreMatchers.equalTo( 4L ) );
-    }
-
-    @Test
-    public void testCombineInputs()
-        throws IOException
-    {
-        File tempFile = File.createTempFile( "test", ".txt" );
-        tempFile.deleteOnExit();
-        File sourceFile = sourceFile();
-        Transforms.Counter<String> stringCounter = new Transforms.Counter<>();
-        Input<String, IOException> text1 = text( sourceFile );
-        Input<String, IOException> text2 = text( sourceFile );
-        List<Input<String, IOException>> list = createList( text1, text2 );
-        Inputs.combine( list ).transferTo(
-            Transforms.map(
-                stringCounter,
-                Transforms.map( new Function<String, String>()
-            {
-                public String map( String s )
-                {
-                    System.out.println( s );
-                    return s;
-                }
-                }, Outputs.text( tempFile ) )
-            )
-        );
-
-        Assert.assertThat( tempFile.length(), CoreMatchers.equalTo( sourceFile.length() * 2 ) );
-        Assert.assertThat( stringCounter.count(), CoreMatchers.equalTo( 8L ) );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private List<Input<String, IOException>> createList( Input<String, IOException> text1,
-                                                         Input<String, IOException> text2
-    )
-    {
-        return asList( text1, text2 );
-    }
-
-    @Test( expected = IOException.class )
-    public void testInputOutputOutputException()
-        throws IOException
-    {
-
-        text( sourceFile() ).
-            transferTo( writerOutput( new Writer()
-                    {
-                        @Override
-                        public void write( char[] cbuf, int off, int len )
-                        throws IOException
-                        {
-                            throw new IOException();
-                        }
-
-                        @Override
-                        public void flush()
-                        throws IOException
-                        {
-                            throw new IOException();
-                        }
-
-                        @Override
-                        public void close()
-                        throws IOException
-                        {
-                            throw new IOException();
-                        }
-            } ) );
-    }
-
-    @Test( expected = RemoteException.class )
-    public void testInputOutputInputException()
-        throws IOException
-    {
-
-        Input<String, RemoteException> input = new Input<String, RemoteException>()
-        {
-            @Override
-            public <OutputThrowableType extends Throwable> void transferTo( Output<? super String, OutputThrowableType> output )
-                throws RemoteException, OutputThrowableType
-            {
-                output.receiveFrom( new Sender<String, RemoteException>()
-                {
-                    @Override
-                    public <ReceiverThrowableType extends Throwable> void sendTo( Receiver<? super String, ReceiverThrowableType> receiverThrowableTypeReceiver )
-                        throws ReceiverThrowableType, RemoteException
-                    {
-                        throw new RemoteException();
-                    }
-                } );
-            }
-        };
-
-        input.transferTo(
-            Transforms.map(
-                new Transforms.Log<String>( Logger.getLogger( getClass().getName() ), "Line: {0}" ),
-                Outputs.systemOut()
-            )
-        );
-    }
-
-    @Test
-    public void testLock()
-        throws IOException
-    {
-        Lock inputLock = new ReentrantLock();
-        Lock outputLock = new ReentrantLock();
-
-        URL source = getClass().getResource( "/iotest.txt" );
-        File destination = File.createTempFile( "test", ".txt" );
-        destination.deleteOnExit();
-        lock( inputLock, text( source ) ).transferTo( lock( outputLock, Outputs.text( destination ) ) );
-    }
-
-    @Test
-    public void testGenerics()
-    {
-        ArrayList<Object> objects = new ArrayList<>( 3 );
-        Inputs.iterable( Arrays.asList( "Foo", "Bar", "Xyzzy" ) ).transferTo( Outputs.collection( objects ) );
-
-        Inputs.iterable( objects ).transferTo( Outputs.systemOut() );
-    }
-
-    @Test
-    public void testOutputstreamInput()
-        throws Throwable
-    {
-        Input<ByteBuffer, IOException> input = Inputs.output( new Visitor<OutputStream, IOException>()
-        {
-            @Override
-            public boolean visit( OutputStream visited )
-                throws IOException
-            {
-                try( PrintWriter writer = new PrintWriter( visited ) )
-                {
-                    writer.print( "Hello World!" );
-                }
-                return true;
-            }
-        }, 256 );
-
-        input.transferTo( Transforms.map( new Transforms.ByteBuffer2String( Charset.defaultCharset() ), Outputs.systemOut() ) );
-        input.transferTo( Transforms.map( new Transforms.ByteBuffer2String( Charset.defaultCharset() ), Outputs.systemOut() ) );
-    }
-
-    public Output<String, IOException> writerOutput( final Writer writer )
-    {
-        return new Output<String, IOException>()
-        {
-            @Override
-            public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends String, SenderThrowableType> sender )
-                throws IOException, SenderThrowableType
-            {
-                // Here we initiate the transfer
-                System.out.println( "Open output" );
-                final StringBuilder builder = new StringBuilder();
-                try
-                {
-                    sender.sendTo( new Receiver<String, IOException>()
-                    {
-                        @Override
-                        public void receive( String item )
-                            throws IOException
-                        {
-                            System.out.println( "Receive input" );
-
-                            // Here we can do batch writes if needed
-                            builder.append( item ).append( "\n" );
-                        }
-                    } );
-
-                    // If transfer went well, do something with it
-                    writer.write( builder.toString() );
-                    writer.flush();
-                    System.out.println( "Output written" );
-                }
-                catch( IOException e )
-                {
-                    // If transfer failed, potentially rollback writes
-                    System.out.println( "Input failed" );
-                    throw e;
-                }
-            }
-        };
-    }
-
-    private File sourceFile()
-    {
-        String path = getClass().getResource( "/iotest.txt" ).getFile();
-        return new File( path.replaceAll( "%20", " " ) );
-    }
-}
diff --git a/core/io/src/test/java/org/qi4j/io/docsupport/IoDocs.java b/core/io/src/test/java/org/qi4j/io/docsupport/IoDocs.java
deleted file mode 100644
index 6028886..0000000
--- a/core/io/src/test/java/org/qi4j/io/docsupport/IoDocs.java
+++ /dev/null
@@ -1,53 +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.qi4j.io.docsupport;
-
-import java.io.File;
-import java.io.IOException;
-import org.qi4j.io.Inputs;
-import org.qi4j.io.Outputs;
-
-// START SNIPPET: io2
-import org.qi4j.io.Transforms.Counter;
-import static org.qi4j.io.Transforms.map;
-// END SNIPPET: io2
-
-public class IoDocs
-{
-    public static void main( String[] args )
-        throws IOException
-    {
-        {
-// START SNIPPET: io1
-            File source = new File( "source.txt" );
-            File destination = new File( "destination.txt" );
-            Inputs.text( source ).transferTo( Outputs.text( destination ) );
-// END SNIPPET: io1
-        }
-        {
-// START SNIPPET: io2
-            File source = new File( "source.txt" );
-            File destination = new File( "destination.txt" );
-            Counter<String> counter = new Counter<String>();
-            Inputs.text( source ).transferTo( map(counter, Outputs.text(destination) ));
-            System.out.println( "Lines: " + counter.count() );
-// END SNIPPET: io2
-        }
-    }
-}
diff --git a/core/io/src/test/resources/iotest.txt b/core/io/src/test/resources/iotest.txt
deleted file mode 100644
index a6d84a8..0000000
--- a/core/io/src/test/resources/iotest.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Test
-of transfer
-from input
-to output
diff --git a/core/runtime/build.gradle b/core/runtime/build.gradle
index 1ddf701..756b3f2 100644
--- a/core/runtime/build.gradle
+++ b/core/runtime/build.gradle
@@ -1,33 +1,42 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-jar { manifest { name = "Apache Zest™ Core Runtime" } }
+apply plugin: 'polygene-core'
+
+jar { manifest { name = "Apache Polygene™ Core Runtime" } }
 
 dependencies {
+  compileOnly libraries.osgi_core
 
-  provided libraries.osgi_core
+  api polygene.core.spi
 
-  compile project( ":org.qi4j.core:org.qi4j.core.bootstrap" )
-  compile libraries.asm
-  compile libraries.asm_util
-  compile libraries.asm_commons
+  implementation polygene.core.bootstrap
+  implementation libraries.asm
+  implementation libraries.asm_util
+  implementation libraries.asm_commons
 
-  testCompile project( ":org.qi4j.core:org.qi4j.core.testsupport" )
-  testCompile project( ":org.qi4j.libraries:org.qi4j.library.constraints" )
+  testImplementation polygene.core.testsupport
+  testImplementation polygene.library( 'constraints' )
+}
+
+compileTestJava {
+  options.fork = true
+  options.compilerArgs += ["-parameters"]
 }
diff --git a/core/runtime/dev-status.xml b/core/runtime/dev-status.xml
index 4f034dc..ba367e6 100644
--- a/core/runtime/dev-status.xml
+++ b/core/runtime/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <codebase>stable</codebase>
     <!--none,early,beta,stable,mature-->
diff --git a/core/runtime/licenses/asm.license b/core/runtime/licenses/asm.license
index 04085ce..ed44300 100644
--- a/core/runtime/licenses/asm.license
+++ b/core/runtime/licenses/asm.license
@@ -1,29 +1,28 @@
-Copyright (c) 2000-2005 INRIA, France Telecom
-All rights reserved.
 
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
+ ASM: a very small and fast Java bytecode manipulation framework
+ Copyright (c) 2000-2011 INRIA, France Telecom
+ All rights reserved.
 
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the names of its
+    contributors may be used to endorse or promote products derived from
+    this software without specific prior written permission.
 
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-3. Neither the name of the copyright holders nor the names of its
-   contributors may be used to endorse or promote products derived from
-   this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/core/runtime/src/docs/runtime.txt b/core/runtime/src/docs/runtime.txt
index ec2c9f3..b0ceea0 100644
--- a/core/runtime/src/docs/runtime.txt
+++ b/core/runtime/src/docs/runtime.txt
@@ -1,16 +1,19 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
+ *  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
  *
- * Licensed 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.
+ *       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.
 //////////////////////
 
 [[core-runtime,Core Runtime]]
@@ -22,10 +25,29 @@
 --------------
 
 First of all, your code should never, ever, have a dependency on Core Runtime. If you think you need this, you should
-probably contact qi4j-dev forum at Google Groups and see if your usecase can either be solved in a existing way or perhaps
-that a new Core SPI Extension is needed.
+probably contact users@polygene.apache.org mailing list and see if your usecase can either be solved in a existing way or
+perhaps that a new Core SPI Extension is needed.
 
 include::../../build/docs/buildinfo/artifact.txt[]
 
 Let's repeat that; *Never, never, ever depend on Core Runtime*. Make sure that the compile dependency does NOT include
-the `org.qi4j.core.runtime` jar.
\ No newline at end of file
+the `org.apache.polygene.core.runtime` jar.
+
+== Custom AssemblyHelper ==
+BUT, there are super-rare cases, where a custom AssemblyHelper might be needed. One known use-case is to introduce
+an alternative bytecode generation algorithm, either better than the one we have, or for a different system, such
+as Dalvik.
+
+To do this, add the +AssemblyHelper+ implementation instance as +metaInfo+ to the +ApplicationAssembly+
+
+We think this is so rare, that the +AssemblyHelper+ class will remain in the +core/runtime+ module and has not
+been promoted to the +core/bootstrap+ module. If you plan to use this feature, please contact the Polygene development
+team at +dev@polygene.apache.org+ to ensure we can make this a better supported, backed by real usecases.
+
+Fictitious example of using a hypothetical Dalvik capable classloader;
+
+[source,java]
+--------------
+source=core/runtime/src/test/java/org/apache/polygene/runtime/bootstrap/docs/DocumentationSupport.java
+tag=customAssemblyHelper
+--------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/PolygeneRuntimeImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/PolygeneRuntimeImpl.java
new file mode 100644
index 0000000..405ade0
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/PolygeneRuntimeImpl.java
@@ -0,0 +1,339 @@
+/*
+ *  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.polygene.runtime;
+
+import java.lang.reflect.InvocationHandler;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.association.AbstractAssociation;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.association.AssociationWrapper;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.ManyAssociationWrapper;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.association.NamedAssociationWrapper;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.property.PropertyWrapper;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
+import org.apache.polygene.bootstrap.ApplicationModelFactory;
+import org.apache.polygene.bootstrap.PolygeneRuntime;
+import org.apache.polygene.runtime.association.AbstractAssociationInstance;
+import org.apache.polygene.runtime.bootstrap.ApplicationAssemblyFactoryImpl;
+import org.apache.polygene.runtime.bootstrap.ApplicationModelFactoryImpl;
+import org.apache.polygene.runtime.composite.ProxyReferenceInvocationHandler;
+import org.apache.polygene.runtime.composite.TransientInstance;
+import org.apache.polygene.runtime.entity.EntityInstance;
+import org.apache.polygene.runtime.property.PropertyInstance;
+import org.apache.polygene.runtime.service.ImportedServiceReferenceInstance;
+import org.apache.polygene.runtime.service.ServiceReferenceInstance;
+import org.apache.polygene.runtime.unitofwork.ModuleUnitOfWork;
+import org.apache.polygene.runtime.value.ValueInstance;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.apache.polygene.spi.entity.EntityState;
+
+import static java.lang.reflect.Proxy.getInvocationHandler;
+import static org.apache.polygene.api.composite.CompositeInstance.compositeInstanceOf;
+
+/**
+ * Incarnation of Polygene.
+ */
+public final class PolygeneRuntimeImpl
+    implements PolygeneSPI, PolygeneRuntime
+{
+    private final ApplicationAssemblyFactory applicationAssemblyFactory;
+    private final ApplicationModelFactory applicationModelFactory;
+
+    public PolygeneRuntimeImpl()
+    {
+        applicationAssemblyFactory = new ApplicationAssemblyFactoryImpl();
+        applicationModelFactory = new ApplicationModelFactoryImpl();
+    }
+
+    @Override
+    public ApplicationAssemblyFactory applicationAssemblyFactory()
+    {
+        return applicationAssemblyFactory;
+    }
+
+    @Override
+    public ApplicationModelFactory applicationModelFactory()
+    {
+        return applicationModelFactory;
+    }
+
+    @Override
+    public PolygeneAPI api()
+    {
+        return this;
+    }
+
+    @Override
+    public PolygeneSPI spi()
+    {
+        return this;
+    }
+
+    // API
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> T dereference( T composite )
+    {
+        InvocationHandler handler = getInvocationHandler( composite );
+        if( handler instanceof ProxyReferenceInvocationHandler )
+        {
+            return (T) ( (ProxyReferenceInvocationHandler) handler ).proxy();
+        }
+        if( handler instanceof CompositeInstance )
+        {
+            return composite;
+        }
+        return null;
+    }
+
+    @Override
+    public ModuleDescriptor moduleOf( Object compositeOrServiceReferenceOrUow )
+    {
+        if( compositeOrServiceReferenceOrUow instanceof Composite )
+        {
+            return compositeInstanceOf( (Composite) compositeOrServiceReferenceOrUow ).module();
+        }
+//        else if( compositeOrServiceReferenceOrUow instanceof ServiceComposite )
+//        {
+//            ServiceComposite composite = (ServiceComposite) compositeOrServiceReferenceOrUow;
+//            InvocationHandler handler = getInvocationHandler( composite );
+//            if( handler instanceof ServiceInstance )
+//            {
+//                return ( (ServiceInstance) handler ).module();
+//            }
+//            return ( (ServiceReferenceInstance.ServiceInvocationHandler) handler ).module();
+//        }
+        else if( compositeOrServiceReferenceOrUow instanceof UnitOfWork )
+        {
+            ModuleUnitOfWork unitOfWork = (ModuleUnitOfWork) compositeOrServiceReferenceOrUow;
+            return unitOfWork.module();
+        }
+        else if( compositeOrServiceReferenceOrUow instanceof ServiceReferenceInstance )
+        {
+            ServiceReferenceInstance<?> reference = (ServiceReferenceInstance<?>) compositeOrServiceReferenceOrUow;
+            return reference.module();
+        }
+        else if( compositeOrServiceReferenceOrUow instanceof ImportedServiceReferenceInstance )
+        {
+            ImportedServiceReferenceInstance<?> importedServiceReference
+                = (ImportedServiceReferenceInstance<?>) compositeOrServiceReferenceOrUow;
+            return importedServiceReference.module();
+        }
+        throw new IllegalArgumentException( "Wrong type. Must be one of "
+                                            + Arrays.asList( TransientComposite.class, ValueComposite.class,
+                                                             EntityComposite.class,
+                                                             ServiceComposite.class, ServiceReference.class,
+                                                             UnitOfWork.class ) );
+    }
+
+    @Override
+    public ModelDescriptor modelDescriptorFor( Object compositeOrServiceReference )
+    {
+        if( compositeOrServiceReference instanceof Composite )
+        {
+            return compositeInstanceOf( (Composite) compositeOrServiceReference ).descriptor();
+        }
+//        else if( compositeOrServiceReference instanceof ServiceComposite )
+//        {
+//            ServiceComposite composite = (ServiceComposite) compositeOrServiceReference;
+//            InvocationHandler handler = getInvocationHandler( composite );
+//            if( handler instanceof ServiceInstance )
+//            {
+//                return ( (ServiceInstance) handler ).descriptor();
+//            }
+//            return ( (ServiceReferenceInstance.ServiceInvocationHandler) handler ).descriptor();
+//        }
+        else if( compositeOrServiceReference instanceof ServiceReferenceInstance )
+        {
+            ServiceReferenceInstance<?> reference = (ServiceReferenceInstance<?>) compositeOrServiceReference;
+            return reference.serviceDescriptor();
+        }
+        else if( compositeOrServiceReference instanceof ImportedServiceReferenceInstance )
+        {
+            ImportedServiceReferenceInstance<?> importedServiceReference
+                = (ImportedServiceReferenceInstance<?>) compositeOrServiceReference;
+            return importedServiceReference.serviceDescriptor();
+        }
+        throw new IllegalArgumentException( "Wrong type. Must be one of "
+                                            + Arrays.asList( TransientComposite.class, ValueComposite.class, EntityComposite.class,
+                                                             ServiceComposite.class, ServiceReference.class,
+                                                             ImportedServiceReferenceInstance.class ) );
+    }
+
+    @Override
+    public CompositeDescriptor compositeDescriptorFor( Object compositeOrServiceReference )
+    {
+        return (CompositeDescriptor) modelDescriptorFor( compositeOrServiceReference );
+    }
+
+    // Descriptors
+
+    @Override
+    public TransientDescriptor transientDescriptorFor( Object transsient )
+    {
+        if( transsient instanceof TransientComposite )
+        {
+            TransientInstance transientInstance = (TransientInstance) compositeInstanceOf( (Composite) transsient );
+            return (TransientDescriptor) transientInstance.descriptor();
+        }
+        throw new IllegalArgumentException( "Wrong type. Must be subtype of " + TransientComposite.class );
+    }
+
+    @Override
+    public StateHolder stateOf( TransientComposite composite )
+    {
+        return compositeInstanceOf( composite ).state();
+    }
+
+    @Override
+    public EntityDescriptor entityDescriptorFor( Object entity )
+    {
+        if( entity instanceof EntityComposite )
+        {
+            EntityInstance entityInstance = (EntityInstance) getInvocationHandler( entity );
+            return entityInstance.entityModel();
+        }
+        throw new IllegalArgumentException( "Wrong type. Must be subtype of " + EntityComposite.class );
+    }
+
+    @Override
+    public AssociationStateHolder stateOf( EntityComposite composite )
+    {
+        return ( (EntityInstance) compositeInstanceOf( composite ) ).state();
+    }
+
+    @Override
+    public ValueDescriptor valueDescriptorFor( Object value )
+    {
+        if( value instanceof ValueComposite )
+        {
+            ValueInstance valueInstance = (ValueInstance) compositeInstanceOf( (Composite) value );
+            return valueInstance.descriptor();
+        }
+        throw new IllegalArgumentException( "Wrong type. {" + value + "} must be subtype of " + ValueComposite.class );
+    }
+
+    @Override
+    public AssociationStateHolder stateOf( ValueComposite composite )
+    {
+        return ( (ValueInstance) compositeInstanceOf( composite ) ).state();
+    }
+
+    @Override
+    public ServiceDescriptor serviceDescriptorFor( Object service )
+    {
+        if( service instanceof ServiceReferenceInstance )
+        {
+            ServiceReferenceInstance<?> ref = (ServiceReferenceInstance<?>) service;
+            return ref.serviceDescriptor();
+        }
+        if( service instanceof ServiceComposite )
+        {
+            ServiceComposite composite = (ServiceComposite) service;
+            return (ServiceDescriptor) compositeInstanceOf( composite ).descriptor();
+        }
+        throw new IllegalArgumentException( "Wrong type. Must be subtype of "
+                                            + ServiceComposite.class + " or " + ServiceReference.class );
+    }
+
+    @Override
+    public PropertyDescriptor propertyDescriptorFor( Property<?> property )
+    {
+        while( property instanceof PropertyWrapper )
+        {
+            property = ( (PropertyWrapper) property ).next();
+        }
+
+        return (PropertyDescriptor) ( (PropertyInstance<?>) property ).propertyInfo();
+    }
+
+    @Override
+    public AssociationDescriptor associationDescriptorFor( AbstractAssociation association )
+    {
+        while( association instanceof AssociationWrapper )
+        {
+            association = ( (AssociationWrapper) association ).next();
+        }
+
+        while( association instanceof ManyAssociationWrapper )
+        {
+            association = ( (ManyAssociationWrapper) association ).next();
+        }
+
+        while( association instanceof NamedAssociationWrapper )
+        {
+            association = ( (NamedAssociationWrapper) association ).next();
+        }
+
+        return (AssociationDescriptor) ( (AbstractAssociationInstance) association ).associationInfo();
+    }
+
+    // SPI
+    @Override
+    public EntityState entityStateOf( EntityComposite composite )
+    {
+        return ( (EntityInstance) compositeInstanceOf( composite ) ).entityState();
+    }
+
+    @Override
+    public EntityReference entityReferenceOf( Association<?> assoc )
+    {
+        return assoc.reference();
+    }
+
+    @Override
+    public Stream<EntityReference> entityReferencesOf( ManyAssociation<?> assoc )
+    {
+        return assoc.references();
+    }
+
+    @Override
+    public Stream<Map.Entry<String, EntityReference>> entityReferencesOf( NamedAssociation<?> assoc )
+    {
+        return assoc.references();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/activation/ActivationDelegate.java b/core/runtime/src/main/java/org/apache/polygene/runtime/activation/ActivationDelegate.java
new file mode 100644
index 0000000..af3a812
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/activation/ActivationDelegate.java
@@ -0,0 +1,384 @@
+/*
+ *  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.polygene.runtime.activation;
+
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivationEvent;
+import org.apache.polygene.api.activation.ActivationEventListener;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.service.ServiceReference;
+
+import static org.apache.polygene.api.activation.ActivationEvent.EventType.ACTIVATED;
+import static org.apache.polygene.api.activation.ActivationEvent.EventType.ACTIVATING;
+import static org.apache.polygene.api.activation.ActivationEvent.EventType.PASSIVATED;
+import static org.apache.polygene.api.activation.ActivationEvent.EventType.PASSIVATING;
+
+/**
+ * This class manage Activation of a target and propagates to children.
+ */
+@SuppressWarnings( "raw" )
+public final class ActivationDelegate
+    extends ActivationEventListenerSupport
+{
+    private final Object target;
+    private final boolean fireEvents;
+    private ActivatorsInstance targetActivators = null;
+    private final LinkedList<Activation> activeChildren = new LinkedList<>();
+
+    /**
+     * Create a new ActivationDelegate that will fire events.
+     * @param target target of Activation
+     */
+    public ActivationDelegate( Object target )
+    {
+        this( target, true );
+    }
+
+    /**
+     * Create a new ActivationDelegate.
+     * @param target target of Activation
+     * @param fireEvents if {@link ActivationEvent}s should be fired
+     */
+    public ActivationDelegate( Object target, boolean fireEvents )
+    {
+        super();
+        this.target = target;
+        this.fireEvents = fireEvents;
+    }
+
+    public void activate( ActivatorsInstance targetActivators, Activation child )
+        throws Exception
+    {
+        activate( targetActivators, Collections.singleton( child ), null );
+    }
+
+    public void activate( ActivatorsInstance targetActivators, Activation child, Runnable callback )
+        throws Exception
+    {
+        activate( targetActivators, Collections.singleton( child ), callback );
+    }
+
+    public void activate( ActivatorsInstance targetActivators, Iterable<? extends Activation> children )
+        throws ActivationException
+    {
+        activate( targetActivators, children, null );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    public void activate( ActivatorsInstance targetActivators, Iterable<? extends Activation> children, Runnable callback )
+        throws ActivationException
+    {
+        if( this.targetActivators != null )
+        {
+            throw new IllegalStateException( "Activation.activate() called multiple times "
+                                             + "or without calling passivate() first!" );
+        }
+
+        try
+        {
+            // Before Activation Events
+            if( fireEvents )
+            {
+                fireEvent( new ActivationEvent( target, ACTIVATING ) );
+            }
+
+            // Before Activation for Activators
+            targetActivators.beforeActivation( target instanceof ServiceReference
+                                               ? new PassiveServiceReference( (ServiceReference) target )
+                                               : target );
+
+            // Activation
+            for( Activation child : children )
+            {
+                if( !activeChildren.contains( child ) )
+                {
+                    child.activate();
+                }
+                activeChildren.addFirst( child );
+            }
+
+            // Internal Activation Callback
+            if( callback != null )
+            {
+                callback.run();
+            }
+
+            // After Activation
+            targetActivators.afterActivation( target );
+
+            // After Activation Events
+            if( fireEvents )
+            {
+                fireEvent( new ActivationEvent( target, ACTIVATED ) );
+            }
+
+            // Activated
+            this.targetActivators = targetActivators;
+        }
+        catch( Exception e )
+        {
+            // Passivate actives
+            try
+            {
+                passivate();
+            }
+            catch( PassivationException e1 )
+            {
+                ActivationException activationEx = new ActivationException( "Unable to Activate application.", e );
+                activationEx.addSuppressed( e1 );
+                throw activationEx;
+            }
+            if( e instanceof ActivationException )
+            {
+                throw ( (ActivationException) e );
+            }
+            throw new ActivationException( "Unable to Activate application.", e );
+        }
+    }
+
+    public void passivate()
+        throws PassivationException
+    {
+        passivate( null );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    public void passivate( Runnable callback )
+        throws PassivationException
+    {
+        Set<Exception> exceptions = new LinkedHashSet<>();
+
+        // Before Passivation Events
+        fireEvents( PASSIVATING, exceptions );
+
+        // Before Passivation for Activators
+        if( targetActivators != null )
+        {
+            try
+            {
+                targetActivators.beforePassivation( target );
+            }
+            catch( PassivationException ex )
+            {
+                exceptions.addAll( ex.causes() );
+            }
+            catch( Exception ex )
+            {
+                exceptions.add( ex );
+            }
+        }
+
+        // Passivation
+        while( !activeChildren.isEmpty() )
+        {
+            passivateOneChild( exceptions );
+        }
+
+        // Internal Passivation Callback
+        if( callback != null )
+        {
+            try
+            {
+                callback.run();
+            }
+            catch( Exception ex )
+            {
+                exceptions.add( ex );
+            }
+        }
+
+        // After Passivation for Activators
+        if( targetActivators != null )
+        {
+            try
+            {
+                targetActivators.afterPassivation( target instanceof ServiceReference
+                                                   ? new PassiveServiceReference( (ServiceReference) target )
+                                                   : target );
+            }
+            catch( PassivationException ex )
+            {
+                exceptions.addAll( ex.causes() );
+            }
+            catch( Exception ex )
+            {
+                exceptions.add( ex );
+            }
+        }
+        targetActivators = null;
+
+        // After Passivation Events
+        fireEvents( PASSIVATED, exceptions );
+
+        // Error handling
+        if( exceptions.isEmpty() )
+        {
+            return;
+        }
+        throw new PassivationException( exceptions );
+    }
+
+    private void fireEvents( ActivationEvent.EventType eventType, Set<Exception> exceptions ) {
+        if( fireEvents )
+        {
+            ActivationEvent event = new ActivationEvent( target, eventType );
+            for( ActivationEventListener listener : listeners )
+            {
+                try
+                {
+                    listener.onEvent( event );
+                }
+                catch( Exception ex )
+                {
+                    if( ex instanceof PassivationException )
+                    {
+                        exceptions.addAll( ( (PassivationException) ex ).causes() );
+                    }
+                    else
+                    {
+                        exceptions.add( ex );
+                    }
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings( "TooBroadCatch" )
+    private void passivateOneChild( Set<Exception> exceptions )
+    {
+        Activation activeChild = activeChildren.removeFirst();
+        try
+        {
+            activeChild.passivate();
+        }
+        catch( PassivationException ex )
+        {
+            exceptions.addAll( ex.causes() );
+        }
+        catch( Exception ex )
+        {
+            exceptions.add( ex );
+        }
+    }
+
+    @SuppressWarnings( "raw" )
+    private static class PassiveServiceReference
+        implements ServiceReference
+    {
+
+        private final ServiceReference reference;
+
+        private PassiveServiceReference( ServiceReference reference )
+        {
+            this.reference = reference;
+        }
+
+        @Override
+        public Identity identity()
+        {
+            return reference.identity();
+        }
+
+        @Override
+        public Object get()
+        {
+            throw new IllegalStateException( "Service is passive, either activating and"
+                                             + " cannot be used yet or passivating and cannot be used anymore." );
+        }
+
+        @Override
+        public boolean isActive()
+        {
+            return false;
+        }
+
+        @Override
+        public boolean isAvailable()
+        {
+            return false;
+        }
+
+        @Override
+        public ModelDescriptor model()
+        {
+            return reference.model();
+        }
+
+        @Override
+        public Stream<Class<?>> types()
+        {
+            return reference.types();
+        }
+
+        @Override
+        public <T> T metaInfo( Class<T> infoType )
+        {
+            return reference.metaInfo( infoType );
+        }
+
+        @Override
+        public void registerActivationEventListener( ActivationEventListener listener )
+        {
+            reference.registerActivationEventListener( listener );
+        }
+
+        @Override
+        public void deregisterActivationEventListener( ActivationEventListener listener )
+        {
+            reference.deregisterActivationEventListener( listener );
+        }
+
+        @Override
+        public int hashCode()
+        {
+            return identity().hashCode();
+        }
+
+        @Override
+        public boolean equals( Object obj )
+        {
+            if( obj == null )
+            {
+                return false;
+            }
+            if( getClass() != obj.getClass() )
+            {
+                return false;
+            }
+            final ServiceReference other = (ServiceReference) obj;
+            return identity().equals( other.identity() );
+        }
+
+        @Override
+        public String toString()
+        {
+            return reference.toString();
+        }
+    }
+
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/activation/ActivationEventListenerSupport.java b/core/runtime/src/main/java/org/apache/polygene/runtime/activation/ActivationEventListenerSupport.java
new file mode 100644
index 0000000..b844756
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/activation/ActivationEventListenerSupport.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.runtime.activation;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.activation.ActivationEvent;
+import org.apache.polygene.api.activation.ActivationEventListener;
+import org.apache.polygene.api.activation.ActivationEventListenerRegistration;
+
+/**
+ * Internal helper for managing registrations and firing events
+ */
+/* package */ class ActivationEventListenerSupport
+    implements ActivationEventListenerRegistration, ActivationEventListener
+{
+    protected List<ActivationEventListener> listeners = new ArrayList<>();
+
+    @Override
+    public void registerActivationEventListener( ActivationEventListener listener )
+    {
+        List<ActivationEventListener> newListeners = new ArrayList<>();
+        newListeners.addAll( listeners );
+        newListeners.add( listener );
+        listeners = newListeners;
+    }
+
+    @Override
+    public void deregisterActivationEventListener( ActivationEventListener listener )
+    {
+        List<ActivationEventListener> newListeners = new ArrayList<>();
+        newListeners.addAll( listeners );
+        newListeners.remove( listener );
+        listeners = newListeners;
+    }
+
+    /* package */ void fireEvent( ActivationEvent event )
+        throws Exception
+    {
+        for( ActivationEventListener listener : listeners )
+        {
+            listener.onEvent( event );
+        }
+    }
+
+    @Override
+    public void onEvent( ActivationEvent event )
+        throws Exception
+    {
+        fireEvent( event );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/activation/ActivatorModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/activation/ActivatorModel.java
new file mode 100644
index 0000000..72d957b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/activation/ActivatorModel.java
@@ -0,0 +1,110 @@
+/*
+ *  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.polygene.runtime.activation;
+
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.activation.ActivatorDescriptor;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.composite.ConstructorsModel;
+import org.apache.polygene.runtime.injection.InjectedFieldsModel;
+import org.apache.polygene.runtime.injection.InjectedMethodsModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+
+/**
+ * Model for a single Activator.
+ *
+ * @param <ActivateeType> Type of the activation target
+ */
+public class ActivatorModel<ActivateeType>
+    implements ActivatorDescriptor, VisitableHierarchy<Object, Object>
+{
+    private final Class<? extends Activator<ActivateeType>> activatorType;
+    private final ConstructorsModel constructorsModel;
+    private final InjectedFieldsModel injectedFieldsModel;
+    private final InjectedMethodsModel injectedMethodsModel;
+
+    public ActivatorModel( Class<? extends Activator<ActivateeType>> activatorType )
+    {
+        this.activatorType = activatorType;
+        this.constructorsModel = new ConstructorsModel( activatorType );
+        this.injectedFieldsModel = new InjectedFieldsModel( activatorType );
+        this.injectedMethodsModel = new InjectedMethodsModel( activatorType );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            if( constructorsModel.accept( visitor ) )
+            {
+                if( injectedFieldsModel.accept( visitor ) )
+                {
+                    injectedMethodsModel.accept( visitor );
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public Activator<ActivateeType> newInstance()
+    {
+        try
+        {
+            return activatorType.newInstance();
+        }
+        catch( InstantiationException | IllegalAccessException ex )
+        {
+            throw new ConstructionException( "Could not instantiate " + activatorType.getName(), ex );
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    public Activator<ActivateeType> newInstance( InjectionContext injectionContext )
+    {
+        try
+        {
+            Activator<ActivateeType> instance = (Activator<ActivateeType>) constructorsModel.newInstance( injectionContext );
+            injectionContext = new InjectionContext( injectionContext.module(), injectionContext.uses(), instance );
+            inject( injectionContext, instance );
+            return instance;
+        }
+        catch( Exception ex )
+        {
+            throw new ConstructionException( "Could not instantiate " + activatorType.getName(), ex );
+        }
+    }
+
+    public void inject( InjectionContext injectionContext, Activator<ActivateeType> instance )
+    {
+        injectedFieldsModel.inject( injectionContext, instance );
+        injectedMethodsModel.inject( injectionContext, instance );
+    }
+
+    @Override
+    public String toString()
+    {
+        return activatorType.getName();
+    }
+
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/activation/ActivatorsInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/activation/ActivatorsInstance.java
new file mode 100644
index 0000000..26ef238
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/activation/ActivatorsInstance.java
@@ -0,0 +1,126 @@
+/*
+ *  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.polygene.runtime.activation;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.activation.PassivationException;
+
+import static java.util.stream.Collectors.toCollection;
+
+/**
+ * Instance of a Polygene Activators of one Activation target. Contains ordered
+ * Activators and roll the Activation on the target.
+ *
+ * @param <ActivateeType> Type of the activation target
+ */
+public class ActivatorsInstance<ActivateeType>
+    implements Activator<ActivateeType>
+{
+    @SuppressWarnings( { "raw", "unchecked" } )
+    public static final ActivatorsInstance EMPTY = new ActivatorsInstance( Collections.emptyList() );
+
+    private final Iterable<Activator<ActivateeType>> activators;
+
+    public ActivatorsInstance( Iterable<Activator<ActivateeType>> activators )
+    {
+        this.activators = activators;
+    }
+
+    @Override
+    public void beforeActivation( ActivateeType activating )
+        throws Exception
+    {
+        for( Activator<ActivateeType> activator : activators )
+        {
+            activator.beforeActivation( activating );
+        }
+    }
+
+    @Override
+    public void afterActivation( ActivateeType activated )
+        throws Exception
+    {
+        for( Activator<ActivateeType> activator : activators )
+        {
+            activator.afterActivation( activated );
+        }
+    }
+
+    @Override
+    public void beforePassivation( ActivateeType passivating )
+        throws Exception
+    {
+        Set<Exception> exceptions = new LinkedHashSet<>();
+        Iterator<Activator<ActivateeType>> iterator = reverseActivatorsIterator();
+        while( iterator.hasNext() )
+        {
+            Activator<ActivateeType> activator = iterator.next();
+            try
+            {
+                activator.beforePassivation( passivating );
+            }
+            catch( Exception ex )
+            {
+                exceptions.add( ex );
+            }
+        }
+        if( !exceptions.isEmpty() )
+        {
+            throw new PassivationException( exceptions );
+        }
+    }
+
+    @Override
+    public void afterPassivation( ActivateeType passivated )
+        throws Exception
+    {
+        Set<Exception> exceptions = new LinkedHashSet<>();
+        Iterator<Activator<ActivateeType>> iterator = reverseActivatorsIterator();
+        while( iterator.hasNext() )
+        {
+            Activator<ActivateeType> activator = iterator.next();
+            try
+            {
+                activator.afterPassivation( passivated );
+            }
+            catch( Exception ex )
+            {
+                exceptions.add( ex );
+            }
+        }
+        if( !exceptions.isEmpty() )
+        {
+            throw new PassivationException( exceptions );
+        }
+    }
+
+    private Iterator<Activator<ActivateeType>> reverseActivatorsIterator()
+    {
+        return StreamSupport.stream( activators.spliterator(), false )
+                            .collect( toCollection( LinkedList::new ) )
+                            .descendingIterator();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/activation/ActivatorsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/activation/ActivatorsModel.java
new file mode 100644
index 0000000..69b3800
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/activation/ActivatorsModel.java
@@ -0,0 +1,98 @@
+/*
+ *  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.polygene.runtime.activation;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.composite.UsesInstance;
+import org.apache.polygene.runtime.injection.InjectionContext;
+
+/**
+ * Activators Model.
+ *
+ * @param <ActivateeType> Type of the activation target
+ */
+public class ActivatorsModel<ActivateeType>
+    implements VisitableHierarchy<Object, Object>
+{
+
+    private final List<ActivatorModel<ActivateeType>> activatorModels = new ArrayList<>();
+    private final Iterable<Class<? extends Activator<ActivateeType>>> activatorsClasses;
+
+    public ActivatorsModel( Iterable<Class<? extends Activator<ActivateeType>>> activatorsClasses )
+    {
+        this.activatorsClasses = activatorsClasses;
+        for( Class<? extends Activator<ActivateeType>> activatorClass : activatorsClasses )
+        {
+            activatorModels.add( new ActivatorModel<>( activatorClass ) );
+        }
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( ActivatorModel<ActivateeType> activatorModel : activatorModels )
+            {
+                if( !activatorModel.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public Iterable<ActivatorModel<ActivateeType>> models()
+    {
+        return activatorModels;
+    }
+
+    public Iterable<Activator<ActivateeType>> newInstances()
+        throws ActivationException
+    {
+        List<Activator<ActivateeType>> activators = new ArrayList<>();
+        for( ActivatorModel<ActivateeType> activatorModel : activatorModels )
+        {
+            activators.add( activatorModel.newInstance() );
+        }
+        return activators;
+    }
+
+    public Iterable<Activator<ActivateeType>> newInstances( ModuleDescriptor module )
+        throws ActivationException
+    {
+        List<Activator<ActivateeType>> activators = new ArrayList<>();
+        for( ActivatorModel<ActivateeType> activatorModel : activatorModels )
+        {
+            InjectionContext injectionContext = new InjectionContext( module, UsesInstance.EMPTY_USES );
+            activators.add( activatorModel.newInstance( injectionContext ) );
+        }
+        return activators;
+    }
+
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/AbstractAssociationInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AbstractAssociationInstance.java
new file mode 100644
index 0000000..51106d3
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AbstractAssociationInstance.java
@@ -0,0 +1,94 @@
+/*
+ *  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.polygene.runtime.association;
+
+import java.lang.reflect.Type;
+import java.util.function.BiFunction;
+import org.apache.polygene.api.association.AbstractAssociation;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+
+/**
+ * Implementation of AbstractAssociation. Includes helper methods for subclasses
+ */
+public abstract class AbstractAssociationInstance<T>
+    implements AbstractAssociation
+{
+    protected AssociationInfo associationInfo;
+    private final BiFunction<EntityReference, Type, Object> entityFunction;
+
+    public AbstractAssociationInstance( AssociationInfo associationInfo,
+                                        BiFunction<EntityReference, Type, Object> entityFunction
+    )
+    {
+        this.associationInfo = associationInfo;
+        this.entityFunction = entityFunction;
+    }
+
+    public AssociationInfo associationInfo()
+    {
+        return associationInfo;
+    }
+
+    public void setAssociationInfo( AssociationInfo newInfo )
+    {
+        this.associationInfo = newInfo;
+    }
+
+    @SuppressWarnings( "unchecked" )
+    protected T getEntity( EntityReference entityId )
+    {
+        if( entityId == null )
+        {
+            return null;
+        }
+
+        return (T) entityFunction.apply( entityId, associationInfo.type() );
+    }
+
+    protected EntityReference getEntityReference( Object composite )
+    {
+        if( composite == null )
+        {
+            return null;
+        }
+
+        return EntityReference.create(((HasIdentity) composite).identity().get());
+    }
+
+    protected void checkType( Object instance )
+    {
+
+        if( instance instanceof HasIdentity || instance == null )
+        {
+            return;
+        }
+        throw new IllegalArgumentException( "Object must be a subtype of org.apache.polygene.api.reference.Identity: " + instance.getClass() );
+    }
+
+    protected void checkImmutable()
+        throws IllegalStateException
+    {
+        if( associationInfo.isImmutable() )
+        {
+            throw new IllegalStateException( "Association [" + associationInfo.qualifiedName() + "] is immutable." );
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/AbstractAssociationModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AbstractAssociationModel.java
new file mode 100644
index 0000000..052ba02
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AbstractAssociationModel.java
@@ -0,0 +1,226 @@
+/*
+ *  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.polygene.runtime.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.Objects;
+import org.apache.polygene.api.association.AbstractAssociation;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.GenericAssociationInfo;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.entity.Aggregated;
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.Immutable;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.Visitable;
+import org.apache.polygene.api.util.Visitor;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.runtime.composite.ValueConstraintsInstance;
+import org.apache.polygene.runtime.model.Binder;
+import org.apache.polygene.runtime.model.Resolution;
+
+public class AbstractAssociationModel<AT>
+    implements AbstractAssociation, AssociationDescriptor, AssociationInfo, Binder, Visitable<AT>
+{
+    private final MetaInfo metaInfo;
+    private final AccessibleObject accessor;
+    private final QualifiedName qualifiedName;
+    private final ValueConstraintsInstance constraints;
+    private final ValueConstraintsInstance associationConstraints;
+    private final boolean queryable;
+    private final boolean immutable;
+    private final boolean aggregated;
+    private Type type;
+    private AssociationInfo builderInfo;
+
+    public AbstractAssociationModel( AccessibleObject accessor,
+                                     ValueConstraintsInstance valueConstraintsInstance,
+                                     ValueConstraintsInstance associationConstraintsInstance,
+                                     MetaInfo metaInfo )
+    {
+        Objects.requireNonNull( accessor );
+        Objects.requireNonNull( metaInfo );
+        this.metaInfo = metaInfo;
+        this.constraints = valueConstraintsInstance;
+        this.associationConstraints = associationConstraintsInstance;
+        this.accessor = accessor;
+        this.type = GenericAssociationInfo.associationTypeOf( accessor );
+        this.qualifiedName = QualifiedName.fromAccessor( accessor );
+        this.immutable = metaInfo.get( Immutable.class ) != null;
+        this.aggregated = metaInfo.get( Aggregated.class ) != null;
+
+        Queryable queryable = accessor.getAnnotation( Queryable.class );
+        this.queryable = queryable == null || queryable.value();
+    }
+
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return metaInfo.get( infoType );
+    }
+
+    @Override
+    public QualifiedName qualifiedName()
+    {
+        return qualifiedName;
+    }
+
+    @Override
+    public Type type()
+    {
+        return type;
+    }
+
+    @Override
+    public boolean isImmutable()
+    {
+        return immutable;
+    }
+
+    @Override
+    public boolean isAggregated()
+    {
+        return aggregated;
+    }
+
+    @Override
+    public AccessibleObject accessor()
+    {
+        return accessor;
+    }
+
+    @Override
+    public boolean queryable()
+    {
+        return queryable;
+    }
+
+    @Override
+    public void checkConstraints( Object value )
+        throws ConstraintViolationException
+    {
+        if( constraints != null )
+        {
+            constraints.checkConstraints( value, accessor );
+        }
+    }
+
+    public void checkAssociationConstraints( AbstractAssociation association )
+        throws ConstraintViolationException
+    {
+        if( associationConstraints != null )
+        {
+            associationConstraints.checkConstraints( association, accessor );
+        }
+    }
+
+    public AssociationInfo builderInfo()
+    {
+        return builderInfo;
+    }
+
+    @Override
+    public void bind( Resolution resolution )
+        throws BindingException
+    {
+        builderInfo = new AssociationInfo()
+        {
+            @Override
+            public boolean isImmutable()
+            {
+                return false;
+            }
+
+            @Override
+            public QualifiedName qualifiedName()
+            {
+                return qualifiedName;
+            }
+
+            @Override
+            public Type type()
+            {
+                return type;
+            }
+
+            @Override
+            public void checkConstraints( Object value )
+                throws ConstraintViolationException
+            {
+                AbstractAssociationModel.this.checkConstraints( value );
+            }
+        };
+
+        if( type instanceof TypeVariable )
+        {
+            Class mainType = resolution.model().types().findFirst().orElse( null );
+            type = Classes.resolveTypeVariable( (TypeVariable) type, ( (Member) accessor ).getDeclaringClass(), mainType );
+        }
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <ThrowableType extends Throwable> boolean accept( Visitor<? super AT, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        return visitor.visit( (AT) this );
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+        AbstractAssociationModel that = (AbstractAssociationModel) o;
+        return accessor.equals( that.accessor );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return accessor.hashCode();
+    }
+
+    @Override
+    public String toString()
+    {
+        if( accessor instanceof Field )
+        {
+            return ( (Field) accessor ).toGenericString();
+        }
+        else
+        {
+            return ( (Method) accessor ).toGenericString();
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationInfo.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationInfo.java
new file mode 100644
index 0000000..e5f7ac0
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationInfo.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.runtime.association;
+
+import java.lang.reflect.Type;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.runtime.composite.ConstraintsCheck;
+
+/**
+ * TODO
+ */
+public interface AssociationInfo
+    extends ConstraintsCheck
+{
+    boolean isImmutable();
+
+    QualifiedName qualifiedName();
+
+    Type type();
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationInstance.java
new file mode 100644
index 0000000..6d5f6fe
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationInstance.java
@@ -0,0 +1,138 @@
+/*
+ *  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.polygene.runtime.association;
+
+import java.lang.reflect.Type;
+import java.util.function.BiFunction;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.AssociationWrapper;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Implementation of Association to a single Entity.
+ */
+public final class AssociationInstance<T>
+    extends AbstractAssociationInstance<T>
+    implements Association<T>
+{
+    private Property<EntityReference> associationState;
+
+    public AssociationInstance( AssociationInfo associationInfo,
+                                BiFunction<EntityReference, Type, Object> entityFunction,
+                                Property<EntityReference> associationState
+    )
+    {
+        super( associationInfo, entityFunction );
+        this.associationState = associationState;
+    }
+
+    // Association implementation
+    @Override
+    public T get()
+    {
+        return getEntity( associationState.get() );
+    }
+
+    @Override
+    public void set( T newValue )
+        throws IllegalArgumentException
+    {
+        checkImmutable();
+        checkType( newValue );
+
+        associationInfo.checkConstraints( newValue );
+
+        // Change association
+        associationState.set( EntityReference.create( ((HasIdentity) newValue ).identity().get()));
+    }
+
+    @Override
+    public EntityReference reference()
+    {
+        return associationState.get();
+    }
+
+    public Property<EntityReference> getAssociationState()
+    {
+        return associationState;
+    }
+
+    @Override
+    public String toString()
+    {
+        if( associationState.get() == null )
+        {
+            return "";
+        }
+        else
+        {
+            return associationState.get().toString();
+        }
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int hash = associationInfo.hashCode() * 39; // Descriptor
+        if( associationState.get() != null )
+        {
+            hash = hash * 997 + associationState.get().hashCode(); // State
+        }
+        return hash;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+        Association<?> that = (Association) o;
+        // Unwrap if needed
+        while( that instanceof AssociationWrapper )
+        {
+            that = ( (AssociationWrapper) that ).next();
+        }
+        // Descriptor equality
+        AssociationInstance<?> thatInstance = (AssociationInstance) that;
+        AssociationDescriptor thatDescriptor = (AssociationDescriptor) thatInstance.associationInfo();
+        if( !associationInfo.equals( thatDescriptor ) )
+        {
+            return false;
+        }
+        // State equality
+        if( associationState.get() != null
+            ? !associationState.get().equals( thatInstance.associationState.get() )
+            : thatInstance.associationState.get() != null )
+        {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationModel.java
new file mode 100644
index 0000000..33c2193
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationModel.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.runtime.association;
+
+import java.lang.reflect.AccessibleObject;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.runtime.composite.ValueConstraintsInstance;
+
+/**
+ * Model for an Association.
+ *
+ * <p>Equality is based on the Association accessor object (associated type and name), not on the QualifiedName.</p>
+ */
+public final class AssociationModel extends AbstractAssociationModel<AssociationModel>
+    implements AssociationDescriptor, AssociationInfo
+{
+
+    public AssociationModel( AccessibleObject accessor,
+                             ValueConstraintsInstance valueConstraintsInstance,
+                             ValueConstraintsInstance associationConstraintsInstance,
+                             MetaInfo metaInfo
+    )
+    {
+        super( accessor, valueConstraintsInstance, associationConstraintsInstance, metaInfo );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationsModel.java
new file mode 100644
index 0000000..a9a53a0
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationsModel.java
@@ -0,0 +1,120 @@
+/*
+ *  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.polygene.runtime.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * Model for Associations.
+ */
+public final class AssociationsModel
+    implements VisitableHierarchy<AssociationsModel, AssociationModel>
+{
+    private final Map<AccessibleObject, AssociationModel> mapAccessorAssociationModel = new LinkedHashMap<>();
+
+    public AssociationsModel()
+    {
+    }
+
+    public Stream<AssociationModel> associations()
+    {
+        return mapAccessorAssociationModel.values().stream();
+    }
+
+    public void addAssociation( AssociationModel associationModel )
+    {
+        mapAccessorAssociationModel.put( associationModel.accessor(), associationModel );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super AssociationsModel, ? super AssociationModel, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( AssociationModel associationModel : mapAccessorAssociationModel.values() )
+            {
+                if( !associationModel.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public AssociationModel getAssociation( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        AssociationModel associationModel = mapAccessorAssociationModel.get( accessor );
+        if( associationModel == null )
+        {
+            throw new IllegalArgumentException( "No association found with name:" + ( (Member) accessor ).getName() );
+        }
+        return associationModel;
+    }
+
+    public AssociationDescriptor getAssociationByName( String name )
+        throws IllegalArgumentException
+    {
+        for( AssociationModel associationModel : mapAccessorAssociationModel.values() )
+        {
+            if( associationModel.qualifiedName().name().equals( name ) )
+            {
+                return associationModel;
+            }
+        }
+        throw new IllegalArgumentException( "No association found with name:" + name );
+    }
+
+    public AssociationDescriptor getAssociationByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException
+    {
+        for( AssociationModel associationModel : mapAccessorAssociationModel.values() )
+        {
+            if( associationModel.qualifiedName().equals( name ) )
+            {
+                return associationModel;
+            }
+        }
+        throw new IllegalArgumentException( "No association found with qualified name:" + name );
+    }
+
+    public void checkConstraints( AssociationStateHolder state )
+    {
+        for( AssociationModel associationModel : mapAccessorAssociationModel.values() )
+        {
+            Association<Object> association = state.associationFor( associationModel.accessor() );
+            associationModel.checkAssociationConstraints( association );
+            associationModel.checkConstraints( association.get() );
+        }
+    }
+
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationInstance.java
new file mode 100644
index 0000000..489a3e0
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationInstance.java
@@ -0,0 +1,232 @@
+/*
+ *  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.polygene.runtime.association;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.BiFunction;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.ManyAssociationWrapper;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.spi.entity.ManyAssociationState;
+
+/**
+ * JAVADOC
+ */
+public class ManyAssociationInstance<T> extends AbstractAssociationInstance<T>
+    implements ManyAssociation<T>
+{
+    private ManyAssociationState manyAssociationState;
+
+    public ManyAssociationInstance( AssociationInfo associationInfo,
+                                    BiFunction<EntityReference, Type, Object> associationFunction,
+                                    ManyAssociationState manyAssociationState
+    )
+    {
+        super( associationInfo, associationFunction );
+        this.manyAssociationState = manyAssociationState;
+    }
+
+    @Override
+    public int count()
+    {
+        return manyAssociationState.count();
+    }
+
+    @Override
+    public boolean contains( T entity )
+    {
+        return manyAssociationState.contains( getEntityReference( entity ) );
+    }
+
+    @Override
+    public boolean add( int i, T entity )
+    {
+        Objects.requireNonNull( entity, "entity" );
+        checkImmutable();
+        checkType( entity );
+        associationInfo.checkConstraints( entity );
+        return manyAssociationState.add( i, EntityReference.create( ((HasIdentity) entity ).identity().get()) );
+    }
+
+    @Override
+    public boolean add( T entity )
+    {
+        return add( manyAssociationState.count(), entity );
+    }
+
+    @Override
+    public boolean remove( T entity )
+    {
+        Objects.requireNonNull( entity, "entity" );
+        checkImmutable();
+        checkType( entity );
+
+        return manyAssociationState.remove( EntityReference.create( ((HasIdentity) entity).identity().get() ) );
+    }
+
+    @Override
+    public boolean clear()
+    {
+        checkImmutable();
+        return manyAssociationState.clear();
+    }
+
+    @Override
+    public T get( int i )
+    {
+        return getEntity( manyAssociationState.get( i ) );
+    }
+
+    @Override
+    public List<T> toList()
+    {
+        ArrayList<T> list = new ArrayList<>();
+        for( EntityReference entityReference : manyAssociationState )
+        {
+            list.add( getEntity( entityReference ) );
+        }
+
+        return list;
+    }
+
+    @Override
+    public Set<T> toSet()
+    {
+        Set<T> set = new HashSet<>();
+        for( EntityReference entityReference : manyAssociationState )
+        {
+            set.add( getEntity( entityReference ) );
+        }
+
+        return set;
+    }
+
+    @Override
+    public Stream<EntityReference> references()
+    {
+        return manyAssociationState.stream();
+    }
+
+    @Override
+    public String toString()
+    {
+        return manyAssociationState.toString();
+    }
+
+    @Override
+    public Iterator<T> iterator()
+    {
+        return new ManyAssociationIterator( manyAssociationState.iterator() );
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+        ManyAssociation<?> that = (ManyAssociation) o;
+        // Unwrap if needed
+        while( that instanceof ManyAssociationWrapper )
+        {
+            that = ( (ManyAssociationWrapper) that ).next();
+        }
+        // Descriptor equality
+        ManyAssociationInstance<?> thatInstance = (ManyAssociationInstance) that;
+        AssociationDescriptor thatDescriptor = (AssociationDescriptor) thatInstance.associationInfo();
+        if( !associationInfo.equals( thatDescriptor ) )
+        {
+            return false;
+        }
+        // State equality
+        if( manyAssociationState.count() != thatInstance.manyAssociationState.count() )
+        {
+            return false;
+        }
+        for( EntityReference ref : manyAssociationState )
+        {
+            if( !thatInstance.manyAssociationState.contains( ref ) )
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int hash = associationInfo.hashCode() * 31; // Descriptor
+        for( EntityReference ref : manyAssociationState )
+        {
+            hash += ref.hashCode() * 7; // State
+        }
+        return hash;
+    }
+
+    public ManyAssociationState getManyAssociationState()
+    {
+        return manyAssociationState;
+    }
+
+    protected class ManyAssociationIterator
+        implements Iterator<T>
+    {
+        private final Iterator<EntityReference> idIterator;
+
+        ManyAssociationIterator( Iterator<EntityReference> idIterator )
+        {
+            this.idIterator = idIterator;
+        }
+
+        @Override
+        public boolean hasNext()
+        {
+            return idIterator.hasNext();
+        }
+
+        @Override
+        public T next()
+        {
+            return getEntity( idIterator.next() );
+        }
+
+        @Override
+        public void remove()
+        {
+            checkImmutable();
+            idIterator.remove();
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationModel.java
new file mode 100644
index 0000000..98e2e2b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationModel.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.runtime.association;
+
+import java.lang.reflect.AccessibleObject;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.runtime.composite.ValueConstraintsInstance;
+import org.apache.polygene.runtime.unitofwork.BuilderEntityState;
+import org.apache.polygene.runtime.unitofwork.ModuleUnitOfWork;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * Model for a ManyAssociation.
+ *
+ * <p>Equality is based on the ManyAssociation accessor object (associated type and name), not on the QualifiedName.</p>
+ */
+public final class ManyAssociationModel extends AbstractAssociationModel<ManyAssociationModel>
+{
+    public ManyAssociationModel( AccessibleObject accessor,
+                                 ValueConstraintsInstance valueConstraintsInstance,
+                                 ValueConstraintsInstance associationConstraintsInstance,
+                                 MetaInfo metaInfo
+    )
+    {
+        super( accessor, valueConstraintsInstance, associationConstraintsInstance, metaInfo );
+    }
+
+    public <T> ManyAssociation<T> newInstance( final ModuleUnitOfWork uow, EntityState state )
+    {
+        return new ManyAssociationInstance<>(
+            state instanceof BuilderEntityState ? builderInfo() : this,
+            ( entityReference, type ) -> uow.get( Classes.RAW_CLASS.apply( type ), entityReference.identity() ),
+            state.manyAssociationValueOf( qualifiedName() )
+        );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationsModel.java
new file mode 100644
index 0000000..8765f42
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationsModel.java
@@ -0,0 +1,128 @@
+/*
+ *  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.polygene.runtime.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.unitofwork.ModuleUnitOfWork;
+import org.apache.polygene.runtime.value.ValueStateInstance;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * Model for ManyAssociations.
+ */
+public final class ManyAssociationsModel
+    implements VisitableHierarchy<ManyAssociationsModel, ManyAssociationModel>
+{
+    private final Map<AccessibleObject, ManyAssociationModel> mapAccessorAssociationModel = new LinkedHashMap<>();
+
+    public ManyAssociationsModel()
+    {
+    }
+
+    public Stream<ManyAssociationModel> manyAssociations()
+    {
+        return mapAccessorAssociationModel.values().stream();
+    }
+
+    public void addManyAssociation( ManyAssociationModel model )
+    {
+        mapAccessorAssociationModel.put( model.accessor(), model );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super ManyAssociationsModel, ? super ManyAssociationModel, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( ManyAssociationModel associationModel : mapAccessorAssociationModel.values() )
+            {
+                if( !associationModel.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public <T> ManyAssociation<T> newInstance( AccessibleObject accessor,
+                                               EntityState entityState,
+                                               ModuleUnitOfWork uow )
+    {
+        return mapAccessorAssociationModel.get( accessor ).newInstance( uow, entityState );
+    }
+
+    public ManyAssociationModel getManyAssociation( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        ManyAssociationModel manyAssociationModel = mapAccessorAssociationModel.get( accessor );
+        if( manyAssociationModel == null )
+        {
+            throw new IllegalArgumentException( "No many-association found with name:" + ( (Member) accessor ).getName() );
+        }
+        return manyAssociationModel;
+    }
+
+    public AssociationDescriptor getManyAssociationByName( String name )
+        throws IllegalArgumentException
+    {
+        for( ManyAssociationModel associationModel : mapAccessorAssociationModel.values() )
+        {
+            if( associationModel.qualifiedName().name().equals( name ) )
+            {
+                return associationModel;
+            }
+        }
+        throw new IllegalArgumentException( "No many-association found with name:" + name );
+    }
+
+    public AssociationDescriptor getManyAssociationByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException
+    {
+        for( ManyAssociationModel associationModel : mapAccessorAssociationModel.values() )
+        {
+            if( associationModel.qualifiedName().equals( name ) )
+            {
+                return associationModel;
+            }
+        }
+        throw new IllegalArgumentException( "No many-association found with qualified name:" + name );
+    }
+
+    public void checkConstraints( ValueStateInstance state )
+    {
+        for( ManyAssociationModel manyAssociationModel : mapAccessorAssociationModel.values() )
+        {
+            AccessibleObject accessor = manyAssociationModel.accessor();
+            ManyAssociationInstance<?> instance = state.manyAssociationFor( accessor );
+            manyAssociationModel.checkAssociationConstraints( instance );
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationInstance.java
new file mode 100644
index 0000000..e855c57
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationInstance.java
@@ -0,0 +1,195 @@
+/*
+ *  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.polygene.runtime.association;
+
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.association.NamedAssociationWrapper;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.spi.entity.NamedAssociationState;
+
+public class NamedAssociationInstance<T> extends AbstractAssociationInstance<T>
+    implements NamedAssociation<T>
+{
+    private final NamedAssociationState namedAssociationState;
+
+    public NamedAssociationInstance( AssociationInfo associationInfo,
+                                     BiFunction<EntityReference, Type, Object> associationFunction,
+                                     NamedAssociationState namedAssociationState
+                                   )
+    {
+        super( associationInfo, associationFunction );
+        this.namedAssociationState = namedAssociationState;
+    }
+
+    @Override
+    public Iterator<String> iterator()
+    {
+        return namedAssociationState.iterator();
+    }
+
+    @Override
+    public int count()
+    {
+        return namedAssociationState.count();
+    }
+
+    @Override
+    public boolean containsName( String name )
+    {
+        return namedAssociationState.containsName( name );
+    }
+
+    @Override
+    public boolean put( String name, T entity )
+    {
+        Objects.requireNonNull( entity, "entity" );
+        checkImmutable();
+        checkType( entity );
+        associationInfo.checkConstraints( entity );
+        return namedAssociationState.put( name, EntityReference.create( ( (HasIdentity) entity ).identity().get() ) );
+    }
+
+    @Override
+    public boolean remove( String name )
+    {
+        checkImmutable();
+        return namedAssociationState.remove( name );
+    }
+
+    @Override
+    public boolean clear()
+    {
+        checkImmutable();
+        return namedAssociationState.clear();
+    }
+
+    @Override
+    public T get( String name )
+    {
+        return getEntity( namedAssociationState.get( name ) );
+    }
+
+    @Override
+    public String nameOf( T entity )
+    {
+        return namedAssociationState.nameOf( getEntityReference( entity ) );
+    }
+
+    @Override
+    public Map<String, T> toMap()
+    {
+        Map<String, T> map = new HashMap<>();
+        for( String name : namedAssociationState )
+        {
+            map.put( name, getEntity( namedAssociationState.get( name ) ) );
+        }
+        return map;
+    }
+
+    @Override
+    public Stream<Map.Entry<String, EntityReference>> references()
+    {
+        return namedAssociationState.stream();
+    }
+
+    @Override
+    public EntityReference referenceOf( String name )
+    {
+        return namedAssociationState.get( name );
+    }
+
+    public Iterable<Map.Entry<String, EntityReference>> getEntityReferences()
+    {
+        return Collections.unmodifiableMap(
+            StreamSupport.stream( namedAssociationState.spliterator(), false )
+                         .collect( Collectors.toMap( Function.identity(), namedAssociationState::get ) )
+                                          ).entrySet();
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+        NamedAssociation<?> that = (NamedAssociation) o;
+        // Unwrap if needed
+        while( that instanceof NamedAssociationWrapper )
+        {
+            that = ( (NamedAssociationWrapper) that ).next();
+        }
+        // Descriptor equality
+        NamedAssociationInstance<?> thatInstance = (NamedAssociationInstance) that;
+        AssociationDescriptor thatDescriptor = (AssociationDescriptor) thatInstance.associationInfo();
+        if( !associationInfo.equals( thatDescriptor ) )
+        {
+            return false;
+        }
+        // State equality
+        if( namedAssociationState.count() != thatInstance.namedAssociationState.count() )
+        {
+            return false;
+        }
+        for( String name : namedAssociationState )
+        {
+            if( !thatInstance.namedAssociationState.containsName( name ) )
+            {
+                return false;
+            }
+            EntityReference thisReference = namedAssociationState.get( name );
+            EntityReference thatReference = thatInstance.namedAssociationState.get( name );
+            if( !thisReference.equals( thatReference ) )
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int hash = associationInfo.hashCode() * 31; // Descriptor
+        for( String name : namedAssociationState )
+        {
+            hash += name.hashCode();
+            hash += namedAssociationState.get( name ).hashCode() * 7; // State
+        }
+        return hash;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationModel.java
new file mode 100644
index 0000000..7c9b053
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationModel.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.runtime.association;
+
+import java.lang.reflect.AccessibleObject;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.runtime.composite.ValueConstraintsInstance;
+import org.apache.polygene.runtime.unitofwork.BuilderEntityState;
+import org.apache.polygene.runtime.unitofwork.ModuleUnitOfWork;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * Model for a NamedAssociation.
+ * <p>
+ * <p>Equality is based on the NamedAssociation accessor object (associated type and name), not on the QualifiedName.</p>
+ */
+public final class NamedAssociationModel extends AbstractAssociationModel<NamedAssociationModel>
+{
+    public NamedAssociationModel( AccessibleObject accessor,
+                                  ValueConstraintsInstance valueConstraintsInstance,
+                                  ValueConstraintsInstance associationConstraintsInstance,
+                                  MetaInfo metaInfo
+                                )
+    {
+        super( accessor, valueConstraintsInstance, associationConstraintsInstance, metaInfo );
+    }
+
+    public <T> NamedAssociation<T> newInstance( final ModuleUnitOfWork uow, EntityState state )
+    {
+        return new NamedAssociationInstance<>(
+            state instanceof BuilderEntityState ? builderInfo() : this,
+            ( entityReference, type ) -> uow.get( Classes.RAW_CLASS.apply( type ), entityReference.identity() ),
+            state.namedAssociationValueOf( qualifiedName() ) );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationsModel.java
new file mode 100644
index 0000000..9007abf
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationsModel.java
@@ -0,0 +1,126 @@
+/*
+ *  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.polygene.runtime.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.unitofwork.ModuleUnitOfWork;
+import org.apache.polygene.runtime.value.ValueStateInstance;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * Model for NamedAssociations.
+ */
+public final class NamedAssociationsModel
+    implements VisitableHierarchy<NamedAssociationsModel, NamedAssociationModel>
+{
+    private final Map<AccessibleObject, NamedAssociationModel> mapAccessorAssociationModel = new LinkedHashMap<>();
+
+    public NamedAssociationsModel()
+    {
+    }
+
+    public Stream<NamedAssociationModel> namedAssociations()
+    {
+        return mapAccessorAssociationModel.values().stream();
+    }
+
+    public void addNamedAssociation( NamedAssociationModel model )
+    {
+        mapAccessorAssociationModel.put( model.accessor(), model );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super NamedAssociationsModel, ? super NamedAssociationModel, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( NamedAssociationModel associationModel : mapAccessorAssociationModel.values() )
+            {
+                if( !associationModel.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public <T> NamedAssociation<T> newInstance( AccessibleObject accessor,
+                                                EntityState entityState,
+                                                ModuleUnitOfWork uow )
+    {
+        return mapAccessorAssociationModel.get( accessor ).newInstance( uow, entityState );
+    }
+
+    public NamedAssociationModel getNamedAssociation( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        NamedAssociationModel namedAssociationModel = mapAccessorAssociationModel.get( accessor );
+        if( namedAssociationModel == null )
+        {
+            throw new IllegalArgumentException( "No named-association found with name:" + ( (Member) accessor ).getName() );
+        }
+        return namedAssociationModel;
+    }
+
+    public AssociationDescriptor getNamedAssociationByName( String name )
+        throws IllegalArgumentException
+    {
+        for( NamedAssociationModel associationModel : mapAccessorAssociationModel.values() )
+        {
+            if( associationModel.qualifiedName().name().equals( name ) )
+            {
+                return associationModel;
+            }
+        }
+        throw new IllegalArgumentException( "No named-association found with name:" + name );
+    }
+
+    public AssociationDescriptor getNamedAssociationByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException
+    {
+        for( NamedAssociationModel associationModel : mapAccessorAssociationModel.values() )
+        {
+            if( associationModel.qualifiedName().equals( name ) )
+            {
+                return associationModel;
+            }
+        }
+        throw new IllegalArgumentException( "No named-association found with qualified name:" + name );
+    }
+
+    public void checkConstraints( ValueStateInstance state )
+    {
+        for( NamedAssociationModel associationModel : mapAccessorAssociationModel.values() )
+        {
+            associationModel.checkAssociationConstraints( state.namedAssociationFor( associationModel.accessor() ) );
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AndAppliesToFilter.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AndAppliesToFilter.java
new file mode 100644
index 0000000..51e5695
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AndAppliesToFilter.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesToFilter;
+
+/**
+ * JAVADOC
+ */
+final class AndAppliesToFilter
+    implements AppliesToFilter
+{
+    private final AppliesToFilter left;
+    private final AppliesToFilter right;
+
+    AndAppliesToFilter( AppliesToFilter left, AppliesToFilter right )
+    {
+        this.left = left;
+        this.right = right;
+    }
+
+    @Override
+    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
+    {
+        return left.appliesTo( method, mixin, compositeType, fragmentClass ) &&
+               right.appliesTo( method, mixin, compositeType, fragmentClass );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AnnotationAppliesToFilter.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AnnotationAppliesToFilter.java
new file mode 100644
index 0000000..006f24b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AnnotationAppliesToFilter.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesToFilter;
+
+/**
+ * JAVADOC
+ */
+final class AnnotationAppliesToFilter
+    implements AppliesToFilter
+{
+    @SuppressWarnings( "raw" )
+    private final Class annotationType;
+
+    @SuppressWarnings( "raw" )
+    AnnotationAppliesToFilter( Class type )
+    {
+        this.annotationType = type;
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
+    {
+        return method.getAnnotation( annotationType ) != null;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationAssemblyFactoryImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationAssemblyFactoryImpl.java
new file mode 100644
index 0000000..46c8cee
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationAssemblyFactoryImpl.java
@@ -0,0 +1,79 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+/**
+ * Factory for ApplicationAssembly.
+ */
+public final class ApplicationAssemblyFactoryImpl
+    implements ApplicationAssemblyFactory
+{
+    @Override
+    public ApplicationAssembly newApplicationAssembly( Assembler assembler )
+        throws AssemblyException
+    {
+        return newApplicationAssembly( new Assembler[][][]{ { { assembler } } } );
+    }
+
+    @Override
+    public ApplicationAssembly newApplicationAssembly( Assembler[][][] assemblers )
+        throws AssemblyException
+    {
+        ApplicationAssembly applicationAssembly = newApplicationAssembly();
+
+        // Build all layers bottom-up
+        LayerAssembly below = null;
+        for( int layer = assemblers.length - 1; layer >= 0; layer-- )
+        {
+            // Create Layer
+            LayerAssembly layerAssembly = applicationAssembly.layer( "Layer " + ( layer + 1 ) );
+            for( int module = 0; module < assemblers[ layer ].length; module++ )
+            {
+                // Create Module
+                ModuleAssembly moduleAssembly = layerAssembly.module( "Module " + ( module + 1 ) );
+                for( Assembler assembler : assemblers[ layer ][ module ] )
+                {
+                    // Register Assembler
+                    assembler.assemble( moduleAssembly );
+                }
+            }
+            if( below != null )
+            {
+                layerAssembly.uses( below ); // Link layers
+            }
+            below = layerAssembly;
+        }
+        return applicationAssembly;
+    }
+
+    @Override
+    public ApplicationAssembly newApplicationAssembly()
+    {
+        return new ApplicationAssemblyImpl();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationAssemblyImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationAssemblyImpl.java
new file mode 100644
index 0000000..db1e9b2
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationAssemblyImpl.java
@@ -0,0 +1,158 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.AssemblyVisitor;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+/**
+ * The representation of an entire application. From
+ * this you can set information about the application
+ * and create LayerAssemblies.
+ */
+public final class ApplicationAssemblyImpl
+    implements ApplicationAssembly
+{
+    private final Map<String, LayerAssemblyImpl> layerAssemblies = new LinkedHashMap<>();
+    private String name = "Application";
+    private String version = "1.0"; // Default version
+    private Application.Mode mode;
+    private final MetaInfo metaInfo = new MetaInfo();
+    private final List<Class<? extends Activator<Application>>> activators = new ArrayList<>();
+
+    public ApplicationAssemblyImpl()
+    {
+        mode = Application.Mode.valueOf( System.getProperty( "mode", "production" ) );
+    }
+
+    @Override
+    public LayerAssembly layer( String name )
+    {
+        if( name != null )
+        {
+            LayerAssemblyImpl existing = layerAssemblies.get( name );
+            if( existing != null )
+            {
+                return existing;
+            }
+        }
+        LayerAssemblyImpl layerAssembly = new LayerAssemblyImpl( this, name );
+        layerAssemblies.put( name, layerAssembly );
+        return layerAssembly;
+    }
+
+    @Override
+    public ModuleAssembly module( String layerName, String moduleName )
+    {
+        return layer( layerName ).module( moduleName );
+    }
+
+    @Override
+    public ApplicationAssembly setName( String name )
+    {
+        this.name = name;
+        return this;
+    }
+
+    @Override
+    public ApplicationAssembly setVersion( String version )
+    {
+        this.version = version;
+        return this;
+    }
+
+    @Override
+    public ApplicationAssembly setMode( Application.Mode mode )
+    {
+        this.mode = mode;
+        return this;
+    }
+
+    @Override
+    public ApplicationAssembly setMetaInfo( Object info )
+    {
+        metaInfo.set( info );
+        return this;
+    }
+
+    @Override
+    @SafeVarargs
+    public final ApplicationAssembly withActivators( Class<? extends Activator<Application>>... activators )
+    {
+        this.activators.addAll( Arrays.asList( activators ) );
+        return this;
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> void visit( AssemblyVisitor<ThrowableType> visitor )
+        throws ThrowableType
+    {
+        visitor.visitApplication( this );
+        for( LayerAssemblyImpl layerAssembly : layerAssemblies.values() )
+        {
+            layerAssembly.visit( visitor );
+        }
+    }
+
+    public Collection<LayerAssemblyImpl> layerAssemblies()
+    {
+        return layerAssemblies.values();
+    }
+
+    public List<Class<? extends Activator<Application>>> activators()
+    {
+        return activators;
+    }
+
+    public MetaInfo metaInfo()
+    {
+        return metaInfo;
+    }
+
+    @Override
+    public String name()
+    {
+        return name;
+    }
+
+    @Override
+    public String version()
+    {
+        return version;
+    }
+
+    @Override
+    public Application.Mode mode()
+    {
+        return mode;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationModelFactoryImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationModelFactoryImpl.java
new file mode 100644
index 0000000..5d3b000
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationModelFactoryImpl.java
@@ -0,0 +1,210 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationModelFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.runtime.activation.ActivatorsModel;
+import org.apache.polygene.runtime.composite.CompositeMethodModel;
+import org.apache.polygene.runtime.injection.InjectedFieldModel;
+import org.apache.polygene.runtime.model.Binder;
+import org.apache.polygene.runtime.model.Resolution;
+import org.apache.polygene.runtime.structure.ApplicationModel;
+import org.apache.polygene.runtime.structure.LayerModel;
+import org.apache.polygene.runtime.structure.ModuleModel;
+import org.apache.polygene.runtime.structure.UsedLayersModel;
+
+/**
+ * Factory for Applications.
+ */
+public final class ApplicationModelFactoryImpl
+    implements ApplicationModelFactory
+{
+    @Override
+    public ApplicationDescriptor newApplicationModel( ApplicationAssembly assembly )
+        throws AssemblyException
+    {
+        AssemblyHelper helper = createAssemblyHelper( assembly );
+
+        ApplicationAssemblyImpl applicationAssembly = (ApplicationAssemblyImpl) assembly;
+        ActivatorsModel<Application> applicationActivators = new ActivatorsModel<>( applicationAssembly.activators() );
+        List<LayerModel> layerModels = new ArrayList<>();
+        final ApplicationModel applicationModel = new ApplicationModel( applicationAssembly.name(),
+                                                                        applicationAssembly.version(),
+                                                                        applicationAssembly.mode(),
+                                                                        applicationAssembly.metaInfo(),
+                                                                        applicationActivators,
+                                                                        layerModels );
+        Map<LayerAssembly, LayerModel> mapAssemblyModel = new HashMap<>();
+        Map<LayerAssembly, List<LayerModel>> mapUsedLayers = new HashMap<>();
+
+        // Build all layers
+        List<LayerAssemblyImpl> layerAssemblies = new ArrayList<>( applicationAssembly.layerAssemblies() );
+        for( LayerAssemblyImpl layerAssembly : layerAssemblies )
+        {
+            List<LayerModel> usedLayers = new ArrayList<>();
+            mapUsedLayers.put( layerAssembly, usedLayers );
+
+            UsedLayersModel usedLayersModel = new UsedLayersModel( usedLayers );
+            List<ModuleModel> moduleModels = new ArrayList<>();
+            String name = layerAssembly.name();
+            if( name == null )
+            {
+                throw new AssemblyException( "Layer must have name set" );
+            }
+            ActivatorsModel<Layer> layerActivators = new ActivatorsModel<>( layerAssembly.activators() );
+            LayerModel layerModel = new LayerModel( name, layerAssembly.metaInfo(), usedLayersModel, layerActivators, moduleModels );
+
+            for( ModuleAssemblyImpl moduleAssembly : layerAssembly.moduleAssemblies() )
+            {
+                moduleModels.add( moduleAssembly.assembleModule( layerModel, helper ) );
+            }
+            mapAssemblyModel.put( layerAssembly, layerModel );
+            layerModels.add( layerModel );
+        }
+
+        // Populate used layer lists
+        for( LayerAssemblyImpl layerAssembly : layerAssemblies )
+        {
+            Set<LayerAssembly> usesLayers = layerAssembly.uses();
+            List<LayerModel> usedLayers = mapUsedLayers.get( layerAssembly );
+            for( LayerAssembly usesLayer : usesLayers )
+            {
+                LayerModel layerModel = mapAssemblyModel.get( usesLayer );
+                usedLayers.add( layerModel );
+            }
+        }
+
+        // Bind model
+        // This will resolve all dependencies
+        try
+        {
+//            applicationModel.bind();
+            applicationModel.accept( new BindingVisitor( applicationModel ) );
+        }
+        catch( BindingException e )
+        {
+            throw new AssemblyException( "Unable to bind: " + applicationModel, e );
+        }
+
+        return applicationModel;
+    }
+
+    private AssemblyHelper createAssemblyHelper( ApplicationAssembly assembly )
+    {
+        if( assembly instanceof ApplicationAssemblyImpl )
+        {
+            ApplicationAssemblyImpl impl = (ApplicationAssemblyImpl) assembly;
+            AssemblyHelper helper = impl.metaInfo().get( AssemblyHelper.class );
+            if( helper != null )
+            {
+                return helper;
+            }
+        }
+        return new AssemblyHelper();
+    }
+
+    private static class BindingVisitor
+        implements HierarchicalVisitor<Object, Object, BindingException>
+    {
+        private LayerModel layer;
+        private ModuleModel module;
+        private ModelDescriptor objectDescriptor;
+        private CompositeMethodModel compositeMethodModel;
+
+        private Resolution resolution;
+        private final ApplicationModel applicationModel;
+
+        private BindingVisitor( ApplicationModel applicationModel )
+        {
+            this.applicationModel = applicationModel;
+        }
+
+        @Override
+        public boolean visitEnter( Object visited )
+            throws BindingException
+        {
+            if( visited instanceof Binder )
+            {
+                Binder binder = (Binder) visited;
+                binder.bind( resolution );
+
+                return false;
+            }
+            else if( visited instanceof CompositeMethodModel )
+            {
+                compositeMethodModel = (CompositeMethodModel) visited;
+                resolution = new Resolution( applicationModel, layer, module, objectDescriptor, compositeMethodModel, null );
+            }
+            else if( visited instanceof ModelDescriptor )
+            {
+                objectDescriptor = (ModelDescriptor) visited;
+                resolution = new Resolution( applicationModel, layer, module, objectDescriptor, null, null );
+            }
+            else if( visited instanceof InjectedFieldModel )
+            {
+                InjectedFieldModel fieldModel = (InjectedFieldModel) visited;
+                fieldModel.bind( new Resolution( applicationModel, layer, module,
+                                                 objectDescriptor, compositeMethodModel, fieldModel.field() ) );
+            }
+            else if( visited instanceof ModuleModel )
+            {
+                module = (ModuleModel) visited;
+            }
+            else if( visited instanceof LayerModel )
+            {
+                layer = (LayerModel) visited;
+            }
+            return true;
+        }
+
+        @Override
+        public boolean visitLeave( Object visited )
+            throws BindingException
+        {
+            return true;
+        }
+
+        @Override
+        public boolean visit( Object visited )
+            throws BindingException
+        {
+            if( visited instanceof Binder )
+            {
+                ( (Binder) visited ).bind( resolution );
+            }
+            return true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AssemblyHelper.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AssemblyHelper.java
new file mode 100644
index 0000000..b456a1e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AssemblyHelper.java
@@ -0,0 +1,198 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.AppliesToFilter;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.runtime.composite.ConcernModel;
+import org.apache.polygene.runtime.composite.ConstraintDeclaration;
+import org.apache.polygene.runtime.composite.FragmentClassLoader;
+import org.apache.polygene.runtime.composite.MixinModel;
+import org.apache.polygene.runtime.composite.SideEffectModel;
+
+/**
+ * This helper is used when building the application model. It keeps track
+ * of already created classloaders and various models
+ */
+@SuppressWarnings("WeakerAccess")
+public class AssemblyHelper
+{
+    private Map<Class, Class> instantiationClasses = new HashMap<>();
+    private Map<Class, ConstraintDeclaration> constraintDeclarations = new HashMap<>();
+    private Map<ClassLoader, FragmentClassLoader> modifierClassLoaders = new HashMap<>();
+    private Map<Class<?>, AppliesToFilter> appliesToInstances = new HashMap<>();
+
+    protected MixinModel getMixinModel(Class mixinClass)
+    {
+        return new MixinModel( mixinClass, instantiationClass( mixinClass ) );
+    }
+
+    protected ConcernModel getConcernModel(Class concernClass)
+    {
+        return new ConcernModel( concernClass, instantiationClass( concernClass ) );
+    }
+
+    protected SideEffectModel getSideEffectModel(Class sideEffectClass)
+    {
+        return new SideEffectModel( sideEffectClass, instantiationClass( sideEffectClass ) );
+    }
+
+    protected Class instantiationClass(Class fragmentClass)
+    {
+        Class instantiationClass = fragmentClass;
+        if( !InvocationHandler.class.isAssignableFrom( fragmentClass ) )
+        {
+            instantiationClass = instantiationClasses.get( fragmentClass );
+
+            if( instantiationClass == null )
+            {
+                try
+                {
+                    FragmentClassLoader fragmentLoader = getModifierClassLoader( fragmentClass.getClassLoader() );
+                    instantiationClass = fragmentLoader.loadFragmentClass( fragmentClass );
+                    instantiationClasses.put( fragmentClass, instantiationClass );
+                }
+                catch( ClassNotFoundException | VerifyError e )
+                {
+                    throw new ConstructionException( "Could not generate mixin subclass " + fragmentClass.getName(), e );
+                }
+            }
+        }
+        return instantiationClass;
+    }
+
+    protected FragmentClassLoader getModifierClassLoader( ClassLoader classLoader )
+    {
+        return modifierClassLoaders.computeIfAbsent( classLoader, k -> instantiateFragmentClassLoader( classLoader ) );
+    }
+
+    protected FragmentClassLoader instantiateFragmentClassLoader( ClassLoader classLoader )
+    {
+        return new FragmentClassLoader( classLoader );
+    }
+
+    public boolean appliesTo( Class<?> fragmentClass, Method method, Iterable<Class<?>> types, Class<?> mixinClass )
+    {
+        AppliesToFilter appliesToFilter = appliesToInstances.computeIfAbsent( fragmentClass, k -> createAppliesToFilter( fragmentClass ) );
+        for( Class<?> compositeType : types )
+        {
+            if( appliesToFilter.appliesTo( method, mixinClass, compositeType, fragmentClass ) )
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    protected AppliesToFilter createAppliesToFilter( Class<?> fragmentClass )
+    {
+        AppliesToFilter result = null;
+        if( !InvocationHandler.class.isAssignableFrom( fragmentClass ) )
+        {
+            result = new TypedFragmentAppliesToFilter();
+            if( Modifier.isAbstract( fragmentClass.getModifiers() ) )
+            {
+                result = new AndAppliesToFilter( result, new ImplementsMethodAppliesToFilter() );
+            }
+        }
+        result = applyAppliesTo( result, fragmentClass );
+        if( result == null )
+        {
+            return AppliesToFilter.ALWAYS;
+        }
+        return result;
+    }
+
+    protected AppliesToFilter applyAppliesTo( AppliesToFilter existing, Class<?> modifierClass )
+    {
+        AppliesTo appliesTo = modifierClass.getAnnotation( AppliesTo.class );
+        if( appliesTo != null )
+        {
+            // Use "or" for all filters specified in the annotation
+            AppliesToFilter appliesToAnnotation = null;
+            for( Class<?> appliesToClass : appliesTo.value() )
+            {
+                AppliesToFilter filter;
+                if( AppliesToFilter.class.isAssignableFrom( appliesToClass ) )
+                {
+                    try
+                    {
+                        @SuppressWarnings("unchecked")
+                        Constructor<AppliesToFilter> cons = (Constructor<AppliesToFilter>) appliesToClass.getDeclaredConstructor();
+                        cons.setAccessible(true);
+                        filter = cons.newInstance();
+                    }
+                    catch( Exception e )
+                    {
+                        throw new ConstructionException( e );
+                    }
+                }
+                else if( Annotation.class.isAssignableFrom( appliesToClass ) )
+                {
+                    filter = new AnnotationAppliesToFilter( appliesToClass );
+                }
+                else // Type check
+                {
+                    filter = new TypeCheckAppliesToFilter( appliesToClass );
+                }
+
+                if( appliesToAnnotation == null )
+                {
+                    appliesToAnnotation = filter;
+                }
+                else
+                {
+                    appliesToAnnotation = new OrAppliesToFilter( appliesToAnnotation, filter );
+                }
+            }
+            // Add to the rest of the rules using "and"
+            if( existing == null )
+            {
+                return appliesToAnnotation;
+            }
+            else
+            {
+                return new AndAppliesToFilter( existing, appliesToAnnotation );
+            }
+        }
+        return existing;
+    }
+
+    public boolean appliesTo( Class<? extends Constraint<?, ?>> constraint,
+                              Class<? extends Annotation> annotationType,
+                              Type valueType
+    )
+    {
+        ConstraintDeclaration constraintDeclaration =
+            constraintDeclarations.computeIfAbsent( constraint, k -> new ConstraintDeclaration( constraint ) );
+        return constraintDeclaration.appliesTo( annotationType, valueType );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/CompositeAssemblyImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/CompositeAssemblyImpl.java
new file mode 100644
index 0000000..543e8cd
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/CompositeAssemblyImpl.java
@@ -0,0 +1,952 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.GenericAssociationInfo;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.api.constraint.Name;
+import org.apache.polygene.api.entity.Lifecycle;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.GenericPropertyInfo;
+import org.apache.polygene.api.property.Immutable;
+import org.apache.polygene.api.property.InitialValueProvider;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.sideeffect.SideEffects;
+import org.apache.polygene.api.type.HasTypes;
+import org.apache.polygene.api.util.Annotations;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.Fields;
+import org.apache.polygene.api.util.HierarchicalVisitorAdapter;
+import org.apache.polygene.bootstrap.AssemblyReportException;
+import org.apache.polygene.bootstrap.StateDeclarations;
+import org.apache.polygene.runtime.association.AssociationModel;
+import org.apache.polygene.runtime.association.AssociationsModel;
+import org.apache.polygene.runtime.association.ManyAssociationModel;
+import org.apache.polygene.runtime.association.ManyAssociationsModel;
+import org.apache.polygene.runtime.association.NamedAssociationModel;
+import org.apache.polygene.runtime.association.NamedAssociationsModel;
+import org.apache.polygene.runtime.composite.AbstractConstraintModel;
+import org.apache.polygene.runtime.composite.CompositeConstraintModel;
+import org.apache.polygene.runtime.composite.CompositeMethodModel;
+import org.apache.polygene.runtime.composite.CompositeMethodsModel;
+import org.apache.polygene.runtime.composite.ConcernModel;
+import org.apache.polygene.runtime.composite.ConcernsModel;
+import org.apache.polygene.runtime.composite.ConstraintModel;
+import org.apache.polygene.runtime.composite.ConstraintsModel;
+import org.apache.polygene.runtime.composite.GenericPredicate;
+import org.apache.polygene.runtime.composite.InterfaceDefaultMethodsMixin;
+import org.apache.polygene.runtime.composite.MixinModel;
+import org.apache.polygene.runtime.composite.MixinsModel;
+import org.apache.polygene.runtime.composite.SideEffectModel;
+import org.apache.polygene.runtime.composite.SideEffectsModel;
+import org.apache.polygene.runtime.composite.StateModel;
+import org.apache.polygene.runtime.composite.ValueConstraintsInstance;
+import org.apache.polygene.runtime.composite.ValueConstraintsModel;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.property.PropertiesModel;
+import org.apache.polygene.runtime.property.PropertyModel;
+
+import static java.util.stream.Stream.concat;
+import static java.util.stream.Stream.of;
+import static org.apache.polygene.api.composite.InvalidCompositeException.handleInvalidCompositeType;
+import static org.apache.polygene.api.util.Annotations.isType;
+import static org.apache.polygene.api.util.Annotations.typeHasAnnotation;
+import static org.apache.polygene.api.util.Classes.classHierarchy;
+import static org.apache.polygene.api.util.Classes.interfacesOf;
+import static org.apache.polygene.api.util.Classes.isAssignableFrom;
+import static org.apache.polygene.api.util.Classes.typeOf;
+import static org.apache.polygene.api.util.Classes.typesOf;
+import static org.apache.polygene.api.util.Classes.wrapperClass;
+
+/**
+ * Declaration of a Composite.
+ */
+public abstract class CompositeAssemblyImpl
+    implements HasTypes
+{
+    List<Class<?>> concerns = new ArrayList<>();
+    List<Class<?>> sideEffects = new ArrayList<>();
+    List<Class<?>> mixins = new ArrayList<>();
+    List<Class<?>> types = new ArrayList<>();
+    MetaInfo metaInfo = new MetaInfo();
+    Visibility visibility = Visibility.module;
+
+    private boolean immutable;
+    PropertiesModel propertiesModel;
+    StateModel stateModel;
+    MixinsModel mixinsModel;
+    CompositeMethodsModel compositeMethodsModel;
+    private AssemblyHelper helper;
+    private StateDeclarations stateDeclarations;
+
+    private Set<String> registeredStateNames = new HashSet<>();
+
+    CompositeAssemblyImpl( Class<?> mainType )
+    {
+        types.add( mainType );
+    }
+
+    @Override
+    public Stream<Class<?>> types()
+    {
+        return types.stream();
+    }
+
+    protected StateModel createStateModel()
+    {
+        return new StateModel( propertiesModel );
+    }
+
+    protected MixinsModel createMixinsModel()
+    {
+        return new MixinsModel();
+    }
+
+    void buildComposite( AssemblyHelper helper,
+                         StateDeclarations stateDeclarations
+                       )
+    {
+        this.stateDeclarations = stateDeclarations;
+        this.helper = helper;
+        for( Class<?> compositeType : types )
+        {
+            metaInfo = new MetaInfo( metaInfo ).withAnnotations( compositeType );
+            addAnnotationsMetaInfo( compositeType, metaInfo );
+        }
+
+        immutable = metaInfo.get( Immutable.class ) != null;
+        propertiesModel = new PropertiesModel();
+        stateModel = createStateModel();
+        mixinsModel = createMixinsModel();
+        compositeMethodsModel = new CompositeMethodsModel( mixinsModel );
+
+        // Implement composite methods
+        List<Class<?>> constraintClasses = toList( constraintDeclarations( getAllTypes() ) );
+        List<Class<?>> concernClasses = toList( concat( concerns.stream(), concernDeclarations( getAllTypes() ) ) );
+        List<Class<?>> sideEffectClasses = toList( concat( sideEffects.stream(), sideEffectDeclarations( getAllTypes() ) ) );
+        List<Class<?>> mixinClasses = toList( concat( mixins.stream(), mixinDeclarations( getAllTypes() ) ) );
+        //noinspection unchecked
+        implementMixinType( types,
+                            constraintClasses,
+                            concernClasses,
+                            sideEffectClasses,
+                            mixinClasses
+                          );
+
+        // Add state from methods and fields
+        //noinspection unchecked
+        addState( constraintClasses );
+    }
+
+    private List<Class<?>> toList( Stream<Class<?>> stream )
+    {
+        return stream.collect( Collectors.toList() );
+    }
+
+    private void addAnnotationsMetaInfo( Class<?> type, MetaInfo compositeMetaInfo )
+    {
+        Class[] declaredInterfaces = type.getInterfaces();
+        for( int i = declaredInterfaces.length - 1; i >= 0; i-- )
+        {
+            addAnnotationsMetaInfo( declaredInterfaces[ i ], compositeMetaInfo );
+        }
+        compositeMetaInfo.withAnnotations( type );
+    }
+
+    private void implementMixinType( List<? extends Class<?>> types,
+                                     List<Class<?>> constraintClasses,
+                                     List<Class<?>> concernClasses,
+                                     List<Class<?>> sideEffectClasses,
+                                     List<Class<?>> mixinClasses
+                                   )
+    {
+        List<Throwable> exceptions = new ArrayList<>();
+        Set<Class<?>> thisDependencies = new HashSet<>();
+        types.stream()
+             .peek( mixinType -> mixinsModel.addMixinType( mixinType ) )
+             .flatMap( mixinType -> Arrays.stream( mixinType.getMethods() ) )
+             .forEach( method -> implementMixinMethod( method, mixinClasses, constraintClasses,
+                                                       concernClasses,
+                                                       sideEffectClasses,
+                                                       exceptions,
+                                                       thisDependencies
+                                                     )
+                     );
+
+        // Implement all @This dependencies that were found
+        thisDependencies.forEach(
+            thisDependency ->
+            {
+                // Add additional declarations from the @This type
+                Stream<Class<?>> typeConstraintClasses = concat(
+                    constraintClasses.stream(),
+                    constraintDeclarations( thisDependency ) );
+                Stream<Class<?>> typeConcernClasses = concat(
+                    concernClasses.stream(),
+                    concernDeclarations( thisDependency ) );
+                Stream<Class<?>> typeSideEffectClasses = concat(
+                    sideEffectClasses.stream(),
+                    sideEffectDeclarations( thisDependency ) );
+                Stream<Class<?>> typeMixinClasses = concat(
+                    mixinClasses.stream(),
+                    mixinDeclarations( thisDependency ) );
+                List<? extends Class<?>> singleton = Collections.singletonList( thisDependency );
+                implementMixinType( singleton,
+                                    toList( typeConstraintClasses ),
+                                    toList( typeConcernClasses ),
+                                    toList( typeSideEffectClasses ),
+                                    toList( typeMixinClasses )
+                                  );
+            } );
+        if( exceptions.size() > 0 )
+        {
+            throw new AssemblyReportException( exceptions );
+        }
+    }
+
+    private void implementMixinMethod( Method method,
+                                       List<Class<?>> mixinClasses,
+                                       List<Class<?>> constraintClasses,
+                                       List<Class<?>> concernClasses,
+                                       List<Class<?>> sideEffectClasses,
+                                       List<Throwable> exceptions,
+                                       Set<Class<?>> thisDependencies )
+    {
+        try
+        {
+            if( !compositeMethodsModel.isImplemented( method )
+                && !Proxy.class.equals( method.getDeclaringClass().getSuperclass() )
+                && !Proxy.class.equals( method.getDeclaringClass() )
+                && !Modifier.isStatic( method.getModifiers() ) )
+            {
+                MixinModel mixinModel = implementMethod( method, mixinClasses );
+                if( mixinModel != null )
+                {
+                    ConcernsModel concernsModel = concernsFor(
+                        method,
+                        mixinModel.mixinClass(),
+                        concat( concernDeclarations( mixinModel.mixinClass() ),
+                                concernClasses.stream() )
+                                                             );
+                    SideEffectsModel sideEffectsModel = sideEffectsFor(
+                        method,
+                        mixinModel.mixinClass(),
+                        concat( sideEffectDeclarations( mixinModel.mixinClass() ),
+                                sideEffectClasses.stream() )
+                                                                      );
+                    Stream<Class<?>> concat = concat( constraintDeclarations( mixinModel.mixinClass() ),
+                                                      constraintClasses.stream() );
+                    ConstraintsModel constraints = constraintsFor( method, toList( concat ) );
+                    CompositeMethodModel methodComposite = new CompositeMethodModel(
+                        method,
+                        constraints,
+                        concernsModel,
+                        sideEffectsModel,
+                        mixinsModel
+                    );
+
+                    Stream<? extends Dependencies> source = of( methodComposite, mixinModel );
+                    source.flatMap( Dependencies::dependencies )
+                          .filter( new DependencyModel.ScopeSpecification( This.class ) )
+                          .map( DependencyModel::rawInjectionType )
+                          .forEach( thisDependencies::add );
+
+                    interfacesOf( mixinModel.mixinClass() )
+                        .map( Classes.RAW_CLASS )
+                        .filter( clazz -> of( Initializable.class, Lifecycle.class, InvocationHandler.class )
+                            .noneMatch( c -> c.equals( clazz ) ) )
+                        .forEach( thisDependencies::add );
+
+                    compositeMethodsModel.addMethod( methodComposite );
+                }
+            }
+        }
+        catch( Exception e )
+        {
+            exceptions.add( e );
+        }
+    }
+
+    @SuppressWarnings( "raw" )
+    private MixinModel implementMethod( Method method, List<Class<?>> mixinDeclarations )
+    {
+        MixinModel implementationModel = mixinsModel.mixinFor( method );
+        if( implementationModel != null )
+        {
+            return implementationModel;
+        }
+        Class mixinClass = findTypedImplementation( method, mixinDeclarations.stream() );
+        if( mixinClass != null )
+        {
+            return implementMethodWithClass( method, mixinClass );
+        }
+
+        // Check generic implementations
+        mixinClass = findGenericImplementation( method, concat( mixinDeclarations.stream(), of( InterfaceDefaultMethodsMixin.class ) ) );
+        if( mixinClass != null )
+        {
+            return implementMethodWithClass( method, mixinClass );
+        }
+        handleInvalidCompositeType( "No implementation found for method ", null, null, null, null, method, types );
+        return null;
+    }
+
+    private Class<?> findTypedImplementation( final Method method, Stream<Class<?>> mixins )
+    {
+        // Check if mixinClass implements the method. If so, check if the mixinClass is generic or if the filter passes.
+        // If a mixinClass is both generic AND non-generic at the same time, then the filter applies to the non-generic
+        // side only.
+        Predicate<Class<?>> appliesToSpec = item -> helper.appliesTo( item, method, types, item );
+        return mixins.filter( isAssignableFrom( method.getDeclaringClass() )
+                                  .and( GenericPredicate.INSTANCE.or( appliesToSpec ) ) )
+                     .findFirst().orElse( null );
+    }
+
+    private Class<?> findGenericImplementation( final Method method, Stream<Class<?>> mixins )
+    {
+        // Check if mixinClass is generic and the applies-to filter passes
+        Predicate<Class<?>> appliesToSpec = item -> helper.appliesTo( item, method, types, item );
+        return mixins.filter( GenericPredicate.INSTANCE.and( appliesToSpec ) ).findFirst().orElse( null );
+    }
+
+    private MixinModel implementMethodWithClass( Method method, Class mixinClass )
+    {
+        MixinModel mixinModel = mixinsModel.getMixinModel( mixinClass );
+        if( mixinModel == null )
+        {
+            mixinModel = helper.getMixinModel( mixinClass );
+            mixinsModel.addMixinModel( mixinModel );
+        }
+        mixinsModel.addMethodMixin( method, mixinModel );
+        return mixinModel;
+    }
+
+    private void addState( final List<Class<?>> constraintClasses )
+    {
+        // Add method state
+        compositeMethodsModel.accept( new HierarchicalVisitorAdapter<Object, Object, RuntimeException>()
+        {
+            @Override
+            public boolean visitEnter( Object visited )
+                throws RuntimeException
+            {
+                if( visited instanceof CompositeMethodModel )
+                {
+                    CompositeMethodModel methodModel = (CompositeMethodModel) visited;
+                    if( methodModel.method().getParameterTypes().length == 0 )
+                    {
+                        addStateFor( methodModel.method(), constraintClasses );
+                    }
+
+                    return false;
+                }
+
+                return super.visitEnter( visited );
+            }
+        } );
+
+        // Add field state
+        mixinsModel.accept( new HierarchicalVisitorAdapter<Object, Object, RuntimeException>()
+        {
+            @Override
+            public boolean visitEnter( Object visited )
+                throws RuntimeException
+            {
+                if( visited instanceof MixinModel )
+                {
+                    MixinModel model = (MixinModel) visited;
+                    Consumer<Field> addState = field -> addStateFor( field, constraintClasses );
+                    Fields.FIELDS_OF.apply( model.mixinClass() )
+                                    .filter( Annotations.hasAnnotation( State.class ) )
+                                    .forEach( addState );
+                    return false;
+                }
+                return super.visitEnter( visited );
+            }
+        } );
+    }
+
+    private void addStateFor( AccessibleObject accessor, List<Class<?>> constraintClasses )
+    {
+        String stateName = QualifiedName.fromAccessor( accessor ).name();
+
+        if( registeredStateNames.contains( stateName ) )
+        {
+            return; // Skip already registered names
+        }
+
+        Class<?> accessorType = Classes.RAW_CLASS.apply( typeOf( accessor ) );
+        if( Property.class.isAssignableFrom( accessorType ) )
+        {
+            propertiesModel.addProperty( newPropertyModel( accessor, constraintClasses ) );
+            registeredStateNames.add( stateName );
+        }
+        else if( Association.class.isAssignableFrom( accessorType ) )
+        {
+            associationsModel().addAssociation( newAssociationModel( accessor, constraintClasses ) );
+            registeredStateNames.add( stateName );
+        }
+        else if( ManyAssociation.class.isAssignableFrom( accessorType ) )
+        {
+            manyAssociationsModel().addManyAssociation( newManyAssociationModel( accessor, constraintClasses ) );
+            registeredStateNames.add( stateName );
+        }
+        else if( NamedAssociation.class.isAssignableFrom( accessorType ) )
+        {
+            namedAssociationsModel().addNamedAssociation( newNamedAssociationModel( accessor, constraintClasses ) );
+            registeredStateNames.add( stateName );
+        }
+    }
+
+    protected AssociationsModel associationsModel()
+    {
+        return null;
+    }
+
+    protected ManyAssociationsModel manyAssociationsModel()
+    {
+        return null;
+    }
+
+    protected NamedAssociationsModel namedAssociationsModel()
+    {
+        return null;
+    }
+
+    private PropertyModel newPropertyModel( AccessibleObject accessor,
+                                            List<Class<?>> constraintClasses
+                                          )
+    {
+        List<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
+        boolean optional = annotations.stream().anyMatch( isType( Optional.class ) );
+        ValueConstraintsModel valueConstraintsModel = constraintsFor(
+            annotations.stream(),
+            GenericPropertyInfo.propertyTypeOf( accessor ),
+            ( (Member) accessor ).getName(),
+            optional,
+            constraintClasses,
+            accessor );
+        ValueConstraintsInstance valueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            valueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+        MetaInfo metaInfo = stateDeclarations.metaInfoFor( accessor );
+        UseDefaults useDefaultsDeclaration = metaInfo.get( UseDefaults.class );
+        Object initialValue = stateDeclarations.initialValueOf( accessor );
+        if( initialValue == null && useDefaultsDeclaration != null )
+        {
+            initialValue = useDefaultsDeclaration.value();
+        }
+        boolean useDefaults = useDefaultsDeclaration != null || stateDeclarations.useDefaults( accessor );
+        boolean immutable = this.immutable || metaInfo.get( Immutable.class ) != null;
+        InitialValueProvider initialValueProvider = metaInfo.get( InitialValueProvider.class );
+        return new PropertyModel(
+            accessor,
+            immutable,
+            useDefaults,
+            valueConstraintsInstance,
+            metaInfo,
+            initialValue,
+            initialValueProvider
+        );
+    }
+
+    // Model
+    private ConstraintsModel constraintsFor( Method method,
+                                             List<Class<?>> constraintClasses
+                                           )
+    {
+        List<ValueConstraintsModel> parameterConstraintModels = Collections.emptyList();
+        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+        Type[] parameterTypes = method.getGenericParameterTypes();
+        boolean constrained = false;
+        for( int i = 0; i < parameterAnnotations.length; i++ )
+        {
+            Annotation[] parameterAnnotation = parameterAnnotations[ i ];
+
+            Name nameAnnotation = (Name) of( parameterAnnotation ).filter( isType( Name.class ) )
+                                                                  .findFirst().orElse( null );
+            String name = nameAnnotation == null ? "param" + ( i + 1 ) : nameAnnotation.value();
+
+            boolean optional = of( parameterAnnotation )
+                .anyMatch( isType( Optional.class ) );
+            ValueConstraintsModel parameterConstraintsModel = constraintsFor(
+                Arrays.stream( parameterAnnotation ),
+                parameterTypes[ i ],
+                name,
+                optional,
+                constraintClasses,
+                method );
+            if( parameterConstraintsModel.isConstrained() )
+            {
+                constrained = true;
+            }
+
+            if( parameterConstraintModels.isEmpty() )
+            {
+                parameterConstraintModels = new ArrayList<>();
+            }
+            parameterConstraintModels.add( parameterConstraintsModel );
+        }
+
+        if( !constrained )
+        {
+            return new ConstraintsModel( Collections.emptyList() );
+        }
+        else
+        {
+            return new ConstraintsModel( parameterConstraintModels );
+        }
+    }
+
+    private ValueConstraintsModel constraintsFor(
+        Stream<Annotation> constraintAnnotations,
+        Type valueType,
+        String name,
+        boolean optional,
+        Iterable<Class<?>> constraintClasses,
+        AccessibleObject accessor
+                                                )
+    {
+        valueType = wrapperClass( valueType );
+
+        List<AbstractConstraintModel> constraintModels = new ArrayList<>();
+        List<Annotation> filtered = constraintAnnotations
+            .filter( typeHasAnnotation( ConstraintDeclaration.class ) )
+            .collect( Collectors.toList() );
+
+        // TODO: This massive block below should be cleaned up.
+        nextConstraint:
+        for( Annotation constraintAnnotation : filtered )
+        {
+            // Check composite declarations first
+            Class<? extends Annotation> annotationType = constraintAnnotation.annotationType();
+            for( Class<?> constraint : constraintClasses )
+            {
+                @SuppressWarnings( "unchecked" )
+                Class<? extends Constraint<?, ?>> constraintType = (Class<? extends Constraint<?, ?>>) constraint;
+                if( helper.appliesTo( constraintType, annotationType, valueType ) )
+                {
+                    constraintModels.add( new ConstraintModel( constraintAnnotation, constraintType ) );
+                    continue nextConstraint;
+                }
+            }
+
+            // Check the annotation itself
+            Constraints constraints = annotationType.getAnnotation( Constraints.class );
+            if( constraints != null )
+            {
+                for( Class<? extends Constraint<?, ?>> constraintClass : constraints.value() )
+                {
+                    if( helper.appliesTo( constraintClass, annotationType, valueType ) )
+                    {
+                        constraintModels.add( new ConstraintModel( constraintAnnotation, constraintClass ) );
+                        continue nextConstraint;
+                    }
+                }
+            }
+
+            // No implementation found!
+            // Check if if it's a composite constraints
+            if( Arrays.stream( annotationType.getAnnotations() )
+                      .anyMatch( typeHasAnnotation( ConstraintDeclaration.class ) ) )
+            {
+                ValueConstraintsModel valueConstraintsModel = constraintsFor(
+                    Arrays.stream( annotationType.getAnnotations() ),
+                    valueType,
+                    name,
+                    optional,
+                    constraintClasses,
+                    accessor );
+                CompositeConstraintModel compositeConstraintModel = new CompositeConstraintModel(
+                    constraintAnnotation,
+                    valueConstraintsModel );
+                constraintModels.add( compositeConstraintModel );
+            }
+            else
+            {
+                handleInvalidCompositeType( "Cannot find implementation of constraint @", null, annotationType, null, valueType, (Member) accessor, types );
+            }
+        }
+        return new ValueConstraintsModel( constraintModels, name, optional );
+    }
+
+    private ConcernsModel concernsFor( Method method,
+                                       Class<?> mixinClass,
+                                       Stream<Class<?>> concernClasses
+                                     )
+    {
+        List<ConcernModel> concernsFor = new ArrayList<>();
+        concernClasses.forEach( concern ->
+                                {
+                                    if( helper.appliesTo( concern, method, types, mixinClass ) )
+                                    {
+                                        addConcernOrRepositionIfExists( concernsFor, helper.getConcernModel( concern ) );
+                                    }
+                                    else
+                                    {
+                                        // Lookup method in mixin
+                                        if( !InvocationHandler.class.isAssignableFrom( mixinClass ) )
+                                        {
+                                            try
+                                            {
+                                                Method mixinMethod = mixinClass.getMethod( method.getName(), method.getParameterTypes() );
+                                                if( helper.appliesTo( concern, mixinMethod, types, mixinClass ) )
+                                                {
+                                                    addConcernOrRepositionIfExists( concernsFor, helper.getConcernModel( concern ) );
+                                                }
+                                            }
+                                            catch( NoSuchMethodException e )
+                                            {
+                                                // Ignore
+                                            }
+                                        }
+                                    }
+                                } );
+
+        for( Annotation annotation : method.getAnnotations() )
+        {
+            if( annotation instanceof Concerns )
+            {
+                // Check @Concerns annotations directly on methods
+                Concerns concerns = (Concerns) annotation;
+                addConcerns( method, mixinClass, concernsFor, concerns );
+            }
+            else
+            {
+                // Check annotations on method that have @Concerns annotations themselves
+                Concerns concerns = annotation.annotationType().getAnnotation( Concerns.class );
+                addConcerns( method, mixinClass, concernsFor, concerns );
+            }
+        }
+
+        if( concernsFor.isEmpty() )
+        {
+            return ConcernsModel.EMPTY_CONCERNS;
+        }
+        else
+        {
+            return new ConcernsModel( concernsFor );
+        }
+    }
+
+    private void addConcerns( Method method, Class<?> mixinClass, List<ConcernModel> concernsFor, Concerns concerns )
+    {
+        if( concerns != null )
+        {
+            for( Class<?> concern : concerns.value() )
+            {
+                if( helper.appliesTo( concern, method, types, mixinClass ) )
+                {
+                    ConcernModel concernModel = helper.getConcernModel( concern );
+                    addConcernOrRepositionIfExists( concernsFor, concernModel );
+                }
+            }
+        }
+    }
+
+    private void addConcernOrRepositionIfExists( List<ConcernModel> concernsFor, ConcernModel concernModel )
+    {
+        // This remove/add is to allow re-ordering of the concerns
+        concernsFor.remove( concernModel );
+        concernsFor.add( concernModel );
+    }
+
+    private SideEffectsModel sideEffectsFor( Method method,
+                                             Class<?> mixinClass,
+                                             Stream<Class<?>> sideEffectClasses
+                                           )
+    {
+        List<SideEffectModel> sideEffectsFor = new ArrayList<>();
+        sideEffectClasses.forEach( sideEffect ->
+                                   {
+                                       SideEffectModel sideEffectModel = helper.getSideEffectModel( sideEffect );
+                                       if( helper.appliesTo( sideEffect, method, types, mixinClass ) )
+                                       {
+                                           addSideEffectOrRepositionIfExists( sideEffectsFor, sideEffectModel );
+                                       }
+                                       else
+                                       {
+                                           // Lookup method in mixin
+                                           if( !InvocationHandler.class.isAssignableFrom( mixinClass ) )
+                                           {
+                                               try
+                                               {
+                                                   Method mixinMethod = mixinClass.getMethod( method.getName(), method.getParameterTypes() );
+                                                   if( helper.appliesTo( sideEffect, mixinMethod, types, mixinClass ) )
+                                                   {
+                                                       addSideEffectOrRepositionIfExists( sideEffectsFor, sideEffectModel );
+                                                   }
+                                               }
+                                               catch( NoSuchMethodException e )
+                                               {
+                                                   // Ignore
+                                               }
+                                           }
+                                       }
+                                   } );
+
+        for( Annotation annotation : method.getAnnotations() )
+        {
+            if( annotation instanceof SideEffects )
+            {
+                // Check SideEffects annotation on method
+                SideEffects sideEffects = (SideEffects) annotation;
+                addSideEffects( method, mixinClass, sideEffectsFor, sideEffects );
+            }
+            else
+            {
+                // Check annotations on method that have @SideEffects annotations themselves
+                SideEffects sideEffects = annotation.annotationType().getAnnotation( SideEffects.class );
+                addSideEffects( method, mixinClass, sideEffectsFor, sideEffects );
+            }
+        }
+
+        if( sideEffectsFor.isEmpty() )
+        {
+            return SideEffectsModel.EMPTY_SIDEEFFECTS;
+        }
+        else
+        {
+            return new SideEffectsModel( sideEffectsFor );
+        }
+    }
+
+    private void addSideEffects( Method method, Class<?> mixinClass, List<SideEffectModel> sideEffectsFor, SideEffects sideEffects )
+    {
+        if( sideEffects != null )
+        {
+            for( Class<?> sideEffect : sideEffects.value() )
+            {
+                if( helper.appliesTo( sideEffect, method, types, mixinClass ) )
+                {
+                    SideEffectModel sideEffectModel = helper.getSideEffectModel( sideEffect );
+                    addSideEffectOrRepositionIfExists( sideEffectsFor, sideEffectModel );
+                }
+            }
+        }
+    }
+
+    private void addSideEffectOrRepositionIfExists( List<SideEffectModel> sideEffectsFor,
+                                                    SideEffectModel sideEffectModel
+                                                  )
+    {
+        // This add/remove is to allow reording of SideEffects.
+        sideEffectsFor.remove( sideEffectModel );
+        sideEffectsFor.add( sideEffectModel );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private Stream<Class<?>> constraintDeclarations( Class<?> type )
+    {
+        Stream<? extends Type> types = getTypes( type );
+        return constraintDeclarations( types );
+    }
+
+    private Stream<Class<?>> constraintDeclarations( Stream<? extends Type> types )
+    {
+        return types
+            .filter( mixinType -> Annotations.annotationOn( mixinType, Constraints.class ) != null )
+            .flatMap( mixinType -> Arrays.stream( Annotations.annotationOn( mixinType, Constraints.class ).value() ) );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private Stream<Class<?>> concernDeclarations( Class<?> type )
+    {
+        Stream<? extends Type> types = getTypes( type );
+        return concernDeclarations( types );
+    }
+
+    private Stream<Class<?>> concernDeclarations( Stream<? extends Type> types )
+    {
+        return types
+            .filter( mixinType -> Annotations.annotationOn( mixinType, Concerns.class ) != null )
+            .flatMap( mixinType -> Arrays.stream( Annotations.annotationOn( mixinType, Concerns.class ).value() ) );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private Stream<Class<?>> sideEffectDeclarations( Class<?> type )
+    {
+        Stream<? extends Type> types = getTypes( type );
+        return sideEffectDeclarations( types );
+    }
+
+    private Stream<Class<?>> sideEffectDeclarations( Stream<? extends Type> types )
+    {
+        return types
+            .filter( mixinType -> Annotations.annotationOn( mixinType, SideEffects.class ) != null )
+            .flatMap( mixinType -> Arrays.stream( Annotations.annotationOn( mixinType, SideEffects.class ).value() ) );
+    }
+
+    private Stream<Class<?>> mixinDeclarations( Class<?> type )
+    {
+        //Stream<? extends Type> types = typesOf( type );
+        return mixinDeclarations( of( type ) );
+    }
+
+    private Stream<Class<?>> mixinDeclarations( Stream<? extends Class> types )
+    {
+        return types.flatMap( this::getTypes ).flatMap( Classes::typesOf )
+                    .filter( mixinType -> Annotations.annotationOn( mixinType, Mixins.class ) != null )
+                    .flatMap( mixinType -> Arrays.stream( Annotations.annotationOn( mixinType, Mixins.class ).value() ) );
+    }
+
+    private Stream<Class> getAllTypes()
+    {
+        return this.types.stream().flatMap( this::getTypes );
+    }
+
+    private Stream<Class> getTypes( Class<?> clazz )
+    {
+        if( clazz.isInterface() )
+        {
+            return typesOf( clazz ).map( Classes.RAW_CLASS );
+        }
+        else
+        {
+            return classHierarchy( clazz ).map( Classes.RAW_CLASS );
+        }
+    }
+
+    private AssociationModel newAssociationModel( AccessibleObject accessor,
+                                                  List<Class<?>> constraintClasses
+                                                )
+    {
+        List<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
+        boolean optional = annotations.stream().anyMatch( isType( Optional.class ) );
+
+        // Constraints for Association references
+        ValueConstraintsModel constraintsModel = constraintsFor( annotations.stream(), GenericAssociationInfo
+            .associationTypeOf( accessor ), ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance valueConstraintsInstance;
+        if( constraintsModel.isConstrained() )
+        {
+            valueConstraintsInstance = constraintsModel.newInstance();
+        }
+        else
+        {
+            valueConstraintsInstance = new ValueConstraintsInstance( Collections.emptyList(), ( (Member) accessor ).getName(), true );
+        }
+
+        // Constraints for the Association itself
+        constraintsModel = constraintsFor( annotations.stream(), Association.class, ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance associationValueConstraintsInstance;
+        if( constraintsModel.isConstrained() )
+        {
+            associationValueConstraintsInstance = constraintsModel.newInstance();
+        }
+        else
+        {
+            associationValueConstraintsInstance = new ValueConstraintsInstance( Collections.emptyList(), ( (Member) accessor ).getName(), true );
+        }
+
+        MetaInfo metaInfo = stateDeclarations.metaInfoFor( accessor );
+        return new AssociationModel( accessor, valueConstraintsInstance, associationValueConstraintsInstance, metaInfo );
+    }
+
+    private ManyAssociationModel newManyAssociationModel( AccessibleObject accessor,
+                                                          List<Class<?>> constraintClasses
+                                                        )
+    {
+        List<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
+        boolean optional = annotations.stream().anyMatch( isType( Optional.class ) );
+
+        // Constraints for entities in ManyAssociation
+        ValueConstraintsModel valueConstraintsModel = constraintsFor( annotations.stream(), GenericAssociationInfo
+            .associationTypeOf( accessor ), ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance valueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            valueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+
+        // Constraints for the ManyAssociation itself
+        valueConstraintsModel = constraintsFor( annotations.stream(), ManyAssociation.class, ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance manyValueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            manyValueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+        MetaInfo metaInfo = stateDeclarations.metaInfoFor( accessor );
+        return new ManyAssociationModel( accessor, valueConstraintsInstance, manyValueConstraintsInstance, metaInfo );
+    }
+
+    private NamedAssociationModel newNamedAssociationModel( AccessibleObject accessor,
+                                                            List<Class<?>> constraintClasses
+                                                          )
+    {
+        List<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
+        boolean optional = annotations.stream().anyMatch( isType( Optional.class ) );
+
+        // Constraints for entities in NamedAssociation
+        ValueConstraintsModel valueConstraintsModel = constraintsFor( annotations.stream(), GenericAssociationInfo
+            .associationTypeOf( accessor ), ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance valueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            valueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+
+        // Constraints for the NamedAssociation itself
+        valueConstraintsModel = constraintsFor( annotations.stream(), NamedAssociation.class, ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance namedValueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            namedValueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+        MetaInfo metaInfo = stateDeclarations.metaInfoFor( accessor );
+        return new NamedAssociationModel( accessor, valueConstraintsInstance, namedValueConstraintsInstance, metaInfo );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ConfigurationDeclarationImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ConfigurationDeclarationImpl.java
new file mode 100644
index 0000000..45c71d5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ConfigurationDeclarationImpl.java
@@ -0,0 +1,126 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.ConfigurationDeclaration;
+
+import static java.util.Arrays.asList;
+
+/**
+ * Declaration of a Composite. Created by {@link org.apache.polygene.bootstrap.ModuleAssembly#configurations(Class[])}.
+ */
+public final class ConfigurationDeclarationImpl
+    implements ConfigurationDeclaration
+{
+    private final Iterable<EntityAssemblyImpl> entities;
+    private final Iterable<ValueAssemblyImpl> values;
+
+    public ConfigurationDeclarationImpl( Iterable<EntityAssemblyImpl> entities, Iterable<ValueAssemblyImpl> values  )
+    {
+        this.entities = entities;
+        this.values = values;
+    }
+
+    @Override
+    public ConfigurationDeclaration setMetaInfo( Object info )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.metaInfo.set( info );
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.metaInfo.set( info );
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationDeclaration visibleIn( Visibility visibility )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.visibility = visibility;
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.visibility = visibility;
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationDeclaration withConcerns( Class<?>... concerns )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.concerns.addAll( asList( concerns ) );
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.concerns.addAll( asList( concerns ) );
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationDeclaration withSideEffects( Class<?>... sideEffects )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.sideEffects.addAll( asList( sideEffects ) );
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.sideEffects.addAll( asList( sideEffects ) );
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationDeclaration withMixins( Class<?>... mixins )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.mixins.addAll( asList( mixins ) );
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.mixins.addAll( asList( mixins ) );
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationDeclaration withTypes( Class<?>... types )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.types.addAll( asList( types ) );
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.types.addAll( asList( types ) );
+        }
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/EntityAssemblyImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/EntityAssemblyImpl.java
new file mode 100644
index 0000000..605084c
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/EntityAssemblyImpl.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.polygene.runtime.bootstrap;
+
+import org.apache.polygene.api.common.InvalidApplicationException;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.bootstrap.AssociationDeclarations;
+import org.apache.polygene.bootstrap.EntityAssembly;
+import org.apache.polygene.bootstrap.ManyAssociationDeclarations;
+import org.apache.polygene.bootstrap.NamedAssociationDeclarations;
+import org.apache.polygene.bootstrap.StateDeclarations;
+import org.apache.polygene.runtime.association.AssociationsModel;
+import org.apache.polygene.runtime.association.ManyAssociationsModel;
+import org.apache.polygene.runtime.association.NamedAssociationsModel;
+import org.apache.polygene.runtime.composite.MixinsModel;
+import org.apache.polygene.runtime.composite.StateModel;
+import org.apache.polygene.runtime.entity.EntityMixinsModel;
+import org.apache.polygene.runtime.entity.EntityModel;
+import org.apache.polygene.runtime.entity.EntityStateModel;
+
+/**
+ * Declaration of a EntityComposite.
+ */
+public final class EntityAssemblyImpl
+    extends CompositeAssemblyImpl
+    implements EntityAssembly
+{
+    private AssociationDeclarations associationDeclarations;
+    private ManyAssociationDeclarations manyAssociationDeclarations;
+    private NamedAssociationDeclarations namedAssociationDeclarations;
+    private AssociationsModel associationsModel;
+    private ManyAssociationsModel manyAssociationsModel;
+    private NamedAssociationsModel namedAssociationsModel;
+
+    public EntityAssemblyImpl( Class<?> entityType )
+    {
+        super( entityType );
+        // The composite must always implement EntityComposite, as a marker interface
+        if( !EntityComposite.class.isAssignableFrom( entityType ) )
+        {
+            types.add( EntityComposite.class );
+        }
+    }
+
+    @Override
+    protected MixinsModel createMixinsModel()
+    {
+        return new EntityMixinsModel();
+    }
+
+    @Override
+    protected AssociationsModel associationsModel()
+    {
+        return associationsModel;
+    }
+
+    @Override
+    protected ManyAssociationsModel manyAssociationsModel()
+    {
+        return manyAssociationsModel;
+    }
+
+    @Override
+    protected NamedAssociationsModel namedAssociationsModel()
+    {
+        return namedAssociationsModel;
+    }
+
+    @Override
+    protected StateModel createStateModel()
+    {
+        return new EntityStateModel( propertiesModel, associationsModel, manyAssociationsModel, namedAssociationsModel );
+    }
+
+    EntityModel newEntityModel(
+        ModuleDescriptor module,
+        StateDeclarations stateDeclarations,
+        AssociationDeclarations associationDecs,
+        ManyAssociationDeclarations manyAssociationDecs,
+        NamedAssociationDeclarations namedAssociationDecs,
+        AssemblyHelper helper
+    )
+    {
+        this.associationDeclarations = associationDecs;
+        this.manyAssociationDeclarations = manyAssociationDecs;
+        this.namedAssociationDeclarations = namedAssociationDecs;
+        try
+        {
+            associationsModel = new AssociationsModel();
+            manyAssociationsModel = new ManyAssociationsModel();
+            namedAssociationsModel = new NamedAssociationsModel();
+            buildComposite( helper, stateDeclarations );
+
+            return new EntityModel( module, types, visibility, metaInfo,
+                                    (EntityMixinsModel) mixinsModel,
+                                    (EntityStateModel) stateModel, compositeMethodsModel );
+        }
+        catch( Exception e )
+        {
+            throw new InvalidApplicationException( "Could not register " + types, e );
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/EntityDeclarationImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/EntityDeclarationImpl.java
new file mode 100644
index 0000000..ee8adf4
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/EntityDeclarationImpl.java
@@ -0,0 +1,100 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.EntityDeclaration;
+
+import static java.util.Arrays.asList;
+
+/**
+ * Declaration of a Composite. Created by {@link org.apache.polygene.bootstrap.ModuleAssembly#transients(Class[])}.
+ */
+public final class EntityDeclarationImpl
+    implements EntityDeclaration
+{
+    private final Iterable<EntityAssemblyImpl> entities;
+
+    public EntityDeclarationImpl( Iterable<EntityAssemblyImpl> entities )
+    {
+        this.entities = entities;
+    }
+
+    @Override
+    public EntityDeclaration setMetaInfo( Object info )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.metaInfo.set( info );
+        }
+        return this;
+    }
+
+    @Override
+    public EntityDeclaration visibleIn( Visibility visibility )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.visibility = visibility;
+        }
+        return this;
+    }
+
+    @Override
+    public EntityDeclaration withConcerns( Class<?>... concerns )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.concerns.addAll( asList( concerns ) );
+        }
+        return this;
+    }
+
+    @Override
+    public EntityDeclaration withSideEffects( Class<?>... sideEffects )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.sideEffects.addAll( asList( sideEffects ) );
+        }
+        return this;
+    }
+
+    @Override
+    public EntityDeclaration withMixins( Class<?>... mixins )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.mixins.addAll( asList( mixins ) );
+        }
+        return this;
+    }
+
+    @Override
+    public EntityDeclaration withTypes( Class<?>... types )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.types.addAll( asList( types ) );
+        }
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImplementsMethodAppliesToFilter.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImplementsMethodAppliesToFilter.java
new file mode 100644
index 0000000..a188253
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImplementsMethodAppliesToFilter.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import org.apache.polygene.api.common.AppliesToFilter;
+
+/**
+ * JAVADOC
+ */
+final class ImplementsMethodAppliesToFilter
+    implements AppliesToFilter
+{
+    @Override
+    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
+    {
+        try
+        {
+            Method fragmentMethod = fragmentClass.getMethod( method.getName(), method.getParameterTypes() );
+            return !Modifier.isAbstract( fragmentMethod.getModifiers() );
+        }
+        catch( NoSuchMethodException e )
+        {
+            return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImportedServiceAssemblyImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImportedServiceAssemblyImpl.java
new file mode 100644
index 0000000..c455aed
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImportedServiceAssemblyImpl.java
@@ -0,0 +1,125 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.common.InvalidApplicationException;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.importer.InstanceImporter;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.bootstrap.ImportedServiceAssembly;
+import org.apache.polygene.runtime.activation.ActivatorsModel;
+import org.apache.polygene.runtime.service.ImportedServiceModel;
+
+/**
+ * Declaration of an imported Service.
+ *
+ * Created by {@link org.apache.polygene.runtime.bootstrap.ModuleAssemblyImpl#importedServices(Class[])}.
+ */
+public final class ImportedServiceAssemblyImpl
+    implements ImportedServiceAssembly
+{
+    private final Class<?> serviceType;
+    private final ModuleAssemblyImpl moduleAssembly;
+    @SuppressWarnings( "raw" )
+    Class<? extends ServiceImporter> serviceProvider = InstanceImporter.class;
+    String identity;
+    boolean importOnStartup = false;
+    MetaInfo metaInfo = new MetaInfo();
+    Visibility visibility = Visibility.module;
+    List<Class<? extends Activator<?>>> activators = new ArrayList<>();
+
+    public ImportedServiceAssemblyImpl( Class<?> serviceType, ModuleAssemblyImpl moduleAssembly )
+    {
+        this.serviceType = serviceType;
+        this.moduleAssembly = moduleAssembly;
+    }
+
+    @Override
+    public Stream<Class<?>> types()
+    {
+        return Stream.of( serviceType );
+    }
+
+    @SuppressWarnings( { "raw", "unchecked" } )
+    void addImportedServiceModel( ModuleDescriptor module, List<ImportedServiceModel> serviceModels )
+    {
+        try
+        {
+            Identity id;
+            if( identity == null )
+            {
+                id = generateId( serviceModels, serviceType );
+            }
+            else
+            {
+                id = new StringIdentity( identity );
+            }
+
+            ImportedServiceModel serviceModel = new ImportedServiceModel( module,
+                                                                          serviceType,
+                                                                          visibility,
+                                                                          serviceProvider,
+                                                                          id,
+                                                                          importOnStartup,
+                                                                          new MetaInfo( metaInfo ).withAnnotations( serviceType ),
+                                                                          new ActivatorsModel( activators ),
+                                                                          moduleAssembly.name() );
+            serviceModels.add( serviceModel );
+        }
+        catch( Exception e )
+        {
+            throw new InvalidApplicationException( "Could not register " + serviceType.getName(), e );
+        }
+    }
+
+    @SuppressWarnings( "raw" )
+    private Identity generateId( List<ImportedServiceModel> serviceModels, Class serviceType )
+    {
+        // Find reference that is not yet used
+        int idx = 0;
+        Identity id = new StringIdentity( serviceType.getSimpleName() );
+        boolean invalid;
+        do
+        {
+            invalid = false;
+            for( ImportedServiceModel serviceModel : serviceModels )
+            {
+                if( serviceModel.identity().equals( id ) )
+                {
+                    idx++;
+                    id = new StringIdentity( serviceType.getSimpleName() + "_" + idx );
+                    invalid = true;
+                    break;
+                }
+            }
+        }
+        while( invalid );
+        return id;
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImportedServiceDeclarationImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImportedServiceDeclarationImpl.java
new file mode 100644
index 0000000..257414e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImportedServiceDeclarationImpl.java
@@ -0,0 +1,128 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.qualifier.ServiceTags;
+import org.apache.polygene.bootstrap.ImportedServiceDeclaration;
+
+/**
+ * Declaration of an imported Service.
+ */
+public final class ImportedServiceDeclarationImpl
+    implements ImportedServiceDeclaration
+{
+    private final Iterable<ImportedServiceAssemblyImpl> assemblies;
+
+    public ImportedServiceDeclarationImpl( Iterable<ImportedServiceAssemblyImpl> assemblies )
+    {
+        this.assemblies = assemblies;
+    }
+
+    @Override
+    public ImportedServiceDeclaration importOnStartup()
+    {
+        for( ImportedServiceAssemblyImpl assembly : assemblies )
+        {
+            assembly.importOnStartup = true;
+        }
+        return this;
+    }
+
+    @Override
+    public ImportedServiceDeclaration visibleIn( Visibility visibility )
+    {
+        for( ImportedServiceAssemblyImpl assembly : assemblies )
+        {
+            assembly.visibility = visibility;
+        }
+        return this;
+    }
+
+    @Override
+    @SuppressWarnings( "raw" )
+    public ImportedServiceDeclaration importedBy( Class<? extends ServiceImporter> sip )
+    {
+        for( ImportedServiceAssemblyImpl assembly : assemblies )
+        {
+            assembly.serviceProvider = sip;
+        }
+        return this;
+    }
+
+    @Override
+    public ImportedServiceDeclaration identifiedBy( String identity )
+    {
+        for( ImportedServiceAssemblyImpl assembly : assemblies )
+        {
+            assembly.identity = identity;
+        }
+        return this;
+    }
+
+    @Override
+    public ImportedServiceDeclaration taggedWith( String... tags )
+    {
+        for( ImportedServiceAssemblyImpl serviceAssembly : assemblies )
+        {
+            ServiceTags previousTags = serviceAssembly.metaInfo.get( ServiceTags.class );
+            if( previousTags != null )
+            {
+                List<String> tagList = new ArrayList<>();
+                Collections.addAll( tagList, previousTags.tags() );
+                Collections.addAll( tagList, tags );
+                serviceAssembly.metaInfo.set( new ServiceTags( tagList.toArray( new String[ tagList.size() ] ) ) );
+            }
+            else
+            {
+                serviceAssembly.metaInfo.set( new ServiceTags( tags ) );
+            }
+        }
+
+        return this;
+    }
+
+    @Override
+    public ImportedServiceDeclaration setMetaInfo( Object serviceAttribute )
+    {
+        for( ImportedServiceAssemblyImpl assembly : assemblies )
+        {
+            assembly.metaInfo.set( serviceAttribute );
+        }
+        return this;
+    }
+
+    @Override
+    @SafeVarargs
+    public final ImportedServiceDeclaration withActivators( Class<? extends Activator<?>>... activators )
+    {
+        for ( ImportedServiceAssemblyImpl serviceAssembly : assemblies ) {
+            serviceAssembly.activators.addAll( Arrays.asList( activators ) );
+        }
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/LayerAssemblyImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/LayerAssemblyImpl.java
new file mode 100644
index 0000000..8b18426
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/LayerAssemblyImpl.java
@@ -0,0 +1,630 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Predicate;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.AssemblyVisitor;
+import org.apache.polygene.bootstrap.EntityAssembly;
+import org.apache.polygene.bootstrap.EntityDeclaration;
+import org.apache.polygene.bootstrap.ImportedServiceAssembly;
+import org.apache.polygene.bootstrap.ImportedServiceDeclaration;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ObjectAssembly;
+import org.apache.polygene.bootstrap.ObjectDeclaration;
+import org.apache.polygene.bootstrap.ServiceAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.bootstrap.TransientAssembly;
+import org.apache.polygene.bootstrap.TransientDeclaration;
+import org.apache.polygene.bootstrap.ValueAssembly;
+import org.apache.polygene.bootstrap.ValueDeclaration;
+
+/**
+ * Assembly of a Layer. From here you can create more ModuleAssemblies for
+ * the Layer that is being assembled. It is also here that you define
+ * what other Layers this Layer is using by calling {@link org.apache.polygene.runtime.bootstrap.LayerAssemblyImpl#uses()}.
+ */
+public final class LayerAssemblyImpl
+    implements LayerAssembly
+{
+    private final ApplicationAssembly applicationAssembly;
+    private final HashMap<String, ModuleAssemblyImpl> moduleAssemblies;
+    private final Set<LayerAssembly> uses;
+
+    private String name;
+    private final MetaInfo metaInfo = new MetaInfo();
+    private final List<Class<? extends Activator<Layer>>> activators = new ArrayList<>();
+
+    public LayerAssemblyImpl( ApplicationAssembly applicationAssembly, String name )
+    {
+        this.applicationAssembly = applicationAssembly;
+        this.name = name;
+
+        moduleAssemblies = new LinkedHashMap<>();
+        uses = new LinkedHashSet<>();
+    }
+
+    @Override
+    public ModuleAssembly module( String name )
+    {
+        if( name != null )
+        {
+            ModuleAssemblyImpl existing = moduleAssemblies.get( name );
+            if( existing != null )
+            {
+                return existing;
+            }
+        }
+        ModuleAssemblyImpl moduleAssembly = new ModuleAssemblyImpl( this, name );
+        moduleAssemblies.put( name, moduleAssembly );
+        return moduleAssembly;
+    }
+
+    @Override
+    public ApplicationAssembly application()
+    {
+        return applicationAssembly;
+    }
+
+    @Override
+    public LayerAssembly setName( String name )
+    {
+        this.name = name;
+        return this;
+    }
+
+    @Override
+    public LayerAssembly setMetaInfo( Object info )
+    {
+        metaInfo.set( info );
+        return this;
+    }
+
+    @Override
+    public LayerAssembly uses( LayerAssembly... layerAssembly )
+        throws IllegalArgumentException
+    {
+        uses.addAll( Arrays.asList( layerAssembly ) );
+        return this;
+    }
+
+    @Override
+    @SafeVarargs
+    public final LayerAssembly withActivators( Class<? extends Activator<Layer>>... activators )
+    {
+        this.activators.addAll( Arrays.asList( activators ) );
+        return this;
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> void visit( AssemblyVisitor<ThrowableType> visitor )
+        throws ThrowableType
+    {
+        visitor.visitLayer( this );
+        for( ModuleAssemblyImpl moduleAssembly : moduleAssemblies.values() )
+        {
+            moduleAssembly.visit( visitor );
+        }
+    }
+
+    @Override
+    public EntityDeclaration entities( Predicate<? super EntityAssembly> specification )
+    {
+        final List<EntityDeclaration> declarations = new ArrayList<>();
+
+        for( ModuleAssemblyImpl moduleAssembly : moduleAssemblies.values() )
+        {
+            declarations.add( moduleAssembly.entities( specification ) );
+        }
+
+        return new EntityDeclaration()
+        {
+            @Override
+            public EntityDeclaration setMetaInfo( Object info )
+            {
+                for( EntityDeclaration declaration : declarations )
+                {
+                    declaration.setMetaInfo( info );
+                }
+                return this;
+            }
+
+            @Override
+            public EntityDeclaration visibleIn( Visibility visibility )
+            {
+                for( EntityDeclaration declaration : declarations )
+                {
+                    declaration.visibleIn( visibility );
+                }
+                return this;
+            }
+
+            @Override
+            public EntityDeclaration withConcerns( Class<?>... concerns )
+            {
+                for( EntityDeclaration declaration : declarations )
+                {
+                    declaration.withConcerns( concerns );
+                }
+                return this;
+            }
+
+            @Override
+            public EntityDeclaration withSideEffects( Class<?>... sideEffects )
+            {
+                for( EntityDeclaration declaration : declarations )
+                {
+                    declaration.withSideEffects( sideEffects );
+                }
+                return this;
+            }
+
+            @Override
+            public EntityDeclaration withMixins( Class<?>... mixins )
+            {
+                for( EntityDeclaration declaration : declarations )
+                {
+                    declaration.withMixins( mixins );
+                }
+                return this;
+            }
+
+            @Override
+            public EntityDeclaration withTypes( Class<?>... types )
+            {
+                for( EntityDeclaration declaration : declarations )
+                {
+                    declaration.withTypes( types );
+                }
+                return this;
+            }
+        };
+    }
+
+    @Override
+    public ServiceDeclaration services( Predicate<? super ServiceAssembly> specification )
+    {
+        final List<ServiceDeclaration> declarations = new ArrayList<>();
+
+        for( ModuleAssemblyImpl moduleAssembly : moduleAssemblies.values() )
+        {
+            declarations.add( moduleAssembly.services( specification ) );
+        }
+
+        return new ServiceDeclaration()
+        {
+            @Override
+            public ServiceDeclaration setMetaInfo( Object serviceAttribute )
+            {
+                for( ServiceDeclaration declaration : declarations )
+                {
+                    declaration.setMetaInfo( serviceAttribute );
+                }
+                return this;
+            }
+
+            @Override
+            public ServiceDeclaration visibleIn( Visibility visibility )
+            {
+                for( ServiceDeclaration declaration : declarations )
+                {
+                    declaration.visibleIn( visibility );
+                }
+                return this;
+            }
+
+            @Override
+            public ServiceDeclaration withConcerns( Class<?>... concerns )
+            {
+                for( ServiceDeclaration declaration : declarations )
+                {
+                    declaration.withConcerns( concerns );
+                }
+                return this;
+            }
+
+            @Override
+            public ServiceDeclaration withSideEffects( Class<?>... sideEffects )
+            {
+                for( ServiceDeclaration declaration : declarations )
+                {
+                    declaration.withSideEffects( sideEffects );
+                }
+                return this;
+            }
+
+            @Override
+            public ServiceDeclaration withMixins( Class<?>... mixins )
+            {
+                for( ServiceDeclaration declaration : declarations )
+                {
+                    declaration.withMixins( mixins );
+                }
+                return this;
+            }
+
+            @Override
+            public ServiceDeclaration withTypes( Class<?>... types )
+            {
+                for( ServiceDeclaration declaration : declarations )
+                {
+                    declaration.withTypes( types );
+                }
+                return this;
+            }
+
+            @Override
+            @SafeVarargs
+            public final ServiceDeclaration withActivators( Class<? extends Activator<?>>... activators )
+            {
+                for( ServiceDeclaration declaration : declarations )
+                {
+                    declaration.withActivators( activators );
+                }
+                return this;
+            }
+
+            @Override
+            public ServiceDeclaration identifiedBy( String identity )
+            {
+                for( ServiceDeclaration declaration : declarations )
+                {
+                    declaration.identifiedBy( identity );
+                }
+                return this;
+            }
+
+            @Override
+            public ServiceDeclaration taggedWith( String... tags )
+            {
+                for( ServiceDeclaration declaration : declarations )
+                {
+                    declaration.taggedWith( tags );
+                }
+                return this;
+            }
+
+            @Override
+            public ServiceDeclaration instantiateOnStartup()
+            {
+                for( ServiceDeclaration declaration : declarations )
+                {
+                    declaration.instantiateOnStartup();
+                }
+
+                return this;
+            }
+        };
+    }
+
+    @Override
+    public TransientDeclaration transients( Predicate<? super TransientAssembly> specification )
+    {
+        final List<TransientDeclaration> declarations = new ArrayList<>();
+
+        for( ModuleAssemblyImpl moduleAssembly : moduleAssemblies.values() )
+        {
+            declarations.add( moduleAssembly.transients( specification ) );
+        }
+
+        return new TransientDeclaration()
+        {
+            @Override
+            public TransientDeclaration setMetaInfo( Object info )
+            {
+                for( TransientDeclaration declaration : declarations )
+                {
+                    declaration.setMetaInfo( info );
+                }
+                return this;
+            }
+
+            @Override
+            public TransientDeclaration visibleIn( Visibility visibility )
+            {
+                for( TransientDeclaration declaration : declarations )
+                {
+                    declaration.visibleIn( visibility );
+                }
+                return this;
+            }
+
+            @Override
+            public TransientDeclaration withConcerns( Class<?>... concerns )
+            {
+                for( TransientDeclaration declaration : declarations )
+                {
+                    declaration.withConcerns( concerns );
+                }
+                return this;
+            }
+
+            @Override
+            public TransientDeclaration withSideEffects( Class<?>... sideEffects )
+            {
+                for( TransientDeclaration declaration : declarations )
+                {
+                    declaration.withSideEffects( sideEffects );
+                }
+                return this;
+            }
+
+            @Override
+            public TransientDeclaration withMixins( Class<?>... mixins )
+            {
+                for( TransientDeclaration declaration : declarations )
+                {
+                    declaration.withMixins( mixins );
+                }
+                return this;
+            }
+
+            @Override
+            public TransientDeclaration withTypes( Class<?>... types )
+            {
+                for( TransientDeclaration declaration : declarations )
+                {
+                    declaration.withTypes( types );
+                }
+                return this;
+            }
+        };
+    }
+
+    @Override
+    public ValueDeclaration values( Predicate<? super ValueAssembly> specification )
+    {
+        final List<ValueDeclaration> declarations = new ArrayList<>();
+
+        for( ModuleAssemblyImpl moduleAssembly : moduleAssemblies.values() )
+        {
+            declarations.add( moduleAssembly.values( specification ) );
+        }
+        return new ValueDeclaration()
+        {
+            @Override
+            public ValueDeclaration setMetaInfo( Object info )
+            {
+                for( ValueDeclaration declaration : declarations )
+                {
+                    declaration.setMetaInfo( info );
+                }
+                return this;
+            }
+
+            @Override
+            public ValueDeclaration visibleIn( Visibility visibility )
+            {
+                for( ValueDeclaration declaration : declarations )
+                {
+                    declaration.visibleIn( visibility );
+                }
+                return this;
+            }
+
+            @Override
+            public ValueDeclaration withConcerns( Class<?>... concerns )
+            {
+                for( ValueDeclaration declaration : declarations )
+                {
+                    declaration.withConcerns( concerns );
+                }
+                return this;
+            }
+
+            @Override
+            public ValueDeclaration withSideEffects( Class<?>... sideEffects )
+            {
+                for( ValueDeclaration declaration : declarations )
+                {
+                    declaration.withSideEffects( sideEffects );
+                }
+                return this;
+            }
+
+            @Override
+            public ValueDeclaration withMixins( Class<?>... mixins )
+            {
+                for( ValueDeclaration declaration : declarations )
+                {
+                    declaration.withMixins( mixins );
+                }
+                return this;
+            }
+
+            @Override
+            public ValueDeclaration withTypes( Class<?>... types )
+            {
+                for( ValueDeclaration declaration : declarations )
+                {
+                    declaration.withTypes( types );
+                }
+                return this;
+            }
+        };
+    }
+
+    @Override
+    public ObjectDeclaration objects( Predicate<? super ObjectAssembly> specification )
+    {
+        final List<ObjectDeclaration> declarations = new ArrayList<>();
+
+        for( ModuleAssemblyImpl moduleAssembly : moduleAssemblies.values() )
+        {
+            declarations.add( moduleAssembly.objects( specification ) );
+        }
+        return new ObjectDeclaration()
+        {
+            @Override
+            public ObjectDeclaration setMetaInfo( Object info )
+            {
+                for( ObjectDeclaration declaration : declarations )
+                {
+                    declaration.setMetaInfo( info );
+                }
+                return this;
+            }
+
+            @Override
+            public ObjectDeclaration visibleIn( Visibility visibility )
+                throws IllegalStateException
+            {
+                for( ObjectDeclaration declaration : declarations )
+                {
+                    declaration.visibleIn( visibility );
+                }
+                return this;
+            }
+        };
+    }
+
+    @Override
+    public ImportedServiceDeclaration importedServices( Predicate<? super ImportedServiceAssembly> specification )
+    {
+        final List<ImportedServiceDeclaration> declarations = new ArrayList<>();
+
+        for( ModuleAssemblyImpl moduleAssembly : moduleAssemblies.values() )
+        {
+            declarations.add( moduleAssembly.importedServices( specification ) );
+        }
+        return new ImportedServiceDeclaration()
+        {
+
+            @Override
+            public ImportedServiceDeclaration importOnStartup()
+            {
+                for( ImportedServiceDeclaration declaration : declarations )
+                {
+                    declaration.importOnStartup();
+                }
+                return this;
+            }
+
+            @Override
+            public ImportedServiceDeclaration visibleIn( Visibility visibility )
+            {
+                for( ImportedServiceDeclaration declaration : declarations )
+                {
+                    declaration.visibleIn( visibility );
+                }
+                return this;
+            }
+
+            @Override
+            public ImportedServiceDeclaration importedBy( Class<? extends ServiceImporter> serviceImporterClass )
+            {
+                for( ImportedServiceDeclaration declaration : declarations )
+                {
+                    declaration.importedBy( serviceImporterClass );
+                }
+                return this;
+            }
+
+            @Override
+            public ImportedServiceDeclaration identifiedBy( String identity )
+            {
+                for( ImportedServiceDeclaration declaration : declarations )
+                {
+                    declaration.identifiedBy( identity );
+                }
+                return this;
+            }
+
+            @Override
+            public ImportedServiceDeclaration taggedWith( String... tags )
+            {
+                for( ImportedServiceDeclaration declaration : declarations )
+                {
+                    declaration.taggedWith( tags );
+                }
+                return this;
+            }
+
+            @Override
+            public ImportedServiceDeclaration setMetaInfo( Object serviceAttribute )
+            {
+                for( ImportedServiceDeclaration declaration : declarations )
+                {
+                    declaration.setMetaInfo( serviceAttribute );
+                }
+                return this;
+            }
+
+            @Override
+            @SafeVarargs
+            public final ImportedServiceDeclaration withActivators( Class<? extends Activator<?>>... activators )
+            {
+                for( ImportedServiceDeclaration declaration : declarations )
+                {
+                    declaration.withActivators( activators );
+                }
+                return this;
+            }
+
+        };
+    }
+
+    Collection<ModuleAssemblyImpl> moduleAssemblies()
+    {
+        return moduleAssemblies.values();
+    }
+
+    Set<LayerAssembly> uses()
+    {
+        return uses;
+    }
+
+    public MetaInfo metaInfo()
+    {
+        return metaInfo;
+    }
+
+    @Override
+    public String name()
+    {
+        return name;
+    }
+
+    public List<Class<? extends Activator<Layer>>> activators()
+    {
+        return activators;
+    }
+
+    @Override
+    public final String toString()
+    {
+        return "LayerAssembly [" + name + "]";
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ModuleAssemblyImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ModuleAssemblyImpl.java
new file mode 100644
index 0000000..011da1b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ModuleAssemblyImpl.java
@@ -0,0 +1,718 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.IdentityGenerator;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.service.DuplicateServiceIdentityException;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.type.HasEqualOrAssignableFromType;
+import org.apache.polygene.api.type.HasTypes;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.AssemblyReportException;
+import org.apache.polygene.bootstrap.AssemblySpecifications;
+import org.apache.polygene.bootstrap.AssemblyVisitor;
+import org.apache.polygene.bootstrap.ConfigurationDeclaration;
+import org.apache.polygene.bootstrap.EntityAssembly;
+import org.apache.polygene.bootstrap.EntityDeclaration;
+import org.apache.polygene.bootstrap.ImportedServiceAssembly;
+import org.apache.polygene.bootstrap.ImportedServiceDeclaration;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.MetaInfoDeclaration;
+import org.apache.polygene.bootstrap.MixinDeclaration;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ObjectAssembly;
+import org.apache.polygene.bootstrap.ObjectDeclaration;
+import org.apache.polygene.bootstrap.ServiceAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.bootstrap.TransientAssembly;
+import org.apache.polygene.bootstrap.TransientDeclaration;
+import org.apache.polygene.bootstrap.ValueAssembly;
+import org.apache.polygene.bootstrap.ValueDeclaration;
+import org.apache.polygene.bootstrap.identity.DefaultIdentityGeneratorAssembler;
+import org.apache.polygene.bootstrap.serialization.DefaultSerializationAssembler;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.apache.polygene.runtime.activation.ActivatorsModel;
+import org.apache.polygene.runtime.composite.TransientModel;
+import org.apache.polygene.runtime.composite.TransientsModel;
+import org.apache.polygene.runtime.entity.EntitiesModel;
+import org.apache.polygene.runtime.entity.EntityModel;
+import org.apache.polygene.runtime.object.ObjectModel;
+import org.apache.polygene.runtime.object.ObjectsModel;
+import org.apache.polygene.runtime.service.ImportedServiceModel;
+import org.apache.polygene.runtime.service.ImportedServicesModel;
+import org.apache.polygene.runtime.service.ServiceModel;
+import org.apache.polygene.runtime.service.ServicesModel;
+import org.apache.polygene.runtime.structure.LayerModel;
+import org.apache.polygene.runtime.structure.ModuleModel;
+import org.apache.polygene.runtime.value.ValueModel;
+import org.apache.polygene.runtime.value.ValuesModel;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.singleton;
+import static java.util.stream.Collectors.toList;
+
+/**
+ * Assembly of a Module. This is where you register all objects, Composites,
+ * Services. Each "add" method returns a declaration that you can use to add
+ * additional information and metadata. If you call an "add" method with many
+ * parameters then the declared metadata will apply to all types in the method
+ * call.
+ */
+final class ModuleAssemblyImpl
+        implements ModuleAssembly
+{
+    private static HashMap<Class, Assembler> defaultAssemblers;
+
+    private final LayerAssembly layerAssembly;
+    private String name;
+    private final MetaInfo metaInfo = new MetaInfo();
+
+    private final List<Class<? extends Activator<Module>>> activators = new ArrayList<>();
+    private final List<ServiceAssemblyImpl> serviceAssemblies = new ArrayList<>();
+    private final Map<Class<?>, ImportedServiceAssemblyImpl> importedServiceAssemblies = new LinkedHashMap<>();
+    private final Map<Class<? extends EntityComposite>, EntityAssemblyImpl> entityAssemblies = new LinkedHashMap<>();
+    private final Map<Class<? extends ValueComposite>, ValueAssemblyImpl> valueAssemblies = new LinkedHashMap<>();
+    private final Map<Class<? extends TransientComposite>, TransientAssemblyImpl> transientAssemblies = new LinkedHashMap<>();
+
+    private final Map<Class<?>, ObjectAssemblyImpl> objectAssemblies = new LinkedHashMap<>();
+
+    private final MetaInfoDeclaration metaInfoDeclaration = new MetaInfoDeclaration();
+
+    static
+    {
+        defaultAssemblers = new HashMap<>();
+        defaultAssemblers.put( UnitOfWorkFactory.class, new DefaultUnitOfWorkAssembler() );
+        defaultAssemblers.put( IdentityGenerator.class, new DefaultIdentityGeneratorAssembler() );
+        defaultAssemblers.put( Serialization.class, new DefaultSerializationAssembler() );
+    }
+
+    ModuleAssemblyImpl(LayerAssembly layerAssembly, String name)
+    {
+        this.layerAssembly = layerAssembly;
+        this.name = name;
+    }
+
+    @Override
+    public LayerAssembly layer()
+    {
+        return layerAssembly;
+    }
+
+    @Override
+    public ModuleAssembly module(String layerName, String moduleName)
+    {
+        return layerAssembly.application().module(layerName, moduleName);
+    }
+
+    @Override
+    public ModuleAssembly setName(String name)
+    {
+        this.name = name;
+        return this;
+    }
+
+    @Override
+    public String name()
+    {
+        return name;
+    }
+
+    public ModuleAssembly setMetaInfo(Object info)
+    {
+        metaInfo.set(info);
+        return this;
+    }
+
+    @Override
+    @SafeVarargs
+    public final ModuleAssembly withActivators(Class<? extends Activator<Module>>... activators)
+    {
+        this.activators.addAll( asList( activators ) );
+        return this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public ValueDeclaration values(Class<?>... valueTypes)
+    {
+        List<ValueAssemblyImpl> assemblies = new ArrayList<>();
+
+        for (Class valueType : valueTypes)
+        {
+            if (valueAssemblies.containsKey(valueType))
+            {
+                assemblies.add(valueAssemblies.get(valueType));
+            }
+            else
+            {
+                ValueAssemblyImpl valueAssembly = new ValueAssemblyImpl(valueType);
+                valueAssemblies.put(valueType, valueAssembly);
+                assemblies.add(valueAssembly);
+            }
+        }
+
+        return new ValueDeclarationImpl(assemblies);
+    }
+
+    @Override
+    public ValueDeclaration values(Predicate<? super ValueAssembly> specification)
+    {
+        List<ValueAssemblyImpl> assemblies = valueAssemblies.values().stream()
+                .filter(specification::test)
+                .collect(toList());
+        return new ValueDeclarationImpl(assemblies);
+    }
+
+    @Override
+    @SuppressWarnings({"raw", "unchecked"})
+    public TransientDeclaration transients(Class<?>... transientTypes)
+    {
+        List<TransientAssemblyImpl> assemblies = new ArrayList<>();
+
+        for (Class valueType : transientTypes)
+        {
+            if (transientAssemblies.containsKey(valueType))
+            {
+                assemblies.add(transientAssemblies.get(valueType));
+            }
+            else
+            {
+                TransientAssemblyImpl transientAssembly = new TransientAssemblyImpl(valueType);
+                transientAssemblies.put(valueType, transientAssembly);
+                assemblies.add(transientAssembly);
+            }
+        }
+
+        return new TransientDeclarationImpl(assemblies);
+    }
+
+    @Override
+    public TransientDeclaration transients(Predicate<? super TransientAssembly> specification)
+    {
+        List<TransientAssemblyImpl> assemblies = transientAssemblies.values().stream()
+                .filter(specification::test)
+                .collect(toList());
+
+        return new TransientDeclarationImpl(assemblies);
+    }
+
+    @Override
+    @SuppressWarnings({"raw", "unchecked"})
+    public EntityDeclaration entities(Class<?>... entityTypes)
+    {
+        List<EntityAssemblyImpl> assemblies = new ArrayList<>();
+
+        for (Class entityType : entityTypes)
+        {
+            if (entityAssemblies.containsKey(entityType))
+            {
+                assemblies.add(entityAssemblies.get(entityType));
+            }
+            else
+            {
+                EntityAssemblyImpl entityAssembly = new EntityAssemblyImpl(entityType);
+                entityAssemblies.put(entityType, entityAssembly);
+                assemblies.add(entityAssembly);
+            }
+        }
+
+        return new EntityDeclarationImpl(assemblies);
+    }
+
+    @Override
+    public EntityDeclaration entities(Predicate<? super EntityAssembly> specification)
+    {
+        List<EntityAssemblyImpl> assemblies = entityAssemblies.values().stream()
+                .filter(specification::test)
+                .collect(toList());
+
+        return new EntityDeclarationImpl(assemblies);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public ConfigurationDeclaration configurations(Class<?>... configurationTypes)
+    {
+        List<EntityAssemblyImpl> entityAssemblyList = new ArrayList<>();
+
+        for (Class entityType : configurationTypes)
+        {
+            if (this.entityAssemblies.containsKey(entityType))
+            {
+                entityAssemblyList.add(this.entityAssemblies.get(entityType));
+            }
+            else
+            {
+                EntityAssemblyImpl entityAssembly = new EntityAssemblyImpl(entityType);
+                this.entityAssemblies.put(entityType, entityAssembly);
+                entityAssemblyList.add(entityAssembly);
+            }
+        }
+
+        List<ValueAssemblyImpl> valueAssemblyList = new ArrayList<>();
+
+        for (Class valueType : configurationTypes)
+        {
+            if (valueAssemblies.containsKey(valueType))
+            {
+                valueAssemblyList.add(valueAssemblies.get(valueType));
+            }
+            else
+            {
+                ValueAssemblyImpl valueAssembly = new ValueAssemblyImpl(valueType);
+                valueAssemblies.put(valueType, valueAssembly);
+                valueAssemblyList.add(valueAssembly);
+                valueAssembly.types.add(HasIdentity.class);
+            }
+        }
+
+        return new ConfigurationDeclarationImpl(entityAssemblyList, valueAssemblyList);
+    }
+
+    @Override
+    public ConfigurationDeclaration configurations( Predicate<HasTypes> specification )
+    {
+        Predicate<HasTypes> isConfigurationComposite = new HasEqualOrAssignableFromType<>( HasIdentity.class );
+        specification = specification.and( isConfigurationComposite );
+        List<EntityAssemblyImpl> entityAssemblyList = new ArrayList<>();
+        for( EntityAssemblyImpl entityAssembly : entityAssemblies.values() )
+        {
+            if( specification.test( entityAssembly ) )
+            {
+                entityAssemblyList.add( entityAssembly );
+            }
+        }
+        List<ValueAssemblyImpl> valueAssemblyList = new ArrayList<>();
+        for( ValueAssemblyImpl transientAssembly : valueAssemblies.values() )
+        {
+            if( specification.test( transientAssembly ) )
+            {
+                valueAssemblyList.add( transientAssembly );
+            }
+        }
+        return new ConfigurationDeclarationImpl( entityAssemblyList, valueAssemblyList );
+    }
+
+    @Override
+    public ObjectDeclaration objects(Class<?>... objectTypes)
+            throws AssemblyException
+    {
+        List<ObjectAssemblyImpl> assemblies = new ArrayList<>();
+
+        for (Class<?> objectType : objectTypes)
+        {
+            if (objectType.isInterface())
+            {
+                throw new AssemblyException("Interfaces can not be Polygene Objects.");
+            }
+            if (objectAssemblies.containsKey(objectType))
+            {
+                assemblies.add(objectAssemblies.get(objectType));
+            }
+            else
+            {
+                ObjectAssemblyImpl objectAssembly = new ObjectAssemblyImpl(objectType);
+                objectAssemblies.put(objectType, objectAssembly);
+                assemblies.add(objectAssembly);
+            }
+        }
+
+        return new ObjectDeclarationImpl(assemblies);
+    }
+
+    @Override
+    public ObjectDeclaration objects(Predicate<? super ObjectAssembly> specification)
+    {
+        List<ObjectAssemblyImpl> assemblies = objectAssemblies.values().stream()
+                .filter(specification::test)
+                .collect(toList());
+
+        return new ObjectDeclarationImpl(assemblies);
+    }
+
+    @Override
+    public ServiceDeclaration addServices(Class<?>... serviceTypes)
+    {
+        List<ServiceAssemblyImpl> assemblies = new ArrayList<>();
+
+        for (Class<?> serviceType : serviceTypes)
+        {
+            ServiceAssemblyImpl serviceAssembly = new ServiceAssemblyImpl(serviceType);
+            serviceAssemblies.add(serviceAssembly);
+            assemblies.add(serviceAssembly);
+        }
+
+        return new ServiceDeclarationImpl(assemblies);
+    }
+
+    @Override
+    public ServiceDeclaration services(Class<?>... serviceTypes)
+    {
+        List<ServiceAssemblyImpl> assemblies = new ArrayList<>();
+
+        for (Class<?> serviceType : serviceTypes)
+        {
+            if( serviceAssemblies.stream().anyMatch( AssemblySpecifications.ofAnyType( serviceType ) ) )
+            {
+                serviceAssemblies.stream().filter( AssemblySpecifications.ofAnyType( serviceType ) )
+                                 .forEach( assemblies::add );
+            }
+            else
+            {
+                ServiceAssemblyImpl serviceAssembly = new ServiceAssemblyImpl(serviceType);
+                serviceAssemblies.add(serviceAssembly);
+                assemblies.add(serviceAssembly);
+            }
+        }
+
+        return new ServiceDeclarationImpl(assemblies);
+    }
+
+    @Override
+    public ServiceDeclaration services(Predicate<? super ServiceAssembly> specification)
+    {
+        List<ServiceAssemblyImpl> assemblies = serviceAssemblies.stream()
+                .filter(specification::test)
+                .collect(toList());
+        return new ServiceDeclarationImpl(assemblies);
+    }
+
+    @Override
+    public ImportedServiceDeclaration importedServices(Class<?>... serviceTypes)
+    {
+        List<ImportedServiceAssemblyImpl> assemblies = new ArrayList<>();
+
+        for (Class<?> serviceType : serviceTypes)
+        {
+            if (importedServiceAssemblies.containsKey(serviceType))
+            {
+                assemblies.add(importedServiceAssemblies.get(serviceType));
+            }
+            else
+            {
+                ImportedServiceAssemblyImpl serviceAssembly = new ImportedServiceAssemblyImpl(serviceType, this);
+                importedServiceAssemblies.put(serviceType, serviceAssembly);
+                assemblies.add(serviceAssembly);
+            }
+        }
+
+        return new ImportedServiceDeclarationImpl(assemblies);
+    }
+
+    @Override
+    public ImportedServiceDeclaration importedServices(Predicate<? super ImportedServiceAssembly> specification)
+    {
+        List<ImportedServiceAssemblyImpl> assemblies = importedServiceAssemblies.values().stream()
+                .filter(specification::test)
+                .collect(toList());
+
+        return new ImportedServiceDeclarationImpl(assemblies);
+    }
+
+    @Override
+    public <T> MixinDeclaration<T> forMixin(Class<T> mixinType)
+    {
+        return metaInfoDeclaration.on(mixinType);
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> void visit(AssemblyVisitor<ThrowableType> visitor)
+            throws ThrowableType
+    {
+        visitor.visitModule( this );
+
+        for( TransientAssemblyImpl compositeDeclaration : transientAssemblies.values() )
+        {
+            visitor.visitComposite( new TransientDeclarationImpl( singleton( compositeDeclaration ) ) );
+        }
+
+        for( EntityAssemblyImpl entityDeclaration : entityAssemblies.values() )
+        {
+            visitor.visitEntity( new EntityDeclarationImpl( singleton( entityDeclaration ) ) );
+        }
+
+        for( ObjectAssemblyImpl objectDeclaration : objectAssemblies.values() )
+        {
+            visitor.visitObject( new ObjectDeclarationImpl( singleton( objectDeclaration ) ) );
+        }
+
+        for( ServiceAssemblyImpl serviceDeclaration : serviceAssemblies )
+        {
+            visitor.visitService( new ServiceDeclarationImpl( singleton( serviceDeclaration ) ) );
+        }
+
+        for( ImportedServiceAssemblyImpl importedServiceDeclaration : importedServiceAssemblies.values() )
+        {
+            visitor.visitImportedService( new ImportedServiceDeclarationImpl( singleton( importedServiceDeclaration ) ) );
+        }
+
+        for( ValueAssemblyImpl valueDeclaration : valueAssemblies.values() )
+        {
+            visitor.visitValue( new ValueDeclarationImpl( singleton( valueDeclaration ) ) );
+        }
+    }
+
+    @SuppressWarnings("OptionalGetWithoutIsPresent")
+    ModuleModel assembleModule(LayerModel layerModel, AssemblyHelper helper)
+            throws AssemblyException
+    {
+        addDefaultAssemblers();
+        List<Throwable> exceptions = new ArrayList<>();
+        List<TransientModel> transientModels = new ArrayList<>();
+        List<ObjectModel> objectModels = new ArrayList<>();
+        List<ValueModel> valueModels = new ArrayList<>();
+        List<ServiceModel> serviceModels = new ArrayList<>();
+        List<ImportedServiceModel> importedServiceModels = new ArrayList<>();
+        List<EntityModel> entityModels = new ArrayList<>();
+        ModuleModel moduleModel = new ModuleModel(name,
+                metaInfo,
+                layerModel,
+                new ActivatorsModel<>(activators),
+                new TransientsModel(transientModels),
+                new EntitiesModel(entityModels),
+                new ObjectsModel(objectModels),
+                new ValuesModel(valueModels),
+                new ServicesModel(serviceModels),
+                new ImportedServicesModel(importedServiceModels));
+
+        if (name == null)
+        {
+            throw new AssemblyException("Module must have name set");
+        }
+
+        transientModels.addAll(transientAssemblies.values().stream()
+                .map( composite ->
+                      {
+                          try
+                          {
+                              return composite.newTransientModel( moduleModel, metaInfoDeclaration, helper );
+                          }
+                          catch( Exception e )
+                          {
+                              exceptions.add( e );
+                              return null;
+                          }
+                      } )
+                .filter( Objects::nonNull )
+                .collect(toList()));
+
+        valueModels.addAll(valueAssemblies.values().stream()
+                .map( value ->
+                      {
+                          try
+                          {
+                              return value.newValueModel( moduleModel, metaInfoDeclaration, helper );
+                          }
+                          catch( Exception e )
+                          {
+                              exceptions.add( e );
+                              return null;
+                          }
+                      } )
+                .filter( Objects::nonNull )
+                .collect(toList()));
+
+        entityModels.addAll(entityAssemblies.values().stream()
+                .map( entityDeclaration ->
+                      {
+                          try
+                          {
+                              return entityDeclaration.newEntityModel( moduleModel,
+                                                                       metaInfoDeclaration,
+                                                                       metaInfoDeclaration,
+                                                                       metaInfoDeclaration,
+                                                                       metaInfoDeclaration,
+                                                                       helper );
+                          }
+                          catch( Exception e )
+                          {
+                              exceptions.add( e );
+                              return null;
+                          }
+                      } )
+                .filter( Objects::nonNull )
+                .collect(Collectors.toList()));
+
+        for (ObjectAssemblyImpl objectDeclaration : objectAssemblies.values())
+        {
+            objectDeclaration.addObjectModel(moduleModel, objectModels);
+        }
+
+        serviceModels.addAll(
+            serviceAssemblies
+                .stream()
+                .map( serviceDeclaration ->
+                      {
+                          try
+                          {
+                              if( serviceDeclaration.identity == null )
+                              {
+                                  serviceDeclaration.identity = generateId( serviceDeclaration.types() );
+                              }
+                              return ( serviceDeclaration.newServiceModel( moduleModel, metaInfoDeclaration, helper ) );
+                          }
+                          catch( Exception e )
+                          {
+                              exceptions.add( e );
+                              return null;
+                          }
+                      } )
+                .filter( Objects::nonNull )
+                .collect( Collectors.toList() ) );
+
+        for (ImportedServiceAssemblyImpl importedServiceDeclaration : importedServiceAssemblies.values())
+        {
+            importedServiceDeclaration.addImportedServiceModel(moduleModel, importedServiceModels);
+        }
+
+        // Check for duplicate service identities
+        Set<String> identities = new HashSet<>();
+        for (ServiceModel serviceModel : serviceModels)
+        {
+            String identity = serviceModel.identity().toString();
+            if (identities.contains(identity))
+            {
+                DuplicateServiceIdentityException exception = new DuplicateServiceIdentityException(
+                    "Duplicated service reference: " + identity + " in module " + moduleModel.name()
+                );
+                exceptions.add( exception.fillInStackTrace() );
+            } else
+            {
+                identities.add( identity );
+            }
+        }
+        for (ImportedServiceModel serviceModel : importedServiceModels)
+        {
+            String identity = serviceModel.identity().toString();
+            if (identities.contains(identity))
+            {
+                DuplicateServiceIdentityException exception = new DuplicateServiceIdentityException(
+                        "Duplicated service reference: " + identity + " in module " + moduleModel.name()
+                );
+                exceptions.add( exception.fillInStackTrace() );
+            }
+            else
+            {
+                identities.add( identity );
+            }
+        }
+
+        importedServiceModels
+            .stream()
+            .filter(
+                importedServiceModel ->
+                    objectModels.stream().noneMatch( model -> model.types().findFirst().get()
+                                                                   .equals( importedServiceModel.serviceImporter() ) ) )
+            .forEach(
+                importedServiceModel ->
+                {
+                    try
+                    {
+                        objectModels.add( new ObjectModel( moduleModel, importedServiceModel.serviceImporter(),
+                                                           Visibility.module, new MetaInfo() ) );
+                    }
+                    catch( Exception e )
+                    {
+                        exceptions.add( e );
+                    }
+                } );
+        if( exceptions.size() == 0 )
+        {
+            return moduleModel;
+        }
+        throw new AssemblyReportException( exceptions );
+    }
+
+    private void addDefaultAssemblers()
+            throws AssemblyException
+    {
+        try
+        {
+            defaultAssemblers.entrySet().stream()
+                    .filter(entry -> serviceAssemblies.stream().noneMatch(serviceAssembly -> serviceAssembly.hasType(entry.getKey())))
+                    .forEach(entry ->
+                    {
+                        try
+                        {
+                            entry.getValue().assemble(this);
+                        }
+                        catch (AssemblyException e)
+                        {
+                            throw new UndeclaredThrowableException(e);
+                        }
+                    });
+        }
+        catch (UndeclaredThrowableException e)
+        {
+            throw (AssemblyException) e.getUndeclaredThrowable();
+        }
+    }
+
+    private Identity generateId(Stream<Class<?>> serviceTypes)
+    {
+        // Find service reference that is not yet used
+        Class<?> serviceType = serviceTypes.findFirst()
+                .orElse(null); // Use the first, which *SHOULD* be the main serviceType
+        int idx = 0;
+        Identity id = new StringIdentity(serviceType.getSimpleName());
+        boolean invalid;
+        do
+        {
+            invalid = false;
+            for (ServiceAssemblyImpl serviceAssembly : serviceAssemblies)
+            {
+                if (serviceAssembly.identity() != null && serviceAssembly.identity().equals(id))
+                {
+                    idx++;
+                    id = new StringIdentity(serviceType.getSimpleName() + "_" + idx);
+                    invalid = true;
+                    break;
+                }
+            }
+        }
+        while (invalid);
+        return id;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ObjectAssemblyImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ObjectAssemblyImpl.java
new file mode 100644
index 0000000..50a4256
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ObjectAssemblyImpl.java
@@ -0,0 +1,73 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import java.lang.reflect.Modifier;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.InvalidApplicationException;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.bootstrap.ObjectAssembly;
+import org.apache.polygene.runtime.object.ObjectModel;
+
+/**
+ * Assembly of an Object.
+ */
+public final class ObjectAssemblyImpl
+    implements ObjectAssembly
+{
+    private Class<?> objectType;
+    MetaInfo metaInfo = new MetaInfo();
+    Visibility visibility = Visibility.module;
+
+    public ObjectAssemblyImpl( Class<?> clazz )
+    {
+        // best try to find out if the class is a concrete class
+        if( clazz.isEnum() ||
+            ( !Composite.class.isAssignableFrom( clazz ) && Modifier.isAbstract( clazz.getModifiers() ) ) )
+        {
+            throw new IllegalArgumentException( "Declared objects must be concrete classes: " + clazz );
+        }
+        this.objectType = clazz;
+    }
+
+    @Override
+    public Stream<Class<?>> types()
+    {
+        return Stream.of( objectType );
+    }
+
+    void addObjectModel( ModuleDescriptor module, List<ObjectModel> objectModels )
+    {
+        try
+        {
+            ObjectModel objectModel = new ObjectModel( module, objectType, visibility, metaInfo );
+            objectModels.add( objectModel );
+        }
+        catch( Throwable e )
+        {
+            throw new InvalidApplicationException( "Could not register " + objectType.getName(), e );
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ObjectDeclarationImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ObjectDeclarationImpl.java
new file mode 100644
index 0000000..bba3faa
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ObjectDeclarationImpl.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.ObjectDeclaration;
+
+/**
+ * Declaration of an Object. Created by {@link org.apache.polygene.runtime.bootstrap.ModuleAssemblyImpl#objects(Class[])}.
+ */
+public final class ObjectDeclarationImpl
+    implements ObjectDeclaration
+{
+    private final Iterable<ObjectAssemblyImpl> assemblies;
+
+    public ObjectDeclarationImpl( Iterable<ObjectAssemblyImpl> assemblies )
+    {
+        this.assemblies = assemblies;
+    }
+
+    @Override
+    public ObjectDeclaration setMetaInfo( Object info )
+    {
+        for( ObjectAssemblyImpl assembly : assemblies )
+        {
+            assembly.metaInfo.set( info );
+        }
+        return this;
+    }
+
+    @Override
+    public ObjectDeclaration visibleIn( Visibility visibility )
+        throws IllegalStateException
+    {
+        for( ObjectAssemblyImpl assembly : assemblies )
+        {
+            assembly.visibility = visibility;
+        }
+        return this;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/OrAppliesToFilter.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/OrAppliesToFilter.java
new file mode 100644
index 0000000..77d9c39
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/OrAppliesToFilter.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesToFilter;
+
+/**
+ * JAVADOC
+ */
+final class OrAppliesToFilter
+    implements AppliesToFilter
+{
+    private final AppliesToFilter left;
+    private final AppliesToFilter right;
+
+    OrAppliesToFilter( AppliesToFilter left, AppliesToFilter right )
+    {
+        this.left = left;
+        this.right = right;
+    }
+
+    @Override
+    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
+    {
+        return left.appliesTo( method, mixin, compositeType, fragmentClass ) ||
+               right.appliesTo( method, mixin, compositeType, fragmentClass );
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ServiceAssemblyImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ServiceAssemblyImpl.java
new file mode 100644
index 0000000..dab0b31
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ServiceAssemblyImpl.java
@@ -0,0 +1,106 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.common.InvalidApplicationException;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.util.Annotations;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.bootstrap.ServiceAssembly;
+import org.apache.polygene.bootstrap.StateDeclarations;
+import org.apache.polygene.runtime.activation.ActivatorsModel;
+import org.apache.polygene.runtime.service.ServiceModel;
+import org.apache.polygene.runtime.structure.ModuleModel;
+
+/**
+ * Assembly of a Service.
+ */
+public final class ServiceAssemblyImpl extends CompositeAssemblyImpl
+    implements ServiceAssembly
+{
+    Identity identity;
+    boolean instantiateOnStartup = false;
+    List<Class<? extends Activator<?>>> activators = new ArrayList<>();
+
+    public ServiceAssemblyImpl( Class<?> serviceType )
+    {
+        super( serviceType );
+        // The composite must always implement ServiceComposite, as a marker interface
+        if( !ServiceComposite.class.isAssignableFrom( serviceType ) )
+        {
+            types.add( ServiceComposite.class );
+        }
+    }
+
+    @Override
+    public Identity identity()
+    {
+        return identity;
+    }
+
+    @SuppressWarnings( { "raw", "unchecked" } )
+    ServiceModel newServiceModel( ModuleModel module, StateDeclarations stateDeclarations, AssemblyHelper helper )
+    {
+        try
+        {
+            buildComposite( helper, stateDeclarations );
+            List<Class<? extends Activator<?>>> activatorClasses = Stream
+                .concat( activators.stream(), activatorsDeclarations( types ) )
+                .collect( Collectors.toList() );
+            return new ServiceModel( module, types, visibility, metaInfo,
+                                     new ActivatorsModel( activatorClasses ),
+                                     mixinsModel, stateModel, compositeMethodsModel,
+                                     identity, instantiateOnStartup );
+        }
+        catch( Exception e )
+        {
+            throw new InvalidApplicationException( "Could not register " + types, e );
+        }
+    }
+
+    private Stream<Class<? extends Activator<?>>> activatorsDeclarations( List<? extends Class<?>> types )
+    {
+        return types.stream()
+                    .flatMap( Classes::typesOf )
+                    //.filter( type -> Annotations.annotationOn( type, Activators.class ) == null )
+                    .flatMap( this::getAnnotations );
+    }
+
+    private Stream<? extends Class<? extends Activator<?>>> getAnnotations( Type type )
+    {
+        Activators activators = Annotations.annotationOn( type, Activators.class );
+        if( activators == null )
+        {
+            return Stream.empty();
+        }
+        return Arrays.stream( activators.value() );
+    }
+
+
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ServiceDeclarationImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ServiceDeclarationImpl.java
new file mode 100644
index 0000000..7740d37
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ServiceDeclarationImpl.java
@@ -0,0 +1,160 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.service.qualifier.ServiceTags;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+
+import static java.util.Arrays.asList;
+
+/**
+ * Declaration of a Service. Created by {@link org.apache.polygene.runtime.bootstrap.ModuleAssemblyImpl#services(Class[])}.
+ */
+public final class ServiceDeclarationImpl
+    implements ServiceDeclaration
+{
+    private final Iterable<ServiceAssemblyImpl> serviceAssemblies;
+
+    public ServiceDeclarationImpl( Iterable<ServiceAssemblyImpl> serviceAssemblies )
+    {
+        this.serviceAssemblies = serviceAssemblies;
+    }
+
+    @Override
+    public ServiceDeclaration visibleIn( Visibility visibility )
+    {
+        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
+        {
+            serviceAssembly.visibility = visibility;
+        }
+        return this;
+    }
+
+    @Override
+    public ServiceDeclaration identifiedBy( String identity )
+    {
+        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
+        {
+            if( identity != null ) {
+                serviceAssembly.identity = new StringIdentity( identity );
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public ServiceDeclaration taggedWith( String... tags )
+    {
+        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
+        {
+            ServiceTags previousTags = serviceAssembly.metaInfo.get( ServiceTags.class );
+            if( previousTags != null )
+            {
+                List<String> tagList = new ArrayList<>();
+                tagList.addAll( asList( previousTags.tags() ) );
+                tagList.addAll( asList( tags ) );
+                serviceAssembly.metaInfo.set( new ServiceTags( tagList.toArray( new String[ tagList.size() ] ) ) );
+            }
+            else
+            {
+                serviceAssembly.metaInfo.set( new ServiceTags( tags ) );
+            }
+        }
+
+        return this;
+    }
+
+    @Override
+    public ServiceDeclaration instantiateOnStartup()
+    {
+        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
+        {
+            serviceAssembly.instantiateOnStartup = true;
+        }
+        return this;
+    }
+
+    @Override
+    public ServiceDeclaration setMetaInfo( Object serviceAttribute )
+    {
+        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
+        {
+            serviceAssembly.metaInfo.set( serviceAttribute );
+        }
+        return this;
+    }
+
+    @Override
+    public ServiceDeclaration withConcerns( Class<?>... concerns )
+    {
+        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
+        {
+            serviceAssembly.concerns.addAll( asList( concerns ) );
+        }
+        return this;
+    }
+
+    @Override
+    public ServiceDeclaration withSideEffects( Class<?>... sideEffects )
+    {
+        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
+        {
+            serviceAssembly.sideEffects.addAll( asList( sideEffects ) );
+        }
+        return this;
+    }
+
+    @Override
+    public ServiceDeclaration withMixins( Class<?>... mixins )
+    {
+        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
+        {
+            serviceAssembly.mixins.addAll( asList( mixins ) );
+        }
+        return this;
+    }
+
+    @Override
+    public ServiceDeclaration withTypes( Class<?>... types )
+    {
+        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
+        {
+            serviceAssembly.types.addAll( asList( types ) );
+        }
+        return this;
+    }
+
+    @Override
+    @SafeVarargs
+    public final ServiceDeclaration withActivators( Class<? extends Activator<?>>... activators )
+    {
+        for ( ServiceAssemblyImpl serviceAssembly : serviceAssemblies ) {
+            serviceAssembly.activators.addAll( asList( activators ) );
+        }
+        return this;
+    }
+
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/TransientAssemblyImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/TransientAssemblyImpl.java
new file mode 100644
index 0000000..11c0230
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/TransientAssemblyImpl.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import org.apache.polygene.api.common.InvalidApplicationException;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.bootstrap.StateDeclarations;
+import org.apache.polygene.bootstrap.TransientAssembly;
+import org.apache.polygene.runtime.composite.TransientModel;
+
+/**
+ * Declaration of a TransientComposite.
+ */
+public final class TransientAssemblyImpl extends CompositeAssemblyImpl
+    implements TransientAssembly
+{
+    public TransientAssemblyImpl( Class<?> transientType )
+    {
+        super( transientType );
+
+        // The composite must always implement TransientComposite, as a marker interface
+        if( !TransientComposite.class.isAssignableFrom( transientType ) )
+        {
+            types.add( TransientComposite.class );
+        }
+
+        // If type is a class, register it as a mixin
+        if( !transientType.isInterface() )
+        {
+            mixins.add( transientType );
+        }
+    }
+
+    TransientModel newTransientModel( ModuleDescriptor module,
+                                      StateDeclarations stateDeclarations,
+                                      AssemblyHelper helper
+    )
+    {
+        try
+        {
+            buildComposite( helper, stateDeclarations );
+            return new TransientModel(
+                module, types, visibility, metaInfo, mixinsModel, stateModel, compositeMethodsModel );
+        }
+        catch( Exception e )
+        {
+            throw new InvalidApplicationException( "Could not register " + types, e );
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/TransientDeclarationImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/TransientDeclarationImpl.java
new file mode 100644
index 0000000..75a07b1
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/TransientDeclarationImpl.java
@@ -0,0 +1,100 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.TransientDeclaration;
+
+import static java.util.Arrays.asList;
+
+/**
+ * Declaration of a Composite. Created by {@link org.apache.polygene.bootstrap.ModuleAssembly#transients(Class[])}.
+ */
+public final class TransientDeclarationImpl
+    implements TransientDeclaration
+{
+    private final Iterable<TransientAssemblyImpl> assemblies;
+
+    public TransientDeclarationImpl( Iterable<TransientAssemblyImpl> assemblies )
+    {
+        this.assemblies = assemblies;
+    }
+
+    @Override
+    public TransientDeclaration setMetaInfo( Object info )
+    {
+        for( TransientAssemblyImpl assembly : assemblies )
+        {
+            assembly.metaInfo.set( info );
+        }
+        return this;
+    }
+
+    @Override
+    public TransientDeclaration visibleIn( Visibility visibility )
+    {
+        for( TransientAssemblyImpl assembly : assemblies )
+        {
+            assembly.visibility = visibility;
+        }
+        return this;
+    }
+
+    @Override
+    public TransientDeclaration withConcerns( Class<?>... concerns )
+    {
+        for( TransientAssemblyImpl assembly : assemblies )
+        {
+            assembly.concerns.addAll( asList( concerns ) );
+        }
+        return this;
+    }
+
+    @Override
+    public TransientDeclaration withSideEffects( Class<?>... sideEffects )
+    {
+        for( TransientAssemblyImpl assembly : assemblies )
+        {
+            assembly.sideEffects.addAll( asList( sideEffects ) );
+        }
+        return this;
+    }
+
+    @Override
+    public TransientDeclaration withMixins( Class<?>... mixins )
+    {
+        for( TransientAssemblyImpl assembly : assemblies )
+        {
+            assembly.mixins.addAll( asList( mixins ) );
+        }
+        return this;
+    }
+
+    @Override
+    public TransientDeclaration withTypes( Class<?>... types )
+    {
+        for( TransientAssemblyImpl assembly : assemblies )
+        {
+            assembly.types.addAll( asList( types ) );
+        }
+        return this;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/TypeCheckAppliesToFilter.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/TypeCheckAppliesToFilter.java
new file mode 100644
index 0000000..9fcac21
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/TypeCheckAppliesToFilter.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesToFilter;
+
+/**
+ * JAVADOC
+ */
+final class TypeCheckAppliesToFilter
+    implements AppliesToFilter
+{
+    @SuppressWarnings( "raw" )
+    private final Class type;
+
+    @SuppressWarnings( "raw" )
+    TypeCheckAppliesToFilter( Class type )
+    {
+        this.type = type;
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
+    {
+        return type.isAssignableFrom( compositeType );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/TypedFragmentAppliesToFilter.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/TypedFragmentAppliesToFilter.java
new file mode 100644
index 0000000..bd6c8f7
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/TypedFragmentAppliesToFilter.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesToFilter;
+
+/**
+ * JAVADOC
+ */
+final class TypedFragmentAppliesToFilter
+    implements AppliesToFilter
+{
+    @Override
+    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
+    {
+        return method.getDeclaringClass().isAssignableFrom( fragmentClass );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ValueAssemblyImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ValueAssemblyImpl.java
new file mode 100644
index 0000000..aa26857
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ValueAssemblyImpl.java
@@ -0,0 +1,88 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import org.apache.polygene.api.common.InvalidApplicationException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.StateDeclarations;
+import org.apache.polygene.bootstrap.ValueAssembly;
+import org.apache.polygene.runtime.association.AssociationsModel;
+import org.apache.polygene.runtime.association.ManyAssociationsModel;
+import org.apache.polygene.runtime.association.NamedAssociationsModel;
+import org.apache.polygene.runtime.composite.StateModel;
+import org.apache.polygene.runtime.value.ValueModel;
+import org.apache.polygene.runtime.value.ValueStateModel;
+
+/**
+ * Declaration of a ValueComposite.
+ */
+public final class ValueAssemblyImpl
+    extends CompositeAssemblyImpl
+    implements ValueAssembly
+{
+    private AssociationsModel associationsModel;
+    private ManyAssociationsModel manyAssociationsModel;
+    private NamedAssociationsModel namedAssociationsModel;
+
+    public ValueAssemblyImpl( Class<?> compositeType )
+    {
+        super( compositeType );
+        // The composite must always implement ValueComposite, as a marker interface
+        if( !ValueComposite.class.isAssignableFrom( compositeType ) )
+        {
+            types.add( ValueComposite.class );
+        }
+    }
+
+    @Override
+    protected StateModel createStateModel()
+    {
+        return new ValueStateModel( propertiesModel, associationsModel, manyAssociationsModel, namedAssociationsModel );
+    }
+
+    ValueModel newValueModel( ModuleDescriptor module,
+                              StateDeclarations stateDeclarations,
+                              AssemblyHelper helper
+    )
+    {
+        associationsModel = new AssociationsModel();
+        manyAssociationsModel = new ManyAssociationsModel();
+        namedAssociationsModel = new NamedAssociationsModel();
+        buildComposite( helper, stateDeclarations );
+        return new ValueModel(
+            module, types, visibility, metaInfo, mixinsModel, (ValueStateModel) stateModel, compositeMethodsModel );
+    }
+
+    protected AssociationsModel associationsModel()
+    {
+        return associationsModel;
+    }
+
+    protected ManyAssociationsModel manyAssociationsModel()
+    {
+        return manyAssociationsModel;
+    }
+
+    protected NamedAssociationsModel namedAssociationsModel()
+    {
+        return namedAssociationsModel;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ValueDeclarationImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ValueDeclarationImpl.java
new file mode 100644
index 0000000..0227a4c
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ValueDeclarationImpl.java
@@ -0,0 +1,100 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.ValueDeclaration;
+
+import static java.util.Arrays.asList;
+
+/**
+ * Declaration of a ValueComposite.
+ */
+public final class ValueDeclarationImpl
+    implements ValueDeclaration
+{
+    private final Iterable<ValueAssemblyImpl> assemblies;
+
+    public ValueDeclarationImpl( Iterable<ValueAssemblyImpl> assemblies )
+    {
+        this.assemblies = assemblies;
+    }
+
+    @Override
+    public ValueDeclaration setMetaInfo( Object info )
+    {
+        for( ValueAssemblyImpl assembly : assemblies )
+        {
+            assembly.metaInfo.set( info );
+        }
+        return this;
+    }
+
+    @Override
+    public ValueDeclaration visibleIn( Visibility visibility )
+    {
+        for( ValueAssemblyImpl assembly : assemblies )
+        {
+            assembly.visibility = visibility;
+        }
+        return this;
+    }
+
+    @Override
+    public ValueDeclaration withConcerns( Class<?>... concerns )
+    {
+        for( ValueAssemblyImpl assembly : assemblies )
+        {
+            assembly.concerns.addAll( asList( concerns ) );
+        }
+        return this;
+    }
+
+    @Override
+    public ValueDeclaration withSideEffects( Class<?>... sideEffects )
+    {
+        for( ValueAssemblyImpl assembly : assemblies )
+        {
+            assembly.sideEffects.addAll( asList( sideEffects ) );
+        }
+        return this;
+    }
+
+    @Override
+    public ValueDeclaration withMixins( Class<?>... mixins )
+    {
+        for( ValueAssemblyImpl assembly : assemblies )
+        {
+            assembly.mixins.addAll( asList( mixins ) );
+        }
+        return this;
+    }
+
+    @Override
+    public ValueDeclaration withTypes( Class<?>... types )
+    {
+        for( ValueAssemblyImpl assembly : assemblies )
+        {
+            assembly.types.addAll( asList( types ) );
+        }
+        return this;
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/AbstractConstraintModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/AbstractConstraintModel.java
new file mode 100644
index 0000000..0c058bd
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/AbstractConstraintModel.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import org.apache.polygene.api.constraint.ConstraintDescriptor;
+import org.apache.polygene.api.util.Visitable;
+import org.apache.polygene.api.util.Visitor;
+
+/**
+ * JAVADOC
+ */
+public abstract class AbstractConstraintModel
+    implements ConstraintDescriptor, Visitable<ConstraintDescriptor>
+{
+    protected final Annotation annotation;
+
+    public AbstractConstraintModel( Annotation annotation )
+    {
+        this.annotation = annotation;
+    }
+
+    @Override
+    public Annotation annotation()
+    {
+        return annotation;
+    }
+
+    public abstract ConstraintInstance<?, ?> newInstance();
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( Visitor<? super ConstraintDescriptor, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        return modelVisitor.visit( this );
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/AbstractModifierModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/AbstractModifierModel.java
new file mode 100644
index 0000000..4a00359
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/AbstractModifierModel.java
@@ -0,0 +1,184 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectedFieldsModel;
+import org.apache.polygene.runtime.injection.InjectedMethodsModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+
+import static org.apache.polygene.api.util.Classes.RAW_CLASS;
+import static org.apache.polygene.api.util.Classes.interfacesOf;
+
+/**
+ * JAVADOC
+ */
+public abstract class AbstractModifierModel
+    implements Dependencies, VisitableHierarchy<Object, Object>
+{
+    private final Class<?> modifierClass;
+
+    private final ConstructorsModel constructorsModel;
+    private final InjectedFieldsModel injectedFieldsModel;
+    private final InjectedMethodsModel injectedMethodsModel;
+
+    private final Class<Class<?>>[] nextInterfaces;
+
+    @SuppressWarnings( "unchecked" )
+    public AbstractModifierModel( Class<?> declaredModifierClass, Class<?> instantiationClass )
+    {
+        this.modifierClass = instantiationClass;
+        constructorsModel = new ConstructorsModel( modifierClass );
+        injectedFieldsModel = new InjectedFieldsModel( declaredModifierClass );
+        injectedMethodsModel = new InjectedMethodsModel( declaredModifierClass );
+        Class<Class<?>> componentType = (Class<Class<?>>) Class.class.cast( Class.class );
+        nextInterfaces = interfacesOf( declaredModifierClass )
+            .map( RAW_CLASS )
+            .distinct()
+            .toArray( size -> (Class<Class<?>>[]) Array.newInstance( componentType, size ) );
+    }
+
+    public Class<?> modifierClass()
+    {
+        return modifierClass;
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public Stream<DependencyModel> dependencies()
+    {
+        Stream<? extends Dependencies> models = Stream.of( this.constructorsModel, injectedFieldsModel, injectedMethodsModel );
+        return models.flatMap( Dependencies::dependencies );
+    }
+
+    public boolean isGeneric()
+    {
+        return InvocationHandler.class.isAssignableFrom( modifierClass );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            if( constructorsModel.accept( visitor ) )
+            {
+                if( injectedFieldsModel.accept( visitor ) )
+                {
+                    injectedMethodsModel.accept( visitor );
+                }
+            }
+        }
+
+        return visitor.visitLeave( this );
+    }
+
+    // Context
+    public InvocationHandler newInstance( ModuleDescriptor module,
+                                          InvocationHandler next,
+                                          ProxyReferenceInvocationHandler proxyHandler,
+                                          Method method
+    )
+    {
+        InjectionContext injectionContext = new InjectionContext( module, wrapNext( next ), proxyHandler );
+
+        Object modifier = constructorsModel.newInstance( injectionContext );
+
+        try
+        {
+            if( FragmentClassLoader.isGenerated( modifier ) )
+            {
+                modifier.getClass().getField( "_instance" ).set( modifier, proxyHandler );
+            }
+        }
+        catch( IllegalAccessException | NoSuchFieldException e )
+        {
+            e.printStackTrace();
+        }
+
+        injectedFieldsModel.inject( injectionContext, modifier );
+        injectedMethodsModel.inject( injectionContext, modifier );
+
+        if( isGeneric() )
+        {
+            return (InvocationHandler) modifier;
+        }
+        else
+        {
+            try
+            {
+                Method invocationMethod = modifierClass.getMethod( "_" + method.getName(), method.getParameterTypes() );
+                TypedModifierInvocationHandler handler = new TypedModifierInvocationHandler();
+                handler.setFragment( modifier );
+                handler.setMethod( invocationMethod );
+                return handler;
+            }
+            catch( NoSuchMethodException e )
+            {
+                throw new ConstructionException( "Could not find modifier method", e );
+            }
+        }
+    }
+
+    private Object wrapNext( InvocationHandler next )
+    {
+        if( isGeneric() )
+        {
+            return next;
+        }
+        else
+        {
+            return Proxy.newProxyInstance( modifierClass.getClassLoader(), nextInterfaces, next );
+        }
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+        AbstractModifierModel that = (AbstractModifierModel) o;
+        return modifierClass.equals( that.modifierClass );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return modifierClass.hashCode();
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/AtomicInstancePool.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/AtomicInstancePool.java
new file mode 100644
index 0000000..95cd988
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/AtomicInstancePool.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Method instance pool that keeps a linked list. Uses atomic reference
+ * to ensure that instances are acquired and returned in a thread-safe
+ * manner.
+ */
+public final class AtomicInstancePool
+    implements InstancePool<CompositeMethodInstance>
+{
+    private final AtomicReference<CompositeMethodInstance> first = new AtomicReference<>();
+
+    @Override
+    public CompositeMethodInstance obtainInstance()
+    {
+        CompositeMethodInstance firstInstance;
+        do
+        {
+            firstInstance = first.get();
+        }
+        while( firstInstance != null && !first.compareAndSet( firstInstance, firstInstance.getNext() ) );
+
+        return firstInstance;
+    }
+
+    @Override
+    public void releaseInstance( CompositeMethodInstance compositeMethodInstance )
+    {
+        CompositeMethodInstance firstInstance;
+        do
+        {
+            firstInstance = first.get();
+            compositeMethodInstance.setNext( firstInstance );
+        }
+        while( !first.compareAndSet( firstInstance, compositeMethodInstance ) );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompactLevel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompactLevel.java
new file mode 100644
index 0000000..5c44e98
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompactLevel.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.runtime.composite;
+
+/**
+ * Compaction Level of the StackTrace clenaup operation.
+ *
+ * <pre>
+ * <b>off</b>       = Do not modify the stack trace.
+ * <b>proxy</b>     = Remove all Polygene internal classes and all JDK internal classes from
+ *             the originating method call.
+ * <b>semi</b>      = Remove all JDK internal classes on the entire stack.
+ * <b>extensive</b> = Remove all Polygene internal and JDK internal classes from the entire stack.
+ * </pre>
+ *
+ * <p>
+ * The Compaction is set through the System Property "<code><b>polygene.compacttrace</b></code>" to
+ * any of the above values.
+ * </p>
+ */
+enum CompactLevel
+{
+    off, proxy, semi, extensive
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeConstraintModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeConstraintModel.java
new file mode 100644
index 0000000..5345594
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeConstraintModel.java
@@ -0,0 +1,74 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.constraint.Constraint;
+
+/**
+ * JAVADOC
+ */
+public final class CompositeConstraintModel
+    extends AbstractConstraintModel
+{
+    private final ValueConstraintsModel constraintsModel;
+
+    public CompositeConstraintModel( Annotation annotation, ValueConstraintsModel constraintsModel )
+    {
+        super( annotation );
+        this.constraintsModel = constraintsModel;
+    }
+
+    @Override
+    @SuppressWarnings( {"raw", "unchecked"} )
+    public ConstraintInstance<?, ?> newInstance()
+    {
+        try
+        {
+            ValueConstraintsInstance compositeConstraintsInstance = constraintsModel.newInstance();
+            Constraint<?, ?> constraint = new CompositeConstraintInstance( compositeConstraintsInstance );
+            return new ConstraintInstance( constraint, annotation );
+        }
+        catch( Exception e )
+        {
+            throw new ConstructionException( "Could not instantiate constraint implementation", e );
+        }
+    }
+
+    private static class CompositeConstraintInstance
+        implements Constraint<Annotation, Object>
+    {
+        private final ValueConstraintsInstance valueConstraintsInstance;
+
+        private CompositeConstraintInstance( ValueConstraintsInstance valueConstraintsInstance )
+        {
+            this.valueConstraintsInstance = valueConstraintsInstance;
+        }
+
+        @Override
+        public boolean isValid( Annotation annotation, Object value )
+            throws NullPointerException
+        {
+            return valueConstraintsInstance.checkConstraints( value ).isEmpty();
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodInstance.java
new file mode 100644
index 0000000..1867bf1
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodInstance.java
@@ -0,0 +1,83 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * JAVADOC
+ */
+public final class CompositeMethodInstance
+{
+    private final InvocationHandler invoker;
+    private final FragmentInvocationHandler mixinInvoker;
+    private final Method method;
+    private final int methodIdx;
+
+    private CompositeMethodInstance next;
+
+    public CompositeMethodInstance( InvocationHandler invoker,
+                                    FragmentInvocationHandler mixinInvoker,
+                                    Method method, int methodIdx
+    )
+    {
+        this.invoker = invoker;
+        this.method = method;
+        this.mixinInvoker = mixinInvoker;
+        this.methodIdx = methodIdx;
+    }
+
+    public Method method()
+    {
+        return method;
+    }
+
+    public Object getMixinFrom( Object[] mixins )
+    {
+        return mixins[ methodIdx ];
+    }
+
+    public Object invoke( Object composite, Object[] params, Object mixin )
+        throws Throwable
+    {
+        mixinInvoker.setFragment( mixin );
+
+        try
+        {
+            return invoker.invoke( composite, method, params );
+        }
+        finally
+        {
+            mixinInvoker.setFragment( null );
+        }
+    }
+
+    public CompositeMethodInstance getNext()
+    {
+        return next;
+    }
+
+    public void setNext( CompositeMethodInstance next )
+    {
+        this.next = next;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodModel.java
new file mode 100644
index 0000000..d290f97
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodModel.java
@@ -0,0 +1,315 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.composite.MethodDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+
+/**
+ * JAVADOC
+ */
+public final class CompositeMethodModel
+    implements MethodDescriptor, Dependencies, VisitableHierarchy<Object, Object>
+{
+    // Model
+    private final Method method;
+    private Method invocationMethod; // This will be the _ prefixed method on typed mixins
+    private final ConstraintsModel constraints;
+    private final ConcernsModel concerns;
+    private final SideEffectsModel sideEffects;
+    private final MixinsModel mixins;
+    private AnnotatedElement annotations;
+
+    // Context
+//    private final SynchronizedCompositeMethodInstancePool instancePool = new SynchronizedCompositeMethodInstancePool();
+    private final AtomicInstancePool instancePool = new AtomicInstancePool();
+    private final ConstraintsInstance constraintsInstance;
+
+    public CompositeMethodModel( Method method,
+                                 ConstraintsModel constraintsModel,
+                                 ConcernsModel concernsModel,
+                                 SideEffectsModel sideEffectsModel,
+                                 MixinsModel mixinsModel
+    )
+    {
+        this.method = method;
+        mixins = mixinsModel;
+        concerns = concernsModel;
+        sideEffects = sideEffectsModel;
+        constraints = constraintsModel;
+        constraintsInstance = constraints.newInstance();
+        annotations = new CompositeMethodAnnotatedElement();
+//        instancePool = new SynchronizedCompositeMethodInstancePool();
+    }
+
+    // Model
+
+    @Override
+    public Method method()
+    {
+        return method;
+    }
+
+    public MixinModel mixin()
+    {
+        return mixins.mixinFor( method );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public Stream<DependencyModel> dependencies()
+    {
+        Stream<? extends Dependencies> concerns = Stream.of( this.concerns, sideEffects );
+        Stream<? extends Dependencies> filteredNonNull = concerns.filter( Objects::nonNull );
+        return filteredNonNull.flatMap( Dependencies::dependencies );
+    }
+
+    // Context
+    public Object invoke( Object composite, Object[] params, MixinsInstance mixins, ModuleDescriptor module )
+        throws Throwable
+    {
+        constraintsInstance.checkValid( composite, method, params );
+
+        CompositeMethodInstance methodInstance = getInstance( module );
+        try
+        {
+            return mixins.invoke( composite, params, methodInstance );
+        }
+        finally
+        {
+            instancePool.releaseInstance( methodInstance );
+        }
+    }
+
+    private CompositeMethodInstance getInstance( ModuleDescriptor module )
+    {
+        CompositeMethodInstance methodInstance = instancePool.obtainInstance();
+        if( methodInstance == null )
+        {
+            methodInstance = newCompositeMethodInstance( module );
+        }
+
+        return methodInstance;
+    }
+
+    private CompositeMethodInstance newCompositeMethodInstance( ModuleDescriptor module )
+        throws ConstructionException
+    {
+        FragmentInvocationHandler mixinInvocationHandler = mixins.newInvocationHandler( method );
+        InvocationHandler invoker = mixinInvocationHandler;
+        if( concerns != ConcernsModel.EMPTY_CONCERNS )
+        {
+            ConcernsInstance concernsInstance = concerns.newInstance( method, module, mixinInvocationHandler );
+            invoker = concernsInstance;
+        }
+        if( sideEffects != SideEffectsModel.EMPTY_SIDEEFFECTS )
+        {
+            SideEffectsInstance sideEffectsInstance = sideEffects.newInstance( method, module, invoker );
+            invoker = sideEffectsInstance;
+        }
+
+        if( invocationMethod == null )
+        {
+            MixinModel model = mixins.mixinFor( method );
+            if( !InvocationHandler.class.isAssignableFrom( model.mixinClass() ) )
+            {
+                try
+                {
+                    invocationMethod = model.instantiationClass()
+                        .getMethod( "_" + method.getName(), method.getParameterTypes() );
+                }
+                catch( NoSuchMethodException e )
+                {
+                    invocationMethod = method;
+//                    throw new ConstructionException( "Could not find the subclass method", e );
+                }
+            }
+            else
+            {
+                invocationMethod = method;
+            }
+        }
+
+        mixinInvocationHandler.setMethod( invocationMethod );
+
+        return new CompositeMethodInstance( invoker, mixinInvocationHandler, method, mixins.methodIndex.get( method ) );
+    }
+
+    public AnnotatedElement annotatedElement()
+    {
+        return annotations;
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            constraints.accept( modelVisitor );
+            concerns.accept( modelVisitor );
+            sideEffects.accept( modelVisitor );
+        }
+        return modelVisitor.visitLeave( this );
+    }
+
+    @Override
+    public String toString()
+    {
+        return method.toGenericString();
+    }
+
+    public Iterable<Method> invocationsFor( Class<?> mixinClass )
+    {
+        return mixins.invocationsFor( mixinClass ).collect( Collectors.toList() );
+    }
+
+    public class CompositeMethodAnnotatedElement
+        implements AnnotatedElement
+    {
+        @Override
+        public boolean isAnnotationPresent( Class<? extends Annotation> annotationClass )
+        {
+            // Check method
+            if( method.isAnnotationPresent( annotationClass ) )
+            {
+                return true;
+            }
+
+            // Check mixin
+            try
+            {
+                MixinModel model = mixins.mixinFor( method );
+                return !GenericPredicate.INSTANCE.test( model.mixinClass() )
+                       && ( model.mixinClass().getMethod( method.getName(), method.getParameterTypes() )
+                                 .isAnnotationPresent( annotationClass ) );
+            }
+            catch( NoSuchMethodException e )
+            {
+                return false;
+            }
+        }
+
+        @Override
+        public <T extends Annotation> T getAnnotation( Class<T> annotationClass )
+        {
+            // Check mixin
+            try
+            {
+                MixinModel model = mixins.mixinFor( method );
+                if( !GenericPredicate.INSTANCE.test( model.mixinClass() ) )
+                {
+                    T annotation = annotationClass.cast( model.mixinClass()
+                                                             .getMethod( method.getName(), method.getParameterTypes() )
+                                                             .getAnnotation( annotationClass ) );
+                    if( annotation != null )
+                    {
+                        return annotation;
+                    }
+                }
+            }
+            catch( NoSuchMethodException e )
+            {
+                // Ignore
+            }
+
+            // Check method
+            return method.getAnnotation( annotationClass );
+        }
+
+        @Override
+        public Annotation[] getAnnotations()
+        {
+            // Add mixin annotations
+            List<Annotation> annotations = new ArrayList<>();
+            MixinModel model = mixins.mixinFor( method );
+            Annotation[] mixinAnnotations = new Annotation[ 0 ];
+            if( !GenericPredicate.INSTANCE.test( model.mixinClass() ) )
+            {
+                mixinAnnotations = model.mixinClass().getAnnotations();
+                annotations.addAll( Arrays.asList( mixinAnnotations ) );
+            }
+
+            // Add method annotations, but don't include duplicates
+            Annotation[] methodAnnotations = method.getAnnotations();
+            next:
+            for( Annotation methodAnnotation : methodAnnotations )
+            {
+                for( int i = 0; i < mixinAnnotations.length; i++ )
+                {
+                    if( annotations.get( i ).annotationType().equals( methodAnnotation.annotationType() ) )
+                    {
+                        continue next;
+                    }
+                }
+
+                annotations.add( methodAnnotation );
+            }
+
+            return annotations.toArray( new Annotation[ annotations.size() ] );
+        }
+
+        @Override
+        public Annotation[] getDeclaredAnnotations()
+        {
+            return new Annotation[ 0 ];
+        }
+
+        // @Override (Since JDK 8)
+        @SuppressWarnings( "unchecked" )
+        public <T extends Annotation> T[] getAnnotationsByType( Class<T> annotationClass )
+        {
+            Objects.requireNonNull( annotationClass, "annotationClass" );
+            return (T[]) Array.newInstance( annotationClass, 0 );
+        }
+
+        // @Override (Since JDK 8)
+        public <T extends Annotation> T getDeclaredAnnotation( Class<T> annotationClass )
+        {
+            Objects.requireNonNull( annotationClass, "annotationClass" );
+            return null;
+        }
+
+        // @Override (Since JDK 8)
+        @SuppressWarnings( "unchecked" )
+        public <T extends Annotation> T[] getDeclaredAnnotationsByType( Class<T> annotationClass )
+        {
+            Objects.requireNonNull( annotationClass, "annotationClass" );
+            return (T[]) Array.newInstance( annotationClass, 0 );
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodsModel.java
new file mode 100644
index 0000000..2223091
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeMethodsModel.java
@@ -0,0 +1,161 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.MissingMethodException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+
+/**
+ * Model for Composite methods. This includes both private and public methods.
+ */
+public final class CompositeMethodsModel
+    implements VisitableHierarchy<Object, Object>, Dependencies
+{
+    private final LinkedHashMap<Method, CompositeMethodModel> methods;
+    private final MixinsModel mixinsModel;
+
+    public CompositeMethodsModel( MixinsModel mixinsModel )
+    {
+        methods = new LinkedHashMap<>();
+        this.mixinsModel = mixinsModel;
+    }
+
+    public Stream<DependencyModel> dependencies()
+    {
+        Collection<CompositeMethodModel> compositeMethods = methods.values();
+        return compositeMethods.stream().flatMap( Dependencies.DEPENDENCIES_FUNCTION );
+    }
+
+    // Context
+    public Object invoke( MixinsInstance mixins,
+                          Object proxy,
+                          Method method,
+                          Object[] args,
+                          ModuleDescriptor moduleInstance
+                        )
+        throws Throwable
+    {
+        CompositeMethodModel compositeMethod = methods.get( method );
+
+        if( compositeMethod == null )
+        {
+            Class<?> declaringClass = method.getDeclaringClass();
+            if( declaringClass.equals( Object.class ) )
+            {
+                return mixins.invokeObject( proxy, args, method );
+            }
+
+            // TODO: Figure out what was the intention of this code block, added by Rickard in 2009. It doesn't do anything useful.
+            // Update (niclas): My guess is that this is preparation for mixins in Objects.
+            if( !declaringClass.isInterface() )
+            {
+                compositeMethod = mixinsModel.mixinTypes().map( aClass ->
+                                                                {
+                                                                    try
+                                                                    {
+                                                                        Method realMethod = aClass.getMethod( method.getName(), method.getParameterTypes() );
+                                                                        return methods.get( realMethod );
+                                                                    }
+                                                                    catch( NoSuchMethodException | SecurityException e )
+                                                                    {
+
+                                                                    }
+                                                                    return null;
+                                                                } ).filter( Objects::nonNull ).findFirst().orElse( null );
+                return compositeMethod.invoke( proxy, args, mixins, moduleInstance );
+            }
+            if( method.isDefault() )
+            {
+                if( proxy instanceof Composite )
+                {
+                    throw new InternalError( "This shouldn't happen!" );
+                }
+                // Does this next line actually make any sense? Can we have a default method on an interface where the instance is not a Composite? Maybe... Let's try to trap a usecase by disallowing it.
+//                return method.invoke( proxy, args );
+                String message = "We have detected a default method on an interface that is not backed by a Composite. "
+                                 + "Please report this to dev@polygene.apache.org together with the information below, "
+                                 + "that/those class(es) and the relevant assembly information. Thank you\nMethod:"
+                                 + method.toGenericString()
+                                 + "\nDeclaring Class:"
+                                 + method.getDeclaringClass().toGenericString()
+                                 + "\nTypes:"
+                                 + mixinsModel.mixinTypes()
+                                              .map( Class::toGenericString )
+                                              .collect( Collectors.joining( "\n" ) );
+                throw new UnsupportedOperationException( message );
+            }
+            throw new MissingMethodException( "Method '" + method + "' is not implemented" );
+        }
+        else
+        {
+            return compositeMethod.invoke( proxy, args, mixins, moduleInstance );
+        }
+    }
+
+    public void addMethod( CompositeMethodModel methodModel )
+    {
+        methods.put( methodModel.method(), methodModel );
+    }
+
+    public boolean isImplemented( Method method )
+    {
+        return methods.containsKey( method );
+    }
+
+    public Iterable<Method> methods()
+    {
+        return methods.keySet();
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            for( CompositeMethodModel compositeMethodModel : methods.values() )
+            {
+                if( !compositeMethodModel.accept( modelVisitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return modelVisitor.visitLeave( this );
+    }
+
+    @Override
+    public String toString()
+    {
+        return methods().toString();
+    }
+
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeModel.java
new file mode 100644
index 0000000..be159bc
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/CompositeModel.java
@@ -0,0 +1,291 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.AccessibleObjects;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+
+import static java.lang.reflect.Proxy.newProxyInstance;
+import static org.apache.polygene.api.composite.InvalidCompositeException.handleInvalidCompositeType;
+
+/**
+ * JAVADOC
+ */
+public abstract class CompositeModel
+    implements VisitableHierarchy<Object, Object>, Dependencies, CompositeDescriptor
+{
+    protected final ModuleDescriptor module;
+    protected final MixinsModel mixinsModel;
+    protected final CompositeMethodsModel compositeMethodsModel;
+    protected final StateModel stateModel;
+
+    private final Class<?> primaryType;
+    private final Set<Class<?>> types;
+    private final Visibility visibility;
+    private final MetaInfo metaInfo;
+
+    private Class<? extends Composite> proxyClass;
+    private Constructor<? extends Composite> proxyConstructor;
+
+    protected CompositeModel( final ModuleDescriptor module,
+                              final List<Class<?>> types,
+                              final Visibility visibility,
+                              final MetaInfo metaInfo,
+                              final MixinsModel mixinsModel,
+                              final StateModel stateModel,
+                              final CompositeMethodsModel compositeMethodsModel
+    )
+    {
+        this.module = module;
+        this.types = new LinkedHashSet<>( types );
+        this.visibility = visibility;
+        this.metaInfo = metaInfo;
+        this.stateModel = stateModel;
+        this.compositeMethodsModel = compositeMethodsModel;
+        this.mixinsModel = mixinsModel;
+
+        // Create proxy class
+        @SuppressWarnings( "OptionalGetWithoutIsPresent" )
+        Class<?> mainType = types.stream().findFirst().get();
+        try
+        {
+            proxyClass = createProxyClass( mainType );
+            proxyConstructor = createProxyConstructor( mainType );
+        }
+        catch( ClassNotFoundException | NoSuchMethodException e )
+        {
+            handleInvalidCompositeType( e.getMessage(), module, mainType, null, null, null, types );
+        }
+        primaryType = mixinTypes()
+            .reduce( null, ( primary, type ) ->
+            {
+                if( primary == null )
+                {
+                    return type;
+                }
+                else if( primary.isAssignableFrom( type ) )
+                {
+                    return type;
+                }
+                return primary;
+            } );
+    }
+
+    // Model
+    @Override
+    public Stream<Class<?>> types()
+    {
+        return types.stream();
+    }
+
+    public StateModel state()
+    {
+        return stateModel;
+    }
+
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return metaInfo.get( infoType );
+    }
+
+    @Override
+    public Visibility visibility()
+    {
+        return visibility;
+    }
+
+    @Override
+    public boolean isAssignableTo( Class<?> type )
+    {
+        for( Class<?> aClass : types )
+        {
+            if( type.isAssignableFrom( aClass ) )
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public MixinsModel mixinsModel()
+    {
+        return mixinsModel;
+    }
+
+    @Override
+    @SuppressWarnings( { "raw", "unchecked" } )
+    public Class<?> primaryType()
+    {
+        return primaryType;
+    }
+
+    @Override
+    public Stream<Class<?>> mixinTypes()
+    {
+        return mixinsModel.mixinTypes();
+    }
+
+    @Override
+    public Stream<DependencyModel> dependencies()
+    {
+        Stream<Dependencies> models = Stream.of( this.mixinsModel, compositeMethodsModel );
+        return models.flatMap( Dependencies::dependencies );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            if( compositeMethodsModel.accept( visitor ) )
+            {
+                if( stateModel.accept( visitor ) )
+                {
+                    mixinsModel.accept( visitor );
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    @SuppressWarnings( { "raw", "unchecked" } )
+    private Class<? extends Composite>  createProxyClass( Class<?> mainType )
+        throws ClassNotFoundException, NoSuchMethodException
+    {
+        Class<? extends Composite>  proxyClass;
+        if( mainType.isInterface() )
+        {
+            ClassLoader proxyClassloader = mainType.getClassLoader();
+
+            Class<?>[] interfaces = types.stream().map( Class.class::cast ).toArray( Class[]::new );
+            proxyClass = (Class<? extends Composite>) ProxyGenerator.createProxyClass( proxyClassloader, interfaces );
+        }
+        else
+        {
+            proxyClass = new TransientClassLoader( getClass().getClassLoader() ).loadFragmentClass( mainType );
+        }
+        return proxyClass;
+    }
+
+    @SuppressWarnings( { "raw", "unchecked" } )
+    private Constructor<? extends Composite> createProxyConstructor( Class<?> mainType )
+        throws ClassNotFoundException, NoSuchMethodException
+    {
+        Constructor<? extends Composite> constructor;
+        if( mainType.isInterface() )
+        {
+            constructor = proxyClass.getConstructor( InvocationHandler.class );
+        }
+        else
+        {
+            constructor = (Constructor<? extends Composite>) proxyClass.getConstructors()[ 0 ];
+        }
+        return AccessibleObjects.accessible( constructor );
+    }
+
+    // Context
+    public final Object invoke( MixinsInstance mixins,
+                                Object proxy,
+                                Method method,
+                                Object[] args
+    )
+        throws Throwable
+    {
+        return compositeMethodsModel.invoke( mixins, proxy, method, args, module );
+    }
+
+    @Override
+    public ModuleDescriptor module()
+    {
+        return module;
+    }
+
+    public Composite newProxy( InvocationHandler invocationHandler )
+        throws ConstructionException
+    {
+        Class<?> mainType = types.stream().findFirst().get();
+        if( mainType.isInterface() )
+        {
+            try
+            {
+                return Composite.class.cast( proxyConstructor.newInstance( invocationHandler ) );
+            }
+            catch( Exception e )
+            {
+                throw new ConstructionException( e );
+            }
+        }
+        else
+        {
+            try
+            {
+                Object[] args = new Object[ proxyConstructor.getParameterTypes().length ];
+                Composite composite = Composite.class.cast( proxyConstructor.newInstance( args ) );
+                proxyClass.getField( "_instance" ).set( composite, invocationHandler );
+                return composite;
+            }
+            catch( Exception e )
+            {
+                throw new ConstructionException( e );
+            }
+        }
+    }
+
+    @SuppressWarnings( "raw" )
+    public <T> T newProxy( InvocationHandler invocationHandler, Class<T> mixinType )
+        throws IllegalArgumentException
+    {
+
+//        if (!matchesAny( isAssignableFrom( mixinType ), types ))
+        if( !mixinsModel.isImplemented( mixinType ) )
+        {
+            String message = "Composite " + primaryType().getName() + " does not implement type " + mixinType.getName();
+            throw new IllegalArgumentException( message );
+        }
+
+        // Instantiate proxy for given mixin interface
+        return mixinType.cast( newProxyInstance( mixinType.getClassLoader(), new Class[]{ mixinType }, invocationHandler ) );
+    }
+
+    @Override
+    public String toString()
+    {
+        return types.toString();
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernModel.java
new file mode 100644
index 0000000..b583aaf
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernModel.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import org.apache.polygene.api.concern.ConcernDescriptor;
+
+/**
+ * JAVADOC
+ */
+public final class ConcernModel extends AbstractModifierModel
+    implements ConcernDescriptor
+{
+    public ConcernModel( Class concernClass, Class instantiationClass )
+    {
+        super( concernClass, instantiationClass );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsInstance.java
new file mode 100644
index 0000000..da2fe20
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsInstance.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * JAVADOC
+ */
+public final class ConcernsInstance
+    implements InvocationHandler
+{
+    private final InvocationHandler firstConcern;
+    private final FragmentInvocationHandler mixinInvocationHandler;
+    private final ProxyReferenceInvocationHandler proxyHandler;
+
+    public ConcernsInstance( InvocationHandler firstConcern,
+                             FragmentInvocationHandler mixinInvocationHandler,
+                             ProxyReferenceInvocationHandler proxyHandler
+    )
+    {
+        this.firstConcern = firstConcern;
+        this.mixinInvocationHandler = mixinInvocationHandler;
+        this.proxyHandler = proxyHandler;
+    }
+
+    public boolean isEmpty()
+    {
+        return firstConcern == mixinInvocationHandler;
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] params )
+        throws Throwable
+    {
+        proxyHandler.setProxy( proxy );
+        try
+        {
+            return firstConcern.invoke( proxy, method, params );
+        }
+        catch( InvocationTargetException e )
+        {
+            throw e.getTargetException();
+        }
+        finally
+        {
+            proxyHandler.clearProxy();
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsModel.java
new file mode 100644
index 0000000..5dde8ce
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConcernsModel.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.concern.ConcernsDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+
+/**
+ * JAVADOC
+ */
+public final class ConcernsModel
+    implements ConcernsDescriptor, Dependencies, VisitableHierarchy<Object, Object>
+{
+    public static final ConcernsModel EMPTY_CONCERNS = new ConcernsModel( Collections.emptyList() );
+
+    private List<ConcernModel> concernsFor;
+
+    public ConcernsModel( List<ConcernModel> concernsFor )
+    {
+        this.concernsFor = concernsFor;
+    }
+
+    @Override
+    public Stream<DependencyModel> dependencies()
+    {
+        return concernsFor.stream().flatMap( ConcernModel::dependencies );
+    }
+
+    // Context
+    public ConcernsInstance newInstance( Method method, ModuleDescriptor module,
+                                         FragmentInvocationHandler mixinInvocationHandler )
+    {
+        ProxyReferenceInvocationHandler proxyHandler = new ProxyReferenceInvocationHandler();
+        InvocationHandler nextConcern = mixinInvocationHandler;
+        for( int i = concernsFor.size() - 1; i >= 0; i-- )
+        {
+            ConcernModel concernModel = concernsFor.get( i );
+            nextConcern = concernModel.newInstance( module, nextConcern, proxyHandler, method );
+        }
+        return new ConcernsInstance( nextConcern, mixinInvocationHandler, proxyHandler );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            for( ConcernModel concernModel : concernsFor )
+            {
+                if( !concernModel.accept( modelVisitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return modelVisitor.visitLeave( this );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintDeclaration.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintDeclaration.java
new file mode 100644
index 0000000..9826681
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintDeclaration.java
@@ -0,0 +1,75 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.api.util.Classes;
+
+/**
+ * JAVADOC
+ */
+public final class ConstraintDeclaration
+{
+    private final Class<? extends Constraint<?, ?>> constraintClass;
+    @SuppressWarnings( "raw" )
+    private final Class constraintAnnotationType;
+    private final Type constraintValueType;
+
+    @SuppressWarnings( "unchecked" )
+    public ConstraintDeclaration( Class<? extends Constraint<?, ?>> constraintClass )
+    {
+        this.constraintClass = constraintClass;
+
+        constraintAnnotationType = (Class<? extends Annotation>) ( (ParameterizedType) constraintClass.getGenericInterfaces()[ 0 ] )
+            .getActualTypeArguments()[ 0 ];
+        constraintValueType = ( (ParameterizedType) constraintClass.getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[ 1 ];
+    }
+
+    public Class<? extends Constraint<?, ?>> constraintClass()
+    {
+        return constraintClass;
+    }
+
+    @SuppressWarnings( {"raw", "unchecked"} )
+    public boolean appliesTo( Class annotationType, Type valueType )
+    {
+        if( constraintValueType instanceof Class )
+        {
+            Class constraintValueClass = (Class) constraintValueType;
+            Class valueClass = Classes.RAW_CLASS.apply( valueType );
+            return constraintAnnotationType.equals( annotationType ) && constraintValueClass.isAssignableFrom( valueClass );
+        }
+        else if( constraintValueType instanceof ParameterizedType )
+        {
+            // TODO Handle nested generics
+            Class constraintValueClass = Classes.RAW_CLASS.apply( constraintValueType );
+            Class valueClass = Classes.RAW_CLASS.apply( valueType );
+            return constraintAnnotationType.equals( annotationType ) && constraintValueClass.isAssignableFrom( valueClass );
+        }
+        else
+        {
+            return false; // TODO Handles more cases. What are they?
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintInstance.java
new file mode 100644
index 0000000..40645f9
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintInstance.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import org.apache.polygene.api.constraint.Constraint;
+
+/**
+ * JAVADOC
+ */
+public final class ConstraintInstance<A extends Annotation, T>
+{
+    private final Constraint<A, T> constraint;
+    private final A annotation;
+
+    public ConstraintInstance( Constraint<A, T> constraint, A annotation )
+    {
+        this.constraint = constraint;
+        this.annotation = annotation;
+    }
+
+    public A annotation()
+    {
+        return annotation;
+    }
+
+    public boolean isValid( T value )
+    {
+        return constraint.isValid( annotation, value );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintModel.java
new file mode 100644
index 0000000..1452eeb
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintModel.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.constraint.Constraint;
+
+/**
+ * JAVADOC
+ */
+public final class ConstraintModel
+    extends AbstractConstraintModel
+{
+    private final Class<? extends Constraint<?, ?>> constraintClass;
+
+    public ConstraintModel( Annotation annotation, Class<? extends Constraint<?, ?>> constraintClass )
+    {
+        super( annotation );
+        this.constraintClass = constraintClass;
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public ConstraintInstance<?, ?> newInstance()
+    {
+        try
+        {
+            Constraint<?, ?> constraint = constraintClass.newInstance();
+            return new ConstraintInstance( constraint, annotation );
+        }
+        catch( Exception e )
+        {
+            throw new ConstructionException( "Could not instantiate constraint implementation", e );
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsCheck.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsCheck.java
new file mode 100644
index 0000000..ad24dbe
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsCheck.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+
+/**
+ * Call this to perform a value constraint check
+ */
+public interface ConstraintsCheck
+{
+    void checkConstraints( Object value )
+        throws ConstraintViolationException;
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsInstance.java
new file mode 100644
index 0000000..23e8f98
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsInstance.java
@@ -0,0 +1,84 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.constraint.ConstraintViolation;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+
+/**
+ * JAVADOC
+ */
+public final class ConstraintsInstance
+{
+    private final List<ValueConstraintsInstance> valueConstraintsInstances;
+
+    public ConstraintsInstance( List<ValueConstraintsInstance> parameterConstraints )
+    {
+        valueConstraintsInstances = parameterConstraints;
+    }
+
+    @SuppressWarnings( "unchecked" )
+    public void checkValid( Object instance, Method method, Object[] params )
+        throws ConstraintViolationException
+    {
+        if( valueConstraintsInstances.isEmpty() )
+        {
+            return; // No constraints to check
+        }
+
+        // Check constraints
+        List<ConstraintViolation> violations = null;
+        for( int i = 0; i < params.length; i++ )
+        {
+            Object param = params[ i ];
+            List<ConstraintViolation> paramViolations = valueConstraintsInstances.get( i ).checkConstraints( param );
+            if( !paramViolations.isEmpty() )
+            {
+                if( violations == null )
+                {
+                    violations = new ArrayList<>();
+                }
+                violations.addAll( paramViolations );
+            }
+        }
+
+        // Check if any constraint failed
+        if( violations != null )
+        {
+            if( instance instanceof Composite )
+            {
+                throw new ConstraintViolationException( (Composite) instance, method, violations );
+            }
+            if( instance instanceof CompositeInstance )
+            {
+                throw new ConstraintViolationException( ( (CompositeInstance) instance ).proxy(), method, violations );
+            }
+            Stream<Class<?>> types = Stream.of( instance.getClass() );
+            throw new ConstraintViolationException( instance.toString(), types, method, violations );
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsModel.java
new file mode 100644
index 0000000..d8eb4be
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstraintsModel.java
@@ -0,0 +1,82 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.polygene.api.constraint.ConstraintsDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * JAVADOC
+ */
+public final class ConstraintsModel
+    implements ConstraintsDescriptor, VisitableHierarchy<Object, Object>
+{
+    private List<ValueConstraintsModel> parameterConstraintModels;
+
+    private static ConstraintsInstance EMPTY_CONSTRAINTS = new ConstraintsInstance( Collections.emptyList() );
+
+    public ConstraintsModel( List<ValueConstraintsModel> parameterConstraintModels )
+    {
+        this.parameterConstraintModels = parameterConstraintModels;
+    }
+
+    public ConstraintsInstance newInstance()
+    {
+        if( parameterConstraintModels.isEmpty() )
+        {
+            return EMPTY_CONSTRAINTS;
+        }
+        else
+        {
+            List<ValueConstraintsInstance> parameterConstraintsInstances = new ArrayList<>( parameterConstraintModels
+                                                                                                .size() );
+            for( ValueConstraintsModel parameterConstraintModel : parameterConstraintModels )
+            {
+                parameterConstraintsInstances.add( parameterConstraintModel.newInstance() );
+            }
+            return new ConstraintsInstance( parameterConstraintsInstances );
+        }
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            if( parameterConstraintModels != null )
+            {
+                for( ValueConstraintsModel parameterConstraintModel : parameterConstraintModels )
+                {
+                    if( !parameterConstraintModel.accept( modelVisitor ) )
+                    {
+                        break;
+                    }
+                }
+            }
+        }
+        return modelVisitor.visitLeave( this );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorModel.java
new file mode 100644
index 0000000..427cff0
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorModel.java
@@ -0,0 +1,115 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.composite.ConstructorDescriptor;
+import org.apache.polygene.api.composite.InvalidCompositeException;
+import org.apache.polygene.api.util.AccessibleObjects;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectedParametersModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+
+/**
+ * JAVADOC
+ */
+public final class ConstructorModel
+    implements ConstructorDescriptor, VisitableHierarchy<Object, Object>
+{
+    private Constructor<?> constructor;
+
+    private InjectedParametersModel parameters;
+
+    public ConstructorModel( Constructor<?> constructor, InjectedParametersModel parameters )
+    {
+        this.constructor = AccessibleObjects.accessible( constructor );
+        this.parameters = parameters;
+    }
+
+    @Override
+    public Constructor<?> constructor()
+    {
+        return constructor;
+    }
+
+    public Stream<DependencyModel> dependencies()
+    {
+        return parameters.dependencies();
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            parameters.accept( modelVisitor );
+        }
+
+        return modelVisitor.visitLeave( this );
+    }
+
+    // Context
+
+    public Object newInstance( InjectionContext context )
+        throws ConstructionException
+    {
+        // Create parameters
+        Object[] parametersInstance = parameters.newParametersInstance( context );
+        // Invoke constructor
+        try
+        {
+            return constructor.newInstance( parametersInstance );
+        }
+        catch( InvocationTargetException e )
+        {
+            Throwable targetException = e.getTargetException();
+            if( targetException instanceof InvalidCompositeException )
+            {
+                throw (InvalidCompositeException) targetException;
+            }
+            throw new ConstructionException( createExceptionMessage( parametersInstance ), targetException );
+        }
+        catch( Throwable e )
+        {
+            throw new ConstructionException( createExceptionMessage( parametersInstance ), e );
+        }
+    }
+
+    private String createExceptionMessage( Object[] parametersInstance )
+    {
+        return "Could not instantiate \n    " + constructor.getDeclaringClass()
+               + "\nusing constructor:\n    " + constructor.toGenericString()
+               + "\nparameter types:\n    " + Arrays.toString( parametersInstance );
+    }
+
+    @Override
+    public String toString()
+    {
+        return constructor.toGenericString();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorsModel.java
new file mode 100644
index 0000000..9b9cf2b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ConstructorsModel.java
@@ -0,0 +1,291 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.injection.InjectionScope;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.HierarchicalVisitorAdapter;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectedParametersModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.ParameterizedTypeInstance;
+import org.apache.polygene.runtime.model.Binder;
+import org.apache.polygene.runtime.model.Resolution;
+
+import static org.apache.polygene.api.composite.InvalidCompositeException.handleInvalidCompositeType;
+import static org.apache.polygene.api.util.Annotations.typeHasAnnotation;
+
+/**
+ * JAVADOC
+ */
+public final class ConstructorsModel
+    implements Binder, Dependencies, VisitableHierarchy<Object, Object>
+{
+    @SuppressWarnings( "raw" )
+    private final Class<?> fragmentClass;
+    private final List<ConstructorModel> constructorModels;
+    private List<ConstructorModel> boundConstructors;
+
+    @SuppressWarnings( { "raw", "unchecked" } )
+    public ConstructorsModel( Class<?> fragmentClass )
+    {
+        this.fragmentClass = fragmentClass;
+        validate( fragmentClass );
+        constructorModels = new ArrayList<>();
+        Constructor<?>[] realConstructors = this.fragmentClass.getDeclaredConstructors();
+        Class<?> injectionClass = FragmentClassLoader.getSourceClass( fragmentClass );
+        for( Constructor<?> constructor : realConstructors )
+        {
+            try
+            {
+                Constructor<?> injectionConstructor = injectionClass.getDeclaredConstructor( constructor.getParameterTypes() );
+                ConstructorModel constructorModel = newConstructorModel( this.fragmentClass, constructor,
+                                                                         injectionConstructor );
+                if( constructorModel != null )
+                {
+                    constructorModels.add( constructorModel );
+                }
+            }
+            catch( NoSuchMethodException e )
+            {
+                // Ignore and continue
+                e.printStackTrace();
+            }
+        }
+    }
+
+    @SuppressWarnings( "raw" )
+    private void validate( Class<?> fragmentClass )
+    {
+        // Ensure that the fragment class is not an inner class, in which case we should give a reasonable exception
+        if( fragmentClass.getDeclaringClass() == null )
+        {
+            return;
+        }
+        if( Modifier.isStatic( fragmentClass.getModifiers() ) )
+        {
+            return;
+        }
+        handleInvalidCompositeType( "Inner classes can not be used. Use static nested classes instead.", null, null, fragmentClass, null, null, null );
+    }
+
+    @Override
+    public Stream<DependencyModel> dependencies()
+    {
+        if( boundConstructors == null )
+        {
+            return constructorModels.stream().flatMap( ConstructorModel::dependencies );
+        }
+        return boundConstructors.stream().flatMap( ConstructorModel::dependencies );
+    }
+
+    @SuppressWarnings( "raw" )
+    private ConstructorModel newConstructorModel( Class<?> fragmentClass,
+                                                  Constructor<?> realConstructor,
+                                                  Constructor<?> injectedConstructor
+    )
+    {
+        int idx = 0;
+        InjectedParametersModel parameters = new InjectedParametersModel();
+        Annotation[][] parameterAnnotations = injectedConstructor.getParameterAnnotations();
+        for( Type type : injectedConstructor.getGenericParameterTypes() )
+        {
+            Annotation injectionAnnotation = Stream.of( parameterAnnotations[ idx ] )
+                                                   .filter( typeHasAnnotation( InjectionScope.class ) )
+                                                   .findFirst().orElse( null );
+
+            if( injectionAnnotation == null )
+            {
+                if( fragmentClass.getSuperclass().isMemberClass() )
+                {
+                    injectionAnnotation = new Uses()
+                    {
+                        @Override
+                        public Class<? extends Annotation> annotationType()
+                        {
+                            return Uses.class;
+                        }
+                    };
+                }
+                else
+                {
+                    return null; // invalid constructor parameter
+                }
+            }
+
+            boolean optional = DependencyModel.isOptional( injectionAnnotation, parameterAnnotations[ idx ] );
+
+            Type genericType = type;
+            if( genericType instanceof ParameterizedType )
+            {
+                genericType = new ParameterizedTypeInstance( ( (ParameterizedType) genericType ).getActualTypeArguments(), ( (ParameterizedType) genericType )
+                    .getRawType(), ( (ParameterizedType) genericType ).getOwnerType() );
+
+                for( int i = 0; i < ( (ParameterizedType) genericType ).getActualTypeArguments().length; i++ )
+                {
+                    Type typeArg = ( (ParameterizedType) genericType ).getActualTypeArguments()[ i ];
+                    if( typeArg instanceof TypeVariable )
+                    {
+                        typeArg = Classes.resolveTypeVariable( (TypeVariable) typeArg, realConstructor.getDeclaringClass(), fragmentClass );
+                        ( (ParameterizedType) genericType ).getActualTypeArguments()[ i ] = typeArg;
+                    }
+                }
+            }
+
+            DependencyModel dependencyModel = new DependencyModel( injectionAnnotation, genericType, fragmentClass, optional,
+                                                                   parameterAnnotations[ idx ] );
+            parameters.addDependency( dependencyModel );
+            idx++;
+        }
+        return new ConstructorModel( realConstructor, parameters );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            if( boundConstructors != null )
+            {
+                for( ConstructorModel constructorModel : boundConstructors )
+                {
+                    if( !constructorModel.accept( visitor ) )
+                    {
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                for( ConstructorModel constructorModel : constructorModels )
+                {
+                    if( !constructorModel.accept( visitor ) )
+                    {
+                        break;
+                    }
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    // Binding
+    @Override
+    public void bind( final Resolution resolution )
+        throws BindingException
+    {
+        boundConstructors = new ArrayList<>();
+        for( ConstructorModel constructorModel : constructorModels )
+        {
+            try
+            {
+                constructorModel.accept( new HierarchicalVisitorAdapter<Object, Object, BindingException>()
+                {
+                    @Override
+                    public boolean visit( Object visitor )
+                        throws BindingException
+                    {
+                        if( visitor instanceof Binder )
+                        {
+                            ( (Binder) visitor ).bind( resolution );
+                        }
+                        return true;
+                    }
+                } );
+                boundConstructors.add( constructorModel );
+            }
+            catch( Exception e )
+            {
+                // Ignore
+                e.printStackTrace();
+            }
+        }
+
+        if( boundConstructors.isEmpty() )
+        {
+            StringBuilder messageBuilder = new StringBuilder( "Found no constructor that could be bound: " );
+            if( resolution.model() instanceof CompositeDescriptor )
+            {
+                messageBuilder.append( fragmentClass.getName() )
+                    .append( " in " )
+                    .append( resolution.model().toString() );
+            }
+            else
+            {
+                messageBuilder.append( resolution.model().toString() );
+            }
+
+            if( messageBuilder.indexOf( "$" ) >= 0 )
+            {
+                // This could be ok if instance is created manually
+                return;
+//                messageBuilder.append( "\nInner classes can not be used." );
+            }
+            String message = messageBuilder.toString();
+            throw new BindingException( message );
+        }
+
+        // Sort based on parameter count
+        boundConstructors.sort(
+            ( o1, o2 ) ->
+            {
+                Integer model2ParametersCount = o2.constructor().getParameterTypes().length;
+                int model1ParametersCount = o1.constructor().getParameterTypes().length;
+                return model2ParametersCount.compareTo( model1ParametersCount );
+            } );
+    }
+
+    public Object newInstance( InjectionContext injectionContext )
+    {
+        // Try all bound constructors, in order
+        ConstructionException exception = null;
+        for( ConstructorModel constructorModel : boundConstructors )
+        {
+            try
+            {
+                return constructorModel.newInstance( injectionContext );
+            }
+            catch( ConstructionException e )
+            {
+                exception = e;
+            }
+        }
+
+        throw exception;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FragmentClassLoader.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FragmentClassLoader.java
new file mode 100644
index 0000000..8849411
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FragmentClassLoader.java
@@ -0,0 +1,841 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.entity.Lifecycle;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.Methods;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+import static org.apache.polygene.api.util.Classes.interfacesOf;
+import static org.objectweb.asm.Opcodes.AASTORE;
+import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static org.objectweb.asm.Opcodes.ACC_STATIC;
+import static org.objectweb.asm.Opcodes.ACC_SUPER;
+import static org.objectweb.asm.Opcodes.ACONST_NULL;
+import static org.objectweb.asm.Opcodes.ALOAD;
+import static org.objectweb.asm.Opcodes.ANEWARRAY;
+import static org.objectweb.asm.Opcodes.ARETURN;
+import static org.objectweb.asm.Opcodes.ASTORE;
+import static org.objectweb.asm.Opcodes.ATHROW;
+import static org.objectweb.asm.Opcodes.BIPUSH;
+import static org.objectweb.asm.Opcodes.CHECKCAST;
+import static org.objectweb.asm.Opcodes.DLOAD;
+import static org.objectweb.asm.Opcodes.DRETURN;
+import static org.objectweb.asm.Opcodes.DUP;
+import static org.objectweb.asm.Opcodes.FLOAD;
+import static org.objectweb.asm.Opcodes.FRETURN;
+import static org.objectweb.asm.Opcodes.GETFIELD;
+import static org.objectweb.asm.Opcodes.GETSTATIC;
+import static org.objectweb.asm.Opcodes.GOTO;
+import static org.objectweb.asm.Opcodes.ICONST_0;
+import static org.objectweb.asm.Opcodes.ICONST_1;
+import static org.objectweb.asm.Opcodes.ICONST_2;
+import static org.objectweb.asm.Opcodes.ICONST_3;
+import static org.objectweb.asm.Opcodes.ICONST_4;
+import static org.objectweb.asm.Opcodes.ICONST_5;
+import static org.objectweb.asm.Opcodes.ILOAD;
+import static org.objectweb.asm.Opcodes.INVOKEINTERFACE;
+import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
+import static org.objectweb.asm.Opcodes.INVOKESTATIC;
+import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
+import static org.objectweb.asm.Opcodes.IRETURN;
+import static org.objectweb.asm.Opcodes.LLOAD;
+import static org.objectweb.asm.Opcodes.LRETURN;
+import static org.objectweb.asm.Opcodes.POP;
+import static org.objectweb.asm.Opcodes.PUTSTATIC;
+import static org.objectweb.asm.Opcodes.RETURN;
+import static org.objectweb.asm.Type.getInternalName;
+
+/**
+ * Generate subclasses of mixins/modifiers that implement all interfaces not in the class itself
+ * and which delegates those calls to a given composite invoker.
+ */
+@SuppressWarnings( "raw" )
+public class FragmentClassLoader
+    extends ClassLoader
+{
+    private static final int JDK_VERSION;
+    public static final String GENERATED_POSTFIX = "_Stub";
+
+    static
+    {
+        String jdkString = System.getProperty( "java.specification.version" );
+        switch( jdkString )
+        {
+            case "1.8":
+            default:
+                JDK_VERSION = Opcodes.V1_8;
+                break;
+        }
+    }
+
+    public FragmentClassLoader( ClassLoader parent )
+    {
+        super( parent );
+    }
+
+    @Override
+    protected Class findClass( String name )
+        throws ClassNotFoundException
+    {
+        if( name.endsWith( GENERATED_POSTFIX ) )
+        {
+            Class baseClass;
+            String baseName = name.substring( 0, name.length() - 5 );
+            try
+            {
+                baseClass = loadClass( baseName );
+            }
+            catch( ClassNotFoundException e )
+            {
+                // Try replacing the last _ with $
+                while( true )
+                {
+                    int idx = baseName.lastIndexOf( "_" );
+                    if( idx != -1 )
+                    {
+                        baseName = baseName.substring( 0, idx ) + "$" + baseName.substring( idx + 1 );
+                        try
+                        {
+                            baseClass = loadClass( baseName );
+                            break;
+                        }
+                        catch( ClassNotFoundException e1 )
+                        {
+                            // Try again
+                        }
+                    }
+                    else
+                    {
+                        throw e;
+                    }
+                }
+            }
+            //  To Allow JDK classes to be composed.
+            if( name.startsWith( "java." ) )
+            {
+                name = "polygene." + name;
+            }
+            byte[] b = generateClass( name, baseClass );
+            return defineClass( name, b, 0, b.length, baseClass.getProtectionDomain() );
+        }
+
+        // Try the classloader of this classloader -> get classes in Polygene such as CompositeInvoker
+        return getClass().getClassLoader().loadClass( name );
+    }
+
+    public byte[] generateClass( String name, Class baseClass )
+        throws ClassNotFoundException
+    {
+        String classSlash = name.replace( '.', '/' );
+        String baseClassSlash = getInternalName( baseClass );
+
+        ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_MAXS );
+
+        // Class definition start
+        cw.visit( JDK_VERSION, ACC_PUBLIC + ACC_SUPER, classSlash, null, baseClassSlash, null );
+
+        // Composite reference
+        {
+            cw.visitField( ACC_PUBLIC, "_instance", "Lorg/apache/polygene/api/composite/CompositeInvoker;", null, null )
+                .visitEnd();
+        }
+
+        // Static Method references
+        boolean hasProxyMethods = false;
+        {
+            int idx = 1;
+            for( Method method : baseClass.getMethods() )
+            {
+                if( isOverridden( method, baseClass ) )
+                {
+                    cw.visitField( ACC_PRIVATE + ACC_STATIC, "m" + idx++, "Ljava/lang/reflect/Method;", null, null )
+                        .visitEnd();
+                    hasProxyMethods = true;
+                }
+            }
+        }
+
+        // Constructors
+        for( Constructor constructor : baseClass.getDeclaredConstructors() )
+        {
+            if( Modifier.isPublic( constructor.getModifiers() ) || Modifier.isProtected( constructor.getModifiers() ) )
+            {
+                String desc = org.objectweb.asm.commons.Method.getMethod( constructor ).getDescriptor();
+                MethodVisitor mv = cw.visitMethod( ACC_PUBLIC, "<init>", desc, null, null );
+                mv.visitCode();
+                mv.visitVarInsn( ALOAD, 0 );
+
+                int idx = 1;
+                for( Class aClass : constructor.getParameterTypes() )
+                {
+                    final int opcode;
+                    if( aClass.equals( Integer.TYPE ) )
+                    {
+                        opcode = ILOAD;
+                    }
+                    else if( aClass.equals( Long.TYPE ) )
+                    {
+                        opcode = LLOAD;
+                    }
+                    else if( aClass.equals( Float.TYPE ) )
+                    {
+                        opcode = FLOAD;
+                    }
+                    else if( aClass.equals( Double.TYPE ) )
+                    {
+                        opcode = DLOAD;
+                    }
+                    else
+                    {
+                        opcode = ALOAD;
+                    }
+                    mv.visitVarInsn( opcode, idx++ );
+                }
+
+                mv.visitMethodInsn( INVOKESPECIAL, baseClassSlash, "<init>", desc, false );
+                mv.visitInsn( RETURN );
+                mv.visitMaxs( idx, idx );
+                mv.visitEnd();
+            }
+        }
+
+        // Overloaded and unimplemented methods
+        if( hasProxyMethods )
+        {
+            Method[] methods = baseClass.getMethods();
+            int idx = 0;
+            List<Label> exceptionLabels = new ArrayList<>();
+            for( Method method : methods )
+            {
+                if( isOverridden( method, baseClass ) )
+                {
+                    idx++;
+                    String methodName = method.getName();
+                    String desc = org.objectweb.asm.commons.Method.getMethod( method ).getDescriptor();
+
+                    String[] exceptions = null;
+                    {
+                        MethodVisitor mv = cw.visitMethod( ACC_PUBLIC, methodName, desc, null, null );
+                        if( isInternalPolygeneMethod( method, baseClass ) )
+                        {
+                            // generate a NoOp method...
+                            mv.visitInsn( RETURN );
+                        }
+                        else
+                        {
+                            Label endLabel = null; // Use this if return type is void
+                            if( method.getExceptionTypes().length > 0 )
+                            {
+                                exceptions = new String[ method.getExceptionTypes().length ];
+                                for( int i = 0; i < method.getExceptionTypes().length; i++ )
+                                {
+                                    Class<?> aClass = method.getExceptionTypes()[ i ];
+                                    exceptions[ i ] = getInternalName( aClass );
+                                }
+                            }
+                            mv.visitCode();
+                            Label l0 = new Label();
+                            Label l1 = new Label();
+
+                            exceptionLabels.clear();
+                            for( Class<?> declaredException : method.getExceptionTypes() )
+                            {
+                                Label ld = new Label();
+                                mv.visitTryCatchBlock( l0, l1, ld, getInternalName( declaredException ) );
+                                exceptionLabels.add( ld ); // Reuse this further down for the catch
+                            }
+
+                            Label lruntime = new Label();
+                            mv.visitTryCatchBlock( l0, l1, lruntime, "java/lang/RuntimeException" );
+                            Label lerror = new Label();
+                            mv.visitTryCatchBlock( l0, l1, lerror, "java/lang/Throwable" );
+
+                            mv.visitLabel( l0 );
+                            mv.visitVarInsn( ALOAD, 0 );
+                            mv.visitFieldInsn( GETFIELD, classSlash, "_instance",
+                                               "Lorg/apache/polygene/api/composite/CompositeInvoker;" );
+                            mv.visitFieldInsn( GETSTATIC, classSlash, "m" + idx, "Ljava/lang/reflect/Method;" );
+
+                            int paramCount = method.getParameterTypes().length;
+                            int stackIdx = 0;
+                            if( paramCount == 0 )
+                            {
+                                // Send in null as parameter
+                                mv.visitInsn( ACONST_NULL );
+                            }
+                            else
+                            {
+                                insn( mv, paramCount );
+                                mv.visitTypeInsn( ANEWARRAY, "java/lang/Object" );
+                                int pidx = 0;
+                                for( Class<?> aClass : method.getParameterTypes() )
+                                {
+                                    mv.visitInsn( DUP );
+                                    insn( mv, pidx++ );
+                                    stackIdx = wrapParameter( mv, aClass, stackIdx + 1 );
+                                    mv.visitInsn( AASTORE );
+                                }
+                            }
+
+                            // Call method
+                            mv.visitMethodInsn( INVOKEINTERFACE, "org/apache/polygene/api/composite/CompositeInvoker",
+                                                "invokeComposite",
+                                                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true );
+
+                            // Return value
+                            if( !method.getReturnType().equals( Void.TYPE ) )
+                            {
+                                unwrapResult( mv, method.getReturnType(), l1 );
+                            }
+                            else
+                            {
+                                mv.visitInsn( POP );
+                                mv.visitLabel( l1 );
+                                endLabel = new Label();
+                                mv.visitJumpInsn( GOTO, endLabel );
+                            }
+
+                            // Increase stack to beyond method args
+                            stackIdx++;
+
+                            // Declared exceptions
+                            int exceptionIdx = 0;
+                            for( Class<?> aClass : method.getExceptionTypes() )
+                            {
+                                mv.visitLabel( exceptionLabels.get( exceptionIdx++ ) );
+                                mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ getInternalName( aClass ) } );
+                                mv.visitVarInsn( ASTORE, stackIdx );
+                                mv.visitVarInsn( ALOAD, stackIdx );
+                                mv.visitInsn( ATHROW );
+                            }
+
+                            // RuntimeException and Error catch-all
+                            mv.visitLabel( lruntime );
+                            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/RuntimeException" } );
+                            mv.visitVarInsn( ASTORE, stackIdx );
+                            mv.visitVarInsn( ALOAD, stackIdx );
+                            mv.visitInsn( ATHROW );
+
+                            mv.visitLabel( lerror );
+                            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/Throwable" } );
+                            mv.visitVarInsn( ASTORE, stackIdx );
+                            mv.visitVarInsn( ALOAD, stackIdx );
+                            mv.visitTypeInsn( CHECKCAST, "java/lang/Error" );
+                            mv.visitInsn( ATHROW );
+
+                            // Return type = void
+                            if( endLabel != null )
+                            {
+                                mv.visitLabel( endLabel );
+                                mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
+                                mv.visitInsn( RETURN );
+                            }
+
+                            mv.visitMaxs( 0, 0 );
+                            mv.visitEnd();
+                        }
+                    }
+
+                    if( !Modifier.isAbstract( method.getModifiers() ) )
+                    {
+                        // Add method with _ as prefix
+                        MethodVisitor mv = cw.visitMethod( ACC_PUBLIC, "_" + method.getName(), desc, null, exceptions );
+                        mv.visitCode();
+                        mv.visitVarInsn( ALOAD, 0 );
+
+                        // Parameters
+                        int stackIdx = 1;
+                        for( Class<?> aClass : method.getParameterTypes() )
+                        {
+                            stackIdx = loadParameter( mv, aClass, stackIdx ) + 1;
+                        }
+
+                        // Call method
+                        mv.visitMethodInsn( INVOKESPECIAL, baseClassSlash, method.getName(), desc, false );
+
+                        // Return value
+                        if( !method.getReturnType().equals( Void.TYPE ) )
+                        {
+                            returnResult( mv, method.getReturnType() );
+                        }
+                        else
+                        {
+                            mv.visitInsn( RETURN );
+                        }
+
+                        mv.visitMaxs( 1, 1 );
+                        mv.visitEnd();
+                    }
+                }
+            }
+
+            // Class initializer
+            {
+                MethodVisitor mv = cw.visitMethod( ACC_STATIC, "<clinit>", "()V", null, null );
+                mv.visitCode();
+                Label l0 = new Label();
+                Label l1 = new Label();
+                Label l2 = new Label();
+                mv.visitTryCatchBlock( l0, l1, l2, "java/lang/NoSuchMethodException" );
+                mv.visitLabel( l0 );
+
+                // Lookup methods and store in static variables
+                int midx = 0;
+                for( Method method : methods )
+                {
+                    if( isOverridden( method, baseClass ) )
+                    {
+                        Class methodClass;
+                        if( Modifier.isAbstract( method.getModifiers() ) )
+                        {
+                            methodClass = method.getDeclaringClass();
+                        }
+                        else
+                        {
+                            try
+                            {
+                                methodClass = getInterfaceMethodDeclaration( method,
+                                                                             baseClass ); // Overridden method lookup
+                            }
+                            catch( NoSuchMethodException e )
+                            {
+                                throw new ClassNotFoundException( name, e );
+                            }
+                        }
+
+                        midx++;
+
+                        mv.visitLdcInsn( Type.getType( methodClass ) );
+                        mv.visitLdcInsn( method.getName() );
+                        insn( mv, method.getParameterTypes().length );
+                        mv.visitTypeInsn( ANEWARRAY, "java/lang/Class" );
+
+                        int pidx = 0;
+                        for( Class<?> aClass : method.getParameterTypes() )
+                        {
+                            mv.visitInsn( DUP );
+                            insn( mv, pidx++ );
+                            type( mv, aClass );
+                            mv.visitInsn( AASTORE );
+                        }
+
+                        mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getMethod",
+                                            "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false );
+                        mv.visitFieldInsn( PUTSTATIC, classSlash, "m" + midx, "Ljava/lang/reflect/Method;" );
+                    }
+                }
+
+                mv.visitLabel( l1 );
+                Label l3 = new Label();
+                mv.visitJumpInsn( GOTO, l3 );
+                mv.visitLabel( l2 );
+                mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/NoSuchMethodException" } );
+                mv.visitVarInsn( ASTORE, 0 );
+                mv.visitVarInsn( ALOAD, 0 );
+                mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/NoSuchMethodException", "printStackTrace", "()V", false );
+                mv.visitLabel( l3 );
+                mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
+                mv.visitInsn( RETURN );
+                mv.visitMaxs( 6, 1 );
+                mv.visitEnd();
+            }
+        }
+        cw.visitEnd();
+        return cw.toByteArray();
+    }
+
+    private static boolean isOverridden( Method method, Class baseClass )
+    {
+        if( Modifier.isAbstract( method.getModifiers() ) )
+        {
+            return true; // Implement all abstract methods
+        }
+
+        if( Modifier.isFinal( method.getModifiers() ) )
+        {
+            return false; // Cannot override final methods
+        }
+
+        if( isInterfaceMethod( method, baseClass ) )
+        {
+            // if() used for clarity.
+            //noinspection RedundantIfStatement
+            if( isInternalPolygeneMethod( method, baseClass ) )
+            {
+                return false; // Skip methods in Polygene-internal interfaces
+            }
+            else
+            {
+                return true;
+            }
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    private static boolean isInternalPolygeneMethod( Method method, Class baseClass )
+    {
+        return isDeclaredIn( method, Initializable.class, baseClass )
+               || isDeclaredIn( method, Lifecycle.class, baseClass );
+    }
+
+    private static boolean isDeclaredIn( Method method, Class<?> clazz, Class<?> baseClass )
+    {
+        return clazz.isAssignableFrom( baseClass ) && checkForMethod( method, clazz );
+    }
+
+    private static Class getInterfaceMethodDeclaration( Method method, Class clazz )
+        throws NoSuchMethodException
+    {
+        return interfacesOf( clazz )
+            .map( Classes.RAW_CLASS )
+            .filter( intface -> checkForMethod( method, intface ) )
+            .findFirst()
+            .orElseThrow( () -> new NoSuchMethodException( method.getName() ) );
+    }
+
+    private static boolean isInterfaceMethod( Method method, Class<?> baseClass )
+    {
+        return interfacesOf( baseClass )
+            .map( Classes.RAW_CLASS )
+            .filter( Methods.HAS_METHODS )
+            .anyMatch( intface -> checkForMethod( method, intface ));
+    }
+
+    private static boolean checkForMethod( Method method, Class<?> intface )
+    {
+        try
+        {
+            intface.getMethod( method.getName(), method.getParameterTypes() );
+            return true;
+        }
+        catch( NoSuchMethodException e )
+        {
+            return false;
+        }
+    }
+
+    private static void type( MethodVisitor mv, Class<?> aClass )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;" );
+        }
+        else
+        {
+            mv.visitLdcInsn( Type.getType( aClass ) );
+        }
+    }
+
+    private static int wrapParameter( MethodVisitor mv, Class<?> aClass, int idx )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitVarInsn( LLOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false );
+            idx++; // Extra jump
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitVarInsn( DLOAD, idx );
+            idx++; // Extra jump
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false );
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitVarInsn( FLOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false );
+        }
+        else
+        {
+            mv.visitVarInsn( ALOAD, idx );
+        }
+
+        return idx;
+    }
+
+    private static void unwrapResult( MethodVisitor mv, Class<?> aClass, Label label )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Integer" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Long" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false );
+            mv.visitLabel( label );
+            mv.visitInsn( LRETURN );
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Short" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Byte" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Double" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false );
+            mv.visitLabel( label );
+            mv.visitInsn( DRETURN );
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Float" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false );
+            mv.visitLabel( label );
+            mv.visitInsn( FRETURN );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Boolean" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Character" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else
+        {
+            mv.visitTypeInsn( CHECKCAST, getInternalName( aClass ) );
+            mv.visitLabel( label );
+            mv.visitInsn( ARETURN );
+        }
+    }
+
+    private static int loadParameter( MethodVisitor mv, Class<?> aClass, int idx )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitVarInsn( LLOAD, idx );
+            idx++; // Extra jump
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitVarInsn( DLOAD, idx );
+            idx++; // Extra jump
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitVarInsn( FLOAD, idx );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else
+        {
+            mv.visitVarInsn( ALOAD, idx );
+        }
+
+        return idx;
+    }
+
+    private static void returnResult( MethodVisitor mv, Class<?> aClass )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitInsn( LRETURN );
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitInsn( DRETURN );
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitInsn( FRETURN );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else
+        {
+            mv.visitTypeInsn( CHECKCAST, getInternalName( aClass ) );
+            mv.visitInsn( ARETURN );
+        }
+    }
+
+    private static void insn( MethodVisitor mv, int length )
+    {
+        switch( length )
+        {
+        case 0:
+            mv.visitInsn( ICONST_0 );
+            return;
+        case 1:
+            mv.visitInsn( ICONST_1 );
+            return;
+        case 2:
+            mv.visitInsn( ICONST_2 );
+            return;
+        case 3:
+            mv.visitInsn( ICONST_3 );
+            return;
+        case 4:
+            mv.visitInsn( ICONST_4 );
+            return;
+        case 5:
+            mv.visitInsn( ICONST_5 );
+            return;
+        default:
+            mv.visitIntInsn( BIPUSH, length );
+        }
+    }
+
+    public static boolean isGenerated( Class clazz )
+    {
+        return clazz.getName().endsWith( GENERATED_POSTFIX );
+    }
+
+    public static boolean isGenerated( Object object )
+    {
+        return object.getClass().getName().endsWith( GENERATED_POSTFIX );
+    }
+
+    public Class loadFragmentClass( Class fragmentClass )
+        throws ClassNotFoundException
+    {
+        return loadClass( fragmentClass.getName().replace( '$', '_' ) + GENERATED_POSTFIX );
+    }
+
+    public static Class getSourceClass( Class fragmentClass )
+    {
+        return fragmentClass.getName().endsWith( GENERATED_POSTFIX ) ? fragmentClass.getSuperclass() : fragmentClass;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FragmentInvocationHandler.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FragmentInvocationHandler.java
new file mode 100644
index 0000000..f0dfca6
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FragmentInvocationHandler.java
@@ -0,0 +1,137 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * JAVADOC
+ */
+abstract class FragmentInvocationHandler
+    implements InvocationHandler
+{
+    private static final String COMPACT_TRACE = "polygene.compacttrace";
+
+    private static final CompactLevel compactLevel;
+
+    static
+    {
+        compactLevel = CompactLevel.valueOf( System.getProperty( COMPACT_TRACE, "proxy" ) );
+    }
+
+    protected Object fragment;
+    protected Method method;
+
+    void setFragment( Object fragment )
+    {
+        this.fragment = fragment;
+    }
+
+    public void setMethod( Method method )
+    {
+        this.method = method;
+    }
+
+    protected Throwable cleanStackTrace( Throwable throwable, Object proxy, Method method )
+    {
+        if( compactLevel == CompactLevel.off )
+        {
+            return throwable;
+        }
+
+        StackTraceElement[] trace = throwable.getStackTrace();
+
+        // Check if exception originated within Polygene or JDK - if so then skip compaction
+        if( trace.length == 0 || !isApplicationClass( trace[ 0 ].getClassName() ) )
+        {
+            return throwable;
+        }
+
+        int count = 0;
+        for( int i = 0; i < trace.length; i++ )
+        {
+            StackTraceElement stackTraceElement = trace[ i ];
+            if( !isApplicationClass( stackTraceElement.getClassName() ) )
+            {
+                // TODO: Should find stack entry outside Runtime, and compact beyond that
+                trace[ i ] = null;
+                count++;
+            }
+            else
+            {
+                boolean classOrigin = stackTraceElement.getClassName().equals( proxy.getClass().getSimpleName() );
+                boolean methodOrigin = stackTraceElement.getMethodName().equals( method.getName() );
+                if( classOrigin && methodOrigin && compactLevel == CompactLevel.proxy )
+                {
+                    // Stop removing if the originating method call has been located in the stack.
+                    // For 'semi' and 'extensive' compaction, we don't and do the entire stack instead.
+                    trace[ i ] = new StackTraceElement( proxy.getClass()
+                                                            .getInterfaces()[ 0 ].getName(), method.getName(), null, -1 );
+                    break; // Stop compacting this trace
+                }
+            }
+        }
+
+        // Create new trace array
+        int idx = 0;
+        StackTraceElement[] newTrace = new StackTraceElement[ trace.length - count ];
+        for( StackTraceElement stackTraceElement : trace )
+        {
+            if( stackTraceElement != null )
+            {
+                newTrace[ idx++ ] = stackTraceElement;
+            }
+        }
+        throwable.setStackTrace( newTrace );
+
+        Throwable nested = throwable.getCause();
+        if( nested != null )
+        {
+            //noinspection ThrowableResultOfMethodCallIgnored
+            cleanStackTrace( nested, proxy, method );
+        }
+        for( Throwable suppressed : throwable.getSuppressed() )
+        {
+            //noinspection ThrowableResultOfMethodCallIgnored
+            cleanStackTrace( suppressed, proxy, method );
+        }
+        return throwable;
+    }
+
+    private boolean isApplicationClass( String className )
+    {
+        if( compactLevel == CompactLevel.semi )
+        {
+            return !isJdkInternals( className );
+        }
+        return !( className.endsWith( FragmentClassLoader.GENERATED_POSTFIX ) ||
+                  className.startsWith( "org.apache.polygene.runtime" ) ||
+                  isJdkInternals( className ) );
+    }
+
+    private boolean isJdkInternals( String className )
+    {
+        return className.startsWith( "java.lang.reflect" )
+               || className.startsWith( "jdk.internal.reflect" )
+               || className.startsWith( "com.sun.proxy" )
+               || className.startsWith( "sun.reflect" );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FunctionStateResolver.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FunctionStateResolver.java
new file mode 100644
index 0000000..3f0d3bc
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/FunctionStateResolver.java
@@ -0,0 +1,113 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.runtime.entity.EntityModel;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.ManyAssociationState;
+import org.apache.polygene.spi.entity.NamedAssociationState;
+
+/**
+ * Function based StateResolver.
+ */
+public class FunctionStateResolver
+    implements StateResolver
+{
+    private final Function<PropertyDescriptor, Object> propertyFunction;
+    private final Function<AssociationDescriptor, EntityReference> associationFunction;
+    private final Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction;
+    private final Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction;
+
+    public FunctionStateResolver( Function<PropertyDescriptor, Object> propertyFunction,
+                                  Function<AssociationDescriptor, EntityReference> associationFunction,
+                                  Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction,
+                                  Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction )
+    {
+        this.propertyFunction = propertyFunction;
+        this.associationFunction = associationFunction;
+        this.manyAssociationFunction = manyAssociationFunction;
+        this.namedAssociationFunction = namedAssociationFunction;
+    }
+
+    @Override
+    public Object getPropertyState( PropertyDescriptor descriptor )
+    {
+        return propertyFunction.apply( descriptor );
+    }
+
+    @Override
+    public EntityReference getAssociationState( AssociationDescriptor descriptor )
+    {
+        return associationFunction.apply( descriptor );
+    }
+
+    @Override
+    public Stream<EntityReference> getManyAssociationState( AssociationDescriptor descriptor )
+    {
+        return manyAssociationFunction.apply( descriptor );
+    }
+
+    @Override
+    public Stream<Map.Entry<String, EntityReference>> getNamedAssociationState( AssociationDescriptor descriptor )
+    {
+        return namedAssociationFunction.apply( descriptor );
+    }
+
+    public void populateState( EntityModel model, EntityState state )
+    {
+        model.state().properties().forEach(
+            propDesc ->
+            {
+                Object value = getPropertyState( propDesc );
+                state.setPropertyValue( propDesc.qualifiedName(), value );
+            } );
+        model.state().associations().forEach(
+            assDesc ->
+            {
+                EntityReference ref = getAssociationState( assDesc );
+                state.setAssociationValue( assDesc.qualifiedName(), ref );
+            } );
+        model.state().manyAssociations().forEach(
+            manyAssDesc ->
+            {
+                ManyAssociationState associationState = state.manyAssociationValueOf( manyAssDesc.qualifiedName() );
+                // First clear existing ones
+                associationState.clear();
+                // then add the new ones.
+                getManyAssociationState( manyAssDesc ).forEach( ref -> associationState.add( 0, ref ) );
+            } );
+        model.state().namedAssociations().forEach(
+            namedAssDesc ->
+            {
+                NamedAssociationState associationState = state.namedAssociationValueOf( namedAssDesc.qualifiedName() );
+                // First clear existing ones
+                associationState.clear();
+                // then add the new ones.
+                getNamedAssociationState( namedAssDesc )
+                    .forEach( entry -> associationState.put( entry.getKey(), entry.getValue() ) );
+            } );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/GenericFragmentInvocationHandler.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/GenericFragmentInvocationHandler.java
new file mode 100644
index 0000000..44259e8
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/GenericFragmentInvocationHandler.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * JAVADOC
+ */
+public final class GenericFragmentInvocationHandler
+    extends FragmentInvocationHandler
+{
+    // InvocationHandler implementation ------------------------------
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        try
+        {
+            return ( (InvocationHandler) fragment ).invoke( proxy, method, args );
+        }
+        catch( InvocationTargetException throwable )
+        {
+            throw cleanStackTrace( throwable.getTargetException(), proxy, method );
+        }
+        catch( Throwable throwable )
+        {
+            throw cleanStackTrace( throwable, proxy, method );
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/GenericPredicate.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/GenericPredicate.java
new file mode 100644
index 0000000..7b5e7d7
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/GenericPredicate.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.util.function.Predicate;
+
+/**
+ * Specification that checks whether a given class implements InvocationHandler or not.
+ */
+public class GenericPredicate
+    implements Predicate<Class<?>>
+{
+    public static final GenericPredicate INSTANCE = new GenericPredicate();
+
+    @Override
+    public boolean test( Class<?> item )
+    {
+        return InvocationHandler.class.isAssignableFrom( item );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/InstancePool.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/InstancePool.java
new file mode 100644
index 0000000..0c6f1f0
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/InstancePool.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.runtime.composite;
+
+/**
+ * JAVADOC
+ */
+public interface InstancePool<T>
+{
+    T obtainInstance();
+
+    void releaseInstance( T instance );
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/InterfaceDefaultMethodsMixin.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/InterfaceDefaultMethodsMixin.java
new file mode 100644
index 0000000..cb2875f
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/InterfaceDefaultMethodsMixin.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.DefaultMethodsFilter;
+import org.apache.polygene.api.injection.scope.This;
+
+@AppliesTo( { DefaultMethodsFilter.class } )
+public class InterfaceDefaultMethodsMixin
+    implements InvocationHandler
+{
+    // TODO (niclas): We have one instance of this class per mixin, so it seems a bit wasteful to have a ConcurrentHashMap. Maybe a small array 3 elements, which is changed to a Map is run out of space? Tricky concurrency on that, so leave it for later (a.k.a. will forget about it)
+    private final ConcurrentMap<Method, MethodCallHandler> methodHandleCache = new ConcurrentHashMap<>();
+
+    @This
+    private Composite me;
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        if( method.isDefault() )
+        {
+            // Call the interface's default method
+            MethodCallHandler callHandler = forMethod( method );
+            return callHandler.invoke( proxy, args );
+        }
+        // call the composite's method instead.
+        return method.invoke( me, args );
+    }
+
+    private MethodCallHandler forMethod( Method method )
+    {
+        return methodHandleCache.computeIfAbsent( method, this::createMethodCallHandler );
+    }
+
+    private MethodCallHandler createMethodCallHandler( Method method )
+    {
+        Class<?> declaringClass = method.getDeclaringClass();
+        try
+        {
+            Constructor<MethodHandles.Lookup> constructor = MethodHandles.Lookup.class.getDeclaredConstructor( Class.class, int.class );
+            constructor.setAccessible( true );
+            MethodHandles.Lookup lookup = constructor.newInstance( declaringClass, MethodHandles.Lookup.PRIVATE );
+            MethodHandle handle = lookup.unreflectSpecial( method, declaringClass );
+            return ( proxy, args ) -> handle.bindTo( proxy ).invokeWithArguments( args );
+        }
+        catch( IllegalAccessException | NoSuchMethodException | InstantiationException | InvocationTargetException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+    @FunctionalInterface
+    private interface MethodCallHandler
+    {
+        Object invoke( Object proxy, Object[] args )
+            throws Throwable;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinModel.java
new file mode 100644
index 0000000..37722e6
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinModel.java
@@ -0,0 +1,184 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.mixin.InitializationException;
+import org.apache.polygene.api.mixin.MixinDescriptor;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectedFieldsModel;
+import org.apache.polygene.runtime.injection.InjectedMethodsModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+
+/**
+ * JAVADOC
+ */
+public final class MixinModel
+    implements MixinDescriptor, VisitableHierarchy<Object, Object>, Dependencies
+{
+    private final Class<?> mixinClass;
+    private final Class<?> instantiationClass;
+    private final ConstructorsModel constructorsModel;
+    private final InjectedFieldsModel injectedFieldsModel;
+    private final InjectedMethodsModel injectedMethodsModel;
+    private final List<Class<?>> thisMixinTypes;
+
+    public MixinModel( Class<?> declaredMixinClass, Class<?> instantiationClass )
+    {
+        injectedFieldsModel = new InjectedFieldsModel( declaredMixinClass );
+        injectedMethodsModel = new InjectedMethodsModel( declaredMixinClass );
+
+        this.mixinClass = declaredMixinClass;
+        this.instantiationClass = instantiationClass;
+        constructorsModel = new ConstructorsModel( instantiationClass );
+
+        thisMixinTypes = buildThisMixinTypes();
+    }
+
+    @Override
+    public Class<?> mixinClass()
+    {
+        return mixinClass;
+    }
+
+    public Class<?> instantiationClass()
+    {
+        return instantiationClass;
+    }
+
+    public boolean isGeneric()
+    {
+        return InvocationHandler.class.isAssignableFrom( mixinClass );
+    }
+
+    public Stream<DependencyModel> dependencies()
+    {
+        Stream<? extends Dependencies> models = Stream.of( constructorsModel, injectedFieldsModel, injectedMethodsModel );
+        return models.flatMap( Dependencies::dependencies );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            if( constructorsModel.accept( visitor ) )
+            {
+                if( injectedFieldsModel.accept( visitor ) )
+                {
+                    injectedMethodsModel.accept( visitor );
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    // Context
+    public Object newInstance( CompositeInstance compositeInstance, StateHolder state, UsesInstance uses )
+    {
+        InjectionContext injectionContext = new InjectionContext( compositeInstance, uses, state );
+        return newInstance( injectionContext );
+    }
+
+    public Object newInstance( InjectionContext injectionContext )
+    {
+        Object mixin;
+        CompositeInstance compositeInstance = injectionContext.compositeInstance();
+
+        mixin = constructorsModel.newInstance( injectionContext );
+
+        if( FragmentClassLoader.isGenerated( instantiationClass ) )
+        {
+            try
+            {
+                instantiationClass.getDeclaredField( "_instance" ).set( mixin,
+                                                                        injectionContext.compositeInstance() );
+            }
+            catch( IllegalAccessException | NoSuchFieldException e )
+            {
+                e.printStackTrace();
+            }
+        }
+
+        injectedFieldsModel.inject( injectionContext, mixin );
+        injectedMethodsModel.inject( injectionContext, mixin );
+        if( mixin instanceof Initializable )
+        {
+            try
+            {
+                ( (Initializable) mixin ).initialize();
+            }
+            catch( Exception e )
+            {
+                List<Class<?>> compositeType = compositeInstance.types().collect( Collectors.toList() );
+                String message = "Unable to initialize " + mixinClass + " in composite " + compositeType;
+                throw new ConstructionException( new InitializationException( message, e ) );
+            }
+        }
+        return mixin;
+    }
+
+    public Iterable<Class<?>> thisMixinTypes()
+    {
+        return thisMixinTypes;
+    }
+
+    private List<Class<?>> buildThisMixinTypes()
+    {
+        return dependencies()
+            .filter( new DependencyModel.ScopeSpecification( This.class ) )
+            .distinct()
+            .map( DependencyModel::rawInjectionType )
+            .collect( Collectors.toList() );
+    }
+
+    protected FragmentInvocationHandler newInvocationHandler( Method method )
+    {
+        if( InvocationHandler.class.isAssignableFrom( mixinClass )
+            && !method.getDeclaringClass().isAssignableFrom( mixinClass ) )
+        {
+            return new GenericFragmentInvocationHandler();
+        }
+        else
+        {
+            return new TypedModifierInvocationHandler();
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        return mixinClass.getName();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinsInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinsInstance.java
new file mode 100644
index 0000000..b26f548
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinsInstance.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.Method;
+
+/**
+ * JAVADOC
+ */
+public interface MixinsInstance
+{
+    Object invoke( Object composite, Object[] params, CompositeMethodInstance methodInstance )
+        throws Throwable;
+
+    Object invokeObject( Object proxy, Object[] args, Method method )
+        throws Throwable;
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinsModel.java
new file mode 100644
index 0000000..35efb9d
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/MixinsModel.java
@@ -0,0 +1,239 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.HierarchicalVisitorAdapter;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectedFieldModel;
+import org.apache.polygene.runtime.model.Binder;
+import org.apache.polygene.runtime.model.Resolution;
+
+import static org.apache.polygene.api.util.Classes.interfacesOf;
+
+/**
+ * Base implementation of model for mixins. This records the mapping between methods in the Composite
+ * and mixin implementations.
+ */
+public class MixinsModel
+    implements Binder, VisitableHierarchy<Object, Object>, Dependencies
+{
+    protected final Map<Method, MixinModel> methodImplementation = new HashMap<>();
+    protected final Map<Method, Integer> methodIndex = new HashMap<>();
+    protected List<MixinModel> mixinModels = new ArrayList<>();
+
+    private final Map<Class, Integer> mixinIndex = new HashMap<>();
+    private final Set<Class<?>> mixinTypes = new LinkedHashSet<>();
+
+    public Stream<Class<?>> mixinTypes()
+    {
+        return mixinTypes.stream();
+    }
+
+    public <T> boolean isImplemented( Class<T> mixinType )
+    {
+        return mixinTypes.contains( mixinType );
+    }
+
+    public List<MixinModel> mixinModels()
+    {
+        return mixinModels;
+    }
+
+    public MixinModel mixinFor( Method method )
+    {
+        return methodImplementation.get( method );
+    }
+
+    public MixinModel getMixinModel( Class mixinClass )
+    {
+        for( MixinModel mixinModel : mixinModels )
+        {
+            if( mixinModel.mixinClass().equals( mixinClass ) )
+            {
+                return mixinModel;
+            }
+        }
+        return null;
+    }
+
+    public void addMixinType( Class mixinType )
+    {
+        Stream<? extends Type> stream = interfacesOf( mixinType );
+        Stream<Class<?>> rawClass = stream.map( Classes.RAW_CLASS );
+        rawClass.forEach( mixinTypes::add );
+    }
+
+    public void addMixinModel( MixinModel mixinModel )
+    {
+        mixinModels.add( mixinModel );
+    }
+
+    public void addMethodMixin( Method method, MixinModel mixinModel )
+    {
+        methodImplementation.put( method, mixinModel );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( MixinModel mixinModel : mixinModels )
+            {
+                mixinModel.accept( visitor );
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    // Binding
+    @Override
+    public void bind( final Resolution resolution )
+        throws BindingException
+    {
+        // Order mixins based on @This usages
+        UsageGraph<MixinModel> deps = new UsageGraph<>( mixinModels, new Uses(), true );
+        mixinModels = deps.resolveOrder();
+
+        // Populate mappings
+        for( int i = 0; i < mixinModels.size(); i++ )
+        {
+            MixinModel mixinModel = mixinModels.get( i );
+            mixinIndex.put( mixinModel.mixinClass(), i );
+        }
+
+        for( Map.Entry<Method, MixinModel> methodClassEntry : methodImplementation.entrySet() )
+        {
+            methodIndex.put( methodClassEntry.getKey(), mixinIndex.get( methodClassEntry.getValue().mixinClass() ) );
+        }
+
+        for( MixinModel mixinModel : mixinModels )
+        {
+            mixinModel.accept( new HierarchicalVisitorAdapter<Object, Object, BindingException>()
+            {
+                @Override
+                public boolean visitEnter( Object visited )
+                    throws BindingException
+                {
+                    if( visited instanceof InjectedFieldModel )
+                    {
+                        InjectedFieldModel fieldModel = (InjectedFieldModel) visited;
+                        fieldModel.bind( resolution.forField( fieldModel.field() ) );
+                        return false;
+                    }
+                    else if( visited instanceof Binder )
+                    {
+                        Binder constructorsModel = (Binder) visited;
+                        constructorsModel.bind( resolution );
+
+                        return false;
+                    }
+                    return true;
+                }
+
+                @Override
+                public boolean visit( Object visited )
+                    throws BindingException
+                {
+                    if( visited instanceof Binder )
+                    {
+                        ( (Binder) visited ).bind( resolution );
+                    }
+                    return true;
+                }
+            } );
+        }
+    }
+
+    // Context
+
+    public Object[] newMixinHolder()
+    {
+        return new Object[ mixinIndex.size() ];
+    }
+
+    public FragmentInvocationHandler newInvocationHandler( final Method method )
+    {
+        MixinModel mixinModel = mixinFor( method );
+        if( mixinModel == null )
+        {
+            throw new InternalError( "MixinModel can't be found." );
+        }
+        return mixinModel.newInvocationHandler( method );
+    }
+
+    public Stream<DependencyModel> dependencies()
+    {
+        return mixinModels.stream().flatMap( Dependencies::dependencies );
+    }
+
+    public Stream<Method> invocationsFor( final Class<?> mixinClass )
+    {
+        return methodImplementation.entrySet()
+            .stream().filter( entry -> entry.getValue().mixinClass().equals( mixinClass ) )
+            .map( Map.Entry::getKey );
+    }
+
+    private class Uses
+        implements UsageGraph.Use<MixinModel>
+    {
+        @Override
+        public Collection<MixinModel> uses( MixinModel source )
+        {
+            // System.out.println("BEGIN> MixinsModel.Uses.uses( "+source+" )");
+            Iterable<Class<?>> thisMixinTypes = source.thisMixinTypes();
+            List<MixinModel> usedMixinClasses = new ArrayList<>();
+            // System.out.println("\tSource Mixin Types and Methods: ");
+            for( Class thisMixinType : thisMixinTypes )
+            {
+                // System.out.println("\t\t"+thisMixinType);
+                for( Method method : thisMixinType.getMethods() )
+                {
+                    // System.out.println("\t\t\t"+method);
+                    if( !Modifier.isStatic( method.getModifiers() ) )
+                    {
+                        MixinModel used = methodImplementation.get( method );
+                        usedMixinClasses.add( used );
+                    }
+                }
+            }
+            // System.out.println( "END>   MixinsModel.Uses.uses( " + source + " )" );
+            return usedMixinClasses;
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ProxyGenerator.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ProxyGenerator.java
new file mode 100644
index 0000000..df7a02a
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ProxyGenerator.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.Proxy;
+
+/**
+ * generates proxyclasses
+ */
+public class ProxyGenerator {
+    public static Class<?> createProxyClass(ClassLoader mainTypeClassLoader, Class<?>[] interfaces) {
+        ClassLoader effectiveClassLoader = Thread.currentThread().getContextClassLoader();
+        if (effectiveClassLoader == null) {
+            effectiveClassLoader = mainTypeClassLoader;
+        }
+        return Proxy.getProxyClass(effectiveClassLoader, interfaces);
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ProxyReferenceInvocationHandler.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ProxyReferenceInvocationHandler.java
new file mode 100644
index 0000000..5d125a2
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ProxyReferenceInvocationHandler.java
@@ -0,0 +1,86 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.UndeclaredThrowableException;
+import org.apache.polygene.api.composite.CompositeInvoker;
+
+public final class ProxyReferenceInvocationHandler
+    implements InvocationHandler, CompositeInvoker
+{
+    private Object proxy;
+
+    public Object proxy()
+    {
+        return proxy;
+    }
+
+    public void setProxy( Object proxy )
+    {
+        this.proxy = proxy;
+    }
+
+    public void clearProxy()
+    {
+        proxy = null;
+    }
+
+    @Override
+    public Object invokeComposite( Method method, Object[] args )
+        throws Throwable
+    {
+        try
+        {
+            InvocationHandler invocationHandler = Proxy.getInvocationHandler( this.proxy );
+            return invocationHandler.invoke( this.proxy, method, args );
+        }
+        catch( InvocationTargetException e )
+        {
+            throw e.getTargetException();
+        }
+        catch( UndeclaredThrowableException e )
+        {
+            throw e.getUndeclaredThrowable();
+        }
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        try
+        {
+            InvocationHandler invocationHandler = Proxy.getInvocationHandler( this.proxy );
+            return invocationHandler.invoke( this.proxy, method, args );
+        }
+        catch( InvocationTargetException e )
+        {
+            throw e.getTargetException();
+        }
+        catch( UndeclaredThrowableException e )
+        {
+            throw e.getUndeclaredThrowable();
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectInvocationHandlerResult.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectInvocationHandlerResult.java
new file mode 100644
index 0000000..44c10d5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectInvocationHandlerResult.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * JAVADOC
+ */
+public final class SideEffectInvocationHandlerResult
+    implements InvocationHandler
+{
+    private Object result;
+    private Throwable throwable;
+
+    public SideEffectInvocationHandlerResult()
+    {
+    }
+
+    public void setResult( Object result, Throwable throwable )
+    {
+        this.result = result;
+        this.throwable = throwable;
+    }
+
+    // InvocationHandler implementation ------------------------------
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        if( throwable != null )
+        {
+            throw throwable;
+        }
+        else
+        {
+            return result;
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectModel.java
new file mode 100644
index 0000000..0b19e80
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectModel.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import org.apache.polygene.api.sideeffect.SideEffectDescriptor;
+
+/**
+ * JAVADOC
+ */
+public final class SideEffectModel
+    extends AbstractModifierModel
+    implements SideEffectDescriptor
+{
+    public SideEffectModel( Class<?> sideEffectClass, Class<?> instantiationClass )
+    {
+        super( sideEffectClass, instantiationClass );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectsInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectsInstance.java
new file mode 100644
index 0000000..011cd9c
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectsInstance.java
@@ -0,0 +1,101 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * JAVADOC
+ */
+public final class SideEffectsInstance
+    implements InvocationHandler
+{
+    private final List<InvocationHandler> sideEffects;
+    private final SideEffectInvocationHandlerResult resultInvocationHandler;
+    private final ProxyReferenceInvocationHandler proxyHandler;
+    private InvocationHandler invoker;
+
+    public SideEffectsInstance( List<InvocationHandler> sideEffects,
+                                SideEffectInvocationHandlerResult resultInvocationHandler,
+                                ProxyReferenceInvocationHandler proxyHandler,
+                                InvocationHandler invoker
+    )
+    {
+        this.sideEffects = sideEffects;
+        this.resultInvocationHandler = resultInvocationHandler;
+        this.proxyHandler = proxyHandler;
+        this.invoker = invoker;
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        try
+        {
+            Object result = invoker.invoke( proxy, method, args );
+            invokeSideEffects( proxy, method, args, result, null );
+            return result;
+        }
+        catch( Throwable throwable )
+        {
+            invokeSideEffects( proxy, method, args, null, throwable );
+            throw throwable;
+        }
+    }
+
+    private void invokeSideEffects( Object proxy,
+                                    Method method,
+                                    Object[] params,
+                                    Object result,
+                                    Throwable originalThrowable
+    )
+        throws Throwable
+    {
+        proxyHandler.setProxy( proxy );
+        resultInvocationHandler.setResult( result, originalThrowable );
+
+        try
+        {
+            for( InvocationHandler sideEffect : sideEffects )
+            {
+                try
+                {
+                    sideEffect.invoke( proxy, method, params );
+                }
+                catch( Throwable throwable )
+                {
+                    if( throwable != originalThrowable )
+                    {
+                        throwable.printStackTrace();
+                    }
+                }
+            }
+        }
+        finally
+        {
+            proxyHandler.clearProxy();
+            resultInvocationHandler.setResult( null, null );
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectsModel.java
new file mode 100644
index 0000000..576b188
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SideEffectsModel.java
@@ -0,0 +1,87 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.sideeffect.SideEffectsDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+
+/**
+ * JAVADOC
+ */
+public final class SideEffectsModel
+    implements SideEffectsDescriptor, Dependencies, VisitableHierarchy<Object, Object>
+{
+    public static final SideEffectsModel EMPTY_SIDEEFFECTS = new SideEffectsModel( Collections.emptyList() );
+
+    private List<SideEffectModel> sideEffectModels = null;
+
+    public SideEffectsModel( List<SideEffectModel> sideEffectModels )
+    {
+        this.sideEffectModels = sideEffectModels;
+    }
+
+    @Override
+    public Stream<DependencyModel> dependencies()
+    {
+        return sideEffectModels.stream().flatMap( Dependencies::dependencies );
+    }
+
+    // Context
+    public SideEffectsInstance newInstance( Method method, ModuleDescriptor module,
+                                            InvocationHandler invoker )
+    {
+        ProxyReferenceInvocationHandler proxyHandler = new ProxyReferenceInvocationHandler();
+        SideEffectInvocationHandlerResult result = new SideEffectInvocationHandlerResult();
+        List<InvocationHandler> sideEffects = new ArrayList<>( sideEffectModels.size() );
+        for( SideEffectModel sideEffectModel : sideEffectModels )
+        {
+            InvocationHandler sideEffect = sideEffectModel.newInstance( module, result, proxyHandler, method );
+            sideEffects.add( sideEffect );
+        }
+        return new SideEffectsInstance( sideEffects, result, proxyHandler, invoker );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            for( SideEffectModel sideEffectModel : sideEffectModels )
+            {
+                if( !sideEffectModel.accept( modelVisitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return modelVisitor.visitLeave( this );
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/StateModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/StateModel.java
new file mode 100644
index 0000000..9995d1b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/StateModel.java
@@ -0,0 +1,79 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.AccessibleObject;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.composite.StateDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.property.PropertiesModel;
+import org.apache.polygene.runtime.property.PropertyModel;
+
+/**
+ * Base model for Composite state
+ */
+public class StateModel
+    implements StateDescriptor, VisitableHierarchy<Object, Object>
+{
+    protected final PropertiesModel propertiesModel;
+
+    public StateModel( PropertiesModel propertiesModel )
+    {
+        this.propertiesModel = propertiesModel;
+    }
+
+    public PropertyModel propertyModelFor( AccessibleObject accessor )
+    {
+        return propertiesModel.getProperty( accessor );
+    }
+
+    @Override
+    public PropertyModel findPropertyModelByName( String name )
+        throws IllegalArgumentException
+    {
+        return propertiesModel.getPropertyByName( name );
+    }
+
+    @Override
+    public PropertyModel findPropertyModelByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException
+    {
+        return propertiesModel.getPropertyByQualifiedName( name );
+    }
+
+    @Override
+    public Stream<PropertyModel> properties()
+    {
+        return propertiesModel.properties();
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            ( (VisitableHierarchy<Object, Object>) propertiesModel ).accept( visitor );
+        }
+        return visitor.visitLeave( this );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/StateResolver.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/StateResolver.java
new file mode 100644
index 0000000..64bc165
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/StateResolver.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.property.PropertyDescriptor;
+
+/**
+ * StateResolver.
+ */
+public interface StateResolver
+{
+    Object getPropertyState( PropertyDescriptor propertyDescriptor );
+
+    EntityReference getAssociationState( AssociationDescriptor associationDescriptor );
+
+    Stream<EntityReference> getManyAssociationState( AssociationDescriptor associationDescriptor );
+
+    Stream<Map.Entry<String, EntityReference>> getNamedAssociationState( AssociationDescriptor associationDescriptor );
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SynchronizedCompositeMethodInstancePool.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SynchronizedCompositeMethodInstancePool.java
new file mode 100644
index 0000000..01025cf
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/SynchronizedCompositeMethodInstancePool.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.runtime.composite;
+
+/**
+ * Method instance pool that keeps a linked list. Uses synchronization
+ * to ensure that instances are acquired and returned in a thread-safe
+ * manner.
+ */
+public final class SynchronizedCompositeMethodInstancePool
+    implements InstancePool<CompositeMethodInstance>
+{
+    private CompositeMethodInstance first = null;
+
+    @Override
+    public synchronized CompositeMethodInstance obtainInstance()
+    {
+        CompositeMethodInstance instance = first;
+        if( instance != null )
+        {
+            first = instance.getNext();
+        }
+        return instance;
+    }
+
+    @Override
+    public synchronized void releaseInstance( CompositeMethodInstance instance )
+    {
+        instance.setNext( first );
+        first = instance;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientBuilderInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientBuilderInstance.java
new file mode 100644
index 0000000..d6312d4
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientBuilderInstance.java
@@ -0,0 +1,102 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.runtime.property.PropertyInstance;
+
+/**
+ * JAVADOC
+ */
+public final class TransientBuilderInstance<T>
+    implements TransientBuilder<T>
+{
+    private TransientModel model;
+
+    // lazy initialized in accessor
+    private UsesInstance uses = UsesInstance.EMPTY_USES;
+
+    // lazy initialized in accessor
+    private CompositeInstance prototypeInstance;
+
+    private TransientStateInstance state;
+
+    public TransientBuilderInstance( TransientDescriptor model,
+                                     TransientStateInstance state,
+                                     UsesInstance uses
+    )
+    {
+        this.model = (TransientModel) model;
+        this.state = state;
+        this.uses = uses;
+    }
+
+    @Override
+    public TransientBuilder<T> use( Object... usedObjects )
+    {
+        uses = uses.use( usedObjects );
+        return this;
+    }
+
+    @Override
+    public T prototype()
+    {
+        // Instantiate given value type
+        if( prototypeInstance == null )
+        {
+            prototypeInstance = model.newInstance( uses, state );
+        }
+
+        return prototypeInstance.proxy();
+    }
+
+    @Override
+    public <K> K prototypeFor( Class<K> mixinType )
+    {
+        // Instantiate given value type
+        if( prototypeInstance == null )
+        {
+            prototypeInstance = model.newInstance( uses, state );
+        }
+
+        return prototypeInstance.newProxy( mixinType );
+    }
+
+    @Override
+    public T newInstance()
+        throws ConstructionException
+    {
+        // Set correct info's (immutable) on the state
+        model.state().properties()
+            .forEach(
+                propertyDescriptor ->
+                    ( (PropertyInstance<Object>) state.propertyFor( propertyDescriptor.accessor() ) )
+                        .setPropertyInfo( propertyDescriptor ) );
+
+        model.checkConstraints( state );
+
+        CompositeInstance compositeInstance = model.newInstance( uses, state );
+        return compositeInstance.proxy();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientClassLoader.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientClassLoader.java
new file mode 100644
index 0000000..7e20a0e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientClassLoader.java
@@ -0,0 +1,784 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.entity.Lifecycle;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.util.Methods;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+import static org.apache.polygene.api.util.Classes.RAW_CLASS;
+import static org.apache.polygene.api.util.Classes.interfacesOf;
+import static org.objectweb.asm.Opcodes.AASTORE;
+import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static org.objectweb.asm.Opcodes.ACC_STATIC;
+import static org.objectweb.asm.Opcodes.ACC_SUPER;
+import static org.objectweb.asm.Opcodes.ACONST_NULL;
+import static org.objectweb.asm.Opcodes.ALOAD;
+import static org.objectweb.asm.Opcodes.ANEWARRAY;
+import static org.objectweb.asm.Opcodes.ARETURN;
+import static org.objectweb.asm.Opcodes.ASTORE;
+import static org.objectweb.asm.Opcodes.ATHROW;
+import static org.objectweb.asm.Opcodes.BIPUSH;
+import static org.objectweb.asm.Opcodes.CHECKCAST;
+import static org.objectweb.asm.Opcodes.DLOAD;
+import static org.objectweb.asm.Opcodes.DRETURN;
+import static org.objectweb.asm.Opcodes.DUP;
+import static org.objectweb.asm.Opcodes.FLOAD;
+import static org.objectweb.asm.Opcodes.FRETURN;
+import static org.objectweb.asm.Opcodes.GETFIELD;
+import static org.objectweb.asm.Opcodes.GETSTATIC;
+import static org.objectweb.asm.Opcodes.GOTO;
+import static org.objectweb.asm.Opcodes.ICONST_0;
+import static org.objectweb.asm.Opcodes.ICONST_1;
+import static org.objectweb.asm.Opcodes.ICONST_2;
+import static org.objectweb.asm.Opcodes.ICONST_3;
+import static org.objectweb.asm.Opcodes.ICONST_4;
+import static org.objectweb.asm.Opcodes.ICONST_5;
+import static org.objectweb.asm.Opcodes.ILOAD;
+import static org.objectweb.asm.Opcodes.INVOKEINTERFACE;
+import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
+import static org.objectweb.asm.Opcodes.INVOKESTATIC;
+import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
+import static org.objectweb.asm.Opcodes.IRETURN;
+import static org.objectweb.asm.Opcodes.LLOAD;
+import static org.objectweb.asm.Opcodes.LRETURN;
+import static org.objectweb.asm.Opcodes.POP;
+import static org.objectweb.asm.Opcodes.PUTSTATIC;
+import static org.objectweb.asm.Opcodes.RETURN;
+import static org.objectweb.asm.Type.getInternalName;
+
+/**
+ * Generate subclasses of classes used for transients. All methods delegate to CompositeInvoker.
+ */
+@SuppressWarnings( "raw" )
+/* package */ final class TransientClassLoader
+    extends ClassLoader
+{
+    private static final int JDK_VERSION;
+    public static final String GENERATED_POSTFIX = "_Proxy";
+
+    static
+    {
+        String jdkString = System.getProperty( "java.specification.version" );
+        switch( jdkString )
+        {
+            case "1.8":
+            default:
+                JDK_VERSION = Opcodes.V1_8;
+                break;
+        }
+    }
+
+    /* package */ TransientClassLoader( ClassLoader parent )
+    {
+        super( parent );
+    }
+
+    @Override
+    protected Class findClass( String name )
+        throws ClassNotFoundException
+    {
+        if( name.endsWith( GENERATED_POSTFIX ) )
+        {
+            Class baseClass;
+            String baseName = name.substring( 0, name.length() - 6 );
+            try
+            {
+                baseClass = loadClass( baseName );
+            }
+            catch( ClassNotFoundException e )
+            {
+                // Try replacing the last _ with $
+                while( true )
+                {
+                    int idx = baseName.lastIndexOf( "_" );
+                    if( idx != -1 )
+                    {
+                        baseName = baseName.substring( 0, idx ) + "$" + baseName.substring( idx + 1 );
+                        try
+                        {
+                            baseClass = loadClass( baseName );
+                            break;
+                        }
+                        catch( ClassNotFoundException e1 )
+                        {
+                            // Try again
+                        }
+                    }
+                    else
+                    {
+                        throw e;
+                    }
+                }
+            }
+
+            byte[] b = generateClass( name, baseClass );
+            return defineClass( name, b, 0, b.length, baseClass.getProtectionDomain() );
+        }
+
+        // Try the classloader of this classloader -> get classes in Polygene such as CompositeInvoker
+        return getClass().getClassLoader().loadClass( name );
+    }
+
+    public static byte[] generateClass( String name, Class baseClass )
+        throws ClassNotFoundException
+    {
+        String classSlash = name.replace( '.', '/' );
+        String baseClassSlash = getInternalName( baseClass );
+
+        ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_MAXS );
+
+        // Class definition start
+        cw.visit( JDK_VERSION, ACC_PUBLIC + ACC_SUPER, classSlash, null, baseClassSlash, new String[] { "org/apache/polygene/api/composite/Composite" } );
+
+        // Composite reference
+        {
+            cw.visitField( ACC_PUBLIC, "_instance", "Lorg/apache/polygene/api/composite/CompositeInvoker;", null, null )
+                .visitEnd();
+        }
+
+        // Static Method references
+        {
+            int idx = 1;
+            for( Method method : baseClass.getMethods() )
+            {
+                if( isOverloaded( method, baseClass ) )
+                {
+                    cw.visitField( ACC_PRIVATE + ACC_STATIC, "m" + idx++, "Ljava/lang/reflect/Method;", null, null )
+                        .visitEnd();
+                }
+            }
+        }
+
+        // Constructors
+        for( Constructor constructor : baseClass.getDeclaredConstructors() )
+        {
+            if( Modifier.isPublic( constructor.getModifiers() ) || Modifier.isProtected( constructor.getModifiers() ) )
+            {
+                String desc = org.objectweb.asm.commons.Method.getMethod( constructor ).getDescriptor();
+                MethodVisitor mv = cw.visitMethod( ACC_PUBLIC, "<init>", desc, null, null );
+                mv.visitCode();
+                mv.visitVarInsn( ALOAD, 0 );
+
+                int idx = 1;
+                for( Class aClass : constructor.getParameterTypes() )
+                {
+                    // TODO Handle other types than objects (?)
+                    mv.visitVarInsn( ALOAD, idx++ );
+                }
+
+                mv.visitMethodInsn( INVOKESPECIAL, baseClassSlash, "<init>", desc, false );
+                mv.visitInsn( RETURN );
+                mv.visitMaxs( idx, idx );
+                mv.visitEnd();
+            }
+        }
+
+        // Overloaded and unimplemented methods
+        Method[] methods = baseClass.getMethods();
+        int idx = 0;
+        List<Label> exceptionLabels = new ArrayList<>();
+        for( Method method : methods )
+        {
+            if( isOverloaded( method, baseClass ) )
+            {
+                idx++;
+                String methodName = method.getName();
+                String desc = org.objectweb.asm.commons.Method.getMethod( method ).getDescriptor();
+
+                String[] exceptions = null;
+                {
+                    MethodVisitor mv = cw.visitMethod( ACC_PUBLIC, methodName, desc, null, exceptions );
+                    if( isInternalPolygeneMethod( method, baseClass ) )
+                    {
+                        // generate a NoOp method...
+                        mv.visitInsn( RETURN );
+                    }
+                    else
+                    {
+                        Label endLabel = null; // Use this if return type is void
+                        if( method.getExceptionTypes().length > 0 )
+                        {
+                            exceptions = new String[ method.getExceptionTypes().length ];
+                            for( int i = 0; i < method.getExceptionTypes().length; i++ )
+                            {
+                                Class<?> aClass = method.getExceptionTypes()[ i ];
+                                exceptions[ i ] = getInternalName( aClass );
+                            }
+                        }
+                        mv.visitCode();
+                        Label l0 = new Label();
+                        Label l1 = new Label();
+
+                        exceptionLabels.clear();
+                        for( Class<?> declaredException : method.getExceptionTypes() )
+                        {
+                            Label ld = new Label();
+                            mv.visitTryCatchBlock( l0, l1, ld, getInternalName( declaredException ) );
+                            exceptionLabels.add( ld ); // Reuse this further down for the catch
+                        }
+
+                        Label lruntime = new Label();
+                        mv.visitTryCatchBlock( l0, l1, lruntime, "java/lang/RuntimeException" );
+                        Label lerror = new Label();
+                        mv.visitTryCatchBlock( l0, l1, lerror, "java/lang/Throwable" );
+
+                        mv.visitLabel( l0 );
+                        mv.visitVarInsn( ALOAD, 0 );
+                        mv.visitFieldInsn( GETFIELD, classSlash, "_instance",
+                                           "Lorg/apache/polygene/api/composite/CompositeInvoker;" );
+                        mv.visitFieldInsn( GETSTATIC, classSlash, "m" + idx, "Ljava/lang/reflect/Method;" );
+
+                        int paramCount = method.getParameterTypes().length;
+                        int stackIdx = 0;
+                        if( paramCount == 0 )
+                        {
+                            // Send in null as parameter
+                            mv.visitInsn( ACONST_NULL );
+                        }
+                        else
+                        {
+                            insn( mv, paramCount );
+                            mv.visitTypeInsn( ANEWARRAY, "java/lang/Object" );
+                            int pidx = 0;
+                            for( Class<?> aClass : method.getParameterTypes() )
+                            {
+                                mv.visitInsn( DUP );
+                                insn( mv, pidx++ );
+                                stackIdx = wrapParameter( mv, aClass, stackIdx + 1 );
+                                mv.visitInsn( AASTORE );
+                            }
+                        }
+
+                        // Call method
+                        mv.visitMethodInsn( INVOKEINTERFACE, "org/apache/polygene/api/composite/CompositeInvoker",
+                                            "invokeComposite",
+                                            "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true );
+
+                        // Return value
+                        if( !method.getReturnType().equals( Void.TYPE ) )
+                        {
+                            unwrapResult( mv, method.getReturnType(), l1 );
+                        }
+                        else
+                        {
+                            mv.visitInsn( POP );
+                            mv.visitLabel( l1 );
+                            endLabel = new Label();
+                            mv.visitJumpInsn( GOTO, endLabel );
+                        }
+
+                        // Increase stack to beyond method args
+                        stackIdx++;
+
+                        // Declared exceptions
+                        int exceptionIdx = 0;
+                        for( Class<?> aClass : method.getExceptionTypes() )
+                        {
+                            mv.visitLabel( exceptionLabels.get( exceptionIdx++ ) );
+                            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ getInternalName( aClass ) } );
+                            mv.visitVarInsn( ASTORE, stackIdx );
+                            mv.visitVarInsn( ALOAD, stackIdx );
+                            mv.visitInsn( ATHROW );
+                        }
+
+                        // RuntimeException and Error catch-all
+                        mv.visitLabel( lruntime );
+                        mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/RuntimeException" } );
+                        mv.visitVarInsn( ASTORE, stackIdx );
+                        mv.visitVarInsn( ALOAD, stackIdx );
+                        mv.visitInsn( ATHROW );
+
+                        mv.visitLabel( lerror );
+                        mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/Throwable" } );
+                        mv.visitVarInsn( ASTORE, stackIdx );
+                        mv.visitVarInsn( ALOAD, stackIdx );
+                        mv.visitTypeInsn( CHECKCAST, "java/lang/Error" );
+                        mv.visitInsn( ATHROW );
+
+                        // Return type = void
+                        if( endLabel != null )
+                        {
+                            mv.visitLabel( endLabel );
+                            mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
+                            mv.visitInsn( RETURN );
+                        }
+
+                        mv.visitMaxs( 0, 0 );
+                        mv.visitEnd();
+                    }
+                }
+
+                if( !Modifier.isAbstract( method.getModifiers() ) )
+                {
+                    // Add method with _ as prefix
+                    MethodVisitor mv = cw.visitMethod( ACC_PUBLIC, "_" + method.getName(), desc, null, exceptions );
+                    mv.visitCode();
+                    mv.visitVarInsn( ALOAD, 0 );
+
+                    // Parameters
+                    int stackIdx = 1;
+                    for( Class<?> aClass : method.getParameterTypes() )
+                    {
+                        stackIdx = loadParameter( mv, aClass, stackIdx ) + 1;
+                    }
+
+                    // Call method
+                    mv.visitMethodInsn( INVOKESPECIAL, baseClassSlash, method.getName(), desc, false );
+
+                    // Return value
+                    if( !method.getReturnType().equals( Void.TYPE ) )
+                    {
+                        returnResult( mv, method.getReturnType() );
+                    }
+                    else
+                    {
+                        mv.visitInsn( RETURN );
+                    }
+
+                    mv.visitMaxs( 1, 1 );
+                    mv.visitEnd();
+                }
+            }
+        }
+
+        // Class initializer
+        {
+            MethodVisitor mv = cw.visitMethod( ACC_STATIC, "<clinit>", "()V", null, null );
+            mv.visitCode();
+            Label l0 = new Label();
+            Label l1 = new Label();
+            Label l2 = new Label();
+            mv.visitTryCatchBlock( l0, l1, l2, "java/lang/NoSuchMethodException" );
+            mv.visitLabel( l0 );
+
+            // Lookup methods and store in static variables
+            int midx = 0;
+            for( Method method : methods )
+            {
+                if( isOverloaded( method, baseClass ) )
+                {
+                    Class methodClass = method.getDeclaringClass();
+
+                    midx++;
+
+                    mv.visitLdcInsn( Type.getType( methodClass ) );
+                    mv.visitLdcInsn( method.getName() );
+                    insn( mv, method.getParameterTypes().length );
+                    mv.visitTypeInsn( ANEWARRAY, "java/lang/Class" );
+
+                    int pidx = 0;
+                    for( Class<?> aClass : method.getParameterTypes() )
+                    {
+                        mv.visitInsn( DUP );
+                        insn( mv, pidx++ );
+                        type( mv, aClass );
+                        mv.visitInsn( AASTORE );
+                    }
+
+                    mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getMethod",
+                                        "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false );
+                    mv.visitFieldInsn( PUTSTATIC, classSlash, "m" + midx, "Ljava/lang/reflect/Method;" );
+                }
+            }
+
+            mv.visitLabel( l1 );
+            Label l3 = new Label();
+            mv.visitJumpInsn( GOTO, l3 );
+            mv.visitLabel( l2 );
+            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/NoSuchMethodException" } );
+            mv.visitVarInsn( ASTORE, 0 );
+            mv.visitVarInsn( ALOAD, 0 );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/NoSuchMethodException", "printStackTrace", "()V", false );
+            mv.visitLabel( l3 );
+            mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
+            mv.visitInsn( RETURN );
+            mv.visitMaxs( 6, 1 );
+            mv.visitEnd();
+        }
+        cw.visitEnd();
+        return cw.toByteArray();
+    }
+
+    private static boolean isOverloaded( Method method, Class baseClass )
+    {
+        return !Modifier.isFinal( method.getModifiers() );
+    }
+
+    private static boolean isInternalPolygeneMethod( Method method, Class baseClass )
+    {
+        return isDeclaredIn( method, Initializable.class, baseClass )
+               || isDeclaredIn( method, Lifecycle.class, baseClass );
+    }
+
+    private static boolean isDeclaredIn( Method method, Class<?> clazz, Class<?> baseClass )
+    {
+        if( !clazz.isAssignableFrom( baseClass ) )
+        {
+            return false;
+        }
+
+        try
+        {
+            clazz.getMethod( method.getName(), method.getParameterTypes() );
+            return true;
+        }
+        catch( NoSuchMethodException e )
+        {
+            return false;
+        }
+    }
+
+    private static Class<?> getInterfaceMethodDeclaration( Method method, Class clazz )
+        throws NoSuchMethodException
+    {
+        return interfacesOf( clazz ).map( RAW_CLASS ).filter( intFace -> {
+            try
+            {
+                intFace.getMethod( method.getName(), method.getParameterTypes() );
+                return true;
+            }
+            catch( NoSuchMethodException e )
+            {
+                // Try next
+                return false;
+            }
+        } ).findFirst().orElseThrow( () -> new NoSuchMethodException( method.getName() ) );
+    }
+
+    private static boolean isInterfaceMethod( Method method, Class<?> baseClass )
+    {
+        return interfacesOf( baseClass ).map( RAW_CLASS ).filter( Methods.HAS_METHODS ).anyMatch( clazz -> {
+            try
+            {
+                clazz.getMethod( method.getName(), method.getParameterTypes() );
+                return true;
+            }
+            catch( NoSuchMethodException e )
+            {
+                // Ignore
+            }
+            return false;
+        } );
+    }
+
+    private static void type( MethodVisitor mv, Class<?> aClass )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;" );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;" );
+        }
+        else
+        {
+            mv.visitLdcInsn( Type.getType( aClass ) );
+        }
+    }
+
+    private static int wrapParameter( MethodVisitor mv, Class<?> aClass, int idx )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitVarInsn( LLOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false );
+            idx++; // Extra jump
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitVarInsn( DLOAD, idx );
+            idx++; // Extra jump
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false );
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitVarInsn( FLOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false );
+        }
+        else
+        {
+            mv.visitVarInsn( ALOAD, idx );
+        }
+
+        return idx;
+    }
+
+    private static void unwrapResult( MethodVisitor mv, Class<?> aClass, Label label )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Integer" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Long" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false );
+            mv.visitLabel( label );
+            mv.visitInsn( LRETURN );
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Short" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Byte" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Double" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false );
+            mv.visitLabel( label );
+            mv.visitInsn( DRETURN );
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Float" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false );
+            mv.visitLabel( label );
+            mv.visitInsn( FRETURN );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Boolean" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Character" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false );
+            mv.visitLabel( label );
+            mv.visitInsn( IRETURN );
+        }
+        else
+        {
+            mv.visitTypeInsn( CHECKCAST, getInternalName( aClass ) );
+            mv.visitLabel( label );
+            mv.visitInsn( ARETURN );
+        }
+    }
+
+    private static int loadParameter( MethodVisitor mv, Class<?> aClass, int idx )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitVarInsn( LLOAD, idx );
+            idx++; // Extra jump
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitVarInsn( DLOAD, idx );
+            idx++; // Extra jump
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitVarInsn( FLOAD, idx );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitVarInsn( ILOAD, idx );
+        }
+        else
+        {
+            mv.visitVarInsn( ALOAD, idx );
+        }
+
+        return idx;
+    }
+
+    private static void returnResult( MethodVisitor mv, Class<?> aClass )
+    {
+        if( aClass.equals( Integer.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Long.TYPE ) )
+        {
+            mv.visitInsn( LRETURN );
+        }
+        else if( aClass.equals( Short.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Byte.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Double.TYPE ) )
+        {
+            mv.visitInsn( DRETURN );
+        }
+        else if( aClass.equals( Float.TYPE ) )
+        {
+            mv.visitInsn( FRETURN );
+        }
+        else if( aClass.equals( Boolean.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else if( aClass.equals( Character.TYPE ) )
+        {
+            mv.visitInsn( IRETURN );
+        }
+        else
+        {
+            mv.visitTypeInsn( CHECKCAST, getInternalName( aClass ) );
+            mv.visitInsn( ARETURN );
+        }
+    }
+
+    private static void insn( MethodVisitor mv, int length )
+    {
+        switch( length )
+        {
+        case 0:
+            mv.visitInsn( ICONST_0 );
+            return;
+        case 1:
+            mv.visitInsn( ICONST_1 );
+            return;
+        case 2:
+            mv.visitInsn( ICONST_2 );
+            return;
+        case 3:
+            mv.visitInsn( ICONST_3 );
+            return;
+        case 4:
+            mv.visitInsn( ICONST_4 );
+            return;
+        case 5:
+            mv.visitInsn( ICONST_5 );
+            return;
+        default:
+            mv.visitIntInsn( BIPUSH, length );
+        }
+    }
+
+    public static boolean isGenerated( Class clazz )
+    {
+        return clazz.getName().endsWith( GENERATED_POSTFIX );
+    }
+
+    public static boolean isGenerated( Object object )
+    {
+        return object.getClass().getName().endsWith( GENERATED_POSTFIX );
+    }
+
+    public Class loadFragmentClass( Class fragmentClass )
+        throws ClassNotFoundException
+    {
+        return loadClass( fragmentClass.getName().replace( '$', '_' ) + GENERATED_POSTFIX );
+    }
+
+    public static Class getSourceClass( Class fragmentClass )
+    {
+        return fragmentClass.getName().endsWith( GENERATED_POSTFIX ) ? fragmentClass.getSuperclass() : fragmentClass;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientInstance.java
new file mode 100644
index 0000000..89cb287
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientInstance.java
@@ -0,0 +1,216 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.stream.Stream;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+
+/**
+ * InvocationHandler for proxy objects.
+ */
+public class TransientInstance
+    implements CompositeInstance, MixinsInstance
+{
+    private final Composite proxy;
+    protected final Object[] mixins;
+    protected StateHolder state;
+    protected final CompositeModel compositeModel;
+
+    public TransientInstance( CompositeModel compositeModel,
+                              Object[] mixins,
+                              StateHolder state
+    )
+    {
+        this.compositeModel = compositeModel;
+        this.mixins = mixins;
+        this.state = state;
+        proxy = compositeModel.newProxy( this );
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        return compositeModel.invoke( this, proxy, method, args );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> T proxy()
+    {
+        return (T) proxy;
+    }
+
+    @Override
+    public <T> T newProxy( Class<T> mixinType )
+        throws IllegalArgumentException
+    {
+        return compositeModel.newProxy( this, mixinType );
+    }
+
+    @Override
+    public Object invokeComposite( Method method, Object[] args )
+        throws Throwable
+    {
+        return compositeModel.invoke( this, proxy, method, args );
+    }
+
+    @Override
+    public CompositeModel descriptor()
+    {
+        return compositeModel;
+    }
+
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return compositeModel.metaInfo( infoType );
+    }
+
+    @Override
+    public Stream<Class<?>> types()
+    {
+        return compositeModel.types();
+    }
+
+    @Override
+    public ModuleDescriptor module()
+    {
+        return compositeModel.module();
+    }
+
+    public LayerDescriptor layer()
+    {
+        return compositeModel.module().layer();
+    }
+
+    @Override
+    public StateHolder state()
+    {
+        return state;
+    }
+
+    @Override
+    public Object invoke( Object composite, Object[] params, CompositeMethodInstance methodInstance )
+        throws Throwable
+    {
+        Object mixin = methodInstance.getMixinFrom( mixins );
+        return methodInstance.invoke( proxy, params, mixin );
+    }
+
+    @Override
+    public Object invokeObject( Object proxy, Object[] args, Method method )
+        throws Throwable
+    {
+        return method.invoke( this, args );
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( o == null )
+        {
+            return false;
+        }
+        if( !Proxy.isProxyClass( o.getClass() ) )
+        {
+            return false;
+        }
+        TransientInstance other = (TransientInstance) PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF.apply( (Composite) o );
+        if( other.mixins.length != mixins.length )
+        {
+            return false;
+        }
+
+        for( int i = 0; i < mixins.length; i++ )
+        {
+            if( !mixins[ i ].equals( other.mixins[ i ] ) )
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int hashCode = 0;
+        for( Object mixin : mixins )
+        {
+            hashCode = hashCode * 31 + mixin.hashCode();
+        }
+        return hashCode;
+    }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder buffer = new StringBuilder();
+        boolean first = true;
+        for( Object mixin : mixins )
+        {
+            try
+            {
+                if( mixin != null )  // Can happen during construction of incorrect composites, during exception creation.
+                {
+                    Class<?> type = mixin.getClass();
+                    Method toStringMethod = type.getMethod( "toString" );
+                    Class<?> declaringClass = toStringMethod.getDeclaringClass();
+                    if( !declaringClass.equals( Object.class ) )
+                    {
+                        if( !first )
+                        {
+                            buffer.append( ", " );
+                        }
+                        first = false;
+                        buffer.append( mixin.toString() );
+                    }
+                }
+            }
+            catch( NoSuchMethodException e )
+            {
+                // Can not happen??
+                e.printStackTrace();
+            }
+        }
+        if( first )
+        {
+            String modelTypeName = compositeModel.getClass().getSimpleName();
+            String metaTypeModel = modelTypeName.substring( 0, modelTypeName.length() - 5 );
+            return metaTypeModel + "Instance{" +
+                   "mixins=" + Arrays.asList( mixins ) +
+                   ", state=" + state +
+                   ", compositeModel=" + compositeModel +
+                   ", module=" + module() +
+                   '}';
+        }
+        return buffer.toString();
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientModel.java
new file mode 100644
index 0000000..4aedb47
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientModel.java
@@ -0,0 +1,74 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.util.List;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.runtime.injection.InjectionContext;
+
+/**
+ * Model for Transient Composites
+ */
+public class TransientModel extends CompositeModel
+    implements TransientDescriptor
+{
+    public TransientModel( ModuleDescriptor module,
+                           List<Class<?>> types, final Visibility visibility,
+                           final MetaInfo metaInfo,
+                           final MixinsModel mixinsModel,
+                           final StateModel stateModel,
+                           final CompositeMethodsModel compositeMethodsModel
+    )
+    {
+        super( module, types, visibility, metaInfo, mixinsModel, stateModel, compositeMethodsModel );
+    }
+
+    public TransientInstance newInstance( UsesInstance uses,
+                                          TransientStateInstance state
+    )
+    {
+        Object[] mixins = mixinsModel.newMixinHolder();
+        TransientInstance compositeInstance = new TransientInstance( this, mixins, state );
+
+        // Instantiate all mixins
+        int i = 0;
+        InjectionContext injectionContext = new InjectionContext( compositeInstance, uses, state );
+        for( MixinModel mixinModel : mixinsModel.mixinModels() )
+        {
+            mixins[ i++ ] = mixinModel.newInstance( injectionContext );
+        }
+
+        // Return
+        return compositeInstance;
+    }
+
+    public void checkConstraints( TransientStateInstance instanceState )
+        throws ConstraintViolationException
+    {
+        stateModel.properties().forEach( propertyModel ->
+            propertyModel.checkConstraints( instanceState.propertyFor( propertyModel.accessor() ).get() )
+        );
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientStateInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientStateInstance.java
new file mode 100644
index 0000000..c70c3b8
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientStateInstance.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.AccessibleObject;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.StateHolder;
+
+/**
+ * TODO
+ */
+public final class TransientStateInstance
+    implements StateHolder
+{
+    private final Map<AccessibleObject, Property<?>> properties;
+
+    public TransientStateInstance( Map<AccessibleObject, Property<?>> properties
+    )
+    {
+        this.properties = properties;
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> Property<T> propertyFor( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        Property<T> property = (Property<T>) properties.get( accessor );
+
+        if( property == null )
+        {
+            throw new IllegalArgumentException( "No such property:" + accessor );
+        }
+
+        return property;
+    }
+
+    @Override
+    public Stream<Property<?>> properties()
+    {
+        return properties.values().stream();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientsModel.java
new file mode 100644
index 0000000..a18ef09
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TransientsModel.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * JAVADOC
+ */
+public class TransientsModel
+    implements VisitableHierarchy<Object, Object>
+{
+    private final List<TransientModel> transientModels;
+
+    public TransientsModel( List<TransientModel> transientModels )
+    {
+        this.transientModels = transientModels;
+    }
+
+    public Stream<TransientModel> models()
+    {
+        return transientModels.stream();
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            for( TransientModel transientModel : transientModels )
+            {
+                if( !transientModel.accept( modelVisitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return modelVisitor.visitLeave( this );
+    }
+
+    public Stream<? extends TransientDescriptor> stream()
+    {
+        return transientModels.stream();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TypedModifierInvocationHandler.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TypedModifierInvocationHandler.java
new file mode 100644
index 0000000..7d96abf
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/TypedModifierInvocationHandler.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * JAVADOC
+ */
+public final class TypedModifierInvocationHandler
+    extends FragmentInvocationHandler
+{
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        try
+        {
+            return this.method.invoke( fragment, args );
+        }
+        catch( InvocationTargetException e )
+        {
+            throw cleanStackTrace( e.getTargetException(), proxy, method );
+        }
+        catch( Throwable e )
+        {
+            throw cleanStackTrace( e, proxy, method );
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/UnsynchronizedCompositeMethodInstancePool.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/UnsynchronizedCompositeMethodInstancePool.java
new file mode 100644
index 0000000..56bfce5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/UnsynchronizedCompositeMethodInstancePool.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.runtime.composite;
+
+/**
+ * Method instance pool that keeps a linked list. Uses synchronization
+ * to ensure that instances are acquired and returned in a thread-safe
+ * manner.
+ */
+public final class UnsynchronizedCompositeMethodInstancePool
+    implements InstancePool<CompositeMethodInstance>
+{
+    private CompositeMethodInstance first = null;
+
+    @Override
+    public CompositeMethodInstance obtainInstance()
+    {
+        CompositeMethodInstance instance = first;
+        if( instance != null )
+        {
+            first = instance.getNext();
+        }
+        return instance;
+    }
+
+    @Override
+    public void releaseInstance( CompositeMethodInstance instance )
+    {
+        instance.setNext( first );
+        first = instance;
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/UsageGraph.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/UsageGraph.java
new file mode 100644
index 0000000..1ccb911
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/UsageGraph.java
@@ -0,0 +1,134 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import org.apache.polygene.bootstrap.BindingException;
+
+/**
+ * This class is NOT thread-safe.
+ * //TODO: Algorithm need to be optimized.
+ */
+public final class UsageGraph<K>
+{
+    private final Collection<K> data;
+    private final Use<K> use;
+    private final boolean allowCyclic;
+    private List<K> resolved;
+    private HashMap<K, List<K>> transitive;
+
+    public UsageGraph( Collection<K> data, Use<K> use, boolean allowCyclic )
+    {
+        this.data = data;
+        this.use = use;
+        this.allowCyclic = allowCyclic;
+    }
+
+    public boolean transitiveUse( K source, K other )
+        throws BindingException
+    {
+        if( transitive == null )
+        {
+            buildUsageGraph();
+        }
+        return transitive.containsKey( source ) && transitive.get( source ).contains( other );
+    }
+
+    private void checkCyclic( List<K> visited, K sourceItem, K used )
+        throws BindingException
+    {
+        Collection<K> nextLevel = use.uses( used );
+        for( K next : nextLevel )
+        {
+            if( next == sourceItem )
+            {
+                if( !allowCyclic )
+                {
+                    visited.add( next );
+                    throw new BindingException( "Cyclic usage detected: " + sourceItem + " -> " + visited );
+                }
+            }
+            if( !visited.contains( next ) )
+            {
+                visited.add( next );
+                checkCyclic( visited, sourceItem, next );
+            }
+        }
+    }
+
+    /**
+     * Must be called if the data set has been modified.
+     */
+    public void invalidate()
+    {
+        resolved = null;
+        transitive = null;
+    }
+
+    public List<K> resolveOrder()
+        throws BindingException
+    {
+        if( resolved == null )
+        {
+            buildUsageGraph();
+            resolved = new LinkedList<>();
+            for( K item : data )
+            {
+                int pos = resolved.size();
+                for( K entry : resolved )
+                {
+                    if( transitiveUse( entry, item ) )
+                    {
+                        pos = resolved.indexOf( entry );
+                        break;
+                    }
+                }
+                resolved.add( pos, item );
+            }
+        }
+        return resolved;
+    }
+
+    private void buildUsageGraph()
+        throws BindingException
+    {
+        transitive = new HashMap<>();
+        for( K sourceItem : data )
+        {
+            LinkedList<K> visited = new LinkedList<K>();
+            checkCyclic( visited, sourceItem, sourceItem );
+            transitive.put( sourceItem, visited );
+        }
+    }
+
+    public interface Use<K>
+    {
+
+        /**
+         * @param source The item to be queried.
+         *
+         * @return A list of items it uses.
+         */
+        Collection<K> uses( K source );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/UsesInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/UsesInstance.java
new file mode 100644
index 0000000..0fc8eb3
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/UsesInstance.java
@@ -0,0 +1,112 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * JAVADOC
+ */
+public final class UsesInstance
+{
+    public static final UsesInstance EMPTY_USES;
+    private final Set<Object> uses;
+
+    static
+    {
+        EMPTY_USES = new UsesInstance( new HashSet<>() );
+    }
+
+    private UsesInstance( HashSet<Object> uses )
+    {
+        this.uses = Collections.unmodifiableSet( uses );
+    }
+
+    public UsesInstance use( Object... objects )
+    {
+        HashSet<Object> useObjects = new HashSet<>();
+        if( !uses.isEmpty() )
+        {
+            useObjects.addAll( uses );
+            for( Object object : objects )
+            {
+                Object oldUseForType = useForType( object.getClass() );
+                if( oldUseForType != null )
+                {
+                    useObjects.remove( oldUseForType );
+                }
+            }
+        }
+        useObjects.addAll( Arrays.asList( objects ) );
+        return new UsesInstance( useObjects );
+    }
+
+    public Object useForType( Class<?> type )
+    {
+        // Check instances first
+        for( Object use : uses )
+        {
+            if( type.isInstance( use ) )
+            {
+                return use;
+            }
+        }
+
+        return null;
+    }
+
+    public Object[] toArray()
+    {
+        return uses.toArray();
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+        UsesInstance that = (UsesInstance) o;
+        return uses.equals( that.uses );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return uses.hashCode();
+    }
+
+    @Override
+    public String toString()
+    {
+        return "UsesInstance{" +
+               "uses=" + uses +
+               '}';
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ValueConstraintsInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ValueConstraintsInstance.java
new file mode 100644
index 0000000..ff53af8
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ValueConstraintsInstance.java
@@ -0,0 +1,143 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.constraint.ConstraintViolation;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+
+/**
+ * JAVADOC
+ */
+public final class ValueConstraintsInstance
+{
+    private static final Optional OPTIONAL;
+
+    static
+    {
+        OPTIONAL = new OptionalDummy();
+    }
+
+    @SuppressWarnings( "raw" )
+    private final List<ConstraintInstance> constraints;
+    private String name;
+    private boolean optional;
+
+    public ValueConstraintsInstance( List<AbstractConstraintModel> constraintModels, String name, boolean optional )
+    {
+        this.name = name;
+        this.optional = optional;
+        constraints = new ArrayList<>();
+        for( AbstractConstraintModel constraintModel : constraintModels )
+        {
+            constraints.add( constraintModel.newInstance() );
+        }
+    }
+
+    @SuppressWarnings( { "raw", "unchecked" } )
+    public List<ConstraintViolation> checkConstraints( Object value )
+    {
+        List<ConstraintViolation> violations = null;
+
+        // Check optional first - this avoids NPE's in constraints
+        if( optional )
+        {
+            if( value == null )
+            {
+                violations = Collections.emptyList();
+            }
+        }
+        else
+        {
+            if( value == null )
+            {
+                violations = new ArrayList<>();
+                violations.add( new ConstraintViolation( name, OPTIONAL, null ) );
+            }
+        }
+
+        if( violations == null && value != null )
+        {
+            for( ConstraintInstance constraint : constraints )
+            {
+                boolean valid;
+                try
+                {
+                    valid = constraint.isValid( value );
+                }
+                catch( NullPointerException e )
+                {
+                    // A NPE is the same as a failing constraint
+                    valid = false;
+                }
+
+                if( !valid )
+                {
+                    if( violations == null )
+                    {
+                        violations = new ArrayList<>();
+                    }
+                    ConstraintViolation violation = new ConstraintViolation( name, constraint.annotation(), value );
+                    violations.add( violation );
+                }
+            }
+        }
+        if( violations == null )
+        {
+            violations = Collections.emptyList();
+        }
+        return violations;
+    }
+
+    public void checkConstraints( Object value, AccessibleObject accessor )
+    {
+        List<ConstraintViolation> violations = checkConstraints( value );
+        if( !violations.isEmpty() )
+        {
+            Stream<Class<?>> empty = Stream.empty();
+            throw new ConstraintViolationException( "", empty, (Member) accessor, violations );
+        }
+    }
+
+    @SuppressWarnings( "AnnotationAsSuperInterface" )
+    private static class OptionalDummy
+        implements Optional
+    {
+        @Override
+        public Class<? extends Annotation> annotationType()
+        {
+            return Optional.class;
+        }
+
+        @Override
+        public String toString()
+        {
+            return "not optional";
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ValueConstraintsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ValueConstraintsModel.java
new file mode 100644
index 0000000..5568881
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/composite/ValueConstraintsModel.java
@@ -0,0 +1,72 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.util.List;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * JAVADOC
+ */
+public final class ValueConstraintsModel
+    implements VisitableHierarchy<Object, Object>
+{
+    private final List<AbstractConstraintModel> constraintModels;
+    private String name;
+    private boolean optional;
+
+    public ValueConstraintsModel( List<AbstractConstraintModel> constraintModels, String name, boolean optional )
+    {
+        this.constraintModels = constraintModels;
+        this.name = name;
+        this.optional = optional;
+    }
+
+    public ValueConstraintsInstance newInstance()
+    {
+        return new ValueConstraintsInstance( constraintModels, name, optional );
+    }
+
+    public boolean isConstrained()
+    {
+        if( !constraintModels.isEmpty() )
+        {
+            return true;
+        }
+
+        return !optional;
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        for( AbstractConstraintModel constraintModel : constraintModels )
+        {
+            if( constraintModel.accept( modelVisitor ) )
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntitiesModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntitiesModel.java
new file mode 100644
index 0000000..ebb3d78
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntitiesModel.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.runtime.entity;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * Model of entities in a particular Module.
+ */
+public class EntitiesModel
+    implements VisitableHierarchy<Object, Object>
+{
+    private final List<EntityModel> entityModels;
+
+    public EntitiesModel( List<EntityModel> entityModels )
+    {
+        this.entityModels = entityModels;
+    }
+
+    public Stream<EntityModel> models()
+    {
+        return entityModels.stream();
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            for( EntityModel entityModel : entityModels )
+            {
+                if( !entityModel.accept( modelVisitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return modelVisitor.visitLeave( this );
+    }
+
+    public Stream<? extends EntityDescriptor> stream()
+    {
+        return entityModels.stream();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityInstance.java
new file mode 100644
index 0000000..6893225
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityInstance.java
@@ -0,0 +1,310 @@
+/*
+ *  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.polygene.runtime.entity;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.AssociationStateDescriptor;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkException;
+import org.apache.polygene.runtime.composite.CompositeMethodInstance;
+import org.apache.polygene.runtime.composite.MixinsInstance;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.EntityStatus;
+
+import static java.util.stream.Collectors.toList;
+
+/**
+ * Entity instance
+ */
+public final class EntityInstance
+    implements CompositeInstance, MixinsInstance
+{
+    private final EntityComposite proxy;
+    private final UnitOfWork uow;
+    private final EntityModel entityModel;
+    private final EntityReference reference;
+    private final EntityState entityState;
+
+    private Object[] mixins;
+    private EntityStateInstance state;
+
+    public EntityInstance( UnitOfWork uow,
+                           EntityModel entityModel,
+                           EntityState entityState
+    )
+    {
+        this.uow = uow;
+        this.entityModel = entityModel;
+        this.reference = entityState.entityReference();
+        this.entityState = entityState;
+
+        proxy = (EntityComposite) entityModel.newProxy( this );
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        return entityModel.invoke( this, this.proxy, method, args );
+    }
+
+    public EntityReference reference()
+    {
+        return reference;
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> T proxy()
+    {
+        return (T) proxy;
+    }
+
+    @Override
+    public EntityDescriptor descriptor()
+    {
+        return entityModel;
+    }
+
+    @Override
+    public <T> T newProxy( Class<T> mixinType )
+        throws IllegalArgumentException
+    {
+        return entityModel.newProxy( this, mixinType );
+    }
+
+    @Override
+    public Object invokeComposite( Method method, Object[] args )
+        throws Throwable
+    {
+        return entityModel.invoke( this, proxy, method, args );
+    }
+
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return entityModel.metaInfo( infoType );
+    }
+
+    public EntityModel entityModel()
+    {
+        return entityModel;
+    }
+
+    @Override
+    public Stream<Class<?>> types()
+    {
+        return entityModel.types();
+    }
+
+    @Override
+    public ModuleDescriptor module()
+    {
+        return entityModel.module();
+    }
+
+    public UnitOfWork unitOfWork()
+    {
+        return uow;
+    }
+
+    public EntityState entityState()
+    {
+        return entityState;
+    }
+
+    @Override
+    public EntityStateInstance state()
+    {
+        if( state == null )
+        {
+            initState();
+        }
+        return state;
+    }
+
+    public EntityStatus status()
+    {
+        return entityState.status();
+    }
+
+    @Override
+    public Object invoke( Object composite, Object[] params, CompositeMethodInstance methodInstance )
+        throws Throwable
+    {
+        if( mixins == null )
+        {
+            initState();
+        }
+
+        Object mixin = methodInstance.getMixinFrom( mixins );
+
+        if( mixin == null )
+        {
+            mixin = entityModel.newMixin( mixins, state, this, methodInstance.method() );
+        }
+
+        return methodInstance.invoke( proxy, params, mixin );
+    }
+
+    @Override
+    public Object invokeObject( Object proxy, Object[] args, Method method )
+        throws Throwable
+    {
+        return method.invoke( this, args );
+    }
+
+    private void initState()
+    {
+        if( !uow.isOpen() )
+        {
+            throw new UnitOfWorkException( "Unit of work has been closed" );
+        }
+
+        if( status() == EntityStatus.REMOVED )
+        {
+            throw new NoSuchEntityException(reference, entityModel.types(), unitOfWork().usecase() );
+        }
+
+        mixins = entityModel.newMixinHolder();
+        state = new EntityStateInstance( entityModel.state(), uow, entityState );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return reference.hashCode();
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        try
+        {
+            HasIdentity other = ( (HasIdentity) o );
+            return other != null && other.identity().get().equals( reference.identity() );
+        }
+        catch( ClassCastException e )
+        {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        if( Boolean.getBoolean( "polygene.entity.print.state" ) )
+        {
+            return state().toString();
+        }
+        else
+        {
+            return reference.toString();
+        }
+    }
+
+    public void remove( UnitOfWork unitOfWork )
+    {
+        invokeRemove();
+
+        removeAggregatedEntities( unitOfWork );
+
+        entityState.remove();
+        mixins = null;
+    }
+
+    public void invokeCreate()
+    {
+        lifecyleInvoke( true );
+    }
+
+    private void invokeRemove()
+    {
+        lifecyleInvoke( false );
+    }
+
+    private void lifecyleInvoke( boolean create )
+    {
+        if( mixins == null )
+        {
+            initState();
+        }
+
+        entityModel.invokeLifecycle( create, mixins, this, state );
+    }
+
+    private void removeAggregatedEntities( UnitOfWork unitOfWork )
+    {
+        // Calculate aggregated Entities
+        AssociationStateDescriptor stateDescriptor = entityModel.state();
+        Stream.concat(
+            stateDescriptor.associations()
+                .filter( AssociationDescriptor::isAggregated )
+                .map( association -> state.associationFor( association.accessor() ).get() )
+                .filter( Objects::nonNull ),
+
+            Stream.concat(
+                stateDescriptor.manyAssociations()
+                    .filter( AssociationDescriptor::isAggregated )
+                    .flatMap( association -> state.manyAssociationFor( association.accessor() ).toList().stream() )
+                    .filter( Objects::nonNull ),
+
+                stateDescriptor.namedAssociations()
+                    .filter( AssociationDescriptor::isAggregated )
+                    .flatMap( association -> state.namedAssociationFor( association.accessor() )
+                        .toMap()
+                        .values()
+                        .stream() )
+                    .filter( Objects::nonNull )
+            )
+        ).distinct().collect( Collectors.toList() ).forEach( unitOfWork::remove );
+    }
+
+    public void checkConstraints()
+    {
+        try
+        {
+            state.checkConstraints();
+        }
+        catch( ConstraintViolationException e )
+        {
+            List<? extends Type> entityModelList = entityModel.types().collect( toList() );
+            throw new ConstraintViolationException( reference.identity(),
+                                                    entityModelList,
+                                                    e.mixinTypeName(),
+                                                    e.methodName(),
+                                                    e.constraintViolations() );
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityMixinsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityMixinsModel.java
new file mode 100644
index 0000000..566557b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityMixinsModel.java
@@ -0,0 +1,118 @@
+/*
+ *  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.polygene.runtime.entity;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.entity.Lifecycle;
+import org.apache.polygene.api.entity.LifecycleException;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.runtime.composite.MixinModel;
+import org.apache.polygene.runtime.composite.MixinsModel;
+import org.apache.polygene.runtime.composite.UsesInstance;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class EntityMixinsModel
+    extends MixinsModel
+{
+    private List<Integer> lifecycleMixins;
+
+    @Override
+    public void bind( Resolution resolution )
+        throws BindingException
+    {
+        super.bind( resolution );
+
+        // Find what mixins implement Lifecycle
+        for( int i = 0; i < mixinModels.size(); i++ )
+        {
+            MixinModel mixinModel = mixinModels.get( i );
+
+            if( Lifecycle.class.isAssignableFrom( mixinModel.mixinClass() ) )
+            {
+                if( lifecycleMixins == null )
+                {
+                    lifecycleMixins = new ArrayList<>();
+                }
+
+                lifecycleMixins.add( i );
+            }
+        }
+    }
+
+    Object newMixin( EntityInstance entityInstance, StateHolder state, Object[] mixins, Method method )
+    {
+        MixinModel model = methodImplementation.get( method );
+        InjectionContext injectionContext = new InjectionContext( entityInstance, UsesInstance.EMPTY_USES, state );
+        Object mixin = model.newInstance( injectionContext );
+        mixins[ methodIndex.get( method ) ] = mixin;
+        return mixin;
+    }
+
+    void invokeLifecycle( boolean create, Object[] mixins, CompositeInstance instance, StateHolder state )
+    {
+        if( lifecycleMixins != null )
+        {
+            InjectionContext injectionContext = new InjectionContext( instance, UsesInstance.EMPTY_USES, state );
+            for( Integer lifecycleMixin : lifecycleMixins )
+            {
+                Lifecycle lifecycle = (Lifecycle) mixins[ lifecycleMixin ];
+
+                if( lifecycle == null )
+                {
+                    lifecycle = (Lifecycle) mixinModels.get( lifecycleMixin ).newInstance( injectionContext );
+                }
+
+                if( create )
+                {
+                    try
+                    {
+                        lifecycle.create();
+                    }
+                    catch( Exception ex )
+                    {
+                        String message = "Unable to invoke create lifecycle on " + lifecycle;
+                        throw new LifecycleException( message, ex );
+                    }
+                }
+                else
+                {
+                    try
+                    {
+                        lifecycle.remove();
+                    }
+                    catch( Exception ex )
+                    {
+                        String message = "Unable to invoke remove lifecycle on " + lifecycle;
+                        throw new LifecycleException( message, ex );
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityModel.java
new file mode 100644
index 0000000..5fc00f5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityModel.java
@@ -0,0 +1,164 @@
+/*
+ *  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.polygene.runtime.entity;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.EntityCompositeType;
+import org.apache.polygene.api.unitofwork.EntityCompositeAlreadyExistsException;
+import org.apache.polygene.api.util.Annotations;
+import org.apache.polygene.runtime.composite.CompositeMethodsModel;
+import org.apache.polygene.runtime.composite.CompositeModel;
+import org.apache.polygene.runtime.unitofwork.ModuleUnitOfWork;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entitystore.EntityAlreadyExistsException;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork;
+import org.apache.polygene.spi.module.ModuleSpi;
+
+import static org.apache.polygene.api.identity.HasIdentity.IDENTITY_METHOD;
+
+/**
+ * JAVADOC
+ */
+public final class EntityModel extends CompositeModel
+    implements EntityDescriptor
+{
+    private final EntityCompositeType valueType;
+    private final boolean queryable;
+
+    public EntityModel( ModuleDescriptor module,
+                        List<Class<?>> types,
+                        Visibility visibility,
+                        MetaInfo info,
+                        EntityMixinsModel mixinsModel,
+                        EntityStateModel stateModel,
+                        CompositeMethodsModel compositeMethodsModel
+    )
+    {
+        super( module, types, visibility, info, mixinsModel, stateModel, compositeMethodsModel );
+
+        this.valueType = EntityCompositeType.of( this );
+        this.queryable = types.stream()
+            .flatMap( Annotations.ANNOTATIONS_OF )
+            .filter( Annotations.isType( Queryable.class ) )
+            .map( annot -> ( (Queryable) annot ).value() )
+            .findFirst()
+            .orElse( true );
+    }
+
+    @Override
+    public EntityCompositeType valueType()
+    {
+        return valueType;
+    }
+
+    @Override
+    public boolean queryable()
+    {
+        return queryable;
+    }
+
+    @Override
+    public EntityStateModel state()
+    {
+        return (EntityStateModel) super.state();
+    }
+
+    public EntityInstance newInstance( ModuleUnitOfWork uow, ModuleSpi moduleInstance, EntityState state )
+    {
+        return new EntityInstance( uow, this, state );
+    }
+
+    public Object[] newMixinHolder()
+    {
+        return mixinsModel.newMixinHolder();
+    }
+
+    public Object newMixin( Object[] mixins,
+                            EntityStateInstance entityState,
+                            EntityInstance entityInstance,
+                            Method method
+    )
+    {
+        return ( (EntityMixinsModel) mixinsModel ).newMixin( entityInstance, entityState, mixins, method );
+    }
+
+    public EntityState newEntityState( EntityStoreUnitOfWork store, EntityReference reference )
+        throws ConstraintViolationException, EntityStoreException
+    {
+        try
+        {
+            // New EntityState
+            EntityState entityState = store.newEntityState( reference, this );
+
+            // Set reference property
+            PropertyDescriptor persistentPropertyDescriptor = state().propertyModelFor( IDENTITY_METHOD );
+            entityState.setPropertyValue( persistentPropertyDescriptor.qualifiedName(), reference.identity() );
+
+            return entityState;
+        }
+        catch( EntityAlreadyExistsException e )
+        {
+            throw new EntityCompositeAlreadyExistsException( reference );
+        }
+        catch( EntityStoreException e )
+        {
+            throw new ConstructionException( "Could not create new entity in store", e );
+        }
+    }
+
+    public void initState( ModuleDescriptor module, EntityState entityState )
+    {
+        // Set new properties to default value
+        state().properties().forEach(
+            propertyDescriptor -> entityState.setPropertyValue( propertyDescriptor.qualifiedName(),
+                                                                propertyDescriptor.resolveInitialValue( module ) ) );
+
+        // Set new associations to null
+        state().associations().forEach(
+            associationDescriptor -> entityState.setAssociationValue( associationDescriptor.qualifiedName(),
+                                                                      null ) );
+
+        // Set new many-associations to empty
+        state().manyAssociations().forEach(
+            associationDescriptor -> entityState.manyAssociationValueOf( associationDescriptor.qualifiedName() ) );
+
+        // Set new named-associations to empty
+        state().namedAssociations().forEach(
+            associationDescriptor -> entityState.namedAssociationValueOf( associationDescriptor.qualifiedName() ) );
+    }
+
+    public void invokeLifecycle( boolean create, Object[] mixins, CompositeInstance instance, StateHolder state )
+    {
+        ( (EntityMixinsModel) mixinsModel ).invokeLifecycle( create, mixins, instance, state );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityPropertyInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityPropertyInstance.java
new file mode 100644
index 0000000..2f57d9e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityPropertyInstance.java
@@ -0,0 +1,58 @@
+/*
+ *  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.polygene.runtime.entity;
+
+import org.apache.polygene.runtime.property.PropertyInfo;
+import org.apache.polygene.runtime.property.PropertyInstance;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * {@code EntityPropertyInstance} represents a property whose value must be backed by an EntityState.
+ */
+public class EntityPropertyInstance<T>
+    extends PropertyInstance<T>
+{
+    private final EntityState entityState;
+
+    /**
+     * Construct an instance of {@code PropertyInstance} with the specified arguments.
+     *
+     * @param aPropertyInfo The property info. This argument must not be {@code null}.
+     * @param entityState EntityState
+     */
+    @SuppressWarnings( "unchecked" )
+    public EntityPropertyInstance( PropertyInfo aPropertyInfo, EntityState entityState )
+    {
+        super( aPropertyInfo, (T) entityState.propertyValueOf( aPropertyInfo.qualifiedName() ) );
+        this.entityState = entityState;
+    }
+
+    /**
+     * Sets this property value.
+     *
+     * @param aNewValue The new value.
+     */
+    @Override
+    public void set( T aNewValue )
+    {
+        super.set( aNewValue );
+        entityState.setPropertyValue( model.qualifiedName(), aNewValue );
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateInstance.java
new file mode 100644
index 0000000..c726223
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateInstance.java
@@ -0,0 +1,215 @@
+/*
+ *  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.polygene.runtime.entity;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.BiFunction;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.runtime.association.AssociationInstance;
+import org.apache.polygene.runtime.association.AssociationModel;
+import org.apache.polygene.runtime.association.ManyAssociationInstance;
+import org.apache.polygene.runtime.association.ManyAssociationModel;
+import org.apache.polygene.runtime.association.NamedAssociationInstance;
+import org.apache.polygene.runtime.association.NamedAssociationModel;
+import org.apache.polygene.runtime.property.PropertyModel;
+import org.apache.polygene.runtime.unitofwork.BuilderEntityState;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * TODO
+ */
+public final class EntityStateInstance
+    implements AssociationStateHolder
+{
+    private Map<AccessibleObject, Object> state;
+
+    private final EntityStateModel stateModel;
+    private EntityState entityState;
+    private final BiFunction<EntityReference, Type, Object> entityFunction;
+
+    EntityStateInstance( EntityStateModel stateModel, final UnitOfWork uow, EntityState entityState )
+    {
+        this.stateModel = stateModel;
+        this.entityState = entityState;
+
+        entityFunction = ( entityReference, type ) -> uow.get( Classes.RAW_CLASS.apply( type ), entityReference.identity() );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> Property<T> propertyFor( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        Map<AccessibleObject, Object> state = state();
+
+        Property<T> property = (Property<T>) state.get( accessor );
+
+        if( property == null )
+        {
+            PropertyModel entityPropertyModel = stateModel.propertyModelFor( accessor );
+            property = new EntityPropertyInstance<>(
+                entityState instanceof BuilderEntityState
+                ? entityPropertyModel.getBuilderInfo()
+                : entityPropertyModel,
+                entityState );
+            state.put( accessor, property );
+        }
+
+        return property;
+    }
+
+    @Override
+    public Stream<Property<?>> properties()
+    {
+        return stateModel.properties().map( descriptor -> propertyFor( descriptor.accessor() ) );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> Association<T> associationFor( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        Map<AccessibleObject, Object> state = state();
+        Association<T> association = (Association<T>) state.get( accessor );
+
+        if( association == null )
+        {
+            final AssociationModel associationModel = stateModel.getAssociation( accessor );
+            association = new AssociationInstance<>(
+                entityState instanceof BuilderEntityState ? associationModel.builderInfo() : associationModel,
+                entityFunction,
+                new Property<EntityReference>()
+                {
+                    @Override
+                    public EntityReference get()
+                    {
+                        return entityState.associationValueOf( associationModel.qualifiedName() );
+                    }
+
+                    @Override
+                    public void set( EntityReference newValue )
+                        throws IllegalArgumentException, IllegalStateException
+                    {
+                        entityState.setAssociationValue( associationModel.qualifiedName(), newValue );
+                    }
+                } );
+            state.put( accessor, association );
+        }
+        return association;
+    }
+
+    @Override
+    public Stream<? extends Association<?>> allAssociations()
+    {
+        return stateModel.associations().map( descriptor -> associationFor( descriptor.accessor() ) );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> ManyAssociation<T> manyAssociationFor( AccessibleObject accessor )
+    {
+        Map<AccessibleObject, Object> state = state();
+        ManyAssociation<T> manyAssociation = (ManyAssociation<T>) state.get( accessor );
+        if( manyAssociation == null )
+        {
+            ManyAssociationModel associationModel = stateModel.getManyAssociation( accessor );
+            manyAssociation = new ManyAssociationInstance<>(
+                entityState instanceof BuilderEntityState ? associationModel.builderInfo() : associationModel,
+                entityFunction,
+                entityState.manyAssociationValueOf( associationModel.qualifiedName() ) );
+            state.put( accessor, manyAssociation );
+        }
+        return manyAssociation;
+    }
+
+    @Override
+    public Stream<ManyAssociation<?>> allManyAssociations()
+    {
+        return stateModel.manyAssociations().map( descriptor -> manyAssociationFor( descriptor.accessor() ) );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> NamedAssociation<T> namedAssociationFor( AccessibleObject accessor )
+    {
+        Map<AccessibleObject, Object> state = state();
+        NamedAssociation<T> namedAssociation = (NamedAssociation<T>) state.get( accessor );
+        if( namedAssociation == null )
+        {
+            NamedAssociationModel associationModel = stateModel.getNamedAssociation( accessor );
+            namedAssociation = new NamedAssociationInstance<>(
+                entityState instanceof BuilderEntityState ? associationModel.builderInfo() : associationModel,
+                entityFunction,
+                entityState.namedAssociationValueOf( associationModel.qualifiedName() ) );
+            state.put( accessor, namedAssociation );
+        }
+        return namedAssociation;
+    }
+
+    @Override
+    public Stream<? extends NamedAssociation<?>> allNamedAssociations()
+    {
+        return stateModel.namedAssociations().map( descriptor -> namedAssociationFor( descriptor.accessor() ) );
+    }
+
+    public void checkConstraints()
+    {
+        stateModel.properties().forEach( propertyDescriptor ->
+                                         {
+                                             Property<Object> property = this.propertyFor( propertyDescriptor.accessor() );
+                                             propertyDescriptor.checkConstraints( property.get() );
+                                         } );
+
+        stateModel.associations().forEach( associationDescriptor ->
+                                           {
+                                               Association<Object> association = this.associationFor( associationDescriptor.accessor() );
+                                               associationDescriptor.checkConstraints( association.get() );
+                                           } );
+
+        // TODO Should ManyAssociations and NamedAssociations be checked too?
+    }
+
+    private Map<AccessibleObject, Object> state()
+    {
+        if( state == null )
+        {
+            state = new HashMap<>();
+        }
+
+        return state;
+    }
+
+    @Override
+    public String toString()
+    {
+        return entityState.toString();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateModel.java
new file mode 100644
index 0000000..7601b4e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateModel.java
@@ -0,0 +1,158 @@
+/*
+ *  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.polygene.runtime.entity;
+
+import java.lang.reflect.AccessibleObject;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.AssociationStateDescriptor;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.association.AssociationModel;
+import org.apache.polygene.runtime.association.AssociationsModel;
+import org.apache.polygene.runtime.association.ManyAssociationModel;
+import org.apache.polygene.runtime.association.ManyAssociationsModel;
+import org.apache.polygene.runtime.association.NamedAssociationModel;
+import org.apache.polygene.runtime.association.NamedAssociationsModel;
+import org.apache.polygene.runtime.composite.StateModel;
+import org.apache.polygene.runtime.property.PropertiesModel;
+
+/**
+ * Model for EntityComposite state.
+ */
+public final class EntityStateModel
+    extends StateModel
+    implements AssociationStateDescriptor
+{
+    private final AssociationsModel associationsModel;
+    private final ManyAssociationsModel manyAssociationsModel;
+    private final NamedAssociationsModel namedAssociationsModel;
+
+    public EntityStateModel( PropertiesModel propertiesModel,
+                             AssociationsModel associationsModel,
+                             ManyAssociationsModel manyAssociationsModel,
+                             NamedAssociationsModel namedAssociationsModel )
+    {
+        super( propertiesModel );
+        this.associationsModel = associationsModel;
+        this.manyAssociationsModel = manyAssociationsModel;
+        this.namedAssociationsModel = namedAssociationsModel;
+    }
+
+    public AssociationModel getAssociation( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        return associationsModel.getAssociation( accessor );
+    }
+
+    @Override
+    public AssociationDescriptor getAssociationByName( String name )
+        throws IllegalArgumentException
+    {
+        return associationsModel.getAssociationByName( name );
+    }
+
+    @Override
+    public AssociationDescriptor getAssociationByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException
+    {
+        return associationsModel.getAssociationByQualifiedName( name );
+    }
+
+    public ManyAssociationModel getManyAssociation( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        return manyAssociationsModel.getManyAssociation( accessor );
+    }
+
+    @Override
+    public AssociationDescriptor getManyAssociationByName( String name )
+        throws IllegalArgumentException
+    {
+        return manyAssociationsModel.getManyAssociationByName( name );
+    }
+
+    @Override
+    public AssociationDescriptor getManyAssociationByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException
+    {
+        return manyAssociationsModel.getManyAssociationByQualifiedName( name );
+    }
+
+    public NamedAssociationModel getNamedAssociation( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        return namedAssociationsModel.getNamedAssociation( accessor );
+    }
+
+    @Override
+    public AssociationDescriptor getNamedAssociationByName( String name )
+        throws IllegalArgumentException
+    {
+        return namedAssociationsModel.getNamedAssociationByName( name );
+    }
+
+    @Override
+    public AssociationDescriptor getNamedAssociationByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException
+    {
+        return namedAssociationsModel.getNamedAssociationByQualifiedName( name );
+    }
+
+    @Override
+    public Stream<AssociationModel> associations()
+    {
+        return associationsModel.associations();
+    }
+
+    @Override
+    public Stream<ManyAssociationModel> manyAssociations()
+    {
+        return manyAssociationsModel.manyAssociations();
+    }
+
+    @Override
+    public Stream<NamedAssociationModel> namedAssociations()
+    {
+        return namedAssociationsModel.namedAssociations();
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            if( ( (VisitableHierarchy<Object, Object>) propertiesModel ).accept( visitor ) )
+            {
+                if( ( (VisitableHierarchy<AssociationsModel, AssociationModel>) associationsModel ).accept( visitor ) )
+                {
+                    if( ( (VisitableHierarchy<ManyAssociationsModel, ManyAssociationModel>) manyAssociationsModel ).accept( visitor ) )
+                    {
+                        ( (VisitableHierarchy<NamedAssociationsModel, NamedAssociationModel>) namedAssociationsModel ).accept( visitor );
+                    }
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/Dependencies.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/Dependencies.java
new file mode 100644
index 0000000..31d8b75
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/Dependencies.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+/**
+ * TODO
+ */
+public interface Dependencies
+{
+    Function<Dependencies, Stream<DependencyModel>> DEPENDENCIES_FUNCTION = Dependencies::dependencies;
+
+    Stream<DependencyModel> dependencies();
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/DependencyModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/DependencyModel.java
new file mode 100644
index 0000000..0c72658
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/DependencyModel.java
@@ -0,0 +1,421 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.DependencyDescriptor;
+import org.apache.polygene.api.util.Visitable;
+import org.apache.polygene.api.util.Visitor;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.injection.provider.CachingInjectionProviderDecorator;
+import org.apache.polygene.runtime.injection.provider.InjectionProviderException;
+import org.apache.polygene.runtime.injection.provider.ServiceInjectionProviderFactory;
+import org.apache.polygene.runtime.model.Binder;
+import org.apache.polygene.runtime.model.Resolution;
+
+import static org.apache.polygene.api.util.Annotations.isType;
+
+/**
+ * JAVADOC
+ * move all the extraction code to a TypeUtils class
+ */
+public final class DependencyModel
+    implements Binder, DependencyDescriptor, Visitable<DependencyModel>
+{
+    public static boolean isOptional( Annotation injectionAnnotation, Annotation[] annotations )
+    {
+        if( Stream.of( annotations ).anyMatch( isType( Optional.class ) ) )
+        {
+            return true;
+        }
+
+        Method[] methods = injectionAnnotation.annotationType().getMethods();
+        for( Method method : methods )
+        {
+            if( method.getName().equals( "optional" ) )
+            {
+                try
+                {
+                    return (Boolean) method.invoke( injectionAnnotation );
+                }
+                catch( Throwable e )
+                {
+                    return false;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    // Model
+    private final Annotation injectionAnnotation;
+    private final Type injectionType;
+    private final Class<?> injectedClass;
+    private final Class<?> rawInjectionClass;
+    private final boolean optional;
+    private final Annotation[] annotations;
+
+    // Binding
+    private InjectionProvider injectionProvider;
+
+    public DependencyModel( Annotation injectionAnnotation,
+                            Type genericType,
+                            Class<?> injectedClass,
+                            boolean optional,
+                            Annotation[] annotations
+    )
+    {
+        this.injectionAnnotation = injectionAnnotation;
+        this.injectedClass = injectedClass;
+
+        this.injectionType = genericType;
+        this.optional = optional;
+        this.annotations = annotations;
+        this.rawInjectionClass = mapPrimitiveTypes( extractRawInjectionClass( injectedClass, injectionType ) );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( Visitor<? super DependencyModel, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        return visitor.visit( this );
+    }
+
+    private Class<?> extractRawInjectionClass( Class<?> injectedClass, final Type injectionType )
+    {
+        // Calculate raw injection type
+        if( injectionType instanceof Class )
+        {
+            return (Class<?>) injectionType;
+        }
+        else if( injectionType instanceof ParameterizedType )
+        {
+            return (Class<?>) ( (ParameterizedType) injectionType ).getRawType();
+        }
+        else if( injectionType instanceof TypeVariable )
+        {
+            return extractRawInjectionClass( injectedClass, (TypeVariable<?>) injectionType );
+        }
+        throw new IllegalArgumentException(
+            "Could not extract the rawInjectionClass of " + injectedClass + " and " + injectionType );
+    }
+
+    private Class<?> extractRawInjectionClass( Class<?> injectedClass, TypeVariable<?> injectionTypeVariable )
+    {
+        int index = 0;
+        for( TypeVariable<?> typeVariable : injectionTypeVariable.getGenericDeclaration().getTypeParameters() )
+        {
+            if( injectionTypeVariable.getName().equals( typeVariable.getName() ) )
+            {
+                return (Class<?>) getActualType( injectedClass, index );
+            }
+            index++;
+        }
+        throw new IllegalArgumentException(
+            "Could not extract the rawInjectionClass of " + injectedClass + " and " + injectionTypeVariable );
+    }
+
+    // todo continue refactoring
+
+    private Type getActualType( Class<?> injectedClass, int index )
+    {
+        // Type index found - map it to actual type
+        Type genericType = injectedClass;
+        Type type = null;
+
+        while( !Object.class.equals( genericType ) && type == null )
+        {
+            genericType = ( (Class<?>) genericType ).getGenericSuperclass();
+            if( genericType instanceof ParameterizedType )
+            {
+                type = ( (ParameterizedType) genericType ).getActualTypeArguments()[ index ];
+            }
+            else
+            {
+                Type[] genericInterfaces = ( (Class<?>) genericType ).getGenericInterfaces();
+                if( genericInterfaces.length > index )
+                {
+                    type = genericInterfaces[ index ];
+                    if( type instanceof ParameterizedType )
+                    {
+                        type = ( (ParameterizedType) type ).getActualTypeArguments()[ index ];
+                    }
+                    // TODO type may still be one of the generic interfaces???
+                }
+            }
+        }
+
+        if( type == null )
+        {
+            type = Object.class; // Generic type with no constraints so Object is fine
+        }
+
+        return type;
+    }
+
+    // FIXME This method is unused, remove it.
+    private Type extractDependencyType( Type injectionType )
+    {
+        if( injectionType instanceof ParameterizedType )
+        {
+            return ( (ParameterizedType) injectionType ).getActualTypeArguments()[ 0 ];
+        }
+        else if( injectionType instanceof TypeVariable )
+        {
+            return ( (TypeVariable) injectionType ).getBounds()[ 0 ];
+        }
+        return injectionType;
+    }
+
+    // Model
+    @Override
+    public Annotation injectionAnnotation()
+    {
+        return injectionAnnotation;
+    }
+
+    @Override
+    public Type injectionType()
+    {
+        return injectionType;
+    }
+
+    @Override
+    public Class<?> injectedClass()
+    {
+        return injectedClass;
+    }
+
+    /**
+     * Get the raw dependency type.
+     * <p>
+     * If the dependency uses generics this is the raw type,
+     * and otherwise it is the type of the field.
+     * <p>
+     * Examples:
+     * <p>
+     * {@code @Service MyService service} -&gt; MyService
+     * <p>
+     * {@code @Entity Iterable<Foo> fooList} -&gt; Iterable
+     * <p>
+     * {@code @Entity Query<Foo> fooQuery} -&gt; Query
+     *
+     * @return raw injection type.
+     */
+    @Override
+    public Class<?> rawInjectionType()
+    {
+        return rawInjectionClass;
+    }
+
+    @Override
+    public boolean optional()
+    {
+        return optional;
+    }
+
+    @Override
+    public Annotation[] annotations()
+    {
+        return annotations;
+    }
+
+    @Override
+    public void bind( Resolution resolution )
+        throws BindingException
+    {
+        InjectionProviderFactory providerFactory = resolution.application().injectionProviderFactory();
+
+        try
+        {
+            injectionProvider = providerFactory.newInjectionProvider( resolution, this );
+
+            if( injectionProvider == null && !optional )
+            {
+                String message =
+                    "[Module " + resolution.module()
+                        .name() + "] Non-optional @" + rawInjectionClass.getName() + " was not bound in " + injectedClass
+                        .getName();
+                throw new ConstructionException( message );
+            }
+        }
+        catch( InvalidInjectionException e )
+        {
+            throw new BindingException( "Could not bind dependency injection", e );
+        }
+    }
+
+    // Context
+    public Object inject( InjectionContext context )
+    {
+        if( injectionProvider == null )
+        {
+            return null;
+        }
+        Object injectedValue;
+        try
+        {
+            injectedValue = injectionProvider.provideInjection( context );
+        }
+        catch( InjectionProviderException e )
+        {
+            Throwable ex = e;
+            if( ex.getCause() != null )
+            {
+                ex = ex.getCause();
+            }
+
+            String message = "[Module " + context.module().name() + "] InjectionProvider unable to resolve @" +
+                             injectionAnnotation.annotationType().getSimpleName() + " " + injectionType.toString();
+            throw new ConstructionException( message, ex );
+        }
+        if( injectedValue == null && !optional )
+        {
+            String simpleName = injectionAnnotation.annotationType().getSimpleName();
+            String message = "[Module " + context.module().name() + "] Non-optional @" +
+                             simpleName + " " + injectionType.toString() +
+                             " was null in " + injectedClass.getName();
+            if( simpleName.toLowerCase().contains( "service" )
+                && !isServiceInjectionProvider() )
+            {
+                message = message + ". Did you mean the @Service injection scope?";
+            }
+            throw new ConstructionException( message );
+        }
+        return getInjectedValue( injectedValue );
+    }
+
+    private boolean isServiceInjectionProvider()
+    {
+
+        InjectionProvider provider = this.injectionProvider;
+        if( provider instanceof CachingInjectionProviderDecorator ){
+            provider = ((CachingInjectionProviderDecorator) provider ).decoratedProvider();
+        }
+        return ServiceInjectionProviderFactory.ServiceInjectionProvider.class.isAssignableFrom( provider.getClass() );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private Object getInjectedValue( Object injectionResult )
+    {
+        if( injectionResult == null )
+        {
+            return null;
+        }
+
+        if( injectionResult instanceof Iterable )
+        {
+            if( Iterable.class.isAssignableFrom( rawInjectionClass )
+                || rawInjectionClass.isInstance( injectionResult ) )
+            {
+                return injectionResult;
+            }
+            else
+            {
+                Iterator iterator = ( (Iterable) injectionResult ).iterator();
+                return iterator.hasNext() ? iterator.next() : null;
+            }
+        }
+        else
+        {
+            if( Iterable.class.equals( injectionType ) )
+            {
+                return Collections.singleton( injectionResult );
+            }
+        }
+        return injectionResult;
+    }
+
+    private final static Class<?>[] primitiveTypeMapping = {
+        boolean.class, Boolean.class,
+        byte.class, Byte.class,
+        short.class, Short.class,
+        char.class, Character.class,
+        long.class, Long.class,
+        double.class, Double.class,
+        float.class, Float.class,
+        int.class, Integer.class,
+        };
+
+    private Class<?> mapPrimitiveTypes( Class<?> rawInjectionType )
+    {
+        if( rawInjectionType == null || !rawInjectionType.isPrimitive() )
+        {
+            return rawInjectionType;
+        }
+        for( int i = 0; i < primitiveTypeMapping.length; i += 2 )
+        {
+            if( primitiveTypeMapping[ i ].equals( rawInjectionType ) )
+            {
+                return primitiveTypeMapping[ i + 1 ];
+            }
+        }
+        return rawInjectionType;
+    }
+
+    public boolean hasScope( final Class<? extends Annotation> scope )
+    {
+        return scope == null || scope.equals( injectionAnnotation().annotationType() );
+    }
+
+    public Class<? extends Annotation> injectionAnnotationType()
+    {
+        if( injectionAnnotation == null )
+        {
+            return null;
+        }
+        return injectionAnnotation.annotationType();
+    }
+
+    @Override
+    public String toString()
+    {
+        return injectionAnnotation + " for " + injectionType + " in " + injectedClass.getName();
+    }
+
+    public static class ScopeSpecification
+        implements Predicate<DependencyModel>
+    {
+        private final Class<? extends Annotation> scope;
+
+        public ScopeSpecification( Class<? extends Annotation> scope )
+        {
+            this.scope = scope;
+        }
+
+        @Override
+        public boolean test( DependencyModel model )
+        {
+            return model.hasScope( scope );
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldModel.java
new file mode 100644
index 0000000..553f1ff
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldModel.java
@@ -0,0 +1,165 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.util.Collection;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.DependencyDescriptor;
+import org.apache.polygene.api.composite.InjectedFieldDescriptor;
+import org.apache.polygene.api.util.AccessibleObjects;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.bootstrap.InjectionException;
+import org.apache.polygene.runtime.composite.TransientInstance;
+import org.apache.polygene.runtime.model.Resolution;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singleton;
+
+/**
+ * JAVADOC
+ */
+public final class InjectedFieldModel
+    implements InjectedFieldDescriptor, Dependencies, VisitableHierarchy<InjectedFieldModel, DependencyModel>
+{
+    private DependencyModel dependencyModel;
+    private Field injectedField;
+
+    public InjectedFieldModel( Field injectedField, DependencyModel dependencyModel )
+    {
+        this.injectedField = AccessibleObjects.accessible( injectedField );
+        this.dependencyModel = dependencyModel;
+    }
+
+    @Override
+    public Stream<DependencyModel> dependencies()
+    {
+        return Stream.of( dependencyModel );
+    }
+
+    @Override
+    public Field field()
+    {
+        return injectedField;
+    }
+
+    @Override
+    public DependencyDescriptor dependency()
+    {
+        return dependencyModel;
+    }
+
+    public void bind( Resolution resolution )
+        throws BindingException
+    {
+        dependencyModel.bind( resolution.forField( injectedField ) );
+    }
+
+    public void inject( InjectionContext context, Object instance )
+    {
+        Object value = dependencyModel.inject( context );
+        try
+        {
+            injectedField.set( instance, value );
+        }
+        catch( IllegalAccessException e )
+        {
+            throw new InjectionException( e );
+        }
+        catch( IllegalArgumentException e )
+        {
+            String valueClassName;
+            if( value == null )
+            {
+                valueClassName = "<null>";
+            }
+            else if( Proxy.isProxyClass( value.getClass() ) )
+            {
+                InvocationHandler invocationHandler = Proxy.getInvocationHandler( value );
+                if( invocationHandler instanceof TransientInstance )
+                {
+                    TransientInstance handler = (TransientInstance) invocationHandler;
+                    valueClassName = Classes.toString( handler.descriptor().types() )
+                                     + " in [" + handler.module().name() + "] of [" + handler.layer().name() + "]";
+                }
+                else
+                {
+                    valueClassName = invocationHandler.toString();
+                }
+            }
+            else
+            {
+                valueClassName = value.getClass().getName();
+            }
+            StringBuilder annotBuilder = new StringBuilder();
+            for( Annotation annot : injectedField.getAnnotations() )
+            {
+                String s = annot.toString();
+                annotBuilder.append( "@" ).append( s.substring( s.lastIndexOf( '.' ) + 1, s.length() - 2 ) );
+                annotBuilder.append( " " );
+            }
+            String annots = annotBuilder.toString();
+            String message = "Can not inject the field\n    "
+                             + injectedField.getDeclaringClass()
+                             + "\n    {\n        " + annots + "\n        "
+                             + injectedField.getType().getSimpleName() + " " + injectedField.getName()
+                             + "\n    }\nwith value \n    " + value + "\nof type\n    "
+                             + valueClassName;
+            throw new InjectionException( message, e );
+        }
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super InjectedFieldModel, ? super DependencyModel, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            visitor.visit( dependencyModel );
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public Collection<DependencyModel> filter( Predicate<DependencyModel> specification )
+    {
+        if( specification.test( dependencyModel ) )
+        {
+            return singleton( dependencyModel );
+        }
+        else
+        {
+            return emptyList();
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        return "InjectedFieldModel{" + ", injectedField=" + injectedField + '}';
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldsModel.java
new file mode 100644
index 0000000..54c8312
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldsModel.java
@@ -0,0 +1,117 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Stream;
+import org.apache.polygene.api.injection.InjectionScope;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.Fields;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+import static org.apache.polygene.api.util.Annotations.typeHasAnnotation;
+
+/**
+ * JAVADOC
+ */
+public final class InjectedFieldsModel
+    implements Dependencies, VisitableHierarchy<Object, Object>
+{
+    private final List<InjectedFieldModel> fields = new ArrayList<>();
+
+    public InjectedFieldsModel( Class fragmentClass )
+    {
+        Fields.fieldsOf( fragmentClass ).forEach( field ->
+            Arrays.stream( field.getAnnotations() )
+                  .filter( typeHasAnnotation( InjectionScope.class ) )
+                  .filter( Objects::nonNull )
+                  .forEach( injectionAnnotation ->  addModel( fragmentClass, field, injectionAnnotation )
+            )
+        );
+    }
+
+    private void addModel( Class fragmentClass, Field field, Annotation injectionAnnotation )
+    {
+        Type genericType = field.getGenericType();
+        if( genericType instanceof ParameterizedType )
+        {
+            Type[] actualTypeArguments = ( (ParameterizedType) genericType ).getActualTypeArguments();
+            Type rawType = ( (ParameterizedType) genericType ).getRawType();
+            Type ownerType = ( (ParameterizedType) genericType ).getOwnerType();
+            genericType = new ParameterizedTypeInstance( actualTypeArguments, rawType, ownerType );
+
+            for( int i = 0; i < actualTypeArguments.length; i++ )
+            {
+                Type type = actualTypeArguments[ i ];
+                if( type instanceof TypeVariable )
+                {
+                    type = Classes.resolveTypeVariable( (TypeVariable) type, field.getDeclaringClass(), fragmentClass );
+                    actualTypeArguments[ i ] = type;
+                }
+            }
+        }
+
+        boolean optional = DependencyModel.isOptional( injectionAnnotation, field.getAnnotations() );
+        DependencyModel dependencyModel = new DependencyModel( injectionAnnotation, genericType, fragmentClass, optional, field.getAnnotations() );
+        InjectedFieldModel injectedFieldModel = new InjectedFieldModel( field, dependencyModel );
+        this.fields.add( injectedFieldModel );
+    }
+
+    @Override
+    public Stream<DependencyModel> dependencies()
+    {
+        return fields.stream().flatMap( Dependencies::dependencies );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            for( InjectedFieldModel field : fields )
+            {
+                if( !field.accept( modelVisitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return modelVisitor.visitLeave( this );
+    }
+
+    public void inject( InjectionContext context, Object instance )
+    {
+        for( InjectedFieldModel field : fields )
+        {
+            field.inject( context, instance );
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodModel.java
new file mode 100644
index 0000000..9df8692
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodModel.java
@@ -0,0 +1,89 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.InjectedMethodDescriptor;
+import org.apache.polygene.api.util.AccessibleObjects;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.bootstrap.InjectionException;
+
+/**
+ * JAVADOC
+ */
+public final class InjectedMethodModel
+    implements InjectedMethodDescriptor, Dependencies, VisitableHierarchy<Object, Object>
+{
+    // Model
+    private Method method;
+    private InjectedParametersModel parameters;
+
+    public InjectedMethodModel( Method method, InjectedParametersModel parameters )
+    {
+        this.method = AccessibleObjects.accessible( method );
+        this.parameters = parameters;
+    }
+
+    @Override
+    public Method method()
+    {
+        return method;
+    }
+
+    @Override
+    public Stream<DependencyModel> dependencies()
+    {
+        return parameters.dependencies();
+    }
+
+    // Context
+    public void inject( InjectionContext context, Object instance )
+        throws InjectionException
+    {
+        Object[] params = parameters.newParametersInstance( context );
+        try
+        {
+            method.invoke( instance, params );
+        }
+        catch( IllegalAccessException e )
+        {
+            throw new InjectionException( e );
+        }
+        catch( InvocationTargetException e )
+        {
+            throw new InjectionException( e.getTargetException() );
+        }
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            parameters.accept( visitor );
+        }
+        return visitor.visitLeave( this );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodsModel.java
new file mode 100644
index 0000000..b2d4c89
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodsModel.java
@@ -0,0 +1,139 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+import javax.annotation.PostConstruct;
+import org.apache.polygene.api.injection.InjectionScope;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.Methods;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+import static org.apache.polygene.api.util.Annotations.typeHasAnnotation;
+
+/**
+ * JAVADOC
+ */
+public final class InjectedMethodsModel
+    implements Dependencies, VisitableHierarchy<Object, Object>
+{
+    // Model
+    private final List<InjectedMethodModel> methodModels = new ArrayList<>();
+
+    public InjectedMethodsModel( Class fragmentClass )
+    {
+        Methods.methodsOf( fragmentClass ).forEach( method -> {
+            Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+            if( parameterAnnotations.length > 0 )
+            {
+                InjectedParametersModel parametersModel = new InjectedParametersModel();
+                final Type[] genericParameterTypes = method.getGenericParameterTypes();
+                boolean found = true;
+                for( int i = 0; i < parameterAnnotations.length; i++ )
+                {
+                    Optional<Annotation> opt = Arrays.stream( parameterAnnotations[ i ] )
+                        .filter( typeHasAnnotation( InjectionScope.class ) )
+                        .findFirst();
+                    if( opt.isPresent() )
+                    {
+                        Annotation injectionAnnotation = opt.get();
+                        Type genericType = genericParameterTypes[ i ];
+                        if( genericType instanceof ParameterizedType )
+                        {
+                            genericType = createParameterizedTypeInstance( (ParameterizedType) genericType );
+
+                            for( int j = 0; j < ( (ParameterizedType) genericType ).getActualTypeArguments().length; j++ )
+                            {
+                                Type type = ( (ParameterizedType) genericType ).getActualTypeArguments()[ j ];
+                                if( type instanceof TypeVariable )
+                                {
+                                    type = Classes.resolveTypeVariable( (TypeVariable) type, method.getDeclaringClass(), fragmentClass );
+                                    ( (ParameterizedType) genericType ).getActualTypeArguments()[ j ] = type;
+                                }
+                            }
+                        }
+                        boolean optional = DependencyModel.isOptional( injectionAnnotation, parameterAnnotations[ i ] );
+                        DependencyModel dependencyModel = new DependencyModel( injectionAnnotation, genericType, fragmentClass, optional, parameterAnnotations[ i ] );
+                        parametersModel.addDependency( dependencyModel );
+                    }
+                    else
+                    {
+                        found = false;
+                        break;
+                    }
+                }
+                if( found )
+                {
+                    methodModels.add( new InjectedMethodModel( method, parametersModel ) );
+                }
+            }
+        } );
+    }
+
+    @PostConstruct
+    private Type createParameterizedTypeInstance( ParameterizedType genericType )
+    {
+        return new ParameterizedTypeInstance(
+            genericType.getActualTypeArguments(), genericType.getRawType(), genericType.getOwnerType()
+        );
+    }
+
+    @Override
+    public Stream<DependencyModel> dependencies()
+    {
+        return methodModels.stream().flatMap( InjectedMethodModel::dependencies );
+    }
+
+    // Context
+    public void inject( InjectionContext context, Object instance )
+    {
+        for( InjectedMethodModel methodModel : methodModels )
+        {
+            methodModel.inject( context, instance );
+        }
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( InjectedMethodModel methodModel : methodModels )
+            {
+                if( !methodModel.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedParametersModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedParametersModel.java
new file mode 100644
index 0000000..82ccd20
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedParametersModel.java
@@ -0,0 +1,95 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.InjectedParametersDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * JAVADOC
+ */
+public final class InjectedParametersModel
+    implements InjectedParametersDescriptor, Dependencies, VisitableHierarchy<Object, Object>
+{
+    private final List<DependencyModel> parameterDependencies;
+
+    public InjectedParametersModel()
+    {
+        parameterDependencies = new ArrayList<>();
+    }
+
+    @Override
+    public Stream<DependencyModel> dependencies()
+    {
+        return parameterDependencies.stream();
+    }
+
+    // Context
+    public Object[] newParametersInstance( InjectionContext context )
+    {
+        Object[] parametersInstance = new Object[ parameterDependencies.size() ];
+
+        // Inject parameterDependencies
+        for( int j = 0; j < parameterDependencies.size(); j++ )
+        {
+            DependencyModel dependencyModel = parameterDependencies.get( j );
+            Object parameter = dependencyModel.inject( context );
+            parametersInstance[ j ] = parameter;
+        }
+
+        return parametersInstance;
+    }
+
+    public void addDependency( DependencyModel dependency )
+    {
+        parameterDependencies.add( dependency );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( DependencyModel parameterDependency : parameterDependencies )
+            {
+                if( !visitor.visit( parameterDependency ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "InjectedParametersModel{" +
+               "parameterDependencies=" + parameterDependencies +
+               '}';
+    }
+}
+
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionContext.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionContext.java
new file mode 100644
index 0000000..dd89d85
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionContext.java
@@ -0,0 +1,126 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.runtime.composite.ProxyReferenceInvocationHandler;
+import org.apache.polygene.runtime.composite.UsesInstance;
+
+/**
+ * JAVADOC
+ */
+public final class InjectionContext
+{
+    private final ModuleDescriptor module;
+    private CompositeInstance compositeInstance;
+    private UsesInstance uses;
+    private StateHolder state;
+    private Object next; // Only used for concerns and side-effects
+    private ProxyReferenceInvocationHandler proxyHandler;
+    private Object instance; // Only used for inner classes
+
+    // For mixins
+
+    public InjectionContext( CompositeInstance compositeInstance, UsesInstance uses, StateHolder state )
+    {
+        this.module = compositeInstance.module();
+        this.compositeInstance = compositeInstance;
+        this.uses = uses;
+        this.state = state;
+    }
+
+    // For concerns and side-effects
+    public InjectionContext( ModuleDescriptor module, Object next, ProxyReferenceInvocationHandler proxyHandler )
+    {
+        this.module = module;
+        this.next = next;
+        this.proxyHandler = proxyHandler;
+    }
+
+    public InjectionContext( ModuleDescriptor module, UsesInstance uses )
+    {
+        this.module = module;
+        this.uses = uses;
+    }
+
+    // For inner classes
+    public InjectionContext( ModuleDescriptor module, UsesInstance uses, Object instance )
+    {
+        this.module = module;
+        this.uses = uses;
+        this.instance = instance;
+    }
+
+    public ModuleDescriptor module()
+    {
+        return module;
+    }
+
+    public CompositeInstance compositeInstance()
+    {
+        return compositeInstance;
+    }
+
+    public UsesInstance uses()
+    {
+        return uses;
+    }
+
+    public StateHolder state()
+    {
+        return state;
+    }
+
+    public Object next()
+    {
+        return next;
+    }
+
+    public Object instance()
+    {
+        return instance;
+    }
+
+    public ProxyReferenceInvocationHandler proxyHandler()
+    {
+        return proxyHandler;
+    }
+
+    public void setUses( UsesInstance uses )
+    {
+        this.uses = uses;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "InjectionContext{" +
+               "compositeInstance=" + compositeInstance +
+               ", module=" + module +
+               ", uses=" + uses +
+               ", state=" + state +
+               ", next=" + next +
+               ", proxyHandler=" + proxyHandler +
+               '}';
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProvider.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProvider.java
new file mode 100644
index 0000000..a21a352
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProvider.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import org.apache.polygene.runtime.injection.provider.InjectionProviderException;
+
+/**
+ * JAVADOC
+ */
+public interface InjectionProvider
+{
+    Object provideInjection( InjectionContext context )
+        throws InjectionProviderException;
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProviderFactory.java
new file mode 100644
index 0000000..8671d4c
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProviderFactory.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public interface InjectionProviderFactory
+{
+    /**
+     * Binding a dependency given an injection resolution. If no binding
+     * can be found, return null. If the dependency is optional the dependency will
+     * then be explicitly set to null.
+     *
+     * @param resolution Injection resolution
+     * @param dependencyModel Dependency model
+     * @return InjectionProvider
+     * @throws InvalidInjectionException if the injection is invalid
+     */
+    InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+        throws InvalidInjectionException;
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/ParameterizedTypeInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/ParameterizedTypeInstance.java
new file mode 100644
index 0000000..d1f2bc7
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/ParameterizedTypeInstance.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+
+/**
+ * TODO
+ */
+public class ParameterizedTypeInstance
+    implements ParameterizedType
+{
+    private Type[] actualTypeArguments;
+    private Type rawType;
+    private Type ownerType;
+
+    public ParameterizedTypeInstance( Type[] actualTypeArguments, Type rawType, Type ownerType )
+    {
+        this.actualTypeArguments = actualTypeArguments;
+        this.rawType = rawType;
+        this.ownerType = ownerType;
+    }
+
+    @Override
+    public Type[] getActualTypeArguments()
+    {
+        return actualTypeArguments;
+    }
+
+    @Override
+    public Type getRawType()
+    {
+        return rawType;
+    }
+
+    @Override
+    public Type getOwnerType()
+    {
+        return ownerType;
+    }
+
+    @Override
+    public String toString()
+    {
+        return rawType.toString() + Arrays.asList( actualTypeArguments );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderDecorator.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderDecorator.java
new file mode 100644
index 0000000..3339a48
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderDecorator.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.runtime.injection.provider;
+
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+
+/**
+ * If a dependency resolution should be a singleton, wrap it with this
+ * to provide a single instance "cache".
+ */
+public final class CachingInjectionProviderDecorator
+    implements InjectionProvider
+{
+    private final InjectionProvider decoratedProvider;
+    private volatile Object singletonInstance;
+
+    public CachingInjectionProviderDecorator( InjectionProvider injectionProvider )
+    {
+        this.decoratedProvider = injectionProvider;
+    }
+
+    public InjectionProvider decoratedProvider()
+    {
+        return decoratedProvider;
+    }
+
+    @Override
+    public Object provideInjection( InjectionContext context )
+        throws InjectionProviderException
+    {
+        if( singletonInstance == null )
+        {
+            synchronized( this )
+            {
+                if( singletonInstance == null )
+                {
+                    singletonInstance = decoratedProvider.provideInjection( context );
+                }
+            }
+        }
+
+        return singletonInstance;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderFactoryDecorator.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderFactoryDecorator.java
new file mode 100644
index 0000000..3e0ea74
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderFactoryDecorator.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.runtime.injection.provider;
+
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public class CachingInjectionProviderFactoryDecorator
+    implements InjectionProviderFactory
+{
+    private final InjectionProviderFactory decoratedFactory;
+
+    public CachingInjectionProviderFactoryDecorator( InjectionProviderFactory decoratedFactory )
+    {
+        this.decoratedFactory = decoratedFactory;
+    }
+
+    @Override
+    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        InjectionProvider injectionProvider = decoratedFactory.newInjectionProvider( resolution, dependencyModel );
+        if( injectionProvider != null )
+        {
+            return new CachingInjectionProviderDecorator( injectionProvider );
+        }
+        else
+        {
+            return null;
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderException.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderException.java
new file mode 100644
index 0000000..43a8872
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderException.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.runtime.injection.provider;
+
+/**
+ * JAVADOC
+ */
+public class InjectionProviderException
+    extends RuntimeException
+{
+    public InjectionProviderException( String string )
+    {
+        super( string );
+    }
+
+    public InjectionProviderException( String string, Throwable throwable )
+    {
+        super( string, throwable );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderFactoryStrategy.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderFactoryStrategy.java
new file mode 100644
index 0000000..38bc5ba
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderFactoryStrategy.java
@@ -0,0 +1,106 @@
+/*
+ *  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.polygene.runtime.injection.provider;
+
+import java.lang.annotation.Annotation;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.composite.InvalidValueCompositeException;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.concern.internal.ConcernFor;
+import org.apache.polygene.api.injection.scope.Invocation;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.sideeffect.internal.SideEffectFor;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class InjectionProviderFactoryStrategy
+    implements InjectionProviderFactory
+{
+    private final Map<Class<? extends Annotation>, InjectionProviderFactory> generalProviderFactories = new HashMap<>();
+    private final Map<Class<? extends Annotation>, InjectionProviderFactory> valuesProviderFactories = new HashMap<>();
+    private MetaInfo metaInfo;
+
+    public InjectionProviderFactoryStrategy( MetaInfo metaInfo )
+    {
+        this.metaInfo = metaInfo;
+        valuesProviderFactories.put( This.class, new ThisInjectionProviderFactory() );
+        ModifiesInjectionProviderFactory modifiesInjectionProviderFactory = new ModifiesInjectionProviderFactory();
+        valuesProviderFactories.put( ConcernFor.class, modifiesInjectionProviderFactory );
+        valuesProviderFactories.put( SideEffectFor.class, modifiesInjectionProviderFactory );
+        valuesProviderFactories.put( State.class, new StateInjectionProviderFactory() );
+
+        valuesProviderFactories.put( Structure.class, new CachingInjectionProviderFactoryDecorator( new StructureInjectionProviderFactory() ) );
+        valuesProviderFactories.put( Service.class, new CachingInjectionProviderFactoryDecorator( new ServiceInjectionProviderFactory() ) );
+        generalProviderFactories.put( Invocation.class, new InvocationInjectionProviderFactory() );
+        generalProviderFactories.put( Uses.class, new UsesInjectionProviderFactory() );
+    }
+
+    @Override
+    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        Class<? extends Annotation> injectionAnnotationType = dependencyModel.injectionAnnotation().annotationType();
+        InjectionProviderFactory factory1 = generalProviderFactories.get( injectionAnnotationType );
+        InjectionProviderFactory factory2 = valuesProviderFactories.get( injectionAnnotationType );
+        if( factory1 == null && factory2 == null )
+        {
+            InjectionProviderFactory factory = metaInfo.get( InjectionProviderFactory.class );
+            if( factory != null )
+            {
+                return factory.newInjectionProvider( resolution, dependencyModel );
+            }
+            else
+            {
+                throw new InvalidInjectionException( "Unknown injection annotation @" + injectionAnnotationType.getSimpleName() );
+            }
+        }
+        ModelDescriptor composite = resolution.model();
+        Class<?> compositeType = composite.types().findFirst().orElse( null );
+        if( factory1 != null && ValueComposite.class.isAssignableFrom( compositeType ) )
+        {
+            throw new InvalidValueCompositeException( "@" + injectionAnnotationType.getSimpleName() + " is not allowed in ValueComposites: " + compositeType );
+        }
+
+        InjectionProviderFactory factory;
+        if( factory1 == null )
+        {
+            factory = factory2;
+        }
+        else
+        {
+            factory = factory1;
+        }
+        return factory.newInjectionProvider( resolution, dependencyModel );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InvocationInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InvocationInjectionProviderFactory.java
new file mode 100644
index 0000000..0db94d6
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InvocationInjectionProviderFactory.java
@@ -0,0 +1,117 @@
+/*
+ *  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.polygene.runtime.injection.provider;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.composite.CompositeMethodModel;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class InvocationInjectionProviderFactory
+    implements InjectionProviderFactory
+{
+    @Override
+    @SuppressWarnings( "raw" )
+    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        Class injectionClass = Classes.RAW_CLASS.apply( dependencyModel.injectionType() );
+        if( injectionClass.equals( Method.class ) ||
+            injectionClass.equals( AnnotatedElement.class ) ||
+            injectionClass.equals( Iterable.class ) ||
+            Annotation.class.isAssignableFrom( injectionClass ) )
+        {
+            return new InvocationDependencyResolution( resolution, dependencyModel );
+        }
+        else
+        {
+            String injectedTo = dependencyModel.injectedClass().getName();
+            throw new InvalidInjectionException( "Invalid injection type " + injectionClass + " in " + injectedTo );
+        }
+    }
+
+    private static class InvocationDependencyResolution
+        implements InjectionProvider
+    {
+        private final Resolution resolution;
+        private final DependencyModel dependencyModel;
+
+        private InvocationDependencyResolution( Resolution resolution, DependencyModel dependencyModel )
+        {
+            this.resolution = resolution;
+            this.dependencyModel = dependencyModel;
+        }
+
+        @Override
+        @SuppressWarnings( {"raw", "unchecked"} )
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            Class injectionClass = Classes.RAW_CLASS.apply( dependencyModel.injectionType() );
+            final CompositeMethodModel methodModel = resolution.method();
+            if( injectionClass.equals( Method.class ) )
+            {
+                return methodModel.method();
+            }
+
+            final AnnotatedElement annotatedElement = methodModel.annotatedElement();
+            if( injectionClass.equals( AnnotatedElement.class ) )
+            {
+                return annotatedElement;
+            }
+            final Annotation annotation = annotatedElement.getAnnotation( injectionClass );
+            if( annotation != null )
+            {
+                return annotation;
+            }
+            if( dependencyModel.injectionType() instanceof Class<?> )
+            {
+                return annotatedElement.getAnnotation( (Class<Annotation>) dependencyModel.injectionType() );
+            }
+            if( dependencyModel.injectionType() instanceof ParameterizedType )
+            {
+                ParameterizedType injectionType = (ParameterizedType) dependencyModel.injectionType();
+                Type rawType = injectionType.getRawType();
+                Type[] actualTypeArguments = injectionType.getActualTypeArguments();
+                boolean isAnIterable = rawType.equals( Iterable.class );
+                boolean haveOneGenericType = actualTypeArguments.length == 1;
+                boolean thatIsOfTypeMethod = actualTypeArguments[ 0 ].equals( Method.class );
+                if( isAnIterable && haveOneGenericType && thatIsOfTypeMethod )
+                {
+                    Class<?> injectedClass = dependencyModel.injectedClass();
+                    return methodModel.invocationsFor( injectedClass );
+                }
+            }
+            return null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ModifiesInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ModifiesInjectionProviderFactory.java
new file mode 100644
index 0000000..b0f662b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ModifiesInjectionProviderFactory.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.runtime.injection.provider;
+
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class ModifiesInjectionProviderFactory
+    implements InjectionProviderFactory
+{
+    @Override
+    public InjectionProvider newInjectionProvider( Resolution bindingContext, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        if( bindingContext.model() instanceof CompositeDescriptor )
+        {
+            Class<?> type = Classes.RAW_CLASS.apply( dependencyModel.injectionType() );
+            if( type.isAssignableFrom( dependencyModel.injectedClass() ) )
+            {
+                return new ModifiedInjectionProvider();
+            }
+            else
+            {
+                throw new InvalidInjectionException( "Composite " + bindingContext.model() + " does not implement @ConcernFor type " + type
+                    .getName() + " in modifier " + dependencyModel.injectedClass().getName() );
+            }
+        }
+        else
+        {
+            throw new InvalidInjectionException( "The class " + dependencyModel.injectedClass()
+                .getName() + " is not a modifier" );
+        }
+    }
+
+    private static class ModifiedInjectionProvider
+        implements InjectionProvider
+    {
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            return context.next();
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ServiceInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ServiceInjectionProviderFactory.java
new file mode 100644
index 0000000..f3dc70c
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ServiceInjectionProviderFactory.java
@@ -0,0 +1,224 @@
+/*
+ *  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.polygene.runtime.injection.provider;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.service.NoSuchServiceException;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.service.qualifier.Qualifier;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+import static java.util.stream.Collectors.toCollection;
+import static org.apache.polygene.api.util.Annotations.typeHasAnnotation;
+
+public final class ServiceInjectionProviderFactory
+    implements InjectionProviderFactory
+{
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        // TODO This could be changed to allow multiple @Qualifier annotations
+        Annotation qualifierAnnotation = Stream.of( dependencyModel.annotations() )
+                                               .filter( typeHasAnnotation( Qualifier.class ) )
+                                               .findFirst().orElse( null );
+        Predicate<ServiceReference<?>> serviceQualifier = null;
+        if( qualifierAnnotation != null )
+        {
+            Qualifier qualifier = qualifierAnnotation.annotationType().getAnnotation( Qualifier.class );
+            try
+            {
+                serviceQualifier = qualifier.value().newInstance().qualifier( qualifierAnnotation );
+            }
+            catch( Exception e )
+            {
+                throw new InvalidInjectionException( "Could not instantiate qualifier serviceQualifier", e );
+            }
+        }
+
+        if( dependencyModel.rawInjectionType().equals( Iterable.class ) )
+        {
+            Type iterableType = ( (ParameterizedType) dependencyModel.injectionType() ).getActualTypeArguments()[ 0 ];
+            if( Classes.RAW_CLASS.apply( iterableType ).equals( ServiceReference.class ) )
+            {
+                // @Service Iterable<ServiceReference<MyService<Foo>> serviceRefs
+                Type serviceType = ( (ParameterizedType) iterableType ).getActualTypeArguments()[ 0 ];
+
+                return new IterableServiceReferenceProvider( serviceType, serviceQualifier );
+            }
+            else
+            {
+                // @Service Iterable<MyService<Foo>> services
+                return new IterableServiceProvider( iterableType, serviceQualifier );
+            }
+        }
+        else if( dependencyModel.rawInjectionType().equals( ServiceReference.class ) )
+        {
+            // @Service ServiceReference<MyService<Foo>> serviceRef
+            Type referencedType = ( (ParameterizedType) dependencyModel.injectionType() ).getActualTypeArguments()[ 0 ];
+            return new ServiceReferenceProvider( referencedType, serviceQualifier );
+        }
+        else
+        {
+            // @Service MyService<Foo> service
+            return new ServiceProvider( dependencyModel.injectionType(), serviceQualifier );
+        }
+    }
+
+    private static class IterableServiceReferenceProvider
+        extends ServiceInjectionProvider
+    {
+        private IterableServiceReferenceProvider( Type serviceType, Predicate<ServiceReference<?>> serviceQualifier )
+        {
+            super( serviceType, serviceQualifier );
+        }
+
+        @Override
+        public synchronized Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            return getServiceReferences( context ).collect( toCollection( ArrayList::new ) );
+        }
+    }
+
+    private static class IterableServiceProvider
+        extends ServiceInjectionProvider
+        implements Function<ServiceReference<?>, Object>
+    {
+        private IterableServiceProvider( Type serviceType, Predicate<ServiceReference<?>> serviceQualifier )
+        {
+            super( serviceType, serviceQualifier );
+        }
+
+        @Override
+        public synchronized Object provideInjection( final InjectionContext context )
+            throws InjectionProviderException
+        {
+            return getServiceReferences( context ).map( ServiceReference::get )
+                                                  .collect( toCollection( ArrayList::new ) );
+        }
+
+        @Override
+        public Object apply( ServiceReference<?> objectServiceReference )
+        {
+            return objectServiceReference.get();
+        }
+    }
+
+    private static class ServiceReferenceProvider
+        extends ServiceInjectionProvider
+    {
+        ServiceReferenceProvider( Type serviceType, Predicate<ServiceReference<?>> qualifier )
+        {
+            super( serviceType, qualifier );
+        }
+
+        @Override
+        public synchronized Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            return getServiceReference( context );
+        }
+    }
+
+    private static class ServiceProvider
+        extends ServiceInjectionProvider
+    {
+        ServiceProvider( Type serviceType, Predicate<ServiceReference<?>> qualifier )
+        {
+            super( serviceType, qualifier );
+        }
+
+        @Override
+        public synchronized Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            ServiceReference<?> ref = getServiceReference( context );
+
+            if( ref != null )
+            {
+                return ref.get();
+            }
+            else
+            {
+                return null;
+            }
+        }
+    }
+
+    public abstract static class ServiceInjectionProvider
+        implements InjectionProvider
+    {
+        private final Type serviceType;
+        private final Predicate<ServiceReference<?>> serviceQualifier;
+
+        private ServiceInjectionProvider( Type serviceType, Predicate<ServiceReference<?>> serviceQualifier )
+        {
+            this.serviceType = serviceType;
+            this.serviceQualifier = serviceQualifier;
+        }
+
+        protected ServiceReference<Object> getServiceReference( InjectionContext context )
+        {
+            try
+            {
+                if( serviceQualifier == null )
+                {
+                    return context.module().instance().findService( serviceType );
+                }
+                else
+                {
+                    return context.module().instance().findServices( serviceType )
+                                  .filter( serviceQualifier ).findFirst().orElse( null );
+                }
+            }
+            catch( NoSuchServiceException e )
+            {
+                return null;
+            }
+        }
+
+        protected Stream<ServiceReference<Object>> getServiceReferences( final InjectionContext context )
+        {
+            if( serviceQualifier == null )
+            {
+                return context.module().instance().findServices( serviceType );
+            }
+            else
+            {
+                return context.module().instance().findServices( serviceType ).filter( serviceQualifier );
+            }
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StateInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StateInjectionProviderFactory.java
new file mode 100644
index 0000000..3a3a80e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StateInjectionProviderFactory.java
@@ -0,0 +1,273 @@
+/*
+ *  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.polygene.runtime.injection.provider;
+
+import org.apache.polygene.api.association.AbstractAssociation;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.AssociationStateDescriptor;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.composite.StateDescriptor;
+import org.apache.polygene.api.composite.StatefulCompositeDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.entity.EntityInstance;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class StateInjectionProviderFactory
+    implements InjectionProviderFactory
+{
+    @Override
+    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        if( StateHolder.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+        {
+            // @State StateHolder properties;
+            return new StateInjectionProvider();
+        }
+        else if( UnitOfWork.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+        {
+            if( !( resolution.model() instanceof EntityDescriptor ) )
+            {
+                throw new InvalidInjectionException( "Only EntityComposites can be injected with '@State UnitOfWork'" );
+            }
+            return new UnitOfWorkInjectionProvider();
+        }
+        else if( Property.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+        {
+            // @State Property<String> name;
+            StateDescriptor descriptor;
+            descriptor = ( (StatefulCompositeDescriptor) resolution.model() ).state();
+
+            State annotation = (State) dependencyModel.injectionAnnotation();
+            String name;
+            if( annotation.value().isEmpty() )
+            {
+                name = resolution.field().getName();
+            }
+            else
+            {
+                name = annotation.value();
+            }
+
+            PropertyDescriptor propertyDescriptor = descriptor.findPropertyModelByName( name );
+            return new PropertyInjectionProvider( propertyDescriptor );
+        }
+        else if( Association.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+        {
+            // @State Association<MyEntity> name;
+            AssociationStateDescriptor descriptor = ( (EntityDescriptor) resolution.model() ).state();
+            State annotation = (State) dependencyModel.injectionAnnotation();
+            String name;
+            if( annotation.value().isEmpty() )
+            {
+                name = resolution.field().getName();
+            }
+            else
+            {
+                name = annotation.value();
+            }
+            AssociationDescriptor model = descriptor.getAssociationByName( name );
+            return new AssociationInjectionProvider( model );
+        }
+        else if( ManyAssociation.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+        {
+            // @State ManyAssociation<MyEntity> name;
+            AssociationStateDescriptor descriptor = ( (EntityDescriptor) resolution.model() ).state();
+            State annotation = (State) dependencyModel.injectionAnnotation();
+            String name;
+            if( annotation.value().isEmpty() )
+            {
+                name = resolution.field().getName();
+            }
+            else
+            {
+                name = annotation.value();
+            }
+            AssociationDescriptor model = descriptor.getManyAssociationByName( name );
+            return new ManyAssociationInjectionProvider( model );
+        }
+        else if( NamedAssociation.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+        {
+            // @State NamedAssociation<MyEntity> name;
+            AssociationStateDescriptor descriptor = ( (EntityDescriptor) resolution.model() ).state();
+            State annotation = (State) dependencyModel.injectionAnnotation();
+            String name;
+            if( annotation.value().isEmpty() )
+            {
+                name = resolution.field().getName();
+            }
+            else
+            {
+                name = annotation.value();
+            }
+            AssociationDescriptor model = descriptor.getNamedAssociationByName( name );
+            return new NamedAssociationInjectionProvider( model );
+        }
+
+        throw new InjectionProviderException( "Injected value has invalid type" );
+    }
+
+    private static class PropertyInjectionProvider
+        implements InjectionProvider
+    {
+        private final PropertyDescriptor propertyDescriptor;
+
+        private PropertyInjectionProvider( PropertyDescriptor propertyDescriptor )
+        {
+            this.propertyDescriptor = propertyDescriptor;
+        }
+
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            Property<?> value = context.state().propertyFor( propertyDescriptor.accessor() );
+            if( value != null )
+            {
+                return value;
+            }
+            else
+            {
+                throw new InjectionProviderException( "Non-optional property " + propertyDescriptor + " had no value" );
+            }
+        }
+    }
+
+    private static class AssociationInjectionProvider
+        implements InjectionProvider
+    {
+        private final AssociationDescriptor associationDescriptor;
+
+        private AssociationInjectionProvider( AssociationDescriptor associationDescriptor )
+        {
+            this.associationDescriptor = associationDescriptor;
+        }
+
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            AbstractAssociation abstractAssociation = ( (AssociationStateHolder) context.state() ).
+                associationFor( associationDescriptor.accessor() );
+            if( abstractAssociation != null )
+            {
+                return abstractAssociation;
+            }
+            else
+            {
+                throw new InjectionProviderException( "Non-optional association " + associationDescriptor.qualifiedName() + " had no association" );
+            }
+        }
+    }
+
+    private static class ManyAssociationInjectionProvider
+        implements InjectionProvider
+    {
+        private final AssociationDescriptor manyAssociationDescriptor;
+
+        private ManyAssociationInjectionProvider( AssociationDescriptor manyAssociationDescriptor )
+        {
+            this.manyAssociationDescriptor = manyAssociationDescriptor;
+        }
+
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            ManyAssociation<?> abstractAssociation = ( (AssociationStateHolder) context.state() ).
+                manyAssociationFor( manyAssociationDescriptor.accessor() );
+            if( abstractAssociation != null )
+            {
+                return abstractAssociation;
+            }
+            else
+            {
+                throw new InjectionProviderException( "Non-optional association " + manyAssociationDescriptor.qualifiedName() + " had no association" );
+            }
+        }
+    }
+
+    private static class NamedAssociationInjectionProvider
+        implements InjectionProvider
+    {
+        private final AssociationDescriptor namedAssociationDescriptor;
+
+        private NamedAssociationInjectionProvider( AssociationDescriptor namedAssociationDescriptor )
+        {
+            this.namedAssociationDescriptor = namedAssociationDescriptor;
+        }
+
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            NamedAssociation<?> abstractAssociation = ( (AssociationStateHolder) context.state() ).
+                namedAssociationFor( namedAssociationDescriptor.accessor() );
+            if( abstractAssociation != null )
+            {
+                return abstractAssociation;
+            }
+            else
+            {
+                throw new InjectionProviderException( "Non-optional association " + namedAssociationDescriptor.qualifiedName() + " had no association" );
+            }
+        }
+    }
+
+    static private class StateInjectionProvider
+        implements InjectionProvider
+    {
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            return context.state();
+        }
+    }
+
+    static private class UnitOfWorkInjectionProvider
+        implements InjectionProvider
+    {
+
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            return ( (EntityInstance) context.compositeInstance() ).unitOfWork();
+        }
+    }
+
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StructureInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StructureInjectionProviderFactory.java
new file mode 100644
index 0000000..0d20dab
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StructureInjectionProviderFactory.java
@@ -0,0 +1,129 @@
+/*
+ *  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.polygene.runtime.injection.provider;
+
+import java.lang.reflect.Type;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+import org.apache.polygene.runtime.structure.ApplicationInstance;
+
+public final class StructureInjectionProviderFactory
+    implements InjectionProviderFactory
+{
+    @Override
+    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        return new StructureInjectionProvider( dependencyModel );
+    }
+
+    private static class StructureInjectionProvider
+        implements InjectionProvider
+    {
+        private final DependencyModel dependencyModel;
+
+        private StructureInjectionProvider( DependencyModel dependencyModel )
+        {
+            this.dependencyModel = dependencyModel;
+        }
+
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            Type type1 = dependencyModel.injectionType();
+            if( !( type1 instanceof Class ) )
+            {
+                throw new InjectionProviderException( "Type [" + type1 + "] can not be injected from the @Structure injection scope: " + context );
+            }
+            Class clazz = (Class) type1;
+            if( clazz.equals( TransientBuilderFactory.class ) )
+            {
+                return context.module().instance();
+            }
+            else if( clazz.equals( ObjectFactory.class ) )
+            {
+                return context.module().instance();
+            }
+            else if( clazz.equals( ValueBuilderFactory.class ) )
+            {
+                return context.module().instance();
+            }
+            else if( clazz.equals( UnitOfWorkFactory.class ) )
+            {
+                return context.module().instance().unitOfWorkFactory();
+            }
+            else if( clazz.equals( QueryBuilderFactory.class ) )
+            {
+                return context.module().instance();
+            }
+            else if( clazz.equals( ServiceFinder.class ) )
+            {
+                return context.module().instance();
+            }
+            else if( Module.class.isAssignableFrom( clazz ) )
+            {
+                return context.module().instance();
+            }
+            else if( ModuleDescriptor.class.isAssignableFrom( clazz ) )
+            {
+                return context.module();
+            }
+            else if( Layer.class.isAssignableFrom( clazz ) )
+            {
+                return context.module().layer().instance();
+            }
+            else if( LayerDescriptor.class.isAssignableFrom( clazz ) )
+            {
+                return context.module().layer();
+            }
+            else if( Application.class.isAssignableFrom( clazz ) )
+            {
+                return context.module().layer().instance().application();
+            }
+            else if( ApplicationDescriptor.class.isAssignableFrom( clazz ) )
+            {
+                return context.module().layer().instance().application().descriptor();
+            }
+            else if( PolygeneAPI.class.isAssignableFrom( clazz ) )
+            {
+                return (( ApplicationInstance) context.module().layer().instance().application()).runtime();
+            }
+            return null;
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ThisInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ThisInjectionProviderFactory.java
new file mode 100644
index 0000000..161cfbd
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ThisInjectionProviderFactory.java
@@ -0,0 +1,130 @@
+/*
+ *  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.polygene.runtime.injection.provider;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.composite.ProxyGenerator;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class ThisInjectionProviderFactory
+    implements InjectionProviderFactory
+{
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public InjectionProvider newInjectionProvider( Resolution bindingContext, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        if( bindingContext.model() instanceof CompositeDescriptor )
+        {
+            // If Composite type then return real type, otherwise use the specified one
+            final Class<?> thisType = dependencyModel.rawInjectionType();
+
+            Stream<Class<?>> injectionTypes;
+            if( Classes.assignableTypeSpecification( thisType ).test( bindingContext.model() ) )
+            {
+                injectionTypes = bindingContext.model().types();
+            }
+            else
+            {
+                CompositeDescriptor acd = ( (CompositeDescriptor) bindingContext.model() );
+                injectionTypes = acd.mixinTypes().filter( thisType::isAssignableFrom );
+            }
+
+            List<Class<?>> classes = injectionTypes.collect( Collectors.toList() );
+            if( classes.size() == 0 )
+            {
+                throw new InvalidInjectionException( "Composite " + bindingContext.model()
+                                                     + " does not implement @This type " + thisType.getName() + " in fragment "
+                                                     + dependencyModel.injectedClass().getName() );
+            }
+            return new ThisInjectionProvider( classes );
+        }
+        else
+        {
+            throw new InvalidInjectionException( "Object " + dependencyModel.injectedClass() + " may not use @This" );
+        }
+    }
+
+    @SuppressWarnings( { "raw", "unchecked" } )
+    private static class ThisInjectionProvider
+        implements InjectionProvider
+    {
+        Constructor proxyConstructor;
+        private Class[] interfaces;
+
+        private ThisInjectionProvider( List<Class<?>> types )
+        {
+            try
+            {
+                Class proxyClass;
+                Class<?> mainType = types.get( 0 );
+                if( Proxy.class.isAssignableFrom( mainType ) )
+                {
+                    proxyClass = mainType;
+                }
+                else
+                {
+                    interfaces = types.stream().map( Class.class::cast ).toArray( Class[]::new );
+                    proxyClass = ProxyGenerator.createProxyClass( mainType.getClassLoader(), interfaces );
+                }
+
+                proxyConstructor = proxyClass.getConstructor( InvocationHandler.class );
+            }
+            catch( Exception e )
+            {
+                // Ignore
+                e.printStackTrace();
+            }
+        }
+
+        @Override
+        public Object provideInjection( InjectionContext context )
+        {
+            try
+            {
+                InvocationHandler handler = context.compositeInstance();
+                if( handler == null )
+                {
+                    handler = context.proxyHandler();
+                }
+                return proxyConstructor.newInstance( handler );
+            }
+            catch( Exception e )
+            {
+                throw new InjectionProviderException( "Could not instantiate @This proxy", e );
+            }
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/UsesInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/UsesInjectionProviderFactory.java
new file mode 100644
index 0000000..6b21d29
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/UsesInjectionProviderFactory.java
@@ -0,0 +1,130 @@
+/*
+ *  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.polygene.runtime.injection.provider;
+
+import java.lang.reflect.Constructor;
+import org.apache.polygene.api.composite.NoSuchTransientException;
+import org.apache.polygene.api.object.NoSuchObjectException;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.util.AccessibleObjects;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.composite.UsesInstance;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class UsesInjectionProviderFactory
+    implements InjectionProviderFactory
+{
+    public UsesInjectionProviderFactory()
+    {
+    }
+
+    @Override
+    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        return new UsesInjectionProvider( dependencyModel );
+    }
+
+    private static class UsesInjectionProvider
+        implements InjectionProvider
+    {
+        private final DependencyModel dependency;
+
+        public UsesInjectionProvider( DependencyModel dependency )
+        {
+            this.dependency = dependency;
+        }
+
+        @SuppressWarnings( "unchecked" )
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            UsesInstance uses = context.uses();
+
+            Class injectionType = dependency.rawInjectionType();
+            Object usesObject = uses.useForType( injectionType );
+
+            if( usesObject == null && !dependency.optional() )
+            {
+                // No @Uses object provided
+                // Try instantiating a Transient or Object for the given type
+                Module moduleInstance = context.module().instance();
+
+                try
+                {
+                    if( context.instance() != null )
+                    {
+                        uses = uses.use( context.instance() );
+                    }
+                    usesObject = moduleInstance.newTransient( injectionType, uses.toArray() );
+                }
+                catch( NoSuchTransientException e )
+                {
+                    try
+                    {
+                        usesObject = moduleInstance.newObject( injectionType, uses.toArray() );
+                    }
+                    catch( NoSuchObjectException e1 )
+                    {
+                        // Could not instantiate an instance - to try instantiate as plain class
+                        try
+                        {
+                            usesObject = injectionType.newInstance();
+                        }
+                        catch( Throwable e2 )
+                        {
+                            // Could not instantiate - try with this as first argument
+                            try
+                            {
+                                Constructor constructor = injectionType.getDeclaredConstructor( context.instance()
+                                                                                                    .getClass() );
+                                AccessibleObjects.accessible( constructor );
+                                usesObject = constructor.newInstance( context.instance() );
+                            }
+                            catch( Throwable e3 )
+                            {
+                                // Really can't instantiate it - ignore
+                            }
+                        }
+                    }
+                }
+
+                if( usesObject != null )
+                {
+                    context.setUses( context.uses().use( usesObject ) ); // Use this for other injections in same graph
+                }
+
+                return usesObject;
+            }
+            else
+            {
+                return usesObject;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/internal/Activator.java b/core/runtime/src/main/java/org/apache/polygene/runtime/internal/Activator.java
new file mode 100644
index 0000000..bf52dd8
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/internal/Activator.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.runtime.internal;
+
+import org.apache.polygene.bootstrap.RuntimeFactory;
+import org.apache.polygene.runtime.PolygeneRuntimeImpl;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ *
+ */
+public class Activator
+    implements BundleActivator
+{
+    private ServiceRegistration registration;
+
+    @Override
+    public void start( BundleContext bundleContext )
+        throws Exception
+    {
+        RuntimeFactory factory = PolygeneRuntimeImpl::new;
+        registration = bundleContext.registerService( RuntimeFactory.class.getName(), factory, null );
+    }
+
+    @Override
+    public void stop( BundleContext bundleContext )
+        throws Exception
+    {
+        registration.unregister();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/model/Binder.java b/core/runtime/src/main/java/org/apache/polygene/runtime/model/Binder.java
new file mode 100644
index 0000000..c59cc96
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/model/Binder.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.runtime.model;
+
+import org.apache.polygene.bootstrap.BindingException;
+
+/**
+ * Interface for models that can understand binding of dependencies
+ */
+public interface Binder
+{
+    void bind( Resolution resolution )
+        throws BindingException;
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/model/Resolution.java b/core/runtime/src/main/java/org/apache/polygene/runtime/model/Resolution.java
new file mode 100644
index 0000000..f5ff0f5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/model/Resolution.java
@@ -0,0 +1,92 @@
+/*
+ *  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.polygene.runtime.model;
+
+import java.lang.reflect.Field;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.runtime.composite.CompositeMethodModel;
+import org.apache.polygene.runtime.structure.ApplicationModel;
+import org.apache.polygene.runtime.structure.LayerModel;
+import org.apache.polygene.runtime.structure.ModuleModel;
+
+/**
+ * JAVADOC
+ */
+public final class Resolution
+{
+    private final ApplicationModel application;
+    private final LayerModel layer;
+    private final ModuleModel module;
+    private final ModelDescriptor modelDescriptor;
+    private final CompositeMethodModel method;
+    private final Field field;
+
+    public Resolution( ApplicationModel application,
+                       LayerModel layer,
+                       ModuleModel module,
+                       ModelDescriptor modelDescriptor,
+                       CompositeMethodModel method,
+                       Field field
+    )
+    {
+        this.application = application;
+        this.layer = layer;
+        this.module = module;
+        this.modelDescriptor = modelDescriptor;
+        this.method = method;
+        this.field = field;
+    }
+
+    public ApplicationModel application()
+    {
+        return application;
+    }
+
+    public LayerModel layer()
+    {
+        return layer;
+    }
+
+    public ModuleModel module()
+    {
+        return module;
+    }
+
+    public ModelDescriptor model()
+    {
+        return modelDescriptor;
+    }
+
+    public CompositeMethodModel method()
+    {
+        return method;
+    }
+
+    public Field field()
+    {
+        return field;
+    }
+
+    public Resolution forField( final Field injectedField )
+    {
+        return new Resolution( application, layer, module, modelDescriptor, method, injectedField );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectModel.java
new file mode 100644
index 0000000..c1a3dbf
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectModel.java
@@ -0,0 +1,158 @@
+/*
+ *  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.polygene.runtime.object;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.mixin.InitializationException;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.composite.ConstructorsModel;
+import org.apache.polygene.runtime.injection.InjectedFieldsModel;
+import org.apache.polygene.runtime.injection.InjectedMethodsModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+
+/**
+ * JAVADOC
+ */
+public final class ObjectModel
+    implements ObjectDescriptor, VisitableHierarchy<Object, Object>
+{
+    private final ModuleDescriptor module;
+    private final Class<?> objectType;
+    private final Visibility visibility;
+    private final MetaInfo metaInfo;
+    private final ConstructorsModel constructorsModel;
+    private final InjectedFieldsModel injectedFieldsModel;
+    private final InjectedMethodsModel injectedMethodsModel;
+
+    public ObjectModel( ModuleDescriptor module,
+                        Class<?> objectType,
+                        Visibility visibility,
+                        MetaInfo metaInfo
+    )
+    {
+        this.module = module;
+        this.objectType = objectType;
+        this.visibility = visibility;
+        this.metaInfo = metaInfo;
+
+        constructorsModel = new ConstructorsModel( objectType );
+        injectedFieldsModel = new InjectedFieldsModel( objectType );
+        injectedMethodsModel = new InjectedMethodsModel( objectType );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public Stream<Class<?>> types()
+    {
+        return Stream.of( objectType );
+    }
+
+    @Override
+    public Visibility visibility()
+    {
+        return visibility;
+    }
+
+    @Override
+    public ModuleDescriptor module()
+    {
+        return module;
+    }
+
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return metaInfo.get( infoType );
+    }
+
+    @Override
+    public boolean isAssignableTo( Class<?> type )
+    {
+        return type.isAssignableFrom( objectType );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            if( constructorsModel.accept( visitor ) )
+            {
+                if( injectedFieldsModel.accept( visitor ) )
+                {
+                    injectedMethodsModel.accept( visitor );
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public Object newInstance( InjectionContext injectionContext )
+    {
+        Object instance;
+        try
+        {
+            instance = constructorsModel.newInstance( injectionContext );
+            injectionContext = new InjectionContext( injectionContext.module(), injectionContext.uses(), instance );
+            injectedFieldsModel.inject( injectionContext, instance );
+            injectedMethodsModel.inject( injectionContext, instance );
+        }
+        catch( Exception e )
+        {
+            throw new ConstructionException( "Could not instantiate " + objectType.getName(), e );
+        }
+
+        if( instance instanceof Initializable )
+        {
+            try
+            {
+                ( (Initializable) instance ).initialize();
+            }
+            catch( Exception e )
+            {
+                String message = "Unable to initialize " + objectType;
+                throw new ConstructionException( new InitializationException( message, e ) );
+            }
+        }
+
+        return instance;
+    }
+
+    public void inject( InjectionContext injectionContext, Object instance )
+    {
+        injectedFieldsModel.inject( injectionContext, instance );
+        injectedMethodsModel.inject( injectionContext, instance );
+    }
+
+    @Override
+    public String toString()
+    {
+        return objectType.getName();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectsModel.java
new file mode 100644
index 0000000..84d2c11
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectsModel.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.runtime.object;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * JAVADOC
+ */
+public class ObjectsModel
+    implements VisitableHierarchy<Object, Object>
+{
+    private final List<ObjectModel> objectModels;
+
+    public ObjectsModel( List<ObjectModel> objectModels )
+    {
+        this.objectModels = objectModels;
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( ObjectModel objectModel : objectModels )
+            {
+                if( !objectModel.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public Stream<ObjectModel> models()
+    {
+        return objectModels.stream();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/package.html b/core/runtime/src/main/java/org/apache/polygene/runtime/package.html
new file mode 100644
index 0000000..1ed6d55
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Apache Polygene™ Runtime.</h2>
+    </body>
+</html>
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertiesModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertiesModel.java
new file mode 100644
index 0000000..cfcfcb5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertiesModel.java
@@ -0,0 +1,107 @@
+/*
+ *  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.polygene.runtime.property;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * Base class for properties model
+ */
+public class PropertiesModel
+    implements VisitableHierarchy<Object, Object>
+{
+    protected final Map<AccessibleObject, PropertyModel> mapAccessiblePropertyModel = new LinkedHashMap<>();
+
+    public PropertiesModel()
+    {
+    }
+
+    public void addProperty( PropertyModel property )
+    {
+        mapAccessiblePropertyModel.put( property.accessor(), property );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( PropertyModel propertyModel : mapAccessiblePropertyModel.values() )
+            {
+                if( !propertyModel.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+
+        return visitor.visitLeave( this );
+    }
+
+    public Stream<PropertyModel> properties()
+    {
+        return mapAccessiblePropertyModel.values().stream();
+    }
+
+    public PropertyModel getProperty( AccessibleObject accessor )
+    {
+        PropertyModel propertyModel = mapAccessiblePropertyModel.get( accessor );
+        if( propertyModel == null )
+        {
+            throw new IllegalArgumentException( "No property found with name: " + ( (Member) accessor ).getName() );
+        }
+
+        return propertyModel;
+    }
+
+    public PropertyModel getPropertyByName( String name )
+        throws IllegalArgumentException
+    {
+        for( PropertyModel propertyModel : mapAccessiblePropertyModel.values() )
+        {
+            if( propertyModel.qualifiedName().name().equals( name ) )
+            {
+                return propertyModel;
+            }
+        }
+        throw new IllegalArgumentException( "No property found with name: " + name );
+    }
+
+    public PropertyModel getPropertyByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException
+    {
+        for( PropertyModel propertyModel : mapAccessiblePropertyModel.values() )
+        {
+            if( propertyModel.qualifiedName().equals( name ) )
+            {
+                return propertyModel;
+            }
+        }
+        throw new IllegalArgumentException( "No property found with qualified name: " + name );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInfo.java b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInfo.java
new file mode 100644
index 0000000..fa8e1e6
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInfo.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.runtime.property;
+
+import java.lang.reflect.Type;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.runtime.composite.ConstraintsCheck;
+
+/**
+ * TODO
+ */
+public interface PropertyInfo
+    extends ConstraintsCheck
+{
+    boolean isImmutable();
+
+    QualifiedName qualifiedName();
+
+    Type type();
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInstance.java
new file mode 100644
index 0000000..4ea4ea3
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInstance.java
@@ -0,0 +1,364 @@
+/*
+ *  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.polygene.runtime.property;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.property.PropertyWrapper;
+import org.apache.polygene.api.type.CollectionType;
+import org.apache.polygene.api.type.MapType;
+import org.apache.polygene.api.type.ValueCompositeType;
+import org.apache.polygene.runtime.value.ValueInstance;
+
+import static org.apache.polygene.api.composite.CompositeInstance.compositeInstanceOf;
+
+/**
+ * {@code PropertyInstance} represents a property.
+ */
+public class PropertyInstance<T>
+    implements Property<T>
+{
+    protected volatile T value;
+    protected PropertyInfo model;
+
+    /**
+     * Construct an instance of {@code PropertyInstance} with the specified arguments.
+     *
+     * @param model  The property model. This argument must not be {@code null}.
+     * @param aValue The property value.
+     */
+    public PropertyInstance( PropertyInfo model, T aValue )
+    {
+        this.model = model;
+        value = aValue;
+    }
+
+    public PropertyInfo propertyInfo()
+    {
+        return model;
+    }
+
+    /**
+     * @param model The property model. This argument must not be {@code null}.
+     */
+    public void setPropertyInfo( PropertyInfo model )
+    {
+        this.model = model;
+    }
+
+    /**
+     * Returns this property value.
+     *
+     * @return This property value.
+     */
+    @Override
+    public T get()
+    {
+        return value;
+    }
+
+    /**
+     * Sets this property value.
+     *
+     * @param aNewValue The new value.
+     */
+    @Override
+    public void set( T aNewValue )
+    {
+        if( model.isImmutable() )
+        {
+            throw new IllegalStateException( "Property [" + model.qualifiedName() + "] is immutable." );
+        }
+
+        model.checkConstraints( aNewValue );
+
+        value = aNewValue;
+    }
+
+    /**
+     * Perform equals with {@code o} argument.
+     * <p>
+     *     The definition of equals() for the Property is that if both the state and descriptor are equal,
+     *     then the properties are equal.
+     * </p>
+     *
+     * @param o The other object to compare.
+     * @return Returns a {@code boolean} indicator whether this object is equals the other.
+     */
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        Property<?> that = (Property<?>) o;
+        // Unwrap if needed
+        while( that instanceof PropertyWrapper )
+        {
+            that = ( (PropertyWrapper) that ).next();
+        }
+        // Descriptor equality
+        PropertyDescriptor thatDescriptor = (PropertyDescriptor) ( (PropertyInstance) that ).propertyInfo();
+        if( !model.equals( thatDescriptor ) )
+        {
+            return false;
+        }
+        // State equality
+        T value = get();
+        if( value == null )
+        {
+            return that.get() == null;
+        }
+        Class<?> valueClass = value.getClass();
+        // Handling arrays
+        if( valueClass.isArray() )
+        {
+            Object thatValue = that.get();
+            if( !thatValue.getClass().isArray() )
+            {
+                return false;
+            }
+            Class<?> componentType = valueClass.getComponentType();
+            if( boolean.class.equals( componentType ) )
+            {
+                return Arrays.equals( (boolean[]) value, (boolean[]) thatValue );
+            }
+            if( char.class.equals( componentType ) )
+            {
+                return Arrays.equals( (char[]) value, (char[]) thatValue );
+            }
+            if( short.class.equals( componentType ) )
+            {
+                return Arrays.equals( (short[]) value, (short[]) thatValue );
+            }
+            if( int.class.equals( componentType ) )
+            {
+                return Arrays.equals( (int[]) value, (int[]) thatValue );
+            }
+            if( byte.class.equals( componentType ) )
+            {
+                return Arrays.equals( (byte[]) value, (byte[]) thatValue );
+            }
+            if( long.class.equals( componentType ) )
+            {
+                return Arrays.equals( (long[]) value, (long[]) thatValue );
+            }
+            if( float.class.equals( componentType ) )
+            {
+                return Arrays.equals( (float[]) value, (float[]) thatValue );
+            }
+            if( double.class.equals( componentType ) )
+            {
+                return Arrays.equals( (double[]) value, (double[]) thatValue );
+            }
+            return Arrays.deepEquals( (Object[]) value, (Object[]) thatValue );
+        }
+        return value.equals( that.get() );
+    }
+
+    /**
+     * Calculate hash code.
+     *
+     * @return the hashcode of this instance.
+     */
+    @Override
+    public int hashCode()
+    {
+        int hash = model.hashCode() * 19; // Descriptor
+        T value = get();
+        if( value != null )
+        {
+            hash += value.hashCode() * 13; // State
+        }
+        return hash;
+    }
+
+    /**
+     * Returns the value as string.
+     *
+     * @return The value as string.
+     */
+    @Override
+    public String toString()
+    {
+        Object value = get();
+        return value == null ? "" : value.toString();
+    }
+
+    @SuppressWarnings( {"raw", "unchecked"} )
+    public void prepareToBuild( PropertyModel propertyDescriptor )
+    {
+        // Check if state has to be modified
+        model = propertyDescriptor.getBuilderInfo();
+        if( propertyDescriptor.valueType() instanceof ValueCompositeType )
+        {
+            Object value = get();
+            if( value != null )
+            {
+                prepareToBuild( value );
+            }
+        }
+        else if( propertyDescriptor.valueType() instanceof CollectionType )
+        {
+            Object value = get();
+
+            if( value != null )
+            {
+                if( value instanceof List )
+                {
+                    value = new ArrayList( (Collection) value );
+                }
+                else if( value instanceof Set )
+                {
+                    value = new LinkedHashSet( (Collection) value );
+                }
+
+                // Check if items are Values
+                CollectionType collection = (CollectionType) propertyDescriptor.valueType();
+                if( collection.collectedType() instanceof ValueCompositeType )
+                {
+                    Collection coll = (Collection) value;
+                    coll.forEach( this::prepareToBuild );
+                }
+
+                set( (T) value );
+            }
+        }
+        else if( propertyDescriptor.valueType() instanceof MapType )
+        {
+            Object value = get();
+
+            if( value != null )
+            {
+                Map map = new LinkedHashMap( (Map) value );
+
+                // Check if keys/values are Values
+                MapType mapType = (MapType) propertyDescriptor.valueType();
+                if( mapType.keyType() instanceof ValueCompositeType )
+                {
+                    map.keySet().forEach( this::prepareToBuild );
+                }
+                if( mapType.valueType() instanceof ValueCompositeType )
+                {
+                    map.values().forEach( this::prepareToBuild );
+                }
+                set( (T) value );
+            }
+        }
+    }
+
+    private void prepareToBuild( Object instance )
+    {
+        ( (ValueInstance) compositeInstanceOf( (Composite) instance ) ).prepareToBuild();
+    }
+
+    @SuppressWarnings( {"raw", "unchecked"} )
+    public void prepareBuilderState( PropertyModel propertyDescriptor )
+    {
+        // Check if state has to be modified
+        if( propertyDescriptor.valueType() instanceof ValueCompositeType )
+        {
+            Object value = get();
+            if( value != null )
+            {
+                prepareBuilderState( value );
+            }
+        }
+        else if( propertyDescriptor.valueType() instanceof CollectionType )
+        {
+            T value = get();
+            if( value != null )
+            {
+                if( propertyDescriptor.isImmutable() )
+                {
+                    if( value instanceof List )
+                    {
+                        value = (T) Collections.unmodifiableList( (List<?>) value );
+                    }
+                    else if( value instanceof Set )
+                    {
+                        value = (T) Collections.unmodifiableSet( (Set<?>) value );
+                    }
+                    else
+                    {
+                        value = (T) Collections.unmodifiableCollection( (Collection<?>) value );
+                    }
+
+                    this.value = value;
+                }
+
+                CollectionType collection = (CollectionType) propertyDescriptor.valueType();
+                if( collection.collectedType() instanceof ValueCompositeType )
+                {
+                    Collection coll = (Collection) value;
+                    coll.forEach( this::prepareBuilderState );
+                }
+            }
+        }
+        else if( propertyDescriptor.valueType() instanceof MapType )
+        {
+            T value = get();
+
+            if( value != null )
+            {
+                MapType mapType = (MapType) propertyDescriptor.valueType();
+                if( mapType.keyType() instanceof ValueCompositeType )
+                {
+                    Map map = (Map) value;
+                    map.keySet().forEach( this::prepareBuilderState );
+                }
+                if( mapType.valueType() instanceof ValueCompositeType )
+                {
+                    Map map = (Map) value;
+                    map.values().forEach( this::prepareBuilderState );
+                }
+                if( propertyDescriptor.isImmutable() )
+                {
+                    value = (T) Collections.unmodifiableMap( (Map<?, ?>) value );
+                }
+
+                this.value = value;
+            }
+        }
+
+        model = propertyDescriptor;
+    }
+
+    private void prepareBuilderState( Object value )
+    {
+        ( (ValueInstance) compositeInstanceOf( (Composite) value ) ).prepareBuilderState();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyModel.java
new file mode 100644
index 0000000..79f7ae9
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyModel.java
@@ -0,0 +1,367 @@
+/*
+ *  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.polygene.runtime.property;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.constraint.ConstraintViolation;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.DefaultValues;
+import org.apache.polygene.api.property.GenericPropertyInfo;
+import org.apache.polygene.api.property.InitialValueProvider;
+import org.apache.polygene.api.property.InvalidPropertyTypeException;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.serialization.Deserializer;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ValueCompositeType;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.Visitable;
+import org.apache.polygene.api.util.Visitor;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.runtime.composite.ValueConstraintsInstance;
+import org.apache.polygene.runtime.model.Binder;
+import org.apache.polygene.runtime.model.Resolution;
+import org.apache.polygene.runtime.type.ValueTypeFactoryInstance;
+
+/**
+ * Model for a Property.
+ * <p>
+ * <p>Equality is based on the Property accessor object (property type and name), not on the QualifiedName.</p>
+ */
+public class PropertyModel
+    implements PropertyDescriptor, PropertyInfo, Binder, Visitable<PropertyModel>
+{
+    private Type type;
+
+    private transient AccessibleObject accessor; // Interface accessor
+
+    private final QualifiedName qualifiedName;
+
+    private final ValueConstraintsInstance constraints; // May be null
+
+    protected final MetaInfo metaInfo;
+
+    private final InitialValueProvider initialValueProvider;
+
+    private final boolean immutable;
+
+    private ValueType valueType;
+
+    protected PropertyInfo builderInfo;
+
+    private final boolean queryable;
+
+    public PropertyModel( AccessibleObject accessor,
+                          boolean immutable,
+                          boolean useDefaults,
+                          ValueConstraintsInstance constraints,
+                          MetaInfo metaInfo,
+                          Object initialValue,
+                          InitialValueProvider initialValueProvider
+                        )
+    {
+        if( accessor instanceof Method )
+        {
+            Method m = (Method) accessor;
+            if( !m.getReturnType().equals( Property.class ) )
+            {
+                throw new InvalidPropertyTypeException( accessor );
+            }
+        }
+        this.immutable = immutable;
+        this.metaInfo = metaInfo;
+        this.accessor = accessor;
+        type = GenericPropertyInfo.propertyTypeOf( accessor );
+        checkTypeValidity( type );
+        qualifiedName = QualifiedName.fromAccessor( accessor );
+        if( initialValueProvider != null )
+        {
+            this.initialValueProvider = initialValueProvider;
+        }
+        else
+        {
+            this.initialValueProvider = new DefaultInitialValueProvider( useDefaults, initialValue );
+        }
+        this.constraints = constraints;
+        final Queryable queryable = accessor.getAnnotation( Queryable.class );
+        this.queryable = queryable == null || queryable.value();
+    }
+
+    private void checkTypeValidity( Type type )
+    {
+        // Make sure certain data types doesn't take hold in Polygene applications.
+        String typeName = type.getTypeName();
+        if( typeName.contains( "java.util.Date" )
+            || typeName.contains( "java.util.Calendar" )
+            || typeName.contains( "java.util.GregorianCalendar" )
+            || typeName.contains( "java.sql.Date" )
+            || typeName.contains( "java.sql.Time" )
+            || typeName.contains( "java.sql.Timestamp" )
+            || typeName.contains( "org.joda.time" )
+            )
+        {
+            throw new InvalidPropertyTypeException( type + " is not allowed in Polygene. Please use Java Time API instead." );
+        }
+        if( typeName.contains( "java.util.Dictionary" )
+            || typeName.contains( "java.util.Hashtable" )
+            || typeName.contains( "java.util.Vector" )
+            )
+        {
+            throw new InvalidPropertyTypeException( type + " is not allowed in Polygene. Please use the modern Java Collection API instead." );
+        }
+    }
+
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return metaInfo.get( infoType );
+    }
+
+    public String name()
+    {
+        return qualifiedName.name();
+    }
+
+    @Override
+    public QualifiedName qualifiedName()
+    {
+        return qualifiedName;
+    }
+
+    @Override
+    public Type type()
+    {
+        return type;
+    }
+
+    @Override
+    public AccessibleObject accessor()
+    {
+        return accessor;
+    }
+
+    @Override
+    public ValueType valueType()
+    {
+        return valueType;
+    }
+
+    @Override
+    public boolean isImmutable()
+    {
+        return immutable;
+    }
+
+    public PropertyInfo getBuilderInfo()
+    {
+        return builderInfo;
+    }
+
+    @Override
+    public boolean queryable()
+    {
+        return queryable;
+    }
+
+    @Override
+    public InitialValueProvider initialValueProvider()
+    {
+        return initialValueProvider;
+    }
+
+    @Override
+    public Object resolveInitialValue( ModuleDescriptor moduleDescriptor )
+    {
+        return initialValueProvider.apply( moduleDescriptor.instance(), this );
+    }
+
+    @Override
+    public void bind( Resolution resolution )
+        throws BindingException
+    {
+        ValueTypeFactoryInstance factory = ValueTypeFactoryInstance.instance();
+        Class<?> declaringClass = ( (Member) accessor() ).getDeclaringClass();
+        Class<?> mainType = resolution.model().types().findFirst().orElse( null );
+        valueType = factory.newValueType( type(), declaringClass, mainType, resolution.module() );
+        builderInfo = new BuilderPropertyInfo();
+        if( type instanceof TypeVariable )
+        {
+            type = Classes.resolveTypeVariable( (TypeVariable) type, declaringClass, mainType );
+        }
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( Visitor<? super PropertyModel, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        return visitor.visit( this );
+    }
+
+    @Override
+    public void checkConstraints( Object value )
+        throws ConstraintViolationException
+    {
+        if( constraints == null )
+        {
+            return;
+        }
+        constraints.checkConstraints( value, accessor );
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        PropertyModel that = (PropertyModel) o;
+        return accessor.equals( that.accessor );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return accessor.hashCode();
+    }
+
+    @Override
+    public String toString()
+    {
+        if( accessor instanceof Field )
+        {
+            return ( (Field) accessor ).toGenericString();
+        }
+        else
+        {
+            return ( (Method) accessor ).toGenericString();
+        }
+    }
+
+    private class BuilderPropertyInfo implements PropertyInfo
+    {
+        @Override
+        public boolean isImmutable()
+        {
+            return false;
+        }
+
+        @Override
+        public QualifiedName qualifiedName()
+        {
+            return qualifiedName;
+        }
+
+        @Override
+        public Type type()
+        {
+            return type;
+        }
+
+        @Override
+        public void checkConstraints( Object value )
+            throws ConstraintViolationException
+        {
+            if( constraints != null )
+            {
+                List<ConstraintViolation> violations = constraints.checkConstraints( value );
+                if( !violations.isEmpty() )
+                {
+                    Stream<Class<?>> empty = Stream.empty();
+                    throw new ConstraintViolationException( "", empty, (Member) accessor, violations );
+                }
+            }
+        }
+    }
+
+    private class DefaultInitialValueProvider
+        implements InitialValueProvider
+    {
+        private final boolean useDefaults;
+        private final Object initialValue;
+
+        private DefaultInitialValueProvider( boolean useDefaults, Object initialValue )
+        {
+            this.useDefaults = useDefaults;
+            this.initialValue = initialValue;
+        }
+
+        @Override
+        public Object apply( Module module, PropertyDescriptor property )
+        {
+            return initialValue( module.descriptor(), initialValue, useDefaults );
+        }
+
+        private Object initialValue( ModuleDescriptor module, Object initialValue, boolean useDefaults )
+        {
+            // Use supplied value from assembly
+            Object value = initialValue;
+
+            // Check for @UseDefaults annotation
+            if( useDefaults )
+            {
+                if( value == null || ( ( value instanceof String ) && ( (String) value ).length() == 0 ) )
+                {
+                    if( valueType instanceof ValueCompositeType )
+                    {
+                        value = module.instance().newValue( valueType.primaryType() );
+                    }
+                    else
+                    {
+                        value = DefaultValues.getDefaultValueOf( type );
+                    }
+                }
+                else
+                {
+                    Class<?> propertyType = valueType().types().findFirst().orElse( null );
+                    if( value instanceof String && !propertyType.equals( String.class ) )
+                    {
+                        ServiceFinder serviceFinder = module.instance().serviceFinder();
+                        Deserializer deserializer = serviceFinder.findService( Deserializer.class ).get();
+                        if( deserializer != null )
+                        {
+                            value = deserializer.deserialize( module, valueType, (String) value );
+                        }
+                    }
+                }
+            }
+            return value;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/query/IterableQuerySource.java b/core/runtime/src/main/java/org/apache/polygene/runtime/query/IterableQuerySource.java
new file mode 100644
index 0000000..b12ba18
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/query/IterableQuerySource.java
@@ -0,0 +1,245 @@
+/*
+ *  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.polygene.runtime.query;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.spi.query.QuerySource;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.polygene.api.util.Classes.instanceOf;
+
+/**
+ * JAVADOC
+ */
+public class IterableQuerySource
+    implements QuerySource
+{
+    private final Iterable iterable;
+
+    /**
+     * Constructor.
+     *
+     * @param iterable iterable
+     */
+    @SuppressWarnings( "raw" )
+    IterableQuerySource( final Iterable iterable )
+    {
+        this.iterable = iterable;
+    }
+
+    @Override
+    public <T> T find( Class<T> resultType,
+                       Predicate<Composite> whereClause,
+                       List<OrderBy> orderBySegments,
+                       Integer firstResult,
+                       Integer maxResults,
+                       Map<String, Object> variables
+    )
+    {
+        return stream( resultType, whereClause, orderBySegments, firstResult, maxResults, variables )
+            .findFirst().orElse( null );
+    }
+
+    @Override
+    public <T> long count( Class<T> resultType,
+                           Predicate<Composite> whereClause,
+                           List<OrderBy> orderBySegments,
+                           Integer firstResult,
+                           Integer maxResults,
+                           Map<String, Object> variables
+    )
+    {
+        return list( resultType, whereClause, orderBySegments, firstResult, maxResults, variables ).size();
+    }
+
+    @Override
+    public <T> Stream<T> stream( Class<T> resultType,
+                                     Predicate<Composite> whereClause,
+                                     List<OrderBy> orderBySegments,
+                                     Integer firstResult,
+                                     Integer maxResults,
+                                     Map<String, Object> variables
+    )
+    {
+        return list( resultType, whereClause, orderBySegments, firstResult, maxResults, variables ).stream();
+    }
+
+    @SuppressWarnings( {"raw", "unchecked"} )
+    private <T> List<T> list( Class<T> resultType,
+                              Predicate<Composite> whereClause,
+                              List<OrderBy> orderBySegments,
+                              Integer firstResult,
+                              Integer maxResults,
+                              Map<String, Object> variables
+    )
+    {
+        // Ensure it's a list first
+        List<T> list = filter( resultType, whereClause );
+
+        // Order list
+        if( orderBySegments != null )
+        {
+            // Sort it
+            list.sort( new OrderByComparator( orderBySegments ) );
+        }
+
+        // Cut results
+        if( firstResult != null )
+        {
+            if( firstResult > list.size() )
+            {
+                return Collections.emptyList();
+            }
+
+            int toIdx;
+            if( maxResults != null )
+            {
+                toIdx = Math.min( firstResult + maxResults, list.size() );
+            }
+            else
+            {
+                toIdx = list.size();
+            }
+
+            list = list.subList( firstResult, toIdx );
+        }
+        else
+        {
+            int toIdx;
+            if( maxResults != null )
+            {
+                toIdx = Math.min( maxResults, list.size() );
+            }
+            else
+            {
+                toIdx = list.size();
+            }
+
+            list = list.subList( 0, toIdx );
+        }
+
+        return list;
+    }
+
+    @SuppressWarnings( {"raw", "unchecked"} )
+    private <T> List<T> filter( Class<T> resultType, Predicate whereClause )
+    {
+        Stream stream = StreamSupport.stream( iterable.spliterator(), false );
+        if( whereClause == null )
+        {
+            return List.class.cast( stream.filter( resultType::isInstance )
+                                          .collect( toList() ) );
+        }
+        else
+        {
+            return List.class.cast( stream.filter( instanceOf( resultType ).and( whereClause ) )
+                                          .collect( toList() ) );
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        return "IterableQuerySource{" + iterable + '}';
+    }
+
+    private static class OrderByComparator<T extends Composite>
+        implements Comparator<T>
+    {
+
+        private final Iterable<OrderBy> orderBySegments;
+
+        private OrderByComparator( Iterable<OrderBy> orderBySegments )
+        {
+            this.orderBySegments = orderBySegments;
+        }
+
+        @Override
+        @SuppressWarnings( {"raw", "unchecked"} )
+        public int compare( T o1, T o2 )
+        {
+            for( OrderBy orderBySegment : orderBySegments )
+            {
+                try
+                {
+                    final Property prop1 = orderBySegment.property().apply( o1 );
+                    final Property prop2 = orderBySegment.property().apply( o2 );
+                    if( prop1 == null || prop2 == null )
+                    {
+                        if( prop1 == null && prop2 == null )
+                        {
+                            return 0;
+                        }
+                        else if( prop1 != null )
+                        {
+                            return 1;
+                        }
+                        return -1;
+                    }
+                    final Object value1 = prop1.get();
+                    final Object value2 = prop2.get();
+                    if( value1 == null || value2 == null )
+                    {
+                        if( value1 == null && value2 == null )
+                        {
+                            return 0;
+                        }
+                        else if( value1 != null )
+                        {
+                            return 1;
+                        }
+                        return -1;
+                    }
+                    if( value1 instanceof Comparable )
+                    {
+                        int result = ( (Comparable) value1 ).compareTo( value2 );
+                        if( result != 0 )
+                        {
+                            if( orderBySegment.order() == OrderBy.Order.ASCENDING )
+                            {
+                                return result;
+                            }
+                            else
+                            {
+                                return -result;
+                            }
+                        }
+                    }
+                }
+                catch( Exception e )
+                {
+                    return 0;
+                }
+            }
+
+            return 0;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryBuilderFactoryImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryBuilderFactoryImpl.java
new file mode 100644
index 0000000..0f572ea
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryBuilderFactoryImpl.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.runtime.query;
+
+import java.util.Objects;
+import org.apache.polygene.api.query.NotQueryableException;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.service.NoSuchServiceException;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.spi.query.EntityFinder;
+
+/**
+ * Default implementation of {@link QueryBuilderFactory}
+ */
+public final class QueryBuilderFactoryImpl
+    implements QueryBuilderFactory
+{
+    private ServiceFinder finder;
+
+    /**
+     * Constructor.
+     *
+     * @param finder The ServiceFinder of the Module this QueryBuilderFactory belongs to.
+     */
+    public QueryBuilderFactoryImpl( ServiceFinder finder )
+    {
+        Objects.requireNonNull( finder, "ServiceFinder" );
+        this.finder = finder;
+    }
+
+    /**
+     * @see QueryBuilderFactory#newQueryBuilder(Class)
+     */
+    @Override
+    public <T> QueryBuilder<T> newQueryBuilder( final Class<T> resultType )
+    {
+        NotQueryableException.throwIfNotQueryable( resultType );
+
+        final ServiceReference<EntityFinder> serviceReference;
+        try
+        {
+            serviceReference = finder.findService( EntityFinder.class );
+            return new QueryBuilderImpl<>( serviceReference.get(), resultType, null );
+        }
+        catch( NoSuchServiceException e )
+        {
+            return new QueryBuilderImpl<>( null, resultType, null );
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryBuilderImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryBuilderImpl.java
new file mode 100644
index 0000000..7d5cb4b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryBuilderImpl.java
@@ -0,0 +1,96 @@
+/*
+ *  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.polygene.runtime.query;
+
+import java.util.function.Predicate;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryExpressions;
+import org.apache.polygene.spi.query.EntityFinder;
+import org.apache.polygene.spi.query.QueryBuilderSPI;
+import org.apache.polygene.spi.query.QuerySource;
+
+/**
+ * Default implementation of {@link QueryBuilder}
+ */
+final class QueryBuilderImpl<T>
+    implements QueryBuilder<T>, QueryBuilderSPI<T>
+{
+
+    /**
+     * Entity finder to be used to locate entities.
+     */
+    private final EntityFinder entityFinder;
+
+    /**
+     * Type of queried entities.
+     */
+    private final Class<T> resultType;
+    /**
+     * Where clause.
+     */
+    private final Predicate<Composite> whereClause;
+
+    /**
+     * Constructor.
+     *
+     * @param entityFinder entity finder to be used to locate entities; canot be null
+     * @param resultType   type of queried entities; cannot be null
+     * @param whereClause  current where-clause
+     */
+    QueryBuilderImpl( final EntityFinder entityFinder,
+                      final Class<T> resultType,
+                      final Predicate<Composite> whereClause
+    )
+    {
+        this.entityFinder = entityFinder;
+        this.resultType = resultType;
+        this.whereClause = whereClause;
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public QueryBuilder<T> where( Predicate<Composite> specification )
+    {
+        if( specification == null )
+        {
+            throw new IllegalArgumentException( "Where clause cannot be null" );
+        }
+        if( this.whereClause != null )
+        {
+            specification = QueryExpressions.and( this.whereClause, specification );
+        }
+        return new QueryBuilderImpl<>( entityFinder, resultType, specification );
+    }
+
+    @Override
+    public Query<T> newQuery( Iterable<T> iterable )
+    {
+        return new QueryImpl<>( resultType, whereClause, new IterableQuerySource( iterable ) );
+    }
+
+    // SPI
+    @Override
+    public Query<T> newQuery( QuerySource querySource )
+    {
+        return new QueryImpl<>( resultType, whereClause, querySource );
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryImpl.java
new file mode 100644
index 0000000..cdbe633
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryImpl.java
@@ -0,0 +1,218 @@
+/*
+ *  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.polygene.runtime.query;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryExecutionException;
+import org.apache.polygene.api.query.QueryExpressions;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.spi.query.QuerySource;
+
+/**
+ * Default implementation of {@link org.apache.polygene.api.query.Query}.
+ */
+class QueryImpl<T>
+    implements Query<T>
+{
+    /**
+     * Type of queried entities.
+     */
+    private final Class<T> resultType;
+    /**
+     * Where clause.
+     */
+    private final Predicate<Composite> whereClause;
+    private QuerySource querySource;
+    /**
+     * Order by clause segments.
+     */
+    private List<OrderBy> orderBySegments;
+    /**
+     * First result to be returned.
+     */
+    private Integer firstResult;
+    /**
+     * Maximum number of results to be returned.
+     */
+    private Integer maxResults;
+    /**
+     * Mapping between variable name and variable values.
+     */
+    private Map<String, Object> variables;
+
+    /**
+     * Constructor.
+     *
+     * @param resultType  type of queried entities; cannot be null
+     * @param whereClause where clause
+     */
+    QueryImpl( final Class<T> resultType,
+               final Predicate<Composite> whereClause,
+               final QuerySource querySource
+             )
+    {
+        this.resultType = resultType;
+        this.whereClause = whereClause;
+        this.querySource = querySource;
+    }
+
+    /**
+     * @see org.apache.polygene.api.query.Query#orderBy(org.apache.polygene.api.query.grammar.OrderBy[])
+     */
+    @Override
+    public Query<T> orderBy( final OrderBy... segments )
+    {
+        orderBySegments = Arrays.asList( segments );
+        return this;
+    }
+
+    /**
+     * @see org.apache.polygene.api.query.Query#orderBy(org.apache.polygene.api.property.Property, org.apache.polygene.api.query.grammar.OrderBy.Order)
+     */
+    @Override
+    public Query<T> orderBy( Property<?> property, OrderBy.Order order )
+    {
+        if( orderBySegments == null )
+        {
+            orderBySegments = new ArrayList<>();
+        }
+        orderBySegments.add( new OrderBy( QueryExpressions.property( property ), order ) );
+        return this;
+    }
+
+    /**
+     * @see org.apache.polygene.api.query.Query#orderBy(org.apache.polygene.api.property.Property)
+     */
+    @Override
+    public Query<T> orderBy( Property<?> property )
+    {
+        orderBy( property, OrderBy.Order.ASCENDING );
+        return this;
+    }
+
+    /**
+     * @see org.apache.polygene.api.query.Query#firstResult(int)
+     */
+    @Override
+    public Query<T> firstResult( int firstResult )
+    {
+        this.firstResult = firstResult;
+        return this;
+    }
+
+    /**
+     * @see org.apache.polygene.api.query.Query#maxResults(int)
+     */
+    @Override
+    public Query<T> maxResults( int maxResults )
+    {
+        this.maxResults = maxResults;
+        return this;
+    }
+
+    /**
+     * @see org.apache.polygene.api.query.Query#setVariable(String, Object)
+     */
+    @SuppressWarnings( "unchecked" )
+    @Override
+    public Query<T> setVariable( final String name, final Object value )
+    {
+        if( variables == null )
+        {
+            variables = new HashMap<>();
+        }
+        variables.put( name, value );
+
+        return this;
+    }
+
+    /**
+     * @see org.apache.polygene.api.query.Query#getVariable(String)
+     */
+    @SuppressWarnings( "unchecked" )
+    @Override
+    public <V> V getVariable( final String name )
+    {
+        if( variables == null )
+        {
+            return null;
+        }
+        else
+        {
+            return (V) variables.get( name );
+        }
+    }
+
+    @Override
+    public Class<T> resultType()
+    {
+        return resultType;
+    }
+
+    @Override
+    public T find()
+        throws QueryExecutionException
+    {
+        return querySource.find( resultType, whereClause, orderBySegments, firstResult, maxResults, variables );
+    }
+
+    @Override
+    public long count()
+        throws QueryExecutionException
+    {
+        return querySource.count( resultType, whereClause, orderBySegments, firstResult, maxResults, variables );
+    }
+
+    @Override
+    public Iterator<T> iterator()
+    {
+        return stream().iterator();
+    }
+
+    @Override
+    public Stream<T> stream()
+    {
+        return querySource.stream( resultType, whereClause, orderBySegments, firstResult, maxResults, variables );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Query{" +
+               " FROM " + querySource +
+               " WHERE " + whereClause +
+               ( orderBySegments != null ? " ORDER BY " + orderBySegments : "" ) +
+               ( firstResult != null ? " FIRST " + firstResult : "" ) +
+               ( maxResults != null ? " MAX " + maxResults : "" ) +
+               " EXPECT " + resultType +
+               ( variables != null ? " WITH VARIABLES " + variables : "" ) +
+               '}';
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceInstance.java
new file mode 100644
index 0000000..104938f
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceInstance.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.runtime.service;
+
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.service.ServiceImporter;
+
+/**
+ * JAVADOC
+ */
+public final class ImportedServiceInstance<T>
+    implements Activation
+{
+    private final T instance;
+    private final ServiceImporter<T> importer;
+
+    public ImportedServiceInstance( T instance, ServiceImporter<T> importer )
+    {
+        this.importer = importer;
+        this.instance = instance;
+    }
+
+    public T instance()
+    {
+        return instance;
+    }
+
+    public ServiceImporter importer()
+    {
+        return importer;
+    }
+
+    public boolean isAvailable()
+    {
+        return importer.isAvailable( instance );
+    }
+
+    @Override
+    public void activate()
+        throws ActivationException
+    {
+        // NOOP
+    }
+
+    @Override
+    public void passivate()
+        throws PassivationException
+    {
+        // NOOP
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceModel.java
new file mode 100644
index 0000000..174735f
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceModel.java
@@ -0,0 +1,197 @@
+/*
+ *  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.polygene.runtime.service;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.ServiceImporterException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.activation.ActivatorsInstance;
+import org.apache.polygene.runtime.activation.ActivatorsModel;
+
+/**
+ * JAVADOC
+ */
+public final class ImportedServiceModel
+    implements ImportedServiceDescriptor, VisitableHierarchy<Object, Object>
+{
+    private final ModuleDescriptor module;
+    private final Class<?> type;
+    private final Visibility visibility;
+    @SuppressWarnings( "raw" )
+    private final Class<? extends ServiceImporter> serviceImporter;
+    private final Identity identity;
+    private final boolean importOnStartup;
+    private final MetaInfo metaInfo;
+    private final ActivatorsModel<?> activatorsModel;
+    private final String moduleName;
+
+    @SuppressWarnings( "raw" )
+    public ImportedServiceModel( ModuleDescriptor module,
+                                 Class serviceType,
+                                 Visibility visibility,
+                                 Class<? extends ServiceImporter> serviceImporter,
+                                 Identity identity,
+                                 boolean importOnStartup,
+                                 MetaInfo metaInfo,
+                                 ActivatorsModel<?> activatorsModel,
+                                 String moduleName
+    )
+    {
+        this.module = module;
+        type = serviceType;
+        this.visibility = visibility;
+        this.serviceImporter = serviceImporter;
+        this.identity = identity;
+        this.importOnStartup = importOnStartup;
+        this.metaInfo = metaInfo;
+        this.activatorsModel = activatorsModel;
+        this.moduleName = moduleName;
+    }
+
+    public boolean isImportOnStartup()
+    {
+        return importOnStartup;
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public Stream<Class<?>> types()
+    {
+        return Stream.of( type );
+    }
+
+    @Override
+    public Visibility visibility()
+    {
+        return visibility;
+    }
+
+    @Override
+    public ModuleDescriptor module()
+    {
+        return module;
+    }
+
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return metaInfo.get( infoType );
+    }
+
+    @Override
+    @SuppressWarnings( "raw" )
+    public Class<? extends ServiceImporter> serviceImporter()
+    {
+        return serviceImporter;
+    }
+
+    @Override
+    public Class<?> type()
+    {
+        return type;
+    }
+
+    @Override
+    public Identity identity()
+    {
+        return identity;
+    }
+
+    public String moduleName()
+    {
+        return moduleName;
+    }
+
+    @SuppressWarnings( { "raw", "unchecked" } )
+    public ActivatorsInstance<?> newActivatorsInstance( ModuleDescriptor module )
+        throws Exception
+    {
+        return new ActivatorsInstance( activatorsModel.newInstances( module ) );
+    }
+
+    @Override
+    public boolean isAssignableTo( Class<?> type )
+    {
+        return this.type.isAssignableFrom( type );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            activatorsModel.accept( visitor );
+        }
+        return visitor.visitLeave( this );
+    }
+
+    @SuppressWarnings( { "raw", "unchecked" } )
+    public <T> ImportedServiceInstance<T> importInstance( ModuleDescriptor module )
+    {
+        try
+        {
+            ServiceImporter importer = module.instance().newObject( serviceImporter );
+            T instance = (T) importer.importService( this );
+            return new ImportedServiceInstance<>( instance, importer );
+        }
+        catch( ServiceImporterException e )
+        {
+            throw e;
+        }
+        catch( Exception e )
+        {
+            throw new ServiceImporterException( "Could not import service " + identity, e );
+        }
+    }
+
+    @SuppressWarnings( "raw" )
+    public Object newProxy( InvocationHandler serviceInvocationHandler )
+    {
+        if( type.isInterface() )
+        {
+            return Proxy.newProxyInstance( type.getClassLoader(),
+                                           new Class[]{ type },
+                                           serviceInvocationHandler );
+        }
+        else
+        {
+            Class[] interfaces = type.getInterfaces();
+            return Proxy.newProxyInstance( type.getClassLoader(),
+                                           interfaces,
+                                           serviceInvocationHandler );
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        return type.getName() + ":" + identity;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceReferenceInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceReferenceInstance.java
new file mode 100644
index 0000000..9517ff8
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceReferenceInstance.java
@@ -0,0 +1,229 @@
+/*
+ *  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.polygene.runtime.service;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivationEventListener;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.service.ServiceImporterException;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.service.ServiceUnavailableException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.runtime.activation.ActivationDelegate;
+
+/**
+ * Implementation of ServiceReference. This manages the reference to the imported service.
+ * <p>
+ * Whenever the service is requested it is returned directly to the client. That means that
+ * to handle service passivation and unavailability correctly, any proxying must be done in the
+ * service importer.
+ * </p>
+ *
+ * @param <T> Service Type
+ */
+public final class ImportedServiceReferenceInstance<T>
+    implements ServiceReference<T>, Activation
+{
+    private volatile ImportedServiceInstance<T> serviceInstance;
+    private T instance;
+    private final ModuleDescriptor module;
+    private final ImportedServiceModel serviceModel;
+    private final ActivationDelegate activation = new ActivationDelegate( this );
+    private boolean active = false;
+    private ImportedServiceInstance<T> serviceInstanceBeingActivated;
+
+    public ImportedServiceReferenceInstance( ImportedServiceModel serviceModel, ModuleDescriptor module )
+    {
+        this.module = module;
+        this.serviceModel = serviceModel;
+    }
+
+    @Override
+    public Identity identity()
+    {
+        return serviceModel.identity();
+    }
+
+    @Override
+    public Stream<Class<?>> types()
+    {
+        return serviceModel.types();
+    }
+
+    @Override
+    public <M> M metaInfo( Class<M> infoType )
+    {
+        return serviceModel.metaInfo( infoType );
+    }
+
+    @Override
+    public synchronized T get()
+    {
+        return getInstance();
+    }
+
+    public ImportedServiceModel serviceDescriptor()
+    {
+        return serviceModel;
+    }
+
+    @Override
+    public void activate()
+        throws ActivationException
+    {
+        if( serviceModel.isImportOnStartup() )
+        {
+            getInstance();
+        }
+    }
+
+    @Override
+    public void passivate()
+        throws PassivationException
+    {
+        if( serviceInstance != null )
+        {
+            try
+            {
+                activation.passivate( () -> active = false );
+            }
+            finally
+            {
+                serviceInstance = null;
+                active = false;
+            }
+        }
+    }
+
+    @Override
+    public boolean isActive()
+    {
+        return active;
+    }
+
+    @Override
+    public boolean isAvailable()
+    {
+        try
+        {
+            getInstance();
+            return serviceInstance.isAvailable();
+        }
+        catch( ServiceImporterException ex )
+        {
+            return false;
+        }
+    }
+
+    @Override
+    public ModelDescriptor model()
+    {
+        return serviceModel;
+    }
+
+    public ModuleDescriptor module()
+    {
+        return module;
+    }
+
+    private T getInstance()
+        throws ServiceImporterException
+    {
+        // DCL that works with Java 1.5 volatile semantics
+        if( serviceInstance == null )
+        {
+            synchronized( this )
+            {
+                if( serviceInstance == null )
+                {
+                    if( serviceInstanceBeingActivated != null )
+                    {
+                        // needed because activation may request its own service.
+                        // There is possible complication with this, as activation may use another service, which in turn
+                        // uses the service under activation before it is being ready. This is a problem left to the
+                        // developer to be aware of and avoid. It is similar to what can happen when pass 'this' inside
+                        // constructors to objects, which may then use an uninitilized object.
+                        return serviceInstanceBeingActivated.instance();
+                    }
+                    serviceInstanceBeingActivated = serviceModel.importInstance( module );
+                    try
+                    {
+                        activation.activate(
+                            serviceModel.newActivatorsInstance( module ),
+                            serviceInstanceBeingActivated, () -> active = true
+                        );
+                    }
+                    catch( Exception e )
+                    {
+                        throw new ServiceUnavailableException( "Could not activate service " + serviceModel.identity(), e );
+                    }
+                    serviceInstance = serviceInstanceBeingActivated;
+                    instance = serviceInstanceBeingActivated.instance();
+                    serviceInstanceBeingActivated = null;
+                }
+            }
+        }
+
+        return instance;
+    }
+
+    @Override
+    public String toString()
+    {
+        return serviceModel.identity() + ", active=" + isActive() + ", module='" + serviceModel.moduleName() + "'";
+    }
+
+    @Override
+    public void registerActivationEventListener( ActivationEventListener listener )
+    {
+        activation.registerActivationEventListener( listener );
+    }
+
+    @Override
+    public void deregisterActivationEventListener( ActivationEventListener listener )
+    {
+        activation.deregisterActivationEventListener( listener );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return identity().hashCode();
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        if( obj == null )
+        {
+            return false;
+        }
+        if( getClass() != obj.getClass() )
+        {
+            return false;
+        }
+        final ServiceReference other = (ServiceReference) obj;
+        return identity().equals( other.identity() );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServicesInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServicesInstance.java
new file mode 100644
index 0000000..61a15c9
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServicesInstance.java
@@ -0,0 +1,128 @@
+/*
+ *  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.polygene.runtime.service;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivationEventListener;
+import org.apache.polygene.api.activation.ActivationEventListenerRegistration;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.runtime.activation.ActivationDelegate;
+import org.apache.polygene.runtime.activation.ActivatorsInstance;
+
+import static java.util.stream.Collectors.toList;
+
+/**
+ * JAVADOC
+ */
+public class ImportedServicesInstance
+    implements Activation, ActivationEventListenerRegistration
+{
+    private final ImportedServicesModel servicesModel;
+    private final List<ServiceReference<?>> serviceReferences;
+    private final ActivationDelegate activation = new ActivationDelegate( this, false );
+
+    public ImportedServicesInstance( ImportedServicesModel servicesModel,
+                                     List<ServiceReference<?>> serviceReferences
+    )
+    {
+        this.servicesModel = servicesModel;
+        this.serviceReferences = serviceReferences;
+        for( ServiceReference serviceReference : serviceReferences )
+        {
+            serviceReference.registerActivationEventListener( activation );
+        }
+    }
+
+    public Stream<ImportedServiceModel> models()
+    {
+        return servicesModel.models();
+    }
+
+    @Override
+    public void activate()
+        throws ActivationException
+    {
+        Iterable<Activation> activatees = serviceReferences.stream().filter( Activation.class::isInstance )
+                                                           .map( Activation.class::cast )
+                                                           .collect( toList() );
+        activation.activate( ActivatorsInstance.EMPTY, activatees );
+    }
+
+    @Override
+    public void passivate()
+        throws PassivationException
+    {
+        activation.passivate();
+    }
+
+    public Stream<ServiceReference<?>> visibleServices( final Visibility visibility )
+    {
+        return serviceReferences.stream()
+            .filter( item ->
+                         ( (ImportedServiceReferenceInstance) item ).serviceDescriptor()
+                             .visibility()
+                             .ordinal() >= visibility.ordinal()
+            );
+    }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder( "Services{" );
+        String sep = " ";
+        for( ServiceReference serviceReference : serviceReferences )
+        {
+            sb.append( sep ).
+                append( serviceReference.identity() ).
+                append( "(active=" ).append( serviceReference.isActive() ).append( ")" );
+            sep = ", ";
+        }
+        return sb.append( " }" ).toString();
+    }
+
+    @Override
+    public void registerActivationEventListener( ActivationEventListener listener )
+    {
+        activation.registerActivationEventListener( listener );
+    }
+
+    @Override
+    public void deregisterActivationEventListener( ActivationEventListener listener )
+    {
+        activation.deregisterActivationEventListener( listener );
+    }
+
+    public Stream<? extends ImportedServiceDescriptor> stream()
+    {
+        return servicesModel.models();
+    }
+
+    public Stream<ServiceReference<?>> references()
+    {
+        return serviceReferences.stream();
+    }
+
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServicesModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServicesModel.java
new file mode 100644
index 0000000..af34755
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServicesModel.java
@@ -0,0 +1,77 @@
+/*
+ *  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.polygene.runtime.service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * JAVADOC
+ */
+public class ImportedServicesModel
+    implements VisitableHierarchy<Object, Object>
+{
+    private List<ImportedServiceModel> importedServiceModels;
+
+    public ImportedServicesModel( List<ImportedServiceModel> importedServiceModels )
+    {
+        this.importedServiceModels = importedServiceModels;
+    }
+
+    public ImportedServicesInstance newInstance( ModuleDescriptor module )
+    {
+        List<ServiceReference<?>> serviceReferences = new ArrayList<>();
+        for( ImportedServiceModel serviceModel : importedServiceModels )
+        {
+            ImportedServiceReferenceInstance serviceReferenceInstance = new ImportedServiceReferenceInstance( serviceModel, module );
+            serviceReferences.add( serviceReferenceInstance );
+        }
+
+        return new ImportedServicesInstance( this, serviceReferences );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( ImportedServiceModel importedServiceModel : importedServiceModels )
+            {
+                if( !importedServiceModel.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public Stream<ImportedServiceModel> models()
+    {
+        return importedServiceModels.stream();
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceInstance.java
new file mode 100644
index 0000000..ba21ca5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceInstance.java
@@ -0,0 +1,80 @@
+/*
+ *  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.polygene.runtime.service;
+
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.configuration.Enabled;
+import org.apache.polygene.api.service.Availability;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.runtime.composite.TransientInstance;
+import org.apache.polygene.runtime.composite.TransientStateInstance;
+
+/**
+ * JAVADOC
+ */
+public class ServiceInstance extends TransientInstance
+    implements Activation
+{
+    private final boolean implementsServiceAvailable;
+    private final boolean hasEnabledConfiguration;
+
+    public ServiceInstance( ServiceModel compositeModel,
+                            Object[] mixins,
+                            TransientStateInstance state
+    )
+    {
+        super( compositeModel, mixins, state );
+
+        implementsServiceAvailable = Classes.assignableTypeSpecification( Availability.class ).test( descriptor() );
+        hasEnabledConfiguration = compositeModel.configurationType() != null
+                                  && Enabled.class.isAssignableFrom( compositeModel.configurationType() );
+    }
+
+    @Override
+    public void activate()
+        throws ActivationException
+    {
+        // NOOP
+    }
+
+    @Override
+    public void passivate()
+        throws PassivationException
+    {
+        // NOOP
+    }
+
+    @SuppressWarnings( "unchecked" )
+    public boolean isAvailable()
+    {
+        // Check Enabled in configuration first
+        if( hasEnabledConfiguration && !( (Configuration<Enabled>) proxy() ).get().enabled().get() )
+        {
+            return false;
+        }
+
+        // Ask service if it's available
+        return !implementsServiceAvailable || ( (Availability) proxy() ).isAvailable();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceModel.java
new file mode 100644
index 0000000..74dd852
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceModel.java
@@ -0,0 +1,192 @@
+/*
+ *  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.polygene.runtime.service;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.ParameterizedType;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.runtime.activation.ActivatorsInstance;
+import org.apache.polygene.runtime.activation.ActivatorsModel;
+import org.apache.polygene.runtime.composite.CompositeMethodsModel;
+import org.apache.polygene.runtime.composite.CompositeModel;
+import org.apache.polygene.runtime.composite.MixinModel;
+import org.apache.polygene.runtime.composite.MixinsModel;
+import org.apache.polygene.runtime.composite.StateModel;
+import org.apache.polygene.runtime.composite.TransientStateInstance;
+import org.apache.polygene.runtime.composite.UsesInstance;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.property.PropertyInstance;
+
+/**
+ * JAVADOC
+ */
+public final class ServiceModel extends CompositeModel
+    implements ServiceDescriptor
+{
+    private final Identity identity;
+    private final boolean instantiateOnStartup;
+    private final ActivatorsModel<?> activatorsModel;
+    private final Class configurationType;
+
+    public ServiceModel( ModuleDescriptor module,
+                         List<Class<?>> types,
+                         Visibility visibility,
+                         MetaInfo metaInfo,
+                         ActivatorsModel<?> activatorsModel,
+                         MixinsModel mixinsModel,
+                         StateModel stateModel,
+                         CompositeMethodsModel compositeMethodsModel,
+                         Identity identity,
+                         boolean instantiateOnStartup
+    )
+    {
+        super( module, types, visibility, metaInfo, mixinsModel, stateModel, compositeMethodsModel );
+
+        this.identity = identity;
+        this.instantiateOnStartup = instantiateOnStartup;
+        this.activatorsModel = activatorsModel;
+
+        // Calculate configuration type
+        this.configurationType = calculateConfigurationType();
+    }
+
+    @Override
+    public boolean isInstantiateOnStartup()
+    {
+        return instantiateOnStartup;
+    }
+
+    @Override
+    public Identity identity()
+    {
+        return identity;
+    }
+
+    @SuppressWarnings( { "raw", "unchecked" } )
+    public ActivatorsInstance<?> newActivatorsInstance( ModuleDescriptor module )
+        throws Exception
+    {
+        return new ActivatorsInstance( activatorsModel.newInstances( module ) );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> Class<T> configurationType()
+    {
+        return configurationType;
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            if( activatorsModel.accept( visitor ) )
+            {
+                if( compositeMethodsModel.accept( visitor ) )
+                {
+                    if( stateModel.accept( visitor ) )
+                    {
+                        mixinsModel.accept( visitor );
+                    }
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public ServiceInstance newInstance( final ModuleDescriptor module )
+    {
+        Object[] mixins = mixinsModel.newMixinHolder();
+
+        Map<AccessibleObject, Property<?>> properties = new HashMap<>();
+        stateModel.properties().forEach( propertyModel -> {
+            Object initialValue = propertyModel.resolveInitialValue(module);
+            if( propertyModel.accessor().equals( HasIdentity.IDENTITY_METHOD ) )
+            {
+                initialValue = identity;
+            }
+
+            Property<?> property = new PropertyInstance<>( propertyModel, initialValue );
+            properties.put( propertyModel.accessor(), property );
+        } );
+
+        TransientStateInstance state = new TransientStateInstance( properties );
+        ServiceInstance compositeInstance = new ServiceInstance( this, mixins, state );
+
+        // Instantiate all mixins
+        int i = 0;
+        UsesInstance uses = UsesInstance.EMPTY_USES.use( this );
+        InjectionContext injectionContext = new InjectionContext( compositeInstance, uses, state );
+        for( MixinModel mixinModel : mixinsModel.mixinModels() )
+        {
+            mixins[ i++ ] = mixinModel.newInstance( injectionContext );
+        }
+
+        return compositeInstance;
+    }
+
+    @Override
+    public String toString()
+    {
+        return super.toString() + ":" + identity;
+    }
+
+    @SuppressWarnings( { "raw", "unchecked" } )
+    public Class calculateConfigurationType()
+    {
+        DependencyModel.ScopeSpecification thisSpec = new DependencyModel.ScopeSpecification( This.class );
+        Predicate<DependencyModel> configurationCheck = item -> item.rawInjectionType().equals( Configuration.class );
+        return dependencies().filter( thisSpec.and( configurationCheck ) )
+            .filter( dependencyModel -> dependencyModel.rawInjectionType().equals( Configuration.class ) )
+            .filter( dependencyModel -> dependencyModel.injectionType() instanceof ParameterizedType )
+            .map( dependencyModel -> Classes.RAW_CLASS.apply( ( (ParameterizedType) dependencyModel.injectionType() ).getActualTypeArguments()[ 0 ] ) )
+            .reduce( null, ( injectionClass, type ) -> {
+                if( injectionClass == null )
+                {
+                    injectionClass = type;
+                }
+                else
+                {
+                    if( injectionClass.isAssignableFrom( type ) )
+                    {
+                        injectionClass = type;
+                    }
+                }
+                return injectionClass;
+            } );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceReferenceInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceReferenceInstance.java
new file mode 100644
index 0000000..dafc742
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceReferenceInstance.java
@@ -0,0 +1,325 @@
+/*
+ *  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.polygene.runtime.service;
+
+import java.lang.reflect.Method;
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivationEventListener;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.service.ServiceImporterException;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.service.ServiceUnavailableException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.runtime.activation.ActivationDelegate;
+
+/**
+ * Implementation of ServiceReference.
+ * <p>
+ * This manages the actual instance of the service and implements the service Activation.
+ * </p>
+ * <p>
+ * Whenever the service is requested a proxy is returned which points to this class. This means
+ * that the instance can be passivated even though a client is holding on to a service proxy.
+ * </p>
+ * @param <T> Service Type
+ */
+public final class ServiceReferenceInstance<T>
+    implements ServiceReference<T>, Activation, ModelDescriptor
+{
+    private volatile ServiceInstance instance;
+    private final T serviceProxy;
+    private final ModuleDescriptor module;
+    private final ServiceModel serviceModel;
+    private final ActivationDelegate activation = new ActivationDelegate( this );
+    private boolean active = false;
+    private ServiceInstance instanceBeingActivated;
+
+    ServiceReferenceInstance( ServiceModel serviceModel, ModuleDescriptor module )
+    {
+        this.module = module;
+        this.serviceModel = serviceModel;
+
+        serviceProxy = newProxy();
+    }
+
+    @Override
+    public Identity identity()
+    {
+        return serviceModel.identity();
+    }
+
+    @Override
+    public Stream<Class<?>> types()
+    {
+        return serviceModel.types();
+    }
+
+    @Override
+    public <M> M metaInfo( Class<M> infoType )
+    {
+        return serviceModel.metaInfo( infoType );
+    }
+
+    @Override
+    public synchronized T get()
+    {
+        return serviceProxy;
+    }
+
+    @Override
+    public boolean isActive()
+    {
+        return active;
+    }
+
+    @Override
+    public boolean isAvailable()
+    {
+        return getInstance().isAvailable();
+    }
+
+    @Override
+    public ModelDescriptor model()
+    {
+        return serviceModel;
+    }
+
+    public ModuleDescriptor module()
+    {
+        return module;
+    }
+
+    @Override
+    public void activate()
+        throws ActivationException
+    {
+        if( serviceModel.isInstantiateOnStartup() )
+        {
+            getInstance();
+        }
+    }
+
+    @Override
+    public void passivate()
+        throws PassivationException
+    {
+        if( instance != null )
+        {
+            try {
+                activation.passivate( () -> active = false );
+            } finally {
+                instance = null;
+                active = false;
+            }
+        }
+    }
+
+    private ServiceInstance getInstance()
+        throws ServiceImporterException
+    {
+        // DCL that works with Java 1.5 volatile semantics
+        if( instance == null )
+        {
+            synchronized( this )
+            {
+                if( instance == null )
+                {
+                    if( instanceBeingActivated != null )
+                    {
+                        // needed because activation may request its own service.
+                        // There is possible complication with this, as activation may use another service, which in turn
+                        // uses the service under activation before it is being ready. This is a problem left to the
+                        // developer to be aware of and avoid. It is similar to what can happen when pass 'this' inside
+                        // constructors to objects, which may then use an uninitilized object.
+                        return instanceBeingActivated;
+                    }
+                    instanceBeingActivated = serviceModel.newInstance( module );
+
+                    try
+                    {
+                        activation.activate( serviceModel.newActivatorsInstance( module ),
+                                             instanceBeingActivated,
+                                             () -> active = true );
+                    }
+                    catch( Exception e )
+                    {
+                        throw new ServiceUnavailableException( "Could not activate service " + serviceModel.identity(), e );
+                    }
+                    instance = instanceBeingActivated;
+                    instanceBeingActivated = null;
+                }
+            }
+        }
+
+        return instance;
+    }
+
+    @Override
+    public String toString()
+    {
+        return serviceModel.identity() + "(active=" + isActive() + ",module='" + module.name() + "')";
+    }
+
+    @SuppressWarnings( "unchecked" )
+    public T newProxy()
+    {
+        return (T) serviceModel.newProxy( new ServiceReferenceInstance.ServiceInvocationHandler() );
+    }
+
+    public ServiceDescriptor serviceDescriptor()
+    {
+        return serviceModel;
+    }
+
+    @Override
+    public Visibility visibility()
+    {
+        return serviceModel.visibility();
+    }
+
+    @Override
+    public boolean isAssignableTo( Class<?> type )
+    {
+        return serviceModel.isAssignableTo( type );
+    }
+
+    public final class ServiceInvocationHandler
+        implements CompositeInstance
+    {
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public <P> P proxy()
+        {
+            return (P) ServiceReferenceInstance.this.get();
+        }
+
+        @Override
+        public <P> P newProxy( Class<P> mixinType )
+            throws IllegalArgumentException
+        {
+            return getInstance().newProxy( mixinType );
+        }
+
+        @Override
+        public <M> M metaInfo( Class<M> infoType )
+        {
+            return ServiceReferenceInstance.this.metaInfo( infoType );
+        }
+
+        @Override
+        public Stream<Class<?>> types()
+        {
+            return ServiceReferenceInstance.this.types();
+        }
+
+        @Override
+        public CompositeDescriptor descriptor()
+        {
+            return ServiceReferenceInstance.this.serviceDescriptor();
+        }
+
+        @Override
+        public Object invokeComposite( Method method, Object[] args )
+            throws Throwable
+        {
+            return getInstance().invokeComposite( method, args );
+        }
+
+        @Override
+        public StateHolder state()
+        {
+            return getInstance().state();
+        }
+
+        @Override
+        public Object invoke( Object object, Method method, Object[] objects )
+            throws Throwable
+        {
+            if( method.getDeclaringClass().equals( Object.class ) )
+            {
+                switch( method.getName() )
+                {
+                    case "toString":
+                        return serviceModel.toString();
+                    case "equals":
+                        return objects[0] == object;
+                    case "hashCode":
+                        return serviceModel.toString().hashCode();
+                }
+            }
+            ServiceInstance instance = getInstance();
+            return instance.invoke( object, method, objects );
+        }
+
+        @Override
+        public String toString()
+        {
+            return serviceModel.toString();
+        }
+
+        @Override
+        public ModuleDescriptor module()
+        {
+            return module;
+        }
+    }
+
+    @Override
+    public void registerActivationEventListener( ActivationEventListener listener )
+    {
+        activation.registerActivationEventListener( listener );
+    }
+
+    @Override
+    public void deregisterActivationEventListener( ActivationEventListener listener )
+    {
+        activation.deregisterActivationEventListener( listener );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return identity().hashCode();
+    }
+
+    @Override
+    @SuppressWarnings( "raw" )
+    public boolean equals( Object obj )
+    {
+        if ( obj == null ) {
+            return false;
+        }
+        if ( getClass() != obj.getClass() ) {
+            return false;
+        }
+        final ServiceReference other = ( ServiceReference ) obj;
+        return identity().equals( other.identity() );
+    }
+
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServicesInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServicesInstance.java
new file mode 100644
index 0000000..c40a74a
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServicesInstance.java
@@ -0,0 +1,122 @@
+/*
+ *  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.polygene.runtime.service;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivationEventListener;
+import org.apache.polygene.api.activation.ActivationEventListenerRegistration;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.runtime.activation.ActivationDelegate;
+import org.apache.polygene.runtime.activation.ActivatorsInstance;
+
+import static java.util.stream.Collectors.toList;
+
+/**
+ * JAVADOC
+ */
+public class ServicesInstance
+    implements Activation, ActivationEventListenerRegistration
+{
+    private final ServicesModel servicesModel;
+    private final List<ServiceReference<?>> serviceReferences;
+    private final ActivationDelegate activation = new ActivationDelegate( this, false );
+
+    public ServicesInstance( ServicesModel servicesModel, List<ServiceReference<?>> serviceReferences )
+    {
+        this.servicesModel = servicesModel;
+        this.serviceReferences = serviceReferences;
+        for( ServiceReference serviceReference : serviceReferences )
+        {
+            serviceReference.registerActivationEventListener( activation );
+        }
+    }
+
+    public Stream<? extends ServiceDescriptor> models()
+    {
+        return servicesModel.models();
+    }
+
+    @Override
+    public void activate()
+        throws ActivationException
+    {
+        Iterable<Activation> activatees = serviceReferences.stream().filter( Activation.class::isInstance )
+                                                           .map( Activation.class::cast )
+                                                           .collect( toList() );
+        activation.activate( ActivatorsInstance.EMPTY, activatees );
+    }
+
+    @Override
+    public void passivate()
+        throws PassivationException
+    {
+        activation.passivate();
+    }
+
+    public Stream<ServiceReference<?>> visibleServices( final Visibility visibility )
+    {
+        return serviceReferences.stream()
+            .filter( item -> ( (ServiceReferenceInstance) item ).serviceDescriptor()
+                                 .visibility().ordinal() >= visibility.ordinal() );
+    }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder( "Services{" );
+        String sep = " ";
+        for( ServiceReference serviceReference : serviceReferences )
+        {
+            sb.append( sep ).
+                append( serviceReference.identity() ).
+                append( "(active=" ).append( serviceReference.isActive() ).append( ")" );
+            sep = ", ";
+        }
+        return sb.append( " }" ).toString();
+    }
+
+    @Override
+    public void registerActivationEventListener( ActivationEventListener listener )
+    {
+        activation.registerActivationEventListener( listener );
+    }
+
+    @Override
+    public void deregisterActivationEventListener( ActivationEventListener listener )
+    {
+        activation.deregisterActivationEventListener( listener );
+    }
+
+    public Stream<? extends ServiceDescriptor> descriptors()
+    {
+        return servicesModel.models();
+    }
+
+    public Stream<ServiceReference<?>> references()
+    {
+        return serviceReferences.stream();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServicesModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServicesModel.java
new file mode 100644
index 0000000..ebdf64c
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServicesModel.java
@@ -0,0 +1,90 @@
+/*
+ *  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.polygene.runtime.service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * JAVADOC
+ */
+public class ServicesModel
+    implements VisitableHierarchy<Object, Object>
+{
+    private final List<ServiceModel> serviceModels;
+
+    public ServicesModel( List<ServiceModel> serviceModels )
+    {
+        this.serviceModels = serviceModels;
+    }
+
+    public ServicesInstance newInstance( ModuleDescriptor module )
+    {
+        List<ServiceReference<?>> serviceReferences = new ArrayList<>();
+        for( ServiceModel serviceModel : serviceModels )
+        {
+            ServiceReferenceInstance serviceReferenceInstance = new ServiceReferenceInstance( serviceModel, module );
+            serviceReferences.add( serviceReferenceInstance );
+        }
+
+        return new ServicesInstance( this, serviceReferences );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( ServiceModel serviceModel : serviceModels )
+            {
+                if( !serviceModel.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public Stream<? extends ServiceDescriptor> models()
+    {
+        return serviceModels.stream();
+    }
+
+    public boolean contains( Class<?> type )
+    {
+        for( ServiceModel model : serviceModels )
+        {
+            if( model.hasType( type ) )
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ApplicationInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ApplicationInstance.java
new file mode 100644
index 0000000..e27a0af
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ApplicationInstance.java
@@ -0,0 +1,174 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.ActivationEventListener;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.PolygeneRuntime;
+import org.apache.polygene.runtime.activation.ActivationDelegate;
+
+/**
+ * Instance of a Polygene application. Contains a list of layers which are managed by this application
+ */
+public class ApplicationInstance
+    implements Application
+{
+
+    // Constructor parameters
+    private final ApplicationModel applicationModel;
+    private final PolygeneRuntime runtime;
+    private final MetaInfo instanceMetaInfo;
+    // Eager instance objects
+    private final ActivationDelegate activation;
+    private final List<LayerInstance> layerInstances;
+
+    public ApplicationInstance( ApplicationModel model, PolygeneRuntime runtime, MetaInfo instanceMetaInfo )
+    {
+        // Constructor parameters
+        this.applicationModel = model;
+        this.runtime = runtime;
+        this.instanceMetaInfo = instanceMetaInfo;
+
+        // Eager instance objects
+        activation = new ActivationDelegate( this );
+        layerInstances = new ArrayList<>();
+    }
+
+    @Override
+    public String toString()
+    {
+        return name();
+    }
+
+    // Implementation of Application
+    @Override
+    public String name()
+    {
+        return applicationModel.name();
+    }
+
+    @Override
+    public String version()
+    {
+        return applicationModel.version();
+    }
+
+    @Override
+    public Mode mode()
+    {
+        return applicationModel.mode();
+    }
+
+    @Override
+    public Layer findLayer( String layerName )
+    {
+        for( LayerInstance layerInstance : layerInstances )
+        {
+            if( layerInstance.model().name().equals( layerName ) )
+            {
+                return layerInstance;
+            }
+        }
+
+        throw new IllegalArgumentException( "No such layer:" + layerName );
+    }
+
+    @Override
+    public Module findModule( String layerName, String moduleName )
+    {
+        for( LayerInstance layerInstance : layerInstances )
+        {
+            if( layerInstance.model().name().equals( layerName ) )
+            {
+                return layerInstance.findModule( moduleName );
+            }
+        }
+
+        throw new IllegalArgumentException( "No such layer:" + layerName );
+    }
+
+    @Override
+    public Stream<? extends Layer> layers()
+    {
+        return layerInstances.stream();
+    }
+
+    @Override
+    public ApplicationDescriptor descriptor()
+    {
+        return applicationModel;
+    }
+
+    // Implementation of MetaInfoHolder
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return instanceMetaInfo.get( infoType );
+    }
+
+    // Implementation of Activation
+    @Override
+    public void activate()
+        throws ActivationException
+    {
+        activation.activate( applicationModel.newActivatorsInstance(), layerInstances );
+    }
+
+    @Override
+    public void passivate()
+        throws PassivationException
+    {
+        activation.passivate();
+    }
+
+    @Override
+    public void registerActivationEventListener( ActivationEventListener listener )
+    {
+        activation.registerActivationEventListener( listener );
+    }
+
+    @Override
+    public void deregisterActivationEventListener( ActivationEventListener listener )
+    {
+        activation.deregisterActivationEventListener( listener );
+    }
+
+    // Other methods
+    void addLayer( LayerInstance layer )
+    {
+        layer.registerActivationEventListener( activation );
+        layerInstances.add( layer );
+    }
+
+    public PolygeneRuntime runtime()
+    {
+        return runtime;
+    }
+
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ApplicationModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ApplicationModel.java
new file mode 100644
index 0000000..a163bed
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ApplicationModel.java
@@ -0,0 +1,178 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.common.InvalidApplicationException;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.bootstrap.PolygeneRuntime;
+import org.apache.polygene.runtime.activation.ActivatorsInstance;
+import org.apache.polygene.runtime.activation.ActivatorsModel;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.injection.provider.InjectionProviderFactoryStrategy;
+
+/**
+ * JAVADOC
+ */
+public final class ApplicationModel
+    implements ApplicationDescriptor
+{
+    private final String name;
+    private final String version;
+    private final Application.Mode mode;
+    private final MetaInfo metaInfo;
+    private final ActivatorsModel<Application> activatorsModel;
+    private final List<LayerModel> layers;
+    private final InjectionProviderFactory ipf;
+
+    public ApplicationModel( String name,
+                             String version,
+                             Application.Mode mode,
+                             MetaInfo metaInfo,
+                             ActivatorsModel<Application> activatorsModel,
+                             List<LayerModel> layers
+    )
+    {
+        this.name = name;
+        this.version = version;
+        this.mode = mode;
+        this.metaInfo = metaInfo;
+        this.activatorsModel = activatorsModel;
+        this.layers = layers;
+        ipf = new InjectionProviderFactoryStrategy( metaInfo );
+    }
+
+    @Override
+    public String name()
+    {
+        return name;
+    }
+
+    public String version()
+    {
+        return version;
+    }
+
+    public Application.Mode mode()
+    {
+        return mode;
+    }
+
+    public MetaInfo metaInfo()
+    {
+        return metaInfo;
+    }
+
+    public ActivatorsInstance<Application> newActivatorsInstance()
+        throws ActivationException
+    {
+        return new ActivatorsInstance<>( activatorsModel.newInstances() );
+    }
+
+    // SPI
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            if( activatorsModel.accept( visitor ) )
+            {
+                for( LayerModel layer : layers )
+                {
+                    if( !layer.accept( visitor ) )
+                    {
+                        break;
+                    }
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    @Override
+    public ApplicationInstance newInstance( PolygeneAPI runtime, Object... importedServiceInstances )
+        throws InvalidApplicationException
+    {
+        MetaInfo instanceMetaInfo = new MetaInfo( metaInfo );
+        for( Object importedServiceInstance : importedServiceInstances )
+        {
+            instanceMetaInfo.set( importedServiceInstance );
+        }
+
+        ApplicationInstance applicationInstance = new ApplicationInstance( this, (PolygeneRuntime) runtime, instanceMetaInfo );
+
+        // Create layer instances
+        Map<LayerDescriptor, LayerDescriptor> layerInstanceMap = new HashMap<>();
+        Map<LayerDescriptor, List<LayerDescriptor>> usedLayers = new HashMap<>();
+        for( LayerModel layer : layers )
+        {
+            List<LayerDescriptor> usedLayerInstances = new ArrayList<>();
+            usedLayers.put( layer, usedLayerInstances );
+            UsedLayersInstance usedLayersInstance = layer.usedLayers().newInstance( usedLayerInstances );
+            LayerInstance layerInstance = layer.newInstance( applicationInstance );
+            applicationInstance.addLayer( layerInstance );
+            layerInstanceMap.put( layer, layerInstance.descriptor() );
+        }
+
+        // Resolve used layer instances
+        for( LayerModel layer : layers )
+        {
+            List<LayerDescriptor> usedLayerInstances = usedLayers.get( layer );
+            layer.usedLayers().layers().forEach(
+                usedLayer ->
+                {
+                    LayerDescriptor layerDescriptor = layerInstanceMap.get( usedLayer );
+                    if( layerDescriptor == null )
+                    {
+                        throw new InvalidApplicationException( "Could not find used layer:" + usedLayer
+                            .name() );
+                    }
+                    usedLayerInstances.add( layerDescriptor );
+                } );
+        }
+
+        return applicationInstance;
+    }
+
+    public InjectionProviderFactory injectionProviderFactory()
+    {
+        return ipf;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "ApplicationModel" +
+               "{name='" + name + '\'' +
+               ", version='" + version + '\'' +
+               ", mode=" + mode +
+               '}';
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/LayerInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/LayerInstance.java
new file mode 100644
index 0000000..09201fb
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/LayerInstance.java
@@ -0,0 +1,150 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.ActivationEventListener;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.runtime.activation.ActivationDelegate;
+
+/**
+ * Instance of a Polygene application layer. Contains a list of modules which are managed by this layer.
+ */
+public class LayerInstance
+    implements Layer
+{
+
+    // Constructor parameters
+    private final LayerModel layerModel;
+    private final ApplicationInstance applicationInstance;
+
+    // Eager instance objects
+    private final ActivationDelegate activation;
+    private final List<ModuleInstance> moduleInstances;
+
+    public LayerInstance( LayerModel model,
+                          ApplicationInstance applicationInstance
+    )
+    {
+        // Constructor parameters
+        this.layerModel = model;
+        this.applicationInstance = applicationInstance;
+
+        // Eager instance objects
+        activation = new ActivationDelegate( this );
+        moduleInstances = new ArrayList<>();
+    }
+
+    @Override
+    public String toString()
+    {
+        return layerModel.toString();
+    }
+
+    // Implementation of Layer
+    @Override
+    public String name()
+    {
+        return layerModel.name();
+    }
+
+    @Override
+    public Application application()
+    {
+        return applicationInstance;
+    }
+
+    // Implementation of MetaInfoHolder
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return layerModel.metaInfo( infoType );
+    }
+
+    // Implementation of Activation
+    @Override
+    public void activate()
+        throws ActivationException
+    {
+        activation.activate( layerModel.newActivatorsInstance(), moduleInstances );
+    }
+
+    @Override
+    public void passivate()
+        throws PassivationException
+    {
+        activation.passivate();
+    }
+
+    @Override
+    public void registerActivationEventListener( ActivationEventListener listener )
+    {
+        activation.registerActivationEventListener( listener );
+    }
+
+    @Override
+    public void deregisterActivationEventListener( ActivationEventListener listener )
+    {
+        activation.deregisterActivationEventListener( listener );
+    }
+
+    @Override
+    public Stream<? extends Module> modules()
+    {
+        return moduleInstances.stream();
+    }
+
+    @Override
+    public LayerDescriptor descriptor()
+    {
+        return layerModel;
+    }
+
+    void addModule( ModuleInstance module )
+    {
+        module.registerActivationEventListener( activation );
+        moduleInstances.add( module );
+    }
+
+    public LayerModel model()
+    {
+        return layerModel;
+    }
+
+    /* package */ ModuleInstance findModule( String moduleName )
+    {
+        for( ModuleInstance moduleInstance : moduleInstances )
+        {
+            if( moduleInstance.model().name().equals( moduleName ) )
+            {
+                return moduleInstance;
+            }
+        }
+
+        throw new IllegalArgumentException( "No such module:" + moduleName );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/LayerModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/LayerModel.java
new file mode 100644
index 0000000..04ca846
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/LayerModel.java
@@ -0,0 +1,170 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.runtime.activation.ActivatorsInstance;
+import org.apache.polygene.runtime.activation.ActivatorsModel;
+
+/**
+ * JAVADOC
+ */
+public final class LayerModel
+    implements LayerDescriptor, VisitableHierarchy<Object, Object>
+{
+    // Model
+    private final String name;
+    private final MetaInfo metaInfo;
+    private final UsedLayersModel usedLayersModel;
+    private final ActivatorsModel<Layer> activatorsModel;
+    private final List<ModuleModel> modules;
+    private LayerInstance layerInstance;
+
+    public LayerModel( String name,
+                       MetaInfo metaInfo,
+                       UsedLayersModel usedLayersModel,
+                       ActivatorsModel<Layer> activatorsModel,
+                       List<ModuleModel> modules
+    )
+    {
+        this.name = name;
+        this.metaInfo = metaInfo;
+        this.usedLayersModel = usedLayersModel;
+        this.activatorsModel = activatorsModel;
+        this.modules = modules;
+    }
+
+    @Override
+    public String name()
+    {
+        return name;
+    }
+
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return metaInfo.get( infoType );
+    }
+
+    public Iterable<ModuleModel> modules()
+    {
+        return modules;
+    }
+
+    @Override
+    public UsedLayersModel usedLayers()
+    {
+        return usedLayersModel;
+    }
+
+    public ActivatorsInstance<Layer> newActivatorsInstance()
+        throws ActivationException
+    {
+        return new ActivatorsInstance<>( activatorsModel.newInstances() );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            if( activatorsModel.accept( modelVisitor ) )
+            {
+                for( ModuleModel module : modules )
+                {
+                    if( !module.accept( modelVisitor ) )
+                    {
+                        break;
+                    }
+                }
+            }
+        }
+        return modelVisitor.visitLeave( this );
+    }
+
+    @Override
+    public Layer instance()
+    {
+        return layerInstance;
+    }
+
+    public LayerInstance newInstance( ApplicationInstance applicationInstance )
+    {
+        layerInstance = new LayerInstance( this, applicationInstance );
+        for( ModuleModel module : modules )
+        {
+            ModuleInstance moduleInstance = module.newInstance( this );
+            layerInstance.addModule( moduleInstance );
+        }
+        return layerInstance;
+    }
+
+    @Override
+    public Stream<? extends ObjectDescriptor> visibleObjects( final Visibility visibility )
+    {
+        return modules.stream().flatMap( module -> module.visibleObjects( visibility ) );
+    }
+
+    @Override
+    public Stream<? extends TransientDescriptor> visibleTransients( final Visibility visibility )
+    {
+        return modules.stream().flatMap( module -> module.visibleTransients( visibility ) );
+    }
+
+    @Override
+    public Stream<? extends EntityDescriptor> visibleEntities( final Visibility visibility )
+    {
+        return modules.stream().flatMap( module -> module.visibleEntities( visibility ) );
+    }
+
+    /* package */
+    @Override
+    public Stream<? extends ValueDescriptor> visibleValues( final Visibility visibility )
+    {
+        return modules.stream().flatMap( module -> module.visibleValues( visibility ) );
+    }
+
+    /* package */
+    @Override
+    public Stream<? extends ModelDescriptor> visibleServices( final Visibility visibility )
+    {
+        return modules.stream().flatMap( module -> module.visibleServices( visibility ) );
+    }
+
+
+    @Override
+    public String toString()
+    {
+        return name;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleClassLoader.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleClassLoader.java
new file mode 100644
index 0000000..2737261
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleClassLoader.java
@@ -0,0 +1,182 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.AmbiguousTypeException;
+import org.apache.polygene.api.composite.ModelDescriptor;
+
+import static java.util.stream.Stream.concat;
+import static org.apache.polygene.api.common.Visibility.application;
+import static org.apache.polygene.api.common.Visibility.module;
+import static org.apache.polygene.api.util.Classes.modelTypeSpecification;
+
+// Module ClassLoader
+class ModuleClassLoader
+    extends ClassLoader
+{
+
+    private final ModuleModel moduleModel;
+    private final ConcurrentHashMap<String, Class<?>> classes = new ConcurrentHashMap<>();
+
+    ModuleClassLoader( ModuleModel moduleModel, ClassLoader classLoader )
+    {
+        super( classLoader );
+        this.moduleModel = moduleModel;
+    }
+
+    @Override
+    protected Class<?> findClass( String className )
+        throws ClassNotFoundException
+    {
+        try
+        {
+            Class<?> resultingClass = classes.computeIfAbsent( className, name ->
+            {
+                Predicate<ModelDescriptor> modelTypeSpecification = modelTypeSpecification( name );
+                Stream<? extends ModelDescriptor> moduleModels = concat(
+                    moduleModel.visibleObjects( Visibility.module ),
+                    concat(
+                        moduleModel.visibleEntities( Visibility.module ),
+                        concat(
+                            moduleModel.visibleTransients( Visibility.module ),
+                            moduleModel.visibleValues( Visibility.module )
+                        )
+                    )
+                ).filter( modelTypeSpecification );
+
+                Class<?> clazz = null;
+                Iterator<? extends ModelDescriptor> iterator = moduleModels.iterator();
+                if( iterator.hasNext() )
+                {
+                    clazz = iterator.next().types().findFirst().orElse( null );
+
+                    if( iterator.hasNext() )
+                    {
+                        // Ambiguous exception
+                        throw new AmbiguousTypeException(
+                            "More than one model matches the classname " + name + ":" + iterator.next()
+                        );
+                    }
+                }
+
+                // Check layer
+                if( clazz == null )
+                {
+                    Stream<? extends ModelDescriptor> modelsInLayer1 = concat(
+                        moduleModel.layer().visibleObjects( Visibility.layer ),
+                        concat(
+                            moduleModel.layer().visibleEntities( Visibility.layer ),
+                            concat(
+                                moduleModel.layer().visibleTransients( Visibility.layer ),
+                                moduleModel.layer().visibleValues( Visibility.layer )
+                            )
+                        )
+                    );
+                    // TODO: What does this actually represents?? Shouldn't 'application' visible models already be handed back from lasyerInstance().visibleXyz() ??
+                    Stream<? extends ModelDescriptor> modelsInLayer2 = concat(
+                        moduleModel.layer().visibleObjects( Visibility.application ),
+                        concat(
+                            moduleModel.layer().visibleEntities( Visibility.application ),
+                            concat(
+                                moduleModel.layer().visibleTransients( Visibility.application ),
+                                moduleModel.layer().visibleValues( Visibility.application )
+                            )
+                        )
+                    );
+                    Stream<? extends ModelDescriptor> layerModels = concat(
+                        modelsInLayer1,
+                        modelsInLayer2
+                    ).filter( modelTypeSpecification );
+
+                    Iterator<? extends ModelDescriptor> layerModelsIter = layerModels.iterator();
+                    if( layerModelsIter.hasNext() )
+                    {
+                        clazz = layerModelsIter.next().types().findFirst().orElse( null );
+
+                        if( layerModelsIter.hasNext() )
+                        {
+                            // Ambiguous exception
+                            throw new AmbiguousTypeException(
+                                "More than one model matches the classname " + name + ":" + layerModelsIter.next()
+                            );
+                        }
+                    }
+                }
+
+                // Check used layers
+                if( clazz == null )
+                {
+                    Stream<? extends ModelDescriptor> usedLayersModels = concat(
+                        moduleModel.layer()
+                            .usedLayers()
+                            .layers()
+                            .flatMap( layer -> layer.visibleObjects( module ) ),
+                        concat(
+                            moduleModel.layer()
+                                .usedLayers()
+                                .layers()
+                                .flatMap( layer -> layer.visibleEntities( Visibility.layer ) ),
+                            concat(
+                                moduleModel.layer()
+                                    .usedLayers()
+                                    .layers()
+                                    .flatMap( layer -> layer.visibleTransients( application ) ),
+                                moduleModel.layer()
+                                    .usedLayers()
+                                    .layers()
+                                    .flatMap( layer -> layer.visibleValues( application ) )
+                            )
+                        )
+                    ).filter( modelTypeSpecification );
+
+                    Iterator<? extends ModelDescriptor> usedLayersModelsIter = usedLayersModels.iterator();
+                    if( usedLayersModelsIter.hasNext() )
+                    {
+                        clazz = usedLayersModelsIter.next().types().findFirst().orElse( null );
+
+                        if( usedLayersModelsIter.hasNext() )
+                        {
+                            // Ambiguous exception
+                            throw new AmbiguousTypeException(
+                                "More than one model matches the classname " + name + ":" + usedLayersModelsIter.next()
+                            );
+                        }
+                    }
+                }
+                return clazz;
+            } );
+            if( resultingClass == null )
+            {
+                throw new ClassNotFoundException();
+            }
+            return resultingClass;
+        }
+        catch( AmbiguousTypeException e )
+        {
+            throw new ClassNotFoundException( className, e );
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleInstance.java
new file mode 100644
index 0000000..955df41
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleInstance.java
@@ -0,0 +1,608 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivationEventListener;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.composite.NoSuchTransientException;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.IdentityGenerator;
+import org.apache.polygene.api.metrics.MetricsProvider;
+import org.apache.polygene.api.object.NoSuchObjectException;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.service.NoSuchServiceException;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.structure.TypeLookup;
+import org.apache.polygene.api.type.HasTypes;
+import org.apache.polygene.api.unitofwork.UnitOfWorkException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.NoSuchValueException;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.runtime.activation.ActivationDelegate;
+import org.apache.polygene.runtime.composite.FunctionStateResolver;
+import org.apache.polygene.runtime.composite.StateResolver;
+import org.apache.polygene.runtime.composite.TransientBuilderInstance;
+import org.apache.polygene.runtime.composite.TransientStateInstance;
+import org.apache.polygene.runtime.composite.UsesInstance;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.object.ObjectModel;
+import org.apache.polygene.runtime.property.PropertyInstance;
+import org.apache.polygene.runtime.property.PropertyModel;
+import org.apache.polygene.runtime.query.QueryBuilderFactoryImpl;
+import org.apache.polygene.runtime.service.ImportedServicesInstance;
+import org.apache.polygene.runtime.service.ImportedServicesModel;
+import org.apache.polygene.runtime.service.ServicesInstance;
+import org.apache.polygene.runtime.service.ServicesModel;
+import org.apache.polygene.runtime.type.ValueTypeFactoryInstance;
+import org.apache.polygene.runtime.value.ValueBuilderInstance;
+import org.apache.polygene.runtime.value.ValueBuilderWithPrototype;
+import org.apache.polygene.runtime.value.ValueBuilderWithState;
+import org.apache.polygene.runtime.value.ValueInstance;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.metrics.MetricsProviderAdapter;
+import org.apache.polygene.spi.module.ModuleSpi;
+
+import static java.util.Arrays.asList;
+import static java.util.stream.Stream.concat;
+import static org.apache.polygene.api.composite.CompositeInstance.compositeInstanceOf;
+
+/**
+ * Instance of a Polygene Module. Contains the various composites for this Module.
+ */
+public class ModuleInstance
+    implements Module, ModuleSpi, Activation
+{
+    // Constructor parameters
+    private final ModuleModel model;
+    private final LayerDescriptor layer;
+    private final TypeLookup typeLookup;
+    private final ServicesInstance services;
+    private final ImportedServicesInstance importedServices;
+    // Eager instance objects
+    private final ActivationDelegate activation;
+    private final QueryBuilderFactory queryBuilderFactory;
+    // Lazy assigned on accessors
+    private EntityStore store;
+    private IdentityGenerator generator;
+    private Serialization serialization;
+    private MetricsProvider metrics;
+    private UnitOfWorkFactory uowf;
+
+    @SuppressWarnings( "LeakingThisInConstructor" )
+    ModuleInstance( ModuleModel moduleModel, LayerDescriptor layer, TypeLookup typeLookup,
+                           ServicesModel servicesModel, ImportedServicesModel importedServicesModel
+    )
+    {
+        // Constructor parameters
+        model = moduleModel;
+        this.layer = layer;
+        this.typeLookup = typeLookup;
+        services = servicesModel.newInstance( moduleModel );
+        importedServices = importedServicesModel.newInstance( moduleModel );
+
+        // Eager instance objects
+        activation = new ActivationDelegate( this );
+        queryBuilderFactory = new QueryBuilderFactoryImpl( this );
+
+        // Activation
+        services.registerActivationEventListener( activation );
+        importedServices.registerActivationEventListener( activation );
+    }
+
+    @Override
+    public String toString()
+    {
+        return model.toString();
+    }
+
+    @Override
+    public ModuleDescriptor descriptor()
+    {
+        return model;
+    }
+
+    // Implementation of Module
+    @Override
+    public String name()
+    {
+        return model.name();
+    }
+
+    // Implementation of MetaInfoHolder
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return model.metaInfo( infoType );
+    }
+
+    // Implementation of ObjectFactory
+    @Override
+    public <T> T newObject( Class<T> mixinType, Object... uses )
+        throws NoSuchObjectException
+    {
+        Objects.requireNonNull( mixinType, "mixinType" );
+        ObjectDescriptor model = typeLookup.lookupObjectModel( mixinType );
+
+        if( model == null )
+        {
+            throw new NoSuchObjectException( mixinType.getName(), name(),
+                                             typeLookup.allObjects().flatMap( HasTypes::types ) );
+        }
+
+        InjectionContext injectionContext = new InjectionContext( model.module(), UsesInstance.EMPTY_USES.use( uses ) );
+        return mixinType.cast( ( (ObjectModel) model ).newInstance( injectionContext ) );
+    }
+
+    @Override
+    public void injectTo( Object instance, Object... uses )
+        throws ConstructionException
+    {
+        Objects.requireNonNull( instance, "instance" );
+        ObjectDescriptor model = typeLookup.lookupObjectModel( instance.getClass() );
+
+        if( model == null )
+        {
+            throw new NoSuchObjectException( instance.getClass().getName(), name(),
+                                             typeLookup.allObjects().flatMap( HasTypes::types ) );
+        }
+
+        InjectionContext injectionContext = new InjectionContext( model.module(), UsesInstance.EMPTY_USES.use( uses ) );
+        ( (ObjectModel) model ).inject( injectionContext, instance );
+    }
+
+    // Implementation of TransientBuilderFactory
+    @Override
+    public <T> TransientBuilder<T> newTransientBuilder( Class<T> mixinType )
+        throws NoSuchTransientException
+    {
+        Objects.requireNonNull( mixinType, "mixinType" );
+        TransientDescriptor model = typeLookup.lookupTransientModel( mixinType );
+
+        if( model == null )
+        {
+            throw new NoSuchTransientException( mixinType.getName(), name(), typeLookup );
+        }
+
+        Map<AccessibleObject, Property<?>> properties = new HashMap<>();
+        model.state().properties().forEach(
+            propertyModel ->
+            {
+                Object initialValue = propertyModel.resolveInitialValue( model.module() );
+                Property<?> property = new PropertyInstance<>( ( (PropertyModel) propertyModel ).getBuilderInfo(),
+                                                               initialValue );
+                properties.put( propertyModel.accessor(), property );
+            } );
+
+        TransientStateInstance state = new TransientStateInstance( properties );
+
+        return new TransientBuilderInstance<>( model, state, UsesInstance.EMPTY_USES );
+    }
+
+    @Override
+    public <T> T newTransient( final Class<T> mixinType, Object... uses )
+        throws NoSuchTransientException, ConstructionException
+    {
+        return newTransientBuilder( mixinType ).use( uses ).newInstance();
+    }
+
+    // Implementation of ValueBuilderFactory
+    @Override
+    public <T> T newValue( Class<T> mixinType )
+        throws NoSuchValueException, ConstructionException
+    {
+        return newValueBuilder( mixinType ).newInstance();
+    }
+
+    @Override
+    public <T> ValueBuilder<T> newValueBuilder( Class<T> mixinType )
+        throws NoSuchValueException
+    {
+        Objects.requireNonNull( mixinType, "mixinType" );
+        ValueDescriptor compositeModelModule = typeLookup.lookupValueModel( mixinType );
+
+        if( compositeModelModule == null )
+        {
+            throw new NoSuchValueException( mixinType.getName(), name(), typeLookup );
+        }
+
+        StateResolver stateResolver = new InitialStateResolver( compositeModelModule.module() );
+        return new ValueBuilderInstance<>( compositeModelModule, this, stateResolver );
+    }
+
+    @Override
+    public <T> ValueBuilder<T> newValueBuilderWithState( Class<T> mixinType,
+                                                         Function<PropertyDescriptor, Object> propertyFunction,
+                                                         Function<AssociationDescriptor, EntityReference> associationFunction,
+                                                         Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction,
+                                                         Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction
+    )
+    {
+        Objects.requireNonNull( propertyFunction, "propertyFunction" );
+        Objects.requireNonNull( associationFunction, "associationFunction" );
+        Objects.requireNonNull( manyAssociationFunction, "manyAssociationFunction" );
+        Objects.requireNonNull( namedAssociationFunction, "namedAssociationFunction" );
+
+        ValueDescriptor compositeModelModule = typeLookup.lookupValueModel( mixinType );
+
+        if( compositeModelModule == null )
+        {
+            throw new NoSuchValueException( mixinType.getName(), name(), typeLookup );
+        }
+
+        StateResolver stateResolver = new FunctionStateResolver(
+            propertyFunction, associationFunction, manyAssociationFunction, namedAssociationFunction
+        );
+        return new ValueBuilderWithState<>( compositeModelModule, this, stateResolver );
+    }
+
+    private static class InitialStateResolver
+        implements StateResolver
+    {
+        private final ModuleDescriptor module;
+
+        private InitialStateResolver( ModuleDescriptor module )
+        {
+            this.module = module;
+        }
+
+        @Override
+        public Object getPropertyState( PropertyDescriptor propertyDescriptor )
+        {
+            return propertyDescriptor.resolveInitialValue( module );
+        }
+
+        @Override
+        public EntityReference getAssociationState( AssociationDescriptor associationDescriptor )
+        {
+            return null;
+        }
+
+        @Override
+        public Stream<EntityReference> getManyAssociationState( AssociationDescriptor associationDescriptor )
+        {
+            return new ArrayList<EntityReference>().stream();
+        }
+
+        @Override
+        public Stream<Map.Entry<String, EntityReference>>
+        getNamedAssociationState( AssociationDescriptor associationDescriptor )
+        {
+            return new HashMap<String, EntityReference>().entrySet().stream();
+        }
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> ValueBuilder<T> newValueBuilderWithPrototype( T prototype )
+    {
+        Objects.requireNonNull( prototype, "prototype" );
+
+        ValueInstance valueInstance = (ValueInstance) compositeInstanceOf( (Composite) prototype );
+        Class<Composite> valueType = (Class<Composite>) valueInstance.types().findFirst().orElse( null );
+
+        ValueDescriptor model = typeLookup.lookupValueModel( valueType );
+
+        if( model == null )
+        {
+            throw new NoSuchValueException( valueType.getName(), name(), typeLookup );
+        }
+
+        return new ValueBuilderWithPrototype<>( model, this, prototype );
+    }
+
+    @Override
+    public <T> T newValueFromSerializedState( Class<T> mixinType, String serializedState )
+        throws NoSuchValueException, ConstructionException
+    {
+        Objects.requireNonNull( mixinType, "mixinType" );
+        ValueDescriptor model = typeLookup.lookupValueModel( mixinType );
+
+        if( model == null )
+        {
+            throw new NoSuchValueException( mixinType.getName(), name(), typeLookup );
+        }
+
+        try
+        {
+            return serialization().deserialize( model.module(), model.valueType(), serializedState );
+        }
+        catch( SerializationException ex )
+        {
+            throw new ConstructionException( "Could not create value from serialized state", ex );
+        }
+    }
+
+    // Implementation of QueryBuilderFactory
+    @Override
+    public <T> QueryBuilder<T> newQueryBuilder( final Class<T> resultType )
+    {
+        return queryBuilderFactory.newQueryBuilder( resultType );
+    }
+
+    @Override
+    public <T> ServiceReference<T> findService( Class<T> serviceType )
+        throws NoSuchServiceException
+    {
+        return findService( (Type) serviceType );
+    }
+
+    @Override
+    public <T> ServiceReference<T> findService( Type serviceType )
+    {
+        ModelDescriptor serviceModel = typeLookup.lookupServiceModel( serviceType );
+        if( serviceModel == null )
+        {
+            throw new NoSuchServiceException( serviceType.getTypeName(), name(), typeLookup );
+        }
+        return findServiceReferenceInstance( serviceModel );
+    }
+
+    @Override
+    public <T> Stream<ServiceReference<T>> findServices( final Class<T> serviceType )
+    {
+        return findServices( (Type) serviceType );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> Stream<ServiceReference<T>> findServices( final Type serviceType )
+    {
+        List<? extends ModelDescriptor> serviceModels = typeLookup.lookupServiceModels( serviceType );
+        if( serviceModels == null )
+        {
+            return Stream.empty();
+        }
+        //noinspection unchecked
+        return serviceModels.stream()
+                            .map( this::findServiceReferenceInstance )
+                            .filter( Objects::nonNull )
+                            .filter( ref -> ref.hasType( serviceType ) )
+                            .map( ref -> (ServiceReference<T>) ref );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private <T> ServiceReference<T> findServiceReferenceInstance( ModelDescriptor model )
+    {
+        ModuleInstance moduleInstanceOfModel = (ModuleInstance) model.module().instance();
+        Optional<ServiceReference<?>> candidate =
+            concat( moduleInstanceOfModel.services.references(), moduleInstanceOfModel.importedServices.references() )
+                .filter( ref -> ref.model().equals( model ) )
+                .findAny();
+        if( candidate.isPresent() )
+        {
+            ServiceReference<?> serviceReference = candidate.get();
+            return (ServiceReference<T>) serviceReference;
+        }
+        return null;
+    }
+
+    // Implementation of Activation
+    @Override
+    public void activate()
+        throws ActivationException
+    {
+        activation.activate( model.newActivatorsInstance(), asList( services, importedServices ) );
+    }
+
+    @Override
+    public void passivate()
+        throws PassivationException
+    {
+        activation.passivate();
+    }
+
+    @Override
+    public void registerActivationEventListener( ActivationEventListener listener )
+    {
+        activation.registerActivationEventListener( listener );
+    }
+
+    @Override
+    public void deregisterActivationEventListener( ActivationEventListener listener )
+    {
+        activation.deregisterActivationEventListener( listener );
+    }
+
+    // Other methods
+    ModuleModel model()
+    {
+        return model;
+    }
+
+    @Override
+    public LayerDescriptor layer()
+    {
+        return layer;
+    }
+
+    @Override
+    public TypeLookup typeLookup()
+    {
+        return typeLookup;
+    }
+
+    @Override
+    public EntityStore entityStore()
+    {
+        if( store == null )
+        {
+            synchronized( this )
+            {
+                if( store == null )
+                {
+                    try
+                    {
+                        ServiceReference<EntityStore> service = findService( EntityStore.class );
+                        store = service.get();
+                    }
+                    catch( NoSuchServiceException e )
+                    {
+                        throw new UnitOfWorkException( "No EntityStore service available in module " + name() );
+                    }
+                }
+            }
+        }
+        return store;
+    }
+
+    @Override
+    public UnitOfWorkFactory unitOfWorkFactory()
+    {
+        if( uowf == null )
+        {
+            synchronized( this )
+            {
+                if( uowf == null )
+                {
+                    try
+                    {
+                        ServiceReference<UnitOfWorkFactory> service = findService( UnitOfWorkFactory.class );
+                        uowf = service.get();
+                    }
+                    catch( NoSuchServiceException e )
+                    {
+                        throw new UnitOfWorkException( "No UnitOfWorkFactory service available in module " + name() );
+                    }
+                }
+            }
+        }
+        return uowf;
+    }
+
+    @Override
+    public ServiceFinder serviceFinder()
+    {
+        return this;
+    }
+
+    @Override
+    public ValueBuilderFactory valueBuilderFactory()
+    {
+        return this;
+    }
+
+    @Override
+    public TransientBuilderFactory transientBuilderFactory()
+    {
+        return this;
+    }
+
+    @Override
+    public ObjectFactory objectFactory()
+    {
+        return this;
+    }
+
+    @Override
+    public IdentityGenerator identityGenerator()
+    {
+        if( generator == null )
+        {
+            synchronized( this )
+            {
+                if( generator == null )
+                {
+                    ServiceReference<IdentityGenerator> service = findService( IdentityGenerator.class );
+                    generator = service.get();
+                }
+            }
+        }
+        return generator;
+    }
+
+    @Override
+    public Serialization serialization()
+    {
+        if( serialization == null )
+        {
+            synchronized( this )
+            {
+                if( serialization == null )
+                {
+                    ServiceReference<Serialization> service = findService( Serialization.class );
+                    serialization = service.get();
+                }
+            }
+        }
+        return serialization;
+    }
+
+    @Override
+    public MetricsProvider metricsProvider()
+    {
+        if( metrics == null )
+        {
+            synchronized( this )
+            {
+                if( metrics == null )
+                {
+                    try
+                    {
+                        ServiceReference<MetricsProvider> service = findService( MetricsProvider.class );
+                        metrics = service.get();
+                    }
+                    catch( NoSuchServiceException e )
+                    {
+                        metrics = new MetricsProviderAdapter();
+                    }
+                }
+            }
+        }
+        return metrics;
+    }
+
+    @Override
+    public ValueTypeFactoryInstance valueTypeFactory()
+    {
+        return ValueTypeFactoryInstance.instance();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleModel.java
new file mode 100644
index 0000000..6b556a5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleModel.java
@@ -0,0 +1,394 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.structure.TypeLookup;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.runtime.activation.ActivatorsInstance;
+import org.apache.polygene.runtime.activation.ActivatorsModel;
+import org.apache.polygene.runtime.composite.TransientsModel;
+import org.apache.polygene.runtime.entity.EntitiesModel;
+import org.apache.polygene.runtime.object.ObjectsModel;
+import org.apache.polygene.runtime.service.ImportedServicesModel;
+import org.apache.polygene.runtime.service.ServicesModel;
+import org.apache.polygene.runtime.value.ValuesModel;
+
+import static java.util.stream.Stream.concat;
+import static org.apache.polygene.api.common.Visibility.application;
+import static org.apache.polygene.api.common.Visibility.layer;
+import static org.apache.polygene.api.common.Visibility.module;
+
+/**
+ * JAVADOC
+ */
+public class ModuleModel
+    implements ModuleDescriptor, VisitableHierarchy<Object, Object>
+{
+    private final LayerDescriptor layerModel;
+    private final ActivatorsModel<Module> activatorsModel;
+    private final TransientsModel transientsModel;
+    private final EntitiesModel entitiesModel;
+    private final ObjectsModel objectsModel;
+    private final ValuesModel valuesModel;
+    private final ServicesModel servicesModel;
+    private final ImportedServicesModel importedServicesModel;
+    private final TypeLookupImpl typeLookup;
+    private final ClassLoader classLoader;
+
+    private final String name;
+    private final MetaInfo metaInfo;
+    private ModuleInstance moduleInstance;
+
+    public ModuleModel( String name,
+                        MetaInfo metaInfo,
+                        LayerDescriptor layerModel,
+                        ActivatorsModel<Module> activatorsModel,
+                        TransientsModel transientsModel,
+                        EntitiesModel entitiesModel,
+                        ObjectsModel objectsModel,
+                        ValuesModel valuesModel,
+                        ServicesModel servicesModel,
+                        ImportedServicesModel importedServicesModel
+    )
+    {
+        this.name = name;
+        this.metaInfo = metaInfo;
+        this.layerModel = layerModel;
+        this.activatorsModel = activatorsModel;
+        this.transientsModel = transientsModel;
+        this.entitiesModel = entitiesModel;
+        this.objectsModel = objectsModel;
+        this.valuesModel = valuesModel;
+        this.servicesModel = servicesModel;
+        this.importedServicesModel = importedServicesModel;
+        typeLookup = new TypeLookupImpl( this );
+        classLoader = new ModuleClassLoader( this, Thread.currentThread().getContextClassLoader() );
+    }
+
+    @Override
+    public String name()
+    {
+        return name;
+    }
+
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return metaInfo.get( infoType );
+    }
+
+    @Override
+    public LayerDescriptor layer()
+    {
+        return layerModel;
+    }
+
+    @Override
+    public ClassLoader classLoader()
+    {
+        return classLoader;
+    }
+
+    public ActivatorsInstance<Module> newActivatorsInstance()
+        throws ActivationException
+    {
+        return new ActivatorsInstance<>( activatorsModel.newInstances() );
+    }
+
+    @Override
+    public EntityDescriptor entityDescriptor( String name )
+    {
+        try
+        {
+            Class<?> type = classLoader().loadClass( name );
+            EntityDescriptor entityModel = typeLookup.lookupEntityModel( type );
+            if( entityModel == null )
+            {
+                return null;
+            }
+            return entityModel;
+        }
+        catch( ClassNotFoundException e )
+        {
+            return null;
+        }
+    }
+
+    @Override
+    public ObjectDescriptor objectDescriptor( String typeName )
+    {
+        try
+        {
+            Class<?> type = classLoader().loadClass( typeName );
+            ObjectDescriptor objectModel = typeLookup.lookupObjectModel( type );
+            if( objectModel == null )
+            {
+                return null;
+            }
+            return objectModel;
+        }
+        catch( ClassNotFoundException e )
+        {
+            return null;
+        }
+    }
+
+    @Override
+    public TransientDescriptor transientDescriptor( String name )
+    {
+        try
+        {
+            Class<?> type = classLoader().loadClass( name );
+            TransientDescriptor transientModel = typeLookup.lookupTransientModel( type );
+            if( transientModel == null )
+            {
+                return null;
+            }
+            return transientModel;
+        }
+        catch( ClassNotFoundException e )
+        {
+            return null;
+        }
+    }
+
+    @Override
+    public ValueDescriptor valueDescriptor( String name )
+    {
+        try
+        {
+            Class<?> type = classLoader().loadClass( name );
+            ValueDescriptor valueModel = typeLookup.lookupValueModel( type );
+            if( valueModel == null )
+            {
+                return null;
+            }
+            return valueModel;
+        }
+        catch( ClassNotFoundException e )
+        {
+            return null;
+        }
+    }
+
+    @Override
+    public Module instance()
+    {
+        return moduleInstance;
+    }
+
+    @Override
+    public TypeLookup typeLookup()
+    {
+        return typeLookup;
+    }
+
+    public ModuleInstance newInstance( LayerDescriptor layerInstance )
+    {
+        moduleInstance = new ModuleInstance( this, layerInstance, typeLookup, servicesModel, importedServicesModel );
+        return moduleInstance;
+    }
+
+    @Override
+    public Stream<? extends TransientDescriptor> transientComposites()
+    {
+        return transientsModel.stream();
+    }
+
+    @Override
+    public Stream<? extends ValueDescriptor> valueComposites()
+    {
+        return valuesModel.stream();
+    }
+
+    @Override
+    public Stream<? extends ServiceDescriptor> serviceComposites()
+    {
+        return servicesModel.models();
+    }
+
+    @Override
+    public Stream<? extends EntityDescriptor> entityComposites()
+    {
+        return entitiesModel.stream();
+    }
+
+    @Override
+    public Stream<? extends ImportedServiceDescriptor> importedServices()
+    {
+        return importedServicesModel.models();
+    }
+
+    @Override
+    public Stream<? extends ObjectDescriptor> objects()
+    {
+        return objectsModel.models();
+    }
+
+    public Stream<? extends ValueDescriptor> findVisibleValueTypes()
+    {
+        return concat( visibleValues( module ),
+                       concat(
+                           layer().visibleValues( layer ),
+                           concat(
+                               layer().visibleValues( application ),
+                               layer().usedLayers().layers().flatMap( layer1 -> layer1.visibleValues( application ) )
+                           )
+                       )
+        );
+    }
+
+    public Stream<? extends EntityDescriptor> findVisibleEntityTypes()
+    {
+        return concat( visibleEntities( module ),
+                       concat(
+                           layer().visibleEntities( layer ),
+                           concat(
+                               layer().visibleEntities( application ),
+                               layer().usedLayers().layers().flatMap( layer1 -> layer1.visibleEntities( application ) )
+                           )
+                       )
+        );
+    }
+
+    public Stream<? extends TransientDescriptor> findVisibleTransientTypes()
+    {
+        return concat( visibleTransients( module ),
+                       concat(
+                           layer().visibleTransients( layer ),
+                           concat(
+                               layer().visibleTransients( application ),
+                               layer().usedLayers()
+                                   .layers()
+                                   .flatMap( layer1 -> layer1.visibleTransients( application ) )
+                           )
+                       )
+        );
+    }
+
+    public Stream<? extends ModelDescriptor> findVisibleServiceTypes()
+    {
+        return concat( visibleServices( module ),
+                       concat(
+                           layer().visibleServices( layer ),
+                           concat(
+                               layer().visibleServices( application ),
+                               layer().usedLayers().layers().flatMap( layer1 -> layer1.visibleServices( application ) )
+                           )
+                       )
+        );
+    }
+
+    public Stream<? extends ObjectDescriptor> findVisibleObjectTypes()
+    {
+        return concat( visibleObjects( module ),
+                       concat(
+                           layer().visibleObjects( layer ),
+                           concat(
+                               layer().visibleObjects( application ),
+                               layer().usedLayers().layers().flatMap( layer -> layer.visibleObjects( application ) )
+                           )
+                       )
+        );
+    }
+
+    public Stream<? extends ObjectDescriptor> visibleObjects( Visibility visibility )
+    {
+        return objectsModel.models()
+            .filter( new VisibilityPredicate( visibility ) );
+    }
+
+    public Stream<? extends TransientDescriptor> visibleTransients( Visibility visibility )
+    {
+        return transientsModel.models()
+            .filter( new VisibilityPredicate( visibility ) );
+    }
+
+    public Stream<? extends EntityDescriptor> visibleEntities( Visibility visibility )
+    {
+        return entitiesModel.models()
+            .filter( new VisibilityPredicate( visibility ) );
+    }
+
+    public Stream<? extends ValueDescriptor> visibleValues( Visibility visibility )
+    {
+        return valuesModel.models()
+            .filter( new VisibilityPredicate( visibility ) );
+    }
+
+    public Stream<? extends ModelDescriptor> visibleServices( Visibility visibility )
+    {
+        return concat(
+            servicesModel.models()
+                .filter( new VisibilityPredicate( visibility ) ),
+            importedServicesModel.models()
+                .filter( new VisibilityPredicate( visibility ) )
+        );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            if( activatorsModel.accept( modelVisitor ) )
+            {
+                if( transientsModel.accept( modelVisitor ) )
+                {
+                    if( entitiesModel.accept( modelVisitor ) )
+                    {
+                        if( servicesModel.accept( modelVisitor ) )
+                        {
+                            if( importedServicesModel.accept( modelVisitor ) )
+                            {
+                                if( objectsModel.accept( modelVisitor ) )
+                                {
+                                    valuesModel.accept( modelVisitor );
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return modelVisitor.visitLeave( this );
+    }
+
+    @Override
+    public String toString()
+    {
+        return name;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/TypeLookupImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/TypeLookupImpl.java
new file mode 100644
index 0000000..6f55c88
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/TypeLookupImpl.java
@@ -0,0 +1,356 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.AmbiguousTypeException;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.structure.TypeLookup;
+import org.apache.polygene.api.type.HasAssignableFromType;
+import org.apache.polygene.api.type.HasEqualType;
+import org.apache.polygene.api.type.HasTypesCollectors;
+import org.apache.polygene.api.value.ValueDescriptor;
+
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Stream.concat;
+import static org.apache.polygene.api.common.Visibility.application;
+import static org.apache.polygene.api.common.Visibility.layer;
+
+/**
+ * Central place for Composite Type lookups.
+ */
+class TypeLookupImpl
+    implements TypeLookup
+{
+    private final LazyValue<List<ObjectDescriptor>> allObjects;
+    private final LazyValue<List<TransientDescriptor>> allTransients;
+    private final LazyValue<List<ValueDescriptor>> allValues;
+    private final LazyValue<List<EntityDescriptor>> allEntities;
+    private final LazyValue<List<? extends ModelDescriptor>> allServices;
+    private final ConcurrentHashMap<Class<?>, ObjectDescriptor> objectModels;
+    private final ConcurrentHashMap<Class<?>, TransientDescriptor> transientModels;
+    private final ConcurrentHashMap<Class<?>, ValueDescriptor> valueModels;
+    private final ConcurrentHashMap<Class<?>, List<EntityDescriptor>> entityModels;
+    private final ConcurrentHashMap<Class<?>, EntityDescriptor> unambiguousEntityModels;
+    private final ConcurrentHashMap<Type, ModelDescriptor> serviceModels;
+    private final ConcurrentHashMap<Type, List<? extends ModelDescriptor>> servicesReferences;
+
+    private final ModuleDescriptor module;
+
+    /**
+     * Create a new TypeLookup bound to the given Module.
+     *
+     * @param module Module bound to this TypeLookup
+     */
+    TypeLookupImpl( ModuleDescriptor module )
+    {
+        this.module = module;
+
+        // Instance caches
+        allObjects = new LazyValue<>();
+        allTransients = new LazyValue<>();
+        allValues = new LazyValue<>();
+        allEntities = new LazyValue<>();
+        allServices = new LazyValue<>();
+        objectModels = new ConcurrentHashMap<>();
+        transientModels = new ConcurrentHashMap<>();
+        valueModels = new ConcurrentHashMap<>();
+        entityModels = new ConcurrentHashMap<>();
+        unambiguousEntityModels = new ConcurrentHashMap<>();
+        serviceModels = new ConcurrentHashMap<>();
+        servicesReferences = new ConcurrentHashMap<>();
+    }
+
+    @Override
+    public ObjectDescriptor lookupObjectModel( final Class<?> type )
+    {
+        return objectModels.computeIfAbsent( type, key ->
+        {
+            List<? extends ObjectDescriptor> allModels = getAllObjects();
+            ObjectDescriptor model = ambiguityMatching( key, allModels, new HasEqualType<>( key ) );
+            if( model == null )
+            {
+                model = ambiguityMatching( key, allModels, new HasAssignableFromType<>( key ) );
+            }
+            return model;
+        } );
+    }
+
+    @Override
+    public TransientDescriptor lookupTransientModel( final Class<?> type )
+    {
+        return transientModels.computeIfAbsent( type, key ->
+        {
+            List<? extends TransientDescriptor> allModels = getAllTransients();
+            TransientDescriptor model = ambiguityMatching( key, allModels, new HasEqualType<>( key ) );
+            if( model == null )
+            {
+                model = ambiguityMatching( key, allModels, new HasAssignableFromType<>( key ) );
+            }
+            return model;
+        } );
+    }
+
+    @Override
+    public ValueDescriptor lookupValueModel( final Class<?> type )
+    {
+        return valueModels.computeIfAbsent( type, key ->
+        {
+            List<? extends ValueDescriptor> allModels = getAllValues();
+            ValueDescriptor model = ambiguityMatching( key, allModels, new HasEqualType<>( key ) );
+            if( model == null )
+            {
+                model = ambiguityMatching( key, allModels, new HasAssignableFromType<>( key ) );
+            }
+            return model;
+        } );
+    }
+
+    @Override
+    public EntityDescriptor lookupEntityModel( final Class<?> type )
+    {
+        return unambiguousEntityModels.computeIfAbsent( type, key ->
+        {
+            List<? extends EntityDescriptor> allModels = getAllEntities();
+            EntityDescriptor model = ambiguityMatching( key, allModels, new HasEqualType<>( key ) );
+            if( model == null )
+            {
+                model = ambiguityMatching( key, allModels, new HasAssignableFromType<>( key ) );
+            }
+            return model;
+        } );
+    }
+
+    @Override
+    public List<EntityDescriptor> lookupEntityModels( final Class type )
+    {
+        return entityModels.computeIfAbsent(
+            type,
+            key -> allEntities().collect( HasTypesCollectors.matchingTypes( key ) ) );
+    }
+
+    @Override
+    public ModelDescriptor lookupServiceModel( Type serviceType )
+    {
+        return serviceModels.computeIfAbsent(
+            serviceType,
+            key -> allServices().collect( HasTypesCollectors.matchingType( key ) ).orElse( null ) );
+    }
+
+    @Override
+    public List<? extends ModelDescriptor> lookupServiceModels( final Type type )
+    {
+        return servicesReferences.computeIfAbsent(
+            type,
+            key -> allServices().collect( HasTypesCollectors.matchingTypes( key ) ) );
+    }
+
+    @Override
+    public Stream<ObjectDescriptor> allObjects()
+    {
+        return getAllObjects().stream();
+    }
+
+    private List<ObjectDescriptor> getAllObjects()
+    {
+        return allObjects.computeIfAbsent(
+            () -> concat( module.objects(),
+                          concat(
+                              concat(
+                                  module.layer().visibleObjects( layer ),
+                                  module.layer().visibleObjects( application )
+                              ),
+                              module.layer().usedLayers().layers()
+                                    .flatMap( layer -> layer.visibleObjects( application ) )
+                          )
+            ).collect( toList() )
+        );
+    }
+
+    @Override
+    public Stream<TransientDescriptor> allTransients()
+    {
+        return getAllTransients().stream();
+    }
+
+    private List<TransientDescriptor> getAllTransients()
+    {
+        return allTransients.computeIfAbsent(
+            () -> concat( module.transientComposites(),
+                          concat(
+                              concat(
+                                  module.layer().visibleTransients( layer ),
+                                  module.layer().visibleTransients( application )
+                              ),
+                              module.layer().usedLayers().layers()
+                                    .flatMap( layer -> layer.visibleTransients( application ) )
+                          )
+            ).collect( toList() )
+        );
+    }
+
+    @Override
+    public Stream<ValueDescriptor> allValues()
+    {
+        return getAllValues().stream();
+    }
+
+    private List<ValueDescriptor> getAllValues()
+    {
+        return allValues.computeIfAbsent(
+            () -> concat( module.valueComposites(),
+                          concat(
+                              concat( module.layer().visibleValues( layer ),
+                                      module.layer().visibleValues( application )
+                              ),
+                              module.layer().usedLayers().layers()
+                                    .flatMap( layer1 -> layer1.visibleValues( application ) )
+                          )
+            ).collect( toList() )
+        );
+    }
+
+    @Override
+    public Stream<EntityDescriptor> allEntities()
+    {
+        return getAllEntities().stream();
+    }
+
+    private List<EntityDescriptor> getAllEntities()
+    {
+        return allEntities.computeIfAbsent(
+            () -> concat( module.entityComposites(),
+                          concat(
+                              concat(
+                                  module.layer().visibleEntities( layer ),
+                                  module.layer().visibleEntities( application )
+                              ),
+                              module.layer().usedLayers().layers()
+                                    .flatMap( layer -> layer.visibleEntities( application ) )
+                          )
+            ).collect( toList() )
+        );
+    }
+
+    @Override
+    public Stream<? extends ModelDescriptor> allServices()
+    {
+        return getAllServices().stream();
+    }
+
+    private List<? extends ModelDescriptor> getAllServices()
+    {
+        return allServices.computeIfAbsent(
+            () -> concat(
+                concat( module.serviceComposites(),
+                        concat(
+                            concat(
+                                module.layer().visibleServices( layer ),
+                                module.layer().visibleServices( application )
+                            ),
+                            module.layer().usedLayers().layers()
+                                  .flatMap( layer -> layer.visibleServices( application ) )
+                        )
+                ),
+                concat( module.importedServices(),
+                        concat(
+                            concat(
+                                module.layer().visibleServices( layer ),
+                                module.layer().visibleServices( application )
+                            ),
+                            module.layer().usedLayers().layers()
+                                  .flatMap( layer -> layer.visibleServices( application ) )
+                        )
+                )
+            ).collect( toList() )
+        );
+    }
+
+    private static <T extends ModelDescriptor> T ambiguityMatching(
+        Class type,
+        List<T> modelModules,
+        Predicate<T> matching
+    )
+    {
+        List<T> models = modelModules.stream()
+                                     .filter( matching.and( new SameVisibility<>() ) )
+                                     .distinct()
+                                     .collect( toList() );
+        if( models.size() > 1 )
+        {
+            throw new AmbiguousTypeException( "More than one type matches " + type.getName() + ": " + models + "]" );
+        }
+        if( models.isEmpty() )
+        {
+            return null;
+        }
+        return models.get( 0 );
+    }
+
+    /**
+     * This Predicate will filter out all Models that doesn't have the same visibility as the first one.
+     */
+    private static class SameVisibility<T extends ModelDescriptor>
+        implements Predicate<T>
+    {
+        private Visibility current = null;
+
+        @Override
+        public boolean test( T model )
+        {
+            if( current == null )
+            {
+                current = model.visibility();
+                return true;
+            }
+            return current == model.visibility();
+        }
+    }
+
+    private static class LazyValue<T>
+    {
+        private volatile T value;
+
+        private T computeIfAbsent( Supplier<T> supplier )
+        {
+            if( value == null )
+            {
+                synchronized( this )
+                {
+                    if( value == null )
+                    {
+                        value = supplier.get();
+                    }
+                }
+            }
+            return value;
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/UsedLayersInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/UsedLayersInstance.java
new file mode 100644
index 0000000..e4d3880
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/UsedLayersInstance.java
@@ -0,0 +1,74 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.value.ValueDescriptor;
+
+/**
+ * JAVADOC
+ */
+public final class UsedLayersInstance
+{
+    private final List<LayerDescriptor> usedLayerInstances;
+
+    public UsedLayersInstance( List<LayerDescriptor> usedLayerInstances )
+    {
+        this.usedLayerInstances = usedLayerInstances;
+    }
+
+    Stream<? extends ObjectDescriptor> visibleObjects()
+    {
+        return usedLayerInstances.stream()
+            .flatMap( layerInstance -> layerInstance.visibleObjects( Visibility.application ) );
+    }
+
+    Stream<? extends TransientDescriptor> visibleTransients()
+    {
+        return usedLayerInstances.stream()
+            .flatMap( layerInstance -> layerInstance.visibleTransients( Visibility.application ) );
+    }
+
+    Stream<? extends EntityDescriptor> visibleEntities()
+    {
+        return usedLayerInstances.stream()
+            .flatMap( layerInstance -> layerInstance.visibleEntities( Visibility.application ) );
+    }
+
+    Stream<? extends ValueDescriptor> visibleValues()
+    {
+        return usedLayerInstances.stream()
+            .flatMap( layerInstance -> layerInstance.visibleValues( Visibility.application ) );
+    }
+
+    Stream<? extends ModelDescriptor> visibleServices()
+    {
+        return usedLayerInstances.stream()
+            .flatMap( layerInstance -> layerInstance.visibleServices( Visibility.application ) );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/UsedLayersModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/UsedLayersModel.java
new file mode 100644
index 0000000..c5bcd1a
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/UsedLayersModel.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.UsedLayersDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * JAVADOC
+ */
+public final class UsedLayersModel
+    implements UsedLayersDescriptor, VisitableHierarchy<Object, Object>
+{
+    private final List<LayerModel> usedLayers;
+
+    public UsedLayersModel( List<LayerModel> usedLayers )
+    {
+        this.usedLayers = usedLayers;
+    }
+
+    @Override
+    public Stream<? extends LayerDescriptor> layers()
+    {
+        return usedLayers.stream();
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( LayerModel usedLayer : usedLayers )
+            {
+                if( !usedLayer.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+
+        return visitor.visitLeave( this );
+    }
+
+    public UsedLayersInstance newInstance( List<LayerDescriptor> usedLayerInstances )
+    {
+        return new UsedLayersInstance( usedLayerInstances );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/VisibilityPredicate.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/VisibilityPredicate.java
new file mode 100644
index 0000000..5478f4b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/VisibilityPredicate.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import java.util.function.Predicate;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.ModelDescriptor;
+
+/**
+ * TODO
+ */
+public class VisibilityPredicate
+    implements Predicate<ModelDescriptor>
+{
+    public static final Predicate<ModelDescriptor> MODULE = new VisibilityPredicate( Visibility.module );
+    public static final Predicate<ModelDescriptor> LAYER = new VisibilityPredicate( Visibility.layer );
+    public static final Predicate<ModelDescriptor> APPLICATION = new VisibilityPredicate( Visibility.application );
+
+    private final Visibility visibility;
+
+    public VisibilityPredicate( Visibility visibility )
+    {
+        this.visibility = visibility;
+    }
+
+    @Override
+    public boolean test( ModelDescriptor item )
+    {
+        return item.visibility().ordinal() >= visibility.ordinal();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/type/ValueTypeFactoryInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/type/ValueTypeFactoryInstance.java
new file mode 100644
index 0000000..e5ccdf5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/type/ValueTypeFactoryInstance.java
@@ -0,0 +1,168 @@
+/*
+ *  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.polygene.runtime.type;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import org.apache.polygene.api.common.InvalidApplicationException;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ArrayType;
+import org.apache.polygene.api.type.CollectionType;
+import org.apache.polygene.api.type.EnumType;
+import org.apache.polygene.api.type.MapType;
+import org.apache.polygene.api.type.ValueCompositeType;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.runtime.entity.EntityInstance;
+import org.apache.polygene.runtime.value.ValueInstance;
+import org.apache.polygene.spi.type.ValueTypeFactory;
+
+import static org.apache.polygene.api.composite.CompositeInstance.compositeInstanceOf;
+
+public class ValueTypeFactoryInstance implements ValueTypeFactory
+{
+    private static final ValueTypeFactoryInstance INSTANCE = new ValueTypeFactoryInstance();
+
+    public static ValueTypeFactoryInstance instance()
+    {
+        return INSTANCE;
+    }
+
+    @Override
+    public ValueType valueTypeOf( ModuleDescriptor module, Object object )
+    {
+        if( object instanceof ValueComposite )
+        {
+            ValueInstance valueInstance = (ValueInstance) compositeInstanceOf( (Composite) object );
+            return valueInstance.descriptor().valueType();
+        }
+        if( object instanceof EntityComposite )
+        {
+            return ( (EntityInstance) compositeInstanceOf( (Composite) object ) ).descriptor().valueType();
+        }
+        if( object instanceof Enum )
+        {
+            return EnumType.of( ( (Enum) object ).getDeclaringClass() );
+        }
+        return valueTypeOf( module, object.getClass() );
+    }
+
+    @Override
+    public ValueType valueTypeOf( ModuleDescriptor module, Class<?> type )
+    {
+        ValueDescriptor valueDescriptor = module.typeLookup().lookupValueModel( type );
+        if( valueDescriptor != null )
+        {
+            return valueDescriptor.valueType();
+        }
+        EntityDescriptor entityDescriptor = module.typeLookup().lookupEntityModel( type );
+        if( entityDescriptor != null )
+        {
+            return entityDescriptor.valueType();
+        }
+        return newValueType( type, type, type, module );
+    }
+
+    public ValueType newValueType( Type type, Class declaringClass, Class compositeType, ModuleDescriptor module )
+    {
+        ValueType valueType;
+        if( EnumType.isEnum( type ) )
+        {
+            valueType = EnumType.of( Classes.RAW_CLASS.apply( type ) );
+        }
+        else if( ArrayType.isArray( type ) )
+        {
+            valueType = ArrayType.of( Classes.RAW_CLASS.apply( type ) );
+        }
+        else if( CollectionType.isCollection( type ) )
+        {
+            if( type instanceof ParameterizedType )
+            {
+                ParameterizedType pt = (ParameterizedType) type;
+                Type collectionType = pt.getActualTypeArguments()[ 0 ];
+                if( collectionType instanceof TypeVariable && declaringClass != null )
+                {
+                    TypeVariable collectionTypeVariable = (TypeVariable) collectionType;
+                    collectionType = Classes.resolveTypeVariable( collectionTypeVariable, declaringClass,
+                                                                  compositeType );
+                }
+                ValueType collectedType = newValueType( collectionType, declaringClass, compositeType, module );
+                valueType = CollectionType.of( Classes.RAW_CLASS.apply( type ), collectedType );
+            }
+            else
+            {
+                ValueType collectedType = newValueType( Object.class, declaringClass, compositeType, module );
+                valueType = CollectionType.of( Classes.RAW_CLASS.apply( type ), collectedType );
+            }
+        }
+        else if( MapType.isMap( type ) )
+        {
+            if( type instanceof ParameterizedType )
+            {
+                ParameterizedType pt = (ParameterizedType) type;
+                Type keyType = pt.getActualTypeArguments()[ 0 ];
+                if( keyType instanceof TypeVariable && declaringClass != null )
+                {
+                    TypeVariable keyTypeVariable = (TypeVariable) keyType;
+                    keyType = Classes.resolveTypeVariable( keyTypeVariable, declaringClass, compositeType );
+                }
+                ValueType keyedType = newValueType( keyType, declaringClass, compositeType, module );
+                Type valType = pt.getActualTypeArguments()[ 1 ];
+                if( valType instanceof TypeVariable && declaringClass != null )
+                {
+                    TypeVariable valueTypeVariable = (TypeVariable) valType;
+                    valType = Classes.resolveTypeVariable( valueTypeVariable, declaringClass, compositeType );
+                }
+                ValueType valuedType = newValueType( valType, declaringClass, compositeType, module );
+                valueType = MapType.of( Classes.RAW_CLASS.apply( type ), keyedType, valuedType );
+            }
+            else
+            {
+                ValueType keyType = newValueType( Object.class, declaringClass, compositeType, module );
+                ValueType valuesType = newValueType( Object.class, declaringClass, compositeType, module );
+                valueType = MapType.of( Classes.RAW_CLASS.apply( type ), keyType, valuesType );
+            }
+        }
+        else if( ValueCompositeType.isValueComposite( type ) )
+        {
+            ValueDescriptor model = module.typeLookup().lookupValueModel( Classes.RAW_CLASS.apply( type ) );
+            if( model == null )
+            {
+                throw new InvalidApplicationException(
+                    "[" + module.name() + "] Could not find ValueComposite of type " + type );
+            }
+
+            valueType = model.valueType();
+        }
+        else
+        {
+            valueType = ValueType.of( Classes.RAW_CLASS.apply( type ) );
+        }
+
+        return valueType;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/BuilderEntityState.java b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/BuilderEntityState.java
new file mode 100644
index 0000000..1a17f22
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/BuilderEntityState.java
@@ -0,0 +1,163 @@
+/*
+ *  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.polygene.runtime.unitofwork;
+
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.entity.ManyAssociationState;
+import org.apache.polygene.spi.entity.NamedAssociationState;
+
+/**
+ * Implementation of EntityState for use through EntityBuilder.
+ */
+public final class BuilderEntityState
+    implements EntityState
+{
+    private final EntityDescriptor entityType;
+    private final EntityReference reference;
+    private final Map<QualifiedName, Object> properties = new HashMap<>();
+    private final Map<QualifiedName, EntityReference> associations = new HashMap<>();
+    private final Map<QualifiedName, ManyAssociationState> manyAssociations = new HashMap<>();
+    private final Map<QualifiedName, NamedAssociationState> namedAssociations = new HashMap<>();
+
+    public BuilderEntityState( EntityDescriptor type, EntityReference reference )
+    {
+        this.entityType = type;
+        this.reference = reference;
+    }
+
+    @Override
+    public EntityReference entityReference()
+    {
+        return reference;
+    }
+
+    @Override
+    public String version()
+    {
+        return "";
+    }
+
+    @Override
+    public Instant lastModified()
+    {
+        return Instant.MIN;
+    }
+
+    @Override
+    public void remove()
+    {
+    }
+
+    @Override
+    public EntityStatus status()
+    {
+        return EntityStatus.NEW;
+    }
+
+    @Override
+    public boolean isAssignableTo( Class<?> type )
+    {
+        return Classes.exactTypeSpecification( type ).test( entityType );
+    }
+
+    @Override
+    public EntityDescriptor entityDescriptor()
+    {
+        return entityType;
+    }
+
+    @Override
+    public Object propertyValueOf( QualifiedName stateName )
+    {
+        return properties.get( stateName );
+    }
+
+    @Override
+    public EntityReference associationValueOf( QualifiedName stateName )
+    {
+        return associations.get( stateName );
+    }
+
+    @Override
+    public void setPropertyValue( QualifiedName stateName, Object newValue )
+    {
+        properties.put( stateName, newValue );
+    }
+
+    @Override
+    public void setAssociationValue( QualifiedName stateName, EntityReference newEntity )
+    {
+        associations.put( stateName, newEntity );
+    }
+
+    @Override
+    public ManyAssociationState manyAssociationValueOf( QualifiedName stateName )
+    {
+        return manyAssociations.computeIfAbsent( stateName,
+                                                 qualifiedName -> new BuilderManyAssociationState() );
+    }
+
+    @Override
+    public NamedAssociationState namedAssociationValueOf( QualifiedName stateName )
+    {
+        return namedAssociations.computeIfAbsent( stateName,
+                                                  qualifiedName -> new BuilderNamedAssociationState() );
+    }
+
+    public void copyTo( EntityState newEntityState )
+    {
+        for( Map.Entry<QualifiedName, Object> fromPropertyEntry : properties.entrySet() )
+        {
+            newEntityState.setPropertyValue( fromPropertyEntry.getKey(), fromPropertyEntry.getValue() );
+        }
+        for( Map.Entry<QualifiedName, EntityReference> fromAssociationEntry : associations.entrySet() )
+        {
+            newEntityState.setAssociationValue( fromAssociationEntry.getKey(), fromAssociationEntry.getValue() );
+        }
+        for( Map.Entry<QualifiedName, ManyAssociationState> fromManyAssociationEntry : manyAssociations.entrySet() )
+        {
+            QualifiedName qName = fromManyAssociationEntry.getKey();
+            ManyAssociationState fromManyAssoc = fromManyAssociationEntry.getValue();
+            ManyAssociationState toManyAssoc = newEntityState.manyAssociationValueOf( qName );
+            for( EntityReference entityReference : fromManyAssoc )
+            {
+                toManyAssoc.add( 0, entityReference );
+            }
+        }
+        for( Map.Entry<QualifiedName, NamedAssociationState> fromNamedAssociationEntry : namedAssociations.entrySet() )
+        {
+            QualifiedName qName = fromNamedAssociationEntry.getKey();
+            NamedAssociationState fromNamedAssoc = fromNamedAssociationEntry.getValue();
+            NamedAssociationState toNamedAssoc = newEntityState.namedAssociationValueOf( qName );
+            for( String name : fromNamedAssoc )
+            {
+                toNamedAssoc.put( name, fromNamedAssoc.get( name ) );
+            }
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/BuilderManyAssociationState.java b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/BuilderManyAssociationState.java
new file mode 100644
index 0000000..767184c
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/BuilderManyAssociationState.java
@@ -0,0 +1,90 @@
+/*
+ *  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.polygene.runtime.unitofwork;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.spi.entity.ManyAssociationState;
+
+/**
+ * Default implementation of ManyAssociationState that also
+ * keeps a list of changes that can be extracted at any time.
+ */
+public final class BuilderManyAssociationState
+    implements ManyAssociationState
+{
+    private List<EntityReference> references = new ArrayList<>();
+
+    @Override
+    public int count()
+    {
+        return references.size();
+    }
+
+    @Override
+    public boolean contains( EntityReference entityReference )
+    {
+        return references.contains( entityReference );
+    }
+
+    @Override
+    public boolean add( int i, EntityReference entityReference )
+    {
+        if( references.contains( entityReference ) )
+        {
+            return false;
+        }
+
+        references.add( i, entityReference );
+        return true;
+    }
+
+    @Override
+    public boolean remove( EntityReference entityReference )
+    {
+        return references.remove( entityReference );
+    }
+
+    @Override
+    public boolean clear()
+    {
+        if( !references.isEmpty() )
+        {
+            references.clear();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public EntityReference get( int i )
+    {
+        return references.get( i );
+    }
+
+    @Override
+    public Iterator<EntityReference> iterator()
+    {
+        return references.iterator();
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/BuilderNamedAssociationState.java b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/BuilderNamedAssociationState.java
new file mode 100644
index 0000000..f7882be
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/BuilderNamedAssociationState.java
@@ -0,0 +1,101 @@
+/*
+ *  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.polygene.runtime.unitofwork;
+
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.spi.entity.NamedAssociationState;
+
+/**
+ * Default implementation of NamedAssociationState that also
+ * keeps a list of changes that can be extracted at any time.
+ */
+public final class BuilderNamedAssociationState
+    implements NamedAssociationState
+{
+    private final Map<String, EntityReference> references;
+
+    public BuilderNamedAssociationState()
+    {
+        references = new LinkedHashMap<>();
+    }
+
+    @Override
+    public int count()
+    {
+        return references.size();
+    }
+
+    @Override
+    public boolean containsName( String name )
+    {
+        return references.containsKey( name );
+    }
+
+    @Override
+    public boolean put( String name, EntityReference entityReference )
+    {
+        return references.put( name, entityReference ) != null;
+    }
+
+    @Override
+    public boolean remove( String name )
+    {
+        return references.remove( name ) != null;
+    }
+
+    @Override
+    public boolean clear()
+    {
+        if( !references.isEmpty() )
+        {
+            references.clear();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public EntityReference get( String name )
+    {
+        return references.get( name );
+    }
+
+    @Override
+    public String nameOf( EntityReference entityReference )
+    {
+        for( Map.Entry<String, EntityReference> entry : references.entrySet() )
+        {
+            if( entry.getValue().equals( entityReference ) )
+            {
+                return entry.getKey();
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Iterator<String> iterator()
+    {
+        return references.keySet().iterator();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/EntityBuilderInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/EntityBuilderInstance.java
new file mode 100644
index 0000000..5dedfa2
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/EntityBuilderInstance.java
@@ -0,0 +1,139 @@
+/*
+ *  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.polygene.runtime.unitofwork;
+
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.entity.LifecycleException;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.runtime.composite.FunctionStateResolver;
+import org.apache.polygene.runtime.entity.EntityInstance;
+import org.apache.polygene.runtime.entity.EntityModel;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork;
+import org.apache.polygene.spi.module.ModuleSpi;
+
+import static org.apache.polygene.api.identity.HasIdentity.IDENTITY_STATE_NAME;
+
+/**
+ * Implementation of EntityBuilder. Maintains an instance of the entity which
+ * will not have its state validated until it is created by calling newInstance().
+ */
+public final class EntityBuilderInstance<T>
+    implements EntityBuilder<T>
+{
+    private final EntityModel model;
+    private final ModuleUnitOfWork uow;
+    private final EntityStoreUnitOfWork store;
+    private Identity identity;
+
+    private final BuilderEntityState entityState;
+    private final EntityInstance prototypeInstance;
+
+    public EntityBuilderInstance(
+        EntityDescriptor model,
+        ModuleUnitOfWork uow,
+        EntityStoreUnitOfWork store,
+        Identity identity
+    )
+    {
+        this( model, uow, store, identity, null );
+    }
+
+    public EntityBuilderInstance(
+        EntityDescriptor model,
+        ModuleUnitOfWork uow,
+        EntityStoreUnitOfWork store,
+        Identity identity,
+        FunctionStateResolver stateResolver
+    )
+    {
+        this.model = (EntityModel) model;
+        this.uow = uow;
+        this.store = store;
+        this.identity = identity;
+        EntityReference reference = EntityReference.create( identity );
+        entityState = new BuilderEntityState( model, reference );
+        this.model.initState( model.module(), entityState );
+        if( stateResolver != null )
+        {
+            stateResolver.populateState( this.model, entityState );
+        }
+        entityState.setPropertyValue( IDENTITY_STATE_NAME, identity );
+        prototypeInstance = this.model.newInstance( uow, (ModuleSpi) model.module().instance(), entityState );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Override
+    public T instance()
+    {
+        checkValid();
+        return prototypeInstance.proxy();
+    }
+
+    @Override
+    public <K> K instanceFor( Class<K> mixinType )
+    {
+        checkValid();
+        return prototypeInstance.newProxy( mixinType );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public T newInstance()
+        throws LifecycleException
+    {
+        checkValid();
+
+        // Figure out whether to use given or generated reference
+        Identity identity = (Identity) entityState.propertyValueOf( IDENTITY_STATE_NAME );
+        EntityReference entityReference = EntityReference.create( identity );
+        EntityState newEntityState = model.newEntityState( store, entityReference );
+
+        prototypeInstance.invokeCreate();
+
+        // Check constraints
+        prototypeInstance.checkConstraints();
+
+        entityState.copyTo( newEntityState );
+
+        EntityInstance instance = model.newInstance( uow, (ModuleSpi) model.module().instance(), newEntityState );
+
+        Object proxy = instance.proxy();
+
+        // Add entity in UOW
+        uow.addEntity( instance );
+
+        // Invalidate builder
+        this.identity = null;
+
+        return (T) proxy;
+    }
+
+    private void checkValid()
+        throws IllegalStateException
+    {
+        if( identity == null )
+        {
+            throw new IllegalStateException( "EntityBuilder is not valid after call to newInstance()" );
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/EntityFunction.java b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/EntityFunction.java
new file mode 100644
index 0000000..936f5aa
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/EntityFunction.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.runtime.unitofwork;
+
+import java.lang.reflect.Type;
+import java.util.function.BiFunction;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+
+import static org.apache.polygene.api.util.Classes.RAW_CLASS;
+
+public class EntityFunction
+    implements BiFunction<EntityReference, Type, Object>
+{
+
+    private final UnitOfWorkFactory uowf;
+
+    public EntityFunction( UnitOfWorkFactory uowf )
+    {
+        this.uowf = uowf;
+    }
+
+    @Override
+    public Object apply( EntityReference entityReference, Type type )
+    {
+        return uowf.currentUnitOfWork().get( RAW_CLASS.apply( type ), entityReference.identity() );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/ModuleUnitOfWork.java b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/ModuleUnitOfWork.java
new file mode 100644
index 0000000..7f4dedf
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/ModuleUnitOfWork.java
@@ -0,0 +1,816 @@
+/*
+ *  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.polygene.runtime.unitofwork;
+
+import java.time.Instant;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.entity.LifecycleException;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.IdentityGenerator;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryExecutionException;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.api.service.NoSuchServiceException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException;
+import org.apache.polygene.api.unitofwork.ToEntityConverter;
+import org.apache.polygene.api.unitofwork.ToValueConverter;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCallback;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.runtime.association.AssociationInstance;
+import org.apache.polygene.runtime.composite.FunctionStateResolver;
+import org.apache.polygene.runtime.entity.EntityInstance;
+import org.apache.polygene.runtime.entity.EntityModel;
+import org.apache.polygene.runtime.property.PropertyModel;
+import org.apache.polygene.runtime.value.ValueStateInstance;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.module.ModuleSpi;
+import org.apache.polygene.spi.query.EntityFinder;
+import org.apache.polygene.spi.query.EntityFinderException;
+import org.apache.polygene.spi.query.QueryBuilderSPI;
+import org.apache.polygene.spi.query.QuerySource;
+
+import static org.apache.polygene.api.composite.CompositeInstance.compositeInstanceOf;
+import static org.apache.polygene.api.identity.HasIdentity.IDENTITY_STATE_NAME;
+
+/**
+ * JAVADOC
+ */
+public class ModuleUnitOfWork
+    implements UnitOfWork
+{
+    @Uses
+    private UnitOfWorkInstance uow;
+
+    @Structure
+    private PolygeneAPI api;
+
+    @Structure
+    private ModuleDescriptor module;
+
+    @Service
+    private UnitOfWorkFactory unitOfWorkFactory;
+
+    public ModuleDescriptor module()
+    {
+        return module;
+    }
+
+    public UnitOfWorkInstance instance()
+    {
+        return uow;
+    }
+
+    @Override
+    public UnitOfWorkFactory unitOfWorkFactory()
+    {
+        return unitOfWorkFactory;
+    }
+
+    @Override
+    public Instant currentTime()
+    {
+        return uow.currentTime();
+    }
+
+    @Override
+    public Usecase usecase()
+    {
+        return uow.usecase();
+    }
+
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return uow.metaInfo().get( infoType );
+    }
+
+    @Override
+    public void setMetaInfo( Object metaInfo )
+    {
+        uow.metaInfo().set( metaInfo );
+    }
+
+    @Override
+    @SuppressWarnings( { "raw", "unchecked" } )
+    public <T> Query<T> newQuery( QueryBuilder<T> queryBuilder )
+    {
+        QueryBuilderSPI queryBuilderSPI = (QueryBuilderSPI) queryBuilder;
+
+        return queryBuilderSPI.newQuery( new UoWQuerySource( this ) );
+    }
+
+    @Override
+    public <T> T newEntity( Class<T> type )
+        throws NoSuchEntityTypeException, LifecycleException
+    {
+        return newEntity( type, null );
+    }
+
+    @Override
+    public <T> T newEntity( Class<T> type, Identity identity )
+        throws NoSuchEntityTypeException, LifecycleException
+    {
+        return newEntityBuilder( type, identity ).newInstance();
+    }
+
+    @Override
+    public <T> EntityBuilder<T> newEntityBuilder( Class<T> type )
+        throws NoSuchEntityTypeException
+    {
+        return newEntityBuilder( type, null );
+    }
+
+    @Override
+    public <T> EntityBuilder<T> newEntityBuilder( Class<T> type, Identity identity )
+        throws NoSuchEntityTypeException
+    {
+        EntityDescriptor model = module.typeLookup().lookupEntityModel( type );
+
+        if( model == null )
+        {
+            throw new NoSuchEntityTypeException( type.getName(), module.name(), module.typeLookup() );
+        }
+
+        ModuleDescriptor modelModule = model.module();
+        EntityStore entityStore = ( (ModuleSpi) modelModule.instance() ).entityStore();
+
+        // Generate id if necessary
+        if( identity == null )
+        {
+            IdentityGenerator idGen = ( (ModuleSpi) modelModule.instance() ).identityGenerator();
+            if( idGen == null )
+            {
+                throw new NoSuchServiceException( IdentityGenerator.class.getName(), modelModule
+                    .name(), modelModule.typeLookup() );
+            }
+            identity = idGen.generate( model.types().findFirst().orElse( null ) );
+        }
+        EntityBuilder<T> builder;
+
+        builder = new EntityBuilderInstance<>( model,
+                                               this,
+                                               uow.getEntityStoreUnitOfWork( entityStore ),
+                                               identity );
+        return builder;
+    }
+
+    @Override
+    public <T> EntityBuilder<T> newEntityBuilderWithState(
+        Class<T> type,
+        Function<PropertyDescriptor, Object> propertyFunction,
+        Function<AssociationDescriptor, EntityReference> associationFunction,
+        Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction,
+        Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction
+                                                         )
+        throws NoSuchEntityTypeException
+    {
+        return newEntityBuilderWithState( type, null,
+                                          propertyFunction,
+                                          associationFunction,
+                                          manyAssociationFunction,
+                                          namedAssociationFunction );
+    }
+
+    @Override
+    public <T> EntityBuilder<T> newEntityBuilderWithState(
+        Class<T> type, Identity identity,
+        Function<PropertyDescriptor, Object> propertyFunction,
+        Function<AssociationDescriptor, EntityReference> associationFunction,
+        Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction,
+        Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction
+                                                         )
+        throws NoSuchEntityTypeException
+    {
+        Objects.requireNonNull( propertyFunction, "propertyFunction" );
+        Objects.requireNonNull( associationFunction, "associationFunction" );
+        Objects.requireNonNull( manyAssociationFunction, "manyAssociationFunction" );
+        Objects.requireNonNull( namedAssociationFunction, "namedAssociationFunction" );
+
+        EntityDescriptor model = module.typeLookup().lookupEntityModel( type );
+
+        if( model == null )
+        {
+            throw new NoSuchEntityTypeException( type.getName(), module.name(), module.typeLookup() );
+        }
+
+        ModuleDescriptor modelModule = model.module();
+        ModuleSpi moduleSpi = (ModuleSpi) modelModule.instance();
+        EntityStore entityStore = moduleSpi.entityStore();
+
+        FunctionStateResolver stateResolver = new FunctionStateResolver(
+            propertyFunction, associationFunction, manyAssociationFunction, namedAssociationFunction
+        );
+
+        if( identity == null )
+        {
+            // Use reference from StateResolver if available
+            PropertyModel identityModel = (PropertyModel) model
+                .state()
+                .findPropertyModelByQualifiedName( IDENTITY_STATE_NAME );
+            String propertyState = (String) stateResolver.getPropertyState( identityModel );
+            if( propertyState == null )
+            {
+                // Generate reference
+                IdentityGenerator idGen = moduleSpi.identityGenerator();
+                if( idGen == null )
+                {
+                    String typeName = IdentityGenerator.class.getName();
+                    throw new NoSuchServiceException( typeName, modelModule.name(), modelModule.typeLookup() );
+                }
+                identity = idGen.generate( model.types().findFirst().orElse( null ) );
+            }
+            else
+            {
+                identity = new StringIdentity( propertyState );
+            }
+        }
+
+        return new EntityBuilderInstance<>( model,
+                                            this,
+                                            uow.getEntityStoreUnitOfWork( entityStore ),
+                                            identity,
+                                            stateResolver );
+    }
+
+    @Override
+    public <T> T get( Class<T> type, Identity identity )
+        throws NoSuchEntityTypeException, NoSuchEntityException
+    {
+        Iterable<EntityDescriptor> models = module.typeLookup().lookupEntityModels( type );
+
+        if( !models.iterator().hasNext() )
+        {
+            throw new NoSuchEntityTypeException( type.getName(), module.name(), module.typeLookup() );
+        }
+
+        return uow.get( EntityReference.create( identity ), this, models, type );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> T get( T entity )
+        throws NoSuchEntityTypeException
+    {
+        EntityComposite entityComposite = (EntityComposite) entity;
+        EntityInstance compositeInstance = (EntityInstance) compositeInstanceOf( entityComposite );
+        EntityDescriptor model = compositeInstance.entityModel();
+        Class<T> type = (Class<T>) compositeInstance.types().findFirst().orElse( null );
+        return uow.get( compositeInstance.reference(), this, Collections.singletonList( model ), type );
+    }
+
+    @Override
+    public void remove( Object entity )
+        throws LifecycleException
+    {
+        uow.checkOpen();
+
+        EntityComposite entityComposite = (EntityComposite) entity;
+
+        EntityInstance compositeInstance = (EntityInstance) compositeInstanceOf( entityComposite );
+
+        if( compositeInstance.status() == EntityStatus.NEW )
+        {
+            compositeInstance.remove( this );
+            uow.remove( compositeInstance.reference() );
+        }
+        else if( compositeInstance.status() == EntityStatus.LOADED || compositeInstance.status() == EntityStatus.UPDATED )
+        {
+            compositeInstance.remove( this );
+        }
+        else
+        {
+            throw new NoSuchEntityException( compositeInstance.reference(), compositeInstance.types(), usecase() );
+        }
+    }
+
+    @SuppressWarnings( "DuplicateThrows" )
+    @Override
+    public void complete()
+        throws UnitOfWorkCompletionException, ConcurrentEntityModificationException
+    {
+        uow.complete();
+    }
+
+    @Override
+    public void discard()
+    {
+        uow.discard();
+    }
+
+    @Override
+    public void close()
+    {
+        discard();
+    }
+
+    @Override
+    public boolean isOpen()
+    {
+        return uow.isOpen();
+    }
+
+    @Override
+    public boolean isPaused()
+    {
+        return uow.isPaused();
+    }
+
+    @Override
+    public void pause()
+    {
+        uow.pause();
+    }
+
+    @Override
+    public void resume()
+    {
+        uow.resume();
+    }
+
+    @Override
+    public void addUnitOfWorkCallback( UnitOfWorkCallback callback )
+    {
+        uow.addUnitOfWorkCallback( callback );
+    }
+
+    @Override
+    public void removeUnitOfWorkCallback( UnitOfWorkCallback callback )
+    {
+        uow.removeUnitOfWorkCallback( callback );
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        ModuleUnitOfWork that = (ModuleUnitOfWork) o;
+
+        return uow.equals( that.uow );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return uow.hashCode();
+    }
+
+    @Override
+    public String toString()
+    {
+        return uow.toString();
+    }
+
+    void addEntity( EntityInstance instance )
+    {
+        uow.addEntity( instance );
+    }
+
+    @Override
+    public <T extends HasIdentity> T toValue( Class<T> primaryType, T entityComposite )
+    {
+        Objects.requireNonNull( primaryType );
+        if( entityComposite == null )
+        {
+            return null;
+        }
+        Function<PropertyDescriptor, Object> propertyFunction = new ToValuePropertyMappingFunction( entityComposite );
+        Function<AssociationDescriptor, EntityReference> assocationFunction = new ToValueAssociationMappingFunction<>( entityComposite );
+        Function<AssociationDescriptor, Stream<EntityReference>> manyAssocFunction = new ToValueManyAssociationMappingFunction<>( entityComposite );
+        Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssocFunction = new ToValueNameAssociationMappingFunction<>( entityComposite );
+        ToValueConverter converter = getConverter( ToValueConverter.class );
+        if( converter != null )
+        {
+            propertyFunction = converter.properties( entityComposite, propertyFunction );
+            assocationFunction = converter.associations( entityComposite, assocationFunction );
+            manyAssocFunction = converter.manyAssociations( entityComposite, manyAssocFunction );
+            namedAssocFunction = converter.namedAssociations( entityComposite, namedAssocFunction );
+        }
+        @SuppressWarnings( "unchecked" )
+        ValueBuilder<T> builder = module().instance().newValueBuilderWithState(
+            primaryType, propertyFunction, assocationFunction, manyAssocFunction, namedAssocFunction );
+        return builder.newInstance();
+    }
+
+    @Override
+    public <T extends HasIdentity> Map<String, T> toValueMap( NamedAssociation<T> association )
+    {
+        @SuppressWarnings( "unchecked" )
+        Class<T> primaryType = (Class<T>) api.associationDescriptorFor( association ).type();
+
+        return association
+            .toMap()
+            .entrySet()
+            .stream()
+            .collect( Collectors.toMap( Map.Entry::getKey, entry -> toValue( primaryType, entry.getValue() ) ) );
+    }
+
+    @Override
+    public <T extends HasIdentity> List<T> toValueList( ManyAssociation<T> association )
+    {
+        @SuppressWarnings( "unchecked" )
+        Class<T> primaryType = (Class<T>) api.associationDescriptorFor( association ).type();
+
+        return association
+            .toList()
+            .stream()
+            .map( entity -> toValue( primaryType, entity ) )
+            .collect( Collectors.toList() );
+    }
+
+    @Override
+    public <T extends HasIdentity> Set<T> toValueSet( ManyAssociation<T> association )
+    {
+        @SuppressWarnings( "unchecked" )
+        Class<T> primaryType = (Class<T>) api.associationDescriptorFor( association ).type();
+
+        return association
+            .toSet()
+            .stream()
+            .map( entity -> toValue( primaryType, entity ) )
+            .collect( Collectors.toSet() );
+    }
+
+    @Override
+    public <T extends HasIdentity> T toEntity( Class<T> primaryType, T valueComposite )
+    {
+        Objects.requireNonNull( primaryType );
+        if( valueComposite == null )
+        {
+            return null;
+        }
+        Function<PropertyDescriptor, Object> propertyFunction = new ToEntityPropertyMappingFunction<>( valueComposite );
+        Function<AssociationDescriptor, EntityReference> assocationFunction = new ToEntityAssociationMappingFunction<>( valueComposite );
+        Function<AssociationDescriptor, Stream<EntityReference>> manyAssocFunction = new ToEntityManyAssociationMappingFunction<>( valueComposite );
+        Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssocFunction = new ToEntityNameAssociationMappingFunction<>( valueComposite );
+        ToEntityConverter converter = getConverter( ToEntityConverter.class );
+        if( converter != null )
+        {
+            propertyFunction = converter.properties( valueComposite, propertyFunction );
+            assocationFunction = converter.associations( valueComposite, assocationFunction );
+            manyAssocFunction = converter.manyAssociations( valueComposite, manyAssocFunction );
+            namedAssocFunction = converter.namedAssociations( valueComposite, namedAssocFunction );
+        }
+        try
+        {
+            T entity = get( primaryType, valueComposite.identity().get() );
+            // If successful, then this entity is to by modified.
+            EntityInstance instance = (EntityInstance) compositeInstanceOf( (EntityComposite) entity );
+            EntityState state = instance.entityState();
+            FunctionStateResolver stateResolver = new FunctionStateResolver( propertyFunction,
+                                                                             assocationFunction,
+                                                                             manyAssocFunction,
+                                                                             namedAssocFunction );
+            EntityModel model = (EntityModel) compositeInstanceOf( (Composite) entity ).descriptor();
+            stateResolver.populateState( model, state );
+            return entity;
+        }
+        catch( NoSuchEntityException e )
+        {
+            EntityBuilder<T> entityBuilder = newEntityBuilderWithState( primaryType,
+                                                                        valueComposite.identity().get(),
+                                                                        propertyFunction,
+                                                                        assocationFunction,
+                                                                        manyAssocFunction,
+                                                                        namedAssocFunction );
+            return entityBuilder.newInstance();
+        }
+    }
+
+    private <T> T getConverter( Class<T> converterType )
+    {
+        T converter = null;
+        Usecase usecase = usecase();
+        if( usecase != null )
+        {
+            converter = usecase.metaInfo( converterType );
+        }
+        if( converter == null )
+        {
+            converter = metaInfo( converterType );
+        }
+        return converter;
+    }
+
+    private static EntityState getEntityState( Object entity )
+    {
+        return ( (EntityInstance) compositeInstanceOf( (Composite) entity ) ).entityState();
+    }
+
+    private static class UoWQuerySource implements QuerySource
+    {
+        private final ModuleUnitOfWork moduleUnitOfWork;
+
+        private UoWQuerySource( ModuleUnitOfWork moduleUnitOfWork )
+        {
+            this.moduleUnitOfWork = moduleUnitOfWork;
+        }
+
+        @Override
+        public <T> T find( Class<T> resultType,
+                           Predicate<Composite> whereClause,
+                           List<OrderBy> orderBySegments,
+                           Integer firstResult,
+                           Integer maxResults,
+                           Map<String, Object> variables
+                         )
+        {
+            final EntityFinder entityFinder = moduleUnitOfWork.module()
+                                                              .instance()
+                                                              .findService( EntityFinder.class )
+                                                              .get();
+
+            try
+            {
+                EntityReference foundEntity = entityFinder.findEntity( resultType, whereClause, variables == null ? Collections.emptyMap() : variables );
+                if( foundEntity != null )
+                {
+                    try
+                    {
+                        return moduleUnitOfWork.get( resultType, foundEntity.identity() );
+                    }
+                    catch( NoSuchEntityException e )
+                    {
+                        return null; // Index is out of sync - entity has been removed
+                    }
+                }
+                // No entity was found
+                return null;
+            }
+            catch( EntityFinderException e )
+            {
+                throw new QueryExecutionException( "Finder caused exception", e );
+            }
+        }
+
+        @Override
+        public <T> long count( Class<T> resultType,
+                               Predicate<Composite> whereClause,
+                               List<OrderBy> orderBySegments,
+                               Integer firstResult,
+                               Integer maxResults,
+                               Map<String, Object> variables
+                             )
+        {
+            EntityFinder entityFinder = moduleUnitOfWork.module().instance().findService( EntityFinder.class ).get();
+
+            try
+            {
+                return entityFinder.countEntities( resultType, whereClause, variables == null ? Collections.emptyMap() : variables );
+            }
+            catch( EntityFinderException e )
+            {
+                e.printStackTrace();
+                return 0;
+            }
+        }
+
+        @Override
+        public <T> Stream<T> stream( Class<T> resultType,
+                                     Predicate<Composite> whereClause,
+                                     List<OrderBy> orderBySegments,
+                                     Integer firstResult,
+                                     Integer maxResults,
+                                     Map<String, Object> variables )
+        {
+            EntityFinder entityFinder = moduleUnitOfWork.module().instance().findService( EntityFinder.class ).get();
+
+            try
+            {
+                return entityFinder.findEntities(
+                    resultType,
+                    whereClause,
+                    orderBySegments,
+                    firstResult,
+                    maxResults,
+                    variables == null ? Collections.emptyMap() : variables
+                                                ).map( ref ->
+                                                       {
+                                                           try
+                                                           {
+                                                               return moduleUnitOfWork.get( resultType, ref.identity() );
+                                                           }
+                                                           catch( NoSuchEntityException e )
+                                                           {
+                                                               // Index is out of sync - entity has been removed
+                                                               return null;
+                                                           }
+                                                       } );
+            }
+            catch( EntityFinderException e )
+            {
+                throw new QueryExecutionException( "Query '" + toString() + "' could not be executed", e );
+            }
+        }
+    }
+
+    private class ToValuePropertyMappingFunction
+        implements Function<PropertyDescriptor, Object>
+    {
+        private Object entity;
+
+        ToValuePropertyMappingFunction( Object entity )
+        {
+            this.entity = entity;
+        }
+
+        @Override
+        public Object apply( PropertyDescriptor propertyDescriptor )
+        {
+            return getEntityState( entity ).propertyValueOf( propertyDescriptor.qualifiedName() );
+        }
+    }
+
+    private class ToValueAssociationMappingFunction<T>
+        implements Function<AssociationDescriptor, EntityReference>
+    {
+        private final T entity;
+
+        ToValueAssociationMappingFunction( T entity )
+        {
+            this.entity = entity;
+        }
+
+        @Override
+        public EntityReference apply( AssociationDescriptor associationDescriptor )
+        {
+            return getEntityState( entity ).associationValueOf( associationDescriptor.qualifiedName() );
+        }
+    }
+
+    private class ToValueManyAssociationMappingFunction<T>
+        implements Function<AssociationDescriptor, Stream<EntityReference>>
+    {
+        private final T entity;
+
+        ToValueManyAssociationMappingFunction( T entity )
+        {
+            this.entity = entity;
+        }
+
+        @Override
+        public Stream<EntityReference> apply( AssociationDescriptor associationDescriptor )
+        {
+            return getEntityState( entity ).manyAssociationValueOf( associationDescriptor.qualifiedName() ).stream();
+        }
+    }
+
+    private class ToValueNameAssociationMappingFunction<T>
+        implements Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>>
+    {
+        private final T entity;
+
+        ToValueNameAssociationMappingFunction( T entity )
+        {
+            this.entity = entity;
+        }
+
+        @Override
+        public Stream<Map.Entry<String, EntityReference>> apply( AssociationDescriptor associationDescriptor )
+        {
+            return getEntityState( entity ).namedAssociationValueOf( associationDescriptor.qualifiedName() ).stream();
+        }
+
+    }
+
+    private class ToEntityPropertyMappingFunction<T>
+        implements Function<PropertyDescriptor, Object>
+    {
+        private final T value;
+
+        private ToEntityPropertyMappingFunction( T value )
+        {
+            this.value = value;
+        }
+
+        @Override
+        public Object apply( PropertyDescriptor propertyDescriptor )
+        {
+            StateHolder state = getValueStateInstance( value );
+            Property<Object> property = state.propertyFor( propertyDescriptor.accessor() );
+            return property.get();
+        }
+    }
+
+    private class ToEntityAssociationMappingFunction<T>
+        implements Function<AssociationDescriptor, EntityReference>
+    {
+
+        private final T value;
+
+        private ToEntityAssociationMappingFunction( T value )
+        {
+            this.value = value;
+        }
+
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public EntityReference apply( AssociationDescriptor associationDescriptor )
+        {
+            AssociationStateHolder state = getValueStateInstance( value );
+            AssociationInstance<T> association = (AssociationInstance<T>) state.associationFor( associationDescriptor.accessor() );
+            return association.getAssociationState().get();
+        }
+    }
+
+    private class ToEntityManyAssociationMappingFunction<T>
+        implements Function<AssociationDescriptor, Stream<EntityReference>>
+    {
+
+        private final T value;
+
+        private ToEntityManyAssociationMappingFunction( T valueComposite )
+        {
+            this.value = valueComposite;
+        }
+
+        @Override
+        public Stream<EntityReference> apply( AssociationDescriptor associationDescriptor )
+        {
+            return getValueStateInstance( value ).manyAssociationFor( associationDescriptor.accessor() ).references();
+        }
+    }
+
+    private class ToEntityNameAssociationMappingFunction<T>
+        implements Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>>
+    {
+        private final T value;
+
+        private ToEntityNameAssociationMappingFunction( T valueComposite )
+        {
+            this.value = valueComposite;
+        }
+
+        @Override
+        public Stream<Map.Entry<String, EntityReference>> apply( AssociationDescriptor associationDescriptor )
+        {
+            return getValueStateInstance( value ).namedAssociationFor( associationDescriptor.accessor() ).references();
+        }
+    }
+
+    private static ValueStateInstance getValueStateInstance( Object value )
+    {
+        return (ValueStateInstance) compositeInstanceOf( (Composite) value ).state();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/UnitOfWorkFactoryMixin.java b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/UnitOfWorkFactoryMixin.java
new file mode 100644
index 0000000..13132c6
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/UnitOfWorkFactoryMixin.java
@@ -0,0 +1,101 @@
+/*
+ *  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.polygene.runtime.unitofwork;
+
+import java.time.Instant;
+import java.util.Stack;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.metrics.MetricsProvider;
+import org.apache.polygene.api.time.SystemTime;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.runtime.entity.EntityInstance;
+import org.apache.polygene.spi.module.ModuleSpi;
+
+public class UnitOfWorkFactoryMixin
+    implements UnitOfWorkFactory
+{
+    @Structure
+    private TransientBuilderFactory tbf;
+
+    @Structure
+    private ModuleSpi module;
+
+    // Implementation of UnitOfWorkFactory
+    @Override
+    public UnitOfWork newUnitOfWork()
+    {
+        return newUnitOfWork( Usecase.DEFAULT );
+    }
+
+    @Override
+    public UnitOfWork newUnitOfWork(Instant currentTime )
+    {
+        return newUnitOfWork( Usecase.DEFAULT, currentTime );
+    }
+
+    @Override
+    public UnitOfWork newUnitOfWork( Usecase usecase )
+    {
+        return newUnitOfWork( usecase == null ? Usecase.DEFAULT : usecase, SystemTime.now() );
+    }
+
+    @Override
+    public UnitOfWork newUnitOfWork( Usecase usecase, Instant currentTime )
+    {
+        UnitOfWorkInstance unitOfWorkInstance = new UnitOfWorkInstance( module, usecase, currentTime, metricsProvider() );
+        return tbf.newTransient( UnitOfWork.class, unitOfWorkInstance );
+    }
+
+    private MetricsProvider metricsProvider()
+    {
+        return module.metricsProvider();
+    }
+
+    @Override
+    public boolean isUnitOfWorkActive()
+    {
+        Stack<UnitOfWorkInstance> stack = UnitOfWorkInstance.getCurrent();
+        return !stack.isEmpty();
+    }
+
+    @Override
+    public UnitOfWork currentUnitOfWork()
+    {
+        Stack<UnitOfWorkInstance> stack = UnitOfWorkInstance.getCurrent();
+        if( stack.size() == 0 )
+        {
+            throw new IllegalStateException( "No current UnitOfWork active" );
+        }
+        return tbf.newTransient( UnitOfWork.class, stack.peek() );
+    }
+
+    @Override
+    public UnitOfWork getUnitOfWork( EntityComposite entity )
+    {
+        EntityInstance instance = (EntityInstance) CompositeInstance.compositeInstanceOf( entity );
+        return instance.unitOfWork();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/UnitOfWorkInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/UnitOfWorkInstance.java
new file mode 100644
index 0000000..927f04b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/UnitOfWorkInstance.java
@@ -0,0 +1,498 @@
+/*
+ *  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.polygene.runtime.unitofwork;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.metrics.MetricNames;
+import org.apache.polygene.api.metrics.MetricsCounter;
+import org.apache.polygene.api.metrics.MetricsCounterFactory;
+import org.apache.polygene.api.metrics.MetricsProvider;
+import org.apache.polygene.api.metrics.MetricsTimer;
+import org.apache.polygene.api.metrics.MetricsTimerFactory;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.HasTypes;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCallback;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkOptions;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.runtime.entity.EntityInstance;
+import org.apache.polygene.runtime.entity.EntityModel;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.entitystore.ConcurrentEntityStateModificationException;
+import org.apache.polygene.spi.entitystore.EntityNotFoundException;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork;
+import org.apache.polygene.spi.entitystore.StateCommitter;
+import org.apache.polygene.spi.module.ModuleSpi;
+
+import static org.apache.polygene.api.unitofwork.UnitOfWorkCallback.UnitOfWorkStatus.COMPLETED;
+import static org.apache.polygene.api.unitofwork.UnitOfWorkCallback.UnitOfWorkStatus.DISCARDED;
+
+public final class UnitOfWorkInstance
+{
+    private static final ThreadLocal<Stack<UnitOfWorkInstance>> CURRENT = ThreadLocal.withInitial( Stack::new );
+
+    public static Stack<UnitOfWorkInstance> getCurrent()
+    {
+        return CURRENT.get();
+    }
+
+    private final HashMap<EntityReference, EntityInstance> instanceCache = new HashMap<>();
+    private final HashMap<EntityStore, EntityStoreUnitOfWork> storeUnitOfWork = new HashMap<>();
+    private final ModuleSpi module;
+    private final Usecase usecase;
+    private final Instant currentTime;
+    private final MetricsProvider metrics;
+
+    private boolean open;
+    private boolean paused;
+
+    private MetricsCounter metricsCounter;
+    private MetricsTimer metricsTimer;
+    private MetricsTimer.Context metricsTimerContext;
+    private MetaInfo metaInfo;
+    private List<UnitOfWorkCallback> callbacks;
+
+    public UnitOfWorkInstance(ModuleSpi module, Usecase usecase, Instant currentTime, MetricsProvider metrics )
+    {
+        this.module = module;
+        this.usecase = usecase;
+        this.currentTime = currentTime;
+        this.metrics = metrics;
+
+        this.open = true;
+        getCurrent().push( this );
+        this.paused = false;
+        startCapture();
+    }
+
+    public Instant currentTime()
+    {
+        return currentTime;
+    }
+
+    public EntityStoreUnitOfWork getEntityStoreUnitOfWork( EntityStore store )
+    {
+        return storeUnitOfWork.computeIfAbsent( store,
+                                                s -> s.newUnitOfWork( module.descriptor(), usecase, currentTime ) );
+    }
+
+    public <T> T get( EntityReference reference,
+                      UnitOfWork uow,
+                      Iterable<? extends EntityDescriptor> potentialModels,
+                      Class<T> mixinType
+    )
+        throws NoSuchEntityTypeException, NoSuchEntityException
+    {
+        checkOpen();
+
+        EntityInstance entityInstance = instanceCache.get( reference );
+        if( entityInstance == null )
+        {   // Not yet in cache
+
+            // Check if this is a root UoW, or if no parent UoW knows about this entity
+            EntityState entityState = null;
+            EntityModel model = null;
+            ModuleDescriptor module = null;
+            // Figure out what EntityStore to use
+            for( EntityDescriptor potentialModel : potentialModels )
+            {
+                EntityStore store = ((ModuleSpi) potentialModel.module().instance()).entityStore();
+                EntityStoreUnitOfWork storeUow = getEntityStoreUnitOfWork( store );
+                try
+                {
+                    entityState = storeUow.entityStateOf( potentialModel.module(), reference );
+                }
+                catch( EntityNotFoundException e )
+                {
+                    continue;
+                }
+
+                // Get the selected model
+                model = (EntityModel) entityState.entityDescriptor();
+                module = potentialModel.module();
+            }
+
+            // Check if model was found
+            if( model == null )
+            {
+                // Check if state was found
+                if( entityState == null )
+                {
+                    throw new NoSuchEntityException( reference, mixinType, usecase );
+                }
+                else
+                {
+                    throw new NoSuchEntityTypeException( mixinType.getName(), module.name(), module.typeLookup() );
+                }
+            }
+            // Create instance
+            entityInstance = new EntityInstance( uow, model, entityState );
+            instanceCache.put( reference, entityInstance );
+        }
+        else
+        {
+            // Check if it has been removed
+            if( entityInstance.status() == EntityStatus.REMOVED )
+            {
+                throw new NoSuchEntityException( reference, mixinType, usecase );
+            }
+        }
+
+        return entityInstance.proxy();
+    }
+
+    public Usecase usecase()
+    {
+        return usecase;
+    }
+
+    public MetaInfo metaInfo()
+    {
+        if( metaInfo == null )
+        {
+            metaInfo = new MetaInfo();
+        }
+
+        return metaInfo;
+    }
+
+    public void pause()
+    {
+        if( !paused )
+        {
+            paused = true;
+            getCurrent().pop();
+
+            UnitOfWorkOptions unitOfWorkOptions = metaInfo().get( UnitOfWorkOptions.class );
+            if( unitOfWorkOptions == null )
+            {
+                unitOfWorkOptions = usecase().metaInfo( UnitOfWorkOptions.class );
+            }
+
+            if( unitOfWorkOptions != null )
+            {
+                if( unitOfWorkOptions.isPruneOnPause() )
+                {
+                    List<EntityReference> prunedInstances = null;
+                    for( EntityInstance entityInstance : instanceCache.values() )
+                    {
+                        if( entityInstance.status() == EntityStatus.LOADED )
+                        {
+                            if( prunedInstances == null )
+                            {
+                                prunedInstances = new ArrayList<>();
+                            }
+                            prunedInstances.add( entityInstance.reference() );
+                        }
+                    }
+                    if( prunedInstances != null )
+                    {
+                        prunedInstances.forEach( instanceCache::remove );
+                    }
+                }
+            }
+        }
+        else
+        {
+            throw new UnitOfWorkException( "Unit of work is not active" );
+        }
+    }
+
+    public void resume()
+    {
+        if( paused )
+        {
+            paused = false;
+            getCurrent().push( this );
+        }
+        else
+        {
+            throw new UnitOfWorkException( "Unit of work has not been paused" );
+        }
+    }
+
+    public void complete()
+        throws UnitOfWorkCompletionException
+    {
+        checkOpen();
+
+        // Copy list so that it cannot be modified during completion
+        List<UnitOfWorkCallback> currentCallbacks = callbacks == null ? null : new ArrayList<>( callbacks );
+
+        // Commit state to EntityStores
+        List<StateCommitter> committers = applyChanges();
+
+        // Check callbacks
+        notifyBeforeCompletion( currentCallbacks );
+
+        // Commit all changes
+        committers.forEach( StateCommitter::commit );
+
+        close();
+
+        // Call callbacks
+        notifyAfterCompletion( currentCallbacks, COMPLETED );
+
+        callbacks = currentCallbacks;
+    }
+
+    public void discard()
+    {
+        if( !isOpen() )
+        {
+            return;
+        }
+        close();
+
+        // Copy list so that it cannot be modified during completion
+        List<UnitOfWorkCallback> currentCallbacks = callbacks == null ? null : new ArrayList<>( callbacks );
+
+        // Call callbacks
+        notifyAfterCompletion( currentCallbacks, DISCARDED );
+        storeUnitOfWork.values().forEach( EntityStoreUnitOfWork::discard );
+        callbacks = currentCallbacks;
+    }
+
+    private void close()
+    {
+        checkOpen();
+
+        if( !isPaused() )
+        {
+            getCurrent().pop();
+        }
+        endCapture();
+        open = false;
+    }
+
+    public boolean isOpen()
+    {
+        return open;
+    }
+
+    public void addUnitOfWorkCallback( UnitOfWorkCallback callback )
+    {
+        if( callbacks == null )
+        {
+            callbacks = new ArrayList<>();
+        }
+
+        callbacks.add( callback );
+    }
+
+    public void removeUnitOfWorkCallback( UnitOfWorkCallback callback )
+    {
+        if( callbacks != null )
+        {
+            callbacks.remove( callback );
+        }
+    }
+
+    public void addEntity( EntityInstance instance )
+    {
+        instanceCache.put( instance.reference(), instance );
+    }
+
+    private List<StateCommitter> applyChanges()
+        throws UnitOfWorkCompletionException
+    {
+        List<StateCommitter> committers = new ArrayList<>();
+        for( EntityStoreUnitOfWork entityStoreUnitOfWork : storeUnitOfWork.values() )
+        {
+            try
+            {
+                StateCommitter committer = entityStoreUnitOfWork.applyChanges();
+                committers.add( committer );
+            }
+            catch( Exception e )
+            {
+                // Cancel all previously prepared stores
+                committers.forEach( StateCommitter::cancel );
+
+                if( e instanceof ConcurrentEntityStateModificationException )
+                {
+                    // If we cancelled due to concurrent modification, then create the proper exception for it!
+                    ConcurrentEntityStateModificationException mee = (ConcurrentEntityStateModificationException) e;
+                    Collection<EntityReference> modifiedEntityIdentities = mee.modifiedEntities();
+                    Map<EntityComposite, HasTypes> modifiedEntities = new HashMap<>();
+                    for( EntityReference modifiedEntityIdentity : modifiedEntityIdentities )
+                    {
+                        instanceCache.values().stream()
+                            .filter( instance -> instance.reference().equals( modifiedEntityIdentity ) )
+                            .forEach( instance -> modifiedEntities.put( instance.<EntityComposite>proxy(), instance ) );
+                    }
+                    throw new ConcurrentEntityModificationException( modifiedEntities, usecase );
+                }
+                else
+                {
+                    throw new UnitOfWorkCompletionException( e );
+                }
+            }
+        }
+        return committers;
+    }
+
+    private void notifyBeforeCompletion( List<UnitOfWorkCallback> callbacks )
+        throws UnitOfWorkCompletionException
+    {
+        // Notify explicitly registered callbacks
+        if( callbacks != null )
+        {
+            callbacks.forEach( UnitOfWorkCallback::beforeCompletion );
+        }
+
+        // Notify entities
+        try
+        {
+            for( EntityInstance instance : instanceCache.values() )
+            {
+                boolean isCallback = instance.proxy() instanceof UnitOfWorkCallback;
+                boolean isNotRemoved = !instance.status().equals( EntityStatus.REMOVED );
+                if( isCallback && isNotRemoved )
+                {
+                    UnitOfWorkCallback callback = UnitOfWorkCallback.class.cast( instance.proxy() );
+                    callback.beforeCompletion();
+                }
+            }
+        }
+        catch( UnitOfWorkCompletionException e )
+        {
+            throw e;
+        }
+        catch( Exception e )
+        {
+            throw new UnitOfWorkCompletionException( e );
+        }
+    }
+
+    private void notifyAfterCompletion( List<UnitOfWorkCallback> callbacks,
+                                        final UnitOfWorkCallback.UnitOfWorkStatus status
+    )
+    {
+        if( callbacks != null )
+        {
+            for( UnitOfWorkCallback callback : callbacks )
+            {
+                try
+                {
+                    callback.afterCompletion( status );
+                }
+                catch( Exception e )
+                {
+                    // Ignore
+                }
+            }
+        }
+
+        // Notify entities
+        try
+        {
+            for( EntityInstance instance : instanceCache.values() )
+            {
+                boolean isCallback = instance.proxy() instanceof UnitOfWorkCallback;
+                boolean isNotRemoved = !instance.status().equals( EntityStatus.REMOVED );
+                if( isCallback && isNotRemoved )
+                {
+                    UnitOfWorkCallback callback = UnitOfWorkCallback.class.cast( instance.proxy() );
+                    callback.afterCompletion( status );
+                }
+            }
+        }
+        catch( Exception e )
+        {
+            // Ignore
+        }
+    }
+
+    public void checkOpen()
+    {
+        if( !isOpen() )
+        {
+            throw new UnitOfWorkException( "Unit of work has been closed" );
+        }
+    }
+
+    public boolean isPaused()
+    {
+        return paused;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "UnitOfWork " + hashCode() + "(" + usecase + "): entities:" + instanceCache.size();
+    }
+
+    public void remove( EntityReference entityReference )
+    {
+        instanceCache.remove( entityReference );
+    }
+
+    private void startCapture()
+    {
+        getMetricsCounter().increment();
+        metricsTimerContext = getMetricsTimer().start();
+    }
+
+    private void endCapture()
+    {
+        getMetricsCounter().decrement();
+        metricsTimerContext.stop();
+        metricsTimerContext = null;
+    }
+
+    private MetricsCounter getMetricsCounter()
+    {
+        if( metricsCounter == null )
+        {
+            MetricsCounterFactory metricsFactory = metrics.createFactory( MetricsCounterFactory.class );
+            metricsCounter = metricsFactory.createCounter( MetricNames.nameFor( module, UnitOfWork.class, "counter" ) );
+        }
+        return metricsCounter;
+    }
+
+    private MetricsTimer getMetricsTimer()
+    {
+        if( metricsTimer == null )
+        {
+            MetricsTimerFactory metricsFactory = metrics.createFactory( MetricsTimerFactory.class );
+            metricsTimer = metricsFactory.createTimer( MetricNames.nameFor( module, UnitOfWork.class, "timer" ) );
+        }
+        return metricsTimer;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ManyAssociationValueState.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ManyAssociationValueState.java
new file mode 100644
index 0000000..590f25d
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ManyAssociationValueState.java
@@ -0,0 +1,116 @@
+/*
+ *  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.polygene.runtime.value;
+
+import java.util.Iterator;
+import java.util.List;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.spi.entity.ManyAssociationState;
+
+/**
+ * ManyAssociationState implementation for Value composites.
+ */
+public class ManyAssociationValueState
+    implements ManyAssociationState
+{
+    private List<EntityReference> references;
+
+    public ManyAssociationValueState( List<EntityReference> references )
+    {
+        this.references = references;
+    }
+
+    @Override
+    public int count()
+    {
+        return references.size();
+    }
+
+    @Override
+    public boolean contains( EntityReference entityReference )
+    {
+        return references.contains( entityReference );
+    }
+
+    @Override
+    public boolean add( int i, EntityReference entityReference )
+    {
+        if( references.contains( entityReference ) )
+        {
+            return false;
+        }
+
+        references.add( i, entityReference );
+        return true;
+    }
+
+    @Override
+    public boolean remove( EntityReference entity )
+    {
+        return references.remove( entity );
+    }
+
+    @Override
+    public boolean clear()
+    {
+        if( !references.isEmpty() )
+        {
+            references.clear();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public EntityReference get( int i )
+    {
+        return references.get( i );
+    }
+
+    @Override
+    public Iterator<EntityReference> iterator()
+    {
+        final Iterator<EntityReference> iter = references.iterator();
+
+        return new Iterator<EntityReference>()
+        {
+            EntityReference current;
+
+            @Override
+            public boolean hasNext()
+            {
+                return iter.hasNext();
+            }
+
+            @Override
+            public EntityReference next()
+            {
+                current = iter.next();
+                return current;
+            }
+
+            @Override
+            public void remove()
+            {
+                iter.remove();
+            }
+        };
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/NamedAssociationValueState.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/NamedAssociationValueState.java
new file mode 100644
index 0000000..c15b950
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/NamedAssociationValueState.java
@@ -0,0 +1,96 @@
+/*
+ *  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.polygene.runtime.value;
+
+import java.util.Iterator;
+import java.util.Map;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.spi.entity.NamedAssociationState;
+
+public class NamedAssociationValueState
+    implements NamedAssociationState
+{
+    private final Map<String, EntityReference> references;
+
+    public NamedAssociationValueState( Map<String, EntityReference> references )
+    {
+        this.references = references;
+    }
+
+    @Override
+    public int count()
+    {
+        return references.size();
+    }
+
+    @Override
+    public boolean containsName( String name )
+    {
+        return references.containsKey( name );
+    }
+
+    @Override
+    public boolean put( String name, EntityReference entityReference )
+    {
+        return references.put( name, entityReference ) != null;
+    }
+
+    @Override
+    public boolean remove( String name )
+    {
+        return references.remove( name ) != null;
+    }
+
+    @Override
+    public boolean clear()
+    {
+        if( !references.isEmpty() )
+        {
+            references.clear();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public EntityReference get( String name )
+    {
+        return references.get( name );
+    }
+
+    @Override
+    public String nameOf( EntityReference entityReference )
+    {
+        for( Map.Entry<String, EntityReference> entry : references.entrySet() )
+        {
+            if( entry.getValue().equals( entityReference ) )
+            {
+                return entry.getKey();
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Iterator<String> iterator()
+    {
+        return references.keySet().iterator();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ReferenceProperty.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ReferenceProperty.java
new file mode 100644
index 0000000..6dd6d18
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ReferenceProperty.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.runtime.value;
+
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * The reference for an Association
+ */
+public class ReferenceProperty
+    implements Property<EntityReference>
+{
+    EntityReference reference;
+
+    public ReferenceProperty()
+    {
+    }
+
+    public ReferenceProperty( EntityReference reference )
+    {
+        this.reference = reference;
+    }
+
+    @Override
+    public EntityReference get()
+    {
+        return reference;
+    }
+
+    @Override
+    public void set( EntityReference newValue )
+        throws IllegalArgumentException, IllegalStateException
+    {
+        reference = newValue;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderInstance.java
new file mode 100644
index 0000000..91f975d
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderInstance.java
@@ -0,0 +1,93 @@
+/*
+ *  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.polygene.runtime.value;
+
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.value.NoSuchValueException;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.runtime.composite.StateResolver;
+import org.apache.polygene.runtime.structure.ModuleInstance;
+
+/**
+ * Implementation of ValueBuilder
+ */
+public final class ValueBuilderInstance<T>
+    implements ValueBuilder<T>
+{
+
+    private final ModuleInstance currentModule;
+    private final ValueInstance prototypeInstance;
+
+    public ValueBuilderInstance( ValueDescriptor compositeModel,
+                                 ModuleInstance currentModule,
+                                 StateResolver stateResolver
+    )
+    {
+        ValueStateInstance state = new ValueStateInstance( compositeModel, currentModule, stateResolver );
+        ValueModel model = (ValueModel) compositeModel;
+        prototypeInstance = model.newValueInstance( state );
+        prototypeInstance.prepareToBuild();
+        this.currentModule = currentModule;
+    }
+
+    @Override
+    public T prototype()
+    {
+        return prototypeInstance.proxy();
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public Class<T> primaryType()
+    {
+        return (Class<T>) prototypeInstance.descriptor().primaryType();
+    }
+
+    @Override
+    public AssociationStateHolder state()
+    {
+        return prototypeInstance.state();
+    }
+
+    @Override
+    public <K> K prototypeFor( Class<K> mixinType )
+    {
+        return prototypeInstance.newProxy( mixinType );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public T newInstance()
+        throws ConstructionException
+    {
+        Class<Composite> valueType = (Class<Composite>) prototypeInstance.types().findFirst().orElse( null );
+
+        ValueDescriptor valueModel = currentModule.typeLookup().lookupValueModel( valueType );
+
+        if( valueModel == null )
+        {
+            throw new NoSuchValueException( valueType.getName(), currentModule.name(), currentModule.typeLookup() );
+        }
+        return new ValueBuilderWithPrototype<>( valueModel, currentModule, prototype() ).newInstance();
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderWithPrototype.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderWithPrototype.java
new file mode 100644
index 0000000..bbb6c99
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderWithPrototype.java
@@ -0,0 +1,211 @@
+/*
+ *  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.polygene.runtime.value;
+
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.runtime.composite.FunctionStateResolver;
+import org.apache.polygene.runtime.composite.MixinModel;
+import org.apache.polygene.runtime.composite.MixinsModel;
+import org.apache.polygene.runtime.composite.StateResolver;
+import org.apache.polygene.runtime.composite.UsesInstance;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.structure.ModuleInstance;
+
+import static org.apache.polygene.api.composite.CompositeInstance.compositeInstanceOf;
+
+/**
+ * Implementation of ValueBuilder with a prototype supplied
+ */
+public class ValueBuilderWithPrototype<T>
+    implements ValueBuilder<T>
+{
+    private ValueInstance prototypeInstance;
+    private final ValueModel valueModel;
+
+    public ValueBuilderWithPrototype( ValueDescriptor compositeModelModule,
+                                      ModuleInstance currentModule,
+                                      T prototype
+                                    )
+    {
+        valueModel = (ValueModel) compositeModelModule;
+        MixinsModel mixinsModel = valueModel.mixinsModel();
+        Object[] mixins = mixinsModel.newMixinHolder();
+        final ValueStateInstance prototypeState = ( (ValueInstance) compositeInstanceOf( (Composite) prototype ) ).state();
+        StateResolver resolver = new FunctionStateResolver(
+            new PropertyDescriptorFunction( prototypeState ),
+            new AssociationDescriptorEntityReferenceFunction( prototypeState ),
+            new AssociationDescriptorIterableFunction( prototypeState ),
+            new AssociationDescriptorMapFunction( prototypeState )
+        );
+        ValueStateInstance state = new ValueStateInstance( compositeModelModule, currentModule, resolver );
+        ValueInstance valueInstance = new ValueInstance(
+            valueModel,
+            mixins,
+            state
+        );
+
+        int i = 0;
+        InjectionContext injectionContext = new InjectionContext( valueInstance, UsesInstance.EMPTY_USES, state );
+        for( MixinModel mixinModel : mixinsModel.mixinModels() )
+        {
+            mixins[ i++ ] = mixinModel.newInstance( injectionContext );
+        }
+
+        valueInstance.prepareToBuild();
+        this.prototypeInstance = valueInstance;
+    }
+
+    @Override
+    public T prototype()
+    {
+        verifyUnderConstruction();
+        return prototypeInstance.proxy();
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public Class<T> primaryType()
+    {
+        return (Class<T>) valueModel.primaryType();
+    }
+
+    @Override
+    public AssociationStateHolder state()
+    {
+        verifyUnderConstruction();
+        return prototypeInstance.state();
+    }
+
+    @Override
+    public <K> K prototypeFor( Class<K> mixinType )
+    {
+        verifyUnderConstruction();
+        return prototypeInstance.newProxy( mixinType );
+    }
+
+    @Override
+    public T newInstance()
+        throws ConstructionException
+    {
+        verifyUnderConstruction();
+
+        // Set correct info's (immutable) on the state
+        prototypeInstance.prepareBuilderState();
+
+        // Check that it is valid
+        valueModel.checkConstraints( prototypeInstance.state() );
+
+        try
+        {
+            return prototypeInstance.proxy();
+        }
+        finally
+        {
+            // Invalidate builder
+            prototypeInstance = null;
+        }
+    }
+
+    private void verifyUnderConstruction()
+    {
+        if( prototypeInstance == null )
+        {
+            throw new IllegalStateException( "ValueBuilder instances cannot be reused" );
+        }
+    }
+
+    private static class PropertyDescriptorFunction
+        implements Function<PropertyDescriptor, Object>
+    {
+        private final ValueStateInstance prototypeState;
+
+        PropertyDescriptorFunction( ValueStateInstance prototypeState )
+        {
+            this.prototypeState = prototypeState;
+        }
+
+        @Override
+        public Object apply( PropertyDescriptor descriptor )
+        {
+            return prototypeState.propertyFor( descriptor.accessor() ).get();
+        }
+    }
+
+    private static class AssociationDescriptorEntityReferenceFunction
+        implements Function<AssociationDescriptor, EntityReference>
+    {
+        private final ValueStateInstance prototypeState;
+
+        AssociationDescriptorEntityReferenceFunction( ValueStateInstance prototypeState )
+        {
+            this.prototypeState = prototypeState;
+        }
+
+        @Override
+        public EntityReference apply( AssociationDescriptor descriptor )
+        {
+            return prototypeState.associationFor( descriptor.accessor() ).reference();
+        }
+    }
+
+    private static class AssociationDescriptorIterableFunction
+        implements Function<AssociationDescriptor, Stream<EntityReference>>
+    {
+        private final ValueStateInstance prototypeState;
+
+        AssociationDescriptorIterableFunction( ValueStateInstance prototypeState )
+        {
+            this.prototypeState = prototypeState;
+        }
+
+        @Override
+        public Stream<EntityReference> apply( AssociationDescriptor descriptor )
+        {
+            return prototypeState.manyAssociationFor( descriptor.accessor() ).references();
+        }
+    }
+
+    private static class AssociationDescriptorMapFunction
+        implements Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>>
+    {
+        private final ValueStateInstance prototypeState;
+
+        AssociationDescriptorMapFunction( ValueStateInstance prototypeState )
+        {
+            this.prototypeState = prototypeState;
+        }
+
+        @Override
+        public Stream<Map.Entry<String, EntityReference>> apply( AssociationDescriptor descriptor )
+        {
+            return prototypeState.namedAssociationFor( descriptor.accessor() ).references();
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderWithState.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderWithState.java
new file mode 100644
index 0000000..c49d809
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderWithState.java
@@ -0,0 +1,105 @@
+/*
+ *  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.polygene.runtime.value;
+
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.runtime.composite.StateResolver;
+import org.apache.polygene.runtime.structure.ModuleInstance;
+
+public class ValueBuilderWithState<T>
+    implements ValueBuilder<T>
+{
+    private final ValueDescriptor model;
+    private ValueInstance prototypeInstance;
+
+    public ValueBuilderWithState( ValueDescriptor compositeModelModule,
+                                  ModuleInstance currentModule,
+                                  StateResolver stateResolver )
+    {
+        ValueStateInstance state = new ValueStateInstance( compositeModelModule, currentModule, stateResolver );
+        ValueInstance instance = ((ValueModel) compositeModelModule).newValueInstance( state );
+        instance.prepareToBuild();
+        this.model = compositeModelModule;
+        this.prototypeInstance = instance;
+    }
+
+    @Override
+    public T prototype()
+    {
+        verifyUnderConstruction();
+        return prototypeInstance.proxy();
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public Class<T> primaryType()
+    {
+        return (Class<T>) model.primaryType();
+    }
+
+    @Override
+    public AssociationStateHolder state()
+    {
+        verifyUnderConstruction();
+        return prototypeInstance.state();
+    }
+
+    @Override
+    public <K> K prototypeFor( Class<K> mixinType )
+    {
+        verifyUnderConstruction();
+
+        return prototypeInstance.newProxy( mixinType );
+    }
+
+    @Override
+    public T newInstance()
+        throws ConstructionException
+    {
+        verifyUnderConstruction();
+
+        // Set correct info's (immutable) on the state
+        prototypeInstance.prepareBuilderState();
+
+        // Check that it is valid
+        ((ValueModel) model).checkConstraints( prototypeInstance.state() );
+
+        try
+        {
+            return prototypeInstance.proxy();
+        }
+        finally
+        {
+            // Invalidate builder
+            prototypeInstance = null;
+        }
+    }
+
+    private void verifyUnderConstruction()
+    {
+        if( prototypeInstance == null )
+        {
+            throw new IllegalStateException( "ValueBuilder instances cannot be reused" );
+        }
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueInstance.java
new file mode 100644
index 0000000..5e678c5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueInstance.java
@@ -0,0 +1,153 @@
+/*
+ *  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.polygene.runtime.value;
+
+import java.lang.reflect.Proxy;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.runtime.composite.MixinsInstance;
+import org.apache.polygene.runtime.composite.TransientInstance;
+import org.apache.polygene.runtime.property.PropertyInstance;
+import org.apache.polygene.spi.module.ModuleSpi;
+
+/**
+ * ValueComposite instance
+ */
+public final class ValueInstance extends TransientInstance
+    implements CompositeInstance, MixinsInstance
+{
+    public ValueInstance( ValueModel compositeModel, Object[] mixins, ValueStateInstance state )
+    {
+        super( compositeModel, mixins, state );
+    }
+
+    /**
+     * Perform equals with {@code o} argument.
+     * <p>
+     * The definition of equals() for the Value is that if both the state and descriptor are equal,
+     * then the values are equal.
+     * </p>
+     *
+     * @param o The other object to compare.
+     *
+     * @return Returns a {@code boolean} indicator whether this object is equals the other.
+     */
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || !Proxy.isProxyClass( o.getClass() ) )
+        {
+            return false;
+        }
+
+        try
+        {
+            ValueInstance that = (ValueInstance) Proxy.getInvocationHandler( o );
+            // Descriptor equality
+            if( !descriptor().equals( that.descriptor() ) )
+            {
+                return false;
+            }
+            // State equality
+            return state.equals( that.state );
+        }
+        catch( ClassCastException e )
+        {
+            return false;
+        }
+    }
+
+    @Override
+    public ValueStateInstance state()
+    {
+        return (ValueStateInstance) state;
+    }
+
+    @Override
+    public ValueModel descriptor()
+    {
+        return (ValueModel) compositeModel;
+    }
+
+    /**
+     * When a ValueBuilder is about to start, ensure that all state has builder infos, i.e. they are mutable.
+     */
+    public void prepareToBuild()
+    {
+        descriptor().state().properties().forEach(
+            descriptor -> ( (PropertyInstance<Object>) state.propertyFor( descriptor.accessor() ) )
+                .prepareToBuild( descriptor ) );
+
+        descriptor().state().associations().forEach(
+            descriptor -> state().associationFor( descriptor.accessor() )
+                                 .setAssociationInfo( descriptor.builderInfo() ) );
+
+        descriptor().state().manyAssociations().forEach(
+            descriptor -> state().manyAssociationFor( descriptor.accessor() )
+                                 .setAssociationInfo( descriptor.builderInfo() ) );
+
+        descriptor().state().namedAssociations().forEach(
+            descriptor -> state().namedAssociationFor( descriptor.accessor() )
+                                 .setAssociationInfo( descriptor.builderInfo() ) );
+    }
+
+    /**
+     * When a ValueBuilder is finished and is about to instantiate a Value, call this to ensure that the state has correct
+     * settings, i.e. is immutable.
+     */
+    public void prepareBuilderState()
+    {
+        descriptor().state().properties().forEach(
+            descriptor -> ( (PropertyInstance<Object>) state.propertyFor( descriptor.accessor() ) )
+                .prepareBuilderState( descriptor ) );
+
+        descriptor().state().associations().forEach(
+            descriptor -> state().associationFor( descriptor.accessor() ).setAssociationInfo( descriptor ) );
+
+        descriptor().state().manyAssociations().forEach(
+            descriptor -> state().manyAssociationFor( descriptor.accessor() ).setAssociationInfo( descriptor ) );
+
+        descriptor().state().namedAssociations().forEach(
+            descriptor -> state().namedAssociationFor( descriptor.accessor() ).setAssociationInfo( descriptor ) );
+    }
+
+    /**
+     * Calculate hash code.
+     *
+     * @return the hashcode of this instance.
+     */
+    @Override
+    public int hashCode()
+    {
+        int hash = compositeModel.hashCode() * 23; // Descriptor
+        return hash + state.hashCode() * 5; // State
+    }
+
+    @Override
+    public String toString()
+    {
+        Serializer serialization = ( (ModuleSpi) module().instance() ).serialization();
+        return serialization.serialize( Serializer.Options.NO_TYPE_INFO, proxy() );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueModel.java
new file mode 100644
index 0000000..b79b298
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueModel.java
@@ -0,0 +1,143 @@
+/*
+ *  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.polygene.runtime.value;
+
+import java.lang.reflect.Member;
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ValueCompositeType;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.runtime.composite.CompositeMethodsModel;
+import org.apache.polygene.runtime.composite.CompositeModel;
+import org.apache.polygene.runtime.composite.MixinModel;
+import org.apache.polygene.runtime.composite.MixinsModel;
+import org.apache.polygene.runtime.composite.UsesInstance;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.unitofwork.UnitOfWorkInstance;
+
+/**
+ * Model for ValueComposites
+ */
+public final class ValueModel extends CompositeModel
+    implements ValueDescriptor
+{
+    private ValueCompositeType valueType;
+
+    public ValueModel( final ModuleDescriptor module,
+                       final List<Class<?>> types,
+                       final Visibility visibility,
+                       final MetaInfo metaInfo,
+                       final MixinsModel mixinsModel,
+                       final ValueStateModel stateModel,
+                       final CompositeMethodsModel compositeMethodsModel
+    )
+    {
+        super( module, types, visibility, metaInfo, mixinsModel, stateModel, compositeMethodsModel );
+
+        valueType = ValueCompositeType.of( this );
+    }
+
+    @Override
+    public ValueCompositeType valueType()
+    {
+        return valueType;
+    }
+
+    @Override
+    public ValueStateModel state()
+    {
+        return (ValueStateModel) super.state();
+    }
+
+    // This method is ONLY called by ValueBuilders
+    void checkConstraints( ValueStateInstance state )
+        throws ConstraintViolationException
+    {
+        stateModel.properties().forEach(
+            propertyModel ->
+            {
+                try
+                {
+                    propertyModel.checkConstraints( state.propertyFor( propertyModel.accessor() ).get() );
+                }
+                catch( ConstraintViolationException e )
+                {
+                    throw new ConstraintViolationException( "<builder>", propertyModel.valueType()
+                        .types(), (Member) propertyModel.accessor(), e.constraintViolations() );
+                }
+            }
+        );
+
+        // IF no UnitOfWork is active, then the Association checks shouldn't be done.
+        if( UnitOfWorkInstance.getCurrent().empty() )
+        {
+            return;
+        }
+        ( (ValueStateModel) stateModel ).associations().forEach(
+            associationModel ->
+            {
+                try
+                {
+                    associationModel.checkConstraints( state.associationFor( associationModel.accessor() ).get() );
+                }
+                catch( ConstraintViolationException e )
+                {
+                    Stream<? extends Type> types = Classes.interfacesOf( associationModel.type() );
+                    throw new ConstraintViolationException( "<builder>", types,
+                                                            (Member) associationModel.accessor(),
+                                                            e.constraintViolations() );
+                }
+            }
+        );
+
+        ( (ValueStateModel) stateModel ).manyAssociations().forEach(
+            model -> model.checkAssociationConstraints( state.manyAssociationFor( model.accessor() ) )
+        );
+
+        ( (ValueStateModel) stateModel ).namedAssociations().forEach(
+            model -> model.checkAssociationConstraints( state.namedAssociationFor( model.accessor() ) )
+        );
+    }
+
+    public ValueInstance newValueInstance( ValueStateInstance state )
+    {
+        Object[] mixins = mixinsModel.newMixinHolder();
+
+        ValueInstance instance = new ValueInstance( this, mixins, state );
+
+        // Instantiate all mixins
+        int i = 0;
+        InjectionContext injectionContext = new InjectionContext( instance, UsesInstance.EMPTY_USES, state );
+        for( MixinModel mixinModel : mixinsModel.mixinModels() )
+        {
+            mixins[ i++ ] = mixinModel.newInstance( injectionContext );
+        }
+
+        // Return
+        return instance;
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueStateInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueStateInstance.java
new file mode 100644
index 0000000..a5e50e0
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueStateInstance.java
@@ -0,0 +1,222 @@
+/*
+ *  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.polygene.runtime.value;
+
+import java.lang.reflect.AccessibleObject;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.runtime.association.AssociationInfo;
+import org.apache.polygene.runtime.association.AssociationInstance;
+import org.apache.polygene.runtime.association.ManyAssociationInstance;
+import org.apache.polygene.runtime.association.NamedAssociationInstance;
+import org.apache.polygene.runtime.composite.StateResolver;
+import org.apache.polygene.runtime.property.PropertyInfo;
+import org.apache.polygene.runtime.property.PropertyInstance;
+import org.apache.polygene.runtime.structure.ModuleInstance;
+import org.apache.polygene.runtime.unitofwork.EntityFunction;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.polygene.api.util.Collectors.toMap;
+
+/**
+ * TODO
+ */
+public final class ValueStateInstance
+    implements AssociationStateHolder
+{
+    private final Map<AccessibleObject, PropertyInstance<?>> properties;
+    private final Map<AccessibleObject, AssociationInstance<?>> associations;
+    private final Map<AccessibleObject, ManyAssociationInstance<?>> manyAssociations;
+    private final Map<AccessibleObject, NamedAssociationInstance<?>> namedAssociations;
+
+    public ValueStateInstance( ValueDescriptor compositeModelModule,
+                               ModuleInstance currentModule,
+                               StateResolver stateResolver
+    )
+    {
+        EntityFunction entityFunction = new EntityFunction( currentModule.unitOfWorkFactory() );
+
+        ValueModel valueModel = (ValueModel) compositeModelModule;
+        this.properties = new LinkedHashMap<>();
+        valueModel.state().properties().forEach( propertyDescriptor -> {
+            PropertyInfo builderInfo = propertyDescriptor.getBuilderInfo();
+            Object value = stateResolver.getPropertyState( propertyDescriptor );
+            PropertyInstance<Object> propertyInstance = new PropertyInstance<>( builderInfo, value );
+            properties.put( propertyDescriptor.accessor(), propertyInstance );
+        } );
+
+        this.associations = new LinkedHashMap<>();
+        valueModel.state().associations().forEach( associationDescriptor -> {
+            AssociationInfo builderInfo = associationDescriptor.builderInfo();
+            EntityReference value = stateResolver.getAssociationState( associationDescriptor );
+            AssociationInstance<Object> associationInstance1 = new AssociationInstance<>(
+                builderInfo,
+                entityFunction,
+                new ReferenceProperty( value ) );
+            associations.put( associationDescriptor.accessor(), associationInstance1 );
+        } );
+
+        this.manyAssociations = new LinkedHashMap<>();
+        valueModel.state().manyAssociations().forEach( associationDescriptor -> {
+            AssociationInfo builderInfo = associationDescriptor.builderInfo();
+            List<EntityReference> value = stateResolver.getManyAssociationState( associationDescriptor )
+                                                       .collect( toList() );
+            ManyAssociationValueState manyAssociationState = new ManyAssociationValueState( value );
+            ManyAssociationInstance<Object> associationInstance = new ManyAssociationInstance<>(
+                builderInfo,
+                entityFunction,
+                manyAssociationState );
+            manyAssociations.put( associationDescriptor.accessor(), associationInstance );
+        } );
+
+        this.namedAssociations = new LinkedHashMap<>();
+        valueModel.state().namedAssociations().forEach( associationDescriptor -> {
+            AssociationInfo builderInfo = associationDescriptor.builderInfo();
+            Map<String, EntityReference> value = stateResolver.getNamedAssociationState( associationDescriptor )
+                                                              .collect( toMap( LinkedHashMap::new ) );
+            NamedAssociationValueState namedAssociationState = new NamedAssociationValueState( value );
+            NamedAssociationInstance<Object> associationInstance = new NamedAssociationInstance<>(
+                builderInfo,
+                entityFunction,
+                namedAssociationState );
+            namedAssociations.put( associationDescriptor.accessor(), associationInstance );
+        } );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> PropertyInstance<T> propertyFor( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        PropertyInstance<T> property = (PropertyInstance<T>) properties.get( accessor );
+
+        if( property == null )
+        {
+            throw new IllegalArgumentException( "No such property:" + accessor );
+        }
+
+        return property;
+    }
+
+    @Override
+    public Stream<PropertyInstance<?>> properties()
+    {
+        return properties.values().stream();
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> AssociationInstance<T> associationFor( AccessibleObject accessor )
+    {
+        AssociationInstance<T> association = (AssociationInstance<T>) associations.get( accessor );
+
+        if( association == null )
+        {
+            throw new IllegalArgumentException( "No such association:" + accessor );
+        }
+
+        return association;
+    }
+
+    @Override
+    public Stream<AssociationInstance<?>> allAssociations()
+    {
+        return associations.values().stream();
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> ManyAssociationInstance<T> manyAssociationFor( AccessibleObject accessor )
+    {
+        ManyAssociationInstance<T> manyAssociation = (ManyAssociationInstance<T>) manyAssociations.get( accessor );
+
+        if( manyAssociation == null )
+        {
+            throw new IllegalArgumentException( "No such many-association:" + accessor );
+        }
+
+        return manyAssociation;
+    }
+
+    @Override
+    public Stream<ManyAssociationInstance<?>> allManyAssociations()
+    {
+        return manyAssociations.values().stream();
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> NamedAssociationInstance<T> namedAssociationFor( AccessibleObject accessor )
+    {
+        NamedAssociationInstance<T> namedAssociation = (NamedAssociationInstance<T>) namedAssociations.get( accessor );
+
+        if( namedAssociation == null )
+        {
+            throw new IllegalArgumentException( "No such named-association:" + accessor );
+        }
+
+        return namedAssociation;
+    }
+
+    @Override
+    public Stream<? extends NamedAssociationInstance<?>> allNamedAssociations()
+    {
+        return namedAssociations.values().stream();
+    }
+
+    @SuppressWarnings( "SimplifiableIfStatement" )
+    @Override
+    public boolean equals( Object obj )
+    {
+        if( !( obj instanceof ValueStateInstance ) )
+        {
+            return false;
+        }
+        ValueStateInstance state = (ValueStateInstance) obj;
+        if( !properties.equals( state.properties ) )
+        {
+            return false;
+        }
+        if( !associations.equals( state.associations ) )
+        {
+            return false;
+        }
+        if( !manyAssociations.equals( state.manyAssociations ) )
+        {
+            return false;
+        }
+        return namedAssociations.equals( state.namedAssociations );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int result = properties.hashCode();
+        result = 31 * result + associations.hashCode();
+        result = 31 * result + manyAssociations.hashCode();
+        result = 31 * result + namedAssociations.hashCode();
+        return result;
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueStateModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueStateModel.java
new file mode 100644
index 0000000..73c6a17
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueStateModel.java
@@ -0,0 +1,133 @@
+/*
+ *  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.polygene.runtime.value;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.AssociationStateDescriptor;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.association.AssociationModel;
+import org.apache.polygene.runtime.association.AssociationsModel;
+import org.apache.polygene.runtime.association.ManyAssociationModel;
+import org.apache.polygene.runtime.association.ManyAssociationsModel;
+import org.apache.polygene.runtime.association.NamedAssociationModel;
+import org.apache.polygene.runtime.association.NamedAssociationsModel;
+import org.apache.polygene.runtime.composite.StateModel;
+import org.apache.polygene.runtime.property.PropertiesModel;
+
+/**
+ * Model for ValueComposite state.
+ */
+public final class ValueStateModel
+    extends StateModel
+    implements AssociationStateDescriptor
+{
+    private final AssociationsModel associationsModel;
+    private final ManyAssociationsModel manyAssociationsModel;
+    private final NamedAssociationsModel namedAssociationsModel;
+
+    public ValueStateModel( PropertiesModel propertiesModel,
+                            AssociationsModel associationsModel,
+                            ManyAssociationsModel manyAssociationsModel,
+                            NamedAssociationsModel namedAssociationsModel
+    )
+    {
+        super( propertiesModel );
+        this.associationsModel = associationsModel;
+        this.manyAssociationsModel = manyAssociationsModel;
+        this.namedAssociationsModel = namedAssociationsModel;
+    }
+
+    @Override
+    public AssociationDescriptor getAssociationByName( String name )
+    {
+        return associationsModel.getAssociationByName( name );
+    }
+
+    @Override
+    public AssociationDescriptor getAssociationByQualifiedName( QualifiedName name )
+    {
+        return associationsModel.getAssociationByQualifiedName( name );
+    }
+
+    @Override
+    public AssociationDescriptor getManyAssociationByName( String name )
+    {
+        return manyAssociationsModel.getManyAssociationByName( name );
+    }
+
+    @Override
+    public AssociationDescriptor getManyAssociationByQualifiedName( QualifiedName name )
+    {
+        return manyAssociationsModel.getManyAssociationByQualifiedName( name );
+    }
+
+    @Override
+    public AssociationDescriptor getNamedAssociationByName( String name )
+    {
+        return namedAssociationsModel.getNamedAssociationByName( name );
+    }
+
+    @Override
+    public AssociationDescriptor getNamedAssociationByQualifiedName( QualifiedName name )
+    {
+        return namedAssociationsModel.getNamedAssociationByQualifiedName( name );
+    }
+
+    @Override
+    public Stream<AssociationModel> associations()
+    {
+        return associationsModel.associations();
+    }
+
+    @Override
+    public Stream<ManyAssociationModel> manyAssociations()
+    {
+        return manyAssociationsModel.manyAssociations();
+    }
+
+    @Override
+    public Stream<NamedAssociationModel> namedAssociations()
+    {
+        return namedAssociationsModel.namedAssociations();
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            if( ( (VisitableHierarchy<Object, Object>) propertiesModel ).accept( visitor ) )
+            {
+                if( ( (VisitableHierarchy<AssociationsModel, AssociationModel>) associationsModel ).accept( visitor ) )
+                {
+                    if( ( (VisitableHierarchy<ManyAssociationsModel, ManyAssociationModel>) manyAssociationsModel ).accept( visitor ) )
+                    {
+                        ( (VisitableHierarchy<NamedAssociationsModel, NamedAssociationModel>) namedAssociationsModel ).accept( visitor );
+                    }
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValuesModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValuesModel.java
new file mode 100644
index 0000000..caa875b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValuesModel.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.runtime.value;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.api.value.ValueDescriptor;
+
+/**
+ * JAVADOC
+ */
+public final class ValuesModel
+    implements VisitableHierarchy<Object, Object>
+{
+    private final List<ValueModel> valueModels;
+
+    public ValuesModel( List<ValueModel> valueModels )
+    {
+        this.valueModels = valueModels;
+    }
+
+    public Stream<ValueModel> models()
+    {
+        return valueModels.stream();
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( ValueModel valueModel : valueModels )
+            {
+                if( !valueModel.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public Stream<? extends ValueDescriptor> stream()
+    {
+        return valueModels.stream();
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/Qi4jRuntimeImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/Qi4jRuntimeImpl.java
deleted file mode 100644
index 232ad6f..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/Qi4jRuntimeImpl.java
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime;
-
-import java.lang.reflect.InvocationHandler;
-import java.util.Arrays;
-import java.util.Map;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.association.AbstractAssociation;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.association.AssociationWrapper;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.ManyAssociationWrapper;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.association.NamedAssociationWrapper;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.api.composite.ModelDescriptor;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.composite.TransientDescriptor;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.property.PropertyWrapper;
-import org.qi4j.api.property.StateHolder;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.bootstrap.ApplicationAssemblyFactory;
-import org.qi4j.bootstrap.ApplicationModelFactory;
-import org.qi4j.bootstrap.Qi4jRuntime;
-import org.qi4j.runtime.association.AbstractAssociationInstance;
-import org.qi4j.runtime.association.AssociationInstance;
-import org.qi4j.runtime.association.ManyAssociationInstance;
-import org.qi4j.runtime.association.NamedAssociationInstance;
-import org.qi4j.runtime.bootstrap.ApplicationAssemblyFactoryImpl;
-import org.qi4j.runtime.bootstrap.ApplicationModelFactoryImpl;
-import org.qi4j.runtime.composite.ProxyReferenceInvocationHandler;
-import org.qi4j.runtime.composite.TransientInstance;
-import org.qi4j.runtime.entity.EntityInstance;
-import org.qi4j.runtime.property.PropertyInstance;
-import org.qi4j.runtime.service.ImportedServiceReferenceInstance;
-import org.qi4j.runtime.service.ServiceInstance;
-import org.qi4j.runtime.service.ServiceReferenceInstance;
-import org.qi4j.runtime.structure.ModuleUnitOfWork;
-import org.qi4j.runtime.value.ValueInstance;
-import org.qi4j.spi.Qi4jSPI;
-import org.qi4j.spi.entity.EntityState;
-
-import static java.lang.reflect.Proxy.getInvocationHandler;
-import static org.qi4j.runtime.composite.TransientInstance.compositeInstanceOf;
-
-/**
- * Incarnation of Zest.
- */
-public final class Qi4jRuntimeImpl
-    implements Qi4jSPI, Qi4jRuntime
-{
-    private final ApplicationAssemblyFactory applicationAssemblyFactory;
-    private final ApplicationModelFactory applicationModelFactory;
-
-    public Qi4jRuntimeImpl()
-    {
-        applicationAssemblyFactory = new ApplicationAssemblyFactoryImpl();
-        applicationModelFactory = new ApplicationModelFactoryImpl();
-    }
-
-    @Override
-    public ApplicationAssemblyFactory applicationAssemblyFactory()
-    {
-        return applicationAssemblyFactory;
-    }
-
-    @Override
-    public ApplicationModelFactory applicationModelFactory()
-    {
-        return applicationModelFactory;
-    }
-
-    @Override
-    public Qi4j api()
-    {
-        return this;
-    }
-
-    @Override
-    public Qi4jSPI spi()
-    {
-        return this;
-    }
-
-    // API
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public <T> T dereference( T composite )
-    {
-        InvocationHandler handler = getInvocationHandler( composite );
-        if( handler instanceof ProxyReferenceInvocationHandler )
-        {
-            return (T) ( (ProxyReferenceInvocationHandler) handler ).proxy();
-        }
-        if( handler instanceof CompositeInstance )
-        {
-            return composite;
-        }
-        return null;
-    }
-
-    @Override
-    public Module moduleOf( Object compositeOrServiceReferenceOrUow )
-    {
-        if( compositeOrServiceReferenceOrUow instanceof TransientComposite )
-        {
-            TransientComposite composite = (TransientComposite) compositeOrServiceReferenceOrUow;
-            return TransientInstance.compositeInstanceOf( composite ).module();
-        }
-        else if( compositeOrServiceReferenceOrUow instanceof EntityComposite )
-        {
-            EntityComposite composite = (EntityComposite) compositeOrServiceReferenceOrUow;
-            return EntityInstance.entityInstanceOf( composite ).module();
-        }
-        else if( compositeOrServiceReferenceOrUow instanceof ValueComposite )
-        {
-            ValueComposite composite = (ValueComposite) compositeOrServiceReferenceOrUow;
-            return ValueInstance.valueInstanceOf( composite ).module();
-        }
-        else if( compositeOrServiceReferenceOrUow instanceof ServiceComposite )
-        {
-            ServiceComposite composite = (ServiceComposite) compositeOrServiceReferenceOrUow;
-            InvocationHandler handler = getInvocationHandler( composite );
-            if( handler instanceof ServiceInstance )
-            {
-                return ( (ServiceInstance) handler ).module();
-            }
-            return ( (ServiceReferenceInstance.ServiceInvocationHandler) handler ).module();
-        }
-        else if( compositeOrServiceReferenceOrUow instanceof UnitOfWork )
-        {
-            ModuleUnitOfWork unitOfWork = (ModuleUnitOfWork) compositeOrServiceReferenceOrUow;
-            return unitOfWork.module();
-        }
-        else if( compositeOrServiceReferenceOrUow instanceof ServiceReferenceInstance )
-        {
-            ServiceReferenceInstance<?> reference = (ServiceReferenceInstance<?>) compositeOrServiceReferenceOrUow;
-            return reference.module();
-        }
-        else if( compositeOrServiceReferenceOrUow instanceof ImportedServiceReferenceInstance )
-        {
-            ImportedServiceReferenceInstance<?> importedServiceReference
-                = (ImportedServiceReferenceInstance<?>) compositeOrServiceReferenceOrUow;
-            return importedServiceReference.module();
-        }
-        throw new IllegalArgumentException( "Wrong type. Must be one of "
-                                            + Arrays.asList( TransientComposite.class, ValueComposite.class,
-                                                             ServiceComposite.class, ServiceReference.class,
-                                                             UnitOfWork.class ) );
-    }
-
-    @Override
-    public ModelDescriptor modelDescriptorFor( Object compositeOrServiceReference )
-    {
-        if( compositeOrServiceReference instanceof TransientComposite )
-        {
-            TransientComposite composite = (TransientComposite) compositeOrServiceReference;
-            return TransientInstance.compositeInstanceOf( composite ).descriptor();
-        }
-        else if( compositeOrServiceReference instanceof EntityComposite )
-        {
-            EntityComposite composite = (EntityComposite) compositeOrServiceReference;
-            return EntityInstance.entityInstanceOf( composite ).descriptor();
-        }
-        else if( compositeOrServiceReference instanceof ValueComposite )
-        {
-            ValueComposite composite = (ValueComposite) compositeOrServiceReference;
-            return ValueInstance.valueInstanceOf( composite ).descriptor();
-        }
-        else if( compositeOrServiceReference instanceof ServiceComposite )
-        {
-            ServiceComposite composite = (ServiceComposite) compositeOrServiceReference;
-            InvocationHandler handler = getInvocationHandler( composite );
-            if( handler instanceof ServiceInstance )
-            {
-                return ( (ServiceInstance) handler ).descriptor();
-            }
-            return ( (ServiceReferenceInstance.ServiceInvocationHandler) handler ).descriptor();
-        }
-        else if( compositeOrServiceReference instanceof ServiceReferenceInstance )
-        {
-            ServiceReferenceInstance<?> reference = (ServiceReferenceInstance<?>) compositeOrServiceReference;
-            return reference.serviceDescriptor();
-        }
-        else if( compositeOrServiceReference instanceof ImportedServiceReferenceInstance )
-        {
-            ImportedServiceReferenceInstance<?> importedServiceReference
-                = (ImportedServiceReferenceInstance<?>) compositeOrServiceReference;
-            return importedServiceReference.serviceDescriptor();
-        }
-        throw new IllegalArgumentException( "Wrong type. Must be one of "
-                                            + Arrays.asList( TransientComposite.class, ValueComposite.class,
-                                                             ServiceComposite.class, ServiceReference.class ) );
-    }
-
-    @Override
-    public CompositeDescriptor compositeDescriptorFor( Object compositeOrServiceReference )
-    {
-        return (CompositeDescriptor) modelDescriptorFor( compositeOrServiceReference );
-    }
-
-    // Descriptors
-
-    @Override
-    public TransientDescriptor transientDescriptorFor( Object transsient )
-    {
-        if( transsient instanceof TransientComposite )
-        {
-            TransientInstance transientInstance = compositeInstanceOf( (Composite) transsient );
-            return (TransientDescriptor) transientInstance.descriptor();
-        }
-        throw new IllegalArgumentException( "Wrong type. Must be subtype of " + TransientComposite.class );
-    }
-
-    @Override
-    public StateHolder stateOf( TransientComposite composite )
-    {
-        return TransientInstance.compositeInstanceOf( composite ).state();
-    }
-
-    @Override
-    public EntityDescriptor entityDescriptorFor( Object entity )
-    {
-        if( entity instanceof EntityComposite )
-        {
-            EntityInstance entityInstance = (EntityInstance) getInvocationHandler( entity );
-            return entityInstance.entityModel();
-        }
-        throw new IllegalArgumentException( "Wrong type. Must be subtype of " + EntityComposite.class );
-    }
-
-    @Override
-    public AssociationStateHolder stateOf( EntityComposite composite )
-    {
-        return EntityInstance.entityInstanceOf( composite ).state();
-    }
-
-    @Override
-    public ValueDescriptor valueDescriptorFor( Object value )
-    {
-        if( value instanceof ValueComposite )
-        {
-            ValueInstance valueInstance = ValueInstance.valueInstanceOf( (ValueComposite) value );
-            return valueInstance.descriptor();
-        }
-        throw new IllegalArgumentException( "Wrong type. Must be subtype of " + ValueComposite.class );
-    }
-
-    @Override
-    public AssociationStateHolder stateOf( ValueComposite composite )
-    {
-        return ValueInstance.valueInstanceOf( composite ).state();
-    }
-
-    @Override
-    public ServiceDescriptor serviceDescriptorFor( Object service )
-    {
-        if( service instanceof ServiceReferenceInstance )
-        {
-            ServiceReferenceInstance<?> ref = (ServiceReferenceInstance<?>) service;
-            return ref.serviceDescriptor();
-        }
-        if( service instanceof ServiceComposite )
-        {
-            ServiceComposite composite = (ServiceComposite) service;
-            return (ServiceDescriptor) ServiceInstance.serviceInstanceOf( composite ).descriptor();
-        }
-        throw new IllegalArgumentException( "Wrong type. Must be subtype of "
-                                            + ServiceComposite.class + " or " + ServiceReference.class );
-    }
-
-    @Override
-    public PropertyDescriptor propertyDescriptorFor( Property<?> property )
-    {
-        while( property instanceof PropertyWrapper )
-        {
-            property = ( (PropertyWrapper) property ).next();
-        }
-
-        return (PropertyDescriptor) ( (PropertyInstance<?>) property ).propertyInfo();
-    }
-
-    @Override
-    public AssociationDescriptor associationDescriptorFor( AbstractAssociation association )
-    {
-        while( association instanceof AssociationWrapper )
-        {
-            association = ( (AssociationWrapper) association ).next();
-        }
-
-        while( association instanceof ManyAssociationWrapper )
-        {
-            association = ( (ManyAssociationWrapper) association ).next();
-        }
-
-        while( association instanceof NamedAssociationWrapper )
-        {
-            association = ( (NamedAssociationWrapper) association ).next();
-        }
-
-        return (AssociationDescriptor) ( (AbstractAssociationInstance) association ).associationInfo();
-    }
-
-    // SPI
-    @Override
-    public EntityState entityStateOf( EntityComposite composite )
-    {
-        return EntityInstance.entityInstanceOf( composite ).entityState();
-    }
-
-    @Override
-    public EntityReference entityReferenceOf( Association assoc )
-    {
-        @SuppressWarnings( "unchecked" )
-        Property<EntityReference> associationState = ( (AssociationInstance) assoc ).getAssociationState();
-        return associationState.get();
-    }
-
-    @Override
-    public Iterable<EntityReference> entityReferenceOf( ManyAssociation assoc )
-    {
-        return ( (ManyAssociationInstance) assoc ).getManyAssociationState();
-    }
-
-    @Override
-    public Iterable<Map.Entry<String, EntityReference>> entityReferenceOf( NamedAssociation assoc )
-    {
-        return ( (NamedAssociationInstance) assoc ).getEntityReferences();
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivationDelegate.java b/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivationDelegate.java
deleted file mode 100644
index 86b1d2c..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivationDelegate.java
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.activation;
-
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.Set;
-import org.qi4j.api.activation.Activation;
-import org.qi4j.api.activation.ActivationEvent;
-import org.qi4j.api.activation.ActivationEventListener;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.activation.PassivationException;
-import org.qi4j.api.service.ServiceReference;
-
-import static org.qi4j.api.activation.ActivationEvent.EventType.ACTIVATED;
-import static org.qi4j.api.activation.ActivationEvent.EventType.ACTIVATING;
-import static org.qi4j.api.activation.ActivationEvent.EventType.PASSIVATED;
-import static org.qi4j.api.activation.ActivationEvent.EventType.PASSIVATING;
-
-/**
- * This class manage Activation of a target and propagates to children.
- */
-@SuppressWarnings( "raw" )
-public final class ActivationDelegate
-    extends ActivationEventListenerSupport
-{
-    private final Object target;
-    private final boolean fireEvents;
-    private ActivatorsInstance targetActivators = null;
-    private final LinkedList<Activation> activeChildren = new LinkedList<>();
-
-    /**
-     * Create a new ActivationDelegate that will fire events.
-     * @param target target of Activation
-     */
-    public ActivationDelegate( Object target )
-    {
-        this( target, true );
-    }
-
-    /**
-     * Create a new ActivationDelegate.
-     * @param target target of Activation
-     * @param fireEvents if {@link ActivationEvent}s should be fired
-     */
-    public ActivationDelegate( Object target, boolean fireEvents )
-    {
-        super();
-        this.target = target;
-        this.fireEvents = fireEvents;
-    }
-
-    public void activate( ActivatorsInstance targetActivators, Activation child )
-        throws Exception
-    {
-        activate( targetActivators, Collections.singleton( child ), null );
-    }
-
-    public void activate( ActivatorsInstance targetActivators, Activation child, Runnable callback )
-        throws Exception
-    {
-        activate( targetActivators, Collections.singleton( child ), callback );
-    }
-
-    public void activate( ActivatorsInstance targetActivators, Iterable<? extends Activation> children )
-        throws ActivationException
-    {
-        activate( targetActivators, children, null );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public void activate( ActivatorsInstance targetActivators, Iterable<? extends Activation> children, Runnable callback )
-        throws ActivationException
-    {
-        if( this.targetActivators != null )
-        {
-            throw new IllegalStateException( "Activation.activate() called multiple times "
-                                             + "or without calling passivate() first!" );
-        }
-
-        try
-        {
-            // Before Activation Events
-            if( fireEvents )
-            {
-                fireEvent( new ActivationEvent( target, ACTIVATING ) );
-            }
-
-            // Before Activation for Activators
-            targetActivators.beforeActivation( target instanceof ServiceReference
-                                               ? new PassiveServiceReference( (ServiceReference) target )
-                                               : target );
-
-            // Activation
-            for( Activation child : children )
-            {
-                if( !activeChildren.contains( child ) )
-                {
-                    child.activate();
-                }
-                activeChildren.addFirst( child );
-            }
-
-            // Internal Activation Callback
-            if( callback != null )
-            {
-                callback.run();
-            }
-
-            // After Activation
-            targetActivators.afterActivation( target );
-
-            // After Activation Events
-            if( fireEvents )
-            {
-                fireEvent( new ActivationEvent( target, ACTIVATED ) );
-            }
-
-            // Activated
-            this.targetActivators = targetActivators;
-        }
-        catch( Exception e )
-        {
-            // Passivate actives
-            try
-            {
-                passivate();
-            }
-            catch( PassivationException e1 )
-            {
-                ActivationException activationEx = new ActivationException( "Unable to Activate application.", e );
-                activationEx.addSuppressed( e1 );
-                throw activationEx;
-            }
-            if( e instanceof ActivationException )
-            {
-                throw ( (ActivationException) e );
-            }
-            throw new ActivationException( "Unable to Activate application.", e );
-        }
-    }
-
-    public void passivate()
-        throws PassivationException
-    {
-        passivate( (Runnable) null );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public void passivate( Runnable callback )
-        throws PassivationException
-    {
-        Set<Exception> exceptions = new LinkedHashSet<>();
-
-        // Before Passivation Events
-        if( fireEvents )
-        {
-            ActivationEvent event = new ActivationEvent( target, PASSIVATING );
-            for( ActivationEventListener listener : listeners )
-            {
-                try
-                {
-                    listener.onEvent( event );
-                }
-                catch( Exception ex )
-                {
-                    if( ex instanceof PassivationException )
-                    {
-                        exceptions.addAll( ( (PassivationException) ex ).causes() );
-                    }
-                    else
-                    {
-                        exceptions.add( ex );
-                    }
-                }
-            }
-        }
-
-        // Before Passivation for Activators
-        if( targetActivators != null )
-        {
-            try
-            {
-                targetActivators.beforePassivation( target );
-            }
-            catch( PassivationException ex )
-            {
-                exceptions.addAll( ex.causes() );
-            }
-            catch( Exception ex )
-            {
-                exceptions.add( ex );
-            }
-        }
-
-        // Passivation
-        while( !activeChildren.isEmpty() )
-        {
-            passivateOneChild( exceptions );
-        }
-
-        // Internal Passivation Callback
-        if( callback != null )
-        {
-            try
-            {
-                callback.run();
-            }
-            catch( Exception ex )
-            {
-                if( ex instanceof PassivationException )
-                {
-                    exceptions.addAll( ( (PassivationException) ex ).causes() );
-                }
-                else
-                {
-                    exceptions.add( ex );
-                }
-            }
-        }
-
-        // After Passivation for Activators
-        if( targetActivators != null )
-        {
-            try
-            {
-                targetActivators.afterPassivation( target instanceof ServiceReference
-                                                   ? new PassiveServiceReference( (ServiceReference) target )
-                                                   : target );
-            }
-            catch( PassivationException ex )
-            {
-                exceptions.addAll( ex.causes() );
-            }
-            catch( Exception ex )
-            {
-                exceptions.add( ex );
-            }
-        }
-        targetActivators = null;
-
-        // After Passivation Events
-        if( fireEvents )
-        {
-            ActivationEvent event = new ActivationEvent( target, PASSIVATED );
-            for( ActivationEventListener listener : listeners )
-            {
-                try
-                {
-                    listener.onEvent( event );
-                }
-                catch( Exception ex )
-                {
-                    if( ex instanceof PassivationException )
-                    {
-                        exceptions.addAll( ( (PassivationException) ex ).causes() );
-                    }
-                    else
-                    {
-                        exceptions.add( ex );
-                    }
-                }
-            }
-        }
-
-        // Error handling
-        if( exceptions.isEmpty() )
-        {
-            return;
-        }
-        throw new PassivationException( exceptions );
-    }
-
-    @SuppressWarnings( "TooBroadCatch" )
-    private void passivateOneChild( Set<Exception> exceptions )
-    {
-        Activation activeChild = activeChildren.removeFirst();
-        try
-        {
-            activeChild.passivate();
-        }
-        catch( PassivationException ex )
-        {
-            exceptions.addAll( ex.causes() );
-        }
-        catch( Exception ex )
-        {
-            exceptions.add( ex );
-        }
-    }
-
-    @SuppressWarnings( "raw" )
-    private static class PassiveServiceReference
-        implements ServiceReference
-    {
-
-        private final ServiceReference reference;
-
-        private PassiveServiceReference( ServiceReference reference )
-        {
-            this.reference = reference;
-        }
-
-        @Override
-        public String identity()
-        {
-            return reference.identity();
-        }
-
-        @Override
-        public Object get()
-        {
-            throw new IllegalStateException( "Service is passive, either activating and"
-                                             + " cannot be used yet or passivating and cannot be used anymore." );
-        }
-
-        @Override
-        public boolean isActive()
-        {
-            return false;
-        }
-
-        @Override
-        public boolean isAvailable()
-        {
-            return false;
-        }
-
-        @Override
-        public Iterable<Class<?>> types()
-        {
-            return reference.types();
-        }
-
-        @Override
-        public <T> T metaInfo( Class<T> infoType )
-        {
-            return reference.metaInfo( infoType );
-        }
-
-        @Override
-        public void registerActivationEventListener( ActivationEventListener listener )
-        {
-            reference.registerActivationEventListener( listener );
-        }
-
-        @Override
-        public void deregisterActivationEventListener( ActivationEventListener listener )
-        {
-            reference.deregisterActivationEventListener( listener );
-        }
-
-        @Override
-        public int hashCode()
-        {
-            return identity().hashCode();
-        }
-
-        @Override
-        public boolean equals( Object obj )
-        {
-            if( obj == null )
-            {
-                return false;
-            }
-            if( getClass() != obj.getClass() )
-            {
-                return false;
-            }
-            final ServiceReference other = (ServiceReference) obj;
-            return identity().equals( other.identity() );
-        }
-
-        @Override
-        public String toString()
-        {
-            return reference.toString();
-        }
-    }
-
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivationEventListenerSupport.java b/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivationEventListenerSupport.java
deleted file mode 100644
index 41c883d..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivationEventListenerSupport.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed 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.qi4j.runtime.activation;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.activation.ActivationEvent;
-import org.qi4j.api.activation.ActivationEventListener;
-import org.qi4j.api.activation.ActivationEventListenerRegistration;
-
-/**
- * Internal helper for managing registrations and firing events
- */
-/* package */ class ActivationEventListenerSupport
-    implements ActivationEventListenerRegistration, ActivationEventListener
-{
-    protected List<ActivationEventListener> listeners = new ArrayList<>();
-
-    @Override
-    public void registerActivationEventListener( ActivationEventListener listener )
-    {
-        List<ActivationEventListener> newListeners = new ArrayList<>();
-        newListeners.addAll( listeners );
-        newListeners.add( listener );
-        listeners = newListeners;
-    }
-
-    @Override
-    public void deregisterActivationEventListener( ActivationEventListener listener )
-    {
-        List<ActivationEventListener> newListeners = new ArrayList<>();
-        newListeners.addAll( listeners );
-        newListeners.remove( listener );
-        listeners = newListeners;
-    }
-
-    /* package */ void fireEvent( ActivationEvent event )
-        throws Exception
-    {
-        for( ActivationEventListener listener : listeners )
-        {
-            listener.onEvent( event );
-        }
-    }
-
-    @Override
-    public void onEvent( ActivationEvent event )
-        throws Exception
-    {
-        fireEvent( event );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivatorModel.java b/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivatorModel.java
deleted file mode 100644
index 823aace..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivatorModel.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.activation;
-
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.activation.ActivatorDescriptor;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.composite.ConstructorsModel;
-import org.qi4j.runtime.injection.InjectedFieldsModel;
-import org.qi4j.runtime.injection.InjectedMethodsModel;
-import org.qi4j.runtime.injection.InjectionContext;
-
-/**
- * Model for a single Activator.
- *
- * @param <ActivateeType> Type of the activation target
- */
-public class ActivatorModel<ActivateeType>
-    implements ActivatorDescriptor, VisitableHierarchy<Object, Object>
-{
-    private final Class<? extends Activator<ActivateeType>> activatorType;
-    private final ConstructorsModel constructorsModel;
-    private final InjectedFieldsModel injectedFieldsModel;
-    private final InjectedMethodsModel injectedMethodsModel;
-
-    public ActivatorModel( Class<? extends Activator<ActivateeType>> activatorType )
-    {
-        this.activatorType = activatorType;
-        this.constructorsModel = new ConstructorsModel( activatorType );
-        this.injectedFieldsModel = new InjectedFieldsModel( activatorType );
-        this.injectedMethodsModel = new InjectedMethodsModel( activatorType );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            if( constructorsModel.accept( visitor ) )
-            {
-                if( injectedFieldsModel.accept( visitor ) )
-                {
-                    injectedMethodsModel.accept( visitor );
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-
-    public Activator<ActivateeType> newInstance()
-    {
-        try
-        {
-            return activatorType.newInstance();
-        }
-        catch( InstantiationException | IllegalAccessException ex )
-        {
-            throw new ConstructionException( "Could not instantiate " + activatorType.getName(), ex );
-        }
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public Activator<ActivateeType> newInstance( InjectionContext injectionContext )
-    {
-        try
-        {
-            Activator<ActivateeType> instance = (Activator<ActivateeType>) constructorsModel.newInstance( injectionContext );
-            injectionContext = new InjectionContext( injectionContext.module(), injectionContext.uses(), instance );
-            inject( injectionContext, instance );
-            return instance;
-        }
-        catch( Exception ex )
-        {
-            throw new ConstructionException( "Could not instantiate " + activatorType.getName(), ex );
-        }
-    }
-
-    public void inject( InjectionContext injectionContext, Activator<ActivateeType> instance )
-    {
-        injectedFieldsModel.inject( injectionContext, instance );
-        injectedMethodsModel.inject( injectionContext, instance );
-    }
-
-    @Override
-    public String toString()
-    {
-        return activatorType.getName();
-    }
-
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivatorsInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivatorsInstance.java
deleted file mode 100644
index 2059e1e..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivatorsInstance.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.activation;
-
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.Set;
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.activation.PassivationException;
-import org.qi4j.functional.Iterables;
-
-/**
- * Instance of a Zest Activators of one Activation target. Contains ordered
- * Activators and roll the Activation on the target.
- *
- * @param <ActivateeType> Type of the activation target
- */
-public class ActivatorsInstance<ActivateeType>
-    implements Activator<ActivateeType>
-{
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public static final ActivatorsInstance EMPTY = new ActivatorsInstance( Collections.emptyList() );
-
-    private final Iterable<Activator<ActivateeType>> activators;
-
-    public ActivatorsInstance( Iterable<Activator<ActivateeType>> activators )
-    {
-        this.activators = activators;
-    }
-
-    @Override
-    public void beforeActivation( ActivateeType activating )
-        throws Exception
-    {
-        for( Activator<ActivateeType> activator : activators )
-        {
-            activator.beforeActivation( activating );
-        }
-    }
-
-    @Override
-    public void afterActivation( ActivateeType activated )
-        throws Exception
-    {
-        for( Activator<ActivateeType> activator : activators )
-        {
-            activator.afterActivation( activated );
-        }
-    }
-
-    @Override
-    public void beforePassivation( ActivateeType passivating )
-        throws Exception
-    {
-        Set<Exception> exceptions = new LinkedHashSet<>();
-        for( Activator<ActivateeType> activator : Iterables.reverse( activators ) )
-        {
-            try
-            {
-                activator.beforePassivation( passivating );
-            }
-            catch( Exception ex )
-            {
-                exceptions.add( ex );
-            }
-        }
-        if( !exceptions.isEmpty() )
-        {
-            throw new PassivationException( exceptions );
-        }
-    }
-
-    @Override
-    public void afterPassivation( ActivateeType passivated )
-        throws Exception
-    {
-        Set<Exception> exceptions = new LinkedHashSet<>();
-        for( Activator<ActivateeType> activator : Iterables.reverse( activators ) )
-        {
-            try
-            {
-                activator.afterPassivation( passivated );
-            }
-            catch( Exception ex )
-            {
-                exceptions.add( ex );
-            }
-        }
-        if( !exceptions.isEmpty() )
-        {
-            throw new PassivationException( exceptions );
-        }
-    }
-
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivatorsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivatorsModel.java
deleted file mode 100644
index 04fc728..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/activation/ActivatorsModel.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.activation;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.structure.Module;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.composite.UsesInstance;
-import org.qi4j.runtime.injection.InjectionContext;
-import org.qi4j.runtime.structure.ModuleInstance;
-
-/**
- * Activators Model.
- *
- * @param <ActivateeType> Type of the activation target
- */
-public class ActivatorsModel<ActivateeType>
-    implements VisitableHierarchy<Object, Object>
-{
-
-    private final List<ActivatorModel<ActivateeType>> activatorModels = new ArrayList<>();
-    private final Iterable<Class<? extends Activator<ActivateeType>>> activatorsClasses;
-
-    public ActivatorsModel( Iterable<Class<? extends Activator<ActivateeType>>> activatorsClasses )
-    {
-        this.activatorsClasses = activatorsClasses;
-        for( Class<? extends Activator<ActivateeType>> activatorClass : activatorsClasses )
-        {
-            activatorModels.add( new ActivatorModel<>( activatorClass ) );
-        }
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( ActivatorModel<ActivateeType> activatorModel : activatorModels )
-            {
-                if( !activatorModel.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-
-    public Iterable<ActivatorModel<ActivateeType>> models()
-    {
-        return activatorModels;
-    }
-
-    public Iterable<Activator<ActivateeType>> newInstances()
-        throws ActivationException
-    {
-        List<Activator<ActivateeType>> activators = new ArrayList<>();
-        for( ActivatorModel<ActivateeType> activatorModel : activatorModels )
-        {
-            activators.add( activatorModel.newInstance() );
-        }
-        return activators;
-    }
-
-    public Iterable<Activator<ActivateeType>> newInstances( Module module )
-        throws ActivationException
-    {
-        List<Activator<ActivateeType>> activators = new ArrayList<>();
-        for( ActivatorModel<ActivateeType> activatorModel : activatorModels )
-        {
-            InjectionContext injectionContext = new InjectionContext( (ModuleInstance) module, UsesInstance.EMPTY_USES );
-            activators.add( activatorModel.newInstance( injectionContext ) );
-        }
-        return activators;
-    }
-
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/AbstractAssociationInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/association/AbstractAssociationInstance.java
deleted file mode 100644
index 21d696a..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/association/AbstractAssociationInstance.java
+++ /dev/null
@@ -1,93 +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.qi4j.runtime.association;
-
-import java.lang.reflect.Type;
-import org.qi4j.api.association.AbstractAssociation;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.functional.Function2;
-
-/**
- * Implementation of AbstractAssociation. Includes helper methods for subclasses
- */
-public abstract class AbstractAssociationInstance<T>
-    implements AbstractAssociation
-{
-    protected AssociationInfo associationInfo;
-    private final Function2<EntityReference, Type, Object> entityFunction;
-
-    public AbstractAssociationInstance( AssociationInfo associationInfo,
-                                        Function2<EntityReference, Type, Object> entityFunction
-    )
-    {
-        this.associationInfo = associationInfo;
-        this.entityFunction = entityFunction;
-    }
-
-    public AssociationInfo associationInfo()
-    {
-        return associationInfo;
-    }
-
-    public void setAssociationInfo( AssociationInfo newInfo )
-    {
-        this.associationInfo = newInfo;
-    }
-
-    @SuppressWarnings( "unchecked" )
-    protected T getEntity( EntityReference entityId )
-    {
-        if( entityId == null )
-        {
-            return null;
-        }
-
-        return (T) entityFunction.map( entityId, associationInfo.type() );
-    }
-
-    protected EntityReference getEntityReference( Object composite )
-    {
-        if( composite == null )
-        {
-            return null;
-        }
-
-        return new EntityReference( ( (Identity) composite ).identity().get() );
-    }
-
-    protected void checkType( Object instance )
-    {
-
-        if( instance instanceof Identity || instance == null )
-        {
-            return;
-        }
-        throw new IllegalArgumentException( "Object must be a subtype of org.qi4j.api.identity.Identity: " + instance.getClass() );
-    }
-
-    protected void checkImmutable()
-        throws IllegalStateException
-    {
-        if( associationInfo.isImmutable() )
-        {
-            throw new IllegalStateException( "Association [" + associationInfo.qualifiedName() + "] is immutable." );
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationInfo.java b/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationInfo.java
deleted file mode 100644
index fd6695d..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationInfo.java
+++ /dev/null
@@ -1,36 +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.qi4j.runtime.association;
-
-import java.lang.reflect.Type;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.runtime.composite.ConstraintsCheck;
-
-/**
- * TODO
- */
-public interface AssociationInfo
-    extends ConstraintsCheck
-{
-    boolean isImmutable();
-
-    QualifiedName qualifiedName();
-
-    Type type();
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationInstance.java
deleted file mode 100644
index e42d8eb..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationInstance.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.association;
-
-import java.lang.reflect.Type;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationWrapper;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.property.Property;
-import org.qi4j.functional.Function2;
-
-/**
- * Implementation of Association to a single Entity.
- */
-public final class AssociationInstance<T>
-    extends AbstractAssociationInstance<T>
-    implements Association<T>
-{
-    private Property<EntityReference> associationState;
-
-    public AssociationInstance( AssociationInfo associationInfo,
-                                Function2<EntityReference, Type, Object> entityFunction,
-                                Property<EntityReference> associationState
-    )
-    {
-        super( associationInfo, entityFunction );
-        this.associationState = associationState;
-    }
-
-    // Association implementation
-    @Override
-    public T get()
-    {
-        return getEntity( associationState.get() );
-    }
-
-    @Override
-    public void set( T newValue )
-        throws IllegalArgumentException
-    {
-        checkImmutable();
-        checkType( newValue );
-
-        associationInfo.checkConstraints( newValue );
-
-        // Change association
-        associationState.set( EntityReference.create( (Identity) newValue ));
-    }
-
-    @Override
-    public EntityReference reference()
-    {
-        return associationState.get();
-    }
-
-    public Property<EntityReference> getAssociationState()
-    {
-        return associationState;
-    }
-
-    @Override
-    public String toString()
-    {
-        if( associationState.get() == null )
-        {
-            return "";
-        }
-        else
-        {
-            return associationState.get().toString();
-        }
-    }
-
-    @Override
-    public int hashCode()
-    {
-        int hash = associationInfo.hashCode() * 39; // Descriptor
-        if( associationState.get() != null )
-        {
-            hash = hash * 997 + associationState.get().hashCode(); // State
-        }
-        return hash;
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-        Association<?> that = (Association) o;
-        // Unwrap if needed
-        while( that instanceof AssociationWrapper )
-        {
-            that = ( (AssociationWrapper) that ).next();
-        }
-        // Descriptor equality
-        AssociationInstance<?> thatInstance = (AssociationInstance) that;
-        AssociationDescriptor thatDescriptor = (AssociationDescriptor) thatInstance.associationInfo();
-        if( !associationInfo.equals( thatDescriptor ) )
-        {
-            return false;
-        }
-        // State equality
-        if( associationState.get() != null
-            ? !associationState.get().equals( thatInstance.associationState.get() )
-            : thatInstance.associationState.get() != null )
-        {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationModel.java b/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationModel.java
deleted file mode 100644
index d1d5f36..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationModel.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.association;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.util.List;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.GenericAssociationInfo;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.constraint.ConstraintViolation;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.entity.Aggregated;
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.util.Classes;
-import org.qi4j.bootstrap.BindingException;
-import org.qi4j.functional.Visitable;
-import org.qi4j.functional.Visitor;
-import org.qi4j.runtime.composite.ValueConstraintsInstance;
-import org.qi4j.runtime.model.Binder;
-import org.qi4j.runtime.model.Resolution;
-
-import static org.qi4j.functional.Iterables.empty;
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Model for an Association.
- *
- * <p>Equality is based on the Association accessor object (associated type and name), not on the QualifiedName.</p>
- */
-public final class AssociationModel
-    implements AssociationDescriptor, AssociationInfo, Binder, Visitable<AssociationModel>
-{
-    private MetaInfo metaInfo;
-    private Type type;
-    private AccessibleObject accessor;
-    private QualifiedName qualifiedName;
-    private ValueConstraintsInstance constraints;
-    private ValueConstraintsInstance associationConstraints;
-    private boolean queryable;
-    private boolean immutable;
-    private boolean aggregated;
-    private AssociationInfo builderInfo;
-
-    public AssociationModel( AccessibleObject accessor,
-                             ValueConstraintsInstance valueConstraintsInstance,
-                             ValueConstraintsInstance associationConstraintsInstance,
-                             MetaInfo metaInfo
-    )
-    {
-        this.metaInfo = metaInfo;
-        this.constraints = valueConstraintsInstance;
-        this.associationConstraints = associationConstraintsInstance;
-        this.accessor = accessor;
-        initialize();
-    }
-
-    private void initialize()
-    {
-        this.type = GenericAssociationInfo.associationTypeOf( accessor );
-        this.qualifiedName = QualifiedName.fromAccessor( accessor );
-        this.immutable = metaInfo.get( Immutable.class ) != null;
-        this.aggregated = metaInfo.get( Aggregated.class ) != null;
-
-        final Queryable queryable = accessor.getAnnotation( Queryable.class );
-        this.queryable = queryable == null || queryable.value();
-    }
-
-    @Override
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return metaInfo.get( infoType );
-    }
-
-    @Override
-    public QualifiedName qualifiedName()
-    {
-        return qualifiedName;
-    }
-
-    @Override
-    public Type type()
-    {
-        return type;
-    }
-
-    @Override
-    public boolean isImmutable()
-    {
-        return immutable;
-    }
-
-    @Override
-    public boolean isAggregated()
-    {
-        return aggregated;
-    }
-
-    @Override
-    public AccessibleObject accessor()
-    {
-        return accessor;
-    }
-
-    @Override
-    public boolean queryable()
-    {
-        return queryable;
-    }
-
-    public AssociationInfo getBuilderInfo()
-    {
-        return builderInfo;
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( Visitor<? super AssociationModel, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        return visitor.visit( this );
-    }
-
-    @Override
-    public void checkConstraints( Object value )
-        throws ConstraintViolationException
-    {
-        if( constraints != null )
-        {
-            List<ConstraintViolation> violations = constraints.checkConstraints( value );
-            if( !violations.isEmpty() )
-            {
-                Iterable<Class<?>> empty = empty();
-                throw new ConstraintViolationException( "", empty, (Member) accessor, violations );
-            }
-        }
-    }
-
-    public void checkAssociationConstraints( Association<?> association )
-        throws ConstraintViolationException
-    {
-        if( associationConstraints != null )
-        {
-            List<ConstraintViolation> violations = associationConstraints.checkConstraints( association );
-            if( !violations.isEmpty() )
-            {
-                throw new ConstraintViolationException( (Composite) association.get(), (Member) accessor, violations );
-            }
-        }
-    }
-
-    @Override
-    public void bind( Resolution resolution )
-        throws BindingException
-    {
-        builderInfo = new AssociationInfo()
-        {
-            @Override
-            public boolean isImmutable()
-            {
-                return false;
-            }
-
-            @Override
-            public QualifiedName qualifiedName()
-            {
-                return qualifiedName;
-            }
-
-            @Override
-            public Type type()
-            {
-                return type;
-            }
-
-            @Override
-            public void checkConstraints( Object value )
-                throws ConstraintViolationException
-            {
-                AssociationModel.this.checkConstraints( value );
-            }
-        };
-
-        if( type instanceof TypeVariable )
-        {
-
-            Class mainType = first( resolution.model().types() );
-            type = Classes.resolveTypeVariable( (TypeVariable) type, ( (Member) accessor ).getDeclaringClass(), mainType );
-        }
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-
-        AssociationModel that = (AssociationModel) o;
-
-        if( !accessor.equals( that.accessor ) )
-        {
-            return false;
-        }
-
-        return true;
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return accessor.hashCode();
-    }
-
-    @Override
-    public String toString()
-    {
-        if( accessor instanceof Field )
-        {
-            return ( (Field) accessor ).toGenericString();
-        }
-        else
-        {
-            return ( (Method) accessor ).toGenericString();
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationsModel.java
deleted file mode 100644
index 310632d..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/association/AssociationsModel.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.association;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Member;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-
-/**
- * Model for Associations.
- */
-public final class AssociationsModel
-    implements VisitableHierarchy<AssociationsModel, AssociationModel>
-{
-    private final Map<AccessibleObject, AssociationModel> mapAccessorAssociationModel = new LinkedHashMap<>();
-
-    public AssociationsModel()
-    {
-    }
-
-    public Iterable<AssociationModel> associations()
-    {
-        return mapAccessorAssociationModel.values();
-    }
-
-    public void addAssociation( AssociationModel associationModel )
-    {
-        mapAccessorAssociationModel.put( associationModel.accessor(), associationModel );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super AssociationsModel, ? super AssociationModel, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( AssociationModel associationModel : mapAccessorAssociationModel.values() )
-            {
-                if( !associationModel.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-
-    public AssociationModel getAssociation( AccessibleObject accessor )
-        throws IllegalArgumentException
-    {
-        AssociationModel associationModel = mapAccessorAssociationModel.get( accessor );
-        if( associationModel == null )
-        {
-            throw new IllegalArgumentException( "No association found with name:" + ( (Member) accessor ).getName() );
-        }
-        return associationModel;
-    }
-
-    public AssociationDescriptor getAssociationByName( String name )
-        throws IllegalArgumentException
-    {
-        for( AssociationModel associationModel : mapAccessorAssociationModel.values() )
-        {
-            if( associationModel.qualifiedName().name().equals( name ) )
-            {
-                return associationModel;
-            }
-        }
-        throw new IllegalArgumentException( "No association found with name:" + name );
-    }
-
-    public AssociationDescriptor getAssociationByQualifiedName( QualifiedName name )
-        throws IllegalArgumentException
-    {
-        for( AssociationModel associationModel : mapAccessorAssociationModel.values() )
-        {
-            if( associationModel.qualifiedName().equals( name ) )
-            {
-                return associationModel;
-            }
-        }
-        throw new IllegalArgumentException( "No association found with qualified name:" + name );
-    }
-
-    public void checkConstraints( AssociationStateHolder state )
-    {
-        for( AssociationModel associationModel : mapAccessorAssociationModel.values() )
-        {
-            Association<Object> association = state.<Object>associationFor( associationModel.accessor() );
-            associationModel.checkAssociationConstraints( association );
-            associationModel.checkConstraints( association.get() );
-        }
-    }
-
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationInstance.java
deleted file mode 100644
index 5c8b4b8..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationInstance.java
+++ /dev/null
@@ -1,225 +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.qi4j.runtime.association;
-
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.ManyAssociationWrapper;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.functional.Function2;
-import org.qi4j.functional.Iterables;
-import org.qi4j.spi.entity.ManyAssociationState;
-
-/**
- * JAVADOC
- */
-public class ManyAssociationInstance<T>
-    extends AbstractAssociationInstance<T>
-    implements ManyAssociation<T>
-{
-    private ManyAssociationState manyAssociationState;
-
-    public ManyAssociationInstance( AssociationInfo associationInfo,
-                                    Function2<EntityReference, Type, Object> associationFunction,
-                                    ManyAssociationState manyAssociationState
-    )
-    {
-        super( associationInfo, associationFunction );
-        this.manyAssociationState = manyAssociationState;
-    }
-
-    @Override
-    public int count()
-    {
-        return manyAssociationState.count();
-    }
-
-    @Override
-    public boolean contains( T entity )
-    {
-        return manyAssociationState.contains( getEntityReference( entity ) );
-    }
-
-    @Override
-    public boolean add( int i, T entity )
-    {
-        NullArgumentException.validateNotNull( "entity", entity );
-        checkImmutable();
-        checkType( entity );
-        associationInfo.checkConstraints( entity );
-        return manyAssociationState.add( i, new EntityReference( ( (Identity) entity ).identity().get() ) );
-    }
-
-    @Override
-    public boolean add( T entity )
-    {
-        return add( manyAssociationState.count(), entity );
-    }
-
-    @Override
-    public boolean remove( T entity )
-    {
-        NullArgumentException.validateNotNull( "entity", entity );
-        checkImmutable();
-        checkType( entity );
-
-        return manyAssociationState.remove( new EntityReference( ( (Identity) entity ).identity().get() ) );
-    }
-
-    @Override
-    public T get( int i )
-    {
-        return getEntity( manyAssociationState.get( i ) );
-    }
-
-    @Override
-    public List<T> toList()
-    {
-        ArrayList<T> list = new ArrayList<>();
-        for( EntityReference entityReference : manyAssociationState )
-        {
-            list.add( getEntity( entityReference ) );
-        }
-
-        return list;
-    }
-
-    @Override
-    public Set<T> toSet()
-    {
-        Set<T> set = new HashSet<>();
-        for( EntityReference entityReference : manyAssociationState )
-        {
-            set.add( getEntity( entityReference ) );
-        }
-
-        return set;
-    }
-
-    @Override
-    public Iterable<EntityReference> references()
-    {
-        return Iterables.toList( manyAssociationState );
-    }
-
-    @Override
-    public String toString()
-    {
-        return manyAssociationState.toString();
-    }
-
-    @Override
-    public Iterator<T> iterator()
-    {
-        return new ManyAssociationIterator( manyAssociationState.iterator() );
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-        ManyAssociation<?> that = (ManyAssociation) o;
-        // Unwrap if needed
-        while( that instanceof ManyAssociationWrapper )
-        {
-            that = ( (ManyAssociationWrapper) that ).next();
-        }
-        // Descriptor equality
-        ManyAssociationInstance<?> thatInstance = (ManyAssociationInstance) that;
-        AssociationDescriptor thatDescriptor = (AssociationDescriptor) thatInstance.associationInfo();
-        if( !associationInfo.equals( thatDescriptor ) )
-        {
-            return false;
-        }
-        // State equality
-        if( manyAssociationState.count() != thatInstance.manyAssociationState.count() )
-        {
-            return false;
-        }
-        for( EntityReference ref : manyAssociationState )
-        {
-            if( !thatInstance.manyAssociationState.contains( ref ) )
-            {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public int hashCode()
-    {
-        int hash = associationInfo.hashCode() * 31; // Descriptor
-        for( EntityReference ref : manyAssociationState )
-        {
-            hash += ref.hashCode() * 7; // State
-        }
-        return hash;
-    }
-
-    public ManyAssociationState getManyAssociationState()
-    {
-        return manyAssociationState;
-    }
-
-    protected class ManyAssociationIterator
-        implements Iterator<T>
-    {
-        private final Iterator<EntityReference> idIterator;
-
-        public ManyAssociationIterator( Iterator<EntityReference> idIterator )
-        {
-            this.idIterator = idIterator;
-        }
-
-        @Override
-        public boolean hasNext()
-        {
-            return idIterator.hasNext();
-        }
-
-        @Override
-        public T next()
-        {
-            return getEntity( idIterator.next() );
-        }
-
-        @Override
-        public void remove()
-        {
-            checkImmutable();
-            idIterator.remove();
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationModel.java b/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationModel.java
deleted file mode 100644
index 3cc5d81..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationModel.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.association;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.util.List;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.GenericAssociationInfo;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.constraint.ConstraintViolation;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.entity.Aggregated;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.util.Classes;
-import org.qi4j.bootstrap.BindingException;
-import org.qi4j.functional.Function2;
-import org.qi4j.functional.Visitable;
-import org.qi4j.functional.Visitor;
-import org.qi4j.runtime.composite.ValueConstraintsInstance;
-import org.qi4j.runtime.model.Binder;
-import org.qi4j.runtime.model.Resolution;
-import org.qi4j.runtime.structure.ModuleUnitOfWork;
-import org.qi4j.runtime.unitofwork.BuilderEntityState;
-import org.qi4j.spi.entity.EntityState;
-
-import static org.qi4j.functional.Iterables.empty;
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Model for a ManyAssociation.
- *
- * <p>Equality is based on the ManyAssociation accessor object (associated type and name), not on the QualifiedName.</p>
- */
-public final class ManyAssociationModel
-    implements AssociationDescriptor, AssociationInfo, Binder, Visitable<ManyAssociationModel>
-{
-    private final ValueConstraintsInstance associationConstraints;
-    private final MetaInfo metaInfo;
-    private Type type;
-    private final AccessibleObject accessor;
-    private QualifiedName qualifiedName;
-    private final ValueConstraintsInstance constraints;
-    private boolean queryable;
-    private boolean immutable;
-    private boolean aggregated;
-    private AssociationInfo builderInfo;
-
-    public ManyAssociationModel( AccessibleObject accessor,
-                                 ValueConstraintsInstance valueConstraintsInstance,
-                                 ValueConstraintsInstance associationConstraintsInstance,
-                                 MetaInfo metaInfo
-    )
-    {
-        this.metaInfo = metaInfo;
-        this.constraints = valueConstraintsInstance;
-        this.associationConstraints = associationConstraintsInstance;
-        this.accessor = accessor;
-        initialize();
-    }
-
-    private void initialize()
-    {
-        this.type = GenericAssociationInfo.associationTypeOf( accessor );
-        this.qualifiedName = QualifiedName.fromAccessor( accessor );
-        this.immutable = metaInfo.get( Immutable.class ) != null;
-        this.aggregated = metaInfo.get( Aggregated.class ) != null;
-
-        final Queryable queryable = accessor.getAnnotation( Queryable.class );
-        this.queryable = queryable == null || queryable.value();
-    }
-
-    @Override
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return metaInfo.get( infoType );
-    }
-
-    @Override
-    public QualifiedName qualifiedName()
-    {
-        return qualifiedName;
-    }
-
-    @Override
-    public Type type()
-    {
-        return type;
-    }
-
-    @Override
-    public boolean isImmutable()
-    {
-        return immutable;
-    }
-
-    @Override
-    public boolean isAggregated()
-    {
-        return aggregated;
-    }
-
-    @Override
-    public AccessibleObject accessor()
-    {
-        return accessor;
-    }
-
-    @Override
-    public boolean queryable()
-    {
-        return queryable;
-    }
-
-    public AssociationInfo getBuilderInfo()
-    {
-        return builderInfo;
-    }
-
-    public <T> ManyAssociation<T> newInstance( final ModuleUnitOfWork uow, EntityState state )
-    {
-        return new ManyAssociationInstance<>( state instanceof BuilderEntityState ? builderInfo : this, new Function2<EntityReference, Type, Object>()
-        {
-            @Override
-            public Object map( EntityReference entityReference, Type type )
-            {
-                return uow.get( Classes.RAW_CLASS.map( type ), entityReference.identity() );
-            }
-        }, state.manyAssociationValueOf( qualifiedName ) );
-    }
-
-    @Override
-    public void checkConstraints( Object composite )
-        throws ConstraintViolationException
-    {
-        if( constraints != null )
-        {
-            List<ConstraintViolation> violations = constraints.checkConstraints( composite );
-            if( !violations.isEmpty() )
-            {
-                Iterable<Class<?>> empty = empty();
-                throw new ConstraintViolationException( "", empty, (Member) accessor, violations );
-            }
-        }
-    }
-
-    public void checkAssociationConstraints( ManyAssociation manyAssociation )
-        throws ConstraintViolationException
-    {
-        if( associationConstraints != null )
-        {
-            List<ConstraintViolation> violations = associationConstraints.checkConstraints( manyAssociation );
-            if( !violations.isEmpty() )
-            {
-                Iterable<Class<?>> empty = empty();
-                throw new ConstraintViolationException( "", empty, (Member) accessor, violations );
-            }
-        }
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( Visitor<? super ManyAssociationModel, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        return visitor.visit( this );
-    }
-
-    @Override
-    public void bind( Resolution resolution )
-        throws BindingException
-    {
-        builderInfo = new AssociationInfo()
-        {
-            @Override
-            public boolean isImmutable()
-            {
-                return false;
-            }
-
-            @Override
-            public QualifiedName qualifiedName()
-            {
-                return qualifiedName;
-            }
-
-            @Override
-            public Type type()
-            {
-                return type;
-            }
-
-            @Override
-            public void checkConstraints( Object value )
-                throws ConstraintViolationException
-            {
-                ManyAssociationModel.this.checkConstraints( value );
-            }
-        };
-
-        if( type instanceof TypeVariable )
-        {
-            Class mainType = first( resolution.model().types() );
-            type = Classes.resolveTypeVariable( (TypeVariable) type, ( (Member) accessor ).getDeclaringClass(), mainType );
-        }
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-
-        ManyAssociationModel that = (ManyAssociationModel) o;
-
-        return accessor.equals( that.accessor );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return accessor.hashCode();
-    }
-
-    @Override
-    public String toString()
-    {
-        if( accessor instanceof Field )
-        {
-            return ( (Field) accessor ).toGenericString();
-        }
-        else
-        {
-            return ( (Method) accessor ).toGenericString();
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationsModel.java
deleted file mode 100644
index 40c5653..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationsModel.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.association;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Member;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.structure.ModuleUnitOfWork;
-import org.qi4j.runtime.value.ValueStateInstance;
-import org.qi4j.spi.entity.EntityState;
-
-/**
- * Model for ManyAssociations.
- */
-public final class ManyAssociationsModel
-    implements VisitableHierarchy<ManyAssociationsModel, ManyAssociationModel>
-{
-    private final Map<AccessibleObject, ManyAssociationModel> mapAccessorAssociationModel = new LinkedHashMap<>();
-
-    public ManyAssociationsModel()
-    {
-    }
-
-    public Iterable<ManyAssociationModel> manyAssociations()
-    {
-        return mapAccessorAssociationModel.values();
-    }
-
-    public void addManyAssociation( ManyAssociationModel model )
-    {
-        mapAccessorAssociationModel.put( model.accessor(), model );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super ManyAssociationsModel, ? super ManyAssociationModel, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( ManyAssociationModel associationModel : mapAccessorAssociationModel.values() )
-            {
-                if( !associationModel.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-
-    public <T> ManyAssociation<T> newInstance( AccessibleObject accessor,
-                                               EntityState entityState,
-                                               ModuleUnitOfWork uow )
-    {
-        return mapAccessorAssociationModel.get( accessor ).newInstance( uow, entityState );
-    }
-
-    public ManyAssociationModel getManyAssociation( AccessibleObject accessor )
-        throws IllegalArgumentException
-    {
-        ManyAssociationModel manyAssociationModel = mapAccessorAssociationModel.get( accessor );
-        if( manyAssociationModel == null )
-        {
-            throw new IllegalArgumentException( "No many-association found with name:" + ( (Member) accessor ).getName() );
-        }
-        return manyAssociationModel;
-    }
-
-    public AssociationDescriptor getManyAssociationByName( String name )
-        throws IllegalArgumentException
-    {
-        for( ManyAssociationModel associationModel : mapAccessorAssociationModel.values() )
-        {
-            if( associationModel.qualifiedName().name().equals( name ) )
-            {
-                return associationModel;
-            }
-        }
-        throw new IllegalArgumentException( "No many-association found with name:" + name );
-    }
-
-    public AssociationDescriptor getManyAssociationByQualifiedName( QualifiedName name )
-        throws IllegalArgumentException
-    {
-        for( ManyAssociationModel associationModel : mapAccessorAssociationModel.values() )
-        {
-            if( associationModel.qualifiedName().equals( name ) )
-            {
-                return associationModel;
-            }
-        }
-        throw new IllegalArgumentException( "No many-association found with qualified name:" + name );
-    }
-
-    public void checkConstraints( ValueStateInstance state )
-    {
-        for( ManyAssociationModel manyAssociationModel : mapAccessorAssociationModel.values() )
-        {
-            manyAssociationModel.checkAssociationConstraints( state.manyAssociationFor( manyAssociationModel.accessor() ) );
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationInstance.java
deleted file mode 100644
index c38ef1a..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationInstance.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (c) 2011-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.association;
-
-import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.ManyAssociationWrapper;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.association.NamedAssociationWrapper;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Function2;
-import org.qi4j.functional.Iterables;
-import org.qi4j.spi.entity.NamedAssociationState;
-
-import static org.qi4j.functional.Iterables.map;
-
-public class NamedAssociationInstance<T>
-    extends AbstractAssociationInstance<T>
-    implements NamedAssociation<T>
-{
-
-    private final NamedAssociationState namedAssociationState;
-
-    public NamedAssociationInstance( AssociationInfo associationInfo,
-                                     Function2<EntityReference, Type, Object> associationFunction,
-                                     NamedAssociationState namedAssociationState
-    )
-    {
-        super( associationInfo, associationFunction );
-        this.namedAssociationState = namedAssociationState;
-    }
-
-    @Override
-    public Iterator<String> iterator()
-    {
-        return namedAssociationState.iterator();
-    }
-
-    @Override
-    public int count()
-    {
-        return namedAssociationState.count();
-    }
-
-    @Override
-    public boolean containsName( String name )
-    {
-        return namedAssociationState.containsName( name );
-    }
-
-    @Override
-    public boolean put( String name, T entity )
-    {
-        NullArgumentException.validateNotNull( "entity", entity );
-        checkImmutable();
-        checkType( entity );
-        associationInfo.checkConstraints( entity );
-        return namedAssociationState.put( name, new EntityReference( ( (Identity) entity ).identity().get() ) );
-    }
-
-    @Override
-    public boolean remove( String name )
-    {
-        checkImmutable();
-        return namedAssociationState.remove( name );
-    }
-
-    @Override
-    public T get( String name )
-    {
-        return getEntity( namedAssociationState.get( name ) );
-    }
-
-    @Override
-    public String nameOf( T entity )
-    {
-        return namedAssociationState.nameOf( getEntityReference( entity ) );
-    }
-
-    @Override
-    public Map<String, T> toMap()
-    {
-        Map<String, T> map = new HashMap<>();
-        for( String name : namedAssociationState )
-        {
-            map.put( name, getEntity( namedAssociationState.get( name ) ) );
-        }
-        return map;
-    }
-
-    @Override
-    public Iterable<EntityReference> references()
-    {
-        return map( new Function<String, EntityReference>()
-        {
-            @Override
-            public EntityReference map( String name )
-            {
-                return namedAssociationState.get( name );
-            }
-        }, namedAssociationState );
-    }
-
-    @Override
-    public EntityReference referenceOf( String name )
-    {
-        return namedAssociationState.get( name );
-    }
-
-    public Iterable<Map.Entry<String, EntityReference>> getEntityReferences()
-    {
-        return map( new Function<String, Map.Entry<String, EntityReference>>()
-        {
-            @Override
-            public Map.Entry<String, EntityReference> map( final String key )
-            {
-                final EntityReference value = namedAssociationState.get( key );
-                return new Map.Entry<String, EntityReference>()
-                {
-                    @Override
-                    public String getKey()
-                    {
-                        return key;
-                    }
-
-                    @Override
-                    public EntityReference getValue()
-                    {
-                        return value;
-                    }
-
-                    @Override
-                    public EntityReference setValue( EntityReference value )
-                    {
-                        throw new UnsupportedOperationException( "Immutable Map" );
-                    }
-
-                    @Override
-                    public boolean equals( Object o )
-                    {
-                        if( o instanceof Map.Entry )
-                        {
-                            Map.Entry other = (Map.Entry) o;
-                            return key.equals( other.getKey() );
-                        }
-                        return false;
-                    }
-
-                    @Override
-                    public int hashCode()
-                    {
-                        return 997 * key.hashCode() + 981813497;
-                    }
-                };
-            }
-        }, namedAssociationState );
-    }
-
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-        NamedAssociation<?> that = (NamedAssociation) o;
-        // Unwrap if needed
-        while( that instanceof NamedAssociationWrapper )
-        {
-            that = ( (NamedAssociationWrapper) that ).next();
-        }
-        // Descriptor equality
-        NamedAssociationInstance<?> thatInstance = (NamedAssociationInstance) that;
-        AssociationDescriptor thatDescriptor = (AssociationDescriptor) thatInstance.associationInfo();
-        if( !associationInfo.equals( thatDescriptor ) )
-        {
-            return false;
-        }
-        // State equality
-        if( namedAssociationState.count() != thatInstance.namedAssociationState.count() )
-        {
-            return false;
-        }
-        for( String name : namedAssociationState )
-        {
-            if( !thatInstance.namedAssociationState.containsName( name ) )
-            {
-                return false;
-            }
-            EntityReference thisReference = namedAssociationState.get( name );
-            EntityReference thatReference = thatInstance.namedAssociationState.get( name );
-            if( !thisReference.equals( thatReference ) )
-            {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public int hashCode()
-    {
-        int hash = associationInfo.hashCode() * 31; // Descriptor
-        for( String name : namedAssociationState )
-        {
-            hash += name.hashCode();
-            hash += namedAssociationState.get( name ).hashCode() * 7; // State
-        }
-        return hash;
-    }
-
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationModel.java b/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationModel.java
deleted file mode 100644
index 7c144d0..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationModel.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (c) 2011-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.association;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.util.List;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.GenericAssociationInfo;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.constraint.ConstraintViolation;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.entity.Aggregated;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.util.Classes;
-import org.qi4j.bootstrap.BindingException;
-import org.qi4j.functional.Function2;
-import org.qi4j.functional.Visitable;
-import org.qi4j.functional.Visitor;
-import org.qi4j.runtime.composite.ValueConstraintsInstance;
-import org.qi4j.runtime.model.Binder;
-import org.qi4j.runtime.model.Resolution;
-import org.qi4j.runtime.structure.ModuleUnitOfWork;
-import org.qi4j.runtime.unitofwork.BuilderEntityState;
-import org.qi4j.spi.entity.EntityState;
-
-import static org.qi4j.functional.Iterables.empty;
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Model for a NamedAssociation.
- *
- * <p>Equality is based on the NamedAssociation accessor object (associated type and name), not on the QualifiedName.</p>
- */
-public final class NamedAssociationModel
-    implements AssociationDescriptor, AssociationInfo, Binder, Visitable<NamedAssociationModel>
-{
-    private final ValueConstraintsInstance associationConstraints;
-    private final MetaInfo metaInfo;
-    private Type type;
-    private final AccessibleObject accessor;
-    private QualifiedName qualifiedName;
-    private final ValueConstraintsInstance constraints;
-    private boolean queryable;
-    private boolean immutable;
-    private boolean aggregated;
-    private AssociationInfo builderInfo;
-
-    public NamedAssociationModel( AccessibleObject accessor,
-                                  ValueConstraintsInstance valueConstraintsInstance,
-                                  ValueConstraintsInstance associationConstraintsInstance,
-                                  MetaInfo metaInfo
-    )
-    {
-        this.metaInfo = metaInfo;
-        this.constraints = valueConstraintsInstance;
-        this.associationConstraints = associationConstraintsInstance;
-        this.accessor = accessor;
-        initialize();
-    }
-
-    private void initialize()
-    {
-        this.type = GenericAssociationInfo.associationTypeOf( accessor );
-        this.qualifiedName = QualifiedName.fromAccessor( accessor );
-        this.immutable = metaInfo.get( Immutable.class ) != null;
-        this.aggregated = metaInfo.get( Aggregated.class ) != null;
-
-        final Queryable queryable = accessor.getAnnotation( Queryable.class );
-        this.queryable = queryable == null || queryable.value();
-    }
-
-    @Override
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return metaInfo.get( infoType );
-    }
-
-    @Override
-    public QualifiedName qualifiedName()
-    {
-        return qualifiedName;
-    }
-
-    @Override
-    public Type type()
-    {
-        return type;
-    }
-
-    @Override
-    public boolean isImmutable()
-    {
-        return immutable;
-    }
-
-    @Override
-    public boolean isAggregated()
-    {
-        return aggregated;
-    }
-
-    @Override
-    public AccessibleObject accessor()
-    {
-        return accessor;
-    }
-
-    @Override
-    public boolean queryable()
-    {
-        return queryable;
-    }
-
-    public AssociationInfo getBuilderInfo()
-    {
-        return builderInfo;
-    }
-
-    public <T> NamedAssociation<T> newInstance( final ModuleUnitOfWork uow, EntityState state )
-    {
-        return new NamedAssociationInstance<>( state instanceof BuilderEntityState ? builderInfo : this, new Function2<EntityReference, Type, Object>()
-        {
-            @Override
-            public Object map( EntityReference entityReference, Type type )
-            {
-                return uow.get( Classes.RAW_CLASS.map( type ), entityReference.identity() );
-            }
-        }, state.namedAssociationValueOf( qualifiedName ) );
-    }
-
-    @Override
-    public void checkConstraints( Object composite )
-        throws ConstraintViolationException
-    {
-        if( constraints != null )
-        {
-            List<ConstraintViolation> violations = constraints.checkConstraints( composite );
-            if( !violations.isEmpty() )
-            {
-                Iterable<Class<?>> empty = empty();
-                throw new ConstraintViolationException( "", empty, (Member) accessor, violations );
-            }
-        }
-    }
-
-    public void checkAssociationConstraints( NamedAssociation association )
-        throws ConstraintViolationException
-    {
-        if( associationConstraints != null )
-        {
-            List<ConstraintViolation> violations = associationConstraints.checkConstraints( association );
-            if( !violations.isEmpty() )
-            {
-                Iterable<Class<?>> empty = empty();
-                throw new ConstraintViolationException( "", empty, (Member) accessor, violations );
-            }
-        }
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( Visitor<? super NamedAssociationModel, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        return visitor.visit( this );
-    }
-
-    @Override
-    public void bind( Resolution resolution )
-        throws BindingException
-    {
-        builderInfo = new AssociationInfo()
-        {
-            @Override
-            public boolean isImmutable()
-            {
-                return false;
-            }
-
-            @Override
-            public QualifiedName qualifiedName()
-            {
-                return qualifiedName;
-            }
-
-            @Override
-            public Type type()
-            {
-                return type;
-            }
-
-            @Override
-            public void checkConstraints( Object value )
-                throws ConstraintViolationException
-            {
-                NamedAssociationModel.this.checkConstraints( value );
-            }
-        };
-
-        if( type instanceof TypeVariable )
-        {
-            Class mainType = first( resolution.model().types() );
-            type = Classes.resolveTypeVariable( (TypeVariable) type, ( (Member) accessor ).getDeclaringClass(), mainType );
-        }
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-
-        NamedAssociationModel that = (NamedAssociationModel) o;
-
-        return accessor.equals( that.accessor );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return accessor.hashCode();
-    }
-
-    @Override
-    public String toString()
-    {
-        if( accessor instanceof Field )
-        {
-            return ( (Field) accessor ).toGenericString();
-        }
-        else
-        {
-            return ( (Method) accessor ).toGenericString();
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationsModel.java
deleted file mode 100644
index 4f3fac5..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationsModel.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2011-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.association;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Member;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.structure.ModuleUnitOfWork;
-import org.qi4j.runtime.value.ValueStateInstance;
-import org.qi4j.spi.entity.EntityState;
-
-/**
- * Model for NamedAssociations.
- */
-public final class NamedAssociationsModel
-    implements VisitableHierarchy<NamedAssociationsModel, NamedAssociationModel>
-{
-    private final Map<AccessibleObject, NamedAssociationModel> mapAccessorAssociationModel = new LinkedHashMap<>();
-
-    public NamedAssociationsModel()
-    {
-    }
-
-    public Iterable<NamedAssociationModel> namedAssociations()
-    {
-        return mapAccessorAssociationModel.values();
-    }
-
-    public void addNamedAssociation( NamedAssociationModel model )
-    {
-        mapAccessorAssociationModel.put( model.accessor(), model );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super NamedAssociationsModel, ? super NamedAssociationModel, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( NamedAssociationModel associationModel : mapAccessorAssociationModel.values() )
-            {
-                if( !associationModel.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-
-    public <T> NamedAssociation<T> newInstance( AccessibleObject accessor,
-                                                EntityState entityState,
-                                                ModuleUnitOfWork uow )
-    {
-        return mapAccessorAssociationModel.get( accessor ).newInstance( uow, entityState );
-    }
-
-    public NamedAssociationModel getNamedAssociation( AccessibleObject accessor )
-        throws IllegalArgumentException
-    {
-        if( false )
-        {
-            return (NamedAssociationModel) getNamedAssociationByName( QualifiedName.fromAccessor( accessor ).name() );
-        }
-        NamedAssociationModel namedAssociationModel = mapAccessorAssociationModel.get( accessor );
-        if( namedAssociationModel == null )
-        {
-            throw new IllegalArgumentException( "No named-association found with name:" + ( (Member) accessor ).getName() );
-        }
-        return namedAssociationModel;
-    }
-
-    public AssociationDescriptor getNamedAssociationByName( String name )
-        throws IllegalArgumentException
-    {
-        for( NamedAssociationModel associationModel : mapAccessorAssociationModel.values() )
-        {
-            if( associationModel.qualifiedName().name().equals( name ) )
-            {
-                return associationModel;
-            }
-        }
-        throw new IllegalArgumentException( "No named-association found with name:" + name );
-    }
-
-    public AssociationDescriptor getNamedAssociationByQualifiedName( QualifiedName name )
-        throws IllegalArgumentException
-    {
-        for( NamedAssociationModel associationModel : mapAccessorAssociationModel.values() )
-        {
-            if( associationModel.qualifiedName().equals( name ) )
-            {
-                return associationModel;
-            }
-        }
-        throw new IllegalArgumentException( "No named-association found with qualified name:" + name );
-    }
-
-    public void checkConstraints( ValueStateInstance state )
-    {
-        for( NamedAssociationModel associationModel : mapAccessorAssociationModel.values() )
-        {
-            associationModel.checkAssociationConstraints( state.namedAssociationFor( associationModel.accessor() ) );
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/AndAppliesToFilter.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/AndAppliesToFilter.java
deleted file mode 100644
index fafc6b7..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/AndAppliesToFilter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesToFilter;
-
-/**
- * JAVADOC
- */
-final class AndAppliesToFilter
-    implements AppliesToFilter
-{
-    private final AppliesToFilter left;
-    private final AppliesToFilter right;
-
-    AndAppliesToFilter( AppliesToFilter left, AppliesToFilter right )
-    {
-        this.left = left;
-        this.right = right;
-    }
-
-    @Override
-    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
-    {
-        return left.appliesTo( method, mixin, compositeType, fragmentClass ) &&
-               right.appliesTo( method, mixin, compositeType, fragmentClass );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/AnnotationAppliesToFilter.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/AnnotationAppliesToFilter.java
deleted file mode 100644
index 54cf2ad..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/AnnotationAppliesToFilter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesToFilter;
-
-/**
- * JAVADOC
- */
-final class AnnotationAppliesToFilter
-    implements AppliesToFilter
-{
-    @SuppressWarnings( "raw" )
-    private final Class annotationType;
-
-    @SuppressWarnings( "raw" )
-    AnnotationAppliesToFilter( Class type )
-    {
-        this.annotationType = type;
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
-    {
-        return method.getAnnotation( annotationType ) != null;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationAssemblyFactoryImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationAssemblyFactoryImpl.java
deleted file mode 100644
index 7a25eed..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationAssemblyFactoryImpl.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.ApplicationAssemblyFactory;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-/**
- * Factory for ApplicationAssembly.
- */
-public final class ApplicationAssemblyFactoryImpl
-    implements ApplicationAssemblyFactory
-{
-    @Override
-    public ApplicationAssembly newApplicationAssembly( Assembler assembler )
-        throws AssemblyException
-    {
-        return newApplicationAssembly( new Assembler[][][]{ { { assembler } } } );
-    }
-
-    @Override
-    public ApplicationAssembly newApplicationAssembly( Assembler[][][] assemblers )
-        throws AssemblyException
-    {
-        ApplicationAssembly applicationAssembly = newApplicationAssembly();
-
-        // Build all layers bottom-up
-        LayerAssembly below = null;
-        for( int layer = assemblers.length - 1; layer >= 0; layer-- )
-        {
-            // Create Layer
-            LayerAssembly layerAssembly = applicationAssembly.layer( "Layer " + ( layer + 1 ) );
-            for( int module = 0; module < assemblers[ layer ].length; module++ )
-            {
-                // Create Module
-                ModuleAssembly moduleAssembly = layerAssembly.module( "Module " + ( module + 1 ) );
-                for( Assembler assembler : assemblers[ layer ][ module ] )
-                {
-                    // Register Assembler
-                    assembler.assemble( moduleAssembly );
-                }
-            }
-            if( below != null )
-            {
-                layerAssembly.uses( below ); // Link layers
-            }
-            below = layerAssembly;
-        }
-        return applicationAssembly;
-    }
-
-    @Override
-    public ApplicationAssembly newApplicationAssembly()
-    {
-        return new ApplicationAssemblyImpl();
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationAssemblyImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationAssemblyImpl.java
deleted file mode 100644
index 48438e1..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationAssemblyImpl.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.structure.Application;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.AssemblyVisitor;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-/**
- * The representation of an entire application. From
- * this you can set information about the application
- * and create LayerAssemblies.
- */
-public final class ApplicationAssemblyImpl
-    implements ApplicationAssembly
-{
-    private final Map<String, LayerAssemblyImpl> layerAssemblies = new LinkedHashMap<>();
-    private String name = "Application";
-    private String version = "1.0"; // Default version
-    private Application.Mode mode;
-    private final MetaInfo metaInfo = new MetaInfo();
-    private final List<Class<? extends Activator<Application>>> activators = new ArrayList<>();
-
-    public ApplicationAssemblyImpl()
-    {
-        mode = Application.Mode.valueOf( System.getProperty( "mode", "production" ) );
-    }
-
-    @Override
-    public LayerAssembly layer( String name )
-    {
-        if( name != null )
-        {
-            LayerAssemblyImpl existing = layerAssemblies.get( name );
-            if( existing != null )
-            {
-                return existing;
-            }
-        }
-        LayerAssemblyImpl layerAssembly = new LayerAssemblyImpl( this, name );
-        layerAssemblies.put( name, layerAssembly );
-        return layerAssembly;
-    }
-
-    @Override
-    public ModuleAssembly module( String layerName, String moduleName )
-    {
-        return layer( layerName ).module( moduleName );
-    }
-
-    @Override
-    public ApplicationAssembly setName( String name )
-    {
-        this.name = name;
-        return this;
-    }
-
-    @Override
-    public ApplicationAssembly setVersion( String version )
-    {
-        this.version = version;
-        return this;
-    }
-
-    @Override
-    public ApplicationAssembly setMode( Application.Mode mode )
-    {
-        this.mode = mode;
-        return this;
-    }
-
-    @Override
-    public ApplicationAssembly setMetaInfo( Object info )
-    {
-        metaInfo.set( info );
-        return this;
-    }
-
-    @Override
-    @SafeVarargs
-    public final ApplicationAssembly withActivators( Class<? extends Activator<Application>>... activators )
-    {
-        this.activators.addAll( Arrays.asList( activators ) );
-        return this;
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> void visit( AssemblyVisitor<ThrowableType> visitor )
-        throws ThrowableType
-    {
-        visitor.visitApplication( this );
-        for( LayerAssemblyImpl layerAssembly : layerAssemblies.values() )
-        {
-            layerAssembly.visit( visitor );
-        }
-    }
-
-    public Collection<LayerAssemblyImpl> layerAssemblies()
-    {
-        return layerAssemblies.values();
-    }
-
-    public List<Class<? extends Activator<Application>>> activators()
-    {
-        return activators;
-    }
-
-    public MetaInfo metaInfo()
-    {
-        return metaInfo;
-    }
-
-    @Override
-    public String name()
-    {
-        return name;
-    }
-
-    public String version()
-    {
-        return version;
-    }
-
-    @Override
-    public Application.Mode mode()
-    {
-        return mode;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationModelFactoryImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationModelFactoryImpl.java
deleted file mode 100644
index 8669ed7..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ApplicationModelFactoryImpl.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.qi4j.api.composite.ModelDescriptor;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.api.structure.Layer;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.ApplicationModelFactory;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.BindingException;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.runtime.activation.ActivatorsModel;
-import org.qi4j.runtime.composite.CompositeMethodModel;
-import org.qi4j.runtime.injection.InjectedFieldModel;
-import org.qi4j.runtime.model.Binder;
-import org.qi4j.runtime.model.Resolution;
-import org.qi4j.runtime.structure.ApplicationModel;
-import org.qi4j.runtime.structure.LayerModel;
-import org.qi4j.runtime.structure.ModuleModel;
-import org.qi4j.runtime.structure.UsedLayersModel;
-
-/**
- * Factory for Applications.
- */
-public final class ApplicationModelFactoryImpl
-    implements ApplicationModelFactory
-{
-    @Override
-    public ApplicationDescriptor newApplicationModel( ApplicationAssembly assembly )
-        throws AssemblyException
-    {
-        AssemblyHelper helper = new AssemblyHelper();
-
-        ApplicationAssemblyImpl applicationAssembly = (ApplicationAssemblyImpl) assembly;
-        ActivatorsModel<Application> applicationActivators = new ActivatorsModel<>( applicationAssembly.activators() );
-        List<LayerModel> layerModels = new ArrayList<>();
-        final ApplicationModel applicationModel = new ApplicationModel( applicationAssembly.name(),
-                                                                        applicationAssembly.version(),
-                                                                        applicationAssembly.mode(),
-                                                                        applicationAssembly.metaInfo(),
-                                                                        applicationActivators,
-                                                                        layerModels );
-        Map<LayerAssembly, LayerModel> mapAssemblyModel = new HashMap<>();
-        Map<LayerAssembly, List<LayerModel>> mapUsedLayers = new HashMap<>();
-
-        // Build all layers
-        List<LayerAssemblyImpl> layerAssemblies = new ArrayList<>( applicationAssembly.layerAssemblies() );
-        for( LayerAssemblyImpl layerAssembly : layerAssemblies )
-        {
-            List<LayerModel> usedLayers = new ArrayList<>();
-            mapUsedLayers.put( layerAssembly, usedLayers );
-
-            UsedLayersModel usedLayersModel = new UsedLayersModel( usedLayers );
-            List<ModuleModel> moduleModels = new ArrayList<>();
-            String name = layerAssembly.name();
-            if( name == null )
-            {
-                throw new AssemblyException( "Layer must have name set" );
-            }
-            ActivatorsModel<Layer> layerActivators = new ActivatorsModel<>( layerAssembly.activators() );
-            LayerModel layerModel = new LayerModel( name, layerAssembly.metaInfo(), usedLayersModel, layerActivators, moduleModels );
-
-            for( ModuleAssemblyImpl moduleAssembly : layerAssembly.moduleAssemblies() )
-            {
-                moduleModels.add( moduleAssembly.assembleModule( helper ) );
-            }
-            mapAssemblyModel.put( layerAssembly, layerModel );
-            layerModels.add( layerModel );
-        }
-
-        // Populate used layer lists
-        for( LayerAssemblyImpl layerAssembly : layerAssemblies )
-        {
-            Set<LayerAssembly> usesLayers = layerAssembly.uses();
-            List<LayerModel> usedLayers = mapUsedLayers.get( layerAssembly );
-            for( LayerAssembly usesLayer : usesLayers )
-            {
-                LayerModel layerModel = mapAssemblyModel.get( usesLayer );
-                usedLayers.add( layerModel );
-            }
-        }
-
-        // Bind model
-        // This will resolve all dependencies
-        try
-        {
-//            applicationModel.bind();
-            applicationModel.accept( new BindingVisitor( applicationModel ) );
-        }
-        catch( BindingException e )
-        {
-            throw new AssemblyException( "Unable to bind: " + applicationModel, e );
-        }
-
-        return applicationModel;
-    }
-
-    private static class BindingVisitor
-        implements HierarchicalVisitor<Object, Object, BindingException>
-    {
-        private LayerModel layer;
-        private ModuleModel module;
-        private ModelDescriptor objectDescriptor;
-        private CompositeMethodModel compositeMethodModel;
-
-        private Resolution resolution;
-        private final ApplicationModel applicationModel;
-
-        private BindingVisitor( ApplicationModel applicationModel )
-        {
-            this.applicationModel = applicationModel;
-        }
-
-        @Override
-        public boolean visitEnter( Object visited )
-            throws BindingException
-        {
-            if( visited instanceof Binder )
-            {
-                Binder binder = (Binder) visited;
-                binder.bind( resolution );
-
-                return false;
-            }
-            else if( visited instanceof CompositeMethodModel )
-            {
-                compositeMethodModel = (CompositeMethodModel) visited;
-                resolution = new Resolution( applicationModel, layer, module, objectDescriptor, compositeMethodModel, null );
-            }
-            else if( visited instanceof ModelDescriptor )
-            {
-                objectDescriptor = (ModelDescriptor) visited;
-                resolution = new Resolution( applicationModel, layer, module, objectDescriptor, null, null );
-            }
-            else if( visited instanceof InjectedFieldModel )
-            {
-                InjectedFieldModel fieldModel = (InjectedFieldModel) visited;
-                fieldModel.bind( new Resolution( applicationModel, layer, module,
-                                                 objectDescriptor, compositeMethodModel, fieldModel.field() ) );
-            }
-            else if( visited instanceof ModuleModel )
-            {
-                module = (ModuleModel) visited;
-            }
-            else if( visited instanceof LayerModel )
-            {
-                layer = (LayerModel) visited;
-            }
-
-            return true;
-        }
-
-        @Override
-        public boolean visitLeave( Object visited )
-            throws BindingException
-        {
-            return true;
-        }
-
-        @Override
-        public boolean visit( Object visited )
-            throws BindingException
-        {
-            if( visited instanceof Binder )
-            {
-                ( (Binder) visited ).bind( resolution );
-            }
-            return true;
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/AssemblyHelper.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/AssemblyHelper.java
deleted file mode 100644
index f67025a..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/AssemblyHelper.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.Map;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.AppliesToFilter;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.runtime.composite.ConcernModel;
-import org.qi4j.runtime.composite.ConstraintDeclaration;
-import org.qi4j.runtime.composite.FragmentClassLoader;
-import org.qi4j.runtime.composite.MixinModel;
-import org.qi4j.runtime.composite.SideEffectModel;
-
-/**
- * This helper is used when building the application model. It keeps track
- * of already created classloaders and various models
- */
-public class AssemblyHelper
-{
-    Map<Class, Class> instantiationClasses = new HashMap<>();
-    Map<Class, ConstraintDeclaration> constraintDeclarations = new HashMap<>();
-    Map<ClassLoader, FragmentClassLoader> modifierClassLoaders = new HashMap<>();
-    Map<Class<?>, AppliesToFilter> appliesToInstances = new HashMap<>();
-
-    public MixinModel getMixinModel( Class mixinClass )
-    {
-        return new MixinModel( mixinClass, instantiationClass( mixinClass ) );
-    }
-
-    public ConcernModel getConcernModel( Class concernClass )
-    {
-        return new ConcernModel( concernClass, instantiationClass( concernClass ) );
-    }
-
-    public SideEffectModel getSideEffectModel( Class sideEffectClass )
-    {
-        return new SideEffectModel( sideEffectClass, instantiationClass( sideEffectClass ) );
-    }
-
-    private Class instantiationClass( Class fragmentClass )
-    {
-        Class instantiationClass = fragmentClass;
-        if( !InvocationHandler.class.isAssignableFrom( fragmentClass ) )
-        {
-            instantiationClass = instantiationClasses.get( fragmentClass );
-
-            if( instantiationClass == null )
-            {
-                try
-                {
-                    FragmentClassLoader fragmentLoader = getModifierClassLoader( fragmentClass.getClassLoader() );
-                    instantiationClass = fragmentLoader.loadFragmentClass( fragmentClass );
-                    instantiationClasses.put( fragmentClass, instantiationClass );
-                }
-                catch( ClassNotFoundException | VerifyError e )
-                {
-                    throw new ConstructionException( "Could not generate mixin subclass " + fragmentClass.getName(), e );
-                }
-            }
-        }
-        return instantiationClass;
-    }
-
-    private FragmentClassLoader getModifierClassLoader( ClassLoader classLoader )
-    {
-        FragmentClassLoader cl = modifierClassLoaders.get( classLoader );
-        if( cl == null )
-        {
-            cl = new FragmentClassLoader( classLoader );
-            modifierClassLoaders.put( classLoader, cl );
-        }
-        return cl;
-    }
-
-    public boolean appliesTo( Class<?> fragmentClass, Method method, Iterable<Class<?>> types, Class<?> mixinClass )
-    {
-        AppliesToFilter appliesToFilter = appliesToInstances.get( fragmentClass );
-        if( appliesToFilter == null )
-        {
-            appliesToFilter = createAppliesToFilter( fragmentClass );
-            appliesToInstances.put( fragmentClass, appliesToFilter );
-        }
-        for( Class<?> compositeType : types )
-        {
-            if( appliesToFilter.appliesTo( method, mixinClass, compositeType, fragmentClass ) )
-            {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public AppliesToFilter createAppliesToFilter( Class<?> fragmentClass )
-    {
-        AppliesToFilter result = null;
-        if( !InvocationHandler.class.isAssignableFrom( fragmentClass ) )
-        {
-            result = new TypedFragmentAppliesToFilter();
-            if( Modifier.isAbstract( fragmentClass.getModifiers() ) )
-            {
-                result = new AndAppliesToFilter( result, new ImplementsMethodAppliesToFilter() );
-            }
-        }
-        result = applyAppliesTo( result, fragmentClass );
-        if( result == null )
-        {
-            return AppliesToFilter.ALWAYS;
-        }
-        return result;
-    }
-
-    private AppliesToFilter applyAppliesTo( AppliesToFilter existing, Class<?> modifierClass )
-    {
-        AppliesTo appliesTo = modifierClass.getAnnotation( AppliesTo.class );
-        if( appliesTo != null )
-        {
-            // Use "or" for all filters specified in the annotation
-            AppliesToFilter appliesToAnnotation = null;
-            for( Class<?> appliesToClass : appliesTo.value() )
-            {
-                AppliesToFilter filter;
-                if( AppliesToFilter.class.isAssignableFrom( appliesToClass ) )
-                {
-                    try
-                    {
-                        filter = (AppliesToFilter) appliesToClass.newInstance();
-                    }
-                    catch( Exception e )
-                    {
-                        throw new ConstructionException( e );
-                    }
-                }
-                else if( Annotation.class.isAssignableFrom( appliesToClass ) )
-                {
-                    filter = new AnnotationAppliesToFilter( appliesToClass );
-                }
-                else // Type check
-                {
-                    filter = new TypeCheckAppliesToFilter( appliesToClass );
-                }
-
-                if( appliesToAnnotation == null )
-                {
-                    appliesToAnnotation = filter;
-                }
-                else
-                {
-                    appliesToAnnotation = new OrAppliesToFilter( appliesToAnnotation, filter );
-                }
-            }
-            // Add to the rest of the rules using "and"
-            if( existing == null )
-            {
-                return appliesToAnnotation;
-            }
-            else
-            {
-                return new AndAppliesToFilter( existing, appliesToAnnotation );
-            }
-        }
-        return existing;
-    }
-
-    public boolean appliesTo( Class<? extends Constraint<?, ?>> constraint,
-                              Class<? extends Annotation> annotationType,
-                              Type valueType
-    )
-    {
-        ConstraintDeclaration constraintDeclaration = constraintDeclarations.get( constraint );
-        if( constraintDeclaration == null )
-        {
-            constraintDeclaration = new ConstraintDeclaration( constraint );
-            constraintDeclarations.put( constraint, constraintDeclaration );
-        }
-
-        return constraintDeclaration.appliesTo( annotationType, valueType );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/CompositeAssemblyImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/CompositeAssemblyImpl.java
deleted file mode 100644
index 7441390..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/CompositeAssemblyImpl.java
+++ /dev/null
@@ -1,837 +0,0 @@
-/*
- * Copyright (c) 2007-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.bootstrap;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Proxy;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.InvalidCompositeException;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.api.constraint.Name;
-import org.qi4j.api.entity.Lifecycle;
-import org.qi4j.api.injection.scope.State;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Initializable;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.GenericPropertyInfo;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.sideeffect.SideEffects;
-import org.qi4j.api.type.HasTypes;
-import org.qi4j.api.util.Annotations;
-import org.qi4j.api.util.Classes;
-import org.qi4j.api.util.Fields;
-import org.qi4j.bootstrap.StateDeclarations;
-import org.qi4j.functional.ForEach;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.HierarchicalVisitorAdapter;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.Visitor;
-import org.qi4j.runtime.composite.AbstractConstraintModel;
-import org.qi4j.runtime.composite.CompositeConstraintModel;
-import org.qi4j.runtime.composite.CompositeMethodModel;
-import org.qi4j.runtime.composite.CompositeMethodsModel;
-import org.qi4j.runtime.composite.ConcernModel;
-import org.qi4j.runtime.composite.ConcernsModel;
-import org.qi4j.runtime.composite.ConstraintModel;
-import org.qi4j.runtime.composite.ConstraintsModel;
-import org.qi4j.runtime.composite.GenericSpecification;
-import org.qi4j.runtime.composite.MixinModel;
-import org.qi4j.runtime.composite.MixinsModel;
-import org.qi4j.runtime.composite.SideEffectModel;
-import org.qi4j.runtime.composite.SideEffectsModel;
-import org.qi4j.runtime.composite.StateModel;
-import org.qi4j.runtime.composite.ValueConstraintsInstance;
-import org.qi4j.runtime.composite.ValueConstraintsModel;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.runtime.property.PropertiesModel;
-import org.qi4j.runtime.property.PropertyModel;
-
-import static java.util.Arrays.asList;
-import static org.qi4j.api.util.Annotations.hasAnnotation;
-import static org.qi4j.api.util.Annotations.isType;
-import static org.qi4j.api.util.Annotations.type;
-import static org.qi4j.api.util.Classes.classHierarchy;
-import static org.qi4j.api.util.Classes.interfacesOf;
-import static org.qi4j.api.util.Classes.isAssignableFrom;
-import static org.qi4j.api.util.Classes.typeOf;
-import static org.qi4j.api.util.Classes.typesOf;
-import static org.qi4j.api.util.Classes.wrapperClass;
-import static org.qi4j.functional.Iterables.addAll;
-import static org.qi4j.functional.Iterables.cast;
-import static org.qi4j.functional.Iterables.empty;
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.flatten;
-import static org.qi4j.functional.Iterables.flattenIterables;
-import static org.qi4j.functional.Iterables.iterable;
-import static org.qi4j.functional.Iterables.map;
-import static org.qi4j.functional.Iterables.matchesAny;
-import static org.qi4j.functional.Iterables.toList;
-import static org.qi4j.functional.Specifications.and;
-import static org.qi4j.functional.Specifications.in;
-import static org.qi4j.functional.Specifications.not;
-import static org.qi4j.functional.Specifications.or;
-import static org.qi4j.functional.Specifications.translate;
-
-/**
- * Declaration of a Composite.
- */
-public abstract class CompositeAssemblyImpl
-    implements HasTypes
-{
-    protected List<Class<?>> concerns = new ArrayList<>();
-    protected List<Class<?>> sideEffects = new ArrayList<>();
-    protected List<Class<?>> mixins = new ArrayList<>();
-    protected List<Class<?>> types = new ArrayList<>();
-    protected MetaInfo metaInfo = new MetaInfo();
-    protected Visibility visibility = Visibility.module;
-
-    protected boolean immutable;
-    protected PropertiesModel propertiesModel;
-    protected StateModel stateModel;
-    protected MixinsModel mixinsModel;
-    protected CompositeMethodsModel compositeMethodsModel;
-    private AssemblyHelper helper;
-    protected StateDeclarations stateDeclarations;
-
-    protected Set<String> registeredStateNames = new HashSet<>();
-
-    public CompositeAssemblyImpl( Class<?> mainType )
-    {
-        types.add( mainType );
-    }
-
-    @Override
-    public Iterable<Class<?>> types()
-    {
-        return types;
-    }
-
-    protected StateModel createStateModel()
-    {
-        return new StateModel( propertiesModel );
-    }
-
-    protected MixinsModel createMixinsModel()
-    {
-        return new MixinsModel();
-    }
-
-    protected void buildComposite( AssemblyHelper helper,
-                                   StateDeclarations stateDeclarations
-    )
-    {
-        this.stateDeclarations = stateDeclarations;
-        this.helper = helper;
-        for( Class<?> compositeType : types )
-        {
-            metaInfo = new MetaInfo( metaInfo ).withAnnotations( compositeType );
-            addAnnotationsMetaInfo( compositeType, metaInfo );
-        }
-
-        immutable = metaInfo.get( Immutable.class ) != null;
-        propertiesModel = new PropertiesModel();
-        stateModel = createStateModel();
-        mixinsModel = createMixinsModel();
-        compositeMethodsModel = new CompositeMethodsModel( mixinsModel );
-
-        // Implement composite methods
-        ArrayList<Type> allTypes = getTypes( this.types );
-        Iterable<Class<? extends Constraint<?, ?>>> constraintClasses = constraintDeclarations( getTypes( this.types ) );
-        Iterable<Class<?>> concernClasses = flatten( concerns, concernDeclarations( allTypes ) );
-        Iterable<Class<?>> sideEffectClasses = flatten( sideEffects, sideEffectDeclarations( allTypes ) );
-        Iterable<Class<?>> mixinClasses = flatten( mixins, mixinDeclarations( this.types ) );
-        implementMixinType( types, constraintClasses, concernClasses, sideEffectClasses, mixinClasses );
-
-        // Add state from methods and fields
-        addState( constraintClasses );
-    }
-
-    protected void addAnnotationsMetaInfo( Class<?> type, MetaInfo compositeMetaInfo )
-    {
-        Class[] declaredInterfaces = type.getInterfaces();
-        for( int i = declaredInterfaces.length - 1; i >= 0; i-- )
-        {
-            addAnnotationsMetaInfo( declaredInterfaces[ i], compositeMetaInfo );
-        }
-        compositeMetaInfo.withAnnotations( type );
-    }
-
-    protected void implementMixinType( Iterable<? extends Class<?>> types,
-                                       Iterable<Class<? extends Constraint<?, ?>>> constraintClasses,
-                                       Iterable<Class<?>> concernClasses,
-                                       Iterable<Class<?>> sideEffectClasses,
-                                       Iterable<Class<?>> mixinClasses
-    )
-    {
-        Set<Class<?>> thisDependencies = new HashSet<>();
-        for( Class<?> mixinType : types )
-        {
-            for( Method method : mixinType.getMethods() )
-            {
-                if( !compositeMethodsModel.isImplemented( method )
-                    && !Proxy.class.equals( method.getDeclaringClass().getSuperclass() )
-                    && !Proxy.class.equals( method.getDeclaringClass() )
-                    && !Modifier.isStatic( method.getModifiers() ) )
-                {
-                    MixinModel mixinModel = implementMethod( method, mixinClasses );
-                    ConcernsModel concernsModel = concernsFor(
-                        method,
-                        mixinModel.mixinClass(),
-                        Iterables.<Class<?>>flatten( concernDeclarations( mixinModel.mixinClass() ),
-                                                     concernClasses )
-                    );
-                    SideEffectsModel sideEffectsModel = sideEffectsFor(
-                        method,
-                        mixinModel.mixinClass(),
-                        Iterables.<Class<?>>flatten( sideEffectDeclarations( mixinModel.mixinClass() ),
-                                                     sideEffectClasses )
-                    );
-                    method.setAccessible( true );
-                    ConstraintsModel constraints = constraintsFor(
-                        method,
-                        Iterables.<Class<? extends Constraint<?, ?>>>flatten( constraintDeclarations( mixinModel.mixinClass() ),
-                                                                              constraintClasses )
-                    );
-                    CompositeMethodModel methodComposite = new CompositeMethodModel(
-                        method,
-                        constraints,
-                        concernsModel,
-                        sideEffectsModel,
-                        mixinsModel
-                    );
-
-                    // Implement @This references
-                    Iterable<Class<?>> map = map( new DependencyModel.InjectionTypeFunction(),
-                                                  filter( new DependencyModel.ScopeSpecification( This.class ),
-                                                          methodComposite.dependencies() ) );
-                    Iterable<Class<?>> map1 = map( new DependencyModel.InjectionTypeFunction(),
-                                                   filter( new DependencyModel.ScopeSpecification( This.class ),
-                                                           mixinModel.dependencies() ) );
-                    @SuppressWarnings( "unchecked" )
-                    Iterable<Class<?>> filter = filter(
-                        not( in( Initializable.class, Lifecycle.class, InvocationHandler.class ) ),
-                        map( Classes.RAW_CLASS, interfacesOf( mixinModel.mixinClass() ) )
-                    );
-                    Iterable<? extends Class<?>> flatten = flatten( map, map1, filter );
-                    addAll( thisDependencies, flatten );
-
-                    compositeMethodsModel.addMethod( methodComposite );
-                }
-            }
-            // Add type to set of mixin types
-            mixinsModel.addMixinType( mixinType );
-        }
-
-        // Implement all @This dependencies that were found
-        for( Class<?> thisDependency : thisDependencies )
-        {
-            // Add additional declarations from the @This type
-            Iterable<Class<? extends Constraint<?, ?>>> typeConstraintClasses = flatten(
-                constraintClasses,
-                constraintDeclarations( thisDependency ) );
-            Iterable<Class<?>> typeConcernClasses = flatten(
-                concernClasses,
-                concernDeclarations( thisDependency ) );
-            Iterable<Class<?>> typeSideEffectClasses = flatten(
-                sideEffectClasses,
-                sideEffectDeclarations( thisDependency ) );
-            Iterable<Class<?>> typeMixinClasses = flatten(
-                mixinClasses,
-                mixinDeclarations( thisDependency ) );
-
-            @SuppressWarnings( "unchecked" )
-            Iterable<? extends Class<?>> singleton = iterable( thisDependency );
-            implementMixinType( singleton, typeConstraintClasses, typeConcernClasses, typeSideEffectClasses, typeMixinClasses );
-        }
-    }
-
-    @SuppressWarnings( "raw" )
-    protected MixinModel implementMethod( Method method, Iterable<Class<?>> mixinDeclarations )
-    {
-        MixinModel implementationModel = mixinsModel.mixinFor( method );
-        if( implementationModel != null )
-        {
-            return implementationModel;
-        }
-        Class mixinClass = findTypedImplementation( method, mixinDeclarations );
-        if( mixinClass != null )
-        {
-            return implementMethodWithClass( method, mixinClass );
-        }
-
-        // Check generic implementations
-        mixinClass = findGenericImplementation( method, mixinDeclarations );
-        if( mixinClass != null )
-        {
-            return implementMethodWithClass( method, mixinClass );
-        }
-
-        throw new InvalidCompositeException( "No implementation found for method \n    " + method.toGenericString()
-                                             + "\nin\n    " + types );
-    }
-
-    @SuppressWarnings( {"raw", "unchecked"} )
-    private Class findTypedImplementation( final Method method, Iterable<Class<?>> mixins )
-    {
-        // Check if mixinClass implements the method. If so, check if the mixinClass is generic or if the filter passes.
-        // If a mixinClass is both generic AND non-generic at the same time, then the filter applies to the non-generic
-        // side only.
-        Specification<Class<?>> appliesToSpec = new Specification<Class<?>>()
-        {
-            @Override
-            public boolean satisfiedBy( Class<?> item )
-            {
-                return helper.appliesTo( item, method, types, item );
-            }
-        };
-        return first( filter( and( isAssignableFrom( method.getDeclaringClass() ),
-                                   or( GenericSpecification.INSTANCE, appliesToSpec ) ),
-                              mixins ) );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private Class<?> findGenericImplementation( final Method method, Iterable<Class<?>> mixins )
-    {
-        // Check if mixinClass is generic and the applies-to filter passes
-        return first( filter( and( GenericSpecification.INSTANCE, new Specification<Class<?>>()
-        {
-            @Override
-            public boolean satisfiedBy( Class<?> item )
-            {
-                return helper.appliesTo( item, method, types, item );
-            }
-        } ), mixins ) );
-    }
-
-    private MixinModel implementMethodWithClass( Method method, Class mixinClass )
-    {
-        MixinModel mixinModel = mixinsModel.getMixinModel( mixinClass );
-        if( mixinModel == null )
-        {
-            mixinModel = helper.getMixinModel( mixinClass );
-            mixinsModel.addMixinModel( mixinModel );
-        }
-
-        mixinsModel.addMethodMixin( method, mixinModel );
-
-        return mixinModel;
-    }
-
-    protected void addState( final Iterable<Class<? extends Constraint<?, ?>>> constraintClasses )
-    {
-        // Add method state
-        compositeMethodsModel.accept( new HierarchicalVisitorAdapter<Object, Object, RuntimeException>()
-        {
-            @Override
-            public boolean visitEnter( Object visited )
-                throws RuntimeException
-            {
-                if( visited instanceof CompositeMethodModel )
-                {
-                    CompositeMethodModel methodModel = (CompositeMethodModel) visited;
-                    if( methodModel.method().getParameterTypes().length == 0 )
-                    {
-                        addStateFor( methodModel.method(), constraintClasses );
-                    }
-
-                    return false;
-                }
-
-                return super.visitEnter( visited );
-            }
-        } );
-
-        // Add field state
-        mixinsModel.accept( new HierarchicalVisitorAdapter<Object, Object, RuntimeException>()
-        {
-            @Override
-            public boolean visitEnter( Object visited )
-                throws RuntimeException
-            {
-                if( visited instanceof MixinModel )
-                {
-                    MixinModel model = (MixinModel) visited;
-                    Visitor<Field, RuntimeException> addState = new Visitor<Field, RuntimeException>()
-                    {
-                        @Override
-                        public boolean visit( Field visited )
-                            throws RuntimeException
-                        {
-                            addStateFor( visited, constraintClasses );
-                            return true;
-                        }
-                    };
-                    ForEach.forEach( Fields.FIELDS_OF.map( model.mixinClass() ) ).
-                        filter( Annotations.hasAnnotation( State.class ) ).
-                        visit( addState );
-                    return false;
-                }
-                return super.visitEnter( visited );
-            }
-        } );
-    }
-
-    protected void addStateFor( AccessibleObject accessor,
-                                Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
-    )
-    {
-        String stateName = QualifiedName.fromAccessor( accessor ).name();
-
-        if( registeredStateNames.contains( stateName ) )
-        {
-            return; // Skip already registered names
-        }
-
-        if( Property.class.isAssignableFrom( Classes.RAW_CLASS.map( typeOf( accessor ) ) ) )
-        {
-            propertiesModel.addProperty( newPropertyModel( accessor, constraintClasses ) );
-            registeredStateNames.add( stateName );
-        }
-    }
-
-    protected PropertyModel newPropertyModel( AccessibleObject accessor,
-                                              Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
-    )
-    {
-        Iterable<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
-        boolean optional = first( filter( isType( Optional.class ), annotations ) ) != null;
-        ValueConstraintsModel valueConstraintsModel = constraintsFor(
-            annotations,
-            GenericPropertyInfo.propertyTypeOf( accessor ),
-            ( (Member) accessor ).getName(),
-            optional,
-            constraintClasses,
-            accessor );
-        ValueConstraintsInstance valueConstraintsInstance = null;
-        if( valueConstraintsModel.isConstrained() )
-        {
-            valueConstraintsInstance = valueConstraintsModel.newInstance();
-        }
-        MetaInfo metaInfo = stateDeclarations.metaInfoFor( accessor );
-        Object initialValue = stateDeclarations.initialValueOf( accessor );
-        boolean useDefaults = metaInfo.get( UseDefaults.class ) != null || stateDeclarations.useDefaults( accessor );
-        boolean immutable = this.immutable || metaInfo.get( Immutable.class ) != null;
-        PropertyModel propertyModel = new PropertyModel(
-            accessor,
-            immutable,
-            useDefaults,
-            valueConstraintsInstance,
-            metaInfo,
-            initialValue );
-        return propertyModel;
-    }
-
-    // Model
-    private ConstraintsModel constraintsFor( Method method,
-                                             Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
-    )
-    {
-        List<ValueConstraintsModel> parameterConstraintModels = Collections.emptyList();
-        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
-        Type[] parameterTypes = method.getGenericParameterTypes();
-        boolean constrained = false;
-        for( int i = 0; i < parameterAnnotations.length; i++ )
-        {
-            Annotation[] parameterAnnotation = parameterAnnotations[i];
-
-            Name nameAnnotation = (Name) first( filter( isType( Name.class ), iterable( parameterAnnotation ) ) );
-            String name = nameAnnotation == null ? "param" + ( i + 1 ) : nameAnnotation.value();
-
-            boolean optional = first( filter( isType( Optional.class ), iterable( parameterAnnotation ) ) ) != null;
-            ValueConstraintsModel parameterConstraintsModel = constraintsFor(
-                asList( parameterAnnotation ),
-                parameterTypes[i],
-                name,
-                optional,
-                constraintClasses,
-                method );
-            if( parameterConstraintsModel.isConstrained() )
-            {
-                constrained = true;
-            }
-
-            if( parameterConstraintModels.isEmpty() )
-            {
-                parameterConstraintModels = new ArrayList<>();
-            }
-            parameterConstraintModels.add( parameterConstraintsModel );
-        }
-
-        if( !constrained )
-        {
-            return new ConstraintsModel( Collections.<ValueConstraintsModel>emptyList() );
-        }
-        else
-        {
-            return new ConstraintsModel( parameterConstraintModels );
-        }
-    }
-
-    protected ValueConstraintsModel constraintsFor(
-        Iterable<Annotation> constraintAnnotations,
-        Type valueType,
-        String name,
-        boolean optional,
-        Iterable<Class<? extends Constraint<?, ?>>> constraintClasses,
-        AccessibleObject accessor
-    )
-    {
-        valueType = wrapperClass( valueType );
-
-        List<AbstractConstraintModel> constraintModels = new ArrayList<>();
-        nextConstraint:
-        for( Annotation constraintAnnotation : filter( translate( type(), hasAnnotation( ConstraintDeclaration.class ) ),
-                                                       constraintAnnotations ) )
-        {
-            // Check composite declarations first
-            Class<? extends Annotation> annotationType = constraintAnnotation.annotationType();
-            for( Class<? extends Constraint<?, ?>> constraint : constraintClasses )
-            {
-                if( helper.appliesTo( constraint, annotationType, valueType ) )
-                {
-                    constraintModels.add( new ConstraintModel( constraintAnnotation, constraint ) );
-                    continue nextConstraint;
-                }
-            }
-
-            // Check the annotation itself
-            Constraints constraints = annotationType.getAnnotation( Constraints.class );
-            if( constraints != null )
-            {
-                for( Class<? extends Constraint<?, ?>> constraintClass : constraints.value() )
-                {
-                    if( helper.appliesTo( constraintClass, annotationType, valueType ) )
-                    {
-                        constraintModels.add( new ConstraintModel( constraintAnnotation, constraintClass ) );
-                        continue nextConstraint;
-                    }
-                }
-            }
-
-            // No implementation found!
-            // Check if if it's a composite constraints
-            Iterable<Annotation> annotations = iterable( annotationType.getAnnotations() );
-            if( matchesAny( translate( type(), hasAnnotation( ConstraintDeclaration.class ) ), annotations ) )
-            {
-                ValueConstraintsModel valueConstraintsModel = constraintsFor(
-                    annotations,
-                    valueType,
-                    name,
-                    optional,
-                    constraintClasses,
-                    accessor );
-                CompositeConstraintModel compositeConstraintModel = new CompositeConstraintModel(
-                    constraintAnnotation,
-                    valueConstraintsModel );
-                constraintModels.add( compositeConstraintModel );
-                continue nextConstraint;
-            }
-
-            throw new InvalidCompositeException(
-                "Cannot find implementation of constraint @"
-                + annotationType.getSimpleName()
-                + " for "
-                + valueType
-                + " in method "
-                + ( (Member) accessor ).getName()
-                + " of composite " + types );
-        }
-
-        return new ValueConstraintsModel( constraintModels, name, optional );
-    }
-
-    private ConcernsModel concernsFor( Method method,
-                                       Class<?> mixinClass,
-                                       Iterable<Class<?>> concernClasses
-    )
-    {
-        List<ConcernModel> concernsFor = new ArrayList<>();
-        for( Class<?> concern : concernClasses )
-        {
-            if( helper.appliesTo( concern, method, types, mixinClass ) )
-            {
-                concernsFor.add( helper.getConcernModel( concern ) );
-            }
-            else
-            {
-                // Lookup method in mixin
-                if( !InvocationHandler.class.isAssignableFrom( mixinClass ) )
-                {
-                    try
-                    {
-                        Method mixinMethod = mixinClass.getMethod( method.getName(), method.getParameterTypes() );
-                        if( helper.appliesTo( concern, mixinMethod, types, mixinClass ) )
-                        {
-                            concernsFor.add( helper.getConcernModel( concern ) );
-                        }
-                    }
-                    catch( NoSuchMethodException e )
-                    {
-                        // Ignore
-                    }
-                }
-            }
-        }
-
-        // Check annotations on method that have @Concerns annotations themselves
-        for( Annotation annotation : method.getAnnotations() )
-        {
-            @SuppressWarnings( "raw" )
-            Concerns concerns = annotation.annotationType().getAnnotation( Concerns.class );
-            if( concerns != null )
-            {
-                for( Class<?> concern : concerns.value() )
-                {
-                    if( helper.appliesTo( concern, method, types, mixinClass ) )
-                    {
-                        concernsFor.add( helper.getConcernModel( concern ) );
-                    }
-                }
-            }
-        }
-
-        if( concernsFor.isEmpty() )
-        {
-            return ConcernsModel.EMPTY_CONCERNS;
-        }
-        else
-        {
-            return new ConcernsModel( concernsFor );
-        }
-    }
-
-    private SideEffectsModel sideEffectsFor( Method method,
-                                             Class<?> mixinClass,
-                                             Iterable<Class<?>> sideEffectClasses
-    )
-    {
-        List<SideEffectModel> sideEffectsFor = new ArrayList<>();
-        for( Class<?> sideEffect : sideEffectClasses )
-        {
-            if( helper.appliesTo( sideEffect, method, types, mixinClass ) )
-            {
-                sideEffectsFor.add( helper.getSideEffectModel( sideEffect ) );
-            }
-            else
-            {
-                // Lookup method in mixin
-                if( !InvocationHandler.class.isAssignableFrom( mixinClass ) )
-                {
-                    try
-                    {
-                        Method mixinMethod = mixinClass.getMethod( method.getName(), method.getParameterTypes() );
-                        if( helper.appliesTo( sideEffect, mixinMethod, types, mixinClass ) )
-                        {
-                            sideEffectsFor.add( helper.getSideEffectModel( sideEffect ) );
-                        }
-                    }
-                    catch( NoSuchMethodException e )
-                    {
-                        // Ignore
-                    }
-                }
-            }
-        }
-
-        if( sideEffectsFor.isEmpty() )
-        {
-            return SideEffectsModel.EMPTY_SIDEEFFECTS;
-        }
-        else
-        {
-            return new SideEffectsModel( sideEffectsFor );
-        }
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private Iterable<Class<? extends Constraint<?, ?>>> constraintDeclarations( Class<?> type )
-    {
-        ArrayList<Type> allTypes = getTypes( type );
-        return constraintDeclarations( allTypes );
-    }
-
-    private Iterable<Class<? extends Constraint<?, ?>>> constraintDeclarations( ArrayList<Type> allTypes )
-    {
-        // Find all constraints and flatten them into an iterable
-        Function<Type, Iterable<Class<? extends Constraint<?, ?>>>> function = new Function<Type, Iterable<Class<? extends Constraint<?, ?>>>>()
-        {
-            @Override
-            public Iterable<Class<? extends Constraint<?, ?>>> map( Type type )
-            {
-                Constraints constraints = Annotations.annotationOn( type, Constraints.class );
-                if( constraints == null )
-                {
-                    return empty();
-                }
-                else
-                {
-                    return iterable( constraints.value() );
-                }
-            }
-        };
-        Iterable<Class<? extends Constraint<?, ?>>> flatten = flattenIterables( map( function, allTypes ) );
-        return toList( flatten );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private Iterable<Class<?>> concernDeclarations( Class<?> type )
-    {
-        Iterable<? extends Class<?>> iterable = iterable( type );
-        return concernDeclarations( getTypes( iterable ) );
-    }
-
-    private Iterable<Class<?>> concernDeclarations( ArrayList<Type> allTypes )
-    {
-        // Find all concerns and flattern them into an iterable
-        Function<Type, Iterable<Class<?>>> function = new Function<Type, Iterable<Class<?>>>()
-        {
-            @Override
-            public Iterable<Class<?>> map( Type type )
-            {
-                Concerns concerns = Annotations.annotationOn( type, Concerns.class );
-                if( concerns == null )
-                {
-                    return empty();
-                }
-                else
-                {
-                    return iterable( concerns.value() );
-                }
-            }
-        };
-        Iterable<Class<?>> flatten = flattenIterables( map( function, allTypes ) );
-        return toList( flatten );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    protected Iterable<Class<?>> sideEffectDeclarations( Class<?> type )
-    {
-        Iterable<? extends Class<?>> iterable = iterable( type );
-        return sideEffectDeclarations( getTypes( iterable ) );
-    }
-
-    protected Iterable<Class<?>> sideEffectDeclarations( ArrayList<Type> allTypes )
-    {
-        // Find all side-effects and flattern them into an iterable
-        Function<Type, Iterable<Class<?>>> function = new Function<Type, Iterable<Class<?>>>()
-        {
-            @Override
-            public Iterable<Class<?>> map( Type type )
-            {
-                SideEffects sideEffects = Annotations.annotationOn( type, SideEffects.class );
-                if( sideEffects == null )
-                {
-                    return empty();
-                }
-                else
-                {
-                    return iterable( sideEffects.value() );
-                }
-            }
-        };
-        Iterable<Class<?>> flatten = flattenIterables( map( function, allTypes ) );
-        return toList( flatten );
-    }
-
-    private ArrayList<Type> getTypes( Class<?> type )
-    {
-        Iterable<? extends Class<?>> iterable = iterable( type );
-        return getTypes( iterable );
-    }
-
-    private ArrayList<Type> getTypes( Iterable<? extends Class<?>> typess )
-    {
-        // Find side-effect declarations
-        ArrayList<Type> allTypes = new ArrayList<>();
-        for( Class<?> type : typess )
-        {
-            Iterable<Type> types;
-            if( type.isInterface() )
-            {
-                types = typesOf( type );
-            }
-            else
-            {
-                types = cast( classHierarchy( type ) );
-            }
-            addAll( allTypes, types );
-        }
-        return allTypes;
-    }
-
-    @SuppressWarnings( "unchecked" )
-    protected Iterable<Class<?>> mixinDeclarations( Class<?> type )
-    {
-        Iterable<? extends Class<?>> iterable = iterable( type );
-        return mixinDeclarations( iterable );
-    }
-
-    protected Iterable<Class<?>> mixinDeclarations( Iterable<? extends Class<?>> typess )
-    {
-        // Find mixin declarations
-        ArrayList<Type> allTypes = new ArrayList<>();
-        for( Class<?> type : typess )
-        {
-            Iterable<Type> types = typesOf( type );
-            addAll( allTypes, types );
-        }
-
-        // Find all mixins and flattern them into an iterable
-        Function<Type, Iterable<Class<?>>> function = new Function<Type, Iterable<Class<?>>>()
-        {
-            @Override
-            public Iterable<Class<?>> map( Type type )
-            {
-                Mixins mixins = Annotations.annotationOn( type, Mixins.class );
-                if( mixins == null )
-                {
-                    return empty();
-                }
-                else
-                {
-                    return iterable( mixins.value() );
-                }
-            }
-        };
-        Iterable<Class<?>> flatten = flattenIterables( map( function, allTypes ) );
-        return toList( flatten );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ConfigurationAssemblyImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ConfigurationAssemblyImpl.java
deleted file mode 100644
index d8088cc..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ConfigurationAssemblyImpl.java
+++ /dev/null
@@ -1,85 +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.qi4j.runtime.bootstrap;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Member;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.GenericAssociationInfo;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.common.InvalidApplicationException;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.GenericPropertyInfo;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.util.Annotations;
-import org.qi4j.api.util.Classes;
-import org.qi4j.bootstrap.AssociationDeclarations;
-import org.qi4j.bootstrap.ConfigurationAssembly;
-import org.qi4j.bootstrap.EntityAssembly;
-import org.qi4j.bootstrap.ManyAssociationDeclarations;
-import org.qi4j.bootstrap.NamedAssociationDeclarations;
-import org.qi4j.bootstrap.StateDeclarations;
-import org.qi4j.runtime.association.AssociationModel;
-import org.qi4j.runtime.association.AssociationsModel;
-import org.qi4j.runtime.association.ManyAssociationModel;
-import org.qi4j.runtime.association.ManyAssociationsModel;
-import org.qi4j.runtime.association.NamedAssociationModel;
-import org.qi4j.runtime.association.NamedAssociationsModel;
-import org.qi4j.runtime.composite.MixinsModel;
-import org.qi4j.runtime.composite.StateModel;
-import org.qi4j.runtime.composite.ValueConstraintsInstance;
-import org.qi4j.runtime.composite.ValueConstraintsModel;
-import org.qi4j.runtime.entity.EntityMixinsModel;
-import org.qi4j.runtime.entity.EntityModel;
-import org.qi4j.runtime.entity.EntityStateModel;
-import org.qi4j.runtime.property.PropertyModel;
-
-import static org.qi4j.api.util.Annotations.isType;
-import static org.qi4j.api.util.Classes.typeOf;
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Declaration of a EntityComposite.
- */
-public final class ConfigurationAssemblyImpl
-    implements ConfigurationAssembly
-{
-    private ValueAssemblyImpl value;
-    private EntityAssemblyImpl entity;
-
-    public ConfigurationAssemblyImpl( Class<?> mainType )
-    {
-        value = new ValueAssemblyImpl( mainType );
-        entity = new EntityAssemblyImpl( mainType );
-    }
-
-    @Override
-    public Iterable<Class<?>> types()
-    {
-        return value.types();
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ConfigurationDeclarationImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ConfigurationDeclarationImpl.java
deleted file mode 100644
index 18a14cb..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ConfigurationDeclarationImpl.java
+++ /dev/null
@@ -1,125 +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.qi4j.runtime.bootstrap;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.ConfigurationDeclaration;
-import org.qi4j.bootstrap.EntityDeclaration;
-
-import static java.util.Arrays.asList;
-
-/**
- * Declaration of a Composite. Created by {@link org.qi4j.bootstrap.ModuleAssembly#configurations(Class[])}.
- */
-public final class ConfigurationDeclarationImpl
-    implements ConfigurationDeclaration
-{
-    private final Iterable<EntityAssemblyImpl> entities;
-    private final Iterable<ValueAssemblyImpl> values;
-
-    public ConfigurationDeclarationImpl( Iterable<EntityAssemblyImpl> entities, Iterable<ValueAssemblyImpl> values  )
-    {
-        this.entities = entities;
-        this.values = values;
-    }
-
-    @Override
-    public ConfigurationDeclaration setMetaInfo( Object info )
-    {
-        for( EntityAssemblyImpl entity : entities )
-        {
-            entity.metaInfo.set( info );
-        }
-        for( ValueAssemblyImpl value : values )
-        {
-            value.metaInfo.set( info );
-        }
-        return this;
-    }
-
-    @Override
-    public ConfigurationDeclaration visibleIn( Visibility visibility )
-    {
-        for( EntityAssemblyImpl entity : entities )
-        {
-            entity.visibility = visibility;
-        }
-        for( ValueAssemblyImpl value : values )
-        {
-            value.visibility = visibility;
-        }
-        return this;
-    }
-
-    @Override
-    public ConfigurationDeclaration withConcerns( Class<?>... concerns )
-    {
-        for( EntityAssemblyImpl entity : entities )
-        {
-            entity.concerns.addAll( asList( concerns ) );
-        }
-        for( ValueAssemblyImpl value : values )
-        {
-            value.concerns.addAll( asList( concerns ) );
-        }
-        return this;
-    }
-
-    @Override
-    public ConfigurationDeclaration withSideEffects( Class<?>... sideEffects )
-    {
-        for( EntityAssemblyImpl entity : entities )
-        {
-            entity.sideEffects.addAll( asList( sideEffects ) );
-        }
-        for( ValueAssemblyImpl value : values )
-        {
-            value.sideEffects.addAll( asList( sideEffects ) );
-        }
-        return this;
-    }
-
-    @Override
-    public ConfigurationDeclaration withMixins( Class<?>... mixins )
-    {
-        for( EntityAssemblyImpl entity : entities )
-        {
-            entity.mixins.addAll( asList( mixins ) );
-        }
-        for( ValueAssemblyImpl value : values )
-        {
-            value.mixins.addAll( asList( mixins ) );
-        }
-        return this;
-    }
-
-    @Override
-    public ConfigurationDeclaration withTypes( Class<?>... types )
-    {
-        for( EntityAssemblyImpl entity : entities )
-        {
-            entity.types.addAll( asList( types ) );
-        }
-        for( ValueAssemblyImpl value : values )
-        {
-            value.types.addAll( asList( types ) );
-        }
-        return this;
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/EntityAssemblyImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/EntityAssemblyImpl.java
deleted file mode 100644
index e74f63c..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/EntityAssemblyImpl.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (c) 2007-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.bootstrap;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Member;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.GenericAssociationInfo;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.common.InvalidApplicationException;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.GenericPropertyInfo;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.util.Annotations;
-import org.qi4j.api.util.Classes;
-import org.qi4j.bootstrap.AssociationDeclarations;
-import org.qi4j.bootstrap.EntityAssembly;
-import org.qi4j.bootstrap.ManyAssociationDeclarations;
-import org.qi4j.bootstrap.NamedAssociationDeclarations;
-import org.qi4j.bootstrap.StateDeclarations;
-import org.qi4j.runtime.association.AssociationModel;
-import org.qi4j.runtime.association.AssociationsModel;
-import org.qi4j.runtime.association.ManyAssociationModel;
-import org.qi4j.runtime.association.ManyAssociationsModel;
-import org.qi4j.runtime.association.NamedAssociationModel;
-import org.qi4j.runtime.association.NamedAssociationsModel;
-import org.qi4j.runtime.composite.MixinsModel;
-import org.qi4j.runtime.composite.StateModel;
-import org.qi4j.runtime.composite.ValueConstraintsInstance;
-import org.qi4j.runtime.composite.ValueConstraintsModel;
-import org.qi4j.runtime.entity.EntityMixinsModel;
-import org.qi4j.runtime.entity.EntityModel;
-import org.qi4j.runtime.entity.EntityStateModel;
-import org.qi4j.runtime.property.PropertyModel;
-
-import static org.qi4j.api.util.Annotations.isType;
-import static org.qi4j.api.util.Classes.typeOf;
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Declaration of a EntityComposite.
- */
-public final class EntityAssemblyImpl
-    extends CompositeAssemblyImpl
-    implements EntityAssembly
-{
-    private AssociationDeclarations associationDeclarations;
-    private ManyAssociationDeclarations manyAssociationDeclarations;
-    private NamedAssociationDeclarations namedAssociationDeclarations;
-    private AssociationsModel associationsModel;
-    private ManyAssociationsModel manyAssociationsModel;
-    private NamedAssociationsModel namedAssociationsModel;
-
-    public EntityAssemblyImpl( Class<?> entityType )
-    {
-        super( entityType );
-        // The composite must always implement EntityComposite, as a marker interface
-        if( !EntityComposite.class.isAssignableFrom( entityType ) )
-        {
-            types.add( EntityComposite.class );
-        }
-    }
-
-    @Override
-    protected MixinsModel createMixinsModel()
-    {
-        return new EntityMixinsModel();
-    }
-
-    @Override
-    protected StateModel createStateModel()
-    {
-        return new EntityStateModel( propertiesModel, associationsModel, manyAssociationsModel, namedAssociationsModel );
-    }
-
-    EntityModel newEntityModel(
-        StateDeclarations stateDeclarations,
-        AssociationDeclarations associationDecs,
-        ManyAssociationDeclarations manyAssociationDecs,
-        NamedAssociationDeclarations namedAssociationDecs,
-        AssemblyHelper helper
-    )
-    {
-        this.associationDeclarations = associationDecs;
-        this.manyAssociationDeclarations = manyAssociationDecs;
-        this.namedAssociationDeclarations = namedAssociationDecs;
-        try
-        {
-            associationsModel = new AssociationsModel();
-            manyAssociationsModel = new ManyAssociationsModel();
-            namedAssociationsModel = new NamedAssociationsModel();
-            buildComposite( helper, stateDeclarations );
-
-            EntityModel entityModel = new EntityModel(
-                types, visibility, metaInfo, (EntityMixinsModel) mixinsModel, (EntityStateModel) stateModel, compositeMethodsModel );
-
-            return entityModel;
-        }
-        catch( Exception e )
-        {
-            throw new InvalidApplicationException( "Could not register " + types, e );
-        }
-    }
-
-    @Override
-    protected void addStateFor( AccessibleObject accessor,
-                                Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
-    )
-    {
-        String stateName = QualifiedName.fromAccessor( accessor ).name();
-
-        if( registeredStateNames.contains( stateName ) )
-        {
-            return; // Skip already registered names
-        }
-
-        Class<?> accessorType = Classes.RAW_CLASS.map( typeOf( accessor ) );
-        if( Property.class.isAssignableFrom( accessorType ) )
-        {
-            propertiesModel.addProperty( newPropertyModel( accessor, constraintClasses ) );
-            registeredStateNames.add( stateName );
-        }
-        else if( Association.class.isAssignableFrom( accessorType ) )
-        {
-            associationsModel.addAssociation( newAssociationModel( accessor, constraintClasses ) );
-            registeredStateNames.add( stateName );
-        }
-        else if( ManyAssociation.class.isAssignableFrom( accessorType ) )
-        {
-            manyAssociationsModel.addManyAssociation( newManyAssociationModel( accessor, constraintClasses ) );
-            registeredStateNames.add( stateName );
-        }
-        else if( NamedAssociation.class.isAssignableFrom( accessorType ) )
-        {
-            namedAssociationsModel.addNamedAssociation( newNamedAssociationModel( accessor, constraintClasses ) );
-            registeredStateNames.add( stateName );
-        }
-    }
-
-    @Override
-    protected PropertyModel newPropertyModel( AccessibleObject accessor,
-                                              Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
-    )
-    {
-        Iterable<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
-        boolean optional = first( filter( isType( Optional.class ), annotations ) ) != null;
-        ValueConstraintsModel valueConstraintsModel = constraintsFor( annotations, GenericPropertyInfo.propertyTypeOf( accessor ), ( (Member) accessor )
-            .getName(), optional, constraintClasses, accessor );
-        ValueConstraintsInstance valueConstraintsInstance = null;
-        if( valueConstraintsModel.isConstrained() )
-        {
-            valueConstraintsInstance = valueConstraintsModel.newInstance();
-        }
-        MetaInfo metaInfo = stateDeclarations.metaInfoFor( accessor );
-        Object defaultValue = stateDeclarations.initialValueOf( accessor );
-        boolean useDefaults = metaInfo.get( UseDefaults.class ) != null || stateDeclarations.useDefaults( accessor );
-        boolean immutable = this.immutable || metaInfo.get( Immutable.class ) != null;
-        PropertyModel propertyModel = new PropertyModel( accessor, immutable, useDefaults, valueConstraintsInstance, metaInfo, defaultValue );
-        return propertyModel;
-    }
-
-    public AssociationModel newAssociationModel( AccessibleObject accessor,
-                                                 Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
-    )
-    {
-        Iterable<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
-        boolean optional = first( filter( isType( Optional.class ), annotations ) ) != null;
-
-        // Constraints for Association references
-        ValueConstraintsModel valueConstraintsModel = constraintsFor( annotations, GenericAssociationInfo
-            .associationTypeOf( accessor ), ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
-        ValueConstraintsInstance valueConstraintsInstance = null;
-        if( valueConstraintsModel.isConstrained() )
-        {
-            valueConstraintsInstance = valueConstraintsModel.newInstance();
-        }
-
-        // Constraints for the Association itself
-        valueConstraintsModel = constraintsFor( annotations, Association.class, ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
-        ValueConstraintsInstance associationValueConstraintsInstance = null;
-        if( valueConstraintsModel.isConstrained() )
-        {
-            associationValueConstraintsInstance = valueConstraintsModel.newInstance();
-        }
-
-        MetaInfo metaInfo = associationDeclarations.metaInfoFor( accessor );
-        AssociationModel associationModel = new AssociationModel( accessor, valueConstraintsInstance, associationValueConstraintsInstance, metaInfo );
-        return associationModel;
-    }
-
-    public ManyAssociationModel newManyAssociationModel( AccessibleObject accessor,
-                                                         Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
-    )
-    {
-        Iterable<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
-        boolean optional = first( filter( isType( Optional.class ), annotations ) ) != null;
-
-        // Constraints for entities in ManyAssociation
-        ValueConstraintsModel valueConstraintsModel = constraintsFor( annotations, GenericAssociationInfo
-            .associationTypeOf( accessor ), ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
-        ValueConstraintsInstance valueConstraintsInstance = null;
-        if( valueConstraintsModel.isConstrained() )
-        {
-            valueConstraintsInstance = valueConstraintsModel.newInstance();
-        }
-
-        // Constraints for the ManyAssociation itself
-        valueConstraintsModel = constraintsFor( annotations, ManyAssociation.class, ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
-        ValueConstraintsInstance manyValueConstraintsInstance = null;
-        if( valueConstraintsModel.isConstrained() )
-        {
-            manyValueConstraintsInstance = valueConstraintsModel.newInstance();
-        }
-        MetaInfo metaInfo = manyAssociationDeclarations.metaInfoFor( accessor );
-        ManyAssociationModel associationModel = new ManyAssociationModel( accessor, valueConstraintsInstance, manyValueConstraintsInstance, metaInfo );
-        return associationModel;
-    }
-
-    public NamedAssociationModel newNamedAssociationModel( AccessibleObject accessor,
-                                                           Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
-    )
-    {
-        Iterable<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
-        boolean optional = first( filter( isType( Optional.class ), annotations ) ) != null;
-
-        // Constraints for entities in NamedAssociation
-        ValueConstraintsModel valueConstraintsModel = constraintsFor( annotations, GenericAssociationInfo
-            .associationTypeOf( accessor ), ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
-        ValueConstraintsInstance valueConstraintsInstance = null;
-        if( valueConstraintsModel.isConstrained() )
-        {
-            valueConstraintsInstance = valueConstraintsModel.newInstance();
-        }
-
-        // Constraints for the NamedAssociation itself
-        valueConstraintsModel = constraintsFor( annotations, NamedAssociation.class, ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
-        ValueConstraintsInstance namedValueConstraintsInstance = null;
-        if( valueConstraintsModel.isConstrained() )
-        {
-            namedValueConstraintsInstance = valueConstraintsModel.newInstance();
-        }
-        MetaInfo metaInfo = namedAssociationDeclarations.metaInfoFor( accessor );
-        NamedAssociationModel associationModel = new NamedAssociationModel( accessor, valueConstraintsInstance, namedValueConstraintsInstance, metaInfo );
-        return associationModel;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/EntityDeclarationImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/EntityDeclarationImpl.java
deleted file mode 100644
index c92af35..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/EntityDeclarationImpl.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.EntityDeclaration;
-
-import static java.util.Arrays.asList;
-
-/**
- * Declaration of a Composite. Created by {@link org.qi4j.bootstrap.ModuleAssembly#transients(Class[])}.
- */
-public final class EntityDeclarationImpl
-    implements EntityDeclaration
-{
-    private final Iterable<EntityAssemblyImpl> entities;
-
-    public EntityDeclarationImpl( Iterable<EntityAssemblyImpl> entities )
-    {
-        this.entities = entities;
-    }
-
-    @Override
-    public EntityDeclaration setMetaInfo( Object info )
-    {
-        for( EntityAssemblyImpl entity : entities )
-        {
-            entity.metaInfo.set( info );
-        }
-        return this;
-    }
-
-    @Override
-    public EntityDeclaration visibleIn( Visibility visibility )
-    {
-        for( EntityAssemblyImpl entity : entities )
-        {
-            entity.visibility = visibility;
-        }
-        return this;
-    }
-
-    @Override
-    public EntityDeclaration withConcerns( Class<?>... concerns )
-    {
-        for( EntityAssemblyImpl entity : entities )
-        {
-            entity.concerns.addAll( asList( concerns ) );
-        }
-        return this;
-    }
-
-    @Override
-    public EntityDeclaration withSideEffects( Class<?>... sideEffects )
-    {
-        for( EntityAssemblyImpl entity : entities )
-        {
-            entity.sideEffects.addAll( asList( sideEffects ) );
-        }
-        return this;
-    }
-
-    @Override
-    public EntityDeclaration withMixins( Class<?>... mixins )
-    {
-        for( EntityAssemblyImpl entity : entities )
-        {
-            entity.mixins.addAll( asList( mixins ) );
-        }
-        return this;
-    }
-
-    @Override
-    public EntityDeclaration withTypes( Class<?>... types )
-    {
-        for( EntityAssemblyImpl entity : entities )
-        {
-            entity.types.addAll( asList( types ) );
-        }
-        return this;
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ImplementsMethodAppliesToFilter.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ImplementsMethodAppliesToFilter.java
deleted file mode 100644
index ea580ff..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ImplementsMethodAppliesToFilter.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import org.qi4j.api.common.AppliesToFilter;
-
-/**
- * JAVADOC
- */
-final class ImplementsMethodAppliesToFilter
-    implements AppliesToFilter
-{
-    @Override
-    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
-    {
-        try
-        {
-            return !Modifier.isAbstract( fragmentClass.getMethod( method.getName(), method.getParameterTypes() )
-                                             .getModifiers() );
-        }
-        catch( NoSuchMethodException e )
-        {
-            return false;
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ImportedServiceAssemblyImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ImportedServiceAssemblyImpl.java
deleted file mode 100644
index 97b36d5..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ImportedServiceAssemblyImpl.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.common.InvalidApplicationException;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.service.importer.InstanceImporter;
-import org.qi4j.bootstrap.ImportedServiceAssembly;
-import org.qi4j.functional.Iterables;
-import org.qi4j.runtime.activation.ActivatorsModel;
-import org.qi4j.runtime.service.ImportedServiceModel;
-
-/**
- * Declaration of an imported Service.
- *
- * Created by {@link org.qi4j.runtime.bootstrap.ModuleAssemblyImpl#importedServices(Class[])}.
- */
-public final class ImportedServiceAssemblyImpl
-    implements ImportedServiceAssembly
-{
-    private final Class<?> serviceType;
-    private final ModuleAssemblyImpl moduleAssembly;
-    @SuppressWarnings( "raw" )
-    Class<? extends ServiceImporter> serviceProvider = InstanceImporter.class;
-    String identity;
-    boolean importOnStartup = false;
-    MetaInfo metaInfo = new MetaInfo();
-    Visibility visibility = Visibility.module;
-    List<Class<? extends Activator<?>>> activators = new ArrayList<>();
-
-    public ImportedServiceAssemblyImpl( Class<?> serviceType, ModuleAssemblyImpl moduleAssembly )
-    {
-        this.serviceType = serviceType;
-        this.moduleAssembly = moduleAssembly;
-    }
-
-    @Override
-    public Iterable<Class<?>> types()
-    {
-        return Iterables.<Class<?>>iterable( serviceType );
-    }
-
-    @SuppressWarnings( {"raw", "unchecked"} )
-    void addImportedServiceModel( List<ImportedServiceModel> serviceModels )
-    {
-        try
-        {
-            String id = identity;
-            if( id == null )
-            {
-                id = generateId( serviceModels, serviceType );
-            }
-
-            ImportedServiceModel serviceModel = new ImportedServiceModel( serviceType,
-                                                                          visibility,
-                                                                          serviceProvider,
-                                                                          id,
-                                                                          importOnStartup,
-                                                                          new MetaInfo( metaInfo ).withAnnotations( serviceType ),
-                                                                          new ActivatorsModel( activators ),
-                                                                          moduleAssembly.name() );
-            serviceModels.add( serviceModel );
-        }
-        catch( Exception e )
-        {
-            throw new InvalidApplicationException( "Could not register " + serviceType.getName(), e );
-        }
-    }
-
-    @SuppressWarnings( "raw" )
-    private String generateId( List<ImportedServiceModel> serviceModels, Class serviceType )
-    {
-        // Find identity that is not yet used
-        int idx = 0;
-        String id = serviceType.getSimpleName();
-        boolean invalid;
-        do
-        {
-            invalid = false;
-            for( ImportedServiceModel serviceModel : serviceModels )
-            {
-                if( serviceModel.identity().equals( id ) )
-                {
-                    idx++;
-                    id = serviceType.getSimpleName() + "_" + idx;
-                    invalid = true;
-                    break;
-                }
-            }
-        }
-        while( invalid );
-        return id;
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ImportedServiceDeclarationImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ImportedServiceDeclarationImpl.java
deleted file mode 100644
index 57eaaeb..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ImportedServiceDeclarationImpl.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.service.qualifier.ServiceTags;
-import org.qi4j.bootstrap.ImportedServiceDeclaration;
-
-/**
- * Declaration of an imported Service.
- */
-public final class ImportedServiceDeclarationImpl
-    implements ImportedServiceDeclaration
-{
-    private final Iterable<ImportedServiceAssemblyImpl> assemblies;
-
-    public ImportedServiceDeclarationImpl( Iterable<ImportedServiceAssemblyImpl> assemblies )
-    {
-        this.assemblies = assemblies;
-    }
-
-    @Override
-    public ImportedServiceDeclaration importOnStartup()
-    {
-        for( ImportedServiceAssemblyImpl assembly : assemblies )
-        {
-            assembly.importOnStartup = true;
-        }
-        return this;
-    }
-
-    @Override
-    public ImportedServiceDeclaration visibleIn( Visibility visibility )
-    {
-        for( ImportedServiceAssemblyImpl assembly : assemblies )
-        {
-            assembly.visibility = visibility;
-        }
-        return this;
-    }
-
-    @Override
-    @SuppressWarnings( "raw" )
-    public ImportedServiceDeclaration importedBy( Class<? extends ServiceImporter> sip )
-    {
-        for( ImportedServiceAssemblyImpl assembly : assemblies )
-        {
-            assembly.serviceProvider = sip;
-        }
-        return this;
-    }
-
-    @Override
-    public ImportedServiceDeclaration identifiedBy( String identity )
-    {
-        for( ImportedServiceAssemblyImpl assembly : assemblies )
-        {
-            assembly.identity = identity;
-        }
-        return this;
-    }
-
-    @Override
-    public ImportedServiceDeclaration taggedWith( String... tags )
-    {
-        for( ImportedServiceAssemblyImpl serviceAssembly : assemblies )
-        {
-            ServiceTags previousTags = serviceAssembly.metaInfo.get( ServiceTags.class );
-            if( previousTags != null )
-            {
-                List<String> tagList = new ArrayList<>();
-                Collections.addAll( tagList, previousTags.tags() );
-                Collections.addAll( tagList, tags );
-                serviceAssembly.metaInfo.set( new ServiceTags( tagList.toArray( new String[ tagList.size() ] ) ) );
-            }
-            else
-            {
-                serviceAssembly.metaInfo.set( new ServiceTags( tags ) );
-            }
-        }
-
-        return this;
-    }
-
-    @Override
-    public ImportedServiceDeclaration setMetaInfo( Object serviceAttribute )
-    {
-        for( ImportedServiceAssemblyImpl assembly : assemblies )
-        {
-            assembly.metaInfo.set( serviceAttribute );
-        }
-        return this;
-    }
-
-    @Override
-    @SafeVarargs
-    public final ImportedServiceDeclaration withActivators( Class<? extends Activator<?>>... activators )
-    {
-        for ( ImportedServiceAssemblyImpl serviceAssembly : assemblies ) {
-            serviceAssembly.activators.addAll( Arrays.asList( activators ) );
-        }
-        return this;
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/LayerAssemblyImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/LayerAssemblyImpl.java
deleted file mode 100644
index 8853f92..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/LayerAssemblyImpl.java
+++ /dev/null
@@ -1,625 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.structure.Layer;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.AssemblyVisitor;
-import org.qi4j.bootstrap.EntityAssembly;
-import org.qi4j.bootstrap.EntityDeclaration;
-import org.qi4j.bootstrap.ImportedServiceAssembly;
-import org.qi4j.bootstrap.ImportedServiceDeclaration;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ObjectAssembly;
-import org.qi4j.bootstrap.ObjectDeclaration;
-import org.qi4j.bootstrap.ServiceAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.bootstrap.TransientAssembly;
-import org.qi4j.bootstrap.TransientDeclaration;
-import org.qi4j.bootstrap.ValueAssembly;
-import org.qi4j.bootstrap.ValueDeclaration;
-import org.qi4j.functional.Specification;
-
-/**
- * Assembly of a Layer. From here you can create more ModuleAssemblies for
- * the Layer that is being assembled. It is also here that you define
- * what other Layers this Layer is using by calling {@link org.qi4j.runtime.bootstrap.LayerAssemblyImpl#uses()}.
- */
-public final class LayerAssemblyImpl
-    implements LayerAssembly
-{
-    private final ApplicationAssembly applicationAssembly;
-    private final HashMap<String, ModuleAssemblyImpl> moduleAssemblies;
-    private final Set<LayerAssembly> uses;
-
-    private String name;
-    private final MetaInfo metaInfo = new MetaInfo();
-    private final List<Class<? extends Activator<Layer>>> activators = new ArrayList<>();
-
-    public LayerAssemblyImpl( ApplicationAssembly applicationAssembly, String name )
-    {
-        this.applicationAssembly = applicationAssembly;
-        this.name = name;
-
-        moduleAssemblies = new LinkedHashMap<>();
-        uses = new LinkedHashSet<>();
-    }
-
-    @Override
-    public ModuleAssembly module( String name )
-    {
-        if( name != null )
-        {
-            ModuleAssemblyImpl existing = moduleAssemblies.get( name );
-            if( existing != null )
-            {
-                return existing;
-            }
-        }
-        ModuleAssemblyImpl moduleAssembly = new ModuleAssemblyImpl( this, name );
-        moduleAssemblies.put( name, moduleAssembly );
-        return moduleAssembly;
-    }
-
-    @Override
-    public ApplicationAssembly application()
-    {
-        return applicationAssembly;
-    }
-
-    @Override
-    public LayerAssembly setName( String name )
-    {
-        this.name = name;
-        return this;
-    }
-
-    @Override
-    public LayerAssembly setMetaInfo( Object info )
-    {
-        metaInfo.set( info );
-        return this;
-    }
-
-    @Override
-    public LayerAssembly uses( LayerAssembly... layerAssembly )
-        throws IllegalArgumentException
-    {
-        uses.addAll( Arrays.asList( layerAssembly ) );
-        return this;
-    }
-
-    @Override
-    @SafeVarargs
-    public final LayerAssembly withActivators( Class<? extends Activator<Layer>>... activators )
-    {
-        this.activators.addAll( Arrays.asList( activators ) );
-        return this;
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> void visit( AssemblyVisitor<ThrowableType> visitor )
-        throws ThrowableType
-    {
-        visitor.visitLayer( this );
-        for( ModuleAssemblyImpl moduleAssembly : moduleAssemblies.values() )
-        {
-            moduleAssembly.visit( visitor );
-        }
-    }
-
-    @Override
-    public EntityDeclaration entities( Specification<? super EntityAssembly> specification )
-    {
-        final List<EntityDeclaration> declarations = new ArrayList<>();
-
-        for( ModuleAssemblyImpl moduleAssembly : moduleAssemblies.values() )
-        {
-            declarations.add( moduleAssembly.entities( specification ) );
-        }
-
-        return new EntityDeclaration()
-        {
-            @Override
-            public EntityDeclaration setMetaInfo( Object info )
-            {
-                for( EntityDeclaration declaration : declarations )
-                {
-                    declaration.setMetaInfo( info );
-                }
-                return this;
-            }
-
-            @Override
-            public EntityDeclaration visibleIn( Visibility visibility )
-            {
-                for( EntityDeclaration declaration : declarations )
-                {
-                    declaration.visibleIn( visibility );
-                }
-                return this;
-            }
-
-            @Override
-            public EntityDeclaration withConcerns( Class<?>... concerns )
-            {
-                for( EntityDeclaration declaration : declarations )
-                {
-                    declaration.withConcerns( concerns );
-                }
-                return this;
-            }
-
-            @Override
-            public EntityDeclaration withSideEffects( Class<?>... sideEffects )
-            {
-                for( EntityDeclaration declaration : declarations )
-                {
-                    declaration.withSideEffects( sideEffects );
-                }
-                return this;
-            }
-
-            @Override
-            public EntityDeclaration withMixins( Class<?>... mixins )
-            {
-                for( EntityDeclaration declaration : declarations )
-                {
-                    declaration.withMixins( mixins );
-                }
-                return this;
-            }
-
-            @Override
-            public EntityDeclaration withTypes( Class<?>... types )
-            {
-                for( EntityDeclaration declaration : declarations )
-                {
-                    declaration.withTypes( types );
-                }
-                return this;
-            }
-        };
-    }
-
-    @Override
-    public ServiceDeclaration services( Specification<? super ServiceAssembly> specification )
-    {
-        final List<ServiceDeclaration> declarations = new ArrayList<>();
-
-        for( ModuleAssemblyImpl moduleAssembly : moduleAssemblies.values() )
-        {
-            declarations.add( moduleAssembly.services( specification ) );
-        }
-
-        return new ServiceDeclaration()
-        {
-            @Override
-            public ServiceDeclaration setMetaInfo( Object serviceAttribute )
-            {
-                for( ServiceDeclaration declaration : declarations )
-                {
-                    declaration.setMetaInfo( serviceAttribute );
-                }
-                return this;
-            }
-
-            @Override
-            public ServiceDeclaration visibleIn( Visibility visibility )
-            {
-                for( ServiceDeclaration declaration : declarations )
-                {
-                    declaration.visibleIn( visibility );
-                }
-                return this;
-            }
-
-            @Override
-            public ServiceDeclaration withConcerns( Class<?>... concerns )
-            {
-                for( ServiceDeclaration declaration : declarations )
-                {
-                    declaration.withConcerns( concerns );
-                }
-                return this;
-            }
-
-            @Override
-            public ServiceDeclaration withSideEffects( Class<?>... sideEffects )
-            {
-                for( ServiceDeclaration declaration : declarations )
-                {
-                    declaration.withSideEffects( sideEffects );
-                }
-                return this;
-            }
-
-            @Override
-            public ServiceDeclaration withMixins( Class<?>... mixins )
-            {
-                for( ServiceDeclaration declaration : declarations )
-                {
-                    declaration.withMixins( mixins );
-                }
-                return this;
-            }
-
-            @Override
-            public ServiceDeclaration withTypes( Class<?>... types )
-            {
-                for( ServiceDeclaration declaration : declarations )
-                {
-                    declaration.withTypes( types );
-                }
-                return this;
-            }
-
-            @Override
-            @SafeVarargs
-            public final ServiceDeclaration withActivators( Class<? extends Activator<?>>... activators )
-            {
-                for( ServiceDeclaration declaration : declarations )
-                {
-                    declaration.withActivators( activators );
-                }
-                return this;
-            }
-
-            @Override
-            public ServiceDeclaration identifiedBy( String identity )
-            {
-                for( ServiceDeclaration declaration : declarations )
-                {
-                    declaration.identifiedBy( identity );
-                }
-                return this;
-            }
-
-            @Override
-            public ServiceDeclaration taggedWith( String... tags )
-            {
-                for( ServiceDeclaration declaration : declarations )
-                {
-                    declaration.taggedWith( tags );
-                }
-                return this;
-            }
-
-            @Override
-            public ServiceDeclaration instantiateOnStartup()
-            {
-                for( ServiceDeclaration declaration : declarations )
-                {
-                    declaration.instantiateOnStartup();
-                }
-
-                return this;
-            }
-        };
-    }
-
-    @Override
-    public TransientDeclaration transients( Specification<? super TransientAssembly> specification )
-    {
-        final List<TransientDeclaration> declarations = new ArrayList<>();
-
-        for( ModuleAssemblyImpl moduleAssembly : moduleAssemblies.values() )
-        {
-            declarations.add( moduleAssembly.transients( specification ) );
-        }
-
-        return new TransientDeclaration()
-        {
-            @Override
-            public TransientDeclaration setMetaInfo( Object info )
-            {
-                for( TransientDeclaration declaration : declarations )
-                {
-                    declaration.setMetaInfo( info );
-                }
-                return this;
-            }
-
-            @Override
-            public TransientDeclaration visibleIn( Visibility visibility )
-            {
-                for( TransientDeclaration declaration : declarations )
-                {
-                    declaration.visibleIn( visibility );
-                }
-                return this;
-            }
-
-            @Override
-            public TransientDeclaration withConcerns( Class<?>... concerns )
-            {
-                for( TransientDeclaration declaration : declarations )
-                {
-                    declaration.withConcerns( concerns );
-                }
-                return this;
-            }
-
-            @Override
-            public TransientDeclaration withSideEffects( Class<?>... sideEffects )
-            {
-                for( TransientDeclaration declaration : declarations )
-                {
-                    declaration.withSideEffects( sideEffects );
-                }
-                return this;
-            }
-
-            @Override
-            public TransientDeclaration withMixins( Class<?>... mixins )
-            {
-                for( TransientDeclaration declaration : declarations )
-                {
-                    declaration.withMixins( mixins );
-                }
-                return this;
-            }
-
-            @Override
-            public TransientDeclaration withTypes( Class<?>... types )
-            {
-                for( TransientDeclaration declaration : declarations )
-                {
-                    declaration.withTypes( types );
-                }
-                return this;
-            }
-        };
-    }
-
-    @Override
-    public ValueDeclaration values( Specification<? super ValueAssembly> specification )
-    {
-        final List<ValueDeclaration> declarations = new ArrayList<>();
-
-        for( ModuleAssemblyImpl moduleAssembly : moduleAssemblies.values() )
-        {
-            declarations.add( moduleAssembly.values( specification ) );
-        }
-        return new ValueDeclaration()
-        {
-            @Override
-            public ValueDeclaration setMetaInfo( Object info )
-            {
-                for( ValueDeclaration declaration : declarations )
-                {
-                    declaration.setMetaInfo( info );
-                }
-                return this;
-            }
-
-            @Override
-            public ValueDeclaration visibleIn( Visibility visibility )
-            {
-                for( ValueDeclaration declaration : declarations )
-                {
-                    declaration.visibleIn( visibility );
-                }
-                return this;
-            }
-
-            @Override
-            public ValueDeclaration withConcerns( Class<?>... concerns )
-            {
-                for( ValueDeclaration declaration : declarations )
-                {
-                    declaration.withConcerns( concerns );
-                }
-                return this;
-            }
-
-            @Override
-            public ValueDeclaration withSideEffects( Class<?>... sideEffects )
-            {
-                for( ValueDeclaration declaration : declarations )
-                {
-                    declaration.withSideEffects( sideEffects );
-                }
-                return this;
-            }
-
-            @Override
-            public ValueDeclaration withMixins( Class<?>... mixins )
-            {
-                for( ValueDeclaration declaration : declarations )
-                {
-                    declaration.withMixins( mixins );
-                }
-                return this;
-            }
-
-            @Override
-            public ValueDeclaration withTypes( Class<?>... types )
-            {
-                for( ValueDeclaration declaration : declarations )
-                {
-                    declaration.withTypes( types );
-                }
-                return this;
-            }
-        };
-    }
-
-    @Override
-    public ObjectDeclaration objects( Specification<? super ObjectAssembly> specification )
-    {
-        final List<ObjectDeclaration> declarations = new ArrayList<>();
-
-        for( ModuleAssemblyImpl moduleAssembly : moduleAssemblies.values() )
-        {
-            declarations.add( moduleAssembly.objects( specification ) );
-        }
-        return new ObjectDeclaration()
-        {
-            @Override
-            public ObjectDeclaration setMetaInfo( Object info )
-            {
-                for( ObjectDeclaration declaration : declarations )
-                {
-                    declaration.setMetaInfo( info );
-                }
-                return this;
-            }
-
-            @Override
-            public ObjectDeclaration visibleIn( Visibility visibility )
-                throws IllegalStateException
-            {
-                for( ObjectDeclaration declaration : declarations )
-                {
-                    declaration.visibleIn( visibility );
-                }
-                return this;
-            }
-        };
-    }
-
-    @Override
-    public ImportedServiceDeclaration importedServices( Specification<? super ImportedServiceAssembly> specification )
-    {
-        final List<ImportedServiceDeclaration> declarations = new ArrayList<>();
-
-        for( ModuleAssemblyImpl moduleAssembly : moduleAssemblies.values() )
-        {
-            declarations.add( moduleAssembly.importedServices( specification ) );
-        }
-        return new ImportedServiceDeclaration()
-        {
-
-            @Override
-            public ImportedServiceDeclaration importOnStartup()
-            {
-                for( ImportedServiceDeclaration declaration : declarations )
-                {
-                    declaration.importOnStartup();
-                }
-                return this;
-            }
-
-            @Override
-            public ImportedServiceDeclaration visibleIn( Visibility visibility )
-            {
-                for( ImportedServiceDeclaration declaration : declarations )
-                {
-                    declaration.visibleIn( visibility );
-                }
-                return this;
-            }
-
-            @Override
-            public ImportedServiceDeclaration importedBy( Class<? extends ServiceImporter> serviceImporterClass )
-            {
-                for( ImportedServiceDeclaration declaration : declarations )
-                {
-                    declaration.importedBy( serviceImporterClass );
-                }
-                return this;
-            }
-
-            @Override
-            public ImportedServiceDeclaration identifiedBy( String identity )
-            {
-                for( ImportedServiceDeclaration declaration : declarations )
-                {
-                    declaration.identifiedBy( identity );
-                }
-                return this;
-            }
-
-            @Override
-            public ImportedServiceDeclaration taggedWith( String... tags )
-            {
-                for( ImportedServiceDeclaration declaration : declarations )
-                {
-                    declaration.taggedWith( tags );
-                }
-                return this;
-            }
-
-            @Override
-            public ImportedServiceDeclaration setMetaInfo( Object serviceAttribute )
-            {
-                for( ImportedServiceDeclaration declaration : declarations )
-                {
-                    declaration.setMetaInfo( serviceAttribute );
-                }
-                return this;
-            }
-
-            @Override
-            @SafeVarargs
-            public final ImportedServiceDeclaration withActivators( Class<? extends Activator<?>>... activators )
-            {
-                for( ImportedServiceDeclaration declaration : declarations )
-                {
-                    declaration.withActivators( activators );
-                }
-                return this;
-            }
-
-        };
-    }
-
-    Collection<ModuleAssemblyImpl> moduleAssemblies()
-    {
-        return moduleAssemblies.values();
-    }
-
-    Set<LayerAssembly> uses()
-    {
-        return uses;
-    }
-
-    public MetaInfo metaInfo()
-    {
-        return metaInfo;
-    }
-
-    @Override
-    public String name()
-    {
-        return name;
-    }
-
-    public List<Class<? extends Activator<Layer>>> activators()
-    {
-        return activators;
-    }
-
-    @Override
-    public final String toString()
-    {
-        return "LayerAssembly [" + name + "]";
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ModuleAssemblyImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ModuleAssemblyImpl.java
deleted file mode 100644
index 1f470dc..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ModuleAssemblyImpl.java
+++ /dev/null
@@ -1,635 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.service.DuplicateServiceIdentityException;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.type.HasTypes;
-import org.qi4j.api.type.MatchTypeSpecification;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.AssemblySpecifications;
-import org.qi4j.bootstrap.AssemblyVisitor;
-import org.qi4j.bootstrap.ConfigurationDeclaration;
-import org.qi4j.bootstrap.EntityAssembly;
-import org.qi4j.bootstrap.EntityDeclaration;
-import org.qi4j.bootstrap.ImportedServiceAssembly;
-import org.qi4j.bootstrap.ImportedServiceDeclaration;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.MetaInfoDeclaration;
-import org.qi4j.bootstrap.MixinDeclaration;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ObjectAssembly;
-import org.qi4j.bootstrap.ObjectDeclaration;
-import org.qi4j.bootstrap.ServiceAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.bootstrap.TransientAssembly;
-import org.qi4j.bootstrap.TransientDeclaration;
-import org.qi4j.bootstrap.ValueAssembly;
-import org.qi4j.bootstrap.ValueDeclaration;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.Specifications;
-import org.qi4j.runtime.activation.ActivatorsModel;
-import org.qi4j.runtime.composite.TransientModel;
-import org.qi4j.runtime.composite.TransientsModel;
-import org.qi4j.runtime.entity.EntitiesModel;
-import org.qi4j.runtime.entity.EntityModel;
-import org.qi4j.runtime.object.ObjectModel;
-import org.qi4j.runtime.object.ObjectsModel;
-import org.qi4j.runtime.service.ImportedServiceModel;
-import org.qi4j.runtime.service.ImportedServicesModel;
-import org.qi4j.runtime.service.ServiceModel;
-import org.qi4j.runtime.service.ServicesModel;
-import org.qi4j.runtime.structure.ModuleModel;
-import org.qi4j.runtime.value.ValueModel;
-import org.qi4j.runtime.value.ValuesModel;
-
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.iterable;
-
-/**
- * Assembly of a Module. This is where you register all objects, Composites,
- * Services. Each "add" method returns a declaration that you can use to add
- * additional information and metadata. If you call an "add" method with many
- * parameters then the declared metadata will apply to all types in the method
- * call.
- */
-public final class ModuleAssemblyImpl
-    implements ModuleAssembly
-{
-    private final LayerAssembly layerAssembly;
-    private String name;
-    private final MetaInfo metaInfo = new MetaInfo();
-    private final List<Class<? extends Activator<Module>>> activators = new ArrayList<>();
-
-    private final List<ServiceAssemblyImpl> serviceAssemblies = new ArrayList<>();
-    private final Map<Class<?>, ImportedServiceAssemblyImpl> importedServiceAssemblies = new LinkedHashMap<>();
-    private final Map<Class<? extends EntityComposite>, EntityAssemblyImpl> entityAssemblies = new LinkedHashMap<>();
-    private final Map<Class<? extends ValueComposite>, ValueAssemblyImpl> valueAssemblies = new LinkedHashMap<>();
-    private final Map<Class<? extends TransientComposite>, TransientAssemblyImpl> transientAssemblies = new LinkedHashMap<>();
-    private final Map<Class<?>, ObjectAssemblyImpl> objectAssemblies = new LinkedHashMap<>();
-
-    private final MetaInfoDeclaration metaInfoDeclaration = new MetaInfoDeclaration();
-
-    public ModuleAssemblyImpl( LayerAssembly layerAssembly, String name )
-    {
-        this.layerAssembly = layerAssembly;
-        this.name = name;
-    }
-
-    @Override
-    public LayerAssembly layer()
-    {
-        return layerAssembly;
-    }
-
-    @Override
-    public ModuleAssembly module( String layerName, String moduleName )
-    {
-        return layerAssembly.application().module( layerName, moduleName );
-    }
-
-    @Override
-    public ModuleAssembly setName( String name )
-    {
-        this.name = name;
-        return this;
-    }
-
-    @Override
-    public String name()
-    {
-        return name;
-    }
-
-    public ModuleAssembly setMetaInfo( Object info )
-    {
-        metaInfo.set( info );
-        return this;
-    }
-
-    @Override
-    @SafeVarargs
-    public final ModuleAssembly withActivators( Class<? extends Activator<Module>>... activators )
-    {
-        this.activators.addAll( Arrays.asList( activators ) );
-        return this;
-    }
-
-    @Override
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public ValueDeclaration values( Class<?>... valueTypes )
-    {
-        List<ValueAssemblyImpl> assemblies = new ArrayList<>();
-
-        for( Class valueType : valueTypes )
-        {
-            if( valueAssemblies.containsKey( valueType ) )
-            {
-                assemblies.add( valueAssemblies.get( valueType ) );
-            }
-            else
-            {
-                ValueAssemblyImpl valueAssembly = new ValueAssemblyImpl( valueType );
-                valueAssemblies.put( valueType, valueAssembly );
-                assemblies.add( valueAssembly );
-            }
-        }
-
-        return new ValueDeclarationImpl( assemblies );
-    }
-
-    @Override
-    public ValueDeclaration values( Specification<? super ValueAssembly> specification )
-    {
-        List<ValueAssemblyImpl> assemblies = new ArrayList<>();
-        for( ValueAssemblyImpl transientAssembly : valueAssemblies.values() )
-        {
-            if( specification.satisfiedBy( transientAssembly ) )
-            {
-                assemblies.add( transientAssembly );
-            }
-        }
-
-        return new ValueDeclarationImpl( assemblies );
-    }
-
-    @Override
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public TransientDeclaration transients( Class<?>... transientTypes )
-    {
-        List<TransientAssemblyImpl> assemblies = new ArrayList<>();
-
-        for( Class valueType : transientTypes )
-        {
-            if( transientAssemblies.containsKey( valueType ) )
-            {
-                assemblies.add( transientAssemblies.get( valueType ) );
-            }
-            else
-            {
-                TransientAssemblyImpl transientAssembly = new TransientAssemblyImpl( valueType );
-                transientAssemblies.put( valueType, transientAssembly );
-                assemblies.add( transientAssembly );
-            }
-        }
-
-        return new TransientDeclarationImpl( assemblies );
-    }
-
-    @Override
-    public TransientDeclaration transients( Specification<? super TransientAssembly> specification )
-    {
-        List<TransientAssemblyImpl> assemblies = new ArrayList<>();
-        for( TransientAssemblyImpl transientAssembly : transientAssemblies.values() )
-        {
-            if( specification.satisfiedBy( transientAssembly ) )
-            {
-                assemblies.add( transientAssembly );
-            }
-        }
-
-        return new TransientDeclarationImpl( assemblies );
-    }
-
-    @Override
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public EntityDeclaration entities( Class<?>... entityTypes )
-    {
-        List<EntityAssemblyImpl> assemblies = new ArrayList<>();
-
-        for( Class entityType : entityTypes )
-        {
-            if( entityAssemblies.containsKey( entityType ) )
-            {
-                assemblies.add( entityAssemblies.get( entityType ) );
-            }
-            else
-            {
-                EntityAssemblyImpl entityAssembly = new EntityAssemblyImpl( entityType );
-                entityAssemblies.put( entityType, entityAssembly );
-                assemblies.add( entityAssembly );
-            }
-        }
-
-        return new EntityDeclarationImpl( assemblies );
-    }
-
-    @Override
-    public EntityDeclaration entities( Specification<? super EntityAssembly> specification )
-    {
-        List<EntityAssemblyImpl> assemblies = new ArrayList<>();
-        for( EntityAssemblyImpl entityAssembly : entityAssemblies.values() )
-        {
-            if( specification.satisfiedBy( entityAssembly ) )
-            {
-                assemblies.add( entityAssembly );
-            }
-        }
-
-        return new EntityDeclarationImpl( assemblies );
-    }
-
-    @Override
-    public ConfigurationDeclaration configurations( Class<?>... configurationTypes )
-    {
-        List<EntityAssemblyImpl> entityAssemblyList = new ArrayList<>();
-
-        for( Class entityType : configurationTypes )
-        {
-            if( this.entityAssemblies.containsKey( entityType ) )
-            {
-                entityAssemblyList.add( this.entityAssemblies.get( entityType ) );
-            }
-            else
-            {
-                EntityAssemblyImpl entityAssembly = new EntityAssemblyImpl( entityType );
-                this.entityAssemblies.put( entityType, entityAssembly );
-                entityAssemblyList.add( entityAssembly );
-            }
-        }
-
-        List<ValueAssemblyImpl> valueAssemblyList = new ArrayList<>();
-
-        for( Class valueType : configurationTypes )
-        {
-            if( valueAssemblies.containsKey( valueType ) )
-            {
-                valueAssemblyList.add( valueAssemblies.get( valueType ) );
-            }
-            else
-            {
-                ValueAssemblyImpl valueAssembly = new ValueAssemblyImpl( valueType );
-                valueAssemblies.put( valueType, valueAssembly );
-                valueAssemblyList.add( valueAssembly );
-                valueAssembly.types.add( Identity.class );
-            }
-        }
-
-        return new ConfigurationDeclarationImpl( entityAssemblyList, valueAssemblyList  );
-    }
-
-    @Override
-    public ConfigurationDeclaration configurations( Specification<HasTypes> specification )
-    {
-        Specification<HasTypes> isConfigurationComposite = new MatchTypeSpecification( Identity.class );
-        specification = Specifications.and( specification, isConfigurationComposite );
-        List<EntityAssemblyImpl> entityAssmblyList = new ArrayList<>();
-        for( EntityAssemblyImpl entityAssembly : entityAssemblies.values() )
-        {
-            if( specification.satisfiedBy( entityAssembly ) )
-            {
-                entityAssmblyList.add( entityAssembly );
-            }
-        }
-        List<ValueAssemblyImpl> valueAssemblyList = new ArrayList<>();
-        for( ValueAssemblyImpl transientAssembly : valueAssemblies.values() )
-        {
-            if( specification.satisfiedBy( transientAssembly ) )
-            {
-                valueAssemblyList.add( transientAssembly );
-            }
-        }
-        return new ConfigurationDeclarationImpl( entityAssmblyList, valueAssemblyList );
-    }
-
-    @Override
-    public ObjectDeclaration objects( Class<?>... objectTypes )
-        throws AssemblyException
-    {
-        List<ObjectAssemblyImpl> assemblies = new ArrayList<>();
-
-        for( Class<?> objectType : objectTypes )
-        {
-            if( objectType.isInterface() )
-            {
-                throw new AssemblyException( "Interfaces can not be Zest Objects." );
-            }
-            if( objectAssemblies.containsKey( objectType ) )
-            {
-                assemblies.add( objectAssemblies.get( objectType ) );
-            }
-            else
-            {
-                ObjectAssemblyImpl objectAssembly = new ObjectAssemblyImpl( objectType );
-                objectAssemblies.put( objectType, objectAssembly );
-                assemblies.add( objectAssembly );
-            }
-        }
-
-        return new ObjectDeclarationImpl( assemblies );
-    }
-
-    @Override
-    public ObjectDeclaration objects( Specification<? super ObjectAssembly> specification )
-    {
-        List<ObjectAssemblyImpl> assemblies = new ArrayList<>();
-        for( ObjectAssemblyImpl objectAssembly : objectAssemblies.values() )
-        {
-            if( specification.satisfiedBy( objectAssembly ) )
-            {
-                assemblies.add( objectAssembly );
-            }
-        }
-
-        return new ObjectDeclarationImpl( assemblies );
-    }
-
-    @Override
-    public ServiceDeclaration addServices( Class<?>... serviceTypes )
-    {
-        List<ServiceAssemblyImpl> assemblies = new ArrayList<>();
-
-        for( Class<?> serviceType : serviceTypes )
-        {
-            ServiceAssemblyImpl serviceAssembly = new ServiceAssemblyImpl( serviceType );
-            serviceAssemblies.add( serviceAssembly );
-            assemblies.add( serviceAssembly );
-        }
-
-        return new ServiceDeclarationImpl( assemblies );
-    }
-
-    @Override
-    public ServiceDeclaration services( Class<?>... serviceTypes )
-    {
-        List<ServiceAssemblyImpl> assemblies = new ArrayList<>();
-
-        for( Class<?> serviceType : serviceTypes )
-        {
-            if( Iterables.matchesAny( AssemblySpecifications.types( serviceType ), serviceAssemblies ) )
-            {
-                Iterables.addAll( assemblies, Iterables.filter( AssemblySpecifications.types( serviceType ), serviceAssemblies ) );
-            }
-            else
-            {
-                ServiceAssemblyImpl serviceAssembly = new ServiceAssemblyImpl( serviceType );
-                serviceAssemblies.add( serviceAssembly );
-                assemblies.add( serviceAssembly );
-            }
-        }
-
-        return new ServiceDeclarationImpl( assemblies );
-    }
-
-    @Override
-    public ServiceDeclaration services( Specification<? super ServiceAssembly> specification )
-    {
-        List<ServiceAssemblyImpl> assemblies = new ArrayList<>();
-        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
-        {
-            if( specification.satisfiedBy( serviceAssembly ) )
-            {
-                assemblies.add( serviceAssembly );
-            }
-        }
-
-        return new ServiceDeclarationImpl( assemblies );
-    }
-
-    @Override
-    public ImportedServiceDeclaration importedServices( Class<?>... serviceTypes )
-    {
-        List<ImportedServiceAssemblyImpl> assemblies = new ArrayList<>();
-
-        for( Class<?> serviceType : serviceTypes )
-        {
-            if( importedServiceAssemblies.containsKey( serviceType ) )
-            {
-                assemblies.add( importedServiceAssemblies.get( serviceType ) );
-            }
-            else
-            {
-                ImportedServiceAssemblyImpl serviceAssembly = new ImportedServiceAssemblyImpl( serviceType, this );
-                importedServiceAssemblies.put( serviceType, serviceAssembly );
-                assemblies.add( serviceAssembly );
-            }
-        }
-
-        return new ImportedServiceDeclarationImpl( assemblies );
-    }
-
-    @Override
-    public ImportedServiceDeclaration importedServices( Specification<? super ImportedServiceAssembly> specification )
-    {
-        List<ImportedServiceAssemblyImpl> assemblies = new ArrayList<>();
-        for( ImportedServiceAssemblyImpl objectAssembly : importedServiceAssemblies.values() )
-        {
-            if( specification.satisfiedBy( objectAssembly ) )
-            {
-                assemblies.add( objectAssembly );
-            }
-        }
-
-        return new ImportedServiceDeclarationImpl( assemblies );
-    }
-
-    @Override
-    public <T> MixinDeclaration<T> forMixin( Class<T> mixinType )
-    {
-        return metaInfoDeclaration.on( mixinType );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> void visit( AssemblyVisitor<ThrowableType> visitor )
-        throws ThrowableType
-    {
-        visitor.visitModule( this );
-
-        for( TransientAssemblyImpl compositeDeclaration : transientAssemblies.values() )
-        {
-            visitor.visitComposite( new TransientDeclarationImpl( iterable( compositeDeclaration ) ) );
-        }
-
-        for( EntityAssemblyImpl entityDeclaration : entityAssemblies.values() )
-        {
-            visitor.visitEntity( new EntityDeclarationImpl( iterable( entityDeclaration ) ) );
-        }
-
-        for( ObjectAssemblyImpl objectDeclaration : objectAssemblies.values() )
-        {
-            visitor.visitObject( new ObjectDeclarationImpl( iterable( objectDeclaration ) ) );
-        }
-
-        for( ServiceAssemblyImpl serviceDeclaration : serviceAssemblies )
-        {
-            visitor.visitService( new ServiceDeclarationImpl( iterable( serviceDeclaration ) ) );
-        }
-
-        for( ImportedServiceAssemblyImpl importedServiceDeclaration : importedServiceAssemblies.values() )
-        {
-            visitor.visitImportedService( new ImportedServiceDeclarationImpl( iterable( importedServiceDeclaration ) ) );
-        }
-
-        for( ValueAssemblyImpl valueDeclaration : valueAssemblies.values() )
-        {
-            visitor.visitValue( new ValueDeclarationImpl( iterable( valueDeclaration ) ) );
-        }
-    }
-
-    ModuleModel assembleModule( AssemblyHelper helper )
-        throws AssemblyException
-    {
-        List<TransientModel> transientModels = new ArrayList<>();
-        List<ObjectModel> objectModels = new ArrayList<>();
-        List<ValueModel> valueModels = new ArrayList<>();
-        List<ServiceModel> serviceModels = new ArrayList<>();
-        List<ImportedServiceModel> importedServiceModels = new ArrayList<>();
-
-        if( name == null )
-        {
-            throw new AssemblyException( "Module must have name set" );
-        }
-
-        for( TransientAssemblyImpl compositeDeclaration : transientAssemblies.values() )
-        {
-            transientModels.add( compositeDeclaration.newTransientModel( metaInfoDeclaration, helper ) );
-        }
-
-        for( ValueAssemblyImpl valueDeclaration : valueAssemblies.values() )
-        {
-            valueModels.add( valueDeclaration.newValueModel( metaInfoDeclaration, helper ) );
-        }
-
-        List<EntityModel> entityModels = new ArrayList<>();
-        for( EntityAssemblyImpl entityDeclaration : entityAssemblies.values() )
-        {
-            entityModels.add( entityDeclaration.newEntityModel( metaInfoDeclaration, 
-                                                                metaInfoDeclaration, 
-                                                                metaInfoDeclaration, 
-                                                                metaInfoDeclaration, 
-                                                                helper ) );
-        }
-
-        for( ObjectAssemblyImpl objectDeclaration : objectAssemblies.values() )
-        {
-            objectDeclaration.addObjectModel( objectModels );
-        }
-
-        for( ServiceAssemblyImpl serviceDeclaration : serviceAssemblies )
-        {
-            if( serviceDeclaration.identity == null )
-            {
-                serviceDeclaration.identity = generateId( serviceDeclaration.types() );
-            }
-
-            serviceModels.add( serviceDeclaration.newServiceModel( metaInfoDeclaration, helper ) );
-        }
-
-        for( ImportedServiceAssemblyImpl importedServiceDeclaration : importedServiceAssemblies.values() )
-        {
-            importedServiceDeclaration.addImportedServiceModel( importedServiceModels );
-        }
-
-        ModuleModel moduleModel = new ModuleModel( name,
-                                                   metaInfo,
-                                                   new ActivatorsModel<>( activators ),
-                                                   new TransientsModel( transientModels ),
-                                                   new EntitiesModel( entityModels ),
-                                                   new ObjectsModel( objectModels ),
-                                                   new ValuesModel( valueModels ),
-                                                   new ServicesModel( serviceModels ),
-                                                   new ImportedServicesModel( importedServiceModels ) );
-
-        // Check for duplicate service identities
-        Set<String> identities = new HashSet<>();
-        for( ServiceModel serviceModel : serviceModels )
-        {
-            String identity = serviceModel.identity();
-            if( identities.contains( identity ) )
-            {
-                throw new DuplicateServiceIdentityException(
-                    "Duplicated service identity: " + identity + " in module " + moduleModel.name()
-                );
-            }
-            identities.add( identity );
-        }
-        for( ImportedServiceModel serviceModel : importedServiceModels )
-        {
-            String identity = serviceModel.identity();
-            if( identities.contains( identity ) )
-            {
-                throw new DuplicateServiceIdentityException(
-                    "Duplicated service identity: " + identity + " in module " + moduleModel.name()
-                );
-            }
-            identities.add( identity );
-        }
-
-        for( ImportedServiceModel importedServiceModel : importedServiceModels )
-        {
-            boolean found = false;
-            for( ObjectModel objectModel : objectModels )
-            {
-                if( first( objectModel.types() ).equals( importedServiceModel.serviceImporter() ) )
-                {
-                    found = true;
-                    break;
-                }
-            }
-            if( !found )
-            {
-                @SuppressWarnings( "raw" )
-                Class<? extends ServiceImporter> serviceFactoryType = importedServiceModel.serviceImporter();
-                ObjectModel objectModel = new ObjectModel( serviceFactoryType, Visibility.module, new MetaInfo() );
-                objectModels.add( objectModel );
-            }
-        }
-
-        return moduleModel;
-    }
-
-    private String generateId( Iterable<Class<?>> serviceTypes )
-    {
-        // Find service identity that is not yet used
-        Class<?> serviceType = serviceTypes.iterator()
-            .next(); // Use the first Iterable, which *SHOULD* be the main serviceType
-        int idx = 0;
-        String id = serviceType.getSimpleName();
-        boolean invalid;
-        do
-        {
-            invalid = false;
-            for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
-            {
-                if( serviceAssembly.identity() != null && serviceAssembly.identity().equals( id ) )
-                {
-                    idx++;
-                    id = serviceType.getSimpleName() + "_" + idx;
-                    invalid = true;
-                    break;
-                }
-            }
-        }
-        while( invalid );
-        return id;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ObjectAssemblyImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ObjectAssemblyImpl.java
deleted file mode 100644
index 71475aa..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ObjectAssemblyImpl.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import java.lang.reflect.Modifier;
-import java.util.List;
-import org.qi4j.api.common.InvalidApplicationException;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.bootstrap.ObjectAssembly;
-import org.qi4j.functional.Iterables;
-import org.qi4j.runtime.object.ObjectModel;
-
-/**
- * Assembly of an Object.
- */
-public final class ObjectAssemblyImpl
-    implements ObjectAssembly
-{
-    private Class<?> objectType;
-    MetaInfo metaInfo = new MetaInfo();
-    Visibility visibility = Visibility.module;
-
-    public ObjectAssemblyImpl( Class<?> clazz )
-    {
-        // best try to find out if the class is a concrete class
-        if( clazz.isEnum() ||
-            ( !Composite.class.isAssignableFrom( clazz ) && Modifier.isAbstract( clazz.getModifiers() ) ) )
-        {
-            throw new IllegalArgumentException( "Declared objects must be concrete classes: " + clazz );
-        }
-        this.objectType = clazz;
-    }
-
-    @Override
-    public Iterable<Class<?>> types()
-    {
-        return Iterables.<Class<?>>iterable( objectType );
-    }
-
-    void addObjectModel( List<ObjectModel> objectModels )
-    {
-        try
-        {
-            ObjectModel objectModel = new ObjectModel( objectType, visibility, metaInfo );
-            objectModels.add( objectModel );
-        }
-        catch( Throwable e )
-        {
-            throw new InvalidApplicationException( "Could not register " + objectType.getName(), e );
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ObjectDeclarationImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ObjectDeclarationImpl.java
deleted file mode 100644
index c06032e..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ObjectDeclarationImpl.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.ObjectDeclaration;
-
-/**
- * Declaration of an Object. Created by {@link org.qi4j.runtime.bootstrap.ModuleAssemblyImpl#objects(Class[])}.
- */
-public final class ObjectDeclarationImpl
-    implements ObjectDeclaration
-{
-    private final Iterable<ObjectAssemblyImpl> assemblies;
-
-    public ObjectDeclarationImpl( Iterable<ObjectAssemblyImpl> assemblies )
-    {
-        this.assemblies = assemblies;
-    }
-
-    @Override
-    public ObjectDeclaration setMetaInfo( Object info )
-    {
-        for( ObjectAssemblyImpl assembly : assemblies )
-        {
-            assembly.metaInfo.set( info );
-        }
-        return this;
-    }
-
-    @Override
-    public ObjectDeclaration visibleIn( Visibility visibility )
-        throws IllegalStateException
-    {
-        for( ObjectAssemblyImpl assembly : assemblies )
-        {
-            assembly.visibility = visibility;
-        }
-        return this;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/OrAppliesToFilter.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/OrAppliesToFilter.java
deleted file mode 100644
index e50b748..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/OrAppliesToFilter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesToFilter;
-
-/**
- * JAVADOC
- */
-final class OrAppliesToFilter
-    implements AppliesToFilter
-{
-    private final AppliesToFilter left;
-    private final AppliesToFilter right;
-
-    OrAppliesToFilter( AppliesToFilter left, AppliesToFilter right )
-    {
-        this.left = left;
-        this.right = right;
-    }
-
-    @Override
-    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
-    {
-        return left.appliesTo( method, mixin, compositeType, fragmentClass ) ||
-               right.appliesTo( method, mixin, compositeType, fragmentClass );
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ServiceAssemblyImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ServiceAssemblyImpl.java
deleted file mode 100644
index 1adbfe6..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ServiceAssemblyImpl.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.common.InvalidApplicationException;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.util.Annotations;
-import org.qi4j.api.util.Classes;
-import org.qi4j.bootstrap.ServiceAssembly;
-import org.qi4j.bootstrap.StateDeclarations;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.runtime.activation.ActivatorsModel;
-import org.qi4j.runtime.service.ServiceModel;
-
-/**
- * Assembly of a Service.
- */
-public final class ServiceAssemblyImpl extends CompositeAssemblyImpl
-    implements ServiceAssembly
-{
-    String identity;
-    boolean instantiateOnStartup = false;
-    List<Class<? extends Activator<?>>> activators = new ArrayList<>();
-
-    public ServiceAssemblyImpl( Class<?> serviceType )
-    {
-        super( serviceType );
-        // The composite must always implement ServiceComposite, as a marker interface
-        if( !ServiceComposite.class.isAssignableFrom( serviceType ) )
-        {
-            types.add( ServiceComposite.class );
-        }
-    }
-
-    @Override
-    public String identity()
-    {
-        return identity;
-    }
-
-    @SuppressWarnings( {"raw", "unchecked"} )
-    ServiceModel newServiceModel( StateDeclarations stateDeclarations, AssemblyHelper helper )
-    {
-        try
-        {
-            buildComposite( helper, stateDeclarations );
-            List<Class<? extends Activator<?>>> activatorClasses = Iterables.toList(
-                    Iterables.<Class<? extends Activator<?>>>flatten( activators, activatorsDeclarations( types ) ) );
-            return new ServiceModel( types, visibility, metaInfo,
-                                     new ActivatorsModel( activatorClasses ),
-                                     mixinsModel, stateModel, compositeMethodsModel,
-                                     identity, instantiateOnStartup );
-        }
-        catch( Exception e )
-        {
-            throw new InvalidApplicationException( "Could not register " + types, e );
-        }
-    }
-    
-    private Iterable<Class<? extends Activator<?>>> activatorsDeclarations( Iterable<? extends Class<?>> typess )
-    {
-        // Find activator declarations
-        ArrayList<Type> allTypes = new ArrayList<>();
-        for( Class<?> type : typess )
-        {
-            Iterable<Type> types = Classes.typesOf( type );
-            Iterables.addAll( allTypes, types );
-        }
-        // Find all activators and flattern them into an iterable
-        Function<Type, Iterable<Class<? extends Activator<?>>>> function = new Function<Type, Iterable<Class<? extends Activator<?>>>>()
-        {
-            @Override
-            public Iterable<Class<? extends Activator<?>>> map( Type type )
-            {
-                Activators activators = Annotations.annotationOn( type, Activators.class );
-                if( activators == null )
-                {
-                    return Iterables.empty();
-                }
-                else
-                {
-                    return Iterables.iterable( activators.value() );
-                }
-            }
-        };
-        Iterable<Class<? extends Activator<?>>> flatten = Iterables.flattenIterables( Iterables.map( function, allTypes ) );
-        return Iterables.toList( flatten );
-    }
-
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ServiceDeclarationImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ServiceDeclarationImpl.java
deleted file mode 100644
index 34e1f6d..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ServiceDeclarationImpl.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.service.qualifier.ServiceTags;
-import org.qi4j.bootstrap.ServiceDeclaration;
-
-import static java.util.Arrays.asList;
-
-/**
- * Declaration of a Service. Created by {@link org.qi4j.runtime.bootstrap.ModuleAssemblyImpl#services(Class[])}.
- */
-public final class ServiceDeclarationImpl
-    implements ServiceDeclaration
-{
-    private final Iterable<ServiceAssemblyImpl> serviceAssemblies;
-
-    public ServiceDeclarationImpl( Iterable<ServiceAssemblyImpl> serviceAssemblies )
-    {
-        this.serviceAssemblies = serviceAssemblies;
-    }
-
-    @Override
-    public ServiceDeclaration visibleIn( Visibility visibility )
-    {
-        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
-        {
-            serviceAssembly.visibility = visibility;
-        }
-        return this;
-    }
-
-    @Override
-    public ServiceDeclaration identifiedBy( String identity )
-    {
-        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
-        {
-            serviceAssembly.identity = identity;
-        }
-        return this;
-    }
-
-    @Override
-    public ServiceDeclaration taggedWith( String... tags )
-    {
-        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
-        {
-            ServiceTags previousTags = serviceAssembly.metaInfo.get( ServiceTags.class );
-            if( previousTags != null )
-            {
-                List<String> tagList = new ArrayList<>();
-                tagList.addAll( asList( previousTags.tags() ) );
-                tagList.addAll( asList( tags ) );
-                serviceAssembly.metaInfo.set( new ServiceTags( tagList.toArray( new String[ tagList.size() ] ) ) );
-            }
-            else
-            {
-                serviceAssembly.metaInfo.set( new ServiceTags( tags ) );
-            }
-        }
-
-        return this;
-    }
-
-    @Override
-    public ServiceDeclaration instantiateOnStartup()
-    {
-        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
-        {
-            serviceAssembly.instantiateOnStartup = true;
-        }
-        return this;
-    }
-
-    @Override
-    public ServiceDeclaration setMetaInfo( Object serviceAttribute )
-    {
-        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
-        {
-            serviceAssembly.metaInfo.set( serviceAttribute );
-        }
-        return this;
-    }
-
-    @Override
-    public ServiceDeclaration withConcerns( Class<?>... concerns )
-    {
-        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
-        {
-            serviceAssembly.concerns.addAll( asList( concerns ) );
-        }
-        return this;
-    }
-
-    @Override
-    public ServiceDeclaration withSideEffects( Class<?>... sideEffects )
-    {
-        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
-        {
-            serviceAssembly.sideEffects.addAll( asList( sideEffects ) );
-        }
-        return this;
-    }
-
-    @Override
-    public ServiceDeclaration withMixins( Class<?>... mixins )
-    {
-        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
-        {
-            serviceAssembly.mixins.addAll( asList( mixins ) );
-        }
-        return this;
-    }
-
-    @Override
-    public ServiceDeclaration withTypes( Class<?>... types )
-    {
-        for( ServiceAssemblyImpl serviceAssembly : serviceAssemblies )
-        {
-            serviceAssembly.types.addAll( asList( types ) );
-        }
-        return this;
-    }
-
-    @Override
-    @SafeVarargs
-    public final ServiceDeclaration withActivators( Class<? extends Activator<?>>... activators )
-    {
-        for ( ServiceAssemblyImpl serviceAssembly : serviceAssemblies ) {
-            serviceAssembly.activators.addAll( asList( activators ) );
-        }
-        return this;
-    }
-
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/TransientAssemblyImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/TransientAssemblyImpl.java
deleted file mode 100644
index dfc9721..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/TransientAssemblyImpl.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import org.qi4j.api.common.InvalidApplicationException;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.bootstrap.StateDeclarations;
-import org.qi4j.bootstrap.TransientAssembly;
-import org.qi4j.runtime.composite.TransientModel;
-
-/**
- * Declaration of a TransientComposite.
- */
-public final class TransientAssemblyImpl extends CompositeAssemblyImpl
-    implements TransientAssembly
-{
-    public TransientAssemblyImpl( Class<?> transientType )
-    {
-        super( transientType );
-
-        // The composite must always implement TransientComposite, as a marker interface
-        if( !TransientComposite.class.isAssignableFrom( transientType ) )
-        {
-            types.add( TransientComposite.class );
-        }
-
-        // If type is a class, register it as a mixin
-        if( !transientType.isInterface() )
-        {
-            mixins.add( transientType );
-        }
-    }
-
-    TransientModel newTransientModel( StateDeclarations stateDeclarations, AssemblyHelper helper )
-    {
-        try
-        {
-            buildComposite( helper, stateDeclarations );
-            TransientModel transientModel = new TransientModel(
-                types, visibility, metaInfo, mixinsModel, stateModel, compositeMethodsModel );
-
-            return transientModel;
-        }
-        catch( Exception e )
-        {
-            throw new InvalidApplicationException( "Could not register " + types, e );
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/TransientDeclarationImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/TransientDeclarationImpl.java
deleted file mode 100644
index 9a9154f..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/TransientDeclarationImpl.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.TransientDeclaration;
-
-import static java.util.Arrays.asList;
-
-/**
- * Declaration of a Composite. Created by {@link org.qi4j.bootstrap.ModuleAssembly#transients(Class[])}.
- */
-public final class TransientDeclarationImpl
-    implements TransientDeclaration
-{
-    private final Iterable<TransientAssemblyImpl> assemblies;
-
-    public TransientDeclarationImpl( Iterable<TransientAssemblyImpl> assemblies )
-    {
-        this.assemblies = assemblies;
-    }
-
-    @Override
-    public TransientDeclaration setMetaInfo( Object info )
-    {
-        for( TransientAssemblyImpl assembly : assemblies )
-        {
-            assembly.metaInfo.set( info );
-        }
-        return this;
-    }
-
-    @Override
-    public TransientDeclaration visibleIn( Visibility visibility )
-    {
-        for( TransientAssemblyImpl assembly : assemblies )
-        {
-            assembly.visibility = visibility;
-        }
-        return this;
-    }
-
-    @Override
-    public TransientDeclaration withConcerns( Class<?>... concerns )
-    {
-        for( TransientAssemblyImpl assembly : assemblies )
-        {
-            assembly.concerns.addAll( asList( concerns ) );
-        }
-        return this;
-    }
-
-    @Override
-    public TransientDeclaration withSideEffects( Class<?>... sideEffects )
-    {
-        for( TransientAssemblyImpl assembly : assemblies )
-        {
-            assembly.sideEffects.addAll( asList( sideEffects ) );
-        }
-        return this;
-    }
-
-    @Override
-    public TransientDeclaration withMixins( Class<?>... mixins )
-    {
-        for( TransientAssemblyImpl assembly : assemblies )
-        {
-            assembly.mixins.addAll( asList( mixins ) );
-        }
-        return this;
-    }
-
-    @Override
-    public TransientDeclaration withTypes( Class<?>... types )
-    {
-        for( TransientAssemblyImpl assembly : assemblies )
-        {
-            assembly.types.addAll( asList( types ) );
-        }
-        return this;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/TypeCheckAppliesToFilter.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/TypeCheckAppliesToFilter.java
deleted file mode 100644
index dee1993..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/TypeCheckAppliesToFilter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesToFilter;
-
-/**
- * JAVADOC
- */
-final class TypeCheckAppliesToFilter
-    implements AppliesToFilter
-{
-    @SuppressWarnings( "raw" )
-    private final Class type;
-
-    @SuppressWarnings( "raw" )
-    TypeCheckAppliesToFilter( Class type )
-    {
-        this.type = type;
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
-    {
-        return type.isAssignableFrom( compositeType );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/TypedFragmentAppliesToFilter.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/TypedFragmentAppliesToFilter.java
deleted file mode 100644
index e007697..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/TypedFragmentAppliesToFilter.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesToFilter;
-
-/**
- * JAVADOC
- */
-final class TypedFragmentAppliesToFilter
-    implements AppliesToFilter
-{
-    @Override
-    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
-    {
-        return method.getDeclaringClass().isAssignableFrom( fragmentClass );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ValueAssemblyImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ValueAssemblyImpl.java
deleted file mode 100644
index 605efa1..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ValueAssemblyImpl.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (c) 2007-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.bootstrap;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Member;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.GenericAssociationInfo;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.common.InvalidApplicationException;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.api.property.GenericPropertyInfo;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.util.Annotations;
-import org.qi4j.api.util.Classes;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.StateDeclarations;
-import org.qi4j.bootstrap.ValueAssembly;
-import org.qi4j.runtime.association.AssociationModel;
-import org.qi4j.runtime.association.AssociationsModel;
-import org.qi4j.runtime.association.ManyAssociationModel;
-import org.qi4j.runtime.association.ManyAssociationsModel;
-import org.qi4j.runtime.association.NamedAssociationModel;
-import org.qi4j.runtime.association.NamedAssociationsModel;
-import org.qi4j.runtime.composite.StateModel;
-import org.qi4j.runtime.composite.ValueConstraintsInstance;
-import org.qi4j.runtime.composite.ValueConstraintsModel;
-import org.qi4j.runtime.property.PropertyModel;
-import org.qi4j.runtime.value.ValueModel;
-import org.qi4j.runtime.value.ValueStateModel;
-
-import static org.qi4j.api.util.Annotations.isType;
-import static org.qi4j.api.util.Classes.typeOf;
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Declaration of a ValueComposite.
- */
-public final class ValueAssemblyImpl
-    extends CompositeAssemblyImpl
-    implements ValueAssembly
-{
-    private AssociationsModel associationsModel;
-    private ManyAssociationsModel manyAssociationsModel;
-    private NamedAssociationsModel namedAssociationsModel;
-
-    public ValueAssemblyImpl( Class<?> compositeType )
-    {
-        super( compositeType );
-        // The composite must always implement ValueComposite, as a marker interface
-        if( !ValueComposite.class.isAssignableFrom( compositeType ) )
-        {
-            types.add( ValueComposite.class );
-        }
-    }
-
-    @Override
-    protected StateModel createStateModel()
-    {
-        return new ValueStateModel( propertiesModel, associationsModel, manyAssociationsModel, namedAssociationsModel );
-    }
-
-    ValueModel newValueModel(
-        StateDeclarations stateDeclarations,
-        AssemblyHelper helper
-    )
-    {
-        try
-        {
-            associationsModel = new AssociationsModel();
-            manyAssociationsModel = new ManyAssociationsModel();
-            namedAssociationsModel = new NamedAssociationsModel();
-            buildComposite( helper, stateDeclarations );
-
-            ValueModel valueModel = new ValueModel(
-                types, visibility, metaInfo, mixinsModel, (ValueStateModel) stateModel, compositeMethodsModel );
-
-            return valueModel;
-        }
-        catch( Exception e )
-        {
-            throw new InvalidApplicationException( "Could not register " + types, e );
-        }
-    }
-
-    @Override
-    protected void addStateFor( AccessibleObject accessor,
-                                Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
-    )
-    {
-        String stateName = QualifiedName.fromAccessor( accessor ).name();
-
-        if( registeredStateNames.contains( stateName ) )
-        {
-            return; // Skip already registered names
-        }
-
-        Class<?> accessorType = Classes.RAW_CLASS.map( typeOf( accessor ) );
-        if( Property.class.isAssignableFrom( accessorType ) )
-        {
-            propertiesModel.addProperty( newPropertyModel( accessor, constraintClasses ) );
-            registeredStateNames.add( stateName );
-        }
-        else if( Association.class.isAssignableFrom( accessorType ) )
-        {
-            associationsModel.addAssociation( newAssociationModel( accessor, constraintClasses ) );
-            registeredStateNames.add( stateName );
-        }
-        else if( ManyAssociation.class.isAssignableFrom( accessorType ) )
-        {
-            manyAssociationsModel.addManyAssociation( newManyAssociationModel( accessor, constraintClasses ) );
-            registeredStateNames.add( stateName );
-        }
-        else if( NamedAssociation.class.isAssignableFrom( accessorType ) )
-        {
-            namedAssociationsModel.addNamedAssociation( newNamedAssociationModel( accessor, constraintClasses ) );
-            registeredStateNames.add( stateName );
-        }
-    }
-
-    @Override
-    protected PropertyModel newPropertyModel( AccessibleObject accessor,
-                                              Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
-    )
-    {
-        Iterable<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
-        boolean optional = first( filter( isType( Optional.class ), annotations ) ) != null;
-        ValueConstraintsModel valueConstraintsModel = constraintsFor( annotations, GenericPropertyInfo.propertyTypeOf( accessor ), ( (Member) accessor )
-            .getName(), optional, constraintClasses, accessor );
-        ValueConstraintsInstance valueConstraintsInstance = null;
-        if( valueConstraintsModel.isConstrained() )
-        {
-            valueConstraintsInstance = valueConstraintsModel.newInstance();
-        }
-        MetaInfo metaInfo = stateDeclarations.metaInfoFor( accessor );
-        boolean useDefaults = metaInfo.get( UseDefaults.class ) != null || stateDeclarations.useDefaults( accessor );
-        Object initialValue = stateDeclarations.initialValueOf( accessor );
-        return new PropertyModel( accessor, true, useDefaults, valueConstraintsInstance, metaInfo, initialValue );
-    }
-
-    public AssociationModel newAssociationModel( AccessibleObject accessor,
-                                                 Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
-    )
-    {
-        Iterable<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
-        boolean optional = first( filter( isType( Optional.class ), annotations ) ) != null;
-
-        // Constraints for Association references
-        ValueConstraintsModel valueConstraintsModel = constraintsFor( annotations, GenericAssociationInfo
-            .associationTypeOf( accessor ), ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
-        ValueConstraintsInstance valueConstraintsInstance = null;
-        if( valueConstraintsModel.isConstrained() )
-        {
-            valueConstraintsInstance = valueConstraintsModel.newInstance();
-        }
-
-        // Constraints for the Association itself
-        valueConstraintsModel = constraintsFor( annotations, Association.class, ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
-        ValueConstraintsInstance associationValueConstraintsInstance = null;
-        if( valueConstraintsModel.isConstrained() )
-        {
-            associationValueConstraintsInstance = valueConstraintsModel.newInstance();
-        }
-
-        MetaInfo metaInfo = stateDeclarations.metaInfoFor( accessor );
-        AssociationModel associationModel = new AssociationModel( accessor, valueConstraintsInstance, associationValueConstraintsInstance, metaInfo );
-        return associationModel;
-    }
-
-    public ManyAssociationModel newManyAssociationModel( AccessibleObject accessor,
-                                                         Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
-    )
-    {
-        Iterable<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
-        boolean optional = first( filter( isType( Optional.class ), annotations ) ) != null;
-
-        // Constraints for entities in ManyAssociation
-        ValueConstraintsModel valueConstraintsModel = constraintsFor( annotations, GenericAssociationInfo
-            .associationTypeOf( accessor ), ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
-        ValueConstraintsInstance valueConstraintsInstance = null;
-        if( valueConstraintsModel.isConstrained() )
-        {
-            valueConstraintsInstance = valueConstraintsModel.newInstance();
-        }
-
-        // Constraints for the ManyAssociation itself
-        valueConstraintsModel = constraintsFor( annotations, ManyAssociation.class, ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
-        ValueConstraintsInstance manyValueConstraintsInstance = null;
-        if( valueConstraintsModel.isConstrained() )
-        {
-            manyValueConstraintsInstance = valueConstraintsModel.newInstance();
-        }
-        MetaInfo metaInfo = stateDeclarations.metaInfoFor( accessor );
-        ManyAssociationModel associationModel = new ManyAssociationModel( accessor, valueConstraintsInstance, manyValueConstraintsInstance, metaInfo );
-        return associationModel;
-    }
-    
-    public NamedAssociationModel newNamedAssociationModel( AccessibleObject accessor,
-                                                           Iterable<Class<? extends Constraint<?, ?>>> constraintClasses
-    )
-    {
-        Iterable<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
-        boolean optional = first( filter( isType( Optional.class ), annotations ) ) != null;
-
-        // Constraints for entities in NamedAssociation
-        ValueConstraintsModel valueConstraintsModel = constraintsFor( annotations, GenericAssociationInfo
-            .associationTypeOf( accessor ), ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
-        ValueConstraintsInstance valueConstraintsInstance = null;
-        if( valueConstraintsModel.isConstrained() )
-        {
-            valueConstraintsInstance = valueConstraintsModel.newInstance();
-        }
-
-        // Constraints for the NamedAssociation itself
-        valueConstraintsModel = constraintsFor( annotations, NamedAssociation.class, ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
-        ValueConstraintsInstance namedValueConstraintsInstance = null;
-        if( valueConstraintsModel.isConstrained() )
-        {
-            namedValueConstraintsInstance = valueConstraintsModel.newInstance();
-        }
-        MetaInfo metaInfo = stateDeclarations.metaInfoFor( accessor );
-        NamedAssociationModel associationModel = new NamedAssociationModel( accessor, valueConstraintsInstance, namedValueConstraintsInstance, metaInfo );
-        return associationModel;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ValueDeclarationImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ValueDeclarationImpl.java
deleted file mode 100644
index 22169bf..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/bootstrap/ValueDeclarationImpl.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.bootstrap;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.ValueDeclaration;
-
-import static java.util.Arrays.asList;
-
-/**
- * Declaration of a ValueComposite.
- */
-public final class ValueDeclarationImpl
-    implements ValueDeclaration
-{
-    private final Iterable<ValueAssemblyImpl> assemblies;
-
-    public ValueDeclarationImpl( Iterable<ValueAssemblyImpl> assemblies )
-    {
-        this.assemblies = assemblies;
-    }
-
-    @Override
-    public ValueDeclaration setMetaInfo( Object info )
-    {
-        for( ValueAssemblyImpl assembly : assemblies )
-        {
-            assembly.metaInfo.set( info );
-        }
-        return this;
-    }
-
-    @Override
-    public ValueDeclaration visibleIn( Visibility visibility )
-    {
-        for( ValueAssemblyImpl assembly : assemblies )
-        {
-            assembly.visibility = visibility;
-        }
-        return this;
-    }
-
-    @Override
-    public ValueDeclaration withConcerns( Class<?>... concerns )
-    {
-        for( ValueAssemblyImpl assembly : assemblies )
-        {
-            assembly.concerns.addAll( asList( concerns ) );
-        }
-        return this;
-    }
-
-    @Override
-    public ValueDeclaration withSideEffects( Class<?>... sideEffects )
-    {
-        for( ValueAssemblyImpl assembly : assemblies )
-        {
-            assembly.sideEffects.addAll( asList( sideEffects ) );
-        }
-        return this;
-    }
-
-    @Override
-    public ValueDeclaration withMixins( Class<?>... mixins )
-    {
-        for( ValueAssemblyImpl assembly : assemblies )
-        {
-            assembly.mixins.addAll( asList( mixins ) );
-        }
-        return this;
-    }
-
-    @Override
-    public ValueDeclaration withTypes( Class<?>... types )
-    {
-        for( ValueAssemblyImpl assembly : assemblies )
-        {
-            assembly.types.addAll( asList( types ) );
-        }
-        return this;
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/AbstractConstraintModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/AbstractConstraintModel.java
deleted file mode 100644
index d9ffbbd..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/AbstractConstraintModel.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.annotation.Annotation;
-import org.qi4j.api.constraint.ConstraintDescriptor;
-import org.qi4j.functional.Visitable;
-import org.qi4j.functional.Visitor;
-
-/**
- * JAVADOC
- */
-public abstract class AbstractConstraintModel
-    implements ConstraintDescriptor, Visitable<ConstraintDescriptor>
-{
-    protected final Annotation annotation;
-
-    public AbstractConstraintModel( Annotation annotation )
-    {
-        this.annotation = annotation;
-    }
-
-    @Override
-    public Annotation annotation()
-    {
-        return annotation;
-    }
-
-    public abstract ConstraintInstance<?, ?> newInstance();
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( Visitor<? super ConstraintDescriptor, ThrowableType> modelVisitor )
-        throws ThrowableType
-    {
-        return modelVisitor.visit( this );
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/AbstractModifierModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/AbstractModifierModel.java
deleted file mode 100644
index b457f1d..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/AbstractModifierModel.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.injection.Dependencies;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.runtime.injection.InjectedFieldsModel;
-import org.qi4j.runtime.injection.InjectedMethodsModel;
-import org.qi4j.runtime.injection.InjectionContext;
-import org.qi4j.spi.module.ModuleSpi;
-
-import static org.qi4j.api.util.Classes.RAW_CLASS;
-import static org.qi4j.api.util.Classes.interfacesOf;
-import static org.qi4j.functional.Iterables.flattenIterables;
-import static org.qi4j.functional.Iterables.iterable;
-import static org.qi4j.functional.Iterables.map;
-import static org.qi4j.functional.Iterables.toArray;
-import static org.qi4j.functional.Iterables.unique;
-
-/**
- * JAVADOC
- */
-public abstract class AbstractModifierModel
-    implements Dependencies, VisitableHierarchy<Object, Object>
-{
-    private final Class<?> modifierClass;
-
-    private final ConstructorsModel constructorsModel;
-    private final InjectedFieldsModel injectedFieldsModel;
-    private final InjectedMethodsModel injectedMethodsModel;
-
-    private final Class<?>[] nextInterfaces;
-
-    @SuppressWarnings( "unchecked" )
-    public AbstractModifierModel( Class<?> declaredModifierClass, Class<?> instantiationClass )
-    {
-        this.modifierClass = instantiationClass;
-        constructorsModel = new ConstructorsModel( modifierClass );
-        injectedFieldsModel = new InjectedFieldsModel( declaredModifierClass );
-        injectedMethodsModel = new InjectedMethodsModel( declaredModifierClass );
-        Class<Class<?>> componentType = (Class<Class<?>>) Class.class.cast( Class.class );
-        nextInterfaces = toArray( componentType, unique( map( RAW_CLASS, interfacesOf( declaredModifierClass ) ) ) );
-    }
-
-    public Class<?> modifierClass()
-    {
-        return modifierClass;
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public Iterable<DependencyModel> dependencies()
-    {
-        return flattenIterables( map( DEPENDENCIES_FUNCTION, iterable( constructorsModel, injectedFieldsModel, injectedMethodsModel ) ) );
-    }
-
-    public boolean isGeneric()
-    {
-        return InvocationHandler.class.isAssignableFrom( modifierClass );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            if( constructorsModel.accept( visitor ) )
-            {
-                if( injectedFieldsModel.accept( visitor ) )
-                {
-                    injectedMethodsModel.accept( visitor );
-                }
-            }
-        }
-
-        return visitor.visitLeave( this );
-    }
-
-    // Context
-    public InvocationHandler newInstance( ModuleSpi moduleInstance,
-                                          InvocationHandler next,
-                                          ProxyReferenceInvocationHandler proxyHandler,
-                                          Method method
-    )
-    {
-        InjectionContext injectionContext = new InjectionContext( moduleInstance, wrapNext( next ), proxyHandler );
-
-        Object modifier = constructorsModel.newInstance( injectionContext );
-
-        try
-        {
-            if( FragmentClassLoader.isGenerated( modifier ) )
-            {
-                modifier.getClass().getField( "_instance" ).set( modifier, proxyHandler );
-            }
-        }
-        catch( IllegalAccessException | NoSuchFieldException e )
-        {
-            e.printStackTrace();
-        }
-
-        injectedFieldsModel.inject( injectionContext, modifier );
-        injectedMethodsModel.inject( injectionContext, modifier );
-
-        if( isGeneric() )
-        {
-            return (InvocationHandler) modifier;
-        }
-        else
-        {
-            try
-            {
-                Method invocationMethod = modifierClass.getMethod( "_" + method.getName(), method.getParameterTypes() );
-                TypedModifierInvocationHandler handler = new TypedModifierInvocationHandler();
-                handler.setFragment( modifier );
-                handler.setMethod( invocationMethod );
-                return handler;
-            }
-            catch( NoSuchMethodException e )
-            {
-                throw new ConstructionException( "Could not find modifier method", e );
-            }
-        }
-    }
-
-    private Object wrapNext( InvocationHandler next )
-    {
-        if( isGeneric() )
-        {
-            return next;
-        }
-        else
-        {
-            return Proxy.newProxyInstance( modifierClass.getClassLoader(), nextInterfaces, next );
-        }
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-        AbstractModifierModel that = (AbstractModifierModel) o;
-        return modifierClass.equals( that.modifierClass );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return modifierClass.hashCode();
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/AtomicInstancePool.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/AtomicInstancePool.java
deleted file mode 100644
index 656b3f8..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/AtomicInstancePool.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Method instance pool that keeps a linked list. Uses atomic reference
- * to ensure that instances are acquired and returned in a thread-safe
- * manner.
- */
-public final class AtomicInstancePool
-    implements InstancePool<CompositeMethodInstance>
-{
-    private final AtomicReference<CompositeMethodInstance> first = new AtomicReference<CompositeMethodInstance>();
-
-    @Override
-    public CompositeMethodInstance obtainInstance()
-    {
-        CompositeMethodInstance firstInstance;
-        do
-        {
-            firstInstance = first.get();
-        }
-        while( firstInstance != null && !first.compareAndSet( firstInstance, firstInstance.getNext() ) );
-
-        return firstInstance;
-    }
-
-    @Override
-    public void releaseInstance( CompositeMethodInstance compositeMethodInstance )
-    {
-        CompositeMethodInstance firstInstance;
-        do
-        {
-            firstInstance = first.get();
-            compositeMethodInstance.setNext( firstInstance );
-        }
-        while( !first.compareAndSet( firstInstance, compositeMethodInstance ) );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/CompactLevel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/CompactLevel.java
deleted file mode 100644
index 199fd4f..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/CompactLevel.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*

- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.

- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.

- *

- * Licensed 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.qi4j.runtime.composite;

-

-/**

- * Compaction Level of the StackTrace clenaup operation.

- *

- * <pre>

- * <b>off</b>       = Do not modify the stack trace.

- * <b>proxy</b>     = Remove all Zest internal classes and all JDK internal classes from

- *             the originating method call.

- * <b>semi</b>      = Remove all JDK internal classes on the entire stack.

- * <b>extensive</b> = Remove all Zest internal and JDK internal classes from the entire stack.

- * </pre>

- *

- * <p>

- * The Compaction is set through the System Property "<code><b>qi4j.compacttrace</b></code>" to

- * any of the above values.

- * </p>

- */

-enum CompactLevel

-{

-    off, proxy, semi, extensive

-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/CompositeConstraintModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/CompositeConstraintModel.java
deleted file mode 100644
index 54a7131..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/CompositeConstraintModel.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.annotation.Annotation;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.constraint.Constraint;
-
-/**
- * JAVADOC
- */
-public final class CompositeConstraintModel
-    extends AbstractConstraintModel
-{
-    private final ValueConstraintsModel constraintsModel;
-
-    public CompositeConstraintModel( Annotation annotation, ValueConstraintsModel constraintsModel )
-    {
-        super( annotation );
-        this.constraintsModel = constraintsModel;
-    }
-
-    @Override
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public ConstraintInstance<?, ?> newInstance()
-    {
-        try
-        {
-            ValueConstraintsInstance compositeConstraintsInstance = constraintsModel.newInstance();
-            Constraint<?, ?> constraint = new CompositeConstraintInstance( compositeConstraintsInstance );
-            return new ConstraintInstance( constraint, annotation );
-        }
-        catch( Exception e )
-        {
-            throw new ConstructionException( "Could not instantiate constraint implementation", e );
-        }
-    }
-
-    private static class CompositeConstraintInstance
-        implements Constraint<Annotation, Object>
-    {
-        private final ValueConstraintsInstance valueConstraintsInstance;
-
-        private CompositeConstraintInstance( ValueConstraintsInstance valueConstraintsInstance )
-        {
-            this.valueConstraintsInstance = valueConstraintsInstance;
-        }
-
-        @Override
-        public boolean isValid( Annotation annotation, Object value )
-            throws NullPointerException
-        {
-            return valueConstraintsInstance.checkConstraints( value ).isEmpty();
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/CompositeMethodInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/CompositeMethodInstance.java
deleted file mode 100644
index c3a4ad2..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/CompositeMethodInstance.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-
-/**
- * JAVADOC
- */
-public final class CompositeMethodInstance
-{
-    private final InvocationHandler invoker;
-    private final FragmentInvocationHandler mixinInvoker;
-    private final Method method;
-    private final int methodIdx;
-
-    private CompositeMethodInstance next;
-
-    public CompositeMethodInstance( InvocationHandler invoker,
-                                    FragmentInvocationHandler mixinInvoker,
-                                    Method method, int methodIdx
-    )
-    {
-        this.invoker = invoker;
-        this.method = method;
-        this.mixinInvoker = mixinInvoker;
-        this.methodIdx = methodIdx;
-    }
-
-    public Method method()
-    {
-        return method;
-    }
-
-    public Object getMixinFrom( Object[] mixins )
-    {
-        return mixins[ methodIdx ];
-    }
-
-    public Object invoke( Object composite, Object[] params, Object mixin )
-        throws Throwable
-    {
-        mixinInvoker.setFragment( mixin );
-
-        try
-        {
-            return invoker.invoke( composite, method, params );
-        }
-        finally
-        {
-            mixinInvoker.setFragment( null );
-        }
-    }
-
-    public CompositeMethodInstance getNext()
-    {
-        return next;
-    }
-
-    public void setNext( CompositeMethodInstance next )
-    {
-        this.next = next;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/CompositeMethodModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/CompositeMethodModel.java
deleted file mode 100644
index 3162130..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/CompositeMethodModel.java
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Array;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.composite.MethodDescriptor;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.injection.Dependencies;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.spi.module.ModuleSpi;
-
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.flattenIterables;
-import static org.qi4j.functional.Iterables.iterable;
-import static org.qi4j.functional.Specifications.notNull;
-
-/**
- * JAVADOC
- */
-public final class CompositeMethodModel
-    implements MethodDescriptor, Dependencies, VisitableHierarchy<Object, Object>
-{
-    // Model
-    private final Method method;
-    private Method invocationMethod; // This will be the _ prefixed method on typed mixins
-    private final ConstraintsModel constraints;
-    private final ConcernsModel concerns;
-    private final SideEffectsModel sideEffects;
-    private final MixinsModel mixins;
-    private AnnotatedElement annotations;
-
-    // Context
-//    private final SynchronizedCompositeMethodInstancePool instancePool = new SynchronizedCompositeMethodInstancePool();
-    private final AtomicInstancePool instancePool = new AtomicInstancePool();
-    private final ConstraintsInstance constraintsInstance;
-
-    public CompositeMethodModel( Method method,
-                                 ConstraintsModel constraintsModel,
-                                 ConcernsModel concernsModel,
-                                 SideEffectsModel sideEffectsModel,
-                                 MixinsModel mixinsModel
-    )
-    {
-        this.method = method;
-        mixins = mixinsModel;
-        concerns = concernsModel;
-        sideEffects = sideEffectsModel;
-        constraints = constraintsModel;
-        constraintsInstance = constraints.newInstance();
-        initialize();
-    }
-
-    private void initialize()
-    {
-        annotations = new CompositeMethodAnnotatedElement();
-        this.method.setAccessible( true );
-//        instancePool = new SynchronizedCompositeMethodInstancePool();
-    }
-
-    // Model
-
-    @Override
-    public Method method()
-    {
-        return method;
-    }
-
-    public MixinModel mixin()
-    {
-        return mixins.mixinFor( method );
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public Iterable<DependencyModel> dependencies()
-    {
-        return flattenIterables( filter( notNull(), iterable( concerns != null ? concerns.dependencies() : null,
-                                                              sideEffects != null ? sideEffects.dependencies() : null ) ) );
-    }
-
-    // Context
-    public Object invoke( Object composite, Object[] params, MixinsInstance mixins, ModuleSpi moduleInstance )
-        throws Throwable
-    {
-        constraintsInstance.checkValid( composite, method, params );
-
-        CompositeMethodInstance methodInstance = getInstance( moduleInstance );
-        try
-        {
-            return mixins.invoke( composite, params, methodInstance );
-        }
-        finally
-        {
-            instancePool.releaseInstance( methodInstance );
-        }
-    }
-
-    private CompositeMethodInstance getInstance( ModuleSpi moduleInstance )
-    {
-        CompositeMethodInstance methodInstance = instancePool.obtainInstance();
-        if( methodInstance == null )
-        {
-            methodInstance = newCompositeMethodInstance( moduleInstance );
-        }
-
-        return methodInstance;
-    }
-
-    private CompositeMethodInstance newCompositeMethodInstance( ModuleSpi moduleInstance )
-        throws ConstructionException
-    {
-        FragmentInvocationHandler mixinInvocationHandler = mixins.newInvocationHandler( method );
-        InvocationHandler invoker = mixinInvocationHandler;
-        if( concerns != ConcernsModel.EMPTY_CONCERNS )
-        {
-            ConcernsInstance concernsInstance = concerns.newInstance( method, moduleInstance, mixinInvocationHandler );
-            invoker = concernsInstance;
-        }
-        if( sideEffects != SideEffectsModel.EMPTY_SIDEEFFECTS )
-        {
-            SideEffectsInstance sideEffectsInstance = sideEffects.newInstance( method, moduleInstance, invoker );
-            invoker = sideEffectsInstance;
-        }
-
-        if( invocationMethod == null )
-        {
-            MixinModel model = mixins.mixinFor( method );
-            if( !InvocationHandler.class.isAssignableFrom( model.mixinClass() ) )
-            {
-                try
-                {
-                    invocationMethod = model.instantiationClass()
-                        .getMethod( "_" + method.getName(), method.getParameterTypes() );
-                }
-                catch( NoSuchMethodException e )
-                {
-                    invocationMethod = method;
-//                    throw new ConstructionException( "Could not find the subclass method", e );
-                }
-            }
-            else
-            {
-                invocationMethod = method;
-            }
-        }
-
-        mixinInvocationHandler.setMethod( invocationMethod );
-
-        return new CompositeMethodInstance( invoker, mixinInvocationHandler, method, mixins.methodIndex.get( method ) );
-    }
-
-    public AnnotatedElement annotatedElement()
-    {
-        return annotations;
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
-        throws ThrowableType
-    {
-        if( modelVisitor.visitEnter( this ) )
-        {
-            constraints.accept( modelVisitor );
-            concerns.accept( modelVisitor );
-            sideEffects.accept( modelVisitor );
-        }
-        return modelVisitor.visitLeave( this );
-    }
-
-    @Override
-    public String toString()
-    {
-        return method.toGenericString();
-    }
-
-    public Iterable<Method> invocationsFor( Class<?> mixinClass )
-    {
-        return mixins.invocationsFor( mixinClass );
-    }
-
-    public class CompositeMethodAnnotatedElement
-        implements AnnotatedElement
-    {
-        @Override
-        public boolean isAnnotationPresent( Class<? extends Annotation> annotationClass )
-        {
-            // Check method
-            if( method.isAnnotationPresent( annotationClass ) )
-            {
-                return true;
-            }
-
-            // Check mixin
-            try
-            {
-                MixinModel model = mixins.mixinFor( method );
-                if( GenericSpecification.INSTANCE.satisfiedBy( model.mixinClass() ) )
-                {
-                    return false;
-                }
-                return ( model.mixinClass()
-                             .getMethod( method.getName(), method.getParameterTypes() )
-                             .isAnnotationPresent( annotationClass ) );
-            }
-            catch( NoSuchMethodException e )
-            {
-                return false;
-            }
-        }
-
-        @Override
-        public <T extends Annotation> T getAnnotation( Class<T> annotationClass )
-        {
-            // Check mixin
-            try
-            {
-                MixinModel model = mixins.mixinFor( method );
-                if( !GenericSpecification.INSTANCE.satisfiedBy( model.mixinClass() ) )
-                {
-                    T annotation = annotationClass.cast( model.mixinClass()
-                                                             .getMethod( method.getName(), method.getParameterTypes() )
-                                                             .getAnnotation( annotationClass ) );
-                    if( annotation != null )
-                    {
-                        return annotation;
-                    }
-                }
-            }
-            catch( NoSuchMethodException e )
-            {
-                // Ignore
-            }
-
-            // Check method
-            return method.getAnnotation( annotationClass );
-        }
-
-        @Override
-        public Annotation[] getAnnotations()
-        {
-            // Add mixin annotations
-            List<Annotation> annotations = new ArrayList<Annotation>();
-            MixinModel model = mixins.mixinFor( method );
-            Annotation[] mixinAnnotations = new Annotation[ 0 ];
-            if( !GenericSpecification.INSTANCE.satisfiedBy( model.mixinClass() ) )
-            {
-                mixinAnnotations = model.mixinClass().getAnnotations();
-                annotations.addAll( Arrays.asList( mixinAnnotations ) );
-            }
-
-            // Add method annotations, but don't include duplicates
-            Annotation[] methodAnnotations = method.getAnnotations();
-            next:
-            for( Annotation methodAnnotation : methodAnnotations )
-            {
-                for( int i = 0; i < mixinAnnotations.length; i++ )
-                {
-                    if( annotations.get( i ).annotationType().equals( methodAnnotation.annotationType() ) )
-                    {
-                        continue next;
-                    }
-                }
-
-                annotations.add( methodAnnotation );
-            }
-
-            return annotations.toArray( new Annotation[ annotations.size() ] );
-        }
-
-        @Override
-        public Annotation[] getDeclaredAnnotations()
-        {
-            return new Annotation[ 0 ];
-        }
-
-        // @Override (Since JDK 8)
-        @SuppressWarnings( "unchecked" )
-        public <T extends Annotation> T[] getAnnotationsByType( Class<T> annotationClass )
-        {
-            NullArgumentException.validateNotNull( "annotationClass", annotationClass );
-            return (T[]) Array.newInstance( annotationClass, 0 );
-        }
-
-        // @Override (Since JDK 8)
-        public <T extends Annotation> T getDeclaredAnnotation( Class<T> annotationClass )
-        {
-            NullArgumentException.validateNotNull( "annotationClass", annotationClass );
-            return null;
-        }
-
-        // @Override (Since JDK 8)
-        @SuppressWarnings( "unchecked" )
-        public <T extends Annotation> T[] getDeclaredAnnotationsByType( Class<T> annotationClass )
-        {
-            NullArgumentException.validateNotNull( "annotationClass", annotationClass );
-            return (T[]) Array.newInstance( annotationClass, 0 );
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/CompositeMethodsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/CompositeMethodsModel.java
deleted file mode 100644
index bf0c113..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/CompositeMethodsModel.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.Method;
-import java.util.LinkedHashMap;
-import org.qi4j.api.composite.MissingMethodException;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.injection.Dependencies;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.spi.module.ModuleSpi;
-
-import static org.qi4j.functional.Iterables.map;
-
-/**
- * Model for Composite methods. This includes both private and public methods.
- */
-public final class CompositeMethodsModel
-    implements VisitableHierarchy<Object, Object>
-{
-    private final LinkedHashMap<Method, CompositeMethodModel> methods;
-    private final MixinsModel mixinsModel;
-
-    public CompositeMethodsModel( MixinsModel mixinsModel )
-    {
-        methods = new LinkedHashMap<>();
-        this.mixinsModel = mixinsModel;
-    }
-
-    public Iterable<DependencyModel> dependencies()
-    {
-        return Iterables.flattenIterables( map( Dependencies.DEPENDENCIES_FUNCTION, methods.values() ) );
-    }
-
-    // Context
-    public Object invoke( MixinsInstance mixins,
-                          Object proxy,
-                          Method method,
-                          Object[] args,
-                          ModuleSpi moduleInstance
-    )
-        throws Throwable
-    {
-        CompositeMethodModel compositeMethod = methods.get( method );
-
-        if( compositeMethod == null )
-        {
-            if( method.getDeclaringClass().equals( Object.class ) )
-            {
-                return mixins.invokeObject( proxy, args, method );
-            }
-
-            if( !method.getDeclaringClass().isInterface() )
-            {
-                Iterable<Class<?>> types = mixinsModel.mixinTypes();
-                for( Class<?> aClass : types )
-                {
-                    try
-                    {
-                        Method realMethod = aClass.getMethod( method.getName(), method.getParameterTypes() );
-                        compositeMethod = methods.get( realMethod );
-                        break;
-                    }
-                    catch( NoSuchMethodException e )
-                    {
-                    }
-                    catch( SecurityException e )
-                    {
-                    }
-                }
-            }
-//            return mixins.invokeObject( proxy, args, method );
-            throw new MissingMethodException( "Method '" + method + "' is not implemented" );
-        }
-        else
-        {
-            return compositeMethod.invoke( proxy, args, mixins, moduleInstance );
-        }
-    }
-
-    public void addMethod( CompositeMethodModel methodModel )
-    {
-        methods.put( methodModel.method(), methodModel );
-    }
-
-    public boolean isImplemented( Method method )
-    {
-        return methods.containsKey( method );
-    }
-
-    public Iterable<Method> methods()
-    {
-        return methods.keySet();
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
-        throws ThrowableType
-    {
-        if( modelVisitor.visitEnter( this ) )
-        {
-            for( CompositeMethodModel compositeMethodModel : methods.values() )
-            {
-                if( !compositeMethodModel.accept( modelVisitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return modelVisitor.visitLeave( this );
-    }
-
-    @Override
-    public String toString()
-    {
-        return methods().toString();
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/CompositeModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/CompositeModel.java
deleted file mode 100644
index a6ea122..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/CompositeModel.java
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.util.LinkedHashSet;
-import java.util.Set;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.composite.InvalidCompositeException;
-import org.qi4j.api.structure.Module;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.injection.Dependencies;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.runtime.structure.ModuleInstance;
-import org.qi4j.spi.module.ModuleSpi;
-
-import static java.lang.reflect.Proxy.newProxyInstance;
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.toList;
-
-/**
- * JAVADOC
- */
-public abstract class CompositeModel
-    implements VisitableHierarchy<Object, Object>, Dependencies, CompositeDescriptor
-{
-    protected final MixinsModel mixinsModel;
-    protected final CompositeMethodsModel compositeMethodsModel;
-    private final Set<Class<?>> types;
-    private final Visibility visibility;
-    private final MetaInfo metaInfo;
-    protected final StateModel stateModel;
-    protected Class<? extends Composite> proxyClass;
-    protected Constructor<? extends Composite> proxyConstructor;
-
-    protected CompositeModel( final Iterable<Class<?>> types,
-                              final Visibility visibility,
-                              final MetaInfo metaInfo,
-                              final MixinsModel mixinsModel,
-                              final StateModel stateModel,
-                              final CompositeMethodsModel compositeMethodsModel
-    )
-    {
-        this.types = Iterables.addAll( new LinkedHashSet<Class<?>>(), types );
-        this.visibility = visibility;
-        this.metaInfo = metaInfo;
-        this.stateModel = stateModel;
-        this.compositeMethodsModel = compositeMethodsModel;
-        this.mixinsModel = mixinsModel;
-
-        // Create proxy class
-        createProxyClass();
-    }
-
-    // Model
-    @Override
-    public Iterable<Class<?>> types()
-    {
-        return types;
-    }
-
-    public StateModel state()
-    {
-        return stateModel;
-    }
-
-    @Override
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return metaInfo.get( infoType );
-    }
-
-    @Override
-    public Visibility visibility()
-    {
-        return visibility;
-    }
-
-    @Override
-    public boolean isAssignableTo( Class<?> type )
-    {
-        for( Class<?> aClass : types )
-        {
-            if( type.isAssignableFrom( aClass ) )
-            {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public MixinsModel mixinsModel()
-    {
-        return mixinsModel;
-    }
-
-    @Override
-    @SuppressWarnings( { "raw", "unchecked" } )
-    public Class<?> primaryType()
-    {
-        Class primaryType = null;
-        for( Class type : mixinTypes() )
-        {
-            if( type.getName().equals( "scala.ScalaObject" ) )
-            {
-                continue;
-            }
-            if( primaryType == null )
-            {
-                primaryType = type;
-            }
-            else if( primaryType.isAssignableFrom( type ) )
-            {
-                primaryType = type;
-            }
-        }
-        return primaryType;
-    }
-
-    @Override
-    public Iterable<Class<?>> mixinTypes()
-    {
-        return mixinsModel.mixinTypes();
-    }
-
-    @Override
-    public Iterable<DependencyModel> dependencies()
-    {
-        return Iterables.flatten( mixinsModel.dependencies(), compositeMethodsModel.dependencies() );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            if( compositeMethodsModel.accept( visitor ) )
-            {
-                if( stateModel.accept( visitor ) )
-                {
-                    mixinsModel.accept( visitor );
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-
-    @SuppressWarnings( { "raw", "unchecked" } )
-    private void createProxyClass()
-    {
-        Class<?> mainType = first( types );
-        if( mainType.isInterface() )
-        {
-            ClassLoader proxyClassloader = mainType.getClassLoader();
-
-            Class<?>[] interfaces = Iterables.toArray( Class.class, Iterables.<Class>cast( types ) );
-            proxyClass = (Class<? extends Composite>) ProxyGenerator.createProxyClass( proxyClassloader, interfaces );
-
-            try
-            {
-                proxyConstructor = proxyClass.getConstructor( InvocationHandler.class );
-            }
-            catch( NoSuchMethodException e )
-            {
-                throw (InvalidCompositeException) new InvalidCompositeException( "Could not get proxy constructor" ).initCause( e );
-            }
-            proxyConstructor.setAccessible( true );
-        }
-        else
-        {
-            try
-            {
-                proxyClass = new TransientClassLoader( getClass().getClassLoader() ).loadFragmentClass( mainType );
-                proxyConstructor = (Constructor<? extends Composite>) proxyClass.getConstructors()[ 0 ];
-            }
-            catch( ClassNotFoundException e )
-            {
-                throw (InvalidCompositeException) new InvalidCompositeException( "Could not get proxy constructor" ).initCause( e );
-            }
-        }
-    }
-
-    // Context
-    public final Object invoke( MixinsInstance mixins,
-                                Object proxy,
-                                Method method,
-                                Object[] args,
-                                ModuleSpi moduleInstance
-    )
-        throws Throwable
-    {
-        return compositeMethodsModel.invoke( mixins, proxy, method, args, moduleInstance );
-    }
-
-    public Composite newProxy( InvocationHandler invocationHandler )
-        throws ConstructionException
-    {
-        Class<?> mainType = first( types() );
-        if( mainType.isInterface() )
-        {
-
-            try
-            {
-                return Composite.class.cast( proxyConstructor.newInstance( invocationHandler ) );
-            }
-            catch( Exception e )
-            {
-                throw new ConstructionException( e );
-            }
-        }
-        else
-        {
-            try
-            {
-                Object[] args = new Object[ proxyConstructor.getParameterTypes().length ];
-                Composite composite = Composite.class.cast( proxyConstructor.newInstance( args ) );
-                proxyClass.getField( "_instance" ).set( composite, invocationHandler );
-                return composite;
-            }
-            catch( Exception e )
-            {
-                throw new ConstructionException( e );
-            }
-        }
-    }
-
-    @SuppressWarnings( "raw" )
-    public <T> T newProxy( InvocationHandler invocationHandler, Class<T> mixinType )
-        throws IllegalArgumentException
-    {
-
-//        if (!matchesAny( isAssignableFrom( mixinType ), types ))
-        if( !mixinsModel.isImplemented( mixinType ) )
-        {
-            String message = "Composite " + primaryType().getName() + " does not implement type " + mixinType.getName();
-            throw new IllegalArgumentException( message );
-        }
-
-        // Instantiate proxy for given mixin interface
-        return mixinType.cast( newProxyInstance( mixinType.getClassLoader(), new Class[]{ mixinType }, invocationHandler ) );
-    }
-
-    @Override
-    public String toString()
-    {
-        return toList( types ).toString();
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConcernModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/ConcernModel.java
deleted file mode 100644
index 893737c..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConcernModel.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import org.qi4j.api.concern.ConcernDescriptor;
-
-/**
- * JAVADOC
- */
-public final class ConcernModel extends AbstractModifierModel
-    implements ConcernDescriptor
-{
-    public ConcernModel( Class concernClass, Class instantiationClass )
-    {
-        super( concernClass, instantiationClass );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConcernsInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/ConcernsInstance.java
deleted file mode 100644
index b65d52d..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConcernsInstance.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- * JAVADOC
- */
-public final class ConcernsInstance
-    implements InvocationHandler
-{
-    private final InvocationHandler firstConcern;
-    private final FragmentInvocationHandler mixinInvocationHandler;
-    private final ProxyReferenceInvocationHandler proxyHandler;
-
-    public ConcernsInstance( InvocationHandler firstConcern,
-                             FragmentInvocationHandler mixinInvocationHandler,
-                             ProxyReferenceInvocationHandler proxyHandler
-    )
-    {
-        this.firstConcern = firstConcern;
-        this.mixinInvocationHandler = mixinInvocationHandler;
-        this.proxyHandler = proxyHandler;
-    }
-
-    public boolean isEmpty()
-    {
-        return firstConcern == mixinInvocationHandler;
-    }
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] params )
-        throws Throwable
-    {
-        proxyHandler.setProxy( proxy );
-        try
-        {
-            return firstConcern.invoke( proxy, method, params );
-        }
-        catch( InvocationTargetException e )
-        {
-            throw e.getTargetException();
-        }
-        finally
-        {
-            proxyHandler.clearProxy();
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConcernsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/ConcernsModel.java
deleted file mode 100644
index 74882f7..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConcernsModel.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.util.Collections;
-import java.util.List;
-import org.qi4j.api.concern.ConcernsDescriptor;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.injection.Dependencies;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.spi.module.ModuleSpi;
-
-/**
- * JAVADOC
- */
-public final class ConcernsModel
-    implements ConcernsDescriptor, Dependencies, VisitableHierarchy<Object, Object>
-{
-    public static final ConcernsModel EMPTY_CONCERNS = new ConcernsModel( Collections.<ConcernModel>emptyList() );
-
-    private List<ConcernModel> concernsFor;
-
-    public ConcernsModel( List<ConcernModel> concernsFor )
-    {
-        this.concernsFor = concernsFor;
-    }
-
-    @Override
-    public Iterable<DependencyModel> dependencies()
-    {
-        return Iterables.flattenIterables( Iterables.map( Dependencies.DEPENDENCIES_FUNCTION, concernsFor ) );
-    }
-
-    // Context
-    public ConcernsInstance newInstance( Method method, ModuleSpi moduleInstance,
-                                         FragmentInvocationHandler mixinInvocationHandler
-    )
-    {
-        ProxyReferenceInvocationHandler proxyHandler = new ProxyReferenceInvocationHandler();
-        InvocationHandler nextConcern = mixinInvocationHandler;
-        for( int i = concernsFor.size() - 1; i >= 0; i-- )
-        {
-            ConcernModel concernModel = concernsFor.get( i );
-
-            nextConcern = concernModel.newInstance( moduleInstance, nextConcern, proxyHandler, method );
-        }
-
-        return new ConcernsInstance( nextConcern, mixinInvocationHandler, proxyHandler );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
-        throws ThrowableType
-    {
-        if( modelVisitor.visitEnter( this ) )
-        {
-            for( ConcernModel concernModel : concernsFor )
-            {
-                if( !concernModel.accept( modelVisitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return modelVisitor.visitLeave( this );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintDeclaration.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintDeclaration.java
deleted file mode 100644
index 048c4ed..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintDeclaration.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.api.util.Classes;
-
-/**
- * JAVADOC
- */
-public final class ConstraintDeclaration
-{
-    private final Class<? extends Constraint<?, ?>> constraintClass;
-    @SuppressWarnings( "raw" )
-    private final Class constraintAnnotationType;
-    private final Type constraintValueType;
-
-    @SuppressWarnings( "unchecked" )
-    public ConstraintDeclaration( Class<? extends Constraint<?, ?>> constraintClass )
-    {
-        this.constraintClass = constraintClass;
-
-        constraintAnnotationType = (Class<? extends Annotation>) ( (ParameterizedType) constraintClass.getGenericInterfaces()[ 0 ] )
-            .getActualTypeArguments()[ 0 ];
-        constraintValueType = ( (ParameterizedType) constraintClass.getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[ 1 ];
-    }
-
-    public Class<? extends Constraint<?, ?>> constraintClass()
-    {
-        return constraintClass;
-    }
-
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public boolean appliesTo( Class annotationType, Type valueType )
-    {
-        if( constraintValueType instanceof Class )
-        {
-            Class constraintValueClass = (Class) constraintValueType;
-            Class valueClass = Classes.RAW_CLASS.map( valueType );
-            return constraintAnnotationType.equals( annotationType ) && constraintValueClass.isAssignableFrom( valueClass );
-        }
-        else if( constraintValueType instanceof ParameterizedType )
-        {
-            // TODO Handle nested generics
-            Class constraintValueClass = Classes.RAW_CLASS.map( constraintValueType );
-            Class valueClass = Classes.RAW_CLASS.map( valueType );
-            return constraintAnnotationType.equals( annotationType ) && constraintValueClass.isAssignableFrom( valueClass );
-        }
-        else
-        {
-            return false; // TODO Handles more cases. What are they?
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintInstance.java
deleted file mode 100644
index fc563e1..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintInstance.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.annotation.Annotation;
-import org.qi4j.api.constraint.Constraint;
-
-/**
- * JAVADOC
- */
-public final class ConstraintInstance<A extends Annotation, T>
-{
-    private final Constraint<A, T> constraint;
-    private final A annotation;
-
-    public ConstraintInstance( Constraint<A, T> constraint, A annotation )
-    {
-        this.constraint = constraint;
-        this.annotation = annotation;
-    }
-
-    public A annotation()
-    {
-        return annotation;
-    }
-
-    public boolean isValid( T value )
-    {
-        return constraint.isValid( annotation, value );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintModel.java
deleted file mode 100644
index df891d8..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintModel.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.annotation.Annotation;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.constraint.Constraint;
-
-/**
- * JAVADOC
- */
-public final class ConstraintModel
-    extends AbstractConstraintModel
-{
-    private final Class<? extends Constraint<?, ?>> constraintClass;
-
-    public ConstraintModel( Annotation annotation, Class<? extends Constraint<?, ?>> constraintClass )
-    {
-        super( annotation );
-        this.constraintClass = constraintClass;
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public ConstraintInstance<?, ?> newInstance()
-    {
-        try
-        {
-            Constraint<?, ?> constraint = constraintClass.newInstance();
-            return new ConstraintInstance( constraint, annotation );
-        }
-        catch( Exception e )
-        {
-            throw new ConstructionException( "Could not instantiate constraint implementation", e );
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintsCheck.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintsCheck.java
deleted file mode 100644
index 59737d0..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintsCheck.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import org.qi4j.api.constraint.ConstraintViolationException;
-
-/**
- * Call this to perform a value constraint check
- */
-public interface ConstraintsCheck
-{
-    public void checkConstraints( Object value )
-        throws ConstraintViolationException;
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintsInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintsInstance.java
deleted file mode 100644
index 35fc533..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintsInstance.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.api.constraint.ConstraintViolation;
-import org.qi4j.api.constraint.ConstraintViolationException;
-
-import static org.qi4j.functional.Iterables.iterable;
-
-/**
- * JAVADOC
- */
-public final class ConstraintsInstance
-{
-    private final List<ValueConstraintsInstance> valueConstraintsInstances;
-
-    public ConstraintsInstance( List<ValueConstraintsInstance> parameterConstraints )
-    {
-        valueConstraintsInstances = parameterConstraints;
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public void checkValid( Object instance, Method method, Object[] params )
-        throws ConstraintViolationException
-    {
-        if( valueConstraintsInstances.isEmpty() )
-        {
-            return; // No constraints to check
-        }
-
-        // Check constraints
-        List<ConstraintViolation> violations = null;
-        for( int i = 0; i < params.length; i++ )
-        {
-            Object param = params[ i ];
-            List<ConstraintViolation> paramViolations = valueConstraintsInstances.get( i ).checkConstraints( param );
-            if( !paramViolations.isEmpty() )
-            {
-                if( violations == null )
-                {
-                    violations = new ArrayList<>();
-                }
-                violations.addAll( paramViolations );
-            }
-        }
-
-        // Check if any constraint failed
-        if( violations != null )
-        {
-            if( instance instanceof Composite )
-            {
-                throw new ConstraintViolationException( (Composite) instance, method, violations );
-            }
-            if( instance instanceof CompositeInstance )
-            {
-                throw new ConstraintViolationException( (Composite) ( (CompositeInstance) instance ).proxy(), method, violations );
-            }
-            Iterable<? extends Class<?>> types = iterable( instance.getClass() );
-            throw new ConstraintViolationException( instance.toString(), (Iterable<Class<?>>) types, method, violations );
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintsModel.java
deleted file mode 100644
index a71d05d..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstraintsModel.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import org.qi4j.api.constraint.ConstraintsDescriptor;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-
-/**
- * JAVADOC
- */
-public final class ConstraintsModel
-    implements ConstraintsDescriptor, VisitableHierarchy<Object, Object>
-{
-    private List<ValueConstraintsModel> parameterConstraintModels;
-
-    private static ConstraintsInstance EMPTY_CONSTRAINTS = new ConstraintsInstance( Collections.<ValueConstraintsInstance>emptyList() );
-
-    public ConstraintsModel( List<ValueConstraintsModel> parameterConstraintModels )
-    {
-        this.parameterConstraintModels = parameterConstraintModels;
-    }
-
-    public ConstraintsInstance newInstance()
-    {
-        if( parameterConstraintModels.isEmpty() )
-        {
-            return EMPTY_CONSTRAINTS;
-        }
-        else
-        {
-            List<ValueConstraintsInstance> parameterConstraintsInstances = new ArrayList<ValueConstraintsInstance>( parameterConstraintModels
-                                                                                                                        .size() );
-            for( ValueConstraintsModel parameterConstraintModel : parameterConstraintModels )
-            {
-                parameterConstraintsInstances.add( parameterConstraintModel.newInstance() );
-            }
-            return new ConstraintsInstance( parameterConstraintsInstances );
-        }
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
-        throws ThrowableType
-    {
-        if( modelVisitor.visitEnter( this ) )
-        {
-            if( parameterConstraintModels != null )
-            {
-                for( ValueConstraintsModel parameterConstraintModel : parameterConstraintModels )
-                {
-                    if( !parameterConstraintModel.accept( modelVisitor ) )
-                    {
-                        break;
-                    }
-                }
-            }
-        }
-        return modelVisitor.visitLeave( this );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstructorModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstructorModel.java
deleted file mode 100644
index 072168e..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstructorModel.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Arrays;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.composite.ConstructorDescriptor;
-import org.qi4j.api.composite.InvalidCompositeException;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.runtime.injection.InjectedParametersModel;
-import org.qi4j.runtime.injection.InjectionContext;
-
-/**
- * JAVADOC
- */
-public final class ConstructorModel
-    implements ConstructorDescriptor, VisitableHierarchy<Object, Object>
-{
-    private Constructor<?> constructor;
-
-    private InjectedParametersModel parameters;
-
-    public ConstructorModel( Constructor<?> constructor, InjectedParametersModel parameters )
-    {
-        this.constructor = constructor;
-        this.parameters = parameters;
-        this.constructor.setAccessible( true );
-    }
-
-    @Override
-    public Constructor<?> constructor()
-    {
-        return constructor;
-    }
-
-    public Iterable<DependencyModel> dependencies()
-    {
-        return parameters.dependencies();
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
-        throws ThrowableType
-    {
-        if( modelVisitor.visitEnter( this ) )
-        {
-            parameters.accept( modelVisitor );
-        }
-
-        return modelVisitor.visitLeave( this );
-    }
-
-    // Context
-
-    public Object newInstance( InjectionContext context )
-        throws ConstructionException
-    {
-        // Create parameters
-        Object[] parametersInstance = parameters.newParametersInstance( context );
-        // Invoke constructor
-        try
-        {
-            return constructor.newInstance( parametersInstance );
-        }
-        catch( InvocationTargetException e )
-        {
-            Throwable targetException = e.getTargetException();
-            if( targetException instanceof InvalidCompositeException )
-            {
-                throw (InvalidCompositeException) targetException;
-            }
-            String message = "Could not instantiate \n    " + constructor.getDeclaringClass() + "\nusing constructor:\n    " + constructor
-                .toGenericString();
-            throw new ConstructionException( message, targetException );
-        }
-        catch( Throwable e )
-        {
-            System.err.println( constructor.toGenericString() );
-            System.err.println( Arrays.asList( parametersInstance ) );
-            throw new ConstructionException( "Could not instantiate " + constructor.getDeclaringClass(), e );
-        }
-    }
-
-    @Override
-    public String toString()
-    {
-        return constructor.toGenericString();
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstructorsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstructorsModel.java
deleted file mode 100644
index f482d3b..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/ConstructorsModel.java
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.composite.InvalidCompositeException;
-import org.qi4j.api.injection.InjectionScope;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.util.Annotations;
-import org.qi4j.api.util.Classes;
-import org.qi4j.bootstrap.BindingException;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.HierarchicalVisitorAdapter;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specifications;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.injection.Dependencies;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.runtime.injection.InjectedParametersModel;
-import org.qi4j.runtime.injection.InjectionContext;
-import org.qi4j.runtime.injection.ParameterizedTypeInstance;
-import org.qi4j.runtime.model.Binder;
-import org.qi4j.runtime.model.Resolution;
-
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.iterable;
-
-/**
- * JAVADOC
- */
-public final class ConstructorsModel
-    implements Binder, Dependencies, VisitableHierarchy<Object, Object>
-{
-    @SuppressWarnings( "raw" )
-    private final Class fragmentClass;
-    private final List<ConstructorModel> constructorModels;
-    private List<ConstructorModel> boundConstructors;
-
-    @SuppressWarnings( { "raw", "unchecked" } )
-    public ConstructorsModel( Class fragmentClass )
-    {
-        this.fragmentClass = fragmentClass;
-        validate( fragmentClass );
-        constructorModels = new ArrayList<>();
-        Constructor[] realConstructors = this.fragmentClass.getDeclaredConstructors();
-        Class injectionClass = FragmentClassLoader.getSourceClass( fragmentClass );
-        for( Constructor constructor : realConstructors )
-        {
-            constructor.setAccessible( true );
-            try
-            {
-                Constructor injectionConstructor = injectionClass.getDeclaredConstructor( constructor.getParameterTypes() );
-                injectionConstructor.setAccessible( true );
-                ConstructorModel constructorModel = newConstructorModel( this.fragmentClass, constructor,
-                                                                         injectionConstructor );
-                if( constructorModel != null )
-                {
-                    constructorModels.add( constructorModel );
-                }
-            }
-            catch( NoSuchMethodException e )
-            {
-                // Ignore and continue
-                e.printStackTrace();
-            }
-        }
-    }
-
-    @SuppressWarnings( "raw" )
-    private void validate( Class fragmentClass )
-    {
-        // Ensure that the fragment class is not an inner class, in which case we should give a reasonable exception
-        if( fragmentClass.getDeclaringClass() == null )
-        {
-            return;
-        }
-        if( Modifier.isStatic( fragmentClass.getModifiers() ) )
-        {
-            return;
-        }
-        throw new InvalidCompositeException( "Inner classes can not be used. Use static nested classes instead: " + fragmentClass );
-    }
-
-    @Override
-    public Iterable<DependencyModel> dependencies()
-    {
-        Function<ConstructorModel, Iterable<DependencyModel>> constructorDependencies = new Function<ConstructorModel, Iterable<DependencyModel>>()
-        {
-            @Override
-            public Iterable<DependencyModel> map( ConstructorModel constructorModel )
-            {
-                return constructorModel.dependencies();
-            }
-        };
-
-        return Iterables.flattenIterables( Iterables.map( constructorDependencies, boundConstructors == null ? constructorModels : boundConstructors ) );
-    }
-
-    @SuppressWarnings( "raw" )
-    private ConstructorModel newConstructorModel( Class fragmentClass,
-                                                  Constructor realConstructor,
-                                                  Constructor injectedConstructor
-    )
-    {
-        int idx = 0;
-        InjectedParametersModel parameters = new InjectedParametersModel();
-        Annotation[][] parameterAnnotations = injectedConstructor.getParameterAnnotations();
-        for( Type type : injectedConstructor.getGenericParameterTypes() )
-        {
-            Annotation injectionAnnotation = first(
-                filter( Specifications.translate( Annotations.type(), Annotations.hasAnnotation( InjectionScope.class ) ), iterable( parameterAnnotations[ idx ] ) ) );
-
-            if( injectionAnnotation == null )
-            {
-                if( fragmentClass.getSuperclass().isMemberClass() )
-                {
-                    injectionAnnotation = new Uses()
-                    {
-                        @Override
-                        public Class<? extends Annotation> annotationType()
-                        {
-                            return Uses.class;
-                        }
-                    };
-                }
-                else
-                {
-                    return null; // invalid constructor parameter
-                }
-            }
-
-            boolean optional = DependencyModel.isOptional( injectionAnnotation, parameterAnnotations[ idx ] );
-
-            Type genericType = type;
-            if( genericType instanceof ParameterizedType )
-            {
-                genericType = new ParameterizedTypeInstance( ( (ParameterizedType) genericType ).getActualTypeArguments(), ( (ParameterizedType) genericType )
-                    .getRawType(), ( (ParameterizedType) genericType ).getOwnerType() );
-
-                for( int i = 0; i < ( (ParameterizedType) genericType ).getActualTypeArguments().length; i++ )
-                {
-                    Type typeArg = ( (ParameterizedType) genericType ).getActualTypeArguments()[ i ];
-                    if( typeArg instanceof TypeVariable )
-                    {
-                        typeArg = Classes.resolveTypeVariable( (TypeVariable) typeArg, realConstructor.getDeclaringClass(), fragmentClass );
-                        ( (ParameterizedType) genericType ).getActualTypeArguments()[ i ] = typeArg;
-                    }
-                }
-            }
-
-            DependencyModel dependencyModel = new DependencyModel( injectionAnnotation, genericType, fragmentClass, optional,
-                                                                   parameterAnnotations[ idx ] );
-            parameters.addDependency( dependencyModel );
-            idx++;
-        }
-        return new ConstructorModel( realConstructor, parameters );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            if( boundConstructors != null )
-            {
-                for( ConstructorModel constructorModel : boundConstructors )
-                {
-                    if( !constructorModel.accept( visitor ) )
-                    {
-                        break;
-                    }
-                }
-            }
-            else
-            {
-                for( ConstructorModel constructorModel : constructorModels )
-                {
-                    if( !constructorModel.accept( visitor ) )
-                    {
-                        break;
-                    }
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-
-    // Binding
-    @Override
-    public void bind( final Resolution resolution )
-        throws BindingException
-    {
-        boundConstructors = new ArrayList<>();
-        for( ConstructorModel constructorModel : constructorModels )
-        {
-            try
-            {
-                constructorModel.accept( new HierarchicalVisitorAdapter<Object, Object, BindingException>()
-                {
-                    @Override
-                    public boolean visit( Object visitor )
-                        throws BindingException
-                    {
-                        if( visitor instanceof Binder )
-                        {
-                            ( (Binder) visitor ).bind( resolution );
-                        }
-                        return true;
-                    }
-                } );
-                boundConstructors.add( constructorModel );
-            }
-            catch( Exception e )
-            {
-                // Ignore
-                e.printStackTrace();
-            }
-        }
-
-        if( boundConstructors.isEmpty() )
-        {
-            StringBuilder messageBuilder = new StringBuilder( "Found no constructor that could be bound: " );
-            if( resolution.model() instanceof CompositeDescriptor )
-            {
-                messageBuilder.append( fragmentClass.getName() )
-                    .append( " in " )
-                    .append( resolution.model().toString() );
-            }
-            else
-            {
-                messageBuilder.append( resolution.model().toString() );
-            }
-
-            if( messageBuilder.indexOf( "$" ) >= 0 )
-            {
-                // This could be ok if instance is created manually
-                return;
-//                messageBuilder.append( "\nInner classes can not be used." );
-            }
-            String message = messageBuilder.toString();
-            throw new BindingException( message );
-        }
-
-        // Sort based on parameter count
-        Collections.sort( boundConstructors, new Comparator<ConstructorModel>()
-        {
-            @Override
-            public int compare( ConstructorModel o1, ConstructorModel o2 )
-            {
-                Integer model2ParametersCount = o2.constructor().getParameterTypes().length;
-                int model1ParametersCount = o1.constructor().getParameterTypes().length;
-                return model2ParametersCount.compareTo( model1ParametersCount );
-            }
-        } );
-    }
-
-    public Object newInstance( InjectionContext injectionContext )
-    {
-        // Try all bound constructors, in order
-        ConstructionException exception = null;
-        for( ConstructorModel constructorModel : boundConstructors )
-        {
-            try
-            {
-                return constructorModel.newInstance( injectionContext );
-            }
-            catch( ConstructionException e )
-            {
-                exception = e;
-            }
-        }
-
-        throw exception;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/FragmentClassLoader.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/FragmentClassLoader.java
deleted file mode 100644
index 4cf4439..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/FragmentClassLoader.java
+++ /dev/null
@@ -1,852 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.List;
-import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-import org.qi4j.api.entity.Lifecycle;
-import org.qi4j.api.mixin.Initializable;
-import org.qi4j.api.util.Classes;
-import org.qi4j.api.util.Methods;
-import org.qi4j.functional.Iterables;
-
-import static org.objectweb.asm.Opcodes.AASTORE;
-import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
-import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
-import static org.objectweb.asm.Opcodes.ACC_STATIC;
-import static org.objectweb.asm.Opcodes.ACC_SUPER;
-import static org.objectweb.asm.Opcodes.ACONST_NULL;
-import static org.objectweb.asm.Opcodes.ALOAD;
-import static org.objectweb.asm.Opcodes.ANEWARRAY;
-import static org.objectweb.asm.Opcodes.ARETURN;
-import static org.objectweb.asm.Opcodes.ASTORE;
-import static org.objectweb.asm.Opcodes.ATHROW;
-import static org.objectweb.asm.Opcodes.BIPUSH;
-import static org.objectweb.asm.Opcodes.CHECKCAST;
-import static org.objectweb.asm.Opcodes.DLOAD;
-import static org.objectweb.asm.Opcodes.DRETURN;
-import static org.objectweb.asm.Opcodes.DUP;
-import static org.objectweb.asm.Opcodes.FLOAD;
-import static org.objectweb.asm.Opcodes.FRETURN;
-import static org.objectweb.asm.Opcodes.GETFIELD;
-import static org.objectweb.asm.Opcodes.GETSTATIC;
-import static org.objectweb.asm.Opcodes.GOTO;
-import static org.objectweb.asm.Opcodes.ICONST_0;
-import static org.objectweb.asm.Opcodes.ICONST_1;
-import static org.objectweb.asm.Opcodes.ICONST_2;
-import static org.objectweb.asm.Opcodes.ICONST_3;
-import static org.objectweb.asm.Opcodes.ICONST_4;
-import static org.objectweb.asm.Opcodes.ICONST_5;
-import static org.objectweb.asm.Opcodes.ILOAD;
-import static org.objectweb.asm.Opcodes.INVOKEINTERFACE;
-import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
-import static org.objectweb.asm.Opcodes.INVOKESTATIC;
-import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
-import static org.objectweb.asm.Opcodes.IRETURN;
-import static org.objectweb.asm.Opcodes.LLOAD;
-import static org.objectweb.asm.Opcodes.LRETURN;
-import static org.objectweb.asm.Opcodes.POP;
-import static org.objectweb.asm.Opcodes.PUTSTATIC;
-import static org.objectweb.asm.Opcodes.RETURN;
-import static org.objectweb.asm.Type.getInternalName;
-import static org.qi4j.api.util.Classes.interfacesOf;
-
-/**
- * Generate subclasses of mixins/modifiers that implement all interfaces not in the class itself
- * and which delegates those calls to a given composite invoker.
- */
-@SuppressWarnings( "raw" )
-public class FragmentClassLoader
-    extends ClassLoader
-{
-    private static final int JDK_VERSION;
-    public static final String GENERATED_POSTFIX = "_Stub";
-
-    static
-    {
-        String jdkString = System.getProperty( "java.specification.version" );
-        switch( jdkString )
-        {
-            case "1.8":
-                JDK_VERSION = Opcodes.V1_8;
-                break;
-            case "1.7":
-            default:
-                JDK_VERSION = Opcodes.V1_7;
-                break;
-        }
-    }
-
-    public FragmentClassLoader( ClassLoader parent )
-    {
-        super( parent );
-    }
-
-    @Override
-    protected Class findClass( String name )
-        throws ClassNotFoundException
-    {
-        if( name.endsWith( GENERATED_POSTFIX ) )
-        {
-            Class baseClass;
-            String baseName = name.substring( 0, name.length() - 5 );
-            try
-            {
-                baseClass = loadClass( baseName );
-            }
-            catch( ClassNotFoundException e )
-            {
-                // Try replacing the last _ with $
-                while( true )
-                {
-                    int idx = baseName.lastIndexOf( "_" );
-                    if( idx != -1 )
-                    {
-                        baseName = baseName.substring( 0, idx ) + "$" + baseName.substring( idx + 1 );
-                        try
-                        {
-                            baseClass = loadClass( baseName );
-                            break;
-                        }
-                        catch( ClassNotFoundException e1 )
-                        {
-                            // Try again
-                        }
-                    }
-                    else
-                    {
-                        throw e;
-                    }
-                }
-            }
-//  To Allow JDK classes to be composed.
-            if( name.startsWith( "java." ))
-                name = "qi4j." + name;
-
-            byte[] b = generateClass( name, baseClass );
-            return defineClass( name, b, 0, b.length, baseClass.getProtectionDomain() );
-        }
-
-        // Try the classloader of this classloader -> get classes in Zest such as CompositeInvoker
-        return getClass().getClassLoader().loadClass( name );
-    }
-
-    public static byte[] generateClass( String name, Class baseClass )
-        throws ClassNotFoundException
-    {
-        String classSlash = name.replace( '.', '/' );
-        String baseClassSlash = getInternalName( baseClass );
-
-        ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_MAXS );
-
-        // Class definition start
-        cw.visit( JDK_VERSION, ACC_PUBLIC + ACC_SUPER, classSlash, null, baseClassSlash, null );
-
-        // Composite reference
-        {
-            cw.visitField( ACC_PUBLIC, "_instance", "Lorg/qi4j/api/composite/CompositeInvoker;", null, null ).visitEnd();
-        }
-
-        // Static Method references
-        boolean hasProxyMethods = false;
-        {
-            int idx = 1;
-            for( Method method : baseClass.getMethods() )
-            {
-                if( isOverridden(method, baseClass) )
-                {
-                    cw.visitField( ACC_PRIVATE + ACC_STATIC, "m" + idx++, "Ljava/lang/reflect/Method;", null,
-                                        null ).visitEnd();
-                    hasProxyMethods = true;
-                }
-            }
-        }
-
-        // Constructors
-        for( Constructor constructor : baseClass.getDeclaredConstructors() )
-        {
-            if( Modifier.isPublic( constructor.getModifiers() ) || Modifier.isProtected( constructor.getModifiers() ) )
-            {
-                String desc = org.objectweb.asm.commons.Method.getMethod( constructor ).getDescriptor();
-                MethodVisitor cmv = cw.visitMethod( ACC_PUBLIC, "<init>", desc, null, null );
-                cmv.visitCode();
-                cmv.visitVarInsn(ALOAD, 0);
-
-                int idx = 1;
-                for( Class aClass : constructor.getParameterTypes() )
-                {
-                    final int opcode;
-                    if (aClass.equals(Integer.TYPE)) {
-                        opcode = ILOAD;
-                    } else if (aClass.equals(Long.TYPE)) {
-                        opcode = LLOAD;
-                    } else if (aClass.equals(Float.TYPE)) {
-                        opcode = FLOAD;
-                    } else if (aClass.equals(Double.TYPE)) {
-                        opcode = DLOAD;
-                    } else {
-                        opcode = ALOAD;
-                    }
-                    cmv.visitVarInsn(opcode, idx++);
-                }
-
-                cmv.visitMethodInsn(INVOKESPECIAL, baseClassSlash, "<init>", desc, false);
-                cmv.visitInsn(RETURN);
-                cmv.visitMaxs(idx, idx);
-                cmv.visitEnd();
-            }
-        }
-
-
-        // Overloaded and unimplemented methods
-        if( hasProxyMethods )
-        {
-            Method[] methods = baseClass.getMethods();
-            int idx = 0;
-            List<Label> exceptionLabels = new ArrayList<>();
-            for( Method method : methods )
-            {
-                if( isOverridden(method, baseClass) )
-                {
-                    idx++;
-                    String methodName = method.getName();
-                    String desc = org.objectweb.asm.commons.Method.getMethod( method ).getDescriptor();
-
-                    String[] exceptions = null;
-                    {
-                        MethodVisitor mv = cw.visitMethod( ACC_PUBLIC, methodName, desc, null, null );
-                        if( isInternalQi4jMethod( method, baseClass ) )
-                        {
-                            // generate a NoOp method...
-                            mv.visitInsn( RETURN );
-                        }
-                        else
-                        {
-                            Label endLabel = null; // Use this if return type is void
-                            if( method.getExceptionTypes().length > 0 )
-                            {
-                                exceptions = new String[ method.getExceptionTypes().length ];
-                                for( int i = 0; i < method.getExceptionTypes().length; i++ )
-                                {
-                                    Class<?> aClass = method.getExceptionTypes()[ i ];
-                                    exceptions[ i ] = getInternalName( aClass );
-                                }
-                            }
-                            mv.visitCode();
-                            Label l0 = new Label();
-                            Label l1 = new Label();
-
-                            exceptionLabels.clear();
-                            for( Class<?> declaredException : method.getExceptionTypes() )
-                            {
-                                Label ld = new Label();
-                                mv.visitTryCatchBlock( l0, l1, ld, getInternalName( declaredException ) );
-                                exceptionLabels.add( ld ); // Reuse this further down for the catch
-                            }
-
-                            Label lruntime = new Label();
-                            mv.visitTryCatchBlock( l0, l1, lruntime, "java/lang/RuntimeException" );
-                            Label lerror = new Label();
-                            mv.visitTryCatchBlock( l0, l1, lerror, "java/lang/Throwable" );
-
-                            mv.visitLabel( l0 );
-                            mv.visitVarInsn( ALOAD, 0 );
-                            mv.visitFieldInsn( GETFIELD, classSlash, "_instance",
-                                               "Lorg/qi4j/api/composite/CompositeInvoker;" );
-                            mv.visitFieldInsn( GETSTATIC, classSlash, "m" + idx, "Ljava/lang/reflect/Method;" );
-
-                            int paramCount = method.getParameterTypes().length;
-                            int stackIdx = 0;
-                            if( paramCount == 0 )
-                            {
-                                // Send in null as parameter
-                                mv.visitInsn( ACONST_NULL );
-                            }
-                            else
-                            {
-                                insn( mv, paramCount );
-                                mv.visitTypeInsn( ANEWARRAY, "java/lang/Object" );
-                                int pidx = 0;
-                                for( Class<?> aClass : method.getParameterTypes() )
-                                {
-                                    mv.visitInsn( DUP );
-                                    insn( mv, pidx++ );
-                                    stackIdx = wrapParameter( mv, aClass, stackIdx + 1 );
-                                    mv.visitInsn( AASTORE );
-                                }
-                            }
-
-                            // Call method
-                            mv.visitMethodInsn( INVOKEINTERFACE, "org/qi4j/api/composite/CompositeInvoker",
-                                                "invokeComposite",
-                                                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true );
-
-                            // Return value
-                            if( !method.getReturnType().equals( Void.TYPE ) )
-                            {
-                                unwrapResult( mv, method.getReturnType(), l1 );
-                            }
-                            else
-                            {
-                                mv.visitInsn( POP );
-                                mv.visitLabel( l1 );
-                                endLabel = new Label();
-                                mv.visitJumpInsn( GOTO, endLabel );
-                            }
-
-                            // Increase stack to beyond method args
-                            stackIdx++;
-
-                            // Declared exceptions
-                            int exceptionIdx = 0;
-                            for( Class<?> aClass : method.getExceptionTypes() )
-                            {
-                                mv.visitLabel( exceptionLabels.get( exceptionIdx++ ) );
-                                mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ getInternalName( aClass ) } );
-                                mv.visitVarInsn( ASTORE, stackIdx );
-                                mv.visitVarInsn( ALOAD, stackIdx );
-                                mv.visitInsn( ATHROW );
-                            }
-
-                            // RuntimeException and Error catch-all
-                            mv.visitLabel( lruntime );
-                            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/RuntimeException" } );
-                            mv.visitVarInsn( ASTORE, stackIdx );
-                            mv.visitVarInsn( ALOAD, stackIdx );
-                            mv.visitInsn( ATHROW );
-
-                            mv.visitLabel( lerror );
-                            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/Throwable" } );
-                            mv.visitVarInsn( ASTORE, stackIdx );
-                            mv.visitVarInsn( ALOAD, stackIdx );
-                            mv.visitTypeInsn( CHECKCAST, "java/lang/Error" );
-                            mv.visitInsn( ATHROW );
-
-                            // Return type = void
-                            if( endLabel != null )
-                            {
-                                mv.visitLabel( endLabel );
-                                mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
-                                mv.visitInsn( RETURN );
-                            }
-
-                            mv.visitMaxs( 0, 0 );
-                            mv.visitEnd();
-                        }
-                    }
-
-                    if( !Modifier.isAbstract( method.getModifiers() ) )
-                    {
-                        // Add method with _ as prefix
-                        MethodVisitor mv;
-                        mv = cw.visitMethod( ACC_PUBLIC, "_" + method.getName(), desc, null, exceptions );
-                        mv.visitCode();
-                        mv.visitVarInsn( ALOAD, 0 );
-
-                        // Parameters
-                        int stackIdx = 1;
-                        for( Class<?> aClass : method.getParameterTypes() )
-                        {
-                            stackIdx = loadParameter( mv, aClass, stackIdx ) + 1;
-                        }
-
-                        // Call method
-                        mv.visitMethodInsn( INVOKESPECIAL, baseClassSlash, method.getName(), desc, false );
-
-                        // Return value
-                        if( !method.getReturnType().equals( Void.TYPE ) )
-                        {
-                            returnResult( mv, method.getReturnType() );
-                        }
-                        else
-                        {
-                            mv.visitInsn( RETURN );
-                        }
-
-                        mv.visitMaxs( 1, 1 );
-                        mv.visitEnd();
-                    }
-                }
-            }
-
-            // Class initializer
-            {
-                MethodVisitor mv;
-                mv = cw.visitMethod( ACC_STATIC, "<clinit>", "()V", null, null );
-                mv.visitCode();
-                Label l0 = new Label();
-                Label l1 = new Label();
-                Label l2 = new Label();
-                mv.visitTryCatchBlock( l0, l1, l2, "java/lang/NoSuchMethodException" );
-                mv.visitLabel( l0 );
-
-                // Lookup methods and store in static variables
-                int midx = 0;
-                for( Method method : methods )
-                {
-                    if( isOverridden(method, baseClass) )
-                    {
-                        method.setAccessible( true );
-                        Class methodClass;
-                        if( Modifier.isAbstract( method.getModifiers() ) )
-                        {
-                            methodClass = method.getDeclaringClass();
-                        }
-                        else
-                        {
-                            try
-                            {
-                                methodClass = getInterfaceMethodDeclaration( method,
-                                                                             baseClass ); // Overridden method lookup
-                            }
-                            catch( NoSuchMethodException e )
-                            {
-                                throw new ClassNotFoundException( name, e );
-                            }
-                        }
-
-                        midx++;
-
-                        mv.visitLdcInsn( Type.getType( methodClass ) );
-                        mv.visitLdcInsn( method.getName() );
-                        insn( mv, method.getParameterTypes().length );
-                        mv.visitTypeInsn( ANEWARRAY, "java/lang/Class" );
-
-                        int pidx = 0;
-                        for( Class<?> aClass : method.getParameterTypes() )
-                        {
-                            mv.visitInsn( DUP );
-                            insn( mv, pidx++ );
-                            type( mv, aClass );
-                            mv.visitInsn( AASTORE );
-                        }
-
-                        mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getMethod",
-                                            "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false );
-                        mv.visitFieldInsn( PUTSTATIC, classSlash, "m" + midx, "Ljava/lang/reflect/Method;" );
-                    }
-                }
-
-                mv.visitLabel( l1 );
-                Label l3 = new Label();
-                mv.visitJumpInsn( GOTO, l3 );
-                mv.visitLabel( l2 );
-                mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/NoSuchMethodException" } );
-                mv.visitVarInsn( ASTORE, 0 );
-                mv.visitVarInsn( ALOAD, 0 );
-                mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/NoSuchMethodException", "printStackTrace", "()V", false );
-                mv.visitLabel( l3 );
-                mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
-                mv.visitInsn( RETURN );
-                mv.visitMaxs( 6, 1 );
-                mv.visitEnd();
-            }
-        }
-        cw.visitEnd();
-        return cw.toByteArray();
-    }
-
-    private static boolean isOverridden(Method method, Class baseClass)
-    {
-        if( Modifier.isAbstract( method.getModifiers() ) )
-        {
-            return true; // Implement all abstract methods
-        }
-
-        if( Modifier.isFinal( method.getModifiers() ) )
-        {
-            return false; // Cannot override final methods
-        }
-
-        if( isInterfaceMethod( method, baseClass ) )
-        {
-            // if() used for clarity.
-            //noinspection RedundantIfStatement
-            if( isInternalQi4jMethod( method, baseClass ) )
-            {
-                return false; // Skip methods in Zest-internal interfaces
-            }
-            else
-            {
-                return true;
-            }
-        }
-        else
-        {
-            return false;
-        }
-    }
-
-    private static boolean isInternalQi4jMethod( Method method, Class baseClass )
-    {
-        return isDeclaredIn( method, Initializable.class, baseClass )
-               || isDeclaredIn( method, Lifecycle.class, baseClass );
-    }
-
-    private static boolean isDeclaredIn( Method method, Class<?> clazz, Class<?> baseClass )
-    {
-        if( !clazz.isAssignableFrom( baseClass ) )
-        {
-            return false;
-        }
-
-        try
-        {
-            clazz.getMethod( method.getName(), method.getParameterTypes() );
-            return true;
-        }
-        catch( NoSuchMethodException e )
-        {
-            return false;
-        }
-    }
-
-    private static Class getInterfaceMethodDeclaration( Method method, Class clazz )
-        throws NoSuchMethodException
-    {
-        Iterable<Class<?>> interfaces = Iterables.map( Classes.RAW_CLASS, interfacesOf( clazz ) );
-        for( Class<?> anInterface : interfaces )
-        {
-            try
-            {
-                anInterface.getMethod( method.getName(), method.getParameterTypes() );
-                return anInterface;
-            }
-            catch( NoSuchMethodException e )
-            {
-                // Try next
-            }
-        }
-
-        throw new NoSuchMethodException( method.getName() );
-    }
-
-    private static boolean isInterfaceMethod( Method method, Class<?> baseClass )
-    {
-        for( Class<?> aClass : Iterables.filter( Methods.HAS_METHODS, Iterables.map( Classes.RAW_CLASS, interfacesOf( baseClass ) ) ) )
-        {
-            try
-            {
-                Method m = aClass.getMethod( method.getName(), method.getParameterTypes() );
-                m.setAccessible( true );
-                return true;
-            }
-            catch( NoSuchMethodException e )
-            {
-                // Ignore
-            }
-        }
-        return false;
-    }
-
-    private static void type( MethodVisitor mv, Class<?> aClass )
-    {
-        if( aClass.equals( Integer.TYPE ) )
-        {
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;" );
-        }
-        else if( aClass.equals( Long.TYPE ) )
-        {
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;" );
-        }
-        else if( aClass.equals( Short.TYPE ) )
-        {
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;" );
-        }
-        else if( aClass.equals( Byte.TYPE ) )
-        {
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;" );
-        }
-        else if( aClass.equals( Double.TYPE ) )
-        {
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;" );
-        }
-        else if( aClass.equals( Float.TYPE ) )
-        {
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;" );
-        }
-        else if( aClass.equals( Boolean.TYPE ) )
-        {
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;" );
-        }
-        else if( aClass.equals( Character.TYPE ) )
-        {
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;" );
-        }
-        else
-        {
-            mv.visitLdcInsn( Type.getType( aClass ) );
-        }
-    }
-
-    private static int wrapParameter( MethodVisitor mv, Class<?> aClass, int idx )
-    {
-        if( aClass.equals( Integer.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false );
-        }
-        else if( aClass.equals( Long.TYPE ) )
-        {
-            mv.visitVarInsn( LLOAD, idx );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false );
-            idx++; // Extra jump
-        }
-        else if( aClass.equals( Short.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false );
-        }
-        else if( aClass.equals( Byte.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false );
-        }
-        else if( aClass.equals( Double.TYPE ) )
-        {
-            mv.visitVarInsn( DLOAD, idx );
-            idx++; // Extra jump
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false );
-        }
-        else if( aClass.equals( Float.TYPE ) )
-        {
-            mv.visitVarInsn( FLOAD, idx );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false );
-        }
-        else if( aClass.equals( Boolean.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false );
-        }
-        else if( aClass.equals( Character.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false );
-        }
-        else
-        {
-            mv.visitVarInsn( ALOAD, idx );
-        }
-
-        return idx;
-    }
-
-    private static void unwrapResult( MethodVisitor mv, Class<?> aClass, Label label )
-    {
-        if( aClass.equals( Integer.TYPE ) )
-        {
-            mv.visitTypeInsn( CHECKCAST, "java/lang/Integer" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false );
-            mv.visitLabel( label );
-            mv.visitInsn( IRETURN );
-        }
-        else if( aClass.equals( Long.TYPE ) )
-        {
-            mv.visitTypeInsn( CHECKCAST, "java/lang/Long" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false );
-            mv.visitLabel( label );
-            mv.visitInsn( LRETURN );
-        }
-        else if( aClass.equals( Short.TYPE ) )
-        {
-            mv.visitTypeInsn( CHECKCAST, "java/lang/Short" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false );
-            mv.visitLabel( label );
-            mv.visitInsn( IRETURN );
-        }
-        else if( aClass.equals( Byte.TYPE ) )
-        {
-            mv.visitTypeInsn( CHECKCAST, "java/lang/Byte" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false );
-            mv.visitLabel( label );
-            mv.visitInsn( IRETURN );
-        }
-        else if( aClass.equals( Double.TYPE ) )
-        {
-            mv.visitTypeInsn( CHECKCAST, "java/lang/Double" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false );
-            mv.visitLabel( label );
-            mv.visitInsn( DRETURN );
-        }
-        else if( aClass.equals( Float.TYPE ) )
-        {
-            mv.visitTypeInsn( CHECKCAST, "java/lang/Float" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false );
-            mv.visitLabel( label );
-            mv.visitInsn( FRETURN );
-        }
-        else if( aClass.equals( Boolean.TYPE ) )
-        {
-            mv.visitTypeInsn( CHECKCAST, "java/lang/Boolean" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false );
-            mv.visitLabel( label );
-            mv.visitInsn( IRETURN );
-        }
-        else if( aClass.equals( Character.TYPE ) )
-        {
-            mv.visitTypeInsn( CHECKCAST, "java/lang/Character" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false );
-            mv.visitLabel( label );
-            mv.visitInsn( IRETURN );
-        }
-        else
-        {
-            mv.visitTypeInsn( CHECKCAST, getInternalName( aClass ) );
-            mv.visitLabel( label );
-            mv.visitInsn( ARETURN );
-        }
-    }
-
-    private static int loadParameter( MethodVisitor mv, Class<?> aClass, int idx )
-    {
-        if( aClass.equals( Integer.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-        }
-        else if( aClass.equals( Long.TYPE ) )
-        {
-            mv.visitVarInsn( LLOAD, idx );
-            idx++; // Extra jump
-        }
-        else if( aClass.equals( Short.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-        }
-        else if( aClass.equals( Byte.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-        }
-        else if( aClass.equals( Double.TYPE ) )
-        {
-            mv.visitVarInsn( DLOAD, idx );
-            idx++; // Extra jump
-        }
-        else if( aClass.equals( Float.TYPE ) )
-        {
-            mv.visitVarInsn( FLOAD, idx );
-        }
-        else if( aClass.equals( Boolean.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-        }
-        else if( aClass.equals( Character.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-        }
-        else
-        {
-            mv.visitVarInsn( ALOAD, idx );
-        }
-
-        return idx;
-    }
-
-    private static void returnResult( MethodVisitor mv, Class<?> aClass )
-    {
-        if( aClass.equals( Integer.TYPE ) )
-        {
-            mv.visitInsn( IRETURN );
-        }
-        else if( aClass.equals( Long.TYPE ) )
-        {
-            mv.visitInsn( LRETURN );
-        }
-        else if( aClass.equals( Short.TYPE ) )
-        {
-            mv.visitInsn( IRETURN );
-        }
-        else if( aClass.equals( Byte.TYPE ) )
-        {
-            mv.visitInsn( IRETURN );
-        }
-        else if( aClass.equals( Double.TYPE ) )
-        {
-            mv.visitInsn( DRETURN );
-        }
-        else if( aClass.equals( Float.TYPE ) )
-        {
-            mv.visitInsn( FRETURN );
-        }
-        else if( aClass.equals( Boolean.TYPE ) )
-        {
-            mv.visitInsn( IRETURN );
-        }
-        else if( aClass.equals( Character.TYPE ) )
-        {
-            mv.visitInsn( IRETURN );
-        }
-        else
-        {
-            mv.visitTypeInsn( CHECKCAST, getInternalName( aClass ) );
-            mv.visitInsn( ARETURN );
-        }
-    }
-
-    private static void insn( MethodVisitor mv, int length )
-    {
-        switch( length )
-        {
-        case 0:
-            mv.visitInsn( ICONST_0 );
-            return;
-        case 1:
-            mv.visitInsn( ICONST_1 );
-            return;
-        case 2:
-            mv.visitInsn( ICONST_2 );
-            return;
-        case 3:
-            mv.visitInsn( ICONST_3 );
-            return;
-        case 4:
-            mv.visitInsn( ICONST_4 );
-            return;
-        case 5:
-            mv.visitInsn( ICONST_5 );
-            return;
-        default:
-            mv.visitIntInsn( BIPUSH, length );
-        }
-    }
-
-    public static boolean isGenerated( Class clazz )
-    {
-        return clazz.getName().endsWith( GENERATED_POSTFIX );
-    }
-
-    public static boolean isGenerated( Object object )
-    {
-        return object.getClass().getName().endsWith( GENERATED_POSTFIX );
-    }
-
-    public Class loadFragmentClass( Class fragmentClass )
-        throws ClassNotFoundException
-    {
-        return loadClass( fragmentClass.getName().replace( '$', '_' ) + GENERATED_POSTFIX );
-    }
-
-    public static Class getSourceClass( Class fragmentClass )
-    {
-        return fragmentClass.getName().endsWith( GENERATED_POSTFIX ) ? fragmentClass.getSuperclass() : fragmentClass;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/FragmentInvocationHandler.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/FragmentInvocationHandler.java
deleted file mode 100644
index ec656ab..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/FragmentInvocationHandler.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-
-/**
- * JAVADOC
- */
-abstract class FragmentInvocationHandler
-    implements InvocationHandler
-{
-    private static final String COMPACT_TRACE = "qi4j.compacttrace";
-
-    private static final CompactLevel compactLevel;
-
-    static
-    {
-        compactLevel = CompactLevel.valueOf( System.getProperty( COMPACT_TRACE, "proxy" ) );
-    }
-
-    protected Object fragment;
-    protected Method method;
-
-    void setFragment( Object fragment )
-    {
-        this.fragment = fragment;
-    }
-
-    public void setMethod( Method method )
-    {
-        this.method = method;
-    }
-
-    protected Throwable cleanStackTrace( Throwable throwable, Object proxy, Method method )
-    {
-        if( compactLevel == CompactLevel.off )
-        {
-            return throwable;
-        }
-
-        StackTraceElement[] trace = throwable.getStackTrace();
-
-        // Check if exception originated within Zest or JDK - if so then skip compaction
-        if( trace.length == 0 || !isApplicationClass( trace[ 0 ].getClassName() ) )
-        {
-            return throwable;
-        }
-
-        int count = 0;
-        for( int i = 0; i < trace.length; i++ )
-        {
-            StackTraceElement stackTraceElement = trace[ i ];
-            if( !isApplicationClass( stackTraceElement.getClassName() ) )
-            {
-                // TODO: Should find stack entry outside Runtime, and compact beyond that
-                trace[ i ] = null;
-                count++;
-            }
-            else
-            {
-                boolean classOrigin = stackTraceElement.getClassName().equals( proxy.getClass().getSimpleName() );
-                boolean methodOrigin = stackTraceElement.getMethodName().equals( method.getName() );
-                if( classOrigin && methodOrigin && compactLevel == CompactLevel.proxy )
-                {
-                    // Stop removing if the originating method call has been located in the stack.
-                    // For 'semi' and 'extensive' compaction, we don't and do the entire stack instead.
-                    trace[ i ] = new StackTraceElement( proxy.getClass()
-                                                            .getInterfaces()[ 0 ].getName(), method.getName(), null, -1 );
-                    break; // Stop compacting this trace
-                }
-            }
-        }
-
-        // Create new trace array
-        int idx = 0;
-        StackTraceElement[] newTrace = new StackTraceElement[ trace.length - count ];
-        for( StackTraceElement stackTraceElement : trace )
-        {
-            if( stackTraceElement != null )
-            {
-                newTrace[ idx++ ] = stackTraceElement;
-            }
-        }
-        throwable.setStackTrace( newTrace );
-
-        Throwable nested = throwable.getCause();
-        if( nested != null )
-        {
-            //noinspection ThrowableResultOfMethodCallIgnored
-            cleanStackTrace( nested, proxy, method );
-        }
-        return throwable;
-    }
-
-    private boolean isApplicationClass( String className )
-    {
-        if( compactLevel == CompactLevel.semi )
-        {
-            return !isJdkInternals( className );
-        }
-        return !( className.endsWith( FragmentClassLoader.GENERATED_POSTFIX ) ||
-                  className.startsWith( "org.qi4j.runtime" ) ||
-                  isJdkInternals( className ) );
-    }
-
-    private boolean isJdkInternals( String className )
-    {
-        return className.startsWith( "java.lang.reflect" )
-               || className.startsWith( "com.sun.proxy" )
-               || className.startsWith( "sun.reflect" );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/FunctionStateResolver.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/FunctionStateResolver.java
deleted file mode 100644
index 01bcc41..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/FunctionStateResolver.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2012, Kent Sølvsten.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.functional.ForEach;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.runtime.association.ManyAssociationModel;
-import org.qi4j.runtime.association.NamedAssociationModel;
-import org.qi4j.runtime.entity.EntityModel;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.ManyAssociationState;
-import org.qi4j.spi.entity.NamedAssociationState;
-
-/**
- * Function based StateResolver.
- */
-public class FunctionStateResolver
-    implements StateResolver
-{
-    final Function<PropertyDescriptor, Object> propertyFunction;
-    final Function<AssociationDescriptor, EntityReference> associationFunction;
-    final Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction;
-    final Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction;
-
-    public FunctionStateResolver( Function<PropertyDescriptor, Object> propertyFunction,
-                                  Function<AssociationDescriptor, EntityReference> associationFunction,
-                                  Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction,
-                                  Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction )
-    {
-        this.propertyFunction = propertyFunction;
-        this.associationFunction = associationFunction;
-        this.manyAssociationFunction = manyAssociationFunction;
-        this.namedAssociationFunction = namedAssociationFunction;
-    }
-
-    @Override
-    public Object getPropertyState( PropertyDescriptor propertyDescriptor )
-    {
-        return propertyFunction.map( propertyDescriptor );
-    }
-
-    @Override
-    public EntityReference getAssociationState( AssociationDescriptor associationDescriptor )
-    {
-        return associationFunction.map( associationDescriptor );
-    }
-
-    @Override
-    public List<EntityReference> getManyAssociationState( AssociationDescriptor associationDescriptor )
-    {
-        return Iterables.toList( manyAssociationFunction.map( associationDescriptor ) );
-    }
-
-    @Override
-    public Map<String, EntityReference> getNamedAssociationState( AssociationDescriptor associationDescriptor )
-    {
-        return namedAssociationFunction.map( associationDescriptor );
-    }
-
-    public void populateState( EntityModel model, EntityState state )
-    {
-        for( PropertyDescriptor propDesc : model.state().properties() )
-        {
-            Object value = getPropertyState( propDesc );
-            state.setPropertyValue( propDesc.qualifiedName(), value );
-        }
-        for( AssociationDescriptor assDesc : model.state().associations() )
-        {
-            EntityReference ref = getAssociationState( assDesc );
-            state.setAssociationValue( assDesc.qualifiedName(), ref );
-        }
-        for( ManyAssociationModel manyAssDesc : model.state().manyAssociations() )
-        {
-            ManyAssociationState associationState = state.manyAssociationValueOf( manyAssDesc.qualifiedName() );
-            // First clear existing ones
-            for( EntityReference ref : associationState )
-            {
-                associationState.remove( ref );
-            }
-            // then add the new ones.
-            for( EntityReference ref : getManyAssociationState( manyAssDesc ) )
-            {
-                associationState.add( 0, ref );
-            }
-        }
-        for( NamedAssociationModel namedAssDesc : model.state().namedAssociations() )
-        {
-            NamedAssociationState associationState = state.namedAssociationValueOf( namedAssDesc.qualifiedName() );
-            // First clear existing ones
-            for( String name : associationState )
-            {
-                associationState.remove( name );
-            }
-            // then add the new ones.
-            for( Map.Entry<String, EntityReference> entry : getNamedAssociationState( namedAssDesc ).entrySet() )
-            {
-                associationState.put( entry.getKey(), entry.getValue() );
-            }
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/GenericFragmentInvocationHandler.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/GenericFragmentInvocationHandler.java
deleted file mode 100644
index 4054300..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/GenericFragmentInvocationHandler.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- * JAVADOC
- */
-public final class GenericFragmentInvocationHandler
-    extends FragmentInvocationHandler
-{
-    // InvocationHandler implementation ------------------------------
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        try
-        {
-            return ( (InvocationHandler) fragment ).invoke( proxy, method, args );
-        }
-        catch( InvocationTargetException throwable )
-        {
-            throw cleanStackTrace( throwable.getTargetException(), proxy, method );
-        }
-        catch( Throwable throwable )
-        {
-            throw cleanStackTrace( throwable, proxy, method );
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/GenericSpecification.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/GenericSpecification.java
deleted file mode 100644
index 458f8bb..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/GenericSpecification.java
+++ /dev/null
@@ -1,37 +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.qi4j.runtime.composite;
-
-import java.lang.reflect.InvocationHandler;
-import org.qi4j.functional.Specification;
-
-/**
- * Specification that checks whether a given class implements InvocationHandler or not.
- */
-public class GenericSpecification
-    implements Specification<Class<?>>
-{
-    public static final GenericSpecification INSTANCE = new GenericSpecification();
-
-    @Override
-    public boolean satisfiedBy( Class<?> item )
-    {
-        return InvocationHandler.class.isAssignableFrom( item );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/InstancePool.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/InstancePool.java
deleted file mode 100644
index 349b7ab..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/InstancePool.java
+++ /dev/null
@@ -1,29 +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.qi4j.runtime.composite;
-
-/**
- * JAVADOC
- */
-public interface InstancePool<T>
-{
-    public T obtainInstance();
-
-    public void releaseInstance( T instance );
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/MixinModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/MixinModel.java
deleted file mode 100644
index 4b281d7..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/MixinModel.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.util.List;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Initializable;
-import org.qi4j.api.mixin.InitializationException;
-import org.qi4j.api.mixin.MixinDescriptor;
-import org.qi4j.api.property.StateHolder;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.runtime.injection.InjectedFieldsModel;
-import org.qi4j.runtime.injection.InjectedMethodsModel;
-import org.qi4j.runtime.injection.InjectionContext;
-
-import static org.qi4j.functional.Iterables.map;
-import static org.qi4j.functional.Iterables.toList;
-import static org.qi4j.functional.Iterables.unique;
-
-/**
- * JAVADOC
- */
-public final class MixinModel
-    implements MixinDescriptor, VisitableHierarchy<Object, Object>
-{
-    private final Class<?> mixinClass;
-    private final Class<?> instantiationClass;
-    private final ConstructorsModel constructorsModel;
-    private final InjectedFieldsModel injectedFieldsModel;
-    private final InjectedMethodsModel injectedMethodsModel;
-    private final Iterable<Class<?>> thisMixinTypes;
-
-    public MixinModel( Class<?> declaredMixinClass, Class<?> instantiationClass )
-    {
-        injectedFieldsModel = new InjectedFieldsModel( declaredMixinClass );
-        injectedMethodsModel = new InjectedMethodsModel( declaredMixinClass );
-
-        this.mixinClass = declaredMixinClass;
-        this.instantiationClass = instantiationClass;
-        constructorsModel = new ConstructorsModel( instantiationClass );
-
-        thisMixinTypes = buildThisMixinTypes();
-    }
-
-    @Override
-    public Class<?> mixinClass()
-    {
-        return mixinClass;
-    }
-
-    public Class<?> instantiationClass()
-    {
-        return instantiationClass;
-    }
-
-    public boolean isGeneric()
-    {
-        return InvocationHandler.class.isAssignableFrom( mixinClass );
-    }
-
-    public Iterable<DependencyModel> dependencies()
-    {
-        return Iterables.flatten( constructorsModel.dependencies(), injectedFieldsModel.dependencies(), injectedMethodsModel
-            .dependencies() );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            if( constructorsModel.accept( visitor ) )
-            {
-                if( injectedFieldsModel.accept( visitor ) )
-                {
-                    injectedMethodsModel.accept( visitor );
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-
-    // Context
-    public Object newInstance( CompositeInstance compositeInstance, StateHolder state, UsesInstance uses )
-    {
-        InjectionContext injectionContext = new InjectionContext( compositeInstance, uses, state );
-        return newInstance( injectionContext );
-    }
-
-    public Object newInstance( InjectionContext injectionContext )
-    {
-        Object mixin;
-        CompositeInstance compositeInstance = injectionContext.compositeInstance();
-
-        mixin = constructorsModel.newInstance( injectionContext );
-
-        if( FragmentClassLoader.isGenerated( instantiationClass ) )
-        {
-            try
-            {
-                instantiationClass.getDeclaredField( "_instance" ).set( mixin,
-                                                                        injectionContext.compositeInstance() );
-            }
-            catch( IllegalAccessException e )
-            {
-                e.printStackTrace();
-            }
-            catch( NoSuchFieldException e )
-            {
-                e.printStackTrace();
-            }
-        }
-
-        injectedFieldsModel.inject( injectionContext, mixin );
-        injectedMethodsModel.inject( injectionContext, mixin );
-        if( mixin instanceof Initializable )
-        {
-            try
-            {
-                ( (Initializable) mixin ).initialize();
-            }
-            catch( InitializationException e )
-            {
-                List<Class<?>> compositeType = toList( compositeInstance.types() );
-                String message = "Unable to initialize " + mixinClass + " in composite " + compositeType;
-                throw new ConstructionException( message, e );
-            }
-        }
-        return mixin;
-    }
-
-    public Iterable<Class<?>> thisMixinTypes()
-    {
-        return thisMixinTypes;
-    }
-
-    private Iterable<Class<?>> buildThisMixinTypes()
-    {
-        return map( new DependencyModel.InjectionTypeFunction(), unique( Iterables.filter( new DependencyModel.ScopeSpecification( This.class ), dependencies() ) ) );
-    }
-
-    protected FragmentInvocationHandler newInvocationHandler( Method method )
-    {
-        if( InvocationHandler.class.isAssignableFrom( mixinClass )
-            && !method.getDeclaringClass().isAssignableFrom( mixinClass ) )
-        {
-            return new GenericFragmentInvocationHandler();
-        }
-        else
-        {
-            return new TypedModifierInvocationHandler();
-        }
-    }
-
-    @Override
-    public String toString()
-    {
-        return mixinClass.getName();
-    }
-
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/MixinsInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/MixinsInstance.java
deleted file mode 100644
index d23805f..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/MixinsInstance.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.Method;
-
-/**
- * JAVADOC
- */
-public interface MixinsInstance
-{
-    Object invoke( Object composite, Object[] params, CompositeMethodInstance methodInstance )
-        throws Throwable;
-
-    Object invokeObject( Object proxy, Object[] args, Method method )
-        throws Throwable;
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/MixinsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/MixinsModel.java
deleted file mode 100644
index 8a4c349..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/MixinsModel.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.qi4j.api.util.Classes;
-import org.qi4j.bootstrap.BindingException;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.HierarchicalVisitorAdapter;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.runtime.injection.InjectedFieldModel;
-import org.qi4j.runtime.model.Binder;
-import org.qi4j.runtime.model.Resolution;
-
-import static org.qi4j.api.util.Classes.interfacesOf;
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.flattenIterables;
-import static org.qi4j.functional.Iterables.map;
-
-/**
- * Base implementation of model for mixins. This records the mapping between methods in the Composite
- * and mixin implementations.
- */
-public class MixinsModel
-    implements Binder, VisitableHierarchy<Object, Object>
-{
-    protected final Map<Method, MixinModel> methodImplementation = new HashMap<Method, MixinModel>();
-    protected final Map<Method, Integer> methodIndex = new HashMap<Method, Integer>();
-    protected List<MixinModel> mixinModels = new ArrayList<MixinModel>();
-
-    private final Map<Class, Integer> mixinIndex = new HashMap<Class, Integer>();
-    private final Set<Class<?>> mixinTypes = new LinkedHashSet<Class<?>>();
-
-    public Iterable<Class<?>> mixinTypes()
-    {
-        return mixinTypes;
-    }
-
-    public <T> boolean isImplemented( Class<T> mixinType )
-    {
-        return mixinTypes.contains( mixinType );
-    }
-
-    public List<MixinModel> mixinModels()
-    {
-        return mixinModels;
-    }
-
-    public MixinModel mixinFor( Method method )
-    {
-        return methodImplementation.get( method );
-    }
-
-    public MixinModel getMixinModel( Class mixinClass )
-    {
-        for( MixinModel mixinModel : mixinModels )
-        {
-            if( mixinModel.mixinClass().equals( mixinClass ) )
-            {
-                return mixinModel;
-            }
-        }
-        return null;
-    }
-
-    public void addMixinType( Class mixinType )
-    {
-        for( Type type : interfacesOf( mixinType ) )
-        {
-            mixinTypes.add( Classes.RAW_CLASS.map( type ) );
-        }
-    }
-
-    public void addMixinModel( MixinModel mixinModel )
-    {
-        mixinModels.add( mixinModel );
-    }
-
-    public void addMethodMixin( Method method, MixinModel mixinModel )
-    {
-        methodImplementation.put( method, mixinModel );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( MixinModel mixinModel : mixinModels )
-            {
-                mixinModel.accept( visitor );
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-
-    // Binding
-    @Override
-    public void bind( final Resolution resolution )
-        throws BindingException
-    {
-        // Order mixins based on @This usages
-        UsageGraph<MixinModel> deps = new UsageGraph<MixinModel>( mixinModels, new Uses(), true );
-        mixinModels = deps.resolveOrder();
-
-        // Populate mappings
-        for( int i = 0; i < mixinModels.size(); i++ )
-        {
-            MixinModel mixinModel = mixinModels.get( i );
-            mixinIndex.put( mixinModel.mixinClass(), i );
-        }
-
-        for( Map.Entry<Method, MixinModel> methodClassEntry : methodImplementation.entrySet() )
-        {
-            methodIndex.put( methodClassEntry.getKey(), mixinIndex.get( methodClassEntry.getValue().mixinClass() ) );
-        }
-
-        for( MixinModel mixinModel : mixinModels )
-        {
-            mixinModel.accept( new HierarchicalVisitorAdapter<Object, Object, BindingException>()
-            {
-                @Override
-                public boolean visitEnter( Object visited )
-                    throws BindingException
-                {
-                    if( visited instanceof InjectedFieldModel )
-                    {
-                        InjectedFieldModel fieldModel = (InjectedFieldModel) visited;
-                        fieldModel.bind( resolution.forField( fieldModel.field() ) );
-                        return false;
-                    }
-                    else if( visited instanceof Binder )
-                    {
-                        Binder constructorsModel = (Binder) visited;
-                        constructorsModel.bind( resolution );
-
-                        return false;
-                    }
-                    return true;
-                }
-
-                @Override
-                public boolean visit( Object visited )
-                    throws BindingException
-                {
-                    if( visited instanceof Binder )
-                    {
-                        ( (Binder) visited ).bind( resolution );
-                    }
-                    return true;
-                }
-            } );
-        }
-    }
-
-    // Context
-
-    public Object[] newMixinHolder()
-    {
-        return new Object[ mixinIndex.size() ];
-    }
-
-    public FragmentInvocationHandler newInvocationHandler( final Method method )
-    {
-        return mixinFor( method ).newInvocationHandler( method );
-    }
-
-    public Iterable<DependencyModel> dependencies()
-    {
-        return flattenIterables( map( new Function<MixinModel, Iterable<DependencyModel>>()
-        {
-            @Override
-            public Iterable<DependencyModel> map( MixinModel mixinModel )
-            {
-                return mixinModel.dependencies();
-            }
-        }, mixinModels ) );
-    }
-
-    public Iterable<Method> invocationsFor( final Class<?> mixinClass )
-    {
-        return map( new Function<Map.Entry<Method, MixinModel>, Method>()
-        {
-            @Override
-            public Method map( Map.Entry<Method, MixinModel> entry )
-            {
-                return entry.getKey();
-            }
-        }, filter( new Specification<Map.Entry<Method, MixinModel>>()
-        {
-            @Override
-            public boolean satisfiedBy( Map.Entry<Method, MixinModel> item )
-            {
-                MixinModel model = item.getValue();
-                return model.mixinClass().equals( mixinClass );
-            }
-        }, methodImplementation.entrySet() ) );
-    }
-
-    private class Uses
-        implements UsageGraph.Use<MixinModel>
-    {
-        @Override
-        public Collection<MixinModel> uses( MixinModel source )
-        {
-            Iterable<Class<?>> thisMixinTypes = source.thisMixinTypes();
-            List<MixinModel> usedMixinClasses = new ArrayList<MixinModel>();
-            for( Class thisMixinType : thisMixinTypes )
-            {
-                for( Method method : thisMixinType.getMethods() )
-                {
-                    usedMixinClasses.add( methodImplementation.get( method ) );
-                }
-            }
-            return usedMixinClasses;
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/ProxyGenerator.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/ProxyGenerator.java
deleted file mode 100644
index 15c52c5..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/ProxyGenerator.java
+++ /dev/null
@@ -1,34 +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.qi4j.runtime.composite;
-
-import java.lang.reflect.Proxy;
-
-/**
- * generates proxyclasses
- */
-public class ProxyGenerator {
-    public static Class<?> createProxyClass(ClassLoader mainTypeClassLoader, Class<?>[] interfaces) {
-        ClassLoader effectiveClassLoader = Thread.currentThread().getContextClassLoader();
-        if (effectiveClassLoader == null) {
-            effectiveClassLoader = mainTypeClassLoader;
-        }
-        return Proxy.getProxyClass(effectiveClassLoader, interfaces);
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/ProxyReferenceInvocationHandler.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/ProxyReferenceInvocationHandler.java
deleted file mode 100644
index cf5526a..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/ProxyReferenceInvocationHandler.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.lang.reflect.UndeclaredThrowableException;
-import org.qi4j.api.composite.CompositeInvoker;
-
-public final class ProxyReferenceInvocationHandler
-    implements InvocationHandler, CompositeInvoker
-{
-    private Object proxy;
-
-    public Object proxy()
-    {
-        return proxy;
-    }
-
-    public void setProxy( Object proxy )
-    {
-        this.proxy = proxy;
-    }
-
-    public void clearProxy()
-    {
-        proxy = null;
-    }
-
-    @Override
-    public Object invokeComposite( Method method, Object[] args )
-        throws Throwable
-    {
-        try
-        {
-            InvocationHandler invocationHandler = Proxy.getInvocationHandler( this.proxy );
-            return invocationHandler.invoke( this.proxy, method, args );
-        }
-        catch( InvocationTargetException e )
-        {
-            throw e.getTargetException();
-        }
-        catch( UndeclaredThrowableException e )
-        {
-            throw e.getUndeclaredThrowable();
-        }
-    }
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        try
-        {
-            InvocationHandler invocationHandler = Proxy.getInvocationHandler( this.proxy );
-            return invocationHandler.invoke( this.proxy, method, args );
-        }
-        catch( InvocationTargetException e )
-        {
-            throw e.getTargetException();
-        }
-        catch( UndeclaredThrowableException e )
-        {
-            throw e.getUndeclaredThrowable();
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/SideEffectInvocationHandlerResult.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/SideEffectInvocationHandlerResult.java
deleted file mode 100644
index 31718d6..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/SideEffectInvocationHandlerResult.java
+++ /dev/null
@@ -1,58 +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.qi4j.runtime.composite;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-
-/**
- * JAVADOC
- */
-public final class SideEffectInvocationHandlerResult
-    implements InvocationHandler
-{
-    private Object result;
-    private Throwable throwable;
-
-    public SideEffectInvocationHandlerResult()
-    {
-    }
-
-    public void setResult( Object result, Throwable throwable )
-    {
-        this.result = result;
-        this.throwable = throwable;
-    }
-
-    // InvocationHandler implementation ------------------------------
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        if( throwable != null )
-        {
-            throw throwable;
-        }
-        else
-        {
-            return result;
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/SideEffectModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/SideEffectModel.java
deleted file mode 100644
index cc3e377..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/SideEffectModel.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import org.qi4j.api.sideeffect.SideEffectDescriptor;
-
-/**
- * JAVADOC
- */
-public final class SideEffectModel
-    extends AbstractModifierModel
-    implements SideEffectDescriptor
-{
-    public SideEffectModel( Class<?> sideEffectClass, Class<?> instantiationClass )
-    {
-        super( sideEffectClass, instantiationClass );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/SideEffectsInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/SideEffectsInstance.java
deleted file mode 100644
index f141b41..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/SideEffectsInstance.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.util.List;
-
-/**
- * JAVADOC
- */
-public final class SideEffectsInstance
-    implements InvocationHandler
-{
-    private final List<InvocationHandler> sideEffects;
-    private final SideEffectInvocationHandlerResult resultInvocationHandler;
-    private final ProxyReferenceInvocationHandler proxyHandler;
-    private InvocationHandler invoker;
-
-    public SideEffectsInstance( List<InvocationHandler> sideEffects,
-                                SideEffectInvocationHandlerResult resultInvocationHandler,
-                                ProxyReferenceInvocationHandler proxyHandler,
-                                InvocationHandler invoker
-    )
-    {
-        this.sideEffects = sideEffects;
-        this.resultInvocationHandler = resultInvocationHandler;
-        this.proxyHandler = proxyHandler;
-        this.invoker = invoker;
-    }
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        try
-        {
-            Object result = invoker.invoke( proxy, method, args );
-            invokeSideEffects( proxy, method, args, result, null );
-            return result;
-        }
-        catch( Throwable throwable )
-        {
-            invokeSideEffects( proxy, method, args, null, throwable );
-            throw throwable;
-        }
-    }
-
-    private void invokeSideEffects( Object proxy,
-                                    Method method,
-                                    Object[] params,
-                                    Object result,
-                                    Throwable originalThrowable
-    )
-        throws Throwable
-    {
-        proxyHandler.setProxy( proxy );
-        resultInvocationHandler.setResult( result, originalThrowable );
-
-        try
-        {
-            for( InvocationHandler sideEffect : sideEffects )
-            {
-                try
-                {
-                    sideEffect.invoke( proxy, method, params );
-                }
-                catch( Throwable throwable )
-                {
-                    if( throwable != originalThrowable )
-                    {
-                        throwable.printStackTrace();
-                    }
-                }
-            }
-        }
-        finally
-        {
-            proxyHandler.clearProxy();
-            resultInvocationHandler.setResult( null, null );
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/SideEffectsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/SideEffectsModel.java
deleted file mode 100644
index 10ae779..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/SideEffectsModel.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import org.qi4j.api.sideeffect.SideEffectsDescriptor;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.injection.Dependencies;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.spi.module.ModuleSpi;
-
-/**
- * JAVADOC
- */
-public final class SideEffectsModel
-    implements SideEffectsDescriptor, Dependencies, VisitableHierarchy<Object, Object>
-{
-    public static final SideEffectsModel EMPTY_SIDEEFFECTS = new SideEffectsModel( Collections.<SideEffectModel>emptyList() );
-
-    private List<SideEffectModel> sideEffectModels = null;
-
-    public SideEffectsModel( List<SideEffectModel> sideEffectModels )
-    {
-        this.sideEffectModels = sideEffectModels;
-    }
-
-    @Override
-    public Iterable<DependencyModel> dependencies()
-    {
-        return Iterables.flattenIterables( Iterables.map( Dependencies.DEPENDENCIES_FUNCTION, sideEffectModels ) );
-    }
-
-    // Context
-    public SideEffectsInstance newInstance( Method method, ModuleSpi moduleInstance, InvocationHandler invoker )
-    {
-        ProxyReferenceInvocationHandler proxyHandler = new ProxyReferenceInvocationHandler();
-        SideEffectInvocationHandlerResult result = new SideEffectInvocationHandlerResult();
-        List<InvocationHandler> sideEffects = new ArrayList<InvocationHandler>( sideEffectModels.size() );
-        for( SideEffectModel sideEffectModel : sideEffectModels )
-        {
-            InvocationHandler sideEffect = sideEffectModel.newInstance( moduleInstance, result, proxyHandler, method );
-            sideEffects.add( sideEffect );
-        }
-        return new SideEffectsInstance( sideEffects, result, proxyHandler, invoker );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
-        throws ThrowableType
-    {
-        if( modelVisitor.visitEnter( this ) )
-        {
-            for( SideEffectModel sideEffectModel : sideEffectModels )
-            {
-                if( !sideEffectModel.accept( modelVisitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return modelVisitor.visitLeave( this );
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/StateModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/StateModel.java
deleted file mode 100644
index 93ac0f1..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/StateModel.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.composite;
-
-import java.lang.reflect.AccessibleObject;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.composite.StateDescriptor;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.property.PropertiesModel;
-import org.qi4j.runtime.property.PropertyModel;
-
-/**
- * Base model for Composite state
- */
-public class StateModel
-    implements StateDescriptor, VisitableHierarchy<Object, Object>
-{
-    protected final PropertiesModel propertiesModel;
-
-    public StateModel( PropertiesModel propertiesModel )
-    {
-        this.propertiesModel = propertiesModel;
-    }
-
-    public PropertyModel propertyModelFor( AccessibleObject accessor )
-    {
-        return propertiesModel.getProperty( accessor );
-    }
-
-    @Override
-    public PropertyModel findPropertyModelByName( String name )
-        throws IllegalArgumentException
-    {
-        return propertiesModel.getPropertyByName( name );
-    }
-
-    @Override
-    public PropertyModel findPropertyModelByQualifiedName( QualifiedName name )
-        throws IllegalArgumentException
-    {
-        return propertiesModel.getPropertyByQualifiedName( name );
-    }
-
-    @Override
-    public Iterable<PropertyModel> properties()
-    {
-        return propertiesModel.properties();
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            ( (VisitableHierarchy<Object, Object>) propertiesModel ).accept( visitor );
-        }
-        return visitor.visitLeave( this );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/StateResolver.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/StateResolver.java
deleted file mode 100644
index 1f7072a..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/StateResolver.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2012, Kent Sølvsten.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.property.PropertyDescriptor;
-
-/**
- * StateResolver.
- */
-public interface StateResolver
-{
-    Object getPropertyState( PropertyDescriptor propertyDescriptor );
-
-    EntityReference getAssociationState( AssociationDescriptor associationDescriptor );
-
-    List<EntityReference> getManyAssociationState( AssociationDescriptor associationDescriptor );
-
-    Map<String, EntityReference> getNamedAssociationState( AssociationDescriptor associationDescriptor );
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/SynchronizedCompositeMethodInstancePool.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/SynchronizedCompositeMethodInstancePool.java
deleted file mode 100644
index da5dbdf..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/SynchronizedCompositeMethodInstancePool.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-/**
- * Method instance pool that keeps a linked list. Uses synchronization
- * to ensure that instances are acquired and returned in a thread-safe
- * manner.
- */
-public final class SynchronizedCompositeMethodInstancePool
-    implements InstancePool<CompositeMethodInstance>
-{
-    private CompositeMethodInstance first = null;
-
-    @Override
-    public synchronized CompositeMethodInstance obtainInstance()
-    {
-        CompositeMethodInstance instance = first;
-        if( instance != null )
-        {
-            first = instance.getNext();
-        }
-        return instance;
-    }
-
-    @Override
-    public synchronized void releaseInstance( CompositeMethodInstance instance )
-    {
-        instance.setNext( first );
-        first = instance;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientBuilderInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientBuilderInstance.java
deleted file mode 100644
index ffb3fc6..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientBuilderInstance.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.runtime.property.PropertyInfo;
-import org.qi4j.runtime.property.PropertyInstance;
-import org.qi4j.spi.module.ModelModule;
-
-/**
- * JAVADOC
- */
-public final class TransientBuilderInstance<T>
-    implements TransientBuilder<T>
-{
-    private ModelModule<TransientModel> model;
-
-    // lazy initialized in accessor
-    private UsesInstance uses = UsesInstance.EMPTY_USES;
-
-    // lazy initialized in accessor
-    private CompositeInstance prototypeInstance;
-
-    private TransientStateInstance state;
-
-    public TransientBuilderInstance( ModelModule<TransientModel> model,
-                                     TransientStateInstance state,
-                                     UsesInstance uses
-    )
-    {
-        this.model = model;
-        this.state = state;
-        this.uses = uses;
-    }
-
-    @Override
-    public TransientBuilder<T> use( Object... usedObjects )
-    {
-        uses = uses.use( usedObjects );
-        return this;
-    }
-
-    @Override
-    public T prototype()
-    {
-        // Instantiate given value type
-        if( prototypeInstance == null )
-        {
-            prototypeInstance = model.model().newInstance( model.module(), uses, state );
-        }
-
-        return prototypeInstance.<T>proxy();
-    }
-
-    @Override
-    public <K> K prototypeFor( Class<K> mixinType )
-    {
-        // Instantiate given value type
-        if( prototypeInstance == null )
-        {
-            prototypeInstance = model.model().newInstance( model.module(), uses, state );
-        }
-
-        return prototypeInstance.newProxy( mixinType );
-    }
-
-    @Override
-    public T newInstance()
-        throws ConstructionException
-    {
-        // Set correct info's (immutable) on the state
-        for( PropertyDescriptor propertyDescriptor : model.model().state().properties() )
-        {
-            ( (PropertyInstance<Object>) state.propertyFor( propertyDescriptor.accessor() ) ).setPropertyInfo( (PropertyInfo) propertyDescriptor );
-        }
-
-        model.model().checkConstraints( state );
-
-        CompositeInstance compositeInstance =
-            model.model().newInstance( model.module(), uses, state );
-        return compositeInstance.<T>proxy();
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientClassLoader.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientClassLoader.java
deleted file mode 100644
index 154dee1..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientClassLoader.java
+++ /dev/null
@@ -1,804 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.List;
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.FieldVisitor;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-import org.qi4j.api.entity.Lifecycle;
-import org.qi4j.api.mixin.Initializable;
-import org.qi4j.api.util.Classes;
-import org.qi4j.api.util.Methods;
-import org.qi4j.functional.Iterables;
-
-import static org.objectweb.asm.Opcodes.AASTORE;
-import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
-import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
-import static org.objectweb.asm.Opcodes.ACC_STATIC;
-import static org.objectweb.asm.Opcodes.ACC_SUPER;
-import static org.objectweb.asm.Opcodes.ACONST_NULL;
-import static org.objectweb.asm.Opcodes.ALOAD;
-import static org.objectweb.asm.Opcodes.ANEWARRAY;
-import static org.objectweb.asm.Opcodes.ARETURN;
-import static org.objectweb.asm.Opcodes.ASTORE;
-import static org.objectweb.asm.Opcodes.ATHROW;
-import static org.objectweb.asm.Opcodes.BIPUSH;
-import static org.objectweb.asm.Opcodes.CHECKCAST;
-import static org.objectweb.asm.Opcodes.DLOAD;
-import static org.objectweb.asm.Opcodes.DRETURN;
-import static org.objectweb.asm.Opcodes.DUP;
-import static org.objectweb.asm.Opcodes.FLOAD;
-import static org.objectweb.asm.Opcodes.FRETURN;
-import static org.objectweb.asm.Opcodes.GETFIELD;
-import static org.objectweb.asm.Opcodes.GETSTATIC;
-import static org.objectweb.asm.Opcodes.GOTO;
-import static org.objectweb.asm.Opcodes.ICONST_0;
-import static org.objectweb.asm.Opcodes.ICONST_1;
-import static org.objectweb.asm.Opcodes.ICONST_2;
-import static org.objectweb.asm.Opcodes.ICONST_3;
-import static org.objectweb.asm.Opcodes.ICONST_4;
-import static org.objectweb.asm.Opcodes.ICONST_5;
-import static org.objectweb.asm.Opcodes.ILOAD;
-import static org.objectweb.asm.Opcodes.INVOKEINTERFACE;
-import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
-import static org.objectweb.asm.Opcodes.INVOKESTATIC;
-import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
-import static org.objectweb.asm.Opcodes.IRETURN;
-import static org.objectweb.asm.Opcodes.LLOAD;
-import static org.objectweb.asm.Opcodes.LRETURN;
-import static org.objectweb.asm.Opcodes.POP;
-import static org.objectweb.asm.Opcodes.PUTSTATIC;
-import static org.objectweb.asm.Opcodes.RETURN;
-import static org.objectweb.asm.Type.getInternalName;
-import static org.qi4j.api.util.Classes.interfacesOf;
-
-/**
- * Generate subclasses of classes used for transients. All methods delegate to CompositeInvoker.
- */
-@SuppressWarnings( "raw" )
-/* package */ final class TransientClassLoader
-    extends ClassLoader
-{
-    private static final int JDK_VERSION;
-    public static final String GENERATED_POSTFIX = "_Proxy";
-
-    static
-    {
-        String jdkString = System.getProperty( "java.specification.version" );
-        switch( jdkString )
-        {
-            case "1.8":
-                JDK_VERSION = Opcodes.V1_8;
-                break;
-            case "1.7":
-            default:
-                JDK_VERSION = Opcodes.V1_7;
-                break;
-        }
-    }
-
-    /* package */ TransientClassLoader( ClassLoader parent )
-    {
-        super( parent );
-    }
-
-    @Override
-    protected Class findClass( String name )
-        throws ClassNotFoundException
-    {
-        if( name.endsWith( GENERATED_POSTFIX ) )
-        {
-            Class baseClass;
-            String baseName = name.substring( 0, name.length() - 6 );
-            try
-            {
-                baseClass = loadClass( baseName );
-            }
-            catch( ClassNotFoundException e )
-            {
-                // Try replacing the last _ with $
-                while( true )
-                {
-                    int idx = baseName.lastIndexOf( "_" );
-                    if( idx != -1 )
-                    {
-                        baseName = baseName.substring( 0, idx ) + "$" + baseName.substring( idx + 1 );
-                        try
-                        {
-                            baseClass = loadClass( baseName );
-                            break;
-                        }
-                        catch( ClassNotFoundException e1 )
-                        {
-                            // Try again
-                        }
-                    }
-                    else
-                    {
-                        throw e;
-                    }
-                }
-            }
-
-            byte[] b = generateClass( name, baseClass );
-            return defineClass( name, b, 0, b.length, baseClass.getProtectionDomain() );
-        }
-
-        // Try the classloader of this classloader -> get classes in Zest such as CompositeInvoker
-        return getClass().getClassLoader().loadClass( name );
-    }
-
-    public static byte[] generateClass( String name, Class baseClass )
-        throws ClassNotFoundException
-    {
-        String classSlash = name.replace( '.', '/' );
-        String baseClassSlash = getInternalName( baseClass );
-
-        ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_MAXS );
-        FieldVisitor fv;
-        MethodVisitor mv;
-        AnnotationVisitor av0;
-
-        // Class definition start
-        cw.visit( JDK_VERSION, ACC_PUBLIC + ACC_SUPER, classSlash, null, baseClassSlash, null );
-
-        // Composite reference
-        {
-            fv = cw.visitField( ACC_PUBLIC, "_instance", "Lorg/qi4j/api/composite/CompositeInvoker;", null, null );
-            fv.visitEnd();
-        }
-
-        // Static Method references
-        {
-            int idx = 1;
-            for( Method method : baseClass.getMethods() )
-            {
-                if( isOverloaded( method, baseClass ) )
-                {
-                    fv = cw.visitField( ACC_PRIVATE + ACC_STATIC, "m" + idx++, "Ljava/lang/reflect/Method;", null,
-                                        null );
-                    fv.visitEnd();
-                }
-            }
-        }
-
-        // Constructors
-        for( Constructor constructor : baseClass.getDeclaredConstructors() )
-        {
-            if( Modifier.isPublic( constructor.getModifiers() ) || Modifier.isProtected( constructor.getModifiers() ) )
-            {
-                String desc = org.objectweb.asm.commons.Method.getMethod( constructor ).getDescriptor();
-                mv = cw.visitMethod( ACC_PUBLIC, "<init>", desc, null, null );
-                mv.visitCode();
-                mv.visitVarInsn( ALOAD, 0 );
-
-                int idx = 1;
-                for( Class aClass : constructor.getParameterTypes() )
-                {
-                    // TODO Handle other types than objects (?)
-                    mv.visitVarInsn( ALOAD, idx++ );
-                }
-
-                mv.visitMethodInsn( INVOKESPECIAL, baseClassSlash, "<init>", desc, false );
-                mv.visitInsn( RETURN );
-                mv.visitMaxs( idx, idx );
-                mv.visitEnd();
-            }
-        }
-
-        // Overloaded and unimplemented methods
-        Method[] methods = baseClass.getMethods();
-        int idx = 0;
-        List<Label> exceptionLabels = new ArrayList<>();
-        for( Method method : methods )
-        {
-            if( isOverloaded( method, baseClass ) )
-            {
-                idx++;
-                String methodName = method.getName();
-                String desc = org.objectweb.asm.commons.Method.getMethod( method ).getDescriptor();
-
-                String[] exceptions = null;
-                {
-                    mv = cw.visitMethod( ACC_PUBLIC, methodName, desc, null, exceptions );
-                    if( isInternalQi4jMethod( method, baseClass ) )
-                    {
-                        // generate a NoOp method...
-                        mv.visitInsn( RETURN );
-                    }
-                    else
-                    {
-                        Label endLabel = null; // Use this if return type is void
-                        if( method.getExceptionTypes().length > 0 )
-                        {
-                            exceptions = new String[ method.getExceptionTypes().length ];
-                            for( int i = 0; i < method.getExceptionTypes().length; i++ )
-                            {
-                                Class<?> aClass = method.getExceptionTypes()[ i ];
-                                exceptions[ i ] = getInternalName( aClass );
-                            }
-                        }
-                        mv.visitCode();
-                        Label l0 = new Label();
-                        Label l1 = new Label();
-
-                        exceptionLabels.clear();
-                        for( Class<?> declaredException : method.getExceptionTypes() )
-                        {
-                            Label ld = new Label();
-                            mv.visitTryCatchBlock( l0, l1, ld, getInternalName( declaredException ) );
-                            exceptionLabels.add( ld ); // Reuse this further down for the catch
-                        }
-
-                        Label lruntime = new Label();
-                        mv.visitTryCatchBlock( l0, l1, lruntime, "java/lang/RuntimeException" );
-                        Label lerror = new Label();
-                        mv.visitTryCatchBlock( l0, l1, lerror, "java/lang/Throwable" );
-
-                        mv.visitLabel( l0 );
-                        mv.visitVarInsn( ALOAD, 0 );
-                        mv.visitFieldInsn( GETFIELD, classSlash, "_instance",
-                                           "Lorg/qi4j/api/composite/CompositeInvoker;" );
-                        mv.visitFieldInsn( GETSTATIC, classSlash, "m" + idx, "Ljava/lang/reflect/Method;" );
-
-                        int paramCount = method.getParameterTypes().length;
-                        int stackIdx = 0;
-                        if( paramCount == 0 )
-                        {
-                            // Send in null as parameter
-                            mv.visitInsn( ACONST_NULL );
-                        }
-                        else
-                        {
-                            insn( mv, paramCount );
-                            mv.visitTypeInsn( ANEWARRAY, "java/lang/Object" );
-                            int pidx = 0;
-                            for( Class<?> aClass : method.getParameterTypes() )
-                            {
-                                mv.visitInsn( DUP );
-                                insn( mv, pidx++ );
-                                stackIdx = wrapParameter( mv, aClass, stackIdx + 1 );
-                                mv.visitInsn( AASTORE );
-                            }
-                        }
-
-                        // Call method
-                        mv.visitMethodInsn( INVOKEINTERFACE, "org/qi4j/api/composite/CompositeInvoker",
-                                            "invokeComposite",
-                                            "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true );
-
-                        // Return value
-                        if( !method.getReturnType().equals( Void.TYPE ) )
-                        {
-                            unwrapResult( mv, method.getReturnType(), l1 );
-                        }
-                        else
-                        {
-                            mv.visitInsn( POP );
-                            mv.visitLabel( l1 );
-                            endLabel = new Label();
-                            mv.visitJumpInsn( GOTO, endLabel );
-                        }
-
-                        // Increase stack to beyond method args
-                        stackIdx++;
-
-                        // Declared exceptions
-                        int exceptionIdx = 0;
-                        for( Class<?> aClass : method.getExceptionTypes() )
-                        {
-                            mv.visitLabel( exceptionLabels.get( exceptionIdx++ ) );
-                            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ getInternalName( aClass ) } );
-                            mv.visitVarInsn( ASTORE, stackIdx );
-                            mv.visitVarInsn( ALOAD, stackIdx );
-                            mv.visitInsn( ATHROW );
-                        }
-
-                        // RuntimeException and Error catch-all
-                        mv.visitLabel( lruntime );
-                        mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/RuntimeException" } );
-                        mv.visitVarInsn( ASTORE, stackIdx );
-                        mv.visitVarInsn( ALOAD, stackIdx );
-                        mv.visitInsn( ATHROW );
-
-                        mv.visitLabel( lerror );
-                        mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/Throwable" } );
-                        mv.visitVarInsn( ASTORE, stackIdx );
-                        mv.visitVarInsn( ALOAD, stackIdx );
-                        mv.visitTypeInsn( CHECKCAST, "java/lang/Error" );
-                        mv.visitInsn( ATHROW );
-
-                        // Return type = void
-                        if( endLabel != null )
-                        {
-                            mv.visitLabel( endLabel );
-                            mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
-                            mv.visitInsn( RETURN );
-                        }
-
-                        mv.visitMaxs( 0, 0 );
-                        mv.visitEnd();
-                    }
-                }
-
-                if( !Modifier.isAbstract( method.getModifiers() ) )
-                {
-                    // Add method with _ as prefix
-                    mv = cw.visitMethod( ACC_PUBLIC, "_" + method.getName(), desc, null, exceptions );
-                    mv.visitCode();
-                    mv.visitVarInsn( ALOAD, 0 );
-
-                    // Parameters
-                    int stackIdx = 1;
-                    for( Class<?> aClass : method.getParameterTypes() )
-                    {
-                        stackIdx = loadParameter( mv, aClass, stackIdx ) + 1;
-                    }
-
-                    // Call method
-                    mv.visitMethodInsn( INVOKESPECIAL, baseClassSlash, method.getName(), desc, false );
-
-                    // Return value
-                    if( !method.getReturnType().equals( Void.TYPE ) )
-                    {
-                        returnResult( mv, method.getReturnType() );
-                    }
-                    else
-                    {
-                        mv.visitInsn( RETURN );
-                    }
-
-                    mv.visitMaxs( 1, 1 );
-                    mv.visitEnd();
-                }
-            }
-        }
-
-        // Class initializer
-        {
-            mv = cw.visitMethod( ACC_STATIC, "<clinit>", "()V", null, null );
-            mv.visitCode();
-            Label l0 = new Label();
-            Label l1 = new Label();
-            Label l2 = new Label();
-            mv.visitTryCatchBlock( l0, l1, l2, "java/lang/NoSuchMethodException" );
-            mv.visitLabel( l0 );
-
-            // Lookup methods and store in static variables
-            int midx = 0;
-            for( Method method : methods )
-            {
-                if( isOverloaded( method, baseClass ) )
-                {
-                    method.setAccessible( true );
-                    Class methodClass;
-                    methodClass = method.getDeclaringClass();
-
-                    midx++;
-
-                    mv.visitLdcInsn( Type.getType( methodClass ) );
-                    mv.visitLdcInsn( method.getName() );
-                    insn( mv, method.getParameterTypes().length );
-                    mv.visitTypeInsn( ANEWARRAY, "java/lang/Class" );
-
-                    int pidx = 0;
-                    for( Class<?> aClass : method.getParameterTypes() )
-                    {
-                        mv.visitInsn( DUP );
-                        insn( mv, pidx++ );
-                        type( mv, aClass );
-                        mv.visitInsn( AASTORE );
-                    }
-
-                    mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getMethod",
-                                        "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false );
-                    mv.visitFieldInsn( PUTSTATIC, classSlash, "m" + midx, "Ljava/lang/reflect/Method;" );
-                }
-            }
-
-            mv.visitLabel( l1 );
-            Label l3 = new Label();
-            mv.visitJumpInsn( GOTO, l3 );
-            mv.visitLabel( l2 );
-            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/NoSuchMethodException" } );
-            mv.visitVarInsn( ASTORE, 0 );
-            mv.visitVarInsn( ALOAD, 0 );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/NoSuchMethodException", "printStackTrace", "()V", false );
-            mv.visitLabel( l3 );
-            mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
-            mv.visitInsn( RETURN );
-            mv.visitMaxs( 6, 1 );
-            mv.visitEnd();
-        }
-
-        cw.visitEnd();
-
-        return cw.toByteArray();
-    }
-
-    private static boolean isOverloaded( Method method, Class baseClass )
-    {
-        if( Modifier.isFinal( method.getModifiers() ) )
-        {
-            return false; // Cannot override final methods
-        }
-        else
-        {
-            return true;
-        }
-    }
-
-    private static boolean isInternalQi4jMethod( Method method, Class baseClass )
-    {
-        return isDeclaredIn( method, Initializable.class, baseClass )
-               || isDeclaredIn( method, Lifecycle.class, baseClass );
-    }
-
-    private static boolean isDeclaredIn( Method method, Class<?> clazz, Class<?> baseClass )
-    {
-        if( !clazz.isAssignableFrom( baseClass ) )
-        {
-            return false;
-        }
-
-        try
-        {
-            clazz.getMethod( method.getName(), method.getParameterTypes() );
-            return true;
-        }
-        catch( NoSuchMethodException e )
-        {
-            return false;
-        }
-    }
-
-    private static Class getInterfaceMethodDeclaration( Method method, Class clazz )
-        throws NoSuchMethodException
-    {
-        Iterable<Class<?>> interfaces = Iterables.map( Classes.RAW_CLASS, interfacesOf( clazz ) );
-        for( Class<?> anInterface : interfaces )
-        {
-            try
-            {
-                anInterface.getMethod( method.getName(), method.getParameterTypes() );
-                return anInterface;
-            }
-            catch( NoSuchMethodException e )
-            {
-                // Try next
-            }
-        }
-
-        throw new NoSuchMethodException( method.getName() );
-    }
-
-    private static boolean isInterfaceMethod( Method method, Class<?> baseClass )
-    {
-        for( Class<?> aClass : Iterables.filter( Methods.HAS_METHODS, Iterables.map( Classes.RAW_CLASS, interfacesOf( baseClass ) ) ) )
-        {
-            try
-            {
-                Method m = aClass.getMethod( method.getName(), method.getParameterTypes() );
-                m.setAccessible( true );
-                return true;
-            }
-            catch( NoSuchMethodException e )
-            {
-                // Ignore
-            }
-        }
-        return false;
-    }
-
-    private static void type( MethodVisitor mv, Class<?> aClass )
-    {
-        if( aClass.equals( Integer.TYPE ) )
-        {
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;" );
-        }
-        else if( aClass.equals( Long.TYPE ) )
-        {
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;" );
-        }
-        else if( aClass.equals( Short.TYPE ) )
-        {
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;" );
-        }
-        else if( aClass.equals( Byte.TYPE ) )
-        {
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;" );
-        }
-        else if( aClass.equals( Double.TYPE ) )
-        {
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;" );
-        }
-        else if( aClass.equals( Float.TYPE ) )
-        {
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;" );
-        }
-        else if( aClass.equals( Boolean.TYPE ) )
-        {
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;" );
-        }
-        else if( aClass.equals( Character.TYPE ) )
-        {
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;" );
-        }
-        else
-        {
-            mv.visitLdcInsn( Type.getType( aClass ) );
-        }
-    }
-
-    private static int wrapParameter( MethodVisitor mv, Class<?> aClass, int idx )
-    {
-        if( aClass.equals( Integer.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false );
-        }
-        else if( aClass.equals( Long.TYPE ) )
-        {
-            mv.visitVarInsn( LLOAD, idx );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false );
-            idx++; // Extra jump
-        }
-        else if( aClass.equals( Short.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false );
-        }
-        else if( aClass.equals( Byte.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false );
-        }
-        else if( aClass.equals( Double.TYPE ) )
-        {
-            mv.visitVarInsn( DLOAD, idx );
-            idx++; // Extra jump
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false );
-        }
-        else if( aClass.equals( Float.TYPE ) )
-        {
-            mv.visitVarInsn( FLOAD, idx );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false );
-        }
-        else if( aClass.equals( Boolean.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false );
-        }
-        else if( aClass.equals( Character.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false );
-        }
-        else
-        {
-            mv.visitVarInsn( ALOAD, idx );
-        }
-
-        return idx;
-    }
-
-    private static void unwrapResult( MethodVisitor mv, Class<?> aClass, Label label )
-    {
-        if( aClass.equals( Integer.TYPE ) )
-        {
-            mv.visitTypeInsn( CHECKCAST, "java/lang/Integer" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false );
-            mv.visitLabel( label );
-            mv.visitInsn( IRETURN );
-        }
-        else if( aClass.equals( Long.TYPE ) )
-        {
-            mv.visitTypeInsn( CHECKCAST, "java/lang/Long" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false );
-            mv.visitLabel( label );
-            mv.visitInsn( LRETURN );
-        }
-        else if( aClass.equals( Short.TYPE ) )
-        {
-            mv.visitTypeInsn( CHECKCAST, "java/lang/Short" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false );
-            mv.visitLabel( label );
-            mv.visitInsn( IRETURN );
-        }
-        else if( aClass.equals( Byte.TYPE ) )
-        {
-            mv.visitTypeInsn( CHECKCAST, "java/lang/Byte" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false );
-            mv.visitLabel( label );
-            mv.visitInsn( IRETURN );
-        }
-        else if( aClass.equals( Double.TYPE ) )
-        {
-            mv.visitTypeInsn( CHECKCAST, "java/lang/Double" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false );
-            mv.visitLabel( label );
-            mv.visitInsn( DRETURN );
-        }
-        else if( aClass.equals( Float.TYPE ) )
-        {
-            mv.visitTypeInsn( CHECKCAST, "java/lang/Float" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false );
-            mv.visitLabel( label );
-            mv.visitInsn( FRETURN );
-        }
-        else if( aClass.equals( Boolean.TYPE ) )
-        {
-            mv.visitTypeInsn( CHECKCAST, "java/lang/Boolean" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false );
-            mv.visitLabel( label );
-            mv.visitInsn( IRETURN );
-        }
-        else if( aClass.equals( Character.TYPE ) )
-        {
-            mv.visitTypeInsn( CHECKCAST, "java/lang/Character" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false );
-            mv.visitLabel( label );
-            mv.visitInsn( IRETURN );
-        }
-        else
-        {
-            mv.visitTypeInsn( CHECKCAST, getInternalName( aClass ) );
-            mv.visitLabel( label );
-            mv.visitInsn( ARETURN );
-        }
-    }
-
-    private static int loadParameter( MethodVisitor mv, Class<?> aClass, int idx )
-    {
-        if( aClass.equals( Integer.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-        }
-        else if( aClass.equals( Long.TYPE ) )
-        {
-            mv.visitVarInsn( LLOAD, idx );
-            idx++; // Extra jump
-        }
-        else if( aClass.equals( Short.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-        }
-        else if( aClass.equals( Byte.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-        }
-        else if( aClass.equals( Double.TYPE ) )
-        {
-            mv.visitVarInsn( DLOAD, idx );
-            idx++; // Extra jump
-        }
-        else if( aClass.equals( Float.TYPE ) )
-        {
-            mv.visitVarInsn( FLOAD, idx );
-        }
-        else if( aClass.equals( Boolean.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-        }
-        else if( aClass.equals( Character.TYPE ) )
-        {
-            mv.visitVarInsn( ILOAD, idx );
-        }
-        else
-        {
-            mv.visitVarInsn( ALOAD, idx );
-        }
-
-        return idx;
-    }
-
-    private static void returnResult( MethodVisitor mv, Class<?> aClass )
-    {
-        if( aClass.equals( Integer.TYPE ) )
-        {
-            mv.visitInsn( IRETURN );
-        }
-        else if( aClass.equals( Long.TYPE ) )
-        {
-            mv.visitInsn( LRETURN );
-        }
-        else if( aClass.equals( Short.TYPE ) )
-        {
-            mv.visitInsn( IRETURN );
-        }
-        else if( aClass.equals( Byte.TYPE ) )
-        {
-            mv.visitInsn( IRETURN );
-        }
-        else if( aClass.equals( Double.TYPE ) )
-        {
-            mv.visitInsn( DRETURN );
-        }
-        else if( aClass.equals( Float.TYPE ) )
-        {
-            mv.visitInsn( FRETURN );
-        }
-        else if( aClass.equals( Boolean.TYPE ) )
-        {
-            mv.visitInsn( IRETURN );
-        }
-        else if( aClass.equals( Character.TYPE ) )
-        {
-            mv.visitInsn( IRETURN );
-        }
-        else
-        {
-            mv.visitTypeInsn( CHECKCAST, getInternalName( aClass ) );
-            mv.visitInsn( ARETURN );
-        }
-    }
-
-    private static void insn( MethodVisitor mv, int length )
-    {
-        switch( length )
-        {
-        case 0:
-            mv.visitInsn( ICONST_0 );
-            return;
-        case 1:
-            mv.visitInsn( ICONST_1 );
-            return;
-        case 2:
-            mv.visitInsn( ICONST_2 );
-            return;
-        case 3:
-            mv.visitInsn( ICONST_3 );
-            return;
-        case 4:
-            mv.visitInsn( ICONST_4 );
-            return;
-        case 5:
-            mv.visitInsn( ICONST_5 );
-            return;
-        default:
-            mv.visitIntInsn( BIPUSH, length );
-        }
-    }
-
-    public static boolean isGenerated( Class clazz )
-    {
-        return clazz.getName().endsWith( GENERATED_POSTFIX );
-    }
-
-    public static boolean isGenerated( Object object )
-    {
-        return object.getClass().getName().endsWith( GENERATED_POSTFIX );
-    }
-
-    public Class loadFragmentClass( Class fragmentClass )
-        throws ClassNotFoundException
-    {
-        return loadClass( fragmentClass.getName().replace( '$', '_' ) + GENERATED_POSTFIX );
-    }
-
-    public static Class getSourceClass( Class fragmentClass )
-    {
-        return fragmentClass.getName().endsWith( GENERATED_POSTFIX ) ? fragmentClass.getSuperclass() : fragmentClass;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientInstance.java
deleted file mode 100644
index 78bc5a2..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientInstance.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2007, Alin Dreghiciu. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.Arrays;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.api.property.StateHolder;
-import org.qi4j.api.structure.Layer;
-import org.qi4j.api.structure.Module;
-import org.qi4j.runtime.structure.ModuleInstance;
-import org.qi4j.spi.module.ModuleSpi;
-
-/**
- * InvocationHandler for proxy objects.
- */
-public class TransientInstance
-    implements CompositeInstance, MixinsInstance
-{
-    public static TransientInstance compositeInstanceOf( Composite composite )
-    {
-        InvocationHandler handler = Proxy.getInvocationHandler( composite );
-        return (TransientInstance) handler;
-    }
-
-    private final Composite proxy;
-    protected final Object[] mixins;
-    protected StateHolder state;
-    protected final CompositeModel compositeModel;
-    private final ModuleSpi moduleInstance;
-
-    public TransientInstance( CompositeModel compositeModel,
-                              ModuleSpi moduleInstance,
-                              Object[] mixins,
-                              StateHolder state
-    )
-    {
-        this.compositeModel = compositeModel;
-        this.moduleInstance = moduleInstance;
-        this.mixins = mixins;
-        this.state = state;
-
-        proxy = compositeModel.newProxy( this );
-    }
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        return compositeModel.invoke( this, proxy, method, args, moduleInstance );
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public <T> T proxy()
-    {
-        return (T) proxy;
-    }
-
-    @Override
-    public <T> T newProxy( Class<T> mixinType )
-        throws IllegalArgumentException
-    {
-        return compositeModel.newProxy( this, mixinType );
-    }
-
-    @Override
-    public Object invokeComposite( Method method, Object[] args )
-        throws Throwable
-    {
-        return compositeModel.invoke( this, proxy, method, args, moduleInstance );
-    }
-
-    @Override
-    public CompositeModel descriptor()
-    {
-        return compositeModel;
-    }
-
-    @Override
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return compositeModel.metaInfo( infoType );
-    }
-
-    @Override
-    public Iterable<Class<?>> types()
-    {
-        return compositeModel.types();
-    }
-
-    @Override
-    public Module module()
-    {
-        return moduleInstance;
-    }
-
-    public Layer layer()
-    {
-        return ( (ModuleInstance) moduleInstance ).layerInstance();
-    }
-
-    @Override
-    public StateHolder state()
-    {
-        return state;
-    }
-
-    @Override
-    public Object invoke( Object composite, Object[] params, CompositeMethodInstance methodInstance )
-        throws Throwable
-    {
-        Object mixin = methodInstance.getMixinFrom( mixins );
-        return methodInstance.invoke( proxy, params, mixin );
-    }
-
-    @Override
-    public Object invokeObject( Object proxy, Object[] args, Method method )
-        throws Throwable
-    {
-        return method.invoke( this, args );
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if( o == null )
-        {
-            return false;
-        }
-        if( !Proxy.isProxyClass( o.getClass() ) )
-        {
-            return false;
-        }
-        TransientInstance other = (TransientInstance) Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF.map( (Composite) o );
-        if( other.mixins.length != mixins.length )
-        {
-            return false;
-        }
-
-        for( int i = 0; i < mixins.length; i++ )
-        {
-            if( !mixins[ i ].equals( other.mixins[ i ] ) )
-            {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public int hashCode()
-    {
-        int hashCode = 0;
-        for( Object mixin : mixins )
-        {
-            hashCode = hashCode * 31 + mixin.hashCode();
-        }
-        return hashCode;
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder buffer = new StringBuilder();
-        boolean first = true;
-        for( Object mixin : mixins )
-        {
-            try
-            {
-                if( mixin != null )  // Can happen during construction of incorrect composites, during exception creation.
-                {
-                    Class<?> type = mixin.getClass();
-                    Method toStringMethod = type.getMethod( "toString" );
-                    Class<?> declaringClass = toStringMethod.getDeclaringClass();
-                    if( !declaringClass.equals( Object.class ) )
-                    {
-                        if( !first )
-                        {
-                            buffer.append( ", " );
-                        }
-                        first = false;
-                        buffer.append( mixin.toString() );
-                    }
-                }
-            }
-            catch( NoSuchMethodException e )
-            {
-                // Can not happen??
-                e.printStackTrace();
-            }
-        }
-        if( first )
-        {
-            String modelTypeName = compositeModel.getClass().getSimpleName();
-            String metaTypeModel = modelTypeName.substring( 0, modelTypeName.length() - 5 );
-            return metaTypeModel + "Instance{" +
-                   "mixins=" + ( mixins == null ? null : Arrays.asList( mixins ) ) +
-                   ", state=" + state +
-                   ", compositeModel=" + compositeModel +
-                   ", module=" + moduleInstance +
-                   '}';
-        }
-        return buffer.toString();
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientModel.java
deleted file mode 100644
index 968fa5e..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientModel.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.TransientDescriptor;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.runtime.injection.InjectionContext;
-import org.qi4j.runtime.property.PropertyModel;
-import org.qi4j.spi.module.ModuleSpi;
-
-/**
- * Model for Transient Composites
- */
-public class TransientModel
-    extends CompositeModel
-    implements TransientDescriptor
-{
-    public TransientModel( Iterable<Class<?>> types, final Visibility visibility,
-                           final MetaInfo metaInfo,
-                           final MixinsModel mixinsModel,
-                           final StateModel stateModel,
-                           final CompositeMethodsModel compositeMethodsModel
-    )
-    {
-        super( types, visibility, metaInfo, mixinsModel, stateModel, compositeMethodsModel );
-    }
-
-    public TransientInstance newInstance( ModuleSpi moduleInstance,
-                                          UsesInstance uses,
-                                          TransientStateInstance state
-    )
-    {
-        Object[] mixins = mixinsModel.newMixinHolder();
-        TransientInstance compositeInstance = new TransientInstance( this, moduleInstance, mixins, state );
-
-        // Instantiate all mixins
-        int i = 0;
-        InjectionContext injectionContext = new InjectionContext( compositeInstance, uses, state );
-        for( MixinModel mixinModel : mixinsModel.mixinModels() )
-        {
-            mixins[ i++ ] = mixinModel.newInstance( injectionContext );
-        }
-
-        // Return
-        return compositeInstance;
-    }
-
-    public void checkConstraints( TransientStateInstance instanceState )
-        throws ConstraintViolationException
-    {
-        for( PropertyModel propertyModel : stateModel.properties() )
-        {
-            propertyModel.checkConstraints( instanceState.<Object>propertyFor( propertyModel.accessor() ).get() );
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientStateInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientStateInstance.java
deleted file mode 100644
index cc0d7e3..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientStateInstance.java
+++ /dev/null
@@ -1,60 +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.qi4j.runtime.composite;
-
-import java.lang.reflect.AccessibleObject;
-import java.util.Map;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.StateHolder;
-
-/**
- * TODO
- */
-public final class TransientStateInstance
-    implements StateHolder
-{
-    private final Map<AccessibleObject, Property<?>> properties;
-
-    public TransientStateInstance( Map<AccessibleObject, Property<?>> properties
-    )
-    {
-        this.properties = properties;
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public <T> Property<T> propertyFor( AccessibleObject accessor )
-        throws IllegalArgumentException
-    {
-        Property<T> property = (Property<T>) properties.get( accessor );
-
-        if( property == null )
-        {
-            throw new IllegalArgumentException( "No such property:" + accessor );
-        }
-
-        return property;
-    }
-
-    @Override
-    public Iterable<Property<?>> properties()
-    {
-        return properties.values();
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientsModel.java
deleted file mode 100644
index b03a496..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/TransientsModel.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.util.List;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-
-/**
- * JAVADOC
- */
-public class TransientsModel
-    implements VisitableHierarchy<Object, Object>
-{
-    private final List<TransientModel> transientModels;
-
-    public TransientsModel( List<TransientModel> transientModels )
-    {
-        this.transientModels = transientModels;
-    }
-
-    public Iterable<TransientModel> models()
-    {
-        return transientModels;
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
-        throws ThrowableType
-    {
-        if( modelVisitor.visitEnter( this ) )
-        {
-            for( TransientModel transientModel : transientModels )
-            {
-                if( !transientModel.accept( modelVisitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return modelVisitor.visitLeave( this );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/TypedModifierInvocationHandler.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/TypedModifierInvocationHandler.java
deleted file mode 100644
index 4e9654a..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/TypedModifierInvocationHandler.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import org.qi4j.api.composite.InvalidCompositeException;
-
-/**
- * JAVADOC
- */
-public final class TypedModifierInvocationHandler
-    extends FragmentInvocationHandler
-{
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        try
-        {
-            return this.method.invoke( fragment, args );
-        }
-        catch( InvocationTargetException e )
-        {
-            throw cleanStackTrace( e.getTargetException(), proxy, method );
-        }
-        catch( Throwable e )
-        {
-            if( fragment == null )
-            {
-                throw new InvalidCompositeException( "No fragment available for method " + method.getName() );
-            }
-            throw cleanStackTrace( e, proxy, method );
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/UnsynchronizedCompositeMethodInstancePool.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/UnsynchronizedCompositeMethodInstancePool.java
deleted file mode 100644
index 0ddf3c6..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/UnsynchronizedCompositeMethodInstancePool.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-/**
- * Method instance pool that keeps a linked list. Uses synchronization
- * to ensure that instances are acquired and returned in a thread-safe
- * manner.
- */
-public final class UnsynchronizedCompositeMethodInstancePool
-    implements InstancePool<CompositeMethodInstance>
-{
-    private CompositeMethodInstance first = null;
-
-    @Override
-    public CompositeMethodInstance obtainInstance()
-    {
-        CompositeMethodInstance instance = first;
-        if( instance != null )
-        {
-            first = instance.getNext();
-        }
-        return instance;
-    }
-
-    @Override
-    public void releaseInstance( CompositeMethodInstance instance )
-    {
-        instance.setNext( first );
-        first = instance;
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/UsageGraph.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/UsageGraph.java
deleted file mode 100644
index ae1e5d9..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/UsageGraph.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.runtime.composite;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import org.qi4j.bootstrap.BindingException;
-
-/**
- * This class is NOT thread-safe.
- * //TODO: Algorithm need to be optimized.
- */
-public final class UsageGraph<K>
-{
-    private final Collection<K> data;
-    private final Use<K> use;
-    private final boolean allowCyclic;
-    private List<K> resolved;
-    private HashMap<K, List<K>> transitive;
-
-    public UsageGraph( Collection<K> data, Use<K> use, boolean allowCyclic )
-    {
-        this.data = data;
-        this.use = use;
-        this.allowCyclic = allowCyclic;
-    }
-
-    public boolean transitiveUse( K source, K other )
-        throws BindingException
-    {
-        if( transitive == null )
-        {
-            buildUsageGraph();
-        }
-        return transitive.containsKey( source ) && transitive.get( source ).contains( other );
-    }
-
-    private void checkCyclic( List<K> visited, K sourceItem, K used )
-        throws BindingException
-    {
-        Collection<K> nextLevel = use.uses( used );
-        for( K next : nextLevel )
-        {
-            if( next == sourceItem )
-            {
-                if( !allowCyclic )
-                {
-                    visited.add( next );
-                    throw new BindingException( "Cyclic usage detected: " + sourceItem + " -> " + visited );
-                }
-            }
-            if( !visited.contains( next ) )
-            {
-                visited.add( next );
-                checkCyclic( visited, sourceItem, next );
-            }
-        }
-    }
-
-    /**
-     * Must be called if the data set has been modified.
-     */
-    public void invalidate()
-    {
-        resolved = null;
-        transitive = null;
-    }
-
-    public List<K> resolveOrder()
-        throws BindingException
-    {
-        if( resolved == null )
-        {
-            buildUsageGraph();
-            resolved = new LinkedList<K>();
-            for( K item : data )
-            {
-                int pos = resolved.size();
-                for( K entry : resolved )
-                {
-                    if( transitiveUse( entry, item ) )
-                    {
-                        pos = resolved.indexOf( entry );
-                        break;
-                    }
-                }
-                resolved.add( pos, item );
-            }
-        }
-        return resolved;
-    }
-
-    private void buildUsageGraph()
-        throws BindingException
-    {
-        transitive = new HashMap<K, List<K>>();
-        for( K sourceItem : data )
-        {
-            LinkedList<K> visited = new LinkedList<K>();
-            checkCyclic( visited, sourceItem, sourceItem );
-            transitive.put( sourceItem, visited );
-        }
-    }
-
-    public interface Use<K>
-    {
-
-        /**
-         * @param source The item to be queried.
-         *
-         * @return A list of items it uses.
-         */
-        Collection<K> uses( K source );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/UsesInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/UsesInstance.java
deleted file mode 100644
index 4d34b93..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/UsesInstance.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import org.qi4j.functional.Iterables;
-
-/**
- * JAVADOC
- */
-public final class UsesInstance
-{
-    public static final UsesInstance EMPTY_USES;
-    private final Set<Object> uses;
-
-    static
-    {
-        EMPTY_USES = new UsesInstance( new HashSet<>() );
-    }
-
-    private UsesInstance( HashSet<Object> uses )
-    {
-        this.uses = Collections.unmodifiableSet( uses );
-    }
-
-    public UsesInstance use( Object... objects )
-    {
-        HashSet<Object> useObjects = new HashSet<>();
-        if( !uses.isEmpty() )
-        {
-            useObjects.addAll( uses );
-            for( Object object : objects )
-            {
-                Object oldUseForType = useForType( object.getClass() );
-                if( oldUseForType != null )
-                {
-                    useObjects.remove( oldUseForType );
-                }
-            }
-        }
-        useObjects.addAll( Arrays.asList( objects ) );
-        return new UsesInstance( useObjects );
-    }
-
-    public Object useForType( Class<?> type )
-    {
-        // Check instances first
-        for( Object use : uses )
-        {
-            if( type.isInstance( use ) )
-            {
-                return use;
-            }
-        }
-
-        return null;
-    }
-
-    public Object[] toArray()
-    {
-        return Iterables.toArray( uses );
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-        UsesInstance that = (UsesInstance) o;
-        return uses.equals( that.uses );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return uses.hashCode();
-    }
-
-    @Override
-    public String toString()
-    {
-        return "UsesInstance{" +
-               "uses=" + uses +
-               '}';
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/ValueConstraintsInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/ValueConstraintsInstance.java
deleted file mode 100644
index 35aa5c2..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/ValueConstraintsInstance.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.annotation.Annotation;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.constraint.ConstraintViolation;
-
-/**
- * JAVADOC
- */
-public final class ValueConstraintsInstance
-{
-    private static final Optional OPTIONAL;
-
-    static
-    {
-        OPTIONAL = new OptionalDummy();
-    }
-
-    @SuppressWarnings( "raw" )
-    private final List<ConstraintInstance> constraints;
-    private String name;
-    private boolean optional;
-
-    public ValueConstraintsInstance( List<AbstractConstraintModel> constraintModels, String name, boolean optional )
-    {
-        this.name = name;
-        this.optional = optional;
-        constraints = new ArrayList<>();
-        for( AbstractConstraintModel constraintModel : constraintModels )
-        {
-            constraints.add( constraintModel.newInstance() );
-        }
-    }
-
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public List<ConstraintViolation> checkConstraints( Object value )
-    {
-        List<ConstraintViolation> violations = null;
-
-        // Check optional first - this avoids NPE's in constraints
-        if( optional )
-        {
-            if( value == null )
-            {
-                violations = Collections.emptyList();
-            }
-        }
-        else
-        {
-            if( value == null )
-            {
-                violations = new ArrayList<>();
-                violations.add( new ConstraintViolation( name, OPTIONAL, null ) );
-            }
-        }
-
-        if( violations == null && value != null )
-        {
-            for( ConstraintInstance constraint : constraints )
-            {
-                boolean valid;
-                try
-                {
-                    valid = constraint.isValid( value );
-                }
-                catch( NullPointerException e )
-                {
-                    // A NPE is the same as a failing constraint
-                    valid = false;
-                }
-
-                if( !valid )
-                {
-                    if( violations == null )
-                    {
-                        violations = new ArrayList<>();
-                    }
-                    ConstraintViolation violation = new ConstraintViolation( name, constraint.annotation(), value );
-                    violations.add( violation );
-                }
-            }
-        }
-
-        if( violations == null )
-        {
-            violations = Collections.emptyList();
-        }
-
-        return violations;
-    }
-
-    @SuppressWarnings( "AnnotationAsSuperInterface" )
-    private static class OptionalDummy
-        implements Optional
-    {
-        @Override
-        public Class<? extends Annotation> annotationType()
-        {
-            return Optional.class;
-        }
-
-        @Override
-        public String toString()
-        {
-            return "not optional";
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/composite/ValueConstraintsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/composite/ValueConstraintsModel.java
deleted file mode 100644
index 8cd2df0..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/composite/ValueConstraintsModel.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.util.List;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-
-/**
- * JAVADOC
- */
-public final class ValueConstraintsModel
-    implements VisitableHierarchy<Object, Object>
-{
-    private final List<AbstractConstraintModel> constraintModels;
-    private String name;
-    private boolean optional;
-
-    public ValueConstraintsModel( List<AbstractConstraintModel> constraintModels, String name, boolean optional )
-    {
-        this.constraintModels = constraintModels;
-        this.name = name;
-        this.optional = optional;
-    }
-
-    public ValueConstraintsInstance newInstance()
-    {
-        return new ValueConstraintsInstance( constraintModels, name, optional );
-    }
-
-    public boolean isConstrained()
-    {
-        if( !constraintModels.isEmpty() )
-        {
-            return true;
-        }
-
-        return !optional;
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
-        throws ThrowableType
-    {
-        for( AbstractConstraintModel constraintModel : constraintModels )
-        {
-            if( constraintModel.accept( modelVisitor ) )
-            {
-                return false;
-            }
-        }
-        return true;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/entity/EntitiesModel.java b/core/runtime/src/main/java/org/qi4j/runtime/entity/EntitiesModel.java
deleted file mode 100644
index 7189682..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/entity/EntitiesModel.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.entity;
-
-import java.util.List;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-
-/**
- * Model of entities in a particular Module.
- */
-public class EntitiesModel
-    implements VisitableHierarchy<Object, Object>
-{
-    private final List<EntityModel> entityModels;
-
-    public EntitiesModel( List<EntityModel> entityModels )
-    {
-        this.entityModels = entityModels;
-    }
-
-    public Iterable<EntityModel> models()
-    {
-        return entityModels;
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
-        throws ThrowableType
-    {
-        if( modelVisitor.visitEnter( this ) )
-        {
-            for( EntityModel entityModel : entityModels )
-            {
-                if( !entityModel.accept( modelVisitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return modelVisitor.visitLeave( this );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityInstance.java
deleted file mode 100644
index 7228c41..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityInstance.java
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright (c) 2008-2009, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2009-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.entity;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.HashSet;
-import java.util.Set;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationStateDescriptor;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.entity.LifecycleException;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkException;
-import org.qi4j.runtime.composite.CompositeMethodInstance;
-import org.qi4j.runtime.composite.MixinsInstance;
-import org.qi4j.runtime.structure.ModuleUnitOfWork;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.EntityStatus;
-import org.qi4j.spi.module.ModuleSpi;
-
-/**
- * Entity instance
- */
-public final class EntityInstance
-    implements CompositeInstance, MixinsInstance
-{
-    public static EntityInstance entityInstanceOf( EntityComposite composite )
-    {
-        return (EntityInstance) Proxy.getInvocationHandler( composite );
-    }
-
-    private final EntityComposite proxy;
-    private final ModuleUnitOfWork uow;
-    private final ModuleSpi moduleInstance;
-    private final EntityModel entityModel;
-    private final EntityReference identity;
-    private final EntityState entityState;
-
-    private Object[] mixins;
-    private EntityStateInstance state;
-
-    public EntityInstance( ModuleUnitOfWork uow,
-                           ModuleSpi moduleInstance,
-                           EntityModel entityModel,
-                           EntityState entityState
-    )
-    {
-        this.uow = uow;
-        this.moduleInstance = moduleInstance;
-        this.entityModel = entityModel;
-        this.identity = entityState.identity();
-        this.entityState = entityState;
-
-        proxy = (EntityComposite) entityModel.newProxy( this );
-    }
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        return entityModel.invoke( this, this.proxy, method, args, moduleInstance );
-    }
-
-    public EntityReference identity()
-    {
-        return identity;
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public <T> T proxy()
-    {
-        return (T) proxy;
-    }
-
-    @Override
-    public CompositeDescriptor descriptor()
-    {
-        return entityModel;
-    }
-
-    @Override
-    public <T> T newProxy( Class<T> mixinType )
-        throws IllegalArgumentException
-    {
-        return entityModel.newProxy( this, mixinType );
-    }
-
-    @Override
-    public Object invokeComposite( Method method, Object[] args )
-        throws Throwable
-    {
-        return entityModel.invoke( this, proxy, method, args, moduleInstance );
-    }
-
-    @Override
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return entityModel.metaInfo( infoType );
-    }
-
-    public EntityModel entityModel()
-    {
-        return entityModel;
-    }
-
-    @Override
-    public Iterable<Class<?>> types()
-    {
-        return entityModel.types();
-    }
-
-    @Override
-    public ModuleSpi module()
-    {
-        return moduleInstance;
-    }
-
-    public UnitOfWork unitOfWork()
-    {
-        return uow;
-    }
-
-    public EntityState entityState()
-    {
-        return entityState;
-    }
-
-    @Override
-    public EntityStateInstance state()
-    {
-        if( state == null )
-        {
-            initState();
-        }
-
-        return state;
-    }
-
-    public EntityStatus status()
-    {
-        return entityState.status();
-    }
-
-    @Override
-    public Object invoke( Object composite, Object[] params, CompositeMethodInstance methodInstance )
-        throws Throwable
-    {
-        if( mixins == null )
-        {
-            initState();
-        }
-
-        Object mixin = methodInstance.getMixinFrom( mixins );
-
-        if( mixin == null )
-        {
-            mixin = entityModel.newMixin( mixins, state, this, methodInstance.method() );
-        }
-
-        return methodInstance.invoke( proxy, params, mixin );
-    }
-
-    @Override
-    public Object invokeObject( Object proxy, Object[] args, Method method )
-        throws Throwable
-    {
-        return method.invoke( this, args );
-    }
-
-    private void initState()
-    {
-        if( !uow.isOpen() )
-        {
-            throw new UnitOfWorkException( "Unit of work has been closed" );
-        }
-
-        if( status() == EntityStatus.REMOVED )
-        {
-            throw new NoSuchEntityException( identity, entityModel.types(), unitOfWork().usecase() );
-        }
-
-        mixins = entityModel.newMixinHolder();
-        state = new EntityStateInstance( entityModel.state(), uow, entityState );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return identity.hashCode();
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        try
-        {
-            Identity other = ( (Identity) o );
-            return other != null && other.identity().get().equals( identity.identity() );
-        }
-        catch( ClassCastException e )
-        {
-            return false;
-        }
-    }
-
-    @Override
-    public String toString()
-    {
-        return identity.toString();
-    }
-
-    public void remove( UnitOfWork unitOfWork )
-        throws LifecycleException
-    {
-        invokeRemove();
-
-        removeAggregatedEntities( unitOfWork );
-
-        entityState.remove();
-        mixins = null;
-    }
-
-    public void invokeCreate()
-    {
-        lifecyleInvoke( true );
-    }
-
-    private void invokeRemove()
-    {
-        lifecyleInvoke( false );
-    }
-
-    private void lifecyleInvoke( boolean create )
-    {
-        if( mixins == null )
-        {
-            initState();
-        }
-
-        entityModel.invokeLifecycle( create, mixins, this, state );
-    }
-
-    private void removeAggregatedEntities( UnitOfWork unitOfWork )
-    {
-        // Calculate aggregated Entities
-        AssociationStateDescriptor stateDescriptor = entityModel.state();
-        Set<Object> aggregatedEntities = new HashSet<>();
-        Iterable<? extends AssociationDescriptor> associations = stateDescriptor.associations();
-        for( AssociationDescriptor association : associations )
-        {
-            if( association.isAggregated() )
-            {
-                Association<?> assoc = state.associationFor( association.accessor() );
-                Object aggregatedEntity = assoc.get();
-                if( aggregatedEntity != null )
-                {
-                    aggregatedEntities.add( aggregatedEntity );
-                }
-            }
-        }
-        Iterable<? extends AssociationDescriptor> manyAssociations = stateDescriptor.manyAssociations();
-        for( AssociationDescriptor association : manyAssociations )
-        {
-            if( association.isAggregated() )
-            {
-                ManyAssociation<?> manyAssoc = state.manyAssociationFor( association.accessor() );
-                for( Object entity : manyAssoc )
-                {
-                    aggregatedEntities.add( entity );
-                }
-            }
-        }
-        Iterable<? extends AssociationDescriptor> namedAssociations = stateDescriptor.namedAssociations();
-        for( AssociationDescriptor association : namedAssociations )
-        {
-            if( association.isAggregated() )
-            {
-                NamedAssociation<?> namedAssoc = state.namedAssociationFor( association.accessor() );
-                for( String name : namedAssoc )
-                {
-                    aggregatedEntities.add( namedAssoc.get( name ) );
-                }
-            }
-        }
-
-        // Remove aggregated Entities
-        for( Object aggregatedEntity : aggregatedEntities )
-        {
-            unitOfWork.remove( aggregatedEntity );
-        }
-    }
-
-    public void checkConstraints()
-    {
-        try
-        {
-            state.checkConstraints();
-        }
-        catch( ConstraintViolationException e )
-        {
-            throw new ConstraintViolationException( identity.identity(), entityModel.types(), e.mixinTypeName(), e.methodName(), e
-                .constraintViolations() );
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityMixinsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityMixinsModel.java
deleted file mode 100644
index a56ffb8..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityMixinsModel.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.entity;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.api.entity.Lifecycle;
-import org.qi4j.api.property.StateHolder;
-import org.qi4j.bootstrap.BindingException;
-import org.qi4j.runtime.composite.MixinModel;
-import org.qi4j.runtime.composite.MixinsModel;
-import org.qi4j.runtime.composite.UsesInstance;
-import org.qi4j.runtime.injection.InjectionContext;
-import org.qi4j.runtime.model.Resolution;
-
-/**
- * JAVADOC
- */
-public final class EntityMixinsModel
-    extends MixinsModel
-{
-    List<Integer> lifecycleMixins;
-
-    @Override
-    public void bind( Resolution resolution )
-        throws BindingException
-    {
-        super.bind( resolution );
-
-        // Find what mixins implement Lifecycle
-        for( int i = 0; i < mixinModels.size(); i++ )
-        {
-            MixinModel mixinModel = mixinModels.get( i );
-            if( Lifecycle.class.isAssignableFrom( mixinModel.mixinClass() ) )
-            {
-                if( lifecycleMixins == null )
-                {
-                    lifecycleMixins = new ArrayList<Integer>();
-                }
-
-                lifecycleMixins.add( i );
-            }
-        }
-    }
-
-    public Object newMixin( EntityInstance entityInstance, StateHolder state, Object[] mixins, Method method )
-    {
-        MixinModel model = methodImplementation.get( method );
-        InjectionContext injectionContext = new InjectionContext( entityInstance, UsesInstance.EMPTY_USES, state );
-        Object mixin = model.newInstance( injectionContext );
-        mixins[ methodIndex.get( method ) ] = mixin;
-        return mixin;
-    }
-
-    public void invokeLifecycle( boolean create, Object[] mixins, CompositeInstance instance, StateHolder state )
-    {
-        if( lifecycleMixins != null )
-        {
-            InjectionContext injectionContext = new InjectionContext( instance, UsesInstance.EMPTY_USES, state );
-            for( Integer lifecycleMixin : lifecycleMixins )
-            {
-                Lifecycle lifecycle = (Lifecycle) mixins[ lifecycleMixin ];
-
-                if( lifecycle == null )
-                {
-                    lifecycle = (Lifecycle) mixinModels.get( lifecycleMixin ).newInstance( injectionContext );
-                }
-
-                if( create )
-                {
-                    lifecycle.create();
-                }
-                else
-                {
-                    lifecycle.remove();
-                }
-            }
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityModel.java b/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityModel.java
deleted file mode 100644
index 8637034..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityModel.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.entity;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.property.StateHolder;
-import org.qi4j.api.unitofwork.EntityCompositeAlreadyExistsException;
-import org.qi4j.api.util.Annotations;
-import org.qi4j.functional.Iterables;
-import org.qi4j.runtime.composite.CompositeMethodsModel;
-import org.qi4j.runtime.composite.CompositeModel;
-import org.qi4j.runtime.property.PropertyModel;
-import org.qi4j.runtime.structure.ModuleUnitOfWork;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entitystore.EntityAlreadyExistsException;
-import org.qi4j.spi.entitystore.EntityStoreException;
-import org.qi4j.spi.entitystore.EntityStoreUnitOfWork;
-import org.qi4j.spi.module.ModuleSpi;
-
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.flattenIterables;
-import static org.qi4j.functional.Iterables.map;
-
-/**
- * JAVADOC
- */
-public final class EntityModel
-    extends CompositeModel
-    implements EntityDescriptor
-{
-    private static final Method IDENTITY_METHOD;
-
-    static
-    {
-        try
-        {
-            IDENTITY_METHOD = Identity.class.getMethod( "identity" );
-        }
-        catch( NoSuchMethodException e )
-        {
-            throw new InternalError( "Zest Core Runtime codebase is corrupted. Contact Zest team: ModuleUnitOfWork" );
-        }
-    }
-
-    private final boolean queryable;
-
-    public EntityModel( Iterable<Class<?>> types,
-                        Visibility visibility,
-                        MetaInfo info,
-                        EntityMixinsModel mixinsModel,
-                        EntityStateModel stateModel,
-                        CompositeMethodsModel compositeMethodsModel
-    )
-    {
-        super( types, visibility, info, mixinsModel, stateModel, compositeMethodsModel );
-
-        final Queryable queryable = first( Iterables.<Queryable>cast(
-            filter( Annotations.isType( Queryable.class ),
-                    flattenIterables( map( Annotations.ANNOTATIONS_OF, types ) ) ) ) );
-        this.queryable = queryable == null || queryable.value();
-    }
-
-    @Override
-    public boolean queryable()
-    {
-        return queryable;
-    }
-
-    @Override
-    public EntityStateModel state()
-    {
-        return (EntityStateModel) super.state();
-    }
-
-    public EntityInstance newInstance( ModuleUnitOfWork uow, ModuleSpi moduleInstance, EntityState state )
-    {
-        EntityInstance instance = new EntityInstance( uow, moduleInstance, this, state );
-        return instance;
-    }
-
-    public Object[] newMixinHolder()
-    {
-        return mixinsModel.newMixinHolder();
-    }
-
-    public Object newMixin( Object[] mixins,
-                            EntityStateInstance entityState,
-                            EntityInstance entityInstance,
-                            Method method
-    )
-    {
-        return ( (EntityMixinsModel) mixinsModel ).newMixin( entityInstance, entityState, mixins, method );
-    }
-
-    public EntityState newEntityState( EntityStoreUnitOfWork store, ModuleSpi module, EntityReference identity )
-        throws ConstraintViolationException, EntityStoreException
-    {
-        try
-        {
-            // New EntityState
-            EntityState entityState = store.newEntityState( module, identity, this );
-
-            // Set identity property
-            PropertyDescriptor persistentPropertyDescriptor = state().propertyModelFor( IDENTITY_METHOD );
-            entityState.setPropertyValue( persistentPropertyDescriptor.qualifiedName(), identity.identity() );
-
-            return entityState;
-        }
-        catch( EntityAlreadyExistsException e )
-        {
-            throw new EntityCompositeAlreadyExistsException( identity );
-        }
-        catch( EntityStoreException e )
-        {
-            throw new ConstructionException( "Could not create new entity in store", e );
-        }
-    }
-
-    public void initState( ModuleSpi module, EntityState entityState )
-    {
-        // Set new properties to default value
-        for( PropertyModel propertyDescriptor : state().properties() )
-        {
-            entityState.setPropertyValue( propertyDescriptor.qualifiedName(), propertyDescriptor.initialValue( module ) );
-        }
-
-        // Set new associations to null
-        for( AssociationDescriptor associationDescriptor : state().associations() )
-        {
-            entityState.setAssociationValue( associationDescriptor.qualifiedName(), null );
-        }
-
-        // Set new many-associations to empty
-        for( AssociationDescriptor associationDescriptor : state().manyAssociations() )
-        {
-            entityState.manyAssociationValueOf( associationDescriptor.qualifiedName() );
-        }
-
-        // Set new named-associations to empty
-        for( AssociationDescriptor associationDescriptor : state().namedAssociations() )
-        {
-            entityState.namedAssociationValueOf( associationDescriptor.qualifiedName() );
-        }
-    }
-
-    public void invokeLifecycle( boolean create, Object[] mixins, CompositeInstance instance, StateHolder state )
-    {
-        ( (EntityMixinsModel) mixinsModel ).invokeLifecycle( create, mixins, instance, state );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityPropertyInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityPropertyInstance.java
deleted file mode 100644
index 0bc6583..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityPropertyInstance.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.entity;
-
-import org.qi4j.runtime.property.PropertyInfo;
-import org.qi4j.runtime.property.PropertyInstance;
-import org.qi4j.spi.entity.EntityState;
-
-/**
- * {@code EntityPropertyInstance} represents a property whose value must be backed by an EntityState.
- */
-public class EntityPropertyInstance<T>
-    extends PropertyInstance<T>
-{
-    private final EntityState entityState;
-
-    /**
-     * Construct an instance of {@code PropertyInstance} with the specified arguments.
-     *
-     * @param aPropertyInfo The property info. This argument must not be {@code null}.
-     * @param entityState EntityState
-     */
-    @SuppressWarnings( "unchecked" )
-    public EntityPropertyInstance( PropertyInfo aPropertyInfo, EntityState entityState )
-    {
-        super( aPropertyInfo, (T) entityState.propertyValueOf( aPropertyInfo.qualifiedName() ) );
-        this.entityState = entityState;
-    }
-
-    /**
-     * Sets this property value.
-     *
-     * @param aNewValue The new value.
-     */
-    @Override
-    public void set( T aNewValue )
-    {
-        super.set( aNewValue );
-        entityState.setPropertyValue( model.qualifiedName(), aNewValue );
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityStateInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityStateInstance.java
deleted file mode 100644
index 505509b..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityStateInstance.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.entity;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.Map;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.util.Classes;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Function2;
-import org.qi4j.functional.Iterables;
-import org.qi4j.runtime.association.AssociationInstance;
-import org.qi4j.runtime.association.AssociationModel;
-import org.qi4j.runtime.association.ManyAssociationInstance;
-import org.qi4j.runtime.association.ManyAssociationModel;
-import org.qi4j.runtime.association.NamedAssociationInstance;
-import org.qi4j.runtime.association.NamedAssociationModel;
-import org.qi4j.runtime.composite.ConstraintsCheck;
-import org.qi4j.runtime.property.PropertyModel;
-import org.qi4j.runtime.unitofwork.BuilderEntityState;
-import org.qi4j.spi.entity.EntityState;
-
-/**
- * TODO
- */
-public final class EntityStateInstance
-    implements AssociationStateHolder
-{
-    private Map<AccessibleObject, Object> state;
-
-    private final EntityStateModel stateModel;
-    private EntityState entityState;
-    private final Function2<EntityReference, Type, Object> entityFunction;
-
-    public EntityStateInstance( EntityStateModel stateModel, final UnitOfWork uow, EntityState entityState )
-    {
-        this.stateModel = stateModel;
-        this.entityState = entityState;
-
-        entityFunction = new Function2<EntityReference, Type, Object>()
-        {
-            @Override
-            public Object map( EntityReference entityReference, Type type )
-            {
-                return uow.get( Classes.RAW_CLASS.map( type ), entityReference.identity() );
-            }
-        };
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public <T> Property<T> propertyFor( AccessibleObject accessor )
-        throws IllegalArgumentException
-    {
-        Map<AccessibleObject, Object> state = state();
-
-        Property<T> property = (Property<T>) state.get( accessor );
-
-        if( property == null )
-        {
-            PropertyModel entityPropertyModel = stateModel.propertyModelFor( accessor );
-            property = new EntityPropertyInstance<>(
-                entityState instanceof BuilderEntityState
-                ? entityPropertyModel.getBuilderInfo()
-                : entityPropertyModel,
-                entityState );
-            state.put( accessor, property );
-        }
-
-        return property;
-    }
-
-    @Override
-    public Iterable<Property<?>> properties()
-    {
-        return Iterables.map( new Function<PropertyDescriptor, Property<?>>()
-        {
-            @Override
-            public Property<?> map( PropertyDescriptor propertyDescriptor )
-            {
-                return propertyFor( propertyDescriptor.accessor() );
-            }
-        }, stateModel.properties() );
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public <T> Association<T> associationFor( AccessibleObject accessor )
-        throws IllegalArgumentException
-    {
-        Map<AccessibleObject, Object> state = state();
-        Association<T> association = (Association<T>) state.get( accessor );
-
-        if( association == null )
-        {
-            final AssociationModel associationModel = stateModel.getAssociation( accessor );
-            association = new AssociationInstance<>(
-                entityState instanceof BuilderEntityState
-                ? associationModel.getBuilderInfo()
-                : associationModel,
-                entityFunction,
-                new Property<EntityReference>()
-            {
-                @Override
-                public EntityReference get()
-                {
-                    return entityState.associationValueOf( associationModel.qualifiedName() );
-                }
-
-                @Override
-                public void set( EntityReference newValue )
-                    throws IllegalArgumentException, IllegalStateException
-                {
-                    entityState.setAssociationValue( associationModel.qualifiedName(), newValue );
-                }
-            } );
-            state.put( accessor, association );
-        }
-
-        return association;
-    }
-
-    @Override
-    public Iterable<Association<?>> allAssociations()
-    {
-        return Iterables.map( new Function<AssociationDescriptor, Association<?>>()
-        {
-            @Override
-            public Association<?> map( AssociationDescriptor associationDescriptor )
-            {
-                return associationFor( associationDescriptor.accessor() );
-            }
-        }, stateModel.associations() );
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public <T> ManyAssociation<T> manyAssociationFor( AccessibleObject accessor )
-    {
-        Map<AccessibleObject, Object> state = state();
-
-        ManyAssociation<T> manyAssociation = (ManyAssociation<T>) state.get( accessor );
-
-        if( manyAssociation == null )
-        {
-            ManyAssociationModel associationModel = stateModel.getManyAssociation( accessor );
-            manyAssociation = new ManyAssociationInstance<>(
-                entityState instanceof BuilderEntityState
-                ? associationModel.getBuilderInfo()
-                : associationModel,
-                entityFunction,
-                entityState.manyAssociationValueOf( associationModel.qualifiedName() ) );
-            state.put( accessor, manyAssociation );
-        }
-
-        return manyAssociation;
-    }
-
-    @Override
-    public Iterable<ManyAssociation<?>> allManyAssociations()
-    {
-        return Iterables.map( new Function<AssociationDescriptor, ManyAssociation<?>>()
-        {
-            @Override
-            public ManyAssociation<?> map( AssociationDescriptor associationDescriptor )
-            {
-                return manyAssociationFor( associationDescriptor.accessor() );
-            }
-        }, stateModel.manyAssociations() );
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public <T> NamedAssociation<T> namedAssociationFor( AccessibleObject accessor )
-    {
-        Map<AccessibleObject, Object> state = state();
-
-        NamedAssociation<T> namedAssociation = (NamedAssociation<T>) state.get( accessor );
-
-        if( namedAssociation == null )
-        {
-            NamedAssociationModel associationModel = stateModel.getNamedAssociation( accessor );
-            namedAssociation = new NamedAssociationInstance<>(
-                entityState instanceof BuilderEntityState
-                ? associationModel.getBuilderInfo()
-                : associationModel,
-                entityFunction,
-                entityState.namedAssociationValueOf( associationModel.qualifiedName() ) );
-            state.put( accessor, namedAssociation );
-        }
-
-        return namedAssociation;
-    }
-
-    @Override
-    public Iterable<? extends NamedAssociation<?>> allNamedAssociations()
-    {
-        return Iterables.map( new Function<AssociationDescriptor, NamedAssociation<?>>()
-        {
-            @Override
-            public NamedAssociation<?> map( AssociationDescriptor associationDescriptor )
-            {
-                return namedAssociationFor( associationDescriptor.accessor() );
-            }
-        }, stateModel.namedAssociations() );
-    }
-
-    public void checkConstraints()
-    {
-        for( PropertyDescriptor propertyDescriptor : stateModel.properties() )
-        {
-            ConstraintsCheck constraints = (ConstraintsCheck) propertyDescriptor;
-            Property<Object> property = this.propertyFor( propertyDescriptor.accessor() );
-            constraints.checkConstraints( property.get() );
-        }
-
-        for( AssociationDescriptor associationDescriptor : stateModel.associations() )
-        {
-            ConstraintsCheck constraints = (ConstraintsCheck) associationDescriptor;
-            Association<Object> association = this.associationFor( associationDescriptor.accessor() );
-            constraints.checkConstraints( association.get() );
-        }
-
-        // TODO Should ManyAssociations and NamedAssociations be checked too?
-    }
-
-    private Map<AccessibleObject, Object> state()
-    {
-        if( state == null )
-        {
-            state = new HashMap<>();
-        }
-
-        return state;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityStateModel.java b/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityStateModel.java
deleted file mode 100644
index 5fae1a2..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/entity/EntityStateModel.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.entity;
-
-import java.lang.reflect.AccessibleObject;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationStateDescriptor;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.association.AssociationModel;
-import org.qi4j.runtime.association.AssociationsModel;
-import org.qi4j.runtime.association.ManyAssociationModel;
-import org.qi4j.runtime.association.ManyAssociationsModel;
-import org.qi4j.runtime.association.NamedAssociationModel;
-import org.qi4j.runtime.association.NamedAssociationsModel;
-import org.qi4j.runtime.composite.StateModel;
-import org.qi4j.runtime.property.PropertiesModel;
-
-/**
- * Model for EntityComposite state.
- */
-public final class EntityStateModel
-    extends StateModel
-    implements AssociationStateDescriptor
-{
-    private final AssociationsModel associationsModel;
-    private final ManyAssociationsModel manyAssociationsModel;
-    private final NamedAssociationsModel namedAssociationsModel;
-
-    public EntityStateModel( PropertiesModel propertiesModel,
-                             AssociationsModel associationsModel,
-                             ManyAssociationsModel manyAssociationsModel,
-                             NamedAssociationsModel namedAssociationsModel )
-    {
-        super( propertiesModel );
-        this.associationsModel = associationsModel;
-        this.manyAssociationsModel = manyAssociationsModel;
-        this.namedAssociationsModel = namedAssociationsModel;
-    }
-
-    public AssociationModel getAssociation( AccessibleObject accessor )
-        throws IllegalArgumentException
-    {
-        return associationsModel.getAssociation( accessor );
-    }
-
-    @Override
-    public AssociationDescriptor getAssociationByName( String name )
-        throws IllegalArgumentException
-    {
-        return associationsModel.getAssociationByName( name );
-    }
-
-    @Override
-    public AssociationDescriptor getAssociationByQualifiedName( QualifiedName name )
-        throws IllegalArgumentException
-    {
-        return associationsModel.getAssociationByQualifiedName( name );
-    }
-
-    public ManyAssociationModel getManyAssociation( AccessibleObject accessor )
-        throws IllegalArgumentException
-    {
-        return manyAssociationsModel.getManyAssociation( accessor );
-    }
-
-    @Override
-    public AssociationDescriptor getManyAssociationByName( String name )
-        throws IllegalArgumentException
-    {
-        return manyAssociationsModel.getManyAssociationByName( name );
-    }
-
-    @Override
-    public AssociationDescriptor getManyAssociationByQualifiedName( QualifiedName name )
-        throws IllegalArgumentException
-    {
-        return manyAssociationsModel.getManyAssociationByQualifiedName( name );
-    }
-
-    public NamedAssociationModel getNamedAssociation( AccessibleObject accessor )
-        throws IllegalArgumentException
-    {
-        return namedAssociationsModel.getNamedAssociation( accessor );
-    }
-
-    @Override
-    public AssociationDescriptor getNamedAssociationByName( String name )
-        throws IllegalArgumentException
-    {
-        return namedAssociationsModel.getNamedAssociationByName( name );
-    }
-
-    @Override
-    public AssociationDescriptor getNamedAssociationByQualifiedName( QualifiedName name )
-        throws IllegalArgumentException
-    {
-        return namedAssociationsModel.getNamedAssociationByQualifiedName( name );
-    }
-
-    @Override
-    public Iterable<AssociationModel> associations()
-    {
-        return associationsModel.associations();
-    }
-
-    @Override
-    public Iterable<ManyAssociationModel> manyAssociations()
-    {
-        return manyAssociationsModel.manyAssociations();
-    }
-
-    @Override
-    public Iterable<NamedAssociationModel> namedAssociations()
-    {
-        return namedAssociationsModel.namedAssociations();
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            if( ( (VisitableHierarchy<Object, Object>) propertiesModel ).accept( visitor ) )
-            {
-                if( ( (VisitableHierarchy<AssociationsModel, AssociationModel>) associationsModel ).accept( visitor ) )
-                {
-                    if( ( (VisitableHierarchy<ManyAssociationsModel, ManyAssociationModel>) manyAssociationsModel ).accept( visitor ) )
-                    {
-                        ( (VisitableHierarchy<NamedAssociationsModel, NamedAssociationModel>) namedAssociationsModel ).accept( visitor );
-                    }
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/Dependencies.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/Dependencies.java
deleted file mode 100644
index bfd8304..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/Dependencies.java
+++ /dev/null
@@ -1,38 +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.qi4j.runtime.injection;
-
-import org.qi4j.functional.Function;
-
-/**
- * TODO
- */
-public interface Dependencies
-{
-    public static Function<Dependencies, Iterable<DependencyModel>> DEPENDENCIES_FUNCTION = new Function<Dependencies, Iterable<DependencyModel>>()
-    {
-        @Override
-        public Iterable<DependencyModel> map( Dependencies dependencies )
-        {
-            return dependencies.dependencies();
-        }
-    };
-
-    Iterable<DependencyModel> dependencies();
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/DependencyModel.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/DependencyModel.java
deleted file mode 100644
index a01d061..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/DependencyModel.java
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.util.Collections;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.DependencyDescriptor;
-import org.qi4j.bootstrap.BindingException;
-import org.qi4j.bootstrap.InvalidInjectionException;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.Visitable;
-import org.qi4j.functional.Visitor;
-import org.qi4j.runtime.injection.provider.InjectionProviderException;
-import org.qi4j.runtime.model.Binder;
-import org.qi4j.runtime.model.Resolution;
-
-import static org.qi4j.api.util.Annotations.isType;
-import static org.qi4j.functional.Iterables.iterable;
-
-/**
- * JAVADOC
- * move all the extraction code to a TypeUtils class
- */
-public final class DependencyModel
-    implements Binder, DependencyDescriptor, Visitable<DependencyModel>
-{
-    public static boolean isOptional( Annotation injectionAnnotation, Annotation[] annotations )
-    {
-        if( Iterables.matchesAny( isType( Optional.class ), iterable( annotations ) ) )
-        {
-            return true;
-        }
-
-        Method[] methods = injectionAnnotation.annotationType().getMethods();
-        for( Method method : methods )
-        {
-            if( method.getName().equals( "optional" ) )
-            {
-                try
-                {
-                    return (Boolean) method.invoke( injectionAnnotation );
-                }
-                catch( Throwable e )
-                {
-                    return false;
-                }
-            }
-        }
-
-        return false;
-    }
-
-    // Model
-    private final Annotation injectionAnnotation;
-    private final Type injectionType;
-    private final Class<?> injectedClass;
-    private final Class<?> rawInjectionClass;
-    private final boolean optional;
-    private final Annotation[] annotations;
-
-    // Binding
-    private InjectionProvider injectionProvider;
-
-    public DependencyModel( Annotation injectionAnnotation,
-                            Type genericType,
-                            Class<?> injectedClass,
-                            boolean optional,
-                            Annotation[] annotations
-    )
-    {
-        this.injectionAnnotation = injectionAnnotation;
-        this.injectedClass = injectedClass;
-
-        this.injectionType = genericType;
-        this.optional = optional;
-        this.annotations = annotations;
-        this.rawInjectionClass = mapPrimitiveTypes( extractRawInjectionClass( injectedClass, injectionType ) );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( Visitor<? super DependencyModel, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        return visitor.visit( this );
-    }
-
-    private Class<?> extractRawInjectionClass( Class<?> injectedClass, final Type injectionType )
-    {
-        // Calculate raw injection type
-        if( injectionType instanceof Class )
-        {
-            return (Class<?>) injectionType;
-        }
-        else if( injectionType instanceof ParameterizedType )
-        {
-            return (Class<?>) ( (ParameterizedType) injectionType ).getRawType();
-        }
-        else if( injectionType instanceof TypeVariable )
-        {
-            return extractRawInjectionClass( injectedClass, (TypeVariable<?>) injectionType );
-        }
-        throw new IllegalArgumentException(
-            "Could not extract the rawInjectionClass of " + injectedClass + " and " + injectionType );
-    }
-
-    private Class<?> extractRawInjectionClass( Class<?> injectedClass, TypeVariable<?> injectionTypeVariable )
-    {
-        int index = 0;
-        for( TypeVariable<?> typeVariable : injectionTypeVariable.getGenericDeclaration().getTypeParameters() )
-        {
-            if( injectionTypeVariable.getName().equals( typeVariable.getName() ) )
-            {
-                return (Class<?>) getActualType( injectedClass, index );
-            }
-            index++;
-        }
-        throw new IllegalArgumentException(
-            "Could not extract the rawInjectionClass of " + injectedClass + " and " + injectionTypeVariable );
-    }
-
-    // todo continue refactoring
-
-    private Type getActualType( Class<?> injectedClass, int index )
-    {
-        // Type index found - map it to actual type
-        Type genericType = injectedClass;
-        Type type = null;
-
-        while( !Object.class.equals( genericType ) && type == null )
-        {
-            genericType = ( (Class<?>) genericType ).getGenericSuperclass();
-            if( genericType instanceof ParameterizedType )
-            {
-                type = ( (ParameterizedType) genericType ).getActualTypeArguments()[ index ];
-            }
-            else
-            {
-                Type[] genericInterfaces = ( (Class<?>) genericType ).getGenericInterfaces();
-                if( genericInterfaces.length > index )
-                {
-                    type = genericInterfaces[ index ];
-                    if( type instanceof ParameterizedType )
-                    {
-                        type = ( (ParameterizedType) type ).getActualTypeArguments()[ index ];
-                    }
-                    // TODO type may still be one of the generic interfaces???
-                }
-            }
-        }
-
-        if( type == null )
-        {
-            type = Object.class; // Generic type with no constraints so Object is fine
-        }
-
-        return type;
-    }
-
-    // FIXME This method is unused, remove it.
-    private Type extractDependencyType( Type injectionType )
-    {
-        if( injectionType instanceof ParameterizedType )
-        {
-            return ( (ParameterizedType) injectionType ).getActualTypeArguments()[ 0 ];
-        }
-        else if( injectionType instanceof TypeVariable )
-        {
-            return ( (TypeVariable) injectionType ).getBounds()[ 0 ];
-        }
-        return injectionType;
-    }
-
-    // Model
-    @Override
-    public Annotation injectionAnnotation()
-    {
-        return injectionAnnotation;
-    }
-
-    @Override
-    public Type injectionType()
-    {
-        return injectionType;
-    }
-
-    @Override
-    public Class<?> injectedClass()
-    {
-        return injectedClass;
-    }
-
-    /**
-     * Get the raw dependency type.
-     * <p>
-     * If the dependency uses generics this is the raw type,
-     * and otherwise it is the type of the field.
-     * <p>
-     * Examples:
-     * <p>
-     * {@code @Service MyService service} -&gt; MyService
-     * <p>
-     * {@code @Entity Iterable<Foo> fooList} -&gt; Iterable
-     * <p>
-     * {@code @Entity Query<Foo> fooQuery} -&gt; Query
-     *
-     * @return raw injection type.
-     */
-    @Override
-    public Class<?> rawInjectionType()
-    {
-        return rawInjectionClass;
-    }
-
-    @Override
-    public boolean optional()
-    {
-        return optional;
-    }
-
-    @Override
-    public Annotation[] annotations()
-    {
-        return annotations;
-    }
-
-    @Override
-    public void bind( Resolution resolution )
-        throws BindingException
-    {
-        InjectionProviderFactory providerFactory = resolution.application().injectionProviderFactory();
-
-        try
-        {
-            injectionProvider = providerFactory.newInjectionProvider( resolution, this );
-
-            if( injectionProvider == null && !optional )
-            {
-                String message =
-                    "[Module " + resolution.module()
-                        .name() + "] Non-optional @" + rawInjectionClass.getName() + " was not bound in " + injectedClass
-                        .getName();
-                throw new ConstructionException( message );
-            }
-        }
-        catch( InvalidInjectionException e )
-        {
-            throw new BindingException( "Could not bind dependency injection", e );
-        }
-    }
-
-    // Context
-    public Object inject( InjectionContext context )
-    {
-        if( injectionProvider == null )
-        {
-            return null;
-        }
-        Object injectedValue;
-        try
-        {
-            injectedValue = injectionProvider.provideInjection( context );
-        }
-        catch( InjectionProviderException e )
-        {
-            Throwable ex = e;
-            if( ex.getCause() != null )
-            {
-                ex = ex.getCause();
-            }
-
-            String message = "[Module " + context.module().name() + "] InjectionProvider unable to resolve @" +
-                             injectionAnnotation.annotationType().getSimpleName() + " " + injectionType.toString();
-            throw new ConstructionException( message, ex );
-        }
-        if( injectedValue == null && !optional )
-        {
-            String simpleName = injectionAnnotation.annotationType().getSimpleName();
-            String message = "[Module " + context.module().name() + "] Non-optional @" +
-                             simpleName + " " + injectionType.toString() +
-                             " was null in " + injectedClass.getName();
-            if( simpleName.toLowerCase().contains( "service" ) )
-            {
-                message = message + ". Did you mean the @Service injection scope?";
-            }
-            throw new ConstructionException( message );
-        }
-        return getInjectedValue( injectedValue );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private Object getInjectedValue( Object injectionResult )
-    {
-        if( injectionResult == null )
-        {
-            return null;
-        }
-
-        if( injectionResult instanceof Iterable )
-        {
-            if( Iterable.class.isAssignableFrom( rawInjectionClass ) || rawInjectionClass.isInstance(
-                injectionResult ) )
-            {
-                return injectionResult;
-            }
-            else
-            {
-                return Iterables.first( (Iterable) injectionResult );
-            }
-        }
-        else
-        {
-            if( Iterable.class.equals( injectionType ) )
-            {
-                return Collections.singleton( injectionResult );
-            }
-        }
-        return injectionResult;
-    }
-
-    private final static Class<?>[] primitiveTypeMapping = {
-        boolean.class, Boolean.class,
-        byte.class, Byte.class,
-        short.class, Short.class,
-        char.class, Character.class,
-        long.class, Long.class,
-        double.class, Double.class,
-        float.class, Float.class,
-        int.class, Integer.class,
-    };
-
-    private Class<?> mapPrimitiveTypes( Class<?> rawInjectionType )
-    {
-        if( rawInjectionType == null || !rawInjectionType.isPrimitive() )
-        {
-            return rawInjectionType;
-        }
-        for( int i = 0; i < primitiveTypeMapping.length; i += 2 )
-        {
-            if( primitiveTypeMapping[ i ].equals( rawInjectionType ) )
-            {
-                return primitiveTypeMapping[ i + 1 ];
-            }
-        }
-        return rawInjectionType;
-    }
-
-    public boolean hasScope( final Class<? extends Annotation> scope )
-    {
-        return scope == null || scope.equals( injectionAnnotation().annotationType() );
-    }
-
-    public Class<? extends Annotation> injectionAnnotationType()
-    {
-        if( injectionAnnotation == null )
-        {
-            return null;
-        }
-        return injectionAnnotation.annotationType();
-    }
-
-    @Override
-    public String toString()
-    {
-        return injectionAnnotation + " for " + injectionType + " in " + injectedClass.getName();
-    }
-
-    public static class ScopeSpecification
-        implements Specification<DependencyModel>
-    {
-        private final Class<? extends Annotation> scope;
-
-        public ScopeSpecification( Class<? extends Annotation> scope )
-        {
-            this.scope = scope;
-        }
-
-        @Override
-        public boolean satisfiedBy( DependencyModel model )
-        {
-            return model.hasScope( scope );
-        }
-    }
-
-    public static class InjectionTypeFunction
-        implements Function<DependencyModel, Class<?>>
-    {
-        @Override
-        public Class<?> map( DependencyModel dependencyModel )
-        {
-            return dependencyModel.rawInjectionType();
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedFieldModel.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedFieldModel.java
deleted file mode 100644
index 5412fec..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedFieldModel.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Proxy;
-import java.util.Collection;
-import org.qi4j.api.composite.InjectedFieldDescriptor;
-import org.qi4j.api.util.Classes;
-import org.qi4j.bootstrap.BindingException;
-import org.qi4j.bootstrap.InjectionException;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.composite.TransientInstance;
-import org.qi4j.runtime.model.Resolution;
-
-import static java.util.Collections.emptyList;
-import static java.util.Collections.singleton;
-
-/**
- * JAVADOC
- */
-public final class InjectedFieldModel
-    implements InjectedFieldDescriptor, VisitableHierarchy<InjectedFieldModel, DependencyModel>
-{
-    private DependencyModel dependencyModel;
-    private Field injectedField;
-
-    public InjectedFieldModel( Field injectedField, DependencyModel dependencyModel )
-    {
-        injectedField.setAccessible( true );
-        this.injectedField = injectedField;
-        this.dependencyModel = dependencyModel;
-    }
-
-    @Override
-    public DependencyModel dependency()
-    {
-        return dependencyModel;
-    }
-
-    @Override
-    public Field field()
-    {
-        return injectedField;
-    }
-
-    public void bind( Resolution resolution )
-        throws BindingException
-    {
-        dependencyModel.bind( resolution.forField( injectedField ) );
-    }
-
-    public void inject( InjectionContext context, Object instance )
-    {
-        Object value = dependencyModel.inject( context );
-        try
-        {
-            injectedField.set( instance, value );
-        }
-        catch( IllegalAccessException e )
-        {
-            throw new InjectionException( e );
-        }
-        catch( IllegalArgumentException e )
-        {
-            String valueClassName;
-            if( Proxy.isProxyClass( value.getClass() ) )
-            {
-                InvocationHandler invocationHandler = Proxy.getInvocationHandler( value );
-                if( invocationHandler instanceof TransientInstance )
-                {
-                    TransientInstance handler = (TransientInstance) invocationHandler;
-                    valueClassName = Classes.toString( handler.descriptor().types() )
-                                     + " in [" + handler.module().name() + "] of [" + handler.layer().name() + "]";
-                }
-                else
-                {
-                    valueClassName = invocationHandler.toString();
-                }
-            }
-            else
-            {
-                valueClassName = value.getClass().getName();
-            }
-            StringBuilder annotBuilder = new StringBuilder();
-            for( Annotation annot : injectedField.getAnnotations() )
-            {
-                String s = annot.toString();
-                annotBuilder.append( "@" ).append( s.substring( s.lastIndexOf( '.' ) + 1, s.length() - 2 ) );
-                annotBuilder.append( " " );
-            }
-            String annots = annotBuilder.toString();
-            String message = "Can not inject the field\n    "
-                             + injectedField.getDeclaringClass()
-                             + "\n    {\n        " + annots + "\n        "
-                             + injectedField.getType().getSimpleName() + " " + injectedField.getName()
-                             + "\n    }\nwith value \n    " + value + "\nof type\n    "
-                             + valueClassName;
-            throw new InjectionException( message, e );
-        }
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super InjectedFieldModel, ? super DependencyModel, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            visitor.visit( dependencyModel );
-        }
-        return visitor.visitLeave( this );
-    }
-
-    public Collection<DependencyModel> filter( Specification<DependencyModel> specification )
-    {
-        if( specification.satisfiedBy( dependencyModel ) )
-        {
-            return singleton( dependencyModel );
-        }
-        else
-        {
-            return emptyList();
-        }
-    }
-
-    @Override
-    public String toString()
-    {
-        return "InjectedFieldModel{" + ", injectedField=" + injectedField + '}';
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedFieldsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedFieldsModel.java
deleted file mode 100644
index dce28f2..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedFieldsModel.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Field;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.injection.InjectionScope;
-import org.qi4j.api.util.Classes;
-import org.qi4j.api.util.Fields;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.VisitableHierarchy;
-
-import static org.qi4j.api.util.Annotations.hasAnnotation;
-import static org.qi4j.api.util.Annotations.type;
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.iterable;
-import static org.qi4j.functional.Specifications.translate;
-
-/**
- * JAVADOC
- */
-public final class InjectedFieldsModel
-    implements Dependencies, VisitableHierarchy<Object, Object>
-{
-    private final List<InjectedFieldModel> fields = new ArrayList<InjectedFieldModel>();
-
-    public InjectedFieldsModel( Class fragmentClass )
-    {
-        Iterable<Field> mappedFields = Fields.FIELDS_OF.map( fragmentClass );
-        for( Field field : mappedFields )
-        {
-            Annotation injectionAnnotation = first( filter( translate( type(), hasAnnotation( InjectionScope.class ) ), iterable( field
-                                                                                                                                      .getAnnotations() ) ) );
-            if( injectionAnnotation != null )
-            {
-                addModel( fragmentClass, field, injectionAnnotation );
-            }
-        }
-    }
-
-    private void addModel( Class fragmentClass, Field field, Annotation injectionAnnotation )
-    {
-        Type genericType = field.getGenericType();
-        if( genericType instanceof ParameterizedType )
-        {
-            genericType = new ParameterizedTypeInstance( ( (ParameterizedType) genericType ).getActualTypeArguments(), ( (ParameterizedType) genericType )
-                .getRawType(), ( (ParameterizedType) genericType ).getOwnerType() );
-
-            for( int i = 0; i < ( (ParameterizedType) genericType ).getActualTypeArguments().length; i++ )
-            {
-                Type type = ( (ParameterizedType) genericType ).getActualTypeArguments()[ i ];
-                if( type instanceof TypeVariable )
-                {
-                    type = Classes.resolveTypeVariable( (TypeVariable) type, field.getDeclaringClass(), fragmentClass );
-                    ( (ParameterizedType) genericType ).getActualTypeArguments()[ i ] = type;
-                }
-            }
-        }
-
-        boolean optional = DependencyModel.isOptional( injectionAnnotation, field.getAnnotations() );
-        DependencyModel dependencyModel = new DependencyModel( injectionAnnotation, genericType, fragmentClass, optional, field
-            .getAnnotations() );
-        InjectedFieldModel injectedFieldModel = new InjectedFieldModel( field, dependencyModel );
-        this.fields.add( injectedFieldModel );
-    }
-
-    @Override
-    public Iterable<DependencyModel> dependencies()
-    {
-        return Iterables.map( new Function<InjectedFieldModel, DependencyModel>()
-        {
-            @Override
-            public DependencyModel map( InjectedFieldModel injectedFieldModel )
-            {
-                return injectedFieldModel.dependency();
-            }
-        }, fields );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
-        throws ThrowableType
-    {
-        if( modelVisitor.visitEnter( this ) )
-        {
-            for( InjectedFieldModel field : fields )
-            {
-                if( !field.accept( modelVisitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return modelVisitor.visitLeave( this );
-    }
-
-    public void inject( InjectionContext context, Object instance )
-    {
-        for( InjectedFieldModel field : fields )
-        {
-            field.inject( context, instance );
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedMethodModel.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedMethodModel.java
deleted file mode 100644
index 483f39c..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedMethodModel.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import org.qi4j.api.composite.InjectedMethodDescriptor;
-import org.qi4j.bootstrap.InjectionException;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-
-/**
- * JAVADOC
- */
-public final class InjectedMethodModel
-    implements InjectedMethodDescriptor, Dependencies, VisitableHierarchy<Object, Object>
-{
-    // Model
-    private Method method;
-    private InjectedParametersModel parameters;
-
-    public InjectedMethodModel( Method method, InjectedParametersModel parameters )
-    {
-        this.method = method;
-        this.method.setAccessible( true );
-        this.parameters = parameters;
-    }
-
-    @Override
-    public Method method()
-    {
-        return method;
-    }
-
-    @Override
-    public Iterable<DependencyModel> dependencies()
-    {
-        return parameters.dependencies();
-    }
-
-    // Context
-    public void inject( InjectionContext context, Object instance )
-        throws InjectionException
-    {
-        Object[] params = parameters.newParametersInstance( context );
-        try
-        {
-            if( !method.isAccessible() )
-            {
-                method.setAccessible( true );
-            }
-            method.invoke( instance, params );
-        }
-        catch( IllegalAccessException e )
-        {
-            throw new InjectionException( e );
-        }
-        catch( InvocationTargetException e )
-        {
-            throw new InjectionException( e.getTargetException() );
-        }
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            parameters.accept( visitor );
-        }
-        return visitor.visitLeave( this );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedMethodsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedMethodsModel.java
deleted file mode 100644
index c40dc98..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedMethodsModel.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.injection.InjectionScope;
-import org.qi4j.api.util.Annotations;
-import org.qi4j.api.util.Classes;
-import org.qi4j.api.util.Methods;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.Specifications;
-import org.qi4j.functional.VisitableHierarchy;
-
-import static org.qi4j.api.util.Annotations.hasAnnotation;
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.flattenIterables;
-import static org.qi4j.functional.Iterables.iterable;
-import static org.qi4j.functional.Iterables.map;
-
-/**
- * JAVADOC
- */
-public final class InjectedMethodsModel
-    implements Dependencies, VisitableHierarchy<Object, Object>
-{
-    // Model
-    private final List<InjectedMethodModel> methodModels = new ArrayList<InjectedMethodModel>();
-
-    public InjectedMethodsModel( Class fragmentClass )
-    {
-        nextMethod:
-        for( Method method : Methods.METHODS_OF.map( fragmentClass ) )
-        {
-            Annotation[][] parameterAnnotations = method.getParameterAnnotations();
-            if( parameterAnnotations.length > 0 )
-            {
-                InjectedParametersModel parametersModel = new InjectedParametersModel();
-                final Type[] genericParameterTypes = method.getGenericParameterTypes();
-                for( int i = 0; i < parameterAnnotations.length; i++ )
-                {
-                    Annotation injectionAnnotation = first( filter( Specifications.translate( Annotations.type(), hasAnnotation( InjectionScope.class ) ), iterable( parameterAnnotations[ i ] ) ) );
-                    if( injectionAnnotation == null )
-                    {
-                        continue nextMethod;
-                    }
-
-                    Type genericType = genericParameterTypes[ i ];
-                    if( genericType instanceof ParameterizedType )
-                    {
-                        genericType = new ParameterizedTypeInstance( ( (ParameterizedType) genericType ).getActualTypeArguments(), ( (ParameterizedType) genericType )
-                            .getRawType(), ( (ParameterizedType) genericType ).getOwnerType() );
-
-                        for( int j = 0; j < ( (ParameterizedType) genericType ).getActualTypeArguments().length; j++ )
-                        {
-                            Type type = ( (ParameterizedType) genericType ).getActualTypeArguments()[ j ];
-                            if( type instanceof TypeVariable )
-                            {
-                                type = Classes.resolveTypeVariable( (TypeVariable) type, method.getDeclaringClass(), fragmentClass );
-                                ( (ParameterizedType) genericType ).getActualTypeArguments()[ j ] = type;
-                            }
-                        }
-                    }
-
-                    boolean optional = DependencyModel.isOptional( injectionAnnotation, parameterAnnotations[ i ] );
-                    DependencyModel dependencyModel = new DependencyModel( injectionAnnotation, genericType, fragmentClass, optional, parameterAnnotations[ i ] );
-                    parametersModel.addDependency( dependencyModel );
-                }
-                InjectedMethodModel methodModel = new InjectedMethodModel( method, parametersModel );
-                methodModels.add( methodModel );
-            }
-        }
-    }
-
-    @Override
-    public Iterable<DependencyModel> dependencies()
-    {
-        return flattenIterables( map( Dependencies.DEPENDENCIES_FUNCTION, methodModels ) );
-    }
-
-    // Context
-    public void inject( InjectionContext context, Object instance )
-    {
-        for( InjectedMethodModel methodModel : methodModels )
-        {
-            methodModel.inject( context, instance );
-        }
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( InjectedMethodModel methodModel : methodModels )
-            {
-                if( !methodModel.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedParametersModel.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedParametersModel.java
deleted file mode 100644
index 1230edb..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectedParametersModel.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.qi4j.api.composite.InjectedParametersDescriptor;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.VisitableHierarchy;
-
-/**
- * JAVADOC
- */
-public final class InjectedParametersModel
-    implements InjectedParametersDescriptor, Dependencies, VisitableHierarchy<Object, Object>
-{
-    private final List<DependencyModel> parameterDependencies;
-
-    public InjectedParametersModel()
-    {
-        parameterDependencies = new ArrayList<DependencyModel>();
-    }
-
-    @Override
-    public Iterable<DependencyModel> dependencies()
-    {
-        return parameterDependencies;
-    }
-
-    // Context
-    public Object[] newParametersInstance( InjectionContext context )
-    {
-        Object[] parametersInstance = new Object[ parameterDependencies.size() ];
-
-        // Inject parameterDependencies
-        for( int j = 0; j < parameterDependencies.size(); j++ )
-        {
-            DependencyModel dependencyModel = parameterDependencies.get( j );
-            Object parameter = dependencyModel.inject( context );
-            parametersInstance[ j ] = parameter;
-        }
-
-        return parametersInstance;
-    }
-
-    public void addDependency( DependencyModel dependency )
-    {
-        parameterDependencies.add( dependency );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( DependencyModel parameterDependency : parameterDependencies )
-            {
-                if( !visitor.visit( parameterDependency ) )
-                {
-                    break;
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-
-    public Collection<DependencyModel> filter( Specification<DependencyModel> specification )
-    {
-        ArrayList<DependencyModel> result = new ArrayList<DependencyModel>();
-        for( DependencyModel model : parameterDependencies )
-        {
-            if( specification.satisfiedBy( model ) )
-            {
-                result.add( model );
-            }
-        }
-        return result;
-    }
-
-    @Override
-    public String toString()
-    {
-        return "InjectedParametersModel{" +
-               "parameterDependencies=" + parameterDependencies +
-               '}';
-    }
-}
-
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectionContext.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectionContext.java
deleted file mode 100644
index b3c4981..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectionContext.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.api.property.StateHolder;
-import org.qi4j.runtime.composite.ProxyReferenceInvocationHandler;
-import org.qi4j.runtime.composite.UsesInstance;
-import org.qi4j.runtime.structure.ModuleInstance;
-import org.qi4j.spi.module.ModuleSpi;
-
-/**
- * JAVADOC
- */
-public final class InjectionContext
-{
-    private final ModuleSpi moduleInstance;
-    private CompositeInstance compositeInstance;
-    private UsesInstance uses;
-    private StateHolder state;
-    private Object next; // Only used for concerns and side-effects
-    private ProxyReferenceInvocationHandler proxyHandler;
-    private Object instance; // Only used for inner classes
-
-    // For mixins
-
-    public InjectionContext( CompositeInstance compositeInstance, UsesInstance uses, StateHolder state )
-    {
-        this.moduleInstance = (ModuleInstance) compositeInstance.module();
-        this.compositeInstance = compositeInstance;
-        this.uses = uses;
-        this.state = state;
-    }
-
-    // For concerns and side-effects
-    public InjectionContext( ModuleSpi moduleInstance, Object next, ProxyReferenceInvocationHandler proxyHandler )
-    {
-        this.moduleInstance = moduleInstance;
-        this.next = next;
-        this.proxyHandler = proxyHandler;
-    }
-
-    public InjectionContext( ModuleSpi moduleInstance, UsesInstance uses )
-    {
-        this.moduleInstance = moduleInstance;
-        this.uses = uses;
-    }
-
-    // For inner classes
-    public InjectionContext( ModuleSpi moduleInstance, UsesInstance uses, Object instance )
-    {
-        this.moduleInstance = moduleInstance;
-        this.uses = uses;
-        this.instance = instance;
-    }
-
-    public ModuleSpi module()
-    {
-        return moduleInstance;
-    }
-
-    public CompositeInstance compositeInstance()
-    {
-        return compositeInstance;
-    }
-
-    public UsesInstance uses()
-    {
-        return uses;
-    }
-
-    public StateHolder state()
-    {
-        return state;
-    }
-
-    public Object next()
-    {
-        return next;
-    }
-
-    public Object instance()
-    {
-        return instance;
-    }
-
-    public ProxyReferenceInvocationHandler proxyHandler()
-    {
-        return proxyHandler;
-    }
-
-    public void setUses( UsesInstance uses )
-    {
-        this.uses = uses;
-    }
-
-    @Override
-    public String toString()
-    {
-        return "InjectionContext{" +
-               "compositeInstance=" + compositeInstance +
-               ", module=" + moduleInstance +
-               ", uses=" + uses +
-               ", state=" + state +
-               ", next=" + next +
-               ", proxyHandler=" + proxyHandler +
-               '}';
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectionProvider.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectionProvider.java
deleted file mode 100644
index d941ab8..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectionProvider.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import org.qi4j.runtime.injection.provider.InjectionProviderException;
-
-/**
- * JAVADOC
- */
-public interface InjectionProvider
-{
-    Object provideInjection( InjectionContext context )
-        throws InjectionProviderException;
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectionProviderFactory.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectionProviderFactory.java
deleted file mode 100644
index a594397..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/InjectionProviderFactory.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import org.qi4j.bootstrap.InvalidInjectionException;
-import org.qi4j.runtime.model.Resolution;
-
-/**
- * JAVADOC
- */
-public interface InjectionProviderFactory
-{
-    /**
-     * Binding a dependency given an injection resolution. If no binding
-     * can be found, return null. If the dependency is optional the dependency will
-     * then be explicitly set to null.
-     *
-     * @param resolution Injection resolution
-     * @param dependencyModel Dependency model
-     * @return InjectionProvider
-     * @throws InvalidInjectionException if the injection is invalid
-     */
-    InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
-        throws InvalidInjectionException;
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/ParameterizedTypeInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/ParameterizedTypeInstance.java
deleted file mode 100644
index 0fe250c..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/ParameterizedTypeInstance.java
+++ /dev/null
@@ -1,65 +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.qi4j.runtime.injection;
-
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.Arrays;
-
-/**
- * TODO
- */
-public class ParameterizedTypeInstance
-    implements ParameterizedType
-{
-    private Type[] actualTypeArguments;
-    private Type rawType;
-    private Type ownerType;
-
-    public ParameterizedTypeInstance( Type[] actualTypeArguments, Type rawType, Type ownerType )
-    {
-        this.actualTypeArguments = actualTypeArguments;
-        this.rawType = rawType;
-        this.ownerType = ownerType;
-    }
-
-    @Override
-    public Type[] getActualTypeArguments()
-    {
-        return actualTypeArguments;
-    }
-
-    @Override
-    public Type getRawType()
-    {
-        return rawType;
-    }
-
-    @Override
-    public Type getOwnerType()
-    {
-        return ownerType;
-    }
-
-    @Override
-    public String toString()
-    {
-        return rawType.toString() + Arrays.asList( actualTypeArguments );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/CachingInjectionProviderDecorator.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/CachingInjectionProviderDecorator.java
deleted file mode 100644
index ebd5a4a..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/CachingInjectionProviderDecorator.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection.provider;
-
-import org.qi4j.runtime.injection.InjectionContext;
-import org.qi4j.runtime.injection.InjectionProvider;
-
-/**
- * If a dependency resolution should be a singleton, wrap it with this
- * to provide a single instance "cache".
- */
-public final class CachingInjectionProviderDecorator
-    implements InjectionProvider
-{
-    private final InjectionProvider decoratedProvider;
-    private volatile Object singletonInstance;
-
-    public CachingInjectionProviderDecorator( InjectionProvider injectionProvider )
-    {
-        this.decoratedProvider = injectionProvider;
-    }
-
-    public InjectionProvider decoratedProvider()
-    {
-        return decoratedProvider;
-    }
-
-    @Override
-    public Object provideInjection( InjectionContext context )
-        throws InjectionProviderException
-    {
-        if( singletonInstance == null )
-        {
-            synchronized( this )
-            {
-                if( singletonInstance == null )
-                {
-                    singletonInstance = decoratedProvider.provideInjection( context );
-                }
-            }
-        }
-
-        return singletonInstance;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/CachingInjectionProviderFactoryDecorator.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/CachingInjectionProviderFactoryDecorator.java
deleted file mode 100644
index 2d00754..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/CachingInjectionProviderFactoryDecorator.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection.provider;
-
-import org.qi4j.bootstrap.InvalidInjectionException;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.runtime.injection.InjectionProvider;
-import org.qi4j.runtime.injection.InjectionProviderFactory;
-import org.qi4j.runtime.model.Resolution;
-
-/**
- * JAVADOC
- */
-public class CachingInjectionProviderFactoryDecorator
-    implements InjectionProviderFactory
-{
-    private final InjectionProviderFactory decoratedFactory;
-
-    public CachingInjectionProviderFactoryDecorator( InjectionProviderFactory decoratedFactory )
-    {
-        this.decoratedFactory = decoratedFactory;
-    }
-
-    @Override
-    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
-        throws InvalidInjectionException
-    {
-        InjectionProvider injectionProvider = decoratedFactory.newInjectionProvider( resolution, dependencyModel );
-        if( injectionProvider != null )
-        {
-            return new CachingInjectionProviderDecorator( injectionProvider );
-        }
-        else
-        {
-            return null;
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/InjectionProviderException.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/InjectionProviderException.java
deleted file mode 100644
index 740300b..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/InjectionProviderException.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection.provider;
-
-/**
- * JAVADOC
- */
-public class InjectionProviderException
-    extends RuntimeException
-{
-    public InjectionProviderException( String string )
-    {
-        super( string );
-    }
-
-    public InjectionProviderException( String string, Throwable throwable )
-    {
-        super( string, throwable );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/InjectionProviderFactoryStrategy.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/InjectionProviderFactoryStrategy.java
deleted file mode 100644
index 2db41da..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/InjectionProviderFactoryStrategy.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection.provider;
-
-import java.lang.annotation.Annotation;
-import java.util.HashMap;
-import java.util.Map;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.composite.InvalidValueCompositeException;
-import org.qi4j.api.composite.ModelDescriptor;
-import org.qi4j.api.concern.internal.ConcernFor;
-import org.qi4j.api.injection.scope.Invocation;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.State;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.sideeffect.internal.SideEffectFor;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.InvalidInjectionException;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.runtime.injection.InjectionProvider;
-import org.qi4j.runtime.injection.InjectionProviderFactory;
-import org.qi4j.runtime.model.Resolution;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * JAVADOC
- */
-public final class InjectionProviderFactoryStrategy
-    implements InjectionProviderFactory
-{
-    private final Map<Class<? extends Annotation>, InjectionProviderFactory> generalProviderFactories = new HashMap<Class<? extends Annotation>, InjectionProviderFactory>();
-    private final Map<Class<? extends Annotation>, InjectionProviderFactory> valuesProviderFactories = new HashMap<Class<? extends Annotation>, InjectionProviderFactory>();
-    private MetaInfo metaInfo;
-
-    public InjectionProviderFactoryStrategy( MetaInfo metaInfo )
-    {
-        this.metaInfo = metaInfo;
-        valuesProviderFactories.put( This.class, new ThisInjectionProviderFactory() );
-        ModifiesInjectionProviderFactory modifiesInjectionProviderFactory = new ModifiesInjectionProviderFactory();
-        valuesProviderFactories.put( ConcernFor.class, modifiesInjectionProviderFactory );
-        valuesProviderFactories.put( SideEffectFor.class, modifiesInjectionProviderFactory );
-        valuesProviderFactories.put( State.class, new StateInjectionProviderFactory() );
-
-        valuesProviderFactories.put( Structure.class, new CachingInjectionProviderFactoryDecorator( new StructureInjectionProviderFactory() ) );
-        valuesProviderFactories.put( Service.class, new CachingInjectionProviderFactoryDecorator( new ServiceInjectionProviderFactory() ) );
-        generalProviderFactories.put( Invocation.class, new InvocationInjectionProviderFactory() );
-        generalProviderFactories.put( Uses.class, new UsesInjectionProviderFactory() );
-    }
-
-    @Override
-    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
-        throws InvalidInjectionException
-    {
-        Class<? extends Annotation> injectionAnnotationType = dependencyModel.injectionAnnotation().annotationType();
-        InjectionProviderFactory factory1 = generalProviderFactories.get( injectionAnnotationType );
-        InjectionProviderFactory factory2 = valuesProviderFactories.get( injectionAnnotationType );
-        if( factory1 == null && factory2 == null )
-        {
-            InjectionProviderFactory factory = metaInfo.get( InjectionProviderFactory.class );
-            if( factory != null )
-            {
-                return factory.newInjectionProvider( resolution, dependencyModel );
-            }
-            else
-            {
-                throw new InvalidInjectionException( "Unknown injection annotation @" + injectionAnnotationType.getSimpleName() );
-            }
-        }
-        ModelDescriptor composite = resolution.model();
-        Class<?> compositeType = first( composite.types() );
-        if( factory1 != null && ValueComposite.class.isAssignableFrom( compositeType ) )
-        {
-            throw new InvalidValueCompositeException( "@" + injectionAnnotationType.getSimpleName() + " is not allowed in ValueComposites: " + compositeType );
-        }
-
-        InjectionProviderFactory factory;
-        if( factory1 == null )
-        {
-            factory = factory2;
-        }
-        else
-        {
-            factory = factory1;
-        }
-        return factory.newInjectionProvider( resolution, dependencyModel );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/InvocationInjectionProviderFactory.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/InvocationInjectionProviderFactory.java
deleted file mode 100644
index e12fd91..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/InvocationInjectionProviderFactory.java
+++ /dev/null
@@ -1,117 +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.qi4j.runtime.injection.provider;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import org.qi4j.api.util.Classes;
-import org.qi4j.bootstrap.InvalidInjectionException;
-import org.qi4j.runtime.composite.CompositeMethodModel;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.runtime.injection.InjectionContext;
-import org.qi4j.runtime.injection.InjectionProvider;
-import org.qi4j.runtime.injection.InjectionProviderFactory;
-import org.qi4j.runtime.model.Resolution;
-
-/**
- * JAVADOC
- */
-public final class InvocationInjectionProviderFactory
-    implements InjectionProviderFactory
-{
-    @Override
-    @SuppressWarnings( "raw" )
-    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
-        throws InvalidInjectionException
-    {
-        Class injectionClass = Classes.RAW_CLASS.map( dependencyModel.injectionType() );
-        if( injectionClass.equals( Method.class ) ||
-            injectionClass.equals( AnnotatedElement.class ) ||
-            injectionClass.equals( Iterable.class ) ||
-            Annotation.class.isAssignableFrom( injectionClass ) )
-        {
-            return new InvocationDependencyResolution( resolution, dependencyModel );
-        }
-        else
-        {
-            String injectedTo = dependencyModel.injectedClass().getName();
-            throw new InvalidInjectionException( "Invalid injection type " + injectionClass + " in " + injectedTo );
-        }
-    }
-
-    private static class InvocationDependencyResolution
-        implements InjectionProvider
-    {
-        private final Resolution resolution;
-        private final DependencyModel dependencyModel;
-
-        private InvocationDependencyResolution( Resolution resolution, DependencyModel dependencyModel )
-        {
-            this.resolution = resolution;
-            this.dependencyModel = dependencyModel;
-        }
-
-        @Override
-        @SuppressWarnings( {"raw", "unchecked"} )
-        public Object provideInjection( InjectionContext context )
-            throws InjectionProviderException
-        {
-            Class injectionClass = Classes.RAW_CLASS.map( dependencyModel.injectionType() );
-            final CompositeMethodModel methodModel = resolution.method();
-            if( injectionClass.equals( Method.class ) )
-            {
-                return methodModel.method();
-            }
-
-            final AnnotatedElement annotatedElement = methodModel.annotatedElement();
-            if( injectionClass.equals( AnnotatedElement.class ) )
-            {
-                return annotatedElement;
-            }
-            final Annotation annotation = annotatedElement.getAnnotation( injectionClass );
-            if( annotation != null )
-            {
-                return annotation;
-            }
-            if( dependencyModel.injectionType() instanceof Class<?> )
-            {
-                return annotatedElement.getAnnotation( (Class<Annotation>) dependencyModel.injectionType() );
-            }
-            if( dependencyModel.injectionType() instanceof ParameterizedType )
-            {
-                ParameterizedType injectionType = (ParameterizedType) dependencyModel.injectionType();
-                Type rawType = injectionType.getRawType();
-                Type[] actualTypeArguments = injectionType.getActualTypeArguments();
-                boolean isAnIterable = rawType.equals( Iterable.class );
-                boolean haveOneGenericType = actualTypeArguments.length == 1;
-                boolean thatIsOfTypeMethod = actualTypeArguments[ 0 ].equals( Method.class );
-                if( isAnIterable && haveOneGenericType && thatIsOfTypeMethod )
-                {
-                    Class<?> injectedClass = dependencyModel.injectedClass();
-                    Iterable<Method> result = methodModel.invocationsFor( injectedClass );
-                    return result;
-                }
-            }
-            return null;
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/ModifiesInjectionProviderFactory.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/ModifiesInjectionProviderFactory.java
deleted file mode 100644
index 31c4a73..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/ModifiesInjectionProviderFactory.java
+++ /dev/null
@@ -1,70 +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.qi4j.runtime.injection.provider;
-
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.util.Classes;
-import org.qi4j.bootstrap.InvalidInjectionException;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.runtime.injection.InjectionContext;
-import org.qi4j.runtime.injection.InjectionProvider;
-import org.qi4j.runtime.injection.InjectionProviderFactory;
-import org.qi4j.runtime.model.Resolution;
-
-/**
- * JAVADOC
- */
-public final class ModifiesInjectionProviderFactory
-    implements InjectionProviderFactory
-{
-    @Override
-    public InjectionProvider newInjectionProvider( Resolution bindingContext, DependencyModel dependencyModel )
-        throws InvalidInjectionException
-    {
-        if( bindingContext.model() instanceof CompositeDescriptor )
-        {
-            Class<?> type = Classes.RAW_CLASS.map( dependencyModel.injectionType() );
-            if( type.isAssignableFrom( dependencyModel.injectedClass() ) )
-            {
-                return new ModifiedInjectionProvider();
-            }
-            else
-            {
-                throw new InvalidInjectionException( "Composite " + bindingContext.model() + " does not implement @ConcernFor type " + type
-                    .getName() + " in modifier " + dependencyModel.injectedClass().getName() );
-            }
-        }
-        else
-        {
-            throw new InvalidInjectionException( "The class " + dependencyModel.injectedClass()
-                .getName() + " is not a modifier" );
-        }
-    }
-
-    private static class ModifiedInjectionProvider
-        implements InjectionProvider
-    {
-        @Override
-        public Object provideInjection( InjectionContext context )
-            throws InjectionProviderException
-        {
-            return context.next();
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/ServiceInjectionProviderFactory.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/ServiceInjectionProviderFactory.java
deleted file mode 100644
index 30c16f5..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/ServiceInjectionProviderFactory.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection.provider;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import org.qi4j.api.service.NoSuchServiceException;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.service.qualifier.Qualifier;
-import org.qi4j.api.util.Annotations;
-import org.qi4j.api.util.Classes;
-import org.qi4j.bootstrap.InvalidInjectionException;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.Specifications;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.runtime.injection.InjectionContext;
-import org.qi4j.runtime.injection.InjectionProvider;
-import org.qi4j.runtime.injection.InjectionProviderFactory;
-import org.qi4j.runtime.model.Resolution;
-
-import static org.qi4j.api.util.Annotations.hasAnnotation;
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.iterable;
-
-public final class ServiceInjectionProviderFactory
-    implements InjectionProviderFactory
-{
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
-        throws InvalidInjectionException
-    {
-        // TODO This could be changed to allow multiple @Qualifier annotations
-        Annotation qualifierAnnotation = first( filter( Specifications.translate( Annotations.type(), hasAnnotation( Qualifier.class ) ), iterable( dependencyModel
-                                                                                                                                                        .annotations() ) ) );
-        Specification<ServiceReference<?>> serviceQualifier = null;
-        if( qualifierAnnotation != null )
-        {
-            Qualifier qualifier = qualifierAnnotation.annotationType().getAnnotation( Qualifier.class );
-            try
-            {
-                serviceQualifier = qualifier.value().newInstance().qualifier( qualifierAnnotation );
-            }
-            catch( Exception e )
-            {
-                throw new InvalidInjectionException( "Could not instantiate qualifier serviceQualifier", e );
-            }
-        }
-
-        if( dependencyModel.rawInjectionType().equals( Iterable.class ) )
-        {
-            Type iterableType = ( (ParameterizedType) dependencyModel.injectionType() ).getActualTypeArguments()[ 0 ];
-            if( Classes.RAW_CLASS.map( iterableType ).equals( ServiceReference.class ) )
-            {
-                // @Service Iterable<ServiceReference<MyService<Foo>> serviceRefs
-                Type serviceType = ( (ParameterizedType) iterableType ).getActualTypeArguments()[ 0 ];
-
-                return new IterableServiceReferenceProvider( serviceType, serviceQualifier );
-            }
-            else
-            {
-                // @Service Iterable<MyService<Foo>> services
-                return new IterableServiceProvider( iterableType, serviceQualifier );
-            }
-        }
-        else if( dependencyModel.rawInjectionType().equals( ServiceReference.class ) )
-        {
-            // @Service ServiceReference<MyService<Foo>> serviceRef
-            Type referencedType = ( (ParameterizedType) dependencyModel.injectionType() ).getActualTypeArguments()[ 0 ];
-            return new ServiceReferenceProvider( referencedType, serviceQualifier );
-        }
-        else
-        {
-            // @Service MyService<Foo> service
-            return new ServiceProvider( dependencyModel.injectionType(), serviceQualifier );
-        }
-    }
-
-    private static class IterableServiceReferenceProvider
-        extends ServiceInjectionProvider
-    {
-        private IterableServiceReferenceProvider( Type serviceType,
-                                                  Specification<ServiceReference<?>> serviceQualifier
-        )
-        {
-            super( serviceType, serviceQualifier );
-        }
-
-        @Override
-        public synchronized Object provideInjection( InjectionContext context )
-            throws InjectionProviderException
-        {
-            return getServiceReferences( context );
-        }
-    }
-
-    private static class IterableServiceProvider
-        extends ServiceInjectionProvider
-        implements Function<ServiceReference<?>, Object>
-    {
-        private IterableServiceProvider( Type serviceType,
-                                         Specification<ServiceReference<?>> serviceQualifier
-        )
-        {
-            super( serviceType, serviceQualifier );
-        }
-
-        @Override
-        public synchronized Object provideInjection( final InjectionContext context )
-            throws InjectionProviderException
-        {
-            return Iterables.map( this, getServiceReferences( context ) );
-        }
-
-        @Override
-        public Object map( ServiceReference<?> objectServiceReference )
-        {
-            return objectServiceReference.get();
-        }
-    }
-
-    private static class ServiceReferenceProvider
-        extends ServiceInjectionProvider
-    {
-        ServiceReferenceProvider( Type serviceType, Specification<ServiceReference<?>> qualifier )
-        {
-            super( serviceType, qualifier );
-        }
-
-        @Override
-        public synchronized Object provideInjection( InjectionContext context )
-            throws InjectionProviderException
-        {
-            return getServiceReference( context );
-        }
-    }
-
-    private static class ServiceProvider
-        extends ServiceInjectionProvider
-    {
-        ServiceProvider( Type serviceType, Specification<ServiceReference<?>> qualifier )
-        {
-            super( serviceType, qualifier );
-        }
-
-        @Override
-        public synchronized Object provideInjection( InjectionContext context )
-            throws InjectionProviderException
-        {
-            ServiceReference<?> ref = getServiceReference( context );
-
-            if( ref != null )
-            {
-                return ref.get();
-            }
-            else
-            {
-                return null;
-            }
-        }
-    }
-
-    private abstract static class ServiceInjectionProvider
-        implements InjectionProvider
-    {
-        private final Type serviceType;
-        private final Specification<ServiceReference<?>> serviceQualifier;
-
-        private ServiceInjectionProvider( Type serviceType,
-                                            Specification<ServiceReference<?>> serviceQualifier
-        )
-        {
-            this.serviceType = serviceType;
-            this.serviceQualifier = serviceQualifier;
-        }
-
-        protected ServiceReference<Object> getServiceReference( InjectionContext context )
-        {
-            try
-            {
-                if( serviceQualifier == null )
-                {
-                    return context.module().findService( serviceType );
-                }
-                else
-                {
-                    return Iterables.first( Iterables.filter( serviceQualifier, context.module()
-                        .findServices( serviceType ) ) );
-                }
-            }
-            catch( NoSuchServiceException e )
-            {
-                return null;
-            }
-        }
-
-        protected Iterable<ServiceReference<Object>> getServiceReferences( final InjectionContext context )
-        {
-            if( serviceQualifier == null )
-            {
-                return context.module().findServices( serviceType );
-            }
-            else
-            {
-                return Iterables.filter( serviceQualifier, context.module().findServices( serviceType ) );
-            }
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/StateInjectionProviderFactory.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/StateInjectionProviderFactory.java
deleted file mode 100644
index 4cfdc1c..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/StateInjectionProviderFactory.java
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.injection.provider;
-
-import org.qi4j.api.association.AbstractAssociation;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationStateDescriptor;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.composite.StateDescriptor;
-import org.qi4j.api.composite.StatefulCompositeDescriptor;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.injection.scope.State;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.property.StateHolder;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.InvalidInjectionException;
-import org.qi4j.runtime.entity.EntityInstance;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.runtime.injection.InjectionContext;
-import org.qi4j.runtime.injection.InjectionProvider;
-import org.qi4j.runtime.injection.InjectionProviderFactory;
-import org.qi4j.runtime.model.Resolution;
-
-/**
- * JAVADOC
- */
-public final class StateInjectionProviderFactory
-    implements InjectionProviderFactory
-{
-    @Override
-    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
-        throws InvalidInjectionException
-    {
-        if( StateHolder.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
-        {
-            // @State StateHolder properties;
-            return new StateInjectionProvider();
-        }
-        else if( UnitOfWork.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
-        {
-            if( !( resolution.model() instanceof EntityDescriptor ) )
-            {
-                throw new InvalidInjectionException( "Only EntityComposites can be injected with '@State UnitOfWork'" );
-            }
-            return new UnitOfWorkInjectionProvider();
-        }
-        else if( Property.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
-        {
-            // @State Property<String> name;
-            StateDescriptor descriptor;
-            descriptor = ( (StatefulCompositeDescriptor) resolution.model() ).state();
-
-            State annotation = (State) dependencyModel.injectionAnnotation();
-            String name;
-            if( annotation.value().isEmpty() )
-            {
-                name = resolution.field().getName();
-            }
-            else
-            {
-                name = annotation.value();
-            }
-
-            PropertyDescriptor propertyDescriptor = descriptor.findPropertyModelByName( name );
-            return new PropertyInjectionProvider( propertyDescriptor );
-        }
-        else if( Association.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
-        {
-            // @State Association<MyEntity> name;
-            AssociationStateDescriptor descriptor = ( (EntityDescriptor) resolution.model() ).state();
-            State annotation = (State) dependencyModel.injectionAnnotation();
-            String name;
-            if( annotation.value().isEmpty() )
-            {
-                name = resolution.field().getName();
-            }
-            else
-            {
-                name = annotation.value();
-            }
-            AssociationDescriptor model = descriptor.getAssociationByName( name );
-            return new AssociationInjectionProvider( model );
-        }
-        else if( ManyAssociation.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
-        {
-            // @State ManyAssociation<MyEntity> name;
-            AssociationStateDescriptor descriptor = ( (EntityDescriptor) resolution.model() ).state();
-            State annotation = (State) dependencyModel.injectionAnnotation();
-            String name;
-            if( annotation.value().isEmpty() )
-            {
-                name = resolution.field().getName();
-            }
-            else
-            {
-                name = annotation.value();
-            }
-            AssociationDescriptor model = descriptor.getManyAssociationByName( name );
-            return new ManyAssociationInjectionProvider( model );
-        }
-        else if( NamedAssociation.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
-        {
-            // @State NamedAssociation<MyEntity> name;
-            AssociationStateDescriptor descriptor = ( (EntityDescriptor) resolution.model() ).state();
-            State annotation = (State) dependencyModel.injectionAnnotation();
-            String name;
-            if( annotation.value().isEmpty() )
-            {
-                name = resolution.field().getName();
-            }
-            else
-            {
-                name = annotation.value();
-            }
-            AssociationDescriptor model = descriptor.getNamedAssociationByName( name );
-            return new NamedAssociationInjectionProvider( model );
-        }
-
-        throw new InjectionProviderException( "Injected value has invalid type" );
-    }
-
-    private static class PropertyInjectionProvider
-        implements InjectionProvider
-    {
-        private final PropertyDescriptor propertyDescriptor;
-
-        private PropertyInjectionProvider( PropertyDescriptor propertyDescriptor )
-        {
-            this.propertyDescriptor = propertyDescriptor;
-        }
-
-        @Override
-        public Object provideInjection( InjectionContext context )
-            throws InjectionProviderException
-        {
-            Property<?> value = context.state().propertyFor( propertyDescriptor.accessor() );
-            if( value != null )
-            {
-                return value;
-            }
-            else
-            {
-                throw new InjectionProviderException( "Non-optional property " + propertyDescriptor + " had no value" );
-            }
-        }
-    }
-
-    private static class AssociationInjectionProvider
-        implements InjectionProvider
-    {
-        private final AssociationDescriptor associationDescriptor;
-
-        private AssociationInjectionProvider( AssociationDescriptor associationDescriptor )
-        {
-            this.associationDescriptor = associationDescriptor;
-        }
-
-        @Override
-        public Object provideInjection( InjectionContext context )
-            throws InjectionProviderException
-        {
-            AbstractAssociation abstractAssociation = ( (AssociationStateHolder) context.state() ).
-                associationFor( associationDescriptor.accessor() );
-            if( abstractAssociation != null )
-            {
-                return abstractAssociation;
-            }
-            else
-            {
-                throw new InjectionProviderException( "Non-optional association " + associationDescriptor.qualifiedName() + " had no association" );
-            }
-        }
-    }
-
-    private static class ManyAssociationInjectionProvider
-        implements InjectionProvider
-    {
-        private final AssociationDescriptor manyAssociationDescriptor;
-
-        private ManyAssociationInjectionProvider( AssociationDescriptor manyAssociationDescriptor )
-        {
-            this.manyAssociationDescriptor = manyAssociationDescriptor;
-        }
-
-        @Override
-        public Object provideInjection( InjectionContext context )
-            throws InjectionProviderException
-        {
-            ManyAssociation<?> abstractAssociation = ( (AssociationStateHolder) context.state() ).
-                manyAssociationFor( manyAssociationDescriptor.accessor() );
-            if( abstractAssociation != null )
-            {
-                return abstractAssociation;
-            }
-            else
-            {
-                throw new InjectionProviderException( "Non-optional association " + manyAssociationDescriptor.qualifiedName() + " had no association" );
-            }
-        }
-    }
-
-    private static class NamedAssociationInjectionProvider
-        implements InjectionProvider
-    {
-        private final AssociationDescriptor namedAssociationDescriptor;
-
-        private NamedAssociationInjectionProvider( AssociationDescriptor namedAssociationDescriptor )
-        {
-            this.namedAssociationDescriptor = namedAssociationDescriptor;
-        }
-
-        @Override
-        public Object provideInjection( InjectionContext context )
-            throws InjectionProviderException
-        {
-            NamedAssociation<?> abstractAssociation = ( (AssociationStateHolder) context.state() ).
-                namedAssociationFor( namedAssociationDescriptor.accessor() );
-            if( abstractAssociation != null )
-            {
-                return abstractAssociation;
-            }
-            else
-            {
-                throw new InjectionProviderException( "Non-optional association " + namedAssociationDescriptor.qualifiedName() + " had no association" );
-            }
-        }
-    }
-
-    static private class StateInjectionProvider
-        implements InjectionProvider
-    {
-        @Override
-        public Object provideInjection( InjectionContext context )
-            throws InjectionProviderException
-        {
-            return context.state();
-        }
-    }
-
-    static private class UnitOfWorkInjectionProvider
-        implements InjectionProvider
-    {
-
-        @Override
-        public Object provideInjection( InjectionContext context )
-            throws InjectionProviderException
-        {
-            return ( (EntityInstance) context.compositeInstance() ).unitOfWork();
-        }
-    }
-
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/StructureInjectionProviderFactory.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/StructureInjectionProviderFactory.java
deleted file mode 100644
index 6ad4e30..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/StructureInjectionProviderFactory.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.injection.provider;
-
-import java.lang.reflect.Type;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.composite.TransientBuilderFactory;
-import org.qi4j.api.object.ObjectFactory;
-import org.qi4j.api.query.QueryBuilderFactory;
-import org.qi4j.api.service.ServiceFinder;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Layer;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.bootstrap.InvalidInjectionException;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.runtime.injection.InjectionContext;
-import org.qi4j.runtime.injection.InjectionProvider;
-import org.qi4j.runtime.injection.InjectionProviderFactory;
-import org.qi4j.runtime.model.Resolution;
-import org.qi4j.runtime.structure.ModuleInstance;
-import org.qi4j.spi.module.ModuleSpi;
-
-public final class StructureInjectionProviderFactory
-    implements InjectionProviderFactory
-{
-    @Override
-    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
-        throws InvalidInjectionException
-    {
-        return new StructureInjectionProvider( dependencyModel );
-    }
-
-    private static class StructureInjectionProvider
-        implements InjectionProvider
-    {
-        private final DependencyModel dependencyModel;
-
-        private StructureInjectionProvider( DependencyModel dependencyModel )
-        {
-            this.dependencyModel = dependencyModel;
-        }
-
-        @Override
-        public Object provideInjection( InjectionContext context )
-            throws InjectionProviderException
-        {
-            Type type1 = dependencyModel.injectionType();
-            if( !( type1 instanceof Class ) )
-            {
-                throw new InjectionProviderException( "Type [" + type1 + "] can not be injected from the @Structure injection scope: " + context );
-            }
-            Class clazz = (Class) type1;
-            if( clazz.equals( TransientBuilderFactory.class ) )
-            {
-                return context.module();
-            }
-            else if( clazz.equals( ObjectFactory.class ) )
-            {
-                return context.module();
-            }
-            else if( clazz.equals( ValueBuilderFactory.class ) )
-            {
-                return context.module();
-            }
-            else if( clazz.equals( UnitOfWorkFactory.class ) )
-            {
-                return context.module();
-            }
-            else if( clazz.equals( QueryBuilderFactory.class ) )
-            {
-                return context.module();
-            }
-            else if( clazz.equals( ServiceFinder.class ) )
-            {
-                return context.module();
-            }
-            else if( Module.class.isAssignableFrom( clazz ) )
-            {
-                return context.module();
-            }
-            else if( ModuleSpi.class.isAssignableFrom( clazz ) )
-            {
-                return context.module();
-            }
-            else if( Layer.class.isAssignableFrom( clazz ) )
-            {
-                return (( ModuleInstance) context.module()).layerInstance();
-            }
-            else if( Application.class.isAssignableFrom( clazz ) )
-            {
-                return (( ModuleInstance) context.module()).layerInstance().applicationInstance();
-            }
-            else if( Qi4j.class.isAssignableFrom( clazz ) )
-            {
-                return (( ModuleInstance) context.module()).layerInstance().applicationInstance().runtime();
-            }
-
-            return null;
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/ThisInjectionProviderFactory.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/ThisInjectionProviderFactory.java
deleted file mode 100644
index c313330..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/ThisInjectionProviderFactory.java
+++ /dev/null
@@ -1,138 +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.qi4j.runtime.injection.provider;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Proxy;
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.util.Classes;
-import org.qi4j.bootstrap.InvalidInjectionException;
-import org.qi4j.functional.Iterables;
-import org.qi4j.runtime.composite.ProxyGenerator;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.runtime.injection.InjectionContext;
-import org.qi4j.runtime.injection.InjectionProvider;
-import org.qi4j.runtime.injection.InjectionProviderFactory;
-import org.qi4j.runtime.model.Resolution;
-
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.iterable;
-
-/**
- * JAVADOC
- */
-public final class ThisInjectionProviderFactory
-    implements InjectionProviderFactory
-{
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public InjectionProvider newInjectionProvider( Resolution bindingContext, DependencyModel dependencyModel )
-        throws InvalidInjectionException
-    {
-        if( bindingContext.model() instanceof CompositeDescriptor )
-        {
-            // If Composite type then return real type, otherwise use the specified one
-            final Class<?> thisType = dependencyModel.rawInjectionType();
-
-            Iterable<Class<?>> injectionTypes = null;
-            if( Classes.assignableTypeSpecification( thisType ).satisfiedBy( bindingContext.model() ) )
-            {
-                injectionTypes = bindingContext.model().types();
-            }
-            else
-            {
-                CompositeDescriptor acd = ( (CompositeDescriptor) bindingContext.model() );
-                for( Class<?> mixinType : acd.mixinTypes() )
-                {
-                    if( thisType.isAssignableFrom( mixinType ) )
-                    {
-                        Iterable<? extends Class<?>> iterable = iterable( thisType );
-                        injectionTypes = (Iterable<Class<?>>) iterable;
-                        break;
-                    }
-                }
-
-                if( injectionTypes == null )
-                {
-                    throw new InvalidInjectionException( "Composite " + bindingContext.model()
-                                                         + " does not implement @This type " + thisType.getName() + " in fragment "
-                                                         + dependencyModel.injectedClass().getName() );
-                }
-            }
-
-            return new ThisInjectionProvider( injectionTypes );
-        }
-        else
-        {
-            throw new InvalidInjectionException( "Object " + dependencyModel.injectedClass() + " may not use @This" );
-        }
-    }
-
-    @SuppressWarnings( {"raw", "unchecked"} )
-    private static class ThisInjectionProvider
-        implements InjectionProvider
-    {
-        Constructor proxyConstructor;
-        private Class[] interfaces;
-
-        private ThisInjectionProvider( Iterable<Class<?>> types )
-        {
-            try
-            {
-                Class proxyClass;
-                if( Proxy.class.isAssignableFrom( first( types ) ) )
-                {
-                    proxyClass = first( types );
-                }
-                else
-                {
-                    Class<?> mainType = first( types );
-                    interfaces = Iterables.toArray( Class.class, Iterables.<Class>cast( types ) );
-                    proxyClass = ProxyGenerator.createProxyClass(mainType.getClassLoader(), interfaces);
-                }
-
-                proxyConstructor = proxyClass.getConstructor( InvocationHandler.class );
-            }
-            catch( Exception e )
-            {
-                // Ignore
-                e.printStackTrace();
-            }
-        }
-
-        @Override
-        public Object provideInjection( InjectionContext context )
-        {
-            try
-            {
-                InvocationHandler handler = context.compositeInstance();
-                if( handler == null )
-                {
-                    handler = context.proxyHandler();
-                }
-                return proxyConstructor.newInstance( handler );
-            }
-            catch( Exception e )
-            {
-                throw new InjectionProviderException( "Could not instantiate @This proxy", e );
-            }
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/UsesInjectionProviderFactory.java b/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/UsesInjectionProviderFactory.java
deleted file mode 100644
index 2069d07..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/injection/provider/UsesInjectionProviderFactory.java
+++ /dev/null
@@ -1,132 +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.qi4j.runtime.injection.provider;
-
-import java.lang.reflect.Constructor;
-import org.qi4j.api.composite.NoSuchTransientException;
-import org.qi4j.api.object.NoSuchObjectException;
-import org.qi4j.api.structure.Module;
-import org.qi4j.bootstrap.InvalidInjectionException;
-import org.qi4j.runtime.composite.UsesInstance;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.runtime.injection.InjectionContext;
-import org.qi4j.runtime.injection.InjectionProvider;
-import org.qi4j.runtime.injection.InjectionProviderFactory;
-import org.qi4j.runtime.model.Resolution;
-import org.qi4j.runtime.structure.ModuleInstance;
-
-/**
- * JAVADOC
- */
-public final class UsesInjectionProviderFactory
-    implements InjectionProviderFactory
-{
-    public UsesInjectionProviderFactory()
-    {
-    }
-
-    @Override
-    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
-        throws InvalidInjectionException
-    {
-        return new UsesInjectionProvider( dependencyModel );
-    }
-
-    private static class UsesInjectionProvider
-        implements InjectionProvider
-    {
-        private final DependencyModel dependency;
-
-        public UsesInjectionProvider( DependencyModel dependency )
-        {
-            this.dependency = dependency;
-        }
-
-        @SuppressWarnings( "unchecked" )
-        @Override
-        public Object provideInjection( InjectionContext context )
-            throws InjectionProviderException
-        {
-            UsesInstance uses = context.uses();
-
-            Class injectionType = dependency.rawInjectionType();
-            Object usesObject = uses.useForType( injectionType );
-
-            if( usesObject == null && !dependency.optional() )
-            {
-                // No @Uses object provided
-                // Try instantiating a Transient or Object for the given type
-                Module moduleInstance = context.module();
-
-                try
-                {
-                    if( context.instance() != null )
-                    {
-                        uses = uses.use( context.instance() );
-                    }
-                    usesObject = moduleInstance.newTransient( injectionType, uses.toArray() );
-                }
-                catch( NoSuchTransientException e )
-                {
-                    try
-                    {
-                        usesObject = moduleInstance.newObject( injectionType, uses.toArray() );
-                    }
-                    catch( NoSuchObjectException e1 )
-                    {
-                        // Could not instantiate an instance - to try instantiate as plain class
-                        try
-                        {
-                            usesObject = injectionType.newInstance();
-                        }
-                        catch( Throwable e2 )
-                        {
-                            // Could not instantiate - try with this as first argument
-                            try
-                            {
-                                Constructor constructor = injectionType.getDeclaredConstructor( context.instance()
-                                                                                                    .getClass() );
-                                if( !constructor.isAccessible() )
-                                {
-                                    constructor.setAccessible( true );
-                                }
-                                usesObject = constructor.newInstance( context.instance() );
-                            }
-                            catch( Throwable e3 )
-                            {
-                                // Really can't instantiate it - ignore
-                            }
-                        }
-                    }
-                }
-
-                if( usesObject != null )
-                {
-                    context.setUses( context.uses().use( usesObject ) ); // Use this for other injections in same graph
-                }
-
-                return usesObject;
-            }
-            else
-            {
-                return usesObject;
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/internal/Activator.java b/core/runtime/src/main/java/org/qi4j/runtime/internal/Activator.java
deleted file mode 100644
index 6725296..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/internal/Activator.java
+++ /dev/null
@@ -1,57 +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.qi4j.runtime.internal;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-import org.qi4j.bootstrap.Qi4jRuntime;
-import org.qi4j.bootstrap.RuntimeFactory;
-import org.qi4j.runtime.Qi4jRuntimeImpl;
-
-/**
- *
- */
-public class Activator
-    implements BundleActivator
-{
-    private ServiceRegistration registration;
-
-    @Override
-    public void start( BundleContext bundleContext )
-        throws Exception
-    {
-        RuntimeFactory factory = new RuntimeFactory()
-        {
-            @Override
-            public Qi4jRuntime createRuntime()
-            {
-                return new Qi4jRuntimeImpl();
-            }
-        };
-        registration = bundleContext.registerService( RuntimeFactory.class.getName(), factory, null );
-    }
-
-    @Override
-    public void stop( BundleContext bundleContext )
-        throws Exception
-    {
-        registration.unregister();
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/model/Binder.java b/core/runtime/src/main/java/org/qi4j/runtime/model/Binder.java
deleted file mode 100644
index 1838c0d..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/model/Binder.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.model;
-
-import org.qi4j.bootstrap.BindingException;
-
-/**
- * Interface for models that can understand binding of dependencies
- */
-public interface Binder
-{
-    void bind( Resolution resolution )
-        throws BindingException;
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/model/Resolution.java b/core/runtime/src/main/java/org/qi4j/runtime/model/Resolution.java
deleted file mode 100644
index 32e485a..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/model/Resolution.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.model;
-
-import java.lang.reflect.Field;
-import org.qi4j.api.composite.ModelDescriptor;
-import org.qi4j.runtime.composite.CompositeMethodModel;
-import org.qi4j.runtime.structure.ApplicationModel;
-import org.qi4j.runtime.structure.LayerModel;
-import org.qi4j.runtime.structure.ModuleModel;
-
-/**
- * JAVADOC
- */
-public final class Resolution
-{
-    private final ApplicationModel application;
-    private final LayerModel layer;
-    private final ModuleModel module;
-    private final ModelDescriptor modelDescriptor;
-    private final CompositeMethodModel method;
-    private final Field field;
-
-    public Resolution( ApplicationModel application,
-                       LayerModel layer,
-                       ModuleModel module,
-                       ModelDescriptor modelDescriptor,
-                       CompositeMethodModel method,
-                       Field field
-    )
-    {
-        this.application = application;
-        this.layer = layer;
-        this.module = module;
-        this.modelDescriptor = modelDescriptor;
-        this.method = method;
-        this.field = field;
-    }
-
-    public ApplicationModel application()
-    {
-        return application;
-    }
-
-    public LayerModel layer()
-    {
-        return layer;
-    }
-
-    public ModuleModel module()
-    {
-        return module;
-    }
-
-    public ModelDescriptor model()
-    {
-        return modelDescriptor;
-    }
-
-    public CompositeMethodModel method()
-    {
-        return method;
-    }
-
-    public Field field()
-    {
-        return field;
-    }
-
-    public Resolution forField( final Field injectedField )
-    {
-        return new Resolution( application, layer, module, modelDescriptor, method, injectedField );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/object/ObjectModel.java b/core/runtime/src/main/java/org/qi4j/runtime/object/ObjectModel.java
deleted file mode 100644
index 8e9ab01..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/object/ObjectModel.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.object;
-
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.mixin.Initializable;
-import org.qi4j.api.mixin.InitializationException;
-import org.qi4j.api.object.ObjectDescriptor;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.composite.ConstructorsModel;
-import org.qi4j.runtime.injection.InjectedFieldsModel;
-import org.qi4j.runtime.injection.InjectedMethodsModel;
-import org.qi4j.runtime.injection.InjectionContext;
-
-import static org.qi4j.functional.Iterables.iterable;
-
-/**
- * JAVADOC
- */
-public final class ObjectModel
-    implements ObjectDescriptor, VisitableHierarchy<Object, Object>
-{
-    private final Class<?> objectType;
-    private final Visibility visibility;
-    private final MetaInfo metaInfo;
-    private final ConstructorsModel constructorsModel;
-    private final InjectedFieldsModel injectedFieldsModel;
-    private final InjectedMethodsModel injectedMethodsModel;
-
-    public ObjectModel( Class<?> objectType,
-                        Visibility visibility,
-                        MetaInfo metaInfo
-    )
-    {
-        this.objectType = objectType;
-        this.visibility = visibility;
-        this.metaInfo = metaInfo;
-
-        constructorsModel = new ConstructorsModel( objectType );
-        injectedFieldsModel = new InjectedFieldsModel( objectType );
-        injectedMethodsModel = new InjectedMethodsModel( objectType );
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public Iterable<Class<?>> types()
-    {
-        Iterable<? extends Class<?>> iterable = iterable( objectType );
-        return (Iterable<Class<?>>) iterable;
-    }
-
-    @Override
-    public Visibility visibility()
-    {
-        return visibility;
-    }
-
-    @Override
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return metaInfo.get( infoType );
-    }
-
-    @Override
-    public boolean isAssignableTo( Class<?> type )
-    {
-        return type.isAssignableFrom( objectType );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            if( constructorsModel.accept( visitor ) )
-            {
-                if( injectedFieldsModel.accept( visitor ) )
-                {
-                    injectedMethodsModel.accept( visitor );
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-
-    public Object newInstance( InjectionContext injectionContext )
-    {
-        Object instance;
-        try
-        {
-            instance = constructorsModel.newInstance( injectionContext );
-            injectionContext = new InjectionContext( injectionContext.module(), injectionContext.uses(), instance );
-            injectedFieldsModel.inject( injectionContext, instance );
-            injectedMethodsModel.inject( injectionContext, instance );
-        }
-        catch( Exception e )
-        {
-            throw new ConstructionException( "Could not instantiate " + objectType.getName(), e );
-        }
-
-        if( instance instanceof Initializable )
-        {
-            try
-            {
-                ( (Initializable) instance ).initialize();
-            }
-            catch( InitializationException e )
-            {
-                throw new ConstructionException( "Unable to initialize " + objectType, e );
-            }
-        }
-
-        return instance;
-    }
-
-    public void inject( InjectionContext injectionContext, Object instance )
-    {
-        injectedFieldsModel.inject( injectionContext, instance );
-        injectedMethodsModel.inject( injectionContext, instance );
-    }
-
-    @Override
-    public String toString()
-    {
-        return objectType.getName();
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/object/ObjectsModel.java b/core/runtime/src/main/java/org/qi4j/runtime/object/ObjectsModel.java
deleted file mode 100644
index 0176f88..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/object/ObjectsModel.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.object;
-
-import java.util.List;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-
-/**
- * JAVADOC
- */
-public class ObjectsModel
-    implements VisitableHierarchy<Object, Object>
-{
-    private final List<ObjectModel> objectModels;
-
-    public ObjectsModel( List<ObjectModel> objectModels )
-    {
-        this.objectModels = objectModels;
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( ObjectModel objectModel : objectModels )
-            {
-                if( !objectModel.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-
-    public Iterable<ObjectModel> models()
-    {
-        return objectModels;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/package.html b/core/runtime/src/main/java/org/qi4j/runtime/package.html
deleted file mode 100644
index 612d1ae..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Apache Zest™ Runtime.</h2>
-    </body>
-</html>
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/property/PropertiesModel.java b/core/runtime/src/main/java/org/qi4j/runtime/property/PropertiesModel.java
deleted file mode 100644
index 2261623..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/property/PropertiesModel.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2007-2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.property;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Member;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-
-/**
- * Base class for properties model
- */
-public class PropertiesModel
-    implements VisitableHierarchy<Object, Object>
-{
-    protected final Map<AccessibleObject, PropertyModel> mapAccessiblePropertyModel = new LinkedHashMap<>();
-
-    public PropertiesModel()
-    {
-    }
-
-    public void addProperty( PropertyModel property )
-    {
-        mapAccessiblePropertyModel.put( property.accessor(), property );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( PropertyModel propertyModel : mapAccessiblePropertyModel.values() )
-            {
-                if( !propertyModel.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-        }
-
-        return visitor.visitLeave( this );
-    }
-
-    public Iterable<PropertyModel> properties()
-    {
-        return mapAccessiblePropertyModel.values();
-    }
-
-    public PropertyModel getProperty( AccessibleObject accessor )
-    {
-        PropertyModel propertyModel = mapAccessiblePropertyModel.get( accessor );
-        if( propertyModel == null )
-        {
-            throw new IllegalArgumentException( "No property found with name: " + ( (Member) accessor ).getName() );
-        }
-
-        return propertyModel;
-    }
-
-    public PropertyModel getPropertyByName( String name )
-        throws IllegalArgumentException
-    {
-        for( PropertyModel propertyModel : mapAccessiblePropertyModel.values() )
-        {
-            if( propertyModel.qualifiedName().name().equals( name ) )
-            {
-                return propertyModel;
-            }
-        }
-        throw new IllegalArgumentException( "No property found with name: " + name );
-    }
-
-    public PropertyModel getPropertyByQualifiedName( QualifiedName name )
-        throws IllegalArgumentException
-    {
-        for( PropertyModel propertyModel : mapAccessiblePropertyModel.values() )
-        {
-            if( propertyModel.qualifiedName().equals( name ) )
-            {
-                return propertyModel;
-            }
-        }
-        throw new IllegalArgumentException( "No property found with qualified name: " + name );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/property/PropertyInfo.java b/core/runtime/src/main/java/org/qi4j/runtime/property/PropertyInfo.java
deleted file mode 100644
index b9869dc..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/property/PropertyInfo.java
+++ /dev/null
@@ -1,36 +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.qi4j.runtime.property;
-
-import java.lang.reflect.Type;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.runtime.composite.ConstraintsCheck;
-
-/**
- * TODO
- */
-public interface PropertyInfo
-    extends ConstraintsCheck
-{
-    boolean isImmutable();
-
-    QualifiedName qualifiedName();
-
-    Type type();
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/property/PropertyInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/property/PropertyInstance.java
deleted file mode 100644
index 11c1da8..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/property/PropertyInstance.java
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.property;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.property.PropertyWrapper;
-import org.qi4j.api.type.CollectionType;
-import org.qi4j.api.type.MapType;
-import org.qi4j.api.type.ValueCompositeType;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.runtime.value.ValueInstance;
-
-/**
- * {@code PropertyInstance} represents a property.
- */
-public class PropertyInstance<T>
-    implements Property<T>
-{
-    protected volatile T value;
-    protected PropertyInfo model;
-
-    /**
-     * Construct an instance of {@code PropertyInstance} with the specified arguments.
-     *
-     * @param model  The property model. This argument must not be {@code null}.
-     * @param aValue The property value.
-     */
-    public PropertyInstance( PropertyInfo model, T aValue )
-    {
-        this.model = model;
-        value = aValue;
-    }
-
-    public PropertyInfo propertyInfo()
-    {
-        return model;
-    }
-
-    /**
-     * @param model The property model. This argument must not be {@code null}.
-     */
-    public void setPropertyInfo( PropertyInfo model )
-    {
-        this.model = model;
-    }
-
-    /**
-     * Returns this property value.
-     *
-     * @return This property value.
-     */
-    @Override
-    public T get()
-    {
-        return value;
-    }
-
-    /**
-     * Sets this property value.
-     *
-     * @param aNewValue The new value.
-     */
-    @Override
-    public void set( T aNewValue )
-    {
-        if( model.isImmutable() )
-        {
-            throw new IllegalStateException( "Property [" + model.qualifiedName() + "] is immutable." );
-        }
-
-        model.checkConstraints( aNewValue );
-
-        value = aNewValue;
-    }
-
-    /**
-     * Perform equals with {@code o} argument.
-     * <p>
-     *     The definition of equals() for the Property is that if both the state and descriptor are equal,
-     *     then the properties are equal.
-     * </p>
-     *
-     * @param o The other object to compare.
-     * @return Returns a {@code boolean} indicator whether this object is equals the other.
-     */
-    @Override
-    public boolean equals( Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-
-        Property<?> that = (Property<?>) o;
-        // Unwrap if needed
-        while( that instanceof PropertyWrapper )
-        {
-            that = ( (PropertyWrapper) that ).next();
-        }
-        // Descriptor equality
-        PropertyDescriptor thatDescriptor = (PropertyDescriptor) ( (PropertyInstance) that ).propertyInfo();
-        if( !model.equals( thatDescriptor ) )
-        {
-            return false;
-        }
-        // State equality
-        T value = get();
-        if( value == null )
-        {
-            return that.get() == null;
-        }
-        return value.equals( that.get() );
-    }
-
-    /**
-     * Calculate hash code.
-     *
-     * @return the hashcode of this instance.
-     */
-    @Override
-    public int hashCode()
-    {
-        int hash = model.hashCode() * 19; // Descriptor
-        T value = get();
-        if( value != null )
-        {
-            hash += value.hashCode() * 13; // State
-        }
-        return hash;
-    }
-
-    /**
-     * Returns the value as string.
-     *
-     * @return The value as string.
-     */
-    @Override
-    public String toString()
-    {
-        Object value = get();
-        return value == null ? "" : value.toString();
-    }
-
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public void prepareToBuild( PropertyModel propertyDescriptor )
-    {
-        // Check if state has to be modified
-        model = propertyDescriptor.getBuilderInfo();
-        if( propertyDescriptor.valueType() instanceof ValueCompositeType )
-        {
-            Object value = get();
-            if( value != null )
-            {
-                ValueInstance.valueInstanceOf( (ValueComposite) value ).prepareToBuild();
-            }
-        }
-        else if( propertyDescriptor.valueType() instanceof CollectionType )
-        {
-            Object value = get();
-
-            if( value != null )
-            {
-                if( value instanceof List )
-                {
-                    value = new ArrayList( (Collection) value );
-                }
-                else if( value instanceof Set )
-                {
-                    value = new LinkedHashSet( (Collection) value );
-                }
-
-                // Check if items are Values
-                CollectionType collection = (CollectionType) propertyDescriptor.valueType();
-                if( collection.collectedType() instanceof ValueCompositeType )
-                {
-                    Collection coll = (Collection) value;
-                    for( Object instance : coll )
-                    {
-                        ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareToBuild();
-                    }
-                }
-
-                set( (T) value );
-            }
-        }
-        else if( propertyDescriptor.valueType() instanceof MapType )
-        {
-            Object value = get();
-
-            if( value != null )
-            {
-                Map map = new LinkedHashMap( (Map) value );
-
-                // Check if keys/values are Values
-                MapType mapType = (MapType) propertyDescriptor.valueType();
-                if( mapType.keyType() instanceof ValueCompositeType )
-                {
-                    for( Object instance : map.keySet() )
-                    {
-                        ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareToBuild();
-                    }
-                }
-                if( mapType.valueType() instanceof ValueCompositeType )
-                {
-                    for( Object instance : map.values() )
-                    {
-                        ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareToBuild();
-                    }
-                }
-
-                set( (T) value );
-            }
-        }
-    }
-
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public void prepareBuilderState( PropertyModel propertyDescriptor )
-    {
-        // Check if state has to be modified
-        if( propertyDescriptor.valueType() instanceof ValueCompositeType )
-        {
-            Object value = get();
-            if( value != null )
-            {
-                ValueInstance.valueInstanceOf( (ValueComposite) value ).prepareBuilderState();
-            }
-        }
-        else if( propertyDescriptor.valueType() instanceof CollectionType )
-        {
-            T value = get();
-            if( value != null )
-            {
-                if( propertyDescriptor.isImmutable() )
-                {
-                    if( value instanceof List )
-                    {
-                        value = (T) Collections.unmodifiableList( (List<? extends Object>) value );
-                    }
-                    else if( value instanceof Set )
-                    {
-                        value = (T) Collections.unmodifiableSet( (Set<? extends Object>) value );
-                    }
-                    else
-                    {
-                        value = (T) Collections.unmodifiableCollection( (Collection<? extends Object>) value );
-                    }
-
-                    this.value = value;
-                }
-
-                CollectionType collection = (CollectionType) propertyDescriptor.valueType();
-                if( collection.collectedType() instanceof ValueCompositeType )
-                {
-                    Collection coll = (Collection) value;
-                    for( Object instance : coll )
-                    {
-                        ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareBuilderState();
-                    }
-                }
-            }
-        }
-        else if( propertyDescriptor.valueType() instanceof MapType )
-        {
-            T value = get();
-
-            if( value != null )
-            {
-                MapType mapType = (MapType) propertyDescriptor.valueType();
-                if( mapType.keyType() instanceof ValueCompositeType )
-                {
-                    Map map = (Map) value;
-                    for( Object instance : map.keySet() )
-                    {
-                        ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareBuilderState();
-                    }
-                }
-                if( mapType.valueType() instanceof ValueCompositeType )
-                {
-                    Map map = (Map) value;
-                    for( Object instance : map.values() )
-                    {
-                        ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareBuilderState();
-                    }
-                }
-                if( propertyDescriptor.isImmutable() )
-                {
-                    value = (T) Collections.unmodifiableMap( (Map<?, ?>) value );
-                }
-
-                this.value = value;
-            }
-        }
-
-        model = propertyDescriptor;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/property/PropertyModel.java b/core/runtime/src/main/java/org/qi4j/runtime/property/PropertyModel.java
deleted file mode 100644
index 2e8b2ce..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/property/PropertyModel.java
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.property;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.util.List;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.constraint.ConstraintViolation;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.api.property.DefaultValues;
-import org.qi4j.api.property.GenericPropertyInfo;
-import org.qi4j.api.property.InvalidPropertyTypeException;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.type.Serialization;
-import org.qi4j.api.type.ValueCompositeType;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.api.util.Classes;
-import org.qi4j.bootstrap.BindingException;
-import org.qi4j.functional.Visitable;
-import org.qi4j.functional.Visitor;
-import org.qi4j.runtime.composite.ValueConstraintsInstance;
-import org.qi4j.runtime.model.Binder;
-import org.qi4j.runtime.model.Resolution;
-import org.qi4j.runtime.types.ValueTypeFactory;
-
-import static org.qi4j.functional.Iterables.empty;
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Model for a Property.
- *
- * <p>Equality is based on the Property accessor object (property type and name), not on the QualifiedName.</p>
- */
-public class PropertyModel
-    implements PropertyDescriptor, PropertyInfo, Binder, Visitable<PropertyModel>
-{
-    private Type type;
-
-    private transient AccessibleObject accessor; // Interface accessor
-
-    private final QualifiedName qualifiedName;
-
-    private final ValueConstraintsInstance constraints; // May be null
-
-    protected final MetaInfo metaInfo;
-
-    private final Object initialValue;
-
-    private final boolean useDefaults;
-
-    private final boolean immutable;
-
-    private ValueType valueType;
-
-    protected PropertyInfo builderInfo;
-
-    private final boolean queryable;
-
-    public PropertyModel( AccessibleObject accessor,
-                          boolean immutable,
-                          boolean useDefaults,
-                          ValueConstraintsInstance constraints,
-                          MetaInfo metaInfo,
-                          Object initialValue
-    )
-    {
-        if( accessor instanceof Method )
-        {
-            Method m = (Method) accessor;
-            if( !m.getReturnType().equals( Property.class ) )
-            {
-                throw new InvalidPropertyTypeException( accessor );
-            }
-        }
-        this.immutable = immutable;
-        this.metaInfo = metaInfo;
-        type = GenericPropertyInfo.propertyTypeOf( accessor );
-        this.accessor = accessor;
-        qualifiedName = QualifiedName.fromAccessor( accessor );
-
-        this.useDefaults = useDefaults;
-
-        this.initialValue = initialValue;
-
-        this.constraints = constraints;
-
-        final Queryable queryable = accessor.getAnnotation( Queryable.class );
-        this.queryable = queryable == null || queryable.value();
-    }
-
-    @Override
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return metaInfo.get( infoType );
-    }
-
-    public String name()
-    {
-        return qualifiedName.name();
-    }
-
-    @Override
-    public QualifiedName qualifiedName()
-    {
-        return qualifiedName;
-    }
-
-    @Override
-    public Type type()
-    {
-        return type;
-    }
-
-    @Override
-    public AccessibleObject accessor()
-    {
-        return accessor;
-    }
-
-    @Override
-    public ValueType valueType()
-    {
-        return valueType;
-    }
-
-    @Override
-    public boolean isImmutable()
-    {
-        return immutable;
-    }
-
-    public PropertyInfo getBuilderInfo()
-    {
-        return builderInfo;
-    }
-
-    @Override
-    public boolean queryable()
-    {
-        return queryable;
-    }
-
-    @Override
-    public Object initialValue( Module module )
-    {
-        // Use supplied value from assembly
-        Object value = initialValue;
-
-        // Check for @UseDefaults annotation
-        if( value == null && useDefaults )
-        {
-            if( valueType instanceof ValueCompositeType )
-            {
-                return module.newValue( (Class<?>) first( valueType().types() ) );
-            }
-            else
-            {
-                value = DefaultValues.getDefaultValueOf( type );
-            }
-        }
-
-        return value;
-    }
-
-    @Override
-    public void bind( Resolution resolution )
-        throws BindingException
-    {
-        ValueTypeFactory factory = ValueTypeFactory.instance();
-        Class<?> declaringClass = ( (Member) accessor() ).getDeclaringClass();
-        Class<?> mainType = first( resolution.model().types() );
-        Serialization.Variant variant = findVariant();
-        valueType = factory.newValueType( type(), declaringClass, mainType, resolution.layer(), resolution.module(), variant );
-        builderInfo = new BuilderPropertyInfo();
-        if( type instanceof TypeVariable )
-        {
-            type = Classes.resolveTypeVariable( (TypeVariable) type, declaringClass, mainType );
-        }
-    }
-
-    private Serialization.Variant findVariant()
-    {
-        Serialization serialization = metaInfo.get( Serialization.class );
-        Serialization.Variant variant = null;
-        if( serialization != null )
-        {
-            variant = serialization.value();
-        }
-        if( variant == null )
-        {
-            variant = Serialization.Variant.entry;
-        }
-        return variant;
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( Visitor<? super PropertyModel, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        return visitor.visit( this );
-    }
-
-    @Override
-    public void checkConstraints( Object value )
-        throws ConstraintViolationException
-    {
-        if( constraints != null )
-        {
-            List<ConstraintViolation> violations = constraints.checkConstraints( value );
-            if( !violations.isEmpty() )
-            {
-                Iterable<Class<?>> empty = empty();
-                throw new ConstraintViolationException( "<new instance>", empty, ( (Member) accessor ), violations );
-            }
-        }
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-
-        PropertyModel that = (PropertyModel) o;
-        return accessor.equals( that.accessor );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return accessor.hashCode();
-    }
-
-    @Override
-    public String toString()
-    {
-        if( accessor instanceof Field )
-        {
-            return ( (Field) accessor ).toGenericString();
-        }
-        else
-        {
-            return ( (Method) accessor ).toGenericString();
-        }
-    }
-
-    private class BuilderPropertyInfo implements PropertyInfo
-    {
-        @Override
-        public boolean isImmutable()
-        {
-            return false;
-        }
-
-        @Override
-        public QualifiedName qualifiedName()
-        {
-            return qualifiedName;
-        }
-
-        @Override
-        public Type type()
-        {
-            return type;
-        }
-
-        @Override
-        public void checkConstraints( Object value )
-            throws ConstraintViolationException
-        {
-            if( constraints != null )
-            {
-                List<ConstraintViolation> violations = constraints.checkConstraints( value );
-                if( !violations.isEmpty() )
-                {
-                    Iterable<Class<?>> empty = empty();
-                    throw new ConstraintViolationException( "<new instance>", empty, ( (Member) accessor ), violations );
-                }
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/query/IterableQuerySource.java b/core/runtime/src/main/java/org/qi4j/runtime/query/IterableQuerySource.java
deleted file mode 100644
index 09490a5..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/query/IterableQuerySource.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.query;
-
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.api.util.Classes;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.Specifications;
-import org.qi4j.spi.query.QuerySource;
-
-/**
- * JAVADOC
- */
-public class IterableQuerySource
-    implements QuerySource
-{
-    private final Iterable iterable;
-
-    /**
-     * Constructor.
-     *
-     * @param iterable iterable
-     */
-    @SuppressWarnings( "raw" )
-    IterableQuerySource( final Iterable iterable )
-    {
-        this.iterable = iterable;
-    }
-
-    @Override
-    public <T> T find( Class<T> resultType,
-                       Specification<Composite> whereClause,
-                       Iterable<OrderBy> orderBySegments,
-                       Integer firstResult,
-                       Integer maxResults,
-                       Map<String, Object> variables
-    )
-    {
-        final Iterator<T> iterator = iterator( resultType, whereClause, orderBySegments, firstResult, maxResults, variables );
-        if( iterator.hasNext() )
-        {
-            return iterator.next();
-        }
-        return null;
-    }
-
-    @Override
-    public <T> long count( Class<T> resultType,
-                           Specification<Composite> whereClause,
-                           Iterable<OrderBy> orderBySegments,
-                           Integer firstResult,
-                           Integer maxResults,
-                           Map<String, Object> variables
-    )
-    {
-        return list( resultType, whereClause, orderBySegments, firstResult, maxResults, variables ).size();
-    }
-
-    @Override
-    public <T> Iterator<T> iterator( Class<T> resultType,
-                                     Specification<Composite> whereClause,
-                                     Iterable<OrderBy> orderBySegments,
-                                     Integer firstResult,
-                                     Integer maxResults,
-                                     Map<String, Object> variables
-    )
-    {
-        return list( resultType, whereClause, orderBySegments, firstResult, maxResults, variables ).iterator();
-    }
-
-    @SuppressWarnings( {"raw", "unchecked"} )
-    private <T> List<T> list( Class<T> resultType,
-                              Specification<Composite> whereClause,
-                              Iterable<OrderBy> orderBySegments,
-                              Integer firstResult,
-                              Integer maxResults,
-                              Map<String, Object> variables
-    )
-    {
-        // Ensure it's a list first
-        List<T> list = filter( resultType, whereClause );
-
-        // Order list
-        if( orderBySegments != null )
-        {
-            // Sort it
-            Collections.sort( list, new OrderByComparator( orderBySegments ) );
-        }
-
-        // Cut results
-        if( firstResult != null )
-        {
-            if( firstResult > list.size() )
-            {
-                return Collections.emptyList();
-            }
-
-            int toIdx;
-            if( maxResults != null )
-            {
-                toIdx = Math.min( firstResult + maxResults, list.size() );
-            }
-            else
-            {
-                toIdx = list.size();
-            }
-
-            list = list.subList( firstResult, toIdx );
-        }
-        else
-        {
-            int toIdx;
-            if( maxResults != null )
-            {
-                toIdx = Math.min( maxResults, list.size() );
-            }
-            else
-            {
-                toIdx = list.size();
-            }
-
-            list = list.subList( 0, toIdx );
-        }
-
-        return list;
-    }
-
-    @SuppressWarnings( {"raw", "unchecked"} )
-    private <T> List<T> filter( Class<T> resultType, Specification whereClause )
-    {
-        if( whereClause == null )
-        {
-            return Iterables.toList( Iterables.filter( Classes.instanceOf( resultType ), iterable ) );
-        }
-        else
-        {
-            return Iterables.toList( Iterables.filter( Specifications.and( Classes.instanceOf( resultType ), whereClause ), iterable ) );
-        }
-    }
-
-    @Override
-    public String toString()
-    {
-        return "IterableQuerySource{" + iterable + '}';
-    }
-
-    private static class OrderByComparator<T extends Composite>
-        implements Comparator<T>
-    {
-
-        private final Iterable<OrderBy> orderBySegments;
-
-        private OrderByComparator( Iterable<OrderBy> orderBySegments )
-        {
-            this.orderBySegments = orderBySegments;
-        }
-
-        @Override
-        @SuppressWarnings( {"raw", "unchecked"} )
-        public int compare( T o1, T o2 )
-        {
-            for( OrderBy orderBySegment : orderBySegments )
-            {
-                try
-                {
-                    final Property prop1 = orderBySegment.property().map( o1 );
-                    final Property prop2 = orderBySegment.property().map( o2 );
-                    if( prop1 == null || prop2 == null )
-                    {
-                        if( prop1 == null && prop2 == null )
-                        {
-                            return 0;
-                        }
-                        else if( prop1 != null )
-                        {
-                            return 1;
-                        }
-                        return -1;
-                    }
-                    final Object value1 = prop1.get();
-                    final Object value2 = prop2.get();
-                    if( value1 == null || value2 == null )
-                    {
-                        if( value1 == null && value2 == null )
-                        {
-                            return 0;
-                        }
-                        else if( value1 != null )
-                        {
-                            return 1;
-                        }
-                        return -1;
-                    }
-                    if( value1 instanceof Comparable )
-                    {
-                        int result = ( (Comparable) value1 ).compareTo( value2 );
-                        if( result != 0 )
-                        {
-                            if( orderBySegment.order() == OrderBy.Order.ASCENDING )
-                            {
-                                return result;
-                            }
-                            else
-                            {
-                                return -result;
-                            }
-                        }
-                    }
-                }
-                catch( Exception e )
-                {
-                    return 0;
-                }
-            }
-
-            return 0;
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/query/QueryBuilderFactoryImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/query/QueryBuilderFactoryImpl.java
deleted file mode 100644
index a21e33d..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/query/QueryBuilderFactoryImpl.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2007-2009 Niclas Hedhman.
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.runtime.query;
-
-import org.qi4j.api.query.NotQueryableException;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.QueryBuilderFactory;
-import org.qi4j.api.service.NoSuchServiceException;
-import org.qi4j.api.service.ServiceFinder;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.spi.query.EntityFinder;
-
-/**
- * Default implementation of {@link QueryBuilderFactory}
- */
-public final class QueryBuilderFactoryImpl
-    implements QueryBuilderFactory
-{
-    private ServiceFinder finder;
-
-    /**
-     * Constructor.
-     *
-     * @param finder The ServiceFinder of the Module this QueryBuilderFactory belongs to.
-     */
-    public QueryBuilderFactoryImpl( ServiceFinder finder )
-    {
-        NullArgumentException.validateNotNull( "ServiceFinder", finder );
-        this.finder = finder;
-    }
-
-    /**
-     * @see QueryBuilderFactory#newQueryBuilder(Class)
-     */
-    @Override
-    public <T> QueryBuilder<T> newQueryBuilder( final Class<T> resultType )
-    {
-        NotQueryableException.throwIfNotQueryable( resultType );
-
-        final ServiceReference<EntityFinder> serviceReference;
-        try
-        {
-            serviceReference = finder.findService( EntityFinder.class );
-            return new QueryBuilderImpl<T>( serviceReference.get(), resultType, null );
-        }
-        catch( NoSuchServiceException e )
-        {
-            return new QueryBuilderImpl<T>( null, resultType, null );
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/query/QueryBuilderImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/query/QueryBuilderImpl.java
deleted file mode 100644
index bef28c5..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/query/QueryBuilderImpl.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2007-2009 Niclas Hedhman.
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.runtime.query;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.QueryExpressions;
-import org.qi4j.functional.Specification;
-import org.qi4j.spi.query.EntityFinder;
-import org.qi4j.spi.query.QueryBuilderSPI;
-import org.qi4j.spi.query.QuerySource;
-
-/**
- * Default implementation of {@link QueryBuilder}
- */
-final class QueryBuilderImpl<T>
-    implements QueryBuilder<T>, QueryBuilderSPI<T>
-{
-
-    /**
-     * Entity finder to be used to locate entities.
-     */
-    private final EntityFinder entityFinder;
-
-    /**
-     * Type of queried entities.
-     */
-    private final Class<T> resultType;
-    /**
-     * Where clause.
-     */
-    private final Specification<Composite> whereClause;
-
-    /**
-     * Constructor.
-     *
-     * @param entityFinder entity finder to be used to locate entities; canot be null
-     * @param resultType   type of queried entities; cannot be null
-     * @param whereClause  current where-clause
-     */
-    QueryBuilderImpl( final EntityFinder entityFinder,
-                      final Class<T> resultType,
-                      final Specification<Composite> whereClause
-    )
-    {
-        this.entityFinder = entityFinder;
-        this.resultType = resultType;
-        this.whereClause = whereClause;
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public QueryBuilder<T> where( Specification<Composite> specification )
-    {
-        if( specification == null )
-        {
-            throw new IllegalArgumentException( "Where clause cannot be null" );
-        }
-        if( this.whereClause != null )
-        {
-            specification = QueryExpressions.and( this.whereClause, specification );
-        }
-        return new QueryBuilderImpl<>( entityFinder, resultType, specification );
-    }
-
-    @Override
-    public Query<T> newQuery( Iterable<T> iterable )
-    {
-        return new QueryImpl<>( resultType, whereClause, new IterableQuerySource( iterable ) );
-    }
-
-    // SPI
-    @Override
-    public Query<T> newQuery( QuerySource querySource )
-    {
-        return new QueryImpl<>( resultType, whereClause, querySource );
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/query/QueryImpl.java b/core/runtime/src/main/java/org/qi4j/runtime/query/QueryImpl.java
deleted file mode 100644
index 7048990..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/query/QueryImpl.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright 2007 Niclas Hedhman.
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.runtime.query;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryExecutionException;
-import org.qi4j.api.query.QueryExpressions;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.spi.query.QuerySource;
-
-/**
- * Default implementation of {@link org.qi4j.api.query.Query}.
- */
-/* package */ class QueryImpl<T>
-    implements Query<T>
-{
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * Type of queried entities.
-     */
-    private final Class<T> resultType;
-    /**
-     * Where clause.
-     */
-    private final Specification<Composite> whereClause;
-    private QuerySource querySource;
-    /**
-     * Order by clause segments.
-     */
-    private Iterable<OrderBy> orderBySegments;
-    /**
-     * First result to be returned.
-     */
-    private Integer firstResult;
-    /**
-     * Maximum number of results to be returned.
-     */
-    private Integer maxResults;
-    /**
-     * Mapping between variable name and variable values.
-     */
-    private Map<String, Object> variables;
-
-    /**
-     * Constructor.
-     *
-     * @param resultType  type of queried entities; cannot be null
-     * @param whereClause where clause
-     */
-    /* package */ QueryImpl( final Class<T> resultType,
-               final Specification<Composite> whereClause,
-               final QuerySource querySource
-    )
-    {
-        this.resultType = resultType;
-        this.whereClause = whereClause;
-        this.querySource = querySource;
-    }
-
-    /**
-     * @see org.qi4j.api.query.Query#orderBy(org.qi4j.api.query.grammar.OrderBy[])
-     */
-    @Override
-    public Query<T> orderBy( final OrderBy... segments )
-    {
-        orderBySegments = Iterables.iterable( segments );
-        return this;
-    }
-
-    /**
-     * @see org.qi4j.api.query.Query#orderBy(org.qi4j.api.property.Property, org.qi4j.api.query.grammar.OrderBy.Order)
-     */
-    @Override
-    public Query<T> orderBy( Property<?> property, OrderBy.Order order )
-    {
-        if( orderBySegments == null )
-        {
-            orderBySegments = Iterables.iterable( new OrderBy( QueryExpressions.property( property ), order ) );
-        }
-        else
-        {
-            orderBySegments = Iterables.append( new OrderBy( QueryExpressions.property( property ), order ), orderBySegments );
-        }
-        return this;
-    }
-
-    /**
-     * @see org.qi4j.api.query.Query#orderBy(org.qi4j.api.property.Property)
-     */
-    @Override
-    public Query<T> orderBy( Property<?> property )
-    {
-        orderBy( property, OrderBy.Order.ASCENDING );
-        return this;
-    }
-
-    /**
-     * @see org.qi4j.api.query.Query#firstResult(int)
-     */
-    @Override
-    public Query<T> firstResult( int firstResult )
-    {
-        this.firstResult = firstResult;
-        return this;
-    }
-
-    /**
-     * @see org.qi4j.api.query.Query#maxResults(int)
-     */
-    @Override
-    public Query<T> maxResults( int maxResults )
-    {
-        this.maxResults = maxResults;
-        return this;
-    }
-
-    /**
-     * @see org.qi4j.api.query.Query#setVariable(String, Object)
-     */
-    @SuppressWarnings( "unchecked" )
-    @Override
-    public Query<T> setVariable( final String name, final Object value )
-    {
-        if( variables == null )
-        {
-            variables = new HashMap<String, Object>();
-        }
-        variables.put( name, value );
-
-        return this;
-    }
-
-    /**
-     * @see org.qi4j.api.query.Query#getVariable(String)
-     */
-    @SuppressWarnings( "unchecked" )
-    @Override
-    public <V> V getVariable( final String name )
-    {
-        if( variables == null )
-        {
-            return null;
-        }
-        else
-        {
-            return (V) variables.get( name );
-        }
-    }
-
-    @Override
-    public Class<T> resultType()
-    {
-        return resultType;
-    }
-
-    @Override
-    public T find()
-        throws QueryExecutionException
-    {
-        return querySource.find( resultType, whereClause, orderBySegments, firstResult, maxResults, variables );
-    }
-
-    @Override
-    public long count()
-        throws QueryExecutionException
-    {
-        return querySource.count( resultType, whereClause, orderBySegments, firstResult, maxResults, variables );
-    }
-
-    @Override
-    public Iterator<T> iterator()
-    {
-        return querySource.iterator( resultType, whereClause, orderBySegments, firstResult, maxResults, variables );
-    }
-
-    @Override
-    public String toString()
-    {
-        return "Query{" +
-               " FROM " + querySource +
-               " WHERE " + whereClause +
-               ( orderBySegments != null ? " ORDER BY " + orderBySegments : "" ) +
-               ( firstResult != null ? " FIRST " + firstResult : "" ) +
-               ( maxResults != null ? " MAX " + maxResults : "" ) +
-               " EXPECT " + resultType +
-               ( variables != null ? " WITH VARIABLES " + variables : "" ) +
-               '}';
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/service/ImportedServiceInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/service/ImportedServiceInstance.java
deleted file mode 100644
index 5533bb4..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/service/ImportedServiceInstance.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.service;
-
-import org.qi4j.api.activation.Activation;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.activation.PassivationException;
-import org.qi4j.api.service.ServiceImporter;
-
-/**
- * JAVADOC
- */
-public final class ImportedServiceInstance<T>
-    implements Activation
-{
-    private final T instance;
-    private final ServiceImporter<T> importer;
-
-    public ImportedServiceInstance( T instance, ServiceImporter<T> importer )
-    {
-        this.importer = importer;
-        this.instance = instance;
-    }
-
-    public T instance()
-    {
-        return instance;
-    }
-
-    public ServiceImporter importer()
-    {
-        return importer;
-    }
-
-    public boolean isAvailable()
-    {
-        return importer.isAvailable( instance );
-    }
-
-    @Override
-    public void activate()
-        throws ActivationException
-    {
-        // NOOP
-    }
-
-    @Override
-    public void passivate()
-        throws PassivationException
-    {
-        // NOOP
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/service/ImportedServiceModel.java b/core/runtime/src/main/java/org/qi4j/runtime/service/ImportedServiceModel.java
deleted file mode 100644
index 5f95934..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/service/ImportedServiceModel.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.service;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Proxy;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.service.ServiceImporterException;
-import org.qi4j.api.structure.Module;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.activation.ActivatorsInstance;
-import org.qi4j.runtime.activation.ActivatorsModel;
-
-import static org.qi4j.functional.Iterables.iterable;
-
-/**
- * JAVADOC
- */
-public final class ImportedServiceModel
-    implements ImportedServiceDescriptor, VisitableHierarchy<Object, Object>
-{
-    private final Class<?> type;
-    private final Visibility visibility;
-    @SuppressWarnings( "raw" )
-    private final Class<? extends ServiceImporter> serviceImporter;
-    private final String identity;
-    private final boolean importOnStartup;
-    private final MetaInfo metaInfo;
-    private final ActivatorsModel<?> activatorsModel;
-    private final String moduleName;
-
-    @SuppressWarnings( "raw" )
-    public ImportedServiceModel( Class serviceType,
-                                 Visibility visibility,
-                                 Class<? extends ServiceImporter> serviceImporter,
-                                 String identity,
-                                 boolean importOnStartup,
-                                 MetaInfo metaInfo,
-                                 ActivatorsModel<?> activatorsModel,
-                                 String moduleName
-    )
-    {
-        type = serviceType;
-        this.visibility = visibility;
-        this.serviceImporter = serviceImporter;
-        this.identity = identity;
-        this.importOnStartup = importOnStartup;
-        this.metaInfo = metaInfo;
-        this.activatorsModel = activatorsModel;
-        this.moduleName = moduleName;
-    }
-
-    public boolean isImportOnStartup()
-    {
-        return importOnStartup;
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public Iterable<Class<?>> types()
-    {
-        Iterable<? extends Class<?>> iterable = iterable( type );
-        return (Iterable<Class<?>>) iterable;
-    }
-
-    @Override
-    public Visibility visibility()
-    {
-        return visibility;
-    }
-
-    @Override
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return metaInfo.get( infoType );
-    }
-
-    @Override
-    @SuppressWarnings( "raw" )
-    public Class<? extends ServiceImporter> serviceImporter()
-    {
-        return serviceImporter;
-    }
-
-    @Override
-    public Class<?> type()
-    {
-        return type;
-    }
-
-    @Override
-    public String identity()
-    {
-        return identity;
-    }
-
-    public String moduleName()
-    {
-        return moduleName;
-    }
-
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public ActivatorsInstance<?> newActivatorsInstance( Module module )
-        throws Exception
-    {
-        return new ActivatorsInstance( activatorsModel.newInstances( module ) );
-    }
-
-    @Override
-    public boolean isAssignableTo( Class<?> type )
-    {
-        return this.type.isAssignableFrom( type );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            activatorsModel.accept( visitor );
-        }
-        return visitor.visitLeave( this );
-    }
-
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public <T> ImportedServiceInstance<T> importInstance( Module module )
-    {
-        ServiceImporter importer = module.newObject( serviceImporter );
-        try
-        {
-            T instance = (T) importer.importService( this );
-            return new ImportedServiceInstance<>( instance, importer );
-        }
-        catch( ServiceImporterException e )
-        {
-            throw e;
-        }
-        catch( Exception e )
-        {
-            throw new ServiceImporterException( "Could not import service " + identity, e );
-        }
-    }
-
-    @SuppressWarnings( "raw" )
-    public Object newProxy( InvocationHandler serviceInvocationHandler )
-    {
-        if( type.isInterface() )
-        {
-            return Proxy.newProxyInstance( type.getClassLoader(),
-                                           new Class[]{ type },
-                                           serviceInvocationHandler );
-        }
-        else
-        {
-            Class[] interfaces = type.getInterfaces();
-            return Proxy.newProxyInstance( type.getClassLoader(),
-                                           interfaces,
-                                           serviceInvocationHandler );
-        }
-    }
-
-    @Override
-    public String toString()
-    {
-        return type.getName() + ":" + identity;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/service/ImportedServiceReferenceInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/service/ImportedServiceReferenceInstance.java
deleted file mode 100644
index 15f65cd..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/service/ImportedServiceReferenceInstance.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.service;
-
-import org.qi4j.api.activation.Activation;
-import org.qi4j.api.activation.ActivationEventListener;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.activation.PassivationException;
-import org.qi4j.api.service.ServiceImporterException;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.service.ServiceUnavailableException;
-import org.qi4j.api.structure.Module;
-import org.qi4j.runtime.activation.ActivationDelegate;
-
-/**
- * Implementation of ServiceReference. This manages the reference to the imported service.
- * <p>
- * Whenever the service is requested it is returned directly to the client. That means that
- * to handle service passivation and unavailability correctly, any proxying must be done in the
- * service importer.
- * </p>
- * @param <T> Service Type
- */
-public final class ImportedServiceReferenceInstance<T>
-    implements ServiceReference<T>, Activation
-{
-    private volatile ImportedServiceInstance<T> serviceInstance;
-    private T instance;
-    private final Module module;
-    private final ImportedServiceModel serviceModel;
-    private final ActivationDelegate activation = new ActivationDelegate( this );
-    private boolean active = false;
-
-    public ImportedServiceReferenceInstance( ImportedServiceModel serviceModel, Module module )
-    {
-        this.module = module;
-        this.serviceModel = serviceModel;
-    }
-
-    @Override
-    public String identity()
-    {
-        return serviceModel.identity();
-    }
-
-    @Override
-    public Iterable<Class<?>> types()
-    {
-        return serviceModel.types();
-    }
-
-    @Override
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return serviceModel.metaInfo( infoType );
-    }
-
-    @Override
-    public synchronized T get()
-    {
-        return getInstance();
-    }
-
-    public ImportedServiceModel serviceDescriptor()
-    {
-        return serviceModel;
-    }
-
-    @Override
-    public void activate()
-        throws ActivationException
-    {
-        if( serviceModel.isImportOnStartup() )
-        {
-            getInstance();
-        }
-    }
-
-    @Override
-    public void passivate()
-        throws PassivationException
-    {
-        if( serviceInstance != null )
-        {
-            try
-            {
-                activation.passivate( new Runnable()
-                {
-                    @Override
-                    public void run()
-                    {
-                        active = false;
-                    }
-                } );
-            }
-            finally
-            {
-                serviceInstance = null;
-                active = false;
-            }
-        }
-    }
-
-    @Override
-    public boolean isActive()
-    {
-        return active;
-    }
-
-    @Override
-    public boolean isAvailable()
-    {
-        try
-        {
-            getInstance();
-            return serviceInstance.isAvailable();
-        }
-        catch( ServiceImporterException ex )
-        {
-            return false;
-        }
-    }
-
-    public Module module()
-    {
-        return module;
-    }
-
-    private T getInstance()
-        throws ServiceImporterException
-    {
-        // DCL that works with Java 1.5 volatile semantics
-        if( serviceInstance == null )
-        {
-            synchronized( this )
-            {
-                if( serviceInstance == null )
-                {
-                    serviceInstance = serviceModel.<T>importInstance( module );
-                    instance = serviceInstance.instance();
-
-                    try
-                    {
-                        activation.activate( serviceModel.newActivatorsInstance( module ), serviceInstance, new Runnable()
-                        {
-                            @Override
-                            public void run()
-                            {
-                                active = true;
-                            }
-                        } );
-                    }
-                    catch( Exception e )
-                    {
-                        serviceInstance = null;
-                        throw new ServiceUnavailableException( "Could not activate service " + serviceModel.identity(), e );
-                    }
-                }
-            }
-        }
-
-        return instance;
-    }
-
-    @Override
-    public String toString()
-    {
-        return serviceModel.identity() + ", active=" + isActive() + ", module='" + serviceModel.moduleName() + "'";
-    }
-
-    @Override
-    public void registerActivationEventListener( ActivationEventListener listener )
-    {
-        activation.registerActivationEventListener( listener );
-    }
-
-    @Override
-    public void deregisterActivationEventListener( ActivationEventListener listener )
-    {
-        activation.deregisterActivationEventListener( listener );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return identity().hashCode();
-    }
-
-    @Override
-    public boolean equals( Object obj )
-    {
-        if( obj == null )
-        {
-            return false;
-        }
-        if( getClass() != obj.getClass() )
-        {
-            return false;
-        }
-        final ServiceReference other = (ServiceReference) obj;
-        return identity().equals( other.identity() );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/service/ImportedServicesInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/service/ImportedServicesInstance.java
deleted file mode 100644
index 211dfad..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/service/ImportedServicesInstance.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.service;
-
-import java.util.List;
-import org.qi4j.api.activation.Activation;
-import org.qi4j.api.activation.ActivationEventListener;
-import org.qi4j.api.activation.ActivationEventListenerRegistration;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.activation.PassivationException;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.runtime.activation.ActivationDelegate;
-import org.qi4j.runtime.activation.ActivatorsInstance;
-
-import static org.qi4j.api.util.Classes.instanceOf;
-import static org.qi4j.functional.Iterables.filter;
-
-/**
- * JAVADOC
- */
-public class ImportedServicesInstance
-    implements Activation, ActivationEventListenerRegistration
-{
-    private final ImportedServicesModel servicesModel;
-    private final List<ServiceReference> serviceReferences;
-    private final ActivationDelegate activation = new ActivationDelegate( this, false );
-
-    public ImportedServicesInstance( ImportedServicesModel servicesModel,
-                                     List<ServiceReference> serviceReferences
-    )
-    {
-        this.servicesModel = servicesModel;
-        this.serviceReferences = serviceReferences;
-        for( ServiceReference serviceReference : serviceReferences )
-        {
-            serviceReference.registerActivationEventListener( activation );
-        }
-    }
-
-    @Override
-    public void activate()
-        throws ActivationException
-    {
-        Iterable<Activation> activatees = Iterables.<Activation>cast( filter( instanceOf( Activation.class ), serviceReferences ) );
-        activation.activate( ActivatorsInstance.EMPTY, activatees );
-    }
-
-    @Override
-    public void passivate()
-        throws PassivationException
-    {
-        activation.passivate();
-    }
-
-    public Iterable<ServiceReference> visibleServices( final Visibility visibility )
-    {
-        return Iterables.filter( new Specification<ServiceReference>()
-        {
-            @Override
-            public boolean satisfiedBy( ServiceReference item )
-            {
-                return ( (ImportedServiceReferenceInstance) item ).serviceDescriptor()
-                    .visibility()
-                    .ordinal() >= visibility.ordinal();
-            }
-        }, serviceReferences );
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder( "Services{" );
-        String sep = " ";
-        for( ServiceReference serviceReference : serviceReferences )
-        {
-            sb.append( sep ).
-                append( serviceReference.identity() ).
-                append( "(active=" ).append( serviceReference.isActive() ).append( ")" );
-            sep = ", ";
-        }
-        return sb.append( " }" ).toString();
-    }
-
-    @Override
-    public void registerActivationEventListener( ActivationEventListener listener )
-    {
-        activation.registerActivationEventListener( listener );
-    }
-
-    @Override
-    public void deregisterActivationEventListener( ActivationEventListener listener )
-    {
-        activation.deregisterActivationEventListener( listener );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/service/ImportedServicesModel.java b/core/runtime/src/main/java/org/qi4j/runtime/service/ImportedServicesModel.java
deleted file mode 100644
index a47529e..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/service/ImportedServicesModel.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.service;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.structure.ModuleInstance;
-
-/**
- * JAVADOC
- */
-public class ImportedServicesModel
-    implements VisitableHierarchy<Object, Object>
-{
-    private List<ImportedServiceModel> importedServiceModels;
-
-    public ImportedServicesModel( List<ImportedServiceModel> importedServiceModels )
-    {
-        this.importedServiceModels = importedServiceModels;
-    }
-
-    public ImportedServicesInstance newInstance( ModuleInstance module )
-    {
-        List<ServiceReference> serviceReferences = new ArrayList<ServiceReference>();
-        for( ImportedServiceModel serviceModel : importedServiceModels )
-        {
-            ImportedServiceReferenceInstance serviceReferenceInstance = new ImportedServiceReferenceInstance( serviceModel, module );
-            serviceReferences.add( serviceReferenceInstance );
-        }
-
-        return new ImportedServicesInstance( this, serviceReferences );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( ImportedServiceModel importedServiceModel : importedServiceModels )
-            {
-                if( !importedServiceModel.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/service/ServiceInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/service/ServiceInstance.java
deleted file mode 100644
index 2bbb462..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/service/ServiceInstance.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.service;
-
-import java.lang.reflect.Proxy;
-import org.qi4j.api.activation.Activation;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.activation.PassivationException;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.configuration.Enabled;
-import org.qi4j.api.service.Availability;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.util.Classes;
-import org.qi4j.runtime.composite.TransientInstance;
-import org.qi4j.runtime.composite.TransientStateInstance;
-import org.qi4j.runtime.structure.ModuleInstance;
-
-/**
- * JAVADOC
- */
-public class ServiceInstance
-    extends TransientInstance
-    implements Activation
-{
-    public static TransientInstance serviceInstanceOf( ServiceComposite composite )
-    {
-        return (TransientInstance) Proxy.getInvocationHandler( composite );
-    }
-
-    private final boolean implementsServiceAvailable;
-    private final boolean hasEnabledConfiguration;
-
-    public ServiceInstance( ServiceModel compositeModel,
-                            ModuleInstance moduleInstance,
-                            Object[] mixins,
-                            TransientStateInstance state
-    )
-    {
-        super( compositeModel, moduleInstance, mixins, state );
-
-        implementsServiceAvailable =
-            Classes.assignableTypeSpecification( Availability.class ).satisfiedBy( descriptor() );
-        hasEnabledConfiguration = compositeModel.configurationType() != null
-                                  && Enabled.class.isAssignableFrom( compositeModel.configurationType() );
-    }
-
-    @Override
-    public void activate()
-        throws ActivationException
-    {
-        // NOOP
-    }
-
-    @Override
-    public void passivate()
-        throws PassivationException
-    {
-        // NOOP
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public boolean isAvailable()
-    {
-        // Check Enabled in configuration first
-        if( hasEnabledConfiguration && !( (Configuration<Enabled>) proxy() ).get().enabled().get() )
-        {
-            return false;
-        }
-
-        // Ask service if it's available
-        return !implementsServiceAvailable || ( (Availability) proxy() ).isAvailable();
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/service/ServiceModel.java b/core/runtime/src/main/java/org/qi4j/runtime/service/ServiceModel.java
deleted file mode 100644
index ec029d1..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/service/ServiceModel.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.service;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.util.HashMap;
-import java.util.Map;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.util.Classes;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.Specifications;
-import org.qi4j.runtime.activation.ActivatorsInstance;
-import org.qi4j.runtime.activation.ActivatorsModel;
-import org.qi4j.runtime.composite.CompositeMethodsModel;
-import org.qi4j.runtime.composite.CompositeModel;
-import org.qi4j.runtime.composite.MixinModel;
-import org.qi4j.runtime.composite.MixinsModel;
-import org.qi4j.runtime.composite.StateModel;
-import org.qi4j.runtime.composite.TransientStateInstance;
-import org.qi4j.runtime.composite.UsesInstance;
-import org.qi4j.runtime.injection.DependencyModel;
-import org.qi4j.runtime.injection.InjectionContext;
-import org.qi4j.runtime.property.PropertyInstance;
-import org.qi4j.runtime.property.PropertyModel;
-import org.qi4j.runtime.structure.ModuleInstance;
-
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Specifications.and;
-import static org.qi4j.functional.Specifications.translate;
-
-/**
- * JAVADOC
- */
-public final class ServiceModel extends CompositeModel
-    implements ServiceDescriptor
-{
-    private static Method identityMethod;
-
-    static
-    {
-        try
-        {
-            identityMethod = Identity.class.getMethod( "identity" );
-        }
-        catch( NoSuchMethodException e )
-        {
-            e.printStackTrace();
-        }
-    }
-
-    private final String identity;
-    private final boolean instantiateOnStartup;
-    private final ActivatorsModel<?> activatorsModel;
-    @SuppressWarnings( "raw" )
-    private final Class configurationType;
-
-    public ServiceModel( Iterable<Class<?>> types,
-                         Visibility visibility,
-                         MetaInfo metaInfo,
-                         ActivatorsModel<?> activatorsModel,
-                         MixinsModel mixinsModel,
-                         StateModel stateModel,
-                         CompositeMethodsModel compositeMethodsModel,
-                         String identity,
-                         boolean instantiateOnStartup
-    )
-    {
-        super( types, visibility, metaInfo, mixinsModel, stateModel, compositeMethodsModel );
-
-        this.identity = identity;
-        this.instantiateOnStartup = instantiateOnStartup;
-        this.activatorsModel = activatorsModel;
-
-        // Calculate configuration type
-        this.configurationType = calculateConfigurationType();
-    }
-
-    @Override
-    public boolean isInstantiateOnStartup()
-    {
-        return instantiateOnStartup;
-    }
-
-    @Override
-    public String identity()
-    {
-        return identity;
-    }
-
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public ActivatorsInstance<?> newActivatorsInstance( Module module ) throws Exception
-    {
-        return new ActivatorsInstance( activatorsModel.newInstances( module ) );
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public <T> Class<T> configurationType()
-    {
-        return configurationType;
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            if( activatorsModel.accept( visitor ) )
-            {
-                if( compositeMethodsModel.accept( visitor ) )
-                {
-                    if( stateModel.accept( visitor ) )
-                    {
-                        mixinsModel.accept( visitor );
-                    }
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-    
-    public ServiceInstance newInstance( final ModuleInstance module )
-    {
-        Object[] mixins = mixinsModel.newMixinHolder();
-
-        Map<AccessibleObject, Property<?>> properties = new HashMap<>();
-        for( PropertyModel propertyModel : stateModel.properties() )
-        {
-            Object initialValue = propertyModel.initialValue( module );
-            if( propertyModel.accessor().equals( identityMethod ) )
-            {
-                initialValue = identity;
-            }
-
-            Property<?> property = new PropertyInstance<>( propertyModel, initialValue );
-            properties.put( propertyModel.accessor(), property );
-        }
-
-        TransientStateInstance state = new TransientStateInstance( properties );
-        ServiceInstance compositeInstance = new ServiceInstance( this, module, mixins, state );
-
-        // Instantiate all mixins
-        int i = 0;
-        UsesInstance uses = UsesInstance.EMPTY_USES.use( this );
-        InjectionContext injectionContext = new InjectionContext( compositeInstance, uses, state );
-        for( MixinModel mixinModel : mixinsModel.mixinModels() )
-        {
-            mixins[ i++ ] = mixinModel.newInstance( injectionContext );
-        }
-
-        return compositeInstance;
-    }
-
-    @Override
-    public String toString()
-    {
-        return super.toString() + ":" + identity;
-    }
-
-    @SuppressWarnings( { "raw", "unchecked" } )
-    public Class calculateConfigurationType()
-    {
-        Class injectionClass = null;
-        Iterable<DependencyModel> configurationThisDependencies = filter( and( translate( new DependencyModel.InjectionTypeFunction(), Specifications
-            .<Class<?>>in( Configuration.class ) ), new DependencyModel.ScopeSpecification( This.class ) ), dependencies() );
-        for( DependencyModel dependencyModel : configurationThisDependencies )
-        {
-            if( dependencyModel.rawInjectionType()
-                    .equals( Configuration.class ) && dependencyModel.injectionType() instanceof ParameterizedType )
-            {
-                Class<?> type = Classes.RAW_CLASS
-                    .map( ( (ParameterizedType) dependencyModel.injectionType() ).getActualTypeArguments()[ 0 ] );
-                if( injectionClass == null )
-                {
-                    injectionClass = type;
-                }
-                else
-                {
-                    if( injectionClass.isAssignableFrom( type ) )
-                    {
-                        injectionClass = type;
-                    }
-                }
-            }
-        }
-        return injectionClass;
-    }
-
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/service/ServiceReferenceInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/service/ServiceReferenceInstance.java
deleted file mode 100644
index 706df16..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/service/ServiceReferenceInstance.java
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.service;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.activation.Activation;
-import org.qi4j.api.activation.ActivationEventListener;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.activation.PassivationException;
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.api.property.StateHolder;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.service.ServiceImporterException;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.service.ServiceUnavailableException;
-import org.qi4j.api.structure.Module;
-import org.qi4j.runtime.activation.ActivationDelegate;
-import org.qi4j.runtime.structure.ModuleInstance;
-
-/**
- * Implementation of ServiceReference.
- * <p>
- * This manages the actual instance of the service and implements the service Activation.
- * </p>
- * <p>
- * Whenever the service is requested a proxy is returned which points to this class. This means
- * that the instance can be passivated even though a client is holding on to a service proxy.
- * </p>
- * @param <T> Service Type
- */
-public final class ServiceReferenceInstance<T>
-    implements ServiceReference<T>, Activation
-{
-    private volatile ServiceInstance instance;
-    private final T serviceProxy;
-    private final ModuleInstance module;
-    private final ServiceModel serviceModel;
-    private final ActivationDelegate activation = new ActivationDelegate( this );
-    private boolean active = false;
-
-    public ServiceReferenceInstance( ServiceModel serviceModel, ModuleInstance module )
-    {
-        this.module = module;
-        this.serviceModel = serviceModel;
-
-        serviceProxy = newProxy();
-    }
-
-    @Override
-    public String identity()
-    {
-        return serviceModel.identity();
-    }
-
-    @Override
-    public Iterable<Class<?>> types()
-    {
-        return serviceModel.types();
-    }
-
-    @Override
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return serviceModel.metaInfo( infoType );
-    }
-
-    @Override
-    public synchronized T get()
-    {
-        return serviceProxy;
-    }
-
-    @Override
-    public boolean isActive()
-    {
-        return active;
-    }
-
-    @Override
-    public boolean isAvailable()
-    {
-        return getInstance().isAvailable();
-    }
-
-    public Module module()
-    {
-        return module;
-    }
-
-    @Override
-    public void activate()
-        throws ActivationException
-    {
-        if( serviceModel.isInstantiateOnStartup() )
-        {
-            getInstance();
-        }
-    }
-
-    @Override
-    public void passivate()
-        throws PassivationException
-    {
-        if( instance != null )
-        {
-            try {
-                activation.passivate( new Runnable()
-                {
-                    @Override
-                    public void run()
-                    {
-                        active = false;
-                    }
-                } );
-            } finally {
-                instance = null;
-                active = false;
-            }
-        }
-    }
-
-    private ServiceInstance getInstance()
-        throws ServiceImporterException
-    {
-        // DCL that works with Java 1.5 volatile semantics
-        if( instance == null )
-        {
-            synchronized( this )
-            {
-                if( instance == null )
-                {
-                    instance = serviceModel.newInstance( module );
-
-                    try
-                    {
-                        activation.activate( serviceModel.newActivatorsInstance( module ), instance, new Runnable()
-                        {
-                            @Override
-                            public void run()
-                            {
-                                active = true;
-                            }
-                        } );
-                    }
-                    catch( Exception e )
-                    {
-                        instance = null;
-                        throw new ServiceUnavailableException( "Could not activate service " + serviceModel.identity(), e );
-                    }
-                }
-            }
-        }
-
-        return instance;
-    }
-
-    @Override
-    public String toString()
-    {
-        return serviceModel.identity() + "(active=" + isActive() + ",module='" + module.name() + "')";
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public T newProxy()
-    {
-        return (T) serviceModel.newProxy( new ServiceReferenceInstance.ServiceInvocationHandler() );
-    }
-
-    public ServiceDescriptor serviceDescriptor()
-    {
-        return serviceModel;
-    }
-
-    public final class ServiceInvocationHandler
-        implements CompositeInstance
-    {
-        @Override
-        @SuppressWarnings( "unchecked" )
-        public <T> T proxy()
-        {
-            return (T) ServiceReferenceInstance.this.get();
-        }
-
-        @Override
-        public <T> T newProxy( Class<T> mixinType )
-            throws IllegalArgumentException
-        {
-            return getInstance().newProxy( mixinType );
-        }
-
-        @Override
-        public <T> T metaInfo( Class<T> infoType )
-        {
-            return ServiceReferenceInstance.this.metaInfo( infoType );
-        }
-
-        @Override
-        public Iterable<Class<?>> types()
-        {
-            return ServiceReferenceInstance.this.types();
-        }
-
-        @Override
-        public CompositeDescriptor descriptor()
-        {
-            return ServiceReferenceInstance.this.serviceDescriptor();
-        }
-
-        @Override
-        public Object invokeComposite( Method method, Object[] args )
-            throws Throwable
-        {
-            return getInstance().invokeComposite( method, args );
-        }
-
-        @Override
-        public StateHolder state()
-        {
-            return getInstance().state();
-        }
-
-        @Override
-        public Object invoke( Object object, Method method, Object[] objects )
-            throws Throwable
-        {
-            if( method.getDeclaringClass().equals( Object.class ) )
-            {
-                switch( method.getName() )
-                {
-                    case "toString":
-                        return serviceModel.toString();
-                    case "equals":
-                        return objects[0] == object;
-                    case "hashCode":
-                        return serviceModel.toString().hashCode();
-                }
-            }
-
-            ServiceInstance instance = getInstance();
-
-/*
-            if (!instance.isAvailable())
-            {
-                throw new ServiceUnavailableException("Service is currently not available");
-            }
-
-*/
-            return instance.invoke( object, method, objects );
-        }
-
-        @Override
-        public String toString()
-        {
-            return serviceModel.toString();
-        }
-
-        @Override
-        public Module module()
-        {
-            return module;
-        }
-    }
-
-    @Override
-    public void registerActivationEventListener( ActivationEventListener listener )
-    {
-        activation.registerActivationEventListener( listener );
-    }
-
-    @Override
-    public void deregisterActivationEventListener( ActivationEventListener listener )
-    {
-        activation.deregisterActivationEventListener( listener );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return identity().hashCode();
-    }
-
-    @Override
-    @SuppressWarnings( "raw" )
-    public boolean equals( Object obj )
-    {
-        if ( obj == null ) {
-            return false;
-        }
-        if ( getClass() != obj.getClass() ) {
-            return false;
-        }
-        final ServiceReference other = ( ServiceReference ) obj;
-        return identity().equals( other.identity() );
-    }
-
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/service/ServicesInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/service/ServicesInstance.java
deleted file mode 100644
index 3920855..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/service/ServicesInstance.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.service;
-
-import java.util.List;
-import org.qi4j.api.activation.Activation;
-import org.qi4j.api.activation.ActivationEventListener;
-import org.qi4j.api.activation.ActivationEventListenerRegistration;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.activation.PassivationException;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.runtime.activation.ActivationDelegate;
-import org.qi4j.runtime.activation.ActivatorsInstance;
-
-import static org.qi4j.api.util.Classes.instanceOf;
-import static org.qi4j.functional.Iterables.filter;
-
-/**
- * JAVADOC
- */
-public class ServicesInstance
-    implements Activation, ActivationEventListenerRegistration
-{
-    private final ServicesModel servicesModel;
-    private final List<ServiceReference> serviceReferences;
-    private final ActivationDelegate activation = new ActivationDelegate( this, false );
-
-    public ServicesInstance( ServicesModel servicesModel, List<ServiceReference> serviceReferences )
-    {
-        this.servicesModel = servicesModel;
-        this.serviceReferences = serviceReferences;
-        for( ServiceReference serviceReference : serviceReferences )
-        {
-            serviceReference.registerActivationEventListener( activation );
-        }
-    }
-
-    @Override
-    public void activate()
-        throws ActivationException
-    {
-        Iterable<Activation> activatees = Iterables.<Activation>cast( filter( instanceOf( Activation.class ), serviceReferences ) );
-        activation.activate( ActivatorsInstance.EMPTY, activatees );
-    }
-
-    @Override
-    public void passivate()
-        throws PassivationException
-    {
-        activation.passivate();
-    }
-
-    public Iterable<ServiceReference> visibleServices( final Visibility visibility )
-    {
-        return Iterables.filter( new Specification<ServiceReference>()
-        {
-            @Override
-            public boolean satisfiedBy( ServiceReference item )
-            {
-                return ( (ServiceReferenceInstance) item ).serviceDescriptor()
-                           .visibility()
-                           .ordinal() >= visibility.ordinal();
-            }
-        }, serviceReferences );
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder( "Services{" );
-        String sep = " ";
-        for( ServiceReference serviceReference : serviceReferences )
-        {
-            sb.append( sep ).
-                append( serviceReference.identity() ).
-                append( "(active=" ).append( serviceReference.isActive() ).append( ")" );
-            sep = ", ";
-        }
-        return sb.append( " }" ).toString();
-    }
-
-    @Override
-    public void registerActivationEventListener( ActivationEventListener listener )
-    {
-        activation.registerActivationEventListener( listener );
-    }
-
-    @Override
-    public void deregisterActivationEventListener( ActivationEventListener listener )
-    {
-        activation.deregisterActivationEventListener( listener );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/service/ServicesModel.java b/core/runtime/src/main/java/org/qi4j/runtime/service/ServicesModel.java
deleted file mode 100644
index 08941f5..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/service/ServicesModel.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.service;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.structure.ModuleInstance;
-
-/**
- * JAVADOC
- */
-public class ServicesModel
-    implements VisitableHierarchy<Object, Object>
-{
-    private final Iterable<ServiceModel> serviceModels;
-
-    public ServicesModel( Iterable<ServiceModel> serviceModels )
-    {
-        this.serviceModels = serviceModels;
-    }
-
-    public ServicesInstance newInstance( ModuleInstance module )
-    {
-        List<ServiceReference> serviceReferences = new ArrayList<ServiceReference>();
-        for( ServiceModel serviceModel : serviceModels )
-        {
-            ServiceReferenceInstance serviceReferenceInstance = new ServiceReferenceInstance( serviceModel, module );
-            serviceReferences.add( serviceReferenceInstance );
-        }
-
-        return new ServicesInstance( this, serviceReferences );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( ServiceModel serviceModel : serviceModels )
-            {
-                if( !serviceModel.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/structure/ApplicationInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/structure/ApplicationInstance.java
deleted file mode 100644
index 0af1092..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/structure/ApplicationInstance.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008, Niclas Hedhman.
- *
- * Licensed 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.qi4j.runtime.structure;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.activation.ActivationEventListener;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.activation.PassivationException;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.api.structure.Layer;
-import org.qi4j.api.structure.Module;
-import org.qi4j.bootstrap.Qi4jRuntime;
-import org.qi4j.runtime.activation.ActivationDelegate;
-
-/**
- * Instance of a Zest application. Contains a list of layers which are managed by this application
- */
-public class ApplicationInstance
-    implements Application
-{
-
-    // Constructor parameters
-    private final ApplicationModel applicationModel;
-    private final Qi4jRuntime runtime;
-    private final MetaInfo instanceMetaInfo;
-    // Eager instance objects
-    private final ActivationDelegate activation;
-    private final List<LayerInstance> layerInstances;
-
-    public ApplicationInstance( ApplicationModel model, Qi4jRuntime runtime, MetaInfo instanceMetaInfo )
-    {
-        // Constructor parameters
-        this.applicationModel = model;
-        this.runtime = runtime;
-        this.instanceMetaInfo = instanceMetaInfo;
-
-        // Eager instance objects
-        activation = new ActivationDelegate( this );
-        layerInstances = new ArrayList<>();
-    }
-
-    @Override
-    public String toString()
-    {
-        return name();
-    }
-
-    // Implementation of Application
-    @Override
-    public String name()
-    {
-        return applicationModel.name();
-    }
-
-    @Override
-    public String version()
-    {
-        return applicationModel.version();
-    }
-
-    @Override
-    public Mode mode()
-    {
-        return applicationModel.mode();
-    }
-
-    @Override
-    public Layer findLayer( String layerName )
-    {
-        for( LayerInstance layerInstance : layerInstances )
-        {
-            if( layerInstance.model().name().equals( layerName ) )
-            {
-                return layerInstance;
-            }
-        }
-
-        throw new IllegalArgumentException( "No such layer:" + layerName );
-    }
-
-    @Override
-    public Module findModule( String layerName, String moduleName )
-    {
-        for( LayerInstance layerInstance : layerInstances )
-        {
-            if( layerInstance.model().name().equals( layerName ) )
-            {
-                return layerInstance.findModule( moduleName );
-            }
-        }
-
-        throw new IllegalArgumentException( "No such layer:" + layerName );
-    }
-
-    @Override
-    public ApplicationDescriptor descriptor()
-    {
-        return applicationModel;
-    }
-
-    // Implementation of MetaInfoHolder
-    @Override
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return instanceMetaInfo.get( infoType );
-    }
-
-    // Implementation of Activation
-    @Override
-    public void activate()
-        throws ActivationException
-    {
-        activation.activate( applicationModel.newActivatorsInstance(), layerInstances );
-    }
-
-    @Override
-    public void passivate()
-        throws PassivationException
-    {
-        activation.passivate();
-    }
-
-    @Override
-    public void registerActivationEventListener( ActivationEventListener listener )
-    {
-        activation.registerActivationEventListener( listener );
-    }
-
-    @Override
-    public void deregisterActivationEventListener( ActivationEventListener listener )
-    {
-        activation.deregisterActivationEventListener( listener );
-    }
-
-    // Other methods
-    /* package */ void addLayer( LayerInstance layer )
-    {
-        layer.registerActivationEventListener( activation );
-        layerInstances.add( layer );
-    }
-
-    public Qi4jRuntime runtime()
-    {
-        return runtime;
-    }
-
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/structure/ApplicationModel.java b/core/runtime/src/main/java/org/qi4j/runtime/structure/ApplicationModel.java
deleted file mode 100644
index 672df8a..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/structure/ApplicationModel.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.structure;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.common.InvalidApplicationException;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.bootstrap.Qi4jRuntime;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.runtime.activation.ActivatorsInstance;
-import org.qi4j.runtime.activation.ActivatorsModel;
-import org.qi4j.runtime.injection.InjectionProviderFactory;
-import org.qi4j.runtime.injection.provider.InjectionProviderFactoryStrategy;
-
-/**
- * JAVADOC
- */
-public final class ApplicationModel
-    implements ApplicationDescriptor
-{
-    private final String name;
-    private final String version;
-    private final Application.Mode mode;
-    private final MetaInfo metaInfo;
-    private final ActivatorsModel<Application> activatorsModel;
-    private final List<LayerModel> layers;
-    private final InjectionProviderFactory ipf;
-
-    public ApplicationModel( String name,
-                             String version,
-                             Application.Mode mode,
-                             MetaInfo metaInfo,
-                             ActivatorsModel<Application> activatorsModel,
-                             List<LayerModel> layers
-    )
-    {
-        this.name = name;
-        this.version = version;
-        this.mode = mode;
-        this.metaInfo = metaInfo;
-        this.activatorsModel = activatorsModel;
-        this.layers = layers;
-        ipf = new InjectionProviderFactoryStrategy( metaInfo );
-    }
-
-    @Override
-    public String name()
-    {
-        return name;
-    }
-
-    public String version()
-    {
-        return version;
-    }
-
-    public Application.Mode mode()
-    {
-        return mode;
-    }
-
-    public MetaInfo metaInfo()
-    {
-        return metaInfo;
-    }
-
-    public ActivatorsInstance<Application> newActivatorsInstance()
-        throws ActivationException
-    {
-        return new ActivatorsInstance<>( activatorsModel.newInstances() );
-    }
-
-    // SPI
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            if( activatorsModel.accept( visitor ) )
-            {
-                for( LayerModel layer : layers )
-                {
-                    if( !layer.accept( visitor ) )
-                    {
-                        break;
-                    }
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-
-    @Override
-    public ApplicationInstance newInstance( Qi4j runtime, Object... importedServiceInstances )
-        throws InvalidApplicationException
-    {
-        MetaInfo instanceMetaInfo = new MetaInfo( metaInfo );
-        for( Object importedServiceInstance : importedServiceInstances )
-        {
-            instanceMetaInfo.set( importedServiceInstance );
-        }
-
-        ApplicationInstance applicationInstance = new ApplicationInstance( this, (Qi4jRuntime) runtime, instanceMetaInfo );
-
-        // Create layer instances
-        Map<LayerModel, LayerInstance> layerInstanceMap = new HashMap<>();
-        Map<LayerModel, List<LayerInstance>> usedLayers = new HashMap<>();
-        for( LayerModel layer : layers )
-        {
-            List<LayerInstance> usedLayerInstances = new ArrayList<>();
-            usedLayers.put( layer, usedLayerInstances );
-            UsedLayersInstance usedLayersInstance = layer.usedLayers().newInstance( usedLayerInstances );
-            LayerInstance layerInstance = layer.newInstance( applicationInstance, usedLayersInstance );
-            applicationInstance.addLayer( layerInstance );
-            layerInstanceMap.put( layer, layerInstance );
-        }
-
-        // Resolve used layer instances
-        for( LayerModel layer : layers )
-        {
-            List<LayerInstance> usedLayerInstances = usedLayers.get( layer );
-            for( LayerModel usedLayer : layer.usedLayers().layers() )
-            {
-                LayerInstance layerInstance = layerInstanceMap.get( usedLayer );
-                if( layerInstance == null )
-                {
-                    throw new InvalidApplicationException( "Could not find used layer:" + usedLayer.name() );
-                }
-                usedLayerInstances.add( layerInstance );
-            }
-        }
-
-        return applicationInstance;
-    }
-
-    public InjectionProviderFactory injectionProviderFactory()
-    {
-        return ipf;
-    }
-
-    @Override
-    public String toString()
-    {
-        final StringBuilder sb = new StringBuilder();
-        sb.append( "ApplicationModel" );
-        sb.append( "{name='" ).append( name ).append( '\'' );
-        sb.append( ", version='" ).append( version ).append( '\'' );
-        sb.append( ", mode=" ).append( mode );
-        sb.append( '}' );
-        return sb.toString();
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/structure/LayerInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/structure/LayerInstance.java
deleted file mode 100644
index 49d83cc..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/structure/LayerInstance.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.structure;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.activation.ActivationEventListener;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.activation.PassivationException;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.TransientDescriptor;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.object.ObjectDescriptor;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Layer;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.functional.Function;
-import org.qi4j.runtime.activation.ActivationDelegate;
-import org.qi4j.spi.module.ModelModule;
-
-import static org.qi4j.functional.Iterables.flattenIterables;
-import static org.qi4j.functional.Iterables.map;
-
-/**
- * Instance of a Zest application layer. Contains a list of modules which are managed by this layer.
- */
-public class LayerInstance
-    implements Layer
-{
-
-    // Constructor parameters
-    private final LayerModel layerModel;
-    private final ApplicationInstance applicationInstance;
-    private final UsedLayersInstance usedLayersInstance;
-    // Eager instance objects
-    private final ActivationDelegate activation;
-    private final List<ModuleInstance> moduleInstances;
-
-    public LayerInstance( LayerModel model,
-                          ApplicationInstance applicationInstance,
-                          UsedLayersInstance usedLayersInstance
-    )
-    {
-        // Constructor parameters
-        this.layerModel = model;
-        this.applicationInstance = applicationInstance;
-        this.usedLayersInstance = usedLayersInstance;
-
-        // Eager instance objects
-        activation = new ActivationDelegate( this );
-        moduleInstances = new ArrayList<>();
-    }
-
-    @Override
-    public String toString()
-    {
-        return layerModel.toString();
-    }
-
-    // Implementation of Layer
-    @Override
-    public String name()
-    {
-        return layerModel.name();
-    }
-
-    // Implementation of MetaInfoHolder
-    @Override
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return layerModel.metaInfo( infoType );
-    }
-
-    // Implementation of Activation
-    @Override
-    public void activate()
-        throws ActivationException
-    {
-        activation.activate( layerModel.newActivatorsInstance(), moduleInstances );
-    }
-
-    @Override
-    public void passivate()
-        throws PassivationException
-    {
-        activation.passivate();
-    }
-
-    @Override
-    public void registerActivationEventListener( ActivationEventListener listener )
-    {
-        activation.registerActivationEventListener( listener );
-    }
-
-    @Override
-    public void deregisterActivationEventListener( ActivationEventListener listener )
-    {
-        activation.deregisterActivationEventListener( listener );
-    }
-
-    // Other methods
-    /* package */ void addModule( ModuleInstance module )
-    {
-        module.registerActivationEventListener( activation );
-        moduleInstances.add( module );
-    }
-
-    /* package */ LayerModel model()
-    {
-        return layerModel;
-    }
-
-    public ApplicationInstance applicationInstance()
-    {
-        return applicationInstance;
-    }
-
-    /* package */ UsedLayersInstance usedLayersInstance()
-    {
-        return usedLayersInstance;
-    }
-
-    /* package */ Iterable<ModelModule<ObjectDescriptor>> visibleObjects( final Visibility visibility )
-    {
-        return flattenIterables( map( new Function<ModuleInstance, Iterable<ModelModule<ObjectDescriptor>>>()
-        {
-
-            @Override
-            public Iterable<ModelModule<ObjectDescriptor>> map( ModuleInstance moduleInstance )
-            {
-                return moduleInstance.visibleObjects( visibility );
-            }
-        }, moduleInstances ) );
-    }
-
-    /* package */ Iterable<ModelModule<TransientDescriptor>> visibleTransients( final Visibility visibility )
-    {
-        return flattenIterables( map( new Function<ModuleInstance, Iterable<ModelModule<TransientDescriptor>>>()
-        {
-
-            @Override
-            public Iterable<ModelModule<TransientDescriptor>> map( ModuleInstance moduleInstance )
-            {
-                return moduleInstance.visibleTransients( visibility );
-            }
-        }, moduleInstances ) );
-    }
-
-    /* package */ Iterable<ModelModule<EntityDescriptor>> visibleEntities( final Visibility visibility )
-    {
-        return flattenIterables( map( new Function<ModuleInstance, Iterable<ModelModule<EntityDescriptor>>>()
-        {
-
-            @Override
-            public Iterable<ModelModule<EntityDescriptor>> map( ModuleInstance moduleInstance )
-            {
-                return moduleInstance.visibleEntities( visibility );
-            }
-        }, moduleInstances ) );
-    }
-
-    /* package */ Iterable<ModelModule<ValueDescriptor>> visibleValues( final Visibility visibility )
-    {
-        return flattenIterables( map( new Function<ModuleInstance, Iterable<ModelModule<ValueDescriptor>>>()
-        {
-
-            @Override
-            public Iterable<ModelModule<ValueDescriptor>> map( ModuleInstance moduleInstance )
-            {
-                return moduleInstance.visibleValues( visibility );
-            }
-        }, moduleInstances ) );
-    }
-
-    /* package */ Iterable<ServiceReference<?>> visibleServices( final Visibility visibility )
-    {
-        return flattenIterables( map( new Function<ModuleInstance, Iterable<ServiceReference<?>>>()
-        {
-
-            @Override
-            public Iterable<ServiceReference<?>> map( ModuleInstance moduleInstance )
-            {
-                return moduleInstance.visibleServices( visibility );
-            }
-        }, moduleInstances ) );
-    }
-
-    /* package */ ModuleInstance findModule( String moduleName )
-    {
-        for( ModuleInstance moduleInstance : moduleInstances )
-        {
-            if( moduleInstance.model().name().equals( moduleName ) )
-            {
-                return moduleInstance;
-            }
-        }
-
-        throw new IllegalArgumentException( "No such module:" + moduleName );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/structure/LayerModel.java b/core/runtime/src/main/java/org/qi4j/runtime/structure/LayerModel.java
deleted file mode 100644
index 58236ce..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/structure/LayerModel.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.structure;
-
-import java.util.List;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.structure.Layer;
-import org.qi4j.api.structure.LayerDescriptor;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.activation.ActivatorsInstance;
-import org.qi4j.runtime.activation.ActivatorsModel;
-
-/**
- * JAVADOC
- */
-public final class LayerModel
-    implements LayerDescriptor, VisitableHierarchy<Object, Object>
-{
-    // Model
-    private final String name;
-    private final MetaInfo metaInfo;
-    private final UsedLayersModel usedLayersModel;
-    private final ActivatorsModel<Layer> activatorsModel;
-    private final List<ModuleModel> modules;
-
-    public LayerModel( String name,
-                       MetaInfo metaInfo,
-                       UsedLayersModel usedLayersModel,
-                       ActivatorsModel<Layer> activatorsModel,
-                       List<ModuleModel> modules
-    )
-    {
-        this.name = name;
-        this.metaInfo = metaInfo;
-        this.usedLayersModel = usedLayersModel;
-        this.activatorsModel = activatorsModel;
-        this.modules = modules;
-    }
-
-    @Override
-    public String name()
-    {
-        return name;
-    }
-
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return metaInfo.get( infoType );
-    }
-
-    public Iterable<ModuleModel> modules()
-    {
-        return modules;
-    }
-
-    @Override
-    public UsedLayersModel usedLayers()
-    {
-        return usedLayersModel;
-    }
-
-    public ActivatorsInstance<Layer> newActivatorsInstance()
-        throws ActivationException
-    {
-        return new ActivatorsInstance<>( activatorsModel.newInstances() );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
-        throws ThrowableType
-    {
-        if( modelVisitor.visitEnter( this ) )
-        {
-            if( activatorsModel.accept( modelVisitor ) )
-            {
-                for( ModuleModel module : modules )
-                {
-                    if( !module.accept( modelVisitor ) )
-                    {
-                        break;
-                    }
-                }
-            }
-        }
-        return modelVisitor.visitLeave( this );
-    }
-
-    // Context
-    public LayerInstance newInstance( ApplicationInstance applicationInstance, UsedLayersInstance usedLayerInstance )
-    {
-        LayerInstance layerInstance = new LayerInstance( this, applicationInstance, usedLayerInstance );
-        for( ModuleModel module : modules )
-        {
-            ModuleInstance moduleInstance = module.newInstance( layerInstance );
-            layerInstance.addModule( moduleInstance );
-        }
-
-        return layerInstance;
-    }
-
-    @Override
-    public String toString()
-    {
-        return name;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleInstance.java
deleted file mode 100644
index 1612089..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleInstance.java
+++ /dev/null
@@ -1,876 +0,0 @@
-/*
- * Copyright (c) 2008-2012, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Kent Sølvsten. All Rights Reserved.
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2012-2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.structure;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Stack;
-import java.util.concurrent.ConcurrentHashMap;
-import org.qi4j.api.activation.Activation;
-import org.qi4j.api.activation.ActivationEventListener;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.activation.PassivationException;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.AmbiguousTypeException;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.composite.ModelDescriptor;
-import org.qi4j.api.composite.NoSuchTransientException;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientDescriptor;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.IdentityGenerator;
-import org.qi4j.api.metrics.MetricsProvider;
-import org.qi4j.api.object.NoSuchObjectException;
-import org.qi4j.api.object.ObjectDescriptor;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.QueryBuilderFactory;
-import org.qi4j.api.service.NoSuchServiceException;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkException;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.api.value.NoSuchValueException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.api.value.ValueSerializationException;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Function2;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.Specifications;
-import org.qi4j.runtime.activation.ActivationDelegate;
-import org.qi4j.runtime.composite.FunctionStateResolver;
-import org.qi4j.runtime.composite.StateResolver;
-import org.qi4j.runtime.composite.TransientBuilderInstance;
-import org.qi4j.runtime.composite.TransientModel;
-import org.qi4j.runtime.composite.TransientStateInstance;
-import org.qi4j.runtime.composite.TransientsModel;
-import org.qi4j.runtime.composite.UsesInstance;
-import org.qi4j.runtime.entity.EntitiesModel;
-import org.qi4j.runtime.entity.EntityInstance;
-import org.qi4j.runtime.entity.EntityModel;
-import org.qi4j.runtime.injection.InjectionContext;
-import org.qi4j.runtime.object.ObjectModel;
-import org.qi4j.runtime.object.ObjectsModel;
-import org.qi4j.runtime.property.PropertyInstance;
-import org.qi4j.runtime.property.PropertyModel;
-import org.qi4j.runtime.query.QueryBuilderFactoryImpl;
-import org.qi4j.runtime.service.ImportedServicesInstance;
-import org.qi4j.runtime.service.ImportedServicesModel;
-import org.qi4j.runtime.service.ServicesInstance;
-import org.qi4j.runtime.service.ServicesModel;
-import org.qi4j.runtime.unitofwork.UnitOfWorkInstance;
-import org.qi4j.runtime.value.ValueBuilderInstance;
-import org.qi4j.runtime.value.ValueBuilderWithPrototype;
-import org.qi4j.runtime.value.ValueBuilderWithState;
-import org.qi4j.runtime.value.ValueInstance;
-import org.qi4j.runtime.value.ValueModel;
-import org.qi4j.runtime.value.ValuesModel;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.metrics.MetricsProviderAdapter;
-import org.qi4j.spi.module.ModelModule;
-import org.qi4j.spi.module.ModuleSpi;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerialization;
-
-import static org.qi4j.api.common.Visibility.application;
-import static org.qi4j.api.common.Visibility.layer;
-import static org.qi4j.api.common.Visibility.module;
-import static org.qi4j.api.util.Classes.RAW_CLASS;
-import static org.qi4j.api.util.Classes.modelTypeSpecification;
-import static org.qi4j.functional.Iterables.cast;
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.flatten;
-import static org.qi4j.functional.Iterables.iterable;
-import static org.qi4j.functional.Iterables.map;
-import static org.qi4j.functional.Iterables.toList;
-
-/**
- * Instance of a Zest Module. Contains the various composites for this Module.
- */
-public class ModuleInstance
-    implements Module, ModuleSpi, Activation
-{
-    // Constructor parameters
-    private final ModuleModel model;
-    private final LayerInstance layer;
-    private final TransientsModel transients;
-    private final ValuesModel values;
-    private final ObjectsModel objects;
-    private final EntitiesModel entities;
-    private final ServicesInstance services;
-    private final ImportedServicesInstance importedServices;
-    // Eager instance objects
-    private final ActivationDelegate activation;
-    private final TypeLookup typeLookup;
-    private final QueryBuilderFactory queryBuilderFactory;
-    private final ClassLoader classLoader;
-    private final EntityFunction entityFunction;
-    // Lazy assigned on accessors
-    private EntityStore store;
-    private IdentityGenerator generator;
-    private ValueSerialization valueSerialization;
-    private MetricsProvider metrics;
-
-    @SuppressWarnings( "LeakingThisInConstructor" )
-    public ModuleInstance( ModuleModel moduleModel, LayerInstance layerInstance, TransientsModel transientsModel,
-                           EntitiesModel entitiesModel, ObjectsModel objectsModel, ValuesModel valuesModel,
-                           ServicesModel servicesModel, ImportedServicesModel importedServicesModel
-    )
-    {
-        // Constructor parameters
-        model = moduleModel;
-        layer = layerInstance;
-        transients = transientsModel;
-        values = valuesModel;
-        objects = objectsModel;
-        entities = entitiesModel;
-        services = servicesModel.newInstance( this );
-        importedServices = importedServicesModel.newInstance( this );
-
-        // Eager instance objects
-        activation = new ActivationDelegate( this );
-        typeLookup = new TypeLookup( this );
-        queryBuilderFactory = new QueryBuilderFactoryImpl( this );
-        classLoader = new ModuleClassLoader( this, Thread.currentThread().getContextClassLoader() );
-        entityFunction = new EntityFunction( this );
-
-        // Activation
-        services.registerActivationEventListener( activation );
-        importedServices.registerActivationEventListener( activation );
-    }
-
-    @Override
-    public String toString()
-    {
-        return model.toString();
-    }
-
-    // Implementation of Module
-    @Override
-    public String name()
-    {
-        return model.name();
-    }
-
-    @Override
-    public ClassLoader classLoader()
-    {
-        return classLoader;
-    }
-
-    @Override
-    public EntityDescriptor entityDescriptor( String name )
-    {
-        try
-        {
-            Class<?> type = classLoader().loadClass( name );
-            ModelModule<EntityModel> entityModel = typeLookup.lookupEntityModel( type );
-            if( entityModel == null )
-            {
-                return null;
-            }
-            return entityModel.model();
-        }
-        catch( ClassNotFoundException e )
-        {
-            return null;
-        }
-    }
-
-    @Override
-    public ObjectDescriptor objectDescriptor( String typeName )
-    {
-        try
-        {
-            Class<?> type = classLoader().loadClass( typeName );
-            ModelModule<ObjectModel> objectModel = typeLookup.lookupObjectModel( type );
-            if( objectModel == null )
-            {
-                return null;
-            }
-            return objectModel.model();
-        }
-        catch( ClassNotFoundException e )
-        {
-            return null;
-        }
-    }
-
-    @Override
-    public TransientDescriptor transientDescriptor( String name )
-    {
-        try
-        {
-            Class<?> type = classLoader().loadClass( name );
-            ModelModule<TransientModel> transientModel = typeLookup.lookupTransientModel( type );
-            if( transientModel == null )
-            {
-                return null;
-            }
-            return transientModel.model();
-        }
-        catch( ClassNotFoundException e )
-        {
-            return null;
-        }
-    }
-
-    @Override
-    public ValueDescriptor valueDescriptor( String name )
-    {
-        try
-        {
-            Class<?> type = classLoader().loadClass( name );
-            ModelModule<ValueModel> valueModel = typeLookup.lookupValueModel( type );
-            if( valueModel == null )
-            {
-                return null;
-            }
-            return valueModel.model();
-        }
-        catch( ClassNotFoundException e )
-        {
-            return null;
-        }
-    }
-
-    // Implementation of MetaInfoHolder
-    @Override
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return model.metaInfo( infoType );
-    }
-
-    // Implementation of ObjectFactory
-    @Override
-    public <T> T newObject( Class<T> mixinType, Object... uses )
-        throws NoSuchObjectException
-    {
-        NullArgumentException.validateNotNull( "mixinType", mixinType );
-        ModelModule<ObjectModel> modelModule = typeLookup.lookupObjectModel( mixinType );
-
-        if( modelModule == null )
-        {
-            throw new NoSuchObjectException( mixinType.getName(), name() );
-        }
-
-        InjectionContext injectionContext = new InjectionContext( modelModule.module(), UsesInstance.EMPTY_USES.use( uses ) );
-        return mixinType.cast( modelModule.model().newInstance( injectionContext ) );
-    }
-
-    @Override
-    public void injectTo( Object instance, Object... uses )
-        throws ConstructionException
-    {
-        NullArgumentException.validateNotNull( "instance", instance );
-        ModelModule<ObjectModel> modelModule = typeLookup.lookupObjectModel( instance.getClass() );
-
-        if( modelModule == null )
-        {
-            throw new NoSuchObjectException( instance.getClass().getName(), name() );
-        }
-
-        InjectionContext injectionContext = new InjectionContext( modelModule.module(), UsesInstance.EMPTY_USES.use( uses ) );
-        modelModule.model().inject( injectionContext, instance );
-    }
-
-    // Implementation of TransientBuilderFactory
-    @Override
-    public <T> TransientBuilder<T> newTransientBuilder( Class<T> mixinType )
-        throws NoSuchTransientException
-    {
-        NullArgumentException.validateNotNull( "mixinType", mixinType );
-        ModelModule<TransientModel> modelModule = typeLookup.lookupTransientModel( mixinType );
-
-        if( modelModule == null )
-        {
-            throw new NoSuchTransientException( mixinType.getName(), name() );
-        }
-
-        Map<AccessibleObject, Property<?>> properties = new HashMap<>();
-        for( PropertyModel propertyModel : modelModule.model().state().properties() )
-        {
-            Property<?> property = new PropertyInstance<>( propertyModel.getBuilderInfo(),
-                                                           propertyModel.initialValue( modelModule.module() ) );
-            properties.put( propertyModel.accessor(), property );
-        }
-
-        TransientStateInstance state = new TransientStateInstance( properties );
-
-        return new TransientBuilderInstance<>( modelModule, state, UsesInstance.EMPTY_USES );
-    }
-
-    @Override
-    public <T> T newTransient( final Class<T> mixinType, Object... uses )
-        throws NoSuchTransientException, ConstructionException
-    {
-        return newTransientBuilder( mixinType ).use( uses ).newInstance();
-    }
-
-    // Implementation of ValueBuilderFactory
-    @Override
-    public <T> T newValue( Class<T> mixinType )
-        throws NoSuchValueException, ConstructionException
-    {
-        return newValueBuilder( mixinType ).newInstance();
-    }
-
-    @Override
-    public <T> ValueBuilder<T> newValueBuilder( Class<T> mixinType )
-        throws NoSuchValueException
-    {
-        NullArgumentException.validateNotNull( "mixinType", mixinType );
-        ModelModule<ValueModel> compositeModelModule = typeLookup.lookupValueModel( mixinType );
-
-        if( compositeModelModule == null )
-        {
-            throw new NoSuchValueException( mixinType.getName(), name() );
-        }
-
-        StateResolver stateResolver = new InitialStateResolver( compositeModelModule.module() );
-        return new ValueBuilderInstance<>( compositeModelModule, this, stateResolver );
-    }
-
-    @Override
-    public <T> ValueBuilder<T> newValueBuilderWithState( Class<T> mixinType,
-                                                         Function<PropertyDescriptor, Object> propertyFunction,
-                                                         Function<AssociationDescriptor, EntityReference> associationFunction,
-                                                         Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction,
-                                                         Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction
-    )
-    {
-        NullArgumentException.validateNotNull( "propertyFunction", propertyFunction );
-        NullArgumentException.validateNotNull( "associationFunction", associationFunction );
-        NullArgumentException.validateNotNull( "manyAssociationFunction", manyAssociationFunction );
-        NullArgumentException.validateNotNull( "namedAssociationFunction", namedAssociationFunction );
-
-        ModelModule<ValueModel> compositeModelModule = typeLookup.lookupValueModel( mixinType );
-
-        if( compositeModelModule == null )
-        {
-            throw new NoSuchValueException( mixinType.getName(), name() );
-        }
-
-        StateResolver stateResolver = new FunctionStateResolver(
-            propertyFunction, associationFunction, manyAssociationFunction, namedAssociationFunction
-        );
-        return new ValueBuilderWithState<>( compositeModelModule, this, stateResolver );
-    }
-
-    private static class InitialStateResolver
-        implements StateResolver
-    {
-        private final Module module;
-
-        private InitialStateResolver( Module module )
-        {
-            this.module = module;
-        }
-
-        @Override
-        public Object getPropertyState( PropertyDescriptor propertyDescriptor )
-        {
-            return propertyDescriptor.initialValue( module );
-        }
-
-        @Override
-        public EntityReference getAssociationState( AssociationDescriptor associationDescriptor )
-        {
-            return null;
-        }
-
-        @Override
-        public List<EntityReference> getManyAssociationState( AssociationDescriptor associationDescriptor )
-        {
-            return new ArrayList<>();
-        }
-
-        @Override
-        public Map<String, EntityReference> getNamedAssociationState( AssociationDescriptor associationDescriptor )
-        {
-            return new HashMap<>();
-        }
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public <T> ValueBuilder<T> newValueBuilderWithPrototype( T prototype )
-    {
-        NullArgumentException.validateNotNull( "prototype", prototype );
-
-        ValueInstance valueInstance = ValueInstance.valueInstanceOf( (ValueComposite) prototype );
-        Class<Composite> valueType = (Class<Composite>) first( valueInstance.types() );
-
-        ModelModule<ValueModel> modelModule = typeLookup.lookupValueModel( valueType );
-
-        if( modelModule == null )
-        {
-            throw new NoSuchValueException( valueType.getName(), name() );
-        }
-
-        return new ValueBuilderWithPrototype<>( modelModule, this, prototype );
-    }
-
-    @Override
-    public <T> T newValueFromSerializedState( Class<T> mixinType, String serializedState )
-        throws NoSuchValueException, ConstructionException
-    {
-        NullArgumentException.validateNotNull( "mixinType", mixinType );
-        ModelModule<ValueModel> modelModule = typeLookup.lookupValueModel( mixinType );
-
-        if( modelModule == null )
-        {
-            throw new NoSuchValueException( mixinType.getName(), name() );
-        }
-
-        try
-        {
-            return valueSerialization().deserialize( modelModule.model().valueType(), serializedState );
-        }
-        catch( ValueSerializationException ex )
-        {
-            throw new ConstructionException( "Could not create value from serialized state", ex );
-        }
-    }
-
-    // Implementation of UnitOfWorkFactory
-    @Override
-    public UnitOfWork newUnitOfWork()
-    {
-        return newUnitOfWork( Usecase.DEFAULT );
-    }
-
-    @Override
-    public UnitOfWork newUnitOfWork( long currentTime )
-    {
-        return newUnitOfWork( Usecase.DEFAULT, currentTime );
-    }
-
-    @Override
-    public UnitOfWork newUnitOfWork( Usecase usecase )
-    {
-        return newUnitOfWork( usecase == null ? Usecase.DEFAULT : usecase, System.currentTimeMillis() );
-    }
-
-    @Override
-    public UnitOfWork newUnitOfWork( Usecase usecase, long currentTime )
-    {
-        UnitOfWorkInstance unitOfWorkInstance = new UnitOfWorkInstance( usecase, currentTime, metricsProvider() );
-        return new ModuleUnitOfWork( ModuleInstance.this, unitOfWorkInstance );
-    }
-
-    @Override
-    public boolean isUnitOfWorkActive()
-    {
-        Stack<UnitOfWorkInstance> stack = UnitOfWorkInstance.getCurrent();
-        return !stack.isEmpty();
-    }
-
-    @Override
-    public UnitOfWork currentUnitOfWork()
-    {
-        Stack<UnitOfWorkInstance> stack = UnitOfWorkInstance.getCurrent();
-        if( stack.size() == 0 )
-        {
-            throw new IllegalStateException( "No current UnitOfWork active" );
-        }
-        return new ModuleUnitOfWork( ModuleInstance.this, stack.peek() );
-    }
-
-    @Override
-    public UnitOfWork getUnitOfWork( EntityComposite entity )
-    {
-        EntityInstance instance = EntityInstance.entityInstanceOf( entity );
-        return instance.unitOfWork();
-    }
-
-    // Implementation of QueryBuilderFactory
-    @Override
-    public <T> QueryBuilder<T> newQueryBuilder( final Class<T> resultType )
-    {
-        return queryBuilderFactory.newQueryBuilder( resultType );
-    }
-
-    // Implementation of ServiceFinder
-    @Override
-    public <T> ServiceReference<T> findService( Class<T> serviceType )
-    {
-        return typeLookup.lookupServiceReference( (Type) serviceType );
-    }
-
-    @Override
-    public <T> ServiceReference<T> findService( Type serviceType )
-    {
-        return typeLookup.lookupServiceReference( serviceType );
-    }
-
-    @Override
-    public <T> Iterable<ServiceReference<T>> findServices( Class<T> serviceType )
-    {
-        return typeLookup.lookupServiceReferences( (Type) serviceType );
-    }
-
-    @Override
-    public <T> Iterable<ServiceReference<T>> findServices( Type serviceType )
-    {
-        return typeLookup.lookupServiceReferences( serviceType );
-    }
-
-    // Implementation of Activation
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public void activate()
-        throws ActivationException
-    {
-        activation.activate( model.newActivatorsInstance(), iterable( services, importedServices ) );
-    }
-
-    @Override
-    public void passivate()
-        throws PassivationException
-    {
-        activation.passivate();
-    }
-
-    @Override
-    public void registerActivationEventListener( ActivationEventListener listener )
-    {
-        activation.registerActivationEventListener( listener );
-    }
-
-    @Override
-    public void deregisterActivationEventListener( ActivationEventListener listener )
-    {
-        activation.deregisterActivationEventListener( listener );
-    }
-
-    // Other methods
-    /* package */ ModuleModel model()
-    {
-        return model;
-    }
-
-    public LayerInstance layerInstance()
-    {
-        return layer;
-    }
-
-    public TypeLookup typeLookup()
-    {
-        return typeLookup;
-    }
-
-    public Function2<EntityReference, Type, Object> getEntityFunction()
-    {
-        return entityFunction;
-    }
-
-    private static class EntityFunction
-        implements Function2<EntityReference, Type, Object>
-    {
-
-        private final UnitOfWorkFactory uowf;
-
-        private EntityFunction( UnitOfWorkFactory uowf )
-        {
-            this.uowf = uowf;
-        }
-
-        @Override
-        public Object map( EntityReference entityReference, Type type )
-        {
-            return uowf.currentUnitOfWork().get( RAW_CLASS.map( type ), entityReference.identity() );
-        }
-    }
-
-    public EntityStore entityStore()
-    {
-        synchronized( this )
-        {
-            if( store == null )
-            {
-                ServiceReference<EntityStore> service = findService( EntityStore.class );
-                if( service == null )
-                {
-                    throw new UnitOfWorkException( "No EntityStore service available in module " + name() );
-                }
-                store = service.get();
-            }
-        }
-        return store;
-    }
-
-    public IdentityGenerator identityGenerator()
-    {
-        synchronized( this )
-        {
-            if( generator == null )
-            {
-                ServiceReference<IdentityGenerator> service = findService( IdentityGenerator.class );
-                generator = service.get();
-            }
-            return generator;
-        }
-    }
-
-    public ValueSerialization valueSerialization()
-    {
-        synchronized( this )
-        {
-            if( valueSerialization == null )
-            {
-                try
-                {
-                    ServiceReference<ValueSerialization> service = findService( ValueSerialization.class );
-                    valueSerialization = service.get();
-                }
-                catch( NoSuchServiceException e )
-                {
-                    valueSerialization = new OrgJsonValueSerialization( layer.applicationInstance(), this, this );
-                }
-            }
-        }
-        return valueSerialization;
-    }
-
-    /* package */ MetricsProvider metricsProvider()
-    {
-        synchronized( this )
-        {
-            if( metrics == null )
-            {
-                try
-                {
-                    ServiceReference<MetricsProvider> service = findService( MetricsProvider.class );
-                    metrics = service.get();
-                }
-                catch( NoSuchServiceException e )
-                {
-                    metrics = new MetricsProviderAdapter();
-                }
-            }
-        }
-        return metrics;
-    }
-
-    public Iterable<ModelModule<ObjectDescriptor>> visibleObjects( Visibility visibility )
-    {
-        return map( ModelModule.<ObjectDescriptor>modelModuleFunction( this ),
-                    filter( new VisibilitySpecification( visibility ), objects.models() ) );
-    }
-
-    public Iterable<ModelModule<TransientDescriptor>> visibleTransients( Visibility visibility )
-    {
-        return map( ModelModule.<TransientDescriptor>modelModuleFunction( this ),
-                    filter( new VisibilitySpecification( visibility ), transients.models() ) );
-    }
-
-    public Iterable<ModelModule<EntityDescriptor>> visibleEntities( Visibility visibility )
-    {
-        return map( ModelModule.<EntityDescriptor>modelModuleFunction( this ),
-                    filter( new VisibilitySpecification( visibility ), entities.models() ) );
-    }
-
-    public Iterable<ModelModule<ValueDescriptor>> visibleValues( Visibility visibility )
-    {
-        return map( ModelModule.<ValueDescriptor>modelModuleFunction( this ),
-                    filter( new VisibilitySpecification( visibility ), values.models() ) );
-    }
-
-    public Iterable<ServiceReference<?>> visibleServices( Visibility visibility )
-    {
-        return flatten( services.visibleServices( visibility ),
-                        importedServices.visibleServices( visibility ) );
-    }
-
-    // Module ClassLoader
-    private static class ModuleClassLoader
-        extends ClassLoader
-    {
-
-        private final ModuleInstance moduleInstance;
-        private final Map<String, Class<?>> classes = new ConcurrentHashMap<>();
-
-        private ModuleClassLoader( ModuleInstance moduleInstance, ClassLoader classLoader )
-        {
-            super( classLoader );
-            this.moduleInstance = moduleInstance;
-        }
-
-        @Override
-        protected Class<?> findClass( String name )
-            throws ClassNotFoundException
-        {
-            Class<?> clazz = classes.get( name );
-            if( clazz == null )
-            {
-                Specification<ModelDescriptor> modelTypeSpecification = modelTypeSpecification( name );
-                Specification<ModelModule<ModelDescriptor>> translate = Specifications.translate( ModelModule.modelFunction(), modelTypeSpecification );
-                // Check module
-                {
-                    Iterable<ModelModule<ModelDescriptor>> i = cast( flatten(
-                        cast( moduleInstance.visibleObjects( Visibility.module ) ),
-                        cast( moduleInstance.visibleEntities( Visibility.module ) ),
-                        cast( moduleInstance.visibleTransients( Visibility.module ) ),
-                        cast( moduleInstance.visibleValues( Visibility.module ) ) ) );
-
-                    Iterable<ModelModule<ModelDescriptor>> moduleModels = filter( translate, i );
-                    Iterator<ModelModule<ModelDescriptor>> iter = moduleModels.iterator();
-                    if( iter.hasNext() )
-                    {
-                        clazz = first( iter.next().model().types() );
-
-                        if( iter.hasNext() )
-                        {
-                            // Ambiguous exception
-                            throw new ClassNotFoundException(
-                                name,
-                                new AmbiguousTypeException(
-                                    "More than one model matches the classname " + name + ":" + toList( moduleModels )
-                                )
-                            );
-                        }
-                    }
-                }
-
-                // Check layer
-                if( clazz == null )
-                {
-                    Iterable<ModelModule<ModelDescriptor>> flatten = cast( flatten(
-                        cast( moduleInstance.layerInstance().visibleObjects( Visibility.layer ) ),
-                        cast( moduleInstance.layerInstance().visibleTransients( Visibility.layer ) ),
-                        cast( moduleInstance.layerInstance().visibleEntities( Visibility.layer ) ),
-                        cast( moduleInstance.layerInstance().visibleValues( Visibility.layer ) ),
-                        cast( moduleInstance.layerInstance().visibleObjects( Visibility.application ) ),
-                        cast( moduleInstance.layerInstance().visibleTransients( Visibility.application ) ),
-                        cast( moduleInstance.layerInstance().visibleEntities( Visibility.application ) ),
-                        cast( moduleInstance.layerInstance().visibleValues( Visibility.application ) ) ) );
-                    Iterable<ModelModule<ModelDescriptor>> layerModels = filter( translate, flatten );
-                    Iterator<ModelModule<ModelDescriptor>> iter = layerModels.iterator();
-                    if( iter.hasNext() )
-                    {
-                        clazz = first( iter.next().model().types() );
-
-                        if( iter.hasNext() )
-                        {
-                            // Ambiguous exception
-                            throw new ClassNotFoundException(
-                                name,
-                                new AmbiguousTypeException(
-                                    "More than one model matches the classname " + name + ":" + toList( layerModels ) )
-                            );
-                        }
-                    }
-                }
-
-                // Check used layers
-                if( clazz == null )
-                {
-                    Iterable<ModelModule<ModelDescriptor>> flatten = cast( flatten(
-                        cast( moduleInstance.layerInstance().usedLayersInstance().visibleObjects() ),
-                        cast( moduleInstance.layerInstance().usedLayersInstance().visibleTransients() ),
-                        cast( moduleInstance.layerInstance().usedLayersInstance().visibleEntities() ),
-                        cast( moduleInstance.layerInstance().usedLayersInstance().visibleValues() ) ) );
-                    Iterable<ModelModule<ModelDescriptor>> usedLayersModels = filter( translate, flatten );
-                    Iterator<ModelModule<ModelDescriptor>> iter = usedLayersModels.iterator();
-                    if( iter.hasNext() )
-                    {
-                        clazz = first( iter.next().model().types() );
-
-                        if( iter.hasNext() )
-                        {
-                            // Ambiguous exception
-                            throw new ClassNotFoundException(
-                                name,
-                                new AmbiguousTypeException(
-                                    "More than one model matches the classname " + name + ":" + toList( usedLayersModels )
-                                )
-                            );
-                        }
-                    }
-                }
-
-                if( clazz == null )
-                {
-                    throw new ClassNotFoundException( name );
-                }
-                classes.put( name, clazz );
-            }
-
-            return clazz;
-        }
-    }
-
-    public Iterable<ModelModule<ValueDescriptor>> findVisibleValueTypes()
-    {
-        return flatten( visibleValues( Visibility.module ),
-            layerInstance().visibleValues( Visibility.layer ),
-            layerInstance().visibleValues( Visibility.application ),
-            layerInstance().usedLayersInstance().visibleValues()
-        );
-    }
-
-    public Iterable<ModelModule<EntityDescriptor>> findVisibleEntityTypes()
-    {
-        return flatten( visibleEntities( Visibility.module ),
-            layerInstance().visibleEntities( Visibility.layer ),
-            layerInstance().visibleEntities( Visibility.application ),
-            layerInstance().usedLayersInstance().visibleEntities()
-        );
-    }
-    public Iterable<ModelModule<TransientDescriptor>> findVisibleTransientTypes()
-    {
-        return flatten( visibleTransients( Visibility.module ),
-            layerInstance().visibleTransients( Visibility.layer ),
-            layerInstance().visibleTransients( Visibility.application ),
-            layerInstance().usedLayersInstance().visibleTransients()
-        );
-    }
-    public Iterable<ModelModule<ServiceDescriptor>> findVisibleServiceTypes()
-    {
-        return flatten( visibleServices( Visibility.module ),
-            layerInstance().visibleServices( Visibility.layer ),
-            layerInstance().visibleServices( Visibility.application ),
-            layerInstance().usedLayersInstance().visibleServices()
-        );
-    }
-    public Iterable<ModelModule<ObjectDescriptor>> findVisibleObjectTypes()
-    {
-        return flatten( visibleObjects( Visibility.module ),
-            layerInstance().visibleObjects( Visibility.layer ),
-            layerInstance().visibleObjects( Visibility.application ),
-            layerInstance().usedLayersInstance().visibleObjects()
-        );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleModel.java b/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleModel.java
deleted file mode 100644
index 777729f..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleModel.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.structure;
-
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.structure.ModuleDescriptor;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.activation.ActivatorsInstance;
-import org.qi4j.runtime.activation.ActivatorsModel;
-import org.qi4j.runtime.composite.TransientsModel;
-import org.qi4j.runtime.entity.EntitiesModel;
-import org.qi4j.runtime.object.ObjectsModel;
-import org.qi4j.runtime.service.ImportedServicesModel;
-import org.qi4j.runtime.service.ServicesModel;
-import org.qi4j.runtime.value.ValuesModel;
-
-/**
- * JAVADOC
- */
-public class ModuleModel
-    implements ModuleDescriptor, VisitableHierarchy<Object, Object>
-{
-    private final ActivatorsModel<Module> activatorsModel;
-    private final TransientsModel transientsModel;
-    private final EntitiesModel entitiesModel;
-    private final ObjectsModel objectsModel;
-    private final ValuesModel valuesModel;
-    private final ServicesModel servicesModel;
-    private final ImportedServicesModel importedServicesModel;
-
-    private final String name;
-    private final MetaInfo metaInfo;
-
-    public ModuleModel( String name,
-                        MetaInfo metaInfo,
-                        ActivatorsModel<Module> activatorsModel,
-                        TransientsModel transientsModel,
-                        EntitiesModel entitiesModel,
-                        ObjectsModel objectsModel,
-                        ValuesModel valuesModel,
-                        ServicesModel servicesModel,
-                        ImportedServicesModel importedServicesModel
-    )
-    {
-        this.name = name;
-        this.metaInfo = metaInfo;
-        this.activatorsModel = activatorsModel;
-        this.transientsModel = transientsModel;
-        this.entitiesModel = entitiesModel;
-        this.objectsModel = objectsModel;
-        this.valuesModel = valuesModel;
-        this.servicesModel = servicesModel;
-        this.importedServicesModel = importedServicesModel;
-    }
-
-    @Override
-    public String name()
-    {
-        return name;
-    }
-
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return metaInfo.get( infoType );
-    }
-
-    public ActivatorsInstance<Module> newActivatorsInstance()
-        throws ActivationException
-    {
-        return new ActivatorsInstance<>( activatorsModel.newInstances() );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
-        throws ThrowableType
-    {
-        if( modelVisitor.visitEnter( this ) )
-        {
-            if( activatorsModel.accept( modelVisitor ) )
-            {
-                if( transientsModel.accept( modelVisitor ) )
-                {
-                    if( entitiesModel.accept( modelVisitor ) )
-                    {
-                        if( servicesModel.accept( modelVisitor ) )
-                        {
-                            if( importedServicesModel.accept( modelVisitor ) )
-                            {
-                                if( objectsModel.accept( modelVisitor ) )
-                                {
-                                    valuesModel.accept( modelVisitor );
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return modelVisitor.visitLeave( this );
-    }
-
-    // Context
-
-    public ModuleInstance newInstance( LayerInstance layerInstance )
-    {
-        return new ModuleInstance( this, layerInstance, transientsModel, entitiesModel, objectsModel, valuesModel, servicesModel, importedServicesModel );
-    }
-
-    @Override
-    public String toString()
-    {
-        return name;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleUnitOfWork.java b/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleUnitOfWork.java
deleted file mode 100644
index 9989f65..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/structure/ModuleUnitOfWork.java
+++ /dev/null
@@ -1,773 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2013-2015, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2013-2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.structure;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.entity.IdentityGenerator;
-import org.qi4j.api.entity.LifecycleException;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.property.StateHolder;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.QueryExecutionException;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.api.service.NoSuchServiceException;
-import org.qi4j.api.unitofwork.ConcurrentEntityModificationException;
-import org.qi4j.api.unitofwork.EntityTypeNotFoundException;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCallback;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.runtime.association.AssociationInstance;
-import org.qi4j.runtime.association.ManyAssociationInstance;
-import org.qi4j.runtime.association.NamedAssociationInstance;
-import org.qi4j.runtime.composite.FunctionStateResolver;
-import org.qi4j.runtime.entity.EntityInstance;
-import org.qi4j.runtime.entity.EntityModel;
-import org.qi4j.runtime.property.PropertyModel;
-import org.qi4j.runtime.unitofwork.EntityBuilderInstance;
-import org.qi4j.runtime.unitofwork.UnitOfWorkInstance;
-import org.qi4j.runtime.value.ValueInstance;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.EntityStatus;
-import org.qi4j.spi.entity.NamedAssociationState;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.module.ModelModule;
-import org.qi4j.spi.query.EntityFinder;
-import org.qi4j.spi.query.EntityFinderException;
-import org.qi4j.spi.query.QueryBuilderSPI;
-import org.qi4j.spi.query.QuerySource;
-
-import static org.qi4j.api.entity.EntityReference.parseEntityReference;
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.map;
-
-/**
- * JAVADOC
- */
-public class ModuleUnitOfWork
-    implements UnitOfWork
-{
-    private static final QualifiedName IDENTITY_STATE_NAME;
-
-    static
-    {
-        try
-        {
-            IDENTITY_STATE_NAME = QualifiedName.fromAccessor( Identity.class.getMethod( "identity" ) );
-        }
-        catch( NoSuchMethodException e )
-        {
-            throw new InternalError( "Zest Core Runtime codebase is corrupted. Contact Zest team: ModuleUnitOfWork" );
-        }
-    }
-
-    private final UnitOfWorkInstance uow;
-    private final ModuleInstance module;
-
-    ModuleUnitOfWork( ModuleInstance module, UnitOfWorkInstance uow )
-    {
-        this.module = module;
-        this.uow = uow;
-    }
-
-    public ModuleInstance module()
-    {
-        return module;
-    }
-
-    public UnitOfWorkInstance instance()
-    {
-        return uow;
-    }
-
-    @Override
-    public UnitOfWorkFactory unitOfWorkFactory()
-    {
-        return module;
-    }
-
-    @Override
-    public long currentTime()
-    {
-        return uow.currentTime();
-    }
-
-    @Override
-    public Usecase usecase()
-    {
-        return uow.usecase();
-    }
-
-    @Override
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return uow.metaInfo().get( infoType );
-    }
-
-    @Override
-    public void setMetaInfo( Object metaInfo )
-    {
-        uow.metaInfo().set( metaInfo );
-    }
-
-    @Override
-    @SuppressWarnings( { "raw", "unchecked" } )
-    public <T> Query<T> newQuery( QueryBuilder<T> queryBuilder )
-    {
-        QueryBuilderSPI queryBuilderSPI = (QueryBuilderSPI) queryBuilder;
-
-        return queryBuilderSPI.newQuery( new UoWQuerySource( this ) );
-    }
-
-    @Override
-    public <T> T newEntity( Class<T> type )
-        throws EntityTypeNotFoundException, LifecycleException
-    {
-        return newEntity( type, null );
-    }
-
-    @Override
-    public <T> T newEntity( Class<T> type, String identity )
-        throws EntityTypeNotFoundException, LifecycleException
-    {
-        return newEntityBuilder( type, identity ).newInstance();
-    }
-
-    @Override
-    public <T> EntityBuilder<T> newEntityBuilder( Class<T> type )
-        throws EntityTypeNotFoundException
-    {
-        return newEntityBuilder( type, null );
-    }
-
-    @Override
-    public <T> EntityBuilder<T> newEntityBuilder( Class<T> type, String identity )
-        throws EntityTypeNotFoundException
-    {
-        ModelModule<EntityModel> model = module.typeLookup().lookupEntityModel( type );
-
-        if( model == null )
-        {
-            throw new EntityTypeNotFoundException( type.getName(),
-                                                   module.name(),
-                                                   map( ModelModule.toStringFunction,
-                                                        module.findVisibleEntityTypes()
-                                                   ) );
-        }
-
-        EntityStore entityStore = model.module().entityStore();
-
-        // Generate id if necessary
-        if( identity == null )
-        {
-            IdentityGenerator idGen = model.module().identityGenerator();
-            if( idGen == null )
-            {
-                throw new NoSuchServiceException( IdentityGenerator.class.getName(), model.module().name() );
-            }
-            identity = idGen.generate( first( model.model().types() ) );
-        }
-        EntityBuilder<T> builder;
-
-        builder = new EntityBuilderInstance<>( model,
-                                               this,
-                                               uow.getEntityStoreUnitOfWork( entityStore, module ),
-                                               identity );
-        return builder;
-    }
-
-    @Override
-    public <T> EntityBuilder<T> newEntityBuilderWithState(
-        Class<T> type,
-        Function<PropertyDescriptor, Object> propertyFunction,
-        Function<AssociationDescriptor, EntityReference> associationFunction,
-        Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction,
-        Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction
-    )
-        throws EntityTypeNotFoundException
-    {
-        return newEntityBuilderWithState( type, null,
-                                          propertyFunction,
-                                          associationFunction,
-                                          manyAssociationFunction,
-                                          namedAssociationFunction );
-    }
-
-    @Override
-    public <T> EntityBuilder<T> newEntityBuilderWithState(
-        Class<T> type, String identity,
-        Function<PropertyDescriptor, Object> propertyFunction,
-        Function<AssociationDescriptor, EntityReference> associationFunction,
-        Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction,
-        Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction
-    )
-        throws EntityTypeNotFoundException
-    {
-        NullArgumentException.validateNotNull( "propertyFunction", propertyFunction );
-        NullArgumentException.validateNotNull( "associationFunction", associationFunction );
-        NullArgumentException.validateNotNull( "manyAssociationFunction", manyAssociationFunction );
-        NullArgumentException.validateNotNull( "namedAssociationFunction", namedAssociationFunction );
-
-        ModelModule<EntityModel> model = module.typeLookup().lookupEntityModel( type );
-
-        if( model == null )
-        {
-            throw new EntityTypeNotFoundException( type.getName(),
-                                                   module.name(),
-                                                   map( ModelModule.toStringFunction,
-                                                        module.findVisibleEntityTypes()
-                                                   ) );
-        }
-
-        EntityStore entityStore = model.module().entityStore();
-
-        FunctionStateResolver stateResolver = new FunctionStateResolver(
-            propertyFunction, associationFunction, manyAssociationFunction, namedAssociationFunction
-        );
-
-        if( identity == null )
-        {
-            // Use identity from StateResolver if available
-            PropertyModel identityModel = model.model().state().findPropertyModelByQualifiedName( IDENTITY_STATE_NAME );
-            identity = (String) stateResolver.getPropertyState( identityModel );
-            if( identity == null )
-            {
-                // Generate identity
-                IdentityGenerator idGen = model.module().identityGenerator();
-                if( idGen == null )
-                {
-                    throw new NoSuchServiceException( IdentityGenerator.class.getName(), model.module().name() );
-                }
-                identity = idGen.generate( first( model.model().types() ) );
-            }
-        }
-
-        return new EntityBuilderInstance<>( model,
-                                            this,
-                                            uow.getEntityStoreUnitOfWork( entityStore, module ),
-                                            identity,
-                                            stateResolver );
-    }
-
-    @Override
-    public <T> T get( Class<T> type, String identity )
-        throws EntityTypeNotFoundException, NoSuchEntityException
-    {
-        Iterable<ModelModule<EntityModel>> models = module.typeLookup().lookupEntityModels( type );
-
-        if( !models.iterator().hasNext() )
-        {
-            throw new EntityTypeNotFoundException( type.getName(),
-                                                   module.name(),
-                                                   map( ModelModule.toStringFunction,
-                                                        module.findVisibleEntityTypes()
-                                                   ) );
-        }
-
-        return uow.get( parseEntityReference( identity ), this, models, type );
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public <T> T get( T entity )
-        throws EntityTypeNotFoundException
-    {
-        EntityComposite entityComposite = (EntityComposite) entity;
-        EntityInstance compositeInstance = EntityInstance.entityInstanceOf( entityComposite );
-        ModelModule<EntityModel> model = new ModelModule<>( compositeInstance.module(), compositeInstance.entityModel() );
-        Class<T> type = (Class<T>) first( compositeInstance.types() );
-        return uow.get( compositeInstance.identity(), this, Collections.singletonList( model ), type );
-    }
-
-    @Override
-    public void remove( Object entity )
-        throws LifecycleException
-    {
-        uow.checkOpen();
-
-        EntityComposite entityComposite = (EntityComposite) entity;
-
-        EntityInstance compositeInstance = EntityInstance.entityInstanceOf( entityComposite );
-
-        if( compositeInstance.status() == EntityStatus.NEW )
-        {
-            compositeInstance.remove( this );
-            uow.remove( compositeInstance.identity() );
-        }
-        else if( compositeInstance.status() == EntityStatus.LOADED || compositeInstance.status() == EntityStatus.UPDATED )
-        {
-            compositeInstance.remove( this );
-        }
-        else
-        {
-            throw new NoSuchEntityException( compositeInstance.identity(), compositeInstance.types(), usecase() );
-        }
-    }
-
-    @SuppressWarnings( "DuplicateThrows" )
-    @Override
-    public void complete()
-        throws UnitOfWorkCompletionException, ConcurrentEntityModificationException
-    {
-        uow.complete();
-    }
-
-    @Override
-    public void discard()
-    {
-        uow.discard();
-    }
-
-    @Override
-    public void close()
-    {
-        discard();
-    }
-
-    @Override
-    public boolean isOpen()
-    {
-        return uow.isOpen();
-    }
-
-    @Override
-    public boolean isPaused()
-    {
-        return uow.isPaused();
-    }
-
-    @Override
-    public void pause()
-    {
-        uow.pause();
-    }
-
-    @Override
-    public void resume()
-    {
-        uow.resume();
-    }
-
-    @Override
-    public void addUnitOfWorkCallback( UnitOfWorkCallback callback )
-    {
-        uow.addUnitOfWorkCallback( callback );
-    }
-
-    @Override
-    public void removeUnitOfWorkCallback( UnitOfWorkCallback callback )
-    {
-        uow.removeUnitOfWorkCallback( callback );
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-
-        ModuleUnitOfWork that = (ModuleUnitOfWork) o;
-
-        return uow.equals( that.uow );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return uow.hashCode();
-    }
-
-    @Override
-    public String toString()
-    {
-        return uow.toString();
-    }
-
-    public void addEntity( EntityInstance instance )
-    {
-        uow.addEntity( instance );
-    }
-
-    @Override
-    public <T extends Identity> T toValue( Class<T> primaryType, T entityComposite )
-    {
-        Function<PropertyDescriptor, Object> propertyFunction = new ToValuePropertyMappingFunction( entityComposite );
-        Function<AssociationDescriptor, EntityReference> assocationFunction = new ToValueAssociationMappingFunction<>( entityComposite );
-        Function<AssociationDescriptor, Iterable<EntityReference>> manyAssocFunction = new ToValueManyAssociationMappingFunction<>( entityComposite );
-        Function<AssociationDescriptor, Map<String, EntityReference>> namedAssocFunction = new ToValueNameAssociationMappingFunction<>( entityComposite );
-
-        @SuppressWarnings( "unchecked" )
-        ValueBuilder<T> builder = module().newValueBuilderWithState(
-            primaryType, propertyFunction, assocationFunction, manyAssocFunction, namedAssocFunction );
-        return builder.newInstance();
-    }
-
-    @Override
-    public <T extends Identity> T toEntity( Class<T> primaryType, T valueComposite )
-    {
-        Function<PropertyDescriptor, Object> propertyFunction = new ToEntityPropertyMappingFunction<>( valueComposite );
-        Function<AssociationDescriptor, EntityReference> assocationFunction = new ToEntityAssociationMappingFunction<>( valueComposite );
-        Function<AssociationDescriptor, Iterable<EntityReference>> manyAssocFunction = new ToEntityManyAssociationMappingFunction<>( valueComposite );
-        Function<AssociationDescriptor, Map<String, EntityReference>> namedAssocFunction = new ToEntityNameAssociationMappingFunction<>( valueComposite );
-
-        String identity = valueComposite.identity().get();
-        try
-        {
-            T entity = get( primaryType, identity );
-            // If successful, then this entity is to by modified.
-            EntityInstance instance = EntityInstance.entityInstanceOf( (EntityComposite) entity );
-            EntityState state = instance.entityState();
-            FunctionStateResolver stateResolver = new FunctionStateResolver( propertyFunction,
-                                                                             assocationFunction,
-                                                                             manyAssocFunction,
-                                                                             namedAssocFunction );
-            EntityModel model = (EntityModel) EntityInstance.entityInstanceOf( (EntityComposite) entity ).descriptor();
-            stateResolver.populateState( model, state );
-            return entity;
-        }
-        catch( NoSuchEntityException e )
-        {
-            EntityBuilder<T> entityBuilder = newEntityBuilderWithState( primaryType,
-                                                                        identity,
-                                                                        propertyFunction,
-                                                                        assocationFunction,
-                                                                        manyAssocFunction,
-                                                                        namedAssocFunction );
-            return entityBuilder.newInstance();
-        }
-    }
-
-    private static class UoWQuerySource implements QuerySource
-    {
-        private final ModuleUnitOfWork moduleUnitOfWork;
-
-        private UoWQuerySource( ModuleUnitOfWork moduleUnitOfWork )
-        {
-            this.moduleUnitOfWork = moduleUnitOfWork;
-        }
-
-        @Override
-        public <T> T find( Class<T> resultType,
-                           Specification<Composite> whereClause,
-                           Iterable<OrderBy> orderBySegments,
-                           Integer firstResult,
-                           Integer maxResults,
-                           Map<String, Object> variables
-        )
-        {
-            final EntityFinder entityFinder = moduleUnitOfWork.module().findService( EntityFinder.class ).get();
-
-            try
-            {
-                final EntityReference foundEntity = entityFinder.findEntity( resultType, whereClause, variables == null ? Collections
-                    .<String, Object>emptyMap() : variables );
-                if( foundEntity != null )
-                {
-                    try
-                    {
-                        return moduleUnitOfWork.get( resultType, foundEntity.identity() );
-                    }
-                    catch( NoSuchEntityException e )
-                    {
-                        return null; // Index is out of sync - entity has been removed
-                    }
-                }
-                // No entity was found
-                return null;
-            }
-            catch( EntityFinderException e )
-            {
-                throw new QueryExecutionException( "Finder caused exception", e );
-            }
-        }
-
-        @Override
-        public <T> long count( Class<T> resultType,
-                               Specification<Composite> whereClause,
-                               Iterable<OrderBy> orderBySegments,
-                               Integer firstResult,
-                               Integer maxResults,
-                               Map<String, Object> variables
-        )
-        {
-            final EntityFinder entityFinder = moduleUnitOfWork.module().findService( EntityFinder.class ).get();
-
-            try
-            {
-                return entityFinder.countEntities( resultType, whereClause, variables == null ? Collections.<String, Object>emptyMap() : variables );
-            }
-            catch( EntityFinderException e )
-            {
-                e.printStackTrace();
-                return 0;
-            }
-        }
-
-        @Override
-        public <T> Iterator<T> iterator( final Class<T> resultType,
-                                         Specification<Composite> whereClause,
-                                         Iterable<OrderBy> orderBySegments,
-                                         Integer firstResult,
-                                         Integer maxResults,
-                                         Map<String, Object> variables
-        )
-        {
-            final EntityFinder entityFinder = moduleUnitOfWork.module().findService( EntityFinder.class ).get();
-
-            try
-            {
-                final Iterator<EntityReference> foundEntities = entityFinder.findEntities( resultType,
-                                                                                           whereClause,
-                                                                                           Iterables.toArray( OrderBy.class, orderBySegments ),
-                                                                                           firstResult,
-                                                                                           maxResults,
-                                                                                           variables == null ? Collections
-                                                                                               .<String, Object>emptyMap() : variables )
-                    .iterator();
-
-                return new Iterator<T>()
-                {
-                    @Override
-                    public boolean hasNext()
-                    {
-                        return foundEntities.hasNext();
-                    }
-
-                    @Override
-                    public T next()
-                    {
-                        final EntityReference foundEntity = foundEntities.next();
-                        try
-                        {
-                            return moduleUnitOfWork.get( resultType, foundEntity.identity() );
-                        }
-                        catch( NoSuchEntityException e )
-                        {
-                            // Index is out of sync - entity has been removed
-                            return null;
-                        }
-                    }
-
-                    @Override
-                    public void remove()
-                    {
-                        throw new UnsupportedOperationException();
-                    }
-                };
-            }
-            catch( EntityFinderException e )
-            {
-                throw new QueryExecutionException( "Query '" + toString() + "' could not be executed", e );
-            }
-        }
-
-        @Override
-        public String toString()
-        {
-            return "UnitOfWork( " + moduleUnitOfWork.usecase().name() + " )";
-        }
-    }
-
-    private class ToValuePropertyMappingFunction
-        implements Function<PropertyDescriptor, Object>
-    {
-        private Object entity;
-
-        public ToValuePropertyMappingFunction( Object entity )
-        {
-            this.entity = entity;
-        }
-
-        @Override
-        public Object map( PropertyDescriptor propertyDescriptor )
-        {
-            EntityState entityState = EntityInstance.entityInstanceOf( (EntityComposite) entity ).entityState();
-            return entityState.propertyValueOf( propertyDescriptor.qualifiedName() );
-        }
-    }
-
-    private class ToValueAssociationMappingFunction<T>
-        implements Function<AssociationDescriptor, EntityReference>
-    {
-        private final T entity;
-
-        public ToValueAssociationMappingFunction( T entity )
-        {
-            this.entity = entity;
-        }
-
-        @Override
-        public EntityReference map( AssociationDescriptor associationDescriptor )
-        {
-            EntityState entityState = EntityInstance.entityInstanceOf( (EntityComposite) entity ).entityState();
-            return entityState.associationValueOf( associationDescriptor.qualifiedName() );
-        }
-    }
-
-    private class ToValueManyAssociationMappingFunction<T>
-        implements Function<AssociationDescriptor, Iterable<EntityReference>>
-    {
-        private final T entity;
-
-        public ToValueManyAssociationMappingFunction( T entity )
-        {
-            this.entity = entity;
-        }
-
-        @Override
-        public Iterable<EntityReference> map( AssociationDescriptor associationDescriptor )
-        {
-            EntityState entityState = EntityInstance.entityInstanceOf( (EntityComposite) entity ).entityState();
-            return entityState.manyAssociationValueOf( associationDescriptor.qualifiedName() );
-        }
-    }
-
-    private class ToValueNameAssociationMappingFunction<T>
-        implements Function<AssociationDescriptor, Map<String, EntityReference>>
-    {
-        private final T entity;
-
-        public ToValueNameAssociationMappingFunction( T entity )
-        {
-            this.entity = entity;
-        }
-
-        @Override
-        public Map<String, EntityReference> map( AssociationDescriptor associationDescriptor )
-        {
-            Map<String, EntityReference> result = new HashMap<>();
-            EntityState entityState = EntityInstance.entityInstanceOf( (EntityComposite) entity ).entityState();
-            final NamedAssociationState state = entityState.namedAssociationValueOf( associationDescriptor.qualifiedName() );
-            for( String name : state )
-            {
-                result.put( name, state.get( name ) );
-            }
-            return result;
-        }
-    }
-
-    private class ToEntityPropertyMappingFunction<T>
-        implements Function<PropertyDescriptor, Object>
-    {
-        private final T value;
-
-        public ToEntityPropertyMappingFunction( T value )
-        {
-            this.value = value;
-        }
-
-        @Override
-        public Object map( PropertyDescriptor propertyDescriptor )
-        {
-            StateHolder state = ValueInstance.valueInstanceOf( (ValueComposite) value ).state();
-            Property<Object> property = state.propertyFor( propertyDescriptor.accessor() );
-            return property.get();
-        }
-    }
-
-    private class ToEntityAssociationMappingFunction<T>
-        implements Function<AssociationDescriptor, EntityReference>
-    {
-
-        private final T value;
-
-        public ToEntityAssociationMappingFunction( T value )
-        {
-            this.value = value;
-        }
-
-        @Override
-        public EntityReference map( AssociationDescriptor associationDescriptor )
-        {
-            AssociationStateHolder state = ValueInstance.valueInstanceOf( (ValueComposite) value ).state();
-            AssociationInstance<T> association = (AssociationInstance<T>) state.associationFor( associationDescriptor.accessor() );
-            return association.getAssociationState().get();
-        }
-    }
-
-    private class ToEntityManyAssociationMappingFunction<T>
-        implements Function<AssociationDescriptor, Iterable<EntityReference>>
-    {
-
-        private final T value;
-
-        public ToEntityManyAssociationMappingFunction( T valueComposite )
-        {
-            this.value = valueComposite;
-        }
-
-        @Override
-        public Iterable<EntityReference> map( AssociationDescriptor associationDescriptor )
-        {
-            AssociationStateHolder state = ValueInstance.valueInstanceOf( (ValueComposite) value ).state();
-            ManyAssociationInstance<T> association =
-                (ManyAssociationInstance<T>) state.manyAssociationFor( associationDescriptor.accessor() );
-            return association.getManyAssociationState();
-        }
-    }
-
-    private class ToEntityNameAssociationMappingFunction<T>
-        implements Function<AssociationDescriptor, Map<String, EntityReference>>
-    {
-        private final T value;
-
-        public ToEntityNameAssociationMappingFunction( T valueComposite )
-        {
-            this.value = valueComposite;
-        }
-
-        @Override
-        public Map<String, EntityReference> map( AssociationDescriptor associationDescriptor )
-        {
-            AssociationStateHolder state = ValueInstance.valueInstanceOf( (ValueComposite) value ).state();
-            NamedAssociationInstance<T> association =
-                (NamedAssociationInstance<T>) state.namedAssociationFor( associationDescriptor.accessor() );
-            HashMap<String, EntityReference> result = new HashMap<>();
-            for( Map.Entry<String, EntityReference> entry : association.getEntityReferences() )
-            {
-                result.put( entry.getKey(), entry.getValue() );
-            }
-            return result;
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/structure/TypeLookup.java b/core/runtime/src/main/java/org/qi4j/runtime/structure/TypeLookup.java
deleted file mode 100644
index 91b49ff..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/structure/TypeLookup.java
+++ /dev/null
@@ -1,629 +0,0 @@
-/*
- * Copyright (c) 2008-2012, Rickard Öberg.
- * Copyright (c) 2008-2012, Niclas Hedhman.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed  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.qi4j.runtime.structure;
-
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.lang.reflect.WildcardType;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import org.qi4j.api.composite.AmbiguousTypeException;
-import org.qi4j.api.composite.ModelDescriptor;
-import org.qi4j.api.service.NoSuchServiceException;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.Specifications;
-import org.qi4j.runtime.composite.TransientModel;
-import org.qi4j.runtime.entity.EntityModel;
-import org.qi4j.runtime.object.ObjectModel;
-import org.qi4j.runtime.value.ValueModel;
-import org.qi4j.spi.module.ModelModule;
-
-import static org.qi4j.api.common.Visibility.application;
-import static org.qi4j.api.common.Visibility.layer;
-import static org.qi4j.api.common.Visibility.module;
-import static org.qi4j.api.util.Classes.RAW_CLASS;
-import static org.qi4j.api.util.Classes.interfacesOf;
-import static org.qi4j.functional.Iterables.cast;
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.flatten;
-import static org.qi4j.functional.Iterables.flattenIterables;
-import static org.qi4j.functional.Iterables.iterable;
-import static org.qi4j.functional.Iterables.toList;
-import static org.qi4j.functional.Iterables.unique;
-
-/**
- * Central place for Composite Type lookups.
- */
-public class TypeLookup
-{
-
-    // Constructor parameters
-    private final ModuleInstance moduleInstance;
-    // Eager instance objects
-    private final Map<Class<?>, ModelModule<ObjectModel>> objectModels;
-    private final Map<Class<?>, ModelModule<TransientModel>> transientModels;
-    private final Map<Class<?>, ModelModule<ValueModel>> valueModels;
-    private final Map<Class<?>, Iterable<ModelModule<EntityModel>>> allEntityModels;
-    private final Map<Class<?>, ModelModule<EntityModel>> unambiguousEntityModels;
-    private final Map<Type, ServiceReference<?>> serviceReferences;
-    private final Map<Type, Iterable<ServiceReference<?>>> servicesReferences;
-
-    /**
-     * Create a new TypeLookup bound to the given ModuleInstance.
-     *
-     * @param moduleInstance ModuleInstance bound to this TypeLookup
-     */
-    /* package */ TypeLookup( ModuleInstance moduleInstance )
-    {
-        // Constructor parameters
-        this.moduleInstance = moduleInstance;
-
-        // Eager instance objects
-        objectModels = new ConcurrentHashMap<>();
-        transientModels = new ConcurrentHashMap<>();
-        valueModels = new ConcurrentHashMap<>();
-        allEntityModels = new ConcurrentHashMap<>();
-        unambiguousEntityModels = new ConcurrentHashMap<>();
-        serviceReferences = new ConcurrentHashMap<>();
-        servicesReferences = new ConcurrentHashMap<>();
-    }
-
-    /**
-     * Lookup first Object Model matching the given Type.
-     *
-     * <p>First, if Object Models exactly match the given type, the closest one (Visibility then Assembly order) is returned.
-     * Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
-     *
-     * <p>Second, if Object Models match a type assignable to the given type, the closest one (Visibility then Assembly order) is returned.
-     * Multiple <b>assignable</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
-     *
-     * <p>Type lookup is done lazily and cached.</p>
-     *
-     * @param type Looked up Type
-     *
-     * @return First matching Object Model
-     */
-    @SuppressWarnings( { "raw", "unchecked" } )
-    /* package */ ModelModule<ObjectModel> lookupObjectModel( final Class type )
-    {
-        ModelModule<ObjectModel> model = objectModels.get( type );
-
-        if( model == null )
-        {
-            // Unambiguously and lazily resolve ObjectModel
-            Iterable<ModelModule<ObjectModel>> flatten = flatten(
-                ambiguousTypeCheck( type,
-                                    findModels( new ExactTypeLookupSpecification( type ),
-                                                moduleInstance.visibleObjects( module ),
-                                                moduleInstance.layerInstance().visibleObjects( layer ),
-                                                moduleInstance.layerInstance().visibleObjects( application ),
-                                                moduleInstance.layerInstance()
-                                                    .usedLayersInstance()
-                                                    .visibleObjects() ) ),
-                ambiguousTypeCheck( type,
-                                    findModels( new AssignableTypeLookupSpecification( type ),
-                                                moduleInstance.visibleObjects( module ),
-                                                moduleInstance.layerInstance().visibleObjects( layer ),
-                                                moduleInstance.layerInstance().visibleObjects( application ),
-                                                moduleInstance.layerInstance()
-                                                    .usedLayersInstance()
-                                                    .visibleObjects() ) ) );
-
-            model = first( flatten );
-
-            if( model != null )
-            {
-                objectModels.put( type, model );
-            }
-        }
-
-        return model;
-    }
-
-    /**
-     * Lookup first Transient Model matching the given Type.
-     *
-     * <p>First, if Transient Models exactly match the given type, the closest one (Visibility then Assembly order) is returned.
-     * Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
-     *
-     * <p>Second, if Transient Models match a type assignable to the given type, the closest one (Visibility then Assembly order) is returned.
-     * Multiple <b>assignable</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
-     *
-     * <p>Type lookup is done lazily and cached.</p>
-     *
-     * @param type Looked up Type
-     *
-     * @return First matching Transient Model
-     */
-    @SuppressWarnings( { "raw", "unchecked" } )
-    /* package */ ModelModule<TransientModel> lookupTransientModel( final Class type )
-    {
-        ModelModule<TransientModel> model = transientModels.get( type );
-
-        if( model == null )
-        {
-            // Unambiguously and lazily resolve TransientModel
-            Iterable<ModelModule<TransientModel>> allModels = flatten(
-                ambiguousTypeCheck( type,
-                                    findModels( new ExactTypeLookupSpecification( type ),
-                                                moduleInstance.visibleTransients( module ),
-                                                moduleInstance.layerInstance().visibleTransients( layer ),
-                                                moduleInstance.layerInstance().visibleTransients( application ),
-                                                moduleInstance.layerInstance().usedLayersInstance().visibleTransients()
-                                    )
-                ),
-
-                ambiguousTypeCheck( type,
-                                    findModels( new AssignableTypeLookupSpecification( type ),
-                                                moduleInstance.visibleTransients( module ),
-                                                moduleInstance.layerInstance().visibleTransients( layer ),
-                                                moduleInstance.layerInstance().visibleTransients( application ),
-                                                moduleInstance.layerInstance().usedLayersInstance().visibleTransients()
-                                    )
-                )
-            );
-            model = first( allModels );
-
-            if( model != null )
-            {
-                transientModels.put( type, model );
-            }
-        }
-
-        return model;
-    }
-
-    /**
-     * Lookup first Value Model matching the given Type.
-     *
-     * <p>First, if Value Models exactly match the given type, the closest one (Visibility then Assembly order) is returned.
-     * Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
-     *
-     * <p>Second, if Value Models match a type assignable to the given type, the closest one (Visibility then Assembly order) is returned.
-     * Multiple <b>assignable</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
-     *
-     * <p>Type lookup is done lazily and cached.</p>
-     *
-     * @param type Looked up Type
-     *
-     * @return First matching Value Model
-     */
-    @SuppressWarnings( { "raw", "unchecked" } )
-    public ModelModule<ValueModel> lookupValueModel( final Class type )
-    {
-        ModelModule<ValueModel> model = valueModels.get( type );
-
-        if( model == null )
-        {
-            // Unambiguously and lazily resolve ValueModel
-            Iterable<ModelModule<ValueModel>> flatten = flatten(
-                ambiguousTypeCheck( type,
-                                    findModels( new ExactTypeLookupSpecification( type ),
-                                                moduleInstance.visibleValues( module ),
-                                                moduleInstance.layerInstance().visibleValues( layer ),
-                                                moduleInstance.layerInstance().visibleValues( application ),
-                                                moduleInstance.layerInstance().usedLayersInstance().visibleValues() ) ),
-                ambiguousTypeCheck( type,
-                                    findModels( new AssignableTypeLookupSpecification( type ),
-                                                moduleInstance.visibleValues( module ),
-                                                moduleInstance.layerInstance().visibleValues( layer ),
-                                                moduleInstance.layerInstance().visibleValues( application ),
-                                                moduleInstance.layerInstance().usedLayersInstance().visibleValues()
-                                    )
-                )
-            );
-
-            model = first( flatten );
-
-            if( model != null )
-            {
-                valueModels.put( type, model );
-            }
-        }
-
-        return model;
-    }
-
-    /**
-     * Lookup first Entity Model matching the given Type.
-     *
-     * <p>First, if Entity Models exactly match the given type, the closest one (Visibility then Assembly order) is returned.
-     * Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
-     *
-     * <p>Second, if Entity Models match a type assignable to the given type, the closest one (Visibility then Assembly order) is returned.
-     * Multiple <b>assignable</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
-     *
-     * <p>Type lookup is done lazily and cached.</p>
-     *
-     * <p><b>Should be used for creational use cases only.</b> For non-creational use cases see
-     * {@link #lookupEntityModels(java.lang.Class)}.</p>
-     *
-     * @param type Looked up Type
-     *
-     * @return First matching Entity Model
-     */
-    @SuppressWarnings( { "raw", "unchecked" } )
-    /* package */ ModelModule<EntityModel> lookupEntityModel( final Class type )
-    {
-        ModelModule<EntityModel> model = unambiguousEntityModels.get( type );
-
-        if( model == null )
-        {
-            // Unambiguously and lazily resolve EntityModels
-            Iterable<ModelModule<EntityModel>> allModels = flatten(
-                ambiguousTypeCheck( type,
-                                    findModels( new ExactTypeLookupSpecification( type ),
-                                                moduleInstance.visibleEntities( module ),
-                                                moduleInstance.layerInstance().visibleEntities( layer ),
-                                                moduleInstance.layerInstance().visibleEntities( application ),
-                                                moduleInstance.layerInstance()
-                                                    .usedLayersInstance()
-                                                    .visibleEntities() ) ),
-                ambiguousTypeCheck( type,
-                                    findModels( new AssignableTypeLookupSpecification( type ),
-                                                moduleInstance.visibleEntities( module ),
-                                                moduleInstance.layerInstance().visibleEntities( layer ),
-                                                moduleInstance.layerInstance().visibleEntities( application ),
-                                                moduleInstance.layerInstance().usedLayersInstance().visibleEntities()
-                                    )
-                )
-            );
-
-            model = first( allModels );
-
-            if( model != null )
-            {
-                unambiguousEntityModels.put( type, model );
-            }
-        }
-
-        return model;
-    }
-
-    /**
-     * Lookup all Entity Models matching the given Type.
-     *
-     * <p>Returned Iterable contains, in order, Entity Models that: </p>
-     *
-     * <ul>
-     * <li>exactly match the given type, in Visibility then Assembly order ;</li>
-     * <li>match a type assignable to the given type, in Visibility then Assembly order.</li>
-     * </ul>
-     *
-     * <p>Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
-     * <p>Multiple <b>assignable</b> matches are <b>allowed</b> to enable polymorphic fetches and queries.</p>
-     *
-     * <p>Type lookup is done lazily and cached.</p>
-     *
-     * <p><b>Should be used for non-creational use cases only.</b> For creational use cases see
-     * {@link #lookupEntityModel(java.lang.Class)}.</p>
-     *
-     * @param type Looked up Type
-     *
-     * @return All matching Entity Models
-     */
-    @SuppressWarnings( { "raw", "unchecked" } )
-    /* package */ Iterable<ModelModule<EntityModel>> lookupEntityModels( final Class type )
-    {
-        Iterable<ModelModule<EntityModel>> models = allEntityModels.get( type );
-        if( models == null )
-        {
-            // Ambiguously and lasily resolve EntityModels
-            Iterable<ModelModule<EntityModel>> matchingEntityModels = flatten(
-                ambiguousTypeCheck( type,
-                                    findModels( new ExactTypeLookupSpecification( type ),
-                                                moduleInstance.visibleEntities( module ),
-                                                moduleInstance.layerInstance().visibleEntities( layer ),
-                                                moduleInstance.layerInstance().visibleEntities( application ),
-                                                moduleInstance.layerInstance().usedLayersInstance().visibleEntities()
-                                    )
-                ),
-                findModels( new AssignableTypeLookupSpecification( type ),
-                            moduleInstance.visibleEntities( module ),
-                            moduleInstance.layerInstance().visibleEntities( layer ),
-                            moduleInstance.layerInstance().visibleEntities( application ),
-                            moduleInstance.layerInstance().usedLayersInstance().visibleEntities() ) );
-
-            // Don't return the same EntityModel multiple times
-            matchingEntityModels = unique( matchingEntityModels );
-
-            models = toList( matchingEntityModels );
-            allEntityModels.put( type, models );
-        }
-        return models;
-    }
-
-    /**
-     * Lookup first ServiceReference matching the given Type.
-     *
-     * <p>Type lookup is done lazily and cached.</p>
-     *
-     * <p>See {@link #lookupServiceReferences(java.lang.reflect.Type)}.</p>
-     *
-     * @param <T>         Service Type
-     * @param serviceType Looked up Type
-     *
-     * @return First matching ServiceReference
-     */
-    /* package */
-    @SuppressWarnings( "unchecked" )
-    <T> ServiceReference<T> lookupServiceReference( Type serviceType )
-    {
-        ServiceReference<?> serviceReference = serviceReferences.get( serviceType );
-        if( serviceReference == null )
-        {
-            // Lazily resolve ServiceReference
-            serviceReference = first( lookupServiceReferences( serviceType ) );
-            if( serviceReference != null )
-            {
-                serviceReferences.put( serviceType, serviceReference );
-            }
-        }
-
-        if( serviceReference == null )
-        {
-            throw new NoSuchServiceException( RAW_CLASS.map( serviceType ).getName(), moduleInstance.name() );
-        }
-
-        return (ServiceReference<T>) serviceReference;
-    }
-
-    /**
-     * Lookup all ServiceReferences matching the given Type.
-     *
-     * <p>Returned Iterable contains, in order, ServiceReferences that: </p>
-     *
-     * <ul>
-     * <li>exactly match the given type, in Visibility then Assembly order ;</li>
-     * <li>match a type assignable to the given type, in Visibility then Assembly order.</li>
-     * </ul>
-     *
-     * <p>Multiple <b>exact</b> matches with the same Visibility are <b>allowed</b> to enable polymorphic lookup/injection.</p>
-     * <p>Multiple <b>assignable</b> matches with the same Visibility are <b>allowed</b> for the very same reason.</p>
-     *
-     * <p>Type lookup is done lazily and cached.</p>
-     *
-     * @param <T>         Service Type
-     * @param serviceType Looked up Type
-     *
-     * @return All matching ServiceReferences
-     */
-    @SuppressWarnings( "unchecked" )
-    /* package */ <T> Iterable<ServiceReference<T>> lookupServiceReferences( final Type serviceType )
-    {
-        Iterable<ServiceReference<?>> serviceRefs = servicesReferences.get( serviceType );
-        if( serviceRefs == null )
-        {
-            // Lazily resolve ServicesReferences
-            Iterable<ServiceReference<?>> matchingServices = flatten(
-                findServiceReferences( new ExactTypeLookupSpecification( serviceType ),
-                                       moduleInstance.visibleServices( module ),
-                                       moduleInstance.layerInstance().visibleServices( layer ),
-                                       moduleInstance.layerInstance().visibleServices( application ),
-                                       moduleInstance.layerInstance().usedLayersInstance().visibleServices() ),
-                findServiceReferences( new AssignableTypeLookupSpecification( serviceType ),
-                                       moduleInstance.visibleServices( module ),
-                                       moduleInstance.layerInstance().visibleServices( layer ),
-                                       moduleInstance.layerInstance().visibleServices( application ),
-                                       moduleInstance.layerInstance().usedLayersInstance().visibleServices() ) );
-
-            // Don't return the same ServiceReference multiple times
-            matchingServices = unique( matchingServices );
-
-            serviceRefs = toList( matchingServices );
-            servicesReferences.put( serviceType, serviceRefs );
-        }
-
-        return cast( serviceRefs );
-    }
-
-    @SuppressWarnings( { "raw", "unchecked" } )
-    private static <T extends ModelDescriptor> Iterable<ModelModule<T>> findModels( Specification<Iterable<Class<?>>> specification,
-                                                                                    Iterable<ModelModule<T>>... models
-    )
-    {
-        Specification<ModelModule<T>> spec = Specifications.translate( new ModelModuleTypesFunction(), specification );
-        Iterable<ModelModule<T>> flattened = flattenIterables( iterable( models ) );
-        return filter( spec, flattened );
-    }
-
-    @SuppressWarnings( { "raw", "unchecked" } )
-    private static Iterable<ServiceReference<?>> findServiceReferences( Specification<Iterable<Class<?>>> specification,
-                                                                        Iterable<ServiceReference<?>>... references
-    )
-    {
-        Specification<ServiceReference<?>> spec = Specifications.translate( new ServiceReferenceTypesFunction(), specification );
-        Iterable<ServiceReference<?>> flattened = flattenIterables( iterable( references ) );
-        return filter( spec, flattened );
-    }
-
-    /**
-     * Check if the list of models contains several ones with the same visibility. If yes, then
-     * throw an AmbiguousTypeException
-     */
-    @SuppressWarnings( "raw" )
-    private static <T extends ModelDescriptor> Iterable<ModelModule<T>> ambiguousTypeCheck( final Class type,
-                                                                                            final Iterable<ModelModule<T>> models
-    )
-    {
-        return new Iterable<ModelModule<T>>()
-        {
-
-            @Override
-            public Iterator<ModelModule<T>> iterator()
-            {
-                ModelModule<T> current = null;
-                List<ModelModule<T>> ambiguous = null;
-                List<ModelModule<T>> results = new ArrayList<>();
-                for( ModelModule<T> model : models )
-                {
-                    if( current != null && !model.equals( current ) )
-                    {
-                        if( model.model().visibility() == current.model().visibility() )
-                        {
-                            if( ambiguous == null )
-                            {
-                                ambiguous = new ArrayList<>();
-                            }
-                            ambiguous.add( model );
-                        }
-                    }
-                    else
-                    {
-                        current = model;
-                    }
-                    results.add( model );
-                }
-                if( ambiguous != null )
-                {
-                    // Check if we had any ambiguities
-                    ambiguous.add( current );
-                    throw new AmbiguousTypeException( "More than one type matches " + type.getName() + ":" + ambiguous );
-                }
-                // Ambiguity check done, and no ambiguities found. Return results
-                return results.iterator();
-            }
-        };
-    }
-
-    private static class ModelModuleTypesFunction<T extends ModelDescriptor>
-        implements Function<ModelModule<T>, Iterable<Class<?>>>
-    {
-
-        @Override
-        public Iterable<Class<?>> map( ModelModule<T> modelModule )
-        {
-            return modelModule.model().types();
-        }
-    }
-
-    private static class ServiceReferenceTypesFunction
-        implements Function<ServiceReference<?>, Iterable<Class<?>>>
-    {
-
-        @Override
-        public Iterable<Class<?>> map( ServiceReference<?> serviceReference )
-        {
-            return serviceReference.types();
-        }
-    }
-
-    private static abstract class AbstractTypeLookupSpecification
-        implements Specification<Iterable<Class<?>>>
-    {
-
-        protected final Type lookedUpType;
-
-        private AbstractTypeLookupSpecification( Type lookedUpType )
-        {
-            this.lookedUpType = lookedUpType;
-        }
-
-        @Override
-        public final boolean satisfiedBy( Iterable<Class<?>> types )
-        {
-            if( lookedUpType instanceof Class )
-            {
-                // Straight class assignability check
-                return checkClassMatch( types, (Class) lookedUpType );
-            }
-            else
-            {
-                if( lookedUpType instanceof ParameterizedType )
-                {
-                    // Foo<Bar> check
-                    // First check Foo
-                    ParameterizedType parameterizedType = (ParameterizedType) lookedUpType;
-                    if( !checkClassMatch( types, (Class) parameterizedType.getRawType() ) )
-                    {
-                        return false;
-                    }
-                    // Then check Bar
-                    for( Type intf : interfacesOf( types ) )
-                    {
-                        if( intf.equals( lookedUpType ) )
-                        {
-                            // All parameters are the same - ok!
-                            return true;
-                        }
-                    }
-                    return false;
-                }
-                else if( lookedUpType instanceof WildcardType )
-                {
-                    return true;
-                }
-                return false;
-            }
-        }
-
-        private boolean checkClassMatch( Iterable<Class<?>> candidates, Class<?> lookedUpType )
-        {
-            for( Class<?> candidate : candidates )
-            {
-                if( checkClassMatch( candidate, lookedUpType ) )
-                {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        protected abstract boolean checkClassMatch( Class<?> candidate, Class<?> lookedUpType );
-    }
-
-    private static final class ExactTypeLookupSpecification
-        extends AbstractTypeLookupSpecification
-    {
-
-        private ExactTypeLookupSpecification( Type lookedupType )
-        {
-            super( lookedupType );
-        }
-
-        @Override
-        protected boolean checkClassMatch( Class<?> candidate, Class<?> lookedUpType )
-        {
-            return candidate.equals( lookedUpType );
-        }
-    }
-
-    private static final class AssignableTypeLookupSpecification
-        extends AbstractTypeLookupSpecification
-    {
-
-        private AssignableTypeLookupSpecification( Type lookedupType )
-        {
-            super( lookedupType );
-        }
-
-        @Override
-        protected boolean checkClassMatch( Class<?> candidate, Class<?> lookedUpType )
-        {
-            return !candidate.equals( lookedUpType ) && lookedUpType.isAssignableFrom( candidate );
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/structure/UsedLayersInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/structure/UsedLayersInstance.java
deleted file mode 100644
index 7eb57b9..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/structure/UsedLayersInstance.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.structure;
-
-import java.util.List;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.TransientDescriptor;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.object.ObjectDescriptor;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.functional.Function;
-import org.qi4j.runtime.composite.TransientModel;
-import org.qi4j.runtime.entity.EntityModel;
-import org.qi4j.runtime.object.ObjectModel;
-import org.qi4j.runtime.value.ValueModel;
-import org.qi4j.spi.module.ModelModule;
-
-import static org.qi4j.functional.Iterables.*;
-
-/**
- * JAVADOC
- */
-public final class UsedLayersInstance
-{
-    private final List<LayerInstance> usedLayerInstances;
-
-    public UsedLayersInstance( List<LayerInstance> usedLayerInstances )
-    {
-        this.usedLayerInstances = usedLayerInstances;
-    }
-
-    /* package */ Iterable<ModelModule<ObjectDescriptor>> visibleObjects()
-    {
-        return flattenIterables( map( new Function<LayerInstance, Iterable<ModelModule<ObjectDescriptor>>>()
-        {
-            @Override
-            public Iterable<ModelModule<ObjectDescriptor>> map( LayerInstance layerInstance )
-            {
-                return layerInstance.visibleObjects( Visibility.application );
-            }
-        }, usedLayerInstances ) );
-    }
-
-    /* package */ Iterable<ModelModule<TransientDescriptor>> visibleTransients()
-    {
-        return flattenIterables( map( new Function<LayerInstance, Iterable<ModelModule<TransientDescriptor>>>()
-        {
-            @Override
-            public Iterable<ModelModule<TransientDescriptor>> map( LayerInstance layerInstance )
-            {
-                return layerInstance.visibleTransients( Visibility.application );
-            }
-        }, usedLayerInstances ) );
-    }
-
-    /* package */ Iterable<ModelModule<EntityDescriptor>> visibleEntities()
-    {
-        return flattenIterables( map( new Function<LayerInstance, Iterable<ModelModule<EntityDescriptor>>>()
-        {
-            @Override
-            public Iterable<ModelModule<EntityDescriptor>> map( LayerInstance layerInstance )
-            {
-                return layerInstance.visibleEntities( Visibility.application );
-            }
-        }, usedLayerInstances ) );
-    }
-
-    /* package */ Iterable<ModelModule<ValueDescriptor>> visibleValues()
-    {
-        return flattenIterables( map( new Function<LayerInstance, Iterable<ModelModule<ValueDescriptor>>>()
-        {
-            @Override
-            public Iterable<ModelModule<ValueDescriptor>> map( LayerInstance layerInstance )
-            {
-                return layerInstance.visibleValues( Visibility.application );
-            }
-        }, usedLayerInstances ) );
-    }
-
-    /* package */ Iterable<ServiceReference<?>> visibleServices()
-    {
-        return flattenIterables( map( new Function<LayerInstance, Iterable<ServiceReference<?>>>()
-        {
-            @Override
-            public Iterable<ServiceReference<?>> map( LayerInstance layerInstance )
-            {
-                return layerInstance.visibleServices( Visibility.application );
-            }
-        }, usedLayerInstances ) );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/structure/UsedLayersModel.java b/core/runtime/src/main/java/org/qi4j/runtime/structure/UsedLayersModel.java
deleted file mode 100644
index e0013d8..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/structure/UsedLayersModel.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.structure;
-
-import java.util.List;
-import org.qi4j.api.structure.UsedLayersDescriptor;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-
-/**
- * JAVADOC
- */
-public final class UsedLayersModel
-    implements UsedLayersDescriptor, VisitableHierarchy<Object, Object>
-{
-    private final List<LayerModel> usedLayers;
-
-    public UsedLayersModel( List<LayerModel> usedLayers )
-    {
-        this.usedLayers = usedLayers;
-    }
-
-    @Override
-    public Iterable<LayerModel> layers()
-    {
-        return usedLayers;
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( LayerModel usedLayer : usedLayers )
-            {
-                if( !usedLayer.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-        }
-
-        return visitor.visitLeave( this );
-    }
-
-    public UsedLayersInstance newInstance( List<LayerInstance> usedLayerInstances )
-    {
-        return new UsedLayersInstance( usedLayerInstances );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/structure/VisibilitySpecification.java b/core/runtime/src/main/java/org/qi4j/runtime/structure/VisibilitySpecification.java
deleted file mode 100644
index 3b57ad3..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/structure/VisibilitySpecification.java
+++ /dev/null
@@ -1,47 +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.qi4j.runtime.structure;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.ModelDescriptor;
-import org.qi4j.functional.Specification;
-
-/**
- * TODO
- */
-public class VisibilitySpecification
-    implements Specification<ModelDescriptor>
-{
-    public static final Specification<ModelDescriptor> MODULE = new VisibilitySpecification( Visibility.module );
-    public static final Specification<ModelDescriptor> LAYER = new VisibilitySpecification( Visibility.layer );
-    public static final Specification<ModelDescriptor> APPLICATION = new VisibilitySpecification( Visibility.application );
-
-    private final Visibility visibility;
-
-    public VisibilitySpecification( Visibility visibility )
-    {
-        this.visibility = visibility;
-    }
-
-    @Override
-    public boolean satisfiedBy( ModelDescriptor item )
-    {
-        return item.visibility().ordinal() >= visibility.ordinal();
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/types/ValueTypeFactory.java b/core/runtime/src/main/java/org/qi4j/runtime/types/ValueTypeFactory.java
deleted file mode 100644
index 9f49953..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/types/ValueTypeFactory.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.types;
-
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import org.qi4j.api.common.InvalidApplicationException;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.type.CollectionType;
-import org.qi4j.api.type.EnumType;
-import org.qi4j.api.type.MapType;
-import org.qi4j.api.type.Serialization;
-import org.qi4j.api.type.ValueCompositeType;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.api.util.Classes;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.functional.HierarchicalVisitorAdapter;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specifications;
-import org.qi4j.runtime.association.AssociationsModel;
-import org.qi4j.runtime.association.ManyAssociationsModel;
-import org.qi4j.runtime.association.NamedAssociationsModel;
-import org.qi4j.runtime.composite.CompositeMethodsModel;
-import org.qi4j.runtime.composite.MixinsModel;
-import org.qi4j.runtime.property.PropertiesModel;
-import org.qi4j.runtime.structure.LayerModel;
-import org.qi4j.runtime.structure.ModuleModel;
-import org.qi4j.runtime.structure.UsedLayersModel;
-import org.qi4j.runtime.value.ValueModel;
-import org.qi4j.runtime.value.ValueStateModel;
-import org.qi4j.runtime.value.ValuesModel;
-
-public class ValueTypeFactory
-{
-    private static final ValueTypeFactory instance = new ValueTypeFactory();
-
-    public static ValueTypeFactory instance()
-    {
-        return instance;
-    }
-
-    @SuppressWarnings( {"raw", "unchecked"} )
-    public ValueType newValueType( Type type,
-                                   Class declaringClass,
-                                   Class compositeType,
-                                   LayerModel layer,
-                                   ModuleModel module,
-                                   Serialization.Variant variant
-    )
-    {
-        ValueType valueType = null;
-        if( CollectionType.isCollection( type ) )
-        {
-            if( type instanceof ParameterizedType )
-            {
-                ParameterizedType pt = (ParameterizedType) type;
-                Type collectionType = pt.getActualTypeArguments()[ 0 ];
-                if( collectionType instanceof TypeVariable )
-                {
-                    TypeVariable collectionTypeVariable = (TypeVariable) collectionType;
-                    collectionType = Classes.resolveTypeVariable( collectionTypeVariable, declaringClass, compositeType );
-                }
-                ValueType collectedType = newValueType( collectionType, declaringClass, compositeType, layer, module, variant );
-                valueType = new CollectionType( Classes.RAW_CLASS.map( type ), collectedType );
-            }
-            else
-            {
-                ValueType collectedType = newValueType( Object.class, declaringClass, compositeType, layer, module, variant );
-                valueType = new CollectionType( Classes.RAW_CLASS.map( type ), collectedType );
-            }
-        }
-        else if( MapType.isMap( type ) )
-        {
-            if( type instanceof ParameterizedType )
-            {
-                ParameterizedType pt = (ParameterizedType) type;
-                Type keyType = pt.getActualTypeArguments()[ 0 ];
-                if( keyType instanceof TypeVariable )
-                {
-                    TypeVariable keyTypeVariable = (TypeVariable) keyType;
-                    keyType = Classes.resolveTypeVariable( keyTypeVariable, declaringClass, compositeType );
-                }
-                ValueType keyedType = newValueType( keyType, declaringClass, compositeType, layer, module, variant );
-                Type valType = pt.getActualTypeArguments()[ 1 ];
-                if( valType instanceof TypeVariable )
-                {
-                    TypeVariable valueTypeVariable = (TypeVariable) valType;
-                    valType = Classes.resolveTypeVariable( valueTypeVariable, declaringClass, compositeType );
-                }
-                ValueType valuedType = newValueType( valType, declaringClass, compositeType, layer, module, variant );
-                valueType = new MapType( Classes.RAW_CLASS.map( type ), keyedType, valuedType, variant );
-            }
-            else
-            {
-                ValueType keyType = newValueType( Object.class, declaringClass, compositeType, layer, module, variant );
-                ValueType valuesType = newValueType( Object.class, declaringClass, compositeType, layer, module, variant );
-                valueType = new MapType( Classes.RAW_CLASS.map( type ), keyType, valuesType, variant );
-            }
-        }
-        else if( ValueCompositeType.isValueComposite( type ) )
-        {
-            // Find ValueModel in module/layer/used layers
-            ValueModel model = new ValueFinder( layer, module, Classes.RAW_CLASS.map( type ) ).getFoundModel();
-
-            if( model == null )
-            {
-                if( type.equals( ValueComposite.class ) )
-                {
-                    // Create default model
-                    MixinsModel mixinsModel = new MixinsModel();
-                    Iterable valueComposite = (Iterable) Iterables.iterable( ValueComposite.class );
-                    ValueStateModel valueStateModel = new ValueStateModel( new PropertiesModel(),
-                                                                           new AssociationsModel(),
-                                                                           new ManyAssociationsModel(),
-                                                                           new NamedAssociationsModel() );
-                    model = new ValueModel( valueComposite, Visibility.application, new MetaInfo(),
-                                            mixinsModel, valueStateModel, new CompositeMethodsModel( mixinsModel ) );
-                }
-                else
-                {
-                    throw new InvalidApplicationException( "[" + module.name() + "] Could not find ValueComposite of type " + type );
-                }
-            }
-
-            return model.valueType();
-        }
-        else if( EnumType.isEnum( type ) )
-        {
-            valueType = new EnumType( Classes.RAW_CLASS.map( type ) );
-        }
-        else
-        {
-            valueType = new ValueType( Classes.RAW_CLASS.map( type ) );
-        }
-
-        return valueType;
-    }
-
-    @SuppressWarnings( "raw" )
-    private static class ValueFinder
-        extends HierarchicalVisitorAdapter<Object, Object, RuntimeException>
-    {
-        private Class type;
-        private ValueModel foundModel;
-        private Visibility visibility;
-
-        private ValueFinder( LayerModel layer, ModuleModel module, Class type )
-        {
-            this.type = type;
-
-            visibility = Visibility.module;
-            module.accept( this );
-
-            if( foundModel == null )
-            {
-                visibility = Visibility.layer;
-                layer.accept( this );
-
-                if( foundModel == null )
-                {
-                    visibility = Visibility.application;
-                    layer.usedLayers().accept( this );
-                }
-            }
-        }
-
-        public ValueModel getFoundModel()
-        {
-            return foundModel;
-        }
-
-        @Override
-        public boolean visitEnter( Object visited )
-            throws RuntimeException
-        {
-            if( visited instanceof ValuesModel )
-            {
-                return true;
-            }
-            else if( visited instanceof ModuleModel )
-            {
-                return true;
-            }
-            else if (visited instanceof LayerModel )
-            {
-                return true;
-            }
-            else if (visited instanceof UsedLayersModel )
-            {
-                return true;
-            }
-            else if( visited instanceof ValueModel )
-            {
-                ValueModel valueModel = (ValueModel) visited;
-                boolean typeEquality = Specifications.in( valueModel.types() ).satisfiedBy( type );
-                if( typeEquality && valueModel.visibility().ordinal() >= visibility.ordinal() )
-                {
-                    foundModel = valueModel;
-                }
-            }
-
-            return false;
-        }
-
-        @Override
-        public boolean visitLeave( Object visited )
-            throws RuntimeException
-        {
-            return foundModel == null;
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/BuilderEntityState.java b/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/BuilderEntityState.java
deleted file mode 100644
index 7c1388c..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/BuilderEntityState.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (c) 2009-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2009-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.unitofwork;
-
-import java.util.HashMap;
-import java.util.Map;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.util.Classes;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.EntityStatus;
-import org.qi4j.spi.entity.ManyAssociationState;
-import org.qi4j.spi.entity.NamedAssociationState;
-
-/**
- * Implementation of EntityState for use through EntityBuilder.
- */
-public final class BuilderEntityState
-    implements EntityState
-{
-    private final EntityDescriptor entityType;
-    private final EntityReference reference;
-    private final Map<QualifiedName, Object> properties = new HashMap<>();
-    private final Map<QualifiedName, EntityReference> associations = new HashMap<>();
-    private final Map<QualifiedName, ManyAssociationState> manyAssociations = new HashMap<>();
-    private final Map<QualifiedName, NamedAssociationState> namedAssociations = new HashMap<>();
-
-    public BuilderEntityState( EntityDescriptor type, EntityReference reference )
-    {
-        this.entityType = type;
-        this.reference = reference;
-    }
-
-    @Override
-    public EntityReference identity()
-    {
-        return reference;
-    }
-
-    @Override
-    public String version()
-    {
-        return "";
-    }
-
-    @Override
-    public long lastModified()
-    {
-        return 0;
-    }
-
-    @Override
-    public void remove()
-    {
-    }
-
-    @Override
-    public EntityStatus status()
-    {
-        return EntityStatus.NEW;
-    }
-
-    @Override
-    public boolean isAssignableTo( Class<?> type )
-    {
-        return Classes.exactTypeSpecification( type ).satisfiedBy( entityType );
-    }
-
-    @Override
-    public EntityDescriptor entityDescriptor()
-    {
-        return entityType;
-    }
-
-    @Override
-    public Object propertyValueOf( QualifiedName stateName )
-    {
-        return properties.get( stateName );
-    }
-
-    @Override
-    public EntityReference associationValueOf( QualifiedName stateName )
-    {
-        return associations.get( stateName );
-    }
-
-    @Override
-    public void setPropertyValue( QualifiedName stateName, Object newValue )
-    {
-        properties.put( stateName, newValue );
-    }
-
-    @Override
-    public void setAssociationValue( QualifiedName stateName, EntityReference newEntity )
-    {
-        associations.put( stateName, newEntity );
-    }
-
-    @Override
-    public ManyAssociationState manyAssociationValueOf( QualifiedName stateName )
-    {
-        ManyAssociationState state = manyAssociations.get( stateName );
-        if( state == null )
-        {
-            state = new BuilderManyAssociationState();
-            manyAssociations.put( stateName, state );
-        }
-        return state;
-    }
-
-    @Override
-    public NamedAssociationState namedAssociationValueOf( QualifiedName stateName )
-    {
-        NamedAssociationState state = namedAssociations.get( stateName );
-        if( state == null )
-        {
-            state = new BuilderNamedAssociationState();
-            namedAssociations.put( stateName, state );
-        }
-        return state;
-    }
-
-    public void copyTo( EntityState newEntityState )
-    {
-        for( Map.Entry<QualifiedName, Object> fromPropertyEntry : properties.entrySet() )
-        {
-            newEntityState.setPropertyValue( fromPropertyEntry.getKey(), fromPropertyEntry.getValue() );
-        }
-        for( Map.Entry<QualifiedName, EntityReference> fromAssociationEntry : associations.entrySet() )
-        {
-            newEntityState.setAssociationValue( fromAssociationEntry.getKey(), fromAssociationEntry.getValue() );
-        }
-        for( Map.Entry<QualifiedName, ManyAssociationState> fromManyAssociationEntry : manyAssociations.entrySet() )
-        {
-            QualifiedName qName = fromManyAssociationEntry.getKey();
-            ManyAssociationState fromManyAssoc = fromManyAssociationEntry.getValue();
-            ManyAssociationState toManyAssoc = newEntityState.manyAssociationValueOf( qName );
-            for( EntityReference entityReference : fromManyAssoc )
-            {
-                toManyAssoc.add( 0, entityReference );
-            }
-        }
-        for( Map.Entry<QualifiedName, NamedAssociationState> fromNamedAssociationEntry : namedAssociations.entrySet() )
-        {
-            QualifiedName qName = fromNamedAssociationEntry.getKey();
-            NamedAssociationState fromNamedAssoc = fromNamedAssociationEntry.getValue();
-            NamedAssociationState toNamedAssoc = newEntityState.namedAssociationValueOf( qName );
-            for( String name : fromNamedAssoc )
-            {
-                toNamedAssoc.put( name, fromNamedAssoc.get( name ) );
-            }
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/BuilderManyAssociationState.java b/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/BuilderManyAssociationState.java
deleted file mode 100644
index 33aa9f1..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/BuilderManyAssociationState.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.unitofwork;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.spi.entity.ManyAssociationState;
-
-/**
- * Default implementation of ManyAssociationState that also
- * keeps a list of changes that can be extracted at any time.
- */
-public final class BuilderManyAssociationState
-    implements ManyAssociationState
-{
-    private List<EntityReference> references;
-
-    public BuilderManyAssociationState()
-    {
-        references = new ArrayList<EntityReference>();
-    }
-
-    @Override
-    public int count()
-    {
-        return references.size();
-    }
-
-    @Override
-    public boolean contains( EntityReference entityReference )
-    {
-        return references.contains( entityReference );
-    }
-
-    @Override
-    public boolean add( int i, EntityReference entityReference )
-    {
-        if( references.contains( entityReference ) )
-        {
-            return false;
-        }
-
-        references.add( i, entityReference );
-        return true;
-    }
-
-    @Override
-    public boolean remove( EntityReference entityReference )
-    {
-        return references.remove( entityReference );
-    }
-
-    @Override
-    public EntityReference get( int i )
-    {
-        return references.get( i );
-    }
-
-    @Override
-    public Iterator<EntityReference> iterator()
-    {
-        return references.iterator();
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/BuilderNamedAssociationState.java b/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/BuilderNamedAssociationState.java
deleted file mode 100644
index 1936a6b..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/BuilderNamedAssociationState.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2011-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.unitofwork;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.spi.entity.NamedAssociationState;
-
-/**
- * Default implementation of NamedAssociationState that also
- * keeps a list of changes that can be extracted at any time.
- */
-public final class BuilderNamedAssociationState
-    implements NamedAssociationState
-{
-    private final Map<String, EntityReference> references;
-
-    public BuilderNamedAssociationState()
-    {
-        references = new HashMap<>();
-    }
-
-    @Override
-    public int count()
-    {
-        return references.size();
-    }
-
-    @Override
-    public boolean containsName( String name )
-    {
-        return references.containsKey( name );
-    }
-
-    @Override
-    public boolean put( String name, EntityReference entityReference )
-    {
-        return references.put( name, entityReference ) != null;
-    }
-
-    @Override
-    public boolean remove( String name )
-    {
-        return references.remove( name ) != null;
-    }
-
-    @Override
-    public EntityReference get( String name )
-    {
-        return references.get( name );
-    }
-
-    @Override
-    public String nameOf( EntityReference entityReference )
-    {
-        for( Map.Entry<String, EntityReference> entry : references.entrySet() )
-        {
-            if( entry.getValue().equals( entityReference ) )
-            {
-                return entry.getKey();
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public Iterator<String> iterator()
-    {
-        return references.keySet().iterator();
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/EntityBuilderInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/EntityBuilderInstance.java
deleted file mode 100644
index f5f39dd..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/EntityBuilderInstance.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 2007-2009, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008, Alin Dreghiciu. All Rights Reserved.
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2014-2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.unitofwork;
-
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.entity.LifecycleException;
-import org.qi4j.runtime.composite.FunctionStateResolver;
-import org.qi4j.runtime.entity.EntityInstance;
-import org.qi4j.runtime.entity.EntityModel;
-import org.qi4j.spi.module.ModelModule;
-import org.qi4j.runtime.structure.ModuleUnitOfWork;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entitystore.EntityStoreUnitOfWork;
-
-/**
- * Implementation of EntityBuilder. Maintains an instance of the entity which
- * will not have its state validated until it is created by calling newInstance().
- */
-public final class EntityBuilderInstance<T>
-    implements EntityBuilder<T>
-{
-    private static final QualifiedName IDENTITY_STATE_NAME;
-
-    private final ModelModule<EntityModel> model;
-    private final ModuleUnitOfWork uow;
-    private final EntityStoreUnitOfWork store;
-    private String identity;
-
-    private final BuilderEntityState entityState;
-    private final EntityInstance prototypeInstance;
-
-    static
-    {
-        try
-        {
-            IDENTITY_STATE_NAME = QualifiedName.fromAccessor( Identity.class.getMethod( "identity" ) );
-        }
-        catch( NoSuchMethodException e )
-        {
-            throw new InternalError( "Zest Core Runtime codebase is corrupted. Contact Zest team: EntityBuilderInstance" );
-        }
-    }
-
-    public EntityBuilderInstance(
-        ModelModule<EntityModel> model,
-        ModuleUnitOfWork uow,
-        EntityStoreUnitOfWork store,
-        String identity
-    )
-    {
-        this( model, uow, store, identity, null );
-    }
-
-    public EntityBuilderInstance(
-        ModelModule<EntityModel> model,
-        ModuleUnitOfWork uow,
-        EntityStoreUnitOfWork store,
-        String identity,
-        FunctionStateResolver stateResolver
-    )
-    {
-        this.model = model;
-        this.uow = uow;
-        this.store = store;
-        this.identity = identity;
-        EntityReference reference = new EntityReference( identity );
-        entityState = new BuilderEntityState( model.model(), reference );
-        model.model().initState( model.module(), entityState );
-        if( stateResolver != null )
-        {
-            stateResolver.populateState( model.model(), entityState );
-        }
-        entityState.setPropertyValue( IDENTITY_STATE_NAME, identity );
-        prototypeInstance = model.model().newInstance( uow, model.module(), entityState );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    @Override
-    public T instance()
-    {
-        checkValid();
-        return prototypeInstance.<T>proxy();
-    }
-
-    @Override
-    public <K> K instanceFor( Class<K> mixinType )
-    {
-        checkValid();
-        return prototypeInstance.newProxy( mixinType );
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public T newInstance()
-        throws LifecycleException
-    {
-        checkValid();
-
-        String identity;
-
-        // Figure out whether to use given or generated identity
-        identity = (String) entityState.propertyValueOf( IDENTITY_STATE_NAME );
-        EntityState newEntityState = model.model().newEntityState( store, uow.module(),
-                                                                   EntityReference.parseEntityReference( identity ) );
-
-        prototypeInstance.invokeCreate();
-
-        // Check constraints
-        prototypeInstance.checkConstraints();
-
-        entityState.copyTo( newEntityState );
-
-        EntityInstance instance = model.model().newInstance( uow, model.module(), newEntityState );
-
-        Object proxy = instance.proxy();
-
-        // Add entity in UOW
-        uow.addEntity( instance );
-
-        // Invalidate builder
-        this.identity = null;
-
-        return (T) proxy;
-    }
-
-    private void checkValid()
-        throws IllegalStateException
-    {
-        if( identity == null )
-        {
-            throw new IllegalStateException( "EntityBuilder is not valid after call to newInstance()" );
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/EntityStateStore.java b/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/EntityStateStore.java
deleted file mode 100644
index 4edfd2b..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/EntityStateStore.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.unitofwork;
-
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.spi.entity.EntityState;
-
-/**
- * JAVADOC
- */
-final class EntityStateStore
-{
-    AssociationStateHolder stateHolder;
-    EntityState state;
-
-    @Override
-    public String toString()
-    {
-        return state.identity().toString();
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/UnitOfWorkInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/UnitOfWorkInstance.java
deleted file mode 100644
index 67abf3a..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/unitofwork/UnitOfWorkInstance.java
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- * Copyright (c) 2007-2013, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.unitofwork;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Stack;
-import java.util.concurrent.TimeUnit;
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.metrics.MetricsCounter;
-import org.qi4j.api.metrics.MetricsCounterFactory;
-import org.qi4j.api.metrics.MetricsProvider;
-import org.qi4j.api.metrics.MetricsTimer;
-import org.qi4j.api.metrics.MetricsTimerFactory;
-import org.qi4j.api.unitofwork.ConcurrentEntityModificationException;
-import org.qi4j.api.unitofwork.EntityTypeNotFoundException;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.unitofwork.UnitOfWorkCallback;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.unitofwork.UnitOfWorkException;
-import org.qi4j.api.unitofwork.UnitOfWorkOptions;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.runtime.entity.EntityInstance;
-import org.qi4j.runtime.entity.EntityModel;
-import org.qi4j.runtime.structure.ModuleUnitOfWork;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.EntityStatus;
-import org.qi4j.spi.entitystore.ConcurrentEntityStateModificationException;
-import org.qi4j.spi.entitystore.EntityNotFoundException;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.EntityStoreUnitOfWork;
-import org.qi4j.spi.entitystore.StateCommitter;
-import org.qi4j.spi.metrics.DefaultMetric;
-import org.qi4j.spi.module.ModelModule;
-import org.qi4j.spi.module.ModuleSpi;
-
-import static org.qi4j.api.unitofwork.UnitOfWorkCallback.UnitOfWorkStatus.COMPLETED;
-import static org.qi4j.api.unitofwork.UnitOfWorkCallback.UnitOfWorkStatus.DISCARDED;
-import static org.qi4j.functional.Iterables.map;
-
-public final class UnitOfWorkInstance
-{
-    private static final ThreadLocal<Stack<UnitOfWorkInstance>> current = new ThreadLocal<Stack<UnitOfWorkInstance>>()
-    {
-        @Override
-        protected Stack<UnitOfWorkInstance> initialValue()
-        {
-            return new Stack<>();
-        }
-    };
-    private MetricsTimer.Context metricsTimer;
-
-    public static Stack<UnitOfWorkInstance> getCurrent()
-    {
-        return current.get();
-    }
-
-    private long currentTime;
-    private MetricsProvider metrics;
-    final HashMap<EntityReference, EntityInstance> instanceCache;
-    final HashMap<EntityStore, EntityStoreUnitOfWork> storeUnitOfWork;
-
-    private boolean open;
-
-    private boolean paused;
-
-    /**
-     * Lazy query builder factory.
-     */
-    private Usecase usecase;
-
-    private MetaInfo metaInfo;
-
-    private List<UnitOfWorkCallback> callbacks;
-
-    public UnitOfWorkInstance( Usecase usecase, long currentTime, MetricsProvider metrics )
-    {
-        this.currentTime = currentTime;
-        this.open = true;
-        instanceCache = new HashMap<>();
-        storeUnitOfWork = new HashMap<>();
-        getCurrent().push( this );
-        paused = false;
-        this.usecase = usecase;
-        startCapture( metrics );
-    }
-
-    public long currentTime()
-    {
-        return currentTime;
-    }
-
-    public EntityStoreUnitOfWork getEntityStoreUnitOfWork( EntityStore store, ModuleSpi module )
-    {
-        EntityStoreUnitOfWork uow = storeUnitOfWork.get( store );
-        if( uow == null )
-        {
-            uow = store.newUnitOfWork( usecase, module, currentTime );
-            storeUnitOfWork.put( store, uow );
-        }
-        return uow;
-    }
-
-    public <T> T get( EntityReference identity,
-                      ModuleUnitOfWork uow,
-                      Iterable<ModelModule<EntityModel>> potentialModels,
-                      Class<T> mixinType
-    )
-        throws EntityTypeNotFoundException, NoSuchEntityException
-    {
-        checkOpen();
-
-        EntityInstance entityInstance = instanceCache.get( identity );
-        if( entityInstance == null )
-        {   // Not yet in cache
-
-            // Check if this is a root UoW, or if no parent UoW knows about this entity
-            EntityState entityState = null;
-            EntityModel model = null;
-            ModuleSpi module = null;
-            // Figure out what EntityStore to use
-            for( ModelModule<EntityModel> potentialModel : potentialModels )
-            {
-                EntityStore store = potentialModel.module().entityStore();
-                EntityStoreUnitOfWork storeUow = getEntityStoreUnitOfWork( store, potentialModel.module() );
-                try
-                {
-                    entityState = storeUow.entityStateOf( potentialModel.module(), identity );
-                }
-                catch( EntityNotFoundException e )
-                {
-                    continue;
-                }
-
-                // Get the selected model
-                model = (EntityModel) entityState.entityDescriptor();
-                module = potentialModel.module();
-            }
-
-            // Check if model was found
-            if( model == null )
-            {
-                // Check if state was found
-                if( entityState == null )
-                {
-                    throw new NoSuchEntityException( identity, mixinType, usecase );
-                }
-                else
-                {
-                    throw new EntityTypeNotFoundException( mixinType.getName(),
-                                                           module.name(),
-                                                           map( ModelModule.toStringFunction,
-                                                                module.findVisibleEntityTypes()
-                                                           ) );
-                }
-            }
-
-            // Create instance
-            entityInstance = new EntityInstance( uow, module, model, entityState );
-
-            instanceCache.put( identity, entityInstance );
-        }
-        else
-        {
-            // Check if it has been removed
-            if( entityInstance.status() == EntityStatus.REMOVED )
-            {
-                throw new NoSuchEntityException( identity, mixinType, usecase );
-            }
-        }
-
-        return entityInstance.proxy();
-    }
-
-    public Usecase usecase()
-    {
-        return usecase;
-    }
-
-    public MetaInfo metaInfo()
-    {
-        if( metaInfo == null )
-        {
-            metaInfo = new MetaInfo();
-        }
-
-        return metaInfo;
-    }
-
-    public void pause()
-    {
-        if( !paused )
-        {
-            paused = true;
-            getCurrent().pop();
-
-            UnitOfWorkOptions unitOfWorkOptions = metaInfo().get( UnitOfWorkOptions.class );
-            if( unitOfWorkOptions == null )
-            {
-                unitOfWorkOptions = usecase().metaInfo( UnitOfWorkOptions.class );
-            }
-
-            if( unitOfWorkOptions != null )
-            {
-                if( unitOfWorkOptions.isPruneOnPause() )
-                {
-                    List<EntityReference> prunedInstances = null;
-                    for( EntityInstance entityInstance : instanceCache.values() )
-                    {
-                        if( entityInstance.status() == EntityStatus.LOADED )
-                        {
-                            if( prunedInstances == null )
-                            {
-                                prunedInstances = new ArrayList<>();
-                            }
-                            prunedInstances.add( entityInstance.identity() );
-                        }
-                    }
-                    if( prunedInstances != null )
-                    {
-                        for( EntityReference prunedInstance : prunedInstances )
-                        {
-                            instanceCache.remove( prunedInstance );
-                        }
-                    }
-                }
-            }
-        }
-        else
-        {
-            throw new UnitOfWorkException( "Unit of work is not active" );
-        }
-    }
-
-    public void resume()
-    {
-        if( paused )
-        {
-            paused = false;
-            getCurrent().push( this );
-        }
-        else
-        {
-            throw new UnitOfWorkException( "Unit of work has not been paused" );
-        }
-    }
-
-    public void complete()
-        throws UnitOfWorkCompletionException
-    {
-        checkOpen();
-
-        // Copy list so that it cannot be modified during completion
-        List<UnitOfWorkCallback> currentCallbacks = callbacks == null ? null : new ArrayList<>( callbacks );
-
-        // Commit state to EntityStores
-        List<StateCommitter> committers = applyChanges();
-
-        // Check callbacks
-        notifyBeforeCompletion( currentCallbacks );
-
-        // Commit all changes
-        for( StateCommitter committer : committers )
-        {
-            committer.commit();
-        }
-
-        close();
-
-        // Call callbacks
-        notifyAfterCompletion( currentCallbacks, COMPLETED );
-
-        callbacks = currentCallbacks;
-    }
-
-    public void discard()
-    {
-        if( !isOpen() )
-        {
-            return;
-        }
-        close();
-
-        // Copy list so that it cannot be modified during completion
-        List<UnitOfWorkCallback> currentCallbacks = callbacks == null ? null : new ArrayList<>( callbacks );
-
-        // Call callbacks
-        notifyAfterCompletion( currentCallbacks, DISCARDED );
-
-        for( EntityStoreUnitOfWork entityStoreUnitOfWork : storeUnitOfWork.values() )
-        {
-            entityStoreUnitOfWork.discard();
-        }
-
-        callbacks = currentCallbacks;
-    }
-
-    private void close()
-    {
-        checkOpen();
-
-        if( !isPaused() )
-        {
-            getCurrent().pop();
-        }
-        endCapture();
-        open = false;
-    }
-
-    public boolean isOpen()
-    {
-        return open;
-    }
-
-    public void addUnitOfWorkCallback( UnitOfWorkCallback callback )
-    {
-        if( callbacks == null )
-        {
-            callbacks = new ArrayList<>();
-        }
-
-        callbacks.add( callback );
-    }
-
-    public void removeUnitOfWorkCallback( UnitOfWorkCallback callback )
-    {
-        if( callbacks != null )
-        {
-            callbacks.remove( callback );
-        }
-    }
-
-    public void addEntity( EntityInstance instance )
-    {
-        instanceCache.put( instance.identity(), instance );
-    }
-
-    private List<StateCommitter> applyChanges()
-        throws UnitOfWorkCompletionException
-    {
-        List<StateCommitter> committers = new ArrayList<>();
-        for( EntityStoreUnitOfWork entityStoreUnitOfWork : storeUnitOfWork.values() )
-        {
-            try
-            {
-                StateCommitter committer = entityStoreUnitOfWork.applyChanges();
-                committers.add( committer );
-            }
-            catch( Exception e )
-            {
-                // Cancel all previously prepared stores
-                for( StateCommitter committer : committers )
-                {
-                    committer.cancel();
-                }
-
-                if( e instanceof ConcurrentEntityStateModificationException )
-                {
-                    // If we cancelled due to concurrent modification, then create the proper exception for it!
-                    ConcurrentEntityStateModificationException mee = (ConcurrentEntityStateModificationException) e;
-                    Collection<EntityReference> modifiedEntityIdentities = mee.modifiedEntities();
-                    Collection<EntityComposite> modifiedEntities = new ArrayList<>();
-                    for( EntityReference modifiedEntityIdentity : modifiedEntityIdentities )
-                    {
-                        Collection<EntityInstance> instances = instanceCache.values();
-                        for( EntityInstance instance : instances )
-                        {
-                            if( instance.identity().equals( modifiedEntityIdentity ) )
-                            {
-                                modifiedEntities.add( instance.<EntityComposite>proxy() );
-                            }
-                        }
-                    }
-                    throw new ConcurrentEntityModificationException( modifiedEntities );
-                }
-                else
-                {
-                    throw new UnitOfWorkCompletionException( e );
-                }
-            }
-        }
-        return committers;
-    }
-
-    private void notifyBeforeCompletion( List<UnitOfWorkCallback> callbacks )
-        throws UnitOfWorkCompletionException
-    {
-        // Notify explicitly registered callbacks
-        if( callbacks != null )
-        {
-            for( UnitOfWorkCallback callback : callbacks )
-            {
-                callback.beforeCompletion();
-            }
-        }
-
-        // Notify entities
-        try
-        {
-            for( EntityInstance instance : instanceCache.values() )
-            {
-                boolean isCallback = instance.proxy() instanceof UnitOfWorkCallback;
-                boolean isNotRemoved = !instance.status().equals( EntityStatus.REMOVED );
-                if( isCallback && isNotRemoved )
-                {
-                    UnitOfWorkCallback callback = UnitOfWorkCallback.class.cast( instance.proxy() );
-                    callback.beforeCompletion();
-                }
-            }
-        }
-        catch( UnitOfWorkCompletionException e )
-        {
-            throw e;
-        }
-        catch( Exception e )
-        {
-            throw new UnitOfWorkCompletionException( e );
-        }
-    }
-
-    private void notifyAfterCompletion( List<UnitOfWorkCallback> callbacks,
-                                        final UnitOfWorkCallback.UnitOfWorkStatus status
-    )
-    {
-        if( callbacks != null )
-        {
-            for( UnitOfWorkCallback callback : callbacks )
-            {
-                try
-                {
-                    callback.afterCompletion( status );
-                }
-                catch( Exception e )
-                {
-                    // Ignore
-                }
-            }
-        }
-
-        // Notify entities
-        try
-        {
-            for( EntityInstance instance : instanceCache.values() )
-            {
-                boolean isCallback = instance.proxy() instanceof UnitOfWorkCallback;
-                boolean isNotRemoved = !instance.status().equals( EntityStatus.REMOVED );
-                if( isCallback && isNotRemoved )
-                {
-                    UnitOfWorkCallback callback = UnitOfWorkCallback.class.cast( instance.proxy() );
-                    callback.afterCompletion( status );
-                }
-            }
-        }
-        catch( Exception e )
-        {
-            // Ignore
-        }
-    }
-
-    public void checkOpen()
-    {
-        if( !isOpen() )
-        {
-            throw new UnitOfWorkException( "Unit of work has been closed" );
-        }
-    }
-
-    public boolean isPaused()
-    {
-        return paused;
-    }
-
-    @Override
-    public String toString()
-    {
-        return "UnitOfWork " + hashCode() + "(" + usecase + "): entities:" + instanceCache.size();
-    }
-
-    public void remove( EntityReference entityReference )
-    {
-        instanceCache.remove( entityReference );
-    }
-
-    private void incrementCount()
-    {
-        MetricsCounter counter = getCounter();
-        counter.increment();
-    }
-
-    private void decrementCount()
-    {
-        MetricsCounter counter = getCounter();
-        counter.decrement();
-    }
-
-    private MetricsCounter getCounter()
-    {
-        if( metrics != null )
-        {
-            MetricsCounterFactory metricsFactory = metrics.createFactory( MetricsCounterFactory.class );
-            return metricsFactory.createCounter( getClass(), "UnitOfWork Counter" );
-        }
-        return new DefaultMetric();
-    }
-
-    private void endCapture()
-    {
-        decrementCount();
-        metricsTimer.stop();
-    }
-
-    private void startCapture( MetricsProvider metrics )
-    {
-        this.metrics = metrics;
-        incrementCount();
-        startTimer( metrics );
-    }
-
-    private void startTimer( MetricsProvider metrics )
-    {
-        MetricsTimerFactory metricsFactory = metrics.createFactory( MetricsTimerFactory.class );
-        String name = "UnitOfWork Timer";
-        MetricsTimer timer = metricsFactory.createTimer( getClass(), name, TimeUnit.MILLISECONDS, TimeUnit.SECONDS );
-        metricsTimer = timer.start();
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/value/ManyAssociationValueState.java b/core/runtime/src/main/java/org/qi4j/runtime/value/ManyAssociationValueState.java
deleted file mode 100644
index 1941062..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/value/ManyAssociationValueState.java
+++ /dev/null
@@ -1,105 +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.qi4j.runtime.value;
-
-import java.util.Iterator;
-import java.util.List;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.spi.entity.ManyAssociationState;
-
-/**
- * ManyAssociationState implementation for Value composites.
- */
-public class ManyAssociationValueState
-    implements ManyAssociationState
-{
-    private List<EntityReference> references;
-
-    public ManyAssociationValueState( List<EntityReference> references )
-    {
-        this.references = references;
-    }
-
-    @Override
-    public int count()
-    {
-        return references.size();
-    }
-
-    @Override
-    public boolean contains( EntityReference entityReference )
-    {
-        return references.contains( entityReference );
-    }
-
-    @Override
-    public boolean add( int i, EntityReference entityReference )
-    {
-        if( references.contains( entityReference ) )
-        {
-            return false;
-        }
-
-        references.add( i, entityReference );
-        return true;
-    }
-
-    @Override
-    public boolean remove( EntityReference entity )
-    {
-        boolean removed = references.remove( entity );
-        return removed;
-    }
-
-    @Override
-    public EntityReference get( int i )
-    {
-        return references.get( i );
-    }
-
-    @Override
-    public Iterator<EntityReference> iterator()
-    {
-        final Iterator<EntityReference> iter = references.iterator();
-
-        return new Iterator<EntityReference>()
-        {
-            EntityReference current;
-
-            @Override
-            public boolean hasNext()
-            {
-                return iter.hasNext();
-            }
-
-            @Override
-            public EntityReference next()
-            {
-                current = iter.next();
-                return current;
-            }
-
-            @Override
-            public void remove()
-            {
-                iter.remove();
-            }
-        };
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/value/NamedAssociationValueState.java b/core/runtime/src/main/java/org/qi4j/runtime/value/NamedAssociationValueState.java
deleted file mode 100644
index 4f3030d..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/value/NamedAssociationValueState.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2011-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.value;
-
-import java.util.Iterator;
-import java.util.Map;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.spi.entity.NamedAssociationState;
-
-public class NamedAssociationValueState
-    implements NamedAssociationState
-{
-    private final Map<String, EntityReference> references;
-
-    public NamedAssociationValueState( Map<String, EntityReference> references )
-    {
-        this.references = references;
-    }
-
-    @Override
-    public int count()
-    {
-        return references.size();
-    }
-
-    @Override
-    public boolean containsName( String name )
-    {
-        return references.containsKey( name );
-    }
-
-    @Override
-    public boolean put( String name, EntityReference entityReference )
-    {
-        return references.put( name, entityReference ) != null;
-    }
-
-    @Override
-    public boolean remove( String name )
-    {
-        return references.remove( name ) != null;
-    }
-
-    @Override
-    public EntityReference get( String name )
-    {
-        return references.get( name );
-    }
-
-    @Override
-    public String nameOf( EntityReference entityReference )
-    {
-        for( Map.Entry<String, EntityReference> entry : references.entrySet() )
-        {
-            if( entry.getValue().equals( entityReference ) )
-            {
-                return entry.getKey();
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public Iterator<String> iterator()
-    {
-        return references.keySet().iterator();
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/value/ReferenceProperty.java b/core/runtime/src/main/java/org/qi4j/runtime/value/ReferenceProperty.java
deleted file mode 100644
index 40e8dbb..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/value/ReferenceProperty.java
+++ /dev/null
@@ -1,53 +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.qi4j.runtime.value;
-
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.property.Property;
-
-/**
- * The reference for an Association
- */
-public class ReferenceProperty
-    implements Property<EntityReference>
-{
-    EntityReference reference;
-
-    public ReferenceProperty()
-    {
-    }
-
-    public ReferenceProperty( EntityReference reference )
-    {
-        this.reference = reference;
-    }
-
-    @Override
-    public EntityReference get()
-    {
-        return reference;
-    }
-
-    @Override
-    public void set( EntityReference newValue )
-        throws IllegalArgumentException, IllegalStateException
-    {
-        reference = newValue;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderInstance.java
deleted file mode 100644
index 6bd6eeb..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderInstance.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.value;
-
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.value.NoSuchValueException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.runtime.composite.StateResolver;
-import org.qi4j.spi.module.ModelModule;
-import org.qi4j.runtime.structure.ModuleInstance;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Implementation of ValueBuilder
- */
-public final class ValueBuilderInstance<T>
-    implements ValueBuilder<T>
-{
-
-    private final ModuleInstance currentModule;
-    private final ValueInstance prototypeInstance;
-
-    public ValueBuilderInstance( ModelModule<ValueModel> compositeModelModule, ModuleInstance currentModule, StateResolver stateResolver )
-    {
-        ValueStateInstance state = new ValueStateInstance( compositeModelModule, currentModule, stateResolver );
-        prototypeInstance = compositeModelModule.model().newValueInstance( compositeModelModule.module(), state );
-        prototypeInstance.prepareToBuild();
-        this.currentModule = currentModule;
-    }
-
-    @Override
-    public T prototype()
-    {
-        return prototypeInstance.<T>proxy();
-    }
-
-    @Override
-    public AssociationStateHolder state()
-    {
-        return prototypeInstance.state();
-    }
-
-    @Override
-    public <K> K prototypeFor( Class<K> mixinType )
-    {
-        return prototypeInstance.newProxy( mixinType );
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public T newInstance()
-        throws ConstructionException
-    {
-        Class<Composite> valueType = (Class<Composite>) first( prototypeInstance.types() );
-
-        ModelModule<ValueModel> valueModel = currentModule.typeLookup().lookupValueModel( valueType );
-
-        if( valueModel == null )
-        {
-            throw new NoSuchValueException( valueType.getName(), currentModule.name() );
-        }
-        return new ValueBuilderWithPrototype<>( valueModel, currentModule, prototype() ).newInstance();
-    }
-
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderWithPrototype.java b/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderWithPrototype.java
deleted file mode 100644
index b6f3e98..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderWithPrototype.java
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright 2007, Rickard Öberg.
- * Copyright 2009, Niclas Hedhman.
- * Copyright 2012, Kent Sølvsten.
- * Copyright 2013, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.value;
-
-import java.util.HashMap;
-import java.util.Map;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.functional.Function;
-import org.qi4j.runtime.composite.FunctionStateResolver;
-import org.qi4j.runtime.composite.MixinModel;
-import org.qi4j.runtime.composite.MixinsModel;
-import org.qi4j.runtime.composite.StateResolver;
-import org.qi4j.runtime.composite.UsesInstance;
-import org.qi4j.runtime.injection.InjectionContext;
-import org.qi4j.spi.module.ModelModule;
-import org.qi4j.runtime.structure.ModuleInstance;
-
-/**
- * Implementation of ValueBuilder with a prototype supplied
- */
-public class ValueBuilderWithPrototype<T>
-    implements ValueBuilder<T>
-{
-    private ValueInstance prototypeInstance;
-    private final ValueModel valueModel;
-
-    public ValueBuilderWithPrototype( ModelModule<ValueModel> compositeModelModule,
-                                      ModuleInstance currentModule,
-                                      T prototype
-    )
-    {
-        valueModel = compositeModelModule.model();
-        // Only shallow clone, as all generic types of the ValueComposites are expected to be Immutable.
-
-        MixinsModel mixinsModel = valueModel.mixinsModel();
-        Object[] mixins = mixinsModel.newMixinHolder();
-        final ValueStateInstance prototypeState = ValueInstance.valueInstanceOf( (ValueComposite) prototype ).state();
-        StateResolver resolver = new FunctionStateResolver(
-            new PropertyDescriptorFunction( prototypeState ),
-            new AssociationDescriptorEntityReferenceFunction( prototypeState ),
-            new AssociationDescriptorIterableFunction( prototypeState ),
-            new AssociationDescriptorMapFunction( prototypeState )
-        );
-        ValueStateInstance state = new ValueStateInstance( compositeModelModule, currentModule, resolver );
-        ValueInstance valueInstance = new ValueInstance(
-            valueModel,
-            currentModule,
-            mixins,
-            state
-        );
-
-        int i = 0;
-        InjectionContext injectionContext = new InjectionContext( valueInstance, UsesInstance.EMPTY_USES, state );
-        for( MixinModel mixinModel : mixinsModel.mixinModels() )
-        {
-            mixins[ i++ ] = mixinModel.newInstance( injectionContext );
-        }
-
-//        // Use serialization-deserialization to make a copy of the prototype
-//        final Object value;
-//        try
-//        {
-//            // @TODO there is probably a more efficient way to do this
-//            ValueSerialization valueSerialization = currentModule.valueSerialization();
-//            String serialized = valueSerialization.serialize( prototype );
-//            value = valueSerialization.deserialize( valueModel.valueType(), serialized);
-//        }
-//        catch( ValueSerializationException e )
-//        {
-//            throw new IllegalStateException( "Could not serialize-copy Value", e );
-//        }
-
-//        ValueInstance valueInstance = ValueInstance.valueInstanceOf( (ValueComposite) value );
-        valueInstance.prepareToBuild();
-        this.prototypeInstance = valueInstance;
-    }
-
-    @Override
-    public T prototype()
-    {
-        verifyUnderConstruction();
-        return prototypeInstance.<T>proxy();
-    }
-
-    @Override
-    public AssociationStateHolder state()
-    {
-        verifyUnderConstruction();
-        return prototypeInstance.state();
-    }
-
-    @Override
-    public <K> K prototypeFor( Class<K> mixinType )
-    {
-        verifyUnderConstruction();
-        return prototypeInstance.newProxy( mixinType );
-    }
-
-    @Override
-    public T newInstance()
-        throws ConstructionException
-    {
-        verifyUnderConstruction();
-
-        // Set correct info's (immutable) on the state
-        prototypeInstance.prepareBuilderState();
-
-        // Check that it is valid
-        valueModel.checkConstraints( prototypeInstance.state() );
-
-        try
-        {
-            return prototypeInstance.<T>proxy();
-        }
-        finally
-        {
-            // Invalidate builder
-            prototypeInstance = null;
-        }
-    }
-
-    private void verifyUnderConstruction()
-    {
-        if( prototypeInstance == null )
-        {
-            throw new IllegalStateException( "ValueBuilder instances cannot be reused" );
-        }
-    }
-
-    private static class PropertyDescriptorFunction
-        implements Function<PropertyDescriptor, Object>
-    {
-        private final ValueStateInstance prototypeState;
-
-        public PropertyDescriptorFunction( ValueStateInstance prototypeState )
-        {
-            this.prototypeState = prototypeState;
-        }
-
-        @Override
-        public Object map( PropertyDescriptor descriptor )
-        {
-            return prototypeState.propertyFor( descriptor.accessor() ).get();
-        }
-    }
-
-    private static class AssociationDescriptorEntityReferenceFunction
-        implements Function<AssociationDescriptor, EntityReference>
-    {
-        private final ValueStateInstance prototypeState;
-
-        public AssociationDescriptorEntityReferenceFunction( ValueStateInstance prototypeState )
-        {
-            this.prototypeState = prototypeState;
-        }
-
-        @Override
-        public EntityReference map( AssociationDescriptor descriptor )
-        {
-            return prototypeState.associationFor( descriptor.accessor() ).reference();
-        }
-    }
-
-    private static class AssociationDescriptorIterableFunction
-        implements Function<AssociationDescriptor, Iterable<EntityReference>>
-    {
-        private final ValueStateInstance prototypeState;
-
-        public AssociationDescriptorIterableFunction( ValueStateInstance prototypeState )
-        {
-            this.prototypeState = prototypeState;
-        }
-
-        @Override
-        public Iterable<EntityReference> map( AssociationDescriptor descriptor )
-        {
-            return prototypeState.manyAssociationFor( descriptor.accessor() ).references();
-        }
-    }
-
-    private static class AssociationDescriptorMapFunction
-        implements Function<AssociationDescriptor, Map<String, EntityReference>>
-    {
-        private final ValueStateInstance prototypeState;
-
-        public AssociationDescriptorMapFunction( ValueStateInstance prototypeState )
-        {
-            this.prototypeState = prototypeState;
-        }
-
-        @Override
-        public Map<String, EntityReference> map( AssociationDescriptor descriptor )
-        {
-            Map<String, EntityReference> result = new HashMap<>();
-            NamedAssociation<?> namedAssociation = prototypeState.namedAssociationFor( descriptor.accessor() );
-            for( String name : namedAssociation )
-            {
-                result.put( name, namedAssociation.referenceOf( name ) );
-            }
-            return result;
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderWithState.java b/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderWithState.java
deleted file mode 100644
index b76ea26..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueBuilderWithState.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2012, Kent Sølvsten. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.value;
-
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.runtime.composite.StateResolver;
-import org.qi4j.spi.module.ModelModule;
-import org.qi4j.runtime.structure.ModuleInstance;
-
-public class ValueBuilderWithState<T> implements ValueBuilder<T>
-{
-    private final ModelModule<ValueModel> model;
-    private ValueInstance prototypeInstance;
-
-    public ValueBuilderWithState( ModelModule<ValueModel> compositeModelModule,
-                                  ModuleInstance currentModule,
-                                  StateResolver stateResolver )
-    {
-        ValueStateInstance state = new ValueStateInstance( compositeModelModule, currentModule, stateResolver );
-        ValueInstance instance = compositeModelModule.model().newValueInstance( compositeModelModule.module(), state );
-        instance.prepareToBuild();
-        this.model = compositeModelModule;
-        this.prototypeInstance = instance;
-    }
-
-    @Override
-    public T prototype()
-    {
-        verifyUnderConstruction();
-        return prototypeInstance.<T>proxy();
-    }
-
-    @Override
-    public AssociationStateHolder state()
-    {
-        verifyUnderConstruction();
-        return prototypeInstance.state();
-    }
-
-    @Override
-    public <K> K prototypeFor( Class<K> mixinType )
-    {
-        verifyUnderConstruction();
-
-        return prototypeInstance.newProxy( mixinType );
-    }
-
-    @Override
-    public T newInstance()
-        throws ConstructionException
-    {
-        verifyUnderConstruction();
-
-        // Set correct info's (immutable) on the state
-        prototypeInstance.prepareBuilderState();
-
-        // Check that it is valid
-        model.model().checkConstraints( prototypeInstance.state() );
-
-        try
-        {
-            return prototypeInstance.<T>proxy();
-        }
-        finally
-        {
-            // Invalidate builder
-            prototypeInstance = null;
-        }
-    }
-
-    private void verifyUnderConstruction()
-    {
-        if( prototypeInstance == null )
-        {
-            throw new IllegalStateException( "ValueBuilder instances cannot be reused" );
-        }
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/value/ValueInstance.java
deleted file mode 100644
index 3b11c04..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueInstance.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2007, Alin Dreghiciu. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.value;
-
-import java.lang.reflect.Proxy;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.runtime.association.AssociationModel;
-import org.qi4j.runtime.association.ManyAssociationModel;
-import org.qi4j.runtime.association.NamedAssociationModel;
-import org.qi4j.runtime.composite.MixinsInstance;
-import org.qi4j.runtime.composite.TransientInstance;
-import org.qi4j.runtime.property.PropertyInstance;
-import org.qi4j.runtime.property.PropertyModel;
-import org.qi4j.spi.module.ModuleSpi;
-
-/**
- * ValueComposite instance
- */
-public final class ValueInstance
-    extends TransientInstance
-    implements CompositeInstance, MixinsInstance
-{
-    public static ValueInstance valueInstanceOf( ValueComposite composite )
-    {
-        return (ValueInstance) Proxy.getInvocationHandler( composite );
-    }
-
-    public ValueInstance( ValueModel compositeModel,
-                          ModuleSpi moduleInstance,
-                          Object[] mixins,
-                          ValueStateInstance state
-    )
-    {
-        super( compositeModel, moduleInstance, mixins, state );
-    }
-
-    /**
-     * Perform equals with {@code o} argument.
-     * <p>
-     * The definition of equals() for the Value is that if both the state and descriptor are equal,
-     * then the values are equal.
-     * </p>
-     *
-     * @param o The other object to compare.
-     *
-     * @return Returns a {@code boolean} indicator whether this object is equals the other.
-     */
-    @Override
-    public boolean equals( Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || !Proxy.isProxyClass( o.getClass() ) )
-        {
-            return false;
-        }
-
-        try
-        {
-            ValueInstance that = (ValueInstance) Proxy.getInvocationHandler( o );
-            // Descriptor equality
-            if( !descriptor().equals( that.descriptor() ) )
-            {
-                return false;
-            }
-            // State equality
-            return state.equals( that.state );
-        }
-        catch( ClassCastException e )
-        {
-            return false;
-        }
-    }
-
-    @Override
-    public ValueStateInstance state()
-    {
-        return (ValueStateInstance) state;
-    }
-
-    @Override
-    public ValueModel descriptor()
-    {
-        return (ValueModel) compositeModel;
-    }
-
-    /**
-     * When a ValueBuilder is about to start, ensure that all state has builder infos, i.e. they are mutable.
-     */
-    public void prepareToBuild()
-    {
-        for( PropertyModel propertyDescriptor : descriptor().state().properties() )
-        {
-            PropertyInstance<Object> propertyInstance =
-                (PropertyInstance<Object>) state.propertyFor( propertyDescriptor.accessor() );
-
-            propertyInstance.prepareToBuild( propertyDescriptor );
-        }
-
-        for( AssociationModel associationDescriptor : descriptor().state().associations() )
-        {
-            state().associationFor( associationDescriptor.accessor() )
-                .setAssociationInfo( associationDescriptor.getBuilderInfo() );
-        }
-
-        for( ManyAssociationModel associationDescriptor : descriptor().state().manyAssociations() )
-        {
-            state().manyAssociationFor( associationDescriptor.accessor() )
-                .setAssociationInfo( associationDescriptor.getBuilderInfo() );
-        }
-
-        for( NamedAssociationModel associationDescriptor : descriptor().state().namedAssociations() )
-        {
-            state().namedAssociationFor( associationDescriptor.accessor() )
-                .setAssociationInfo( associationDescriptor.getBuilderInfo() );
-        }
-    }
-
-    /**
-     * When a ValueBuilder is finished and is about to instantiate a Value, call this to ensure that the state has correct
-     * settings, i.e. is immutable.
-     */
-    public void prepareBuilderState()
-    {
-        for( PropertyModel propertyDescriptor : descriptor().state().properties() )
-        {
-            PropertyInstance<Object> propertyInstance =
-                (PropertyInstance<Object>) state.propertyFor( propertyDescriptor.accessor() );
-            propertyInstance.prepareBuilderState( propertyDescriptor );
-        }
-
-        for( AssociationModel associationDescriptor : descriptor().state().associations() )
-        {
-            state().associationFor( associationDescriptor.accessor() ).setAssociationInfo( associationDescriptor );
-        }
-
-        for( ManyAssociationModel associationDescriptor : descriptor().state().manyAssociations() )
-        {
-            state().manyAssociationFor( associationDescriptor.accessor() ).setAssociationInfo( associationDescriptor );
-        }
-
-        for( NamedAssociationModel associationDescriptor : descriptor().state().namedAssociations() )
-        {
-            state().namedAssociationFor( associationDescriptor.accessor() ).setAssociationInfo( associationDescriptor );
-        }
-    }
-
-    /**
-     * Calculate hash code.
-     *
-     * @return the hashcode of this instance.
-     */
-    @Override
-    public int hashCode()
-    {
-        int hash = compositeModel.hashCode() * 23; // Descriptor
-        return hash + state.hashCode() * 5; // State
-    }
-
-    @Override
-    public String toString()
-    {
-        return ( (ModuleSpi) module() ).valueSerialization().serialize( this.<ValueComposite>proxy() );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueModel.java b/core/runtime/src/main/java/org/qi4j/runtime/value/ValueModel.java
deleted file mode 100644
index 0efe6f5..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueModel.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.value;
-
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.type.ValueCompositeType;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.runtime.association.AssociationModel;
-import org.qi4j.runtime.association.ManyAssociationModel;
-import org.qi4j.runtime.composite.CompositeMethodsModel;
-import org.qi4j.runtime.composite.CompositeModel;
-import org.qi4j.runtime.composite.MixinModel;
-import org.qi4j.runtime.composite.MixinsModel;
-import org.qi4j.runtime.composite.UsesInstance;
-import org.qi4j.runtime.injection.InjectionContext;
-import org.qi4j.runtime.property.PropertyModel;
-import org.qi4j.runtime.unitofwork.UnitOfWorkInstance;
-import org.qi4j.spi.module.ModuleSpi;
-
-/**
- * Model for ValueComposites
- */
-public final class ValueModel
-    extends CompositeModel
-    implements ValueDescriptor
-{
-    private ValueCompositeType valueType;
-
-    public ValueModel( final Iterable<Class<?>> types,
-                       final Visibility visibility,
-                       final MetaInfo metaInfo,
-                       final MixinsModel mixinsModel,
-                       final ValueStateModel stateModel,
-                       final CompositeMethodsModel compositeMethodsModel
-    )
-    {
-        super( types, visibility, metaInfo, mixinsModel, stateModel, compositeMethodsModel );
-
-        valueType = new ValueCompositeType( this );
-    }
-
-    @Override
-    public ValueCompositeType valueType()
-    {
-        return valueType;
-    }
-
-    @Override
-    public ValueStateModel state()
-    {
-        return (ValueStateModel) super.state();
-    }
-
-    // This method is ONLY called by ValueBuilders
-    void checkConstraints( ValueStateInstance state )
-        throws ConstraintViolationException
-    {
-        for( PropertyModel propertyModel : stateModel.properties() )
-        {
-            propertyModel.checkConstraints( state.propertyFor( propertyModel.accessor() ).get() );
-        }
-
-        // IF no UnitOfWork is active, then the Association checks shouldn't be done.
-        if( UnitOfWorkInstance.getCurrent().empty() )
-        {
-            return;
-        }
-        for( AssociationModel associationModel : ( (ValueStateModel) stateModel ).associations() )
-        {
-            associationModel.checkConstraints( state.associationFor( associationModel.accessor() ).get() );
-        }
-
-        for( ManyAssociationModel associationModel : ( (ValueStateModel) stateModel ).manyAssociations() )
-        {
-            associationModel.checkAssociationConstraints( state.manyAssociationFor( associationModel.accessor() ) );
-        }
-    }
-
-    public ValueInstance newValueInstance( ModuleSpi moduleInstance,
-                                           ValueStateInstance state
-    )
-    {
-        Object[] mixins = mixinsModel.newMixinHolder();
-
-        ValueInstance instance = new ValueInstance( this, moduleInstance, mixins, state );
-
-        // Instantiate all mixins
-        int i = 0;
-        InjectionContext injectionContext = new InjectionContext( instance, UsesInstance.EMPTY_USES, state );
-        for( MixinModel mixinModel : mixinsModel.mixinModels() )
-        {
-            mixins[ i++ ] = mixinModel.newInstance( injectionContext );
-        }
-
-        // Return
-        return instance;
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueStateInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/value/ValueStateInstance.java
deleted file mode 100644
index c66734f..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueStateInstance.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2012, Kent Sølvsten. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.value;
-
-import java.lang.reflect.AccessibleObject;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.runtime.association.AssociationInfo;
-import org.qi4j.runtime.association.AssociationInstance;
-import org.qi4j.runtime.association.AssociationModel;
-import org.qi4j.runtime.association.ManyAssociationInstance;
-import org.qi4j.runtime.association.ManyAssociationModel;
-import org.qi4j.runtime.association.NamedAssociationInstance;
-import org.qi4j.runtime.association.NamedAssociationModel;
-import org.qi4j.runtime.composite.StateResolver;
-import org.qi4j.runtime.property.PropertyInfo;
-import org.qi4j.runtime.property.PropertyInstance;
-import org.qi4j.runtime.property.PropertyModel;
-import org.qi4j.spi.module.ModelModule;
-import org.qi4j.runtime.structure.ModuleInstance;
-
-/**
- * TODO
- */
-public final class ValueStateInstance
-    implements AssociationStateHolder
-{
-    private final Map<AccessibleObject, PropertyInstance<?>> properties;
-    private final Map<AccessibleObject, AssociationInstance<?>> associations;
-    private final Map<AccessibleObject, ManyAssociationInstance<?>> manyAssociations;
-    private final Map<AccessibleObject, NamedAssociationInstance<?>> namedAssociations;
-
-    public ValueStateInstance( Map<AccessibleObject, PropertyInstance<?>> properties,
-                               Map<AccessibleObject, AssociationInstance<?>> associations,
-                               Map<AccessibleObject, ManyAssociationInstance<?>> manyAssociations,
-                               Map<AccessibleObject, NamedAssociationInstance<?>> namedAssociations
-    )
-    {
-        this.properties = properties;
-        this.associations = associations;
-        this.manyAssociations = manyAssociations;
-        this.namedAssociations = namedAssociations;
-    }
-
-    public ValueStateInstance( ModelModule<ValueModel> compositeModelModule,
-                               ModuleInstance currentModule,
-                               StateResolver stateResolver )
-    {
-        ValueModel valueModel = compositeModelModule.model();
-        this.properties = new LinkedHashMap<>();
-        for( PropertyDescriptor propertyDescriptor : valueModel.state().properties() )
-        {
-            PropertyInfo builderInfo = ( (PropertyModel) propertyDescriptor ).getBuilderInfo();
-            Object value = stateResolver.getPropertyState( propertyDescriptor );
-            PropertyInstance<Object> propertyInstance = new PropertyInstance<>( builderInfo, value );
-            properties.put( propertyDescriptor.accessor(), propertyInstance );
-        }
-
-        this.associations = new LinkedHashMap<>();
-        for( AssociationDescriptor associationDescriptor : valueModel.state().associations() )
-        {
-            AssociationInfo builderInfo = ( (AssociationModel) associationDescriptor ).getBuilderInfo();
-            EntityReference value = stateResolver.getAssociationState( associationDescriptor );
-            AssociationInstance<Object> associationInstance1 = new AssociationInstance<>(
-                builderInfo,
-                currentModule.getEntityFunction(),
-                new ReferenceProperty( value ) );
-            associations.put( associationDescriptor.accessor(), associationInstance1 );
-        }
-
-        this.manyAssociations = new LinkedHashMap<>();
-        for( AssociationDescriptor associationDescriptor : valueModel.state().manyAssociations() )
-        {
-            AssociationInfo builderInfo = ( (ManyAssociationModel) associationDescriptor ).getBuilderInfo();
-            List<EntityReference> value = stateResolver.getManyAssociationState( associationDescriptor );
-            ManyAssociationValueState manyAssociationState = new ManyAssociationValueState( value );
-            ManyAssociationInstance<Object> associationInstance = new ManyAssociationInstance<>(
-                builderInfo,
-                currentModule.getEntityFunction(),
-                manyAssociationState );
-            manyAssociations.put( associationDescriptor.accessor(), associationInstance );
-        }
-
-        this.namedAssociations = new LinkedHashMap<>();
-        for( AssociationDescriptor associationDescriptor : valueModel.state().namedAssociations() )
-        {
-            AssociationInfo builderInfo = ( (NamedAssociationModel) associationDescriptor ).getBuilderInfo();
-            Map<String, EntityReference> value = stateResolver.getNamedAssociationState( associationDescriptor );
-            NamedAssociationValueState namedAssociationState = new NamedAssociationValueState( value );
-            NamedAssociationInstance<Object> associationInstance = new NamedAssociationInstance<>(
-                builderInfo,
-                currentModule.getEntityFunction(),
-                namedAssociationState );
-            namedAssociations.put( associationDescriptor.accessor(), associationInstance );
-        }
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public <T> PropertyInstance<T> propertyFor( AccessibleObject accessor )
-        throws IllegalArgumentException
-    {
-        PropertyInstance<T> property = (PropertyInstance<T>) properties.get( accessor );
-
-        if( property == null )
-        {
-            throw new IllegalArgumentException( "No such property:" + accessor );
-        }
-
-        return property;
-    }
-
-    @Override
-    public Iterable<PropertyInstance<?>> properties()
-    {
-        return properties.values();
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public <T> AssociationInstance<T> associationFor( AccessibleObject accessor )
-    {
-        AssociationInstance<T> association = (AssociationInstance<T>) associations.get( accessor );
-
-        if( association == null )
-        {
-            throw new IllegalArgumentException( "No such association:" + accessor );
-        }
-
-        return association;
-    }
-
-    @Override
-    public Iterable<AssociationInstance<?>> allAssociations()
-    {
-        return associations.values();
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public <T> ManyAssociationInstance<T> manyAssociationFor( AccessibleObject accessor )
-    {
-        ManyAssociationInstance<T> manyAssociation = (ManyAssociationInstance<T>) manyAssociations.get( accessor );
-
-        if( manyAssociation == null )
-        {
-            throw new IllegalArgumentException( "No such many-association:" + accessor );
-        }
-
-        return manyAssociation;
-    }
-
-    @Override
-    public Iterable<ManyAssociationInstance<?>> allManyAssociations()
-    {
-        return manyAssociations.values();
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public <T> NamedAssociationInstance<T> namedAssociationFor( AccessibleObject accessor )
-    {
-        NamedAssociationInstance<T> namedAssociation = (NamedAssociationInstance<T>) namedAssociations.get( accessor );
-
-        if( namedAssociation == null )
-        {
-            throw new IllegalArgumentException( "No such named-association:" + accessor );
-        }
-
-        return namedAssociation;
-    }
-
-    @Override
-    public Iterable<? extends NamedAssociationInstance<?>> allNamedAssociations()
-    {
-        return namedAssociations.values();
-    }
-
-    @Override
-    public boolean equals( Object obj )
-    {
-        if( !( obj instanceof ValueStateInstance ) )
-        {
-            return false;
-        }
-        ValueStateInstance state = (ValueStateInstance) obj;
-        if( !properties.equals( state.properties ) )
-        {
-            return false;
-        }
-        if( !associations.equals( state.associations ) )
-        {
-            return false;
-        }
-        if( !manyAssociations.equals( state.manyAssociations ) )
-        {
-            return false;
-        }
-        return namedAssociations.equals( state.namedAssociations );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        int result = properties.hashCode();
-        result = 31 * result + associations.hashCode();
-        result = 31 * result + manyAssociations.hashCode();
-        result = 31 * result + namedAssociations.hashCode();
-        return result;
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueStateModel.java b/core/runtime/src/main/java/org/qi4j/runtime/value/ValueStateModel.java
deleted file mode 100644
index 76e4bb8..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/value/ValueStateModel.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg.
- * Copyright (c) 2012, Kent Sølvsten.
- * Copyright (c) 2014-2015, Paul Merlin.
- *
- * Licensed  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.qi4j.runtime.value;
-
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationStateDescriptor;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-import org.qi4j.runtime.association.AssociationModel;
-import org.qi4j.runtime.association.AssociationsModel;
-import org.qi4j.runtime.association.ManyAssociationModel;
-import org.qi4j.runtime.association.ManyAssociationsModel;
-import org.qi4j.runtime.association.NamedAssociationModel;
-import org.qi4j.runtime.association.NamedAssociationsModel;
-import org.qi4j.runtime.composite.StateModel;
-import org.qi4j.runtime.property.PropertiesModel;
-
-/**
- * Model for ValueComposite state.
- */
-public final class ValueStateModel
-    extends StateModel
-    implements AssociationStateDescriptor
-{
-    private final AssociationsModel associationsModel;
-    private final ManyAssociationsModel manyAssociationsModel;
-    private final NamedAssociationsModel namedAssociationsModel;
-
-    public ValueStateModel( PropertiesModel propertiesModel,
-                            AssociationsModel associationsModel,
-                            ManyAssociationsModel manyAssociationsModel,
-                            NamedAssociationsModel namedAssociationsModel
-    )
-    {
-        super( propertiesModel );
-        this.associationsModel = associationsModel;
-        this.manyAssociationsModel = manyAssociationsModel;
-        this.namedAssociationsModel = namedAssociationsModel;
-    }
-
-    @Override
-    public AssociationDescriptor getAssociationByName( String name )
-    {
-        return associationsModel.getAssociationByName( name );
-    }
-
-    @Override
-    public AssociationDescriptor getAssociationByQualifiedName( QualifiedName name )
-    {
-        return associationsModel.getAssociationByQualifiedName( name );
-    }
-
-    @Override
-    public AssociationDescriptor getManyAssociationByName( String name )
-    {
-        return manyAssociationsModel.getManyAssociationByName( name );
-    }
-
-    @Override
-    public AssociationDescriptor getManyAssociationByQualifiedName( QualifiedName name )
-    {
-        return manyAssociationsModel.getManyAssociationByQualifiedName( name );
-    }
-
-    @Override
-    public AssociationDescriptor getNamedAssociationByName( String name )
-    {
-        return namedAssociationsModel.getNamedAssociationByName( name );
-    }
-
-    @Override
-    public AssociationDescriptor getNamedAssociationByQualifiedName( QualifiedName name )
-    {
-        return namedAssociationsModel.getNamedAssociationByQualifiedName( name );
-    }
-
-    @Override
-    public Iterable<AssociationModel> associations()
-    {
-        return associationsModel.associations();
-    }
-
-    @Override
-    public Iterable<ManyAssociationModel> manyAssociations()
-    {
-        return manyAssociationsModel.manyAssociations();
-    }
-
-    @Override
-    public Iterable<NamedAssociationModel> namedAssociations()
-    {
-        return namedAssociationsModel.namedAssociations();
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            if( ( (VisitableHierarchy<Object, Object>) propertiesModel ).accept( visitor ) )
-            {
-                if( ( (VisitableHierarchy<AssociationsModel, AssociationModel>) associationsModel ).accept( visitor ) )
-                {
-                    if( ( (VisitableHierarchy<ManyAssociationsModel, ManyAssociationModel>) manyAssociationsModel ).accept( visitor ) )
-                    {
-                        ( (VisitableHierarchy<NamedAssociationsModel, NamedAssociationModel>) namedAssociationsModel ).accept( visitor );
-                    }
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-}
diff --git a/core/runtime/src/main/java/org/qi4j/runtime/value/ValuesModel.java b/core/runtime/src/main/java/org/qi4j/runtime/value/ValuesModel.java
deleted file mode 100644
index 723fd6d..0000000
--- a/core/runtime/src/main/java/org/qi4j/runtime/value/ValuesModel.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.value;
-
-import java.util.List;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-
-/**
- * JAVADOC
- */
-public final class ValuesModel
-    implements VisitableHierarchy<Object, Object>
-{
-    private final List<ValueModel> valueModels;
-
-    public ValuesModel( List<ValueModel> valueModels )
-    {
-        this.valueModels = valueModels;
-    }
-
-    public Iterable<ValueModel> models()
-    {
-        return valueModels;
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( ValueModel valueModel : valueModels )
-            {
-                if( !valueModel.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/api/common/OptionalTest.java b/core/runtime/src/test/java/org/apache/polygene/api/common/OptionalTest.java
new file mode 100644
index 0000000..6a43690
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/api/common/OptionalTest.java
@@ -0,0 +1,202 @@
+/*
+ *  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.polygene.api.common;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Tests for @Optional
+ */
+public class OptionalTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( TestComposite.class );
+        module.transients( TestComposite2.class );
+        module.entities( TestComposite3.class, TestComposite4.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Test
+    public void givenOptionalMethodWhenCorrectInvokeThenNoException()
+    {
+        TestComposite instance = transientBuilderFactory.newTransient( TestComposite.class );
+        instance.doStuff( "Hello WOrld", "Hello World" );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void givenOptionalMethodWhenMandatoryMissingThenException()
+    {
+        TestComposite instance = transientBuilderFactory.newTransient( TestComposite.class );
+        instance.doStuff( "Hello World", null );
+    }
+
+    @Test
+    public void givenOptionalMethodWhenOptionalMissingThenNoException()
+    {
+        TestComposite instance = transientBuilderFactory.newTransient( TestComposite.class );
+        instance.doStuff( null, "Hello World" );
+    }
+
+    @Test
+    public void givenOptionalPropertyWhenOptionalMissingThenNoException()
+    {
+        TransientBuilder<TestComposite2> builder = transientBuilderFactory.newTransientBuilder( TestComposite2.class );
+        builder.prototype().mandatoryProperty().set( "Hello World" );
+        TestComposite2 testComposite2 = builder.newInstance();
+    }
+
+    @Test
+    public void givenOptionalPropertyWhenOptionalSetThenNoException()
+    {
+        TransientBuilder<TestComposite2> builder = transientBuilderFactory.newTransientBuilder( TestComposite2.class );
+        builder.prototype().mandatoryProperty().set( "Hello World" );
+        builder.prototype().optionalProperty().set( "Hello World" );
+        TestComposite2 testComposite2 = builder.newInstance();
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void givenMandatoryPropertyWhenMandatoryMissingThenException()
+    {
+        TestComposite2 testComposite2 = transientBuilderFactory.newTransient( TestComposite2.class );
+    }
+
+    @Test
+    public void givenOptionalAssociationWhenOptionalMissingThenNoException()
+        throws Exception
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            TestComposite4 ref = unitOfWork.newEntity( TestComposite4.class );
+
+            EntityBuilder<TestComposite3> builder = unitOfWork.newEntityBuilder( TestComposite3.class );
+            builder.instance().mandatoryAssociation().set( ref );
+            TestComposite3 testComposite3 = builder.newInstance();
+
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    @Test
+    public void givenOptionalAssociationWhenOptionalSetThenNoException()
+        throws Exception
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            TestComposite4 ref = unitOfWork.newEntity( TestComposite4.class );
+
+            EntityBuilder<TestComposite3> builder = unitOfWork.newEntityBuilder( TestComposite3.class );
+            builder.instance().mandatoryAssociation().set( ref );
+            builder.instance().optionalAssociation().set( ref );
+            TestComposite3 testComposite3 = builder.newInstance();
+
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void givenMandatoryAssociationWhenMandatoryMissingThenException()
+        throws Exception
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            TestComposite4 ref = unitOfWork.newEntity( TestComposite4.class );
+
+            EntityBuilder<TestComposite3> builder = unitOfWork.newEntityBuilder( TestComposite3.class );
+            builder.instance().optionalAssociation().set( ref );
+            TestComposite3 testComposite3 = builder.newInstance();
+
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    @Mixins( TestComposite.TestMixin.class )
+    public interface TestComposite
+        extends TransientComposite
+    {
+        void doStuff( @Optional String optional, String mandatory );
+
+        abstract class TestMixin
+            implements TestComposite
+        {
+            public void doStuff( @Optional String optional, String mandatory )
+            {
+                assertThat( "Mandatory is not null", mandatory, notNullValue() );
+            }
+        }
+    }
+
+    public interface TestComposite2
+        extends TransientComposite
+    {
+        @Optional
+        Property<String> optionalProperty();
+
+        Property<String> mandatoryProperty();
+    }
+
+    public interface TestComposite3
+        extends EntityComposite
+    {
+        @Optional
+        Association<TestComposite4> optionalAssociation();
+
+        Association<TestComposite4> mandatoryAssociation();
+    }
+
+    public interface TestComposite4
+        extends EntityComposite
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/api/common/PropertyErrorTest.java b/core/runtime/src/test/java/org/apache/polygene/api/common/PropertyErrorTest.java
new file mode 100644
index 0000000..97aba67
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/api/common/PropertyErrorTest.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.api.common;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+/**
+ * Error messages for Properties
+ */
+public class PropertyErrorTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( PersonEntity.class );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void givenEntityWithNonOptionPropertyWhenInstantiatedThenException()
+        throws Exception
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            PersonEntity person = unitOfWork.newEntity( PersonEntity.class );
+
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    interface PersonEntity
+        extends EntityComposite
+    {
+        Property<String> foo();
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/api/common/PropertyTypeTest.java b/core/runtime/src/test/java/org/apache/polygene/api/common/PropertyTypeTest.java
new file mode 100644
index 0000000..79349ae
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/api/common/PropertyTypeTest.java
@@ -0,0 +1,166 @@
+/*
+ *  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.polygene.api.common;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.injection.scope.Invocation;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+/**
+ * Test for ability to set constraints on Properties
+ */
+public class PropertyTypeTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( PersonEntity.class );
+        module.transients( PersonComposite.class );
+    }
+
+    @Test
+    public void givenEntityWithPropertyConstraintsWhenInstantiatedThenPropertiesWork()
+        throws Exception
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            EntityBuilder<PersonEntity> builder = unitOfWork.newEntityBuilder( PersonEntity.class );
+            PersonEntity personEntity = builder.instance();
+            personEntity.givenName().set( "Rickard" );
+            personEntity.familyName().set( "Öberg" );
+            personEntity = builder.newInstance();
+
+            personEntity.givenName().set( "Niclas" );
+            personEntity.familyName().set( "Hedhman" );
+
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    @Test
+    public void givenCompositeWithPropertyConstraintsWhenInstantiatedThenPropertiesWork()
+        throws Exception
+    {
+        TransientBuilder<PersonComposite> builder = transientBuilderFactory.newTransientBuilder( PersonComposite.class );
+        PersonComposite personComposite = builder.prototype();
+        personComposite.givenName().set( "Rickard" );
+        personComposite.familyName().set( "Öberg" );
+        personComposite = builder.newInstance();
+
+        personComposite.givenName().set( "Niclas" );
+        personComposite.familyName().set( "Hedhman" );
+    }
+
+    @ConstraintDeclaration
+    @Retention( RetentionPolicy.RUNTIME )
+    @MaxLength( 50 )
+    public @interface Name
+    {
+    }
+
+    @ConstraintDeclaration
+    @Retention( RetentionPolicy.RUNTIME )
+    @NotEmpty
+    @Name
+    public @interface GivenName
+    {
+    }
+
+    interface PersonEntity
+        extends EntityComposite
+    {
+        @GivenName
+        Property<String> givenName();
+
+        @Name
+        Property<String> familyName();
+    }
+
+    interface PersonComposite
+        extends TransientComposite
+    {
+        @GivenName
+        Property<String> givenName();
+
+        @Name
+        Property<String> familyName();
+    }
+
+    @ConstraintDeclaration
+    @Retention( RetentionPolicy.RUNTIME )
+    @Constraints( MaxLengthConstraint.class )
+    public @interface MaxLength
+    {
+        int value();
+    }
+
+    public static class MaxLengthConstraint
+        implements Constraint<MaxLength, String>
+    {
+        public boolean isValid( MaxLength annotation, String argument )
+        {
+            if( argument != null )
+            {
+                return argument.length() <= annotation.value();
+            }
+
+            return false;
+        }
+    }
+
+    @ConstraintDeclaration
+    @Retention( RetentionPolicy.RUNTIME )
+    @Constraints( { NotEmptyStringConstraint.class } )
+    public @interface NotEmpty
+    {
+    }
+
+    public static class NotEmptyStringConstraint
+        implements Constraint<NotEmpty, String>
+    {
+
+        public boolean isValid( NotEmpty annotation, String value )
+        {
+            return value.trim().length() > 0;
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/api/common/RemovalTest.java b/core/runtime/src/test/java/org/apache/polygene/api/common/RemovalTest.java
new file mode 100644
index 0000000..a900a4f
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/api/common/RemovalTest.java
@@ -0,0 +1,127 @@
+/*
+ *  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.polygene.api.common;
+
+import org.apache.polygene.api.identity.StringIdentity;
+import org.junit.Test;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+public class RemovalTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( TestEntity.class );
+        module.entities( PidRegulator.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Test
+    public void givenEntityIsCreatedAndUnitOfWorkIsNotCompletedWhenEntityIsRemoveThenSuccessfulRemoval()
+        throws Exception
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        EntityBuilder<TestEntity> builder = uow.newEntityBuilder( TestEntity.class, new StringIdentity( "123" ) );
+        builder.instance().test().set( "habba" );
+        TestEntity test = builder.newInstance();
+        uow.remove( test );
+        uow.complete();
+    }
+
+    @Test
+    public void givenStandardPidRegulatorWhenNoChangeInInputExpectOutputToGoTowardsMinimum()
+        throws Exception
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        PidRegulator regulator = null;
+        try
+        {
+            regulator = createPidRegulator( uow );
+        }
+        finally
+        {
+            if( regulator != null )
+            {
+                uow.remove( regulator );
+            }
+            // TODO: This problem is related to that uow.remove() has a bug.
+            // If the Entity is both created and removed in the same session, then the remove() should simply remove
+            // the entity from the internal UoW holding area, and not set the REMOVED status.
+
+            // Probably that UnitOfWorkInstance.remove() should also call instanceCache.remove(), but the question is
+            // then what is an InstanceKey vs EntityReference
+            uow.complete();
+        }
+    }
+
+    public interface TestEntity
+        extends EntityComposite
+    {
+        @Optional
+        Property<String> test();
+    }
+
+    private PidRegulator createPidRegulator( UnitOfWork uow )
+        throws UnitOfWorkCompletionException
+    {
+        EntityBuilder<PidRegulator> builder = uow.newEntityBuilder( PidRegulator.class );
+        PidRegulator prototype = builder.instance();
+        prototype.p().set( 1.0f );
+        prototype.i().set( 10f );
+        prototype.d().set( 0.1f );
+        prototype.maxD().set( 10f );
+        prototype.maximum().set( 100f );
+        prototype.minimum().set( 0f );
+        PidRegulator regulator = builder.newInstance();
+
+        return regulator;
+    }
+
+    //    @Mixins( { PidRegulatorAlgorithmMixin.class } )
+    public interface PidRegulator
+        extends PidParameters, EntityComposite
+    {
+    }
+
+    public interface PidParameters
+    {
+        Property<Float> p();
+
+        Property<Float> i();
+
+        Property<Float> d();
+
+        Property<Float> maxD();
+
+        Property<Float> minimum();
+
+        Property<Float> maximum();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/api/common/ValueCompositeTest.java b/core/runtime/src/test/java/org/apache/polygene/api/common/ValueCompositeTest.java
new file mode 100644
index 0000000..0a6d1d3
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/api/common/ValueCompositeTest.java
@@ -0,0 +1,244 @@
+/*
+ *  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.polygene.api.common;
+
+import java.util.List;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Tests for ValueComposites
+ */
+public class ValueCompositeTest
+    extends AbstractPolygeneTest
+{
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.values( SomeValue.class, AnotherValue.class );
+        module.entities( SomeEntity.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Test( expected = IllegalStateException.class )
+    public void testImmutabilityOfValueComposite()
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        SomeValue some = builder.prototype();
+        some.other().set( "test" );
+        some = builder.newInstance();
+        some.other().set( "test2" );
+    }
+
+    @Test
+    public void testCreationOfValueComposite()
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        SomeValue some = builder.prototype();
+        some.other().set( "test" );
+        builder.newInstance();
+    }
+
+    @Test
+    public void testEqualityOfValueComposite()
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        SomeValue prototype = builder.prototype();
+        prototype.other().set( "test" );
+        SomeValue instance = builder.newInstance();
+
+        builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        prototype = builder.prototype();
+        prototype.other().set( "test" );
+        SomeValue other = builder.newInstance();
+        Assert.assertFalse( "Instances should not be the same.", instance == other );
+        Assert.assertEquals( "Equal values.", instance, other );
+    }
+
+    @Test
+    public void testHashcodeOfValueComposite()
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        SomeValue prototype = builder.prototype();
+        prototype.other().set( "test" );
+        SomeValue instance = builder.newInstance();
+
+        builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        prototype = builder.prototype();
+        prototype.other().set( "test" );
+        SomeValue other = builder.newInstance();
+        Assert.assertFalse( "Instances should not be the same.", instance == other );
+        Assert.assertEquals( "Equal values.", instance.hashCode(), other.hashCode() );
+    }
+
+    @Test
+    public void testModifyValue()
+    {
+        ValueBuilder<AnotherValue> anotherBuilder = valueBuilderFactory.newValueBuilder( AnotherValue.class );
+        anotherBuilder.prototype().val1().set( "Val1" );
+        AnotherValue anotherValue = anotherBuilder.newInstance();
+
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        SomeValue prototype = builder.prototype();
+        prototype.some().set( "foo" );
+        prototype.other().set( "test" );
+        prototype.xyzzyList().get().add( "blah" );
+        prototype.another().set( anotherValue );
+        SomeValue instance = builder.newInstance();
+
+        assertThat( "List has value blah", instance.xyzzyList().get().get( 0 ), equalTo( "blah" ) );
+
+        // Modify value
+        builder = valueBuilderFactory.newValueBuilderWithPrototype( instance );
+        builder.prototype().some().set( "bar" );
+        instance = builder.newInstance();
+
+        assertThat( "Other is set to test", instance.other().get(), equalTo( "test" ) );
+        assertThat( "List has value blah", instance.xyzzyList().get().get( 0 ), equalTo( "blah" ) );
+        assertThat( "AnotherValue.val1 has value Val1", instance.another().get().val1().get(), equalTo( "Val1" ) );
+
+        // Modify value again using method 2
+        builder = valueBuilderFactory.newValueBuilderWithPrototype( instance );
+        builder.prototype().other().set( "test2" );
+        instance = builder.newInstance();
+
+        assertThat( "Other is set to test2", instance.other().get(), equalTo( "test2" ) );
+        assertThat( "Some is set to bar", instance.some().get(), equalTo( "bar" ) );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void givenValueWhenModifyToIncorrectValueThenThrowConstraintException()
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        SomeValue prototype = builder.prototype();
+        prototype.some().set( "foo" );
+        SomeValue instance = builder.newInstance();
+
+        builder = valueBuilderFactory.newValueBuilderWithPrototype( instance );
+        builder.prototype().some().set( null );
+    }
+
+    @Test
+    public void givenValueWithListOfValueWhenPrototypeThenListedValuesAreEditable()
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        builder.prototype().anotherList().get().add( valueBuilderFactory.newValue( AnotherValue.class ) );
+        SomeValue some = builder.newInstance();
+
+        builder = valueBuilderFactory.newValueBuilderWithPrototype( some );
+        builder.prototype().anotherList().get().get( 0 ).val1().set( "Foo" );
+        builder.prototype().anotherList().get().add( valueBuilderFactory.newValue( AnotherValue.class ) );
+        some = builder.newInstance();
+
+        assertThat( "Val1 has been set", some.anotherList().get().get( 0 ).val1().get(), equalTo( "Foo" ) );
+
+        try
+        {
+            some.anotherList().get().get( 0 ).val1().set( "Bar" );
+            Assert.fail( "Should not be allowed to modify value" );
+        }
+        catch( IllegalStateException e )
+        {
+            // Ok
+        }
+    }
+
+    @Test
+    public void givenEntityWhenUpdateValueThenValueIsSet()
+        throws UnitOfWorkCompletionException
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        builder.prototype().anotherList().get().add( valueBuilderFactory.newValue( AnotherValue.class ) );
+        ValueBuilder<AnotherValue> valueBuilder = valueBuilderFactory.newValueBuilder( AnotherValue.class );
+        valueBuilder.prototype().val1().set( "Foo" );
+        builder.prototype().another().set( valueBuilder.newInstance() );
+        builder.prototype().number().set( 42L );
+        SomeValue some = builder.newInstance();
+
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        EntityBuilder<SomeEntity> entityBuilder = unitOfWork.newEntityBuilder( SomeEntity.class );
+        entityBuilder.instance().someValue().set( some );
+        SomeEntity entity = entityBuilder.newInstance();
+
+        assertThat( "Value has been set", entity.someValue().get().another().get().val1().get(), equalTo( "Foo" ) );
+
+        unitOfWork.complete();
+    }
+
+    public enum TestEnum
+    {
+        somevalue, anothervalue
+    }
+
+    public interface SomeValue
+        extends ValueComposite
+    {
+        @UseDefaults
+        Property<String> some();
+
+        @UseDefaults
+        Property<String> other();
+
+        @UseDefaults
+        Property<Long> number();
+
+        @UseDefaults
+        Property<List<String>> xyzzyList();
+
+        @Optional
+        Property<AnotherValue> another();
+
+        @UseDefaults
+        Property<List<AnotherValue>> anotherList();
+
+        @UseDefaults
+        Property<TestEnum> testEnum();
+    }
+
+    public interface AnotherValue
+        extends ValueComposite
+    {
+        @UseDefaults
+        Property<String> val1();
+    }
+
+    public interface SomeEntity
+        extends EntityComposite
+    {
+        Property<SomeValue> someValue();
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/bootstrap/ApplicationAssemblerTest.java b/core/runtime/src/test/java/org/apache/polygene/bootstrap/ApplicationAssemblerTest.java
new file mode 100644
index 0000000..f924408
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/bootstrap/ApplicationAssemblerTest.java
@@ -0,0 +1,115 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.identity.IdentityGenerator;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitorAdapter;
+
+/**
+ * TODO
+ */
+public class ApplicationAssemblerTest
+{
+    @Test
+    public void testApplicationAssembler()
+        throws AssemblyException
+    {
+        Energy4Java is = new Energy4Java();
+
+        ApplicationDescriptor model = is.newApplicationModel( new ApplicationAssembler()
+        {
+            @Override
+            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+                throws AssemblyException
+            {
+                ApplicationAssembly assembly = applicationFactory.newApplicationAssembly();
+
+                LayerAssembly layer1 = assembly.layer( "Layer1" );
+
+                ModuleAssembly module = layer1.module( "Module1" );
+
+                module.services( TestService.class );
+
+                module.entities( TestEntity.class );
+
+                layer1.services( AssemblySpecifications.ofAnyType( TestService.class ) ).instantiateOnStartup();
+
+                layer1.services( s -> true ).visibleIn( Visibility.layer );
+
+                layer1.entities( s -> true ).visibleIn( Visibility.application );
+
+                return assembly;
+            }
+        } );
+
+        model.accept( new HierarchicalVisitorAdapter<Object, Object, RuntimeException>()
+        {
+            @Override
+            public boolean visitEnter( Object visited )
+                throws RuntimeException
+            {
+                if( visited instanceof ServiceDescriptor )
+                {
+                    ServiceDescriptor serviceDescriptor = (ServiceDescriptor) visited;
+                    if( serviceDescriptor.hasType( UnitOfWorkFactory.class )
+                        || serviceDescriptor.hasType( IdentityGenerator.class )
+                        || serviceDescriptor.hasType( Serialization.class ) )
+                    {
+                        return false;
+                    }
+                    Assert.assertTrue( serviceDescriptor.isInstantiateOnStartup() );
+                    Assert.assertTrue( serviceDescriptor.visibility() == Visibility.layer );
+                    return false;
+                }
+                else if( visited instanceof EntityDescriptor )
+                {
+                    EntityDescriptor entityDescriptor = (EntityDescriptor) visited;
+                    Assert.assertTrue( entityDescriptor.visibility() == Visibility.application );
+                    return false;
+                }
+
+                return true;
+            }
+        } );
+        model.newInstance( is.spi() );
+    }
+
+    interface TestService
+        extends ServiceComposite
+    {
+
+    }
+
+    interface TestEntity
+        extends EntityComposite
+    {
+
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/bootstrap/ErrorReportingTest.java b/core/runtime/src/test/java/org/apache/polygene/bootstrap/ErrorReportingTest.java
new file mode 100644
index 0000000..bcd8e2a
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/bootstrap/ErrorReportingTest.java
@@ -0,0 +1,83 @@
+/*
+ *  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.polygene.bootstrap;
+
+import java.util.Map;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.core.StringContains.containsString;
+import static org.junit.Assert.assertThat;
+
+public class ErrorReportingTest extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.values( Person.class );
+        module.values( Pet.class );
+    }
+
+    @Override
+    protected void assemblyException( AssemblyException exception )
+        throws AssemblyException
+    {
+        assertThat( exception.getMessage(), containsString( "Composition Problems Report:\n" ) );
+        assertThat( exception.getMessage(), containsString( "    message: No implementation found for method \n"
+                                                            + "    method: Map doAnotherThing(String name, int value)\n"
+                                                            + "    types: [Person,ValueComposite]\n" ) );
+
+        assertThat( exception.getMessage(), containsString( "    message: No implementation found for method \n"
+                                                            + "    method: void doOneThing()\n"
+                                                            + "    types: [Person,ValueComposite]\n" ) );
+
+        assertThat( exception.getMessage(), containsString( "    message: No implementation found for method \n"
+                                                            + "    method: void goForWalk(int minutes)\n"
+                                                            + "    types: [Pet,ValueComposite]\n" ) );
+    }
+
+    @Test
+    public void dummy()
+    {
+
+    }
+
+    public interface Person
+    {
+        void doOneThing();
+
+        Map<String, Integer> doAnotherThing( String name, int value );
+
+        Property<String> name();
+
+        Association<Person> spouse();
+
+        ManyAssociation<Pet> pets();
+    }
+
+    public interface Pet
+    {
+        void goForWalk( int minutes );
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/bootstrap/RuntimeMixinsTest.java b/core/runtime/src/test/java/org/apache/polygene/bootstrap/RuntimeMixinsTest.java
new file mode 100644
index 0000000..cdf8ead
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/bootstrap/RuntimeMixinsTest.java
@@ -0,0 +1,187 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.mixin.NoopMixin;
+import org.junit.Test;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertThat;
+
+public class RuntimeMixinsTest
+{
+    @Test
+    public void givenValueWithRuntimeMixinsWhenAssembledExpectCorrectComposition()
+        throws ActivationException
+    {
+        SingletonAssembler singletonAssembler = new SingletonAssembler(
+            module ->
+            {
+                module.values( SayWhat.class ).withMixins( SayThisMixin.class, SayThatMixin.class );
+            }
+        );
+
+        SayWhat value = singletonAssembler.valueBuilderFactory().newValue( SayWhat.class );
+        assertThat( value.sayThis(), equalTo( "this" ) );
+        assertThat( value.sayThat(), equalTo( "that" ) );
+    }
+
+    @Test
+    public void givenValueWithRuntimeMixinOverrideWhenAssembledExpectCorrectComposition()
+        throws ActivationException
+    {
+        SingletonAssembler singletonAssembler = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.values( SayWhere.class ).withMixins( SayHereMixin.class );
+            }
+        };
+        SayWhere value = singletonAssembler.valueBuilderFactory().newValue( SayWhere.class );
+        assertThat( value.sayHere(), equalTo( "here" ) );
+        assertThat( value.sayThere(), nullValue() );
+    }
+
+    @Test
+    public void givenTransientWithRuntimeMixinsWhenAssembledExpectCorrectComposition()
+        throws ActivationException
+    {
+        SingletonAssembler singletonAssembler = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( SayWhat.class ).withMixins( SayThisMixin.class, SayThatMixin.class );
+            }
+        };
+        SayWhat value = singletonAssembler.transientBuilderFactory().newTransient( SayWhat.class );
+        assertThat( value.sayThis(), equalTo( "this" ) );
+        assertThat( value.sayThat(), equalTo( "that" ) );
+    }
+
+    @Test
+    public void givenTransientWithRuntimeMixinOverrideWhenAssembledExpectCorrectComposition()
+        throws ActivationException
+    {
+        SingletonAssembler singletonAssembler = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( SayWhere.class ).withMixins( SayHereMixin.class );
+            }
+        };
+        SayWhere value = singletonAssembler.transientBuilderFactory().newTransient( SayWhere.class );
+        assertThat( value.sayHere(), equalTo( "here" ) );
+        assertThat( value.sayThere(), nullValue() );
+    }
+
+    @Test
+    public void givenServiceWithRuntimeMixinsWhenAssembledExpectCorrectComposition()
+        throws ActivationException
+    {
+        SingletonAssembler singletonAssembler = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.services( SayWhat.class ).withMixins( SayThisMixin.class, SayThatMixin.class );
+            }
+        };
+        SayWhat value = singletonAssembler.serviceFinder().findService( SayWhat.class ).get();
+        assertThat( value.sayThis(), equalTo( "this" ) );
+        assertThat( value.sayThat(), equalTo( "that" ) );
+    }
+
+    @Test
+    public void givenServiceWithRuntimeMixinOverrideWhenAssembledExpectCorrectComposition()
+        throws ActivationException
+    {
+        SingletonAssembler singletonAssembler = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.services( SayWhere.class ).withMixins( SayHereMixin.class );
+            }
+        };
+        SayWhere value = singletonAssembler.serviceFinder().findService( SayWhere.class ).get();
+        assertThat( value.sayHere(), equalTo( "here" ) );
+        assertThat( value.sayThere(), nullValue() );
+    }
+
+    public interface SayWhat
+    {
+        String sayThis();
+
+        String sayThat();
+    }
+
+    @Mixins( NoopMixin.class )
+    public interface SayWhere
+    {
+        String sayHere();
+
+        String sayThere();
+    }
+
+    protected abstract static class SayThisMixin
+        implements SayWhat
+    {
+        @Override
+        public String sayThis()
+        {
+            return "this";
+        }
+    }
+
+    protected abstract static class SayThatMixin
+        implements SayWhat
+    {
+        @Override
+        public String sayThat()
+        {
+            return "that";
+        }
+    }
+
+    protected abstract static class SayHereMixin
+        implements SayWhere
+    {
+        @Override
+        public String sayHere()
+        {
+            return "here";
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/bootstrap/ServiceAssemblyTest.java b/core/runtime/src/test/java/org/apache/polygene/bootstrap/ServiceAssemblyTest.java
new file mode 100644
index 0000000..2f0492f
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/bootstrap/ServiceAssemblyTest.java
@@ -0,0 +1,93 @@
+/*
+ *  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.polygene.bootstrap;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class ServiceAssemblyTest extends AbstractPolygeneTest
+{
+    @Test
+    public void givenMyServiceWithTwoDeclarationsWhenActivatingServiceExpectServiceActivatedOnce()
+        throws Exception
+    {
+        ServiceReference<MyService> ref = serviceFinder.findService( MyService.class );
+        MyService underTest = ref.get();
+        assertThat(underTest.activated(), equalTo(1));
+        underTest.passivateService();
+        assertThat(underTest.passivated(), equalTo(1));
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( MyService.class ).instantiateOnStartup();
+        module.services( MyService.class ).setMetaInfo( "Hello" );
+    }
+
+    @Mixins( MyServiceMixin.class )
+    public static interface MyService extends ServiceActivation
+    {
+        int activated();
+        int passivated();
+    }
+
+    public static class MyServiceMixin implements MyService, ServiceActivation
+    {
+
+        private int activated;
+        private int passivated;
+
+        @Override
+        public int activated()
+        {
+            return activated;
+        }
+
+        @Override
+        public int passivated()
+        {
+            return passivated;
+        }
+
+        @Override
+        public void activateService()
+            throws Exception
+        {
+            activated++;
+        }
+
+        @Override
+        public void passivateService()
+            throws Exception
+        {
+            passivated++;
+
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/constraints/PropertyConstraintTest.java b/core/runtime/src/test/java/org/apache/polygene/constraints/PropertyConstraintTest.java
new file mode 100644
index 0000000..ca3b1fa
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/constraints/PropertyConstraintTest.java
@@ -0,0 +1,79 @@
+/*
+ *  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.polygene.constraints;
+
+import java.util.Collection;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.constraint.ConstraintViolation;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.constraints.MinLengthConstraint;
+import org.apache.polygene.library.constraints.annotation.Matches;
+import org.apache.polygene.library.constraints.annotation.MinLength;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class PropertyConstraintTest
+    extends AbstractPolygeneTest
+{
+    @org.junit.Test
+    public void givenConstraintOnPropertyWhenInvalidValueThenThrowException()
+        throws Throwable
+    {
+        TransientBuilder<Test> builder = transientBuilderFactory.newTransientBuilder( Test.class );
+        builder.prototype().test().set( "XXXXXX" );
+        Test test = builder.newInstance();
+        try
+        {
+            test.test().set( "YY" );
+            fail( "Should have thrown a ConstraintViolationException." );
+        }
+        catch( ConstraintViolationException e )
+        {
+            Collection<ConstraintViolation> violations = e.constraintViolations();
+            assertEquals( 2, violations.size() );
+        }
+    }
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( TestComposite.class );
+    }
+
+    @Constraints( { MinLengthConstraint.class } )
+    public interface TestComposite
+        extends Test, TransientComposite
+    {
+    }
+
+    public interface Test
+    {
+        @MinLength( 3 )
+        @Matches( "X*" )
+        Property<String> test();
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/regression/qi230/Qi230IssueTest.java b/core/runtime/src/test/java/org/apache/polygene/regression/qi230/Qi230IssueTest.java
new file mode 100644
index 0000000..271147f
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/regression/qi230/Qi230IssueTest.java
@@ -0,0 +1,139 @@
+/*
+ *  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.polygene.regression.qi230;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.mixin.NoopMixin;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * JAVADOC
+ */
+public class Qi230IssueTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( Some.class ).withMixins( NoopMixin.class ).withConcerns( OtherConcern.class );
+//        module.services( Some.class );
+        module.services( Result.class );
+    }
+
+    @Test
+    public void whenDerefencingInsideConcernThisExpectItToWork()
+        throws Exception
+    {
+        Result result = serviceFinder.findService( Result.class ).get();
+        Some some = serviceFinder.findService( Some.class ).get();
+        assertEquals( "method()", some.method() );
+        assertEquals( some.identity(), result.some().identity() );
+        assertEquals( some.identity().get(), result.some().identity().get() );
+    }
+
+    @Mixins( ResultMixin.class )
+    public interface Result
+        extends ServiceComposite
+    {
+        void execute( Some value );
+
+        Some some();
+    }
+
+    public static abstract class ResultMixin
+        implements Result
+    {
+
+        private Some value;
+
+        public void execute( Some value )
+        {
+            this.value = value;
+        }
+
+        public Some some()
+        {
+            return value;
+        }
+    }
+
+    @Concerns( OtherConcern.class )
+    @Mixins( NoopMixin.class )
+    public interface Other
+    {
+        void other();
+    }
+
+    @Mixins( SomeMixin.class )
+    public interface Some
+        extends ServiceComposite
+//        extends ServiceComposite, Other
+    {
+        String method();
+    }
+
+    public abstract static class SomeMixin
+        implements Some
+    {
+        @This
+        private Other other;
+
+        public String method()
+        {
+            other.other();
+            return "method()";
+        }
+    }
+
+    public static class OtherConcern
+        extends ConcernOf<Other>
+        implements Other
+    {
+        @Structure
+        private PolygeneAPI api;
+
+        @This
+        private Composite me;
+
+        @Service
+        private Result result;
+
+        public void other()
+        {
+            Composite value = api.dereference( me );
+            result.execute( (Some) value );
+            next.other();
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/regression/qi377/InterfaceCollisionWithRelatedReturnTypesTest.java b/core/runtime/src/test/java/org/apache/polygene/regression/qi377/InterfaceCollisionWithRelatedReturnTypesTest.java
new file mode 100644
index 0000000..f766590
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/regression/qi377/InterfaceCollisionWithRelatedReturnTypesTest.java
@@ -0,0 +1,202 @@
+/*
+ *  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.polygene.regression.qi377;
+
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+
+public class InterfaceCollisionWithRelatedReturnTypesTest
+    extends AbstractPolygeneTest
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( Employee.class, Company.class );
+    }
+
+    @Test
+    public void shouldBeAbleToSetNameToTheCompany()
+        throws UnitOfWorkCompletionException
+    {
+        Identity identity;
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            Company startUp = uow.newEntity( Company.class );
+            startUp.name().set( "Acme" );
+            identity = ((HasIdentity) startUp).identity().get();
+            uow.complete();
+        }
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            Company startUp = uow.get( Company.class, identity );
+            assertThat( startUp.name().get(), equalTo( "Acme" ) );
+
+            SalesTeam sales = uow.get( SalesTeam.class, identity );
+            assertThat( sales.name().get(), equalTo( "Acme" ) );
+
+            ResearchTeam research = uow.get( ResearchTeam.class, identity );
+            assertThat( research.name().get(), equalTo( "Acme" ) );
+        }
+    }
+
+    @Test
+    public void shouldBeAbleToSetLeadToTheCompany()
+        throws UnitOfWorkCompletionException
+    {
+        Identity identity;
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            Company startUp = uow.newEntity( Company.class );
+            Employee niclas = uow.newEntity( Employee.class );
+
+            startUp.lead().set( niclas );
+            identity = ((HasIdentity) startUp).identity().get();
+
+            uow.complete();
+        }
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            Company startUp = uow.get( Company.class, identity );
+            Employee niclas = startUp.lead().get();
+            assertThat( niclas, notNullValue() );
+
+            SalesTeam sales = uow.get( SalesTeam.class, identity );
+            assertThat( sales.lead().get(), equalTo( niclas ) );
+
+            ResearchTeam research = uow.get( ResearchTeam.class, identity );
+            assertThat( research.lead().get(), equalTo( niclas ) );
+        }
+    }
+
+    @Test
+    public void shouldBeAbleToSetLeadToTheSalesTeam()
+    {
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            SalesTeam startUp = uow.newEntity( SalesTeam.class );
+            Employee niclas = uow.newEntity( Employee.class );
+
+            startUp.lead().set( niclas );
+        }
+    }
+
+    @Test
+    public void shouldBeAbleToSetLeadToTheResearchTeam()
+    {
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            ResearchTeam startUp = uow.newEntity( ResearchTeam.class );
+            Employee niclas = uow.newEntity( Employee.class );
+
+            startUp.lead().set( niclas );
+        }
+    }
+
+    @Test
+    public void shouldBeAbleToAddEmployeesToTheCompany()
+    {
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            Company startUp = uow.newEntity( Company.class );
+            Employee niclas = uow.newEntity( Employee.class );
+
+            // To which team is Niclas added? Seems to be the interface listed first in the interface declaration?
+            // This contrived example is probably just bad design...
+            startUp.employees().add( niclas );
+        }
+    }
+
+    @Test
+    public void shouldBeAbleToAddEmployeesToTheSalesTeam()
+    {
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            SalesTeam startUp = uow.newEntity( SalesTeam.class );
+            Employee niclas = uow.newEntity( Employee.class );
+
+            startUp.employees().add( niclas );
+        }
+    }
+
+    @Test
+    public void shouldBeAbleToAddEmployeesToTheResearchTeam()
+    {
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            ResearchTeam startUp = uow.newEntity( ResearchTeam.class );
+            Employee niclas = uow.newEntity( Employee.class );
+
+            startUp.employees().add( niclas );
+        }
+    }
+
+    public interface Employee
+    {
+    }
+
+    public interface SalesTeam
+    {
+        @Optional
+        Property<String> name();
+
+        @Optional
+        Association<Employee> lead();
+
+        ManyAssociation<Employee> employees();
+    }
+
+    public interface ResearchTeam
+    {
+        @Optional
+        Property<String> name();
+
+        @Optional
+        Association<Employee> lead();
+
+        ManyAssociation<Employee> employees();
+    }
+
+    /**
+     * This compiles, unlike the example in {@link InterfaceCollisionWithUnrelatedReturnTypesTest}.
+     */
+    public interface Company
+        extends SalesTeam, ResearchTeam
+    {
+    }
+
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/regression/qi377/InterfaceCollisionWithUnrelatedReturnTypesTest.java b/core/runtime/src/test/java/org/apache/polygene/regression/qi377/InterfaceCollisionWithUnrelatedReturnTypesTest.java
new file mode 100644
index 0000000..7e149e0
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/regression/qi377/InterfaceCollisionWithUnrelatedReturnTypesTest.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.regression.qi377;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+public class InterfaceCollisionWithUnrelatedReturnTypesTest
+    extends AbstractPolygeneTest
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+    }
+
+    public interface Person
+    {
+        @UseDefaults
+        Property<String> name();
+    }
+
+    public interface Robot
+    {
+        @UseDefaults
+        Property<Integer> name();
+    }
+
+    /**
+     * DOESN'T COMPILE!!!
+     * java: types org.apache.polygene.regression.qi377.InterfaceCollisionWithUnrelatedReturnTypesTest.Robot and org.apache.polygene.regression.qi377.InterfaceCollisionWithUnrelatedReturnTypesTest.Person are incompatible; both define name(), but with unrelated return types
+     */
+//    public interface TeamMember extends Person, Robot {}
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/regression/qi377/IssueTest.java b/core/runtime/src/test/java/org/apache/polygene/regression/qi377/IssueTest.java
new file mode 100644
index 0000000..31a57b5
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/regression/qi377/IssueTest.java
@@ -0,0 +1,75 @@
+/*
+ *  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.polygene.regression.qi377;
+
+import org.junit.Test;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class IssueTest
+    extends AbstractPolygeneTest
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( TeamMember.class );
+    }
+
+    @Test
+    public void propertyNameCollisionsShouldWork()
+    {
+        TeamMember m = transientBuilderFactory.newTransient( TeamMember.class );
+        m.name().set( "Niclas" );
+        Person p = m;
+        p.name().set( "Chris" );
+        Employee e = m;
+        e.name().set( "Paul" );
+
+        assertThat( m.name().get(), equalTo( "Paul" ) );
+        assertThat( e.name().get(), equalTo( "Paul" ) );
+        assertThat( p.name().get(), equalTo( "Paul" ) );
+    }
+
+    public interface Person
+    {
+        @UseDefaults
+        Property<String> name();
+    }
+
+    public interface Employee
+    {
+        @UseDefaults
+        Property<String> name();
+    }
+
+    public interface TeamMember
+        extends Person, Employee
+    {
+    }
+
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/regression/qi377/SetAssociationInSideEffectTest.java b/core/runtime/src/test/java/org/apache/polygene/regression/qi377/SetAssociationInSideEffectTest.java
new file mode 100644
index 0000000..bcb7654
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/regression/qi377/SetAssociationInSideEffectTest.java
@@ -0,0 +1,133 @@
+/*
+ *  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.polygene.regression.qi377;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.junit.Test;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.sideeffect.GenericSideEffect;
+import org.apache.polygene.api.sideeffect.SideEffects;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.theInstance;
+import static org.junit.Assert.assertThat;
+
+public class SetAssociationInSideEffectTest
+    extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+
+        module.entities( Pianist.class, Steinway.class );
+    }
+
+    @Test
+    public void whenSettingAnAssociationInASideEffectExpectItToWork()
+    {
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "Purchase Steinway" ) ) )
+        {
+            Pianist chris = uow.newEntity( Pianist.class, new StringIdentity( "Chris" ) );
+            Steinway modelD = uow.newEntity( Steinway.class, new StringIdentity( "ModelD-274" ) );
+
+            assertThat( modelD.owner().get(), is( nullValue() ) );
+
+            chris.purchase( modelD );
+
+            assertThat( modelD.owner().get(), is( theInstance( chris ) ) );
+        }
+    }
+
+    @Mixins( PianistMixin.class )
+    @SideEffects( ChangeOwnerSideEffect.class )
+    public interface Pianist
+        extends Owner, EntityComposite
+    {
+        @Optional
+        Association<Steinway> steinway();
+
+        @ChangesOwner
+        void purchase( Steinway piano );
+    }
+
+    public static abstract class PianistMixin
+        implements Pianist
+    {
+        @Override
+        public void purchase( Steinway piano )
+        {
+            steinway().set( piano );
+        }
+    }
+
+    public interface Steinway
+        extends Ownable, EntityComposite
+    {
+    }
+
+    public interface Owner
+    {
+    }
+
+    public interface Ownable
+    {
+        @Optional
+        Association<Owner> owner();
+    }
+
+    @AppliesTo( ChangesOwner.class )
+    public static class ChangeOwnerSideEffect
+        extends GenericSideEffect
+    {
+        @This
+        Owner owner;
+
+        @Override
+        protected void invoke( Method method, Object[] args )
+            throws Throwable
+        {
+            Ownable ownable = (Ownable) args[ 0];
+            ownable.owner().set( owner );
+        }
+    }
+
+    @Retention( RetentionPolicy.RUNTIME )
+    public @interface ChangesOwner
+    {
+    }
+
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/regression/qi377/ValueCollisionWithRelatedReturnTypesTest.java b/core/runtime/src/test/java/org/apache/polygene/regression/qi377/ValueCollisionWithRelatedReturnTypesTest.java
new file mode 100644
index 0000000..1163024
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/regression/qi377/ValueCollisionWithRelatedReturnTypesTest.java
@@ -0,0 +1,150 @@
+/*
+ *  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.polygene.regression.qi377;
+
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.junit.Test;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+public class ValueCollisionWithRelatedReturnTypesTest
+    extends AbstractPolygeneTest
+{
+
+    public static final Identity NICLAS = new StringIdentity( "niclas" );
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.values( Employee.class, Company.class );
+    }
+
+    @Test
+    public void shouldBeAbleToSetNameToTheCompany()
+    {
+        ValueBuilder<Company> builder = valueBuilderFactory.newValueBuilder( Company.class );
+        builder.prototype().name().set( "Acme" );
+        Company startUp = builder.newInstance();
+    }
+
+    @Test
+    public void shouldBeAbleToSetLeadToTheCompany()
+    {
+        Company startUp = valueBuilderFactory.newValue( Company.class );
+        ValueBuilder<Employee> builder = valueBuilderFactory.newValueBuilder( Employee.class );
+        builder.prototype().identity().set(NICLAS);
+        Employee niclas = builder.newInstance();
+        startUp.lead().set( niclas );
+    }
+
+    @Test
+    public void shouldBeAbleToSetLeadToTheSalesTeam()
+    {
+        SalesTeam startUp = valueBuilderFactory.newValue( SalesTeam.class );
+        ValueBuilder<Employee> builder = valueBuilderFactory.newValueBuilder( Employee.class );
+        builder.prototype().identity().set(NICLAS);
+        Employee niclas = builder.newInstance();
+        startUp.lead().set( niclas );
+    }
+
+    @Test
+    public void shouldBeAbleToSetLeadToTheResearchTeam()
+    {
+        ResearchTeam startUp = valueBuilderFactory.newValue( ResearchTeam.class );
+        ValueBuilder<Employee> builder = valueBuilderFactory.newValueBuilder( Employee.class );
+        builder.prototype().identity().set(NICLAS);
+        Employee niclas = builder.newInstance();
+        startUp.lead().set( niclas );
+    }
+
+    @Test
+    public void shouldBeAbleToAddEmployeesToTheCompany()
+    {
+        Company startUp = valueBuilderFactory.newValue( Company.class );
+        ValueBuilder<Employee> builder = valueBuilderFactory.newValueBuilder( Employee.class );
+        builder.prototype().identity().set(NICLAS);
+        Employee niclas = builder.newInstance();
+        startUp.employees().add( niclas );
+    }
+
+    @Test
+    public void shouldBeAbleToAddEmployeesToTheSalesTeam()
+    {
+        SalesTeam startUp = valueBuilderFactory.newValue( SalesTeam.class );
+        ValueBuilder<Employee> builder = valueBuilderFactory.newValueBuilder( Employee.class );
+        builder.prototype().identity().set(NICLAS);
+        Employee niclas = builder.newInstance();
+        startUp.employees().add( niclas );
+    }
+
+    @Test
+    public void shouldBeAbleToAddEmployeesToTheResearchTeam()
+    {
+        ResearchTeam startUp = valueBuilderFactory.newValue( ResearchTeam.class );
+        ValueBuilder<Employee> builder = valueBuilderFactory.newValueBuilder( Employee.class );
+        builder.prototype().identity().set( NICLAS );
+        Employee niclas = builder.newInstance();
+        startUp.employees().add( niclas );
+    }
+
+    public interface Employee
+        extends HasIdentity
+    {
+    }
+
+    public interface SalesTeam
+    {
+        @Optional
+        Property<String> name();
+
+        @Optional
+        Association<Employee> lead();
+
+        ManyAssociation<Employee> employees();
+    }
+
+    public interface ResearchTeam
+    {
+        @Optional
+        Property<String> name();
+
+        @Optional
+        Association<Employee> lead();
+
+        ManyAssociation<Employee> employees();
+    }
+
+    /**
+     * This compiles, unlike the example in {@link InterfaceCollisionWithUnrelatedReturnTypesTest}.
+     */
+    public interface Company
+        extends SalesTeam, ResearchTeam
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/regression/qi382/Qi382Test.java b/core/runtime/src/test/java/org/apache/polygene/regression/qi382/Qi382Test.java
new file mode 100644
index 0000000..f09aa1c
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/regression/qi382/Qi382Test.java
@@ -0,0 +1,110 @@
+/*
+ *  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.polygene.regression.qi382;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.Lifecycle;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+
+public class Qi382Test extends AbstractPolygeneTest
+{
+
+    public static final Identity FERRARI = new StringIdentity( "Ferrari" );
+    public static final Identity NICLAS = new StringIdentity( "Niclas" );
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.addServices( MemoryEntityStoreService.class );
+        module.entities( Car.class, Person.class );
+    }
+
+    @Test
+    public void givenCreationOfTwoEntitiesWhenAssigningOneToOtherExpectCompletionToSucceed()
+        throws UnitOfWorkCompletionException
+    {
+        try( UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork() )
+        {
+            Car car = unitOfWork.newEntity( Car.class, FERRARI);
+            unitOfWork.complete();
+        }
+        try( UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork() )
+        {
+            Car car = unitOfWork.get( Car.class, FERRARI);
+            assertThat( car, notNullValue() );
+            Person p = unitOfWork.get( Person.class, NICLAS);
+            assertThat( p, notNullValue() );
+            assertThat( p.car().get(), equalTo( car ) );
+        }
+    }
+
+    @Mixins( Car.CarMixin.class )
+    public interface Car extends EntityComposite, Lifecycle
+    {
+
+        static class CarMixin implements Lifecycle
+        {
+            @This
+            private Car me;
+
+            @Structure
+            private UnitOfWorkFactory uowf;
+
+            @Override
+            public void create()
+            {
+                UnitOfWork unitOfWork = uowf.currentUnitOfWork();
+                EntityBuilder<Person> builder = unitOfWork.newEntityBuilder( Person.class, NICLAS);
+                builder.instance().car().set( me );
+                builder.newInstance();
+            }
+
+            @Override
+            public void remove()
+            {
+
+            }
+        }
+    }
+
+    public interface Person extends EntityComposite
+    {
+        Association<Car> car();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/regression/qi383/Qi383Test.java b/core/runtime/src/test/java/org/apache/polygene/regression/qi383/Qi383Test.java
new file mode 100644
index 0000000..8ed138c
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/regression/qi383/Qi383Test.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.regression.qi383;
+
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.unitofwork.EntityCompositeAlreadyExistsException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+public class Qi383Test extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.addServices( MemoryEntityStoreService.class );
+        module.entities( Car.class );
+    }
+
+    @Test( expected = EntityCompositeAlreadyExistsException.class )
+    public void givenUnitOfWorkInProgressWhenAddingSameEntityTwiceExpectException()
+        throws UnitOfWorkCompletionException
+    {
+        try( UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork() )
+        {
+            unitOfWork.newEntity( Car.class, new StringIdentity( "Ferrari" ) );
+            unitOfWork.newEntity( Car.class, new StringIdentity( "Ford" ) );
+            unitOfWork.newEntity( Car.class, new StringIdentity( "Ferrari" ) );
+            unitOfWork.complete();
+        }
+    }
+
+    public interface Car extends EntityComposite
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/regression/qi53/IssueTest.java b/core/runtime/src/test/java/org/apache/polygene/regression/qi53/IssueTest.java
new file mode 100644
index 0000000..bea4d6f
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/regression/qi53/IssueTest.java
@@ -0,0 +1,104 @@
+/*
+ *  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.polygene.regression.qi53;
+
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Immutable;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class IssueTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( CostPerUnitComposite.class );
+    }
+
+    @Test
+    public void genericPropertiesAndParameters()
+        throws SecurityException, NoSuchMethodException
+    {
+        TransientBuilder<CostPerUnitComposite> builder = transientBuilderFactory.newTransientBuilder( CostPerUnitComposite.class );
+        builder.prototype().unit().set( new Unit<Integer>( 10 ) );
+        CostPerUnitComposite test = builder.newInstance();
+        assertEquals( 10, test.unit().get().value );
+        assertEquals( 50, test.toCostPer( new Unit<Integer>( 50 ) ).unit().get().value );
+    }
+
+    public interface CostPerUnit
+    {
+        @Immutable
+        Property<Unit<?>> unit();
+
+        CostPerUnit toCostPer( Unit<?> unit );
+    }
+
+    public static class Unit<T>
+    {
+        private T value;
+
+        public Unit( T value )
+        {
+            this.value = value;
+        }
+
+        T get()
+        {
+            return value;
+        }
+    }
+
+    public static abstract class CostPerUnitMixin
+        implements CostPerUnit
+    {
+
+        @This
+        CostPerUnit costPerUnit;
+        @Structure
+        TransientBuilderFactory builderFactory;
+
+        public CostPerUnit toCostPer( Unit<?> unit )
+        {
+            TransientBuilder<CostPerUnitComposite> builder =
+                builderFactory.newTransientBuilder( CostPerUnitComposite.class );
+
+            builder.prototype().unit().set( unit );
+            return builder.newInstance();
+        }
+    }
+
+    @Mixins( { CostPerUnitMixin.class } )
+    public interface CostPerUnitComposite
+        extends CostPerUnit, TransientComposite
+    {
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/regression/qi55/IssueTest.java b/core/runtime/src/test/java/org/apache/polygene/regression/qi55/IssueTest.java
new file mode 100644
index 0000000..f907013
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/regression/qi55/IssueTest.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.regression.qi55;
+
+import org.junit.Test;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class IssueTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.objects( AClass.class );
+    }
+
+    @Test
+    public void objectWithGenericUsage()
+    {
+        assertEquals( "Using - Test string", objectFactory.newObject( AClass.class, "Test string" ).uses() );
+    }
+
+    public static class AClass<T>
+    {
+        @Uses
+        T value;
+
+        public String uses()
+        {
+            return "Using - " + value;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/regression/qi59/IssueTest.java b/core/runtime/src/test/java/org/apache/polygene/regression/qi59/IssueTest.java
new file mode 100644
index 0000000..37f0dff
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/regression/qi59/IssueTest.java
@@ -0,0 +1,96 @@
+/*
+ *  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.polygene.regression.qi59;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.constraints.annotation.NotEmpty;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.fail;
+
+/**
+ * Test for QI-59
+ */
+public class IssueTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( TestCase.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Test
+    public void givenEntityWithConstrainedPropertyWhenInvalidPropertyValueSetThenThrowException()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+
+        try
+        {
+            TestCase testCase = uow.newEntity( TestCase.class );
+
+            testCase.someProperty().set( null );
+
+            uow.complete();
+            fail( "Should not be allowed to set invalid property value" );
+        }
+        catch( Exception e )
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void givenEntityWithComplexConstrainedPropertyWhenInvalidPropertyValueSetThenThrowException()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+
+        try
+        {
+            TestCase testCase = uow.newEntity( TestCase.class );
+
+            testCase.otherProperty().set( "" );
+
+            uow.complete();
+            fail( "Should not be allowed to set invalid property value" );
+        }
+        catch( Exception e )
+        {
+            uow.discard();
+        }
+    }
+
+    interface TestCase
+        extends EntityComposite
+    {
+        Property<String> someProperty();
+
+        @NotEmpty
+        Property<String> otherProperty();
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/regression/qi65/IssueTest.java b/core/runtime/src/test/java/org/apache/polygene/regression/qi65/IssueTest.java
new file mode 100644
index 0000000..f4a3a97
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/regression/qi65/IssueTest.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.regression.qi65;
+
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+public class IssueTest
+    extends AbstractPolygeneTest
+{
+    private final static Class<?> CLAZZ = Object.class;
+    private final static String METHOD_NAME = "toString";
+    private final static Class<?> PARAM_TYPES[] = { };
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( TestComposite.class );
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void constraintOnMethodParameter()
+        throws SecurityException, NoSuchMethodException
+    {
+        TestComposite test = transientBuilderFactory.newTransient( TestComposite.class );
+
+        test.someMethod( null );
+    }
+
+    @Mixins( TestMixin.class )
+    public interface TestComposite
+        extends TransientComposite
+    {
+        String someMethod( String value );
+    }
+
+    public static abstract class TestMixin
+        implements TestComposite
+    {
+        public String someMethod( String value )
+        {
+            return value + " " + value;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/regression/qi74/IssueTest.java b/core/runtime/src/test/java/org/apache/polygene/regression/qi74/IssueTest.java
new file mode 100644
index 0000000..e265cf8
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/regression/qi74/IssueTest.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.regression.qi74;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+public class IssueTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( ValueHolder.class );
+    }
+
+    @Test
+    public void testConstraintCheckedOnCompsiteCreation()
+    {
+        try
+        {
+            TransientBuilder<ValueHolder> builder = transientBuilderFactory.newTransientBuilder( ValueHolder.class );
+            builder.newInstance();
+            Assert.fail( "NotNull constraint violated but no exception is raised" );
+        }
+        catch( ConstraintViolationException e )
+        {
+            // expected
+        }
+    }
+
+    static interface ValueHolder
+        extends TransientComposite
+    {
+        Property<String> val();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/regression/qi78/IssueTest.java b/core/runtime/src/test/java/org/apache/polygene/regression/qi78/IssueTest.java
new file mode 100644
index 0000000..7e96d69
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/regression/qi78/IssueTest.java
@@ -0,0 +1,93 @@
+/*
+ *  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.polygene.regression.qi78;
+
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitorAdapter;
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class IssueTest
+{
+    @Test
+    public void testLayersCanBeCreatedInOrderDifferentFromTheirDependency()
+        throws AssemblyException
+    {
+        Energy4Java polygene = new Energy4Java();
+
+        Application app = polygene.newApplication( new ApplicationAssembler()
+        {
+            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+                throws AssemblyException
+            {
+                ApplicationAssembly assembly = applicationFactory.newApplicationAssembly();
+
+                LayerAssembly domainLayer = assembly.layer( null );
+                domainLayer.setName( "Domain" );
+
+                LayerAssembly infrastructureLayer = assembly.layer( null );
+                infrastructureLayer.setName( "Infrastructure" );
+
+                domainLayer.uses( infrastructureLayer );
+
+                return assembly;
+            }
+        } );
+        ApplicationDescriptor model = app.descriptor();
+        model.accept( new HierarchicalVisitorAdapter<Object, Object, RuntimeException>()
+        {
+            @Override
+            public boolean visitEnter( Object visited )
+                throws RuntimeException
+            {
+                return visited instanceof ApplicationDescriptor;
+            }
+
+            @Override
+            public boolean visitLeave( Object visited )
+                throws RuntimeException
+            {
+                return visited instanceof LayerDescriptor;
+            }
+
+            @Override
+            public boolean visit( Object visited )
+                throws RuntimeException
+            {
+                if( visited instanceof LayerDescriptor )
+                {
+                    ( (LayerDescriptor) visited ).usedLayers().layers().forEach( usedLayerModel -> {
+                        Assert.assertNotNull( "Used layer model is null", usedLayerModel );
+                    } );
+                }
+
+                return false;
+            }
+        } );
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/regression/qi94/IssueTest.java b/core/runtime/src/test/java/org/apache/polygene/regression/qi94/IssueTest.java
new file mode 100644
index 0000000..6a60093
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/regression/qi94/IssueTest.java
@@ -0,0 +1,76 @@
+/*
+ *  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.polygene.regression.qi94;
+
+import org.junit.Test;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.assertEquals;
+
+public class IssueTest
+    extends AbstractPolygeneTest
+{
+    @SuppressWarnings( "unchecked" )
+    public void assemble( ModuleAssembly aModule )
+        throws AssemblyException
+    {
+        aModule.entities( Item.class, ItemType.class );
+        new EntityTestAssembler().assemble( aModule );
+    }
+
+    @Test
+    public void entityBuilderAssociationTypeIsNotNull()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            EntityBuilder<Item> builder = uow.newEntityBuilder( Item.class );
+            assertEquals( ItemType.class, polygene.api()
+                .entityDescriptorFor( builder.instance() )
+                .state()
+                .getAssociationByName( "typeOfItem" )
+                .type() );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    interface Item
+        extends EntityComposite
+    {
+        Association<ItemType> typeOfItem();
+    }
+
+    interface ItemType
+        extends EntityComposite
+    {
+        Property<String> name();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/PolygeneAPITest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/PolygeneAPITest.java
new file mode 100644
index 0000000..24419d6
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/PolygeneAPITest.java
@@ -0,0 +1,87 @@
+/*
+ *  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.polygene.runtime;
+
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+/**
+ * JAVADOC
+ */
+public class PolygeneAPITest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.transients( TestTransient.class );
+        module.entities( TestEntity.class );
+        module.values( TestValue.class );
+        module.services( TestService.class );
+    }
+
+    @Test
+    public void testGetModuleOfComposite()
+        throws Exception
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        TestEntity testEntity = unitOfWork.newEntity( TestEntity.class );
+
+        api.moduleOf( testEntity );
+
+        unitOfWork.discard();
+
+        api.moduleOf( valueBuilderFactory.newValue( TestValue.class ) );
+
+        api.moduleOf( transientBuilderFactory.newTransient( TestTransient.class ) );
+
+        api.moduleOf( serviceFinder.findService( TestService.class ).get() );
+    }
+
+    public interface TestTransient
+        extends TransientComposite
+    {
+    }
+
+    public interface TestEntity
+        extends EntityComposite
+    {
+    }
+
+    public interface TestValue
+        extends ValueComposite
+    {
+    }
+
+    public interface TestService
+        extends ServiceComposite
+    {
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/PolygeneSPITest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/PolygeneSPITest.java
new file mode 100644
index 0000000..7c60d87
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/PolygeneSPITest.java
@@ -0,0 +1,129 @@
+/*
+ *  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.polygene.runtime;
+
+import org.hamcrest.CoreMatchers;
+import org.junit.Test;
+import org.apache.polygene.api.association.AbstractAssociation;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.AssociationStateDescriptor;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.assertThat;
+
+/**
+ * JAVADOC
+ */
+public class PolygeneSPITest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( TestEntity.class, TestEntity2.class );
+    }
+
+    @Test
+    public void givenEntityWhenGettingStateThenGetCorrectState()
+        throws Exception
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        TestEntity testEntity;
+        try
+        {
+            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class );
+
+            testEntity = builder.newInstance();
+
+            AssociationStateHolder state = spi.stateOf( testEntity );
+
+            validateState( state, spi.entityDescriptorFor( testEntity ) );
+
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            testEntity = uow.get( testEntity );
+            validateState( spi.stateOf( testEntity ), spi.entityDescriptorFor( testEntity ) );
+            uow.complete();
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    private void validateState( AssociationStateHolder state, EntityDescriptor entityDescriptor )
+    {
+        entityDescriptor.state().properties().forEach( propertyDescriptor -> {
+            Property<?> prop = state.propertyFor( propertyDescriptor.accessor() );
+            assertThat( "Properties could be listed", prop, CoreMatchers.notNullValue() );
+        } );
+
+        AssociationStateDescriptor descriptor = entityDescriptor.state();
+        descriptor.associations().forEach( associationDescriptor -> {
+            AbstractAssociation assoc = state.associationFor( associationDescriptor.accessor() );
+            assertThat( "Assocs could be listed", assoc, CoreMatchers.notNullValue() );
+        } );
+    }
+
+    public interface TestEntity
+        extends EntityComposite
+    {
+        @Optional
+        Property<String> property();
+
+        @Optional
+        Association<TestEntity> association();
+
+        ManyAssociation<TestEntity> manyAssociation();
+    }
+
+    public interface TestEntity2
+        extends EntityComposite
+    {
+        @Optional
+        Property<String> property();
+
+        @Optional
+        Association<TestEntity> association();
+
+        ManyAssociation<TestEntity> manyAssociation();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ActivatorOrderTestSupport.java b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ActivatorOrderTestSupport.java
new file mode 100644
index 0000000..540f346
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ActivatorOrderTestSupport.java
@@ -0,0 +1,162 @@
+/*
+ *  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.polygene.runtime.activation;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.polygene.api.activation.Activator;
+
+public class ActivatorOrderTestSupport
+{
+
+    //
+    // Common expected results --------------------------------------------
+    //
+    public static interface Expected
+    {
+
+        String ALPHA_BETA_SINGLE = Arrays.toString( new String[]{
+                    "Alpha.beforeActivation",
+                    "Beta.beforeActivation",
+                    // -> Activation
+                    "Alpha.afterActivation",
+                    "Beta.afterActivation",
+                    // -> Active
+                    "Beta.beforePassivation",
+                    "Alpha.beforePassivation",
+                    // -> Passivation
+                    "Beta.afterPassivation",
+                    "Alpha.afterPassivation"
+                } );
+
+    }
+
+    //
+    // ActivationStep recorder --------------------------------------------
+    //
+    public static final class ActivationStep
+    {
+
+        public final String activator;
+
+        public final String step;
+
+        public ActivationStep( String activator, String step )
+        {
+            this.activator = activator;
+            this.step = step;
+        }
+
+        @Override
+        public String toString()
+        {
+            return activator + "." + step;
+        }
+
+    }
+
+    public static interface ActivationStepsRecorder
+    {
+
+        void reset();
+
+        void record( ActivationStep step );
+
+        List<ActivationStep> steps();
+
+    }
+
+    public static class ActivationStepsRecorderInstance
+            implements ActivationStepsRecorder
+    {
+
+        private List<ActivationStep> steps = new ArrayList<ActivationStep>();
+
+        @Override
+        public void reset()
+        {
+            steps = new ArrayList<ActivationStep>();
+        }
+
+        @Override
+        public void record( ActivationStep step )
+        {
+            steps.add( step );
+        }
+
+        @Override
+        public List<ActivationStep> steps()
+        {
+            return Collections.unmodifiableList( steps );
+        }
+
+    }
+
+    //
+    // Activator that call the ActivationStepsRecorder --------------------
+    //
+    public static abstract class OrderTestActivator<T>
+            implements Activator<T>
+    {
+
+        private final String activator;
+
+        private final ActivationStepsRecorder recorder;
+
+        public OrderTestActivator( String activator, ActivationStepsRecorder recorder )
+        {
+            this.activator = activator;
+            this.recorder = recorder;
+        }
+
+        @Override
+        public final void beforeActivation( T activating )
+                throws Exception
+        {
+            recorder.record( new ActivationStep( activator, "beforeActivation" ) );
+        }
+
+        @Override
+        public final void afterActivation( T activated )
+                throws Exception
+        {
+            recorder.record( new ActivationStep( activator, "afterActivation" ) );
+        }
+
+        @Override
+        public final void beforePassivation( T passivating )
+                throws Exception
+        {
+            recorder.record( new ActivationStep( activator, "beforePassivation" ) );
+        }
+
+        @Override
+        public final void afterPassivation( T passivated )
+                throws Exception
+        {
+            recorder.record( new ActivationStep( activator, "afterPassivation" ) );
+        }
+
+    }
+
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ApplicationActivationTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ApplicationActivationTest.java
new file mode 100644
index 0000000..95084a4
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ApplicationActivationTest.java
@@ -0,0 +1,91 @@
+/*
+ *  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.polygene.runtime.activation;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+public class ApplicationActivationTest
+{
+
+    private static int activationLevel = 0;
+
+    private static int passivationLevel = 0;
+
+    public static class TestedActivator
+            implements Activator<Application>
+    {
+
+        public void beforeActivation( Application activating )
+        {
+            activationLevel++;
+        }
+
+        public void afterActivation( Application activated )
+        {
+            activationLevel++;
+        }
+
+        public void beforePassivation( Application passivating )
+        {
+            passivationLevel++;
+        }
+
+        public void afterPassivation( Application passivated )
+        {
+            passivationLevel++;
+        }
+
+    }
+
+    @Test
+    public void testApplicationActivator()
+            throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                module.layer().application().withActivators( TestedActivator.class );
+            }
+
+        };
+
+        // Activate
+        Application application = assembly.application();
+
+        // Assert activated
+        Assert.assertEquals( "Activation Level", 2, activationLevel );
+
+        // Passivate
+        application.passivate();
+
+        // Assert passivated
+        Assert.assertEquals( "Passivation Level", 2, passivationLevel );
+    }
+
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ImportedServiceActivationTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ImportedServiceActivationTest.java
new file mode 100644
index 0000000..6d65488
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ImportedServiceActivationTest.java
@@ -0,0 +1,210 @@
+/*
+ *  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.polygene.runtime.activation;
+
+import org.apache.polygene.api.identity.StringIdentity;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.ServiceImporterException;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ImportedServiceDeclaration;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+import static org.junit.Assert.*;
+
+public class ImportedServiceActivationTest
+{
+
+    private static int activationLevel = 0;
+
+    private static int passivationLevel = 0;
+
+    public static class TestedActivator
+            implements Activator<ServiceReference<TestedService>>
+    {
+
+        public void beforeActivation( ServiceReference<TestedService> activating )
+        {
+            assertFalse( "Service should not be active before activation", activating.isActive() );
+            try {
+                activating.get();
+                fail( "Service is not activated yet, the reference get method should throw IllegalStateException." );
+            } catch ( IllegalStateException expected ) {
+            }
+            activationLevel++;
+        }
+
+        public void afterActivation( ServiceReference<TestedService> activated )
+        {
+            assertTrue( "Service should be active after activation", activated.isActive() );
+            assertEquals( "After activation", "bar", activated.get().foo() );
+            activationLevel++;
+        }
+
+        public void beforePassivation( ServiceReference<TestedService> passivating )
+        {
+            assertTrue( "Service should be active before passivation", passivating.isActive() );
+            assertEquals( "Before passivation", "bar", passivating.get().foo() );
+            passivationLevel++;
+        }
+
+        public void afterPassivation( ServiceReference<TestedService> passivated )
+        {
+            assertFalse( "Service should not be active after passivation", passivated.isActive() );
+            try {
+                passivated.get();
+                fail( "Service is passivated, the reference get method should throw IllegalStateException." );
+            } catch ( IllegalStateException expected ) {
+            }
+            passivationLevel++;
+        }
+
+    }
+
+    public static interface TestedService
+    {
+
+        String foo();
+
+    }
+
+    public static class TestedServiceInstance
+            implements TestedService
+    {
+
+        public String foo()
+        {
+            return "bar";
+        }
+
+    }
+
+    @Mixins( TestedServiceImporterService.Mixin.class )
+    interface TestedServiceImporterService
+            extends ServiceComposite, ServiceImporter<TestedService>
+    {
+
+        class Mixin
+                implements ServiceImporter<TestedService>
+        {
+
+            public TestedService importService( ImportedServiceDescriptor serviceDescriptor )
+                    throws ServiceImporterException
+            {
+                return new TestedServiceInstance();
+            }
+
+            public boolean isAvailable( TestedService instance )
+            {
+                return true;
+            }
+
+        }
+
+    }
+
+    @Before
+    public void beforeEachTest()
+    {
+        activationLevel = 0;
+        passivationLevel = 0;
+    }
+
+    @Test
+    public void testNewInstanceImportedServiceActivators()
+            throws Exception
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                module.importedServices( TestedService.class ).
+                        withActivators( TestedActivator.class ).
+                        setMetaInfo( new TestedServiceInstance() ).
+                        importOnStartup();
+            }
+
+        };
+        Application application = assembler.application();
+        assertEquals( "Activation Level", 2, activationLevel );
+        application.passivate();
+        assertEquals( "Passivation Level", 2, passivationLevel );
+    }
+
+    @Test
+    public void testNewObjectImportedServiceActivators()
+            throws Exception
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                module.importedServices( TestedService.class ).
+                        importedBy( ImportedServiceDeclaration.NEW_OBJECT ).
+                        withActivators( TestedActivator.class ).
+                        importOnStartup();
+                module.objects( TestedServiceInstance.class );
+            }
+
+        };
+        Application application = assembler.application();
+        assertEquals( "Activation Level", 2, activationLevel );
+        application.passivate();
+        assertEquals( "Passivation Level", 2, passivationLevel );
+    }
+
+    @Test
+    public void testServiceImporterImportedServiceActivators()
+            throws Exception
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                module.importedServices( TestedService.class ).
+                        importedBy( ImportedServiceDeclaration.SERVICE_IMPORTER ).
+                        setMetaInfo( new StringIdentity( "testimporter" ) ).
+                        withActivators( TestedActivator.class ).
+                        importOnStartup();
+                module.services( TestedServiceImporterService.class ).identifiedBy( "testimporter" );
+            }
+
+        };
+        Application application = assembler.application();
+        assertEquals( "Activation Level", 2, activationLevel );
+        application.passivate();
+        assertEquals( "Passivation Level", 2, passivationLevel );
+    }
+
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/activation/IntraMixinActivationOrderTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/IntraMixinActivationOrderTest.java
new file mode 100644
index 0000000..2d6eb39
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/IntraMixinActivationOrderTest.java
@@ -0,0 +1,213 @@
+/*
+ *  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.polygene.runtime.activation;
+
+import java.util.Arrays;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.runtime.activation.ActivatorOrderTestSupport.ActivationStep;
+import org.apache.polygene.runtime.activation.ActivatorOrderTestSupport.ActivationStepsRecorder;
+import org.apache.polygene.runtime.activation.ActivatorOrderTestSupport.ActivationStepsRecorderInstance;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Assert that intra-mixin activation order is correct.
+ * Alpha* depends on Beta* to be activated.
+ */
+public class IntraMixinActivationOrderTest
+{
+
+    public static final ActivationStepsRecorder RECORDER = new ActivationStepsRecorderInstance();
+
+    @Before
+    public void beforeEachTest()
+    {
+        RECORDER.reset();
+    }
+
+    public interface AlphaMixinType
+    {
+    }
+
+    public static class AlphaMixin
+        implements AlphaMixinType, AlphaActivation
+    {
+
+        @This
+        private BetaMixinType beta;
+
+        @Override
+        public void setupAlpha()
+        {
+            beta.ensureActivated();
+            RECORDER.record( new ActivationStep( "alpha", "setup" ) );
+        }
+
+        @Override
+        public void tearDownAlpha()
+        {
+            RECORDER.record( new ActivationStep( "alpha", "tear-down" ) );
+        }
+
+    }
+
+    public interface BetaMixinType
+    {
+
+        void ensureActivated();
+
+    }
+
+    public static class BetaMixin
+        implements BetaMixinType, BetaActivation
+    {
+
+        private boolean activated = false;
+
+        @Override
+        public void ensureActivated()
+        {
+            if( !activated )
+            {
+                throw new IllegalStateException( "BetaMixin is not activated" );
+            }
+        }
+
+        @Override
+        public void setupBeta()
+        {
+            RECORDER.record( new ActivationStep( "beta", "setup" ) );
+            activated = true;
+        }
+
+        @Override
+        public void tearDownBeta()
+        {
+            RECORDER.record( new ActivationStep( "beta", "tear-down" ) );
+            activated = false;
+        }
+
+    }
+
+    @Activators( AlphaActivation.AlphaActivator.class )
+    @Mixins( AlphaMixin.class )
+    public interface AlphaActivation
+    {
+
+        void setupAlpha();
+
+        void tearDownAlpha();
+
+        public class AlphaActivator
+            extends ActivatorAdapter<ServiceReference<AlphaActivation>>
+        {
+
+            @Override
+            public void afterActivation( ServiceReference<AlphaActivation> activated )
+                throws Exception
+            {
+                activated.get().setupAlpha();
+            }
+
+            @Override
+            public void beforePassivation( ServiceReference<AlphaActivation> passivating )
+                throws Exception
+            {
+                passivating.get().tearDownAlpha();
+            }
+
+        }
+
+    }
+
+    @Activators( BetaActivation.BetaActivator.class )
+    @Mixins( BetaMixin.class )
+    public interface BetaActivation
+    {
+
+        void setupBeta();
+
+        void tearDownBeta();
+
+        public class BetaActivator
+            extends ActivatorAdapter<ServiceReference<BetaActivation>>
+        {
+
+            @Override
+            public void afterActivation( ServiceReference<BetaActivation> activated )
+                throws Exception
+            {
+                activated.get().setupBeta();
+            }
+
+            @Override
+            public void beforePassivation( ServiceReference<BetaActivation> passivating )
+                throws Exception
+            {
+                passivating.get().tearDownBeta();
+            }
+
+        }
+
+    }
+
+    // Order of declaration here ensure that Beta is activated before Alpha
+    public interface UnderTestServiceType
+        extends BetaActivation, AlphaActivation
+    {
+    }
+
+    @Test
+    public void test()
+        throws AssemblyException, ActivationException, PassivationException
+    {
+        new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.services( UnderTestServiceType.class ).instantiateOnStartup();
+            }
+        }.application().passivate();
+        // System.out.println( RECORDER.steps() );
+        String expected = Arrays.toString( new String[]
+        {
+            "beta.setup",
+            "alpha.setup",
+            "alpha.tear-down",
+            "beta.tear-down",
+        } );
+        String actual = Arrays.toString( RECORDER.steps().toArray() );
+        assertEquals( expected, actual );
+    }
+
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/activation/LayerActivationTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/LayerActivationTest.java
new file mode 100644
index 0000000..cfa7a57
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/LayerActivationTest.java
@@ -0,0 +1,91 @@
+/*
+ *  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.polygene.runtime.activation;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+public class LayerActivationTest
+{
+
+    private static int activationLevel = 0;
+
+    private static int passivationLevel = 0;
+
+    public static class TestedActivator
+            implements Activator<Layer>
+    {
+
+        public void beforeActivation( Layer activating )
+        {
+            activationLevel++;
+        }
+
+        public void afterActivation( Layer activated )
+        {
+            activationLevel++;
+        }
+
+        public void beforePassivation( Layer passivating )
+        {
+            passivationLevel++;
+        }
+
+        public void afterPassivation( Layer passivated )
+        {
+            passivationLevel++;
+        }
+
+    }
+
+    @Test
+    public void testLayersActivators()
+            throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                module.layer().withActivators( TestedActivator.class );
+            }
+
+        };
+        // Activate
+        Application application = assembly.application();
+
+        // Assert activated
+        Assert.assertEquals( "Activation Level", 2, activationLevel );
+
+        // Passivate
+        application.passivate();
+
+        // Assert passivated
+        Assert.assertEquals( "Passivation Level", 2, passivationLevel );
+    }
+
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ModuleActivationTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ModuleActivationTest.java
new file mode 100644
index 0000000..b6e3e2a
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ModuleActivationTest.java
@@ -0,0 +1,91 @@
+/*
+ *  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.polygene.runtime.activation;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+public class ModuleActivationTest
+{
+
+    private static int activationLevel = 0;
+
+    private static int passivationLevel = 0;
+
+    public static class TestedActivator
+            implements Activator<Module>
+    {
+
+        public void beforeActivation( Module activating )
+        {
+            activationLevel++;
+        }
+
+        public void afterActivation( Module activated )
+        {
+            activationLevel++;
+        }
+
+        public void beforePassivation( Module passivating )
+        {
+            passivationLevel++;
+        }
+
+        public void afterPassivation( Module passivated )
+        {
+            passivationLevel++;
+        }
+
+    }
+
+    @Test
+    public void testModulesActivators()
+            throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                module.withActivators( TestedActivator.class );
+            }
+
+        };
+        // Activate
+        Application application = assembly.application();
+
+        // Assert activated
+        Assert.assertEquals( "Activation Level", 2, activationLevel );
+
+        // Passivate
+        application.passivate();
+
+        // Assert passivated
+        Assert.assertEquals( "Passivation Level", 2, passivationLevel );
+    }
+
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ServiceActivationTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ServiceActivationTest.java
new file mode 100644
index 0000000..708c6fa
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ServiceActivationTest.java
@@ -0,0 +1,145 @@
+/*
+ *  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.polygene.runtime.activation;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+public class ServiceActivationTest
+{
+
+    private static int activationLevel = 0;
+
+    private static int passivationLevel = 0;
+
+    public static class TestedActivator
+            implements Activator<ServiceReference<TestedService>>
+    {
+
+        public void beforeActivation( ServiceReference<TestedService> activating )
+        {
+            Assert.assertFalse( "Service should not be active before activation", activating.isActive() );
+            try {
+                activating.get();
+                Assert.fail( "Service is not activated yet, the reference get method should throw IllegalStateException." );
+            } catch ( IllegalStateException expected ) {
+            }
+            activationLevel++;
+        }
+
+        public void afterActivation( ServiceReference<TestedService> activated )
+        {
+            Assert.assertTrue( "Service should be active after activation", activated.isActive() );
+            Assert.assertEquals( "After activation", "bar", activated.get().foo() );
+            activationLevel++;
+        }
+
+        public void beforePassivation( ServiceReference<TestedService> passivating )
+        {
+            Assert.assertTrue( "Service should be active before passivation", passivating.isActive() );
+            Assert.assertEquals( "Before passivation", "bar", passivating.get().foo() );
+            passivationLevel++;
+        }
+
+        public void afterPassivation( ServiceReference<TestedService> passivated )
+        {
+            Assert.assertFalse( "Service should not be active after passivation", passivated.isActive() );
+            try {
+                passivated.get();
+                Assert.fail( "Service is passivated, the reference get method should throw IllegalStateException." );
+            } catch ( IllegalStateException expected ) {
+            }
+            passivationLevel++;
+        }
+
+    }
+
+    @Mixins( TestedServiceMixin.class )
+    public static interface TestedServiceComposite
+            extends TestedService, ServiceComposite
+    {
+    }
+
+    @Mixins( TestedServiceMixin.class )
+    public static interface TestedServiceComposite2
+            extends TestedService, ServiceComposite
+    {
+    }
+
+    public static interface TestedService
+    {
+
+        String foo();
+
+    }
+
+    public static class TestedServiceMixin
+            implements TestedService
+    {
+
+        public String foo()
+        {
+            return "bar";
+        }
+
+    }
+
+    @Test
+    public void testServicesActivators()
+            throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                module.addServices( TestedServiceComposite.class ).
+                        withActivators( TestedActivator.class ).
+                        instantiateOnStartup();
+                module.addServices( TestedServiceComposite2.class ).
+                        withActivators( TestedActivator.class ).
+                        instantiateOnStartup();
+            }
+
+        };
+        // Activate
+        Application application = assembly.application();
+
+        // Assert activated
+        Assert.assertEquals( "Activation Level", 4, activationLevel );
+
+        // Passivate
+        application.passivate();
+
+        // Assert passivated
+        Assert.assertEquals( "Passivation Level", 4, passivationLevel );
+    }
+
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ServiceActivatorOrderTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ServiceActivatorOrderTest.java
new file mode 100644
index 0000000..20a91de
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/ServiceActivatorOrderTest.java
@@ -0,0 +1,368 @@
+/*
+ *  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.polygene.runtime.activation;
+
+import java.util.Arrays;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.runtime.activation.ActivatorOrderTestSupport.ActivationStepsRecorder;
+import org.apache.polygene.runtime.activation.ActivatorOrderTestSupport.ActivationStepsRecorderInstance;
+import org.apache.polygene.runtime.activation.ActivatorOrderTestSupport.Expected;
+import org.apache.polygene.runtime.activation.ActivatorOrderTestSupport.OrderTestActivator;
+
+import static org.junit.Assert.assertEquals;
+
+public class ServiceActivatorOrderTest
+{
+
+    //
+    // ActivationStepsRecorder --------------------------------------------
+    //
+    public static final ActivationStepsRecorder RECORDER = new ActivationStepsRecorderInstance();
+
+    @Before
+    public void beforeEachTest()
+    {
+        RECORDER.reset();
+    }
+
+    //
+    // FooBarService ------------------------------------------------------
+    //
+    public static interface FooBar
+    {
+        
+        String foo();
+        
+    }
+
+    public static abstract class FooBarInstance
+            implements FooBar
+    {
+
+        @Override
+        public String foo()
+        {
+            return "bar";
+        }
+
+    }
+
+    @Mixins( FooBarInstance.class )
+    public static interface FooBarService
+            extends FooBar, ServiceComposite
+    {
+    }
+
+    @Mixins( FooBarInstance.class )
+    @Activators( { GammaActivator.class, DeltaActivator.class } )
+    public static interface FooBarServiceWithActivators
+            extends FooBar, ServiceComposite
+    {
+    }
+
+    //
+    // BazarService ------------------------------------------------------
+    //
+    @Activators( GammaActivator.class )
+    public static interface Bazar
+            extends Things, Stuff
+    {
+    }
+    
+    @Activators( DeltaActivator.class )
+    public static interface Things
+    {
+        
+        String things();
+        
+    }
+    
+    @Activators( EpsilonActivator.class )
+    public static interface Stuff
+    {
+        
+        String stuff();
+        
+    }
+    
+    public static class ThingsInstance
+            implements Things
+    {
+
+        @Override
+        public String things()
+        {
+            return "things";
+        }
+        
+    }
+    
+    public static class StuffInstance
+            implements Stuff
+    {
+
+        @Override
+        public String stuff()
+        {
+            return "stuff";
+        }
+        
+    }
+    
+    @Mixins( { ThingsInstance.class, StuffInstance.class } )
+    @Activators( BetaActivator.class )
+    public static interface BazarService
+            extends Bazar, ServiceComposite
+    {
+    }
+    
+    //
+    // Activators in order: Alpha, Beta, Gamma, Delta, Epsilon, Zeta ------
+    //
+    public static class AlphaActivator
+            extends OrderTestActivator<ServiceReference<?>>
+    {
+
+        public AlphaActivator()
+        {
+            super( "Alpha", RECORDER );
+        }
+
+    }
+
+    public static class BetaActivator
+            extends OrderTestActivator<ServiceReference<?>>
+    {
+
+        public BetaActivator()
+        {
+            super( "Beta", RECORDER );
+        }
+
+    }
+
+    public static class GammaActivator
+            extends OrderTestActivator<ServiceReference<?>>
+    {
+
+        public GammaActivator()
+        {
+            super( "Gamma", RECORDER );
+        }
+
+    }
+
+    public static class DeltaActivator
+            extends OrderTestActivator<ServiceReference<?>>
+    {
+
+        public DeltaActivator()
+        {
+            super( "Delta", RECORDER );
+        }
+
+    }
+
+    public static class EpsilonActivator
+            extends OrderTestActivator<ServiceReference<?>>
+    {
+
+        public EpsilonActivator()
+        {
+            super( "Epsilon", RECORDER );
+        }
+
+    }
+
+    public static class ZetaActivator
+            extends OrderTestActivator<ServiceReference<?>>
+    {
+
+        public ZetaActivator()
+        {
+            super( "Zeta", RECORDER );
+        }
+
+    }
+
+    //
+    // Tests --------------------------------------------------------------
+    //
+    @Test
+    public void testTwoActivatorsOrderOnSimpleService()
+            throws Exception
+    {
+        new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                module.services( FooBarService.class ).
+                        withActivators( AlphaActivator.class, BetaActivator.class ).
+                        instantiateOnStartup();
+            }
+
+        }.application().passivate();
+
+        String actual = Arrays.toString( RECORDER.steps().toArray() );
+        // System.out.println( "\n" + Expected.ALPHA_BETA_SINGLE + "\n" + actual + "\n" );
+        assertEquals( Expected.ALPHA_BETA_SINGLE, actual );
+    }
+
+    @Test
+    public void testAnnotationActivatorsOrderOnSimpleService()
+            throws Exception
+    {
+        new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                module.services( FooBarServiceWithActivators.class ).
+                        instantiateOnStartup();
+            }
+
+        }.application().passivate();
+
+        String expected = Arrays.toString( new String[]{
+                    "Gamma.beforeActivation",   // Annotation
+                    "Delta.beforeActivation",   // Annotation
+                    // -> Activation
+                    "Gamma.afterActivation",
+                    "Delta.afterActivation",
+                    // -> Active
+                    "Delta.beforePassivation",
+                    "Gamma.beforePassivation",
+                    // -> Passivation
+                    "Delta.afterPassivation",
+                    "Gamma.afterPassivation"
+                } );
+
+        String actual = Arrays.toString( RECORDER.steps().toArray() );
+        // System.out.println( "\n" + expected + "\n" + actual + "\n" );
+        assertEquals( expected, actual );
+    }
+
+    @Test
+    public void testMixedAnnotationAndAssemblyActivatorsOrderOnSimpleService()
+            throws Exception
+    {
+        new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                module.services( FooBarServiceWithActivators.class ).
+                        withActivators( AlphaActivator.class, BetaActivator.class ).
+                        instantiateOnStartup();
+            }
+
+        }.application().passivate();
+
+        String expected = Arrays.toString( new String[]{
+                    "Alpha.beforeActivation",   // Assembly
+                    "Beta.beforeActivation",    // Assembly
+                    "Gamma.beforeActivation",   // Annotation
+                    "Delta.beforeActivation",   // Annotation
+                    // -> Activation
+                    "Alpha.afterActivation",
+                    "Beta.afterActivation",
+                    "Gamma.afterActivation",
+                    "Delta.afterActivation",
+                    // -> Active
+                    "Delta.beforePassivation",
+                    "Gamma.beforePassivation",
+                    "Beta.beforePassivation",
+                    "Alpha.beforePassivation",
+                    // -> Passivation
+                    "Delta.afterPassivation",
+                    "Gamma.afterPassivation",
+                    "Beta.afterPassivation",
+                    "Alpha.afterPassivation"
+                } );
+
+        String actual = Arrays.toString( RECORDER.steps().toArray() );
+        // System.out.println( "\n" + expected + "\n" + actual + "\n" );
+        assertEquals( expected, actual );
+    }
+    
+    @Test
+    public void testMixedAnnotationAndAssemblyActivatorsOrderOnComplexService()
+            throws Exception
+    {
+        new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                module.services( BazarService.class ).
+                        withActivators( AlphaActivator.class ).
+                        instantiateOnStartup();
+            }
+
+        }.application().passivate();
+        
+        String expected = Arrays.toString( new String[]{
+                    "Alpha.beforeActivation",   // Assembly
+                    "Beta.beforeActivation",    // Service type annotation
+                    "Gamma.beforeActivation",   // Base type annotation
+                    "Delta.beforeActivation",   // First composite type annotation
+                    "Epsilon.beforeActivation", // Second composite type annotation
+                    // -> Activation
+                    "Alpha.afterActivation",
+                    "Beta.afterActivation",
+                    "Gamma.afterActivation",
+                    "Delta.afterActivation",
+                    "Epsilon.afterActivation",
+                    // -> Active
+                    "Epsilon.beforePassivation",
+                    "Delta.beforePassivation",
+                    "Gamma.beforePassivation",
+                    "Beta.beforePassivation",
+                    "Alpha.beforePassivation",
+                    // -> Passivation
+                    "Epsilon.afterPassivation",
+                    "Delta.afterPassivation",
+                    "Gamma.afterPassivation",
+                    "Beta.afterPassivation",
+                    "Alpha.afterPassivation"
+        } );
+        String actual = Arrays.toString( RECORDER.steps().toArray() );
+        // System.out.println( "\n" + expected + "\n" + actual + "\n" );
+        assertEquals( expected, actual );
+    }
+
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/activation/StructureActivatorOrderTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/StructureActivatorOrderTest.java
new file mode 100644
index 0000000..f130b18
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/activation/StructureActivatorOrderTest.java
@@ -0,0 +1,264 @@
+/*
+ *  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.polygene.runtime.activation;
+
+import java.util.Arrays;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.runtime.activation.ActivatorOrderTestSupport.ActivationStepsRecorder;
+import org.apache.polygene.runtime.activation.ActivatorOrderTestSupport.ActivationStepsRecorderInstance;
+import org.apache.polygene.runtime.activation.ActivatorOrderTestSupport.Expected;
+import org.apache.polygene.runtime.activation.ActivatorOrderTestSupport.OrderTestActivator;
+
+import static org.junit.Assert.assertEquals;
+
+public class StructureActivatorOrderTest
+{
+
+    //
+    // ActivationStepsRecorder --------------------------------------------
+    //
+    public static final ActivationStepsRecorder RECORDER = new ActivationStepsRecorderInstance();
+
+    @Before
+    public void beforeEachTest()
+    {
+        RECORDER.reset();
+    }
+
+    //
+    // Activators in order: Alpha, Beta -----------------------------------
+    //
+    public static class AlphaApplicationActivator
+            extends OrderTestActivator<Application>
+    {
+
+        public AlphaApplicationActivator()
+        {
+            super( "Alpha", RECORDER );
+        }
+
+    }
+
+    public static class BetaApplicationActivator
+            extends OrderTestActivator<Application>
+    {
+
+        public BetaApplicationActivator()
+        {
+            super( "Beta", RECORDER );
+        }
+
+    }
+
+    public static class AlphaLayerActivator
+            extends OrderTestActivator<Layer>
+    {
+
+        public AlphaLayerActivator()
+        {
+            super( "Alpha", RECORDER );
+        }
+
+    }
+
+    public static class BetaLayerActivator
+            extends OrderTestActivator<Layer>
+    {
+
+        public BetaLayerActivator()
+        {
+            super( "Beta", RECORDER );
+        }
+
+    }
+
+    public static class AlphaModuleActivator
+            extends OrderTestActivator<Module>
+    {
+
+        public AlphaModuleActivator()
+        {
+            super( "Alpha", RECORDER );
+        }
+
+    }
+
+    public static class BetaModuleActivator
+            extends OrderTestActivator<Module>
+    {
+
+        public BetaModuleActivator()
+        {
+            super( "Beta", RECORDER );
+        }
+
+    }
+
+    //
+    // Tests --------------------------------------------------------------
+    //
+    @Test
+    public void testTwoActivatorsOrderOnApplication()
+            throws Exception
+    {
+        new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                module.layer().application().withActivators( AlphaApplicationActivator.class,
+                                                             BetaApplicationActivator.class );
+            }
+
+        }.application().passivate();
+
+        String actual = Arrays.toString( RECORDER.steps().toArray() );
+        System.out.println( "\n" + Expected.ALPHA_BETA_SINGLE + "\n" + actual + "\n" );
+        assertEquals( Expected.ALPHA_BETA_SINGLE, actual );
+    }
+
+    @Test
+    public void testTwoActivatorsOrderOnLayer()
+            throws Exception
+    {
+        new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                module.layer().withActivators( AlphaLayerActivator.class,
+                                               BetaLayerActivator.class );
+            }
+
+        }.application().passivate();
+
+        String actual = Arrays.toString( RECORDER.steps().toArray() );
+        System.out.println( "\n" + Expected.ALPHA_BETA_SINGLE + "\n" + actual + "\n" );
+        assertEquals( Expected.ALPHA_BETA_SINGLE, actual );
+    }
+
+    @Test
+    public void testTwoActivatorsOrderOnModule()
+            throws Exception
+    {
+        new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                module.withActivators( AlphaModuleActivator.class,
+                                       BetaModuleActivator.class );
+            }
+
+        }.application().passivate();
+
+        String actual = Arrays.toString( RECORDER.steps().toArray() );
+        System.out.println( "\n" + Expected.ALPHA_BETA_SINGLE + "\n" + actual + "\n" );
+        assertEquals( Expected.ALPHA_BETA_SINGLE, actual );
+    }
+
+    @Test
+    public void testTwoActivatorsOrderOnApplicationLayerAndModule()
+            throws Exception
+    {
+        new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                module.layer().application().withActivators( AlphaApplicationActivator.class,
+                                                             BetaApplicationActivator.class );
+                module.layer().withActivators( AlphaLayerActivator.class,
+                                               BetaLayerActivator.class );
+                module.withActivators( AlphaModuleActivator.class,
+                                       BetaModuleActivator.class );
+            }
+
+        }.application().passivate();
+
+        String expected = Arrays.toString( new String[]{
+                    // Application.beforeActivation
+                    "Alpha.beforeActivation",
+                    "Beta.beforeActivation",
+                    // Layer.beforeActivation
+                    "Alpha.beforeActivation",
+                    "Beta.beforeActivation",
+                    // Module.beforeActivation
+                    "Alpha.beforeActivation",
+                    "Beta.beforeActivation",
+                    //
+                    // -> Activation
+                    //
+                    // Application.afterActivation
+                    "Alpha.afterActivation",
+                    "Beta.afterActivation",
+                    // Layer.afterActivation
+                    "Alpha.afterActivation",
+                    "Beta.afterActivation",
+                    // Module.afterActivation
+                    "Alpha.afterActivation",
+                    "Beta.afterActivation",
+                    //
+                    // -> Active
+                    //
+                    // Module.beforePassivation
+                    "Beta.beforePassivation",
+                    "Alpha.beforePassivation",
+                    // Layer.beforePassivation
+                    "Beta.beforePassivation",
+                    "Alpha.beforePassivation",
+                    // Application.beforePassivation
+                    "Beta.beforePassivation",
+                    "Alpha.beforePassivation",
+                    //
+                    // -> Passivation
+                    //
+                    // Module.afterPassivation
+                    "Beta.afterPassivation",
+                    "Alpha.afterPassivation",
+                    // Layer.afterPassivation
+                    "Beta.afterPassivation",
+                    "Alpha.afterPassivation",
+                    // Application.afterPassivation
+                    "Beta.afterPassivation",
+                    "Alpha.afterPassivation"
+                } );
+
+        String actual = Arrays.toString( RECORDER.steps().toArray() );
+        System.out.println( "\n" + expected + "\n" + actual + "\n" );
+        assertEquals( expected, actual );
+    }
+
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/appliesto/AppliesToFilterTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/appliesto/AppliesToFilterTest.java
new file mode 100644
index 0000000..4fe8ba0
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/appliesto/AppliesToFilterTest.java
@@ -0,0 +1,113 @@
+/*
+ *  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.polygene.runtime.appliesto;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.AppliesToFilter;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.concern.GenericConcern;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+/**
+ * Test of the AppliesToFilter
+ */
+public class AppliesToFilterTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( SomeComposite.class );
+    }
+
+    @Test
+    public void givenAnAppliesToFilterWhenAppliedThenFilterMethods()
+        throws Exception
+    {
+        Some some = transientBuilderFactory.newTransient( Some.class );
+        Assert.assertEquals( ",", some.doStuff1() );
+        Assert.assertEquals( ",,..", some.doStuff2() );
+        Assert.assertEquals( ",,,", some.doStuff3() );
+    }
+
+    @Concerns( MyConcern.class )
+    @Mixins( SomeMixin.class )
+    private interface SomeComposite
+        extends Some, TransientComposite
+    {
+    }
+
+    public static interface Some
+    {
+        String doStuff1();
+
+        String doStuff2();
+
+        String doStuff3();
+    }
+
+    @AppliesTo( TestFilter.class )
+    public static class MyConcern
+        extends GenericConcern
+    {
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            String str = (String) next.invoke( proxy, method, args );
+            return str + "..";
+        }
+    }
+
+    public static class SomeMixin
+        implements Some
+    {
+
+        public String doStuff1()
+        {
+            return ",";
+        }
+
+        public String doStuff2()
+        {
+            return ",,";
+        }
+
+        public String doStuff3()
+        {
+            return ",,,";
+        }
+    }
+
+    public static class TestFilter
+        implements AppliesToFilter
+    {
+        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
+        {
+            return method.getName().equals( "doStuff2" );
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/appliesto/AppliesToOrConditionQI241Test.java b/core/runtime/src/test/java/org/apache/polygene/runtime/appliesto/AppliesToOrConditionQI241Test.java
new file mode 100644
index 0000000..6a01c0c
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/appliesto/AppliesToOrConditionQI241Test.java
@@ -0,0 +1,251 @@
+/*
+ *  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.polygene.runtime.appliesto;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.injection.InjectionScope;
+import org.apache.polygene.api.injection.scope.Invocation;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.junit.Assert.assertTrue;
+
+public class AppliesToOrConditionQI241Test
+    extends AbstractPolygeneTest
+{
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( SomeServiceCompositeWithTwoAnnotations.class );
+        module.services( SomeServiceCompositeWithFirstAnnotation.class );
+        module.services( SomeServiceCompositeWithSecondAnnotation.class );
+    }
+
+    @Test
+    public void testMultiConcerns1()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+
+        try
+        {
+            ServiceReference<SomeServiceCompositeWithFirstAnnotation> refWithFirst = serviceFinder.findService(
+                SomeServiceCompositeWithFirstAnnotation.class );
+            SomeServiceCompositeWithFirstAnnotation someWithFirst = refWithFirst.get();
+            someWithFirst.doStuff();
+            assertTrue( "AppliesTo did not match with first annotation", someWithFirst.concernHasBeenPlayed() );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void testMultiConcerns2()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+
+        try
+        {
+            ServiceReference<SomeServiceCompositeWithSecondAnnotation> refWithSecond = serviceFinder.findService(
+                SomeServiceCompositeWithSecondAnnotation.class );
+            SomeServiceCompositeWithSecondAnnotation someWithSecond = refWithSecond.get();
+            someWithSecond.doStuff();
+            assertTrue( "AppliesTo did not match with second annotation", someWithSecond.concernHasBeenPlayed() );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void testMultiConcernsBoth()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+
+        try
+        {
+            ServiceReference<SomeServiceCompositeWithTwoAnnotations> refWithTwo = serviceFinder.findService(
+                SomeServiceCompositeWithTwoAnnotations.class );
+            SomeServiceCompositeWithTwoAnnotations someWithTwo = refWithTwo.get();
+            someWithTwo.doStuff();
+            assertTrue( "AppliesTo did not match with two annotations", someWithTwo.concernHasBeenPlayed() );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Mixins( SomeMixinWithTwoAnnotations.class )
+    @Concerns( MultiConcerns.class )
+    public interface SomeServiceCompositeWithTwoAnnotations
+        extends SomeService, ServiceComposite
+    {
+    }
+
+    @Mixins( SomeMixinWithFirstAnnotation.class )
+    @Concerns( MultiConcerns.class )
+    public interface SomeServiceCompositeWithFirstAnnotation
+        extends SomeService, ServiceComposite
+    {
+    }
+
+    @Mixins( SomeMixinWithSecondAnnotation.class )
+    @Concerns( MultiConcerns.class )
+    public interface SomeServiceCompositeWithSecondAnnotation
+        extends SomeService, ServiceComposite
+    {
+    }
+
+    public interface SomeService
+    {
+
+        String doStuff();
+
+        /**
+         * Only for assertion purpose.
+         */
+        void playConcern();
+
+        /**
+         * Only for assertion purpose.
+         */
+        boolean concernHasBeenPlayed();
+    }
+
+    public static abstract class SomeBaseMixin
+        implements SomeService
+    {
+        private boolean played = false;
+
+        public void playConcern()
+        {
+            played = true;
+        }
+
+        public boolean concernHasBeenPlayed()
+        {
+            return played;
+        }
+    }
+
+    public static abstract class SomeMixinWithTwoAnnotations
+        extends SomeBaseMixin
+        implements SomeService
+    {
+        @FirstAnnotation( "first one" )
+        @SecondAnnotation( "second one" )
+        public String doStuff()
+        {
+            return "Blah blah";
+        }
+    }
+
+    public static abstract class SomeMixinWithFirstAnnotation
+        extends SomeBaseMixin
+        implements SomeService
+    {
+
+        @FirstAnnotation( "first one" )
+        public String doStuff()
+        {
+            return "Blah blah";
+        }
+    }
+
+    public static abstract class SomeMixinWithSecondAnnotation
+        extends SomeBaseMixin
+        implements SomeService
+    {
+        @SecondAnnotation( "second one" )
+        public String doStuff()
+        {
+            return "Blah blah";
+        }
+    }
+
+    @Retention( RetentionPolicy.RUNTIME )
+    @Target( { ElementType.METHOD } )
+    @InjectionScope
+    public @interface FirstAnnotation
+    {
+        String value();
+    }
+
+    @Retention( RetentionPolicy.RUNTIME )
+    @Target( { ElementType.METHOD } )
+    @InjectionScope
+    public @interface SecondAnnotation
+    {
+        String value();
+    }
+
+    @AppliesTo( { FirstAnnotation.class, SecondAnnotation.class } )
+    public static class MultiConcerns
+        extends ConcernOf<InvocationHandler>
+        implements InvocationHandler
+    {
+
+        @Optional
+        @Invocation
+        private FirstAnnotation first;
+
+        @Optional
+        @Invocation
+        private SecondAnnotation second;
+
+        @This
+        private SomeService someServiceComposite;
+
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            if( first != null )
+            {
+                System.err.println( "FIRST IS HERE AND HAS VALUE: " + first.value() );
+            }
+            if( second != null )
+            {
+                System.err.println( "SECOND IS HERE AND HAS VALUE: " + second.value() );
+            }
+            someServiceComposite.playConcern();
+            return next.invoke( proxy, method, args );
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/appliesto/AppliesToTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/appliesto/AppliesToTest.java
new file mode 100644
index 0000000..5af4e96
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/appliesto/AppliesToTest.java
@@ -0,0 +1,137 @@
+/*
+ *  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.polygene.runtime.appliesto;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+/**
+ * Test of the @AppliesTo annotation
+ */
+public class AppliesToTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( SomeComposite.class );
+    }
+
+    @Test
+    public void givenAnAppliesToWhenNoAnnotationExpectNoConcernInInvocationStack()
+        throws Exception
+    {
+        Some some = transientBuilderFactory.newTransient( Some.class );
+        Assert.assertEquals( ",", some.doStuff1() );
+    }
+
+    @Test
+    public void givenAnAppliesToWhenAnnotationIsOnMixinTypeExpectConcernInInvocationStack()
+        throws Exception
+    {
+        Some some = transientBuilderFactory.newTransient( Some.class );
+        Assert.assertEquals( ",,..", some.doStuff2() );
+    }
+
+    @Test
+    public void givenAnAppliesToWhenAnnotationIsOnMixinImplementationExpectConcernInInvocationStack()
+        throws Exception
+    {
+        Some some = transientBuilderFactory.newTransient( Some.class );
+        Assert.assertEquals( ",", some.doStuff1() );
+        Assert.assertEquals( ",,..", some.doStuff2() );
+        Assert.assertEquals( ",,,", some.doStuff3() );
+    }
+
+    @Concerns( MyConcern.class )
+    @Mixins( SomeMixin.class )
+    private interface SomeComposite
+        extends Some, TransientComposite
+    {
+    }
+
+    public static interface Some
+    {
+        String doStuff1();
+
+        @Foo
+        String doStuff2();
+
+        String doStuff3();
+    }
+
+    @AppliesTo( Foo.class )
+    public static class MyConcern
+        extends ConcernOf<Some>
+        implements Some
+    {
+
+        public String doStuff1()
+        {
+            return next.doStuff1() + ".";
+        }
+
+        public String doStuff2()
+        {
+            return next.doStuff2() + "..";
+        }
+
+        public String doStuff3()
+        {
+            return next.doStuff3() + "...";
+        }
+    }
+
+    public static class SomeMixin
+        implements Some
+    {
+
+        public String doStuff1()
+        {
+            return ",";
+        }
+
+        public String doStuff2()
+        {
+            return ",,";
+        }
+
+        @Foo
+        public String doStuff3()
+        {
+            return ",,,";
+        }
+    }
+
+    @Retention( RetentionPolicy.RUNTIME )
+    private @interface Foo
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/appliesto/FragmentAppliesToTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/appliesto/FragmentAppliesToTest.java
new file mode 100644
index 0000000..d0fb47e
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/appliesto/FragmentAppliesToTest.java
@@ -0,0 +1,169 @@
+/*
+ *  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.polygene.runtime.appliesto;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+import org.junit.Test;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.sideeffect.GenericSideEffect;
+import org.apache.polygene.api.sideeffect.SideEffects;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class FragmentAppliesToTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( Composite1.class );
+    }
+
+    @Test
+    public void testMixin()
+        throws Exception
+    {
+        TransientBuilder<Composite1> builder = transientBuilderFactory.newTransientBuilder( Composite1.class );
+
+        Composite1 instance = builder.newInstance();
+        assertNotNull( "DependencyOld not injected.", instance.getBuilderFactory() );
+        assertNotNull( "This not injected.", instance.getMeAsMixin2() );
+        assertEquals( 1, instance.getValue() );
+        instance.getBuilderFactory();
+        instance.getMeAsMixin2();
+        instance.getBuilderFactory();
+        instance.getMeAsMixin2();
+        instance.getMeAsMixin2();
+        instance.getBuilderFactory();
+        assertEquals( 4, instance.getValue() );
+    }
+
+    @Mixins( { Mixin1.Mixin1Impl.class, Mixin2.Mixin2Impl.class, CounterImpl.class } )
+    public interface Composite1
+        extends TransientComposite, Mixin1, Mixin2, Counter
+    {
+    }
+
+    public interface Mixin1
+    {
+        TransientBuilderFactory getBuilderFactory();
+
+        Mixin2 getMeAsMixin2();
+
+        @SideEffects( CountCallsSideEffect.class )
+        public static class Mixin1Impl
+            implements Mixin1
+        {
+
+            @Structure
+            private TransientBuilderFactory builderFactory;
+
+            @This
+            private Mixin2 meAsMixin2;
+
+            @CountCalls
+            public TransientBuilderFactory getBuilderFactory()
+            {
+                return builderFactory;
+            }
+
+            public Mixin2 getMeAsMixin2()
+            {
+                return meAsMixin2;
+            }
+        }
+    }
+
+    public static class CounterImpl
+        implements Counter
+    {
+        private int value;
+
+        public void increment()
+        {
+            value++;
+        }
+
+        public void clear()
+        {
+            value = 0;
+        }
+
+        public int getValue()
+        {
+            return value;
+        }
+    }
+
+    public interface Mixin2
+    {
+        public static class Mixin2Impl
+            implements Mixin2
+        {
+        }
+    }
+
+    public interface Counter
+    {
+        void increment();
+
+        void clear();
+
+        int getValue();
+    }
+
+    @AppliesTo( CountCalls.class )
+    public static class CountCallsSideEffect
+        extends GenericSideEffect
+    {
+
+        @This
+        private Counter counter;
+
+        protected void invoke( Method method, Object[] args )
+        {
+            counter.increment();
+        }
+    }
+
+    @Retention( RetentionPolicy.RUNTIME )
+    @Target( ElementType.METHOD )
+    @Documented
+    @Inherited
+    public @interface CountCalls
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/association/AssociationAssignmentTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/association/AssociationAssignmentTest.java
new file mode 100644
index 0000000..c3131eb
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/association/AssociationAssignmentTest.java
@@ -0,0 +1,80 @@
+/*
+ *  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.polygene.runtime.association;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+
+public class AssociationAssignmentTest extends AbstractPolygeneTest
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( MemoryEntityStoreService.class );
+        module.entities( TheAssociatedType.class );
+        module.entities( TheMainType.class );
+    }
+
+    @Test
+    public void givenAssignmentOfAssociationAtCreationWhenDereferencingAssocationExpectCorrectValue()
+        throws Exception
+    {
+        UnitOfWork work = unitOfWorkFactory.newUnitOfWork();
+        TheAssociatedType entity1 = work.newEntity( TheAssociatedType.class );
+        EntityBuilder<TheMainType> builder = work.newEntityBuilder( TheMainType.class );
+        builder.instance().assoc().set( entity1 );
+        TheMainType entity2 = builder.newInstance();
+        Identity id1 = entity1.identity().get();
+        Identity id2 = entity2.identity().get();
+        work.complete();
+        assertThat(id1, notNullValue());
+        assertThat(id2, notNullValue());
+
+        work = unitOfWorkFactory.newUnitOfWork();
+        TheMainType entity3 = work.get(TheMainType.class, id2 );
+        TheAssociatedType entity4 = entity3.assoc().get();
+        assertThat( entity4.identity().get(), equalTo(id1));
+        work.discard();
+    }
+
+    interface TheAssociatedType extends EntityComposite
+    {
+    }
+
+    interface TheMainType extends EntityComposite
+    {
+        Association<TheAssociatedType> assoc();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/association/AssociationEqualityTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/association/AssociationEqualityTest.java
new file mode 100644
index 0000000..9d968f0
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/association/AssociationEqualityTest.java
@@ -0,0 +1,458 @@
+/*
+ *  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.polygene.runtime.association;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Assert that Association, ManyAssociation and NamedAssociation equals/hashcode methods combine AssociationDescriptor and State.
+ */
+public class AssociationEqualityTest
+    extends AbstractPolygeneTest
+{
+
+    //
+    // --------------------------------------:: Types under test ::-----------------------------------------------------
+    //
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( AnEntity.class );
+        module.values( SomeWithAssociations.class, OtherWithAssociations.class );
+    }
+
+    public interface AnEntity
+    {
+    }
+
+    public interface SomeWithAssociations
+    {
+
+        @Optional
+        Association<AnEntity> anEntity();
+
+        ManyAssociation<AnEntity> manyEntities();
+
+        NamedAssociation<AnEntity> namedEntities();
+    }
+
+    public interface OtherWithAssociations
+    {
+
+        @Optional
+        Association<AnEntity> anEntity();
+
+        ManyAssociation<AnEntity> manyEntities();
+
+        NamedAssociation<AnEntity> namedEntities();
+    }
+
+    //
+    // ----------------------------:: AssociationDescriptor equality tests ::-------------------------------------------
+    //
+    @Test
+    public void givenValuesOfTheSameTypeAndSameStateWhenTestingAssociationDescriptorEqualityExpectEquals()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            AnEntity anEntity = uow.newEntity( AnEntity.class );
+
+            SomeWithAssociations some = buildSomeWithAssociation( anEntity );
+            AssociationDescriptor someAssocDesc = polygene.api().associationDescriptorFor( some.anEntity() );
+            AssociationDescriptor someManyAssocDesc = polygene.api().associationDescriptorFor( some.manyEntities() );
+            AssociationDescriptor someNamedAssocDesc = polygene.api().associationDescriptorFor( some.namedEntities() );
+
+            SomeWithAssociations some2 = buildSomeWithAssociation( anEntity );
+            AssociationDescriptor some2AssocDesc = polygene.api().associationDescriptorFor( some2.anEntity() );
+            AssociationDescriptor some2ManyAssocDesc = polygene.api().associationDescriptorFor( some2.manyEntities() );
+            AssociationDescriptor some2NamedAssocDesc = polygene.api().associationDescriptorFor( some2.namedEntities() );
+
+            assertThat( "AssociationDescriptor equal",
+                        someAssocDesc,
+                        equalTo( some2AssocDesc ) );
+            assertThat( "AssociationDescriptor hashcode equal",
+                        someAssocDesc.hashCode(),
+                        equalTo( some2AssocDesc.hashCode() ) );
+            assertThat( "ManyAssociationDescriptor equal",
+                        someManyAssocDesc,
+                        equalTo( some2ManyAssocDesc ) );
+            assertThat( "ManyAssociationDescriptor hashcode equal",
+                        someManyAssocDesc.hashCode(),
+                        equalTo( some2ManyAssocDesc.hashCode() ) );
+            assertThat( "NamedAssociationDescriptor equal",
+                        someNamedAssocDesc,
+                        equalTo( some2NamedAssocDesc ) );
+            assertThat( "NamedAssociationDescriptor hashcode equal",
+                        someNamedAssocDesc.hashCode(),
+                        equalTo( some2NamedAssocDesc.hashCode() ) );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void givenValuesOfTheSameTypeAndDifferentStateWhenTestingAssociationDescriptorEqualityExpectEquals()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            SomeWithAssociations some = buildSomeWithAssociation( uow.newEntity( AnEntity.class ) );
+            AssociationDescriptor someAssocDesc = polygene.api().associationDescriptorFor( some.anEntity() );
+            AssociationDescriptor someManyAssocDesc = polygene.api().associationDescriptorFor( some.manyEntities() );
+            AssociationDescriptor someNamedAssocDesc = polygene.api().associationDescriptorFor( some.namedEntities() );
+
+            SomeWithAssociations some2 = buildSomeWithAssociation( uow.newEntity( AnEntity.class ) );
+            AssociationDescriptor some2AssocDesc = polygene.api().associationDescriptorFor( some2.anEntity() );
+            AssociationDescriptor some2ManyAssocDesc = polygene.api().associationDescriptorFor( some2.manyEntities() );
+            AssociationDescriptor some2NamedAssocDesc = polygene.api().associationDescriptorFor( some2.namedEntities() );
+
+            assertThat( "AssociationDescriptor equal",
+                        someAssocDesc,
+                        equalTo( some2AssocDesc ) );
+            assertThat( "AssociationDescriptor hashcode equal",
+                        someAssocDesc.hashCode(),
+                        equalTo( some2AssocDesc.hashCode() ) );
+            assertThat( "ManyAssociationDescriptor equal",
+                        someManyAssocDesc,
+                        equalTo( some2ManyAssocDesc ) );
+            assertThat( "ManyAssociationDescriptor hashcode equal",
+                        someManyAssocDesc.hashCode(),
+                        equalTo( some2ManyAssocDesc.hashCode() ) );
+            assertThat( "NamedAssociationDescriptor equal",
+                        someNamedAssocDesc,
+                        equalTo( some2NamedAssocDesc ) );
+            assertThat( "NamedAssociationDescriptor hashcode equal",
+                        someNamedAssocDesc.hashCode(),
+                        equalTo( some2NamedAssocDesc.hashCode() ) );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void givenValuesOfDifferentTypeAndSameStateWhenTestingAssociationDescriptorEqualityExpectNotEquals()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            AnEntity anEntity = uow.newEntity( AnEntity.class );
+
+            SomeWithAssociations some = buildSomeWithAssociation( anEntity );
+            AssociationDescriptor someAssocDesc = polygene.api().associationDescriptorFor( some.anEntity() );
+            AssociationDescriptor someManyAssocDesc = polygene.api().associationDescriptorFor( some.manyEntities() );
+            AssociationDescriptor someNamedAssocDesc = polygene.api().associationDescriptorFor( some.namedEntities() );
+
+            OtherWithAssociations other = buildOtherWithAssociation( anEntity );
+            AssociationDescriptor otherAssocDesc = polygene.api().associationDescriptorFor( other.anEntity() );
+            AssociationDescriptor otherManyAssocDesc = polygene.api().associationDescriptorFor( other.manyEntities() );
+            AssociationDescriptor otherNamedAssocDesc = polygene.api().associationDescriptorFor( other.namedEntities() );
+
+            assertThat( "AssociationDescriptor not equal",
+                        someAssocDesc,
+                        not( equalTo( otherAssocDesc ) ) );
+            assertThat( "AssociationDescriptor hashcode not equal",
+                        someAssocDesc.hashCode(),
+                        not( equalTo( otherAssocDesc.hashCode() ) ) );
+            assertThat( "ManyAssociationDescriptor not equal",
+                        someManyAssocDesc,
+                        not( equalTo( otherManyAssocDesc ) ) );
+            assertThat( "ManyAssociationDescriptor hashcode not equal",
+                        someManyAssocDesc.hashCode(),
+                        not( equalTo( otherManyAssocDesc.hashCode() ) ) );
+            assertThat( "NamedAssociationDescriptor not equal",
+                        someNamedAssocDesc,
+                        not( equalTo( otherNamedAssocDesc ) ) );
+            assertThat( "NamedAssociationDescriptor hashcode not equal",
+                        someNamedAssocDesc.hashCode(),
+                        not( equalTo( otherNamedAssocDesc.hashCode() ) ) );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    //
+    // --------------------------------:: Association State equality tests ::----------------------------------------------
+    //
+    @Test
+    public void givenValuesOfSameTypeAndDifferentStateWhenTestingAssociationStateEqualityExpectNotEquals()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            SomeWithAssociations some = buildSomeWithAssociation( uow.newEntity( AnEntity.class ) );
+            SomeWithAssociations some2 = buildSomeWithAssociation( uow.newEntity( AnEntity.class ) );
+
+            assertThat( "Association State not equal",
+                        some.anEntity().get(),
+                        not( equalTo( some2.anEntity().get() ) ) );
+            assertThat( "Association State hashcode not equal",
+                        some.anEntity().get().hashCode(),
+                        not( equalTo( some2.anEntity().get().hashCode() ) ) );
+            assertThat( "ManyAssociation State not equal",
+                        some.manyEntities().toList(),
+                        not( equalTo( some2.manyEntities().toList() ) ) );
+            assertThat( "ManyAssociation State hashcode not equal",
+                        some.manyEntities().toList().hashCode(),
+                        not( equalTo( some2.manyEntities().toList().hashCode() ) ) );
+            assertThat( "NamedAssociation State not equal",
+                        some.namedEntities().toMap(),
+                        not( equalTo( some2.namedEntities().toMap() ) ) );
+            assertThat( "NamedAssociation State hashcode not equal",
+                        some.namedEntities().toMap().hashCode(),
+                        not( equalTo( some2.namedEntities().toMap().hashCode() ) ) );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void givenValuesOfDifferentTypesAndSameStateWhenTestingAssociationStateEqualityExpectEquals()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            AnEntity anEntity = uow.newEntity( AnEntity.class );
+
+            SomeWithAssociations some = buildSomeWithAssociation( anEntity );
+            OtherWithAssociations other = buildOtherWithAssociation( anEntity );
+
+            assertThat( "Association State equal",
+                        some.anEntity().get(),
+                        equalTo( other.anEntity().get() ) );
+            assertThat( "Association State hashcode equal",
+                        some.anEntity().get().hashCode(),
+                        equalTo( other.anEntity().get().hashCode() ) );
+            assertThat( "ManyAssociation State equal",
+                        some.manyEntities().toList(),
+                        equalTo( other.manyEntities().toList() ) );
+            assertThat( "ManyAssociation State hashcode equal",
+                        some.manyEntities().toList().hashCode(),
+                        equalTo( other.manyEntities().toList().hashCode() ) );
+            assertThat( "NamedAssociation State equal",
+                        some.namedEntities().toMap(),
+                        equalTo( other.namedEntities().toMap() ) );
+            assertThat( "NamedAssociation State hashcode equal",
+                        some.namedEntities().toMap().hashCode(),
+                        equalTo( other.namedEntities().toMap().hashCode() ) );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    //
+    // ----------------------------------:: Association equality tests ::-----------------------------------------------
+    //
+    @Test
+    public void givenValuesOfTheSameTypeAndSameStateWhenTestingAssociationEqualityExpectEquals()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            AnEntity anEntity = uow.newEntity( AnEntity.class );
+
+            SomeWithAssociations some = buildSomeWithAssociation( anEntity );
+            SomeWithAssociations some2 = buildSomeWithAssociation( anEntity );
+
+            assertThat( "Association equal",
+                        some.anEntity(),
+                        equalTo( some2.anEntity() ) );
+            assertThat( "Association hashcode equal",
+                        some.anEntity().hashCode(),
+                        equalTo( some2.anEntity().hashCode() ) );
+            assertThat( "ManyAssociation equal",
+                        some.manyEntities(),
+                        equalTo( some2.manyEntities() ) );
+            assertThat( "ManyAssociation hashcode equal",
+                        some.manyEntities().hashCode(),
+                        equalTo( some2.manyEntities().hashCode() ) );
+            assertThat( "NamedAssociation equal",
+                        some.namedEntities(),
+                        equalTo( some2.namedEntities() ) );
+            assertThat( "NamedAssociation hashcode equal",
+                        some.namedEntities().hashCode(),
+                        equalTo( some2.namedEntities().hashCode() ) );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void givenValuesOfTheSameTypeAndDifferentStateWhenTestingAssociationEqualityExpectNotEquals()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            SomeWithAssociations some = buildSomeWithAssociation( uow.newEntity( AnEntity.class ) );
+            SomeWithAssociations some2 = buildSomeWithAssociation( uow.newEntity( AnEntity.class ) );
+
+            assertThat( "Association not equal",
+                        some.anEntity(),
+                        not( equalTo( some2.anEntity() ) ) );
+            assertThat( "Association hashcode not equal",
+                        some.anEntity().hashCode(),
+                        not( equalTo( some2.anEntity().hashCode() ) ) );
+            assertThat( "ManyAssociation not equal",
+                        some.manyEntities(),
+                        not( equalTo( some2.manyEntities() ) ) );
+            assertThat( "ManyAssociation hashcode not equal",
+                        some.manyEntities().hashCode(),
+                        not( equalTo( some2.manyEntities().hashCode() ) ) );
+            assertThat( "NamedAssociation not equal",
+                        some.namedEntities(),
+                        not( equalTo( some2.namedEntities() ) ) );
+            assertThat( "NamedAssociation hashcode not equal",
+                        some.namedEntities().hashCode(),
+                        not( equalTo( some2.namedEntities().hashCode() ) ) );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void givenValuesOfDifferentTypesAndSameStateWhenTestingAssociationEqualityExpectNotEquals()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            AnEntity anEntity = uow.newEntity( AnEntity.class );
+
+            SomeWithAssociations some = buildSomeWithAssociation( anEntity );
+            OtherWithAssociations other = buildOtherWithAssociation( anEntity );
+
+            assertThat( "Association not equal",
+                        some.anEntity(),
+                        not( equalTo( other.anEntity() ) ) );
+            assertThat( "Association hashcode not equal",
+                        some.anEntity().hashCode(),
+                        not( equalTo( other.anEntity().hashCode() ) ) );
+            assertThat( "ManyAssociation not equal",
+                        some.manyEntities(),
+                        not( equalTo( other.manyEntities() ) ) );
+            assertThat( "ManyAssociation hashcode not equal",
+                        some.manyEntities().hashCode(),
+                        not( equalTo( other.manyEntities().hashCode() ) ) );
+            assertThat( "NamedAssociation not equal",
+                        some.namedEntities(),
+                        not( equalTo( other.namedEntities() ) ) );
+            assertThat( "NamedAssociation hashcode not equal",
+                        some.namedEntities().hashCode(),
+                        not( equalTo( other.namedEntities().hashCode() ) ) );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void givenValuesOfDifferentTypesAndDifferentStateWhenTestingAssociationEqualityExpectNotEquals()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            SomeWithAssociations some = buildSomeWithAssociation( uow.newEntity( AnEntity.class ) );
+            OtherWithAssociations other = buildOtherWithAssociation( uow.newEntity( AnEntity.class ) );
+
+            assertThat( "Association not equal",
+                        some.anEntity(),
+                        not( equalTo( other.anEntity() ) ) );
+            assertThat( "Association hashcode not equal",
+                        some.anEntity().hashCode(),
+                        not( equalTo( other.anEntity().hashCode() ) ) );
+            assertThat( "ManyAssociation not equal",
+                        some.manyEntities(),
+                        not( equalTo( other.manyEntities() ) ) );
+            assertThat( "ManyAssociation hashcode not equal",
+                        some.manyEntities().hashCode(),
+                        not( equalTo( other.manyEntities().hashCode() ) ) );
+            assertThat( "NamedAssociation not equal",
+                        some.namedEntities(),
+                        not( equalTo( other.namedEntities() ) ) );
+            assertThat( "NamedAssociation hashcode not equal",
+                        some.namedEntities().hashCode(),
+                        not( equalTo( other.namedEntities().hashCode() ) ) );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    //
+    // -----------------------------------:: Values factory methods ::--------------------------------------------------
+    //
+    private SomeWithAssociations buildSomeWithAssociation( AnEntity associated )
+    {
+        SomeWithAssociations some;
+        {
+            ValueBuilder<SomeWithAssociations> builder = valueBuilderFactory.newValueBuilder( SomeWithAssociations.class );
+            builder.prototype().anEntity().set( associated );
+            builder.prototype().manyEntities().add( associated );
+            builder.prototype().namedEntities().put( "someKey", associated );
+            some = builder.newInstance();
+        }
+        return some;
+    }
+
+    private OtherWithAssociations buildOtherWithAssociation( AnEntity associated )
+    {
+        OtherWithAssociations some;
+        {
+            ValueBuilder<OtherWithAssociations> builder = valueBuilderFactory.newValueBuilder( OtherWithAssociations.class );
+            builder.prototype().anEntity().set( associated );
+            builder.prototype().manyEntities().add( associated );
+            builder.prototype().namedEntities().put( "someKey", associated );
+            some = builder.newInstance();
+        }
+        return some;
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/bootstrap/DereferenceForBootstrappedConcernsTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/bootstrap/DereferenceForBootstrappedConcernsTest.java
new file mode 100644
index 0000000..f7afdee
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/bootstrap/DereferenceForBootstrappedConcernsTest.java
@@ -0,0 +1,137 @@
+/*
+ *  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.polygene.runtime.bootstrap;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.mixin.NoopMixin;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.junit.Assert.assertEquals;
+
+public class DereferenceForBootstrappedConcernsTest
+    extends AbstractPolygeneTest
+{
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+//        module.addImportedServiceModel( Some.class ).withMixins( NoopMixin.class ).withConcerns( OtherConcern.class );
+        module.services( Some.class );
+        module.services( Result.class );
+    }
+
+    @Test
+    public void whenDerefencingInsideConcernThisExpectItToWork()
+        throws Exception
+    {
+        Result result = serviceFinder.findService( Result.class ).get();
+        Some some = serviceFinder.findService( Some.class ).get();
+        assertEquals( "method()", some.method() );
+        assertEquals( some.identity(), result.some().identity() );
+        assertEquals( some.identity().get(), result.some().identity().get() );
+    }
+
+    @Mixins( ResultMixin.class )
+    public interface Result
+        extends ServiceComposite
+    {
+        void execute( Some value );
+
+        Some some();
+    }
+
+    public static abstract class ResultMixin
+        implements Result
+    {
+
+        private Some value;
+
+        public void execute( Some value )
+        {
+            this.value = value;
+        }
+
+        public Some some()
+        {
+            return value;
+        }
+    }
+
+    @Concerns( OtherConcern.class )
+    @Mixins( NoopMixin.class )
+    public interface Other
+    {
+        void other();
+    }
+
+    @Mixins( SomeMixin.class )
+    public interface Some
+//        extends ServiceComposite
+        extends ServiceComposite, Other
+    {
+        String method();
+    }
+
+    public abstract static class SomeMixin
+        implements Some
+    {
+        @This
+        private Other other;
+
+        public String method()
+        {
+            other.other();
+            return "method()";
+        }
+    }
+
+    public static class OtherConcern
+        extends ConcernOf<Other>
+        implements Other
+    {
+        @Structure
+        private PolygeneAPI api;
+
+        @This
+        private Composite me;
+
+        @Service
+        private Result result;
+
+        public void other()
+        {
+            Composite value = api.dereference( me );
+            result.execute( (Some) value );
+            next.other();
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/bootstrap/docs/DocumentationSupport.java b/core/runtime/src/test/java/org/apache/polygene/runtime/bootstrap/docs/DocumentationSupport.java
new file mode 100644
index 0000000..3c80414
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/bootstrap/docs/DocumentationSupport.java
@@ -0,0 +1,80 @@
+/*
+ *  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.polygene.runtime.bootstrap.docs;
+
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.runtime.bootstrap.AssemblyHelper;
+import org.apache.polygene.runtime.composite.FragmentClassLoader;
+
+public class DocumentationSupport
+{
+    // START SNIPPET: customAssemblyHelper
+    private static Energy4Java polygene;
+
+    private static Application application;
+
+    public static void main( String[] args )
+        throws Exception
+    {
+        // Create a Polygene Runtime
+        polygene = new Energy4Java();
+        application = polygene.newApplication( new ApplicationAssembler()
+        {
+
+            @Override
+            public ApplicationAssembly assemble( ApplicationAssemblyFactory appFactory )
+                throws AssemblyException
+            {
+                ApplicationAssembly assembly = appFactory.newApplicationAssembly();
+                assembly.setMetaInfo( new DalvikAssemblyHelper() );
+                // END SNIPPET: customAssemblyHelper
+                // START SNIPPET: customAssemblyHelper
+                return assembly;
+            }
+        } );
+        // activate the application
+        application.activate();
+    }
+
+    public static class DalvikAssemblyHelper extends AssemblyHelper
+    {
+        @Override
+        protected FragmentClassLoader instantiateFragmentClassLoader( ClassLoader parent )
+        {
+            return new DalvikFragmentClassLoader( parent );
+        }
+    }
+
+    public static class DalvikFragmentClassLoader extends FragmentClassLoader
+    {
+
+        public DalvikFragmentClassLoader( ClassLoader parent )
+        {
+            super( parent );
+        }
+    }
+    // END SNIPPET: customAssemblyHelper
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/composite/AbstractMixinTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/AbstractMixinTest.java
new file mode 100644
index 0000000..1575f50
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/AbstractMixinTest.java
@@ -0,0 +1,127 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.concern.GenericConcern;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+/**
+ * JAVADOC
+ */
+public class AbstractMixinTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        System.setProperty( "polygene.compacttrace", "off" );
+        module.transients( TestComposite.class );
+    }
+
+    @Test
+    public void testAbstractMixin()
+    {
+        TestComposite instance = transientBuilderFactory.newTransient( TestComposite.class );
+
+        Assert.assertEquals( "Hello WorldHello World", instance.test( "Hello World" ) );
+    }
+
+    public interface TestComposite
+        extends TestInterface, TransientComposite
+    {
+    }
+
+    @Mixins( TestComposite.TestMixin.class )
+    @Concerns( { TestInterface.TestConcern.class, TestInterface.TestAbstractConcern.class } )
+    public interface TestInterface
+    {
+        String test( String newValue );
+
+        interface TestState
+        {
+            @Optional
+            Property<String> bar();
+
+            void barChanged( String newValue );
+        }
+
+        abstract class TestMixin
+            implements TestInterface, TestState
+        {
+            public void init( @Structure Module module )
+            {
+                System.out.println( module );
+            }
+
+            public String test( String newValue )
+            {
+                newValue = duplicate( newValue );
+                barChanged( newValue );
+                return bar().get();
+            }
+
+            public void barChanged( String newValue )
+            {
+                bar().set( newValue );
+            }
+
+            public String duplicate( String newValue )
+            {
+                return newValue + newValue;
+            }
+        }
+
+        public class TestConcern
+            extends GenericConcern
+        {
+            public Object invoke( Object proxy, Method method, Object[] args )
+                throws Throwable
+            {
+                System.out.println( method.toGenericString() );
+                return next.invoke( proxy, method, args );
+            }
+        }
+
+        public abstract class TestAbstractConcern
+            extends ConcernOf<TestState>
+            implements TestState
+        {
+            public void barChanged( String newValue )
+            {
+                next.barChanged( newValue );
+                System.out.println( "Concern:" + bar().get() );
+            }
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/composite/CompositeFactoryImplTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/CompositeFactoryImplTest.java
new file mode 100644
index 0000000..f13c0b0
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/CompositeFactoryImplTest.java
@@ -0,0 +1,160 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.Properties;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.AppliesToFilter;
+import org.apache.polygene.api.composite.NoSuchTransientException;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.junit.Assert.fail;
+
+public class CompositeFactoryImplTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // This is required to instantiate [SecondComposite] composite in [testNewComposition9]
+        module.transients( SecondComposite.class );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Test( expected = NoSuchTransientException.class )
+    public void testNewInstanceNotExtendingComposite()
+        throws Exception
+    {
+        Class aClass = FirstComposite.class;
+        TransientBuilder builder = transientBuilderFactory.newTransientBuilder( aClass );
+        builder.newInstance();
+    }
+
+    @Test
+    public void testNewComposition9()
+        throws Exception
+    {
+        try
+        {
+            TransientBuilder<SecondComposite> builder = transientBuilderFactory.newTransientBuilder(
+                SecondComposite.class );
+            SecondComposite composition9 = builder.newInstance();
+            composition9.setValue( "satisfiedBy value" );
+        }
+        catch( Exception e )
+        {
+            e.printStackTrace();
+            fail( "Fail to instantiate composite: " + SecondComposite.class );
+        }
+    }
+
+    @Mixins( PropertiesMixin.class )
+    public interface FirstComposite
+        extends Mixin3
+    {
+    }
+
+    @Mixins( PropertiesMixin.class )
+    public interface SecondComposite
+        extends Mixin3, TransientComposite
+    {
+    }
+
+    public interface Mixin3
+    {
+        void setValue( String value );
+
+        String getValue();
+    }
+
+    /**
+     * Generic property mixin. Methods in interface
+     * can be of the following types:
+     * setFoo = set property named foo
+     * getFoo = get property named foo
+     * addFoo = add object to list named foo
+     * removeFoo = remove object from list named foo
+     * fooIterator - return an iterator over the list of Foos
+     */
+    @AppliesTo( { Getters.class, Setters.class } )
+    public static class PropertiesMixin
+        implements InvocationHandler
+    {
+        private Properties properties;
+
+        public PropertiesMixin()
+        {
+            properties = new Properties();
+        }
+
+        @SuppressWarnings( "unchecked" )
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            String methodName = method.getName();
+            String property = methodName.substring( 3 );
+            if( methodName.startsWith( "get" ) )
+            {
+                return properties.get( property );
+            }
+            else
+            {
+                properties.put( property, args[ 0 ] );
+                return null;
+            }
+        }
+    }
+
+    /**
+     * Filter for getter methods. Method name must match "get*" or "is*" or "has*".
+     */
+    public static class Getters
+        implements AppliesToFilter
+    {
+        public boolean appliesTo( Method method, Class mixin, Class compositeType, Class modelClass )
+        {
+            final String name = method.getName();
+            return !method.getReturnType().equals( Void.TYPE ) && name.startsWith( "get" ) && name.length() > 4 &&
+                   method.getParameterTypes().length == 0;
+        }
+    }
+
+    /**
+     * Filter for setter methods. Method name must match "set*","add*" or "remove*".
+     */
+    public static class Setters
+        implements AppliesToFilter
+    {
+        public boolean appliesTo( Method method, Class mixin, Class compositeType, Class modelClass )
+        {
+            final String name = method.getName();
+            return method.getReturnType().equals( Void.TYPE ) && name.startsWith( "set" ) && name.length() > 4 &&
+                   method.getParameterTypes().length == 1;
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/composite/CompositeModelResolverTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/CompositeModelResolverTest.java
new file mode 100644
index 0000000..b6b000d
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/CompositeModelResolverTest.java
@@ -0,0 +1,149 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+public class CompositeModelResolverTest
+{
+    @Test
+    public void testWhenDependentMixinsThenOrderMixins()
+        throws Exception
+    {
+        Module module = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( TestComposite1.class );
+            }
+        }.module();
+
+        Assert.assertEquals( "ok", module.newTransient( TestComposite1.class ).testB() );
+    }
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+    }
+
+    @Mixins( TestA.TestAMixin.class )
+    public static interface TestA
+    {
+        public String test();
+
+        class TestAMixin
+            implements TestA
+        {
+            public String test()
+            {
+                return "ok";
+            }
+        }
+    }
+
+    @Mixins( TestB.TestBMixin.class )
+    public static interface TestB
+    {
+        public String testB();
+
+        class TestBMixin
+            implements TestB
+        {
+            private TestA testA;
+
+            public TestBMixin( @This TestA testA )
+            {
+                this.testA = testA;
+                testA.test();
+            }
+
+            public String testB()
+            {
+                return testA.test();
+            }
+        }
+    }
+
+    @Mixins( TestC.TestCMixin.class )
+    public static interface TestC
+    {
+        public String testC();
+
+        class TestCMixin
+            implements TestC
+        {
+            private TestD testD;
+
+            public TestCMixin( @This TestD testD )
+            {
+                this.testD = testD;
+                testD.testD();
+            }
+
+            public String testC()
+            {
+                return testD.testD();
+            }
+        }
+    }
+
+    @Mixins( TestD.TestDMixin.class )
+    public static interface TestD
+    {
+        public String testD();
+
+        class TestDMixin
+            implements TestD
+        {
+            private TestC testC;
+
+            public TestDMixin( @This TestC testC )
+            {
+                this.testC = testC;
+                testC.testC();
+            }
+
+            public String testD()
+            {
+                return testC.testC();
+            }
+        }
+    }
+
+    public static interface TestComposite1
+        extends TransientComposite, TestA, TestB
+    {
+    }
+
+    public static interface TestComposite2
+        extends Composite, TestC, TestD
+    {
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/composite/FunctionalListTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/FunctionalListTest.java
new file mode 100644
index 0000000..d7abd0f
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/FunctionalListTest.java
@@ -0,0 +1,99 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+import org.junit.Test;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.hamcrest.CoreMatchers.hasItems;
+import static org.junit.Assert.assertThat;
+
+public class FunctionalListTest extends AbstractPolygeneTest
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( List.class ).withTypes( FList.class ).withMixins( ArrayList.class );
+    }
+
+    @Test
+    public void givenArrayListWithMapOpCapabilityWhenMappingIntegerToStringExpectCorrectResult()
+    {
+        List<Integer> integers = transientBuilderFactory.newTransient( List.class );
+        integers.add( 5 );
+        integers.add( 15 );
+        integers.add( 45 );
+        integers.add( 85 );
+        FList<Integer> list = (FList<Integer>) integers;
+
+        List<String> strings = list.translate( new Function<Integer, String>()
+        {
+            @Override
+            public String apply( Integer x )
+            {
+                return x.toString();
+            }
+        } );
+
+        String[] expected = new String[]
+        {
+            "5", "15", "45", "85"
+        };
+        assertThat( strings, hasItems( expected ) );
+    }
+
+    @Mixins( FListMixin.class )
+    public interface FList<FROM>
+    {
+        <TO> List<TO> translate( Function<FROM, TO> function );
+    }
+
+    public static class FListMixin<FROM>
+        implements FList<FROM>
+    {
+        @This
+        private List<FROM> list;
+
+        @Structure
+        private Module module;
+
+        @Override
+        public <TO> List<TO> translate( Function<FROM, TO> function )
+        {
+            List<TO> result = module.newTransient( List.class );
+            for( FROM data : list )
+            {
+                result.add( function.apply( data ) );
+            }
+            return result;
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/composite/InterfaceDefaultMethodsTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/InterfaceDefaultMethodsTest.java
new file mode 100644
index 0000000..f70ced7
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/InterfaceDefaultMethodsTest.java
@@ -0,0 +1,278 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.composite.DefaultMethodsFilter;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.sideeffect.SideEffectOf;
+import org.apache.polygene.api.sideeffect.SideEffects;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.constraints.annotation.NotEmpty;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.apache.polygene.test.util.Assume.assumeJavaVersion;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Assert that interface default methods are mixed in composites.
+ */
+public class InterfaceDefaultMethodsTest extends AbstractPolygeneTest
+{
+    @BeforeClass
+    public static void assumeJavaVersionIs8() { assumeJavaVersion( 8 ); }
+
+    public interface DefaultMethods
+    {
+        @UseDefaults( "Hello" )
+        Property<String> greeting();
+
+        default String sayHello( String name )
+        {
+            return greeting().get() + ", " + name + '!';
+        }
+    }
+
+    public interface OverrideDefaultMethods extends DefaultMethods
+    {
+        @Override
+        default String sayHello( String name )
+        {
+            return greeting().get() + ", overridden in " + name + '!';
+        }
+    }
+
+    public static abstract class MixinDefaultMethods implements DefaultMethods
+    {
+        @Override
+        public String sayHello( String name )
+        {
+            return greeting().get() + ", mixed in " + name + '!';
+        }
+    }
+
+    public interface DefaultMethodsConstraints extends DefaultMethods
+    {
+        @Override
+        default String sayHello( @NotEmpty String name )
+        {
+            return greeting().get() + ", " + name + '!';
+        }
+    }
+
+    @Concerns( DefaultMethodsConcern.class )
+    public interface DefaultMethodsConcerns extends DefaultMethods
+    {
+        @Override
+        default String sayHello( String name )
+        {
+            return greeting().get() + ", " + name + '!';
+        }
+
+        default String sayGoodBye( String name )
+        {
+            return "Good Bye, " + name + '!';
+        }
+    }
+
+    public static abstract class DefaultMethodsConcern extends ConcernOf<DefaultMethodsConcerns>
+        implements DefaultMethodsConcerns
+    {
+        @Override
+        public String sayHello( String name )
+        {
+            return next.sayHello( "concerned " + name );
+        }
+    }
+
+    @Concerns( DefaultMethodsGenericConcern.class )
+    public interface DefaultMethodsGenericConcerns extends DefaultMethods
+    {
+        @Override
+        default String sayHello( String name )
+        {
+            return greeting().get() + ", " + name + '!';
+        }
+
+        default String sayGoodBye( String name )
+        {
+            return "Good Bye, " + name + '!';
+        }
+    }
+
+    @AppliesTo( DefaultMethodsFilter.class )
+    public static class DefaultMethodsGenericConcern extends ConcernOf<InvocationHandler>
+        implements InvocationHandler
+    {
+        static int count = 0;
+
+        @Override
+        public Object invoke( Object o, Method method, Object[] objects )
+            throws Throwable
+        {
+            count++;
+            return next.invoke( o, method, objects );
+        }
+    }
+
+    @SideEffects( DefaultMethodsSideEffect.class )
+    public interface DefaultMethodsSideEffects extends DefaultMethods
+    {
+        @Override
+        default String sayHello( String name )
+        {
+            return greeting().get() + ", " + name + '!';
+        }
+    }
+
+    public static abstract class DefaultMethodsSideEffect extends SideEffectOf<DefaultMethodsSideEffects>
+        implements DefaultMethodsSideEffects
+    {
+        static int count;
+
+        @Override
+        public String sayHello( String name )
+        {
+            count++;
+            return null;
+        }
+    }
+
+    @SideEffects( DefaultMethodsGenericSideEffect.class )
+    public interface DefaultMethodsGenericSideEffects extends DefaultMethods
+    {
+        @Override
+        default String sayHello( String name )
+        {
+            return greeting().get() + ", " + name + '!';
+        }
+    }
+
+    @AppliesTo( DefaultMethodsFilter.class )
+    public static class DefaultMethodsGenericSideEffect extends SideEffectOf<InvocationHandler>
+        implements InvocationHandler
+    {
+        static int count = 0;
+
+        @Override
+        public Object invoke( Object o, Method method, Object[] objects )
+            throws Throwable
+        {
+            count++;
+            return null;
+        }
+    }
+
+    @Override
+    public void assemble( final ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( DefaultMethods.class,
+                           OverrideDefaultMethods.class,
+                           MixinDefaultMethods.class,
+                           DefaultMethodsConstraints.class,
+                           DefaultMethodsConcerns.class,
+                           DefaultMethodsSideEffects.class,
+                           DefaultMethodsGenericConcerns.class,
+                           DefaultMethodsGenericSideEffects.class
+                         );
+    }
+
+    @Test
+    public void defaultMethods()
+    {
+        DefaultMethods composite = transientBuilderFactory.newTransient( DefaultMethods.class );
+        assertThat( composite.sayHello( "John" ), equalTo( "Hello, John!" ) );
+    }
+
+    @Test
+    public void overrideDefaultMethods()
+    {
+        OverrideDefaultMethods composite = transientBuilderFactory.newTransient( OverrideDefaultMethods.class );
+        assertThat( composite.sayHello( "John" ), equalTo( "Hello, overridden in John!" ) );
+    }
+
+    @Test
+    public void mixinDefaultMethods()
+    {
+        MixinDefaultMethods composite = transientBuilderFactory.newTransient( MixinDefaultMethods.class );
+        assertThat( composite.sayHello( "John" ), equalTo( "Hello, mixed in John!" ) );
+    }
+
+    @Test
+    public void defaultMethodsConstraints()
+    {
+        DefaultMethodsConstraints composite = transientBuilderFactory.newTransient( DefaultMethodsConstraints.class );
+        try
+        {
+            composite.sayHello( "" );
+        }
+        catch( ConstraintViolationException ex )
+        {
+            assertThat( ex.getMessage(), containsString( "sayHello" ) );
+        }
+    }
+
+    @Test
+    public void defaultMethodsConcerns()
+    {
+        DefaultMethodsConcerns composite = transientBuilderFactory.newTransient( DefaultMethodsConcerns.class );
+        assertThat( composite.sayHello( "John" ), equalTo( "Hello, concerned John!" ) );
+        assertThat( composite.sayGoodBye( "John" ), equalTo( "Good Bye, John!" ) );
+    }
+
+    @Test
+    public void defaultMethodsGenericConcerns()
+    {
+        DefaultMethodsGenericConcerns composite = transientBuilderFactory.newTransient( DefaultMethodsGenericConcerns.class );
+        assertThat( composite.sayHello( "John" ), equalTo( "Hello, John!" ) );
+        assertThat( composite.sayGoodBye( "John" ), equalTo( "Good Bye, John!" ) );
+        assertThat( DefaultMethodsGenericConcern.count, equalTo( 2 ) );
+    }
+
+    @Test
+    public void defaultMethodsSideEffects()
+    {
+        DefaultMethodsSideEffects composite = transientBuilderFactory.newTransient( DefaultMethodsSideEffects.class );
+        assertThat( composite.sayHello( "John" ), equalTo( "Hello, John!" ) );
+        assertThat( composite.sayHello( "John" ), equalTo( "Hello, John!" ) );
+        assertThat( composite.sayHello( "John" ), equalTo( "Hello, John!" ) );
+        assertThat( DefaultMethodsSideEffect.count, equalTo( 3 ) );
+    }
+
+    @Test
+    public void defaultMethodsGenericSideEffects()
+    {
+        DefaultMethodsGenericSideEffects composite = transientBuilderFactory.newTransient( DefaultMethodsGenericSideEffects.class );
+        assertThat( composite.sayHello( "John" ), equalTo( "Hello, John!" ) );
+        assertThat( composite.sayHello( "John" ), equalTo( "Hello, John!" ) );
+        assertThat( composite.sayHello( "John" ), equalTo( "Hello, John!" ) );
+        assertThat( DefaultMethodsGenericSideEffect.count, equalTo( 3 ) );
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/composite/InterfaceStaticMethodsTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/InterfaceStaticMethodsTest.java
new file mode 100644
index 0000000..ee97d3f
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/InterfaceStaticMethodsTest.java
@@ -0,0 +1,77 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Assert that interface static methods are ignored when assembling composites.
+ */
+public class InterfaceStaticMethodsTest extends AbstractPolygeneTest
+{
+    public interface StaticMethods
+    {
+        @UseDefaults( "foo" )
+        Property<String> foo();
+
+        static String bar()
+        {
+            return "bar";
+        }
+    }
+
+    public interface OverrideStaticMethods extends StaticMethods
+    {
+        static String bar()
+        {
+            return "bar overridden";
+        }
+    }
+
+    @Override
+    public void assemble( final ModuleAssembly module ) throws AssemblyException
+    {
+        module.transients( StaticMethods.class, OverrideStaticMethods.class );
+    }
+
+    @Test
+    public void staticMethods() throws NoSuchMethodException
+    {
+        StaticMethods staticMethods = transientBuilderFactory.newTransient( StaticMethods.class );
+
+        assertThat( staticMethods.foo().get(), equalTo( "foo" ) );
+        assertThat( StaticMethods.bar(), equalTo( "bar" ) );
+    }
+
+    @Test
+    public void overrideStaticMethods()
+    {
+        OverrideStaticMethods staticMethods = transientBuilderFactory.newTransient( OverrideStaticMethods.class );
+
+        assertThat( staticMethods.foo().get(), equalTo( "foo" ) );
+        assertThat( OverrideStaticMethods.bar(), equalTo( "bar overridden" ) );
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/composite/MapOverrideTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/MapOverrideTest.java
new file mode 100644
index 0000000..bfd908a
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/MapOverrideTest.java
@@ -0,0 +1,205 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.injection.scope.Invocation;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * This test shows how to override any java.util.Map to become read-only. HashMap will be used as the Mixin!!
+ *
+ * Note that keySet(), values() and entrySet() would ALSO require overloading, but this has been left out for
+ * clarity reasons.
+ */
+@Ignore( "Awaiting QI-298 - Allow Transients to be declared by classes" )
+public class MapOverrideTest
+    extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // unable to add the concern, since it is applied on the prototype too!
+        // this seems to be a generic problem with prototypes.
+        module.transients( Map.class ).withMixins( HashMap.class ).withConcerns( ReadOnlyMapConcern.class );
+    }
+
+    @Test
+    public void givenReadOnlyAnnotatedHashMapWhenCallingSizeExpectSuccess()
+    {
+        ValueBuilder<Map> builder = valueBuilderFactory.newValueBuilder( Map.class );
+        Map<String, String> prototype = builder.prototype();
+        prototype.put( "Niclas", "Hedhman" );
+        Map<String, String> underTest = builder.newInstance();
+        assertThat( underTest.size(), equalTo( 1 ) );
+    }
+
+    @Test
+    public void givenReadOnlyAnnotatedHashMapWhenCallingIsEmptyExpectSuccess()
+    {
+        ValueBuilder<Map> builder = valueBuilderFactory.newValueBuilder( Map.class );
+        Map<String, String> prototype = builder.prototype();
+        prototype.put( "Niclas", "Hedhman" );
+        Map<String, String> underTest = builder.newInstance();
+        assertThat( underTest.isEmpty(), equalTo( false ) );
+    }
+
+    @Test
+    public void givenReadOnlyAnnotatedHashMapWhenCallingContainsKeyExpectSuccess()
+    {
+        ValueBuilder<Map> builder = valueBuilderFactory.newValueBuilder( Map.class );
+        Map<String, String> prototype = builder.prototype();
+        prototype.put( "Niclas", "Hedhman" );
+        Map<String, String> underTest = builder.newInstance();
+        assertThat( underTest.containsKey( "Niclas" ), equalTo( true ) );
+    }
+
+    @Test
+    public void givenReadOnlyAnnotatedHashMapWhenCallingContainsValueExpectSuccess()
+    {
+        ValueBuilder<Map> builder = valueBuilderFactory.newValueBuilder( Map.class );
+        Map<String, String> prototype = builder.prototype();
+        prototype.put( "Niclas", "Hedhman" );
+        Map<String, String> underTest = builder.newInstance();
+        assertThat( underTest.containsValue( "Hedhman" ), equalTo( true ) );
+    }
+
+    @Test
+    public void givenReadOnlyAnnotatedHashMapWhenCallingGetExpectSuccess()
+    {
+        ValueBuilder<Map> builder = valueBuilderFactory.newValueBuilder( Map.class );
+        Map<String, String> prototype = builder.prototype();
+        prototype.put( "Niclas", "Hedhman" );
+        Map<String, String> underTest = builder.newInstance();
+        assertThat( underTest.get( "Niclas" ), equalTo( "Hedhman" ) );
+    }
+
+    @Test
+    public void givenReadOnlyAnnotatedHashMapWhenCallingKeySetExpectSuccess()
+    {
+        ValueBuilder<Map> builder = valueBuilderFactory.newValueBuilder( Map.class );
+        Map<String, String> prototype = builder.prototype();
+        prototype.put( "Niclas", "Hedhman" );
+        Map<String, String> underTest = builder.newInstance();
+        assertThat( underTest.keySet(), equalTo( Collections.singleton( "Niclas" ) ) );
+    }
+
+    @Test
+    public void givenReadOnlyAnnotatedHashMapWhenCallingEntrySetExpectSuccess()
+    {
+        // TODO
+    }
+
+    @Test
+    public void givenReadOnlyAnnotatedHashMapWhenCallingValuesExpectSuccess()
+    {
+        ValueBuilder<Map> builder = valueBuilderFactory.newValueBuilder( Map.class );
+        Map<String, String> prototype = builder.prototype();
+        prototype.put( "Niclas", "Hedhman" );
+        Map<String, String> underTest = builder.newInstance();
+        Collection<String> values = Collections.singletonList( "Hedhman" );
+        assertThat( underTest.values().size(), equalTo( values.size() ) );
+        assertThat( underTest.values().contains( "Hedhman" ), equalTo( true ) );
+    }
+
+    @Test( expected = ReadOnlyException.class )
+    public void givenReadOnlyAnnotatedHashMapWhenCallingPutExpectReadOnlyException()
+    {
+        // TODO
+    }
+
+    @Test( expected = ReadOnlyException.class )
+    public void givenReadOnlyAnnotatedHashMapWhenCallingRemoveExpectReadOnlyException()
+    {
+        // TODO
+    }
+
+    @Test( expected = ReadOnlyException.class )
+    public void givenReadOnlyAnnotatedHashMapWhenCallingPutAllExpectReadOnlyException()
+    {
+        // TODO
+    }
+
+    @Test( expected = ReadOnlyException.class )
+    public void givenReadOnlyAnnotatedHashMapWhenCallingClearExpectReadOnlyException()
+    {
+        // TODO
+    }
+
+    public static abstract class ReadOnlyMapConcern extends ConcernOf<Map>
+        implements Map
+    {
+        @Invocation
+        private Method method;
+
+        @This
+        private Composite me;
+
+        @Override
+        public Object put( Object key, Object value )
+        {
+            throw new ReadOnlyException( me, method );
+        }
+
+        @Override
+        public Object remove( Object key )
+        {
+            throw new ReadOnlyException( me, method );
+        }
+
+        @Override
+        public void putAll( Map m )
+        {
+            throw new ReadOnlyException( me, method );
+        }
+
+        @Override
+        public void clear()
+        {
+            throw new ReadOnlyException( me, method );
+        }
+    }
+
+    private static class ReadOnlyException
+        extends RuntimeException
+    {
+        public ReadOnlyException( Composite me, Method method )
+        {
+            super( "Method " + method.getName() + " in [" + me.toString() + "] is READ ONLY." );
+        }
+    }
+
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/composite/QI247Test1.java b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/QI247Test1.java
new file mode 100644
index 0000000..ec34343
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/QI247Test1.java
@@ -0,0 +1,143 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class QI247Test1
+    extends AbstractPolygeneTest
+{
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( TransientWithMixin.class );
+    }
+
+    private void checkToString( ObjectMethods withMixin )
+    {
+        assertEquals( ObjectMethods.MESSAGE, withMixin.toString() );
+    }
+
+    private void checkHashCode( ObjectMethods withMixin )
+    {
+        assertEquals( ObjectMethods.CODE, withMixin.hashCode() );
+    }
+
+    private void checkSelfEquals( ObjectMethods withMixin )
+    {
+        assertEquals( withMixin, withMixin );
+    }
+
+    private void checkTwoNotEqual( ObjectMethods first, ObjectMethods second )
+    {
+        assertFalse( first.equals( second ) );
+    }
+
+    // MIXIN
+
+    @Test
+    public void testWithMixinToString()
+    {
+        ObjectMethods withMixin = transientBuilderFactory.newTransient( ObjectMethods.class );
+        checkToString( withMixin );
+    }
+
+    @Test
+    public void testWithMixinHashCode()
+    {
+        ObjectMethods withMixin = transientBuilderFactory.newTransient( ObjectMethods.class );
+        checkHashCode( withMixin );
+    }
+
+    @Test
+    public void testWithMixinSelfEquals()
+    {
+        ObjectMethods withMixin = transientBuilderFactory.newTransient( ObjectMethods.class );
+        checkSelfEquals( withMixin );
+    }
+
+    @Test
+    public void testWithMixinSelfEquals2()
+    {
+        ObjectMethods withMixin = transientBuilderFactory.newTransient( ObjectMethods.class );
+        assertTrue( withMixin.equals( withMixin ) );
+    }
+
+    @Test
+    public void testWithMixinSelfSame()
+    {
+        ObjectMethods withMixin = transientBuilderFactory.newTransient( ObjectMethods.class );
+        assertSame( withMixin, withMixin );
+    }
+
+    @Test
+    public void testWithMixinTwoNotEqual()
+    {
+        ObjectMethods first = transientBuilderFactory.newTransient( ObjectMethods.class );
+        ObjectMethods second = transientBuilderFactory.newTransient( ObjectMethods.class );
+        checkTwoNotEqual( first, second );
+    }
+
+    public interface ObjectMethods
+    {
+        String MESSAGE = "Does not work :(";
+        int CODE = 123;
+
+        void someMethod();
+    }
+
+    public static class ObjectMethodsMixin
+        implements ObjectMethods
+    {
+
+        @Override
+        public int hashCode()
+        {
+            return CODE;
+        }
+
+        @Override
+        public String toString()
+        {
+            return MESSAGE;
+        }
+
+        public void someMethod()
+        {
+        }
+    }
+
+    @Mixins( ObjectMethodsMixin.class )
+    public interface TransientWithMixin
+        extends TransientComposite, ObjectMethods
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/composite/QI247Test2.java b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/QI247Test2.java
new file mode 100644
index 0000000..d39ed6e
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/QI247Test2.java
@@ -0,0 +1,159 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class QI247Test2
+    extends AbstractPolygeneTest
+{
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( TransientWithHandler.class );
+    }
+
+    private void checkToString( ObjectMethods instance )
+    {
+        assertEquals( ObjectMethods.MESSAGE, instance.toString() );
+    }
+
+    private void checkHashCode( ObjectMethods instance )
+    {
+        assertEquals( ObjectMethods.CODE, instance.hashCode() );
+    }
+
+    private void checkSelfEquals( ObjectMethods instance )
+    {
+        assertEquals( instance, instance );
+    }
+
+    private void checkTwoNotEqual( ObjectMethods first, ObjectMethods second )
+    {
+        assertFalse( first.equals( second ) );
+    }
+
+    //HANDLER
+
+    @Test
+    public void testWithHandlerToString()
+    {
+        ObjectMethods withHandler = transientBuilderFactory.newTransient( ObjectMethods.class );
+        checkToString( withHandler );
+    }
+
+    @Test
+    public void testWithHandlerHashCode()
+    {
+        ObjectMethods withHandler = transientBuilderFactory.newTransient( ObjectMethods.class );
+        checkHashCode( withHandler );
+    }
+
+    @Test
+    public void testWithHandlerSelfEquals()
+    {
+        ObjectMethods withHandler = transientBuilderFactory.newTransient( ObjectMethods.class );
+        checkSelfEquals( withHandler );
+    }
+
+    @Test
+    public void testWithHandlerSelfEquals2()
+    {
+        ObjectMethods withHandler = transientBuilderFactory.newTransient( ObjectMethods.class );
+        assertTrue( withHandler.equals( withHandler ) );
+    }
+
+    @Test
+    public void testWithHandlerSelfSame()
+    {
+        ObjectMethods withHandler = transientBuilderFactory.newTransient( ObjectMethods.class );
+        assertSame( withHandler, withHandler );
+    }
+
+    @Test
+    public void testWithHandlerTwoNotEqual()
+    {
+        ObjectMethods first = transientBuilderFactory.newTransient( ObjectMethods.class );
+        ObjectMethods second = transientBuilderFactory.newTransient( ObjectMethods.class );
+        checkTwoNotEqual( first, second );
+    }
+
+    public interface ObjectMethods
+    {
+        String MESSAGE = "Does not work :(";
+
+        int CODE = 123;
+
+        void someMethod();
+    }
+
+    public static class ObjectMethodsHandler
+        implements InvocationHandler
+    {
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            System.out.println( "invoke(proxy, " + method.getName() + ", args" );
+            if( "someMethod".equals( method.getName() ) )
+            {
+                System.out.println( "Hello." );
+                return null;
+            }
+            else
+            {
+                throw new UnsupportedOperationException( method.toString() );
+            }
+        }
+
+        public String toString()
+        {
+            return ObjectMethods.MESSAGE;
+        }
+
+        public int hashCode()
+        {
+            return ObjectMethods.CODE;
+        }
+
+        public boolean equals( Object o )
+        {
+            return o == this;
+        }
+    }
+
+    @Mixins( ObjectMethodsHandler.class )
+    public interface TransientWithHandler
+        extends TransientComposite, ObjectMethods
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/composite/QI256Test.java b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/QI256Test.java
new file mode 100644
index 0000000..6219487
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/QI256Test.java
@@ -0,0 +1,344 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+/**
+ * JAVADOC
+ */
+public class QI256Test
+    extends AbstractPolygeneTest
+{
+
+    public static class TestException
+        extends RuntimeException
+    {
+        public TestException()
+        {
+            super( "Test" );
+        }
+    }
+
+    @Mixins( { TestTransient.TestTransientMixin.class } )
+    public interface TestTransient
+        extends TransientComposite
+    {
+        void declaredMethodThatThrowsCustomException();
+
+        void invokeDeclaredPublicMethodThatThrowsCustomException();
+
+        void invokePrivateMethodThatThrowsCustomException();
+
+        void invokeProtectedMethodThatThrowsCustomException();
+
+        void invokeUndeclaredPublicMethodThatThrowsCustomException();
+
+        void declaredMethodThatThrowsBuiltinInheritedException();
+
+        void invokeDeclaredPublicMethodThatThrowsBuiltinInheritedException();
+
+        void invokePrivateMethodThatThrowsBuiltinInheritedException();
+
+        void invokeProtectedMethodThatThrowsBuiltinInheritedException();
+
+        void invokeUndeclaredPublicMethodThatThrowsBuiltinInheritedException();
+
+        void declaredMethodThatThrowsBuiltinException();
+
+        void invokeDeclaredPublicMethodThatThrowsBuiltinException();
+
+        void invokePrivateMethodThatThrowsBuiltinException();
+
+        void invokeProtectedMethodThatThrowsBuiltinException();
+
+        void invokeUndeclaredPublicMethodThatThrowsBuiltinException();
+
+        abstract class TestTransientMixin
+            implements TestTransient
+        {
+            public void declaredMethodThatThrowsCustomException()
+            {
+                throw new TestException();
+            }
+
+            public void invokeDeclaredPublicMethodThatThrowsCustomException()
+            {
+                this.declaredMethodThatThrowsCustomException();
+            }
+
+            public void invokePrivateMethodThatThrowsCustomException()
+            {
+                this.privateThrowException( TestException.class );
+            }
+
+            public void invokeProtectedMethodThatThrowsCustomException()
+            {
+                this.protectedThrowException( TestException.class );
+            }
+
+            public void invokeUndeclaredPublicMethodThatThrowsCustomException()
+            {
+                this.publicThrowException( TestException.class );
+            }
+
+            public void declaredMethodThatThrowsBuiltinInheritedException()
+            {
+                throw new IllegalArgumentException();
+            }
+
+            public void invokeDeclaredPublicMethodThatThrowsBuiltinInheritedException()
+            {
+                this.declaredMethodThatThrowsBuiltinInheritedException();
+            }
+
+            public void invokePrivateMethodThatThrowsBuiltinInheritedException()
+            {
+                this.privateThrowException( IllegalArgumentException.class );
+            }
+
+            public void invokeProtectedMethodThatThrowsBuiltinInheritedException()
+            {
+                this.protectedThrowException( IllegalArgumentException.class );
+            }
+
+            public void invokeUndeclaredPublicMethodThatThrowsBuiltinInheritedException()
+            {
+                this.publicThrowException( IllegalArgumentException.class );
+            }
+
+            public void declaredMethodThatThrowsBuiltinException()
+            {
+                throw new RuntimeException();
+            }
+
+            public void invokeDeclaredPublicMethodThatThrowsBuiltinException()
+            {
+                this.declaredMethodThatThrowsBuiltinException();
+            }
+
+            public void invokePrivateMethodThatThrowsBuiltinException()
+            {
+                this.privateThrowException( RuntimeException.class );
+            }
+
+            public void invokeProtectedMethodThatThrowsBuiltinException()
+            {
+                this.protectedThrowException( RuntimeException.class );
+            }
+
+            public void invokeUndeclaredPublicMethodThatThrowsBuiltinException()
+            {
+                this.publicThrowException( RuntimeException.class );
+            }
+
+            private void privateThrowException( Class<? extends RuntimeException> clazz )
+            {
+                try
+                {
+                    throw clazz.newInstance();
+                }
+                catch( Throwable t )
+                {
+                    if( clazz.isInstance( t ) )
+                    {
+                        throw clazz.cast( t );
+                    }
+                    // Ignore
+                }
+            }
+
+            protected void protectedThrowException( Class<? extends RuntimeException> clazz )
+            {
+                try
+                {
+                    throw clazz.newInstance();
+                }
+                catch( Throwable t )
+                {
+                    if( clazz.isInstance( t ) )
+                    {
+                        throw clazz.cast( t );
+                    }
+                    // Ignore
+                }
+            }
+
+            public void publicThrowException( Class<? extends RuntimeException> clazz )
+            {
+                try
+                {
+                    throw clazz.newInstance();
+                }
+                catch( Throwable t )
+                {
+                    if( clazz.isInstance( t ) )
+                    {
+                        throw clazz.cast( t );
+                    }
+                    // Ignore
+                }
+            }
+        }
+    }
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( TestTransient.class );
+    }
+
+    @Test( expected = TestException.class )
+    public void invokeCustomExceptionThrowingMethod()
+        throws Throwable
+    {
+        this.transientBuilderFactory.newTransient( TestTransient.class ).declaredMethodThatThrowsCustomException();
+    }
+
+    @Test( expected = TestException.class )
+    public void invokeDeclaredPublicMethodWhichInvokesCustomExceptionThrowingMethod()
+        throws Throwable
+    {
+        this.transientBuilderFactory
+            .newTransient( TestTransient.class )
+            .invokeDeclaredPublicMethodThatThrowsCustomException();
+    }
+
+    @Test( expected = TestException.class )
+    public void invokeUndeclaredPublicMethodWhichInvokesCustomExceptionThrowingMethod()
+        throws Throwable
+    {
+        this.transientBuilderFactory
+            .newTransient( TestTransient.class )
+            .invokeUndeclaredPublicMethodThatThrowsCustomException();
+    }
+
+    @Test( expected = TestException.class )
+    public void invokePrivateMethodWhichInvokesCustomExceptionThrowingMethod()
+        throws Throwable
+    {
+        this.transientBuilderFactory.newTransient( TestTransient.class ).invokePrivateMethodThatThrowsCustomException();
+    }
+
+    @Test( expected = TestException.class )
+    public void invokeProtectedMethodWhichInvokesCustomExceptionThrowingMethod()
+        throws Throwable
+    {
+        this.transientBuilderFactory
+            .newTransient( TestTransient.class )
+            .invokeProtectedMethodThatThrowsCustomException();
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void invokeBuiltinInheritedExceptionThrowingMethod()
+        throws Throwable
+    {
+        this.transientBuilderFactory
+            .newTransient( TestTransient.class )
+            .declaredMethodThatThrowsBuiltinInheritedException();
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void invokeDeclaredPublicMethodWhichInvokesBuiltinInheritedExceptionThrowingMethod()
+        throws Throwable
+    {
+        this.transientBuilderFactory
+            .newTransient( TestTransient.class )
+            .invokeDeclaredPublicMethodThatThrowsBuiltinInheritedException();
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void invokeUndeclaredPublicMethodWhichInvokesBuiltinInheritedExceptionThrowingMethod()
+        throws Throwable
+    {
+        this.transientBuilderFactory
+            .newTransient( TestTransient.class )
+            .invokeUndeclaredPublicMethodThatThrowsBuiltinInheritedException();
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void invokePrivateMethodWhichInvokesBuiltinInheritedExceptionThrowingMethod()
+        throws Throwable
+    {
+        this.transientBuilderFactory
+            .newTransient( TestTransient.class )
+            .invokePrivateMethodThatThrowsBuiltinInheritedException();
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void invokeProtectedMethodWhichInvokesBuiltinInheritedExceptionThrowingMethod()
+        throws Throwable
+    {
+        this.transientBuilderFactory
+            .newTransient( TestTransient.class )
+            .invokeProtectedMethodThatThrowsBuiltinInheritedException();
+    }
+
+    @Test( expected = RuntimeException.class )
+    public void invokeBuiltinExceptionThrowingMethod()
+        throws Throwable
+    {
+        this.transientBuilderFactory
+            .newTransient( TestTransient.class )
+            .declaredMethodThatThrowsBuiltinInheritedException();
+    }
+
+    @Test( expected = RuntimeException.class )
+    public void invokeDeclaredPublicMethodWhichInvokesBuiltinExceptionThrowingMethod()
+        throws Throwable
+    {
+        this.transientBuilderFactory
+            .newTransient( TestTransient.class )
+            .invokeDeclaredPublicMethodThatThrowsBuiltinInheritedException();
+    }
+
+    @Test( expected = RuntimeException.class )
+    public void invokeUndeclaredPublicMethodWhichInvokesBuiltinExceptionThrowingMethod()
+        throws Throwable
+    {
+        this.transientBuilderFactory
+            .newTransient( TestTransient.class )
+            .invokeUndeclaredPublicMethodThatThrowsBuiltinInheritedException();
+    }
+
+    @Test( expected = RuntimeException.class )
+    public void invokePrivateMethodWhichInvokesBuiltinExceptionThrowingMethod()
+        throws Throwable
+    {
+        this.transientBuilderFactory
+            .newTransient( TestTransient.class )
+            .invokePrivateMethodThatThrowsBuiltinInheritedException();
+    }
+
+    @Test( expected = RuntimeException.class )
+    public void invokeProtectedMethodWhichInvokesBuiltinExceptionThrowingMethod()
+        throws Throwable
+    {
+        this.transientBuilderFactory
+            .newTransient( TestTransient.class )
+            .invokeProtectedMethodThatThrowsBuiltinInheritedException();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/composite/TransientAsClassTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/TransientAsClassTest.java
new file mode 100644
index 0000000..f189593
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/TransientAsClassTest.java
@@ -0,0 +1,74 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for QI-298.
+ */
+public class TransientAsClassTest
+    extends AbstractPolygeneTest
+{
+    public static class UnderTestConcern extends ConcernOf<InvocationHandler>
+        implements InvocationHandler
+    {
+
+        @Override
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            return next.invoke( proxy, method, args ) + " bar";
+        }
+    }
+
+    @Concerns(UnderTestConcern.class)
+    public static class UnderTest
+    {
+        public String foo()
+        {
+            return "foo";
+        }
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( UnderTest.class );
+    }
+
+    @Test
+    public void test()
+    {
+        UnderTest underTest = transientBuilderFactory.newTransient( UnderTest.class );
+        assertThat( underTest.foo(), equalTo( "foo bar" ) );
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/composite/TransientClassLoaderTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/TransientClassLoaderTest.java
new file mode 100644
index 0000000..0824f81
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/TransientClassLoaderTest.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.runtime.composite;
+
+public class TransientClassLoaderTest
+{
+
+    public void givenTransientWhenLoadingClassExpectSubclassGenerated()
+    {
+//        new TransientClassLoader( getClass().getClassLoader() ).loadFragmentClass( mainType );
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/composite/UsageGraphTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/UsageGraphTest.java
new file mode 100644
index 0000000..9eb1159
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/composite/UsageGraphTest.java
@@ -0,0 +1,372 @@
+/*
+ *  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.polygene.runtime.composite;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.bootstrap.BindingException;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class UsageGraphTest
+{
+
+    @Before
+    public void setUp()
+    {
+        Thing.counter = 1;
+    }
+
+    @Test
+    public void verifyRandomDoesNotAffect()
+        throws Exception
+    {
+        for( int i = 0; i < 100; i++ )
+        {
+            whenGraphIsOpenEndedGivenNotAllowCyclicDependenciesThenNoError();
+            whenGraphIsCyclicGivenAllowCyclicDependencyThenNoError();
+        }
+    }
+
+    @Test
+    public void whenGraphIsOpenEndedGivenNotAllowCyclicDependenciesThenNoError()
+        throws Exception
+    {
+        Thing thing1 = new Thing();
+        Thing thing2 = new Thing();
+        Thing thing3 = new Thing();
+        Thing thing4 = new Thing();
+        Thing thing5 = new Thing();
+        Thing thing6 = new Thing();
+        Thing thing7 = new Thing();
+        thing1.uses.add( thing3 );
+        thing2.uses.add( thing3 );
+        thing3.uses.add( thing4 );
+        thing4.uses.add( thing5 );
+        thing1.uses.add( thing6 );
+        thing7.uses.add( thing1 );
+        thing7.uses.add( thing2 );
+        thing7.uses.add( thing4 );
+        List<Thing> data = new ArrayList<Thing>();
+        data.add( thing7 );
+        data.add( thing4 );
+        data.add( thing3 );
+        data.add( thing1 );
+        data.add( thing6 );
+        data.add( thing5 );
+        data.add( thing2 );
+        randomize( data );
+        UsageGraph<Thing> deps = new UsageGraph<Thing>( data, new Userator(), false );
+        assertFalse( deps.transitiveUse( thing1, thing1 ) );
+        assertFalse( deps.transitiveUse( thing1, thing2 ) );
+        assertTrue( deps.transitiveUse( thing1, thing3 ) );
+        assertTrue( deps.transitiveUse( thing1, thing4 ) );
+        assertTrue( deps.transitiveUse( thing1, thing5 ) );
+        assertTrue( deps.transitiveUse( thing1, thing6 ) );
+        assertFalse( deps.transitiveUse( thing1, thing7 ) );
+        assertFalse( deps.transitiveUse( thing2, thing1 ) );
+        assertFalse( deps.transitiveUse( thing2, thing2 ) );
+        assertTrue( deps.transitiveUse( thing2, thing3 ) );
+        assertTrue( deps.transitiveUse( thing2, thing4 ) );
+        assertTrue( deps.transitiveUse( thing2, thing5 ) );
+        assertFalse( deps.transitiveUse( thing2, thing6 ) );
+        assertFalse( deps.transitiveUse( thing2, thing7 ) );
+        assertFalse( deps.transitiveUse( thing3, thing1 ) );
+        assertFalse( deps.transitiveUse( thing3, thing2 ) );
+        assertFalse( deps.transitiveUse( thing3, thing3 ) );
+        assertTrue( deps.transitiveUse( thing3, thing4 ) );
+        assertTrue( deps.transitiveUse( thing3, thing5 ) );
+        assertFalse( deps.transitiveUse( thing3, thing6 ) );
+        assertFalse( deps.transitiveUse( thing3, thing7 ) );
+        assertFalse( deps.transitiveUse( thing4, thing1 ) );
+        assertFalse( deps.transitiveUse( thing4, thing2 ) );
+        assertFalse( deps.transitiveUse( thing4, thing3 ) );
+        assertFalse( deps.transitiveUse( thing4, thing4 ) );
+        assertTrue( deps.transitiveUse( thing4, thing5 ) );
+        assertFalse( deps.transitiveUse( thing4, thing6 ) );
+        assertFalse( deps.transitiveUse( thing4, thing7 ) );
+        assertFalse( deps.transitiveUse( thing5, thing1 ) );
+        assertFalse( deps.transitiveUse( thing5, thing2 ) );
+        assertFalse( deps.transitiveUse( thing5, thing3 ) );
+        assertFalse( deps.transitiveUse( thing5, thing4 ) );
+        assertFalse( deps.transitiveUse( thing5, thing5 ) );
+        assertFalse( deps.transitiveUse( thing5, thing6 ) );
+        assertFalse( deps.transitiveUse( thing5, thing7 ) );
+        assertFalse( deps.transitiveUse( thing6, thing1 ) );
+        assertFalse( deps.transitiveUse( thing6, thing2 ) );
+        assertFalse( deps.transitiveUse( thing6, thing3 ) );
+        assertFalse( deps.transitiveUse( thing6, thing4 ) );
+        assertFalse( deps.transitiveUse( thing6, thing5 ) );
+        assertFalse( deps.transitiveUse( thing6, thing6 ) );
+        assertFalse( deps.transitiveUse( thing6, thing7 ) );
+        assertTrue( deps.transitiveUse( thing7, thing1 ) );
+        assertTrue( deps.transitiveUse( thing7, thing2 ) );
+        assertTrue( deps.transitiveUse( thing7, thing3 ) );
+        assertTrue( deps.transitiveUse( thing7, thing4 ) );
+        assertTrue( deps.transitiveUse( thing7, thing5 ) );
+        assertTrue( deps.transitiveUse( thing7, thing6 ) );
+        assertFalse( deps.transitiveUse( thing7, thing7 ) );
+        List<Thing> resolved = deps.resolveOrder();
+        System.out.println( resolved );
+        assertTrue( resolved.indexOf( thing1 ) > resolved.indexOf( thing6 ) );
+        assertTrue( resolved.indexOf( thing2 ) > resolved.indexOf( thing3 ) );
+        assertTrue( resolved.indexOf( thing2 ) > resolved.indexOf( thing4 ) );
+        assertTrue( resolved.indexOf( thing2 ) > resolved.indexOf( thing5 ) );
+        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing1 ) );
+        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing2 ) );
+        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing4 ) );
+        assertTrue( resolved.indexOf( thing1 ) > resolved.indexOf( thing3 ) );
+        assertTrue( resolved.indexOf( thing1 ) > resolved.indexOf( thing4 ) );
+        assertTrue( resolved.indexOf( thing1 ) > resolved.indexOf( thing5 ) );
+        assertTrue( resolved.indexOf( thing3 ) > resolved.indexOf( thing4 ) );
+        assertTrue( resolved.indexOf( thing3 ) > resolved.indexOf( thing5 ) );
+        assertTrue( resolved.indexOf( thing4 ) > resolved.indexOf( thing5 ) );
+        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing4 ) );
+        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing5 ) );
+        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing6 ) );
+    }
+
+    private void randomize( List<Thing> data )
+    {
+        int n = (int) ( Math.random() * 100 );
+        for( int i = 0; i < n; i++ )
+        {
+            int pos1 = 0;
+            int pos2 = 0;
+            while( pos1 == pos2 )
+            {
+                pos1 = (int) ( Math.floor( Math.random() * data.size() ) );
+                pos2 = (int) ( Math.floor( Math.random() * data.size() ) );
+            }
+            if( pos1 < pos2 )
+            {
+                int temp = pos2;
+                pos2 = pos1;
+                pos1 = temp;
+            }
+            Thing thing1 = data.remove( pos1 );
+            Thing thing2 = data.remove( pos2 );
+            data.add( pos2, thing1 );
+            data.add( pos1, thing2 );
+        }
+    }
+
+    @Test
+    public void whenAskingForDependencyGivenThatGraphContainsCyclicDepThenDetectTheError()
+        throws Exception
+    {
+        Thing thing1 = new Thing();
+        Thing thing2 = new Thing();
+        Thing thing3 = new Thing();
+        Thing thing4 = new Thing();
+        Thing thing5 = new Thing();
+        Thing thing6 = new Thing();
+        Thing thing7 = new Thing();
+        thing1.uses.add( thing3 );
+        thing2.uses.add( thing3 );
+        thing3.uses.add( thing4 );
+        thing4.uses.add( thing5 );
+        thing5.uses.add( thing1 );      // <-- Cyclic
+        thing1.uses.add( thing6 );
+        thing7.uses.add( thing1 );
+        thing7.uses.add( thing2 );
+        thing7.uses.add( thing4 );
+        List<Thing> data = new ArrayList<Thing>();
+        data.add( thing7 );
+        data.add( thing4 );
+        data.add( thing1 );
+        data.add( thing3 );
+        data.add( thing6 );
+        data.add( thing5 );
+        data.add( thing2 );
+        randomize( data );
+        UsageGraph<Thing> deps = new UsageGraph<Thing>( data, new Userator(), false );
+        try
+        {
+            List<Thing> resolved = deps.resolveOrder();
+            Assert.fail( "Cyclic Dependency Not Detected." );
+        }
+        catch( BindingException e )
+        {
+            // Expected!
+        }
+    }
+
+    @Test
+    public void whenAskingForResolveOrderGivenThatGraphContainsCyclicDepThenDetectTheError()
+        throws Exception
+    {
+        Thing thing1 = new Thing();
+        Thing thing2 = new Thing();
+        Thing thing3 = new Thing();
+        Thing thing4 = new Thing();
+        Thing thing5 = new Thing();
+        Thing thing6 = new Thing();
+        Thing thing7 = new Thing();
+        thing1.uses.add( thing3 );
+        thing2.uses.add( thing3 );
+        thing3.uses.add( thing4 );
+        thing4.uses.add( thing5 );
+        thing5.uses.add( thing1 );      // <-- Cyclic
+        thing1.uses.add( thing6 );
+        thing7.uses.add( thing1 );
+        thing7.uses.add( thing2 );
+        thing7.uses.add( thing4 );
+        List<Thing> data = new ArrayList<Thing>();
+        data.add( thing7 );
+        data.add( thing4 );
+        data.add( thing1 );
+        data.add( thing3 );
+        data.add( thing6 );
+        data.add( thing5 );
+        data.add( thing2 );
+        randomize( data );
+        UsageGraph<Thing> deps = new UsageGraph<Thing>( data, new Userator(), false );
+        try
+        {
+            assertTrue( deps.transitiveUse( thing1, thing3 ) );
+            Assert.fail( "Cyclic Dependency Not Detected." );
+        }
+        catch( BindingException e )
+        {
+            // Expected!
+        }
+    }
+
+    @Test
+    public void whenGraphIsCyclicGivenAllowCyclicDependencyThenNoError()
+        throws Exception
+    {
+        Thing thing1 = new Thing();
+        Thing thing2 = new Thing();
+        Thing thing3 = new Thing();
+        Thing thing4 = new Thing();
+        Thing thing5 = new Thing();
+        Thing thing6 = new Thing();
+        Thing thing7 = new Thing();
+        thing1.uses.add( thing3 );
+        thing2.uses.add( thing3 );
+        thing3.uses.add( thing4 );
+        thing4.uses.add( thing5 );
+        thing1.uses.add( thing6 );
+        thing5.uses.add( thing1 );      // <-- Cyclic
+        thing7.uses.add( thing1 );
+        thing7.uses.add( thing2 );
+        thing7.uses.add( thing4 );
+        List<Thing> data = new ArrayList<Thing>();
+        data.add( thing7 );
+        data.add( thing4 );
+        data.add( thing1 );
+        data.add( thing3 );
+        data.add( thing6 );
+        data.add( thing5 );
+        data.add( thing2 );
+        randomize( data );
+        UsageGraph<Thing> deps = new UsageGraph<Thing>( data, new Userator(), true );
+        assertTrue( deps.transitiveUse( thing1, thing1 ) );
+        assertFalse( deps.transitiveUse( thing1, thing2 ) );
+        assertTrue( deps.transitiveUse( thing1, thing3 ) );
+        assertTrue( deps.transitiveUse( thing1, thing4 ) );
+        assertTrue( deps.transitiveUse( thing1, thing5 ) );
+        assertTrue( deps.transitiveUse( thing1, thing6 ) );
+        assertFalse( deps.transitiveUse( thing1, thing7 ) );
+        assertTrue( deps.transitiveUse( thing2, thing1 ) );
+        assertFalse( deps.transitiveUse( thing2, thing2 ) );
+        assertTrue( deps.transitiveUse( thing2, thing3 ) );
+        assertTrue( deps.transitiveUse( thing2, thing4 ) );
+        assertTrue( deps.transitiveUse( thing2, thing5 ) );
+        assertTrue( deps.transitiveUse( thing2, thing6 ) );
+        assertFalse( deps.transitiveUse( thing2, thing7 ) );
+        assertTrue( deps.transitiveUse( thing3, thing1 ) );
+        assertFalse( deps.transitiveUse( thing3, thing2 ) );
+        assertTrue( deps.transitiveUse( thing3, thing3 ) );
+        assertTrue( deps.transitiveUse( thing3, thing4 ) );
+        assertTrue( deps.transitiveUse( thing3, thing5 ) );
+        assertTrue( deps.transitiveUse( thing3, thing6 ) );
+        assertFalse( deps.transitiveUse( thing3, thing7 ) );
+        assertTrue( deps.transitiveUse( thing4, thing1 ) );
+        assertFalse( deps.transitiveUse( thing4, thing2 ) );
+        assertTrue( deps.transitiveUse( thing4, thing3 ) );
+        assertTrue( deps.transitiveUse( thing4, thing4 ) );
+        assertTrue( deps.transitiveUse( thing4, thing5 ) );
+        assertTrue( deps.transitiveUse( thing4, thing6 ) );
+        assertFalse( deps.transitiveUse( thing4, thing7 ) );
+        assertTrue( deps.transitiveUse( thing5, thing1 ) );
+        assertFalse( deps.transitiveUse( thing5, thing2 ) );
+        assertTrue( deps.transitiveUse( thing5, thing3 ) );
+        assertTrue( deps.transitiveUse( thing5, thing4 ) );
+        assertTrue( deps.transitiveUse( thing5, thing5 ) );
+        assertTrue( deps.transitiveUse( thing5, thing6 ) );
+        assertFalse( deps.transitiveUse( thing5, thing7 ) );
+        assertFalse( deps.transitiveUse( thing6, thing1 ) );
+        assertFalse( deps.transitiveUse( thing6, thing2 ) );
+        assertFalse( deps.transitiveUse( thing6, thing3 ) );
+        assertFalse( deps.transitiveUse( thing6, thing4 ) );
+        assertFalse( deps.transitiveUse( thing6, thing5 ) );
+        assertFalse( deps.transitiveUse( thing6, thing6 ) );
+        assertFalse( deps.transitiveUse( thing6, thing7 ) );
+        assertTrue( deps.transitiveUse( thing7, thing1 ) );
+        assertTrue( deps.transitiveUse( thing7, thing2 ) );
+        assertTrue( deps.transitiveUse( thing7, thing3 ) );
+        assertTrue( deps.transitiveUse( thing7, thing4 ) );
+        assertTrue( deps.transitiveUse( thing7, thing5 ) );
+        assertTrue( deps.transitiveUse( thing7, thing6 ) );
+        assertFalse( deps.transitiveUse( thing7, thing7 ) );
+        List<Thing> resolved = deps.resolveOrder();
+        System.out.println( resolved );
+        assertTrue( resolved.indexOf( thing1 ) > resolved.indexOf( thing6 ) );
+        assertTrue( resolved.indexOf( thing2 ) > resolved.indexOf( thing3 ) );
+        assertTrue( resolved.indexOf( thing2 ) > resolved.indexOf( thing4 ) );
+        assertTrue( resolved.indexOf( thing2 ) > resolved.indexOf( thing5 ) );
+        assertTrue( resolved.indexOf( thing2 ) > resolved.indexOf( thing1 ) );
+        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing1 ) );
+        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing2 ) );
+        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing4 ) );
+
+        // The cyclic nodes can not be determine which one is before the other
+    }
+
+    public class Userator
+        implements UsageGraph.Use<Thing>
+    {
+
+        public List<Thing> uses( Thing source )
+        {
+            return source.uses;
+        }
+    }
+
+    public static class Thing
+    {
+        private static int counter = 1;
+
+        private List<Thing> uses = new ArrayList<Thing>();
+        private String name = "Thing" + counter++;
+
+        public String toString()
+        {
+            return name;
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/concerns/GenericConcernTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/concerns/GenericConcernTest.java
new file mode 100644
index 0000000..2de631a
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/concerns/GenericConcernTest.java
@@ -0,0 +1,83 @@
+/*
+ *  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.polygene.runtime.concerns;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+/**
+ * Tests for GenericConcern
+ */
+public class GenericConcernTest
+    extends AbstractPolygeneTest
+{
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( SomeComposite.class );
+    }
+
+    @Test
+    public void testNestedUnitOfWork()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        Some some = transientBuilderFactory.newTransient( Some.class );
+        some.doStuff();
+        uow.discard();
+    }
+
+    @Mixins( SomeMixin.class )
+    public interface SomeComposite
+        extends Some, TransientComposite
+    {
+    }
+
+    public interface Some
+    {
+        @NestedUnitOfWork
+        public String doStuff();
+    }
+
+    public static abstract class SomeMixin
+        implements Some
+    {
+        public String doStuff()
+        {
+            return "Blah blah";
+        }
+    }
+
+    @Retention( RetentionPolicy.RUNTIME )
+    @Target( { ElementType.METHOD } )
+    public @interface NestedUnitOfWork
+    {
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/concerns/MethodConcernsTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/concerns/MethodConcernsTest.java
new file mode 100644
index 0000000..245c12f
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/concerns/MethodConcernsTest.java
@@ -0,0 +1,94 @@
+/*
+ *  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.polygene.runtime.concerns;
+
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.sideeffect.SideEffectOf;
+import org.apache.polygene.api.sideeffect.SideEffects;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class MethodConcernsTest extends AbstractPolygeneTest
+{
+    private static int count = 0;
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.values( SomeType.class );
+    }
+
+    @Test
+    public void givenTypedConcernWhenCallingMethodExpectConcernToBeInvoked()
+        throws Exception
+    {
+        SomeType value = valueBuilderFactory.newValue( SomeType.class );
+        assertThat( value.doSomething( "abc" ), equalTo( "(...abc...)" ) );
+        assertThat( count, equalTo(1) );
+    }
+
+    @Mixins( Mixin.class )
+    public interface SomeType
+    {
+        @Concerns( ParenWrapConcern.class )
+        @SideEffects( CountInvocationsSideEffect.class )
+        String doSomething( String value );
+    }
+
+    public class Mixin implements SomeType
+    {
+
+        @Override
+        public String doSomething( String value )
+        {
+            return "..." + value + "...";
+        }
+    }
+
+    public static class ParenWrapConcern extends ConcernOf<SomeType>
+        implements SomeType
+    {
+
+        @Override
+        public String doSomething( String value )
+        {
+            return "(" + next.doSomething( value ) + ")";
+        }
+    }
+
+    public static class CountInvocationsSideEffect extends SideEffectOf<SomeType>
+        implements SomeType
+    {
+        @Override
+        public String doSomething( String value )
+        {
+            count++;
+            return null;  // side effect returns are ignored.
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/concerns/ModuleConcernTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/concerns/ModuleConcernTest.java
new file mode 100644
index 0000000..b2e9e47
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/concerns/ModuleConcernTest.java
@@ -0,0 +1,103 @@
+/*
+ *  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.polygene.runtime.concerns;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.concern.GenericConcern;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.AssemblyVisitorAdapter;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.TransientDeclaration;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test of declaring concern in assembly
+ */
+public class ModuleConcernTest
+    extends AbstractPolygeneTest
+{
+    public static boolean ok;
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( FooComposite.class );
+
+        module.layer().application().visit( new AssemblyVisitorAdapter<RuntimeException>()
+        {
+            @Override
+            public void visitComposite( TransientDeclaration declaration )
+            {
+                declaration.withConcerns( TraceConcern.class );
+            }
+        }
+
+        );
+    }
+
+    @Test
+    public void testModuleConcerns()
+    {
+        transientBuilderFactory.newTransient( Foo.class ).test( "Foo", 42 );
+        assertThat( "Concern has executed", ok, equalTo( true ) );
+    }
+
+    @Mixins( FooMixin.class )
+    public interface FooComposite
+        extends TransientComposite, Foo
+    {
+    }
+
+    public interface Foo
+    {
+        String test( String foo, int bar );
+    }
+
+    public static class FooMixin
+        implements Foo
+    {
+        public String test( String foo, int bar )
+        {
+            return foo + " " + bar;
+        }
+    }
+
+    public static class TraceConcern
+        extends GenericConcern
+    {
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            ok = true;
+            Object result = next.invoke( proxy, method, args );
+            String str = method.getName() + Arrays.asList( args );
+            System.out.println( str );
+            return result;
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/concerns/PropertyInheritanceTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/concerns/PropertyInheritanceTest.java
new file mode 100644
index 0000000..1982f2d
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/concerns/PropertyInheritanceTest.java
@@ -0,0 +1,109 @@
+/*
+ *  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.polygene.runtime.concerns;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.AssemblyReportException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+//TODO 2.0 removed this possibility when simplifying the Property handling. So, we are now checking that a decent
+// exception is thrown, but should be changed to supported instead.
+public class PropertyInheritanceTest extends AbstractPolygeneTest
+{
+
+    private boolean failed;
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( Audit.class );
+    }
+
+    @Override
+    protected void assemblyException( AssemblyException exception )
+        throws AssemblyException
+    {
+        if( exception instanceof AssemblyReportException )
+        {
+            failed = true;
+            return;
+        }
+        super.assemblyException( exception );
+    }
+
+    @Test
+    public void givenConcernOnInheritedPropertyWhenAccessingPropertyExpectConcernToBeCalled()
+    {
+        assertThat( failed, equalTo( true ) );
+
+// TODO: The following test code is testing the feature once it has been implemented. The @Test is needed to ensure check for the right Exception.
+//        List<String> data = new ArrayList<String>();
+//        data.add( "First" );
+//        data.add( "Second" );
+//        data.add( "Third" );
+//        Audit audit = module.newTransient( Audit.class );
+//        AuditTrail trail = audit.trail();
+//        trail.set( data );
+//        assertThat( audit.trail().get().get( 0 ), equalTo( "1: First" ) );
+//        assertThat( audit.trail().get().get( 1 ), equalTo( "2: Second" ) );
+//        assertThat( audit.trail().get().get( 2 ), equalTo("3: Third"));
+    }
+
+    public static abstract class AuditTrailMarkupConcern extends ConcernOf<AuditTrail>
+        implements AuditTrail
+    {
+
+        @Override
+        public void set( List<String> newValue )
+            throws IllegalArgumentException, IllegalStateException
+        {
+            List<String> markedUp = new ArrayList<String>();
+            int counter = 0;
+            for( String value : newValue )
+            {
+                markedUp.add( counter++ + ": " + value );
+            }
+            next.set( markedUp );
+        }
+    }
+
+    @Concerns( AuditTrailMarkupConcern.class )
+    public interface AuditTrail extends Property<List<String>>
+    {
+    }
+
+    public interface Audit
+    {
+        @UseDefaults
+        AuditTrail trail();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/constraints/ConstraintsTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/constraints/ConstraintsTest.java
new file mode 100644
index 0000000..f560439
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/constraints/ConstraintsTest.java
@@ -0,0 +1,209 @@
+/*
+ *  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.polygene.runtime.constraints;
+
+import java.lang.annotation.Retention;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.ConstraintViolation;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.api.constraint.Name;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class ConstraintsTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( MyOneComposite.class );
+        module.transients( MyOneComposite2.class );
+    }
+
+    @Test
+    public void givenCompositeWithConstraintsWhenInstantiatedThenUseDeclarationOnComposite()
+        throws Throwable
+    {
+        MyOne my = transientBuilderFactory.newTransient( MyOneComposite.class );
+        ArrayList<String> list = new ArrayList<String>();
+        list.add( "zout" );
+        my.doSomething( "habba", list );
+        try
+        {
+            my.doSomething( "niclas", new ArrayList<String>() );
+            fail( "Should have thrown a ConstraintViolationException." );
+        }
+        catch( ConstraintViolationException e )
+        {
+            Collection<ConstraintViolation> violations = e.constraintViolations();
+            assertEquals( 2, violations.size() );
+//            assertEquals( MyOne.class.getName(), e.mixinTypeName() );
+        }
+    }
+
+    @Test
+    public void givenCompositeWithoutConstraintsWhenInstantiatedThenUseDeclarationOnConstraint()
+        throws Throwable
+    {
+        MyOne my = transientBuilderFactory.newTransient( MyOneComposite2.class );
+        ArrayList<String> list = new ArrayList<String>();
+        list.add( "zout" );
+        my.doSomething( "habba", list );
+        try
+        {
+            my.doSomething( "niclas", new ArrayList<String>() );
+            fail( "Should have thrown a ConstraintViolationException." );
+        }
+        catch( ConstraintViolationException e )
+        {
+            Collection<ConstraintViolation> violations = e.constraintViolations();
+            assertEquals( 2, violations.size() );
+//            assertEquals( MyOne.class.getName(), e.mixinTypeName() );
+        }
+    }
+
+    @Test
+    public void givenConstrainedGenericWildcardParameterWhenInvokedThenUseConstraint()
+    {
+        MyOne myOne = transientBuilderFactory.newTransient( MyOneComposite.class );
+        ArrayList<String> list = new ArrayList<String>();
+        list.add( "Foo" );
+        myOne.doSomething2( list );
+    }
+
+    @Test
+    public void givenCompositeConstraintWhenInvokedThenUseAllConstraints()
+    {
+        MyOne myOne = transientBuilderFactory.newTransient( MyOneComposite.class );
+        ArrayList<String> list = new ArrayList<String>();
+        list.add( "Foo" );
+        myOne.doSomething3( list );
+    }
+
+    @Constraints( TestConstraintImpl.class )
+    @Mixins( MyOneMixin.class )
+    public interface MyOneComposite
+        extends MyOne, TransientComposite
+    {
+    }
+
+    @Mixins( MyOneMixin.class )
+    public interface MyOneComposite2
+        extends MyOne, TransientComposite
+    {
+    }
+
+    public interface MyOne
+    {
+        void doSomething( @Optional @TestConstraint String abc, @TestConstraint List<String> collection );
+
+        void doSomething2( @TestConstraint @NonEmptyCollection List<?> collection );
+
+        void doSomething3( @CompositeConstraint @Name( "somecollection" ) List<?> collection );
+    }
+
+    public abstract static class MyOneMixin
+        implements MyOne
+    {
+        public void doSomething( String abc, List<String> collection )
+        {
+            if( abc == null || collection == null )
+            {
+                throw new NullPointerException();
+            }
+        }
+
+        public void doSomething2( List<?> collection )
+        {
+            if( collection == null )
+            {
+                throw new NullPointerException();
+            }
+        }
+
+        public void doSomething3( List<?> collection )
+        {
+            if( collection == null )
+            {
+                throw new NullPointerException();
+            }
+        }
+    }
+
+    @ConstraintDeclaration
+    @Retention( RUNTIME )
+    @Constraints( TestConstraintImpl.class )
+    public @interface TestConstraint
+    {
+    }
+
+    public static class TestConstraintImpl
+        implements Constraint<TestConstraint, Object>
+    {
+        public boolean isValid( TestConstraint annotation, Object value )
+            throws NullPointerException
+        {
+            if( value instanceof String )
+            {
+                return ( (String) value ).startsWith( "habba" );
+            }
+            return value instanceof Collection && ( (Collection) value ).size() > 0;
+        }
+    }
+
+    @ConstraintDeclaration
+    @Retention( RUNTIME )
+    @Constraints( { NonEmptyCollectionConstraint.class } )
+    public @interface NonEmptyCollection
+    {
+    }
+
+    public static class NonEmptyCollectionConstraint
+        implements Constraint<NonEmptyCollection, Collection<?>>
+    {
+        public boolean isValid( NonEmptyCollection annotation, Collection<?> value )
+            throws NullPointerException
+        {
+            return value.size() > 0;
+        }
+    }
+
+    @ConstraintDeclaration
+    @Retention( RUNTIME )
+    @TestConstraint
+    @NonEmptyCollection
+    public @interface CompositeConstraint
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/constraints/ConstraintsTest.properties b/core/runtime/src/test/java/org/apache/polygene/runtime/constraints/ConstraintsTest.properties
new file mode 100644
index 0000000..5f3fd7a
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/constraints/ConstraintsTest.properties
@@ -0,0 +1,26 @@
+#
+#  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.
+#
+#
+#
+
+polygene.constraint.ConstraintsTest$MyOneComposite=Message1
+
+polygene.constraint.NotNull=Message2
+
+polygene.constraint.ConstraintsTest$MyOneComposite.doSomething=Message3
+
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/defaults/UseDefaultsTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/defaults/UseDefaultsTest.java
new file mode 100644
index 0000000..2bc7b34
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/defaults/UseDefaultsTest.java
@@ -0,0 +1,143 @@
+/*
+ *  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.polygene.runtime.defaults;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * JAVADOC
+ */
+public class UseDefaultsTest extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        module.transients( TestComposite.class );
+        module.forMixin( TestComposite.class ).declareDefaults().assemblyString().set( "habba" );
+    }
+
+    @Test
+    public void givenPropertyWithUseDefaultsWhenInstantiatedThenPropertiesAreDefaulted()
+    {
+        TransientBuilder<TestComposite> builder = transientBuilderFactory.newTransientBuilder( TestComposite.class );
+        TestComposite testComposite = builder.newInstance();
+
+        assertThat( "nullInt is null", testComposite.nullInt().get(), nullValue() );
+        assertThat( "zeroInt is zero", testComposite.defaultInt().get(), equalTo( 0 ) );
+        assertThat( "nullString is null", testComposite.nullString().get(), nullValue() );
+        assertThat( "defaultString is empty string", testComposite.defaultString().get(), equalTo( "" ) );
+        assertThat( "assemblyString is set string", testComposite.assemblyString().get(), equalTo( "habba" ) );
+
+        assertThat( "nullPrimitiveArray is null", testComposite.nullPrimitiveArray().get(), nullValue() );
+        assertTrue( "emptyPrimitiveArray is empty",
+                    Arrays.equals( testComposite.emptyPrimitiveArray().get(), new int[ 0 ] ) );
+        assertThat( "nullArray is null", testComposite.nullArray().get(), nullValue() );
+        assertTrue( "emptyArray is empty array",
+                    Arrays.equals( testComposite.emptyArray().get(), new Integer[ 0 ] ) );
+    }
+
+    @Test
+    public void givenPropertyWithValuedUseDefaultsWhenInstantiatedExpectCorrectDefaultValues()
+    {
+        TransientBuilder<TestComposite> builder = transientBuilderFactory.newTransientBuilder( TestComposite.class );
+        TestComposite testComposite = builder.newInstance();
+
+        assertThat( testComposite.initializedStringDefault().get(), equalTo( "abc" ) );
+        assertThat( testComposite.initializedIntegerDefaultValue().get(), equalTo( 123 ) );
+        assertThat( testComposite.initializedFloatDefaultValue().get(), equalTo( 123.45f ) );
+        List<String> expectedList = Collections.singletonList( "abcde" );
+        assertThat( testComposite.initializedStringListDefultString().get(), equalTo( expectedList ) );
+        Map<String, Integer> expectedMap = Collections.singletonMap( "abcd", 345 );
+        assertThat( testComposite.initializedMapDefaultValue().get(), equalTo( expectedMap ) );
+
+        assertTrue( "initializedPrimitiveArray is set",
+                    Arrays.equals( testComposite.initializedPrimitiveArray().get(), new int[] { 23, 42 } ) );
+        assertTrue( "initializedArray is set",
+                    Arrays.equals( testComposite.initializedArray().get(), new Integer[] { 23, 42 } ) );
+    }
+
+    interface TestComposite
+    {
+        @Optional
+        Property<Integer> nullInt();
+
+        @Optional
+        @UseDefaults
+        Property<Integer> defaultInt();
+
+        @Optional
+        Property<String> nullString();
+
+        @Optional
+        @UseDefaults
+        Property<String> defaultString();
+
+        Property<String> assemblyString();
+
+        @UseDefaults( "abc" )
+        Property<String> initializedStringDefault();
+
+        @UseDefaults( "123" )
+        Property<Integer> initializedIntegerDefaultValue();
+
+        @UseDefaults( "123.45" )
+        Property<Float> initializedFloatDefaultValue();
+
+        @UseDefaults( "[\"abcde\"]" )
+        Property<List<String>> initializedStringListDefultString();
+
+        @UseDefaults( "{\"abcd\": 345}" )
+        Property<Map<String, Integer>> initializedMapDefaultValue();
+
+        @Optional
+        Property<int[]> nullPrimitiveArray();
+
+        @UseDefaults
+        Property<int[]> emptyPrimitiveArray();
+
+        @UseDefaults( "[23, 42]" )
+        Property<int[]> initializedPrimitiveArray();
+
+        @Optional
+        Property<Integer[]> nullArray();
+
+        @UseDefaults
+        Property<Integer[]> emptyArray();
+
+        @UseDefaults( "[23, 42]" )
+        Property<Integer[]> initializedArray();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/entity/AggregatedTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/AggregatedTest.java
new file mode 100644
index 0000000..f648549
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/AggregatedTest.java
@@ -0,0 +1,169 @@
+/*
+ *  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.polygene.runtime.entity;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.entity.Aggregated;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.fail;
+
+/**
+ * JAVADOC
+ */
+public class AggregatedTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( CompanyEntity.class, EmployeeEntity.class, PersonEntity.class );
+
+        new EntityTestAssembler().assemble( module );
+
+        module.objects( getClass() );
+    }
+
+    @Test
+    public void givenAggregatedEntitiesWhenAggregateRootIsDeletedThenDeleteAggregatedEntities()
+        throws Exception
+    {
+        CompanyEntity companyEntity;
+        PersonEntity personEntity, personEntity2;
+        EmployeeEntity employeeEntity, employeeEntity2;
+        try( UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "Creation" ) ) )
+        {
+            {
+                EntityBuilder<PersonEntity> builder = unitOfWork.newEntityBuilder( PersonEntity.class );
+                personEntity = builder.instance();
+                personEntity.name().set( "Rickard" );
+                personEntity = builder.newInstance();
+            }
+
+            {
+                EntityBuilder<PersonEntity> builder = unitOfWork.newEntityBuilder( PersonEntity.class );
+                personEntity2 = builder.instance();
+                personEntity2.name().set( "Niclas" );
+                builder.newInstance();
+            }
+
+            {
+                EntityBuilder<EmployeeEntity> builder = unitOfWork.newEntityBuilder( EmployeeEntity.class );
+                employeeEntity = builder.instance();
+                employeeEntity.person().set( personEntity );
+                employeeEntity.salary().set( 50000 );
+                employeeEntity.title().set( "Director" );
+                employeeEntity = builder.newInstance();
+            }
+
+            {
+                EntityBuilder<EmployeeEntity> builder = unitOfWork.newEntityBuilder( EmployeeEntity.class );
+                employeeEntity2 = builder.instance();
+                employeeEntity2.person().set( personEntity );
+                employeeEntity2.salary().set( 40000 );
+                employeeEntity2.title().set( "Developer" );
+                employeeEntity2 = builder.newInstance();
+            }
+
+            {
+                EntityBuilder<CompanyEntity> builder = unitOfWork.newEntityBuilder( CompanyEntity.class );
+                companyEntity = builder.instance();
+                companyEntity.director().set( employeeEntity );
+                companyEntity.employees().add( 0, employeeEntity );
+                companyEntity.employees().add( 0, employeeEntity2 );
+                companyEntity = builder.newInstance();
+            }
+
+            unitOfWork.complete();
+        }
+
+        try( UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "Removal" ) ) )
+        {
+            companyEntity = unitOfWork.get( companyEntity );
+            unitOfWork.remove( companyEntity );
+
+            unitOfWork.complete();
+        }
+
+        try( UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "No 1st employee" ) ) )
+        {
+            unitOfWork.get( employeeEntity );
+            fail( "Should not work" );
+        }
+        catch( NoSuchEntityException e )
+        {
+            // Expected
+        }
+
+        try( UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "No 2nd employee" ) ) )
+        {
+            unitOfWork.get( employeeEntity2 );
+            fail( "Should not work" );
+        }
+        catch( NoSuchEntityException e )
+        {
+            // Expected
+        }
+
+        try( UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "Persons not removed" ) ) )
+        {
+            unitOfWork.get( personEntity );
+            unitOfWork.get( personEntity2 );
+        }
+    }
+
+    public interface CompanyEntity
+        extends EntityComposite
+    {
+        @Aggregated
+        Association<EmployeeEntity> director();
+
+        @Aggregated
+        ManyAssociation<EmployeeEntity> employees();
+    }
+
+    public interface EmployeeEntity
+        extends EntityComposite
+    {
+        Property<String> title();
+
+        Property<Integer> salary();
+
+        Association<PersonEntity> person();
+    }
+
+    public interface PersonEntity
+        extends EntityComposite
+    {
+        Property<String> name();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityBuilderWithStateTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityBuilderWithStateTest.java
new file mode 100644
index 0000000..35539a2
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityBuilderWithStateTest.java
@@ -0,0 +1,131 @@
+/*
+ *  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.polygene.runtime.entity;
+
+import java.util.Collections;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * EntityBuilder With State Test.
+ */
+public class EntityBuilderWithStateTest
+    extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( SomeEntity.class );
+        new DefaultUnitOfWorkAssembler().assemble( module );
+    }
+
+    @Test
+    public void test()
+        throws UnitOfWorkCompletionException
+    {
+        final Identity associatedIdentity;
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            EntityBuilder<SomeEntity> builder = uow.newEntityBuilder( SomeEntity.class );
+            builder.instance().prop().set( "Associated" );
+            SomeEntity entity = builder.newInstance();
+            associatedIdentity = entity.identity().get();
+            uow.complete();
+        }
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            SomeEntity entity = uow.newEntityBuilderWithState(
+                SomeEntity.class,
+                descriptor -> {
+                    if( "prop".equals( descriptor.qualifiedName().name() ) )
+                    {
+                        return "Foo";
+                    }
+                    return null;
+                },
+                descriptor -> {
+                    if( "ass".equals( descriptor.qualifiedName().name() ) )
+                    {
+                        return EntityReference.create( associatedIdentity );
+                    }
+                    return null;
+                },
+                descriptor -> {
+                    if( "manyAss".equals( descriptor.qualifiedName().name() ) )
+                    {
+                        return Stream.of( EntityReference.create( associatedIdentity ) );
+                    }
+                    return null;
+                },
+                descriptor -> {
+                    if( "namedAss".equals( descriptor.qualifiedName().name() ) )
+                    {
+                        return Collections.singletonMap(
+                            "foo",
+                            EntityReference.create( associatedIdentity )
+                        ).entrySet().stream();
+                    }
+                    return null;
+                }
+            ).newInstance();
+            assertThat( entity.prop().get(), equalTo( "Foo" ) );
+            assertThat( entity.ass().get().identity().get(), equalTo( associatedIdentity ) );
+            assertThat( entity.manyAss().get( 0 ).identity().get(), equalTo( associatedIdentity ) );
+            assertThat( entity.namedAss().get( "foo" ).identity().get(), equalTo( associatedIdentity ) );
+            uow.complete();
+        }
+    }
+
+    public interface SomeEntity
+        extends HasIdentity
+    {
+        Property<String> prop();
+
+        @Optional
+        Association<SomeEntity> ass();
+
+        @Optional
+        ManyAssociation<SomeEntity> manyAss();
+
+        @Optional
+        NamedAssociation<SomeEntity> namedAss();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityCompositeEqualityTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityCompositeEqualityTest.java
new file mode 100644
index 0000000..c2ca024
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityCompositeEqualityTest.java
@@ -0,0 +1,92 @@
+/*
+ *  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.polygene.runtime.entity;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Testing of equality of entity composites.
+ */
+public class EntityCompositeEqualityTest
+    extends AbstractPolygeneTest
+{
+    private UnitOfWork unitOfWork;
+    private EntityBuilder<MyComposite> myCompositeBuilder;
+
+    @Before
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        unitOfWork = this.unitOfWorkFactory.newUnitOfWork();
+        myCompositeBuilder = unitOfWork.newEntityBuilder( MyComposite.class );
+    }
+
+    @After
+    public void completeUnitOfWork()
+        throws Exception
+    {
+        unitOfWork.complete();
+        super.tearDown();
+    }
+
+    @Test
+    public void shouldNotBeEqualToNull()
+        throws UnitOfWorkCompletionException
+    {
+        MyComposite simpleComposite = myCompositeBuilder.newInstance();
+        assertThat( "simpleComposite is not equal to null", simpleComposite.equals( null ), equalTo( false ) );
+    }
+
+    @Test
+    public void shouldBeEqualToItself()
+    {
+        MyComposite simpleComposite = myCompositeBuilder.newInstance();
+        assertThat( "simple composite is equal to itself", simpleComposite.equals( simpleComposite ), equalTo( true ) );
+    }
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().visibleIn( Visibility.layer ).assemble( module );
+        module.objects( EntityCompositeEqualityTest.class );
+        module.entities( MyComposite.class );
+    }
+
+    private static interface MyComposite
+        extends EntityComposite
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityCompositeToStringTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityCompositeToStringTest.java
new file mode 100644
index 0000000..05a8757
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityCompositeToStringTest.java
@@ -0,0 +1,90 @@
+/*
+ *  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.polygene.runtime.entity;
+
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class EntityCompositeToStringTest extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        module.entities( Some.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Test
+    public void givenEntityWhenToStringExpectStringIdentity()
+    {
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            Some some = createSome( uow );
+            assertThat( some.toString(), equalTo( some.identity().get().toString() ) );
+        }
+    }
+
+    @Test
+    public void givenEntityWhenPrintStateSystemPropertyAndToStringExpectState()
+    {
+        String propertyName = "polygene.entity.print.state";
+        String previous = System.getProperty( propertyName, null );
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            System.setProperty( propertyName, "true" );
+            Some some = createSome( uow );
+            assertThat( some.toString(), allOf( containsString( "someString" ), containsString( "foo" ) ) );
+        }
+        finally
+        {
+            if( previous != null )
+            {
+                System.setProperty( propertyName, previous );
+            }
+            else
+            {
+                System.clearProperty( propertyName );
+            }
+        }
+    }
+
+    private Some createSome( UnitOfWork uow )
+    {
+        EntityBuilder<Some> builder = uow.newEntityBuilder( Some.class );
+        builder.instance().someString().set( "foo" );
+        return builder.newInstance();
+    }
+
+    interface Some extends HasIdentity
+    {
+        Property<String> someString();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityCreationTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityCreationTest.java
new file mode 100644
index 0000000..4766868
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityCreationTest.java
@@ -0,0 +1,98 @@
+/*
+ *  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.polygene.runtime.entity;
+
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.Lifecycle;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Immutable;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Test;
+
+/**
+ * Test case for http://team.ops4j.org/browse/QI-274
+ */
+public class EntityCreationTest
+    extends AbstractPolygeneTest
+{
+
+    @Mixins( SomeEntityMixin.class )
+    public interface SomeEntity
+            extends EntityComposite, Lifecycle
+    {
+
+        @Immutable
+        public Property<String> someProperty();
+
+    }
+
+    public static class SomeEntityMixin
+            implements Lifecycle
+    {
+
+        @This
+        private SomeEntity _me;
+
+        @Override
+        public void create()
+        {
+            this._me.someProperty().set( "SomeValue" );
+        }
+
+        @Override
+        public void remove()
+        {
+        }
+
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+            throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( SomeEntity.class );
+    }
+
+    @Test
+    public void doTestUseUowNewEntity()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        SomeEntity entity = uow.newEntity( SomeEntity.class );
+        uow.discard();
+    }
+
+    @Test
+    public void doTestUseEntityBuilder()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        EntityBuilder<SomeEntity> builder = uow.newEntityBuilder( SomeEntity.class );
+        SomeEntity entity = builder.newInstance();
+        uow.discard();
+    }
+
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityTypeTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityTypeTest.java
new file mode 100644
index 0000000..c5ef312
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityTypeTest.java
@@ -0,0 +1,74 @@
+/*
+ *  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.polygene.runtime.entity;
+
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+public class EntityTypeTest
+    extends AbstractPolygeneTest
+{
+    @Test
+    public void givenSubclassedEntityWhenRequestingSuperclassExpectResolutionToWork()
+        throws Exception
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            EntityBuilder<Rst> builder3 = uow.newEntityBuilder( Rst.class, new StringIdentity( "123" ) );
+            EntityBuilder<Def> builder2 = uow.newEntityBuilder( Def.class, new StringIdentity( "456" ) );
+            EntityBuilder<Abc> builder1 = uow.newEntityBuilder( Abc.class, new StringIdentity( "789" ) );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( Rst.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    public interface Abc
+        extends EntityComposite
+    {
+    }
+
+    public interface Def
+        extends Abc
+    {
+    }
+
+    public interface Rst
+        extends Def, EntityComposite
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityVisibilityTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityVisibilityTest.java
new file mode 100644
index 0000000..642bb14
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/EntityVisibilityTest.java
@@ -0,0 +1,1029 @@
+/*
+ *  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.polygene.runtime.entity;
+
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.ApplicationAssemblerAdapter;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+public class EntityVisibilityTest
+{
+
+    public static final Identity TEST_IDENTITY = new StringIdentity( "123" );
+
+    private Energy4Java polygene;
+    private Module module;
+    private Application app;
+    private UnitOfWorkFactory uowf;
+
+    @Before
+    public void setup()
+        throws Exception
+    {
+        polygene = new Energy4Java();
+
+        Assembler[][][] assemblers = new Assembler[][][]
+            {
+                { // Layer Above
+                  {
+                      new AboveAssembler()
+                  }
+                },
+                { // Layer From
+                  { // From Module
+                    new FromAssembler(),
+                  },
+                  { // Beside Module
+                    new BesideAssembler()
+                  }
+                },
+                { // Layer Below
+                  {
+                      new BelowAssembler()
+                  }
+                }
+            };
+        app = polygene.newApplication( new ApplicationAssemblerAdapter( assemblers )
+        {
+        } );
+        app.activate();
+        module = app.findModule( "From Layer", "From" );
+        uowf = module.unitOfWorkFactory();
+    }
+
+    @After
+    public void tearDown()
+        throws Exception
+    {
+        app.passivate();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromServiceWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromServiceWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromServiceWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromServiceWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromServiceWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromServiceWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.aboveModuleVisible();
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.moduleApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.moduleLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.moduleModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.besideApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.besideLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromEntityWhenAccessingBesideModuleVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.besideModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.belowApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromEntityWhenAccessingBelowLayerVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.belowLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromEntityWhenAccessingBelowModuleVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.belowModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromEntityWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.aboveApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromEntityWhenAccessingAboveLayerVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.aboveLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromEntityWhenAccessingAboveModuleVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.aboveModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromValueWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromValueWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromValueWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromValueWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromValueWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromValueWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.aboveModuleVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromTransientWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromTransientWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromTransientWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromTransientWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromTransientWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromTransientWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.aboveModuleVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromObjectWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromObjectWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromObjectWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromObjectWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromObjectWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchEntityTypeException.class )
+    public void givenFromObjectWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.aboveModuleVisible();
+    }
+
+    private static class FromAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.layer().setName( "From Layer" );
+            module.setName( "From" );
+            module.services( FromService.class );
+            module.entities( FromEntity.class );
+            module.transients( FromTransient.class );
+            module.values( FromValue.class );
+            module.objects( FromObject.class );
+
+            module.entities( ModuleApplicationVisible.class ).visibleIn( Visibility.application );
+            module.entities( ModuleLayerVisible.class ).visibleIn( Visibility.layer );
+            module.entities( ModuleModuleVisible.class ).visibleIn( Visibility.module );
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    private static class BelowAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.layer().setName( "Below Layer" );
+            module.setName( "Below" );
+            module.entities( BelowApplicationVisible.class ).visibleIn( Visibility.application );
+            module.entities( BelowLayerVisible.class ).visibleIn( Visibility.layer );
+            module.entities( BelowModuleVisible.class ).visibleIn( Visibility.module );
+
+            new EntityTestAssembler().visibleIn( Visibility.application ).assemble( module );
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    private static class AboveAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.layer().setName( "Above Layer" );
+            module.setName( "Above" );
+            module.entities( AboveApplicationVisible.class ).visibleIn( Visibility.application );
+            module.entities( AboveLayerVisible.class ).visibleIn( Visibility.layer );
+            module.entities( AboveModuleVisible.class ).visibleIn( Visibility.module );
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    private static class BesideAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.setName( "Beside" );
+            module.entities( BesideApplicationVisible.class ).visibleIn( Visibility.application );
+            module.entities( BesideLayerVisible.class ).visibleIn( Visibility.layer );
+            module.entities( BesideModuleVisible.class ).visibleIn( Visibility.module );
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    @Mixins( Mixin.class )
+    public interface From
+    {
+        void moduleApplicationVisible();
+
+        void moduleLayerVisible();
+
+        void moduleModuleVisible();
+
+        void besideApplicationVisible();
+
+        void besideLayerVisible();
+
+        void besideModuleVisible();
+
+        void belowApplicationVisible();
+
+        void belowLayerVisible();
+
+        void belowModuleVisible();
+
+        void aboveApplicationVisible();
+
+        void aboveLayerVisible();
+
+        void aboveModuleVisible();
+    }
+
+    public interface FromValue extends From, ValueComposite
+    {
+    }
+
+    public interface FromEntity extends From, EntityComposite
+    {
+    }
+
+    public interface FromService extends From, ServiceComposite
+    {
+    }
+
+    public interface FromTransient extends From, TransientComposite
+    {
+    }
+
+    public static class FromObject extends Mixin
+    {
+    }
+
+    public abstract static class Mixin
+        implements From
+    {
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @Override
+        public void moduleApplicationVisible()
+        {
+            UnitOfWork uow = uowf.newUnitOfWork();
+            try
+            {
+                ModuleApplicationVisible entity = uow.newEntity( ModuleApplicationVisible.class );
+            }
+            finally
+            {
+                if( uow.isOpen() )
+                {
+                    uow.discard();
+                }
+            }
+        }
+
+        @Override
+        public void moduleLayerVisible()
+        {
+            UnitOfWork uow = uowf.newUnitOfWork();
+            try
+            {
+                ModuleLayerVisible entity = uow.newEntity( ModuleLayerVisible.class );
+            }
+            finally
+            {
+                if( uow.isOpen() )
+                {
+                    uow.discard();
+                }
+            }
+        }
+
+        @Override
+        public void moduleModuleVisible()
+        {
+            UnitOfWork uow = uowf.newUnitOfWork();
+            try
+            {
+                ModuleModuleVisible entity = uow.newEntity( ModuleModuleVisible.class );
+            }
+            finally
+            {
+                if( uow.isOpen() )
+                {
+                    uow.discard();
+                }
+            }
+        }
+
+        @Override
+        public void besideApplicationVisible()
+        {
+            UnitOfWork uow = uowf.newUnitOfWork();
+            try
+            {
+                BesideApplicationVisible entity = uow.newEntity( BesideApplicationVisible.class );
+            }
+            finally
+            {
+                if( uow.isOpen() )
+                {
+                    uow.discard();
+                }
+            }
+        }
+
+        @Override
+        public void besideLayerVisible()
+        {
+            UnitOfWork uow = uowf.newUnitOfWork();
+            try
+            {
+                BesideLayerVisible entity = uow.newEntity( BesideLayerVisible.class );
+            }
+            finally
+            {
+                if( uow.isOpen() )
+                {
+                    uow.discard();
+                }
+            }
+        }
+
+        @Override
+        public void besideModuleVisible()
+        {
+            UnitOfWork uow = uowf.newUnitOfWork();
+            try
+            {
+                BesideModuleVisible entity = uow.newEntity( BesideModuleVisible.class );
+            }
+            finally
+            {
+                if( uow.isOpen() )
+                {
+                    uow.discard();
+                }
+            }
+        }
+
+        @Override
+        public void belowApplicationVisible()
+        {
+            UnitOfWork uow = uowf.newUnitOfWork();
+            try
+            {
+                BelowApplicationVisible entity = uow.newEntity( BelowApplicationVisible.class );
+            }
+            finally
+            {
+                if( uow.isOpen() )
+                {
+                    uow.discard();
+                }
+            }
+        }
+
+        @Override
+        public void belowLayerVisible()
+        {
+            UnitOfWork uow = uowf.newUnitOfWork();
+            try
+            {
+                BelowLayerVisible entity = uow.newEntity( BelowLayerVisible.class );
+            }
+            finally
+            {
+                if( uow.isOpen() )
+                {
+                    uow.discard();
+                }
+            }
+        }
+
+        @Override
+        public void belowModuleVisible()
+        {
+            UnitOfWork uow = uowf.newUnitOfWork();
+            try
+            {
+                BelowModuleVisible entity = uow.newEntity( BelowModuleVisible.class );
+            }
+            finally
+            {
+                if( uow.isOpen() )
+                {
+                    uow.discard();
+                }
+            }
+        }
+
+        @Override
+        public void aboveApplicationVisible()
+        {
+            UnitOfWork uow = uowf.newUnitOfWork();
+            try
+            {
+                AboveApplicationVisible entity = uow.newEntity( AboveApplicationVisible.class );
+            }
+            finally
+            {
+                if( uow.isOpen() )
+                {
+                    uow.discard();
+                }
+            }
+        }
+
+        @Override
+        public void aboveLayerVisible()
+        {
+            UnitOfWork uow = uowf.newUnitOfWork();
+            try
+            {
+                AboveLayerVisible entity = uow.newEntity( AboveLayerVisible.class );
+            }
+            finally
+            {
+                if( uow.isOpen() )
+                {
+                    uow.discard();
+                }
+            }
+        }
+
+        @Override
+        public void aboveModuleVisible()
+        {
+            UnitOfWork uow = uowf.newUnitOfWork();
+            try
+            {
+                AboveModuleVisible entity = uow.newEntity( AboveModuleVisible.class );
+            }
+            finally
+            {
+                if( uow.isOpen() )
+                {
+                    uow.discard();
+                }
+            }
+        }
+    }
+
+    public interface ModuleApplicationVisible extends EntityComposite
+    {
+    }
+
+    public interface ModuleLayerVisible extends EntityComposite
+    {
+    }
+
+    public interface ModuleModuleVisible extends EntityComposite
+    {
+    }
+
+    public interface BesideApplicationVisible extends EntityComposite
+    {
+    }
+
+    public interface BesideLayerVisible extends EntityComposite
+    {
+    }
+
+    public interface BesideModuleVisible extends EntityComposite
+    {
+    }
+
+    public interface BelowApplicationVisible extends EntityComposite
+    {
+    }
+
+    public interface BelowLayerVisible extends EntityComposite
+    {
+    }
+
+    public interface BelowModuleVisible extends EntityComposite
+    {
+    }
+
+    public interface AboveApplicationVisible extends EntityComposite
+    {
+    }
+
+    public interface AboveLayerVisible extends EntityComposite
+    {
+    }
+
+    public interface AboveModuleVisible extends EntityComposite
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/entity/LifecycleTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/LifecycleTest.java
new file mode 100644
index 0000000..1794120
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/LifecycleTest.java
@@ -0,0 +1,122 @@
+/*
+ *  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.polygene.runtime.entity;
+
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.Lifecycle;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.hamcrest.CoreMatchers;
+import org.junit.Test;
+
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for the Lifecycle interface
+ */
+public class LifecycleTest
+    extends AbstractPolygeneTest
+{
+    public static boolean create;
+    public static boolean remove;
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( TestEntity.class );
+    }
+
+    @Test
+    public void whenEntityHasLifecycleWhenInstantiatedThenInvokeCreate()
+        throws UnitOfWorkCompletionException
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class );
+            builder.newInstance();
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+
+        assertThat( "Lifecycle.create() was invoked", create, CoreMatchers.equalTo( true ) );
+    }
+
+    @Test
+    public void whenEntityHasLifecycleWhenRemovedThenInvokeRemove()
+        throws UnitOfWorkCompletionException
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class );
+            TestEntity testEntity = builder.newInstance();
+            unitOfWork.remove( testEntity );
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+
+        assertThat( "Lifecycle.remove() was invoked", remove, CoreMatchers.equalTo( true ) );
+    }
+
+    public interface Testing
+    {
+        void doSomething();
+    }
+
+    @Mixins( TestMixin.class )
+    public interface TestEntity
+        extends Testing, EntityComposite
+    {
+    }
+
+    public static class TestMixin
+        implements Lifecycle, Testing
+    {
+        public void create()
+        {
+            create = true;
+        }
+
+        public void remove()
+        {
+            remove = true;
+        }
+
+        public void doSomething()
+        {
+            System.out.println( "Test!" );
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/entity/QI273Test.java b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/QI273Test.java
new file mode 100644
index 0000000..97627ba
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/QI273Test.java
@@ -0,0 +1,103 @@
+/*
+ *  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.polygene.runtime.entity;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class QI273Test
+    extends AbstractPolygeneTest
+{
+
+    public static interface RoleA
+    {
+        public Property<String> theProperty();
+    }
+
+    public static interface RoleB
+    {
+        public Property<String> theProperty();
+    }
+
+    @Mixins( SomeDomainEntityMixin.class )
+    public static interface SomeDomainEntity
+        extends EntityComposite
+    {
+        public String getRoleAProperty();
+
+        public String getRoleBProperty();
+    }
+
+    public static abstract class SomeDomainEntityMixin
+        implements SomeDomainEntity
+    {
+        @This
+        private RoleA _a;
+        @This
+        private RoleB _b;
+
+        public String getRoleAProperty()
+        {
+            return this._a.theProperty().get();
+        }
+
+        public String getRoleBProperty()
+        {
+            return this._b.theProperty().get();
+        }
+    }
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( SomeDomainEntity.class );
+    }
+
+    @Test
+    public void doTest()
+        throws Exception
+    {
+/*
+        UnitOfWork uow = this.module.newUnitOfWork();
+
+        EntityBuilder<SomeDomainEntity> builder = uow.newEntityBuilder( SomeDomainEntity.class );
+        builder.instanceFor( RoleA.class ).theProperty().set( "a" );
+        builder.instanceFor( RoleB.class ).theProperty().set( "b" );
+        SomeDomainEntity entity = builder.newInstance();
+
+        Assert.assertEquals( "Property must be same as set.", "a", entity.getRoleAProperty() );
+        Assert.assertEquals( "Property must be same as set.", "b", entity.getRoleBProperty() );
+
+        uow.complete();
+*/
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/entity/associations/AssociationTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/associations/AssociationTest.java
new file mode 100644
index 0000000..f049c40
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/associations/AssociationTest.java
@@ -0,0 +1,222 @@
+/*
+ *  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.polygene.runtime.entity.associations;
+
+import java.io.Serializable;
+import javax.swing.Icon;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+/**
+ * Tests for associations
+ */
+public class AssociationTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( AssociationTest.Person.class,
+                         AssociationTest.Company.class );
+        module.forMixin( Employer.class )
+            .setMetaInfo( new DisplayInfo( "Employees", "Employees in the company", "Employees", null ) )
+            .declareDefaults()
+            .employees();
+        module.forMixin( Company.class ).declareDefaults().name().set( "A Company" );
+    }
+
+    @Test
+    public void testAssociation()
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+
+        try
+        {
+            Company company = unitOfWork.newEntity( Company.class );
+            Assert.assertEquals( "Company Name Default", "A Company", company.name().get() );
+
+            {
+                EntityBuilder<Company> builder = unitOfWork.newEntityBuilder( Company.class );
+                final Company companyPrototype = builder.instance();
+                companyPrototype.name().set( "JayWay" );
+                company = builder.newInstance();
+                Assert.assertEquals( "Company Name ", "JayWay", company.name().get() );
+            }
+
+            company.name().set( "Jayway" );
+            Assert.assertEquals( "Company Name ", "Jayway", company.name().get() );
+
+            System.out.println( "Name is:" + company.name().get() );
+
+            EntityBuilder<Person> builder = unitOfWork.newEntityBuilder( Person.class );
+            builder.instance().name().set( "Rickard" );
+            Person rickard = builder.newInstance();
+
+            builder = unitOfWork.newEntityBuilder( Person.class );
+            builder.instance().name().set( "Niclas" );
+            builder.instance().friend().set( rickard );
+            Person niclas = builder.newInstance();
+
+            niclas.members().add( rickard );
+
+            company.employees().add( 0, rickard );
+
+            for( Employer employer : rickard.employers() )
+            {
+                System.out.println( ( (Nameable) employer ).name() );
+            }
+
+            Assert.assertEquals( niclas.friend().get(), rickard );
+            Assert.assertEquals( niclas.members().get( 0 ), rickard );
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    public interface Friend<T>
+    {
+        @Optional
+        Association<T> friend();
+    }
+
+    public interface Team<T>
+    {
+        ManyAssociation<T> members();
+    }
+
+    public interface Company
+        extends AssociationTest.Nameable,
+                AssociationTest.Employer,
+                AssociationTest.StandardComposite,
+                EntityComposite
+    {
+    }
+
+    public interface Person
+        extends AssociationTest.Nameable,
+                AssociationTest.Employee,
+                AssociationTest.Friend<Person>,
+                AssociationTest.Team<Person>,
+                AssociationTest.StandardComposite,
+                EntityComposite
+    {
+    }
+
+    public interface StandardComposite
+    {
+    }
+
+    public interface Nameable
+    {
+        Property<String> name();
+    }
+
+    public interface Employer
+    {
+        ManyAssociation<Employee> employees();
+    }
+
+    public interface Employee
+    {
+        ManyAssociation<AssociationTest.Employer> employers();
+    }
+
+    public static class DisplayInfo
+        implements Serializable
+    {
+        private String name;
+        private String description;
+        private String toolTip;
+        private Icon icon;
+
+        public DisplayInfo( String name, String description, String toolTip )
+        {
+            this.name = name;
+            this.description = description;
+            this.toolTip = toolTip;
+        }
+
+        public DisplayInfo( String name, String description, String toolTip, Icon icon )
+        {
+            this.name = name;
+            this.description = description;
+            this.toolTip = toolTip;
+            this.icon = icon;
+        }
+
+        public String getName()
+        {
+            return name;
+        }
+
+        public String getDescription()
+        {
+            return description;
+        }
+
+        public String getToolTip()
+        {
+            return toolTip;
+        }
+
+        public Icon getIcon()
+        {
+            return icon;
+        }
+    }
+
+    public static class RdfInfo
+        implements Serializable
+    {
+        private String predicate;
+        private String namespace;
+
+        public RdfInfo( String predicate, String namespace )
+        {
+            this.predicate = predicate;
+            this.namespace = namespace;
+        }
+
+        public String getPredicate()
+        {
+            return predicate;
+        }
+
+        public String getNamespace()
+        {
+            return namespace;
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/entity/associations/ImmutableAssociationTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/associations/ImmutableAssociationTest.java
new file mode 100644
index 0000000..57c02dc
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/entity/associations/ImmutableAssociationTest.java
@@ -0,0 +1,157 @@
+/*
+ *  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.polygene.runtime.entity.associations;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Immutable;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+/**
+ * Test that associations can be marked as @Immutable
+ */
+public class ImmutableAssociationTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( PersonEntity.class );
+    }
+
+    @Test
+    public void givenEntityWithImmutableAssociationWhenBuildingThenNoException()
+        throws Exception
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            PersonEntity father = unitOfWork.newEntity( PersonEntity.class );
+
+            EntityBuilder<PersonEntity> builder = unitOfWork.newEntityBuilder( PersonEntity.class );
+            PersonEntity instance = builder.instance();
+            instance.father().set( father );
+            PersonEntity child = builder.newInstance();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    @Test( expected = IllegalStateException.class )
+    public void givenEntityWithImmutableAssociationWhenChangingValueThenThrowException()
+        throws Exception
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            EntityBuilder<PersonEntity> builder = unitOfWork.newEntityBuilder( PersonEntity.class );
+            PersonEntity father = builder.instance();
+            father = builder.newInstance();
+
+            builder = unitOfWork.newEntityBuilder( PersonEntity.class );
+            PersonEntity child = builder.instance();
+            child = builder.newInstance();
+
+            child.father().set( father );
+
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    @Test
+    public void givenEntityWithImmutableManyAssociationWhenBuildingThenNoException()
+        throws Exception
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            EntityBuilder<PersonEntity> builder = unitOfWork.newEntityBuilder( PersonEntity.class );
+            PersonEntity person1 = builder.instance();
+            person1 = builder.newInstance();
+
+            builder = unitOfWork.newEntityBuilder( PersonEntity.class );
+            PersonEntity person2 = builder.instance();
+            person2.colleagues().add( 0, person1 );
+            person2 = builder.newInstance();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    @Test( expected = IllegalStateException.class )
+    public void givenEntityWithImmutableManyAssociationWhenChangingValueThenThrowException()
+        throws Exception
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            EntityBuilder<PersonEntity> builder = unitOfWork.newEntityBuilder( PersonEntity.class );
+            PersonEntity person1 = builder.instance();
+            person1 = builder.newInstance();
+
+            builder = unitOfWork.newEntityBuilder( PersonEntity.class );
+            PersonEntity person2 = builder.instance();
+            person2 = builder.newInstance();
+
+            person1.colleagues().add( 0, person2 );
+
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    interface PersonEntity
+        extends EntityComposite
+    {
+        @Optional
+        @Immutable
+        Association<PersonEntity> father();
+
+        @Immutable
+        ManyAssociation<PersonEntity> children();
+
+        @Immutable
+        ManyAssociation<PersonEntity> friends();
+
+        @Immutable
+        ManyAssociation<PersonEntity> colleagues();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/injection/ActivatorInjectionTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/ActivatorInjectionTest.java
new file mode 100644
index 0000000..8fed08e
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/ActivatorInjectionTest.java
@@ -0,0 +1,172 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Assert that injections on Activators works.
+ */
+public class ActivatorInjectionTest
+    extends AbstractPolygeneTest
+{
+
+    @Mixins( MixinA.class )
+    public interface ServiceA
+    {
+        String what();
+    }
+
+    public static class MixinA
+        implements ServiceA
+    {
+
+        @Override
+        public String what()
+        {
+            return "A";
+        }
+
+    }
+
+    @Mixins( MixinB.class )
+    public interface ServiceB
+    {
+        String what();
+    }
+
+    public static class MixinB
+        implements ServiceB
+    {
+
+        @Override
+        public String what()
+        {
+            return "B";
+        }
+
+    }
+
+    public static class Foo
+    {
+        public String bar()
+        {
+            return "BAZAR";
+        }
+    }
+
+    public static class ServiceAActivator
+        extends ActivatorAdapter<ServiceReference<ServiceA>>
+    {
+        @Structure
+        private Application application;
+        @Structure
+        private Layer layer;
+        @Structure
+        private Module module;
+        @Service
+        private ServiceReference<ServiceB> serviceRefB;
+        @Service
+        private ServiceB serviceB;
+
+        @Override
+        public void afterActivation( ServiceReference<ServiceA> activatee )
+            throws Exception
+        {
+            assertThat( application, notNullValue() );
+            assertThat( layer, notNullValue() );
+            assertThat( module, notNullValue() );
+            assertThat( serviceRefB.isActive(), is( false ) );
+            assertThat( serviceB, notNullValue() );
+            assertThat( serviceB.what(), equalTo( "B" ) );
+        }
+    }
+
+    public static class ServiceBActivator
+        extends ActivatorAdapter<ServiceReference<ServiceB>>
+    {
+        @Structure
+        private Application application;
+        @Structure
+        private Layer layer;
+        @Structure
+        private Module module;
+        @Uses
+        private Foo foo;
+
+        @Override
+        public void afterActivation( ServiceReference<ServiceB> activatee )
+            throws Exception
+        {
+            assertThat( application, notNullValue() );
+            assertThat( layer, notNullValue() );
+            assertThat( module, notNullValue() );
+            assertThat( foo.bar(), equalTo( "BAZAR" ) );
+        }
+    }
+
+    public static class ModuleActivator
+        extends ActivatorAdapter<Module>
+    {
+
+        @Override
+        public void afterActivation( Module activatee )
+            throws Exception
+        {
+            // No injection support in Structure Activators
+            assertThat( activatee, notNullValue() );
+        }
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.withActivators( ModuleActivator.class );
+        module.objects( Foo.class );
+        module.services( ServiceA.class ).withActivators( ServiceAActivator.class ).instantiateOnStartup();
+        module.services( ServiceB.class ).withActivators( ServiceBActivator.class ).instantiateOnStartup();
+    }
+
+    @Test
+    public void test()
+    {
+        assertThat( serviceFinder.findService( ServiceA.class ).get().what(), equalTo( "A" ) );
+        assertThat( serviceFinder.findService( ServiceB.class ).get().what(), equalTo( "B" ) );
+    }
+
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/injection/ConstructorInjectionOfThisTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/ConstructorInjectionOfThisTest.java
new file mode 100644
index 0000000..413b8c5
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/ConstructorInjectionOfThisTest.java
@@ -0,0 +1,175 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.NoopMixin;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.sideeffect.SideEffectOf;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+import static org.junit.Assert.assertFalse;
+
+/**
+ * This test is created in response to QI-359
+ */
+public class ConstructorInjectionOfThisTest
+{
+
+    @Test
+    public void givenMixinWithThisInConstructorWhenCreatingModelExpectNoException()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler singletonAssembler = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.values( Does.class ).withMixins( DoesMixin.class );
+                new DefaultUnitOfWorkAssembler().assemble( module );
+            }
+        };
+        Module module = singletonAssembler.application().findModule( "Layer 1", "Module 1" );
+        Does does = module.newValue( Does.class );
+        does.doSomething();
+    }
+
+    @Test
+    public void givenConcernWithThisInConstructorWhenCreatingModelExpectNoException()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler singletonAssembler = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.values( Does.class ).withMixins( NoopMixin.class ).withConcerns( DoesConcern.class );
+            }
+        };
+        Module module = singletonAssembler.application().findModule( "Layer 1", "Module 1" );
+        Does does = module.newValue( Does.class );
+        does.doSomething();
+    }
+
+    @Test
+    public void givenSideEffectWithThisInConstructorWhenCreatingModelExpectNoException()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler singletonAssembler = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.values( Does.class ).withMixins( NoopMixin.class ).withSideEffects( DoesSideEffect.class );
+            }
+        };
+        Module module = singletonAssembler.application().findModule( "Layer 1", "Module 1" );
+        Does does = module.newValue( Does.class );
+        does.doSomething();
+    }
+
+    public static class DoesMixin
+        implements Does
+    {
+        private DoesPrivateFragment doesPrivateFragment;
+
+        public DoesMixin( @This DoesPrivateFragment doesPrivateFragment )
+        {
+            if( doesPrivateFragment == null )
+            {
+                throw new NullPointerException();
+            }
+            this.doesPrivateFragment = doesPrivateFragment;
+        }
+
+        @Override
+        public void doSomething()
+        {
+            assertFalse( doesPrivateFragment.someState().get() );
+        }
+    }
+
+    public static class DoesConcern
+        extends ConcernOf<Does>
+        implements Does
+    {
+
+        public DoesConcern( @This Does work )
+        {
+            if( work == null )
+            {
+                throw new NullPointerException();
+            }
+            System.out.print( "Niclas " );
+        }
+
+        @Override
+        public void doSomething()
+        {
+            next.doSomething();
+        }
+    }
+
+    public static class DoesSideEffect
+        extends SideEffectOf<Does>
+        implements Does
+    {
+
+        public DoesSideEffect( @This Does work )
+        {
+            if( work == null )
+            {
+                throw new NullPointerException();
+            }
+            System.out.print( "Niclas " );
+        }
+
+        @Override
+        public void doSomething()
+        {
+            this.result.doSomething();
+        }
+    }
+
+    public interface DoesPrivateFragment
+    {
+        @UseDefaults
+        Property<Boolean> someState();
+    }
+
+    public interface Does
+    {
+        void doSomething();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/injection/IllegalUnitOfWorkInjectionTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/IllegalUnitOfWorkInjectionTest.java
new file mode 100644
index 0000000..ca41d50
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/IllegalUnitOfWorkInjectionTest.java
@@ -0,0 +1,96 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.fail;
+
+public class IllegalUnitOfWorkInjectionTest
+    extends AbstractPolygeneTest
+{
+    private boolean failed = false;
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( TrialTransient.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Override
+    protected void assemblyException( AssemblyException exception )
+        throws AssemblyException
+    {
+        failed = true;
+    }
+
+    @Test
+    public void givenTransientCompositeWhenInjectingUnitOfWorkThenExpectAnInjectionException()
+        throws Exception
+    {
+        if( !failed )
+        {
+            fail( "Transients should not be allowed to have @State UnitOfWork injections." );
+        }
+    }
+
+    interface Trial
+    {
+        void doSomething();
+
+        String usecaseName();
+    }
+
+    @Mixins( TrialMixin.class )
+    interface TrialTransient
+        extends Trial, TransientComposite
+    {
+    }
+
+    public static class TrialMixin
+        implements Trial
+    {
+        @State
+        private UnitOfWork uow;
+
+        private String uowIdentity;
+
+        public void doSomething()
+        {
+            uowIdentity = uow.usecase().name();
+        }
+
+        public String usecaseName()
+        {
+            return uowIdentity;
+        }
+    }
+}
+
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/injection/InvocationInjectionTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/InvocationInjectionTest.java
new file mode 100644
index 0000000..045f722
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/InvocationInjectionTest.java
@@ -0,0 +1,147 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import java.lang.annotation.Retention;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.injection.scope.Invocation;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Test the @Invocation annotation
+ */
+public class InvocationInjectionTest
+{
+    @Test
+    public void whenInvocationInjectionWithMethodWhenInjectedThenInjectMethod()
+        throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( MyComposite.class );
+            }
+        };
+
+        MyComposite composite = assembly.module().newTransient( MyComposite.class );
+
+        composite.doStuff();
+        composite.doStuff();
+        composite.doStuff2();
+        composite.doStuff3();
+    }
+
+    @Mixins( MyMixin.class )
+    @Concerns( MyConcern.class )
+// START SNIPPET: declaration
+    public interface MyComposite
+        extends TransientComposite
+    {
+        @Foo( "1" )
+        void doStuff();
+// END SNIPPET: declaration
+        void doStuff2();
+
+        @Foo( "X" )
+        void doStuff3();
+    }
+
+// START SNIPPET: use1
+    public abstract static class MyConcern
+        extends ConcernOf<MyComposite>
+        implements MyComposite
+    {
+        @Invocation
+        Foo foo;
+// END SNIPPET: use1
+        @Invocation
+        Method method;
+
+        @Invocation
+        AnnotatedElement ae;
+
+        public void doStuff()
+        {
+            Assert.assertThat( "interface has been injected", foo.value(), CoreMatchers.equalTo( "1" ) );
+            Assert.assertThat( "annotations have been injected", ae.getAnnotation( Foo.class )
+                .value(), CoreMatchers.equalTo( "1" ) );
+            Assert.assertThat( "Method has been injected", method.getName(), CoreMatchers.equalTo( "doStuff" ) );
+            next.doStuff();
+        }
+
+        public void doStuff2()
+        {
+            Assert.assertThat( "mixin has been injected", foo.value(), CoreMatchers.equalTo( "2" ) );
+            Assert.assertThat( "annotations have been injected", ae.getAnnotation( Foo.class )
+                .value(), CoreMatchers.equalTo( "2" ) );
+            Assert.assertThat( "Method has been injected", method.getName(), CoreMatchers.equalTo( "doStuff2" ) );
+            next.doStuff2();
+        }
+
+        public void doStuff3()
+        {
+            Assert.assertThat( "mixin has overridden interface", foo.value(), CoreMatchers.equalTo( "3" ) );
+            Assert.assertThat( "annotations have been injected", ae.getAnnotation( Foo.class )
+                .value(), CoreMatchers.equalTo( "3" ) );
+            Assert.assertThat( "Method has been injected", method.getName(), CoreMatchers.equalTo( "doStuff3" ) );
+            next.doStuff3();
+        }
+    }
+
+    public abstract static class MyMixin
+        implements MyComposite
+    {
+        public void doStuff()
+        {
+        }
+
+        @Foo( "2" )
+        public void doStuff2()
+        {
+        }
+
+        @Foo( "3" )
+        public void doStuff3()
+        {
+        }
+    }
+// START SNIPPET: annotation
+    @Retention( RUNTIME )
+    @interface Foo
+    {
+        String value();
+    }
+// END SNIPPET: annotation
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/injection/ServiceInjectionTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/ServiceInjectionTest.java
new file mode 100644
index 0000000..e0d8f6b
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/ServiceInjectionTest.java
@@ -0,0 +1,374 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import java.io.Serializable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.function.Predicate;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceImporterException;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.service.qualifier.AnnotationQualifier;
+import org.apache.polygene.api.service.qualifier.IdentifiedBy;
+import org.apache.polygene.api.service.qualifier.Qualifier;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.junit.Test;
+
+import static org.apache.polygene.api.common.Visibility.application;
+import static org.apache.polygene.api.common.Visibility.layer;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test the @Service injection annotation
+ */
+public class ServiceInjectionTest
+{
+    @Test
+    public void testInjectService()
+        throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.services( MyServiceComposite.class )
+                    .identifiedBy( "Foo" )
+                    .setMetaInfo( new ServiceName( "Foo" ) );
+                module.services( MyServiceComposite2.class )
+                    .identifiedBy( "Bar" )
+                    .setMetaInfo( new ServiceName( "Bar" ) );
+                module.services( StringService.class, LongService.class );
+                module.objects( ServiceUser.class );
+            }
+        };
+
+        testInjection( assembly );
+    }
+
+    private void testInjection( SingletonAssembler assembly )
+    {
+        ObjectFactory factory = assembly.module();
+        ServiceUser user = factory.newObject( ServiceUser.class );
+
+        assertEquals( "X", user.testSingle() );
+        assertThat( user.testIdentity(), equalTo( new StringIdentity( "Foo" ) ) );
+        assertEquals( "FooX", user.testServiceReference() );
+        assertEquals( "Bar", user.testQualifier() );
+        assertEquals( "A", user.testStringIterable() );
+        assertEquals( new Long( 1L ), user.testLongIterable() );
+        assertEquals( "FooXBarX", user.testIterableServiceReferences() );
+        assertEquals( "XX", user.testIterable() );
+    }
+
+    @Test
+    public void testInjectionServiceBetweenModules()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.services( MyServiceComposite.class )
+                    .identifiedBy( "Foo" )
+                    .setMetaInfo( new ServiceName( "Foo" ) );
+                module.services( StringService.class, LongService.class );
+                module.objects( ServiceUser.class );
+
+                ModuleAssembly module2 = module.layer().module( "Other module" );
+                ServiceDeclaration service2Decl = module2.services( MyServiceComposite.class );
+                service2Decl.identifiedBy( "Bar" ).setMetaInfo( new ServiceName( "Bar" ) ).visibleIn( layer );
+
+                ServiceDeclaration service3Decl = module2.services( MyServiceComposite2.class );
+                service3Decl.identifiedBy( "Boo" ).setMetaInfo( new ServiceName( "Boo" ) );
+            }
+        };
+
+        testInjection( assembly );
+    }
+
+    @Test
+    public void testInjectionServiceBetweenLayers()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.services( MyServiceComposite.class )
+                    .identifiedBy( "Foo" )
+                    .setMetaInfo( new ServiceName( "Foo" ) );
+                module.services( StringService.class, LongService.class );
+                LayerAssembly layerAssembly = module.layer();
+                module.objects( ServiceUser.class );
+
+                ApplicationAssembly applicationAssembly = layerAssembly.application();
+                LayerAssembly layer2Assembly = applicationAssembly.layer( "Other layer" );
+                layerAssembly.uses( layer2Assembly );
+
+                ModuleAssembly module2 = layer2Assembly.module( "Other module" );
+
+                ServiceDeclaration service2Decl = module2.services( MyServiceComposite2.class );
+                service2Decl.identifiedBy( "Bar" ).setMetaInfo( new ServiceName( "Bar" ) ).visibleIn( application );
+            }
+        };
+
+        testInjection( assembly );
+    }
+
+    @Test( expected = ConstructionException.class )
+    public void testMissingServiceDependency()
+        throws ActivationException, AssemblyException
+    {
+        // No service fulfils the dependency injection -> fail to create application
+        new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.objects( ServiceUser.class );
+            }
+        }.module().newObject( ServiceUser.class );
+    }
+
+    @Mixins( MyServiceMixin.class )
+    public interface MyServiceComposite
+        extends MyService, ServiceComposite
+    {
+    }
+
+    public interface MyServiceComposite2
+        extends MyServiceComposite
+    {
+    }
+
+    public interface MyService
+    {
+        String doStuff();
+    }
+
+    public static class MyServiceMixin
+        implements MyService
+    {
+
+        public String doStuff()
+        {
+            return "X";
+        }
+    }
+
+    public static class ServiceUser
+        extends AbstractServiceUser<String>
+    {
+    }
+
+    public static class AbstractServiceUser<T>
+    {
+        @Service
+        MyService service;
+
+        @Service
+        MyServiceComposite serviceComposite;
+
+        @Service
+        Iterable<MyService> services;
+
+        @Service
+        ServiceReference<MyService> serviceRef;
+
+        @Service
+        Iterable<ServiceReference<MyService>> serviceRefs;
+
+        @Service
+        @IdentifiedBy( "Bar" )
+        ServiceReference<MyService> qualifiedService;
+
+        @Service
+        @IdentifiedBy( "Bar" )
+        Iterable<ServiceReference<MyService>> qualifiedServiceRefs;
+
+        @Optional
+        @Service
+        MyServiceMixin optionalService12;
+
+        @Service
+        Foo<Long> longService;
+
+        @Service
+        Foo<T> stringService;
+
+        public String testSingle()
+        {
+            return service.doStuff();
+        }
+
+        public Identity testIdentity()
+        {
+            return serviceComposite.identity().get();
+        }
+
+        public String testIterable()
+        {
+            String str = "";
+            for( MyService myService : services )
+            {
+                str += myService.doStuff();
+            }
+            return str;
+        }
+
+        public String testServiceReference()
+            throws ServiceImporterException
+        {
+            ServiceName info = serviceRef.metaInfo( ServiceName.class );
+            return info.getName() + serviceRef.get().doStuff();
+        }
+
+        public String testIterableServiceReferences()
+            throws ServiceImporterException
+        {
+            String str = "";
+            for( ServiceReference<MyService> serviceReference : serviceRefs )
+            {
+                str += serviceReference.metaInfo( ServiceName.class ).getName();
+                str += serviceReference.get().doStuff();
+            }
+            return str;
+        }
+
+        public String testQualifier()
+        {
+            return qualifiedService.metaInfo( ServiceName.class ).getName();
+        }
+
+        public String testQualifiedServices()
+        {
+            String str = "";
+            for( ServiceReference<MyService> qualifiedServiceRef : qualifiedServiceRefs )
+            {
+                str += qualifiedServiceRef.metaInfo( ServiceName.class ).getName();
+            }
+            return str;
+        }
+
+        public T testStringIterable()
+        {
+            return stringService.get();
+        }
+
+        public Long testLongIterable()
+        {
+            return longService.get();
+        }
+    }
+
+    @Qualifier( NamedSelector.class )
+    @Retention( RetentionPolicy.RUNTIME )
+    public @interface Named
+    {
+        String value();
+    }
+
+    public static final class NamedSelector
+        implements AnnotationQualifier<Named>
+    {
+        public <T> Predicate<ServiceReference<?>> qualifier( final Named named )
+        {
+            return new Predicate<ServiceReference<?>>()
+            {
+                public boolean test( ServiceReference<?> service )
+                {
+                    ServiceName serviceName = service.metaInfo( ServiceName.class );
+                    return ( serviceName != null && serviceName.getName().equals( named.value() ) );
+                }
+            };
+        }
+    }
+
+    public static class ServiceName
+        implements Serializable
+    {
+        private String name;
+
+        public ServiceName( String name )
+        {
+            this.name = name;
+        }
+
+        public String getName()
+        {
+            return name;
+        }
+    }
+
+    public interface Foo<T>
+    {
+        T get();
+    }
+
+    @Mixins( StringService.Mixin.class )
+    public interface StringService
+        extends Foo<String>, ServiceComposite
+    {
+        class Mixin
+            implements Foo<String>
+        {
+            @Override
+            public String get()
+            {
+                return "A";
+            }
+        }
+    }
+
+    @Mixins( LongService.Mixin.class )
+    public interface LongService
+        extends Foo<Long>, ServiceComposite
+    {
+        class Mixin
+            implements Foo<Long>
+        {
+            @Override
+            public Long get()
+            {
+                return 1L;
+            }
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/injection/StateInjectionTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/StateInjectionTest.java
new file mode 100644
index 0000000..f6a0663
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/StateInjectionTest.java
@@ -0,0 +1,111 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import org.junit.Test;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test the @State annotation
+ */
+public class StateInjectionTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( StateInjectionTest.PropertyFieldInjectionComposite.class );
+    }
+
+    /**
+     * Tests that a mixin is injected into member variables annotated with {@link @PropertyField}.
+     *
+     * @throws Exception re-thrown
+     */
+    @Test
+    public void mixinIsInjectedForMemberVariablesAnnotatedWithPropertyField()
+        throws Exception
+    {
+        TransientBuilder<PropertyFieldInjectionComposite> pficBuilder =
+            transientBuilderFactory.newTransientBuilder( StateInjectionTest.PropertyFieldInjectionComposite.class );
+        pficBuilder.prototype().testField().set( "X" );
+        PropertyFieldInjectionComposite pfic = pficBuilder.newInstance();
+        assertThat( "Test field", pfic.testField().get(), is( equalTo( "X" ) ) );
+        assertThat( "Named fieldX", pfic.namedField().get(), is( equalTo( "X" ) ) );
+        assertThat( "State", pfic.getState()
+                                 .propertyFor( PropertyFieldInjectionComposite.class.getMethod( "testField" ) )
+                                 .get(), is( equalTo( "X" ) ) );
+    }
+
+    @Mixins( PropertyFieldInjectionMixin.class )
+    public interface PropertyFieldInjectionComposite
+        extends TransientComposite
+    {
+        @Optional
+        Property<String> testField();
+
+        @Optional
+        Property<String> namedField();
+
+        StateHolder getState();
+    }
+
+    public abstract static class PropertyFieldInjectionMixin
+        implements PropertyFieldInjectionComposite
+    {
+        @State
+        Property<String> testField;
+
+        @State( "testField" )
+        Property<String> namedField;
+
+        @State
+        StateHolder state;
+
+        public StateHolder getState()
+        {
+            return state;
+        }
+
+        public Property<String> testField()
+        {
+            return testField;
+        }
+
+        public Property<String> namedField()
+        {
+            return namedField;
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/injection/StateParameterInjectionTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/StateParameterInjectionTest.java
new file mode 100644
index 0000000..74e632c
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/StateParameterInjectionTest.java
@@ -0,0 +1,102 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test the @State annotation when used for parameters
+ */
+public class StateParameterInjectionTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( PropertyParameterInjectionComposite.class );
+    }
+
+    /**
+     * Tests that a mixin is injected where method parameters are annotated with {@link @PropertyParameter}.
+     *
+     * @throws Exception re-thrown
+     */
+    @Test
+    public void mixinIsInjectedForMethodParametersAnnotatedWithPropertyparameter()
+        throws Exception
+    {
+        TransientBuilder<PropertyParameterInjectionComposite> pficBuilder =
+            transientBuilderFactory.newTransientBuilder( PropertyParameterInjectionComposite.class );
+        pficBuilder.prototype().testField().set( "X" );
+        pficBuilder.prototype().namedField().set( "Y" );
+        PropertyParameterInjectionComposite pfic = pficBuilder.newInstance();
+        assertThat( "Test field", pfic.testField().get(), is( equalTo( "X" ) ) );
+        assertThat( "Named field", pfic.namedField().get(), is( equalTo( "Y" ) ) );
+    }
+
+    @Mixins( PropertyParameterInjectionMixin.class )
+    public interface PropertyParameterInjectionComposite
+        extends TransientComposite
+    {
+        Property<String> testField();
+
+        Property<String> namedField();
+    }
+
+    public abstract static class PropertyParameterInjectionMixin
+        implements PropertyParameterInjectionComposite
+    {
+        Property<String> testField;
+        Property<String> namedField;
+
+        public PropertyParameterInjectionMixin( @State( "testField" ) Property<String> testField )
+        {
+            this.testField = testField;
+        }
+
+        void init( @State( "namedField" ) Property<String> namedField )
+        {
+            this.namedField = namedField;
+        }
+
+        public Property<String> testField()
+        {
+            return testField;
+        }
+
+        public Property<String> namedField()
+        {
+            return namedField;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/injection/StructureInjectionTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/StructureInjectionTest.java
new file mode 100644
index 0000000..d98c51e
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/StructureInjectionTest.java
@@ -0,0 +1,202 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import org.junit.Test;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test the @Structure annotation
+ */
+public class StructureInjectionTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( StructureInjectionComposite.class );
+    }
+
+    /**
+     * Tests injected mixin for a CompositeBuilderFactory annotated with {@link @org.apache.polygene.composite.scope.Structure}.
+     */
+    @Test
+    public void injectedStructureForCompositeBuilderFactory()
+    {
+        StructureInjectionComposite sic = transientBuilderFactory.newTransient( StructureInjectionComposite.class );
+        assertThat( "Injected CompositeBuilderFactory", sic.getCompositeBuilderFactory(), is( notNullValue() ) );
+    }
+
+    /**
+     * Tests injected mixin for a ObjectBuilderFactory annotated with {@link @org.apache.polygene.composite.scope.Structure}.
+     */
+    @Test
+    public void injectedStructureForObjectBuilderFactory()
+    {
+        StructureInjectionComposite sic = transientBuilderFactory.newTransient( StructureInjectionComposite.class );
+        assertThat( "Injected ObjectBuilderFactory", sic.getObjectFactory(), is( notNullValue() ) );
+    }
+
+    /**
+     * Tests injected mixin for a UnitOfWorkFactory annotated with {@link @org.apache.polygene.composite.scope.Structure}.
+     */
+    @Test
+    public void injectedStructureForUnitOfWorkFactory()
+    {
+        StructureInjectionComposite sic = transientBuilderFactory.newTransient( StructureInjectionComposite.class );
+        assertThat( "Injected UnitOfWorkFactory", sic.getUnitOfWorkFactory(), is( notNullValue() ) );
+    }
+
+    /**
+     * Tests injected mixin for a ServiceLocator annotated with {@link @org.apache.polygene.composite.scope.Structure}.
+     */
+    @Test
+    public void injectedStructureForServiceLocator()
+    {
+        StructureInjectionComposite sic = transientBuilderFactory.newTransient( StructureInjectionComposite.class );
+        assertThat( "Injected ServiceLocator", sic.getServiceLocator(), is( notNullValue() ) );
+    }
+
+    /**
+     * Tests injected mixin for a ModuleBinding annotated with {@link @org.apache.polygene.composite.scope.Structure}.
+     */
+    @Test
+    public void injectedStructureForModuleBinding()
+    {
+        StructureInjectionComposite sic = transientBuilderFactory.newTransient( StructureInjectionComposite.class );
+        assertThat( "Injected Module", sic.getModule(), is( notNullValue() ) );
+    }
+
+    /**
+     * Tests injected mixin for a Polygene annotated with {@link @org.apache.polygene.composite.scope.Structure}.
+     */
+    @Test
+    public void injectedStructureForPolygene()
+    {
+        StructureInjectionComposite sic = transientBuilderFactory.newTransient( StructureInjectionComposite.class );
+        assertThat( "Injected Polygene", sic.getPolygene(), is( notNullValue() ) );
+    }
+
+    /**
+     * Tests injected mixin for a PolygeneSPI annotated with {@link @org.apache.polygene.composite.scope.Structure}.
+     */
+    @Test
+    public void injectedStructureForPolygeneSpi()
+    {
+        StructureInjectionComposite sic = transientBuilderFactory.newTransient( StructureInjectionComposite.class );
+        assertThat( "Injected PolygeneSPI", sic.getPolygeneSpi(), is( notNullValue() ) );
+    }
+
+    @Mixins( StructureInjectionMixin.class )
+    public interface StructureInjectionComposite
+        extends TransientComposite
+    {
+        public TransientBuilderFactory getCompositeBuilderFactory();
+
+        public ObjectFactory getObjectFactory();
+
+        public UnitOfWorkFactory getUnitOfWorkFactory();
+
+        public ServiceFinder getServiceLocator();
+
+        public Module getModule();
+
+        public PolygeneAPI getPolygene();
+
+        public PolygeneSPI getPolygeneSpi();
+    }
+
+    public abstract static class StructureInjectionMixin
+        implements StructureInjectionComposite
+    {
+        @Structure
+        TransientBuilderFactory compositeBuilderFactory;
+
+        @Structure
+        ObjectFactory objectFactory;
+
+        @Structure
+        UnitOfWorkFactory unitOfWorkFactory;
+
+        @Structure
+        ServiceFinder serviceLocator;
+
+        @Structure
+        Module module;
+
+        @Structure
+        PolygeneAPI api;
+        @Structure
+        PolygeneSPI spi;
+
+        public TransientBuilderFactory getCompositeBuilderFactory()
+        {
+            return compositeBuilderFactory;
+        }
+
+        public ObjectFactory getObjectFactory()
+        {
+            return objectFactory;
+        }
+
+        public UnitOfWorkFactory getUnitOfWorkFactory()
+        {
+            return unitOfWorkFactory;
+        }
+
+        public ServiceFinder getServiceLocator()
+        {
+            return serviceLocator;
+        }
+
+        public Module getModule()
+        {
+            return module;
+        }
+
+        public PolygeneAPI getPolygene()
+        {
+            return api;
+        }
+
+        public PolygeneSPI getPolygeneSpi()
+        {
+            return spi;
+        }
+    }
+}
+
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/injection/ThisInjectionTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/ThisInjectionTest.java
new file mode 100644
index 0000000..de0aed8
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/ThisInjectionTest.java
@@ -0,0 +1,143 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.sideeffect.SideEffectOf;
+import org.apache.polygene.api.sideeffect.SideEffects;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test the @This annotation
+ */
+public class ThisInjectionTest
+    extends AbstractPolygeneTest
+{
+    public static boolean sideEffectInjected;
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( TestComposite.class );
+    }
+
+    /**
+     * Tests the injected object for {@link @org.apache.polygene.composite.scope.This} annotation.
+     *
+     * @throws Exception re-thrown
+     */
+    @org.junit.Test
+    public void givenCompositeWithThisInjectionsWhenInstantiatedThenCompositeIsInjected()
+        throws Exception
+    {
+        TestComposite testComposite = transientBuilderFactory.newTransient( TestComposite.class );
+
+        assertThat( "Injection worked", testComposite.isInjected() && sideEffectInjected, is( equalTo( true ) ) );
+    }
+
+    public interface Test
+    {
+        boolean isInjected();
+
+        String test();
+    }
+
+    public interface TestPrivate
+    {
+        @UseDefaults
+        Property<Boolean> testPrivate();
+    }
+
+    @SideEffects( TestSideEffect.class )
+    @Concerns( TestConcern.class )
+    @Mixins( TestMixin.class )
+    public interface TestComposite
+        extends TransientComposite, Test
+    {
+    }
+
+    public static class TestMixin
+        implements Test
+    {
+        @This
+        Test test;
+
+        @This
+        TestPrivate testPrivate;
+
+        public boolean isInjected()
+        {
+            return test != null && !testPrivate.testPrivate().get();
+        }
+
+        public String test()
+        {
+            return "Foo";
+        }
+    }
+
+    public static abstract class TestConcern
+        extends ConcernOf<Test>
+        implements Test
+    {
+        @This
+        Test test;
+
+        @This
+        TestPrivate testPrivate;
+
+        public boolean isInjected()
+        {
+            return test != null && test.test().equals( "Foo" ) &&
+                   !testPrivate.testPrivate().get() &&
+                   next.isInjected();
+        }
+    }
+
+    public static abstract class TestSideEffect
+        extends SideEffectOf<Test>
+        implements Test
+    {
+        @This
+        Test test;
+        @This
+        TestPrivate testPrivate;
+
+        public boolean isInjected()
+        {
+            sideEffectInjected = test != null && !testPrivate.testPrivate().get();
+
+            return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/injection/UnitOfWorkInjectionTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/UnitOfWorkInjectionTest.java
new file mode 100644
index 0000000..8a38d17
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/UnitOfWorkInjectionTest.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.polygene.runtime.injection;
+
+import org.apache.polygene.api.identity.StringIdentity;
+import org.junit.Test;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.assertEquals;
+
+public class UnitOfWorkInjectionTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( TrialEntity.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Test
+    public void givenEntityInOneUnitOfWorkWhenCurrentUnitOfWorkHasChangedThenUnitOfWorkInjectionInEntityPointsToCorrectUow()
+        throws Exception
+    {
+        Usecase usecase = UsecaseBuilder.newUsecase( "usecase1" );
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( usecase );
+        try
+        {
+            Trial trial = uow.newEntity( Trial.class, new StringIdentity( "123" ) );
+            trial.doSomething();
+            uow.complete();
+            uow = unitOfWorkFactory.newUnitOfWork( usecase );
+            usecase = UsecaseBuilder.newUsecase( "usecase2" );
+            UnitOfWork uow2 = unitOfWorkFactory.newUnitOfWork( usecase );
+            trial = uow.get( trial );
+            trial.doSomething();
+            assertEquals( "123", ( (EntityComposite) trial ).identity().get().toString() );
+            assertEquals( "usecase1", trial.usecaseName() );
+            uow2.discard();
+        }
+        catch( Throwable ex )
+        {
+            ex.printStackTrace();
+        }
+        finally
+        {
+            try
+            {
+                while( unitOfWorkFactory.isUnitOfWorkActive() )
+                {
+                    uow = unitOfWorkFactory.currentUnitOfWork();
+                    uow.discard();
+                }
+            }
+            catch( IllegalStateException e )
+            {
+                // Continue
+            }
+        }
+    }
+
+    public interface Trial
+    {
+        void doSomething();
+
+        String usecaseName();
+    }
+
+    @Mixins( TrialMixin.class )
+    public interface TrialEntity
+        extends Trial, EntityComposite
+    {
+    }
+
+    public static class TrialMixin
+        implements Trial
+    {
+        @State
+        private UnitOfWork uow;
+
+        private String uowIdentity;
+
+        public void doSomething()
+        {
+            uowIdentity = uow.usecase().name();
+        }
+
+        public String usecaseName()
+        {
+            return uowIdentity;
+        }
+    }
+}
+
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/injection/UsesGenericClassTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/UsesGenericClassTest.java
new file mode 100644
index 0000000..2b94d47
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/UsesGenericClassTest.java
@@ -0,0 +1,75 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test of generic class injection
+ */
+public class UsesGenericClassTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( TestCase.class );
+    }
+
+    @Test
+    public void givenMixinUsesGenericClassWhenUseClassThenInjectWorks()
+    {
+        TransientBuilder<TestCase> builder = transientBuilderFactory.newTransientBuilder( TestCase.class );
+
+        builder.use( UsesGenericClassTest.class );
+
+        TestCase testCase = builder.newInstance();
+        assertThat( "class name is returned", testCase.test(), equalTo( UsesGenericClassTest.class.getName() ) );
+    }
+
+    @Mixins( TestMixin.class )
+    public interface TestCase
+        extends TransientComposite
+    {
+        String test();
+    }
+
+    public abstract static class TestMixin
+        implements TestCase
+    {
+        @Uses
+        Class<? extends TestCase> clazz;
+
+        public String test()
+        {
+            return clazz.getName();
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/injection/UsesGenericListTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/UsesGenericListTest.java
new file mode 100644
index 0000000..7dc6f78
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/UsesGenericListTest.java
@@ -0,0 +1,77 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import java.util.ArrayList;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+/**
+ * Test of generic list injection
+ */
+public class UsesGenericListTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( TestCase.class );
+    }
+
+    @Test
+    public void givenMixinUsesGenericListWhenUseListThenInjectWorks()
+    {
+        TransientBuilder<TestCase> builder = transientBuilderFactory.newTransientBuilder( TestCase.class );
+
+        ArrayList<String> list = new ArrayList<String>();
+        list.add( "Hello" );
+        list.add( "Bye" );
+        builder.use( list );
+
+        TestCase TestCase = builder.newInstance();
+        TestCase.sayHello();
+    }
+
+    @Mixins( TestMixin.class )
+    public interface TestCase
+        extends TransientComposite
+    {
+        void sayHello();
+    }
+
+    public abstract static class TestMixin
+        implements TestCase
+    {
+        @Uses
+        ArrayList<String> messages;
+
+        public void sayHello()
+        {
+            System.out.println( messages );
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/injection/UsesGraphTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/UsesGraphTest.java
new file mode 100644
index 0000000..d42c846
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/UsesGraphTest.java
@@ -0,0 +1,90 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+
+/**
+ * Test creation of object graph, where @Uses is used to refer to instances
+ */
+public class UsesGraphTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.objects( A.class, B.class, C.class, D.class );
+    }
+
+    @Test
+    public void givenGraphDependenciesWhenInstantiateAThenGetSameReferences()
+    {
+        D d = new D();
+        A a = objectFactory.newObject( A.class, objectFactory.newObject( C.class, d ), d );
+
+        Assert.assertThat( "Same reference expected", a.c, equalTo( a.b.c ) );
+        Assert.assertThat( "Same reference expected", a.d, equalTo( a.b.c.d ) );
+    }
+
+    @Test
+    public void givenGraphDependenciesWhenInstantiateUsingBuildersThenDontGetSameReferences()
+    {
+        A a = objectFactory.newObject( A.class );
+        Assert.assertThat( "Same reference not expected", a.c, not( equalTo( a.b.c ) ) );
+        Assert.assertThat( "Same reference not expected", a.d, not( equalTo( a.b.c.d ) ) );
+    }
+
+    static public class A
+    {
+        @Uses
+        B b;
+
+        @Uses
+        C c;
+
+        @Uses
+        D d;
+    }
+
+    static public class B
+    {
+        @Uses
+        C c;
+    }
+
+    static public class C
+    {
+        @Uses
+        D d;
+    }
+
+    static public class D
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/injection/UsesInjectionTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/UsesInjectionTest.java
new file mode 100644
index 0000000..88c55c2
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/injection/UsesInjectionTest.java
@@ -0,0 +1,93 @@
+/*
+ *  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.polygene.runtime.injection;
+
+import org.junit.Test;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test the @Uses annotation
+ */
+public class UsesInjectionTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.objects( InjectionTarget.class, ToBeInjected.class );
+    }
+
+    @Test
+    public void givenUsedObjectWhenUseWithBuilderThenInjectReferences()
+        throws Exception
+    {
+        ToBeInjected toBeInjected = new ToBeInjected();
+        assertThat( "Injected object", objectFactory.newObject( InjectionTarget.class, toBeInjected, true )
+            .getUsedObject(), is( equalTo( toBeInjected ) ) );
+        assertThat( "Injected boolean", objectFactory.newObject( InjectionTarget.class, toBeInjected, true )
+            .isUsedBoolean(), is( equalTo( true ) ) );
+    }
+
+    @Test
+    public void givenUsedObjectBuilderWhenUseWithBuilderThenInjectNewInstance()
+        throws Exception
+    {
+        assertThat( "Injected object", objectFactory.newObject( InjectionTarget.class, objectFactory.newObject( ToBeInjected.class ), true ), is( notNullValue() ) );
+    }
+
+    @Test
+    public void givenNoUsesWhenBuilderNewInstanceThenInjectNewInstance()
+        throws Exception
+    {
+        assertThat( "Injected object", objectFactory.newObject( InjectionTarget.class, true ), is( notNullValue() ) );
+    }
+
+    public static class InjectionTarget
+    {
+        @Uses
+        ToBeInjected usedObject;
+
+        @Uses
+        boolean usedBoolean;
+
+        public ToBeInjected getUsedObject()
+        {
+            return usedObject;
+        }
+
+        public boolean isUsedBoolean()
+        {
+            return usedBoolean;
+        }
+    }
+
+    public static class ToBeInjected
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/instantiation/EagerServiceInstantiationTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/instantiation/EagerServiceInstantiationTest.java
new file mode 100644
index 0000000..70282d3
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/instantiation/EagerServiceInstantiationTest.java
@@ -0,0 +1,86 @@
+/*
+ *  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.polygene.runtime.instantiation;
+
+import org.junit.Test;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class EagerServiceInstantiationTest
+    extends AbstractPolygeneTest
+{
+    private TestInfo testInfo;
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        testInfo = new TestInfo();
+        module.services( MyService.class ).setMetaInfo( testInfo ).instantiateOnStartup();
+    }
+
+    @Test
+    public void givenServiceInstantiatedOnStartUpWhenTestIsRunExpectServiceToHaveRun()
+    {
+        assertEquals( "123", testInfo.test );
+    }
+
+    @Mixins( MyMixin.class )
+    public interface MyService
+        extends My, ServiceComposite
+    {
+    }
+
+    public interface My
+    {
+        void doSomething();
+    }
+
+    public static class MyMixin
+        implements My
+    {
+        public MyMixin( @Uses ServiceDescriptor descriptor )
+        {
+            descriptor.metaInfo( TestInfo.class ).test = "123";
+        }
+
+        public MyMixin()
+        {
+            System.out.println( "Constructor" );
+        }
+
+        public void doSomething()
+        {
+            System.out.println( "Execute" );
+        }
+    }
+
+    public class TestInfo
+    {
+        private String test = "abc";
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/instantiation/ServiceInstantiationTests.java b/core/runtime/src/test/java/org/apache/polygene/runtime/instantiation/ServiceInstantiationTests.java
new file mode 100644
index 0000000..214c4bc
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/instantiation/ServiceInstantiationTests.java
@@ -0,0 +1,78 @@
+/*
+ *  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.polygene.runtime.instantiation;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+public class ServiceInstantiationTests
+    extends AbstractPolygeneTest
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( MyConfiguration.class );
+        module.services( My.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Test
+    public void whenCreatingServiceCompositeGivenAServiceCompositeThenSucceed()
+        throws Exception
+    {
+        ServiceReference<My> service = serviceFinder.findService( My.class );
+        Assert.assertEquals( "HabbaZout", service.get().doSomething() );
+    }
+
+    @Mixins( MyMixin.class )
+    public interface My
+    {
+        String doSomething();
+    }
+
+    public interface MyConfiguration
+    {
+        Property<String> data();
+    }
+
+    public static class MyMixin
+        implements My
+    {
+        @This
+        Configuration<MyConfiguration> config;
+
+        @Override
+        public String doSomething()
+        {
+            return config.get().data().get();
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/instantiation/TransientInstantiationTests.java b/core/runtime/src/test/java/org/apache/polygene/runtime/instantiation/TransientInstantiationTests.java
new file mode 100644
index 0000000..39f17f0
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/instantiation/TransientInstantiationTests.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.runtime.instantiation;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+public class TransientInstantiationTests
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( MyTransient.class );
+    }
+
+    @Test
+    public void whenCreatingServiceCompositeGivenAServiceCompositeThenSucceed()
+        throws Exception
+    {
+        TransientBuilder<My> builder = transientBuilderFactory.newTransientBuilder( My.class );
+        My my = builder.newInstance();
+        Assert.assertEquals( "Niclas", my.doSomething() );
+    }
+
+    @Mixins( MyMixin.class )
+    public interface MyTransient
+        extends TransientComposite, My
+    {
+    }
+
+    public interface My
+    {
+        String doSomething();
+    }
+
+    public static class MyMixin
+        implements My
+    {
+        public String doSomething()
+        {
+            return "Niclas";
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/instantiation/ValueInstantiationTests.java b/core/runtime/src/test/java/org/apache/polygene/runtime/instantiation/ValueInstantiationTests.java
new file mode 100644
index 0000000..b149220
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/instantiation/ValueInstantiationTests.java
@@ -0,0 +1,111 @@
+/*
+ *  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.polygene.runtime.instantiation;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.junit.Assert.fail;
+
+public class ValueInstantiationTests
+    extends AbstractPolygeneTest
+{
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.values( MyValue.class );
+    }
+
+    @Test
+    public void whenTryingToCreateValueFromNullTypeThenExpectNullPointerException()
+        throws Exception
+    {
+        // valueBuilderFactory.newValueBuilder()
+        try
+        {
+            valueBuilderFactory.newValueBuilder( null );
+            fail( "NullPointerException was expected." );
+        }
+        catch( NullPointerException e )
+        {
+            // expected
+        }
+
+        // valueBuilderFactory.newValue();
+        try
+        {
+            valueBuilderFactory.newValue( null );
+            fail( "NullPointerException was expected." );
+        }
+        catch( NullPointerException e )
+        {
+            // expected
+        }
+
+        //module.newValueFromSerializedState();
+        try
+        {
+            valueBuilderFactory.newValueFromSerializedState( null, "abc:123" );
+            ValueBuilder<My> builder = valueBuilderFactory.newValueBuilder( null );
+            fail( "NullPointerException was expected." );
+        }
+        catch( NullPointerException e )
+        {
+            // expected
+        }
+    }
+
+    @Test
+    public void whenCreatingServiceCompositeGivenAServiceCompositeThenSucceed()
+        throws Exception
+    {
+        ValueBuilder<My> builder = valueBuilderFactory.newValueBuilder( My.class );
+        My my = builder.newInstance();
+        Assert.assertEquals( "Niclas", my.doSomething() );
+    }
+
+    @Mixins( MyMixin.class )
+    public interface MyValue
+        extends ValueComposite, My
+    {
+    }
+
+    public interface My
+    {
+        String doSomething();
+    }
+
+    public static class MyMixin
+        implements My
+    {
+
+        public String doSomething()
+        {
+            return "Niclas";
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/AssemblyMixinTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/AssemblyMixinTest.java
new file mode 100644
index 0000000..e0ed2ba
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/AssemblyMixinTest.java
@@ -0,0 +1,114 @@
+/*
+ *  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.polygene.runtime.mixin;
+
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test of declaring mixin in assembly
+ */
+public class AssemblyMixinTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+
+        module.transients( FooComposite.class ).withMixins( CustomFooMixin.class );
+
+        module.entities( FooEntity.class ).withMixins( FooMixin.class );
+    }
+
+    @Test
+    public void testAssemblyMixins()
+    {
+        assertThat( "Custom mixin has executed", transientBuilderFactory.newTransient( Foo.class )
+            .test( "Foo", 42 ), equalTo( "Foo/42" ) );
+    }
+
+    @Test
+    public void testAssemblyMixinsEntity()
+        throws UnitOfWorkCompletionException
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        FooEntity entity = uow.newEntity( FooEntity.class, new StringIdentity( "123" ) );
+        uow.complete();
+
+        uow = unitOfWorkFactory.newUnitOfWork();
+        Foo foo = uow.get( Foo.class, new StringIdentity( "123" ) );
+
+        try
+        {
+            assertThat( "Custom mixin has executed", foo.test( "Foo", 42 ), equalTo( "Foo 42" ) );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    public interface FooComposite
+        extends TransientComposite, Foo
+    {
+    }
+
+    public interface Foo
+    {
+        String test( String foo, int bar );
+    }
+
+    public static class FooMixin
+        implements Foo
+    {
+        public String test( String foo, int bar )
+        {
+            return foo + " " + bar;
+        }
+    }
+
+    public static class CustomFooMixin
+        implements Foo
+    {
+        public String test( String foo, int bar )
+        {
+            return foo + "/" + bar;
+        }
+    }
+
+    public interface FooEntity
+        extends EntityComposite, Foo
+    {
+
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/AssemblyRoleTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/AssemblyRoleTest.java
new file mode 100644
index 0000000..0f1f3b9
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/AssemblyRoleTest.java
@@ -0,0 +1,129 @@
+/*
+ *  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.polygene.runtime.mixin;
+
+import org.apache.polygene.api.identity.StringIdentity;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test of declaring types in assembly
+ */
+public class AssemblyRoleTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+
+        module.transients( FooComposite.class ).withTypes( Foo.class );
+        module.transients( FooComposite2.class ).withTypes( Foo.class ).withMixins( CustomFooMixin.class );
+
+        module.entities( FooEntity.class ).withTypes( Foo.class );
+    }
+
+    @Test
+    public void testAssemblyTypesCustomMixin()
+    {
+        FooComposite2 composite2 = transientBuilderFactory.newTransient( FooComposite2.class );
+        assertThat( "Custom mixin has executed", ( (Foo) composite2 ).test( "Foo", 42 ), equalTo( "Foo/42" ) );
+    }
+
+    @Test
+    public void testAssemblyTypesDefaultMixin()
+    {
+        FooComposite composite = transientBuilderFactory.newTransient( FooComposite.class );
+        assertThat( "Default mixin has executed", ( (Foo) composite ).test( "Foo", 42 ), equalTo( "Foo 42" ) );
+    }
+
+    @Test
+    public void testAssemblyMixinsEntity()
+        throws UnitOfWorkCompletionException
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        uow.newEntity( FooEntity.class, new StringIdentity( "123" ) );
+        uow.complete();
+
+        uow = unitOfWorkFactory.newUnitOfWork();
+        Foo foo = uow.get( Foo.class, new StringIdentity( "123" ) );
+
+        try
+        {
+            assertThat( "Default mixin has executed", foo.test( "Foo", 42 ), equalTo( "Foo 42" ) );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    public interface FooComposite
+        extends TransientComposite
+    {
+    }
+
+    public interface FooComposite2
+        extends TransientComposite
+    {
+    }
+
+    @Mixins( FooMixin.class )
+    public interface Foo
+    {
+        String test( String foo, int bar );
+    }
+
+    public static class FooMixin
+        implements Foo
+    {
+        public String test( String foo, int bar )
+        {
+            return foo + " " + bar;
+        }
+    }
+
+    public static class CustomFooMixin
+        implements Foo
+    {
+        public String test( String foo, int bar )
+        {
+            return foo + "/" + bar;
+        }
+    }
+
+    public interface FooEntity
+        extends EntityComposite
+    {
+
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/DefaultMethodsTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/DefaultMethodsTest.java
new file mode 100644
index 0000000..20f22be
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/DefaultMethodsTest.java
@@ -0,0 +1,97 @@
+/*
+ *  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.polygene.runtime.mixin;
+
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.apache.polygene.test.util.Assume.assumeJavaVersion;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Initial tests for interface default methods support.
+ */
+public class DefaultMethodsTest extends AbstractPolygeneTest
+{
+    @BeforeClass
+    public static void assumeJavaVersionIs8() { assumeJavaVersion( 8 ); }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.values( Hello.class );
+        module.transients( Hello.class ).withMixins( SpeakMixin.class );
+    }
+
+    @Test
+    public void givenInterfaceWithDefaultMethodWhenCallingExpectSuccess()
+    {
+        ValueBuilder<Hello> builder = valueBuilderFactory.newValueBuilder( Hello.class );
+        Hello prototype = builder.prototype();
+        Property<String> phrase = prototype.phrase();
+        phrase.set( "Hello" );
+        Hello hello = builder.newInstance();
+        assertThat( hello.speak(), equalTo( "Hello" ) );
+        assertThat( Hello.noise(), equalTo( "Good Bye" ) );
+    }
+
+    @Test
+    public void givenInterfaceWithDefaultMethodAndMixinImplementationWhenCallingExpectMixinValueReturned()
+    {
+        TransientBuilder<Hello> builder = transientBuilderFactory.newTransientBuilder( Hello.class );
+        Hello prototype = builder.prototype();
+        Property<String> phrase = prototype.phrase();
+        phrase.set( "Hello" );
+        Hello hello = builder.newInstance();
+        assertThat( hello.speak(), equalTo( "Hello, Mixin!" ) );
+        assertThat( Hello.noise(), equalTo( "Good Bye" ) );
+    }
+
+    public interface Hello
+    {
+        Property<String> phrase();
+
+        default String speak()
+        {
+            return phrase().get();
+        }
+
+        static String noise()
+        {
+            return "Good Bye";
+        }
+    }
+
+    public static abstract class SpeakMixin
+        implements Hello
+    {
+        @Override
+        public String speak()
+        {
+            return phrase().get() + ", Mixin!";
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/InitializableTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/InitializableTest.java
new file mode 100644
index 0000000..cc5e054
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/InitializableTest.java
@@ -0,0 +1,235 @@
+/*
+ *  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.polygene.runtime.mixin;
+
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.util.NotYetImplemented;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test of Initializable interface
+ */
+public class InitializableTest extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+    {
+        module.objects( TestObject.class );
+        module.transients( TestComposite.class, NoMethod.class );
+        module.values( TestComposite.class );
+        module.services( TestComposite.class );
+        module.entities( TestComposite.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Test
+    public void givenTransientWithInitializableMixinWhenInstantiatedThenInvokeInitialize()
+    {
+        TestComposite instance = transientBuilderFactory.newTransient( TestComposite.class );
+        assertThat( "mixin has been initialized", instance.ok(), equalTo( true ) );
+    }
+
+    @Test
+    public void givenValueWithInitializableMixinWhenInstantiatedThenInvokeInitialize()
+    {
+        TestComposite instance = valueBuilderFactory.newValue( TestComposite.class );
+        assertThat( "mixin has been initialized", instance.ok(), equalTo( true ) );
+    }
+
+    @Test
+    public void givenServiceWithInitializableMixinWhenInstantiatedThenInvokeInitialize()
+    {
+        TestComposite instance = serviceFinder.findService( TestComposite.class ).get();
+        assertThat( "mixin has been initialized", instance.ok(), equalTo( true ) );
+    }
+
+    @Test
+    public void givenEntityWithInitializableMixinWhenInstantiatedThenInvokeInitialize()
+    {
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            TestComposite instance = uow.newEntity( TestComposite.class );
+            assertThat( "mixin has been initialized", instance.ok(), equalTo( true ) );
+        }
+    }
+
+    @Test
+    public void givenObjectImplementingInitializableWhenInstantiatedThenInvokeInitialize()
+    {
+        TestObject instance = objectFactory.newObject( TestObject.class );
+        assertThat( "object has been initialized", instance.ok(), equalTo( true ) );
+    }
+
+    @NotYetImplemented( reason = "Mixin of types with no method are not scrutinized for Initializable implementation" )
+    @Test
+    public void givenTypeWithNoMethodsAndInitializableMixinWhenInstantiatedThenInvokeInitialize()
+    {
+        NoMethod instance = transientBuilderFactory.newTransient( NoMethod.class );
+        assertThat( "mixin has been initialized", noMethodMixinOk, equalTo( true ) );
+    }
+
+    @Mixins( TestMixin.class )
+    public interface TestComposite extends ComposedInitializable
+    {
+        boolean ok();
+    }
+
+    public abstract static class TestMixin implements TestComposite, Initializable
+    {
+        boolean ok = false;
+
+        @This
+        ComposedInitializable composedInitializable;
+
+        @This
+        PrivateInitializable privateInitializable;
+
+        @Override
+        public void initialize()
+        {
+            ok = true;
+        }
+
+        @Override
+        public boolean ok()
+        {
+            return ok && composedInitializable.composedOk() && privateInitializable.ok();
+        }
+    }
+
+    @Mixins( ComposedInitializableMixin.class )
+    public interface ComposedInitializable
+    {
+        boolean composedOk();
+    }
+
+    public static class ComposedInitializableMixin implements ComposedInitializable, Initializable
+    {
+        boolean ok = false;
+
+        @Override
+        public void initialize()
+        {
+            ok = true;
+        }
+
+        @Override
+        public boolean composedOk()
+        {
+            return ok;
+        }
+    }
+
+    @Mixins( PrivateInitializableMixin.class )
+    public interface PrivateInitializable
+    {
+        boolean ok();
+    }
+
+    public static class PrivateInitializableMixin implements PrivateInitializable, Initializable
+    {
+        @This
+        NestedInitializable nestedInitializable;
+
+        boolean ok = false;
+
+        @Override
+        public void initialize()
+        {
+            ok = true;
+        }
+
+        @Override
+        public boolean ok()
+        {
+            return ok && nestedInitializable.nestedOk();
+        }
+    }
+
+    @Mixins( NestedInitializableMixin.class )
+    public interface NestedInitializable
+    {
+        boolean nestedOk();
+    }
+
+    public static class NestedInitializableMixin implements NestedInitializable, Initializable
+    {
+        boolean ok = false;
+
+        @Override
+        public void initialize()
+        {
+            ok = true;
+        }
+
+        @Override
+        public boolean nestedOk()
+        {
+            return ok;
+        }
+    }
+
+    static boolean noMethodMixinOk;
+
+    @Before
+    public void resetNoMethodMixinStaticState()
+    {
+        noMethodMixinOk = false;
+    }
+
+    @Mixins( NoMethodMixin.class )
+    public interface NoMethod {}
+
+    public static class NoMethodMixin implements Initializable
+    {
+        @Override
+        public void initialize()
+        {
+            noMethodMixinOk = true;
+        }
+    }
+
+    public static class TestObject implements Initializable
+    {
+        boolean ok = false;
+
+        @Override
+        public void initialize()
+        {
+            ok = true;
+        }
+
+        public boolean ok()
+        {
+            return ok;
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/InvokeServiceFromModuleAssemblyTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/InvokeServiceFromModuleAssemblyTest.java
new file mode 100644
index 0000000..36d7f2a
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/InvokeServiceFromModuleAssemblyTest.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.runtime.mixin;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.mixin.NoopMixin;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.junit.Assert.fail;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class InvokeServiceFromModuleAssemblyTest
+    extends AbstractPolygeneTest
+{
+    @Mixins( NoopMixin.class )
+    public interface TestService
+        extends ServiceComposite
+    {
+        public void voidMethod();
+    }
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        try
+        {
+            module.services( TestService.class );
+            module.forMixin( TestService.class ).declareDefaults().voidMethod();
+            fail( "It is not allowed to declareDefaults on methods not returning Property." );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // expected
+        }
+    }
+
+    @Test
+    public void failingAssemblyTest()
+    {
+
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/JDKMixinTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/JDKMixinTest.java
new file mode 100644
index 0000000..fc4937a
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/JDKMixinTest.java
@@ -0,0 +1,187 @@
+/*
+ *  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.polygene.runtime.mixin;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import javax.json.Json;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.concern.GenericConcern;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Assert that JDK classes are usable as Mixins.
+ */
+public class JDKMixinTest extends AbstractPolygeneTest
+{
+    @Concerns( JDKMixinConcern.class )
+    public interface JSONSerializableMap extends Map<String, String>
+    {
+        JsonObject toJSON();
+    }
+
+    @SuppressWarnings( "serial" )
+    public static class ExtendsJDKMixin extends HashMap<String, String>
+        implements JSONSerializableMap
+    {
+        @Override
+        public JsonObject toJSON()
+        {
+            System.out.println( ">>>> Call ExtendsJDKMixin.toJSON()" );
+            JsonObjectBuilder builder = Json.createObjectBuilder();
+            entrySet().forEach( entry -> builder.add( entry.getKey(), entry.getValue() ) );
+            return builder.build();
+        }
+    }
+
+    public static abstract class ComposeWithJDKMixin
+        implements JSONSerializableMap
+    {
+        @This
+        private Map<String, String> map;
+
+        @Override
+        public JsonObject toJSON()
+        {
+            System.out.println( ">>>> Call ComposeWithJDKMixin.toJSON()" );
+            JsonObjectBuilder builder = Json.createObjectBuilder();
+            map.entrySet().forEach( entry -> builder.add( entry.getKey(), entry.getValue() ) );
+            return builder.build();
+        }
+    }
+
+    public static class JDKMixinConcern extends GenericConcern
+    {
+        @Override
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            System.out.println( ">>>> Call to JDKMixinConcern." + method.getName() );
+            CONCERN_RECORDS.add( method.getName() );
+            return next.invoke( proxy, method, args );
+        }
+    }
+
+    private static final Identity EXTENDS_IDENTITY = new StringIdentity( ExtendsJDKMixin.class.getName() );
+    private static final Identity COMPOSE_IDENTITY = new StringIdentity( ComposeWithJDKMixin.class.getName() );
+    private static final Predicate<ServiceReference<?>> EXTENDS_IDENTITY_SPEC = new ServiceIdentitySpec(
+        EXTENDS_IDENTITY );
+    private static final Predicate<ServiceReference<?>> COMPOSE_IDENTITY_SPEC = new ServiceIdentitySpec(
+        COMPOSE_IDENTITY );
+    private static final List<String> CONCERN_RECORDS = new ArrayList<String>();
+
+    @Before
+    public void beforeEachTest()
+    {
+        CONCERN_RECORDS.clear();
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( JSONSerializableMap.class )
+              .identifiedBy( EXTENDS_IDENTITY.toString() )
+              .withMixins( ExtendsJDKMixin.class )
+              .instantiateOnStartup();
+
+        module.layer().module( "compose" ).services( JSONSerializableMap.class )
+              .visibleIn( Visibility.layer )
+              .identifiedBy( COMPOSE_IDENTITY.toString() )
+              .withMixins( HashMap.class, ComposeWithJDKMixin.class )
+              .instantiateOnStartup();
+    }
+
+    @Test
+    public void testMixinExtendsJDK()
+    {
+        List<ServiceReference<JSONSerializableMap>> services = serviceFinder.findServices( JSONSerializableMap.class )
+                                                                            .filter( EXTENDS_IDENTITY_SPEC )
+                                                                            .collect( Collectors.toList() );
+
+        assertThat( services.size(), equalTo( 1 ) );
+        assertThat( services.get( 0 ).identity(), equalTo( EXTENDS_IDENTITY ) );
+
+        JSONSerializableMap extending = services.get( 0 ).get();
+        extending.put( "foo", "bar" ); // Concern trigger #1 (put)
+        JsonObject json = extending.toJSON(); // Concern trigger #2 and #3 (toJSON, entrySet)
+
+        assertThat( json.size(), equalTo( 1 ) );
+        assertThat( json.getString( "foo" ), equalTo( "bar" ) );
+
+        assertThat( CONCERN_RECORDS.size(), equalTo( 3 ) );
+    }
+
+    @Test
+    public void testComposeJDKMixin()
+    {
+        List<ServiceReference<JSONSerializableMap>> services = serviceFinder.findServices( JSONSerializableMap.class )
+                                                                            .filter( COMPOSE_IDENTITY_SPEC )
+                                                                            .collect( Collectors.toList() );
+
+        assertThat( services.size(), equalTo( 1 ) );
+        assertThat( services.get( 0 ).identity(), equalTo( COMPOSE_IDENTITY ) );
+
+        JSONSerializableMap composing = services.get( 0 ).get();
+        composing.put( "foo", "bar" ); // Concern trigger #1 (put)
+        JsonObject json = composing.toJSON(); // Concern trigger #2 and #3 (toJSON, entrySet)
+
+        assertThat( json.size(), equalTo( 1 ) );
+        assertThat( json.getString( "foo" ), equalTo( "bar" ) );
+
+        assertThat( CONCERN_RECORDS.size(), equalTo( 3 ) );
+    }
+
+    private static class ServiceIdentitySpec
+        implements Predicate<ServiceReference<?>>
+    {
+        private final Identity identity;
+
+        ServiceIdentitySpec( Identity identity )
+        {
+            this.identity = identity;
+        }
+
+        @Override
+        public boolean test( ServiceReference<?> item )
+        {
+            return item.identity().equals( identity );
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/MethodInterceptionMixinTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/MethodInterceptionMixinTest.java
new file mode 100644
index 0000000..8885e8a
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/MethodInterceptionMixinTest.java
@@ -0,0 +1,101 @@
+/*
+ *  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.polygene.runtime.mixin;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.junit.Assert.assertEquals;
+
+public class MethodInterceptionMixinTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( SomeService.class );
+    }
+
+    @Test
+    public void whenMixinCallsPublicMethodExpectInvocationStackToBeCalled()
+    {
+        ServiceReference<SomeService> service = serviceFinder.findService( SomeService.class );
+        Collection<String> result1 = service.get().result();
+        assertEquals( "Concern should have been called.", 1, result1.size() );
+        assertEquals( "Concern should have been called.", "Concern1", result1.iterator().next() );
+    }
+
+    @Concerns( { SomeConcern1.class } )
+    @Mixins( { SomeMixin.class } )
+    public interface SomeService
+        extends Some, ServiceComposite
+    {
+    }
+
+    public interface Some
+    {
+        Collection<String> doSome();
+
+        Collection<String> result();
+    }
+
+    public static abstract class SomeMixin
+        implements Some
+    {
+
+        @This
+        Some some;
+
+        public Collection<String> doSome()
+        {
+            return new ArrayList<String>();
+        }
+
+        public List<String> result()
+        {
+            return (List<String>) some.doSome();
+        }
+    }
+
+    public static abstract class SomeConcern1
+        extends ConcernOf<Some>
+        implements Some
+    {
+
+        public Collection<String> doSome()
+        {
+            Collection<String> some = next.doSome();
+            some.add( "Concern1" );
+            return some;
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/MixinPrecedenceTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/MixinPrecedenceTest.java
new file mode 100644
index 0000000..5dc94c1
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/MixinPrecedenceTest.java
@@ -0,0 +1,134 @@
+/*
+ *  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.polygene.runtime.mixin;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test mixin declaration precedence satisfiedBy
+ */
+public class MixinPrecedenceTest
+    extends AbstractPolygeneTest
+{
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( TestComposite1.class,
+                           TestComposite2.class,
+                           TestComposite3.class );
+    }
+
+    @Test
+    public void whenMultipleTypedMixinsPrecedence()
+    {
+        TestComposite1 instance = transientBuilderFactory.newTransient( TestComposite1.class );
+        assertThat( "Mixin precedence", instance.AMethod(), equalTo( "A1" ) );
+    }
+
+    @Test
+    public void whenGenericAndTypedMixinPrecedence()
+    {
+        TestComposite2 instance = transientBuilderFactory.newTransient( TestComposite2.class );
+        assertThat( "Typed mixin is chosen over generic mixin", instance.AMethod(), equalTo( "A1" ) );
+    }
+
+    @Test
+    public void whenMultipleGenericMixinsPrecedence()
+    {
+        TestComposite3 instance = transientBuilderFactory.newTransient( TestComposite3.class );
+        assertEquals( "GM1", instance.AMethod() );
+    }
+
+    @Mixins( { AMixin1.class, AMixin2.class } )
+    public static interface TestComposite1
+        extends A, TransientComposite
+    {
+    }
+
+    @Mixins( { GenericMixin1.class, AMixin1.class } )
+    public static interface TestComposite2
+        extends A, TransientComposite
+    {
+    }
+
+    @Mixins( { GenericMixin1.class, GenericMixin2.class } )
+    public static interface TestComposite3
+        extends A, TransientComposite
+    {
+    }
+
+    public interface A
+    {
+        String AMethod();
+    }
+
+    public static class AMixin1
+        implements A
+    {
+
+        public String AMethod()
+        {
+            return "A1";
+        }
+    }
+
+    public static class AMixin2
+        implements A
+    {
+
+        public String AMethod()
+        {
+            return "A2";
+        }
+    }
+
+    public static class GenericMixin1
+        implements InvocationHandler
+    {
+        public Object invoke( Object object, Method method, Object[] objects )
+            throws Throwable
+        {
+            return "GM1";
+        }
+    }
+
+    public static class GenericMixin2
+        implements InvocationHandler
+    {
+        public Object invoke( Object object, Method method, Object[] objects )
+            throws Throwable
+        {
+            return "GM2";
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/MixinsOnThisInjectionTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/MixinsOnThisInjectionTest.java
new file mode 100644
index 0000000..95c856d
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/MixinsOnThisInjectionTest.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.runtime.mixin;
+
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test of declaring Mixin in @This declared interface
+ */
+public class MixinsOnThisInjectionTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( TestCase.class );
+    }
+
+    @Test
+    public void givenCompositeWithThisInjectionAndNoMixinDeclarationWhenBindingCompositeThenUseInterfaceDeclaredMixin()
+    {
+        TestCase TestCase = transientBuilderFactory.newTransient( TestCase.class );
+        assertThat( "Composite can be instantiated", TestCase.sayHello(), equalTo( "Hello" ) );
+    }
+
+    @Mixins( TestMixin.class )
+    public interface TestCase
+        extends TransientComposite
+    {
+        String sayHello();
+    }
+
+    public abstract static class TestMixin
+        implements TestCase
+    {
+        @This
+        TestCase2 testCase2;
+
+        public String sayHello()
+        {
+            return testCase2.sayHello();
+        }
+    }
+
+    @Mixins( TestMixin2.class )
+    public interface TestCase2
+    {
+        String sayHello();
+    }
+
+    public abstract static class TestMixin2
+        implements TestCase2
+    {
+        public String sayHello()
+        {
+            return "Hello";
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/PrivateMixinTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/PrivateMixinTest.java
new file mode 100644
index 0000000..438089a
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/PrivateMixinTest.java
@@ -0,0 +1,118 @@
+/*
+ *  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.polygene.runtime.mixin;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Unit tests related to private mixins.
+ */
+public class PrivateMixinTest
+    extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( SpeakComposite.class );
+    }
+
+    /**
+     * Tests that private mixins are injected correctly.
+     */
+    @Test
+    public void privateMixinFieldAndConstructorInjection()
+    {
+        SpeakComposite test = transientBuilderFactory.newTransient( SpeakComposite.class );
+        assertThat( "Speak", test.speak(), is( equalTo( "I say it works!" ) ) );
+    }
+
+    @Mixins( SpeakMixin.class )
+    public interface Speak
+    {
+        String speak();
+    }
+
+    public static class SpeakMixin
+        implements Speak
+    {
+        private final Word word;
+        @This Punctuation punctuation;
+
+        public SpeakMixin( @This Word word )
+        {
+            this.word = word;
+        }
+
+        @Override
+        public String speak()
+        {
+            return "I say " + word.get() + punctuation.punctuate();
+        }
+    }
+
+    public interface SpeakComposite
+        extends Speak, TransientComposite
+    {
+    }
+
+    @Mixins( WordMixin.class )
+    public interface Word
+    {
+        String get();
+    }
+
+    public static class WordMixin
+        implements Word
+    {
+        @Override
+        public String get()
+        {
+            return "it works";
+        }
+    }
+
+    @Mixins( PunctuationMixin.class )
+    public interface Punctuation
+    {
+        String punctuate();
+    }
+
+    public static class PunctuationMixin
+        implements Punctuation
+    {
+        @Override
+        public String punctuate()
+        {
+            return "!";
+        }
+
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/Qi228Test.java b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/Qi228Test.java
new file mode 100644
index 0000000..e2d2b5a
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/mixin/Qi228Test.java
@@ -0,0 +1,77 @@
+/*
+ *  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.polygene.runtime.mixin;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+public class Qi228Test
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( SomeLogicService.class );
+    }
+
+    @Test
+    public void test1()
+        throws Exception
+    {
+        SomeLogic service = serviceFinder.findService( SomeLogic.class ).get();
+        try
+        {
+            service.getNumbers();
+            // Either should succeed.
+        }
+        catch( Exception e )
+        {
+            // Or fail with a decent Excpetion.
+        }
+    }
+
+    public interface SomeLogic
+    {
+        Collection<Integer> getNumbers();
+    }
+
+    public static class SomeLogicMixin
+        implements SomeLogic
+    {
+        public List<Integer> getNumbers()
+        {
+            return Collections.emptyList();
+        }
+    }
+
+    @Mixins( { SomeLogicMixin.class } )
+    public interface SomeLogicService
+        extends SomeLogic, ServiceComposite
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/objects/ObjectBuilderFactoryTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/objects/ObjectBuilderFactoryTest.java
new file mode 100644
index 0000000..f978aa0
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/objects/ObjectBuilderFactoryTest.java
@@ -0,0 +1,179 @@
+/*
+ *  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.polygene.runtime.objects;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.object.NoSuchObjectException;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.notNullValue;
+
+/**
+ * Unit tests for ObjectBuilderFactory.
+ */
+public class ObjectBuilderFactoryTest
+{
+
+    /**
+     * Tests that an object builder cannot be created for an unregistered object.
+     *
+     * @throws Exception expected
+     */
+    @Test( expected = NoSuchObjectException.class )
+    public void newBuilderForUnregisteredObject()
+        throws Exception
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+            }
+        };
+        assembler.module().newObject( AnyObject.class );
+    }
+
+    /**
+     * Tests that an object builder cannot be created for a 'null' type.
+     *
+     * @throws Exception expected
+     */
+    @Test( expected = NullPointerException.class )
+    public void newBuilderForNullType()
+        throws Exception
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+            }
+        };
+        assembler.module().newObject( null );
+    }
+
+    /**
+     * Tests that an object builder cannot be created for a 'null' type.
+     *
+     * @throws Exception expected
+     */
+    @Test( expected = NullPointerException.class )
+    public void newObjectInstanceForNullType()
+        throws Exception
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+            }
+        };
+        assembler.module().newObject( null );
+    }
+
+    /**
+     * Tests that an object can be created for an registered object class.
+     */
+    @Test
+    public void newInstanceForRegisteredObject()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.objects( AnyObject.class );
+            }
+        };
+        assembler.module().newObject( AnyObject.class );
+    }
+
+    @Test
+    public void givenManyConstructorsWhenInstantiateThenChooseCorrectConstructor()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.objects( ManyConstructorObject.class );
+            }
+        };
+
+        ManyConstructorObject object = assembler.module().newObject( ManyConstructorObject.class );
+        Assert.assertThat( "ref is not null", object.anyObject, notNullValue() );
+
+        object = assembler.module()
+            .newObject( ManyConstructorObject.class, new AnyObject() );
+
+        Assert.assertThat( "ref is not null", object.anyObject, notNullValue() );
+    }
+
+    @Test
+    public void givenClassWithInnerClassesWhenInstantiateThenInstantiateInnerClass()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.objects( OuterClass.class );
+            }
+        };
+
+        Assert.assertThat( "inner class has been injected", assembler.module()
+            .newObject( OuterClass.class )
+            .name(), equalTo( "Module 1" ) );
+    }
+
+    public static final class AnyObject
+    {
+    }
+
+    public static final class ManyConstructorObject
+    {
+        AnyObject anyObject;
+        Module module;
+
+        public ManyConstructorObject( @Uses AnyObject anyObject, @Structure Module module )
+        {
+            this.anyObject = anyObject;
+            this.module = module;
+        }
+
+        public ManyConstructorObject( @Structure Module module )
+        {
+            this.module = module;
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/objects/ObjectConcernTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/objects/ObjectConcernTest.java
new file mode 100644
index 0000000..2af7434
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/objects/ObjectConcernTest.java
@@ -0,0 +1,75 @@
+/*
+ *  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.polygene.runtime.objects;
+
+import java.lang.reflect.Method;
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.concern.GenericConcern;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+/**
+ * JAVADOC
+ */
+public class ObjectConcernTest
+{
+
+    @Test
+    public void testConcernOnObject()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.objects( TestObject.class );
+            }
+        };
+
+        TestObject object = assembler.module().newObject( TestObject.class );
+
+        object.doStuff();
+    }
+
+    @Concerns( LogConcern.class )
+    public static class TestObject
+    {
+        public void doStuff()
+        {
+        }
+    }
+
+    public static class LogConcern
+        extends GenericConcern
+    {
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            System.out.println( "Invoked " + method.getName() + " on " + proxy );
+
+            return next.invoke( proxy, method, args );
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/objects/ObjectVisibilityTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/objects/ObjectVisibilityTest.java
new file mode 100644
index 0000000..45691e8
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/objects/ObjectVisibilityTest.java
@@ -0,0 +1,900 @@
+/*
+ *  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.polygene.runtime.objects;
+
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.object.NoSuchObjectException;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.ApplicationAssemblerAdapter;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+public class ObjectVisibilityTest
+{
+
+    public static final Identity TEST_IDENTITY = new StringIdentity( "123" );
+
+    private Energy4Java polygene;
+    private Module module;
+    private UnitOfWorkFactory uowf;
+    private Application app;
+
+    @Before
+    public void setup()
+        throws Exception
+    {
+        polygene = new Energy4Java();
+
+        Assembler[][][] assemblers = new Assembler[][][]
+            {
+                { // Layer Above
+                  {
+                      new AboveAssembler()
+                  }
+                },
+                { // Layer From
+                  { // From Module
+                    new FromAssembler(),
+                  },
+                  { // Beside Module
+                    new BesideAssembler()
+                  }
+                },
+                { // Layer Below
+                  {
+                      new BelowAssembler()
+                  }
+                }
+            };
+        app = polygene.newApplication( new ApplicationAssemblerAdapter( assemblers )
+        {
+        } );
+        app.activate();
+        module = app.findModule( "From Layer", "From" );
+        uowf = module.unitOfWorkFactory();
+    }
+
+    @After
+    public void tearDown()
+        throws Exception
+    {
+        app.passivate();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromServiceWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromServiceWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromServiceWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromServiceWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromServiceWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromServiceWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.aboveModuleVisible();
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY );
+            entity.moduleApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY );
+            entity.moduleLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.moduleModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.besideApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.besideLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromEntityWhenAccessingBesideModuleVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.besideModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.belowApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromEntityWhenAccessingBelowLayerVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.belowLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromEntityWhenAccessingBelowModuleVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.belowModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromEntityWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.aboveApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromEntityWhenAccessingAboveLayerVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.aboveLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromEntityWhenAccessingAboveModuleVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.aboveModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromValueWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromValueWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromValueWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromValueWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromValueWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromValueWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.aboveModuleVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromTransientWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromTransientWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromTransientWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromTransientWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromTransientWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromTransientWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.aboveModuleVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromObjectWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromObjectWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromObjectWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromObjectWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromObjectWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchObjectException.class )
+    public void givenFromObjectWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.aboveModuleVisible();
+    }
+
+    private static class FromAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.layer().setName( "From Layer" );
+            module.setName( "From" );
+            module.services( FromService.class );
+            module.entities( FromEntity.class );
+            module.transients( FromTransient.class );
+            module.values( FromValue.class );
+            module.objects( FromObject.class );
+
+            module.objects( ModuleApplicationVisible.class ).visibleIn( Visibility.application );
+            module.objects( ModuleLayerVisible.class ).visibleIn( Visibility.layer );
+            module.objects( ModuleModuleVisible.class ).visibleIn( Visibility.module );
+
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    private static class BelowAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.layer().setName( "Below Layer" );
+            module.setName( "Below" );
+            module.objects( BelowApplicationVisible.class ).visibleIn( Visibility.application );
+            module.objects( BelowLayerVisible.class ).visibleIn( Visibility.layer );
+            module.objects( BelowModuleVisible.class ).visibleIn( Visibility.module );
+
+            new EntityTestAssembler().visibleIn( Visibility.application ).assemble( module );
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    private static class AboveAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.layer().setName( "Above Layer" );
+            module.setName( "Above" );
+            module.objects( AboveApplicationVisible.class ).visibleIn( Visibility.application );
+            module.objects( AboveLayerVisible.class ).visibleIn( Visibility.layer );
+            module.objects( AboveModuleVisible.class ).visibleIn( Visibility.module );
+
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    private static class BesideAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.setName( "Beside" );
+            module.objects( BesideApplicationVisible.class ).visibleIn( Visibility.application );
+            module.objects( BesideLayerVisible.class ).visibleIn( Visibility.layer );
+            module.objects( BesideModuleVisible.class ).visibleIn( Visibility.module );
+
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    @Mixins( Mixin.class )
+    public interface From
+    {
+        void moduleApplicationVisible();
+
+        void moduleLayerVisible();
+
+        void moduleModuleVisible();
+
+        void besideApplicationVisible();
+
+        void besideLayerVisible();
+
+        void besideModuleVisible();
+
+        void belowApplicationVisible();
+
+        void belowLayerVisible();
+
+        void belowModuleVisible();
+
+        void aboveApplicationVisible();
+
+        void aboveLayerVisible();
+
+        void aboveModuleVisible();
+    }
+
+    public interface FromValue extends From, ValueComposite
+    {
+    }
+
+    public interface FromEntity extends From, EntityComposite
+    {
+    }
+
+    public interface FromService extends From, ServiceComposite
+    {
+    }
+
+    public interface FromTransient extends From, TransientComposite
+    {
+    }
+
+    public static class FromObject extends Mixin
+    {
+    }
+
+    public abstract static class Mixin
+        implements From
+    {
+        @Structure
+        private Module module;
+
+        @Override
+        public void moduleApplicationVisible()
+        {
+            module.newObject( ModuleApplicationVisible.class );
+        }
+
+        @Override
+        public void moduleLayerVisible()
+        {
+            module.newObject( ModuleLayerVisible.class );
+        }
+
+        @Override
+        public void moduleModuleVisible()
+        {
+            module.newObject( ModuleModuleVisible.class );
+        }
+
+        @Override
+        public void besideApplicationVisible()
+        {
+            module.newObject( BesideApplicationVisible.class );
+        }
+
+        @Override
+        public void besideLayerVisible()
+        {
+            module.newObject( BesideLayerVisible.class );
+        }
+
+        @Override
+        public void besideModuleVisible()
+        {
+            module.newObject( BesideModuleVisible.class );
+        }
+
+        @Override
+        public void belowApplicationVisible()
+        {
+            module.newObject( BelowApplicationVisible.class );
+        }
+
+        @Override
+        public void belowLayerVisible()
+        {
+            module.newObject( BelowLayerVisible.class );
+        }
+
+        @Override
+        public void belowModuleVisible()
+        {
+            module.newObject( BelowModuleVisible.class );
+        }
+
+        @Override
+        public void aboveApplicationVisible()
+        {
+            module.newObject( AboveApplicationVisible.class );
+        }
+
+        @Override
+        public void aboveLayerVisible()
+        {
+            module.newObject( AboveLayerVisible.class );
+        }
+
+        @Override
+        public void aboveModuleVisible()
+        {
+            module.newObject( AboveModuleVisible.class );
+        }
+    }
+
+    public static class ModuleApplicationVisible
+    {
+    }
+
+    public static class ModuleLayerVisible
+    {
+    }
+
+    public static class ModuleModuleVisible
+    {
+    }
+
+    public static class BesideApplicationVisible
+    {
+    }
+
+    public static class BesideLayerVisible
+    {
+    }
+
+    public static class BesideModuleVisible
+    {
+    }
+
+    public static class BelowApplicationVisible
+    {
+    }
+
+    public static class BelowLayerVisible
+    {
+    }
+
+    public static class BelowModuleVisible
+    {
+    }
+
+    public static class AboveApplicationVisible
+    {
+    }
+
+    public static class AboveLayerVisible
+    {
+    }
+
+    public static class AboveModuleVisible
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/objects/OuterClass.java b/core/runtime/src/test/java/org/apache/polygene/runtime/objects/OuterClass.java
new file mode 100644
index 0000000..7d43fba
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/objects/OuterClass.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.runtime.objects;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.structure.Module;
+
+/**
+ * TODO
+ */
+public class OuterClass
+{
+    @Uses
+    InnerClass instance;
+
+    @Structure
+    Module module;
+
+    public String name()
+    {
+        return instance.name();
+    }
+
+    class InnerClass
+    {
+        public String name()
+        {
+            return module.name();
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/property/ImmutablePropertyTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/property/ImmutablePropertyTest.java
new file mode 100644
index 0000000..c3518dc
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/property/ImmutablePropertyTest.java
@@ -0,0 +1,135 @@
+/*
+ *  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.polygene.runtime.property;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Immutable;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public final class ImmutablePropertyTest
+    extends AbstractPolygeneTest
+{
+    private static final String KUALA_LUMPUR = "Kuala Lumpur";
+
+    @Test
+    public final void testCreationalWithStateFor()
+    {
+        Location location = createLocation( KUALA_LUMPUR );
+        testNamePropertyGet( location, KUALA_LUMPUR );
+    }
+
+    private Location createLocation( String locationName )
+    {
+        TransientBuilder<Location> locationBuilder = transientBuilderFactory.newTransientBuilder( Location.class );
+        Location locState = locationBuilder.prototypeFor( Location.class );
+        locState.name().set( locationName );
+        return locationBuilder.newInstance();
+    }
+
+    private void testNamePropertyGet( Location location, String locationName )
+    {
+        assertNotNull( location );
+        assertEquals( locationName, location.name().get() );
+    }
+
+    @Test
+    public final void testCreationWithStateOfComposite()
+    {
+        TransientBuilder<Location> locationBuilder = transientBuilderFactory.newTransientBuilder( Location.class );
+        Location locState = locationBuilder.prototype();
+        locState.name().set( KUALA_LUMPUR );
+        Location location = locationBuilder.newInstance();
+
+        testNamePropertyGet( location, KUALA_LUMPUR );
+    }
+
+    @Test( expected = IllegalStateException.class )
+    public final void testSetter()
+    {
+        Location location = createLocation( KUALA_LUMPUR );
+
+        // Must fail!
+        Property<String> stringProperty = location.name();
+        stringProperty.set( "abc" );
+    }
+
+    @Test
+    public final void testImmutableEntityProperty()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            EntityBuilder<LocationEntity> builder = uow.newEntityBuilder( LocationEntity.class );
+            builder.instance().name().set( "Rickard" );
+            Location location = builder.newInstance();
+
+            try
+            {
+                location.name().set( "Niclas" );
+                Assert.fail( "Should be immutable" );
+            }
+            catch( IllegalStateException e )
+            {
+                // Ok
+            }
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    public final void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( LocationComposite.class );
+        module.entities( LocationEntity.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    interface LocationComposite
+        extends Location, TransientComposite
+    {
+    }
+
+    interface LocationEntity
+        extends Location, EntityComposite
+    {
+    }
+
+    interface Location
+    {
+        @Immutable
+        Property<String> name();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/property/PropertyEqualityTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/property/PropertyEqualityTest.java
new file mode 100644
index 0000000..fbccfa2
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/property/PropertyEqualityTest.java
@@ -0,0 +1,439 @@
+/*
+ *  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.polygene.runtime.property;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZonedDateTime;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static java.time.ZoneOffset.UTC;
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Assert that Property equals/hashcode methods combine PropertyDescriptor and State.
+ */
+public class PropertyEqualityTest
+    extends AbstractPolygeneTest
+{
+
+    //
+    // --------------------------------------:: Types under test ::-----------------------------------------------------
+    //
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.values( PrimitivesValue.class, Some.class, AnotherSome.class, Other.class );
+    }
+
+    private enum AnEnum
+    {
+
+        BAZAR, CATHEDRAL
+    }
+
+    public interface PrimitivesValue
+    {
+
+        Property<Character> characterProperty();
+
+        Property<String> stringProperty();
+
+        Property<Boolean> booleanProperty();
+
+        Property<Integer> integerProperty();
+
+        Property<Long> longProperty();
+
+        Property<Float> floatProperty();
+
+        Property<Double> doubleProperty();
+
+        Property<Short> shortProperty();
+
+        Property<Byte> byteProperty();
+
+        Property<AnEnum> enumProperty();
+    }
+
+    public interface Some
+        extends PrimitivesValue
+    {
+
+        @Optional
+        Property<Some> selfProperty();
+
+        Property<BigInteger> bigIntegerProperty();
+
+        Property<BigDecimal> bigDecimalProperty();
+
+        Property<Instant> instantProperty();
+
+        Property<ZonedDateTime> dateTimeProperty();
+
+        Property<LocalDate> localDateProperty();
+
+        Property<LocalDateTime> localDateTimeProperty();
+    }
+
+    public interface AnotherSome
+        extends Some
+    {
+    }
+
+    public interface Other
+    {
+
+        Property<Character> characterProperty();
+    }
+
+    //
+    // ------------------------------:: PropertyDescriptor equality tests ::--------------------------------------------
+    //
+    @Test
+    public void givenValuesOfTheSameTypeWhenTestingPropertyDescriptorEqualityExpectEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        ValueDescriptor someDescriptor = polygene.api().valueDescriptorFor( some );
+        PropertyDescriptor someCharPropDesc = someDescriptor.state().findPropertyModelByName( "characterProperty" );
+
+        Some other = buildSomeValue( valueBuilderFactory );
+        ValueDescriptor otherDescriptor = polygene.api().valueDescriptorFor( other );
+        PropertyDescriptor otherCharPropDesc = otherDescriptor.state().findPropertyModelByName( "characterProperty" );
+
+        assertThat( "PropertyDescriptors equal",
+                    someCharPropDesc,
+                    equalTo( otherCharPropDesc ) );
+        assertThat( "PropertyDescriptors hashcode equal",
+                    someCharPropDesc.hashCode(),
+                    equalTo( otherCharPropDesc.hashCode() ) );
+    }
+
+    @Test
+    public void givenValuesOfCommonTypesWhenTestingPropertyDescriptorEqualityExpectEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        ValueDescriptor someDescriptor = polygene.api().valueDescriptorFor( some );
+        PropertyDescriptor someCharPropDesc = someDescriptor.state().findPropertyModelByName( "characterProperty" );
+
+        PrimitivesValue primitive = buildPrimitivesValue( valueBuilderFactory );
+        ValueDescriptor primitiveDescriptor = polygene.api().valueDescriptorFor( primitive );
+        PropertyDescriptor primitiveCharPropDesc = primitiveDescriptor.state()
+            .findPropertyModelByName( "characterProperty" );
+
+        assertThat( "PropertyDescriptors equal",
+                    someCharPropDesc,
+                    equalTo( primitiveCharPropDesc ) );
+        assertThat( "PropertyDescriptors hashcode equal",
+                    someCharPropDesc.hashCode(),
+                    equalTo( primitiveCharPropDesc.hashCode() ) );
+    }
+
+    @Test
+    public void givenValuesOfDifferentTypesWhenTestingPropertyDescriptorEqualityExpectNotEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        ValueDescriptor someDescriptor = polygene.api().valueDescriptorFor( some );
+        PropertyDescriptor someCharPropDesc = someDescriptor.state().findPropertyModelByName( "characterProperty" );
+
+        Other other = buildOtherValue( valueBuilderFactory );
+        ValueDescriptor otherDescriptor = polygene.api().valueDescriptorFor( other );
+        PropertyDescriptor otherCharPropDesc = otherDescriptor.state().findPropertyModelByName( "characterProperty" );
+
+        assertThat( "PropertyDescriptors not equal",
+                    someCharPropDesc,
+                    not( equalTo( otherCharPropDesc ) ) );
+        assertThat( "PropertyDescriptors hashcode not equal",
+                    someCharPropDesc.hashCode(),
+                    not( equalTo( otherCharPropDesc.hashCode() ) ) );
+    }
+
+    //
+    // --------------------------------:: Property State equality tests ::----------------------------------------------
+    //
+    @Test
+    public void givenValuesOfDifferentTypesAndSameStateWhenTestingPropertyStateEqualityExpectEquals()
+    {
+        PrimitivesValue primitives = buildPrimitivesValue( valueBuilderFactory );
+        Some some = buildSomeValue( valueBuilderFactory );
+        Some some2 = buildSomeValue( valueBuilderFactory );
+        Other other = buildOtherValue( valueBuilderFactory );
+        assertThat( "Property state equal",
+                    'q',
+                    allOf( equalTo( primitives.characterProperty().get() ),
+                           equalTo( some.characterProperty().get() ),
+                           equalTo( some2.characterProperty().get() ),
+                           equalTo( other.characterProperty().get() ) ) );
+        assertThat( "Property state hashcode equal",
+                    new Character( 'q' ).hashCode(),
+                    allOf( equalTo( primitives.characterProperty().get().hashCode() ),
+                           equalTo( some.characterProperty().get().hashCode() ),
+                           equalTo( some2.characterProperty().get().hashCode() ),
+                           equalTo( other.characterProperty().get().hashCode() ) ) );
+    }
+
+    //
+    // -----------------------------------:: Property equality tests ::-------------------------------------------------
+    //
+    @Test
+    public void givenValuesOfTheSameTypeAndSameStateWhenTestingPropertyEqualityExpectEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        Some some2 = buildSomeValue( valueBuilderFactory );
+        assertThat( "Property equals",
+                    some.characterProperty(),
+                    equalTo( some2.characterProperty() ) );
+        assertThat( "Property hashcode equals",
+                    some.characterProperty().hashCode(),
+                    equalTo( some2.characterProperty().hashCode() ) );
+    }
+
+    @Test
+    public void givenValuesOfTheSameTypeWithDifferentStateWhenTestingPropertyEqualityExpectNotEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        Some some2 = buildSomeValueWithDifferentState( valueBuilderFactory );
+        assertThat( "Property not equals",
+                    some.characterProperty(),
+                    not( equalTo( some2.characterProperty() ) ) );
+        assertThat( "Property hashcode not equals",
+                    some.characterProperty().hashCode(),
+                    not( equalTo( some2.characterProperty().hashCode() ) ) );
+    }
+
+    @Test
+    public void givenValuesOfCommonTypesAndSameStateWhenTestingPropertyEqualityExpectEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        PrimitivesValue primitive = buildPrimitivesValue( valueBuilderFactory );
+        assertThat( "Property equal",
+                    some.characterProperty(),
+                    equalTo( primitive.characterProperty() ) );
+    }
+
+    @Test
+    public void givenValuesOfCommonTypesWithDifferentStateWhenTestingPropertyEqualityExpectNotEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        PrimitivesValue primitive = buildPrimitivesValueWithDifferentState( valueBuilderFactory );
+        assertThat( "Property not equal",
+                    some.characterProperty(),
+                    not( equalTo( primitive.characterProperty() ) ) );
+    }
+
+    @Test
+    public void givenValuesOfDifferentTypesAndSameStateWhenTestingPropertyEqualityExpectNotEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        Other other = buildOtherValue( valueBuilderFactory );
+        assertThat( "Property not equal",
+                    some.characterProperty(),
+                    not( equalTo( other.characterProperty() ) ) );
+    }
+
+    @Test
+    public void givenValuesOfDifferentTypesWithDifferentStateWhenTestingPropertyEqualityExpectNotEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        Other other = buildOtherValue( valueBuilderFactory );
+        assertThat( "Property not equal",
+                    some.characterProperty(),
+                    not( equalTo( other.characterProperty() ) ) );
+    }
+
+    //
+    // -----------------------------------:: Values factory methods ::--------------------------------------------------
+    //
+    public static PrimitivesValue buildPrimitivesValue( ValueBuilderFactory vbf )
+    {
+        PrimitivesValue primitive;
+        {
+            ValueBuilder<PrimitivesValue> builder = vbf.newValueBuilder( PrimitivesValue.class );
+            builder.prototype().characterProperty().set( 'q' );
+            builder.prototype().stringProperty().set( "foo" );
+            builder.prototype().booleanProperty().set( true );
+            builder.prototype().integerProperty().set( 42 );
+            builder.prototype().longProperty().set( 42L );
+            builder.prototype().floatProperty().set( 42.23F );
+            builder.prototype().doubleProperty().set( 42.23D );
+            builder.prototype().shortProperty().set( (short) 42 );
+            builder.prototype().byteProperty().set( (byte) 42 );
+            builder.prototype().enumProperty().set( AnEnum.BAZAR );
+            primitive = builder.newInstance();
+        }
+        return primitive;
+    }
+
+    private static PrimitivesValue buildPrimitivesValueWithDifferentState( ValueBuilderFactory vbf )
+    {
+        PrimitivesValue primitive;
+        {
+            ValueBuilder<PrimitivesValue> builder = vbf.newValueBuilder( PrimitivesValue.class );
+            builder.prototype().characterProperty().set( 'i' );
+            builder.prototype().stringProperty().set( "bar" );
+            builder.prototype().booleanProperty().set( false );
+            builder.prototype().integerProperty().set( 23 );
+            builder.prototype().longProperty().set( 23L );
+            builder.prototype().floatProperty().set( 23.42F );
+            builder.prototype().doubleProperty().set( 23.42D );
+            builder.prototype().shortProperty().set( (short) 23 );
+            builder.prototype().byteProperty().set( (byte) 23 );
+            builder.prototype().enumProperty().set( AnEnum.CATHEDRAL );
+            primitive = builder.newInstance();
+        }
+        return primitive;
+    }
+
+    public static Some buildSomeValue( ValueBuilderFactory vbf )
+    {
+        Some some;
+        {
+            ZonedDateTime refDate = ZonedDateTime.of( 2020, 3, 4, 13, 24, 35, 0, UTC );
+
+            ValueBuilder<Some> builder = vbf.newValueBuilder( Some.class );
+            builder.prototype().characterProperty().set( 'q' );
+            builder.prototype().stringProperty().set( "foo" );
+            builder.prototype().booleanProperty().set( true );
+            builder.prototype().integerProperty().set( 42 );
+            builder.prototype().longProperty().set( 42L );
+            builder.prototype().floatProperty().set( 42.23F );
+            builder.prototype().doubleProperty().set( 42.23D );
+            builder.prototype().shortProperty().set( (short) 42 );
+            builder.prototype().byteProperty().set( (byte) 42 );
+            builder.prototype().enumProperty().set( AnEnum.BAZAR );
+            builder.prototype().bigIntegerProperty().set( new BigInteger( "42" ) );
+            builder.prototype().bigDecimalProperty().set( new BigDecimal( "42.23" ) );
+            builder.prototype().instantProperty().set( refDate.toInstant() );
+            builder.prototype().dateTimeProperty().set( refDate );
+            builder.prototype().localDateProperty().set( LocalDate.of( 2020, 3, 4 ) );
+            builder.prototype().localDateTimeProperty().set( LocalDateTime.of( 2020, 3, 4, 13, 23, 0 ) );
+            some = builder.newInstance();
+        }
+        return some;
+    }
+
+    public static Some buildSomeValueWithDifferentState( ValueBuilderFactory vbf )
+    {
+        Some some;
+        {
+            ZonedDateTime refDate = ZonedDateTime.of( 2030, 2, 8, 9, 9, 9, 0, UTC );
+            ValueBuilder<Some> builder = vbf.newValueBuilder( Some.class );
+            builder.prototype().characterProperty().set( 'i' );
+            builder.prototype().stringProperty().set( "bar" );
+            builder.prototype().booleanProperty().set( false );
+            builder.prototype().integerProperty().set( 23 );
+            builder.prototype().longProperty().set( 23L );
+            builder.prototype().floatProperty().set( 23.42F );
+            builder.prototype().doubleProperty().set( 23.42D );
+            builder.prototype().shortProperty().set( (short) 23 );
+            builder.prototype().byteProperty().set( (byte) 23 );
+            builder.prototype().enumProperty().set( AnEnum.CATHEDRAL );
+            builder.prototype().bigIntegerProperty().set( new BigInteger( "23" ) );
+            builder.prototype().bigDecimalProperty().set( new BigDecimal( "23.42" ) );
+            builder.prototype().instantProperty().set( refDate.toInstant() );
+            builder.prototype().dateTimeProperty().set( refDate );
+            builder.prototype().localDateProperty().set( LocalDate.of( 2030, 2, 8 ) );
+            builder.prototype().localDateTimeProperty().set( LocalDateTime.of( 2030, 2, 8, 9, 9, 9 ) );
+            some = builder.newInstance();
+        }
+        return some;
+    }
+
+    public static AnotherSome buildAnotherSomeValue( ValueBuilderFactory vbf )
+    {
+        AnotherSome anotherSome;
+        {
+            ZonedDateTime refDate = ZonedDateTime.of( 2020, 3, 4, 13, 24, 35, 0, UTC );
+            ValueBuilder<AnotherSome> builder = vbf.newValueBuilder( AnotherSome.class );
+            builder.prototype().characterProperty().set( 'q' );
+            builder.prototype().stringProperty().set( "foo" );
+            builder.prototype().booleanProperty().set( true );
+            builder.prototype().integerProperty().set( 42 );
+            builder.prototype().longProperty().set( 42L );
+            builder.prototype().floatProperty().set( 42.23F );
+            builder.prototype().doubleProperty().set( 42.23D );
+            builder.prototype().shortProperty().set( (short) 42 );
+            builder.prototype().byteProperty().set( (byte) 42 );
+            builder.prototype().enumProperty().set( AnEnum.BAZAR );
+            builder.prototype().bigIntegerProperty().set( new BigInteger( "42" ) );
+            builder.prototype().bigDecimalProperty().set( new BigDecimal( "42.23" ) );
+            builder.prototype().instantProperty().set( refDate.toInstant() );
+            builder.prototype().dateTimeProperty().set( refDate );
+            builder.prototype().localDateProperty().set( refDate.toLocalDate() );
+            builder.prototype().localDateTimeProperty().set( LocalDateTime.of( 2020, 3, 4, 13, 23, 0 ) );
+            anotherSome = builder.newInstance();
+        }
+        return anotherSome;
+    }
+
+    public static AnotherSome buildAnotherSomeValueWithDifferentState( ValueBuilderFactory vbf )
+    {
+        AnotherSome anotherSome;
+        {
+            ValueBuilder<AnotherSome> builder = vbf.newValueBuilder( AnotherSome.class );
+            builder.prototype().characterProperty().set( 'i' );
+            builder.prototype().stringProperty().set( "bar" );
+            builder.prototype().booleanProperty().set( false );
+            builder.prototype().integerProperty().set( 23 );
+            builder.prototype().longProperty().set( 23L );
+            builder.prototype().floatProperty().set( 23.42F );
+            builder.prototype().doubleProperty().set( 23.42D );
+            builder.prototype().shortProperty().set( (short) 23 );
+            builder.prototype().byteProperty().set( (byte) 23 );
+            builder.prototype().enumProperty().set( AnEnum.CATHEDRAL );
+            builder.prototype().bigIntegerProperty().set( new BigInteger( "23" ) );
+            builder.prototype().bigDecimalProperty().set( new BigDecimal( "23.42" ) );
+            ZonedDateTime refDate = ZonedDateTime.of( 2030, 2, 8, 9, 9, 9, 0, UTC );
+            builder.prototype().instantProperty().set( refDate.toInstant() );
+            builder.prototype().dateTimeProperty().set( refDate );
+            builder.prototype().localDateProperty().set( LocalDate.of( 2030, 2, 8 ) );
+            builder.prototype().localDateTimeProperty().set( LocalDateTime.of( 2030, 2, 8, 9, 9, 9 ) );
+            anotherSome = builder.newInstance();
+        }
+        return anotherSome;
+    }
+
+    public static Other buildOtherValue( ValueBuilderFactory vbf )
+    {
+        Other other;
+        {
+            ValueBuilder<Other> builder = vbf.newValueBuilder( Other.class );
+            builder.prototype().characterProperty().set( 'q' );
+            other = builder.newInstance();
+        }
+        return other;
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/property/PropertyStringArrayTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/property/PropertyStringArrayTest.java
new file mode 100644
index 0000000..179e2eb
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/property/PropertyStringArrayTest.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.runtime.property;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Tests for string arrays as properties (QI-132)
+ */
+public class PropertyStringArrayTest
+    extends AbstractPolygeneTest
+{
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( TestComposite.class );
+    }
+
+    @Test
+    public void testProperty()
+    {
+        TestComposite instance;
+        {
+            TransientBuilder<TestComposite> builder = transientBuilderFactory.newTransientBuilder( TestComposite.class );
+            builder.prototype().array().set( new String[]{ "Foo", "Bar" } );
+            instance = builder.newInstance();
+        }
+
+        assertThat( "property has correct value", instance.array().get()[ 0 ], equalTo( "Foo" ) );
+
+        instance.array().set( new String[]{ "Hello", "World" } );
+
+        assertThat( "property has correct value", instance.array().get()[ 0 ], equalTo( "Hello" ) );
+    }
+
+    public interface TestComposite
+        extends TransientComposite
+    {
+        Property<String[]> array();
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/property/PropertyTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/property/PropertyTest.java
new file mode 100644
index 0000000..530cd71
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/property/PropertyTest.java
@@ -0,0 +1,195 @@
+/*
+ *  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.polygene.runtime.property;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import javax.swing.Icon;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.concern.GenericConcern;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyMixin;
+import org.apache.polygene.api.property.PropertyWrapper;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for properties
+ */
+//@Ignore(
+//    "This is an incorrect satisfiedBy case. The Property fragment support is not well defined at the moment, so until" +
+//    "more work is finalized on exactly what should be supported, this is ignored not to be forgotten." )
+public class PropertyTest
+    extends AbstractPolygeneTest
+{
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( Company.class ).withConcerns( LogConcern.class );
+        module.forMixin( Nameable.class )
+            .setMetaInfo( new DisplayInfo( "Name", "Name of something", "The name" ) )  // Add UI info
+            .setMetaInfo(
+                new RdfInfo( "label", "http://www.w3.org/1999/02/22-rdf-syntax-ns#" ) )  // Add persistence info
+            .declareDefaults()
+            .name()  // Select accessor
+            .set( "Hello World" ); // Set default value
+    }
+
+    @Test
+    public void testProperty()
+    {
+        Company company;
+        {
+            TransientBuilder<Company> builder = transientBuilderFactory.newTransientBuilder( Company.class );
+            builder.prototype().name().set( "JayWay" );
+            company = builder.newInstance();
+        }
+
+        company.name().set( "Jayway" );
+        assertEquals( "Jayway", company.name().get() );
+        System.out.println( "Name is:" + company.name().get() );
+    }
+
+    public interface Company
+        extends Nameable, StandardComposite, TransientComposite
+    {
+    }
+
+    public interface StandardComposite
+    {
+    }
+
+    public interface Nameable
+    {
+        Property<String> name();
+    }
+
+    @AppliesTo( PropertyMixin.PropertyFilter.class )
+    public static class LogConcern
+        extends GenericConcern
+    {
+        @Override
+        public Object invoke( Object o, final Method method, Object[] objects )
+            throws Throwable
+        {
+            final Property<Object> property = (Property<Object>) next.invoke( o, method, objects );
+
+            return new PropertyWrapper( property )
+            {
+                @Override
+                public Object get()
+                {
+                    Object result = next.get();
+
+                    System.out.println( "Property " + method.getName() + " accessed with value " + result );
+
+                    return result;
+                }
+
+                @Override
+                public void set( Object newValue )
+                    throws IllegalArgumentException, IllegalStateException
+                {
+                    Object current = next.get();
+
+                    next.set( newValue );
+
+                    System.out
+                        .println( "Property " + method.getName() + " changed from " + current + " to " + newValue );
+                }
+            };
+        }
+    }
+
+    public static class DisplayInfo
+        implements Serializable
+    {
+        private String name;
+        private String description;
+        private String toolTip;
+        private Icon icon;
+
+        public DisplayInfo( String name, String description, String toolTip )
+        {
+            this.name = name;
+            this.description = description;
+            this.toolTip = toolTip;
+        }
+
+        public DisplayInfo( String name, String description, String toolTip, Icon icon )
+        {
+            this.name = name;
+            this.description = description;
+            this.toolTip = toolTip;
+            this.icon = icon;
+        }
+
+        public String getName()
+        {
+            return name;
+        }
+
+        public String getDescription()
+        {
+            return description;
+        }
+
+        public String getToolTip()
+        {
+            return toolTip;
+        }
+
+        public Icon getIcon()
+        {
+            return icon;
+        }
+    }
+
+    public static class RdfInfo
+        implements Serializable
+    {
+        private String predicate;
+        private String namespace;
+
+        public RdfInfo( String predicate, String namespace )
+        {
+            this.predicate = predicate;
+            this.namespace = namespace;
+        }
+
+        public String getPredicate()
+        {
+            return predicate;
+        }
+
+        public String getNamespace()
+        {
+            return namespace;
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/property/ValueNestedBuilderTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/property/ValueNestedBuilderTest.java
new file mode 100644
index 0000000..026cb13
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/property/ValueNestedBuilderTest.java
@@ -0,0 +1,130 @@
+/*
+ *  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.polygene.runtime.property;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+public class ValueNestedBuilderTest
+    extends AbstractPolygeneTest
+{
+    private interface InnerValue
+        extends ValueComposite
+    {
+        Property<List<String>> listProp();
+
+        Property<Map<String, String>> mapProp();
+    }
+
+    private interface InnerDefaultedValue
+        extends ValueComposite
+    {
+
+        @UseDefaults
+        Property<List<String>> listPropDefault();
+
+        @UseDefaults
+        Property<Map<String, String>> mapPropDefault();
+    }
+
+    private interface OuterValue
+        extends ValueComposite
+    {
+
+        Property<List<InnerValue>> innerListProp();
+    }
+
+    private interface OuterDefaultedValue
+        extends ValueComposite
+    {
+
+        @UseDefaults
+        Property<List<InnerDefaultedValue>> innerListPropDefault();
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.values( InnerValue.class, InnerDefaultedValue.class, OuterValue.class, OuterDefaultedValue.class );
+    }
+
+    @Test
+    public void testInner()
+    {
+        ValueBuilder<InnerValue> innerBuilder = valueBuilderFactory.newValueBuilder( InnerValue.class );
+        InnerValue inner = innerBuilder.prototype();
+        inner.listProp().set( new ArrayList<String>() );
+        inner.mapProp().set( new HashMap<String, String>() );
+        inner = innerBuilder.newInstance();
+        // If we reach this point, value creation went well
+    }
+
+    @Test
+    public void testOuter()
+    {
+        ValueBuilder<InnerValue> innerBuilder = valueBuilderFactory.newValueBuilder( InnerValue.class );
+        InnerValue inner = innerBuilder.prototype();
+        inner.listProp().set( new ArrayList<String>() );
+        inner.mapProp().set( new HashMap<String, String>() );
+        inner = innerBuilder.newInstance();
+        ValueBuilder<OuterValue> outerBuilder = valueBuilderFactory.newValueBuilder( OuterValue.class );
+        OuterValue outer = outerBuilder.prototype();
+        List<InnerValue> inners = new ArrayList<InnerValue>();
+        inners.add( inner );
+        outer.innerListProp().set( inners );
+        outer = outerBuilder.newInstance();
+        System.out.println( outer.toString() );
+        // If we reach this point, value creation went well
+    }
+
+    @Test
+    public void testDefaultedInner()
+    {
+        ValueBuilder<InnerDefaultedValue> innerBuilder = valueBuilderFactory.newValueBuilder( InnerDefaultedValue.class );
+        InnerDefaultedValue inner = innerBuilder.newInstance();
+        // If we reach this point, value creation went well
+    }
+
+    @Test
+    public void testDefaultedOuter()
+    {
+        ValueBuilder<InnerDefaultedValue> innerBuilder = valueBuilderFactory.newValueBuilder( InnerDefaultedValue.class );
+        InnerDefaultedValue inner = innerBuilder.newInstance();
+        ValueBuilder<OuterDefaultedValue> outerBuilder = valueBuilderFactory.newValueBuilder( OuterDefaultedValue.class );
+        OuterDefaultedValue outer = outerBuilder.prototype();
+        List<InnerDefaultedValue> inners = new ArrayList<InnerDefaultedValue>();
+        inners.add( inner );
+        outer.innerListPropDefault().set( inners );
+        outer = outerBuilder.newInstance();
+        System.out.println( outer.toString() );
+        // If we reach this point, value creation went well
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/IterableQuerySourceTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/IterableQuerySourceTest.java
new file mode 100644
index 0000000..2df68f1
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/IterableQuerySourceTest.java
@@ -0,0 +1,526 @@
+/*
+ *  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.polygene.runtime.query;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.query.QueryExpressions;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ClassScanner;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.runtime.query.model.City;
+import org.apache.polygene.runtime.query.model.Describable;
+import org.apache.polygene.runtime.query.model.Domain;
+import org.apache.polygene.runtime.query.model.Female;
+import org.apache.polygene.runtime.query.model.Male;
+import org.apache.polygene.runtime.query.model.Nameable;
+import org.apache.polygene.runtime.query.model.Person;
+import org.apache.polygene.runtime.query.model.Pet;
+import org.apache.polygene.runtime.query.model.entities.DomainEntity;
+import org.apache.polygene.runtime.query.model.entities.PetEntity;
+import org.apache.polygene.runtime.query.model.values.ContactValue;
+import org.apache.polygene.runtime.query.model.values.ContactsValue;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.apache.polygene.api.query.QueryExpressions.eq;
+import static org.apache.polygene.api.query.QueryExpressions.ge;
+import static org.apache.polygene.api.query.QueryExpressions.gt;
+import static org.apache.polygene.api.query.QueryExpressions.isNotNull;
+import static org.apache.polygene.api.query.QueryExpressions.isNull;
+import static org.apache.polygene.api.query.QueryExpressions.lt;
+import static org.apache.polygene.api.query.QueryExpressions.matches;
+import static org.apache.polygene.api.query.QueryExpressions.not;
+import static org.apache.polygene.api.query.QueryExpressions.or;
+import static org.apache.polygene.api.query.QueryExpressions.orderBy;
+import static org.apache.polygene.api.query.QueryExpressions.property;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+
+public class IterableQuerySourceTest
+{
+
+    private UnitOfWork uow;
+    private QueryBuilderFactory qbf;
+
+    @Before
+    public void setUp()
+        throws UnitOfWorkCompletionException, ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                ClassScanner.findClasses( DomainEntity.class ).forEach( module::entities );
+
+                module.values( ContactsValue.class, ContactValue.class );
+                new EntityTestAssembler().assemble( module );
+                new DefaultUnitOfWorkAssembler().assemble( module );
+            }
+        };
+        uow = assembler.module().unitOfWorkFactory().newUnitOfWork();
+        Network.populate( uow, assembler.module() );
+        uow.complete();
+        uow = assembler.module().unitOfWorkFactory().newUnitOfWork();
+        Network.refresh( uow );
+        qbf = assembler.module();
+    }
+
+    @After
+    public void tearDown()
+    {
+        if( uow != null )
+        {
+            uow.discard();
+        }
+    }
+
+    private static void verifyUnorderedResults( final Iterable<? extends Nameable> results,
+                                                final String... names
+    )
+    {
+        final List<String> expected = new ArrayList<String>( Arrays.asList( names ) );
+
+        for( Nameable entity : results )
+        {
+            String name = entity.name().get();
+            assertTrue( name + " returned but not expected", expected.remove( name ) );
+        }
+
+        for( String notReturned : expected )
+        {
+            fail( notReturned + " was expected but not returned" );
+        }
+    }
+
+    private static void verifyOrderedResults( final Iterable<? extends Nameable> results,
+                                              final String... names
+    )
+    {
+        final List<String> expected = new ArrayList<String>( Arrays.asList( names ) );
+
+        for( Nameable entity : results )
+        {
+            String firstExpected = null;
+            if( expected.size() > 0 )
+            {
+                firstExpected = expected.get( 0 );
+            }
+            if( firstExpected == null )
+            {
+                fail( entity.name().get() + " returned but not expected" );
+            }
+            else if( !firstExpected.equals( entity.name().get() ) )
+            {
+                fail( entity.name().get() + " is not in the expected order" );
+            }
+            expected.remove( 0 );
+        }
+        for( String notReturned : expected )
+        {
+            fail( notReturned + " was expected but not returned" );
+        }
+    }
+
+    @Test
+    public void givenQueryWhenExecutedReturnAll()
+    {
+        final QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
+        final Query<Person> query = qb.newQuery( Network.persons() );
+        System.out.println( query );
+        verifyUnorderedResults( query, "Joe Doe", "Ann Doe", "Jack Doe", "Vivian Smith" );
+    }
+
+    @Test
+    public void givenEqQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Domain> qb = qbf.newQueryBuilder( Domain.class );
+        final Nameable nameable = templateFor( Nameable.class );
+        final Query<Domain> query = qb.where(
+            eq( nameable.name(), "Gaming" )
+        ).newQuery( Network.domains() );
+        verifyUnorderedResults( query, "Gaming" );
+    }
+
+    @Test
+    public void givenMixinTypeQueryWhenExecutedReturnAll()
+    {
+        QueryBuilder<Nameable> qb = qbf.newQueryBuilder( Nameable.class );
+        Query<Nameable> query = qb.newQuery( Network.nameables() );
+        verifyUnorderedResults(
+            query,
+            "Joe Doe", "Ann Doe", "Jack Doe", "Vivian Smith",
+            "Penang", "Kuala Lumpur",
+            "Cooking", "Gaming", "Programming", "Cars"
+        );
+    }
+
+    @Test
+    public void givenEqQueryOnValueWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
+        Person personTemplate = templateFor( Person.class );
+        City placeOfBirth = personTemplate.placeOfBirth().get();
+        Query<Person> query = qb.where(
+            eq( placeOfBirth.name(), "Kuala Lumpur" )
+        ).newQuery( Network.persons() );
+        verifyUnorderedResults( query, "Joe Doe", "Ann Doe", "Vivian Smith" );
+    }
+
+    @Test
+    public void givenEqQueryOnAssociationAndPropertyWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = qb.where(
+            eq( person.mother().get().placeOfBirth().get().name(), "Kuala Lumpur" )
+        ).newQuery( Network.persons() );
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void givenEqQueryOnAssociationWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        City kl = uow.get( City.class, new StringIdentity( "kualalumpur" ));
+        Query<Person> query = qb.where(
+            eq( person.mother().get().placeOfBirth(), kl )
+        ).newQuery( Network.persons() );
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void givenGeQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = qb.where(
+            ge( person.yearOfBirth(), 1973 )
+        ).newQuery( Network.persons() );
+        verifyUnorderedResults( query, "Joe Doe", "Ann Doe", "Vivian Smith" );
+    }
+
+    @Test
+    public void givenAndQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Nameable> qb = qbf.newQueryBuilder( Nameable.class );
+        Person person = templateFor( Person.class );
+        Query<Nameable> query = qb.where(
+            ge( person.yearOfBirth(), 1900 ).and( eq( person.placeOfBirth().get().name(), "Penang" ) )
+        ).newQuery( Network.nameables() );
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void givenMultipleAndQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Nameable> qb = qbf.newQueryBuilder( Nameable.class );
+        Person person = templateFor( Person.class );
+        Query<Nameable> query = qb.where(
+            ge( person.yearOfBirth(), 1900 ).
+                and( lt( person.yearOfBirth(), 2000 ) ).
+                and( eq( person.placeOfBirth().get().name(), "Penang" ) )
+        ).newQuery( Network.nameables() );
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void givenOrQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = qb.where(
+            or(
+                eq( person.yearOfBirth(), 1970 ),
+                eq( person.yearOfBirth(), 1975 )
+            )
+        ).newQuery( Network.persons() );
+        verifyUnorderedResults( query, "Jack Doe", "Ann Doe" );
+    }
+
+    @Test
+    public void givenMultipleOrQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = qb.where(
+            or(
+                eq( person.yearOfBirth(), 1970 ),
+                eq( person.yearOfBirth(), 1975 ),
+                eq( person.yearOfBirth(), 1990 )
+            )
+        ).newQuery( Network.persons() );
+        verifyUnorderedResults( query, "Jack Doe", "Ann Doe", "Joe Doe" );
+    }
+
+    @Test
+    public void givenOrQueryOnFemalesWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Female> qb = qbf.newQueryBuilder( Female.class );
+        Person person = templateFor( Person.class );
+        Query<Female> query = qb.where(
+            or(
+                eq( person.yearOfBirth(), 1970 ),
+                eq( person.yearOfBirth(), 1975 )
+            )
+        ).newQuery( Network.females() );
+        verifyUnorderedResults( query, "Ann Doe" );
+    }
+
+    @Test
+    public void givenNotQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = qb.where(
+            not(
+                eq( person.yearOfBirth(), 1975 )
+            )
+        ).newQuery( Network.persons() );
+        verifyUnorderedResults( query, "Jack Doe", "Joe Doe", "Vivian Smith" );
+    }
+
+    @Test
+    public void givenIsNotNullQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = qb.where(
+            isNotNull( person.email() )
+        ).newQuery( Network.persons() );
+        verifyUnorderedResults( query, "Joe Doe", "Vivian Smith" );
+    }
+
+    @Test
+    public void givenIsNullQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = qb.where(
+            isNull( person.email() )
+        ).newQuery( Network.persons() );
+        verifyUnorderedResults( query, "Ann Doe", "Jack Doe" );
+    }
+
+    @Test
+    public void givenIsNotNullOnMixinTypeWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
+        Male person = templateFor( Male.class );
+        Query<Person> query = qb.where(
+            isNotNull( person.wife() )
+        ).newQuery( Network.persons() );
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void givenIsNullOnMixinTypeWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Male> qb = qbf.newQueryBuilder( Male.class );
+        Male person = templateFor( Male.class );
+        Query<Male> query = qb.where(
+            isNull( person.wife() )
+        ).newQuery( Network.males() );
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void givenIsNullOnAssociationWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
+        Male person = templateFor( Male.class );
+        Query<Person> query = qb.where(
+            isNull( person.wife() )
+        ).newQuery( Network.persons() );
+        verifyUnorderedResults( query, "Joe Doe", "Ann Doe", "Vivian Smith" );
+    }
+
+    @Test
+    public void givenOrderAndMaxResultsQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Nameable> qb = qbf.newQueryBuilder( Nameable.class );
+        // should return only 2 entities
+        Nameable nameable = templateFor( Nameable.class );
+        Query<Nameable> query = qb.newQuery( Network.nameables() );
+        query.orderBy( orderBy( nameable.name() ) );
+        query.maxResults( 2 );
+        verifyOrderedResults(
+            query,
+            "Ann Doe", "Cars"
+        );
+    }
+
+    @Test
+    public void givenOrderAndFirstAndMaxResultsQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Nameable> qb = qbf.newQueryBuilder( Nameable.class );
+        // should return only 3 entities starting with forth one
+        Nameable nameable = templateFor( Nameable.class );
+        Query<Nameable> query = qb.newQuery( Network.nameables() );
+        query.orderBy( orderBy( nameable.name() ) );
+        query.firstResult( 3 );
+        query.maxResults( 3 );
+        verifyOrderedResults(
+            query,
+            "Gaming", "Jack Doe", "Joe Doe"
+        );
+    }
+
+    @Test
+    public void givenOrderByOnMixinTypeQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Nameable> qb = qbf.newQueryBuilder( Nameable.class );
+        // should return all Nameable entities sorted by name
+        Nameable nameable = templateFor( Nameable.class );
+        Query<Nameable> query = qb.newQuery( Network.nameables() );
+        query.orderBy( orderBy( nameable.name() ) );
+        verifyOrderedResults(
+            query,
+            "Ann Doe", "Cars", "Cooking", "Gaming", "Jack Doe", "Joe Doe", "Kuala Lumpur", "Penang", "Programming", "Vivian Smith"
+        );
+    }
+
+    @Test
+    public void givenGtAndOrderByQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Nameable> qb = qbf.newQueryBuilder( Nameable.class );
+        // should return all Nameable entities with a name > "D" sorted by name
+        Nameable nameable = templateFor( Nameable.class );
+        Query<Nameable> query = qb.where(
+            gt( nameable.name(), "D" )
+        ).newQuery( Network.nameables() );
+        query.orderBy( orderBy( nameable.name() ) );
+        verifyOrderedResults(
+            query,
+            "Gaming", "Jack Doe", "Joe Doe", "Kuala Lumpur", "Penang", "Programming", "Vivian Smith"
+        );
+    }
+
+    @Test
+    public void givenGtAndOrderByDescendingQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
+        // should return all Persons born after 1973 (Ann and Joe Doe) sorted descending by name
+        Person person = templateFor( Person.class );
+        Query<Person> query = qb.where(
+            gt( person.yearOfBirth(), 1973 )
+        ).newQuery( Network.persons() );
+        query.orderBy( orderBy( person.name(), OrderBy.Order.DESCENDING ) );
+        verifyOrderedResults( query, "Vivian Smith", "Joe Doe", "Ann Doe" );
+    }
+
+    @Test
+    public void givenOrderByMultipleQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
+        // should return all Persons sorted by name of the city they were born, and then by year they were born
+        Person person = templateFor( Person.class );
+        Query<Person> query = qb.newQuery( Network.persons() );
+        query.orderBy( orderBy( person.placeOfBirth().get().name() ),
+                       orderBy( person.yearOfBirth() ) );
+        verifyOrderedResults( query, "Ann Doe", "Joe Doe", "Vivian Smith", "Jack Doe" );
+    }
+
+    @Test
+    public void givenMatchesQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Nameable> qb = qbf.newQueryBuilder( Nameable.class );
+        Nameable nameable = templateFor( Nameable.class );
+        // should return Jack and Joe Doe
+        Query<Nameable> query = qb.where(
+            matches( nameable.name(), "J.*Doe" )
+        ).newQuery( Network.nameables() );
+        verifyUnorderedResults(
+            query,
+            "Jack Doe", "Joe Doe"
+        );
+    }
+
+    // TODO solve ManyAssociation filtering for iterables
+    // @Test
+    public void givenOneOfQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Domain interests = person.interests().get( 0 );
+        Query<Person> query = qb.where( eq( interests.name(), "Cars" ) ).newQuery( Network.persons() );
+        verifyOrderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void givenManyAssociationContainsQueryWhenExecutedThenReturnCorrect()
+    {
+        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Domain value = Network.domains().iterator().next();
+        Query<Person> query = qb.where( QueryExpressions.contains( person.interests(), value ) )
+            .newQuery( Network.persons() );
+        for( Person person1 : query )
+        {
+            System.out.println( person1.name() );
+        }
+        verifyOrderedResults( query, "Joe Doe", "Vivian Smith" );
+    }
+
+    @Test
+    public void givenEntitiesWithInternalStateWhenQueriedThenReturnCorrect()
+    {
+        QueryBuilder<PetEntity> qb = qbf.newQueryBuilder( PetEntity.class );
+        Pet.PetState pet = templateFor( Pet.PetState.class );
+        Nameable petOwner = templateFor( Nameable.class, pet.owner() );
+        Query<PetEntity> query = qb.where( eq( petOwner.name(), "Jack Doe" ) ).newQuery( Network.pets() );
+        verifyOrderedResults( query, "Rex" );
+    }
+
+    @Test
+    public void givenEntitiesWithFieldPropertyByNameWhenQueriedThenReturnCorrect()
+    {
+        QueryBuilder<PetEntity> qb = qbf.newQueryBuilder( PetEntity.class );
+        Query<PetEntity> query = qb.where( eq( property( Describable.Mixin.class, "description" ), "Rex is a great dog" ) )
+            .newQuery( Network.pets() );
+        verifyOrderedResults( query, "Rex" );
+    }
+
+    @Test
+    public void givenEntitiesWithFieldPropertyWhenQueriedThenReturnCorrect()
+    {
+        QueryBuilder<PetEntity> qb = qbf.newQueryBuilder( PetEntity.class );
+        Query<PetEntity> query = qb.where( eq( templateFor( Describable.Mixin.class ).description, "Rex is a great dog" ) )
+            .newQuery( Network.pets() );
+        verifyOrderedResults( query, "Rex" );
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/Network.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/Network.java
new file mode 100644
index 0000000..8930654
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/Network.java
@@ -0,0 +1,243 @@
+/*
+ *  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.polygene.runtime.query;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.runtime.query.model.City;
+import org.apache.polygene.runtime.query.model.Domain;
+import org.apache.polygene.runtime.query.model.Female;
+import org.apache.polygene.runtime.query.model.Male;
+import org.apache.polygene.runtime.query.model.Nameable;
+import org.apache.polygene.runtime.query.model.Person;
+import org.apache.polygene.runtime.query.model.entities.FemaleEntity;
+import org.apache.polygene.runtime.query.model.entities.MaleEntity;
+import org.apache.polygene.runtime.query.model.entities.PetEntity;
+import org.apache.polygene.runtime.query.model.values.ContactValue;
+import org.apache.polygene.runtime.query.model.values.ContactsValue;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+class Network
+{
+    public static final Identity KUALALUMPUR = new StringIdentity( "kualalumpur" );
+    public static final Identity PENANG = new StringIdentity( "penang" );
+    private static List<Domain> domains;
+    private static List<Person> persons;
+    private static List<Male> males;
+    private static List<Female> females;
+    private static List<PetEntity> pets;
+    private static List<Nameable> nameables;
+
+    static void populate( final UnitOfWork uow, ValueBuilderFactory vbf )
+        throws UnitOfWorkCompletionException
+    {
+        domains = new ArrayList<>();
+        persons = new ArrayList<>();
+        males = new ArrayList<>();
+        females = new ArrayList<>();
+        pets = new ArrayList<>();
+        nameables = new ArrayList<>();
+
+        Domain gaming = uow.newEntity( Domain.class );
+        setName( gaming, "Gaming" );
+        gaming.description().set( "Gaming domain" );
+
+        Domain programming = uow.newEntity( Domain.class );
+        setName( programming, "Programming" );
+        programming.description().set( "Programing domain" );
+
+        Domain cooking = uow.newEntity( Domain.class );
+        setName( cooking, "Cooking" );
+        cooking.description().set( "Cooking domain" );
+
+        Domain cars = uow.newEntity( Domain.class );
+        setName( cars, "Cars" );
+        cars.description().set( "Cars" );
+
+        City kualaLumpur = uow.newEntity( City.class, KUALALUMPUR);
+        setName( kualaLumpur, "Kuala Lumpur" );
+        kualaLumpur.country().set( "Malaysia" );
+        kualaLumpur.county().set( "Some Jaya" );
+
+        City penang = uow.newEntity( City.class, PENANG);
+        setName( penang, "Penang" );
+        penang.country().set( "Malaysia" );
+        penang.county().set( "Some Other Jaya" );
+
+        Female vivianSmith = uow.newEntity( FemaleEntity.class );
+        setName( vivianSmith, "Vivian Smith" );
+        vivianSmith.placeOfBirth().set( kualaLumpur );
+        vivianSmith.yearOfBirth().set( 1992 );
+        vivianSmith.interests().add( 0, gaming );
+        vivianSmith.interests().add( 0, programming );
+        vivianSmith.email().set( "viv@smith.edu" );
+        List<String> vivianTags = new ArrayList<>();
+        vivianTags.add( "Awesome" );
+        vivianTags.add( "Pretty" );
+        vivianTags.add( "Cool" );
+        vivianSmith.tags().set( vivianTags );
+
+        Female annDoe = uow.newEntity( FemaleEntity.class );
+        setName( annDoe, "Ann Doe" );
+        annDoe.placeOfBirth().set( kualaLumpur );
+        annDoe.yearOfBirth().set( 1975 );
+        annDoe.interests().add( 0, cooking );
+        List<String> annTags = new ArrayList<>();
+        annTags.add( "Conservative" );
+        annTags.add( "Pretty" );
+        annDoe.tags().set( annTags );
+
+        Male joeDoe = uow.newEntity( MaleEntity.class );
+        setName( joeDoe, "Joe Doe" );
+        joeDoe.placeOfBirth().set( kualaLumpur );
+        joeDoe.yearOfBirth().set( 1990 );
+        joeDoe.mother().set( annDoe );
+        joeDoe.pastGirlFriends().add( 0, annDoe );
+        joeDoe.interests().add( 0, programming );
+        joeDoe.interests().add( 0, gaming );
+        joeDoe.email().set( "joe@thedoes.net" );
+        List<String> joeTags = new ArrayList<>();
+        joeTags.add( "Cool" );
+        joeTags.add( "Hunk" );
+        joeTags.add( "Awesome" );
+        joeDoe.tags().set( joeTags );
+
+        Male jackDoe = uow.newEntity( MaleEntity.class );
+        setName( jackDoe, "Jack Doe" );
+        jackDoe.placeOfBirth().set( penang );
+        jackDoe.yearOfBirth().set( 1970 );
+        jackDoe.interests().add( 0, cars );
+        jackDoe.wife().set( annDoe );
+        List<String> jackTags = new ArrayList<String>();
+        jackTags.add( "Conservative" );
+        jackTags.add( "Awesome" );
+        jackDoe.tags().set( jackTags );
+
+        ValueBuilder<ContactsValue> builder = vbf.newValueBuilder( ContactsValue.class );
+        ValueBuilder<ContactValue> contactBuilder = vbf.newValueBuilder( ContactValue.class );
+        contactBuilder.prototype().email().set( "jackdoe@someplace.com" );
+        contactBuilder.prototype().phone().set( "555-1234" );
+        builder.prototype().contacts().get().add( contactBuilder.newInstance() );
+        jackDoe.contacts().set( builder.newInstance() );
+
+        annDoe.husband().set( jackDoe );
+
+        PetEntity rex = uow.newEntity( PetEntity.class );
+        setName( rex, "Rex" );
+        rex.changeOwner( jackDoe );
+        rex.updateDescription( "Rex is a great dog" );
+
+        PetEntity kitty = uow.newEntity( PetEntity.class );
+        setName( kitty, "Kitty" );
+        kitty.changeOwner( annDoe );
+
+        domains.add( gaming );
+        domains.add( programming );
+        domains.add( cooking );
+        domains.add( cars );
+
+        persons.add( annDoe );
+        persons.add( joeDoe );
+        persons.add( jackDoe );
+        persons.add( vivianSmith );
+
+        females.add( annDoe );
+        females.add( vivianSmith );
+
+        males.add( joeDoe );
+        males.add( jackDoe );
+
+        pets.add( rex );
+        pets.add( kitty );
+
+        nameables.add( gaming );
+        nameables.add( programming );
+        nameables.add( cooking );
+        nameables.add( cars );
+        nameables.add( kualaLumpur );
+        nameables.add( penang );
+        nameables.add( annDoe );
+        nameables.add( joeDoe );
+        nameables.add( jackDoe );
+        nameables.add( vivianSmith );
+    }
+
+    static void refresh( UnitOfWork uow )
+    {
+        refresh( uow, domains );
+        refresh( uow, persons );
+        refresh( uow, males );
+        refresh( uow, females );
+        refresh( uow, pets );
+        refresh( uow, nameables );
+    }
+
+    private static <T> void refresh( UnitOfWork uow, List<T> list )
+    {
+        for( int i = 0; i < list.size(); i++ )
+        {
+            T entity = list.get( i );
+            list.set( i, uow.get( entity ) );
+        }
+    }
+
+    static Iterable<Domain> domains()
+    {
+        return domains;
+    }
+
+    static Iterable<Person> persons()
+    {
+        return persons;
+    }
+
+    static Iterable<Nameable> nameables()
+    {
+        return nameables;
+    }
+
+    static Iterable<Male> males()
+    {
+        return males;
+    }
+
+    static Iterable<Female> females()
+    {
+        return females;
+    }
+
+    static Iterable<PetEntity> pets()
+    {
+        return pets;
+    }
+
+    private static void setName( Nameable nameable, String name )
+    {
+        nameable.name().set( name );
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/NonQueryableTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/NonQueryableTest.java
new file mode 100644
index 0000000..8cae196
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/NonQueryableTest.java
@@ -0,0 +1,95 @@
+/*
+ *  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.polygene.runtime.query;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.apache.polygene.api.query.QueryExpressions.eq;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+
+public class NonQueryableTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+    }
+
+    @Test
+    public void whenQuerableIsFalseOnPropertyThenExpectException()
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            QueryBuilder<Abc> builder = queryBuilderFactory.newQueryBuilder( Abc.class );
+            Abc proto = templateFor( Abc.class );
+            builder.where( eq( proto.isValid(), Boolean.TRUE ) );
+            Assert.fail( "Exception was expected." );
+        }
+        catch( QueryException e )
+        {
+            // expected!!
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    @Test
+    public void testQueryIterable()
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            queryBuilderFactory.newQueryBuilder( Abc2.class );
+            Assert.fail( "Exception was expected." );
+        }
+        catch( QueryException e )
+        {
+            // expected!!
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    static interface Abc
+    {
+        @Queryable( false )
+        Property<Boolean> isValid();
+    }
+
+    @Queryable( false )
+    public interface Abc2
+    {
+        Property<Boolean> isValid();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/QueryBuilderFactoryImplTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/QueryBuilderFactoryImplTest.java
new file mode 100644
index 0000000..3549165
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/QueryBuilderFactoryImplTest.java
@@ -0,0 +1,167 @@
+/*
+ *  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.polygene.runtime.query;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.apache.polygene.api.query.QueryExpressions.and;
+import static org.apache.polygene.api.query.QueryExpressions.ge;
+import static org.apache.polygene.api.query.QueryExpressions.lt;
+import static org.apache.polygene.api.query.QueryExpressions.orderBy;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+
+/**
+ * JAVADOC
+ */
+public class QueryBuilderFactoryImplTest
+    extends AbstractPolygeneTest
+{
+    private List<TestComposite> composites;
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( TestComposite.class );
+    }
+
+    @Before
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        composites = new ArrayList<>();
+        composites.add( newInstance( "A", 6 ) );
+        composites.add( newInstance( "B", 2 ) );
+        composites.add( newInstance( "C", 3 ) );
+        composites.add( newInstance( "C", 4 ) );
+        composites.add( newInstance( "E", 5 ) );
+        composites.add( newInstance( "A", 1 ) );
+    }
+
+    @Test
+    public void givenPlainQueryWhenFindEntityExpectFirstEntityReturned()
+    {
+        Query<TestComposite> query = queryBuilderFactory.newQueryBuilder( TestComposite.class ).newQuery( composites );
+        assertEquals( "A", query.find().a().get() );
+        assertEquals( 6, query.count() );
+    }
+
+    @Test
+    public void givenPlainQueryWhenOrderByFirstPropertyExpectOrderedResult()
+    {
+        Query<TestComposite> query = queryBuilderFactory.newQueryBuilder( TestComposite.class ).newQuery( composites );
+        TestComposite template = templateFor( TestComposite.class );
+        query.orderBy( orderBy( template.a() ) );
+        verifyOrder( query, "612345" );
+    }
+
+    @Test
+    public void givenPlainQueryWhenOrderBySecondPropertyExpectOrderedResult()
+    {
+        Query<TestComposite> query = queryBuilderFactory.newQueryBuilder( TestComposite.class ).newQuery( composites );
+        TestComposite template = templateFor( TestComposite.class );
+        query.orderBy( orderBy( template.b() ) );
+        verifyOrder( query, "123456" );
+    }
+
+    @Test
+    public void givenPlainQueryWhenOrderByTwoPropertiesExpectOrderedResult()
+    {
+        Query<TestComposite> query = queryBuilderFactory.newQueryBuilder( TestComposite.class ).newQuery( composites );
+        TestComposite template = templateFor( TestComposite.class );
+        query.orderBy( orderBy( template.a() ), orderBy( template.b() ) );
+        verifyOrder( query, "162345" );
+    }
+
+    @Test
+    public void givenPlainQueryWhenMaxedResultExpectLimitedResult()
+    {
+        Query<TestComposite> query = queryBuilderFactory.newQueryBuilder( TestComposite.class ).newQuery( composites );
+        query.maxResults( 5 );
+        verifyOrder( query, "62345" );
+    }
+
+    @Test
+    public void givenPlainQueryWhenFirstResultIsBeyondFirstElementExpectLimitedResult()
+    {
+        Query<TestComposite> query = queryBuilderFactory.newQueryBuilder( TestComposite.class ).newQuery( composites );
+        query.firstResult( 2 );
+        verifyOrder( query, "3451" );
+    }
+
+    @Test
+    public void givenWhereQueryWhenWhereClauseLimitsToRangeExpectLimitedResult()
+    {
+        final QueryBuilder<TestComposite> qb = queryBuilderFactory.newQueryBuilder( TestComposite.class );
+        TestComposite template = templateFor( TestComposite.class );
+        Query<TestComposite> query = qb.where(
+            and(
+                ge( template.b(), 3 ),
+                lt( template.b(), 5 )
+            )
+        ).newQuery( composites );
+        verifyOrder( query, "34" );
+    }
+
+    private void verifyOrder( Query<TestComposite> query, String expected )
+    {
+        String actual = "";
+        for( TestComposite testComposite : query )
+        {
+            actual = actual + testComposite.b().get();
+        }
+
+        assertThat( "Query is correct", actual, equalTo( expected ) );
+        assertThat( "Count is correct", query.count(), equalTo( (long) expected.length() ) );
+    }
+
+    private TestComposite newInstance( String a, int b )
+    {
+        TransientBuilder<TestComposite> builder =
+            transientBuilderFactory.newTransientBuilder( TestComposite.class );
+        TestComposite instance = builder.prototype();
+        instance.a().set( a );
+        instance.b().set( b );
+        return builder.newInstance();
+    }
+
+    public interface TestComposite
+        extends TransientComposite
+    {
+        Property<String> a();
+
+        Property<Integer> b();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Alive.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Alive.java
new file mode 100644
index 0000000..e1bb431
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Alive.java
@@ -0,0 +1,24 @@
+/*
+ *  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.polygene.runtime.query.model;
+
+public interface Alive
+{
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/City.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/City.java
new file mode 100644
index 0000000..d9b568c
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/City.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.runtime.query.model;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+
+public interface City
+    extends Nameable
+{
+    @Optional
+    Property<String> country();
+
+    @Optional
+    Property<String> county();
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Describable.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Describable.java
new file mode 100644
index 0000000..a4c4b5e
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Describable.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.runtime.query.model;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * TODO
+ */
+@Mixins( Describable.Mixin.class )
+public interface Describable
+{
+    String getDescription();
+
+    void updateDescription( String newDescription );
+
+    class Mixin
+        implements Describable
+    {
+        @State
+        @UseDefaults
+        public Property<String> description;
+
+        @Override
+        public String getDescription()
+        {
+            return description.get();
+        }
+
+        @Override
+        public void updateDescription( String newDescription )
+        {
+            description.set( newDescription );
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Domain.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Domain.java
new file mode 100644
index 0000000..93ad92d
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Domain.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.runtime.query.model;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+
+public interface Domain
+    extends Nameable
+{
+    @Optional
+    Property<String> description();
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Female.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Female.java
new file mode 100644
index 0000000..1aca746
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Female.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.runtime.query.model;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Optional;
+
+public interface Female
+    extends Person
+{
+    @Optional
+    Association<Male> husband();
+
+    @Optional
+    ManyAssociation<Male> pastBoyFriends();
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Male.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Male.java
new file mode 100644
index 0000000..b1afc60
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Male.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.runtime.query.model;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Optional;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+public interface Male
+    extends Person
+{
+    @Optional
+    Association<Female> wife();
+
+    @Optional
+    ManyAssociation<Female> pastGirlFriends();
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Nameable.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Nameable.java
new file mode 100644
index 0000000..32b6f9a
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Nameable.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.runtime.query.model;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+
+public interface Nameable
+{
+    @Optional
+    Property<String> name();
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Person.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Person.java
new file mode 100644
index 0000000..8c4228e
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Person.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.runtime.query.model;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Map;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.runtime.query.model.values.ContactsValue;
+
+public interface Person
+    extends Nameable, Alive
+{
+    @Optional
+    Association<City> placeOfBirth();
+
+    @Optional
+    Property<Integer> yearOfBirth();
+
+    @Optional
+    Association<Female> mother();
+
+    @Optional
+    Association<Male> father();
+
+    @Optional
+    ManyAssociation<Domain> interests();
+
+    @Optional
+    Property<String> email();
+
+    @Optional
+    Property<Map<LocalDate, String>> datesToRemember();
+
+    @Optional
+    Property<List<String>> tags();
+
+    @Optional
+    Property<ContactsValue> contacts();
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Pet.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Pet.java
new file mode 100644
index 0000000..117ce01
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/Pet.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.runtime.query.model;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+
+/**
+ * Test traversal over internal interfaces.
+ */
+@Mixins( Pet.PetMixin.class )
+public interface Pet
+{
+    void changeOwner( Person owner );
+
+    interface PetState
+    {
+        @Optional
+        Association<Person> owner();
+    }
+
+    class PetMixin
+        implements Pet
+    {
+        @This
+        PetState state;
+
+        public void changeOwner( Person owner )
+        {
+            state.owner().set( owner );
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/CityEntity.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/CityEntity.java
new file mode 100644
index 0000000..bb45a98
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/CityEntity.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.runtime.query.model.entities;
+
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.runtime.query.model.City;
+
+public interface CityEntity
+    extends City, EntityComposite
+{
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/DomainEntity.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/DomainEntity.java
new file mode 100644
index 0000000..4b18b53
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/DomainEntity.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.runtime.query.model.entities;
+
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.runtime.query.model.Domain;
+
+public interface DomainEntity
+    extends Domain, EntityComposite
+{
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/FemaleEntity.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/FemaleEntity.java
new file mode 100644
index 0000000..481817d
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/FemaleEntity.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.runtime.query.model.entities;
+
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.runtime.query.model.Female;
+
+public interface FemaleEntity
+    extends Female, EntityComposite
+{
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/MaleEntity.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/MaleEntity.java
new file mode 100644
index 0000000..4f33830
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/MaleEntity.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.runtime.query.model.entities;
+
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.runtime.query.model.Male;
+
+public interface MaleEntity
+    extends Male, EntityComposite
+{
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/PersonEntity.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/PersonEntity.java
new file mode 100644
index 0000000..cca70cd
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/PersonEntity.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.runtime.query.model.entities;
+
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.runtime.query.model.Person;
+
+public interface PersonEntity
+    extends Person, EntityComposite
+{
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/PetEntity.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/PetEntity.java
new file mode 100644
index 0000000..7c1928a
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/entities/PetEntity.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.runtime.query.model.entities;
+
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.runtime.query.model.Describable;
+import org.apache.polygene.runtime.query.model.Nameable;
+import org.apache.polygene.runtime.query.model.Pet;
+
+/**
+ * JAVADOC
+ */
+public interface PetEntity
+    extends Pet, Nameable, Describable, EntityComposite
+{
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/values/ContactValue.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/values/ContactValue.java
new file mode 100644
index 0000000..3098082
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/values/ContactValue.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.runtime.query.model.values;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * JAVADOC
+ */
+public interface ContactValue
+    extends ValueComposite
+{
+    Property<String> email();
+
+    Property<String> phone();
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/values/ContactsValue.java b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/values/ContactsValue.java
new file mode 100644
index 0000000..c6001d6
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/query/model/values/ContactsValue.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.runtime.query.model.values;
+
+import java.util.List;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * JAVADOC
+ */
+public interface ContactsValue
+    extends ValueComposite
+{
+    @UseDefaults
+    Property<List<ContactValue>> contacts();
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/service/ActivatableServiceTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/service/ActivatableServiceTest.java
new file mode 100644
index 0000000..60ce6fd
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/service/ActivatableServiceTest.java
@@ -0,0 +1,100 @@
+/*
+ *  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.polygene.runtime.service;
+
+import org.junit.Test;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test of activatable services
+ */
+public class ActivatableServiceTest
+{
+    @Service
+    ServiceReference<ActivatableComposite> service;
+
+    public static boolean isActive;
+
+    @Test
+    public void testActivatable()
+        throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.objects( ActivatableServiceTest.class );
+                module.services( ActivatableComposite.class ).withActivators( TestActivator.class).instantiateOnStartup();
+            }
+        };
+
+        assertTrue( isActive );
+
+        assembly.module().injectTo( this );
+
+        assertTrue( isActive );
+
+        service.get();
+
+        assertTrue( isActive );
+
+        assembly.application().passivate();
+
+        assertFalse( isActive );
+    }
+
+    public static interface ActivatableComposite
+        extends ServiceComposite
+    {
+    }
+
+    public static class TestActivator
+            extends org.apache.polygene.api.activation.ActivatorAdapter<Object>
+    {
+
+        @Override
+        public void afterActivation( Object activated )
+        {
+            isActive = true;
+        }
+
+        @Override
+        public void afterPassivation( Object passivated )
+                throws Exception
+        {
+            if ( !isActive ) {
+                throw new Exception( "Not active!" );
+            }
+
+            isActive = false;
+        }
+
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/service/AvailableServiceTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/service/AvailableServiceTest.java
new file mode 100644
index 0000000..8efa667
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/service/AvailableServiceTest.java
@@ -0,0 +1,191 @@
+/*
+ *  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.polygene.runtime.service;
+
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.configuration.ConfigurationComposite;
+import org.apache.polygene.api.configuration.Enabled;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.Availability;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.service.qualifier.Available;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.assertThat;
+
+/**
+ * JAVADOC
+ */
+public class AvailableServiceTest
+{
+    @Test
+    public void givenAvailableServiceWhenCheckServiceReferenceThenReturnTrue()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.services( TestServiceComposite1.class );
+                new DefaultUnitOfWorkAssembler().assemble( module );
+            }
+        };
+
+        ServiceReference<TestServiceComposite1> serviceRef = assembler.module()
+            .findService( TestServiceComposite1.class );
+
+        assertThat( "service is available", serviceRef.isAvailable(), equalTo( true ) );
+    }
+
+    @Test
+    public void givenEnablableServiceWhenCheckAvailableThenReturnEnabledStatus()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.services( TestServiceComposite2.class );
+                module.entities( TestServiceConfiguration.class );
+
+                new EntityTestAssembler().assemble( module );
+                new DefaultUnitOfWorkAssembler().assemble( module );
+            }
+        };
+
+        ServiceReference<TestServiceComposite2> serviceRef = assembler.module()
+            .findService( TestServiceComposite2.class );
+
+        assertThat( "service is unavailable", serviceRef.isAvailable(), equalTo( false ) );
+
+        serviceRef.get().get().enabled().set( true );
+        serviceRef.get().save();
+
+        assertThat( "service is available", serviceRef.isAvailable(), equalTo( true ) );
+    }
+
+    @Test
+    public void givenEnablableServiceWhenInjectWithAvailableQualifierThenInjectCorrectly()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.objects( TestObject.class );
+                module.services( TestServiceComposite2.class );
+                module.entities( TestServiceConfiguration.class );
+
+                new EntityTestAssembler().assemble( module );
+                new DefaultUnitOfWorkAssembler().assemble( module );
+            }
+        };
+
+        TestObject object = assembler.module().newObject( TestObject.class );
+
+        assertThat( "service is unavailable", object.getService(), nullValue() );
+
+        ServiceReference<TestServiceComposite2> serviceRef = assembler.module()
+            .findService( TestServiceComposite2.class );
+        serviceRef.get().get().enabled().set( true );
+        serviceRef.get().save();
+
+        object = assembler.module().newObject( TestObject.class );
+        assertThat( "service is available", object.getService(), notNullValue() );
+    }
+
+    // This service has to be asked for availability
+    @Mixins( TestMixin1.class )
+    public interface TestServiceComposite1
+        extends TestService, Availability, ServiceComposite
+    {
+    }
+
+    // This service has availability set through configuration
+    @Mixins( TestMixin2.class )
+    public interface TestServiceComposite2
+        extends TestService, Configuration<TestServiceConfiguration>, ServiceComposite
+    {
+    }
+
+    public interface TestServiceConfiguration
+        extends Enabled, ConfigurationComposite
+    {
+    }
+
+    public interface TestService
+    {
+        String test();
+    }
+
+    public static class TestMixin1
+        implements TestService, Availability
+    {
+        public String test()
+        {
+            return "mixin1";
+        }
+
+        public boolean isAvailable()
+        {
+            return true;
+        }
+    }
+
+    public static class TestMixin2
+        implements TestService
+    {
+        @This
+        Configuration<TestServiceConfiguration> config;
+
+        public String test()
+        {
+            return "mixin2";
+        }
+    }
+
+    public static class TestObject
+    {
+        @Service
+        @Optional
+        @Available
+        TestService service;
+
+        public TestService getService()
+        {
+            return service;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/service/ComplexActivatableTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/service/ComplexActivatableTest.java
new file mode 100644
index 0000000..baef5c0
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/service/ComplexActivatableTest.java
@@ -0,0 +1,104 @@
+/*
+ *  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.polygene.runtime.service;
+
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.junit.Assert.assertEquals;
+
+public class ComplexActivatableTest
+    extends AbstractPolygeneTest
+{
+
+    public void assemble( ModuleAssembly module )
+            throws AssemblyException
+    {
+        module.services( SuperType.class ).withActivators( TestActivator.class ).instantiateOnStartup();
+    }
+
+    @Test
+    public void validateThatApplicationGotAssembled()
+    {
+        ServiceReference<SuperType> reference = serviceFinder.findService( SuperType.class );
+        assertEquals( "Hello, World", reference.get().sayHello() );
+    }
+
+    @Mixins( { DomainType.class, InitializationMixin.class } )
+    public interface SuperType
+            extends ServiceComposite, Initializable
+    {
+
+        String sayHello();
+
+        Property<String> greeting();
+
+        Property<String> recepient();
+
+    }
+
+    public abstract static class DomainType
+            implements SuperType
+    {
+
+        public String sayHello()
+        {
+            return greeting().get() + ", " + recepient().get();
+        }
+
+    }
+
+    public static class InitializationMixin
+            implements Initializable
+    {
+
+        @This
+        private SuperType me;
+
+        public void initialize()
+        {
+            me.greeting().set( "Hello" );
+        }
+
+    }
+
+    public static class TestActivator
+            extends ActivatorAdapter<ServiceReference<SuperType>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<SuperType> activated )
+                throws Exception
+        {
+            activated.get().recepient().set( "World" );
+        }
+
+    }
+
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/service/ConfigurationTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/service/ConfigurationTest.java
new file mode 100644
index 0000000..b8cc751
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/service/ConfigurationTest.java
@@ -0,0 +1,147 @@
+/*
+ *  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.polygene.runtime.service;
+
+import org.junit.Test;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.configuration.ConfigurationComposite;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test of configuration for services
+ */
+public class ConfigurationTest
+    extends AbstractPolygeneTest
+{
+    @Service
+    ServiceReference<HelloWorldService> service;
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.objects( this.getClass() );
+        module.entities( HelloWorldConfiguration.class );
+        module.services( HelloWorldService.class ).identifiedBy( "HelloWorldService" );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Test
+    public void whenConfiguredThenSayHelloWorks()
+        throws Exception
+    {
+        UnitOfWork unit = unitOfWorkFactory.newUnitOfWork();
+        EntityBuilder<HelloWorldConfiguration> entityBuilder = unit.newEntityBuilder( HelloWorldConfiguration.class, service.identity() );
+        HelloWorldConfiguration config = entityBuilder.instance();
+        config.phrase().set( "Hey" );
+        config.name().set( "Universe" );
+        entityBuilder.newInstance();
+        unit.complete();
+
+        assertThat( "result is correct", service.get().sayHello(), equalTo( "Hey Universe" ) );
+    }
+
+    @Test
+    public void whenUnconfiguredThenSayHelloGivesDefaults()
+        throws Exception
+    {
+        assertThat( "result is correct", service.get().sayHello(), equalTo( "Hello World" ) );
+    }
+
+    @Test
+    public void givenConfiguredServiceWhenReconfiguredAndRefreshedThenNewConfigurationIsUsed()
+        throws Exception
+    {
+        HelloWorldConfiguration config;
+
+        {
+            UnitOfWork unit = unitOfWorkFactory.newUnitOfWork();
+            EntityBuilder<HelloWorldConfiguration> entityBuilder = unit.newEntityBuilder( HelloWorldConfiguration.class, service.identity() );
+            config = entityBuilder.instance();
+            config.phrase().set( "Hello" );
+            config.name().set( "World" );
+            config = entityBuilder.newInstance();
+            unit.complete();
+        }
+
+        assertThat( "result is correct", service.get().sayHello(), equalTo( "Hello World" ) );
+
+        {
+            UnitOfWork unit = unitOfWorkFactory.newUnitOfWork();
+            config = unit.get( config );
+            config.phrase().set( "Hey" );
+            config.name().set( "Universe" );
+            unit.complete();
+        }
+
+        assertThat( "new configuration is not used", service.get().sayHello(), equalTo( "Hello World" ) );
+
+        service.get().refresh();
+
+        assertThat( "new configuration is used", service.get().sayHello(), equalTo( "Hey Universe" ) );
+    }
+
+    public interface HelloWorld
+    {
+        String sayHello();
+    }
+
+    @Mixins( HelloWorldMixin.class )
+    public interface HelloWorldService
+        extends HelloWorld, ServiceComposite, Configuration
+    {
+    }
+
+    public interface HelloWorldConfiguration
+        extends ConfigurationComposite
+    {
+        @UseDefaults
+        Property<String> phrase();
+
+        @UseDefaults
+        Property<String> name();
+    }
+
+    public static class HelloWorldMixin
+        implements HelloWorld
+    {
+        @This
+        Configuration<HelloWorldConfiguration> config;
+
+        public String sayHello()
+        {
+            return config.get().phrase() + " " + config.get().name();
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/service/LazyActivatedServiceTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/service/LazyActivatedServiceTest.java
new file mode 100644
index 0000000..52a9d1b
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/service/LazyActivatedServiceTest.java
@@ -0,0 +1,119 @@
+/*
+ *  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.polygene.runtime.service;
+
+import junit.framework.TestCase;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+/**
+ * Test of lazily activated services
+ */
+public class LazyActivatedServiceTest
+    extends TestCase
+{
+    @Service
+    ServiceReference<MyService> service;
+
+    public static boolean isActive;
+
+    public void testActivatable()
+        throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.objects( LazyActivatedServiceTest.class );
+                module.services( LazyActivatedServiceTest.MyServiceComposite.class ).withActivators( TestActivator.class );
+            }
+        };
+
+        assertFalse( isActive );
+
+        assembly.module().injectTo( this );
+
+        assertFalse( isActive );
+
+        service.get();
+
+        assertFalse( isActive );
+
+        service.get().doStuff();
+
+        assertTrue( isActive );
+
+        assembly.application().passivate();
+
+        assertFalse( isActive );
+    }
+
+    @Mixins( { MyServiceMixin.class } )
+    public static interface MyServiceComposite
+        extends MyService, ServiceComposite
+    {
+    }
+
+    public static interface MyService
+    {
+        String doStuff();
+    }
+
+    public static class MyServiceMixin
+        implements MyService
+    {
+
+        public String doStuff()
+        {
+            return "X";
+        }
+    }
+
+    public static class TestActivator
+            extends ActivatorAdapter<Object>
+    {
+
+        @Override
+        public void afterActivation( Object activated )
+        {
+            isActive = true;
+        }
+
+        @Override
+        public void afterPassivation( Object passivated )
+                throws Exception
+        {
+            if ( !isActive ) {
+                throw new Exception( "Not active!" );
+            }
+
+            isActive = false;
+        }
+
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/service/PassivationTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/service/PassivationTest.java
new file mode 100644
index 0000000..c3964f6
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/service/PassivationTest.java
@@ -0,0 +1,215 @@
+/*
+ *  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.polygene.runtime.service;
+
+import java.util.ArrayList;
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class PassivationTest
+{
+
+    @Test
+    public void givenSuccessPassivationWhenPassivatingExpectNoExceptions()
+        throws Throwable
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
+                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
+            }
+        };
+
+        assembly.module().findServices( DataAccess.class ).forEach(
+            service ->
+            {
+                assertTrue( "Service should not be Active before accessed", !service.isActive() );
+                assertTrue( service.get().data().activated );
+                assertTrue( "Service should be Active after access.", service.isActive() );
+            }
+        );
+        assembly.application().passivate();
+    }
+
+    @Test
+    public void givenMixedSuccessFailurePassivationWhenPassivatingExpectAllPassivateMethodsToBeCalled()
+        throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
+                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
+                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
+                module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
+                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
+                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
+                module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
+                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
+                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
+                module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
+                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
+                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
+                module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
+            }
+        };
+
+        ArrayList<Data> datas = new ArrayList<Data>();
+
+        assembly.module().findServices( DataAccess.class ).forEach(
+            service ->
+            {
+                assertTrue( "Service should not be Active before accessed", !service.isActive() );
+                Data data = service.get().data();
+                if( DataAccessService.class.isInstance( service.get() ) )
+                {
+                    // Collect the expected successes.
+                    datas.add( data );
+                }
+                assertTrue( "Data should indicate that the service is activated", data.activated );
+                assertTrue( "Service should be Active after access.", service.isActive() );
+            }
+        );
+        try
+        {
+            assembly.application().passivate();
+            fail( "PassivationException should have been thrown." );
+        }
+        catch( PassivationException e )
+        {
+            // Expected
+        }
+
+        // Still ensure that all services have been shutdown.
+        assembly.module().findServices( DataAccess.class ).forEach(
+            service ->
+            {
+                assertFalse( "All services should have been shutdown", service.isActive() );
+            }
+        );
+    }
+
+    @Test(expected = PassivationException.class)
+    public void givenMultipleFailingPassivationWhenPassivatingExpectPassivationExceptionToBubbleUp()
+        throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
+                module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
+            }
+        };
+
+        assembly.module().findServices( DataAccess.class ).forEach(
+            service ->
+            {
+                assertTrue( "Service should not be Active before accessed", !service.isActive() );
+                assertTrue( service.get().data().activated );
+                assertTrue( "Service should be Active after access.", service.isActive() );
+            }
+        );
+        assembly.application().passivate();
+    }
+
+    @Mixins(DataAccessMixin.class)
+    public interface DataAccessService
+        extends DataAccess, ServiceComposite
+    {
+    }
+
+    public interface DataAccess
+    {
+        Data data();
+    }
+
+    public static class DataAccessMixin
+        implements DataAccess
+    {
+        Data data = new Data();
+
+        public Data data()
+        {
+            return data;
+        }
+    }
+
+    public static class PassivationSuccessActivator
+        extends ActivatorAdapter<ServiceReference<DataAccess>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<DataAccess> activated )
+            throws Exception
+        {
+            activated.get().data().activated = true;
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<DataAccess> passivating )
+            throws Exception
+        {
+            passivating.get().data().activated = false;
+        }
+    }
+
+    public static class PassivationFailureActivator
+        extends ActivatorAdapter<ServiceReference<DataAccess>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<DataAccess> activated )
+            throws Exception
+        {
+            activated.get().data().activated = true;
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<DataAccess> passivating )
+            throws Exception
+        {
+            throw new IllegalStateException();
+        }
+    }
+
+    public static class Data
+    {
+        boolean activated = false;
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/service/ServiceFinderTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/service/ServiceFinderTest.java
new file mode 100644
index 0000000..9bddd31
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/service/ServiceFinderTest.java
@@ -0,0 +1,129 @@
+/*
+ *  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.polygene.runtime.service;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+
+public class ServiceFinderTest extends AbstractPolygeneTest
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( CompileTimeService.class );
+        module.services( RuntimeService.class )
+            .withTypes( MyRuntimeService.class )
+            .withMixins( MyRuntimeServiceMixin.class );
+    }
+
+    @Test
+    public void givenServiceCompileTimeWeavingWhenFindingServiceBySuperTypeExceptServiceToBeFound()
+    {
+        ServiceReference<MyCompileTimeService> service = serviceFinder.findService( MyCompileTimeService.class );
+        assertThat( service, notNullValue() );
+        assertThat( service.get(), notNullValue() );
+        assertThat( service.get().doSomething(), equalTo( "Niclas" ) );
+    }
+
+    @Test
+    public void givenServiceRuntimeWeavingWhenFindingServiceBySuperTypeExceptServiceToBeFound()
+    {
+        ServiceReference<MyRuntimeService> service = serviceFinder.findService( MyRuntimeService.class );
+        assertThat( service, notNullValue() );
+        assertThat( service.get(), notNullValue() );
+        assertThat( service.get().doSomething(), equalTo( "Niclas" ) );
+    }
+
+    @Mixins( MyCompileTimeServiceMixin.class )
+    public interface MyCompileTimeService
+    {
+        String doSomething();
+    }
+
+    public interface MyRuntimeService
+    {
+        String doSomething();
+    }
+
+    public class MyCompileTimeServiceMixin
+        implements MyCompileTimeService
+    {
+
+        @Override
+        public String doSomething()
+        {
+            return "Niclas";
+        }
+    }
+
+    public class MyRuntimeServiceMixin
+        implements MyRuntimeService
+    {
+
+        @Override
+        public String doSomething()
+        {
+            return "Niclas";
+        }
+    }
+
+    @Mixins( CompileTimeServiceMixin.class )
+    public interface CompileTimeService extends MyCompileTimeService
+    {
+        String anotherMethod();
+    }
+
+    @Mixins( RuntimeServiceMixin.class )
+    public interface RuntimeService
+    {
+        String anotherMethod();
+    }
+
+    public abstract class CompileTimeServiceMixin
+        implements CompileTimeService
+    {
+        @Override
+        public String anotherMethod()
+        {
+            return "Hedhman";
+        }
+    }
+
+    public class RuntimeServiceMixin
+        implements RuntimeService
+    {
+        @Override
+        public String anotherMethod()
+        {
+            return "Hedhman";
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/service/ServiceIdSelectorTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/service/ServiceIdSelectorTest.java
new file mode 100644
index 0000000..d00af2a
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/service/ServiceIdSelectorTest.java
@@ -0,0 +1,118 @@
+/*
+ *  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.polygene.runtime.service;
+
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.junit.Test;
+
+import static org.apache.polygene.api.service.qualifier.ServiceQualifier.withId;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * JAVADOC
+ */
+public class ServiceIdSelectorTest
+{
+    @Test
+    public void givenManyServicesWhenInjectServiceThenGetSelectedOne()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.objects( ServiceConsumer.class );
+                module.services( TestServiceComposite1.class,
+                                 TestServiceComposite2.class );
+            }
+        };
+
+        ObjectFactory obf = assembler.module();
+        ServiceConsumer consumer = obf.newObject( ServiceConsumer.class, TestServiceComposite2.class.getSimpleName() );
+        TestService service = consumer.getService();
+
+        assertThat( "service is selected one", service.test(), equalTo( "mixin2" ) );
+    }
+
+    public static class ServiceConsumer
+    {
+        private TestService service;
+
+        public ServiceConsumer( @Uses String serviceId, @Service Iterable<ServiceReference<TestService>> serviceRefs )
+        {
+            service = StreamSupport.stream( serviceRefs.spliterator(), false )
+                                   .filter( withId( serviceId ) )
+                                   .findFirst().map( ServiceReference::get ).orElse( null );
+        }
+
+        public TestService getService()
+        {
+            return service;
+        }
+    }
+
+    @Mixins( TestMixin1.class )
+    public interface TestServiceComposite1
+        extends TestService, ServiceComposite
+    {
+    }
+
+    @Mixins( TestMixin2.class )
+    public interface TestServiceComposite2
+        extends TestService, ServiceComposite
+    {
+    }
+
+    public interface TestService
+    {
+        String test();
+    }
+
+    public static class TestMixin1
+        implements TestService
+    {
+        public String test()
+        {
+            return "mixin1";
+        }
+    }
+
+    public static class TestMixin2
+        implements TestService
+    {
+        public String test()
+        {
+            return "mixin2";
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/service/ServiceVisibilityTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/service/ServiceVisibilityTest.java
new file mode 100644
index 0000000..d59b6ed
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/service/ServiceVisibilityTest.java
@@ -0,0 +1,897 @@
+/*
+ *  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.polygene.runtime.service;
+
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.NoSuchServiceException;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.ApplicationAssemblerAdapter;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+public class ServiceVisibilityTest
+{
+    public static final Identity TEST_IDENTITY = new StringIdentity( "123" );
+
+    private Energy4Java polygene;
+    private Module module;
+    private Application app;
+    private UnitOfWorkFactory uowf;
+
+    @Before
+    public void setup()
+        throws Exception
+    {
+        polygene = new Energy4Java();
+
+        Assembler[][][] assemblers = new Assembler[][][]
+            {
+                { // Layer Above
+                  {
+                      new AboveAssembler()
+                  }
+                },
+                { // Layer From
+                  { // From Module
+                    new FromAssembler(),
+                  },
+                  { // Beside Module
+                    new BesideAssembler()
+                  }
+                },
+                { // Layer Below
+                  {
+                      new BelowAssembler()
+                  }
+                }
+            };
+        app = polygene.newApplication( new ApplicationAssemblerAdapter( assemblers )
+        {
+        } );
+        app.activate();
+        module = app.findModule( "From Layer", "From" );
+        uowf = module.unitOfWorkFactory();
+    }
+
+    @After
+    public void tearDown()
+        throws Exception
+    {
+        app.passivate();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromServiceWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromServiceWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromServiceWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromServiceWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromServiceWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromServiceWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.aboveModuleVisible();
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.moduleApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.moduleLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.moduleModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.besideApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.besideLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromEntityWhenAccessingBesideModuleVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.besideModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.belowApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromEntityWhenAccessingBelowLayerVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.belowLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromEntityWhenAccessingBelowModuleVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.belowModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromEntityWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.aboveApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromEntityWhenAccessingAboveLayerVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.aboveLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromEntityWhenAccessingAboveModuleVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.aboveModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromValueWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromValueWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromValueWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromValueWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromValueWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromValueWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.aboveModuleVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromTransientWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromTransientWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromTransientWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromTransientWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromTransientWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromTransientWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.aboveModuleVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromObjectWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromObjectWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromObjectWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromObjectWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromObjectWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchServiceException.class )
+    public void givenFromObjectWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.aboveModuleVisible();
+    }
+
+    private static class FromAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.layer().setName( "From Layer" );
+            module.setName( "From" );
+            module.services( FromService.class );
+            module.entities( FromEntity.class );
+            module.transients( FromTransient.class );
+            module.values( FromValue.class );
+            module.objects( FromObject.class );
+
+            module.services( ModuleApplicationVisible.class ).visibleIn( Visibility.application );
+            module.services( ModuleLayerVisible.class ).visibleIn( Visibility.layer );
+            module.services( ModuleModuleVisible.class ).visibleIn( Visibility.module );
+
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    private static class BelowAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.layer().setName( "Below Layer" );
+            module.setName( "Below" );
+            module.services( BelowApplicationVisible.class ).visibleIn( Visibility.application );
+            module.services( BelowLayerVisible.class ).visibleIn( Visibility.layer );
+            module.services( BelowModuleVisible.class ).visibleIn( Visibility.module );
+
+            new EntityTestAssembler().visibleIn( Visibility.application ).assemble( module );
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    private static class AboveAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.layer().setName( "Above Layer" );
+            module.setName( "Above" );
+            module.services( AboveApplicationVisible.class ).visibleIn( Visibility.application );
+            module.services( AboveLayerVisible.class ).visibleIn( Visibility.layer );
+            module.services( AboveModuleVisible.class ).visibleIn( Visibility.module );
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    private static class BesideAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.setName( "Beside" );
+            module.services( BesideApplicationVisible.class ).visibleIn( Visibility.application );
+            module.services( BesideLayerVisible.class ).visibleIn( Visibility.layer );
+            module.services( BesideModuleVisible.class ).visibleIn( Visibility.module );
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    @Mixins( Mixin.class )
+    public interface From
+    {
+        void moduleApplicationVisible();
+
+        void moduleLayerVisible();
+
+        void moduleModuleVisible();
+
+        void besideApplicationVisible();
+
+        void besideLayerVisible();
+
+        void besideModuleVisible();
+
+        void belowApplicationVisible();
+
+        void belowLayerVisible();
+
+        void belowModuleVisible();
+
+        void aboveApplicationVisible();
+
+        void aboveLayerVisible();
+
+        void aboveModuleVisible();
+    }
+
+    public interface FromValue extends From, ValueComposite
+    {
+    }
+
+    public interface FromEntity extends From, EntityComposite
+    {
+    }
+
+    public interface FromService extends From, ServiceComposite
+    {
+    }
+
+    public interface FromTransient extends From, TransientComposite
+    {
+    }
+
+    public static class FromObject extends Mixin
+    {
+    }
+
+    public abstract static class Mixin
+        implements From
+    {
+        @Structure
+        private Module module;
+
+        @Override
+        public void moduleApplicationVisible()
+        {
+            ModuleApplicationVisible service = module.findService( ModuleApplicationVisible.class ).get();
+        }
+
+        @Override
+        public void moduleLayerVisible()
+        {
+            ModuleLayerVisible service = module.findService( ModuleLayerVisible.class ).get();
+        }
+
+        @Override
+        public void moduleModuleVisible()
+        {
+            ModuleModuleVisible service = module.findService( ModuleModuleVisible.class ).get();
+        }
+
+        @Override
+        public void besideApplicationVisible()
+        {
+            BesideApplicationVisible service = module.findService( BesideApplicationVisible.class ).get();
+        }
+
+        @Override
+        public void besideLayerVisible()
+        {
+            BesideLayerVisible service = module.findService( BesideLayerVisible.class ).get();
+        }
+
+        @Override
+        public void besideModuleVisible()
+        {
+            BesideModuleVisible service = module.findService( BesideModuleVisible.class ).get();
+        }
+
+        @Override
+        public void belowApplicationVisible()
+        {
+            BelowApplicationVisible service = module.findService( BelowApplicationVisible.class ).get();
+        }
+
+        @Override
+        public void belowLayerVisible()
+        {
+            BelowLayerVisible service = module.findService( BelowLayerVisible.class ).get();
+        }
+
+        @Override
+        public void belowModuleVisible()
+        {
+            BelowModuleVisible service = module.findService( BelowModuleVisible.class ).get();
+        }
+
+        @Override
+        public void aboveApplicationVisible()
+        {
+            AboveApplicationVisible service = module.findService( AboveApplicationVisible.class ).get();
+        }
+
+        @Override
+        public void aboveLayerVisible()
+        {
+            AboveLayerVisible service = module.findService( AboveLayerVisible.class ).get();
+        }
+
+        @Override
+        public void aboveModuleVisible()
+        {
+            AboveModuleVisible service = module.findService( AboveModuleVisible.class ).get();
+        }
+    }
+
+    public interface ModuleApplicationVisible extends ServiceComposite
+    {
+    }
+
+    public interface ModuleLayerVisible extends ServiceComposite
+    {
+    }
+
+    public interface ModuleModuleVisible extends ServiceComposite
+    {
+    }
+
+    public interface BesideApplicationVisible extends ServiceComposite
+    {
+    }
+
+    public interface BesideLayerVisible extends ServiceComposite
+    {
+    }
+
+    public interface BesideModuleVisible extends ServiceComposite
+    {
+    }
+
+    public interface BelowApplicationVisible extends ServiceComposite
+    {
+    }
+
+    public interface BelowLayerVisible extends ServiceComposite
+    {
+    }
+
+    public interface BelowModuleVisible extends ServiceComposite
+    {
+    }
+
+    public interface AboveApplicationVisible extends ServiceComposite
+    {
+    }
+
+    public interface AboveLayerVisible extends ServiceComposite
+    {
+    }
+
+    public interface AboveModuleVisible extends ServiceComposite
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/sideeffects/GenericSideEffectTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/sideeffects/GenericSideEffectTest.java
new file mode 100644
index 0000000..4ff5e2b
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/sideeffects/GenericSideEffectTest.java
@@ -0,0 +1,113 @@
+/*
+ *  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.polygene.runtime.sideeffects;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.AppliesToFilter;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.sideeffect.GenericSideEffect;
+import org.apache.polygene.api.sideeffect.SideEffects;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertThat;
+
+/**
+ * JAVADOC
+ */
+public class GenericSideEffectTest
+    extends AbstractPolygeneTest
+{
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( SomeComposite.class );
+    }
+
+    @Test
+    public void testGenericSideEffect()
+    {
+        SomeComposite some = transientBuilderFactory.newTransient( SomeComposite.class );
+        Property<Integer> count = some.count();
+        assertThat( "count is zero", count.get(), equalTo( 0 ) );
+        some.doStuff();
+        assertThat( "count is not zero", count.get(), not( equalTo( 0 ) ) );
+    }
+
+    @SideEffects( CounterSideEffect.class )
+    @Mixins( SomeMixin.class )
+    public interface SomeComposite
+        extends Some, Counter, TransientComposite
+    {
+    }
+
+    public interface Some
+    {
+        public String doStuff();
+    }
+
+    public static abstract class SomeMixin
+        implements Some
+    {
+        public String doStuff()
+        {
+            return "Blah blah";
+        }
+    }
+
+    public interface Counter
+    {
+        @UseDefaults
+        Property<Integer> count();
+    }
+
+    @AppliesTo( NotCounterFilter.class )
+    public static class CounterSideEffect
+        extends GenericSideEffect
+    {
+        @This
+        Counter counter;
+
+        public void invoke( Method method, Object[] objects )
+        {
+            counter.count().set( counter.count().get() + 1 );
+        }
+    }
+
+    public static class NotCounterFilter
+        implements AppliesToFilter
+    {
+        public boolean appliesTo( Method method, Class mixin, Class compositeType, Class modifierClass )
+        {
+            return !method.getDeclaringClass().equals( Counter.class );
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/sideeffects/ModuleSideEffectTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/sideeffects/ModuleSideEffectTest.java
new file mode 100644
index 0000000..78f2d9c
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/sideeffects/ModuleSideEffectTest.java
@@ -0,0 +1,89 @@
+/*
+ *  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.polygene.runtime.sideeffects;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.sideeffect.GenericSideEffect;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+/**
+ * Test of declaring sideeffect in assembly
+ */
+public class ModuleSideEffectTest
+    extends AbstractPolygeneTest
+{
+    public static boolean ok = false;
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( FooComposite.class ).withSideEffects( TraceSideEffect.class );
+    }
+
+    @Test
+    public void testModuleSideEffect()
+    {
+        transientBuilderFactory.newTransient( Foo.class ).test( "Foo", 42 );
+        Assert.assertThat( "SideEffect has been called", ok, CoreMatchers.equalTo( true ) );
+    }
+
+    @Mixins( FooMixin.class )
+    public interface FooComposite
+        extends TransientComposite, Foo
+    {
+    }
+
+    public interface Foo
+    {
+        String test( String foo, int bar );
+    }
+
+    public static class FooMixin
+        implements Foo
+    {
+        public String test( String foo, int bar )
+        {
+            return foo + " " + bar;
+        }
+    }
+
+    public static class TraceSideEffect
+        extends GenericSideEffect
+    {
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            ok = true;
+            Object result = this.result.invoke( proxy, method, args );
+            String str = method.getName() + Arrays.asList( args );
+            System.out.println( str );
+            return result;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/sideeffects/SampleTransientTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/sideeffects/SampleTransientTest.java
new file mode 100644
index 0000000..022f1f0
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/sideeffects/SampleTransientTest.java
@@ -0,0 +1,89 @@
+/*
+ *  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.polygene.runtime.sideeffects;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.sideeffect.SideEffectOf;
+import org.apache.polygene.api.sideeffect.SideEffects;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class SampleTransientTest extends AbstractPolygeneTest
+{
+
+    @Structure
+    TransientBuilderFactory transientBuilderFactory;
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( SampleTransient.class );
+    }
+
+    @Test
+    public void givenTransientWithSideEffectsWhenInvokingMethodShouldExecuteSideEffectOnlyOnce()
+    {
+        SampleTransient sample = transientBuilderFactory.newTransient( SampleTransient.class );
+        sample.execute();
+        assertThat( sample.count().get(), equalTo(1));
+    }
+
+    @SideEffects( SampleSideEffect.class )
+    @Mixins( SampleTransientMixin.class )
+    public static interface SampleTransient
+    {
+        void execute();
+
+        @UseDefaults
+        Property<Integer> count();
+    }
+
+    public abstract static class SampleTransientMixin
+        implements SampleTransient
+    {
+        @Override
+        public void execute()
+        {
+            System.out.println( "Invocation of Transient" );
+        }
+    }
+
+    public abstract static class SampleSideEffect extends SideEffectOf<SampleTransient>
+        implements SampleTransient
+    {
+        @Override
+        public void execute()
+        {
+            System.out.println( "Invocation of SideEffect" );
+            count().set( count().get() + 1 );
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/sideeffects/SpecificSideEffectTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/sideeffects/SpecificSideEffectTest.java
new file mode 100644
index 0000000..0c7daae
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/sideeffects/SpecificSideEffectTest.java
@@ -0,0 +1,101 @@
+/*
+ *  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.polygene.runtime.sideeffects;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.sideeffect.SideEffectOf;
+import org.apache.polygene.api.sideeffect.SideEffects;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for adding side-effects to methods specified by domain interfaces
+ */
+public class SpecificSideEffectTest
+    extends AbstractPolygeneTest
+{
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( SomeComposite.class );
+    }
+
+    @Test
+    public void specificSideEffect()
+    {
+        SomeComposite some = transientBuilderFactory.newTransient( SomeComposite.class );
+        Property<Integer> count = some.count();
+        assertThat( "count is zero", count.get(), equalTo( 0 ) );
+        some.doStuff();
+        assertThat( "count is not zero", count.get(), equalTo( 1 ) );
+    }
+
+    @SideEffects( CounterSideEffect.class )
+    @Mixins( SomeMixin.class )
+    public interface SomeComposite
+        extends Some, Counter, TransientComposite
+    {
+    }
+
+    public interface Some
+    {
+        public String doStuff();
+    }
+
+    public static abstract class SomeMixin
+        implements Some
+    {
+        public String doStuff()
+        {
+            return "Blah blah";
+        }
+    }
+
+    public interface Counter
+    {
+        @UseDefaults
+        Property<Integer> count();
+    }
+
+    public static class CounterSideEffect
+        extends SideEffectOf<Some>
+        implements Some
+    {
+        @This
+        Counter counter;
+
+        public String doStuff()
+        {
+            counter.count().set( counter.count().get() + 1 );
+            return null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/structure/ApplicationModeTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/structure/ApplicationModeTest.java
new file mode 100644
index 0000000..61c1a1d
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/structure/ApplicationModeTest.java
@@ -0,0 +1,114 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+public class ApplicationModeTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+
+    }
+
+    @Test
+    public void testApplicationModeNotSet()
+    {
+        // mode is set to test in AbstractPolygeneTest
+        Assert.assertThat( "mode set to default",
+                           application.mode(),
+                           CoreMatchers.equalTo( Application.Mode.test ) );
+    }
+
+    @Test
+    public void testApplicationTestModeSet()
+        throws ActivationException, AssemblyException
+    {
+        Application.Mode mode = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.layer().application().setMode( Application.Mode.test );
+            }
+        }.application().mode();
+
+        Assert.assertThat( "mode set to given value", mode, CoreMatchers.equalTo( Application.Mode.test ) );
+    }
+
+    @Test
+    public void testApplicationStagingModeSet()
+        throws ActivationException, AssemblyException
+    {
+        Application.Mode mode = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.layer().application().setMode( Application.Mode.staging );
+            }
+        }.application().mode();
+
+        Assert.assertThat( "mode set to given value", mode, CoreMatchers.equalTo( Application.Mode.staging ) );
+    }
+
+    @Test
+    public void testApplicationDevelopmentModeSet()
+        throws ActivationException, AssemblyException
+    {
+        Application.Mode mode = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.layer().application().setMode( Application.Mode.development );
+            }
+        }.application().mode();
+
+        Assert.assertThat( "mode set to given value", mode, CoreMatchers.equalTo( Application.Mode.development ) );
+    }
+
+    @Test
+    public void testApplicationProductionModeSet()
+        throws ActivationException, AssemblyException
+    {
+        Application.Mode mode = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.layer().application().setMode( Application.Mode.production );
+            }
+        }.application().mode();
+
+        Assert.assertThat( "mode set to given value", mode, CoreMatchers.equalTo( Application.Mode.production ) );
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/structure/CompositeDescriptorTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/structure/CompositeDescriptorTest.java
new file mode 100644
index 0000000..af1d815
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/structure/CompositeDescriptorTest.java
@@ -0,0 +1,87 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class CompositeDescriptorTest
+    extends AbstractPolygeneTest
+{
+    @Test
+    public final void testCompositeDescriptorWithComposite()
+        throws Throwable
+    {
+        // Test with Standard composite
+        AddressComposite address = transientBuilderFactory.newTransient( AddressComposite.class );
+        CompositeDescriptor addressDescriptor = spi.compositeDescriptorFor( address );
+
+        assertNotNull( addressDescriptor );
+        assertEquals( AddressComposite.class, addressDescriptor.types().findFirst().orElse( null ) );
+        assertTrue( TransientDescriptor.class.isAssignableFrom( addressDescriptor.getClass() ) );
+    }
+
+    @Test
+    public final void testTransientCompositeDescriptorWithComposite()
+        throws Throwable
+    {
+        // Test with Standard composite
+        AddressComposite address = transientBuilderFactory.newTransient( AddressComposite.class );
+        TransientDescriptor addressDescriptor = spi.transientDescriptorFor( address );
+
+        assertNotNull( addressDescriptor );
+        assertEquals( AddressComposite.class, addressDescriptor.types().findFirst().orElse( null ) );
+        assertTrue( TransientDescriptor.class.isAssignableFrom( addressDescriptor.getClass() ) );
+    }
+
+    @Test
+    public final void testCompositeDescriptorWithMixin()
+    {
+        // Test with composite
+        TransientDescriptor addressDesc = module.transientDescriptor( AddressComposite.class.getName() );
+        assertNotNull( addressDesc );
+
+        assertEquals( AddressComposite.class, addressDesc.types().findFirst().orElse( null ) );
+    }
+
+    public final void assemble( ModuleAssembly aModule )
+        throws AssemblyException
+    {
+        aModule.transients( AddressComposite.class );
+    }
+
+    private interface AddressComposite
+        extends Address, TransientComposite
+    {
+    }
+
+    private interface Address
+    {
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/structure/MixinVisibilityTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/structure/MixinVisibilityTest.java
new file mode 100644
index 0000000..eaf9794
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/structure/MixinVisibilityTest.java
@@ -0,0 +1,444 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import org.junit.Test;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.AmbiguousTypeException;
+import org.apache.polygene.api.composite.NoSuchTransientException;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.ApplicationAssemblerAdapter;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * JAVADOC
+ */
+public class MixinVisibilityTest
+{
+    @Test
+    public void testMixinInModuleIsVisible()
+        throws Exception
+    {
+        Energy4Java boot = new Energy4Java();
+        Assembler[][][] assemblers = new Assembler[][][]
+            {
+                { // Layer
+                  {  // Module 1
+                     new Assembler()
+                     {
+                         public void assemble( ModuleAssembly module )
+                             throws AssemblyException
+                         {
+                             module.setName( "Module A" );
+                             module.transients( B1Composite.class );
+                             module.objects( ObjectA.class );
+                         }
+                     }
+                  }
+                }
+            };
+
+        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
+        {
+        } );
+        app.activate();
+        ObjectA object = app.findModule( "Layer 1", "Module A" ).newObject( ObjectA.class );
+        assertEquals( "ok", object.test1() );
+        assertEquals( "abc", object.test2() );
+    }
+
+    @Test( expected = AmbiguousTypeException.class )
+    public void testMultipleMixinsInModuleWillFail()
+        throws Exception
+    {
+        Energy4Java boot = new Energy4Java();
+        Assembler[][][] assemblers = new Assembler[][][]
+            {
+                { // Layer
+                  {  // Module 1
+                     new Assembler()
+                     {
+                         public void assemble( ModuleAssembly module )
+                             throws AssemblyException
+                         {
+                             module.setName( "Module A" );
+                             module.transients( B1Composite.class, B2Composite.class );
+                             module.objects( ObjectA.class );
+                         }
+                     }
+                  }
+                }
+            };
+
+        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
+        {
+        } );
+        app.activate();
+        ObjectA object = app.findModule( "Layer 1", "Module A" ).newObject( ObjectA.class );
+        assertEquals( "ok", object.test1() );
+        assertEquals( "abc", object.test2() );
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void testMixinInLayerIsNotVisible()
+        throws Exception
+    {
+        Energy4Java boot = new Energy4Java();
+        Assembler[][][] assemblers = new Assembler[][][]
+            {
+                { // Layer
+                  {
+                      new Assembler()
+                      {
+                          public void assemble( ModuleAssembly module )
+                              throws AssemblyException
+                          {
+                              module.setName( "Module A" );
+                              module.objects( ObjectA.class );
+                          }
+                      }
+                  },
+                  {
+                      new Assembler()
+                      {
+                          public void assemble( ModuleAssembly module )
+                              throws AssemblyException
+                          {
+                              module.setName( "Module B" );
+                              module.transients( B1Composite.class );
+                          }
+                      }
+                  }
+                }
+            };
+
+        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
+        {
+        } );
+        app.activate();
+        ObjectA object = app.findModule( "Layer 1", "Module A" ).newObject( ObjectA.class );
+        assertEquals( "ok", object.test1() );
+        assertEquals( "abc", object.test2() );
+    }
+
+    @Test
+    public void testMixinInLayerIsVisible()
+        throws Exception
+    {
+        Energy4Java boot = new Energy4Java();
+        Assembler[][][] assemblers = new Assembler[][][]
+            {
+                { // Layer
+                  {
+                      new Assembler()
+                      {
+                          public void assemble( ModuleAssembly module )
+                              throws AssemblyException
+                          {
+                              module.setName( "Module A" );
+                              module.objects( ObjectA.class );
+                          }
+                      }
+                  },
+                  {
+                      new Assembler()
+                      {
+                          public void assemble( ModuleAssembly module )
+                              throws AssemblyException
+                          {
+                              module.setName( "Module B" );
+                              module.transients( B1Composite.class ).visibleIn( Visibility.layer );
+                          }
+                      }
+                  }
+                }
+            };
+
+        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
+        {
+        } );
+        app.activate();
+        ObjectA object = app.findModule( "Layer 1", "Module A" ).newObject( ObjectA.class );
+        assertEquals( "ok", object.test1() );
+        assertEquals( "abc", object.test2() );
+    }
+
+    @Test( expected = AmbiguousTypeException.class )
+    public void testMultipleMixinsInLayerWillFailSameModule()
+        throws Exception
+    {
+        Energy4Java boot = new Energy4Java();
+        Assembler[][][] assemblers = new Assembler[][][]
+            {
+                { // Layer
+                  {
+                      new Assembler()
+                      {
+                          public void assemble( ModuleAssembly module )
+                              throws AssemblyException
+                          {
+                              module.setName( "Module A" );
+                              module.objects( ObjectA.class );
+                          }
+                      }
+                  },
+                  {
+                      new Assembler()
+                      {
+                          public void assemble( ModuleAssembly module )
+                              throws AssemblyException
+                          {
+                              module.setName( "Module B" );
+                              module.transients( B1Composite.class, B2Composite.class )
+                                  .visibleIn( Visibility.layer );
+                          }
+                      }
+                  }
+                }
+            };
+
+        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
+        {
+        } );
+        app.activate();
+        ObjectA object = app.findModule( "Layer 1", "Module A" ).newObject( ObjectA.class );
+        assertEquals( "ok", object.test1() );
+        assertEquals( "abc", object.test2() );
+    }
+
+    @Test( expected = AmbiguousTypeException.class )
+    public void testMultipleMixinsInLayerWillFailDiffModule()
+        throws Exception
+    {
+        Energy4Java boot = new Energy4Java();
+        Assembler[][][] assemblers = new Assembler[][][]
+            {
+                { // Layer
+                  { // Module 1
+                    new Assembler()
+                    {
+                        public void assemble( ModuleAssembly module )
+                            throws AssemblyException
+                        {
+                            module.setName( "Module A" );
+                            module.objects( ObjectA.class );
+                        }
+                    }
+                  },
+                  { // Module 2
+                    new Assembler()
+                    {
+                        public void assemble( ModuleAssembly module )
+                            throws AssemblyException
+                        {
+                            module.setName( "Module B" );
+                            module.transients( B1Composite.class ).visibleIn( Visibility.layer );
+                        }
+                    }
+                  },
+                  { // Module 3
+                    new Assembler()
+                    {
+                        public void assemble( ModuleAssembly module )
+                            throws AssemblyException
+                        {
+                            module.setName( "Module C" );
+                            module.transients( B2Composite.class ).visibleIn( Visibility.layer );
+                        }
+                    }
+                  }
+                }
+            };
+
+        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
+        {
+        } );
+        app.activate();
+        ObjectA object = app.findModule( "Layer 1", "Module A" ).newObject( ObjectA.class );
+        assertEquals( "ok", object.test1() );
+        assertEquals( "abc", object.test2() );
+    }
+
+    // @Test( expected= MixinTypeNotAvailableException.class )
+
+    public void testMixinInLowerLayerIsNotVisible()
+        throws Exception
+    {
+
+        Energy4Java boot = new Energy4Java();
+        Assembler[][][] assemblers = new Assembler[][][]
+            {
+                { // Layer 1
+                  {
+                      new Assembler()
+                      {
+                          public void assemble( ModuleAssembly module )
+                              throws AssemblyException
+                          {
+                              module.setName( "Module A" );
+                              module.objects( ObjectA.class );
+                          }
+                      }
+                  }
+                },
+                { // Layer 2
+                  {
+                      new Assembler()
+                      {
+                          public void assemble( ModuleAssembly module )
+                              throws AssemblyException
+                          {
+                              module.setName( "Module B" );
+                              module.transients( B1Composite.class ).visibleIn( Visibility.layer );
+                          }
+                      }
+                  }
+                }
+            };
+
+        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
+        {
+        } );
+        app.activate();
+        ObjectA object = app.findModule( "Layer 1", "Module " ).newObject( ObjectA.class );
+        assertEquals( "ok", object.test1() );
+        assertEquals( "abc", object.test2() );
+    }
+
+    @Test
+    public void testMixinInLowerLayerIsVisible()
+        throws Exception
+    {
+        Energy4Java boot = new Energy4Java();
+        Assembler[][][] assemblers = new Assembler[][][]
+            {
+                { // Layer 1
+                  {
+                      new Assembler()
+                      {
+                          public void assemble( ModuleAssembly module )
+                              throws AssemblyException
+                          {
+                              module.setName( "Module A" );
+                              module.objects( ObjectA.class );
+                          }
+                      }
+                  }
+                },
+                { // Layer 2
+                  {
+                      new Assembler()
+                      {
+                          public void assemble( ModuleAssembly module )
+                              throws AssemblyException
+                          {
+                              module.setName( "Module B" );
+                              module.transients( B1Composite.class ).visibleIn( Visibility.application );
+                          }
+                      }
+                  }
+                }
+            };
+
+        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
+        {
+        } );
+        app.activate();
+        ObjectA object = app.findModule( "Layer 1", "Module A" ).newObject( ObjectA.class );
+        assertEquals( "ok", object.test1() );
+        assertEquals( "abc", object.test2() );
+    }
+
+    class AssemblerB
+        implements Assembler
+    {
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.setName( "Module B" );
+            module.transients( B1Composite.class ).visibleIn( Visibility.module );
+        }
+    }
+
+    public static class ObjectA
+    {
+        @Structure
+        TransientBuilderFactory cbf;
+
+        String test1()
+        {
+            B1 instance = cbf.newTransient( B1.class );
+            return instance.test();
+        }
+
+        String test2()
+        {
+            TransientBuilder<B2> builder = cbf.newTransientBuilder( B2.class );
+            builder.prototypeFor( B2.class ).b2().set( "abc" );
+            B2 instance = builder.newInstance();
+            return instance.b2().get();
+        }
+    }
+
+    @Mixins( { MixinB.class } )
+    public interface B1Composite
+        extends TransientComposite, B1
+    {
+    }
+
+    public interface B2Composite
+        extends TransientComposite, B2
+    {
+    }
+
+    public interface B2
+    {
+        @Optional
+        Property<String> b2();
+    }
+
+    public interface B1
+        extends B2
+    {
+        String test();
+    }
+
+    public abstract static class MixinB
+        implements B1
+    {
+        public String test()
+        {
+            return "ok";
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/structure/ModuleTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/structure/ModuleTest.java
new file mode 100644
index 0000000..aeb9fb7
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/structure/ModuleTest.java
@@ -0,0 +1,168 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test of the Module interface. This should satisfiedBy both the general interface and all possible visibility
+ * rules.
+ */
+public class ModuleTest
+{
+    public Application givenFixture1()
+        throws AssemblyException
+    {
+        Energy4Java boot = new Energy4Java();
+        return boot.newApplication( new ApplicationAssembler()
+        {
+            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+                throws AssemblyException
+            {
+                return applicationFactory.newApplicationAssembly( new Assembler[][][]
+                                                                  {
+                                                                      {
+                                                                          {
+                                                                              new Assembler()
+                                                                              {
+                                                                                  public void assemble( ModuleAssembly module )
+                                                                                      throws AssemblyException
+                                                                                  {
+                                                                                      module.transients( TestComposite1.class );
+                                                                                  }
+                                                                              }
+                                                                          },
+                                                                          {
+                                                                              new Assembler()
+                                                                              {
+                                                                                  public void assemble( ModuleAssembly module )
+                                                                                      throws AssemblyException
+                                                                                  {
+                                                                                      module.transients( TestComposite2.class )
+                                                                                          .visibleIn( Visibility.layer );
+                                                                                  }
+                                                                              }
+                                                                          }
+                                                                      }
+                                                                  } );
+            }
+        } );
+    }
+
+    @Test
+    public void givenFixture1WhenGetNameThenConfiguredNameIsReturned()
+        throws AssemblyException
+    {
+        Application app = givenFixture1();
+
+        Module module = app.findModule( "Layer 1", "Module 1" ).newTransient( TestComposite1.class ).getModule();
+        assertThat( "module name is correct", module.name(), equalTo( "Module 1" ) );
+    }
+
+    @Test
+    public void givenFixture1WhenGetModuleForCompositeThenCorrectModuleIsReturned()
+        throws AssemblyException
+    {
+        Application app = givenFixture1();
+
+        Module module = app.findModule( "Layer 1", "Module 1" ).newTransient( TestComposite1.class ).getModule();
+        assertThat( "module for composite is correct", module, equalTo( module ) );
+    }
+
+    @Test
+    public void givenFixture1WhenFindFromAnotherModuleThenCompositeTypeIsReturned()
+        throws ClassNotFoundException, AssemblyException
+    {
+        Application app = givenFixture1();
+
+        Module module = app.findModule( "Layer 1", "Module 1" ).newTransient( TestComposite1.class ).getModule();
+        module.descriptor().classLoader().loadClass( TestComposite2.class.getName() );
+    }
+
+    @Mixins( TestMixin1.class )
+    public interface TestComposite1
+        extends TransientComposite
+    {
+        Module getModule();
+    }
+
+    public abstract static class TestMixin1
+        implements TestComposite1
+    {
+        @Structure
+        Module module;
+
+        public Module getModule()
+        {
+            return module;
+        }
+    }
+
+    @Mixins( TestMixin2.class )
+    public interface TestComposite2
+        extends TransientComposite
+    {
+        Module getModule();
+    }
+
+    public abstract static class TestMixin2
+        implements TestComposite2
+    {
+        @Structure
+        Module module;
+
+        public Module getModule()
+        {
+            return module;
+        }
+    }
+
+    public interface TestComposite21
+        extends TestComposite2
+    {
+    }
+
+    public static class TestObject1
+    {
+
+    }
+
+    public static class TestObject2
+    {
+
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/structure/PrivateCompositeVisibilityTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/structure/PrivateCompositeVisibilityTest.java
new file mode 100644
index 0000000..8991605
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/structure/PrivateCompositeVisibilityTest.java
@@ -0,0 +1,116 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.NoSuchTransientException;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.ApplicationAssemblerAdapter;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+/**
+ * JAVADOC
+ */
+public class PrivateCompositeVisibilityTest
+{
+    @Test( expected = NoSuchTransientException.class )
+    public void testPrivateCompositeVisibility()
+        throws Exception
+    {
+        Energy4Java boot = new Energy4Java();
+        Assembler[][][] assemblers = new Assembler[][][]
+            {
+                { // Layer
+                  {
+                      new AssemblerA()
+                  },
+                  {
+                      new AssemblerB()
+                  }
+                }
+            };
+        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
+        {
+        } );
+        app.activate();
+        ObjectA object = app.findModule( "Layer 1", "Module A" ).newObject( ObjectA.class );
+        object.test();
+    }
+
+    class AssemblerA
+        implements Assembler
+    {
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.setName( "Module A" );
+            module.objects( ObjectA.class );
+        }
+    }
+
+    class AssemblerB
+        implements Assembler
+    {
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.setName( "Module B" );
+            module.transients( CompositeB.class ).visibleIn( Visibility.module );
+        }
+    }
+
+    public static class ObjectA
+    {
+        @Structure
+        TransientBuilderFactory cbf;
+
+        String test()
+        {
+            CompositeB instance = cbf.newTransient( CompositeB.class );
+            return instance.test();
+        }
+    }
+
+    @Mixins( MixinB.class )
+    public interface CompositeB
+        extends TransientComposite
+    {
+        String test();
+    }
+
+    public abstract static class MixinB
+        implements CompositeB
+    {
+
+        public String test()
+        {
+            return "ok";
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/structure/StructureTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/structure/StructureTest.java
new file mode 100644
index 0000000..5dec9df
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/structure/StructureTest.java
@@ -0,0 +1,135 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import org.junit.Test;
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.ApplicationAssemblerAdapter;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+/**
+ * JAVADOC
+ */
+public class StructureTest
+{
+
+    @Test
+    public void createApplicationUsingApplicationAssembly()
+        throws AssemblyException
+    {
+        Energy4Java boot = new Energy4Java();
+        boot.newApplication( new ApplicationAssembler()
+        {
+            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+                throws AssemblyException
+            {
+                ApplicationAssembly applicationAssembly = applicationFactory.newApplicationAssembly();
+                // Application Layer
+                LayerAssembly applicationLayer = applicationAssembly.layer( "Application" );
+                ModuleAssembly applicationModule = applicationLayer.module( "Application" );
+                new DomainApplicationAssembler().assemble( applicationModule );
+
+                // View Layer
+                LayerAssembly viewLayer = applicationAssembly.layer( "View" );
+                ModuleAssembly viewModule = viewLayer.module( "View" );
+                new ViewAssembler().assemble( viewModule );
+                viewLayer.uses( applicationLayer );
+                return applicationAssembly;
+            }
+        } );
+    }
+
+    @Test
+    public void createApplicationUsingArrayOfAssemblers()
+        throws AssemblyException
+    {
+        Energy4Java boot = new Energy4Java();
+        Assembler[][][] assemblers = new Assembler[][][]
+            {
+                { // User Interface layer
+                  {
+                      new ViewAssembler()
+                  }
+                },
+                { // Application layer
+                  {
+                      new DomainApplicationAssembler()
+                  }
+                },
+                { // Domain layer
+                  {
+                      new DomainModelAssembler()
+                  }
+                },
+                { // Infrastructure layer
+                  {
+                      new InfrastructureAssembler()
+                  }
+                }
+            };
+
+        boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
+        {
+        } );
+    }
+
+    static class ViewAssembler
+        implements Assembler
+    {
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+        }
+    }
+
+    static class DomainApplicationAssembler
+        implements Assembler
+    {
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+        }
+    }
+
+    static class DomainModelAssembler
+        implements Assembler
+    {
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+        }
+    }
+
+    static class InfrastructureAssembler
+        implements Assembler
+    {
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/structure/TypeToCompositeLookupTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/structure/TypeToCompositeLookupTest.java
new file mode 100644
index 0000000..c32e2ef
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/structure/TypeToCompositeLookupTest.java
@@ -0,0 +1,402 @@
+/*
+ *  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.polygene.runtime.structure;
+
+import java.util.Iterator;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.composite.AmbiguousTypeException;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+/**
+ * Theses tests ensure that Type to Composite lookup work as expected for
+ * Objects, Transients, Values, Entities and Services.
+ */
+public class TypeToCompositeLookupTest
+{
+
+    private static final String CATHEDRAL = "cathedral";
+    private static final String BAZAR = "bazar";
+
+    public interface Foo
+    {
+        String bar();
+    }
+
+    public static class BasicFooImpl
+        implements Foo
+    {
+
+        @Override
+        public String bar()
+        {
+            return BAZAR;
+        }
+
+    }
+
+    public static class SomeOtherFooImpl
+        extends BasicFooImpl
+    {
+
+        @Override
+        public String bar()
+        {
+            return CATHEDRAL;
+        }
+
+    }
+
+    @Mixins( BasicFooImpl.class )
+    public interface BasicFoo
+        extends Foo
+    {
+    }
+
+    @Mixins( SomeOtherFooImpl.class )
+    public interface SomeOtherFoo
+        extends BasicFoo
+    {
+    }
+
+    @Test
+    public void objects()
+        throws ActivationException, AssemblyException
+    {
+        Module module = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.objects( SomeOtherFooImpl.class );
+                new DefaultUnitOfWorkAssembler().assemble( module );
+            }
+
+        }.module();
+
+        assertEquals( CATHEDRAL, module.newObject( SomeOtherFooImpl.class ).bar() );
+        assertEquals( CATHEDRAL, module.newObject( BasicFooImpl.class ).bar() );
+        assertEquals( CATHEDRAL, module.newObject( Foo.class ).bar() );
+    }
+
+    @Test
+    public void objectsAmbiguousDeclaration()
+        throws ActivationException, AssemblyException
+    {
+        Module module = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.objects( SomeOtherFooImpl.class, BasicFooImpl.class );
+                new DefaultUnitOfWorkAssembler().assemble( module );
+            }
+
+        }.module();
+
+        assertEquals( CATHEDRAL, module.newObject( SomeOtherFooImpl.class ).bar() );
+        assertEquals( BAZAR, module.newObject( BasicFooImpl.class ).bar() );
+
+        try
+        {
+            module.newObject( Foo.class );
+            fail( "Ambiguous type exception not detected for Objects" );
+        }
+        catch( AmbiguousTypeException expected )
+        {
+        }
+    }
+
+    @Test
+    public void transients()
+        throws ActivationException, AssemblyException
+    {
+        Module module = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( SomeOtherFoo.class );
+                new DefaultUnitOfWorkAssembler().assemble( module );
+            }
+
+        }.module();
+
+        assertEquals( CATHEDRAL, module.newTransientBuilder( SomeOtherFoo.class ).newInstance().bar() );
+        assertEquals( CATHEDRAL, module.newTransientBuilder( BasicFoo.class ).newInstance().bar() );
+        assertEquals( CATHEDRAL, module.newTransientBuilder( Foo.class ).newInstance().bar() );
+    }
+
+    @Test
+    public void transientsAmbiguousDeclaration()
+        throws ActivationException, AssemblyException
+    {
+        Module module = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( SomeOtherFoo.class, BasicFoo.class );
+                new DefaultUnitOfWorkAssembler().assemble( module );
+            }
+
+        }.module();
+
+        assertEquals( CATHEDRAL, module.newTransientBuilder( SomeOtherFoo.class ).newInstance().bar() );
+        assertEquals( BAZAR, module.newTransientBuilder( BasicFoo.class ).newInstance().bar() );
+
+        try
+        {
+            module.newTransientBuilder( Foo.class );
+            fail( "Ambiguous type exception not detected for Transients" );
+        }
+        catch( AmbiguousTypeException expected )
+        {
+        }
+    }
+
+    @Test
+    public void values()
+        throws ActivationException, AssemblyException
+    {
+        Module module = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.values( SomeOtherFoo.class );
+                new DefaultUnitOfWorkAssembler().assemble( module );
+            }
+
+        }.module();
+
+        assertEquals( CATHEDRAL, module.newValueBuilder( SomeOtherFoo.class ).newInstance().bar() );
+        assertEquals( CATHEDRAL, module.newValueBuilder( BasicFoo.class ).newInstance().bar() );
+        assertEquals( CATHEDRAL, module.newValueBuilder( Foo.class ).newInstance().bar() );
+    }
+
+    @Test
+    public void valuesAmbiguousDeclaration()
+        throws ActivationException, AssemblyException
+    {
+        Module module = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.values( SomeOtherFoo.class, BasicFoo.class );
+                new DefaultUnitOfWorkAssembler().assemble( module );
+            }
+
+        }.module();
+
+        assertEquals( CATHEDRAL, module.newValueBuilder( SomeOtherFoo.class ).newInstance().bar() );
+        assertEquals( BAZAR, module.newValueBuilder( BasicFoo.class ).newInstance().bar() );
+
+        try
+        {
+            module.newValueBuilder( Foo.class );
+            fail( "Ambiguous type exception not detected for Values" );
+        }
+        catch( AmbiguousTypeException expected )
+        {
+        }
+    }
+
+    @Test
+    public void entities()
+        throws UnitOfWorkCompletionException, ActivationException, AssemblyException
+    {
+        UnitOfWorkFactory uowf = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                new EntityTestAssembler().assemble( module );
+                module.entities( SomeOtherFoo.class );
+                new DefaultUnitOfWorkAssembler().assemble( module );
+            }
+
+        }.module().unitOfWorkFactory();
+
+        UnitOfWork uow = uowf.newUnitOfWork();
+
+        SomeOtherFoo someOtherFoo = uow.newEntityBuilder( SomeOtherFoo.class ).newInstance();
+        BasicFoo basicFoo = uow.newEntityBuilder( BasicFoo.class ).newInstance();
+        Foo foo = uow.newEntityBuilder( Foo.class ).newInstance();
+
+        assertEquals( CATHEDRAL, someOtherFoo.bar() );
+        assertEquals( CATHEDRAL, basicFoo.bar() );
+        assertEquals( CATHEDRAL, foo.bar() );
+
+        Identity someOtherFooIdentity = ((HasIdentity) someOtherFoo).identity().get();
+        Identity basicFooIdentity = ((HasIdentity) basicFoo).identity().get();
+        Identity fooIdentity = ((HasIdentity) foo).identity().get();
+
+        uow.complete();
+
+        uow = uowf.newUnitOfWork();
+
+        uow.get( SomeOtherFoo.class,  someOtherFooIdentity );
+        uow.get( BasicFoo.class, basicFooIdentity );
+        uow.get( Foo.class,  fooIdentity );
+
+        uow.discard();
+    }
+
+    @Test
+    public void entitiesAmbiguousDeclaration()
+        throws UnitOfWorkCompletionException, ActivationException, AssemblyException
+    {
+        UnitOfWorkFactory uowf = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                new EntityTestAssembler().assemble( module );
+                module.entities( SomeOtherFoo.class, BasicFoo.class );
+                new DefaultUnitOfWorkAssembler().assemble( module );
+            }
+
+        }.module().unitOfWorkFactory();
+
+        UnitOfWork uow = uowf.newUnitOfWork();
+
+        SomeOtherFoo someOtherFoo = uow.newEntityBuilder( SomeOtherFoo.class ).newInstance();
+        BasicFoo basicFoo = uow.newEntityBuilder( BasicFoo.class ).newInstance();
+        try
+        {
+            uow.newEntityBuilder( Foo.class ).newInstance();
+            fail( "Ambiguous type exception not detected for Entities" );
+        }
+        catch( AmbiguousTypeException expected )
+        {
+        }
+
+        // Specific Type used
+        assertEquals( CATHEDRAL, uow.newEntityBuilder( SomeOtherFoo.class ).newInstance().bar() );
+
+        // Specific Type used
+        assertEquals( BAZAR, uow.newEntityBuilder( BasicFoo.class ).newInstance().bar() );
+
+        Identity someOtherFooIdentity = ((HasIdentity) someOtherFoo).identity().get();
+        Identity basicFooIdentity = ((HasIdentity) basicFoo).identity().get();
+
+        uow.complete();
+
+        uow = uowf.newUnitOfWork();
+
+        assertEquals( CATHEDRAL, uow.get( SomeOtherFoo.class, someOtherFooIdentity ).bar() );
+        assertEquals( BAZAR, uow.get( BasicFoo.class, basicFooIdentity ).bar() );
+        assertEquals( CATHEDRAL, uow.get( Foo.class, someOtherFooIdentity ).bar() );
+        assertEquals( BAZAR, uow.get( Foo.class, basicFooIdentity ).bar() );
+
+        uow.discard();
+    }
+
+    @Test
+    public void services()
+        throws ActivationException, AssemblyException
+    {
+        Module module = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.services( SomeOtherFoo.class );
+            }
+
+        }.module();
+
+        assertEquals( CATHEDRAL, module.findService( SomeOtherFoo.class ).get().bar() );
+        assertEquals( CATHEDRAL, module.findService( BasicFoo.class ).get().bar() );
+        assertEquals( CATHEDRAL, module.findService( Foo.class ).get().bar() );
+    }
+
+    @Test
+    public void servicesPluralDeclaration()
+        throws ActivationException, AssemblyException
+    {
+        Module module = new SingletonAssembler()
+        {
+
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.services( SomeOtherFoo.class, BasicFoo.class );
+            }
+
+        }.module();
+
+        assertEquals( 1, module.findServices( SomeOtherFoo.class ).count() );
+        assertEquals( 2, module.findServices( BasicFoo.class ).count() );
+        assertEquals( 2, module.findServices( Foo.class ).count() );
+
+        assertEquals( CATHEDRAL, module.findService( SomeOtherFoo.class ).get().bar() );
+
+        // Exact type match first even if it is assembled _after_ an assignable, the assignable comes after
+        Iterator<ServiceReference<BasicFoo>> basicFoos = module.findServices( BasicFoo.class ).iterator();
+        assertEquals( BAZAR, basicFoos.next().get().bar() );
+        assertEquals( CATHEDRAL, basicFoos.next().get().bar() );
+        assertFalse( basicFoos.hasNext() );
+
+        // No exact type match, all assembled are assignable, follows assembly Type order
+        Iterator<ServiceReference<Foo>> foos = module.findServices( Foo.class ).iterator();
+        assertEquals( CATHEDRAL, foos.next().get().bar() );
+        assertEquals( BAZAR, foos.next().get().bar() );
+        assertFalse( foos.hasNext() );
+    }
+
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/threaded/ContextCompositeTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/threaded/ContextCompositeTest.java
new file mode 100644
index 0000000..fcc0ee8
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/threaded/ContextCompositeTest.java
@@ -0,0 +1,144 @@
+/*
+ *  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.polygene.runtime.threaded;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.composite.CompositeContext;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.junit.Assert.assertEquals;
+
+public class ContextCompositeTest
+    extends AbstractPolygeneTest
+{
+
+    @Test
+    public void testThreadScope()
+        throws InterruptedException
+    {
+        for( int i = 0; i < 5; i++ )
+        {
+            TransientBuilder<MyCompositeContext> builder = transientBuilderFactory.newTransientBuilder( MyCompositeContext.class );
+            builder.prototypeFor( MyData.class ).data().set( 0 );
+            MyCompositeContext context = new CompositeContext<>( module, MyCompositeContext.class ).proxy();
+
+            Worker w1;
+            Worker w2;
+            MyCompositeContext c1 = builder.newInstance();
+            {
+                w1 = new Worker( "w1", context, 100, 0 );
+                w2 = new Worker( "w2", context, 400, 20 );
+                w2.start();
+                w1.start();
+            }
+            w1.join();
+            w2.join();
+            System.out.println( "W1: " + w1.getData() );
+            System.out.println( "W2: " + w2.getData() );
+            assertEquals( 0, (int) c1.data().get() );
+            assertEquals( 100, w1.getData() );
+            assertEquals( 400, w2.getData() );
+        }
+    }
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( MyCompositeContext.class );
+    }
+
+    public static interface MyCompositeContext
+        extends TransientComposite, MyData
+    {
+    }
+
+    public static interface MyData
+    {
+        @UseDefaults
+        Property<Integer> data();
+    }
+
+    static class Worker
+        extends Thread
+    {
+        private MyCompositeContext composite;
+        private int loops;
+        private final String spaces;
+        private int data;
+
+        public Worker( String name, MyCompositeContext composite, int loops, int spaces )
+        {
+            super( name );
+            this.composite = composite;
+            this.loops = loops;
+            StringBuilder builder = new StringBuilder();
+            for( int i = 0; i < spaces; i++ )
+            {
+                builder.append( " " );
+            }
+            this.spaces = builder.toString();
+        }
+
+        public void run()
+        {
+            int counter = 0;
+            int mismatchCounter = 0;
+            Property<Integer> readProperty = composite.data();
+            Property<Integer> writeProperty = composite.data();
+            try
+            {
+                int oldValue = 0;
+                for( int i = 0; i < loops; i++ )
+                {
+                    int value;
+                    value = readProperty.get();
+                    if( oldValue != value )
+                    {
+                        mismatchCounter++;
+                    }
+                    value = value + 1;
+                    oldValue = value;
+                    Thread.sleep( Math.round( Math.random() * 3 ) );
+                    writeProperty.set( value );
+                    counter++;
+                }
+            }
+            catch( InterruptedException e )
+            {
+                e.printStackTrace();
+            }
+            data = composite.data().get();
+            System.out
+                .println( counter + "/" + loops + "    " + data + ", " + mismatchCounter + ", " + System.identityHashCode( readProperty ) + ", " + System
+                    .identityHashCode( writeProperty ) );
+        }
+
+        public int getData()
+        {
+            return data;
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/transients/TransientBuilderFactoryTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/transients/TransientBuilderFactoryTest.java
new file mode 100644
index 0000000..9383841
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/transients/TransientBuilderFactoryTest.java
@@ -0,0 +1,221 @@
+/*
+ *  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.polygene.runtime.transients;
+
+import java.lang.reflect.Method;
+import org.hamcrest.core.IsEqual;
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.composite.NoSuchTransientException;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.concern.GenericConcern;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.library.constraints.annotation.MaxLength;
+
+import static org.junit.Assert.assertThat;
+
+/**
+ * Unit tests for CompositeBuilderFactory.
+ */
+public class TransientBuilderFactoryTest
+{
+
+    /**
+     * Tests that an transient builder cannot be created for an unregistered object.
+     *
+     * @throws Exception expected
+     */
+    @Test( expected = NoSuchTransientException.class )
+    public void newBuilderForUnregisteredComposite()
+        throws Exception
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+            }
+        };
+        assembler.module().newTransientBuilder( AnyComposite.class );
+    }
+
+    /**
+     * Tests that an transient builder cannot be created for a 'null' type.
+     *
+     * @throws Exception expected
+     */
+    @Test( expected = NullPointerException.class )
+    public void newBuilderForNullType()
+        throws Exception
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+            }
+        };
+        assembler.module().newTransientBuilder( null );
+    }
+
+    /**
+     * Tests that a transient composite instance cannot be created for a 'null' type.
+     *
+     * @throws Exception expected
+     */
+    @Test( expected = NullPointerException.class )
+    public void newInstanceForNullType()
+        throws Exception
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+            }
+        };
+        assembler.module().newTransient( null );
+    }
+
+    /**
+     * Tests that an object builder can be created for an registered object.
+     */
+    @Test
+    public void newBuilderForRegisteredComposite()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( AnyComposite.class );
+            }
+        };
+        assembler.module().newTransientBuilder( AnyComposite.class );
+    }
+
+    /**
+     * Tests that an object can be created for an registered object class.
+     */
+    @Test
+    public void newInstanceForRegisteredComposite()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( AnyComposite.class );
+            }
+        };
+        assembler.module().newTransientBuilder( AnyComposite.class );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void testClassAsTransient()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( AnyTransient.class );
+            }
+        };
+
+        AnyTransient anyTransient = assembler.module().newTransient( AnyTransient.class );
+        assertThat( anyTransient.hello( "me" ), new IsEqual<>( "Hello ME from Module 1" ) );
+
+        assertThat( anyTransient.hello( "World" ), new IsEqual<>( "Hello WORLD from ME" ) );
+        anyTransient.hello( "Universe" );
+    }
+
+    public interface AnyComposite
+        extends TransientComposite
+    {
+    }
+
+    public static class CapitalizeConcern
+        extends GenericConcern
+    {
+        @Override
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            if( args != null )
+            {
+                args[ 0 ] = ( (String) args[ 0 ] ).toUpperCase();
+                return next.invoke( proxy, method, args );
+            }
+            else
+            {
+                return next.invoke( proxy, method, args );
+            }
+        }
+    }
+
+    @Concerns( CapitalizeConcern.class )
+    public static class AnyTransient
+        implements TransientComposite
+    {
+        @Structure
+        Module module;
+
+        public String hello( @MaxLength( 5 ) String name )
+        {
+            try
+            {
+                String from = data.foo().get();
+                if( from.length() == 0 )
+                {
+                    from = module.name();
+                }
+                return "Hello " + name + " from " + from;
+            }
+            finally
+            {
+                data.foo().set( name );
+            }
+        }
+
+        @This
+        AnyData data;
+    }
+
+    public interface AnyData
+    {
+        @UseDefaults
+        Property<String> foo();
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/transients/TransientVisibilityTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/transients/TransientVisibilityTest.java
new file mode 100644
index 0000000..19b91e2
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/transients/TransientVisibilityTest.java
@@ -0,0 +1,912 @@
+/*
+ *  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.polygene.runtime.transients;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.NoSuchTransientException;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.ApplicationAssemblerAdapter;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TransientVisibilityTest
+{
+    public static final Identity TEST_IDENTITY = new StringIdentity( "123" );
+    private Energy4Java polygene;
+    private Module module;
+    private Application app;
+    private UnitOfWorkFactory uowf;
+
+    @Before
+    public void setup()
+        throws Exception
+    {
+        polygene = new Energy4Java();
+
+        Assembler[][][] assemblers = new Assembler[][][]
+            {
+                { // Layer Above
+                  {
+                      new AboveAssembler()
+                  }
+                },
+                { // Layer From
+                  { // From Module
+                    new FromAssembler(),
+                    },
+                  { // Beside Module
+                    new BesideAssembler()
+                  }
+                },
+                { // Layer Below
+                  {
+                      new BelowAssembler()
+                  }
+                }
+            };
+        app = polygene.newApplication( new ApplicationAssemblerAdapter( assemblers )
+        {
+        } );
+        app.activate();
+        module = app.findModule( "From Layer", "From" );
+        uowf = module.unitOfWorkFactory();
+    }
+
+    @After
+    public void tearDown()
+        throws Exception
+    {
+        app.passivate();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromServiceWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromServiceWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromServiceWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromServiceWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromServiceWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromServiceWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.aboveModuleVisible();
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.moduleApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.moduleLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.moduleModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.besideApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.besideLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromEntityWhenAccessingBesideModuleVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.besideModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.belowApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromEntityWhenAccessingBelowLayerVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.belowLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromEntityWhenAccessingBelowModuleVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.belowModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromEntityWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.aboveApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromEntityWhenAccessingAboveLayerVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.aboveLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromEntityWhenAccessingAboveModuleVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTITY);
+            entity.aboveModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromValueWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromValueWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromValueWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromValueWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromValueWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromValueWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.aboveModuleVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromTransientWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromTransientWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromTransientWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromTransientWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromTransientWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromTransientWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.aboveModuleVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromObjectWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromObjectWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromObjectWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromObjectWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromObjectWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchTransientException.class )
+    public void givenFromObjectWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.aboveModuleVisible();
+    }
+
+    private static class FromAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.layer().setName( "From Layer" );
+            module.setName( "From" );
+            module.services( FromService.class );
+            module.entities( FromEntity.class );
+            module.transients( FromTransient.class );
+            module.values( FromValue.class );
+            module.objects( FromObject.class );
+
+            module.transients( ModuleApplicationVisible.class ).visibleIn( Visibility.application );
+            module.transients( ModuleLayerVisible.class ).visibleIn( Visibility.layer );
+            module.transients( ModuleModuleVisible.class ).visibleIn( Visibility.module );
+
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    private static class BelowAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.layer().setName( "Below Layer" );
+            module.setName( "Below" );
+            module.transients( BelowApplicationVisible.class ).visibleIn( Visibility.application );
+            module.transients( BelowLayerVisible.class ).visibleIn( Visibility.layer );
+            module.transients( BelowModuleVisible.class ).visibleIn( Visibility.module );
+
+            new EntityTestAssembler().visibleIn( Visibility.application ).assemble( module );
+
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    private static class AboveAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.layer().setName( "Above Layer" );
+            module.setName( "Above" );
+            module.transients( AboveApplicationVisible.class ).visibleIn( Visibility.application );
+            module.transients( AboveLayerVisible.class ).visibleIn( Visibility.layer );
+            module.transients( AboveModuleVisible.class ).visibleIn( Visibility.module );
+
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    private static class BesideAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.setName( "Beside" );
+            module.transients( BesideApplicationVisible.class ).visibleIn( Visibility.application );
+            module.transients( BesideLayerVisible.class ).visibleIn( Visibility.layer );
+            module.transients( BesideModuleVisible.class ).visibleIn( Visibility.module );
+
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    @Mixins( Mixin.class )
+    public interface From
+    {
+        void moduleApplicationVisible();
+
+        void moduleLayerVisible();
+
+        void moduleModuleVisible();
+
+        void besideApplicationVisible();
+
+        void besideLayerVisible();
+
+        void besideModuleVisible();
+
+        void belowApplicationVisible();
+
+        void belowLayerVisible();
+
+        void belowModuleVisible();
+
+        void aboveApplicationVisible();
+
+        void aboveLayerVisible();
+
+        void aboveModuleVisible();
+    }
+
+    public interface FromValue extends From, ValueComposite
+    {
+    }
+
+    public interface FromEntity extends From, EntityComposite
+    {
+    }
+
+    public interface FromService extends From, ServiceComposite
+    {
+    }
+
+    public interface FromTransient extends From, TransientComposite
+    {
+    }
+
+    public static class FromObject extends Mixin
+    {
+    }
+
+    public abstract static class Mixin
+        implements From
+    {
+        @Structure
+        private Module module;
+
+        @Override
+        public void moduleApplicationVisible()
+        {
+            TransientBuilder<ModuleApplicationVisible> builder = module.newTransientBuilder( ModuleApplicationVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void moduleLayerVisible()
+        {
+            TransientBuilder<ModuleLayerVisible> builder = module.newTransientBuilder( ModuleLayerVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void moduleModuleVisible()
+        {
+            TransientBuilder<ModuleModuleVisible> builder = module.newTransientBuilder( ModuleModuleVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void besideApplicationVisible()
+        {
+            TransientBuilder<BesideApplicationVisible> builder = module.newTransientBuilder( BesideApplicationVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void besideLayerVisible()
+        {
+            TransientBuilder<BesideLayerVisible> builder = module.newTransientBuilder( BesideLayerVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void besideModuleVisible()
+        {
+            TransientBuilder<BesideModuleVisible> builder = module.newTransientBuilder( BesideModuleVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void belowApplicationVisible()
+        {
+            TransientBuilder<BelowApplicationVisible> builder = module.newTransientBuilder( BelowApplicationVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void belowLayerVisible()
+        {
+            TransientBuilder<BelowLayerVisible> builder = module.newTransientBuilder( BelowLayerVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void belowModuleVisible()
+        {
+            TransientBuilder<BelowModuleVisible> builder = module.newTransientBuilder( BelowModuleVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void aboveApplicationVisible()
+        {
+            TransientBuilder<AboveApplicationVisible> builder = module.newTransientBuilder( AboveApplicationVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void aboveLayerVisible()
+        {
+            TransientBuilder<AboveLayerVisible> builder = module.newTransientBuilder( AboveLayerVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void aboveModuleVisible()
+        {
+            TransientBuilder<AboveModuleVisible> builder = module.newTransientBuilder( AboveModuleVisible.class );
+            builder.newInstance();
+        }
+    }
+
+    public interface ModuleApplicationVisible extends TransientComposite
+    {
+    }
+
+    public interface ModuleLayerVisible extends TransientComposite
+    {
+    }
+
+    public interface ModuleModuleVisible extends TransientComposite
+    {
+    }
+
+    public interface BesideApplicationVisible extends TransientComposite
+    {
+    }
+
+    public interface BesideLayerVisible extends TransientComposite
+    {
+    }
+
+    public interface BesideModuleVisible extends TransientComposite
+    {
+    }
+
+    public interface BelowApplicationVisible extends TransientComposite
+    {
+    }
+
+    public interface BelowLayerVisible extends TransientComposite
+    {
+    }
+
+    public interface BelowModuleVisible extends TransientComposite
+    {
+    }
+
+    public interface AboveApplicationVisible extends TransientComposite
+    {
+    }
+
+    public interface AboveLayerVisible extends TransientComposite
+    {
+    }
+
+    public interface AboveModuleVisible extends TransientComposite
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/unitofwork/AutoCloseableUoWTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/unitofwork/AutoCloseableUoWTest.java
new file mode 100644
index 0000000..3c10c1f
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/unitofwork/AutoCloseableUoWTest.java
@@ -0,0 +1,89 @@
+/*
+ *  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.polygene.runtime.unitofwork;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.After;
+import org.junit.Test;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Assert that Automatic Resource Management (ie. Java 7 try-with-resources) work on UoWs.
+ */
+public class AutoCloseableUoWTest
+    extends AbstractPolygeneTest
+{
+
+    public interface TestEntity
+    {
+
+        Property<String> mandatory();
+
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( TestEntity.class );
+    }
+
+    @Test
+    public void givenGoodAutoCloseableUoWWhenTryWithResourceExpectSuccess()
+        throws UnitOfWorkCompletionException
+    {
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            EntityBuilder<TestEntity> builder = uow.newEntityBuilder( TestEntity.class );
+            builder.instance().mandatory().set( "Mandatory property" );
+            builder.newInstance();
+            uow.complete();
+        }
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void givenWrongAutoCloseableUoWWhenTryWithResourceExpectSuccess()
+        throws UnitOfWorkCompletionException
+    {
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            uow.newEntity( TestEntity.class );
+            uow.complete();
+        }
+    }
+
+    @After
+    public void afterEachTest()
+    {
+        assertThat( unitOfWorkFactory.isUnitOfWorkActive(), is( false ) );
+    }
+
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/unitofwork/PrivateEntityUnitOfWorkTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/unitofwork/PrivateEntityUnitOfWorkTest.java
new file mode 100644
index 0000000..69775b6
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/unitofwork/PrivateEntityUnitOfWorkTest.java
@@ -0,0 +1,263 @@
+/*
+ *  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.polygene.runtime.unitofwork;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Test;
+
+import static org.apache.polygene.api.common.Visibility.application;
+import static org.junit.Assert.fail;
+
+/**
+ * JAVADOC
+ */
+public class PrivateEntityUnitOfWorkTest
+{
+    private static final Identity TEST_IDENTITY = new StringIdentity( "1" );
+
+    @Structure
+    private UnitOfWorkFactory uowf;
+
+    @Test
+    public void givenAppWithPrivateEntityWhenUnitOfWorkCanSeeItThenCanCommit()
+        throws Exception
+    {
+        System.setProperty( "polygene.compacttrace", "off" );
+
+        Energy4Java is = new Energy4Java();
+        Application app = is.newApplication(
+            applicationFactory ->
+                applicationFactory.newApplicationAssembly( new Assembler[][][]{
+                    {
+                        {
+                            module -> {
+                                module.objects( PrivateEntityUnitOfWorkTest.class );
+                                new DefaultUnitOfWorkAssembler().assemble( module );
+                            }
+                        }
+                    },
+                    {
+                        {
+                            module -> {
+                                module.entities( ProductEntity.class );
+                                module.entities( ProductCatalogEntity.class ).visibleIn( application );
+                                module.values( ProductInfo.class );
+                                new EntityTestAssembler().assemble( module );
+                                new DefaultUnitOfWorkAssembler().assemble( module );
+                            }
+                        }
+                    }
+                } ) );
+        app.activate();
+
+        Module module = app.findModule( "Layer 1", "Module 1" );
+        module.injectTo( this );
+
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+
+        try
+        {
+            unitOfWork.newEntity( ProductEntity.class );
+            fail( "Should not be able to create product here" );
+        }
+        catch( NoSuchEntityTypeException e )
+        {
+            // Ok
+            ProductCatalog catalog = unitOfWork.newEntity( ProductCatalog.class, TEST_IDENTITY);
+            unitOfWork.complete();
+        }
+        unitOfWork = uowf.newUnitOfWork();
+
+        Identity id;
+        try
+        {
+            ProductCatalog catalog = unitOfWork.get( ProductCatalog.class, TEST_IDENTITY);
+            id = catalog.newProduct().identity().get();
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+
+        unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            ProductCatalog catalog = unitOfWork.get( ProductCatalog.class, TEST_IDENTITY);
+            Product product = catalog.findProduct( id );
+            product.price().set( 100 );
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    public interface ProductCatalog
+    {
+        Product newProduct();
+
+        Product findProduct( Identity id );
+    }
+
+    @Mixins( ProductCatalogEntity.ProductRepositoryMixin.class )
+    interface ProductCatalogEntity
+        extends ProductCatalog, EntityComposite
+    {
+        abstract class ProductRepositoryMixin
+            implements ProductCatalog
+        {
+            @Structure
+            private UnitOfWorkFactory uowf;
+
+            @Structure
+            private ValueBuilderFactory vbf;
+
+            public Product newProduct()
+            {
+                ValueBuilder<ProductInfo> vb = vbf.newValueBuilder( ProductInfo.class );
+                vb.prototype().description().set( "Some mundane description" );
+                vb.prototype().weight().set( 1.0f );
+                ProductInfo info = vb.newInstance();
+
+                UnitOfWork uow = uowf.currentUnitOfWork();
+                EntityBuilder<Product> eb = uow.newEntityBuilder( Product.class );
+                eb.instance().name().set( "Product Name" );
+                eb.instance().price().set( 100 );
+                eb.instance().productInfo().set( info );
+                return eb.newInstance();
+            }
+
+            public Product findProduct( Identity id )
+            {
+                UnitOfWork uow = uowf.currentUnitOfWork();
+                return uow.get( Product.class,  id );
+            }
+        }
+    }
+
+    @Mixins( { AccountMixin.class } )
+    public interface AccountComposite
+        extends Account, EntityComposite
+    {
+    }
+
+    public interface Account
+    {
+        Property<Integer> balance();
+
+        void add( int amount );
+
+        void remove( int amount );
+    }
+
+    public static abstract class AccountMixin
+        implements Account
+    {
+        public void add( int amount )
+        {
+            balance().set( balance().get() + amount );
+        }
+
+        public void remove( int amount )
+        {
+            balance().set( balance().get() - amount );
+        }
+    }
+
+    public interface Customer
+    {
+        Association<Account> account();
+
+        Property<String> name();
+    }
+
+    public interface CustomerComposite
+        extends Customer, EntityComposite
+    {
+    }
+
+    public interface LineItem
+    {
+        Association<Product> product();
+    }
+
+    public interface LineItemComposite
+        extends LineItem, EntityComposite
+    {
+    }
+
+    public interface Order
+    {
+        Association<Customer> customer();
+
+        ManyAssociation<LineItem> lineItems();
+    }
+
+    public interface OrderComposite
+        extends Order, EntityComposite
+    {
+    }
+
+    public interface ProductInfo
+        extends ValueComposite
+    {
+        Property<String> description();
+
+        Property<Float> weight();
+    }
+
+    public interface Product extends HasIdentity
+    {
+        Property<String> name();
+
+        Property<Integer> price();
+
+        Property<ProductInfo> productInfo();
+    }
+
+    public interface ProductEntity
+        extends Product, EntityComposite
+    {
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/unitofwork/RemovalTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/unitofwork/RemovalTest.java
new file mode 100644
index 0000000..843c103
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/unitofwork/RemovalTest.java
@@ -0,0 +1,163 @@
+/*
+ *  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.polygene.runtime.unitofwork;
+
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.junit.Test;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class RemovalTest
+    extends AbstractPolygeneTest
+{
+
+    private static final Identity TEST_IDENTITY = new StringIdentity( "123" );
+
+    public void assemble(ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( Abc.class );
+    }
+
+    @Test
+    public void givenUnitOfWorkHasBeenCreateWhenCreatingNewEntityThenFindNewEntityWithGet()
+        throws Exception
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            EntityBuilder<Abc> builder = uow.newEntityBuilder( Abc.class, TEST_IDENTITY);
+            builder.instance().name().set( "Niclas" );
+            builder.newInstance();
+            uow.complete();
+            uow = unitOfWorkFactory.newUnitOfWork();
+            Abc abc = uow.get( Abc.class, TEST_IDENTITY);
+            assertEquals( "Niclas", abc.name().get() );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void givenEntityCreatedWhenRemovingEntityThenFindNewEntityShouldNotExist()
+        throws Exception
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            EntityBuilder<Abc> builder = uow.newEntityBuilder( Abc.class, TEST_IDENTITY);
+            builder.instance().name().set( "Niclas" );
+            builder.newInstance();
+            uow.complete();
+            uow = unitOfWorkFactory.newUnitOfWork();
+            Abc abc = uow.get( Abc.class, TEST_IDENTITY);
+            assertEquals( "Niclas", abc.name().get() );
+            uow.remove( abc );
+            uow.complete();
+            uow = unitOfWorkFactory.newUnitOfWork();
+            uow.get( Abc.class, TEST_IDENTITY);
+            fail( "This '123' entity should not exist." );
+        }
+        catch( NoSuchEntityException e )
+        {
+            // Expected.
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void givenDetachedEntityWhenRemovingEntityThenFindNewEntityShouldNotExist()
+        throws Exception
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            EntityBuilder<Abc> builder = uow.newEntityBuilder( Abc.class, TEST_IDENTITY);
+            builder.instance().name().set( "Niclas" );
+            Abc abc = builder.newInstance();
+            uow.complete();
+            uow = unitOfWorkFactory.newUnitOfWork();
+            abc = uow.get( abc );  // Attach the detached entity to 'uow' session.
+            uow.remove( abc );
+            uow.complete();
+            uow = unitOfWorkFactory.newUnitOfWork();
+            uow.get( Abc.class, TEST_IDENTITY);
+            fail( "This '123' entity should not exist." );
+        }
+        catch( NoSuchEntityException e )
+        {
+            // Expected.
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void givenEntityCreatedWhenRemovingEntityBeforeCompletingUowThenFindNewEntityShouldNotExist()
+        throws Exception
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            EntityBuilder<Abc> builder = uow.newEntityBuilder( Abc.class, TEST_IDENTITY);
+            builder.instance().name().set( "Niclas" );
+            Abc abc = builder.newInstance();
+            uow.remove( abc );
+            uow.complete();
+            uow = unitOfWorkFactory.newUnitOfWork();
+            uow.get( Abc.class, TEST_IDENTITY);
+            fail( "This '123' entity should not exist." );
+        }
+        catch( NoSuchEntityException e )
+        {
+            // Expected.
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    public interface Abc
+        extends EntityComposite
+    {
+        Property<String> name();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/unitofwork/UnitOfWorkFactoryTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/unitofwork/UnitOfWorkFactoryTest.java
new file mode 100644
index 0000000..a7adb40
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/unitofwork/UnitOfWorkFactoryTest.java
@@ -0,0 +1,146 @@
+/*
+ *  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.polygene.runtime.unitofwork;
+
+import org.junit.Test;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+public class UnitOfWorkFactoryTest
+    extends AbstractPolygeneTest
+{
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( AccountComposite.class,
+                         OrderComposite.class,
+                         ProductEntity.class,
+                         CustomerComposite.class );
+
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Test
+    public void testUnitOfWork()
+        throws Exception
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+
+        // Create product
+        EntityBuilder<ProductEntity> cb = unitOfWork.newEntityBuilder( ProductEntity.class );
+        cb.instance().name().set( "Chair" );
+        cb.instance().price().set( 57 );
+        Product chair = cb.newInstance();
+
+        String actual = chair.name().get();
+        org.junit.Assert.assertThat( "Chair.name()", actual, org.hamcrest.CoreMatchers.equalTo( "Chair" ) );
+        org.junit.Assert.assertThat( "Chair.price()", chair.price().get(), org.hamcrest.CoreMatchers.equalTo( 57 ) );
+
+        unitOfWork.complete();
+    }
+
+    @Mixins( { AccountMixin.class } )
+    public interface AccountComposite
+        extends Account, EntityComposite
+    {
+    }
+
+    public interface Account
+    {
+        Property<Integer> balance();
+
+        void add( int amount );
+
+        void remove( int amount );
+    }
+
+    public static abstract class AccountMixin
+        implements Account
+    {
+        public void add( int amount )
+        {
+            balance().set( balance().get() + amount );
+        }
+
+        public void remove( int amount )
+        {
+            balance().set( balance().get() - amount );
+        }
+    }
+
+    public interface Customer
+    {
+        Association<Account> account();
+
+        Property<String> name();
+    }
+
+    public interface CustomerComposite
+        extends Customer, EntityComposite
+    {
+    }
+
+    public interface LineItem
+    {
+        Association<Product> product();
+    }
+
+    public interface LineItemComposite
+        extends LineItem, EntityComposite
+    {
+    }
+
+    public interface Order
+    {
+        Association<Customer> customer();
+
+        ManyAssociation<LineItem> lineItems();
+    }
+
+    public interface OrderComposite
+        extends Order, EntityComposite
+    {
+    }
+
+    public interface Product
+    {
+        @UseDefaults
+        Property<String> name();
+
+        @UseDefaults
+        Property<Integer> price();
+    }
+
+    public interface ProductEntity
+        extends Product, EntityComposite
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/util/AnnotationsTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/util/AnnotationsTest.java
new file mode 100644
index 0000000..cc00ba1
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/util/AnnotationsTest.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.runtime.util;
+
+import java.lang.reflect.Type;
+import java.util.Collection;
+import org.junit.Test;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.sideeffect.SideEffects;
+import org.apache.polygene.api.util.Annotations;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+public class AnnotationsTest
+{
+    @Mixins( value = AnnotatedClass.class )
+    interface AnnotatedClass<T>
+    {
+        Collection<T> list();
+    }
+
+    @Test
+    public void getAnnotationOrNull()
+        throws NoSuchMethodException
+    {
+        assertNotNull( "Mixins annotation found", Annotations.annotationOn( AnnotatedClass.class, Mixins.class ) );
+
+        assertNull( "No SideEffects annotation found", Annotations.annotationOn( AnnotatedClass.class, SideEffects.class ) );
+
+        final Type returnType = AnnotatedClass.class.getDeclaredMethod( "list" ).getGenericReturnType();
+        assertNull( "Null on no class type", Annotations.annotationOn( returnType, Mixins.class ) );
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/value/AssociationToValueTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/value/AssociationToValueTest.java
new file mode 100644
index 0000000..18b6935
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/value/AssociationToValueTest.java
@@ -0,0 +1,211 @@
+/*
+ *  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.polygene.runtime.value;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.BiFunction;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkConcern;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
+import static org.junit.Assert.assertThat;
+
+public class AssociationToValueTest extends AbstractPolygeneTest
+{
+    @Service
+    PersonRepository repo;
+
+    @Test
+    public void givenAdamWhenRequestingChildrenListExpectAbelAndKain()
+    {
+        Person adam = repo.findPersonByName( "Adam" );
+        Person abel = repo.findPersonByName( "Abel" );
+        Person kain = repo.findPersonByName( "Kain" );
+        List<Person> children = repo.transact( adam, ( p, uow ) -> uow.toValueList( p.children() ) );
+        assertThat( children, containsInAnyOrder( kain, abel ) );
+    }
+
+    @Test
+    public void givenAbelWhenRequestingChildrenSetExpectAdamAndEve()
+    {
+        Person abel = repo.findPersonByName( "Abel" );
+        Person adam = repo.findPersonByName( "Adam" );
+        Person eve = repo.findPersonByName( "Eve" );
+        Set<Person> children = repo.transact( abel, ( p, uow ) -> uow.toValueSet( p.children() ) );
+        assertThat( children, containsInAnyOrder( adam, eve ) );
+    }
+
+    @Test
+    public void givenBobWhenRequestingRolesExpectAllRolesWithCorrectPerson()
+    {
+        Person bob = repo.findPersonByName( "Bob" );
+        Person alice = repo.findPersonByName( "Alice" );
+        Person john = repo.findPersonByName( "John" );
+        Person jane = repo.findPersonByName( "Jane" );
+        Person kim = repo.findPersonByName( "Kim" );
+        Person robin = repo.findPersonByName( "Robin" );
+        Map<String, Person> roles = repo.transact( bob, ( p, uow ) -> uow.toValueMap( p.roles() ) );
+        assertThat( roles.keySet(), containsInAnyOrder( "spouse", "mechanic", "maid", "plumber", "electrician" ) );
+        assertThat( roles.values(), containsInAnyOrder( alice, john, jane, kim, robin ) );
+    }
+
+    @Test
+    public void givenLouisWhenRequestingRolesExpectAllRolesOfMarie()
+    {
+        Person louis = repo.findPersonByName( "Louis" );
+        Person marie = repo.findPersonByName( "Marie" );
+        Map<String, Person> roles = repo.transact( louis, ( p, uow ) -> uow.toValueMap( p.roles() ) );
+        assertThat( roles.keySet(), containsInAnyOrder( "spouse", "lover", "death-mate" ) );
+        assertThat( roles.values(), containsInAnyOrder( marie, marie, marie ) );
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( Person.class );
+        module.values( Person.class );
+        module.services( PersonRepository.class ).withConcerns( UnitOfWorkConcern.class );
+        module.services( MemoryEntityStoreService.class );
+
+        module.services( Runnable.class )
+            .withMixins( LoadData.class )
+            .withConcerns( UnitOfWorkConcern.class )
+            .instantiateOnStartup();
+    }
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        serviceFinder.findService( Runnable.class ).get().run();
+    }
+
+    public interface Person extends HasIdentity
+    {
+        ManyAssociation<Person> children();
+
+        NamedAssociation<Person> roles();
+    }
+
+    @Mixins( PersonRepositoryMixin.class )
+    public interface PersonRepository
+    {
+        @UnitOfWorkPropagation
+        <T, R> R transact( T arg, BiFunction<T, UnitOfWork, R> closure );
+
+        @UnitOfWorkPropagation
+        Person findPersonByName( String name );
+    }
+
+    protected static class PersonRepositoryMixin
+        implements PersonRepository
+    {
+        @Structure
+        UnitOfWorkFactory unitOfWorkFactory;
+
+        @Override
+        public <T, R> R transact( T arg, BiFunction<T, UnitOfWork, R> closure )
+        {
+            UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+            return closure.apply( arg, uow );
+        }
+
+        @Override
+        public Person findPersonByName( String name )
+        {
+            UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+            return uow.toValue( Person.class, uow.get( Person.class, new StringIdentity( name ) ) );
+        }
+    }
+
+    public static class LoadData
+        implements Runnable
+    {
+        @Structure
+        UnitOfWorkFactory uowf;
+
+        @Override
+        @UnitOfWorkPropagation
+        public void run()
+        {
+            Person bob = createPerson( "Bob" );
+            Person alice = createPerson( "Alice" );
+            Person john = createPerson( "John" );
+            Person jane = createPerson( "Jane" );
+            Person kim = createPerson( "Kim" );
+            Person robin = createPerson( "Robin" );
+            Person william = createPerson( "William" );
+            Person adam = createPerson( "Adam" );
+            Person eve = createPerson( "Eve" );
+            Person abel = createPerson( "Abel" );
+            Person kain = createPerson( "Kain" );
+            Person louis = createPerson( "Louis" );
+            Person marie = createPerson( "Marie" );
+            Person romeo = createPerson( "Romeo" );
+            Person juliette = createPerson( "Juliette" );
+            adam.children().add( abel );
+            adam.children().add( kain );
+            eve.children().add( abel );
+            eve.children().add( kain );
+            abel.children().add( adam );
+            abel.children().add( eve );
+            abel.children().add( adam );
+            abel.children().add( eve );
+            abel.children().add( eve );
+            bob.roles().put( "spouse", alice );
+            bob.roles().put( "mechanic", john );
+            bob.roles().put( "maid", jane );
+            bob.roles().put( "plumber", kim );
+            bob.roles().put( "electrician", robin );
+            louis.roles().put( "spouse", marie );
+            louis.roles().put( "lover", marie );
+            louis.roles().put( "death-mate", marie );
+            juliette.roles().put( "lover", romeo );
+            juliette.roles().put( "author", william );
+            romeo.roles().put( "lover", juliette );
+            romeo.roles().put( "author", william );
+        }
+
+        private Person createPerson( String name )
+        {
+            UnitOfWork uow = uowf.currentUnitOfWork();
+            return uow.newEntity( Person.class, new StringIdentity( name ) );
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/value/NestedValueBuilderTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/value/NestedValueBuilderTest.java
new file mode 100644
index 0000000..45859de
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/value/NestedValueBuilderTest.java
@@ -0,0 +1,188 @@
+/*
+ *  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.polygene.runtime.value;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.junit.Assert.fail;
+
+public class NestedValueBuilderTest
+    extends AbstractPolygeneTest
+{
+
+    static interface InnerValue
+        extends ValueComposite
+    {
+
+        Property<List<String>> listProp();
+
+        Property<Map<String, String>> mapProp();
+    }
+
+    static interface InnerDefaultedValue
+        extends ValueComposite
+    {
+
+        @UseDefaults
+        Property<List<String>> listPropDefault();
+
+        @UseDefaults
+        Property<Map<String, String>> mapPropDefault();
+    }
+
+    static interface OuterValue
+        extends ValueComposite
+    {
+
+        Property<List<InnerValue>> innerListProp();
+    }
+
+    static interface OuterDefaultedValue
+        extends ValueComposite
+    {
+
+        @UseDefaults
+        Property<List<InnerDefaultedValue>> innerListPropDefault();
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.values( InnerValue.class, InnerDefaultedValue.class, OuterValue.class, OuterDefaultedValue.class );
+    }
+
+    @Test
+    public void testInner()
+    {
+        ValueBuilder<InnerValue> innerBuilder = valueBuilderFactory.newValueBuilder( InnerValue.class );
+        InnerValue inner = innerBuilder.prototype();
+        inner.listProp().set( new ArrayList<>() );
+        inner.mapProp().set( new HashMap<>() );
+        inner = innerBuilder.newInstance();
+        // If we reach this point, value creation went well
+        try
+        {
+            inner.listProp().get().add( "Should be immutable now!" ); // Must not be allowed
+            fail( "List is not immutable!" );
+        }
+        catch( UnsupportedOperationException e )
+        {
+            // expected
+        }
+        try
+        {
+            inner.mapProp().get().put( "Should be immutable now!", "" ); // Must not be allowed
+            fail( "Map is not immutable!" );
+        }
+        catch( UnsupportedOperationException e )
+        {
+            // expected
+        }
+    }
+
+    @Test
+    public void testOuter()
+    {
+        ValueBuilder<InnerValue> innerBuilder = valueBuilderFactory.newValueBuilder( InnerValue.class );
+        InnerValue innerPrototype = innerBuilder.prototype();
+        innerPrototype.listProp().set( new ArrayList<>() );
+        innerPrototype.mapProp().set( new HashMap<>() );
+        InnerValue innerInstance = innerBuilder.newInstance();
+        ValueBuilder<OuterValue> outerBuilder = valueBuilderFactory.newValueBuilder( OuterValue.class );
+        OuterValue outerPrototype = outerBuilder.prototype();
+        List<InnerValue> inners = new ArrayList<>();
+        inners.add( innerInstance );
+        outerPrototype.innerListProp().set( inners );
+        OuterValue outerInstance = outerBuilder.newInstance();
+        System.out.println( outerInstance.toString() );
+        // If we reach this point, value creation went well
+        try
+        {
+            outerInstance.innerListProp().get().add( innerInstance ); // Must not be allowed
+            fail( "List is not immutable!" );
+        }
+        catch( UnsupportedOperationException e )
+        {
+            // expected
+        }
+    }
+
+    @Test
+    public void testDefaultedInner()
+    {
+        ValueBuilder<InnerDefaultedValue> innerBuilder = valueBuilderFactory.newValueBuilder( InnerDefaultedValue.class );
+        InnerDefaultedValue inner = innerBuilder.newInstance();
+        // If we reach this point, value creation went well
+        try
+        {
+            inner.listPropDefault().get().add( "Should not work!" ); // Must not be allowed
+            fail( "List is not immutable!" );
+        }
+        catch( UnsupportedOperationException e )
+        {
+            // expected
+        }
+        try
+        {
+            inner.mapPropDefault().get().put( "Should not work!", "" ); // Must not be allowed
+            fail( "List is not immutable!" );
+        }
+        catch( UnsupportedOperationException e )
+        {
+            // expected
+        }
+    }
+
+    @Test
+    public void testDefaultedOuter()
+    {
+        ValueBuilder<InnerDefaultedValue> innerBuilder = valueBuilderFactory.newValueBuilder( InnerDefaultedValue.class );
+        InnerDefaultedValue innerInstance = innerBuilder.newInstance();
+        ValueBuilder<OuterDefaultedValue> outerBuilder = valueBuilderFactory.newValueBuilder( OuterDefaultedValue.class );
+        OuterDefaultedValue outerPrototype = outerBuilder.prototype();
+        List<InnerDefaultedValue> inners = new ArrayList<>();
+        inners.add( innerInstance );
+        outerPrototype.innerListPropDefault().set( inners );
+        OuterDefaultedValue outerInstance = outerBuilder.newInstance();
+        System.out.println( outerPrototype.toString() );
+        // If we reach this point, value creation went well
+        try
+        {
+            outerInstance.innerListPropDefault().get().add( innerInstance ); // Must not be allowed
+            fail( "List is not immutable!" );
+        }
+        catch( UnsupportedOperationException e )
+        {
+            // expected
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueComposite2Test.java b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueComposite2Test.java
new file mode 100644
index 0000000..3dbe3d8
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueComposite2Test.java
@@ -0,0 +1,141 @@
+/*
+ *  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.polygene.runtime.value;
+
+import java.security.Guard;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+public class ValueComposite2Test
+{
+    @Test
+    public void testServiceAndStructureInjectionsAllowedInValueComposite()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler app = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.values( SomeValue.class );
+                module.services( DummyService.class );
+                new DefaultUnitOfWorkAssembler().assemble( module );
+            }
+        };
+        ValueBuilder<Some> builder = app.module().newValueBuilder( Some.class );
+        Some prototype = builder.prototype();
+        Property<String> otherProperty = prototype.other();
+        otherProperty.set( "Abc" );
+        Some value = builder.newInstance();
+        Assert.assertEquals( value.other().get(), "Abc" );
+    }
+
+    @Test( expected = AssemblyException.class )
+    public void testUsesAnnotationIsNotAllowedInValueComposite()
+        throws ActivationException, AssemblyException
+    {
+        new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.values( SomeValue2.class );
+            }
+        };
+    }
+
+    public interface Some
+    {
+        DummyService service();
+
+        Module module();
+
+        Property<String> other();
+    }
+
+    @Mixins( SomeMixin.class )
+    public interface SomeValue
+        extends Some, ValueComposite
+    {
+    }
+
+    public static abstract class SomeMixin
+        implements Some
+    {
+        @Service
+        DummyService service;
+        @Structure
+        Module module;
+
+        public DummyService service()
+        {
+            return service;
+        }
+
+        public Module module()
+        {
+            return module;
+        }
+    }
+
+    @Mixins( SomeMixin2.class )
+    public interface SomeValue2
+        extends Some, ValueComposite
+    {
+    }
+
+    public static abstract class SomeMixin2
+        implements Some
+    {
+        @Uses
+        Guard illegal;
+
+        public DummyService service()
+        {
+            return null;
+        }
+
+        public Module module()
+        {
+            return null;
+        }
+    }
+
+    public static interface DummyService
+        extends ServiceComposite
+    {
+    }
+}
+
+
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueCompositeBasicsTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueCompositeBasicsTest.java
new file mode 100644
index 0000000..bc538f1
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueCompositeBasicsTest.java
@@ -0,0 +1,100 @@
+/*
+ *  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.polygene.runtime.value;
+
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+public class ValueCompositeBasicsTest
+    extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.values( SomeValue.class );
+    }
+
+    @Test
+    public void testEqualsForValueComposite()
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        builder.prototypeFor( SomeInternalState.class ).name().set( "Niclas" );
+        assertEquals("Niclas", builder.prototype().name());
+        SomeValue value1 = builder.newInstance();
+        SomeValue value2 = builder.newInstance();
+        builder.prototypeFor( SomeInternalState.class ).name().set( "Niclas2" );
+        SomeValue value3 = builder.newInstance();
+        assertEquals( value1, value2 );
+        assertFalse( value1.equals( value3 ) );
+    }
+
+    @Test
+    public void testToStringForValueComposite()
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        builder.prototypeFor( SomeInternalState.class ).name().set( "Niclas" );
+        SomeValue underTest = builder.newInstance();
+        assertEquals( "{\"name\":\"Niclas\"}", underTest.toString() );
+    }
+
+    @Test
+    public void testToJSonForValueComposite()
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        builder.prototypeFor( SomeInternalState.class ).name().set( "Niclas" );
+        SomeValue underTest = builder.newInstance();
+        assertEquals( "{\"name\":\"Niclas\"}", underTest.toString() );
+    }
+
+    public abstract static class SomeMixin
+        implements SomeValue
+    {
+        @This
+        private SomeInternalState state;
+
+        @Override
+        public String name()
+        {
+            return state.name().get();
+        }
+    }
+
+    @Mixins( SomeMixin.class )
+    public interface SomeValue
+        //extends ValueComposite
+    {
+        String name();
+    }
+
+    public interface SomeInternalState
+    {
+        Property<String> name();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueEqualityTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueEqualityTest.java
new file mode 100644
index 0000000..fa57b28
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueEqualityTest.java
@@ -0,0 +1,241 @@
+/*
+ *  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.polygene.runtime.value;
+
+import org.junit.Test;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.runtime.property.PropertyEqualityTest.AnotherSome;
+import org.apache.polygene.runtime.property.PropertyEqualityTest.Other;
+import org.apache.polygene.runtime.property.PropertyEqualityTest.PrimitivesValue;
+import org.apache.polygene.runtime.property.PropertyEqualityTest.Some;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertThat;
+import static org.apache.polygene.runtime.property.PropertyEqualityTest.buildAnotherSomeValue;
+import static org.apache.polygene.runtime.property.PropertyEqualityTest.buildAnotherSomeValueWithDifferentState;
+import static org.apache.polygene.runtime.property.PropertyEqualityTest.buildOtherValue;
+import static org.apache.polygene.runtime.property.PropertyEqualityTest.buildPrimitivesValue;
+import static org.apache.polygene.runtime.property.PropertyEqualityTest.buildSomeValue;
+import static org.apache.polygene.runtime.property.PropertyEqualityTest.buildSomeValueWithDifferentState;
+
+/**
+ * Assert that Value equals/hashcode methods combine ValueDescriptor and ValueState.
+ */
+public class ValueEqualityTest
+    extends AbstractPolygeneTest
+{
+
+    //
+    // --------------------------------------:: Types under test ::-----------------------------------------------------
+    //
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.values( PrimitivesValue.class, Some.class, AnotherSome.class, Other.class );
+    }
+
+    //
+    // -------------------------------:: ValueDescriptor equality tests ::----------------------------------------------
+    //
+    @Test
+    public void givenValuesOfTheSameTypeWhenTestingValueDescriptorEqualityExpectEquals()
+    {
+        Some some = buildSomeValue(valueBuilderFactory);
+        ValueDescriptor someDescriptor = polygene.api().valueDescriptorFor( some );
+
+        Some other = buildSomeValue( valueBuilderFactory );
+        ValueDescriptor otherDescriptor = polygene.api().valueDescriptorFor( other );
+
+        assertThat( "ValueDescriptors equal",
+                    someDescriptor,
+                    equalTo( otherDescriptor ) );
+        assertThat( "ValueDescriptors hashcode equal",
+                    someDescriptor.hashCode(),
+                    equalTo( otherDescriptor.hashCode() ) );
+    }
+
+    @Test
+    public void givenValuesOfCommonTypesWhenTestingValueDescriptorEqualityExpectNotEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        ValueDescriptor someDescriptor = polygene.api().valueDescriptorFor( some );
+
+        PrimitivesValue primitive = buildPrimitivesValue( valueBuilderFactory );
+        ValueDescriptor primitiveDescriptor = polygene.api().valueDescriptorFor( primitive );
+
+        assertThat( "ValueDescriptors not equal",
+                    someDescriptor,
+                    not( equalTo( primitiveDescriptor ) ) );
+        assertThat( "ValueDescriptors hashcode not equal",
+                    someDescriptor.hashCode(),
+                    not( equalTo( primitiveDescriptor.hashCode() ) ) );
+    }
+
+    @Test
+    public void givenValuesOfDifferentTypesWhenTestingValueDescriptorEqualityExpectNotEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        ValueDescriptor someDescriptor = polygene.api().valueDescriptorFor( some );
+
+        Other other = buildOtherValue( valueBuilderFactory );
+        ValueDescriptor otherDescriptor = polygene.api().valueDescriptorFor( other );
+
+        assertThat( "ValueDescriptors not equal",
+                    someDescriptor,
+                    not( equalTo( otherDescriptor ) ) );
+        assertThat( "ValueDescriptors hashcode not equal",
+                    someDescriptor.hashCode(),
+                    not( equalTo( otherDescriptor.hashCode() ) ) );
+    }
+
+    //
+    // ---------------------------------:: Value State equality tests ::------------------------------------------------
+    //
+    @Test
+    public void givenValuesOfSameTypesAndSameStateWhenTestingValueStateEqualityExpectEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        AssociationStateHolder someState = polygene.spi().stateOf( (ValueComposite) some );
+
+        Some some2 = buildSomeValue( valueBuilderFactory );
+        AssociationStateHolder some2State = polygene.spi().stateOf( (ValueComposite) some2 );
+
+        assertThat( "ValueStates equal",
+                    someState,
+                    equalTo( some2State ) );
+        assertThat( "ValueStates hashcode equal",
+                    someState.hashCode(),
+                    equalTo( some2State.hashCode() ) );
+    }
+
+    @Test
+    public void givenValuesOfSameTypesAndDifferentStateWhenTestingValueStateEqualityExpectNotEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        AssociationStateHolder someState = polygene.spi().stateOf( (ValueComposite) some );
+
+        Some some2 = buildSomeValueWithDifferentState( valueBuilderFactory );
+        AssociationStateHolder some2State = polygene.spi().stateOf( (ValueComposite) some2 );
+
+        assertThat( "ValueStates not equal",
+                    someState,
+                    not( equalTo( some2State ) ) );
+        assertThat( "ValueStates hashcode not equal",
+                    someState.hashCode(),
+                    not( equalTo( some2State.hashCode() ) ) );
+    }
+
+    @Test
+    public void givenValuesOfDifferentTypesAndSameStateWhenTestingValueStateEqualityExpectEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        AssociationStateHolder someState = polygene.spi().stateOf( (ValueComposite) some );
+
+        AnotherSome anotherSome = buildAnotherSomeValue( valueBuilderFactory );
+        AssociationStateHolder anotherSomeState = polygene.spi().stateOf( (ValueComposite) anotherSome );
+
+        assertThat( "ValueStates equal",
+                    someState,
+                    equalTo( anotherSomeState ) );
+        assertThat( "ValueStates hashcode equal",
+                    someState.hashCode(),
+                    equalTo( anotherSomeState.hashCode() ) );
+    }
+
+    @Test
+    public void givenValuesOfDifferentTypesAndDifferentStateWhenTestingValueStateEqualityExpectNotEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        AssociationStateHolder someState = polygene.spi().stateOf( (ValueComposite) some );
+
+        AnotherSome anotherSome = buildAnotherSomeValueWithDifferentState( valueBuilderFactory );
+        AssociationStateHolder anotherSomeState = polygene.spi().stateOf( (ValueComposite) anotherSome );
+
+        assertThat( "ValueStates not equal",
+                    someState,
+                    not( equalTo( anotherSomeState ) ) );
+        assertThat( "ValueStates hashcode not equal",
+                    someState.hashCode(),
+                    not( equalTo( anotherSomeState.hashCode() ) ) );
+    }
+
+    //
+    // ------------------------------------:: Value equality tests ::---------------------------------------------------
+    //
+    @Test
+    public void givenValuesOfSameTypesAndSameStateWhenTestingValueEqualityExpectEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        Some some2 = buildSomeValue( valueBuilderFactory );
+        assertThat( "Values equal",
+                    some,
+                    equalTo( some2 ) );
+        assertThat( "Values hashcode equal",
+                    some.hashCode(),
+                    equalTo( some2.hashCode() ) );
+    }
+
+    @Test
+    public void givenValuesOfTheSameTypeWithDifferentStateWhenTestingValueEqualityExpectNotEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        Some some2 = buildSomeValueWithDifferentState( valueBuilderFactory );
+        assertThat( "Values not equals",
+                    some,
+                    not( equalTo( some2 ) ) );
+        assertThat( "Values hashcode not equals",
+                    some.hashCode(),
+                    not( equalTo( some2.hashCode() ) ) );
+    }
+
+    @Test
+    public void givenValuesOfDifferentTypesAndSameStateWhenTestingValueEqualityExpectNotEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        Some anotherSome = buildAnotherSomeValue( valueBuilderFactory );
+
+        assertThat( "Values not equal",
+                    some,
+                    not( equalTo( anotherSome ) ) );
+        assertThat( "Values hashcode not equal",
+                    some.hashCode(),
+                    not( equalTo( anotherSome.hashCode() ) ) );
+    }
+
+    @Test
+    public void givenValuesOfDifferentTypesAndDifferentStateWhenTestingValueEqualityExpectNotEquals()
+    {
+        Some some = buildSomeValue( valueBuilderFactory );
+        Some anotherSome = buildAnotherSomeValueWithDifferentState( valueBuilderFactory );
+        assertThat( "Values not equal",
+                    some,
+                    not( equalTo( anotherSome ) ) );
+        assertThat( "Values hashcode not equal",
+                    some.hashCode(),
+                    not( equalTo( anotherSome.hashCode() ) ) );
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueInjectionDeserializationTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueInjectionDeserializationTest.java
new file mode 100644
index 0000000..3a77b79
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueInjectionDeserializationTest.java
@@ -0,0 +1,133 @@
+/*
+ *  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.polygene.runtime.value;
+
+import org.apache.polygene.api.identity.Identity;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+public class ValueInjectionDeserializationTest
+    extends AbstractPolygeneTest
+{
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( Niclas.class );
+        module.values( SomeValue.class );
+        module.services( DummyService.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Test
+    public void testThatServiceAndStructureInjectionWorkForValueWhenEntityRetrievedFromStore()
+        throws Exception
+    {
+        UnitOfWork uow = null;
+        try
+        {
+            ValueBuilder<Some> builder = valueBuilderFactory.newValueBuilder( Some.class );
+            builder.prototype().data().set( "Niclas" );
+            Some value = builder.newInstance();
+
+            uow = unitOfWorkFactory.newUnitOfWork();
+            EntityBuilder<Niclas> eb = uow.newEntityBuilder( Niclas.class );
+            eb.instance().value().set( value );
+            Niclas niclas1 = eb.newInstance();
+            Identity id = niclas1.identity().get();
+            uow.complete();
+
+            uow = unitOfWorkFactory.newUnitOfWork();
+            Niclas niclas2 = uow.get( Niclas.class, id );
+            Some someValue = niclas2.value().get();
+            Assert.assertEquals( someValue.data().get(), "Niclas" );
+            Assert.assertNotNull( someValue.module() );
+            Assert.assertNotNull( someValue.service() );
+        }
+        finally
+        {
+            if( uow != null )
+            {
+                uow.discard();
+            }
+        }
+    }
+
+    public interface Niclas
+        extends EntityComposite
+    {
+        Property<Some> value();
+    }
+
+    public interface Some
+    {
+        DummyService service();
+
+        Module module();
+
+        Property<String> data();
+    }
+
+    @Mixins( SomeMixin.class )
+    public interface SomeValue
+        extends Some, ValueComposite
+    {
+    }
+
+    public static abstract class SomeMixin
+        implements Some
+    {
+        @Service
+        DummyService service;
+        @Structure
+        Module module;
+
+        public DummyService service()
+        {
+            return service;
+        }
+
+        public Module module()
+        {
+            return module;
+        }
+    }
+
+    public interface DummyService
+        extends ServiceComposite
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueSerializationRegressionTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueSerializationRegressionTest.java
new file mode 100644
index 0000000..fe8cdd8
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueSerializationRegressionTest.java
@@ -0,0 +1,74 @@
+/*
+ *  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.polygene.runtime.value;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+public class ValueSerializationRegressionTest extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( SimpleEntity.class );
+        module.entities( DualFaced.class );
+        module.values( DualFaced.class );
+        module.services( MemoryEntityStoreService.class );
+    }
+
+    @Test
+    public void givenNewValueWhenConvertingToEntityExpectNewEntityInStore()
+        throws UnitOfWorkCompletionException
+    {
+        ValueBuilder<DualFaced> builder = valueBuilderFactory.newValueBuilder( DualFaced.class );
+        builder.prototype().identity().set( new StringIdentity( "1234" ) );
+        builder.prototype().name().set( "Hedhman" );
+        DualFaced value = builder.newInstance();
+    }
+
+    public interface SimpleEntity extends HasIdentity
+    {
+        Property<String> name();
+    }
+
+    public interface DualFaced extends HasIdentity
+    {
+        Property<String> name();
+
+        Association<SimpleEntity> simple();
+
+        ManyAssociation<SimpleEntity> simples();
+
+        NamedAssociation<SimpleEntity> namedSimples();
+    }
+}
+
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueVisibilityTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueVisibilityTest.java
new file mode 100644
index 0000000..4dff8ae
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueVisibilityTest.java
@@ -0,0 +1,912 @@
+/*
+ *  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.polygene.runtime.value;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.NoSuchValueException;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.ApplicationAssemblerAdapter;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ValueVisibilityTest
+{
+
+    public static final Identity TEST_IDENTIY = new StringIdentity( "123" );
+    private Energy4Java polygene;
+    private Module module;
+    private Application app;
+    private UnitOfWorkFactory uowf;
+
+    @Before
+    public void setup()
+        throws Exception
+    {
+        polygene = new Energy4Java();
+
+        Assembler[][][] assemblers = new Assembler[][][]
+            {
+                { // Layer Above
+                  {
+                      new AboveAssembler()
+                  }
+                },
+                { // Layer From
+                  { // From Module
+                    new FromAssembler(),
+                  },
+                  { // Beside Module
+                    new BesideAssembler()
+                  }
+                },
+                { // Layer Below
+                  {
+                      new BelowAssembler()
+                  }
+                }
+            };
+        app = polygene.newApplication( new ApplicationAssemblerAdapter( assemblers )
+        {
+        } );
+        app.activate();
+        module = app.findModule( "From Layer", "From" );
+        uowf = module.unitOfWorkFactory();
+    }
+
+    @After
+    public void tearDown()
+        throws Exception
+    {
+        app.passivate();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromServiceWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromServiceWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromServiceWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromServiceWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromServiceWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromServiceWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromServiceWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromService service = module.findService( FromService.class ).get();
+        service.aboveModuleVisible();
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTIY);
+            entity.moduleApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTIY);
+            entity.moduleLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTIY);
+            entity.moduleModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTIY);
+            entity.besideApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTIY);
+            entity.besideLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromEntityWhenAccessingBesideModuleVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTIY);
+            entity.besideModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromEntityWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTIY);
+            entity.belowApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromEntityWhenAccessingBelowLayerVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTIY);
+            entity.belowLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromEntityWhenAccessingBelowModuleVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTIY);
+            entity.belowModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromEntityWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTIY);
+            entity.aboveApplicationVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromEntityWhenAccessingAboveLayerVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTIY);
+            entity.aboveLayerVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromEntityWhenAccessingAboveModuleVisibleExpectException()
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            FromEntity entity = unitOfWork.newEntity( FromEntity.class, TEST_IDENTIY);
+            entity.aboveModuleVisible();
+        }
+        finally
+        {
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.discard();
+            }
+        }
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromValueWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromValueWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromValueWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromValueWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromValueWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromValueWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromValueWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromValue value = module.newValue( FromValue.class );
+        value.aboveModuleVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromTransientWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromTransientWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromTransientWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromTransientWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromTransientWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromTransientWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromTransientWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromTransient transientt = module.newTransient( FromTransient.class );
+        transientt.aboveModuleVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingModuleApplicationVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.moduleApplicationVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingModuleLayerVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.moduleLayerVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingModuleModuleVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.moduleModuleVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingBesideApplicationVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.besideApplicationVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingBesideLayerVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.besideLayerVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromObjectWhenAccessingBesideModuleVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.besideModuleVisible();
+    }
+
+    @Test
+    public void givenFromObjectWhenAccessingBelowApplicationVisibleExpectSuccess()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.belowApplicationVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromObjectWhenAccessingBelowLayerVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.belowLayerVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromObjectWhenAccessingBelowModuleVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.belowModuleVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromObjectWhenAccessingAboveApplicationVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.aboveApplicationVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromObjectWhenAccessingAboveLayerVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.aboveLayerVisible();
+    }
+
+    @Test( expected = NoSuchValueException.class )
+    public void givenFromObjectWhenAccessingAboveModuleVisibleExpectException()
+    {
+        FromObject object = module.newObject( FromObject.class );
+        object.aboveModuleVisible();
+    }
+
+    private static class FromAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.layer().setName( "From Layer" );
+            module.setName( "From" );
+            module.services( FromService.class );
+            module.entities( FromEntity.class );
+            module.transients( FromTransient.class );
+            module.values( FromValue.class );
+            module.objects( FromObject.class );
+
+            module.values( ModuleApplicationVisible.class ).visibleIn( Visibility.application );
+            module.values( ModuleLayerVisible.class ).visibleIn( Visibility.layer );
+            module.values( ModuleModuleVisible.class ).visibleIn( Visibility.module );
+
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    private static class BelowAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.layer().setName( "Below Layer" );
+            module.setName( "Below" );
+            module.values( BelowApplicationVisible.class ).visibleIn( Visibility.application );
+            module.values( BelowLayerVisible.class ).visibleIn( Visibility.layer );
+            module.values( BelowModuleVisible.class ).visibleIn( Visibility.module );
+
+            new EntityTestAssembler().visibleIn( Visibility.application ).assemble( module );
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    private static class AboveAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.layer().setName( "Above Layer" );
+            module.setName( "Above" );
+            module.values( AboveApplicationVisible.class ).visibleIn( Visibility.application );
+            module.values( AboveLayerVisible.class ).visibleIn( Visibility.layer );
+            module.values( AboveModuleVisible.class ).visibleIn( Visibility.module );
+
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    private static class BesideAssembler
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.setName( "Beside" );
+            module.values( BesideApplicationVisible.class ).visibleIn( Visibility.application );
+            module.values( BesideLayerVisible.class ).visibleIn( Visibility.layer );
+            module.values( BesideModuleVisible.class ).visibleIn( Visibility.module );
+
+            new DefaultUnitOfWorkAssembler().assemble( module );
+        }
+    }
+
+    @Mixins( Mixin.class )
+    public interface From
+    {
+        void moduleApplicationVisible();
+
+        void moduleLayerVisible();
+
+        void moduleModuleVisible();
+
+        void besideApplicationVisible();
+
+        void besideLayerVisible();
+
+        void besideModuleVisible();
+
+        void belowApplicationVisible();
+
+        void belowLayerVisible();
+
+        void belowModuleVisible();
+
+        void aboveApplicationVisible();
+
+        void aboveLayerVisible();
+
+        void aboveModuleVisible();
+    }
+
+    public interface FromValue extends From, ValueComposite
+    {
+    }
+
+    public interface FromEntity extends From, EntityComposite
+    {
+    }
+
+    public interface FromService extends From, ServiceComposite
+    {
+    }
+
+    public interface FromTransient extends From, TransientComposite
+    {
+    }
+
+    public static class FromObject extends Mixin
+    {
+    }
+
+    public abstract static class Mixin
+        implements From
+    {
+        @Structure
+        private Module module;
+
+        @Override
+        public void moduleApplicationVisible()
+        {
+            ValueBuilder<ModuleApplicationVisible> builder = module.newValueBuilder( ModuleApplicationVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void moduleLayerVisible()
+        {
+            ValueBuilder<ModuleLayerVisible> builder = module.newValueBuilder( ModuleLayerVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void moduleModuleVisible()
+        {
+            ValueBuilder<ModuleModuleVisible> builder = module.newValueBuilder( ModuleModuleVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void besideApplicationVisible()
+        {
+            ValueBuilder<BesideApplicationVisible> builder = module.newValueBuilder( BesideApplicationVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void besideLayerVisible()
+        {
+            ValueBuilder<BesideLayerVisible> builder = module.newValueBuilder( BesideLayerVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void besideModuleVisible()
+        {
+            ValueBuilder<BesideModuleVisible> builder = module.newValueBuilder( BesideModuleVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void belowApplicationVisible()
+        {
+            ValueBuilder<BelowApplicationVisible> builder = module.newValueBuilder( BelowApplicationVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void belowLayerVisible()
+        {
+            ValueBuilder<BelowLayerVisible> builder = module.newValueBuilder( BelowLayerVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void belowModuleVisible()
+        {
+            ValueBuilder<BelowModuleVisible> builder = module.newValueBuilder( BelowModuleVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void aboveApplicationVisible()
+        {
+            ValueBuilder<AboveApplicationVisible> builder = module.newValueBuilder( AboveApplicationVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void aboveLayerVisible()
+        {
+            ValueBuilder<AboveLayerVisible> builder = module.newValueBuilder( AboveLayerVisible.class );
+            builder.newInstance();
+        }
+
+        @Override
+        public void aboveModuleVisible()
+        {
+            ValueBuilder<AboveModuleVisible> builder = module.newValueBuilder( AboveModuleVisible.class );
+            builder.newInstance();
+        }
+    }
+
+    public interface ModuleApplicationVisible extends ValueComposite
+    {
+    }
+
+    public interface ModuleLayerVisible extends ValueComposite
+    {
+    }
+
+    public interface ModuleModuleVisible extends ValueComposite
+    {
+    }
+
+    public interface BesideApplicationVisible extends ValueComposite
+    {
+    }
+
+    public interface BesideLayerVisible extends ValueComposite
+    {
+    }
+
+    public interface BesideModuleVisible extends ValueComposite
+    {
+    }
+
+    public interface BelowApplicationVisible extends ValueComposite
+    {
+    }
+
+    public interface BelowLayerVisible extends ValueComposite
+    {
+    }
+
+    public interface BelowModuleVisible extends ValueComposite
+    {
+    }
+
+    public interface AboveApplicationVisible extends ValueComposite
+    {
+    }
+
+    public interface AboveLayerVisible extends ValueComposite
+    {
+    }
+
+    public interface AboveModuleVisible extends ValueComposite
+    {
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueWithAssociationTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueWithAssociationTest.java
new file mode 100644
index 0000000..4441a76
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/value/ValueWithAssociationTest.java
@@ -0,0 +1,200 @@
+/*
+ *  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.polygene.runtime.value;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class ValueWithAssociationTest extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( SimpleName.class );
+        module.entities( DualFaced.class );
+        module.values( SimpleName.class );
+        module.values( DualFaced.class );
+        module.services( MemoryEntityStoreService.class );
+    }
+
+    @Test
+    public void givenEntityInStoreWhenFetchEntityReferenceExpectSuccess()
+        throws UnitOfWorkCompletionException
+    {
+        Identity identity1;
+        Identity identity2;
+        DualFaced value;
+        try (UnitOfWork uow = unitOfWorkFactory.newUnitOfWork())
+        {
+            EntityBuilder<SimpleName> builder1 = uow.newEntityBuilder( SimpleName.class );
+            builder1.instance().name().set( "Niclas" );
+            SimpleName simpleEntity = builder1.newInstance();
+            identity1 = simpleEntity.identity().get();
+
+            EntityBuilder<DualFaced> builder2 = uow.newEntityBuilder( DualFaced.class );
+            DualFaced proto = builder2.instance();
+            proto.name().set( "Hedhman" );
+            proto.simple().set( simpleEntity );
+            proto.simples().add( simpleEntity );
+            proto.namedSimples().put( "niclas", simpleEntity );
+            DualFaced faced = builder2.newInstance();
+            identity2 = faced.identity().get();
+            value = uow.toValue( DualFaced.class, faced );
+            assertThat( value.identity().get(), equalTo( identity2 ) );
+            uow.complete();
+        }
+
+        try (UnitOfWork uow = unitOfWorkFactory.newUnitOfWork())
+        {
+            DualFaced entity = uow.get( DualFaced.class, identity2 );
+            AssociationStateHolder holder = spi.stateOf( (EntityComposite) entity );
+            Association<?> simple = holder.allAssociations().iterator().next();
+            ManyAssociation<?> simples = holder.allManyAssociations().iterator().next();
+            NamedAssociation<?> namedSimples = holder.allNamedAssociations().iterator().next();
+
+            assertThat( spi.entityReferenceOf( simple ), equalTo( EntityReference.create( identity1 ) ) );
+            assertThat( spi.entityReferencesOf( simples )
+                            .iterator()
+                            .next(), equalTo( EntityReference.create( identity1 ) ) );
+            assertThat( spi.entityReferencesOf( namedSimples )
+                            .iterator()
+                            .next()
+                            .getValue(), equalTo( EntityReference.create( identity1 ) ) );
+
+            DualFaced resurrected = uow.toEntity( DualFaced.class, value );
+            assertThat( resurrected.simple(), equalTo( entity.simple() ) );
+            assertThat( resurrected.simples(), equalTo( entity.simples() ) );
+            assertThat( resurrected.namedSimples(), equalTo( entity.namedSimples() ) );
+        }
+    }
+
+    @Test
+    public void givenNewValueWhenConvertingToEntityExpectNewEntityInStore()
+        throws UnitOfWorkCompletionException
+    {
+        ValueBuilder<DualFaced> builder = valueBuilderFactory.newValueBuilder( DualFaced.class );
+        builder.prototype().identity().set( new StringIdentity( "1234" ) );
+        builder.prototype().name().set( "Hedhman" );
+        DualFaced value = builder.newInstance();
+
+        try (UnitOfWork uow = unitOfWorkFactory.newUnitOfWork())
+        {
+            uow.toEntity( DualFaced.class, value );
+            uow.complete();
+        }
+
+        try (UnitOfWork uow = unitOfWorkFactory.newUnitOfWork())
+        {
+            DualFaced entity = uow.get( DualFaced.class, new StringIdentity( "1234" ) );
+            assertThat( entity.identity().get(), equalTo( new StringIdentity( "1234" ) ) );
+            assertThat( entity.name().get(), equalTo( "Hedhman" ) );
+            uow.complete();
+        }
+    }
+
+    @Test
+    public void givenValueWithIdentityAlreadyInStoreWhenConvertingToEntityExpectExistingEntityToBeUpdated()
+        throws UnitOfWorkCompletionException
+    {
+        Identity identity1;
+        Identity identity2;
+        try (UnitOfWork uow = unitOfWorkFactory.newUnitOfWork())
+        {
+            EntityBuilder<SimpleName> builder1 = uow.newEntityBuilder( SimpleName.class );
+            builder1.instance().name().set( "Niclas" );
+            SimpleName simpleEntity = builder1.newInstance();
+            identity1 = simpleEntity.identity().get();
+
+            EntityBuilder<DualFaced> builder2 = uow.newEntityBuilder( DualFaced.class );
+            DualFaced proto = builder2.instance();
+            proto.name().set( "Hedhman" );
+            proto.simple().set( simpleEntity );
+            proto.simples().add( simpleEntity );
+            proto.namedSimples().put( "niclas", simpleEntity );
+            DualFaced faced = builder2.newInstance();
+            identity2 = faced.identity().get();
+            uow.complete();
+        }
+        ValueBuilder<SimpleName> vb1 = valueBuilderFactory.newValueBuilder( SimpleName.class );
+        vb1.prototype().identity().set( identity1 );
+        vb1.prototype().name().set( "Paul" );
+        SimpleName simpleValue = vb1.newInstance();
+
+        ValueBuilder<DualFaced> vb2 = valueBuilderFactory.newValueBuilder( DualFaced.class );
+        vb2.prototype().identity().set( identity2 );
+        vb2.prototype().name().set( "Merlin" );
+        vb2.prototype().simple().set( simpleValue );
+        vb2.prototype().simples().add( simpleValue );
+        vb2.prototype().namedSimples().put( "paul", simpleValue );
+        DualFaced dualValue = vb2.newInstance();
+
+        try (UnitOfWork uow = unitOfWorkFactory.newUnitOfWork())
+        {
+            DualFaced dualEntity = uow.toEntity( DualFaced.class, dualValue );
+            // The root entity is expected to have changed value,
+            assertThat( dualEntity.name().get(), equalTo( "Merlin" ) );
+            // But the referenced entity is not updated, only using the EntityReference, which still points to "Niclas",
+            // even though the value contains "Paul" for that entity. That entity needds to be updated separately
+            assertThat( dualEntity.simple().get().name().get(), equalTo( "Niclas" ) );
+            assertThat( dualEntity.simples().get(0).name().get(), equalTo( "Niclas" ) );
+            assertThat( dualEntity.namedSimples().get("paul").name().get(), equalTo( "Niclas" ) );
+            assertThat( dualEntity.namedSimples().get("niclas"), equalTo( null ) );
+        }
+    }
+
+    public interface SimpleName extends HasIdentity
+    {
+        Property<String> name();
+    }
+
+    public interface DualFaced extends HasIdentity
+    {
+        Property<String> name();
+
+        @Optional
+        Association<SimpleName> simple();
+
+        ManyAssociation<SimpleName> simples();
+
+        NamedAssociation<SimpleName> namedSimples();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/runtime/visibility/VisibilityInUnitOfWorkTest.java b/core/runtime/src/test/java/org/apache/polygene/runtime/visibility/VisibilityInUnitOfWorkTest.java
new file mode 100644
index 0000000..66c4bc8
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/runtime/visibility/VisibilityInUnitOfWorkTest.java
@@ -0,0 +1,160 @@
+/*
+ *  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.polygene.runtime.visibility;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+import org.junit.Test;
+
+public class VisibilityInUnitOfWorkTest
+{
+
+    public static final Identity TEST_IDENTITY1 = new StringIdentity( "123" );
+    public static final Identity TEST_IDENTITY2 = new StringIdentity( "345" );
+
+    @Test
+    public void givenTwoModulesWithServiceAndEntityInOneAndEntityInOtherWhenOtherEntityAccessServiceWhichUsesItsEntityExpectServiceToHaveVisibility()
+        throws Exception
+    {
+        Application underTest = createApplication();
+        Module module = underTest.findModule( "layer1", "My Module" );
+        ServiceReference<MyService> service = module.findService( MyService.class );
+        service.get().create();
+    }
+
+    @Mixins( YourService.Mixin.class )
+    public interface YourService
+    {
+        void create();
+
+        YourEntity get();
+
+        class Mixin
+            implements YourService
+        {
+            @Structure
+            private UnitOfWorkFactory uowf;
+
+            @Override
+            public void create()
+            {
+                UnitOfWork uow = uowf.currentUnitOfWork();
+                YourEntity entity = uow.newEntity( YourEntity.class, TEST_IDENTITY2);
+            }
+
+            @Override
+            public YourEntity get()
+            {
+                UnitOfWork uow = uowf.currentUnitOfWork();
+                return uow.get( YourEntity.class, TEST_IDENTITY2);
+            }
+        }
+    }
+
+    public interface YourEntity
+    {
+    }
+
+    @Mixins( MyEntity.Mixin.class )
+    public interface MyEntity
+    {
+        void logic();
+
+        class Mixin
+            implements MyEntity
+        {
+            @Service
+            private YourService service;
+
+            @Override
+            public void logic()
+            {
+                YourEntity result = service.get();
+            }
+        }
+    }
+
+    @Mixins( MyService.Mixin.class )
+    public interface MyService
+    {
+        void create();
+
+        class Mixin
+            implements MyService
+        {
+
+            @Service
+            private YourService service;
+
+            @Structure
+            private UnitOfWorkFactory uowf;
+
+            @Override
+            public void create()
+            {
+                try (UnitOfWork uow = uowf.newUnitOfWork())
+                {
+                    uow.newEntity( MyEntity.class, TEST_IDENTITY1 );
+                    MyEntity entity1 = uow.get( MyEntity.class, TEST_IDENTITY1 );
+                    service.create();
+                    YourEntity entity2 = service.get();
+                }
+            }
+        }
+    }
+
+    private Application createApplication()
+        throws AssemblyException
+    {
+        Energy4Java polygene = new Energy4Java();
+        return polygene.newApplication( appFactory -> {
+            ApplicationAssembly appAssembly = appFactory.newApplicationAssembly();
+            LayerAssembly layer1 = appAssembly.layer( "layer1" );
+            ModuleAssembly myModule = layer1.module( "My Module" );
+            ModuleAssembly yourModule = layer1.module( "Your Module" );
+            ModuleAssembly infraModule = layer1.module( "Infra Module" );
+            myModule.services( MyService.class );
+            myModule.entities( MyEntity.class );
+            new DefaultUnitOfWorkAssembler().assemble( myModule );
+            yourModule.entities( YourEntity.class );
+            yourModule.services( YourService.class ).visibleIn( Visibility.layer );
+            new DefaultUnitOfWorkAssembler().assemble( yourModule );
+            infraModule.services( MemoryEntityStoreService.class ).visibleIn( Visibility.layer );
+            new DefaultUnitOfWorkAssembler().assemble( infraModule );
+            return appAssembly;
+        } );
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/spi/service/importer/InstanceImporterTest.java b/core/runtime/src/test/java/org/apache/polygene/spi/service/importer/InstanceImporterTest.java
new file mode 100644
index 0000000..538d365
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/spi/service/importer/InstanceImporterTest.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.spi.service.importer;
+
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test import of singleton services
+ */
+public class InstanceImporterTest
+    extends AbstractPolygeneTest
+{
+    @Service
+    TestInterface service;
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ModuleAssembly serviceModule = module.layer().module( "Service module" );
+        serviceModule.importedServices( TestInterface.class )
+            .setMetaInfo( new TestService() )
+            .visibleIn( Visibility.layer );
+        module.objects( InstanceImporterTest.class );
+    }
+
+    @Test
+    public void givenSingletonServiceObjectWhenServicesAreInjectedThenSingletonIsFound()
+    {
+        assertThat( "service is injected properly", service.helloWorld(), equalTo( "Hello World" ) );
+    }
+
+    public interface TestInterface
+    {
+        public String helloWorld();
+    }
+
+    public static class TestService
+        implements TestInterface
+    {
+        public String helloWorld()
+        {
+            return "Hello World";
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/spi/service/importer/NewObjectImporterTest.java b/core/runtime/src/test/java/org/apache/polygene/spi/service/importer/NewObjectImporterTest.java
new file mode 100644
index 0000000..c863dc2
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/spi/service/importer/NewObjectImporterTest.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.spi.service.importer;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ImportedServiceDeclaration;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+/**
+ * JAVADOC
+ */
+public class NewObjectImporterTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.importedServices( TestService.class ).
+            identifiedBy( "test" ).
+            importedBy( ImportedServiceDeclaration.NEW_OBJECT );
+
+        module.objects( TestService.class, NewObjectImporterTest.class );
+    }
+
+    @Service
+    TestService service;
+
+    @Test
+    public void testImportServiceFromService()
+    {
+        Assert.assertThat( service.helloWorld(), CoreMatchers.equalTo( "Hello World" ) );
+    }
+
+    public static class TestService
+    {
+        String helloWorld()
+        {
+            return "Hello World";
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/spi/service/importer/ServiceInstanceImporterTest.java b/core/runtime/src/test/java/org/apache/polygene/spi/service/importer/ServiceInstanceImporterTest.java
new file mode 100644
index 0000000..6a891c4
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/spi/service/importer/ServiceInstanceImporterTest.java
@@ -0,0 +1,92 @@
+/*
+ *  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.polygene.spi.service.importer;
+
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.ServiceImporterException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ImportedServiceDeclaration;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+/**
+ * JAVADOC
+ */
+public class ServiceInstanceImporterTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.importedServices( TestService.class ).
+            identifiedBy( "test" ).
+            setMetaInfo( new StringIdentity( "testimporter" ) ).
+            importedBy( ImportedServiceDeclaration.SERVICE_IMPORTER );
+        module.services( TestImporterService.class ).identifiedBy( "testimporter" );
+
+        module.objects( ServiceInstanceImporterTest.class );
+    }
+
+    @Service
+    TestService service;
+
+    @Test
+    public void testImportServiceFromService()
+    {
+        Assert.assertThat( service.helloWorld(), CoreMatchers.equalTo( "Hello World" ) );
+    }
+
+    public static class TestService
+    {
+        String helloWorld()
+        {
+            return "Hello World";
+        }
+    }
+
+    @Mixins( TestImporterService.Mixin.class )
+    interface TestImporterService
+        extends ServiceComposite, ServiceImporter<TestService>
+    {
+        class Mixin
+            implements ServiceImporter<TestService>
+        {
+            public TestService importService( ImportedServiceDescriptor serviceDescriptor )
+                throws ServiceImporterException
+            {
+                return new TestService();
+            }
+
+            public boolean isAvailable( TestService instance )
+            {
+                return true;
+            }
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/spi/service/importer/ServiceSelectorImporterTest.java b/core/runtime/src/test/java/org/apache/polygene/spi/service/importer/ServiceSelectorImporterTest.java
new file mode 100644
index 0000000..334acd1
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/spi/service/importer/ServiceSelectorImporterTest.java
@@ -0,0 +1,166 @@
+/*
+ *  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.polygene.spi.service.importer;
+
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.qualifier.ServiceQualifier;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.apache.polygene.bootstrap.ImportedServiceDeclaration.SERVICE_SELECTOR;
+
+/**
+ * Test of service selector importer
+ */
+public class ServiceSelectorImporterTest
+{
+    @Test
+    public void givenManyServicesWhenInjectServiceThenGetFirstOne()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.objects( ServiceConsumer.class );
+                module.services( TestServiceComposite1.class,
+                                 TestServiceComposite2.class );
+            }
+        };
+
+        TestService service = assembler.module().newObject( ServiceConsumer.class ).getService();
+
+        assertThat( "service is first one", service.test(), equalTo( "mixin1" ) );
+    }
+
+    @Test
+    public void givenManyServicesAndFilterWhenInjectServiceThenGetSpecifiedOne()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.objects( ServiceConsumer.class );
+
+                module.importedServices( TestService.class )
+                    .importedBy( SERVICE_SELECTOR )
+                    .setMetaInfo( ServiceQualifier.withId( TestServiceComposite2.class.getSimpleName() ) );
+
+                ModuleAssembly module2 = module.layer().module( "Other module" );
+                module2.services( TestServiceComposite2.class, TestServiceComposite2.class )
+                    .visibleIn( Visibility.layer );
+            }
+        };
+
+        TestService service = assembler.module().newObject( ServiceConsumer.class ).getService();
+
+        assertThat( "service is specified one", service.test(), equalTo( "mixin2" ) );
+    }
+
+    @Test
+    public void givenManyServicesAndSelectFirstWhenInjectServiceThenDontGetSelf()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.objects( ServiceConsumer.class );
+
+                module.importedServices( TestService.class )
+                    .importedBy( SERVICE_SELECTOR )
+                    .setMetaInfo( ServiceQualifier.withId( "TestServiceComposite2_1" ) );
+
+                ModuleAssembly module2 = module.layer().module( "Other module" );
+                module2.addServices( TestServiceComposite2.class, TestServiceComposite2.class )
+                    .visibleIn( Visibility.layer );
+            }
+        };
+
+        TestService service = assembler.module().newObject( ServiceConsumer.class ).getService();
+
+        assertThat( "service is specified one", service.test(), equalTo( "mixin2" ) );
+    }
+
+    public static class ServiceConsumer
+    {
+        private
+        @Service
+        TestService service;
+
+        public TestService getService()
+        {
+            return service;
+        }
+    }
+
+    @Mixins( TestMixin1.class )
+    public interface TestServiceComposite1
+        extends TestServiceComposite
+    {
+    }
+
+    @Mixins( TestMixin2.class )
+    public interface TestServiceComposite2
+        extends TestServiceComposite
+    {
+    }
+
+    public interface TestServiceComposite
+        extends TestService, ServiceComposite
+    {
+    }
+
+    public interface TestService
+    {
+        String test();
+    }
+
+    public static class TestMixin1
+        implements TestService
+    {
+        public String test()
+        {
+            return "mixin1";
+        }
+    }
+
+    public static class TestMixin2
+        implements TestService
+    {
+        public String test()
+        {
+            return "mixin2";
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/test/ASMTest.java b/core/runtime/src/test/java/org/apache/polygene/test/ASMTest.java
new file mode 100644
index 0000000..5179e8f
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/test/ASMTest.java
@@ -0,0 +1,588 @@
+/*
+ *  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.polygene.test;
+
+import java.io.PrintWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.util.ASMifier;
+import org.objectweb.asm.util.TraceClassVisitor;
+import org.apache.polygene.api.composite.CompositeInvoker;
+import org.apache.polygene.runtime.composite.FragmentClassLoader;
+import org.apache.polygene.runtime.composite.QI256Test;
+
+import static org.objectweb.asm.Opcodes.*;
+
+public class ASMTest
+{
+    @Test
+    public void generateASM()
+        throws Exception
+    {
+        ASMifier.main( new String[]{ SomeMixin_Stubx.class.getName() } );
+    }
+
+    @Test
+    public void createClass()
+        throws Exception
+    {
+
+        FragmentClassLoader classLoader = new FragmentClassLoader( SomeMixin.class.getClassLoader() );
+
+        Class clazz = classLoader.loadClass( SomeMixin.class.getName() + "_Stub" );
+
+        //       Class clazz = SomeMixin_Stubx.class;
+
+        final Other other = new Other()
+        {
+            public String other()
+            {
+                return "other";
+            }
+
+            public String foo( String bar, int x )
+            {
+                return "bar:" + bar;
+            }
+
+            public void bar( double doub,
+                             boolean bool,
+                             float fl,
+                             char ch,
+                             int integer,
+                             long lg,
+                             short sh,
+                             byte b,
+                             Double doubObj,
+                             Object[] objArr,
+                             int[] intArr
+            )
+            {
+            }
+
+            public void multiEx( String bar )
+                throws Exception1, Exception2
+            {
+            }
+
+            public long unwrapResult()
+            {
+                return 0;
+            }
+
+            public void generic( List<String> list )
+            {
+                list.add( "Hello World" );
+            }
+        };
+
+        final Some instance = (Some) clazz.getConstructor().newInstance();
+
+        CompositeInvoker invoker = new CompositeInvoker()
+        {
+            public Object invokeComposite( Method method, Object[] args )
+                throws Throwable
+            {
+                Method fakeMethod = null;
+                try
+                {
+                    fakeMethod = instance.getClass().getMethod( "_" + method.getName(), method.getParameterTypes() );
+
+                    try
+                    {
+                        return fakeMethod.invoke( instance, args );
+                    }
+                    catch( InvocationTargetException e )
+                    {
+                        throw e.getCause();
+                    }
+                }
+                catch( NoSuchMethodException e )
+                {
+                    try
+                    {
+                        return method.invoke( other, args );
+                    }
+                    catch( InvocationTargetException ex )
+                    {
+                        throw ex.getCause();
+                    }
+                }
+            }
+        };
+
+        clazz.getField( "_instance" ).set( instance, invoker );
+
+        System.out.println( instance.some() );
+
+        System.out.println( instance.testConcern() );
+    }
+
+    @Test
+    @Ignore( "Convenience to look at what code is generated in the Fragment Classloader, and is not really a test case." )
+    public void fragmentClassLoaderGenerateClassTest()
+        throws Exception
+    {
+        FragmentClassLoader classLoader = new FragmentClassLoader( getClass().getClassLoader() );
+        byte[] asm = generateClass();
+        byte[] cl = classLoader.generateClass(
+            QI256Test.TestTransient.TestTransientMixin.class.getName() + "_Stub",
+            QI256Test.TestTransient.TestTransientMixin.class );
+
+        new ClassReader( cl ).accept( new TraceClassVisitor( new PrintWriter( System.out, true ) ), 0 );
+
+        Assert.assertArrayEquals( asm, cl );
+    }
+
+    // This is the code generated from the manual stub
+    private static byte[] generateClass()
+    {
+        ClassWriter cw = new ClassWriter( 0 );
+        FieldVisitor fv;
+        MethodVisitor mv;
+        AnnotationVisitor av0;
+
+        cw.visit( V1_6, ACC_PUBLIC + ACC_SUPER, "org/apache/polygene/satisfiedBy/SomeMixin_Stub", null,
+                  "org/apache/polygene/satisfiedBy/SomeMixin", null );
+
+        {
+            fv = cw.visitField( ACC_PUBLIC, "_instance", "Lorg/apache/polygene/spi/composite/CompositeInvoker;", null, null );
+            fv.visitEnd();
+        }
+        {
+            fv = cw.visitField( ACC_PRIVATE + ACC_STATIC, "m1", "Ljava/lang/reflect/Method;", null, null );
+            fv.visitEnd();
+        }
+        {
+            fv = cw.visitField( ACC_PRIVATE + ACC_STATIC, "m2", "Ljava/lang/reflect/Method;", null, null );
+            fv.visitEnd();
+        }
+        {
+            fv = cw.visitField( ACC_PRIVATE + ACC_STATIC, "m3", "Ljava/lang/reflect/Method;", null, null );
+            fv.visitEnd();
+        }
+        {
+            fv = cw.visitField( ACC_PRIVATE + ACC_STATIC, "m4", "Ljava/lang/reflect/Method;", null, null );
+            fv.visitEnd();
+        }
+        {
+            fv = cw.visitField( ACC_PRIVATE + ACC_STATIC, "m5", "Ljava/lang/reflect/Method;", null, null );
+            fv.visitEnd();
+        }
+        {
+            mv = cw.visitMethod( ACC_PUBLIC, "<init>", "()V", null, null );
+            mv.visitCode();
+            mv.visitVarInsn( ALOAD, 0 );
+            mv.visitMethodInsn( INVOKESPECIAL, "org/apache/polygene/satisfiedBy/SomeMixin", "<init>", "()V", false );
+            mv.visitInsn( RETURN );
+            mv.visitMaxs( 1, 1 );
+            mv.visitEnd();
+        }
+        {
+            mv = cw.visitMethod( ACC_PUBLIC, "<init>", "(Ljava/lang/String;)V", null, null );
+            mv.visitCode();
+            mv.visitVarInsn( ALOAD, 0 );
+            mv.visitVarInsn( ALOAD, 1 );
+            mv.visitMethodInsn( INVOKESPECIAL, "org/apache/polygene/satisfiedBy/SomeMixin", "<init>", "(Ljava/lang/String;)V", false );
+            mv.visitInsn( RETURN );
+            mv.visitMaxs( 2, 2 );
+            mv.visitEnd();
+        }
+        {
+            mv = cw.visitMethod( ACC_PUBLIC, "other", "()Ljava/lang/String;", null, null );
+            mv.visitCode();
+            Label l0 = new Label();
+            Label l1 = new Label();
+            Label l2 = new Label();
+            mv.visitTryCatchBlock( l0, l1, l2, "java/lang/Throwable" );
+            mv.visitLabel( l0 );
+            mv.visitVarInsn( ALOAD, 0 );
+            mv.visitFieldInsn( GETFIELD, "org/apache/polygene/satisfiedBy/SomeMixin_Stub", "_instance",
+                               "Lorg/apache/polygene/spi/composite/CompositeInvoker;" );
+            mv.visitFieldInsn( GETSTATIC, "org/apache/polygene/satisfiedBy/SomeMixin_Stub", "m1", "Ljava/lang/reflect/Method;" );
+            mv.visitInsn( ACONST_NULL );
+            mv.visitMethodInsn( INVOKEINTERFACE, "org/apache/polygene/spi/composite/CompositeInvoker", "invokeComposite",
+                                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true );
+            mv.visitTypeInsn( CHECKCAST, "java/lang/String" );
+            mv.visitLabel( l1 );
+            mv.visitInsn( ARETURN );
+            mv.visitLabel( l2 );
+            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/Throwable" } );
+            mv.visitVarInsn( ASTORE, 1 );
+            mv.visitTypeInsn( NEW, "java/lang/reflect/UndeclaredThrowableException" );
+            mv.visitInsn( DUP );
+            mv.visitVarInsn( ALOAD, 1 );
+            mv.visitMethodInsn( INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>",
+                                "(Ljava/lang/Throwable;)V", false );
+            mv.visitInsn( ATHROW );
+            mv.visitMaxs( 3, 2 );
+            mv.visitEnd();
+        }
+        {
+            mv = cw.visitMethod( ACC_PUBLIC, "foo", "(Ljava/lang/String;I)Ljava/lang/String;", null,
+                                 new String[]{ "java/lang/IllegalArgumentException" } );
+            mv.visitCode();
+            Label l0 = new Label();
+            Label l1 = new Label();
+            Label l2 = new Label();
+            mv.visitTryCatchBlock( l0, l1, l2, "java/lang/IllegalArgumentException" );
+            Label l3 = new Label();
+            mv.visitTryCatchBlock( l0, l1, l3, "java/lang/Throwable" );
+            mv.visitLabel( l0 );
+            mv.visitVarInsn( ALOAD, 0 );
+            mv.visitFieldInsn( GETFIELD, "org/apache/polygene/satisfiedBy/SomeMixin_Stub", "_instance",
+                               "Lorg/apache/polygene/spi/composite/CompositeInvoker;" );
+            mv.visitFieldInsn( GETSTATIC, "org/apache/polygene/satisfiedBy/SomeMixin_Stub", "m2", "Ljava/lang/reflect/Method;" );
+            mv.visitInsn( ICONST_2 );
+            mv.visitTypeInsn( ANEWARRAY, "java/lang/Object" );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_0 );
+            mv.visitVarInsn( ALOAD, 1 );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_1 );
+            mv.visitVarInsn( ILOAD, 2 );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false );
+            mv.visitInsn( AASTORE );
+            mv.visitMethodInsn( INVOKEINTERFACE, "org/apache/polygene/spi/composite/CompositeInvoker", "invokeComposite",
+                                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true );
+            mv.visitTypeInsn( CHECKCAST, "java/lang/String" );
+            mv.visitLabel( l1 );
+            mv.visitInsn( ARETURN );
+            mv.visitLabel( l2 );
+            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/IllegalArgumentException" } );
+            mv.visitVarInsn( ASTORE, 3 );
+            mv.visitVarInsn( ALOAD, 3 );
+            mv.visitInsn( ATHROW );
+            mv.visitLabel( l3 );
+            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/Throwable" } );
+            mv.visitVarInsn( ASTORE, 3 );
+            mv.visitTypeInsn( NEW, "java/lang/reflect/UndeclaredThrowableException" );
+            mv.visitInsn( DUP );
+            mv.visitVarInsn( ALOAD, 3 );
+            mv.visitMethodInsn( INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>",
+                                "(Ljava/lang/Throwable;)V", false );
+            mv.visitInsn( ATHROW );
+            mv.visitMaxs( 6, 4 );
+            mv.visitEnd();
+        }
+        {
+            mv = cw.visitMethod( ACC_PUBLIC, "bar", "(DZFCIJSBLjava/lang/Double;[Ljava/lang/Object;[I)V", null, null );
+            mv.visitCode();
+            Label l0 = new Label();
+            Label l1 = new Label();
+            Label l2 = new Label();
+            mv.visitTryCatchBlock( l0, l1, l2, "java/lang/Throwable" );
+            mv.visitLabel( l0 );
+            mv.visitVarInsn( ALOAD, 0 );
+            mv.visitFieldInsn( GETFIELD, "org/apache/polygene/satisfiedBy/SomeMixin_Stub", "_instance",
+                               "Lorg/apache/polygene/spi/composite/CompositeInvoker;" );
+            mv.visitFieldInsn( GETSTATIC, "org/apache/polygene/satisfiedBy/SomeMixin_Stub", "m3", "Ljava/lang/reflect/Method;" );
+            mv.visitIntInsn( BIPUSH, 11 );
+            mv.visitTypeInsn( ANEWARRAY, "java/lang/Object" );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_0 );
+            mv.visitVarInsn( DLOAD, 1 );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_1 );
+            mv.visitVarInsn( ILOAD, 3 );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_2 );
+            mv.visitVarInsn( FLOAD, 4 );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_3 );
+            mv.visitVarInsn( ILOAD, 5 );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_4 );
+            mv.visitVarInsn( ILOAD, 6 );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_5 );
+            mv.visitVarInsn( LLOAD, 7 );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitIntInsn( BIPUSH, 6 );
+            mv.visitVarInsn( ILOAD, 9 );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitIntInsn( BIPUSH, 7 );
+            mv.visitVarInsn( ILOAD, 10 );
+            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitIntInsn( BIPUSH, 8 );
+            mv.visitVarInsn( ALOAD, 11 );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitIntInsn( BIPUSH, 9 );
+            mv.visitVarInsn( ALOAD, 12 );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitIntInsn( BIPUSH, 10 );
+            mv.visitVarInsn( ALOAD, 13 );
+            mv.visitInsn( AASTORE );
+            mv.visitMethodInsn( INVOKEINTERFACE, "org/apache/polygene/spi/composite/CompositeInvoker", "invokeComposite",
+                                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true );
+            mv.visitInsn( POP );
+            mv.visitLabel( l1 );
+            Label l3 = new Label();
+            mv.visitJumpInsn( GOTO, l3 );
+            mv.visitLabel( l2 );
+            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/Throwable" } );
+            mv.visitVarInsn( ASTORE, 14 );
+            mv.visitTypeInsn( NEW, "java/lang/reflect/UndeclaredThrowableException" );
+            mv.visitInsn( DUP );
+            mv.visitVarInsn( ALOAD, 14 );
+            mv.visitMethodInsn( INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>",
+                                "(Ljava/lang/Throwable;)V", false );
+            mv.visitInsn( ATHROW );
+            mv.visitLabel( l3 );
+            mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
+            mv.visitInsn( RETURN );
+            mv.visitMaxs( 7, 15 );
+            mv.visitEnd();
+        }
+        {
+            mv = cw.visitMethod( ACC_PUBLIC, "multiEx", "(Ljava/lang/String;)V", null,
+                                 new String[]{ "org/apache/polygene/satisfiedBy/Exception1", "org/apache/polygene/satisfiedBy/Exception2" } );
+            mv.visitCode();
+            Label l0 = new Label();
+            Label l1 = new Label();
+            Label l2 = new Label();
+            mv.visitTryCatchBlock( l0, l1, l2, "org/apache/polygene/satisfiedBy/Exception1" );
+            Label l3 = new Label();
+            mv.visitTryCatchBlock( l0, l1, l3, "org/apache/polygene/satisfiedBy/Exception2" );
+            Label l4 = new Label();
+            mv.visitTryCatchBlock( l0, l1, l4, "java/lang/Throwable" );
+            mv.visitLabel( l0 );
+            mv.visitVarInsn( ALOAD, 0 );
+            mv.visitFieldInsn( GETFIELD, "org/apache/polygene/satisfiedBy/SomeMixin_Stub", "_instance",
+                               "Lorg/apache/polygene/spi/composite/CompositeInvoker;" );
+            mv.visitFieldInsn( GETSTATIC, "org/apache/polygene/satisfiedBy/SomeMixin_Stub", "m4", "Ljava/lang/reflect/Method;" );
+            mv.visitInsn( ICONST_1 );
+            mv.visitTypeInsn( ANEWARRAY, "java/lang/Object" );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_0 );
+            mv.visitVarInsn( ALOAD, 1 );
+            mv.visitInsn( AASTORE );
+            mv.visitMethodInsn( INVOKEINTERFACE, "org/apache/polygene/spi/composite/CompositeInvoker", "invokeComposite",
+                                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true );
+            mv.visitInsn( POP );
+            mv.visitLabel( l1 );
+            Label l5 = new Label();
+            mv.visitJumpInsn( GOTO, l5 );
+            mv.visitLabel( l2 );
+            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "org/apache/polygene/satisfiedBy/Exception1" } );
+            mv.visitVarInsn( ASTORE, 2 );
+            mv.visitVarInsn( ALOAD, 2 );
+            mv.visitInsn( ATHROW );
+            mv.visitLabel( l3 );
+            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "org/apache/polygene/satisfiedBy/Exception2" } );
+            mv.visitVarInsn( ASTORE, 2 );
+            mv.visitVarInsn( ALOAD, 2 );
+            mv.visitInsn( ATHROW );
+            mv.visitLabel( l4 );
+            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/Throwable" } );
+            mv.visitVarInsn( ASTORE, 2 );
+            mv.visitTypeInsn( NEW, "java/lang/reflect/UndeclaredThrowableException" );
+            mv.visitInsn( DUP );
+            mv.visitVarInsn( ALOAD, 2 );
+            mv.visitMethodInsn( INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>",
+                                "(Ljava/lang/Throwable;)V", false );
+            mv.visitInsn( ATHROW );
+            mv.visitLabel( l5 );
+            mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
+            mv.visitInsn( RETURN );
+            mv.visitMaxs( 6, 3 );
+            mv.visitEnd();
+        }
+        {
+            mv = cw.visitMethod( ACC_PUBLIC, "unwrapResult", "()I", null, null );
+            mv.visitCode();
+            Label l0 = new Label();
+            Label l1 = new Label();
+            Label l2 = new Label();
+            mv.visitTryCatchBlock( l0, l1, l2, "java/lang/Throwable" );
+            mv.visitLabel( l0 );
+            mv.visitVarInsn( ALOAD, 0 );
+            mv.visitFieldInsn( GETFIELD, "org/apache/polygene/satisfiedBy/SomeMixin_Stub", "_instance",
+                               "Lorg/apache/polygene/spi/composite/CompositeInvoker;" );
+            mv.visitFieldInsn( GETSTATIC, "org/apache/polygene/satisfiedBy/SomeMixin_Stub", "m5", "Ljava/lang/reflect/Method;" );
+            mv.visitInsn( ACONST_NULL );
+            mv.visitMethodInsn( INVOKEINTERFACE, "org/apache/polygene/spi/composite/CompositeInvoker", "invokeComposite",
+                                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true );
+            mv.visitTypeInsn( CHECKCAST, "java/lang/Integer" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false );
+            mv.visitLabel( l1 );
+            mv.visitInsn( IRETURN );
+            mv.visitLabel( l2 );
+            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/Throwable" } );
+            mv.visitVarInsn( ASTORE, 1 );
+            mv.visitTypeInsn( NEW, "java/lang/reflect/UndeclaredThrowableException" );
+            mv.visitInsn( DUP );
+            mv.visitVarInsn( ALOAD, 1 );
+            mv.visitMethodInsn( INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>",
+                                "(Ljava/lang/Throwable;)V", false );
+            mv.visitInsn( ATHROW );
+            mv.visitMaxs( 3, 2 );
+            mv.visitEnd();
+        }
+        {
+            mv = cw.visitMethod( ACC_STATIC, "<clinit>", "()V", null, null );
+            mv.visitCode();
+            Label l0 = new Label();
+            Label l1 = new Label();
+            Label l2 = new Label();
+            mv.visitTryCatchBlock( l0, l1, l2, "java/lang/NoSuchMethodException" );
+            mv.visitLabel( l0 );
+            mv.visitLdcInsn( Type.getType( "Lorg/apache/polygene/satisfiedBy/Other;" ) );
+            mv.visitLdcInsn( "other" );
+            mv.visitInsn( ICONST_0 );
+            mv.visitTypeInsn( ANEWARRAY, "java/lang/Class" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getMethod",
+                                "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false );
+            mv.visitFieldInsn( PUTSTATIC, "org/apache/polygene/satisfiedBy/SomeMixin_Stub", "m1", "Ljava/lang/reflect/Method;" );
+            mv.visitLdcInsn( Type.getType( "Lorg/apache/polygene/satisfiedBy/Other;" ) );
+            mv.visitLdcInsn( "foo" );
+            mv.visitInsn( ICONST_2 );
+            mv.visitTypeInsn( ANEWARRAY, "java/lang/Class" );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_0 );
+            mv.visitLdcInsn( Type.getType( "Ljava/lang/String;" ) );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_1 );
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;" );
+            mv.visitInsn( AASTORE );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getMethod",
+                                "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false );
+            mv.visitFieldInsn( PUTSTATIC, "org/apache/polygene/satisfiedBy/SomeMixin_Stub", "m2", "Ljava/lang/reflect/Method;" );
+            mv.visitLdcInsn( Type.getType( "Lorg/apache/polygene/satisfiedBy/Other;" ) );
+            mv.visitLdcInsn( "bar" );
+            mv.visitIntInsn( BIPUSH, 11 );
+            mv.visitTypeInsn( ANEWARRAY, "java/lang/Class" );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_0 );
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;" );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_1 );
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;" );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_2 );
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;" );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_3 );
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;" );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_4 );
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;" );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_5 );
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;" );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitIntInsn( BIPUSH, 6 );
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;" );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitIntInsn( BIPUSH, 7 );
+            mv.visitFieldInsn( GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;" );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitIntInsn( BIPUSH, 8 );
+            mv.visitLdcInsn( Type.getType( "Ljava/lang/Double;" ) );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitIntInsn( BIPUSH, 9 );
+            mv.visitLdcInsn( Type.getType( "[Ljava/lang/Object;" ) );
+            mv.visitInsn( AASTORE );
+            mv.visitInsn( DUP );
+            mv.visitIntInsn( BIPUSH, 10 );
+            mv.visitLdcInsn( Type.getType( "[I" ) );
+            mv.visitInsn( AASTORE );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getMethod",
+                                "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false );
+            mv.visitFieldInsn( PUTSTATIC, "org/apache/polygene/satisfiedBy/SomeMixin_Stub", "m3", "Ljava/lang/reflect/Method;" );
+            mv.visitLdcInsn( Type.getType( "Lorg/apache/polygene/satisfiedBy/Other;" ) );
+            mv.visitLdcInsn( "multiEx" );
+            mv.visitInsn( ICONST_1 );
+            mv.visitTypeInsn( ANEWARRAY, "java/lang/Class" );
+            mv.visitInsn( DUP );
+            mv.visitInsn( ICONST_0 );
+            mv.visitLdcInsn( Type.getType( "Ljava/lang/String;" ) );
+            mv.visitInsn( AASTORE );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getMethod",
+                                "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false );
+            mv.visitFieldInsn( PUTSTATIC, "org/apache/polygene/satisfiedBy/SomeMixin_Stub", "m4", "Ljava/lang/reflect/Method;" );
+            mv.visitLdcInsn( Type.getType( "Lorg/apache/polygene/satisfiedBy/Other;" ) );
+            mv.visitLdcInsn( "unwrapResult" );
+            mv.visitInsn( ICONST_0 );
+            mv.visitTypeInsn( ANEWARRAY, "java/lang/Class" );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getMethod",
+                                "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false );
+            mv.visitFieldInsn( PUTSTATIC, "org/apache/polygene/satisfiedBy/SomeMixin_Stub", "m5", "Ljava/lang/reflect/Method;" );
+            mv.visitLabel( l1 );
+            Label l3 = new Label();
+            mv.visitJumpInsn( GOTO, l3 );
+            mv.visitLabel( l2 );
+            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/NoSuchMethodException" } );
+            mv.visitVarInsn( ASTORE, 0 );
+            mv.visitVarInsn( ALOAD, 0 );
+            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/NoSuchMethodException", "printStackTrace", "()V", false );
+            mv.visitLabel( l3 );
+            mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
+            mv.visitInsn( RETURN );
+            mv.visitMaxs( 6, 1 );
+            mv.visitEnd();
+        }
+        cw.visitEnd();
+
+        return cw.toByteArray();
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/test/Exception1.java b/core/runtime/src/test/java/org/apache/polygene/test/Exception1.java
new file mode 100644
index 0000000..4f9fb88
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/test/Exception1.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.test;
+
+/**
+ * JAVADOC
+ */
+public class Exception1
+    extends Exception
+{
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/test/Exception2.java b/core/runtime/src/test/java/org/apache/polygene/test/Exception2.java
new file mode 100644
index 0000000..0f56576
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/test/Exception2.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.test;
+
+/**
+ * JAVADOC
+ */
+public class Exception2
+    extends Exception
+{
+}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/apache/polygene/test/Other.java b/core/runtime/src/test/java/org/apache/polygene/test/Other.java
new file mode 100644
index 0000000..9f5ec1b
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/test/Other.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.test;
+
+import java.util.List;
+
+/**
+ * JAVADOC
+ */
+public interface Other
+{
+    public String other();
+
+    public String foo( String bar, int blah )
+        throws IllegalArgumentException;
+
+    public void bar( double doub,
+                     boolean bool,
+                     float fl,
+                     char ch,
+                     int integer,
+                     long lg,
+                     short sh,
+                     byte b,
+                     Double doubObj,
+                     Object[] objArr,
+                     int[] intArr
+    );
+
+    public void multiEx( String bar )
+        throws Exception1, Exception2;
+
+    public long unwrapResult();
+
+    public void generic( List<String> list );
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/test/Some.java b/core/runtime/src/test/java/org/apache/polygene/test/Some.java
new file mode 100644
index 0000000..f159305
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/test/Some.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.test;
+
+/**
+ * JAVADOC
+ */
+public interface Some
+{
+    String some()
+        throws Exception2, Exception1;
+
+    String testConcern();
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/test/SomeMixin.java b/core/runtime/src/test/java/org/apache/polygene/test/SomeMixin.java
new file mode 100644
index 0000000..3388c01
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/test/SomeMixin.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.test;
+
+import java.util.ArrayList;
+
+/**
+ * JAVADOC
+ */
+public abstract class SomeMixin
+    implements Some, Other, World
+{
+
+    protected SomeMixin()
+    {
+    }
+
+    protected SomeMixin( String foo )
+    {
+
+    }
+
+    public String some()
+        throws Exception2, Exception1
+    {
+        multiEx( "foo" );
+        unwrapResult();
+        bar( 1.0, true, 1.0F, 'x', 0, 0L, (short) 0, (byte) 3, new Double( 4F ), new Object[ 0 ], new int[ 0 ] );
+        generic( new ArrayList() );
+
+        return "Hello " + other() + foo( "Test", 0 );
+    }
+
+    public String testConcern()
+    {
+        return someMethod( "Hello", 0, 0 );
+    }
+
+    public String someMethod( String foo, double x, int y )
+    {
+        return foo;
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/test/SomeMixin_Stubx.java b/core/runtime/src/test/java/org/apache/polygene/test/SomeMixin_Stubx.java
new file mode 100644
index 0000000..6016656
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/test/SomeMixin_Stubx.java
@@ -0,0 +1,249 @@
+/*
+ *  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.polygene.test;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import org.apache.polygene.api.composite.CompositeInvoker;
+
+/**
+ * JAVADOC
+ */
+public class SomeMixin_Stubx
+    extends SomeMixin
+{
+    public CompositeInvoker _instance;
+
+    private static Method m1;
+    private static Method m2;
+    private static Method m3;
+    private static Method m4;
+    private static Method m5;
+    private static Method m6;
+
+    private static Method m7;
+    private static Method m8;
+
+    static
+    {
+        try
+        {
+            m1 = Other.class.getMethod( "other" );
+            m2 = Other.class.getMethod( "foo", String.class, Integer.TYPE );
+            m3 = Other.class.getMethod( "bar",
+                                        Double.TYPE,
+                                        Boolean.TYPE,
+                                        Float.TYPE,
+                                        Character.TYPE,
+                                        Integer.TYPE,
+                                        Long.TYPE,
+                                        Short.TYPE,
+                                        Byte.TYPE,
+                                        Double.class,
+                                        Object[].class,
+                                        int[].class );
+            m4 = Other.class.getMethod( "multiEx", String.class );
+            m5 = Other.class.getMethod( "unwrapResult" );
+            m6 = Other.class.getMethod( "generic", List.class );
+
+            m7 = Some.class.getMethod( "testConcern" );
+            m8 = World.class.getMethod( "someMethod", String.class, Double.TYPE, Integer.TYPE );
+        }
+        catch( Throwable e )
+        {
+            e.printStackTrace();
+        }
+    }
+
+    public SomeMixin_Stubx()
+    {
+        super();
+    }
+
+    public SomeMixin_Stubx( String foo )
+    {
+        super( foo );
+    }
+
+    public String other()
+    {
+        try
+        {
+            return (String) _instance.invokeComposite( m1, null );
+        }
+        catch( RuntimeException runtime )
+        {
+            throw runtime;
+        }
+        catch( Throwable error )
+        {
+            throw (Error) error;
+        }
+    }
+
+    public String foo( String bar, int x )
+        throws IllegalArgumentException
+    {
+        try
+        {
+            return (String) _instance.invokeComposite( m2, new Object[]{ bar, x } );
+        }
+        catch( IllegalArgumentException ex )
+        {
+            throw ex;
+        }
+        catch( RuntimeException runtime )
+        {
+            throw runtime;
+        }
+        catch( Throwable error )
+        {
+            throw (Error) error;
+        }
+    }
+
+    public void bar( double doub,
+                     boolean bool,
+                     float fl,
+                     char ch,
+                     int integer,
+                     long lg,
+                     short sh,
+                     byte b,
+                     Double doubObj,
+                     Object[] objArr,
+                     int[] intArr
+    )
+    {
+        try
+        {
+            _instance.invokeComposite( m3, new Object[]{ doub, bool, fl, ch, integer, lg, sh, b, doubObj, objArr, intArr } );
+        }
+        catch( RuntimeException runtime )
+        {
+            throw runtime;
+        }
+        catch( Throwable error )
+        {
+            throw (Error) error;
+        }
+    }
+
+    public void multiEx( String bar )
+        throws Exception1, Exception2
+    {
+        try
+        {
+            _instance.invokeComposite( m4, new Object[]{ bar } );
+        }
+        catch( Exception1 throwable )
+        {
+            throw throwable;
+        }
+        catch( Exception2 throwable )
+        {
+            throw throwable;
+        }
+        catch( RuntimeException runtime )
+        {
+            throw runtime;
+        }
+        catch( Throwable error )
+        {
+            throw (Error) error;
+        }
+    }
+
+    public long unwrapResult()
+    {
+        try
+        {
+            return (Long) _instance.invokeComposite( m5, null );
+        }
+        catch( RuntimeException runtime )
+        {
+            throw runtime;
+        }
+        catch( Throwable error )
+        {
+            throw (Error) error;
+        }
+    }
+
+    public void generic( List<String> list )
+    {
+        try
+        {
+            _instance.invokeComposite( m6, new Object[]{ list } );
+        }
+        catch( RuntimeException runtime )
+        {
+            throw runtime;
+        }
+        catch( Throwable error )
+        {
+            throw (Error) error;
+        }
+    }
+
+    public String testConcern()
+    {
+        try
+        {
+            return (String) _instance.invokeComposite( m7, null );
+        }
+        catch( RuntimeException runtime )
+        {
+            throw runtime;
+        }
+        catch( Throwable error )
+        {
+            throw (Error) error;
+        }
+    }
+
+    public String _testConcern()
+    {
+        return super.testConcern();
+    }
+
+    @Override
+    public String someMethod( String foo, double x, int y )
+    {
+        try
+        {
+            return (String) _instance.invokeComposite( m8, new Object[]{ foo, x, y } );
+        }
+        catch( RuntimeException runtime )
+        {
+            throw runtime;
+        }
+        catch( Throwable error )
+        {
+            throw (Error) error;
+        }
+    }
+
+    public String _someMethod( String foo, double x, int y )
+    {
+        return super.someMethod( foo, x, y );
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/test/World.java b/core/runtime/src/test/java/org/apache/polygene/test/World.java
new file mode 100644
index 0000000..1bfecd6
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/test/World.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.test;
+
+/**
+ * JAVADOC
+ */
+public interface World
+{
+    String someMethod( String foo, double x, int y );
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/test/composite/CleanStackTraceTest.java b/core/runtime/src/test/java/org/apache/polygene/test/composite/CleanStackTraceTest.java
new file mode 100644
index 0000000..010f7ae
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/test/composite/CleanStackTraceTest.java
@@ -0,0 +1,138 @@
+/*
+ *  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.polygene.test.composite;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.concern.GenericConcern;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeTrue;
+
+/**
+ * Test if the stacktrace is cleaned up properly.
+ * <p>
+ * NOTE: This satisfiedBy MUST NOT be inside package org.apache.polygene.runtime, or it will fail.
+ * </p>
+ */
+public class CleanStackTraceTest extends AbstractPolygeneTest
+{
+    @BeforeClass
+    public static void beforeClass_IBMJDK()
+    {
+        assumeTrue( !( System.getProperty( "java.vendor" ).contains( "IBM" ) ) );
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        module.transients( CleanStackTraceTest.TestComposite.class );
+    }
+
+    /**
+     * Tests that stack trace is cleaned up on an application exception.
+     */
+    @Test
+    public void cleanStackTraceOnApplicationException()
+    {
+        // Don't run the satisfiedBy if compacttrace is set to anything else but proxy
+        String compactTracePropertyValue = System.getProperty( "polygene.compacttrace" );
+        if( compactTracePropertyValue != null && !"proxy".equals( compactTracePropertyValue ) )
+        {
+            return;
+        }
+        TestComposite composite = transientBuilderFactory.newTransient( TestComposite.class );
+        try
+        {
+            composite.doStuff();
+        }
+        catch( RuntimeException e )
+        {
+            String separator = System.getProperty( "line.separator" );
+            String correctTrace1 = "java.lang.RuntimeException: level 2" + separator +
+                                   "\tat org.apache.polygene.test.composite.CleanStackTraceTest$DoStuffMixin.doStuff(CleanStackTraceTest.java:123)" + separator +
+                                   "\tat org.apache.polygene.test.composite.CleanStackTraceTest$NillyWilly.invoke(CleanStackTraceTest.java:135)" + separator +
+                                   "\tat org.apache.polygene.test.composite.CleanStackTraceTest.cleanStackTraceOnApplicationException(CleanStackTraceTest.java:75)";
+            assertEquality( e, correctTrace1 );
+            String correctTrace2 = "java.lang.RuntimeException: level 1" + separator +
+                                   "\tat org.apache.polygene.test.composite.CleanStackTraceTest$DoStuffMixin.doStuff(CleanStackTraceTest.java:119)" + separator +
+                                   "\tat org.apache.polygene.test.composite.CleanStackTraceTest$NillyWilly.invoke(CleanStackTraceTest.java:135)" + separator +
+                                   "\tat org.apache.polygene.test.composite.CleanStackTraceTest.cleanStackTraceOnApplicationException(CleanStackTraceTest.java:75)";
+            assertThat( e.getCause(), notNullValue() );
+            assertEquality( e.getCause(), correctTrace2 );
+        }
+    }
+
+    private void assertEquality( Throwable e, String correctTrace )
+    {
+        StringWriter actualTrace = new StringWriter();
+        e.printStackTrace( new PrintWriter( actualTrace ) );
+
+        String actual = actualTrace.toString();
+        actual = actual.substring( 0, correctTrace.length() );
+        assertEquals( correctTrace, actual );
+    }
+
+    @Concerns( NillyWilly.class )
+    @Mixins( DoStuffMixin.class )
+    public interface TestComposite
+    {
+        void doStuff();
+    }
+
+    public static class DoStuffMixin
+        implements TestComposite
+    {
+        @Override
+        public void doStuff()
+        {
+            try
+            {
+                throw new RuntimeException( "level 1" );
+            }
+            catch( RuntimeException e )
+            {
+                throw new RuntimeException( "level 2", e );
+            }
+        }
+    }
+
+    static class NillyWilly extends GenericConcern
+        implements InvocationHandler
+    {
+        @Override
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            return next.invoke( proxy, method, args );
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/apache/polygene/test/performance/entitystore/memory/MemoryEntityStoreTest.java b/core/runtime/src/test/java/org/apache/polygene/test/performance/entitystore/memory/MemoryEntityStoreTest.java
new file mode 100644
index 0000000..25c4a1b
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/polygene/test/performance/entitystore/memory/MemoryEntityStoreTest.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.test.performance.entitystore.memory;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entitystore.StateChangeListener;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+
+import static org.apache.polygene.bootstrap.ImportedServiceDeclaration.NEW_OBJECT;
+
+/**
+ * Test of MemoryEntityStoreService
+ */
+public class MemoryEntityStoreTest
+    extends AbstractEntityStoreTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+
+        module.services( MemoryEntityStoreService.class );
+        module.importedServices( StatePrinter.class ).importedBy( NEW_OBJECT );
+        module.objects( StatePrinter.class );
+    }
+
+    private static class StatePrinter
+        implements StateChangeListener
+    {
+        public void notifyChanges( Iterable<EntityState> changedStates )
+        {
+            for( EntityState changedState : changedStates )
+            {
+                System.out.println( changedState.status().name() + ":" + changedState.entityReference() );
+            }
+        }
+    }
+}
diff --git a/core/runtime/src/test/java/org/qi4j/api/common/OptionalTest.java b/core/runtime/src/test/java/org/qi4j/api/common/OptionalTest.java
deleted file mode 100644
index 1cdd7f1..0000000
--- a/core/runtime/src/test/java/org/qi4j/api/common/OptionalTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.common;
-
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.junit.Assert.assertThat;
-
-/**
- * Tests for @Optional
- */
-public class OptionalTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TestComposite.class );
-        module.transients( TestComposite2.class );
-        module.entities( TestComposite3.class, TestComposite4.class );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Test
-    public void givenOptionalMethodWhenCorrectInvokeThenNoException()
-    {
-        TestComposite instance = module.newTransient( TestComposite.class );
-        instance.doStuff( "Hello WOrld", "Hello World" );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void givenOptionalMethodWhenMandatoryMissingThenException()
-    {
-        TestComposite instance = module.newTransient( TestComposite.class );
-        instance.doStuff( "Hello World", null );
-    }
-
-    @Test
-    public void givenOptionalMethodWhenOptionalMissingThenNoException()
-    {
-        TestComposite instance = module.newTransient( TestComposite.class );
-        instance.doStuff( null, "Hello World" );
-    }
-
-    @Test
-    public void givenOptionalPropertyWhenOptionalMissingThenNoException()
-    {
-        TransientBuilder<TestComposite2> builder = module.newTransientBuilder( TestComposite2.class );
-        builder.prototype().mandatoryProperty().set( "Hello World" );
-        TestComposite2 testComposite2 = builder.newInstance();
-    }
-
-    @Test
-    public void givenOptionalPropertyWhenOptionalSetThenNoException()
-    {
-        TransientBuilder<TestComposite2> builder = module.newTransientBuilder( TestComposite2.class );
-        builder.prototype().mandatoryProperty().set( "Hello World" );
-        builder.prototype().optionalProperty().set( "Hello World" );
-        TestComposite2 testComposite2 = builder.newInstance();
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void givenMandatoryPropertyWhenMandatoryMissingThenException()
-    {
-        TestComposite2 testComposite2 = module.newTransient( TestComposite2.class );
-    }
-
-    @Test
-    public void givenOptionalAssociationWhenOptionalMissingThenNoException()
-        throws Exception
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            TestComposite4 ref = unitOfWork.newEntity( TestComposite4.class );
-
-            EntityBuilder<TestComposite3> builder = unitOfWork.newEntityBuilder( TestComposite3.class );
-            builder.instance().mandatoryAssociation().set( ref );
-            TestComposite3 testComposite3 = builder.newInstance();
-
-            unitOfWork.complete();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    @Test
-    public void givenOptionalAssociationWhenOptionalSetThenNoException()
-        throws Exception
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            TestComposite4 ref = unitOfWork.newEntity( TestComposite4.class );
-
-            EntityBuilder<TestComposite3> builder = unitOfWork.newEntityBuilder( TestComposite3.class );
-            builder.instance().mandatoryAssociation().set( ref );
-            builder.instance().optionalAssociation().set( ref );
-            TestComposite3 testComposite3 = builder.newInstance();
-
-            unitOfWork.complete();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void givenMandatoryAssociationWhenMandatoryMissingThenException()
-        throws Exception
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            TestComposite4 ref = unitOfWork.newEntity( TestComposite4.class );
-
-            EntityBuilder<TestComposite3> builder = unitOfWork.newEntityBuilder( TestComposite3.class );
-            builder.instance().optionalAssociation().set( ref );
-            TestComposite3 testComposite3 = builder.newInstance();
-
-            unitOfWork.complete();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    @Mixins( TestComposite.TestMixin.class )
-    public interface TestComposite
-        extends TransientComposite
-    {
-        void doStuff( @Optional String optional, String mandatory );
-
-        abstract class TestMixin
-            implements TestComposite
-        {
-            public void doStuff( @Optional String optional, String mandatory )
-            {
-                assertThat( "Mandatory is not null", mandatory, notNullValue() );
-            }
-        }
-    }
-
-    public interface TestComposite2
-        extends TransientComposite
-    {
-        @Optional
-        Property<String> optionalProperty();
-
-        Property<String> mandatoryProperty();
-    }
-
-    public interface TestComposite3
-        extends EntityComposite
-    {
-        @Optional
-        Association<TestComposite4> optionalAssociation();
-
-        Association<TestComposite4> mandatoryAssociation();
-    }
-
-    public interface TestComposite4
-        extends EntityComposite
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/api/common/PluginTest.java b/core/runtime/src/test/java/org/qi4j/api/common/PluginTest.java
deleted file mode 100644
index def6c38..0000000
--- a/core/runtime/src/test/java/org/qi4j/api/common/PluginTest.java
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.common;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.Collections;
-import java.util.List;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceFinder;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.service.ServiceImporterException;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.ApplicationAssemblyFactory;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.LayerName;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ModuleName;
-import org.qi4j.functional.Iterables;
-
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.toArray;
-
-/**
- * Sample of how a plugin architecture could work.
- * The plugins can use services in the main application and the main
- * application can use services from the plugins
- */
-public class PluginTest
-{
-    @Test
-    @Ignore( "Must fix the TODOs below. This example relied on ability to set Service MetaInfo at runtime, it seems it's not possible anymore." )
-    public void testPlugins()
-        throws Exception
-    {
-        Energy4Java runtime = new Energy4Java();
-        Application app = runtime.newApplication( new MainApplicationAssembler() );
-        app.activate();
-    }
-
-    // Main application
-
-    class MainApplicationAssembler
-        implements ApplicationAssembler
-    {
-        public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-            throws AssemblyException
-        {
-            return applicationFactory.newApplicationAssembly( new Assembler[][][]
-                                                              {
-                                                                  {
-                                                                      {
-                                                                          new PluginAssembler(),
-                                                                          new UIAssembler(),
-                                                                      }
-                                                                  },
-                                                                  {
-                                                                      {
-                                                                          new ServiceAssembler()
-                                                                      }
-                                                                  }
-                                                              } );
-        }
-    }
-
-    // The UI uses the plugins
-
-    class UIAssembler
-        implements Assembler
-    {
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.services( PluginTesterService.class ).instantiateOnStartup();
-            module.importedServices( Plugin.class )
-                .importedBy( ServiceFinderImporter.class )
-                .visibleIn( Visibility.layer );
-        }
-    }
-
-    // Get a reference to a plugin and use it
-
-    @Mixins( PluginTesterService.PluginTesterMixin.class )
-    interface PluginTesterService
-        extends ServiceActivation, ServiceComposite
-    {
-        class PluginTesterMixin
-            implements ServiceActivation
-        {
-            @Service
-            Plugin plugin;
-
-            @Service
-            PluginsService plugins;
-
-            public void activateService()
-                throws Exception
-            {
-                // Use plugin
-                System.out.println( plugin.say( "Hello", "World" ) );
-
-                // Restart plugin
-                plugins.passivateService();
-
-                // Plugin is now unavailable
-                try
-                {
-                    System.out.println( plugin.say( "Hello", "World" ) );
-                }
-                catch( ServiceImporterException e )
-                {
-                    // Ignore
-                }
-
-                plugins.activateService();
-
-                // Use plugin
-                System.out.println( plugin.say( "Hello", "World" ) );
-            }
-
-            public void passivateService()
-                throws Exception
-            {
-            }
-        }
-    }
-
-    // Assemble the base service that the plugin can use
-
-    class ServiceAssembler
-        implements Assembler
-    {
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.services( HelloWorldService.class ).visibleIn( Visibility.application );
-        }
-    }
-
-    // Plugins can access service instances with this interface
-
-    interface HelloWorld
-    {
-        String say( String phrase, String name );
-    }
-
-    // Implementation of service that the plugin can use
-
-    @Mixins( HelloWorldService.HelloWorldMixin.class )
-    interface HelloWorldService
-        extends HelloWorld, ServiceComposite
-    {
-        class HelloWorldMixin
-            implements HelloWorld
-        {
-            public String say( String phrase, String name )
-            {
-                return phrase + " " + name;
-            }
-        }
-    }
-
-    // Assemble the plugins module
-
-    class PluginAssembler
-        implements Assembler
-    {
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.services( PluginsService.class ).instantiateOnStartup();
-        }
-    }
-
-// Plugin service
-// This assembles and activates a separate application for the plugins
-// The plugins can look up services in the host application and the
-
-    // plugins can be looked up by the host application
-
-    @Mixins( PluginsService.PluginsMixin.class )
-    interface PluginsService
-        extends ServiceComposite, ServiceActivation
-    {
-        class PluginsMixin
-            implements ServiceActivation
-        {
-            @Structure
-            ServiceFinder finder;
-            @Service
-            ServiceReference<Plugin> plugin;
-            private Application app;
-
-            public void activateService()
-                throws Exception
-            {
-                Energy4Java runtime = new Energy4Java();
-                app = runtime.newApplication( new PluginApplicationAssembler( finder ) );
-
-                app.activate();
-                ServiceFinder pluginFinder = app.findModule( "Plugin layer", "Plugin module" );
-
-                // TODO: Niclas wrote: No clue how all this Test is supposed to work, and can't figure out to create a workaround for this.
-//                finder.findService(Plugin.class).metaInfo().add(ServiceFinder.class, pluginFinder);
-            }
-
-            public void passivateService()
-                throws Exception
-            {
-                // TODO: Niclas wrote: No clue how all this Test is supposed to work, and can't figure out to create a workaround for this.
-//                plugin.metaInfo().remove(ServiceFinder.class);
-
-                app.passivate();
-            }
-        }
-    }
-
-    // Assemble the plugin application
-
-    public static class PluginApplicationAssembler
-        implements ApplicationAssembler
-    {
-        private ServiceFinder finder;
-
-        public PluginApplicationAssembler( ServiceFinder finder )
-        {
-            this.finder = finder;
-        }
-
-        public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-            throws AssemblyException
-        {
-            return applicationFactory.newApplicationAssembly( new Assembler()
-            {
-                public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-                {
-                    new LayerName( "Plugin layer" ).assemble( module );
-                    new ModuleName( "Plugin module" ).assemble( module );
-
-                    LayerAssembly layer = module.layer();
-
-                    // In a real case you would "detect" the plugins somehow. Here the plugin assembler is hardcoded
-                    List<Assembler> pluginAssemblers = Collections.<Assembler>singletonList( new SimonAssembler() );
-
-                    for( int i = 0; i < pluginAssemblers.size(); i++ )
-                    {
-                        ModuleAssembly pluginModule = layer.module( "Plugin " + ( i + 1 ) );
-                        Assembler assembler = pluginAssemblers.get( i );
-                        assembler.assemble( pluginModule );
-                    }
-
-                    // Import host services
-                    module.importedServices( HelloWorld.class )
-                        .importedBy( ServiceFinderImporter.class )
-                        .setMetaInfo( finder )
-                        .visibleIn( Visibility.layer );
-                }
-            } );
-        }
-    }
-
-    // Service importer that uses a ServiceFinder
-
-    public static class ServiceFinderImporter
-        implements ServiceImporter
-    {
-        public Object importService( final ImportedServiceDescriptor serviceDescriptor )
-            throws ServiceImporterException
-        {
-            final Class<?> mainType = first( serviceDescriptor.types() );
-            
-            Class[] interfaces = toArray( Class.class, Iterables.<Class>cast( serviceDescriptor.types() ) );
-            return Proxy.newProxyInstance(
-                mainType.getClassLoader(),
-                interfaces,
-                new InvocationHandler()
-                {
-                    public Object invoke( Object proxy, Method method, Object[] args )
-                        throws Throwable
-                    {
-                        ServiceFinder finder = serviceDescriptor.metaInfo( ServiceFinder.class );
-                        if( finder == null )
-                        {
-                            throw new ServiceImporterException( "No ServiceFinder specified for imported service " + serviceDescriptor
-                                .identity() );
-                        }
-                        Object service = finder.findService( mainType ).get();
-                        return method.invoke( service, args );
-                    }
-                } );
-        }
-
-        public boolean isAvailable( Object instance )
-        {
-            return true;
-        }
-    }
-
-// The plugin interface. Plugins should implement this, and they can then
-
-    // be looked up by the host application
-
-    interface Plugin
-    {
-        String say( String phrase, String name );
-    }
-
-    // Assemble a sample plugin
-
-    public static class SimonAssembler
-        implements Assembler
-    {
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.services( SimonSaysPlugin.class ).visibleIn( Visibility.layer );
-        }
-    }
-
-    // Test implementation of the plugin interface
-
-    @Mixins( SimonSaysPlugin.SimonSaysMixin.class )
-    interface SimonSaysPlugin
-        extends Plugin, ServiceComposite
-    {
-        class SimonSaysMixin
-            implements Plugin
-        {
-            @Service
-            HelloWorld helloWorld;
-            private long time;
-
-            public SimonSaysMixin()
-            {
-                time = System.currentTimeMillis();
-            }
-
-            public String say( String phrase, String name )
-            {
-                return "Simon says:" + helloWorld.say( phrase, name ) + " (plugin started at:" + time + ")";
-            }
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/api/common/PropertyErrorTest.java b/core/runtime/src/test/java/org/qi4j/api/common/PropertyErrorTest.java
deleted file mode 100644
index ee14988..0000000
--- a/core/runtime/src/test/java/org/qi4j/api/common/PropertyErrorTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.common;
-
-import org.junit.Test;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-/**
- * Error messages for Properties
- */
-public class PropertyErrorTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.entities( PersonEntity.class );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void givenEntityWithNonOptionPropertyWhenInstantiatedThenException()
-        throws Exception
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            PersonEntity person = unitOfWork.newEntity( PersonEntity.class );
-
-            unitOfWork.complete();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    interface PersonEntity
-        extends EntityComposite
-    {
-        Property<String> foo();
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/api/common/PropertyTypeTest.java b/core/runtime/src/test/java/org/qi4j/api/common/PropertyTypeTest.java
deleted file mode 100644
index f73f9ea..0000000
--- a/core/runtime/src/test/java/org/qi4j/api/common/PropertyTypeTest.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.common;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-/**
- * Test for ability to set constraints on Properties
- */
-public class PropertyTypeTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.entities( PersonEntity.class );
-        module.transients( PersonComposite.class );
-    }
-
-    @Test
-    public void givenEntityWithPropertyConstraintsWhenInstantiatedThenPropertiesWork()
-        throws Exception
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            EntityBuilder<PersonEntity> builder = unitOfWork.newEntityBuilder( PersonEntity.class );
-            PersonEntity personEntity = builder.instance();
-            personEntity.givenName().set( "Rickard" );
-            personEntity.familyName().set( "Öberg" );
-            personEntity = builder.newInstance();
-
-            personEntity.givenName().set( "Niclas" );
-            personEntity.familyName().set( "Hedhman" );
-
-            unitOfWork.complete();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    @Test
-    public void givenCompositeWithPropertyConstraintsWhenInstantiatedThenPropertiesWork()
-        throws Exception
-    {
-        TransientBuilder<PersonComposite> builder = module.newTransientBuilder( PersonComposite.class );
-        PersonComposite personComposite = builder.prototype();
-        personComposite.givenName().set( "Rickard" );
-        personComposite.familyName().set( "Öberg" );
-        personComposite = builder.newInstance();
-
-        personComposite.givenName().set( "Niclas" );
-        personComposite.familyName().set( "Hedhman" );
-    }
-
-    @ConstraintDeclaration
-    @Retention( RetentionPolicy.RUNTIME )
-    @MaxLength( 50 )
-    public @interface Name
-    {
-    }
-
-    @ConstraintDeclaration
-    @Retention( RetentionPolicy.RUNTIME )
-    @NotEmpty
-    @Name
-    public @interface GivenName
-    {
-    }
-
-    interface PersonEntity
-        extends EntityComposite
-    {
-        @GivenName
-        Property<String> givenName();
-
-        @Name
-        Property<String> familyName();
-    }
-
-    interface PersonComposite
-        extends TransientComposite
-    {
-        @GivenName
-        Property<String> givenName();
-
-        @Name
-        Property<String> familyName();
-    }
-
-    @ConstraintDeclaration
-    @Retention( RetentionPolicy.RUNTIME )
-    @Constraints( MaxLengthConstraint.class )
-    public @interface MaxLength
-    {
-        int value();
-    }
-
-    public static class MaxLengthConstraint
-        implements Constraint<MaxLength, String>
-    {
-        public boolean isValid( MaxLength annotation, String argument )
-        {
-            if( argument != null )
-            {
-                return argument.length() <= annotation.value();
-            }
-
-            return false;
-        }
-    }
-
-    @ConstraintDeclaration
-    @Retention( RetentionPolicy.RUNTIME )
-    @Constraints( { NotEmptyStringConstraint.class } )
-    public @interface NotEmpty
-    {
-    }
-
-    public static class NotEmptyStringConstraint
-        implements Constraint<NotEmpty, String>
-    {
-
-        public boolean isValid( NotEmpty annotation, String value )
-        {
-            return value.trim().length() > 0;
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/api/common/RemovalTest.java b/core/runtime/src/test/java/org/qi4j/api/common/RemovalTest.java
deleted file mode 100644
index d4d9696..0000000
--- a/core/runtime/src/test/java/org/qi4j/api/common/RemovalTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.api.common;
-
-import org.junit.Test;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-public class RemovalTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( TestEntity.class );
-        module.entities( PidRegulator.class );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Test
-    public void givenEntityIsCreatedAndUnitOfWorkIsNotCompletedWhenEntityIsRemoveThenSuccessfulRemoval()
-        throws Exception
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        EntityBuilder<TestEntity> builder = uow.newEntityBuilder( TestEntity.class, "123" );
-        builder.instance().test().set( "habba" );
-        TestEntity test = builder.newInstance();
-        uow.remove( test );
-        uow.complete();
-    }
-
-    @Test
-    public void givenStandardPidRegulatorWhenNoChangeInInputExpectOutputToGoTowardsMinimum()
-        throws Exception
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        PidRegulator regulator = null;
-        try
-        {
-            regulator = createPidRegulator( uow );
-        }
-        finally
-        {
-            if( regulator != null )
-            {
-                uow.remove( regulator );
-            }
-            // TODO: This problem is related to that uow.remove() has a bug.
-            // If the Entity is both created and removed in the same session, then the remove() should simply remove
-            // the entity from the internal UoW holding area, and not set the REMOVED status.
-
-            // Probably that UnitOfWorkInstance.remove() should also call instanceCache.remove(), but the question is
-            // then what is an InstanceKey vs EntityReference
-            uow.complete();
-        }
-    }
-
-    public interface TestEntity
-        extends EntityComposite
-    {
-        @Optional
-        Property<String> test();
-    }
-
-    private PidRegulator createPidRegulator( UnitOfWork uow )
-        throws UnitOfWorkCompletionException
-    {
-        EntityBuilder<PidRegulator> builder = uow.newEntityBuilder( PidRegulator.class );
-        PidRegulator prototype = builder.instance();
-        prototype.p().set( 1.0f );
-        prototype.i().set( 10f );
-        prototype.d().set( 0.1f );
-        prototype.maxD().set( 10f );
-        prototype.maximum().set( 100f );
-        prototype.minimum().set( 0f );
-        PidRegulator regulator = builder.newInstance();
-
-        return regulator;
-    }
-
-    //    @Mixins( { PidRegulatorAlgorithmMixin.class } )
-    public interface PidRegulator
-        extends PidParameters, EntityComposite
-    {
-    }
-
-    public interface PidParameters
-    {
-        Property<Float> p();
-
-        Property<Float> i();
-
-        Property<Float> d();
-
-        Property<Float> maxD();
-
-        Property<Float> minimum();
-
-        Property<Float> maximum();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/api/common/ValueCompositeTest.java b/core/runtime/src/test/java/org/qi4j/api/common/ValueCompositeTest.java
deleted file mode 100644
index fd3fc19..0000000
--- a/core/runtime/src/test/java/org/qi4j/api/common/ValueCompositeTest.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.api.common;
-
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-/**
- * Tests for ValueComposites
- */
-public class ValueCompositeTest
-    extends AbstractQi4jTest
-{
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.values( SomeValue.class, AnotherValue.class );
-        module.entities( SomeEntity.class );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Test( expected = IllegalStateException.class )
-    public void testImmutabilityOfValueComposite()
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        SomeValue some = builder.prototype();
-        some.other().set( "test" );
-        some = builder.newInstance();
-        some.other().set( "test2" );
-    }
-
-    @Test
-    public void testCreationOfValueComposite()
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        SomeValue some = builder.prototype();
-        some.other().set( "test" );
-        builder.newInstance();
-    }
-
-    @Test
-    public void testEqualityOfValueComposite()
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        SomeValue prototype = builder.prototype();
-        prototype.other().set( "test" );
-        SomeValue instance = builder.newInstance();
-
-        builder = module.newValueBuilder( SomeValue.class );
-        prototype = builder.prototype();
-        prototype.other().set( "test" );
-        SomeValue other = builder.newInstance();
-        Assert.assertFalse( "Instances should not be the same.", instance == other );
-        Assert.assertEquals( "Equal values.", instance, other );
-    }
-
-    @Test
-    public void testHashcodeOfValueComposite()
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        SomeValue prototype = builder.prototype();
-        prototype.other().set( "test" );
-        SomeValue instance = builder.newInstance();
-
-        builder = module.newValueBuilder( SomeValue.class );
-        prototype = builder.prototype();
-        prototype.other().set( "test" );
-        SomeValue other = builder.newInstance();
-        Assert.assertFalse( "Instances should not be the same.", instance == other );
-        Assert.assertEquals( "Equal values.", instance.hashCode(), other.hashCode() );
-    }
-
-    @Test
-    public void testModifyValue()
-    {
-        ValueBuilder<AnotherValue> anotherBuilder = module.newValueBuilder( AnotherValue.class );
-        anotherBuilder.prototype().val1().set( "Val1" );
-        AnotherValue anotherValue = anotherBuilder.newInstance();
-
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        SomeValue prototype = builder.prototype();
-        prototype.some().set( "foo" );
-        prototype.other().set( "test" );
-        prototype.xyzzyList().get().add( "blah" );
-        prototype.another().set( anotherValue );
-        SomeValue instance = builder.newInstance();
-
-        assertThat( "List has value blah", instance.xyzzyList().get().get( 0 ), equalTo( "blah" ) );
-
-        // Modify value
-        builder = module.newValueBuilderWithPrototype( instance );
-        builder.prototype().some().set( "bar" );
-        instance = builder.newInstance();
-
-        assertThat( "Other is set to test", instance.other().get(), equalTo( "test" ) );
-        assertThat( "List has value blah", instance.xyzzyList().get().get( 0 ), equalTo( "blah" ) );
-        assertThat( "AnotherValue.val1 has value Val1", instance.another().get().val1().get(), equalTo( "Val1" ) );
-
-        // Modify value again using method 2
-        builder = module.newValueBuilderWithPrototype( instance );
-        builder.prototype().other().set( "test2" );
-        instance = builder.newInstance();
-
-        assertThat( "Other is set to test2", instance.other().get(), equalTo( "test2" ) );
-        assertThat( "Some is set to bar", instance.some().get(), equalTo( "bar" ) );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void givenValueWhenModifyToIncorrectValueThenThrowConstraintException()
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        SomeValue prototype = builder.prototype();
-        prototype.some().set( "foo" );
-        SomeValue instance = builder.newInstance();
-
-        builder = module.newValueBuilderWithPrototype( instance );
-        builder.prototype().some().set( null );
-    }
-
-    @Test
-    public void givenValueWithListOfValueWhenPrototypeThenListedValuesAreEditable()
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        builder.prototype().anotherList().get().add( module.newValue( AnotherValue.class ) );
-        SomeValue some = builder.newInstance();
-
-        builder = module.newValueBuilderWithPrototype( some );
-        builder.prototype().anotherList().get().get( 0 ).val1().set( "Foo" );
-        builder.prototype().anotherList().get().add( module.newValue( AnotherValue.class ) );
-        some = builder.newInstance();
-
-        assertThat( "Val1 has been set", some.anotherList().get().get( 0 ).val1().get(), equalTo( "Foo" ) );
-
-        try
-        {
-            some.anotherList().get().get( 0 ).val1().set( "Bar" );
-            Assert.fail( "Should not be allowed to modify value" );
-        }
-        catch( IllegalStateException e )
-        {
-            // Ok
-        }
-    }
-
-    @Test
-    public void givenEntityWhenUpdateValueThenValueIsSet()
-        throws UnitOfWorkCompletionException
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        builder.prototype().anotherList().get().add( module.newValue( AnotherValue.class ) );
-        ValueBuilder<AnotherValue> valueBuilder = module.newValueBuilder( AnotherValue.class );
-        valueBuilder.prototype().val1().set( "Foo" );
-        builder.prototype().another().set( valueBuilder.newInstance() );
-        builder.prototype().number().set( 42L );
-        SomeValue some = builder.newInstance();
-
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        EntityBuilder<SomeEntity> entityBuilder = unitOfWork.newEntityBuilder( SomeEntity.class );
-        entityBuilder.instance().someValue().set( some );
-        SomeEntity entity = entityBuilder.newInstance();
-
-        assertThat( "Value has been set", entity.someValue().get().another().get().val1().get(), equalTo( "Foo" ) );
-
-        unitOfWork.complete();
-    }
-
-    public enum TestEnum
-    {
-        somevalue, anothervalue
-    }
-
-    public interface SomeValue
-        extends ValueComposite
-    {
-        @UseDefaults
-        Property<String> some();
-
-        @UseDefaults
-        Property<String> other();
-
-        @UseDefaults
-        Property<Long> number();
-
-        @UseDefaults
-        Property<List<String>> xyzzyList();
-
-        @Optional
-        Property<AnotherValue> another();
-
-        @UseDefaults
-        Property<List<AnotherValue>> anotherList();
-
-        @UseDefaults
-        Property<TestEnum> testEnum();
-    }
-
-    public interface AnotherValue
-        extends ValueComposite
-    {
-        @UseDefaults
-        Property<String> val1();
-    }
-
-    public interface SomeEntity
-        extends EntityComposite
-    {
-        Property<SomeValue> someValue();
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/bootstrap/ApplicationAssemblerTest.java b/core/runtime/src/test/java/org/qi4j/bootstrap/ApplicationAssemblerTest.java
deleted file mode 100644
index 0894619..0000000
--- a/core/runtime/src/test/java/org/qi4j/bootstrap/ApplicationAssemblerTest.java
+++ /dev/null
@@ -1,106 +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.qi4j.bootstrap;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.functional.HierarchicalVisitorAdapter;
-import org.qi4j.functional.Specifications;
-
-/**
- * TODO
- */
-public class ApplicationAssemblerTest
-{
-    @Test
-    public void testApplicationAssembler()
-        throws AssemblyException
-    {
-        Energy4Java is = new Energy4Java();
-
-        ApplicationDescriptor model = is.newApplicationModel( new ApplicationAssembler()
-        {
-            @Override
-            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-                throws AssemblyException
-            {
-                ApplicationAssembly assembly = applicationFactory.newApplicationAssembly();
-
-                LayerAssembly layer1 = assembly.layer( "Layer1" );
-
-                ModuleAssembly module = layer1.module( "Module1" );
-
-                module.services( TestService.class );
-
-                module.entities( TestEntity.class );
-
-                layer1.services( AssemblySpecifications.types( TestService.class ) ).instantiateOnStartup();
-
-                layer1.services( Specifications.<Object>TRUE() ).visibleIn( Visibility.layer );
-
-                layer1.entities( Specifications.<Object>TRUE() ).visibleIn( Visibility.application );
-
-                return assembly;
-            }
-        } );
-
-        model.accept( new HierarchicalVisitorAdapter<Object, Object, RuntimeException>()
-        {
-            @Override
-            public boolean visitEnter( Object visited )
-                throws RuntimeException
-            {
-                if( visited instanceof ServiceDescriptor )
-                {
-                    ServiceDescriptor serviceDescriptor = (ServiceDescriptor) visited;
-                    Assert.assertTrue( serviceDescriptor.isInstantiateOnStartup() );
-                    Assert.assertTrue( serviceDescriptor.visibility() == Visibility.layer );
-                    return false;
-                }
-                else if( visited instanceof EntityDescriptor )
-                {
-                    EntityDescriptor entityDescriptor = (EntityDescriptor) visited;
-                    Assert.assertTrue( entityDescriptor.visibility() == Visibility.application );
-                    return false;
-                }
-
-                return true;
-            }
-        } );
-        model.newInstance( is.spi() );
-    }
-
-    interface TestService
-        extends ServiceComposite
-    {
-
-    }
-
-    interface TestEntity
-        extends EntityComposite
-    {
-
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/constraints/PropertyConstraintTest.java b/core/runtime/src/test/java/org/qi4j/constraints/PropertyConstraintTest.java
deleted file mode 100644
index 32e76b6..0000000
--- a/core/runtime/src/test/java/org/qi4j/constraints/PropertyConstraintTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.constraints;
-
-import java.util.Collection;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.constraint.ConstraintViolation;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.constraints.MinLengthConstraint;
-import org.qi4j.library.constraints.annotation.Matches;
-import org.qi4j.library.constraints.annotation.MinLength;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-public class PropertyConstraintTest
-    extends AbstractQi4jTest
-{
-    @org.junit.Test
-    public void givenConstraintOnPropertyWhenInvalidValueThenThrowException()
-        throws Throwable
-    {
-        TransientBuilder<Test> builder = module.newTransientBuilder( Test.class );
-        builder.prototype().test().set( "XXXXXX" );
-        Test test = builder.newInstance();
-        try
-        {
-            test.test().set( "YY" );
-            fail( "Should have thrown a ConstraintViolationException." );
-        }
-        catch( ConstraintViolationException e )
-        {
-            Collection<ConstraintViolation> violations = e.constraintViolations();
-            assertEquals( 2, violations.size() );
-        }
-    }
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TestComposite.class );
-    }
-
-    @Constraints( { MinLengthConstraint.class } )
-    public interface TestComposite
-        extends Test, TransientComposite
-    {
-    }
-
-    public interface Test
-    {
-        @MinLength( 3 )
-        @Matches( "X*" )
-        Property<String> test();
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/regression/qi230/Qi230IssueTest.java b/core/runtime/src/test/java/org/qi4j/regression/qi230/Qi230IssueTest.java
deleted file mode 100644
index 5b22265..0000000
--- a/core/runtime/src/test/java/org/qi4j/regression/qi230/Qi230IssueTest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.regression.qi230;
-
-import org.junit.Test;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.mixin.NoopMixin;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * JAVADOC
- */
-public class Qi230IssueTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( Some.class ).withMixins( NoopMixin.class ).withConcerns( OtherConcern.class );
-//        module.services( Some.class );
-        module.services( Result.class );
-    }
-
-    @Test
-    public void whenDerefencingInsideConcernThisExpectItToWork()
-        throws Exception
-    {
-        Result result = module.findService( Result.class ).get();
-        Some some = module.findService( Some.class ).get();
-        assertEquals( "method()", some.method() );
-        assertEquals( some.identity(), result.some().identity() );
-        assertEquals( some.identity().get(), result.some().identity().get() );
-    }
-
-    @Mixins( ResultMixin.class )
-    public interface Result
-        extends ServiceComposite
-    {
-        void execute( Some value );
-
-        Some some();
-    }
-
-    public static abstract class ResultMixin
-        implements Result
-    {
-
-        private Some value;
-
-        public void execute( Some value )
-        {
-            this.value = value;
-        }
-
-        public Some some()
-        {
-            return value;
-        }
-    }
-
-    @Concerns( OtherConcern.class )
-    @Mixins( NoopMixin.class )
-    public interface Other
-    {
-        void other();
-    }
-
-    @Mixins( SomeMixin.class )
-    public interface Some
-        extends ServiceComposite
-//        extends ServiceComposite, Other
-    {
-        String method();
-    }
-
-    public abstract static class SomeMixin
-        implements Some
-    {
-        @This
-        private Other other;
-
-        public String method()
-        {
-            other.other();
-            return "method()";
-        }
-    }
-
-    public static class OtherConcern
-        extends ConcernOf<Other>
-        implements Other
-    {
-        @Structure
-        private Qi4j api;
-
-        @This
-        private Composite me;
-
-        @Service
-        private Result result;
-
-        public void other()
-        {
-            Composite value = api.dereference( me );
-            result.execute( (Some) value );
-            next.other();
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/regression/qi377/InterfaceCollisionWithRelatedReturnTypesTest.java b/core/runtime/src/test/java/org/qi4j/regression/qi377/InterfaceCollisionWithRelatedReturnTypesTest.java
deleted file mode 100644
index b467a4d..0000000
--- a/core/runtime/src/test/java/org/qi4j/regression/qi377/InterfaceCollisionWithRelatedReturnTypesTest.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 2013, Chris Chapman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.regression.qi377;
-
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertThat;
-
-public class InterfaceCollisionWithRelatedReturnTypesTest
-    extends AbstractQi4jTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.entities( Employee.class, Company.class );
-    }
-
-    @Test
-    public void shouldBeAbleToSetNameToTheCompany()
-        throws UnitOfWorkCompletionException
-    {
-        String identity;
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            Company startUp = uow.newEntity( Company.class );
-            startUp.name().set( "Acme" );
-            identity = ( (Identity) startUp ).identity().get();
-            uow.complete();
-        }
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            Company startUp = uow.get( Company.class, identity );
-            assertThat( startUp.name().get(), equalTo( "Acme" ) );
-
-            SalesTeam sales = uow.get( SalesTeam.class, identity );
-            assertThat( sales.name().get(), equalTo( "Acme" ) );
-
-            ResearchTeam research = uow.get( ResearchTeam.class, identity );
-            assertThat( research.name().get(), equalTo( "Acme" ) );
-        }
-    }
-
-    @Test
-    public void shouldBeAbleToSetLeadToTheCompany()
-        throws UnitOfWorkCompletionException
-    {
-        String identity;
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            Company startUp = uow.newEntity( Company.class );
-            Employee niclas = uow.newEntity( Employee.class );
-
-            startUp.lead().set( niclas );
-            identity = ( (Identity) startUp ).identity().get();
-
-            uow.complete();
-        }
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            Company startUp = uow.get( Company.class, identity );
-            Employee niclas = startUp.lead().get();
-            assertThat( niclas, notNullValue() );
-
-            SalesTeam sales = uow.get( SalesTeam.class, identity );
-            assertThat( sales.lead().get(), equalTo( niclas ) );
-
-            ResearchTeam research = uow.get( ResearchTeam.class, identity );
-            assertThat( research.lead().get(), equalTo( niclas ) );
-        }
-    }
-
-    @Test
-    public void shouldBeAbleToSetLeadToTheSalesTeam()
-    {
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            SalesTeam startUp = uow.newEntity( SalesTeam.class );
-            Employee niclas = uow.newEntity( Employee.class );
-
-            startUp.lead().set( niclas );
-        }
-    }
-
-    @Test
-    public void shouldBeAbleToSetLeadToTheResearchTeam()
-    {
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            ResearchTeam startUp = uow.newEntity( ResearchTeam.class );
-            Employee niclas = uow.newEntity( Employee.class );
-
-            startUp.lead().set( niclas );
-        }
-    }
-
-    @Test
-    public void shouldBeAbleToAddEmployeesToTheCompany()
-    {
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            Company startUp = uow.newEntity( Company.class );
-            Employee niclas = uow.newEntity( Employee.class );
-
-            // To which team is Niclas added? Seems to be the interface listed first in the interface declaration?
-            // This contrived example is probably just bad design...
-            startUp.employees().add( niclas );
-        }
-    }
-
-    @Test
-    public void shouldBeAbleToAddEmployeesToTheSalesTeam()
-    {
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            SalesTeam startUp = uow.newEntity( SalesTeam.class );
-            Employee niclas = uow.newEntity( Employee.class );
-
-            startUp.employees().add( niclas );
-        }
-    }
-
-    @Test
-    public void shouldBeAbleToAddEmployeesToTheResearchTeam()
-    {
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            ResearchTeam startUp = uow.newEntity( ResearchTeam.class );
-            Employee niclas = uow.newEntity( Employee.class );
-
-            startUp.employees().add( niclas );
-        }
-    }
-
-    public interface Employee
-    {
-    }
-
-    public interface SalesTeam
-    {
-        @Optional
-        Property<String> name();
-
-        @Optional
-        Association<Employee> lead();
-
-        ManyAssociation<Employee> employees();
-    }
-
-    public interface ResearchTeam
-    {
-        @Optional
-        Property<String> name();
-
-        @Optional
-        Association<Employee> lead();
-
-        ManyAssociation<Employee> employees();
-    }
-
-    /**
-     * This compiles, unlike the example in {@link InterfaceCollisionWithUnrelatedReturnTypesTest}.
-     */
-    public interface Company
-        extends SalesTeam, ResearchTeam
-    {
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/regression/qi377/InterfaceCollisionWithUnrelatedReturnTypesTest.java b/core/runtime/src/test/java/org/qi4j/regression/qi377/InterfaceCollisionWithUnrelatedReturnTypesTest.java
deleted file mode 100644
index a0d7f90..0000000
--- a/core/runtime/src/test/java/org/qi4j/regression/qi377/InterfaceCollisionWithUnrelatedReturnTypesTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2013, Chris Chapman. All Rights Reserved.
- *
- * Licensed  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.qi4j.regression.qi377;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-public class InterfaceCollisionWithUnrelatedReturnTypesTest
-    extends AbstractQi4jTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-    }
-
-    public interface Person
-    {
-        @UseDefaults
-        Property<String> name();
-    }
-
-    public interface Robot
-    {
-        @UseDefaults
-        Property<Integer> name();
-    }
-
-    /**
-     * DOESN'T COMPILE!!!
-     * java: types org.qi4j.regression.qi377.InterfaceCollisionWithUnrelatedReturnTypesTest.Robot and org.qi4j.regression.qi377.InterfaceCollisionWithUnrelatedReturnTypesTest.Person are incompatible; both define name(), but with unrelated return types
-     */
-//    public interface TeamMember extends Person, Robot {}
-}
diff --git a/core/runtime/src/test/java/org/qi4j/regression/qi377/IssueTest.java b/core/runtime/src/test/java/org/qi4j/regression/qi377/IssueTest.java
deleted file mode 100644
index e0a0cba..0000000
--- a/core/runtime/src/test/java/org/qi4j/regression/qi377/IssueTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2013, Chris Chapman. All Rights Reserved.
- *
- * Licensed  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.qi4j.regression.qi377;
-
-import org.junit.Test;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
-
-public class IssueTest
-    extends AbstractQi4jTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TeamMember.class );
-    }
-
-    @Test
-    public void propertyNameCollisionsShouldWork()
-    {
-        TeamMember m = module.newTransient( TeamMember.class );
-        m.name().set( "Niclas" );
-        Person p = m;
-        p.name().set( "Chris" );
-        Employee e = m;
-        e.name().set( "Paul" );
-
-        assertThat( m.name().get(), equalTo( "Paul" ) );
-        assertThat( e.name().get(), equalTo( "Paul" ) );
-        assertThat( p.name().get(), equalTo( "Paul" ) );
-    }
-
-    public interface Person
-    {
-        @UseDefaults
-        Property<String> name();
-    }
-
-    public interface Employee
-    {
-        @UseDefaults
-        Property<String> name();
-    }
-
-    public interface TeamMember
-        extends Person, Employee
-    {
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/regression/qi377/SetAssociationInSideEffectTest.java b/core/runtime/src/test/java/org/qi4j/regression/qi377/SetAssociationInSideEffectTest.java
deleted file mode 100644
index b40ef28..0000000
--- a/core/runtime/src/test/java/org/qi4j/regression/qi377/SetAssociationInSideEffectTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2013, Chris Chapman. All Rights Reserved.
- *
- * Licensed  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.qi4j.regression.qi377;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.reflect.Method;
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.sideeffect.GenericSideEffect;
-import org.qi4j.api.sideeffect.SideEffects;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.theInstance;
-import static org.junit.Assert.assertThat;
-
-public class SetAssociationInSideEffectTest
-    extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-
-        module.entities( Pianist.class, Steinway.class );
-    }
-
-    @Test
-    public void whenSettingAnAssociationInASideEffectExpectItToWork()
-    {
-        try( UnitOfWork uow = module.newUnitOfWork( UsecaseBuilder.newUsecase( "Purchase Steinway" ) ) )
-        {
-            Pianist chris = uow.newEntity( Pianist.class, "Chris" );
-            Steinway modelD = uow.newEntity( Steinway.class, "ModelD-274" );
-
-            assertThat( modelD.owner().get(), is( nullValue() ) );
-
-            chris.purchase( modelD );
-
-            assertThat( modelD.owner().get(), is( theInstance( (Owner) chris ) ) );
-        }
-    }
-
-    @Mixins( PianistMixin.class )
-    @SideEffects( ChangeOwnerSideEffect.class )
-    public interface Pianist
-        extends Owner, EntityComposite
-    {
-        @Optional
-        Association<Steinway> steinway();
-
-        @ChangesOwner
-        void purchase( Steinway piano );
-    }
-
-    public static abstract class PianistMixin
-        implements Pianist
-    {
-        @Override
-        public void purchase( Steinway piano )
-        {
-            steinway().set( piano );
-        }
-    }
-
-    public interface Steinway
-        extends Ownable, EntityComposite
-    {
-    }
-
-    public interface Owner
-    {
-    }
-
-    public interface Ownable
-    {
-        @Optional
-        Association<Owner> owner();
-    }
-
-    @AppliesTo( ChangesOwner.class )
-    public static class ChangeOwnerSideEffect
-        extends GenericSideEffect
-    {
-        @This
-        Owner owner;
-
-        @Override
-        protected void invoke( Method method, Object[] args )
-            throws Throwable
-        {
-            Ownable ownable = (Ownable) args[ 0];
-            ownable.owner().set( owner );
-        }
-    }
-
-    @Retention( RetentionPolicy.RUNTIME )
-    public @interface ChangesOwner
-    {
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/regression/qi377/ValueCollisionWithRelatedReturnTypesTest.java b/core/runtime/src/test/java/org/qi4j/regression/qi377/ValueCollisionWithRelatedReturnTypesTest.java
deleted file mode 100644
index ea232c1..0000000
--- a/core/runtime/src/test/java/org/qi4j/regression/qi377/ValueCollisionWithRelatedReturnTypesTest.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2013, Chris Chapman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.regression.qi377;
-
-import org.junit.Test;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-public class ValueCollisionWithRelatedReturnTypesTest
-    extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.values( Employee.class, Company.class );
-    }
-
-    @Test
-    public void shouldBeAbleToSetNameToTheCompany()
-    {
-        ValueBuilder<Company> builder = module.newValueBuilder( Company.class );
-        builder.prototype().name().set( "Acme" );
-        Company startUp = builder.newInstance();
-    }
-
-    @Test
-    public void shouldBeAbleToSetLeadToTheCompany()
-    {
-        Company startUp = module.newValue( Company.class );
-        ValueBuilder<Employee> builder = module.newValueBuilder( Employee.class );
-        builder.prototype().identity().set( "niclas" );
-        Employee niclas = builder.newInstance();
-        startUp.lead().set( niclas );
-    }
-
-    @Test
-    public void shouldBeAbleToSetLeadToTheSalesTeam()
-    {
-        SalesTeam startUp = module.newValue( SalesTeam.class );
-        ValueBuilder<Employee> builder = module.newValueBuilder( Employee.class );
-        builder.prototype().identity().set( "niclas" );
-        Employee niclas = builder.newInstance();
-        startUp.lead().set( niclas );
-    }
-
-    @Test
-    public void shouldBeAbleToSetLeadToTheResearchTeam()
-    {
-        ResearchTeam startUp = module.newValue( ResearchTeam.class );
-        ValueBuilder<Employee> builder = module.newValueBuilder( Employee.class );
-        builder.prototype().identity().set( "niclas" );
-        Employee niclas = builder.newInstance();
-        startUp.lead().set( niclas );
-    }
-
-    @Test
-    public void shouldBeAbleToAddEmployeesToTheCompany()
-    {
-        Company startUp = module.newValue( Company.class );
-        ValueBuilder<Employee> builder = module.newValueBuilder( Employee.class );
-        builder.prototype().identity().set( "niclas" );
-        Employee niclas = builder.newInstance();
-        startUp.employees().add( niclas );
-    }
-
-    @Test
-    public void shouldBeAbleToAddEmployeesToTheSalesTeam()
-    {
-        SalesTeam startUp = module.newValue( SalesTeam.class );
-        ValueBuilder<Employee> builder = module.newValueBuilder( Employee.class );
-        builder.prototype().identity().set( "niclas" );
-        Employee niclas = builder.newInstance();
-        startUp.employees().add( niclas );
-    }
-
-    @Test
-    public void shouldBeAbleToAddEmployeesToTheResearchTeam()
-    {
-        ResearchTeam startUp = module.newValue( ResearchTeam.class );
-        ValueBuilder<Employee> builder = module.newValueBuilder( Employee.class );
-        builder.prototype().identity().set( "niclas" );
-        Employee niclas = builder.newInstance();
-        startUp.employees().add( niclas );
-    }
-
-    public interface Employee
-        extends Identity
-    {
-    }
-
-    public interface SalesTeam
-    {
-        @Optional
-        Property<String> name();
-
-        @Optional
-        Association<Employee> lead();
-
-        ManyAssociation<Employee> employees();
-    }
-
-    public interface ResearchTeam
-    {
-        @Optional
-        Property<String> name();
-
-        @Optional
-        Association<Employee> lead();
-
-        ManyAssociation<Employee> employees();
-    }
-
-    /**
-     * This compiles, unlike the example in {@link InterfaceCollisionWithUnrelatedReturnTypesTest}.
-     */
-    public interface Company
-        extends SalesTeam, ResearchTeam
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/regression/qi382/Qi382Test.java b/core/runtime/src/test/java/org/qi4j/regression/qi382/Qi382Test.java
deleted file mode 100644
index bbb8c27..0000000
--- a/core/runtime/src/test/java/org/qi4j/regression/qi382/Qi382Test.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2013 Niclas Hedhman.
- *
- * Licensed  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.qi4j.regression.qi382;
-
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.Lifecycle;
-import org.qi4j.api.entity.LifecycleException;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertThat;
-
-public class Qi382Test extends AbstractQi4jTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.addServices( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
-        module.addServices( MemoryEntityStoreService.class );
-        module.entities( Car.class, Person.class );
-    }
-
-    @Test
-    public void givenCreationOfTwoEntitiesWhenAssigningOneToOtherExpectCompletionToSucceed()
-        throws UnitOfWorkCompletionException
-    {
-        try( UnitOfWork unitOfWork = module.newUnitOfWork() )
-        {
-            Car car = unitOfWork.newEntity( Car.class, "Ferrari" );
-            unitOfWork.complete();
-        }
-        try( UnitOfWork unitOfWork = module.newUnitOfWork() )
-        {
-            Car car = unitOfWork.get( Car.class, "Ferrari" );
-            assertThat( car, notNullValue() );
-            Person p = unitOfWork.get( Person.class, "Niclas" );
-            assertThat( p, notNullValue() );
-            assertThat( p.car().get(), equalTo( car ) );
-        }
-    }
-
-    @Mixins( Car.CarMixin.class )
-    public interface Car extends EntityComposite, Lifecycle
-    {
-
-        static class CarMixin implements Lifecycle
-        {
-            @This
-            private Car me;
-
-            @Structure
-            private Module module;
-
-            @Override
-            public void create()
-                throws LifecycleException
-            {
-                UnitOfWork unitOfWork = module.currentUnitOfWork();
-                EntityBuilder<Person> builder = unitOfWork.newEntityBuilder( Person.class, "Niclas" );
-                builder.instance().car().set( me );
-                builder.newInstance();
-            }
-
-            @Override
-            public void remove()
-                throws LifecycleException
-            {
-
-            }
-        }
-    }
-
-    public interface Person extends EntityComposite
-    {
-        Association<Car> car();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/regression/qi383/Qi383Test.java b/core/runtime/src/test/java/org/qi4j/regression/qi383/Qi383Test.java
deleted file mode 100644
index 8fd2df5..0000000
--- a/core/runtime/src/test/java/org/qi4j/regression/qi383/Qi383Test.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2013 Niclas Hedhman.
- *
- * Licensed  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.qi4j.regression.qi383;
-
-import org.junit.Test;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.unitofwork.EntityCompositeAlreadyExistsException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-public class Qi383Test extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.addServices( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
-        module.addServices( MemoryEntityStoreService.class );
-        module.entities( Car.class );
-    }
-
-    @Test( expected = EntityCompositeAlreadyExistsException.class )
-    public void givenUnitOfWorkInProgressWhenAddingSameEntityTwiceExpectException()
-        throws UnitOfWorkCompletionException
-    {
-        try( UnitOfWork unitOfWork = module.newUnitOfWork() )
-        {
-            unitOfWork.newEntity( Car.class, "Ferrari" );
-            unitOfWork.newEntity( Car.class, "Ford" );
-            unitOfWork.newEntity( Car.class, "Ferrari" );
-            unitOfWork.complete();
-        }
-    }
-
-    public interface Car extends EntityComposite
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/regression/qi53/IssueTest.java b/core/runtime/src/test/java/org/qi4j/regression/qi53/IssueTest.java
deleted file mode 100644
index c1b5156..0000000
--- a/core/runtime/src/test/java/org/qi4j/regression/qi53/IssueTest.java
+++ /dev/null
@@ -1,103 +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.qi4j.regression.qi53;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientBuilderFactory;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-
-public class IssueTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( CostPerUnitComposite.class );
-    }
-
-    @Test
-    public void genericPropertiesAndParameters()
-        throws SecurityException, NoSuchMethodException
-    {
-        TransientBuilder<CostPerUnitComposite> builder = module.newTransientBuilder( CostPerUnitComposite.class );
-        builder.prototype().unit().set( new Unit<Integer>( 10 ) );
-        CostPerUnitComposite test = builder.newInstance();
-        assertEquals( 10, test.unit().get().value );
-        assertEquals( 50, test.toCostPer( new Unit<Integer>( 50 ) ).unit().get().value );
-    }
-
-    public interface CostPerUnit
-    {
-        @Immutable
-        Property<Unit<?>> unit();
-
-        CostPerUnit toCostPer( Unit<?> unit );
-    }
-
-    public static class Unit<T>
-    {
-        private T value;
-
-        public Unit( T value )
-        {
-            this.value = value;
-        }
-
-        T get()
-        {
-            return value;
-        }
-    }
-
-    public static abstract class CostPerUnitMixin
-        implements CostPerUnit
-    {
-
-        @This
-        CostPerUnit costPerUnit;
-        @Structure
-        TransientBuilderFactory builderFactory;
-
-        public CostPerUnit toCostPer( Unit<?> unit )
-        {
-            TransientBuilder<CostPerUnitComposite> builder =
-                builderFactory.newTransientBuilder( CostPerUnitComposite.class );
-
-            builder.prototype().unit().set( unit );
-            return builder.newInstance();
-        }
-    }
-
-    @Mixins( { CostPerUnitMixin.class } )
-    public interface CostPerUnitComposite
-        extends CostPerUnit, TransientComposite
-    {
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/regression/qi55/IssueTest.java b/core/runtime/src/test/java/org/qi4j/regression/qi55/IssueTest.java
deleted file mode 100644
index 6171308..0000000
--- a/core/runtime/src/test/java/org/qi4j/regression/qi55/IssueTest.java
+++ /dev/null
@@ -1,56 +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.qi4j.regression.qi55;
-
-import org.junit.Test;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-
-public class IssueTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.objects( AClass.class );
-    }
-
-    @Test
-    public void objectWithGenericUsage()
-    {
-        assertEquals( "Using - Test string", module.
-            newObject( AClass.class, "Test string" ).
-            uses() );
-    }
-
-    public static class AClass<T>
-    {
-        @Uses
-        T value;
-
-        public String uses()
-        {
-            return "Using - " + value;
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/regression/qi59/IssueTest.java b/core/runtime/src/test/java/org/qi4j/regression/qi59/IssueTest.java
deleted file mode 100644
index 34b44c0..0000000
--- a/core/runtime/src/test/java/org/qi4j/regression/qi59/IssueTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.regression.qi59;
-
-import org.junit.Test;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.constraints.annotation.NotEmpty;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.fail;
-
-/**
- * Test for QI-59
- */
-public class IssueTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( TestCase.class );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Test
-    public void givenEntityWithConstrainedPropertyWhenInvalidPropertyValueSetThenThrowException()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-
-        try
-        {
-            TestCase testCase = uow.newEntity( TestCase.class );
-
-            testCase.someProperty().set( null );
-
-            uow.complete();
-            fail( "Should not be allowed to set invalid property value" );
-        }
-        catch( Exception e )
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void givenEntityWithComplexConstrainedPropertyWhenInvalidPropertyValueSetThenThrowException()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-
-        try
-        {
-            TestCase testCase = uow.newEntity( TestCase.class );
-
-            testCase.otherProperty().set( "" );
-
-            uow.complete();
-            fail( "Should not be allowed to set invalid property value" );
-        }
-        catch( Exception e )
-        {
-            uow.discard();
-        }
-    }
-
-    interface TestCase
-        extends EntityComposite
-    {
-        Property<String> someProperty();
-
-        @NotEmpty
-        Property<String> otherProperty();
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/regression/qi65/IssueTest.java b/core/runtime/src/test/java/org/qi4j/regression/qi65/IssueTest.java
deleted file mode 100644
index 169cd1b..0000000
--- a/core/runtime/src/test/java/org/qi4j/regression/qi65/IssueTest.java
+++ /dev/null
@@ -1,65 +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.qi4j.regression.qi65;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-public class IssueTest
-    extends AbstractQi4jTest
-{
-    private final static Class<?> CLAZZ = Object.class;
-    private final static String METHOD_NAME = "toString";
-    private final static Class<?> PARAM_TYPES[] = { };
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TestComposite.class );
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void constraintOnMethodParameter()
-        throws SecurityException, NoSuchMethodException
-    {
-        TestComposite test = module.newTransient( TestComposite.class );
-
-        test.someMethod( null );
-    }
-
-    @Mixins( TestMixin.class )
-    public interface TestComposite
-        extends TransientComposite
-    {
-        String someMethod( String value );
-    }
-
-    public static abstract class TestMixin
-        implements TestComposite
-    {
-        public String someMethod( String value )
-        {
-            return value + " " + value;
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/regression/qi74/IssueTest.java b/core/runtime/src/test/java/org/qi4j/regression/qi74/IssueTest.java
deleted file mode 100644
index 3fd76cb..0000000
--- a/core/runtime/src/test/java/org/qi4j/regression/qi74/IssueTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2008 Sonny Gill. All Rights Reserved.
- *
- * Licensed  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.qi4j.regression.qi74;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-public class IssueTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( ValueHolder.class );
-    }
-
-    @Test
-    public void testConstraintCheckedOnCompsiteCreation()
-    {
-        try
-        {
-            TransientBuilder<ValueHolder> builder = module.newTransientBuilder( ValueHolder.class );
-            builder.newInstance();
-            Assert.fail( "NotNull constraint violated but no exception is raised" );
-        }
-        catch( ConstraintViolationException e )
-        {
-            // expected
-        }
-    }
-
-    static interface ValueHolder
-        extends TransientComposite
-    {
-        Property<String> val();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/regression/qi78/IssueTest.java b/core/runtime/src/test/java/org/qi4j/regression/qi78/IssueTest.java
deleted file mode 100644
index 91d2e1e..0000000
--- a/core/runtime/src/test/java/org/qi4j/regression/qi78/IssueTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2008 Sonny Gill. All Rights Reserved.
- *
- * Licensed  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.qi4j.regression.qi78;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.api.structure.LayerDescriptor;
-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;
-import org.qi4j.functional.HierarchicalVisitorAdapter;
-
-public class IssueTest
-{
-    @Test
-    public void testLayersCanBeCreatedInOrderDifferentFromTheirDependency()
-        throws AssemblyException
-    {
-        Energy4Java qi4j = new Energy4Java();
-
-        Application app = qi4j.newApplication( new ApplicationAssembler()
-        {
-            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-                throws AssemblyException
-            {
-                ApplicationAssembly assembly = applicationFactory.newApplicationAssembly();
-
-                LayerAssembly domainLayer = assembly.layer( null );
-                domainLayer.setName( "Domain" );
-
-                LayerAssembly infrastructureLayer = assembly.layer( null );
-                infrastructureLayer.setName( "Infrastructure" );
-
-                domainLayer.uses( infrastructureLayer );
-
-                return assembly;
-            }
-        } );
-        ApplicationDescriptor model = app.descriptor();
-        model.accept( new HierarchicalVisitorAdapter<Object, Object, RuntimeException>()
-        {
-            @Override
-            public boolean visitEnter( Object visited )
-                throws RuntimeException
-            {
-                return visited instanceof ApplicationDescriptor;
-            }
-
-            @Override
-            public boolean visitLeave( Object visited )
-                throws RuntimeException
-            {
-                return visited instanceof LayerDescriptor;
-            }
-
-            @Override
-            public boolean visit( Object visited )
-                throws RuntimeException
-            {
-                if( visited instanceof LayerDescriptor )
-                {
-                    Iterable<? extends LayerDescriptor> usedLayers = ( (LayerDescriptor) visited ).usedLayers()
-                        .layers();
-                    for( LayerDescriptor usedLayerModel : usedLayers )
-                    {
-                        Assert.assertNotNull( "Used layer model is null", usedLayerModel );
-                    }
-                }
-
-                return false;
-            }
-        } );
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/regression/qi94/IssueTest.java b/core/runtime/src/test/java/org/qi4j/regression/qi94/IssueTest.java
deleted file mode 100644
index 29e9109..0000000
--- a/core/runtime/src/test/java/org/qi4j/regression/qi94/IssueTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2008 Richard Wallace. All Rights Reserved.
- *
- * Licensed  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.qi4j.regression.qi94;
-
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.assertEquals;
-
-public class IssueTest
-    extends AbstractQi4jTest
-{
-    @SuppressWarnings( "unchecked" )
-    public void assemble( ModuleAssembly aModule )
-        throws AssemblyException
-    {
-        aModule.entities( Item.class, ItemType.class );
-        new EntityTestAssembler().assemble( aModule );
-    }
-
-    @Test
-    public void entityBuilderAssociationTypeIsNotNull()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            EntityBuilder<Item> builder = uow.newEntityBuilder( Item.class );
-            assertEquals( ItemType.class, qi4j.api()
-                .entityDescriptorFor( builder.instance() )
-                .state()
-                .getAssociationByName( "typeOfItem" )
-                .type() );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    interface Item
-        extends EntityComposite
-    {
-        Association<ItemType> typeOfItem();
-    }
-
-    interface ItemType
-        extends EntityComposite
-    {
-        Property<String> name();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/Qi4jAPITest.java b/core/runtime/src/test/java/org/qi4j/runtime/Qi4jAPITest.java
deleted file mode 100644
index e354c6e..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/Qi4jAPITest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-/**
- * JAVADOC
- */
-public class Qi4jAPITest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.transients( TestTransient.class );
-        module.entities( TestEntity.class );
-        module.values( TestValue.class );
-        module.services( TestService.class );
-    }
-
-    @Test
-    public void testGetModuleOfComposite()
-        throws Exception
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        TestEntity testEntity = unitOfWork.newEntity( TestEntity.class );
-
-        api.moduleOf( testEntity );
-
-        unitOfWork.discard();
-
-        api.moduleOf( module.newValue( TestValue.class ) );
-
-        api.moduleOf( module.newTransient( TestTransient.class ) );
-
-        api.moduleOf( module.findService( TestService.class ).get() );
-    }
-
-    public interface TestTransient
-        extends TransientComposite
-    {
-    }
-
-    public interface TestEntity
-        extends EntityComposite
-    {
-    }
-
-    public interface TestValue
-        extends ValueComposite
-    {
-    }
-
-    public interface TestService
-        extends ServiceComposite
-    {
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/Qi4jSPITest.java b/core/runtime/src/test/java/org/qi4j/runtime/Qi4jSPITest.java
deleted file mode 100644
index 5bbfc69..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/Qi4jSPITest.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime;
-
-import org.hamcrest.CoreMatchers;
-import org.junit.Test;
-import org.qi4j.api.association.AbstractAssociation;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationStateDescriptor;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.assertThat;
-
-/**
- * JAVADOC
- */
-public class Qi4jSPITest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.entities( TestEntity.class, TestEntity2.class );
-    }
-
-    @Test
-    public void givenEntityWhenGettingStateThenGetCorrectState()
-        throws Exception
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        TestEntity testEntity;
-        try
-        {
-            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class );
-
-            testEntity = builder.newInstance();
-
-            AssociationStateHolder state = spi.stateOf( testEntity );
-
-            validateState( state, spi.entityDescriptorFor( testEntity ) );
-
-            unitOfWork.complete();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            testEntity = uow.get( testEntity );
-            validateState( spi.stateOf( testEntity ), spi.entityDescriptorFor( testEntity ) );
-            uow.complete();
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    private void validateState( AssociationStateHolder state, EntityDescriptor entityDescriptor )
-    {
-        for( PropertyDescriptor propertyDescriptor : entityDescriptor.state().properties() )
-        {
-            Property<?> prop = state.propertyFor( propertyDescriptor.accessor() );
-            assertThat( "Properties could be listed", prop, CoreMatchers.notNullValue() );
-        }
-
-        AssociationStateDescriptor descriptor = entityDescriptor.state();
-        for( AssociationDescriptor associationDescriptor : descriptor.associations() )
-        {
-            AbstractAssociation assoc = state.associationFor( associationDescriptor.accessor() );
-            assertThat( "Assocs could be listed", assoc, CoreMatchers.notNullValue() );
-        }
-    }
-
-    public interface TestEntity
-        extends EntityComposite
-    {
-        @Optional
-        Property<String> property();
-
-        @Optional
-        Association<TestEntity> association();
-
-        ManyAssociation<TestEntity> manyAssociation();
-    }
-
-    public interface TestEntity2
-        extends EntityComposite
-    {
-        @Optional
-        Property<String> property();
-
-        @Optional
-        Association<TestEntity> association();
-
-        ManyAssociation<TestEntity> manyAssociation();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/activation/ActivatorOrderTestSupport.java b/core/runtime/src/test/java/org/qi4j/runtime/activation/ActivatorOrderTestSupport.java
deleted file mode 100644
index 3747240..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/activation/ActivatorOrderTestSupport.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.activation;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import org.qi4j.api.activation.Activator;
-
-public class ActivatorOrderTestSupport
-{
-
-    //
-    // Common expected results --------------------------------------------
-    //
-    public static interface Expected
-    {
-
-        String ALPHA_BETA_SINGLE = Arrays.toString( new String[]{
-                    "Alpha.beforeActivation",
-                    "Beta.beforeActivation",
-                    // -> Activation
-                    "Alpha.afterActivation",
-                    "Beta.afterActivation",
-                    // -> Active
-                    "Beta.beforePassivation",
-                    "Alpha.beforePassivation",
-                    // -> Passivation
-                    "Beta.afterPassivation",
-                    "Alpha.afterPassivation"
-                } );
-
-    }
-
-    //
-    // ActivationStep recorder --------------------------------------------
-    //
-    public static final class ActivationStep
-    {
-
-        public final String activator;
-
-        public final String step;
-
-        public ActivationStep( String activator, String step )
-        {
-            this.activator = activator;
-            this.step = step;
-        }
-
-        @Override
-        public String toString()
-        {
-            return activator + "." + step;
-        }
-
-    }
-
-    public static interface ActivationStepsRecorder
-    {
-
-        void reset();
-
-        void record( ActivationStep step );
-
-        List<ActivationStep> steps();
-
-    }
-
-    public static class ActivationStepsRecorderInstance
-            implements ActivationStepsRecorder
-    {
-
-        private List<ActivationStep> steps = new ArrayList<ActivationStep>();
-
-        @Override
-        public void reset()
-        {
-            steps = new ArrayList<ActivationStep>();
-        }
-
-        @Override
-        public void record( ActivationStep step )
-        {
-            steps.add( step );
-        }
-
-        @Override
-        public List<ActivationStep> steps()
-        {
-            return Collections.unmodifiableList( steps );
-        }
-
-    }
-
-    //
-    // Activator that call the ActivationStepsRecorder --------------------
-    //
-    public static abstract class OrderTestActivator<T>
-            implements Activator<T>
-    {
-
-        private final String activator;
-
-        private final ActivationStepsRecorder recorder;
-
-        public OrderTestActivator( String activator, ActivationStepsRecorder recorder )
-        {
-            this.activator = activator;
-            this.recorder = recorder;
-        }
-
-        @Override
-        public final void beforeActivation( T activating )
-                throws Exception
-        {
-            recorder.record( new ActivationStep( activator, "beforeActivation" ) );
-        }
-
-        @Override
-        public final void afterActivation( T activated )
-                throws Exception
-        {
-            recorder.record( new ActivationStep( activator, "afterActivation" ) );
-        }
-
-        @Override
-        public final void beforePassivation( T passivating )
-                throws Exception
-        {
-            recorder.record( new ActivationStep( activator, "beforePassivation" ) );
-        }
-
-        @Override
-        public final void afterPassivation( T passivated )
-                throws Exception
-        {
-            recorder.record( new ActivationStep( activator, "afterPassivation" ) );
-        }
-
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/activation/ApplicationActivationTest.java b/core/runtime/src/test/java/org/qi4j/runtime/activation/ApplicationActivationTest.java
deleted file mode 100644
index cccfd1c..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/activation/ApplicationActivationTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.activation;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.structure.Application;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-public class ApplicationActivationTest
-{
-
-    private static int activationLevel = 0;
-
-    private static int passivationLevel = 0;
-
-    public static class TestedActivator
-            implements Activator<Application>
-    {
-
-        public void beforeActivation( Application activating )
-        {
-            activationLevel++;
-        }
-
-        public void afterActivation( Application activated )
-        {
-            activationLevel++;
-        }
-
-        public void beforePassivation( Application passivating )
-        {
-            passivationLevel++;
-        }
-
-        public void afterPassivation( Application passivated )
-        {
-            passivationLevel++;
-        }
-
-    }
-
-    @Test
-    public void testApplicationActivator()
-            throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                module.layer().application().withActivators( TestedActivator.class );
-            }
-
-        };
-
-        // Activate
-        Application application = assembly.application();
-
-        // Assert activated
-        Assert.assertEquals( "Activation Level", 2, activationLevel );
-
-        // Passivate
-        application.passivate();
-
-        // Assert passivated
-        Assert.assertEquals( "Passivation Level", 2, passivationLevel );
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/activation/ImportedServiceActivationTest.java b/core/runtime/src/test/java/org/qi4j/runtime/activation/ImportedServiceActivationTest.java
deleted file mode 100644
index d2d88fb..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/activation/ImportedServiceActivationTest.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.activation;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.service.ServiceImporterException;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ImportedServiceDeclaration;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-import static org.junit.Assert.*;
-
-public class ImportedServiceActivationTest
-{
-
-    private static int activationLevel = 0;
-
-    private static int passivationLevel = 0;
-
-    public static class TestedActivator
-            implements Activator<ServiceReference<TestedService>>
-    {
-
-        public void beforeActivation( ServiceReference<TestedService> activating )
-        {
-            assertFalse( "Service should not be active before activation", activating.isActive() );
-            try {
-                activating.get();
-                fail( "Service is not activated yet, the reference get method should throw IllegalStateException." );
-            } catch ( IllegalStateException expected ) {
-            }
-            activationLevel++;
-        }
-
-        public void afterActivation( ServiceReference<TestedService> activated )
-        {
-            assertTrue( "Service should be active after activation", activated.isActive() );
-            assertEquals( "After activation", "bar", activated.get().foo() );
-            activationLevel++;
-        }
-
-        public void beforePassivation( ServiceReference<TestedService> passivating )
-        {
-            assertTrue( "Service should be active before passivation", passivating.isActive() );
-            assertEquals( "Before passivation", "bar", passivating.get().foo() );
-            passivationLevel++;
-        }
-
-        public void afterPassivation( ServiceReference<TestedService> passivated )
-        {
-            assertFalse( "Service should not be active after passivation", passivated.isActive() );
-            try {
-                passivated.get();
-                fail( "Service is passivated, the reference get method should throw IllegalStateException." );
-            } catch ( IllegalStateException expected ) {
-            }
-            passivationLevel++;
-        }
-
-    }
-
-    public static interface TestedService
-    {
-
-        String foo();
-
-    }
-
-    public static class TestedServiceInstance
-            implements TestedService
-    {
-
-        public String foo()
-        {
-            return "bar";
-        }
-
-    }
-
-    @Mixins( TestedServiceImporterService.Mixin.class )
-    interface TestedServiceImporterService
-            extends ServiceComposite, ServiceImporter<TestedService>
-    {
-
-        class Mixin
-                implements ServiceImporter<TestedService>
-        {
-
-            public TestedService importService( ImportedServiceDescriptor serviceDescriptor )
-                    throws ServiceImporterException
-            {
-                return new TestedServiceInstance();
-            }
-
-            public boolean isAvailable( TestedService instance )
-            {
-                return true;
-            }
-
-        }
-
-    }
-
-    @Before
-    public void beforeEachTest()
-    {
-        activationLevel = 0;
-        passivationLevel = 0;
-    }
-
-    @Test
-    public void testNewInstanceImportedServiceActivators()
-            throws Exception
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                module.importedServices( TestedService.class ).
-                        withActivators( TestedActivator.class ).
-                        setMetaInfo( new TestedServiceInstance() ).
-                        importOnStartup();
-            }
-
-        };
-        Application application = assembler.application();
-        assertEquals( "Activation Level", 2, activationLevel );
-        application.passivate();
-        assertEquals( "Passivation Level", 2, passivationLevel );
-    }
-
-    @Test
-    public void testNewObjectImportedServiceActivators()
-            throws Exception
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                module.importedServices( TestedService.class ).
-                        importedBy( ImportedServiceDeclaration.NEW_OBJECT ).
-                        withActivators( TestedActivator.class ).
-                        importOnStartup();
-                module.objects( TestedServiceInstance.class );
-            }
-
-        };
-        Application application = assembler.application();
-        assertEquals( "Activation Level", 2, activationLevel );
-        application.passivate();
-        assertEquals( "Passivation Level", 2, passivationLevel );
-    }
-
-    @Test
-    public void testServiceImporterImportedServiceActivators()
-            throws Exception
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                module.importedServices( TestedService.class ).
-                        importedBy( ImportedServiceDeclaration.SERVICE_IMPORTER ).
-                        setMetaInfo( "testimporter" ).
-                        withActivators( TestedActivator.class ).
-                        importOnStartup();
-                module.services( TestedServiceImporterService.class ).identifiedBy( "testimporter" );
-            }
-
-        };
-        Application application = assembler.application();
-        assertEquals( "Activation Level", 2, activationLevel );
-        application.passivate();
-        assertEquals( "Passivation Level", 2, passivationLevel );
-    }
-
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/activation/IntraMixinActivationOrderTest.java b/core/runtime/src/test/java/org/qi4j/runtime/activation/IntraMixinActivationOrderTest.java
deleted file mode 100644
index 5e8291c..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/activation/IntraMixinActivationOrderTest.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/* 
- * Copyright (c) 2013, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.activation;
-
-import java.util.Arrays;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.activation.PassivationException;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.runtime.activation.ActivatorOrderTestSupport.ActivationStep;
-import org.qi4j.runtime.activation.ActivatorOrderTestSupport.ActivationStepsRecorder;
-import org.qi4j.runtime.activation.ActivatorOrderTestSupport.ActivationStepsRecorderInstance;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * Assert that intra-mixin activation order is correct.
- * Alpha* depends on Beta* to be activated.
- */
-public class IntraMixinActivationOrderTest
-{
-
-    public static final ActivationStepsRecorder RECORDER = new ActivationStepsRecorderInstance();
-
-    @Before
-    public void beforeEachTest()
-    {
-        RECORDER.reset();
-    }
-
-    public interface AlphaMixinType
-    {
-    }
-
-    public static class AlphaMixin
-        implements AlphaMixinType, AlphaActivation
-    {
-
-        @This
-        private BetaMixinType beta;
-
-        @Override
-        public void setupAlpha()
-        {
-            beta.ensureActivated();
-            RECORDER.record( new ActivationStep( "alpha", "setup" ) );
-        }
-
-        @Override
-        public void tearDownAlpha()
-        {
-            RECORDER.record( new ActivationStep( "alpha", "tear-down" ) );
-        }
-
-    }
-
-    public interface BetaMixinType
-    {
-
-        void ensureActivated();
-
-    }
-
-    public static class BetaMixin
-        implements BetaMixinType, BetaActivation
-    {
-
-        private boolean activated = false;
-
-        @Override
-        public void ensureActivated()
-        {
-            if( !activated )
-            {
-                throw new IllegalStateException( "BetaMixin is not activated" );
-            }
-        }
-
-        @Override
-        public void setupBeta()
-        {
-            RECORDER.record( new ActivationStep( "beta", "setup" ) );
-            activated = true;
-        }
-
-        @Override
-        public void tearDownBeta()
-        {
-            RECORDER.record( new ActivationStep( "beta", "tear-down" ) );
-            activated = false;
-        }
-
-    }
-
-    @Activators( AlphaActivation.AlphaActivator.class )
-    @Mixins( AlphaMixin.class )
-    public interface AlphaActivation
-    {
-
-        void setupAlpha();
-
-        void tearDownAlpha();
-
-        public class AlphaActivator
-            extends ActivatorAdapter<ServiceReference<AlphaActivation>>
-        {
-
-            @Override
-            public void afterActivation( ServiceReference<AlphaActivation> activated )
-                throws Exception
-            {
-                activated.get().setupAlpha();
-            }
-
-            @Override
-            public void beforePassivation( ServiceReference<AlphaActivation> passivating )
-                throws Exception
-            {
-                passivating.get().tearDownAlpha();
-            }
-
-        }
-
-    }
-
-    @Activators( BetaActivation.BetaActivator.class )
-    @Mixins( BetaMixin.class )
-    public interface BetaActivation
-    {
-
-        void setupBeta();
-
-        void tearDownBeta();
-
-        public class BetaActivator
-            extends ActivatorAdapter<ServiceReference<BetaActivation>>
-        {
-
-            @Override
-            public void afterActivation( ServiceReference<BetaActivation> activated )
-                throws Exception
-            {
-                activated.get().setupBeta();
-            }
-
-            @Override
-            public void beforePassivation( ServiceReference<BetaActivation> passivating )
-                throws Exception
-            {
-                passivating.get().tearDownBeta();
-            }
-
-        }
-
-    }
-
-    // Order of declaration here ensure that Beta is activated before Alpha
-    public interface UnderTestServiceType
-        extends BetaActivation, AlphaActivation
-    {
-    }
-
-    @Test
-    public void test()
-        throws AssemblyException, ActivationException, PassivationException
-    {
-        new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.services( UnderTestServiceType.class ).instantiateOnStartup();
-            }
-        }.application().passivate();
-        // System.out.println( RECORDER.steps() );
-        String expected = Arrays.toString( new String[]
-        {
-            "beta.setup",
-            "alpha.setup",
-            "alpha.tear-down",
-            "beta.tear-down",
-        } );
-        String actual = Arrays.toString( RECORDER.steps().toArray() );
-        assertEquals( expected, actual );
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/activation/LayerActivationTest.java b/core/runtime/src/test/java/org/qi4j/runtime/activation/LayerActivationTest.java
deleted file mode 100644
index 1b1e6e9..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/activation/LayerActivationTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.activation;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Layer;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-public class LayerActivationTest
-{
-
-    private static int activationLevel = 0;
-
-    private static int passivationLevel = 0;
-
-    public static class TestedActivator
-            implements Activator<Layer>
-    {
-
-        public void beforeActivation( Layer activating )
-        {
-            activationLevel++;
-        }
-
-        public void afterActivation( Layer activated )
-        {
-            activationLevel++;
-        }
-
-        public void beforePassivation( Layer passivating )
-        {
-            passivationLevel++;
-        }
-
-        public void afterPassivation( Layer passivated )
-        {
-            passivationLevel++;
-        }
-
-    }
-
-    @Test
-    public void testLayersActivators()
-            throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                module.layer().withActivators( TestedActivator.class );
-            }
-
-        };
-        // Activate
-        Application application = assembly.application();
-
-        // Assert activated
-        Assert.assertEquals( "Activation Level", 2, activationLevel );
-
-        // Passivate
-        application.passivate();
-
-        // Assert passivated
-        Assert.assertEquals( "Passivation Level", 2, passivationLevel );
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/activation/ModuleActivationTest.java b/core/runtime/src/test/java/org/qi4j/runtime/activation/ModuleActivationTest.java
deleted file mode 100644
index 878a686..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/activation/ModuleActivationTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.activation;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-public class ModuleActivationTest
-{
-
-    private static int activationLevel = 0;
-
-    private static int passivationLevel = 0;
-
-    public static class TestedActivator
-            implements Activator<Module>
-    {
-
-        public void beforeActivation( Module activating )
-        {
-            activationLevel++;
-        }
-
-        public void afterActivation( Module activated )
-        {
-            activationLevel++;
-        }
-
-        public void beforePassivation( Module passivating )
-        {
-            passivationLevel++;
-        }
-
-        public void afterPassivation( Module passivated )
-        {
-            passivationLevel++;
-        }
-
-    }
-
-    @Test
-    public void testModulesActivators()
-            throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                module.withActivators( TestedActivator.class );
-            }
-
-        };
-        // Activate
-        Application application = assembly.application();
-
-        // Assert activated
-        Assert.assertEquals( "Activation Level", 2, activationLevel );
-
-        // Passivate
-        application.passivate();
-
-        // Assert passivated
-        Assert.assertEquals( "Passivation Level", 2, passivationLevel );
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/activation/ServiceActivationTest.java b/core/runtime/src/test/java/org/qi4j/runtime/activation/ServiceActivationTest.java
deleted file mode 100644
index 8158c2d..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/activation/ServiceActivationTest.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.activation;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import org.qi4j.api.activation.Activator;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-public class ServiceActivationTest
-{
-
-    private static int activationLevel = 0;
-
-    private static int passivationLevel = 0;
-
-    public static class TestedActivator
-            implements Activator<ServiceReference<TestedService>>
-    {
-
-        public void beforeActivation( ServiceReference<TestedService> activating )
-        {
-            Assert.assertFalse( "Service should not be active before activation", activating.isActive() );
-            try {
-                activating.get();
-                Assert.fail( "Service is not activated yet, the reference get method should throw IllegalStateException." );
-            } catch ( IllegalStateException expected ) {
-            }
-            activationLevel++;
-        }
-
-        public void afterActivation( ServiceReference<TestedService> activated )
-        {
-            Assert.assertTrue( "Service should be active after activation", activated.isActive() );
-            Assert.assertEquals( "After activation", "bar", activated.get().foo() );
-            activationLevel++;
-        }
-
-        public void beforePassivation( ServiceReference<TestedService> passivating )
-        {
-            Assert.assertTrue( "Service should be active before passivation", passivating.isActive() );
-            Assert.assertEquals( "Before passivation", "bar", passivating.get().foo() );
-            passivationLevel++;
-        }
-
-        public void afterPassivation( ServiceReference<TestedService> passivated )
-        {
-            Assert.assertFalse( "Service should not be active after passivation", passivated.isActive() );
-            try {
-                passivated.get();
-                Assert.fail( "Service is passivated, the reference get method should throw IllegalStateException." );
-            } catch ( IllegalStateException expected ) {
-            }
-            passivationLevel++;
-        }
-
-    }
-
-    @Mixins( TestedServiceMixin.class )
-    public static interface TestedServiceComposite
-            extends TestedService, ServiceComposite
-    {
-    }
-
-    @Mixins( TestedServiceMixin.class )
-    public static interface TestedServiceComposite2
-            extends TestedService, ServiceComposite
-    {
-    }
-
-    public static interface TestedService
-    {
-
-        String foo();
-
-    }
-
-    public static class TestedServiceMixin
-            implements TestedService
-    {
-
-        public String foo()
-        {
-            return "bar";
-        }
-
-    }
-
-    @Test
-    public void testServicesActivators()
-            throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                module.addServices( TestedServiceComposite.class ).
-                        withActivators( TestedActivator.class ).
-                        instantiateOnStartup();
-                module.addServices( TestedServiceComposite2.class ).
-                        withActivators( TestedActivator.class ).
-                        instantiateOnStartup();
-            }
-
-        };
-        // Activate
-        Application application = assembly.application();
-
-        // Assert activated
-        Assert.assertEquals( "Activation Level", 4, activationLevel );
-
-        // Passivate
-        application.passivate();
-
-        // Assert passivated
-        Assert.assertEquals( "Passivation Level", 4, passivationLevel );
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/activation/ServiceActivatorOrderTest.java b/core/runtime/src/test/java/org/qi4j/runtime/activation/ServiceActivatorOrderTest.java
deleted file mode 100644
index d3dec69..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/activation/ServiceActivatorOrderTest.java
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.activation;
-
-import java.util.Arrays;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.runtime.activation.ActivatorOrderTestSupport.ActivationStepsRecorder;
-import org.qi4j.runtime.activation.ActivatorOrderTestSupport.ActivationStepsRecorderInstance;
-import org.qi4j.runtime.activation.ActivatorOrderTestSupport.Expected;
-import org.qi4j.runtime.activation.ActivatorOrderTestSupport.OrderTestActivator;
-
-import static org.junit.Assert.assertEquals;
-
-public class ServiceActivatorOrderTest
-{
-
-    //
-    // ActivationStepsRecorder --------------------------------------------
-    //
-    public static final ActivationStepsRecorder RECORDER = new ActivationStepsRecorderInstance();
-
-    @Before
-    public void beforeEachTest()
-    {
-        RECORDER.reset();
-    }
-
-    //
-    // FooBarService ------------------------------------------------------
-    //
-    public static interface FooBar
-    {
-        
-        String foo();
-        
-    }
-
-    public static abstract class FooBarInstance
-            implements FooBar
-    {
-
-        @Override
-        public String foo()
-        {
-            return "bar";
-        }
-
-    }
-
-    @Mixins( FooBarInstance.class )
-    public static interface FooBarService
-            extends FooBar, ServiceComposite
-    {
-    }
-
-    @Mixins( FooBarInstance.class )
-    @Activators( { GammaActivator.class, DeltaActivator.class } )
-    public static interface FooBarServiceWithActivators
-            extends FooBar, ServiceComposite
-    {
-    }
-
-    //
-    // BazarService ------------------------------------------------------
-    //
-    @Activators( GammaActivator.class )
-    public static interface Bazar
-            extends Things, Stuff
-    {
-    }
-    
-    @Activators( DeltaActivator.class )
-    public static interface Things
-    {
-        
-        String things();
-        
-    }
-    
-    @Activators( EpsilonActivator.class )
-    public static interface Stuff
-    {
-        
-        String stuff();
-        
-    }
-    
-    public static class ThingsInstance
-            implements Things
-    {
-
-        @Override
-        public String things()
-        {
-            return "things";
-        }
-        
-    }
-    
-    public static class StuffInstance
-            implements Stuff
-    {
-
-        @Override
-        public String stuff()
-        {
-            return "stuff";
-        }
-        
-    }
-    
-    @Mixins( { ThingsInstance.class, StuffInstance.class } )
-    @Activators( BetaActivator.class )
-    public static interface BazarService
-            extends Bazar, ServiceComposite
-    {
-    }
-    
-    //
-    // Activators in order: Alpha, Beta, Gamma, Delta, Epsilon, Zeta ------
-    //
-    public static class AlphaActivator
-            extends OrderTestActivator<ServiceReference<?>>
-    {
-
-        public AlphaActivator()
-        {
-            super( "Alpha", RECORDER );
-        }
-
-    }
-
-    public static class BetaActivator
-            extends OrderTestActivator<ServiceReference<?>>
-    {
-
-        public BetaActivator()
-        {
-            super( "Beta", RECORDER );
-        }
-
-    }
-
-    public static class GammaActivator
-            extends OrderTestActivator<ServiceReference<?>>
-    {
-
-        public GammaActivator()
-        {
-            super( "Gamma", RECORDER );
-        }
-
-    }
-
-    public static class DeltaActivator
-            extends OrderTestActivator<ServiceReference<?>>
-    {
-
-        public DeltaActivator()
-        {
-            super( "Delta", RECORDER );
-        }
-
-    }
-
-    public static class EpsilonActivator
-            extends OrderTestActivator<ServiceReference<?>>
-    {
-
-        public EpsilonActivator()
-        {
-            super( "Epsilon", RECORDER );
-        }
-
-    }
-
-    public static class ZetaActivator
-            extends OrderTestActivator<ServiceReference<?>>
-    {
-
-        public ZetaActivator()
-        {
-            super( "Zeta", RECORDER );
-        }
-
-    }
-
-    //
-    // Tests --------------------------------------------------------------
-    //
-    @Test
-    public void testTwoActivatorsOrderOnSimpleService()
-            throws Exception
-    {
-        new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                module.services( FooBarService.class ).
-                        withActivators( AlphaActivator.class, BetaActivator.class ).
-                        instantiateOnStartup();
-            }
-
-        }.application().passivate();
-
-        String actual = Arrays.toString( RECORDER.steps().toArray() );
-        // System.out.println( "\n" + Expected.ALPHA_BETA_SINGLE + "\n" + actual + "\n" );
-        assertEquals( Expected.ALPHA_BETA_SINGLE, actual );
-    }
-
-    @Test
-    public void testAnnotationActivatorsOrderOnSimpleService()
-            throws Exception
-    {
-        new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                module.services( FooBarServiceWithActivators.class ).
-                        instantiateOnStartup();
-            }
-
-        }.application().passivate();
-
-        String expected = Arrays.toString( new String[]{
-                    "Gamma.beforeActivation",   // Annotation
-                    "Delta.beforeActivation",   // Annotation
-                    // -> Activation
-                    "Gamma.afterActivation",
-                    "Delta.afterActivation",
-                    // -> Active
-                    "Delta.beforePassivation",
-                    "Gamma.beforePassivation",
-                    // -> Passivation
-                    "Delta.afterPassivation",
-                    "Gamma.afterPassivation"
-                } );
-
-        String actual = Arrays.toString( RECORDER.steps().toArray() );
-        // System.out.println( "\n" + expected + "\n" + actual + "\n" );
-        assertEquals( expected, actual );
-    }
-
-    @Test
-    public void testMixedAnnotationAndAssemblyActivatorsOrderOnSimpleService()
-            throws Exception
-    {
-        new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                module.services( FooBarServiceWithActivators.class ).
-                        withActivators( AlphaActivator.class, BetaActivator.class ).
-                        instantiateOnStartup();
-            }
-
-        }.application().passivate();
-
-        String expected = Arrays.toString( new String[]{
-                    "Alpha.beforeActivation",   // Assembly
-                    "Beta.beforeActivation",    // Assembly
-                    "Gamma.beforeActivation",   // Annotation
-                    "Delta.beforeActivation",   // Annotation
-                    // -> Activation
-                    "Alpha.afterActivation",
-                    "Beta.afterActivation",
-                    "Gamma.afterActivation",
-                    "Delta.afterActivation",
-                    // -> Active
-                    "Delta.beforePassivation",
-                    "Gamma.beforePassivation",
-                    "Beta.beforePassivation",
-                    "Alpha.beforePassivation",
-                    // -> Passivation
-                    "Delta.afterPassivation",
-                    "Gamma.afterPassivation",
-                    "Beta.afterPassivation",
-                    "Alpha.afterPassivation"
-                } );
-
-        String actual = Arrays.toString( RECORDER.steps().toArray() );
-        // System.out.println( "\n" + expected + "\n" + actual + "\n" );
-        assertEquals( expected, actual );
-    }
-    
-    @Test
-    public void testMixedAnnotationAndAssemblyActivatorsOrderOnComplexService()
-            throws Exception
-    {
-        new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                module.services( BazarService.class ).
-                        withActivators( AlphaActivator.class ).
-                        instantiateOnStartup();
-            }
-
-        }.application().passivate();
-        
-        String expected = Arrays.toString( new String[]{
-                    "Alpha.beforeActivation",   // Assembly
-                    "Beta.beforeActivation",    // Service type annotation
-                    "Gamma.beforeActivation",   // Base type annotation
-                    "Delta.beforeActivation",   // First composite type annotation
-                    "Epsilon.beforeActivation", // Second composite type annotation
-                    // -> Activation
-                    "Alpha.afterActivation",
-                    "Beta.afterActivation",
-                    "Gamma.afterActivation",
-                    "Delta.afterActivation",
-                    "Epsilon.afterActivation",
-                    // -> Active
-                    "Epsilon.beforePassivation",
-                    "Delta.beforePassivation",
-                    "Gamma.beforePassivation",
-                    "Beta.beforePassivation",
-                    "Alpha.beforePassivation",
-                    // -> Passivation
-                    "Epsilon.afterPassivation",
-                    "Delta.afterPassivation",
-                    "Gamma.afterPassivation",
-                    "Beta.afterPassivation",
-                    "Alpha.afterPassivation"
-        } );
-        String actual = Arrays.toString( RECORDER.steps().toArray() );
-        // System.out.println( "\n" + expected + "\n" + actual + "\n" );
-        assertEquals( expected, actual );
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/activation/StructureActivatorOrderTest.java b/core/runtime/src/test/java/org/qi4j/runtime/activation/StructureActivatorOrderTest.java
deleted file mode 100644
index 834517b..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/activation/StructureActivatorOrderTest.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.activation;
-
-import java.util.Arrays;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Layer;
-import org.qi4j.api.structure.Module;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.runtime.activation.ActivatorOrderTestSupport.ActivationStepsRecorder;
-import org.qi4j.runtime.activation.ActivatorOrderTestSupport.ActivationStepsRecorderInstance;
-import org.qi4j.runtime.activation.ActivatorOrderTestSupport.Expected;
-import org.qi4j.runtime.activation.ActivatorOrderTestSupport.OrderTestActivator;
-
-import static org.junit.Assert.assertEquals;
-
-public class StructureActivatorOrderTest
-{
-
-    //
-    // ActivationStepsRecorder --------------------------------------------
-    //
-    public static final ActivationStepsRecorder RECORDER = new ActivationStepsRecorderInstance();
-
-    @Before
-    public void beforeEachTest()
-    {
-        RECORDER.reset();
-    }
-
-    //
-    // Activators in order: Alpha, Beta -----------------------------------
-    //
-    public static class AlphaApplicationActivator
-            extends OrderTestActivator<Application>
-    {
-
-        public AlphaApplicationActivator()
-        {
-            super( "Alpha", RECORDER );
-        }
-
-    }
-
-    public static class BetaApplicationActivator
-            extends OrderTestActivator<Application>
-    {
-
-        public BetaApplicationActivator()
-        {
-            super( "Beta", RECORDER );
-        }
-
-    }
-
-    public static class AlphaLayerActivator
-            extends OrderTestActivator<Layer>
-    {
-
-        public AlphaLayerActivator()
-        {
-            super( "Alpha", RECORDER );
-        }
-
-    }
-
-    public static class BetaLayerActivator
-            extends OrderTestActivator<Layer>
-    {
-
-        public BetaLayerActivator()
-        {
-            super( "Beta", RECORDER );
-        }
-
-    }
-
-    public static class AlphaModuleActivator
-            extends OrderTestActivator<Module>
-    {
-
-        public AlphaModuleActivator()
-        {
-            super( "Alpha", RECORDER );
-        }
-
-    }
-
-    public static class BetaModuleActivator
-            extends OrderTestActivator<Module>
-    {
-
-        public BetaModuleActivator()
-        {
-            super( "Beta", RECORDER );
-        }
-
-    }
-
-    //
-    // Tests --------------------------------------------------------------
-    //
-    @Test
-    public void testTwoActivatorsOrderOnApplication()
-            throws Exception
-    {
-        new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                module.layer().application().withActivators( AlphaApplicationActivator.class,
-                                                             BetaApplicationActivator.class );
-            }
-
-        }.application().passivate();
-
-        String actual = Arrays.toString( RECORDER.steps().toArray() );
-        System.out.println( "\n" + Expected.ALPHA_BETA_SINGLE + "\n" + actual + "\n" );
-        assertEquals( Expected.ALPHA_BETA_SINGLE, actual );
-    }
-
-    @Test
-    public void testTwoActivatorsOrderOnLayer()
-            throws Exception
-    {
-        new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                module.layer().withActivators( AlphaLayerActivator.class,
-                                               BetaLayerActivator.class );
-            }
-
-        }.application().passivate();
-
-        String actual = Arrays.toString( RECORDER.steps().toArray() );
-        System.out.println( "\n" + Expected.ALPHA_BETA_SINGLE + "\n" + actual + "\n" );
-        assertEquals( Expected.ALPHA_BETA_SINGLE, actual );
-    }
-
-    @Test
-    public void testTwoActivatorsOrderOnModule()
-            throws Exception
-    {
-        new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                module.withActivators( AlphaModuleActivator.class,
-                                       BetaModuleActivator.class );
-            }
-
-        }.application().passivate();
-
-        String actual = Arrays.toString( RECORDER.steps().toArray() );
-        System.out.println( "\n" + Expected.ALPHA_BETA_SINGLE + "\n" + actual + "\n" );
-        assertEquals( Expected.ALPHA_BETA_SINGLE, actual );
-    }
-
-    @Test
-    public void testTwoActivatorsOrderOnApplicationLayerAndModule()
-            throws Exception
-    {
-        new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                module.layer().application().withActivators( AlphaApplicationActivator.class,
-                                                             BetaApplicationActivator.class );
-                module.layer().withActivators( AlphaLayerActivator.class,
-                                               BetaLayerActivator.class );
-                module.withActivators( AlphaModuleActivator.class,
-                                       BetaModuleActivator.class );
-            }
-
-        }.application().passivate();
-
-        String expected = Arrays.toString( new String[]{
-                    // Application.beforeActivation
-                    "Alpha.beforeActivation",
-                    "Beta.beforeActivation",
-                    // Layer.beforeActivation
-                    "Alpha.beforeActivation",
-                    "Beta.beforeActivation",
-                    // Module.beforeActivation
-                    "Alpha.beforeActivation",
-                    "Beta.beforeActivation",
-                    //
-                    // -> Activation
-                    //
-                    // Application.afterActivation
-                    "Alpha.afterActivation",
-                    "Beta.afterActivation",
-                    // Layer.afterActivation
-                    "Alpha.afterActivation",
-                    "Beta.afterActivation",
-                    // Module.afterActivation
-                    "Alpha.afterActivation",
-                    "Beta.afterActivation",
-                    //
-                    // -> Active
-                    //
-                    // Module.beforePassivation
-                    "Beta.beforePassivation",
-                    "Alpha.beforePassivation",
-                    // Layer.beforePassivation
-                    "Beta.beforePassivation",
-                    "Alpha.beforePassivation",
-                    // Application.beforePassivation
-                    "Beta.beforePassivation",
-                    "Alpha.beforePassivation",
-                    //
-                    // -> Passivation
-                    //
-                    // Module.afterPassivation
-                    "Beta.afterPassivation",
-                    "Alpha.afterPassivation",
-                    // Layer.afterPassivation
-                    "Beta.afterPassivation",
-                    "Alpha.afterPassivation",
-                    // Application.afterPassivation
-                    "Beta.afterPassivation",
-                    "Alpha.afterPassivation"
-                } );
-
-        String actual = Arrays.toString( RECORDER.steps().toArray() );
-        System.out.println( "\n" + expected + "\n" + actual + "\n" );
-        assertEquals( expected, actual );
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/appliesto/AppliesToFilterTest.java b/core/runtime/src/test/java/org/qi4j/runtime/appliesto/AppliesToFilterTest.java
deleted file mode 100644
index d5eb483..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/appliesto/AppliesToFilterTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.appliesto;
-
-import java.lang.reflect.Method;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.AppliesToFilter;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.concern.GenericConcern;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-/**
- * Test of the AppliesToFilter
- */
-public class AppliesToFilterTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( SomeComposite.class );
-    }
-
-    @Test
-    public void givenAnAppliesToFilterWhenAppliedThenFilterMethods()
-        throws Exception
-    {
-        Some some = module.newTransient( Some.class );
-        Assert.assertEquals( ",", some.doStuff1() );
-        Assert.assertEquals( ",,..", some.doStuff2() );
-        Assert.assertEquals( ",,,", some.doStuff3() );
-    }
-
-    @Concerns( MyConcern.class )
-    @Mixins( SomeMixin.class )
-    private interface SomeComposite
-        extends Some, TransientComposite
-    {
-    }
-
-    public static interface Some
-    {
-        String doStuff1();
-
-        String doStuff2();
-
-        String doStuff3();
-    }
-
-    @AppliesTo( TestFilter.class )
-    public static class MyConcern
-        extends GenericConcern
-    {
-        public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-        {
-            String str = (String) next.invoke( proxy, method, args );
-            return str + "..";
-        }
-    }
-
-    public static class SomeMixin
-        implements Some
-    {
-
-        public String doStuff1()
-        {
-            return ",";
-        }
-
-        public String doStuff2()
-        {
-            return ",,";
-        }
-
-        public String doStuff3()
-        {
-            return ",,,";
-        }
-    }
-
-    public static class TestFilter
-        implements AppliesToFilter
-    {
-        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
-        {
-            return method.getName().equals( "doStuff2" );
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/appliesto/AppliesToOrConditionQI241Test.java b/core/runtime/src/test/java/org/qi4j/runtime/appliesto/AppliesToOrConditionQI241Test.java
deleted file mode 100644
index 2623fa1..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/appliesto/AppliesToOrConditionQI241Test.java
+++ /dev/null
@@ -1,250 +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.qi4j.runtime.appliesto;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.junit.Test;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.injection.InjectionScope;
-import org.qi4j.api.injection.scope.Invocation;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertTrue;
-
-public class AppliesToOrConditionQI241Test
-    extends AbstractQi4jTest
-{
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( SomeServiceCompositeWithTwoAnnotations.class );
-        module.services( SomeServiceCompositeWithFirstAnnotation.class );
-        module.services( SomeServiceCompositeWithSecondAnnotation.class );
-    }
-
-    @Test
-    public void testMultiConcerns1()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-
-        try
-        {
-            ServiceReference<SomeServiceCompositeWithFirstAnnotation> refWithFirst = module.findService(
-                SomeServiceCompositeWithFirstAnnotation.class );
-            SomeServiceCompositeWithFirstAnnotation someWithFirst = refWithFirst.get();
-            someWithFirst.doStuff();
-            assertTrue( "AppliesTo did not match with first annotation", someWithFirst.concernHasBeenPlayed() );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void testMultiConcerns2()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-
-        try
-        {
-            ServiceReference<SomeServiceCompositeWithSecondAnnotation> refWithSecond = module.findService(
-                SomeServiceCompositeWithSecondAnnotation.class );
-            SomeServiceCompositeWithSecondAnnotation someWithSecond = refWithSecond.get();
-            someWithSecond.doStuff();
-            assertTrue( "AppliesTo did not match with second annotation", someWithSecond.concernHasBeenPlayed() );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void testMultiConcernsBoth()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-
-        try
-        {
-            ServiceReference<SomeServiceCompositeWithTwoAnnotations> refWithTwo = module.findService(
-                SomeServiceCompositeWithTwoAnnotations.class );
-            SomeServiceCompositeWithTwoAnnotations someWithTwo = refWithTwo.get();
-            someWithTwo.doStuff();
-            assertTrue( "AppliesTo did not match with two annotations", someWithTwo.concernHasBeenPlayed() );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Mixins( SomeMixinWithTwoAnnotations.class )
-    @Concerns( MultiConcerns.class )
-    public interface SomeServiceCompositeWithTwoAnnotations
-        extends SomeService, ServiceComposite
-    {
-    }
-
-    @Mixins( SomeMixinWithFirstAnnotation.class )
-    @Concerns( MultiConcerns.class )
-    public interface SomeServiceCompositeWithFirstAnnotation
-        extends SomeService, ServiceComposite
-    {
-    }
-
-    @Mixins( SomeMixinWithSecondAnnotation.class )
-    @Concerns( MultiConcerns.class )
-    public interface SomeServiceCompositeWithSecondAnnotation
-        extends SomeService, ServiceComposite
-    {
-    }
-
-    public interface SomeService
-    {
-
-        String doStuff();
-
-        /**
-         * Only for assertion purpose.
-         */
-        void playConcern();
-
-        /**
-         * Only for assertion purpose.
-         */
-        boolean concernHasBeenPlayed();
-    }
-
-    public static abstract class SomeBaseMixin
-        implements SomeService
-    {
-        private boolean played = false;
-
-        public void playConcern()
-        {
-            played = true;
-        }
-
-        public boolean concernHasBeenPlayed()
-        {
-            return played;
-        }
-    }
-
-    public static abstract class SomeMixinWithTwoAnnotations
-        extends SomeBaseMixin
-        implements SomeService
-    {
-        @FirstAnnotation( "first one" )
-        @SecondAnnotation( "second one" )
-        public String doStuff()
-        {
-            return "Blah blah";
-        }
-    }
-
-    public static abstract class SomeMixinWithFirstAnnotation
-        extends SomeBaseMixin
-        implements SomeService
-    {
-
-        @FirstAnnotation( "first one" )
-        public String doStuff()
-        {
-            return "Blah blah";
-        }
-    }
-
-    public static abstract class SomeMixinWithSecondAnnotation
-        extends SomeBaseMixin
-        implements SomeService
-    {
-        @SecondAnnotation( "second one" )
-        public String doStuff()
-        {
-            return "Blah blah";
-        }
-    }
-
-    @Retention( RetentionPolicy.RUNTIME )
-    @Target( { ElementType.METHOD } )
-    @InjectionScope
-    public @interface FirstAnnotation
-    {
-        String value();
-    }
-
-    @Retention( RetentionPolicy.RUNTIME )
-    @Target( { ElementType.METHOD } )
-    @InjectionScope
-    public @interface SecondAnnotation
-    {
-        String value();
-    }
-
-    @AppliesTo( { FirstAnnotation.class, SecondAnnotation.class } )
-    public static class MultiConcerns
-        extends ConcernOf<InvocationHandler>
-        implements InvocationHandler
-    {
-
-        @Optional
-        @Invocation
-        private FirstAnnotation first;
-
-        @Optional
-        @Invocation
-        private SecondAnnotation second;
-
-        @This
-        private SomeService someServiceComposite;
-
-        public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-        {
-            if( first != null )
-            {
-                System.err.println( "FIRST IS HERE AND HAS VALUE: " + first.value() );
-            }
-            if( second != null )
-            {
-                System.err.println( "SECOND IS HERE AND HAS VALUE: " + second.value() );
-            }
-            someServiceComposite.playConcern();
-            return next.invoke( proxy, method, args );
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/appliesto/AppliesToTest.java b/core/runtime/src/test/java/org/qi4j/runtime/appliesto/AppliesToTest.java
deleted file mode 100644
index 350b9a4..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/appliesto/AppliesToTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.appliesto;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-/**
- * Test of the @AppliesTo annotation
- */
-public class AppliesToTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( SomeComposite.class );
-    }
-
-    @Test
-    public void givenAnAppliesToWhenNoAnnotationExpectNoConcernInInvocationStack()
-        throws Exception
-    {
-        Some some = module.newTransient( Some.class );
-        Assert.assertEquals( ",", some.doStuff1() );
-    }
-
-    @Test
-    public void givenAnAppliesToWhenAnnotationIsOnMixinTypeExpectConcernInInvocationStack()
-        throws Exception
-    {
-        Some some = module.newTransient( Some.class );
-        Assert.assertEquals( ",,..", some.doStuff2() );
-    }
-
-    @Test
-    public void givenAnAppliesToWhenAnnotationIsOnMixinImplementationExpectConcernInInvocationStack()
-        throws Exception
-    {
-        Some some = module.newTransient( Some.class );
-        Assert.assertEquals( ",", some.doStuff1() );
-        Assert.assertEquals( ",,..", some.doStuff2() );
-        Assert.assertEquals( ",,,", some.doStuff3() );
-    }
-
-    @Concerns( MyConcern.class )
-    @Mixins( SomeMixin.class )
-    private interface SomeComposite
-        extends Some, TransientComposite
-    {
-    }
-
-    public static interface Some
-    {
-        String doStuff1();
-
-        @Foo
-        String doStuff2();
-
-        String doStuff3();
-    }
-
-    @AppliesTo( Foo.class )
-    public static class MyConcern
-        extends ConcernOf<Some>
-        implements Some
-    {
-
-        public String doStuff1()
-        {
-            return next.doStuff1() + ".";
-        }
-
-        public String doStuff2()
-        {
-            return next.doStuff2() + "..";
-        }
-
-        public String doStuff3()
-        {
-            return next.doStuff3() + "...";
-        }
-    }
-
-    public static class SomeMixin
-        implements Some
-    {
-
-        public String doStuff1()
-        {
-            return ",";
-        }
-
-        public String doStuff2()
-        {
-            return ",,";
-        }
-
-        @Foo
-        public String doStuff3()
-        {
-            return ",,,";
-        }
-    }
-
-    @Retention( RetentionPolicy.RUNTIME )
-    private @interface Foo
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/appliesto/FragmentAppliesToTest.java b/core/runtime/src/test/java/org/qi4j/runtime/appliesto/FragmentAppliesToTest.java
deleted file mode 100644
index 01ff69a..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/appliesto/FragmentAppliesToTest.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*  Copyright 2007-2009 Niclas Hedhman.
- *
- * Licensed 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.qi4j.runtime.appliesto;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.reflect.Method;
-import org.junit.Test;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientBuilderFactory;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.sideeffect.GenericSideEffect;
-import org.qi4j.api.sideeffect.SideEffects;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-public class FragmentAppliesToTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( Composite1.class );
-    }
-
-    @Test
-    public void testMixin()
-        throws Exception
-    {
-        TransientBuilder<Composite1> builder = module.newTransientBuilder( Composite1.class );
-
-        Composite1 instance = builder.newInstance();
-        assertNotNull( "DependencyOld not injected.", instance.getBuilderFactory() );
-        assertNotNull( "This not injected.", instance.getMeAsMixin2() );
-        assertEquals( 1, instance.getValue() );
-        instance.getBuilderFactory();
-        instance.getMeAsMixin2();
-        instance.getBuilderFactory();
-        instance.getMeAsMixin2();
-        instance.getMeAsMixin2();
-        instance.getBuilderFactory();
-        assertEquals( 4, instance.getValue() );
-    }
-
-    @Mixins( { Mixin1.Mixin1Impl.class, Mixin2.Mixin2Impl.class, CounterImpl.class } )
-    public interface Composite1
-        extends TransientComposite, Mixin1, Mixin2, Counter
-    {
-    }
-
-    public interface Mixin1
-    {
-        TransientBuilderFactory getBuilderFactory();
-
-        Mixin2 getMeAsMixin2();
-
-        @SideEffects( CountCallsSideEffect.class )
-        public static class Mixin1Impl
-            implements Mixin1
-        {
-
-            @Structure
-            private TransientBuilderFactory builderFactory;
-
-            @This
-            private Mixin2 meAsMixin2;
-
-            @CountCalls
-            public TransientBuilderFactory getBuilderFactory()
-            {
-                return builderFactory;
-            }
-
-            public Mixin2 getMeAsMixin2()
-            {
-                return meAsMixin2;
-            }
-        }
-    }
-
-    public static class CounterImpl
-        implements Counter
-    {
-        private int value;
-
-        public void increment()
-        {
-            value++;
-        }
-
-        public void clear()
-        {
-            value = 0;
-        }
-
-        public int getValue()
-        {
-            return value;
-        }
-    }
-
-    public interface Mixin2
-    {
-        public static class Mixin2Impl
-            implements Mixin2
-        {
-        }
-    }
-
-    public interface Counter
-    {
-        void increment();
-
-        void clear();
-
-        int getValue();
-    }
-
-    @AppliesTo( CountCalls.class )
-    public static class CountCallsSideEffect
-        extends GenericSideEffect
-    {
-
-        @This
-        private Counter counter;
-
-        protected void invoke( Method method, Object[] args )
-        {
-            counter.increment();
-        }
-    }
-
-    @Retention( RetentionPolicy.RUNTIME )
-    @Target( ElementType.METHOD )
-    @Documented
-    @Inherited
-    public @interface CountCalls
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/association/AssociationEqualityTest.java b/core/runtime/src/test/java/org/qi4j/runtime/association/AssociationEqualityTest.java
deleted file mode 100644
index 7aabc8c..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/association/AssociationEqualityTest.java
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * Copyright (c) 2013, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.association;
-
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.not;
-import static org.junit.Assert.assertThat;
-
-/**
- * Assert that Association, ManyAssociation and NamedAssociation equals/hashcode methods combine AssociationDescriptor and State.
- */
-public class AssociationEqualityTest
-    extends AbstractQi4jTest
-{
-
-    //
-    // --------------------------------------:: Types under test ::-----------------------------------------------------
-    //
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.entities( AnEntity.class );
-        module.values( SomeWithAssociations.class, OtherWithAssociations.class );
-    }
-
-    public interface AnEntity
-    {
-    }
-
-    public interface SomeWithAssociations
-    {
-
-        @Optional
-        Association<AnEntity> anEntity();
-
-        ManyAssociation<AnEntity> manyEntities();
-
-        NamedAssociation<AnEntity> namedEntities();
-    }
-
-    public interface OtherWithAssociations
-    {
-
-        @Optional
-        Association<AnEntity> anEntity();
-
-        ManyAssociation<AnEntity> manyEntities();
-
-        NamedAssociation<AnEntity> namedEntities();
-    }
-
-    //
-    // ----------------------------:: AssociationDescriptor equality tests ::-------------------------------------------
-    //
-    @Test
-    public void givenValuesOfTheSameTypeAndSameStateWhenTestingAssociationDescriptorEqualityExpectEquals()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            AnEntity anEntity = uow.newEntity( AnEntity.class );
-
-            SomeWithAssociations some = buildSomeWithAssociation( anEntity );
-            AssociationDescriptor someAssocDesc = qi4j.api().associationDescriptorFor( some.anEntity() );
-            AssociationDescriptor someManyAssocDesc = qi4j.api().associationDescriptorFor( some.manyEntities() );
-            AssociationDescriptor someNamedAssocDesc = qi4j.api().associationDescriptorFor( some.namedEntities() );
-
-            SomeWithAssociations some2 = buildSomeWithAssociation( anEntity );
-            AssociationDescriptor some2AssocDesc = qi4j.api().associationDescriptorFor( some2.anEntity() );
-            AssociationDescriptor some2ManyAssocDesc = qi4j.api().associationDescriptorFor( some2.manyEntities() );
-            AssociationDescriptor some2NamedAssocDesc = qi4j.api().associationDescriptorFor( some2.namedEntities() );
-
-            assertThat( "AssociationDescriptor equal",
-                        someAssocDesc,
-                        equalTo( some2AssocDesc ) );
-            assertThat( "AssociationDescriptor hashcode equal",
-                        someAssocDesc.hashCode(),
-                        equalTo( some2AssocDesc.hashCode() ) );
-            assertThat( "ManyAssociationDescriptor equal",
-                        someManyAssocDesc,
-                        equalTo( some2ManyAssocDesc ) );
-            assertThat( "ManyAssociationDescriptor hashcode equal",
-                        someManyAssocDesc.hashCode(),
-                        equalTo( some2ManyAssocDesc.hashCode() ) );
-            assertThat( "NamedAssociationDescriptor equal",
-                        someNamedAssocDesc,
-                        equalTo( some2NamedAssocDesc ) );
-            assertThat( "NamedAssociationDescriptor hashcode equal",
-                        someNamedAssocDesc.hashCode(),
-                        equalTo( some2NamedAssocDesc.hashCode() ) );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void givenValuesOfTheSameTypeAndDifferentStateWhenTestingAssociationDescriptorEqualityExpectEquals()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            SomeWithAssociations some = buildSomeWithAssociation( uow.newEntity( AnEntity.class ) );
-            AssociationDescriptor someAssocDesc = qi4j.api().associationDescriptorFor( some.anEntity() );
-            AssociationDescriptor someManyAssocDesc = qi4j.api().associationDescriptorFor( some.manyEntities() );
-            AssociationDescriptor someNamedAssocDesc = qi4j.api().associationDescriptorFor( some.namedEntities() );
-
-            SomeWithAssociations some2 = buildSomeWithAssociation( uow.newEntity( AnEntity.class ) );
-            AssociationDescriptor some2AssocDesc = qi4j.api().associationDescriptorFor( some2.anEntity() );
-            AssociationDescriptor some2ManyAssocDesc = qi4j.api().associationDescriptorFor( some2.manyEntities() );
-            AssociationDescriptor some2NamedAssocDesc = qi4j.api().associationDescriptorFor( some2.namedEntities() );
-
-            assertThat( "AssociationDescriptor equal",
-                        someAssocDesc,
-                        equalTo( some2AssocDesc ) );
-            assertThat( "AssociationDescriptor hashcode equal",
-                        someAssocDesc.hashCode(),
-                        equalTo( some2AssocDesc.hashCode() ) );
-            assertThat( "ManyAssociationDescriptor equal",
-                        someManyAssocDesc,
-                        equalTo( some2ManyAssocDesc ) );
-            assertThat( "ManyAssociationDescriptor hashcode equal",
-                        someManyAssocDesc.hashCode(),
-                        equalTo( some2ManyAssocDesc.hashCode() ) );
-            assertThat( "NamedAssociationDescriptor equal",
-                        someNamedAssocDesc,
-                        equalTo( some2NamedAssocDesc ) );
-            assertThat( "NamedAssociationDescriptor hashcode equal",
-                        someNamedAssocDesc.hashCode(),
-                        equalTo( some2NamedAssocDesc.hashCode() ) );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void givenValuesOfDifferentTypeAndSameStateWhenTestingAssociationDescriptorEqualityExpectNotEquals()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            AnEntity anEntity = uow.newEntity( AnEntity.class );
-
-            SomeWithAssociations some = buildSomeWithAssociation( anEntity );
-            AssociationDescriptor someAssocDesc = qi4j.api().associationDescriptorFor( some.anEntity() );
-            AssociationDescriptor someManyAssocDesc = qi4j.api().associationDescriptorFor( some.manyEntities() );
-            AssociationDescriptor someNamedAssocDesc = qi4j.api().associationDescriptorFor( some.namedEntities() );
-
-            OtherWithAssociations other = buildOtherWithAssociation( anEntity );
-            AssociationDescriptor otherAssocDesc = qi4j.api().associationDescriptorFor( other.anEntity() );
-            AssociationDescriptor otherManyAssocDesc = qi4j.api().associationDescriptorFor( other.manyEntities() );
-            AssociationDescriptor otherNamedAssocDesc = qi4j.api().associationDescriptorFor( other.namedEntities() );
-
-            assertThat( "AssociationDescriptor not equal",
-                        someAssocDesc,
-                        not( equalTo( otherAssocDesc ) ) );
-            assertThat( "AssociationDescriptor hashcode not equal",
-                        someAssocDesc.hashCode(),
-                        not( equalTo( otherAssocDesc.hashCode() ) ) );
-            assertThat( "ManyAssociationDescriptor not equal",
-                        someManyAssocDesc,
-                        not( equalTo( otherManyAssocDesc ) ) );
-            assertThat( "ManyAssociationDescriptor hashcode not equal",
-                        someManyAssocDesc.hashCode(),
-                        not( equalTo( otherManyAssocDesc.hashCode() ) ) );
-            assertThat( "NamedAssociationDescriptor not equal",
-                        someNamedAssocDesc,
-                        not( equalTo( otherNamedAssocDesc ) ) );
-            assertThat( "NamedAssociationDescriptor hashcode not equal",
-                        someNamedAssocDesc.hashCode(),
-                        not( equalTo( otherNamedAssocDesc.hashCode() ) ) );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    //
-    // --------------------------------:: Association State equality tests ::----------------------------------------------
-    //
-    @Test
-    public void givenValuesOfSameTypeAndDifferentStateWhenTestingAssociationStateEqualityExpectNotEquals()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            SomeWithAssociations some = buildSomeWithAssociation( uow.newEntity( AnEntity.class ) );
-            SomeWithAssociations some2 = buildSomeWithAssociation( uow.newEntity( AnEntity.class ) );
-
-            assertThat( "Association State not equal",
-                        some.anEntity().get(),
-                        not( equalTo( some2.anEntity().get() ) ) );
-            assertThat( "Association State hashcode not equal",
-                        some.anEntity().get().hashCode(),
-                        not( equalTo( some2.anEntity().get().hashCode() ) ) );
-            assertThat( "ManyAssociation State not equal",
-                        some.manyEntities().toList(),
-                        not( equalTo( some2.manyEntities().toList() ) ) );
-            assertThat( "ManyAssociation State hashcode not equal",
-                        some.manyEntities().toList().hashCode(),
-                        not( equalTo( some2.manyEntities().toList().hashCode() ) ) );
-            assertThat( "NamedAssociation State not equal",
-                        some.namedEntities().toMap(),
-                        not( equalTo( some2.namedEntities().toMap() ) ) );
-            assertThat( "NamedAssociation State hashcode not equal",
-                        some.namedEntities().toMap().hashCode(),
-                        not( equalTo( some2.namedEntities().toMap().hashCode() ) ) );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void givenValuesOfDifferentTypesAndSameStateWhenTestingAssociationStateEqualityExpectEquals()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            AnEntity anEntity = uow.newEntity( AnEntity.class );
-
-            SomeWithAssociations some = buildSomeWithAssociation( anEntity );
-            OtherWithAssociations other = buildOtherWithAssociation( anEntity );
-
-            assertThat( "Association State equal",
-                        some.anEntity().get(),
-                        equalTo( other.anEntity().get() ) );
-            assertThat( "Association State hashcode equal",
-                        some.anEntity().get().hashCode(),
-                        equalTo( other.anEntity().get().hashCode() ) );
-            assertThat( "ManyAssociation State equal",
-                        some.manyEntities().toList(),
-                        equalTo( other.manyEntities().toList() ) );
-            assertThat( "ManyAssociation State hashcode equal",
-                        some.manyEntities().toList().hashCode(),
-                        equalTo( other.manyEntities().toList().hashCode() ) );
-            assertThat( "NamedAssociation State equal",
-                        some.namedEntities().toMap(),
-                        equalTo( other.namedEntities().toMap() ) );
-            assertThat( "NamedAssociation State hashcode equal",
-                        some.namedEntities().toMap().hashCode(),
-                        equalTo( other.namedEntities().toMap().hashCode() ) );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    //
-    // ----------------------------------:: Association equality tests ::-----------------------------------------------
-    //
-    @Test
-    public void givenValuesOfTheSameTypeAndSameStateWhenTestingAssociationEqualityExpectEquals()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            AnEntity anEntity = uow.newEntity( AnEntity.class );
-
-            SomeWithAssociations some = buildSomeWithAssociation( anEntity );
-            SomeWithAssociations some2 = buildSomeWithAssociation( anEntity );
-
-            assertThat( "Association equal",
-                        some.anEntity(),
-                        equalTo( some2.anEntity() ) );
-            assertThat( "Association hashcode equal",
-                        some.anEntity().hashCode(),
-                        equalTo( some2.anEntity().hashCode() ) );
-            assertThat( "ManyAssociation equal",
-                        some.manyEntities(),
-                        equalTo( some2.manyEntities() ) );
-            assertThat( "ManyAssociation hashcode equal",
-                        some.manyEntities().hashCode(),
-                        equalTo( some2.manyEntities().hashCode() ) );
-            assertThat( "NamedAssociation equal",
-                        some.namedEntities(),
-                        equalTo( some2.namedEntities() ) );
-            assertThat( "NamedAssociation hashcode equal",
-                        some.namedEntities().hashCode(),
-                        equalTo( some2.namedEntities().hashCode() ) );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void givenValuesOfTheSameTypeAndDifferentStateWhenTestingAssociationEqualityExpectNotEquals()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            SomeWithAssociations some = buildSomeWithAssociation( uow.newEntity( AnEntity.class ) );
-            SomeWithAssociations some2 = buildSomeWithAssociation( uow.newEntity( AnEntity.class ) );
-
-            assertThat( "Association not equal",
-                        some.anEntity(),
-                        not( equalTo( some2.anEntity() ) ) );
-            assertThat( "Association hashcode not equal",
-                        some.anEntity().hashCode(),
-                        not( equalTo( some2.anEntity().hashCode() ) ) );
-            assertThat( "ManyAssociation not equal",
-                        some.manyEntities(),
-                        not( equalTo( some2.manyEntities() ) ) );
-            assertThat( "ManyAssociation hashcode not equal",
-                        some.manyEntities().hashCode(),
-                        not( equalTo( some2.manyEntities().hashCode() ) ) );
-            assertThat( "NamedAssociation not equal",
-                        some.namedEntities(),
-                        not( equalTo( some2.namedEntities() ) ) );
-            assertThat( "NamedAssociation hashcode not equal",
-                        some.namedEntities().hashCode(),
-                        not( equalTo( some2.namedEntities().hashCode() ) ) );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void givenValuesOfDifferentTypesAndSameStateWhenTestingAssociationEqualityExpectNotEquals()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            AnEntity anEntity = uow.newEntity( AnEntity.class );
-
-            SomeWithAssociations some = buildSomeWithAssociation( anEntity );
-            OtherWithAssociations other = buildOtherWithAssociation( anEntity );
-
-            assertThat( "Association not equal",
-                        some.anEntity(),
-                        not( equalTo( other.anEntity() ) ) );
-            assertThat( "Association hashcode not equal",
-                        some.anEntity().hashCode(),
-                        not( equalTo( other.anEntity().hashCode() ) ) );
-            assertThat( "ManyAssociation not equal",
-                        some.manyEntities(),
-                        not( equalTo( other.manyEntities() ) ) );
-            assertThat( "ManyAssociation hashcode not equal",
-                        some.manyEntities().hashCode(),
-                        not( equalTo( other.manyEntities().hashCode() ) ) );
-            assertThat( "NamedAssociation not equal",
-                        some.namedEntities(),
-                        not( equalTo( other.namedEntities() ) ) );
-            assertThat( "NamedAssociation hashcode not equal",
-                        some.namedEntities().hashCode(),
-                        not( equalTo( other.namedEntities().hashCode() ) ) );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void givenValuesOfDifferentTypesAndDifferentStateWhenTestingAssociationEqualityExpectNotEquals()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            SomeWithAssociations some = buildSomeWithAssociation( uow.newEntity( AnEntity.class ) );
-            OtherWithAssociations other = buildOtherWithAssociation( uow.newEntity( AnEntity.class ) );
-
-            assertThat( "Association not equal",
-                        some.anEntity(),
-                        not( equalTo( other.anEntity() ) ) );
-            assertThat( "Association hashcode not equal",
-                        some.anEntity().hashCode(),
-                        not( equalTo( other.anEntity().hashCode() ) ) );
-            assertThat( "ManyAssociation not equal",
-                        some.manyEntities(),
-                        not( equalTo( other.manyEntities() ) ) );
-            assertThat( "ManyAssociation hashcode not equal",
-                        some.manyEntities().hashCode(),
-                        not( equalTo( other.manyEntities().hashCode() ) ) );
-            assertThat( "NamedAssociation not equal",
-                        some.namedEntities(),
-                        not( equalTo( other.namedEntities() ) ) );
-            assertThat( "NamedAssociation hashcode not equal",
-                        some.namedEntities().hashCode(),
-                        not( equalTo( other.namedEntities().hashCode() ) ) );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    //
-    // -----------------------------------:: Values factory methods ::--------------------------------------------------
-    //
-    private SomeWithAssociations buildSomeWithAssociation( AnEntity associated )
-    {
-        SomeWithAssociations some;
-        {
-            ValueBuilder<SomeWithAssociations> builder = module.newValueBuilder( SomeWithAssociations.class );
-            builder.prototype().anEntity().set( associated );
-            builder.prototype().manyEntities().add( associated );
-            builder.prototype().namedEntities().put( "someKey", associated );
-            some = builder.newInstance();
-        }
-        return some;
-    }
-
-    private OtherWithAssociations buildOtherWithAssociation( AnEntity associated )
-    {
-        OtherWithAssociations some;
-        {
-            ValueBuilder<OtherWithAssociations> builder = module.newValueBuilder( OtherWithAssociations.class );
-            builder.prototype().anEntity().set( associated );
-            builder.prototype().manyEntities().add( associated );
-            builder.prototype().namedEntities().put( "someKey", associated );
-            some = builder.newInstance();
-        }
-        return some;
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/bootstrap/DereferenceForBootstrappedConcernsTest.java b/core/runtime/src/test/java/org/qi4j/runtime/bootstrap/DereferenceForBootstrappedConcernsTest.java
deleted file mode 100644
index 8803dda..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/bootstrap/DereferenceForBootstrappedConcernsTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.bootstrap;
-
-import org.junit.Test;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.mixin.NoopMixin;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-
-public class DereferenceForBootstrappedConcernsTest
-    extends AbstractQi4jTest
-{
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-//        module.addImportedServiceModel( Some.class ).withMixins( NoopMixin.class ).withConcerns( OtherConcern.class );
-        module.services( Some.class );
-        module.services( Result.class );
-    }
-
-    @Test
-    public void whenDerefencingInsideConcernThisExpectItToWork()
-        throws Exception
-    {
-        Result result = module.findService( Result.class ).get();
-        Some some = module.findService( Some.class ).get();
-        assertEquals( "method()", some.method() );
-        assertEquals( some.identity(), result.some().identity() );
-        assertEquals( some.identity().get(), result.some().identity().get() );
-    }
-
-    @Mixins( ResultMixin.class )
-    public interface Result
-        extends ServiceComposite
-    {
-        void execute( Some value );
-
-        Some some();
-    }
-
-    public static abstract class ResultMixin
-        implements Result
-    {
-
-        private Some value;
-
-        public void execute( Some value )
-        {
-            this.value = value;
-        }
-
-        public Some some()
-        {
-            return value;
-        }
-    }
-
-    @Concerns( OtherConcern.class )
-    @Mixins( NoopMixin.class )
-    public interface Other
-    {
-        void other();
-    }
-
-    @Mixins( SomeMixin.class )
-    public interface Some
-//        extends ServiceComposite
-        extends ServiceComposite, Other
-    {
-        String method();
-    }
-
-    public abstract static class SomeMixin
-        implements Some
-    {
-        @This
-        private Other other;
-
-        public String method()
-        {
-            other.other();
-            return "method()";
-        }
-    }
-
-    public static class OtherConcern
-        extends ConcernOf<Other>
-        implements Other
-    {
-        @Structure
-        private Qi4j api;
-
-        @This
-        private Composite me;
-
-        @Service
-        private Result result;
-
-        public void other()
-        {
-            Composite value = api.dereference( me );
-            result.execute( (Some) value );
-            next.other();
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/composite/AbstractMixinTest.java b/core/runtime/src/test/java/org/qi4j/runtime/composite/AbstractMixinTest.java
deleted file mode 100644
index ecfca32..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/composite/AbstractMixinTest.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.Method;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.concern.GenericConcern;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.structure.Module;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-/**
- * JAVADOC
- */
-public class AbstractMixinTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        System.setProperty( "qi4j.compacttrace", "off" );
-        module.transients( TestComposite.class );
-    }
-
-    @Test
-    public void testAbstractMixin()
-    {
-        TestComposite instance = module.newTransient( TestComposite.class );
-
-        Assert.assertEquals( "Hello WorldHello World", instance.test( "Hello World" ) );
-    }
-
-    public interface TestComposite
-        extends TestInterface, TransientComposite
-    {
-    }
-
-    @Mixins( TestComposite.TestMixin.class )
-    @Concerns( { TestInterface.TestConcern.class, TestInterface.TestAbstractConcern.class } )
-    public interface TestInterface
-    {
-        String test( String newValue );
-
-        interface TestState
-        {
-            @Optional
-            Property<String> bar();
-
-            void barChanged( String newValue );
-        }
-
-        abstract class TestMixin
-            implements TestInterface, TestState
-        {
-            public void init( @Structure Module module )
-            {
-                System.out.println( module );
-            }
-
-            public String test( String newValue )
-            {
-                newValue = duplicate( newValue );
-                barChanged( newValue );
-                return bar().get();
-            }
-
-            public void barChanged( String newValue )
-            {
-                bar().set( newValue );
-            }
-
-            public String duplicate( String newValue )
-            {
-                return newValue + newValue;
-            }
-        }
-
-        public class TestConcern
-            extends GenericConcern
-        {
-            public Object invoke( Object proxy, Method method, Object[] args )
-                throws Throwable
-            {
-                System.out.println( method.toGenericString() );
-                return next.invoke( proxy, method, args );
-            }
-        }
-
-        public abstract class TestAbstractConcern
-            extends ConcernOf<TestState>
-            implements TestState
-        {
-            public void barChanged( String newValue )
-            {
-                next.barChanged( newValue );
-                System.out.println( "Concern:" + bar().get() );
-            }
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/composite/CompositeFactoryImplTest.java b/core/runtime/src/test/java/org/qi4j/runtime/composite/CompositeFactoryImplTest.java
deleted file mode 100644
index 40666e0..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/composite/CompositeFactoryImplTest.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) 2007, Sianny Halim. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.util.Properties;
-import org.junit.Test;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.AppliesToFilter;
-import org.qi4j.api.composite.NoSuchTransientException;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.fail;
-
-public class CompositeFactoryImplTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // This is required to instantiate [SecondComposite] composite in [testNewComposition9]
-        module.transients( SecondComposite.class );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    @Test( expected = NoSuchTransientException.class )
-    public void testNewInstanceNotExtendingComposite()
-        throws Exception
-    {
-        Class aClass = FirstComposite.class;
-        TransientBuilder builder = module.newTransientBuilder( aClass );
-        builder.newInstance();
-    }
-
-    @Test
-    public void testNewComposition9()
-        throws Exception
-    {
-        try
-        {
-            TransientBuilder<SecondComposite> builder = module.newTransientBuilder(
-                SecondComposite.class );
-            SecondComposite composition9 = builder.newInstance();
-            composition9.setValue( "satisfiedBy value" );
-        }
-        catch( Exception e )
-        {
-            e.printStackTrace();
-            fail( "Fail to instantiate composite: " + SecondComposite.class );
-        }
-    }
-
-    @Mixins( PropertiesMixin.class )
-    public interface FirstComposite
-        extends Mixin3
-    {
-    }
-
-    @Mixins( PropertiesMixin.class )
-    public interface SecondComposite
-        extends Mixin3, TransientComposite
-    {
-    }
-
-    public interface Mixin3
-    {
-        void setValue( String value );
-
-        String getValue();
-    }
-
-    /**
-     * Generic property mixin. Methods in interface
-     * can be of the following types:
-     * setFoo = set property named foo
-     * getFoo = get property named foo
-     * addFoo = add object to list named foo
-     * removeFoo = remove object from list named foo
-     * fooIterator - return an iterator over the list of Foos
-     */
-    @AppliesTo( { Getters.class, Setters.class } )
-    public static class PropertiesMixin
-        implements InvocationHandler
-    {
-        private Properties properties;
-
-        public PropertiesMixin()
-        {
-            properties = new Properties();
-        }
-
-        @SuppressWarnings( "unchecked" )
-        public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-        {
-            String methodName = method.getName();
-            String property = methodName.substring( 3 );
-            if( methodName.startsWith( "get" ) )
-            {
-                return properties.get( property );
-            }
-            else
-            {
-                properties.put( property, args[ 0 ] );
-                return null;
-            }
-        }
-    }
-
-    /**
-     * Filter for getter methods. Method name must match "get*" or "is*" or "has*".
-     */
-    public static class Getters
-        implements AppliesToFilter
-    {
-        public boolean appliesTo( Method method, Class mixin, Class compositeType, Class modelClass )
-        {
-            final String name = method.getName();
-            return !method.getReturnType().equals( Void.TYPE ) && name.startsWith( "get" ) && name.length() > 4 &&
-                   method.getParameterTypes().length == 0;
-        }
-    }
-
-    /**
-     * Filter for setter methods. Method name must match "set*","add*" or "remove*".
-     */
-    public static class Setters
-        implements AppliesToFilter
-    {
-        public boolean appliesTo( Method method, Class mixin, Class compositeType, Class modelClass )
-        {
-            final String name = method.getName();
-            return method.getReturnType().equals( Void.TYPE ) && name.startsWith( "set" ) && name.length() > 4 &&
-                   method.getParameterTypes().length == 1;
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/composite/CompositeModelResolverTest.java b/core/runtime/src/test/java/org/qi4j/runtime/composite/CompositeModelResolverTest.java
deleted file mode 100644
index 560e0bb..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/composite/CompositeModelResolverTest.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.runtime.composite;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.structure.Module;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-public class CompositeModelResolverTest
-{
-    @Test
-    public void testWhenDependentMixinsThenOrderMixins()
-        throws Exception
-    {
-        Module module = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( TestComposite1.class );
-            }
-        }.module();
-
-        Assert.assertEquals( "ok", module.newTransient( TestComposite1.class ).testB() );
-    }
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-    }
-
-    @Mixins( TestA.TestAMixin.class )
-    public static interface TestA
-    {
-        public String test();
-
-        class TestAMixin
-            implements TestA
-        {
-            public String test()
-            {
-                return "ok";
-            }
-        }
-    }
-
-    @Mixins( TestB.TestBMixin.class )
-    public static interface TestB
-    {
-        public String testB();
-
-        class TestBMixin
-            implements TestB
-        {
-            private TestA testA;
-
-            public TestBMixin( @This TestA testA )
-            {
-                this.testA = testA;
-                testA.test();
-            }
-
-            public String testB()
-            {
-                return testA.test();
-            }
-        }
-    }
-
-    @Mixins( TestC.TestCMixin.class )
-    public static interface TestC
-    {
-        public String testC();
-
-        class TestCMixin
-            implements TestC
-        {
-            private TestD testD;
-
-            public TestCMixin( @This TestD testD )
-            {
-                this.testD = testD;
-                testD.testD();
-            }
-
-            public String testC()
-            {
-                return testD.testD();
-            }
-        }
-    }
-
-    @Mixins( TestD.TestDMixin.class )
-    public static interface TestD
-    {
-        public String testD();
-
-        class TestDMixin
-            implements TestD
-        {
-            private TestC testC;
-
-            public TestDMixin( @This TestC testC )
-            {
-                this.testC = testC;
-                testC.testC();
-            }
-
-            public String testD()
-            {
-                return testC.testC();
-            }
-        }
-    }
-
-    public static interface TestComposite1
-        extends TransientComposite, TestA, TestB
-    {
-    }
-
-    public static interface TestComposite2
-        extends Composite, TestC, TestD
-    {
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/composite/FunctionalListTest.java b/core/runtime/src/test/java/org/qi4j/runtime/composite/FunctionalListTest.java
deleted file mode 100644
index b848958..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/composite/FunctionalListTest.java
+++ /dev/null
@@ -1,98 +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.qi4j.runtime.composite;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.junit.Test;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.structure.Module;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Function;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.hasItems;
-import static org.junit.Assert.assertThat;
-
-public class FunctionalListTest extends AbstractQi4jTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( List.class ).withTypes( FList.class ).withMixins( ArrayList.class );
-    }
-
-    @Test
-    public void givenArrayListWithMapOpCapabilityWhenMappingIntegerToStringExpectCorrectResult()
-    {
-        List<Integer> integers = module.newTransient( List.class );
-        integers.add( 5 );
-        integers.add( 15 );
-        integers.add( 45 );
-        integers.add( 85 );
-        FList<Integer> list = (FList<Integer>) integers;
-
-        List<String> strings = list.translate( new Function<Integer, String>()
-        {
-            @Override
-            public String map( Integer x )
-            {
-                return x.toString();
-            }
-        } );
-
-        String[] expected = new String[]
-        {
-            "5", "15", "45", "85"
-        };
-        assertThat( strings, hasItems( expected ) );
-    }
-
-    @Mixins( FListMixin.class )
-    public interface FList<FROM>
-    {
-        <TO> List<TO> translate( Function<FROM, TO> function );
-    }
-
-    public static class FListMixin<FROM>
-        implements FList<FROM>
-    {
-        @This
-        private List<FROM> list;
-
-        @Structure
-        private Module module;
-
-        @Override
-        public <TO> List<TO> translate( Function<FROM, TO> function )
-        {
-            List<TO> result = module.newTransient( List.class );
-            for( FROM data : list )
-            {
-                result.add( function.map( data ) );
-            }
-            return result;
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/composite/MapOverrideTest.java b/core/runtime/src/test/java/org/qi4j/runtime/composite/MapOverrideTest.java
deleted file mode 100644
index 03de4b3..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/composite/MapOverrideTest.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import java.lang.reflect.Method;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.injection.scope.Invocation;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
-
-/**
- * This test shows how to override any java.util.Map to become read-only. HashMap will be used as the Mixin!!
- *
- * Note that keySet(), values() and entrySet() would ALSO require overloading, but this has been left out for
- * clarity reasons.
- */
-@Ignore( "Awaiting QI-298" )
-public class MapOverrideTest
-    extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // unable to add the concern, since it is applied on the prototype too!
-        // this seems to be a generic problem with prototypes.
-        module.transients( Map.class ).withMixins( HashMap.class ).withConcerns( ReadOnlyMapConcern.class );
-    }
-
-    @Test
-    public void givenReadOnlyAnnotatedHashMapWhenCallingSizeExpectSuccess()
-    {
-        ValueBuilder<Map> builder = module.newValueBuilder( Map.class );
-        Map<String, String> prototype = builder.prototype();
-        prototype.put( "Niclas", "Hedhman" );
-        Map<String, String> underTest = builder.newInstance();
-        assertThat( underTest.size(), equalTo( 1 ) );
-    }
-
-    @Test
-    public void givenReadOnlyAnnotatedHashMapWhenCallingIsEmptyExpectSuccess()
-    {
-        ValueBuilder<Map> builder = module.newValueBuilder( Map.class );
-        Map<String, String> prototype = builder.prototype();
-        prototype.put( "Niclas", "Hedhman" );
-        Map<String, String> underTest = builder.newInstance();
-        assertThat( underTest.isEmpty(), equalTo( false ) );
-    }
-
-    @Test
-    public void givenReadOnlyAnnotatedHashMapWhenCallingContainsKeyExpectSuccess()
-    {
-        ValueBuilder<Map> builder = module.newValueBuilder( Map.class );
-        Map<String, String> prototype = builder.prototype();
-        prototype.put( "Niclas", "Hedhman" );
-        Map<String, String> underTest = builder.newInstance();
-        assertThat( underTest.containsKey( "Niclas" ), equalTo( true ) );
-    }
-
-    @Test
-    public void givenReadOnlyAnnotatedHashMapWhenCallingContainsValueExpectSuccess()
-    {
-        ValueBuilder<Map> builder = module.newValueBuilder( Map.class );
-        Map<String, String> prototype = builder.prototype();
-        prototype.put( "Niclas", "Hedhman" );
-        Map<String, String> underTest = builder.newInstance();
-        assertThat( underTest.containsValue( "Hedhman" ), equalTo( true ) );
-    }
-
-    @Test
-    public void givenReadOnlyAnnotatedHashMapWhenCallingGetExpectSuccess()
-    {
-        ValueBuilder<Map> builder = module.newValueBuilder( Map.class );
-        Map<String, String> prototype = builder.prototype();
-        prototype.put( "Niclas", "Hedhman" );
-        Map<String, String> underTest = builder.newInstance();
-        assertThat( underTest.get( "Niclas" ), equalTo( "Hedhman" ) );
-    }
-
-    @Test
-    public void givenReadOnlyAnnotatedHashMapWhenCallingKeySetExpectSuccess()
-    {
-        ValueBuilder<Map> builder = module.newValueBuilder( Map.class );
-        Map<String, String> prototype = builder.prototype();
-        prototype.put( "Niclas", "Hedhman" );
-        Map<String, String> underTest = builder.newInstance();
-        assertThat( underTest.keySet(), equalTo( Collections.singleton( "Niclas" ) ) );
-    }
-
-    @Test
-    @Ignore
-    public void givenReadOnlyAnnotatedHashMapWhenCallingEntrySetExpectSuccess()
-    {
-    }
-
-    @Test
-    public void givenReadOnlyAnnotatedHashMapWhenCallingValuesExpectSuccess()
-    {
-        ValueBuilder<Map> builder = module.newValueBuilder( Map.class );
-        Map<String, String> prototype = builder.prototype();
-        prototype.put( "Niclas", "Hedhman" );
-        Map<String, String> underTest = builder.newInstance();
-        Collection<String> values = Collections.singletonList( "Hedhman" );
-        assertThat( underTest.values().size(), equalTo( values.size() ) );
-        assertThat( underTest.values().contains( "Hedhman" ), equalTo( true ) );
-    }
-
-    @Test( expected = ReadOnlyException.class )
-    @Ignore
-    public void givenReadOnlyAnnotatedHashMapWhenCallingPutExpectReadOnlyException()
-    {
-
-    }
-
-    @Test( expected = ReadOnlyException.class )
-    @Ignore
-    public void givenReadOnlyAnnotatedHashMapWhenCallingRemoveExpectReadOnlyException()
-    {
-
-    }
-
-    @Test( expected = ReadOnlyException.class )
-    @Ignore
-    public void givenReadOnlyAnnotatedHashMapWhenCallingPutAllExpectReadOnlyException()
-    {
-
-    }
-
-    @Test( expected = ReadOnlyException.class )
-    @Ignore
-    public void givenReadOnlyAnnotatedHashMapWhenCallingClearExpectReadOnlyException()
-    {
-
-    }
-
-    public static abstract class ReadOnlyMapConcern
-        extends ConcernOf<Map>
-        implements Map
-    {
-        @Invocation
-        private Method method;
-
-        @This
-        private Composite me;
-
-        @Override
-        public Object put( Object key, Object value )
-        {
-            throw new ReadOnlyException( me, method );
-        }
-
-        @Override
-        public Object remove( Object key )
-        {
-            throw new ReadOnlyException( me, method );
-        }
-
-        @Override
-        public void putAll( Map m )
-        {
-            throw new ReadOnlyException( me, method );
-        }
-
-        @Override
-        public void clear()
-        {
-            throw new ReadOnlyException( me, method );
-        }
-    }
-
-    private static class ReadOnlyException
-        extends RuntimeException
-    {
-        public ReadOnlyException( Composite me, Method method )
-        {
-            super( "Method " + method.getName() + " in [" + me.toString() + "] is READ ONLY." );
-        }
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/composite/QI247Test1.java b/core/runtime/src/test/java/org/qi4j/runtime/composite/QI247Test1.java
deleted file mode 100644
index d187155..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/composite/QI247Test1.java
+++ /dev/null
@@ -1,142 +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.qi4j.runtime.composite;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class QI247Test1
-    extends AbstractQi4jTest
-{
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TransientWithMixin.class );
-    }
-
-    private void checkToString( ObjectMethods withMixin )
-    {
-        assertEquals( ObjectMethods.MESSAGE, withMixin.toString() );
-    }
-
-    private void checkHashCode( ObjectMethods withMixin )
-    {
-        assertEquals( ObjectMethods.CODE, withMixin.hashCode() );
-    }
-
-    private void checkSelfEquals( ObjectMethods withMixin )
-    {
-        assertEquals( withMixin, withMixin );
-    }
-
-    private void checkTwoNotEqual( ObjectMethods first, ObjectMethods second )
-    {
-        assertFalse( first.equals( second ) );
-    }
-
-    // MIXIN
-
-    @Test
-    public void testWithMixinToString()
-    {
-        ObjectMethods withMixin = module.newTransient( ObjectMethods.class );
-        checkToString( withMixin );
-    }
-
-    @Test
-    public void testWithMixinHashCode()
-    {
-        ObjectMethods withMixin = module.newTransient( ObjectMethods.class );
-        checkHashCode( withMixin );
-    }
-
-    @Test
-    public void testWithMixinSelfEquals()
-    {
-        ObjectMethods withMixin = module.newTransient( ObjectMethods.class );
-        checkSelfEquals( withMixin );
-    }
-
-    @Test
-    public void testWithMixinSelfEquals2()
-    {
-        ObjectMethods withMixin = module.newTransient( ObjectMethods.class );
-        assertTrue( withMixin.equals( withMixin ) );
-    }
-
-    @Test
-    public void testWithMixinSelfSame()
-    {
-        ObjectMethods withMixin = module.newTransient( ObjectMethods.class );
-        assertSame( withMixin, withMixin );
-    }
-
-    @Test
-    public void testWithMixinTwoNotEqual()
-    {
-        ObjectMethods first = module.newTransient( ObjectMethods.class );
-        ObjectMethods second = module.newTransient( ObjectMethods.class );
-        checkTwoNotEqual( first, second );
-    }
-
-    public interface ObjectMethods
-    {
-        String MESSAGE = "Does not work :(";
-        int CODE = 123;
-
-        void someMethod();
-    }
-
-    public static class ObjectMethodsMixin
-        implements ObjectMethods
-    {
-
-        @Override
-        public int hashCode()
-        {
-            return CODE;
-        }
-
-        @Override
-        public String toString()
-        {
-            return MESSAGE;
-        }
-
-        public void someMethod()
-        {
-        }
-    }
-
-    @Mixins( ObjectMethodsMixin.class )
-    public interface TransientWithMixin
-        extends TransientComposite, ObjectMethods
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/composite/QI247Test2.java b/core/runtime/src/test/java/org/qi4j/runtime/composite/QI247Test2.java
deleted file mode 100644
index e70c90a..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/composite/QI247Test2.java
+++ /dev/null
@@ -1,158 +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.qi4j.runtime.composite;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class QI247Test2
-    extends AbstractQi4jTest
-{
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TransientWithHandler.class );
-    }
-
-    private void checkToString( ObjectMethods instance )
-    {
-        assertEquals( ObjectMethods.MESSAGE, instance.toString() );
-    }
-
-    private void checkHashCode( ObjectMethods instance )
-    {
-        assertEquals( ObjectMethods.CODE, instance.hashCode() );
-    }
-
-    private void checkSelfEquals( ObjectMethods instance )
-    {
-        assertEquals( instance, instance );
-    }
-
-    private void checkTwoNotEqual( ObjectMethods first, ObjectMethods second )
-    {
-        assertFalse( first.equals( second ) );
-    }
-
-    //HANDLER
-
-    @Test
-    public void testWithHandlerToString()
-    {
-        ObjectMethods withHandler = module.newTransient( ObjectMethods.class );
-        checkToString( withHandler );
-    }
-
-    @Test
-    public void testWithHandlerHashCode()
-    {
-        ObjectMethods withHandler = module.newTransient( ObjectMethods.class );
-        checkHashCode( withHandler );
-    }
-
-    @Test
-    public void testWithHandlerSelfEquals()
-    {
-        ObjectMethods withHandler = module.newTransient( ObjectMethods.class );
-        checkSelfEquals( withHandler );
-    }
-
-    @Test
-    public void testWithHandlerSelfEquals2()
-    {
-        ObjectMethods withHandler = module.newTransient( ObjectMethods.class );
-        assertTrue( withHandler.equals( withHandler ) );
-    }
-
-    @Test
-    public void testWithHandlerSelfSame()
-    {
-        ObjectMethods withHandler = module.newTransient( ObjectMethods.class );
-        assertSame( withHandler, withHandler );
-    }
-
-    @Test
-    public void testWithHandlerTwoNotEqual()
-    {
-        ObjectMethods first = module.newTransient( ObjectMethods.class );
-        ObjectMethods second = module.newTransient( ObjectMethods.class );
-        checkTwoNotEqual( first, second );
-    }
-
-    public interface ObjectMethods
-    {
-        String MESSAGE = "Does not work :(";
-
-        int CODE = 123;
-
-        void someMethod();
-    }
-
-    public static class ObjectMethodsHandler
-        implements InvocationHandler
-    {
-        public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-        {
-            System.out.println( "invoke(proxy, " + method.getName() + ", args" );
-            if( "someMethod".equals( method.getName() ) )
-            {
-                System.out.println( "Hello." );
-                return null;
-            }
-            else
-            {
-                throw new UnsupportedOperationException( method.toString() );
-            }
-        }
-
-        public String toString()
-        {
-            return ObjectMethods.MESSAGE;
-        }
-
-        public int hashCode()
-        {
-            return ObjectMethods.CODE;
-        }
-
-        public boolean equals( Object o )
-        {
-            return o == this;
-        }
-    }
-
-    @Mixins( ObjectMethodsHandler.class )
-    public interface TransientWithHandler
-        extends TransientComposite, ObjectMethods
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/composite/QI256Test.java b/core/runtime/src/test/java/org/qi4j/runtime/composite/QI256Test.java
deleted file mode 100644
index eae1f8c..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/composite/QI256Test.java
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.composite;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-/**
- * JAVADOC
- */
-public class QI256Test
-    extends AbstractQi4jTest
-{
-
-    public static class TestException
-        extends RuntimeException
-    {
-        public TestException()
-        {
-            super( "Test" );
-        }
-    }
-
-    @Mixins( { TestTransient.TestTransientMixin.class } )
-    public static interface TestTransient
-        extends TransientComposite
-    {
-        public void declaredMethodThatThrowsCustomException();
-
-        public void invokeDeclaredPublicMethodThatThrowsCustomException();
-
-        public void invokePrivateMethodThatThrowsCustomException();
-
-        public void invokeProtectedMethodThatThrowsCustomException();
-
-        public void invokeUndeclaredPublicMethodThatThrowsCustomException();
-
-        public void declaredMethodThatThrowsBuiltinInheritedException();
-
-        public void invokeDeclaredPublicMethodThatThrowsBuiltinInheritedException();
-
-        public void invokePrivateMethodThatThrowsBuiltinInheritedException();
-
-        public void invokeProtectedMethodThatThrowsBuiltinInheritedException();
-
-        public void invokeUndeclaredPublicMethodThatThrowsBuiltinInheritedException();
-
-        public void declaredMethodThatThrowsBuiltinException();
-
-        public void invokeDeclaredPublicMethodThatThrowsBuiltinException();
-
-        public void invokePrivateMethodThatThrowsBuiltinException();
-
-        public void invokeProtectedMethodThatThrowsBuiltinException();
-
-        public void invokeUndeclaredPublicMethodThatThrowsBuiltinException();
-
-        public abstract class TestTransientMixin
-            implements TestTransient
-        {
-            public void declaredMethodThatThrowsCustomException()
-            {
-                throw new TestException();
-            }
-
-            public void invokeDeclaredPublicMethodThatThrowsCustomException()
-            {
-                this.declaredMethodThatThrowsCustomException();
-            }
-
-            public void invokePrivateMethodThatThrowsCustomException()
-            {
-                this.privateThrowException( TestException.class );
-            }
-
-            public void invokeProtectedMethodThatThrowsCustomException()
-            {
-                this.protectedThrowException( TestException.class );
-            }
-
-            public void invokeUndeclaredPublicMethodThatThrowsCustomException()
-            {
-                this.publicThrowException( TestException.class );
-            }
-
-            public void declaredMethodThatThrowsBuiltinInheritedException()
-            {
-                throw new IllegalArgumentException();
-            }
-
-            public void invokeDeclaredPublicMethodThatThrowsBuiltinInheritedException()
-            {
-                this.declaredMethodThatThrowsBuiltinInheritedException();
-            }
-
-            public void invokePrivateMethodThatThrowsBuiltinInheritedException()
-            {
-                this.privateThrowException( IllegalArgumentException.class );
-            }
-
-            public void invokeProtectedMethodThatThrowsBuiltinInheritedException()
-            {
-                this.protectedThrowException( IllegalArgumentException.class );
-            }
-
-            public void invokeUndeclaredPublicMethodThatThrowsBuiltinInheritedException()
-            {
-                this.publicThrowException( IllegalArgumentException.class );
-            }
-
-            public void declaredMethodThatThrowsBuiltinException()
-            {
-                throw new RuntimeException();
-            }
-
-            public void invokeDeclaredPublicMethodThatThrowsBuiltinException()
-            {
-                this.declaredMethodThatThrowsBuiltinException();
-            }
-
-            public void invokePrivateMethodThatThrowsBuiltinException()
-            {
-                this.privateThrowException( RuntimeException.class );
-            }
-
-            public void invokeProtectedMethodThatThrowsBuiltinException()
-            {
-                this.protectedThrowException( RuntimeException.class );
-            }
-
-            public void invokeUndeclaredPublicMethodThatThrowsBuiltinException()
-            {
-                this.publicThrowException( RuntimeException.class );
-            }
-
-            private void privateThrowException( Class<? extends RuntimeException> clazz )
-            {
-                try
-                {
-                    throw clazz.newInstance();
-                }
-                catch( Throwable t )
-                {
-                    if( clazz.isInstance( t ) )
-                    {
-                        throw clazz.cast( t );
-                    }
-                    // Ignore
-                }
-            }
-
-            protected void protectedThrowException( Class<? extends RuntimeException> clazz )
-            {
-                try
-                {
-                    throw clazz.newInstance();
-                }
-                catch( Throwable t )
-                {
-                    if( clazz.isInstance( t ) )
-                    {
-                        throw clazz.cast( t );
-                    }
-                    // Ignore
-                }
-            }
-
-            public void publicThrowException( Class<? extends RuntimeException> clazz )
-            {
-                try
-                {
-                    throw clazz.newInstance();
-                }
-                catch( Throwable t )
-                {
-                    if( clazz.isInstance( t ) )
-                    {
-                        throw clazz.cast( t );
-                    }
-                    // Ignore
-                }
-            }
-        }
-    }
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TestTransient.class );
-    }
-
-    @Test( expected = TestException.class )
-    public void invokeCustomExceptionThrowingMethod()
-        throws Throwable
-    {
-        this.module.newTransient( TestTransient.class ).declaredMethodThatThrowsCustomException();
-    }
-
-    @Test( expected = TestException.class )
-    public void invokeDeclaredPublicMethodWhichInvokesCustomExceptionThrowingMethod()
-        throws Throwable
-    {
-        this.module
-            .newTransient( TestTransient.class )
-            .invokeDeclaredPublicMethodThatThrowsCustomException();
-    }
-
-    @Test( expected = TestException.class )
-    public void invokeUndeclaredPublicMethodWhichInvokesCustomExceptionThrowingMethod()
-        throws Throwable
-    {
-        this.module
-            .newTransient( TestTransient.class )
-            .invokeUndeclaredPublicMethodThatThrowsCustomException();
-    }
-
-    @Test( expected = TestException.class )
-    public void invokePrivateMethodWhichInvokesCustomExceptionThrowingMethod()
-        throws Throwable
-    {
-        this.module.newTransient( TestTransient.class ).invokePrivateMethodThatThrowsCustomException();
-    }
-
-    @Test( expected = TestException.class )
-    public void invokeProtectedMethodWhichInvokesCustomExceptionThrowingMethod()
-        throws Throwable
-    {
-        this.module
-            .newTransient( TestTransient.class )
-            .invokeProtectedMethodThatThrowsCustomException();
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void invokeBuiltinInheritedExceptionThrowingMethod()
-        throws Throwable
-    {
-        this.module
-            .newTransient( TestTransient.class )
-            .declaredMethodThatThrowsBuiltinInheritedException();
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void invokeDeclaredPublicMethodWhichInvokesBuiltinInheritedExceptionThrowingMethod()
-        throws Throwable
-    {
-        this.module
-            .newTransient( TestTransient.class )
-            .invokeDeclaredPublicMethodThatThrowsBuiltinInheritedException();
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void invokeUndeclaredPublicMethodWhichInvokesBuiltinInheritedExceptionThrowingMethod()
-        throws Throwable
-    {
-        this.module
-            .newTransient( TestTransient.class )
-            .invokeUndeclaredPublicMethodThatThrowsBuiltinInheritedException();
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void invokePrivateMethodWhichInvokesBuiltinInheritedExceptionThrowingMethod()
-        throws Throwable
-    {
-        this.module
-            .newTransient( TestTransient.class )
-            .invokePrivateMethodThatThrowsBuiltinInheritedException();
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void invokeProtectedMethodWhichInvokesBuiltinInheritedExceptionThrowingMethod()
-        throws Throwable
-    {
-        this.module
-            .newTransient( TestTransient.class )
-            .invokeProtectedMethodThatThrowsBuiltinInheritedException();
-    }
-
-    @Test( expected = RuntimeException.class )
-    public void invokeBuiltinExceptionThrowingMethod()
-        throws Throwable
-    {
-        this.module
-            .newTransient( TestTransient.class )
-            .declaredMethodThatThrowsBuiltinInheritedException();
-    }
-
-    @Test( expected = RuntimeException.class )
-    public void invokeDeclaredPublicMethodWhichInvokesBuiltinExceptionThrowingMethod()
-        throws Throwable
-    {
-        this.module
-            .newTransient( TestTransient.class )
-            .invokeDeclaredPublicMethodThatThrowsBuiltinInheritedException();
-    }
-
-    @Test( expected = RuntimeException.class )
-    public void invokeUndeclaredPublicMethodWhichInvokesBuiltinExceptionThrowingMethod()
-        throws Throwable
-    {
-        this.module
-            .newTransient( TestTransient.class )
-            .invokeUndeclaredPublicMethodThatThrowsBuiltinInheritedException();
-    }
-
-    @Test( expected = RuntimeException.class )
-    public void invokePrivateMethodWhichInvokesBuiltinExceptionThrowingMethod()
-        throws Throwable
-    {
-        this.module
-            .newTransient( TestTransient.class )
-            .invokePrivateMethodThatThrowsBuiltinInheritedException();
-    }
-
-    @Test( expected = RuntimeException.class )
-    public void invokeProtectedMethodWhichInvokesBuiltinExceptionThrowingMethod()
-        throws Throwable
-    {
-        this.module
-            .newTransient( TestTransient.class )
-            .invokeProtectedMethodThatThrowsBuiltinInheritedException();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/composite/TransientAsClassTest.java b/core/runtime/src/test/java/org/qi4j/runtime/composite/TransientAsClassTest.java
deleted file mode 100644
index 644da0d..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/composite/TransientAsClassTest.java
+++ /dev/null
@@ -1,58 +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.qi4j.runtime.composite;
-
-import org.junit.Ignore;
-import org.junit.Test;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test for QI-298.
- */
-@Ignore( "Awaiting QI-298" )
-public class TransientAsClassTest
-    extends AbstractQi4jTest
-{
-    public static class UnderTest
-    {
-        public String foo()
-        {
-            return "bar";
-        }
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( UnderTest.class );
-    }
-
-    @Test
-    public void test()
-    {
-        UnderTest underTest = module.newTransient( UnderTest.class );
-        assertThat( underTest.foo(), equalTo( "bar" ) );
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/composite/UsageGraphTest.java b/core/runtime/src/test/java/org/qi4j/runtime/composite/UsageGraphTest.java
deleted file mode 100644
index b21a3ba..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/composite/UsageGraphTest.java
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.runtime.composite;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.bootstrap.BindingException;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class UsageGraphTest
-{
-
-    @Before
-    public void setUp()
-    {
-        Thing.counter = 1;
-    }
-
-    @Test
-    public void verifyRandomDoesNotAffect()
-        throws Exception
-    {
-        for( int i = 0; i < 100; i++ )
-        {
-            whenGraphIsOpenEndedGivenNotAllowCyclicDependenciesThenNoError();
-            whenGraphIsCyclicGivenAllowCyclicDependencyThenNoError();
-        }
-    }
-
-    @Test
-    public void whenGraphIsOpenEndedGivenNotAllowCyclicDependenciesThenNoError()
-        throws Exception
-    {
-        Thing thing1 = new Thing();
-        Thing thing2 = new Thing();
-        Thing thing3 = new Thing();
-        Thing thing4 = new Thing();
-        Thing thing5 = new Thing();
-        Thing thing6 = new Thing();
-        Thing thing7 = new Thing();
-        thing1.uses.add( thing3 );
-        thing2.uses.add( thing3 );
-        thing3.uses.add( thing4 );
-        thing4.uses.add( thing5 );
-        thing1.uses.add( thing6 );
-        thing7.uses.add( thing1 );
-        thing7.uses.add( thing2 );
-        thing7.uses.add( thing4 );
-        List<Thing> data = new ArrayList<Thing>();
-        data.add( thing7 );
-        data.add( thing4 );
-        data.add( thing3 );
-        data.add( thing1 );
-        data.add( thing6 );
-        data.add( thing5 );
-        data.add( thing2 );
-        randomize( data );
-        UsageGraph<Thing> deps = new UsageGraph<Thing>( data, new Userator(), false );
-        assertFalse( deps.transitiveUse( thing1, thing1 ) );
-        assertFalse( deps.transitiveUse( thing1, thing2 ) );
-        assertTrue( deps.transitiveUse( thing1, thing3 ) );
-        assertTrue( deps.transitiveUse( thing1, thing4 ) );
-        assertTrue( deps.transitiveUse( thing1, thing5 ) );
-        assertTrue( deps.transitiveUse( thing1, thing6 ) );
-        assertFalse( deps.transitiveUse( thing1, thing7 ) );
-        assertFalse( deps.transitiveUse( thing2, thing1 ) );
-        assertFalse( deps.transitiveUse( thing2, thing2 ) );
-        assertTrue( deps.transitiveUse( thing2, thing3 ) );
-        assertTrue( deps.transitiveUse( thing2, thing4 ) );
-        assertTrue( deps.transitiveUse( thing2, thing5 ) );
-        assertFalse( deps.transitiveUse( thing2, thing6 ) );
-        assertFalse( deps.transitiveUse( thing2, thing7 ) );
-        assertFalse( deps.transitiveUse( thing3, thing1 ) );
-        assertFalse( deps.transitiveUse( thing3, thing2 ) );
-        assertFalse( deps.transitiveUse( thing3, thing3 ) );
-        assertTrue( deps.transitiveUse( thing3, thing4 ) );
-        assertTrue( deps.transitiveUse( thing3, thing5 ) );
-        assertFalse( deps.transitiveUse( thing3, thing6 ) );
-        assertFalse( deps.transitiveUse( thing3, thing7 ) );
-        assertFalse( deps.transitiveUse( thing4, thing1 ) );
-        assertFalse( deps.transitiveUse( thing4, thing2 ) );
-        assertFalse( deps.transitiveUse( thing4, thing3 ) );
-        assertFalse( deps.transitiveUse( thing4, thing4 ) );
-        assertTrue( deps.transitiveUse( thing4, thing5 ) );
-        assertFalse( deps.transitiveUse( thing4, thing6 ) );
-        assertFalse( deps.transitiveUse( thing4, thing7 ) );
-        assertFalse( deps.transitiveUse( thing5, thing1 ) );
-        assertFalse( deps.transitiveUse( thing5, thing2 ) );
-        assertFalse( deps.transitiveUse( thing5, thing3 ) );
-        assertFalse( deps.transitiveUse( thing5, thing4 ) );
-        assertFalse( deps.transitiveUse( thing5, thing5 ) );
-        assertFalse( deps.transitiveUse( thing5, thing6 ) );
-        assertFalse( deps.transitiveUse( thing5, thing7 ) );
-        assertFalse( deps.transitiveUse( thing6, thing1 ) );
-        assertFalse( deps.transitiveUse( thing6, thing2 ) );
-        assertFalse( deps.transitiveUse( thing6, thing3 ) );
-        assertFalse( deps.transitiveUse( thing6, thing4 ) );
-        assertFalse( deps.transitiveUse( thing6, thing5 ) );
-        assertFalse( deps.transitiveUse( thing6, thing6 ) );
-        assertFalse( deps.transitiveUse( thing6, thing7 ) );
-        assertTrue( deps.transitiveUse( thing7, thing1 ) );
-        assertTrue( deps.transitiveUse( thing7, thing2 ) );
-        assertTrue( deps.transitiveUse( thing7, thing3 ) );
-        assertTrue( deps.transitiveUse( thing7, thing4 ) );
-        assertTrue( deps.transitiveUse( thing7, thing5 ) );
-        assertTrue( deps.transitiveUse( thing7, thing6 ) );
-        assertFalse( deps.transitiveUse( thing7, thing7 ) );
-        List<Thing> resolved = deps.resolveOrder();
-        System.out.println( resolved );
-        assertTrue( resolved.indexOf( thing1 ) > resolved.indexOf( thing6 ) );
-        assertTrue( resolved.indexOf( thing2 ) > resolved.indexOf( thing3 ) );
-        assertTrue( resolved.indexOf( thing2 ) > resolved.indexOf( thing4 ) );
-        assertTrue( resolved.indexOf( thing2 ) > resolved.indexOf( thing5 ) );
-        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing1 ) );
-        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing2 ) );
-        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing4 ) );
-        assertTrue( resolved.indexOf( thing1 ) > resolved.indexOf( thing3 ) );
-        assertTrue( resolved.indexOf( thing1 ) > resolved.indexOf( thing4 ) );
-        assertTrue( resolved.indexOf( thing1 ) > resolved.indexOf( thing5 ) );
-        assertTrue( resolved.indexOf( thing3 ) > resolved.indexOf( thing4 ) );
-        assertTrue( resolved.indexOf( thing3 ) > resolved.indexOf( thing5 ) );
-        assertTrue( resolved.indexOf( thing4 ) > resolved.indexOf( thing5 ) );
-        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing4 ) );
-        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing5 ) );
-        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing6 ) );
-    }
-
-    private void randomize( List<Thing> data )
-    {
-        int n = (int) ( Math.random() * 100 );
-        for( int i = 0; i < n; i++ )
-        {
-            int pos1 = 0;
-            int pos2 = 0;
-            while( pos1 == pos2 )
-            {
-                pos1 = (int) ( Math.floor( Math.random() * data.size() ) );
-                pos2 = (int) ( Math.floor( Math.random() * data.size() ) );
-            }
-            if( pos1 < pos2 )
-            {
-                int temp = pos2;
-                pos2 = pos1;
-                pos1 = temp;
-            }
-            Thing thing1 = data.remove( pos1 );
-            Thing thing2 = data.remove( pos2 );
-            data.add( pos2, thing1 );
-            data.add( pos1, thing2 );
-        }
-    }
-
-    @Test
-    public void whenAskingForDependencyGivenThatGraphContainsCyclicDepThenDetectTheError()
-        throws Exception
-    {
-        Thing thing1 = new Thing();
-        Thing thing2 = new Thing();
-        Thing thing3 = new Thing();
-        Thing thing4 = new Thing();
-        Thing thing5 = new Thing();
-        Thing thing6 = new Thing();
-        Thing thing7 = new Thing();
-        thing1.uses.add( thing3 );
-        thing2.uses.add( thing3 );
-        thing3.uses.add( thing4 );
-        thing4.uses.add( thing5 );
-        thing5.uses.add( thing1 );      // <-- Cyclic
-        thing1.uses.add( thing6 );
-        thing7.uses.add( thing1 );
-        thing7.uses.add( thing2 );
-        thing7.uses.add( thing4 );
-        List<Thing> data = new ArrayList<Thing>();
-        data.add( thing7 );
-        data.add( thing4 );
-        data.add( thing1 );
-        data.add( thing3 );
-        data.add( thing6 );
-        data.add( thing5 );
-        data.add( thing2 );
-        randomize( data );
-        UsageGraph<Thing> deps = new UsageGraph<Thing>( data, new Userator(), false );
-        try
-        {
-            List<Thing> resolved = deps.resolveOrder();
-            Assert.fail( "Cyclic Dependency Not Detected." );
-        }
-        catch( BindingException e )
-        {
-            // Expected!
-        }
-    }
-
-    @Test
-    public void whenAskingForResolveOrderGivenThatGraphContainsCyclicDepThenDetectTheError()
-        throws Exception
-    {
-        Thing thing1 = new Thing();
-        Thing thing2 = new Thing();
-        Thing thing3 = new Thing();
-        Thing thing4 = new Thing();
-        Thing thing5 = new Thing();
-        Thing thing6 = new Thing();
-        Thing thing7 = new Thing();
-        thing1.uses.add( thing3 );
-        thing2.uses.add( thing3 );
-        thing3.uses.add( thing4 );
-        thing4.uses.add( thing5 );
-        thing5.uses.add( thing1 );      // <-- Cyclic
-        thing1.uses.add( thing6 );
-        thing7.uses.add( thing1 );
-        thing7.uses.add( thing2 );
-        thing7.uses.add( thing4 );
-        List<Thing> data = new ArrayList<Thing>();
-        data.add( thing7 );
-        data.add( thing4 );
-        data.add( thing1 );
-        data.add( thing3 );
-        data.add( thing6 );
-        data.add( thing5 );
-        data.add( thing2 );
-        randomize( data );
-        UsageGraph<Thing> deps = new UsageGraph<Thing>( data, new Userator(), false );
-        try
-        {
-            assertTrue( deps.transitiveUse( thing1, thing3 ) );
-            Assert.fail( "Cyclic Dependency Not Detected." );
-        }
-        catch( BindingException e )
-        {
-            // Expected!
-        }
-    }
-
-    @Test
-    public void whenGraphIsCyclicGivenAllowCyclicDependencyThenNoError()
-        throws Exception
-    {
-        Thing thing1 = new Thing();
-        Thing thing2 = new Thing();
-        Thing thing3 = new Thing();
-        Thing thing4 = new Thing();
-        Thing thing5 = new Thing();
-        Thing thing6 = new Thing();
-        Thing thing7 = new Thing();
-        thing1.uses.add( thing3 );
-        thing2.uses.add( thing3 );
-        thing3.uses.add( thing4 );
-        thing4.uses.add( thing5 );
-        thing1.uses.add( thing6 );
-        thing5.uses.add( thing1 );      // <-- Cyclic
-        thing7.uses.add( thing1 );
-        thing7.uses.add( thing2 );
-        thing7.uses.add( thing4 );
-        List<Thing> data = new ArrayList<Thing>();
-        data.add( thing7 );
-        data.add( thing4 );
-        data.add( thing1 );
-        data.add( thing3 );
-        data.add( thing6 );
-        data.add( thing5 );
-        data.add( thing2 );
-        randomize( data );
-        UsageGraph<Thing> deps = new UsageGraph<Thing>( data, new Userator(), true );
-        assertTrue( deps.transitiveUse( thing1, thing1 ) );
-        assertFalse( deps.transitiveUse( thing1, thing2 ) );
-        assertTrue( deps.transitiveUse( thing1, thing3 ) );
-        assertTrue( deps.transitiveUse( thing1, thing4 ) );
-        assertTrue( deps.transitiveUse( thing1, thing5 ) );
-        assertTrue( deps.transitiveUse( thing1, thing6 ) );
-        assertFalse( deps.transitiveUse( thing1, thing7 ) );
-        assertTrue( deps.transitiveUse( thing2, thing1 ) );
-        assertFalse( deps.transitiveUse( thing2, thing2 ) );
-        assertTrue( deps.transitiveUse( thing2, thing3 ) );
-        assertTrue( deps.transitiveUse( thing2, thing4 ) );
-        assertTrue( deps.transitiveUse( thing2, thing5 ) );
-        assertTrue( deps.transitiveUse( thing2, thing6 ) );
-        assertFalse( deps.transitiveUse( thing2, thing7 ) );
-        assertTrue( deps.transitiveUse( thing3, thing1 ) );
-        assertFalse( deps.transitiveUse( thing3, thing2 ) );
-        assertTrue( deps.transitiveUse( thing3, thing3 ) );
-        assertTrue( deps.transitiveUse( thing3, thing4 ) );
-        assertTrue( deps.transitiveUse( thing3, thing5 ) );
-        assertTrue( deps.transitiveUse( thing3, thing6 ) );
-        assertFalse( deps.transitiveUse( thing3, thing7 ) );
-        assertTrue( deps.transitiveUse( thing4, thing1 ) );
-        assertFalse( deps.transitiveUse( thing4, thing2 ) );
-        assertTrue( deps.transitiveUse( thing4, thing3 ) );
-        assertTrue( deps.transitiveUse( thing4, thing4 ) );
-        assertTrue( deps.transitiveUse( thing4, thing5 ) );
-        assertTrue( deps.transitiveUse( thing4, thing6 ) );
-        assertFalse( deps.transitiveUse( thing4, thing7 ) );
-        assertTrue( deps.transitiveUse( thing5, thing1 ) );
-        assertFalse( deps.transitiveUse( thing5, thing2 ) );
-        assertTrue( deps.transitiveUse( thing5, thing3 ) );
-        assertTrue( deps.transitiveUse( thing5, thing4 ) );
-        assertTrue( deps.transitiveUse( thing5, thing5 ) );
-        assertTrue( deps.transitiveUse( thing5, thing6 ) );
-        assertFalse( deps.transitiveUse( thing5, thing7 ) );
-        assertFalse( deps.transitiveUse( thing6, thing1 ) );
-        assertFalse( deps.transitiveUse( thing6, thing2 ) );
-        assertFalse( deps.transitiveUse( thing6, thing3 ) );
-        assertFalse( deps.transitiveUse( thing6, thing4 ) );
-        assertFalse( deps.transitiveUse( thing6, thing5 ) );
-        assertFalse( deps.transitiveUse( thing6, thing6 ) );
-        assertFalse( deps.transitiveUse( thing6, thing7 ) );
-        assertTrue( deps.transitiveUse( thing7, thing1 ) );
-        assertTrue( deps.transitiveUse( thing7, thing2 ) );
-        assertTrue( deps.transitiveUse( thing7, thing3 ) );
-        assertTrue( deps.transitiveUse( thing7, thing4 ) );
-        assertTrue( deps.transitiveUse( thing7, thing5 ) );
-        assertTrue( deps.transitiveUse( thing7, thing6 ) );
-        assertFalse( deps.transitiveUse( thing7, thing7 ) );
-        List<Thing> resolved = deps.resolveOrder();
-        System.out.println( resolved );
-        assertTrue( resolved.indexOf( thing1 ) > resolved.indexOf( thing6 ) );
-        assertTrue( resolved.indexOf( thing2 ) > resolved.indexOf( thing3 ) );
-        assertTrue( resolved.indexOf( thing2 ) > resolved.indexOf( thing4 ) );
-        assertTrue( resolved.indexOf( thing2 ) > resolved.indexOf( thing5 ) );
-        assertTrue( resolved.indexOf( thing2 ) > resolved.indexOf( thing1 ) );
-        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing1 ) );
-        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing2 ) );
-        assertTrue( resolved.indexOf( thing7 ) > resolved.indexOf( thing4 ) );
-
-        // The cyclic nodes can not be determine which one is before the other
-    }
-
-    public class Userator
-        implements UsageGraph.Use<Thing>
-    {
-
-        public List<Thing> uses( Thing source )
-        {
-            return source.uses;
-        }
-    }
-
-    public static class Thing
-    {
-        private static int counter = 1;
-
-        private List<Thing> uses = new ArrayList<Thing>();
-        private String name = "Thing" + counter++;
-
-        public String toString()
-        {
-            return name;
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/concerns/GenericConcernTest.java b/core/runtime/src/test/java/org/qi4j/runtime/concerns/GenericConcernTest.java
deleted file mode 100644
index cf91205..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/concerns/GenericConcernTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.concerns;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-/**
- * Tests for GenericConcern
- */
-public class GenericConcernTest
-    extends AbstractQi4jTest
-{
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( SomeComposite.class );
-    }
-
-    @Test
-    public void testNestedUnitOfWork()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        Some some = module.newTransient( Some.class );
-        some.doStuff();
-        uow.discard();
-    }
-
-    @Mixins( SomeMixin.class )
-    public interface SomeComposite
-        extends Some, TransientComposite
-    {
-    }
-
-    public interface Some
-    {
-        @NestedUnitOfWork
-        public String doStuff();
-    }
-
-    public static abstract class SomeMixin
-        implements Some
-    {
-        public String doStuff()
-        {
-            return "Blah blah";
-        }
-    }
-
-    @Retention( RetentionPolicy.RUNTIME )
-    @Target( { ElementType.METHOD } )
-    public @interface NestedUnitOfWork
-    {
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/concerns/ModuleConcernTest.java b/core/runtime/src/test/java/org/qi4j/runtime/concerns/ModuleConcernTest.java
deleted file mode 100644
index 51388eb..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/concerns/ModuleConcernTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.concerns;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.concern.GenericConcern;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.AssemblyVisitorAdapter;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.TransientDeclaration;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test of declaring concern in assembly
- */
-public class ModuleConcernTest
-    extends AbstractQi4jTest
-{
-    public static boolean ok;
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( FooComposite.class );
-
-        module.layer().application().visit( new AssemblyVisitorAdapter<RuntimeException>()
-        {
-            @Override
-            public void visitComposite( TransientDeclaration declaration )
-            {
-                declaration.withConcerns( TraceConcern.class );
-            }
-        }
-
-        );
-    }
-
-    @Test
-    public void testModuleConcerns()
-    {
-        module.newTransient( Foo.class ).test( "Foo", 42 );
-        assertThat( "Concern has executed", ok, equalTo( true ) );
-    }
-
-    @Mixins( FooMixin.class )
-    public interface FooComposite
-        extends TransientComposite, Foo
-    {
-    }
-
-    public interface Foo
-    {
-        String test( String foo, int bar );
-    }
-
-    public static class FooMixin
-        implements Foo
-    {
-        public String test( String foo, int bar )
-        {
-            return foo + " " + bar;
-        }
-    }
-
-    public static class TraceConcern
-        extends GenericConcern
-    {
-        public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-        {
-            ok = true;
-            Object result = next.invoke( proxy, method, args );
-            String str = method.getName() + Arrays.asList( args );
-            System.out.println( str );
-            return result;
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/concerns/PropertyInheritanceTest.java b/core/runtime/src/test/java/org/qi4j/runtime/concerns/PropertyInheritanceTest.java
deleted file mode 100644
index 79b3d49..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/concerns/PropertyInheritanceTest.java
+++ /dev/null
@@ -1,112 +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.qi4j.runtime.concerns;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.junit.Test;
-import org.qi4j.api.common.InvalidApplicationException;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.property.InvalidPropertyTypeException;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
-
-//TODO 2.0 removed this possibility when simplifying the Property handling. So, we are now checking that a decent
-// exception is thrown, but should be changed to supported instead.
-public class PropertyInheritanceTest extends AbstractQi4jTest
-{
-
-    private boolean failed;
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( Audit.class );
-    }
-
-    @Override
-    protected void assemblyException( AssemblyException exception )
-        throws AssemblyException
-    {
-        if( exception.getCause() instanceof InvalidApplicationException )
-        {
-            if( exception.getCause().getCause() instanceof InvalidPropertyTypeException )
-            {
-                failed = true;
-                return;
-            }
-        }
-        super.assemblyException( exception );
-    }
-
-    @Test
-    public void givenConcernOnInheritedPropertyWhenAccessingPropertyExpectConcernToBeCalled()
-    {
-        assertThat( failed, equalTo( true ) );
-
-// TODO: The following test code is testing the feature once it has been implemented. The @Test is needed to ensure check for the right Exception.
-//        List<String> data = new ArrayList<String>();
-//        data.add( "First" );
-//        data.add( "Second" );
-//        data.add( "Third" );
-//        Audit audit = module.newTransient( Audit.class );
-//        AuditTrail trail = audit.trail();
-//        trail.set( data );
-//        assertThat( audit.trail().get().get( 0 ), equalTo( "1: First" ) );
-//        assertThat( audit.trail().get().get( 1 ), equalTo( "2: Second" ) );
-//        assertThat( audit.trail().get().get( 2 ), equalTo("3: Third"));
-    }
-
-    public static abstract class AuditTrailMarkupConcern extends ConcernOf<AuditTrail>
-        implements AuditTrail
-    {
-
-        @Override
-        public void set( List<String> newValue )
-            throws IllegalArgumentException, IllegalStateException
-        {
-            List<String> markedUp = new ArrayList<String>();
-            int counter = 0;
-            for( String value : newValue )
-            {
-                markedUp.add( counter++ + ": " + value );
-            }
-            next.set( markedUp );
-        }
-    }
-
-    @Concerns( AuditTrailMarkupConcern.class )
-    public interface AuditTrail extends Property<List<String>>
-    {
-    }
-
-    public interface Audit
-    {
-        @UseDefaults
-        AuditTrail trail();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/constraints/ConstraintsTest.java b/core/runtime/src/test/java/org/qi4j/runtime/constraints/ConstraintsTest.java
deleted file mode 100644
index 4b77266..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/constraints/ConstraintsTest.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.runtime.constraints;
-
-import java.lang.annotation.Retention;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Test;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.ConstraintViolation;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.api.constraint.Name;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-public class ConstraintsTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( MyOneComposite.class );
-        module.transients( MyOneComposite2.class );
-    }
-
-    @Test
-    public void givenCompositeWithConstraintsWhenInstantiatedThenUseDeclarationOnComposite()
-        throws Throwable
-    {
-        MyOne my = module.newTransient( MyOneComposite.class );
-        ArrayList<String> list = new ArrayList<String>();
-        list.add( "zout" );
-        my.doSomething( "habba", list );
-        try
-        {
-            my.doSomething( "niclas", new ArrayList<String>() );
-            fail( "Should have thrown a ConstraintViolationException." );
-        }
-        catch( ConstraintViolationException e )
-        {
-            Collection<ConstraintViolation> violations = e.constraintViolations();
-            assertEquals( 2, violations.size() );
-//            assertEquals( MyOne.class.getName(), e.mixinTypeName() );
-        }
-    }
-
-    @Test
-    public void givenCompositeWithoutConstraintsWhenInstantiatedThenUseDeclarationOnConstraint()
-        throws Throwable
-    {
-        MyOne my = module.newTransient( MyOneComposite2.class );
-        ArrayList<String> list = new ArrayList<String>();
-        list.add( "zout" );
-        my.doSomething( "habba", list );
-        try
-        {
-            my.doSomething( "niclas", new ArrayList<String>() );
-            fail( "Should have thrown a ConstraintViolationException." );
-        }
-        catch( ConstraintViolationException e )
-        {
-            Collection<ConstraintViolation> violations = e.constraintViolations();
-            assertEquals( 2, violations.size() );
-//            assertEquals( MyOne.class.getName(), e.mixinTypeName() );
-        }
-    }
-
-    @Test
-    public void givenConstrainedGenericWildcardParameterWhenInvokedThenUseConstraint()
-    {
-        MyOne myOne = module.newTransient( MyOneComposite.class );
-        ArrayList<String> list = new ArrayList<String>();
-        list.add( "Foo" );
-        myOne.doSomething2( list );
-    }
-
-    @Test
-    public void givenCompositeConstraintWhenInvokedThenUseAllConstraints()
-    {
-        MyOne myOne = module.newTransient( MyOneComposite.class );
-        ArrayList<String> list = new ArrayList<String>();
-        list.add( "Foo" );
-        myOne.doSomething3( list );
-    }
-
-    @Constraints( TestConstraintImpl.class )
-    @Mixins( MyOneMixin.class )
-    public interface MyOneComposite
-        extends MyOne, TransientComposite
-    {
-    }
-
-    @Mixins( MyOneMixin.class )
-    public interface MyOneComposite2
-        extends MyOne, TransientComposite
-    {
-    }
-
-    public interface MyOne
-    {
-        void doSomething( @Optional @TestConstraint String abc, @TestConstraint List<String> collection );
-
-        void doSomething2( @TestConstraint @NonEmptyCollection List<?> collection );
-
-        void doSomething3( @CompositeConstraint @Name( "somecollection" ) List<?> collection );
-    }
-
-    public abstract static class MyOneMixin
-        implements MyOne
-    {
-        public void doSomething( String abc, List<String> collection )
-        {
-            if( abc == null || collection == null )
-            {
-                throw new NullPointerException();
-            }
-        }
-
-        public void doSomething2( List<?> collection )
-        {
-            if( collection == null )
-            {
-                throw new NullPointerException();
-            }
-        }
-
-        public void doSomething3( List<?> collection )
-        {
-            if( collection == null )
-            {
-                throw new NullPointerException();
-            }
-        }
-    }
-
-    @ConstraintDeclaration
-    @Retention( RUNTIME )
-    @Constraints( TestConstraintImpl.class )
-    public @interface TestConstraint
-    {
-    }
-
-    public static class TestConstraintImpl
-        implements Constraint<TestConstraint, Object>
-    {
-        public boolean isValid( TestConstraint annotation, Object value )
-            throws NullPointerException
-        {
-            if( value instanceof String )
-            {
-                return ( (String) value ).startsWith( "habba" );
-            }
-            return value instanceof Collection && ( (Collection) value ).size() > 0;
-        }
-    }
-
-    @ConstraintDeclaration
-    @Retention( RUNTIME )
-    @Constraints( { NonEmptyCollectionConstraint.class } )
-    public @interface NonEmptyCollection
-    {
-    }
-
-    public static class NonEmptyCollectionConstraint
-        implements Constraint<NonEmptyCollection, Collection<?>>
-    {
-        public boolean isValid( NonEmptyCollection annotation, Collection<?> value )
-            throws NullPointerException
-        {
-            return value.size() > 0;
-        }
-    }
-
-    @ConstraintDeclaration
-    @Retention( RUNTIME )
-    @TestConstraint
-    @NonEmptyCollection
-    public @interface CompositeConstraint
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/constraints/ConstraintsTest.properties b/core/runtime/src/test/java/org/qi4j/runtime/constraints/ConstraintsTest.properties
deleted file mode 100644
index bb18d5f..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/constraints/ConstraintsTest.properties
+++ /dev/null
@@ -1,21 +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.
-
-qi4j.constraint.ConstraintsTest$MyOneComposite=Message1
-
-qi4j.constraint.NotNull=Message2
-
-qi4j.constraint.ConstraintsTest$MyOneComposite.doSomething=Message3
-
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/defaults/UseDefaultsTest.java b/core/runtime/src/test/java/org/qi4j/runtime/defaults/UseDefaultsTest.java
deleted file mode 100644
index cd762a6..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/defaults/UseDefaultsTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.defaults;
-
-import org.junit.Test;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.junit.Assert.assertThat;
-
-/**
- * JAVADOC
- */
-public class UseDefaultsTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TestComposite.class );
-        module.forMixin( TestComposite.class ).declareDefaults().assemblyString();
-    }
-
-    @Test
-    public void givenPropertyWithUseDefaultsWhenInstantiatedThenPropertiesAreDefaulted()
-    {
-        TransientBuilder<TestComposite> builder = module.newTransientBuilder( TestComposite.class );
-        TestComposite testComposite = builder.newInstance();
-
-        assertThat( "nullInt is null", testComposite.nullInt().get(), nullValue() );
-        assertThat( "zeroInt is zero", testComposite.defaultInt().get(), equalTo( 0 ) );
-        assertThat( "nullString is null", testComposite.nullString().get(), nullValue() );
-        assertThat( "defaultString is empty string", testComposite.defaultString().get(), equalTo( "" ) );
-        assertThat( "assemblyString is empty string", testComposite.assemblyString().get(), equalTo( "" ) );
-    }
-
-    interface TestComposite
-        extends TransientComposite
-    {
-        @Optional
-        Property<Integer> nullInt();
-
-        @Optional
-        @UseDefaults
-        Property<Integer> defaultInt();
-
-        @Optional
-        Property<String> nullString();
-
-        @Optional
-        @UseDefaults
-        Property<String> defaultString();
-
-        Property<String> assemblyString();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/entity/AggregatedTest.java b/core/runtime/src/test/java/org/qi4j/runtime/entity/AggregatedTest.java
deleted file mode 100644
index 0e43a3b..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/entity/AggregatedTest.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.entity;
-
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.entity.Aggregated;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.fail;
-
-/**
- * JAVADOC
- */
-public class AggregatedTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( CompanyEntity.class, EmployeeEntity.class, PersonEntity.class );
-
-        new EntityTestAssembler().assemble( module );
-
-        module.objects( getClass() );
-    }
-
-    @Test
-    public void givenAggregatedEntitiesWhenAggregateRootIsDeletedThenDeleteAggregatedEntities()
-        throws Exception
-    {
-        CompanyEntity companyEntity;
-        PersonEntity personEntity, personEntity2;
-        EmployeeEntity employeeEntity, employeeEntity2;
-        {
-            UnitOfWork unitOfWork = module.newUnitOfWork();
-            try
-            {
-                {
-                    EntityBuilder<PersonEntity> builder = unitOfWork.newEntityBuilder( PersonEntity.class );
-                    personEntity = builder.instance();
-                    personEntity.name().set( "Rickard" );
-                    personEntity = builder.newInstance();
-                }
-
-                {
-                    EntityBuilder<PersonEntity> builder = unitOfWork.newEntityBuilder( PersonEntity.class );
-                    personEntity2 = builder.instance();
-                    personEntity2.name().set( "Niclas" );
-                    builder.newInstance();
-                }
-
-                {
-                    EntityBuilder<EmployeeEntity> builder = unitOfWork.newEntityBuilder( EmployeeEntity.class );
-                    employeeEntity = builder.instance();
-                    employeeEntity.person().set( personEntity );
-                    employeeEntity.salary().set( 50000 );
-                    employeeEntity.title().set( "Director" );
-                    employeeEntity = builder.newInstance();
-                }
-
-                {
-                    EntityBuilder<EmployeeEntity> builder = unitOfWork.newEntityBuilder( EmployeeEntity.class );
-                    employeeEntity2 = builder.instance();
-                    employeeEntity2.person().set( personEntity );
-                    employeeEntity2.salary().set( 40000 );
-                    employeeEntity2.title().set( "Developer" );
-                    employeeEntity2 = builder.newInstance();
-                }
-
-                {
-                    EntityBuilder<CompanyEntity> builder = unitOfWork.newEntityBuilder( CompanyEntity.class );
-                    companyEntity = builder.instance();
-                    companyEntity.director().set( employeeEntity );
-                    companyEntity.employees().add( 0, employeeEntity );
-                    companyEntity.employees().add( 0, employeeEntity2 );
-                    companyEntity = builder.newInstance();
-                }
-
-                unitOfWork.complete();
-            }
-            finally
-            {
-                unitOfWork.discard();
-            }
-        }
-
-        {
-            UnitOfWork unitOfWork = module.newUnitOfWork();
-            try
-            {
-                companyEntity = unitOfWork.get( companyEntity );
-                unitOfWork.remove( companyEntity );
-
-                unitOfWork.complete();
-            }
-            finally
-            {
-                unitOfWork.discard();
-            }
-        }
-
-        {
-            UnitOfWork unitOfWork = module.newUnitOfWork();
-            try
-            {
-                unitOfWork.get( employeeEntity );
-
-                fail( "Should not work" );
-
-                unitOfWork.complete();
-            }
-            catch( NoSuchEntityException e )
-            {
-                unitOfWork.discard();
-            }
-        }
-
-        {
-            UnitOfWork unitOfWork = module.newUnitOfWork();
-            try
-            {
-                unitOfWork.get( employeeEntity2 );
-                fail( "Should not work" );
-
-                unitOfWork.complete();
-            }
-            catch( NoSuchEntityException e )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    public interface CompanyEntity
-        extends EntityComposite
-    {
-        @Aggregated
-        Association<EmployeeEntity> director();
-
-        @Aggregated
-        ManyAssociation<EmployeeEntity> employees();
-    }
-
-    public interface EmployeeEntity
-        extends EntityComposite
-    {
-        Property<String> title();
-
-        Property<Integer> salary();
-
-        Association<PersonEntity> person();
-    }
-
-    public interface PersonEntity
-        extends EntityComposite
-    {
-        Property<String> name();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityBuilderWithStateTest.java b/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityBuilderWithStateTest.java
deleted file mode 100644
index a949419..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityBuilderWithStateTest.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2015 Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.entity;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Map;
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Function;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-/**
- * EntityBuilder With State Test.
- */
-public class EntityBuilderWithStateTest
-    extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.entities( SomeEntity.class );
-    }
-
-    @Test
-    public void test()
-        throws UnitOfWorkCompletionException
-    {
-        final String associatedIdentity;
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            EntityBuilder<SomeEntity> builder = uow.newEntityBuilder( SomeEntity.class );
-            builder.instance().prop().set( "Associated" );
-            SomeEntity entity = builder.newInstance();
-            associatedIdentity = entity.identity().get();
-            uow.complete();
-        }
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            SomeEntity entity = uow.newEntityBuilderWithState(
-                SomeEntity.class,
-                new Function<PropertyDescriptor, Object>()
-                {
-                    @Override
-                    public Object map( PropertyDescriptor descriptor )
-                    {
-                        if( "prop".equals( descriptor.qualifiedName().name() ) )
-                        {
-                            return "Foo";
-                        }
-                        return null;
-                    }
-                },
-                new Function<AssociationDescriptor, EntityReference>()
-                {
-                    @Override
-                    public EntityReference map( AssociationDescriptor descriptor )
-                    {
-                        if( "ass".equals( descriptor.qualifiedName().name() ) )
-                        {
-                            return EntityReference.parseEntityReference( associatedIdentity );
-                        }
-                        return null;
-                    }
-                },
-                new Function<AssociationDescriptor, Iterable<EntityReference>>()
-                {
-                    @Override
-                    public Iterable<EntityReference> map( AssociationDescriptor descriptor )
-                    {
-                        if( "manyAss".equals( descriptor.qualifiedName().name() ) )
-                        {
-                            return Arrays.asList( EntityReference.parseEntityReference( associatedIdentity ) );
-                        }
-                        return null;
-                    }
-                },
-                new Function<AssociationDescriptor, Map<String, EntityReference>>()
-                {
-                    @Override
-                    public Map<String, EntityReference> map( AssociationDescriptor descriptor )
-                    {
-                        if( "namedAss".equals( descriptor.qualifiedName().name() ) )
-                        {
-                            return Collections.singletonMap(
-                                "foo",
-                                EntityReference.parseEntityReference( associatedIdentity )
-                            );
-                        }
-                        return null;
-                    }
-                }
-            ).newInstance();
-            assertThat( entity.prop().get(), equalTo( "Foo" ) );
-            assertThat( entity.ass().get().identity().get(), equalTo( associatedIdentity ) );
-            assertThat( entity.manyAss().get( 0 ).identity().get(), equalTo( associatedIdentity ) );
-            assertThat( entity.namedAss().get( "foo" ).identity().get(), equalTo( associatedIdentity ) );
-            uow.complete();
-        }
-    }
-
-    public interface SomeEntity
-        extends Identity
-    {
-        Property<String> prop();
-
-        @Optional
-        Association<SomeEntity> ass();
-
-        @Optional
-        ManyAssociation<SomeEntity> manyAss();
-
-        @Optional
-        NamedAssociation<SomeEntity> namedAss();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityCompositeEqualityTest.java b/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityCompositeEqualityTest.java
deleted file mode 100644
index 354e5d0..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityCompositeEqualityTest.java
+++ /dev/null
@@ -1,91 +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.qi4j.runtime.entity;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-/**
- * Testing of equality of entity composites.
- */
-public class EntityCompositeEqualityTest
-    extends AbstractQi4jTest
-{
-    private UnitOfWork unitOfWork;
-    private EntityBuilder<MyComposite> myCompositeBuilder;
-
-    @Before
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        unitOfWork = this.module.newUnitOfWork();
-        myCompositeBuilder = unitOfWork.newEntityBuilder( MyComposite.class );
-    }
-
-    @After
-    public void completeUnitOfWork()
-        throws Exception
-    {
-        unitOfWork.complete();
-        super.tearDown();
-    }
-
-    @Test
-    public void shouldNotBeEqualToNull()
-        throws UnitOfWorkCompletionException
-    {
-        MyComposite simpleComposite = myCompositeBuilder.newInstance();
-        assertThat( "simpleComposite is not equal to null", simpleComposite.equals( null ), equalTo( false ) );
-    }
-
-    @Test
-    public void shouldBeEqualToItself()
-    {
-        MyComposite simpleComposite = myCompositeBuilder.newInstance();
-        assertThat( "simple composite is equal to itself", simpleComposite.equals( simpleComposite ), equalTo( true ) );
-    }
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().visibleIn( Visibility.layer ).assemble( module );
-        module.objects( EntityCompositeEqualityTest.class );
-        module.entities( MyComposite.class );
-    }
-
-    private static interface MyComposite
-        extends EntityComposite
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityCreationTest.java b/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityCreationTest.java
deleted file mode 100755
index 12bf605..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityCreationTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.entity;
-
-import org.junit.Test;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.Lifecycle;
-import org.qi4j.api.entity.LifecycleException;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-/**
- * Test case for http://team.ops4j.org/browse/QI-274
- */
-public class EntityCreationTest
-        extends AbstractQi4jTest
-{
-
-    @Mixins( SomeEntityMixin.class )
-    public interface SomeEntity
-            extends EntityComposite, Lifecycle
-    {
-
-        @Immutable
-        public Property<String> someProperty();
-
-    }
-
-    public static class SomeEntityMixin
-            implements Lifecycle
-    {
-
-        @This
-        private SomeEntity _me;
-
-        @Override
-        public void create()
-                throws LifecycleException
-        {
-            this._me.someProperty().set( "SomeValue" );
-        }
-
-        @Override
-        public void remove()
-                throws LifecycleException
-        {
-        }
-
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-            throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.entities( SomeEntity.class );
-    }
-
-    @Test
-    public void doTestUseUowNewEntity()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        SomeEntity entity = uow.newEntity( SomeEntity.class );
-        uow.discard();
-    }
-
-    @Test
-    public void doTestUseEntityBuilder()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        EntityBuilder<SomeEntity> builder = uow.newEntityBuilder( SomeEntity.class );
-        SomeEntity entity = builder.newInstance();
-        uow.discard();
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityTypeTest.java b/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityTypeTest.java
deleted file mode 100644
index 47ae593..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityTypeTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.entity;
-
-import org.junit.Test;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-public class EntityTypeTest
-    extends AbstractQi4jTest
-{
-    @Test
-    public void givenSubclassedEntityWhenRequestingSuperclassExpectResolutionToWork()
-        throws Exception
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            EntityBuilder<Rst> builder3 = uow.newEntityBuilder( Rst.class, "123" );
-            EntityBuilder<Def> builder2 = uow.newEntityBuilder( Def.class, "456" );
-            EntityBuilder<Abc> builder1 = uow.newEntityBuilder( Abc.class, "789" );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( Rst.class );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    public interface Abc
-        extends EntityComposite
-    {
-    }
-
-    public interface Def
-        extends Abc
-    {
-    }
-
-    public interface Rst
-        extends Def, EntityComposite
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityVisibilityTest.java b/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityVisibilityTest.java
deleted file mode 100644
index c10cf92..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/entity/EntityVisibilityTest.java
+++ /dev/null
@@ -1,1013 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.entity;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.EntityTypeNotFoundException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.ApplicationAssemblerAdapter;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-
-public class EntityVisibilityTest
-{
-
-    private Energy4Java qi4j;
-    private Module module;
-    private Application app;
-
-    @Before
-    public void setup()
-        throws Exception
-    {
-        qi4j = new Energy4Java();
-
-        Assembler[][][] assemblers = new Assembler[][][]
-            {
-                { // Layer Above
-                  {
-                      new AboveAssembler()
-                  }
-                },
-                { // Layer From
-                  { // From Module
-                    new FromAssembler(),
-                  },
-                  { // Beside Module
-                    new BesideAssembler()
-                  }
-                },
-                { // Layer Below
-                  {
-                      new BelowAssembler()
-                  }
-                }
-            };
-        app = qi4j.newApplication( new ApplicationAssemblerAdapter( assemblers )
-        {
-        } );
-        app.activate();
-        module = app.findModule( "From Layer", "From" );
-    }
-
-    @After
-    public void tearDown()
-        throws Exception
-    {
-        app.passivate();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.besideLayerVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromServiceWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.belowApplicationVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromServiceWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.belowLayerVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromServiceWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.belowModuleVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromServiceWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.aboveApplicationVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromServiceWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.aboveLayerVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromServiceWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.aboveModuleVisible();
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.moduleApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.moduleLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.moduleModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.besideApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.besideLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromEntityWhenAccessingBesideModuleVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.besideModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.belowApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromEntityWhenAccessingBelowLayerVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.belowLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromEntityWhenAccessingBelowModuleVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.belowModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromEntityWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.aboveApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromEntityWhenAccessingAboveLayerVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.aboveLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromEntityWhenAccessingAboveModuleVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.aboveModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.besideLayerVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromValueWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.belowApplicationVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromValueWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.belowLayerVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromValueWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.belowModuleVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromValueWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.aboveApplicationVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromValueWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.aboveLayerVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromValueWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.aboveModuleVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.besideLayerVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromTransientWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.belowApplicationVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromTransientWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.belowLayerVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromTransientWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.belowModuleVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromTransientWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.aboveApplicationVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromTransientWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.aboveLayerVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromTransientWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.aboveModuleVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.besideLayerVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromObjectWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.belowApplicationVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromObjectWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.belowLayerVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromObjectWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.belowModuleVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromObjectWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.aboveApplicationVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromObjectWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.aboveLayerVisible();
-    }
-
-    @Test( expected = EntityTypeNotFoundException.class )
-    public void givenFromObjectWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.aboveModuleVisible();
-    }
-
-    private static class FromAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.layer().setName( "From Layer" );
-            module.setName( "From" );
-            module.services( FromService.class );
-            module.entities( FromEntity.class );
-            module.transients( FromTransient.class );
-            module.values( FromValue.class );
-            module.objects( FromObject.class );
-
-            module.entities( ModuleApplicationVisible.class ).visibleIn( Visibility.application );
-            module.entities( ModuleLayerVisible.class ).visibleIn( Visibility.layer );
-            module.entities( ModuleModuleVisible.class ).visibleIn( Visibility.module );
-        }
-    }
-
-    private static class BelowAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.layer().setName( "Below Layer" );
-            module.setName( "Below" );
-            module.entities( BelowApplicationVisible.class ).visibleIn( Visibility.application );
-            module.entities( BelowLayerVisible.class ).visibleIn( Visibility.layer );
-            module.entities( BelowModuleVisible.class ).visibleIn( Visibility.module );
-
-            new EntityTestAssembler().visibleIn( Visibility.application ).assemble( module );
-        }
-    }
-
-    private static class AboveAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.layer().setName( "Above Layer" );
-            module.setName( "Above" );
-            module.entities( AboveApplicationVisible.class ).visibleIn( Visibility.application );
-            module.entities( AboveLayerVisible.class ).visibleIn( Visibility.layer );
-            module.entities( AboveModuleVisible.class ).visibleIn( Visibility.module );
-        }
-    }
-
-    private static class BesideAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.setName( "Beside" );
-            module.entities( BesideApplicationVisible.class ).visibleIn( Visibility.application );
-            module.entities( BesideLayerVisible.class ).visibleIn( Visibility.layer );
-            module.entities( BesideModuleVisible.class ).visibleIn( Visibility.module );
-        }
-    }
-
-    @Mixins( Mixin.class )
-    public interface From
-    {
-        void moduleApplicationVisible();
-
-        void moduleLayerVisible();
-
-        void moduleModuleVisible();
-
-        void besideApplicationVisible();
-
-        void besideLayerVisible();
-
-        void besideModuleVisible();
-
-        void belowApplicationVisible();
-
-        void belowLayerVisible();
-
-        void belowModuleVisible();
-
-        void aboveApplicationVisible();
-
-        void aboveLayerVisible();
-
-        void aboveModuleVisible();
-    }
-
-    public interface FromValue extends From, ValueComposite
-    {
-    }
-
-    public interface FromEntity extends From, EntityComposite
-    {
-    }
-
-    public interface FromService extends From, ServiceComposite
-    {
-    }
-
-    public interface FromTransient extends From, TransientComposite
-    {
-    }
-
-    public static class FromObject extends Mixin
-    {
-    }
-
-    public abstract static class Mixin
-        implements From
-    {
-        @Structure
-        private Module module;
-
-        @Override
-        public void moduleApplicationVisible()
-        {
-            UnitOfWork uow = module.newUnitOfWork();
-            try
-            {
-                ModuleApplicationVisible entity = uow.newEntity( ModuleApplicationVisible.class );
-            }
-            finally
-            {
-                if( uow.isOpen() )
-                {
-                    uow.discard();
-                }
-            }
-        }
-
-        @Override
-        public void moduleLayerVisible()
-        {
-            UnitOfWork uow = module.newUnitOfWork();
-            try
-            {
-                ModuleLayerVisible entity = uow.newEntity( ModuleLayerVisible.class );
-            }
-            finally
-            {
-                if( uow.isOpen() )
-                {
-                    uow.discard();
-                }
-            }
-        }
-
-        @Override
-        public void moduleModuleVisible()
-        {
-            UnitOfWork uow = module.newUnitOfWork();
-            try
-            {
-                ModuleModuleVisible entity = uow.newEntity( ModuleModuleVisible.class );
-            }
-            finally
-            {
-                if( uow.isOpen() )
-                {
-                    uow.discard();
-                }
-            }
-        }
-
-        @Override
-        public void besideApplicationVisible()
-        {
-            UnitOfWork uow = module.newUnitOfWork();
-            try
-            {
-                BesideApplicationVisible entity = uow.newEntity( BesideApplicationVisible.class );
-            }
-            finally
-            {
-                if( uow.isOpen() )
-                {
-                    uow.discard();
-                }
-            }
-        }
-
-        @Override
-        public void besideLayerVisible()
-        {
-            UnitOfWork uow = module.newUnitOfWork();
-            try
-            {
-                BesideLayerVisible entity = uow.newEntity( BesideLayerVisible.class );
-            }
-            finally
-            {
-                if( uow.isOpen() )
-                {
-                    uow.discard();
-                }
-            }
-        }
-
-        @Override
-        public void besideModuleVisible()
-        {
-            UnitOfWork uow = module.newUnitOfWork();
-            try
-            {
-                BesideModuleVisible entity = uow.newEntity( BesideModuleVisible.class );
-            }
-            finally
-            {
-                if( uow.isOpen() )
-                {
-                    uow.discard();
-                }
-            }
-        }
-
-        @Override
-        public void belowApplicationVisible()
-        {
-            UnitOfWork uow = module.newUnitOfWork();
-            try
-            {
-                BelowApplicationVisible entity = uow.newEntity( BelowApplicationVisible.class );
-            }
-            finally
-            {
-                if( uow.isOpen() )
-                {
-                    uow.discard();
-                }
-            }
-        }
-
-        @Override
-        public void belowLayerVisible()
-        {
-            UnitOfWork uow = module.newUnitOfWork();
-            try
-            {
-                BelowLayerVisible entity = uow.newEntity( BelowLayerVisible.class );
-            }
-            finally
-            {
-                if( uow.isOpen() )
-                {
-                    uow.discard();
-                }
-            }
-        }
-
-        @Override
-        public void belowModuleVisible()
-        {
-            UnitOfWork uow = module.newUnitOfWork();
-            try
-            {
-                BelowModuleVisible entity = uow.newEntity( BelowModuleVisible.class );
-            }
-            finally
-            {
-                if( uow.isOpen() )
-                {
-                    uow.discard();
-                }
-            }
-        }
-
-        @Override
-        public void aboveApplicationVisible()
-        {
-            UnitOfWork uow = module.newUnitOfWork();
-            try
-            {
-                AboveApplicationVisible entity = uow.newEntity( AboveApplicationVisible.class );
-            }
-            finally
-            {
-                if( uow.isOpen() )
-                {
-                    uow.discard();
-                }
-            }
-        }
-
-        @Override
-        public void aboveLayerVisible()
-        {
-            UnitOfWork uow = module.newUnitOfWork();
-            try
-            {
-                AboveLayerVisible entity = uow.newEntity( AboveLayerVisible.class );
-            }
-            finally
-            {
-                if( uow.isOpen() )
-                {
-                    uow.discard();
-                }
-            }
-        }
-
-        @Override
-        public void aboveModuleVisible()
-        {
-            UnitOfWork uow = module.newUnitOfWork();
-            try
-            {
-                AboveModuleVisible entity = uow.newEntity( AboveModuleVisible.class );
-            }
-            finally
-            {
-                if( uow.isOpen() )
-                {
-                    uow.discard();
-                }
-            }
-        }
-    }
-
-    public interface ModuleApplicationVisible extends EntityComposite
-    {
-    }
-
-    public interface ModuleLayerVisible extends EntityComposite
-    {
-    }
-
-    public interface ModuleModuleVisible extends EntityComposite
-    {
-    }
-
-    public interface BesideApplicationVisible extends EntityComposite
-    {
-    }
-
-    public interface BesideLayerVisible extends EntityComposite
-    {
-    }
-
-    public interface BesideModuleVisible extends EntityComposite
-    {
-    }
-
-    public interface BelowApplicationVisible extends EntityComposite
-    {
-    }
-
-    public interface BelowLayerVisible extends EntityComposite
-    {
-    }
-
-    public interface BelowModuleVisible extends EntityComposite
-    {
-    }
-
-    public interface AboveApplicationVisible extends EntityComposite
-    {
-    }
-
-    public interface AboveLayerVisible extends EntityComposite
-    {
-    }
-
-    public interface AboveModuleVisible extends EntityComposite
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/entity/LifecycleTest.java b/core/runtime/src/test/java/org/qi4j/runtime/entity/LifecycleTest.java
deleted file mode 100644
index 2cc77a8..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/entity/LifecycleTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman.
- *
- * Licensed 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.qi4j.runtime.entity;
-
-import org.hamcrest.CoreMatchers;
-import org.junit.Test;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.Lifecycle;
-import org.qi4j.api.entity.LifecycleException;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.assertThat;
-
-/**
- * Test for the Lifecycle interface
- */
-public class LifecycleTest
-    extends AbstractQi4jTest
-{
-    public static boolean create;
-    public static boolean remove;
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.entities( TestEntity.class );
-    }
-
-    @Test
-    public void whenEntityHasLifecycleWhenInstantiatedThenInvokeCreate()
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class );
-            builder.newInstance();
-            unitOfWork.complete();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-
-        assertThat( "Lifecycle.create() was invoked", create, CoreMatchers.equalTo( true ) );
-    }
-
-    @Test
-    public void whenEntityHasLifecycleWhenRemovedThenInvokeRemove()
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class );
-            TestEntity testEntity = builder.newInstance();
-            unitOfWork.remove( testEntity );
-            unitOfWork.complete();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-
-        assertThat( "Lifecycle.remove() was invoked", remove, CoreMatchers.equalTo( true ) );
-    }
-
-    public interface Testing
-    {
-        void doSomething();
-    }
-
-    @Mixins( TestMixin.class )
-    public interface TestEntity
-        extends Testing, EntityComposite
-    {
-    }
-
-    public static class TestMixin
-        implements Lifecycle, Testing
-    {
-        public void create()
-            throws LifecycleException
-        {
-            create = true;
-        }
-
-        public void remove()
-            throws LifecycleException
-        {
-            remove = true;
-        }
-
-        public void doSomething()
-        {
-            System.out.println( "Test!" );
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/entity/QI273Test.java b/core/runtime/src/test/java/org/qi4j/runtime/entity/QI273Test.java
deleted file mode 100644
index d787827..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/entity/QI273Test.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.entity;
-
-import org.junit.Test;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-/**
- * @author Stanislav Muhametsin
- */
-public class QI273Test
-    extends AbstractQi4jTest
-{
-
-    public static interface RoleA
-    {
-        public Property<String> theProperty();
-    }
-
-    public static interface RoleB
-    {
-        public Property<String> theProperty();
-    }
-
-    @Mixins( SomeDomainEntityMixin.class )
-    public static interface SomeDomainEntity
-        extends EntityComposite
-    {
-        public String getRoleAProperty();
-
-        public String getRoleBProperty();
-    }
-
-    public static abstract class SomeDomainEntityMixin
-        implements SomeDomainEntity
-    {
-        @This
-        private RoleA _a;
-        @This
-        private RoleB _b;
-
-        public String getRoleAProperty()
-        {
-            return this._a.theProperty().get();
-        }
-
-        public String getRoleBProperty()
-        {
-            return this._b.theProperty().get();
-        }
-    }
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.entities( SomeDomainEntity.class );
-    }
-
-    @Test
-    public void doTest()
-        throws Exception
-    {
-/*
-        UnitOfWork uow = this.module.newUnitOfWork();
-
-        EntityBuilder<SomeDomainEntity> builder = uow.newEntityBuilder( SomeDomainEntity.class );
-        builder.instanceFor( RoleA.class ).theProperty().set( "a" );
-        builder.instanceFor( RoleB.class ).theProperty().set( "b" );
-        SomeDomainEntity entity = builder.newInstance();
-
-        Assert.assertEquals( "Property must be same as set.", "a", entity.getRoleAProperty() );
-        Assert.assertEquals( "Property must be same as set.", "b", entity.getRoleBProperty() );
-
-        uow.complete();
-*/
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/entity/associations/AssociationTest.java b/core/runtime/src/test/java/org/qi4j/runtime/entity/associations/AssociationTest.java
deleted file mode 100644
index ac321c9..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/entity/associations/AssociationTest.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.entity.associations;
-
-import java.io.Serializable;
-import javax.swing.Icon;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-/**
- * Tests for associations
- */
-public class AssociationTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.entities( AssociationTest.Person.class,
-                         AssociationTest.Company.class );
-        module.forMixin( Employer.class )
-            .setMetaInfo( new DisplayInfo( "Employees", "Employees in the company", "Employees", null ) )
-            .declareDefaults()
-            .employees();
-        module.forMixin( Company.class ).declareDefaults().name().set( "A Company" );
-    }
-
-    @Test
-    public void testAssociation()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-
-        try
-        {
-            Company company = unitOfWork.newEntity( Company.class );
-            Assert.assertEquals( "Company Name Default", "A Company", company.name().get() );
-
-            {
-                EntityBuilder<Company> builder = unitOfWork.newEntityBuilder( Company.class );
-                final Company companyPrototype = builder.instance();
-                companyPrototype.name().set( "JayWay" );
-                company = builder.newInstance();
-                Assert.assertEquals( "Company Name ", "JayWay", company.name().get() );
-            }
-
-            company.name().set( "Jayway" );
-            Assert.assertEquals( "Company Name ", "Jayway", company.name().get() );
-
-            System.out.println( "Name is:" + company.name().get() );
-
-            EntityBuilder<Person> builder = unitOfWork.newEntityBuilder( Person.class );
-            builder.instance().name().set( "Rickard" );
-            Person rickard = builder.newInstance();
-
-            builder = unitOfWork.newEntityBuilder( Person.class );
-            builder.instance().name().set( "Niclas" );
-            builder.instance().friend().set( rickard );
-            Person niclas = builder.newInstance();
-
-            niclas.members().add( rickard );
-
-            company.employees().add( 0, rickard );
-
-            for( Employer employer : rickard.employers() )
-            {
-                System.out.println( ( (Nameable) employer ).name() );
-            }
-
-            Assert.assertEquals( niclas.friend().get(), rickard );
-            Assert.assertEquals( niclas.members().get( 0 ), rickard );
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    public interface Friend<T>
-    {
-        @Optional
-        Association<T> friend();
-    }
-
-    public interface Team<T>
-    {
-        ManyAssociation<T> members();
-    }
-
-    public interface Company
-        extends AssociationTest.Nameable,
-                AssociationTest.Employer,
-                AssociationTest.StandardComposite,
-                EntityComposite
-    {
-    }
-
-    public interface Person
-        extends AssociationTest.Nameable,
-                AssociationTest.Employee,
-                AssociationTest.Friend<Person>,
-                AssociationTest.Team<Person>,
-                AssociationTest.StandardComposite,
-                EntityComposite
-    {
-    }
-
-    public interface StandardComposite
-    {
-    }
-
-    public interface Nameable
-    {
-        Property<String> name();
-    }
-
-    public interface Employer
-    {
-        ManyAssociation<Employee> employees();
-    }
-
-    public interface Employee
-    {
-        ManyAssociation<AssociationTest.Employer> employers();
-    }
-
-    public static class DisplayInfo
-        implements Serializable
-    {
-        private String name;
-        private String description;
-        private String toolTip;
-        private Icon icon;
-
-        public DisplayInfo( String name, String description, String toolTip )
-        {
-            this.name = name;
-            this.description = description;
-            this.toolTip = toolTip;
-        }
-
-        public DisplayInfo( String name, String description, String toolTip, Icon icon )
-        {
-            this.name = name;
-            this.description = description;
-            this.toolTip = toolTip;
-            this.icon = icon;
-        }
-
-        public String getName()
-        {
-            return name;
-        }
-
-        public String getDescription()
-        {
-            return description;
-        }
-
-        public String getToolTip()
-        {
-            return toolTip;
-        }
-
-        public Icon getIcon()
-        {
-            return icon;
-        }
-    }
-
-    public static class RdfInfo
-        implements Serializable
-    {
-        private String predicate;
-        private String namespace;
-
-        public RdfInfo( String predicate, String namespace )
-        {
-            this.predicate = predicate;
-            this.namespace = namespace;
-        }
-
-        public String getPredicate()
-        {
-            return predicate;
-        }
-
-        public String getNamespace()
-        {
-            return namespace;
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/entity/associations/ImmutableAssociationTest.java b/core/runtime/src/test/java/org/qi4j/runtime/entity/associations/ImmutableAssociationTest.java
deleted file mode 100644
index 02c3144..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/entity/associations/ImmutableAssociationTest.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.entity.associations;
-
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-/**
- * Test that associations can be marked as @Immutable
- */
-public class ImmutableAssociationTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.entities( PersonEntity.class );
-    }
-
-    @Test
-    public void givenEntityWithImmutableAssociationWhenBuildingThenNoException()
-        throws Exception
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            PersonEntity father = unitOfWork.newEntity( PersonEntity.class );
-
-            EntityBuilder<PersonEntity> builder = unitOfWork.newEntityBuilder( PersonEntity.class );
-            PersonEntity instance = builder.instance();
-            instance.father().set( father );
-            PersonEntity child = builder.newInstance();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    @Test( expected = IllegalStateException.class )
-    public void givenEntityWithImmutableAssociationWhenChangingValueThenThrowException()
-        throws Exception
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            EntityBuilder<PersonEntity> builder = unitOfWork.newEntityBuilder( PersonEntity.class );
-            PersonEntity father = builder.instance();
-            father = builder.newInstance();
-
-            builder = unitOfWork.newEntityBuilder( PersonEntity.class );
-            PersonEntity child = builder.instance();
-            child = builder.newInstance();
-
-            child.father().set( father );
-
-            unitOfWork.complete();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    @Test
-    public void givenEntityWithImmutableManyAssociationWhenBuildingThenNoException()
-        throws Exception
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            EntityBuilder<PersonEntity> builder = unitOfWork.newEntityBuilder( PersonEntity.class );
-            PersonEntity person1 = builder.instance();
-            person1 = builder.newInstance();
-
-            builder = unitOfWork.newEntityBuilder( PersonEntity.class );
-            PersonEntity person2 = builder.instance();
-            person2.colleagues().add( 0, person1 );
-            person2 = builder.newInstance();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    @Test( expected = IllegalStateException.class )
-    public void givenEntityWithImmutableManyAssociationWhenChangingValueThenThrowException()
-        throws Exception
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            EntityBuilder<PersonEntity> builder = unitOfWork.newEntityBuilder( PersonEntity.class );
-            PersonEntity person1 = builder.instance();
-            person1 = builder.newInstance();
-
-            builder = unitOfWork.newEntityBuilder( PersonEntity.class );
-            PersonEntity person2 = builder.instance();
-            person2 = builder.newInstance();
-
-            person1.colleagues().add( 0, person2 );
-
-            unitOfWork.complete();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    interface PersonEntity
-        extends EntityComposite
-    {
-        @Optional
-        @Immutable
-        Association<PersonEntity> father();
-
-        @Immutable
-        ManyAssociation<PersonEntity> children();
-
-        @Immutable
-        ManyAssociation<PersonEntity> friends();
-
-        @Immutable
-        ManyAssociation<PersonEntity> colleagues();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/injection/ActivatorInjectionTest.java b/core/runtime/src/test/java/org/qi4j/runtime/injection/ActivatorInjectionTest.java
deleted file mode 100644
index 6eb036f..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/injection/ActivatorInjectionTest.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.runtime.injection;
-
-import org.junit.Test;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Layer;
-import org.qi4j.api.structure.Module;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertThat;
-
-/**
- * Assert that injections on Activators works.
- */
-public class ActivatorInjectionTest
-    extends AbstractQi4jTest
-{
-
-    @Mixins( MixinA.class )
-    public interface ServiceA
-    {
-        String what();
-    }
-
-    public static class MixinA
-        implements ServiceA
-    {
-
-        @Override
-        public String what()
-        {
-            return "A";
-        }
-
-    }
-
-    @Mixins( MixinB.class )
-    public interface ServiceB
-    {
-        String what();
-    }
-
-    public static class MixinB
-        implements ServiceB
-    {
-
-        @Override
-        public String what()
-        {
-            return "B";
-        }
-
-    }
-
-    public static class Foo
-    {
-        public String bar()
-        {
-            return "BAZAR";
-        }
-    }
-
-    public static class ServiceAActivator
-        extends ActivatorAdapter<ServiceReference<ServiceA>>
-    {
-        @Structure
-        private Application application;
-        @Structure
-        private Layer layer;
-        @Structure
-        private Module module;
-        @Service
-        private ServiceReference<ServiceB> serviceRefB;
-        @Service
-        private ServiceB serviceB;
-
-        @Override
-        public void afterActivation( ServiceReference<ServiceA> activatee )
-            throws Exception
-        {
-            assertThat( application, notNullValue() );
-            assertThat( layer, notNullValue() );
-            assertThat( module, notNullValue() );
-            assertThat( serviceRefB.isActive(), is( false ) );
-            assertThat( serviceB, notNullValue() );
-            assertThat( serviceB.what(), equalTo( "B" ) );
-        }
-    }
-
-    public static class ServiceBActivator
-        extends ActivatorAdapter<ServiceReference<ServiceB>>
-    {
-        @Structure
-        private Application application;
-        @Structure
-        private Layer layer;
-        @Structure
-        private Module module;
-        @Uses
-        private Foo foo;
-
-        @Override
-        public void afterActivation( ServiceReference<ServiceB> activatee )
-            throws Exception
-        {
-            assertThat( application, notNullValue() );
-            assertThat( layer, notNullValue() );
-            assertThat( module, notNullValue() );
-            assertThat( foo.bar(), equalTo( "BAZAR" ) );
-        }
-    }
-
-    public static class ModuleActivator
-        extends ActivatorAdapter<Module>
-    {
-
-        @Override
-        public void afterActivation( Module activatee )
-            throws Exception
-        {
-            // No injection support in Structure Activators
-            assertThat( activatee, notNullValue() );
-        }
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.withActivators( ModuleActivator.class );
-        module.objects( Foo.class );
-        module.services( ServiceA.class ).withActivators( ServiceAActivator.class ).instantiateOnStartup();
-        module.services( ServiceB.class ).withActivators( ServiceBActivator.class ).instantiateOnStartup();
-    }
-
-    @Test
-    public void test()
-    {
-        assertThat( module.findService( ServiceA.class ).get().what(), equalTo( "A" ) );
-        assertThat( module.findService( ServiceB.class ).get().what(), equalTo( "B" ) );
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/injection/ConstructorInjectionOfThisTest.java b/core/runtime/src/test/java/org/qi4j/runtime/injection/ConstructorInjectionOfThisTest.java
deleted file mode 100644
index c28e332..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/injection/ConstructorInjectionOfThisTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.mixin.NoopMixin;
-import org.qi4j.api.sideeffect.SideEffectOf;
-import org.qi4j.api.structure.Module;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-/**
- * This test is created in response to QI-359
- */
-public class ConstructorInjectionOfThisTest
-{
-
-    @Test
-    public void givenConcernWithThisInConstructorWhenCreatingModelExpectException()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler singletonAssembler = new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.values( Does.class ).withConcerns( DoesConcern.class );
-            }
-        };
-        Module module = singletonAssembler.application().findModule( "Layer 1", "Module 1" );
-        Does does = module.newValue( Does.class );
-        does.doSomething();
-    }
-
-    @Test
-    public void givenSideEffectWithThisInConstructorWhenCreatingModelExpectException()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler singletonAssembler = new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.values( Does.class ).withSideEffects( DoesSideEffect.class );
-            }
-        };
-        Module module = singletonAssembler.application().findModule( "Layer 1", "Module 1" );
-        Does does = module.newValue( Does.class );
-        does.doSomething();
-    }
-
-    public static class DoesConcern extends ConcernOf<Does>
-        implements Does
-    {
-
-        public DoesConcern( @This Does work )
-        {
-            if( work == null )
-            {
-                throw new NullPointerException();
-            }
-            System.out.print( "Niclas " );
-        }
-
-        @Override
-        public void doSomething()
-        {
-            next.doSomething();
-        }
-    }
-
-    public static class DoesSideEffect extends SideEffectOf<Does>
-        implements Does
-    {
-
-        public DoesSideEffect( @This Does work )
-        {
-            if( work == null )
-            {
-                throw new NullPointerException();
-            }
-            System.out.print( "Niclas " );
-        }
-
-        @Override
-        public void doSomething()
-        {
-            this.result.doSomething();
-        }
-    }
-
-    @Mixins( NoopMixin.class )
-    public interface Does
-    {
-        void doSomething();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/injection/IllegalUnitOfWorkInjectionTest.java b/core/runtime/src/test/java/org/qi4j/runtime/injection/IllegalUnitOfWorkInjectionTest.java
deleted file mode 100644
index 8edf684..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/injection/IllegalUnitOfWorkInjectionTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.injection;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.State;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.fail;
-
-public class IllegalUnitOfWorkInjectionTest
-    extends AbstractQi4jTest
-{
-    private boolean failed = false;
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TrialTransient.class );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Override
-    protected void assemblyException( AssemblyException exception )
-        throws AssemblyException
-    {
-        failed = true;
-    }
-
-    @Test
-    public void givenTransientCompositeWhenInjectingUnitOfWorkThenExpectAnInjectionException()
-        throws Exception
-    {
-        if( !failed )
-        {
-            fail( "Transients should not be allowed to have @State UnitOfWork injections." );
-        }
-    }
-
-    interface Trial
-    {
-        void doSomething();
-
-        String usecaseName();
-    }
-
-    @Mixins( TrialMixin.class )
-    interface TrialTransient
-        extends Trial, TransientComposite
-    {
-    }
-
-    public static class TrialMixin
-        implements Trial
-    {
-        @State
-        private UnitOfWork uow;
-
-        private String uowIdentity;
-
-        public void doSomething()
-        {
-            uowIdentity = uow.usecase().name();
-        }
-
-        public String usecaseName()
-        {
-            return uowIdentity;
-        }
-    }
-}
-
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/injection/InvocationInjectionTest.java b/core/runtime/src/test/java/org/qi4j/runtime/injection/InvocationInjectionTest.java
deleted file mode 100644
index bf5091c..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/injection/InvocationInjectionTest.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import java.lang.annotation.Retention;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Method;
-import org.hamcrest.CoreMatchers;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.injection.scope.Invocation;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-/**
- * Test the @Invocation annotation
- */
-public class InvocationInjectionTest
-{
-    @Test
-    public void whenInvocationInjectionWithMethodWhenInjectedThenInjectMethod()
-        throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( MyComposite.class );
-            }
-        };
-
-        MyComposite composite = assembly.module().newTransient( MyComposite.class );
-
-        composite.doStuff();
-        composite.doStuff();
-        composite.doStuff2();
-        composite.doStuff3();
-    }
-
-    @Mixins( MyMixin.class )
-    @Concerns( MyConcern.class )
-// START SNIPPET: declaration
-    public interface MyComposite
-        extends TransientComposite
-    {
-        @Foo( "1" )
-        void doStuff();
-// END SNIPPET: declaration
-        void doStuff2();
-
-        @Foo( "X" )
-        void doStuff3();
-    }
-
-// START SNIPPET: use1
-    public abstract static class MyConcern
-        extends ConcernOf<MyComposite>
-        implements MyComposite
-    {
-        @Invocation
-        Foo foo;
-// END SNIPPET: use1
-        @Invocation
-        Method method;
-
-        @Invocation
-        AnnotatedElement ae;
-
-        public void doStuff()
-        {
-            Assert.assertThat( "interface has been injected", foo.value(), CoreMatchers.equalTo( "1" ) );
-            Assert.assertThat( "annotations have been injected", ae.getAnnotation( Foo.class )
-                .value(), CoreMatchers.equalTo( "1" ) );
-            Assert.assertThat( "Method has been injected", method.getName(), CoreMatchers.equalTo( "doStuff" ) );
-            next.doStuff();
-        }
-
-        public void doStuff2()
-        {
-            Assert.assertThat( "mixin has been injected", foo.value(), CoreMatchers.equalTo( "2" ) );
-            Assert.assertThat( "annotations have been injected", ae.getAnnotation( Foo.class )
-                .value(), CoreMatchers.equalTo( "2" ) );
-            Assert.assertThat( "Method has been injected", method.getName(), CoreMatchers.equalTo( "doStuff2" ) );
-            next.doStuff2();
-        }
-
-        public void doStuff3()
-        {
-            Assert.assertThat( "mixin has overridden interface", foo.value(), CoreMatchers.equalTo( "3" ) );
-            Assert.assertThat( "annotations have been injected", ae.getAnnotation( Foo.class )
-                .value(), CoreMatchers.equalTo( "3" ) );
-            Assert.assertThat( "Method has been injected", method.getName(), CoreMatchers.equalTo( "doStuff3" ) );
-            next.doStuff3();
-        }
-    }
-
-    public abstract static class MyMixin
-        implements MyComposite
-    {
-        public void doStuff()
-        {
-        }
-
-        @Foo( "2" )
-        public void doStuff2()
-        {
-        }
-
-        @Foo( "3" )
-        public void doStuff3()
-        {
-        }
-    }
-// START SNIPPET: annotation
-    @Retention( RUNTIME )
-    @interface Foo
-    {
-        String value();
-    }
-// END SNIPPET: annotation
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/injection/ServiceInjectionTest.java b/core/runtime/src/test/java/org/qi4j/runtime/injection/ServiceInjectionTest.java
deleted file mode 100644
index 1038b79..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/injection/ServiceInjectionTest.java
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import java.io.Serializable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.common.ConstructionException;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.object.ObjectFactory;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceImporterException;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.service.qualifier.AnnotationQualifier;
-import org.qi4j.api.service.qualifier.IdentifiedBy;
-import org.qi4j.api.service.qualifier.Qualifier;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.functional.Specification;
-
-import static org.junit.Assert.assertEquals;
-import static org.qi4j.api.common.Visibility.application;
-import static org.qi4j.api.common.Visibility.layer;
-
-/**
- * Test the @Service injection annotation
- */
-public class ServiceInjectionTest
-{
-    @Test
-    public void testInjectService()
-        throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.services( MyServiceComposite.class )
-                    .identifiedBy( "Foo" )
-                    .setMetaInfo( new ServiceName( "Foo" ) );
-                module.services( MyServiceComposite2.class )
-                    .identifiedBy( "Bar" )
-                    .setMetaInfo( new ServiceName( "Bar" ) );
-                module.services( StringService.class, LongService.class );
-                module.objects( ServiceUser.class );
-            }
-        };
-
-        testInjection( assembly );
-    }
-
-    private void testInjection( SingletonAssembler assembly )
-    {
-        ObjectFactory factory = assembly.module();
-        ServiceUser user = factory.newObject( ServiceUser.class );
-
-        assertEquals( "X", user.testSingle() );
-        assertEquals( "Foo", user.testIdentity() );
-        assertEquals( "XX", user.testIterable() );
-        assertEquals( "FooX", user.testServiceReference() );
-        assertEquals( "FooXBarX", user.testIterableServiceReferences() );
-        assertEquals( "Bar", user.testQualifier() );
-        assertEquals( "A", user.testStringIterable() );
-        assertEquals( new Long( 1L ), user.testLongIterable() );
-    }
-
-    @Test
-    public void testInjectionServiceBetweenModules()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.services( MyServiceComposite.class )
-                    .identifiedBy( "Foo" )
-                    .setMetaInfo( new ServiceName( "Foo" ) );
-                module.services( StringService.class, LongService.class );
-                module.objects( ServiceUser.class );
-
-                ModuleAssembly module2 = module.layer().module( "Other module" );
-                ServiceDeclaration service2Decl = module2.services( MyServiceComposite.class );
-                service2Decl.identifiedBy( "Bar" ).setMetaInfo( new ServiceName( "Bar" ) ).visibleIn( layer );
-
-                ServiceDeclaration service3Decl = module2.services( MyServiceComposite2.class );
-                service3Decl.identifiedBy( "Boo" ).setMetaInfo( new ServiceName( "Boo" ) );
-            }
-        };
-
-        testInjection( assembly );
-    }
-
-    @Test
-    public void testInjectionServiceBetweenLayers()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.services( MyServiceComposite.class )
-                    .identifiedBy( "Foo" )
-                    .setMetaInfo( new ServiceName( "Foo" ) );
-                module.services( StringService.class, LongService.class );
-                LayerAssembly layerAssembly = module.layer();
-                module.objects( ServiceUser.class );
-
-                ApplicationAssembly applicationAssembly = layerAssembly.application();
-                LayerAssembly layer2Assembly = applicationAssembly.layer( "Other layer" );
-                layerAssembly.uses( layer2Assembly );
-
-                ModuleAssembly module2 = layer2Assembly.module( "Other module" );
-
-                ServiceDeclaration service2Decl = module2.services( MyServiceComposite2.class );
-                service2Decl.identifiedBy( "Bar" ).setMetaInfo( new ServiceName( "Bar" ) ).visibleIn( application );
-            }
-        };
-
-        testInjection( assembly );
-    }
-
-    @Test( expected = ConstructionException.class )
-    public void testMissingServiceDependency()
-        throws ActivationException, AssemblyException
-    {
-        // No service fulfils the dependency injection -> fail to create application
-        new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.objects( ServiceUser.class );
-            }
-        }.module().newObject( ServiceUser.class );
-    }
-
-    @Mixins( MyServiceMixin.class )
-    public static interface MyServiceComposite
-        extends MyService, ServiceComposite
-    {
-    }
-
-    public static interface MyServiceComposite2
-        extends MyServiceComposite
-    {
-    }
-
-    public static interface MyService
-    {
-        String doStuff();
-    }
-
-    public static class MyServiceMixin
-        implements MyService
-    {
-
-        public String doStuff()
-        {
-            return "X";
-        }
-    }
-
-    public static class ServiceUser
-        extends AbstractServiceUser<String>
-    {
-    }
-
-    public static class AbstractServiceUser<T>
-    {
-        @Service
-        MyService service;
-        @Service
-        MyServiceComposite serviceComposite;
-        @Service
-        Iterable<MyService> services;
-        @Service
-        ServiceReference<MyService> serviceRef;
-        @Service
-        Iterable<ServiceReference<MyService>> serviceRefs;
-
-        @Service
-        @IdentifiedBy( "Bar" )
-        ServiceReference<MyService> qualifiedService;
-
-        @Service
-        @IdentifiedBy( "Bar" )
-        Iterable<ServiceReference<MyService>> qualifiedServiceRefs;
-
-        @Optional
-        @Service
-        MyServiceMixin optionalService12;
-
-        @Service
-        Foo<Long> longService;
-
-        @Service
-        Foo<T> stringService;
-
-        public String testSingle()
-        {
-            return service.doStuff();
-        }
-
-        public String testIdentity()
-        {
-            return serviceComposite.identity().get();
-        }
-
-        public String testIterable()
-        {
-            String str = "";
-            for( MyService myService : services )
-            {
-                str += myService.doStuff();
-            }
-            return str;
-        }
-
-        public String testServiceReference()
-            throws ServiceImporterException
-        {
-            ServiceName info = serviceRef.metaInfo( ServiceName.class );
-            return info.getName() + serviceRef.get().doStuff();
-        }
-
-        public String testIterableServiceReferences()
-            throws ServiceImporterException
-        {
-            String str = "";
-            for( ServiceReference<MyService> serviceReference : serviceRefs )
-            {
-                str += serviceReference.metaInfo( ServiceName.class ).getName();
-                str += serviceReference.get().doStuff();
-            }
-            return str;
-        }
-
-        public String testQualifier()
-        {
-            return qualifiedService.metaInfo( ServiceName.class ).getName();
-        }
-
-        public String testQualifiedServices()
-        {
-            String str = "";
-            for( ServiceReference<MyService> qualifiedServiceRef : qualifiedServiceRefs )
-            {
-                str += qualifiedServiceRef.metaInfo( ServiceName.class ).getName();
-            }
-            return str;
-        }
-
-        public T testStringIterable()
-        {
-            return stringService.get();
-        }
-
-        public Long testLongIterable()
-        {
-            return longService.get();
-        }
-    }
-
-    @Qualifier( NamedSelector.class )
-    @Retention( RetentionPolicy.RUNTIME )
-    public @interface Named
-    {
-        public abstract String value();
-    }
-
-    public static final class NamedSelector
-        implements AnnotationQualifier<Named>
-    {
-        public <T> Specification<ServiceReference<?>> qualifier( final Named named )
-        {
-            return new Specification<ServiceReference<?>>()
-            {
-                public boolean satisfiedBy( ServiceReference<?> service )
-                {
-                    ServiceName serviceName = service.metaInfo( ServiceName.class );
-                    return ( serviceName != null && serviceName.getName().equals( named.value() ) );
-                }
-            };
-        }
-    }
-
-    public static class ServiceName
-        implements Serializable
-    {
-        private String name;
-
-        public ServiceName( String name )
-        {
-            this.name = name;
-        }
-
-        public String getName()
-        {
-            return name;
-        }
-    }
-
-    public static interface Foo<T>
-    {
-        T get();
-    }
-
-    @Mixins( StringService.Mixin.class )
-    public static interface StringService
-        extends Foo<String>, ServiceComposite
-    {
-        class Mixin
-            implements Foo<String>
-        {
-            @Override
-            public String get()
-            {
-                return "A";
-            }
-        }
-    }
-
-    @Mixins( LongService.Mixin.class )
-    public static interface LongService
-        extends Foo<Long>, ServiceComposite
-    {
-        class Mixin
-            implements Foo<Long>
-        {
-            @Override
-            public Long get()
-            {
-                return 1L;
-            }
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/injection/StateInjectionTest.java b/core/runtime/src/test/java/org/qi4j/runtime/injection/StateInjectionTest.java
deleted file mode 100644
index 85bcc4d..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/injection/StateInjectionTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import org.junit.Test;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.State;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.StateHolder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test the @State annotation
- */
-public class StateInjectionTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( StateInjectionTest.PropertyFieldInjectionComposite.class );
-    }
-
-    /**
-     * Tests that a mixin is injected into member variables annotated with {@link @PropertyField}.
-     *
-     * @throws Exception re-thrown
-     */
-    @Test
-    public void mixinIsInjectedForMemberVariablesAnnotatedWithPropertyField()
-        throws Exception
-    {
-        TransientBuilder<PropertyFieldInjectionComposite> pficBuilder =
-            module.newTransientBuilder( StateInjectionTest.PropertyFieldInjectionComposite.class );
-        pficBuilder.prototype().testField().set( "X" );
-        PropertyFieldInjectionComposite pfic = pficBuilder.newInstance();
-        assertThat( "Test field", pfic.testField().get(), is( equalTo( "X" ) ) );
-        assertThat( "Named fieldX", pfic.namedField().get(), is( equalTo( "X" ) ) );
-        assertThat( "State", (String) pfic.getState()
-            .propertyFor( PropertyFieldInjectionComposite.class.getMethod( "testField" ) )
-            .get(), is( equalTo( "X" ) ) );
-    }
-
-    @Mixins( PropertyFieldInjectionMixin.class )
-    public interface PropertyFieldInjectionComposite
-        extends TransientComposite
-    {
-        @Optional
-        Property<String> testField();
-
-        @Optional
-        Property<String> namedField();
-
-        StateHolder getState();
-    }
-
-    public abstract static class PropertyFieldInjectionMixin
-        implements PropertyFieldInjectionComposite
-    {
-        @State
-        Property<String> testField;
-
-        @State( "testField" )
-        Property<String> namedField;
-
-        @State
-        StateHolder state;
-
-        public StateHolder getState()
-        {
-            return state;
-        }
-
-        public Property<String> testField()
-        {
-            return testField;
-        }
-
-        public Property<String> namedField()
-        {
-            return namedField;
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/injection/StateParameterInjectionTest.java b/core/runtime/src/test/java/org/qi4j/runtime/injection/StateParameterInjectionTest.java
deleted file mode 100644
index 23e2e18..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/injection/StateParameterInjectionTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.State;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test the @State annotation when used for parameters
- */
-public class StateParameterInjectionTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( PropertyParameterInjectionComposite.class );
-    }
-
-    /**
-     * Tests that a mixin is injected where method parameters are annotated with {@link @PropertyParameter}.
-     *
-     * @throws Exception re-thrown
-     */
-    @Test
-    public void mixinIsInjectedForMethodParametersAnnotatedWithPropertyparameter()
-        throws Exception
-    {
-        TransientBuilder<PropertyParameterInjectionComposite> pficBuilder =
-            module.newTransientBuilder( PropertyParameterInjectionComposite.class );
-        pficBuilder.prototype().testField().set( "X" );
-        pficBuilder.prototype().namedField().set( "Y" );
-        PropertyParameterInjectionComposite pfic = pficBuilder.newInstance();
-        assertThat( "Test field", pfic.testField().get(), is( equalTo( "X" ) ) );
-        assertThat( "Named field", pfic.namedField().get(), is( equalTo( "Y" ) ) );
-    }
-
-    @Mixins( PropertyParameterInjectionMixin.class )
-    public interface PropertyParameterInjectionComposite
-        extends TransientComposite
-    {
-        Property<String> testField();
-
-        Property<String> namedField();
-    }
-
-    public abstract static class PropertyParameterInjectionMixin
-        implements PropertyParameterInjectionComposite
-    {
-        Property<String> testField;
-        Property<String> namedField;
-
-        public PropertyParameterInjectionMixin( @State( "testField" ) Property<String> testField )
-        {
-            this.testField = testField;
-        }
-
-        void init( @State( "namedField" ) Property<String> namedField )
-        {
-            this.namedField = namedField;
-        }
-
-        public Property<String> testField()
-        {
-            return testField;
-        }
-
-        public Property<String> namedField()
-        {
-            return namedField;
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/injection/StructureInjectionTest.java b/core/runtime/src/test/java/org/qi4j/runtime/injection/StructureInjectionTest.java
deleted file mode 100644
index cbc8858..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/injection/StructureInjectionTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import org.junit.Test;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.composite.TransientBuilderFactory;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.object.ObjectFactory;
-import org.qi4j.api.service.ServiceFinder;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.spi.Qi4jSPI;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test the @Structure annotation
- */
-public class StructureInjectionTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( StructureInjectionComposite.class );
-    }
-
-    /**
-     * Tests injected mixin for a CompositeBuilderFactory annotated with {@link @org.qi4j.composite.scope.Structure}.
-     */
-    @Test
-    public void injectedStructureForCompositeBuilderFactory()
-    {
-        StructureInjectionComposite sic = module.newTransient( StructureInjectionComposite.class );
-        assertThat( "Injected CompositeBuilderFactory", sic.getCompositeBuilderFactory(), is( notNullValue() ) );
-    }
-
-    /**
-     * Tests injected mixin for a ObjectBuilderFactory annotated with {@link @org.qi4j.composite.scope.Structure}.
-     */
-    @Test
-    public void injectedStructureForObjectBuilderFactory()
-    {
-        StructureInjectionComposite sic = module.newTransient( StructureInjectionComposite.class );
-        assertThat( "Injected ObjectBuilderFactory", sic.getObjectFactory(), is( notNullValue() ) );
-    }
-
-    /**
-     * Tests injected mixin for a UnitOfWorkFactory annotated with {@link @org.qi4j.composite.scope.Structure}.
-     */
-    @Test
-    public void injectedStructureForUnitOfWorkFactory()
-    {
-        StructureInjectionComposite sic = module.newTransient( StructureInjectionComposite.class );
-        assertThat( "Injected UnitOfWorkFactory", sic.getUnitOfWorkFactory(), is( notNullValue() ) );
-    }
-
-    /**
-     * Tests injected mixin for a ServiceLocator annotated with {@link @org.qi4j.composite.scope.Structure}.
-     */
-    @Test
-    public void injectedStructureForServiceLocator()
-    {
-        StructureInjectionComposite sic = module.newTransient( StructureInjectionComposite.class );
-        assertThat( "Injected ServiceLocator", sic.getServiceLocator(), is( notNullValue() ) );
-    }
-
-    /**
-     * Tests injected mixin for a ModuleBinding annotated with {@link @org.qi4j.composite.scope.Structure}.
-     */
-    @Test
-    public void injectedStructureForModuleBinding()
-    {
-        StructureInjectionComposite sic = module.newTransient( StructureInjectionComposite.class );
-        assertThat( "Injected Module", sic.getModule(), is( notNullValue() ) );
-    }
-
-    /**
-     * Tests injected mixin for a Zest annotated with {@link @org.qi4j.composite.scope.Structure}.
-     */
-    @Test
-    public void injectedStructureForQi4j()
-    {
-        StructureInjectionComposite sic = module.newTransient( StructureInjectionComposite.class );
-        assertThat( "Injected Zest", sic.getQi4j(), is( notNullValue() ) );
-    }
-
-    /**
-     * Tests injected mixin for a Qi4jSpi annotated with {@link @org.qi4j.composite.scope.Structure}.
-     */
-    @Test
-    public void injectedStructureForQi4jSpi()
-    {
-        StructureInjectionComposite sic = module.newTransient( StructureInjectionComposite.class );
-        assertThat( "Injected Qi4jSpi", sic.getQi4jSpi(), is( notNullValue() ) );
-    }
-
-    @Mixins( StructureInjectionMixin.class )
-    public interface StructureInjectionComposite
-        extends TransientComposite
-    {
-        public TransientBuilderFactory getCompositeBuilderFactory();
-
-        public ObjectFactory getObjectFactory();
-
-        public UnitOfWorkFactory getUnitOfWorkFactory();
-
-        public ServiceFinder getServiceLocator();
-
-        public Module getModule();
-
-        public Qi4j getQi4j();
-
-        public Qi4jSPI getQi4jSpi();
-    }
-
-    public abstract static class StructureInjectionMixin
-        implements StructureInjectionComposite
-    {
-        @Structure
-        TransientBuilderFactory compositeBuilderFactory;
-
-        @Structure
-        ObjectFactory objectFactory;
-
-        @Structure
-        UnitOfWorkFactory unitOfWorkFactory;
-
-        @Structure
-        ServiceFinder serviceLocator;
-
-        @Structure
-        Module module;
-
-        @Structure
-        Qi4j qi4j;
-        @Structure
-        Qi4jSPI qi4jSpi;
-
-        public TransientBuilderFactory getCompositeBuilderFactory()
-        {
-            return compositeBuilderFactory;
-        }
-
-        public ObjectFactory getObjectFactory()
-        {
-            return objectFactory;
-        }
-
-        public UnitOfWorkFactory getUnitOfWorkFactory()
-        {
-            return unitOfWorkFactory;
-        }
-
-        public ServiceFinder getServiceLocator()
-        {
-            return serviceLocator;
-        }
-
-        public Module getModule()
-        {
-            return module;
-        }
-
-        public Qi4j getQi4j()
-        {
-            return qi4j;
-        }
-
-        public Qi4jSPI getQi4jSpi()
-        {
-            return qi4jSpi;
-        }
-    }
-}
-
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/injection/ThisInjectionTest.java b/core/runtime/src/test/java/org/qi4j/runtime/injection/ThisInjectionTest.java
deleted file mode 100644
index 2ee2586..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/injection/ThisInjectionTest.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.sideeffect.SideEffectOf;
-import org.qi4j.api.sideeffect.SideEffects;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test the @This annotation
- */
-public class ThisInjectionTest
-    extends AbstractQi4jTest
-{
-    public static boolean sideEffectInjected;
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TestComposite.class );
-    }
-
-    /**
-     * Tests the injected object for {@link @org.qi4j.composite.scope.This} annotation.
-     *
-     * @throws Exception re-thrown
-     */
-    @org.junit.Test
-    public void givenCompositeWithThisInjectionsWhenInstantiatedThenCompositeIsInjected()
-        throws Exception
-    {
-        TestComposite testComposite = module.newTransient( TestComposite.class );
-
-        assertThat( "Injection worked", testComposite.isInjected() && sideEffectInjected, is( equalTo( true ) ) );
-    }
-
-    public interface Test
-    {
-        boolean isInjected();
-
-        String test();
-    }
-
-    public interface TestPrivate
-    {
-        @UseDefaults
-        Property<Boolean> testPrivate();
-    }
-
-    @SideEffects( TestSideEffect.class )
-    @Concerns( TestConcern.class )
-    @Mixins( TestMixin.class )
-    public interface TestComposite
-        extends TransientComposite, Test
-    {
-    }
-
-    public static class TestMixin
-        implements Test
-    {
-        @This
-        Test test;
-
-        @This
-        TestPrivate testPrivate;
-
-        public boolean isInjected()
-        {
-            return test != null && !testPrivate.testPrivate().get();
-        }
-
-        public String test()
-        {
-            return "Foo";
-        }
-    }
-
-    public static abstract class TestConcern
-        extends ConcernOf<Test>
-        implements Test
-    {
-        @This
-        Test test;
-
-        @This
-        TestPrivate testPrivate;
-
-        public boolean isInjected()
-        {
-            return test != null && test.test().equals( "Foo" ) &&
-                   !testPrivate.testPrivate().get() &&
-                   next.isInjected();
-        }
-    }
-
-    public static abstract class TestSideEffect
-        extends SideEffectOf<Test>
-        implements Test
-    {
-        @This
-        Test test;
-        @This
-        TestPrivate testPrivate;
-
-        public boolean isInjected()
-        {
-            sideEffectInjected = test != null && !testPrivate.testPrivate().get();
-
-            return false;
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/injection/UnitOfWorkInjectionTest.java b/core/runtime/src/test/java/org/qi4j/runtime/injection/UnitOfWorkInjectionTest.java
deleted file mode 100644
index 68717f5..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/injection/UnitOfWorkInjectionTest.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.injection;
-
-import org.junit.Test;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.State;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.assertEquals;
-
-public class UnitOfWorkInjectionTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( TrialEntity.class );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Test
-    public void givenEntityInOneUnitOfWorkWhenCurrentUnitOfWorkHasChangedThenUnitOfWorkInjectionInEntityPointsToCorrectUow()
-        throws Exception
-    {
-        Usecase usecase = UsecaseBuilder.newUsecase( "usecase1" );
-        UnitOfWork uow = module.newUnitOfWork( usecase );
-        try
-        {
-            Trial trial = uow.newEntity( Trial.class, "123" );
-            trial.doSomething();
-            uow.complete();
-            uow = module.newUnitOfWork( usecase );
-            usecase = UsecaseBuilder.newUsecase( "usecase2" );
-            UnitOfWork uow2 = module.newUnitOfWork( usecase );
-            trial = uow.get( trial );
-            trial.doSomething();
-            assertEquals( "123", ( (EntityComposite) trial ).identity().get() );
-            assertEquals( "usecase1", trial.usecaseName() );
-            uow2.discard();
-        }
-        catch( Throwable ex )
-        {
-            ex.printStackTrace();
-        }
-        finally
-        {
-            try
-            {
-                while( module.isUnitOfWorkActive() )
-                {
-                    uow = module.currentUnitOfWork();
-                    uow.discard();
-                }
-            }
-            catch( IllegalStateException e )
-            {
-                // Continue
-            }
-        }
-    }
-
-    public interface Trial
-    {
-        void doSomething();
-
-        String usecaseName();
-    }
-
-    @Mixins( TrialMixin.class )
-    public interface TrialEntity
-        extends Trial, EntityComposite
-    {
-    }
-
-    public static class TrialMixin
-        implements Trial
-    {
-        @State
-        private UnitOfWork uow;
-
-        private String uowIdentity;
-
-        public void doSomething()
-        {
-            uowIdentity = uow.usecase().name();
-        }
-
-        public String usecaseName()
-        {
-            return uowIdentity;
-        }
-    }
-}
-
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/injection/UsesGenericClassTest.java b/core/runtime/src/test/java/org/qi4j/runtime/injection/UsesGenericClassTest.java
deleted file mode 100644
index e2798b8..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/injection/UsesGenericClassTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test of generic class injection
- */
-public class UsesGenericClassTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TestCase.class );
-    }
-
-    @Test
-    public void givenMixinUsesGenericClassWhenUseClassThenInjectWorks()
-    {
-        TransientBuilder<TestCase> builder = module.newTransientBuilder( TestCase.class );
-
-        builder.use( UsesGenericClassTest.class );
-
-        TestCase testCase = builder.newInstance();
-        assertThat( "class name is returned", testCase.test(), equalTo( UsesGenericClassTest.class.getName() ) );
-    }
-
-    @Mixins( TestMixin.class )
-    public interface TestCase
-        extends TransientComposite
-    {
-        String test();
-    }
-
-    public abstract static class TestMixin
-        implements TestCase
-    {
-        @Uses
-        Class<? extends TestCase> clazz;
-
-        public String test()
-        {
-            return clazz.getName();
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/injection/UsesGenericListTest.java b/core/runtime/src/test/java/org/qi4j/runtime/injection/UsesGenericListTest.java
deleted file mode 100644
index 6aa591c..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/injection/UsesGenericListTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg.
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.injection;
-
-import java.util.ArrayList;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-/**
- * Test of generic list injection
- */
-public class UsesGenericListTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TestCase.class );
-    }
-
-    @Test
-    public void givenMixinUsesGenericListWhenUseListThenInjectWorks()
-    {
-        TransientBuilder<TestCase> builder = module.newTransientBuilder( TestCase.class );
-
-        ArrayList<String> list = new ArrayList<String>();
-        list.add( "Hello" );
-        list.add( "Bye" );
-        builder.use( list );
-
-        TestCase TestCase = builder.newInstance();
-        TestCase.sayHello();
-    }
-
-    @Mixins( TestMixin.class )
-    public interface TestCase
-        extends TransientComposite
-    {
-        void sayHello();
-    }
-
-    public abstract static class TestMixin
-        implements TestCase
-    {
-        @Uses
-        ArrayList<String> messages;
-
-        public void sayHello()
-        {
-            System.out.println( messages );
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/injection/UsesGraphTest.java b/core/runtime/src/test/java/org/qi4j/runtime/injection/UsesGraphTest.java
deleted file mode 100644
index 855380e..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/injection/UsesGraphTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.not;
-
-/**
- * Test creation of object graph, where @Uses is used to refer to instances
- */
-public class UsesGraphTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.objects( A.class, B.class, C.class, D.class );
-    }
-
-    @Test
-    public void givenGraphDependenciesWhenInstantiateAThenGetSameReferences()
-    {
-        D d = new D();
-        A a = module.newObject( A.class, module.newObject( C.class, d ), d );
-
-        Assert.assertThat( "Same reference expected", a.c, equalTo( a.b.c ) );
-        Assert.assertThat( "Same reference expected", a.d, equalTo( a.b.c.d ) );
-    }
-
-    @Test
-    public void givenGraphDependenciesWhenInstantiateUsingBuildersThenDontGetSameReferences()
-    {
-        A a = module.newObject( A.class );
-        Assert.assertThat( "Same reference not expected", a.c, not( equalTo( a.b.c ) ) );
-        Assert.assertThat( "Same reference not expected", a.d, not( equalTo( a.b.c.d ) ) );
-    }
-
-    static public class A
-    {
-        @Uses
-        B b;
-
-        @Uses
-        C c;
-
-        @Uses
-        D d;
-    }
-
-    static public class B
-    {
-        @Uses
-        C c;
-    }
-
-    static public class C
-    {
-        @Uses
-        D d;
-    }
-
-    static public class D
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/injection/UsesInjectionTest.java b/core/runtime/src/test/java/org/qi4j/runtime/injection/UsesInjectionTest.java
deleted file mode 100644
index 9e827b1..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/injection/UsesInjectionTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.injection;
-
-import org.junit.Test;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test the @Uses annotation
- */
-public class UsesInjectionTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.objects( InjectionTarget.class, ToBeInjected.class );
-    }
-
-    @Test
-    public void givenUsedObjectWhenUseWithBuilderThenInjectReferences()
-        throws Exception
-    {
-        ToBeInjected toBeInjected = new ToBeInjected();
-        assertThat( "Injected object", module.newObject( InjectionTarget.class, toBeInjected, true )
-            .getUsedObject(), is( equalTo( toBeInjected ) ) );
-        assertThat( "Injected boolean", module.newObject( InjectionTarget.class, toBeInjected, true )
-            .isUsedBoolean(), is( equalTo( true ) ) );
-    }
-
-    @Test
-    public void givenUsedObjectBuilderWhenUseWithBuilderThenInjectNewInstance()
-        throws Exception
-    {
-        assertThat( "Injected object", module.newObject( InjectionTarget.class, module.newObject( ToBeInjected.class ), true ), is( notNullValue() ) );
-    }
-
-    @Test
-    public void givenNoUsesWhenBuilderNewInstanceThenInjectNewInstance()
-        throws Exception
-    {
-        assertThat( "Injected object", module.newObject( InjectionTarget.class, true ), is( notNullValue() ) );
-    }
-
-    public static class InjectionTarget
-    {
-        @Uses
-        ToBeInjected usedObject;
-
-        @Uses
-        boolean usedBoolean;
-
-        public ToBeInjected getUsedObject()
-        {
-            return usedObject;
-        }
-
-        public boolean isUsedBoolean()
-        {
-            return usedBoolean;
-        }
-    }
-
-    public static class ToBeInjected
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/instantiation/EagerServiceInstantiationTest.java b/core/runtime/src/test/java/org/qi4j/runtime/instantiation/EagerServiceInstantiationTest.java
deleted file mode 100644
index deec311..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/instantiation/EagerServiceInstantiationTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.runtime.instantiation;
-
-import org.junit.Test;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-
-public class EagerServiceInstantiationTest
-    extends AbstractQi4jTest
-{
-    private TestInfo testInfo;
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        testInfo = new TestInfo();
-        module.services( MyService.class ).setMetaInfo( testInfo ).instantiateOnStartup();
-    }
-
-    @Test
-    public void givenServiceInstantiatedOnStartUpWhenTestIsRunExpectServiceToHaveRun()
-    {
-        assertEquals( "123", testInfo.test );
-    }
-
-    @Mixins( MyMixin.class )
-    public interface MyService
-        extends My, ServiceComposite
-    {
-    }
-
-    public interface My
-    {
-        void doSomething();
-    }
-
-    public static class MyMixin
-        implements My
-    {
-        public MyMixin( @Uses ServiceDescriptor descriptor )
-        {
-            descriptor.metaInfo( TestInfo.class ).test = "123";
-        }
-
-        public MyMixin()
-        {
-            System.out.println( "Constructor" );
-        }
-
-        public void doSomething()
-        {
-            System.out.println( "Execute" );
-        }
-    }
-
-    public class TestInfo
-    {
-        private String test = "abc";
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/instantiation/ServiceInstantiationTests.java b/core/runtime/src/test/java/org/qi4j/runtime/instantiation/ServiceInstantiationTests.java
deleted file mode 100644
index 1ec1c3b..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/instantiation/ServiceInstantiationTests.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.instantiation;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-public class ServiceInstantiationTests
-    extends AbstractQi4jTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( MyConfiguration.class );
-        module.services( My.class );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Test
-    public void whenCreatingServiceCompositeGivenAServiceCompositeThenSucceed()
-        throws Exception
-    {
-        ServiceReference<My> service = module.findService( My.class );
-        Assert.assertEquals( "HabbaZout", service.get().doSomething() );
-    }
-
-    @Mixins( MyMixin.class )
-    public interface My
-    {
-        String doSomething();
-    }
-
-    public interface MyConfiguration
-    {
-        Property<String> data();
-    }
-
-    public static class MyMixin
-        implements My
-    {
-        @This
-        Configuration<MyConfiguration> config;
-
-        @Override
-        public String doSomething()
-        {
-            return config.get().data().get();
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/instantiation/TransientInstantiationTests.java b/core/runtime/src/test/java/org/qi4j/runtime/instantiation/TransientInstantiationTests.java
deleted file mode 100644
index 00a4e8f..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/instantiation/TransientInstantiationTests.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.instantiation;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-public class TransientInstantiationTests
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( MyTransient.class );
-    }
-
-    @Test
-    public void whenCreatingServiceCompositeGivenAServiceCompositeThenSucceed()
-        throws Exception
-    {
-        TransientBuilder<My> builder = module.newTransientBuilder( My.class );
-        My my = builder.newInstance();
-        Assert.assertEquals( "Niclas", my.doSomething() );
-    }
-
-    @Mixins( MyMixin.class )
-    public interface MyTransient
-        extends TransientComposite, My
-    {
-    }
-
-    public interface My
-    {
-        String doSomething();
-    }
-
-    public static class MyMixin
-        implements My
-    {
-
-        public String doSomething()
-        {
-            return "Niclas";
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/instantiation/ValueInstantiationTests.java b/core/runtime/src/test/java/org/qi4j/runtime/instantiation/ValueInstantiationTests.java
deleted file mode 100644
index 2f7afc0..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/instantiation/ValueInstantiationTests.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.instantiation;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.fail;
-
-public class ValueInstantiationTests
-    extends AbstractQi4jTest
-{
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.values( MyValue.class );
-    }
-
-    @Test
-    public void whenTryingToCreateValueFromNullTypeThenExpectNullArgumentException()
-        throws Exception
-    {
-        // valueBuilderFactory.newValueBuilder()
-        try
-        {
-            module.newValueBuilder( null );
-            fail( "NullArgumentException was expected." );
-        }
-        catch( NullArgumentException e )
-        {
-            // expected
-        }
-
-        // valueBuilderFactory.newValue();
-        try
-        {
-            module.newValue( null );
-            fail( "NullArgumentException was expected." );
-        }
-        catch( NullArgumentException e )
-        {
-            // expected
-        }
-
-        //module.newValueFromSerializedState();
-        try
-        {
-            module.newValueFromSerializedState( null, "abc:123" );
-            ValueBuilder<My> builder = module.newValueBuilder( null );
-            fail( "NullArgumentException was expected." );
-        }
-        catch( NullArgumentException e )
-        {
-            // expected
-        }
-    }
-
-    @Test
-    public void whenCreatingServiceCompositeGivenAServiceCompositeThenSucceed()
-        throws Exception
-    {
-        ValueBuilder<My> builder = module.newValueBuilder( My.class );
-        My my = builder.newInstance();
-        Assert.assertEquals( "Niclas", my.doSomething() );
-    }
-
-    @Mixins( MyMixin.class )
-    public interface MyValue
-        extends ValueComposite, My
-    {
-    }
-
-    public interface My
-    {
-        String doSomething();
-    }
-
-    public static class MyMixin
-        implements My
-    {
-
-        public String doSomething()
-        {
-            return "Niclas";
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/mixin/AssemblyMixinTest.java b/core/runtime/src/test/java/org/qi4j/runtime/mixin/AssemblyMixinTest.java
deleted file mode 100644
index 3b875e8..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/mixin/AssemblyMixinTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.mixin;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test of declaring mixin in assembly
- */
-public class AssemblyMixinTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-
-        module.transients( FooComposite.class ).withMixins( CustomFooMixin.class );
-
-        module.entities( FooEntity.class ).withMixins( FooMixin.class );
-    }
-
-    @Test
-    public void testAssemblyMixins()
-    {
-        assertThat( "Custom mixin has executed", module.newTransient( Foo.class )
-            .test( "Foo", 42 ), equalTo( "Foo/42" ) );
-    }
-
-    @Test
-    public void testAssemblyMixinsEntity()
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        FooEntity entity = uow.newEntity( FooEntity.class, "123" );
-        uow.complete();
-
-        uow = module.newUnitOfWork();
-        Foo foo = uow.get( Foo.class, "123" );
-
-        try
-        {
-            assertThat( "Custom mixin has executed", foo.test( "Foo", 42 ), equalTo( "Foo 42" ) );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    public interface FooComposite
-        extends TransientComposite, Foo
-    {
-    }
-
-    public interface Foo
-    {
-        String test( String foo, int bar );
-    }
-
-    public static class FooMixin
-        implements Foo
-    {
-        public String test( String foo, int bar )
-        {
-            return foo + " " + bar;
-        }
-    }
-
-    public static class CustomFooMixin
-        implements Foo
-    {
-        public String test( String foo, int bar )
-        {
-            return foo + "/" + bar;
-        }
-    }
-
-    public interface FooEntity
-        extends EntityComposite, Foo
-    {
-
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/mixin/AssemblyRoleTest.java b/core/runtime/src/test/java/org/qi4j/runtime/mixin/AssemblyRoleTest.java
deleted file mode 100644
index 13cc41e..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/mixin/AssemblyRoleTest.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.mixin;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test of declaring types in assembly
- */
-public class AssemblyRoleTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-
-        module.transients( FooComposite.class ).withTypes( Foo.class );
-        module.transients( FooComposite2.class ).withTypes( Foo.class ).withMixins( CustomFooMixin.class );
-
-        module.entities( FooEntity.class ).withTypes( Foo.class );
-    }
-
-    @Test
-    public void testAssemblyTypesCustomMixin()
-    {
-        FooComposite2 composite2 = module.newTransient( FooComposite2.class );
-        assertThat( "Custom mixin has executed", ( (Foo) composite2 ).test( "Foo", 42 ), equalTo( "Foo/42" ) );
-    }
-
-    @Test
-    public void testAssemblyTypesDefaultMixin()
-    {
-        FooComposite composite = module.newTransient( FooComposite.class );
-        assertThat( "Default mixin has executed", ( (Foo) composite ).test( "Foo", 42 ), equalTo( "Foo 42" ) );
-    }
-
-    @Test
-    public void testAssemblyMixinsEntity()
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        FooEntity entity = uow.newEntity( FooEntity.class, "123" );
-        uow.complete();
-
-        uow = module.newUnitOfWork();
-        Foo foo = uow.get( Foo.class, "123" );
-
-        try
-        {
-            assertThat( "Default mixin has executed", foo.test( "Foo", 42 ), equalTo( "Foo 42" ) );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    public interface FooComposite
-        extends TransientComposite
-    {
-    }
-
-    public interface FooComposite2
-        extends TransientComposite
-    {
-    }
-
-    @Mixins( FooMixin.class )
-    public interface Foo
-    {
-        String test( String foo, int bar );
-    }
-
-    public static class FooMixin
-        implements Foo
-    {
-        public String test( String foo, int bar )
-        {
-            return foo + " " + bar;
-        }
-    }
-
-    public static class CustomFooMixin
-        implements Foo
-    {
-        public String test( String foo, int bar )
-        {
-            return foo + "/" + bar;
-        }
-    }
-
-    public interface FooEntity
-        extends EntityComposite
-    {
-
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/mixin/InitializableTest.java b/core/runtime/src/test/java/org/qi4j/runtime/mixin/InitializableTest.java
deleted file mode 100644
index 5435aa9..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/mixin/InitializableTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.mixin;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Initializable;
-import org.qi4j.api.mixin.InitializationException;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test of Initializable interface
- */
-public class InitializableTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.objects( TestObject.class );
-        module.transients( TestComposite.class );
-    }
-
-    @Test
-    public void givenCompositeWithInitializableMixinWhenInstantiatedThenInvokeInitialize()
-    {
-        TestComposite instance = module.newTransient( TestComposite.class );
-        assertThat( "mixin has been initialized", instance.ok(), equalTo( true ) );
-    }
-
-    @Test
-    public void givenObjectImplementingInitializableWhenInstantiatedThenInvokeInitialize()
-    {
-        TestObject instance = module.newObject( TestObject.class );
-        assertThat( "object has been initialized", instance.ok(), equalTo( true ) );
-    }
-
-    @Mixins( TestMixin.class )
-    public interface TestComposite
-        extends TransientComposite
-    {
-        boolean ok();
-    }
-
-    public abstract static class TestMixin
-        implements TestComposite, Initializable
-    {
-        boolean ok = false;
-
-        public void initialize()
-            throws InitializationException
-        {
-            ok = true;
-        }
-
-        public boolean ok()
-        {
-            return ok;
-        }
-    }
-
-    public static class TestObject
-        implements Initializable
-    {
-        boolean ok = false;
-
-        public void initialize()
-            throws InitializationException
-        {
-            ok = true;
-        }
-
-        public boolean ok()
-        {
-            return ok;
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/mixin/InvokeServiceFromModuleAssemblyTest.java b/core/runtime/src/test/java/org/qi4j/runtime/mixin/InvokeServiceFromModuleAssemblyTest.java
deleted file mode 100644
index 94fb71a..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/mixin/InvokeServiceFromModuleAssemblyTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.mixin;
-
-import org.junit.Test;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.mixin.NoopMixin;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.fail;
-
-/**
- * @author Stanislav Muhametsin
- */
-public class InvokeServiceFromModuleAssemblyTest
-    extends AbstractQi4jTest
-{
-    @Mixins( NoopMixin.class )
-    public interface TestService
-        extends ServiceComposite
-    {
-        public void voidMethod();
-    }
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        try
-        {
-            module.services( TestService.class );
-            module.forMixin( TestService.class ).declareDefaults().voidMethod();
-            fail( "It is not allowed to declareDefaults on methods not returning Property." );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // expected
-        }
-    }
-
-    @Test
-    public void failingAssemblyTest()
-    {
-
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/mixin/JDKMixinTest.java b/core/runtime/src/test/java/org/qi4j/runtime/mixin/JDKMixinTest.java
deleted file mode 100644
index f52a6c6..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/mixin/JDKMixinTest.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.mixin;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.json.JSONObject;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.concern.GenericConcern;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Specification;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.core.IsEqual.*;
-import static org.junit.Assert.*;
-import static org.qi4j.functional.Iterables.*;
-
-/**
- * Assert that JDK classes are usable as Mixins.
- */
-public class JDKMixinTest
-    extends AbstractQi4jTest
-{
-
-    @Concerns( JDKMixinConcern.class )
-    public interface JSONSerializableMap
-        extends Map<String, String>
-    {
-
-        JSONObject toJSON();
-
-    }
-
-    @SuppressWarnings( "serial" )
-    public static class ExtendsJDKMixin
-        extends HashMap<String, String>
-        implements JSONSerializableMap
-    {
-
-        @Override
-        public JSONObject toJSON()
-        {
-            System.out.println( ">>>> Call ExtendsJDKMixin.toJSON()" );
-            // Copy the Map before handing it to JSONObject so that the JSONObject do not use the Composite
-            return new JSONObject( new HashMap<String, String>( this ) );
-        }
-
-    }
-
-    public static abstract class ComposeWithJDKMixin
-        implements JSONSerializableMap
-    {
-
-        @This
-        private Map<String, String> map;
-
-        @Override
-        public JSONObject toJSON()
-        {
-            System.out.println( ">>>> Call ComposeWithJDKMixin.toJSON()" );
-            // Copy the Map before handing it to JSONObject so that the JSONObject do not use the Composite
-            return new JSONObject( new HashMap<String, String>( map ) );
-        }
-
-    }
-
-    public static class JDKMixinConcern
-        extends GenericConcern
-    {
-
-        @Override
-        public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-        {
-            System.out.println( ">>>> Call to JDKMixinConcern." + method.getName() );
-            CONCERN_RECORDS.add( method.getName() );
-            return next.invoke( proxy, method, args );
-        }
-
-    }
-
-    private static final String EXTENDS_IDENTITY = ExtendsJDKMixin.class.getName();
-    private static final String COMPOSE_IDENTITY = ComposeWithJDKMixin.class.getName();
-    private static final Specification<ServiceReference<?>> EXTENDS_IDENTITY_SPEC = new ServiceIdentitySpec( EXTENDS_IDENTITY );
-    private static final Specification<ServiceReference<?>> COMPOSE_IDENTITY_SPEC = new ServiceIdentitySpec( COMPOSE_IDENTITY );
-    private static final List<String> CONCERN_RECORDS = new ArrayList<String>();
-
-    @Before
-    public void beforeEachTest()
-    {
-        CONCERN_RECORDS.clear();
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( JSONSerializableMap.class ).
-            identifiedBy( EXTENDS_IDENTITY ).
-            withMixins( ExtendsJDKMixin.class ).
-            instantiateOnStartup();
-
-        module.layer().module( "compose" ).services( JSONSerializableMap.class ).
-            visibleIn( Visibility.layer ).
-            identifiedBy( COMPOSE_IDENTITY ).
-            withMixins( HashMap.class, ComposeWithJDKMixin.class ).
-            instantiateOnStartup();
-    }
-
-    @Test
-    public void testMixinExtendsJDK()
-    {
-        List<ServiceReference<JSONSerializableMap>> services = toList(
-            filter( EXTENDS_IDENTITY_SPEC,
-                    module.findServices( JSONSerializableMap.class ) ) );
-
-        assertThat( services.size(), equalTo( 1 ) );
-        assertThat( services.get( 0 ).identity(), equalTo( EXTENDS_IDENTITY ) );
-
-        JSONSerializableMap extending = services.get( 0 ).get();
-        extending.put( "foo", "bar" ); // Concern trigger #1 (put)
-        JSONObject json = extending.toJSON(); // Concern trigger #2, #3 and #4 (toJSON, size, entrySet)
-
-        assertThat( json.length(), equalTo( 1 ) );
-        assertThat( json.optString( "foo" ), equalTo( "bar" ) );
-
-        assertThat( CONCERN_RECORDS.size(), equalTo( 4 ) );
-    }
-
-    @Test
-    public void testComposeJDKMixin()
-    {
-        List<ServiceReference<JSONSerializableMap>> services = toList(
-            filter( COMPOSE_IDENTITY_SPEC,
-                    module.findServices( JSONSerializableMap.class ) ) );
-
-        assertThat( services.size(), equalTo( 1 ) );
-        assertThat( services.get( 0 ).identity(), equalTo( COMPOSE_IDENTITY ) );
-
-        JSONSerializableMap composing = services.get( 0 ).get();
-        composing.put( "foo", "bar" ); // Concern trigger #1 (put)
-        JSONObject json = composing.toJSON(); // Concern trigger #2, #3 and #4 (toJSON, size, entrySet)
-
-        assertThat( json.length(), equalTo( 1 ) );
-        assertThat( json.optString( "foo" ), equalTo( "bar" ) );
-
-        assertThat( CONCERN_RECORDS.size(), equalTo( 4 ) );
-    }
-
-    private static class ServiceIdentitySpec
-        implements Specification<ServiceReference<?>>
-    {
-
-        private final String identity;
-
-        public ServiceIdentitySpec( String identity )
-        {
-            this.identity = identity;
-        }
-
-        @Override
-        public boolean satisfiedBy( ServiceReference<?> item )
-        {
-            return item.identity().equals( identity );
-        }
-
-    }
-
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/mixin/MethodInterceptionMixinTest.java b/core/runtime/src/test/java/org/qi4j/runtime/mixin/MethodInterceptionMixinTest.java
deleted file mode 100644
index 20dd671..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/mixin/MethodInterceptionMixinTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.mixin;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Test;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-
-public class MethodInterceptionMixinTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( SomeService.class );
-    }
-
-    @Test
-    public void whenMixinCallsPublicMethodExpectInvocationStackToBeCalled()
-    {
-        ServiceReference<SomeService> service = module.findService( SomeService.class );
-        Collection<String> result1 = service.get().result();
-        assertEquals( "Concern should have been called.", 1, result1.size() );
-        assertEquals( "Concern should have been called.", "Concern1", result1.iterator().next() );
-    }
-
-    @Concerns( { SomeConcern1.class } )
-    @Mixins( { SomeMixin.class } )
-    public interface SomeService
-        extends Some, ServiceComposite
-    {
-    }
-
-    public interface Some
-    {
-        Collection<String> doSome();
-
-        Collection<String> result();
-    }
-
-    public static abstract class SomeMixin
-        implements Some
-    {
-
-        @This
-        Some some;
-
-        public Collection<String> doSome()
-        {
-            return new ArrayList<String>();
-        }
-
-        public List<String> result()
-        {
-            return (List<String>) some.doSome();
-        }
-    }
-
-    public static abstract class SomeConcern1
-        extends ConcernOf<Some>
-        implements Some
-    {
-
-        public Collection<String> doSome()
-        {
-            Collection<String> some = next.doSome();
-            some.add( "Concern1" );
-            return some;
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/mixin/MixinPrecedenceTest.java b/core/runtime/src/test/java/org/qi4j/runtime/mixin/MixinPrecedenceTest.java
deleted file mode 100644
index 3fdb1f5..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/mixin/MixinPrecedenceTest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.mixin;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test mixin declaration precedence satisfiedBy
- */
-public class MixinPrecedenceTest
-    extends AbstractQi4jTest
-{
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TestComposite1.class,
-                           TestComposite2.class,
-                           TestComposite3.class );
-    }
-
-    @Test
-    public void whenMultipleTypedMixinsPrecedence()
-    {
-        TestComposite1 instance = module.newTransient( TestComposite1.class );
-        assertThat( "Mixin precedence", instance.AMethod(), equalTo( "A1" ) );
-    }
-
-    @Test
-    public void whenGenericAndTypedMixinPrecedence()
-    {
-        TestComposite2 instance = module.newTransient( TestComposite2.class );
-        assertThat( "Typed mixin is chosen over generic mixin", instance.AMethod(), equalTo( "A1" ) );
-    }
-
-    @Test
-    public void whenMultipleGenericMixinsPrecedence()
-    {
-        TestComposite3 instance = module.newTransient( TestComposite3.class );
-        assertEquals( "GM1", instance.AMethod() );
-    }
-
-    @Mixins( { AMixin1.class, AMixin2.class } )
-    public static interface TestComposite1
-        extends A, TransientComposite
-    {
-    }
-
-    @Mixins( { GenericMixin1.class, AMixin1.class } )
-    public static interface TestComposite2
-        extends A, TransientComposite
-    {
-    }
-
-    @Mixins( { GenericMixin1.class, GenericMixin2.class } )
-    public static interface TestComposite3
-        extends A, TransientComposite
-    {
-    }
-
-    public interface A
-    {
-        String AMethod();
-    }
-
-    public static class AMixin1
-        implements A
-    {
-
-        public String AMethod()
-        {
-            return "A1";
-        }
-    }
-
-    public static class AMixin2
-        implements A
-    {
-
-        public String AMethod()
-        {
-            return "A2";
-        }
-    }
-
-    public static class GenericMixin1
-        implements InvocationHandler
-    {
-        public Object invoke( Object object, Method method, Object[] objects )
-            throws Throwable
-        {
-            return "GM1";
-        }
-    }
-
-    public static class GenericMixin2
-        implements InvocationHandler
-    {
-        public Object invoke( Object object, Method method, Object[] objects )
-            throws Throwable
-        {
-            return "GM2";
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/mixin/MixinsOnThisInjectionTest.java b/core/runtime/src/test/java/org/qi4j/runtime/mixin/MixinsOnThisInjectionTest.java
deleted file mode 100644
index 72ff2cc..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/mixin/MixinsOnThisInjectionTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.mixin;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test of declaring Mixin in @This declared interface
- */
-public class MixinsOnThisInjectionTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TestCase.class );
-    }
-
-    @Test
-    public void givenCompositeWithThisInjectionAndNoMixinDeclarationWhenBindingCompositeThenUseInterfaceDeclaredMixin()
-    {
-        TestCase TestCase = module.newTransient( TestCase.class );
-        assertThat( "Composite can be instantiated", TestCase.sayHello(), equalTo( "Hello" ) );
-    }
-
-    @Mixins( TestMixin.class )
-    public interface TestCase
-        extends TransientComposite
-    {
-        String sayHello();
-    }
-
-    public abstract static class TestMixin
-        implements TestCase
-    {
-        @This
-        TestCase2 testCase2;
-
-        public String sayHello()
-        {
-            return testCase2.sayHello();
-        }
-    }
-
-    @Mixins( TestMixin2.class )
-    public interface TestCase2
-    {
-        String sayHello();
-    }
-
-    public abstract static class TestMixin2
-        implements TestCase2
-    {
-        public String sayHello()
-        {
-            return "Hello";
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/mixin/PrivateMixinTest.java b/core/runtime/src/test/java/org/qi4j/runtime/mixin/PrivateMixinTest.java
deleted file mode 100644
index d5de777..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/mixin/PrivateMixinTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.mixin;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-/**
- * Unit tests related to private mixins.
- */
-public class PrivateMixinTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( SpeakComposite.class );
-    }
-
-    /**
-     * Tests that private mixins are injected correctly.
-     */
-    @Test
-    public void privateMixinInjection()
-    {
-        SpeakComposite test = module.newTransient( SpeakComposite.class );
-        assertThat( "Speak", test.speak(), is( equalTo( "I say it works" ) ) );
-    }
-
-    @Mixins( SpeakMixin.class )
-    public interface Speak
-    {
-        String speak();
-    }
-
-    public static class SpeakMixin
-        implements Speak
-    {
-        @This
-        Word word;
-
-        public String speak()
-        {
-            return "I say " + word.get();
-        }
-    }
-
-    @Mixins( { WordMixin.class } )
-    public interface SpeakComposite
-        extends Speak, TransientComposite
-    {
-    }
-
-    public interface Word
-    {
-        String get();
-    }
-
-    public static class WordMixin
-        implements Word
-    {
-        public String get()
-        {
-            return "it works";
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/mixin/Qi228Test.java b/core/runtime/src/test/java/org/qi4j/runtime/mixin/Qi228Test.java
deleted file mode 100644
index 3047e31..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/mixin/Qi228Test.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2009 Lukasz Zielinski.
- *
- * Licensed  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.qi4j.runtime.mixin;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import org.junit.Test;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-public class Qi228Test
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( SomeLogicService.class );
-    }
-
-    @Test
-    public void test1()
-        throws Exception
-    {
-        SomeLogic service = module.findService( SomeLogic.class ).get();
-        try
-        {
-            service.getNumbers();
-            // Either should succeed.
-        }
-        catch( Exception e )
-        {
-            // Or fail with a decent Excpetion.
-        }
-    }
-
-    public interface SomeLogic
-    {
-        Collection<Integer> getNumbers();
-    }
-
-    public static class SomeLogicMixin
-        implements SomeLogic
-    {
-        public List<Integer> getNumbers()
-        {
-            return Collections.emptyList();
-        }
-    }
-
-    @Mixins( { SomeLogicMixin.class } )
-    public interface SomeLogicService
-        extends SomeLogic, ServiceComposite
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/objects/ObjectBuilderFactoryTest.java b/core/runtime/src/test/java/org/qi4j/runtime/objects/ObjectBuilderFactoryTest.java
deleted file mode 100644
index 98d0ad3..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/objects/ObjectBuilderFactoryTest.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.objects;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.object.NoSuchObjectException;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.notNullValue;
-
-/**
- * Unit tests for ObjectBuilderFactory.
- */
-public class ObjectBuilderFactoryTest
-{
-
-    /**
-     * Tests that an object builder cannot be created for an unregistered object.
-     *
-     * @throws Exception expected
-     */
-    @Test( expected = NoSuchObjectException.class )
-    public void newBuilderForUnregisteredObject()
-        throws Exception
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-            }
-        };
-        assembler.module().newObject( AnyObject.class );
-    }
-
-    /**
-     * Tests that an object builder cannot be created for a 'null' type.
-     *
-     * @throws Exception expected
-     */
-    @Test( expected = NullArgumentException.class )
-    public void newBuilderForNullType()
-        throws Exception
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-            }
-        };
-        assembler.module().newObject( null );
-    }
-
-    /**
-     * Tests that an object builder cannot be created for a 'null' type.
-     *
-     * @throws Exception expected
-     */
-    @Test( expected = NullArgumentException.class )
-    public void newObjectInstanceForNullType()
-        throws Exception
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-            }
-        };
-        assembler.module().newObject( null );
-    }
-
-    /**
-     * Tests that an object can be created for an registered object class.
-     */
-    @Test
-    public void newInstanceForRegisteredObject()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.objects( AnyObject.class );
-            }
-        };
-        assembler.module().newObject( AnyObject.class );
-    }
-
-    @Test
-    public void givenManyConstructorsWhenInstantiateThenChooseCorrectConstructor()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.objects( ManyConstructorObject.class );
-            }
-        };
-
-        ManyConstructorObject object = assembler.module().newObject( ManyConstructorObject.class );
-        Assert.assertThat( "ref is not null", object.anyObject, notNullValue() );
-
-        object = assembler.module()
-            .newObject( ManyConstructorObject.class, new AnyObject() );
-
-        Assert.assertThat( "ref is not null", object.anyObject, notNullValue() );
-    }
-
-    @Test
-    public void givenClassWithInnerClassesWhenInstantiateThenInstantiateInnerClass()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.objects( OuterClass.class );
-            }
-        };
-
-        Assert.assertThat( "inner class has been injected", assembler.module()
-            .newObject( OuterClass.class )
-            .name(), equalTo( "Module 1" ) );
-    }
-
-    public static final class AnyObject
-    {
-    }
-
-    public static final class ManyConstructorObject
-    {
-        AnyObject anyObject;
-        Module module;
-
-        public ManyConstructorObject( @Uses AnyObject anyObject, @Structure Module module )
-        {
-            this.anyObject = anyObject;
-            this.module = module;
-        }
-
-        public ManyConstructorObject( @Structure Module module )
-        {
-            this.module = module;
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/objects/ObjectConcernTest.java b/core/runtime/src/test/java/org/qi4j/runtime/objects/ObjectConcernTest.java
deleted file mode 100644
index 0a8935f..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/objects/ObjectConcernTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.objects;
-
-import java.lang.reflect.Method;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.concern.GenericConcern;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-/**
- * JAVADOC
- */
-public class ObjectConcernTest
-{
-
-    @Test
-    public void testConcernOnObject()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.objects( TestObject.class );
-            }
-        };
-
-        TestObject object = assembler.module().newObject( TestObject.class );
-
-        object.doStuff();
-    }
-
-    @Concerns( LogConcern.class )
-    public static class TestObject
-    {
-        public void doStuff()
-        {
-        }
-    }
-
-    public static class LogConcern
-        extends GenericConcern
-    {
-        public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-        {
-            System.out.println( "Invoked " + method.getName() + " on " + proxy );
-
-            return next.invoke( proxy, method, args );
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/objects/ObjectVisibilityTest.java b/core/runtime/src/test/java/org/qi4j/runtime/objects/ObjectVisibilityTest.java
deleted file mode 100644
index 4dda084..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/objects/ObjectVisibilityTest.java
+++ /dev/null
@@ -1,881 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.objects;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.object.NoSuchObjectException;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.ApplicationAssemblerAdapter;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-
-public class ObjectVisibilityTest
-{
-
-    private Energy4Java qi4j;
-    private Module module;
-    private Application app;
-
-    @Before
-    public void setup()
-        throws Exception
-    {
-        qi4j = new Energy4Java();
-
-        Assembler[][][] assemblers = new Assembler[][][]
-            {
-                { // Layer Above
-                  {
-                      new AboveAssembler()
-                  }
-                },
-                { // Layer From
-                  { // From Module
-                    new FromAssembler(),
-                  },
-                  { // Beside Module
-                    new BesideAssembler()
-                  }
-                },
-                { // Layer Below
-                  {
-                      new BelowAssembler()
-                  }
-                }
-            };
-        app = qi4j.newApplication( new ApplicationAssemblerAdapter( assemblers )
-        {
-        } );
-        app.activate();
-        module = app.findModule( "From Layer", "From" );
-    }
-
-    @After
-    public void tearDown()
-        throws Exception
-    {
-        app.passivate();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.besideLayerVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromServiceWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.belowApplicationVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromServiceWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.belowLayerVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromServiceWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.belowModuleVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromServiceWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.aboveApplicationVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromServiceWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.aboveLayerVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromServiceWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.aboveModuleVisible();
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.moduleApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.moduleLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.moduleModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.besideApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.besideLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromEntityWhenAccessingBesideModuleVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.besideModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.belowApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromEntityWhenAccessingBelowLayerVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.belowLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromEntityWhenAccessingBelowModuleVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.belowModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromEntityWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.aboveApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromEntityWhenAccessingAboveLayerVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.aboveLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromEntityWhenAccessingAboveModuleVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.aboveModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.besideLayerVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromValueWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.belowApplicationVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromValueWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.belowLayerVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromValueWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.belowModuleVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromValueWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.aboveApplicationVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromValueWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.aboveLayerVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromValueWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.aboveModuleVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.besideLayerVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromTransientWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.belowApplicationVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromTransientWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.belowLayerVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromTransientWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.belowModuleVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromTransientWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.aboveApplicationVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromTransientWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.aboveLayerVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromTransientWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.aboveModuleVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.besideLayerVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromObjectWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.belowApplicationVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromObjectWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.belowLayerVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromObjectWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.belowModuleVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromObjectWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.aboveApplicationVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromObjectWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.aboveLayerVisible();
-    }
-
-    @Test( expected = NoSuchObjectException.class )
-    public void givenFromObjectWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.aboveModuleVisible();
-    }
-
-    private static class FromAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.layer().setName( "From Layer" );
-            module.setName( "From" );
-            module.services( FromService.class );
-            module.entities( FromEntity.class );
-            module.transients( FromTransient.class );
-            module.values( FromValue.class );
-            module.objects( FromObject.class );
-
-            module.objects( ModuleApplicationVisible.class ).visibleIn( Visibility.application );
-            module.objects( ModuleLayerVisible.class ).visibleIn( Visibility.layer );
-            module.objects( ModuleModuleVisible.class ).visibleIn( Visibility.module );
-        }
-    }
-
-    private static class BelowAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.layer().setName( "Below Layer" );
-            module.setName( "Below" );
-            module.objects( BelowApplicationVisible.class ).visibleIn( Visibility.application );
-            module.objects( BelowLayerVisible.class ).visibleIn( Visibility.layer );
-            module.objects( BelowModuleVisible.class ).visibleIn( Visibility.module );
-
-            new EntityTestAssembler().visibleIn( Visibility.application ).assemble( module );
-        }
-    }
-
-    private static class AboveAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.layer().setName( "Above Layer" );
-            module.setName( "Above" );
-            module.objects( AboveApplicationVisible.class ).visibleIn( Visibility.application );
-            module.objects( AboveLayerVisible.class ).visibleIn( Visibility.layer );
-            module.objects( AboveModuleVisible.class ).visibleIn( Visibility.module );
-        }
-    }
-
-    private static class BesideAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.setName( "Beside" );
-            module.objects( BesideApplicationVisible.class ).visibleIn( Visibility.application );
-            module.objects( BesideLayerVisible.class ).visibleIn( Visibility.layer );
-            module.objects( BesideModuleVisible.class ).visibleIn( Visibility.module );
-        }
-    }
-
-    @Mixins( Mixin.class )
-    public interface From
-    {
-        void moduleApplicationVisible();
-
-        void moduleLayerVisible();
-
-        void moduleModuleVisible();
-
-        void besideApplicationVisible();
-
-        void besideLayerVisible();
-
-        void besideModuleVisible();
-
-        void belowApplicationVisible();
-
-        void belowLayerVisible();
-
-        void belowModuleVisible();
-
-        void aboveApplicationVisible();
-
-        void aboveLayerVisible();
-
-        void aboveModuleVisible();
-    }
-
-    public interface FromValue extends From, ValueComposite
-    {
-    }
-
-    public interface FromEntity extends From, EntityComposite
-    {
-    }
-
-    public interface FromService extends From, ServiceComposite
-    {
-    }
-
-    public interface FromTransient extends From, TransientComposite
-    {
-    }
-
-    public static class FromObject extends Mixin
-    {
-    }
-
-    public abstract static class Mixin
-        implements From
-    {
-        @Structure
-        private Module module;
-
-        @Override
-        public void moduleApplicationVisible()
-        {
-            module.newObject( ModuleApplicationVisible.class );
-        }
-
-        @Override
-        public void moduleLayerVisible()
-        {
-            module.newObject( ModuleLayerVisible.class );
-        }
-
-        @Override
-        public void moduleModuleVisible()
-        {
-            module.newObject( ModuleModuleVisible.class );
-        }
-
-        @Override
-        public void besideApplicationVisible()
-        {
-            module.newObject( BesideApplicationVisible.class );
-        }
-
-        @Override
-        public void besideLayerVisible()
-        {
-            module.newObject( BesideLayerVisible.class );
-        }
-
-        @Override
-        public void besideModuleVisible()
-        {
-            module.newObject( BesideModuleVisible.class );
-        }
-
-        @Override
-        public void belowApplicationVisible()
-        {
-            module.newObject( BelowApplicationVisible.class );
-        }
-
-        @Override
-        public void belowLayerVisible()
-        {
-            module.newObject( BelowLayerVisible.class );
-        }
-
-        @Override
-        public void belowModuleVisible()
-        {
-            module.newObject( BelowModuleVisible.class );
-        }
-
-        @Override
-        public void aboveApplicationVisible()
-        {
-            module.newObject( AboveApplicationVisible.class );
-        }
-
-        @Override
-        public void aboveLayerVisible()
-        {
-            module.newObject( AboveLayerVisible.class );
-        }
-
-        @Override
-        public void aboveModuleVisible()
-        {
-            module.newObject( AboveModuleVisible.class );
-        }
-    }
-
-    public static class ModuleApplicationVisible
-    {
-    }
-
-    public static class ModuleLayerVisible
-    {
-    }
-
-    public static class ModuleModuleVisible
-    {
-    }
-
-    public static class BesideApplicationVisible
-    {
-    }
-
-    public static class BesideLayerVisible
-    {
-    }
-
-    public static class BesideModuleVisible
-    {
-    }
-
-    public static class BelowApplicationVisible
-    {
-    }
-
-    public static class BelowLayerVisible
-    {
-    }
-
-    public static class BelowModuleVisible
-    {
-    }
-
-    public static class AboveApplicationVisible
-    {
-    }
-
-    public static class AboveLayerVisible
-    {
-    }
-
-    public static class AboveModuleVisible
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/objects/OuterClass.java b/core/runtime/src/test/java/org/qi4j/runtime/objects/OuterClass.java
deleted file mode 100644
index 815fe99..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/objects/OuterClass.java
+++ /dev/null
@@ -1,48 +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.qi4j.runtime.objects;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.structure.Module;
-
-/**
- * TODO
- */
-public class OuterClass
-{
-    @Uses
-    InnerClass instance;
-
-    @Structure
-    Module module;
-
-    public String name()
-    {
-        return instance.name();
-    }
-
-    class InnerClass
-    {
-        public String name()
-        {
-            return module.name();
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/property/ImmutablePropertyTest.java b/core/runtime/src/test/java/org/qi4j/runtime/property/ImmutablePropertyTest.java
deleted file mode 100644
index 1c14e51..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/property/ImmutablePropertyTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.runtime.property;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-public final class ImmutablePropertyTest
-    extends AbstractQi4jTest
-{
-    private static final String KUALA_LUMPUR = "Kuala Lumpur";
-
-    @Test
-    public final void testCreationalWithStateFor()
-    {
-        Location location = createLocation( KUALA_LUMPUR );
-        testNamePropertyGet( location, KUALA_LUMPUR );
-    }
-
-    private Location createLocation( String locationName )
-    {
-        TransientBuilder<Location> locationBuilder = module.newTransientBuilder( Location.class );
-        Location locState = locationBuilder.prototypeFor( Location.class );
-        locState.name().set( locationName );
-        return locationBuilder.newInstance();
-    }
-
-    private void testNamePropertyGet( Location location, String locationName )
-    {
-        assertNotNull( location );
-        assertEquals( locationName, location.name().get() );
-    }
-
-    @Test
-    public final void testCreationWithStateOfComposite()
-    {
-        TransientBuilder<Location> locationBuilder = module.newTransientBuilder( Location.class );
-        Location locState = locationBuilder.prototype();
-        locState.name().set( KUALA_LUMPUR );
-        Location location = locationBuilder.newInstance();
-
-        testNamePropertyGet( location, KUALA_LUMPUR );
-    }
-
-    @Test( expected = IllegalStateException.class )
-    public final void testSetter()
-    {
-        Location location = createLocation( KUALA_LUMPUR );
-
-        // Must fail!
-        Property<String> stringProperty = location.name();
-        stringProperty.set( "abc" );
-    }
-
-    @Test
-    public final void testImmutableEntityProperty()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            EntityBuilder<LocationEntity> builder = uow.newEntityBuilder( LocationEntity.class );
-            builder.instance().name().set( "Rickard" );
-            Location location = builder.newInstance();
-
-            try
-            {
-                location.name().set( "Niclas" );
-                Assert.fail( "Should be immutable" );
-            }
-            catch( IllegalStateException e )
-            {
-                // Ok
-            }
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    public final void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( LocationComposite.class );
-        module.entities( LocationEntity.class );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    interface LocationComposite
-        extends Location, TransientComposite
-    {
-    }
-
-    interface LocationEntity
-        extends Location, EntityComposite
-    {
-    }
-
-    interface Location
-    {
-        @Immutable
-        Property<String> name();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/property/PropertyEqualityTest.java b/core/runtime/src/test/java/org/qi4j/runtime/property/PropertyEqualityTest.java
deleted file mode 100644
index 22de796..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/property/PropertyEqualityTest.java
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * Copyright (c) 2013, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.property;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.Date;
-import org.joda.time.DateTime;
-import org.joda.time.LocalDate;
-import org.joda.time.LocalDateTime;
-import org.junit.Test;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.allOf;
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.not;
-import static org.joda.time.DateTimeZone.UTC;
-import static org.junit.Assert.assertThat;
-
-/**
- * Assert that Property equals/hashcode methods combine PropertyDescriptor and State.
- */
-public class PropertyEqualityTest
-    extends AbstractQi4jTest
-{
-
-    //
-    // --------------------------------------:: Types under test ::-----------------------------------------------------
-    //
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.values( PrimitivesValue.class, Some.class, AnotherSome.class, Other.class );
-    }
-
-    public enum AnEnum
-    {
-
-        BAZAR, CATHEDRAL
-    }
-
-    public interface PrimitivesValue
-    {
-
-        Property<Character> characterProperty();
-
-        Property<String> stringProperty();
-
-        Property<Boolean> booleanProperty();
-
-        Property<Integer> integerProperty();
-
-        Property<Long> longProperty();
-
-        Property<Float> floatProperty();
-
-        Property<Double> doubleProperty();
-
-        Property<Short> shortProperty();
-
-        Property<Byte> byteProperty();
-
-        Property<AnEnum> enumProperty();
-    }
-
-    public interface Some
-        extends PrimitivesValue
-    {
-
-        @Optional
-        Property<Some> selfProperty();
-
-        Property<BigInteger> bigIntegerProperty();
-
-        Property<BigDecimal> bigDecimalProperty();
-
-        Property<Date> dateProperty();
-
-        Property<DateTime> dateTimeProperty();
-
-        Property<LocalDate> localDateProperty();
-
-        Property<LocalDateTime> localDateTimeProperty();
-    }
-
-    public interface AnotherSome
-        extends Some
-    {
-    }
-
-    public interface Other
-    {
-
-        Property<Character> characterProperty();
-    }
-
-    //
-    // ------------------------------:: PropertyDescriptor equality tests ::--------------------------------------------
-    //
-    @Test
-    public void givenValuesOfTheSameTypeWhenTestingPropertyDescriptorEqualityExpectEquals()
-    {
-        Some some = buildSomeValue( module );
-        ValueDescriptor someDescriptor = qi4j.api().valueDescriptorFor( some );
-        PropertyDescriptor someCharPropDesc = someDescriptor.state().findPropertyModelByName( "characterProperty" );
-
-        Some other = buildSomeValue( module );
-        ValueDescriptor otherDescriptor = qi4j.api().valueDescriptorFor( other );
-        PropertyDescriptor otherCharPropDesc = otherDescriptor.state().findPropertyModelByName( "characterProperty" );
-
-        assertThat( "PropertyDescriptors equal",
-                    someCharPropDesc,
-                    equalTo( otherCharPropDesc ) );
-        assertThat( "PropertyDescriptors hashcode equal",
-                    someCharPropDesc.hashCode(),
-                    equalTo( otherCharPropDesc.hashCode() ) );
-    }
-
-    @Test
-    public void givenValuesOfCommonTypesWhenTestingPropertyDescriptorEqualityExpectEquals()
-    {
-        Some some = buildSomeValue( module );
-        ValueDescriptor someDescriptor = qi4j.api().valueDescriptorFor( some );
-        PropertyDescriptor someCharPropDesc = someDescriptor.state().findPropertyModelByName( "characterProperty" );
-
-        PrimitivesValue primitive = buildPrimitivesValue( module );
-        ValueDescriptor primitiveDescriptor = qi4j.api().valueDescriptorFor( primitive );
-        PropertyDescriptor primitiveCharPropDesc = primitiveDescriptor.state().findPropertyModelByName( "characterProperty" );
-
-        assertThat( "PropertyDescriptors equal",
-                    someCharPropDesc,
-                    equalTo( primitiveCharPropDesc ) );
-        assertThat( "PropertyDescriptors hashcode equal",
-                    someCharPropDesc.hashCode(),
-                    equalTo( primitiveCharPropDesc.hashCode() ) );
-    }
-
-    @Test
-    public void givenValuesOfDifferentTypesWhenTestingPropertyDescriptorEqualityExpectNotEquals()
-    {
-        Some some = buildSomeValue( module );
-        ValueDescriptor someDescriptor = qi4j.api().valueDescriptorFor( some );
-        PropertyDescriptor someCharPropDesc = someDescriptor.state().findPropertyModelByName( "characterProperty" );
-
-        Other other = buildOtherValue( module );
-        ValueDescriptor otherDescriptor = qi4j.api().valueDescriptorFor( other );
-        PropertyDescriptor otherCharPropDesc = otherDescriptor.state().findPropertyModelByName( "characterProperty" );
-
-        assertThat( "PropertyDescriptors not equal",
-                    someCharPropDesc,
-                    not( equalTo( otherCharPropDesc ) ) );
-        assertThat( "PropertyDescriptors hashcode not equal",
-                    someCharPropDesc.hashCode(),
-                    not( equalTo( otherCharPropDesc.hashCode() ) ) );
-    }
-
-    //
-    // --------------------------------:: Property State equality tests ::----------------------------------------------
-    //
-    @Test
-    public void givenValuesOfDifferentTypesAndSameStateWhenTestingPropertyStateEqualityExpectEquals()
-    {
-        PrimitivesValue primitives = buildPrimitivesValue( module );
-        Some some = buildSomeValue( module );
-        Some some2 = buildSomeValue( module );
-        Other other = buildOtherValue( module );
-        assertThat( "Property state equal",
-                    'q',
-                    allOf( equalTo( primitives.characterProperty().get() ),
-                           equalTo( some.characterProperty().get() ),
-                           equalTo( some2.characterProperty().get() ),
-                           equalTo( other.characterProperty().get() ) ) );
-        assertThat( "Property state hashcode equal",
-                    new Character( 'q' ).hashCode(),
-                    allOf( equalTo( primitives.characterProperty().get().hashCode() ),
-                           equalTo( some.characterProperty().get().hashCode() ),
-                           equalTo( some2.characterProperty().get().hashCode() ),
-                           equalTo( other.characterProperty().get().hashCode() ) ) );
-    }
-
-    //
-    // -----------------------------------:: Property equality tests ::-------------------------------------------------
-    //
-    @Test
-    public void givenValuesOfTheSameTypeAndSameStateWhenTestingPropertyEqualityExpectEquals()
-    {
-        Some some = buildSomeValue( module );
-        Some some2 = buildSomeValue( module );
-        assertThat( "Property equals",
-                    some.characterProperty(),
-                    equalTo( some2.characterProperty() ) );
-        assertThat( "Property hashcode equals",
-                    some.characterProperty().hashCode(),
-                    equalTo( some2.characterProperty().hashCode() ) );
-    }
-
-    @Test
-    public void givenValuesOfTheSameTypeWithDifferentStateWhenTestingPropertyEqualityExpectNotEquals()
-    {
-        Some some = buildSomeValue( module );
-        Some some2 = buildSomeValueWithDifferentState( module );
-        assertThat( "Property not equals",
-                    some.characterProperty(),
-                    not( equalTo( some2.characterProperty() ) ) );
-        assertThat( "Property hashcode not equals",
-                    some.characterProperty().hashCode(),
-                    not( equalTo( some2.characterProperty().hashCode() ) ) );
-    }
-
-    @Test
-    public void givenValuesOfCommonTypesAndSameStateWhenTestingPropertyEqualityExpectEquals()
-    {
-        Some some = buildSomeValue( module );
-        PrimitivesValue primitive = buildPrimitivesValue( module );
-        assertThat( "Property equal",
-                    some.characterProperty(),
-                    equalTo( primitive.characterProperty() ) );
-    }
-
-    @Test
-    public void givenValuesOfCommonTypesWithDifferentStateWhenTestingPropertyEqualityExpectNotEquals()
-    {
-        Some some = buildSomeValue( module );
-        PrimitivesValue primitive = buildPrimitivesValueWithDifferentState( module );
-        assertThat( "Property not equal",
-                    some.characterProperty(),
-                    not( equalTo( primitive.characterProperty() ) ) );
-    }
-
-    @Test
-    public void givenValuesOfDifferentTypesAndSameStateWhenTestingPropertyEqualityExpectNotEquals()
-    {
-        Some some = buildSomeValue( module );
-        Other other = buildOtherValue( module );
-        assertThat( "Property not equal",
-                    some.characterProperty(),
-                    not( equalTo( other.characterProperty() ) ) );
-    }
-
-    @Test
-    public void givenValuesOfDifferentTypesWithDifferentStateWhenTestingPropertyEqualityExpectNotEquals()
-    {
-        Some some = buildSomeValue( module );
-        Other other = buildOtherValue( module );
-        assertThat( "Property not equal",
-                    some.characterProperty(),
-                    not( equalTo( other.characterProperty() ) ) );
-    }
-
-    //
-    // -----------------------------------:: Values factory methods ::--------------------------------------------------
-    //
-    public static PrimitivesValue buildPrimitivesValue( Module module )
-    {
-        PrimitivesValue primitive;
-        {
-            ValueBuilder<PrimitivesValue> builder = module.newValueBuilder( PrimitivesValue.class );
-            builder.prototype().characterProperty().set( 'q' );
-            builder.prototype().stringProperty().set( "foo" );
-            builder.prototype().booleanProperty().set( true );
-            builder.prototype().integerProperty().set( 42 );
-            builder.prototype().longProperty().set( 42L );
-            builder.prototype().floatProperty().set( 42.23F );
-            builder.prototype().doubleProperty().set( 42.23D );
-            builder.prototype().shortProperty().set( (short) 42 );
-            builder.prototype().byteProperty().set( (byte) 42 );
-            builder.prototype().enumProperty().set( AnEnum.BAZAR );
-            primitive = builder.newInstance();
-        }
-        return primitive;
-    }
-
-    public static PrimitivesValue buildPrimitivesValueWithDifferentState( Module module )
-    {
-        PrimitivesValue primitive;
-        {
-            ValueBuilder<PrimitivesValue> builder = module.newValueBuilder( PrimitivesValue.class );
-            builder.prototype().characterProperty().set( 'i' );
-            builder.prototype().stringProperty().set( "bar" );
-            builder.prototype().booleanProperty().set( false );
-            builder.prototype().integerProperty().set( 23 );
-            builder.prototype().longProperty().set( 23L );
-            builder.prototype().floatProperty().set( 23.42F );
-            builder.prototype().doubleProperty().set( 23.42D );
-            builder.prototype().shortProperty().set( (short) 23 );
-            builder.prototype().byteProperty().set( (byte) 23 );
-            builder.prototype().enumProperty().set( AnEnum.CATHEDRAL );
-            primitive = builder.newInstance();
-        }
-        return primitive;
-    }
-
-    public static Some buildSomeValue( Module module )
-    {
-        Some some;
-        {
-            ValueBuilder<Some> builder = module.newValueBuilder( Some.class );
-            builder.prototype().characterProperty().set( 'q' );
-            builder.prototype().stringProperty().set( "foo" );
-            builder.prototype().booleanProperty().set( true );
-            builder.prototype().integerProperty().set( 42 );
-            builder.prototype().longProperty().set( 42L );
-            builder.prototype().floatProperty().set( 42.23F );
-            builder.prototype().doubleProperty().set( 42.23D );
-            builder.prototype().shortProperty().set( (short) 42 );
-            builder.prototype().byteProperty().set( (byte) 42 );
-            builder.prototype().enumProperty().set( AnEnum.BAZAR );
-            builder.prototype().bigIntegerProperty().set( new BigInteger( "42" ) );
-            builder.prototype().bigDecimalProperty().set( new BigDecimal( "42.23" ) );
-            builder.prototype().dateProperty().set( new DateTime( "2020-03-04T13:24:35", UTC ).toDate() );
-            builder.prototype().dateTimeProperty().set( new DateTime( "2020-03-04T13:24:35", UTC ) );
-            builder.prototype().localDateProperty().set( new LocalDate( "2020-03-04" ) );
-            builder.prototype().localDateTimeProperty().set( new LocalDateTime( "2020-03-04T13:23:00", UTC ) );
-            some = builder.newInstance();
-        }
-        return some;
-    }
-
-    public static Some buildSomeValueWithDifferentState( Module module )
-    {
-        Some some;
-        {
-            ValueBuilder<Some> builder = module.newValueBuilder( Some.class );
-            builder.prototype().characterProperty().set( 'i' );
-            builder.prototype().stringProperty().set( "bar" );
-            builder.prototype().booleanProperty().set( false );
-            builder.prototype().integerProperty().set( 23 );
-            builder.prototype().longProperty().set( 23L );
-            builder.prototype().floatProperty().set( 23.42F );
-            builder.prototype().doubleProperty().set( 23.42D );
-            builder.prototype().shortProperty().set( (short) 23 );
-            builder.prototype().byteProperty().set( (byte) 23 );
-            builder.prototype().enumProperty().set( AnEnum.CATHEDRAL );
-            builder.prototype().bigIntegerProperty().set( new BigInteger( "23" ) );
-            builder.prototype().bigDecimalProperty().set( new BigDecimal( "23.42" ) );
-            builder.prototype().dateProperty().set( new DateTime( "2030-02-08T09:09:09", UTC ).toDate() );
-            builder.prototype().dateTimeProperty().set( new DateTime( "2030-02-08T09:09:09", UTC ) );
-            builder.prototype().localDateProperty().set( new LocalDate( "2030-02-08" ) );
-            builder.prototype().localDateTimeProperty().set( new LocalDateTime( "2030-02-08T09:09:09", UTC ) );
-            some = builder.newInstance();
-        }
-        return some;
-    }
-
-    public static AnotherSome buildAnotherSomeValue( Module module )
-    {
-        AnotherSome anotherSome;
-        {
-            ValueBuilder<AnotherSome> builder = module.newValueBuilder( AnotherSome.class );
-            builder.prototype().characterProperty().set( 'q' );
-            builder.prototype().stringProperty().set( "foo" );
-            builder.prototype().booleanProperty().set( true );
-            builder.prototype().integerProperty().set( 42 );
-            builder.prototype().longProperty().set( 42L );
-            builder.prototype().floatProperty().set( 42.23F );
-            builder.prototype().doubleProperty().set( 42.23D );
-            builder.prototype().shortProperty().set( (short) 42 );
-            builder.prototype().byteProperty().set( (byte) 42 );
-            builder.prototype().enumProperty().set( AnEnum.BAZAR );
-            builder.prototype().bigIntegerProperty().set( new BigInteger( "42" ) );
-            builder.prototype().bigDecimalProperty().set( new BigDecimal( "42.23" ) );
-            builder.prototype().dateProperty().set( new DateTime( "2020-03-04T13:24:35", UTC ).toDate() );
-            builder.prototype().dateTimeProperty().set( new DateTime( "2020-03-04T13:24:35", UTC ) );
-            builder.prototype().localDateProperty().set( new LocalDate( "2020-03-04" ) );
-            builder.prototype().localDateTimeProperty().set( new LocalDateTime( "2020-03-04T13:23:00", UTC ) );
-            anotherSome = builder.newInstance();
-        }
-        return anotherSome;
-    }
-
-    public static AnotherSome buildAnotherSomeValueWithDifferentState( Module module )
-    {
-        AnotherSome anotherSome;
-        {
-            ValueBuilder<AnotherSome> builder = module.newValueBuilder( AnotherSome.class );
-            builder.prototype().characterProperty().set( 'i' );
-            builder.prototype().stringProperty().set( "bar" );
-            builder.prototype().booleanProperty().set( false );
-            builder.prototype().integerProperty().set( 23 );
-            builder.prototype().longProperty().set( 23L );
-            builder.prototype().floatProperty().set( 23.42F );
-            builder.prototype().doubleProperty().set( 23.42D );
-            builder.prototype().shortProperty().set( (short) 23 );
-            builder.prototype().byteProperty().set( (byte) 23 );
-            builder.prototype().enumProperty().set( AnEnum.CATHEDRAL );
-            builder.prototype().bigIntegerProperty().set( new BigInteger( "23" ) );
-            builder.prototype().bigDecimalProperty().set( new BigDecimal( "23.42" ) );
-            builder.prototype().dateProperty().set( new DateTime( "2030-02-08T09:09:09", UTC ).toDate() );
-            builder.prototype().dateTimeProperty().set( new DateTime( "2030-02-08T09:09:09", UTC ) );
-            builder.prototype().localDateProperty().set( new LocalDate( "2030-02-08" ) );
-            builder.prototype().localDateTimeProperty().set( new LocalDateTime( "2030-02-08T09:09:09", UTC ) );
-            anotherSome = builder.newInstance();
-        }
-        return anotherSome;
-    }
-
-    public static Other buildOtherValue( Module module )
-    {
-        Other other;
-        {
-            ValueBuilder<Other> builder = module.newValueBuilder( Other.class );
-            builder.prototype().characterProperty().set( 'q' );
-            other = builder.newInstance();
-        }
-        return other;
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/property/PropertyStringArrayTest.java b/core/runtime/src/test/java/org/qi4j/runtime/property/PropertyStringArrayTest.java
deleted file mode 100644
index 0a68baa..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/property/PropertyStringArrayTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.property;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-/**
- * Tests for string arrays as properties (QI-132)
- */
-public class PropertyStringArrayTest
-    extends AbstractQi4jTest
-{
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TestComposite.class );
-    }
-
-    @Test
-    public void testProperty()
-    {
-        TestComposite instance;
-        {
-            TransientBuilder<TestComposite> builder = module.newTransientBuilder( TestComposite.class );
-            builder.prototype().array().set( new String[]{ "Foo", "Bar" } );
-            instance = builder.newInstance();
-        }
-
-        assertThat( "property has correct value", instance.array().get()[ 0 ], equalTo( "Foo" ) );
-
-        instance.array().set( new String[]{ "Hello", "World" } );
-
-        assertThat( "property has correct value", instance.array().get()[ 0 ], equalTo( "Hello" ) );
-    }
-
-    public interface TestComposite
-        extends TransientComposite
-    {
-        Property<String[]> array();
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/property/PropertyTest.java b/core/runtime/src/test/java/org/qi4j/runtime/property/PropertyTest.java
deleted file mode 100644
index ea2a319..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/property/PropertyTest.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.property;
-
-import java.io.Serializable;
-import java.lang.reflect.Method;
-import javax.swing.Icon;
-import org.junit.Test;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.concern.GenericConcern;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.PropertyMixin;
-import org.qi4j.api.property.PropertyWrapper;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * Tests for properties
- */
-//@Ignore(
-//    "This is an incorrect satisfiedBy case. The Property fragment support is not well defined at the moment, so until" +
-//    "more work is finalized on exactly what should be supported, this is ignored not to be forgotten." )
-public class PropertyTest
-    extends AbstractQi4jTest
-{
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( Company.class ).withConcerns( LogConcern.class );
-        module.forMixin( Nameable.class )
-            .setMetaInfo( new DisplayInfo( "Name", "Name of something", "The name" ) )  // Add UI info
-            .setMetaInfo(
-                new RdfInfo( "label", "http://www.w3.org/1999/02/22-rdf-syntax-ns#" ) )  // Add persistence info
-            .declareDefaults()
-            .name()  // Select accessor
-            .set( "Hello World" ); // Set default value
-    }
-
-    @Test
-    public void testProperty()
-    {
-        Company company;
-        {
-            TransientBuilder<Company> builder = module.newTransientBuilder( Company.class );
-            builder.prototype().name().set( "JayWay" );
-            company = builder.newInstance();
-        }
-
-        company.name().set( "Jayway" );
-        assertEquals( "Jayway", company.name().get() );
-        System.out.println( "Name is:" + company.name().get() );
-    }
-
-    public interface Company
-        extends Nameable, StandardComposite, TransientComposite
-    {
-    }
-
-    public interface StandardComposite
-    {
-    }
-
-    public interface Nameable
-    {
-        Property<String> name();
-    }
-
-    @AppliesTo( PropertyMixin.PropertyFilter.class )
-    public static class LogConcern
-        extends GenericConcern
-    {
-        @Override
-        public Object invoke( Object o, final Method method, Object[] objects )
-            throws Throwable
-        {
-            final Property<Object> property = (Property<Object>) next.invoke( o, method, objects );
-
-            return new PropertyWrapper( property )
-            {
-                @Override
-                public Object get()
-                {
-                    Object result = next.get();
-
-                    System.out.println( "Property " + method.getName() + " accessed with value " + result );
-
-                    return result;
-                }
-
-                @Override
-                public void set( Object newValue )
-                    throws IllegalArgumentException, IllegalStateException
-                {
-                    Object current = next.get();
-
-                    next.set( newValue );
-
-                    System.out
-                        .println( "Property " + method.getName() + " changed from " + current + " to " + newValue );
-                }
-            };
-        }
-    }
-
-    public static class DisplayInfo
-        implements Serializable
-    {
-        private String name;
-        private String description;
-        private String toolTip;
-        private Icon icon;
-
-        public DisplayInfo( String name, String description, String toolTip )
-        {
-            this.name = name;
-            this.description = description;
-            this.toolTip = toolTip;
-        }
-
-        public DisplayInfo( String name, String description, String toolTip, Icon icon )
-        {
-            this.name = name;
-            this.description = description;
-            this.toolTip = toolTip;
-            this.icon = icon;
-        }
-
-        public String getName()
-        {
-            return name;
-        }
-
-        public String getDescription()
-        {
-            return description;
-        }
-
-        public String getToolTip()
-        {
-            return toolTip;
-        }
-
-        public Icon getIcon()
-        {
-            return icon;
-        }
-    }
-
-    public static class RdfInfo
-        implements Serializable
-    {
-        private String predicate;
-        private String namespace;
-
-        public RdfInfo( String predicate, String namespace )
-        {
-            this.predicate = predicate;
-            this.namespace = namespace;
-        }
-
-        public String getPredicate()
-        {
-            return predicate;
-        }
-
-        public String getNamespace()
-        {
-            return namespace;
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/property/ValueNestedBuilderTest.java b/core/runtime/src/test/java/org/qi4j/runtime/property/ValueNestedBuilderTest.java
deleted file mode 100644
index a28f8dd..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/property/ValueNestedBuilderTest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.property;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.junit.Test;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-public class ValueNestedBuilderTest
-        extends AbstractQi4jTest
-{
-
-    static interface InnerValue
-            extends ValueComposite
-    {
-
-        Property<List<String>> listProp();
-
-        Property<Map<String, String>> mapProp();
-
-    }
-
-    static interface InnerDefaultedValue
-            extends ValueComposite
-    {
-
-        @UseDefaults
-        Property<List<String>> listPropDefault();
-
-        @UseDefaults
-        Property<Map<String, String>> mapPropDefault();
-
-    }
-
-    static interface OuterValue
-            extends ValueComposite
-    {
-
-        Property<List<InnerValue>> innerListProp();
-
-    }
-
-    static interface OuterDefaultedValue
-            extends ValueComposite
-    {
-
-        @UseDefaults
-        Property<List<InnerDefaultedValue>> innerListPropDefault();
-
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-            throws AssemblyException
-    {
-        module.values( InnerValue.class, InnerDefaultedValue.class, OuterValue.class, OuterDefaultedValue.class );
-    }
-
-    @Test
-    public void testInner()
-    {
-        ValueBuilder<InnerValue> innerBuilder = module.newValueBuilder( InnerValue.class );
-        InnerValue inner = innerBuilder.prototype();
-        inner.listProp().set( new ArrayList<String>() );
-        inner.mapProp().set( new HashMap<String, String>() );
-        inner = innerBuilder.newInstance();
-        // If we reach this point, value creation went well
-    }
-
-    @Test
-    public void testOuter()
-    {
-        ValueBuilder<InnerValue> innerBuilder = module.newValueBuilder( InnerValue.class );
-        InnerValue inner = innerBuilder.prototype();
-        inner.listProp().set( new ArrayList<String>() );
-        inner.mapProp().set( new HashMap<String, String>() );
-        inner = innerBuilder.newInstance();
-        ValueBuilder<OuterValue> outerBuilder = module.newValueBuilder( OuterValue.class );
-        OuterValue outer = outerBuilder.prototype();
-        List<InnerValue> inners = new ArrayList<InnerValue>();
-        inners.add( inner );
-        outer.innerListProp().set( inners );
-        outer = outerBuilder.newInstance();
-        System.out.println( outer.toString() );
-        // If we reach this point, value creation went well
-    }
-
-    @Test
-    public void testDefaultedInner()
-    {
-        ValueBuilder<InnerDefaultedValue> innerBuilder = module.newValueBuilder( InnerDefaultedValue.class );
-        InnerDefaultedValue inner = innerBuilder.newInstance();
-        // If we reach this point, value creation went well
-    }
-
-    @Test
-    public void testDefaultedOuter()
-    {
-        ValueBuilder<InnerDefaultedValue> innerBuilder = module.newValueBuilder( InnerDefaultedValue.class );
-        InnerDefaultedValue inner = innerBuilder.newInstance();
-        ValueBuilder<OuterDefaultedValue> outerBuilder = module.newValueBuilder( OuterDefaultedValue.class );
-        OuterDefaultedValue outer = outerBuilder.prototype();
-        List<InnerDefaultedValue> inners = new ArrayList<InnerDefaultedValue>();
-        inners.add( inner );
-        outer.innerListPropDefault().set( inners );
-        outer = outerBuilder.newInstance();
-        System.out.println( outer.toString() );
-        // If we reach this point, value creation went well
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/IterableQuerySourceTest.java b/core/runtime/src/test/java/org/qi4j/runtime/query/IterableQuerySourceTest.java
deleted file mode 100644
index ecd7276..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/IterableQuerySourceTest.java
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.runtime.query;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.QueryBuilderFactory;
-import org.qi4j.api.query.QueryExpressions;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ClassScanner;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.runtime.query.model.City;
-import org.qi4j.runtime.query.model.Describable;
-import org.qi4j.runtime.query.model.Domain;
-import org.qi4j.runtime.query.model.Female;
-import org.qi4j.runtime.query.model.Male;
-import org.qi4j.runtime.query.model.Nameable;
-import org.qi4j.runtime.query.model.Person;
-import org.qi4j.runtime.query.model.Pet;
-import org.qi4j.runtime.query.model.entities.DomainEntity;
-import org.qi4j.runtime.query.model.entities.PetEntity;
-import org.qi4j.runtime.query.model.values.ContactValue;
-import org.qi4j.runtime.query.model.values.ContactsValue;
-import org.qi4j.spi.query.EntityFinderException;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.qi4j.api.query.QueryExpressions.eq;
-import static org.qi4j.api.query.QueryExpressions.ge;
-import static org.qi4j.api.query.QueryExpressions.gt;
-import static org.qi4j.api.query.QueryExpressions.isNotNull;
-import static org.qi4j.api.query.QueryExpressions.isNull;
-import static org.qi4j.api.query.QueryExpressions.lt;
-import static org.qi4j.api.query.QueryExpressions.matches;
-import static org.qi4j.api.query.QueryExpressions.not;
-import static org.qi4j.api.query.QueryExpressions.or;
-import static org.qi4j.api.query.QueryExpressions.orderBy;
-import static org.qi4j.api.query.QueryExpressions.property;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-public class IterableQuerySourceTest
-{
-
-    private UnitOfWork uow;
-    private QueryBuilderFactory qbf;
-
-    @Before
-    public void setUp()
-        throws UnitOfWorkCompletionException, ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                Iterable<Class<?>> entities = ClassScanner.findClasses( DomainEntity.class );
-
-                for( Class entity : entities )
-                {
-                    module.entities( entity );
-                }
-
-                module.values( ContactsValue.class, ContactValue.class );
-                new EntityTestAssembler().assemble( module );
-            }
-        };
-        uow = assembler.module().newUnitOfWork();
-        Network.populate( uow, assembler.module() );
-        uow.complete();
-        uow = assembler.module().newUnitOfWork();
-        Network.refresh( uow );
-        qbf = assembler.module();
-    }
-
-    @After
-    public void tearDown()
-    {
-        if( uow != null )
-        {
-            uow.discard();
-        }
-    }
-
-    private static void verifyUnorderedResults( final Iterable<? extends Nameable> results,
-                                                final String... names
-    )
-    {
-        final List<String> expected = new ArrayList<String>( Arrays.asList( names ) );
-
-        for( Nameable entity : results )
-        {
-            String name = entity.name().get();
-            assertTrue( name + " returned but not expected", expected.remove( name ) );
-        }
-
-        for( String notReturned : expected )
-        {
-            fail( notReturned + " was expected but not returned" );
-        }
-    }
-
-    private static void verifyOrderedResults( final Iterable<? extends Nameable> results,
-                                              final String... names
-    )
-    {
-        final List<String> expected = new ArrayList<String>( Arrays.asList( names ) );
-
-        for( Nameable entity : results )
-        {
-            String firstExpected = null;
-            if( expected.size() > 0 )
-            {
-                firstExpected = expected.get( 0 );
-            }
-            if( firstExpected == null )
-            {
-                fail( entity.name().get() + " returned but not expected" );
-            }
-            else if( !firstExpected.equals( entity.name().get() ) )
-            {
-                fail( entity.name().get() + " is not in the expected order" );
-            }
-            expected.remove( 0 );
-        }
-        for( String notReturned : expected )
-        {
-            fail( notReturned + " was expected but not returned" );
-        }
-    }
-
-    @Test
-    public void givenQueryWhenExecutedReturnAll()
-        throws EntityFinderException
-    {
-        final QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
-        final Query<Person> query = qb.newQuery( Network.persons() );
-        System.out.println( query );
-        verifyUnorderedResults( query, "Joe Doe", "Ann Doe", "Jack Doe", "Vivian Smith" );
-    }
-
-    @Test
-    public void givenEqQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Domain> qb = qbf.newQueryBuilder( Domain.class );
-        final Nameable nameable = templateFor( Nameable.class );
-        final Query<Domain> query = qb.where(
-            eq( nameable.name(), "Gaming" )
-        ).newQuery( Network.domains() );
-        verifyUnorderedResults( query, "Gaming" );
-    }
-
-    @Test
-    public void givenMixinTypeQueryWhenExecutedReturnAll()
-        throws EntityFinderException
-    {
-        QueryBuilder<Nameable> qb = qbf.newQueryBuilder( Nameable.class );
-        Query<Nameable> query = qb.newQuery( Network.nameables() );
-        verifyUnorderedResults(
-            query,
-            "Joe Doe", "Ann Doe", "Jack Doe", "Vivian Smith",
-            "Penang", "Kuala Lumpur",
-            "Cooking", "Gaming", "Programming", "Cars"
-        );
-    }
-
-    @Test
-    public void givenEqQueryOnValueWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
-        Person personTemplate = templateFor( Person.class );
-        City placeOfBirth = personTemplate.placeOfBirth().get();
-        Query<Person> query = qb.where(
-            eq( placeOfBirth.name(), "Kuala Lumpur" )
-        ).newQuery( Network.persons() );
-        verifyUnorderedResults( query, "Joe Doe", "Ann Doe", "Vivian Smith" );
-    }
-
-    @Test
-    public void givenEqQueryOnAssociationAndPropertyWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = qb.where(
-            eq( person.mother().get().placeOfBirth().get().name(), "Kuala Lumpur" )
-        ).newQuery( Network.persons() );
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void givenEqQueryOnAssociationWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        City kl = uow.get( City.class, "kualalumpur" );
-        Query<Person> query = qb.where(
-            eq( person.mother().get().placeOfBirth(), kl )
-        ).newQuery( Network.persons() );
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void givenGeQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = qb.where(
-            ge( person.yearOfBirth(), 1973 )
-        ).newQuery( Network.persons() );
-        verifyUnorderedResults( query, "Joe Doe", "Ann Doe", "Vivian Smith" );
-    }
-
-    @Test
-    public void givenAndQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Nameable> qb = qbf.newQueryBuilder( Nameable.class );
-        Person person = templateFor( Person.class );
-        Query<Nameable> query = qb.where(
-            ge( person.yearOfBirth(), 1900 ).and( eq( person.placeOfBirth().get().name(), "Penang" ) )
-        ).newQuery( Network.nameables() );
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void givenMultipleAndQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Nameable> qb = qbf.newQueryBuilder( Nameable.class );
-        Person person = templateFor( Person.class );
-        Query<Nameable> query = qb.where(
-            ge( person.yearOfBirth(), 1900 ).
-                and( lt( person.yearOfBirth(), 2000 ) ).
-                and( eq( person.placeOfBirth().get().name(), "Penang" ) )
-        ).newQuery( Network.nameables() );
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void givenOrQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = qb.where(
-            or(
-                eq( person.yearOfBirth(), 1970 ),
-                eq( person.yearOfBirth(), 1975 )
-            )
-        ).newQuery( Network.persons() );
-        verifyUnorderedResults( query, "Jack Doe", "Ann Doe" );
-    }
-
-    @Test
-    public void givenMultipleOrQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = qb.where(
-            or(
-                eq( person.yearOfBirth(), 1970 ),
-                eq( person.yearOfBirth(), 1975 ),
-                eq( person.yearOfBirth(), 1990 )
-            )
-        ).newQuery( Network.persons() );
-        verifyUnorderedResults( query, "Jack Doe", "Ann Doe", "Joe Doe" );
-    }
-
-    @Test
-    public void givenOrQueryOnFemalesWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Female> qb = qbf.newQueryBuilder( Female.class );
-        Person person = templateFor( Person.class );
-        Query<Female> query = qb.where(
-            or(
-                eq( person.yearOfBirth(), 1970 ),
-                eq( person.yearOfBirth(), 1975 )
-            )
-        ).newQuery( Network.females() );
-        verifyUnorderedResults( query, "Ann Doe" );
-    }
-
-    @Test
-    public void givenNotQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = qb.where(
-            not(
-                eq( person.yearOfBirth(), 1975 )
-            )
-        ).newQuery( Network.persons() );
-        verifyUnorderedResults( query, "Jack Doe", "Joe Doe", "Vivian Smith" );
-    }
-
-    @Test
-    public void givenIsNotNullQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = qb.where(
-            isNotNull( person.email() )
-        ).newQuery( Network.persons() );
-        verifyUnorderedResults( query, "Joe Doe", "Vivian Smith" );
-    }
-
-    @Test
-    public void givenIsNullQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = qb.where(
-            isNull( person.email() )
-        ).newQuery( Network.persons() );
-        verifyUnorderedResults( query, "Ann Doe", "Jack Doe" );
-    }
-
-    @Test
-    public void givenIsNotNullOnMixinTypeWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
-        Male person = templateFor( Male.class );
-        Query<Person> query = qb.where(
-            isNotNull( person.wife() )
-        ).newQuery( Network.persons() );
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void givenIsNullOnMixinTypeWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Male> qb = qbf.newQueryBuilder( Male.class );
-        Male person = templateFor( Male.class );
-        Query<Male> query = qb.where(
-            isNull( person.wife() )
-        ).newQuery( Network.males() );
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void givenIsNullOnAssociationWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
-        Male person = templateFor( Male.class );
-        Query<Person> query = qb.where(
-            isNull( person.wife() )
-        ).newQuery( Network.persons() );
-        verifyUnorderedResults( query, "Joe Doe", "Ann Doe", "Vivian Smith" );
-    }
-
-    @Test
-    public void givenOrderAndMaxResultsQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Nameable> qb = qbf.newQueryBuilder( Nameable.class );
-        // should return only 2 entities
-        Nameable nameable = templateFor( Nameable.class );
-        Query<Nameable> query = qb.newQuery( Network.nameables() );
-        query.orderBy( orderBy( nameable.name() ) );
-        query.maxResults( 2 );
-        verifyOrderedResults(
-            query,
-            "Ann Doe", "Cars"
-        );
-    }
-
-    @Test
-    public void givenOrderAndFirstAndMaxResultsQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Nameable> qb = qbf.newQueryBuilder( Nameable.class );
-        // should return only 3 entities starting with forth one
-        Nameable nameable = templateFor( Nameable.class );
-        Query<Nameable> query = qb.newQuery( Network.nameables() );
-        query.orderBy( orderBy( nameable.name() ) );
-        query.firstResult( 3 );
-        query.maxResults( 3 );
-        verifyOrderedResults(
-            query,
-            "Gaming", "Jack Doe", "Joe Doe"
-        );
-    }
-
-    @Test
-    public void givenOrderByOnMixinTypeQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Nameable> qb = qbf.newQueryBuilder( Nameable.class );
-        // should return all Nameable entities sorted by name
-        Nameable nameable = templateFor( Nameable.class );
-        Query<Nameable> query = qb.newQuery( Network.nameables() );
-        query.orderBy( orderBy( nameable.name() ) );
-        verifyOrderedResults(
-            query,
-            "Ann Doe", "Cars", "Cooking", "Gaming", "Jack Doe", "Joe Doe", "Kuala Lumpur", "Penang", "Programming", "Vivian Smith"
-        );
-    }
-
-    @Test
-    public void givenGtAndOrderByQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Nameable> qb = qbf.newQueryBuilder( Nameable.class );
-        // should return all Nameable entities with a name > "D" sorted by name
-        Nameable nameable = templateFor( Nameable.class );
-        Query<Nameable> query = qb.where(
-            gt( nameable.name(), "D" )
-        ).newQuery( Network.nameables() );
-        query.orderBy( orderBy( nameable.name() ) );
-        verifyOrderedResults(
-            query,
-            "Gaming", "Jack Doe", "Joe Doe", "Kuala Lumpur", "Penang", "Programming", "Vivian Smith"
-        );
-    }
-
-    @Test
-    public void givenGtAndOrderByDescendingQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
-        // should return all Persons born after 1973 (Ann and Joe Doe) sorted descending by name
-        Person person = templateFor( Person.class );
-        Query<Person> query = qb.where(
-            gt( person.yearOfBirth(), 1973 )
-        ).newQuery( Network.persons() );
-        query.orderBy( orderBy( person.name(), OrderBy.Order.DESCENDING ) );
-        verifyOrderedResults( query, "Vivian Smith", "Joe Doe", "Ann Doe" );
-    }
-
-    @Test
-    public void givenOrderByMultipleQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
-        // should return all Persons sorted by name of the city they were born, and then by year they were born
-        Person person = templateFor( Person.class );
-        Query<Person> query = qb.newQuery( Network.persons() );
-        query.orderBy( orderBy( person.placeOfBirth().get().name() ),
-                       orderBy( person.yearOfBirth() ) );
-        verifyOrderedResults( query, "Ann Doe", "Joe Doe", "Vivian Smith", "Jack Doe" );
-    }
-
-    @Test
-    public void givenMatchesQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Nameable> qb = qbf.newQueryBuilder( Nameable.class );
-        Nameable nameable = templateFor( Nameable.class );
-        // should return Jack and Joe Doe
-        Query<Nameable> query = qb.where(
-            matches( nameable.name(), "J.*Doe" )
-        ).newQuery( Network.nameables() );
-        verifyUnorderedResults(
-            query,
-            "Jack Doe", "Joe Doe"
-        );
-    }
-
-    // TODO solve ManyAssociation filtering for iterables
-    // @Test
-    public void givenOneOfQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Domain interests = person.interests().get( 0 );
-        Query<Person> query = qb.where( eq( interests.name(), "Cars" ) ).newQuery( Network.persons() );
-        verifyOrderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void givenManyAssociationContainsQueryWhenExecutedThenReturnCorrect()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = qbf.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Domain value = Network.domains().iterator().next();
-        Query<Person> query = qb.where( QueryExpressions.contains( person.interests(), value ) )
-            .newQuery( Network.persons() );
-        for( Person person1 : query )
-        {
-            System.out.println( person1.name() );
-        }
-        verifyOrderedResults( query, "Joe Doe", "Vivian Smith" );
-    }
-
-    @Test
-    public void givenEntitiesWithInternalStateWhenQueriedThenReturnCorrect()
-    {
-        QueryBuilder<PetEntity> qb = qbf.newQueryBuilder( PetEntity.class );
-        Pet.PetState pet = templateFor( Pet.PetState.class );
-        Nameable petOwner = templateFor( Nameable.class, pet.owner() );
-        Query<PetEntity> query = qb.where( eq( petOwner.name(), "Jack Doe" ) ).newQuery( Network.pets() );
-        verifyOrderedResults( query, "Rex" );
-    }
-
-    @Test
-    public void givenEntitiesWithFieldPropertyByNameWhenQueriedThenReturnCorrect()
-    {
-        QueryBuilder<PetEntity> qb = qbf.newQueryBuilder( PetEntity.class );
-        Query<PetEntity> query = qb.where( eq( property( Describable.Mixin.class, "description" ), "Rex is a great dog" ) )
-            .newQuery( Network.pets() );
-        verifyOrderedResults( query, "Rex" );
-    }
-
-    @Test
-    public void givenEntitiesWithFieldPropertyWhenQueriedThenReturnCorrect()
-    {
-        QueryBuilder<PetEntity> qb = qbf.newQueryBuilder( PetEntity.class );
-        Query<PetEntity> query = qb.where( eq( templateFor( Describable.Mixin.class ).description, "Rex is a great dog" ) )
-            .newQuery( Network.pets() );
-        verifyOrderedResults( query, "Rex" );
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/Network.java b/core/runtime/src/test/java/org/qi4j/runtime/query/Network.java
deleted file mode 100644
index abe68b2..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/Network.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.runtime.query;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.runtime.query.model.City;
-import org.qi4j.runtime.query.model.Domain;
-import org.qi4j.runtime.query.model.Female;
-import org.qi4j.runtime.query.model.Male;
-import org.qi4j.runtime.query.model.Nameable;
-import org.qi4j.runtime.query.model.Person;
-import org.qi4j.runtime.query.model.entities.FemaleEntity;
-import org.qi4j.runtime.query.model.entities.MaleEntity;
-import org.qi4j.runtime.query.model.entities.PetEntity;
-import org.qi4j.runtime.query.model.values.ContactValue;
-import org.qi4j.runtime.query.model.values.ContactsValue;
-
-/**
- * JAVADOC Add JavaDoc
- */
-class Network
-{
-    private static List<Domain> domains;
-    private static List<Person> persons;
-    private static List<Male> males;
-    private static List<Female> females;
-    private static List<PetEntity> pets;
-    private static List<Nameable> nameables;
-
-    static void populate( final UnitOfWork uow, ValueBuilderFactory vbf )
-        throws UnitOfWorkCompletionException
-    {
-        domains = new ArrayList<Domain>();
-        persons = new ArrayList<Person>();
-        males = new ArrayList<Male>();
-        females = new ArrayList<Female>();
-        pets = new ArrayList<PetEntity>();
-        nameables = new ArrayList<Nameable>();
-
-        Domain gaming = uow.newEntity( Domain.class );
-        setName( gaming, "Gaming" );
-        gaming.description().set( "Gaming domain" );
-
-        Domain programming = uow.newEntity( Domain.class );
-        setName( programming, "Programming" );
-        programming.description().set( "Programing domain" );
-
-        Domain cooking = uow.newEntity( Domain.class );
-        setName( cooking, "Cooking" );
-        cooking.description().set( "Cooking domain" );
-
-        Domain cars = uow.newEntity( Domain.class );
-        setName( cars, "Cars" );
-        cars.description().set( "Cars" );
-
-        City kualaLumpur = uow.newEntity( City.class, "kualalumpur" );
-        setName( kualaLumpur, "Kuala Lumpur" );
-        kualaLumpur.country().set( "Malaysia" );
-        kualaLumpur.county().set( "Some Jaya" );
-
-        City penang = uow.newEntity( City.class, "penang" );
-        setName( penang, "Penang" );
-        penang.country().set( "Malaysia" );
-        penang.county().set( "Some Other Jaya" );
-
-        Female vivianSmith = uow.newEntity( FemaleEntity.class );
-        setName( vivianSmith, "Vivian Smith" );
-        vivianSmith.placeOfBirth().set( kualaLumpur );
-        vivianSmith.yearOfBirth().set( 1992 );
-        vivianSmith.interests().add( 0, gaming );
-        vivianSmith.interests().add( 0, programming );
-        vivianSmith.email().set( "viv@smith.edu" );
-        List<String> vivianTags = new ArrayList<String>();
-        vivianTags.add( "Awesome" );
-        vivianTags.add( "Pretty" );
-        vivianTags.add( "Cool" );
-        vivianSmith.tags().set( vivianTags );
-
-        Female annDoe = uow.newEntity( FemaleEntity.class );
-        setName( annDoe, "Ann Doe" );
-        annDoe.placeOfBirth().set( kualaLumpur );
-        annDoe.yearOfBirth().set( 1975 );
-        annDoe.interests().add( 0, cooking );
-        List<String> annTags = new ArrayList<String>();
-        annTags.add( "Conservative" );
-        annTags.add( "Pretty" );
-        annDoe.tags().set( annTags );
-
-        Male joeDoe = uow.newEntity( MaleEntity.class );
-        setName( joeDoe, "Joe Doe" );
-        joeDoe.placeOfBirth().set( kualaLumpur );
-        joeDoe.yearOfBirth().set( 1990 );
-        joeDoe.mother().set( annDoe );
-        joeDoe.pastGirlFriends().add( 0, annDoe );
-        joeDoe.interests().add( 0, programming );
-        joeDoe.interests().add( 0, gaming );
-        joeDoe.email().set( "joe@thedoes.net" );
-        List<String> joeTags = new ArrayList<String>();
-        joeTags.add( "Cool" );
-        joeTags.add( "Hunk" );
-        joeTags.add( "Awesome" );
-        joeDoe.tags().set( joeTags );
-
-        Male jackDoe = uow.newEntity( MaleEntity.class );
-        setName( jackDoe, "Jack Doe" );
-        jackDoe.placeOfBirth().set( penang );
-        jackDoe.yearOfBirth().set( 1970 );
-        jackDoe.interests().add( 0, cars );
-        jackDoe.wife().set( annDoe );
-        List<String> jackTags = new ArrayList<String>();
-        jackTags.add( "Conservative" );
-        jackTags.add( "Awesome" );
-        jackDoe.tags().set( jackTags );
-
-        ValueBuilder<ContactsValue> builder = vbf.newValueBuilder( ContactsValue.class );
-        ValueBuilder<ContactValue> contactBuilder = vbf.newValueBuilder( ContactValue.class );
-        contactBuilder.prototype().email().set( "jackdoe@someplace.com" );
-        contactBuilder.prototype().phone().set( "555-1234" );
-        builder.prototype().contacts().get().add( contactBuilder.newInstance() );
-        jackDoe.contacts().set( builder.newInstance() );
-
-        annDoe.husband().set( jackDoe );
-
-        PetEntity rex = uow.newEntity( PetEntity.class );
-        setName( rex, "Rex" );
-        rex.changeOwner( jackDoe );
-        rex.updateDescription( "Rex is a great dog" );
-
-        PetEntity kitty = uow.newEntity( PetEntity.class );
-        setName( kitty, "Kitty" );
-        kitty.changeOwner( annDoe );
-
-        domains.add( gaming );
-        domains.add( programming );
-        domains.add( cooking );
-        domains.add( cars );
-
-        persons.add( annDoe );
-        persons.add( joeDoe );
-        persons.add( jackDoe );
-        persons.add( vivianSmith );
-
-        females.add( annDoe );
-        females.add( vivianSmith );
-
-        males.add( joeDoe );
-        males.add( jackDoe );
-
-        pets.add( rex );
-        pets.add( kitty );
-
-        nameables.add( gaming );
-        nameables.add( programming );
-        nameables.add( cooking );
-        nameables.add( cars );
-        nameables.add( kualaLumpur );
-        nameables.add( penang );
-        nameables.add( annDoe );
-        nameables.add( joeDoe );
-        nameables.add( jackDoe );
-        nameables.add( vivianSmith );
-    }
-
-    static void refresh( UnitOfWork uow )
-    {
-        refresh( uow, domains );
-        refresh( uow, persons );
-        refresh( uow, males );
-        refresh( uow, females );
-        refresh( uow, pets );
-        refresh( uow, nameables );
-    }
-
-    private static <T> void refresh( UnitOfWork uow, List<T> list )
-    {
-        for( int i = 0; i < list.size(); i++ )
-        {
-            T entity = list.get( i );
-            list.set( i, uow.get( entity ) );
-        }
-    }
-
-    static Iterable<Domain> domains()
-    {
-        return domains;
-    }
-
-    static Iterable<Person> persons()
-    {
-        return persons;
-    }
-
-    static Iterable<Nameable> nameables()
-    {
-        return nameables;
-    }
-
-    static Iterable<Male> males()
-    {
-        return males;
-    }
-
-    static Iterable<Female> females()
-    {
-        return females;
-    }
-
-    static Iterable<PetEntity> pets()
-    {
-        return pets;
-    }
-
-    private static void setName( Nameable nameable, String name )
-    {
-        nameable.name().set( name );
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/NonQueryableTest.java b/core/runtime/src/test/java/org/qi4j/runtime/query/NonQueryableTest.java
deleted file mode 100644
index 85b4a8c..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/NonQueryableTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.query;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.QueryException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.qi4j.api.query.QueryExpressions.eq;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-public class NonQueryableTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-    }
-
-    @Test
-    public void whenQuerableIsFalseOnPropertyThenExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            QueryBuilder<Abc> builder = module.newQueryBuilder( Abc.class );
-            Abc proto = templateFor( Abc.class );
-            builder.where( eq( proto.isValid(), Boolean.TRUE ) );
-            Assert.fail( "Exception was expected." );
-        }
-        catch( QueryException e )
-        {
-            // expected!!
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    @Test
-    public void testQueryIterable()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            module.newQueryBuilder( Abc2.class );
-            Assert.fail( "Exception was expected." );
-        }
-        catch( QueryException e )
-        {
-            // expected!!
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    static interface Abc
-    {
-        @Queryable( false )
-        Property<Boolean> isValid();
-    }
-
-    @Queryable( false )
-    public interface Abc2
-    {
-        Property<Boolean> isValid();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/QueryBuilderFactoryImplTest.java b/core/runtime/src/test/java/org/qi4j/runtime/query/QueryBuilderFactoryImplTest.java
deleted file mode 100644
index 1291a96..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/QueryBuilderFactoryImplTest.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.query;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.api.query.QueryExpressions.and;
-import static org.qi4j.api.query.QueryExpressions.ge;
-import static org.qi4j.api.query.QueryExpressions.lt;
-import static org.qi4j.api.query.QueryExpressions.orderBy;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-/**
- * JAVADOC
- */
-public class QueryBuilderFactoryImplTest
-    extends AbstractQi4jTest
-{
-    private List<TestComposite> composites;
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TestComposite.class );
-    }
-
-    @Before
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        composites = new ArrayList<TestComposite>();
-        composites.add( newInstance( "A", 6 ) );
-        composites.add( newInstance( "B", 2 ) );
-        composites.add( newInstance( "C", 3 ) );
-        composites.add( newInstance( "C", 4 ) );
-        composites.add( newInstance( "E", 5 ) );
-        composites.add( newInstance( "A", 1 ) );
-    }
-
-    @Test
-    public void givenPlainQueryWhenFindEntityExpectFirstEntityReturned()
-    {
-        Query<TestComposite> query = module.newQueryBuilder( TestComposite.class ).newQuery( composites );
-        assertEquals( "A", query.find().a().get() );
-        assertEquals( 6, query.count() );
-    }
-
-    @Test
-    public void givenPlainQueryWhenOrderByFirstPropertyExpectOrderedResult()
-    {
-        Query<TestComposite> query = module.newQueryBuilder( TestComposite.class ).newQuery( composites );
-        TestComposite template = templateFor( TestComposite.class );
-        query.orderBy( orderBy( template.a() ) );
-        verifyOrder( query, "612345" );
-    }
-
-    @Test
-    public void givenPlainQueryWhenOrderBySecondPropertyExpectOrderedResult()
-    {
-        Query<TestComposite> query = module.newQueryBuilder( TestComposite.class ).newQuery( composites );
-        TestComposite template = templateFor( TestComposite.class );
-        query.orderBy( orderBy( template.b() ) );
-        verifyOrder( query, "123456" );
-    }
-
-    @Test
-    public void givenPlainQueryWhenOrderByTwoPropertiesExpectOrderedResult()
-    {
-        Query<TestComposite> query = module.newQueryBuilder( TestComposite.class ).newQuery( composites );
-        TestComposite template = templateFor( TestComposite.class );
-        query.orderBy( orderBy( template.a() ), orderBy( template.b() ) );
-        verifyOrder( query, "162345" );
-    }
-
-    @Test
-    public void givenPlainQueryWhenMaxedResultExpectLimitedResult()
-    {
-        Query<TestComposite> query = module.newQueryBuilder( TestComposite.class ).newQuery( composites );
-        query.maxResults( 5 );
-        verifyOrder( query, "62345" );
-    }
-
-    @Test
-    public void givenPlainQueryWhenFirstResultIsBeyondFirstElementExpectLimitedResult()
-    {
-        Query<TestComposite> query = module.newQueryBuilder( TestComposite.class ).newQuery( composites );
-        query.firstResult( 2 );
-        verifyOrder( query, "3451" );
-    }
-
-    @Test
-    public void givenWhereQueryWhenWhereClauseLimitsToRangeExpectLimitedResult()
-    {
-        final QueryBuilder<TestComposite> qb = module.newQueryBuilder( TestComposite.class );
-        TestComposite template = templateFor( TestComposite.class );
-        Query<TestComposite> query = qb.where(
-            and(
-                ge( template.b(), 3 ),
-                lt( template.b(), 5 )
-            )
-        ).newQuery( composites );
-        verifyOrder( query, "34" );
-    }
-
-    private void verifyOrder( Query<TestComposite> query, String expected )
-    {
-        String actual = "";
-        for( TestComposite testComposite : query )
-        {
-            actual = actual + testComposite.b().get();
-        }
-
-        assertThat( "Query is correct", actual, equalTo( expected ) );
-        assertThat( "Count is correct", query.count(), equalTo( (long) expected.length() ) );
-    }
-
-    private TestComposite newInstance( String a, int b )
-    {
-        TransientBuilder<TestComposite> builder =
-            module.newTransientBuilder( TestComposite.class );
-        TestComposite instance = builder.prototype();
-        instance.a().set( a );
-        instance.b().set( b );
-        return builder.newInstance();
-    }
-
-    public interface TestComposite
-        extends TransientComposite
-    {
-        Property<String> a();
-
-        Property<Integer> b();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/model/Alive.java b/core/runtime/src/test/java/org/qi4j/runtime/query/model/Alive.java
deleted file mode 100644
index 6766d67..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/model/Alive.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.runtime.query.model;
-
-public interface Alive
-{
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/model/City.java b/core/runtime/src/test/java/org/qi4j/runtime/query/model/City.java
deleted file mode 100644
index 5a4586e..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/model/City.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.runtime.query.model;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-
-public interface City
-    extends Nameable
-{
-    @Optional
-    Property<String> country();
-
-    @Optional
-    Property<String> county();
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/model/Describable.java b/core/runtime/src/test/java/org/qi4j/runtime/query/model/Describable.java
deleted file mode 100644
index b1ca88f..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/model/Describable.java
+++ /dev/null
@@ -1,55 +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.qi4j.runtime.query.model;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.injection.scope.State;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-
-/**
- * TODO
- */
-@Mixins( Describable.Mixin.class )
-public interface Describable
-{
-    String getDescription();
-
-    void updateDescription( String newDescription );
-
-    class Mixin
-        implements Describable
-    {
-        @State
-        @UseDefaults
-        public Property<String> description;
-
-        @Override
-        public String getDescription()
-        {
-            return description.get();
-        }
-
-        @Override
-        public void updateDescription( String newDescription )
-        {
-            description.set( newDescription );
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/model/Domain.java b/core/runtime/src/test/java/org/qi4j/runtime/query/model/Domain.java
deleted file mode 100644
index 6edf38f..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/model/Domain.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.runtime.query.model;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-
-public interface Domain
-    extends Nameable
-{
-    @Optional
-    Property<String> description();
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/model/Female.java b/core/runtime/src/test/java/org/qi4j/runtime/query/model/Female.java
deleted file mode 100644
index 60ab165..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/model/Female.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.runtime.query.model;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.Optional;
-
-public interface Female
-    extends Person
-{
-    @Optional
-    Association<Male> husband();
-
-    @Optional
-    ManyAssociation<Male> pastBoyFriends();
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/model/Male.java b/core/runtime/src/test/java/org/qi4j/runtime/query/model/Male.java
deleted file mode 100644
index d51ecb3..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/model/Male.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.query.model;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.Optional;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface Male
-    extends Person
-{
-    @Optional
-    Association<Female> wife();
-
-    @Optional
-    ManyAssociation<Female> pastGirlFriends();
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/model/Nameable.java b/core/runtime/src/test/java/org/qi4j/runtime/query/model/Nameable.java
deleted file mode 100644
index 87834a7..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/model/Nameable.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.runtime.query.model;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-
-public interface Nameable
-{
-    @Optional
-    Property<String> name();
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/model/Person.java b/core/runtime/src/test/java/org/qi4j/runtime/query/model/Person.java
deleted file mode 100644
index d8dab13..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/model/Person.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.runtime.query.model;
-
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-import org.qi4j.runtime.query.model.values.ContactsValue;
-
-public interface Person
-    extends Nameable, Alive
-{
-    @Optional
-    Association<City> placeOfBirth();
-
-    @Optional
-    Property<Integer> yearOfBirth();
-
-    @Optional
-    Association<Female> mother();
-
-    @Optional
-    Association<Male> father();
-
-    @Optional
-    ManyAssociation<Domain> interests();
-
-    @Optional
-    Property<String> email();
-
-    @Optional
-    Property<Map<Date, String>> datesToRemember();
-
-    @Optional
-    Property<List<String>> tags();
-
-    @Optional
-    Property<ContactsValue> contacts();
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/model/Pet.java b/core/runtime/src/test/java/org/qi4j/runtime/query/model/Pet.java
deleted file mode 100644
index c0f16b6..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/model/Pet.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.query.model;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-
-/**
- * Test traversal over internal interfaces.
- */
-@Mixins( Pet.PetMixin.class )
-public interface Pet
-{
-    void changeOwner( Person owner );
-
-    interface PetState
-    {
-        @Optional
-        Association<Person> owner();
-    }
-
-    class PetMixin
-        implements Pet
-    {
-        @This
-        PetState state;
-
-        public void changeOwner( Person owner )
-        {
-            state.owner().set( owner );
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/CityEntity.java b/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/CityEntity.java
deleted file mode 100644
index 541c414..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/CityEntity.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.runtime.query.model.entities;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.runtime.query.model.City;
-
-public interface CityEntity
-    extends City, EntityComposite
-{
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/DomainEntity.java b/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/DomainEntity.java
deleted file mode 100644
index 6781d98..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/DomainEntity.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.runtime.query.model.entities;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.runtime.query.model.Domain;
-
-public interface DomainEntity
-    extends Domain, EntityComposite
-{
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/FemaleEntity.java b/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/FemaleEntity.java
deleted file mode 100644
index 4fb2ff9..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/FemaleEntity.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.runtime.query.model.entities;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.runtime.query.model.Female;
-
-public interface FemaleEntity
-    extends Female, EntityComposite
-{
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/MaleEntity.java b/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/MaleEntity.java
deleted file mode 100644
index 640d515..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/MaleEntity.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.runtime.query.model.entities;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.runtime.query.model.Male;
-
-public interface MaleEntity
-    extends Male, EntityComposite
-{
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/PersonEntity.java b/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/PersonEntity.java
deleted file mode 100644
index 22db3ea..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/PersonEntity.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.runtime.query.model.entities;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.runtime.query.model.Person;
-
-public interface PersonEntity
-    extends Person, EntityComposite
-{
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/PetEntity.java b/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/PetEntity.java
deleted file mode 100644
index c3f88dc..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/model/entities/PetEntity.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.query.model.entities;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.runtime.query.model.Describable;
-import org.qi4j.runtime.query.model.Nameable;
-import org.qi4j.runtime.query.model.Pet;
-
-/**
- * JAVADOC
- */
-public interface PetEntity
-    extends Pet, Nameable, Describable, EntityComposite
-{
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/model/values/ContactValue.java b/core/runtime/src/test/java/org/qi4j/runtime/query/model/values/ContactValue.java
deleted file mode 100644
index 165ee65..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/model/values/ContactValue.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.query.model.values;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * JAVADOC
- */
-public interface ContactValue
-    extends ValueComposite
-{
-    Property<String> email();
-
-    Property<String> phone();
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/query/model/values/ContactsValue.java b/core/runtime/src/test/java/org/qi4j/runtime/query/model/values/ContactsValue.java
deleted file mode 100644
index 52fd41c..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/query/model/values/ContactsValue.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.query.model.values;
-
-import java.util.List;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * JAVADOC
- */
-public interface ContactsValue
-    extends ValueComposite
-{
-    @UseDefaults
-    Property<List<ContactValue>> contacts();
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/service/ActivatableServiceTest.java b/core/runtime/src/test/java/org/qi4j/runtime/service/ActivatableServiceTest.java
deleted file mode 100644
index 86ca1d5..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/service/ActivatableServiceTest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.service;
-
-import org.junit.Test;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Test of activatable services
- */
-public class ActivatableServiceTest
-{
-    @Service
-    ServiceReference<ActivatableComposite> service;
-
-    public static boolean isActive;
-
-    @Test
-    public void testActivatable()
-        throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.objects( ActivatableServiceTest.class );
-                module.services( ActivatableComposite.class ).withActivators( TestActivator.class).instantiateOnStartup();
-            }
-        };
-
-        assertTrue( isActive );
-
-        assembly.module().injectTo( this );
-
-        assertTrue( isActive );
-
-        service.get();
-
-        assertTrue( isActive );
-
-        assembly.application().passivate();
-
-        assertFalse( isActive );
-    }
-
-    public static interface ActivatableComposite
-        extends ServiceComposite
-    {
-    }
-
-    public static class TestActivator
-            extends org.qi4j.api.activation.ActivatorAdapter<Object>
-    {
-
-        @Override
-        public void afterActivation( Object activated )
-        {
-            isActive = true;
-        }
-
-        @Override
-        public void afterPassivation( Object passivated )
-                throws Exception
-        {
-            if ( !isActive ) {
-                throw new Exception( "Not active!" );
-            }
-
-            isActive = false;
-        }
-
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/service/AvailableServiceTest.java b/core/runtime/src/test/java/org/qi4j/runtime/service/AvailableServiceTest.java
deleted file mode 100644
index 46ab9e2..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/service/AvailableServiceTest.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.service;
-
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.configuration.Enabled;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.Availability;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.service.qualifier.Available;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.assertThat;
-
-/**
- * JAVADOC
- */
-public class AvailableServiceTest
-{
-    @Test
-    public void givenAvailableServiceWhenCheckServiceReferenceThenReturnTrue()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.services( TestServiceComposite1.class );
-            }
-        };
-
-        ServiceReference<TestServiceComposite1> serviceRef = assembler.module()
-            .findService( TestServiceComposite1.class );
-
-        assertThat( "service is available", serviceRef.isAvailable(), equalTo( true ) );
-    }
-
-    @Test
-    public void givenEnablableServiceWhenCheckAvailableThenReturnEnabledStatus()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.services( TestServiceComposite2.class );
-                module.entities( TestServiceConfiguration.class );
-
-                new EntityTestAssembler().assemble( module );
-            }
-        };
-
-        ServiceReference<TestServiceComposite2> serviceRef = assembler.module()
-            .findService( TestServiceComposite2.class );
-
-        assertThat( "service is unavailable", serviceRef.isAvailable(), equalTo( false ) );
-
-        serviceRef.get().get().enabled().set( true );
-        serviceRef.get().save();
-
-        assertThat( "service is available", serviceRef.isAvailable(), equalTo( true ) );
-    }
-
-    @Test
-    public void givenEnablableServiceWhenInjectWithAvailableQualifierThenInjectCorrectly()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.objects( TestObject.class );
-                module.services( TestServiceComposite2.class );
-                module.entities( TestServiceConfiguration.class );
-
-                new EntityTestAssembler().assemble( module );
-            }
-        };
-
-        TestObject object = assembler.module().newObject( TestObject.class );
-
-        assertThat( "service is unavailable", object.getService(), nullValue() );
-
-        ServiceReference<TestServiceComposite2> serviceRef = assembler.module()
-            .findService( TestServiceComposite2.class );
-        serviceRef.get().get().enabled().set( true );
-        serviceRef.get().save();
-
-        object = assembler.module().newObject( TestObject.class );
-        assertThat( "service is available", object.getService(), notNullValue() );
-    }
-
-    // This service has to be asked for availability
-    @Mixins( TestMixin1.class )
-    public interface TestServiceComposite1
-        extends TestService, Availability, ServiceComposite
-    {
-    }
-
-    // This service has availability set through configuration
-    @Mixins( TestMixin2.class )
-    public interface TestServiceComposite2
-        extends TestService, Configuration<TestServiceConfiguration>, ServiceComposite
-    {
-    }
-
-    public interface TestServiceConfiguration
-        extends Enabled, ConfigurationComposite
-    {
-    }
-
-    public interface TestService
-    {
-        String test();
-    }
-
-    public static class TestMixin1
-        implements TestService, Availability
-    {
-        public String test()
-        {
-            return "mixin1";
-        }
-
-        public boolean isAvailable()
-        {
-            return true;
-        }
-    }
-
-    public static class TestMixin2
-        implements TestService
-    {
-        @This
-        Configuration<TestServiceConfiguration> config;
-
-        public String test()
-        {
-            return "mixin2";
-        }
-    }
-
-    public static class TestObject
-    {
-        @Service
-        @Optional
-        @Available
-        TestService service;
-
-        public TestService getService()
-        {
-            return service;
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/service/ComplexActivatableTest.java b/core/runtime/src/test/java/org/qi4j/runtime/service/ComplexActivatableTest.java
deleted file mode 100644
index 6fbc12a..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/service/ComplexActivatableTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2010, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.service;
-
-import org.junit.Test;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Initializable;
-import org.qi4j.api.mixin.InitializationException;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-
-public class ComplexActivatableTest
-        extends AbstractQi4jTest
-{
-
-    public void assemble( ModuleAssembly module )
-            throws AssemblyException
-    {
-        module.services( SuperType.class ).withActivators( TestActivator.class ).instantiateOnStartup();
-    }
-
-    @Test
-    public void validateThatApplicationGotAssembled()
-    {
-        ServiceReference<SuperType> reference = module.findService( SuperType.class );
-        assertEquals( "Hello, World", reference.get().sayHello() );
-    }
-
-    @Mixins( { DomainType.class, InitializationMixin.class } )
-    public interface SuperType
-            extends ServiceComposite, Initializable
-    {
-
-        String sayHello();
-
-        Property<String> greeting();
-
-        Property<String> recepient();
-
-    }
-
-    public abstract static class DomainType
-            implements SuperType
-    {
-
-        public String sayHello()
-        {
-            return greeting().get() + ", " + recepient().get();
-        }
-
-    }
-
-    public static class InitializationMixin
-            implements Initializable
-    {
-
-        @This
-        private SuperType me;
-
-        public void initialize()
-                throws InitializationException
-        {
-            me.greeting().set( "Hello" );
-        }
-
-    }
-
-    public static class TestActivator
-            extends ActivatorAdapter<ServiceReference<SuperType>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<SuperType> activated )
-                throws Exception
-        {
-            activated.get().recepient().set( "World" );
-        }
-
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/service/ConfigurationTest.java b/core/runtime/src/test/java/org/qi4j/runtime/service/ConfigurationTest.java
deleted file mode 100644
index 4d6b25e..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/service/ConfigurationTest.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.service;
-
-import org.junit.Test;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test of configuration for services
- */
-public class ConfigurationTest
-    extends AbstractQi4jTest
-{
-    @Service
-    ServiceReference<HelloWorldService> service;
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.objects( this.getClass() );
-        module.entities( HelloWorldConfiguration.class );
-        module.services( HelloWorldService.class ).identifiedBy( "HelloWorldService" );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Test
-    public void whenConfiguredThenSayHelloWorks()
-        throws Exception
-    {
-        module.injectTo( this );
-
-        UnitOfWork unit = module.newUnitOfWork();
-        EntityBuilder<HelloWorldConfiguration> entityBuilder = unit.newEntityBuilder( HelloWorldConfiguration.class, service
-            .identity() );
-        HelloWorldConfiguration config = entityBuilder.instance();
-        config.phrase().set( "Hey" );
-        config.name().set( "Universe" );
-        entityBuilder.newInstance();
-        unit.complete();
-
-        assertThat( "result is correct", service.get().sayHello(), equalTo( "Hey Universe" ) );
-    }
-
-    @Test
-    public void whenUnconfiguredThenSayHelloGivesDefaults()
-        throws Exception
-    {
-        module.injectTo( this );
-
-        assertThat( "result is correct", service.get().sayHello(), equalTo( "Hello World" ) );
-    }
-
-    @Test
-    public void givenConfiguredServiceWhenReconfiguredAndRefreshedThenNewConfigurationIsUsed()
-        throws Exception
-    {
-        module.injectTo( this );
-
-        HelloWorldConfiguration config;
-
-        {
-            UnitOfWork unit = module.newUnitOfWork();
-            EntityBuilder<HelloWorldConfiguration> entityBuilder = unit.newEntityBuilder( HelloWorldConfiguration.class, service
-                .identity() );
-            config = entityBuilder.instance();
-            config.phrase().set( "Hello" );
-            config.name().set( "World" );
-            config = entityBuilder.newInstance();
-            unit.complete();
-        }
-
-        assertThat( "result is correct", service.get().sayHello(), equalTo( "Hello World" ) );
-
-        {
-            UnitOfWork unit = module.newUnitOfWork();
-            config = unit.get( config );
-            config.phrase().set( "Hey" );
-            config.name().set( "Universe" );
-            unit.complete();
-        }
-
-        assertThat( "new configuration is not used", service.get().sayHello(), equalTo( "Hello World" ) );
-
-        service.get().refresh();
-
-        assertThat( "new configuration is used", service.get().sayHello(), equalTo( "Hey Universe" ) );
-    }
-
-    public interface HelloWorld
-    {
-        String sayHello();
-    }
-
-    @Mixins( HelloWorldMixin.class )
-    public interface HelloWorldService
-        extends HelloWorld, ServiceComposite, Configuration
-    {
-    }
-
-    public interface HelloWorldConfiguration
-        extends ConfigurationComposite
-    {
-        @UseDefaults
-        Property<String> phrase();
-
-        @UseDefaults
-        Property<String> name();
-    }
-
-    public static class HelloWorldMixin
-        implements HelloWorld
-    {
-        @This
-        Configuration<HelloWorldConfiguration> config;
-
-        public String sayHello()
-        {
-            return config.get().phrase() + " " + config.get().name();
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/service/LazyActivatedServiceTest.java b/core/runtime/src/test/java/org/qi4j/runtime/service/LazyActivatedServiceTest.java
deleted file mode 100644
index e8e9b83..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/service/LazyActivatedServiceTest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.service;
-
-import junit.framework.TestCase;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-/**
- * Test of lazily activated services
- */
-public class LazyActivatedServiceTest
-    extends TestCase
-{
-    @Service
-    ServiceReference<MyService> service;
-
-    public static boolean isActive;
-
-    public void testActivatable()
-        throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.objects( LazyActivatedServiceTest.class );
-                module.services( LazyActivatedServiceTest.MyServiceComposite.class ).withActivators( TestActivator.class );
-            }
-        };
-
-        assertFalse( isActive );
-
-        assembly.module().injectTo( this );
-
-        assertFalse( isActive );
-
-        service.get();
-
-        assertFalse( isActive );
-
-        service.get().doStuff();
-
-        assertTrue( isActive );
-
-        assembly.application().passivate();
-
-        assertFalse( isActive );
-    }
-
-    @Mixins( { MyServiceMixin.class } )
-    public static interface MyServiceComposite
-        extends MyService, ServiceComposite
-    {
-    }
-
-    public static interface MyService
-    {
-        String doStuff();
-    }
-
-    public static class MyServiceMixin
-        implements MyService
-    {
-
-        public String doStuff()
-        {
-            return "X";
-        }
-    }
-
-    public static class TestActivator
-            extends ActivatorAdapter<Object>
-    {
-
-        @Override
-        public void afterActivation( Object activated )
-        {
-            isActive = true;
-        }
-
-        @Override
-        public void afterPassivation( Object passivated )
-                throws Exception
-        {
-            if ( !isActive ) {
-                throw new Exception( "Not active!" );
-            }
-
-            isActive = false;
-        }
-
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/service/PassivationTest.java b/core/runtime/src/test/java/org/qi4j/runtime/service/PassivationTest.java
deleted file mode 100644
index 0dd2627..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/service/PassivationTest.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.runtime.service;
-
-import java.util.ArrayList;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.PassivationException;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-public class PassivationTest
-{
-
-    @Test
-    public void givenSuccessPassivationWhenPassivatingExpectNoExceptions()
-        throws Throwable
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
-                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
-            }
-        };
-
-        Iterable<ServiceReference<DataAccess>> iterable = assembly.module().findServices( DataAccess.class );
-        for( ServiceReference<DataAccess> service : iterable )
-        {
-            assertTrue( "Service should not be Active before accessed", !service.isActive() );
-            assertTrue( service.get().data().activated );
-            assertTrue( "Service should be Active after access.", service.isActive() );
-        }
-        assembly.application().passivate();
-    }
-
-    @Test
-    public void givenMixedSuccessFailurePassivationWhenPassivatingExpectAllPassivateMethodsToBeCalled()
-        throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
-                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
-                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
-                module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
-                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
-                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
-                module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
-                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
-                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
-                module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
-                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
-                module.addServices( DataAccessService.class ).withActivators( PassivationSuccessActivator.class );
-                module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
-            }
-        };
-
-        ArrayList<Data> datas = new ArrayList<Data>();
-
-        Iterable<ServiceReference<DataAccess>> iterable = assembly.module().findServices( DataAccess.class );
-        for( ServiceReference<DataAccess> service : iterable )
-        {
-            assertTrue( "Service should not be Active before accessed", !service.isActive() );
-            Data data = service.get().data();
-            if( DataAccessService.class.isInstance( service.get() ) )
-            {
-                // Collect the expected successes.
-                datas.add( data );
-            }
-            assertTrue( "Data should indicate that the service is activated", data.activated );
-            assertTrue( "Service should be Active after access.", service.isActive() );
-        }
-        try
-        {
-            assembly.application().passivate();
-            fail( "PassivationException should have been thrown." );
-        }
-        catch( PassivationException e )
-        {
-            // Expected
-        }
-
-        // Still ensure that all services have been shutdown.
-        for( ServiceReference<DataAccess> service : iterable )
-        {
-            assertFalse( "All services should have been shutdown", service.isActive() );
-        }
-    }
-
-    @Test(expected = PassivationException.class)
-    public void givenMultipleFailingPassivationWhenPassivatingExpectPassivationExceptionToBubbleUp()
-        throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
-                module.addServices( DataAccessService.class ).withActivators( PassivationFailureActivator.class );
-            }
-        };
-
-        Iterable<ServiceReference<DataAccess>> iterable = assembly.module().findServices( DataAccess.class );
-        for( ServiceReference<DataAccess> service : iterable )
-        {
-            assertTrue( "Service should not be Active before accessed", !service.isActive() );
-            assertTrue( service.get().data().activated );
-            assertTrue( "Service should be Active after access.", service.isActive() );
-        }
-        assembly.application().passivate();
-    }
-
-    @Mixins(DataAccessMixin.class)
-    public interface DataAccessService
-        extends DataAccess, ServiceComposite
-    {
-    }
-
-    public interface DataAccess
-    {
-        Data data();
-    }
-
-    public static class DataAccessMixin
-        implements DataAccess
-    {
-        Data data = new Data();
-
-        public Data data()
-        {
-            return data;
-        }
-    }
-
-    public static class PassivationSuccessActivator
-        extends ActivatorAdapter<ServiceReference<DataAccess>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<DataAccess> activated )
-            throws Exception
-        {
-            activated.get().data().activated = true;
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<DataAccess> passivating )
-            throws Exception
-        {
-            passivating.get().data().activated = false;
-        }
-    }
-
-    public static class PassivationFailureActivator
-        extends ActivatorAdapter<ServiceReference<DataAccess>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<DataAccess> activated )
-            throws Exception
-        {
-            activated.get().data().activated = true;
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<DataAccess> passivating )
-            throws Exception
-        {
-            throw new IllegalStateException();
-        }
-    }
-
-    public static class Data
-    {
-        boolean activated = false;
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/service/ServiceFinderTest.java b/core/runtime/src/test/java/org/qi4j/runtime/service/ServiceFinderTest.java
deleted file mode 100644
index 09d6fdb..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/service/ServiceFinderTest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.service;
-
-import org.junit.Test;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertThat;
-
-public class ServiceFinderTest extends AbstractQi4jTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( CompileTimeService.class );
-        module.services( RuntimeService.class )
-            .withTypes( MyRuntimeService.class )
-            .withMixins( MyRuntimeServiceMixin.class );
-    }
-
-    @Test
-    public void givenServiceCompileTimeWeavingWhenFindingServiceBySuperTypeExceptServiceToBeFound()
-    {
-        ServiceReference<MyCompileTimeService> service = module.findService( MyCompileTimeService.class );
-        assertThat( service, notNullValue() );
-        assertThat( service.get(), notNullValue() );
-        assertThat( service.get().doSomething(), equalTo( "Niclas" ) );
-    }
-
-    @Test
-    public void givenServiceRuntimeWeavingWhenFindingServiceBySuperTypeExceptServiceToBeFound()
-    {
-        ServiceReference<MyRuntimeService> service = module.findService( MyRuntimeService.class );
-        assertThat( service, notNullValue() );
-        assertThat( service.get(), notNullValue() );
-        assertThat( service.get().doSomething(), equalTo( "Niclas" ) );
-    }
-
-    @Mixins( MyCompileTimeServiceMixin.class )
-    public interface MyCompileTimeService
-    {
-        String doSomething();
-    }
-
-    public interface MyRuntimeService
-    {
-        String doSomething();
-    }
-
-    public class MyCompileTimeServiceMixin
-        implements MyCompileTimeService
-    {
-
-        @Override
-        public String doSomething()
-        {
-            return "Niclas";
-        }
-    }
-
-    public class MyRuntimeServiceMixin
-        implements MyRuntimeService
-    {
-
-        @Override
-        public String doSomething()
-        {
-            return "Niclas";
-        }
-    }
-
-    @Mixins( CompileTimeServiceMixin.class )
-    public interface CompileTimeService extends MyCompileTimeService
-    {
-        String anotherMethod();
-    }
-
-    @Mixins( RuntimeServiceMixin.class )
-    public interface RuntimeService
-    {
-        String anotherMethod();
-    }
-
-    public abstract class CompileTimeServiceMixin
-        implements CompileTimeService
-    {
-        @Override
-        public String anotherMethod()
-        {
-            return "Hedhman";
-        }
-    }
-
-    public class RuntimeServiceMixin
-        implements RuntimeService
-    {
-        @Override
-        public String anotherMethod()
-        {
-            return "Hedhman";
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/service/ServiceIdSelectorTest.java b/core/runtime/src/test/java/org/qi4j/runtime/service/ServiceIdSelectorTest.java
deleted file mode 100644
index b504465..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/service/ServiceIdSelectorTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.service;
-
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.object.ObjectFactory;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.api.service.qualifier.ServiceQualifier.firstService;
-import static org.qi4j.api.service.qualifier.ServiceQualifier.withId;
-
-/**
- * JAVADOC
- */
-public class ServiceIdSelectorTest
-{
-    @Test
-    public void givenManyServicesWhenInjectServiceThenGetSelectedOne()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.objects( ServiceConsumer.class );
-                module.services( TestServiceComposite1.class,
-                                 TestServiceComposite2.class );
-            }
-        };
-
-        ObjectFactory obf = assembler.module();
-        ServiceConsumer consumer = obf.newObject( ServiceConsumer.class, TestServiceComposite2.class.getSimpleName() );
-        TestService service = consumer.getService();
-
-        assertThat( "service is selected one", service.test(), equalTo( "mixin2" ) );
-    }
-
-    public static class ServiceConsumer
-    {
-        private TestService service;
-
-        public ServiceConsumer( @Uses String serviceId, @Service Iterable<ServiceReference<TestService>> serviceRefs )
-        {
-            service = firstService( withId( serviceId ), serviceRefs );
-        }
-
-        public TestService getService()
-        {
-            return service;
-        }
-    }
-
-    @Mixins( TestMixin1.class )
-    public interface TestServiceComposite1
-        extends TestService, ServiceComposite
-    {
-    }
-
-    @Mixins( TestMixin2.class )
-    public interface TestServiceComposite2
-        extends TestService, ServiceComposite
-    {
-    }
-
-    public interface TestService
-    {
-        String test();
-    }
-
-    public static class TestMixin1
-        implements TestService
-    {
-        public String test()
-        {
-            return "mixin1";
-        }
-    }
-
-    public static class TestMixin2
-        implements TestService
-    {
-        public String test()
-        {
-            return "mixin2";
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/service/ServiceVisibilityTest.java b/core/runtime/src/test/java/org/qi4j/runtime/service/ServiceVisibilityTest.java
deleted file mode 100644
index 9950022..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/service/ServiceVisibilityTest.java
+++ /dev/null
@@ -1,880 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.service;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.NoSuchServiceException;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.ApplicationAssemblerAdapter;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-
-public class ServiceVisibilityTest
-{
-    private Energy4Java qi4j;
-    private Module module;
-    private Application app;
-
-    @Before
-    public void setup()
-        throws Exception
-    {
-        qi4j = new Energy4Java();
-
-        Assembler[][][] assemblers = new Assembler[][][]
-            {
-                { // Layer Above
-                  {
-                      new AboveAssembler()
-                  }
-                },
-                { // Layer From
-                  { // From Module
-                    new FromAssembler(),
-                  },
-                  { // Beside Module
-                    new BesideAssembler()
-                  }
-                },
-                { // Layer Below
-                  {
-                      new BelowAssembler()
-                  }
-                }
-            };
-        app = qi4j.newApplication( new ApplicationAssemblerAdapter( assemblers )
-        {
-        } );
-        app.activate();
-        module = app.findModule( "From Layer", "From" );
-    }
-
-    @After
-    public void tearDown()
-        throws Exception
-    {
-        app.passivate();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.besideLayerVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromServiceWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.belowApplicationVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromServiceWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.belowLayerVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromServiceWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.belowModuleVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromServiceWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.aboveApplicationVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromServiceWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.aboveLayerVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromServiceWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.aboveModuleVisible();
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.moduleApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.moduleLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.moduleModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.besideApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.besideLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromEntityWhenAccessingBesideModuleVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.besideModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.belowApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromEntityWhenAccessingBelowLayerVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.belowLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromEntityWhenAccessingBelowModuleVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.belowModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromEntityWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.aboveApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromEntityWhenAccessingAboveLayerVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.aboveLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromEntityWhenAccessingAboveModuleVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.aboveModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.besideLayerVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromValueWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.belowApplicationVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromValueWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.belowLayerVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromValueWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.belowModuleVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromValueWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.aboveApplicationVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromValueWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.aboveLayerVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromValueWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.aboveModuleVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.besideLayerVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromTransientWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.belowApplicationVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromTransientWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.belowLayerVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromTransientWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.belowModuleVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromTransientWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.aboveApplicationVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromTransientWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.aboveLayerVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromTransientWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.aboveModuleVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.besideLayerVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromObjectWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.belowApplicationVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromObjectWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.belowLayerVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromObjectWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.belowModuleVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromObjectWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.aboveApplicationVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromObjectWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.aboveLayerVisible();
-    }
-
-    @Test( expected = NoSuchServiceException.class )
-    public void givenFromObjectWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.aboveModuleVisible();
-    }
-
-    private static class FromAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.layer().setName( "From Layer" );
-            module.setName( "From" );
-            module.services( FromService.class );
-            module.entities( FromEntity.class );
-            module.transients( FromTransient.class );
-            module.values( FromValue.class );
-            module.objects( FromObject.class );
-
-            module.services( ModuleApplicationVisible.class ).visibleIn( Visibility.application );
-            module.services( ModuleLayerVisible.class ).visibleIn( Visibility.layer );
-            module.services( ModuleModuleVisible.class ).visibleIn( Visibility.module );
-        }
-    }
-
-    private static class BelowAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.layer().setName( "Below Layer" );
-            module.setName( "Below" );
-            module.services( BelowApplicationVisible.class ).visibleIn( Visibility.application );
-            module.services( BelowLayerVisible.class ).visibleIn( Visibility.layer );
-            module.services( BelowModuleVisible.class ).visibleIn( Visibility.module );
-
-            new EntityTestAssembler().visibleIn( Visibility.application ).assemble( module );
-        }
-    }
-
-    private static class AboveAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.layer().setName( "Above Layer" );
-            module.setName( "Above" );
-            module.services( AboveApplicationVisible.class ).visibleIn( Visibility.application );
-            module.services( AboveLayerVisible.class ).visibleIn( Visibility.layer );
-            module.services( AboveModuleVisible.class ).visibleIn( Visibility.module );
-        }
-    }
-
-    private static class BesideAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.setName( "Beside" );
-            module.services( BesideApplicationVisible.class ).visibleIn( Visibility.application );
-            module.services( BesideLayerVisible.class ).visibleIn( Visibility.layer );
-            module.services( BesideModuleVisible.class ).visibleIn( Visibility.module );
-        }
-    }
-
-    @Mixins( Mixin.class )
-    public interface From
-    {
-        void moduleApplicationVisible();
-
-        void moduleLayerVisible();
-
-        void moduleModuleVisible();
-
-        void besideApplicationVisible();
-
-        void besideLayerVisible();
-
-        void besideModuleVisible();
-
-        void belowApplicationVisible();
-
-        void belowLayerVisible();
-
-        void belowModuleVisible();
-
-        void aboveApplicationVisible();
-
-        void aboveLayerVisible();
-
-        void aboveModuleVisible();
-    }
-
-    public interface FromValue extends From, ValueComposite
-    {
-    }
-
-    public interface FromEntity extends From, EntityComposite
-    {
-    }
-
-    public interface FromService extends From, ServiceComposite
-    {
-    }
-
-    public interface FromTransient extends From, TransientComposite
-    {
-    }
-
-    public static class FromObject extends Mixin
-    {
-    }
-
-    public abstract static class Mixin
-        implements From
-    {
-        @Structure
-        private Module module;
-
-        @Override
-        public void moduleApplicationVisible()
-        {
-            ModuleApplicationVisible service = module.findService( ModuleApplicationVisible.class ).get();
-        }
-
-        @Override
-        public void moduleLayerVisible()
-        {
-            ModuleLayerVisible service = module.findService( ModuleLayerVisible.class ).get();
-        }
-
-        @Override
-        public void moduleModuleVisible()
-        {
-            ModuleModuleVisible service = module.findService( ModuleModuleVisible.class ).get();
-        }
-
-        @Override
-        public void besideApplicationVisible()
-        {
-            BesideApplicationVisible service = module.findService( BesideApplicationVisible.class ).get();
-        }
-
-        @Override
-        public void besideLayerVisible()
-        {
-            BesideLayerVisible service = module.findService( BesideLayerVisible.class ).get();
-        }
-
-        @Override
-        public void besideModuleVisible()
-        {
-            BesideModuleVisible service = module.findService( BesideModuleVisible.class ).get();
-        }
-
-        @Override
-        public void belowApplicationVisible()
-        {
-            BelowApplicationVisible service = module.findService( BelowApplicationVisible.class ).get();
-        }
-
-        @Override
-        public void belowLayerVisible()
-        {
-            BelowLayerVisible service = module.findService( BelowLayerVisible.class ).get();
-        }
-
-        @Override
-        public void belowModuleVisible()
-        {
-            BelowModuleVisible service = module.findService( BelowModuleVisible.class ).get();
-        }
-
-        @Override
-        public void aboveApplicationVisible()
-        {
-            AboveApplicationVisible service = module.findService( AboveApplicationVisible.class ).get();
-        }
-
-        @Override
-        public void aboveLayerVisible()
-        {
-            AboveLayerVisible service = module.findService( AboveLayerVisible.class ).get();
-        }
-
-        @Override
-        public void aboveModuleVisible()
-        {
-            AboveModuleVisible service = module.findService( AboveModuleVisible.class ).get();
-        }
-    }
-
-    public interface ModuleApplicationVisible extends ServiceComposite
-    {
-    }
-
-    public interface ModuleLayerVisible extends ServiceComposite
-    {
-    }
-
-    public interface ModuleModuleVisible extends ServiceComposite
-    {
-    }
-
-    public interface BesideApplicationVisible extends ServiceComposite
-    {
-    }
-
-    public interface BesideLayerVisible extends ServiceComposite
-    {
-    }
-
-    public interface BesideModuleVisible extends ServiceComposite
-    {
-    }
-
-    public interface BelowApplicationVisible extends ServiceComposite
-    {
-    }
-
-    public interface BelowLayerVisible extends ServiceComposite
-    {
-    }
-
-    public interface BelowModuleVisible extends ServiceComposite
-    {
-    }
-
-    public interface AboveApplicationVisible extends ServiceComposite
-    {
-    }
-
-    public interface AboveLayerVisible extends ServiceComposite
-    {
-    }
-
-    public interface AboveModuleVisible extends ServiceComposite
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/sideeffects/GenericSideEffectTest.java b/core/runtime/src/test/java/org/qi4j/runtime/sideeffects/GenericSideEffectTest.java
deleted file mode 100644
index 46007bd..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/sideeffects/GenericSideEffectTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.sideeffects;
-
-import java.lang.reflect.Method;
-import org.junit.Test;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.AppliesToFilter;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.sideeffect.GenericSideEffect;
-import org.qi4j.api.sideeffect.SideEffects;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.not;
-import static org.junit.Assert.assertThat;
-
-/**
- * JAVADOC
- */
-public class GenericSideEffectTest
-    extends AbstractQi4jTest
-{
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( SomeComposite.class );
-    }
-
-    @Test
-    public void testGenericSideEffect()
-    {
-        SomeComposite some = module.newTransient( SomeComposite.class );
-        Property<Integer> count = some.count();
-        assertThat( "count is zero", count.get(), equalTo( 0 ) );
-        some.doStuff();
-        assertThat( "count is not zero", count.get(), not( equalTo( 0 ) ) );
-    }
-
-    @SideEffects( CounterSideEffect.class )
-    @Mixins( SomeMixin.class )
-    public interface SomeComposite
-        extends Some, Counter, TransientComposite
-    {
-    }
-
-    public interface Some
-    {
-        public String doStuff();
-    }
-
-    public static abstract class SomeMixin
-        implements Some
-    {
-        public String doStuff()
-        {
-            return "Blah blah";
-        }
-    }
-
-    public interface Counter
-    {
-        @UseDefaults
-        Property<Integer> count();
-    }
-
-    @AppliesTo( NotCounterFilter.class )
-    public static class CounterSideEffect
-        extends GenericSideEffect
-    {
-        @This
-        Counter counter;
-
-        public void invoke( Method method, Object[] objects )
-        {
-            counter.count().set( counter.count().get() + 1 );
-        }
-    }
-
-    public static class NotCounterFilter
-        implements AppliesToFilter
-    {
-        public boolean appliesTo( Method method, Class mixin, Class compositeType, Class modifierClass )
-        {
-            return !method.getDeclaringClass().equals( Counter.class );
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/sideeffects/ModuleSideEffectTest.java b/core/runtime/src/test/java/org/qi4j/runtime/sideeffects/ModuleSideEffectTest.java
deleted file mode 100644
index 8bf2b3f..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/sideeffects/ModuleSideEffectTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.sideeffects;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import org.hamcrest.CoreMatchers;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.sideeffect.GenericSideEffect;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-/**
- * Test of declaring sideeffect in assembly
- */
-public class ModuleSideEffectTest
-    extends AbstractQi4jTest
-{
-    public static boolean ok = false;
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( FooComposite.class ).withSideEffects( TraceSideEffect.class );
-    }
-
-    @Test
-    public void testModuleSideEffect()
-    {
-        module.newTransient( Foo.class ).test( "Foo", 42 );
-        Assert.assertThat( "SideEffect has been called", ok, CoreMatchers.equalTo( true ) );
-    }
-
-    @Mixins( FooMixin.class )
-    public interface FooComposite
-        extends TransientComposite, Foo
-    {
-    }
-
-    public interface Foo
-    {
-        String test( String foo, int bar );
-    }
-
-    public static class FooMixin
-        implements Foo
-    {
-        public String test( String foo, int bar )
-        {
-            return foo + " " + bar;
-        }
-    }
-
-    public static class TraceSideEffect
-        extends GenericSideEffect
-    {
-        public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-        {
-            ok = true;
-            Object result = this.result.invoke( proxy, method, args );
-            String str = method.getName() + Arrays.asList( args );
-            System.out.println( str );
-            return result;
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/sideeffects/SampleTransientTest.java b/core/runtime/src/test/java/org/qi4j/runtime/sideeffects/SampleTransientTest.java
deleted file mode 100644
index 6a0d4f6..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/sideeffects/SampleTransientTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2014, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Dominic Jones. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.sideeffects;
-
-import org.junit.Test;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.composite.TransientBuilderFactory;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.sideeffect.SideEffectOf;
-import org.qi4j.api.sideeffect.SideEffects;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-public class SampleTransientTest extends AbstractQi4jTest
-{
-
-    @Structure
-    TransientBuilderFactory transientBuilderFactory;
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( SampleTransient.class );
-    }
-
-    @Test
-    public void givenTransientWithSideEffectsWhenInvokingMethodShouldExecuteSideEffectOnlyOnce()
-    {
-        SampleTransient sample = transientBuilderFactory.newTransient( SampleTransient.class );
-        sample.execute();
-        assertThat( sample.count().get(), equalTo(1));
-    }
-
-    @SideEffects( SampleSideEffect.class )
-    @Mixins( SampleTransientMixin.class )
-    public static interface SampleTransient
-    {
-        void execute();
-
-        @UseDefaults
-        Property<Integer> count();
-    }
-
-    public abstract static class SampleTransientMixin
-        implements SampleTransient
-    {
-        @Override
-        public void execute()
-        {
-            System.out.println( "Invocation of Transient" );
-        }
-    }
-
-    public abstract static class SampleSideEffect extends SideEffectOf<SampleTransient>
-        implements SampleTransient
-    {
-        @Override
-        public void execute()
-        {
-            System.out.println( "Invocation of SideEffect" );
-            count().set( count().get() + 1 );
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/sideeffects/SpecificSideEffectTest.java b/core/runtime/src/test/java/org/qi4j/runtime/sideeffects/SpecificSideEffectTest.java
deleted file mode 100644
index 21f8c4e..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/sideeffects/SpecificSideEffectTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.sideeffects;
-
-import org.junit.Test;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.sideeffect.SideEffectOf;
-import org.qi4j.api.sideeffect.SideEffects;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.not;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test for adding side-effects to methods specified by domain interfaces
- */
-public class SpecificSideEffectTest
-    extends AbstractQi4jTest
-{
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( SomeComposite.class );
-    }
-
-    @Test
-    public void specificSideEffect()
-    {
-        SomeComposite some = module.newTransient( SomeComposite.class );
-        Property<Integer> count = some.count();
-        assertThat( "count is zero", count.get(), equalTo( 0 ) );
-        some.doStuff();
-        assertThat( "count is not zero", count.get(), equalTo( 1 ) );
-    }
-
-    @SideEffects( CounterSideEffect.class )
-    @Mixins( SomeMixin.class )
-    public interface SomeComposite
-        extends Some, Counter, TransientComposite
-    {
-    }
-
-    public interface Some
-    {
-        public String doStuff();
-    }
-
-    public static abstract class SomeMixin
-        implements Some
-    {
-        public String doStuff()
-        {
-            return "Blah blah";
-        }
-    }
-
-    public interface Counter
-    {
-        @UseDefaults
-        Property<Integer> count();
-    }
-
-    public static class CounterSideEffect
-        extends SideEffectOf<Some>
-        implements Some
-    {
-        @This
-        Counter counter;
-
-        public String doStuff()
-        {
-            counter.count().set( counter.count().get() + 1 );
-            return null;
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/structure/ApplicationModeTest.java b/core/runtime/src/test/java/org/qi4j/runtime/structure/ApplicationModeTest.java
deleted file mode 100644
index 1ef4046..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/structure/ApplicationModeTest.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.structure;
-
-import org.hamcrest.CoreMatchers;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.structure.Application;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.test.AbstractQi4jTest;
-
-public class ApplicationModeTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-
-    }
-
-    @Test
-    public void testApplicationModeNotSet()
-    {
-        // mode is set to test in AbstractQi4jTest
-        Assert.assertThat( "mode set to default",
-                           application.mode(),
-                           CoreMatchers.equalTo( Application.Mode.test ) );
-    }
-
-    @Test
-    public void testApplicationTestModeSet()
-        throws ActivationException, AssemblyException
-    {
-        Application.Mode mode = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.layer().application().setMode( Application.Mode.test );
-            }
-        }.application().mode();
-
-        Assert.assertThat( "mode set to given value", mode, CoreMatchers.equalTo( Application.Mode.test ) );
-    }
-
-    @Test
-    public void testApplicationStagingModeSet()
-        throws ActivationException, AssemblyException
-    {
-        Application.Mode mode = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.layer().application().setMode( Application.Mode.staging );
-            }
-        }.application().mode();
-
-        Assert.assertThat( "mode set to given value", mode, CoreMatchers.equalTo( Application.Mode.staging ) );
-    }
-
-    @Test
-    public void testApplicationDevelopmentModeSet()
-        throws ActivationException, AssemblyException
-    {
-        Application.Mode mode = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.layer().application().setMode( Application.Mode.development );
-            }
-        }.application().mode();
-
-        Assert.assertThat( "mode set to given value", mode, CoreMatchers.equalTo( Application.Mode.development ) );
-    }
-
-    @Test
-    public void testApplicationProductionModeSet()
-        throws ActivationException, AssemblyException
-    {
-        Application.Mode mode = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.layer().application().setMode( Application.Mode.production );
-            }
-        }.application().mode();
-
-        Assert.assertThat( "mode set to given value", mode, CoreMatchers.equalTo( Application.Mode.production ) );
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/structure/CompositeDescriptorTest.java b/core/runtime/src/test/java/org/qi4j/runtime/structure/CompositeDescriptorTest.java
deleted file mode 100644
index 101fe7a..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/structure/CompositeDescriptorTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.runtime.structure;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.composite.TransientDescriptor;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.qi4j.functional.Iterables.first;
-
-public class CompositeDescriptorTest
-    extends AbstractQi4jTest
-{
-    @Test
-    public final void testCompositeDescriptorWithComposite()
-        throws Throwable
-    {
-        // Test with Standard composite
-        AddressComposite address = module.newTransient( AddressComposite.class );
-        TransientDescriptor addressDescriptor = spi.transientDescriptorFor( address );
-
-        assertNotNull( addressDescriptor );
-        assertEquals( AddressComposite.class, first( addressDescriptor.types() ) );
-        assertTrue( TransientDescriptor.class.isAssignableFrom( addressDescriptor.getClass() ) );
-    }
-
-    @Test
-    public final void testCompositeDescriptorWithMixin()
-    {
-        // Test with composite
-        TransientDescriptor addressDesc = module.transientDescriptor( AddressComposite.class.getName() );
-        assertNotNull( addressDesc );
-
-        assertEquals( AddressComposite.class, first( addressDesc.types() ) );
-    }
-
-    public final void assemble( ModuleAssembly aModule )
-        throws AssemblyException
-    {
-        aModule.transients( AddressComposite.class );
-    }
-
-    private static interface AddressComposite
-        extends Address, TransientComposite
-    {
-    }
-
-    private static interface Address
-    {
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/structure/MixinVisibilityTest.java b/core/runtime/src/test/java/org/qi4j/runtime/structure/MixinVisibilityTest.java
deleted file mode 100644
index 21e4d37..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/structure/MixinVisibilityTest.java
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.structure;
-
-import org.junit.Test;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.AmbiguousTypeException;
-import org.qi4j.api.composite.NoSuchTransientException;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientBuilderFactory;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.structure.Application;
-import org.qi4j.bootstrap.ApplicationAssemblerAdapter;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * JAVADOC
- */
-public class MixinVisibilityTest
-{
-    @Test
-    public void testMixinInModuleIsVisible()
-        throws Exception
-    {
-        Energy4Java boot = new Energy4Java();
-        Assembler[][][] assemblers = new Assembler[][][]
-            {
-                { // Layer
-                  {  // Module 1
-                     new Assembler()
-                     {
-                         public void assemble( ModuleAssembly module )
-                             throws AssemblyException
-                         {
-                             module.setName( "Module A" );
-                             module.transients( B1Composite.class );
-                             module.objects( ObjectA.class );
-                         }
-                     }
-                  }
-                }
-            };
-
-        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
-        {
-        } );
-        app.activate();
-        ObjectA object = app.findModule( "Layer 1", "Module A" ).newObject( ObjectA.class );
-        assertEquals( "ok", object.test1() );
-        assertEquals( "abc", object.test2() );
-    }
-
-    @Test( expected = AmbiguousTypeException.class )
-    public void testMultipleMixinsInModuleWillFail()
-        throws Exception
-    {
-        Energy4Java boot = new Energy4Java();
-        Assembler[][][] assemblers = new Assembler[][][]
-            {
-                { // Layer
-                  {  // Module 1
-                     new Assembler()
-                     {
-                         public void assemble( ModuleAssembly module )
-                             throws AssemblyException
-                         {
-                             module.setName( "Module A" );
-                             module.transients( B1Composite.class, B2Composite.class );
-                             module.objects( ObjectA.class );
-                         }
-                     }
-                  }
-                }
-            };
-
-        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
-        {
-        } );
-        app.activate();
-        ObjectA object = app.findModule( "Layer 1", "Module A" ).newObject( ObjectA.class );
-        assertEquals( "ok", object.test1() );
-        assertEquals( "abc", object.test2() );
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void testMixinInLayerIsNotVisible()
-        throws Exception
-    {
-        Energy4Java boot = new Energy4Java();
-        Assembler[][][] assemblers = new Assembler[][][]
-            {
-                { // Layer
-                  {
-                      new Assembler()
-                      {
-                          public void assemble( ModuleAssembly module )
-                              throws AssemblyException
-                          {
-                              module.setName( "Module A" );
-                              module.objects( ObjectA.class );
-                          }
-                      }
-                  },
-                  {
-                      new Assembler()
-                      {
-                          public void assemble( ModuleAssembly module )
-                              throws AssemblyException
-                          {
-                              module.setName( "Module B" );
-                              module.transients( B1Composite.class );
-                          }
-                      }
-                  }
-                }
-            };
-
-        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
-        {
-        } );
-        app.activate();
-        ObjectA object = app.findModule( "Layer 1", "Module A" ).newObject( ObjectA.class );
-        assertEquals( "ok", object.test1() );
-        assertEquals( "abc", object.test2() );
-    }
-
-    @Test
-    public void testMixinInLayerIsVisible()
-        throws Exception
-    {
-        Energy4Java boot = new Energy4Java();
-        Assembler[][][] assemblers = new Assembler[][][]
-            {
-                { // Layer
-                  {
-                      new Assembler()
-                      {
-                          public void assemble( ModuleAssembly module )
-                              throws AssemblyException
-                          {
-                              module.setName( "Module A" );
-                              module.objects( ObjectA.class );
-                          }
-                      }
-                  },
-                  {
-                      new Assembler()
-                      {
-                          public void assemble( ModuleAssembly module )
-                              throws AssemblyException
-                          {
-                              module.setName( "Module B" );
-                              module.transients( B1Composite.class ).visibleIn( Visibility.layer );
-                          }
-                      }
-                  }
-                }
-            };
-
-        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
-        {
-        } );
-        app.activate();
-        ObjectA object = app.findModule( "Layer 1", "Module A" ).newObject( ObjectA.class );
-        assertEquals( "ok", object.test1() );
-        assertEquals( "abc", object.test2() );
-    }
-
-    @Test( expected = AmbiguousTypeException.class )
-    public void testMultipleMixinsInLayerWillFailSameModule()
-        throws Exception
-    {
-        Energy4Java boot = new Energy4Java();
-        Assembler[][][] assemblers = new Assembler[][][]
-            {
-                { // Layer
-                  {
-                      new Assembler()
-                      {
-                          public void assemble( ModuleAssembly module )
-                              throws AssemblyException
-                          {
-                              module.setName( "Module A" );
-                              module.objects( ObjectA.class );
-                          }
-                      }
-                  },
-                  {
-                      new Assembler()
-                      {
-                          public void assemble( ModuleAssembly module )
-                              throws AssemblyException
-                          {
-                              module.setName( "Module B" );
-                              module.transients( B1Composite.class, B2Composite.class )
-                                  .visibleIn( Visibility.layer );
-                          }
-                      }
-                  }
-                }
-            };
-
-        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
-        {
-        } );
-        app.activate();
-        ObjectA object = app.findModule( "Layer 1", "Module A" ).newObject( ObjectA.class );
-        assertEquals( "ok", object.test1() );
-        assertEquals( "abc", object.test2() );
-    }
-
-    @Test( expected = AmbiguousTypeException.class )
-    public void testMultipleMixinsInLayerWillFailDiffModule()
-        throws Exception
-    {
-        Energy4Java boot = new Energy4Java();
-        Assembler[][][] assemblers = new Assembler[][][]
-            {
-                { // Layer
-                  { // Module 1
-                    new Assembler()
-                    {
-                        public void assemble( ModuleAssembly module )
-                            throws AssemblyException
-                        {
-                            module.setName( "Module A" );
-                            module.objects( ObjectA.class );
-                        }
-                    }
-                  },
-                  { // Module 2
-                    new Assembler()
-                    {
-                        public void assemble( ModuleAssembly module )
-                            throws AssemblyException
-                        {
-                            module.setName( "Module B" );
-                            module.transients( B1Composite.class ).visibleIn( Visibility.layer );
-                        }
-                    }
-                  },
-                  { // Module 3
-                    new Assembler()
-                    {
-                        public void assemble( ModuleAssembly module )
-                            throws AssemblyException
-                        {
-                            module.setName( "Module C" );
-                            module.transients( B2Composite.class ).visibleIn( Visibility.layer );
-                        }
-                    }
-                  }
-                }
-            };
-
-        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
-        {
-        } );
-        app.activate();
-        ObjectA object = app.findModule( "Layer 1", "Module A" ).newObject( ObjectA.class );
-        assertEquals( "ok", object.test1() );
-        assertEquals( "abc", object.test2() );
-    }
-
-    // @Test( expected= MixinTypeNotAvailableException.class )
-
-    public void testMixinInLowerLayerIsNotVisible()
-        throws Exception
-    {
-
-        Energy4Java boot = new Energy4Java();
-        Assembler[][][] assemblers = new Assembler[][][]
-            {
-                { // Layer 1
-                  {
-                      new Assembler()
-                      {
-                          public void assemble( ModuleAssembly module )
-                              throws AssemblyException
-                          {
-                              module.setName( "Module A" );
-                              module.objects( ObjectA.class );
-                          }
-                      }
-                  }
-                },
-                { // Layer 2
-                  {
-                      new Assembler()
-                      {
-                          public void assemble( ModuleAssembly module )
-                              throws AssemblyException
-                          {
-                              module.setName( "Module B" );
-                              module.transients( B1Composite.class ).visibleIn( Visibility.layer );
-                          }
-                      }
-                  }
-                }
-            };
-
-        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
-        {
-        } );
-        app.activate();
-        ObjectA object = app.findModule( "Layer 1", "Module " ).newObject( ObjectA.class );
-        assertEquals( "ok", object.test1() );
-        assertEquals( "abc", object.test2() );
-    }
-
-    @Test
-    public void testMixinInLowerLayerIsVisible()
-        throws Exception
-    {
-        Energy4Java boot = new Energy4Java();
-        Assembler[][][] assemblers = new Assembler[][][]
-            {
-                { // Layer 1
-                  {
-                      new Assembler()
-                      {
-                          public void assemble( ModuleAssembly module )
-                              throws AssemblyException
-                          {
-                              module.setName( "Module A" );
-                              module.objects( ObjectA.class );
-                          }
-                      }
-                  }
-                },
-                { // Layer 2
-                  {
-                      new Assembler()
-                      {
-                          public void assemble( ModuleAssembly module )
-                              throws AssemblyException
-                          {
-                              module.setName( "Module B" );
-                              module.transients( B1Composite.class ).visibleIn( Visibility.application );
-                          }
-                      }
-                  }
-                }
-            };
-
-        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
-        {
-        } );
-        app.activate();
-        ObjectA object = app.findModule( "Layer 1", "Module A" ).newObject( ObjectA.class );
-        assertEquals( "ok", object.test1() );
-        assertEquals( "abc", object.test2() );
-    }
-
-    class AssemblerB
-        implements Assembler
-    {
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.setName( "Module B" );
-            module.transients( B1Composite.class ).visibleIn( Visibility.module );
-        }
-    }
-
-    public static class ObjectA
-    {
-        @Structure
-        TransientBuilderFactory cbf;
-
-        String test1()
-        {
-            B1 instance = cbf.newTransient( B1.class );
-            return instance.test();
-        }
-
-        String test2()
-        {
-            TransientBuilder<B2> builder = cbf.newTransientBuilder( B2.class );
-            builder.prototypeFor( B2.class ).b2().set( "abc" );
-            B2 instance = builder.newInstance();
-            return instance.b2().get();
-        }
-    }
-
-    @Mixins( { MixinB.class } )
-    public interface B1Composite
-        extends TransientComposite, B1
-    {
-    }
-
-    public interface B2Composite
-        extends TransientComposite, B2
-    {
-    }
-
-    public interface B2
-    {
-        @Optional
-        Property<String> b2();
-    }
-
-    public interface B1
-        extends B2
-    {
-        String test();
-    }
-
-    public abstract static class MixinB
-        implements B1
-    {
-        public String test()
-        {
-            return "ok";
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/structure/ModuleTest.java b/core/runtime/src/test/java/org/qi4j/runtime/structure/ModuleTest.java
deleted file mode 100644
index d9e14f2..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/structure/ModuleTest.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.structure;
-
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.ApplicationAssemblyFactory;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test of the Module interface. This should satisfiedBy both the general interface and all possible visibility
- * rules.
- */
-public class ModuleTest
-{
-    public Application givenFixture1()
-        throws AssemblyException
-    {
-        Energy4Java boot = new Energy4Java();
-        return boot.newApplication( new ApplicationAssembler()
-        {
-            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-                throws AssemblyException
-            {
-                return applicationFactory.newApplicationAssembly( new Assembler[][][]
-                                                                  {
-                                                                      {
-                                                                          {
-                                                                              new Assembler()
-                                                                              {
-                                                                                  public void assemble( ModuleAssembly module )
-                                                                                      throws AssemblyException
-                                                                                  {
-                                                                                      module.transients( TestComposite1.class );
-                                                                                  }
-                                                                              }
-                                                                          },
-                                                                          {
-                                                                              new Assembler()
-                                                                              {
-                                                                                  public void assemble( ModuleAssembly module )
-                                                                                      throws AssemblyException
-                                                                                  {
-                                                                                      module.transients( TestComposite2.class )
-                                                                                          .visibleIn( Visibility.layer );
-                                                                                  }
-                                                                              }
-                                                                          }
-                                                                      }
-                                                                  } );
-            }
-        } );
-    }
-
-    @Test
-    public void givenFixture1WhenGetNameThenConfiguredNameIsReturned()
-        throws AssemblyException
-    {
-        Application app = givenFixture1();
-
-        Module module = app.findModule( "Layer 1", "Module 1" ).newTransient( TestComposite1.class ).getModule();
-        assertThat( "module name is correct", module.name(), equalTo( "Module 1" ) );
-    }
-
-    @Test
-    public void givenFixture1WhenGetModuleForCompositeThenCorrectModuleIsReturned()
-        throws AssemblyException
-    {
-        Application app = givenFixture1();
-
-        Module module = app.findModule( "Layer 1", "Module 1" ).newTransient( TestComposite1.class ).getModule();
-        assertThat( "module for composite is correct", module, equalTo( module ) );
-    }
-
-    @Test
-    public void givenFixture1WhenFindFromAnotherModuleThenCompositeTypeIsReturned()
-        throws ClassNotFoundException, AssemblyException
-    {
-        Application app = givenFixture1();
-
-        Module module = app.findModule( "Layer 1", "Module 1" ).newTransient( TestComposite1.class ).getModule();
-        module.classLoader().loadClass( TestComposite2.class.getName() );
-    }
-
-    @Mixins( TestMixin1.class )
-    public interface TestComposite1
-        extends TransientComposite
-    {
-        Module getModule();
-    }
-
-    public abstract static class TestMixin1
-        implements TestComposite1
-    {
-        @Structure
-        Module module;
-
-        public Module getModule()
-        {
-            return module;
-        }
-    }
-
-    @Mixins( TestMixin2.class )
-    public interface TestComposite2
-        extends TransientComposite
-    {
-        Module getModule();
-    }
-
-    public abstract static class TestMixin2
-        implements TestComposite2
-    {
-        @Structure
-        Module module;
-
-        public Module getModule()
-        {
-            return module;
-        }
-    }
-
-    public interface TestComposite21
-        extends TestComposite2
-    {
-    }
-
-    public static class TestObject1
-    {
-
-    }
-
-    public static class TestObject2
-    {
-
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/structure/PrivateCompositeVisibilityTest.java b/core/runtime/src/test/java/org/qi4j/runtime/structure/PrivateCompositeVisibilityTest.java
deleted file mode 100644
index 67edf89..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/structure/PrivateCompositeVisibilityTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.structure;
-
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.NoSuchTransientException;
-import org.qi4j.api.composite.TransientBuilderFactory;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.structure.Application;
-import org.qi4j.bootstrap.ApplicationAssemblerAdapter;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-/**
- * JAVADOC
- */
-public class PrivateCompositeVisibilityTest
-{
-    @Test( expected = NoSuchTransientException.class )
-    public void testPrivateCompositeVisibility()
-        throws Exception
-    {
-        Energy4Java boot = new Energy4Java();
-        Assembler[][][] assemblers = new Assembler[][][]
-            {
-                { // Layer
-                  {
-                      new AssemblerA()
-                  },
-                  {
-                      new AssemblerB()
-                  }
-                }
-            };
-        Application app = boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
-        {
-        } );
-        app.activate();
-        ObjectA object = app.findModule( "Layer 1", "Module A" ).newObject( ObjectA.class );
-        object.test();
-    }
-
-    class AssemblerA
-        implements Assembler
-    {
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.setName( "Module A" );
-            module.objects( ObjectA.class );
-        }
-    }
-
-    class AssemblerB
-        implements Assembler
-    {
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.setName( "Module B" );
-            module.transients( CompositeB.class ).visibleIn( Visibility.module );
-        }
-    }
-
-    public static class ObjectA
-    {
-        @Structure
-        TransientBuilderFactory cbf;
-
-        String test()
-        {
-            CompositeB instance = cbf.newTransient( CompositeB.class );
-            return instance.test();
-        }
-    }
-
-    @Mixins( MixinB.class )
-    public interface CompositeB
-        extends TransientComposite
-    {
-        String test();
-    }
-
-    public abstract static class MixinB
-        implements CompositeB
-    {
-
-        public String test()
-        {
-            return "ok";
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/structure/StructureTest.java b/core/runtime/src/test/java/org/qi4j/runtime/structure/StructureTest.java
deleted file mode 100644
index c1a2630..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/structure/StructureTest.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.structure;
-
-import org.junit.Test;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.ApplicationAssemblerAdapter;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.ApplicationAssemblyFactory;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-/**
- * JAVADOC
- */
-public class StructureTest
-{
-
-    @Test
-    public void createApplicationUsingApplicationAssembly()
-        throws AssemblyException
-    {
-        Energy4Java boot = new Energy4Java();
-        boot.newApplication( new ApplicationAssembler()
-        {
-            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-                throws AssemblyException
-            {
-                ApplicationAssembly applicationAssembly = applicationFactory.newApplicationAssembly();
-                // Application Layer
-                LayerAssembly applicationLayer = applicationAssembly.layer( "Application" );
-                ModuleAssembly applicationModule = applicationLayer.module( "Application" );
-                new DomainApplicationAssembler().assemble( applicationModule );
-
-                // View Layer
-                LayerAssembly viewLayer = applicationAssembly.layer( "View" );
-                ModuleAssembly viewModule = viewLayer.module( "View" );
-                new ViewAssembler().assemble( viewModule );
-                viewLayer.uses( applicationLayer );
-                return applicationAssembly;
-            }
-        } );
-    }
-
-    @Test
-    public void createApplicationUsingArrayOfAssemblers()
-        throws AssemblyException
-    {
-        Energy4Java boot = new Energy4Java();
-        Assembler[][][] assemblers = new Assembler[][][]
-            {
-                { // User Interface layer
-                  {
-                      new ViewAssembler()
-                  }
-                },
-                { // Application layer
-                  {
-                      new DomainApplicationAssembler()
-                  }
-                },
-                { // Domain layer
-                  {
-                      new DomainModelAssembler()
-                  }
-                },
-                { // Infrastructure layer
-                  {
-                      new InfrastructureAssembler()
-                  }
-                }
-            };
-
-        boot.newApplication( new ApplicationAssemblerAdapter( assemblers )
-        {
-        } );
-    }
-
-    static class ViewAssembler
-        implements Assembler
-    {
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-        }
-    }
-
-    static class DomainApplicationAssembler
-        implements Assembler
-    {
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-        }
-    }
-
-    static class DomainModelAssembler
-        implements Assembler
-    {
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-        }
-    }
-
-    static class InfrastructureAssembler
-        implements Assembler
-    {
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/structure/TypeToCompositeLookupTest.java b/core/runtime/src/test/java/org/qi4j/runtime/structure/TypeToCompositeLookupTest.java
deleted file mode 100644
index 9e6bbcd..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/structure/TypeToCompositeLookupTest.java
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.runtime.structure;
-
-import java.util.Iterator;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.composite.AmbiguousTypeException;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.functional.Iterables;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.*;
-
-/**
- * Theses tests ensure that Type to Composite lookup work as expected for
- * Objects, Transients, Values, Entities and Services.
- */
-public class TypeToCompositeLookupTest
-{
-
-    private static final String CATHEDRAL = "cathedral";
-    private static final String BAZAR = "bazar";
-
-    public interface Foo
-    {
-
-        String bar();
-
-    }
-
-    public static class BasicFooImpl
-        implements Foo
-    {
-
-        @Override
-        public String bar()
-        {
-            return BAZAR;
-        }
-
-    }
-
-    public static class SomeOtherFooImpl
-        extends BasicFooImpl
-    {
-
-        @Override
-        public String bar()
-        {
-            return CATHEDRAL;
-        }
-
-    }
-
-    @Mixins( BasicFooImpl.class )
-    public interface BasicFoo
-        extends Foo
-    {
-    }
-
-    @Mixins( SomeOtherFooImpl.class )
-    public interface SomeOtherFoo
-        extends BasicFoo
-    {
-    }
-
-    @Test
-    public void objects()
-        throws ActivationException, AssemblyException
-    {
-        Module module = new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.objects( SomeOtherFooImpl.class );
-            }
-
-        }.module();
-
-        assertEquals( CATHEDRAL, module.newObject( SomeOtherFooImpl.class ).bar() );
-        assertEquals( CATHEDRAL, module.newObject( BasicFooImpl.class ).bar() );
-        assertEquals( CATHEDRAL, module.newObject( Foo.class ).bar() );
-    }
-
-    @Test
-    public void objectsAmbiguousDeclaration()
-        throws ActivationException, AssemblyException
-    {
-        Module module = new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.objects( SomeOtherFooImpl.class, BasicFooImpl.class );
-            }
-
-        }.module();
-
-        assertEquals( CATHEDRAL, module.newObject( SomeOtherFooImpl.class ).bar() );
-        assertEquals( BAZAR, module.newObject( BasicFooImpl.class ).bar() );
-
-        try
-        {
-            module.newObject( Foo.class );
-            fail( "Ambiguous type exception not detected for Objects" );
-        }
-        catch( AmbiguousTypeException expected )
-        {
-        }
-    }
-
-    @Test
-    public void transients()
-        throws ActivationException, AssemblyException
-    {
-        Module module = new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( SomeOtherFoo.class );
-            }
-
-        }.module();
-
-        assertEquals( CATHEDRAL, module.newTransientBuilder( SomeOtherFoo.class ).newInstance().bar() );
-        assertEquals( CATHEDRAL, module.newTransientBuilder( BasicFoo.class ).newInstance().bar() );
-        assertEquals( CATHEDRAL, module.newTransientBuilder( Foo.class ).newInstance().bar() );
-    }
-
-    @Test
-    public void transientsAmbiguousDeclaration()
-        throws ActivationException, AssemblyException
-    {
-        Module module = new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( SomeOtherFoo.class, BasicFoo.class );
-            }
-
-        }.module();
-
-        assertEquals( CATHEDRAL, module.newTransientBuilder( SomeOtherFoo.class ).newInstance().bar() );
-        assertEquals( BAZAR, module.newTransientBuilder( BasicFoo.class ).newInstance().bar() );
-
-        try
-        {
-            module.newTransientBuilder( Foo.class );
-            fail( "Ambiguous type exception not detected for Transients" );
-        }
-        catch( AmbiguousTypeException expected )
-        {
-        }
-    }
-
-    @Test
-    public void values()
-        throws ActivationException, AssemblyException
-    {
-        Module module = new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.values( SomeOtherFoo.class );
-            }
-
-        }.module();
-
-        assertEquals( CATHEDRAL, module.newValueBuilder( SomeOtherFoo.class ).newInstance().bar() );
-        assertEquals( CATHEDRAL, module.newValueBuilder( BasicFoo.class ).newInstance().bar() );
-        assertEquals( CATHEDRAL, module.newValueBuilder( Foo.class ).newInstance().bar() );
-    }
-
-    @Test
-    public void valuesAmbiguousDeclaration()
-        throws ActivationException, AssemblyException
-    {
-        Module module = new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.values( SomeOtherFoo.class, BasicFoo.class );
-            }
-
-        }.module();
-
-        assertEquals( CATHEDRAL, module.newValueBuilder( SomeOtherFoo.class ).newInstance().bar() );
-        assertEquals( BAZAR, module.newValueBuilder( BasicFoo.class ).newInstance().bar() );
-
-        try
-        {
-            module.newValueBuilder( Foo.class );
-            fail( "Ambiguous type exception not detected for Values" );
-        }
-        catch( AmbiguousTypeException expected )
-        {
-        }
-    }
-
-    @Test
-    public void entities()
-        throws UnitOfWorkCompletionException, ActivationException, AssemblyException
-    {
-        Module module = new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                new EntityTestAssembler().assemble( module );
-                module.entities( SomeOtherFoo.class );
-            }
-
-        }.module();
-
-        UnitOfWork uow = module.newUnitOfWork();
-
-        SomeOtherFoo someOtherFoo = uow.newEntityBuilder( SomeOtherFoo.class ).newInstance();
-        BasicFoo basicFoo = uow.newEntityBuilder( BasicFoo.class ).newInstance();
-        Foo foo = uow.newEntityBuilder( Foo.class ).newInstance();
-
-        assertEquals( CATHEDRAL, someOtherFoo.bar() );
-        assertEquals( CATHEDRAL, basicFoo.bar() );
-        assertEquals( CATHEDRAL, foo.bar() );
-
-        String someOtherFooIdentity = ( (Identity) someOtherFoo ).identity().get();
-        String basicFooIdentity = ( (Identity) basicFoo ).identity().get();
-        String fooIdentity = ( (Identity) foo ).identity().get();
-
-        uow.complete();
-
-        uow = module.newUnitOfWork();
-
-        uow.get( SomeOtherFoo.class, someOtherFooIdentity );
-        uow.get( BasicFoo.class, basicFooIdentity );
-        uow.get( Foo.class, fooIdentity );
-
-        uow.discard();
-    }
-
-    @Test
-    public void entitiesAmbiguousDeclaration()
-        throws UnitOfWorkCompletionException, ActivationException, AssemblyException
-    {
-        Module module = new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                new EntityTestAssembler().assemble( module );
-                module.entities( SomeOtherFoo.class, BasicFoo.class );
-            }
-
-        }.module();
-
-        UnitOfWork uow = module.newUnitOfWork();
-
-        SomeOtherFoo someOtherFoo = uow.newEntityBuilder( SomeOtherFoo.class ).newInstance();
-        BasicFoo basicFoo = uow.newEntityBuilder( BasicFoo.class ).newInstance();
-        try
-        {
-            uow.newEntityBuilder( Foo.class ).newInstance();
-            fail( "Ambiguous type exception not detected for Entities" );
-        }
-        catch( AmbiguousTypeException expected )
-        {
-        }
-
-        // Specific Type used
-        assertEquals( CATHEDRAL, uow.newEntityBuilder( SomeOtherFoo.class ).newInstance().bar() );
-
-        // Specific Type used
-        assertEquals( BAZAR, uow.newEntityBuilder( BasicFoo.class ).newInstance().bar() );
-
-        String someOtherFooIdentity = ( (Identity) someOtherFoo ).identity().get();
-        String basicFooIdentity = ( (Identity) basicFoo ).identity().get();
-
-        uow.complete();
-
-        uow = module.newUnitOfWork();
-
-        assertEquals( CATHEDRAL, uow.get( SomeOtherFoo.class, someOtherFooIdentity ).bar() );
-        assertEquals( BAZAR, uow.get( BasicFoo.class, basicFooIdentity ).bar() );
-        assertEquals( CATHEDRAL, uow.get( Foo.class, someOtherFooIdentity ).bar() );
-        assertEquals( BAZAR, uow.get( Foo.class, basicFooIdentity ).bar() );
-
-        uow.discard();
-    }
-
-    @Test
-    public void services()
-        throws ActivationException, AssemblyException
-    {
-        Module module = new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.services( SomeOtherFoo.class );
-            }
-
-        }.module();
-
-        assertEquals( CATHEDRAL, module.findService( SomeOtherFoo.class ).get().bar() );
-        assertEquals( CATHEDRAL, module.findService( BasicFoo.class ).get().bar() );
-        assertEquals( CATHEDRAL, module.findService( Foo.class ).get().bar() );
-    }
-
-    @Test
-    public void servicesPluralDeclaration()
-        throws ActivationException, AssemblyException
-    {
-        Module module = new SingletonAssembler()
-        {
-
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.services( SomeOtherFoo.class, BasicFoo.class );
-            }
-
-        }.module();
-
-        assertEquals( 1, Iterables.count( module.findServices( SomeOtherFoo.class ) ) );
-        assertEquals( 2, Iterables.count( module.findServices( BasicFoo.class ) ) );
-        assertEquals( 2, Iterables.count( module.findServices( Foo.class ) ) );
-
-        assertEquals( CATHEDRAL, module.findService( SomeOtherFoo.class ).get().bar() );
-
-        // Exact type match first even if it is assembled _after_ an assignable, the assignable comes after
-        Iterator<ServiceReference<BasicFoo>> basicFoos = module.findServices( BasicFoo.class ).iterator();
-        assertEquals( BAZAR, basicFoos.next().get().bar() );
-        assertEquals( CATHEDRAL, basicFoos.next().get().bar() );
-        assertFalse( basicFoos.hasNext() );
-
-        // No exact type match, all assembled are assignable, follows assembly Type order
-        Iterator<ServiceReference<Foo>> foos = module.findServices( Foo.class ).iterator();
-        assertEquals( CATHEDRAL, foos.next().get().bar() );
-        assertEquals( BAZAR, foos.next().get().bar() );
-        assertFalse( foos.hasNext() );
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/threaded/ContextCompositeTest.java b/core/runtime/src/test/java/org/qi4j/runtime/threaded/ContextCompositeTest.java
deleted file mode 100644
index 6631b68..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/threaded/ContextCompositeTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.threaded;
-
-import org.junit.Test;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.composite.CompositeContext;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-
-public class ContextCompositeTest
-    extends AbstractQi4jTest
-{
-
-    @Test
-    public void testThreadScope()
-        throws InterruptedException
-    {
-        for( int i = 0; i < 5; i++ )
-        {
-            TransientBuilder<MyCompositeContext> builder = module.newTransientBuilder( MyCompositeContext.class );
-            builder.prototypeFor( MyData.class ).data().set( 0 );
-            MyCompositeContext context = new CompositeContext<MyCompositeContext>( module, MyCompositeContext.class ).proxy();
-
-            Worker w1;
-            Worker w2;
-            MyCompositeContext c1 = builder.newInstance();
-            {
-                w1 = new Worker( "w1", context, 100, 0 );
-                w2 = new Worker( "w2", context, 400, 20 );
-                w2.start();
-                w1.start();
-            }
-            w1.join();
-            w2.join();
-            System.out.println( "W1: " + w1.getData() );
-            System.out.println( "W2: " + w2.getData() );
-            assertEquals( 0, (int) c1.data().get() );
-            assertEquals( 100, w1.getData() );
-            assertEquals( 400, w2.getData() );
-        }
-    }
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( MyCompositeContext.class );
-    }
-
-    public static interface MyCompositeContext
-        extends TransientComposite, MyData
-    {
-    }
-
-    public static interface MyData
-    {
-        @UseDefaults
-        Property<Integer> data();
-    }
-
-    static class Worker
-        extends Thread
-    {
-        private MyCompositeContext composite;
-        private int loops;
-        private final String spaces;
-        private int data;
-
-        public Worker( String name, MyCompositeContext composite, int loops, int spaces )
-        {
-            super( name );
-            this.composite = composite;
-            this.loops = loops;
-            StringBuilder builder = new StringBuilder();
-            for( int i = 0; i < spaces; i++ )
-            {
-                builder.append( " " );
-            }
-            this.spaces = builder.toString();
-        }
-
-        public void run()
-        {
-            int counter = 0;
-            int mismatchCounter = 0;
-            Property<Integer> readProperty = composite.data();
-            Property<Integer> writeProperty = composite.data();
-            try
-            {
-                int oldValue = 0;
-                for( int i = 0; i < loops; i++ )
-                {
-                    int value;
-                    value = readProperty.get();
-                    if( oldValue != value )
-                    {
-                        mismatchCounter++;
-                    }
-                    value = value + 1;
-                    oldValue = value;
-                    Thread.sleep( Math.round( Math.random() * 3 ) );
-                    writeProperty.set( value );
-                    counter++;
-                }
-            }
-            catch( InterruptedException e )
-            {
-                e.printStackTrace();
-            }
-            data = composite.data().get();
-            System.out
-                .println( counter + "/" + loops + "    " + data + ", " + mismatchCounter + ", " + System.identityHashCode( readProperty ) + ", " + System
-                    .identityHashCode( writeProperty ) );
-        }
-
-        public int getData()
-        {
-            return data;
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/transients/TransientBuilderFactoryTest.java b/core/runtime/src/test/java/org/qi4j/runtime/transients/TransientBuilderFactoryTest.java
deleted file mode 100644
index 85c002c..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/transients/TransientBuilderFactoryTest.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.transients;
-
-import java.lang.reflect.Method;
-import org.hamcrest.core.IsEqual;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.composite.NoSuchTransientException;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.concern.GenericConcern;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.library.constraints.annotation.MaxLength;
-
-import static org.junit.Assert.assertThat;
-
-/**
- * Unit tests for CompositeBuilderFactory.
- */
-public class TransientBuilderFactoryTest
-{
-
-    /**
-     * Tests that an transient builder cannot be created for an unregistered object.
-     *
-     * @throws Exception expected
-     */
-    @Test( expected = NoSuchTransientException.class )
-    public void newBuilderForUnregisteredComposite()
-        throws Exception
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-            }
-        };
-        assembler.module().newTransientBuilder( AnyComposite.class );
-    }
-
-    /**
-     * Tests that an transient builder cannot be created for a 'null' type.
-     *
-     * @throws Exception expected
-     */
-    @Test( expected = NullArgumentException.class )
-    public void newBuilderForNullType()
-        throws Exception
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-            }
-        };
-        assembler.module().newTransientBuilder( null );
-    }
-
-    /**
-     * Tests that a transient composite instance cannot be created for a 'null' type.
-     *
-     * @throws Exception expected
-     */
-    @Test( expected = NullArgumentException.class )
-    public void newInstanceForNullType()
-        throws Exception
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-            }
-        };
-        assembler.module().newTransient( null );
-    }
-
-    /**
-     * Tests that an object builder can be created for an registered object.
-     */
-    @Test
-    public void newBuilderForRegisteredComposite()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( AnyComposite.class );
-            }
-        };
-        assembler.module().newTransientBuilder( AnyComposite.class );
-    }
-
-    /**
-     * Tests that an object can be created for an registered object class.
-     */
-    @Test
-    public void newInstanceForRegisteredComposite()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( AnyComposite.class );
-            }
-        };
-        assembler.module().newTransientBuilder( AnyComposite.class );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void testClassAsTransient()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( AnyTransient.class );
-            }
-        };
-
-        AnyTransient anyTransient = assembler.module().newTransient( AnyTransient.class );
-        assertThat( anyTransient.hello( "me" ), new IsEqual<String>( "Hello ME from Module 1" ) );
-
-        assertThat( anyTransient.hello( "World" ), new IsEqual<String>( "Hello WORLD from ME" ) );
-        anyTransient.hello( "Universe" );
-    }
-
-    public static interface AnyComposite
-        extends TransientComposite
-    {
-    }
-
-    public static class CapitalizeConcern
-        extends GenericConcern
-    {
-        @Override
-        public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-        {
-            if( args != null )
-            {
-                args[ 0 ] = ( (String) args[ 0 ] ).toUpperCase();
-                return next.invoke( proxy, method, args );
-            }
-            else
-            {
-                return next.invoke( proxy, method, args );
-            }
-        }
-    }
-
-    @Concerns( CapitalizeConcern.class )
-    public static class AnyTransient
-        implements TransientComposite
-    {
-        @Structure
-        Module module;
-
-        public String hello( @MaxLength( 5 ) String name )
-        {
-            try
-            {
-                String from = data.foo().get();
-                if( from.length() == 0 )
-                {
-                    from = module.name();
-                }
-                return "Hello " + name + " from " + from;
-            }
-            finally
-            {
-                data.foo().set( name );
-            }
-        }
-
-        @This
-        AnyData data;
-    }
-
-    public interface AnyData
-    {
-        @UseDefaults
-        Property<String> foo();
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/transients/TransientVisibilityTest.java b/core/runtime/src/test/java/org/qi4j/runtime/transients/TransientVisibilityTest.java
deleted file mode 100644
index 0b3ac0e..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/transients/TransientVisibilityTest.java
+++ /dev/null
@@ -1,893 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.transients;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.NoSuchTransientException;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.ApplicationAssemblerAdapter;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-
-public class TransientVisibilityTest
-{
-    private Energy4Java qi4j;
-    private Module module;
-    private Application app;
-
-    @Before
-    public void setup()
-        throws Exception
-    {
-        qi4j = new Energy4Java();
-
-        Assembler[][][] assemblers = new Assembler[][][]
-            {
-                { // Layer Above
-                  {
-                      new AboveAssembler()
-                  }
-                },
-                { // Layer From
-                  { // From Module
-                    new FromAssembler(),
-                  },
-                  { // Beside Module
-                    new BesideAssembler()
-                  }
-                },
-                { // Layer Below
-                  {
-                      new BelowAssembler()
-                  }
-                }
-            };
-        app = qi4j.newApplication( new ApplicationAssemblerAdapter( assemblers )
-        {
-        } );
-        app.activate();
-        module = app.findModule( "From Layer", "From" );
-    }
-
-    @After
-    public void tearDown()
-        throws Exception
-    {
-        app.passivate();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.besideLayerVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromServiceWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.belowApplicationVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromServiceWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.belowLayerVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromServiceWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.belowModuleVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromServiceWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.aboveApplicationVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromServiceWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.aboveLayerVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromServiceWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.aboveModuleVisible();
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.moduleApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.moduleLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.moduleModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.besideApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.besideLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromEntityWhenAccessingBesideModuleVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.besideModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.belowApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromEntityWhenAccessingBelowLayerVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.belowLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromEntityWhenAccessingBelowModuleVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.belowModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromEntityWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.aboveApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromEntityWhenAccessingAboveLayerVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.aboveLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromEntityWhenAccessingAboveModuleVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.aboveModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.besideLayerVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromValueWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.belowApplicationVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromValueWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.belowLayerVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromValueWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.belowModuleVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromValueWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.aboveApplicationVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromValueWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.aboveLayerVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromValueWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.aboveModuleVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.besideLayerVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromTransientWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.belowApplicationVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromTransientWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.belowLayerVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromTransientWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.belowModuleVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromTransientWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.aboveApplicationVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromTransientWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.aboveLayerVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromTransientWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.aboveModuleVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.besideLayerVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromObjectWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.belowApplicationVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromObjectWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.belowLayerVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromObjectWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.belowModuleVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromObjectWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.aboveApplicationVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromObjectWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.aboveLayerVisible();
-    }
-
-    @Test( expected = NoSuchTransientException.class )
-    public void givenFromObjectWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.aboveModuleVisible();
-    }
-
-    private static class FromAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.layer().setName( "From Layer" );
-            module.setName( "From" );
-            module.services( FromService.class );
-            module.entities( FromEntity.class );
-            module.transients( FromTransient.class );
-            module.values( FromValue.class );
-            module.objects( FromObject.class );
-
-            module.transients( ModuleApplicationVisible.class ).visibleIn( Visibility.application );
-            module.transients( ModuleLayerVisible.class ).visibleIn( Visibility.layer );
-            module.transients( ModuleModuleVisible.class ).visibleIn( Visibility.module );
-        }
-    }
-
-    private static class BelowAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.layer().setName( "Below Layer" );
-            module.setName( "Below" );
-            module.transients( BelowApplicationVisible.class ).visibleIn( Visibility.application );
-            module.transients( BelowLayerVisible.class ).visibleIn( Visibility.layer );
-            module.transients( BelowModuleVisible.class ).visibleIn( Visibility.module );
-
-            new EntityTestAssembler().visibleIn( Visibility.application ).assemble( module );
-        }
-    }
-
-    private static class AboveAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.layer().setName( "Above Layer" );
-            module.setName( "Above" );
-            module.transients( AboveApplicationVisible.class ).visibleIn( Visibility.application );
-            module.transients( AboveLayerVisible.class ).visibleIn( Visibility.layer );
-            module.transients( AboveModuleVisible.class ).visibleIn( Visibility.module );
-        }
-    }
-
-    private static class BesideAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.setName( "Beside" );
-            module.transients( BesideApplicationVisible.class ).visibleIn( Visibility.application );
-            module.transients( BesideLayerVisible.class ).visibleIn( Visibility.layer );
-            module.transients( BesideModuleVisible.class ).visibleIn( Visibility.module );
-        }
-    }
-
-    @Mixins( Mixin.class )
-    public interface From
-    {
-        void moduleApplicationVisible();
-
-        void moduleLayerVisible();
-
-        void moduleModuleVisible();
-
-        void besideApplicationVisible();
-
-        void besideLayerVisible();
-
-        void besideModuleVisible();
-
-        void belowApplicationVisible();
-
-        void belowLayerVisible();
-
-        void belowModuleVisible();
-
-        void aboveApplicationVisible();
-
-        void aboveLayerVisible();
-
-        void aboveModuleVisible();
-    }
-
-    public interface FromValue extends From, ValueComposite
-    {
-    }
-
-    public interface FromEntity extends From, EntityComposite
-    {
-    }
-
-    public interface FromService extends From, ServiceComposite
-    {
-    }
-
-    public interface FromTransient extends From, TransientComposite
-    {
-    }
-
-    public static class FromObject extends Mixin
-    {
-    }
-
-    public abstract static class Mixin
-        implements From
-    {
-        @Structure
-        private Module module;
-
-        @Override
-        public void moduleApplicationVisible()
-        {
-            TransientBuilder<ModuleApplicationVisible> builder = module.newTransientBuilder( ModuleApplicationVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void moduleLayerVisible()
-        {
-            TransientBuilder<ModuleLayerVisible> builder = module.newTransientBuilder( ModuleLayerVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void moduleModuleVisible()
-        {
-            TransientBuilder<ModuleModuleVisible> builder = module.newTransientBuilder( ModuleModuleVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void besideApplicationVisible()
-        {
-            TransientBuilder<BesideApplicationVisible> builder = module.newTransientBuilder( BesideApplicationVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void besideLayerVisible()
-        {
-            TransientBuilder<BesideLayerVisible> builder = module.newTransientBuilder( BesideLayerVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void besideModuleVisible()
-        {
-            TransientBuilder<BesideModuleVisible> builder = module.newTransientBuilder( BesideModuleVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void belowApplicationVisible()
-        {
-            TransientBuilder<BelowApplicationVisible> builder = module.newTransientBuilder( BelowApplicationVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void belowLayerVisible()
-        {
-            TransientBuilder<BelowLayerVisible> builder = module.newTransientBuilder( BelowLayerVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void belowModuleVisible()
-        {
-            TransientBuilder<BelowModuleVisible> builder = module.newTransientBuilder( BelowModuleVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void aboveApplicationVisible()
-        {
-            TransientBuilder<AboveApplicationVisible> builder = module.newTransientBuilder( AboveApplicationVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void aboveLayerVisible()
-        {
-            TransientBuilder<AboveLayerVisible> builder = module.newTransientBuilder( AboveLayerVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void aboveModuleVisible()
-        {
-            TransientBuilder<AboveModuleVisible> builder = module.newTransientBuilder( AboveModuleVisible.class );
-            builder.newInstance();
-        }
-    }
-
-    public interface ModuleApplicationVisible extends TransientComposite
-    {
-    }
-
-    public interface ModuleLayerVisible extends TransientComposite
-    {
-    }
-
-    public interface ModuleModuleVisible extends TransientComposite
-    {
-    }
-
-    public interface BesideApplicationVisible extends TransientComposite
-    {
-    }
-
-    public interface BesideLayerVisible extends TransientComposite
-    {
-    }
-
-    public interface BesideModuleVisible extends TransientComposite
-    {
-    }
-
-    public interface BelowApplicationVisible extends TransientComposite
-    {
-    }
-
-    public interface BelowLayerVisible extends TransientComposite
-    {
-    }
-
-    public interface BelowModuleVisible extends TransientComposite
-    {
-    }
-
-    public interface AboveApplicationVisible extends TransientComposite
-    {
-    }
-
-    public interface AboveLayerVisible extends TransientComposite
-    {
-    }
-
-    public interface AboveModuleVisible extends TransientComposite
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/unitofwork/AutoCloseableUoWTest.java b/core/runtime/src/test/java/org/qi4j/runtime/unitofwork/AutoCloseableUoWTest.java
deleted file mode 100644
index 79dc232..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/unitofwork/AutoCloseableUoWTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2013, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.unitofwork;
-
-import org.junit.After;
-import org.junit.Test;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-/**
- * Assert that Automatic Resource Management (ie. Java 7 try-with-resources) work on UoWs.
- */
-public class AutoCloseableUoWTest
-    extends AbstractQi4jTest
-{
-
-    public interface TestEntity
-    {
-
-        Property<String> mandatory();
-
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.entities( TestEntity.class );
-    }
-
-    @Test
-    public void givenGoodAutoCloseableUoWWhenTryWithResourceExpectSuccess()
-        throws UnitOfWorkCompletionException
-    {
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            EntityBuilder<TestEntity> builder = uow.newEntityBuilder( TestEntity.class );
-            builder.instance().mandatory().set( "Mandatory property" );
-            builder.newInstance();
-            uow.complete();
-        }
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void givenWrongAutoCloseableUoWWhenTryWithResourceExpectSuccess()
-        throws UnitOfWorkCompletionException
-    {
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            uow.newEntity( TestEntity.class );
-            uow.complete();
-        }
-    }
-
-    @After
-    public void afterEachTest()
-    {
-        assertThat( module.isUnitOfWorkActive(), is( false ) );
-    }
-
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/unitofwork/PrivateEntityUnitOfWorkTest.java b/core/runtime/src/test/java/org/qi4j/runtime/unitofwork/PrivateEntityUnitOfWorkTest.java
deleted file mode 100644
index 98f6d6b..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/unitofwork/PrivateEntityUnitOfWorkTest.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.unitofwork;
-
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.EntityTypeNotFoundException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.ApplicationAssemblyFactory;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.fail;
-import static org.qi4j.api.common.Visibility.application;
-
-/**
- * JAVADOC
- */
-public class PrivateEntityUnitOfWorkTest
-{
-    @Structure
-    private UnitOfWorkFactory uowf;
-
-    @Test
-    public void givenAppWithPrivateEntityWhenUnitOfWorkCanSeeItThenCanCommit()
-        throws Exception
-    {
-        System.setProperty( "qi4j.compacttrace", "off" );
-
-        Energy4Java is = new Energy4Java();
-        Application app = is.newApplication( new ApplicationAssembler()
-        {
-            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-                throws AssemblyException
-            {
-                return applicationFactory.newApplicationAssembly( new Assembler[][][]{
-                    {
-                        {
-                            new Assembler()
-                            {
-                                public void assemble( ModuleAssembly module )
-                                    throws AssemblyException
-                                {
-                                    module.objects( PrivateEntityUnitOfWorkTest.class );
-                                }
-                            }
-                        }
-                    },
-                    {
-                        {
-                            new Assembler()
-                            {
-                                public void assemble( ModuleAssembly module )
-                                    throws AssemblyException
-                                {
-                                    module.entities( ProductEntity.class );
-                                    module.entities( ProductCatalogEntity.class ).visibleIn( application );
-                                    module.values( ProductInfo.class );
-                                    new EntityTestAssembler().assemble( module );
-                                }
-                            }
-                        }
-                    }
-                } );
-            }
-        } );
-        app.activate();
-
-        Module module = app.findModule( "Layer 1", "Module 1" );
-        module.injectTo( this );
-
-        UnitOfWork unitOfWork = uowf.newUnitOfWork();
-
-        try
-        {
-            unitOfWork.newEntity( ProductEntity.class );
-            fail( "Should not be able to create product here" );
-        }
-        catch( EntityTypeNotFoundException e )
-        {
-            // Ok
-            ProductCatalog catalog = unitOfWork.newEntity( ProductCatalog.class, "1" );
-            unitOfWork.complete();
-        }
-        unitOfWork = uowf.newUnitOfWork();
-
-        String id;
-        try
-        {
-            ProductCatalog catalog = unitOfWork.get( ProductCatalog.class, "1" );
-            id = ( (Identity) catalog.newProduct() ).identity().get();
-            unitOfWork.complete();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-
-        unitOfWork = module.newUnitOfWork();
-        try
-        {
-            ProductCatalog catalog = unitOfWork.get( ProductCatalog.class, "1" );
-            Product product = catalog.findProduct( id );
-            product.price().set( 100 );
-            unitOfWork.complete();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    public interface ProductCatalog
-    {
-        Product newProduct();
-
-        Product findProduct( String id );
-    }
-
-    @Mixins( ProductCatalogEntity.ProductRepositoryMixin.class )
-    interface ProductCatalogEntity
-        extends ProductCatalog, EntityComposite
-    {
-        abstract class ProductRepositoryMixin
-            implements ProductCatalog
-        {
-            @Structure
-            private UnitOfWorkFactory uowf;
-
-            @Structure
-            private ValueBuilderFactory vbf;
-
-            public Product newProduct()
-            {
-                ValueBuilder<ProductInfo> vb = vbf.newValueBuilder( ProductInfo.class );
-                vb.prototype().description().set( "Some mundane description" );
-                vb.prototype().weight().set( 1.0f );
-                ProductInfo info = vb.newInstance();
-
-                UnitOfWork uow = uowf.currentUnitOfWork();
-                EntityBuilder<Product> eb = uow.newEntityBuilder( Product.class );
-                eb.instance().name().set( "Product Name" );
-                eb.instance().price().set( 100 );
-                eb.instance().productInfo().set( info );
-                return eb.newInstance();
-            }
-
-            public Product findProduct( String id )
-            {
-                UnitOfWork uow = uowf.currentUnitOfWork();
-                return uow.get( Product.class, id );
-            }
-        }
-    }
-
-    @Mixins( { AccountMixin.class } )
-    public interface AccountComposite
-        extends Account, EntityComposite
-    {
-    }
-
-    public interface Account
-    {
-        Property<Integer> balance();
-
-        void add( int amount );
-
-        void remove( int amount );
-    }
-
-    public static abstract class AccountMixin
-        implements Account
-    {
-        public void add( int amount )
-        {
-            balance().set( balance().get() + amount );
-        }
-
-        public void remove( int amount )
-        {
-            balance().set( balance().get() - amount );
-        }
-    }
-
-    public interface Customer
-    {
-        Association<Account> account();
-
-        Property<String> name();
-    }
-
-    public interface CustomerComposite
-        extends Customer, EntityComposite
-    {
-    }
-
-    public interface LineItem
-    {
-        Association<Product> product();
-    }
-
-    public interface LineItemComposite
-        extends LineItem, EntityComposite
-    {
-    }
-
-    public interface Order
-    {
-        Association<Customer> customer();
-
-        ManyAssociation<LineItem> lineItems();
-    }
-
-    public interface OrderComposite
-        extends Order, EntityComposite
-    {
-    }
-
-    public interface ProductInfo
-        extends ValueComposite
-    {
-        Property<String> description();
-
-        Property<Float> weight();
-    }
-
-    public interface Product
-    {
-        Property<String> name();
-
-        Property<Integer> price();
-
-        Property<ProductInfo> productInfo();
-    }
-
-    public interface ProductEntity
-        extends Product, EntityComposite
-    {
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/unitofwork/RemovalTest.java b/core/runtime/src/test/java/org/qi4j/runtime/unitofwork/RemovalTest.java
deleted file mode 100644
index bfa41cf..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/unitofwork/RemovalTest.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.unitofwork;
-
-import org.junit.Test;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-public class RemovalTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.entities( Abc.class );
-    }
-
-    @Test
-    public void givenUnitOfWorkHasBeenCreateWhenCreatingNewEntityThenFindNewEntityWithGet()
-        throws Exception
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            EntityBuilder<Abc> builder = uow.newEntityBuilder( Abc.class, "123" );
-            builder.instance().name().set( "Niclas" );
-            builder.newInstance();
-            uow.complete();
-            uow = module.newUnitOfWork();
-            Abc abc = uow.get( Abc.class, "123" );
-            assertEquals( "Niclas", abc.name().get() );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void givenEntityCreatedWhenRemovingEntityThenFindNewEntityShouldNotExist()
-        throws Exception
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            EntityBuilder<Abc> builder = uow.newEntityBuilder( Abc.class, "123" );
-            builder.instance().name().set( "Niclas" );
-            builder.newInstance();
-            uow.complete();
-            uow = module.newUnitOfWork();
-            Abc abc = uow.get( Abc.class, "123" );
-            assertEquals( "Niclas", abc.name().get() );
-            uow.remove( abc );
-            uow.complete();
-            uow = module.newUnitOfWork();
-            uow.get( Abc.class, "123" );
-            fail( "This '123' entity should not exist." );
-        }
-        catch( NoSuchEntityException e )
-        {
-            // Expected.
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void givenDetachedEntityWhenRemovingEntityThenFindNewEntityShouldNotExist()
-        throws Exception
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            EntityBuilder<Abc> builder = uow.newEntityBuilder( Abc.class, "123" );
-            builder.instance().name().set( "Niclas" );
-            Abc abc = builder.newInstance();
-            uow.complete();
-            uow = module.newUnitOfWork();
-            abc = uow.get( abc );  // Attach the detached entity to 'uow' session.
-            uow.remove( abc );
-            uow.complete();
-            uow = module.newUnitOfWork();
-            uow.get( Abc.class, "123" );
-            fail( "This '123' entity should not exist." );
-        }
-        catch( NoSuchEntityException e )
-        {
-            // Expected.
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void givenEntityCreatedWhenRemovingEntityBeforeCompletingUowThenFindNewEntityShouldNotExist()
-        throws Exception
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            EntityBuilder<Abc> builder = uow.newEntityBuilder( Abc.class, "123" );
-            builder.instance().name().set( "Niclas" );
-            Abc abc = builder.newInstance();
-            uow.remove( abc );
-            uow.complete();
-            uow = module.newUnitOfWork();
-            uow.get( Abc.class, "123" );
-            fail( "This '123' entity should not exist." );
-        }
-        catch( NoSuchEntityException e )
-        {
-            // Expected.
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    public interface Abc
-        extends EntityComposite
-    {
-        Property<String> name();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/unitofwork/UnitOfWorkFactoryTest.java b/core/runtime/src/test/java/org/qi4j/runtime/unitofwork/UnitOfWorkFactoryTest.java
deleted file mode 100644
index ae0b499..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/unitofwork/UnitOfWorkFactoryTest.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.unitofwork;
-
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-public class UnitOfWorkFactoryTest
-    extends AbstractQi4jTest
-{
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( AccountComposite.class,
-                         OrderComposite.class,
-                         ProductEntity.class,
-                         CustomerComposite.class );
-
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Test
-    public void testUnitOfWork()
-        throws Exception
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-
-        // Create product
-        EntityBuilder<ProductEntity> cb = unitOfWork.newEntityBuilder( ProductEntity.class );
-        cb.instance().name().set( "Chair" );
-        cb.instance().price().set( 57 );
-        Product chair = cb.newInstance();
-
-        String actual = chair.name().get();
-        org.junit.Assert.assertThat( "Chair.name()", actual, org.hamcrest.CoreMatchers.equalTo( "Chair" ) );
-        org.junit.Assert.assertThat( "Chair.price()", chair.price().get(), org.hamcrest.CoreMatchers.equalTo( 57 ) );
-
-        unitOfWork.complete();
-    }
-
-    @Mixins( { AccountMixin.class } )
-    public interface AccountComposite
-        extends Account, EntityComposite
-    {
-    }
-
-    public interface Account
-    {
-        Property<Integer> balance();
-
-        void add( int amount );
-
-        void remove( int amount );
-    }
-
-    public static abstract class AccountMixin
-        implements Account
-    {
-        public void add( int amount )
-        {
-            balance().set( balance().get() + amount );
-        }
-
-        public void remove( int amount )
-        {
-            balance().set( balance().get() - amount );
-        }
-    }
-
-    public interface Customer
-    {
-        Association<Account> account();
-
-        Property<String> name();
-    }
-
-    public interface CustomerComposite
-        extends Customer, EntityComposite
-    {
-    }
-
-    public interface LineItem
-    {
-        Association<Product> product();
-    }
-
-    public interface LineItemComposite
-        extends LineItem, EntityComposite
-    {
-    }
-
-    public interface Order
-    {
-        Association<Customer> customer();
-
-        ManyAssociation<LineItem> lineItems();
-    }
-
-    public interface OrderComposite
-        extends Order, EntityComposite
-    {
-    }
-
-    public interface Product
-    {
-        @UseDefaults
-        Property<String> name();
-
-        @UseDefaults
-        Property<Integer> price();
-    }
-
-    public interface ProductEntity
-        extends Product, EntityComposite
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/util/AnnotationsTest.java b/core/runtime/src/test/java/org/qi4j/runtime/util/AnnotationsTest.java
deleted file mode 100644
index 60f1188..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/util/AnnotationsTest.java
+++ /dev/null
@@ -1,50 +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.qi4j.runtime.util;
-
-import java.lang.reflect.Type;
-import java.util.Collection;
-import org.junit.Test;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.sideeffect.SideEffects;
-import org.qi4j.api.util.Annotations;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-public class AnnotationsTest
-{
-    @Mixins( value = AnnotatedClass.class )
-    interface AnnotatedClass<T>
-    {
-        Collection<T> list();
-    }
-
-    @Test
-    public void getAnnotationOrNull()
-        throws NoSuchMethodException
-    {
-        assertNotNull( "Mixins annotation found", Annotations.annotationOn( AnnotatedClass.class, Mixins.class ) );
-
-        assertNull( "No SideEffects annotation found", Annotations.annotationOn( AnnotatedClass.class, SideEffects.class ) );
-
-        final Type returnType = AnnotatedClass.class.getDeclaredMethod( "list" ).getGenericReturnType();
-        assertNull( "Null on no class type", Annotations.annotationOn( returnType, Mixins.class ) );
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/value/NestedValueBuilderTest.java b/core/runtime/src/test/java/org/qi4j/runtime/value/NestedValueBuilderTest.java
deleted file mode 100644
index 27bee6c..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/value/NestedValueBuilderTest.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
-* Copyright (c) 2012, Paul Merlin. All Rights Reserved.
-*
-* Licensed 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.qi4j.runtime.value;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.junit.Test;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.fail;
-
-public class NestedValueBuilderTest
-    extends AbstractQi4jTest
-{
-
-    static interface InnerValue
-        extends ValueComposite
-    {
-
-        Property<List<String>> listProp();
-
-        Property<Map<String, String>> mapProp();
-    }
-
-    static interface InnerDefaultedValue
-        extends ValueComposite
-    {
-
-        @UseDefaults
-        Property<List<String>> listPropDefault();
-
-        @UseDefaults
-        Property<Map<String, String>> mapPropDefault();
-    }
-
-    static interface OuterValue
-        extends ValueComposite
-    {
-
-        Property<List<InnerValue>> innerListProp();
-    }
-
-    static interface OuterDefaultedValue
-        extends ValueComposite
-    {
-
-        @UseDefaults
-        Property<List<InnerDefaultedValue>> innerListPropDefault();
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.values( InnerValue.class, InnerDefaultedValue.class, OuterValue.class, OuterDefaultedValue.class );
-    }
-
-    @Test
-    public void testInner()
-    {
-        ValueBuilder<InnerValue> innerBuilder = module.newValueBuilder( InnerValue.class );
-        InnerValue inner = innerBuilder.prototype();
-        inner.listProp().set( new ArrayList<String>() );
-        inner.mapProp().set( new HashMap<String, String>() );
-        inner = innerBuilder.newInstance();
-        // If we reach this point, value creation went well
-        try
-        {
-            inner.listProp().get().add( "Should be immutable now!" ); // Must not be allowed
-            fail( "List is not immutable!" );
-        }
-        catch( UnsupportedOperationException e )
-        {
-            // expected
-        }
-        try
-        {
-            inner.mapProp().get().put( "Should be immutable now!", "" ); // Must not be allowed
-            fail( "Map is not immutable!" );
-        }
-        catch( UnsupportedOperationException e )
-        {
-            // expected
-        }
-    }
-
-    @Test
-    public void testOuter()
-    {
-        ValueBuilder<InnerValue> innerBuilder = module.newValueBuilder( InnerValue.class );
-        InnerValue innerPrototype = innerBuilder.prototype();
-        innerPrototype.listProp().set( new ArrayList<String>() );
-        innerPrototype.mapProp().set( new HashMap<String, String>() );
-        InnerValue innerInstance = innerBuilder.newInstance();
-        ValueBuilder<OuterValue> outerBuilder = module.newValueBuilder( OuterValue.class );
-        OuterValue outerPrototype = outerBuilder.prototype();
-        List<InnerValue> inners = new ArrayList<InnerValue>();
-        inners.add( innerInstance );
-        outerPrototype.innerListProp().set( inners );
-        OuterValue outerInstance = outerBuilder.newInstance();
-        System.out.println( outerInstance.toString() );
-        // If we reach this point, value creation went well
-        try
-        {
-            outerInstance.innerListProp().get().add( innerInstance ); // Must not be allowed
-            fail( "List is not immutable!" );
-        }
-        catch( UnsupportedOperationException e )
-        {
-            // expected
-        }
-    }
-
-    @Test
-    public void testDefaultedInner()
-    {
-        ValueBuilder<InnerDefaultedValue> innerBuilder = module.newValueBuilder( InnerDefaultedValue.class );
-        InnerDefaultedValue inner = innerBuilder.newInstance();
-        // If we reach this point, value creation went well
-        try
-        {
-            inner.listPropDefault().get().add( "Should not work!" ); // Must not be allowed
-            fail( "List is not immutable!" );
-        }
-        catch( UnsupportedOperationException e )
-        {
-            // expected
-        }
-        try
-        {
-            inner.mapPropDefault().get().put( "Should not work!", "" ); // Must not be allowed
-            fail( "List is not immutable!" );
-        }
-        catch( UnsupportedOperationException e )
-        {
-            // expected
-        }
-    }
-
-    @Test
-    public void testDefaultedOuter()
-    {
-        ValueBuilder<InnerDefaultedValue> innerBuilder = module.newValueBuilder( InnerDefaultedValue.class );
-        InnerDefaultedValue innerInstance = innerBuilder.newInstance();
-        ValueBuilder<OuterDefaultedValue> outerBuilder = module.newValueBuilder( OuterDefaultedValue.class );
-        OuterDefaultedValue outerPrototype = outerBuilder.prototype();
-        List<InnerDefaultedValue> inners = new ArrayList<InnerDefaultedValue>();
-        inners.add( innerInstance );
-        outerPrototype.innerListPropDefault().set( inners );
-        OuterDefaultedValue outerInstance = outerBuilder.newInstance();
-        System.out.println( outerPrototype.toString() );
-        // If we reach this point, value creation went well
-        try
-        {
-            outerInstance.innerListPropDefault().get().add( innerInstance ); // Must not be allowed
-            fail( "List is not immutable!" );
-        }
-        catch( UnsupportedOperationException e )
-        {
-            // expected
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/value/ValueComposite2Test.java b/core/runtime/src/test/java/org/qi4j/runtime/value/ValueComposite2Test.java
deleted file mode 100644
index 2dd190c..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/value/ValueComposite2Test.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.value;
-
-import java.security.Guard;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.composite.InvalidValueCompositeException;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-public class ValueComposite2Test
-{
-    @Test
-    public void testServiceAndStructureInjectionsAllowedInValueComposite()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler app = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.values( SomeValue.class );
-                module.services( DummyService.class );
-            }
-        };
-        ValueBuilder<Some> builder = app.module().newValueBuilder( Some.class );
-        Some prototype = builder.prototype();
-        Property<String> otherProperty = prototype.other();
-        otherProperty.set( "Abc" );
-        Some value = builder.newInstance();
-        Assert.assertEquals( value.other().get(), "Abc" );
-    }
-
-    @Test( expected = AssemblyException.class )
-    public void testUsesAnnotationIsNotAllowedInValueComposite()
-        throws ActivationException, AssemblyException
-    {
-        new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.values( SomeValue2.class );
-            }
-        };
-    }
-
-    public interface Some
-    {
-        DummyService service();
-
-        Module module();
-
-        Property<String> other();
-    }
-
-    @Mixins( SomeMixin.class )
-    public interface SomeValue
-        extends Some, ValueComposite
-    {
-    }
-
-    public static abstract class SomeMixin
-        implements Some
-    {
-        @Service
-        DummyService service;
-        @Structure
-        Module module;
-
-        public DummyService service()
-        {
-            return service;
-        }
-
-        public Module module()
-        {
-            return module;
-        }
-    }
-
-    @Mixins( SomeMixin2.class )
-    public interface SomeValue2
-        extends Some, ValueComposite
-    {
-    }
-
-    public static abstract class SomeMixin2
-        implements Some
-    {
-        @Uses
-        Guard illegal;
-
-        public DummyService service()
-        {
-            return null;
-        }
-
-        public Module module()
-        {
-            return null;
-        }
-    }
-
-    public static interface DummyService
-        extends ServiceComposite
-    {
-    }
-}
-
-
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/value/ValueCompositeBasicsTest.java b/core/runtime/src/test/java/org/qi4j/runtime/value/ValueCompositeBasicsTest.java
deleted file mode 100644
index 3ad4fd9..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/value/ValueCompositeBasicsTest.java
+++ /dev/null
@@ -1,99 +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.qi4j.runtime.value;
-
-import org.junit.Test;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-
-public class ValueCompositeBasicsTest
-    extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.values( SomeValue.class );
-    }
-
-    @Test
-    public void testEqualsForValueComposite()
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        builder.prototypeFor( SomeInternalState.class ).name().set( "Niclas" );
-        assertEquals("Niclas", builder.prototype().name());
-        SomeValue value1 = builder.newInstance();
-        SomeValue value2 = builder.newInstance();
-        builder.prototypeFor( SomeInternalState.class ).name().set( "Niclas2" );
-        SomeValue value3 = builder.newInstance();
-        assertEquals( value1, value2 );
-        assertFalse( value1.equals( value3 ) );
-    }
-
-    @Test
-    public void testToStringForValueComposite()
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        builder.prototypeFor( SomeInternalState.class ).name().set( "Niclas" );
-        SomeValue underTest = builder.newInstance();
-        assertEquals( "{\"name\":\"Niclas\"}", underTest.toString() );
-    }
-
-    @Test
-    public void testToJSonForValueComposite()
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        builder.prototypeFor( SomeInternalState.class ).name().set( "Niclas" );
-        SomeValue underTest = builder.newInstance();
-        assertEquals( "{\"name\":\"Niclas\"}", underTest.toString() );
-    }
-
-    public abstract static class SomeMixin
-        implements SomeValue
-    {
-        @This
-        private SomeInternalState state;
-
-        @Override
-        public String name()
-        {
-            return state.name().get();
-        }
-    }
-
-    @Mixins( SomeMixin.class )
-    public interface SomeValue
-        //extends ValueComposite
-    {
-        String name();
-    }
-
-    public interface SomeInternalState
-    {
-        Property<String> name();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/value/ValueEqualityTest.java b/core/runtime/src/test/java/org/qi4j/runtime/value/ValueEqualityTest.java
deleted file mode 100644
index e0df77a..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/value/ValueEqualityTest.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2013, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.value;
-
-import org.junit.Test;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.runtime.property.PropertyEqualityTest.AnotherSome;
-import org.qi4j.runtime.property.PropertyEqualityTest.Other;
-import org.qi4j.runtime.property.PropertyEqualityTest.PrimitivesValue;
-import org.qi4j.runtime.property.PropertyEqualityTest.Some;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.not;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.runtime.property.PropertyEqualityTest.buildAnotherSomeValue;
-import static org.qi4j.runtime.property.PropertyEqualityTest.buildAnotherSomeValueWithDifferentState;
-import static org.qi4j.runtime.property.PropertyEqualityTest.buildOtherValue;
-import static org.qi4j.runtime.property.PropertyEqualityTest.buildPrimitivesValue;
-import static org.qi4j.runtime.property.PropertyEqualityTest.buildSomeValue;
-import static org.qi4j.runtime.property.PropertyEqualityTest.buildSomeValueWithDifferentState;
-
-/**
- * Assert that Value equals/hashcode methods combine ValueDescriptor and ValueState.
- */
-public class ValueEqualityTest
-    extends AbstractQi4jTest
-{
-
-    //
-    // --------------------------------------:: Types under test ::-----------------------------------------------------
-    //
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.values( PrimitivesValue.class, Some.class, AnotherSome.class, Other.class );
-    }
-
-    //
-    // -------------------------------:: ValueDescriptor equality tests ::----------------------------------------------
-    //
-    @Test
-    public void givenValuesOfTheSameTypeWhenTestingValueDescriptorEqualityExpectEquals()
-    {
-        Some some = buildSomeValue( module );
-        ValueDescriptor someDescriptor = qi4j.api().valueDescriptorFor( some );
-
-        Some other = buildSomeValue( module );
-        ValueDescriptor otherDescriptor = qi4j.api().valueDescriptorFor( other );
-
-        assertThat( "ValueDescriptors equal",
-                    someDescriptor,
-                    equalTo( otherDescriptor ) );
-        assertThat( "ValueDescriptors hashcode equal",
-                    someDescriptor.hashCode(),
-                    equalTo( otherDescriptor.hashCode() ) );
-    }
-
-    @Test
-    public void givenValuesOfCommonTypesWhenTestingValueDescriptorEqualityExpectNotEquals()
-    {
-        Some some = buildSomeValue( module );
-        ValueDescriptor someDescriptor = qi4j.api().valueDescriptorFor( some );
-
-        PrimitivesValue primitive = buildPrimitivesValue( module );
-        ValueDescriptor primitiveDescriptor = qi4j.api().valueDescriptorFor( primitive );
-
-        assertThat( "ValueDescriptors not equal",
-                    someDescriptor,
-                    not( equalTo( primitiveDescriptor ) ) );
-        assertThat( "ValueDescriptors hashcode not equal",
-                    someDescriptor.hashCode(),
-                    not( equalTo( primitiveDescriptor.hashCode() ) ) );
-    }
-
-    @Test
-    public void givenValuesOfDifferentTypesWhenTestingValueDescriptorEqualityExpectNotEquals()
-    {
-        Some some = buildSomeValue( module );
-        ValueDescriptor someDescriptor = qi4j.api().valueDescriptorFor( some );
-
-        Other other = buildOtherValue( module );
-        ValueDescriptor otherDescriptor = qi4j.api().valueDescriptorFor( other );
-
-        assertThat( "ValueDescriptors not equal",
-                    someDescriptor,
-                    not( equalTo( otherDescriptor ) ) );
-        assertThat( "ValueDescriptors hashcode not equal",
-                    someDescriptor.hashCode(),
-                    not( equalTo( otherDescriptor.hashCode() ) ) );
-    }
-
-    //
-    // ---------------------------------:: Value State equality tests ::------------------------------------------------
-    //
-    @Test
-    public void givenValuesOfSameTypesAndSameStateWhenTestingValueStateEqualityExpectEquals()
-    {
-        Some some = buildSomeValue( module );
-        AssociationStateHolder someState = qi4j.spi().stateOf( (ValueComposite) some );
-
-        Some some2 = buildSomeValue( module );
-        AssociationStateHolder some2State = qi4j.spi().stateOf( (ValueComposite) some2 );
-
-        assertThat( "ValueStates equal",
-                    someState,
-                    equalTo( some2State ) );
-        assertThat( "ValueStates hashcode equal",
-                    someState.hashCode(),
-                    equalTo( some2State.hashCode() ) );
-    }
-
-    @Test
-    public void givenValuesOfSameTypesAndDifferentStateWhenTestingValueStateEqualityExpectNotEquals()
-    {
-        Some some = buildSomeValue( module );
-        AssociationStateHolder someState = qi4j.spi().stateOf( (ValueComposite) some );
-
-        Some some2 = buildSomeValueWithDifferentState( module );
-        AssociationStateHolder some2State = qi4j.spi().stateOf( (ValueComposite) some2 );
-
-        assertThat( "ValueStates not equal",
-                    someState,
-                    not( equalTo( some2State ) ) );
-        assertThat( "ValueStates hashcode not equal",
-                    someState.hashCode(),
-                    not( equalTo( some2State.hashCode() ) ) );
-    }
-
-    @Test
-    public void givenValuesOfDifferentTypesAndSameStateWhenTestingValueStateEqualityExpectEquals()
-    {
-        Some some = buildSomeValue( module );
-        AssociationStateHolder someState = qi4j.spi().stateOf( (ValueComposite) some );
-
-        AnotherSome anotherSome = buildAnotherSomeValue( module );
-        AssociationStateHolder anotherSomeState = qi4j.spi().stateOf( (ValueComposite) anotherSome );
-
-        assertThat( "ValueStates equal",
-                    someState,
-                    equalTo( anotherSomeState ) );
-        assertThat( "ValueStates hashcode equal",
-                    someState.hashCode(),
-                    equalTo( anotherSomeState.hashCode() ) );
-    }
-
-    @Test
-    public void givenValuesOfDifferentTypesAndDifferentStateWhenTestingValueStateEqualityExpectNotEquals()
-    {
-        Some some = buildSomeValue( module );
-        AssociationStateHolder someState = qi4j.spi().stateOf( (ValueComposite) some );
-
-        AnotherSome anotherSome = buildAnotherSomeValueWithDifferentState( module );
-        AssociationStateHolder anotherSomeState = qi4j.spi().stateOf( (ValueComposite) anotherSome );
-
-        assertThat( "ValueStates not equal",
-                    someState,
-                    not( equalTo( anotherSomeState ) ) );
-        assertThat( "ValueStates hashcode not equal",
-                    someState.hashCode(),
-                    not( equalTo( anotherSomeState.hashCode() ) ) );
-    }
-
-    //
-    // ------------------------------------:: Value equality tests ::---------------------------------------------------
-    //
-    @Test
-    public void givenValuesOfSameTypesAndSameStateWhenTestingValueEqualityExpectEquals()
-    {
-        Some some = buildSomeValue( module );
-        Some some2 = buildSomeValue( module );
-        assertThat( "Values equal",
-                    some,
-                    equalTo( some2 ) );
-        assertThat( "Values hashcode equal",
-                    some.hashCode(),
-                    equalTo( some2.hashCode() ) );
-    }
-
-    @Test
-    public void givenValuesOfTheSameTypeWithDifferentStateWhenTestingValueEqualityExpectNotEquals()
-    {
-        Some some = buildSomeValue( module );
-        Some some2 = buildSomeValueWithDifferentState( module );
-        assertThat( "Values not equals",
-                    some,
-                    not( equalTo( some2 ) ) );
-        assertThat( "Values hashcode not equals",
-                    some.hashCode(),
-                    not( equalTo( some2.hashCode() ) ) );
-    }
-
-    @Test
-    public void givenValuesOfDifferentTypesAndSameStateWhenTestingValueEqualityExpectNotEquals()
-    {
-        Some some = buildSomeValue( module );
-        Some anotherSome = buildAnotherSomeValue( module );
-
-        assertThat( "Values not equal",
-                    some,
-                    not( equalTo( anotherSome ) ) );
-        assertThat( "Values hashcode not equal",
-                    some.hashCode(),
-                    not( equalTo( anotherSome.hashCode() ) ) );
-    }
-
-    @Test
-    public void givenValuesOfDifferentTypesAndDifferentStateWhenTestingValueEqualityExpectNotEquals()
-    {
-        Some some = buildSomeValue( module );
-        Some anotherSome = buildAnotherSomeValueWithDifferentState( module );
-        assertThat( "Values not equal",
-                    some,
-                    not( equalTo( anotherSome ) ) );
-        assertThat( "Values hashcode not equal",
-                    some.hashCode(),
-                    not( equalTo( anotherSome.hashCode() ) ) );
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/value/ValueInjectionDeserializationTest.java b/core/runtime/src/test/java/org/qi4j/runtime/value/ValueInjectionDeserializationTest.java
deleted file mode 100644
index c8d0250..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/value/ValueInjectionDeserializationTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.runtime.value;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-public class ValueInjectionDeserializationTest
-    extends AbstractQi4jTest
-{
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( Niclas.class );
-        module.values( SomeValue.class );
-        module.services( DummyService.class );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Test
-    public void testThatServiceAndStructureInjectionWorkForValueWhenEntityRetrievedFromStore()
-        throws Exception
-    {
-        UnitOfWork uow = null;
-        try
-        {
-            ValueBuilder<Some> builder = module.newValueBuilder( Some.class );
-            builder.prototype().data().set( "Niclas" );
-            Some value = builder.newInstance();
-
-            uow = module.newUnitOfWork();
-            EntityBuilder<Niclas> eb = uow.newEntityBuilder( Niclas.class );
-            eb.instance().value().set( value );
-            Niclas niclas1 = eb.newInstance();
-            String id = niclas1.identity().get();
-            uow.complete();
-
-            uow = module.newUnitOfWork();
-            Niclas niclas2 = uow.get( Niclas.class, id );
-            Some someValue = niclas2.value().get();
-            Assert.assertEquals( someValue.data().get(), "Niclas" );
-            Assert.assertNotNull( someValue.module() );
-            Assert.assertNotNull( someValue.service() );
-        }
-        finally
-        {
-            if( uow != null )
-            {
-                uow.discard();
-            }
-        }
-    }
-
-    public interface Niclas
-        extends EntityComposite
-    {
-        Property<Some> value();
-    }
-
-    public interface Some
-    {
-        DummyService service();
-
-        Module module();
-
-        Property<String> data();
-    }
-
-    @Mixins( SomeMixin.class )
-    public interface SomeValue
-        extends Some, ValueComposite
-    {
-    }
-
-    public static abstract class SomeMixin
-        implements Some
-    {
-        @Service
-        DummyService service;
-        @Structure
-        Module module;
-
-        public DummyService service()
-        {
-            return service;
-        }
-
-        public Module module()
-        {
-            return module;
-        }
-    }
-
-    public interface DummyService
-        extends ServiceComposite
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/value/ValueSerializationRegressionTest.java b/core/runtime/src/test/java/org/qi4j/runtime/value/ValueSerializationRegressionTest.java
deleted file mode 100644
index 4684d0e..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/value/ValueSerializationRegressionTest.java
+++ /dev/null
@@ -1,77 +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.qi4j.runtime.value;
-
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-public class ValueSerializationRegressionTest extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( SimpleEntity.class );
-        module.entities( DualFaced.class );
-        module.values( DualFaced.class );
-        module.services( MemoryEntityStoreService.class );
-        module.services( UuidIdentityGeneratorService.class );
-        module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
-    }
-
-    @Test
-    public void givenNewValueWhenConvertingToEntityExpectNewEntityInStore()
-        throws UnitOfWorkCompletionException
-    {
-        ValueBuilder<DualFaced> builder = module.newValueBuilder( DualFaced.class );
-        builder.prototype().identity().set( "1234" );
-        builder.prototype().name().set( "Hedhman" );
-        DualFaced value = builder.newInstance();
-    }
-
-    public interface SimpleEntity extends Identity
-    {
-        Property<String> name();
-    }
-
-    public interface DualFaced extends Identity
-    {
-        Property<String> name();
-
-        Association<SimpleEntity> simple();
-
-        ManyAssociation<SimpleEntity> simples();
-
-        NamedAssociation<SimpleEntity> namedSimples();
-    }
-}
-
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/value/ValueVisibilityTest.java b/core/runtime/src/test/java/org/qi4j/runtime/value/ValueVisibilityTest.java
deleted file mode 100644
index 3785139..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/value/ValueVisibilityTest.java
+++ /dev/null
@@ -1,894 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.runtime.value;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.NoSuchValueException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.ApplicationAssemblerAdapter;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-
-public class ValueVisibilityTest
-{
-
-    private Energy4Java qi4j;
-    private Module module;
-    private Application app;
-
-    @Before
-    public void setup()
-        throws Exception
-    {
-        qi4j = new Energy4Java();
-
-        Assembler[][][] assemblers = new Assembler[][][]
-            {
-                { // Layer Above
-                  {
-                      new AboveAssembler()
-                  }
-                },
-                { // Layer From
-                  { // From Module
-                    new FromAssembler(),
-                  },
-                  { // Beside Module
-                    new BesideAssembler()
-                  }
-                },
-                { // Layer Below
-                  {
-                      new BelowAssembler()
-                  }
-                }
-            };
-        app = qi4j.newApplication( new ApplicationAssemblerAdapter( assemblers )
-        {
-        } );
-        app.activate();
-        module = app.findModule( "From Layer", "From" );
-    }
-
-    @After
-    public void tearDown()
-        throws Exception
-    {
-        app.passivate();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.besideLayerVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromServiceWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromServiceWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.belowApplicationVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromServiceWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.belowLayerVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromServiceWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.belowModuleVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromServiceWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.aboveApplicationVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromServiceWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.aboveLayerVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromServiceWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromService service = module.findService( FromService.class ).get();
-        service.aboveModuleVisible();
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.moduleApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.moduleLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.moduleModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.besideApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.besideLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromEntityWhenAccessingBesideModuleVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.besideModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromEntityWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.belowApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromEntityWhenAccessingBelowLayerVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.belowLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromEntityWhenAccessingBelowModuleVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.belowModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromEntityWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.aboveApplicationVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromEntityWhenAccessingAboveLayerVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.aboveLayerVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromEntityWhenAccessingAboveModuleVisibleExpectException()
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            FromEntity entity = unitOfWork.newEntity( FromEntity.class, "123" );
-            entity.aboveModuleVisible();
-        }
-        finally
-        {
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.discard();
-            }
-        }
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.besideLayerVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromValueWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromValueWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.belowApplicationVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromValueWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.belowLayerVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromValueWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.belowModuleVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromValueWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.aboveApplicationVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromValueWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.aboveLayerVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromValueWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromValue value = module.newValue( FromValue.class );
-        value.aboveModuleVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.besideLayerVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromTransientWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromTransientWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.belowApplicationVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromTransientWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.belowLayerVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromTransientWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.belowModuleVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromTransientWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.aboveApplicationVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromTransientWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.aboveLayerVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromTransientWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromTransient transientt = module.newTransient( FromTransient.class );
-        transientt.aboveModuleVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingModuleApplicationVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.moduleApplicationVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingModuleLayerVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.moduleLayerVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingModuleModuleVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.moduleModuleVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingBesideApplicationVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.besideApplicationVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingBesideLayerVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.besideLayerVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromObjectWhenAccessingBesideModuleVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.besideModuleVisible();
-    }
-
-    @Test
-    public void givenFromObjectWhenAccessingBelowApplicationVisibleExpectSuccess()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.belowApplicationVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromObjectWhenAccessingBelowLayerVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.belowLayerVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromObjectWhenAccessingBelowModuleVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.belowModuleVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromObjectWhenAccessingAboveApplicationVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.aboveApplicationVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromObjectWhenAccessingAboveLayerVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.aboveLayerVisible();
-    }
-
-    @Test( expected = NoSuchValueException.class )
-    public void givenFromObjectWhenAccessingAboveModuleVisibleExpectException()
-    {
-        FromObject object = module.newObject( FromObject.class );
-        object.aboveModuleVisible();
-    }
-
-    private static class FromAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.layer().setName( "From Layer" );
-            module.setName( "From" );
-            module.services( FromService.class );
-            module.entities( FromEntity.class );
-            module.transients( FromTransient.class );
-            module.values( FromValue.class );
-            module.objects( FromObject.class );
-
-            module.values( ModuleApplicationVisible.class ).visibleIn( Visibility.application );
-            module.values( ModuleLayerVisible.class ).visibleIn( Visibility.layer );
-            module.values( ModuleModuleVisible.class ).visibleIn( Visibility.module );
-        }
-    }
-
-    private static class BelowAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.layer().setName( "Below Layer" );
-            module.setName( "Below" );
-            module.values( BelowApplicationVisible.class ).visibleIn( Visibility.application );
-            module.values( BelowLayerVisible.class ).visibleIn( Visibility.layer );
-            module.values( BelowModuleVisible.class ).visibleIn( Visibility.module );
-
-            new EntityTestAssembler().visibleIn( Visibility.application ).assemble( module );
-        }
-    }
-
-    private static class AboveAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.layer().setName( "Above Layer" );
-            module.setName( "Above" );
-            module.values( AboveApplicationVisible.class ).visibleIn( Visibility.application );
-            module.values( AboveLayerVisible.class ).visibleIn( Visibility.layer );
-            module.values( AboveModuleVisible.class ).visibleIn( Visibility.module );
-        }
-    }
-
-    private static class BesideAssembler
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.setName( "Beside" );
-            module.values( BesideApplicationVisible.class ).visibleIn( Visibility.application );
-            module.values( BesideLayerVisible.class ).visibleIn( Visibility.layer );
-            module.values( BesideModuleVisible.class ).visibleIn( Visibility.module );
-        }
-    }
-
-    @Mixins( Mixin.class )
-    public interface From
-    {
-        void moduleApplicationVisible();
-
-        void moduleLayerVisible();
-
-        void moduleModuleVisible();
-
-        void besideApplicationVisible();
-
-        void besideLayerVisible();
-
-        void besideModuleVisible();
-
-        void belowApplicationVisible();
-
-        void belowLayerVisible();
-
-        void belowModuleVisible();
-
-        void aboveApplicationVisible();
-
-        void aboveLayerVisible();
-
-        void aboveModuleVisible();
-    }
-
-    public interface FromValue extends From, ValueComposite
-    {
-    }
-
-    public interface FromEntity extends From, EntityComposite
-    {
-    }
-
-    public interface FromService extends From, ServiceComposite
-    {
-    }
-
-    public interface FromTransient extends From, TransientComposite
-    {
-    }
-
-    public static class FromObject extends Mixin
-    {
-    }
-
-    public abstract static class Mixin
-        implements From
-    {
-        @Structure
-        private Module module;
-
-        @Override
-        public void moduleApplicationVisible()
-        {
-            ValueBuilder<ModuleApplicationVisible> builder = module.newValueBuilder( ModuleApplicationVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void moduleLayerVisible()
-        {
-            ValueBuilder<ModuleLayerVisible> builder = module.newValueBuilder( ModuleLayerVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void moduleModuleVisible()
-        {
-            ValueBuilder<ModuleModuleVisible> builder = module.newValueBuilder( ModuleModuleVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void besideApplicationVisible()
-        {
-            ValueBuilder<BesideApplicationVisible> builder = module.newValueBuilder( BesideApplicationVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void besideLayerVisible()
-        {
-            ValueBuilder<BesideLayerVisible> builder = module.newValueBuilder( BesideLayerVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void besideModuleVisible()
-        {
-            ValueBuilder<BesideModuleVisible> builder = module.newValueBuilder( BesideModuleVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void belowApplicationVisible()
-        {
-            ValueBuilder<BelowApplicationVisible> builder = module.newValueBuilder( BelowApplicationVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void belowLayerVisible()
-        {
-            ValueBuilder<BelowLayerVisible> builder = module.newValueBuilder( BelowLayerVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void belowModuleVisible()
-        {
-            ValueBuilder<BelowModuleVisible> builder = module.newValueBuilder( BelowModuleVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void aboveApplicationVisible()
-        {
-            ValueBuilder<AboveApplicationVisible> builder = module.newValueBuilder( AboveApplicationVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void aboveLayerVisible()
-        {
-            ValueBuilder<AboveLayerVisible> builder = module.newValueBuilder( AboveLayerVisible.class );
-            builder.newInstance();
-        }
-
-        @Override
-        public void aboveModuleVisible()
-        {
-            ValueBuilder<AboveModuleVisible> builder = module.newValueBuilder( AboveModuleVisible.class );
-            builder.newInstance();
-        }
-    }
-
-    public interface ModuleApplicationVisible extends ValueComposite
-    {
-    }
-
-    public interface ModuleLayerVisible extends ValueComposite
-    {
-    }
-
-    public interface ModuleModuleVisible extends ValueComposite
-    {
-    }
-
-    public interface BesideApplicationVisible extends ValueComposite
-    {
-    }
-
-    public interface BesideLayerVisible extends ValueComposite
-    {
-    }
-
-    public interface BesideModuleVisible extends ValueComposite
-    {
-    }
-
-    public interface BelowApplicationVisible extends ValueComposite
-    {
-    }
-
-    public interface BelowLayerVisible extends ValueComposite
-    {
-    }
-
-    public interface BelowModuleVisible extends ValueComposite
-    {
-    }
-
-    public interface AboveApplicationVisible extends ValueComposite
-    {
-    }
-
-    public interface AboveLayerVisible extends ValueComposite
-    {
-    }
-
-    public interface AboveModuleVisible extends ValueComposite
-    {
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/value/ValueWithAssociationTest.java b/core/runtime/src/test/java/org/qi4j/runtime/value/ValueWithAssociationTest.java
deleted file mode 100644
index 679542e..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/value/ValueWithAssociationTest.java
+++ /dev/null
@@ -1,202 +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.qi4j.runtime.value;
-
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
-
-public class ValueWithAssociationTest extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( SimpleName.class );
-        module.entities( DualFaced.class );
-        module.values( SimpleName.class );
-        module.values( DualFaced.class );
-        module.services( MemoryEntityStoreService.class );
-        module.services( UuidIdentityGeneratorService.class );
-        module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
-    }
-
-    @Test
-    public void givenEntityInStoreWhenFetchEntityReferenceExpectSuccess()
-        throws UnitOfWorkCompletionException
-    {
-        String identity1;
-        String identity2;
-        DualFaced value;
-        try (UnitOfWork uow = module.newUnitOfWork())
-        {
-            EntityBuilder<SimpleName> builder1 = uow.newEntityBuilder( SimpleName.class );
-            builder1.instance().name().set( "Niclas" );
-            SimpleName simpleEntity = builder1.newInstance();
-            identity1 = simpleEntity.identity().get();
-
-            EntityBuilder<DualFaced> builder2 = uow.newEntityBuilder( DualFaced.class );
-            DualFaced proto = builder2.instance();
-            proto.name().set( "Hedhman" );
-            proto.simple().set( simpleEntity );
-            proto.simples().add( simpleEntity );
-            proto.namedSimples().put( "niclas", simpleEntity );
-            DualFaced faced = builder2.newInstance();
-            identity2 = faced.identity().get();
-            value = uow.toValue( DualFaced.class, faced );
-            assertThat( value.identity().get(), equalTo( identity2 ) );
-            uow.complete();
-        }
-
-        try (UnitOfWork uow = module.newUnitOfWork())
-        {
-            DualFaced entity = uow.get( DualFaced.class, identity2 );
-            AssociationStateHolder holder = spi.stateOf( (EntityComposite) entity );
-            Association<?> simple = holder.allAssociations().iterator().next();
-            ManyAssociation<?> simples = holder.allManyAssociations().iterator().next();
-            NamedAssociation<?> namedSimples = holder.allNamedAssociations().iterator().next();
-
-            assertThat( spi.entityReferenceOf( simple ), equalTo( EntityReference.parseEntityReference( identity1 ) ) );
-            assertThat( spi.entityReferenceOf( simples )
-                            .iterator()
-                            .next(), equalTo( EntityReference.parseEntityReference( identity1 ) ) );
-            assertThat( spi.entityReferenceOf( namedSimples )
-                            .iterator()
-                            .next()
-                            .getValue(), equalTo( EntityReference.parseEntityReference( identity1 ) ) );
-
-            DualFaced resurrected = uow.toEntity( DualFaced.class, value );
-            assertThat( resurrected.simple(), equalTo( entity.simple() ) );
-            assertThat( resurrected.simples(), equalTo( entity.simples() ) );
-            assertThat( resurrected.namedSimples(), equalTo( entity.namedSimples() ) );
-        }
-    }
-
-    @Test
-    public void givenNewValueWhenConvertingToEntityExpectNewEntityInStore()
-        throws UnitOfWorkCompletionException
-    {
-        ValueBuilder<DualFaced> builder = module.newValueBuilder( DualFaced.class );
-        builder.prototype().identity().set( "1234" );
-        builder.prototype().name().set( "Hedhman" );
-        DualFaced value = builder.newInstance();
-
-        try (UnitOfWork uow = module.newUnitOfWork())
-        {
-            uow.toEntity( DualFaced.class, value );
-            uow.complete();
-        }
-
-        try (UnitOfWork uow = module.newUnitOfWork())
-        {
-            DualFaced entity = uow.get( DualFaced.class, "1234" );
-            assertThat( entity.identity().get(), equalTo( "1234" ) );
-            assertThat( entity.name().get(), equalTo( "Hedhman" ) );
-            uow.complete();
-        }
-    }
-
-    @Test
-    public void givenValueWithIdentityAlreadyInStoreWhenConvertingToEntityExpectExistingEntityToBeUpdated()
-        throws UnitOfWorkCompletionException
-    {
-        String identity1;
-        String identity2;
-        try (UnitOfWork uow = module.newUnitOfWork())
-        {
-            EntityBuilder<SimpleName> builder1 = uow.newEntityBuilder( SimpleName.class );
-            builder1.instance().name().set( "Niclas" );
-            SimpleName simpleEntity = builder1.newInstance();
-            identity1 = simpleEntity.identity().get();
-
-            EntityBuilder<DualFaced> builder2 = uow.newEntityBuilder( DualFaced.class );
-            DualFaced proto = builder2.instance();
-            proto.name().set( "Hedhman" );
-            proto.simple().set( simpleEntity );
-            proto.simples().add( simpleEntity );
-            proto.namedSimples().put( "niclas", simpleEntity );
-            DualFaced faced = builder2.newInstance();
-            identity2 = faced.identity().get();
-            uow.complete();
-        }
-        ValueBuilder<SimpleName> vb1 = module.newValueBuilder( SimpleName.class );
-        vb1.prototype().identity().set( identity1 );
-        vb1.prototype().name().set( "Paul" );
-        SimpleName simpleValue = vb1.newInstance();
-
-        ValueBuilder<DualFaced> vb2 = module.newValueBuilder( DualFaced.class );
-        vb2.prototype().identity().set( identity2 );
-        vb2.prototype().name().set( "Merlin" );
-        vb2.prototype().simple().set( simpleValue );
-        vb2.prototype().simples().add( simpleValue );
-        vb2.prototype().namedSimples().put( "paul", simpleValue );
-        DualFaced dualValue = vb2.newInstance();
-
-        try (UnitOfWork uow = module.newUnitOfWork())
-        {
-            DualFaced dualEntity = uow.toEntity( DualFaced.class, dualValue );
-            // The root entity is expected to have changed value,
-            assertThat( dualEntity.name().get(), equalTo( "Merlin" ) );
-            // But the referenced entity is not updated, only using the EntityReference, which still points to "Niclas",
-            // even though the value contains "Paul" for that entity. That entity needds to be updated separately
-            assertThat( dualEntity.simple().get().name().get(), equalTo( "Niclas" ) );
-            assertThat( dualEntity.simples().get(0).name().get(), equalTo( "Niclas" ) );
-            assertThat( dualEntity.namedSimples().get("paul").name().get(), equalTo( "Niclas" ) );
-            assertThat( dualEntity.namedSimples().get("niclas"), equalTo( null ) );
-        }
-    }
-
-    public interface SimpleName extends Identity
-    {
-        Property<String> name();
-    }
-
-    public interface DualFaced extends Identity
-    {
-        Property<String> name();
-
-        @Optional
-        Association<SimpleName> simple();
-
-        ManyAssociation<SimpleName> simples();
-
-        NamedAssociation<SimpleName> namedSimples();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/runtime/visibility/VisibilityInUnitOfWorkTest.java b/core/runtime/src/test/java/org/qi4j/runtime/visibility/VisibilityInUnitOfWorkTest.java
deleted file mode 100644
index 9a9ef6d..0000000
--- a/core/runtime/src/test/java/org/qi4j/runtime/visibility/VisibilityInUnitOfWorkTest.java
+++ /dev/null
@@ -1,159 +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.qi4j.runtime.visibility;
-
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueSerialization;
-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;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-public class VisibilityInUnitOfWorkTest
-{
-    @Test
-    public void givenTwoModulesWithServiceAndEntityInOneAndEntityInOtherWhenOtherEntityAccessServiceWhichUsesItsEntityExpectServiceToHaveVisibility()
-        throws Exception
-    {
-        Application underTest = createApplication();
-        Module module = underTest.findModule( "layer1", "My Module" );
-        ServiceReference<MyService> service = module.findService( MyService.class );
-        service.get().create();
-    }
-
-    @Mixins( YourService.Mixin.class )
-    public interface YourService
-    {
-        void create();
-
-        YourEntity get();
-
-        class Mixin
-            implements YourService
-        {
-            @Structure
-            private Module module;
-
-            @Override
-            public void create()
-            {
-                UnitOfWork uow = module.currentUnitOfWork();
-                YourEntity entity = uow.newEntity( YourEntity.class, "345" );
-            }
-
-            @Override
-            public YourEntity get()
-            {
-                UnitOfWork uow = module.currentUnitOfWork();
-                return uow.get( YourEntity.class, "345" );
-            }
-        }
-    }
-
-    public interface YourEntity
-    {
-    }
-
-    @Mixins( MyEntity.Mixin.class )
-    public interface MyEntity
-    {
-        void logic();
-
-        class Mixin
-            implements MyEntity
-        {
-            @Service
-            private YourService service;
-
-            @Override
-            public void logic()
-            {
-                YourEntity result = service.get();
-            }
-        }
-    }
-
-    @Mixins( MyService.Mixin.class )
-    public interface MyService
-    {
-        void create();
-
-        class Mixin
-            implements MyService
-        {
-
-            @Service
-            private YourService service;
-
-            @Structure
-            private Module module;
-
-            @Override
-            public void create()
-            {
-                try (UnitOfWork uow = module.newUnitOfWork())
-                {
-                    uow.newEntity( MyEntity.class, "123" );
-                    MyEntity entity1 = uow.get( MyEntity.class, "123" );
-                    service.create();
-                    YourEntity entity2 = service.get();
-                }
-            }
-        }
-    }
-
-    private Application createApplication()
-        throws AssemblyException
-    {
-        Energy4Java qi4j = new Energy4Java();
-        return qi4j.newApplication( new ApplicationAssembler()
-        {
-            @Override
-            public ApplicationAssembly assemble( ApplicationAssemblyFactory appFactory )
-                throws AssemblyException
-            {
-                ApplicationAssembly appAssembly = appFactory.newApplicationAssembly();
-                LayerAssembly layer1 = appAssembly.layer( "layer1" );
-                ModuleAssembly myModule = layer1.module( "My Module" );
-                ModuleAssembly yourModule = layer1.module( "Your Module" );
-                ModuleAssembly infraModule = layer1.module( "Infra Module" );
-                myModule.services( MyService.class );
-                myModule.entities( MyEntity.class );
-                yourModule.entities( YourEntity.class );
-                yourModule.services( YourService.class ).visibleIn( Visibility.layer );
-                infraModule.services( MemoryEntityStoreService.class ).visibleIn( Visibility.layer );
-                infraModule.services( UuidIdentityGeneratorService.class ).visibleIn( Visibility.layer );
-                infraModule.services( OrgJsonValueSerializationService.class ).visibleIn( Visibility.layer).taggedWith( ValueSerialization.Formats.JSON );
-                return appAssembly;
-            }
-        } );
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/spi/service/importer/InstanceImporterTest.java b/core/runtime/src/test/java/org/qi4j/spi/service/importer/InstanceImporterTest.java
deleted file mode 100644
index 1a09465..0000000
--- a/core/runtime/src/test/java/org/qi4j/spi/service/importer/InstanceImporterTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.service.importer;
-
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test import of singleton services
- */
-public class InstanceImporterTest
-    extends AbstractQi4jTest
-{
-    @Service
-    TestInterface service;
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ModuleAssembly serviceModule = module.layer().module( "Service module" );
-        serviceModule.importedServices( TestInterface.class )
-            .setMetaInfo( new TestService() )
-            .visibleIn( Visibility.layer );
-        module.objects( InstanceImporterTest.class );
-    }
-
-    @Test
-    public void givenSingletonServiceObjectWhenServicesAreInjectedThenSingletonIsFound()
-    {
-        module.injectTo( this );
-
-        assertThat( "service is injected properly", service.helloWorld(), equalTo( "Hello World" ) );
-    }
-
-    public interface TestInterface
-    {
-        public String helloWorld();
-    }
-
-    public static class TestService
-        implements TestInterface
-    {
-        public String helloWorld()
-        {
-            return "Hello World";
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/spi/service/importer/NewObjectImporterTest.java b/core/runtime/src/test/java/org/qi4j/spi/service/importer/NewObjectImporterTest.java
deleted file mode 100644
index 794eba9..0000000
--- a/core/runtime/src/test/java/org/qi4j/spi/service/importer/NewObjectImporterTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.service.importer;
-
-import org.hamcrest.CoreMatchers;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ImportedServiceDeclaration;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-/**
- * JAVADOC
- */
-public class NewObjectImporterTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.importedServices( TestService.class ).
-            identifiedBy( "test" ).
-            importedBy( ImportedServiceDeclaration.NEW_OBJECT );
-
-        module.objects( TestService.class, NewObjectImporterTest.class );
-    }
-
-    @Service
-    TestService service;
-
-    @Test
-    public void testImportServiceFromService()
-    {
-        module.injectTo( this );
-
-        Assert.assertThat( service.helloWorld(), CoreMatchers.equalTo( "Hello World" ) );
-    }
-
-    public static class TestService
-    {
-        String helloWorld()
-        {
-            return "Hello World";
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/spi/service/importer/ServiceInstanceImporterTest.java b/core/runtime/src/test/java/org/qi4j/spi/service/importer/ServiceInstanceImporterTest.java
deleted file mode 100644
index db14e70..0000000
--- a/core/runtime/src/test/java/org/qi4j/spi/service/importer/ServiceInstanceImporterTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.service.importer;
-
-import org.hamcrest.CoreMatchers;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.service.ServiceImporterException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ImportedServiceDeclaration;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-/**
- * JAVADOC
- */
-public class ServiceInstanceImporterTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.importedServices( TestService.class ).
-            identifiedBy( "test" ).
-            setMetaInfo( "testimporter" ).
-            importedBy( ImportedServiceDeclaration.SERVICE_IMPORTER );
-        module.services( TestImporterService.class ).identifiedBy( "testimporter" );
-
-        module.objects( ServiceInstanceImporterTest.class );
-    }
-
-    @Service
-    TestService service;
-
-    @Test
-    public void testImportServiceFromService()
-    {
-        module.injectTo( this );
-
-        Assert.assertThat( service.helloWorld(), CoreMatchers.equalTo( "Hello World" ) );
-    }
-
-    public static class TestService
-    {
-        String helloWorld()
-        {
-            return "Hello World";
-        }
-    }
-
-    @Mixins( TestImporterService.Mixin.class )
-    interface TestImporterService
-        extends ServiceComposite, ServiceImporter<TestService>
-    {
-        class Mixin
-            implements ServiceImporter<TestService>
-        {
-            public TestService importService( ImportedServiceDescriptor serviceDescriptor )
-                throws ServiceImporterException
-            {
-                return new TestService();
-            }
-
-            public boolean isAvailable( TestService instance )
-            {
-                return true;
-            }
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/spi/service/importer/ServiceSelectorImporterTest.java b/core/runtime/src/test/java/org/qi4j/spi/service/importer/ServiceSelectorImporterTest.java
deleted file mode 100644
index 5ff899c..0000000
--- a/core/runtime/src/test/java/org/qi4j/spi/service/importer/ServiceSelectorImporterTest.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.service.importer;
-
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.qualifier.ServiceQualifier;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.bootstrap.ImportedServiceDeclaration.SERVICE_SELECTOR;
-
-/**
- * Test of service selector importer
- */
-public class ServiceSelectorImporterTest
-{
-    @Test
-    public void givenManyServicesWhenInjectServiceThenGetFirstOne()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.objects( ServiceConsumer.class );
-                module.services( TestServiceComposite1.class,
-                                 TestServiceComposite2.class );
-            }
-        };
-
-        TestService service = assembler.module().newObject( ServiceConsumer.class ).getService();
-
-        assertThat( "service is first one", service.test(), equalTo( "mixin1" ) );
-    }
-
-    @Test
-    public void givenManyServicesAndFilterWhenInjectServiceThenGetSpecifiedOne()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.objects( ServiceConsumer.class );
-
-                module.importedServices( TestService.class )
-                    .importedBy( SERVICE_SELECTOR )
-                    .setMetaInfo( ServiceQualifier.withId( TestServiceComposite2.class.getSimpleName() ) );
-
-                ModuleAssembly module2 = module.layer().module( "Other module" );
-                module2.services( TestServiceComposite2.class, TestServiceComposite2.class )
-                    .visibleIn( Visibility.layer );
-            }
-        };
-
-        TestService service = assembler.module().newObject( ServiceConsumer.class ).getService();
-
-        assertThat( "service is specified one", service.test(), equalTo( "mixin2" ) );
-    }
-
-    @Test
-    public void givenManyServicesAndSelectFirstWhenInjectServiceThenDontGetSelf()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.objects( ServiceConsumer.class );
-
-                module.importedServices( TestService.class )
-                    .importedBy( SERVICE_SELECTOR )
-                    .setMetaInfo( ServiceQualifier.withId( "TestServiceComposite2_1" ) );
-
-                ModuleAssembly module2 = module.layer().module( "Other module" );
-                module2.addServices( TestServiceComposite2.class, TestServiceComposite2.class )
-                    .visibleIn( Visibility.layer );
-            }
-        };
-
-        TestService service = assembler.module().newObject( ServiceConsumer.class ).getService();
-
-        assertThat( "service is specified one", service.test(), equalTo( "mixin2" ) );
-    }
-
-    public static class ServiceConsumer
-    {
-        private
-        @Service
-        TestService service;
-
-        public TestService getService()
-        {
-            return service;
-        }
-    }
-
-    @Mixins( TestMixin1.class )
-    public interface TestServiceComposite1
-        extends TestServiceComposite
-    {
-    }
-
-    @Mixins( TestMixin2.class )
-    public interface TestServiceComposite2
-        extends TestServiceComposite
-    {
-    }
-
-    public interface TestServiceComposite
-        extends TestService, ServiceComposite
-    {
-    }
-
-    public interface TestService
-    {
-        String test();
-    }
-
-    public static class TestMixin1
-        implements TestService
-    {
-        public String test()
-        {
-            return "mixin1";
-        }
-    }
-
-    public static class TestMixin2
-        implements TestService
-    {
-        public String test()
-        {
-            return "mixin2";
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/test/ASMTest.java b/core/runtime/src/test/java/org/qi4j/test/ASMTest.java
deleted file mode 100644
index c39fa71..0000000
--- a/core/runtime/src/test/java/org/qi4j/test/ASMTest.java
+++ /dev/null
@@ -1,581 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.test;
-
-import java.io.PrintWriter;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.List;
-import org.junit.Assert;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.FieldVisitor;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-import org.objectweb.asm.util.ASMifier;
-import org.objectweb.asm.util.TraceClassVisitor;
-import org.qi4j.api.composite.CompositeInvoker;
-import org.qi4j.runtime.composite.FragmentClassLoader;
-import org.qi4j.runtime.composite.QI256Test;
-
-import static org.objectweb.asm.Opcodes.*;
-
-public class ASMTest
-{
-    @Test
-    public void generateASM()
-        throws Exception
-    {
-        ASMifier.main( new String[]{ SomeMixin_Stubx.class.getName() } );
-    }
-
-    @Test
-    public void createClass()
-        throws Exception
-    {
-
-        FragmentClassLoader classLoader = new FragmentClassLoader( SomeMixin.class.getClassLoader() );
-
-        Class clazz = classLoader.loadClass( SomeMixin.class.getName() + "_Stub" );
-
-        //       Class clazz = SomeMixin_Stubx.class;
-
-        final Other other = new Other()
-        {
-            public String other()
-            {
-                return "other";
-            }
-
-            public String foo( String bar, int x )
-            {
-                return "bar:" + bar;
-            }
-
-            public void bar( double doub,
-                             boolean bool,
-                             float fl,
-                             char ch,
-                             int integer,
-                             long lg,
-                             short sh,
-                             byte b,
-                             Double doubObj,
-                             Object[] objArr,
-                             int[] intArr
-            )
-            {
-            }
-
-            public void multiEx( String bar )
-                throws Exception1, Exception2
-            {
-            }
-
-            public long unwrapResult()
-            {
-                return 0;
-            }
-
-            public void generic( List<String> list )
-            {
-                list.add( "Hello World" );
-            }
-        };
-
-        final Some instance = (Some) clazz.getConstructor().newInstance();
-
-        CompositeInvoker invoker = new CompositeInvoker()
-        {
-            public Object invokeComposite( Method method, Object[] args )
-                throws Throwable
-            {
-                Method fakeMethod = null;
-                try
-                {
-                    fakeMethod = instance.getClass().getMethod( "_" + method.getName(), method.getParameterTypes() );
-
-                    try
-                    {
-                        return fakeMethod.invoke( instance, args );
-                    }
-                    catch( InvocationTargetException e )
-                    {
-                        throw e.getCause();
-                    }
-                }
-                catch( NoSuchMethodException e )
-                {
-                    try
-                    {
-                        return method.invoke( other, args );
-                    }
-                    catch( InvocationTargetException ex )
-                    {
-                        throw ex.getCause();
-                    }
-                }
-            }
-        };
-
-        clazz.getField( "_instance" ).set( instance, invoker );
-
-        System.out.println( instance.some() );
-
-        System.out.println( instance.testConcern() );
-    }
-
-    @Test
-    @Ignore( "Convenience to look at what code is generated in the Fragment Classloader, and is not really a test case." )
-    public void fragmentClassLoaderGenerateClassTest()
-        throws Exception
-    {
-        byte[] asm = generateClass();
-        byte[] cl = FragmentClassLoader.generateClass(
-            QI256Test.TestTransient.TestTransientMixin.class.getName() + "_Stub",
-            QI256Test.TestTransient.TestTransientMixin.class );
-
-        new ClassReader( cl ).accept( new TraceClassVisitor( new PrintWriter( System.out, true ) ), 0 );
-
-        Assert.assertArrayEquals( asm, cl );
-    }
-
-    // This is the code generated from the manual stub
-    private static byte[] generateClass()
-    {
-        ClassWriter cw = new ClassWriter( 0 );
-        FieldVisitor fv;
-        MethodVisitor mv;
-        AnnotationVisitor av0;
-
-        cw.visit( V1_6, ACC_PUBLIC + ACC_SUPER, "org/qi4j/satisfiedBy/SomeMixin_Stub", null,
-                  "org/qi4j/satisfiedBy/SomeMixin", null );
-
-        {
-            fv = cw.visitField( ACC_PUBLIC, "_instance", "Lorg/qi4j/spi/composite/CompositeInvoker;", null, null );
-            fv.visitEnd();
-        }
-        {
-            fv = cw.visitField( ACC_PRIVATE + ACC_STATIC, "m1", "Ljava/lang/reflect/Method;", null, null );
-            fv.visitEnd();
-        }
-        {
-            fv = cw.visitField( ACC_PRIVATE + ACC_STATIC, "m2", "Ljava/lang/reflect/Method;", null, null );
-            fv.visitEnd();
-        }
-        {
-            fv = cw.visitField( ACC_PRIVATE + ACC_STATIC, "m3", "Ljava/lang/reflect/Method;", null, null );
-            fv.visitEnd();
-        }
-        {
-            fv = cw.visitField( ACC_PRIVATE + ACC_STATIC, "m4", "Ljava/lang/reflect/Method;", null, null );
-            fv.visitEnd();
-        }
-        {
-            fv = cw.visitField( ACC_PRIVATE + ACC_STATIC, "m5", "Ljava/lang/reflect/Method;", null, null );
-            fv.visitEnd();
-        }
-        {
-            mv = cw.visitMethod( ACC_PUBLIC, "<init>", "()V", null, null );
-            mv.visitCode();
-            mv.visitVarInsn( ALOAD, 0 );
-            mv.visitMethodInsn( INVOKESPECIAL, "org/qi4j/satisfiedBy/SomeMixin", "<init>", "()V", false );
-            mv.visitInsn( RETURN );
-            mv.visitMaxs( 1, 1 );
-            mv.visitEnd();
-        }
-        {
-            mv = cw.visitMethod( ACC_PUBLIC, "<init>", "(Ljava/lang/String;)V", null, null );
-            mv.visitCode();
-            mv.visitVarInsn( ALOAD, 0 );
-            mv.visitVarInsn( ALOAD, 1 );
-            mv.visitMethodInsn( INVOKESPECIAL, "org/qi4j/satisfiedBy/SomeMixin", "<init>", "(Ljava/lang/String;)V", false );
-            mv.visitInsn( RETURN );
-            mv.visitMaxs( 2, 2 );
-            mv.visitEnd();
-        }
-        {
-            mv = cw.visitMethod( ACC_PUBLIC, "other", "()Ljava/lang/String;", null, null );
-            mv.visitCode();
-            Label l0 = new Label();
-            Label l1 = new Label();
-            Label l2 = new Label();
-            mv.visitTryCatchBlock( l0, l1, l2, "java/lang/Throwable" );
-            mv.visitLabel( l0 );
-            mv.visitVarInsn( ALOAD, 0 );
-            mv.visitFieldInsn( GETFIELD, "org/qi4j/satisfiedBy/SomeMixin_Stub", "_instance",
-                               "Lorg/qi4j/spi/composite/CompositeInvoker;" );
-            mv.visitFieldInsn( GETSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m1", "Ljava/lang/reflect/Method;" );
-            mv.visitInsn( ACONST_NULL );
-            mv.visitMethodInsn( INVOKEINTERFACE, "org/qi4j/spi/composite/CompositeInvoker", "invokeComposite",
-                                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true );
-            mv.visitTypeInsn( CHECKCAST, "java/lang/String" );
-            mv.visitLabel( l1 );
-            mv.visitInsn( ARETURN );
-            mv.visitLabel( l2 );
-            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/Throwable" } );
-            mv.visitVarInsn( ASTORE, 1 );
-            mv.visitTypeInsn( NEW, "java/lang/reflect/UndeclaredThrowableException" );
-            mv.visitInsn( DUP );
-            mv.visitVarInsn( ALOAD, 1 );
-            mv.visitMethodInsn( INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>",
-                                "(Ljava/lang/Throwable;)V", false );
-            mv.visitInsn( ATHROW );
-            mv.visitMaxs( 3, 2 );
-            mv.visitEnd();
-        }
-        {
-            mv = cw.visitMethod( ACC_PUBLIC, "foo", "(Ljava/lang/String;I)Ljava/lang/String;", null,
-                                 new String[]{ "java/lang/IllegalArgumentException" } );
-            mv.visitCode();
-            Label l0 = new Label();
-            Label l1 = new Label();
-            Label l2 = new Label();
-            mv.visitTryCatchBlock( l0, l1, l2, "java/lang/IllegalArgumentException" );
-            Label l3 = new Label();
-            mv.visitTryCatchBlock( l0, l1, l3, "java/lang/Throwable" );
-            mv.visitLabel( l0 );
-            mv.visitVarInsn( ALOAD, 0 );
-            mv.visitFieldInsn( GETFIELD, "org/qi4j/satisfiedBy/SomeMixin_Stub", "_instance",
-                               "Lorg/qi4j/spi/composite/CompositeInvoker;" );
-            mv.visitFieldInsn( GETSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m2", "Ljava/lang/reflect/Method;" );
-            mv.visitInsn( ICONST_2 );
-            mv.visitTypeInsn( ANEWARRAY, "java/lang/Object" );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_0 );
-            mv.visitVarInsn( ALOAD, 1 );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_1 );
-            mv.visitVarInsn( ILOAD, 2 );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false );
-            mv.visitInsn( AASTORE );
-            mv.visitMethodInsn( INVOKEINTERFACE, "org/qi4j/spi/composite/CompositeInvoker", "invokeComposite",
-                                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true );
-            mv.visitTypeInsn( CHECKCAST, "java/lang/String" );
-            mv.visitLabel( l1 );
-            mv.visitInsn( ARETURN );
-            mv.visitLabel( l2 );
-            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/IllegalArgumentException" } );
-            mv.visitVarInsn( ASTORE, 3 );
-            mv.visitVarInsn( ALOAD, 3 );
-            mv.visitInsn( ATHROW );
-            mv.visitLabel( l3 );
-            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/Throwable" } );
-            mv.visitVarInsn( ASTORE, 3 );
-            mv.visitTypeInsn( NEW, "java/lang/reflect/UndeclaredThrowableException" );
-            mv.visitInsn( DUP );
-            mv.visitVarInsn( ALOAD, 3 );
-            mv.visitMethodInsn( INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>",
-                                "(Ljava/lang/Throwable;)V", false );
-            mv.visitInsn( ATHROW );
-            mv.visitMaxs( 6, 4 );
-            mv.visitEnd();
-        }
-        {
-            mv = cw.visitMethod( ACC_PUBLIC, "bar", "(DZFCIJSBLjava/lang/Double;[Ljava/lang/Object;[I)V", null, null );
-            mv.visitCode();
-            Label l0 = new Label();
-            Label l1 = new Label();
-            Label l2 = new Label();
-            mv.visitTryCatchBlock( l0, l1, l2, "java/lang/Throwable" );
-            mv.visitLabel( l0 );
-            mv.visitVarInsn( ALOAD, 0 );
-            mv.visitFieldInsn( GETFIELD, "org/qi4j/satisfiedBy/SomeMixin_Stub", "_instance",
-                               "Lorg/qi4j/spi/composite/CompositeInvoker;" );
-            mv.visitFieldInsn( GETSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m3", "Ljava/lang/reflect/Method;" );
-            mv.visitIntInsn( BIPUSH, 11 );
-            mv.visitTypeInsn( ANEWARRAY, "java/lang/Object" );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_0 );
-            mv.visitVarInsn( DLOAD, 1 );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_1 );
-            mv.visitVarInsn( ILOAD, 3 );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_2 );
-            mv.visitVarInsn( FLOAD, 4 );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_3 );
-            mv.visitVarInsn( ILOAD, 5 );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_4 );
-            mv.visitVarInsn( ILOAD, 6 );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_5 );
-            mv.visitVarInsn( LLOAD, 7 );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitIntInsn( BIPUSH, 6 );
-            mv.visitVarInsn( ILOAD, 9 );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitIntInsn( BIPUSH, 7 );
-            mv.visitVarInsn( ILOAD, 10 );
-            mv.visitMethodInsn( INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitIntInsn( BIPUSH, 8 );
-            mv.visitVarInsn( ALOAD, 11 );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitIntInsn( BIPUSH, 9 );
-            mv.visitVarInsn( ALOAD, 12 );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitIntInsn( BIPUSH, 10 );
-            mv.visitVarInsn( ALOAD, 13 );
-            mv.visitInsn( AASTORE );
-            mv.visitMethodInsn( INVOKEINTERFACE, "org/qi4j/spi/composite/CompositeInvoker", "invokeComposite",
-                                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true );
-            mv.visitInsn( POP );
-            mv.visitLabel( l1 );
-            Label l3 = new Label();
-            mv.visitJumpInsn( GOTO, l3 );
-            mv.visitLabel( l2 );
-            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/Throwable" } );
-            mv.visitVarInsn( ASTORE, 14 );
-            mv.visitTypeInsn( NEW, "java/lang/reflect/UndeclaredThrowableException" );
-            mv.visitInsn( DUP );
-            mv.visitVarInsn( ALOAD, 14 );
-            mv.visitMethodInsn( INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>",
-                                "(Ljava/lang/Throwable;)V", false );
-            mv.visitInsn( ATHROW );
-            mv.visitLabel( l3 );
-            mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
-            mv.visitInsn( RETURN );
-            mv.visitMaxs( 7, 15 );
-            mv.visitEnd();
-        }
-        {
-            mv = cw.visitMethod( ACC_PUBLIC, "multiEx", "(Ljava/lang/String;)V", null,
-                                 new String[]{ "org/qi4j/satisfiedBy/Exception1", "org/qi4j/satisfiedBy/Exception2" } );
-            mv.visitCode();
-            Label l0 = new Label();
-            Label l1 = new Label();
-            Label l2 = new Label();
-            mv.visitTryCatchBlock( l0, l1, l2, "org/qi4j/satisfiedBy/Exception1" );
-            Label l3 = new Label();
-            mv.visitTryCatchBlock( l0, l1, l3, "org/qi4j/satisfiedBy/Exception2" );
-            Label l4 = new Label();
-            mv.visitTryCatchBlock( l0, l1, l4, "java/lang/Throwable" );
-            mv.visitLabel( l0 );
-            mv.visitVarInsn( ALOAD, 0 );
-            mv.visitFieldInsn( GETFIELD, "org/qi4j/satisfiedBy/SomeMixin_Stub", "_instance",
-                               "Lorg/qi4j/spi/composite/CompositeInvoker;" );
-            mv.visitFieldInsn( GETSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m4", "Ljava/lang/reflect/Method;" );
-            mv.visitInsn( ICONST_1 );
-            mv.visitTypeInsn( ANEWARRAY, "java/lang/Object" );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_0 );
-            mv.visitVarInsn( ALOAD, 1 );
-            mv.visitInsn( AASTORE );
-            mv.visitMethodInsn( INVOKEINTERFACE, "org/qi4j/spi/composite/CompositeInvoker", "invokeComposite",
-                                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true );
-            mv.visitInsn( POP );
-            mv.visitLabel( l1 );
-            Label l5 = new Label();
-            mv.visitJumpInsn( GOTO, l5 );
-            mv.visitLabel( l2 );
-            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "org/qi4j/satisfiedBy/Exception1" } );
-            mv.visitVarInsn( ASTORE, 2 );
-            mv.visitVarInsn( ALOAD, 2 );
-            mv.visitInsn( ATHROW );
-            mv.visitLabel( l3 );
-            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "org/qi4j/satisfiedBy/Exception2" } );
-            mv.visitVarInsn( ASTORE, 2 );
-            mv.visitVarInsn( ALOAD, 2 );
-            mv.visitInsn( ATHROW );
-            mv.visitLabel( l4 );
-            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/Throwable" } );
-            mv.visitVarInsn( ASTORE, 2 );
-            mv.visitTypeInsn( NEW, "java/lang/reflect/UndeclaredThrowableException" );
-            mv.visitInsn( DUP );
-            mv.visitVarInsn( ALOAD, 2 );
-            mv.visitMethodInsn( INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>",
-                                "(Ljava/lang/Throwable;)V", false );
-            mv.visitInsn( ATHROW );
-            mv.visitLabel( l5 );
-            mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
-            mv.visitInsn( RETURN );
-            mv.visitMaxs( 6, 3 );
-            mv.visitEnd();
-        }
-        {
-            mv = cw.visitMethod( ACC_PUBLIC, "unwrapResult", "()I", null, null );
-            mv.visitCode();
-            Label l0 = new Label();
-            Label l1 = new Label();
-            Label l2 = new Label();
-            mv.visitTryCatchBlock( l0, l1, l2, "java/lang/Throwable" );
-            mv.visitLabel( l0 );
-            mv.visitVarInsn( ALOAD, 0 );
-            mv.visitFieldInsn( GETFIELD, "org/qi4j/satisfiedBy/SomeMixin_Stub", "_instance",
-                               "Lorg/qi4j/spi/composite/CompositeInvoker;" );
-            mv.visitFieldInsn( GETSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m5", "Ljava/lang/reflect/Method;" );
-            mv.visitInsn( ACONST_NULL );
-            mv.visitMethodInsn( INVOKEINTERFACE, "org/qi4j/spi/composite/CompositeInvoker", "invokeComposite",
-                                "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;", true );
-            mv.visitTypeInsn( CHECKCAST, "java/lang/Integer" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false );
-            mv.visitLabel( l1 );
-            mv.visitInsn( IRETURN );
-            mv.visitLabel( l2 );
-            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/Throwable" } );
-            mv.visitVarInsn( ASTORE, 1 );
-            mv.visitTypeInsn( NEW, "java/lang/reflect/UndeclaredThrowableException" );
-            mv.visitInsn( DUP );
-            mv.visitVarInsn( ALOAD, 1 );
-            mv.visitMethodInsn( INVOKESPECIAL, "java/lang/reflect/UndeclaredThrowableException", "<init>",
-                                "(Ljava/lang/Throwable;)V", false );
-            mv.visitInsn( ATHROW );
-            mv.visitMaxs( 3, 2 );
-            mv.visitEnd();
-        }
-        {
-            mv = cw.visitMethod( ACC_STATIC, "<clinit>", "()V", null, null );
-            mv.visitCode();
-            Label l0 = new Label();
-            Label l1 = new Label();
-            Label l2 = new Label();
-            mv.visitTryCatchBlock( l0, l1, l2, "java/lang/NoSuchMethodException" );
-            mv.visitLabel( l0 );
-            mv.visitLdcInsn( Type.getType( "Lorg/qi4j/satisfiedBy/Other;" ) );
-            mv.visitLdcInsn( "other" );
-            mv.visitInsn( ICONST_0 );
-            mv.visitTypeInsn( ANEWARRAY, "java/lang/Class" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getMethod",
-                                "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false );
-            mv.visitFieldInsn( PUTSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m1", "Ljava/lang/reflect/Method;" );
-            mv.visitLdcInsn( Type.getType( "Lorg/qi4j/satisfiedBy/Other;" ) );
-            mv.visitLdcInsn( "foo" );
-            mv.visitInsn( ICONST_2 );
-            mv.visitTypeInsn( ANEWARRAY, "java/lang/Class" );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_0 );
-            mv.visitLdcInsn( Type.getType( "Ljava/lang/String;" ) );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_1 );
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;" );
-            mv.visitInsn( AASTORE );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getMethod",
-                                "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false );
-            mv.visitFieldInsn( PUTSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m2", "Ljava/lang/reflect/Method;" );
-            mv.visitLdcInsn( Type.getType( "Lorg/qi4j/satisfiedBy/Other;" ) );
-            mv.visitLdcInsn( "bar" );
-            mv.visitIntInsn( BIPUSH, 11 );
-            mv.visitTypeInsn( ANEWARRAY, "java/lang/Class" );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_0 );
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;" );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_1 );
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;" );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_2 );
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;" );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_3 );
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;" );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_4 );
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;" );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_5 );
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;" );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitIntInsn( BIPUSH, 6 );
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;" );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitIntInsn( BIPUSH, 7 );
-            mv.visitFieldInsn( GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;" );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitIntInsn( BIPUSH, 8 );
-            mv.visitLdcInsn( Type.getType( "Ljava/lang/Double;" ) );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitIntInsn( BIPUSH, 9 );
-            mv.visitLdcInsn( Type.getType( "[Ljava/lang/Object;" ) );
-            mv.visitInsn( AASTORE );
-            mv.visitInsn( DUP );
-            mv.visitIntInsn( BIPUSH, 10 );
-            mv.visitLdcInsn( Type.getType( "[I" ) );
-            mv.visitInsn( AASTORE );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getMethod",
-                                "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false );
-            mv.visitFieldInsn( PUTSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m3", "Ljava/lang/reflect/Method;" );
-            mv.visitLdcInsn( Type.getType( "Lorg/qi4j/satisfiedBy/Other;" ) );
-            mv.visitLdcInsn( "multiEx" );
-            mv.visitInsn( ICONST_1 );
-            mv.visitTypeInsn( ANEWARRAY, "java/lang/Class" );
-            mv.visitInsn( DUP );
-            mv.visitInsn( ICONST_0 );
-            mv.visitLdcInsn( Type.getType( "Ljava/lang/String;" ) );
-            mv.visitInsn( AASTORE );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getMethod",
-                                "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false );
-            mv.visitFieldInsn( PUTSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m4", "Ljava/lang/reflect/Method;" );
-            mv.visitLdcInsn( Type.getType( "Lorg/qi4j/satisfiedBy/Other;" ) );
-            mv.visitLdcInsn( "unwrapResult" );
-            mv.visitInsn( ICONST_0 );
-            mv.visitTypeInsn( ANEWARRAY, "java/lang/Class" );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getMethod",
-                                "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false );
-            mv.visitFieldInsn( PUTSTATIC, "org/qi4j/satisfiedBy/SomeMixin_Stub", "m5", "Ljava/lang/reflect/Method;" );
-            mv.visitLabel( l1 );
-            Label l3 = new Label();
-            mv.visitJumpInsn( GOTO, l3 );
-            mv.visitLabel( l2 );
-            mv.visitFrame( Opcodes.F_SAME1, 0, null, 1, new Object[]{ "java/lang/NoSuchMethodException" } );
-            mv.visitVarInsn( ASTORE, 0 );
-            mv.visitVarInsn( ALOAD, 0 );
-            mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/NoSuchMethodException", "printStackTrace", "()V", false );
-            mv.visitLabel( l3 );
-            mv.visitFrame( Opcodes.F_SAME, 0, null, 0, null );
-            mv.visitInsn( RETURN );
-            mv.visitMaxs( 6, 1 );
-            mv.visitEnd();
-        }
-        cw.visitEnd();
-
-        return cw.toByteArray();
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/test/Exception1.java b/core/runtime/src/test/java/org/qi4j/test/Exception1.java
deleted file mode 100644
index 69a6a11..0000000
--- a/core/runtime/src/test/java/org/qi4j/test/Exception1.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.test;
-
-/**
- * JAVADOC
- */
-public class Exception1
-    extends Exception
-{
-}
diff --git a/core/runtime/src/test/java/org/qi4j/test/Exception2.java b/core/runtime/src/test/java/org/qi4j/test/Exception2.java
deleted file mode 100644
index 3cdeff1..0000000
--- a/core/runtime/src/test/java/org/qi4j/test/Exception2.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.test;
-
-/**
- * JAVADOC
- */
-public class Exception2
-    extends Exception
-{
-}
\ No newline at end of file
diff --git a/core/runtime/src/test/java/org/qi4j/test/Other.java b/core/runtime/src/test/java/org/qi4j/test/Other.java
deleted file mode 100644
index c27cce6..0000000
--- a/core/runtime/src/test/java/org/qi4j/test/Other.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.test;
-
-import java.util.List;
-
-/**
- * JAVADOC
- */
-public interface Other
-{
-    public String other();
-
-    public String foo( String bar, int blah )
-        throws IllegalArgumentException;
-
-    public void bar( double doub,
-                     boolean bool,
-                     float fl,
-                     char ch,
-                     int integer,
-                     long lg,
-                     short sh,
-                     byte b,
-                     Double doubObj,
-                     Object[] objArr,
-                     int[] intArr
-    );
-
-    public void multiEx( String bar )
-        throws Exception1, Exception2;
-
-    public long unwrapResult();
-
-    public void generic( List<String> list );
-}
diff --git a/core/runtime/src/test/java/org/qi4j/test/Some.java b/core/runtime/src/test/java/org/qi4j/test/Some.java
deleted file mode 100644
index fa47db1..0000000
--- a/core/runtime/src/test/java/org/qi4j/test/Some.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.test;
-
-/**
- * JAVADOC
- */
-public interface Some
-{
-    String some()
-        throws Exception2, Exception1;
-
-    String testConcern();
-}
diff --git a/core/runtime/src/test/java/org/qi4j/test/SomeMixin.java b/core/runtime/src/test/java/org/qi4j/test/SomeMixin.java
deleted file mode 100644
index 4da15b3..0000000
--- a/core/runtime/src/test/java/org/qi4j/test/SomeMixin.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.test;
-
-import java.util.ArrayList;
-
-/**
- * JAVADOC
- */
-public abstract class SomeMixin
-    implements Some, Other, World
-{
-
-    protected SomeMixin()
-    {
-    }
-
-    protected SomeMixin( String foo )
-    {
-
-    }
-
-    public String some()
-        throws Exception2, Exception1
-    {
-        multiEx( "foo" );
-        unwrapResult();
-        bar( 1.0, true, 1.0F, 'x', 0, 0L, (short) 0, (byte) 3, new Double( 4F ), new Object[ 0 ], new int[ 0 ] );
-        generic( new ArrayList() );
-
-        return "Hello " + other() + foo( "Test", 0 );
-    }
-
-    public String testConcern()
-    {
-        return someMethod( "Hello", 0, 0 );
-    }
-
-    public String someMethod( String foo, double x, int y )
-    {
-        return foo;
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/test/SomeMixin_Stubx.java b/core/runtime/src/test/java/org/qi4j/test/SomeMixin_Stubx.java
deleted file mode 100644
index a9614ec..0000000
--- a/core/runtime/src/test/java/org/qi4j/test/SomeMixin_Stubx.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.test;
-
-import java.lang.reflect.Method;
-import java.util.List;
-import org.qi4j.api.composite.CompositeInvoker;
-
-/**
- * JAVADOC
- */
-public class SomeMixin_Stubx
-    extends SomeMixin
-{
-    public CompositeInvoker _instance;
-
-    private static Method m1;
-    private static Method m2;
-    private static Method m3;
-    private static Method m4;
-    private static Method m5;
-    private static Method m6;
-
-    private static Method m7;
-    private static Method m8;
-
-    static
-    {
-        try
-        {
-            m1 = Other.class.getMethod( "other" );
-            m2 = Other.class.getMethod( "foo", String.class, Integer.TYPE );
-            m3 = Other.class.getMethod( "bar",
-                                        Double.TYPE,
-                                        Boolean.TYPE,
-                                        Float.TYPE,
-                                        Character.TYPE,
-                                        Integer.TYPE,
-                                        Long.TYPE,
-                                        Short.TYPE,
-                                        Byte.TYPE,
-                                        Double.class,
-                                        Object[].class,
-                                        int[].class );
-            m4 = Other.class.getMethod( "multiEx", String.class );
-            m5 = Other.class.getMethod( "unwrapResult" );
-            m6 = Other.class.getMethod( "generic", List.class );
-
-            m7 = Some.class.getMethod( "testConcern" );
-            m8 = World.class.getMethod( "someMethod", String.class, Double.TYPE, Integer.TYPE );
-        }
-        catch( Throwable e )
-        {
-            e.printStackTrace();
-        }
-    }
-
-    public SomeMixin_Stubx()
-    {
-        super();
-    }
-
-    public SomeMixin_Stubx( String foo )
-    {
-        super( foo );
-    }
-
-    public String other()
-    {
-        try
-        {
-            return (String) _instance.invokeComposite( m1, null );
-        }
-        catch( RuntimeException runtime )
-        {
-            throw runtime;
-        }
-        catch( Throwable error )
-        {
-            throw (Error) error;
-        }
-    }
-
-    public String foo( String bar, int x )
-        throws IllegalArgumentException
-    {
-        try
-        {
-            return (String) _instance.invokeComposite( m2, new Object[]{ bar, x } );
-        }
-        catch( IllegalArgumentException ex )
-        {
-            throw ex;
-        }
-        catch( RuntimeException runtime )
-        {
-            throw runtime;
-        }
-        catch( Throwable error )
-        {
-            throw (Error) error;
-        }
-    }
-
-    public void bar( double doub,
-                     boolean bool,
-                     float fl,
-                     char ch,
-                     int integer,
-                     long lg,
-                     short sh,
-                     byte b,
-                     Double doubObj,
-                     Object[] objArr,
-                     int[] intArr
-    )
-    {
-        try
-        {
-            _instance.invokeComposite( m3, new Object[]{ doub, bool, fl, ch, integer, lg, sh, b, doubObj, objArr, intArr } );
-        }
-        catch( RuntimeException runtime )
-        {
-            throw runtime;
-        }
-        catch( Throwable error )
-        {
-            throw (Error) error;
-        }
-    }
-
-    public void multiEx( String bar )
-        throws Exception1, Exception2
-    {
-        try
-        {
-            _instance.invokeComposite( m4, new Object[]{ bar } );
-        }
-        catch( Exception1 throwable )
-        {
-            throw throwable;
-        }
-        catch( Exception2 throwable )
-        {
-            throw throwable;
-        }
-        catch( RuntimeException runtime )
-        {
-            throw runtime;
-        }
-        catch( Throwable error )
-        {
-            throw (Error) error;
-        }
-    }
-
-    public long unwrapResult()
-    {
-        try
-        {
-            return (Long) _instance.invokeComposite( m5, null );
-        }
-        catch( RuntimeException runtime )
-        {
-            throw runtime;
-        }
-        catch( Throwable error )
-        {
-            throw (Error) error;
-        }
-    }
-
-    public void generic( List<String> list )
-    {
-        try
-        {
-            _instance.invokeComposite( m6, new Object[]{ list } );
-        }
-        catch( RuntimeException runtime )
-        {
-            throw runtime;
-        }
-        catch( Throwable error )
-        {
-            throw (Error) error;
-        }
-    }
-
-    public String testConcern()
-    {
-        try
-        {
-            return (String) _instance.invokeComposite( m7, null );
-        }
-        catch( RuntimeException runtime )
-        {
-            throw runtime;
-        }
-        catch( Throwable error )
-        {
-            throw (Error) error;
-        }
-    }
-
-    public String _testConcern()
-    {
-        return super.testConcern();
-    }
-
-    @Override
-    public String someMethod( String foo, double x, int y )
-    {
-        try
-        {
-            return (String) _instance.invokeComposite( m8, new Object[]{ foo, x, y } );
-        }
-        catch( RuntimeException runtime )
-        {
-            throw runtime;
-        }
-        catch( Throwable error )
-        {
-            throw (Error) error;
-        }
-    }
-
-    public String _someMethod( String foo, double x, int y )
-    {
-        return super.someMethod( foo, x, y );
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/test/World.java b/core/runtime/src/test/java/org/qi4j/test/World.java
deleted file mode 100644
index fbec515..0000000
--- a/core/runtime/src/test/java/org/qi4j/test/World.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.test;
-
-/**
- * JAVADOC
- */
-public interface World
-{
-    String someMethod( String foo, double x, int y );
-}
diff --git a/core/runtime/src/test/java/org/qi4j/test/composite/CleanStackTraceTest.java b/core/runtime/src/test/java/org/qi4j/test/composite/CleanStackTraceTest.java
deleted file mode 100644
index e5883f1..0000000
--- a/core/runtime/src/test/java/org/qi4j/test/composite/CleanStackTraceTest.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.test.composite;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.concern.GenericConcern;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assume.assumeTrue;
-
-/**
- * Test if the stacktrace is cleaned up properly.
- * <p>
- * NOTE: This satisfiedBy MUST NOT be inside package org.qi4j.runtime, or it will fail.
- * </p>
- */
-public class CleanStackTraceTest
-    extends AbstractQi4jTest
-{
-
-    @BeforeClass
-    public static void beforeClass_IBMJDK()
-    {   
-        assumeTrue( !( System.getProperty( "java.vendor" ).contains( "IBM" ) ) );
-    }   
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( CleanStackTraceTest.TestComposite.class );
-    }
-
-    /**
-     * Tests that stack trace is cleaned up on an application exception.
-     */
-    @Test
-    public void cleanStackTraceOnApplicationException()
-    {
-        // Don't run the satisfiedBy if compacttrace is set to anything else but proxy
-        String compactTracePropertyValue = System.getProperty( "qi4j.compacttrace" );
-        if( compactTracePropertyValue != null && !"proxy".equals( compactTracePropertyValue ) )
-        {
-            return;
-        }
-        TestComposite composite = module.newTransient( TestComposite.class );
-        try
-        {
-            composite.doStuff();
-        }
-        catch( RuntimeException e )
-        {
-            String separator = System.getProperty( "line.separator" );
-            String correctTrace1 = "java.lang.RuntimeException: level 2" + separator +
-                                   "\tat org.qi4j.test.composite.CleanStackTraceTest$DoStuffMixin.doStuff(CleanStackTraceTest.java:122)" + separator +
-                                   "\tat org.qi4j.test.composite.CleanStackTraceTest$NillyWilly.invoke(CleanStackTraceTest.java:135)" + separator +
-                                   "\tat org.qi4j.test.composite.CleanStackTraceTest.cleanStackTraceOnApplicationException(CleanStackTraceTest.java:73)";
-            assertEquality( e, correctTrace1 );
-            String correctTrace2 = "java.lang.RuntimeException: level 1" + separator +
-                                   "\tat org.qi4j.test.composite.CleanStackTraceTest$DoStuffMixin.doStuff(CleanStackTraceTest.java:118)" + separator +
-                                   "\tat org.qi4j.test.composite.CleanStackTraceTest$NillyWilly.invoke(CleanStackTraceTest.java:135)" + separator +
-                                   "\tat org.qi4j.test.composite.CleanStackTraceTest.cleanStackTraceOnApplicationException(CleanStackTraceTest.java:73)";
-            assertThat( e.getCause(), notNullValue() );
-            assertEquality( e.getCause(), correctTrace2 );
-        }
-    }
-
-    private void assertEquality( Throwable e, String correctTrace )
-    {
-        StringWriter actualTrace = new StringWriter();
-        e.printStackTrace( new PrintWriter( actualTrace ) );
-
-        String actual = actualTrace.toString();
-        actual = actual.substring( 0, correctTrace.length() );
-        assertEquals( correctTrace, actual );
-    }
-
-    @Concerns( NillyWilly.class )
-    @Mixins(DoStuffMixin.class)
-    public interface TestComposite
-    {
-        void doStuff();
-    }
-
-    public static class DoStuffMixin
-        implements TestComposite
-    {
-
-        @Override
-        public void doStuff()
-        {
-            try
-            {
-                throw new RuntimeException( "level 1" );
-            }
-            catch( RuntimeException e )
-            {
-                throw new RuntimeException( "level 2", e );
-            }
-        }
-    }
-
-    static class NillyWilly extends GenericConcern
-        implements InvocationHandler
-    {
-
-        @Override
-        public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-        {
-            return next.invoke( proxy, method, args );
-        }
-    }
-}
diff --git a/core/runtime/src/test/java/org/qi4j/test/performance/entitystore/memory/MemoryEntityStoreTest.java b/core/runtime/src/test/java/org/qi4j/test/performance/entitystore/memory/MemoryEntityStoreTest.java
deleted file mode 100644
index a66afd6..0000000
--- a/core/runtime/src/test/java/org/qi4j/test/performance/entitystore/memory/MemoryEntityStoreTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.test.performance.entitystore.memory;
-
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entitystore.StateChangeListener;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-import static org.qi4j.bootstrap.ImportedServiceDeclaration.NEW_OBJECT;
-
-/**
- * Test of MemoryEntityStoreService
- */
-public class MemoryEntityStoreTest
-    extends AbstractEntityStoreTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-
-        module.services( MemoryEntityStoreService.class, UuidIdentityGeneratorService.class );
-        module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
-        module.importedServices( StatePrinter.class ).importedBy( NEW_OBJECT );
-        module.objects( StatePrinter.class );
-    }
-
-    static public class StatePrinter
-        implements StateChangeListener
-    {
-        public void notifyChanges( Iterable<EntityState> changedStates )
-        {
-            for( EntityState changedState : changedStates )
-            {
-                System.out.println( changedState.status().name() + ":" + changedState.identity() );
-            }
-        }
-    }
-}
diff --git a/core/runtime/src/test/resources/org/apache/polygene/runtime/instantiation/My.properties b/core/runtime/src/test/resources/org/apache/polygene/runtime/instantiation/My.properties
new file mode 100644
index 0000000..0088bde
--- /dev/null
+++ b/core/runtime/src/test/resources/org/apache/polygene/runtime/instantiation/My.properties
@@ -0,0 +1,21 @@
+#
+#  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.
+#
+#
+#
+
+data=HabbaZout
\ No newline at end of file
diff --git a/core/runtime/src/test/resources/org/apache/polygene/runtime/service/HelloWorldService.properties b/core/runtime/src/test/resources/org/apache/polygene/runtime/service/HelloWorldService.properties
new file mode 100644
index 0000000..a51ce6a
--- /dev/null
+++ b/core/runtime/src/test/resources/org/apache/polygene/runtime/service/HelloWorldService.properties
@@ -0,0 +1,22 @@
+#
+#  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.
+#
+#
+#
+
+phrase=Hello
+name=World
diff --git a/core/runtime/src/test/resources/org/qi4j/runtime/instantiation/My.properties b/core/runtime/src/test/resources/org/qi4j/runtime/instantiation/My.properties
deleted file mode 100644
index 7044813..0000000
--- a/core/runtime/src/test/resources/org/qi4j/runtime/instantiation/My.properties
+++ /dev/null
@@ -1,16 +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.
-
-data=HabbaZout
\ No newline at end of file
diff --git a/core/runtime/src/test/resources/org/qi4j/runtime/service/HelloWorldService.properties b/core/runtime/src/test/resources/org/qi4j/runtime/service/HelloWorldService.properties
deleted file mode 100644
index f6308ba..0000000
--- a/core/runtime/src/test/resources/org/qi4j/runtime/service/HelloWorldService.properties
+++ /dev/null
@@ -1,17 +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.
-
-phrase=Hello
-name=World
diff --git a/core/spi/build.gradle b/core/spi/build.gradle
index 3908bc6..605d3c7 100644
--- a/core/spi/build.gradle
+++ b/core/spi/build.gradle
@@ -1,32 +1,35 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-jar { manifest { name = "Apache Zest™ Core SPI"}}
+apply plugin: 'polygene-core'
+
+jar { manifest { name = "Apache Polygene™ Core SPI" } }
 
 dependencies {
+  api polygene.core.api
+  api libraries.javax_json
 
-    compile project( ':org.qi4j.core:org.qi4j.core.api' )
-    compile libraries.org_json
+  runtimeOnly libraries.johnzon
 
-    testCompile project(":org.qi4j.core:org.qi4j.core.testsupport")
+  testImplementation polygene.core.testsupport
 
-    testRuntime project(":org.qi4j.core:org.qi4j.core.runtime")
-    testRuntime libraries.logback
-
+  testRuntimeOnly polygene.core.runtime
+  testRuntimeOnly libraries.logback
 }
diff --git a/core/spi/dev-status.xml b/core/spi/dev-status.xml
index 4f034dc..ba367e6 100644
--- a/core/spi/dev-status.xml
+++ b/core/spi/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <codebase>stable</codebase>
     <!--none,early,beta,stable,mature-->
diff --git a/core/spi/src/docs/metrics.txt b/core/spi/src/docs/metrics.txt
index 678db90..1f6e8ab 100644
--- a/core/spi/src/docs/metrics.txt
+++ b/core/spi/src/docs/metrics.txt
@@ -1,16 +1,19 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
+ *  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
  *
- * Licensed 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.
+ *       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.
 //////////////////////
 
 [[core-spi-metrics,Metrics SPI]]
diff --git a/core/spi/src/docs/serialization.txt b/core/spi/src/docs/serialization.txt
new file mode 100644
index 0000000..d2d2580
--- /dev/null
+++ b/core/spi/src/docs/serialization.txt
@@ -0,0 +1,115 @@
+///////////////////////////////////////////////////////////////
+ * 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.
+///////////////////////////////////////////////////////////////
+
+[[core-spi-serialization,Serialization SPI]]
+= Serialization SPI =
+
+TIP: Find Serialization extensions in the <<extensions>> list.
+
+== Overview ==
+
+The Polygene™ Core Runtime use Serialization to provide string representation of ValueComposites via their `toString()`
+method, and, their instantiation from the very same representation via the `newValueFromSerializedState(..)` method of
+the ValueBuilderFactory API.
+
+[snippet,java]
+--------------
+source=core/api/src/test/java/org/apache/polygene/api/value/DocumentationSupport.java
+tag=default
+--------------
+
+In each Module, if no Serialization service is assembled, a default one supporting the JSON format is used.
+
+[snippet,java]
+--------------
+source=core/api/src/test/java/org/apache/polygene/api/value/DocumentationSupport.java
+tag=service
+--------------
+
+== Text or Binary?
+
+The Core SPI provides adapters for text or bytes based serialization, extends the following types to implement a custom
+serialization.
+
+For text based serialization:
+
+[snippet,java]
+--------------
+source=core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractTextSerializer.java
+tag=text
+--------------
+
+[snippet,java]
+--------------
+source=core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractTextDeserializer.java
+tag=text
+--------------
+
+For bytes based serialization:
+
+[snippet,java]
+--------------
+source=core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractBinarySerializer.java
+tag=binary
+--------------
+
+[snippet,java]
+--------------
+source=core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractBinaryDeserializer.java
+tag=binary
+--------------
+
+== JSON or XML?
+
+The Core SPI provides JSON and XML serialization respectively based on `javax.json` and `javax.xml` types and APIs to
+work directly with these types so you can work with the actual object representations without serializing to text or
+bytes. They both rely on the text serialization adapters shown above.
+
+Here is an example using the `JsonSerialization` service:
+
+[snippet,java]
+--------------
+source=extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonValueCompositeSerializationTest.java
+tag=json-serialization
+--------------
+
+And another using the `XmlSerialization` service:
+
+[snippet,java]
+--------------
+source=extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlValueCompositeSerializationTest.java
+tag=xml-serialization
+--------------
+
+
+== Implementation notes ==
+
+Simply implement Serialization to create an extension for the Serialization SPI.
+The Core SPI module provides adapters to create Serializers and Deserializers.
+
+The behaviour described here apply to all Serialization services implemented using the Core SPI adapters. Note that
+nothing stops you from implementing an extension for the Serialization SPI without relying on theses adapters.
+
+Theses adapters are tailored for serialization mechanisms that support the following two structures that can be nested:
+
+    * a collection of name/value pairs. In various languages, this is realized as an object, record, struct,
+      dictionary, hash table, keyed list, or associative array,
+    * an ordered list of values. In most languages, this is realized as an array, vector, list, or sequence ;
+
+in other words, a JSON-like structure.
diff --git a/core/spi/src/docs/spi.txt b/core/spi/src/docs/spi.txt
index 32fc8b2..9371827 100644
--- a/core/spi/src/docs/spi.txt
+++ b/core/spi/src/docs/spi.txt
@@ -1,16 +1,19 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
+ *  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
  *
- * Licensed 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.
+ *       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.
 //////////////////////
 
 [[core-spi,Extension SPI]]
@@ -21,7 +24,7 @@
 source=core/spi/dev-status.xml
 --------------
 
-The Zest™ Core Runtime has a number of extension points, which we call the _Qi4j Core Extension SPI_. These are defined
+The Polygene™ Core Runtime has a number of extension points, which we call the _Polygene Core Extension SPI_. These are defined
 interfaces used *only* by the Core Runtime and *never* directly by application code. <<extensions>> are assembled in
 applications during the bootstrap phase.
 
@@ -29,20 +32,20 @@
 
 There are currently 5 Core SPI extensions;
 
-    * <<core-spi-valueserialization>>
+    * <<core-spi-serialization>>
     * <<core-spi-entitystore>>
     * <<core-spi-cache>>
     * <<core-spi-indexing>>
     * <<core-spi-metrics>>
 
-Zest™ Runtime Extensions implementations may depend on Zest™ Libraries, but Libraries are NOT ALLOWED to depend on
+Polygene™ Runtime Extensions implementations may depend on Polygene™ Libraries, but Libraries are NOT ALLOWED to depend on
 Extensions. Applications code is NOT ALLOWED to depend on extensions. And application code SHOULD NOT depend on the
-Core Extension SPI. If you think that is needed, please contact qi4j-dev forum at Google Groups, to see if your usecase
+Core Extension SPI. If you think that is needed, please contact users@dev.apache.org mailing list, to see if your usecase
 can be solved in a support manner, or that we need to extend the Core API to support it.
 
 :leveloffset: {level3}
 
-include::valueserialization.txt[]
+include::serialization.txt[]
 
 :leveloffset: {level3}
 
diff --git a/core/spi/src/docs/valueserialization.txt b/core/spi/src/docs/valueserialization.txt
deleted file mode 100644
index fa5fb86..0000000
--- a/core/spi/src/docs/valueserialization.txt
+++ /dev/null
@@ -1,83 +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.
-///////////////////////////////////////////////////////////////
-
-[[core-spi-valueserialization,ValueSerialization SPI]]
-= ValueSerialization SPI =
-
-== Overview ==
-
-The Zest™ Core Runtime use ValueSerialization to provide string representation of ValueComposites via their `toString()`
-method, and, their instanciation from the very same representation via the `newValueFromSerializedState(..)` method of
-the ValueBuilderFactory API.
-
-If no ValueSerialization service is visible, a default implementation supporting the JSON format used but note that it
-won't be available as a Service. So, in order to use the full ValueSerialization API a ValueSerialization service must
-be explicitely assembled in the Application. See the <<extensions>> documentation for details.
-
-== Implementation notes ==
-
-Simply implement ValueSerialization to create an extension for the ValueSerialization SPI.
-The Core SPI module provides adapters to create pull-parsing capable ValueSerializers and pull-parsing and tree-parsing
-capable ValueDeserializers.
-
-The behaviour described here apply to all ValueSerialization services implemented using the Core SPI adapters. Note that
-nothing stops you from implementing an extension for the ValueSerialization SPI without relying on theses adapters.
-
-Theses adapters are tailored for serialization mechanisms that support the following two structures that can be nested:
-
-    * a collection of name/value pairs. In various languages, this is realized as an object, record, struct,
-      dictionary, hash table, keyed list, or associative array,
-    * an ordered list of values. In most languages, this is realized as an array, vector, list, or sequence ;
-
-in other words, a JSON-like structure.
-
-Special attention is taken when dealing with Maps. They are serialized as an ordered list of collections of
-name/value pairs to keep the Map order for least surprise. That way, even when the underlying serialization mechanism
-do not keep the collection of name/value pairs order we can rely on it being kept.
-
-Here is a sample Map with two entries in JSON notation to make things clear:
-
-[source,javascript]
-----
-[
-    { "key": "foo",       "value": "bar"   },
-    { "key": "cathedral", "value": "bazar" }
-]
-----
-
-Among Plain Values (see the <<core-api-value,ValueSerialization API>> section) some are considered primitives to
-underlying serialization mechanisms and by so handed/come without conversion to/from implementations.
-
-Primitive values can be one of:
-
-    * String,
-    * Boolean or boolean,
-    * Integer or int,
-    * Long or long,
-    * Short or short,
-    * Byte or byte,
-    * Float or float,
-    * Double or double.
-
-Serialization is always done in a streaming manner using a pull-parsing based approach.
-
-Deserialization is done in a streaming manner using a pull-parsing based approach except when encountering a
-ValueComposite. ValueComposite types are deserialized using a tree-parsing based approach.
-
-All this means that you can serialize and deserialize large collections of values without filling the heap.
diff --git a/core/spi/src/main/java/org/apache/polygene/entitystore/memory/MemoryEntityStoreService.java b/core/spi/src/main/java/org/apache/polygene/entitystore/memory/MemoryEntityStoreService.java
new file mode 100644
index 0000000..9659646
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/entitystore/memory/MemoryEntityStoreService.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.entitystore.memory;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.spi.entitystore.BackupRestore;
+import org.apache.polygene.spi.entitystore.ConcurrentModificationCheckConcern;
+import org.apache.polygene.spi.entitystore.EntityStateVersions;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.StateChangeNotificationConcern;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreActivation;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreMixin;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * In-memory EntityStore service.
+ * <p>Useful for testing and non-persistent entities.</p>
+ * <p>Based on {@link JSONMapEntityStoreMixin}</p>
+ */
+@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
+@Mixins( { JSONMapEntityStoreMixin.class, MemoryMapEntityStoreMixin.class } )
+public interface MemoryEntityStoreService
+    extends EntityStore, EntityStateVersions, BackupRestore, StateStore, ServiceComposite, JSONMapEntityStoreActivation
+{
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/entitystore/memory/MemoryMapEntityStoreMixin.java b/core/spi/src/main/java/org/apache/polygene/entitystore/memory/MemoryMapEntityStoreMixin.java
new file mode 100644
index 0000000..71c9ad1
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/entitystore/memory/MemoryMapEntityStoreMixin.java
@@ -0,0 +1,167 @@
+/*
+ *  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.polygene.entitystore.memory;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.spi.entitystore.BackupRestore;
+import org.apache.polygene.spi.entitystore.EntityAlreadyExistsException;
+import org.apache.polygene.spi.entitystore.EntityNotFoundException;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+import org.apache.polygene.spi.entitystore.helpers.JSONKeys;
+import org.apache.polygene.spi.entitystore.helpers.MapEntityStore;
+import org.apache.polygene.spi.entitystore.helpers.MapEntityStoreActivation;
+
+/**
+ * In-memory implementation of MapEntityStore.
+ */
+public class MemoryMapEntityStoreMixin
+    implements MapEntityStore, BackupRestore, MapEntityStoreActivation
+{
+    private final Map<EntityReference, String> store;
+
+    @Service
+    private JavaxJsonFactories jsonFactories;
+
+    public MemoryMapEntityStoreMixin()
+    {
+        store = new HashMap<>();
+    }
+
+    @Override
+    public void activateMapEntityStore() {}
+
+    public boolean contains( EntityReference entityReference, EntityDescriptor descriptor ) throws EntityStoreException
+    {
+        return store.containsKey( entityReference );
+    }
+
+    @Override
+    public Reader get( EntityReference entityReference ) throws EntityStoreException
+    {
+        String state = store.get( entityReference );
+        if( state == null )
+        {
+            throw new EntityNotFoundException( entityReference );
+        }
+
+        return new StringReader( state );
+    }
+
+    @Override
+    public void applyChanges( MapEntityStore.MapChanges changes ) throws Exception
+    {
+        changes.visitMap( new MemoryMapChanger() );
+    }
+
+    @Override
+    public Stream<Reader> entityStates()
+    {
+        return store.values().stream().map( StringReader::new );
+    }
+
+    @Override
+    public Stream<String> backup()
+    {
+        return store.values().stream();
+    }
+
+    @Override
+    public void restore( Stream<String> stream )
+    {
+        store.clear();
+        stream.forEach(
+            item ->
+            {
+                String id = jsonFactories.readerFactory().createReader( new StringReader( item ) )
+                                         .readObject().getString( JSONKeys.IDENTITY );
+                store.put( EntityReference.parseEntityReference( id ), item );
+            } );
+    }
+
+    private class MemoryMapChanger
+        implements MapChanger
+    {
+        @Override
+        public Writer newEntity( EntityReference ref, EntityDescriptor descriptor )
+        {
+            return new StringWriter( 1000 )
+            {
+                @Override
+                public void close()
+                    throws IOException
+                {
+                    super.close();
+                    String old = store.put( ref, toString() );
+                    if( old != null )
+                    {
+                        store.put( ref, old );
+                        throw new EntityAlreadyExistsException( ref );
+                    }
+                }
+            };
+        }
+
+        @Override
+        public Writer updateEntity( MapChange mapChange )
+            throws IOException
+        {
+            return new StringWriter( 1000 )
+            {
+                @Override
+                public void close()
+                    throws IOException
+                {
+                    super.close();
+                    EntityReference reference = mapChange.reference();
+                    String old = store.put( reference, toString() );
+                    if( old == null )
+                    {
+                        store.remove( reference );
+                        throw new EntityNotFoundException( reference );
+                    }
+                }
+            };
+        }
+
+        @Override
+        public void removeEntity( EntityReference ref, EntityDescriptor descriptor )
+            throws EntityNotFoundException
+        {
+            String state = store.remove( ref );
+            // Ignore if the entity didn't already exist, as that can happen if it is both created and removed
+            // within the same UnitOfWork.
+//            if( state == null )
+//            {
+//                throw new EntityNotFoundException( ref );
+//            }
+        }
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/entitystore/memory/package.html b/core/spi/src/main/java/org/apache/polygene/entitystore/memory/package.html
new file mode 100644
index 0000000..eb9e94e
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/entitystore/memory/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>In-Memory EntityStore.</h2>
+    </body>
+</html>
diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJson.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJson.java
new file mode 100644
index 0000000..eb4961d
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJson.java
@@ -0,0 +1,92 @@
+/*
+ *  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.polygene.serialization.javaxjson;
+
+import javax.json.JsonArray;
+import javax.json.JsonException;
+import javax.json.JsonObject;
+import javax.json.JsonString;
+import javax.json.JsonStructure;
+import javax.json.JsonValue;
+
+/**
+ * javax.json utilities.
+ */
+public class JavaxJson
+{
+    /**
+     * Get a {@link String} out of a {@link JsonValue}.
+     *
+     * @param jsonValue the JSON value
+     * @return the String
+     */
+    public static String asString( JsonValue jsonValue )
+    {
+        return jsonValue instanceof JsonString ? ( (JsonString) jsonValue ).getString() : jsonValue.toString();
+    }
+
+    /**
+     * Require a {@link JsonValue} to be a {@link JsonStructure}.
+     *
+     * @param json the JSON value
+     * @return the JSON structure
+     * @throws JsonException if it is not
+     */
+    public static JsonStructure requireJsonStructure( JsonValue json )
+    {
+        if( json.getValueType() != JsonValue.ValueType.OBJECT && json.getValueType() != JsonValue.ValueType.ARRAY )
+        {
+            throw new JsonException( "Expected a JSON object or array but got " + json );
+        }
+        return (JsonStructure) json;
+    }
+
+    /**
+     * Require a {@link JsonValue} to be a {@link JsonObject}.
+     *
+     * @param json the JSON value
+     * @return the JSON object
+     * @throws JsonException if it is not
+     */
+    public static JsonObject requireJsonObject( JsonValue json )
+    {
+        if( json.getValueType() != JsonValue.ValueType.OBJECT )
+        {
+            throw new JsonException( "Expected a JSON object but got " + json );
+        }
+        return (JsonObject) json;
+    }
+
+    /**
+     * Require a {@link JsonValue} to be a {@link JsonArray}.
+     *
+     * @param json the JSON value
+     * @return the JSON array
+     * @throws JsonException if it is not
+     */
+    public static JsonArray requireJsonArray( JsonValue json )
+    {
+        if( json.getValueType() != JsonValue.ValueType.ARRAY )
+        {
+            throw new JsonException( "Expected a JSON array but got " + json );
+        }
+        return (JsonArray) json;
+    }
+
+    private JavaxJson() {}
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapter.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapter.java
new file mode 100644
index 0000000..eaaa986
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapter.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.serialization.javaxjson;
+
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import javax.json.JsonValue;
+import org.apache.polygene.api.type.ValueType;
+
+/**
+ * Adapter for JSON (de)serialization.
+ *
+ * @param <T> the adapted type
+ */
+public interface JavaxJsonAdapter<T>
+{
+    /**
+     * @return the adapted type
+     */
+    Class<T> type();
+
+    /**
+     * Serialize.
+     *
+     * @param jsonFactories Factories to create JSON
+     * @param object Object to serialize, never null
+     * @param serialize Serialization function for nested structure serialization
+     * @return Serialized JSON representation
+     */
+    JsonValue serialize( JavaxJsonFactories jsonFactories, Object object, Function<Object, JsonValue> serialize );
+
+    /**
+     * Deserialize.
+     *
+     * @param json JSON to deserialize from, never null
+     * @param deserialize Deserialization function for nested structure deserialization
+     * @return Deserialized object
+     */
+    T deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserialize );
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapters.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapters.java
new file mode 100644
index 0000000..75359f2
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapters.java
@@ -0,0 +1,386 @@
+/*
+ *  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.polygene.serialization.javaxjson;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import javax.json.JsonNumber;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.serialization.Converters;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.spi.serialization.BuiltInConverters;
+
+import static org.apache.polygene.api.type.HasTypesCollectors.closestType;
+import static org.apache.polygene.serialization.javaxjson.JavaxJsonSettings.orDefault;
+
+@Mixins( JavaxJsonAdapters.Mixin.class )
+public interface JavaxJsonAdapters
+{
+    void registerAdapter( ValueType valueType, JavaxJsonAdapter<?> adapter );
+
+    <T> JavaxJsonAdapter<T> adapterFor( ValueType valueType );
+
+    default <T> JavaxJsonAdapter<T> adapterFor( Class<T> type )
+    {
+        return adapterFor( ValueType.of( type ) );
+    }
+
+    class Mixin implements JavaxJsonAdapters, Initializable
+    {
+        private final Map<ValueType, JavaxJsonAdapter<?>> adapters = new LinkedHashMap<>();
+        private final Map<ValueType, JavaxJsonAdapter<?>> resolvedAdaptersCache = new HashMap<>();
+
+        @Uses
+        private ServiceDescriptor descriptor;
+
+        @This
+        private BuiltInConverters builtInConverters;
+
+        @This
+        private Converters converters;
+
+        @Override
+        public void initialize()
+        {
+            JavaxJsonSettings settings = orDefault( descriptor.metaInfo( JavaxJsonSettings.class ) );
+            settings.getConverters()
+                    .forEach( ( type, converter ) -> converters.registerConverter( type, converter ) );
+            builtInConverters.registerBuiltInConverters( converters );
+            settings.getAdapters().forEach( adapters::put );
+            registerBaseJavaxJsonAdapters();
+        }
+
+        @Override
+        public void registerAdapter( ValueType valueType, JavaxJsonAdapter<?> adapter )
+        {
+            adapters.put( valueType, adapter );
+            resolvedAdaptersCache.put( valueType, adapter );
+        }
+
+        @Override
+        public <T> JavaxJsonAdapter<T> adapterFor( ValueType valueType )
+        {
+            if( resolvedAdaptersCache.containsKey( valueType ) )
+            {
+                return castAdapter( resolvedAdaptersCache.get( valueType ) );
+            }
+            JavaxJsonAdapter<T> adapter = castAdapter( adapters.keySet().stream()
+                                                               .collect( closestType( valueType ) )
+                                                               .map( adapters::get )
+                                                               .orElse( null ) );
+            resolvedAdaptersCache.put( valueType, adapter );
+            return adapter;
+        }
+
+        @SuppressWarnings( "unchecked" )
+        private <T> JavaxJsonAdapter<T> castAdapter( JavaxJsonAdapter<?> adapter )
+        {
+            return (JavaxJsonAdapter<T>) adapter;
+        }
+
+        private void registerBaseJavaxJsonAdapters()
+        {
+            // Primitive Value types
+            adapters.put( ValueType.STRING, new StringAdapter() );
+            adapters.put( ValueType.CHARACTER, new CharacterAdapter() );
+            adapters.put( ValueType.BOOLEAN, new BooleanAdapter() );
+            adapters.put( ValueType.INTEGER, new IntegerAdapter() );
+            adapters.put( ValueType.LONG, new LongAdapter() );
+            adapters.put( ValueType.SHORT, new ShortAdapter() );
+            adapters.put( ValueType.BYTE, new ByteAdapter() );
+            adapters.put( ValueType.FLOAT, new FloatAdapter() );
+            adapters.put( ValueType.DOUBLE, new DoubleAdapter() );
+        }
+
+        private static abstract class ToJsonStringAdapter<T> implements JavaxJsonAdapter<T>
+        {
+            @Override
+            public JsonValue serialize( JavaxJsonFactories jsonFactories, Object object,
+                                        Function<Object, JsonValue> serialize )
+            {
+                return jsonFactories.toJsonString( object );
+            }
+        }
+
+        private static class StringAdapter extends ToJsonStringAdapter<String>
+        {
+            @Override
+            public Class<String> type() { return String.class; }
+
+            @Override
+            public String deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserialize )
+            {
+                return JavaxJson.asString( json );
+            }
+        }
+
+        private static class CharacterAdapter extends ToJsonStringAdapter<Character>
+        {
+            @Override
+            public Class<Character> type() { return Character.class; }
+
+            @Override
+            public Character deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserialize )
+            {
+                String string = JavaxJson.asString( json );
+                return string.isEmpty() ? null : string.charAt( 0 );
+            }
+        }
+
+        private static class BooleanAdapter implements JavaxJsonAdapter<Boolean>
+        {
+            @Override
+            public Class<Boolean> type() { return Boolean.class; }
+
+            @Override
+            public JsonValue serialize( JavaxJsonFactories jsonFactories, Object object,
+                                        Function<Object, JsonValue> serialize )
+            {
+                return type().cast( object ) ? JsonValue.TRUE : JsonValue.FALSE;
+            }
+
+            @Override
+            public Boolean deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserialize )
+            {
+                switch( json.getValueType() )
+                {
+                    case TRUE:
+                        return true;
+                    case FALSE:
+                        return false;
+                    case NULL:
+                        return null;
+                    case NUMBER:
+                        return ( (JsonNumber) json ).doubleValue() > 0;
+                    case STRING:
+                        return Boolean.valueOf( ( (JsonString) json ).getString() );
+                    default:
+                        throw new SerializationException( "Don't know how to deserialize Boolean from " + json );
+                }
+            }
+        }
+
+        private static class IntegerAdapter implements JavaxJsonAdapter<Integer>
+        {
+            @Override
+            public Class<Integer> type() { return Integer.class; }
+
+            @Override
+            public JsonValue serialize( JavaxJsonFactories jsonFactories,
+                                        Object object, Function<Object, JsonValue> serialize )
+            {
+                return jsonFactories.builderFactory().createObjectBuilder()
+                                    .add( "value", type().cast( object ) )
+                                    .build()
+                                    .getJsonNumber( "value" );
+            }
+
+            @Override
+            public Integer deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserialize )
+            {
+                switch( json.getValueType() )
+                {
+                    case NULL:
+                        return null;
+                    case NUMBER:
+                        return ( (JsonNumber) json ).intValueExact();
+                    case STRING:
+                        String string = ( (JsonString) json ).getString();
+                        return string.isEmpty() ? 0 : Integer.parseInt( string );
+                    default:
+                        throw new SerializationException( "Don't know how to deserialize Integer from " + json );
+                }
+            }
+        }
+
+        private static class LongAdapter implements JavaxJsonAdapter<Long>
+        {
+            @Override
+            public Class<Long> type() { return Long.class; }
+
+            @Override
+            public JsonValue serialize( JavaxJsonFactories jsonFactories,
+                                        Object object, Function<Object, JsonValue> serialize )
+            {
+                return jsonFactories.builderFactory().createObjectBuilder()
+                                    .add( "value", type().cast( object ) )
+                                    .build()
+                                    .getJsonNumber( "value" );
+            }
+
+            @Override
+            public Long deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserialize )
+            {
+                switch( json.getValueType() )
+                {
+                    case NULL:
+                        return null;
+                    case NUMBER:
+                        return ( (JsonNumber) json ).longValueExact();
+                    case STRING:
+                        String string = ( (JsonString) json ).getString();
+                        return string.isEmpty() ? 0L : Long.parseLong( string );
+                    default:
+                        throw new SerializationException( "Don't know how to deserialize Long from " + json );
+                }
+            }
+        }
+
+        private static class ShortAdapter implements JavaxJsonAdapter<Short>
+        {
+            @Override
+            public Class<Short> type() { return Short.class; }
+
+            @Override
+            public JsonValue serialize( JavaxJsonFactories jsonFactories,
+                                        Object object, Function<Object, JsonValue> serialize )
+            {
+                return jsonFactories.builderFactory().createObjectBuilder()
+                                    .add( "value", type().cast( object ) )
+                                    .build()
+                                    .getJsonNumber( "value" );
+            }
+
+            @Override
+            public Short deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserialize )
+            {
+                switch( json.getValueType() )
+                {
+                    case NULL:
+                        return null;
+                    case NUMBER:
+                        return (short) ( (JsonNumber) json ).intValueExact();
+                    case STRING:
+                        String string = ( (JsonString) json ).getString();
+                        return string.isEmpty() ? 0 : Short.parseShort( string );
+                    default:
+                        throw new SerializationException( "Don't know how to deserialize Short from " + json );
+                }
+            }
+        }
+
+        private static class ByteAdapter implements JavaxJsonAdapter<Byte>
+        {
+            @Override
+            public Class<Byte> type() { return Byte.class; }
+
+            @Override
+            public JsonValue serialize( JavaxJsonFactories jsonFactories,
+                                        Object object, Function<Object, JsonValue> serialize )
+            {
+                return jsonFactories.builderFactory().createObjectBuilder()
+                                    .add( "value", type().cast( object ) )
+                                    .build()
+                                    .getJsonNumber( "value" );
+            }
+
+            @Override
+            public Byte deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserialize )
+            {
+                switch( json.getValueType() )
+                {
+                    case NULL:
+                        return null;
+                    case NUMBER:
+                        return (byte) ( (JsonNumber) json ).intValueExact();
+                    case STRING:
+                        String string = ( (JsonString) json ).getString();
+                        return string.isEmpty() ? 0 : Byte.parseByte( string );
+                    default:
+                        throw new SerializationException( "Don't know how to deserialize Byte from " + json );
+                }
+            }
+        }
+
+        private static class FloatAdapter implements JavaxJsonAdapter<Float>
+        {
+            @Override
+            public Class<Float> type() { return Float.class; }
+
+            @Override
+            public JsonValue serialize( JavaxJsonFactories jsonFactories,
+                                        Object object, Function<Object, JsonValue> serialize )
+            {
+                return jsonFactories.builderFactory().createObjectBuilder()
+                                    .add( "value", type().cast( object ) )
+                                    .build()
+                                    .getJsonNumber( "value" );
+            }
+
+            @Override
+            public Float deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserialize )
+            {
+                switch( json.getValueType() )
+                {
+                    case NULL:
+                        return null;
+                    case NUMBER:
+                        return (float) ( (JsonNumber) json ).doubleValue();
+                    case STRING:
+                        String string = ( (JsonString) json ).getString();
+                        return string.isEmpty() ? 0F : Float.parseFloat( string );
+                    default:
+                        throw new SerializationException( "Don't know how to deserialize Float from " + json );
+                }
+            }
+        }
+
+        private static class DoubleAdapter implements JavaxJsonAdapter<Double>
+        {
+            @Override
+            public Class<Double> type() { return Double.class; }
+
+            @Override
+            public JsonValue serialize( JavaxJsonFactories jsonFactories,
+                                        Object object, Function<Object, JsonValue> serialize )
+            {
+                return jsonFactories.builderFactory().createObjectBuilder()
+                                    .add( "value", type().cast( object ) )
+                                    .build()
+                                    .getJsonNumber( "value" );
+            }
+
+            @Override
+            public Double deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserialize )
+            {
+                switch( json.getValueType() )
+                {
+                    case NULL:
+                        return null;
+                    case NUMBER:
+                        return ( (JsonNumber) json ).doubleValue();
+                    case STRING:
+                        String string = ( (JsonString) json ).getString();
+                        return string.isEmpty() ? 0D : Double.parseDouble( string );
+                    default:
+                        throw new SerializationException( "Don't know how to deserialize Double from " + json );
+                }
+            }
+        }
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonDeserializer.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonDeserializer.java
new file mode 100644
index 0000000..ad647a4
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonDeserializer.java
@@ -0,0 +1,398 @@
+/*
+ *  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.polygene.serialization.javaxjson;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.UncheckedIOException;
+import java.lang.reflect.Array;
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonReader;
+import javax.json.JsonString;
+import javax.json.JsonStructure;
+import javax.json.JsonValue;
+import javax.json.stream.JsonParser;
+import javax.json.stream.JsonParsingException;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.StatefulAssociationCompositeDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.serialization.Converter;
+import org.apache.polygene.api.serialization.Converters;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ArrayType;
+import org.apache.polygene.api.type.CollectionType;
+import org.apache.polygene.api.type.MapType;
+import org.apache.polygene.api.type.StatefulAssociationValueType;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.spi.serialization.AbstractTextDeserializer;
+import org.apache.polygene.spi.serialization.JsonDeserializer;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.Collections.unmodifiableList;
+import static java.util.Collections.unmodifiableMap;
+import static java.util.Collections.unmodifiableSet;
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.toCollection;
+import static org.apache.polygene.api.util.Collectors.toMapWithNullValues;
+import static org.apache.polygene.serialization.javaxjson.JavaxJson.asString;
+import static org.apache.polygene.serialization.javaxjson.JavaxJson.requireJsonArray;
+import static org.apache.polygene.serialization.javaxjson.JavaxJson.requireJsonObject;
+import static org.apache.polygene.serialization.javaxjson.JavaxJson.requireJsonStructure;
+
+public class JavaxJsonDeserializer extends AbstractTextDeserializer
+    implements JsonDeserializer, Initializable
+{
+    @This
+    private JavaxJsonFactories jsonFactories;
+
+    @This
+    private Converters converters;
+
+    @This
+    private JavaxJsonAdapters adapters;
+
+    @Uses
+    private ServiceDescriptor descriptor;
+
+    private JavaxJsonSettings settings;
+    private JsonString emptyJsonString;
+
+    @Override
+    public void initialize() throws Exception
+    {
+        settings = JavaxJsonSettings.orDefault( descriptor.metaInfo( JavaxJsonSettings.class ) );
+        emptyJsonString = jsonFactories.builderFactory().createObjectBuilder().add( "s", "" ).build()
+                                       .getJsonString( "s" );
+    }
+
+    @Override
+    public <T> T deserialize( ModuleDescriptor module, ValueType valueType, Reader state )
+    {
+        // JSR-353 Does not allow reading "out of structure" values
+        // See https://www.jcp.org/en/jsr/detail?id=353
+        // And commented JsonReader#readValue() method in the javax.json API
+        // BUT, it will be part of the JsonReader contract in the next version
+        // See https://www.jcp.org/en/jsr/detail?id=374
+        // Implementation by provider is optional though, so we'll always need a default implementation here.
+        // Fortunately, JsonParser has new methods allowing to read structures while parsing so it will be easy to do.
+        // In the meantime, a poor man's implementation reading the json into memory will do.
+        // TODO Revisit values out of structure JSON deserialization when JSR-374 is out
+        String stateString;
+        try( BufferedReader buffer = new BufferedReader( state ) )
+        {
+            stateString = buffer.lines().collect( joining( "\n" ) );
+        }
+        catch( IOException ex )
+        {
+            throw new UncheckedIOException( ex );
+        }
+        // We want plain Strings, BigDecimals, BigIntegers to be deserialized even when unquoted
+        Function<String, T> plainValueFunction = string ->
+        {
+            String poorMans = "{\"value\":" + string + "}";
+            JsonObject poorMansJson = jsonFactories.readerFactory()
+                                                   .createReader( new StringReader( poorMans ) )
+                                                   .readObject();
+            JsonValue value = poorMansJson.get( "value" );
+            return fromJson( module, valueType, value );
+        };
+        Function<String, T> outOfStructureFunction = string ->
+        {
+            // Is this an unquoted plain value?
+            try
+            {
+                return plainValueFunction.apply( '"' + string + '"' );
+            }
+            catch( JsonParsingException ex )
+            {
+                return plainValueFunction.apply( string );
+            }
+        };
+        try( JsonParser parser = jsonFactories.parserFactory().createParser( new StringReader( stateString ) ) )
+        {
+            if( parser.hasNext() )
+            {
+                JsonParser.Event e = parser.next();
+                switch( e )
+                {
+                    case VALUE_NULL:
+                        return null;
+                    case START_ARRAY:
+                    case START_OBJECT:
+                        // JSON Structure
+                        try( JsonReader reader = jsonFactories.readerFactory()
+                                                              .createReader( new StringReader( stateString ) ) )
+                        {
+                            return fromJson( module, valueType, reader.read() );
+                        }
+                    default:
+                        // JSON Value out of structure
+                        return outOfStructureFunction.apply( stateString );
+                }
+            }
+        }
+        catch( JsonParsingException ex )
+        {
+            return outOfStructureFunction.apply( stateString );
+        }
+        // Empty state string?
+        return fromJson( module, valueType, emptyJsonString );
+    }
+
+    @Override
+    public <T> T fromJson( ModuleDescriptor module, ValueType valueType, JsonValue state )
+    {
+        return doDeserialize( module, valueType, state );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private <T> T doDeserialize( ModuleDescriptor module, ValueType valueType, JsonValue json )
+    {
+        if( json == null || JsonValue.NULL.equals( json ) )
+        {
+            return null;
+        }
+        Converter<Object> converter = converters.converterFor( valueType );
+        if( converter != null )
+        {
+            return (T) converter.fromString( doDeserialize( module, ValueType.STRING, json ).toString() );
+        }
+        JavaxJsonAdapter<?> adapter = adapters.adapterFor( valueType );
+        if( adapter != null )
+        {
+            return (T) adapter.deserialize( json, ( jsonValue, type ) -> doDeserialize( module, type, jsonValue ) );
+        }
+        Class<? extends ValueType> valueTypeClass = valueType.getClass();
+        if( ArrayType.class.isAssignableFrom( valueTypeClass ) )
+        {
+            return (T) deserializeArray( module, (ArrayType) valueType, json );
+        }
+        if( CollectionType.class.isAssignableFrom( valueTypeClass ) )
+        {
+            return (T) deserializeCollection( module, (CollectionType) valueType, requireJsonArray( json ) );
+        }
+        if( MapType.class.isAssignableFrom( valueTypeClass ) )
+        {
+            return (T) deserializeMap( module, (MapType) valueType, requireJsonStructure( json ) );
+        }
+        if( StatefulAssociationValueType.class.isAssignableFrom( valueTypeClass ) )
+        {
+            return (T) deserializeStatefulAssociationValue( module, (StatefulAssociationValueType<?>) valueType,
+                                                            requireJsonObject( json ) );
+        }
+        return doGuessDeserialize( module, valueType, json );
+    }
+
+    private Object deserializeArray( ModuleDescriptor module, ArrayType arrayType, JsonValue json )
+    {
+        if( arrayType.isArrayOfPrimitiveBytes() && json.getValueType() == JsonValue.ValueType.STRING )
+        {
+            byte[] bytes = asString( json ).getBytes( UTF_8 );
+            return Base64.getDecoder().decode( bytes );
+        }
+        if( json.getValueType() == JsonValue.ValueType.ARRAY )
+        {
+            CollectionType collectionType = CollectionType.listOf( arrayType.collectedType() );
+            List<Object> collection = (List<Object>) deserializeCollection( module,
+                                                                            collectionType,
+                                                                            requireJsonArray( json ) );
+            Object array = Array.newInstance( arrayType.collectedType().primaryType(), collection.size() );
+            for( int idx = 0; idx < collection.size(); idx++ )
+            {
+                Array.set( array, idx, collection.get( idx ) );
+            }
+            return array;
+        }
+        throw new SerializationException( "Don't know how to deserialize " + arrayType + " from " + json );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private <T> T doGuessDeserialize( ModuleDescriptor module, ValueType valueType, JsonValue json )
+    {
+        switch( json.getValueType() )
+        {
+            case OBJECT:
+                JsonObject object = (JsonObject) json;
+                String typeInfo = object.getString( settings.getTypeInfoPropertyName(),
+                                                    valueType.primaryType().getName() );
+                StatefulAssociationCompositeDescriptor descriptor = statefulCompositeDescriptorFor( module, typeInfo );
+                if( descriptor != null )
+                {
+                    return (T) deserializeStatefulAssociationValue( ( (CompositeDescriptor) descriptor ).module(),
+                                                                    descriptor.valueType(),
+                                                                    object );
+                }
+            default:
+                throw new SerializationException( "Don't know how to deserialize " + valueType + " from " + json );
+        }
+    }
+
+    private <T> Collection<T> deserializeCollection( ModuleDescriptor module, CollectionType collectionType,
+                                                     JsonArray json )
+    {
+        return (Collection<T>) json.stream()
+                                   .map( item -> doDeserialize( module, collectionType.collectedType(), item ) )
+                                   .collect( toCollection(
+                                       () -> collectionType.isSet() ? new LinkedHashSet<>() : new ArrayList<>() ) );
+    }
+
+    /**
+     * Map deserialization.
+     *
+     * {@literal JsonObject}s are deserialized to {@literal Map<String, ?>}.
+     * {@literal JsonArray}s of key/value {@literal JsonObject}s are deserialized to {@literal Map<?, ?>}.
+     */
+    private Map<?, ?> deserializeMap( ModuleDescriptor module, MapType mapType, JsonStructure json )
+    {
+        if( json.getValueType() == JsonValue.ValueType.OBJECT )
+        {
+            JsonObject object = (JsonObject) json;
+            return object.entrySet().stream()
+                         .map( entry -> new AbstractMap.SimpleImmutableEntry<>(
+                             entry.getKey(),
+                             doDeserialize( module, mapType.valueType(), entry.getValue() ) ) )
+                         .collect( toMapWithNullValues( LinkedHashMap::new ) );
+        }
+        if( json.getValueType() == JsonValue.ValueType.ARRAY )
+        {
+            JsonArray array = (JsonArray) json;
+            return array.stream()
+                        .map( JsonObject.class::cast )
+                        .map( entry -> new AbstractMap.SimpleImmutableEntry<>(
+                            doDeserialize( module, mapType.keyType(), entry.get( "key" ) ),
+                            doDeserialize( module, mapType.valueType(), entry.get( "value" ) )
+                        ) )
+                        .collect( toMapWithNullValues( LinkedHashMap::new ) );
+        }
+        throw new SerializationException( "Don't know how to deserialize " + mapType + " from " + json );
+    }
+
+    private Object deserializeStatefulAssociationValue( ModuleDescriptor module,
+                                                        StatefulAssociationValueType<?> valueType,
+                                                        JsonObject json )
+    {
+        String typeInfoName = settings.getTypeInfoPropertyName();
+        String typeInfo = json.getString( typeInfoName, null );
+        if( typeInfo != null )
+        {
+            StatefulAssociationCompositeDescriptor descriptor = statefulCompositeDescriptorFor( module, typeInfo );
+            if( descriptor == null )
+            {
+                throw new SerializationException(
+                    typeInfoName + ": " + typeInfo + " could not be resolved while deserializing " + json );
+            }
+            valueType = descriptor.valueType();
+        }
+        ValueBuilder builder = module.instance().newValueBuilderWithState(
+            valueType.primaryType(),
+            propertyFunction( valueType.module(), json ),
+            associationFunction( valueType.module(), json ),
+            manyAssociationFunction( valueType.module(), json ),
+            namedAssociationFunction( valueType.module(), json ) );
+        return builder.newInstance();
+    }
+
+    private Function<PropertyDescriptor, Object> propertyFunction( ModuleDescriptor module, JsonObject object )
+    {
+        return property ->
+        {
+            JsonValue jsonValue = object.get( property.qualifiedName().name() );
+            if( jsonValue != null )
+            {
+                Object value;
+                Converter converter = converters.converterFor( property );
+                if( converter != null )
+                {
+                    value = converter.fromString( doDeserialize( module, ValueType.STRING, jsonValue ) );
+                }
+                else
+                {
+                    value = doDeserialize( module, property.valueType(), jsonValue );
+                }
+                if( property.isImmutable() )
+                {
+                    if( value instanceof Set )
+                    {
+                        return unmodifiableSet( (Set<?>) value );
+                    }
+                    else if( value instanceof List )
+                    {
+                        return unmodifiableList( (List<?>) value );
+                    }
+                    else if( value instanceof Map )
+                    {
+                        return unmodifiableMap( (Map<?, ?>) value );
+                    }
+                }
+                return value;
+            }
+            return property.resolveInitialValue( module );
+        };
+    }
+
+    private Function<AssociationDescriptor, EntityReference> associationFunction( ModuleDescriptor module,
+                                                                                  JsonObject object )
+    {
+        return association -> doDeserialize( module, ValueType.ENTITY_REFERENCE,
+                                             object.get( association.qualifiedName().name() ) );
+    }
+
+    private Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction( ModuleDescriptor module,
+                                                                                              JsonObject object )
+    {
+        return association ->
+        {
+            List<EntityReference> list = doDeserialize( module, ENTITY_REF_LIST_VALUE_TYPE,
+                                                        object.get( association.qualifiedName().name() ) );
+            return list == null ? Stream.empty() : list.stream();
+        };
+    }
+
+    private Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction(
+        ModuleDescriptor module, JsonObject object )
+    {
+        return association ->
+        {
+            Map<String, EntityReference> map = doDeserialize( module, ENTITY_REF_MAP_VALUE_TYPE,
+                                                              object.get( association.qualifiedName().name() ) );
+            return map == null ? Stream.empty() : map.entrySet().stream();
+        };
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonFactories.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonFactories.java
new file mode 100644
index 0000000..0a790f2
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonFactories.java
@@ -0,0 +1,255 @@
+/*
+ *  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.polygene.serialization.javaxjson;
+
+import java.util.Arrays;
+import java.util.List;
+import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonBuilderFactory;
+import javax.json.JsonException;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonReaderFactory;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+import javax.json.JsonWriterFactory;
+import javax.json.spi.JsonProvider;
+import javax.json.stream.JsonGeneratorFactory;
+import javax.json.stream.JsonParserFactory;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceDescriptor;
+
+@Mixins( JavaxJsonFactories.Mixin.class )
+public interface JavaxJsonFactories
+{
+    JsonParserFactory parserFactory();
+
+    JsonReaderFactory readerFactory();
+
+    JsonGeneratorFactory generatorFactory();
+
+    JsonBuilderFactory builderFactory();
+
+    JsonWriterFactory writerFactory();
+
+    /**
+     * Creates a {@link JsonString} with the {@link Object#toString()} result on the given object.
+     *
+     * @param object the object
+     * @return the JsonString
+     */
+    JsonString toJsonString( Object object );
+
+    /**
+     * Creates a {@link JsonObjectBuilder} populated with the state of a {@link JsonObject}.
+     *
+     * @param jsonObject the JsonObject
+     * @return the builder
+     */
+    JsonObjectBuilder cloneBuilder( JsonObject jsonObject );
+
+    /**
+     * Creates a {@link JsonObjectBuilder} populated with the state of a {@link JsonObject}, including only some keys.
+     *
+     * @param jsonObject the JsonObject
+     * @param keys the keys to include
+     * @return the builder
+     */
+    JsonObjectBuilder cloneBuilderInclude( JsonObject jsonObject, String... keys );
+
+    /**
+     * Creates a {@link JsonObjectBuilder} populated with the state of a {@link JsonObject}, excluding some keys.
+     *
+     * @param jsonObject the JsonObject
+     * @param keys the keys to exclude
+     * @return the builder
+     */
+    JsonObjectBuilder cloneBuilderExclude( JsonObject jsonObject, String... keys );
+
+    /**
+     * Creates a {@link JsonArrayBuilder} populated with the state of a {@link JsonArray}.
+     *
+     * @param jsonArray the JsonArray
+     * @return the builder
+     */
+    JsonArrayBuilder cloneBuilder( JsonArray jsonArray );
+
+    /**
+     * Creates a {@link JsonArrayBuilder} populated with the state of a {@link JsonArray}, excluding some values.
+     *
+     * @param jsonArray the JsonArray
+     * @param values the values to exclude
+     * @return the builder
+     */
+    JsonArrayBuilder cloneBuilderExclude( JsonArray jsonArray, JsonValue... values );
+
+    class Mixin implements JavaxJsonFactories, Initializable
+    {
+        @Uses
+        private ServiceDescriptor descriptor;
+
+        private JsonParserFactory parserFactory;
+        private JsonReaderFactory readerFactory;
+        private JsonGeneratorFactory generatorFactory;
+        private JsonBuilderFactory builderFactory;
+        private JsonWriterFactory writerFactory;
+
+        @Override
+        public void initialize() throws Exception
+        {
+            JavaxJsonSettings settings = JavaxJsonSettings.orDefault( descriptor.metaInfo( JavaxJsonSettings.class ) );
+
+            String jsonProviderClassName = settings.getJsonProviderClassName();
+            JsonProvider jsonProvider;
+            if( jsonProviderClassName == null )
+            {
+                jsonProvider = JsonProvider.provider();
+            }
+            else
+            {
+                try
+                {
+                    Class<?> clazz = Class.forName( jsonProviderClassName );
+                    jsonProvider = (JsonProvider) clazz.newInstance();
+                }
+                catch( ClassNotFoundException ex )
+                {
+                    throw new JsonException( "Provider " + jsonProviderClassName + " not found", ex );
+                }
+                catch( Exception ex )
+                {
+                    throw new JsonException( "Provider " + jsonProviderClassName + " could not be instantiated", ex );
+                }
+            }
+
+            parserFactory = jsonProvider.createParserFactory( settings.getJsonParserProperties() );
+            readerFactory = jsonProvider.createReaderFactory( settings.getJsonParserProperties() );
+
+            generatorFactory = jsonProvider.createGeneratorFactory( settings.getJsonGeneratorProperties() );
+            builderFactory = jsonProvider.createBuilderFactory( settings.getJsonGeneratorProperties() );
+            writerFactory = jsonProvider.createWriterFactory( settings.getJsonGeneratorProperties() );
+        }
+
+        @Override
+        public JsonParserFactory parserFactory()
+        {
+            return parserFactory;
+        }
+
+        @Override
+        public JsonReaderFactory readerFactory()
+        {
+            return readerFactory;
+        }
+
+        @Override
+        public JsonGeneratorFactory generatorFactory()
+        {
+            return generatorFactory;
+        }
+
+        @Override
+        public JsonBuilderFactory builderFactory()
+        {
+            return builderFactory;
+        }
+
+        @Override
+        public JsonWriterFactory writerFactory()
+        {
+            return writerFactory;
+        }
+
+        @Override
+        public JsonString toJsonString( Object object )
+        {
+            return builderFactory.createObjectBuilder().add( "value", object.toString() ).build()
+                                 .getJsonString( "value" );
+        }
+
+        @Override
+        public JsonObjectBuilder cloneBuilder( JsonObject jsonObject )
+        {
+            JsonObjectBuilder builder = builderFactory.createObjectBuilder();
+            for( String key : jsonObject.keySet() )
+            {
+                builder.add( key, jsonObject.get( key ) );
+            }
+            return builder;
+        }
+
+        @Override
+        public JsonObjectBuilder cloneBuilderInclude( JsonObject jsonObject, String... keys )
+        {
+            List<String> includes = Arrays.asList( keys );
+            JsonObjectBuilder builder = builderFactory.createObjectBuilder();
+            for( String include : includes )
+            {
+                if( jsonObject.containsKey( include ) )
+                {
+                    builder.add( include, jsonObject.get( include ) );
+                }
+            }
+            return builder;
+        }
+
+        @Override
+        public JsonObjectBuilder cloneBuilderExclude( JsonObject jsonObject, String... keys )
+        {
+            List<String> excludes = Arrays.asList( keys );
+            JsonObjectBuilder builder = builderFactory.createObjectBuilder();
+            for( String key : jsonObject.keySet() )
+            {
+                if( !excludes.contains( key ) )
+                {
+                    builder.add( key, jsonObject.get( key ) );
+                }
+            }
+            return builder;
+        }
+
+        @Override
+        public JsonArrayBuilder cloneBuilder( JsonArray jsonArray )
+        {
+            JsonArrayBuilder builder = builderFactory.createArrayBuilder();
+            for( JsonValue entry : jsonArray )
+            {
+                builder.add( entry );
+            }
+            return builder;
+        }
+
+        @Override
+        public JsonArrayBuilder cloneBuilderExclude( JsonArray jsonArray, JsonValue... values )
+        {
+            List<JsonValue> excludes = Arrays.asList( values );
+            JsonArrayBuilder job = builderFactory.createArrayBuilder();
+            for( JsonValue entry : jsonArray )
+            {
+                if( !excludes.contains( entry ) )
+                {
+                    job.add( entry );
+                }
+            }
+            return job;
+        }
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerialization.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerialization.java
new file mode 100644
index 0000000..2e034b0
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerialization.java
@@ -0,0 +1,26 @@
+/*
+ *  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.polygene.serialization.javaxjson;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.spi.serialization.JsonSerialization;
+
+@Mixins( { JavaxJsonSerializer.class, JavaxJsonDeserializer.class } )
+public interface JavaxJsonSerialization extends JsonSerialization
+{
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerializer.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerializer.java
new file mode 100644
index 0000000..065e28b
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerializer.java
@@ -0,0 +1,267 @@
+/*
+ *  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.polygene.serialization.javaxjson;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.io.Writer;
+import java.util.Base64;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.composite.StatefulAssociationCompositeDescriptor;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.serialization.Converter;
+import org.apache.polygene.api.serialization.Converters;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.type.ArrayType;
+import org.apache.polygene.api.type.MapType;
+import org.apache.polygene.api.type.StatefulAssociationValueType;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.spi.serialization.AbstractTextSerializer;
+import org.apache.polygene.spi.serialization.JsonSerializer;
+import org.apache.polygene.spi.util.ArrayIterable;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.stream.Collectors.toList;
+import static org.apache.polygene.api.util.Collectors.toMap;
+
+public class JavaxJsonSerializer extends AbstractTextSerializer
+    implements JsonSerializer, Initializable
+{
+    @This
+    private JavaxJsonFactories jsonFactories;
+
+    @This
+    private Converters converters;
+
+    @This
+    private JavaxJsonAdapters adapters;
+
+    @Uses
+    private ServiceDescriptor descriptor;
+
+    private JavaxJsonSettings settings;
+
+    @Override
+    public void initialize() throws Exception
+    {
+        settings = JavaxJsonSettings.orDefault( descriptor.metaInfo( JavaxJsonSettings.class ) );
+    }
+
+    @Override
+    public void serialize( Options options, Writer writer, @Optional Object object )
+    {
+        JsonValue jsonValue = toJson( options, object );
+        if( jsonValue == null )
+        {
+            return;
+        }
+        try
+        {
+            // We want plain Strings to be serialized without quotes which is non JSON compliant
+            // See https://java.net/jira/browse/JSON_PROCESSING_SPEC-65
+            if( jsonValue.getValueType() == JsonValue.ValueType.STRING )
+            {
+                writer.write( ( (JsonString) jsonValue ).getString() );
+            }
+            else
+            {
+                writer.write( jsonValue.toString() );
+            }
+        }
+        catch( IOException ex )
+        {
+            throw new UncheckedIOException( ex );
+        }
+    }
+
+    @Override
+    public <T> Function<T, JsonValue> toJsonFunction( Options options )
+    {
+        return object -> doSerialize( options, object, true );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private JsonValue doSerialize( Options options, Object object, boolean root )
+    {
+        if( object == null )
+        {
+            return JsonValue.NULL;
+        }
+        Class<?> objectClass = object.getClass();
+        Converter<Object> converter = converters.converterFor( objectClass );
+        if( converter != null )
+        {
+            return doSerialize( options, converter.toString( object ), false );
+        }
+        JavaxJsonAdapter<?> adapter = adapters.adapterFor( objectClass );
+        if( adapter != null )
+        {
+            return adapter.serialize( jsonFactories, object, obj -> doSerialize( options, obj, false ) );
+        }
+        if( StatefulAssociationValueType.isStatefulAssociationValue( objectClass ) )
+        {
+            return serializeStatefulAssociationValue( options, object, root );
+        }
+        if( MapType.isMap( objectClass ) )
+        {
+            return serializeMap( options, (Map<?, ?>) object );
+        }
+        if( ArrayType.isArray( objectClass ) )
+        {
+            return serializeArray( options, object );
+        }
+        if( Iterable.class.isAssignableFrom( objectClass ) )
+        {
+            return serializeIterable( options, (Iterable<?>) object );
+        }
+        if( Stream.class.isAssignableFrom( objectClass ) )
+        {
+            return serializeStream( options, (Stream<?>) object );
+        }
+        throw new SerializationException( "Don't know how to serialize " + object );
+    }
+
+    private JsonObject serializeStatefulAssociationValue( Options options, Object composite, boolean root )
+    {
+        CompositeInstance instance = PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF.apply( (Composite) composite );
+        StatefulAssociationCompositeDescriptor descriptor =
+            (StatefulAssociationCompositeDescriptor) instance.descriptor();
+        AssociationStateHolder state = (AssociationStateHolder) instance.state();
+        StatefulAssociationValueType<?> valueType = descriptor.valueType();
+
+        JsonObjectBuilder builder = jsonFactories.builderFactory().createObjectBuilder();
+        valueType.properties().forEach(
+            property ->
+            {
+                Object value = state.propertyFor( property.accessor() ).get();
+                Converter converter = converters.converterFor( property );
+                if( converter != null )
+                {
+                    value = converter.toString( value );
+                }
+                builder.add( property.qualifiedName().name(), doSerialize( options, value, false ) );
+            } );
+        valueType.associations().forEach(
+            association -> builder.add(
+                association.qualifiedName().name(),
+                doSerialize( options, state.associationFor( association.accessor() ).reference(), false ) ) );
+        valueType.manyAssociations().forEach(
+            association -> builder.add(
+                association.qualifiedName().name(),
+                doSerialize( options, state.manyAssociationFor( association.accessor() ).references()
+                                           .collect( toList() ),
+                             false ) ) );
+        valueType.namedAssociations().forEach(
+            association -> builder.add(
+                association.qualifiedName().name(),
+                doSerialize( options,
+                             state.namedAssociationFor( association.accessor() ).references()
+                                  .collect( toMap() ),
+                             false ) ) );
+        if( ( root && options.rootTypeInfo() ) || ( !root && options.nestedTypeInfo() ) )
+        {
+            withTypeInfo( builder, valueType );
+        }
+        return builder.build();
+    }
+
+    private void withTypeInfo( JsonObjectBuilder builder, ValueType valueType )
+    {
+        builder.add( settings.getTypeInfoPropertyName(), valueType.primaryType().getName() );
+    }
+
+    /**
+     * Map serialization.
+     *
+     * {@literal Map<String, ?>} are serialized to a {@literal JsonObject}.
+     * {@literal Map<?, ?>} are serialized to a {@literal JsonArray} or key/value {@literal JsonObject}s.
+     * Empty maps are serialized to an empty {@literal JsonObject}.
+     */
+    private JsonValue serializeMap( Options options, Map<?, ?> map )
+    {
+        if( map.isEmpty() )
+        {
+            // Defaults to {}
+            return jsonFactories.builderFactory().createObjectBuilder().build();
+        }
+        Predicate<Object> characterKeyPredicate = key ->
+            key != null && ( key instanceof CharSequence || key instanceof Character );
+        if( map.keySet().stream().allMatch( characterKeyPredicate ) )
+        {
+            JsonObjectBuilder builder = jsonFactories.builderFactory().createObjectBuilder();
+            map.forEach( ( key, value ) -> builder.add( key.toString(),
+                                                        doSerialize( options, value, false ) ) );
+            return builder.build();
+        }
+        else
+        {
+            JsonArrayBuilder builder = jsonFactories.builderFactory().createArrayBuilder();
+            map.forEach( ( key, value ) -> builder.add(
+                jsonFactories.builderFactory().createObjectBuilder()
+                             .add( "key", doSerialize( options, key, false ) )
+                             .add( "value", doSerialize( options, value, false ) )
+                             .build() ) );
+            return builder.build();
+        }
+    }
+
+    private JsonValue serializeArray( Options options, Object object )
+    {
+        ArrayType valueType = ArrayType.of( object.getClass() );
+        if( valueType.isArrayOfPrimitiveBytes() )
+        {
+            byte[] base64 = Base64.getEncoder().encode( (byte[]) object );
+            return jsonFactories.toJsonString( new String( base64, UTF_8 ) );
+        }
+        if( valueType.isArrayOfPrimitives() )
+        {
+            return serializeIterable( options, new ArrayIterable( object ) );
+        }
+        return serializeStream( options, Stream.of( (Object[]) object ) );
+    }
+
+    private JsonArray serializeIterable( Options options, Iterable<?> iterable )
+    {
+        return serializeStream( options, StreamSupport.stream( iterable.spliterator(), false ) );
+    }
+
+    private <T> JsonArray serializeStream( Options options, Stream<?> stream )
+    {
+        JsonArrayBuilder builder = jsonFactories.builderFactory().createArrayBuilder();
+        stream.forEach( element -> builder.add( doSerialize( options, element, false ) ) );
+        return builder.build();
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSettings.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSettings.java
new file mode 100644
index 0000000..e19392e
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSettings.java
@@ -0,0 +1,113 @@
+/*
+ *  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.polygene.serialization.javaxjson;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.spi.serialization.SerializationSettings;
+
+public class JavaxJsonSettings extends SerializationSettings<JavaxJsonSettings>
+{
+    public static final JavaxJsonSettings DEFAULT = new JavaxJsonSettings();
+
+    public static JavaxJsonSettings orDefault( JavaxJsonSettings settings )
+    {
+        return settings != null ? settings : DEFAULT;
+    }
+
+    private String jsonProviderClassName;
+    private Map<String, Object> jsonParserProperties;
+    private Map<String, Object> jsonGeneratorProperties;
+    private String typeInfoPropertyName;
+    private Map<ValueType, JavaxJsonAdapter<?>> adapters;
+
+    public JavaxJsonSettings()
+    {
+        jsonParserProperties = new HashMap<String, Object>()
+        {{
+            put( "org.apache.johnzon.supports-comments", true );
+        }};
+        jsonGeneratorProperties = new HashMap<>();
+        typeInfoPropertyName = "_type";
+        adapters = new LinkedHashMap<>();
+    }
+
+    public String getJsonProviderClassName()
+    {
+        return jsonProviderClassName;
+    }
+
+    public void setJsonProviderClassName( String jsonProviderClassName )
+    {
+        this.jsonProviderClassName = jsonProviderClassName;
+    }
+
+    public Map<String, Object> getJsonParserProperties()
+    {
+        return jsonParserProperties;
+    }
+
+    public void setJsonParserProperties( Map<String, Object> jsonParserProperties )
+    {
+        this.jsonParserProperties = jsonParserProperties;
+    }
+
+    public Map<String, Object> getJsonGeneratorProperties()
+    {
+        return jsonGeneratorProperties;
+    }
+
+    public void setJsonGeneratorProperties( Map<String, Object> jsonGeneratorProperties )
+    {
+        this.jsonGeneratorProperties = jsonGeneratorProperties;
+    }
+
+    public String getTypeInfoPropertyName()
+    {
+        return typeInfoPropertyName;
+    }
+
+    public void setTypeInfoPropertyName( String typeInfoPropertyName )
+    {
+        this.typeInfoPropertyName = typeInfoPropertyName;
+    }
+
+    public Map<ValueType, JavaxJsonAdapter<?>> getAdapters()
+    {
+        return adapters;
+    }
+
+    public JavaxJsonSettings withTypeInfoPropertyName( String typeInfoPropertyName )
+    {
+        this.typeInfoPropertyName = typeInfoPropertyName;
+        return this;
+    }
+
+    public JavaxJsonSettings withJsonAdapter( ValueType valueType, JavaxJsonAdapter<?> adapter )
+    {
+        adapters.put( valueType, adapter );
+        return this;
+    }
+
+    public JavaxJsonSettings withJsonAdapter( JavaxJsonAdapter<?> adapter )
+    {
+        return withJsonAdapter( ValueType.of( adapter.type() ), adapter );
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/package.html b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/package.html
new file mode 100644
index 0000000..43db1d9
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>javax.json Serialization.</h2>
+    </body>
+</html>
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/PolygeneSPI.java b/core/spi/src/main/java/org/apache/polygene/spi/PolygeneSPI.java
new file mode 100644
index 0000000..b8571aa
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/PolygeneSPI.java
@@ -0,0 +1,75 @@
+/*
+ *  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.polygene.spi;
+
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * Encapsulation of the Polygene SPI. This is implemented by the runtime.
+ */
+public interface PolygeneSPI
+    extends PolygeneAPI
+{
+    StateHolder stateOf( TransientComposite composite );
+
+    AssociationStateHolder stateOf( EntityComposite composite );
+
+    AssociationStateHolder stateOf( ValueComposite composite );
+
+    // Entities
+    EntityState entityStateOf( EntityComposite composite );
+
+    /**
+     * Fetches the EntityReference without loading the referenced entity.
+     *
+     * @param assoc The Association for which we want to obtain the EntityReference
+     * @return The EntityReference of the given Association.
+     */
+    EntityReference entityReferenceOf( Association<?> assoc );
+
+    /**
+     * Fetches the EntityReferences without loading the referenced entities.
+     *
+     * @param assoc The ManyAssociation for which we want to obtain the EntityReferences.
+     * @return A stream of all the EntityReferences of the given ManyAssociation.
+     */
+    Stream<EntityReference> entityReferencesOf( ManyAssociation<?> assoc );
+
+    /**
+     * Fetches the EntityReferences without loading the referenced entities.
+     *
+     * @param assoc The NamedAssociation for which we want to obtain the EntityReference
+     * @return A stream of Map.Entry with the names and EntityReferences of the given NamedAssociation.
+     */
+    Stream<Map.Entry<String, EntityReference>> entityReferencesOf( NamedAssociation<?> assoc );
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/cache/Cache.java b/core/spi/src/main/java/org/apache/polygene/spi/cache/Cache.java
new file mode 100644
index 0000000..0e6c60a
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/cache/Cache.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.spi.cache;
+
+/**
+ * Interface to interact with Cache implementations.
+ * The Cache interface has the simple put/get/remove method to make implementations very easy and straight forward.
+ * The key is always a String, since it is intended to be used for the EntityComposite's reference, and not totally
+ * generic.
+ *
+ * @param <T> The Value type to be stored in the cache.
+ */
+public interface Cache<T>
+{
+    T get( String key );
+
+    T remove( String key );
+
+    void put( String key, T value );
+
+    boolean exists( String key );
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/cache/CachePool.java b/core/spi/src/main/java/org/apache/polygene/spi/cache/CachePool.java
new file mode 100644
index 0000000..b29b2bf
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/cache/CachePool.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.spi.cache;
+
+/**
+ * A CachePool is a service that manages the Persistence Caches.
+ * <p>
+ * The CachePool is typically implemented as a Polygene Extension, and is an optional extension in the persistence
+ * subsystem of Polygene. If a Cache Extension is not provided, caching will be turned off. However, since caching
+ * operate on EntityStore level, and is an optional component at that, just because you have defined a Cache
+ * Extension does not necessary mean that your system will use it. Check the EntityStore implementations for
+ * details if they are Cache enabled. Most EntityStore implementations has this enabled, often via the MapEntityStore
+ * and JSONMapEntityStore SPI.
+ * </p>
+ * <p>
+ * NOTE: Make sure that there is a match between the fetchCache and returnCache methods, to ensure no memory leakage
+ * occur. Also remember that if the reference count reaches zero, the CachePool will destroy the Cache as soon
+ * as possible and a new fetchCache will return an empty one.
+ * </p>
+ */
+public interface CachePool
+{
+
+    /**
+     * Fetches a cache from the pool.
+     * If the cache does not exist already, then a new Cache should be created and returned. For each fetchCache()
+     * call, a reference count on the Cache must be increased.
+     *
+     * @param cacheId   The reference of the cache. If the same id is given as a previous fetch, the same cache will be
+     *                  returned.
+     * @param valueType Value type
+     * @param <T>       Value type
+     *
+     * @return The cache fetched from the pool.
+     */
+    <T> Cache<T> fetchCache( String cacheId, Class<T> valueType );
+
+    /**
+     * Returns the cache back to the pool.
+     * The reference count for the cache must then be decreased and if the count reaches zero, the Cache should be
+     * destroyed and cleared from memory.
+     *
+     * @param cache The cache to return to the pool.
+     */
+    void returnCache( Cache<?> cache );
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/cache/NullCache.java b/core/spi/src/main/java/org/apache/polygene/spi/cache/NullCache.java
new file mode 100644
index 0000000..a0bc626
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/cache/NullCache.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.spi.cache;
+
+/**
+ * Cache null object.
+ */
+public final class NullCache<T>
+    implements Cache<T>
+{
+    @Override
+    public T get( String key )
+    {
+        return null;
+    }
+
+    @Override
+    public T remove( String key )
+    {
+        return null;
+    }
+
+    @Override
+    public void put( String key, T value )
+    {
+    }
+
+    @Override
+    public boolean exists( String key )
+    {
+        return false;
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/cache/package.html b/core/spi/src/main/java/org/apache/polygene/spi/cache/package.html
new file mode 100644
index 0000000..9494703
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/cache/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Cache SPI.</h2>
+    </body>
+</html>
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entity/EntityState.java b/core/spi/src/main/java/org/apache/polygene/spi/entity/EntityState.java
new file mode 100644
index 0000000..a7d6bdb
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entity/EntityState.java
@@ -0,0 +1,87 @@
+/*
+ *  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.polygene.spi.entity;
+
+import java.time.Instant;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.time.SystemTime;
+
+/**
+ * State holder for Entities.
+ */
+public interface EntityState
+{
+    /**
+     * Returns the reference of the entity that this EntityState represents.
+     *
+     * @return the reference of the entity that this EntityState represents.
+     */
+    EntityReference entityReference();
+
+    /**
+     * Version of the entity. This is managed by the EntityStore.
+     * <p>
+     * If the underlying EntityStore does not support versioning, then version
+     * must always be set to 0.
+     * </p>
+     * @return version of the entity
+     */
+    String version();
+
+    /**
+     * Last modified timestamp of the entity. This is managed by the EntityStore.
+     * <p>
+     * If the underlying EntityStore does not support timestamping, then last modified
+     * must always be set to the current time.
+     * </p>
+     * @return last modified timestamp of the entity, as defined by {@link SystemTime#now()}
+     */
+    Instant lastModified();
+
+    /**
+     * Remove the entity represented by this EntityState when the unit of work is completed.
+     */
+    void remove();
+
+    /**
+     * The status of this EntityState
+     *
+     * @return the status
+     */
+    EntityStatus status();
+
+    boolean isAssignableTo( Class<?> type );
+
+    EntityDescriptor entityDescriptor();
+
+    Object propertyValueOf( QualifiedName stateName );
+
+    void setPropertyValue( QualifiedName stateName, Object json );
+
+    EntityReference associationValueOf( QualifiedName stateName );
+
+    void setAssociationValue( QualifiedName stateName, EntityReference newEntity );
+
+    ManyAssociationState manyAssociationValueOf( QualifiedName stateName );
+    
+    NamedAssociationState namedAssociationValueOf( QualifiedName stateName );
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entity/EntityStatus.java b/core/spi/src/main/java/org/apache/polygene/spi/entity/EntityStatus.java
new file mode 100644
index 0000000..7731e40
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entity/EntityStatus.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.spi.entity;
+
+/**
+ * Status of entity. This is used in the default implementation
+ * of EntityState
+ */
+public enum EntityStatus
+{
+    NEW, // When the Entity has just been created in the UnitOfWork 
+    LOADED,  // When it has been previously created, and is loaded through the UnitOfWork
+    UPDATED, // When it has been previously loaded, and has been changed in the UnitOfWork
+    REMOVED // When the Entity has been removed in the UnitOfWork
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entity/ManyAssociationState.java b/core/spi/src/main/java/org/apache/polygene/spi/entity/ManyAssociationState.java
new file mode 100644
index 0000000..5f3b32a
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entity/ManyAssociationState.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.spi.entity;
+
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.entity.EntityReference;
+
+/**
+ * State holder for ManyAssociations. The actual state
+ * can be eager-loaded or lazy-loaded. This is an implementation detail.
+ */
+public interface ManyAssociationState
+    extends Iterable<EntityReference>
+{
+    int count();
+
+    boolean contains( EntityReference entityReference );
+
+    boolean add( int index, EntityReference entityReference );
+
+    boolean remove( EntityReference entityReference );
+
+    boolean clear();
+
+    EntityReference get( int index );
+
+    default Stream<EntityReference> stream() {
+        return StreamSupport.stream( spliterator(), false );
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entity/NamedAssociationState.java b/core/spi/src/main/java/org/apache/polygene/spi/entity/NamedAssociationState.java
new file mode 100644
index 0000000..c2a6030
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entity/NamedAssociationState.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.spi.entity;
+
+import java.util.AbstractMap;
+import java.util.Map;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.entity.EntityReference;
+
+/**
+ * State holder for NamedAssociations.
+ * The actual state can be eager-loaded or lazy-loaded.
+ * This is an implementation detail.
+ * The Iterable&lt;String&gt; returns the names in the association set.
+ */
+public interface NamedAssociationState
+    extends Iterable<String>
+{
+    int count();
+
+    boolean containsName( String name );
+
+    boolean put( String name, EntityReference entityReference );
+
+    boolean remove( String name );
+
+    boolean clear();
+
+    EntityReference get( String name );
+
+    String nameOf( EntityReference entityReference );
+
+    default Stream<Map.Entry<String, EntityReference>> stream()
+    {
+        return StreamSupport.stream( spliterator(), false )
+                            .map( name -> new AbstractMap.SimpleImmutableEntry<>( name, get( name ) ) );
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entity/package.html b/core/spi/src/main/java/org/apache/polygene/spi/entity/package.html
new file mode 100644
index 0000000..7f3bcb3
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entity/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Entity SPI.</h2>
+    </body>
+</html>
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/BackupRestore.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/BackupRestore.java
new file mode 100644
index 0000000..9676c3e
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/BackupRestore.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.spi.entitystore;
+
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
+/**
+ * Allow backups and restores of data in an EntityStore to be made
+ */
+public interface BackupRestore
+{
+    /**
+     * Backup entity states.
+     *
+     * @return Stream of serialized entity states, must be closed
+     */
+    Stream<String> backup();
+
+    /**
+     * Restore entity states.
+     *
+     * @param states Stream of serialized entity states
+     */
+    void restore( Stream<String> states );
+
+    /**
+     * Restore entity states.
+     *
+     * @return A consumer of streams of serialized entity states
+     */
+    default Consumer<Stream<String>> restore()
+    {
+        return this::restore;
+    }
+}
\ No newline at end of file
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/ConcurrentEntityStateModificationException.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/ConcurrentEntityStateModificationException.java
new file mode 100644
index 0000000..f6bbfe8
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/ConcurrentEntityStateModificationException.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.spi.entitystore;
+
+import java.util.Collection;
+import org.apache.polygene.api.entity.EntityReference;
+
+/**
+ * This exception should be thrown if the EntityStore detects that the entities being saved have been changed
+ * since they were created.
+ */
+public class ConcurrentEntityStateModificationException
+    extends EntityStoreException
+{
+    private Collection<EntityReference> modifiedEntities;
+
+    public ConcurrentEntityStateModificationException( Collection<EntityReference> modifiedEntities )
+    {
+        super();
+        this.modifiedEntities = modifiedEntities;
+    }
+
+    public Collection<EntityReference> modifiedEntities()
+    {
+        return modifiedEntities;
+    }
+
+    @Override
+    public String getMessage()
+    {
+        return "Entities changed concurrently.\nModified entities are;\n" + modifiedEntities;
+    }
+}
\ No newline at end of file
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/ConcurrentModificationCheckConcern.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/ConcurrentModificationCheckConcern.java
new file mode 100644
index 0000000..a76b033
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/ConcurrentModificationCheckConcern.java
@@ -0,0 +1,208 @@
+/*
+ *  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.polygene.spi.entitystore;
+
+import java.time.Instant;
+import java.util.HashSet;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * Concern that helps EntityStores do concurrent modification checks.
+ * <p>
+ * It caches the versions of state that it loads, and forgets them when
+ * the state is committed. For normal operation this means that it does
+ * not have to go down to the underlying store to get the current version.
+ * Whenever there is a concurrent modification the store will most likely
+ * have to check with the underlying store what the current version is.
+ * </p>
+ */
+public abstract class ConcurrentModificationCheckConcern
+    extends ConcernOf<EntityStore>
+    implements EntityStore
+{
+    @This
+    private EntityStateVersions versions;
+
+    @Structure
+    private PolygeneAPI api;
+
+    @Override
+    public EntityStoreUnitOfWork newUnitOfWork( ModuleDescriptor module, Usecase usecase, Instant currentTime )
+    {
+        final EntityStoreUnitOfWork uow = next.newUnitOfWork( module, usecase, currentTime );
+        return new ConcurrentCheckingEntityStoreUnitOfWork( uow, api.dereference( versions ), currentTime );
+    }
+
+    private static class ConcurrentCheckingEntityStoreUnitOfWork
+        implements EntityStoreUnitOfWork
+    {
+        private final EntityStoreUnitOfWork uow;
+        private EntityStateVersions versions;
+        private Instant currentTime;
+
+        private HashSet<EntityState> loaded = new HashSet<>();
+
+        private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+
+        public ConcurrentCheckingEntityStoreUnitOfWork( EntityStoreUnitOfWork uow,
+                                                        EntityStateVersions versions,
+                                                        Instant currentTime
+        )
+        {
+            this.uow = uow;
+            this.versions = versions;
+            this.currentTime = currentTime;
+        }
+
+        @Override
+        public Identity identity()
+        {
+            return uow.identity();
+        }
+
+        @Override
+        public Instant currentTime()
+        {
+            return uow.currentTime();
+        }
+
+        @Override
+        public EntityState newEntityState( EntityReference anIdentity,
+                                           EntityDescriptor entityDescriptor
+        )
+            throws EntityStoreException
+        {
+            return uow.newEntityState( anIdentity, entityDescriptor );
+        }
+
+        @Override
+        public StateCommitter applyChanges()
+            throws EntityStoreException
+        {
+            lock.writeLock().lock();
+
+            try
+            {
+                versions.checkForConcurrentModification( loaded, currentTime );
+
+                final StateCommitter committer = uow.applyChanges();
+
+                return new StateCommitter()
+                {
+                    @Override
+                    public void commit()
+                    {
+                        committer.commit();
+                        versions.forgetVersions( loaded );
+
+                        lock.writeLock().unlock();
+                    }
+
+                    @Override
+                    public void cancel()
+                    {
+                        committer.cancel();
+                        versions.forgetVersions( loaded );
+
+                        lock.writeLock().unlock();
+                    }
+                };
+            }
+            catch( EntityStoreException e )
+            {
+                lock.writeLock().unlock();
+                throw e;
+            }
+        }
+
+        @Override
+        public void discard()
+        {
+            try
+            {
+                uow.discard();
+            }
+            finally
+            {
+                lock.writeLock().lock();
+
+                try
+                {
+                    versions.forgetVersions( loaded );
+                }
+                finally
+                {
+                    lock.writeLock().unlock();
+                }
+            }
+        }
+
+        @Override
+        public Usecase usecase()
+        {
+            return uow.usecase();
+        }
+
+        @Override
+        public ModuleDescriptor module()
+        {
+            return uow.module();
+        }
+
+        @SuppressWarnings( "DuplicateThrows" )
+        @Override
+        public EntityState entityStateOf( ModuleDescriptor module, EntityReference anIdentity )
+            throws EntityStoreException, EntityNotFoundException
+        {
+            lock.readLock().lock();
+
+            try
+            {
+                EntityState entityState = uow.entityStateOf( module, anIdentity );
+                versions.rememberVersion( entityState.entityReference(), entityState.version() );
+                loaded.add( entityState );
+                return entityState;
+            }
+            finally
+            {
+                lock.readLock().unlock();
+            }
+        }
+
+
+        @Override
+        public String versionOf( EntityReference anIdentity )
+            throws EntityStoreException
+        {
+            return uow.versionOf( anIdentity );
+        }
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/DefaultEntityStoreUnitOfWork.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/DefaultEntityStoreUnitOfWork.java
new file mode 100644
index 0000000..5df3330
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/DefaultEntityStoreUnitOfWork.java
@@ -0,0 +1,134 @@
+/*
+ *  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.polygene.spi.entitystore;
+
+import java.time.Instant;
+import java.util.HashMap;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * Default EntityStore UnitOfWork.
+ */
+public final class DefaultEntityStoreUnitOfWork
+    implements EntityStoreUnitOfWork
+{
+    private final ModuleDescriptor module;
+    private EntityStoreSPI entityStoreSPI;
+    private Identity identity;
+    private HashMap<EntityReference, EntityState> states = new HashMap<>();
+    private Usecase usecase;
+    private Instant currentTime;
+
+    public DefaultEntityStoreUnitOfWork( ModuleDescriptor module,
+                                         EntityStoreSPI entityStoreSPI,
+                                         Identity identity,
+                                         Usecase usecase,
+                                         Instant currentTime
+    )
+    {
+        this.module = module;
+        this.entityStoreSPI = entityStoreSPI;
+        this.identity = identity;
+        this.usecase = usecase;
+        this.currentTime = currentTime;
+    }
+
+    @Override
+    public Identity identity()
+    {
+        return identity;
+    }
+
+    @Override
+    public Instant currentTime()
+    {
+        return currentTime;
+    }
+
+    public Usecase usecase()
+    {
+        return usecase;
+    }
+
+    @Override
+    public ModuleDescriptor module()
+    {
+        return module;
+    }
+// EntityStore
+
+    @Override
+    public EntityState newEntityState( EntityReference anIdentity, EntityDescriptor descriptor )
+        throws EntityStoreException
+    {
+        EntityState entityState = states.get( anIdentity );
+        if( entityState != null )
+        {
+            throw new EntityAlreadyExistsException( anIdentity );
+        }
+        EntityState state = entityStoreSPI.newEntityState( this, anIdentity, descriptor );
+        states.put( anIdentity, state );
+        return state;
+    }
+
+    @Override
+    public EntityState entityStateOf( ModuleDescriptor module, EntityReference anIdentity )
+        throws EntityNotFoundException
+    {
+        EntityState entityState = states.get( anIdentity );
+        if( entityState != null )
+        {
+            return entityState;
+        }
+        entityState = entityStoreSPI.entityStateOf( this, module, anIdentity );
+        states.put( anIdentity, entityState );
+        return entityState;
+    }
+
+    @Override
+    public String versionOf( EntityReference anIdentity )
+        throws EntityNotFoundException
+    {
+        EntityState entityState = states.get( anIdentity );
+        if( entityState != null )
+        {
+            return entityState.version();
+        }
+        return entityStoreSPI.versionOf( this, anIdentity );
+    }
+
+    @Override
+    public StateCommitter applyChanges()
+        throws EntityStoreException
+    {
+        return entityStoreSPI.applyChanges( this, states.values() );
+    }
+
+    @Override
+    public void discard()
+    {
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityAlreadyExistsException.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityAlreadyExistsException.java
new file mode 100644
index 0000000..26c9c3e
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityAlreadyExistsException.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.spi.entitystore;
+
+import org.apache.polygene.api.entity.EntityReference;
+
+/**
+ * This exception is thrown when an Entity already exists.
+ */
+public class EntityAlreadyExistsException
+    extends EntityStoreException
+{
+    private EntityReference reference;
+
+    public EntityAlreadyExistsException( EntityReference reference)
+    {
+        super("Entity " + reference + " already exists.");
+        this.reference = reference;
+    }
+
+    public EntityReference reference()
+    {
+        return reference;
+    }
+
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityNotFoundException.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityNotFoundException.java
new file mode 100644
index 0000000..a3958f6
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityNotFoundException.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.spi.entitystore;
+
+import org.apache.polygene.api.entity.EntityReference;
+
+/**
+ * This exception is thrown when an Entity could not be found.
+ */
+public class EntityNotFoundException
+    extends EntityStoreException
+{
+    private EntityReference reference;
+
+    public EntityNotFoundException( EntityReference reference)
+    {
+        super("Entity " + reference + " not found");
+        this.reference = reference;
+    }
+
+    public EntityReference reference()
+    {
+        return reference;
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityStateVersions.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityStateVersions.java
new file mode 100644
index 0000000..a752a2d
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityStateVersions.java
@@ -0,0 +1,112 @@
+/*
+ *  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.polygene.spi.entitystore;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.EntityStatus;
+
+/**
+ * Entity versions state.
+ */
+@Mixins( EntityStateVersions.EntityStateVersionsMixin.class )
+public interface EntityStateVersions
+{
+    void forgetVersions( Iterable<EntityState> states );
+
+    void rememberVersion( EntityReference reference, String version );
+
+    void checkForConcurrentModification( Iterable<EntityState> loaded, Instant currentTime )
+        throws ConcurrentEntityStateModificationException;
+
+    /**
+     * Entity versions state mixin.
+     */
+    class EntityStateVersionsMixin
+        implements EntityStateVersions
+    {
+        @This
+        private EntityStore store;
+
+        private final Map<EntityReference, String> versions = new WeakHashMap<>();
+
+        @Override
+        public synchronized void forgetVersions( Iterable<EntityState> states )
+        {
+            for( EntityState state : states )
+            {
+                versions.remove( state.entityReference() );
+            }
+        }
+
+        @Override
+        public synchronized void rememberVersion( EntityReference reference, String version )
+        {
+            versions.put( reference, version );
+        }
+
+        @Override
+        public synchronized void checkForConcurrentModification( Iterable<EntityState> loaded,
+                                                                 Instant currentTime
+        )
+            throws ConcurrentEntityStateModificationException
+        {
+            List<EntityReference> changed = null;
+            for( EntityState entityState : loaded )
+            {
+                if( entityState.status().equals( EntityStatus.NEW ) )
+                {
+                    continue;
+                }
+
+                String storeVersion = versions.get( entityState.entityReference() );
+                if( storeVersion == null )
+                {
+                    EntityStoreUnitOfWork unitOfWork = store.newUnitOfWork( entityState.entityDescriptor().module(), Usecase.DEFAULT, currentTime );
+                    storeVersion = unitOfWork.versionOf( entityState.entityReference() );
+                    unitOfWork.discard();
+                }
+
+                if( !entityState.version().equals( storeVersion ) )
+                {
+                    if( changed == null )
+                    {
+                        changed = new ArrayList<>();
+                    }
+                    changed.add( entityState.entityReference() );
+                }
+            }
+
+            if( changed != null )
+            {
+                throw new ConcurrentEntityStateModificationException( changed );
+            }
+        }
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityStore.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityStore.java
new file mode 100644
index 0000000..b8ee5a4
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityStore.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.spi.entitystore;
+
+import java.time.Instant;
+import java.util.stream.Stream;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * Interface that must be implemented by store for persistent state of EntityComposites.
+ */
+public interface EntityStore
+{
+    EntityStoreUnitOfWork newUnitOfWork( ModuleDescriptor module, Usecase usecase, Instant currentTime );
+
+    /**
+     * Stream of all entity states, must be closed.
+     *
+     * @param module Module
+     * @return Stream of all entity states, must be closed
+     */
+    Stream<EntityState> entityStates( ModuleDescriptor module );
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityStoreException.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityStoreException.java
new file mode 100644
index 0000000..22705c8
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityStoreException.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.spi.entitystore;
+
+/**
+ * Base EntityStore Exception.
+ */
+public class EntityStoreException
+    extends RuntimeException
+{
+    public EntityStoreException()
+    {
+    }
+
+    public EntityStoreException( String message )
+    {
+        super( message );
+    }
+
+    public EntityStoreException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+
+    public EntityStoreException( Throwable cause )
+    {
+        super( cause );
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityStoreSPI.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityStoreSPI.java
new file mode 100644
index 0000000..65e9409
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityStoreSPI.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.spi.entitystore;
+
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * EntityStore SPI.
+ */
+public interface EntityStoreSPI
+{
+    EntityState newEntityState( EntityStoreUnitOfWork unitOfWork,
+                                EntityReference reference, EntityDescriptor entityDescriptor
+    );
+
+    EntityState entityStateOf( EntityStoreUnitOfWork unitOfWork, ModuleDescriptor module, EntityReference reference );
+
+    String versionOf( EntityStoreUnitOfWork unitOfWork, EntityReference reference );
+
+    StateCommitter applyChanges( EntityStoreUnitOfWork unitOfWork, Iterable<EntityState> state );
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityStoreUnitOfWork.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityStoreUnitOfWork.java
new file mode 100644
index 0000000..8c0b7c5
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/EntityStoreUnitOfWork.java
@@ -0,0 +1,82 @@
+/*
+ *  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.polygene.spi.entitystore;
+
+import java.time.Instant;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * EntityStore UnitOfWork.
+ */
+public interface EntityStoreUnitOfWork
+{
+    Identity identity();
+
+    Instant currentTime();
+
+    /**
+     * Create new EntityState for a given reference.
+     * <p>
+     * This should only create the EntityState and not insert it into any database, since that should occur during
+     * the {@link EntityStoreUnitOfWork#applyChanges()} call.
+     * </p>
+     * @param anIdentity       the reference of the entity
+     * @param entityDescriptor entity descriptor
+     *
+     * @return The new entity state.
+     *
+     * @throws EntityStoreException Thrown if creational fails.
+     */
+    EntityState newEntityState( EntityReference anIdentity, EntityDescriptor entityDescriptor )
+        throws EntityStoreException;
+
+    /**
+     * Get the EntityState for a given reference. Throws {@link EntityNotFoundException}
+     * if the entity with given {@code anIdentity} is not found.
+     *
+     *
+     * @param module Module descriptor
+     * @param anIdentity The entity reference. This argument must not be {@code null}.
+     *
+     * @return Entity state given the composite descriptor and reference.
+     *
+     * @throws EntityStoreException    thrown if retrieval failed.
+     * @throws EntityNotFoundException if requested entity does not exist
+     */
+    EntityState entityStateOf( ModuleDescriptor module, EntityReference anIdentity )
+        throws EntityStoreException, EntityNotFoundException;
+
+    String versionOf( EntityReference anIdentity ) throws EntityStoreException;
+
+    StateCommitter applyChanges()
+        throws EntityStoreException;
+
+    void discard();
+
+    Usecase usecase();
+
+    ModuleDescriptor module();
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/StateChangeListener.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/StateChangeListener.java
new file mode 100644
index 0000000..d4d5ff6
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/StateChangeListener.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.spi.entitystore;
+
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * Implement this interface in a Service if you want it to listen
+ * to changes from EntityStores.
+ */
+public interface StateChangeListener
+{
+    void notifyChanges( Iterable<EntityState> changedStates );
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/StateChangeNotificationConcern.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/StateChangeNotificationConcern.java
new file mode 100644
index 0000000..dd878d7
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/StateChangeNotificationConcern.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.spi.entitystore;
+
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * State change notification Concern.
+ */
+public abstract class StateChangeNotificationConcern
+    extends ConcernOf<EntityStoreSPI>
+    implements EntityStoreSPI
+{
+    @Service
+    Iterable<StateChangeListener> listeners;
+
+    @Override
+    public StateCommitter applyChanges( final EntityStoreUnitOfWork unitofwork,
+                                        final Iterable<EntityState> state
+    )
+    {
+        final StateCommitter committer = next.applyChanges( unitofwork, state );
+        return new StateCommitter()
+        {
+            @Override
+            public void commit()
+            {
+                for( StateChangeListener listener : listeners )
+                {
+                    listener.notifyChanges( state );
+                }
+                committer.commit();
+            }
+
+            @Override
+            public void cancel()
+            {
+                committer.cancel();
+            }
+        };
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/StateCommitter.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/StateCommitter.java
new file mode 100644
index 0000000..3850651
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/StateCommitter.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.spi.entitystore;
+
+/**
+ * After all EntityStore's have been prepared by {@link org.apache.polygene.api.unitofwork.UnitOfWork#complete()}
+ */
+public interface StateCommitter
+{
+    void commit();
+
+    void cancel();
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/DefaultEntityState.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/DefaultEntityState.java
new file mode 100644
index 0000000..2926b8c
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/DefaultEntityState.java
@@ -0,0 +1,250 @@
+/*
+ *  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.polygene.spi.entitystore.helpers;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.entity.ManyAssociationState;
+import org.apache.polygene.spi.entity.NamedAssociationState;
+
+/**
+ * Standard implementation of EntityState.
+ */
+public final class DefaultEntityState
+    implements EntityState
+{
+    private EntityStatus status;
+
+    private String version;
+    private Instant lastModified;
+    private final EntityReference reference;
+    private final EntityDescriptor entityDescriptor;
+
+    private final Map<QualifiedName, Object> properties;
+    private final Map<QualifiedName, EntityReference> associations;
+    private final Map<QualifiedName, List<EntityReference>> manyAssociations;
+    private final Map<QualifiedName, Map<String, EntityReference>> namedAssociations;
+
+    public DefaultEntityState( Instant currentTime,
+                               EntityReference reference,
+                               EntityDescriptor entityDescriptor
+    )
+    {
+        this( "",
+              currentTime,
+              reference,
+              EntityStatus.NEW,
+              entityDescriptor,
+              new HashMap<>(),
+              new HashMap<>(),
+              new HashMap<>(),
+              new HashMap<>() );
+    }
+
+    public DefaultEntityState( String version,
+                               Instant lastModified,
+                               EntityReference reference,
+                               EntityStatus status,
+                               EntityDescriptor entityDescriptor,
+                               Map<QualifiedName, Object> properties,
+                               Map<QualifiedName, EntityReference> associations,
+                               Map<QualifiedName, List<EntityReference>> manyAssociations,
+                               Map<QualifiedName, Map<String, EntityReference>> namedAssociations
+    )
+    {
+        this.version = version;
+        this.lastModified = lastModified;
+        this.reference = reference;
+        this.status = status;
+        this.entityDescriptor = entityDescriptor;
+        this.properties = properties;
+        this.associations = associations;
+        this.manyAssociations = manyAssociations;
+        this.namedAssociations = namedAssociations;
+    }
+
+    // EntityState implementation
+    @Override
+    public final String version()
+    {
+        return version;
+    }
+
+    @Override
+    public Instant lastModified()
+    {
+        return lastModified;
+    }
+
+    @Override
+    public EntityReference entityReference()
+    {
+        return reference;
+    }
+
+    @Override
+    public Object propertyValueOf( QualifiedName stateName )
+    {
+        return properties.get( stateName );
+    }
+
+    @Override
+    public void setPropertyValue( QualifiedName stateName, Object newValue )
+    {
+        properties.put( stateName, newValue );
+        markUpdated();
+    }
+
+    @Override
+    public EntityReference associationValueOf( QualifiedName stateName )
+    {
+        return associations.get( stateName );
+    }
+
+    @Override
+    public void setAssociationValue( QualifiedName stateName, EntityReference newEntity )
+    {
+        associations.put( stateName, newEntity );
+        markUpdated();
+    }
+
+    @Override
+    public ManyAssociationState manyAssociationValueOf( QualifiedName stateName )
+    {
+        List<EntityReference> manyAssociationState = manyAssociations.computeIfAbsent(
+            stateName, key -> new ArrayList<>() );
+        return new DefaultManyAssociationState( this, manyAssociationState );
+    }
+
+    @Override
+    public NamedAssociationState namedAssociationValueOf( QualifiedName stateName )
+    {
+        Map<String, EntityReference> namedAssociationState = namedAssociations.computeIfAbsent(
+            stateName, key -> new LinkedHashMap<>() );
+        return new DefaultNamedAssociationState( this, namedAssociationState );
+    }
+
+    public void copyTo( DefaultEntityState entityState )
+    {
+        // Copy properties
+        entityState.properties.clear();
+        for( Map.Entry<QualifiedName, Object> stateNameStringEntry : properties.entrySet() )
+        {
+            entityState.properties.put( stateNameStringEntry.getKey(), stateNameStringEntry.getValue() );
+        }
+
+        // Copy associations
+        entityState.associations.clear();
+        for( Map.Entry<QualifiedName, EntityReference> stateNameStringEntry : associations.entrySet() )
+        {
+            entityState.associations.put( stateNameStringEntry.getKey(), stateNameStringEntry.getValue() );
+        }
+
+        // Copy many-associations
+        entityState.manyAssociations.clear();
+        for( Map.Entry<QualifiedName, List<EntityReference>> stateNameStringEntry : manyAssociations.entrySet() )
+        {
+            entityState.manyAssociations.put( stateNameStringEntry.getKey(), stateNameStringEntry.getValue() );
+        }
+
+        // Copy named-associations
+        entityState.namedAssociations.clear();
+        for( Map.Entry<QualifiedName, Map<String, EntityReference>> entry : namedAssociations.entrySet() )
+        {
+            entityState.namedAssociations.put( entry.getKey(), entry.getValue() );
+        }
+
+        // Set version and timestamp
+        entityState.version = version;
+        entityState.lastModified = lastModified;
+    }
+
+    @Override
+    public void remove()
+    {
+        status = EntityStatus.REMOVED;
+    }
+
+    @Override
+    public EntityStatus status()
+    {
+        return status;
+    }
+
+    @Override
+    public boolean isAssignableTo( Class<?> type )
+    {
+        return Classes.exactTypeSpecification( type ).test( entityDescriptor );
+    }
+
+    @Override
+    public EntityDescriptor entityDescriptor()
+    {
+        return entityDescriptor;
+    }
+
+    public Map<QualifiedName, Object> properties()
+    {
+        return properties;
+    }
+
+    public Map<QualifiedName, EntityReference> associations()
+    {
+        return associations;
+    }
+
+    public Map<QualifiedName, List<EntityReference>> manyAssociations()
+    {
+        return manyAssociations;
+    }
+
+    public Map<QualifiedName, Map<String, EntityReference>> namedAssociations()
+    {
+        return namedAssociations;
+    }
+
+    @Override
+    public String toString()
+    {
+        return reference + "("
+               + properties.size() + " properties, "
+               + associations.size() + " associations, "
+               + manyAssociations.size() + " many-associations, "
+               + namedAssociations.size() + " named-associations)";
+    }
+
+    public void markUpdated()
+    {
+        if( status == EntityStatus.LOADED )
+        {
+            status = EntityStatus.UPDATED;
+        }
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/DefaultManyAssociationState.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/DefaultManyAssociationState.java
new file mode 100644
index 0000000..9e95188
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/DefaultManyAssociationState.java
@@ -0,0 +1,127 @@
+/*
+ *  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.polygene.spi.entitystore.helpers;
+
+import java.util.Iterator;
+import java.util.List;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.spi.entity.ManyAssociationState;
+
+/**
+ * Default implementation of ManyAssociationState. Backed by ArrayList.
+ */
+public final class DefaultManyAssociationState
+    implements ManyAssociationState
+{
+    private DefaultEntityState entityState;
+    private List<EntityReference> references;
+
+    public DefaultManyAssociationState( DefaultEntityState entityState, List<EntityReference> references )
+    {
+        this.entityState = entityState;
+        this.references = references;
+    }
+
+    @Override
+    public int count()
+    {
+        return references.size();
+    }
+
+    @Override
+    public boolean contains( EntityReference entityReference )
+    {
+        return references.contains( entityReference );
+    }
+
+    @Override
+    public boolean add( int i, EntityReference entityReference )
+    {
+        if( references.contains( entityReference ) )
+        {
+            return false;
+        }
+
+        references.add( i, entityReference );
+        entityState.markUpdated();
+        return true;
+    }
+
+    @Override
+    public boolean remove( EntityReference entity )
+    {
+        boolean removed = references.remove( entity );
+        if( removed )
+        {
+            entityState.markUpdated();
+        }
+        return removed;
+    }
+
+    @Override
+    public boolean clear()
+    {
+        if( !references.isEmpty() )
+        {
+            references.clear();
+            entityState.markUpdated();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public EntityReference get( int i )
+    {
+        return references.get( i );
+    }
+
+    @Override
+    public Iterator<EntityReference> iterator()
+    {
+        final Iterator<EntityReference> iter = references.iterator();
+
+        return new Iterator<EntityReference>()
+        {
+            EntityReference current;
+
+            @Override
+            public boolean hasNext()
+            {
+                return iter.hasNext();
+            }
+
+            @Override
+            public EntityReference next()
+            {
+                current = iter.next();
+                return current;
+            }
+
+            @Override
+            public void remove()
+            {
+                iter.remove();
+                entityState.markUpdated();
+            }
+        };
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/DefaultNamedAssociationState.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/DefaultNamedAssociationState.java
new file mode 100644
index 0000000..94f30ca
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/DefaultNamedAssociationState.java
@@ -0,0 +1,137 @@
+/*
+ *  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.polygene.spi.entitystore.helpers;
+
+import java.util.Iterator;
+import java.util.Map;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.spi.entity.NamedAssociationState;
+
+/**
+ * Default implementation of NamedAssociationState.
+ * Backed by HashMap.
+ */
+public final class DefaultNamedAssociationState
+    implements NamedAssociationState
+{
+    private final DefaultEntityState entityState;
+    private final Map<String, EntityReference> references;
+
+    public DefaultNamedAssociationState( DefaultEntityState entityState, Map<String, EntityReference> references )
+    {
+        this.entityState = entityState;
+        this.references = references;
+    }
+
+    @Override
+    public int count()
+    {
+        return references.size();
+    }
+
+    @Override
+    public boolean containsName( String name )
+    {
+        return references.containsKey( name );
+    }
+
+    @Override
+    public boolean put( String name, EntityReference entityReference )
+    {
+        if( references.put( name, entityReference ) == null )
+        {
+            return false;
+        }
+        entityState.markUpdated();
+        return true;
+    }
+
+    @Override
+    public boolean remove( String name )
+    {
+        if( references.remove( name ) == null )
+        {
+            return false;
+        }
+        entityState.markUpdated();
+        return true;
+    }
+
+    @Override
+    public boolean clear()
+    {
+        if( !references.isEmpty() )
+        {
+            references.clear();
+            entityState.markUpdated();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public EntityReference get( String name )
+    {
+        return references.get( name );
+    }
+
+    @Override
+    public String nameOf( EntityReference entityReference )
+    {
+        for( Map.Entry<String, EntityReference> entry : references.entrySet() )
+        {
+            if( entry.getValue().equals( entityReference ) )
+            {
+                return entry.getKey();
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Iterator<String> iterator()
+    {
+        final Iterator<String> iter = references.keySet().iterator();
+        return new Iterator<String>()
+        {
+            private String current;
+
+            @Override
+            public boolean hasNext()
+            {
+                return iter.hasNext();
+            }
+
+            @Override
+            public String next()
+            {
+                current = iter.next();
+                return current;
+            }
+
+            @Override
+            public void remove()
+            {
+                iter.remove();
+                entityState.markUpdated();
+            }
+        };
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONEntityState.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONEntityState.java
new file mode 100644
index 0000000..7bb6c2e
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONEntityState.java
@@ -0,0 +1,368 @@
+/*
+ *  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.polygene.spi.entitystore.helpers;
+
+import java.time.Instant;
+import java.util.Objects;
+import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.entity.ManyAssociationState;
+import org.apache.polygene.spi.entity.NamedAssociationState;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+import org.apache.polygene.spi.serialization.JsonSerialization;
+
+import static org.apache.polygene.api.serialization.Serializer.Options.ALL_TYPE_INFO;
+
+/**
+ * Standard JSON implementation of EntityState.
+ */
+public final class JSONEntityState
+    implements EntityState
+{
+    private final ModuleDescriptor module;
+    private final String version;
+    private final EntityReference reference;
+    private final EntityDescriptor entityDescriptor;
+    private final JsonSerialization serialization;
+    private final JavaxJsonFactories jsonFactories;
+
+    private EntityStatus status;
+    private Instant lastModified;
+    private JsonObject state;
+
+    /* package */ JSONEntityState( ModuleDescriptor module,
+                                   JsonSerialization serialization,
+                                   JavaxJsonFactories jsonFactories,
+                                   String version,
+                                   Instant lastModified,
+                                   EntityReference reference,
+                                   EntityStatus status,
+                                   EntityDescriptor entityDescriptor,
+                                   JsonObject state
+    )
+    {
+        this.module = module;
+        this.serialization = serialization;
+        this.jsonFactories = jsonFactories;
+        this.version = version;
+        this.lastModified = lastModified;
+        this.reference = reference;
+        this.status = status;
+        this.entityDescriptor = entityDescriptor;
+        this.state = state;
+    }
+
+    // EntityState implementation
+    @Override
+    public final String version()
+    {
+        return version;
+    }
+
+    @Override
+    public Instant lastModified()
+    {
+        return lastModified;
+    }
+
+    @Override
+    public EntityReference entityReference()
+    {
+        return reference;
+    }
+
+    @Override
+    public Object propertyValueOf( QualifiedName stateName )
+    {
+        try
+        {
+            ValueType valueType = entityDescriptor.state().findPropertyModelByQualifiedName( stateName ).valueType();
+            JsonValue jsonValue = state.getJsonObject( JSONKeys.VALUE ).get( stateName.name() );
+            return serialization.fromJson( module, valueType, jsonValue );
+        }
+        catch( SerializationException e )
+        {
+            throw new EntityStoreException( e );
+        }
+    }
+
+    @Override
+    public void setPropertyValue( QualifiedName stateName, Object newValue )
+    {
+        try
+        {
+            JsonValue jsonValue = serialization.toJson( ALL_TYPE_INFO, newValue );
+            if( stateCloneWithProperty( stateName.name(), jsonValue ) )
+            {
+                markUpdated();
+            }
+        }
+        catch( SerializationException e )
+        {
+            throw new EntityStoreException( "Unable to set property " + stateName + " value " + newValue, e );
+        }
+    }
+
+    @Override
+    public EntityReference associationValueOf( QualifiedName stateName )
+    {
+        JsonValue associationValue = state.getJsonObject( JSONKeys.VALUE ).get( stateName.name() );
+        if( associationValue == JsonValue.NULL )
+        {
+            return null;
+        }
+        return EntityReference.parseEntityReference( ( (JsonString) associationValue ).getString() );
+    }
+
+    @Override
+    public void setAssociationValue( QualifiedName stateName, EntityReference entityReference )
+    {
+        if( stateCloneWithAssociation( stateName.name(), entityReference ) )
+        {
+            markUpdated();
+        }
+    }
+
+    @Override
+    public ManyAssociationState manyAssociationValueOf( QualifiedName stateName )
+    {
+        return new JSONManyAssociationState( jsonFactories, this, stateName.name() );
+    }
+
+    @Override
+    public NamedAssociationState namedAssociationValueOf( QualifiedName stateName )
+    {
+        return new JSONNamedAssociationState( jsonFactories, this, stateName.name() );
+    }
+
+    @Override
+    public void remove()
+    {
+        status = EntityStatus.REMOVED;
+    }
+
+    @Override
+    public EntityStatus status()
+    {
+        return status;
+    }
+
+    @Override
+    public boolean isAssignableTo( Class<?> type )
+    {
+        return entityDescriptor.isAssignableTo( type );
+    }
+
+    @Override
+    public EntityDescriptor entityDescriptor()
+    {
+        return entityDescriptor;
+    }
+
+    public JsonObject state()
+    {
+        return state;
+    }
+
+    @Override
+    public String toString()
+    {
+        return state.toString();
+    }
+
+    void markUpdated()
+    {
+        if( status == EntityStatus.LOADED )
+        {
+            status = EntityStatus.UPDATED;
+        }
+    }
+
+    void stateCloneWithVersionAndModified( String version, Instant lastModified )
+    {
+        state = jsonFactories.cloneBuilderExclude( state, JSONKeys.VERSION, JSONKeys.MODIFIED )
+                             .add( JSONKeys.VERSION, version )
+                             .add( JSONKeys.MODIFIED, lastModified.toEpochMilli() )
+                             .build();
+    }
+
+    private boolean stateCloneWithProperty( String stateName, JsonValue value )
+    {
+        JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+        if( Objects.equals( valueState.get( stateName ), value ) )
+        {
+            return false;
+        }
+        JsonObjectBuilder valueBuilder = jsonFactories.cloneBuilderExclude( valueState, stateName );
+        if( value == null )
+        {
+            valueBuilder.addNull( stateName );
+        }
+        else
+        {
+            valueBuilder.add( stateName, value );
+        }
+        state = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                             .add( JSONKeys.VALUE, valueBuilder.build() )
+                             .build();
+        return true;
+    }
+
+    private boolean stateCloneWithAssociation( String stateName, EntityReference ref )
+    {
+        JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+        JsonValue jsonRef = ref == null ? JsonValue.NULL : jsonFactories.toJsonString( ref.identity().toString() );
+        if( Objects.equals( valueState.get( stateName ), jsonRef ) )
+        {
+            return false;
+        }
+        valueState = jsonFactories.cloneBuilderExclude( valueState, stateName )
+                                  .add( stateName, jsonRef )
+                                  .build();
+        state = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                             .add( JSONKeys.VALUE, valueState )
+                             .build();
+        return true;
+    }
+
+    void stateCloneAddManyAssociation( int idx, String stateName, EntityReference ref )
+    {
+        JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+        String identity = ref.identity().toString();
+        JsonArray manyAssoc;
+        if( valueState.containsKey( stateName ) )
+        {
+            JsonArrayBuilder manyAssocBuilder = jsonFactories.builderFactory().createArrayBuilder();
+            JsonArray previousManyAssoc = valueState.getJsonArray( stateName );
+            int currentIdx = 0;
+            for( JsonValue jsonRef : previousManyAssoc )
+            {
+                if( currentIdx == idx )
+                {
+                    manyAssocBuilder.add( identity );
+                }
+                manyAssocBuilder.add( jsonRef );
+                currentIdx++;
+            }
+            if( idx >= previousManyAssoc.size() )
+            {
+                manyAssocBuilder.add( identity );
+            }
+            manyAssoc = manyAssocBuilder.build();
+        }
+        else
+        {
+            manyAssoc = jsonFactories.builderFactory().createArrayBuilder().add( identity ).build();
+        }
+        valueState = jsonFactories.cloneBuilderExclude( valueState, stateName )
+                                  .add( stateName, manyAssoc )
+                                  .build();
+        state = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                             .add( JSONKeys.VALUE, valueState )
+                             .build();
+    }
+
+    void stateCloneRemoveManyAssociation( String stateName, EntityReference ref )
+    {
+        JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+        if( valueState.containsKey( stateName ) )
+        {
+            String identity = ref.identity().toString();
+            JsonArray manyAssoc = jsonFactories.cloneBuilderExclude( valueState.getJsonArray( stateName ),
+                                                                     jsonFactories.toJsonString( identity ) )
+                                               .build();
+            valueState = jsonFactories.cloneBuilderExclude( valueState, stateName )
+                                      .add( stateName, manyAssoc ).build();
+            state = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                 .add( JSONKeys.VALUE, valueState )
+                                 .build();
+        }
+    }
+
+    void stateCloneClearManyAssociation( String stateName )
+    {
+        JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+        if( valueState.containsKey( stateName ) )
+        {
+            valueState = jsonFactories.cloneBuilderExclude( valueState, stateName )
+                                      .add( stateName, jsonFactories.builderFactory().createArrayBuilder().build() )
+                                      .build();
+            state = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                 .add( JSONKeys.VALUE, valueState )
+                                 .build();
+        }
+    }
+
+    void stateCloneAddNamedAssociation( String stateName, String name, EntityReference ref )
+    {
+        JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+        JsonObjectBuilder namedAssoc = valueState.containsKey( stateName )
+                                       ? jsonFactories.cloneBuilder( valueState.getJsonObject( stateName ) )
+                                       : jsonFactories.builderFactory().createObjectBuilder();
+        namedAssoc.add( name, ref.identity().toString() );
+        valueState = jsonFactories.cloneBuilderExclude( valueState, stateName )
+                                  .add( stateName, namedAssoc.build() )
+                                  .build();
+        state = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                             .add( JSONKeys.VALUE, valueState )
+                             .build();
+    }
+
+    void stateCloneRemoveNamedAssociation( String stateName, String name )
+    {
+        JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+        if( valueState.containsKey( stateName ) )
+        {
+            JsonObject namedAssoc = jsonFactories.cloneBuilderExclude( valueState.getJsonObject( stateName ), name )
+                                                 .build();
+            valueState = jsonFactories.cloneBuilderExclude( valueState, stateName )
+                                      .add( stateName, namedAssoc )
+                                      .build();
+            state = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                 .add( JSONKeys.VALUE, valueState )
+                                 .build();
+        }
+    }
+
+    void stateCloneClearNamedAssociation( String stateName )
+    {
+        JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+        if( valueState.containsKey( stateName ) )
+        {
+            valueState = jsonFactories.cloneBuilderExclude( valueState, stateName )
+                                      .add( stateName, jsonFactories.builderFactory().createObjectBuilder().build() )
+                                      .build();
+            state = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                 .add( JSONKeys.VALUE, valueState )
+                                 .build();
+        }
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONKeys.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONKeys.java
new file mode 100644
index 0000000..4c0fa0e
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONKeys.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.spi.entitystore.helpers;
+
+import org.apache.polygene.api.time.SystemTime;
+
+/**
+ * JSON keys for values in the stored data.
+ */
+public interface JSONKeys
+{
+    /**
+     * Identity of the entity.
+     */
+    String IDENTITY = "reference";
+    /**
+     * Version of the application which last updated the entity.
+     */
+    String APPLICATION_VERSION = "application_version";
+    /**
+     * Type of the entity.
+     */
+    String TYPE = "type";
+    /**
+     * Version of the entity.
+     */
+    String VERSION = "version";
+    /**
+     * When entity was last modified according to {@link SystemTime#now()}
+     */
+    String MODIFIED = "modified";
+    /**
+     * Entity value state.
+     */
+    String VALUE = "value";
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONManyAssociationState.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONManyAssociationState.java
new file mode 100644
index 0000000..275da51
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONManyAssociationState.java
@@ -0,0 +1,177 @@
+/*
+ *  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.polygene.spi.entitystore.helpers;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import javax.json.JsonArray;
+import javax.json.JsonException;
+import javax.json.JsonValue;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.spi.entity.ManyAssociationState;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+
+/**
+ * JSON implementation of ManyAssociationState.
+ * <p>Backed by a JsonArray.</p>
+ */
+public final class JSONManyAssociationState
+    implements ManyAssociationState
+{
+    private final JavaxJsonFactories jsonFactories;
+    private final JSONEntityState entityState;
+    private final String stateName;
+
+    /* package */ JSONManyAssociationState( JavaxJsonFactories jsonFactories,
+                                            JSONEntityState entityState,
+                                            String stateName )
+    {
+        this.jsonFactories = jsonFactories;
+        this.entityState = entityState;
+        this.stateName = stateName;
+    }
+
+    private JsonArray getReferences()
+    {
+        JsonValue references = entityState.state().getJsonObject( JSONKeys.VALUE ).get( stateName );
+        if( references != null && references.getValueType() == JsonValue.ValueType.ARRAY )
+        {
+            return (JsonArray) references;
+        }
+        return jsonFactories.builderFactory().createArrayBuilder().build();
+    }
+
+    @Override
+    public int count()
+    {
+        return getReferences().size();
+    }
+
+    @Override
+    public boolean contains( EntityReference entityReference )
+    {
+        return indexOfReference( entityReference.identity().toString() ) != -1;
+    }
+
+    @Override
+    public boolean add( int idx, EntityReference entityReference )
+    {
+        try
+        {
+            if( indexOfReference( entityReference.identity().toString() ) != -1 )
+            {
+                return false;
+            }
+            entityState.stateCloneAddManyAssociation( idx, stateName, entityReference );
+            entityState.markUpdated();
+            return true;
+        }
+        catch( JsonException e )
+        {
+            throw new EntityStoreException( e );
+        }
+    }
+
+    @Override
+    public boolean remove( EntityReference entityReference )
+    {
+        int refIndex = indexOfReference( entityReference.identity().toString() );
+        if( refIndex != -1 )
+        {
+            entityState.stateCloneRemoveManyAssociation( stateName, entityReference );
+            entityState.markUpdated();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean clear()
+    {
+        if( count() > 0 )
+        {
+            entityState.stateCloneClearManyAssociation( stateName );
+            entityState.markUpdated();
+        }
+        return false;
+    }
+
+    @Override
+    public EntityReference get( int i )
+    {
+        return EntityReference.parseEntityReference( getReferences().getString( i ) );
+    }
+
+    @Override
+    public Iterator<EntityReference> iterator()
+    {
+        return new Iterator<EntityReference>()
+        {
+            private int idx = 0;
+
+            @Override
+            public boolean hasNext()
+            {
+                return idx < getReferences().size();
+            }
+
+            @Override
+            public EntityReference next()
+            {
+                try
+                {
+                    EntityReference ref = EntityReference.parseEntityReference( getReferences().getString( idx ) );
+                    idx++;
+                    return ref;
+                }
+                catch( JsonException e )
+                {
+                    throw new NoSuchElementException();
+                }
+            }
+
+            @Override
+            public void remove()
+            {
+                throw new UnsupportedOperationException( "remove() is not supported on ManyAssociation iterators." );
+            }
+        };
+    }
+
+    @Override
+    public String toString()
+    {
+        return getReferences().toString();
+    }
+
+    private int indexOfReference( String entityIdentityAsString )
+    {
+        JsonArray references = getReferences();
+        for( int idx = 0; idx < references.size(); idx++ )
+        {
+            if( entityIdentityAsString.equals( references.getString( idx, null ) ) )
+            {
+                return idx;
+            }
+        }
+        return -1;
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONMapEntityStoreActivation.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONMapEntityStoreActivation.java
new file mode 100644
index 0000000..03d6d87
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONMapEntityStoreActivation.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.spi.entitystore.helpers;
+
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.service.ServiceReference;
+
+/**
+ * Activation for JSONMapEntityStoreMixin.
+ */
+@Activators( JSONMapEntityStoreActivation.Activator.class )
+public interface JSONMapEntityStoreActivation
+{
+
+    void setUpJSONMapES()
+        throws Exception;
+
+    void tearDownJSONMapES()
+        throws Exception;
+
+    /**
+     * JSONMapEntityStoreMixin Activator.
+     */
+    class Activator
+        extends ActivatorAdapter<ServiceReference<JSONMapEntityStoreActivation>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<JSONMapEntityStoreActivation> activated )
+            throws Exception
+        {
+            activated.get().setUpJSONMapES();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<JSONMapEntityStoreActivation> passivating )
+            throws Exception
+        {
+            passivating.get().tearDownJSONMapES();
+        }
+
+    }
+
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONMapEntityStoreMixin.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONMapEntityStoreMixin.java
new file mode 100644
index 0000000..bc715b7
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONMapEntityStoreMixin.java
@@ -0,0 +1,555 @@
+/*
+ *  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.polygene.spi.entitystore.helpers;
+
+import java.io.BufferedReader;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.Writer;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonReader;
+import org.apache.polygene.api.cache.CacheOptions;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.IdentityGenerator;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.spi.cache.Cache;
+import org.apache.polygene.spi.cache.CachePool;
+import org.apache.polygene.spi.cache.NullCache;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.entitystore.DefaultEntityStoreUnitOfWork;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+import org.apache.polygene.spi.entitystore.EntityStoreSPI;
+import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork;
+import org.apache.polygene.spi.entitystore.StateCommitter;
+import org.apache.polygene.spi.serialization.JsonSerialization;
+
+import static java.util.stream.Collectors.joining;
+
+/**
+ * Implementation of EntityStore that works with an implementation of MapEntityStore.
+ *
+ * <p>Implement {@link MapEntityStore} and add as mixin to the service using this mixin.</p>
+ * <p>See {@link org.apache.polygene.entitystore.memory.MemoryMapEntityStoreMixin} for reference.</p>
+ * <p>EntityStores based on this mixin gets support for the <b>Migration</b> and <b>Cache</b> extensions.</p>
+ * <p>MapEntityStore implementations will get their values as JSON.</p>
+ */
+public class JSONMapEntityStoreMixin
+    implements EntityStore, EntityStoreSPI, StateStore, JSONMapEntityStoreActivation
+{
+    @This
+    private MapEntityStore mapEntityStore;
+
+    @This
+    private EntityStoreSPI entityStoreSpi;
+
+    @Structure
+    private Application application;
+
+    @Service
+    private JsonSerialization serialization;
+
+    @Service
+    private JavaxJsonFactories jsonFactories;
+
+    @Service
+    private IdentityGenerator identityGenerator;
+
+    @Optional
+    @Service
+    private Migration migration;
+
+    @Uses
+    private ServiceDescriptor descriptor;
+
+    @Optional
+    @Service
+    private CachePool caching;
+    private Cache<CacheState> cache;
+
+    protected String uuid;
+
+    public JSONMapEntityStoreMixin()
+    {
+    }
+
+    @Override
+    public void setUpJSONMapES()
+        throws Exception
+    {
+        uuid = descriptor.identity() + "-" + UUID.randomUUID().toString();
+        if( caching != null )
+        {
+            cache = caching.fetchCache( uuid, CacheState.class );
+        }
+        else
+        {
+            cache = new NullCache<>();
+        }
+    }
+
+    @Override
+    public void tearDownJSONMapES()
+        throws Exception
+    {
+        if( caching != null )
+        {
+            caching.returnCache( cache );
+            cache = null;
+        }
+    }
+
+    // EntityStore
+
+    @Override
+    public EntityStoreUnitOfWork newUnitOfWork( ModuleDescriptor module, Usecase usecase, Instant currentTime )
+    {
+        return new DefaultEntityStoreUnitOfWork( module, entityStoreSpi, newUnitOfWorkId(), usecase, currentTime );
+    }
+
+    // EntityStoreSPI
+
+    @Override
+    public EntityState newEntityState( EntityStoreUnitOfWork uow,
+                                       EntityReference reference,
+                                       EntityDescriptor entityDescriptor
+    )
+    {
+        try
+        {
+            JsonObjectBuilder builder = jsonFactories.builderFactory().createObjectBuilder();
+            builder.add( JSONKeys.IDENTITY, reference.identity().toString() );
+            builder.add( JSONKeys.APPLICATION_VERSION, application.version() );
+            builder.add( JSONKeys.TYPE, entityDescriptor.types().findFirst().get().getName() );
+            builder.add( JSONKeys.VERSION, uow.identity().toString() );
+            builder.add( JSONKeys.MODIFIED, uow.currentTime().toEpochMilli() );
+            builder.add( JSONKeys.VALUE, jsonFactories.builderFactory().createObjectBuilder().build() );
+            JsonObject state = builder.build();
+            return new JSONEntityState( entityDescriptor.module(), serialization, jsonFactories,
+                                        uow.identity().toString(), uow.currentTime(),
+                                        reference,
+                                        EntityStatus.NEW, entityDescriptor,
+                                        state );
+        }
+        catch( Exception e )
+        {
+            throw new EntityStoreException( e );
+        }
+    }
+
+    @Override
+    public synchronized EntityState entityStateOf( EntityStoreUnitOfWork uow,
+                                                   ModuleDescriptor module,
+                                                   EntityReference reference )
+    {
+        try
+        {
+            EntityState state = fetchCachedState( reference, module, uow.currentTime() );
+            if( state != null )
+            {
+                return state;
+            }
+            // Get state
+            try( Reader in = mapEntityStore.get( reference ) )
+            {
+                JSONEntityState loadedState = readEntityState( module, in );
+                if( loadedState.status() == EntityStatus.UPDATED )
+                {
+                    List<JSONEntityState> migrated = new ArrayList<>( 1 );
+                    migrated.add( loadedState );
+                    synchMigratedEntities( migrated );
+                }
+                if( doCacheOnRead( uow ) )
+                {
+                    cache.put( reference.identity().toString(), new CacheState( loadedState.state().toString() ) );
+                }
+                return loadedState;
+            }
+        }
+        catch( EntityStoreException ex )
+        {
+            throw ex;
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( ex );
+        }
+    }
+
+    @Override
+    public synchronized String versionOf( EntityStoreUnitOfWork uow, EntityReference reference )
+    {
+        CacheState cacheState = cache.get( reference.identity().toString() );
+        if( cacheState != null )
+        {
+            return jsonFactories.readerFactory().createReader( new StringReader( cacheState.string ) ).readObject()
+                                .getString( JSONKeys.VERSION );
+        }
+        // Get state
+        try( JsonReader reader = jsonFactories.readerFactory().createReader( mapEntityStore.get( reference ) ) )
+        {
+            return reader.readObject().getString( JSONKeys.VERSION );
+        }
+        catch( EntityStoreException ex )
+        {
+            throw ex;
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( ex );
+        }
+    }
+
+    @Override
+    public StateCommitter applyChanges( EntityStoreUnitOfWork uow, Iterable<EntityState> entityStates )
+        throws EntityStoreException
+    {
+        return new StateCommitter()
+        {
+            @Override
+            public void commit()
+            {
+                try
+                {
+                    mapEntityStore.applyChanges(
+                        changer ->
+                        {
+                            CacheOptions options = uow.usecase().metaInfo( CacheOptions.class );
+                            if( options == null )
+                            {
+                                options = CacheOptions.ALWAYS;
+                            }
+
+                            for( EntityState entityState : entityStates )
+                            {
+                                JSONEntityState state = (JSONEntityState) entityState;
+                                String newVersion = uow.identity().toString();
+                                Instant lastModified = uow.currentTime();
+                                if( state.status().equals( EntityStatus.NEW ) )
+                                {
+                                    try( Writer writer = changer.newEntity( state.entityReference(),
+                                                                            state.entityDescriptor() ) )
+                                    {
+                                        writeEntityState( state, writer, newVersion, lastModified );
+                                    }
+                                    if( options.cacheOnNew() )
+                                    {
+                                        cache.put( state.entityReference().identity().toString(),
+                                                   new CacheState( state.state().toString() ) );
+                                    }
+                                }
+                                else if( state.status().equals( EntityStatus.UPDATED ) )
+                                {
+                                    MapEntityStore.MapChange mapChange = new MapEntityStore.MapChange(
+                                        state.entityReference(), state.entityDescriptor(),
+                                        state.version(), newVersion, lastModified
+                                    );
+                                    try( Writer writer = changer.updateEntity( mapChange ) )
+                                    {
+                                        writeEntityState( state, writer, newVersion, lastModified );
+                                    }
+                                    if( options.cacheOnWrite() )
+                                    {
+                                        cache.put( state.entityReference().identity().toString(),
+                                                   new CacheState( state.state().toString() ) );
+                                    }
+                                }
+                                else if( state.status().equals( EntityStatus.REMOVED ) )
+                                {
+                                    changer.removeEntity( state.entityReference(), state.entityDescriptor() );
+                                    cache.remove( state.entityReference().identity().toString() );
+                                }
+                            }
+                        } );
+                }
+                catch( Exception e )
+                {
+                    throw new EntityStoreException( e );
+                }
+            }
+
+            @Override
+            public void cancel()
+            {
+            }
+        };
+    }
+
+    @Override
+    public Stream<EntityState> entityStates( ModuleDescriptor module )
+    {
+        try
+        {
+            Stream<Reader> stateStream = mapEntityStore.entityStates();
+            List<JSONEntityState> migrated = new ArrayList<>();
+            Function<Reader, EntityState> function = reader ->
+            {
+                JSONEntityState entity = readEntityState( module, reader );
+                if( entity.status() == EntityStatus.UPDATED )
+                {
+                    migrated.add( entity );
+                    // Synch back 100 at a time
+                    if( migrated.size() > 100 )
+                    {
+                        synchMigratedEntities( migrated );
+                    }
+                }
+                return entity;
+            };
+            Runnable closer = () ->
+            {
+                // Synch any remaining migrated entities
+                if( !migrated.isEmpty() )
+                {
+                    synchMigratedEntities( migrated );
+                }
+            };
+            return stateStream.map( function ).onClose( closer );
+        }
+        catch( EntityStoreException ex )
+        {
+            throw ex;
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( ex );
+        }
+    }
+
+    private void synchMigratedEntities( List<JSONEntityState> migratedEntities )
+    {
+        try
+        {
+            mapEntityStore.applyChanges(
+                changer ->
+                {
+                    for( JSONEntityState state : migratedEntities )
+                    {
+                        Instant lastModified = state.lastModified();
+                        String version = state.version();
+                        MapEntityStore.MapChange changeInfo = new MapEntityStore.MapChange(
+                            state.entityReference(), state.entityDescriptor(),
+                            version, version, lastModified
+                        );
+                        try( Writer writer = changer.updateEntity( changeInfo ) )
+                        {
+                            writeEntityState( state, writer, version, lastModified );
+                        }
+                    }
+                } );
+            migratedEntities.clear();
+        }
+        catch( EntityStoreException ex )
+        {
+            throw ex;
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( "Synchronization of Migrated Entities failed.", ex );
+        }
+    }
+
+    protected Identity newUnitOfWorkId()
+    {
+        return identityGenerator.generate( EntityStore.class );
+    }
+
+    protected void writeEntityState( JSONEntityState state, Writer writer, String version, Instant lastModified )
+        throws EntityStoreException
+    {
+        try
+        {
+            state.stateCloneWithVersionAndModified( version, lastModified );
+            writer.append( state.state().toString() );
+        }
+        catch( IOException e )
+        {
+            throw new EntityStoreException( "Could not store EntityState", e );
+        }
+    }
+
+    protected JSONEntityState readEntityState( ModuleDescriptor module, Reader entityState )
+        throws EntityStoreException
+    {
+        try( JsonReader reader = jsonFactories.readerFactory().createReader( entityState ) )
+        {
+            JsonObject parsedState = reader.readObject();
+            JsonObjectBuilder jsonStateBuilder = jsonFactories.cloneBuilder( parsedState );
+            EntityStatus status = EntityStatus.LOADED;
+
+            String version = parsedState.getString( JSONKeys.VERSION );
+            Instant modified = Instant.ofEpochMilli( parsedState.getJsonNumber( JSONKeys.MODIFIED ).longValueExact() );
+            Identity identity = new StringIdentity( parsedState.getString( JSONKeys.IDENTITY ) );
+
+            // Check if version is correct
+            JsonObject state;
+            String currentAppVersion = parsedState.getString( JSONKeys.APPLICATION_VERSION, "0.0" );
+            if( currentAppVersion.equals( application.version() ) )
+            {
+                state = jsonStateBuilder.build();
+            }
+            else
+            {
+                if( migration != null )
+                {
+                    state = migration.migrate( jsonStateBuilder.build(), application.version(), this );
+                }
+                else
+                {
+                    // Do nothing - set version to be correct
+                    jsonStateBuilder.add( JSONKeys.APPLICATION_VERSION, application.version() );
+                    state = jsonStateBuilder.build();
+                }
+                // State changed
+                status = EntityStatus.UPDATED;
+            }
+
+            String type = state.getString( JSONKeys.TYPE );
+
+            EntityDescriptor entityDescriptor = module.entityDescriptor( type );
+            if( entityDescriptor == null )
+            {
+                throw new NoSuchEntityTypeException( type, module.name(), module.typeLookup() );
+            }
+
+            return new JSONEntityState( entityDescriptor.module(), serialization, jsonFactories,
+                                        version, modified,
+                                        EntityReference.create( identity ),
+                                        status, entityDescriptor,
+                                        state
+            );
+        }
+        catch( EntityStoreException ex )
+        {
+            throw ex;
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( ex );
+        }
+    }
+
+    @Override
+    public JsonObject jsonStateOf( String id )
+    {
+        try( JsonReader jsonReader = jsonFactories
+            .readerFactory().createReader( mapEntityStore.get( EntityReference.parseEntityReference( id ) ) ) )
+        {
+            return jsonReader.readObject();
+        }
+        catch( EntityStoreException ex )
+        {
+            throw ex;
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( ex );
+        }
+    }
+
+    private EntityState fetchCachedState( EntityReference reference, ModuleDescriptor module, Instant currentTime )
+    {
+        CacheState cacheState = cache.get( reference.identity().toString() );
+        if( cacheState != null )
+        {
+            JsonObject state = jsonFactories.readerFactory().createReader( new StringReader( cacheState.string ) )
+                                            .readObject();
+            try
+            {
+                String type = state.getString( JSONKeys.TYPE );
+                EntityDescriptor entityDescriptor = module.entityDescriptor( type );
+                String version = state.getString( JSONKeys.VERSION );
+                Instant modified = Instant.ofEpochMilli( state.getJsonNumber( JSONKeys.MODIFIED ).longValueExact() );
+                return new JSONEntityState( entityDescriptor.module(), serialization, jsonFactories,
+                                            version, modified,
+                                            reference,
+                                            EntityStatus.LOADED, entityDescriptor,
+                                            state );
+            }
+            catch( Exception e )
+            {
+                // Should not be able to happen, unless internal error in the cache system.
+                throw new EntityStoreException( e );
+            }
+        }
+        return null;
+    }
+
+    private boolean doCacheOnRead( EntityStoreUnitOfWork unitOfWork )
+    {
+        CacheOptions cacheOptions = unitOfWork.usecase().metaInfo( CacheOptions.class );
+        return cacheOptions == null || cacheOptions.cacheOnRead();
+    }
+
+    public static class CacheState
+        implements Externalizable
+    {
+        public String string;
+
+        public CacheState()
+        {
+        }
+
+        private CacheState( String string )
+        {
+            this.string = string;
+        }
+
+        @Override
+        public void writeExternal( ObjectOutput out )
+            throws IOException
+        {
+            out.writeUTF( string );
+        }
+
+        @Override
+        public void readExternal( ObjectInput in )
+            throws IOException, ClassNotFoundException
+        {
+            try( BufferedReader reader = new BufferedReader( new StringReader( in.readUTF() ) ) )
+            {
+                string = reader.lines().collect( joining( "\n" ) );
+            }
+        }
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONNamedAssociationState.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONNamedAssociationState.java
new file mode 100644
index 0000000..1981eb9
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONNamedAssociationState.java
@@ -0,0 +1,189 @@
+/*
+ *  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.polygene.spi.entitystore.helpers;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import javax.json.JsonException;
+import javax.json.JsonObject;
+import javax.json.JsonValue;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.spi.entity.NamedAssociationState;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+
+/**
+ * JSON implementation of NamedAssociationState.
+ * <p>Backed by a JsonObject.</p>
+ */
+public final class JSONNamedAssociationState
+    implements NamedAssociationState
+{
+    private final JavaxJsonFactories jsonFactories;
+    private final JSONEntityState entityState;
+    private final String stateName;
+
+    /* package */ JSONNamedAssociationState( JavaxJsonFactories jsonFactories,
+                                             JSONEntityState entityState,
+                                             String stateName )
+    {
+        this.jsonFactories = jsonFactories;
+        this.entityState = entityState;
+        this.stateName = stateName;
+    }
+
+    private JsonObject getReferences()
+    {
+        JsonValue references = entityState.state().getJsonObject( JSONKeys.VALUE ).get( stateName );
+        if( references != null && references.getValueType() == JsonValue.ValueType.OBJECT )
+        {
+            return (JsonObject) references;
+        }
+        return jsonFactories.builderFactory().createObjectBuilder().build();
+    }
+
+    @Override
+    public int count()
+    {
+        return getReferences().size();
+    }
+
+    @Override
+    public boolean containsName( String name )
+    {
+        return getReferences().containsKey( name );
+    }
+
+    @Override
+    public boolean put( String name, EntityReference entityReference )
+    {
+        try
+        {
+            if( containsName( name )
+                && entityReference.identity().toString().equals( getReferences().getString( name ) ) )
+            {
+                return false;
+            }
+            entityState.stateCloneAddNamedAssociation( stateName, name, entityReference );
+            entityState.markUpdated();
+            return true;
+        }
+        catch( JsonException ex )
+        {
+            throw new EntityStoreException( ex );
+        }
+    }
+
+    @Override
+    public boolean remove( String name )
+    {
+        if( !containsName( name ) )
+        {
+            return false;
+        }
+        entityState.stateCloneRemoveNamedAssociation( stateName, name );
+        entityState.markUpdated();
+        return true;
+    }
+
+    @Override
+    public boolean clear()
+    {
+        if( count() > 0 )
+        {
+            entityState.stateCloneClearNamedAssociation( stateName );
+            entityState.markUpdated();
+        }
+        return false;
+    }
+
+    @Override
+    public EntityReference get( String name )
+    {
+        String stringRef = getReferences().getString( name, null );
+        return stringRef == null ? null : EntityReference.parseEntityReference( stringRef );
+    }
+
+    @Override
+    public String nameOf( EntityReference entityReference )
+    {
+        try
+        {
+            JsonObject references = getReferences();
+            for( String name : references.keySet() )
+            {
+                if( entityReference.identity().toString().equals( references.getString( name ) ) )
+                {
+                    return name;
+                }
+            }
+            return null;
+        }
+        catch( JsonException ex )
+        {
+            throw new EntityStoreException( ex );
+        }
+    }
+
+    @Override
+    public Iterator<String> iterator()
+    {
+        List<String> names = new ArrayList<>( getReferences().keySet() );
+        return new Iterator<String>()
+        {
+            private int idx = 0;
+
+            @Override
+            public boolean hasNext()
+            {
+                return idx < names.size();
+            }
+
+            @Override
+            public String next()
+            {
+                try
+                {
+                    String next = names.get( idx );
+                    idx++;
+                    return next;
+                }
+                catch( JsonException ex )
+                {
+                    throw new NoSuchElementException();
+                }
+            }
+
+            @Override
+            public void remove()
+            {
+                throw new UnsupportedOperationException( "remove() is not supported on NamedAssociation iterators." );
+            }
+        };
+    }
+
+    @Override
+    public String toString()
+    {
+        return getReferences().toString();
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStore.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStore.java
new file mode 100644
index 0000000..901c2c1
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStore.java
@@ -0,0 +1,128 @@
+/*
+ *  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.polygene.spi.entitystore.helpers;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.time.Instant;
+import java.util.stream.Stream;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+
+/**
+ * MapEntityStore.
+ */
+public interface MapEntityStore
+{
+    /**
+     * @param entityReference The reference to the entity that we want to get.
+     * @return Entity state Reader
+     */
+    Reader get( EntityReference entityReference ) throws Exception;
+
+    /**
+     * @return All entities state Readers, must be closed
+     */
+    Stream<Reader> entityStates() throws Exception;
+
+    void applyChanges( MapChanges changes ) throws Exception;
+
+    /**
+     * Changes to be applied on a MapEntityStore.
+     */
+    interface MapChanges
+    {
+        /**
+         * Visitable MapChanges.
+         *
+         * @param changer Map changer
+         * @throws IOException on error
+         */
+        void visitMap( MapChanger changer ) throws Exception;
+    }
+
+    /**
+     * MapEntityStore changes applier.
+     */
+    interface MapChanger
+    {
+        Writer newEntity( EntityReference ref, EntityDescriptor entityDescriptor )
+            throws Exception;
+
+        Writer updateEntity( MapChange mapChange ) throws Exception;
+
+        void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor )
+            throws Exception;
+    }
+
+    /**
+     * MapEntityStore change meta info.
+     *
+     * Implementations backed by a shared store can make use of this for e.g. optimistic locking.
+     */
+    class MapChange
+    {
+        private final EntityReference reference;
+        private final EntityDescriptor descriptor;
+        private final String previousVersion;
+        private final String newVersion;
+        private final Instant lastModified;
+
+        public MapChange( EntityReference reference, EntityDescriptor descriptor,
+                          String previousVersion, String newVersion,
+                          Instant lastModified )
+        {
+            this.reference = reference;
+            this.descriptor = descriptor;
+            this.previousVersion = previousVersion;
+            this.newVersion = newVersion;
+            this.lastModified = lastModified;
+        }
+
+        public EntityReference reference()
+        {
+            return reference;
+        }
+
+        public EntityDescriptor descriptor()
+        {
+            return descriptor;
+        }
+
+        /**
+         * @return null if the change is an insertion
+         */
+        public String previousVersion()
+        {
+            return previousVersion;
+        }
+
+        public String newVersion()
+        {
+            return newVersion;
+        }
+
+        public Instant lastModified()
+        {
+            return lastModified;
+        }
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStoreActivation.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStoreActivation.java
new file mode 100644
index 0000000..f2aff28
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStoreActivation.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.polygene.spi.entitystore.helpers;
+
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.service.ServiceReference;
+
+/**
+ * Activation for MapEntityStoreMixin.
+ */
+@Activators( MapEntityStoreActivation.Activator.class )
+public interface MapEntityStoreActivation
+{
+
+    void activateMapEntityStore()
+        throws Exception;
+
+    /**
+     * MapEntityStoreMixin Activator.
+     */
+    class Activator
+        extends ActivatorAdapter<ServiceReference<MapEntityStoreActivation>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<MapEntityStoreActivation> activated )
+            throws Exception
+        {
+            activated.get().activateMapEntityStore();
+        }
+
+    }
+
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStoreMixin.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStoreMixin.java
new file mode 100644
index 0000000..c8bd163
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStoreMixin.java
@@ -0,0 +1,542 @@
+/*
+ *  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.polygene.spi.entitystore.helpers;
+
+import java.io.Reader;
+import java.io.Writer;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonException;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonReader;
+import javax.json.JsonValue;
+import javax.json.JsonWriter;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.IdentityGenerator;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.entitystore.DefaultEntityStoreUnitOfWork;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+import org.apache.polygene.spi.entitystore.EntityStoreSPI;
+import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork;
+import org.apache.polygene.spi.entitystore.StateCommitter;
+import org.apache.polygene.spi.serialization.JsonSerialization;
+
+import static org.apache.polygene.api.entity.EntityReference.parseEntityReference;
+
+/**
+ * Implementation of EntityStore that works with an implementation of MapEntityStore.
+ *
+ * <p>Implement {@link MapEntityStore} and add as mixin to the service using this mixin.</p>
+ * <p>See {@link org.apache.polygene.entitystore.memory.MemoryMapEntityStoreMixin} for reference.</p>
+ * <p>EntityStores based on this mixin gets support for the <b>Migration</b> extension.</p>
+ * <p>MapEntityStore implementations will get their values as JSON.</p>
+ */
+public class MapEntityStoreMixin
+    implements EntityStore, EntityStoreSPI, StateStore, MapEntityStoreActivation
+{
+    @This
+    private MapEntityStore mapEntityStore;
+
+    @This
+    private EntityStoreSPI entityStoreSpi;
+
+    @Structure
+    private Application application;
+
+    @Service
+    private JsonSerialization jsonSerialization;
+
+    @Service
+    private JavaxJsonFactories jsonFactories;
+
+    @Optional
+    @Service
+    private Migration migration;
+
+    @Service
+    private IdentityGenerator identityGenerator;
+
+    @Override
+    public void activateMapEntityStore() {}
+
+    // EntityStore
+    @Override
+    public EntityStoreUnitOfWork newUnitOfWork( ModuleDescriptor module, Usecase usecase, Instant currentTime )
+    {
+        return new DefaultEntityStoreUnitOfWork( module, entityStoreSpi, newUnitOfWorkId(),
+                                                 usecase, currentTime );
+    }
+
+    // EntityStoreSPI
+    @Override
+    public EntityState newEntityState( EntityStoreUnitOfWork uow,
+                                       EntityReference reference, EntityDescriptor entityDescriptor )
+    {
+        return new DefaultEntityState( uow.currentTime(), reference, entityDescriptor );
+    }
+
+    @Override
+    public synchronized EntityState entityStateOf( EntityStoreUnitOfWork uow,
+                                                   ModuleDescriptor module, EntityReference reference )
+    {
+        try
+        {
+            Reader in = mapEntityStore.get( reference );
+            EntityState loadedState = readEntityState( module, in );
+            if( loadedState.status() == EntityStatus.UPDATED )
+            {
+                List<EntityState> migrated = new ArrayList<>( 1 );
+                migrated.add( loadedState );
+                synchMigratedEntities( migrated );
+            }
+            return loadedState;
+        }
+        catch( EntityStoreException ex )
+        {
+            throw ex;
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( ex );
+        }
+    }
+
+    @Override
+    public synchronized String versionOf( EntityStoreUnitOfWork uow, EntityReference reference )
+    {
+        try( JsonReader jsonReader = jsonFactories.readerFactory().createReader( mapEntityStore.get( reference ) ) )
+        {
+            return jsonReader.readObject().getString( JSONKeys.VERSION );
+        }
+        catch( EntityStoreException ex )
+        {
+            throw ex;
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( ex );
+        }
+    }
+
+    @Override
+    public StateCommitter applyChanges( EntityStoreUnitOfWork uow, Iterable<EntityState> state )
+        throws EntityStoreException
+    {
+        return new StateCommitter()
+        {
+            @Override
+            public void commit()
+            {
+                try
+                {
+                    mapEntityStore.applyChanges(
+                        changer ->
+                        {
+                            for( EntityState entityState : state )
+                            {
+                                DefaultEntityState state1 = (DefaultEntityState) entityState;
+                                String newVersion = uow.identity().toString();
+                                Instant lastModified = uow.currentTime();
+                                if( state1.status().equals( EntityStatus.NEW ) )
+                                {
+                                    try( Writer writer = changer.newEntity( state1.entityReference(),
+                                                                            state1.entityDescriptor() ) )
+                                    {
+                                        writeEntityState( state1, writer, newVersion, lastModified );
+                                    }
+                                }
+                                else if( state1.status().equals( EntityStatus.UPDATED ) )
+                                {
+                                    MapEntityStore.MapChange mapChange = new MapEntityStore.MapChange(
+                                        state1.entityReference(), state1.entityDescriptor(),
+                                        state1.version(), newVersion, lastModified
+                                    );
+                                    try( Writer writer = changer.updateEntity( mapChange ) )
+                                    {
+                                        writeEntityState( state1, writer, newVersion, lastModified );
+                                    }
+                                }
+                                else if( state1.status().equals( EntityStatus.REMOVED ) )
+                                {
+                                    changer.removeEntity( state1.entityReference(), state1.entityDescriptor() );
+                                }
+                            }
+                        } );
+                }
+                catch( EntityStoreException ex )
+                {
+                    throw ex;
+                }
+                catch( Exception ex )
+                {
+                    throw new EntityStoreException( ex );
+                }
+            }
+
+            @Override
+            public void cancel()
+            {
+            }
+        };
+    }
+
+    @Override
+    public Stream<EntityState> entityStates( ModuleDescriptor module )
+    {
+        try
+        {
+            Stream<Reader> stateStream = mapEntityStore.entityStates();
+            List<EntityState> migrated = new ArrayList<>();
+            String migrationErrorMsg = "Synchronization of Migrated Entities failed.";
+            Function<Reader, EntityState> function = reader ->
+            {
+                EntityState entity = readEntityState( module, reader );
+                if( entity.status() == EntityStatus.UPDATED )
+                {
+                    migrated.add( entity );
+                    // Sync back 100 at a time
+                    if( migrated.size() > 100 )
+                    {
+                        try
+                        {
+                            synchMigratedEntities( migrated );
+                        }
+                        catch( EntityStoreException ex )
+                        {
+                            throw ex;
+                        }
+                        catch( Exception ex )
+                        {
+                            throw new EntityStoreException( migrationErrorMsg, ex );
+                        }
+                    }
+                }
+                return entity;
+            };
+            Runnable closer = () ->
+            {
+                // Sync any remaining migrated entities
+                if( !migrated.isEmpty() )
+                {
+                    try
+                    {
+                        synchMigratedEntities( migrated );
+                    }
+                    catch( EntityStoreException ex )
+                    {
+                        throw ex;
+                    }
+                    catch( Exception ex )
+                    {
+                        throw new EntityStoreException( migrationErrorMsg, ex );
+                    }
+                }
+            };
+            return stateStream.map( function ).onClose( closer );
+        }
+        catch( EntityStoreException ex )
+        {
+            throw ex;
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( ex );
+        }
+    }
+
+    private void synchMigratedEntities( final List<EntityState> migratedEntities )
+        throws Exception
+    {
+        mapEntityStore.applyChanges(
+            changer ->
+            {
+                for( EntityState migratedEntity : migratedEntities )
+                {
+                    DefaultEntityState state = (DefaultEntityState) migratedEntity;
+                    String version = state.version();
+                    Instant lastModified = state.lastModified();
+                    MapEntityStore.MapChange mapChange = new MapEntityStore.MapChange(
+                        state.entityReference(), state.entityDescriptor(),
+                        version, version, lastModified
+                    );
+                    try( Writer writer = changer.updateEntity( mapChange ) )
+                    {
+                        writeEntityState( state, writer, version, lastModified );
+                    }
+                }
+            } );
+        migratedEntities.clear();
+    }
+
+    protected Identity newUnitOfWorkId()
+    {
+        return identityGenerator.generate( EntityStore.class );
+    }
+
+    protected void writeEntityState( DefaultEntityState state, Writer writer, String version, Instant lastModified )
+        throws EntityStoreException
+    {
+        try
+        {
+            JsonObjectBuilder json = jsonFactories.builderFactory().createObjectBuilder();
+            json.add( JSONKeys.IDENTITY, state.entityReference().identity().toString() );
+            json.add( JSONKeys.APPLICATION_VERSION, application.version() );
+            json.add( JSONKeys.TYPE, state.entityDescriptor().primaryType().getName() );
+            json.add( JSONKeys.VERSION, version );
+            json.add( JSONKeys.MODIFIED, lastModified.toEpochMilli() );
+            JsonObjectBuilder valueBuilder = jsonFactories.builderFactory().createObjectBuilder();
+            EntityDescriptor entityType = state.entityDescriptor();
+            entityType.state().properties().forEach(
+                persistentProperty ->
+                {
+                    Object value = state.properties().get( persistentProperty.qualifiedName() );
+                    JsonValue jsonValue = jsonSerialization.toJson( value );
+                    valueBuilder.add( persistentProperty.qualifiedName().name(), jsonValue );
+                } );
+
+            for( Map.Entry<QualifiedName, EntityReference> entry : state.associations().entrySet() )
+            {
+                EntityReference value = entry.getValue();
+                valueBuilder.add( entry.getKey().name(), value == null ? null : value.identity().toString() );
+            }
+
+            for( Map.Entry<QualifiedName, List<EntityReference>> entry : state.manyAssociations().entrySet() )
+            {
+                JsonArrayBuilder arrayBuilder = jsonFactories.builderFactory().createArrayBuilder();
+                for( EntityReference entityReference : entry.getValue() )
+                {
+                    arrayBuilder.add( entityReference.identity().toString() );
+                }
+                valueBuilder.add( entry.getKey().name(), arrayBuilder.build() );
+            }
+
+            for( Map.Entry<QualifiedName, Map<String, EntityReference>> entry : state.namedAssociations().entrySet() )
+            {
+                JsonObjectBuilder objectBuilder = jsonFactories.builderFactory().createObjectBuilder();
+                for( Map.Entry<String, EntityReference> namedRef : entry.getValue().entrySet() )
+                {
+                    objectBuilder.add( namedRef.getKey(), namedRef.getValue().identity().toString() );
+                }
+                valueBuilder.add( entry.getKey().name(), objectBuilder.build() );
+            }
+            json.add( JSONKeys.VALUE, valueBuilder.build() );
+            JsonObject jsonState = json.build();
+            try( JsonWriter jsonWriter = jsonFactories.writerFactory().createWriter( writer ) )
+            {
+                jsonWriter.write( jsonState );
+            }
+        }
+        catch( Exception e )
+        {
+            throw new EntityStoreException( "Could not store EntityState", e );
+        }
+    }
+
+    protected EntityState readEntityState( ModuleDescriptor module, Reader entityState )
+        throws EntityStoreException
+    {
+        try( JsonReader jsonReader = jsonFactories.readerFactory().createReader( entityState ) )
+        {
+            JsonObject parsedState = jsonReader.readObject();
+            JsonObjectBuilder jsonStateBuilder = jsonFactories.cloneBuilder( parsedState );
+            final EntityStatus[] status = { EntityStatus.LOADED };
+
+            String version = parsedState.getString( JSONKeys.VERSION );
+            Instant modified = Instant.ofEpochMilli( parsedState.getJsonNumber( JSONKeys.MODIFIED ).longValueExact() );
+            Identity identity = new StringIdentity( parsedState.getString( JSONKeys.IDENTITY ) );
+
+            // Check if version is correct
+            JsonObject state;
+            String currentAppVersion = parsedState.getString( JSONKeys.APPLICATION_VERSION, "0.0" );
+            if( currentAppVersion.equals( application.version() ) )
+            {
+                state = jsonStateBuilder.build();
+            }
+            else
+            {
+                if( migration != null )
+                {
+                    state = migration.migrate( jsonStateBuilder.build(), application.version(), this );
+                }
+                else
+                {
+                    // Do nothing - set version to be correct
+                    jsonStateBuilder.add( JSONKeys.APPLICATION_VERSION, application.version() );
+                    state = jsonStateBuilder.build();
+                }
+                // State changed
+                status[ 0 ] = EntityStatus.UPDATED;
+            }
+
+            String type = state.getString( JSONKeys.TYPE );
+
+            EntityDescriptor entityDescriptor = module.entityDescriptor( type );
+            if( entityDescriptor == null )
+            {
+                throw new NoSuchEntityTypeException( type, module.name(), module.typeLookup() );
+            }
+
+            Map<QualifiedName, Object> properties = new HashMap<>();
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            entityDescriptor.state().properties().forEach(
+                property ->
+                {
+                    try
+                    {
+                        JsonValue jsonValue = valueState.get( property.qualifiedName().name() );
+                        Object value = jsonSerialization.fromJson( module, property.valueType(), jsonValue );
+                        properties.put( property.qualifiedName(), value );
+                    }
+                    catch( JsonException e )
+                    {
+                        // Value not found, default it
+                        Object initialValue = property.resolveInitialValue( module );
+                        properties.put( property.qualifiedName(), initialValue );
+                        status[ 0 ] = EntityStatus.UPDATED;
+                    }
+                } );
+
+            Map<QualifiedName, EntityReference> associations = new HashMap<>();
+            entityDescriptor.state().associations().forEach(
+                association ->
+                {
+                    try
+                    {
+                        String jsonValue = valueState.getString( association.qualifiedName().name(), null );
+                        EntityReference value = jsonValue == null
+                                                ? null
+                                                : parseEntityReference( jsonValue );
+                        associations.put( association.qualifiedName(), value );
+                    }
+                    catch( JsonException e )
+                    {
+                        // Association not found, default it to null
+                        associations.put( association.qualifiedName(), null );
+                        status[ 0 ] = EntityStatus.UPDATED;
+                    }
+                } );
+
+            Map<QualifiedName, List<EntityReference>> manyAssociations = new HashMap<>();
+            entityDescriptor.state().manyAssociations().forEach(
+                association ->
+                {
+                    List<EntityReference> references = new ArrayList<>();
+                    try
+                    {
+                        JsonArray jsonValues = valueState.getJsonArray( association.qualifiedName().name() );
+                        for( int i = 0; i < jsonValues.size(); i++ )
+                        {
+                            String jsonValue = jsonValues.getString( i, null );
+                            EntityReference value = jsonValue == null
+                                                    ? null
+                                                    : parseEntityReference( jsonValue );
+                            references.add( value );
+                        }
+                        manyAssociations.put( association.qualifiedName(), references );
+                    }
+                    catch( JsonException e )
+                    {
+                        // ManyAssociation not found, default to empty one
+                        manyAssociations.put( association.qualifiedName(), references );
+                    }
+                } );
+
+            Map<QualifiedName, Map<String, EntityReference>> namedAssociations = new HashMap<>();
+            entityDescriptor.state().namedAssociations().forEach(
+                association ->
+                {
+                    Map<String, EntityReference> references = new LinkedHashMap<>();
+                    try
+                    {
+                        JsonObject jsonValues = valueState.getJsonObject( association.qualifiedName().name() );
+                        for( String name : jsonValues.keySet() )
+                        {
+                            String value = jsonValues.getString( name, null );
+                            EntityReference ref = value == null
+                                                  ? null
+                                                  : parseEntityReference( value );
+                            references.put( name, ref );
+                        }
+                        namedAssociations.put( association.qualifiedName(), references );
+                    }
+                    catch( JsonException e )
+                    {
+                        // NamedAssociation not found, default to empty one
+                        namedAssociations.put( association.qualifiedName(), references );
+                    }
+                } );
+
+            return new DefaultEntityState( version,
+                                           modified,
+                                           EntityReference.create( identity ),
+                                           status[ 0 ],
+                                           entityDescriptor,
+                                           properties,
+                                           associations,
+                                           manyAssociations,
+                                           namedAssociations
+            );
+        }
+        catch( Exception e )
+        {
+            throw new EntityStoreException( e );
+        }
+    }
+
+    @Override
+    public JsonObject jsonStateOf( String id )
+    {
+        try( JsonReader reader = jsonFactories.readerFactory()
+                                              .createReader( mapEntityStore.get( parseEntityReference( id ) ) ) )
+        {
+            return reader.readObject();
+        }
+        catch( EntityStoreException ex )
+        {
+            throw ex;
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( ex );
+        }
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/Migration.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/Migration.java
new file mode 100644
index 0000000..6a8ebfb
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/Migration.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.spi.entitystore.helpers;
+
+import javax.json.JsonException;
+import javax.json.JsonObject;
+
+/**
+ * State Migration SPI.
+ */
+public interface Migration
+{
+    JsonObject migrate( JsonObject state, String toVersion, StateStore stateStore )
+        throws JsonException;
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/StateStore.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/StateStore.java
new file mode 100644
index 0000000..8aa9e6e
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/StateStore.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.spi.entitystore.helpers;
+
+import javax.json.JsonObject;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+
+/**
+ * StateStore SPI.
+ */
+public interface StateStore
+{
+    JsonObject jsonStateOf( String id ) throws EntityStoreException;
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/package.html b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/package.html
new file mode 100644
index 0000000..43bd82f
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>EntityStore Helpers.</h2>
+    </body>
+</html>
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/package.html b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/package.html
new file mode 100644
index 0000000..ca4701e
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>EntityStore SPI.</h2>
+    </body>
+</html>
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/metrics/DefaultMetric.java b/core/spi/src/main/java/org/apache/polygene/spi/metrics/DefaultMetric.java
new file mode 100644
index 0000000..91ea9fc
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/metrics/DefaultMetric.java
@@ -0,0 +1,91 @@
+/*
+ *  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.polygene.spi.metrics;
+
+import org.apache.polygene.api.metrics.MetricsCounter;
+import org.apache.polygene.api.metrics.MetricsGauge;
+import org.apache.polygene.api.metrics.MetricsHealthCheck;
+import org.apache.polygene.api.metrics.MetricsHistogram;
+import org.apache.polygene.api.metrics.MetricsMeter;
+import org.apache.polygene.api.metrics.MetricsTimer;
+
+/**
+ * Default Metric implementing all supported Metrics as a null object.
+ */
+public final class DefaultMetric
+    implements MetricsGauge, MetricsCounter, MetricsHistogram, MetricsHealthCheck, MetricsMeter, MetricsTimer
+{
+    public static final DefaultMetric NULL = new DefaultMetric();
+
+    @Override
+    public void increment()
+    {
+    }
+
+    @Override
+    public void increment( int steps )
+    {
+    }
+
+    @Override
+    public void decrement()
+    {
+    }
+
+    @Override
+    public void decrement( int steps )
+    {
+    }
+
+    @Override
+    public Context start()
+    {
+        return () -> {};
+    }
+
+    @Override
+    public Object value()
+    {
+        return null;
+    }
+
+    @Override
+    public void update( long newValue )
+    {
+    }
+
+    @Override
+    public Result check()
+        throws Exception
+    {
+        return  Result.healthOk();
+    }
+
+    @Override
+    public void mark()
+    {
+    }
+
+    @Override
+    public void mark( int numberOfEvents )
+    {
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/metrics/MetricsProviderAdapter.java b/core/spi/src/main/java/org/apache/polygene/spi/metrics/MetricsProviderAdapter.java
new file mode 100644
index 0000000..d83a624
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/metrics/MetricsProviderAdapter.java
@@ -0,0 +1,106 @@
+/*
+ *  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.polygene.spi.metrics;
+
+import org.apache.polygene.api.metrics.MetricsCounterFactory;
+import org.apache.polygene.api.metrics.MetricsFactory;
+import org.apache.polygene.api.metrics.MetricsGaugeFactory;
+import org.apache.polygene.api.metrics.MetricsHealthCheckFactory;
+import org.apache.polygene.api.metrics.MetricsHistogramFactory;
+import org.apache.polygene.api.metrics.MetricsMeterFactory;
+import org.apache.polygene.api.metrics.MetricsNotSupportedException;
+import org.apache.polygene.api.metrics.MetricsProvider;
+import org.apache.polygene.api.metrics.MetricsTimerFactory;
+
+/**
+ * Adapter to ease MetricsProvider implementation.
+ */
+public class MetricsProviderAdapter
+    implements MetricsProvider
+{
+    private static final MetricsCounterFactory NULL_COUNTER_FACTORY = new NullMetricsFactory.NullCounterFactory();
+    private static final MetricsGaugeFactory NULL_GAUGE_FACTORY = new NullMetricsFactory.NullGaugeFactory();
+    private static final MetricsMeterFactory NULL_METER_FACTORY = new NullMetricsFactory.NullMeterFactory();
+    private static final MetricsHistogramFactory NULL_HISTOGRAM_FACTORY = new NullMetricsFactory.NullHistogramFactory();
+    private static final MetricsTimerFactory NULL_TIMER_FACTORY = new NullMetricsFactory.NullTimerFactory();
+    private static final MetricsHealthCheckFactory NULL_HEALTHCHECK_FACTORY = new NullMetricsFactory.NullHealthCheckFactory();
+
+    @SuppressWarnings( "unchecked" )
+    @Override
+    public <T extends MetricsFactory> T createFactory( Class<T> factoryType )
+    {
+        if( factoryType.equals( MetricsCounterFactory.class ) )
+        {
+            return (T) createMetricsCounterFactory();
+        }
+        else if( factoryType.equals( MetricsGaugeFactory.class ) )
+        {
+            return (T) createMetricsGaugeFactory();
+        }
+        else if( factoryType.equals( MetricsHealthCheckFactory.class ) )
+        {
+            return (T) createMetricsHealthCheckFactory();
+        }
+        else if( factoryType.equals( MetricsHistogramFactory.class ) )
+        {
+            return (T) createMetricsHistogramFactory();
+        }
+        else if( factoryType.equals( MetricsMeterFactory.class ) )
+        {
+            return (T) createMetricsMeterFactory();
+        }
+        else if( factoryType.equals( MetricsTimerFactory.class ) )
+        {
+            return (T) createMetricsTimerFactory();
+        }
+        throw new MetricsNotSupportedException( factoryType, getClass() );
+    }
+
+    protected MetricsTimerFactory createMetricsTimerFactory()
+    {
+        return NULL_TIMER_FACTORY;
+    }
+
+    protected MetricsMeterFactory createMetricsMeterFactory()
+    {
+        return NULL_METER_FACTORY;
+    }
+
+    protected MetricsHistogramFactory createMetricsHistogramFactory()
+    {
+        return NULL_HISTOGRAM_FACTORY;
+    }
+
+    protected MetricsHealthCheckFactory createMetricsHealthCheckFactory()
+    {
+        return NULL_HEALTHCHECK_FACTORY;
+    }
+
+    protected MetricsGaugeFactory createMetricsGaugeFactory()
+    {
+        return NULL_GAUGE_FACTORY;
+    }
+
+    protected MetricsCounterFactory createMetricsCounterFactory()
+    {
+        return NULL_COUNTER_FACTORY;
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/metrics/NullMetricsFactory.java b/core/spi/src/main/java/org/apache/polygene/spi/metrics/NullMetricsFactory.java
new file mode 100644
index 0000000..2ea60d7
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/metrics/NullMetricsFactory.java
@@ -0,0 +1,134 @@
+/*
+ *  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.polygene.spi.metrics;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.metrics.Metric;
+import org.apache.polygene.api.metrics.MetricsCounter;
+import org.apache.polygene.api.metrics.MetricsCounterFactory;
+import org.apache.polygene.api.metrics.MetricsGauge;
+import org.apache.polygene.api.metrics.MetricsGaugeFactory;
+import org.apache.polygene.api.metrics.MetricsHealthCheck;
+import org.apache.polygene.api.metrics.MetricsHealthCheckFactory;
+import org.apache.polygene.api.metrics.MetricsHistogram;
+import org.apache.polygene.api.metrics.MetricsHistogramFactory;
+import org.apache.polygene.api.metrics.MetricsMeter;
+import org.apache.polygene.api.metrics.MetricsMeterFactory;
+import org.apache.polygene.api.metrics.MetricsTimer;
+import org.apache.polygene.api.metrics.MetricsTimerFactory;
+
+/**
+ * Factory for Metrics null objects.
+ */
+public final class NullMetricsFactory
+{
+    public static class NullCounterFactory implements MetricsCounterFactory
+    {
+        @Override
+        public MetricsCounter createCounter( String name )
+        {
+            return DefaultMetric.NULL;
+        }
+
+        @Override
+        public Stream<Metric> registered()
+        {
+            return Stream.of( DefaultMetric.NULL );
+        }
+    }
+
+    public static class NullGaugeFactory implements MetricsGaugeFactory
+    {
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public <T> MetricsGauge<T> registerGauge( String name, MetricsGauge<T> gauge )
+        {
+            return DefaultMetric.NULL;
+        }
+
+        @Override
+        public Stream<Metric> registered()
+        {
+            return Stream.of( DefaultMetric.NULL );
+        }
+    }
+
+    public static class NullHealthCheckFactory implements MetricsHealthCheckFactory
+    {
+        @Override
+        public MetricsHealthCheck registerHealthCheck( String name, MetricsHealthCheck check )
+        {
+            return DefaultMetric.NULL;
+        }
+
+        @Override
+        public Stream<Metric> registered()
+        {
+            return Stream.of( DefaultMetric.NULL );
+        }
+    }
+
+    public static class NullHistogramFactory implements MetricsHistogramFactory
+    {
+        @Override
+        public MetricsHistogram createHistogram( String name )
+        {
+            return DefaultMetric.NULL;
+        }
+
+        @Override
+        public Stream<Metric> registered()
+        {
+            return Stream.of( DefaultMetric.NULL );
+        }
+    }
+
+    public static class NullMeterFactory implements MetricsMeterFactory
+    {
+        @Override
+        public MetricsMeter createMeter( String name )
+        {
+
+            return DefaultMetric.NULL;
+        }
+
+        @Override
+        public Stream<Metric> registered()
+        {
+            return Stream.of( DefaultMetric.NULL );
+        }
+    }
+
+    public static class NullTimerFactory implements MetricsTimerFactory
+    {
+        @Override
+        public MetricsTimer createTimer( String name )
+        {
+            return DefaultMetric.NULL;
+        }
+
+        @Override
+        public Stream<Metric> registered()
+        {
+            return Stream.of( DefaultMetric.NULL );
+        }
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/metrics/package.html b/core/spi/src/main/java/org/apache/polygene/spi/metrics/package.html
new file mode 100644
index 0000000..2a30767
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/metrics/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Metrics SPI.</h2>
+    </body>
+</html>
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/module/ModuleSpi.java b/core/spi/src/main/java/org/apache/polygene/spi/module/ModuleSpi.java
new file mode 100644
index 0000000..eccc612
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/module/ModuleSpi.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.spi.module;
+
+import org.apache.polygene.api.identity.IdentityGenerator;
+import org.apache.polygene.api.metrics.MetricsProvider;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.type.ValueTypeFactory;
+
+public interface ModuleSpi extends Module
+{
+    EntityStore entityStore();
+
+    IdentityGenerator identityGenerator();
+
+    Serialization serialization();
+
+    MetricsProvider metricsProvider();
+
+    ValueTypeFactory valueTypeFactory();
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/module/package.html b/core/spi/src/main/java/org/apache/polygene/spi/module/package.html
new file mode 100644
index 0000000..6153019
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/module/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Module SPI.</h2>
+    </body>
+</html>
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/package.html b/core/spi/src/main/java/org/apache/polygene/spi/package.html
new file mode 100644
index 0000000..ca8389a
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Apache Polygene™ SPI.</h2>
+    </body>
+</html>
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/query/EntityFinder.java b/core/spi/src/main/java/org/apache/polygene/spi/query/EntityFinder.java
new file mode 100644
index 0000000..44223e0
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/query/EntityFinder.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.spi.query;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.query.grammar.OrderBy;
+
+/**
+ * Entity Finder.
+ */
+public interface EntityFinder
+{
+    /**
+     * Find entities matching the query criterion.
+     *
+     * @param resultType        Type that the entities must have.
+     * @param whereClause       Where clause specification.
+     * @param orderBySegments   Ordering
+     * @param firstResult       Index of the first returned entity.
+     * @param maxResults        Maximum returned entities.
+     * @param variables         Query variables
+     * @return Entities matching the query criterion.
+     * @throws EntityFinderException on error
+     */
+    Stream<EntityReference> findEntities( Class<?> resultType,
+                                          @Optional Predicate<Composite> whereClause,
+                                          @Optional List<OrderBy> orderBySegments,
+                                          @Optional Integer firstResult,
+                                          @Optional Integer maxResults,
+                                          Map<String, Object> variables )
+        throws EntityFinderException;
+
+    /**
+     * Find a single entity matching the query criterion.
+     *
+     * @param resultType    Type that the entity must have.
+     * @param whereClause   Where clause specification.
+     * @param variables     Query variables
+     * @return Single entity matching the query criterion.
+     * @throws EntityFinderException on error
+     */
+    EntityReference findEntity( Class<?> resultType,
+                                @Optional Predicate<Composite> whereClause,
+                                Map<String, Object> variables
+    )
+        throws EntityFinderException;
+
+    /**
+     * Count entities matching the query criterion.
+     *
+     * @param resultType    Type that the entities must have.
+     * @param whereClause   Where clause specification.
+     * @param variables     Query variables
+     * @return Count entities matching the query criterion.
+     * @throws EntityFinderException on error
+     */
+    long countEntities( Class<?> resultType,
+                        @Optional Predicate<Composite> whereClause,
+                        Map<String, Object> variables
+    )
+        throws EntityFinderException;
+}
\ No newline at end of file
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/query/EntityFinderException.java b/core/spi/src/main/java/org/apache/polygene/spi/query/EntityFinderException.java
new file mode 100644
index 0000000..d837bb8
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/query/EntityFinderException.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.spi.query;
+
+/**
+ * Entity Finder Exception.
+ */
+public class EntityFinderException extends RuntimeException
+{
+    public EntityFinderException( final String message )
+    {
+        super( message );
+    }
+
+    public EntityFinderException( final String message,
+                                  final Throwable throwable
+    )
+    {
+        super( message, throwable );
+    }
+
+    public EntityFinderException( final Throwable throwable )
+    {
+        super( throwable );
+    }
+}
\ No newline at end of file
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/query/IndexExporter.java b/core/spi/src/main/java/org/apache/polygene/spi/query/IndexExporter.java
new file mode 100644
index 0000000..ad78d56
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/query/IndexExporter.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.spi.query;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * Interface for exporting the index currently held by the Indexing Engine.
+ * Index Engine implementations are encouraged to implement this interface to allow for trouble-shooting index related
+ * problems.
+ */
+public interface IndexExporter
+{
+    /**
+     * Write the index to the provided output stream in an implementation specific, human-readable format.
+     *
+     * @param out The output stream that the index will be sent to.
+     *
+     * @throws java.io.IOException           if an IOException occurs in the underlying PrintStream.
+     * @throws UnsupportedOperationException if the method is not supported by this implementation.
+     */
+    void exportReadableToStream( PrintStream out )
+        throws IOException, UnsupportedOperationException;
+
+    /**
+     * Write the index to the provided print writer in an implementation specific, machine-readable format, preferably
+     * either XML or JSON.
+     *
+     * @param out The print writer that the index will be sent to.
+     *
+     * @throws java.io.IOException           if an IOException occurs in the underlying PrintWriter.
+     * @throws UnsupportedOperationException if the method is not supported by this implementation.
+     */
+    void exportFormalToWriter( PrintWriter out )
+        throws IOException, UnsupportedOperationException;
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/query/QueryBuilderSPI.java b/core/spi/src/main/java/org/apache/polygene/spi/query/QueryBuilderSPI.java
new file mode 100644
index 0000000..d89bc73
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/query/QueryBuilderSPI.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.spi.query;
+
+import org.apache.polygene.api.query.Query;
+
+/**
+ * QueryBuilder SPI.
+ */
+public interface QueryBuilderSPI<T>
+{
+    Query<T> newQuery( QuerySource querySource );
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/query/QuerySource.java b/core/spi/src/main/java/org/apache/polygene/spi/query/QuerySource.java
new file mode 100644
index 0000000..6287f03
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/query/QuerySource.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.spi.query;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.query.grammar.OrderBy;
+
+/**
+ * Query Source, used in QueryBuilder SPI.
+ */
+public interface QuerySource
+{
+    <T> T find( Class<T> resultType,
+                Predicate<Composite> whereClause,
+                List<OrderBy> orderBySegments,
+                Integer firstResult,
+                Integer maxResults,
+                Map<String, Object> variables
+    );
+
+    <T> long count( Class<T> resultType,
+                    Predicate<Composite> whereClause,
+                    List<OrderBy> orderBySegments,
+                    Integer firstResult,
+                    Integer maxResults,
+                    Map<String, Object> variables
+    );
+
+    <T> Stream<T> stream( Class<T> resultType,
+                          Predicate<Composite> whereClause,
+                          List<OrderBy> orderBySegments,
+                          Integer firstResult,
+                          Integer maxResults,
+                          Map<String, Object> variables
+    );
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/query/package.html b/core/spi/src/main/java/org/apache/polygene/spi/query/package.html
new file mode 100644
index 0000000..0ecef79
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/query/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Index/Query SPI.</h2>
+    </body>
+</html>
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractBinaryDeserializer.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractBinaryDeserializer.java
new file mode 100644
index 0000000..5cf2660
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractBinaryDeserializer.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.spi.serialization;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.UncheckedIOException;
+import java.util.Base64;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ValueType;
+
+import static java.util.stream.Collectors.joining;
+
+// START SNIPPET: binary
+/**
+ * Base Binary Deserializer.
+ *
+ * Implementations work on bytes, this base deserializer decode Strings from Base64 to produce bytes.
+ *
+ * See {@link AbstractBinarySerializer}.
+ */
+public abstract class AbstractBinaryDeserializer extends AbstractDeserializer
+// END SNIPPET: binary
+{
+    @Override
+    public <T> T deserialize( ModuleDescriptor module, ValueType valueType, Reader state )
+    {
+        String stateString;
+        try( BufferedReader buffer = new BufferedReader( state ) )
+        {
+            stateString = buffer.lines().collect( joining( "\n" ) );
+        }
+        catch( IOException ex )
+        {
+            throw new UncheckedIOException( ex );
+        }
+        byte[] decoded = Base64.getDecoder().decode( stateString );
+        return deserialize( module, valueType, new ByteArrayInputStream( decoded ) );
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractBinarySerializer.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractBinarySerializer.java
new file mode 100644
index 0000000..c17ffb4
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractBinarySerializer.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.spi.serialization;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.io.Writer;
+import java.util.Base64;
+import org.apache.polygene.api.common.Optional;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+// START SNIPPET: binary
+/**
+ * Base Binary Serializer.
+ *
+ * Implementations work on bytes, this base serializer encode these bytes in Base64 to produce Strings.
+ *
+ * See {@link AbstractBinaryDeserializer}.
+ */
+public abstract class AbstractBinarySerializer extends AbstractSerializer
+// END SNIPPET: binary
+{
+    @Override
+    public void serialize( Options options, Writer writer, @Optional Object object )
+    {
+        try
+        {
+            ByteArrayOutputStream output = new ByteArrayOutputStream();
+            serialize( options, output, object );
+            byte[] base64 = Base64.getEncoder().encode( output.toByteArray() );
+            writer.write( new String( base64, UTF_8 ) );
+        }
+        catch( IOException ex )
+        {
+            throw new UncheckedIOException( ex );
+        }
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractDeserializer.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractDeserializer.java
new file mode 100644
index 0000000..0b604aa
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractDeserializer.java
@@ -0,0 +1,184 @@
+/*
+ *  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.polygene.spi.serialization;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.composite.AmbiguousTypeException;
+import org.apache.polygene.api.composite.StatefulAssociationCompositeDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.serialization.Deserializer;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.CollectionType;
+import org.apache.polygene.api.type.MapType;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.spi.module.ModuleSpi;
+
+/**
+ * Base Deserializer.
+ *
+ * Provides default implementations for convenience API methods.
+ *
+ * See {@link AbstractSerializer}.
+ */
+public abstract class AbstractDeserializer implements Deserializer
+{
+    protected static final ValueType ENTITY_REF_LIST_VALUE_TYPE = CollectionType.listOf( EntityReference.class );
+    protected static final ValueType ENTITY_REF_MAP_VALUE_TYPE = MapType.of( String.class, EntityReference.class );
+
+    @Override
+    public <T> T deserialize( ModuleDescriptor module, ValueType valueType, String state )
+    {
+        return deserialize( module, valueType, new StringReader( state ) );
+    }
+
+    @Override
+    public <T> Function<String, T> deserializeFunction( ModuleDescriptor module, ValueType valueType )
+    {
+        return state -> deserialize( module, valueType, new StringReader( state ) );
+    }
+
+    @Override
+    public <T> Stream<T> deserializeEach( ModuleDescriptor module, ValueType valueType, Iterable<String> states )
+    {
+        return StreamSupport.stream( states.spliterator(), false )
+                            .map( state -> deserialize( module, valueType, new StringReader( state ) ) );
+    }
+
+    @Override
+    public <T> Stream<T> deserializeEach( ModuleDescriptor module, ValueType valueType, String... states )
+    {
+        return Stream.of( states ).map( state -> deserialize( module, valueType, new StringReader( state ) ) );
+    }
+
+    @Override
+    public <T> T fromBytes( ModuleDescriptor module, ValueType valueType, byte[] bytes )
+    {
+        return deserialize( module, valueType, new ByteArrayInputStream( bytes ) );
+    }
+
+    @Override
+    public <T> Function<byte[], T> fromBytesFunction( ModuleDescriptor module, ValueType valueType )
+    {
+        return bytes -> deserialize( module, valueType, new ByteArrayInputStream( bytes ) );
+    }
+
+    @Override
+    public <T> Stream<T> fromBytesEach( ModuleDescriptor module, ValueType valueType, Iterable<byte[]> states )
+    {
+        return StreamSupport.stream( states.spliterator(), false )
+                            .map( bytes -> deserialize( module, valueType, new ByteArrayInputStream( bytes ) ) );
+    }
+
+    @Override
+    public <T> Stream<T> fromBytesEach( ModuleDescriptor module, ValueType valueType, byte[]... states )
+    {
+        return Stream.of( states ).map( bytes -> deserialize( module, valueType, new ByteArrayInputStream( bytes ) ) );
+    }
+
+    @Override
+    public <T> T deserialize( ModuleDescriptor module, Class<T> type, InputStream state )
+    {
+        return deserialize( module, valueTypeOf( module, type ), state );
+    }
+
+    @Override
+    public <T> T deserialize( ModuleDescriptor module, Class<T> type, Reader state )
+    {
+        return deserialize( module, valueTypeOf( module, type ), state );
+    }
+
+    @Override
+    public <T> T deserialize( ModuleDescriptor module, Class<T> type, String state )
+    {
+        return deserialize( module, valueTypeOf( module, type ), state );
+    }
+
+    @Override
+    public <T> Function<String, T> deserializeFunction( ModuleDescriptor module, Class<T> type )
+    {
+        return deserializeFunction( module, valueTypeOf( module, type ) );
+    }
+
+    @Override
+    public <T> Stream<T> deserializeEach( ModuleDescriptor module, Class<T> type, Iterable<String> states )
+    {
+        return deserializeEach( module, valueTypeOf( module, type ), states );
+    }
+
+    @Override
+    public <T> Stream<T> deserializeEach( ModuleDescriptor module, Class<T> type, String... states )
+    {
+        return deserializeEach( module, valueTypeOf( module, type ), states );
+    }
+
+    @Override
+    public <T> T fromBytes( ModuleDescriptor module, Class<T> type, byte[] bytes )
+    {
+        return fromBytes( module, valueTypeOf( module, type ), bytes );
+    }
+
+    @Override
+    public <T> Function<byte[], T> fromBytesFunction( ModuleDescriptor module, Class<T> type )
+    {
+        return fromBytesFunction( module, valueTypeOf( module, type ) );
+    }
+
+    @Override
+    public <T> Stream<T> fromBytesEach( ModuleDescriptor module, Class<T> type, Iterable<byte[]> states )
+    {
+        return fromBytesEach( module, valueTypeOf( module, type ), states );
+    }
+
+    @Override
+    public <T> Stream<T> fromBytesEach( ModuleDescriptor module, Class<T> type, byte[]... states )
+    {
+        return fromBytesEach( module, valueTypeOf( module, type ), states );
+    }
+
+    private ValueType valueTypeOf( ModuleDescriptor module, Class<?> type )
+    {
+        // TODO Remove (ModuleSpi) cast
+        return ( (ModuleSpi) module.instance() ).valueTypeFactory().valueTypeOf( module, type );
+    }
+
+    protected final StatefulAssociationCompositeDescriptor statefulCompositeDescriptorFor( ModuleDescriptor module,
+                                                                                           String typeName )
+    {
+        StatefulAssociationCompositeDescriptor descriptor = null;
+        try
+        {
+            descriptor = module.valueDescriptor( typeName );
+        }
+        catch( AmbiguousTypeException ex ) { }
+        if( descriptor == null )
+        {
+            try
+            {
+                descriptor = module.entityDescriptor( typeName );
+            }
+            catch( AmbiguousTypeException ex ) { }
+        }
+        return descriptor;
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractSerializer.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractSerializer.java
new file mode 100644
index 0000000..3269adb
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractSerializer.java
@@ -0,0 +1,154 @@
+/*
+ *  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.polygene.spi.serialization;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.serialization.Serializer;
+
+/**
+ * Base Serializer.
+ *
+ * Provides default implementations for convenience API methods.
+ *
+ * See {@link AbstractDeserializer}.
+ */
+public abstract class AbstractSerializer implements Serializer
+{
+    @Override
+    public void serialize( Writer writer, @Optional Object object )
+    {
+        serialize( Options.DEFAULT, writer, object );
+    }
+
+    @Override
+    public void serialize( OutputStream output, @Optional Object object )
+    {
+        serialize( Options.DEFAULT, output, object );
+    }
+
+    @Override
+    public String serialize( Options options, @Optional Object object )
+    {
+        StringWriter writer = new StringWriter();
+        serialize( options, writer, object );
+        return writer.toString();
+    }
+
+    @Override
+    public String serialize( @Optional Object object )
+    {
+        return serialize( Options.DEFAULT, object );
+    }
+
+    @Override
+    public <T> Function<T, String> serializeFunction( Options options )
+    {
+        return object -> serialize( options, object );
+    }
+
+    @Override
+    public <T> Function<T, String> serializeFunction()
+    {
+        return object -> serialize( Options.DEFAULT, object );
+    }
+
+    @Override
+    public Stream<String> serializeEach( Options options, Iterable<Object> objects )
+    {
+        return StreamSupport.stream( objects.spliterator(), false )
+                            .map( object -> serialize( options, object ) );
+    }
+
+    @Override
+    public Stream<String> serializeEach( Iterable<Object> objects )
+    {
+        return StreamSupport.stream( objects.spliterator(), false )
+                            .map( object -> serialize( Options.DEFAULT, object ) );
+    }
+
+    @Override
+    public Stream<String> serializeEach( Options options, Object... objects )
+    {
+        return Stream.of( objects ).map( object -> serialize( options, object ) );
+    }
+
+    @Override
+    public Stream<String> serializeEach( Object... objects )
+    {
+        return Stream.of( objects ).map( object -> serialize( Options.DEFAULT, object ) );
+    }
+
+    @Override
+    public byte[] toBytes( Options options, @Optional Object object )
+    {
+        ByteArrayOutputStream output = new ByteArrayOutputStream();
+        serialize( options, output, object );
+        return output.toByteArray();
+    }
+
+    @Override
+    public byte[] toBytes( @Optional Object object )
+    {
+        return toBytes( Options.DEFAULT, object );
+    }
+
+    @Override
+    public <T> Function<T, byte[]> toBytesFunction( Options options )
+    {
+        return object -> toBytes( options, object );
+    }
+
+    @Override
+    public <T> Function<T, byte[]> toBytesFunction()
+    {
+        return object -> toBytes( Options.DEFAULT, object );
+    }
+
+    @Override
+    public Stream<byte[]> toBytesEach( Options options, Iterable<Object> objects )
+    {
+        return StreamSupport.stream( objects.spliterator(), false )
+                            .map( object -> toBytes( options, object ) );
+    }
+
+    @Override
+    public Stream<byte[]> toBytesEach( Iterable<Object> objects )
+    {
+        return StreamSupport.stream( objects.spliterator(), false )
+                            .map( object -> toBytes( Options.DEFAULT, object ) );
+    }
+
+    @Override
+    public Stream<byte[]> toBytesEach( Options options, Object... objects )
+    {
+        return Stream.of( objects ).map( object -> toBytes( options, object ) );
+    }
+
+    @Override
+    public Stream<byte[]> toBytesEach( Object... objects )
+    {
+        return Stream.of( objects ).map( object -> toBytes( Options.DEFAULT, object ) );
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractTextDeserializer.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractTextDeserializer.java
new file mode 100644
index 0000000..f61db14
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractTextDeserializer.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.spi.serialization;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ValueType;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+// START SNIPPET: text
+/**
+ * Base Text Deserializer.
+ *
+ * Implementations work on Strings, this base deserializer decode bytes in UTF-8 to produce strings.
+ *
+ * See {@link AbstractTextSerializer}.
+ */
+public abstract class AbstractTextDeserializer extends AbstractDeserializer
+// END SNIPPET: text
+{
+    @Override
+    public <T> T deserialize( ModuleDescriptor module, ValueType valueType, InputStream state )
+    {
+        return deserialize( module, valueType, new InputStreamReader( state, UTF_8 ) );
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractTextSerializer.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractTextSerializer.java
new file mode 100644
index 0000000..aa9821d
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractTextSerializer.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.polygene.spi.serialization;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.StringWriter;
+import java.io.UncheckedIOException;
+import org.apache.polygene.api.common.Optional;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+// START SNIPPET: text
+/**
+ * Base Text Serializer.
+ *
+ * Implementations work on Strings, this base serializer encode these strings in UTF-8 to produce bytes.
+ *
+ * See {@link AbstractTextDeserializer}.
+ */
+public abstract class AbstractTextSerializer extends AbstractSerializer
+// END SNIPPET: text
+{
+    public void serialize( Options options, OutputStream output, @Optional Object object )
+    {
+        try
+        {
+            StringWriter writer = new StringWriter();
+            serialize( options, writer, object );
+            output.write( writer.toString().getBytes( UTF_8 ) );
+        }
+        catch( IOException ex )
+        {
+            throw new UncheckedIOException( ex );
+        }
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/BuiltInConverters.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/BuiltInConverters.java
new file mode 100644
index 0000000..0c1b774
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/BuiltInConverters.java
@@ -0,0 +1,256 @@
+/*
+ *  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.polygene.spi.serialization;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.Period;
+import java.time.ZonedDateTime;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.serialization.Converter;
+import org.apache.polygene.api.serialization.Converters;
+import org.apache.polygene.api.type.ValueType;
+
+/**
+ * Built-in serialization converters.
+ *
+ * Mixin for {@link org.apache.polygene.api.serialization.Serialization} implementations that provides built-in
+ * {@link Converter}s for the following types:
+ *
+ * <ul>
+ *     <li>{@link Identity}</li>
+ *     <li>{@link EntityReference}</li>
+ *     <li>{@link BigDecimal}</li>
+ *     <li>{@link BigInteger}</li>
+ *     <li>{@link Instant}</li>
+ *     <li>{@link ZonedDateTime}</li>
+ *     <li>{@link OffsetDateTime}</li>
+ *     <li>{@link LocalDateTime}</li>
+ *     <li>{@link LocalDate}</li>
+ *     <li>{@link LocalTime}</li>
+ *     <li>{@link Duration}</li>
+ *     <li>{@link Period}</li>
+ * </ul>
+ *
+ * Note that this does not include {@link String} nor primitive values and their boxed counterparts.
+ * {@literal Serialization} implementations must handle those.
+ */
+@Mixins( BuiltInConverters.Mixin.class )
+public interface BuiltInConverters
+{
+    void registerBuiltInConverters( Converters converters );
+
+    class Mixin implements BuiltInConverters
+    {
+        @Override
+        public void registerBuiltInConverters( Converters converters )
+        {
+            // Polygene types
+            converters.registerConverter( ValueType.IDENTITY, new IdentityConverter() );
+            converters.registerConverter( ValueType.ENTITY_REFERENCE, new EntityReferenceConverter() );
+
+            // Big numbers types
+            converters.registerConverter( ValueType.BIG_DECIMAL, new BigDecimalConverter() );
+            converters.registerConverter( ValueType.BIG_INTEGER, new BigIntegerConverter() );
+
+            // Date types
+            converters.registerConverter( ValueType.INSTANT, new InstantConverter() );
+            converters.registerConverter( ValueType.ZONED_DATE_TIME, new ZonedDateTimeConverter() );
+            converters.registerConverter( ValueType.OFFSET_DATE_TIME, new OffsetDateTimeConverter() );
+            converters.registerConverter( ValueType.LOCAL_DATE_TIME, new LocalDateTimeConverter() );
+            converters.registerConverter( ValueType.LOCAL_DATE, new LocalDateConverter() );
+            converters.registerConverter( ValueType.LOCAL_TIME, new LocalTimeConverter() );
+            converters.registerConverter( ValueType.DURATION, new DurationConverter() );
+            converters.registerConverter( ValueType.PERIOD, new PeriodConverter() );
+        }
+
+        private static abstract class ToStringConverter<T> implements Converter<T>
+        {
+            @Override
+            public String toString( T object )
+            {
+                return object.toString();
+            }
+        }
+
+        private static class IdentityConverter extends ToStringConverter<Identity>
+        {
+            @Override
+            public Class<Identity> type()
+            {
+                return Identity.class;
+            }
+
+            @Override
+            public Identity fromString( String string )
+            {
+                return StringIdentity.fromString( string );
+            }
+        }
+
+        private static class EntityReferenceConverter extends ToStringConverter<EntityReference>
+        {
+            @Override
+            public Class<EntityReference> type()
+            {
+                return EntityReference.class;
+            }
+
+            @Override
+            public EntityReference fromString( String string )
+            {
+                return EntityReference.parseEntityReference( string );
+            }
+        }
+
+        private static class BigDecimalConverter extends ToStringConverter<BigDecimal>
+        {
+            @Override
+            public Class<BigDecimal> type()
+            {
+                return BigDecimal.class;
+            }
+
+            @Override
+            public BigDecimal fromString( String string )
+            {
+                return new BigDecimal( string );
+            }
+        }
+
+        private static class BigIntegerConverter extends ToStringConverter<BigInteger>
+        {
+            @Override
+            public Class<BigInteger> type()
+            {
+                return BigInteger.class;
+            }
+
+            @Override
+            public BigInteger fromString( String string )
+            {
+                return new BigInteger( string );
+            }
+        }
+
+        private static class PeriodConverter extends ToStringConverter<Period>
+        {
+            @Override
+            public Class<Period> type() { return Period.class; }
+
+            @Override
+            public Period fromString( String string )
+            {
+                return Period.parse( string );
+            }
+        }
+
+        private static class DurationConverter extends ToStringConverter<Duration>
+        {
+            @Override
+            public Class<Duration> type() { return Duration.class; }
+
+            @Override
+            public Duration fromString( String string )
+            {
+                return Duration.parse( string );
+            }
+        }
+
+        private static class LocalTimeConverter extends ToStringConverter<LocalTime>
+        {
+            @Override
+            public Class<LocalTime> type() { return LocalTime.class; }
+
+            @Override
+            public LocalTime fromString( String string )
+            {
+                return LocalTime.parse( string );
+            }
+        }
+
+        private static class LocalDateConverter extends ToStringConverter<LocalDate>
+        {
+            @Override
+            public Class<LocalDate> type() { return LocalDate.class; }
+
+            @Override
+            public LocalDate fromString( String string )
+            {
+                return LocalDate.parse( string );
+            }
+        }
+
+        private static class LocalDateTimeConverter extends ToStringConverter<LocalDateTime>
+        {
+            @Override
+            public Class<LocalDateTime> type() { return LocalDateTime.class; }
+
+            @Override
+            public LocalDateTime fromString( String string )
+            {
+                return LocalDateTime.parse( string );
+            }
+        }
+
+        private static class OffsetDateTimeConverter extends ToStringConverter<OffsetDateTime>
+        {
+            @Override
+            public Class<OffsetDateTime> type() { return OffsetDateTime.class; }
+
+            @Override
+            public OffsetDateTime fromString( String string )
+            {
+                return OffsetDateTime.parse( string );
+            }
+        }
+
+        private static class ZonedDateTimeConverter extends ToStringConverter<ZonedDateTime>
+        {
+            @Override
+            public Class<ZonedDateTime> type() { return ZonedDateTime.class; }
+
+            @Override
+            public ZonedDateTime fromString( String string )
+            {
+                return ZonedDateTime.parse( string );
+            }
+        }
+
+        private static class InstantConverter extends ToStringConverter<Instant>
+        {
+            @Override
+            public Class<Instant> type() { return Instant.class; }
+
+            @Override
+            public Instant fromString( String string )
+            {
+                return Instant.parse( string );
+            }
+        }
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/JsonDeserializer.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/JsonDeserializer.java
new file mode 100644
index 0000000..61a39c9
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/JsonDeserializer.java
@@ -0,0 +1,83 @@
+/*
+ *  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.polygene.spi.serialization;
+
+import java.util.function.Function;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import javax.json.JsonValue;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.serialization.Deserializer;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.spi.module.ModuleSpi;
+
+/**
+ * {@literal javax.json} deserializer.
+ */
+public interface JsonDeserializer extends Deserializer
+{
+    <T> T fromJson( ModuleDescriptor module, ValueType valueType, @Optional JsonValue state );
+
+    default <T> Function<JsonValue, T> fromJsonFunction( ModuleDescriptor module, ValueType valueType )
+    {
+        return state -> fromJson( module, valueType, state );
+    }
+
+    default <T> Stream<T> fromJsonEach( ModuleDescriptor module, ValueType valueType, Stream<JsonValue> states )
+    {
+        return states.map( fromJsonFunction( module, valueType ) );
+    }
+
+    default <T> Stream<T> fromJsonEach( ModuleDescriptor module, ValueType valueType, Iterable<JsonValue> states )
+    {
+        return fromJsonEach( module, valueType, StreamSupport.stream( states.spliterator(), false ) );
+    }
+
+    default <T> Stream<T> fromJsonEach( ModuleDescriptor module, ValueType valueType, JsonValue... states )
+    {
+        return fromJsonEach( module, valueType, Stream.of( states ) );
+    }
+
+    default <T> T fromJson( ModuleDescriptor module, Class<T> type, @Optional JsonValue state )
+    {
+        // TODO Remove (ModuleSpi) cast
+        ValueType valueType = ( (ModuleSpi) module.instance() ).valueTypeFactory().valueTypeOf( module, type );
+        return fromJson( module, valueType, state );
+    }
+
+    default <T> Function<JsonValue, T> fromJson( ModuleDescriptor module, Class<T> type )
+    {
+        return state -> fromJson( module, type, state );
+    }
+
+    default <T> Stream<T> fromJsonEach( ModuleDescriptor module, Class<T> valueType, Stream<JsonValue> states )
+    {
+        return states.map( fromJson( module, valueType ) );
+    }
+
+    default <T> Stream<T> fromJsonEach( ModuleDescriptor module, Class<T> valueType, Iterable<JsonValue> states )
+    {
+        return fromJsonEach( module, valueType, StreamSupport.stream( states.spliterator(), false ) );
+    }
+
+    default <T> Stream<T> fromJsonEach( ModuleDescriptor module, Class<T> valueType, JsonValue... states )
+    {
+        return fromJsonEach( module, valueType, Stream.of( states ) );
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/JsonSerialization.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/JsonSerialization.java
new file mode 100644
index 0000000..f41078b
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/JsonSerialization.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.spi.serialization;
+
+import org.apache.polygene.api.serialization.Serialization;
+
+/**
+ * {@literal javax.json} serialization.
+ */
+public interface JsonSerialization extends Serialization, JsonSerializer, JsonDeserializer
+{
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/JsonSerializer.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/JsonSerializer.java
new file mode 100644
index 0000000..956b591
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/JsonSerializer.java
@@ -0,0 +1,78 @@
+/*
+ *  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.polygene.spi.serialization;
+
+import java.util.function.Function;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import javax.json.JsonValue;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.serialization.Serializer;
+
+/**
+ * {@literal javax.json} serializer.
+ */
+public interface JsonSerializer extends Serializer
+{
+    <T> Function<T, JsonValue> toJsonFunction( Options options );
+
+    default <T> Function<T, JsonValue> toJsonFunction()
+    {
+        return object -> toJsonFunction( Options.DEFAULT ).apply( object );
+    }
+
+    default JsonValue toJson( Options options, @Optional Object object )
+    {
+        return toJsonFunction( options ).apply( object );
+    }
+
+    default JsonValue toJson( @Optional Object object )
+    {
+        return toJsonFunction( Options.DEFAULT ).apply( object );
+    }
+
+    default <T> Stream<JsonValue> toJsonEach( Options options, Stream<T> objects )
+    {
+        return objects.map( toJsonFunction( options ) );
+    }
+
+    default <T> Stream<JsonValue> toJsonEach( Options options, Iterable<T> objects )
+    {
+        return toJsonEach( options, StreamSupport.stream( objects.spliterator(), false ) );
+    }
+
+    default <T> Stream<JsonValue> toJsonEach( Options options, Object... objects )
+    {
+        return toJsonEach( options, Stream.of( objects ) );
+    }
+
+    default <T> Stream<JsonValue> toJsonEach( Stream<T> objects )
+    {
+        return objects.map( toJsonFunction( Options.DEFAULT ) );
+    }
+
+    default <T> Stream<JsonValue> toJsonEach( Iterable<T> objects )
+    {
+        return toJsonEach( Options.DEFAULT, StreamSupport.stream( objects.spliterator(), false ) );
+    }
+
+    default <T> Stream<JsonValue> toJsonEach( Object... objects )
+    {
+        return toJsonEach( Options.DEFAULT, Stream.of( objects ) );
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/SerializationSettings.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/SerializationSettings.java
new file mode 100644
index 0000000..fd33629
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/SerializationSettings.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.spi.serialization;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.apache.polygene.api.serialization.Converter;
+import org.apache.polygene.api.type.ValueType;
+
+/**
+ * Serialization Settings.
+ *
+ * Serialization implementations might extend this with additional specialized settings.
+ *
+ * @param <SettingsType> Specialization type of SerializationSettings for a fluent usage
+ */
+public class SerializationSettings<SettingsType extends SerializationSettings>
+{
+    public static final SerializationSettings DEFAULT = new SerializationSettings();
+
+    public static SerializationSettings orDefault( SerializationSettings settings )
+    {
+        return settings != null ? settings : DEFAULT;
+    }
+
+    private final Map<ValueType, Converter<Object>> converters = new LinkedHashMap<>();
+
+    public final Map<ValueType, Converter<?>> getConverters()
+    {
+        return Collections.unmodifiableMap( converters );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    public final SettingsType withConverter( ValueType valueType, Converter<Object> adapter )
+    {
+        converters.put( valueType, adapter );
+        return (SettingsType) this;
+    }
+
+    public final SettingsType withConverter( Converter<Object> adapter )
+    {
+        return withConverter( ValueType.of( adapter.type() ), adapter );
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/XmlDeserializer.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/XmlDeserializer.java
new file mode 100644
index 0000000..cc5ddc6
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/XmlDeserializer.java
@@ -0,0 +1,83 @@
+/*
+ *  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.polygene.spi.serialization;
+
+import java.util.function.Function;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.serialization.Deserializer;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.spi.module.ModuleSpi;
+import org.w3c.dom.Node;
+
+/**
+ * {@literal javax.xml} deserializer.
+ */
+public interface XmlDeserializer extends Deserializer
+{
+    <T> T fromXml( ModuleDescriptor module, ValueType valueType, @Optional Node state );
+
+    default <T> Function<Node, T> fromXmlFunction( ModuleDescriptor module, ValueType valueType )
+    {
+        return state -> fromXml( module, valueType, state );
+    }
+
+    default <T> Stream<T> fromXmlEach( ModuleDescriptor module, ValueType valueType, Stream<Node> states )
+    {
+        return states.map( fromXmlFunction( module, valueType ) );
+    }
+
+    default <T> Stream<T> fromXmlEach( ModuleDescriptor module, ValueType valueType, Iterable<Node> states )
+    {
+        return fromXmlEach( module, valueType, StreamSupport.stream( states.spliterator(), false ) );
+    }
+
+    default <T> Stream<T> fromXmlEach( ModuleDescriptor module, ValueType valueType, Node... states )
+    {
+        return fromXmlEach( module, valueType, Stream.of( states ) );
+    }
+
+    default <T> T fromXml( ModuleDescriptor module, Class<T> type, @Optional Node state )
+    {
+        // TODO Remove (ModuleSpi) cast
+        ValueType valueType = ( (ModuleSpi) module.instance() ).valueTypeFactory().valueTypeOf( module, type );
+        return fromXml( module, valueType, state );
+    }
+
+    default <T> Function<Node, T> fromXml( ModuleDescriptor module, Class<T> type )
+    {
+        return state -> fromXml( module, type, state );
+    }
+
+    default <T> Stream<T> fromXmlEach( ModuleDescriptor module, Class<T> valueType, Stream<Node> states )
+    {
+        return states.map( fromXml( module, valueType ) );
+    }
+
+    default <T> Stream<T> fromXmlEach( ModuleDescriptor module, Class<T> valueType, Iterable<Node> states )
+    {
+        return fromXmlEach( module, valueType, StreamSupport.stream( states.spliterator(), false ) );
+    }
+
+    default <T> Stream<T> fromXmlEach( ModuleDescriptor module, Class<T> valueType, Node... states )
+    {
+        return fromXmlEach( module, valueType, Stream.of( states ) );
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/XmlSerialization.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/XmlSerialization.java
new file mode 100644
index 0000000..c4b7f37
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/XmlSerialization.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.spi.serialization;
+
+import org.apache.polygene.api.serialization.Serialization;
+
+/**
+ * {@literal javax.xml} serialization.
+ */
+public interface XmlSerialization extends Serialization, XmlSerializer, XmlDeserializer
+{
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/XmlSerializer.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/XmlSerializer.java
new file mode 100644
index 0000000..007f731
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/XmlSerializer.java
@@ -0,0 +1,78 @@
+/*
+ *  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.polygene.spi.serialization;
+
+import java.util.function.Function;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.serialization.Serializer;
+import org.w3c.dom.Document;
+
+/**
+ * {@literal javax.xml} serializer.
+ */
+public interface XmlSerializer extends Serializer
+{
+    <T> Function<T, Document> toXmlFunction( Options options );
+
+    default <T> Function<T, Document> toXmlFunction()
+    {
+        return object -> toXmlFunction( Options.DEFAULT ).apply( object );
+    }
+
+    default Document toXml( Options options, @Optional Object object )
+    {
+        return toXmlFunction( options ).apply( object );
+    }
+
+    default Document toXml( @Optional Object object )
+    {
+        return toXmlFunction( Options.DEFAULT ).apply( object );
+    }
+
+    default <T> Stream<Document> toXmlEach( Options options, Stream<T> objects )
+    {
+        return objects.map( toXmlFunction( options ) );
+    }
+
+    default <T> Stream<Document> toXmlEach( Options options, Iterable<T> objects )
+    {
+        return toXmlEach( options, StreamSupport.stream( objects.spliterator(), false ) );
+    }
+
+    default <T> Stream<Document> toXmlEach( Options options, Object... objects )
+    {
+        return toXmlEach( options, Stream.of( objects ) );
+    }
+
+    default <T> Stream<Document> toXmlEach( Stream<T> objects )
+    {
+        return objects.map( toXmlFunction( Options.DEFAULT ) );
+    }
+
+    default <T> Stream<Document> toXmlEach( Iterable<T> objects )
+    {
+        return toXmlEach( Options.DEFAULT, StreamSupport.stream( objects.spliterator(), false ) );
+    }
+
+    default <T> Stream<Document> toXmlEach( Object... objects )
+    {
+        return toXmlEach( Options.DEFAULT, Stream.of( objects ) );
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/package.html b/core/spi/src/main/java/org/apache/polygene/spi/serialization/package.html
new file mode 100644
index 0000000..8af1964
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/package.html
@@ -0,0 +1,68 @@
+<!--
+  ~  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.
+  -->
+<html>
+<body>
+<h2>Serialization SPI.</h2>
+<p>
+    This package contains specialized serialization APIs for the {@literal JSON} and {@literal XML} formats.
+    See {@link org.apache.polygene.spi.serialization.JsonSerialization}, based on {@literal javax.json},
+    and {@link org.apache.polygene.spi.serialization.XmlSerialization}, based on {@literal javax.xml}.
+</p>
+<p>
+    This package also contains base implementations, mixins and helpers for serialization API implementations:
+</p>
+<p><strong>Base implementations</strong></p>
+<ul>
+    <li>
+        Use {@link org.apache.polygene.spi.serialization.AbstractTextSerializer}
+        and {@link org.apache.polygene.spi.serialization.AbstractTextDeserializer}
+        as a basis to implement the serialization API for text representations.
+    </li>
+    <li>
+        Use {@link org.apache.polygene.spi.serialization.AbstractBinarySerializer}
+        and {@link org.apache.polygene.spi.serialization.AbstractBinaryDeserializer}
+        as a basis to implement the serialization API for binary representations.
+    </li>
+    <li>
+        Use {@link org.apache.polygene.spi.serialization.AbstractSerializer}
+        and {@link org.apache.polygene.spi.serialization.AbstractDeserializer}
+        if you need to handle text/binary conversion yourself.
+    </li>
+</ul>
+<p>
+    <strong>Mixins</strong>
+</p>
+<ul>
+    <li>
+        {@link org.apache.polygene.spi.serialization.BuiltInConverters} provides built-in
+        {@link org.apache.polygene.api.serialization.Converter}s for types supported by the Polygene Runtime.
+    </li>
+</ul>
+<p>
+    <strong>Helpers</strong>
+</p>
+<ul>
+    <li>
+        {@link org.apache.polygene.spi.serialization.SerializationSettings}
+        can be used to register custom Converters at assembly time.
+        Serialization implementations might extend this with additional specialized settings,
+        see their respective documentation for details.
+    </li>
+</ul>
+</body>
+</html>
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/type/ValueTypeFactory.java b/core/spi/src/main/java/org/apache/polygene/spi/type/ValueTypeFactory.java
new file mode 100644
index 0000000..1c18659
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/type/ValueTypeFactory.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.spi.type;
+
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ValueType;
+
+public interface ValueTypeFactory
+{
+    ValueType valueTypeOf( ModuleDescriptor module, Object object );
+
+    ValueType valueTypeOf( ModuleDescriptor module, Class<?> type );
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/util/ArrayIterable.java b/core/spi/src/main/java/org/apache/polygene/spi/util/ArrayIterable.java
new file mode 100644
index 0000000..71f8748
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/util/ArrayIterable.java
@@ -0,0 +1,75 @@
+/*
+ *  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.polygene.spi.util;
+
+import java.lang.reflect.Array;
+import java.util.Iterator;
+
+/**
+ * Iterate over arrays, both primitive arrays and Object[].
+ */
+public class ArrayIterable implements Iterable<Object>
+{
+    private final Object array;
+
+    public ArrayIterable( final Object array )
+    {
+        if( !array.getClass().isArray() )
+        {
+            throw new IllegalArgumentException( array + " is not an array" );
+        }
+        this.array = array;
+    }
+
+    @Override
+    public Iterator<Object> iterator()
+    {
+        return new ArrayIterator( array );
+    }
+
+    private class ArrayIterator implements Iterator<Object>
+    {
+        private final Object array;
+        private int currentIndex = 0;
+
+        private ArrayIterator( Object array )
+        {
+            this.array = array;
+        }
+
+        @Override
+        public boolean hasNext()
+        {
+            return currentIndex < Array.getLength( array );
+        }
+
+        @Override
+        public Object next()
+        {
+            return Array.get( array, currentIndex++ );
+        }
+
+        @Override
+        public void remove()
+        {
+            throw new UnsupportedOperationException( "cannot remove items from an array" );
+        }
+    }
+}
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/util/package.html b/core/spi/src/main/java/org/apache/polygene/spi/util/package.html
new file mode 100644
index 0000000..a6ad50b
--- /dev/null
+++ b/core/spi/src/main/java/org/apache/polygene/spi/util/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SPI Utilities.</h2>
+    </body>
+</html>
diff --git a/core/spi/src/main/java/org/qi4j/entitystore/memory/MemoryEntityStoreService.java b/core/spi/src/main/java/org/qi4j/entitystore/memory/MemoryEntityStoreService.java
deleted file mode 100644
index f5b4db1..0000000
--- a/core/spi/src/main/java/org/qi4j/entitystore/memory/MemoryEntityStoreService.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.memory;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.spi.entitystore.BackupRestore;
-import org.qi4j.spi.entitystore.ConcurrentModificationCheckConcern;
-import org.qi4j.spi.entitystore.EntityStateVersions;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.StateChangeNotificationConcern;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreActivation;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreMixin;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * In-memory EntityStore service.
- * <p>Useful for testing and non-persistent entities.</p>
- * <p>Based on {@link JSONMapEntityStoreMixin}</p>
- */
-@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
-@Mixins( { JSONMapEntityStoreMixin.class, MemoryMapEntityStoreMixin.class } )
-public interface MemoryEntityStoreService
-    extends EntityStore, EntityStateVersions, BackupRestore, StateStore, ServiceComposite, JSONMapEntityStoreActivation
-{
-}
diff --git a/core/spi/src/main/java/org/qi4j/entitystore/memory/MemoryMapEntityStoreMixin.java b/core/spi/src/main/java/org/qi4j/entitystore/memory/MemoryMapEntityStoreMixin.java
deleted file mode 100644
index d031fb5..0000000
--- a/core/spi/src/main/java/org/qi4j/entitystore/memory/MemoryMapEntityStoreMixin.java
+++ /dev/null
@@ -1,241 +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.qi4j.entitystore.memory;
-
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.HashMap;
-import java.util.Map;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.json.JSONTokener;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.spi.entitystore.BackupRestore;
-import org.qi4j.spi.entitystore.EntityAlreadyExistsException;
-import org.qi4j.spi.entitystore.EntityNotFoundException;
-import org.qi4j.spi.entitystore.EntityStoreException;
-import org.qi4j.spi.entitystore.helpers.JSONKeys;
-import org.qi4j.spi.entitystore.helpers.MapEntityStore;
-import org.qi4j.spi.entitystore.helpers.MapEntityStoreActivation;
-
-/**
- * In-memory implementation of MapEntityStore.
- */
-public class MemoryMapEntityStoreMixin
-    implements MapEntityStore, BackupRestore, MapEntityStoreActivation
-{
-    private final Map<EntityReference, String> store;
-
-    public MemoryMapEntityStoreMixin()
-    {
-        store = new HashMap<>();
-    }
-
-    @Override
-    public void activateMapEntityStore()
-        throws Exception
-    {
-        // NOOP
-    }
-
-    public boolean contains( EntityReference entityReference, EntityDescriptor descriptor )
-        throws EntityStoreException
-    {
-        return store.containsKey( entityReference );
-    }
-
-    @Override
-    public Reader get( EntityReference entityReference )
-        throws EntityStoreException
-    {
-        String state = store.get( entityReference );
-        if( state == null )
-        {
-            throw new EntityNotFoundException( entityReference );
-        }
-
-        return new StringReader( state );
-    }
-
-    @Override
-    public void applyChanges( MapEntityStore.MapChanges changes )
-        throws IOException
-    {
-        changes.visitMap( new MemoryMapChanger() );
-    }
-
-    @Override
-    public Input<Reader, IOException> entityStates()
-    {
-        return new Input<Reader, IOException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super Reader, ReceiverThrowableType> output )
-                throws IOException, ReceiverThrowableType
-            {
-                output.receiveFrom( new Sender<Reader, IOException>()
-                {
-                    @Override
-                    public <ReceiverThrowableType extends Throwable> void sendTo( Receiver<? super Reader, ReceiverThrowableType> receiver )
-                        throws ReceiverThrowableType, IOException
-                    {
-                        for( String state : store.values() )
-                        {
-                            receiver.receive( new StringReader( state ) );
-                        }
-                    }
-                } );
-            }
-        };
-    }
-
-    @Override
-    public Input<String, IOException> backup()
-    {
-        return new Input<String, IOException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super String, ReceiverThrowableType> output )
-                throws IOException, ReceiverThrowableType
-            {
-                output.receiveFrom( new Sender<String, IOException>()
-                {
-                    @Override
-                    public <ReceiverThrowableType extends Throwable> void sendTo( Receiver<? super String, ReceiverThrowableType> receiver )
-                        throws ReceiverThrowableType, IOException
-                    {
-                        for( String state : store.values() )
-                        {
-                            receiver.receive( state );
-                        }
-                    }
-                } );
-            }
-        };
-    }
-
-    @Override
-    public Output<String, IOException> restore()
-    {
-        return new Output<String, IOException>()
-        {
-            @Override
-            public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends String, SenderThrowableType> sender )
-                throws IOException, SenderThrowableType
-            {
-                store.clear();
-
-                try
-                {
-                    sender.sendTo( new Receiver<String, IOException>()
-                    {
-                        @Override
-                        public void receive( String item )
-                            throws IOException
-                        {
-                            try
-                            {
-                                JSONTokener tokener = new JSONTokener( item );
-                                JSONObject entity = (JSONObject) tokener.nextValue();
-                                String id = entity.getString( JSONKeys.IDENTITY );
-                                store.put( new EntityReference( id ), item );
-                            }
-                            catch( JSONException e )
-                            {
-                                throw new IOException( e );
-                            }
-                        }
-                    } );
-                }
-                catch( IOException e )
-                {
-                    store.clear();
-                    throw e;
-                }
-            }
-        };
-    }
-
-    private class MemoryMapChanger
-        implements MapChanger
-    {
-        @Override
-        public Writer newEntity( final EntityReference ref, EntityDescriptor descriptor )
-        {
-            return new StringWriter( 1000 )
-            {
-                @Override
-                public void close()
-                    throws IOException
-                {
-                    super.close();
-                    String old = store.put( ref, toString() );
-                    if( old != null )
-                    {
-                        store.put( ref, old );
-                        throw new EntityAlreadyExistsException( ref );
-                    }
-                }
-            };
-        }
-
-        @Override
-        public Writer updateEntity( final EntityReference ref, EntityDescriptor descriptor )
-            throws IOException
-        {
-            return new StringWriter( 1000 )
-            {
-                @Override
-                public void close()
-                    throws IOException
-                {
-                    super.close();
-                    String old = store.put( ref, toString() );
-                    if( old == null )
-                    {
-                        store.remove( ref );
-                        throw new EntityNotFoundException( ref );
-                    }
-                }
-            };
-        }
-
-        @Override
-        public void removeEntity( EntityReference ref, EntityDescriptor descriptor )
-            throws EntityNotFoundException
-        {
-            String state = store.remove( ref );
-            // Ignore if the entity didn't already exist, as that can happen if it is both created and removed
-            // within the same UnitOfWork.
-//            if( state == null )
-//            {
-//                throw new EntityNotFoundException( ref );
-//            }
-        }
-    }
-
-}
diff --git a/core/spi/src/main/java/org/qi4j/entitystore/memory/package.html b/core/spi/src/main/java/org/qi4j/entitystore/memory/package.html
deleted file mode 100644
index d907b6c..0000000
--- a/core/spi/src/main/java/org/qi4j/entitystore/memory/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>In-Memory EntityStore.</h2>
-    </body>
-</html>
diff --git a/core/spi/src/main/java/org/qi4j/spi/Qi4jSPI.java b/core/spi/src/main/java/org/qi4j/spi/Qi4jSPI.java
deleted file mode 100644
index eb44d6d..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/Qi4jSPI.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi;
-
-import java.util.Map;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.property.StateHolder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.spi.entity.EntityState;
-
-/**
- * Encapsulation of the Zest SPI. This is implemented by the runtime.
- */
-public interface Qi4jSPI
-    extends Qi4j
-{
-    StateHolder stateOf( TransientComposite composite );
-
-    AssociationStateHolder stateOf( EntityComposite composite );
-
-    AssociationStateHolder stateOf( ValueComposite composite );
-
-    // Entities
-    EntityState entityStateOf( EntityComposite composite );
-
-    /**
-     * Fetches the EntityReference without loading the referenced entity.
-     *
-     * @param assoc The Association for which we want to obtain the EntityReference
-     * @return The EntityReference of the given Association.
-     */
-    EntityReference entityReferenceOf( Association assoc );
-
-    /**
-     * Fetches the EntityReferences without loading the referenced entities.
-     *
-     * @param assoc The ManyAssociation for which we want to obtain the EntityReferences.
-     * @return An Iteranble of all the EntityReferences of the given ManyAssociation.
-     */
-    Iterable<EntityReference> entityReferenceOf( ManyAssociation assoc );
-
-    /**
-     * Fetches the EntityReferences without loading the referenced entities.
-     *
-     * @param assoc The NamedAssociation for which we want to obtain the EntityReference
-     * @return An Iteranble of Map.Entry with the name and EntityReference of the given NamedAssociation.
-     */
-    Iterable<Map.Entry<String,EntityReference>> entityReferenceOf( NamedAssociation assoc );
-
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/cache/Cache.java b/core/spi/src/main/java/org/qi4j/spi/cache/Cache.java
deleted file mode 100644
index 0db5f83..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/cache/Cache.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2010 Niclas Hedhman.
- *
- * Licensed  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.qi4j.spi.cache;
-
-/**
- * Interface to interact with Cache implementations.
- * The Cache interface has the simple put/get/remove method to make implementations very easy and straight forward.
- * The key is always a String, since it is intended to be used for the EntityComposite's identity, and not totally
- * generic.
- *
- * @param <T> The Value type to be stored in the cache.
- */
-public interface Cache<T>
-{
-    T get( String key );
-
-    T remove( String key );
-
-    void put( String key, T value );
-
-    boolean exists( String key );
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/cache/CachePool.java b/core/spi/src/main/java/org/qi4j/spi/cache/CachePool.java
deleted file mode 100644
index c4ee5ac..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/cache/CachePool.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2010 Niclas Hedhman.
- *
- * Licensed  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.qi4j.spi.cache;
-
-/**
- * A CachePool is a service that manages the Persistence Caches.
- * <p>
- * The CachePool is typically implemented as a Zest Extension, and is an optional extension in the persistence
- * subsystem of Zest. If a Cache Extension is not provided, caching will be turned off. However, since caching
- * operate on EntityStore level, and is an optional component at that, just because you have defined a Cache
- * Extension does not necessary mean that your system will use it. Check the EntityStore implementations for
- * details if they are Cache enabled. Most EntityStore implementations has this enabled, often via the MapEntityStore
- * and JSONMapEntityStore SPI.
- * </p>
- * <p>
- * NOTE: Make sure that there is a match between the fetchCache and returnCache methods, to ensure no memory leakage
- * occur. Also remember that if the reference count reaches zero, the CachePool will destroy the Cache as soon
- * as possible and a new fetchCache will return an empty one.
- * </p>
- */
-public interface CachePool
-{
-
-    /**
-     * Fetches a cache from the pool.
-     * If the cache does not exist already, then a new Cache should be created and returned. For each fetchCache()
-     * call, a reference count on the Cache must be increased.
-     *
-     * @param cacheId   The identity of the cache. If the same id is given as a previous fetch, the same cache will be
-     *                  returned.
-     * @param valueType
-     * @param <T>
-     *
-     * @return The cache fetched from the pool.
-     */
-    <T> Cache<T> fetchCache( String cacheId, Class<T> valueType );
-
-    /**
-     * Returns the cache back to the pool.
-     * The reference count for the cache must then be decreased and if the count reaches zero, the Cache should be
-     * destroyed and cleared from memory.
-     *
-     * @param cache The cache to return to the pool.
-     */
-    void returnCache( Cache<?> cache );
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/cache/NullCache.java b/core/spi/src/main/java/org/qi4j/spi/cache/NullCache.java
deleted file mode 100644
index e0a4b04..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/cache/NullCache.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2010 Niclas Hedhman.
- *
- * Licensed  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.qi4j.spi.cache;
-
-/**
- * Cache null object.
- */
-public final class NullCache<T>
-    implements Cache<T>
-{
-    @Override
-    public T get( String key )
-    {
-        return null;
-    }
-
-    @Override
-    public T remove( String key )
-    {
-        return null;
-    }
-
-    @Override
-    public void put( String key, T value )
-    {
-    }
-
-    @Override
-    public boolean exists( String key )
-    {
-        return false;
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/cache/package.html b/core/spi/src/main/java/org/qi4j/spi/cache/package.html
deleted file mode 100644
index c96994a..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/cache/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Cache SPI.</h2>
-    </body>
-</html>
diff --git a/core/spi/src/main/java/org/qi4j/spi/entity/EntityState.java b/core/spi/src/main/java/org/qi4j/spi/entity/EntityState.java
deleted file mode 100644
index 2e149ca..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entity/EntityState.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.spi.entity;
-
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-
-/**
- * State holder for Entities.
- */
-public interface EntityState
-{
-    /**
-     * Returns the identity of the entity that this EntityState represents.
-     *
-     * @return the identity of the entity that this EntityState represents.
-     */
-    EntityReference identity();
-
-    /**
-     * Version of the entity. This is managed by the EntityStore.
-     * <p>
-     * If the underlying EntityStore does not support versioning, then version
-     * must always be set to 0.
-     * </p>
-     * @return version of the entity
-     */
-    String version();
-
-    /**
-     * Last modified timestamp of the entity. This is managed by the EntityStore.
-     * <p>
-     * If the underlying EntityStore does not support timestamping, then last modified
-     * must always be set to the current time.
-     * </p>
-     * @return last modified timestamp of the entity, as defined by System.currentTimeMillis()
-     */
-    long lastModified();
-
-    /**
-     * Remove the entity represented by this EntityState when the unit of work is completed.
-     */
-    void remove();
-
-    /**
-     * The status of this EntityState
-     *
-     * @return the status
-     */
-    EntityStatus status();
-
-    boolean isAssignableTo( Class<?> type );
-
-    EntityDescriptor entityDescriptor();
-
-    Object propertyValueOf( QualifiedName stateName );
-
-    void setPropertyValue( QualifiedName stateName, Object json );
-
-    EntityReference associationValueOf( QualifiedName stateName );
-
-    void setAssociationValue( QualifiedName stateName, EntityReference newEntity );
-
-    ManyAssociationState manyAssociationValueOf( QualifiedName stateName );
-    
-    NamedAssociationState namedAssociationValueOf( QualifiedName stateName );
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entity/EntityStatus.java b/core/spi/src/main/java/org/qi4j/spi/entity/EntityStatus.java
deleted file mode 100644
index 192cfd7..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entity/EntityStatus.java
+++ /dev/null
@@ -1,31 +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.qi4j.spi.entity;
-
-/**
- * Status of entity. This is used in the default implementation
- * of EntityState
- */
-public enum EntityStatus
-{
-    NEW, // When the Entity has just been created in the UnitOfWork 
-    LOADED,  // When it has been previously created, and is loaded through the UnitOfWork
-    UPDATED, // When it has been previously loaded, and has been changed in the UnitOfWork
-    REMOVED // When the Entity has been removed in the UnitOfWork
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entity/ManyAssociationState.java b/core/spi/src/main/java/org/qi4j/spi/entity/ManyAssociationState.java
deleted file mode 100644
index 2b604ce..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entity/ManyAssociationState.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.entity;
-
-import org.qi4j.api.entity.EntityReference;
-
-/**
- * State holder for ManyAssociations. The actual state
- * can be eager-loaded or lazy-loaded. This is an implementation detail.
- */
-public interface ManyAssociationState
-    extends Iterable<EntityReference>
-{
-    int count();
-
-    boolean contains( EntityReference entityReference );
-
-    boolean add( int index, EntityReference entityReference );
-
-    boolean remove( EntityReference entityReference );
-
-    EntityReference get( int index );
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entity/NamedAssociationState.java b/core/spi/src/main/java/org/qi4j/spi/entity/NamedAssociationState.java
deleted file mode 100644
index 584feee..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entity/NamedAssociationState.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2011-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.spi.entity;
-
-import org.qi4j.api.entity.EntityReference;
-
-/**
- * State holder for NamedAssociations.
- * The actual state can be eager-loaded or lazy-loaded.
- * This is an implementation detail.
- * The Iterable&lt;String&gt; returns the names in the association set.
- */
-public interface NamedAssociationState
-    extends Iterable<String>
-{
-    int count();
-
-    boolean containsName( String name );
-
-    boolean put( String name, EntityReference entityReference );
-
-    boolean remove( String name );
-
-    EntityReference get( String name );
-
-    String nameOf( EntityReference entityReference );
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entity/QualifiedIdentity.java b/core/spi/src/main/java/org/qi4j/spi/entity/QualifiedIdentity.java
deleted file mode 100644
index 71defc5..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entity/QualifiedIdentity.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.entity;
-
-import java.io.Serializable;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.util.Classes;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * A Qualified Identity is the combination of the Composite type name and the identity of a specific
- * Entity instance. When stringified, these two are separated by the ":" character. Example:
- * <pre>
- * com.mycompany.mydomain.SomeEntity:123456
- * </pre>
- * where "com.mycompany.mydomain.SomeEntity" is the Composite type, and "123456" is the identity.
- */
-public final class QualifiedIdentity
-    implements Serializable
-{
-    public static QualifiedIdentity parseURI( String uri )
-    {
-        String str = uri.substring( "urn:qi4j:entity:".length() );
-        int idx = str.indexOf( "/" );
-        String type = str.substring( 0, idx ).replace( "-", "$" );
-        String identity = str.substring( idx + 1 );
-        return new QualifiedIdentity( identity, type );
-    }
-
-    public static QualifiedIdentity parseQualifiedIdentity( String id )
-    {
-        return new QualifiedIdentity( id );
-    }
-
-    public static QualifiedIdentity qualifiedIdentityOf( Object o )
-    {
-        return new QualifiedIdentity( (EntityComposite) o );
-    }
-
-    private static final long serialVersionUID = 1L;
-
-    // Associations who have been set to "null" should use this as the representation in the EntityState
-    public static final QualifiedIdentity NULL = new QualifiedIdentity( "null", "none" );
-
-    private String identity;
-    private String compositeType;
-
-    public QualifiedIdentity( EntityComposite entityComposite )
-    {
-        this( entityComposite.identity().get(), first( Qi4j.FUNCTION_DESCRIPTOR_FOR
-                                                           .map( entityComposite )
-                                                           .types() ).getName() );
-    }
-
-    public QualifiedIdentity( String identity, Class<?> clazz )
-    {
-        this.identity = identity;
-        this.compositeType = clazz.getName();
-    }
-
-    public QualifiedIdentity( String identity, String clazz )
-    {
-        this.identity = identity;
-        this.compositeType = clazz;
-    }
-
-    protected QualifiedIdentity( String qualifiedIdentity )
-    {
-        int separatorIndex = qualifiedIdentity.indexOf( ":" );
-        if( separatorIndex == -1 )
-        {
-            throw new IllegalArgumentException( "Supplied string is not a qualified identity: " + qualifiedIdentity );
-        }
-        this.compositeType = qualifiedIdentity.substring( 0, separatorIndex );
-        this.identity = qualifiedIdentity.substring( separatorIndex + 1 );
-    }
-
-    public final String identity()
-    {
-        return identity;
-    }
-
-    public final String type()
-    {
-        return compositeType;
-    }
-
-    public final String toURI()
-    {
-        return "urn:qi4j:entity:" + Classes.normalizeClassToURI( compositeType ) + "/" + identity;
-    }
-
-    @Override
-    @SuppressWarnings( "AccessingNonPublicFieldOfAnotherObject" )
-    public boolean equals( Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-        QualifiedIdentity that = (QualifiedIdentity) o;
-        return compositeType.equals( that.compositeType ) && identity.equals( that.identity );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        int result;
-        result = identity.hashCode();
-        result = 31 * result + compositeType.hashCode();
-        return result;
-    }
-
-    @Override
-    public String toString()
-    {
-        return compositeType + ":" + identity;
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entity/package.html b/core/spi/src/main/java/org/qi4j/spi/entity/package.html
deleted file mode 100644
index 2b9c206..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entity/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Entity SPI.</h2>
-    </body>
-</html>
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/BackupRestore.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/BackupRestore.java
deleted file mode 100644
index f777f45..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/BackupRestore.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2010, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.entitystore;
-
-import java.io.IOException;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-
-/**
- * Allow backups and restores of data in an EntityStore to be made
- */
-public interface BackupRestore
-{
-    /**
-     * Input that allows data from the entity store to be backed up.
-     *
-     * @return An Input instance containing the data to back up.
-     */
-    Input<String, IOException> backup();
-
-    /**
-     * Output that allows data to be restored from a backup.
-     *
-     * @return An Output instance to receive the restored data.
-     */
-    Output<String, IOException> restore();
-}
\ No newline at end of file
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/ConcurrentEntityStateModificationException.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/ConcurrentEntityStateModificationException.java
deleted file mode 100644
index 222105b..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/ConcurrentEntityStateModificationException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*  Copyright 2007 Niclas Hedhman.
- *
- * Licensed 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.qi4j.spi.entitystore;
-
-import java.util.Collection;
-import org.qi4j.api.entity.EntityReference;
-
-/**
- * This exception should be thrown if the EntityStore detects that the entities being saved have been changed
- * since they were created.
- */
-public class ConcurrentEntityStateModificationException
-    extends EntityStoreException
-{
-    private Collection<EntityReference> modifiedEntities;
-
-    public ConcurrentEntityStateModificationException( Collection<EntityReference> modifiedEntities )
-    {
-        super("Entities changed concurrently:" + modifiedEntities);
-        this.modifiedEntities = modifiedEntities;
-    }
-
-    public Collection<EntityReference> modifiedEntities()
-    {
-        return modifiedEntities;
-    }
-}
\ No newline at end of file
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/ConcurrentModificationCheckConcern.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/ConcurrentModificationCheckConcern.java
deleted file mode 100644
index 118389c..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/ConcurrentModificationCheckConcern.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.entitystore;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.module.ModuleSpi;
-
-/**
- * Concern that helps EntityStores do concurrent modification checks.
- * <p>
- * It caches the versions of state that it loads, and forgets them when
- * the state is committed. For normal operation this means that it does
- * not have to go down to the underlying store to get the current version.
- * Whenever there is a concurrent modification the store will most likely
- * have to check with the underlying store what the current version is.
- * </p>
- */
-public abstract class ConcurrentModificationCheckConcern
-    extends ConcernOf<EntityStore>
-    implements EntityStore
-{
-    @This
-    private EntityStateVersions versions;
-
-    @Structure
-    private Qi4j api;
-
-    @Override
-    public EntityStoreUnitOfWork newUnitOfWork( Usecase usecase, ModuleSpi module, long currentTime )
-    {
-        final EntityStoreUnitOfWork uow = next.newUnitOfWork( usecase, module, currentTime );
-        return new ConcurrentCheckingEntityStoreUnitOfWork( uow, api.dereference( versions ), module, currentTime );
-    }
-
-    private static class ConcurrentCheckingEntityStoreUnitOfWork
-        implements EntityStoreUnitOfWork
-    {
-        private final EntityStoreUnitOfWork uow;
-        private EntityStateVersions versions;
-        private ModuleSpi module;
-        private long currentTime;
-
-        private List<EntityState> loaded = new ArrayList<>();
-
-        private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
-
-        public ConcurrentCheckingEntityStoreUnitOfWork( EntityStoreUnitOfWork uow,
-                                                        EntityStateVersions versions,
-                                                        ModuleSpi module,
-                                                        long currentTime
-        )
-        {
-            this.uow = uow;
-            this.versions = versions;
-            this.module = module;
-            this.currentTime = currentTime;
-        }
-
-        @Override
-        public String identity()
-        {
-            return uow.identity();
-        }
-
-        @Override
-        public long currentTime()
-        {
-            return uow.currentTime();
-        }
-
-        @Override
-        public EntityState newEntityState( ModuleSpi module,
-                                           EntityReference anIdentity,
-                                           EntityDescriptor entityDescriptor
-        )
-            throws EntityStoreException
-        {
-            return uow.newEntityState( module, anIdentity, entityDescriptor );
-        }
-
-        @Override
-        public StateCommitter applyChanges()
-            throws EntityStoreException
-        {
-            lock.writeLock().lock();
-
-            try
-            {
-                versions.checkForConcurrentModification( loaded, module, currentTime );
-
-                final StateCommitter committer = uow.applyChanges();
-
-                return new StateCommitter()
-                {
-                    @Override
-                    public void commit()
-                    {
-                        committer.commit();
-                        versions.forgetVersions( loaded );
-
-                        lock.writeLock().unlock();
-                    }
-
-                    @Override
-                    public void cancel()
-                    {
-                        committer.cancel();
-                        versions.forgetVersions( loaded );
-
-                        lock.writeLock().unlock();
-                    }
-                };
-            }
-            catch( EntityStoreException e )
-            {
-                lock.writeLock().unlock();
-                throw e;
-            }
-        }
-
-        @Override
-        public void discard()
-        {
-            try
-            {
-                uow.discard();
-            }
-            finally
-            {
-                lock.writeLock().lock();
-
-                try
-                {
-                    versions.forgetVersions( loaded );
-                }
-                finally
-                {
-                    lock.writeLock().unlock();
-                }
-            }
-        }
-
-        @Override
-        public Usecase usecase()
-        {
-            return uow.usecase();
-        }
-
-        @SuppressWarnings( "DuplicateThrows" )
-        @Override
-        public EntityState entityStateOf( ModuleSpi module, EntityReference anIdentity )
-            throws EntityStoreException, EntityNotFoundException
-        {
-            lock.readLock().lock();
-
-            try
-            {
-                EntityState entityState = uow.entityStateOf( module, anIdentity );
-                versions.rememberVersion( entityState.identity(), entityState.version() );
-                loaded.add( entityState );
-                return entityState;
-            }
-            finally
-            {
-                lock.readLock().unlock();
-            }
-        }
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/DefaultEntityStoreUnitOfWork.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/DefaultEntityStoreUnitOfWork.java
deleted file mode 100644
index 1c1d794..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/DefaultEntityStoreUnitOfWork.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.entitystore;
-
-import java.util.HashMap;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.module.ModuleSpi;
-
-/**
- * Default EntityStore UnitOfWork.
- */
-public final class DefaultEntityStoreUnitOfWork
-    implements EntityStoreUnitOfWork
-{
-    private EntityStoreSPI entityStoreSPI;
-    private String identity;
-    private HashMap<EntityReference, EntityState> states = new HashMap<>();
-    private Usecase usecase;
-    private long currentTime;
-
-    public DefaultEntityStoreUnitOfWork( EntityStoreSPI entityStoreSPI,
-                                         String identity,
-                                         Usecase usecase,
-                                         long currentTime
-    )
-    {
-        this.entityStoreSPI = entityStoreSPI;
-        this.identity = identity;
-        this.usecase = usecase;
-        this.currentTime = currentTime;
-    }
-
-    @Override
-    public String identity()
-    {
-        return identity;
-    }
-
-    @Override
-    public long currentTime()
-    {
-        return currentTime;
-    }
-
-    public Usecase usecase()
-    {
-        return usecase;
-    }
-
-    // EntityStore
-
-    @Override
-    public EntityState newEntityState( ModuleSpi module, EntityReference anIdentity, EntityDescriptor descriptor )
-        throws EntityStoreException
-    {
-        EntityState entityState = states.get( anIdentity );
-        if( entityState != null )
-        {
-            throw new EntityAlreadyExistsException( anIdentity );
-        }
-        EntityState state = entityStoreSPI.newEntityState( this, module, anIdentity, descriptor );
-        states.put( anIdentity, state );
-        return state;
-    }
-
-    @Override
-    public EntityState entityStateOf( ModuleSpi module, EntityReference anIdentity )
-        throws EntityNotFoundException
-    {
-
-        EntityState entityState = states.get( anIdentity );
-        if( entityState != null )
-        {
-            return entityState;
-        }
-        entityState = entityStoreSPI.entityStateOf( this, module, anIdentity );
-        states.put( anIdentity, entityState );
-        return entityState;
-    }
-
-    @Override
-    public StateCommitter applyChanges()
-        throws EntityStoreException
-    {
-        return entityStoreSPI.applyChanges( this, states.values() );
-    }
-
-    @Override
-    public void discard()
-    {
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityAlreadyExistsException.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityAlreadyExistsException.java
deleted file mode 100644
index 6054dcd..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityAlreadyExistsException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*  Copyright 2007 Niclas Hedhman.
- *
- * Licensed 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.qi4j.spi.entitystore;
-
-import org.qi4j.api.entity.EntityReference;
-
-/**
- * This exception is thrown when an Entity already exists.
- */
-public class EntityAlreadyExistsException
-    extends EntityStoreException
-{
-    private EntityReference identity;
-
-    public EntityAlreadyExistsException( EntityReference identity )
-    {
-        super("Entity " + identity + " already exists.");
-        this.identity = identity;
-    }
-
-    public EntityReference identity()
-    {
-        return identity;
-    }
-
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityNotFoundException.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityNotFoundException.java
deleted file mode 100644
index 19dfe9e..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityNotFoundException.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*  Copyright 2007 Niclas Hedhman.
- *
- * Licensed 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.qi4j.spi.entitystore;
-
-import org.qi4j.api.entity.EntityReference;
-
-/**
- * This exception is thrown when an Entity could not be found.
- */
-public class EntityNotFoundException
-    extends EntityStoreException
-{
-    private EntityReference identity;
-
-    public EntityNotFoundException( EntityReference identity )
-    {
-        super("Entity " + identity + " not found");
-        this.identity = identity;
-    }
-
-    public EntityReference identity()
-    {
-        return identity;
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityStateVersions.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityStateVersions.java
deleted file mode 100644
index 08e268d..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityStateVersions.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.entitystore;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.WeakHashMap;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.EntityStatus;
-import org.qi4j.spi.module.ModuleSpi;
-
-/**
- * Entity versions state.
- */
-@Mixins( EntityStateVersions.EntityStateVersionsMixin.class )
-public interface EntityStateVersions
-{
-    void forgetVersions( Iterable<EntityState> states );
-
-    void rememberVersion( EntityReference identity, String version );
-
-    void checkForConcurrentModification( Iterable<EntityState> loaded, ModuleSpi module, long currentTime )
-        throws ConcurrentEntityStateModificationException;
-
-    /**
-     * Entity versions state mixin.
-     */
-    class EntityStateVersionsMixin
-        implements EntityStateVersions
-    {
-        @This
-        private EntityStore store;
-
-        private final Map<EntityReference, String> versions = new WeakHashMap<>();
-
-        @Override
-        public synchronized void forgetVersions( Iterable<EntityState> states )
-        {
-            for( EntityState state : states )
-            {
-                versions.remove( state.identity() );
-            }
-        }
-
-        @Override
-        public synchronized void rememberVersion( EntityReference identity, String version )
-        {
-            versions.put( identity, version );
-        }
-
-        @Override
-        public synchronized void checkForConcurrentModification( Iterable<EntityState> loaded,
-                                                                 ModuleSpi module,
-                                                                 long currentTime
-        )
-            throws ConcurrentEntityStateModificationException
-        {
-            List<EntityReference> changed = null;
-            for( EntityState entityState : loaded )
-            {
-                if( entityState.status().equals( EntityStatus.NEW ) )
-                {
-                    continue;
-                }
-
-                String storeVersion = versions.get( entityState.identity() );
-                if( storeVersion == null )
-                {
-                    EntityStoreUnitOfWork unitOfWork = store.newUnitOfWork( Usecase.DEFAULT, module, currentTime );
-                    EntityState state = unitOfWork.entityStateOf( module, entityState.identity() );
-                    storeVersion = state.version();
-                    unitOfWork.discard();
-                }
-
-                if( !entityState.version().equals( storeVersion ) )
-                {
-                    if( changed == null )
-                    {
-                        changed = new ArrayList<>();
-                    }
-                    changed.add( entityState.identity() );
-                }
-            }
-
-            if( changed != null )
-            {
-                throw new ConcurrentEntityStateModificationException( changed );
-            }
-        }
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityStore.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityStore.java
deleted file mode 100644
index b8de305..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityStore.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*  Copyright 2007 Niclas Hedhman.
- *
- * Licensed 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.qi4j.spi.entitystore;
-
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.io.Input;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.module.ModuleSpi;
-
-/**
- * Interface that must be implemented by store for persistent state of EntityComposites.
- */
-public interface EntityStore
-{
-    EntityStoreUnitOfWork newUnitOfWork( Usecase usecase, ModuleSpi module, long currentTime );
-
-    Input<EntityState, EntityStoreException> entityStates( ModuleSpi module );
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityStoreException.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityStoreException.java
deleted file mode 100644
index 123381a..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityStoreException.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*  Copyright 2007 Niclas Hedhman.
- *
- * Licensed 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.qi4j.spi.entitystore;
-
-/**
- * Base EntityStore Exception.
- */
-public class EntityStoreException
-    extends RuntimeException
-{
-    public EntityStoreException()
-    {
-    }
-
-    public EntityStoreException( String message )
-    {
-        super( message );
-    }
-
-    public EntityStoreException( String message, Throwable cause )
-    {
-        super( message, cause );
-    }
-
-    public EntityStoreException( Throwable cause )
-    {
-        super( cause );
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityStoreSPI.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityStoreSPI.java
deleted file mode 100644
index 521d2ce..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityStoreSPI.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.entitystore;
-
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.module.ModuleSpi;
-
-/**
- * EntityStore SPI.
- */
-public interface EntityStoreSPI
-{
-    EntityState newEntityState( EntityStoreUnitOfWork unitOfWork,
-                                ModuleSpi module,
-                                EntityReference identity, EntityDescriptor entityDescriptor
-    );
-
-    EntityState entityStateOf( EntityStoreUnitOfWork unitOfWork, ModuleSpi module, EntityReference identity );
-
-    StateCommitter applyChanges( EntityStoreUnitOfWork unitOfWork, Iterable<EntityState> state
-    );
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityStoreUnitOfWork.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityStoreUnitOfWork.java
deleted file mode 100644
index 0b055bf..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/EntityStoreUnitOfWork.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.entitystore;
-
-import org.qi4j.api.common.MetaInfo;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.module.ModuleSpi;
-
-/**
- * EntityStore UnitOfWork.
- */
-public interface EntityStoreUnitOfWork
-{
-    String identity();
-
-    long currentTime();
-
-    /**
-     * Create new EntityState for a given identity.
-     * <p>
-     * This should only create the EntityState and not insert it into any database, since that should occur during
-     * the {@link EntityStoreUnitOfWork#applyChanges()} call.
-     * </p>
-     * @param anIdentity       the identity of the entity
-     * @param entityDescriptor entity descriptor
-     *
-     * @return The new entity state.
-     *
-     * @throws EntityStoreException Thrown if creational fails.
-     */
-    EntityState newEntityState( ModuleSpi module, EntityReference anIdentity, EntityDescriptor entityDescriptor )
-        throws EntityStoreException;
-
-    /**
-     * Get the EntityState for a given identity. Throws {@link EntityNotFoundException}
-     * if the entity with given {@code anIdentity} is not found.
-     *
-     * @param anIdentity The entity identity. This argument must not be {@code null}.
-     *
-     * @return Entity state given the composite descriptor and identity.
-     *
-     * @throws EntityStoreException    thrown if retrieval failed.
-     * @throws EntityNotFoundException if requested entity does not exist
-     */
-    EntityState entityStateOf( ModuleSpi module, EntityReference anIdentity )
-        throws EntityStoreException, EntityNotFoundException;
-
-    StateCommitter applyChanges()
-        throws EntityStoreException;
-
-    void discard();
-
-    Usecase usecase();
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/ModuleEntityStoreUnitOfWork.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/ModuleEntityStoreUnitOfWork.java
deleted file mode 100644
index 5aae65b..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/ModuleEntityStoreUnitOfWork.java
+++ /dev/null
@@ -1,85 +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.qi4j.spi.entitystore;
-
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.module.ModuleSpi;
-
-public class ModuleEntityStoreUnitOfWork
-    implements EntityStoreUnitOfWork
-{
-    private final ModuleSpi module;
-    private final EntityStoreUnitOfWork underlying;
-
-    public ModuleEntityStoreUnitOfWork( ModuleSpi module, EntityStoreUnitOfWork underlying )
-    {
-        this.module = module;
-        this.underlying = underlying;
-    }
-
-    public ModuleSpi module()
-    {
-        return module;
-    }
-
-    @Override
-    public String identity()
-    {
-        return underlying.identity();
-    }
-
-    @Override
-    public long currentTime()
-    {
-        return underlying.currentTime();
-    }
-
-    @Override
-    public EntityState newEntityState( ModuleSpi module, EntityReference reference, EntityDescriptor descriptor )
-        throws EntityStoreException
-    {
-        return underlying.newEntityState( module, reference, descriptor );
-    }
-
-    @Override
-    public EntityState entityStateOf( ModuleSpi module, EntityReference reference )
-        throws EntityStoreException, EntityNotFoundException
-    {
-        return underlying.entityStateOf( module, reference );
-    }
-
-    @Override
-    public StateCommitter applyChanges()
-        throws EntityStoreException
-    {
-        return underlying.applyChanges();
-    }
-
-    @Override
-    public void discard()
-    {
-        underlying.discard();
-    }
-
-    public Usecase usecase()
-    {
-        return underlying.usecase();
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/ReadOnlyEntityStoreException.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/ReadOnlyEntityStoreException.java
deleted file mode 100644
index 91c9960..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/ReadOnlyEntityStoreException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.spi.entitystore;
-
-/**
- * This exception is thrown for methods that creates or updates entities in read-only EntityStores.
- */
-public class ReadOnlyEntityStoreException
-    extends EntityStoreException
-{
-    public ReadOnlyEntityStoreException( String message )
-    {
-        super( message );
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/StateChangeListener.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/StateChangeListener.java
deleted file mode 100644
index 5b9c865..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/StateChangeListener.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.entitystore;
-
-import org.qi4j.spi.entity.EntityState;
-
-/**
- * Implement this interface in a Service if you want it to listen
- * to changes from EntityStores.
- */
-public interface StateChangeListener
-{
-    void notifyChanges( Iterable<EntityState> changedStates );
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/StateChangeNotificationConcern.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/StateChangeNotificationConcern.java
deleted file mode 100644
index 1365881..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/StateChangeNotificationConcern.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.entitystore;
-
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.module.ModuleSpi;
-
-/**
- * State change notification Concern.
- */
-public abstract class StateChangeNotificationConcern
-    extends ConcernOf<EntityStoreSPI>
-    implements EntityStoreSPI
-{
-    @Service
-    Iterable<StateChangeListener> listeners;
-
-    @Override
-    public StateCommitter applyChanges( final EntityStoreUnitOfWork unitofwork,
-                                        final Iterable<EntityState> state
-    )
-    {
-        final StateCommitter committer = next.applyChanges( unitofwork, state );
-        return new StateCommitter()
-        {
-            @Override
-            public void commit()
-            {
-                for( StateChangeListener listener : listeners )
-                {
-                    listener.notifyChanges( state );
-                }
-                committer.commit();
-            }
-
-            @Override
-            public void cancel()
-            {
-                committer.cancel();
-            }
-        };
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/StateCommitter.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/StateCommitter.java
deleted file mode 100644
index 5119b11..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/StateCommitter.java
+++ /dev/null
@@ -1,29 +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.qi4j.spi.entitystore;
-
-/**
- * After all EntityStore's have been prepared by {@link org.qi4j.api.unitofwork.UnitOfWork#complete()}
- */
-public interface StateCommitter
-{
-    void commit();
-
-    void cancel();
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/DefaultEntityState.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/DefaultEntityState.java
deleted file mode 100644
index 4d66073..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/DefaultEntityState.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright (c) 2009-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.spi.entitystore.helpers;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.util.Classes;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.EntityStatus;
-import org.qi4j.spi.entity.ManyAssociationState;
-import org.qi4j.spi.entity.NamedAssociationState;
-
-/**
- * Standard implementation of EntityState.
- */
-public final class DefaultEntityState
-    implements EntityState
-{
-    private EntityStatus status;
-
-    private String version;
-    private long lastModified;
-    private final EntityReference identity;
-    private final EntityDescriptor entityDescriptor;
-
-    private final Map<QualifiedName, Object> properties;
-    private final Map<QualifiedName, EntityReference> associations;
-    private final Map<QualifiedName, List<EntityReference>> manyAssociations;
-    private final Map<QualifiedName, Map<String, EntityReference>> namedAssociations;
-
-    public DefaultEntityState( long currentTime,
-                               EntityReference identity,
-                               EntityDescriptor entityDescriptor
-    )
-    {
-        this( "",
-              currentTime,
-              identity,
-              EntityStatus.NEW,
-              entityDescriptor,
-              new HashMap<QualifiedName, Object>(),
-              new HashMap<QualifiedName, EntityReference>(),
-              new HashMap<QualifiedName, List<EntityReference>>(),
-              new HashMap<QualifiedName, Map<String, EntityReference>>() );
-    }
-
-    public DefaultEntityState( String version,
-                               long lastModified,
-                               EntityReference identity,
-                               EntityStatus status,
-                               EntityDescriptor entityDescriptor,
-                               Map<QualifiedName, Object> properties,
-                               Map<QualifiedName, EntityReference> associations,
-                               Map<QualifiedName, List<EntityReference>> manyAssociations,
-                               Map<QualifiedName, Map<String, EntityReference>> namedAssociations
-    )
-    {
-        this.version = version;
-        this.lastModified = lastModified;
-        this.identity = identity;
-        this.status = status;
-        this.entityDescriptor = entityDescriptor;
-        this.properties = properties;
-        this.associations = associations;
-        this.manyAssociations = manyAssociations;
-        this.namedAssociations = namedAssociations;
-    }
-
-    // EntityState implementation
-    @Override
-    public final String version()
-    {
-        return version;
-    }
-
-    @Override
-    public long lastModified()
-    {
-        return lastModified;
-    }
-
-    @Override
-    public EntityReference identity()
-    {
-        return identity;
-    }
-
-    @Override
-    public Object propertyValueOf( QualifiedName stateName )
-    {
-        return properties.get( stateName );
-    }
-
-    @Override
-    public void setPropertyValue( QualifiedName stateName, Object newValue )
-    {
-        properties.put( stateName, newValue );
-        markUpdated();
-    }
-
-    @Override
-    public EntityReference associationValueOf( QualifiedName stateName )
-    {
-        return associations.get( stateName );
-    }
-
-    @Override
-    public void setAssociationValue( QualifiedName stateName, EntityReference newEntity )
-    {
-        associations.put( stateName, newEntity );
-        markUpdated();
-    }
-
-    @Override
-    public ManyAssociationState manyAssociationValueOf( QualifiedName stateName )
-    {
-        List<EntityReference> manyAssociationState = manyAssociations.get( stateName );
-        if( manyAssociationState == null )
-        {
-            manyAssociationState = new ArrayList<>();
-            manyAssociations.put( stateName, manyAssociationState );
-        }
-        return new DefaultManyAssociationState( this, manyAssociationState );
-    }
-
-    @Override
-    public NamedAssociationState namedAssociationValueOf( QualifiedName stateName )
-    {
-        Map<String, EntityReference> namedAssociationState = namedAssociations.get( stateName );
-        if( namedAssociationState == null )
-        {
-            namedAssociationState = new LinkedHashMap<>();
-            namedAssociations.put( stateName, namedAssociationState );
-        }
-        return new DefaultNamedAssociationState( this, namedAssociationState );
-    }
-
-    public void copyTo( DefaultEntityState entityState )
-    {
-        // Copy properties
-        entityState.properties.clear();
-        for( Map.Entry<QualifiedName, Object> stateNameStringEntry : properties.entrySet() )
-        {
-            entityState.properties.put( stateNameStringEntry.getKey(), stateNameStringEntry.getValue() );
-        }
-
-        // Copy associations
-        entityState.associations.clear();
-        for( Map.Entry<QualifiedName, EntityReference> stateNameStringEntry : associations.entrySet() )
-        {
-            entityState.associations.put( stateNameStringEntry.getKey(), stateNameStringEntry.getValue() );
-        }
-
-        // Copy many-associations
-        entityState.manyAssociations.clear();
-        for( Map.Entry<QualifiedName, List<EntityReference>> stateNameStringEntry : manyAssociations.entrySet() )
-        {
-            entityState.manyAssociations.put( stateNameStringEntry.getKey(), stateNameStringEntry.getValue() );
-        }
-
-        // Copy named-associations
-        entityState.namedAssociations.clear();
-        for( Map.Entry<QualifiedName, Map<String, EntityReference>> entry : namedAssociations.entrySet() )
-        {
-            entityState.namedAssociations.put( entry.getKey(), entry.getValue() );
-        }
-
-        // Set version and timestamp
-        entityState.version = version;
-        entityState.lastModified = lastModified;
-    }
-
-    @Override
-    public void remove()
-    {
-        status = EntityStatus.REMOVED;
-    }
-
-    @Override
-    public EntityStatus status()
-    {
-        return status;
-    }
-
-    @Override
-    public boolean isAssignableTo( Class<?> type )
-    {
-        return Classes.exactTypeSpecification( type ).satisfiedBy( entityDescriptor );
-    }
-
-    @Override
-    public EntityDescriptor entityDescriptor()
-    {
-        return entityDescriptor;
-    }
-
-    public Map<QualifiedName, Object> properties()
-    {
-        return properties;
-    }
-
-    public Map<QualifiedName, EntityReference> associations()
-    {
-        return associations;
-    }
-
-    public Map<QualifiedName, List<EntityReference>> manyAssociations()
-    {
-        return manyAssociations;
-    }
-
-    public Map<QualifiedName, Map<String, EntityReference>> namedAssociations()
-    {
-        return namedAssociations;
-    }
-
-    @Override
-    public String toString()
-    {
-        return identity + "("
-               + properties.size() + " properties, "
-               + associations.size() + " associations, "
-               + manyAssociations.size() + " many-associations, "
-               + namedAssociations.size() + " named-associations)";
-    }
-
-    public void markUpdated()
-    {
-        if( status == EntityStatus.LOADED )
-        {
-            status = EntityStatus.UPDATED;
-        }
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/DefaultManyAssociationState.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/DefaultManyAssociationState.java
deleted file mode 100644
index 51ba3df..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/DefaultManyAssociationState.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.entitystore.helpers;
-
-import java.util.Iterator;
-import java.util.List;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.spi.entity.ManyAssociationState;
-
-/**
- * Default implementation of ManyAssociationState. Backed by ArrayList.
- */
-public final class DefaultManyAssociationState
-    implements ManyAssociationState
-{
-    private DefaultEntityState entityState;
-    private List<EntityReference> references;
-
-    public DefaultManyAssociationState( DefaultEntityState entityState, List<EntityReference> references )
-    {
-        this.entityState = entityState;
-        this.references = references;
-    }
-
-    @Override
-    public int count()
-    {
-        return references.size();
-    }
-
-    @Override
-    public boolean contains( EntityReference entityReference )
-    {
-        return references.contains( entityReference );
-    }
-
-    @Override
-    public boolean add( int i, EntityReference entityReference )
-    {
-        if( references.contains( entityReference ) )
-        {
-            return false;
-        }
-
-        references.add( i, entityReference );
-        entityState.markUpdated();
-        return true;
-    }
-
-    @Override
-    public boolean remove( EntityReference entity )
-    {
-        boolean removed = references.remove( entity );
-        entityState.markUpdated();
-        return removed;
-    }
-
-    @Override
-    public EntityReference get( int i )
-    {
-        return references.get( i );
-    }
-
-    @Override
-    public Iterator<EntityReference> iterator()
-    {
-        final Iterator<EntityReference> iter = references.iterator();
-
-        return new Iterator<EntityReference>()
-        {
-            EntityReference current;
-
-            @Override
-            public boolean hasNext()
-            {
-                return iter.hasNext();
-            }
-
-            @Override
-            public EntityReference next()
-            {
-                current = iter.next();
-                return current;
-            }
-
-            @Override
-            public void remove()
-            {
-                iter.remove();
-                entityState.markUpdated();
-            }
-        };
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/DefaultNamedAssociationState.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/DefaultNamedAssociationState.java
deleted file mode 100644
index 7f3e688..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/DefaultNamedAssociationState.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2011-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.spi.entitystore.helpers;
-
-import java.util.Iterator;
-import java.util.Map;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.spi.entity.NamedAssociationState;
-
-/**
- * Default implementation of NamedAssociationState.
- * Backed by HashMap.
- */
-public final class DefaultNamedAssociationState
-    implements NamedAssociationState
-{
-    private final DefaultEntityState entityState;
-    private final Map<String, EntityReference> references;
-
-    public DefaultNamedAssociationState( DefaultEntityState entityState, Map<String, EntityReference> references )
-    {
-        this.entityState = entityState;
-        this.references = references;
-    }
-
-    @Override
-    public int count()
-    {
-        return references.size();
-    }
-
-    @Override
-    public boolean containsName( String name )
-    {
-        return references.containsKey( name );
-    }
-
-    @Override
-    public boolean put( String name, EntityReference entityReference )
-    {
-        if( references.put( name, entityReference ) == null )
-        {
-            return false;
-        }
-        entityState.markUpdated();
-        return true;
-    }
-
-    @Override
-    public boolean remove( String name )
-    {
-        if( references.remove( name ) == null )
-        {
-            return false;
-        }
-        entityState.markUpdated();
-        return true;
-    }
-
-    @Override
-    public EntityReference get( String name )
-    {
-        return references.get( name );
-    }
-
-    @Override
-    public String nameOf( EntityReference entityReference )
-    {
-        for( Map.Entry<String, EntityReference> entry : references.entrySet() )
-        {
-            if( entry.getValue().equals( entityReference ) )
-            {
-                return entry.getKey();
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public Iterator<String> iterator()
-    {
-        final Iterator<String> iter = references.keySet().iterator();
-        return new Iterator<String>()
-        {
-            private String current;
-
-            @Override
-            public boolean hasNext()
-            {
-                return iter.hasNext();
-            }
-
-            @Override
-            public String next()
-            {
-                current = iter.next();
-                return current;
-            }
-
-            @Override
-            public void remove()
-            {
-                iter.remove();
-                entityState.markUpdated();
-            }
-        };
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONEntityState.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONEntityState.java
deleted file mode 100644
index ae60809..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONEntityState.java
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright (c) 2009-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2013-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.spi.entitystore.helpers;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.api.value.ValueSerializationException;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.EntityStatus;
-import org.qi4j.spi.entity.ManyAssociationState;
-import org.qi4j.spi.entity.NamedAssociationState;
-import org.qi4j.spi.entitystore.EntityStoreException;
-
-/**
- * Standard JSON implementation of EntityState.
- */
-public final class JSONEntityState
-    implements EntityState
-{
-    private static final String[] EMPTY_NAMES = new String[ 0 ];
-    private static final String[] CLONE_NAMES =
-        {
-            JSONKeys.IDENTITY,
-            JSONKeys.APPLICATION_VERSION,
-            JSONKeys.TYPE,
-            JSONKeys.VERSION,
-            JSONKeys.MODIFIED
-        };
-
-    private final ValueSerialization valueSerialization;
-    private final String version;
-    private final EntityReference identity;
-    private final EntityDescriptor entityDescriptor;
-
-    private EntityStatus status;
-    private long lastModified;
-    private JSONObject state;
-
-    /* package */ JSONEntityState( long time,
-                                   ValueSerialization valueSerialization,
-                                   EntityReference identity,
-                                   EntityDescriptor entityDescriptor,
-                                   JSONObject initialState
-    )
-    {
-        this( valueSerialization,
-              "",
-              time,
-              identity,
-              EntityStatus.NEW,
-              entityDescriptor,
-              initialState );
-    }
-
-    /* package */ JSONEntityState( ValueSerialization valueSerialization,
-                                   String version,
-                                   long lastModified,
-                                   EntityReference identity,
-                                   EntityStatus status,
-                                   EntityDescriptor entityDescriptor,
-                                   JSONObject state
-    )
-    {
-        this.valueSerialization = valueSerialization;
-        this.version = version;
-        this.lastModified = lastModified;
-        this.identity = identity;
-        this.status = status;
-        this.entityDescriptor = entityDescriptor;
-        this.state = state;
-    }
-
-    // EntityState implementation
-    @Override
-    public final String version()
-    {
-        return version;
-    }
-
-    @Override
-    public long lastModified()
-    {
-        return lastModified;
-    }
-
-    @Override
-    public EntityReference identity()
-    {
-        return identity;
-    }
-
-    @Override
-    public Object propertyValueOf( QualifiedName stateName )
-    {
-        try
-        {
-            Object json = state.getJSONObject( JSONKeys.PROPERTIES ).opt( stateName.name() );
-            if( JSONObject.NULL.equals( json ) )
-            {
-                return null;
-            }
-            else
-            {
-                PropertyDescriptor descriptor = entityDescriptor.state().findPropertyModelByQualifiedName( stateName );
-                if( descriptor == null )
-                {
-                    return null;
-                }
-                return valueSerialization.deserialize( descriptor.valueType(), json.toString() );
-            }
-        }
-        catch( ValueSerializationException | JSONException e )
-        {
-            throw new EntityStoreException( e );
-        }
-    }
-
-    @Override
-    public void setPropertyValue( QualifiedName stateName, Object newValue )
-    {
-        try
-        {
-            Object jsonValue;
-            if( newValue == null || ValueType.isPrimitiveValue( newValue ) )
-            {
-                jsonValue = newValue;
-            }
-            else
-            {
-                String serialized = valueSerialization.serialize( newValue );
-                if( serialized.startsWith( "{" ) )
-                {
-                    jsonValue = new JSONObject( serialized );
-                }
-                else if( serialized.startsWith( "[" ) )
-                {
-                    jsonValue = new JSONArray( serialized );
-                }
-                else
-                {
-                    jsonValue = serialized;
-                }
-            }
-            cloneStateIfGlobalStateLoaded();
-            state.getJSONObject( JSONKeys.PROPERTIES ).put( stateName.name(), jsonValue );
-            markUpdated();
-        }
-        catch( ValueSerializationException | JSONException e )
-        {
-            throw new EntityStoreException( e );
-        }
-    }
-
-    private JSONObject cloneJSON( JSONObject jsonObject )
-        throws JSONException
-    {
-        String[] names = JSONObject.getNames( jsonObject );
-        if( names == null )
-        {
-            names = EMPTY_NAMES;
-        }
-        return new JSONObject( jsonObject, names );
-    }
-
-    @Override
-    public EntityReference associationValueOf( QualifiedName stateName )
-    {
-        try
-        {
-            Object jsonValue = state.getJSONObject( JSONKeys.ASSOCIATIONS ).opt( stateName.name() );
-            if( jsonValue == null )
-            {
-                return null;
-            }
-
-            EntityReference value = jsonValue == JSONObject.NULL
-                                    ? null
-                                    : EntityReference.parseEntityReference( (String) jsonValue );
-            return value;
-        }
-        catch( JSONException e )
-        {
-            throw new EntityStoreException( e );
-        }
-    }
-
-    @Override
-    public void setAssociationValue( QualifiedName stateName, EntityReference newEntity )
-    {
-        try
-        {
-            cloneStateIfGlobalStateLoaded();
-            state.getJSONObject( JSONKeys.ASSOCIATIONS ).put( stateName.name(), newEntity == null
-                                                                                ? null
-                                                                                : newEntity.identity() );
-            markUpdated();
-        }
-        catch( JSONException e )
-        {
-            throw new EntityStoreException( e );
-        }
-    }
-
-    @Override
-    public ManyAssociationState manyAssociationValueOf( QualifiedName stateName )
-    {
-        try
-        {
-            JSONObject manyAssociations = state.getJSONObject( JSONKeys.MANY_ASSOCIATIONS );
-            JSONArray jsonValues = manyAssociations.optJSONArray( stateName.name() );
-            if( jsonValues == null )
-            {
-                jsonValues = new JSONArray();
-                manyAssociations.put( stateName.name(), jsonValues );
-            }
-            return new JSONManyAssociationState( this, jsonValues );
-        }
-        catch( JSONException e )
-        {
-            throw new EntityStoreException( e );
-        }
-    }
-
-    @Override
-    public NamedAssociationState namedAssociationValueOf( QualifiedName stateName )
-    {
-        try
-        {
-            JSONObject namedAssociations = state.getJSONObject( JSONKeys.NAMED_ASSOCIATIONS );
-            JSONObject jsonValues = namedAssociations.optJSONObject( stateName.name() );
-            if( jsonValues == null )
-            {
-                jsonValues = new JSONObject();
-                namedAssociations.put( stateName.name(), jsonValues );
-            }
-            return new JSONNamedAssociationState( this, jsonValues );
-        }
-        catch( JSONException e )
-        {
-            throw new EntityStoreException( e );
-        }
-    }
-
-    @Override
-    public void remove()
-    {
-        status = EntityStatus.REMOVED;
-    }
-
-    @Override
-    public EntityStatus status()
-    {
-        return status;
-    }
-
-    @Override
-    public boolean isAssignableTo( Class<?> type )
-    {
-        return entityDescriptor.isAssignableTo( type );
-    }
-
-    @Override
-    public EntityDescriptor entityDescriptor()
-    {
-        return entityDescriptor;
-    }
-
-    public JSONObject state()
-    {
-        return state;
-    }
-
-    @Override
-    public String toString()
-    {
-        return identity + "(" + state + ")";
-    }
-
-    public void markUpdated()
-    {
-        if( status == EntityStatus.LOADED )
-        {
-            status = EntityStatus.UPDATED;
-        }
-    }
-
-    void cloneStateIfGlobalStateLoaded()
-    {
-        if( status != EntityStatus.LOADED )
-        {
-            return;
-        }
-
-        try
-        {
-            JSONObject newProperties = cloneJSON( state.getJSONObject( JSONKeys.PROPERTIES ) );
-            JSONObject newAssoc = cloneJSON( state.getJSONObject( JSONKeys.ASSOCIATIONS ) );
-            JSONObject newManyAssoc = cloneJSON( state.getJSONObject( JSONKeys.MANY_ASSOCIATIONS ) );
-            JSONObject newNamedAssoc = cloneJSON( state.getJSONObject( JSONKeys.NAMED_ASSOCIATIONS ) );
-            JSONObject stateClone = new JSONObject( state, CLONE_NAMES );
-            stateClone.put( JSONKeys.PROPERTIES, newProperties );
-            stateClone.put( JSONKeys.ASSOCIATIONS, newAssoc );
-            stateClone.put( JSONKeys.MANY_ASSOCIATIONS, newManyAssoc );
-            stateClone.put( JSONKeys.NAMED_ASSOCIATIONS, newNamedAssoc );
-            state = stateClone;
-        }
-        catch( JSONException e )
-        {
-            throw new EntityStoreException( e );
-        }
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONKeys.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONKeys.java
deleted file mode 100644
index 99b29a4..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONKeys.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2009-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.spi.entitystore.helpers;
-
-/**
- * JSON keys for values in the stored data.
- */
-public interface JSONKeys
-{
-    /**
-     * Identity of the entity.
-     */
-    String IDENTITY = "identity";
-    /**
-     * Version of the application which last updated the entity.
-     */
-    String APPLICATION_VERSION = "application_version";
-    /**
-     * Type of the entity.
-     */
-    String TYPE = "type";
-    /**
-     * Version of the entity.
-     */
-    String VERSION = "version";
-    /**
-     * When entity was last modified according to System.currentTimeMillis().
-     */
-    String MODIFIED = "modified";
-    /**
-     * Map of properties.
-     */
-    String PROPERTIES = "properties";
-    /**
-     * Map of associations.
-     */
-    String ASSOCIATIONS = "associations";
-    /**
-     * Map of manyassociations.
-     */
-    String MANY_ASSOCIATIONS = "manyassociations";
-    /**
-     * Map of namedassociations.
-     */
-    String NAMED_ASSOCIATIONS = "namedassociations";
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONManyAssociationState.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONManyAssociationState.java
deleted file mode 100644
index e95e2a9..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONManyAssociationState.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.entitystore.helpers;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.spi.entity.ManyAssociationState;
-import org.qi4j.spi.entitystore.EntityStoreException;
-
-/**
- * JSON implementation of ManyAssociationState.
- * <p>Backed by a JSONArray.</p>
- */
-public final class JSONManyAssociationState
-    implements ManyAssociationState
-{
-
-    private final JSONEntityState entityState;
-    private final JSONArray references;
-
-    public JSONManyAssociationState( JSONEntityState entityState, JSONArray references )
-    {
-        this.entityState = entityState;
-        this.references = references;
-    }
-
-    @Override
-    public int count()
-    {
-        return references.length();
-    }
-
-    @Override
-    public boolean contains( EntityReference entityReference )
-    {
-        return indexOfReference( entityReference.identity() ) != -1;
-    }
-
-    @Override
-    public boolean add( int idx, EntityReference entityReference )
-    {
-        try
-        {
-            if( indexOfReference( entityReference.identity() ) != -1 )
-            {
-                return false;
-            }
-            entityState.cloneStateIfGlobalStateLoaded();
-            insertReference( idx, entityReference.identity() );
-            entityState.markUpdated();
-            return true;
-        }
-        catch( JSONException e )
-        {
-            throw new EntityStoreException( e );
-        }
-    }
-
-    @Override
-    public boolean remove( EntityReference entityReference )
-    {
-        int refIndex = indexOfReference( entityReference.identity() );
-        if( refIndex != -1 )
-        {
-            entityState.cloneStateIfGlobalStateLoaded();
-            references.remove( refIndex );
-            entityState.markUpdated();
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public EntityReference get( int i )
-    {
-        try
-        {
-            return new EntityReference( references.getString( i ) );
-        }
-        catch( JSONException e )
-        {
-            throw new EntityStoreException( e );
-        }
-    }
-
-    @Override
-    public Iterator<EntityReference> iterator()
-    {
-        return new Iterator<EntityReference>()
-        {
-            private int idx = 0;
-
-            @Override
-            public boolean hasNext()
-            {
-                return idx < references.length();
-            }
-
-            @Override
-            public EntityReference next()
-            {
-                try
-                {
-                    EntityReference ref = new EntityReference( references.getString( idx ) );
-                    idx++;
-                    return ref;
-                }
-                catch( JSONException e )
-                {
-                    throw new NoSuchElementException();
-                }
-            }
-
-            @Override
-            public void remove()
-            {
-                throw new UnsupportedOperationException( "remove() is not supported on ManyAssociation iterators." );
-            }
-        };
-    }
-
-    @Override
-    public String toString()
-    {
-        return references.toString();
-    }
-
-    private int indexOfReference( Object item )
-    {
-        for( int idx = 0; idx < references.length(); idx++ )
-        {
-            if( item.equals( references.opt( idx ) ) )
-            {
-                return idx;
-            }
-        }
-        return -1;
-    }
-
-    private void insertReference( int insert, Object item )
-        throws JSONException
-    {
-        if( insert < 0 || insert > references.length() )
-        {
-            throw new JSONException( "JSONArray[" + insert + "] is out of bounds." );
-        }
-        if( insert == references.length() )
-        {
-            // append
-            references.put( item );
-        }
-        else
-        {
-            // insert (copy/insert/apply)
-            JSONArray output = new JSONArray();
-            for( int idx = 0; idx < references.length(); idx++ )
-            {
-                if( idx == insert )
-                {
-                    output.put( item );
-                }
-                output.put( references.opt( idx ) );
-            }
-            for( int idx = 0; idx < output.length(); idx++ )
-            {
-                references.put( idx, output.opt( idx ) );
-            }
-        }
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONMapEntityStoreActivation.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONMapEntityStoreActivation.java
deleted file mode 100644
index 0da0de0..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONMapEntityStoreActivation.java
+++ /dev/null
@@ -1,61 +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.qi4j.spi.entitystore.helpers;
-
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.service.ServiceReference;
-
-/**
- * Activation for JSONMapEntityStoreMixin.
- */
-@Activators( JSONMapEntityStoreActivation.Activator.class )
-public interface JSONMapEntityStoreActivation
-{
-
-    void setUpJSONMapES()
-        throws Exception;
-
-    void tearDownJSONMapES()
-        throws Exception;
-
-    /**
-     * JSONMapEntityStoreMixin Activator.
-     */
-    public class Activator
-        extends ActivatorAdapter<ServiceReference<JSONMapEntityStoreActivation>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<JSONMapEntityStoreActivation> activated )
-            throws Exception
-        {
-            activated.get().setUpJSONMapES();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<JSONMapEntityStoreActivation> passivating )
-            throws Exception
-        {
-            passivating.get().tearDownJSONMapES();
-        }
-
-    }
-
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONMapEntityStoreMixin.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONMapEntityStoreMixin.java
deleted file mode 100644
index cac8ec9..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONMapEntityStoreMixin.java
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- * Copyright 2007-2011, Niclas Hedhman. All Rights Reserved.
- * Copyright 2009-2013, Rickard Öberg. All Rights Reserved.
- * Copyright 2012-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.entitystore.helpers;
-
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.io.Reader;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.json.JSONTokener;
-import org.qi4j.api.cache.CacheOptions;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.service.qualifier.Tagged;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.unitofwork.EntityTypeNotFoundException;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.spi.Qi4jSPI;
-import org.qi4j.spi.cache.Cache;
-import org.qi4j.spi.cache.CachePool;
-import org.qi4j.spi.cache.NullCache;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.EntityStatus;
-import org.qi4j.spi.entitystore.DefaultEntityStoreUnitOfWork;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.EntityStoreException;
-import org.qi4j.spi.entitystore.EntityStoreSPI;
-import org.qi4j.spi.entitystore.EntityStoreUnitOfWork;
-import org.qi4j.spi.entitystore.ModuleEntityStoreUnitOfWork;
-import org.qi4j.spi.entitystore.StateCommitter;
-import org.qi4j.spi.module.ModelModule;
-import org.qi4j.spi.module.ModuleSpi;
-
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.map;
-
-/**
- * Implementation of EntityStore that works with an implementation of MapEntityStore.
- *
- * <p>Implement {@link MapEntityStore} and add as mixin to the service using this mixin.</p>
- * <p>See {@link org.qi4j.entitystore.memory.MemoryMapEntityStoreMixin} for reference.</p>
- * <p>EntityStores based on this mixin gets support for the <b>Migration</b> and <b>Cache</b> extensions.</p>
- * <p>MapEntityStore implementations will get their values as JSON.</p>
- */
-public class JSONMapEntityStoreMixin
-    implements EntityStore, EntityStoreSPI, StateStore, JSONMapEntityStoreActivation
-{
-    @This
-    private MapEntityStore mapEntityStore;
-
-    @This
-    private EntityStoreSPI entityStoreSpi;
-
-    @Structure
-    private Qi4jSPI spi;
-
-    @Structure
-    private Application application;
-
-    @Service
-    @Tagged( ValueSerialization.Formats.JSON )
-    private ValueSerialization valueSerialization;
-
-    @Optional
-    @Service
-    private Migration migration;
-
-    @Uses
-    private ServiceDescriptor descriptor;
-
-    @Optional
-    @Service
-    private CachePool caching;
-    private Cache<CacheState> cache;
-
-    protected String uuid;
-    private int count;
-
-    public JSONMapEntityStoreMixin()
-    {
-    }
-
-    @Override
-    public void setUpJSONMapES()
-        throws Exception
-    {
-        uuid = descriptor.identity() + "-" + UUID.randomUUID().toString();
-        if( caching != null )
-        {
-            cache = caching.fetchCache( uuid, CacheState.class );
-        }
-        else
-        {
-            cache = new NullCache<>();
-        }
-    }
-
-    @Override
-    public void tearDownJSONMapES()
-        throws Exception
-    {
-        if( caching != null )
-        {
-            caching.returnCache( cache );
-            cache = null;
-        }
-    }
-
-    // EntityStore
-
-    @Override
-    public EntityStoreUnitOfWork newUnitOfWork( Usecase usecaseMetaInfo, ModuleSpi module, long currentTime )
-    {
-        EntityStoreUnitOfWork storeUnitOfWork = new DefaultEntityStoreUnitOfWork( entityStoreSpi, newUnitOfWorkId(), usecaseMetaInfo, currentTime );
-        storeUnitOfWork = new ModuleEntityStoreUnitOfWork( module, storeUnitOfWork );
-        return storeUnitOfWork;
-    }
-
-    // EntityStoreSPI
-
-    @Override
-    public EntityState newEntityState( EntityStoreUnitOfWork unitOfWork,
-                                       ModuleSpi module,
-                                       EntityReference identity,
-                                       EntityDescriptor entityDescriptor
-    )
-    {
-        try
-        {
-            JSONObject state = new JSONObject();
-            state.put( JSONKeys.IDENTITY, identity.identity() );
-            state.put( JSONKeys.APPLICATION_VERSION, application.version() );
-            state.put( JSONKeys.TYPE, first( entityDescriptor.types() ).getName() );
-            state.put( JSONKeys.VERSION, unitOfWork.identity() );
-            state.put( JSONKeys.MODIFIED, unitOfWork.currentTime() );
-            state.put( JSONKeys.PROPERTIES, new JSONObject() );
-            state.put( JSONKeys.ASSOCIATIONS, new JSONObject() );
-            state.put( JSONKeys.MANY_ASSOCIATIONS, new JSONObject() );
-            state.put( JSONKeys.NAMED_ASSOCIATIONS, new JSONObject() );
-            return new JSONEntityState( unitOfWork.currentTime(), valueSerialization,
-                                        identity, entityDescriptor, state );
-        }
-        catch( JSONException e )
-        {
-            throw new EntityStoreException( e );
-        }
-    }
-
-    @Override
-    public synchronized EntityState entityStateOf( EntityStoreUnitOfWork unitOfWork,
-                                                   ModuleSpi module,
-                                                   EntityReference identity
-    )
-    {
-        EntityState state = fetchCachedState( identity, module, unitOfWork.currentTime() );
-        if( state != null )
-        {
-            return state;
-        }
-        // Get state
-        Reader in = mapEntityStore.get( identity );
-        JSONEntityState loadedState = readEntityState( module, in );
-        if( doCacheOnRead( unitOfWork ) )
-        {
-            cache.put( identity.identity(), new CacheState( loadedState.state() ) );
-        }
-        return loadedState;
-    }
-
-    @Override
-    public StateCommitter applyChanges( final EntityStoreUnitOfWork unitOfWork,
-                                        final Iterable<EntityState> state
-    )
-        throws EntityStoreException
-    {
-        return new StateCommitter()
-        {
-            @Override
-            public void commit()
-            {
-                try
-                {
-                    mapEntityStore.applyChanges( new MapEntityStore.MapChanges()
-                    {
-                        @Override
-                        public void visitMap( MapEntityStore.MapChanger changer )
-                            throws IOException
-                        {
-                            CacheOptions options = unitOfWork.usecase().metaInfo( CacheOptions.class );
-                            if( options == null )
-                            {
-                                options = CacheOptions.ALWAYS;
-                            }
-
-                            for( EntityState entityState : state )
-                            {
-                                JSONEntityState state = (JSONEntityState) entityState;
-                                if( state.status().equals( EntityStatus.NEW ) )
-                                {
-                                    try (Writer writer = changer.newEntity( state.identity(), state.entityDescriptor() ))
-                                    {
-                                        writeEntityState( state, writer, unitOfWork.identity(), unitOfWork.currentTime() );
-                                    }
-                                    if( options.cacheOnNew() )
-                                    {
-                                        cache.put( state.identity().identity(), new CacheState( state.state() ) );
-                                    }
-                                }
-                                else if( state.status().equals( EntityStatus.UPDATED ) )
-                                {
-                                    try (Writer writer = changer.updateEntity( state.identity(), state.entityDescriptor() ))
-                                    {
-                                        writeEntityState( state, writer, unitOfWork.identity(), unitOfWork.currentTime() );
-                                    }
-                                    if( options.cacheOnWrite() )
-                                    {
-                                        cache.put( state.identity().identity(), new CacheState( state.state() ) );
-                                    }
-                                }
-                                else if( state.status().equals( EntityStatus.REMOVED ) )
-                                {
-                                    changer.removeEntity( state.identity(), state.entityDescriptor() );
-                                    cache.remove( state.identity().identity() );
-                                }
-                            }
-                        }
-                    } );
-                }
-                catch( IOException e )
-                {
-                    throw new EntityStoreException( e );
-                }
-            }
-
-            @Override
-            public void cancel()
-            {
-            }
-        };
-    }
-
-    @Override
-    public Input<EntityState, EntityStoreException> entityStates( final ModuleSpi module )
-    {
-        return new Input<EntityState, EntityStoreException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super EntityState, ReceiverThrowableType> output )
-                throws EntityStoreException, ReceiverThrowableType
-            {
-                output.receiveFrom( new Sender<EntityState, EntityStoreException>()
-                {
-                    @Override
-                    public <ReceiverThrowableType extends Throwable> void sendTo( final Receiver<? super EntityState, ReceiverThrowableType> receiver )
-                        throws ReceiverThrowableType, EntityStoreException
-                    {
-                        final List<EntityState> migrated = new ArrayList<>();
-                        try
-                        {
-                            mapEntityStore.entityStates().transferTo( new Output<Reader, ReceiverThrowableType>()
-                            {
-                                @Override
-                                public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends Reader, SenderThrowableType> sender )
-                                    throws ReceiverThrowableType, SenderThrowableType
-                                {
-                                    sender.sendTo( new Receiver<Reader, ReceiverThrowableType>()
-                                    {
-                                        @Override
-                                        public void receive( Reader item )
-                                            throws ReceiverThrowableType
-                                        {
-                                            final EntityState entity = readEntityState( module, item );
-                                            if( entity.status() == EntityStatus.UPDATED )
-                                            {
-                                                migrated.add( entity );
-
-                                                // Synch back 100 at a time
-                                                if( migrated.size() > 100 )
-                                                {
-                                                    try
-                                                    {
-                                                        synchMigratedEntities( migrated );
-                                                    }
-                                                    catch( IOException e )
-                                                    {
-                                                        throw new EntityStoreException( "Synchronization of Migrated Entities failed.", e );
-                                                    }
-                                                }
-                                            }
-                                            receiver.receive( entity );
-                                        }
-                                    } );
-
-                                    // Synch any remaining migrated entities
-                                    if( !migrated.isEmpty() )
-                                    {
-                                        try
-                                        {
-                                            synchMigratedEntities( migrated );
-                                        }
-                                        catch( IOException e )
-                                        {
-                                            throw new EntityStoreException( "Synchronization of Migrated Entities failed.", e );
-                                        }
-                                    }
-                                }
-                            } );
-                        }
-                        catch( IOException e )
-                        {
-                            throw new EntityStoreException( e );
-                        }
-                    }
-                } );
-            }
-        };
-    }
-
-    private void synchMigratedEntities( final List<EntityState> migratedEntities )
-        throws IOException
-    {
-        mapEntityStore.applyChanges( new MapEntityStore.MapChanges()
-        {
-            @Override
-            public void visitMap( MapEntityStore.MapChanger changer )
-                throws IOException
-            {
-                for( EntityState migratedEntity : migratedEntities )
-                {
-                    JSONEntityState state = (JSONEntityState) migratedEntity;
-                    try (Writer writer = changer.updateEntity( state.identity(), state.entityDescriptor() ))
-                    {
-                        writeEntityState( state, writer, state.version(), state.lastModified() );
-                    }
-                }
-            }
-        } );
-        migratedEntities.clear();
-    }
-
-    protected String newUnitOfWorkId()
-    {
-        return uuid + Integer.toHexString( count++ );
-    }
-
-    protected void writeEntityState( JSONEntityState state, Writer writer, String identity, long lastModified )
-        throws EntityStoreException
-    {
-        try
-        {
-            JSONObject jsonState = state.state();
-            jsonState.put( JSONKeys.VERSION, identity );
-            jsonState.put( JSONKeys.MODIFIED, lastModified );
-            writer.append( jsonState.toString() );
-        }
-        catch( JSONException | IOException e )
-        {
-            throw new EntityStoreException( "Could not store EntityState", e );
-        }
-    }
-
-    protected JSONEntityState readEntityState( ModuleSpi module, Reader entityState )
-        throws EntityStoreException
-    {
-        try
-        {
-            JSONObject jsonObject = new JSONObject( new JSONTokener( entityState ) );
-            EntityStatus status = EntityStatus.LOADED;
-
-            String version = jsonObject.getString( JSONKeys.VERSION );
-            long modified = jsonObject.getLong( JSONKeys.MODIFIED );
-            String identity = jsonObject.getString( JSONKeys.IDENTITY );
-
-            // Check if NamedAssociation is supported
-            if( !jsonObject.has( JSONKeys.NAMED_ASSOCIATIONS ) )
-            {
-                jsonObject.put( JSONKeys.NAMED_ASSOCIATIONS, new JSONObject() );
-            }
-
-            // Check if version is correct
-            String currentAppVersion = jsonObject.optString( JSONKeys.APPLICATION_VERSION, "0.0" );
-            if( !currentAppVersion.equals( application.version() ) )
-            {
-                if( migration != null )
-                {
-                    migration.migrate( jsonObject, application.version(), this );
-                }
-                else
-                {
-                    // Do nothing - set version to be correct
-                    jsonObject.put( JSONKeys.APPLICATION_VERSION, application.version() );
-                }
-                // State changed
-                status = EntityStatus.UPDATED;
-            }
-
-            String type = jsonObject.getString( JSONKeys.TYPE );
-
-            EntityDescriptor entityDescriptor = module.entityDescriptor( type );
-            if( entityDescriptor == null )
-            {
-                throw new EntityTypeNotFoundException( type,
-                                                       module.name(),
-                                                       map( ModelModule.toStringFunction,
-                                                            module.findVisibleEntityTypes()
-                                                       ) );
-            }
-
-            return new JSONEntityState( valueSerialization,
-                                        version,
-                                        modified,
-                                        EntityReference.parseEntityReference( identity ),
-                                        status,
-                                        entityDescriptor,
-                                        jsonObject
-            );
-        }
-        catch( JSONException e )
-        {
-            throw new EntityStoreException( e );
-        }
-    }
-
-    @Override
-    public JSONObject jsonStateOf( String id )
-        throws IOException
-    {
-        try (Reader reader = mapEntityStore.get( EntityReference.parseEntityReference( id ) ))
-        {
-            return new JSONObject( new JSONTokener( reader ) );
-        }
-        catch( JSONException e )
-        {
-            throw new IOException( e );
-        }
-    }
-
-    private EntityState fetchCachedState( EntityReference identity, ModuleSpi module, long currentTime )
-    {
-        CacheState cacheState = cache.get( identity.identity() );
-        if( cacheState != null )
-        {
-            JSONObject data = cacheState.json;
-            try
-            {
-                String type = data.getString( JSONKeys.TYPE );
-                EntityDescriptor entityDescriptor = module.entityDescriptor( type );
-//                return new JSONEntityState( currentTime, valueSerialization, identity, entityDescriptor, data );
-                return new JSONEntityState( valueSerialization, data.getString( JSONKeys.VERSION ), data.getLong( JSONKeys.MODIFIED ), identity, EntityStatus.LOADED, entityDescriptor, data );
-            }
-            catch( JSONException e )
-            {
-                // Should not be able to happen, unless internal error in the cache system.
-                throw new EntityStoreException( e );
-            }
-        }
-        return null;
-    }
-
-    private boolean doCacheOnRead( EntityStoreUnitOfWork unitOfWork )
-    {
-        CacheOptions cacheOptions = unitOfWork.usecase().metaInfo( CacheOptions.class );
-        return cacheOptions == null || cacheOptions.cacheOnRead();
-    }
-
-    public static class CacheState
-        implements Externalizable
-    {
-        public JSONObject json;
-
-        public CacheState()
-        {
-        }
-
-        private CacheState( JSONObject state )
-        {
-            json = state;
-        }
-
-        @Override
-        public void writeExternal( ObjectOutput out )
-            throws IOException
-        {
-            out.writeUTF( json.toString() );
-        }
-
-        @Override
-        public void readExternal( ObjectInput in )
-            throws IOException, ClassNotFoundException
-        {
-            try
-            {
-                json = new JSONObject( in.readUTF() );
-            }
-            catch( JSONException e )
-            {
-                throw new IOException( e );
-            }
-        }
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONNamedAssociationState.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONNamedAssociationState.java
deleted file mode 100644
index e183e53..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/JSONNamedAssociationState.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (c) 2009-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2007-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.spi.entitystore.helpers;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.spi.entity.NamedAssociationState;
-import org.qi4j.spi.entitystore.EntityStoreException;
-
-/**
- * JSON implementation of NamedAssociationState.
- * <p>Backed by a JSONObject.</p>
- */
-public final class JSONNamedAssociationState
-    implements NamedAssociationState
-{
-
-    private final JSONEntityState entityState;
-    private final JSONObject references;
-
-    public JSONNamedAssociationState( JSONEntityState entityState, JSONObject references )
-    {
-        this.entityState = entityState;
-        this.references = references;
-    }
-
-    @Override
-    public int count()
-    {
-        return references.length();
-    }
-
-    @Override
-    public boolean containsName( String name )
-    {
-        return references.has( name );
-    }
-
-    @Override
-    public boolean put( String name, EntityReference entityReference )
-    {
-        try
-        {
-            if( references.has( name ) && entityReference.identity().equals( references.getString( name ) ) )
-            {
-                return false;
-            }
-            entityState.cloneStateIfGlobalStateLoaded();
-            references.put( name, entityReference.identity() );
-            entityState.markUpdated();
-            return true;
-        }
-        catch( JSONException ex )
-        {
-            throw new EntityStoreException( ex );
-        }
-    }
-
-    @Override
-    public boolean remove( String name )
-    {
-        if( !references.has( name ) )
-        {
-            return false;
-        }
-        entityState.cloneStateIfGlobalStateLoaded();
-        references.remove( name );
-        entityState.markUpdated();
-        return true;
-    }
-
-    @Override
-    public EntityReference get( String name )
-    {
-        try
-        {
-            return new EntityReference( references.getString( name ) );
-        }
-        catch( JSONException ex )
-        {
-            return null;
-        }
-    }
-
-    @Override
-    public String nameOf( EntityReference entityReference )
-    {
-        JSONArray names = references.names();
-        if( names == null )
-        {
-            return null;
-        }
-        try
-        {
-            for( int idx = 0; idx < names.length(); idx++ )
-            {
-                String name = names.getString( idx );
-                if( entityReference.identity().equals( references.getString( name ) ) )
-                {
-                    return name;
-                }
-            }
-            return null;
-        }
-        catch( JSONException ex )
-        {
-            throw new EntityStoreException( ex );
-        }
-    }
-
-    @Override
-    public Iterator<String> iterator()
-    {
-        final JSONArray names = references.names() == null ? new JSONArray() : references.names();
-        return new Iterator<String>()
-        {
-            private int idx = 0;
-
-            @Override
-            public boolean hasNext()
-            {
-                return idx < names.length();
-            }
-
-            @Override
-            public String next()
-            {
-                try
-                {
-                    String next = names.getString( idx );
-                    idx++;
-                    return next;
-                }
-                catch( JSONException ex )
-                {
-                    throw new NoSuchElementException();
-                }
-            }
-
-            @Override
-            public void remove()
-            {
-                throw new UnsupportedOperationException( "remove() is not supported on NamedAssociation iterators." );
-            }
-        };
-    }
-
-    @Override
-    public String toString()
-    {
-        return references.toString();
-    }
-
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/MapEntityStore.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/MapEntityStore.java
deleted file mode 100644
index 1b87f22..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/MapEntityStore.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.entitystore.helpers;
-
-import java.io.IOException;
-import java.io.Reader;
-import java.io.Writer;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.io.Input;
-import org.qi4j.spi.entitystore.EntityNotFoundException;
-import org.qi4j.spi.entitystore.EntityStoreException;
-
-/**
- * MapEntityStore.
- */
-public interface MapEntityStore
-{
-
-    /**
-     * @param entityReference The reference to the entity that we want to get.
-     * @return Entity state Reader
-     */
-    Reader get( EntityReference entityReference )
-        throws EntityStoreException;
-
-    /**
-     * @return All entities state Readers
-     */
-    Input<Reader, IOException> entityStates();
-
-    void applyChanges( MapChanges changes )
-        throws IOException;
-
-    /**
-     * Changes to be applied on a MapEntityStore.
-     */
-    interface MapChanges
-    {
-
-        /**
-         * Visitable MapChanges.
-         */
-        void visitMap( MapChanger changer )
-            throws IOException;
-
-    }
-
-    /**
-     * MapEntityStore changes applier.
-     */
-    interface MapChanger
-    {
-
-        Writer newEntity( EntityReference ref, EntityDescriptor entityDescriptor )
-            throws IOException;
-
-        Writer updateEntity( EntityReference ref, EntityDescriptor entityDescriptor )
-            throws IOException;
-
-        void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor )
-            throws EntityNotFoundException;
-
-    }
-
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/MapEntityStoreActivation.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/MapEntityStoreActivation.java
deleted file mode 100644
index 5e7d87a..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/MapEntityStoreActivation.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.spi.entitystore.helpers;
-
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.service.ServiceReference;
-
-/**
- * Activation for MapEntityStoreMixin.
- */
-@Activators( MapEntityStoreActivation.Activator.class )
-public interface MapEntityStoreActivation
-{
-
-    void activateMapEntityStore()
-        throws Exception;
-
-    /**
-     * MapEntityStoreMixin Activator.
-     */
-    class Activator
-        extends ActivatorAdapter<ServiceReference<MapEntityStoreActivation>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<MapEntityStoreActivation> activated )
-            throws Exception
-        {
-            activated.get().activateMapEntityStore();
-        }
-
-    }
-
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/MapEntityStoreMixin.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/MapEntityStoreMixin.java
deleted file mode 100644
index a2d02bc..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/MapEntityStoreMixin.java
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * Copyright (c) 2009-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2009-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.spi.entitystore.helpers;
-
-import java.io.IOException;
-import java.io.Reader;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.json.JSONTokener;
-import org.json.JSONWriter;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.service.qualifier.Tagged;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.api.unitofwork.EntityTypeNotFoundException;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.spi.Qi4jSPI;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.EntityStatus;
-import org.qi4j.spi.entitystore.DefaultEntityStoreUnitOfWork;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.EntityStoreException;
-import org.qi4j.spi.entitystore.EntityStoreSPI;
-import org.qi4j.spi.entitystore.EntityStoreUnitOfWork;
-import org.qi4j.spi.entitystore.ModuleEntityStoreUnitOfWork;
-import org.qi4j.spi.entitystore.StateCommitter;
-import org.qi4j.spi.module.ModelModule;
-import org.qi4j.spi.module.ModuleSpi;
-
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.map;
-
-/**
- * Implementation of EntityStore that works with an implementation of MapEntityStore.
- *
- * <p>Implement {@link MapEntityStore} and add as mixin to the service using this mixin.</p>
- * <p>See {@link org.qi4j.entitystore.memory.MemoryMapEntityStoreMixin} for reference.</p>
- * <p>EntityStores based on this mixin gets support for the <b>Migration</b> extension.</p>
- * <p>MapEntityStore implementations will get their values as JSON.</p>
- */
-public class MapEntityStoreMixin
-    implements EntityStore, EntityStoreSPI, StateStore, MapEntityStoreActivation
-{
-    @This
-    private MapEntityStore mapEntityStore;
-
-    @This
-    private EntityStoreSPI entityStoreSpi;
-
-    @Structure
-    private Qi4jSPI spi;
-
-    @Structure
-    private Application application;
-
-    @Service
-    @Tagged( ValueSerialization.Formats.JSON )
-    private ValueSerialization valueSerialization;
-
-    @Optional
-    @Service
-    private Migration migration;
-
-    @Uses
-    private ServiceDescriptor descriptor;
-
-    protected String uuid;
-    private int count;
-
-    @Override
-    public void activateMapEntityStore()
-        throws Exception
-    {
-        uuid = UUID.randomUUID().toString() + "-";
-    }
-
-    // EntityStore
-    @Override
-    public EntityStoreUnitOfWork newUnitOfWork( Usecase usecaseMetaInfo, ModuleSpi module, long currentTime )
-    {
-        EntityStoreUnitOfWork storeUnitOfWork =
-            new DefaultEntityStoreUnitOfWork( entityStoreSpi, newUnitOfWorkId(), usecaseMetaInfo, currentTime );
-        storeUnitOfWork = new ModuleEntityStoreUnitOfWork( module, storeUnitOfWork );
-        return storeUnitOfWork;
-    }
-
-    // EntityStoreSPI
-    @Override
-    public EntityState newEntityState( EntityStoreUnitOfWork unitOfWork,
-                                       ModuleSpi module,
-                                       EntityReference identity,
-                                       EntityDescriptor entityDescriptor
-    )
-    {
-        return new DefaultEntityState( unitOfWork.currentTime(), identity, entityDescriptor );
-    }
-
-    @Override
-    public synchronized EntityState entityStateOf( EntityStoreUnitOfWork unitofwork,
-                                                   ModuleSpi module,
-                                                   EntityReference identity
-    )
-    {
-        Reader in = mapEntityStore.get( identity );
-        return readEntityState( module, in );
-    }
-
-    @Override
-    public StateCommitter applyChanges( final EntityStoreUnitOfWork unitofwork, final Iterable<EntityState> state
-    )
-        throws EntityStoreException
-    {
-        return new StateCommitter()
-        {
-            @Override
-            public void commit()
-            {
-                try
-                {
-                    mapEntityStore.applyChanges( new MapEntityStore.MapChanges()
-                    {
-                        @Override
-                        public void visitMap( MapEntityStore.MapChanger changer )
-                            throws IOException
-                        {
-                            for( EntityState entityState : state )
-                            {
-                                DefaultEntityState state = (DefaultEntityState) entityState;
-                                if( state.status().equals( EntityStatus.NEW ) )
-                                {
-                                    try (Writer writer = changer.newEntity( state.identity(), state.entityDescriptor() ))
-                                    {
-                                        writeEntityState( state, writer, unitofwork.identity(), unitofwork.currentTime() );
-                                    }
-                                }
-                                else if( state.status().equals( EntityStatus.UPDATED ) )
-                                {
-                                    try (Writer writer = changer.updateEntity( state.identity(), state.entityDescriptor() ))
-                                    {
-                                        writeEntityState( state, writer, unitofwork.identity(), unitofwork.currentTime() );
-                                    }
-                                }
-                                else if( state.status().equals( EntityStatus.REMOVED ) )
-                                {
-                                    changer.removeEntity( state.identity(), state.entityDescriptor() );
-                                }
-                            }
-                        }
-                    } );
-                }
-                catch( IOException e )
-                {
-                    throw new EntityStoreException( e );
-                }
-            }
-
-            @Override
-            public void cancel()
-            {
-            }
-        };
-    }
-
-    @Override
-    public Input<EntityState, EntityStoreException> entityStates( final ModuleSpi module )
-    {
-        return new Input<EntityState, EntityStoreException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super EntityState, ReceiverThrowableType> output )
-                throws EntityStoreException, ReceiverThrowableType
-            {
-                output.receiveFrom( new Sender<EntityState, EntityStoreException>()
-                {
-                    @Override
-                    public <ReceiverThrowableType extends Throwable> void sendTo( final Receiver<? super EntityState, ReceiverThrowableType> receiver )
-                        throws ReceiverThrowableType, EntityStoreException
-                    {
-                        final List<EntityState> migrated = new ArrayList<>();
-                        try
-                        {
-                            mapEntityStore.entityStates().transferTo( new Output<Reader, ReceiverThrowableType>()
-                            {
-                                @Override
-                                public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends Reader, SenderThrowableType> sender )
-                                    throws ReceiverThrowableType, SenderThrowableType
-                                {
-                                    sender.sendTo( new Receiver<Reader, ReceiverThrowableType>()
-                                    {
-                                        @Override
-                                        public void receive( Reader item )
-                                            throws ReceiverThrowableType
-                                        {
-                                            final EntityState entity = readEntityState( module, item );
-                                            if( entity.status() == EntityStatus.UPDATED )
-                                            {
-                                                migrated.add( entity );
-
-                                                // Synch back 100 at a time
-                                                if( migrated.size() > 100 )
-                                                {
-                                                    try
-                                                    {
-                                                        synchMigratedEntities( migrated );
-                                                    }
-                                                    catch( IOException e )
-                                                    {
-                                                        throw new EntityStoreException( "Synchronization of Migrated Entities failed.", e );
-                                                    }
-                                                }
-                                            }
-                                            receiver.receive( entity );
-                                        }
-                                    } );
-
-                                    // Synch any remaining migrated entities
-                                    if( !migrated.isEmpty() )
-                                    {
-                                        try
-                                        {
-                                            synchMigratedEntities( migrated );
-                                        }
-                                        catch( IOException e )
-                                        {
-                                            throw new EntityStoreException( "Synchronization of Migrated Entities failed.", e );
-                                        }
-                                    }
-                                }
-                            } );
-                        }
-                        catch( IOException e )
-                        {
-                            throw new EntityStoreException( e );
-                        }
-                    }
-                } );
-            }
-        };
-    }
-
-    private void synchMigratedEntities( final List<EntityState> migratedEntities )
-        throws IOException
-    {
-        mapEntityStore.applyChanges( new MapEntityStore.MapChanges()
-        {
-            @Override
-            public void visitMap( MapEntityStore.MapChanger changer )
-                throws IOException
-            {
-                for( EntityState migratedEntity : migratedEntities )
-                {
-                    DefaultEntityState state = (DefaultEntityState) migratedEntity;
-                    try (Writer writer = changer.updateEntity( state.identity(), state.entityDescriptor() ))
-                    {
-                        writeEntityState( state, writer, state.version(), state.lastModified() );
-                    }
-                }
-            }
-        } );
-        migratedEntities.clear();
-    }
-
-    protected String newUnitOfWorkId()
-    {
-        return uuid + Integer.toHexString( count++ );
-    }
-
-    protected void writeEntityState( DefaultEntityState state, Writer writer, String version, long lastModified )
-        throws EntityStoreException
-    {
-        try
-        {
-            JSONWriter json = new JSONWriter( writer );
-            JSONWriter properties = json.object().
-                key( JSONKeys.IDENTITY ).value( state.identity().identity() ).
-                key( JSONKeys.APPLICATION_VERSION ).value( application.version() ).
-                key( JSONKeys.TYPE ).value( first( state.entityDescriptor().types() ).getName() ).
-                key( JSONKeys.VERSION ).value( version ).
-                key( JSONKeys.MODIFIED ).value( lastModified ).
-                key( JSONKeys.PROPERTIES ).object();
-            EntityDescriptor entityType = state.entityDescriptor();
-            for( PropertyDescriptor persistentProperty : entityType.state().properties() )
-            {
-                Object value = state.properties().get( persistentProperty.qualifiedName() );
-                json.key( persistentProperty.qualifiedName().name() );
-                if( value == null || ValueType.isPrimitiveValue( value ) )
-                {
-                    json.value( value );
-                }
-                else
-                {
-                    String serialized = valueSerialization.serialize( value );
-                    if( serialized.startsWith( "{" ) )
-                    {
-                        json.value( new JSONObject( serialized ) );
-                    }
-                    else if( serialized.startsWith( "[" ) )
-                    {
-                        json.value( new JSONArray( serialized ) );
-                    }
-                    else
-                    {
-                        json.value( serialized );
-                    }
-                }
-            }
-
-            JSONWriter associations = properties.endObject().key( JSONKeys.ASSOCIATIONS ).object();
-            for( Map.Entry<QualifiedName, EntityReference> stateNameEntityReferenceEntry : state.associations()
-                .entrySet() )
-            {
-                EntityReference value = stateNameEntityReferenceEntry.getValue();
-                associations.key( stateNameEntityReferenceEntry.getKey().name() ).
-                    value( value != null ? value.identity() : null );
-            }
-
-            JSONWriter manyAssociations = associations.endObject().key( JSONKeys.MANY_ASSOCIATIONS ).object();
-            for( Map.Entry<QualifiedName, List<EntityReference>> stateNameListEntry : state.manyAssociations()
-                .entrySet() )
-            {
-                JSONWriter assocs = manyAssociations.key( stateNameListEntry.getKey().name() ).array();
-                for( EntityReference entityReference : stateNameListEntry.getValue() )
-                {
-                    assocs.value( entityReference.identity() );
-                }
-                assocs.endArray();
-            }
-
-            JSONWriter namedAssociations = manyAssociations.endObject().key( JSONKeys.NAMED_ASSOCIATIONS ).object();
-            for( Map.Entry<QualifiedName, Map<String, EntityReference>> stateNameMapEntry : state.namedAssociations()
-                .entrySet() )
-            {
-                JSONWriter assocs = namedAssociations.key( stateNameMapEntry.getKey().name() ).object();
-                for( Map.Entry<String, EntityReference> namedRef : stateNameMapEntry.getValue().entrySet() )
-                {
-                    assocs.key( namedRef.getKey() ).value( namedRef.getValue().identity() );
-                }
-                assocs.endObject();
-            }
-            namedAssociations.endObject().endObject();
-        }
-        catch( JSONException e )
-        {
-            throw new EntityStoreException( "Could not store EntityState", e );
-        }
-    }
-
-    protected EntityState readEntityState( ModuleSpi module, Reader entityState )
-        throws EntityStoreException
-    {
-        try
-        {
-            JSONObject jsonObject = new JSONObject( new JSONTokener( entityState ) );
-            EntityStatus status = EntityStatus.LOADED;
-
-            String version = jsonObject.getString( JSONKeys.VERSION );
-            long modified = jsonObject.getLong( JSONKeys.MODIFIED );
-            String identity = jsonObject.getString( JSONKeys.IDENTITY );
-
-            // Check if version is correct
-            String currentAppVersion = jsonObject.optString( JSONKeys.APPLICATION_VERSION, "0.0" );
-            if( !currentAppVersion.equals( application.version() ) )
-            {
-                if( migration != null )
-                {
-                    migration.migrate( jsonObject, application.version(), this );
-                }
-                else
-                {
-                    // Do nothing - set version to be correct
-                    jsonObject.put( JSONKeys.APPLICATION_VERSION, application.version() );
-                }
-                // State changed
-                status = EntityStatus.UPDATED;
-            }
-
-            String type = jsonObject.getString( JSONKeys.TYPE );
-
-            EntityDescriptor entityDescriptor = module.entityDescriptor( type );
-            if( entityDescriptor == null )
-            {
-                throw new EntityTypeNotFoundException( type,
-                                                       module.name(),
-                                                       map( ModelModule.toStringFunction,
-                                                            module.findVisibleEntityTypes()
-                                                       ) );
-            }
-
-            Map<QualifiedName, Object> properties = new HashMap<>();
-            JSONObject props = jsonObject.getJSONObject( JSONKeys.PROPERTIES );
-            for( PropertyDescriptor propertyDescriptor : entityDescriptor.state().properties() )
-            {
-                Object jsonValue;
-                try
-                {
-                    jsonValue = props.get( propertyDescriptor.qualifiedName().name() );
-                }
-                catch( JSONException e )
-                {
-                    // Value not found, default it
-                    Object initialValue = propertyDescriptor.initialValue( module );
-                    properties.put( propertyDescriptor.qualifiedName(), initialValue );
-                    status = EntityStatus.UPDATED;
-                    continue;
-                }
-                if( JSONObject.NULL.equals( jsonValue ) )
-                {
-                    properties.put( propertyDescriptor.qualifiedName(), null );
-                }
-                else
-                {
-                    Object value = valueSerialization.deserialize( propertyDescriptor.valueType(), jsonValue.toString() );
-                    properties.put( propertyDescriptor.qualifiedName(), value );
-                }
-            }
-
-            Map<QualifiedName, EntityReference> associations = new HashMap<>();
-            JSONObject assocs = jsonObject.getJSONObject( JSONKeys.ASSOCIATIONS );
-            for( AssociationDescriptor associationType : entityDescriptor.state().associations() )
-            {
-                try
-                {
-                    Object jsonValue = assocs.get( associationType.qualifiedName().name() );
-                    EntityReference value = jsonValue == JSONObject.NULL
-                                            ? null
-                                            : EntityReference.parseEntityReference( (String) jsonValue );
-                    associations.put( associationType.qualifiedName(), value );
-                }
-                catch( JSONException e )
-                {
-                    // Association not found, default it to null
-                    associations.put( associationType.qualifiedName(), null );
-                    status = EntityStatus.UPDATED;
-                }
-            }
-
-            JSONObject manyAssocs = jsonObject.getJSONObject( JSONKeys.MANY_ASSOCIATIONS );
-            Map<QualifiedName, List<EntityReference>> manyAssociations = new HashMap<>();
-            for( AssociationDescriptor manyAssociationType : entityDescriptor.state().manyAssociations() )
-            {
-                List<EntityReference> references = new ArrayList<>();
-                try
-                {
-                    JSONArray jsonValues = manyAssocs.getJSONArray( manyAssociationType.qualifiedName().name() );
-                    for( int i = 0; i < jsonValues.length(); i++ )
-                    {
-                        Object jsonValue = jsonValues.getString( i );
-                        EntityReference value = jsonValue == JSONObject.NULL
-                                                ? null
-                                                : EntityReference.parseEntityReference( (String) jsonValue );
-                        references.add( value );
-                    }
-                    manyAssociations.put( manyAssociationType.qualifiedName(), references );
-                }
-                catch( JSONException e )
-                {
-                    // ManyAssociation not found, default to empty one
-                    manyAssociations.put( manyAssociationType.qualifiedName(), references );
-                }
-            }
-
-            JSONObject namedAssocs = jsonObject.getJSONObject( JSONKeys.NAMED_ASSOCIATIONS );
-            Map<QualifiedName, Map<String, EntityReference>> namedAssociations = new HashMap<>();
-            for( AssociationDescriptor namedAssociationType : entityDescriptor.state().namedAssociations() )
-            {
-                Map<String, EntityReference> references = new LinkedHashMap<>();
-                try
-                {
-                    JSONObject jsonValues = namedAssocs.getJSONObject( namedAssociationType.qualifiedName().name() );
-                    JSONArray names = jsonValues.names();
-                    if( names != null )
-                    {
-                        for( int idx = 0; idx < names.length(); idx++ )
-                        {
-                            String name = names.getString( idx );
-                            Object value = jsonValues.get( name );
-                            EntityReference ref = value == JSONObject.NULL
-                                                  ? null
-                                                  : EntityReference.parseEntityReference( (String) value );
-                            references.put( name, ref );
-                        }
-                    }
-                    namedAssociations.put( namedAssociationType.qualifiedName(), references );
-                }
-                catch( JSONException e )
-                {
-                    // NamedAssociation not found, default to empty one
-                    namedAssociations.put( namedAssociationType.qualifiedName(), references );
-                }
-            }
-
-            return new DefaultEntityState( version,
-                                           modified,
-                                           EntityReference.parseEntityReference( identity ),
-                                           status,
-                                           entityDescriptor,
-                                           properties,
-                                           associations,
-                                           manyAssociations,
-                                           namedAssociations
-            );
-        }
-        catch( JSONException e )
-        {
-            throw new EntityStoreException( e );
-        }
-    }
-
-    @Override
-    public JSONObject jsonStateOf( String id )
-        throws IOException
-    {
-        JSONObject jsonObject;
-        try (Reader reader = mapEntityStore.get( EntityReference.parseEntityReference( id ) ))
-        {
-            jsonObject = new JSONObject( new JSONTokener( reader ) );
-        }
-        catch( JSONException e )
-        {
-            throw new IOException( e );
-        }
-        return jsonObject;
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/Migration.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/Migration.java
deleted file mode 100644
index 33cee60..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/Migration.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.entitystore.helpers;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-/**
- * State Migration SPI.
- */
-public interface Migration
-{
-    boolean migrate( JSONObject state, String toVersion, StateStore stateStore )
-        throws JSONException;
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/StateStore.java b/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/StateStore.java
deleted file mode 100644
index 02c6778..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/StateStore.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.entitystore.helpers;
-
-import java.io.IOException;
-import org.json.JSONObject;
-
-/**
- * StateStore SPI.
- */
-public interface StateStore
-{
-    JSONObject jsonStateOf( String id )
-        throws IOException;
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/package.html b/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/package.html
deleted file mode 100644
index 1196526..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/helpers/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EntityStore Helpers.</h2>
-    </body>
-</html>
diff --git a/core/spi/src/main/java/org/qi4j/spi/entitystore/package.html b/core/spi/src/main/java/org/qi4j/spi/entitystore/package.html
deleted file mode 100644
index 5f55399..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/entitystore/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EntityStore SPI.</h2>
-    </body>
-</html>
diff --git a/core/spi/src/main/java/org/qi4j/spi/metrics/DefaultMetric.java b/core/spi/src/main/java/org/qi4j/spi/metrics/DefaultMetric.java
deleted file mode 100644
index 87320d8..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/metrics/DefaultMetric.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.metrics;
-
-import org.qi4j.api.metrics.MetricsCounter;
-import org.qi4j.api.metrics.MetricsGauge;
-import org.qi4j.api.metrics.MetricsHealthCheck;
-import org.qi4j.api.metrics.MetricsHistogram;
-import org.qi4j.api.metrics.MetricsMeter;
-import org.qi4j.api.metrics.MetricsTimer;
-
-/**
- * Default Metric implementing all supported Metrics as a null object.
- */
-public final class DefaultMetric
-    implements MetricsGauge, MetricsCounter, MetricsHistogram, MetricsHealthCheck, MetricsMeter, MetricsTimer
-{
-    public static final DefaultMetric NULL = new DefaultMetric();
-
-    @Override
-    public void increment()
-    {
-    }
-
-    @Override
-    public void increment( int steps )
-    {
-    }
-
-    @Override
-    public void decrement()
-    {
-    }
-
-    @Override
-    public void decrement( int steps )
-    {
-    }
-
-    @Override
-    public Context start()
-    {
-        return new Context()
-        {
-            @Override
-            public void stop()
-            {
-            }
-        };
-    }
-
-    @Override
-    public Object value()
-    {
-        return null;
-    }
-
-    @Override
-    public void update( long newValue )
-    {
-    }
-
-    @Override
-    public Result check()
-        throws Exception
-    {
-        return new Result( true, "No checks", null );
-    }
-
-    @Override
-    public void mark()
-    {
-    }
-
-    @Override
-    public void mark( int numberOfEvents )
-    {
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/metrics/MetricsProviderAdapter.java b/core/spi/src/main/java/org/qi4j/spi/metrics/MetricsProviderAdapter.java
deleted file mode 100644
index 7113363..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/metrics/MetricsProviderAdapter.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.metrics;
-
-import org.qi4j.api.metrics.MetricsCounterFactory;
-import org.qi4j.api.metrics.MetricsFactory;
-import org.qi4j.api.metrics.MetricsGaugeFactory;
-import org.qi4j.api.metrics.MetricsHealthCheckFactory;
-import org.qi4j.api.metrics.MetricsHistogramFactory;
-import org.qi4j.api.metrics.MetricsMeterFactory;
-import org.qi4j.api.metrics.MetricsNotSupportedException;
-import org.qi4j.api.metrics.MetricsProvider;
-import org.qi4j.api.metrics.MetricsTimerFactory;
-
-/**
- * Adapter to ease MetricsProvider implementation.
- */
-public class MetricsProviderAdapter
-    implements MetricsProvider
-{
-    private static final MetricsCounterFactory NULL_COUNTER_FACTORY = new NullMetricsFactory.NullCounterFactory();
-    private static final MetricsGaugeFactory NULL_GAUGE_FACTORY = new NullMetricsFactory.NullGaugeFactory();
-    private static final MetricsMeterFactory NULL_METER_FACTORY = new NullMetricsFactory.NullMeterFactory();
-    private static final MetricsHistogramFactory NULL_HISTOGRAM_FACTORY = new NullMetricsFactory.NullHistogramFactory();
-    private static final MetricsTimerFactory NULL_TIMER_FACTORY = new NullMetricsFactory.NullTimerFactory();
-    private static final MetricsHealthCheckFactory NULL_HEALTHCHECK_FACTORY = new NullMetricsFactory.NullHealthCheckFactory();
-
-    @SuppressWarnings( "unchecked" )
-    @Override
-    public <T extends MetricsFactory> T createFactory( Class<T> factoryType )
-    {
-        if( factoryType.equals( MetricsCounterFactory.class ) )
-        {
-            return (T) createMetricsCounterFactory();
-        }
-        else if( factoryType.equals( MetricsGaugeFactory.class ) )
-        {
-            return (T) createMetricsGaugeFactory();
-        }
-        else if( factoryType.equals( MetricsHealthCheckFactory.class ) )
-        {
-            return (T) createMetricsHealthCheckFactory();
-        }
-        else if( factoryType.equals( MetricsHistogramFactory.class ) )
-        {
-            return (T) createMetricsHistogramFactory();
-        }
-        else if( factoryType.equals( MetricsMeterFactory.class ) )
-        {
-            return (T) createMetricsMeterFactory();
-        }
-        else if( factoryType.equals( MetricsTimerFactory.class ) )
-        {
-            return (T) createMetricsTimerFactory();
-        }
-        throw new MetricsNotSupportedException( factoryType, getClass() );
-    }
-
-    protected MetricsTimerFactory createMetricsTimerFactory()
-    {
-        return NULL_TIMER_FACTORY;
-    }
-
-    protected MetricsMeterFactory createMetricsMeterFactory()
-    {
-        return NULL_METER_FACTORY;
-    }
-
-    protected MetricsHistogramFactory createMetricsHistogramFactory()
-    {
-        return NULL_HISTOGRAM_FACTORY;
-    }
-
-    protected MetricsHealthCheckFactory createMetricsHealthCheckFactory()
-    {
-        return NULL_HEALTHCHECK_FACTORY;
-    }
-
-    protected MetricsGaugeFactory createMetricsGaugeFactory()
-    {
-        return NULL_GAUGE_FACTORY;
-    }
-
-    protected MetricsCounterFactory createMetricsCounterFactory()
-    {
-        return NULL_COUNTER_FACTORY;
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/metrics/NullMetricsFactory.java b/core/spi/src/main/java/org/qi4j/spi/metrics/NullMetricsFactory.java
deleted file mode 100644
index f737c7c..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/metrics/NullMetricsFactory.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.metrics;
-
-import java.util.concurrent.TimeUnit;
-import org.qi4j.api.metrics.Metric;
-import org.qi4j.api.metrics.MetricsCounter;
-import org.qi4j.api.metrics.MetricsCounterFactory;
-import org.qi4j.api.metrics.MetricsGauge;
-import org.qi4j.api.metrics.MetricsGaugeFactory;
-import org.qi4j.api.metrics.MetricsHealthCheck;
-import org.qi4j.api.metrics.MetricsHealthCheckFactory;
-import org.qi4j.api.metrics.MetricsHistogram;
-import org.qi4j.api.metrics.MetricsHistogramFactory;
-import org.qi4j.api.metrics.MetricsMeter;
-import org.qi4j.api.metrics.MetricsMeterFactory;
-import org.qi4j.api.metrics.MetricsTimer;
-import org.qi4j.api.metrics.MetricsTimerFactory;
-import org.qi4j.functional.Iterables;
-
-/**
- * Factory for Metrics null objects.
- */
-public final class NullMetricsFactory
-{
-    public static class NullCounterFactory implements MetricsCounterFactory
-    {
-        @Override
-        public MetricsCounter createCounter( Class<?> origin, String name )
-        {
-            return DefaultMetric.NULL;
-        }
-
-        @Override
-        public Iterable<Metric> registered()
-        {
-            return Iterables.iterable( (Metric) DefaultMetric.NULL );
-        }
-    }
-
-    public static class NullGaugeFactory implements MetricsGaugeFactory
-    {
-        @Override
-        @SuppressWarnings( "unchecked" )
-        public <T> MetricsGauge<T> registerGauge( Class<?> origin, String name, MetricsGauge<T> gauge )
-        {
-            return DefaultMetric.NULL;
-        }
-
-        @Override
-        public Iterable<Metric> registered()
-        {
-            return Iterables.iterable( (Metric) DefaultMetric.NULL );
-        }
-    }
-
-    public static class NullHealthCheckFactory implements MetricsHealthCheckFactory
-    {
-        @Override
-        public MetricsHealthCheck registerHealthCheck( Class<?> origin, String name, MetricsHealthCheck check )
-        {
-            return DefaultMetric.NULL;
-        }
-
-        @Override
-        public Iterable<Metric> registered()
-        {
-            return Iterables.iterable( (Metric) DefaultMetric.NULL );
-        }
-    }
-
-    public static class NullHistogramFactory implements MetricsHistogramFactory
-    {
-        @Override
-        public MetricsHistogram createHistogram( Class<?> origin, String name )
-        {
-            return DefaultMetric.NULL;
-        }
-
-        @Override
-        public Iterable<Metric> registered()
-        {
-            return Iterables.iterable( (Metric) DefaultMetric.NULL );
-        }
-    }
-
-    public static class NullMeterFactory implements MetricsMeterFactory
-    {
-        @Override
-        public MetricsMeter createMeter( Class<?> origin, String name, String eventType, TimeUnit rate )
-        {
-
-            return DefaultMetric.NULL;
-        }
-
-        @Override
-        public Iterable<Metric> registered()
-        {
-            return Iterables.iterable( (Metric) DefaultMetric.NULL );
-        }
-    }
-
-    public static class NullTimerFactory implements MetricsTimerFactory
-    {
-        @Override
-        public MetricsTimer createTimer( Class<?> origin, String name, TimeUnit duration, TimeUnit rate )
-        {
-            return DefaultMetric.NULL;
-        }
-
-        @Override
-        public Iterable<Metric> registered()
-        {
-            return Iterables.iterable( (Metric) DefaultMetric.NULL );
-        }
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/metrics/package.html b/core/spi/src/main/java/org/qi4j/spi/metrics/package.html
deleted file mode 100644
index a6eaa36..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/metrics/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Metrics SPI.</h2>
-    </body>
-</html>
diff --git a/core/spi/src/main/java/org/qi4j/spi/module/ModelModule.java b/core/spi/src/main/java/org/qi4j/spi/module/ModelModule.java
deleted file mode 100644
index 4d7d37e..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/module/ModelModule.java
+++ /dev/null
@@ -1,124 +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.qi4j.spi.module;
-
-import org.qi4j.api.composite.ModelDescriptor;
-import org.qi4j.functional.Function;
-import org.qi4j.spi.Qi4jSPI;
-
-import static org.qi4j.functional.Iterables.map;
-
-/**
- * TODO
- */
-public class ModelModule<T extends ModelDescriptor>
-{
-
-    public static Function<?, String> toStringFunction = new Function<ModelModule<?>, String>()
-    {
-        @Override
-        public String map( ModelModule item )
-        {
-            return item.model()
-                       .types()
-                       .iterator()
-                       .next()
-                       .getName() + "[" + item.module().name() + "]";
-        }
-    };
-
-    public static <T extends ModelDescriptor> Function<T, ModelModule<T>> modelModuleFunction( final ModuleSpi module )
-    {
-        return new Function<T, ModelModule<T>>()
-        {
-            @Override
-            public ModelModule<T> map( T model )
-            {
-                return new ModelModule<>( module, model );
-            }
-        };
-    }
-
-    public static <T extends ModelDescriptor> Function<ModelModule<T>, T> modelFunction()
-    {
-        return new Function<ModelModule<T>, T>()
-        {
-            @Override
-            public T map( ModelModule<T> modelModule )
-            {
-                return modelModule.model();
-            }
-        };
-    }
-
-    private final ModuleSpi module;
-    private final T model;
-
-    public ModelModule( ModuleSpi module, T model )
-    {
-        this.module = module;
-        this.model = model;
-    }
-
-    public ModuleSpi module()
-    {
-        return module;
-    }
-
-    public T model()
-    {
-        return model;
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-
-        ModelModule that = (ModelModule) o;
-
-        if( model != null ? !model.equals( that.model ) : that.model != null )
-        {
-            return false;
-        }
-
-        return !( module != null ? !module.equals( that.module ) : that.module != null );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        int result = module != null ? module.hashCode() : 0;
-        result = 31 * result + ( model != null ? model.hashCode() : 0 );
-        return result;
-    }
-
-    @Override
-    public String toString()
-    {
-        return module.name() + ":" + model;
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/module/ModuleSpi.java b/core/spi/src/main/java/org/qi4j/spi/module/ModuleSpi.java
deleted file mode 100644
index de4a788..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/module/ModuleSpi.java
+++ /dev/null
@@ -1,46 +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.qi4j.spi.module;
-
-import org.qi4j.api.composite.TransientDescriptor;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.IdentityGenerator;
-import org.qi4j.api.object.ObjectDescriptor;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.spi.entitystore.EntityStore;
-
-public interface ModuleSpi extends Module
-{
-    EntityStore entityStore();
-
-    IdentityGenerator identityGenerator();
-
-    ValueSerialization valueSerialization();
-
-    Iterable<ModelModule<EntityDescriptor>> findVisibleEntityTypes();
-
-    Iterable<ModelModule<ValueDescriptor>> findVisibleValueTypes();
-
-    Iterable<ModelModule<TransientDescriptor>> findVisibleTransientTypes();
-
-    Iterable<ModelModule<ObjectDescriptor>> findVisibleObjectTypes();
-
-    Iterable<ModelModule<ServiceDescriptor>> findVisibleServiceTypes();
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/module/package.html b/core/spi/src/main/java/org/qi4j/spi/module/package.html
deleted file mode 100644
index ac6ddcf..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/module/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Module SPI.</h2>
-    </body>
-</html>
diff --git a/core/spi/src/main/java/org/qi4j/spi/package.html b/core/spi/src/main/java/org/qi4j/spi/package.html
deleted file mode 100644
index faaf1b7..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Apache Zest™ SPI.</h2>
-    </body>
-</html>
diff --git a/core/spi/src/main/java/org/qi4j/spi/query/EntityFinder.java b/core/spi/src/main/java/org/qi4j/spi/query/EntityFinder.java
deleted file mode 100644
index d00a99d..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/query/EntityFinder.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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
- *count( INTERFACES_OF.map( A.class ) ), equalTo( 1L )
- * 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.qi4j.spi.query;
-
-import java.util.Map;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.functional.Specification;
-
-/**
- * Entity Finder.
- */
-public interface EntityFinder
-{
-    /**
-     * Find entities matching the query criterion.
-     *
-     * @param resultType        Type that the entities must have.
-     * @param whereClause       Where clause specification.
-     * @param orderBySegments   Ordering
-     * @param firstResult       Index of the first returned entity.
-     * @param maxResults        Maximum returned entities.
-     * @param variables         Query variables
-     * @return Single entity matching the query criterion.
-     */
-    Iterable<EntityReference> findEntities( Class<?> resultType,
-                                            @Optional Specification<Composite> whereClause,
-                                            @Optional OrderBy[] orderBySegments,
-                                            @Optional Integer firstResult,
-                                            @Optional Integer maxResults,
-                                            Map<String, Object> variables
-    )
-        throws EntityFinderException;
-
-    /**
-     * Find a single entity matching the query criterion.
-     *
-     * @param resultType    Type that the entity must have.
-     * @param whereClause   Where clause specification.
-     * @param variables     Query variables
-     * @return Single entity matching the query criterion.
-     */
-    EntityReference findEntity( Class<?> resultType,
-                                @Optional Specification<Composite> whereClause,
-                                Map<String, Object> variables
-    )
-        throws EntityFinderException;
-
-    /**
-     * Count entities matching the query criterion.
-     *
-     * @param resultType    Type that the entities must have.
-     * @param whereClause   Where clause specification.
-     * @param variables     Query variables
-     * @return Count entities matching the query criterion.
-     */
-    long countEntities( Class<?> resultType,
-                        @Optional Specification<Composite> whereClause,
-                        Map<String, Object> variables
-    )
-        throws EntityFinderException;
-}
\ No newline at end of file
diff --git a/core/spi/src/main/java/org/qi4j/spi/query/EntityFinderException.java b/core/spi/src/main/java/org/qi4j/spi/query/EntityFinderException.java
deleted file mode 100644
index 359e970..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/query/EntityFinderException.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed 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.qi4j.spi.query;
-
-/**
- * Entity Finder Exception.
- */
-public class EntityFinderException
-    extends Exception
-{
-    public EntityFinderException( final String message )
-    {
-        super( message );
-    }
-
-    public EntityFinderException( final String message,
-                                  final Throwable throwable
-    )
-    {
-        super( message, throwable );
-    }
-
-    public EntityFinderException( final Throwable throwable )
-    {
-        super( throwable );
-    }
-}
\ No newline at end of file
diff --git a/core/spi/src/main/java/org/qi4j/spi/query/IndexExporter.java b/core/spi/src/main/java/org/qi4j/spi/query/IndexExporter.java
deleted file mode 100644
index 89e2ff1..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/query/IndexExporter.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.spi.query;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.io.PrintWriter;
-
-/**
- * Interface for exporting the index currently held by the Indexing Engine.
- * Index Engine implementations are encouraged to implement this interface to allow for trouble-shooting index related
- * problems.
- */
-public interface IndexExporter
-{
-    /**
-     * Write the index to the provided output stream in an implementation specific, human-readable format.
-     *
-     * @param out The output stream that the index will be sent to.
-     *
-     * @throws java.io.IOException           if an IOException occurs in the underlying PrintStream.
-     * @throws UnsupportedOperationException if the method is not supported by this implementation.
-     */
-    void exportReadableToStream( PrintStream out )
-        throws IOException, UnsupportedOperationException;
-
-    /**
-     * Write the index to the provided print writer in an implementation specific, machine-readable format, preferably
-     * either XML or JSON.
-     *
-     * @param out The print writer that the index will be sent to.
-     *
-     * @throws java.io.IOException           if an IOException occurs in the underlying PrintWriter.
-     * @throws UnsupportedOperationException if the method is not supported by this implementation.
-     */
-    void exportFormalToWriter( PrintWriter out )
-        throws IOException, UnsupportedOperationException;
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/query/QueryBuilderSPI.java b/core/spi/src/main/java/org/qi4j/spi/query/QueryBuilderSPI.java
deleted file mode 100644
index d04b1fb..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/query/QueryBuilderSPI.java
+++ /dev/null
@@ -1,29 +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.qi4j.spi.query;
-
-import org.qi4j.api.query.Query;
-
-/**
- * QueryBuilder SPI.
- */
-public interface QueryBuilderSPI<T>
-{
-    Query<T> newQuery( QuerySource querySource );
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/query/QuerySource.java b/core/spi/src/main/java/org/qi4j/spi/query/QuerySource.java
deleted file mode 100644
index 7e90084..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/query/QuerySource.java
+++ /dev/null
@@ -1,55 +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.qi4j.spi.query;
-
-import java.util.Iterator;
-import java.util.Map;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.functional.Specification;
-
-/**
- * Query Source, used in QueryBuilder SPI.
- */
-public interface QuerySource
-{
-    <T> T find( Class<T> resultType,
-                Specification<Composite> whereClause,
-                Iterable<OrderBy> orderBySegments,
-                Integer firstResult,
-                Integer maxResults,
-                Map<String, Object> variables
-    );
-
-    <T> long count( Class<T> resultType,
-                    Specification<Composite> whereClause,
-                    Iterable<OrderBy> orderBySegments,
-                    Integer firstResult,
-                    Integer maxResults,
-                    Map<String, Object> variables
-    );
-
-    <T> Iterator<T> iterator( Class<T> resultType,
-                              Specification<Composite> whereClause,
-                              Iterable<OrderBy> orderBySegments,
-                              Integer firstResult,
-                              Integer maxResults,
-                              Map<String, Object> variables
-    );
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/query/package.html b/core/spi/src/main/java/org/qi4j/spi/query/package.html
deleted file mode 100644
index 3cab930..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/query/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Index/Query SPI.</h2>
-    </body>
-</html>
diff --git a/core/spi/src/main/java/org/qi4j/spi/uuid/UuidIdentityGeneratorMixin.java b/core/spi/src/main/java/org/qi4j/spi/uuid/UuidIdentityGeneratorMixin.java
deleted file mode 100644
index 9b6a5f7..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/uuid/UuidIdentityGeneratorMixin.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*  Copyright 2007 Niclas Hedhman.
- *
- * Licensed 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.qi4j.spi.uuid;
-
-import java.util.UUID;
-import org.qi4j.api.entity.IdentityGenerator;
-
-/**
- * UUID based Identity generator mixin.
- */
-public class UuidIdentityGeneratorMixin
-    implements IdentityGenerator
-{
-    protected String uuid;
-    private int count;
-
-    public UuidIdentityGeneratorMixin()
-    {
-        uuid = UUID.randomUUID().toString() + "-";
-    }
-
-    @Override
-    public String generate( Class<?> compositeType )
-    {
-        return uuid + Integer.toHexString( count++ );
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/uuid/UuidIdentityGeneratorService.java b/core/spi/src/main/java/org/qi4j/spi/uuid/UuidIdentityGeneratorService.java
deleted file mode 100644
index 8552842..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/uuid/UuidIdentityGeneratorService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.uuid;
-
-import org.qi4j.api.entity.IdentityGenerator;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-/**
- * UUID based Identity generator Service.
- */
-@Mixins( UuidIdentityGeneratorMixin.class )
-public interface UuidIdentityGeneratorService
-    extends IdentityGenerator, ServiceComposite
-{
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/uuid/package.html b/core/spi/src/main/java/org/qi4j/spi/uuid/package.html
deleted file mode 100644
index fc37e36..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/uuid/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>UUID Identity SPI.</h2>
-    </body>
-</html>
diff --git a/core/spi/src/main/java/org/qi4j/spi/value/ValueDeserializerAdapter.java b/core/spi/src/main/java/org/qi4j/spi/value/ValueDeserializerAdapter.java
deleted file mode 100644
index 53cf81d..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/value/ValueDeserializerAdapter.java
+++ /dev/null
@@ -1,1100 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2010, Niclas Hehdman. All Rights Reserved.
- * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.value;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.Set;
-import org.joda.time.DateTime;
-import org.joda.time.LocalDate;
-import org.joda.time.LocalDateTime;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.type.CollectionType;
-import org.qi4j.api.type.EnumType;
-import org.qi4j.api.type.MapType;
-import org.qi4j.api.type.ValueCompositeType;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.api.type.Serialization;
-import org.qi4j.api.util.Base64Encoder;
-import org.qi4j.api.util.Dates;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.api.value.ValueDeserializer;
-import org.qi4j.api.value.ValueSerializationException;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Function2;
-
-import static org.qi4j.functional.Iterables.empty;
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Adapter for pull-parsing and tree-parsing capable ValueDeserializers.
- *
- * <p>
- *     Among Plain values (see {@link ValueDeserializer}) some are considered primitives to underlying serialization
- *     mechanisms and by so handed/come without conversion to/from implementations. Primitive values can be one of:
- * </p>
- * <ul>
- *     <li>String,</li>
- *     <li>Character or char,</li>
- *     <li>Boolean or boolean,</li>
- *     <li>Integer or int,</li>
- *     <li>Long or long,</li>
- *     <li>Short or short,</li>
- *     <li>Byte or byte,</li>
- *     <li>Float or float,</li>
- *     <li>Double or double.</li>
- * </ul>
- * <p>
- *     Some other Plain values are expected in given formats:
- * </p>
- * <ul>
- *     <li>BigInteger and BigDecimal depends on {@link org.qi4j.api.value.ValueSerializer.Options};</li>
- *     <li>Date as String in ISO-8601, {@literal @millis@} or {@literal /Date(..)} Microsoft format;</li>
- *     <li>DateTime (JodaTime) as a ISO-8601 String with optional timezone offset;</li>
- *     <li>LocalDateTime (JodaTime) as whatever {@link LocalDateTime#LocalDateTime(java.lang.Object)} accept as {@literal instant};</li>
- *     <li>LocalDate (JodaTime) as whatever {@link LocalDate#LocalDate(java.lang.Object)} accept as {@literal instant};</li>
- * </ul>
- *
- * @param <InputType> Implementor pull-parser type
- * @param <InputNodeType> Implementor tree-parser node type
- */
-public abstract class ValueDeserializerAdapter<InputType, InputNodeType>
-    implements ValueDeserializer
-{
-    public static interface ComplexDeserializer<T, InputType, InputNodeType>
-    {
-        T deserializePull( InputType input )
-            throws Exception;
-
-        T deserializeTree( InputNodeType inputNode )
-            throws Exception;
-    }
-
-    private static final String UTF_8 = "UTF-8";
-    private final Map<Class<?>, Function<Object, Object>> deserializers = new HashMap<>( 16 );
-    private final Map<Class<?>, ComplexDeserializer<Object, InputType, InputNodeType>> complexDeserializers = new HashMap<>( 2 );
-    private final Application application;
-    private final Module module;
-    private Function<Application, Module> valuesModuleFinder;
-    private Module valuesModule;
-
-    /**
-     * Register a Plain Value type deserialization Function.
-     *
-     * @param <T> Plain Value parametrized Type
-     * @param type Plain Value Type
-     * @param deserializer Deserialization Function
-     */
-    @SuppressWarnings( "unchecked" )
-    protected final <T> void registerDeserializer( Class<T> type, Function<Object, T> deserializer )
-    {
-        deserializers.put( type, (Function<Object, Object>) deserializer );
-    }
-
-    @SuppressWarnings( { "UnusedDeclaration", "unchecked" } )
-    protected final <T> void registerComplexDeserializer( Class<T> type,
-                                                          ComplexDeserializer<T, InputType, InputNodeType> deserializer )
-    {
-        complexDeserializers.put( type, (ComplexDeserializer<Object, InputType, InputNodeType>) deserializer );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public ValueDeserializerAdapter( @Structure Application application,
-                                     @Structure Module module,
-                                     @Service ServiceReference<ValueDeserializer> serviceRef )
-    {
-        this( application, module, serviceRef.metaInfo( Function.class ) );
-    }
-
-    protected ValueDeserializerAdapter( Application application,
-                                        Module module,
-                                        Function<Application, Module> valuesModuleFinder )
-    {
-
-        this.application = application;
-        this.module = module;
-        setValuesModuleFinder( valuesModuleFinder );
-
-        // Primitive Value types
-        registerDeserializer( String.class, new Function<Object, String>()
-        {
-            @Override
-            public String map( Object input )
-            {
-                return input.toString();
-            }
-        } );
-        registerDeserializer( Character.class, new Function<Object, Character>()
-        {
-            @Override
-            public Character map( Object input )
-            {
-                return input.toString().charAt( 0 );
-            }
-        } );
-        registerDeserializer( Boolean.class, new Function<Object, Boolean>()
-        {
-            @SuppressWarnings( "UnnecessaryUnboxing" )
-            @Override
-            public Boolean map( Object input )
-            {
-                return ( input instanceof String )
-                       ? Boolean.parseBoolean( (String) input )
-                       : ( (Boolean) input ).booleanValue();
-            }
-        } );
-        registerDeserializer( Integer.class, new Function<Object, Integer>()
-        {
-            @Override
-            public Integer map( Object input )
-            {
-                return ( input instanceof String )
-                       ? Integer.parseInt( (String) input )
-                       : ( (Number) input ).intValue();
-            }
-        } );
-        registerDeserializer( Long.class, new Function<Object, Long>()
-        {
-            @Override
-            public Long map( Object input )
-            {
-                return ( input instanceof String )
-                       ? Long.parseLong( (String) input )
-                       : ( (Number) input ).longValue();
-            }
-        } );
-        registerDeserializer( Short.class, new Function<Object, Short>()
-        {
-            @Override
-            public Short map( Object input )
-            {
-                return ( input instanceof String )
-                       ? Short.parseShort( (String) input )
-                       : ( (Number) input ).shortValue();
-            }
-        } );
-        registerDeserializer( Byte.class, new Function<Object, Byte>()
-        {
-            @Override
-            public Byte map( Object input )
-            {
-                return ( input instanceof String )
-                       ? Byte.parseByte( (String) input )
-                       : ( (Number) input ).byteValue();
-            }
-        } );
-        registerDeserializer( Float.class, new Function<Object, Float>()
-        {
-            @Override
-            public Float map( Object input )
-            {
-                return ( input instanceof String )
-                       ? Float.parseFloat( (String) input )
-                       : ( (Number) input ).floatValue();
-            }
-        } );
-        registerDeserializer( Double.class, new Function<Object, Double>()
-        {
-            @Override
-            public Double map( Object input )
-            {
-                return ( input instanceof String )
-                       ? Double.parseDouble( (String) input )
-                       : ( (Number) input ).doubleValue();
-            }
-        } );
-
-        // Number types
-        registerDeserializer( BigDecimal.class, new Function<Object, BigDecimal>()
-        {
-            @Override
-            public BigDecimal map( Object input )
-            {
-                return new BigDecimal( input.toString() );
-            }
-        } );
-        registerDeserializer( BigInteger.class, new Function<Object, BigInteger>()
-        {
-            @Override
-            public BigInteger map( Object input )
-            {
-                return new BigInteger( input.toString() );
-            }
-        } );
-
-        // Date types
-        registerDeserializer( Date.class, new Function<Object, Date>()
-        {
-            @Override
-            public Date map( Object input )
-            {
-                return Dates.fromString( input.toString() );
-            }
-        } );
-        registerDeserializer( DateTime.class, new Function<Object, DateTime>()
-        {
-            @Override
-            public DateTime map( Object input )
-            {
-                return DateTime.parse( input.toString() );
-            }
-        } );
-        registerDeserializer( LocalDateTime.class, new Function<Object, LocalDateTime>()
-        {
-            @Override
-            public LocalDateTime map( Object input )
-            {
-                return new LocalDateTime( input );
-            }
-        } );
-        registerDeserializer( LocalDate.class, new Function<Object, LocalDate>()
-        {
-            @Override
-            public LocalDate map( Object input )
-            {
-                return new LocalDate( input );
-            }
-        } );
-
-        // Other supported types
-        registerDeserializer( EntityReference.class, new Function<Object, EntityReference>()
-        {
-            @Override
-            public EntityReference map( Object input )
-            {
-                return EntityReference.parseEntityReference( input.toString() );
-            }
-        } );
-    }
-
-    private void setValuesModuleFinder( Function<Application, Module> valuesModuleFinder )
-    {
-        this.valuesModuleFinder = valuesModuleFinder;
-        this.valuesModule = null;
-    }
-
-    private Module valuesModule()
-    {
-        if( valuesModule == null )
-        {
-            if( valuesModuleFinder == null )
-            {
-                valuesModule = module;
-            }
-            else
-            {
-                valuesModule = valuesModuleFinder.map( application );
-                if( valuesModule == null )
-                {
-                    throw new ValueSerializationException( "Values Module provided by the finder Function was null." );
-                }
-            }
-        }
-        return valuesModule;
-    }
-
-    @Override
-    public <T> Function<String, T> deserialize( Class<T> type )
-    {
-        if( CollectionType.isCollection( type ) )
-        {
-            ValueType objectValueType = new ValueType( Object.class );
-            return deserialize( new CollectionType( type, objectValueType ) );
-        }
-        if( MapType.isMap( type ) )
-        {
-            ValueType objectValueType = new ValueType( Object.class );
-            return deserialize( new MapType( type, objectValueType, objectValueType ) );
-        }
-        return deserialize( new ValueType( type ) );
-    }
-
-    @Override
-    public final <T> Function<String, T> deserialize( final ValueType valueType )
-    {
-        return new Function<String, T>()
-        {
-            @Override
-            public T map( String input )
-            {
-                return deserialize( valueType, input );
-            }
-        };
-    }
-
-    @Override
-    public final <T> Function2<ValueType, String, T> deserialize()
-    {
-        return new Function2<ValueType, String, T>()
-        {
-            @Override
-            public T map( ValueType valueType, String input )
-            {
-                return deserialize( valueType, input );
-            }
-        };
-    }
-
-    @Override
-    public final <T> T deserialize( Class<?> type, String input )
-        throws ValueSerializationException
-    {
-        if( CollectionType.isCollection( type ) )
-        {
-            ValueType objectValueType = new ValueType( Object.class );
-            return deserialize( new CollectionType( type, objectValueType ), input );
-        }
-        if( MapType.isMap( type ) )
-        {
-            ValueType objectValueType = new ValueType( Object.class );
-            return deserialize( new MapType( type, objectValueType, objectValueType ), input );
-        }
-        return deserialize( new ValueType( type ), input );
-    }
-
-    @Override
-    public final <T> T deserialize( ValueType valueType, String input )
-        throws ValueSerializationException
-    {
-        try
-        {
-            return deserializeRoot( valueType, new ByteArrayInputStream( input.getBytes( UTF_8 ) ) );
-        }
-        catch( ValueSerializationException ex )
-        {
-            throw ex;
-        }
-        catch( Exception ex )
-        {
-            throw new ValueSerializationException( "Could not deserialize value", ex );
-        }
-    }
-
-    @Override
-    public final <T> T deserialize( Class<?> type, InputStream input )
-        throws ValueSerializationException
-    {
-        if( CollectionType.isCollection( type ) )
-        {
-            ValueType objectValueType = new ValueType( Object.class );
-            return deserialize( new CollectionType( type, objectValueType ), input );
-        }
-        if( MapType.isMap( type ) )
-        {
-            ValueType objectValueType = new ValueType( Object.class );
-            return deserialize( new MapType( type, objectValueType, objectValueType ), input );
-        }
-        return deserialize( new ValueType( type ), input );
-    }
-
-    @Override
-    public final <T> T deserialize( ValueType valueType, InputStream input )
-        throws ValueSerializationException
-    {
-        try
-        {
-            return deserializeRoot( valueType, input );
-        }
-        catch( ValueSerializationException ex )
-        {
-            throw ex;
-        }
-        catch( Exception ex )
-        {
-            throw new ValueSerializationException( "Could not deserialize value", ex );
-        }
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private <T> T deserializeRoot( ValueType valueType, InputStream input )
-        throws Exception
-    {
-        final Class<?> type = first( valueType.types() );
-        // Plain ValueType
-        if( deserializers.get( type ) != null )
-        {
-            Scanner scanner = new Scanner( input, UTF_8 ).useDelimiter( "\\A" );
-            if( !scanner.hasNext() )
-            {
-                return String.class.equals( type ) ? (T) "" : null;
-            }
-            String string = scanner.next();
-            return (T) deserializers.get( type ).map( string );
-        }
-        else // Array ValueType
-        if( type.isArray() )
-        {
-            Scanner scanner = new Scanner( input, UTF_8 ).useDelimiter( "\\A" );
-            if( !scanner.hasNext() )
-            {
-                return null;
-            }
-            String string = scanner.next();
-            return (T) deserializeBase64Serialized( string );
-        }
-        else // Complex ValueType
-        {
-            InputType adaptedInput = adaptInput( input );
-            onDeserializationStart( valueType, adaptedInput );
-            T deserialized = doDeserialize( valueType, adaptedInput );
-            onDeserializationEnd( valueType, adaptedInput );
-            return deserialized;
-        }
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private <T> T doDeserialize( ValueType valueType, InputType input )
-        throws Exception
-    {
-        final Class<?> type = first( valueType.types() );
-        // Registered deserializers
-        if( deserializers.get( type ) != null )
-        {
-            Object value = readPlainValue( input );
-            if( value == null )
-            {
-                return null;
-            }
-            return (T) deserializers.get( type ).map( value );
-        }
-        else if( complexDeserializers.get( type ) != null )
-        {
-            return (T) complexDeserializers.get( type ).deserializePull( input );
-        }
-        else // Explicit ValueComposite
-        if( ValueCompositeType.class.isAssignableFrom( valueType.getClass() ) )
-        {
-            return (T) deserializeValueComposite( valueType, input );
-        }
-        else // Explicit Collections
-        if( CollectionType.class.isAssignableFrom( valueType.getClass() ) )
-        {
-            return (T) deserializeCollection( (CollectionType) valueType, input );
-        }
-        else // Explicit Map
-        if( MapType.class.isAssignableFrom( valueType.getClass() ) )
-        {
-            return (T) deserializeMap( (MapType) valueType, input );
-        }
-        else // Enum
-        if( EnumType.class.isAssignableFrom( valueType.getClass() ) || type.isEnum() )
-        {
-            return (T) Enum.valueOf( (Class) type, readPlainValue( input ).toString() );
-        }
-        else // Array
-        if( type.isArray() )
-        {
-            return (T) deserializeBase64Serialized( readPlainValue( input ).toString() );
-        }
-        // Guessed Deserialization
-        return (T) deserializeGuessed( valueType, input );
-    }
-
-    private <T> Function<InputType, T> buildDeserializeInputFunction( final ValueType valueType )
-    {
-        return new Function<InputType, T>()
-        {
-            @Override
-            public T map( InputType input )
-            {
-                try
-                {
-                    return doDeserialize( valueType, input );
-                }
-                catch( ValueSerializationException ex )
-                {
-                    throw ex;
-                }
-                catch( Exception ex )
-                {
-                    throw new ValueSerializationException( ex );
-                }
-            }
-        };
-    }
-
-    private <T> Collection<T> deserializeCollection( CollectionType collectionType, InputType input )
-        throws Exception
-    {
-        Collection<T> collection;
-        Class<?> collectionMainType = first( collectionType.types() );
-        if( Set.class.equals( collectionMainType ) )
-        {
-            collection = new LinkedHashSet<>();
-        }
-        else
-        {
-            collection = new ArrayList<>();
-        }
-        return readArrayInCollection( input,
-                                      this.<T>buildDeserializeInputFunction( collectionType.collectedType() ),
-                                      collection );
-    }
-
-    private <K, V> Map<K, V> deserializeMap( MapType mapType, InputType input )
-        throws Exception
-    {
-        return readMapInMap( input,
-                             this.<K>buildDeserializeInputFunction( mapType.keyType() ),
-                             this.<V>buildDeserializeInputFunction( mapType.valueType() ),
-                             new HashMap<K, V>() );
-    }
-
-    private <T> T deserializeValueComposite( ValueType valueType, InputType input )
-        throws Exception
-    {
-        InputNodeType inputNode = readObjectTree( input );
-        if( inputNode == null )
-        {
-            return null;
-        }
-        return deserializeNodeValueComposite( valueType, inputNode );
-    }
-
-    private <T> T deserializeNodeValueComposite( ValueType valueType, InputNodeType inputNode )
-        throws Exception
-    {
-        ValueCompositeType valueCompositeType = (ValueCompositeType) valueType;
-        Class<?> valueBuilderType = first( valueCompositeType.types() );
-        String typeInfo = this.getObjectFieldValue(
-            inputNode,
-            "_type",
-            this.<String>buildDeserializeInputNodeFunction( new ValueType( String.class ) ) );
-        if( typeInfo != null )
-        {
-            ValueDescriptor valueDescriptor = valuesModule().valueDescriptor( typeInfo );
-            if( valueDescriptor == null )
-            {
-                throw new ValueSerializationException( "Specified value type could not be resolved: " + typeInfo );
-            }
-            valueCompositeType = valueDescriptor.valueType();
-            valueBuilderType = Class.forName( typeInfo );
-        }
-        return deserializeValueComposite( valueCompositeType, valueBuilderType, inputNode );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private <T> T deserializeValueComposite( ValueCompositeType valueCompositeType, Class<?> valueBuilderType, InputNodeType inputNode )
-        throws Exception
-    {
-        final Map<String, Object> stateMap = new HashMap<>();
-
-        // Properties
-        for( PropertyDescriptor property : valueCompositeType.properties() )
-        {
-            String propertyName = property.qualifiedName().name();
-            Object value;
-            if( objectHasField( inputNode, propertyName ) )
-            {
-                value = getObjectFieldValue(
-                    inputNode,
-                    propertyName,
-                    buildDeserializeInputNodeFunction( property.valueType() ) );
-                if( property.isImmutable() )
-                {
-                    if( value instanceof Set )
-                    {
-                        value = Collections.unmodifiableSet( (Set<?>) value );
-                    }
-                    else if( value instanceof List )
-                    {
-                        value = Collections.unmodifiableList( (List<?>) value );
-                    }
-                    else if( value instanceof Map )
-                    {
-                        value = Collections.unmodifiableMap( (Map<?, ?>) value );
-                    }
-                }
-            }
-            else
-            {
-                // Serialized object does not contain the field, try to default it
-                value = property.initialValue( valuesModule() );
-            }
-            stateMap.put( propertyName, value );
-        }
-
-        // Associations
-        for( AssociationDescriptor association : valueCompositeType.associations() )
-        {
-            String associationName = association.qualifiedName().name();
-            if( objectHasField( inputNode, associationName ) )
-            {
-                Object value = getObjectFieldValue(
-                    inputNode,
-                    associationName,
-                    buildDeserializeInputNodeFunction( new ValueType( EntityReference.class ) ) );
-                stateMap.put( associationName, value );
-            }
-        }
-
-        // ManyAssociations
-        for( AssociationDescriptor manyAssociation : valueCompositeType.manyAssociations() )
-        {
-            String manyAssociationName = manyAssociation.qualifiedName().name();
-            if( objectHasField( inputNode, manyAssociationName ) )
-            {
-                Object value = getObjectFieldValue(
-                    inputNode,
-                    manyAssociationName,
-                    buildDeserializeInputNodeFunction( new CollectionType( Collection.class,
-                                                                           new ValueType( EntityReference.class ) ) ) );
-                stateMap.put( manyAssociationName, value );
-            }
-        }
-
-        // NamedAssociations
-        for( AssociationDescriptor namedAssociation : valueCompositeType.namedAssociations() )
-        {
-            String namedAssociationName = namedAssociation.qualifiedName().name();
-            if( objectHasField( inputNode, namedAssociationName ) )
-            {
-                Object value = getObjectFieldValue(
-                    inputNode,
-                    namedAssociationName,
-                    buildDeserializeInputNodeFunction( MapType.of( String.class, EntityReference.class, Serialization.Variant.object ) ) );
-                stateMap.put( namedAssociationName, value );
-            }
-        }
-
-        ValueBuilder<?> valueBuilder = buildNewValueBuilderWithState( valueBuilderType, stateMap );
-        return (T) valueBuilder.newInstance(); // Unchecked cast because the builder could use a type != T
-    }
-
-    private <T> Function<InputNodeType, T> buildDeserializeInputNodeFunction( final ValueType valueType )
-    {
-        return new Function<InputNodeType, T>()
-        {
-            @Override
-            public T map( InputNodeType inputNode )
-            {
-                try
-                {
-                    return doDeserializeInputNodeValue( valueType, inputNode );
-                }
-                catch( ValueSerializationException ex )
-                {
-                    throw ex;
-                }
-                catch( Exception ex )
-                {
-                    throw new ValueSerializationException( ex );
-                }
-            }
-        };
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private <T> T doDeserializeInputNodeValue( ValueType valueType, InputNodeType inputNode )
-        throws Exception
-    {
-        if( inputNode == null )
-        {
-            return null;
-        }
-        final Class<?> type = first( valueType.types() );
-        // Registered deserializers
-        if( deserializers.get( type ) != null )
-        {
-            Object value = asSimpleValue( inputNode );
-            if( value == null )
-            {
-                return null;
-            }
-            return (T) deserializers.get( type ).map( value );
-        }
-        else if( complexDeserializers.get( type ) != null )
-        {
-            return (T) complexDeserializers.get( type ).deserializeTree( inputNode );
-        }
-        else // Explicit ValueComposite
-        if( ValueCompositeType.class.isAssignableFrom( valueType.getClass() ) )
-        {
-            return (T) deserializeNodeValueComposite( valueType, inputNode );
-        }
-        else // Explicit Collections
-        if( CollectionType.class.isAssignableFrom( valueType.getClass() ) )
-        {
-            return (T) deserializeNodeCollection( (CollectionType) valueType, inputNode );
-        }
-        else // Explicit Map
-        if( MapType.class.isAssignableFrom( valueType.getClass() ) )
-        {
-            MapType mapType = (MapType) valueType;
-            if( mapType.variant().equals( Serialization.Variant.entry ) )
-            {
-                return (T) deserializeNodeEntryMap( (MapType) valueType, inputNode );
-            }
-            else
-            {
-                return (T) deserializeNodeObjectMap( (MapType) valueType, inputNode );
-            }
-        }
-        else // Enum
-        if( EnumType.class.isAssignableFrom( valueType.getClass() ) || type.isEnum() )
-        {
-            Object value = asSimpleValue( inputNode );
-            if( value == null )
-            {
-                return null;
-            }
-            return (T) Enum.valueOf( (Class) type, value.toString() );
-        }
-        // Guessed deserialization
-        return (T) deserializeNodeGuessed( valueType, inputNode );
-    }
-
-    private ValueBuilder<?> buildNewValueBuilderWithState( Class<?> type, final Map<String, Object> stateMap )
-    {
-        return valuesModule().newValueBuilderWithState(
-            type,
-            new Function<PropertyDescriptor, Object>()
-        {
-            @Override
-            public Object map( PropertyDescriptor property )
-            {
-                return stateMap.get( property.qualifiedName().name() );
-            }
-            },
-            new Function<AssociationDescriptor, EntityReference>()
-            {
-                @Override
-                public EntityReference map( AssociationDescriptor association )
-                {
-                    Object entityRef = stateMap.get( association.qualifiedName().name() );
-                    if( entityRef == null )
-                    {
-                        return null;
-                    }
-                    return (EntityReference) entityRef;
-                }
-            },
-            new Function<AssociationDescriptor, Iterable<EntityReference>>()
-            {
-                @Override
-                @SuppressWarnings( "unchecked" )
-                public Iterable<EntityReference> map( AssociationDescriptor manyAssociation )
-                {
-                    Object entityRefs = stateMap.get( manyAssociation.qualifiedName().name() );
-                    if( entityRefs == null )
-                    {
-                        return empty();
-                    }
-                    return (Iterable<EntityReference>) entityRefs;
-                }
-            },
-            new Function<AssociationDescriptor, Map<String, EntityReference>>()
-            {
-                @Override
-                @SuppressWarnings( "unchecked" )
-                public Map<String, EntityReference> map( AssociationDescriptor namedAssociation )
-                {
-                    Object entityRefs = stateMap.get( namedAssociation.qualifiedName().name() );
-                    if( entityRefs == null )
-                    {
-                        return Collections.emptyMap();
-                    }
-                    return (Map<String, EntityReference>) entityRefs;
-                }
-            } );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private <T> T deserializeGuessed( ValueType valueType, InputType input )
-        throws Exception
-    {
-        InputNodeType inputNode = readObjectTree( input );
-        if( inputNode == null )
-        {
-            return null;
-        }
-        return deserializeNodeGuessed( valueType, inputNode );
-    }
-
-    private <T> Collection<T> deserializeNodeCollection( CollectionType collectionType, InputNodeType inputNode )
-        throws Exception
-    {
-        Collection<T> collection;
-        Class<?> collectionMainType = first( collectionType.types() );
-        if( Set.class.equals( collectionMainType ) )
-        {
-            collection = new LinkedHashSet<>();
-        }
-        else
-        {
-            collection = new ArrayList<>();
-        }
-        putArrayNodeInCollection( inputNode,
-                                  this.<T>buildDeserializeInputNodeFunction( collectionType.collectedType() ),
-                                  collection );
-        return collection;
-    }
-
-    private <K, V> Map<K, V> deserializeNodeEntryMap( MapType mapType, InputNodeType inputNode )
-        throws Exception
-    {
-        Map<K, V> map = new HashMap<>();
-        putArrayNodeInMap( inputNode,
-                           this.<K>buildDeserializeInputNodeFunction( mapType.keyType() ),
-                           this.<V>buildDeserializeInputNodeFunction( mapType.valueType() ),
-                           map );
-        return map;
-    }
-
-    private <V> Map<String, V> deserializeNodeObjectMap( MapType mapType, InputNodeType inputNode )
-        throws Exception
-    {
-        Map<String, V> map = new HashMap<>();
-        putObjectNodeInMap( inputNode,
-                            this.<V>buildDeserializeInputNodeFunction( mapType.valueType() ),
-                            map );
-        return map;
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private <T> T deserializeNodeGuessed( ValueType valueType, InputNodeType inputNode )
-        throws Exception
-    {
-        if( isObjectValue( inputNode ) )
-        {
-            // Attempt ValueComposite deserialization
-            ValueCompositeType valueCompositeType;
-            if( objectHasField( inputNode, "_type" ) ) // with _type info
-            {
-                String typeInfo = this.getObjectFieldValue(
-                    inputNode,
-                    "_type",
-                    this.<String>buildDeserializeInputNodeFunction( new ValueType( String.class ) ) );
-                ValueDescriptor valueDescriptor = valuesModule().valueDescriptor( typeInfo );
-                if( valueDescriptor == null )
-                {
-                    throw new ValueSerializationException( "Specified value type could not be resolved: " + typeInfo );
-                }
-                valueCompositeType = valueDescriptor.valueType();
-            }
-            else // without _type info
-            {
-                ValueDescriptor valueDescriptor = valuesModule().valueDescriptor( first( valueType.types() ).getName() );
-                if( valueDescriptor == null )
-                {
-                    throw new ValueSerializationException( "Don't know how to deserialize " + inputNode );
-                }
-                valueCompositeType = valueDescriptor.valueType();
-            }
-            Class<?> valueBuilderType = first( valueCompositeType.types() );
-            return deserializeValueComposite( valueCompositeType, valueBuilderType, inputNode );
-        }
-        // Last resort : base64 java deserialization
-        return (T) deserializeBase64Serialized( inputNode );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private <T> T deserializeBase64Serialized( InputNodeType inputNode )
-        throws Exception
-    {
-        Object value = asSimpleValue( inputNode );
-        if( value == null )
-        {
-            return null;
-        }
-        String base64 = value.toString();
-        return deserializeBase64Serialized( base64 );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private <T> T deserializeBase64Serialized( String inputString )
-        throws Exception
-    {
-        byte[] bytes = inputString.getBytes( UTF_8 );
-        bytes = Base64Encoder.decode( bytes );
-        Object result;
-        try( ObjectInputStream oin = new ObjectInputStream( new ByteArrayInputStream( bytes ) ) )
-        {
-            result = oin.readObject();
-        }
-        return (T) result;
-    }
-
-    //
-    // Deserialization Extension Points
-    //
-    /**
-     * Called by the adapter on deserialization start, after {@link #adaptInput(java.io.InputStream)}.
-     *
-     * @param valueType ValueType
-     * @param input Input
-     * @throws Exception that will be wrapped in a {@link ValueSerializationException}
-     */
-    @SuppressWarnings( "UnusedParameters" )
-    protected void onDeserializationStart( ValueType valueType, InputType input )
-        throws Exception
-    {
-        // NOOP
-    }
-
-    /**
-     * Called by the adapter on deserialization end.
-     *
-     * @param valueType ValueType
-     * @param input Input
-     * @throws Exception that will be wrapped in a {@link ValueSerializationException}
-     */
-    protected void onDeserializationEnd( ValueType valueType, InputType input )
-        throws Exception
-    {
-        // NOOP
-    }
-
-    //
-    // Pull Parsing Deserialization
-    //
-    /**
-     * This method is always called first, this is a chance to wrap the input type.
-     *
-     * @param input InputStream to adapt
-     * @return Adapted input
-     * @throws Exception that will be wrapped in a {@link ValueSerializationException}
-     */
-    protected abstract InputType adaptInput( InputStream input )
-        throws Exception;
-
-    /**
-     * @param input Input
-     * @return a Plain Value read from the input
-     * @throws Exception that will be wrapped in a {@link ValueSerializationException}
-     */
-    protected abstract Object readPlainValue( InputType input )
-        throws Exception;
-
-    /**
-     * @param <T> Parameterized collection type
-     * @param input Input
-     * @param deserializer Deserialization function
-     * @param collection Collection
-     * @return The filled collection or null if no array
-     * @throws Exception that will be wrapped in a {@link ValueSerializationException}
-     */
-    protected abstract <T> Collection<T> readArrayInCollection( InputType input,
-                                                                Function<InputType, T> deserializer,
-                                                                Collection<T> collection )
-        throws Exception;
-
-    /**
-     * A Map&lt;K,V&gt; is serialized in an array of entries objects.
-     *
-     * <p>Here is an example in JSON:</p>
-     * <pre>
-     * [
-     *     { "key": "foo",       "value": "bar"   },
-     *     { "key": "cathedral", "value": "bazar" }
-     * ]
-     * </pre>
-     * <p>And an empty Map:</p>
-     * <pre>[]</pre>
-     * <p>
-     *     This allow to use any type as keys and values while keeping the Map order at the cost of having
-     *     non-predictible order of key/value inside an entry object.
-     * </p>
-     *
-     * @param <K> Parameterized map key type
-     * @param <V> Parameterized map value type
-     * @param input Input
-     * @param keyDeserializer Map key deserialization function
-     * @param valueDeserializer Map value deserialization function
-     * @param map Map
-     * @return The filled map or null if no array
-     * @throws Exception that will be wrapped in a {@link ValueSerializationException}
-     */
-    protected abstract <K, V> Map<K, V> readMapInMap( InputType input,
-                                                      Function<InputType, K> keyDeserializer,
-                                                      Function<InputType, V> valueDeserializer,
-                                                      Map<K, V> map )
-        throws Exception;
-
-    /**
-     * @param input Input
-     * @return an InputNodeType or null if the value was null
-     * @throws Exception that will be wrapped in a {@link ValueSerializationException}
-     */
-    protected abstract InputNodeType readObjectTree( InputType input )
-        throws Exception;
-
-    //
-    // Tree Parsing Deserialization
-    //
-    protected abstract Object asSimpleValue( InputNodeType inputNode )
-        throws Exception;
-
-    protected abstract boolean isObjectValue( InputNodeType inputNode )
-        throws Exception;
-
-    protected abstract boolean objectHasField( InputNodeType inputNode, String key )
-        throws Exception;
-
-    /**
-     * Return null if the field do not exists.
-     * @param <T> Parameterized object field value type
-     * @param inputNode Input Node
-     * @param key Object key
-     * @param valueDeserializer Deserialization function
-     * @return The value of the field.
-     * @throws Exception that will be wrapped in a {@link ValueSerializationException}
-     */
-    protected abstract <T> T getObjectFieldValue( InputNodeType inputNode,
-                                                  String key,
-                                                  Function<InputNodeType, T> valueDeserializer )
-        throws Exception;
-
-    protected abstract <T> void putArrayNodeInCollection( InputNodeType inputNode,
-                                                          Function<InputNodeType, T> deserializer,
-                                                          Collection<T> collection )
-        throws Exception;
-
-    protected abstract <K, V> void putArrayNodeInMap( InputNodeType inputNode,
-                                                      Function<InputNodeType, K> keyDeserializer,
-                                                      Function<InputNodeType, V> valueDeserializer,
-                                                      Map<K, V> map
-    )
-        throws Exception;
-
-    protected abstract <V> void putObjectNodeInMap( InputNodeType inputNode,
-                                                    Function<InputNodeType, V> valueDeserializer,
-                                                    Map<String, V> map
-    )
-        throws Exception;
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/value/ValueSerializerAdapter.java b/core/spi/src/main/java/org/qi4j/spi/value/ValueSerializerAdapter.java
deleted file mode 100644
index 6f17569..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/value/ValueSerializerAdapter.java
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2010, Niclas Hednman. All Rights Reserved.
- * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.value;
-
-import java.io.ByteArrayOutputStream;
-import java.io.ObjectOutputStream;
-import java.io.OutputStream;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import org.joda.time.DateTime;
-import org.joda.time.LocalDate;
-import org.joda.time.LocalDateTime;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.util.Base64Encoder;
-import org.qi4j.api.util.Dates;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.api.value.ValueSerializationException;
-import org.qi4j.api.value.ValueSerializer;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Function2;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Adapter for pull-parsing capable ValueSerializers.
- *
- * <p>
- * Among Plain values (see {@link ValueSerializer}) some are considered primitives to underlying serialization
- * mechanisms and by so handed/come without conversion to/from implementations. Primitive values can be one of:
- * </p>
- * <ul>
- * <li>String,</li>
- * <li>Character or char,</li>
- * <li>Boolean or boolean,</li>
- * <li>Integer or int,</li>
- * <li>Long or long,</li>
- * <li>Short or short,</li>
- * <li>Byte or byte,</li>
- * <li>Float or float,</li>
- * <li>Double or double.</li>
- * </ul>
- * <p>
- * Some other Plain values are transformed before being handed to implementations:
- * </p>
- * <ul>
- * <li>BigInteger and BigDecimal depends on ValueSerializer.{@link org.qi4j.api.value.ValueSerializer.Options};</li>
- * <li>Date as a ISO-8601 UTC String;</li>
- * <li>DateTime (JodaTime) as a ISO-8601 String with timezone offset or Z for UTC;</li>
- * <li>LocalDateTime (JodaTime) as a ISO-8601 String with no timezone offset;</li>
- * <li>LocalDate (JodaTime) as a ISO-8601 String with no time info;</li>
- * </ul>
- *
- * @param <OutputType> Implementor output type
- */
-public abstract class ValueSerializerAdapter<OutputType>
-    implements ValueSerializer
-{
-
-    public static interface ComplexSerializer<T, OutputType>
-    {
-        void serialize( Options options, T object, OutputType output )
-            throws Exception;
-    }
-
-    private static final String UTF_8 = "UTF-8";
-
-    private static <TO, FROM extends TO> Function2<Options, FROM, TO> identitySerializer()
-    {
-        return new Function2<Options, FROM, TO>()
-        {
-            @Override
-            public TO map( Options options, FROM from )
-            {
-                return from;
-            }
-        };
-    }
-
-    private final Map<Class<?>, Function2<Options, Object, Object>> serializers = new HashMap<>( 16 );
-    private final Map<Class<?>, ComplexSerializer<Object, OutputType>> complexSerializers = new HashMap<>( 2 );
-
-    /**
-     * Register a Plain Value type serialization Function.
-     *
-     * @param <T>        Plain Value parametrized Type
-     * @param type       Plain Value Type
-     * @param serializer Serialization Function
-     */
-    @SuppressWarnings( "unchecked" )
-    protected final <T> void registerSerializer( Class<T> type, Function2<Options, T, Object> serializer )
-    {
-        serializers.put( type, (Function2<Options, Object, Object>) serializer );
-    }
-
-    /**
-     * Register a Complex Value type serialization Function.
-     *
-     * @param <T>        Complex Value parametrized Type
-     * @param type       Complex Value Type
-     * @param serializer Serialization Function
-     */
-    @SuppressWarnings( "unchecked" )
-    protected final <T> void registerComplexSerializer( Class<T> type, ComplexSerializer<T, OutputType> serializer )
-    {
-        complexSerializers.put( type, (ComplexSerializer<Object, OutputType>) serializer );
-    }
-
-    public ValueSerializerAdapter()
-    {
-        // Primitive Value types
-        registerSerializer( String.class, ValueSerializerAdapter.<Object, String>identitySerializer() );
-        registerSerializer( Character.class, ValueSerializerAdapter.<Object, Character>identitySerializer() );
-        registerSerializer( Boolean.class, ValueSerializerAdapter.<Object, Boolean>identitySerializer() );
-        registerSerializer( Integer.class, ValueSerializerAdapter.<Object, Integer>identitySerializer() );
-        registerSerializer( Long.class, ValueSerializerAdapter.<Object, Long>identitySerializer() );
-        registerSerializer( Short.class, ValueSerializerAdapter.<Object, Short>identitySerializer() );
-        registerSerializer( Byte.class, ValueSerializerAdapter.<Object, Byte>identitySerializer() );
-        registerSerializer( Float.class, ValueSerializerAdapter.<Object, Float>identitySerializer() );
-        registerSerializer( Double.class, ValueSerializerAdapter.<Object, Double>identitySerializer() );
-
-        // Number types
-        registerSerializer( BigDecimal.class, new Function2<Options, BigDecimal, Object>()
-        {
-            @Override
-            public Object map( Options options, BigDecimal bigDecimal )
-            {
-                return bigDecimal.toString();
-            }
-        } );
-        registerSerializer( BigInteger.class, new Function2<Options, BigInteger, Object>()
-        {
-            @Override
-            public Object map( Options options, BigInteger bigInteger )
-            {
-                return bigInteger.toString();
-            }
-        } );
-
-        // Date types
-        registerSerializer( Date.class, new Function2<Options, Date, Object>()
-        {
-            @Override
-            public Object map( Options options, Date date )
-            {
-                return Dates.toUtcString( date );
-            }
-        } );
-        registerSerializer( DateTime.class, new Function2<Options, DateTime, Object>()
-        {
-            @Override
-            public Object map( Options options, DateTime date )
-            {
-                return date.toString();
-            }
-        } );
-        registerSerializer( LocalDateTime.class, new Function2<Options, LocalDateTime, Object>()
-        {
-            @Override
-            public Object map( Options options, LocalDateTime date )
-            {
-                return date.toString();
-            }
-        } );
-        registerSerializer( LocalDate.class, new Function2<Options, LocalDate, Object>()
-        {
-            @Override
-            public Object map( Options options, LocalDate date )
-            {
-                return date.toString();
-            }
-        } );
-
-        // Other supported types
-        registerSerializer( EntityReference.class, new Function2<Options, EntityReference, Object>()
-        {
-            @Override
-            public Object map( Options options, EntityReference ref )
-            {
-                return ref.toString();
-            }
-        } );
-    }
-
-    @Override
-    public final <T> Function<T, String> serialize()
-    {
-        return new Function<T, String>()
-        {
-            @Override
-            public String map( T object )
-            {
-                return serialize( object );
-            }
-        };
-    }
-
-    @Override
-    public final <T> Function<T, String> serialize( final Options options )
-    {
-        return new Function<T, String>()
-        {
-            @Override
-            public String map( T object )
-            {
-                return serialize( options, object );
-            }
-        };
-    }
-
-    @Override
-    @Deprecated
-    public final <T> Function<T, String> serialize( final boolean includeTypeInfo )
-    {
-        return new Function<T, String>()
-        {
-            @Override
-            public String map( T object )
-            {
-                return serialize( includeTypeInfo ? new Options().withTypeInfo() : new Options().withoutTypeInfo(),
-                                  object );
-            }
-        };
-    }
-
-    @Override
-    public final String serialize( Object object )
-        throws ValueSerializationException
-    {
-        return serialize( new Options(), object );
-    }
-
-    @Override
-    public final String serialize( Options options, Object object )
-        throws ValueSerializationException
-    {
-        try
-        {
-            ByteArrayOutputStream output = new ByteArrayOutputStream();
-            serializeRoot( options, object, output );
-            return output.toString( UTF_8 );
-        }
-        catch( ValueSerializationException ex )
-        {
-            throw ex;
-        }
-        catch( Exception ex )
-        {
-            throw new ValueSerializationException( "Could not serialize value", ex );
-        }
-    }
-
-    @Override
-    @Deprecated
-    public final String serialize( Object object, boolean includeTypeInfo )
-        throws ValueSerializationException
-    {
-        return serialize( includeTypeInfo ? new Options().withTypeInfo() : new Options().withoutTypeInfo(),
-                          object );
-    }
-
-    @Override
-    public final void serialize( Object object, OutputStream output )
-        throws ValueSerializationException
-    {
-        serialize( new Options(), object, output );
-    }
-
-    @Override
-    public final void serialize( Options options, Object object, OutputStream output )
-        throws ValueSerializationException
-    {
-        try
-        {
-            serializeRoot( options, object, output );
-        }
-        catch( ValueSerializationException ex )
-        {
-            throw ex;
-        }
-        catch( Exception ex )
-        {
-            throw new ValueSerializationException( "Could not serialize value", ex );
-        }
-    }
-
-    @Override
-    @Deprecated
-    public final void serialize( Object object, OutputStream output, boolean includeTypeInfo )
-        throws ValueSerializationException
-    {
-        serialize( includeTypeInfo ? new Options().withTypeInfo() : new Options().withoutTypeInfo(),
-                   object, output );
-    }
-
-    private void serializeRoot( Options options, Object object, OutputStream output )
-        throws Exception
-    {
-        if( object != null )
-        {
-            if( serializers.get( object.getClass() ) != null )
-            {
-                // Plain Value
-                Object serialized = serializers.get( object.getClass() ).map( options, object );
-                output.write( serialized.toString().getBytes( UTF_8 ) );
-            }
-            else if( object.getClass().isEnum() )
-            {
-                // Enum Value
-                output.write( object.toString().getBytes( UTF_8 ) );
-            }
-            else if( object.getClass().isArray() )
-            {
-                // Array Value
-                output.write( serializeBase64Serializable( object ).getBytes( UTF_8 ) );
-            }
-            else
-            {
-                // Complex Value
-                OutputType adaptedOutput = adaptOutput( output );
-                onSerializationStart( object, adaptedOutput );
-                doSerialize( options, object, adaptedOutput, true );
-                onSerializationEnd( object, adaptedOutput );
-            }
-        }
-    }
-
-    private void doSerialize( Options options, Object object, OutputType output, boolean rootPass )
-        throws Exception
-    {
-        // Null
-        if( object == null )
-        {
-            onValue( output, null );
-        }
-        else // Registered serializer
-            if( serializers.get( object.getClass() ) != null )
-            {
-                onValue( output, serializers.get( object.getClass() ).map( options, object ) );
-            }
-            else if( complexSerializers.get( object.getClass() ) != null )
-            {
-                complexSerializers.get( object.getClass() ).serialize( options, object, output );
-            }
-            else // ValueComposite
-                if( ValueComposite.class.isAssignableFrom( object.getClass() ) )
-                {
-                    serializeValueComposite( options, object, output, rootPass );
-                }
-                else // EntityComposite
-                    if( EntityComposite.class.isAssignableFrom( object.getClass() ) )
-                    {
-                        serializeEntityComposite( object, output );
-                    }
-                    else // Collection - Iterable
-                        if( Iterable.class.isAssignableFrom( object.getClass() ) )
-                        {
-                            serializeIterable( options, object, output );
-                        }
-                        else // Array - QUID Remove this and use java serialization for arrays?
-                            if( object.getClass().isArray() )
-                            {
-                                serializeBase64Serializable( object, output );
-                            }
-                            else // Map
-                                if( Map.class.isAssignableFrom( object.getClass() ) )
-                                {
-                                    serializeMap( options, object, output );
-                                }
-                                else // Enum
-                                    if( object.getClass().isEnum() )
-                                    {
-                                        onValue( output, object.toString() );
-                                    }
-                                    else // Fallback to Base64 encoded Java Serialization
-                                    {
-                                        serializeBase64Serializable( object, output );
-                                    }
-    }
-
-    private void serializeValueComposite( Options options, Object object, OutputType output, boolean rootPass )
-        throws Exception
-    {
-        CompositeInstance valueInstance = Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF.map( (ValueComposite) object );
-        ValueDescriptor descriptor = (ValueDescriptor) valueInstance.descriptor();
-        AssociationStateHolder state = (AssociationStateHolder) valueInstance.state();
-
-        onObjectStart( output );
-
-        //noinspection ConstantConditions
-        if( options.getBoolean( Options.INCLUDE_TYPE_INFO ) && !rootPass )
-        {
-            onFieldStart( output, "_type" );
-            onValueStart( output );
-            onValue( output, first( descriptor.valueType().types() ).getName() );
-            onValueEnd( output );
-            onFieldEnd( output );
-        }
-
-        for( PropertyDescriptor persistentProperty : descriptor.valueType().properties() )
-        {
-            Property<?> property = state.propertyFor( persistentProperty.accessor() );
-            onFieldStart( output, persistentProperty.qualifiedName().name() );
-            onValueStart( output );
-            doSerialize( options, property.get(), output, false );
-            onValueEnd( output );
-            onFieldEnd( output );
-        }
-        for( AssociationDescriptor associationDescriptor : descriptor.valueType().associations() )
-        {
-            Association<?> association = state.associationFor( associationDescriptor.accessor() );
-            onFieldStart( output, associationDescriptor.qualifiedName().name() );
-            onValueStart( output );
-            EntityReference ref = association.reference();
-            if( ref == null )
-            {
-                onValue( output, null );
-            }
-            else
-            {
-                onValue( output, ref.identity() );
-            }
-            onValueEnd( output );
-            onFieldEnd( output );
-        }
-        for( AssociationDescriptor associationDescriptor : descriptor.valueType().manyAssociations() )
-        {
-            ManyAssociation<?> manyAssociation = state.manyAssociationFor( associationDescriptor.accessor() );
-            onFieldStart( output, associationDescriptor.qualifiedName().name() );
-            onValueStart( output );
-            onArrayStart( output );
-            for( EntityReference ref : manyAssociation.references() )
-            {
-                onValueStart( output );
-                onValue( output, ref.identity() );
-                onValueEnd( output );
-            }
-            onArrayEnd( output );
-            onValueEnd( output );
-            onFieldEnd( output );
-        }
-        for( AssociationDescriptor associationDescriptor : descriptor.valueType().namedAssociations() )
-        {
-            NamedAssociation<?> namedAssociation = state.namedAssociationFor( associationDescriptor.accessor() );
-            onFieldStart( output, associationDescriptor.qualifiedName().name() );
-            onValueStart( output );
-            onObjectStart( output );
-            for( String name : namedAssociation )
-            {
-                onFieldStart( output, name );
-                onValueStart( output );
-                EntityReference ref = namedAssociation.referenceOf( name );
-                onValue( output, ref.identity() );
-                onValueEnd( output );
-                onFieldEnd( output );
-            }
-            onObjectEnd( output );
-            onValueEnd( output );
-            onFieldEnd( output );
-        }
-
-        onObjectEnd( output );
-    }
-
-    private void serializeEntityComposite( Object object, OutputType output )
-        throws Exception
-    {
-        onValue( output, EntityReference.entityReferenceFor( object ) );
-    }
-
-    private void serializeIterable( Options options, Object object, OutputType output )
-        throws Exception
-    {
-        @SuppressWarnings( "unchecked" )
-        Iterable<Object> collection = (Iterable<Object>) object;
-        onArrayStart( output );
-        for( Object item : collection )
-        {
-            onValueStart( output );
-            doSerialize( options, item, output, false );
-            onValueEnd( output );
-        }
-        onArrayEnd( output );
-    }
-
-    private void serializeMap( Options options, Object object, OutputType output )
-        throws Exception
-    {
-        @SuppressWarnings( "unchecked" )
-        Map<Object, Object> map = (Map<Object, Object>) object;
-        if( options.getBoolean( Options.MAP_ENTRIES_AS_OBJECTS ) )
-        {
-            onObjectStart( output );
-            for( Map.Entry<Object, Object> entry : map.entrySet() )
-            {
-                onFieldStart( output, entry.getKey().toString() );
-                onValueStart( output );
-                doSerialize( options, entry.getValue(), output, false );
-                onValueEnd( output );
-                onFieldEnd( output );
-            }
-            onObjectEnd( output );
-        }
-        else
-        {
-            onArrayStart( output );
-            for( Map.Entry<Object, Object> entry : map.entrySet() )
-            {
-                onObjectStart( output );
-
-                onFieldStart( output, "key" );
-                onValueStart( output );
-                onValue( output, entry.getKey().toString() );
-                onValueEnd( output );
-                onFieldEnd( output );
-
-                onFieldStart( output, "value" );
-                onValueStart( output );
-                doSerialize( options, entry.getValue(), output, false );
-                onValueEnd( output );
-                onFieldEnd( output );
-
-                onObjectEnd( output );
-            }
-            onArrayEnd( output );
-        }
-    }
-
-    private void serializeBase64Serializable( Object object, OutputType output )
-        throws Exception
-    {
-        onValue( output, serializeBase64Serializable( object ) );
-    }
-
-    private String serializeBase64Serializable( Object object )
-        throws Exception
-    {
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        try (ObjectOutputStream out = new ObjectOutputStream( bout ))
-        {
-            out.writeUnshared( object );
-        }
-        byte[] bytes = Base64Encoder.encode( bout.toByteArray(), true );
-        return new String( bytes, UTF_8 );
-    }
-
-    protected abstract OutputType adaptOutput( OutputStream output )
-        throws Exception;
-
-    protected void onSerializationStart( Object object, OutputType output )
-        throws Exception
-    {
-        // NOOP
-    }
-
-    protected void onSerializationEnd( Object object, OutputType output )
-        throws Exception
-    {
-        // NOOP
-    }
-
-    protected abstract void onArrayStart( OutputType output )
-        throws Exception;
-
-    protected abstract void onArrayEnd( OutputType output )
-        throws Exception;
-
-    protected abstract void onObjectStart( OutputType output )
-        throws Exception;
-
-    protected abstract void onObjectEnd( OutputType output )
-        throws Exception;
-
-    protected abstract void onFieldStart( OutputType output, String fieldName )
-        throws Exception;
-
-    protected void onFieldEnd( OutputType output )
-        throws Exception
-    {
-        // NOOP
-    }
-
-    protected void onValueStart( OutputType output )
-        throws Exception
-    {
-        // NOOP
-    }
-
-    protected abstract void onValue( OutputType output, Object value )
-        throws Exception;
-
-    protected void onValueEnd( OutputType output )
-        throws Exception
-    {
-        // NOOP
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/spi/value/package.html b/core/spi/src/main/java/org/qi4j/spi/value/package.html
deleted file mode 100644
index 727bc2c..0000000
--- a/core/spi/src/main/java/org/qi4j/spi/value/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Value SPI.</h2>
-    </body>
-</html>
diff --git a/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueDeserializer.java b/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueDeserializer.java
deleted file mode 100644
index 223bc99..0000000
--- a/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueDeserializer.java
+++ /dev/null
@@ -1,481 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2010, Niclas Hehdman. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.orgjson;
-
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
-import org.json.JSONArray;
-import org.json.JSONObject;
-import org.json.JSONTokener;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueDeserializer;
-import org.qi4j.api.value.ValueSerializationException;
-import org.qi4j.functional.Function;
-import org.qi4j.spi.value.ValueDeserializerAdapter;
-
-/**
- * ValueDeserializer reading Values from JSON documents using org.json.
- */
-public class OrgJsonValueDeserializer
-    extends ValueDeserializerAdapter<JSONTokener, Object>
-{
-
-    public OrgJsonValueDeserializer(
-        @Structure Application application,
-        @Structure Module module,
-        @Service ServiceReference<ValueDeserializer> serviceRef )
-    {
-        super( application, module, serviceRef );
-    }
-
-    /* package */ OrgJsonValueDeserializer(
-        Application application,
-        Module module,
-        Function<Application, Module> valuesModuleFinder )
-    {
-        super( application, module, valuesModuleFinder );
-    }
-
-    @Override
-    protected JSONTokener adaptInput( InputStream input )
-        throws Exception
-    {
-        return new JSONTokener( new InputStreamReader( input, "UTF-8" ) );
-    }
-
-    @Override
-    protected Object readPlainValue( JSONTokener input )
-        throws Exception
-    {
-        Object nextValue = input.nextValue();
-        if( JSONObject.NULL.equals( nextValue ) )
-        {
-            return null;
-        }
-        else // Object or Array
-        if( JSONObject.class.isAssignableFrom( nextValue.getClass() )
-            || JSONArray.class.isAssignableFrom( nextValue.getClass() ) )
-        {
-            throw new ValueSerializationException( "Asked for a Value but found an Object or an Array." );
-        }
-        return nextValue;
-    }
-
-    @Override
-    protected <T> Collection<T> readArrayInCollection( JSONTokener input,
-                                                       Function<JSONTokener, T> deserializer,
-                                                       Collection<T> collection )
-        throws Exception
-    {
-        char c = input.nextClean();
-        char q;
-        if( c == 'n' ) // null?
-        {
-            /*
-             * Handle unquoted text. This could be the values true, false, or
-             * null, or it can be a number. An implementation (such as this one)
-             * is allowed to also accept non-standard forms.
-             *
-             * Accumulate characters until we reach the end of the text or a
-             * formatting character.
-             */
-            StringBuilder sb = new StringBuilder();
-            sb.setLength( 0 );
-            while( c >= ' ' && ",:]}/\\\"[{;=#".indexOf( c ) < 0 )
-            {
-                sb.append( c );
-                c = input.next();
-            }
-            input.back();
-            String s = sb.toString().trim();
-            if( !"null".equals( s ) )
-            {
-                input.syntaxError( "Unknown value: '" + s + "'" );
-            }
-            return null;
-        }
-        else if( c == '[' )
-        {
-            q = ']';
-        }
-        else
-        {
-            throw input.syntaxError( "A JSONArray text must start with '['" );
-        }
-        if( input.nextClean() == ']' )
-        {
-            return collection;
-        }
-        input.back();
-        for( ;; )
-        {
-            if( input.nextClean() == ',' )
-            {
-                input.back();
-                collection.add( null );
-            }
-            else
-            {
-                input.back();
-                collection.add( deserializer.map( input ) );
-            }
-            c = input.nextClean();
-            switch( c )
-            {
-                case ';':
-                case ',':
-                    if( input.nextClean() == ']' )
-                    {
-                        return collection;
-                    }
-                    input.back();
-                    break;
-                case ']':
-                case ')':
-                    if( q != c )
-                    {
-                        throw input.syntaxError( "Expected a '" + Character.valueOf( q ) + "'" );
-                    }
-                    return collection;
-                default:
-                    throw input.syntaxError( "Expected a ',' or ']'" );
-            }
-        }
-    }
-
-    @Override
-    protected <K, V> Map<K, V> readMapInMap( JSONTokener input,
-                                             Function<JSONTokener, K> keyDeserializer,
-                                             Function<JSONTokener, V> valueDeserializer,
-                                             Map<K, V> map )
-        throws Exception
-    {
-        char c = input.nextClean();
-        char q;
-        if( c == 'n' ) // null?
-        {
-            /*
-             * Handle unquoted text. This could be the values true, false, or
-             * null, or it can be a number. An implementation (such as this one)
-             * is allowed to also accept non-standard forms.
-             *
-             * Accumulate characters until we reach the end of the text or a
-             * formatting character.
-             */
-            StringBuilder sb = new StringBuilder();
-            sb.setLength( 0 );
-            while( c >= ' ' && ",:]}/\\\"[{;=#".indexOf( c ) < 0 )
-            {
-                sb.append( c );
-                c = input.next();
-            }
-            input.back();
-            String s = sb.toString().trim();
-            if( !"null".equals( s ) )
-            {
-                input.syntaxError( "Unknown value: '" + s + "'" );
-            }
-            return null;
-        }
-        else if( c == '[' )
-        {
-            q = ']';
-        }
-        else
-        {
-            throw input.syntaxError( "A JSONArray text must start with '['" );
-        }
-        if( input.nextClean() == ']' )
-        {
-            return map;
-        }
-        input.back();
-
-        for( ;; )
-        {
-            if( input.nextClean() == ',' )
-            {
-                input.back();
-            }
-            else
-            {
-                input.back();
-                // Map entry!
-                if( input.nextClean() != '{' )
-                {
-                    throw input.syntaxError( "A JSONObject text must begin with '{'" );
-                }
-
-                String objectKey;
-                K key = null;
-                V value = null;
-
-                boolean breakIteration = false;
-                while( !breakIteration )
-                {
-                    c = input.nextClean();
-                    switch( c )
-                    {
-                        case 0:
-                            throw input.syntaxError( "A JSONObject text must end with '}'" );
-                        case '}':
-                            breakIteration = true;
-                            continue;
-                        default:
-                            input.back();
-                            objectKey = input.nextValue().toString();
-                    }
-
-                    /*
-                     * The key is followed by ':'. We will also tolerate '=' or '=>'.
-                     */
-                    c = input.nextClean();
-                    if( c == '=' )
-                    {
-                        if( input.next() != '>' )
-                        {
-                            input.back();
-                        }
-                    }
-                    else if( c != ':' )
-                    {
-                        throw input.syntaxError( "Expected a ':' after a key" );
-                    }
-
-                    if( "key".equals( objectKey ) )
-                    {
-                        key = keyDeserializer.map( input );
-                    }
-                    else if( "value".equals( objectKey ) )
-                    {
-                        value = valueDeserializer.map( input );
-                    }
-                    else
-                    {
-                        input.nextValue();
-                    }
-
-                    /*
-                     * Pairs are separated by ','. We will also tolerate ';'.
-                     */
-                    switch( input.nextClean() )
-                    {
-                        case ';':
-                        case ',':
-                            if( input.nextClean() == '}' )
-                            {
-                                breakIteration = true;
-                                continue;
-                            }
-                            input.back();
-                            continue;
-                        case '}':
-                            breakIteration = true;
-                            continue;
-                        default:
-                            throw input.syntaxError( "Expected a ',' or '}'" );
-                    }
-                }
-                if( key != null )
-                {
-                    map.put( key, value );
-                }
-            }
-            c = input.nextClean();
-            switch( c )
-            {
-                case ';':
-                case ',':
-                    if( input.nextClean() == ']' )
-                    {
-                        return map;
-                    }
-                    input.back();
-                    break;
-                case ']':
-                case ')':
-                    if( q != c )
-                    {
-                        throw input.syntaxError( "Expected a '" + Character.valueOf( q ) + "'" );
-                    }
-                    return map;
-                default:
-                    throw input.syntaxError( "Expected a ',' or ']'" );
-            }
-        }
-    }
-
-    //
-    // Deserialization - Tree parsing
-    //
-    @Override
-    protected JSONObject readObjectTree( JSONTokener input )
-        throws Exception
-    {
-        Object objectTree = input.nextValue();
-        if( JSONObject.NULL.equals( objectTree ) )
-        {
-            return null;
-        }
-        return (JSONObject) objectTree;
-    }
-
-    @Override
-    protected Object asSimpleValue( Object inputNode )
-        throws Exception
-    {
-        if( JSONObject.NULL.equals( inputNode ) )
-        {
-            return null;
-        }
-        if( inputNode instanceof JSONObject || inputNode instanceof JSONArray )
-        {
-            throw new ValueSerializationException( "Expected a simple value but got " + inputNode );
-        }
-        return inputNode;
-    }
-
-    @Override
-    protected boolean isObjectValue( Object inputNode )
-        throws Exception
-    {
-        if( JSONObject.NULL.equals( inputNode ) )
-        {
-            return false;
-        }
-        return inputNode instanceof JSONObject;
-    }
-
-    @Override
-    protected boolean objectHasField( Object inputNode, String key )
-        throws Exception
-    {
-        if( JSONObject.NULL.equals( inputNode ) )
-        {
-            return false;
-        }
-        if( !( inputNode instanceof JSONObject ) )
-        {
-            throw new ValueSerializationException( "Expected an object but got " + inputNode );
-        }
-        JSONObject json = (JSONObject) inputNode;
-        return json.has( key );
-    }
-
-    @Override
-    protected <T> T getObjectFieldValue( Object inputNode, String key, Function<Object, T> valueDeserializer )
-        throws Exception
-    {
-        JSONObject json = (JSONObject) inputNode;
-        Object valueNode = json.opt( key );
-        if( JSONObject.NULL.equals( valueNode ) )
-        {
-            return null;
-        }
-        T value = valueDeserializer.map( valueNode );
-        return value;
-    }
-
-    @Override
-    protected <T> void putArrayNodeInCollection( Object inputNode, Function<Object, T> deserializer, Collection<T> collection )
-        throws Exception
-    {
-        if( JSONObject.NULL.equals( inputNode ) )
-        {
-            return;
-        }
-        if( !( inputNode instanceof JSONArray ) )
-        {
-            throw new ValueSerializationException( "Expected an array but got " + inputNode );
-        }
-        JSONArray array = (JSONArray) inputNode;
-        for( int idx = 0; idx < array.length(); idx++ )
-        {
-            Object item = array.get( idx );
-            T value = deserializer.map( item );
-            collection.add( value );
-        }
-    }
-
-    @Override
-    protected <K, V> void putArrayNodeInMap( Object inputNode, Function<Object, K> keyDeserializer, Function<Object, V> valueDeserializer, Map<K, V> map )
-        throws Exception
-    {
-        if( JSONObject.NULL.equals( inputNode ) )
-        {
-            return;
-        }
-        if( !( inputNode instanceof JSONArray ) )
-        {
-            throw new ValueSerializationException( "Expected an array but got " + inputNode );
-        }
-        JSONArray array = (JSONArray) inputNode;
-        for( int idx = 0; idx < array.length(); idx++ )
-        {
-            Object item = array.get( idx );
-            if( !( item instanceof JSONObject ) )
-            {
-                throw new ValueSerializationException( "Expected an object but got " + inputNode );
-            }
-            JSONObject object = (JSONObject) item;
-            Object keyNode = object.get( "key" );
-            Object valueNode = object.get( "value" );
-            K key = keyDeserializer.map( keyNode );
-            V value = valueDeserializer.map( valueNode );
-            if( key != null )
-            {
-                map.put( key, value );
-            }
-        }
-    }
-
-    @Override
-    protected <V> void putObjectNodeInMap( Object inputNode, Function<Object, V> valueDeserializer, Map<String, V> map )
-        throws Exception
-    {
-        if( JSONObject.NULL.equals( inputNode ) )
-        {
-            return;
-        }
-        if( !( inputNode instanceof JSONObject ) )
-        {
-            throw new ValueSerializationException( "Expected an object but got " + inputNode );
-        }
-        JSONObject object = (JSONObject) inputNode;
-
-        @SuppressWarnings( "unchecked" )
-        Iterator<String> it = object.keys();
-        while( it.hasNext() )
-        {
-            String key = it.next();
-            Object item = object.get( key );
-            V valueValue = valueDeserializer.map( item );
-            if( key != null )
-            {
-                map.put( key, valueValue );
-            }
-        }
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueSerialization.java b/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueSerialization.java
deleted file mode 100644
index 2e5413f..0000000
--- a/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueSerialization.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.orgjson;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.api.value.ValueSerializationException;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Function2;
-
-/**
- * ValueSerialization producing and consuming JSON documents using org.json.
- *
- * <p>
- *     This class is used internally by the Zest Runtime to provide default ValueSerialization when no
- *     ValueSerialization Service is available.
- * </p>
- * <p>
- *     In application code, prefer the use of {@link OrgJsonValueSerializationService}.
- * </p>
- */
-public class OrgJsonValueSerialization
-    implements ValueSerialization
-{
-
-    private final OrgJsonValueSerializer serializer;
-    private final OrgJsonValueDeserializer deserializer;
-
-    public OrgJsonValueSerialization( Application application, Module module, final Module valuesModule )
-    {
-        this.serializer = new OrgJsonValueSerializer();
-        this.deserializer = new OrgJsonValueDeserializer( application, module, new Function<Application, Module>()
-        {
-            @Override
-            public Module map( Application from )
-            {
-                return valuesModule;
-            }
-        } );
-    }
-
-    @Override
-    public <T> Function<T, String> serialize()
-    {
-        return serializer.serialize();
-    }
-
-    @Override
-    public <T> Function<T, String> serialize( Options options )
-    {
-        return serializer.serialize( options );
-    }
-
-    @Override
-    @Deprecated
-    public <T> Function<T, String> serialize( boolean includeTypeInfo )
-    {
-        return serializer.serialize( includeTypeInfo );
-    }
-
-    @Override
-    public String serialize( Object object )
-        throws ValueSerializationException
-    {
-        return serializer.serialize( object );
-    }
-
-    @Override
-    public String serialize( Options options, Object object )
-        throws ValueSerializationException
-    {
-        return serializer.serialize( options, object );
-    }
-
-    @Override
-    @Deprecated
-    public String serialize( Object object, boolean includeTypeInfo )
-        throws ValueSerializationException
-    {
-        return serializer.serialize( object, includeTypeInfo );
-    }
-
-    @Override
-    public void serialize( Object object, OutputStream output )
-        throws ValueSerializationException
-    {
-        serializer.serialize( object, output );
-    }
-
-    @Override
-    public void serialize( Options options, Object object, OutputStream output )
-        throws ValueSerializationException
-    {
-        serializer.serialize( options, object, output );
-    }
-
-    @Override
-    @Deprecated
-    public void serialize( Object object, OutputStream output, boolean includeTypeInfo )
-        throws ValueSerializationException
-    {
-        serializer.serialize( object, output, includeTypeInfo );
-    }
-
-    @Override
-    public <T> Function<String, T> deserialize( Class<T> type )
-    {
-        return deserializer.deserialize( type );
-    }
-
-    @Override
-    public <T> Function<String, T> deserialize( ValueType valueType )
-    {
-        return deserializer.deserialize( valueType );
-    }
-
-    @Override
-    public <T> Function2<ValueType, String, T> deserialize()
-    {
-        return deserializer.deserialize();
-    }
-
-    @Override
-    public <T> T deserialize( Class<?> type, String input )
-        throws ValueSerializationException
-    {
-        return deserializer.deserialize( type, input );
-    }
-
-    @Override
-    public <T> T deserialize( ValueType type, String input )
-        throws ValueSerializationException
-    {
-        return deserializer.deserialize( type, input );
-    }
-
-    @Override
-    public <T> T deserialize( Class<?> type, InputStream input )
-        throws ValueSerializationException
-    {
-        return deserializer.deserialize( new ValueType( type ), input );
-    }
-
-    @Override
-    public <T> T deserialize( ValueType type, InputStream input )
-        throws ValueSerializationException
-    {
-        return deserializer.deserialize( type, input );
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueSerializationService.java b/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueSerializationService.java
deleted file mode 100644
index 5420b48..0000000
--- a/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueSerializationService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.orgjson;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.value.ValueSerialization;
-
-/**
- * ValueSerialization Service producing and consuming JSON documents using org.json.
- */
-@Mixins( { OrgJsonValueSerializer.class, OrgJsonValueDeserializer.class } )
-public interface OrgJsonValueSerializationService
-    extends ValueSerialization
-{
-}
diff --git a/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueSerializer.java b/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueSerializer.java
deleted file mode 100644
index ddf2fb1..0000000
--- a/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueSerializer.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2010, Niclas Hehdman. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.orgjson;
-
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import org.json.JSONWriter;
-import org.qi4j.spi.value.ValueSerializerAdapter;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializer.OrgJsonOutput;
-
-/**
- * ValueSerializer producing Values state as JSON documents using org.json.
- */
-public class OrgJsonValueSerializer
-    extends ValueSerializerAdapter<OrgJsonOutput>
-{
-
-    /**
-     * Helper to pass around the Writer alongside the JSONWriter so we can flush it onSerializationEnd.
-     *
-     * This is needed because the org.json package do not allow to get a handle on the Writer from a JSONWriter.
-     */
-    public static class OrgJsonOutput
-    {
-
-        private final Writer writer;
-        private final JSONWriter json;
-
-        private OrgJsonOutput( Writer writer, JSONWriter json )
-        {
-            this.writer = writer;
-            this.json = json;
-        }
-    }
-
-    //
-    // Serialization
-    //
-    @Override
-    protected OrgJsonOutput adaptOutput( OutputStream output )
-        throws Exception
-    {
-        Writer writer = new OutputStreamWriter( output, "UTF-8" );
-        JSONWriter json = new JSONWriter( writer );
-        return new OrgJsonOutput( writer, json );
-    }
-
-    @Override
-    protected void onSerializationEnd( Object object, OrgJsonOutput output )
-        throws Exception
-    {
-        output.writer.flush();
-    }
-
-    @Override
-    protected void onArrayStart( OrgJsonOutput output )
-        throws Exception
-    {
-        output.json.array();
-    }
-
-    @Override
-    protected void onArrayEnd( OrgJsonOutput output )
-        throws Exception
-    {
-        output.json.endArray();
-    }
-
-    @Override
-    protected void onObjectStart( OrgJsonOutput output )
-        throws Exception
-    {
-        output.json.object();
-    }
-
-    @Override
-    protected void onObjectEnd( OrgJsonOutput output )
-        throws Exception
-    {
-        output.json.endObject();
-    }
-
-    @Override
-    protected void onFieldStart( OrgJsonOutput output, String fieldName )
-        throws Exception
-    {
-        output.json.key( fieldName );
-    }
-
-    @Override
-    protected void onValue( OrgJsonOutput output, Object value )
-        throws Exception
-    {
-        output.json.value( value );
-    }
-}
diff --git a/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/package.html b/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/package.html
deleted file mode 100644
index f88bff8..0000000
--- a/core/spi/src/main/java/org/qi4j/valueserialization/orgjson/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>org.json Value Serialization.</h2>
-    </body>
-</html>
diff --git a/core/spi/src/test/java/org/apache/polygene/spi/entitystore/Polygene142Test.java b/core/spi/src/test/java/org/apache/polygene/spi/entitystore/Polygene142Test.java
new file mode 100644
index 0000000..935d2ee
--- /dev/null
+++ b/core/spi/src/test/java/org/apache/polygene/spi/entitystore/Polygene142Test.java
@@ -0,0 +1,105 @@
+/*
+ *  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.polygene.spi.entitystore;
+
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.qualifier.Tagged;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Test;
+
+public class Polygene142Test extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        module.values( Regression142Type.class );
+        module.entities( Regression142Type.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Service
+    @Tagged( Serialization.Format.JSON )
+    private Serialization serialization;
+
+    @Test
+    public void polygene142RegressionTest()
+        throws Exception
+    {
+        Regression142Type value;
+        {
+            ValueBuilder<Regression142Type> builder = valueBuilderFactory.newValueBuilder( Regression142Type.class );
+            builder.prototype().price().set( 23.45 );
+            builder.prototype().testenum().set( Regression142Enum.B );
+            value = builder.newInstance();
+            String serialized = serialization.serialize( value );
+            System.out.println( serialized ); // ok
+            value = serialization.deserialize( module, Regression142Type.class, serialized ); // ok
+        }
+        {
+            Identity valueId = new StringIdentity( "abcdefg" );
+            {
+                try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "create" ) ) )
+                {
+                    EntityBuilder<Regression142Type> builder = uow.newEntityBuilder( Regression142Type.class, valueId );
+                    builder.instance().price().set( 45.67 );
+                    builder.instance().testenum().set( Regression142Enum.A );
+                    value = builder.newInstance();
+                    System.out.println( value.testenum().get() );
+                    uow.complete();
+                }
+                catch( Exception e_ )
+                {
+                    e_.printStackTrace();
+                }
+            }
+            {
+                try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "read" ) ) )
+                {
+                    value = uow.get( Regression142Type.class, valueId );
+                    System.out.println( value.price().get() );
+                    System.out.println( value.testenum().get() ); // FAIL
+                }
+            }
+        }
+    }
+
+    private enum Regression142Enum
+    {
+        A,
+        B,
+        C,
+        D
+    }
+
+    interface Regression142Type
+    {
+        Property<Double> price();
+
+        Property<Regression142Enum> testenum();
+    }
+}
diff --git a/core/spi/src/test/java/org/apache/polygene/spi/entitystore/helpers/JSONManyAssociationStateTest.java b/core/spi/src/test/java/org/apache/polygene/spi/entitystore/helpers/JSONManyAssociationStateTest.java
new file mode 100644
index 0000000..a55c642
--- /dev/null
+++ b/core/spi/src/test/java/org/apache/polygene/spi/entitystore/helpers/JSONManyAssociationStateTest.java
@@ -0,0 +1,150 @@
+/*
+ *  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.polygene.spi.entitystore.helpers;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.json.Json;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.time.SystemTime;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.serialization.JsonSerialization;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertThat;
+
+public class JSONManyAssociationStateTest extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+    }
+
+    @Service
+    private JsonSerialization serialization;
+
+    @Service
+    private JavaxJsonFactories jsonFactories;
+
+    @Test
+    public void givenEmptyJSONManyAssociationStateWhenAddingTwoRefsAtZeroIndexExpectCorrectOrder()
+    {
+        // Fake JSONManyAssociationState
+        JsonObjectBuilder builder = Json.createObjectBuilder();
+        builder.add( JSONKeys.VALUE, Json.createObjectBuilder().build() );
+        JsonObject state = builder.build();
+        JSONEntityState entityState = new JSONEntityState( module,
+                                                           serialization,
+                                                           jsonFactories,
+                                                           "0",
+                                                           SystemTime.now(),
+                                                           EntityReference.parseEntityReference( "123" ),
+                                                           EntityStatus.NEW,
+                                                           null,
+                                                           state );
+        JSONManyAssociationState jsonState = new JSONManyAssociationState( jsonFactories, entityState, "under-test" );
+
+        jsonState.add( 0, EntityReference.parseEntityReference( "first" ) );
+        jsonState.add( 0, EntityReference.parseEntityReference( "second" ) );
+
+        assertThat( jsonState.count(), equalTo( 2 ) );
+    }
+
+    @Test
+    public void givenJSONManyAssociationStateWhenChangingReferencesExpectCorrectBehavior()
+    {
+        // Fake JSONManyAssociationState
+        JsonObjectBuilder builder = Json.createObjectBuilder();
+        builder.add( JSONKeys.VALUE, Json.createObjectBuilder().build() );
+        JsonObject state = builder.build();
+        JSONEntityState entityState = new JSONEntityState( module,
+                                                           serialization,
+                                                           jsonFactories,
+                                                           "0",
+                                                           SystemTime.now(),
+                                                           EntityReference.parseEntityReference( "123" ),
+                                                           EntityStatus.NEW,
+                                                           null,
+                                                           state );
+        JSONManyAssociationState jsonState = new JSONManyAssociationState( jsonFactories, entityState, "under-test" );
+
+        assertThat( jsonState.contains( EntityReference.parseEntityReference( "NOT_PRESENT" ) ), is( false ) );
+
+        jsonState.add( 0, EntityReference.parseEntityReference( "0" ) );
+        jsonState.add( 1, EntityReference.parseEntityReference( "1" ) );
+        jsonState.add( 2, EntityReference.parseEntityReference( "2" ) );
+
+        assertThat( jsonState.contains( EntityReference.parseEntityReference( "1" ) ), is( true ) );
+
+        assertThat( jsonState.get( 0 ).identity().toString(), equalTo( "0" ) );
+        assertThat( jsonState.get( 1 ).identity().toString(), equalTo( "1" ) );
+        assertThat( jsonState.get( 2 ).identity().toString(), equalTo( "2" ) );
+
+        assertThat( jsonState.count(), equalTo( 3 ) );
+
+        jsonState.remove( EntityReference.parseEntityReference( "1" ) );
+
+        assertThat( jsonState.count(), equalTo( 2 ) );
+        assertThat( jsonState.contains( EntityReference.parseEntityReference( "1" ) ), is( false ) );
+        assertThat( jsonState.get( 0 ).identity().toString(), equalTo( "0" ) );
+        assertThat( jsonState.get( 1 ).identity().toString(), equalTo( "2" ) );
+
+        jsonState.add( 2, EntityReference.parseEntityReference( "1" ) );
+
+        assertThat( jsonState.count(), equalTo( 3 ) );
+
+        jsonState.add( 0, EntityReference.parseEntityReference( "A" ) );
+        jsonState.add( 0, EntityReference.parseEntityReference( "B" ) );
+        jsonState.add( 0, EntityReference.parseEntityReference( "C" ) );
+
+        assertThat( jsonState.count(), equalTo( 6 ) );
+
+        assertThat( jsonState.get( 0 ).identity().toString(), equalTo( "C" ) );
+        assertThat( jsonState.get( 1 ).identity().toString(), equalTo( "B" ) );
+        assertThat( jsonState.get( 2 ).identity().toString(), equalTo( "A" ) );
+
+        assertThat( jsonState.contains( EntityReference.parseEntityReference( "C" ) ), is( true ) );
+        assertThat( jsonState.contains( EntityReference.parseEntityReference( "B" ) ), is( true ) );
+        assertThat( jsonState.contains( EntityReference.parseEntityReference( "A" ) ), is( true ) );
+        assertThat( jsonState.contains( EntityReference.parseEntityReference( "0" ) ), is( true ) );
+        assertThat( jsonState.contains( EntityReference.parseEntityReference( "2" ) ), is( true ) );
+        assertThat( jsonState.contains( EntityReference.parseEntityReference( "1" ) ), is( true ) );
+
+        List<String> refList = new ArrayList<>();
+        for( EntityReference ref : jsonState )
+        {
+            refList.add( ref.identity().toString() );
+        }
+        assertThat( refList.isEmpty(), is( false ) );
+        assertArrayEquals( new String[]
+                               {
+                                   "C", "B", "A", "0", "2", "1"
+                               }, refList.toArray() );
+    }
+}
diff --git a/core/spi/src/test/java/org/apache/polygene/spi/entitystore/helpers/JsonNamedAssociationStateTest.java b/core/spi/src/test/java/org/apache/polygene/spi/entitystore/helpers/JsonNamedAssociationStateTest.java
new file mode 100644
index 0000000..5bab0c1
--- /dev/null
+++ b/core/spi/src/test/java/org/apache/polygene/spi/entitystore/helpers/JsonNamedAssociationStateTest.java
@@ -0,0 +1,118 @@
+/*
+ *  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.polygene.spi.entitystore.helpers;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import javax.json.Json;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.time.SystemTime;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.serialization.JsonSerialization;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.hasItems;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+public class JsonNamedAssociationStateTest extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+    }
+
+    @Service
+    private JsonSerialization serialization;
+
+    @Service
+    private JavaxJsonFactories jsonFactories;
+
+    @Test
+    public void givenJsonNamedAssociationStateWhenChangingReferencesExpectCorrectBehavior()
+    {
+        // Fake JsonNamedAssociationState
+        JsonObjectBuilder builder = Json.createObjectBuilder();
+        builder.add( JSONKeys.VALUE, Json.createObjectBuilder().build() );
+        JsonObject state = builder.build();
+        JSONEntityState entityState = new JSONEntityState( module,
+                                                           serialization,
+                                                           jsonFactories,
+                                                           "0",
+                                                           SystemTime.now(),
+                                                           EntityReference.parseEntityReference( "123" ),
+                                                           EntityStatus.NEW,
+                                                           null,
+                                                           state );
+        JSONNamedAssociationState jsonState = new JSONNamedAssociationState( jsonFactories, entityState, "under-test" );
+
+
+        assertThat( jsonState.containsName( "foo" ), is( false ) );
+
+        jsonState.put( "foo", EntityReference.parseEntityReference( "0" ) );
+        jsonState.put( "bar", EntityReference.parseEntityReference( "1" ) );
+        jsonState.put( "bazar", EntityReference.parseEntityReference( "2" ) );
+
+        assertThat( jsonState.containsName( "bar" ), is( true ) );
+
+        assertThat( jsonState.get( "foo" ).identity().toString(), equalTo( "0" ) );
+        assertThat( jsonState.get( "bar" ).identity().toString(), equalTo( "1" ) );
+        assertThat( jsonState.get( "bazar" ).identity().toString(), equalTo( "2" ) );
+
+        assertThat( jsonState.count(), equalTo( 3 ) );
+
+        jsonState.remove( "bar" );
+
+        assertThat( jsonState.count(), equalTo( 2 ) );
+        assertThat( jsonState.containsName( "bar" ), is( false ) );
+        assertThat( jsonState.get( "foo" ).identity().toString(), equalTo( "0" ) );
+        assertThat( jsonState.get( "bazar" ).identity().toString(), equalTo( "2" ) );
+
+        jsonState.put( "bar", EntityReference.parseEntityReference( "1" ) );
+
+        assertThat( jsonState.count(), equalTo( 3 ) );
+
+        jsonState.put( "oof", EntityReference.parseEntityReference( "A" ) );
+        jsonState.put( "rab", EntityReference.parseEntityReference( "B" ) );
+        jsonState.put( "razab", EntityReference.parseEntityReference( "C" ) );
+
+        assertThat( jsonState.count(), equalTo( 6 ) );
+
+        assertThat( jsonState.get( "razab" ).identity().toString(), equalTo( "C" ) );
+        assertThat( jsonState.get( "rab" ).identity().toString(), equalTo( "B" ) );
+        assertThat( jsonState.get( "oof" ).identity().toString(), equalTo( "A" ) );
+
+        Map<String, String> refMap = new LinkedHashMap<>();
+        for( String name : jsonState )
+        {
+            refMap.put( name, jsonState.get( name ).identity().toString() );
+        }
+        assertThat( refMap.isEmpty(), is( false ) );
+        assertThat( refMap.keySet(), hasItems( "foo", "bar", "bazar", "oof", "rab", "razab" ) );
+        assertThat( refMap.values(), hasItems( "0", "1", "2", "A", "B", "C" ) );
+    }
+}
diff --git a/core/spi/src/test/java/org/apache/polygene/spi/metrics/DefaultMetricsTest.java b/core/spi/src/test/java/org/apache/polygene/spi/metrics/DefaultMetricsTest.java
new file mode 100644
index 0000000..acbb40d
--- /dev/null
+++ b/core/spi/src/test/java/org/apache/polygene/spi/metrics/DefaultMetricsTest.java
@@ -0,0 +1,118 @@
+/*
+ *  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.polygene.spi.metrics;
+
+import java.time.Instant;
+import org.apache.polygene.api.time.SystemTime;
+import org.junit.Test;
+import org.apache.polygene.api.metrics.MetricsCounter;
+import org.apache.polygene.api.metrics.MetricsCounterFactory;
+import org.apache.polygene.api.metrics.MetricsGauge;
+import org.apache.polygene.api.metrics.MetricsGaugeFactory;
+import org.apache.polygene.api.metrics.MetricsHealthCheck;
+import org.apache.polygene.api.metrics.MetricsHealthCheckFactory;
+import org.apache.polygene.api.metrics.MetricsHistogram;
+import org.apache.polygene.api.metrics.MetricsHistogramFactory;
+import org.apache.polygene.api.metrics.MetricsMeter;
+import org.apache.polygene.api.metrics.MetricsMeterFactory;
+import org.apache.polygene.api.metrics.MetricsProvider;
+import org.apache.polygene.api.metrics.MetricsTimer;
+import org.apache.polygene.api.metrics.MetricsTimerFactory;
+
+import static org.junit.Assert.assertNull;
+
+public class DefaultMetricsTest
+{
+    @Test
+    public void givenMetricsProviderWithoutSupportForCounterWhenRequestingCounterExpectDefaultNullImplementation()
+    {
+        MetricsProvider underTest = new MetricsProviderAdapter();
+        MetricsCounterFactory factory = underTest.createFactory( MetricsCounterFactory.class );
+        MetricsCounter test = factory.createCounter( "test" );
+        test.increment();
+        test.decrement();
+    }
+
+    @Test
+    public void givenMetricsProviderWithoutSupportForGaugeWhenRequestingGaugeExpectDefaultNullImplementation()
+    {
+        MetricsProvider underTest = new MetricsProviderAdapter();
+        MetricsGaugeFactory factory = underTest.createFactory( MetricsGaugeFactory.class );
+        MetricsGauge<Instant> test = factory.registerGauge( "test", new MetricsGauge<Instant>()
+        {
+            @Override
+            public Instant value()
+            {
+                return SystemTime.now();
+            }
+        } );
+        assertNull( test.value() );
+    }
+
+    @Test
+    public void givenMetricsProviderWithoutSupportForHealthCheckWhenRequestingHealthCheckExpectDefaultNullImplementation()
+        throws Exception
+    {
+        MetricsProvider underTest = new MetricsProviderAdapter();
+        MetricsHealthCheckFactory factory = underTest.createFactory( MetricsHealthCheckFactory.class );
+        MetricsHealthCheck test = factory.registerHealthCheck( "test", new MetricsHealthCheck()
+        {
+            @Override
+            public Result check()
+                throws Exception
+            {
+                throw new RuntimeException( "Not healthy!!!" );
+            }
+        } );
+        test.check(); // Should not throw an exception, as it should have been replaced by a null implementation.
+    }
+
+    @Test
+    public void givenMetricsProviderWithoutSupportForHistogramWhenRequestingHistogramExpectDefaultNullImplementation()
+    {
+        MetricsProvider underTest = new MetricsProviderAdapter();
+        MetricsHistogramFactory factory = underTest.createFactory( MetricsHistogramFactory.class );
+        MetricsHistogram test = factory.createHistogram( "test" );
+        test.update( 5L );
+        test.update( 5L );
+        test.update( 5L );
+    }
+
+    @Test
+    public void givenMetricsProviderWithoutSupportForMeterWhenRequestingMeterExpectDefaultNullImplementation()
+    {
+        MetricsProvider underTest = new MetricsProviderAdapter();
+        MetricsMeterFactory factory = underTest.createFactory( MetricsMeterFactory.class );
+        MetricsMeter test = factory.createMeter( "test" );
+        test.mark();
+        test.mark();
+        test.mark();
+    }
+
+    @Test
+    public void givenMetricsProviderWithoutSupportForTimerWhenRequestingTimerExpectDefaultNullImplementation()
+    {
+        MetricsProvider underTest = new MetricsProviderAdapter();
+        MetricsTimerFactory factory = underTest.createFactory( MetricsTimerFactory.class );
+        MetricsTimer test = factory.createTimer( "test" );
+        test.start().stop();
+    }
+}
diff --git a/core/spi/src/test/java/org/apache/polygene/spi/property/DefaultValuesTest.java b/core/spi/src/test/java/org/apache/polygene/spi/property/DefaultValuesTest.java
new file mode 100644
index 0000000..5b7fc91
--- /dev/null
+++ b/core/spi/src/test/java/org/apache/polygene/spi/property/DefaultValuesTest.java
@@ -0,0 +1,76 @@
+/*
+ *  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.polygene.spi.property;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import org.junit.Test;
+import org.apache.polygene.api.property.DefaultValues;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Test for DefaultValues
+ */
+public class DefaultValuesTest
+{
+    @Test
+    public void givenDefaultValuesWhenRequestStringThenGetEmptyString()
+    {
+        assertThat( "Empty string", DefaultValues.getDefaultValueOf( String.class ), equalTo( "" ) );
+    }
+
+    @Test
+    public void givenDefaultValuesWhenRequestListThenGetEmptyList()
+    {
+        assertThat( "Empty list", DefaultValues.getDefaultValueOf( List.class ), equalTo( Collections.emptyList() ) );
+    }
+
+    @Test
+    public void givenDefaultValuesWhenRequestSetThenGetEmptySet()
+    {
+        assertThat( "Empty set", DefaultValues.getDefaultValueOf( Set.class ), equalTo( Collections.emptySet() ) );
+    }
+
+    @Test
+    public void givenDefaultValuesWhenRequestCollectionThenGetEmptyCollection()
+    {
+        Collection<Object> coll = (Collection<Object>) DefaultValues.getDefaultValueOf( Collection.class );
+        Collection<Object> empty = Collections.EMPTY_LIST;
+        assertThat( "Empty collection", coll, equalTo( empty ) );
+    }
+
+    @Test
+    public void givenDefaultValuesWhenRequestEnumThenGetFirstValue()
+    {
+        Object val = DefaultValues.getDefaultValueOf( ValueTest.class );
+        Object value1 = ValueTest.VALUE1;
+        assertThat( "Enum first value", val, equalTo( value1 ) );
+    }
+
+    public enum ValueTest
+    {
+        VALUE1, VALUE2, VALUE3
+    }
+}
diff --git a/core/spi/src/test/java/org/qi4j/spi/entitystore/helpers/JSONManyAssociationStateTest.java b/core/spi/src/test/java/org/qi4j/spi/entitystore/helpers/JSONManyAssociationStateTest.java
deleted file mode 100644
index dba4b58..0000000
--- a/core/spi/src/test/java/org/qi4j/spi/entitystore/helpers/JSONManyAssociationStateTest.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2013-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.entitystore.helpers;
-
-import java.util.List;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.junit.Test;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.functional.Function;
-import org.qi4j.spi.entity.EntityStatus;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.functional.Iterables.map;
-import static org.qi4j.functional.Iterables.toList;
-
-public class JSONManyAssociationStateTest
-{
-
-    @Test
-    public void givenEmptyJSONManyAssociationStateWhenAddingTwoRefsAtZeroIndexExpectCorrectOrder()
-        throws JSONException
-    {
-        // Fake JSONManyAssociationState
-        JSONObject state = new JSONObject();
-        state.put( JSONKeys.PROPERTIES, new JSONObject() );
-        state.put( JSONKeys.ASSOCIATIONS, new JSONObject() );
-        state.put( JSONKeys.MANY_ASSOCIATIONS, new JSONObject() );
-        state.put( JSONKeys.NAMED_ASSOCIATIONS, new JSONObject() );
-        JSONEntityState entityState = new JSONEntityState( null,
-                                                           "0",
-                                                           System.currentTimeMillis(),
-                                                           EntityReference.parseEntityReference( "123" ),
-                                                           EntityStatus.NEW,
-                                                           null,
-                                                           state );
-        JSONManyAssociationState jsonState = new JSONManyAssociationState( entityState, new JSONArray() );
-
-        jsonState.add( 0, EntityReference.parseEntityReference( "first" ) );
-        jsonState.add( 0, EntityReference.parseEntityReference( "second" ) );
-
-        assertThat( jsonState.count(), equalTo( 2 ) );
-    }
-
-    @Test
-    public void givenJSONManyAssociationStateWhenChangingReferencesExpectCorrectBehavior()
-        throws JSONException
-    {
-        // Fake JSONManyAssociationState
-        JSONObject state = new JSONObject();
-        state.put( JSONKeys.PROPERTIES, new JSONObject() );
-        state.put( JSONKeys.ASSOCIATIONS, new JSONObject() );
-        state.put( JSONKeys.MANY_ASSOCIATIONS, new JSONObject() );
-        state.put( JSONKeys.NAMED_ASSOCIATIONS, new JSONObject() );
-        JSONEntityState entityState = new JSONEntityState( null,
-                                                           "0",
-                                                           System.currentTimeMillis(),
-                                                           EntityReference.parseEntityReference( "123" ),
-                                                           EntityStatus.NEW,
-                                                           null,
-                                                           state );
-        JSONManyAssociationState jsonState = new JSONManyAssociationState( entityState, new JSONArray() );
-
-        assertThat( jsonState.contains( EntityReference.parseEntityReference( "NOT_PRESENT" ) ), is( false ) );
-
-        jsonState.add( 0, EntityReference.parseEntityReference( "0" ) );
-        jsonState.add( 1, EntityReference.parseEntityReference( "1" ) );
-        jsonState.add( 2, EntityReference.parseEntityReference( "2" ) );
-
-        assertThat( jsonState.contains( EntityReference.parseEntityReference( "1" ) ), is( true ) );
-
-        assertThat( jsonState.get( 0 ).identity(), equalTo( "0" ) );
-        assertThat( jsonState.get( 1 ).identity(), equalTo( "1" ) );
-        assertThat( jsonState.get( 2 ).identity(), equalTo( "2" ) );
-
-        assertThat( jsonState.count(), equalTo( 3 ) );
-
-        jsonState.remove( EntityReference.parseEntityReference( "1" ) );
-
-        assertThat( jsonState.count(), equalTo( 2 ) );
-        assertThat( jsonState.contains( EntityReference.parseEntityReference( "1" ) ), is( false ) );
-        assertThat( jsonState.get( 0 ).identity(), equalTo( "0" ) );
-        assertThat( jsonState.get( 1 ).identity(), equalTo( "2" ) );
-
-        jsonState.add( 2, EntityReference.parseEntityReference( "1" ) );
-
-        assertThat( jsonState.count(), equalTo( 3 ) );
-
-        jsonState.add( 0, EntityReference.parseEntityReference( "A" ) );
-        jsonState.add( 0, EntityReference.parseEntityReference( "B" ) );
-        jsonState.add( 0, EntityReference.parseEntityReference( "C" ) );
-
-        assertThat( jsonState.count(), equalTo( 6 ) );
-
-        assertThat( jsonState.get( 0 ).identity(), equalTo( "C" ) );
-        assertThat( jsonState.get( 1 ).identity(), equalTo( "B" ) );
-        assertThat( jsonState.get( 2 ).identity(), equalTo( "A" ) );
-
-        assertThat( jsonState.contains( EntityReference.parseEntityReference( "C" ) ), is( true ) );
-        assertThat( jsonState.contains( EntityReference.parseEntityReference( "B" ) ), is( true ) );
-        assertThat( jsonState.contains( EntityReference.parseEntityReference( "A" ) ), is( true ) );
-        assertThat( jsonState.contains( EntityReference.parseEntityReference( "0" ) ), is( true ) );
-        assertThat( jsonState.contains( EntityReference.parseEntityReference( "2" ) ), is( true ) );
-        assertThat( jsonState.contains( EntityReference.parseEntityReference( "1" ) ), is( true ) );
-
-        List<String> refList = toList( map( new Function<EntityReference, String>()
-        {
-            @Override
-            public String map( EntityReference from )
-            {
-                return from.identity();
-            }
-        }, jsonState ) );
-        assertThat( refList.isEmpty(), is( false ) );
-        assertArrayEquals( new String[]
-        {
-            "C", "B", "A", "0", "2", "1"
-        }, refList.toArray() );
-    }
-}
diff --git a/core/spi/src/test/java/org/qi4j/spi/metrics/DefaultMetricsTest.java b/core/spi/src/test/java/org/qi4j/spi/metrics/DefaultMetricsTest.java
deleted file mode 100644
index 981b196..0000000
--- a/core/spi/src/test/java/org/qi4j/spi/metrics/DefaultMetricsTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file Expect 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.qi4j.spi.metrics;
-
-import java.util.concurrent.TimeUnit;
-import org.junit.Test;
-import org.qi4j.api.metrics.MetricsCounter;
-import org.qi4j.api.metrics.MetricsCounterFactory;
-import org.qi4j.api.metrics.MetricsGauge;
-import org.qi4j.api.metrics.MetricsGaugeFactory;
-import org.qi4j.api.metrics.MetricsHealthCheck;
-import org.qi4j.api.metrics.MetricsHealthCheckFactory;
-import org.qi4j.api.metrics.MetricsHistogram;
-import org.qi4j.api.metrics.MetricsHistogramFactory;
-import org.qi4j.api.metrics.MetricsMeter;
-import org.qi4j.api.metrics.MetricsMeterFactory;
-import org.qi4j.api.metrics.MetricsProvider;
-import org.qi4j.api.metrics.MetricsTimer;
-import org.qi4j.api.metrics.MetricsTimerFactory;
-
-import static org.junit.Assert.assertNull;
-
-public class DefaultMetricsTest
-{
-    @Test
-    public void givenMetricsProviderWithoutSupportForCounterWhenRequestingCounterExpectDefaultNullImplementation()
-    {
-        MetricsProvider underTest = new MetricsProviderAdapter();
-        MetricsCounterFactory factory = underTest.createFactory( MetricsCounterFactory.class );
-        MetricsCounter test = factory.createCounter( getClass(), "test" );
-        test.increment();
-        test.decrement();
-    }
-
-    @Test
-    public void givenMetricsProviderWithoutSupportForGaugeWhenRequestingGaugeExpectDefaultNullImplementation()
-    {
-        MetricsProvider underTest = new MetricsProviderAdapter();
-        MetricsGaugeFactory factory = underTest.createFactory( MetricsGaugeFactory.class );
-        MetricsGauge<Long> test = factory.registerGauge( getClass(), "test", new MetricsGauge<Long>()
-        {
-            @Override
-            public Long value()
-            {
-                return System.currentTimeMillis();
-            }
-        } );
-        assertNull( test.value() );
-    }
-
-    @Test
-    public void givenMetricsProviderWithoutSupportForHealthCheckWhenRequestingHealthCheckExpectDefaultNullImplementation()
-        throws Exception
-    {
-        MetricsProvider underTest = new MetricsProviderAdapter();
-        MetricsHealthCheckFactory factory = underTest.createFactory( MetricsHealthCheckFactory.class );
-        MetricsHealthCheck test = factory.registerHealthCheck( getClass(), "test", new MetricsHealthCheck()
-        {
-            @Override
-            public Result check()
-                throws Exception
-            {
-                throw new RuntimeException( "Not healthy!!!" );
-            }
-        } );
-        test.check(); // Should not throw an exception, as it should have been replaced by a null implementation.
-    }
-
-    @Test
-    public void givenMetricsProviderWithoutSupportForHistogramWhenRequestingHistogramExpectDefaultNullImplementation()
-    {
-        MetricsProvider underTest = new MetricsProviderAdapter();
-        MetricsHistogramFactory factory = underTest.createFactory( MetricsHistogramFactory.class );
-        MetricsHistogram test = factory.createHistogram( getClass(), "test" );
-        test.update( 5L );
-        test.update( 5L );
-        test.update( 5L );
-    }
-
-    @Test
-    public void givenMetricsProviderWithoutSupportForMeterWhenRequestingMeterExpectDefaultNullImplementation()
-    {
-        MetricsProvider underTest = new MetricsProviderAdapter();
-        MetricsMeterFactory factory = underTest.createFactory( MetricsMeterFactory.class );
-        MetricsMeter test = factory.createMeter( getClass(), "test", "niclas", TimeUnit.MILLISECONDS );
-        test.mark();
-        test.mark();
-        test.mark();
-    }
-
-    @Test
-    public void givenMetricsProviderWithoutSupportForTimerWhenRequestingTimerExpectDefaultNullImplementation()
-    {
-        MetricsProvider underTest = new MetricsProviderAdapter();
-        MetricsTimerFactory factory = underTest.createFactory( MetricsTimerFactory.class );
-        MetricsTimer test = factory.createTimer( getClass(), "test", TimeUnit.MILLISECONDS, TimeUnit.DAYS );
-        test.start().stop();
-    }
-}
diff --git a/core/spi/src/test/java/org/qi4j/spi/property/DefaultValuesTest.java b/core/spi/src/test/java/org/qi4j/spi/property/DefaultValuesTest.java
deleted file mode 100644
index 7d01e27..0000000
--- a/core/spi/src/test/java/org/qi4j/spi/property/DefaultValuesTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.spi.property;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import org.junit.Test;
-import org.qi4j.api.property.DefaultValues;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-/**
- * Test for DefaultValues
- */
-public class DefaultValuesTest
-{
-    @Test
-    public void givenDefaultValuesWhenRequestStringThenGetEmptyString()
-    {
-        assertThat( "Empty string", (String) DefaultValues.getDefaultValueOf( String.class ), equalTo( "" ) );
-    }
-
-    @Test
-    public void givenDefaultValuesWhenRequestListThenGetEmptyList()
-    {
-        assertThat( "Empty list", (List<Object>) DefaultValues.getDefaultValueOf( List.class ), equalTo( Collections.emptyList() ) );
-    }
-
-    @Test
-    public void givenDefaultValuesWhenRequestSetThenGetEmptySet()
-    {
-        assertThat( "Empty set", (Set<Object>) DefaultValues.getDefaultValueOf( Set.class ), equalTo( Collections.emptySet() ) );
-    }
-
-    @Test
-    public void givenDefaultValuesWhenRequestCollectionThenGetEmptyCollection()
-    {
-        Collection<Object> coll = (Collection<Object>) DefaultValues.getDefaultValueOf( Collection.class );
-        Collection<Object> empty = Collections.EMPTY_LIST;
-        assertThat( "Empty collection", coll, equalTo( empty ) );
-    }
-
-    @Test
-    public void givenDefaultValuesWhenRequestEnumThenGetFirstValue()
-    {
-        Object val = DefaultValues.getDefaultValueOf( ValueTest.class );
-        Object value1 = ValueTest.VALUE1;
-        assertThat( "Enum first value", val, equalTo( value1 ) );
-    }
-
-    public enum ValueTest
-    {
-        VALUE1, VALUE2, VALUE3
-    }
-}
diff --git a/core/spi/src/test/resources/logback-test.xml b/core/spi/src/test/resources/logback-test.xml
index ce6e028..e78e598 100644
--- a/core/spi/src/test/resources/logback-test.xml
+++ b/core/spi/src/test/resources/logback-test.xml
@@ -1,20 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <configuration>
 
     <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
@@ -27,6 +30,6 @@
         <appender-ref ref="stdout" />
     </root>
 
-    <logger name="org.qi4j.spi" level="debug"/>
+    <logger name="org.apache.polygene.spi" level="debug"/>
 
 </configuration>
diff --git a/core/testsupport/build.gradle b/core/testsupport/build.gradle
index 2f0af58..adfa425 100644
--- a/core/testsupport/build.gradle
+++ b/core/testsupport/build.gradle
@@ -1,29 +1,31 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-jar { manifest { name = "Apache Zest™ Core TestSupport"}}
+apply plugin: 'polygene-core'
+
+jar { manifest { name = "Apache Polygene™ Core Test Support" } }
 
 dependencies {
+  api polygene.core.bootstrap
+  api libraries.junit
+  api libraries.hamcrest
 
-  compile project( ':org.qi4j.core:org.qi4j.core.bootstrap' )
-  compile libraries.junit
-
-  testRuntime project( ':org.qi4j.core:org.qi4j.core.runtime' )
-
+  testRuntimeOnly polygene.core.runtime
 }
diff --git a/core/testsupport/dev-status.xml b/core/testsupport/dev-status.xml
index 7b1a30b..2e7c7ff 100644
--- a/core/testsupport/dev-status.xml
+++ b/core/testsupport/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <codebase>stable</codebase>
     <!--none,early,beta,stable,mature-->
diff --git a/core/testsupport/licenses/hamcrest.license b/core/testsupport/licenses/hamcrest.license
new file mode 100644
index 0000000..0bf6264
--- /dev/null
+++ b/core/testsupport/licenses/hamcrest.license
@@ -0,0 +1,27 @@
+BSD License
+
+Copyright (c) 2000-2015 www.hamcrest.org
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of
+conditions and the following disclaimer. Redistributions in binary form must reproduce
+the above copyright notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the distribution.
+
+Neither the name of Hamcrest nor the names of its contributors may be used to endorse
+or promote products derived from this software without specific prior written
+permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
\ No newline at end of file
diff --git a/core/testsupport/licenses/junit.license b/core/testsupport/licenses/junit.license
new file mode 100644
index 0000000..598690e
--- /dev/null
+++ b/core/testsupport/licenses/junit.license
@@ -0,0 +1,229 @@
+Copyright junit.org
+
+Eclipse Public License - v 1.0
+
+   THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+   PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF
+   THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+   1. DEFINITIONS
+
+   "Contribution" means:
+
+   a) in the case of the initial Contributor, the initial code and
+   documentation distributed under this Agreement, and
+
+   b) in the case of each subsequent Contributor:
+
+   i) changes to the Program, and
+
+   ii) additions to the Program;
+
+   where such changes and/or additions to the Program originate from and
+   are distributed by that particular Contributor. A Contribution
+   'originates' from a Contributor if it was added to the Program by such
+   Contributor itself or anyone acting on such Contributor's behalf.
+   Contributions do not include additions to the Program which: (i) are
+   separate modules of software distributed in conjunction with the
+   Program under their own license agreement, and (ii) are not derivative
+   works of the Program.
+
+   "Contributor" means any person or entity that distributes the Program.
+
+   "Licensed Patents" mean patent claims licensable by a Contributor which
+   are necessarily infringed by the use or sale of its Contribution alone
+   or when combined with the Program.
+
+   "Program" means the Contributions distributed in accordance with this
+   Agreement.
+
+   "Recipient" means anyone who receives the Program under this Agreement,
+   including all Contributors.
+
+   2. GRANT OF RIGHTS
+
+   a) Subject to the terms of this Agreement, each Contributor hereby
+   grants Recipient a non-exclusive, worldwide, royalty-free copyright
+   license to reproduce, prepare derivative works of, publicly display,
+   publicly perform, distribute and sublicense the Contribution of such
+   Contributor, if any, and such derivative works, in source code and
+   object code form.
+
+   b) Subject to the terms of this Agreement, each Contributor hereby
+   grants Recipient a non-exclusive, worldwide, royalty-free patent
+   license under Licensed Patents to make, use, sell, offer to sell,
+   import and otherwise transfer the Contribution of such Contributor, if
+   any, in source code and object code form. This patent license shall
+   apply to the combination of the Contribution and the Program if, at the
+   time the Contribution is added by the Contributor, such addition of the
+   Contribution causes such combination to be covered by the Licensed
+   Patents. The patent license shall not apply to any other combinations
+   which include the Contribution. No hardware per se is licensed
+   hereunder.
+
+   c) Recipient understands that although each Contributor grants the
+   licenses to its Contributions set forth herein, no assurances are
+   provided by any Contributor that the Program does not infringe the
+   patent or other intellectual property rights of any other entity. Each
+   Contributor disclaims any liability to Recipient for claims brought by
+   any other entity based on infringement of intellectual property rights
+   or otherwise. As a condition to exercising the rights and licenses
+   granted hereunder, each Recipient hereby assumes sole responsibility to
+   secure any other intellectual property rights needed, if any. For
+   example, if a third party patent license is required to allow Recipient
+   to distribute the Program, it is Recipient's responsibility to acquire
+   that license before distributing the Program.
+
+   d) Each Contributor represents that to its knowledge it has sufficient
+   copyright rights in its Contribution, if any, to grant the copyright
+   license set forth in this Agreement.
+
+   3. REQUIREMENTS
+
+   A Contributor may choose to distribute the Program in object code form
+   under its own license agreement, provided that:
+
+   a) it complies with the terms and conditions of this Agreement; and
+
+   b) its license agreement:
+
+   i) effectively disclaims on behalf of all Contributors all warranties
+   and conditions, express and implied, including warranties or conditions
+   of title and non-infringement, and implied warranties or conditions of
+   merchantability and fitness for a particular purpose;
+
+   ii) effectively excludes on behalf of all Contributors all liability
+   for damages, including direct, indirect, special, incidental and
+   consequential damages, such as lost profits;
+
+   iii) states that any provisions which differ from this Agreement are
+   offered by that Contributor alone and not by any other party; and
+
+   iv) states that source code for the Program is available from such
+   Contributor, and informs licensees how to obtain it in a reasonable
+   manner on or through a medium customarily used for software exchange.
+
+   When the Program is made available in source code form:
+
+   a) it must be made available under this Agreement; and
+
+   b) a copy of this Agreement must be included with each copy of the
+   Program.
+
+   Contributors may not remove or alter any copyright notices contained
+   within the Program.
+
+   Each Contributor must identify itself as the originator of its
+   Contribution, if any, in a manner that reasonably allows subsequent
+   Recipients to identify the originator of the Contribution.
+
+   4. COMMERCIAL DISTRIBUTION
+
+   Commercial distributors of software may accept certain responsibilities
+   with respect to end users, business partners and the like. While this
+   license is intended to facilitate the commercial use of the Program,
+   the Contributor who includes the Program in a commercial product
+   offering should do so in a manner which does not create potential
+   liability for other Contributors. Therefore, if a Contributor includes
+   the Program in a commercial product offering, such Contributor
+   ("Commercial Contributor") hereby agrees to defend and indemnify every
+   other Contributor ("Indemnified Contributor") against any losses,
+   damages and costs (collectively "Losses") arising from claims, lawsuits
+   and other legal actions brought by a third party against the
+   Indemnified Contributor to the extent caused by the acts or omissions
+   of such Commercial Contributor in connection with its distribution of
+   the Program in a commercial product offering. The obligations in this
+   section do not apply to any claims or Losses relating to any actual or
+   alleged intellectual property infringement. In order to qualify, an
+   Indemnified Contributor must: a) promptly notify the Commercial
+   Contributor in writing of such claim, and b) allow the Commercial
+   Contributor to control, and cooperate with the Commercial Contributor
+   in, the defense and any related settlement negotiations. The
+   Indemnified Contributor may participate in any such claim at its own
+   expense.
+
+   For example, a Contributor might include the Program in a commercial
+   product offering, Product X. That Contributor is then a Commercial
+   Contributor. If that Commercial Contributor then makes performance
+   claims, or offers warranties related to Product X, those performance
+   claims and warranties are such Commercial Contributor's responsibility
+   alone. Under this section, the Commercial Contributor would have to
+   defend claims against the other Contributors related to those
+   performance claims and warranties, and if a court requires any other
+   Contributor to pay any damages as a result, the Commercial Contributor
+   must pay those damages.
+
+   5. NO WARRANTY
+
+   EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+   PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+   KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+   WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
+   FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible
+   for determining the appropriateness of using and distributing the
+   Program and assumes all risks associated with its exercise of rights
+   under this Agreement , including but not limited to the risks and costs
+   of program errors, compliance with applicable laws, damage to or loss
+   of data, programs or equipment, and unavailability or interruption of
+   operations.
+
+   6. DISCLAIMER OF LIABILITY
+
+   EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
+   ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+   WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+   DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+   HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+   7. GENERAL
+
+   If any provision of this Agreement is invalid or unenforceable under
+   applicable law, it shall not affect the validity or enforceability of
+   the remainder of the terms of this Agreement, and without further
+   action by the parties hereto, such provision shall be reformed to the
+   minimum extent necessary to make such provision valid and enforceable.
+
+   If Recipient institutes patent litigation against any entity (including
+   a cross-claim or counterclaim in a lawsuit) alleging that the Program
+   itself (excluding combinations of the Program with other software or
+   hardware) infringes such Recipient's patent(s), then such Recipient's
+   rights granted under Section 2(b) shall terminate as of the date such
+   litigation is filed.
+
+   All Recipient's rights under this Agreement shall terminate if it fails
+   to comply with any of the material terms or conditions of this
+   Agreement and does not cure such failure in a reasonable period of time
+   after becoming aware of such noncompliance. If all Recipient's rights
+   under this Agreement terminate, Recipient agrees to cease use and
+   distribution of the Program as soon as reasonably practicable. However,
+   Recipient's obligations under this Agreement and any licenses granted
+   by Recipient relating to the Program shall continue and survive.
+
+   Everyone is permitted to copy and distribute copies of this Agreement,
+   but in order to avoid inconsistency the Agreement is copyrighted and
+   may only be modified in the following manner. The Agreement Steward
+   reserves the right to publish new versions (including revisions) of
+   this Agreement from time to time. No one other than the Agreement
+   Steward has the right to modify this Agreement. The Eclipse Foundation
+   is the initial Agreement Steward. The Eclipse Foundation may assign the
+   responsibility to serve as the Agreement Steward to a suitable separate
+   entity. Each new version of the Agreement will be given a
+   distinguishing version number. The Program (including Contributions)
+   may always be distributed subject to the version of the Agreement under
+   which it was received. In addition, after a new version of the
+   Agreement is published, Contributor may elect to distribute the Program
+   (including its Contributions) under the new version. Except as
+   expressly stated in Sections 2(a) and 2(b) above, Recipient receives no
+   rights or licenses to the intellectual property of any Contributor
+   under this Agreement, whether expressly, by implication, estoppel or
+   otherwise. All rights in the Program not expressly granted under this
+   Agreement are reserved.
+
+   This Agreement is governed by the laws of the State of New York and the
+   intellectual property laws of the United States of America. No party to
+   this Agreement will bring a legal action under this Agreement more than
+   one year after the cause of action arose. Each party waives its rights
+   to a jury trial in any resulting litigation.
\ No newline at end of file
diff --git a/core/testsupport/src/docs/reference/AbstractQi4jScenarioTest.txt b/core/testsupport/src/docs/reference/AbstractPolygeneScenarioTest.txt
similarity index 100%
rename from core/testsupport/src/docs/reference/AbstractQi4jScenarioTest.txt
rename to core/testsupport/src/docs/reference/AbstractPolygeneScenarioTest.txt
diff --git a/core/testsupport/src/docs/reference/AbstractQi4jTest.txt b/core/testsupport/src/docs/reference/AbstractPolygeneTest.txt
similarity index 100%
rename from core/testsupport/src/docs/reference/AbstractQi4jTest.txt
rename to core/testsupport/src/docs/reference/AbstractPolygeneTest.txt
diff --git a/core/testsupport/src/docs/reference/ref-testsupport.txt b/core/testsupport/src/docs/reference/ref-testsupport.txt
index e1f117f..2814fa0 100644
--- a/core/testsupport/src/docs/reference/ref-testsupport.txt
+++ b/core/testsupport/src/docs/reference/ref-testsupport.txt
@@ -17,9 +17,9 @@
  * under the License.
 ///////////////////////////////////////////////////////////////
 
-include::AbstractQi4jTest.txt
+include::AbstractPolygeneTest.txt
 
-include::AbstractQi4jScenarioTest.txt
+include::AbstractPolygeneScenarioTest.txt
 
 include::AbstractEntityStoreTest.txt
 
diff --git a/core/testsupport/src/docs/testsupport.txt b/core/testsupport/src/docs/testsupport.txt
index f3c9585..d0abd44 100644
--- a/core/testsupport/src/docs/testsupport.txt
+++ b/core/testsupport/src/docs/testsupport.txt
@@ -1,16 +1,19 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
+ *  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
  *
- * Licensed 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.
+ *       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.
 //////////////////////
 
 [[core-testsupport,TestSupport]]
@@ -21,36 +24,36 @@
 source=core/testsupport/dev-status.xml
 --------------
 
-Zest™ comes with classes to help with testing. For general development, only a couple of classes are of interest as the
+Polygene™ comes with classes to help with testing. For general development, only a couple of classes are of interest as the
 others are mostly for EntityStore and Index/Query SPI implementations. There is also some mocking support, to allow
-some of Zest's unique aspects to be mocked, but since Zest™ is so flexible at a fine-granular level, we have found that
+some of Polygene's unique aspects to be mocked, but since Polygene™ is so flexible at a fine-granular level, we have found that
 mocking is seldom, if ever, needed.
 
 include::../../build/docs/buildinfo/artifact.txt[]
 
 == Your First Testcase ==
-In most cases, you will probably use the AbstractQi4jTest class to simplify starting a Zest™ test instance.
+In most cases, you will probably use the AbstractPolygeneTest class to simplify starting a Polygene™ test instance.
 
 [snippet,java]
 --------------
-source=tutorials/hello/src/test/java/org/qi4j/tutorials/hello/HelloTest.java
+source=tutorials/hello/src/test/java/org/apache/polygene/tutorials/hello/HelloTest.java
 tag=step1
 --------------
 
-This will do all the initialization of a Zest™ runtime instance and create a single layer with a single module in it.
+This will do all the initialization of a Polygene™ runtime instance and create a single layer with a single module in it.
 What goes into that module is declared in the assembly() method;
 
 [snippet,java]
 --------------
-source=tutorials/hello/src/test/java/org/qi4j/tutorials/hello/HelloTest.java
+source=tutorials/hello/src/test/java/org/apache/polygene/tutorials/hello/HelloTest.java
 tag=step2
 --------------
 
-In this case we declare that we have a ValueComposite of type org.qi4j.tutorials.hello.Hello which looks like
+In this case we declare that we have a ValueComposite of type org.apache.polygene.tutorials.hello.Hello which looks like
 
 [snippet,java]
 --------------
-source=tutorials/hello/src/main/java/org/qi4j/tutorials/hello/Hello.java
+source=tutorials/hello/src/main/java/org/apache/polygene/tutorials/hello/Hello.java
 tag=body
 --------------
 
@@ -61,7 +64,7 @@
 
 [snippet,java]
 --------------
-source=tutorials/hello/src/test/java/org/qi4j/tutorials/hello/HelloTest.java
+source=tutorials/hello/src/test/java/org/apache/polygene/tutorials/hello/HelloTest.java
 tag=step3
 --------------
 
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/AbstractPolygeneBaseTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/AbstractPolygeneBaseTest.java
new file mode 100644
index 0000000..6d7d6ba
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/AbstractPolygeneBaseTest.java
@@ -0,0 +1,129 @@
+/*
+ *  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.polygene.test;
+
+import org.apache.polygene.test.util.NotYetImplemented;
+import org.junit.After;
+import org.junit.Before;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.junit.Rule;
+
+public abstract class AbstractPolygeneBaseTest
+{
+    @Rule public NotYetImplemented.Rule notYetImplementedRule = new NotYetImplemented.Rule();
+
+    protected PolygeneAPI api;
+    protected PolygeneSPI spi;
+
+    protected Energy4Java polygene;
+    protected ApplicationDescriptor applicationModel;
+    protected Application application;
+
+    @Before
+    public void setUp()
+        throws Exception
+    {
+        polygene = new Energy4Java();
+        applicationModel = newApplicationModel();
+        if( applicationModel == null )
+        {
+            // An AssemblyException has occurred that the Test wants to check for.
+            return;
+        }
+        application = newApplicationInstance( applicationModel );
+        initApplication( application );
+        api = spi = polygene.spi();
+        application.activate();
+    }
+
+    /** Called by the superclass for the test to define the entire application, every layer, every module and all
+     * the contents of each module.
+     *
+     * @param applicationAssembly the {@link org.apache.polygene.bootstrap.ApplicationAssembly} to be populated.
+     *
+     * @throws AssemblyException on invalid assembly
+     */
+    protected abstract void defineApplication( ApplicationAssembly applicationAssembly )
+        throws AssemblyException;
+
+    protected Application newApplicationInstance( ApplicationDescriptor applicationModel )
+    {
+        return applicationModel.newInstance( polygene.api() );
+    }
+
+    protected ApplicationDescriptor newApplicationModel()
+        throws AssemblyException
+    {
+        ApplicationAssembler assembler = applicationFactory ->
+        {
+            ApplicationAssembly applicationAssembly = applicationFactory.newApplicationAssembly();
+            applicationAssembly.setMode( Application.Mode.test );
+            defineApplication( applicationAssembly );
+            return applicationAssembly;
+        };
+
+        try
+        {
+            return polygene.newApplicationModel( assembler );
+        }
+        catch( AssemblyException e )
+        {
+            assemblyException( e );
+            return null;
+        }
+    }
+
+    /**
+     * This method is called when there was an AssemblyException in the creation of the Polygene application model.
+     * <p>
+     * Override this method to catch valid failures to place into satisfiedBy suites.
+     * </p>
+     * @param exception the exception thrown.
+     *
+     * @throws org.apache.polygene.bootstrap.AssemblyException The default implementation of this method will simply re-throw the exception.
+     */
+    protected void assemblyException( AssemblyException exception )
+        throws AssemblyException
+    {
+        throw exception;
+    }
+
+    protected void initApplication( Application app )
+        throws Exception
+    {
+    }
+
+    @After
+    public void tearDown()
+        throws Exception
+    {
+        if( application != null )
+        {
+            application.passivate();
+        }
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/AbstractPolygeneScenarioTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/AbstractPolygeneScenarioTest.java
new file mode 100644
index 0000000..4f85962
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/AbstractPolygeneScenarioTest.java
@@ -0,0 +1,142 @@
+/*
+ *  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.polygene.test;
+
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+/**
+ * Base class for Polygene scenario tests. This will create one Polygene application per class instead of per test.
+ */
+public abstract class AbstractPolygeneScenarioTest
+    implements Assembler
+{
+    static protected PolygeneAPI api;
+    static protected PolygeneSPI spi;
+
+    static protected Energy4Java polygene;
+    static protected ApplicationDescriptor applicationModel;
+    static protected Application application;
+
+    static protected Module module;
+
+    static protected Assembler assembler; // Initialize this in static block of subclass
+    private static UnitOfWorkFactory uowf;
+
+    @BeforeClass
+    public static void setUp()
+        throws Exception
+    {
+        polygene = new Energy4Java();
+        applicationModel = newApplication();
+        if( applicationModel == null )
+        {
+            // An AssemblyException has occurred that the Test wants to check for.
+            return;
+        }
+        application = applicationModel.newInstance( polygene.spi() );
+        initApplication( application );
+        api = spi = polygene.spi();
+        application.activate();
+
+        // Assume only one module
+        module = application.findModule( "Layer 1", "Module 1" );
+        uowf = module.unitOfWorkFactory();
+    }
+
+    static protected ApplicationDescriptor newApplication()
+        throws AssemblyException
+    {
+        final Assembler asm = assembler;
+
+        ApplicationAssembler assembler = applicationFactory -> applicationFactory.newApplicationAssembly( asm );
+        try
+        {
+            return polygene.newApplicationModel( assembler );
+        }
+        catch( AssemblyException e )
+        {
+            assemblyException( e );
+            return null;
+        }
+    }
+
+    /**
+     * This method is called when there was an AssemblyException in the creation of the Polygene application model.
+     * <p>
+     * Override this method to catch valid failures to place into satisfiedBy suites.
+     * </p>
+     *
+     * @param exception the exception thrown.
+     *
+     * @throws org.apache.polygene.bootstrap.AssemblyException The default implementation of this method will simply re-throw the exception.
+     */
+    static protected void assemblyException( AssemblyException exception )
+        throws AssemblyException
+    {
+        throw exception;
+    }
+
+    static protected void initApplication( Application app )
+        throws Exception
+    {
+    }
+
+    @AfterClass
+    public void tearDown()
+        throws Exception
+    {
+        if( uowf != null && uowf.isUnitOfWorkActive() )
+        {
+            while( uowf.isUnitOfWorkActive() )
+            {
+                UnitOfWork uow = uowf.currentUnitOfWork();
+                if( uow.isOpen() )
+                {
+                    uow.discard();
+                }
+                else
+                {
+                    throw new InternalError( "I have seen a case where a UoW is on the stack, but not opened. First is" + uow
+                        .usecase()
+                        .name() );
+                }
+            }
+            new Exception( "UnitOfWork not properly cleaned up" ).printStackTrace();
+        }
+
+        if( application != null )
+        {
+            application.passivate();
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/AbstractPolygeneTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/AbstractPolygeneTest.java
new file mode 100644
index 0000000..db3c8d8
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/AbstractPolygeneTest.java
@@ -0,0 +1,120 @@
+/*
+ *  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.polygene.test;
+
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.junit.After;
+import org.junit.Before;
+
+/**
+ * Base class for Composite tests.
+ */
+public abstract class AbstractPolygeneTest extends AbstractPolygeneBaseTest
+    implements Assembler
+{
+    @Structure
+    protected UnitOfWorkFactory unitOfWorkFactory;
+
+    @Structure
+    protected TransientBuilderFactory transientBuilderFactory;
+
+    @Structure
+    protected ValueBuilderFactory valueBuilderFactory;
+
+    @Structure
+    protected ServiceFinder serviceFinder;
+
+    @Structure
+    protected ObjectFactory objectFactory;
+
+    @Structure
+    protected QueryBuilderFactory queryBuilderFactory;
+
+    @Structure
+    protected ModuleDescriptor module;
+
+    @Before
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        if( application == null )
+        {
+            return; // failure in Assembly.
+        }
+        Module module = application.findModule( "Layer 1", "Module 1" );
+        module.injectTo( this );
+    }
+
+    @Override
+    protected void defineApplication( ApplicationAssembly applicationAssembly )
+        throws AssemblyException
+    {
+        LayerAssembly layer = applicationAssembly.layer( "Layer 1" );
+        ModuleAssembly module = layer.module( "Module 1" );
+        new DefaultUnitOfWorkAssembler().assemble( module );
+        module.objects( AbstractPolygeneTest.this.getClass() );
+        assemble( module );
+    }
+
+    @After
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        if( unitOfWorkFactory != null && unitOfWorkFactory.isUnitOfWorkActive() )
+        {
+            while( unitOfWorkFactory.isUnitOfWorkActive() )
+            {
+                UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+                if( uow.isOpen() )
+                {
+                    System.err.println( "UnitOfWork not cleaned up:" + uow.usecase().name() );
+                    uow.discard();
+                }
+                else
+                {
+                    throw new InternalError( "I have seen a case where a UoW is on the stack, but not opened. First is: " + uow
+                        .usecase()
+                        .name() );
+                }
+            }
+            new Exception( "UnitOfWork not properly cleaned up" ).printStackTrace();
+        }
+        super.tearDown();
+    }
+}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/EntityTestAssembler.java b/core/testsupport/src/main/java/org/apache/polygene/test/EntityTestAssembler.java
new file mode 100644
index 0000000..ec7237b
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/EntityTestAssembler.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.test;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+
+/**
+ * Helper assembler that adds an in-memory EntityStore to the module
+ */
+public class EntityTestAssembler
+    extends Assemblers.VisibilityIdentity<EntityTestAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( MemoryEntityStoreService.class ).visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/cache/AbstractCachePoolTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/cache/AbstractCachePoolTest.java
new file mode 100644
index 0000000..937c03a
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/cache/AbstractCachePoolTest.java
@@ -0,0 +1,129 @@
+/*
+ *  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.polygene.test.cache;
+
+import java.util.Collection;
+import java.util.Random;
+import org.apache.polygene.api.constraint.ConstraintViolation;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.spi.cache.Cache;
+import org.apache.polygene.spi.cache.CachePool;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+/**
+ * Abstract satisfiedBy with tests for the CachePool interface.
+ */
+public abstract class AbstractCachePoolTest
+    extends AbstractPolygeneTest
+{
+    protected CachePool cachePool;
+    protected Cache<String> cache;
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        cachePool = module.instance().findService( CachePool.class ).get();
+        cache = cachePool.fetchCache( "1", String.class );
+    }
+
+    @Test
+    public void givenInvalidCacheNameWhenFetchingCacheExpectIllegalArgumentException()
+    {
+        try
+        {
+            cache = cachePool.fetchCache( "", String.class );
+            fail( "Expected " + IllegalArgumentException.class.getSimpleName() );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // expected
+        }
+    }
+
+    @Test
+    public void givenNullKeyWhenFetchingCacheExpectConstraintViolationException()
+    {
+        try
+        {
+            cache = cachePool.fetchCache( null, String.class );
+            fail( "Expected " + ConstraintViolationException.class.getSimpleName() );
+        }
+        catch( ConstraintViolationException e )
+        {
+            // expected
+            Collection<ConstraintViolation> violations = e.constraintViolations();
+            assertEquals( 1, violations.size() );
+            ConstraintViolation violation = violations.iterator().next();
+            assertEquals( "not optional", violation.constraint().toString() );
+            assertEquals( "param1", violation.name() );
+        }
+    }
+
+    @Test
+    public void givenLoooongCacheNameWhenFetchingCacheExpectOk()
+    {
+        Random random = new Random();
+        StringBuilder longName = new StringBuilder();
+        for( int i = 0; i < 10000; i++ )
+        {
+            longName.append( (char) ( random.nextInt( 26 ) + 65 ) );
+        }
+        cache = cachePool.fetchCache( longName.toString(), String.class );
+    }
+
+    @Test
+    public void givenEmptyCacheWhenFetchingValueExpectNull()
+    {
+        assertNull( cache.get( "1" ) );
+    }
+
+    @Test
+    public void givenCacheWithAValueWhenRequestingThatValueExpectItBack()
+    {
+        cache.put( "Habba", "Zout" );
+        assertEquals( "Zout", cache.get( "Habba" ) );
+    }
+
+    @Test
+    public void givenCacheWithAValueWhenReplacingValueExpectNewValue()
+    {
+        cache.put( "Habba", "Zout" );
+        assertEquals( "Zout", cache.get( "Habba" ) );
+        cache.put( "Habba", "Zout2" );
+        assertEquals( "Zout2", cache.get( "Habba" ) );
+    }
+
+    @Test
+    public void givenCacheWithValueWhenDroppingReferenceAndRequestNewCacheAndItsValueExpectItToBeGone()
+    {
+        cache.put( "Habba", "Zout" );
+        assertEquals( "Zout", cache.get( "Habba" ) );
+        cachePool.returnCache( cache );
+        cache = cachePool.fetchCache( "1", String.class );
+        assertNull( "Value not missing", cache.get( "Habba" ) );
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/cache/AbstractEntityStoreWithCacheTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/cache/AbstractEntityStoreWithCacheTest.java
new file mode 100644
index 0000000..a2f6d29
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/cache/AbstractEntityStoreWithCacheTest.java
@@ -0,0 +1,168 @@
+/*
+ *  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.polygene.test.cache;
+
+import org.junit.Test;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Assert Cache behaviour when used by an EntityStore.
+ * <p>
+ * Use an in-memory CachePool by default, implement the <code>assembleCachePool</code> method to override.
+ */
+public abstract class AbstractEntityStoreWithCacheTest
+    extends AbstractEntityStoreTest
+{
+    @Optional @Service MemoryCachePoolService cachePool;
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+        assembleCachePool( module );
+    }
+
+    protected void assembleCachePool( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( MemoryCachePoolService.class );
+    }
+
+    @Test
+    public void whenNewEntityThenCanFindEntityAndCorrectValues()
+        throws Exception
+    {
+        super.whenNewEntityThenCanFindEntityAndCorrectValues();
+        if( cachePool != null )
+        {
+            MemoryCacheImpl<?> cache = cachePool.singleCache();
+            assertThat( cache.size(), is( 1 ) );
+            assertThat( cache.gets(), is( 1 ) );
+            assertThat( cache.puts(), is( 1 ) );
+            assertThat( cache.removes(), is( 0 ) );
+            assertThat( cache.exists(), is( 0 ) );
+        }
+    }
+
+    @Test
+    public void whenRemovedEntityThenCannotFindEntity()
+        throws Exception
+    {
+        super.whenRemovedEntityThenCannotFindEntity();
+        if( cachePool != null )
+        {
+            MemoryCacheImpl<?> cache = cachePool.singleCache();
+            assertThat( cache.size(), is( 0 ) );
+            assertThat( cache.gets(), is( 2 ) );
+            assertThat( cache.puts(), is( 1 ) );
+            assertThat( cache.removes(), is( 1 ) );
+            assertThat( cache.exists(), is( 0 ) );
+        }
+    }
+
+    @Test
+    public void givenEntityIsNotModifiedWhenUnitOfWorkCompletesThenDontStoreState()
+        throws UnitOfWorkCompletionException
+    {
+        super.givenEntityIsNotModifiedWhenUnitOfWorkCompletesThenDontStoreState();
+        if( cachePool != null )
+        {
+            MemoryCacheImpl<?> cache = cachePool.singleCache();
+            assertThat( cache.size(), is( 1 ) );
+            assertThat( cache.gets(), is( 2 ) );
+            assertThat( cache.puts(), is( 1 ) );
+            assertThat( cache.removes(), is( 0 ) );
+            assertThat( cache.exists(), is( 0 ) );
+        }
+    }
+
+    @Test
+    public void givenPropertyIsModifiedWhenUnitOfWorkCompletesThenStoreState()
+        throws UnitOfWorkCompletionException
+    {
+        super.givenPropertyIsModifiedWhenUnitOfWorkCompletesThenStoreState();
+        if( cachePool != null )
+        {
+            MemoryCacheImpl<?> cache = cachePool.singleCache();
+            assertThat( cache.size(), is( 1 ) );
+            assertThat( cache.gets(), is( 2 ) );
+            assertThat( cache.puts(), is( 2 ) );
+            assertThat( cache.removes(), is( 0 ) );
+            assertThat( cache.exists(), is( 0 ) );
+        }
+    }
+
+    @Test
+    public void givenManyAssociationIsModifiedWhenUnitOfWorkCompletesThenStoreState()
+        throws UnitOfWorkCompletionException
+    {
+        super.givenManyAssociationIsModifiedWhenUnitOfWorkCompletesThenStoreState();
+        if( cachePool != null )
+        {
+            MemoryCacheImpl<?> cache = cachePool.singleCache();
+            assertThat( cache.size(), is( 1 ) );
+            assertThat( cache.gets(), is( 2 ) );
+            assertThat( cache.puts(), is( 2 ) );
+            assertThat( cache.removes(), is( 0 ) );
+            assertThat( cache.exists(), is( 0 ) );
+        }
+    }
+
+    @Test
+    public void givenConcurrentUnitOfWorksWhenUoWCompletesThenCheckConcurrentModification()
+        throws UnitOfWorkCompletionException
+    {
+        super.givenConcurrentUnitOfWorksWhenUoWCompletesThenCheckConcurrentModification();
+        if( cachePool != null )
+        {
+            MemoryCacheImpl<?> cache = cachePool.singleCache();
+            assertThat( cache.size(), is( 1 ) );
+            assertThat( cache.gets(), is( 4 ) );
+            assertThat( cache.puts(), is( 2 ) );
+            assertThat( cache.removes(), is( 0 ) );
+            assertThat( cache.exists(), is( 0 ) );
+        }
+    }
+
+    @Test
+    public void givenEntityStoredLoadedChangedWhenUnitOfWorkDiscardsThenDontStoreState()
+        throws UnitOfWorkCompletionException
+    {
+        super.givenEntityStoredLoadedChangedWhenUnitOfWorkDiscardsThenDontStoreState();
+        if( cachePool != null )
+        {
+            MemoryCacheImpl<?> cache = cachePool.singleCache();
+            assertThat( cache.size(), is( 1 ) );
+            assertThat( cache.gets(), is( 2 ) );
+            assertThat( cache.puts(), is( 1 ) );
+            assertThat( cache.removes(), is( 0 ) );
+            assertThat( cache.exists(), is( 0 ) );
+        }
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/cache/MemoryCacheImpl.java b/core/testsupport/src/main/java/org/apache/polygene/test/cache/MemoryCacheImpl.java
new file mode 100644
index 0000000..5382739
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/cache/MemoryCacheImpl.java
@@ -0,0 +1,145 @@
+/*
+ *  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.polygene.test.cache;
+
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.polygene.spi.cache.Cache;
+
+/**
+ * In-Memory Cache implementation based on ConcurrentHashMap.
+ */
+public class MemoryCacheImpl<T>
+    implements Cache<T>
+{
+    private int refCount;
+
+    private final ConcurrentHashMap<String, Object> backingCache;
+    private final Class<T> valueType;
+    private final String id;
+
+    private int gets;
+    private int removes;
+    private int puts;
+    private int exists;
+
+    public MemoryCacheImpl( String cacheId, ConcurrentHashMap<String, Object> cache, Class<T> valueType )
+    {
+        this.id = cacheId;
+        this.backingCache = cache;
+        this.valueType = valueType;
+    }
+
+    @Override
+    public T get( String key )
+    {
+        try
+        {
+            return valueType.cast( backingCache.get( key ) );
+        }
+        finally
+        {
+            gets++;
+        }
+    }
+
+    @Override
+    public T remove( String key )
+    {
+        try
+        {
+            return valueType.cast( backingCache.remove( key ) );
+        }
+        finally
+        {
+            removes++;
+        }
+    }
+
+    @Override
+    public void put( String key, T value )
+    {
+        try
+        {
+            backingCache.put( key, value );
+        }
+        finally
+        {
+            puts++;
+        }
+    }
+
+    @Override
+    public boolean exists( String key )
+    {
+        try
+        {
+            return backingCache.containsKey( key );
+        }
+        finally
+        {
+            exists++;
+        }
+    }
+
+    synchronized void decRefCount()
+    {
+        refCount--;
+    }
+
+    synchronized void incRefCount()
+    {
+        refCount++;
+    }
+
+    synchronized boolean isNotUsed()
+    {
+        return refCount == 0;
+    }
+
+    public String cacheId()
+    {
+        return id;
+    }
+
+    public int size()
+    {
+        return backingCache.size();
+    }
+
+    public int gets()
+    {
+        return gets;
+    }
+
+    public int removes()
+    {
+        return removes;
+    }
+
+    public int puts()
+    {
+        return puts;
+    }
+
+    public int exists()
+    {
+        return exists;
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/cache/MemoryCachePoolMixin.java b/core/testsupport/src/main/java/org/apache/polygene/test/cache/MemoryCachePoolMixin.java
new file mode 100644
index 0000000..b682bf9
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/cache/MemoryCachePoolMixin.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.test.cache;
+
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.polygene.spi.cache.Cache;
+
+import static org.apache.polygene.api.util.Collectors.single;
+
+/**
+ * In-Memory CachePool Mixin based on ConcurrentHashMap.
+ */
+public abstract class MemoryCachePoolMixin
+    implements MemoryCachePoolService
+{
+    private final ConcurrentHashMap<String, MemoryCacheImpl<?>> caches = new ConcurrentHashMap<>();
+
+    @Override
+    public <T> Cache<T> fetchCache( String cacheId, Class<T> valueType )
+    {
+        Objects.requireNonNull( cacheId, "cacheId" );
+        if( cacheId.isEmpty() )
+        {
+            throw new IllegalArgumentException( "cacheId was empty string" );
+        }
+        @SuppressWarnings( "unchecked" )
+        MemoryCacheImpl<T> cache = (MemoryCacheImpl<T>) caches.computeIfAbsent( cacheId, k -> createNewCache( cacheId, valueType ) );
+        cache.incRefCount();
+        return cache;
+    }
+
+    private <T> MemoryCacheImpl<T> createNewCache( String cacheId, Class<T> valueType )
+    {
+        return new MemoryCacheImpl<>( cacheId, new ConcurrentHashMap<>(), valueType );
+    }
+
+    @Override
+    public void returnCache( Cache<?> cache )
+    {
+        MemoryCacheImpl<?> memory = (MemoryCacheImpl<?>) cache;
+        memory.decRefCount();
+        if( memory.isNotUsed() )
+        {
+            caches.remove( memory.cacheId() );
+        }
+    }
+
+    @Override
+    public void activateService()
+        throws Exception
+    {
+        caches.clear();
+    }
+
+    @Override
+    public void passivateService()
+        throws Exception
+    {
+        caches.clear();
+    }
+
+    @Override
+    public MemoryCacheImpl<?> singleCache()
+    {
+        return caches.values().stream().collect( single() );
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/cache/MemoryCachePoolService.java b/core/testsupport/src/main/java/org/apache/polygene/test/cache/MemoryCachePoolService.java
new file mode 100644
index 0000000..3c5119b
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/cache/MemoryCachePoolService.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.test.cache;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.spi.cache.CachePool;
+
+/**
+ * In-Memory CachePool Service.
+ */
+@Mixins( MemoryCachePoolMixin.class )
+public interface MemoryCachePoolService
+    extends CachePool, ServiceActivation
+{
+    /**
+     * Get the single Cache of this CachePool.
+     *
+     * @return The single Cache of this CachePool
+     * @throws IllegalArgumentException if no or more than one Cache is present in the CachePool
+     */
+    MemoryCacheImpl<?> singleCache();
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/cache/package.html b/core/testsupport/src/main/java/org/apache/polygene/test/cache/package.html
new file mode 100644
index 0000000..9091fe7
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/cache/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Cache SPI Test Support.</h2>
+    </body>
+</html>
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/entity/AbstractConfigurationDeserializationTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/entity/AbstractConfigurationDeserializationTest.java
new file mode 100644
index 0000000..f8877c0
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/entity/AbstractConfigurationDeserializationTest.java
@@ -0,0 +1,116 @@
+/*
+ *  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.polygene.test.entity;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+
+public abstract class AbstractConfigurationDeserializationTest extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ModuleAssembly storageModule = module.layer().module( "storage" );
+        module.configurations( ConfigSerializationConfig.class );
+        module.values( Host.class );
+        module.services( MyService.class ).identifiedBy( "configtest" );
+        storageModule.services( MemoryEntityStoreService.class ).visibleIn( Visibility.layer );
+    }
+
+    @Test
+    public void givenServiceWhenInitializingExpectCorrectDeserialization()
+    {
+        ServiceReference<MyService> ref = module.instance().findService( MyService.class );
+        assertThat( ref, notNullValue() );
+        assertThat( ref.isAvailable(), equalTo( true ) );
+        MyService myService = ref.get();
+        assertThat( myService, notNullValue() );
+        assertThat( myService.name(), equalTo( "main" ) );
+        assertThat( myService.hostIp(), equalTo( "12.23.34.45" ) );
+        assertThat( myService.hostPort(), equalTo( 1234 ) );
+    }
+
+    @Mixins( MyServiceMixin.class )
+    public interface MyService
+    {
+
+        String hostIp();
+
+        Integer hostPort();
+
+        String name();
+    }
+
+    public static class MyServiceMixin
+        implements MyService
+    {
+
+        @This
+        private Configuration<ConfigSerializationConfig> config;
+
+        @Override
+        public String hostIp()
+        {
+            return config.get().host().get().ip().get();
+        }
+
+        @Override
+        public Integer hostPort()
+        {
+            return config.get().host().get().port().get();
+        }
+
+        @Override
+        public String name()
+        {
+            return config.get().name().get();
+        }
+    }
+
+    public interface ConfigSerializationConfig extends HasIdentity
+    {
+        Property<String> name();
+
+        Property<Host> host();
+    }
+
+    public interface Host
+    {
+        Property<String> ip();
+
+        Property<Integer> port();
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/entity/AbstractEntityStoreTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/entity/AbstractEntityStoreTest.java
new file mode 100644
index 0000000..2fec7df
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/entity/AbstractEntityStoreTest.java
@@ -0,0 +1,654 @@
+/*
+ *  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.polygene.test.entity;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.Period;
+import java.time.ZonedDateTime;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.After;
+import org.junit.Test;
+
+import static java.time.ZoneOffset.UTC;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+/**
+ * Abstract satisfiedBy with tests for the EntityStore interface.
+ */
+public abstract class AbstractEntityStoreTest
+    extends AbstractPolygeneTest
+{
+
+    @Service
+    private EntityStore store;
+
+    @Structure
+    private Module moduleInstance;
+    private ZonedDateTime refDate = ZonedDateTime.of( 2020, 3, 4, 13, 24, 35, 0, UTC );
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( TestEntity.class );
+        module.values( TestValue.class, TestValue2.class, TjabbaValue.class );
+        module.objects( getClass() );
+    }
+
+    @Override
+    @After
+    public void tearDown()
+        throws Exception
+    {
+        super.tearDown();
+    }
+
+    protected TestEntity createEntity( UnitOfWork unitOfWork )
+        throws UnitOfWorkCompletionException
+    {
+        // Create entity
+        EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class );
+        builder.instance().instantValue().set( Instant.now() );
+        TestEntity instance = builder.newInstance();
+
+        instance.name().set( "Test" );
+        instance.intValue().set( 42 );
+        instance.longValue().set( 42L );
+        instance.doubleValue().set( 42D );
+        instance.floatValue().set( 42F );
+        instance.booleanValue().set( Boolean.TRUE );
+        instance.bigIntegerValue().set( new BigInteger( "42" ) );
+        instance.bigDecimalValue().set( new BigDecimal( "42" ) );
+        instance.instantValue().set( refDate.toInstant() );
+        instance.dateTimeValue().set( refDate );
+        instance.localDateTimeValue().set( LocalDateTime.of( 2020, 3, 4, 13, 23, 0 ) );
+        instance.localDateValue().set( LocalDate.of( 2020, 3, 4 ) );
+        instance.localTimeValue().set( LocalTime.of( 19, 20, 21 ) );
+
+        instance.duractionValue().set( Duration.between( LocalDateTime.of( 2010, 1, 2, 19, 20, 21 ),
+                                                         LocalDateTime.of( 2010, 1, 2, 20, 21, 22 ) ) );
+        instance.periodValue().set( Period.between( LocalDate.of( 2005, 12, 21 ), LocalDate.of( 2007, 1, 23 ) ) );
+
+        instance.association().set( instance );
+
+        ValueBuilder<Tjabba> valueBuilder4 = moduleInstance.newValueBuilder( Tjabba.class );
+        final Tjabba prototype4 = valueBuilder4.prototype();
+        prototype4.bling().set( "BlinkLjus" );
+
+        // Set value
+        ValueBuilder<TestValue2> valueBuilder2 = moduleInstance.newValueBuilder( TestValue2.class );
+        TestValue2 prototype2 = valueBuilder2.prototype();
+        prototype2.stringValue().set( "Bar" );
+        Tjabba newValue = valueBuilder4.newInstance();
+        prototype2.anotherValue().set( newValue );
+        prototype2.anotherValue().set( newValue );
+
+        ValueBuilder<Tjabba> valueBuilder3 = moduleInstance.newValueBuilder( Tjabba.class );
+        final Tjabba prototype3 = valueBuilder3.prototype();
+        prototype3.bling().set( "Brakfis" );
+
+        ValueBuilder<TestValue> valueBuilder1 = moduleInstance.newValueBuilder( TestValue.class );
+        TestValue prototype = valueBuilder1.prototype();
+        prototype.enumProperty().set( TestEnum.VALUE3 );
+        prototype.listProperty().get().add( "Foo" );
+
+        prototype.valueProperty().set( valueBuilder2.newInstance() );
+        prototype.tjabbaProperty().set( valueBuilder3.newInstance() );
+        Map<String, String> mapValue = new HashMap<>( 1 );
+        mapValue.put( "foo", "bar" );
+        prototype.mapStringStringProperty().set( mapValue );
+        instance.valueProperty().set( valueBuilder1.newInstance() );
+
+        instance.manyAssociation().add( 0, instance );
+
+        instance.namedAssociation().put( "foo", instance );
+        instance.namedAssociation().put( "bar", instance );
+
+        return instance;
+    }
+
+    @Test
+    public void whenNewEntityThenCanFindEntityAndCorrectValues()
+        throws Exception
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            TestEntity instance = createEntity( unitOfWork );
+            unitOfWork.complete();
+
+            // Find entity
+            unitOfWork = unitOfWorkFactory.newUnitOfWork();
+            instance = unitOfWork.get( instance );
+
+            // Check state
+            assertThat( "property 'intValue' has correct value",
+                        instance.intValue().get(),
+                        equalTo( 42 ) );
+
+            assertThat( "property 'longValue' has correct value",
+                        instance.longValue().get(),
+                        equalTo( 42L ) );
+
+            assertThat( "property 'doubleValue' has correct value",
+                        instance.doubleValue().get(),
+                        equalTo( 42D ) );
+
+            assertThat( "property 'floatValue' has correct value",
+                        instance.floatValue().get(),
+                        equalTo( 42F ) );
+
+            assertThat( "property 'booleanValue' has correct value",
+                        instance.booleanValue().get(),
+                        equalTo( Boolean.TRUE ) );
+
+            assertThat( "property 'bigInteger' has correct value",
+                        instance.bigIntegerValue().get(),
+                        equalTo( new BigInteger( "42" ) ) );
+
+            assertThat( "property 'bigDecimal' has correct value",
+                        instance.bigDecimalValue().get(),
+                        equalTo( new BigDecimal( "42" ) ) );
+
+            assertThat( "property 'instantValue' has correct value",
+                        instance.instantValue().get(),
+                        equalTo( refDate.toInstant() ) );
+
+            assertThat( "property 'dateTimeValue' has correct value",
+                        instance.dateTimeValue().get(),
+                        equalTo( refDate ) );
+
+            assertThat( "property 'localDateTimeValue' has correct value",
+                        instance.localDateTimeValue().get(),
+                        equalTo( LocalDateTime.of( 2020, 3, 4, 13, 23, 0 ) ) );
+
+            assertThat( "property 'localDateValue' has correct value",
+                        instance.localDateValue().get(),
+                        equalTo( LocalDate.of( 2020, 3, 4 ) ) );
+
+            assertThat( "property 'localTimeValue' has correct value",
+                        instance.localTimeValue().get(),
+                        equalTo( LocalTime.of( 19, 20, 21 ) ) );
+
+            assertThat( "property 'periodValue' has correct value",
+                        instance.periodValue().get(),
+                        equalTo( Period.of( 1, 1, 2 ) ) );
+
+            assertThat( "property 'durationValue' has correct value",
+                        instance.duractionValue().get(),
+                        equalTo( Duration.ofSeconds( 3661 ) ) );
+
+            assertThat( "property 'name' has correct value",
+                        instance.name().get(),
+                        equalTo( "Test" ) );
+
+            assertThat( "property 'unsetName' has correct value",
+                        instance.unsetName().get(),
+                        equalTo( null ) );
+
+            assertThat( "property 'emptyName' has correct value",
+                        instance.emptyName().get(),
+                        equalTo( "" ) );
+
+            assertThat( "property 'valueProperty.stringValue' has correct value",
+                        instance.valueProperty().get().valueProperty().get().stringValue().get(),
+                        equalTo( "Bar" ) );
+
+            assertThat( "property 'valueProperty.listProperty' has correct value",
+                        instance.valueProperty().get().listProperty().get().get( 0 ),
+                        equalTo( "Foo" ) );
+
+            assertThat( "property 'valueProperty.enumProperty' has correct value",
+                        instance.valueProperty().get().enumProperty().get(),
+                        equalTo( TestEnum.VALUE3 ) );
+
+            assertThat( "property 'valueProperty.anotherValue.bling' has correct value",
+                        instance.valueProperty().get().valueProperty().get().anotherValue().get().bling().get(),
+                        equalTo( "BlinkLjus" ) );
+
+            assertThat( "property 'valueProperty.tjabbaProperty.bling' has correct value",
+                        instance.valueProperty().get().tjabbaProperty().get().bling().get(),
+                        equalTo( "Brakfis" ) );
+
+            Map<String, String> mapValue = new HashMap<>();
+            mapValue.put( "foo", "bar" );
+            assertThat( "property 'valueProperty.mapStringStringProperty' has correct value",
+                        instance.valueProperty().get().mapStringStringProperty().get(),
+                        equalTo( mapValue ) );
+
+            assertThat( "association has correct value",
+                        instance.association().get(),
+                        equalTo( instance ) );
+
+            assertThat( "manyAssociation has correct value",
+                        instance.manyAssociation().iterator().next(),
+                        equalTo( instance ) );
+
+            assertThat( "namedAssociation has correct 'foo' value",
+                        instance.namedAssociation().get( "foo" ),
+                        equalTo( instance ) );
+
+            assertThat( "namedAssociation has correct 'bar' value",
+                        instance.namedAssociation().get( "bar" ),
+                        equalTo( instance ) );
+
+            unitOfWork.discard();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    @Test
+    public void whenRemovedEntityThenCannotFindEntity()
+        throws Exception
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        TestEntity newInstance = createEntity( unitOfWork );
+        Identity identity = newInstance.identity().get();
+        unitOfWork.complete();
+
+        // Remove entity
+        unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        TestEntity instance = unitOfWork.get( newInstance );
+        unitOfWork.remove( instance );
+        unitOfWork.complete();
+
+        // Find entity
+        unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            unitOfWork.get( TestEntity.class, identity );
+            fail( "Should not be able to find entity" );
+        }
+        catch( NoSuchEntityException e )
+        {
+            // Ok!
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    @Test
+    public void givenEntityIsNotModifiedWhenUnitOfWorkCompletesThenDontStoreState()
+        throws UnitOfWorkCompletionException
+    {
+        TestEntity testEntity;
+        String version;
+        {
+            UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class );
+
+            testEntity = builder.newInstance();
+            unitOfWork.complete();
+        }
+        {
+            UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+            testEntity = unitOfWork.get( testEntity );
+            version = spi.entityStateOf( testEntity ).version();
+
+            unitOfWork.complete();
+        }
+        {
+            UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+            testEntity = unitOfWork.get( testEntity );
+            String newVersion = spi.entityStateOf( testEntity ).version();
+            assertThat( "version has not changed", newVersion, equalTo( version ) );
+
+            unitOfWork.complete();
+        }
+    }
+
+    @Test
+    public void givenPropertyIsModifiedWhenUnitOfWorkCompletesThenStoreState()
+        throws UnitOfWorkCompletionException
+    {
+        TestEntity testEntity;
+        String version;
+        {
+            UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class );
+
+            testEntity = builder.newInstance();
+            unitOfWork.complete();
+        }
+        {
+            UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+            testEntity = unitOfWork.get( testEntity );
+            testEntity.name().set( "Rickard" );
+            version = spi.entityStateOf( testEntity ).version();
+
+            unitOfWork.complete();
+        }
+        {
+            UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+            testEntity = unitOfWork.get( testEntity );
+            String newVersion = spi.entityStateOf( testEntity ).version();
+            assertThat( "version has not changed", newVersion, not( equalTo( version ) ) );
+
+            unitOfWork.complete();
+        }
+    }
+
+    @Test
+    public void givenManyAssociationIsModifiedWhenUnitOfWorkCompletesThenStoreState()
+        throws UnitOfWorkCompletionException
+    {
+        TestEntity testEntity;
+        String version;
+        {
+            UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class );
+
+            testEntity = builder.newInstance();
+            unitOfWork.complete();
+        }
+        {
+            UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+            testEntity = unitOfWork.get( testEntity );
+            testEntity.manyAssociation().add( 0, testEntity );
+            version = spi.entityStateOf( testEntity ).version();
+
+            unitOfWork.complete();
+        }
+        {
+            UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+            testEntity = unitOfWork.get( testEntity );
+            String newVersion = spi.entityStateOf( testEntity ).version();
+            assertThat( "version has not changed", newVersion, not( equalTo( version ) ) );
+
+            unitOfWork.complete();
+        }
+    }
+
+    @Test
+    public void givenConcurrentUnitOfWorksWhenUoWCompletesThenCheckConcurrentModification()
+        throws UnitOfWorkCompletionException
+    {
+        TestEntity testEntity;
+        {
+            UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class );
+
+            testEntity = builder.newInstance();
+            unitOfWork.complete();
+        }
+
+        UnitOfWork unitOfWork1;
+        TestEntity testEntity1;
+        String version;
+        {
+            // Start working with Entity in one UoW
+            unitOfWork1 = unitOfWorkFactory.newUnitOfWork();
+            testEntity1 = unitOfWork1.get( testEntity );
+            version = spi.entityStateOf( testEntity1 ).version();
+            if( version.isEmpty() )
+            {
+                unitOfWork1.discard();
+                return; // Store doesn't track versions - no point in testing it
+            }
+            testEntity1.name().set( "A" );
+            testEntity1.unsetName().set( "A" );
+        }
+        {
+            // Start working with same Entity in another UoW, and complete it
+            UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+            TestEntity testEntity2 = unitOfWork.get( testEntity );
+            assertThat( "version is correct", spi.entityStateOf( testEntity1 ).version(), equalTo( version ) );
+            testEntity2.name().set( "B" );
+            unitOfWork.complete();
+        }
+        {
+            // Try to complete first UnitOfWork
+            try
+            {
+                unitOfWork1.complete();
+                fail( "Should have thrown concurrent modification exception" );
+            }
+            catch( ConcurrentEntityModificationException e )
+            {
+                unitOfWork1.discard();
+            }
+        }
+        {
+            // Check values
+            unitOfWork1 = unitOfWorkFactory.newUnitOfWork();
+            testEntity1 = unitOfWork1.get( testEntity );
+            assertThat( "property name has not been set", testEntity1.name().get(), equalTo( "B" ) );
+            assertThat( "version is incorrect", spi.entityStateOf( testEntity1 ).version(),
+                        not( equalTo( version ) ) );
+            unitOfWork1.discard();
+        }
+    }
+
+    @Test
+    public void givenEntityStoredLoadedChangedWhenUnitOfWorkDiscardsThenDontStoreState()
+        throws UnitOfWorkCompletionException
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            Identity identity = createEntity( unitOfWork ).identity().get();
+            unitOfWork.complete();
+
+            unitOfWork = unitOfWorkFactory.newUnitOfWork();
+            TestEntity entity = unitOfWork.get( TestEntity.class, identity );
+            assertThat( entity.intValue().get(), is( 42 ) );
+            entity.intValue().set( 23 );
+            unitOfWork.discard();
+
+            unitOfWork = unitOfWorkFactory.newUnitOfWork();
+            entity = unitOfWork.get( TestEntity.class, identity );
+            assertThat( entity.intValue().get(), is( 42 ) );
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+
+    @Test
+    public void entityStatesSPI()
+    {
+        EntityStore entityStore = serviceFinder.findService( EntityStore.class ).get();
+
+        try( Stream<EntityState> states = entityStore.entityStates( module ) )
+        {
+            assertThat( states.count(), is( 0L ) );
+        }
+
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        TestEntity newInstance = createEntity( unitOfWork );
+        unitOfWork.complete();
+
+        try( Stream<EntityState> states = entityStore.entityStates( module ) )
+        {
+            assertThat( states.count(), is( 1L ) );
+        }
+
+        unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        TestEntity instance = unitOfWork.get( newInstance );
+        unitOfWork.remove( instance );
+        unitOfWork.complete();
+
+        try( Stream<EntityState> states = entityStore.entityStates( module ) )
+        {
+            assertThat( states.count(), is( 0L ) );
+        }
+    }
+
+    public interface TestEntity
+        extends EntityComposite
+    {
+
+        @UseDefaults
+        Property<Integer> intValue();
+
+        @UseDefaults
+        Property<Long> longValue();
+
+        @UseDefaults
+        Property<Double> doubleValue();
+
+        @UseDefaults
+        Property<Float> floatValue();
+
+        @UseDefaults
+        Property<Boolean> booleanValue();
+
+        @Optional
+        Property<BigInteger> bigIntegerValue();
+
+        @Optional
+        Property<BigDecimal> bigDecimalValue();
+
+        @Optional
+        Property<Instant> instantValue();
+
+        @Optional
+        Property<ZonedDateTime> dateTimeValue();
+
+        @Optional
+        Property<LocalDateTime> localDateTimeValue();
+
+        @Optional
+        Property<LocalDate> localDateValue();
+
+        @Optional
+        Property<LocalTime> localTimeValue();
+
+        @Optional
+        Property<Period> periodValue();
+
+        @Optional
+        Property<Duration> duractionValue();
+
+        @Optional
+        Property<String> name();
+
+        @Optional
+        Property<String> unsetName();
+
+        @UseDefaults
+        Property<String> emptyName();
+
+        @Optional
+        Property<TestValue> valueProperty();
+
+        @Optional
+        Association<TestEntity> association();
+
+        @Optional
+        Association<TestEntity> unsetAssociation();
+
+        ManyAssociation<TestEntity> manyAssociation();
+
+        NamedAssociation<TestEntity> namedAssociation();
+    }
+
+    public interface TjabbaValue
+        extends Tjabba, ValueComposite
+    {
+    }
+
+    public interface Tjabba
+    {
+
+        Property<String> bling();
+    }
+
+    public interface TestValue
+        extends ValueComposite
+    {
+
+        @UseDefaults
+        Property<String> stringProperty();
+
+        @UseDefaults
+        Property<Integer> intProperty();
+
+        @UseDefaults
+        Property<TestEnum> enumProperty();
+
+        @UseDefaults
+        Property<List<String>> listProperty();
+
+        @UseDefaults
+        Property<Map<String, Tjabba>> mapProperty();
+
+        Property<TestValue2> valueProperty();
+
+        Property<Tjabba> tjabbaProperty();
+
+        Property<Map<String, String>> mapStringStringProperty();
+    }
+
+    public interface TestValue2
+        extends ValueComposite
+    {
+        Property<String> stringValue();
+
+        Property<Tjabba> anotherValue();
+    }
+
+    public enum TestEnum
+    {
+        VALUE1, VALUE2, VALUE3
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/entity/CanRemoveAll.java b/core/testsupport/src/main/java/org/apache/polygene/test/entity/CanRemoveAll.java
new file mode 100644
index 0000000..d65c513
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/entity/CanRemoveAll.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.test.entity;
+
+public interface CanRemoveAll
+{
+    void removeAll();
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/entity/package.html b/core/testsupport/src/main/java/org/apache/polygene/test/entity/package.html
new file mode 100644
index 0000000..2f20bc5
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/entity/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>EntityStore SPI Test Support.</h2>
+    </body>
+</html>
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/indexing/AbstractAnyQueryTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/AbstractAnyQueryTest.java
new file mode 100644
index 0000000..b2872e9
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/AbstractAnyQueryTest.java
@@ -0,0 +1,102 @@
+/*
+ *  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.polygene.test.indexing;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.model.Account;
+import org.apache.polygene.test.model.Address;
+import org.apache.polygene.test.model.Cat;
+import org.apache.polygene.test.model.City;
+import org.apache.polygene.test.model.Domain;
+import org.apache.polygene.test.model.Female;
+import org.apache.polygene.test.model.File;
+import org.apache.polygene.test.model.Host;
+import org.apache.polygene.test.model.Male;
+import org.apache.polygene.test.model.Port;
+import org.apache.polygene.test.model.Protocol;
+import org.apache.polygene.test.model.QueryParam;
+import org.apache.polygene.test.model.URL;
+
+/**
+ * Abstract satisfiedBy with tests for any queries against Index/Query engines.
+ */
+public class AbstractAnyQueryTest
+    extends AbstractPolygeneTest
+{
+    protected UnitOfWork unitOfWork;
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        assembleEntities( module, Visibility.module );
+        assembleValues( module, Visibility.module );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    protected void assembleEntities( ModuleAssembly module, Visibility visibility )
+    {
+        module.entities( Male.class,
+                         Female.class,
+                         City.class,
+                         Domain.class,
+                         Account.class,
+                         Cat.class ). visibleIn( visibility );
+    }
+
+    protected void assembleValues( ModuleAssembly module, Visibility visibility )
+    {
+        module.values( URL.class,
+                       Address.class,
+                       Protocol.class,
+                       Host.class,
+                       Port.class,
+                       File.class,
+                       QueryParam.class ).visibleIn( visibility );
+    }
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        TestData.populate( module.instance() );
+
+        this.unitOfWork = this.module.instance().unitOfWorkFactory().newUnitOfWork();
+    }
+
+
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        if( this.unitOfWork != null )
+        {
+            this.unitOfWork.discard();
+            this.unitOfWork = null;
+        }
+        super.tearDown();
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/indexing/AbstractComplexQueryTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/AbstractComplexQueryTest.java
new file mode 100644
index 0000000..78eb77e
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/AbstractComplexQueryTest.java
@@ -0,0 +1,334 @@
+/*
+ *  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.polygene.test.indexing;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.structure.Module;
+import org.junit.Test;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.spi.query.IndexExporter;
+import org.apache.polygene.test.model.Address;
+import org.apache.polygene.test.model.Person;
+import org.apache.polygene.test.model.Protocol;
+import org.apache.polygene.test.model.QueryParam;
+import org.apache.polygene.test.model.URL;
+
+import static org.apache.polygene.api.query.QueryExpressions.contains;
+import static org.apache.polygene.api.query.QueryExpressions.containsAll;
+import static org.apache.polygene.api.query.QueryExpressions.eq;
+import static org.apache.polygene.api.query.QueryExpressions.not;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+import static org.apache.polygene.test.indexing.NameableAssert.verifyUnorderedResults;
+
+/**
+ * Abstract satisfiedBy with tests for complex queries against Index/Query engines, ie. queries by "example values".
+ */
+public abstract class AbstractComplexQueryTest
+    extends AbstractAnyQueryTest
+{
+
+    private static final String ANN = "Ann Doe";
+    private static final String JOE = "Joe Doe";
+    private static final String JACK = "Jack Doe";
+
+    @Structure
+    Module moduleInstance;
+
+
+    @Test
+    public void showNetwork()
+        throws IOException
+    {
+        IndexExporter indexerExporter = moduleInstance.findService( IndexExporter.class ).get();
+        indexerExporter.exportReadableToStream( System.out );
+    }
+
+    @Test
+    public void script01()
+    {
+        ValueBuilder<Address> addressBuilder = this.moduleInstance.newValueBuilder( Address.class );
+        Address address = addressBuilder.prototype();
+        address.line1().set( "Qi Street 4j" );
+        address.line2().set( "Off main Java Street" );
+        address.zipcode().set( "12345" );
+
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Property<Address> addressProp = templateFor( Person.class ).address();
+        qb = qb.where( eq( addressProp, addressBuilder.newInstance() ) );
+        Query<Person> query = unitOfWork.newQuery( qb );
+        System.out.println( "*** script01: " + query );
+
+        verifyUnorderedResults( query, ANN );
+    }
+
+    @Test
+    public void script02()
+    {
+        ValueBuilder<Address> addressBuilder = this.moduleInstance.newValueBuilder( Address.class );
+        Address address = addressBuilder.prototype();
+        address.line1().set( "Qi Street 4j" );
+        address.line2().set( "Off main Java Street" );
+        address.zipcode().set( "12345" );
+
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Property<Address> addressProp = templateFor( Person.class ).address();
+        qb = qb.where( not( eq( addressProp, addressBuilder.newInstance() ) ) );
+        Query<Person> query = unitOfWork.newQuery( qb );
+        System.out.println( "*** script02: " + query );
+
+        verifyUnorderedResults( query, JOE, JACK );
+    }
+
+    @Test
+    public void script03()
+    {
+        ValueBuilder<QueryParam> queryParamBuilder = this.moduleInstance.newValueBuilder( QueryParam.class );
+        List<QueryParam> queryParams = new ArrayList<>( 2 );
+        QueryParam param = queryParamBuilder.prototype();
+        param.name().set( "user" );
+        param.value().set( "jackdoe" );
+        queryParams.add( queryParamBuilder.newInstance() );
+
+        queryParamBuilder = this.moduleInstance.newValueBuilder( QueryParam.class );
+        param = queryParamBuilder.prototype();
+        param.name().set( "password" );
+        param.value().set( "somepassword" );
+        queryParams.add( queryParamBuilder.newInstance() );
+
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Property<Collection<QueryParam>> paramsProp = templateFor( Person.class ).personalWebsite().get().queryParams();
+        qb = qb.where( eq( paramsProp, queryParams ) );
+        Query<Person> query = unitOfWork.newQuery( qb );
+        System.out.println( "*** script03: " + query );
+
+        verifyUnorderedResults( query, JACK );
+    }
+
+    @Test
+    public void script04()
+    {
+        ValueBuilder<QueryParam> queryParamBuilder = this.moduleInstance.newValueBuilder( QueryParam.class );
+        List<QueryParam> queryParams = new ArrayList<>( 2 );
+        QueryParam param = queryParamBuilder.prototype();
+        // Different order
+        param.name().set( "password" );
+        param.value().set( "somepassword" );
+        queryParams.add( queryParamBuilder.newInstance() );
+
+        queryParamBuilder = this.moduleInstance.newValueBuilder( QueryParam.class );
+        param = queryParamBuilder.prototype();
+        param.name().set( "user" );
+        param.value().set( "jackdoe" );
+        queryParams.add( queryParamBuilder.newInstance() );
+
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Property<Collection<QueryParam>> paramsProp = templateFor( Person.class ).personalWebsite().get().queryParams();
+        qb = qb.where( eq( paramsProp, queryParams ) );
+        Query<Person> query = unitOfWork.newQuery( qb );
+        System.out.println( "*** script04: " + query );
+
+        verifyUnorderedResults( query );
+    }
+
+    @Test
+    public void script05()
+    {
+        ValueBuilder<QueryParam> queryParamBuilder = this.moduleInstance.newValueBuilder( QueryParam.class );
+        List<QueryParam> queryParams = new ArrayList<>( 2 );
+        QueryParam param = queryParamBuilder.prototype();
+        param.name().set( "user" );
+        param.value().set( "jackdoe" );
+        queryParams.add( queryParamBuilder.newInstance() );
+
+        queryParamBuilder = this.moduleInstance.newValueBuilder( QueryParam.class );
+        param = queryParamBuilder.prototype();
+        param.name().set( "password" );
+        param.value().set( "somepassword" );
+        queryParams.add( queryParamBuilder.newInstance() );
+
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Property<Collection<QueryParam>> paramsProp = templateFor( Person.class ).personalWebsite().get().queryParams();
+        qb = qb.where( not( eq( paramsProp, queryParams ) ) );
+        Query<Person> query = unitOfWork.newQuery( qb );
+        System.out.println( "*** script05: " + query );
+
+        verifyUnorderedResults( query, ANN, JOE );
+    }
+
+    @Test
+    public void script06()
+    {
+        ValueBuilder<URL> urlBuilder = this.moduleInstance.newValueBuilder( URL.class );
+        ValueBuilder<Protocol> protocolBuilder = this.moduleInstance.newValueBuilder( Protocol.class );
+        ValueBuilder<QueryParam> queryParamBuilder = this.moduleInstance.newValueBuilder( QueryParam.class );
+
+        Protocol protocol = protocolBuilder.prototype();
+        protocol.value().set( "http" );
+
+        List<QueryParam> queryParams = new ArrayList<>( 2 );
+        QueryParam param = queryParamBuilder.prototype();
+        param.name().set( "user" );
+        param.value().set( "jackdoe" );
+        queryParams.add( queryParamBuilder.newInstance() );
+
+        queryParamBuilder = this.moduleInstance.newValueBuilder( QueryParam.class );
+        param = queryParamBuilder.prototype();
+        param.name().set( "password" );
+        param.value().set( "somepassword" );
+        queryParams.add( queryParamBuilder.newInstance() );
+
+        URL url = urlBuilder.prototype();
+        url.protocol().set( protocolBuilder.newInstance() );
+        url.queryParams().set( queryParams );
+
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Property<URL> websiteProp = templateFor( Person.class ).personalWebsite();
+        qb = qb.where( eq( websiteProp, urlBuilder.newInstance() ) );
+        Query<Person> query = unitOfWork.newQuery( qb );
+        System.out.println( "*** script06: " + query );
+
+        verifyUnorderedResults( query, JACK );
+    }
+
+    @Test
+    public void script07()
+    {
+        ValueBuilder<URL> urlBuilder = this.moduleInstance.newValueBuilder( URL.class );
+        ValueBuilder<Protocol> protocolBuilder = this.moduleInstance.newValueBuilder( Protocol.class );
+        ValueBuilder<QueryParam> queryParamBuilder = this.moduleInstance.newValueBuilder( QueryParam.class );
+
+        Protocol protocol = protocolBuilder.prototype();
+        protocol.value().set( "http" );
+
+        List<QueryParam> queryParams = new ArrayList<>( 2 );
+        QueryParam param = queryParamBuilder.prototype();
+        param.name().set( "user" );
+        param.value().set( "jackdoe" );
+        queryParams.add( queryParamBuilder.newInstance() );
+
+        queryParamBuilder = this.moduleInstance.newValueBuilder( QueryParam.class );
+        param = queryParamBuilder.prototype();
+        param.name().set( "password" );
+        param.value().set( "somepassword" );
+        queryParams.add( queryParamBuilder.newInstance() );
+
+        URL url = urlBuilder.prototype();
+        url.protocol().set( protocolBuilder.newInstance() );
+        url.queryParams().set( queryParams );
+
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Property<URL> websiteProp = templateFor( Person.class ).personalWebsite();
+        qb = qb.where( not( eq( websiteProp, urlBuilder.newInstance() ) ) );
+        Query<Person> query = unitOfWork.newQuery( qb );
+        System.out.println( "*** script07: " + query );
+
+        verifyUnorderedResults( query, ANN, JOE );
+    }
+
+    @Test
+    public void script08()
+    {
+        ValueBuilder<QueryParam> queryParamBuilder = this.moduleInstance.newValueBuilder( QueryParam.class );
+        QueryParam param = queryParamBuilder.prototype();
+        param.name().set( "user" );
+        param.value().set( "jackdoe" );
+
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Property<Collection<QueryParam>> paramsProp = templateFor( Person.class ).personalWebsite().get().queryParams();
+        qb = qb.where( contains( paramsProp, queryParamBuilder.newInstance() ) );
+        Query<Person> query = unitOfWork.newQuery( qb );
+        System.out.println( "*** script08: " + query );
+        verifyUnorderedResults( query, JACK );
+    }
+
+    @Test
+    public void script09()
+    {
+        ValueBuilder<QueryParam> queryParamBuilder = this.moduleInstance.newValueBuilder( QueryParam.class );
+
+        QueryParam param = queryParamBuilder.prototype();
+        param.name().set( "user" );
+        param.value().set( "jackdoe" );
+
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Property<Collection<QueryParam>> paramsProp = templateFor( Person.class ).personalWebsite().get().queryParams();
+        qb = qb.where( not( contains( paramsProp, queryParamBuilder.newInstance() ) ) );
+        Query<Person> query = unitOfWork.newQuery( qb );
+        System.out.println( "*** script09: " + query );
+        verifyUnorderedResults( query, ANN, JOE );
+    }
+
+    @Test
+    public void script10()
+    {
+        ValueBuilder<QueryParam> queryParamBuilder = this.moduleInstance.newValueBuilder( QueryParam.class );
+
+        List<QueryParam> queryParams = new ArrayList<>( 2 );
+        QueryParam param = queryParamBuilder.prototype();
+        param.name().set( "user" );
+        param.value().set( "jackdoe" );
+        queryParams.add( queryParamBuilder.newInstance() );
+
+        queryParamBuilder = this.moduleInstance.newValueBuilder( QueryParam.class );
+        param = queryParamBuilder.prototype();
+        param.name().set( "password" );
+        param.value().set( "somepassword" );
+        queryParams.add( queryParamBuilder.newInstance() );
+
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Property<Collection<QueryParam>> paramsProp = templateFor( Person.class ).personalWebsite().get().queryParams();
+        qb = qb.where( containsAll( paramsProp, queryParams ) );
+        Query<Person> query = unitOfWork.newQuery( qb );
+        System.out.println( "*** script10: " + query );
+        verifyUnorderedResults( query, JACK );
+    }
+
+    @Test
+    public void script11()
+    {
+        ValueBuilder<QueryParam> queryParamBuilder = this.moduleInstance.newValueBuilder( QueryParam.class );
+
+        List<QueryParam> queryParams = new ArrayList<>( 2 );
+        QueryParam param = queryParamBuilder.prototype();
+        param.name().set( "user" );
+        param.value().set( "jackdoe" );
+        queryParams.add( queryParamBuilder.newInstance() );
+
+        queryParamBuilder = this.moduleInstance.newValueBuilder( QueryParam.class );
+        param = queryParamBuilder.prototype();
+        param.name().set( "password" );
+        param.value().set( "somepassword" );
+        queryParams.add( queryParamBuilder.newInstance() );
+
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Property<Collection<QueryParam>> paramsProp = templateFor( Person.class ).personalWebsite().get().queryParams();
+        qb = qb.where( not( containsAll( paramsProp, queryParams ) ) );
+        Query<Person> query = unitOfWork.newQuery( qb );
+        System.out.println( "*** script11: " + query );
+        verifyUnorderedResults( query, ANN, JOE );
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/indexing/AbstractEntityFinderTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/AbstractEntityFinderTest.java
new file mode 100644
index 0000000..9e0b845
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/AbstractEntityFinderTest.java
@@ -0,0 +1,447 @@
+/*
+ *  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.polygene.test.indexing;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.spi.query.EntityFinder;
+import org.apache.polygene.spi.query.IndexExporter;
+import org.apache.polygene.test.model.Domain;
+import org.apache.polygene.test.model.Female;
+import org.apache.polygene.test.model.Male;
+import org.apache.polygene.test.model.Nameable;
+import org.apache.polygene.test.model.Person;
+import org.junit.Before;
+import org.junit.Test;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.polygene.api.query.QueryExpressions.and;
+import static org.apache.polygene.api.query.QueryExpressions.eq;
+import static org.apache.polygene.api.query.QueryExpressions.ge;
+import static org.apache.polygene.api.query.QueryExpressions.gt;
+import static org.apache.polygene.api.query.QueryExpressions.isNotNull;
+import static org.apache.polygene.api.query.QueryExpressions.isNull;
+import static org.apache.polygene.api.query.QueryExpressions.matches;
+import static org.apache.polygene.api.query.QueryExpressions.not;
+import static org.apache.polygene.api.query.QueryExpressions.or;
+import static org.apache.polygene.api.query.QueryExpressions.orderBy;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+import static org.apache.polygene.api.query.QueryExpressions.variable;
+import static org.apache.polygene.test.indexing.NameableAssert.assertNames;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Abstract satisfiedBy with tests for the EntityFinder interface.
+ */
+public abstract class AbstractEntityFinderTest
+    extends AbstractAnyQueryTest
+{
+
+    private static final Predicate<Composite> ALL = null;
+
+    private static final OrderBy[] NO_SORTING = null;
+    private static final List<OrderBy> NO_SORTING2 = null;
+
+    private static final Integer NO_FIRST_RESULT = null;
+
+    private static final Integer NO_MAX_RESULTS = null;
+
+    private static final Map<String, Object> NO_VARIABLES = Collections.emptyMap();
+
+    private static final String JACK = "Jack Doe";
+
+    private static final String JOE = "Joe Doe";
+
+    private static final String ANN = "Ann Doe";
+
+    @Structure
+    Module moduleInstance;
+
+
+    private EntityFinder entityFinder;
+
+    @Before
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        entityFinder = this.moduleInstance.findService( EntityFinder.class ).get();
+    }
+
+    @Test
+    public void showNetwork()
+        throws IOException
+    {
+        final ServiceReference<IndexExporter> indexerService = this.moduleInstance.findService( IndexExporter.class );
+        final IndexExporter exporter = indexerService.get();
+        exporter.exportReadableToStream( System.out );
+        // todo asserts
+    }
+
+    @Test
+    public void script01()
+    {
+        // should return all persons (Joe, Ann, Jack Doe)
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Person.class,
+            ALL,
+            NO_SORTING2,
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( entities, JOE, JACK, ANN );
+    }
+
+    @Test
+    public void script02()
+    {
+        Nameable nameable = templateFor( Nameable.class );
+        // should return Gaming domain
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Domain.class,
+            eq( nameable.name(), "Gaming" ),
+            NO_SORTING2,
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( entities, "Gaming" );
+    }
+
+    @Test
+    public void script03()
+    {
+        // should return all entities
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Nameable.class,
+            ALL,
+            NO_SORTING2,
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( entities, NameableAssert.allNames() );
+    }
+
+    @Test
+    public void script04()
+    {
+        Person person = templateFor( Person.class );
+        // should return Joe and Ann Doe
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Person.class,
+            eq( person.placeOfBirth().get().name(), "Kuala Lumpur" ),
+            NO_SORTING2,
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( entities, JOE, ANN );
+    }
+
+    @Test
+    public void script05()
+    {
+        Person person = templateFor( Person.class );
+        // should return Joe Doe
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Person.class,
+            eq( person.mother().get().placeOfBirth().get().name(), "Kuala Lumpur" ),
+            NO_SORTING2,
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( entities, JOE );
+    }
+
+    @Test
+    public void script06()
+    {
+        Person person = templateFor( Person.class );
+        // should return Joe and Ann Doe
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Person.class,
+            ge( person.yearOfBirth(), 1973 ),
+            NO_SORTING2,
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( entities, JOE, ANN );
+    }
+
+    @Test
+    @SuppressWarnings( "unchecked" )
+    public void script07()
+    {
+        Person person = templateFor( Person.class );
+        // should return Jack Doe
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Nameable.class,
+            and( ge( person.yearOfBirth(), 1900 ), eq( person.placeOfBirth().get().name(), "Penang" ) ),
+            NO_SORTING2,
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( entities, JACK );
+    }
+
+    @Test
+    @SuppressWarnings( "unchecked" )
+    public void script08()
+    {
+        Person person = templateFor( Person.class );
+        // should return Jack and Ann Doe
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Person.class,
+            or( eq( person.yearOfBirth(), 1970 ), eq( person.yearOfBirth(), 1975 ) ),
+            NO_SORTING2,
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( entities, JACK, ANN );
+    }
+
+    @Test
+    @SuppressWarnings( "unchecked" )
+    public void script09()
+    {
+        Person person = templateFor( Person.class );
+        // should return Ann Doe
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Female.class,
+            or( eq( person.yearOfBirth(), 1970 ), eq( person.yearOfBirth(), 1975 ) ),
+            NO_SORTING2,
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( entities, ANN );
+    }
+
+    @Test
+    public void script10()
+    {
+        Person person = templateFor( Person.class );
+        // should return Joe and Jack Doe
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Person.class,
+            not( eq( person.yearOfBirth(), 1975 ) ),
+            NO_SORTING2,
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( entities, JOE, JACK );
+    }
+
+    @Test
+    public void script11()
+    {
+        Person person = templateFor( Person.class );
+        // should return Joe Doe
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Person.class,
+            isNotNull( person.email() ),
+            NO_SORTING2,
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( entities, JOE );
+    }
+
+    @Test
+    public void script12()
+    {
+        Person person = templateFor( Person.class );
+        // should return Ann and Jack Doe
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Person.class,
+            isNull( person.email() ),
+            NO_SORTING2,
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( entities, ANN, JACK );
+    }
+
+    @Test
+    public void script13()
+    {
+        Male person = templateFor( Male.class );
+        // should return Jack Doe
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Person.class,
+            isNotNull( person.wife() ),
+            NO_SORTING2,
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( entities, JACK );
+    }
+
+    @Test
+    public void script14()
+    {
+        Male person = templateFor( Male.class );
+        // should return Joe Doe
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Male.class,
+            isNull( person.wife() ),
+            NO_SORTING2,
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( entities, JOE );
+    }
+
+    @Test
+    public void script15()
+    {
+        Male person = templateFor( Male.class );
+        // should return Ann and Joe Doe
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Person.class,
+            isNull( person.wife() ),
+            NO_SORTING2,
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( entities, ANN, JOE );
+    }
+
+    @Test
+    public void script16()
+    {
+        // should return only 2 entities
+        Stream<EntityReference> references = entityFinder.findEntities(
+            Nameable.class,
+            ALL,
+            NO_SORTING2,
+            NO_FIRST_RESULT, 2,
+            NO_VARIABLES );
+        assertEquals( "2 identities", 2, references.count() );
+    }
+
+    @Test
+    public void script17()
+    {
+        // should return only 2 entities starting with third one
+        Stream<EntityReference> references = entityFinder.findEntities(
+            Nameable.class,
+            ALL,
+            NO_SORTING2,
+            3, 2,
+            NO_VARIABLES );
+        assertEquals( "2 identitities", 2, references.count() );
+    }
+
+    @Test
+    public void script18()
+    {
+        // should return all Nameable entities sorted by name
+        Nameable nameable = templateFor( Nameable.class );
+        final String[] allNames = NameableAssert.allNames();
+        Arrays.sort( allNames );
+
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Nameable.class,
+            ALL,
+            Collections.singletonList( orderBy( nameable.name() ) ),
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( false, entities, allNames );
+    }
+
+    @Test
+    public void script19()
+    {
+        // should return all Nameable entities with a name > "B" sorted by name
+        Nameable nameable = templateFor( Nameable.class );
+        List<String> largerThanB = new ArrayList<>();
+        for( String name : NameableAssert.allNames() )
+        {
+            if( name.compareTo( "B" ) > 0 )
+            {
+                largerThanB.add( name );
+            }
+        }
+        Collections.sort( largerThanB );
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Nameable.class,
+            gt( nameable.name(), "B" ),
+            Collections.singletonList( orderBy( nameable.name() ) ),
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( false, entities, largerThanB.toArray( new String[ largerThanB.size() ] ) );
+    }
+
+    @Test
+    public void script20()
+    {
+        // should return all Persons born after 1973 (Ann and Joe Doe) sorted descending by name
+        Person person = templateFor( Person.class );
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Person.class,
+            gt( person.yearOfBirth(), 1973 ),
+            Collections.singletonList( orderBy( person.name(), OrderBy.Order.DESCENDING ) ),
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( false, entities, JOE, ANN );
+    }
+
+    @Test
+    public void script21()
+    {
+        // should return all Persons sorted name of the city they were born
+        Person person = templateFor( Person.class );
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Person.class,
+            ALL,
+            Arrays.asList( orderBy( person.placeOfBirth().get().name() ), orderBy( person.name() ) ),
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( false, entities, ANN, JOE, JACK );
+    }
+
+    @Test
+    public void script22()
+    {
+        Nameable nameable = templateFor( Nameable.class );
+        // should return Jack and Joe Doe
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Nameable.class,
+            matches( nameable.name(), "J.*Doe" ),
+            NO_SORTING2,
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            NO_VARIABLES ).collect( toList() );
+        assertNames( entities, JACK, JOE );
+    }
+
+    @Test
+    public void script23()
+    {
+        Nameable nameable = templateFor( Nameable.class );
+        // Try using variables
+        Map<String, Object> variables = new HashMap<>( 1 );
+        variables.put( "domain", "Gaming" );
+        Iterable<EntityReference> entities = entityFinder.findEntities(
+            Domain.class,
+            eq( nameable.name(), variable( "domain" ) ),
+            NO_SORTING2,
+            NO_FIRST_RESULT, NO_MAX_RESULTS,
+            variables ).collect( toList() );
+        assertNames( entities, "Gaming" );
+    }
+
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/indexing/AbstractNamedQueryTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/AbstractNamedQueryTest.java
new file mode 100644
index 0000000..a2b269e
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/AbstractNamedQueryTest.java
@@ -0,0 +1,335 @@
+/*
+ *  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.polygene.test.indexing;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Predicate;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.spi.query.IndexExporter;
+import org.apache.polygene.test.model.Domain;
+import org.apache.polygene.test.model.Female;
+import org.apache.polygene.test.model.Male;
+import org.apache.polygene.test.model.Nameable;
+import org.apache.polygene.test.model.Person;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.apache.polygene.api.query.QueryExpressions.orderBy;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+import static org.apache.polygene.test.indexing.NameableAssert.verifyOrderedResults;
+import static org.apache.polygene.test.indexing.NameableAssert.verifyUnorderedResults;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Abstract satisfiedBy with tests for named queries against Index/Query engines.
+ */
+public abstract class AbstractNamedQueryTest
+    extends AbstractAnyQueryTest
+{
+    @Structure
+    Module moduleInstance;
+
+    protected final Map<String, Predicate<Composite>> queries = new HashMap<>();
+
+    @Before
+    public void assembleQueryStrings()
+    {
+        String[] query = queryStrings();
+        for( int i = 0; i < query.length; i++ )
+        {
+            String queryName = String.format( "script%02d", i + 1 );
+            if( query[i].length() != 0 )
+            {
+                Predicate<Composite> expression = createNamedQueryDescriptor( queryName, query[i] );
+                queries.put( queryName, expression );
+            }
+        }
+    }
+
+    protected abstract String[] queryStrings();
+
+    protected abstract Predicate<Composite> createNamedQueryDescriptor( String queryName, String queryString );
+
+    @Test
+    public void showNetwork()
+        throws IOException
+    {
+        IndexExporter indexerExporter = moduleInstance.findService( IndexExporter.class ).get();
+        indexerExporter.exportReadableToStream( System.out );
+    }
+
+    @Test
+    public void script01()
+    {
+        final Query<Person> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Person.class )
+            .where( queries.get( "script01" ) ) );
+        System.out.println( "*** script01: " + query );
+        verifyUnorderedResults( query, "Joe Doe", "Ann Doe", "Jack Doe" );
+    }
+
+    @Test
+    public void script02()
+    {
+        final Query<Domain> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Domain.class )
+            .where( queries.get( "script02" ) ) );
+        System.out.println( "*** script02: " + query );
+        verifyUnorderedResults( query, "Gaming" );
+    }
+
+    @Test
+    public void script03()
+    {
+        final Query<Nameable> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Nameable.class )
+            .where( queries.get( "script03" ) ) );
+        System.out.println( "*** script03: " + query );
+        verifyUnorderedResults( query, "Joe Doe", "Felix", "Ann Doe", "Jack Doe", "Penang", "Kuala Lumpur", "Cooking",
+                                "Gaming", "Programming", "Cars" );
+    }
+
+    @Test
+    public void script04()
+    {
+        final Query<Person> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Person.class )
+            .where( queries.get( "script04" ) ) );
+        System.out.println( "*** script04: " + query );
+        verifyUnorderedResults( query, "Joe Doe", "Ann Doe" );
+    }
+
+    @Test
+    public void script05()
+    {
+        final Query<Person> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Person.class )
+            .where( queries.get( "script05" ) ) );
+        System.out.println( "*** script05: " + query );
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script06()
+    {
+        final Query<Person> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Person.class )
+            .where( queries.get( "script06" ) ) );
+        System.out.println( "*** script06: " + query );
+        verifyUnorderedResults( query, "Joe Doe", "Ann Doe" );
+    }
+
+    @Test
+    public void script07()
+    {
+        final Query<Nameable> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Nameable.class )
+            .where( queries.get( "script07" ) ) );
+        System.out.println( "*** script07: " + query );
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void script08()
+    {
+        final Query<Person> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Person.class )
+            .where( queries.get( "script08" ) ) );
+        System.out.println( "*** script08: " + query );
+        verifyUnorderedResults( query, "Jack Doe", "Ann Doe" );
+    }
+
+    @Test
+    public void script09()
+    {
+        final Query<Female> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Female.class )
+            .where( queries.get( "script09" ) ) );
+        System.out.println( "*** script09: " + query );
+        verifyUnorderedResults( query, "Ann Doe" );
+    }
+
+    @Test
+    public void script10()
+    {
+        final Query<Person> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Person.class )
+            .where( queries.get( "script10" ) ) );
+        System.out.println( "*** script10: " + query );
+        verifyUnorderedResults( query, "Jack Doe", "Joe Doe" );
+    }
+
+    @Test
+    public void script11()
+    {
+        final Query<Person> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Person.class )
+            .where( queries.get( "script11" ) ) );
+        System.out.println( "*** script11: " + query );
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script12()
+    {
+        final Query<Person> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Person.class )
+            .where( queries.get( "script12" ) ) );
+        System.out.println( "*** script12: " + query );
+        verifyUnorderedResults( query, "Ann Doe", "Jack Doe" );
+    }
+
+    @Test
+    public void script13()
+    {
+        final Query<Person> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Person.class )
+            .where( queries.get( "script13" ) ) );
+        System.out.println( "*** script13: " + query );
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void script14()
+    {
+        final Query<Male> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Male.class )
+            .where( queries.get( "script14" ) ) );
+        System.out.println( "*** script14: " + query );
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script15()
+    {
+        final Query<Person> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Person.class )
+            .where( queries.get( "script15" ) ) );
+        System.out.println( "*** script15: " + query );
+        verifyUnorderedResults( query, "Joe Doe", "Ann Doe" );
+    }
+
+    @Test
+    public void script16()
+    {
+        Nameable nameable = templateFor( Nameable.class );
+        final Query<Nameable> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Nameable.class )
+            .where( queries.get( "script16" ) ) );
+        query.orderBy( orderBy( nameable.name() ) );
+        query.maxResults( 2 );
+        System.out.println( "*** script16: " + query );
+        verifyOrderedResults( query, "Ann Doe", "Cars" );
+    }
+
+    @Test
+    public void script17()
+    {
+        Nameable nameable = templateFor( Nameable.class );
+        Predicate<Composite> predicate = queries.get( "script17" );
+        final Query<Nameable> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Nameable.class )
+            .where( predicate ) );
+        query.orderBy( orderBy( nameable.name() ) );
+        query.firstResult( 3 );
+        query.maxResults( 3 );
+        System.out.println( "*** script17: " + query );
+        verifyOrderedResults( query, "Felix", "Gaming", "Jack Doe" );
+    }
+
+    @Test
+    public void script18()
+    {
+        Nameable nameable = templateFor( Nameable.class );
+        Predicate<Composite> predicate = queries.get( "script18" );
+        final Query<Nameable> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Nameable.class )
+            .where( predicate ) );
+        query.orderBy( orderBy( nameable.name() ) );
+        System.out.println( "*** script18: " + query );
+        verifyOrderedResults( query, "Ann Doe", "Cars", "Cooking", "Felix", "Gaming", "Jack Doe", "Joe Doe",
+                              "Kuala Lumpur", "Penang", "Programming" );
+    }
+
+    @Test
+    public void script19()
+    {
+        Nameable nameable = templateFor( Nameable.class );
+        final Query<Nameable> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Nameable.class )
+            .where( queries.get( "script19" ) ) );
+        query.orderBy( orderBy( nameable.name() ) );
+        System.out.println( "*** script19: " + query );
+        verifyOrderedResults( query, "Felix", "Gaming", "Jack Doe", "Joe Doe", "Kuala Lumpur", "Penang", "Programming" );
+    }
+
+    @Test
+    public void script20()
+    {
+        Person person = templateFor( Person.class );
+        final Query<Person> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Person.class )
+            .where( queries.get( "script20" ) ) );
+        query.orderBy( orderBy( person.name(), OrderBy.Order.DESCENDING ) );
+        System.out.println( "*** script20: " + query );
+        verifyOrderedResults( query, "Joe Doe", "Ann Doe" );
+    }
+
+    @Test
+    public void script21()
+    {
+        Person person = templateFor( Person.class );
+        final Query<Person> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Person.class )
+            .where( queries.get( "script21" ) ) );
+        query.orderBy( orderBy( person.placeOfBirth().get().name() ), orderBy( person.yearOfBirth() ) );
+        System.out.println( "*** script21: " + query );
+        verifyOrderedResults( query, "Ann Doe", "Joe Doe", "Jack Doe" );
+    }
+
+    @Test
+    public void script22()
+    {
+        final Query<Nameable> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Nameable.class )
+            .where( queries.get( "script22" ) ) );
+        System.out.println( "*** script22: " + query );
+        verifyUnorderedResults( query, "Jack Doe", "Joe Doe" );
+    }
+
+    @Test
+    public void script24()
+    {
+        final Query<Domain> query = unitOfWork.newQuery( this.moduleInstance
+            .newQueryBuilder( Domain.class )
+            .where( queries.get( "script24" ) ) );
+        query.setVariable( "domain", "Gaming" );
+        System.out.println( "*** script24: " + query );
+        assertThat( query.find().name().get(), is( equalTo( "Gaming" ) ) );
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/indexing/AbstractQueryTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/AbstractQueryTest.java
new file mode 100644
index 0000000..f005398
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/AbstractQueryTest.java
@@ -0,0 +1,829 @@
+/*
+ *  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.polygene.test.indexing;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.query.NotQueryableException;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.spi.query.IndexExporter;
+import org.apache.polygene.test.model.Account;
+import org.apache.polygene.test.model.City;
+import org.apache.polygene.test.model.Domain;
+import org.apache.polygene.test.model.Female;
+import org.apache.polygene.test.model.File;
+import org.apache.polygene.test.model.Male;
+import org.apache.polygene.test.model.Nameable;
+import org.apache.polygene.test.model.Person;
+import org.apache.polygene.test.model.QueryParam;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static java.time.ZoneOffset.UTC;
+import static org.apache.polygene.api.query.QueryExpressions.and;
+import static org.apache.polygene.api.query.QueryExpressions.contains;
+import static org.apache.polygene.api.query.QueryExpressions.containsName;
+import static org.apache.polygene.api.query.QueryExpressions.eq;
+import static org.apache.polygene.api.query.QueryExpressions.ge;
+import static org.apache.polygene.api.query.QueryExpressions.gt;
+import static org.apache.polygene.api.query.QueryExpressions.isNotNull;
+import static org.apache.polygene.api.query.QueryExpressions.isNull;
+import static org.apache.polygene.api.query.QueryExpressions.lt;
+import static org.apache.polygene.api.query.QueryExpressions.matches;
+import static org.apache.polygene.api.query.QueryExpressions.ne;
+import static org.apache.polygene.api.query.QueryExpressions.not;
+import static org.apache.polygene.api.query.QueryExpressions.oneOf;
+import static org.apache.polygene.api.query.QueryExpressions.or;
+import static org.apache.polygene.api.query.QueryExpressions.orderBy;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+import static org.apache.polygene.test.indexing.NameableAssert.verifyOrderedResults;
+import static org.apache.polygene.test.indexing.NameableAssert.verifyUnorderedResults;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Abstract satisfiedBy with tests for simple queries against Index/Query engines.
+ */
+public abstract class AbstractQueryTest
+    extends AbstractAnyQueryTest
+{
+    @Structure
+    Module moduleInstance;
+
+    @Test
+    public void showNetwork()
+        throws IOException
+    {
+        IndexExporter indexerExporter = moduleInstance.findService( IndexExporter.class ).get();
+        indexerExporter.exportReadableToStream( System.out );
+    }
+
+    @Test
+    public void script01()
+    {
+        final QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        final Query<Person> query = unitOfWork.newQuery( qb );
+        System.out.println( "*** script01: " + query );
+        verifyUnorderedResults( query, "Joe Doe", "Ann Doe", "Jack Doe" );
+    }
+
+    @Test
+    public void script02()
+    {
+        final QueryBuilder<Domain> qb = this.moduleInstance.newQueryBuilder( Domain.class );
+        final Nameable nameable = templateFor( Nameable.class );
+        final Query<Domain> query = unitOfWork.newQuery( qb.where( eq( nameable.name(), "Gaming" ) ) );
+        System.out.println( "*** script02: " + query );
+        verifyUnorderedResults( query, "Gaming" );
+    }
+
+    @Test
+    public void script03()
+    {
+        QueryBuilder<Nameable> qb = this.moduleInstance.newQueryBuilder( Nameable.class );
+        Query<Nameable> query = unitOfWork.newQuery( qb );
+        System.out.println( "*** script03: " + query );
+        verifyUnorderedResults( query, "Felix", "Joe Doe", "Ann Doe", "Jack Doe", "Penang", "Kuala Lumpur", "Cooking", "Gaming",
+                                "Programming", "Cars" );
+    }
+
+    @Test
+    public void script04()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person personTemplate = templateFor( Person.class );
+        City placeOfBirth = personTemplate.placeOfBirth().get();
+        Query<Person> query = unitOfWork.newQuery( qb.where( eq( placeOfBirth.name(), "Kuala Lumpur" ) ) );
+        System.out.println( "*** script04: " + query );
+        verifyUnorderedResults( query, "Joe Doe", "Ann Doe" );
+    }
+
+    @Test
+    public void script04_ne()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person personTemplate = templateFor( Person.class );
+        City placeOfBirth = personTemplate.placeOfBirth().get();
+        Query<Person> query = unitOfWork.newQuery( qb.where( ne( placeOfBirth.name(), "Kuala Lumpur" ) ) );
+        System.out.println( "*** script04_ne: " + query );
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void script05()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.mother()
+                                                                     .get()
+                                                                     .placeOfBirth()
+                                                                     .get()
+                                                                     .name(), "Kuala Lumpur" ) )
+        );
+        System.out.println( "*** script05: " + query );
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script06()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where( ge( person.yearOfBirth(), 1973 ) ) );
+        System.out.println( "*** script06: " + query );
+        verifyUnorderedResults( query, "Joe Doe", "Ann Doe" );
+    }
+
+    @Test
+    @SuppressWarnings( "unchecked" )
+    public void script07()
+    {
+        QueryBuilder<Nameable> qb = this.moduleInstance.newQueryBuilder( Nameable.class );
+        Person person = templateFor( Person.class );
+        Query<Nameable> query = unitOfWork.newQuery( qb.where(
+            and( ge( person.yearOfBirth(), 1900 ), eq( person.placeOfBirth().get().name(), "Penang" ) ) ) );
+        System.out.println( "*** script07: " + query );
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    @SuppressWarnings( "unchecked" )
+    public void script08()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where( or( eq( person.yearOfBirth(), 1970 ), eq( person.yearOfBirth(), 1975 ) ) )
+        );
+        System.out.println( "*** script08: " + query );
+        verifyUnorderedResults( query, "Jack Doe", "Ann Doe" );
+    }
+
+    @Test
+    @SuppressWarnings( "unchecked" )
+    public void script09()
+    {
+        QueryBuilder<Female> qb = this.moduleInstance.newQueryBuilder( Female.class );
+        Person person = templateFor( Person.class );
+        Query<Female> query = unitOfWork.newQuery( qb.where( or( eq( person.yearOfBirth(), 1970 ), eq( person.yearOfBirth(), 1975 ) ) )
+        );
+        System.out.println( "*** script09: " + query );
+        verifyUnorderedResults( query, "Ann Doe" );
+    }
+
+    @Test
+    public void script10()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where( not( eq( person.yearOfBirth(), 1975 ) ) ) );
+        System.out.println( "*** script10: " + query );
+        verifyUnorderedResults( query, "Jack Doe", "Joe Doe" );
+    }
+
+    @Test
+    public void script11()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where( isNotNull( person.email() ) ) );
+        System.out.println( "*** script11: " + query );
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script12()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where( isNull( person.email() ) ) );
+        System.out.println( "*** script12: " + query );
+        verifyUnorderedResults( query, "Ann Doe", "Jack Doe" );
+    }
+
+    @Test
+    public void script12_ne()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where( ne( person.email(), "joe@thedoes.net" ) ) );
+        System.out.println( "*** script12_ne: " + query );
+        verifyUnorderedResults( query );
+    }
+
+    @Test
+    public void script13()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Male person = templateFor( Male.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where( isNotNull( person.wife() ) ) );
+        System.out.println( "*** script13: " + query );
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void script14()
+    {
+        QueryBuilder<Male> qb = this.moduleInstance.newQueryBuilder( Male.class );
+        Male person = templateFor( Male.class );
+        Query<Male> query = unitOfWork.newQuery( qb.where( isNull( person.wife() ) ) );
+        System.out.println( "*** script14: " + query );
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script15()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Male person = templateFor( Male.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where( isNull( person.wife() ) ) );
+        System.out.println( "*** script15: " + query );
+        verifyUnorderedResults( query, "Joe Doe", "Ann Doe" );
+    }
+
+    @Test
+    public void script16()
+    {
+        QueryBuilder<Nameable> qb = this.moduleInstance.newQueryBuilder( Nameable.class );
+        // should return only 2 entities
+        Nameable nameable = templateFor( Nameable.class );
+        Query<Nameable> query = unitOfWork.newQuery( qb );
+        query.orderBy( orderBy( nameable.name() ) );
+        query.maxResults( 2 );
+        System.out.println( "*** script16: " + query );
+        verifyOrderedResults( query, "Ann Doe", "Cars" );
+    }
+
+    @Test
+    public void script17()
+    {
+        QueryBuilder<Nameable> qb = this.moduleInstance.newQueryBuilder( Nameable.class );
+        // should return only 3 entities starting with forth one
+        Nameable nameable = templateFor( Nameable.class );
+        Query<Nameable> query = unitOfWork.newQuery( qb );
+        query.orderBy( orderBy( nameable.name() ) );
+        query.firstResult( 3 );
+        query.maxResults( 2 );
+        System.out.println( "*** script17: " + query );
+        verifyOrderedResults( query, "Felix", "Gaming" );
+    }
+
+    @Test
+    public void script18()
+    {
+        QueryBuilder<Nameable> qb = this.moduleInstance.newQueryBuilder( Nameable.class );
+        // should return all Nameable entities sorted by name
+        Nameable nameable = templateFor( Nameable.class );
+        Query<Nameable> query = unitOfWork.newQuery( qb );
+        query.orderBy( orderBy( nameable.name() ) );
+        System.out.println( "*** script18: " + query );
+        verifyOrderedResults( query, "Ann Doe", "Cars", "Cooking", "Felix", "Gaming", "Jack Doe", "Joe Doe", "Kuala Lumpur",
+                              "Penang", "Programming" );
+    }
+
+    @Test
+    public void script19()
+    {
+        QueryBuilder<Nameable> qb = this.moduleInstance.newQueryBuilder( Nameable.class );
+        // should return all Nameable entities with a name > "D" sorted by name
+        Nameable nameable = templateFor( Nameable.class );
+        Query<Nameable> query = unitOfWork.newQuery( qb.where( gt( nameable.name(), "D" ) ) );
+        query.orderBy( orderBy( nameable.name() ) );
+        System.out.println( "*** script19: " + query );
+        verifyOrderedResults( query, "Felix", "Gaming", "Jack Doe", "Joe Doe", "Kuala Lumpur", "Penang", "Programming" );
+    }
+
+    @Test
+    public void script20()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        // should return all Persons born after 1973 (Ann and Joe Doe) sorted descending by name
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where( gt( person.yearOfBirth(), 1973 ) ) );
+        query.orderBy( orderBy( person.name(), OrderBy.Order.DESCENDING ) );
+        System.out.println( "*** script20: " + query );
+        verifyOrderedResults( query, "Joe Doe", "Ann Doe" );
+    }
+
+    @Test
+    public void script21()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        // should return all Persons sorted by name of the city they were born, and then by year they were born
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb );
+        query.orderBy( orderBy( person.placeOfBirth().get().name() ), orderBy( person.yearOfBirth() ) );
+        System.out.println( "*** script21: " + query );
+        verifyOrderedResults( query, "Ann Doe", "Joe Doe", "Jack Doe" );
+    }
+
+    @Test
+    public void script22()
+    {
+        QueryBuilder<Nameable> qb = this.moduleInstance.newQueryBuilder( Nameable.class );
+        Nameable nameable = templateFor( Nameable.class );
+        // should return Jack and Joe Doe
+        Query<Nameable> query = unitOfWork.newQuery( qb.where( matches( nameable.name(), "J.*Doe" ) ) );
+        System.out.println( "*** script22: " + query );
+        verifyUnorderedResults( query, "Jack Doe", "Joe Doe" );
+    }
+
+    @Test
+    public void script23()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Domain interests = oneOf( person.interests() );
+        Query<Person> query = unitOfWork.newQuery( qb.where( eq( interests.name(), "Cars" ) ) );
+        System.out.println( "*** script23: " + query );
+        verifyOrderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void script24()
+    {
+        final QueryBuilder<Domain> qb = this.moduleInstance.newQueryBuilder( Domain.class );
+        final Nameable nameable = templateFor( Nameable.class );
+        final Query<Domain> query = unitOfWork.newQuery( qb.where( eq( nameable.name(), "Gaming" ) ) );
+        System.out.println( "*** script24: " + query );
+        assertThat( query.find().name().get(), is( equalTo( "Gaming" ) ) );
+    }
+
+    @Test( expected = NotQueryableException.class )
+    public void script25()
+    {
+        this.moduleInstance.newQueryBuilder( File.class );
+    }
+
+    @Test( expected = NotQueryableException.class )
+    public void script26()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        qb.where( eq( person.personalWebsite().get().file().get().value(), "some/path" ) );
+    }
+
+    @Test( expected = NotQueryableException.class )
+    public void script27()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        qb.where( eq( person.personalWebsite().get().host().get().value(), "polygene.apache.org" ) );
+    }
+
+    @Test( expected = NotQueryableException.class )
+    public void script28()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        qb.where( eq( person.personalWebsite().get().port().get().value(), 8080 ) );
+    }
+
+    @Test
+    public void script29()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.personalWebsite()
+                                                                     .get()
+                                                                     .protocol()
+                                                                     .get()
+                                                                     .value(), "http" ) )
+        );
+        System.out.println( "*** script29: " + query );
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    @Ignore( "Wait till 1.1?" )
+    // Paul: I don't understand this test
+    @SuppressWarnings( "unchecked" )
+    public void script30()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        QueryParam queryParam = null; //oneOf( person.personalWebsite().get().queryParams() );
+        Query<Person> query = unitOfWork.newQuery( qb.where( and( eq( queryParam.name(), "foo" ), eq( queryParam.value(), "bar" ) ) ) );
+        System.out.println( "*** script30: " + query );
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    @Ignore( "Equality on Property<Map<?,?>> not implemented" )
+    public void script31()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Map<String, String> info = new HashMap<>( 0 );
+        Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.additionalInfo(), info ) ) );
+        System.out.println( "*** script31: " + query );
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void script32()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.address().get().line1(), "Qi Alley 4j" ) ) );
+        System.out.println( "*** script32: " + query );
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script33()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Domain gaming = unitOfWork.get( Domain.class, new StringIdentity( "Gaming" ) );
+        Query<Person> query = unitOfWork.newQuery( qb.where( contains( person.interests(), gaming ) ) );
+        System.out.println( "*** script33: " + query );
+
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script34()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Female annDoe = unitOfWork.get( Female.class, new StringIdentity( "anndoe" ) );
+        Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.mother(), annDoe ) ) );
+        System.out.println( "*** script34: " + query );
+
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script35()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where( containsName( person.accounts(), "anns" ) ) );
+        System.out.println( "*** script35: " + query );
+
+        verifyUnorderedResults( query, "Jack Doe", "Ann Doe" );
+    }
+
+    @Test
+    public void script36()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Account anns = unitOfWork.get( Account.class, new StringIdentity( "accountOfAnnDoe" ) );
+        Query<Person> query = unitOfWork.newQuery( qb.where( contains( person.accounts(), anns ) ) );
+        System.out.println( "*** script36: " + query );
+
+        verifyUnorderedResults( query, "Jack Doe", "Ann Doe" );
+    }
+
+    @Test
+    @Ignore( "Traversing of NamedAssociations is not implemented" )
+    public void script37()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.accounts().get( "anns" ).number(),
+                                                                 "accountOfAnnDoe" ) ) );
+        System.out.println( "*** script37: " + query );
+
+        verifyUnorderedResults( query, "Jack Doe", "Ann Doe" );
+    }
+
+    @Test
+    public void script38()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.title(), Person.Title.DR ) ) );
+        System.out.println( "*** script38: " + query );
+
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void script39()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where( ne( person.title(), Person.Title.DR ) ) );
+        System.out.println( "*** script39: " + query );
+
+        verifyUnorderedResults( query, "Ann Doe", "Joe Doe" );
+    }
+
+    @Test
+    public void script40_Date()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Instant refInstant = ZonedDateTime.of( 2010, 3, 4, 13, 24, 35, 0, UTC ).toInstant();
+        System.out.println( refInstant );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            eq( person.instantValue(), refInstant ) ) );
+        System.out.println( "*** script40_Date: " + query );
+
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void script41_Instant()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Instant refInstant = ZonedDateTime.of( 2010, 3, 4, 13, 24, 35, 0, UTC ).toInstant();
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            ne( person.instantValue(), refInstant ) ) );
+        System.out.println( "*** script41_Instant: " + query );
+
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script42_Instant()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        ZonedDateTime cetTime = ZonedDateTime.of( 2010, 3, 4, 14, 24, 35, 0, ZoneId.of( "CET" ) );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            ne( person.instantValue(), cetTime.toInstant() ) ) );
+        System.out.println( "*** script42_Instant: " + query );
+
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script43_Date()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        ZonedDateTime start = ZonedDateTime.of( 2005, 3, 4, 13, 24, 35, 0, UTC );
+        ZonedDateTime end = ZonedDateTime.of( 2015, 3, 4, 13, 24, 35, 0, UTC );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            and( gt( person.instantValue(), start.toInstant() ),
+                 lt( person.instantValue(), end.toInstant() ) ) ) );
+        System.out.println( "*** script43_Date: " + query );
+
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void script40_DateTime()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        ZonedDateTime time = ZonedDateTime.of( 2010, 3, 4, 13, 24, 35, 0, UTC );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            eq( person.dateTimeValue(), time ) ) );
+        System.out.println( "*** script40_DateTime: " + query );
+
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void script41_DateTime()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        ZonedDateTime time = ZonedDateTime.of( 2010, 3, 4, 13, 24, 35, 0, UTC );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            ne( person.dateTimeValue(), time ) ) );
+        System.out.println( "*** script41_DateTime: " + query );
+
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script42_DateTime()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        ZonedDateTime time = ZonedDateTime.of( 2010, 3, 4, 13, 24, 35, 0, ZoneId.of( "CET" ) );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            ne( person.dateTimeValue(), time ) ) );
+        System.out.println( "*** script42_DateTime: " + query );
+
+        verifyUnorderedResults( query, "Jack Doe", "Joe Doe" );
+    }
+
+    @Test
+    public void script43_DateTime()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        ZonedDateTime start = ZonedDateTime.of( 2005, 3, 4, 13, 24, 35, 0, UTC );
+        ZonedDateTime end = ZonedDateTime.of( 2015, 3, 4, 13, 24, 35, 0, UTC );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            and( gt( person.dateTimeValue(), start ),
+                 lt( person.dateTimeValue(), end ) ) ) );
+        System.out.println( "*** script43_DateTime: " + query );
+
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void script40_LocalDateTime()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            eq( person.localDateTimeValue(), LocalDateTime.of( 2010, 3, 4, 13, 23, 0 ) ) ) );
+        System.out.println( "*** script40_LocalDateTime: " + query );
+
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void script41_LocalDateTime()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            ne( person.localDateTimeValue(), LocalDateTime.of( 2010, 3, 4, 13, 23, 0 ) ) ) );
+        System.out.println( "*** script41_LocalDateTime: " + query );
+
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script42_LocalDateTime()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        LocalDateTime time = LocalDateTime.of( 2010, 3, 4, 13, 23, 0 );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            ne( person.localDateTimeValue(), time ) ) );
+        System.out.println( "*** script42_LocalDateTime: " + query );
+
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script43_LocalDateTime()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        LocalDateTime start = ZonedDateTime.of( 2005, 3, 4, 13, 24, 35, 0, UTC ).toLocalDateTime();
+        LocalDateTime end = ZonedDateTime.of( 2015, 3, 4, 13, 24, 35, 0, UTC ).toLocalDateTime();
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            and( gt( person.localDateTimeValue(), start ),
+                 lt( person.localDateTimeValue(), end ) ) ) );
+        System.out.println( "*** script43_LocalDateTime: " + query );
+
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void script40_LocalDate()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            eq( person.localDateValue(), LocalDate.of( 2010, 3, 4 ) ) ) );
+        System.out.println( "*** script40_LocalDate: " + query );
+
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void script41_LocalDate()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            ne( person.localDateValue(), LocalDate.of( 2010, 3, 4 ) ) ) );
+        System.out.println( "*** script41_LocalDate: " + query );
+
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script42_LocalDate()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        LocalDate time = ZonedDateTime.of( 2010, 3, 4, 13, 24, 35, 0, ZoneId.of( "CET" ) ).toLocalDate();
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            ne( person.localDateValue(), time ) ) );
+        System.out.println( "*** script42_LocalDate: " + query );
+
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script43_LocalDate()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        LocalDate start = ZonedDateTime.of( 2005, 3, 4, 13, 24, 35, 0, UTC ).toLocalDate();
+        LocalDate end = ZonedDateTime.of( 2015, 3, 4, 13, 24, 35, 0, UTC ).toLocalDate();
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            and( gt( person.localDateValue(), start ),
+                 lt( person.localDateValue(), end ) ) ) );
+        System.out.println( "*** script43_LocalDate: " + query );
+
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void script50_BigInteger()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            eq( person.bigInteger(), new BigInteger( "23232323232323232323232323" ) ) ) );
+        System.out.println( "*** script50_BigInteger: " + query );
+
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script51_BigInteger()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            ne( person.bigInteger(), new BigInteger( "23232323232323232323232323" ) ) ) );
+        System.out.println( "*** script51_BigInteger: " + query );
+
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void script52_BigInteger()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            ge( person.bigInteger(), new BigInteger( "23232323232323232323232323" ) ) ) );
+        System.out.println( "*** script52_BigInteger: " + query );
+
+        verifyUnorderedResults( query, "Jack Doe", "Joe Doe" );
+    }
+
+    @Test
+    public void script50_BigDecimal()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            eq( person.bigDecimal(), new BigDecimal( "2342.76931348623157e+307" ) ) ) );
+        System.out.println( "*** script50_BigDecimal: " + query );
+
+        verifyUnorderedResults( query, "Joe Doe" );
+    }
+
+    @Test
+    public void script51_BigDecimal()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            ne( person.bigDecimal(), new BigDecimal( "2342.76931348623157e+307" ) ) ) );
+        System.out.println( "*** script51_BigDecimal: " + query );
+
+        verifyUnorderedResults( query, "Jack Doe" );
+    }
+
+    @Test
+    public void script52_BigDecimal()
+    {
+        QueryBuilder<Person> qb = this.moduleInstance.newQueryBuilder( Person.class );
+        Person person = templateFor( Person.class );
+        Query<Person> query = unitOfWork.newQuery( qb.where(
+            ge( person.bigDecimal(), new BigDecimal( "2342.76931348623157e+307" ) ) ) );
+        System.out.println( "*** script52_BigDecimal: " + query );
+
+        verifyUnorderedResults( query, "Jack Doe", "Joe Doe" );
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/indexing/NameableAssert.java b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/NameableAssert.java
new file mode 100644
index 0000000..58dde55
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/NameableAssert.java
@@ -0,0 +1,151 @@
+/*
+ *  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.polygene.test.indexing;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.test.model.Nameable;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class NameableAssert
+{
+    // id -> name
+    private static final Map<Identity, String> world = new HashMap<>();
+
+    public static void clear()
+    {
+        world.clear();
+    }
+
+    public static void assertNames( Iterable<EntityReference> identitiesIterable, String... expectedNames )
+    {
+        assertNames( true, identitiesIterable, expectedNames );
+    }
+
+    public static void assertNames( boolean sort,
+                                    Iterable<EntityReference> identitiesIterable,
+                                    String... expectedNames
+    )
+    {
+        final List<EntityReference> references = StreamSupport.stream( identitiesIterable.spliterator(), false )
+                                                              .collect( Collectors.toList() );
+        assertThat( expectedNames.length + " entries(" + expectedNames.length + ", got " + getNames( references ) + ")",
+                    references.size(),
+                    equalTo( expectedNames.length ) );
+        List<String> sortedNames = getNames( references );
+        final List<String> expectedSorted = java.util.Arrays.asList( expectedNames );
+        if( sort )
+        {
+            Collections.sort( sortedNames );
+            Collections.sort( expectedSorted );
+        }
+        assertThat( "names", sortedNames, equalTo( expectedSorted ) );
+    }
+
+    public static void trace( Nameable nameable )
+    {
+        world.put( nameable.identity().get(), nameable.name().get() );
+    }
+
+    public static void assertName( String expectedName, EntityReference reference )
+    {
+        final String existingName = getName( reference );
+        assertThat( "Name of " + reference, existingName, equalTo( expectedName ) );
+    }
+
+    public static String getName( EntityReference reference )
+    {
+        return world.get( reference.identity() );
+    }
+
+    public static List<String> getNames( List<EntityReference> references )
+    {
+        List<String> result = new ArrayList<>( references.size() );
+        for( EntityReference reference : references )
+        {
+            final String name = getName( reference );
+            assertThat( "Name of " + reference, name, notNullValue() );
+            result.add( name );
+        }
+        return result;
+    }
+
+    public static String[] allNames()
+    {
+        Collection<String> values = world.values();
+        return values.toArray( new String[ world.size() ] );
+    }
+
+    public static void verifyUnorderedResults( final Iterable<? extends Nameable> results, final String... names )
+    {
+        List<String> expected = new ArrayList<>( Arrays.asList( names ) );
+        List<String> unexpected = new ArrayList<>();
+        for( Nameable result : results )
+        {
+            String name = result.name().get();
+            if( !expected.remove( name ) )
+            {
+                unexpected.add( name );
+            }
+        }
+        if( !unexpected.isEmpty() || !expected.isEmpty() )
+        {
+            String message = "";
+            if( !unexpected.isEmpty() )
+            {
+                message += unexpected + " returned but not expected\n";
+            }
+            if( !expected.isEmpty() )
+            {
+                message += expected + " expected but not returned\n";
+            }
+            fail( message.substring( 0, message.length() - 1 ) );
+        }
+    }
+
+    public static void verifyOrderedResults( final Iterable<? extends Nameable> results, final String... names )
+    {
+        List<String> expected = new ArrayList<>( Arrays.asList( names ) );
+        List<String> actual = new ArrayList<>();
+        for( Nameable result : results )
+        {
+            actual.add( result.name().get() );
+        }
+
+        assertThat( "Result is incorrect", actual, equalTo( expected ) );
+    }
+
+    private NameableAssert()
+    {
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/indexing/TestData.java b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/TestData.java
new file mode 100644
index 0000000..aaa8bac
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/TestData.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.polygene.test.indexing;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZonedDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.test.model.Account;
+import org.apache.polygene.test.model.Address;
+import org.apache.polygene.test.model.Cat;
+import org.apache.polygene.test.model.City;
+import org.apache.polygene.test.model.Domain;
+import org.apache.polygene.test.model.Female;
+import org.apache.polygene.test.model.Male;
+import org.apache.polygene.test.model.Person;
+import org.apache.polygene.test.model.Protocol;
+import org.apache.polygene.test.model.QueryParam;
+import org.apache.polygene.test.model.URL;
+
+import static java.time.ZoneOffset.UTC;
+
+/**
+ * Utility class to populate Index/Query tests data.
+ */
+public class TestData
+{
+    public static void populate( Module module )
+        throws UnitOfWorkCompletionException
+    {
+        try (UnitOfWork unitOfWork = module.unitOfWorkFactory().newUnitOfWork())
+        {
+            NameableAssert.clear();
+            Domain gaming;
+            {
+                EntityBuilder<Domain> domainBuilder = unitOfWork.newEntityBuilder( Domain.class, new StringIdentity( "Gaming" ) );
+                gaming = domainBuilder.instance();
+                gaming.name().set( "Gaming" );
+                gaming.description().set( "Gaming domain" );
+                gaming = domainBuilder.newInstance();
+                NameableAssert.trace( gaming );
+            }
+
+            Domain programming;
+            {
+                EntityBuilder<Domain> domainBuilder = unitOfWork.newEntityBuilder( Domain.class );
+                programming = domainBuilder.instance();
+                programming.name().set( "Programming" );
+                programming.description().set( "Programing domain" );
+                programming = domainBuilder.newInstance();
+                NameableAssert.trace( programming );
+            }
+
+            Domain cooking;
+            {
+                EntityBuilder<Domain> domainBuilder = unitOfWork.newEntityBuilder( Domain.class );
+                cooking = domainBuilder.instance();
+                cooking.name().set( "Cooking" );
+                cooking.description().set( "Cooking domain" );
+                cooking = domainBuilder.newInstance();
+                NameableAssert.trace( cooking );
+            }
+
+            Domain cars;
+            {
+                EntityBuilder<Domain> domainBuilder = unitOfWork.newEntityBuilder( Domain.class );
+                cars = domainBuilder.instance();
+                cars.name().set( "Cars" );
+                cars.description().set( "Cars" );
+                cars = domainBuilder.newInstance();
+                NameableAssert.trace( cars );
+            }
+
+            City kualaLumpur;
+            {
+                EntityBuilder<City> cityBuilder = unitOfWork.newEntityBuilder( City.class );
+                kualaLumpur = cityBuilder.instance();
+                kualaLumpur.name().set( "Kuala Lumpur" );
+                kualaLumpur.country().set( "Malaysia" );
+                kualaLumpur.county().set( "Some Jaya" );
+                kualaLumpur = cityBuilder.newInstance();
+                NameableAssert.trace( kualaLumpur );
+            }
+
+            City penang;
+            {
+                EntityBuilder<City> cityBuilder = unitOfWork.newEntityBuilder( City.class );
+                penang = cityBuilder.instance();
+                penang.name().set( "Penang" );
+                penang.country().set( "Malaysia" );
+                penang.county().set( "Some Other Jaya" );
+                penang = cityBuilder.newInstance();
+                NameableAssert.trace( penang );
+            }
+
+            Account annsAccount;
+            {
+                EntityBuilder<Account> accountBuilder = unitOfWork.newEntityBuilder( Account.class, new StringIdentity( "accountOfAnnDoe" ) );
+                annsAccount = accountBuilder.instance();
+                annsAccount.number().set( "accountOfAnnDoe" );
+                annsAccount = accountBuilder.newInstance();
+            }
+
+            Account jacksAccount;
+            {
+                EntityBuilder<Account> accountBuilder = unitOfWork.newEntityBuilder( Account.class, new StringIdentity( "accountOfJackDoe" ) );
+                jacksAccount = accountBuilder.instance();
+                jacksAccount.number().set( "accountOfJackDoe" );
+                jacksAccount = accountBuilder.newInstance();
+            }
+
+            ValueBuilder<Address> addressBuilder = module.newValueBuilder( Address.class );
+            Address address = addressBuilder.prototype();
+            address.line1().set( "Qi Street 4j" );
+            address.line2().set( "Off main Java Street" );
+            address.zipcode().set( "12345" );
+
+            Female annDoe;
+            {
+                EntityBuilder<Female> femaleBuilder = unitOfWork.newEntityBuilder( Female.class, new StringIdentity( "anndoe" ) );
+                annDoe = femaleBuilder.instance();
+                annDoe.name().set( "Ann Doe" );
+                annDoe.title().set( Person.Title.MRS );
+                annDoe.placeOfBirth().set( kualaLumpur );
+                annDoe.yearOfBirth().set( 1975 );
+                annDoe.interests().add( 0, cooking );
+                annDoe.password().set( "passwordOfAnnDoe" );
+                annDoe.mainAccount().set( annsAccount );
+                annDoe.accounts().put( "anns", annsAccount );
+                annDoe.accounts().put( "jacks", jacksAccount );
+                annDoe.address().set( addressBuilder.newInstance() );
+                annDoe = femaleBuilder.newInstance();
+                NameableAssert.trace( annDoe );
+            }
+
+            {
+                EntityBuilder<Male> maleBuilder = unitOfWork.newEntityBuilder( Male.class );
+                Male joeDoe = maleBuilder.instance();
+                joeDoe.name().set( "Joe Doe" );
+                joeDoe.title().set( Person.Title.MR );
+                joeDoe.placeOfBirth().set( kualaLumpur );
+                joeDoe.yearOfBirth().set( 1990 );
+                joeDoe.mother().set( annDoe );
+                joeDoe.interests().add( 0, programming );
+                joeDoe.interests().add( 0, gaming );
+                joeDoe.email().set( "joe@thedoes.net" );
+                joeDoe.password().set( "passwordOfJoeDoe" );
+                joeDoe = maleBuilder.newInstance();
+                address = module.newValueBuilderWithPrototype( address ).prototype();
+                address.line1().set( "Qi Alley 4j" );
+                joeDoe.address().set( address );
+                joeDoe.bigInteger().set( new BigInteger( "23232323232323232323232323" ) );
+                joeDoe.bigDecimal().set( new BigDecimal( "23.4276931348623157e+309" ) );
+                joeDoe.instantValue().set( ZonedDateTime.of( 2020, 3, 4, 13, 24, 35, 0, UTC ).toInstant() );
+                joeDoe.dateTimeValue().set( ZonedDateTime.of( 2020, 3, 4, 13, 24, 35, 0, UTC ) );
+                joeDoe.localDateTimeValue().set( LocalDateTime.of( 2020, 3, 4, 13, 23, 0 ) );
+                joeDoe.localDateValue().set( LocalDate.of( 2020, 3, 4 ) );
+                NameableAssert.trace( joeDoe );
+            }
+
+            {
+                EntityBuilder<Male> maleBuilder = unitOfWork.newEntityBuilder( Male.class );
+                Male jackDoe = maleBuilder.instance();
+                jackDoe.name().set( "Jack Doe" );
+                jackDoe.title().set( Person.Title.DR );
+                jackDoe.placeOfBirth().set( penang );
+                jackDoe.yearOfBirth().set( 1970 );
+                jackDoe.interests().add( 0, cars );
+                jackDoe.wife().set( annDoe );
+                jackDoe.password().set( "passwordOfJohnDoe" );
+                jackDoe.mainAccount().set( jacksAccount );
+                jackDoe.accounts().put( "anns", annsAccount );
+                jackDoe.accounts().put( "jacks", jacksAccount );
+                address = module.newValueBuilderWithPrototype( address ).prototype();
+                address.line1().set( "Qi Avenue 4j" );
+                jackDoe.address().set( address );
+                jackDoe.bigInteger().set( new BigInteger( "42424242424242424242424242" ) );
+                jackDoe.bigDecimal().set( new BigDecimal( "42.2376931348623157e+309" ) );
+                jackDoe.instantValue().set( ZonedDateTime.of( 2010, 3, 4, 13, 24, 35, 0, UTC ).toInstant() );
+                jackDoe.dateTimeValue().set( ZonedDateTime.of( 2010, 3, 4, 13, 24, 35, 0, UTC ) );
+                jackDoe.localDateTimeValue().set( LocalDateTime.of( 2010, 3, 4, 13, 23, 0 ) );
+                jackDoe.localDateValue().set( LocalDate.of( 2010, 3, 4 ) );
+
+                ValueBuilder<URL> urlBuilder = module.newValueBuilder( URL.class );
+                ValueBuilder<Protocol> protocolBuilder = module.newValueBuilder( Protocol.class );
+                ValueBuilder<QueryParam> queryParamBuilder = module.newValueBuilder( QueryParam.class );
+
+                Protocol protocol = protocolBuilder.prototype();
+                protocol.value().set( "http" );
+
+                List<QueryParam> queryParams = new ArrayList<>( 2 );
+                QueryParam param = queryParamBuilder.prototype();
+                param.name().set( "user" );
+                param.value().set( "jackdoe" );
+                queryParams.add( queryParamBuilder.newInstance() );
+                queryParamBuilder = module.newValueBuilder( QueryParam.class );
+                param = queryParamBuilder.prototype();
+                param.name().set( "password" );
+                param.value().set( "somepassword" );
+                queryParams.add( queryParamBuilder.newInstance() );
+
+                URL url = urlBuilder.prototype();
+                url.protocol().set( protocolBuilder.newInstance() );
+                url.queryParams().set( queryParams );
+
+                jackDoe.personalWebsite().set( urlBuilder.newInstance() );
+
+                jackDoe = maleBuilder.newInstance();
+                NameableAssert.trace( jackDoe );
+            }
+
+            {
+                EntityBuilder<Cat> catBuilder = unitOfWork.newEntityBuilder( Cat.class );
+                Cat felix = catBuilder.instance();
+                felix.name().set( "Felix" );
+                catBuilder.newInstance();
+                NameableAssert.trace( felix );
+            }
+            unitOfWork.complete();
+        }
+    }
+
+    private TestData()
+    {
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/indexing/layered/AbstractMultiLayeredIndexingTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/layered/AbstractMultiLayeredIndexingTest.java
new file mode 100644
index 0000000..a5b4b5a
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/layered/AbstractMultiLayeredIndexingTest.java
@@ -0,0 +1,137 @@
+/*
+ *  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.polygene.test.indexing.layered;
+
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.service.qualifier.Tagged;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.test.indexing.TestData;
+import org.apache.polygene.test.model.assembly.ApplicationAssembler;
+import org.junit.Before;
+import org.junit.Test;
+
+public abstract class AbstractMultiLayeredIndexingTest
+{
+    public static Class<? extends ModuleAssembler> indexingAssembler;
+
+    protected Application application;
+
+    @Structure
+    private UnitOfWorkFactory uowf;
+
+    @Optional
+    @Service
+    @Tagged( "Suite1Case1" )
+    private ServiceReference<TestCase> suite1Case1;
+
+    @Optional
+    @Service
+    @Tagged( "Suite1Case2" )
+    private ServiceReference<TestCase> suite1Case2;
+
+    @Optional
+    @Service
+    @Tagged( "Suite2Case1" )
+    private ServiceReference<TestCase> suite2Case1;
+
+    @Optional
+    @Service
+    @Tagged( "Suite3Case1" )
+    private ServiceReference<TestCase> suite3Case1;
+
+    public AbstractMultiLayeredIndexingTest( Class<? extends ModuleAssembler> indexingAssembler )
+    {
+        AbstractMultiLayeredIndexingTest.indexingAssembler = indexingAssembler;
+    }
+
+    @Before
+    public void setup()
+        throws AssemblyException, ActivationException
+    {
+        ApplicationAssembler assembler =
+            new ApplicationAssembler( "Multi Layered Indexing Test", "1.0", Application.Mode.development, getClass() );
+        assembler.initialize();
+        assembler.start();
+        application = assembler.application();
+        Module familyModule = application.findModule( "Domain Layer", "Family Module" );
+        TestData.populate( familyModule );
+        Module executionModule = application.findModule( "Access Layer", "TestExecution Module" );
+        executionModule.injectTo( this );
+    }
+
+    @Test
+    public void suite1Case1()
+        throws Exception
+    {
+        runTest( suite1Case1, "suite1Case1" );
+    }
+
+    @Test
+    public void suite1Case2()
+        throws Exception
+    {
+        runTest( suite1Case2, "suite1Case2"  );
+    }
+
+    @Test
+    public void suite2Case1()
+        throws Exception
+    {
+        runTest( suite2Case1, "suite2Case1"  );
+    }
+
+    @Test
+    public void suite3Case1()
+        throws Exception
+    {
+        runTest( suite3Case1, "suite3Case1"  );
+    }
+
+    private void runTest( ServiceReference<TestCase> testCaseRef, String testName )
+        throws Exception
+    {
+        if( testCaseRef == null )
+        {
+            System.err.println( "TestCase is not defined." );
+        }
+        else
+        {
+            TestCase testCase = testCaseRef.get();
+            try(UnitOfWork uow = uowf.newUnitOfWork( UsecaseBuilder.newUsecase( testName ) ))
+            {
+                testCase.given();
+                testCase.when();
+                testCase.expect();
+                uow.complete();
+            }
+        }
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/indexing/layered/Suite1Case1.java b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/layered/Suite1Case1.java
new file mode 100644
index 0000000..8477b18
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/layered/Suite1Case1.java
@@ -0,0 +1,75 @@
+/*
+ *  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.polygene.test.indexing.layered;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.query.QueryExpressions;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.test.model.Male;
+import org.apache.polygene.test.model.Person;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class Suite1Case1
+    implements TestCase
+{
+    @Structure
+    private UnitOfWorkFactory uowf;
+
+    @Structure
+    private QueryBuilderFactory qbf;
+
+    private QueryBuilder<Male> builder;
+
+    private Query<Male> query;
+
+    @Override
+    public void given()
+        throws Exception
+    {
+        QueryBuilder<Male> qb = qbf.newQueryBuilder( Male.class );
+        Male prototype = QueryExpressions.templateFor( Male.class );
+        builder = qb.where( QueryExpressions.eq(prototype.name(), "Joe Doe" ) );
+    }
+
+    @Override
+    public void when()
+        throws Exception
+    {
+        UnitOfWork uow = uowf.currentUnitOfWork();
+        query = uow.newQuery( builder );
+    }
+
+    @Override
+    public void expect()
+        throws Exception
+    {
+        assertThat( query.count(), equalTo(1) );
+        Male male = query.find();
+        assertThat( male.title().get(), equalTo( Person.Title.MR ));
+        assertThat( male.name().get(), equalTo( "Joe Doe" ));
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/indexing/layered/Suite1Case2.java b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/layered/Suite1Case2.java
new file mode 100644
index 0000000..6c54831
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/layered/Suite1Case2.java
@@ -0,0 +1,76 @@
+/*
+ *  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.polygene.test.indexing.layered;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.query.QueryExpressions;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation;
+import org.apache.polygene.test.model.Male;
+import org.apache.polygene.test.model.Person;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class Suite1Case2
+    implements TestCase
+{
+    @Structure
+    private UnitOfWorkFactory uowf;
+
+    @Structure
+    private QueryBuilderFactory qbf;
+
+    private QueryBuilder<Male> builder;
+
+    private Query<Male> query;
+
+    @Override
+    public void given()
+        throws Exception
+    {
+        QueryBuilder<Male> qb = qbf.newQueryBuilder( Male.class );
+        Male prototype = QueryExpressions.templateFor( Male.class );
+        builder = qb.where( QueryExpressions.eq(prototype.name(), "Joe Doe" ) );
+    }
+
+    @Override
+    @UnitOfWorkPropagation
+    public void when()
+        throws Exception
+    {
+        UnitOfWork uow = uowf.currentUnitOfWork();
+        query = uow.newQuery( builder );
+    }
+
+    @Override
+    public void expect()
+        throws Exception
+    {
+        assertThat( query.count(), equalTo(1) );
+        Male male = query.find();
+        assertThat( male.title().get(), equalTo( Person.Title.MR ));
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/indexing/layered/TestCase.java b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/layered/TestCase.java
new file mode 100644
index 0000000..70733b6
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/layered/TestCase.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.test.indexing.layered;
+
+public interface TestCase
+{
+    void given()
+        throws Exception;
+
+    void when()
+        throws Exception;
+
+    void expect()
+        throws Exception;
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/indexing/package.html b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/package.html
new file mode 100644
index 0000000..dc3d67a
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/indexing/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Index/Query SPI Test Support.</h2>
+    </body>
+</html>
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/metrics/AbstractPolygeneMetricsTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/metrics/AbstractPolygeneMetricsTest.java
new file mode 100644
index 0000000..98efb6a
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/metrics/AbstractPolygeneMetricsTest.java
@@ -0,0 +1,338 @@
+/*
+ *  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.polygene.test.metrics;
+
+import java.util.Collection;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.metrics.TimingCapture;
+import org.apache.polygene.api.metrics.TimingCaptureAllConcern;
+import org.apache.polygene.api.metrics.TimingCaptureConcern;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkConcern;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneBaseTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.util.JmxFixture;
+import org.junit.Test;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation.Propagation.MANDATORY;
+import static org.apache.polygene.api.usecase.UsecaseBuilder.newUsecase;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.StringContains.containsString;
+import static org.hamcrest.collection.IsIterableContainingInOrder .contains;
+import static org.junit.Assert.assertThat;
+
+// TODO Test errors
+public abstract class AbstractPolygeneMetricsTest extends AbstractPolygeneBaseTest
+{
+    public interface Person
+    {
+        Property<String> name();
+    }
+
+    public interface PersonList
+    {
+        Identity LIST_ID = StringIdentity.fromString( "person-list" );
+
+        ManyAssociation<Person> all();
+    }
+
+    @Concerns( { TimingCaptureAllConcern.class, UnitOfWorkConcern.class} )
+    @Mixins( CommandsMixin.class )
+    public interface Commands extends ServiceActivation
+    {
+        @UnitOfWorkPropagation( MANDATORY )
+        Person create( Identity id, String name );
+
+        @UnitOfWorkPropagation( MANDATORY )
+        void rename( Identity id, String newName );
+
+        @UnitOfWorkPropagation( MANDATORY )
+        void delete( Identity id );
+    }
+
+    public static class CommandsMixin implements Commands
+    {
+        @Structure
+        private Module module;
+
+        @Override
+        public void activateService() throws Exception
+        {
+            try (UnitOfWork uow = module.unitOfWorkFactory().newUnitOfWork( newUsecase( "Init Person List" ) ) )
+            {
+                try
+                {
+                    uow.get( PersonList.class, PersonList.LIST_ID );
+                }
+                catch( NoSuchEntityException ex )
+                {
+                    uow.newEntity( PersonList.class, PersonList.LIST_ID );
+                    uow.complete();
+                }
+            }
+        }
+
+        @Override
+        public void passivateService()
+        {
+        }
+
+        @Override
+        public Person create( Identity id, String name )
+        {
+            UnitOfWork uow = module.unitOfWorkFactory().currentUnitOfWork();
+            PersonList list = uow.get( PersonList.class, PersonList.LIST_ID );
+            EntityBuilder<Person> builder = uow.newEntityBuilder( Person.class, id );
+            builder.instance().name().set( name );
+            Person person = builder.newInstance();
+            list.all().add( person );
+            return person;
+        }
+
+        @Override
+        public void rename( Identity id, String newName )
+        {
+            module.unitOfWorkFactory().currentUnitOfWork().get( Person.class, id ).name().set( newName );
+        }
+
+        @Override
+        public void delete( Identity id )
+        {
+            UnitOfWork uow = module.unitOfWorkFactory().currentUnitOfWork();
+            PersonList list = uow.get( PersonList.class, PersonList.LIST_ID );
+            Person person = uow.get( Person.class, id );
+            list.all().remove( person );
+            uow.remove( person );
+        }
+    }
+
+    @Concerns( { TimingCaptureConcern.class, UnitOfWorkConcern.class} )
+    @Mixins( QueriesMixin.class )
+    public interface Queries
+    {
+        @UnitOfWorkPropagation( MANDATORY )
+        Person byId( Identity id );
+
+        @TimingCapture
+        @UnitOfWorkPropagation( MANDATORY )
+        Iterable<Person> all();
+    }
+
+    public static class QueriesMixin implements Queries
+    {
+        @Structure
+        private Module module;
+
+        @Override
+        public Person byId( Identity id )
+        {
+            return module.unitOfWorkFactory().currentUnitOfWork().get( Person.class, id );
+        }
+
+        @Override
+        public Iterable<Person> all()
+        {
+            return module.unitOfWorkFactory().currentUnitOfWork()
+                    .get( PersonList.class, PersonList.LIST_ID )
+                    .all().toList();
+        }
+    }
+
+    @Override
+    protected final void defineApplication( ApplicationAssembly app ) throws AssemblyException
+    {
+        app.setName( "app" );
+
+        LayerAssembly domain = app.layer( "domain" );
+        ModuleAssembly model = domain.module( "model" );
+        model.entities( Person.class, PersonList.class )
+                .visibleIn( Visibility.layer );
+        ModuleAssembly services = domain.module( "services" );
+        services.services( Commands.class, Queries.class )
+                .instantiateOnStartup()
+                .visibleIn( Visibility.application );
+
+        LayerAssembly config = app.layer( "config" );
+        ModuleAssembly configModule = config.module( "config" );
+        new EntityTestAssembler()
+                .visibleIn( Visibility.module )
+                .assemble( configModule );
+
+        LayerAssembly infra = app.layer( "infra" );
+        ModuleAssembly storage = infra.module( "storage" );
+        entityStoreAssembler( configModule, Visibility.application )
+                .visibleIn( Visibility.application )
+                .assemble( storage );
+        metricsAssembler()
+                .visibleIn( Visibility.application )
+                .assemble( infra.module( "metrics" ) );
+
+        domain.uses( infra );
+        infra.uses( config );
+    }
+
+    protected Assemblers.Visible<? extends Assembler> entityStoreAssembler( ModuleAssembly configModule, Visibility configVisibility ) throws AssemblyException
+    {
+        return new EntityTestAssembler();
+    }
+
+    protected abstract Assemblers.Visible<? extends Assembler> metricsAssembler();
+
+    protected Module metricsModule()
+    {
+        return application.findModule( "infra", "metrics" );
+    }
+
+    protected static final String UOW_TIMER_NAME = "app.domain.services.UnitOfWork.timer";
+    protected static final String ALL_NAME = "app.domain.services.AbstractPolygeneMetricsTest.Queries.all";
+    protected static final String CREATE_NAME = "app.domain.services.AbstractPolygeneMetricsTest.Commands.create";
+    protected static final String RENAME_NAME = "app.domain.services.AbstractPolygeneMetricsTest.Commands.rename";
+    protected static final String DELETE_NAME = "app.domain.services.AbstractPolygeneMetricsTest.Commands.delete";
+
+    protected final void assertUowTimer( MetricValuesProvider metrics ) throws PassivationException, ActivationException
+    {
+        Long initialUowCount = metrics.timerCount( UOW_TIMER_NAME );
+        runScenario1();
+        assertThat( UOW_TIMER_NAME + " count incremented by 3", metrics.timerCount( UOW_TIMER_NAME ), is( initialUowCount + 3L ) );
+        application.passivate();
+        application.activate();
+        assertThat( UOW_TIMER_NAME + " count reset on passivation", metrics.timerCount( UOW_TIMER_NAME ), equalTo( initialUowCount ) );
+    }
+
+    protected final void assertTimingCapture( MetricValuesProvider metrics ) throws PassivationException, ActivationException
+    {
+        // Initial state
+        assertThat( ALL_NAME + " count is 0 at start", metrics.timerCount( ALL_NAME ), is( 0L ) );
+        assertThat( CREATE_NAME + " count is 0 at start", metrics.timerCount( CREATE_NAME ), is( 0L ) );
+        assertThat( RENAME_NAME + " count is 0 at start", metrics.timerCount( RENAME_NAME ), is( 0L ) );
+        assertThat( DELETE_NAME+ " count is 0 at start", metrics.timerCount( DELETE_NAME ), is( 0L ) );
+
+        // Run scenario
+        runScenario1();
+
+        // Queries.byId() timings are not captured
+        assertThat( "Queries.byId() has no timer", metrics.registeredMetricNames(), not( contains( containsString( "byId" ) ) ) );
+
+        // Captured timings
+        assertThat( ALL_NAME + " count is 4 after scenario", metrics.timerCount( ALL_NAME ), is( 4L ) );
+        assertThat( CREATE_NAME + " count is 1 after scenario", metrics.timerCount( CREATE_NAME ), is( 1L ) );
+        assertThat( RENAME_NAME + " count is 1 after scenario", metrics.timerCount( RENAME_NAME ), is( 1L ) );
+        assertThat( DELETE_NAME + " count is 1 after scenario", metrics.timerCount( DELETE_NAME ), is( 1L ) );
+
+        // Reset on passivation
+        application.passivate();
+        application.activate();
+        assertThat( ALL_NAME + " count is 0 after restart", metrics.timerCount( ALL_NAME ), is( 0L ) );
+        assertThat( CREATE_NAME + " count is 0 after restart", metrics.timerCount( CREATE_NAME ), is( 0L ) );
+        assertThat( RENAME_NAME + " count is 0 after restart", metrics.timerCount( RENAME_NAME ), is( 0L ) );
+        assertThat( DELETE_NAME + " count is 0 after restart", metrics.timerCount( DELETE_NAME ), is( 0L ) );
+    }
+
+    protected final void runScenario1()
+    {
+        Module services = application.findModule( "domain", "services" );
+        Commands commands = services.findService( Commands.class ).get();
+        Queries queries = services.findService( Queries.class ).get();
+
+        Identity identity = StringIdentity.fromString( "1" );
+
+        try (UnitOfWork uow = services.unitOfWorkFactory().newUnitOfWork( newUsecase( "Step 1" ) ) )
+        {
+            assertThat( queries.all().iterator().hasNext(), is( false ) );
+            assertThat( commands.create( identity, "Bob Geldof" ).name().get(), equalTo( "Bob Geldof" ) );
+            assertThat( queries.byId( identity ).name().get(), equalTo( "Bob Geldof" ) );
+            uow.complete();
+        }
+
+        try (UnitOfWork uow = services.unitOfWorkFactory().newUnitOfWork(newUsecase("Step 2")))
+        {
+            assertThat( queries.all().iterator().next().name().get(), equalTo( "Bob Geldof" ) );
+            assertThat( queries.byId( identity ).name().get(), equalTo( "Bob Geldof" ) );
+            commands.rename( identity, "Nina Hagen" );
+            assertThat( queries.all().iterator().next().name().get(), equalTo( "Nina Hagen" ) );
+            uow.complete();
+        }
+
+        try (UnitOfWork uow = services.unitOfWorkFactory().newUnitOfWork(newUsecase("Step 3")))
+        {
+            commands.delete( identity );
+            assertThat( queries.all().iterator().hasNext(), is( false ) );
+            uow.complete();
+        }
+    }
+
+    protected static class JmxMetricTestAdapter implements MetricValuesProvider
+    {
+        private final JmxFixture jmx = new JmxFixture( "metrics:name=" );
+
+        @Override
+        public long timerCount( String name )
+        {
+            if( jmx.objectExists( name ) ) {
+                return jmx.attributeValue( name, "Count", Long.class );
+            }
+            return 0L;
+        }
+
+        @Override
+        public Collection<String> registeredMetricNames()
+        {
+            return jmx.allObjectNames().stream()
+                    .filter( objName -> objName.startsWith( jmx.prefix() ) )
+                    .map( objName -> objName.substring( jmx.prefix().length() ) )
+                    .collect( toList() );
+        }
+    }
+
+    @Test
+    public void uowTimerJmx() throws PassivationException, ActivationException
+    {
+        assertUowTimer( new JmxMetricTestAdapter() );
+    }
+
+    @Test
+    public void timingCaptureJmx() throws PassivationException, ActivationException
+    {
+        assertTimingCapture( new JmxMetricTestAdapter() );
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/metrics/AbstractTimingCaptureTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/metrics/AbstractTimingCaptureTest.java
new file mode 100644
index 0000000..4b25622
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/metrics/AbstractTimingCaptureTest.java
@@ -0,0 +1,149 @@
+/*
+ *  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.polygene.test.metrics;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.metrics.TimingCapture;
+import org.apache.polygene.api.metrics.TimingCaptureAllConcern;
+import org.apache.polygene.api.metrics.TimingCaptureConcern;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+public abstract class AbstractTimingCaptureTest extends AbstractPolygeneTest
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.layer().application().setName( "SomeApplication" );
+        module.transients( Country1.class );
+        module.transients( Country2.class ).withConcerns( TimingCaptureAllConcern.class );
+        module.transients( Country3.class ).withConcerns( TimingCaptureConcern.class );
+        metricsAssembler().assemble( module );
+    }
+
+    protected abstract Assemblers.Visible<? extends Assembler> metricsAssembler();
+
+    protected abstract MetricValuesProvider metricValuesProvider();
+
+    @Test
+    public void givenNonInstrumentedCompositeExpectNoTimers()
+    {
+        Country underTest = transientBuilderFactory.newTransient( Country1.class );
+        updateName( underTest, 10 );
+        assertThat( metricValuesProvider().timerCount( "Layer 1.Module 1.AbstractTimingCaptureTest.Country.name" ), is( 0L ) );
+        assertThat( metricValuesProvider().timerCount( "Layer 1.Module 1.AbstractTimingCaptureTest.Country.updateName" ), is( 0L ) );
+    }
+
+    @Test
+    public void givenInstrumentedWithAllCompositeWhenCallingUpdateNameExpectTimers()
+    {
+        Country underTest = transientBuilderFactory.newTransient( Country2.class );
+        updateName( underTest, 10 );
+        assertThat( metricValuesProvider().timerCount( "Layer 1.Module 1.AbstractTimingCaptureTest.Country.name" ), is( 10L ) );
+        assertThat( metricValuesProvider().timerCount( "Layer 1.Module 1.AbstractTimingCaptureTest.Country.updateName" ), is( 10L ) );
+    }
+
+    @Test
+    public void givenOneMethodAnnotatedWhenCallingUpdateNameExpectTimerForThatMethodOnly()
+    {
+        Country underTest = transientBuilderFactory.newTransient( Country3.class );
+        updateName( underTest, 10 );
+        assertThat( metricValuesProvider().timerCount( "Layer 1.Module 1.AbstractTimingCaptureTest.Country.name" ), is( 0L ) );
+        assertThat( metricValuesProvider().timerCount( "Country3.updateName" ), is( 10L ) );
+    }
+
+    private void updateName( Country underTest, int times )
+    {
+        for( int i = 0; i < times; i++ )
+        {
+            underTest.updateName( "Name" + i );
+        }
+    }
+
+    // START SNIPPET: complex-capture
+    public interface Country extends TransientComposite
+    {
+        @Optional
+        Property<String> name();
+
+        void updateName( String newName );
+    }
+
+    @Mixins( Country1Mixin.class )
+    public interface Country1 extends Country
+    {
+    }
+
+    public static abstract class Country1Mixin
+        implements Country1
+    {
+        @Override
+        public void updateName( String newName )
+        {
+            name().set( newName );
+        }
+    }
+
+    @Mixins( Country2Mixin.class )
+    public interface Country2 extends Country
+    {
+    }
+
+    public static abstract class Country2Mixin
+        implements Country2
+    {
+        @Override
+        public void updateName( String newName )
+        {
+            name().set( newName );
+        }
+    }
+
+    @Mixins( Country3Mixin.class )
+    public interface Country3 extends Country
+    {
+        @TimingCapture( "Country3.updateName" )
+        @Override
+        void updateName( String newName );
+    }
+
+    public static abstract class Country3Mixin
+        implements Country3
+    {
+        @Override
+        public void updateName( String newName )
+        {
+            name().set( newName );
+        }
+    }
+    // END SNIPPET: complex-capture
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/metrics/MetricValuesProvider.java b/core/testsupport/src/main/java/org/apache/polygene/test/metrics/MetricValuesProvider.java
new file mode 100644
index 0000000..5c4c7dc
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/metrics/MetricValuesProvider.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.test.metrics;
+
+import java.util.Collection;
+
+/**
+ * Metrics values provider.
+ */
+public interface MetricValuesProvider
+{
+    /**
+     * All registered metrics names.
+     *
+     * @return All registered metrics names
+     */
+    Collection<String> registeredMetricNames();
+
+    /**
+     * Timer count.
+     * <p>
+     * Should not throw.
+     * Must return {@literal 0} if the timer does not exist.
+     *
+     * @param name Timer name
+     * @return Timer count
+     */
+    long timerCount( String name );
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/mock/MockComposite.java b/core/testsupport/src/main/java/org/apache/polygene/test/mock/MockComposite.java
new file mode 100644
index 0000000..ccc155a
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/mock/MockComposite.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.test.mock;
+
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.test.mock.internal.MockRecorderMixin;
+
+/**
+ * A mocked composite. Adds {@link org.apache.polygene.test.mock.MockRecorder} to the mocked composite.
+ */
+@Mixins( { MockRecorderMixin.class } )
+public interface MockComposite
+    extends MockRecorder, TransientComposite
+{
+}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/mock/MockPlayerConcern.java b/core/testsupport/src/main/java/org/apache/polygene/test/mock/MockPlayerConcern.java
new file mode 100644
index 0000000..bf96f9a
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/mock/MockPlayerConcern.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.test.mock;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.concern.ConcernOf;
+
+public class MockPlayerConcern
+    extends ConcernOf<InvocationHandler>
+    implements InvocationHandler
+{
+    /**
+     * @see java.lang.reflect.InvocationHandler#invoke(Object, java.lang.reflect.Method, Object[])
+     */
+    @Override
+    public Object invoke( final Object proxy, final Method method, final Object[] args )
+        throws Throwable
+    {
+        // TODO implementation
+        throw new UnsupportedOperationException( "MockResolver player concern is not yet implemented" );
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/mock/MockPlayerMixin.java b/core/testsupport/src/main/java/org/apache/polygene/test/mock/MockPlayerMixin.java
new file mode 100644
index 0000000..42b3111
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/mock/MockPlayerMixin.java
@@ -0,0 +1,67 @@
+/*
+ *  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.polygene.test.mock;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.test.mock.internal.MockRepository;
+import org.apache.polygene.test.mock.internal.MockResolver;
+
+/**
+ * Generic mixin for mock composites. Overrides any generic mixins but not typed mixins, as typed mixins have precedence
+ * over generic mixins. To override a typed mixin {@link org.apache.polygene.test.mock.MockPlayerConcern} can be used.
+ * MockResolver player mixin will delegate method invocations to registered mocks. Mocks can be registered by using
+ * {@link org.apache.polygene.test.mock.MockComposite}.
+ * If there is no mock registered to handle the method invocation invocation will fail by throwing an
+ * IllegalStateException.
+ */
+public class MockPlayerMixin
+    implements InvocationHandler
+{
+
+    /**
+     * MockResolver repository. Holds all registred mocks.
+     */
+    @This
+    MockRepository mockRepository;
+
+    /**
+     * Finds a registered mock that can handle the method invocation and delegate to it. If there is no such mock throws
+     * IllegalStateException.
+     *
+     * @see java.lang.reflect.InvocationHandler#invoke(Object, java.lang.reflect.Method, Object[])
+     */
+    @Override
+    public Object invoke( final Object proxy, final Method method, final Object[] args )
+        throws Throwable
+    {
+        System.out.println( "Play mock for " + method );
+        for( MockResolver mockResolver : mockRepository.getAll() )
+        {
+            InvocationHandler handler = mockResolver.getInvocationHandler( proxy, method, args );
+            if( handler != null )
+            {
+                return handler.invoke( mockResolver, method, args );
+            }
+        }
+        throw new IllegalStateException( "There is no mock registered that can handle " + method );
+    }
+}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/mock/MockRecorder.java b/core/testsupport/src/main/java/org/apache/polygene/test/mock/MockRecorder.java
new file mode 100644
index 0000000..6a22349
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/mock/MockRecorder.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.test.mock;
+
+public interface MockRecorder
+{
+    MockResolverType useMock( Object mock );
+}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/mock/MockResolverType.java b/core/testsupport/src/main/java/org/apache/polygene/test/mock/MockResolverType.java
new file mode 100644
index 0000000..309a3d7
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/mock/MockResolverType.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.test.mock;
+
+public interface MockResolverType
+{
+    void forClass( Class clazz );
+}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MethodClassMatcherMockResolver.java b/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MethodClassMatcherMockResolver.java
new file mode 100644
index 0000000..ff57bff
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MethodClassMatcherMockResolver.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.test.mock.internal;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+public class MethodClassMatcherMockResolver
+    implements MockResolver, InvocationHandler
+{
+
+    private final Object recordedMock;
+    private final Class methodClass;
+
+    public MethodClassMatcherMockResolver( Object recordedMock, Class methodClass )
+    {
+        this.recordedMock = recordedMock;
+        this.methodClass = methodClass;
+    }
+
+    @Override
+    public InvocationHandler getInvocationHandler( Object proxy, Method method, Object[] args )
+    {
+        if( method.getDeclaringClass().equals( methodClass ) )
+        {
+            return this;
+        }
+        return null;
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        return method.invoke( recordedMock, args );
+    }
+}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MockRecorderMixin.java b/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MockRecorderMixin.java
new file mode 100644
index 0000000..e0a17d2
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MockRecorderMixin.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.test.mock.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import org.apache.polygene.test.mock.MockRecorder;
+import org.apache.polygene.test.mock.MockResolverType;
+
+public class MockRecorderMixin
+    implements MockRecorder, MockRepository
+{
+
+    private final Collection<MockResolver> mockResolvers;
+
+    public MockRecorderMixin()
+    {
+        this.mockResolvers = new ArrayList<MockResolver>();
+    }
+
+    public MockResolverType useMock( Object mock )
+    {
+        System.out.println( "Recorded " + mock );
+        MockResolverProxy proxy = new MockResolverProxy( mock, new UnresolvableMockResolver() );
+        add( proxy );
+        return new MockResolverTypeImpl( proxy );
+    }
+
+    public void add( MockResolver mockResolver )
+    {
+        mockResolvers.add( mockResolver );
+    }
+
+    public Iterable<MockResolver> getAll()
+    {
+        return mockResolvers;
+    }
+}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MockRepository.java b/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MockRepository.java
new file mode 100644
index 0000000..228762d
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MockRepository.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.test.mock.internal;
+
+public interface MockRepository
+{
+    void add( MockResolver mockResolver );
+
+    Iterable<MockResolver> getAll();
+}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MockResolver.java b/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MockResolver.java
new file mode 100644
index 0000000..b339e49
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MockResolver.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.test.mock.internal;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * Resolves the invocation handler for a registered mock. Actual matching method is specific to each implementation.
+ */
+public interface MockResolver
+{
+    /**
+     * Matches the method invocation to an invocation handler for a registered mock.
+     *
+     * @param proxy  object on which the method was invoked
+     * @param method invoked method
+     * @param args   invocation arguments
+     *
+     * @return invocation handler if this resolved can handle the call or null otherwise.
+     */
+    InvocationHandler getInvocationHandler( Object proxy, Method method, Object[] args );
+}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MockResolverProxy.java b/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MockResolverProxy.java
new file mode 100644
index 0000000..d4d75b9
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MockResolverProxy.java
@@ -0,0 +1,95 @@
+/*
+ *  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.polygene.test.mock.internal;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.Objects;
+
+/**
+ * Proxy to another mock resolver that can be set/changed over time. This allows
+ * {@link org.apache.polygene.test.mock.MockResolverType} to change the mock resolver for a mock.
+ */
+public class MockResolverProxy
+    implements MockResolver
+{
+    /**
+     * Registered mock. Cannot be null.
+     */
+    private final Object registeredMock;
+    /**
+     * Mock resolver delegate. Cannot be null.
+     */
+    private MockResolver mockResolver;
+
+    /**
+     * Constructor.
+     *
+     * @param registeredMock registered mock; cannot be null
+     * @param mockResolver   mock resolver delegate; cannot be null
+     *
+     * @throws NullPointerException - If registred mock is null
+     *                               - If mock resolver is null
+     */
+    MockResolverProxy( final Object registeredMock, final MockResolver mockResolver )
+    {
+        Objects.requireNonNull( registeredMock, "Registered mock" );
+        Objects.requireNonNull( mockResolver, "Mock resolver delegate" );
+        this.registeredMock = registeredMock;
+        this.mockResolver = mockResolver;
+    }
+
+    /**
+     * Setter.
+     *
+     * @param mockResolver mock resolver delegate; cannot be null
+     *
+     * @return itself
+     *
+     * @throws NullPointerException - If mock resolver is null
+     */
+    MockResolverProxy setMock( final MockResolver mockResolver )
+    {
+        Objects.requireNonNull( mockResolver, "Mock resolver delegate" );
+        this.mockResolver = mockResolver;
+        return this;
+    }
+
+    /**
+     * Getter.
+     *
+     * @return registered mock
+     */
+    public Object getRegisteredMock()
+    {
+        return registeredMock;
+    }
+
+    /**
+     * Delegates to current mock resolver delegate.
+     *
+     * @see MockResolver#getInvocationHandler(Object, java.lang.reflect.Method, Object[])
+     */
+    @Override
+    public InvocationHandler getInvocationHandler( final Object proxy, final Method method, final Object[] args )
+    {
+        return mockResolver.getInvocationHandler( proxy, method, args );
+    }
+}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MockResolverTypeImpl.java b/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MockResolverTypeImpl.java
new file mode 100644
index 0000000..228f8d6
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/MockResolverTypeImpl.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.test.mock.internal;
+
+import org.apache.polygene.test.mock.MockResolverType;
+
+public class MockResolverTypeImpl
+    implements MockResolverType
+{
+    private final MockResolverProxy proxy;
+
+    public MockResolverTypeImpl( MockResolverProxy proxy )
+    {
+        this.proxy = proxy;
+    }
+
+    @Override
+    public void forClass( final Class clazz )
+    {
+        proxy.setMock( new MethodClassMatcherMockResolver( proxy.getRegisteredMock(), clazz ) );
+    }
+}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/UnresolvableMockResolver.java b/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/UnresolvableMockResolver.java
new file mode 100644
index 0000000..aa97fb0
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/UnresolvableMockResolver.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.test.mock.internal;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * Placeholder for a not specified resolver type.
+ */
+public class UnresolvableMockResolver
+    implements MockResolver
+{
+    /**
+     * Does not match any method invocation. Always returns null.
+     *
+     * @see MockResolver#getInvocationHandler(Object, java.lang.reflect.Method, Object[])
+     */
+    @Override
+    public InvocationHandler getInvocationHandler( final Object proxy, final Method method, final Object[] args )
+    {
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/package.html b/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/package.html
new file mode 100644
index 0000000..13e4f38
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/mock/internal/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Test Support Composites Mocking Internal/Private package.</h2>
+    </body>
+</html>
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/mock/package.html b/core/testsupport/src/main/java/org/apache/polygene/test/mock/package.html
new file mode 100644
index 0000000..838048c
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/mock/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Test Support Composites Mocking.</h2>
+    </body>
+</html>
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/Account.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/Account.java
new file mode 100644
index 0000000..c77ea1f
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/Account.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.test.model;
+
+import org.apache.polygene.api.property.Property;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+public interface Account
+{
+    Property<String> number();
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/Address.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/Address.java
new file mode 100644
index 0000000..3a24972
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/Address.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.test.model;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+public interface Address extends ValueComposite // necessary, @See POLYGENE-137
+{
+    Property<String> line1();
+
+    Property<String> line2();
+
+    Property<String> zipcode();
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/Alive.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/Alive.java
new file mode 100644
index 0000000..f8dbf25
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/Alive.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.test.model;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+public interface Alive
+{
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/Cat.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/Cat.java
new file mode 100644
index 0000000..5d0aef9
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/Cat.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.test.model;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+public interface Cat extends Pet
+{
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/City.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/City.java
new file mode 100644
index 0000000..57c2aa9
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/City.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.test.model;
+
+import org.apache.polygene.api.property.Property;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+public interface City extends Nameable
+{
+    Property<String> country();
+
+    Property<String> county();
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/Dog.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/Dog.java
new file mode 100644
index 0000000..3448aa4
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/Dog.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.test.model;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+public interface Dog extends Pet
+{
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/Domain.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/Domain.java
new file mode 100644
index 0000000..09536d5
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/Domain.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.test.model;
+
+import org.apache.polygene.api.property.Property;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+public interface Domain extends Nameable
+{
+    Property<String> description();
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/Female.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/Female.java
new file mode 100644
index 0000000..dcffeec
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/Female.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.test.model;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.common.Optional;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+public interface Female extends Person
+{
+    @Optional
+    Association<Male> husband();
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/File.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/File.java
new file mode 100644
index 0000000..8897059
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/File.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.test.model;
+
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * JAVADOC Add JavaDoc.
+ */
+@Queryable( false )
+public interface File
+{
+    Property<String> value();
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/Host.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/Host.java
new file mode 100644
index 0000000..1da358d
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/Host.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.test.model;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * JAVADOC Add JavaDoc.
+ */
+public interface Host extends ValueComposite
+{
+    Property<String> value();
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/Male.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/Male.java
new file mode 100644
index 0000000..5a676e8
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/Male.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.test.model;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.common.Optional;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+public interface Male extends Person
+{
+    @Optional
+    Association<Female> wife();
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/Nameable.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/Nameable.java
new file mode 100644
index 0000000..43914ac
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/Nameable.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.test.model;
+
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+public interface Nameable extends HasIdentity
+{
+    Property<String> name();
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/Owner.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/Owner.java
new file mode 100644
index 0000000..a783955
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/Owner.java
@@ -0,0 +1,24 @@
+/*
+ *  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.polygene.test.model;
+
+public interface Owner extends Person
+{
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/Person.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/Person.java
new file mode 100644
index 0000000..7646928
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/Person.java
@@ -0,0 +1,99 @@
+/*
+ *  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.polygene.test.model;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZonedDateTime;
+import java.util.Map;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+public interface Person
+    extends Nameable, Alive
+{
+    enum Title
+    {
+        MR, MS, MRS, DR
+    }
+
+    Property<Title> title();
+
+    @Optional
+    Association<City> placeOfBirth();
+
+    Property<Integer> yearOfBirth();
+
+    @Optional
+    Property<Address> address();
+
+    @Optional
+    Association<Female> mother();
+
+    @Optional
+    Association<Male> father();
+
+    ManyAssociation<Domain> interests();
+
+    @Optional
+    Property<String> email();
+
+    @Optional
+    Property<URL> personalWebsite();
+
+    @Queryable( false )
+    Property<String> password();
+
+    @Optional
+    Association<Account> mainAccount();
+
+    NamedAssociation<Account> accounts();
+
+    @Optional
+    Property<Map<String, String>> additionalInfo();
+
+    @Optional
+    Property<BigInteger> bigInteger();
+
+    @Optional
+    Property<BigDecimal> bigDecimal();
+
+    @Optional
+    Property<Instant> instantValue();
+
+    @Optional
+    Property<ZonedDateTime> dateTimeValue();
+
+    @Optional
+    Property<LocalDateTime> localDateTimeValue();
+
+    @Optional
+    Property<LocalDate> localDateValue();
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/Pet.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/Pet.java
new file mode 100644
index 0000000..77839f9
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/Pet.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.test.model;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+public interface Pet
+    extends Nameable, Alive
+{
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/PetShop.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/PetShop.java
new file mode 100644
index 0000000..b50ad45
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/PetShop.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.test.model;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.property.Property;
+
+public interface PetShop
+{
+    Property<Address> address();
+    Association<City> city();
+    ManyAssociation<Owner> owners();
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/Port.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/Port.java
new file mode 100644
index 0000000..f0f6bd7
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/Port.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.test.model;
+
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * JAVADOC Add JavaDoc.
+ */
+public interface Port
+{
+    @Queryable( false )
+    Property<Integer> value();
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/Protocol.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/Protocol.java
new file mode 100644
index 0000000..d05c6db
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/Protocol.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.test.model;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * JAVADOC Add JavaDoc.
+ */
+public interface Protocol extends ValueComposite
+{
+    Property<String> value();
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/QueryParam.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/QueryParam.java
new file mode 100644
index 0000000..c079f75
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/QueryParam.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.test.model;
+
+import org.apache.polygene.api.property.Property;
+
+/**
+ * JAVADOC Add JavaDoc.
+ */
+public interface QueryParam
+{
+    Property<String> name();
+
+    Property<String> value();
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/Staff.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/Staff.java
new file mode 100644
index 0000000..c41b0f4
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/Staff.java
@@ -0,0 +1,24 @@
+/*
+ *  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.polygene.test.model;
+
+public interface Staff extends Person
+{
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/URL.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/URL.java
new file mode 100644
index 0000000..e30e565
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/URL.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.test.model;
+
+import java.util.Collection;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * JAVADOC Add JavaDoc.
+ */
+public interface URL extends ValueComposite
+{
+    Property<Protocol> protocol();
+
+    @Optional
+    @Queryable( false )
+    Property<Host> host();
+
+    @Optional
+    Property<Port> port();
+
+    @Optional
+    Property<File> file();
+
+    @Optional
+    Property<Collection<QueryParam>> queryParams();
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/AccessLayer.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/AccessLayer.java
new file mode 100644
index 0000000..045b621
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/AccessLayer.java
@@ -0,0 +1,65 @@
+/*
+ *  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.polygene.test.model.assembly;
+
+import java.lang.reflect.InvocationTargetException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.layered.LayeredLayerAssembler;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+
+class AccessLayer extends LayeredLayerAssembler
+{
+
+    private final Class<?> testClass;
+
+    AccessLayer( Class<?> testClass )
+    {
+        this.testClass = testClass;
+    }
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        createModule( layer, TestExecutionModule.class );
+        createModule( layer, TestSuite1Module.class );
+        createModule( layer, TestSuite2Module.class );
+        createModule( layer, TestSuite3Module.class );
+        return layer;
+    }
+
+    @Override
+    protected ModuleAssembler instantiateAssembler( LayerAssembly layer,
+                                                    Class<? extends ModuleAssembler> moduleAssemblerClass
+    )
+        throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException
+    {
+        if( moduleAssemblerClass.equals(TestExecutionModule.class))
+        {
+            return new TestExecutionModule( testClass );
+        }
+        else
+        {
+            return super.instantiateAssembler( layer, moduleAssemblerClass );
+        }
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/AccountModule.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/AccountModule.java
new file mode 100644
index 0000000..eec1885
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/AccountModule.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.test.model.assembly;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.test.model.Account;
+import org.apache.polygene.test.model.Domain;
+import org.apache.polygene.test.model.File;
+import org.apache.polygene.test.model.Host;
+import org.apache.polygene.test.model.Port;
+import org.apache.polygene.test.model.Protocol;
+import org.apache.polygene.test.model.QueryParam;
+import org.apache.polygene.test.model.URL;
+
+class AccountModule
+    implements ModuleAssembler
+{
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( Account.class, Domain.class ).visibleIn( Visibility.layer );
+        module.values( File.class, Host.class, Port.class, Protocol.class, QueryParam.class, URL.class )
+            .visibleIn( Visibility.layer );
+        return module;
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/ApplicationAssembler.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/ApplicationAssembler.java
new file mode 100644
index 0000000..e793455
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/ApplicationAssembler.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.test.model.assembly;
+
+import java.lang.reflect.InvocationTargetException;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.layered.IllegalLayerAssemblerException;
+import org.apache.polygene.bootstrap.layered.LayerAssembler;
+import org.apache.polygene.bootstrap.layered.LayeredApplicationAssembler;
+
+public class ApplicationAssembler extends LayeredApplicationAssembler
+{
+
+    private final Class<?> testClass;
+
+    public ApplicationAssembler( String name, String version, Application.Mode mode, Class<?> testClass )
+        throws AssemblyException
+    {
+        super( name, version, mode );
+        this.testClass = testClass;
+    }
+
+    @Override
+    protected void assembleLayers( ApplicationAssembly assembly )
+        throws AssemblyException
+    {
+        LayerAssembly accessLayer = createLayer( AccessLayer.class );
+        LayerAssembly domainLayer = createLayer( DomainLayer.class );
+        LayerAssembly persistenceLayer = createLayer( PersistenceLayer.class );
+        LayerAssembly indexingLayer = createLayer( IndexingLayer.class );
+        LayerAssembly configLayer = createLayer( ConfigLayer.class );
+        accessLayer.uses( domainLayer );
+        domainLayer.uses( persistenceLayer, indexingLayer );
+        persistenceLayer.uses( configLayer );
+        indexingLayer.uses( configLayer );
+    }
+
+    @Override
+    protected <T extends LayerAssembler> LayerAssembler instantiateLayerAssembler( Class<T> layerAssemblerClass,
+                                                                                   LayerAssembly layer
+    )
+        throws InstantiationException, IllegalAccessException, InvocationTargetException, IllegalLayerAssemblerException
+    {
+        if( layerAssemblerClass.equals( AccessLayer.class ))
+        {
+            return new AccessLayer( testClass );
+        }
+        return super.instantiateLayerAssembler( layerAssemblerClass, layer );
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/ConfigLayer.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/ConfigLayer.java
new file mode 100644
index 0000000..2413ea3
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/ConfigLayer.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.test.model.assembly;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.layered.LayeredLayerAssembler;
+
+class ConfigLayer extends LayeredLayerAssembler
+{
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        createModule( layer, ConfigModule.class );
+        return layer;
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/ConfigModule.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/ConfigModule.java
new file mode 100644
index 0000000..6c7c52e
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/ConfigModule.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.test.model.assembly;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+
+class ConfigModule
+    implements ModuleAssembler
+{
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( MemoryEntityStoreService.class ).visibleIn( Visibility.application );
+        return module;
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/DomainLayer.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/DomainLayer.java
new file mode 100644
index 0000000..3754fd8
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/DomainLayer.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.test.model.assembly;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.layered.LayeredLayerAssembler;
+
+class DomainLayer extends LayeredLayerAssembler
+{
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        createModule( layer, PetShopModule.class );
+        createModule( layer, FamilyModule.class );
+        createModule( layer, AccountModule.class );
+        return layer;
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/FamilyModule.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/FamilyModule.java
new file mode 100644
index 0000000..42054a7
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/FamilyModule.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.polygene.test.model.assembly;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.test.model.Address;
+import org.apache.polygene.test.model.Cat;
+import org.apache.polygene.test.model.City;
+import org.apache.polygene.test.model.Dog;
+import org.apache.polygene.test.model.Female;
+import org.apache.polygene.test.model.Male;
+
+class FamilyModule
+    implements ModuleAssembler
+{
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( Male.class,
+                         Female.class,
+                         City.class,
+                         Cat.class,
+                         Dog.class ).visibleIn( Visibility.application );
+
+        module.values( Address.class ).visibleIn( Visibility.application );
+        return module;
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/IndexingLayer.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/IndexingLayer.java
new file mode 100644
index 0000000..b0b5b87
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/IndexingLayer.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.test.model.assembly;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.layered.LayeredLayerAssembler;
+import org.apache.polygene.test.indexing.layered.AbstractMultiLayeredIndexingTest;
+
+class IndexingLayer extends LayeredLayerAssembler
+{
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        createModule( layer, AbstractMultiLayeredIndexingTest.indexingAssembler );
+        return layer;
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/PersistenceLayer.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/PersistenceLayer.java
new file mode 100644
index 0000000..26e69ab
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/PersistenceLayer.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.test.model.assembly;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.layered.LayeredLayerAssembler;
+
+class PersistenceLayer extends LayeredLayerAssembler
+{
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        createModule( layer, PersistenceModule.class );
+        return layer;
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/PersistenceModule.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/PersistenceModule.java
new file mode 100644
index 0000000..202c640
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/PersistenceModule.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.test.model.assembly;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+
+class PersistenceModule
+    implements ModuleAssembler
+{
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( MemoryEntityStoreService.class ).visibleIn( Visibility.application );
+        return module;
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/PetShopModule.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/PetShopModule.java
new file mode 100644
index 0000000..40fae45
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/PetShopModule.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.test.model.assembly;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.test.model.Address;
+import org.apache.polygene.test.model.Cat;
+import org.apache.polygene.test.model.City;
+import org.apache.polygene.test.model.Dog;
+import org.apache.polygene.test.model.Owner;
+import org.apache.polygene.test.model.Staff;
+
+class PetShopModule
+    implements ModuleAssembler
+{
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( Owner.class,
+                         Staff.class );
+        module.entities( City.class,
+                         Cat.class,
+                         Dog.class );
+
+        module.values( Address.class );
+        return module;
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/TestExecutionModule.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/TestExecutionModule.java
new file mode 100644
index 0000000..09dd396
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/TestExecutionModule.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.test.model.assembly;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+
+public class TestExecutionModule
+    implements ModuleAssembler
+{
+    private final Class<?> testClass;
+
+    public TestExecutionModule( Class<?> testClass)
+    {
+        this.testClass = testClass;
+    }
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.objects( testClass ).visibleIn( Visibility.layer );
+        return module;
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/TestSuite1Module.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/TestSuite1Module.java
new file mode 100644
index 0000000..ff2fa08
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/TestSuite1Module.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.test.model.assembly;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.test.indexing.layered.Suite1Case1;
+import org.apache.polygene.test.indexing.layered.Suite1Case2;
+import org.apache.polygene.test.indexing.layered.TestCase;
+
+class TestSuite1Module
+    implements ModuleAssembler
+{
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        declareTestCase( module, Suite1Case1.class );
+        declareTestCase( module, Suite1Case2.class );
+        return module;
+    }
+
+    private void declareTestCase( ModuleAssembly module, Class<?> testcaseMixin )
+    {
+        module.services( TestCase.class )
+            .withMixins( testcaseMixin )
+            .visibleIn( Visibility.layer )
+            .taggedWith( testcaseMixin.getSimpleName() );
+
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/TestSuite2Module.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/TestSuite2Module.java
new file mode 100644
index 0000000..cae05ac
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/TestSuite2Module.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.test.model.assembly;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+
+class TestSuite2Module
+    implements ModuleAssembler
+{
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        return module;
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/TestSuite3Module.java b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/TestSuite3Module.java
new file mode 100644
index 0000000..369cbba
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/assembly/TestSuite3Module.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.test.model.assembly;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+
+class TestSuite3Module
+    implements ModuleAssembler
+{
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        return module;
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/model/package.html b/core/testsupport/src/main/java/org/apache/polygene/test/model/package.html
new file mode 100644
index 0000000..f006a94
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/model/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Index/Query SPI Test Support - Model.</h2>
+    </body>
+</html>
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/package.html b/core/testsupport/src/main/java/org/apache/polygene/test/package.html
new file mode 100644
index 0000000..833d340
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Apache Polygene™ Test Support.</h2>
+    </body>
+</html>
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractCollectionSerializationTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractCollectionSerializationTest.java
new file mode 100644
index 0000000..a78c3fa
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractCollectionSerializationTest.java
@@ -0,0 +1,481 @@
+/*
+ *  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.polygene.test.serialization;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.type.CollectionType;
+import org.apache.polygene.api.type.EnumType;
+import org.apache.polygene.api.type.MapType;
+import org.apache.polygene.api.type.ValueCompositeType;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Assert that Serialization behaviour on Collections and Maps is correct.
+ */
+public class AbstractCollectionSerializationTest
+    extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.values( SomeValue.class );
+    }
+
+    @Service
+    @SuppressWarnings( "ProtectedField" )
+    protected Serialization serialization;
+
+    @Test
+    public void givenPrimitiveArrayWithIntsWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        int[] primitiveArray = new int[]
+            {
+                23, 42, -23, -42
+            };
+        String output = serialization.serialize( primitiveArray );
+        System.out.println( output );
+        int[] deserialized = serialization.deserialize( module, int[].class, output );
+        assertArrayEquals( primitiveArray, deserialized );
+    }
+
+    @Test
+    public void givenArrayWithByteAndNullElementWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        Byte[] array = new Byte[]
+            {
+                9, null, -12, -12, 127, -128, 73
+            };
+        String output = serialization.serialize( array );
+        System.out.println( output );
+        Byte[] deserialized = serialization.deserialize( module, Byte[].class, output );
+        assertArrayEquals( array, deserialized );
+    }
+
+    @Test
+    public void givenIterableTypeWithByteAndNullElementWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        String output = serialization.serialize( new AdHocIterable<>( byteCollection() ) );
+        System.out.println( output );
+        CollectionType collectionType = CollectionType.listOf( ValueType.BYTE );
+        List<Byte> list = serialization.deserialize( module, collectionType, output );
+        assertEquals( byteCollection(), list );
+    }
+
+    @Test
+    public void givenCollectionTypeWithByteAndNullElementWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        String output = serialization.serialize( byteCollection() );
+        System.out.println( output );
+        CollectionType collectionType = CollectionType.setOf( ValueType.BYTE );
+        Set<Byte> list = serialization.deserialize( module, collectionType, output );
+        assertEquals( new LinkedHashSet<>( byteCollection() ), list );
+    }
+
+    @Test
+    public void givenCollectionTypeWithCharacterAndNullElementWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        String output = serialization.serialize( characterCollection() );
+        System.out.println( output );
+        CollectionType collectionType = CollectionType.listOf( ValueType.CHARACTER );
+        List<Character> list = serialization.deserialize( module, collectionType, output );
+        assertEquals( characterCollection(), list );
+    }
+
+    @Test
+    public void givenCollectionTypeWithShortAndNullElementWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        String output = serialization.serialize( shortCollection() );
+        System.out.println( output );
+        CollectionType collectionType = CollectionType.listOf( ValueType.SHORT );
+        List<Short> list = serialization.deserialize( module, collectionType, output );
+        assertEquals( shortCollection(), list );
+    }
+
+    @Test
+    public void givenCollectionTypeWithIntegerAndNullElementWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        String output = serialization.serialize( integerCollection() );
+        System.out.println( output );
+        CollectionType collectionType = CollectionType.listOf( ValueType.INTEGER );
+        List<Integer> list = serialization.deserialize( module, collectionType, output );
+        assertEquals( integerCollection(), list );
+    }
+
+    @Test
+    public void givenCollectionTypeWithLongAndNullElementWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        String output = serialization.serialize( longCollection() );
+        System.out.println( output );
+        CollectionType collectionType = CollectionType.listOf( ValueType.LONG );
+        List<Long> list = serialization.deserialize( module, collectionType, output );
+        assertEquals( longCollection(), list );
+    }
+
+    @Test
+    public void givenCollectionTypeWithFloatAndNullElementWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        String output = serialization.serialize( floatCollection() );
+        System.out.println( output );
+        CollectionType collectionType = CollectionType.listOf( ValueType.FLOAT );
+        List<Float> list = serialization.deserialize( module, collectionType, output );
+        assertEquals( floatCollection(), list );
+    }
+
+    @Test
+    public void givenCollectionTypeWithDoubleAndNullElementWhenSerializingExpectCorrectJsonOutput()
+        throws Exception
+    {
+        String output = serialization.serialize( doubleCollection() );
+        System.out.println( output );
+        CollectionType collectionType = CollectionType.listOf( ValueType.DOUBLE );
+        List<Double> list = serialization.deserialize( module, collectionType, output );
+        assertEquals( doubleCollection(), list );
+    }
+
+    @Test
+    public void givenCollectionTypeWithBigIntegerAndNullElementWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        String output = serialization.serialize( bigIntegerCollection() );
+        System.out.println( output );
+        CollectionType collectionType = CollectionType.listOf( ValueType.BIG_INTEGER );
+        List<BigInteger> list = serialization.deserialize( module, collectionType, output );
+        assertEquals( bigIntegerCollection(), list );
+    }
+
+    @Test
+    public void givenCollectionTypeWithBigDecimalAndNullElementWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        String output = serialization.serialize( bigDecimalCollection() );
+        System.out.println( output );
+        CollectionType collectionType = CollectionType.collectionOf( ValueType.BIG_DECIMAL );
+        Collection<BigDecimal> collection = serialization.deserialize( module, collectionType, output );
+        assertEquals( bigDecimalCollection(), collection );
+    }
+
+    @Test
+    public void givenMapOfStringByteAndNullElementWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        String output = serialization.serialize( stringByteMap() );
+        System.out.println( output );
+        MapType mapType = MapType.of( ValueType.STRING, ValueType.BYTE );
+        Map<String, Byte> value = serialization.deserialize( module, mapType, output );
+        assertEquals( stringByteMap(), value );
+    }
+
+    @Test
+    public void givenMapOfStringListStringAndNullElementWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        String output = serialization.serialize( stringMultiMap() );
+        System.out.println( output );
+        CollectionType collectionType = CollectionType.listOf( ValueType.STRING );
+        MapType mapType = MapType.of( ValueType.STRING, collectionType );
+        Map<String, List<String>> value = serialization.deserialize( module, mapType, output );
+        assertEquals( stringMultiMap(), value );
+    }
+
+    @Test
+    public void givenListOfMapStringStringAndNullElementWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        String output = serialization.serialize( stringListOfMaps() );
+        System.out.println( output );
+        CollectionType collectionType = CollectionType.listOf( MapType.of( ValueType.STRING, ValueType.STRING ) );
+        List<Map<String, String>> value = serialization.deserialize( module, collectionType, output );
+        assertEquals( stringListOfMaps(), value );
+    }
+
+    @Test
+    public void givenListOfValueCompositesAndNullElementWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        String output = serialization.serialize( valueCompositesList() );
+        System.out.println( output );
+        ValueCompositeType valueType = module.valueDescriptor( SomeValue.class.getName() ).valueType();
+        CollectionType collectionType = CollectionType.listOf( valueType );
+        List<SomeValue> value = serialization.deserialize( module, collectionType, output );
+        assertEquals( valueCompositesList(), value );
+    }
+
+    @Test
+    public void givenEnumSetWhenSerializingAndDeserializingExpectEquals()
+    {
+        Set<SomeEnum> enumSet = EnumSet.allOf( SomeEnum.class );
+        String output = serialization.serialize( enumSet );
+        System.out.println( output );
+        CollectionType valueType = CollectionType.setOf( EnumType.of( SomeEnum.class ) );
+        Set<SomeEnum> value = serialization.deserialize( module, valueType, output );
+        assertEquals( enumSet, value );
+    }
+
+    @Test
+    public void givenEnumMapWhenSerializingAndDeserializingExpectEquals()
+    {
+        EnumMap<SomeEnum, Number> enumMap = new EnumMap<>( SomeEnum.class );
+        for( SomeEnum value : SomeEnum.values() )
+        {
+            enumMap.put( value, 23 );
+        }
+        String output = serialization.serialize( enumMap );
+        System.out.println( output );
+        MapType valueType = MapType.of( EnumType.of( SomeEnum.class ), ValueType.of( Integer.class ) );
+        Map<SomeEnum, Number> value = serialization.deserialize( module, valueType, output );
+        assertEquals( enumMap, value );
+    }
+
+    private ArrayList<Byte> byteCollection()
+    {
+        ArrayList<Byte> value = new ArrayList<>();
+        value.add( (byte) 9 );
+        value.add( null );
+        value.add( (byte) -12 );
+        value.add( (byte) -12 );
+        value.add( (byte) 127 );
+        value.add( (byte) -128 );
+        value.add( (byte) 73 );
+        return value;
+    }
+
+    private List<Character> characterCollection()
+    {
+        List<Character> value = new ArrayList<>();
+        value.add( 'Q' );
+        value.add( 'i' );
+        value.add( null );
+        value.add( '4' );
+        value.add( 'j' );
+        return value;
+    }
+
+    private Collection<Short> shortCollection()
+    {
+        Collection<Short> value = new ArrayList<>();
+        value.add( (short) -32768 );
+        value.add( (short) 32767 );
+        value.add( (short) -82 );
+        value.add( null );
+        return value;
+    }
+
+    private Collection<Integer> integerCollection()
+    {
+        Collection<Integer> value = new ArrayList<>();
+        value.add( Integer.MAX_VALUE );
+        value.add( -283 );
+        value.add( null );
+        value.add( Integer.MIN_VALUE );
+        value.add( 238 );
+        return value;
+    }
+
+    private Collection<Long> longCollection()
+    {
+        Collection<Long> value = new ArrayList<>();
+        value.add( 98239723L );
+        value.add( -1298233L );
+        value.add( -1L );
+        value.add( 0L );
+        value.add( null );
+        value.add( 1L );
+        value.add( Long.MAX_VALUE );
+        value.add( Long.MIN_VALUE );
+        return value;
+    }
+
+    private Collection<Float> floatCollection()
+    {
+        Collection<Float> value = new ArrayList<>();
+        value.add( -1f );
+        value.add( 1f );
+        value.add( 1f );
+        value.add( 0f );
+        value.add( Float.MAX_VALUE );
+        value.add( Float.MIN_VALUE );
+        value.add( null );
+        value.add( 0.123456f );
+        value.add( -0.232321f );
+        return value;
+    }
+
+    private Collection<Double> doubleCollection()
+    {
+        Collection<Double> value = new ArrayList<>();
+        value.add( -1.0 );
+        value.add( 1.0 );
+        value.add( 0.0 );
+        value.add( Double.MAX_VALUE );
+        value.add( null );
+        value.add( Double.MIN_VALUE );
+        value.add( 0.123456 );
+        value.add( -0.232321 );
+        return value;
+    }
+
+    private Collection<BigInteger> bigIntegerCollection()
+    {
+        Collection<BigInteger> value = new ArrayList<>();
+        value.add( new BigInteger( "-1" ) );
+        value.add( BigInteger.ZERO );
+        value.add( BigInteger.ONE );
+        value.add( null );
+        value.add( BigInteger.TEN );
+        value.add( new BigInteger( "-1827368263823729372397239829332" ) );
+        value.add( new BigInteger( "2398723982982379827373972398723" ) );
+        return value;
+    }
+
+    private Collection<BigDecimal> bigDecimalCollection()
+    {
+        Collection<BigDecimal> value = new ArrayList<>();
+        value.add( new BigDecimal( "1.2" ) );
+        value.add( new BigDecimal( "3.4" ) );
+        value.add( null );
+        value.add( new BigDecimal( "5.6" ) );
+        return value;
+    }
+
+    private Map<String, Byte> stringByteMap()
+    {
+        Map<String, Byte> value = new LinkedHashMap<>();
+        value.put( "a", (byte) 9 );
+        value.put( "b", null );
+        value.put( "c", (byte) -12 );
+        return value;
+    }
+
+    private Map<String, List<String>> stringMultiMap()
+    {
+        Map<String, List<String>> value = new LinkedHashMap<>();
+        List<String> list = new ArrayList<>();
+        list.add( "foo" );
+        list.add( "bar" );
+        list.add( null );
+        list.add( "cathedral" );
+        list.add( "bazar" );
+        value.put( "alpha", list );
+        value.put( "beta", null );
+        value.put( "gamma", Collections.emptyList() );
+        return value;
+    }
+
+    private List<Map<String, String>> stringListOfMaps()
+    {
+        List<Map<String, String>> value = new ArrayList<>();
+        Map<String, String> map = new LinkedHashMap<>();
+        map.put( "foo", "bar" );
+        map.put( "cathedral", "bazar" );
+        map.put( "yield", null );
+        map.put( "42", "23" );
+        value.add( map );
+        value.add( null );
+        value.add( Collections.emptyMap() );
+        return value;
+    }
+
+    private List<SomeValue> valueCompositesList()
+    {
+        List<SomeValue> list = new ArrayList<>();
+        list.add( newSomeValue( "", "bazar" ) );
+        list.add( null );
+        list.add( newSomeValue( "bar", null ) );
+        return list;
+    }
+
+    public interface SomeValue
+    {
+        Property<String> foo();
+
+        @Optional
+        Property<String> cathedral();
+    }
+
+    private SomeValue newSomeValue( String foo, String cathedral )
+    {
+        ValueBuilder<SomeValue> builder = module.instance().newValueBuilder( SomeValue.class );
+        SomeValue value = builder.prototype();
+        value.foo().set( foo );
+        if( cathedral != null )
+        {
+            value.cathedral().set( cathedral );
+        }
+        return builder.newInstance();
+    }
+
+    private static class AdHocIterable<T> implements Iterable<T>
+    {
+        private final Iterable<T> delegate;
+
+        private AdHocIterable( Iterable<T> delegate )
+        {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public Iterator<T> iterator()
+        {
+            return delegate.iterator();
+        }
+    }
+
+    private enum SomeEnum
+    {
+        FOO,
+        BAR,
+        BAZAR,
+        CATHEDRAL
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractConvertersSerializationTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractConvertersSerializationTest.java
new file mode 100644
index 0000000..254196f
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractConvertersSerializationTest.java
@@ -0,0 +1,169 @@
+/*
+ *  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.polygene.test.serialization;
+
+import java.util.Objects;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.serialization.ConvertedBy;
+import org.apache.polygene.api.serialization.Converter;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+public abstract class AbstractConvertersSerializationTest extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        module.values( SomeValue.class );
+        module.forMixin( SomeValue.class )
+              .setMetaInfo( new CustomPropertyConverter() )
+              .declareDefaults()
+              .customAssemblyConvertedProperty();
+    }
+
+    protected abstract String getStringFromValueState( String state, String key ) throws Exception;
+
+    public interface SomeValue
+    {
+        Property<CustomPlainValue> customPlainValue();
+
+        @ConvertedBy( CustomPropertyConverter.class )
+        Property<String> customConvertedProperty();
+
+        Property<String> customAssemblyConvertedProperty();
+    }
+
+    @ConvertedBy( CustomPlainValueConverter.class )
+    public static class CustomPlainValue
+    {
+        private final String state;
+
+        CustomPlainValue( String state )
+        {
+            this.state = state;
+        }
+
+        public String getState()
+        {
+            return state;
+        }
+
+        @Override
+        public boolean equals( final Object o )
+        {
+            if( this == o ) { return true; }
+            if( o == null || getClass() != o.getClass() ) { return false; }
+            CustomPlainValue that = (CustomPlainValue) o;
+            return Objects.equals( state, that.state );
+        }
+
+        @Override
+        public int hashCode()
+        {
+            return Objects.hash( state );
+        }
+    }
+
+    public static class CustomPlainValueConverter implements Converter<CustomPlainValue>
+    {
+        @Override
+        public Class<CustomPlainValue> type()
+        {
+            return CustomPlainValue.class;
+        }
+
+        @Override
+        public String toString( CustomPlainValue object )
+        {
+            return rot13( object.getState() );
+        }
+
+        @Override
+        public CustomPlainValue fromString( String string )
+        {
+            return new CustomPlainValue( rot13( string ) );
+        }
+    }
+
+    public static class CustomPropertyConverter implements Converter<String>
+    {
+        @Override
+        public Class<String> type()
+        {
+            return String.class;
+        }
+
+        @Override
+        public String toString( String object )
+        {
+            return rot13( object );
+        }
+
+        @Override
+        public String fromString( String string )
+        {
+            return rot13( string );
+        }
+    }
+
+    @Service
+    private Serialization serialization;
+
+    @Test
+    public void testConvertedByAnnotation() throws Exception
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        builder.prototype().customPlainValue().set( new CustomPlainValue( "foo" ) );
+        builder.prototype().customConvertedProperty().set( "bar" );
+        builder.prototype().customAssemblyConvertedProperty().set( "bazar" );
+        SomeValue value = builder.newInstance();
+
+        String serialized = serialization.serialize( value );
+        assertThat( getStringFromValueState( serialized, "customPlainValue" ),
+                    equalTo( rot13( "foo" ) ) );
+        assertThat( getStringFromValueState( serialized, "customConvertedProperty" ),
+                    equalTo( rot13( "bar" ) ) );
+        assertThat( getStringFromValueState( serialized, "customAssemblyConvertedProperty" ),
+                    equalTo( rot13( "bazar" ) ) );
+
+        SomeValue deserialized = serialization.deserialize( module, SomeValue.class, serialized );
+        assertThat( deserialized, equalTo( value ) );
+    }
+
+    private static String rot13( String string )
+    {
+        StringBuilder builder = new StringBuilder();
+        for( int i = 0; i < string.length(); i++ )
+        {
+            char c = string.charAt( i );
+            if( c >= 'a' && c <= 'm' ) { c += 13; }
+            else if( c >= 'A' && c <= 'M' ) { c += 13; }
+            else if( c >= 'n' && c <= 'z' ) { c -= 13; }
+            else if( c >= 'N' && c <= 'Z' ) { c -= 13; }
+            builder.append( c );
+        }
+        return builder.toString();
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractPlainValueSerializationTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractPlainValueSerializationTest.java
new file mode 100644
index 0000000..4b34b64
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractPlainValueSerializationTest.java
@@ -0,0 +1,437 @@
+/*
+ *  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.polygene.test.serialization;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.Period;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.util.Objects;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.serialization.Converter;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.type.EnumType;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.spi.serialization.SerializationSettings;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.Matchers.startsWith;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+/**
+ * Assert that Serialization behaviour on plain values is correct.
+ *
+ * Implementations must:
+ * <ul>
+ *     <li>implement {@link #assemble(ModuleAssembly)}</li>
+ *     <li>
+ *         apply test {@link SerializationSettings} using {@link #withTestSettings(SerializationSettings)}
+ *         in {@literal assemble()}
+ *     </li>
+ *     <li>implement {@link #getSingleStringRawState(String)}</li>
+ * </ul>
+ */
+public abstract class AbstractPlainValueSerializationTest extends AbstractPolygeneTest
+{
+    @Service
+    protected Serialization serialization;
+
+    @SuppressWarnings( "unchecked" )
+    protected <T extends SerializationSettings> T withTestSettings( T settings )
+    {
+        return (T) settings.withConverter( new CustomConverter() );
+    }
+
+    protected abstract String getSingleStringRawState( String state ) throws Exception;
+
+    @Test
+    public void dontKnowHowToSerializeJavaLangObject()
+    {
+        try
+        {
+            serialization.serialize( new Object() );
+            fail( "serialization.serialize( new Object() ) should have failed" );
+        }
+        catch( SerializationException ex )
+        {
+            assertThat( ex.getMessage(), startsWith( "Don't know how to serialize" ) );
+        }
+    }
+
+    @Test
+    public void givenNullValueWhenSerializingAndDeserializingExpectNull()
+    {
+        String output = serialization.serialize( null );
+        System.out.println( output );
+
+        assertThat( serialization.deserialize( module, ValueType.of( Integer.class ), output ), nullValue() );
+        assertThat( serialization.deserialize( module, ValueType.of( String.class ), output ), nullValue() );
+        assertThat( serialization.deserialize( module, ValueType.of( SomeEnum.class ), output ), nullValue() );
+    }
+
+    @Test
+    public void givenEnumValueWhenSerializingAndDeserializingExpectEquals() throws Exception
+    {
+        String output = serialization.serialize( SomeEnum.BÆR );
+        System.out.println( output );
+        assertThat( getSingleStringRawState( output ), equalTo( "BÆR" ) );
+
+        SomeEnum value = serialization.deserialize( module, EnumType.of( SomeEnum.class ), output );
+        assertThat( value, is( SomeEnum.BÆR ) );
+    }
+
+    @Test
+    public void givenPrimitiveValueWhenSerializingAndDeserializingUsingPrimitiveAndBoxedTypesExpectEquals()
+    {
+        assertPrimitiveBoxedDeserializationEquals( char.class, Character.class, '€' );
+        assertPrimitiveBoxedDeserializationEquals( boolean.class, Boolean.class, true );
+        assertPrimitiveBoxedDeserializationEquals( short.class, Short.class, (short) 23 );
+        assertPrimitiveBoxedDeserializationEquals( int.class, Integer.class, 23 );
+        assertPrimitiveBoxedDeserializationEquals( byte.class, Byte.class, (byte) 23 );
+        assertPrimitiveBoxedDeserializationEquals( long.class, Long.class, 23L );
+        assertPrimitiveBoxedDeserializationEquals( float.class, Float.class, 23F );
+        assertPrimitiveBoxedDeserializationEquals( double.class, Double.class, 23D );
+    }
+
+    private <P, B> void assertPrimitiveBoxedDeserializationEquals( Class<P> primitiveType, Class<B> boxedType, P value )
+    {
+        String serialized = serialization.serialize( value );
+        System.out.println( serialized );
+
+        B boxed = serialization.deserialize( module, boxedType, serialized );
+        P primitive = serialization.deserialize( module, primitiveType, serialized );
+        assertThat( "Primitive/Boxed", boxed, equalTo( primitive ) );
+    }
+
+    @Test
+    public void givenCharacterValueWhenSerializingAndDeserializingExpectEquals() throws Exception
+    {
+        String serialized = serialization.serialize( '∫' );
+        System.out.println( serialized );
+
+        Character deserialized = serialization.deserialize( module, Character.class, serialized );
+        assertThat( "Deserialized", deserialized, equalTo( '∫' ) );
+
+        deserialized = serialization.deserialize( module, char.class, serialized );
+        assertThat( "Deserialized", deserialized, is( '∫' ) );
+    }
+
+    @Test
+    public void givenEmptyStringValueWhenSerializingAndDeserializingExpectEquals() throws Exception
+    {
+        String serialized = serialization.serialize( "" );
+        System.out.println( serialized );
+        assertThat( getSingleStringRawState( serialized ), equalTo( "" ) );
+
+        String deserialized = serialization.deserialize( module, String.class, serialized );
+        assertThat( "Deserialized", deserialized, equalTo( "" ) );
+    }
+
+    @Test
+    public void givenStringValueWhenSerializingAndDeserializingExpectEquals() throws Exception
+    {
+        String serialized = serialization.serialize( "Å∫" );
+        System.out.println( serialized );
+        assertThat( getSingleStringRawState( serialized ), equalTo( "Å∫" ) );
+
+        String deserialized = serialization.deserialize( module, String.class, serialized );
+        assertThat( deserialized, equalTo( "Å∫" ) );
+    }
+
+    @Test
+    public void givenBooleanValueWhenSerializingAndDeserializingExpectEquals()
+    {
+        String serialized = serialization.serialize( true );
+        System.out.println( serialized );
+
+        Boolean deserialized = serialization.deserialize( module, Boolean.class, serialized );
+        assertThat( deserialized, equalTo( Boolean.TRUE ) );
+    }
+
+    @Test
+    public void givenIntegerValueWhenSerializingAndDeserializingExpectEquals()
+    {
+        String serialized = serialization.serialize( 42 );
+        System.out.println( serialized );
+
+        Integer deserialized = serialization.deserialize( module, Integer.class, serialized );
+        assertThat( deserialized, equalTo( 42 ) );
+    }
+
+    @Test
+    public void givenLongValueWhenSerializingAndDeserializingExpectEquals()
+    {
+        String serialized = serialization.serialize( 42L );
+        System.out.println( serialized );
+
+        Long deserialized = serialization.deserialize( module, Long.class, serialized );
+        assertThat( deserialized, equalTo( 42L ) );
+    }
+
+    @Test
+    public void givenShortValueWhenSerializingAndDeserializingExpectEquals()
+    {
+        String serialized = serialization.serialize( (short) 42 );
+        System.out.println( serialized );
+
+        Short deserialized = serialization.deserialize( module, Short.class, serialized );
+        assertThat( deserialized, equalTo( (short) 42 ) );
+    }
+
+    @Test
+    public void givenByteValueWhenSerializingAndDeserializingExpectEquals()
+    {
+        String serialized = serialization.serialize( (byte) 42 );
+        System.out.println( serialized );
+
+        Byte deserialized = serialization.deserialize( module, Byte.class, serialized );
+        assertThat( deserialized, equalTo( (byte) 42 ) );
+    }
+
+    @Test
+    public void givenFloatValueWhenSerializingAndDeserializingExpectEquals()
+    {
+        String serialized = serialization.serialize( 42F );
+        System.out.println( serialized );
+
+        Float deserialized = serialization.deserialize( module, Float.class, serialized );
+        assertThat( deserialized, equalTo( 42F ) );
+    }
+
+    @Test
+    public void givenDoubleValueWhenSerializingAndDeserializingExpectEquals()
+    {
+        String serialized = serialization.serialize( 42D );
+        System.out.println( serialized );
+
+        Double deserialized = serialization.deserialize( module, Double.class, serialized );
+        assertThat( deserialized, equalTo( 42D ) );
+    }
+
+    @Test
+    public void givenBigIntegerValueWhenSerializingAndDeserializingExpectEquals()
+    {
+        BigInteger bigInteger = new BigInteger( "42424242424242424242424242" );
+        assertThat( bigInteger, not( equalTo( BigInteger.valueOf( bigInteger.longValue() ) ) ) );
+
+        String serialized = serialization.serialize( bigInteger );
+        System.out.println( serialized );
+
+        BigInteger deserialized = serialization.deserialize( module, BigInteger.class, serialized );
+        assertThat( deserialized, equalTo( bigInteger ) );
+    }
+
+    @Test
+    public void givenBigDecimalValueWhenSerializingAndDeserializingExpectEquals()
+    {
+        BigDecimal bigDecimal = new BigDecimal( "42.2376931348623157e+309" );
+        assertThat( bigDecimal.doubleValue(), equalTo( Double.POSITIVE_INFINITY ) );
+
+        String serialized = serialization.serialize( bigDecimal );
+        System.out.println( serialized );
+
+        BigDecimal deserialized = serialization.deserialize( module, BigDecimal.class, serialized );
+        assertThat( deserialized, equalTo( bigDecimal ) );
+    }
+
+    @Test
+    public void givenLocalDateTimeValueWhenSerializingAndDeserializingExpectEquals() throws Exception
+    {
+        // Serialized without TimeZone
+        String serialized = serialization.serialize( LocalDateTime.of( 2020, 3, 4, 13, 23, 12 ) );
+        System.out.println( serialized );
+        assertThat( getSingleStringRawState( serialized ), equalTo( "2020-03-04T13:23:12" ) );
+
+        LocalDateTime deserialized = serialization.deserialize( module, LocalDateTime.class, serialized );
+        assertThat( deserialized, equalTo( LocalDateTime.of( 2020, 3, 4, 13, 23, 12 ) ) );
+    }
+
+    @Test
+    public void givenLocalDateValueWhenSerializingAndDeserializingExpectEquals() throws Exception
+    {
+        String serialized = serialization.serialize( LocalDate.of( 2020, 3, 4 ) );
+        System.out.println( serialized );
+        assertThat( getSingleStringRawState( serialized ), equalTo( "2020-03-04" ) );
+
+        LocalDate deserialized = serialization.deserialize( module, LocalDate.class, serialized );
+        assertThat( deserialized, equalTo( LocalDate.of( 2020, 3, 4 ) ) );
+    }
+
+    @Test
+    public void givenLocalTimeValueWhenSerializingAndDeserializingExpectEquals() throws Exception
+    {
+        String serialized = serialization.serialize( LocalTime.of( 14, 54, 27 ) );
+        System.out.println( serialized );
+        assertThat( getSingleStringRawState( serialized ), equalTo( "14:54:27" ) );
+
+        LocalTime deserialized = serialization.deserialize( module, LocalTime.class, serialized );
+        assertThat( deserialized, equalTo( LocalTime.of( 14, 54, 27 ) ) );
+    }
+
+    @Test
+    public void givenOffsetDateTimeValueWhenSerializingAndDeserializingExpectEquals() throws Exception
+    {
+        String serialized = serialization.serialize( OffsetDateTime.of( 2009, 8, 12, 14, 54, 27, 895000000,
+                                                                        ZoneOffset.ofHours( 8 ) ) );
+        System.out.println( serialized );
+        assertThat( getSingleStringRawState( serialized ), equalTo( "2009-08-12T14:54:27.895+08:00" ) );
+
+        OffsetDateTime deserialized = serialization.deserialize( module, OffsetDateTime.class, serialized );
+        assertThat( deserialized, equalTo( OffsetDateTime.of( 2009, 8, 12, 14, 54, 27, 895000000,
+                                                              ZoneOffset.ofHours( 8 ) ) ) );
+    }
+
+    @Test
+    public void givenZonedDateTimeValueWhenSerializingAndDeserializingExpectEquals() throws Exception
+    {
+        String serialized = serialization.serialize( ZonedDateTime.of( 2009, 8, 12, 14, 54, 27, 895000000,
+                                                                       ZoneId.of( "CET" ) ) );
+        System.out.println( serialized );
+        assertThat( getSingleStringRawState( serialized ), equalTo( "2009-08-12T14:54:27.895+02:00[CET]" ) );
+
+        ZonedDateTime deserialized = serialization.deserialize( module, ZonedDateTime.class, serialized );
+        assertThat( deserialized, equalTo( ZonedDateTime.of( 2009, 8, 12, 14, 54, 27, 895000000,
+                                                             ZoneId.of( "CET" ) ) ) );
+    }
+
+    @Test
+    public void givenInstantValueWhenSerializingAndDeserializingExpectEquals() throws Exception
+    {
+        String serialized = serialization.serialize( Instant.parse( "2016-06-11T08:47:12.620Z" ) );
+        System.out.println( serialized );
+        assertThat( getSingleStringRawState( serialized ), equalTo( "2016-06-11T08:47:12.620Z" ) );
+
+        Instant deserialized = serialization.deserialize( module, Instant.class, serialized );
+        assertThat( deserialized, equalTo( Instant.parse( "2016-06-11T08:47:12.620Z" ) ) );
+    }
+
+    @Test
+    public void givenDurationValueWhenSerializingAndDeserializingExpectEquals() throws Exception
+    {
+        String serialized = serialization.serialize( Duration.ofMillis( 3500 ) );
+        System.out.println( serialized );
+        assertThat( getSingleStringRawState( serialized ), equalTo( "PT3.5S" ) );
+
+        Duration deserialized = serialization.deserialize( module, Duration.class, serialized );
+        assertThat( deserialized, equalTo( Duration.ofMillis( 3500 ) ) );
+    }
+
+    @Test
+    public void givenPeriodValueWhenSerializingAndDeserializingExpectEquals() throws Exception
+    {
+        String serialized = serialization.serialize( Period.of( 3, 5, 13 ) );
+        System.out.println( serialized );
+        assertThat( getSingleStringRawState( serialized ), equalTo( "P3Y5M13D" ) );
+
+        Period deserialized = serialization.deserialize( module, Period.class, serialized );
+        assertThat( deserialized, equalTo( Period.of( 3, 5, 13 ) ) );
+    }
+
+    @Test
+    public void givenEntityReferenceValueWhenSerializingAndDeserializingExpectEquals() throws Exception
+    {
+        String serialized = serialization.serialize( EntityReference.parseEntityReference( "ABCD-1234" ) );
+        System.out.println( serialized );
+        assertThat( getSingleStringRawState( serialized ), equalTo( "ABCD-1234" ) );
+
+        EntityReference deserialized = serialization.deserialize( module, EntityReference.class, serialized );
+        assertThat( deserialized, equalTo( EntityReference.parseEntityReference( "ABCD-1234" ) ) );
+    }
+
+    @Test
+    public void givenCustomPlainValueTypeAndItsConverterWhenSerializingAndDeserializingExpectEquals() throws Exception
+    {
+        String serialized = serialization.serialize( new CustomConvertedValue( "ABCD-1234" ) );
+        System.out.println( serialized );
+        assertThat( getSingleStringRawState( serialized ), equalTo( "ABCD-1234" ) );
+
+        CustomConvertedValue deserialized = serialization.deserialize( module, CustomConvertedValue.class, serialized );
+        assertThat( deserialized, equalTo( new CustomConvertedValue( "ABCD-1234" ) ) );
+    }
+
+    private enum SomeEnum
+    {
+        BÆR,
+        BAZAR
+    }
+
+    static class CustomConverter implements Converter<CustomConvertedValue>
+    {
+        @Override
+        public Class<CustomConvertedValue> type()
+        {
+            return CustomConvertedValue.class;
+        }
+
+        @Override
+        public String toString( CustomConvertedValue object )
+        {
+            return object.value;
+        }
+
+        @Override
+        public CustomConvertedValue fromString( String string )
+        {
+            return new CustomConvertedValue( string );
+        }
+    }
+
+    static class CustomConvertedValue
+    {
+        private final String value;
+
+        CustomConvertedValue( String value )
+        {
+            this.value = value;
+        }
+
+        @Override
+        public boolean equals( final Object o )
+        {
+            if( this == o ) { return true; }
+            if( o == null || getClass() != o.getClass() ) { return false; }
+            CustomConvertedValue that = (CustomConvertedValue) o;
+            return Objects.equals( value, that.value );
+        }
+
+        @Override
+        public int hashCode()
+        {
+            return Objects.hashCode( value );
+        }
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractValueCompositeSerializationTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractValueCompositeSerializationTest.java
new file mode 100644
index 0000000..3741fd2
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractValueCompositeSerializationTest.java
@@ -0,0 +1,678 @@
+/*
+ *  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.polygene.test.serialization;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.serialization.ConvertedBy;
+import org.apache.polygene.api.serialization.JavaSerializationConverter;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.polygene.api.usecase.UsecaseBuilder.newUsecase;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Assert that Serialization behaviour on ValueComposites is correct.
+ */
+// TODO Assert Generics behaviour!
+public abstract class AbstractValueCompositeSerializationTest
+    extends AbstractPolygeneTest
+{
+    @Rule
+    public TestName testName = new TestName();
+
+    @Before
+    public void before()
+    {
+        System.out.println( "# BEGIN " + testName.getMethodName() );
+    }
+
+    @After
+    public void after()
+    {
+        System.out.println( "# END " + testName.getMethodName() );
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        module.objects( JavaSerializationConverter.class );
+        module.values( Some.class, SomeExtended.class, SomeShuffled.class,
+                       AnotherValue.class, FooValue.class, CustomFooValue.class,
+                       SpecificCollection.class /*, SpecificValue.class, GenericValue.class */ );
+        module.entities( Some.class, BarEntity.class );
+
+        new EntityTestAssembler().visibleIn( Visibility.layer ).assemble( module.layer().module( "persistence" ) );
+    }
+
+    @Structure
+    protected Module moduleInstance;
+
+    @Service
+    protected Serialization serialization;
+
+    @Test
+    public void givenValueCompositeWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            Some some = buildSomeValue( moduleInstance, uow, "23" );
+
+            // Serialize using injected service
+            String stateString = serialization.serialize( some );
+            System.out.println( stateString );
+
+            // Deserialize using Module API
+            Some some2 = moduleInstance.newValueFromSerializedState( Some.class, stateString );
+
+            assertThat( "Map<String, Integer>",
+                        some2.stringIntMap().get().get( "foo" ),
+                        equalTo( 42 ) );
+            assertThat( "Map<String, Value>",
+                        some2.stringValueMap().get().get( "foo" ).internalVal(),
+                        equalTo( "Bar" ) );
+
+            assertThat( "Nested Entities",
+                        some2.barAssociation().get().cathedral().get(),
+                        equalTo( "bazar in barAssociation" ) );
+
+            assertThat( "Polymorphic deserialization of value type NOT extending ValueComposite",
+                        some.customFoo().get() instanceof CustomFooValue,
+                        is( true ) );
+            assertThat( "Polymorphic deserialization of value type extending ValueComposite",
+                        some.customFooValue().get() instanceof CustomFooValue,
+                        is( true ) );
+
+            assertThat( "Value equality", some, equalTo( some2 ) );
+
+            uow.complete();
+        }
+    }
+
+    @Test
+    public void givenEntityCompositeWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            Some some = buildSomeEntity( moduleInstance, uow, "23" );
+
+            // Serialize using injected service
+            String stateString = serialization.serialize( some );
+            System.out.println( stateString );
+
+            // Deserialize using Module API
+            Some some2 = moduleInstance.newValueFromSerializedState( Some.class, stateString );
+
+            assertThat( "Map<String, Integer>",
+                        some2.stringIntMap().get().get( "foo" ),
+                        equalTo( 42 ) );
+            assertThat( "Map<String, Value>",
+                        some2.stringValueMap().get().get( "foo" ).internalVal(),
+                        equalTo( "Bar" ) );
+
+            assertThat( "Nested Entities",
+                        some2.barAssociation().get().cathedral().get(),
+                        equalTo( "bazar in barAssociation" ) );
+
+            assertThat( "Polymorphic deserialization of value type NOT extending ValueComposite",
+                        some.customFoo().get() instanceof CustomFooValue,
+                        is( true ) );
+            assertThat( "Polymorphic deserialization of value type extending ValueComposite",
+                        some.customFooValue().get() instanceof CustomFooValue,
+                        is( true ) );
+
+            assertThat( "Value equality", some, equalTo( some2 ) );
+
+            uow.complete();
+        }
+    }
+
+    @Test
+    public void canDeserializeUsingSuperTypeWithLessState()
+    {
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            SomeExtended someExtended = buildSomeExtendedValue( moduleInstance, uow, "42" );
+
+            String serialized = serialization.serialize( someExtended );
+            System.out.println( serialized );
+
+            Some deserialized = serialization.deserialize( module, Some.class, serialized );
+            System.out.println( deserialized );
+
+            uow.complete();
+        }
+    }
+
+    @Test
+    public void canDeserializeUsingChildTypeWithSupplementaryOptionalState()
+    {
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            Some some = buildSomeValue( moduleInstance, uow, "42" );
+
+            String serialized = serialization.serialize( some );
+            System.out.println( serialized );
+
+            SomeExtended deserialized = serialization.deserialize( module, SomeExtended.class, serialized );
+            System.out.println( deserialized );
+
+            uow.complete();
+        }
+    }
+
+    /**
+     * State model order depend on declaration order, this test ensures that moving a state method up/down into a type
+     * does not break deserialization.
+     */
+    @Test
+    public void canDeserializeFromShuffledState()
+    {
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            SomeExtended someExtended = buildSomeExtendedValue( moduleInstance, uow, "42" );
+
+            String serialized = serialization.serialize( someExtended );
+            System.out.println( serialized );
+
+            SomeShuffled deserialized = serialization.deserialize( module, SomeShuffled.class, serialized );
+            System.out.println( deserialized );
+
+            serialized = serialization.serialize( deserialized );
+            System.out.println( serialized );
+
+            serialization.deserialize( module, SomeExtended.class, serialized );
+            System.out.println( deserialized );
+
+            uow.complete();
+        }
+    }
+
+    @Test
+    @Ignore( "JSONEntityState cannot handle polymorphic deserialization" )
+    // TODO Entity == Identity + Value
+    // JSONEntityState does not allow for polymorphic serialization
+    public void valueAndEntityTypeEquality()
+    {
+        Identity identity = StringIdentity.fromString( "42" );
+        Some createdValue, loadedValue;
+
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( newUsecase( "create" ) ) )
+        {
+            Some entity = buildSomeEntity( moduleInstance, uow, identity );
+            createdValue = uow.toValue( Some.class, entity );
+            System.out.println( "Created Entity\n\t" + entity + "\nCreated Value\n\t" + createdValue );
+            uow.complete();
+        }
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( newUsecase( "load" ) ) )
+        {
+            Some entity = uow.get( Some.class, identity );
+            loadedValue = uow.toValue( Some.class, entity );
+            System.out.println( "Loaded Entity\n\t" + entity + "\nLoaded Value\n\t" + loadedValue );
+        }
+
+        assertThat( "Create/Read equality",
+                    createdValue, equalTo( loadedValue ) );
+
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( newUsecase( "remove" ) ) )
+        {
+            uow.remove( uow.get( Some.class, identity ) );
+            uow.complete();
+        }
+
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( newUsecase( "create from value" ) ) )
+        {
+            Some entity = uow.toEntity( Some.class, loadedValue );
+            createdValue = uow.toValue( Some.class, entity );
+            System.out.println( "Created Entity from Value\n\t" + entity + "\nCreated Value\n\t" + createdValue );
+            uow.complete();
+        }
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( newUsecase( "read again" ) ) )
+        {
+            Some entity = uow.get( Some.class, identity );
+            loadedValue = uow.toValue( Some.class, entity );
+            System.out.println( "Loaded Entity\n\t" + entity + "\nLoaded Value\n\t" + loadedValue );
+        }
+
+        assertThat( "Create from Value/Read equality",
+                    createdValue, equalTo( loadedValue ) );
+    }
+
+    protected static Some buildSomeEntity( Module module, UnitOfWork uow, String identity )
+    {
+        EntityBuilder<Some> builder = uow.newEntityBuilder( Some.class );
+        Some proto = builder.instance();
+        proto.identity().set( StringIdentity.fromString( identity ) );
+        setSomeValueState( module, uow, proto );
+        return builder.newInstance();
+    }
+
+    /**
+     * @return a Some ValueComposite whose state is populated with test data.
+     */
+    protected static Some buildSomeValue( Module module, UnitOfWork uow, String identity )
+    {
+        ValueBuilder<Some> builder = module.newValueBuilder( Some.class );
+        Some proto = builder.prototype();
+        proto.identity().set( StringIdentity.fromString( identity ) );
+        setSomeValueState( module, uow, proto );
+        return builder.newInstance();
+    }
+
+    protected static SomeExtended buildSomeExtendedValue( Module module, UnitOfWork uow, String identity )
+    {
+        ValueBuilder<SomeExtended> builder = module.newValueBuilder( SomeExtended.class );
+        SomeExtended proto = builder.prototype();
+        proto.identity().set( StringIdentity.fromString( identity ) );
+        setSomeValueState( module, uow, proto );
+        proto.extraProperty().set( "extra property" );
+        proto.extraAssociation().set( buildBarEntity( module, uow, "extra association" ) );
+        proto.extraManyAssociation().add( buildBarEntity( module, uow, "extra many association" ) );
+        proto.extraNamedAssociation().put( "extra", buildBarEntity( module, uow, "extra named association" ) );
+        return builder.newInstance();
+    }
+
+    /**
+     * @return a Some EntityComposite whose state is populated with test data.
+     */
+    protected static Some buildSomeEntity( Module module, UnitOfWork uow, Identity identity )
+    {
+        EntityBuilder<Some> builder = uow.newEntityBuilder( Some.class, identity );
+        setSomeValueState( module, uow, builder.instance() );
+        return builder.newInstance();
+    }
+
+    private static void setSomeValueState( Module module, UnitOfWork uow, Some some )
+    {
+        some.anotherList().get().add( module.newValue( AnotherValue.class ) );
+
+        ValueBuilder<SpecificCollection> specificColBuilder = module.newValueBuilder( SpecificCollection.class );
+        SpecificCollection specificColProto = specificColBuilder.prototype();
+        List<String> genericList = new ArrayList<>( 2 );
+        genericList.add( "Some" );
+        genericList.add( "String" );
+        specificColProto.genericList().set( genericList );
+        some.specificCollection().set( specificColBuilder.newInstance() );
+
+        AnotherValue anotherValue1 = createAnotherValue( module, "Foo", "Bar" );
+        AnotherValue anotherValue2 = createAnotherValue( module, "Habba", "ZoutZout" );
+        AnotherValue anotherValue3 = createAnotherValue( module, "Niclas", "Hedhman" );
+
+        some.string().set( "Foo\"Bar\"\nTest\f\t\b\r" );
+        some.string2().set( "/Foo/bar" );
+        some.number().set( 43L );
+        some.localTime().set( LocalTime.now() );
+        some.dateTime().set( OffsetDateTime.of( 2020, 3, 4, 13, 24, 35, 0, ZoneOffset.ofHours( 1 ) ) );
+        some.localDate().set( LocalDate.now() );
+        some.localDateTime().set( LocalDateTime.now() );
+        some.entityReference().set( EntityReference.parseEntityReference( "12345" ) );
+        some.stringIntMap().get().put( "foo", 42 );
+
+        // Can't put more than one entry in Map because this test rely on the fact that the underlying implementations
+        // maintain a certain order but it's not the case on some JVMs. On OpenJDK 8 they are reversed for example.
+        // This should not be enforced tough as both the Map API and the JSON specification state that name-value pairs
+        // are unordered.
+        // As a consequence this test should be enhanced to be Map order independent.
+        //
+        // proto.stringIntMap().get().put( "bar", 67 );
+
+        some.stringValueMap().get().put( "foo", anotherValue1 );
+        some.another().set( anotherValue1 );
+        some.arrayOfValues().set( new AnotherValue[] { anotherValue1, anotherValue2, anotherValue3 } );
+        some.primitiveByteArray().set( "foo".getBytes( UTF_8 ) );
+        some.byteArray().set( new Byte[] { 23, null, 42 } );
+        some.serializable().set( new SerializableObject() );
+        some.foo().set( module.newValue( FooValue.class ) );
+        some.fooValue().set( module.newValue( FooValue.class ) );
+        some.customFoo().set( module.newValue( CustomFooValue.class ) );
+        some.customFooValue().set( module.newValue( CustomFooValue.class ) );
+
+        // NestedEntities
+        some.barAssociation().set( buildBarEntity( module, uow, "bazar in barAssociation" ) );
+        some.barEntityAssociation().set( buildBarEntity( module, uow, "bazar in barEntityAssociation" ) );
+        some.barManyAssociation().add( buildBarEntity( module, uow, "bazar ONE in barManyAssociation" ) );
+        some.barManyAssociation().add( buildBarEntity( module, uow, "bazar TWO in barManyAssociation" ) );
+        some.barEntityManyAssociation().add( buildBarEntity( module, uow, "bazar ONE in barEntityManyAssociation" ) );
+        some.barEntityManyAssociation().add( buildBarEntity( module, uow, "bazar TWO in barEntityManyAssociation" ) );
+        some.barNamedAssociation().put( "bazar", buildBarEntity( module, uow, "bazar in barNamedAssociation" ) );
+        some.barNamedAssociation().put( "cathedral",
+                                        buildBarEntity( module, uow, "cathedral in barNamedAssociation" ) );
+        some.barEntityNamedAssociation().put( "bazar",
+                                              buildBarEntity( module, uow, "bazar in barEntityNamedAssociation" ) );
+        some.barEntityNamedAssociation().put( "cathedral",
+                                              buildBarEntity( module, uow, "cathedral in barEntityNamedAssociation" ) );
+    }
+
+    private static AnotherValue createAnotherValue( Module module, String val1, String val2 )
+    {
+        ValueBuilder<AnotherValue> valueBuilder = module.newValueBuilder( AnotherValue.class );
+        valueBuilder.prototype().val1().set( val1 );
+        valueBuilder.prototypeFor( AnotherValueInternalState.class ).val2().set( val2 );
+        return valueBuilder.newInstance();
+    }
+
+    private static BarEntity buildBarEntity( Module module, UnitOfWork uow, String cathedral )
+    {
+        EntityBuilder<BarEntity> barBuilder = uow.newEntityBuilder( BarEntity.class );
+        barBuilder.instance().cathedral().set( cathedral );
+        barBuilder.instance().another().set( createAnotherValue( module, "nested", "value" ) );
+        return barBuilder.newInstance();
+    }
+
+    public enum TestEnum
+    {
+        somevalue,
+        anothervalue
+    }
+
+    public interface Some extends HasIdentity
+    {
+        Property<String> string();
+
+        Property<String> string2();
+
+        @Optional
+        Property<String> nullString();
+
+        @UseDefaults
+        Property<String> emptyString();
+
+        @UseDefaults
+        Property<Long> number();
+
+        Property<LocalTime> localTime();
+
+        Property<OffsetDateTime> dateTime();
+
+        Property<LocalDate> localDate();
+
+        Property<LocalDateTime> localDateTime();
+
+        Property<EntityReference> entityReference();
+
+        @UseDefaults
+        Property<List<String>> stringList();
+
+        @UseDefaults
+        Property<Map<String, Integer>> stringIntMap();
+
+        @UseDefaults
+        Property<Map<String, AnotherValue>> stringValueMap();
+
+        Property<AnotherValue> another();
+
+        Property<AnotherValue[]> arrayOfValues();
+
+        @Optional
+        Property<AnotherValue> anotherNull();
+
+        @UseDefaults
+        Property<List<AnotherValue>> anotherList();
+
+        @Optional
+        Property<List<AnotherValue>> anotherListNull();
+
+        @UseDefaults
+        Property<List<AnotherValue>> anotherListEmpty();
+
+        @UseDefaults
+        Property<TestEnum> testEnum();
+
+        Property<byte[]> primitiveByteArray();
+
+        @Optional
+        Property<byte[]> primitiveByteArrayNull();
+
+        Property<Byte[]> byteArray();
+
+        @Optional
+        Property<Byte[]> byteArrayNull();
+
+        Property<SerializableObject> serializable();
+
+        Property<Foo> foo();
+
+        Property<FooValue> fooValue();
+
+        Property<Foo> customFoo();
+
+        Property<FooValue> customFooValue();
+
+        Property<SpecificCollection> specificCollection();
+
+        /* Too complicated to do generics here for now
+         Property<SpecificValue> specificValue();
+         */
+        @Optional
+        Association<Bar> barAssociationOptional();
+
+        Association<Bar> barAssociation();
+
+        Association<BarEntity> barEntityAssociation();
+
+        ManyAssociation<Bar> barManyAssociationEmpty();
+
+        ManyAssociation<Bar> barManyAssociation();
+
+        ManyAssociation<BarEntity> barEntityManyAssociation();
+
+        NamedAssociation<Bar> barNamedAssociationEmpty();
+
+        NamedAssociation<Bar> barNamedAssociation();
+
+        NamedAssociation<BarEntity> barEntityNamedAssociation();
+    }
+
+    interface SomeExtended extends Some
+    {
+        @Optional
+        Property<String> extraProperty();
+
+        @Optional
+        Association<Bar> extraAssociation();
+
+        ManyAssociation<Bar> extraManyAssociation();
+
+        NamedAssociation<Bar> extraNamedAssociation();
+    }
+
+    interface SomeShuffled extends SomeExtended
+    {
+        NamedAssociation<Bar> extraNamedAssociation();
+
+        @Override
+        NamedAssociation<Bar> barNamedAssociation();
+
+        ManyAssociation<Bar> extraManyAssociation();
+
+        @Override
+        ManyAssociation<Bar> barManyAssociation();
+
+        Association<Bar> extraAssociation();
+
+        @Override
+        Association<Bar> barAssociation();
+
+        Property<String> extraProperty();
+
+        @Override
+        Property<String> string();
+    }
+
+    public interface SpecificCollection
+        extends GenericCollection<String>
+    {
+    }
+
+    public interface GenericCollection<TYPE>
+        extends ValueComposite
+    {
+        @UseDefaults
+        Property<List<TYPE>> genericList();
+    }
+
+    public interface SpecificValue
+        extends GenericValue<String>
+    {
+    }
+
+    public interface GenericValue<TYPE>
+        extends ValueComposite
+    {
+        @Optional
+        Property<TYPE> item();
+    }
+
+    @Mixins( AnotherValueMixin.class )
+    public interface AnotherValue
+        extends ValueComposite
+    {
+        @UseDefaults
+        Property<String> val1();
+
+        String internalVal();
+    }
+
+    public interface AnotherValueInternalState
+    {
+        @UseDefaults
+        Property<String> val2();
+    }
+
+    public static abstract class AnotherValueMixin
+        implements AnotherValue
+    {
+        @This
+        private AnotherValueInternalState internalState;
+
+        @Override
+        public String internalVal()
+        {
+            return internalState.val2().get();
+        }
+    }
+
+    public interface Foo
+    {
+        @UseDefaults
+        Property<String> bar();
+    }
+
+    public interface FooValue
+        extends Foo, ValueComposite
+    {
+    }
+
+    public interface CustomFooValue
+        extends FooValue
+    {
+        @UseDefaults
+        Property<String> custom();
+    }
+
+    public interface Bar
+    {
+        @UseDefaults
+        Property<String> cathedral();
+
+        Property<AnotherValue> another();
+    }
+
+    public interface BarEntity
+        extends Bar, EntityComposite
+    {
+    }
+
+    @ConvertedBy( JavaSerializationConverter.class )
+    public static class SerializableObject
+        implements Serializable
+    {
+        private static final long serialVersionUID = 1L;
+        private final String foo = "Foo";
+        private final int val = 35;
+
+        @Override
+        public boolean equals( Object o )
+        {
+            if( this == o )
+            {
+                return true;
+            }
+            if( o == null || getClass() != o.getClass() )
+            {
+                return false;
+            }
+            SerializableObject that = (SerializableObject) o;
+            return val == that.val && foo.equals( that.foo );
+        }
+
+        @Override
+        public int hashCode()
+        {
+            int result = foo.hashCode();
+            result = 31 * result + val;
+            return result;
+        }
+    }
+}
+
+
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/serialization/package.html b/core/testsupport/src/main/java/org/apache/polygene/test/serialization/package.html
new file mode 100644
index 0000000..7a03a27
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/serialization/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Serialization SPI Test Support.</h2>
+    </body>
+</html>
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/util/Assume.java b/core/testsupport/src/main/java/org/apache/polygene/test/util/Assume.java
new file mode 100644
index 0000000..ec65719
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/util/Assume.java
@@ -0,0 +1,129 @@
+/*
+ *  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.polygene.test.util;
+
+import java.awt.GraphicsEnvironment;
+import java.io.IOException;
+import java.net.NetworkInterface;
+import java.net.Socket;
+import java.net.SocketException;
+import java.util.Enumeration;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.StringStartsWith.startsWith;
+
+/**
+ * A set of methods useful for stating assumptions about the conditions in which a test is meaningful.
+ */
+public class Assume
+    extends org.junit.Assume
+{
+    /**
+     * If called on a JDK which version is different than the given one, the test will halt and be ignored.
+     * @param version the java version, 6, 7, 8, 9, 10
+     */
+    public static void assumeJavaVersion( int version )
+    {
+        assumeThat( System.getProperty( "java.version" ), startsWith( "1." + version ) );
+    }
+
+    /**
+     * If called on a IBM JDK, the test will halt and be ignored.
+     */
+    public static void assumeNoIbmJdk()
+    {
+        assumeFalse( System.getProperty( "java.vendor" ).contains( "IBM" ) );
+    }
+
+    /**
+     * If called on a headless runtime, the test will halt and be ignored.
+     */
+    public static void assumeDisplayPresent()
+    {
+        try
+        {
+            assumeFalse( GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance() );
+            String display = System.getenv( "DISPLAY" );
+            assumeThat( display, is( notNullValue() ) );
+            assumeTrue( display.length() > 0 );
+        }
+        catch( UnsatisfiedLinkError e )
+        {
+            // assuming that this is caused due to missing video subsystem, or similar
+            assumeNoException( "Grahics system is missing?", e );
+        }
+    }
+
+    /**
+     * If called on a networkless runtime, the test will halt and be ignored.
+     */
+    public static void assumeNetworking()
+    {
+        try
+        {
+            Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
+            assumeThat( ifaces, is( notNullValue() ) );
+            assumeTrue( ifaces.hasMoreElements() );
+        }
+        catch( SocketException ex )
+        {
+            assumeNoException( ex );
+        }
+    }
+
+    /**
+     * If called on a runtime with no access to polygene.apache.org on port 80, the test will halt and be ignored.
+     */
+    public static void assumeConnectivity()
+    {
+        assumeConnectivity( "polygene.apache.org", 80 );
+    }
+
+    /**
+     * If called on a runtime with no access to given host and port, the test will halt and be ignored.
+     *
+     * @param host Host
+     * @param port Port
+     */
+    public static void assumeConnectivity( String host, int port )
+    {
+        try( Socket socket = new Socket( host, port ) )
+        {
+            // Connected
+        }
+        catch( IOException ex )
+        {
+            assumeNoException( ex );
+        }
+    }
+
+    /**
+     * If called on a runtime without the given System Property set, the test will halt and be ignored.
+     * @param key the name of the system property
+     * @return The System Propery value if not null
+     */
+    public static String assumeSystemPropertyNotNull( String key )
+    {
+        String property = System.getProperty( key );
+        assumeNotNull( property );
+        return property;
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/util/FreePortFinder.java b/core/testsupport/src/main/java/org/apache/polygene/test/util/FreePortFinder.java
new file mode 100644
index 0000000..e6c05fa
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/util/FreePortFinder.java
@@ -0,0 +1,227 @@
+/*
+ *  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.polygene.test.util;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.OptionalInt;
+import java.util.Random;
+import java.util.function.IntPredicate;
+import java.util.stream.Stream;
+
+import static java.util.Collections.shuffle;
+import static java.util.stream.Collectors.collectingAndThen;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.IntStream.rangeClosed;
+
+public class FreePortFinder
+{
+    private static class Range
+    {
+        final int lowerBound;
+        final int higherBound;
+
+        private Range( int lowerBound, int higherBound )
+        {
+            this.lowerBound = lowerBound;
+            this.higherBound = higherBound;
+        }
+    }
+
+    // Presumably the least used port ranges with >500 slots
+    // See http://stackoverflow.com/a/28369841/300053
+    private static final List<Range> LEAST_USED_RANGES = Arrays.asList(
+        new Range( 29170, 29998 ),
+        new Range( 38866, 39680 ),
+        new Range( 41798, 42507 ),
+        new Range( 43442, 44122 ),
+        new Range( 46337, 46997 ),
+        new Range( 35358, 36000 ),
+        new Range( 36866, 37474 ),
+        new Range( 38204, 38799 ),
+        new Range( 33657, 34248 ),
+        new Range( 30261, 30831 ),
+        new Range( 41231, 41793 ),
+        new Range( 21011, 21552 ),
+        new Range( 28590, 29117 ),
+        new Range( 14415, 14935 ),
+        new Range( 26490, 26999 )
+    );
+
+    // Seen busy on builds.apache.org
+    private static final List<Integer> BLACKLIST = Arrays.asList(
+        42187, 37334, 38615, 33951, 41652, 41841
+    );
+
+    private static final int MAX_PORT_CHECKS = 20;
+
+    public static boolean isFreePortOnLocalHost( int port )
+    {
+        return isFreePort( getLocalHostUnchecked(), port );
+    }
+
+    public static boolean isFreePort( InetAddress address, int port )
+    {
+        try
+        {
+            checkFreePort( address, port );
+            return true;
+        }
+        catch( UncheckedIOException ex )
+        {
+            return false;
+        }
+    }
+
+    public static void checkFreePortOnLocalHost( int port )
+    {
+        checkFreePort( getLocalHostUnchecked(), port );
+    }
+
+    public static void checkFreePort( InetAddress address, int port )
+    {
+        ServerSocket server = null;
+        try
+        {
+            server = new ServerSocket( port, 1, address );
+        }
+        catch( IOException ex )
+        {
+            throw new UncheckedIOException( ex );
+        }
+        finally
+        {
+            if( server != null )
+            {
+                try
+                {
+                    server.close();
+                }
+                catch( IOException e )
+                {
+                    // Ignore
+                }
+            }
+        }
+    }
+
+    public static int findFreePortOnLocalHost()
+        throws IOException
+    {
+        return findFreePort( getLocalHostUnchecked() );
+    }
+
+    public static int findFreePortOnLoopback()
+    {
+        return findFreePort( InetAddress.getLoopbackAddress() );
+    }
+
+    public static int findFreePort( InetAddress address )
+    {
+        FreePortPredicate check = new FreePortPredicate( address );
+        // Randomly choose MAX_PORT_CHECKS ports from the least used ranges
+        Range range = LEAST_USED_RANGES.get( new Random().nextInt( LEAST_USED_RANGES.size() ) );
+        OptionalInt port = rangeClosed( range.lowerBound, range.higherBound )
+            .boxed()
+            .collect( collectingAndThen( toList(), collected ->
+            {
+                collected.removeAll( BLACKLIST );
+                shuffle( collected );
+                return collected.stream();
+            } ) )
+            .limit( MAX_PORT_CHECKS )
+            .mapToInt( Integer::intValue )
+            .filter( check )
+            .findFirst();
+        return port.orElseThrow( () ->
+        {
+            IOException exception = new IOException( "Unable to find a free port on " + address );
+            check.errors.build().forEach( exception::addSuppressed );
+            return new UncheckedIOException( exception );
+        } );
+    }
+
+    public static int findFreePortInRangeOnLocalhost( int lowerBound, int higherBound )
+    {
+        return findFreePortInRange( getLocalHostUnchecked(), lowerBound, higherBound );
+    }
+
+    public static int findFreePortInRange( InetAddress address, int lowerBound, int higherBound )
+    {
+        if( higherBound - lowerBound < 0 )
+        {
+            throw new IllegalArgumentException( "Invalid port range " + lowerBound + '-' + higherBound );
+        }
+        FreePortPredicate check = new FreePortPredicate( address );
+        OptionalInt port = rangeClosed( lowerBound, higherBound ).filter( check ).findFirst();
+        return port.orElseThrow( () ->
+        {
+            String message = "Unable to find a free port in range " + lowerBound + '-' + higherBound + " on " + address;
+            IOException exception = new IOException( message );
+            check.errors.build().forEach( exception::addSuppressed );
+            return new UncheckedIOException( exception );
+        } );
+    }
+
+    private static class FreePortPredicate implements IntPredicate
+    {
+        private final InetAddress address;
+        private final Stream.Builder<Throwable> errors;
+
+        private FreePortPredicate( InetAddress address )
+        {
+            this.address = address;
+            this.errors = Stream.builder();
+        }
+
+        @Override
+        public boolean test( int candidate )
+        {
+            try
+            {
+                checkFreePort( address, candidate );
+                System.err.println( "FreePortFinder found port " + candidate + " free" );
+                return true;
+            }
+            catch( UncheckedIOException ex )
+            {
+                errors.add( ex );
+                return false;
+            }
+        }
+    }
+
+    private static InetAddress getLocalHostUnchecked()
+    {
+        try
+        {
+            return InetAddress.getLocalHost();
+        }
+        catch( UnknownHostException ex )
+        {
+            throw new UncheckedIOException( ex );
+        }
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/util/JmxFixture.java b/core/testsupport/src/main/java/org/apache/polygene/test/util/JmxFixture.java
new file mode 100644
index 0000000..a8c106c
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/util/JmxFixture.java
@@ -0,0 +1,120 @@
+/*
+ *  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.polygene.test.util;
+
+import org.hamcrest.Matcher;
+import org.junit.Assert;
+
+import javax.management.JMException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import java.lang.management.ManagementFactory;
+import java.util.List;
+
+import static java.util.stream.Collectors.toList;
+
+/**
+ * JMX Test Fixture.
+ */
+public class JmxFixture extends Assert {
+
+    private final MBeanServer server;
+    private final String prefix;
+
+    public JmxFixture()
+    {
+        this( ManagementFactory.getPlatformMBeanServer(), "" );
+    }
+
+    public JmxFixture( String prefix )
+    {
+        this( ManagementFactory.getPlatformMBeanServer(), prefix );
+    }
+
+    public JmxFixture( MBeanServer server )
+    {
+        this( server, "" );
+    }
+
+    public JmxFixture( MBeanServer server, String prefix )
+    {
+        this.server = server;
+        this.prefix = prefix;
+    }
+
+    public String prefix() {
+        return prefix;
+    }
+
+    public boolean objectExists( String objName ) {
+        try
+        {
+            ObjectName objectName = new ObjectName( prefix + objName );
+            return server.isRegistered( objectName );
+        }
+        catch( MalformedObjectNameException ex )
+        {
+            throw new IllegalArgumentException( ex.getMessage(), ex );
+        }
+    }
+
+
+    public void assertObjectPresent( String objName )
+    {
+        if( !objectExists( objName ) )
+        {
+            fail( objName + " is absent" );
+        }
+    }
+
+    public void assertObjectAbsent( String objName )
+    {
+        if( objectExists( objName ) ) {
+            fail( objName + " is present" );
+        }
+    }
+
+    public <T> void assertAttributeValue( String objName, String attribute, Class<? extends T> type, Matcher<? super T> matcher )
+    {
+        assertThat( attributeValue( objName, attribute, type ), matcher );
+    }
+
+    public <T> T attributeValue( String objName, String attribute, Class<? extends T> type )
+    {
+        try
+        {
+            ObjectName objectName = new ObjectName( prefix + objName );
+            Object value = server.getAttribute( objectName, attribute );
+            return type.cast( value );
+        }
+        catch( MalformedObjectNameException ex )
+        {
+            throw new IllegalArgumentException( ex.getMessage(), ex );
+        }
+        catch( JMException ex )
+        {
+            throw new RuntimeException( ex.getMessage(), ex );
+        }
+    }
+
+    public List<String> allObjectNames()
+    {
+        return server.queryNames( null, null ).stream().map( ObjectName::toString ).collect( toList() );
+    }
+}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/util/NotYetImplemented.java b/core/testsupport/src/main/java/org/apache/polygene/test/util/NotYetImplemented.java
new file mode 100644
index 0000000..35dd7e2
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/util/NotYetImplemented.java
@@ -0,0 +1,80 @@
+/*
+ *  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.polygene.test.util;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import junit.framework.AssertionFailedError;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * JUnit annotation and rule to mark not yet implemented tests.
+ *
+ * In order to use this annotation you must register the corresponding {@link NotYetImplemented.Rule}.
+ *
+ * Not yet implemented tests are run an expected to fail, an assertion error is thrown if they pass.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.TYPE, ElementType.METHOD } )
+@Documented
+public @interface NotYetImplemented
+{
+    String reason() default "";
+
+    class Rule implements TestRule
+    {
+        @Override
+        public Statement apply( Statement base, Description description )
+        {
+            if( description.getAnnotation( NotYetImplemented.class ) == null )
+            {
+                return base;
+            }
+            return new Statement()
+            {
+                @Override
+                public void evaluate() throws Throwable
+                {
+                    boolean passed = false;
+                    try
+                    {
+                        base.evaluate();
+                        passed = true;
+                    }
+                    catch( Throwable ex )
+                    {
+                        System.err.println( "Not yet implemented test expectedly failed" );
+                        ex.printStackTrace( System.err );
+                    }
+                    if( passed )
+                    {
+                        throw new AssertionFailedError(
+                            "Test " + description.getDisplayName()
+                            + " is annotated as not yet implemented, expected it to fail but it passed."
+                        );
+                    }
+                }
+            };
+        }
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/util/RepeatRule.java b/core/testsupport/src/main/java/org/apache/polygene/test/util/RepeatRule.java
new file mode 100644
index 0000000..50e019a
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/util/RepeatRule.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.test.util;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * JUnit Rule to run tests repeatedly.
+ *
+ * <p>To repeat a complete test class:</p>
+ * <pre>@ClassRule public static final RepeatRule REPEAT = new RepeatRule( 10 );</pre>
+ *
+ * <p>To repeat each test on the same test class instance:</p>
+ * <pre>@Rule public final RepeatRule repeat = new RepeatRule( 10 );</pre>
+ */
+public class RepeatRule
+    implements TestRule
+{
+    private final int count;
+
+    public RepeatRule( int count )
+    {
+        this.count = count;
+    }
+
+    @Override
+    public Statement apply( final Statement base, Description description )
+    {
+        return new Statement()
+        {
+            @Override
+            public void evaluate()
+                throws Throwable
+            {
+                for( int repeat = 0; repeat < count; repeat++ )
+                {
+                    base.evaluate();
+                }
+            }
+        };
+    }
+
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/util/RetryRule.java b/core/testsupport/src/main/java/org/apache/polygene/test/util/RetryRule.java
new file mode 100644
index 0000000..84768e1
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/util/RetryRule.java
@@ -0,0 +1,72 @@
+/*
+ *  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.polygene.test.util;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * JUnit Rule to retry tests.
+ * Useful for flaky tests.
+ */
+public class RetryRule implements TestRule
+{
+    private static final int MAX_DEFAULT = 3;
+
+    private final int max;
+    private int attempts = 0;
+
+    public RetryRule()
+    {
+        this( MAX_DEFAULT );
+    }
+
+    public RetryRule( int max )
+    {
+        this.max = max;
+    }
+
+    @Override
+    public Statement apply( Statement base, Description description )
+    {
+        return new Statement()
+        {
+            @Override
+            public void evaluate() throws Throwable
+            {
+                attempts++;
+                try
+                {
+                    base.evaluate();
+                }
+                catch( Throwable ex )
+                {
+                    if( attempts <= max )
+                    {
+                        evaluate();
+                    }
+                    else
+                    {
+                        throw ex;
+                    }
+                }
+            }
+        };
+    }
+}
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/util/package.html b/core/testsupport/src/main/java/org/apache/polygene/test/util/package.html
new file mode 100644
index 0000000..2792f09
--- /dev/null
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/util/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Test Support Utilities.</h2>
+    </body>
+</html>
diff --git a/core/testsupport/src/main/java/org/qi4j/test/AbstractQi4jBaseTest.java b/core/testsupport/src/main/java/org/qi4j/test/AbstractQi4jBaseTest.java
deleted file mode 100644
index 949dca3..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/AbstractQi4jBaseTest.java
+++ /dev/null
@@ -1,128 +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.qi4j.test;
-
-import org.junit.After;
-import org.junit.Before;
-import org.qi4j.api.Qi4j;
-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.spi.Qi4jSPI;
-
-public abstract class AbstractQi4jBaseTest
-{
-    protected Qi4j api;
-    protected Qi4jSPI spi;
-
-    protected Energy4Java qi4j;
-    protected ApplicationDescriptor applicationModel;
-    protected Application application;
-
-    @Before
-    public void setUp()
-        throws Exception
-    {
-        qi4j = new Energy4Java();
-        applicationModel = newApplication();
-        if( applicationModel == null )
-        {
-            // An AssemblyException has occurred that the Test wants to check for.
-            return;
-        }
-        application = newApplicationInstance( applicationModel );
-        initApplication( application );
-        api = spi = qi4j.spi();
-        application.activate();
-    }
-
-    /** Called by the superclass for the test to define the entire application, every layer, every module and all
-     * the contents of each module.
-     *
-     * @param applicationAssembly the {@link org.qi4j.bootstrap.ApplicationAssembly} to be populated.
-     */
-    protected abstract void defineApplication( ApplicationAssembly applicationAssembly )
-        throws AssemblyException;
-
-    protected Application newApplicationInstance( ApplicationDescriptor applicationModel )
-    {
-        return applicationModel.newInstance( qi4j.api() );
-    }
-
-    protected ApplicationDescriptor newApplication()
-        throws AssemblyException
-    {
-        ApplicationAssembler assembler = new ApplicationAssembler()
-        {
-            @Override
-            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-                throws AssemblyException
-            {
-                ApplicationAssembly applicationAssembly = applicationFactory.newApplicationAssembly();
-                applicationAssembly.setMode( Application.Mode.test );
-                defineApplication( applicationAssembly );
-                return applicationAssembly;
-            }
-        };
-
-        try
-        {
-            return qi4j.newApplicationModel( assembler );
-        }
-        catch( AssemblyException e )
-        {
-            assemblyException( e );
-            return null;
-        }
-    }
-
-    /**
-     * This method is called when there was an AssemblyException in the creation of the Zest application model.
-     * <p>
-     * Override this method to catch valid failures to place into satisfiedBy suites.
-     * </p>
-     * @param exception the exception thrown.
-     *
-     * @throws org.qi4j.bootstrap.AssemblyException The default implementation of this method will simply re-throw the exception.
-     */
-    protected void assemblyException( AssemblyException exception )
-        throws AssemblyException
-    {
-        throw exception;
-    }
-
-    protected void initApplication( Application app )
-        throws Exception
-    {
-    }
-
-    @After
-    public void tearDown()
-        throws Exception
-    {
-        if( application != null )
-        {
-            application.passivate();
-        }
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/AbstractQi4jScenarioTest.java b/core/testsupport/src/main/java/org/qi4j/test/AbstractQi4jScenarioTest.java
deleted file mode 100644
index 27948f6..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/AbstractQi4jScenarioTest.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.test;
-
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.ApplicationAssemblyFactory;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.spi.Qi4jSPI;
-
-/**
- * Base class for Zest scenario tests. This will create one Zest application per class instead of per test.
- */
-public abstract class AbstractQi4jScenarioTest
-    implements Assembler
-{
-    static protected Qi4j api;
-    static protected Qi4jSPI spi;
-
-    static protected Energy4Java qi4j;
-    static protected ApplicationDescriptor applicationModel;
-    static protected Application application;
-
-    static protected Module module;
-
-    static protected Assembler assembler; // Initialize this in static block of subclass
-
-    @BeforeClass
-    public static void setUp()
-        throws Exception
-    {
-        qi4j = new Energy4Java();
-        applicationModel = newApplication();
-        if( applicationModel == null )
-        {
-            // An AssemblyException has occurred that the Test wants to check for.
-            return;
-        }
-        application = applicationModel.newInstance( qi4j.spi() );
-        initApplication( application );
-        api = spi = qi4j.spi();
-        application.activate();
-
-        // Assume only one module
-        module = application.findModule( "Layer 1", "Module 1" );
-    }
-
-    static protected ApplicationDescriptor newApplication()
-        throws AssemblyException
-    {
-        final Assembler asm = assembler;
-
-        ApplicationAssembler assembler = new ApplicationAssembler()
-        {
-            @Override
-            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-                throws AssemblyException
-            {
-                return applicationFactory.newApplicationAssembly( asm );
-            }
-        };
-        try
-        {
-            return qi4j.newApplicationModel( assembler );
-        }
-        catch( AssemblyException e )
-        {
-            assemblyException( e );
-            return null;
-        }
-    }
-
-    /**
-     * This method is called when there was an AssemblyException in the creation of the Zest application model.
-     * <p>
-     * Override this method to catch valid failures to place into satisfiedBy suites.
-     * </p>
-     *
-     * @param exception the exception thrown.
-     *
-     * @throws org.qi4j.bootstrap.AssemblyException The default implementation of this method will simply re-throw the exception.
-     */
-    static protected void assemblyException( AssemblyException exception )
-        throws AssemblyException
-    {
-        throw exception;
-    }
-
-    static protected void initApplication( Application app )
-        throws Exception
-    {
-    }
-
-    @AfterClass
-    public void tearDown()
-        throws Exception
-    {
-        if( module != null && module.isUnitOfWorkActive() )
-        {
-            while( module.isUnitOfWorkActive() )
-            {
-                UnitOfWork uow = module.currentUnitOfWork();
-                if( uow.isOpen() )
-                {
-                    uow.discard();
-                }
-                else
-                {
-                    throw new InternalError( "I have seen a case where a UoW is on the stack, but not opened. First is" + uow
-                        .usecase()
-                        .name() );
-                }
-            }
-            new Exception( "UnitOfWork not properly cleaned up" ).printStackTrace();
-        }
-
-        if( application != null )
-        {
-            application.passivate();
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/qi4j/test/AbstractQi4jTest.java b/core/testsupport/src/main/java/org/qi4j/test/AbstractQi4jTest.java
deleted file mode 100644
index 2ef0647..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/AbstractQi4jTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.test;
-
-import org.junit.After;
-import org.junit.Before;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.spi.module.ModuleSpi;
-
-/**
- * Base class for Composite tests.
- */
-public abstract class AbstractQi4jTest extends AbstractQi4jBaseTest
-    implements Assembler
-{
-    protected ModuleSpi module;
-
-    @Before
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        if( application == null )
-        {
-            return; // failure in Assembly.
-        }
-        module = (ModuleSpi) application.findModule( "Layer 1", "Module 1" );
-        module.injectTo( this );
-    }
-
-    @Override
-    protected void defineApplication( ApplicationAssembly applicationAssembly )
-        throws AssemblyException
-    {
-        LayerAssembly layer = applicationAssembly.layer( "Layer 1" );
-        ModuleAssembly module = layer.module( "Module 1" );
-        module.objects( AbstractQi4jTest.this.getClass() );
-        assemble( module );
-    }
-
-    @After
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        if( module != null && module.isUnitOfWorkActive() )
-        {
-            while( module.isUnitOfWorkActive() )
-            {
-                UnitOfWork uow = module.currentUnitOfWork();
-                if( uow.isOpen() )
-                {
-                    System.err.println( "UnitOfWork not cleaned up:" + uow.usecase().name() );
-                    uow.discard();
-                }
-                else
-                {
-                    throw new InternalError( "I have seen a case where a UoW is on the stack, but not opened. First is: " + uow
-                        .usecase()
-                        .name() );
-                }
-            }
-            new Exception( "UnitOfWork not properly cleaned up" ).printStackTrace();
-        }
-        super.tearDown();
-    }
-}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/qi4j/test/EntityTestAssembler.java b/core/testsupport/src/main/java/org/qi4j/test/EntityTestAssembler.java
deleted file mode 100644
index 6b3d91c..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/EntityTestAssembler.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.test;
-
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-/**
- * Helper assembler that adds an in-memory EntityStore, a UUID generator, and an Entity type registry to the module
- */
-public class EntityTestAssembler
-    extends Assemblers.VisibilityIdentity<EntityTestAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ServiceDeclaration service = module.services( MemoryEntityStoreService.class ).visibleIn( visibility() );
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        module.services( UuidIdentityGeneratorService.class ).visibleIn( visibility() );
-        module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/cache/AbstractCachePoolTest.java b/core/testsupport/src/main/java/org/qi4j/test/cache/AbstractCachePoolTest.java
deleted file mode 100644
index aee81d1..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/cache/AbstractCachePoolTest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright 2010 Niclas Hedhman.
- *
- * Licensed  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.qi4j.test.cache;
-
-import java.util.Collection;
-import java.util.Random;
-import org.junit.Test;
-import org.qi4j.api.constraint.ConstraintViolation;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.spi.cache.Cache;
-import org.qi4j.spi.cache.CachePool;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-
-/**
- * Abstract satisfiedBy with tests for the CachePool interface.
- */
-public abstract class AbstractCachePoolTest
-    extends AbstractQi4jTest
-{
-    protected CachePool cachePool;
-    protected Cache<String> cache;
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        cachePool = module.findService( CachePool.class ).get();
-        cache = cachePool.fetchCache( "1", String.class );
-    }
-
-    @Test
-    public void givenInvalidCacheNameWhenFetchingCacheExpectNullArgumentException()
-    {
-        try
-        {
-            cache = cachePool.fetchCache( "", String.class );
-            fail( "Expected " + NullArgumentException.class.getSimpleName() );
-        }
-        catch( NullArgumentException e )
-        {
-            // expected
-        }
-        try
-        {
-            cache = cachePool.fetchCache( null, String.class );
-            fail( "Expected " + NullArgumentException.class.getSimpleName() );
-
-        }
-        catch( ConstraintViolationException e )
-        {
-            // expected
-            Collection<ConstraintViolation> violations = e.constraintViolations();
-            assertEquals( 1, violations.size() );
-            ConstraintViolation violation = violations.iterator().next();
-            assertEquals( "not optional", violation.constraint().toString() );
-            assertEquals( "param1", violation.name() );
-        }
-    }
-
-    @Test
-    public void givenLoooongCacheNameWhenFetchingCacheExpectOk()
-    {
-        Random random = new Random();
-        StringBuilder longName = new StringBuilder();
-        for( int i = 0; i < 10000; i++ )
-        {
-            longName.append( (char) ( random.nextInt( 26 ) + 65 ) );
-        }
-        cache = cachePool.fetchCache( longName.toString(), String.class );
-    }
-
-    @Test
-    public void givenEmptyCacheWhenFetchingValueExpectNull()
-    {
-        assertNull( cache.get( "1" ) );
-    }
-
-    @Test
-    public void givenCacheWithAValueWhenRequestingThatValueExpectItBack()
-    {
-        cache.put( "Habba", "Zout" );
-        assertEquals( "Zout", cache.get( "Habba" ) );
-    }
-
-    @Test
-    public void givenCacheWithAValueWhenReplacingValueExpectNewValue()
-    {
-        cache.put( "Habba", "Zout" );
-        assertEquals( "Zout", cache.get( "Habba" ) );
-        cache.put( "Habba", "Zout2" );
-        assertEquals( "Zout2", cache.get( "Habba" ) );
-    }
-
-    @Test
-    public void givenCacheWithValueWhenDroppingReferenceAndRequestNewCacheAndItsValueExpectItToBeGone()
-    {
-        cache.put( "Habba", "Zout" );
-        assertEquals( "Zout", cache.get( "Habba" ) );
-        cachePool.returnCache( cache );
-        cache = cachePool.fetchCache( "1", String.class );
-        assertNull( "Value not missing", cache.get( "Habba" ) );
-    }
-
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/cache/AbstractEntityStoreWithCacheTest.java b/core/testsupport/src/main/java/org/qi4j/test/cache/AbstractEntityStoreWithCacheTest.java
deleted file mode 100644
index 0d3de54..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/cache/AbstractEntityStoreWithCacheTest.java
+++ /dev/null
@@ -1,165 +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.qi4j.test.cache;
-
-import org.junit.Test;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-/**
- * Assert Cache behaviour when used by an EntityStore.
- * <p>
- * Use an in-memory CachePool by default, implement the <code>assembleCachePool</code> method to override.
- */
-public abstract class AbstractEntityStoreWithCacheTest
-    extends AbstractEntityStoreTest
-{
-    @Optional @Service MemoryCachePoolService cachePool;
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        assembleCachePool( module );
-    }
-
-    protected void assembleCachePool( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( MemoryCachePoolService.class );
-    }
-
-    @Test
-    public void whenNewEntityThenCanFindEntityAndCorrectValues()
-        throws Exception
-    {
-        super.whenNewEntityThenCanFindEntityAndCorrectValues();
-        if( cachePool != null )
-        {
-            MemoryCacheImpl<?> cache = cachePool.singleCache();
-            assertThat( cache.size(), is( 1 ) );
-            assertThat( cache.gets(), is( 1 ) );
-            assertThat( cache.puts(), is( 1 ) );
-            assertThat( cache.removes(), is( 0 ) );
-            assertThat( cache.exists(), is( 0 ) );
-        }
-    }
-
-    @Test
-    public void whenRemovedEntityThenCannotFindEntity()
-        throws Exception
-    {
-        super.whenRemovedEntityThenCannotFindEntity();
-        if( cachePool != null )
-        {
-            MemoryCacheImpl<?> cache = cachePool.singleCache();
-            assertThat( cache.size(), is( 0 ) );
-            assertThat( cache.gets(), is( 2 ) );
-            assertThat( cache.puts(), is( 1 ) );
-            assertThat( cache.removes(), is( 1 ) );
-            assertThat( cache.exists(), is( 0 ) );
-        }
-    }
-
-    @Test
-    public void givenEntityIsNotModifiedWhenUnitOfWorkCompletesThenDontStoreState()
-        throws UnitOfWorkCompletionException
-    {
-        super.givenEntityIsNotModifiedWhenUnitOfWorkCompletesThenDontStoreState();
-        if( cachePool != null )
-        {
-            MemoryCacheImpl<?> cache = cachePool.singleCache();
-            assertThat( cache.size(), is( 1 ) );
-            assertThat( cache.gets(), is( 2 ) );
-            assertThat( cache.puts(), is( 1 ) );
-            assertThat( cache.removes(), is( 0 ) );
-            assertThat( cache.exists(), is( 0 ) );
-        }
-    }
-
-    @Test
-    public void givenPropertyIsModifiedWhenUnitOfWorkCompletesThenStoreState()
-        throws UnitOfWorkCompletionException
-    {
-        super.givenPropertyIsModifiedWhenUnitOfWorkCompletesThenStoreState();
-        if( cachePool != null )
-        {
-            MemoryCacheImpl<?> cache = cachePool.singleCache();
-            assertThat( cache.size(), is( 1 ) );
-            assertThat( cache.gets(), is( 2 ) );
-            assertThat( cache.puts(), is( 2 ) );
-            assertThat( cache.removes(), is( 0 ) );
-            assertThat( cache.exists(), is( 0 ) );
-        }
-    }
-
-    @Test
-    public void givenManyAssociationIsModifiedWhenUnitOfWorkCompletesThenStoreState()
-        throws UnitOfWorkCompletionException
-    {
-        super.givenManyAssociationIsModifiedWhenUnitOfWorkCompletesThenStoreState();
-        if( cachePool != null )
-        {
-            MemoryCacheImpl<?> cache = cachePool.singleCache();
-            assertThat( cache.size(), is( 1 ) );
-            assertThat( cache.gets(), is( 2 ) );
-            assertThat( cache.puts(), is( 2 ) );
-            assertThat( cache.removes(), is( 0 ) );
-            assertThat( cache.exists(), is( 0 ) );
-        }
-    }
-
-    @Test
-    public void givenConcurrentUnitOfWorksWhenUoWCompletesThenCheckConcurrentModification()
-        throws UnitOfWorkCompletionException
-    {
-        super.givenConcurrentUnitOfWorksWhenUoWCompletesThenCheckConcurrentModification();
-        if( cachePool != null )
-        {
-            MemoryCacheImpl<?> cache = cachePool.singleCache();
-            assertThat( cache.size(), is( 1 ) );
-            assertThat( cache.gets(), is( 4 ) );
-            assertThat( cache.puts(), is( 2 ) );
-            assertThat( cache.removes(), is( 0 ) );
-            assertThat( cache.exists(), is( 0 ) );
-        }
-    }
-
-    @Test
-    public void givenEntityStoredLoadedChangedWhenUnitOfWorkDiscardsThenDontStoreState()
-        throws UnitOfWorkCompletionException
-    {
-        super.givenEntityStoredLoadedChangedWhenUnitOfWorkDiscardsThenDontStoreState();
-        if( cachePool != null )
-        {
-            MemoryCacheImpl<?> cache = cachePool.singleCache();
-            assertThat( cache.size(), is( 1 ) );
-            assertThat( cache.gets(), is( 2 ) );
-            assertThat( cache.puts(), is( 1 ) );
-            assertThat( cache.removes(), is( 0 ) );
-            assertThat( cache.exists(), is( 0 ) );
-        }
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/cache/MemoryCacheImpl.java b/core/testsupport/src/main/java/org/qi4j/test/cache/MemoryCacheImpl.java
deleted file mode 100644
index 18a99c8..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/cache/MemoryCacheImpl.java
+++ /dev/null
@@ -1,142 +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.qi4j.test.cache;
-
-import java.util.concurrent.ConcurrentHashMap;
-import org.qi4j.spi.cache.Cache;
-
-/**
- * In-Memory Cache implementation based on ConcurrentHashMap.
- */
-public class MemoryCacheImpl<T>
-    implements Cache<T>
-{
-    private int refCount;
-
-    private final ConcurrentHashMap<String, Object> backingCache;
-    private final Class<T> valueType;
-    private final String id;
-
-    private int gets;
-    private int removes;
-    private int puts;
-    private int exists;
-
-    public MemoryCacheImpl( String cacheId, ConcurrentHashMap<String, Object> cache, Class<T> valueType )
-    {
-        this.id = cacheId;
-        this.backingCache = cache;
-        this.valueType = valueType;
-    }
-
-    @Override
-    public T get( String key )
-    {
-        try
-        {
-            return valueType.cast( backingCache.get( key ) );
-        }
-        finally
-        {
-            gets++;
-        }
-    }
-
-    @Override
-    public T remove( String key )
-    {
-        try
-        {
-            return valueType.cast( backingCache.remove( key ) );
-        }
-        finally
-        {
-            removes++;
-        }
-    }
-
-    @Override
-    public void put( String key, T value )
-    {
-        try
-        {
-            backingCache.put( key, value );
-        }
-        finally
-        {
-            puts++;
-        }
-    }
-
-    @Override
-    public boolean exists( String key )
-    {
-        try
-        {
-            return backingCache.containsKey( key );
-        }
-        finally
-        {
-            exists++;
-        }
-    }
-
-    synchronized void decRefCount()
-    {
-        refCount--;
-    }
-
-    synchronized void incRefCount()
-    {
-        refCount++;
-    }
-
-    synchronized boolean isNotUsed()
-    {
-        return refCount == 0;
-    }
-
-    public String cacheId()
-    {
-        return id;
-    }
-
-    public int size()
-    {
-        return backingCache.size();
-    }
-
-    public int gets()
-    {
-        return gets;
-    }
-
-    public int removes()
-    {
-        return removes;
-    }
-
-    public int puts()
-    {
-        return puts;
-    }
-
-    public int exists()
-    {
-        return exists;
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/cache/MemoryCachePoolMixin.java b/core/testsupport/src/main/java/org/qi4j/test/cache/MemoryCachePoolMixin.java
deleted file mode 100644
index cc9e014..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/cache/MemoryCachePoolMixin.java
+++ /dev/null
@@ -1,82 +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.qi4j.test.cache;
-
-import java.util.concurrent.ConcurrentHashMap;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.spi.cache.Cache;
-
-import static org.qi4j.functional.Iterables.single;
-
-/**
- * In-Memory CachePool Mixin based on ConcurrentHashMap.
- */
-public abstract class MemoryCachePoolMixin
-    implements MemoryCachePoolService
-{
-    private final ConcurrentHashMap<String, MemoryCacheImpl<?>> caches = new ConcurrentHashMap<>();
-
-    @Override
-    public <T> Cache<T> fetchCache( String cacheId, Class<T> valueType )
-    {
-        NullArgumentException.validateNotEmpty( "cacheId", cacheId );
-        MemoryCacheImpl<?> cache = caches.get( cacheId );
-        if( cache == null )
-        {
-            cache = createNewCache( cacheId, valueType );
-            caches.put( cacheId, cache );
-        }
-        cache.incRefCount();
-        return (Cache<T>) cache;
-    }
-
-    private <T> MemoryCacheImpl<T> createNewCache( String cacheId, Class<T> valueType )
-    {
-        return new MemoryCacheImpl<>( cacheId, new ConcurrentHashMap<String, Object>(), valueType );
-    }
-
-    @Override
-    public void returnCache( Cache<?> cache )
-    {
-        MemoryCacheImpl<?> memory = (MemoryCacheImpl<?>) cache;
-        memory.decRefCount();
-        if( memory.isNotUsed() )
-        {
-            caches.remove( memory.cacheId() );
-        }
-    }
-
-    @Override
-    public void activateService()
-        throws Exception
-    {
-        caches.clear();
-    }
-
-    @Override
-    public void passivateService()
-        throws Exception
-    {
-        caches.clear();
-    }
-
-    @Override
-    public MemoryCacheImpl<?> singleCache()
-    {
-        return single( caches.values() );
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/cache/MemoryCachePoolService.java b/core/testsupport/src/main/java/org/qi4j/test/cache/MemoryCachePoolService.java
deleted file mode 100644
index 66b5c94..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/cache/MemoryCachePoolService.java
+++ /dev/null
@@ -1,37 +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.qi4j.test.cache;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.spi.cache.CachePool;
-
-/**
- * In-Memory CachePool Service.
- */
-@Mixins( MemoryCachePoolMixin.class )
-public interface MemoryCachePoolService
-    extends CachePool, ServiceActivation
-{
-    /**
-     * Get the single Cache of this CachePool.
-     *
-     * @return The single Cache of this CachePool
-     * @throws IllegalArgumentException if no or more than one Cache is present in the CachePool
-     */
-    MemoryCacheImpl<?> singleCache();
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/cache/package.html b/core/testsupport/src/main/java/org/qi4j/test/cache/package.html
deleted file mode 100644
index be867a7..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/cache/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Cache SPI Test Support.</h2>
-    </body>
-</html>
diff --git a/core/testsupport/src/main/java/org/qi4j/test/entity/AbstractConfigurationDeserializationTest.java b/core/testsupport/src/main/java/org/qi4j/test/entity/AbstractConfigurationDeserializationTest.java
deleted file mode 100644
index 7e2b7ea..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/entity/AbstractConfigurationDeserializationTest.java
+++ /dev/null
@@ -1,120 +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.qi4j.test.entity;
-
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertThat;
-
-public abstract class AbstractConfigurationDeserializationTest extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-//        ModuleAssembly storageModule = module.layer().module( "storage" );
-        ModuleAssembly storageModule = module; // Disable the more complex set up. The entire value serialization has gotten the deserialization type lookup problem wrong.
-        module.configurations( ConfigSerializationConfig.class );
-        module.values( Host.class );
-        module.services( MyService.class ).identifiedBy( "configtest" );
-        storageModule.services( MemoryEntityStoreService.class ).visibleIn( Visibility.layer );
-        storageModule.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
-        storageModule.services( UuidIdentityGeneratorService.class );
-    }
-
-    @Test
-    public void givenServiceWhenInitializingExpectCorrectDeserialization()
-    {
-        ServiceReference<MyService> ref = module.findService( MyService.class );
-        assertThat( ref, notNullValue() );
-        assertThat( ref.isAvailable(), equalTo( true ) );
-        MyService myService = ref.get();
-        assertThat( myService, notNullValue() );
-        assertThat( myService.name(), equalTo( "main" ) );
-        assertThat( myService.hostIp(), equalTo( "12.23.34.45" ) );
-        assertThat( myService.hostPort(), equalTo( 1234 ) );
-    }
-
-    @Mixins( MyServiceMixin.class )
-    public interface MyService
-    {
-
-        String hostIp();
-
-        Integer hostPort();
-
-        String name();
-    }
-
-    public static class MyServiceMixin
-        implements MyService
-    {
-
-        @This
-        private Configuration<ConfigSerializationConfig> config;
-
-        @Override
-        public String hostIp()
-        {
-            return config.get().host().get().ip().get();
-        }
-
-        @Override
-        public Integer hostPort()
-        {
-            return config.get().host().get().port().get();
-        }
-
-        @Override
-        public String name()
-        {
-            return config.get().name().get();
-        }
-    }
-
-    public interface ConfigSerializationConfig extends Identity
-    {
-        Property<String> name();
-
-        Property<Host> host();
-    }
-
-    public interface Host
-    {
-        Property<String> ip();
-
-        Property<Integer> port();
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/entity/AbstractEntityStoreTest.java b/core/testsupport/src/main/java/org/qi4j/test/entity/AbstractEntityStoreTest.java
deleted file mode 100644
index f78f932..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/entity/AbstractEntityStoreTest.java
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2008, Michael Hunger. All Rights Reserved.
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2013, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.test.entity;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.joda.time.DateTime;
-import org.joda.time.LocalDate;
-import org.joda.time.LocalDateTime;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.ConcurrentEntityModificationException;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.not;
-import static org.joda.time.DateTimeZone.UTC;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-/**
- * Abstract satisfiedBy with tests for the EntityStore interface.
- */
-public abstract class AbstractEntityStoreTest
-    extends AbstractQi4jTest
-{
-
-    @Service
-    private EntityStore store;
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( UuidIdentityGeneratorService.class );
-        module.entities( TestEntity.class );
-        module.values( TestValue.class, TestValue2.class, TjabbaValue.class );
-        module.objects( getClass() );
-    }
-
-    @Before
-    public void init()
-    {
-        module.injectTo( this );
-    }
-
-    @Override
-    @After
-    public void tearDown()
-        throws Exception
-    {
-        super.tearDown();
-    }
-
-    protected TestEntity createEntity( UnitOfWork unitOfWork )
-        throws UnitOfWorkCompletionException
-    {
-        // Create entity
-        EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class );
-        builder.instance().dateValue().set( new Date() );
-        TestEntity instance = builder.newInstance();
-
-        instance.name().set( "Test" );
-        instance.intValue().set( 42 );
-        instance.longValue().set( 42L );
-        instance.doubleValue().set( 42D );
-        instance.floatValue().set( 42F );
-        instance.booleanValue().set( Boolean.TRUE );
-        instance.bigIntegerValue().set( new BigInteger( "42" ) );
-        instance.bigDecimalValue().set( new BigDecimal( "42" ) );
-        instance.dateValue().set( new DateTime( "2020-03-04T13:24:35", UTC ).toDate() );
-        instance.dateTimeValue().set( new DateTime( "2020-03-04T13:24:35", UTC ) );
-        instance.localDateTimeValue().set( new LocalDateTime( "2020-03-04T13:23:00" ) );
-        instance.localDateValue().set( new LocalDate( "2020-03-04" ) );
-        instance.association().set( instance );
-
-        ValueBuilder<Tjabba> valueBuilder4 = module.newValueBuilder( Tjabba.class );
-        final Tjabba prototype4 = valueBuilder4.prototype();
-        prototype4.bling().set( "BlinkLjus" );
-
-        // Set value
-        ValueBuilder<TestValue2> valueBuilder2 = module.newValueBuilder( TestValue2.class );
-        TestValue2 prototype2 = valueBuilder2.prototype();
-        prototype2.stringValue().set( "Bar" );
-        Tjabba newValue = valueBuilder4.newInstance();
-        prototype2.anotherValue().set( newValue );
-        prototype2.anotherValue().set( newValue );
-
-        ValueBuilder<Tjabba> valueBuilder3 = module.newValueBuilder( Tjabba.class );
-        final Tjabba prototype3 = valueBuilder3.prototype();
-        prototype3.bling().set( "Brakfis" );
-
-        ValueBuilder<TestValue> valueBuilder1 = module.newValueBuilder( TestValue.class );
-        TestValue prototype = valueBuilder1.prototype();
-        prototype.enumProperty().set( TestEnum.VALUE3 );
-        prototype.listProperty().get().add( "Foo" );
-
-        prototype.valueProperty().set( valueBuilder2.newInstance() );
-        prototype.tjabbaProperty().set( valueBuilder3.newInstance() );
-        Map<String, String> mapValue = new HashMap<>( 1 );
-        mapValue.put( "foo", "bar" );
-        prototype.mapStringStringProperty().set( mapValue );
-        instance.valueProperty().set( valueBuilder1.newInstance() );
-
-        instance.manyAssociation().add( 0, instance );
-
-        instance.namedAssociation().put( "foo", instance );
-        instance.namedAssociation().put( "bar", instance );
-
-        return instance;
-    }
-
-    @Test
-    public void whenNewEntityThenCanFindEntityAndCorrectValues()
-        throws Exception
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            TestEntity instance = createEntity( unitOfWork );
-            unitOfWork.complete();
-
-            // Find entity
-            unitOfWork = module.newUnitOfWork();
-            instance = unitOfWork.get( instance );
-
-            // Check state
-            assertThat( "property 'intValue' has correct value",
-                        instance.intValue().get(),
-                        equalTo( 42 ) );
-
-            assertThat( "property 'longValue' has correct value",
-                        instance.longValue().get(),
-                        equalTo( 42L ) );
-
-            assertThat( "property 'doubleValue' has correct value",
-                        instance.doubleValue().get(),
-                        equalTo( 42D ) );
-
-            assertThat( "property 'floatValue' has correct value",
-                        instance.floatValue().get(),
-                        equalTo( 42F ) );
-
-            assertThat( "property 'booleanValue' has correct value",
-                        instance.booleanValue().get(),
-                        equalTo( Boolean.TRUE ) );
-
-            assertThat( "property 'bigInteger' has correct value",
-                        instance.bigIntegerValue().get(),
-                        equalTo( new BigInteger( "42" ) ) );
-
-            assertThat( "property 'bigDecimal' has correct value",
-                        instance.bigDecimalValue().get(),
-                        equalTo( new BigDecimal( "42" ) ) );
-
-            assertThat( "property 'dateValue' has correct value",
-                        instance.dateValue().get(),
-                        equalTo( new DateTime( "2020-03-04T13:24:35", UTC ).toDate() ) );
-
-            assertThat( "property 'dateTimeValue' has correct value",
-                        instance.dateTimeValue().get(),
-                        equalTo( new DateTime( "2020-03-04T13:24:35", UTC ) ) );
-
-            assertThat( "property 'localDateTimeValue' has correct value",
-                        instance.localDateTimeValue().get(),
-                        equalTo( new LocalDateTime( "2020-03-04T13:23:00", UTC ) ) );
-
-            assertThat( "property 'localDateValue' has correct value",
-                        instance.localDateValue().get(),
-                        equalTo( new LocalDate( "2020-03-04" ) ) );
-
-            assertThat( "property 'name' has correct value",
-                        instance.name().get(),
-                        equalTo( "Test" ) );
-
-            assertThat( "property 'unsetName' has correct value",
-                        instance.unsetName().get(),
-                        equalTo( null ) );
-
-            assertThat( "property 'emptyName' has correct value",
-                        instance.emptyName().get(),
-                        equalTo( "" ) );
-
-            assertThat( "property 'valueProperty.stringValue' has correct value",
-                        instance.valueProperty().get().valueProperty().get().stringValue().get(),
-                        equalTo( "Bar" ) );
-
-            assertThat( "property 'valueProperty.listProperty' has correct value",
-                        instance.valueProperty().get().listProperty().get().get( 0 ),
-                        equalTo( "Foo" ) );
-
-            assertThat( "property 'valueProperty.enumProperty' has correct value",
-                        instance.valueProperty().get().enumProperty().get(),
-                        equalTo( TestEnum.VALUE3 ) );
-
-            assertThat( "property 'valueProperty.anotherValue.bling' has correct value",
-                        instance.valueProperty().get().valueProperty().get().anotherValue().get().bling().get(),
-                        equalTo( "BlinkLjus" ) );
-
-            assertThat( "property 'valueProperty.tjabbaProperty.bling' has correct value",
-                        instance.valueProperty().get().tjabbaProperty().get().bling().get(),
-                        equalTo( "Brakfis" ) );
-
-            Map<String, String> mapValue = new HashMap<>();
-            mapValue.put( "foo", "bar" );
-            assertThat( "property 'valueProperty.mapStringStringProperty' has correct value",
-                        instance.valueProperty().get().mapStringStringProperty().get(),
-                        equalTo( mapValue ) );
-
-            assertThat( "association has correct value",
-                        instance.association().get(),
-                        equalTo( instance ) );
-
-            assertThat( "manyAssociation has correct value",
-                        instance.manyAssociation().iterator().next(),
-                        equalTo( instance ) );
-
-            assertThat( "namedAssociation has correct 'foo' value",
-                        instance.namedAssociation().get( "foo" ),
-                        equalTo( instance ) );
-
-            assertThat( "namedAssociation has correct 'bar' value",
-                        instance.namedAssociation().get( "bar" ),
-                        equalTo( instance ) );
-
-            unitOfWork.discard();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    @Test
-    public void whenRemovedEntityThenCannotFindEntity()
-        throws Exception
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        TestEntity newInstance = createEntity( unitOfWork );
-        String identity = newInstance.identity().get();
-        unitOfWork.complete();
-
-        // Remove entity
-        unitOfWork = module.newUnitOfWork();
-        TestEntity instance = unitOfWork.get( newInstance );
-        unitOfWork.remove( instance );
-        unitOfWork.complete();
-
-        // Find entity
-        unitOfWork = module.newUnitOfWork();
-        try
-        {
-            unitOfWork.get( TestEntity.class, identity );
-            fail( "Should not be able to find entity" );
-        }
-        catch( NoSuchEntityException e )
-        {
-            // Ok!
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    @Test
-    public void givenEntityIsNotModifiedWhenUnitOfWorkCompletesThenDontStoreState()
-        throws UnitOfWorkCompletionException
-    {
-        TestEntity testEntity;
-        String version;
-        {
-            UnitOfWork unitOfWork = module.newUnitOfWork();
-            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class );
-
-            testEntity = builder.newInstance();
-            unitOfWork.complete();
-        }
-        {
-            UnitOfWork unitOfWork = module.newUnitOfWork();
-            testEntity = unitOfWork.get( testEntity );
-            version = spi.entityStateOf( testEntity ).version();
-
-            unitOfWork.complete();
-        }
-        {
-            UnitOfWork unitOfWork = module.newUnitOfWork();
-            testEntity = unitOfWork.get( testEntity );
-            String newVersion = spi.entityStateOf( testEntity ).version();
-            assertThat( "version has not changed", newVersion, equalTo( version ) );
-
-            unitOfWork.complete();
-        }
-    }
-
-    @Test
-    public void givenPropertyIsModifiedWhenUnitOfWorkCompletesThenStoreState()
-        throws UnitOfWorkCompletionException
-    {
-        TestEntity testEntity;
-        String version;
-        {
-            UnitOfWork unitOfWork = module.newUnitOfWork();
-            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class );
-
-            testEntity = builder.newInstance();
-            unitOfWork.complete();
-        }
-        {
-            UnitOfWork unitOfWork = module.newUnitOfWork();
-            testEntity = unitOfWork.get( testEntity );
-            testEntity.name().set( "Rickard" );
-            version = spi.entityStateOf( testEntity ).version();
-
-            unitOfWork.complete();
-        }
-        {
-            UnitOfWork unitOfWork = module.newUnitOfWork();
-            testEntity = unitOfWork.get( testEntity );
-            String newVersion = spi.entityStateOf( testEntity ).version();
-            assertThat( "version has changed", newVersion, not( equalTo( version ) ) );
-
-            unitOfWork.complete();
-        }
-    }
-
-    @Test
-    public void givenManyAssociationIsModifiedWhenUnitOfWorkCompletesThenStoreState()
-        throws UnitOfWorkCompletionException
-    {
-        TestEntity testEntity;
-        String version;
-        {
-            UnitOfWork unitOfWork = module.newUnitOfWork();
-            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class );
-
-            testEntity = builder.newInstance();
-            unitOfWork.complete();
-        }
-        {
-            UnitOfWork unitOfWork = module.newUnitOfWork();
-            testEntity = unitOfWork.get( testEntity );
-            testEntity.manyAssociation().add( 0, testEntity );
-            version = spi.entityStateOf( testEntity ).version();
-
-            unitOfWork.complete();
-        }
-        {
-            UnitOfWork unitOfWork = module.newUnitOfWork();
-            testEntity = unitOfWork.get( testEntity );
-            String newVersion = spi.entityStateOf( testEntity ).version();
-            assertThat( "version has changed", newVersion, not( equalTo( version ) ) );
-
-            unitOfWork.complete();
-        }
-    }
-
-    @Test
-    public void givenConcurrentUnitOfWorksWhenUoWCompletesThenCheckConcurrentModification()
-        throws UnitOfWorkCompletionException
-    {
-        TestEntity testEntity;
-        {
-            UnitOfWork unitOfWork = module.newUnitOfWork();
-            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class );
-
-            testEntity = builder.newInstance();
-            unitOfWork.complete();
-        }
-
-        UnitOfWork unitOfWork1;
-        TestEntity testEntity1;
-        String version;
-        {
-            // Start working with Entity in one UoW
-            unitOfWork1 = module.newUnitOfWork();
-            testEntity1 = unitOfWork1.get( testEntity );
-            version = spi.entityStateOf( testEntity1 ).version();
-            if( version.isEmpty() )
-            {
-                unitOfWork1.discard();
-                return; // Store doesn't track versions - no point in testing it
-            }
-            testEntity1.name().set( "A" );
-            testEntity1.unsetName().set( "A" );
-        }
-        {
-            // Start working with same Entity in another UoW, and complete it
-            UnitOfWork unitOfWork = module.newUnitOfWork();
-            TestEntity testEntity2 = unitOfWork.get( testEntity );
-            assertThat( "version is correct", spi.entityStateOf( testEntity1 ).version(), equalTo( version ) );
-            testEntity2.name().set( "B" );
-            unitOfWork.complete();
-        }
-        {
-            // Try to complete first UnitOfWork
-            try
-            {
-                unitOfWork1.complete();
-                fail( "Should have thrown concurrent modification exception" );
-            }
-            catch( ConcurrentEntityModificationException e )
-            {
-                unitOfWork1.discard();
-            }
-        }
-        {
-            // Check values
-            unitOfWork1 = module.newUnitOfWork();
-            testEntity1 = unitOfWork1.get( testEntity );
-            assertThat( "property name has not been set", testEntity1.name().get(), equalTo( "B" ) );
-            assertThat( "version is incorrect", spi.entityStateOf( testEntity1 ).version(),
-                        not( equalTo( version ) ) );
-            unitOfWork1.discard();
-        }
-    }
-
-    @Test
-    public void givenEntityStoredLoadedChangedWhenUnitOfWorkDiscardsThenDontStoreState()
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            String identity = createEntity( unitOfWork ).identity().get();
-            unitOfWork.complete();
-
-            unitOfWork = module.newUnitOfWork();
-            TestEntity entity = unitOfWork.get( TestEntity.class, identity );
-            assertThat( entity.intValue().get(), is( 42 ) );
-            entity.intValue().set( 23 );
-            unitOfWork.discard();
-
-            unitOfWork = module.newUnitOfWork();
-            entity = unitOfWork.get( TestEntity.class, identity );
-            assertThat( entity.intValue().get(), is( 42 ) );
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-
-    public interface TestEntity
-        extends EntityComposite
-    {
-
-        @UseDefaults
-        Property<Integer> intValue();
-
-        @UseDefaults
-        Property<Long> longValue();
-
-        @UseDefaults
-        Property<Double> doubleValue();
-
-        @UseDefaults
-        Property<Float> floatValue();
-
-        @UseDefaults
-        Property<Boolean> booleanValue();
-
-        @Optional
-        Property<BigInteger> bigIntegerValue();
-
-        @Optional
-        Property<BigDecimal> bigDecimalValue();
-
-        @Optional
-        Property<Date> dateValue();
-
-        @Optional
-        Property<DateTime> dateTimeValue();
-
-        @Optional
-        Property<LocalDateTime> localDateTimeValue();
-
-        @Optional
-        Property<LocalDate> localDateValue();
-
-        @Optional
-        Property<String> name();
-
-        @Optional
-        Property<String> unsetName();
-
-        @UseDefaults
-        Property<String> emptyName();
-
-        @Optional
-        Property<TestValue> valueProperty();
-
-        @Optional
-        Association<TestEntity> association();
-
-        @Optional
-        Association<TestEntity> unsetAssociation();
-
-        ManyAssociation<TestEntity> manyAssociation();
-
-        NamedAssociation<TestEntity> namedAssociation();
-    }
-
-    public interface TjabbaValue
-        extends Tjabba, ValueComposite
-    {
-    }
-
-    public interface Tjabba
-    {
-
-        Property<String> bling();
-    }
-
-    public interface TestValue
-        extends ValueComposite
-    {
-
-        @UseDefaults
-        Property<String> stringProperty();
-
-        @UseDefaults
-        Property<Integer> intProperty();
-
-        @UseDefaults
-        Property<TestEnum> enumProperty();
-
-        @UseDefaults
-        Property<List<String>> listProperty();
-
-        @UseDefaults
-        Property<Map<String, Tjabba>> mapProperty();
-
-        Property<TestValue2> valueProperty();
-
-        Property<Tjabba> tjabbaProperty();
-
-        Property<Map<String, String>> mapStringStringProperty();
-    }
-
-    public interface TestValue2
-        extends ValueComposite
-    {
-
-        Property<String> stringValue();
-
-        Property<Tjabba> anotherValue();
-    }
-
-    public enum TestEnum
-    {
-
-        VALUE1, VALUE2, VALUE3
-    }
-
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/entity/package.html b/core/testsupport/src/main/java/org/qi4j/test/entity/package.html
deleted file mode 100644
index abad269..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/entity/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EntityStore SPI Test Support.</h2>
-    </body>
-</html>
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/AbstractAnyQueryTest.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/AbstractAnyQueryTest.java
deleted file mode 100644
index be8e07a..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/AbstractAnyQueryTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed  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.qi4j.test.indexing;
-
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.indexing.model.Address;
-import org.qi4j.test.indexing.model.File;
-import org.qi4j.test.indexing.model.Host;
-import org.qi4j.test.indexing.model.Port;
-import org.qi4j.test.indexing.model.Protocol;
-import org.qi4j.test.indexing.model.QueryParam;
-import org.qi4j.test.indexing.model.URL;
-import org.qi4j.test.indexing.model.entities.AccountEntity;
-import org.qi4j.test.indexing.model.entities.CatEntity;
-import org.qi4j.test.indexing.model.entities.CityEntity;
-import org.qi4j.test.indexing.model.entities.DomainEntity;
-import org.qi4j.test.indexing.model.entities.FemaleEntity;
-import org.qi4j.test.indexing.model.entities.MaleEntity;
-
-/**
- * Abstract satisfiedBy with tests for any queries against Index/Query engines.
- */
-public class AbstractAnyQueryTest
-    extends AbstractQi4jTest
-{
-    protected UnitOfWork unitOfWork;
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( MaleEntity.class,
-                         FemaleEntity.class,
-                         CityEntity.class,
-                         DomainEntity.class,
-                         AccountEntity.class,
-                         CatEntity.class );
-        module.values( URL.class,
-                       Address.class,
-                       Protocol.class,
-                       Host.class,
-                       Port.class,
-                       File.class,
-                       QueryParam.class );
-
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        TestData.populate( module );
-
-        this.unitOfWork = this.module.newUnitOfWork();
-    }
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        if( this.unitOfWork != null )
-        {
-            this.unitOfWork.discard();
-            this.unitOfWork = null;
-        }
-        super.tearDown();
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/AbstractComplexQueryTest.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/AbstractComplexQueryTest.java
deleted file mode 100644
index 398f29d..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/AbstractComplexQueryTest.java
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.test.indexing;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.junit.Test;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.spi.query.IndexExporter;
-import org.qi4j.test.indexing.model.Address;
-import org.qi4j.test.indexing.model.Person;
-import org.qi4j.test.indexing.model.Protocol;
-import org.qi4j.test.indexing.model.QueryParam;
-import org.qi4j.test.indexing.model.URL;
-
-import static org.qi4j.api.query.QueryExpressions.contains;
-import static org.qi4j.api.query.QueryExpressions.containsAll;
-import static org.qi4j.api.query.QueryExpressions.eq;
-import static org.qi4j.api.query.QueryExpressions.not;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-import static org.qi4j.test.indexing.NameableAssert.verifyUnorderedResults;
-
-/**
- * Abstract satisfiedBy with tests for complex queries against Index/Query engines, ie. queries by "example values".
- */
-public abstract class AbstractComplexQueryTest
-    extends AbstractAnyQueryTest
-{
-
-    private static final String ANN = "Ann Doe";
-    private static final String JOE = "Joe Doe";
-    private static final String JACK = "Jack Doe";
-
-    @Test
-    public void showNetwork()
-        throws IOException
-    {
-        IndexExporter indexerExporter = module.<IndexExporter>findService( IndexExporter.class ).get();
-        indexerExporter.exportReadableToStream( System.out );
-    }
-
-    @Test
-    public void script01()
-    {
-        ValueBuilder<Address> addressBuilder = this.module.newValueBuilder( Address.class );
-        Address address = addressBuilder.prototype();
-        address.line1().set( "Qi Street 4j" );
-        address.line2().set( "Off main Java Street" );
-        address.zipcode().set( "12345" );
-
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Property<Address> addressProp = templateFor( Person.class ).address();
-        qb = qb.where( eq( addressProp, addressBuilder.newInstance() ) );
-        Query<Person> query = unitOfWork.newQuery( qb );
-        System.out.println( "*** script01: " + query );
-
-        verifyUnorderedResults( query, ANN );
-    }
-
-    @Test
-    public void script02()
-    {
-        ValueBuilder<Address> addressBuilder = this.module.newValueBuilder( Address.class );
-        Address address = addressBuilder.prototype();
-        address.line1().set( "Qi Street 4j" );
-        address.line2().set( "Off main Java Street" );
-        address.zipcode().set( "12345" );
-
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Property<Address> addressProp = templateFor( Person.class ).address();
-        qb = qb.where( not( eq( addressProp, addressBuilder.newInstance() ) ) );
-        Query<Person> query = unitOfWork.newQuery( qb );
-        System.out.println( "*** script02: " + query );
-
-        verifyUnorderedResults( query, JOE, JACK );
-    }
-
-    @Test
-    public void script03()
-    {
-        ValueBuilder<QueryParam> queryParamBuilder = this.module.newValueBuilder( QueryParam.class );
-        List<QueryParam> queryParams = new ArrayList<>( 2 );
-        QueryParam param = queryParamBuilder.prototype();
-        param.name().set( "user" );
-        param.value().set( "jackdoe" );
-        queryParams.add( queryParamBuilder.newInstance() );
-
-        queryParamBuilder = this.module.newValueBuilder( QueryParam.class );
-        param = queryParamBuilder.prototype();
-        param.name().set( "password" );
-        param.value().set( "somepassword" );
-        queryParams.add( queryParamBuilder.newInstance() );
-
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Property<Collection<QueryParam>> paramsProp = templateFor( Person.class ).personalWebsite().get().queryParams();
-        qb = qb.where( eq( paramsProp, queryParams ) );
-        Query<Person> query = unitOfWork.newQuery( qb );
-        System.out.println( "*** script03: " + query );
-
-        verifyUnorderedResults( query, JACK );
-    }
-
-    @Test
-    public void script04()
-    {
-        ValueBuilder<QueryParam> queryParamBuilder = this.module.newValueBuilder( QueryParam.class );
-        List<QueryParam> queryParams = new ArrayList<>( 2 );
-        QueryParam param = queryParamBuilder.prototype();
-        // Different order
-        param.name().set( "password" );
-        param.value().set( "somepassword" );
-        queryParams.add( queryParamBuilder.newInstance() );
-
-        queryParamBuilder = this.module.newValueBuilder( QueryParam.class );
-        param = queryParamBuilder.prototype();
-        param.name().set( "user" );
-        param.value().set( "jackdoe" );
-        queryParams.add( queryParamBuilder.newInstance() );
-
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Property<Collection<QueryParam>> paramsProp = templateFor( Person.class ).personalWebsite().get().queryParams();
-        qb = qb.where( eq( paramsProp, queryParams ) );
-        Query<Person> query = unitOfWork.newQuery( qb );
-        System.out.println( "*** script04: " + query );
-
-        verifyUnorderedResults( query );
-    }
-
-    @Test
-    public void script05()
-    {
-        ValueBuilder<QueryParam> queryParamBuilder = this.module.newValueBuilder( QueryParam.class );
-        List<QueryParam> queryParams = new ArrayList<>( 2 );
-        QueryParam param = queryParamBuilder.prototype();
-        param.name().set( "user" );
-        param.value().set( "jackdoe" );
-        queryParams.add( queryParamBuilder.newInstance() );
-
-        queryParamBuilder = this.module.newValueBuilder( QueryParam.class );
-        param = queryParamBuilder.prototype();
-        param.name().set( "password" );
-        param.value().set( "somepassword" );
-        queryParams.add( queryParamBuilder.newInstance() );
-
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Property<Collection<QueryParam>> paramsProp = templateFor( Person.class ).personalWebsite().get().queryParams();
-        qb = qb.where( not( eq( paramsProp, queryParams ) ) );
-        Query<Person> query = unitOfWork.newQuery( qb );
-        System.out.println( "*** script05: " + query );
-
-        verifyUnorderedResults( query, ANN, JOE );
-    }
-
-    @Test
-    public void script06()
-    {
-        ValueBuilder<URL> urlBuilder = this.module.newValueBuilder( URL.class );
-        ValueBuilder<Protocol> protocolBuilder = this.module.newValueBuilder( Protocol.class );
-        ValueBuilder<QueryParam> queryParamBuilder = this.module.newValueBuilder( QueryParam.class );
-
-        Protocol protocol = protocolBuilder.prototype();
-        protocol.value().set( "http" );
-
-        List<QueryParam> queryParams = new ArrayList<>( 2 );
-        QueryParam param = queryParamBuilder.prototype();
-        param.name().set( "user" );
-        param.value().set( "jackdoe" );
-        queryParams.add( queryParamBuilder.newInstance() );
-
-        queryParamBuilder = this.module.newValueBuilder( QueryParam.class );
-        param = queryParamBuilder.prototype();
-        param.name().set( "password" );
-        param.value().set( "somepassword" );
-        queryParams.add( queryParamBuilder.newInstance() );
-
-        URL url = urlBuilder.prototype();
-        url.protocol().set( protocolBuilder.newInstance() );
-        url.queryParams().set( queryParams );
-
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Property<URL> websiteProp = templateFor( Person.class ).personalWebsite();
-        qb = qb.where( eq( websiteProp, urlBuilder.newInstance() ) );
-        Query<Person> query = unitOfWork.newQuery( qb );
-        System.out.println( "*** script06: " + query );
-
-        verifyUnorderedResults( query, JACK );
-    }
-
-    @Test
-    public void script07()
-    {
-        ValueBuilder<URL> urlBuilder = this.module.newValueBuilder( URL.class );
-        ValueBuilder<Protocol> protocolBuilder = this.module.newValueBuilder( Protocol.class );
-        ValueBuilder<QueryParam> queryParamBuilder = this.module.newValueBuilder( QueryParam.class );
-
-        Protocol protocol = protocolBuilder.prototype();
-        protocol.value().set( "http" );
-
-        List<QueryParam> queryParams = new ArrayList<>( 2 );
-        QueryParam param = queryParamBuilder.prototype();
-        param.name().set( "user" );
-        param.value().set( "jackdoe" );
-        queryParams.add( queryParamBuilder.newInstance() );
-
-        queryParamBuilder = this.module.newValueBuilder( QueryParam.class );
-        param = queryParamBuilder.prototype();
-        param.name().set( "password" );
-        param.value().set( "somepassword" );
-        queryParams.add( queryParamBuilder.newInstance() );
-
-        URL url = urlBuilder.prototype();
-        url.protocol().set( protocolBuilder.newInstance() );
-        url.queryParams().set( queryParams );
-
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Property<URL> websiteProp = templateFor( Person.class ).personalWebsite();
-        qb = qb.where( not( eq( websiteProp, urlBuilder.newInstance() ) ) );
-        Query<Person> query = unitOfWork.newQuery( qb );
-        System.out.println( "*** script07: " + query );
-
-        verifyUnorderedResults( query, ANN, JOE );
-    }
-
-    @Test
-    public void script08()
-    {
-        ValueBuilder<QueryParam> queryParamBuilder = this.module.newValueBuilder( QueryParam.class );
-        QueryParam param = queryParamBuilder.prototype();
-        param.name().set( "user" );
-        param.value().set( "jackdoe" );
-
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Property<Collection<QueryParam>> paramsProp = templateFor( Person.class ).personalWebsite().get().queryParams();
-        qb = qb.where( contains( paramsProp, queryParamBuilder.newInstance() ) );
-        Query<Person> query = unitOfWork.newQuery( qb );
-        System.out.println( "*** script08: " + query );
-        verifyUnorderedResults( query, JACK );
-    }
-
-    @Test
-    public void script09()
-    {
-        ValueBuilder<QueryParam> queryParamBuilder = this.module.newValueBuilder( QueryParam.class );
-
-        QueryParam param = queryParamBuilder.prototype();
-        param.name().set( "user" );
-        param.value().set( "jackdoe" );
-
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Property<Collection<QueryParam>> paramsProp = templateFor( Person.class ).personalWebsite().get().queryParams();
-        qb = qb.where( not( contains( paramsProp, queryParamBuilder.newInstance() ) ) );
-        Query<Person> query = unitOfWork.newQuery( qb );
-        System.out.println( "*** script09: " + query );
-        verifyUnorderedResults( query, ANN, JOE );
-    }
-
-    @Test
-    public void script10()
-    {
-        ValueBuilder<QueryParam> queryParamBuilder = this.module.newValueBuilder( QueryParam.class );
-
-        List<QueryParam> queryParams = new ArrayList<>( 2 );
-        QueryParam param = queryParamBuilder.prototype();
-        param.name().set( "user" );
-        param.value().set( "jackdoe" );
-        queryParams.add( queryParamBuilder.newInstance() );
-
-        queryParamBuilder = this.module.newValueBuilder( QueryParam.class );
-        param = queryParamBuilder.prototype();
-        param.name().set( "password" );
-        param.value().set( "somepassword" );
-        queryParams.add( queryParamBuilder.newInstance() );
-
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Property<Collection<QueryParam>> paramsProp = templateFor( Person.class ).personalWebsite().get().queryParams();
-        qb = qb.where( containsAll( paramsProp, queryParams ) );
-        Query<Person> query = unitOfWork.newQuery( qb );
-        System.out.println( "*** script10: " + query );
-        verifyUnorderedResults( query, JACK );
-    }
-
-    @Test
-    public void script11()
-    {
-        ValueBuilder<QueryParam> queryParamBuilder = this.module.newValueBuilder( QueryParam.class );
-
-        List<QueryParam> queryParams = new ArrayList<>( 2 );
-        QueryParam param = queryParamBuilder.prototype();
-        param.name().set( "user" );
-        param.value().set( "jackdoe" );
-        queryParams.add( queryParamBuilder.newInstance() );
-
-        queryParamBuilder = this.module.newValueBuilder( QueryParam.class );
-        param = queryParamBuilder.prototype();
-        param.name().set( "password" );
-        param.value().set( "somepassword" );
-        queryParams.add( queryParamBuilder.newInstance() );
-
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Property<Collection<QueryParam>> paramsProp = templateFor( Person.class ).personalWebsite().get().queryParams();
-        qb = qb.where( not( containsAll( paramsProp, queryParams ) ) );
-        Query<Person> query = unitOfWork.newQuery( qb );
-        System.out.println( "*** script11: " + query );
-        verifyUnorderedResults( query, ANN, JOE );
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/AbstractEntityFinderTest.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/AbstractEntityFinderTest.java
deleted file mode 100644
index 8d881b7..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/AbstractEntityFinderTest.java
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- * Copyright 2012 Stanislav Muhametsin.
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.test.indexing;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.functional.Specification;
-import org.qi4j.spi.query.EntityFinder;
-import org.qi4j.spi.query.EntityFinderException;
-import org.qi4j.spi.query.IndexExporter;
-import org.qi4j.test.indexing.model.Domain;
-import org.qi4j.test.indexing.model.Female;
-import org.qi4j.test.indexing.model.Male;
-import org.qi4j.test.indexing.model.Nameable;
-import org.qi4j.test.indexing.model.Person;
-
-import static org.junit.Assert.assertEquals;
-import static org.qi4j.api.query.QueryExpressions.and;
-import static org.qi4j.api.query.QueryExpressions.eq;
-import static org.qi4j.api.query.QueryExpressions.ge;
-import static org.qi4j.api.query.QueryExpressions.gt;
-import static org.qi4j.api.query.QueryExpressions.isNotNull;
-import static org.qi4j.api.query.QueryExpressions.isNull;
-import static org.qi4j.api.query.QueryExpressions.matches;
-import static org.qi4j.api.query.QueryExpressions.not;
-import static org.qi4j.api.query.QueryExpressions.or;
-import static org.qi4j.api.query.QueryExpressions.orderBy;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-import static org.qi4j.api.query.QueryExpressions.variable;
-import static org.qi4j.functional.Iterables.toList;
-import static org.qi4j.test.indexing.NameableAssert.assertNames;
-
-/**
- * Abstract satisfiedBy with tests for the EntityFinder interface.
- */
-public abstract class AbstractEntityFinderTest
-    extends AbstractAnyQueryTest
-{
-
-    private static final Specification<Composite> ALL = null;
-
-    private static final OrderBy[] NO_SORTING = null;
-
-    private static final Integer NO_FIRST_RESULT = null;
-
-    private static final Integer NO_MAX_RESULTS = null;
-
-    private static final Map<String, Object> NO_VARIABLES = Collections.<String, Object>emptyMap();
-
-    private static final String JACK = "Jack Doe";
-
-    private static final String JOE = "Joe Doe";
-
-    private static final String ANN = "Ann Doe";
-
-    private EntityFinder entityFinder;
-
-    @Before
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        entityFinder = this.module.findService( EntityFinder.class ).get();
-    }
-
-    @Test
-    public void showNetwork()
-        throws IOException
-    {
-        final ServiceReference<IndexExporter> indexerService = this.module.findService( IndexExporter.class );
-        final IndexExporter exporter = indexerService.get();
-        exporter.exportReadableToStream( System.out );
-        // todo asserts
-    }
-
-    @Test
-    public void script01()
-        throws EntityFinderException
-    {
-        // should return all persons (Joe, Ann, Jack Doe)
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Person.class,
-            ALL,
-            NO_SORTING,
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( entities, JOE, JACK, ANN );
-    }
-
-    @Test
-    public void script02()
-        throws EntityFinderException
-    {
-        Nameable nameable = templateFor( Nameable.class );
-        // should return Gaming domain
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Domain.class,
-            eq( nameable.name(), "Gaming" ),
-            NO_SORTING,
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( entities, "Gaming" );
-    }
-
-    @Test
-    public void script03()
-        throws EntityFinderException
-    {
-        // should return all entities
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Nameable.class,
-            ALL,
-            NO_SORTING,
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( entities, NameableAssert.allNames() );
-    }
-
-    @Test
-    public void script04()
-        throws EntityFinderException
-    {
-        Person person = templateFor( Person.class );
-        // should return Joe and Ann Doe
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Person.class,
-            eq( person.placeOfBirth().get().name(), "Kuala Lumpur" ),
-            NO_SORTING,
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( entities, JOE, ANN );
-    }
-
-    @Test
-    public void script05()
-        throws EntityFinderException
-    {
-        Person person = templateFor( Person.class );
-        // should return Joe Doe
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Person.class,
-            eq( person.mother().get().placeOfBirth().get().name(), "Kuala Lumpur" ),
-            NO_SORTING,
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( entities, JOE );
-    }
-
-    @Test
-    public void script06()
-        throws EntityFinderException
-    {
-        Person person = templateFor( Person.class );
-        // should return Joe and Ann Doe
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Person.class,
-            ge( person.yearOfBirth(), 1973 ),
-            NO_SORTING,
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( entities, JOE, ANN );
-    }
-
-    @Test
-    @SuppressWarnings( "unchecked" )
-    public void script07()
-        throws EntityFinderException
-    {
-        Person person = templateFor( Person.class );
-        // should return Jack Doe
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Nameable.class,
-            and( ge( person.yearOfBirth(), 1900 ), eq( person.placeOfBirth().get().name(), "Penang" ) ),
-            NO_SORTING,
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( entities, JACK );
-    }
-
-    @Test
-    @SuppressWarnings( "unchecked" )
-    public void script08()
-        throws EntityFinderException
-    {
-        Person person = templateFor( Person.class );
-        // should return Jack and Ann Doe
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Person.class,
-            or( eq( person.yearOfBirth(), 1970 ), eq( person.yearOfBirth(), 1975 ) ),
-            NO_SORTING,
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( entities, JACK, ANN );
-    }
-
-    @Test
-    @SuppressWarnings( "unchecked" )
-    public void script09()
-        throws EntityFinderException
-    {
-        Person person = templateFor( Person.class );
-        // should return Ann Doe
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Female.class,
-            or( eq( person.yearOfBirth(), 1970 ), eq( person.yearOfBirth(), 1975 ) ),
-            NO_SORTING,
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( entities, ANN );
-    }
-
-    @Test
-    public void script10()
-        throws EntityFinderException
-    {
-        Person person = templateFor( Person.class );
-        // should return Joe and Jack Doe
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Person.class,
-            not( eq( person.yearOfBirth(), 1975 ) ),
-            NO_SORTING,
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( entities, JOE, JACK );
-    }
-
-    @Test
-    public void script11()
-        throws EntityFinderException
-    {
-        Person person = templateFor( Person.class );
-        // should return Joe Doe
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Person.class,
-            isNotNull( person.email() ),
-            NO_SORTING,
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( entities, JOE );
-    }
-
-    @Test
-    public void script12()
-        throws EntityFinderException
-    {
-        Person person = templateFor( Person.class );
-        // should return Ann and Jack Doe
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Person.class,
-            isNull( person.email() ),
-            NO_SORTING,
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( entities, ANN, JACK );
-    }
-
-    @Test
-    public void script13()
-        throws EntityFinderException
-    {
-        Male person = templateFor( Male.class );
-        // should return Jack Doe
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Person.class,
-            isNotNull( person.wife() ),
-            NO_SORTING,
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( entities, JACK );
-    }
-
-    @Test
-    public void script14()
-        throws EntityFinderException
-    {
-        Male person = templateFor( Male.class );
-        // should return Joe Doe
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Male.class,
-            isNull( person.wife() ),
-            NO_SORTING,
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( entities, JOE );
-    }
-
-    @Test
-    public void script15()
-        throws EntityFinderException
-    {
-        Male person = templateFor( Male.class );
-        // should return Ann and Joe Doe
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Person.class,
-            isNull( person.wife() ),
-            NO_SORTING,
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( entities, ANN, JOE );
-    }
-
-    @Test
-    public void script16()
-        throws EntityFinderException
-    {
-        // should return only 2 entities
-        final List<EntityReference> references = toList( entityFinder.findEntities(
-            Nameable.class,
-            ALL,
-            NO_SORTING,
-            NO_FIRST_RESULT, 2,
-            NO_VARIABLES ) );
-        assertEquals( "2 identitities", 2, references.size() );
-    }
-
-    @Test
-    public void script17()
-        throws EntityFinderException
-    {
-        // should return only 2 entities starting with third one
-        final List<EntityReference> references = toList( entityFinder.findEntities(
-            Nameable.class,
-            ALL,
-            NO_SORTING,
-            3, 2,
-            NO_VARIABLES ) );
-        assertEquals( "2 identitities", 2, references.size() );
-    }
-
-    @Test
-    public void script18()
-        throws EntityFinderException
-    {
-        // should return all Nameable entities sorted by name
-        Nameable nameable = templateFor( Nameable.class );
-        final String[] allNames = NameableAssert.allNames();
-        Arrays.sort( allNames );
-
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Nameable.class,
-            ALL,
-            new OrderBy[]
-        {
-            orderBy( nameable.name() )
-            },
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( false, entities, allNames );
-    }
-
-    @Test
-    public void script19()
-        throws EntityFinderException
-    {
-        // should return all Nameable entities with a name > "B" sorted by name
-        Nameable nameable = templateFor( Nameable.class );
-        List<String> largerThanB = new ArrayList<>();
-        for( String name : NameableAssert.allNames() )
-        {
-            if( name.compareTo( "B" ) > 0 )
-            {
-                largerThanB.add( name );
-            }
-        }
-        Collections.sort( largerThanB );
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Nameable.class,
-            gt( nameable.name(), "B" ),
-            new OrderBy[]
-        {
-            orderBy( nameable.name() )
-            },
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( false, entities, largerThanB.toArray( new String[ largerThanB.size() ] ) );
-    }
-
-    @Test
-    public void script20()
-        throws EntityFinderException
-    {
-        // should return all Persons born after 1973 (Ann and Joe Doe) sorted descending by name
-        Person person = templateFor( Person.class );
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Person.class,
-            gt( person.yearOfBirth(), 1973 ),
-            new OrderBy[]
-        {
-            orderBy( person.name(), OrderBy.Order.DESCENDING )
-            },
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( false, entities, JOE, ANN );
-    }
-
-    @Test
-    public void script21()
-        throws EntityFinderException
-    {
-        // should return all Persons sorted name of the city they were born
-        Person person = templateFor( Person.class );
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Person.class,
-            ALL,
-            new OrderBy[]
-        {
-            orderBy( person.placeOfBirth().get().name() ), orderBy( person.name() )
-            },
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( false, entities, ANN, JOE, JACK );
-    }
-
-    @Test
-    public void script22()
-        throws EntityFinderException
-    {
-        Nameable nameable = templateFor( Nameable.class );
-        // should return Jack and Joe Doe
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Nameable.class,
-            matches( nameable.name(), "J.*Doe" ),
-            NO_SORTING,
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            NO_VARIABLES );
-        assertNames( entities, JACK, JOE );
-    }
-
-    @Test
-    public void script23()
-        throws EntityFinderException
-    {
-        Nameable nameable = templateFor( Nameable.class );
-        // Try using variables
-        Map<String, Object> variables = new HashMap<>( 1 );
-        variables.put( "domain", "Gaming" );
-        Iterable<EntityReference> entities = entityFinder.findEntities(
-            Domain.class,
-            eq( nameable.name(), variable( "domain" ) ),
-            NO_SORTING,
-            NO_FIRST_RESULT, NO_MAX_RESULTS,
-            variables );
-        assertNames( entities, "Gaming" );
-    }
-
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/AbstractNamedQueryTest.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/AbstractNamedQueryTest.java
deleted file mode 100644
index a00e293..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/AbstractNamedQueryTest.java
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.test.indexing;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import org.junit.Test;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Specification;
-import org.qi4j.spi.query.EntityFinderException;
-import org.qi4j.spi.query.IndexExporter;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.indexing.model.Domain;
-import org.qi4j.test.indexing.model.Female;
-import org.qi4j.test.indexing.model.Male;
-import org.qi4j.test.indexing.model.Nameable;
-import org.qi4j.test.indexing.model.Person;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.api.query.QueryExpressions.orderBy;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-import static org.qi4j.test.indexing.NameableAssert.verifyOrderedResults;
-import static org.qi4j.test.indexing.NameableAssert.verifyUnorderedResults;
-
-/**
- * Abstract satisfiedBy with tests for named queries against Index/Query engines.
- */
-public abstract class AbstractNamedQueryTest
-    extends AbstractAnyQueryTest
-{
-
-    private final Map<String, Specification<Composite>> queries = new HashMap<>();
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        new EntityTestAssembler().assemble( module );
-        String[] query = queryStrings();
-        for( int i = 0; i < query.length; i++ )
-        {
-            String queryName = String.format( "script%02d", i + 1 );
-            if( query[i].length() != 0 )
-            {
-                Specification<Composite> expression = createNamedQueryDescriptor( queryName, query[i] );
-                queries.put( queryName, expression );
-            }
-        }
-    }
-
-    protected abstract String[] queryStrings();
-
-    protected abstract Specification<Composite> createNamedQueryDescriptor( String queryName, String queryString );
-
-    @Test
-    public void showNetwork()
-        throws IOException
-    {
-        IndexExporter indexerExporter = module.findService( IndexExporter.class ).get();
-        indexerExporter.exportReadableToStream( System.out );
-    }
-
-    @Test
-    public void script01()
-        throws EntityFinderException
-    {
-        final Query<Person> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Person.class )
-            .where( queries.get( "script01" ) ) );
-        System.out.println( "*** script01: " + query );
-        verifyUnorderedResults( query, "Joe Doe", "Ann Doe", "Jack Doe" );
-    }
-
-    @Test
-    public void script02()
-        throws EntityFinderException
-    {
-        final Query<Domain> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Domain.class )
-            .where( queries.get( "script02" ) ) );
-        System.out.println( "*** script02: " + query );
-        verifyUnorderedResults( query, "Gaming" );
-    }
-
-    @Test
-    public void script03()
-        throws EntityFinderException
-    {
-        final Query<Nameable> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Nameable.class )
-            .where( queries.get( "script03" ) ) );
-        System.out.println( "*** script03: " + query );
-        verifyUnorderedResults( query, "Joe Doe", "Ann Doe", "Jack Doe", "Penang", "Kuala Lumpur", "Cooking", "Gaming",
-                                "Programming", "Cars" );
-    }
-
-    @Test
-    public void script04()
-        throws EntityFinderException
-    {
-        final Query<Person> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Person.class )
-            .where( queries.get( "script04" ) ) );
-        System.out.println( "*** script04: " + query );
-        verifyUnorderedResults( query, "Joe Doe", "Ann Doe" );
-    }
-
-    @Test
-    public void script05()
-        throws EntityFinderException
-    {
-        final Query<Person> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Person.class )
-            .where( queries.get( "script05" ) ) );
-        System.out.println( "*** script05: " + query );
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script06()
-        throws EntityFinderException
-    {
-        final Query<Person> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Person.class )
-            .where( queries.get( "script06" ) ) );
-        System.out.println( "*** script06: " + query );
-        verifyUnorderedResults( query, "Joe Doe", "Ann Doe" );
-    }
-
-    @Test
-    public void script07()
-        throws EntityFinderException
-    {
-        final Query<Nameable> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Nameable.class )
-            .where( queries.get( "script07" ) ) );
-        System.out.println( "*** script07: " + query );
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void script08()
-        throws EntityFinderException
-    {
-        final Query<Person> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Person.class )
-            .where( queries.get( "script08" ) ) );
-        System.out.println( "*** script08: " + query );
-        verifyUnorderedResults( query, "Jack Doe", "Ann Doe" );
-    }
-
-    @Test
-    public void script09()
-        throws EntityFinderException
-    {
-        final Query<Female> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Female.class )
-            .where( queries.get( "script09" ) ) );
-        System.out.println( "*** script09: " + query );
-        verifyUnorderedResults( query, "Ann Doe" );
-    }
-
-    @Test
-    public void script10()
-        throws EntityFinderException
-    {
-        final Query<Person> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Person.class )
-            .where( queries.get( "script10" ) ) );
-        System.out.println( "*** script10: " + query );
-        verifyUnorderedResults( query, "Jack Doe", "Joe Doe" );
-    }
-
-    @Test
-    public void script11()
-        throws EntityFinderException
-    {
-        final Query<Person> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Person.class )
-            .where( queries.get( "script11" ) ) );
-        System.out.println( "*** script11: " + query );
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script12()
-        throws EntityFinderException
-    {
-        final Query<Person> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Person.class )
-            .where( queries.get( "script12" ) ) );
-        System.out.println( "*** script12: " + query );
-        verifyUnorderedResults( query, "Ann Doe", "Jack Doe" );
-    }
-
-    @Test
-    public void script13()
-        throws EntityFinderException
-    {
-        final Query<Person> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Person.class )
-            .where( queries.get( "script13" ) ) );
-        System.out.println( "*** script13: " + query );
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void script14()
-        throws EntityFinderException
-    {
-        final Query<Male> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Male.class )
-            .where( queries.get( "script14" ) ) );
-        System.out.println( "*** script14: " + query );
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script15()
-        throws EntityFinderException
-    {
-        final Query<Person> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Person.class )
-            .where( queries.get( "script15" ) ) );
-        System.out.println( "*** script15: " + query );
-        verifyUnorderedResults( query, "Joe Doe", "Ann Doe" );
-    }
-
-    @Test
-    public void script16()
-        throws EntityFinderException
-    {
-        Nameable nameable = templateFor( Nameable.class );
-        final Query<Nameable> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Nameable.class )
-            .where( queries.get( "script16" ) ) );
-        query.orderBy( orderBy( nameable.name() ) );
-        query.maxResults( 2 );
-        System.out.println( "*** script16: " + query );
-        verifyOrderedResults( query, "Ann Doe", "Cars" );
-    }
-
-    @Test
-    public void script17()
-        throws EntityFinderException
-    {
-        Nameable nameable = templateFor( Nameable.class );
-        final Query<Nameable> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Nameable.class )
-            .where( queries.get( "script17" ) ) );
-        query.orderBy( orderBy( nameable.name() ) );
-        query.firstResult( 3 );
-        query.maxResults( 3 );
-        System.out.println( "*** script17: " + query );
-        verifyOrderedResults( query, "Gaming", "Jack Doe", "Joe Doe" );
-    }
-
-    @Test
-    public void script18()
-        throws EntityFinderException
-    {
-        Nameable nameable = templateFor( Nameable.class );
-        final Query<Nameable> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Nameable.class )
-            .where( queries.get( "script18" ) ) );
-        query.orderBy( orderBy( nameable.name() ) );
-        System.out.println( "*** script18: " + query );
-        verifyOrderedResults( query, "Ann Doe", "Cars", "Cooking", "Gaming", "Jack Doe", "Joe Doe", "Kuala Lumpur",
-                              "Penang", "Programming" );
-    }
-
-    @Test
-    public void script19()
-        throws EntityFinderException
-    {
-        Nameable nameable = templateFor( Nameable.class );
-        final Query<Nameable> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Nameable.class )
-            .where( queries.get( "script19" ) ) );
-        query.orderBy( orderBy( nameable.name() ) );
-        System.out.println( "*** script19: " + query );
-        verifyOrderedResults( query, "Gaming", "Jack Doe", "Joe Doe", "Kuala Lumpur", "Penang", "Programming" );
-    }
-
-    @Test
-    public void script20()
-        throws EntityFinderException
-    {
-        Person person = templateFor( Person.class );
-        final Query<Person> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Person.class )
-            .where( queries.get( "script20" ) ) );
-        query.orderBy( orderBy( person.name(), OrderBy.Order.DESCENDING ) );
-        System.out.println( "*** script20: " + query );
-        verifyOrderedResults( query, "Joe Doe", "Ann Doe" );
-    }
-
-    @Test
-    public void script21()
-        throws EntityFinderException
-    {
-        Person person = templateFor( Person.class );
-        final Query<Person> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Person.class )
-            .where( queries.get( "script21" ) ) );
-        query.orderBy( orderBy( person.placeOfBirth().get().name() ), orderBy( person.yearOfBirth() ) );
-        System.out.println( "*** script21: " + query );
-        verifyOrderedResults( query, "Ann Doe", "Joe Doe", "Jack Doe" );
-    }
-
-    @Test
-    public void script22()
-        throws EntityFinderException
-    {
-        final Query<Nameable> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Nameable.class )
-            .where( queries.get( "script22" ) ) );
-        System.out.println( "*** script22: " + query );
-        verifyUnorderedResults( query, "Jack Doe", "Joe Doe" );
-    }
-
-    @Test
-    public void script24()
-        throws EntityFinderException
-    {
-        final Query<Domain> query = unitOfWork.newQuery( this.module
-            .newQueryBuilder( Domain.class )
-            .where( queries.get( "script24" ) ) );
-        query.setVariable( "domain", "Gaming" );
-        System.out.println( "*** script24: " + query );
-        assertThat( query.find().name().get(), is( equalTo( "Gaming" ) ) );
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/AbstractQueryTest.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/AbstractQueryTest.java
deleted file mode 100644
index 8794358..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/AbstractQueryTest.java
+++ /dev/null
@@ -1,833 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- * Copyright 2009-2012 Niclas Hedhman.
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.test.indexing;
-
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.HashMap;
-import java.util.Map;
-import org.joda.time.DateTime;
-import org.joda.time.LocalDate;
-import org.joda.time.LocalDateTime;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.qi4j.api.query.NotQueryableException;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.spi.query.EntityFinderException;
-import org.qi4j.spi.query.IndexExporter;
-import org.qi4j.test.indexing.model.Account;
-import org.qi4j.test.indexing.model.City;
-import org.qi4j.test.indexing.model.Domain;
-import org.qi4j.test.indexing.model.Female;
-import org.qi4j.test.indexing.model.File;
-import org.qi4j.test.indexing.model.Male;
-import org.qi4j.test.indexing.model.Nameable;
-import org.qi4j.test.indexing.model.Person;
-import org.qi4j.test.indexing.model.QueryParam;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.joda.time.DateTimeZone.UTC;
-import static org.joda.time.DateTimeZone.forID;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.api.query.QueryExpressions.and;
-import static org.qi4j.api.query.QueryExpressions.contains;
-import static org.qi4j.api.query.QueryExpressions.containsName;
-import static org.qi4j.api.query.QueryExpressions.eq;
-import static org.qi4j.api.query.QueryExpressions.ge;
-import static org.qi4j.api.query.QueryExpressions.gt;
-import static org.qi4j.api.query.QueryExpressions.isNotNull;
-import static org.qi4j.api.query.QueryExpressions.isNull;
-import static org.qi4j.api.query.QueryExpressions.lt;
-import static org.qi4j.api.query.QueryExpressions.matches;
-import static org.qi4j.api.query.QueryExpressions.ne;
-import static org.qi4j.api.query.QueryExpressions.not;
-import static org.qi4j.api.query.QueryExpressions.oneOf;
-import static org.qi4j.api.query.QueryExpressions.or;
-import static org.qi4j.api.query.QueryExpressions.orderBy;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-import static org.qi4j.test.indexing.NameableAssert.verifyOrderedResults;
-import static org.qi4j.test.indexing.NameableAssert.verifyUnorderedResults;
-
-/**
- * Abstract satisfiedBy with tests for simple queries against Index/Query engines.
- */
-public abstract class AbstractQueryTest
-    extends AbstractAnyQueryTest
-{
-
-    @Test
-    public void showNetwork()
-        throws IOException
-    {
-        IndexExporter indexerExporter = module.findService( IndexExporter.class ).get();
-        indexerExporter.exportReadableToStream( System.out );
-    }
-
-    @Test
-    public void script01()
-        throws EntityFinderException
-    {
-        final QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        final Query<Person> query = unitOfWork.newQuery( qb );
-        System.out.println( "*** script01: " + query );
-        verifyUnorderedResults( query, "Joe Doe", "Ann Doe", "Jack Doe" );
-    }
-
-    @Test
-    public void script02()
-        throws EntityFinderException
-    {
-        final QueryBuilder<Domain> qb = this.module.newQueryBuilder( Domain.class );
-        final Nameable nameable = templateFor( Nameable.class );
-        final Query<Domain> query = unitOfWork.newQuery( qb.where( eq( nameable.name(), "Gaming" ) ) );
-        System.out.println( "*** script02: " + query );
-        verifyUnorderedResults( query, "Gaming" );
-    }
-
-    @Test
-    public void script03()
-        throws EntityFinderException
-    {
-        QueryBuilder<Nameable> qb = this.module.newQueryBuilder( Nameable.class );
-        Query<Nameable> query = unitOfWork.newQuery( qb );
-        System.out.println( "*** script03: " + query );
-        verifyUnorderedResults( query, "Joe Doe", "Ann Doe", "Jack Doe", "Penang", "Kuala Lumpur", "Cooking", "Gaming",
-                                "Programming", "Cars" );
-    }
-
-    @Test
-    public void script04()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person personTemplate = templateFor( Person.class );
-        City placeOfBirth = personTemplate.placeOfBirth().get();
-        Query<Person> query = unitOfWork.newQuery( qb.where( eq( placeOfBirth.name(), "Kuala Lumpur" ) ) );
-        System.out.println( "*** script04: " + query );
-        verifyUnorderedResults( query, "Joe Doe", "Ann Doe" );
-    }
-
-    @Test
-    public void script04_ne()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person personTemplate = templateFor( Person.class );
-        City placeOfBirth = personTemplate.placeOfBirth().get();
-        Query<Person> query = unitOfWork.newQuery( qb.where( ne( placeOfBirth.name(), "Kuala Lumpur" ) ) );
-        System.out.println( "*** script04_ne: " + query );
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void script05()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.mother()
-            .get()
-            .placeOfBirth()
-            .get()
-            .name(), "Kuala Lumpur" ) )
-        );
-        System.out.println( "*** script05: " + query );
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script06()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where( ge( person.yearOfBirth(), 1973 ) ) );
-        System.out.println( "*** script06: " + query );
-        verifyUnorderedResults( query, "Joe Doe", "Ann Doe" );
-    }
-
-    @Test
-    @SuppressWarnings( "unchecked" )
-    public void script07()
-        throws EntityFinderException
-    {
-        QueryBuilder<Nameable> qb = this.module.newQueryBuilder( Nameable.class );
-        Person person = templateFor( Person.class );
-        Query<Nameable> query = unitOfWork.newQuery( qb.where(
-            and( ge( person.yearOfBirth(), 1900 ), eq( person.placeOfBirth().get().name(), "Penang" ) ) ) );
-        System.out.println( "*** script07: " + query );
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    @SuppressWarnings( "unchecked" )
-    public void script08()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where( or( eq( person.yearOfBirth(), 1970 ), eq( person.yearOfBirth(), 1975 ) ) )
-        );
-        System.out.println( "*** script08: " + query );
-        verifyUnorderedResults( query, "Jack Doe", "Ann Doe" );
-    }
-
-    @Test
-    @SuppressWarnings( "unchecked" )
-    public void script09()
-        throws EntityFinderException
-    {
-        QueryBuilder<Female> qb = this.module.newQueryBuilder( Female.class );
-        Person person = templateFor( Person.class );
-        Query<Female> query = unitOfWork.newQuery( qb.where( or( eq( person.yearOfBirth(), 1970 ), eq( person.yearOfBirth(), 1975 ) ) )
-        );
-        System.out.println( "*** script09: " + query );
-        verifyUnorderedResults( query, "Ann Doe" );
-    }
-
-    @Test
-    public void script10()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where( not( eq( person.yearOfBirth(), 1975 ) ) ) );
-        System.out.println( "*** script10: " + query );
-        verifyUnorderedResults( query, "Jack Doe", "Joe Doe" );
-    }
-
-    @Test
-    public void script11()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where( isNotNull( person.email() ) ) );
-        System.out.println( "*** script11: " + query );
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script12()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where( isNull( person.email() ) ) );
-        System.out.println( "*** script12: " + query );
-        verifyUnorderedResults( query, "Ann Doe", "Jack Doe" );
-    }
-
-    @Test
-    public void script12_ne()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where( ne( person.email(), "joe@thedoes.net" ) ) );
-        System.out.println( "*** script12_ne: " + query );
-        verifyUnorderedResults( query );
-    }
-
-    @Test
-    public void script13()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Male person = templateFor( Male.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where( isNotNull( person.wife() ) ) );
-        System.out.println( "*** script13: " + query );
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void script14()
-        throws EntityFinderException
-    {
-        QueryBuilder<Male> qb = this.module.newQueryBuilder( Male.class );
-        Male person = templateFor( Male.class );
-        Query<Male> query = unitOfWork.newQuery( qb.where( isNull( person.wife() ) ) );
-        System.out.println( "*** script14: " + query );
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script15()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Male person = templateFor( Male.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where( isNull( person.wife() ) ) );
-        System.out.println( "*** script15: " + query );
-        verifyUnorderedResults( query, "Joe Doe", "Ann Doe" );
-    }
-
-    @Test
-    public void script16()
-        throws EntityFinderException
-    {
-        QueryBuilder<Nameable> qb = this.module.newQueryBuilder( Nameable.class );
-        // should return only 2 entities
-        Nameable nameable = templateFor( Nameable.class );
-        Query<Nameable> query = unitOfWork.newQuery( qb );
-        query.orderBy( orderBy( nameable.name() ) );
-        query.maxResults( 2 );
-        System.out.println( "*** script16: " + query );
-        verifyOrderedResults( query, "Ann Doe", "Cars" );
-    }
-
-    @Test
-    public void script17()
-        throws EntityFinderException
-    {
-        QueryBuilder<Nameable> qb = this.module.newQueryBuilder( Nameable.class );
-        // should return only 3 entities starting with forth one
-        Nameable nameable = templateFor( Nameable.class );
-        Query<Nameable> query = unitOfWork.newQuery( qb );
-        query.orderBy( orderBy( nameable.name() ) );
-        query.firstResult( 3 );
-        query.maxResults( 2 );
-        System.out.println( "*** script17: " + query );
-        verifyOrderedResults( query, "Gaming", "Jack Doe" );
-    }
-
-    @Test
-    public void script18()
-        throws EntityFinderException
-    {
-        QueryBuilder<Nameable> qb = this.module.newQueryBuilder( Nameable.class );
-        // should return all Nameable entities sorted by name
-        Nameable nameable = templateFor( Nameable.class );
-        Query<Nameable> query = unitOfWork.newQuery( qb );
-        query.orderBy( orderBy( nameable.name() ) );
-        System.out.println( "*** script18: " + query );
-        verifyOrderedResults( query, "Ann Doe", "Cars", "Cooking", "Gaming", "Jack Doe", "Joe Doe", "Kuala Lumpur",
-                              "Penang", "Programming" );
-    }
-
-    @Test
-    public void script19()
-        throws EntityFinderException
-    {
-        QueryBuilder<Nameable> qb = this.module.newQueryBuilder( Nameable.class );
-        // should return all Nameable entities with a name > "D" sorted by name
-        Nameable nameable = templateFor( Nameable.class );
-        Query<Nameable> query = unitOfWork.newQuery( qb.where( gt( nameable.name(), "D" ) ) );
-        query.orderBy( orderBy( nameable.name() ) );
-        System.out.println( "*** script19: " + query );
-        verifyOrderedResults( query, "Gaming", "Jack Doe", "Joe Doe", "Kuala Lumpur", "Penang", "Programming" );
-    }
-
-    @Test
-    public void script20()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        // should return all Persons born after 1973 (Ann and Joe Doe) sorted descending by name
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where( gt( person.yearOfBirth(), 1973 ) ) );
-        query.orderBy( orderBy( person.name(), OrderBy.Order.DESCENDING ) );
-        System.out.println( "*** script20: " + query );
-        verifyOrderedResults( query, "Joe Doe", "Ann Doe" );
-    }
-
-    @Test
-    public void script21()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        // should return all Persons sorted by name of the city they were born, and then by year they were born
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb );
-        query.orderBy( orderBy( person.placeOfBirth().get().name() ), orderBy( person.yearOfBirth() ) );
-        System.out.println( "*** script21: " + query );
-        verifyOrderedResults( query, "Ann Doe", "Joe Doe", "Jack Doe" );
-    }
-
-    @Test
-    public void script22()
-        throws EntityFinderException
-    {
-        QueryBuilder<Nameable> qb = this.module.newQueryBuilder( Nameable.class );
-        Nameable nameable = templateFor( Nameable.class );
-        // should return Jack and Joe Doe
-        Query<Nameable> query = unitOfWork.newQuery( qb.where( matches( nameable.name(), "J.*Doe" ) ) );
-        System.out.println( "*** script22: " + query );
-        verifyUnorderedResults( query, "Jack Doe", "Joe Doe" );
-    }
-
-    @Test
-    public void script23()
-        throws EntityFinderException
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Domain interests = oneOf( person.interests() );
-        Query<Person> query = unitOfWork.newQuery( qb.where( eq( interests.name(), "Cars" ) ) );
-        System.out.println( "*** script23: " + query );
-        verifyOrderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void script24()
-        throws EntityFinderException
-    {
-        final QueryBuilder<Domain> qb = this.module.newQueryBuilder( Domain.class );
-        final Nameable nameable = templateFor( Nameable.class );
-        final Query<Domain> query = unitOfWork.newQuery( qb.where( eq( nameable.name(), "Gaming" ) ) );
-        System.out.println( "*** script24: " + query );
-        assertThat( query.find().name().get(), is( equalTo( "Gaming" ) ) );
-    }
-
-    @Test( expected = NotQueryableException.class )
-    public void script25()
-    {
-        this.module.newQueryBuilder( File.class );
-    }
-
-    @Test( expected = NotQueryableException.class )
-    public void script26()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        qb.where( eq( person.personalWebsite().get().file().get().value(), "some/path" ) );
-    }
-
-    @Test( expected = NotQueryableException.class )
-    public void script27()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        qb.where( eq( person.personalWebsite().get().host().get().value(), "www.qi4j.org" ) );
-    }
-
-    @Test( expected = NotQueryableException.class )
-    public void script28()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        qb.where( eq( person.personalWebsite().get().port().get().value(), 8080 ) );
-    }
-
-    @Test
-    public void script29()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.personalWebsite()
-            .get()
-            .protocol()
-            .get()
-            .value(), "http" ) )
-        );
-        System.out.println( "*** script29: " + query );
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    @Ignore( "Wait till 1.1?" )
-    // Paul: I don't understand this test
-    @SuppressWarnings( "unchecked" )
-    public void script30()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        QueryParam queryParam = null; // oneOf( person.personalWebsite().get().queryParams() );
-        Query<Person> query = unitOfWork.newQuery( qb.where( and( eq( queryParam.name(), "foo" ), eq( queryParam.value(), "bar" ) ) ) );
-        System.out.println( "*** script30: " + query );
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    @Ignore( "Equality on Property<Map<?,?>> not implemented" )
-    public void script31()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Map<String, String> info = new HashMap<>( 0 );
-        Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.additionalInfo(), info ) ) );
-        System.out.println( "*** script31: " + query );
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void script32()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.address().get().line1(), "Qi Alley 4j" ) ) );
-        System.out.println( "*** script32: " + query );
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script33()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Domain gaming = unitOfWork.get( Domain.class, "Gaming" );
-        Query<Person> query = unitOfWork.newQuery( qb.where( contains( person.interests(), gaming ) ) );
-        System.out.println( "*** script33: " + query );
-
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script34()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Female annDoe = unitOfWork.get( Female.class, "anndoe" );
-        Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.mother(), annDoe ) ) );
-        System.out.println( "*** script34: " + query );
-
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script35()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where( containsName( person.accounts(), "anns" ) ) );
-        System.out.println( "*** script35: " + query );
-
-        verifyUnorderedResults( query, "Jack Doe", "Ann Doe" );
-    }
-
-    @Test
-    public void script36()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Account anns = unitOfWork.get( Account.class, "accountOfAnnDoe" );
-        Query<Person> query = unitOfWork.newQuery( qb.where( contains( person.accounts(), anns ) ) );
-        System.out.println( "*** script36: " + query );
-
-        verifyUnorderedResults( query, "Jack Doe", "Ann Doe" );
-    }
-
-    @Test
-    @Ignore( "Traversing of NamedAssociations is not implemented" )
-    public void script37()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.accounts().get( "anns" ).number(),
-                                                                 "accountOfAnnDoe" ) ) );
-        System.out.println( "*** script37: " + query );
-
-        verifyUnorderedResults( query, "Jack Doe", "Ann Doe" );
-    }
-
-    @Test
-    public void script38()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where( eq( person.title(), Person.Title.DR ) ) );
-        System.out.println( "*** script38: " + query );
-
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void script39()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where( ne( person.title(), Person.Title.DR ) ) );
-        System.out.println( "*** script39: " + query );
-
-        verifyUnorderedResults( query, "Ann Doe", "Joe Doe" );
-    }
-
-    @Test
-    public void script40_Date()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            eq( person.dateValue(), new DateTime( "2010-03-04T13:24:35", UTC ).toDate() ) ) );
-        System.out.println( "*** script40_Date: " + query );
-
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void script41_Date()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            ne( person.dateValue(), new DateTime( "2010-03-04T13:24:35", UTC ).toDate() ) ) );
-        System.out.println( "*** script41_Date: " + query );
-
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script42_Date()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            ne( person.dateValue(), new DateTime( "2010-03-04T14:24:35", forID( "CET" ) ).toDate() ) ) );
-        System.out.println( "*** script42_Date: " + query );
-
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script43_Date()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            and( gt( person.dateValue(), new DateTime( "2005-03-04T13:24:35", UTC ).toDate() ),
-                 lt( person.dateValue(), new DateTime( "2015-03-04T13:24:35", UTC ).toDate() ) ) ) );
-        System.out.println( "*** script43_Date: " + query );
-
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void script40_DateTime()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            eq( person.dateTimeValue(), new DateTime( "2010-03-04T13:24:35", UTC ) ) ) );
-        System.out.println( "*** script40_DateTime: " + query );
-
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void script41_DateTime()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            ne( person.dateTimeValue(), new DateTime( "2010-03-04T13:24:35", UTC ) ) ) );
-        System.out.println( "*** script41_DateTime: " + query );
-
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script42_DateTime()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            ne( person.dateTimeValue(), new DateTime( "2010-03-04T14:24:35", forID( "CET" ) ) ) ) );
-        System.out.println( "*** script42_DateTime: " + query );
-
-        verifyUnorderedResults( query, "Jack Doe", "Joe Doe" );
-    }
-
-    @Test
-    public void script43_DateTime()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            and( gt( person.dateTimeValue(), new DateTime( "2005-03-04T13:24:35", UTC ) ),
-                 lt( person.dateTimeValue(), new DateTime( "2015-03-04T13:24:35", UTC ) ) ) ) );
-        System.out.println( "*** script43_DateTime: " + query );
-
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void script40_LocalDateTime()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            eq( person.localDateTimeValue(), new LocalDateTime( "2010-03-04T13:23:00", UTC ) ) ) );
-        System.out.println( "*** script40_LocalDateTime: " + query );
-
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void script41_LocalDateTime()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            ne( person.localDateTimeValue(), new LocalDateTime( "2010-03-04T13:23:00", UTC ) ) ) );
-        System.out.println( "*** script41_LocalDateTime: " + query );
-
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script42_LocalDateTime()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            ne( person.localDateTimeValue(), new LocalDateTime( "2010-03-04T13:23:00", forID( "CET" ) ) ) ) );
-        System.out.println( "*** script42_LocalDateTime: " + query );
-
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script43_LocalDateTime()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            and( gt( person.localDateTimeValue(), new LocalDateTime( "2005-03-04T13:24:35", UTC ) ),
-                 lt( person.localDateTimeValue(), new LocalDateTime( "2015-03-04T13:24:35", UTC ) ) ) ) );
-        System.out.println( "*** script43_LocalDateTime: " + query );
-
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void script40_LocalDate()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            eq( person.localDateValue(), new LocalDate( "2010-03-04", UTC ) ) ) );
-        System.out.println( "*** script40_LocalDate: " + query );
-
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void script41_LocalDate()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            ne( person.localDateValue(), new LocalDate( "2010-03-04", UTC ) ) ) );
-        System.out.println( "*** script41_LocalDate: " + query );
-
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script42_LocalDate()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            ne( person.localDateValue(), new LocalDate( "2010-03-04", forID( "CET" ) ) ) ) );
-        System.out.println( "*** script42_LocalDate: " + query );
-
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script43_LocalDate()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            and( gt( person.localDateValue(), new LocalDate( "2005-03-04", UTC ) ),
-                 lt( person.localDateValue(), new LocalDate( "2015-03-04", UTC ) ) ) ) );
-        System.out.println( "*** script43_LocalDate: " + query );
-
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void script50_BigInteger()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            eq( person.bigInteger(), new BigInteger( "23232323232323232323232323" ) ) ) );
-        System.out.println( "*** script50_BigInteger: " + query );
-
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script51_BigInteger()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            ne( person.bigInteger(), new BigInteger( "23232323232323232323232323" ) ) ) );
-        System.out.println( "*** script51_BigInteger: " + query );
-
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void script52_BigInteger()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            ge( person.bigInteger(), new BigInteger( "23232323232323232323232323" ) ) ) );
-        System.out.println( "*** script52_BigInteger: " + query );
-
-        verifyUnorderedResults( query, "Jack Doe", "Joe Doe" );
-    }
-
-    @Test
-    public void script50_BigDecimal()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            eq( person.bigDecimal(), new BigDecimal( "2342.76931348623157e+307" ) ) ) );
-        System.out.println( "*** script50_BigDecimal: " + query );
-
-        verifyUnorderedResults( query, "Joe Doe" );
-    }
-
-    @Test
-    public void script51_BigDecimal()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            ne( person.bigDecimal(), new BigDecimal( "2342.76931348623157e+307" ) ) ) );
-        System.out.println( "*** script51_BigDecimal: " + query );
-
-        verifyUnorderedResults( query, "Jack Doe" );
-    }
-
-    @Test
-    public void script52_BigDecimal()
-    {
-        QueryBuilder<Person> qb = this.module.newQueryBuilder( Person.class );
-        Person person = templateFor( Person.class );
-        Query<Person> query = unitOfWork.newQuery( qb.where(
-            ge( person.bigDecimal(), new BigDecimal( "2342.76931348623157e+307" ) ) ) );
-        System.out.println( "*** script52_BigDecimal: " + query );
-
-        verifyUnorderedResults( query, "Jack Doe", "Joe Doe" );
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/NameableAssert.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/NameableAssert.java
deleted file mode 100644
index 94d1309..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/NameableAssert.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright 2008 Michael Hunger.
- *
- * Licensed  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.qi4j.test.indexing;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.test.indexing.model.Nameable;
-
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-import static org.qi4j.functional.Iterables.toList;
-
-public class NameableAssert
-{
-    // id -> name
-    private static final Map<String, String> world = new HashMap<>();
-
-    public static void clear()
-    {
-        world.clear();
-    }
-
-    public static void assertNames( Iterable<EntityReference> identitiesIterable, String... expectedNames )
-    {
-        assertNames( true, identitiesIterable, expectedNames );
-    }
-
-    public static void assertNames( boolean sort,
-                                    Iterable<EntityReference> identitiesIterable,
-                                    String... expectedNames
-    )
-    {
-        final List<EntityReference> references = toList( identitiesIterable );
-        assertThat( expectedNames.length + " entries(" + expectedNames.length + ", got " + getNames( references ) + ")",
-                    references.size(),
-                    equalTo( expectedNames.length ) );
-        List<String> sortedNames = getNames( references );
-        final List<String> expectedSorted = java.util.Arrays.asList( expectedNames );
-        if( sort )
-        {
-            Collections.sort( sortedNames );
-            Collections.sort( expectedSorted );
-        }
-        assertThat( "names", sortedNames, equalTo( expectedSorted ) );
-    }
-
-    public static void trace( Nameable nameable )
-    {
-        world.put( ( (Identity) nameable ).identity().get(), nameable.name().get() );
-    }
-
-    public static void assertName( String expectedName, EntityReference reference )
-    {
-        final String existingName = getName( reference );
-        assertThat( "Name of " + reference, existingName, equalTo( expectedName ) );
-    }
-
-    public static String getName( EntityReference reference )
-    {
-        return world.get( reference.identity() );
-    }
-
-    public static List<String> getNames( List<EntityReference> references )
-    {
-        List<String> result = new ArrayList<>( references.size() );
-        for( EntityReference reference : references )
-        {
-            final String name = getName( reference );
-            assertThat( "Name of " + reference, name, notNullValue() );
-            result.add( name );
-        }
-        return result;
-    }
-
-    public static String[] allNames()
-    {
-        return world.values().toArray( new String[ world.size() ] );
-    }
-
-    public static void verifyUnorderedResults( final Iterable<? extends Nameable> results, final String... names )
-    {
-        List<String> expected = new ArrayList<>( Arrays.asList( names ) );
-        List<String> unexpected = new ArrayList<>();
-        for( Nameable result : results )
-        {
-            String name = result.name().get();
-            if( !expected.remove( name ) )
-            {
-                unexpected.add( name );
-            }
-        }
-        if( !unexpected.isEmpty() || !expected.isEmpty() )
-        {
-            String message = "";
-            if( !unexpected.isEmpty() )
-            {
-                message += unexpected + " returned but not expected\n";
-            }
-            if( !expected.isEmpty() )
-            {
-                message += expected + " expected but not returned\n";
-            }
-            fail( message.substring( 0, message.length() - 1 ) );
-        }
-    }
-
-    public static void verifyOrderedResults( final Iterable<? extends Nameable> results, final String... names )
-    {
-        List<String> expected = new ArrayList<>( Arrays.asList( names ) );
-        List<String> actual = new ArrayList<>();
-        for( Nameable result : results )
-        {
-            actual.add( result.name().get() );
-        }
-
-        assertThat( "Result is incorrect", actual, equalTo( expected ) );
-    }
-
-    private NameableAssert()
-    {
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/TestData.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/TestData.java
deleted file mode 100644
index 72dfe88..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/TestData.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.test.indexing;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import org.joda.time.DateTime;
-import org.joda.time.LocalDate;
-import org.joda.time.LocalDateTime;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.test.indexing.model.Account;
-import org.qi4j.test.indexing.model.Address;
-import org.qi4j.test.indexing.model.Cat;
-import org.qi4j.test.indexing.model.City;
-import org.qi4j.test.indexing.model.Domain;
-import org.qi4j.test.indexing.model.Female;
-import org.qi4j.test.indexing.model.Male;
-import org.qi4j.test.indexing.model.Person;
-import org.qi4j.test.indexing.model.Protocol;
-import org.qi4j.test.indexing.model.QueryParam;
-import org.qi4j.test.indexing.model.URL;
-import org.qi4j.test.indexing.model.entities.CatEntity;
-import org.qi4j.test.indexing.model.entities.FemaleEntity;
-import org.qi4j.test.indexing.model.entities.MaleEntity;
-
-import static org.joda.time.DateTimeZone.UTC;
-
-/**
- * Utility class to populate Index/Query tests data.
- */
-class TestData
-{
-    static void populate( Module module )
-        throws UnitOfWorkCompletionException
-    {
-        try( UnitOfWork unitOfWork = module.newUnitOfWork() )
-        {
-            NameableAssert.clear();
-            Domain gaming;
-            {
-                EntityBuilder<Domain> domainBuilder = unitOfWork.newEntityBuilder( Domain.class, "Gaming" );
-                gaming = domainBuilder.instance();
-                gaming.name().set( "Gaming" );
-                gaming.description().set( "Gaming domain" );
-                gaming = domainBuilder.newInstance();
-                NameableAssert.trace( gaming );
-            }
-
-            Domain programming;
-            {
-                EntityBuilder<Domain> domainBuilder = unitOfWork.newEntityBuilder( Domain.class );
-                programming = domainBuilder.instance();
-                programming.name().set( "Programming" );
-                programming.description().set( "Programing domain" );
-                programming = domainBuilder.newInstance();
-                NameableAssert.trace( programming );
-            }
-
-            Domain cooking;
-            {
-                EntityBuilder<Domain> domainBuilder = unitOfWork.newEntityBuilder( Domain.class );
-                cooking = domainBuilder.instance();
-                cooking.name().set( "Cooking" );
-                cooking.description().set( "Cooking domain" );
-                cooking = domainBuilder.newInstance();
-                NameableAssert.trace( cooking );
-            }
-
-            Domain cars;
-            {
-                EntityBuilder<Domain> domainBuilder = unitOfWork.newEntityBuilder( Domain.class );
-                cars = domainBuilder.instance();
-                cars.name().set( "Cars" );
-                cars.description().set( "Cars" );
-                cars = domainBuilder.newInstance();
-                NameableAssert.trace( cars );
-            }
-
-            City kualaLumpur;
-            {
-                EntityBuilder<City> cityBuilder = unitOfWork.newEntityBuilder( City.class );
-                kualaLumpur = cityBuilder.instance();
-                kualaLumpur.name().set( "Kuala Lumpur" );
-                kualaLumpur.country().set( "Malaysia" );
-                kualaLumpur.county().set( "Some Jaya" );
-                kualaLumpur = cityBuilder.newInstance();
-                NameableAssert.trace( kualaLumpur );
-            }
-
-            City penang;
-            {
-                EntityBuilder<City> cityBuilder = unitOfWork.newEntityBuilder( City.class );
-                penang = cityBuilder.instance();
-                penang.name().set( "Penang" );
-                penang.country().set( "Malaysia" );
-                penang.county().set( "Some Other Jaya" );
-                penang = cityBuilder.newInstance();
-                NameableAssert.trace( penang );
-            }
-
-            Account annsAccount;
-            {
-                EntityBuilder<Account> accountBuilder = unitOfWork.newEntityBuilder( Account.class, "accountOfAnnDoe" );
-                annsAccount = accountBuilder.instance();
-                annsAccount.number().set( "accountOfAnnDoe" );
-                annsAccount = accountBuilder.newInstance();
-            }
-
-            Account jacksAccount;
-            {
-                EntityBuilder<Account> accountBuilder = unitOfWork.newEntityBuilder( Account.class, "accountOfJackDoe" );
-                jacksAccount = accountBuilder.instance();
-                jacksAccount.number().set( "accountOfJackDoe" );
-                jacksAccount = accountBuilder.newInstance();
-            }
-
-            ValueBuilder<Address> addressBuilder = module.newValueBuilder( Address.class );
-            Address address = addressBuilder.prototype();
-            address.line1().set( "Qi Street 4j" );
-            address.line2().set( "Off main Java Street" );
-            address.zipcode().set( "12345" );
-
-            Female annDoe;
-            {
-                EntityBuilder<FemaleEntity> femaleBuilder = unitOfWork.newEntityBuilder( FemaleEntity.class, "anndoe" );
-                annDoe = femaleBuilder.instance();
-                annDoe.name().set( "Ann Doe" );
-                annDoe.title().set( Person.Title.MRS );
-                annDoe.placeOfBirth().set( kualaLumpur );
-                annDoe.yearOfBirth().set( 1975 );
-                annDoe.interests().add( 0, cooking );
-                annDoe.password().set( "passwordOfAnnDoe" );
-                annDoe.mainAccount().set( annsAccount );
-                annDoe.accounts().put( "anns", annsAccount );
-                annDoe.accounts().put( "jacks", jacksAccount );
-                annDoe.address().set( addressBuilder.newInstance() );
-                annDoe = femaleBuilder.newInstance();
-                NameableAssert.trace( annDoe );
-            }
-
-            {
-                EntityBuilder<MaleEntity> maleBuilder = unitOfWork.newEntityBuilder( MaleEntity.class );
-                Male joeDoe = maleBuilder.instance();
-                joeDoe.name().set( "Joe Doe" );
-                joeDoe.title().set( Person.Title.MR );
-                joeDoe.placeOfBirth().set( kualaLumpur );
-                joeDoe.yearOfBirth().set( 1990 );
-                joeDoe.mother().set( annDoe );
-                joeDoe.interests().add( 0, programming );
-                joeDoe.interests().add( 0, gaming );
-                joeDoe.email().set( "joe@thedoes.net" );
-                joeDoe.password().set( "passwordOfJoeDoe" );
-                joeDoe = maleBuilder.newInstance();
-                address = module.newValueBuilderWithPrototype( address ).prototype();
-                address.line1().set( "Qi Alley 4j" );
-                joeDoe.address().set( address );
-                joeDoe.bigInteger().set( new BigInteger( "23232323232323232323232323" ) );
-                joeDoe.bigDecimal().set( new BigDecimal( "23.4276931348623157e+309" ) );
-                joeDoe.dateValue().set( new DateTime( "2020-03-04T13:24:35", UTC ).toDate() );
-                joeDoe.dateTimeValue().set( new DateTime( "2020-03-04T13:24:35", UTC ) );
-                joeDoe.localDateTimeValue().set( new LocalDateTime( "2020-03-04T13:23:00" ) );
-                joeDoe.localDateValue().set( new LocalDate( "2020-03-04" ) );
-                NameableAssert.trace( joeDoe );
-            }
-
-            {
-                EntityBuilder<MaleEntity> maleBuilder = unitOfWork.newEntityBuilder( MaleEntity.class );
-                Male jackDoe = maleBuilder.instance();
-                jackDoe.name().set( "Jack Doe" );
-                jackDoe.title().set( Person.Title.DR );
-                jackDoe.placeOfBirth().set( penang );
-                jackDoe.yearOfBirth().set( 1970 );
-                jackDoe.interests().add( 0, cars );
-                jackDoe.wife().set( annDoe );
-                jackDoe.password().set( "passwordOfJohnDoe" );
-                jackDoe.mainAccount().set( jacksAccount );
-                jackDoe.accounts().put( "anns", annsAccount );
-                jackDoe.accounts().put( "jacks", jacksAccount );
-                address = module.newValueBuilderWithPrototype( address ).prototype();
-                address.line1().set( "Qi Avenue 4j" );
-                jackDoe.address().set( address );
-                jackDoe.bigInteger().set( new BigInteger( "42424242424242424242424242" ) );
-                jackDoe.bigDecimal().set( new BigDecimal( "42.2376931348623157e+309" ) );
-                jackDoe.dateValue().set( new DateTime( "2010-03-04T13:24:35", UTC ).toDate() );
-                jackDoe.dateTimeValue().set( new DateTime( "2010-03-04T13:24:35", UTC ) );
-                jackDoe.localDateTimeValue().set( new LocalDateTime( "2010-03-04T13:23:00" ) );
-                jackDoe.localDateValue().set( new LocalDate( "2010-03-04" ) );
-
-                ValueBuilder<URL> urlBuilder = module.newValueBuilder( URL.class );
-                ValueBuilder<Protocol> protocolBuilder = module.newValueBuilder( Protocol.class );
-                ValueBuilder<QueryParam> queryParamBuilder = module.newValueBuilder( QueryParam.class );
-
-                Protocol protocol = protocolBuilder.prototype();
-                protocol.value().set( "http" );
-
-                List<QueryParam> queryParams = new ArrayList<>( 2 );
-                QueryParam param = queryParamBuilder.prototype();
-                param.name().set( "user" );
-                param.value().set( "jackdoe" );
-                queryParams.add( queryParamBuilder.newInstance() );
-                queryParamBuilder = module.newValueBuilder( QueryParam.class );
-                param = queryParamBuilder.prototype();
-                param.name().set( "password" );
-                param.value().set( "somepassword" );
-                queryParams.add( queryParamBuilder.newInstance() );
-
-                URL url = urlBuilder.prototype();
-                url.protocol().set( protocolBuilder.newInstance() );
-                url.queryParams().set( queryParams );
-
-                jackDoe.personalWebsite().set( urlBuilder.newInstance() );
-
-                jackDoe = maleBuilder.newInstance();
-                NameableAssert.trace( jackDoe );
-            }
-
-            {
-                EntityBuilder<CatEntity> catBuilder = unitOfWork.newEntityBuilder( CatEntity.class );
-                Cat felix = catBuilder.instance();
-                felix.name().set( "Felix" );
-                catBuilder.newInstance();
-            }
-            unitOfWork.complete();
-        }
-    }
-
-    private TestData()
-    {
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Account.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Account.java
deleted file mode 100644
index be3daf4..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Account.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model;
-
-import org.qi4j.api.property.Property;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface Account
-{
-    Property<String> number();
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Address.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Address.java
deleted file mode 100644
index 026b61b..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Address.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.test.indexing.model;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-public interface Address
-    extends ValueComposite
-{
-    Property<String> line1();
-
-    Property<String> line2();
-
-    Property<String> zipcode();
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Alive.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Alive.java
deleted file mode 100644
index d1e06e7..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Alive.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface Alive
-{
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Cat.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Cat.java
deleted file mode 100644
index 90059a9..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Cat.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface Cat
-    extends Pet
-{
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/City.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/City.java
deleted file mode 100644
index dc91eb7..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/City.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model;
-
-import org.qi4j.api.property.Property;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface City
-    extends Nameable
-{
-    Property<String> country();
-
-    Property<String> county();
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Dog.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Dog.java
deleted file mode 100644
index 2946b76..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Dog.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface Dog
-    extends Pet
-{
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Domain.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Domain.java
deleted file mode 100644
index cbc6682..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Domain.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model;
-
-import org.qi4j.api.property.Property;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface Domain
-    extends Nameable
-{
-    Property<String> description();
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Female.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Female.java
deleted file mode 100644
index 75ee3d1..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Female.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.common.Optional;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface Female
-    extends Person
-{
-    @Optional
-    Association<Male> husband();
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/File.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/File.java
deleted file mode 100644
index 86676dc..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/File.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2009 Alin Dreghiciu.
- *
- * Licensed 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.qi4j.test.indexing.model;
-
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * JAVADOC Add JavaDoc.
- */
-@Queryable( false )
-public interface File
-    extends ValueComposite
-{
-    Property<String> value();
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Host.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Host.java
deleted file mode 100644
index a89cf43..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Host.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2009 Alin Dreghiciu.
- *
- * Licensed 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.qi4j.test.indexing.model;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * JAVADOC Add JavaDoc.
- */
-public interface Host
-    extends ValueComposite
-{
-    Property<String> value();
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Male.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Male.java
deleted file mode 100644
index 217b91e..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Male.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.common.Optional;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface Male
-    extends Person
-{
-    @Optional
-    Association<Female> wife();
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Nameable.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Nameable.java
deleted file mode 100644
index bebef2a..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Nameable.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model;
-
-import org.qi4j.api.property.Property;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface Nameable
-{
-    Property<String> name();
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Person.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Person.java
deleted file mode 100644
index 1b1819a..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Person.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.test.indexing.model;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import org.joda.time.DateTime;
-import org.joda.time.LocalDate;
-import org.joda.time.LocalDateTime;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.api.property.Property;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface Person
-    extends Nameable, Alive
-{
-    enum Title
-    {
-        MR, MS, MRS, DR
-    }
-
-    Property<Title> title();
-
-    @Optional
-    Association<City> placeOfBirth();
-
-    Property<Integer> yearOfBirth();
-
-    @Optional
-    Property<Address> address();
-
-    @Optional
-    Association<Female> mother();
-
-    @Optional
-    Association<Male> father();
-
-    ManyAssociation<Domain> interests();
-
-    @Optional
-    Property<String> email();
-
-    @Optional
-    Property<URL> personalWebsite();
-
-    @Queryable( false )
-    Property<String> password();
-
-    @Optional
-    Association<Account> mainAccount();
-
-    NamedAssociation<Account> accounts();
-
-    @Optional
-    Property<Map<String, String>> additionalInfo();
-
-    @Optional
-    Property<BigInteger> bigInteger();
-
-    @Optional
-    Property<BigDecimal> bigDecimal();
-
-    @Optional
-    Property<Date> dateValue();
-
-    @Optional
-    Property<DateTime> dateTimeValue();
-
-    @Optional
-    Property<LocalDateTime> localDateTimeValue();
-
-    @Optional
-    Property<LocalDate> localDateValue();
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Pet.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Pet.java
deleted file mode 100644
index 8237c52..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Pet.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface Pet
-    extends Nameable, Alive
-{
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Port.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Port.java
deleted file mode 100644
index d8a1ff3..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Port.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2009 Alin Dreghiciu.
- *
- * Licensed 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.qi4j.test.indexing.model;
-
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * JAVADOC Add JavaDoc.
- */
-public interface Port
-    extends ValueComposite
-{
-    @Queryable( false )
-    Property<Integer> value();
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Protocol.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Protocol.java
deleted file mode 100644
index 5c29e63..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/Protocol.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2009 Alin Dreghiciu.
- *
- * Licensed 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.qi4j.test.indexing.model;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * JAVADOC Add JavaDoc.
- */
-public interface Protocol
-    extends ValueComposite
-{
-    Property<String> value();
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/QueryParam.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/QueryParam.java
deleted file mode 100644
index be9abb4..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/QueryParam.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2009 Alin Dreghiciu.
- *
- * Licensed 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.qi4j.test.indexing.model;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * JAVADOC Add JavaDoc.
- */
-public interface QueryParam
-    extends ValueComposite
-{
-    Property<String> name();
-
-    Property<String> value();
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/URL.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/URL.java
deleted file mode 100644
index 426bbf3..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/URL.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2009 Alin Dreghiciu.
- *
- * Licensed 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.qi4j.test.indexing.model;
-
-import java.util.Collection;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * JAVADOC Add JavaDoc.
- */
-public interface URL
-    extends ValueComposite
-{
-    Property<Protocol> protocol();
-
-    @Optional
-    @Queryable( false )
-    Property<Host> host();
-
-    @Optional
-    Property<Port> port();
-
-    @Optional
-    Property<File> file();
-
-    @Optional
-    Property<Collection<QueryParam>> queryParams();
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/AccountEntity.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/AccountEntity.java
deleted file mode 100644
index bad4ddf..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/AccountEntity.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model.entities;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.test.indexing.model.Account;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface AccountEntity
-    extends Account, EntityComposite
-{
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/CatEntity.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/CatEntity.java
deleted file mode 100644
index 14c7c7f..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/CatEntity.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model.entities;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.test.indexing.model.Cat;
-
-/**
- * JAVADOC Add JavaDoc
- */
-@Queryable( false )
-public interface CatEntity
-    extends Cat, EntityComposite
-{
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/CityEntity.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/CityEntity.java
deleted file mode 100644
index e06eede..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/CityEntity.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model.entities;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.test.indexing.model.City;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface CityEntity
-    extends City, EntityComposite
-{
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/DogEntity.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/DogEntity.java
deleted file mode 100644
index 84291e3..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/DogEntity.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model.entities;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.test.indexing.model.Dog;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface DogEntity
-    extends Dog, EntityComposite
-{
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/DomainEntity.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/DomainEntity.java
deleted file mode 100644
index 6b4ad57..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/DomainEntity.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model.entities;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.test.indexing.model.Domain;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface DomainEntity
-    extends Domain, EntityComposite
-{
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/FemaleEntity.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/FemaleEntity.java
deleted file mode 100644
index 001c9d8..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/FemaleEntity.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model.entities;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.test.indexing.model.Female;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface FemaleEntity
-    extends Female, EntityComposite
-{
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/MaleEntity.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/MaleEntity.java
deleted file mode 100644
index a2c0d67..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/MaleEntity.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model.entities;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.test.indexing.model.Male;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface MaleEntity
-    extends Male, EntityComposite
-{
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/PersonEntity.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/PersonEntity.java
deleted file mode 100644
index 5b63bdf..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/PersonEntity.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model.entities;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.test.indexing.model.Person;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface PersonEntity
-    extends Person, EntityComposite
-{
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/PetEntity.java b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/PetEntity.java
deleted file mode 100644
index c645f45..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/PetEntity.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.indexing.model.entities;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.test.indexing.model.Pet;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface PetEntity
-    extends Pet, EntityComposite
-{
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/package.html b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/package.html
deleted file mode 100644
index b19cc59..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/entities/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Index/Query SPI Test Support - Entities.</h2>
-    </body>
-</html>
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/package.html b/core/testsupport/src/main/java/org/qi4j/test/indexing/model/package.html
deleted file mode 100644
index c4acb13..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/model/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Index/Query SPI Test Support - Model.</h2>
-    </body>
-</html>
diff --git a/core/testsupport/src/main/java/org/qi4j/test/indexing/package.html b/core/testsupport/src/main/java/org/qi4j/test/indexing/package.html
deleted file mode 100644
index e26df9a..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/indexing/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Index/Query SPI Test Support.</h2>
-    </body>
-</html>
diff --git a/core/testsupport/src/main/java/org/qi4j/test/mock/MockComposite.java b/core/testsupport/src/main/java/org/qi4j/test/mock/MockComposite.java
deleted file mode 100644
index 2234649..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/mock/MockComposite.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.mock;
-
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.test.mock.internal.MockRecorderMixin;
-
-/**
- * A mocked composite. Adds {@link org.qi4j.test.mock.MockRecorder} to the mocked composite.
- */
-@Mixins( { MockRecorderMixin.class } )
-public interface MockComposite
-    extends MockRecorder, TransientComposite
-{
-}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/qi4j/test/mock/MockPlayerConcern.java b/core/testsupport/src/main/java/org/qi4j/test/mock/MockPlayerConcern.java
deleted file mode 100644
index 68d2111..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/mock/MockPlayerConcern.java
+++ /dev/null
@@ -1,39 +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.qi4j.test.mock;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.qi4j.api.concern.ConcernOf;
-
-public class MockPlayerConcern
-    extends ConcernOf<InvocationHandler>
-    implements InvocationHandler
-{
-    /**
-     * @see java.lang.reflect.InvocationHandler#invoke(Object, java.lang.reflect.Method, Object[])
-     */
-    @Override
-    public Object invoke( final Object proxy, final Method method, final Object[] args )
-        throws Throwable
-    {
-        // TODO implementation
-        throw new UnsupportedOperationException( "MockResolver player concern is not yet implemented" );
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/mock/MockPlayerMixin.java b/core/testsupport/src/main/java/org/qi4j/test/mock/MockPlayerMixin.java
deleted file mode 100644
index 0c8f37a..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/mock/MockPlayerMixin.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.mock;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.test.mock.internal.MockRepository;
-import org.qi4j.test.mock.internal.MockResolver;
-
-/**
- * Generic mixin for mock composites. Overrides any generic mixins but not typed mixins, as typed mixins have precedence
- * over generic mixins. To override a typed mixin {@link org.qi4j.test.mock.MockPlayerConcern} can be used.
- * MockResolver player mixin will delegate method invocations to registered mocks. Mocks can be registered by using
- * {@link org.qi4j.test.mock.MockComposite}.
- * If there is no mock registered to handle the method invocation invocation will fail by throwing an
- * IllegalStateException.
- */
-public class MockPlayerMixin
-    implements InvocationHandler
-{
-
-    /**
-     * MockResolver repository. Holds all registred mocks.
-     */
-    @This
-    MockRepository mockRepository;
-
-    /**
-     * Finds a registered mock that can handle the method invocation and delegate to it. If there is no such mock throws
-     * IllegalStateException.
-     *
-     * @see java.lang.reflect.InvocationHandler#invoke(Object, java.lang.reflect.Method, Object[])
-     */
-    @Override
-    public Object invoke( final Object proxy, final Method method, final Object[] args )
-        throws Throwable
-    {
-        System.out.println( "Play mock for " + method );
-        for( MockResolver mockResolver : mockRepository.getAll() )
-        {
-            InvocationHandler handler = mockResolver.getInvocationHandler( proxy, method, args );
-            if( handler != null )
-            {
-                return handler.invoke( mockResolver, method, args );
-            }
-        }
-        throw new IllegalStateException( "There is no mock registered that can handle " + method );
-    }
-}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/qi4j/test/mock/MockRecorder.java b/core/testsupport/src/main/java/org/qi4j/test/mock/MockRecorder.java
deleted file mode 100644
index af6e3ad..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/mock/MockRecorder.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.mock;
-
-public interface MockRecorder
-{
-    MockResolverType useMock( Object mock );
-}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/qi4j/test/mock/MockResolverType.java b/core/testsupport/src/main/java/org/qi4j/test/mock/MockResolverType.java
deleted file mode 100644
index f4127c6..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/mock/MockResolverType.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.mock;
-
-public interface MockResolverType
-{
-    void forClass( Class clazz );
-}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MethodClassMatcherMockResolver.java b/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MethodClassMatcherMockResolver.java
deleted file mode 100644
index de3302f..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MethodClassMatcherMockResolver.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.mock.internal;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-
-public class MethodClassMatcherMockResolver
-    implements MockResolver, InvocationHandler
-{
-
-    private final Object recordedMock;
-    private final Class methodClass;
-
-    public MethodClassMatcherMockResolver( Object recordedMock, Class methodClass )
-    {
-        this.recordedMock = recordedMock;
-        this.methodClass = methodClass;
-    }
-
-    @Override
-    public InvocationHandler getInvocationHandler( Object proxy, Method method, Object[] args )
-    {
-        if( method.getDeclaringClass().equals( methodClass ) )
-        {
-            return this;
-        }
-        return null;
-    }
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        return method.invoke( recordedMock, args );
-    }
-}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MockRecorderMixin.java b/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MockRecorderMixin.java
deleted file mode 100644
index 555ee14..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MockRecorderMixin.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.mock.internal;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import org.qi4j.test.mock.MockRecorder;
-import org.qi4j.test.mock.MockResolverType;
-
-public class MockRecorderMixin
-    implements MockRecorder, MockRepository
-{
-
-    private final Collection<MockResolver> mockResolvers;
-
-    public MockRecorderMixin()
-    {
-        this.mockResolvers = new ArrayList<MockResolver>();
-    }
-
-    public MockResolverType useMock( Object mock )
-    {
-        System.out.println( "Recorded " + mock );
-        MockResolverProxy proxy = new MockResolverProxy( mock, new UnresolvableMockResolver() );
-        add( proxy );
-        return new MockResolverTypeImpl( proxy );
-    }
-
-    public void add( MockResolver mockResolver )
-    {
-        mockResolvers.add( mockResolver );
-    }
-
-    public Iterable<MockResolver> getAll()
-    {
-        return mockResolvers;
-    }
-}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MockRepository.java b/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MockRepository.java
deleted file mode 100644
index 1c4d8be..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MockRepository.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.mock.internal;
-
-public interface MockRepository
-{
-    void add( MockResolver mockResolver );
-
-    Iterable<MockResolver> getAll();
-}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MockResolver.java b/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MockResolver.java
deleted file mode 100644
index 06fc919..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MockResolver.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.mock.internal;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-
-/**
- * Resolves the invocation handler for a registred mock. Actual matching method is specific to each implementation.
- */
-public interface MockResolver
-{
-    /**
-     * Matches the method invocation to an invocation handler for a registered mock.
-     *
-     * @param proxy  object on which the method was invoked
-     * @param method invoked method
-     * @param args   invocation arguments
-     *
-     * @return invocation handler if this resolved can handle the call or null otherwise.
-     */
-    InvocationHandler getInvocationHandler( Object proxy, Method method, Object[] args );
-}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MockResolverProxy.java b/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MockResolverProxy.java
deleted file mode 100644
index 98711f3..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MockResolverProxy.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.mock.internal;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.qi4j.api.util.NullArgumentException;
-
-/**
- * Proxy to another mock resolver that can be set/changed over time. This allows
- * {@link org.qi4j.test.mock.MockResolverType} to change the mock resolver for a mock.
- */
-public class MockResolverProxy
-    implements MockResolver
-{
-    /**
-     * Registered mock. Cannot be null.
-     */
-    private final Object registeredMock;
-    /**
-     * Mock resolver delegate. Cannot be null.
-     */
-    private MockResolver mockResolver;
-
-    /**
-     * Constructor.
-     *
-     * @param registeredMock registered mock; cannot be null
-     * @param mockResolver   mock resolver delegate; cannot be null
-     *
-     * @throws NullArgumentException - If registred mock is null
-     *                               - If mock resolver is null
-     */
-    MockResolverProxy( final Object registeredMock, final MockResolver mockResolver )
-    {
-        NullArgumentException.validateNotNull( "Registered mock", registeredMock );
-        NullArgumentException.validateNotNull( "Mock resolver delegate", mockResolver );
-        this.registeredMock = registeredMock;
-        this.mockResolver = mockResolver;
-    }
-
-    /**
-     * Setter.
-     *
-     * @param mockResolver mock resolver delegate; cannot be null
-     *
-     * @return itself
-     *
-     * @throws NullArgumentException - If mock resolver is null
-     */
-    MockResolverProxy setMock( final MockResolver mockResolver )
-    {
-        NullArgumentException.validateNotNull( "Mock resolver delegate", mockResolver );
-        this.mockResolver = mockResolver;
-        return this;
-    }
-
-    /**
-     * Getter.
-     *
-     * @return registered mock
-     */
-    public Object getRegisteredMock()
-    {
-        return registeredMock;
-    }
-
-    /**
-     * Delegates to current mock resolver delegate.
-     *
-     * @see MockResolver#getInvocationHandler(Object, java.lang.reflect.Method, Object[])
-     */
-    @Override
-    public InvocationHandler getInvocationHandler( final Object proxy, final Method method, final Object[] args )
-    {
-        return mockResolver.getInvocationHandler( proxy, method, args );
-    }
-}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MockResolverTypeImpl.java b/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MockResolverTypeImpl.java
deleted file mode 100644
index 552e08e..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/mock/internal/MockResolverTypeImpl.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.mock.internal;
-
-import org.qi4j.test.mock.MockResolverType;
-
-public class MockResolverTypeImpl
-    implements MockResolverType
-{
-    private final MockResolverProxy proxy;
-
-    public MockResolverTypeImpl( MockResolverProxy proxy )
-    {
-        this.proxy = proxy;
-    }
-
-    @Override
-    public void forClass( final Class clazz )
-    {
-        proxy.setMock( new MethodClassMatcherMockResolver( proxy.getRegisteredMock(), clazz ) );
-    }
-}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/qi4j/test/mock/internal/UnresolvableMockResolver.java b/core/testsupport/src/main/java/org/qi4j/test/mock/internal/UnresolvableMockResolver.java
deleted file mode 100644
index 9bf0375..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/mock/internal/UnresolvableMockResolver.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.test.mock.internal;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-
-/**
- * Placeholder for a not specified resolver type.
- */
-public class UnresolvableMockResolver
-    implements MockResolver
-{
-    /**
-     * Does not match any method invocation. Always returns null.
-     *
-     * @see MockResolver#getInvocationHandler(Object, java.lang.reflect.Method, Object[])
-     */
-    @Override
-    public InvocationHandler getInvocationHandler( final Object proxy, final Method method, final Object[] args )
-    {
-        return null;
-    }
-}
\ No newline at end of file
diff --git a/core/testsupport/src/main/java/org/qi4j/test/mock/internal/package.html b/core/testsupport/src/main/java/org/qi4j/test/mock/internal/package.html
deleted file mode 100644
index 24923b1..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/mock/internal/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Test Support Composites Mocking Internal/Private package.</h2>
-    </body>
-</html>
diff --git a/core/testsupport/src/main/java/org/qi4j/test/mock/package.html b/core/testsupport/src/main/java/org/qi4j/test/mock/package.html
deleted file mode 100644
index 2431af0..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/mock/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Test Support Composites Mocking.</h2>
-    </body>
-</html>
diff --git a/core/testsupport/src/main/java/org/qi4j/test/package.html b/core/testsupport/src/main/java/org/qi4j/test/package.html
deleted file mode 100644
index 8e463ac..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Apache Zest™ Test Support.</h2>
-    </body>
-</html>
diff --git a/core/testsupport/src/main/java/org/qi4j/test/util/Assume.java b/core/testsupport/src/main/java/org/qi4j/test/util/Assume.java
deleted file mode 100644
index f60b0d3..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/util/Assume.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.test.util;
-
-import java.awt.GraphicsEnvironment;
-import java.io.IOException;
-import java.net.NetworkInterface;
-import java.net.Socket;
-import java.net.SocketException;
-import java.util.Enumeration;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-
-/**
- * A set of methods useful for stating assumptions about the conditions in which a test is meaningful.
- */
-public class Assume
-    extends org.junit.Assume
-{
-
-    /**
-     * If called on a IBM JDK, the test will halt and be ignored.
-     */
-    public static void assumeNoIbmJdk()
-    {
-        assumeFalse( System.getProperty( "java.vendor" ).contains( "IBM" ) );
-    }
-
-    /**
-     * If called on a headless runtime, the test will halt and be ignored.
-     */
-    public static void assumeDisplayPresent()
-    {
-        try
-        {
-            assumeFalse( GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance() );
-            String display = System.getenv( "DISPLAY" );
-            assumeThat( display, is( notNullValue() ) );
-            assumeTrue( display.length() > 0 );
-        } catch( UnsatisfiedLinkError e )
-        {
-            // assuming that this is caused due to missing video subsystem, or similar
-            assumeNoException( "Grahics system is missing?", e );
-        }
-    }
-
-    /**
-     * If called on a networkless runtime, the test will halt and be ignored.
-     */
-    public static void assumeNetworking()
-    {
-        try
-        {
-            Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
-            assumeThat( ifaces, is( notNullValue() ) );
-            assumeTrue( ifaces.hasMoreElements() );
-        }
-        catch( SocketException ex )
-        {
-            assumeNoException( ex );
-        }
-    }
-
-    /**
-     * // TODO: qi4j.org will soon go down.
-     * If called on a runtime with no access to qi4j.org on port 80, the test will halt and be ignored.
-     */
-    public static void assumeConnectivity()
-    {
-        assumeConnectivity( "qi4j.org", 80 );
-    }
-
-    /**
-     * If called on a runtime with no access to given host and port, the test will halt and be ignored.
-     *
-     * @param host Host
-     * @param port Port
-     */
-    public static void assumeConnectivity( String host, int port )
-    {
-        try( Socket socket = new Socket( host, port ) )
-        {
-            // Connected
-        }
-        catch( IOException ex )
-        {
-            assumeNoException( ex );
-        }
-    }
-
-    /**
-     * If called on a runtime without the given System Property set, the test will halt and be ignored.
-     * @param key the name of the system property
-     * @return The System Propery value if not null
-     */
-    public static String assumeSystemPropertyNotNull( String key )
-    {
-        String property = System.getProperty( key );
-        assumeNotNull( property );
-        return property;
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/util/DelTreeAfter.java b/core/testsupport/src/main/java/org/qi4j/test/util/DelTreeAfter.java
deleted file mode 100644
index 1dd4afb..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/util/DelTreeAfter.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2013 Paul Merlin.
- *
- * Licensed  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.qi4j.test.util;
-
-import java.io.File;
-import java.io.IOException;
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-
-/**
- * JUnit Test Rule that delete directories after the test.
- */
-public class DelTreeAfter
-    implements TestRule
-{
-
-    private final boolean createDirsBefore;
-    private final File[] directories;
-
-    public DelTreeAfter( File... directories )
-    {
-        this( false, directories );
-    }
-
-    public DelTreeAfter( boolean createDirsBefore, File[] directories )
-    {
-        this.createDirsBefore = createDirsBefore;
-        this.directories = directories;
-    }
-
-    @Override
-    public Statement apply( final Statement base, Description description )
-    {
-        return new Statement()
-        {
-            @Override
-            public void evaluate()
-                throws Throwable
-            {
-                if( createDirsBefore )
-                {
-                    for( File dir : directories )
-                    {
-                        if( !dir.mkdirs() )
-                        {
-                            throw new IOException( "Unable to create directory: " + dir );
-                        }
-                    }
-                }
-                try
-                {
-                    base.evaluate();
-                }
-                finally
-                {
-                    if( directories != null )
-                    {
-                        for( File dir : directories )
-                        {
-                            if( dir.exists() )
-                            {
-                                delTree( dir );
-                            }
-                        }
-                    }
-                }
-            }
-        };
-    }
-
-    private static void delTree( File dir )
-    {
-        if( dir.isDirectory() )
-        {
-            for( File file : dir.listFiles() )
-            {
-                delTree( file );
-            }
-            dir.delete();
-        }
-        else
-        {
-            dir.delete();
-        }
-    }
-
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/util/FreePortFinder.java b/core/testsupport/src/main/java/org/qi4j/test/util/FreePortFinder.java
deleted file mode 100644
index d682b08..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/util/FreePortFinder.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.test.util;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-
-public class FreePortFinder
-{
-
-    public static int findFreePortOnLoopback()
-            throws IOException
-    {
-        return findFreePortOnIface( InetAddress.getLocalHost() );
-    }
-
-    public static int findFreePortOnLoopback( int prefered )
-            throws IOException
-    {
-        return findFreePortOnIface( InetAddress.getLocalHost(), prefered );
-    }
-
-    public static int findFreePortOnIface( InetAddress address )
-            throws IOException
-    {
-        return findFreePortOnIface( address, -1 );
-    }
-
-    public static int findFreePortOnIface( InetAddress address, int prefered )
-            throws IOException
-    {
-        ServerSocket server;
-        if ( prefered > 0 ) {
-            server = new ServerSocket( prefered, 1, address );
-        } else {
-            server = new ServerSocket( 0, 1, address );
-        }
-        int port = server.getLocalPort();
-        server.close();
-        return port;
-    }
-
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/util/JSONAssert.java b/core/testsupport/src/main/java/org/qi4j/test/util/JSONAssert.java
deleted file mode 100644
index 3a69e36..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/util/JSONAssert.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.test.util;
-
-import java.util.Iterator;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.junit.Assert;
-
-/**
- * A set of assertion methods useful for tests using org.json.
- */
-public class JSONAssert
-    extends Assert
-{
-
-    /**
-     * Assert that two JSONObjects are equals without enforcing field order.
-     */
-    public static void jsonObjectsEquals( JSONObject o1, JSONObject o2 )
-        throws JSONException
-    {
-        if( o1 != o2 )
-        {
-            if( o1.length() != o2.length() )
-            {
-                fail( "JSONObjects length differ: " + o1.length() + " / " + o2.length() );
-            }
-            @SuppressWarnings( "unchecked" )
-            Iterator<String> o1Keys = o1.keys();
-            while( o1Keys.hasNext() )
-            {
-                String key = o1Keys.next();
-                Object o1Value = o1.get( key );
-                Object o2Value = o2.get( key );
-                if( !jsonValueEquals( o1Value, o2Value ) )
-                {
-                    fail( "JSONObject '" + key + "' values differ: " + o1Value + " / " + o2Value );
-                }
-            }
-        }
-    }
-
-    /**
-     * Assert that two JSONArrays are equals.
-     */
-    public static void jsonArraysEquals( JSONArray a1, JSONArray a2 )
-        throws JSONException
-    {
-        if( a1 != a2 )
-        {
-            if( a1.length() != a2.length() )
-            {
-                fail( "JSONArrays length differ: " + a1.length() + " / " + a2.length() );
-            }
-            for( int idx = 0; idx < a1.length(); idx++ )
-            {
-                Object a1Value = a1.get( idx );
-                Object a2Value = a2.get( idx );
-                if( !jsonValueEquals( a1Value, a2Value ) )
-                {
-                    fail( "JSONArray '" + idx + "' values differ: " + a1Value + " / " + a2Value );
-                }
-            }
-        }
-    }
-
-    private static boolean jsonValueEquals( Object o1Value, Object o2Value )
-        throws JSONException
-    {
-        if( o1Value instanceof JSONObject )
-        {
-
-            if( !( o2Value instanceof JSONObject ) )
-            {
-                return false;
-            }
-            jsonObjectsEquals( (JSONObject) o1Value, (JSONObject) o2Value );
-
-        }
-        else if( o1Value instanceof JSONArray )
-        {
-
-            if( !( o2Value instanceof JSONArray ) )
-            {
-                return false;
-            }
-            jsonArraysEquals( (JSONArray) o1Value, (JSONArray) o2Value );
-
-        }
-        else if( !o1Value.equals( o2Value ) )
-        {
-
-            return false;
-
-        }
-        return true;
-    }
-
-    private JSONAssert()
-    {
-    }
-
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/util/RepeatRule.java b/core/testsupport/src/main/java/org/qi4j/test/util/RepeatRule.java
deleted file mode 100644
index 7b5a9fe..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/util/RepeatRule.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.test.util;
-
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-
-/**
- * JUnit Rule to run tests repeatedly.
- *
- * <p>To repeat a complete test class:</p>
- * <pre>@ClassRule public static final RepeatRule REPEAT = new RepeatRule( 10 );</pre>
- *
- * <p>To repeat each test on the same test class instance:</p>
- * <pre>@Rule public final RepeatRule repeat = new RepeatRule( 10 );</pre>
- */
-public class RepeatRule
-    implements TestRule
-{
-    private final int count;
-
-    public RepeatRule( int count )
-    {
-        this.count = count;
-    }
-
-    @Override
-    public Statement apply( final Statement base, Description description )
-    {
-        return new Statement()
-        {
-            @Override
-            public void evaluate()
-                throws Throwable
-            {
-                for( int repeat = 0; repeat < count; repeat++ )
-                {
-                    base.evaluate();
-                }
-            }
-        };
-    }
-
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/util/package.html b/core/testsupport/src/main/java/org/qi4j/test/util/package.html
deleted file mode 100644
index d74efb2..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/util/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Test Support Utilities.</h2>
-    </body>
-</html>
diff --git a/core/testsupport/src/main/java/org/qi4j/test/value/AbstractCollectionSerializationTest.java b/core/testsupport/src/main/java/org/qi4j/test/value/AbstractCollectionSerializationTest.java
deleted file mode 100644
index 3a04ee5..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/value/AbstractCollectionSerializationTest.java
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright (c) 2011, Niclas Hehdman. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.test.value;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.type.CollectionType;
-import org.qi4j.api.type.MapType;
-import org.qi4j.api.type.ValueCompositeType;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Iterables;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.*;
-import static org.qi4j.io.Inputs.iterable;
-import static org.qi4j.io.Inputs.text;
-import static org.qi4j.io.Outputs.collection;
-import static org.qi4j.io.Outputs.text;
-import static org.qi4j.io.Transforms.map;
-
-/**
- * Assert that ValueSerialization behaviour on Collections and Maps is correct.
- */
-// TODO How to assert that given a collection of valuecomposites when serializing and deserializing we have to OOME?
-public class AbstractCollectionSerializationTest
-    extends AbstractQi4jTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.values( SomeValue.class );
-    }
-
-    @Before
-    public void before()
-    {
-        module.injectTo( this );
-    }
-
-    @Service
-    @SuppressWarnings( "ProtectedField" )
-    protected ValueSerialization valueSerialization;
-
-    @Test
-    public void testIOString()
-        throws Exception
-    {
-        StringBuilder sb = new StringBuilder();
-        iterable( byteCollection() ).transferTo( map( valueSerialization.serialize(), text( sb ) ) );
-        String output = sb.toString();
-
-        List<Byte> list = new ArrayList<Byte>();
-        text( output ).transferTo( map( valueSerialization.deserialize( Byte.class ), collection( list ) ) );
-        assertEquals( byteCollection(), list );
-    }
-
-    @Test
-    public void givenPrimitiveArrayWithIntsWhenSerializingAndDeserializingExpectEquals()
-        throws Exception
-    {
-        int[] primitiveArray = new int[]
-        {
-            23, 42, -23, -42
-        };
-        String output = valueSerialization.serialize( primitiveArray );
-        int[] deserialized = valueSerialization.deserialize( int[].class, output );
-        assertArrayEquals( primitiveArray, deserialized );
-    }
-
-    @Test
-    public void givenArrayWithByteAndNullElementWhenSerializingAndDeserializingExpectEquals()
-        throws Exception
-    {
-        Byte[] array = new Byte[]
-        {
-            9, null, -12, -12, 127, -128, 73
-        };
-        String output = valueSerialization.serialize( array );
-        Byte[] deserialized = valueSerialization.deserialize( Byte[].class, output );
-        assertArrayEquals( array, deserialized );
-    }
-
-    @Test
-    public void givenIterableTypeWithByteAndNullElementWhenSerializingAndDeserializingExpectEquals()
-        throws Exception
-    {
-        String output = valueSerialization.serialize( Iterables.iterable( byteCollection().toArray() ) );
-        CollectionType collectionType = new CollectionType( List.class, new ValueType( Byte.class ) );
-        List<Byte> list = valueSerialization.deserialize( collectionType, output );
-        assertEquals( byteCollection(), list );
-    }
-
-    @Test
-    public void givenCollectionTypeWithByteAndNullElementWhenSerializingAndDeserializingExpectEquals()
-        throws Exception
-    {
-        String output = valueSerialization.serialize( byteCollection() );
-        CollectionType collectionType = new CollectionType( Set.class, new ValueType( Byte.class ) );
-        Set<Byte> list = valueSerialization.deserialize( collectionType, output );
-        assertEquals( new LinkedHashSet<Byte>( byteCollection() ), list );
-    }
-
-    @Test
-    public void givenCollectionTypeWithCharacterAndNullElementWhenSerializingAndDeserializingExpectEquals()
-        throws Exception
-    {
-        String output = valueSerialization.serialize( characterCollection() );
-        CollectionType collectionType = new CollectionType( List.class, new ValueType( Character.class ) );
-        List<Character> list = valueSerialization.deserialize( collectionType, output );
-        assertEquals( characterCollection(), list );
-    }
-
-    @Test
-    public void givenCollectionTypeWithShortAndNullElementWhenSerializingAndDeserializingExpectEquals()
-        throws Exception
-    {
-        String output = valueSerialization.serialize( shortCollection() );
-        CollectionType collectionType = new CollectionType( List.class, new ValueType( Short.class ) );
-        List<Short> list = valueSerialization.deserialize( collectionType, output );
-        assertEquals( shortCollection(), list );
-    }
-
-    @Test
-    public void givenCollectionTypeWithIntegerAndNullElementWhenSerializingAndDeserializingExpectEquals()
-        throws Exception
-    {
-        String output = valueSerialization.serialize( integerCollection() );
-        CollectionType collectionType = new CollectionType( List.class, new ValueType( Integer.class ) );
-        List<Integer> list = valueSerialization.deserialize( collectionType, output );
-        assertEquals( integerCollection(), list );
-    }
-
-    @Test
-    public void givenCollectionTypeWithLongAndNullElementWhenSerializingAndDeserializingExpectEquals()
-        throws Exception
-    {
-        String output = valueSerialization.serialize( longCollection() );
-        CollectionType collectionType = new CollectionType( List.class, new ValueType( Long.class ) );
-        List<Long> list = valueSerialization.deserialize( collectionType, output );
-        assertEquals( longCollection(), list );
-    }
-
-    @Test
-    public void givenCollectionTypeWithFloatAndNullElementWhenSerializingAndDeserializingExpectEquals()
-        throws Exception
-    {
-        String output = valueSerialization.serialize( floatCollection() );
-        CollectionType collectionType = new CollectionType( List.class, new ValueType( Float.class ) );
-        List<Float> list = valueSerialization.deserialize( collectionType, output );
-        assertEquals( floatCollection(), list );
-    }
-
-    @Test
-    public void givenCollectionTypeWithDoubleAndNullElementWhenSerializingExpectCorrectJsonOutput()
-        throws Exception
-    {
-        String output = valueSerialization.serialize( doubleCollection() );
-        CollectionType collectionType = new CollectionType( List.class, new ValueType( Double.class ) );
-        List<Double> list = valueSerialization.deserialize( collectionType, output );
-        assertEquals( doubleCollection(), list );
-
-    }
-
-    @Test
-    public void givenCollectionTypeWithBigIntegerAndNullElementWhenSerializingAndDeserializingExpectEquals()
-        throws Exception
-    {
-        String output = valueSerialization.serialize( bigIntegerCollection() );
-        CollectionType collectionType = new CollectionType( List.class, new ValueType( BigInteger.class ) );
-        List<BigInteger> list = valueSerialization.deserialize( collectionType, output );
-        assertEquals( bigIntegerCollection(), list );
-    }
-
-    @Test
-    public void givenCollectionTypeWithBigDecimalAndNullElementWhenSerializingAndDeserializingExpectEquals()
-        throws Exception
-    {
-        String output = valueSerialization.serialize( bigDecimalCollection() );
-        CollectionType collectionType = new CollectionType( Collection.class, new ValueType( BigDecimal.class ) );
-        Collection<BigDecimal> collection = valueSerialization.deserialize( collectionType, output );
-        assertEquals( bigDecimalCollection(), collection );
-    }
-
-    @Test
-    public void givenMapOfStringByteAndNullElementWhenSerializingAndDeserializingExpectEquals()
-        throws Exception
-    {
-        String output = valueSerialization.serialize( stringByteMap() );
-        MapType mapType = new MapType( Map.class, new ValueType( String.class ), new ValueType( Byte.class ) );
-        Map<String, Byte> value = valueSerialization.deserialize( mapType, output );
-        assertEquals( stringByteMap(), value );
-    }
-
-    @Test
-    public void givenMapOfStringListStringAndNullElementWhenSerializingAndDeserializingExpectEquals()
-        throws Exception
-    {
-        String output = valueSerialization.serialize( stringMultiMap() );
-        CollectionType collectionType = new CollectionType( List.class, new ValueType( String.class ) );
-        MapType mapType = new MapType( Map.class, new ValueType( String.class ), collectionType );
-        Map<String, List<String>> value = valueSerialization.deserialize( mapType, output );
-        assertEquals( stringMultiMap(), value );
-    }
-
-    @Test
-    public void givenListOfMapStringStringAndNullElementWhenSerializingAndDeserializingExpectEquals()
-        throws Exception
-    {
-        String output = valueSerialization.serialize( stringListOfMaps() );
-        ValueType stringType = new ValueType( String.class );
-        CollectionType collectionType = new CollectionType( List.class, new MapType( Map.class, stringType, stringType ) );
-        List<Map<String, String>> value = valueSerialization.deserialize( collectionType, output );
-        assertEquals( stringListOfMaps(), value );
-    }
-
-    @Test
-    public void givenListOfValueCompositesAndNullElementWhenSerializingAndDeserializingExpectEquals()
-        throws Exception
-    {
-        String output = valueSerialization.serialize( valueCompositesList() );
-        ValueCompositeType valueType = module.valueDescriptor( SomeValue.class.getName() ).valueType();
-        CollectionType collectionType = new CollectionType( List.class, valueType );
-        List<SomeValue> value = valueSerialization.deserialize( collectionType, output );
-        assertEquals( valueCompositesList(), value );
-    }
-
-    private ArrayList<Byte> byteCollection()
-    {
-        ArrayList<Byte> value = new ArrayList<Byte>();
-        value.add( (byte) 9 );
-        value.add( null );
-        value.add( (byte) -12 );
-        value.add( (byte) -12 );
-        value.add( (byte) 127 );
-        value.add( (byte) -128 );
-        value.add( (byte) 73 );
-        return value;
-    }
-
-    private List<Character> characterCollection()
-    {
-        List<Character> value = new ArrayList<Character>();
-        value.add( 'Q' );
-        value.add( 'i' );
-        value.add( null );
-        value.add( '4' );
-        value.add( 'j' );
-        return value;
-    }
-
-    private Collection<Short> shortCollection()
-    {
-        Collection<Short> value = new ArrayList<Short>();
-        value.add( (short) -32768 );
-        value.add( (short) 32767 );
-        value.add( (short) -82 );
-        value.add( null );
-        return value;
-    }
-
-    private Collection<Integer> integerCollection()
-    {
-        Collection<Integer> value = new ArrayList<Integer>();
-        value.add( Integer.MAX_VALUE );
-        value.add( -283 );
-        value.add( null );
-        value.add( Integer.MIN_VALUE );
-        value.add( 238 );
-        return value;
-    }
-
-    private Collection<Long> longCollection()
-    {
-        Collection<Long> value = new ArrayList<Long>();
-        value.add( 98239723L );
-        value.add( -1298233L );
-        value.add( -1L );
-        value.add( 0L );
-        value.add( null );
-        value.add( 1L );
-        value.add( Long.MAX_VALUE );
-        value.add( Long.MIN_VALUE );
-        return value;
-    }
-
-    private Collection<Float> floatCollection()
-    {
-        Collection<Float> value = new ArrayList<Float>();
-        value.add( -1f );
-        value.add( 1f );
-        value.add( 1f );
-        value.add( 0f );
-        value.add( Float.MAX_VALUE );
-        value.add( Float.MIN_VALUE );
-        value.add( null );
-        value.add( 0.123456f );
-        value.add( -0.232321f );
-        return value;
-    }
-
-    private Collection<Double> doubleCollection()
-    {
-        Collection<Double> value = new ArrayList<Double>();
-        value.add( -1.0 );
-        value.add( 1.0 );
-        value.add( 0.0 );
-        value.add( Double.MAX_VALUE );
-        value.add( null );
-        value.add( Double.MIN_VALUE );
-        value.add( 0.123456 );
-        value.add( -0.232321 );
-        return value;
-    }
-
-    private Collection<BigInteger> bigIntegerCollection()
-    {
-        Collection<BigInteger> value = new ArrayList<BigInteger>();
-        value.add( new BigInteger( "-1" ) );
-        value.add( BigInteger.ZERO );
-        value.add( BigInteger.ONE );
-        value.add( null );
-        value.add( BigInteger.TEN );
-        value.add( new BigInteger( "-1827368263823729372397239829332" ) );
-        value.add( new BigInteger( "2398723982982379827373972398723" ) );
-        return value;
-    }
-
-    private Collection<BigDecimal> bigDecimalCollection()
-    {
-        Collection<BigDecimal> value = new ArrayList<BigDecimal>();
-        value.add( new BigDecimal( "1.2" ) );
-        value.add( new BigDecimal( "3.4" ) );
-        value.add( null );
-        value.add( new BigDecimal( "5.6" ) );
-        return value;
-    }
-
-    private Map<String, Byte> stringByteMap()
-    {
-        Map<String, Byte> value = new LinkedHashMap<String, Byte>();
-        value.put( "a", (byte) 9 );
-        value.put( "b", null );
-        value.put( "c", (byte) -12 );
-        return value;
-    }
-
-    private Map<String, List<String>> stringMultiMap()
-    {
-        Map<String, List<String>> value = new LinkedHashMap<String, List<String>>();
-        List<String> list = new ArrayList<String>();
-        list.add( "foo" );
-        list.add( "bar" );
-        list.add( null );
-        list.add( "cathedral" );
-        list.add( "bazar" );
-        value.put( "alpha", list );
-        value.put( "beta", null );
-        value.put( "gamma", Collections.<String>emptyList() );
-        return value;
-    }
-
-    private List<Map<String, String>> stringListOfMaps()
-    {
-        List<Map<String, String>> value = new ArrayList<Map<String, String>>();
-        Map<String, String> map = new LinkedHashMap<String, String>();
-        map.put( "foo", "bar" );
-        map.put( "cathedral", "bazar" );
-        map.put( "yield", null );
-        map.put( "42", "23" );
-        value.add( map );
-        value.add( null );
-        value.add( Collections.<String, String>emptyMap() );
-        return value;
-    }
-
-    private List<SomeValue> valueCompositesList()
-    {
-        List<SomeValue> list = new ArrayList<SomeValue>();
-        list.add( newSomeValue( "", "bazar" ) );
-        list.add( null );
-        list.add( newSomeValue( "bar", null ) );
-        return list;
-    }
-
-    public static interface SomeValue
-    {
-
-        Property<String> foo();
-
-        @Optional
-        Property<String> cathedral();
-    }
-
-    private SomeValue newSomeValue( String foo, String cathedral )
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        SomeValue value = builder.prototype();
-        value.foo().set( foo );
-        if( cathedral != null )
-        {
-            value.cathedral().set( cathedral );
-        }
-        return builder.newInstance();
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/value/AbstractJsonDateFormatTest.java b/core/testsupport/src/main/java/org/qi4j/test/value/AbstractJsonDateFormatTest.java
deleted file mode 100644
index 712691e..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/value/AbstractJsonDateFormatTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.test.value;
-
-import java.util.Date;
-import java.util.List;
-import org.joda.time.DateTime;
-import org.joda.time.DateTimeZone;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.type.CollectionType;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.api.value.ValueDeserializer;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.*;
-
-/**
- * Assert that a JSON ValueDeserializer support various date formats.
- */
-@SuppressWarnings( "ProtectedField" )
-public class AbstractJsonDateFormatTest
-    extends AbstractQi4jTest
-{
-
-    private final ValueType dateType = new ValueType( Date.class );
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-    }
-
-    @Before
-    public void before()
-    {
-        module.injectTo( this );
-    }
-    @Service
-    protected ValueDeserializer valueDeserializer;
-
-    @Test
-    public void givenISO6801DateFormatWhenConvertingFromSerializedStateExpectValidDate()
-        throws Exception
-    {
-        CollectionType collectionType = new CollectionType( List.class, dateType );
-        List<Date> value = valueDeserializer.deserialize( collectionType, "[\"2009-08-12T14:54:27.895+0800\"]" );
-        assertEquals( new DateTime( "2009-08-12T06:54:27.895Z", DateTimeZone.UTC ).toDate(), value.get( 0 ) );
-    }
-
-    @Test
-    public void givenAtDateFormatWhenConvertingFromSerializedStateExpectValidDate()
-        throws Exception
-    {
-        long tstamp = System.currentTimeMillis();
-        CollectionType collectionType = new CollectionType( List.class, dateType );
-        List<Date> value = valueDeserializer.deserialize( collectionType, "[\"@" + tstamp + "@\"]" );
-        assertEquals( new Date( tstamp ), value.get( 0 ) );
-    }
-
-    @Test
-    public void givenMicrosoftDateFormatWhenConvertingFromSerializedStateExpectValidDate()
-        throws Exception
-    {
-        long tstamp = System.currentTimeMillis();
-        CollectionType collectionType = new CollectionType( List.class, dateType );
-        List<Date> value = valueDeserializer.deserialize( collectionType, "[\"/Date(" + tstamp + ")/\"]" );
-        assertEquals( new Date( tstamp ), value.get( 0 ) );
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/value/AbstractPlainValueSerializationTest.java b/core/testsupport/src/main/java/org/qi4j/test/value/AbstractPlainValueSerializationTest.java
deleted file mode 100644
index 218cca6..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/value/AbstractPlainValueSerializationTest.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2011, Niclas Hehdman. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.test.value;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.Date;
-import org.joda.time.DateTime;
-import org.joda.time.LocalDate;
-import org.joda.time.LocalDateTime;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.hamcrest.core.IsNot.not;
-import static org.joda.time.DateTimeZone.UTC;
-import static org.joda.time.DateTimeZone.forID;
-import static org.joda.time.DateTimeZone.forOffsetHours;
-import static org.junit.Assert.assertThat;
-
-/**
- * Assert that ValueSerialization behaviour on plain values is correct.
- */
-public abstract class AbstractPlainValueSerializationTest
-    extends AbstractQi4jTest
-{
-
-    @Before
-    public void before()
-    {
-        module.injectTo( this );
-    }
-    @Service
-    @SuppressWarnings( "ProtectedField" )
-    protected ValueSerialization valueSerialization;
-
-    @Test
-    public void givenCharacterValueWhenSerializingAndDeserializingExpectEquals()
-    {
-        String serialized = valueSerialization.serialize( 'q' );
-        assertThat( "Serialized", serialized, equalTo( "q" ) );
-
-        Character deserialized = valueSerialization.deserialize( Character.class, serialized );
-        assertThat( "Deserialized", deserialized, equalTo( 'q' ) );
-    }
-
-    @Test
-    public void givenEmptyStringValueWhenSerializingAndDeserializingExpectEquals()
-    {
-        String serialized = valueSerialization.serialize( "" );
-        assertThat( "Serialized", serialized, equalTo( "" ) );
-
-        String deserialized = valueSerialization.deserialize( String.class, serialized );
-        assertThat( "Deserialized", deserialized, equalTo( "" ) );
-    }
-
-    @Test
-    public void givenStringValueWhenSerializingAndDeserializingExpectEquals()
-    {
-        String serialized = valueSerialization.serialize( "test" );
-        assertThat( serialized, equalTo( "test" ) );
-
-        String deserialized = valueSerialization.deserialize( String.class, serialized );
-        assertThat( deserialized, equalTo( "test" ) );
-    }
-
-    @Test
-    public void givenBooleanValueWhenSerializingAndDeserializingExpectEquals()
-    {
-        String serialized = valueSerialization.serialize( Boolean.TRUE );
-        assertThat( serialized, equalTo( "true" ) );
-
-        Boolean deserialized = valueSerialization.deserialize( Boolean.class, serialized );
-        assertThat( deserialized, equalTo( Boolean.TRUE ) );
-    }
-
-    @Test
-    public void givenIntegerValueWhenSerializingAndDeserializingExpectEquals()
-    {
-        String serialized = valueSerialization.serialize( 42 );
-        assertThat( serialized, equalTo( "42" ) );
-        Integer deserialized = valueSerialization.deserialize( Integer.class, serialized );
-        assertThat( deserialized, equalTo( 42 ) );
-    }
-
-    @Test
-    public void givenLongValueWhenSerializingAndDeserializingExpectEquals()
-    {
-        String serialized = valueSerialization.serialize( 42L );
-        assertThat( serialized, equalTo( "42" ) );
-
-        Long deserialized = valueSerialization.deserialize( Long.class, serialized );
-        assertThat( deserialized, equalTo( 42L ) );
-    }
-
-    @Test
-    public void givenShortValueWhenSerializingAndDeserializingExpectEquals()
-    {
-        String serialized = valueSerialization.serialize( (short) 42 );
-        assertThat( serialized, equalTo( "42" ) );
-
-        Short deserialized = valueSerialization.deserialize( Short.class, serialized );
-        assertThat( deserialized, equalTo( (short) 42 ) );
-    }
-
-    @Test
-    public void givenByteValueWhenSerializingAndDeserializingExpectEquals()
-    {
-        String serialized = valueSerialization.serialize( (byte) 42 );
-        assertThat( serialized, equalTo( "42" ) );
-        Byte deserialized = valueSerialization.deserialize( Byte.class, serialized );
-        assertThat( deserialized, equalTo( (byte) 42 ) );
-    }
-
-    @Test
-    public void givenFloatValueWhenSerializingAndDeserializingExpectEquals()
-    {
-        String serialized = valueSerialization.serialize( 42F );
-        assertThat( serialized, equalTo( "42.0" ) );
-
-        Float deserialized = valueSerialization.deserialize( Float.class, serialized );
-        assertThat( deserialized, equalTo( 42F ) );
-    }
-
-    @Test
-    public void givenDoubleValueWhenSerializingAndDeserializingExpectEquals()
-    {
-        String serialized = valueSerialization.serialize( 42D );
-        assertThat( serialized, equalTo( "42.0" ) );
-
-        Double deserialized = valueSerialization.deserialize( Double.class, serialized );
-        assertThat( deserialized, equalTo( 42D ) );
-    }
-
-    @Test
-    public void givenBigIntegerValueWhenSerializingAndDeserializingExpectEquals()
-    {
-        BigInteger bigInteger = new BigInteger( "42424242424242424242424242" );
-        assertThat( bigInteger, not( equalTo( BigInteger.valueOf( bigInteger.longValue() ) ) ) );
-
-        String serialized = valueSerialization.serialize( bigInteger );
-        assertThat( serialized, equalTo( "42424242424242424242424242" ) );
-
-        BigInteger deserialized = valueSerialization.deserialize( BigInteger.class, serialized );
-        assertThat( deserialized, equalTo( bigInteger ) );
-    }
-
-    @Test
-    public void givenBigDecimalValueWhenSerializingAndDeserializingExpectEquals()
-    {
-        BigDecimal bigDecimal = new BigDecimal( "42.2376931348623157e+309" );
-        assertThat( bigDecimal.doubleValue(), equalTo( Double.POSITIVE_INFINITY ) );
-        
-        String serialized = valueSerialization.serialize( bigDecimal );
-        assertThat( serialized, equalTo( "4.22376931348623157E+310" ) );
-
-        BigDecimal deserialized = valueSerialization.deserialize( BigDecimal.class, serialized );
-        assertThat( deserialized, equalTo( bigDecimal ) );
-    }
-
-    @Test
-    public void givenDateValueWhenSerializingAndDeserializingExpectEquals()
-    {
-        String serialized = valueSerialization.serialize( new DateTime( "2020-03-04T13:24:35", forID( "CET" ) ).toDate() );
-        assertThat( serialized, equalTo( "2020-03-04T12:24:35.000Z" ) );
-
-        Date deserialized = valueSerialization.deserialize( Date.class, serialized );
-        assertThat( deserialized, equalTo( new DateTime( "2020-03-04T13:24:35", forID( "CET" ) ).toDate() ) );
-        assertThat( deserialized, equalTo( new DateTime( "2020-03-04T12:24:35", UTC ).toDate() ) );
-    }
-
-    @Test
-    public void givenDateTimeValueWhenSerializingAndDeserializingExpectEquals()
-    {
-        // We specify the TimeZone explicitely here so that serialized/deserialized is equals
-        // See https://github.com/JodaOrg/joda-time/issues/106
-        String serialized = valueSerialization.serialize( new DateTime( "2020-03-04T13:24:35", forOffsetHours( 1 ) ) );
-        assertThat( serialized, equalTo( "2020-03-04T13:24:35.000+01:00" ) );
-        DateTime deserialized = valueSerialization.deserialize( DateTime.class, serialized );
-        assertThat( deserialized, equalTo( new DateTime( "2020-03-04T13:24:35", forOffsetHours( 1 ) ) ) );
-    }
-
-    @Test
-    public void givenLocalDateTimeValueWhenSerializingAndDeserializingExpectEquals()
-    {
-        // Serialized without TimeZone
-        String serialized = valueSerialization.serialize( new LocalDateTime( "2020-03-04T13:23:00", forID( "CET" ) ) );
-        assertThat( serialized, equalTo( "2020-03-04T13:23:00.000" ) );
-
-        LocalDateTime deserialized = valueSerialization.deserialize( LocalDateTime.class, serialized );
-        assertThat( deserialized, equalTo( new LocalDateTime( "2020-03-04T13:23:00", UTC ) ) );
-    }
-
-    @Test
-    public void givenLocalDateValueWhenSerializingAndDeserializingExpectEquals()
-    {
-        String serialized = valueSerialization.serialize( new LocalDate( "2020-03-04" ) );
-        assertThat( serialized, equalTo( "2020-03-04" ) );
-
-        LocalDate deserialized = valueSerialization.deserialize( LocalDate.class, serialized );
-        assertThat( deserialized, equalTo( new LocalDate( "2020-03-04" ) ) );
-    }
-
-    @Test
-    public void givenEntityReferenceValueWhenSerializingAndDeserializingExpectEquals()
-    {
-        String serialized = valueSerialization.serialize( EntityReference.parseEntityReference( "ABCD-1234" ) );
-        assertThat( serialized, equalTo( "ABCD-1234" ) );
-
-        EntityReference deserialized = valueSerialization.deserialize( EntityReference.class, serialized );
-        assertThat( deserialized, equalTo( EntityReference.parseEntityReference( "ABCD-1234" ) ) );
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/value/AbstractValueCompositeSerializationTest.java b/core/testsupport/src/main/java/org/qi4j/test/value/AbstractValueCompositeSerializationTest.java
deleted file mode 100644
index 82947e9..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/value/AbstractValueCompositeSerializationTest.java
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.test.value;
-
-import java.io.ByteArrayOutputStream;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import org.joda.time.DateTime;
-import org.joda.time.DateTimeZone;
-import org.joda.time.LocalDate;
-import org.joda.time.LocalDateTime;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestName;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-/**
- * Assert that ValueSerialization behaviour on ValueComposites is correct.
- */
-// TODO Assert Arrays behaviour!
-// TODO Assert Generics behaviour!
-public abstract class AbstractValueCompositeSerializationTest
-    extends AbstractQi4jTest
-{
-    @Rule
-    public TestName testName = new TestName();
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.values( SomeValue.class, AnotherValue.class, FooValue.class, CustomFooValue.class,
-                       SpecificCollection.class /*, SpecificValue.class, GenericValue.class */ );
-
-        new EntityTestAssembler().visibleIn( Visibility.layer ).assemble( module.layer().module( "persistence" ) );
-        module.entities( BarEntity.class );
-    }
-
-    @Before
-    public void before()
-    {
-        module.injectTo( this );
-    }
-
-    @Service
-    protected ValueSerialization valueSerialization;
-
-    @Test
-    public void givenValueCompositeWhenSerializingAndDeserializingExpectEquals()
-        throws Exception
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            SomeValue some = buildSomeValue();
-
-            // Serialize using injected service
-            ByteArrayOutputStream output = new ByteArrayOutputStream();
-            valueSerialization.serialize( some, output );
-            String stateString = output.toString( "UTF-8" );
-
-            // Deserialize using Module API
-            SomeValue some2 = module.newValueFromSerializedState( SomeValue.class, stateString );
-
-            assertThat( "Same value toString", some.toString(), equalTo( some2.toString() ) );
-            assertThat( "Same value", some, equalTo( some2 ) );
-            assertThat( "Same JSON value toString", stateString, equalTo( some2.toString() ) );
-            assertThat( "Same JSON value", some.customFoo().get() instanceof CustomFooValue, is( true ) );
-            assertThat( "Same JSON value explicit", some.customFooValue().get() instanceof CustomFooValue, is( true ) );
-
-            assertThat( "String Integer Map", some2.stringIntMap().get().get( "foo" ), equalTo( 42 ) );
-            assertThat( "String Value Map", some2.stringValueMap().get().get( "foo" ).internalVal(), equalTo( "Bar" ) );
-            assertThat( "Nested Entities", some2.barAssociation().get().cathedral().get(), equalTo( "bazar in barAssociation" ) );
-        }
-        catch( Exception ex )
-        {
-            throw ex;
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    /**
-     * @return a SomeValue ValueComposite whose state is populated with test data.
-     */
-    private SomeValue buildSomeValue()
-    {
-        ValueBuilder<SomeValue> builder = module.newValueBuilder( SomeValue.class );
-        SomeValue proto = builder.prototype();
-        proto.anotherList().get().add( module.newValue( AnotherValue.class ) );
-
-        ValueBuilder<SpecificCollection> specificColBuilder = module.newValueBuilder( SpecificCollection.class );
-        SpecificCollection specificColProto = specificColBuilder.prototype();
-        List<String> genericList = new ArrayList<>( 2 );
-        genericList.add( "Some" );
-        genericList.add( "String" );
-        specificColProto.genericList().set( genericList );
-        proto.specificCollection().set( specificColBuilder.newInstance() );
-
-        AnotherValue anotherValue1 = createAnotherValue( "Foo", "Bar" );
-        AnotherValue anotherValue2 = createAnotherValue( "Habba", "ZoutZout" );
-        AnotherValue anotherValue3 = createAnotherValue( "Niclas", "Hedhman" );
-
-        // FIXME Some Control Chars are not supported in JSON nor in XML, what should we do about it?
-        // Should Zest Core ensure the chars used in strings are supported by the whole stack?
-        // proto.string().set( "Foo\"Bar\"\nTest\f\t\b" );
-        proto.string().set( "Foo\"Bar\"\nTest\t" );
-        proto.string2().set( "/Foo/bar" );
-        proto.number().set( 42L );
-        proto.date().set( new Date() );
-        // We specify the TimeZone explicitely here so that serialized/deserialized is equals
-        // See https://github.com/JodaOrg/joda-time/issues/106
-        proto.dateTime().set( new DateTime( "2020-03-04T13:24:35", DateTimeZone.forOffsetHours( 1 ) ) );
-        proto.localDate().set( new LocalDate() );
-        proto.localDateTime().set( new LocalDateTime() );
-        proto.entityReference().set( EntityReference.parseEntityReference( "12345" ) );
-        proto.stringIntMap().get().put( "foo", 42 );
-
-        // Can't put more than one entry in Map because this test rely on the fact that the underlying implementations
-        // maintain a certain order but it's not the case on some JVMs. On OpenJDK 8 they are reversed for example.
-        // This should not be enforced tough as both the Map API and the JSON specification state that name-value pairs
-        // are unordered.
-        // As a consequence this test should be enhanced to be Map order independant.
-        //
-        // proto.stringIntMap().get().put( "bar", 67 );
-
-        proto.stringValueMap().get().put( "foo", anotherValue1 );
-        proto.another().set( anotherValue1 );
-        // proto.arrayOfValues().set( new AnotherValue[] { anotherValue1, anotherValue2, anotherValue3 } );
-        proto.serializable().set( new SerializableObject() );
-        proto.foo().set( module.newValue( FooValue.class ) );
-        proto.fooValue().set( module.newValue( FooValue.class ) );
-        proto.customFoo().set( module.newValue( CustomFooValue.class ) );
-        proto.customFooValue().set( module.newValue( CustomFooValue.class ) );
-
-        // Arrays
-        // TODO FIXME Disabled as ValueComposite equality fails here
-        //proto.primitiveByteArray().set( new byte[]
-        //    {
-        //        9, -12, 42, -12, 127, 23, -128, 73
-        //    } );
-        //proto.byteArray().set( new Byte[]
-        //    {
-        //        9, null, -12, 23, -12, 127, -128, 73
-        //    } );
-
-        // NestedEntities
-        proto.barAssociation().set( buildBarEntity( "bazar in barAssociation" ) );
-        proto.barEntityAssociation().set( buildBarEntity( "bazar in barEntityAssociation" ) );
-        proto.barManyAssociation().add( buildBarEntity( "bazar ONE in barManyAssociation" ) );
-        proto.barManyAssociation().add( buildBarEntity( "bazar TWO in barManyAssociation" ) );
-        proto.barEntityManyAssociation().add( buildBarEntity( "bazar ONE in barEntityManyAssociation" ) );
-        proto.barEntityManyAssociation().add( buildBarEntity( "bazar TWO in barEntityManyAssociation" ) );
-        proto.barNamedAssociation().put( "bazar", buildBarEntity( "bazar in barNamedAssociation" ) );
-        proto.barNamedAssociation().put( "cathedral", buildBarEntity( "cathedral in barNamedAssociation" ) );
-        proto.barEntityNamedAssociation().put( "bazar", buildBarEntity( "bazar in barEntityNamedAssociation" ) );
-        proto.barEntityNamedAssociation().put( "cathedral", buildBarEntity( "cathedral in barEntityNamedAssociation" ) );
-
-        return builder.newInstance();
-    }
-
-    private AnotherValue createAnotherValue( String val1, String val2 )
-    {
-        ValueBuilder<AnotherValue> valueBuilder = module.newValueBuilder( AnotherValue.class );
-        valueBuilder.prototype().val1().set( val1 );
-        valueBuilder.prototypeFor( AnotherValueInternalState.class ).val2().set( val2 );
-        return valueBuilder.newInstance();
-    }
-
-    private BarEntity buildBarEntity( String cathedral )
-    {
-        EntityBuilder<BarEntity> barBuilder = module.currentUnitOfWork().newEntityBuilder( BarEntity.class );
-        barBuilder.instance().cathedral().set( cathedral );
-        return barBuilder.newInstance();
-    }
-
-    public enum TestEnum
-    {
-        somevalue, anothervalue
-    }
-
-    public interface SomeValue
-        extends ValueComposite
-    {
-        Property<String> string();
-
-        Property<String> string2();
-
-        @Optional
-        Property<String> nullString();
-
-        @UseDefaults
-        Property<String> emptyString();
-
-        @UseDefaults
-        Property<Long> number();
-
-        Property<Date> date();
-
-        Property<DateTime> dateTime();
-
-        Property<LocalDate> localDate();
-
-        Property<LocalDateTime> localDateTime();
-
-        Property<EntityReference> entityReference();
-
-        @UseDefaults
-        Property<List<String>> stringList();
-
-        @UseDefaults
-        Property<Map<String, Integer>> stringIntMap();
-
-        @UseDefaults
-        Property<Map<String, AnotherValue>> stringValueMap();
-
-        Property<AnotherValue> another();
-
-        // Property<AnotherValue[]> arrayOfValues();
-
-        @Optional
-        Property<AnotherValue> anotherNull();
-
-        @UseDefaults
-        Property<List<AnotherValue>> anotherList();
-
-        @Optional
-        Property<List<AnotherValue>> anotherListNull();
-
-        @UseDefaults
-        Property<List<AnotherValue>> anotherListEmpty();
-
-        @UseDefaults
-        Property<TestEnum> testEnum();
-
-        // TODO FIXME Disabled as ValueComposite equality fails here
-        //Property<byte[]> primitiveByteArray();
-        //
-        //@Optional
-        //Property<byte[]> primitiveByteArrayNull();
-        //
-        //Property<Byte[]> byteArray();
-        //
-        //@Optional
-        //Property<Byte[]> byteArrayNull();
-
-        Property<Object> serializable();
-
-        Property<Foo> foo();
-
-        Property<FooValue> fooValue();
-
-        Property<Foo> customFoo();
-
-        Property<FooValue> customFooValue();
-
-        Property<SpecificCollection> specificCollection();
-
-        /* Too complicated to do generics here for now
-         Property<SpecificValue> specificValue();
-         */
-        @Optional
-        Association<Bar> barAssociationOptional();
-
-        Association<Bar> barAssociation();
-
-        Association<BarEntity> barEntityAssociation();
-
-        ManyAssociation<Bar> barManyAssociationEmpty();
-
-        ManyAssociation<Bar> barManyAssociation();
-
-        ManyAssociation<BarEntity> barEntityManyAssociation();
-
-        NamedAssociation<Bar> barNamedAssociationEmpty();
-
-        NamedAssociation<Bar> barNamedAssociation();
-
-        NamedAssociation<BarEntity> barEntityNamedAssociation();
-    }
-
-    public interface SpecificCollection
-        extends GenericCollection<String>
-    {
-    }
-
-    public interface GenericCollection<TYPE>
-        extends ValueComposite
-    {
-        @UseDefaults
-        Property<List<TYPE>> genericList();
-    }
-
-    public interface SpecificValue
-        extends GenericValue<String>
-    {
-    }
-
-    public interface GenericValue<TYPE>
-        extends ValueComposite
-    {
-        @Optional
-        Property<TYPE> item();
-    }
-
-    @Mixins( AnotherValueMixin.class )
-    public interface AnotherValue
-        extends ValueComposite
-    {
-        @UseDefaults
-        Property<String> val1();
-
-        String internalVal();
-    }
-
-    public interface AnotherValueInternalState
-    {
-        @UseDefaults
-        Property<String> val2();
-    }
-
-    public static abstract class AnotherValueMixin
-        implements AnotherValue
-    {
-        @This
-        private AnotherValueInternalState internalState;
-
-        @Override
-        public String internalVal()
-        {
-            return internalState.val2().get();
-        }
-    }
-
-    public interface Foo
-    {
-        @UseDefaults
-        Property<String> bar();
-    }
-
-    public interface FooValue
-        extends Foo, ValueComposite
-    {
-    }
-
-    public interface CustomFooValue
-        extends FooValue
-    {
-        @UseDefaults
-        Property<String> custom();
-    }
-
-    public interface Bar
-    {
-        @UseDefaults
-        Property<String> cathedral();
-    }
-
-    public interface BarEntity
-        extends Bar, EntityComposite
-    {
-    }
-
-    public static class SerializableObject
-        implements Serializable
-    {
-        private static final long serialVersionUID = 1L;
-        private final String foo = "Foo";
-        private final int val = 35;
-
-        @Override
-        public boolean equals( Object o )
-        {
-            if( this == o )
-            {
-                return true;
-            }
-            if( o == null || getClass() != o.getClass() )
-            {
-                return false;
-            }
-            SerializableObject that = (SerializableObject) o;
-            return val == that.val && foo.equals( that.foo );
-        }
-
-        @Override
-        public int hashCode()
-        {
-            int result = foo.hashCode();
-            result = 31 * result + val;
-            return result;
-        }
-    }
-}
diff --git a/core/testsupport/src/main/java/org/qi4j/test/value/package.html b/core/testsupport/src/main/java/org/qi4j/test/value/package.html
deleted file mode 100644
index a82e564..0000000
--- a/core/testsupport/src/main/java/org/qi4j/test/value/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ValueSerialization SPI Test Support.</h2>
-    </body>
-</html>
diff --git a/core/testsupport/src/test/java/org/apache/polygene/test/cache/MemoryCacheTest.java b/core/testsupport/src/test/java/org/apache/polygene/test/cache/MemoryCacheTest.java
new file mode 100644
index 0000000..c9e2fe1
--- /dev/null
+++ b/core/testsupport/src/test/java/org/apache/polygene/test/cache/MemoryCacheTest.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.test.cache;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+public class MemoryCacheTest
+    extends AbstractCachePoolTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( MemoryCachePoolService.class );
+    }
+}
diff --git a/core/testsupport/src/test/java/org/apache/polygene/test/cache/RetryRuleTest.java b/core/testsupport/src/test/java/org/apache/polygene/test/cache/RetryRuleTest.java
new file mode 100644
index 0000000..019b5e9
--- /dev/null
+++ b/core/testsupport/src/test/java/org/apache/polygene/test/cache/RetryRuleTest.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.test.cache;
+
+import org.apache.polygene.test.util.RetryRule;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class RetryRuleTest
+{
+    @Rule public RetryRule retry = new RetryRule( 3 );
+
+    static int count = 0;
+
+    @Test
+    public void test()
+    {
+        count++;
+        assertThat( count, is( 3 ) );
+    }
+}
diff --git a/core/testsupport/src/test/java/org/qi4j/test/cache/MemoryCacheTest.java b/core/testsupport/src/test/java/org/qi4j/test/cache/MemoryCacheTest.java
deleted file mode 100644
index 1bbd6cf..0000000
--- a/core/testsupport/src/test/java/org/qi4j/test/cache/MemoryCacheTest.java
+++ /dev/null
@@ -1,32 +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.qi4j.test.cache;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.cache.AbstractCachePoolTest;
-
-public class MemoryCacheTest
-    extends AbstractCachePoolTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( MemoryCachePoolService.class );
-    }
-}
diff --git a/dependencies.gradle b/dependencies.gradle
new file mode 100644
index 0000000..3bab48f
--- /dev/null
+++ b/dependencies.gradle
@@ -0,0 +1,278 @@
+/*
+ *  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.
+ */
+import org.apache.polygene.gradle.dependencies.DependenciesDeclarationExtension
+
+def dependencies = extensions.getByType( DependenciesDeclarationExtension )
+
+// Remote repositories
+dependencies.repositoriesUrls << [
+  mavenCentral: "https://repo1.maven.org/maven2/",
+  restlet     : 'https://maven.restlet.com/',
+  clojars     : "https://clojars.org/repo/",
+]
+
+// Core dependencies
+def asmVersion = '5.2'
+def javaxJsonVersion = '1.0'
+def osgiVersion = '4.3.1'
+dependencies.libraries << [
+  asm        : "org.ow2.asm:asm:$asmVersion",
+  asm_commons: "org.ow2.asm:asm-commons:$asmVersion",
+  asm_util   : "org.ow2.asm:asm-util:$asmVersion",
+  javax_json : "javax.json:javax.json-api:$javaxJsonVersion",
+  osgi_core  : "org.osgi:org.osgi.core:$osgiVersion",
+]
+
+// Extensions, Libraries and Tools dependencies
+def bonecpVersion = '0.8.0.RELEASE'
+def bouncyVersion = '1.56'
+def cassandraClientVersion = '3.2.0'
+def codahaleMetricsVersion = '3.2.2'
+def commonsDbcpVersion = '2.1.1'
+def commonsLangVersion = '3.5'
+def derbyVersion = '10.13.1.1'
+def ehcacheVersion = '3.3.1'
+def elasticsearchVersion = '5.2.2'
+def freemarkerVersion = '2.3.26-incubating'
+def geodeVersion = '1.1.1'
+def groovyVersion = '2.4.10'
+def hazelcastVersion = '3.8'
+def httpClientVersion = '4.5.3'
+def jacksonVersion = '2.8.7'
+def jaxbApiVersion = '2.2.12'
+def jcloudsVersion = '2.0.1'
+def jdbmVersion = '2.4'
+def jedisVersion = '2.9.0'
+def jettyVersion = '9.2.17.v20160517' // 9.3.x Tests fail!
+def johnzonVersion = '1.0.0'
+def jooqVersion = '3.9.1'
+def leveldbVersion = '0.9'
+def leveldbJniVersion = '1.8'
+def liquibaseVersion = '3.5.3'
+def mongodbVersion = '3.4.2'
+def msgpackVersion = '0.8.12'
+def restletVersion = '2.3.9'
+def rdfVersion = '2.7.16' // 2.8.x change query results!! 4.x exists
+def riakVersion = '2.1.1'
+def servletVersion = '3.1.0'
+def shiroVersion = '1.3.2'
+def slf4jVersion = '1.7.25'
+def solrVersion = "1.4.1" // 4.x Fails to compile!
+def springVersion = '4.3.7.RELEASE'
+def spymemcachedVersion = '2.12.2'
+def velocityVersion = '1.7'
+dependencies.libraries << [
+  bonecp              : "com.jolbox:bonecp:$bonecpVersion",
+  bouncy_castle       : "org.bouncycastle:bcprov-jdk15on:$bouncyVersion",
+  cassandra_client    : "com.datastax.cassandra:cassandra-driver-core:$cassandraClientVersion",
+  codahale_metrics    : [ "io.dropwizard.metrics:metrics-core:$codahaleMetricsVersion",
+                          "io.dropwizard.metrics:metrics-healthchecks:$codahaleMetricsVersion" ],
+  commons_dbcp        : "org.apache.commons:commons-dbcp2:$commonsDbcpVersion",
+  commons_lang        : "org.apache.commons:commons-lang3:$commonsLangVersion",
+  ehcache             : "org.ehcache:ehcache:$ehcacheVersion",
+  elasticsearch       : [ "org.elasticsearch:elasticsearch:$elasticsearchVersion",
+                          "org.elasticsearch.client:transport:$elasticsearchVersion",
+                          // Elasticsearch 5.0 do not work with log4j 2.7
+                          "org.apache.logging.log4j:log4j-api:2.6.2",
+                          "org.apache.logging.log4j:log4j-core:2.6.2" ],
+  freemarker          : "org.freemarker:freemarker:$freemarkerVersion",
+  geode               : "org.apache.geode:geode-core:$geodeVersion",
+  groovy              : "org.codehaus.groovy:groovy-all:$groovyVersion",
+  hazelcast           : "com.hazelcast:hazelcast:$hazelcastVersion",
+  http_client         : "org.apache.httpcomponents:httpclient:$httpClientVersion",
+  jackson_mapper      : "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion",
+  jaxb_api            : "javax.xml.bind:jaxb-api:$jaxbApiVersion",
+  jclouds_core        : "org.apache.jclouds:jclouds-core:$jcloudsVersion",
+  jclouds_blobstore   : "org.apache.jclouds:jclouds-allblobstore:$jcloudsVersion",
+  jclouds_filesystem  : "org.apache.jclouds.api:filesystem:$jcloudsVersion",
+  jetty_server        : "org.eclipse.jetty:jetty-server:$jettyVersion",
+  jetty_webapp        : "org.eclipse.jetty:jetty-webapp:$jettyVersion",
+  jetty_servlet       : "org.eclipse.jetty:jetty-servlet:$jettyVersion",
+  jetty_http          : "org.eclipse.jetty:jetty-http:$jettyVersion",
+  jetty_io            : "org.eclipse.jetty:jetty-io:$jettyVersion",
+  jetty_jmx           : "org.eclipse.jetty:jetty-jmx:$jettyVersion",
+  jetty_security      : "org.eclipse.jetty:jetty-security:$jettyVersion",
+  jetty_jsp           : "org.eclipse.jetty:jetty-jsp:$jettyVersion",
+  jetty_util          : "org.eclipse.jetty:jetty-util:$jettyVersion",
+  jetty_continuation  : "org.eclipse.jetty:jetty-continuation:$jettyVersion",
+  jetty_client        : "org.eclipse.jetty:jetty-client:$jettyVersion",
+  jetty_xml           : "org.eclipse.jetty:jetty-xml:$jettyVersion",
+  johnzon             : "org.apache.johnzon:johnzon-core:$johnzonVersion",
+  jooq                : "org.jooq:jooq:$jooqVersion",
+  jdbm                : "jdbm:jdbm:$jdbmVersion",
+  jedis               : "redis.clients:jedis:$jedisVersion",
+  leveldb_api         : "org.iq80.leveldb:leveldb-api:$leveldbVersion",
+  leveldb_java        : "org.iq80.leveldb:leveldb:$leveldbVersion",
+  leveldb_jni_all     : "org.fusesource.leveldbjni:leveldbjni-all:$leveldbJniVersion",
+  liquibase           : "org.liquibase:liquibase-core:$liquibaseVersion",
+  mongodb             : "org.mongodb:mongo-java-driver:$mongodbVersion",
+  msgpack             : "org.msgpack:msgpack-core:$msgpackVersion",
+  osgi_compendium     : "org.osgi:org.osgi.compendium:$osgiVersion",
+  osgi_enterprise     : "org.osgi:org.osgi.enterprise:$osgiVersion",
+  restlet             : [ "org.restlet.jee:org.restlet:$restletVersion",
+                          "org.restlet.jee:org.restlet.ext.atom:$restletVersion",
+                          "org.restlet.jee:org.restlet.ext.servlet:$restletVersion",
+                          "org.restlet.jee:org.restlet.ext.slf4j:$restletVersion" ],
+  restlet_xml         : "org.restlet.jee:org.restlet.ext.xml:$restletVersion",
+  riak                : "com.basho.riak:riak-client:$riakVersion",
+  servlet_api         : "javax.servlet:javax.servlet-api:$servletVersion",
+  sesame              : [ "org.openrdf.sesame:sesame-model:$rdfVersion",
+                          "org.openrdf.sesame:sesame-queryparser-sparql:$rdfVersion",
+                          "org.openrdf.sesame:sesame-repository-dataset:$rdfVersion",
+                          "org.openrdf.sesame:sesame-repository-http:$rdfVersion",
+                          "org.openrdf.sesame:sesame-rio-api:$rdfVersion",
+                          "org.openrdf.sesame:sesame-rio-n3:$rdfVersion",
+                          "org.openrdf.sesame:sesame-rio-ntriples:$rdfVersion",
+                          "org.openrdf.sesame:sesame-rio-rdfxml:$rdfVersion",
+                          "org.openrdf.sesame:sesame-rio-trig:$rdfVersion",
+                          "org.openrdf.sesame:sesame-rio-trix:$rdfVersion",
+                          "org.openrdf.sesame:sesame-rio-turtle:$rdfVersion",
+                          "org.openrdf.sesame:sesame-sail-api:$rdfVersion",
+                          "org.openrdf.sesame:sesame-sail-memory:$rdfVersion",
+                          "org.openrdf.sesame:sesame-sail-nativerdf:$rdfVersion",
+                          "org.openrdf.sesame:sesame-sail-rdbms:$rdfVersion" ],
+  shiro               : "org.apache.shiro:shiro-core:$shiroVersion",
+  shiro_web           : "org.apache.shiro:shiro-web:$shiroVersion",
+  slf4j_api           : "org.slf4j:slf4j-api:$slf4jVersion",
+  solr                : [ "org.apache.solr:solr-core:$solrVersion",
+                          "org.apache.solr:solr-solrj:$solrVersion" ],
+  sparql              : [ "org.openrdf.sesame:sesame-queryresultio-sparqlxml:$rdfVersion",
+                          "org.openrdf.sesame:sesame-queryresultio-sparqljson:$rdfVersion" ],
+  spring_core         : [ "org.springframework:spring-beans:$springVersion",
+                          "org.springframework:spring-context:$springVersion" ],
+  spymemcached        : "net.spy:spymemcached:$spymemcachedVersion",
+  velocity            : "org.apache.velocity:velocity:$velocityVersion",
+]
+
+// Tools dependencies
+def jgoodiesLooksVersion = '2.7.0'
+def pdfboxVersion = '2.0.4'
+def prefuseVersion = '1.0.1'
+dependencies.libraries << [
+  jgoodies_looks: "com.jgoodies:jgoodies-looks:$jgoodiesLooksVersion",
+  pdfbox        : "org.apache.pdfbox:pdfbox:$pdfboxVersion",
+  prefuse       : "de.sciss:prefuse-core:$prefuseVersion",
+]
+
+// Runtime, Test and Samples dependencies
+def awaitilityVersion = '2.0.0'
+def dnsJavaVersion = '2.1.8'
+def dockerJUnitVersion = '0.3'
+def easyMockVersion = '3.4'
+def embedMongoVersion = '1.50.5' // 2.0.0 exists
+def h2Version = '1.4.194'
+def hamcrestVersion = '1.3'
+def jaxRsApiVersion = '2.0.1'
+def junitVersion = '4.12'
+def logbackVersion = '1.2.2' // TODO Replace with Apache Log4j 2
+def mockitoVersion = '2.7.21'
+def mysqlVersion = '6.0.6'
+def postgresqlVersion = '42.0.0'
+def sqliteVersion = '3.16.1'
+def xmlUnitVersion = '2.3.0'
+dependencies.libraries << [
+  awaitility        : "org.awaitility:awaitility:$awaitilityVersion",
+  derby             : "org.apache.derby:derby:$derbyVersion",
+  dnsjava           : "dnsjava:dnsjava:$dnsJavaVersion",
+  docker_junit      : "com.github.tdomzal:junit-docker-rule:$dockerJUnitVersion",
+  easymock          : "org.easymock:easymock:$easyMockVersion",
+  embed_mongo       : "de.flapdoodle.embed:de.flapdoodle.embed.mongo:$embedMongoVersion",
+  h2                : "com.h2database:h2:$h2Version",
+  hamcrest          : [ "org.hamcrest:hamcrest-core:$hamcrestVersion",
+                        "org.hamcrest:hamcrest-library:$hamcrestVersion" ],
+  junit             : "junit:junit:$junitVersion",
+  logback           : "ch.qos.logback:logback-classic:$logbackVersion",
+  mockito           : "org.mockito:mockito-core:$mockitoVersion",
+  mysql_connector   : "mysql:mysql-connector-java:$mysqlVersion",
+  postgres          : "org.postgresql:postgresql:$postgresqlVersion",
+  spring_testsupport: "org.springframework:spring-test:$springVersion",
+  sqlite            : "org.xerial:sqlite-jdbc:$sqliteVersion",
+  xmlunit           : "org.xmlunit:xmlunit-matchers:$xmlUnitVersion",
+]
+
+// Default dependencies
+dependencies.defaultDependencies << [
+  testImplementation: [ dependencies.libraries.junit, dependencies.libraries.hamcrest ]
+]
+
+// Resolution rules
+dependencies.dependencySubstitutionSpec = { DependencySubstitution substitution, ModuleComponentSelector dep ->
+  // Always resolve ASM to the same version
+  if( dep.group == 'org.ow2.asm' )
+  {
+    substitution.useTarget group: dep.group, name: dep.module, version: asmVersion
+  }
+  // Always resolve OSGi to the same version
+  else if( dep.group == 'org.osgi' )
+  {
+    substitution.useTarget group: dep.group, name: dep.module, version: osgiVersion
+  }
+  // Always resolve SLF4J to the same version
+  else if( dep.group == 'org.slf4j' )
+  {
+    substitution.useTarget group: dep.group, name: dep.module, version: slf4jVersion
+  }
+  // Always resolve Jackson to the same version
+  else if( dep.group.startsWith( 'com.fasterxml.jackson' ) && dep.module != 'jackson-parent' )
+  {
+    substitution.useTarget group: dep.group, name: dep.module, version: jacksonVersion
+  }
+  // Always resolve JAX-RS API to the same version
+  else if( [ 'jaxrs-api', 'jsr311-api', 'javax.ws.rs-api' ].contains( dep.module ) )
+  {
+    substitution.useTarget group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: jaxRsApiVersion
+  }
+  // woodstox:wstx-asl is broken (no pom), use org.codehaus.woodstox:wstx-asl instead
+  else if( dep.group == 'woodstox' && dep.module == 'wstx-asl' )
+  {
+    substitution.useTarget group: 'org.codehaus.woodstox', name: 'wstx-asl', version: dep.version
+  }
+  // some bad citizens have SNAPSHOT parents ...
+  else if( dep.module == 'commons-sandbox-parent' && dep.version == '3-SNAPSHOT' )
+  {
+    substitution.useTarget group: dep.group, name: dep.module, version: '3'
+  }
+  // Findbugs Annotation is LGPL, use https://github.com/stephenc/findbugs-annotations which is
+  // Apache 2 licensed instead
+  else if( dep.group == 'net.sourceforge.findbugs' && dep.module == 'annotations' )
+  {
+    substitution.useTarget group: 'com.github.stephenc.findbugs', name: 'findbugs-annotations', version: '1.3.9-1'
+  }
+}
+
+// NodeJS
+dependencies.nodeVersions << [
+    node: '6.10.2',
+    npm: '4.4.4'
+]
+
+// Build Tools
+dependencies.buildToolsVersions << [
+  jacoco: '0.7.9'
+]
+
+// Docker Images
+dependencies.dockerImagesVersions << [
+  cassandra: 'cassandra:3.10',
+  memcached: 'memcached:1.4.36-alpine',
+  mariadb  : 'mariadb:10.1.21',
+  postgres : 'postgres:9.6.2-alpine',
+  redis    : 'redis:3.2.8-alpine',
+  riak     : 'basho/riak-kv:ubuntu-2.2.3',
+  s3server : 'scality/s3server:mem-6a8e1cd'
+]
diff --git a/distributions/build.gradle b/distributions/build.gradle
new file mode 100644
index 0000000..e2ef55c
--- /dev/null
+++ b/distributions/build.gradle
@@ -0,0 +1,19 @@
+/*
+ *  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.
+ */
+
+apply plugin: 'polygene-distributions'
diff --git a/distributions/src/bin-dist/NOTICE.txt b/distributions/src/bin-dist/NOTICE.txt
new file mode 100644
index 0000000..998fdf8
--- /dev/null
+++ b/distributions/src/bin-dist/NOTICE.txt
@@ -0,0 +1,5 @@
+Apache Polygene™ (Java Edition) SDK Binary Distribution
+Copyright 2015 The Apache Software Foundation.
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/distributions/src/bin-dist/README.txt b/distributions/src/bin-dist/README.txt
new file mode 100644
index 0000000..9d69361
--- /dev/null
+++ b/distributions/src/bin-dist/README.txt
@@ -0,0 +1,49 @@
+
+Welcome to the world of Apache Polygene
+   - Composite Oriented Programming on the Java platform.
+
+
+This Apache Polygene™ Binary Distribution contains everything you need to
+create Polygene™ applications.
+
+
+Polygene™ (then Polygene™) started in 2007, and is still in heavy development
+at the Apache Software Foundation. We would like
+developers around the world to participate in the advancement of this
+cool, new and challenging technology. We are especially interested in
+people willing to help improve the SDK, samples, tutorials, documentation
+and other supporting material.
+
+Please see https://polygene.apache.org for more information.
+
+
+Licensing
+---------
+All Polygene™ code is licensed subject to the Apache License.
+
+Third-Party Dependencies may be licensed under other terms. The only
+required dependencies are SLF4J (MIT Licence) and ASM (BSD Licence)
+
+Finally, Polygene™ TestSupport depends on JUnit 4.x and its dependencies, which
+is also not included in the SDK itself, as it is present among most Java
+developers.
+
+
+Dependencies not included
+-------------------------
+The binary distributions contains Polygene™ artifacts only to keep the download
+size small. Each Polygene™ artifact comes with a file prefixed ..-runtime-deps.txt
+that contains the list of its dependencies. Moreover, at the binary
+distribution's root, you'll find both Maven (go-offline.pom) and Gradle
+(go-offline.gradle) build files whoses sole purpose is to easily download all
+needed dependencies jars. Instructions are given into theses files.
+
+If you prefer to use a dependency management system, go to:
+https://polygene.apache.org/java/latest/howto-depend-on-polygene.html
+
+
+Thank you for trying out Apache Polygene™ and Composite Oriented Programming.
+
+
+-- Apache Polygene™ Team
+
diff --git a/distributions/src/src-dist/README.txt b/distributions/src/src-dist/README.txt
new file mode 100644
index 0000000..de6c218
--- /dev/null
+++ b/distributions/src/src-dist/README.txt
@@ -0,0 +1,71 @@
+
+Welcome to the world of Apache Polygene
+   - Composite Oriented Programming on the Java platform.
+
+
+This Apache Polygene™ Source Distribution contains everything you need to
+create Polygene™ applications.
+
+
+Polygene™ started in 2007, and is still in heavy development under the umbrella of
+the Apache Polygene™ project at the Apache Software Foundation. We would like
+developers around the world to participate in the advancement of this
+cool, new and challenging technology. We are especially interested in
+people willing to help improve the SDK, samples, tutorials, documentation
+and other supporting material.
+
+Please see https://polygene.apache.org for more information.
+
+
+Licensing
+---------
+All Polygene™ code is licensed subject to the Apache License.
+
+Third-Party Dependencies may be licensed under other terms. The only
+required dependencies are SLF4J (MIT Licence) and ASM (BSD Licence).
+
+Finally, Polygene™ TestSupport depends on JUnit 4.x and its dependencies, which
+is also not included in the SDK itself, as it is present among most Java
+developers.
+
+
+Dependencies not included
+-------------------------
+The source distribution contains Polygene™ sources only to keep the download
+size small. The Gradle build automatically downloads needed dependencies.
+If you need to go offline type `./gradlew goOffline` to ensure all needed
+dependencies are cached by Gradle.
+
+If you prefer to use a dependency management system, go to:
+https://polygene.apache.org/java/latest/howto-depend-on-polygene.html
+
+
+Building Apache Polygene
+---------------------
+To build Polygene™ from sources you only need to have a valid Java JDK >= 8
+installation and any version of Gradle.
+
+This distribution embeds the exact version of Gradle needed to build Polygene™.
+It is in the gradle/wrapper/gradle-wrapper.properties file.
+Here is how to bootstrap that version:
+
+    gradle wrapper
+
+This will download the required Gradle distribution and create gradlew and
+gradlew.bat script files that you should use from now on.
+
+Once you have the wrapper installed you can invoke the build system.
+
+Here is how to run a full build with checks:
+
+    ./gradlew check assemble
+
+Read the Polygene™ Build System tutorial for more details:
+https://polygene.apache.org/java/latest/build-system.html
+
+
+Thank you for trying out Apache Polygene™ and Composite Oriented Programming.
+
+
+-- Apache Polygene™ Team
+
diff --git a/doap.rdf b/doap.rdf
index bb13fa0..6ffbfa0 100644
--- a/doap.rdf
+++ b/doap.rdf
@@ -29,17 +29,17 @@
 
   =======================================================================
 -->
-  <Project rdf:about="http://zest.apache.org/">
+  <Project rdf:about="http://polygene.apache.org/">
     <created>2008-12-17</created>
     <license rdf:resource="http://usefulinc.com/doap/licenses/asl20" />
-    <name>Apache Zest</name>
-    <homepage rdf:resource="https://zest.apache.org/" />
-    <asfext:pmc rdf:resource="https://zest.apache.org" />
-    <shortdesc>Apache Zest is a community based effort exploring Composite Oriented Programming for domain centric application development.</shortdesc>
-    <description>Apache Zest is a community based effort exploring Composite Oriented Programming for domain centric application development. This includes evolved concepts from Aspect Oriented Programming, Dependency Injection and Domain Driven Design. Composite Oriented Programming allows developers to work with 'fragments', smaller than classes, and 'compose' fragments into larger 'composites' which acts like the regular objects. Zest also tackles the enforcement of application composition, i.e. composites are declared in modules, modules are contained in layers and access between layers are controlled/enforced. Apache Zest™ (Java Edition), first Apache Zest sub-project, is an implementation of Composite Oriented Programming, using the standard Java platform, without the use of any pre-processors or new language elements. Everything you know from Java still applies and you can leverage both your experience and toolkits to become more productive with Composite Oriented Programming today.</description>    
-    <bug-database rdf:resource="https://issues.apache.org/jira/browse/ZEST" />
+    <name>Apache Polygene</name>
+    <homepage rdf:resource="https://polygene.apache.org/" />
+    <asfext:pmc rdf:resource="https://polygene.apache.org" />
+    <shortdesc>Apache Polygene is a community based effort exploring Composite Oriented Programming for domain centric application development.</shortdesc>
+    <description>Apache Polygene is a community based effort exploring Composite Oriented Programming for domain centric application development. This includes evolved concepts from Aspect Oriented Programming, Dependency Injection and Domain Driven Design. Composite Oriented Programming allows developers to work with 'fragments', smaller than classes, and 'compose' fragments into larger 'composites' which acts like the regular objects. Polygene also tackles the enforcement of application composition, i.e. composites are declared in modules, modules are contained in layers and access between layers are controlled/enforced. Apache Polygene™ (Java Edition), first Apache Polygene sub-project, is an implementation of Composite Oriented Programming, using the standard Java platform, without the use of any pre-processors or new language elements. Everything you know from Java still applies and you can leverage both your experience and toolkits to become more productive with Composite Oriented Programming today.</description>
+    <bug-database rdf:resource="https://issues.apache.org/jira/browse/POLYGENE" />
     <mailing-list rdf:resource="https://www.apache.org/foundation/mailinglists.html" />
-    <download-page rdf:resource="https://zest.apache.org/download.html" />
+    <download-page rdf:resource="https://polygene.apache.org/download.html" />
     <programming-language>Java</programming-language>
     <programming-language>C#</programming-language>
     <programming-language>Scala</programming-language>
@@ -48,14 +48,14 @@
     <category rdf:resource="http://projects.apache.org/category/library" />
     <repository>
       <SVNRepository>
-        <location rdf:resource="http://svn.apache.org/repos/asf/zest/"/>
-        <browse rdf:resource="http://svn.apache.org/viewcvs.cgi/zest/"/>
+        <location rdf:resource="http://svn.apache.org/repos/asf/polygene/"/>
+        <browse rdf:resource="http://svn.apache.org/viewcvs.cgi/polygene/"/>
       </SVNRepository>
     </repository>
     <repository>
       <GitRepository>
-        <location rdf:resource="https://git-wip-us.apache.org/repos/asf/zest-java.git"/>
-        <browse rdf:resource="https://github.com/apache/zest-java"/>
+        <location rdf:resource="https://git-wip-us.apache.org/repos/asf/polygene-java.git"/>
+        <browse rdf:resource="https://github.com/apache/polygene-java"/>
       </GitRepository>
     </repository>
     <maintainer>
diff --git a/etc/apache-rat-output-to-html.xsl b/etc/apache-rat-output-to-html.xsl
index dcf19c5..039dc80 100644
--- a/etc/apache-rat-output-to-html.xsl
+++ b/etc/apache-rat-output-to-html.xsl
@@ -1,3 +1,23 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
 
 <!--***********************************************************
diff --git a/etc/polygene-api-checkstyle.xml b/etc/polygene-api-checkstyle.xml
new file mode 100644
index 0000000..4db3ae8
--- /dev/null
+++ b/etc/polygene-api-checkstyle.xml
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
+<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
+  "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
+
+<!-- Documentation is availableService at
+     http://checkstyle.sourceforge.net/availablechecks.html
+-->
+<module name="Checker">
+  <property name="severity" value="warning"/>
+  <module name="NewlineAtEndOfFile"/>
+  <module name="Translation"/>
+  <module name="JavadocPackage"/>
+  <module name="TreeWalker">
+    <module name="MutableException"/>
+
+    <module name="CyclomaticComplexity">
+      <property name="max" value="7"/>
+    </module>
+    <module name="Indentation"/>
+    <module name="CovariantEquals"/>
+    <module name="FileContentsHolder"/>
+    <module name="ArrayTypeStyle"/>
+    <!-- 2005-Oct-05
+         final in method arguments is just ugly in my opinion,
+         communicates very little, and is not preventing much
+         problem. Remove it for now.
+    <module name="FinalParameters">
+        <property name="severity" value="ignore"/>
+        <property name="tokens" value="METHOD_DEF, CTOR_DEF"/>
+    </module>
+    -->
+
+    <!--
+        <module name="GenericIllegalRegexp">
+          <property name="severity" value="ignore"/>
+          <property name="format" value="\s+$"/>
+          <property name="message" value="Line has trailing spaces."/>
+        </module>
+    -->
+
+    <module name="ModifierOrder"/>
+    <module name="RedundantModifier">
+      <property name="severity" value="ignore"/>
+      <property name="tokens" value="METHOD_DEF, VARIABLE_DEF"/>
+    </module>
+
+    <module name="TodoComment"/>
+    <module name="UpperEll"/>
+    <module name="AvoidNestedBlocks"/>
+    <module name="EmptyBlock">
+      <property name="tokens"
+                value="LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_IF, LITERAL_FOR, LITERAL_TRY, LITERAL_WHILE, STATIC_INIT"/>
+    </module>
+    <module name="LeftCurly">
+      <property name="option" value="nl"/>
+      <property name="tokens"
+                value="CLASS_DEF, CTOR_DEF, INTERFACE_DEF, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF"/>
+
+    </module>
+    <module name="NeedBraces"/>
+    <module name="RightCurly">
+      <property name="option" value="alone"/>
+      <property name="tokens" value="LITERAL_CATCH, LITERAL_ELSE, LITERAL_TRY"/>
+    </module>
+    <module name="AvoidInlineConditionals"/>
+    <module name="DoubleCheckedLocking"/>
+    <module name="EmptyStatement"/>
+
+    <module name="EqualsHashCode"/>
+    <!--<module name="HiddenField"/>-->
+    <module name="IllegalInstantiation"/>
+    <module name="InnerAssignment"/>
+    <module name="MagicNumber">
+      <property name="tokens" value="NUM_DOUBLE, NUM_FLOAT"/>
+      <property name="ignoreNumbers" value="-1, 0, 1, 2, 10, 50, 60, 100, 1000, 3600"/>
+    </module>
+    <module name="MissingSwitchDefault"/>
+
+    <!--
+         Niclas 2005-09-16:
+         This check seems somewhat broken, since
+         a = b == false;
+         is more readable in my view than
+         a = !b
+         but the former will trigger this rule. Therefor I disable it.
+         <module name="SimplifyBooleanExpression">
+         </module>
+    -->
+    <module name="SimplifyBooleanReturn"/>
+    <module name="StringLiteralEquality"/>
+    <module name="NestedIfDepth">
+      <property name="max" value="3"/>
+    </module>
+    <module name="NestedTryDepth">
+      <property name="max" value="2"/>
+    </module>
+
+    <module name="SuperClone"/>
+    <module name="SuperFinalize"/>
+    <module name="IllegalCatch">
+      <property name="illegalClassNames" value="java.lang.Exception, java.lang.Throwable, java.lang.Error"/>
+    </module>
+    <module name="IllegalThrows">
+      <property name="illegalClassNames"
+                value="java.lang.Exception, java.lang.Throwable, java.lang.RuntimeException, java.lang.Error"/>
+    </module>
+    <module name="PackageDeclaration"/>
+
+    <module name="JUnitTestCase"/>
+    <module name="DeclarationOrder"/>
+    <module name="ParameterAssignment"/>
+    <!--<module name="MissingCtor"/>-->
+    <module name="MultipleVariableDeclarations"/>
+    <module name="DesignForExtension">
+      <property name="severity" value="ignore"/>
+    </module>
+    <module name="FinalClass"/>
+
+    <module name="HideUtilityClassConstructor"/>
+    <module name="VisibilityModifier"/>
+    <module name="AvoidStarImport"/>
+    <module name="IllegalImport"/>
+    <module name="RedundantImport"/>
+    <module name="UnusedImports"/>
+    <module name="ImportOrder">
+      <property name="groups" value=""/>
+      <property name="ordered" value="true"/>
+      <property name="option" value="under"/>
+      <property name="separated" value="true"/>
+      <property name="caseSensitive" value="true"/>
+    </module>
+
+    <!--TODO Removing this until Javadoc effort has picked up -->
+    <!--<module name="JavadocMethod"/>-->
+    <!--<module name="JavadocType"/>-->
+    <!--<module name="JavadocVariable">-->
+      <!--<property name="scope" value="package"/>-->
+    <!--</module>-->
+    <module name="ConstantName">
+      <property name="format" value="^[A-Z0-9_$]*$"/>
+    </module>
+    <module name="LocalFinalVariableName"/>
+    <module name="LocalVariableName"/>
+    <module name="MemberName">
+      <property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
+    </module>
+    <module name="MethodName"/>
+    <module name="PackageName"/>
+
+    <module name="ParameterName"/>
+    <module name="StaticVariableName">
+      <property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
+    </module>
+    <module name="TypeName"/>
+    <module name="LineLength">
+
+      <property name="max" value="120"/>
+    </module>
+    <module name="MethodLength"/>
+    <module name="AnonInnerLength">
+      <property name="max" value="60"/>
+    </module>
+    <module name="ParameterNumber">
+      <property name="max" value="12"/>
+    </module>
+
+    <module name="EmptyForIteratorPad"/>
+    <module name="NoWhitespaceAfter">
+      <property name="tokens" value="BNOT,DEC,DOT,INC,UNARY_MINUS,UNARY_PLUS"/>
+    </module>
+    <!--<module name="OperatorWrap"/>-->
+    <module name="ParenPad">
+      <property name="option" value="space"/>
+      <property name="tokens" value="CTOR_CALL, LPAREN, METHOD_CALL, RPAREN, SUPER_CTOR_CALL"/>
+    </module>
+
+    <!--
+        <module name="TabCharacter"/>
+    -->
+
+    <module name="WhitespaceAfter"/>
+    <module name="WhitespaceAround">
+      <property name="tokens"
+                value="BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, EQUAL, GE, GT, LAND, LCURLY, LE, LITERAL_ASSERT, LITERAL_DO, LITERAL_RETURN, LITERAL_TRY, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR, SR_ASSIGN, STAR, STAR_ASSIGN"/>
+    </module>
+  </module>
+
+  <module name="FileLength">
+    <property name="max" value="1000"/>
+  </module>
+
+</module>
diff --git a/etc/polygene-runtime-checkstyle.xml b/etc/polygene-runtime-checkstyle.xml
new file mode 100644
index 0000000..8d4b9f7
--- /dev/null
+++ b/etc/polygene-runtime-checkstyle.xml
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
+<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
+  "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
+
+<!-- Documentation is availableService at
+     http://checkstyle.sourceforge.net/availablechecks.html
+-->
+<module name="Checker">
+  <property name="severity" value="warning"/>
+  <module name="NewlineAtEndOfFile"/>
+  <module name="Translation"/>
+  <!--TODO Removing this until Javadoc effort has picked up -->
+  <!--<module name="JavadocPackage"/>-->
+  <module name="TreeWalker">
+    <module name="MutableException"/>
+
+    <module name="CyclomaticComplexity">
+      <property name="max" value="7"/>
+    </module>
+    <module name="Indentation"/>
+    <module name="CovariantEquals"/>
+    <module name="FileContentsHolder"/>
+    <module name="ArrayTypeStyle"/>
+    <!-- 2005-Oct-05
+         final in method arguments is just ugly in my opinion,
+         communicates very little, and is not preventing much
+         problem. Remove it for now.
+    <module name="FinalParameters">
+        <property name="severity" value="ignore"/>
+        <property name="tokens" value="METHOD_DEF, CTOR_DEF"/>
+    </module>
+    -->
+
+    <!--
+        <module name="GenericIllegalRegexp">
+          <property name="severity" value="ignore"/>
+          <property name="format" value="\s+$"/>
+          <property name="message" value="Line has trailing spaces."/>
+        </module>
+    -->
+
+    <module name="ModifierOrder"/>
+    <module name="RedundantModifier">
+      <property name="severity" value="ignore"/>
+      <property name="tokens" value="METHOD_DEF, VARIABLE_DEF"/>
+    </module>
+
+    <module name="TodoComment"/>
+    <module name="UpperEll"/>
+    <module name="AvoidNestedBlocks"/>
+    <module name="EmptyBlock">
+      <property name="tokens"
+                value="LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_IF, LITERAL_FOR, LITERAL_TRY, LITERAL_WHILE, STATIC_INIT"/>
+    </module>
+    <module name="LeftCurly">
+      <property name="option" value="nl"/>
+      <property name="tokens"
+                value="CLASS_DEF, CTOR_DEF, INTERFACE_DEF, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF"/>
+
+    </module>
+    <module name="NeedBraces"/>
+    <module name="RightCurly">
+      <property name="option" value="alone"/>
+      <property name="tokens" value="LITERAL_CATCH, LITERAL_ELSE, LITERAL_TRY"/>
+    </module>
+    <module name="AvoidInlineConditionals"/>
+    <module name="DoubleCheckedLocking"/>
+    <module name="EmptyStatement"/>
+
+    <module name="EqualsHashCode"/>
+    <!--<module name="HiddenField"/>-->
+    <module name="IllegalInstantiation"/>
+    <module name="InnerAssignment"/>
+    <module name="MagicNumber">
+      <property name="tokens" value="NUM_DOUBLE, NUM_FLOAT"/>
+      <property name="ignoreNumbers" value="-1, 0, 1, 2, 10, 50, 60, 100, 1000, 3600"/>
+    </module>
+    <module name="MissingSwitchDefault"/>
+
+    <!--
+         Niclas 2005-09-16:
+         This check seems somewhat broken, since
+         a = b == false;
+         is more readable in my view than
+         a = !b
+         but the former will trigger this rule. Therefor I disable it.
+         <module name="SimplifyBooleanExpression">
+         </module>
+    -->
+    <module name="SimplifyBooleanReturn"/>
+    <module name="StringLiteralEquality"/>
+    <module name="NestedIfDepth">
+      <property name="max" value="3"/>
+    </module>
+    <module name="NestedTryDepth">
+      <property name="max" value="2"/>
+    </module>
+
+    <module name="SuperClone"/>
+    <module name="SuperFinalize"/>
+    <module name="IllegalCatch">
+      <property name="illegalClassNames" value="java.lang.Exception, java.lang.Throwable, java.lang.Error"/>
+    </module>
+    <module name="IllegalThrows">
+      <property name="illegalClassNames"
+                value="java.lang.Exception, java.lang.Throwable, java.lang.RuntimeException, java.lang.Error"/>
+    </module>
+    <module name="PackageDeclaration"/>
+
+    <module name="JUnitTestCase"/>
+    <module name="DeclarationOrder"/>
+    <module name="ParameterAssignment"/>
+    <!--<module name="MissingCtor"/>-->
+    <module name="MultipleVariableDeclarations"/>
+    <module name="DesignForExtension">
+      <property name="severity" value="ignore"/>
+    </module>
+    <module name="FinalClass"/>
+
+    <module name="HideUtilityClassConstructor"/>
+    <module name="VisibilityModifier"/>
+    <module name="AvoidStarImport"/>
+    <module name="IllegalImport"/>
+    <module name="RedundantImport"/>
+    <module name="UnusedImports"/>
+    <module name="ImportOrder">
+      <property name="groups" value=""/>
+      <property name="ordered" value="true"/>
+      <property name="option" value="under"/>
+      <property name="separated" value="true"/>
+      <property name="caseSensitive" value="true"/>
+    </module>
+    <!--TODO Removing this until Javadoc effort has picked up -->
+    <!--<module name="JavadocType"/>-->
+    <module name="ConstantName">
+      <property name="format" value="^[A-Z0-9_$]*$"/>
+    </module>
+    <module name="LocalFinalVariableName"/>
+    <module name="LocalVariableName"/>
+    <module name="MemberName">
+      <property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
+    </module>
+    <module name="MethodName"/>
+    <module name="PackageName"/>
+
+    <module name="ParameterName"/>
+    <module name="StaticVariableName">
+      <property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
+    </module>
+    <module name="TypeName"/>
+    <module name="LineLength">
+
+      <property name="max" value="120"/>
+    </module>
+    <module name="MethodLength"/>
+    <module name="AnonInnerLength">
+      <property name="max" value="60"/>
+    </module>
+    <module name="ParameterNumber">
+      <property name="max" value="12"/>
+    </module>
+
+    <module name="EmptyForIteratorPad"/>
+    <module name="NoWhitespaceAfter">
+      <property name="tokens" value="BNOT,DEC,DOT,INC,UNARY_MINUS,UNARY_PLUS"/>
+    </module>
+    <!--<module name="OperatorWrap"/>-->
+    <module name="ParenPad">
+      <property name="option" value="space"/>
+      <property name="tokens" value="CTOR_CALL, LPAREN, METHOD_CALL, RPAREN, SUPER_CTOR_CALL"/>
+    </module>
+
+    <!--
+        <module name="TabCharacter"/>
+    -->
+
+    <module name="WhitespaceAfter"/>
+    <module name="WhitespaceAround">
+      <property name="tokens"
+                value="BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, EQUAL, GE, GT, LAND, LCURLY, LE, LITERAL_ASSERT, LITERAL_DO, LITERAL_RETURN, LITERAL_TRY, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR, SR_ASSIGN, STAR, STAR_ASSIGN"/>
+    </module>
+  </module>
+
+  <module name="FileLength">
+    <property name="max" value="1000"/>
+  </module>
+
+</module>
diff --git a/etc/polygene-tests-checkstyle.xml b/etc/polygene-tests-checkstyle.xml
new file mode 100644
index 0000000..fc741ac
--- /dev/null
+++ b/etc/polygene-tests-checkstyle.xml
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
+<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
+  "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
+
+<!-- Documentation is availableService at
+     http://checkstyle.sourceforge.net/availablechecks.html
+-->
+<module name="Checker">
+  <property name="severity" value="warning"/>
+  <module name="NewlineAtEndOfFile"/>
+  <module name="Translation"/>
+  <module name="TreeWalker">
+    <module name="MutableException"/>
+
+    <module name="CyclomaticComplexity">
+      <property name="max" value="7"/>
+    </module>
+    <module name="Indentation"/>
+    <module name="CovariantEquals"/>
+    <module name="FileContentsHolder"/>
+    <module name="ArrayTypeStyle"/>
+    <!--
+        <module name="GenericIllegalRegexp">
+          <property name="severity" value="ignore"/>
+          <property name="format" value="\s+$"/>
+          <property name="message" value="Line has trailing spaces."/>
+        </module>
+    -->
+
+    <module name="ModifierOrder"/>
+    <module name="RedundantModifier">
+      <property name="severity" value="ignore"/>
+      <property name="tokens" value="METHOD_DEF, VARIABLE_DEF"/>
+    </module>
+
+    <module name="TodoComment"/>
+    <module name="UpperEll"/>
+    <module name="AvoidNestedBlocks"/>
+    <module name="EmptyBlock">
+      <property name="tokens"
+                value="LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_IF, LITERAL_FOR, LITERAL_TRY, LITERAL_WHILE, STATIC_INIT"/>
+    </module>
+    <module name="LeftCurly">
+      <property name="option" value="nl"/>
+      <property name="tokens"
+                value="CLASS_DEF, CTOR_DEF, INTERFACE_DEF, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF"/>
+
+    </module>
+    <module name="NeedBraces"/>
+    <module name="RightCurly">
+      <property name="option" value="alone"/>
+      <property name="tokens" value="LITERAL_CATCH, LITERAL_ELSE, LITERAL_TRY"/>
+    </module>
+    <module name="AvoidInlineConditionals"/>
+    <module name="DoubleCheckedLocking"/>
+    <module name="EmptyStatement"/>
+
+    <module name="EqualsHashCode"/>
+    <!--<module name="HiddenField"/>-->
+    <module name="IllegalInstantiation"/>
+    <module name="InnerAssignment"/>
+    <module name="MagicNumber">
+      <property name="tokens" value="NUM_DOUBLE, NUM_FLOAT"/>
+      <property name="ignoreNumbers" value="-1, 0, 1, 2, 10, 50, 60, 100, 1000, 3600"/>
+    </module>
+    <module name="MissingSwitchDefault"/>
+
+    <!--
+         Niclas 2005-09-16:
+         This check seems somewhat broken, since
+         a = b == false;
+         is more readable in my view than
+         a = !b
+         but the former will trigger this rule. Therefor I disable it.
+         <module name="SimplifyBooleanExpression">
+         </module>
+    -->
+    <module name="SimplifyBooleanReturn"/>
+    <module name="StringLiteralEquality"/>
+    <module name="NestedIfDepth">
+      <property name="max" value="3"/>
+    </module>
+    <module name="NestedTryDepth">
+      <property name="max" value="2"/>
+    </module>
+
+    <module name="SuperClone"/>
+    <module name="SuperFinalize"/>
+    <!-- Ok in tests...
+    <module name="IllegalCatch">
+      <property name="illegalClassNames" value="java.lang.Exception, java.lang.Throwable, java.lang.Error"/>
+    </module>
+    <module name="IllegalThrows">
+      <property name="illegalClassNames"
+                value="java.lang.Exception, java.lang.Throwable, java.lang.RuntimeException, java.lang.Error"/>
+    </module>
+    -->
+    <module name="PackageDeclaration"/>
+
+    <module name="JUnitTestCase"/>
+    <module name="DeclarationOrder"/>
+    <module name="ParameterAssignment"/>
+    <!--<module name="MissingCtor"/>-->
+    <module name="MultipleVariableDeclarations"/>
+    <module name="DesignForExtension">
+      <property name="severity" value="ignore"/>
+    </module>
+    <module name="FinalClass"/>
+
+    <module name="HideUtilityClassConstructor"/>
+    <module name="VisibilityModifier"/>
+    <module name="AvoidStarImport"/>
+    <module name="IllegalImport"/>
+    <module name="RedundantImport"/>
+    <module name="UnusedImports"/>
+    <module name="ImportOrder">
+      <property name="groups" value=""/>
+      <property name="ordered" value="true"/>
+      <property name="separated" value="false"/>
+      <property name="caseSensitive" value="true"/>
+      <property name="option" value="under"/>
+    </module>
+    <module name="ConstantName">
+      <property name="format" value="^[A-Z0-9_$]*$"/>
+    </module>
+    <module name="LocalFinalVariableName"/>
+    <module name="LocalVariableName"/>
+    <module name="MemberName">
+      <property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
+    </module>
+    <module name="MethodName"/>
+    <module name="PackageName"/>
+
+    <module name="ParameterName"/>
+    <module name="StaticVariableName">
+      <property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
+    </module>
+    <module name="TypeName"/>
+    <module name="LineLength">
+
+      <property name="max" value="120"/>
+    </module>
+    <module name="MethodLength"/>
+    <module name="AnonInnerLength">
+      <property name="max" value="60"/>
+    </module>
+    <module name="ParameterNumber">
+      <property name="max" value="12"/>
+    </module>
+
+    <module name="EmptyForIteratorPad"/>
+    <module name="NoWhitespaceAfter">
+      <property name="tokens" value="BNOT,DEC,DOT,INC,UNARY_MINUS,UNARY_PLUS"/>
+    </module>
+    <!--<module name="OperatorWrap"/>-->
+    <module name="ParenPad">
+      <property name="option" value="space"/>
+      <property name="tokens" value="CTOR_CALL, LPAREN, METHOD_CALL, RPAREN, SUPER_CTOR_CALL"/>
+    </module>
+
+    <!--
+        <module name="TabCharacter"/>
+    -->
+
+    <module name="WhitespaceAfter"/>
+    <module name="WhitespaceAround">
+      <property name="tokens"
+                value="BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, EQUAL, GE, GT, LAND, LCURLY, LE, LITERAL_ASSERT, LITERAL_DO, LITERAL_RETURN, LITERAL_TRY, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR, SR_ASSIGN, STAR, STAR_ASSIGN"/>
+    </module>
+  </module>
+
+  <module name="FileLength">
+    <property name="max" value="1000"/>
+  </module>
+
+</module>
diff --git a/etc/qi4j-api-checkstyle.xml b/etc/qi4j-api-checkstyle.xml
deleted file mode 100644
index d9c55c2..0000000
--- a/etc/qi4j-api-checkstyle.xml
+++ /dev/null
@@ -1,213 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
-  "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
-
-<!--***********************************************************
- *
- * 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.
- *
- ***********************************************************-->
-
-<!-- Documentation is availableService at
-     http://checkstyle.sourceforge.net/availablechecks.html
--->
-<module name="Checker">
-  <property name="severity" value="warning"/>
-  <module name="NewlineAtEndOfFile"/>
-  <module name="Translation"/>
-  <module name="JavadocPackage"/>
-  <module name="TreeWalker">
-    <module name="MutableException"/>
-
-    <module name="CyclomaticComplexity">
-      <property name="max" value="7"/>
-    </module>
-    <module name="Indentation"/>
-    <module name="CovariantEquals"/>
-    <module name="FileContentsHolder"/>
-    <module name="ArrayTypeStyle"/>
-    <!-- 2005-Oct-05
-         final in method arguments is just ugly in my opinion,
-         communicates very little, and is not preventing much
-         problem. Remove it for now.
-    <module name="FinalParameters">
-        <property name="severity" value="ignore"/>
-        <property name="tokens" value="METHOD_DEF, CTOR_DEF"/>
-    </module>
-    -->
-
-    <!--
-        <module name="GenericIllegalRegexp">
-          <property name="severity" value="ignore"/>
-          <property name="format" value="\s+$"/>
-          <property name="message" value="Line has trailing spaces."/>
-        </module>
-    -->
-
-    <module name="ModifierOrder"/>
-    <module name="RedundantModifier">
-      <property name="severity" value="ignore"/>
-      <property name="tokens" value="METHOD_DEF, VARIABLE_DEF"/>
-    </module>
-
-    <module name="TodoComment"/>
-    <module name="UpperEll"/>
-    <module name="AvoidNestedBlocks"/>
-    <module name="EmptyBlock">
-      <property name="tokens"
-                value="LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_IF, LITERAL_FOR, LITERAL_TRY, LITERAL_WHILE, STATIC_INIT"/>
-    </module>
-    <module name="LeftCurly">
-      <property name="option" value="nl"/>
-      <property name="tokens"
-                value="CLASS_DEF, CTOR_DEF, INTERFACE_DEF, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF"/>
-
-    </module>
-    <module name="NeedBraces"/>
-    <module name="RightCurly">
-      <property name="option" value="alone"/>
-      <property name="tokens" value="LITERAL_CATCH, LITERAL_ELSE, LITERAL_TRY"/>
-    </module>
-    <module name="AvoidInlineConditionals"/>
-    <module name="DoubleCheckedLocking"/>
-    <module name="EmptyStatement"/>
-
-    <module name="EqualsHashCode"/>
-    <!--<module name="HiddenField"/>-->
-    <module name="IllegalInstantiation"/>
-    <module name="InnerAssignment"/>
-    <module name="MagicNumber">
-      <property name="tokens" value="NUM_DOUBLE, NUM_FLOAT"/>
-      <property name="ignoreNumbers" value="-1, 0, 1, 2, 10, 50, 60, 100, 1000, 3600"/>
-    </module>
-    <module name="MissingSwitchDefault"/>
-
-    <!--
-         Niclas 2005-09-16:
-         This check seems somewhat broken, since
-         a = b == false;
-         is more readable in my view than
-         a = !b
-         but the former will trigger this rule. Therefor I disable it.
-         <module name="SimplifyBooleanExpression">
-         </module>
-    -->
-    <module name="SimplifyBooleanReturn"/>
-    <module name="StringLiteralEquality"/>
-    <module name="NestedIfDepth">
-      <property name="max" value="3"/>
-    </module>
-    <module name="NestedTryDepth">
-      <property name="max" value="2"/>
-    </module>
-
-    <module name="SuperClone"/>
-    <module name="SuperFinalize"/>
-    <module name="IllegalCatch">
-      <property name="illegalClassNames" value="java.lang.Exception, java.lang.Throwable, java.lang.Error"/>
-    </module>
-    <module name="IllegalThrows">
-      <property name="illegalClassNames"
-                value="java.lang.Exception, java.lang.Throwable, java.lang.RuntimeException, java.lang.Error"/>
-    </module>
-    <module name="PackageDeclaration"/>
-
-    <module name="JUnitTestCase"/>
-    <module name="DeclarationOrder"/>
-    <module name="ParameterAssignment"/>
-    <!--<module name="MissingCtor"/>-->
-    <module name="MultipleVariableDeclarations"/>
-    <module name="DesignForExtension">
-      <property name="severity" value="ignore"/>
-    </module>
-    <module name="FinalClass"/>
-
-    <module name="HideUtilityClassConstructor"/>
-    <module name="VisibilityModifier"/>
-    <module name="AvoidStarImport"/>
-    <module name="IllegalImport"/>
-    <module name="RedundantImport"/>
-    <module name="UnusedImports"/>
-    <module name="ImportOrder">
-      <property name="groups" value=""/>
-      <property name="ordered" value="true"/>
-      <property name="option" value="under"/>
-      <property name="separated" value="true"/>
-      <property name="caseSensitive" value="true"/>
-    </module>
-
-    <!--TODO Removing this until Javadoc effort has picked up -->
-    <!--<module name="JavadocMethod"/>-->
-    <!--<module name="JavadocType"/>-->
-    <!--<module name="JavadocVariable">-->
-      <!--<property name="scope" value="package"/>-->
-    <!--</module>-->
-    <module name="ConstantName">
-      <property name="format" value="^[A-Z0-9_$]*$"/>
-    </module>
-    <module name="LocalFinalVariableName"/>
-    <module name="LocalVariableName"/>
-    <module name="MemberName">
-      <property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
-    </module>
-    <module name="MethodName"/>
-    <module name="PackageName"/>
-
-    <module name="ParameterName"/>
-    <module name="StaticVariableName">
-      <property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
-    </module>
-    <module name="TypeName"/>
-    <module name="LineLength">
-
-      <property name="max" value="120"/>
-    </module>
-    <module name="MethodLength"/>
-    <module name="AnonInnerLength">
-      <property name="max" value="60"/>
-    </module>
-    <module name="ParameterNumber">
-      <property name="max" value="12"/>
-    </module>
-
-    <module name="EmptyForIteratorPad"/>
-    <module name="NoWhitespaceAfter">
-      <property name="tokens" value="BNOT,DEC,DOT,INC,UNARY_MINUS,UNARY_PLUS"/>
-    </module>
-    <!--<module name="OperatorWrap"/>-->
-    <module name="ParenPad">
-      <property name="option" value="space"/>
-      <property name="tokens" value="CTOR_CALL, LPAREN, METHOD_CALL, RPAREN, SUPER_CTOR_CALL"/>
-    </module>
-
-    <!--
-        <module name="TabCharacter"/>
-    -->
-
-    <module name="WhitespaceAfter"/>
-    <module name="WhitespaceAround">
-      <property name="tokens"
-                value="BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, EQUAL, GE, GT, LAND, LCURLY, LE, LITERAL_ASSERT, LITERAL_DO, LITERAL_RETURN, LITERAL_TRY, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR, SR_ASSIGN, STAR, STAR_ASSIGN"/>
-    </module>
-  </module>
-
-  <module name="FileLength">
-    <property name="max" value="1000"/>
-  </module>
-
-</module>
diff --git a/etc/qi4j-runtime-checkstyle.xml b/etc/qi4j-runtime-checkstyle.xml
deleted file mode 100644
index a50e0db..0000000
--- a/etc/qi4j-runtime-checkstyle.xml
+++ /dev/null
@@ -1,209 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
-  "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
-
-<!--***********************************************************
- *
- * 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.
- *
- ***********************************************************-->
-
-<!-- Documentation is availableService at
-     http://checkstyle.sourceforge.net/availablechecks.html
--->
-<module name="Checker">
-  <property name="severity" value="warning"/>
-  <module name="NewlineAtEndOfFile"/>
-  <module name="Translation"/>
-  <!--TODO Removing this until Javadoc effort has picked up -->
-  <!--<module name="JavadocPackage"/>-->
-  <module name="TreeWalker">
-    <module name="MutableException"/>
-
-    <module name="CyclomaticComplexity">
-      <property name="max" value="7"/>
-    </module>
-    <module name="Indentation"/>
-    <module name="CovariantEquals"/>
-    <module name="FileContentsHolder"/>
-    <module name="ArrayTypeStyle"/>
-    <!-- 2005-Oct-05
-         final in method arguments is just ugly in my opinion,
-         communicates very little, and is not preventing much
-         problem. Remove it for now.
-    <module name="FinalParameters">
-        <property name="severity" value="ignore"/>
-        <property name="tokens" value="METHOD_DEF, CTOR_DEF"/>
-    </module>
-    -->
-
-    <!--
-        <module name="GenericIllegalRegexp">
-          <property name="severity" value="ignore"/>
-          <property name="format" value="\s+$"/>
-          <property name="message" value="Line has trailing spaces."/>
-        </module>
-    -->
-
-    <module name="ModifierOrder"/>
-    <module name="RedundantModifier">
-      <property name="severity" value="ignore"/>
-      <property name="tokens" value="METHOD_DEF, VARIABLE_DEF"/>
-    </module>
-
-    <module name="TodoComment"/>
-    <module name="UpperEll"/>
-    <module name="AvoidNestedBlocks"/>
-    <module name="EmptyBlock">
-      <property name="tokens"
-                value="LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_IF, LITERAL_FOR, LITERAL_TRY, LITERAL_WHILE, STATIC_INIT"/>
-    </module>
-    <module name="LeftCurly">
-      <property name="option" value="nl"/>
-      <property name="tokens"
-                value="CLASS_DEF, CTOR_DEF, INTERFACE_DEF, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF"/>
-
-    </module>
-    <module name="NeedBraces"/>
-    <module name="RightCurly">
-      <property name="option" value="alone"/>
-      <property name="tokens" value="LITERAL_CATCH, LITERAL_ELSE, LITERAL_TRY"/>
-    </module>
-    <module name="AvoidInlineConditionals"/>
-    <module name="DoubleCheckedLocking"/>
-    <module name="EmptyStatement"/>
-
-    <module name="EqualsHashCode"/>
-    <!--<module name="HiddenField"/>-->
-    <module name="IllegalInstantiation"/>
-    <module name="InnerAssignment"/>
-    <module name="MagicNumber">
-      <property name="tokens" value="NUM_DOUBLE, NUM_FLOAT"/>
-      <property name="ignoreNumbers" value="-1, 0, 1, 2, 10, 50, 60, 100, 1000, 3600"/>
-    </module>
-    <module name="MissingSwitchDefault"/>
-
-    <!--
-         Niclas 2005-09-16:
-         This check seems somewhat broken, since
-         a = b == false;
-         is more readable in my view than
-         a = !b
-         but the former will trigger this rule. Therefor I disable it.
-         <module name="SimplifyBooleanExpression">
-         </module>
-    -->
-    <module name="SimplifyBooleanReturn"/>
-    <module name="StringLiteralEquality"/>
-    <module name="NestedIfDepth">
-      <property name="max" value="3"/>
-    </module>
-    <module name="NestedTryDepth">
-      <property name="max" value="2"/>
-    </module>
-
-    <module name="SuperClone"/>
-    <module name="SuperFinalize"/>
-    <module name="IllegalCatch">
-      <property name="illegalClassNames" value="java.lang.Exception, java.lang.Throwable, java.lang.Error"/>
-    </module>
-    <module name="IllegalThrows">
-      <property name="illegalClassNames"
-                value="java.lang.Exception, java.lang.Throwable, java.lang.RuntimeException, java.lang.Error"/>
-    </module>
-    <module name="PackageDeclaration"/>
-
-    <module name="JUnitTestCase"/>
-    <module name="DeclarationOrder"/>
-    <module name="ParameterAssignment"/>
-    <!--<module name="MissingCtor"/>-->
-    <module name="MultipleVariableDeclarations"/>
-    <module name="DesignForExtension">
-      <property name="severity" value="ignore"/>
-    </module>
-    <module name="FinalClass"/>
-
-    <module name="HideUtilityClassConstructor"/>
-    <module name="VisibilityModifier"/>
-    <module name="AvoidStarImport"/>
-    <module name="IllegalImport"/>
-    <module name="RedundantImport"/>
-    <module name="UnusedImports"/>
-    <module name="ImportOrder">
-      <property name="groups" value=""/>
-      <property name="ordered" value="true"/>
-      <property name="option" value="under"/>
-      <property name="separated" value="true"/>
-      <property name="caseSensitive" value="true"/>
-    </module>
-    <!--TODO Removing this until Javadoc effort has picked up -->
-    <!--<module name="JavadocType"/>-->
-    <module name="ConstantName">
-      <property name="format" value="^[A-Z0-9_$]*$"/>
-    </module>
-    <module name="LocalFinalVariableName"/>
-    <module name="LocalVariableName"/>
-    <module name="MemberName">
-      <property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
-    </module>
-    <module name="MethodName"/>
-    <module name="PackageName"/>
-
-    <module name="ParameterName"/>
-    <module name="StaticVariableName">
-      <property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
-    </module>
-    <module name="TypeName"/>
-    <module name="LineLength">
-
-      <property name="max" value="120"/>
-    </module>
-    <module name="MethodLength"/>
-    <module name="AnonInnerLength">
-      <property name="max" value="60"/>
-    </module>
-    <module name="ParameterNumber">
-      <property name="max" value="12"/>
-    </module>
-
-    <module name="EmptyForIteratorPad"/>
-    <module name="NoWhitespaceAfter">
-      <property name="tokens" value="BNOT,DEC,DOT,INC,UNARY_MINUS,UNARY_PLUS"/>
-    </module>
-    <!--<module name="OperatorWrap"/>-->
-    <module name="ParenPad">
-      <property name="option" value="space"/>
-      <property name="tokens" value="CTOR_CALL, LPAREN, METHOD_CALL, RPAREN, SUPER_CTOR_CALL"/>
-    </module>
-
-    <!--
-        <module name="TabCharacter"/>
-    -->
-
-    <module name="WhitespaceAfter"/>
-    <module name="WhitespaceAround">
-      <property name="tokens"
-                value="BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, EQUAL, GE, GT, LAND, LCURLY, LE, LITERAL_ASSERT, LITERAL_DO, LITERAL_RETURN, LITERAL_TRY, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR, SR_ASSIGN, STAR, STAR_ASSIGN"/>
-    </module>
-  </module>
-
-  <module name="FileLength">
-    <property name="max" value="1000"/>
-  </module>
-
-</module>
diff --git a/etc/qi4j-tests-checkstyle.xml b/etc/qi4j-tests-checkstyle.xml
deleted file mode 100644
index be1fca6..0000000
--- a/etc/qi4j-tests-checkstyle.xml
+++ /dev/null
@@ -1,197 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
-  "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
-
-<!--***********************************************************
- *
- * 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.
- *
- ***********************************************************-->
-
-<!-- Documentation is availableService at
-     http://checkstyle.sourceforge.net/availablechecks.html
--->
-<module name="Checker">
-  <property name="severity" value="warning"/>
-  <module name="NewlineAtEndOfFile"/>
-  <module name="Translation"/>
-  <module name="TreeWalker">
-    <module name="MutableException"/>
-
-    <module name="CyclomaticComplexity">
-      <property name="max" value="7"/>
-    </module>
-    <module name="Indentation"/>
-    <module name="CovariantEquals"/>
-    <module name="FileContentsHolder"/>
-    <module name="ArrayTypeStyle"/>
-    <!--
-        <module name="GenericIllegalRegexp">
-          <property name="severity" value="ignore"/>
-          <property name="format" value="\s+$"/>
-          <property name="message" value="Line has trailing spaces."/>
-        </module>
-    -->
-
-    <module name="ModifierOrder"/>
-    <module name="RedundantModifier">
-      <property name="severity" value="ignore"/>
-      <property name="tokens" value="METHOD_DEF, VARIABLE_DEF"/>
-    </module>
-
-    <module name="TodoComment"/>
-    <module name="UpperEll"/>
-    <module name="AvoidNestedBlocks"/>
-    <module name="EmptyBlock">
-      <property name="tokens"
-                value="LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_IF, LITERAL_FOR, LITERAL_TRY, LITERAL_WHILE, STATIC_INIT"/>
-    </module>
-    <module name="LeftCurly">
-      <property name="option" value="nl"/>
-      <property name="tokens"
-                value="CLASS_DEF, CTOR_DEF, INTERFACE_DEF, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF"/>
-
-    </module>
-    <module name="NeedBraces"/>
-    <module name="RightCurly">
-      <property name="option" value="alone"/>
-      <property name="tokens" value="LITERAL_CATCH, LITERAL_ELSE, LITERAL_TRY"/>
-    </module>
-    <module name="AvoidInlineConditionals"/>
-    <module name="DoubleCheckedLocking"/>
-    <module name="EmptyStatement"/>
-
-    <module name="EqualsHashCode"/>
-    <!--<module name="HiddenField"/>-->
-    <module name="IllegalInstantiation"/>
-    <module name="InnerAssignment"/>
-    <module name="MagicNumber">
-      <property name="tokens" value="NUM_DOUBLE, NUM_FLOAT"/>
-      <property name="ignoreNumbers" value="-1, 0, 1, 2, 10, 50, 60, 100, 1000, 3600"/>
-    </module>
-    <module name="MissingSwitchDefault"/>
-
-    <!--
-         Niclas 2005-09-16:
-         This check seems somewhat broken, since
-         a = b == false;
-         is more readable in my view than
-         a = !b
-         but the former will trigger this rule. Therefor I disable it.
-         <module name="SimplifyBooleanExpression">
-         </module>
-    -->
-    <module name="SimplifyBooleanReturn"/>
-    <module name="StringLiteralEquality"/>
-    <module name="NestedIfDepth">
-      <property name="max" value="3"/>
-    </module>
-    <module name="NestedTryDepth">
-      <property name="max" value="2"/>
-    </module>
-
-    <module name="SuperClone"/>
-    <module name="SuperFinalize"/>
-    <!-- Ok in tests...
-    <module name="IllegalCatch">
-      <property name="illegalClassNames" value="java.lang.Exception, java.lang.Throwable, java.lang.Error"/>
-    </module>
-    <module name="IllegalThrows">
-      <property name="illegalClassNames"
-                value="java.lang.Exception, java.lang.Throwable, java.lang.RuntimeException, java.lang.Error"/>
-    </module>
-    -->
-    <module name="PackageDeclaration"/>
-
-    <module name="JUnitTestCase"/>
-    <module name="DeclarationOrder"/>
-    <module name="ParameterAssignment"/>
-    <!--<module name="MissingCtor"/>-->
-    <module name="MultipleVariableDeclarations"/>
-    <module name="DesignForExtension">
-      <property name="severity" value="ignore"/>
-    </module>
-    <module name="FinalClass"/>
-
-    <module name="HideUtilityClassConstructor"/>
-    <module name="VisibilityModifier"/>
-    <module name="AvoidStarImport"/>
-    <module name="IllegalImport"/>
-    <module name="RedundantImport"/>
-    <module name="UnusedImports"/>
-    <module name="ImportOrder">
-      <property name="groups" value=""/>
-      <property name="ordered" value="true"/>
-      <property name="separated" value="false"/>
-      <property name="caseSensitive" value="true"/>
-      <property name="option" value="under"/>
-    </module>
-    <module name="ConstantName">
-      <property name="format" value="^[A-Z0-9_$]*$"/>
-    </module>
-    <module name="LocalFinalVariableName"/>
-    <module name="LocalVariableName"/>
-    <module name="MemberName">
-      <property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
-    </module>
-    <module name="MethodName"/>
-    <module name="PackageName"/>
-
-    <module name="ParameterName"/>
-    <module name="StaticVariableName">
-      <property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
-    </module>
-    <module name="TypeName"/>
-    <module name="LineLength">
-
-      <property name="max" value="120"/>
-    </module>
-    <module name="MethodLength"/>
-    <module name="AnonInnerLength">
-      <property name="max" value="60"/>
-    </module>
-    <module name="ParameterNumber">
-      <property name="max" value="12"/>
-    </module>
-
-    <module name="EmptyForIteratorPad"/>
-    <module name="NoWhitespaceAfter">
-      <property name="tokens" value="BNOT,DEC,DOT,INC,UNARY_MINUS,UNARY_PLUS"/>
-    </module>
-    <!--<module name="OperatorWrap"/>-->
-    <module name="ParenPad">
-      <property name="option" value="space"/>
-      <property name="tokens" value="CTOR_CALL, LPAREN, METHOD_CALL, RPAREN, SUPER_CTOR_CALL"/>
-    </module>
-
-    <!--
-        <module name="TabCharacter"/>
-    -->
-
-    <module name="WhitespaceAfter"/>
-    <module name="WhitespaceAround">
-      <property name="tokens"
-                value="BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, EQUAL, GE, GT, LAND, LCURLY, LE, LITERAL_ASSERT, LITERAL_DO, LITERAL_RETURN, LITERAL_TRY, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR, SR_ASSIGN, STAR, STAR_ASSIGN"/>
-    </module>
-  </module>
-
-  <module name="FileLength">
-    <property name="max" value="1000"/>
-  </module>
-
-</module>
diff --git a/extensions/cache-ehcache/build.gradle b/extensions/cache-ehcache/build.gradle
index 9d68d45..c61a790 100644
--- a/extensions/cache-ehcache/build.gradle
+++ b/extensions/cache-ehcache/build.gradle
@@ -1,34 +1,39 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Ehcache Cache Extension"
+apply plugin: 'polygene-extension'
 
-jar { manifest { name = "Apache Zest™ Extension: EhCache"}}
+description = "Apache Polygene™ Ehcache Cache Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension: EhCache" } }
 
 dependencies {
+  api polygene.core.bootstrap
+  api polygene.library( 'fileconfig' )
 
-  compile(project(':org.qi4j.core:org.qi4j.core.spi'))
-  compile(project(':org.qi4j.core:org.qi4j.core.bootstrap'))
-  compile(libraries.ehcache)
+  implementation polygene.library( 'constraints' )
+  implementation libraries.ehcache
 
-  testCompile( project(':org.qi4j.core:org.qi4j.core.testsupport') )
+  runtimeOnly polygene.core.runtime
 
-  testRuntime( project(':org.qi4j.core:org.qi4j.core.runtime'))
-  testRuntime(libraries.logback)
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
 }
diff --git a/extensions/cache-ehcache/dev-status.xml b/extensions/cache-ehcache/dev-status.xml
index b863976..e6cf5af 100644
--- a/extensions/cache-ehcache/dev-status.xml
+++ b/extensions/cache-ehcache/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
         <!--none,early,beta,stable,mature-->
         <codebase>beta</codebase>
diff --git a/extensions/cache-ehcache/src/docs/cache-ehcache.txt b/extensions/cache-ehcache/src/docs/cache-ehcache.txt
index 32c8bc8..ca462d3 100644
--- a/extensions/cache-ehcache/src/docs/cache-ehcache.txt
+++ b/extensions/cache-ehcache/src/docs/cache-ehcache.txt
@@ -40,7 +40,7 @@
 
 [snippet,java]
 ----
-source=extensions/cache-ehcache/src/test/java/org/qi4j/cache/ehcache/EhCacheTest.java
+source=extensions/cache-ehcache/src/test/java/org/apache/polygene/cache/ehcache/EhCacheTest.java
 tag=assembly
 ----
 
@@ -51,6 +51,9 @@
 
 [snippet,java]
 ----
-source=extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/EhCacheConfiguration.java
+source=extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/EhCacheConfiguration.java
 tag=config
 ----
+
+Cache overflow to disk may be configured using the <<library-fileconfig>>.
+If the FileConfig library is not in use, then it defaults to a temporary directory in `java.io.tmpdir`.
diff --git a/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/EhCacheConfiguration.java b/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/EhCacheConfiguration.java
new file mode 100644
index 0000000..b75e8b7
--- /dev/null
+++ b/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/EhCacheConfiguration.java
@@ -0,0 +1,142 @@
+/*
+ *  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.polygene.cache.ehcache;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.constraints.annotation.OneOf;
+
+// START SNIPPET: config
+public interface EhCacheConfiguration {
+
+    /**
+     * Heap tier size.
+     *
+     * Default to 1MB, you may want to change this.
+     *
+     * @return Heap tier size
+     */
+    @UseDefaults( "1" )
+    Property<Long> heapSize();
+
+    /**
+     * Heap tier size unit.
+     *
+     * @return Heap tier size unit
+     */
+    @OneOf( { "B", "KB", "MB", "GB", "TB", "PB" } )
+    @UseDefaults( "MB" )
+    Property<String> heapUnit();
+
+    /**
+     * Optional off-heap tier size.
+     *
+     * @return Optional off-heap tier size
+     */
+    @Optional
+    Property<Long> offHeapSize();
+
+    /**
+     * Off-heap tier size unit.
+     *
+     * @return Off-heap tier size unit
+     */
+    @OneOf( { "B", "KB", "MB", "GB", "TB", "PB" } )
+    @UseDefaults( "MB" )
+    Property<String> offHeapUnit();
+
+    /**
+     * Optional disk tier size.
+     *
+     * @return Optional disk tier size
+     */
+    @Optional
+    Property<Long> diskSize();
+
+    /**
+     * Disk tier size unit.
+     *
+     * @return Disk tier size unit
+     */
+    @OneOf( { "B", "KB", "MB", "GB", "TB", "PB" } )
+    @UseDefaults( "MB" )
+    Property<String> diskUnit();
+
+    /**
+     * If the disk tier is persistent or not.
+     *
+     * @return If the disk tier is persistent or not
+     */
+    @UseDefaults
+    Property<Boolean> diskPersistent();
+
+    /**
+     * Maximum size of cached objects.
+     *
+     * @return Maximum size of cached objects
+     */
+    @Optional
+    Property<Long> maxObjectSize();
+
+    /**
+     * Unit for maximum size of cached objects.
+     *
+     * @return Unit for maximum size of cached objects
+     */
+    @OneOf( { "B", "KB", "MB", "GB", "TB", "PB" } )
+    @UseDefaults( "MB" )
+    Property<String> maxObjectSizeUnit();
+
+    /**
+     * Maximum cached object graph depth.
+     *
+     * @return Maximum cached object graph depth
+     */
+    @Optional
+    Property<Long> maxObjectGraphDepth();
+
+    /**
+     * Expiry policy.
+     *
+     * @return Expiry policy
+     */
+    @OneOf( { "NONE", "TIME_TO_IDLE", "TIME_TO_LIVE" } )
+    @UseDefaults( "NONE" )
+    Property<String> expiry();
+
+    /**
+     * Expiry length.
+     *
+     * @return Expiry length
+     */
+    @Optional
+    Property<Long> expiryLength();
+
+    /**
+     * Expiry time unit.
+     *
+     * @return Expiry time unit
+     */
+    @OneOf( { "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS" } )
+    @UseDefaults( "SECONDS" )
+    Property<String> expiryTimeUnit();
+}
+// END SNIPPET: config
diff --git a/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/EhCacheImpl.java b/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/EhCacheImpl.java
new file mode 100644
index 0000000..546d492
--- /dev/null
+++ b/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/EhCacheImpl.java
@@ -0,0 +1,89 @@
+/*
+ *  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.polygene.cache.ehcache;
+
+import org.apache.polygene.spi.cache.Cache;
+
+public class EhCacheImpl<T>
+    implements Cache<T>
+{
+    private int refCount;
+    private final org.ehcache.Cache backingCache;
+    private final Class<T> valueType;
+    private final String id;
+
+    public EhCacheImpl( String cacheId, org.ehcache.Cache cache, Class<T> valueType )
+    {
+        this.id = cacheId;
+        this.backingCache = cache;
+        this.valueType = valueType;
+    }
+
+    @Override
+    public T get( String key )
+    {
+        Object element = backingCache.get( key );
+        if( element == null )
+        {
+            return null;
+        }
+        return valueType.cast( element );
+    }
+
+    @Override
+    public T remove( String key )
+    {
+        T old = valueType.cast( backingCache.get( key ) );
+        backingCache.remove( key );
+        return old;
+    }
+
+    @Override
+    public void put( String key, T value )
+    {
+        backingCache.put( key, value );
+    }
+
+    @Override
+    public boolean exists( String key )
+    {
+        return backingCache.containsKey( key );
+    }
+
+    synchronized void decRefCount()
+    {
+        refCount--;
+    }
+
+    synchronized void incRefCount()
+    {
+        refCount++;
+    }
+
+    synchronized boolean isNotUsed()
+    {
+        return refCount == 0;
+    }
+
+    public String cacheId()
+    {
+        return id;
+    }
+}
diff --git a/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/EhCachePoolMixin.java b/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/EhCachePoolMixin.java
new file mode 100644
index 0000000..958610f
--- /dev/null
+++ b/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/EhCachePoolMixin.java
@@ -0,0 +1,179 @@
+/*
+ *  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.polygene.cache.ehcache;
+
+import java.io.File;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.library.fileconfig.FileConfiguration;
+import org.apache.polygene.spi.cache.Cache;
+import org.ehcache.CacheManager;
+import org.ehcache.config.CacheConfiguration;
+import org.ehcache.config.builders.CacheConfigurationBuilder;
+import org.ehcache.config.builders.CacheManagerBuilder;
+import org.ehcache.config.builders.ResourcePoolsBuilder;
+import org.ehcache.config.units.MemoryUnit;
+import org.ehcache.expiry.Duration;
+
+import static org.ehcache.expiry.Expirations.*;
+
+public abstract class EhCachePoolMixin
+    implements EhCachePoolService
+{
+    private final ConcurrentHashMap<String, EhCacheImpl<?>> caches = new ConcurrentHashMap<>();
+
+    @This
+    private HasIdentity identity;
+
+    @This
+    private Configuration<EhCacheConfiguration> configuration;
+
+    @Optional
+    @Service
+    private FileConfiguration fileConfiguration;
+
+    private CacheManager cacheManager;
+
+    @Override
+    public void activateService()
+        throws Exception
+    {
+        cacheManager = CacheManagerBuilder
+            .newCacheManagerBuilder()
+            .with( CacheManagerBuilder.persistence( diskStorePath().getAbsolutePath() ) )
+            .withDefaultDiskStoreThreadPool( cacheManagerThreadPoolName( "disk-store" ) )
+            .withDefaultEventListenersThreadPool( cacheManagerThreadPoolName( "event-listeners" ) )
+            .withDefaultWriteBehindThreadPool( cacheManagerThreadPoolName( "write-behind" ) )
+            .build();
+        cacheManager.init();
+    }
+
+    private File diskStorePath()
+    {
+        String stringIdentity = identity.identity().get().toString();
+        if( fileConfiguration != null )
+        {
+            return new File( fileConfiguration.cacheDirectory(), stringIdentity );
+        }
+        return new File( System.getProperty( "java.io.tmpdir" ), stringIdentity );
+    }
+
+    @Override
+    public void passivateService()
+        throws Exception
+    {
+        cacheManager.close();
+        cacheManager = null;
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> Cache<T> fetchCache( String cacheId, Class<T> valueType )
+    {
+        // Note: Small bug in Ehcache; If the cache name is an empty String it will actually work until
+        //       you try to remove the Cache instance from the CacheManager, at which point it is silently
+        //       ignored but not removed so there is a follow up problem of too much in the CacheManager.
+        Objects.requireNonNull( cacheId, "cacheId" );
+        if( cacheId.isEmpty() )
+        {
+            throw new IllegalArgumentException( "cacheId was empty string" );
+        }
+        EhCacheImpl<?> cache = caches.computeIfAbsent( cacheId, key -> createNewCache( cacheId, valueType ) );
+        cache.incRefCount();
+        return (Cache<T>) cache;
+    }
+
+    private <T> EhCacheImpl<T> createNewCache( String cacheId, Class<T> valueType )
+    {
+        configuration.refresh();
+        EhCacheConfiguration config = configuration.get();
+
+        ResourcePoolsBuilder poolsBuilder = ResourcePoolsBuilder.newResourcePoolsBuilder();
+
+        poolsBuilder = poolsBuilder.heap( config.heapSize().get(), MemoryUnit.valueOf( config.heapUnit().get() ) );
+
+        if( config.offHeapSize().get() != null )
+        {
+            poolsBuilder = poolsBuilder.offheap( config.offHeapSize().get(),
+                                                 MemoryUnit.valueOf( config.offHeapUnit().get() ) );
+        }
+        if( config.diskSize().get() != null )
+        {
+            poolsBuilder = poolsBuilder.disk( config.diskSize().get(),
+                                              MemoryUnit.valueOf( config.diskUnit().get() ),
+                                              config.diskPersistent().get() );
+        }
+
+        CacheConfigurationBuilder<String, T> configBuilder = CacheConfigurationBuilder
+            .newCacheConfigurationBuilder( String.class, valueType, poolsBuilder );
+        if( config.maxObjectSize().get() != null )
+        {
+            configBuilder = configBuilder.withSizeOfMaxObjectSize( config.maxObjectSize().get(),
+                                                                   MemoryUnit.valueOf( config.maxObjectSizeUnit().get() ) );
+        }
+        if( config.maxObjectGraphDepth().get() != null )
+        {
+            configBuilder = configBuilder.withSizeOfMaxObjectGraph( config.maxObjectGraphDepth().get() );
+        }
+        switch( config.expiry().get() )
+        {
+            case "TIME_TO_IDLE":
+                configBuilder = configBuilder.withExpiry( timeToIdleExpiration( Duration.of(
+                    config.expiryLength().get() == null ? - 1L : config.expiryLength().get(),
+                    TimeUnit.valueOf( config.expiryTimeUnit().get() ) ) ) );
+                break;
+            case "TIME_TO_LIVE":
+                configBuilder = configBuilder.withExpiry( timeToLiveExpiration( Duration.of(
+                    config.expiryLength().get() == null ? - 1L : config.expiryLength().get(),
+                    TimeUnit.valueOf( config.expiryTimeUnit().get() ) ) ) );
+                break;
+            case "NONE":
+            default:
+                configBuilder = configBuilder.withExpiry( noExpiration() );
+                break;
+        }
+        CacheConfiguration<String, T> cacheConfig = configBuilder.build();
+        org.ehcache.Cache<String, T> cache = cacheManager.createCache( cacheId, cacheConfig );
+        return new EhCacheImpl<>( cacheId, cache, valueType );
+    }
+
+    @Override
+    public void returnCache( Cache<?> cache )
+    {
+        EhCacheImpl<?> eh = (EhCacheImpl<?>) cache;
+        eh.decRefCount();
+        if( eh.isNotUsed() )
+        {
+            caches.remove( eh.cacheId() );
+            cacheManager.removeCache( eh.cacheId() );
+        }
+    }
+
+    private String cacheManagerThreadPoolName( String name )
+    {
+        return identity.identity().get().toString() + "-" + name;
+    }
+}
diff --git a/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/EhCachePoolService.java b/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/EhCachePoolService.java
new file mode 100644
index 0000000..6368394
--- /dev/null
+++ b/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/EhCachePoolService.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.cache.ehcache;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.spi.cache.CachePool;
+
+@Mixins( EhCachePoolMixin.class )
+public interface EhCachePoolService
+    extends CachePool, ServiceActivation
+{
+}
diff --git a/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/assembly/EhCacheAssembler.java b/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/assembly/EhCacheAssembler.java
new file mode 100644
index 0000000..077a24f
--- /dev/null
+++ b/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/assembly/EhCacheAssembler.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.cache.ehcache.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.cache.ehcache.EhCacheConfiguration;
+import org.apache.polygene.cache.ehcache.EhCachePoolService;
+
+public class EhCacheAssembler
+    extends Assemblers.VisibilityIdentityConfig<EhCacheAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( EhCachePoolService.class ).visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+        if( hasConfig() )
+        {
+            configModule().entities( EhCacheConfiguration.class ).visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/assembly/package.html b/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/assembly/package.html
new file mode 100644
index 0000000..8eb2472
--- /dev/null
+++ b/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>EHCache EntityStore CachePool Assembly.</h2>
+    </body>
+</html>
diff --git a/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/package.html b/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/package.html
new file mode 100644
index 0000000..f8d9e3e
--- /dev/null
+++ b/extensions/cache-ehcache/src/main/java/org/apache/polygene/cache/ehcache/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>EHCache EntityStore CachePool.</h2>
+    </body>
+</html>
diff --git a/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/EhCacheConfiguration.java b/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/EhCacheConfiguration.java
deleted file mode 100644
index 06fbb2f..0000000
--- a/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/EhCacheConfiguration.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2010 Niclas Hedhman.
- *
- * Licensed  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.qi4j.cache.ehcache;
-
-import net.sf.ehcache.config.PersistenceConfiguration.Strategy;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-// START SNIPPET: config
-public interface EhCacheConfiguration
-    extends ConfigurationComposite
-{
-
-    @Optional @UseDefaults
-    Property<Boolean> clearOnFlush();
-
-    @Optional @UseDefaults
-    Property<Integer> diskAccessStripes();
-
-    @Optional @UseDefaults
-    Property<Long> diskExpiryThreadIntervalSeconds();
-
-    /**
-     * Cache Persistence Strategy.
-     *
-     * Can be:
-     * <ul>
-     *   <li>LOCALTEMPSWAP: Standard open source (non fault-tolerant) on-disk persistence.</li>
-     *   <li>LOCALRESTARTABLE: Enterprise fault tolerant persistence.</li>
-     *   <li>NONE: No persistence.</li>
-     *   <li>DISTRIBUTED: Terracotta clustered persistence (requires a Terracotta clustered cache).</li>
-     * </ul>
-     * Defaults to NONE.
-     */
-    @Optional
-    Property<Strategy> persistenceStrategy();
-
-    @Optional @UseDefaults
-    Property<String> diskStorePath();
-
-    @Optional @UseDefaults
-    Property<Integer> diskSpoolBufferSizeMB();
-
-    @Optional @UseDefaults
-    Property<Boolean> eternal();
-
-    @Optional @UseDefaults
-    Property<Boolean> loggingEnabled();
-
-    /**
-     * Number of objects the ehCache should keep in memory.
-     * Defaults to 1000
-     *
-     * @return The maximum number of elements to be kept in memory.
-     */
-    @Optional @UseDefaults
-    Property<Integer> maxElementsInMemory();
-
-    @Optional @UseDefaults
-    Property<Integer> maxElementsOnDisk();
-
-    @Optional @UseDefaults
-    Property<String> memoryStoreEvictionPolicy();
-
-    @Optional @UseDefaults
-    Property<String> name();
-
-    @Optional @UseDefaults
-    Property<String> transactionalMode();
-
-    @Optional @UseDefaults
-    Property<Long> timeToLiveSeconds();
-
-    @Optional @UseDefaults
-    Property<Long> timeToIdleSeconds();
-
-    @Optional @UseDefaults
-    Property<String> cacheManagerName();
-
-    @Optional @UseDefaults
-    Property<String> monitoring();
-
-    @Optional @UseDefaults
-    Property<Boolean> updateCheck();
-}
-// END SNIPPET: config
diff --git a/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/EhCacheImpl.java b/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/EhCacheImpl.java
deleted file mode 100644
index 2b0286b..0000000
--- a/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/EhCacheImpl.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2010 Niclas Hedhman.
- *
- * Licensed  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.qi4j.cache.ehcache;
-
-import net.sf.ehcache.Element;
-import org.qi4j.spi.cache.Cache;
-
-public class EhCacheImpl<T>
-    implements Cache<T>
-{
-    private int refCount;
-    private final net.sf.ehcache.Cache backingCache;
-    private final Class<T> valueType;
-    private final String id;
-
-    public EhCacheImpl( String cacheId, net.sf.ehcache.Cache cache, Class<T> valueType )
-    {
-        this.id = cacheId;
-        this.backingCache = cache;
-        this.valueType = valueType;
-    }
-
-    @Override
-    public T get( String key )
-    {
-        Element element = backingCache.get( key );
-        if( element == null )
-        {
-            return null;
-        }
-        return valueType.cast( element.getObjectValue() );
-    }
-
-    @Override
-    public T remove( String key )
-    {
-        T old = valueType.cast( backingCache.get( key ).getObjectValue() );
-        backingCache.remove( key );
-        return old;
-    }
-
-    @Override
-    public void put( String key, T value )
-    {
-        Element element = new Element( key, value );
-        backingCache.put( element );
-    }
-
-    @Override
-    public boolean exists( String key )
-    {
-        return backingCache.isKeyInCache( key );
-    }
-
-    synchronized void decRefCount()
-    {
-        refCount--;
-    }
-
-    synchronized void incRefCount()
-    {
-        refCount++;
-    }
-
-    synchronized boolean isNotUsed()
-    {
-        return refCount == 0;
-    }
-
-    public String cacheId()
-    {
-        return id;
-    }
-}
diff --git a/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/EhCachePoolMixin.java b/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/EhCachePoolMixin.java
deleted file mode 100644
index 41a81f5..0000000
--- a/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/EhCachePoolMixin.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright 2010 Niclas Hedhman.
- *
- * Licensed  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.qi4j.cache.ehcache;
-
-import java.util.concurrent.ConcurrentHashMap;
-import net.sf.ehcache.CacheManager;
-import net.sf.ehcache.config.CacheConfiguration;
-import net.sf.ehcache.config.PersistenceConfiguration;
-import net.sf.ehcache.config.PersistenceConfiguration.Strategy;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.spi.cache.Cache;
-
-public abstract class EhCachePoolMixin
-    implements EhCachePoolService
-{
-
-    private final ConcurrentHashMap<String, EhCacheImpl<?>> caches = new ConcurrentHashMap<>();
-    @This @Optional
-    private Configuration<EhCacheConfiguration> config;
-    private CacheManager cacheManager;
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public <T> Cache<T> fetchCache( String cacheId, Class<T> valueType )
-    {
-        // Note: Small bug in Ehcache; If the cache name is an empty String it will actually work until
-        //       you try to remove the Cache instance from the CacheManager, at which point it is silently
-        //       ignored but not removed so there is an follow up problem of too much in the CacheManager.
-        NullArgumentException.validateNotEmpty( "cacheId", cacheId );
-        EhCacheImpl<?> cache = caches.get( cacheId );
-        if( cache == null )
-        {
-            cache = createNewCache( cacheId, valueType );
-            caches.put( cacheId, cache );
-        }
-        cache.incRefCount();
-        return (Cache<T>) cache;
-    }
-
-    private <T> EhCacheImpl<T> createNewCache( String cacheId, Class<T> valueType )
-    {
-        CacheConfiguration cc = createCacheConfiguration( cacheId );
-
-        // TODO: We also need all the other Configurations that are possible, like cacheLoaderFactoryConfiguration
-        net.sf.ehcache.Cache cache = new net.sf.ehcache.Cache( cc );
-        cacheManager.addCache( cache );
-
-        return new EhCacheImpl<>( cacheId, cache, valueType );
-    }
-
-    @Override
-    public void returnCache( Cache<?> cache )
-    {
-        EhCacheImpl<?> eh = (EhCacheImpl<?>) cache;
-        eh.decRefCount();
-        if( eh.isNotUsed() )
-        {
-            caches.remove( eh.cacheId() );
-            cacheManager.removeCache( eh.cacheId() );
-        }
-    }
-
-    @Override
-    public void activateService()
-        throws Exception
-    {
-        net.sf.ehcache.config.Configuration configuration = new net.sf.ehcache.config.Configuration();
-        configureEhCache( configuration );
-        CacheConfiguration cc = createCacheConfiguration( "qi4j.ehcache.config.default" );
-        configuration.setDefaultCacheConfiguration( cc );
-        cacheManager = CacheManager.newInstance( configuration );
-    }
-
-    @Override
-    public void passivateService()
-        throws Exception
-    {
-        cacheManager.shutdown();
-    }
-
-    private void configureEhCache( net.sf.ehcache.config.Configuration configuration )
-    {
-        EhCacheConfiguration conf = config.get();
-        Boolean updateCheck = conf.updateCheck().get();
-        configuration.setUpdateCheck( updateCheck );
-        configuration.setDynamicConfig( true );
-        String monitoring = conf.monitoring().get().trim();
-        if( monitoring.length() > 0 )
-        {
-            configuration.setMonitoring( monitoring );
-        }
-        String name = conf.cacheManagerName().get();
-        if( name == null )
-        {
-            name = "Zest Cache Extension";
-        }
-        configuration.setName( name );
-        String diskStorePath = conf.diskStorePath().get();
-        if( diskStorePath.length() > 0 )
-        {
-            configuration.getDiskStoreConfiguration().path( diskStorePath );
-        }
-    }
-
-    private CacheConfiguration createCacheConfiguration( String cacheId )
-    {
-        EhCacheConfiguration conf = config.get();
-        Integer maxElementsInMemory = conf.maxElementsInMemory().get();
-        if( maxElementsInMemory <= 0 )
-        {
-            maxElementsInMemory = 10000;
-        }
-        CacheConfiguration cacheConfig = new CacheConfiguration( cacheId, maxElementsInMemory );
-        String transactionalMode = conf.transactionalMode().get();
-        if( transactionalMode.length() > 0 )
-        {
-            cacheConfig.transactionalMode( transactionalMode );
-        }
-
-        Long timeToLiveSeconds = conf.timeToLiveSeconds().get();
-        if( timeToLiveSeconds > 0 )
-        {
-            cacheConfig.timeToLiveSeconds( timeToLiveSeconds );
-        }
-
-        Long timeToIdleSeconds = conf.timeToIdleSeconds().get();
-        if( timeToIdleSeconds > 0 )
-        {
-            cacheConfig.timeToIdleSeconds( timeToIdleSeconds );
-        }
-
-        String name = conf.name().get();
-        if( name.length() > 0 )
-        {
-            cacheConfig.name( name );
-        }
-
-        String memoryStoreEvictionPolicy = conf.memoryStoreEvictionPolicy().get();
-        if( memoryStoreEvictionPolicy.length() > 0 )
-        {
-            cacheConfig.memoryStoreEvictionPolicy( memoryStoreEvictionPolicy );
-        }
-
-        Integer maxElementsOnDisk = conf.maxElementsOnDisk().get();
-        if( maxElementsOnDisk > 0 )
-        {
-            cacheConfig.maxElementsOnDisk( maxElementsOnDisk );
-        }
-
-        Boolean loggingEnabled = conf.loggingEnabled().get();
-        if( loggingEnabled != null )
-        {
-            cacheConfig.logging( loggingEnabled );
-        }
-
-        Boolean eternal = conf.eternal().get();
-        cacheConfig.eternal( eternal );
-
-        Integer diskSpoolBufferSizeMB = conf.diskSpoolBufferSizeMB().get();
-        if( diskSpoolBufferSizeMB > 0 )
-        {
-            cacheConfig.diskSpoolBufferSizeMB( diskSpoolBufferSizeMB );
-        }
-
-        Long diskExpiryThreadIntervalSeconds = conf.diskExpiryThreadIntervalSeconds().get();
-        if( diskExpiryThreadIntervalSeconds > 0 )
-        {
-            cacheConfig.diskExpiryThreadIntervalSeconds( diskExpiryThreadIntervalSeconds );
-        }
-
-        Integer diskAccessStripes = conf.diskAccessStripes().get();
-        if( diskAccessStripes > 0 )
-        {
-            cacheConfig.diskAccessStripes( diskAccessStripes );
-        }
-        Boolean clearOnFlush = conf.clearOnFlush().get();
-        if( clearOnFlush != null )
-        {
-            cacheConfig.clearOnFlush( clearOnFlush );
-        }
-
-        // Persistence Configuration
-        PersistenceConfiguration persistenceConfig = new PersistenceConfiguration();
-        Strategy strategy = conf.persistenceStrategy().get();
-        if( strategy == null )
-        {
-            persistenceConfig.strategy( Strategy.NONE );
-        }
-        else
-        {
-            persistenceConfig.strategy( strategy );
-        }
-        cacheConfig.persistence( persistenceConfig );
-
-        return cacheConfig;
-    }
-
-}
diff --git a/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/EhCachePoolService.java b/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/EhCachePoolService.java
deleted file mode 100644
index f47fcb4..0000000
--- a/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/EhCachePoolService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2010 Niclas Hedhman.
- *
- * Licensed  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.qi4j.cache.ehcache;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.spi.cache.CachePool;
-
-@Mixins( EhCachePoolMixin.class )
-public interface EhCachePoolService
-    extends CachePool, ServiceActivation
-{
-}
diff --git a/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/assembly/EhCacheAssembler.java b/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/assembly/EhCacheAssembler.java
deleted file mode 100644
index 5eb28ba..0000000
--- a/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/assembly/EhCacheAssembler.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2010 Niclas Hedhman.
- *
- * Licensed  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.qi4j.cache.ehcache.assembly;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.cache.ehcache.EhCacheConfiguration;
-import org.qi4j.cache.ehcache.EhCachePoolService;
-
-public class EhCacheAssembler
-    extends Assemblers.VisibilityIdentityConfig<EhCacheAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ServiceDeclaration service = module.services( EhCachePoolService.class ).visibleIn( visibility() );
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        if( hasConfig() )
-        {
-            configModule().entities( EhCacheConfiguration.class ).visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/assembly/package.html b/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/assembly/package.html
deleted file mode 100644
index efa9790..0000000
--- a/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/assembly/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EHCache EntityStore CachePool Assembly.</h2>
-    </body>
-</html>
diff --git a/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/package.html b/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/package.html
deleted file mode 100644
index 608617b..0000000
--- a/extensions/cache-ehcache/src/main/java/org/qi4j/cache/ehcache/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EHCache EntityStore CachePool.</h2>
-    </body>
-</html>
diff --git a/extensions/cache-ehcache/src/test/java/org/apache/polygene/cache/ehcache/EhCacheTest.java b/extensions/cache-ehcache/src/test/java/org/apache/polygene/cache/ehcache/EhCacheTest.java
new file mode 100644
index 0000000..52e6291
--- /dev/null
+++ b/extensions/cache-ehcache/src/test/java/org/apache/polygene/cache/ehcache/EhCacheTest.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.cache.ehcache;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.cache.ehcache.assembly.EhCacheAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.cache.AbstractCachePoolTest;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+public class EhCacheTest
+    extends AbstractCachePoolTest
+{
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+    {
+        // END SNIPPET: assembly
+        ModuleAssembly confModule = module.layer().module( "confModule" );
+        new EntityTestAssembler().visibleIn( Visibility.layer ).assemble( confModule );
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+
+        // START SNIPPET: assembly
+        new EhCacheAssembler()
+            .withConfig( confModule, Visibility.layer )
+            .assemble( module );
+    }
+    // END SNIPPET: assembly
+}
diff --git a/extensions/cache-ehcache/src/test/java/org/qi4j/cache/ehcache/EhCacheTest.java b/extensions/cache-ehcache/src/test/java/org/qi4j/cache/ehcache/EhCacheTest.java
deleted file mode 100644
index 72b62ba..0000000
--- a/extensions/cache-ehcache/src/test/java/org/qi4j/cache/ehcache/EhCacheTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2010 Niclas Hedhman.
- *
- * Licensed  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.qi4j.cache.ehcache;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.cache.ehcache.assembly.EhCacheAssembler;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.cache.AbstractCachePoolTest;
-
-public class EhCacheTest
-    extends AbstractCachePoolTest
-{
-    @Override
-    // START SNIPPET: assembly
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-	    // END SNIPPET: assembly
-        ModuleAssembly confModule = module.layer().module( "confModule" );
-        new EntityTestAssembler().visibleIn( Visibility.layer ).assemble( confModule );
-
-        // START SNIPPET: assembly
-        new EhCacheAssembler().
-            withConfig( confModule, Visibility.layer ).
-            assemble( module );
-    }
-    // END SNIPPET: assembly
-}
diff --git a/extensions/cache-memcache/build.gradle b/extensions/cache-memcache/build.gradle
index c78356f..8aa67a7 100644
--- a/extensions/cache-memcache/build.gradle
+++ b/extensions/cache-memcache/build.gradle
@@ -1,34 +1,37 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Memcache Cache Extension"
+apply plugin: 'polygene-extension'
 
-jar { manifest { name = "Apache Zest™ Extension - Cache - Memcache"}}
+description = "Apache Polygene™ Memcache Cache Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - Cache - Memcache" } }
 
 dependencies {
+  api polygene.core.bootstrap
 
-    compile project( ':org.qi4j.core:org.qi4j.core.bootstrap' )
-    compile libraries.spymemcached
+  implementation libraries.spymemcached
 
-    testCompile project( ':org.qi4j.core:org.qi4j.core.testsupport' )
+  runtimeOnly polygene.core.runtime
 
-    testRuntime project( ':org.qi4j.core:org.qi4j.core.runtime' )
-    testRuntime libraries.logback
+  testImplementation polygene.internals.testsupport
 
+  testRuntimeOnly libraries.logback
 }
diff --git a/extensions/cache-memcache/dev-status.xml b/extensions/cache-memcache/dev-status.xml
index b863976..e6cf5af 100644
--- a/extensions/cache-memcache/dev-status.xml
+++ b/extensions/cache-memcache/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
         <!--none,early,beta,stable,mature-->
         <codebase>beta</codebase>
diff --git a/extensions/cache-memcache/src/docs/cache-memcache.txt b/extensions/cache-memcache/src/docs/cache-memcache.txt
index 5cd5081..ef2adf3 100644
--- a/extensions/cache-memcache/src/docs/cache-memcache.txt
+++ b/extensions/cache-memcache/src/docs/cache-memcache.txt
@@ -47,7 +47,7 @@
 
 [snippet,java]
 ----
-source=extensions/cache-memcache/src/test/java/org/qi4j/cache/memcache/MemcacheCachePoolTest.java
+source=extensions/cache-memcache/src/test/java/org/apache/polygene/cache/memcache/MemcacheCachePoolTest.java
 tag=assembly
 ----
 
@@ -58,7 +58,7 @@
 
 [snippet,java]
 ----
-source=extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/MemcacheConfiguration.java
+source=extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/MemcacheConfiguration.java
 tag=config
 ----
 
diff --git a/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/MemcacheConfiguration.java b/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/MemcacheConfiguration.java
new file mode 100644
index 0000000..2663907
--- /dev/null
+++ b/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/MemcacheConfiguration.java
@@ -0,0 +1,80 @@
+/*
+ *  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.polygene.cache.memcache;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Memcache CachePool Configuration.
+ */
+// START SNIPPET: config
+public interface MemcacheConfiguration
+{
+    /**
+     * Cached items expiration in seconds.
+     * Defaulted to 3600 seconds, one hour.
+     * @return Cached items expiration configuration property
+     */
+    @Optional
+    Property<Integer> expiration();
+
+    /**
+     * Memcached server addresses space separated.
+     * Eg. {@literal "server1:11211 server2:11211"}.
+     * Defaulted to {@literal "127.0.0.1:11211"}.
+     * @return Memcached server addresses configuration property
+     */
+    @Optional
+    Property<String> addresses();
+
+    /**
+     * Memcache Protocol.
+     * Can be {@literal text} or {@literal binary}
+     * Defaulted to {@literal text}.
+     * @return Memcache Protocol configuration property
+     */
+    @Optional
+    Property<String> protocol();
+
+    /**
+     * Username.
+     * Authentication happens only if set.
+     * @return Username configuration property
+     */
+    @Optional
+    Property<String> username();
+
+    /**
+     * Password.
+     * @return Password configuration property
+     */
+    @Optional
+    Property<String> password();
+
+    /**
+     * SASL authentication mechanism.
+     * Defaulted to PLAIN.
+     * @return Authentication mechanism configuration property
+     */
+    @Optional
+    Property<String> authMechanism();
+}
+// END SNIPPET: config
diff --git a/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/MemcacheImpl.java b/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/MemcacheImpl.java
new file mode 100644
index 0000000..416147a
--- /dev/null
+++ b/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/MemcacheImpl.java
@@ -0,0 +1,112 @@
+/*
+ *  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.polygene.cache.memcache;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import net.spy.memcached.MemcachedClient;
+import net.spy.memcached.transcoders.SerializingTranscoder;
+import org.apache.polygene.spi.cache.Cache;
+
+/**
+ * Memcache Implementation.
+ * Use Java Serialization under the hood.
+ * @param <T> Parameterized Type of cached entries
+ */
+/* package */ class MemcacheImpl<T>
+    implements Cache<T>
+{
+    private static final AtomicInteger INSTANCES = new AtomicInteger();
+    private final MemcachedClient client;
+    private final String cacheId;
+    private final String cachePrefix;
+    private final Class<T> valueType;
+    private final int expiration;
+    private int refCount;
+
+    /* package */ MemcacheImpl( MemcachedClient client, String cacheId, Class<T> valueType, int expiration )
+    {
+        this.client = client;
+        this.cacheId = cacheId;
+        this.cachePrefix = cacheId + "." + INSTANCES.incrementAndGet() + ".";
+        this.valueType = valueType;
+        this.expiration = expiration;
+    }
+
+    @Override
+    public T get( String key )
+    {
+        Object value = client.get( prefix( key ), new SerializingTranscoder() );
+        client.touch( prefix( key ), expiration );
+        if( value == null )
+        {
+            return null;
+        }
+        return valueType.cast( value );
+    }
+
+    @Override
+    public T remove( String key )
+    {
+        String prefixedKey = prefix( key );
+        Object old = client.get( prefixedKey, new SerializingTranscoder() );
+        if( old != null )
+        {
+            client.delete( prefixedKey );
+        }
+        return valueType.cast( old );
+    }
+
+    @Override
+    public void put( String key, T value )
+    {
+        client.set( prefix( key ), expiration, value, new SerializingTranscoder() );
+    }
+
+    @Override
+    public boolean exists( String key )
+    {
+        return client.get( prefix( key ) ) != null;
+    }
+
+    private String prefix( String key )
+    {
+        return cachePrefix + key;
+    }
+
+    synchronized void decRefCount()
+    {
+        refCount--;
+    }
+
+    synchronized void incRefCount()
+    {
+        refCount++;
+    }
+
+    synchronized boolean isNotUsed()
+    {
+        return refCount == 0;
+    }
+
+    public String cacheId()
+    {
+        return cacheId;
+    }
+}
diff --git a/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/MemcachePoolMixin.java b/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/MemcachePoolMixin.java
new file mode 100644
index 0000000..dabaea0
--- /dev/null
+++ b/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/MemcachePoolMixin.java
@@ -0,0 +1,134 @@
+/*
+ *  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.polygene.cache.memcache;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import net.spy.memcached.AddrUtil;
+import net.spy.memcached.ConnectionFactoryBuilder;
+import net.spy.memcached.ConnectionFactoryBuilder.Protocol;
+import net.spy.memcached.MemcachedClient;
+import net.spy.memcached.auth.AuthDescriptor;
+import net.spy.memcached.auth.PlainCallbackHandler;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.spi.cache.Cache;
+
+/**
+ * Memcache CachePool Mixin.
+ */
+public class MemcachePoolMixin
+    implements MemcachePoolService
+{
+    private final Map<String, MemcacheImpl<?>> caches = new HashMap<>();
+    @This @Optional
+    private Configuration<MemcacheConfiguration> configuration;
+    private MemcachedClient client;
+    private int expiration;
+
+    @Override
+    public void activateService()
+        throws Exception
+    {
+        if( configuration != null )
+        {
+            MemcacheConfiguration config = configuration.get();
+            expiration = ( config.expiration().get() == null )
+                         ? 3600
+                         : config.expiration().get();
+            String addresses = ( config.addresses().get() == null )
+                               ? "localhost:11211"
+                               : config.addresses().get();
+            Protocol protocol = ( config.protocol().get() == null )
+                                ? Protocol.TEXT
+                                : Protocol.valueOf( config.protocol().get().toUpperCase() );
+            String username = config.username().get();
+            String password = config.password().get();
+            String authMech = config.authMechanism().get() == null
+                              ? "PLAIN"
+                              : config.authMechanism().get();
+
+            ConnectionFactoryBuilder builder = new ConnectionFactoryBuilder();
+            builder.setProtocol( protocol );
+            if( username != null && !username.isEmpty() )
+            {
+                builder.setAuthDescriptor(
+                    new AuthDescriptor(
+                        new String[]
+                        {
+                            authMech
+                        },
+                        new PlainCallbackHandler( username, password )
+                    )
+                );
+            }
+
+            client = new MemcachedClient( builder.build(), AddrUtil.getAddresses( addresses ) );
+        }
+    }
+
+    @Override
+    public void passivateService()
+        throws Exception
+    {
+        if( client != null )
+        {
+            client.shutdown();
+        }
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> Cache<T> fetchCache( String cacheId, Class<T> valueType )
+    {
+        Objects.requireNonNull( cacheId, "cacheId" );
+        if( cacheId.isEmpty() )
+        {
+            throw new IllegalArgumentException( "cacheId was empty string" );
+        }
+        synchronized( caches )
+        {
+            MemcacheImpl<?> cache = caches.get( cacheId );
+            if( cache == null )
+            {
+                cache = new MemcacheImpl<>( client, cacheId, valueType, expiration );
+                caches.put( cacheId, cache );
+            }
+            cache.incRefCount();
+            return (Cache<T>) cache;
+        }
+    }
+
+    @Override
+    public void returnCache( Cache<?> cache )
+    {
+        MemcacheImpl<?> memcache = (MemcacheImpl<?>) cache;
+        memcache.decRefCount();
+        synchronized( caches )
+        {
+            if( memcache.isNotUsed() )
+            {
+                caches.remove( memcache.cacheId() );
+            }
+        }
+    }
+}
diff --git a/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/MemcachePoolService.java b/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/MemcachePoolService.java
new file mode 100644
index 0000000..1ca90c8
--- /dev/null
+++ b/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/MemcachePoolService.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.cache.memcache;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.spi.cache.CachePool;
+
+/**
+ * Memcache CachePool Service.
+ */
+@Mixins( MemcachePoolMixin.class )
+public interface MemcachePoolService
+    extends CachePool, ServiceActivation
+{
+}
diff --git a/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/assembly/MemcacheAssembler.java b/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/assembly/MemcacheAssembler.java
new file mode 100644
index 0000000..e2cbc11
--- /dev/null
+++ b/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/assembly/MemcacheAssembler.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.cache.memcache.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.cache.memcache.MemcacheConfiguration;
+import org.apache.polygene.cache.memcache.MemcachePoolService;
+
+/**
+ * Memcache CachePool Assembler.
+ */
+public class MemcacheAssembler
+    extends Assemblers.VisibilityIdentityConfig<MemcacheAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( MemcachePoolService.class ).visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+        if( hasConfig() )
+        {
+            configModule().entities( MemcacheConfiguration.class ).visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/package.html b/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/package.html
new file mode 100644
index 0000000..796db5d
--- /dev/null
+++ b/extensions/cache-memcache/src/main/java/org/apache/polygene/cache/memcache/package.html
@@ -0,0 +1,42 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Memcache EntityStore CachePool.</h2>
+        <p>Memcache has no namespace support. In addition to that, the protocol disallow key listing.</p>
+        <p>The CachePool contract is to drop a cache once all of its references have been returned.</p>
+        <p>Therefore, all keys are prefixed, that way;</p>
+        <pre>cacheId.cacheInstanceId.key</pre>
+        <ul>
+            <li><code>cacheId</code> is the identity of the requested cache</li>
+            <li><code>cacheInstanceId</code> is an autogenerated cache instance identifier</li>
+            <li><code>key</code> is the original key</li>
+        </ul>
+        <p>
+            In other words and for a given <code>cacheId</code>, once all references of the Cache are returned to the
+            CachePool, the next <code>fetchCache(..)</code> invocation will generate a new Cache instance identifier and
+            hence use different prefixed keys.
+        </p>
+        <p>
+            All this allow the Memcache EntityStore CachePool to conform to the CachePool contract despite limitations
+            of the Memcache protocol.
+        </p>
+    </body>
+</html>
diff --git a/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/MemcacheAssembler.java b/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/MemcacheAssembler.java
deleted file mode 100644
index 220d4be..0000000
--- a/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/MemcacheAssembler.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.cache.memcache;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-
-/**
- * Memcache CachePool Assembler.
- */
-public class MemcacheAssembler
-    extends Assemblers.VisibilityIdentityConfig<MemcacheAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ServiceDeclaration service = module.services( MemcachePoolService.class ).visibleIn( visibility() );
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        if( hasConfig() )
-        {
-            configModule().entities( MemcacheConfiguration.class ).visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/MemcacheConfiguration.java b/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/MemcacheConfiguration.java
deleted file mode 100644
index 8e4518f..0000000
--- a/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/MemcacheConfiguration.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.cache.memcache;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.property.Property;
-
-/**
- * Memcache CachePool Configuration.
- */
-// START SNIPPET: config
-public interface MemcacheConfiguration
-    extends Configuration<MemcachePoolService>
-{
-    /**
-     * Cached items expiration in seconds.
-     * Defaulted to 3600 seconds, one hour.
-     * @return Cached items expiration configuration property
-     */
-    @Optional
-    Property<Integer> expiration();
-
-    /**
-     * Memcached server addresses space separated.
-     * Eg. {@literal "server1:11211 server2:11211"}.
-     * Defaulted to {@literal "127.0.0.1:11211"}.
-     * @return Memcached server addresses configuration property
-     */
-    @Optional
-    Property<String> addresses();
-
-    /**
-     * Memcache Protocol.
-     * Can be {@literal text} or {@literal binary}
-     * Defaulted to {@literal text}.
-     * @return Memcache Protocol configuration property
-     */
-    @Optional
-    Property<String> protocol();
-
-    /**
-     * Username.
-     * Authentication happens only if set.
-     * @return Username configuration property
-     */
-    @Optional
-    Property<String> username();
-
-    /**
-     * Password.
-     * @return Password configuration property
-     */
-    @Optional
-    Property<String> password();
-
-    /**
-     * SASL authentication mechanism.
-     * Defaulted to PLAIN.
-     * @return Authentication mechanism configuration property
-     */
-    @Optional
-    Property<String> authMechanism();
-}
-// END SNIPPET: config
diff --git a/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/MemcacheImpl.java b/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/MemcacheImpl.java
deleted file mode 100644
index 76af8b0..0000000
--- a/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/MemcacheImpl.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.cache.memcache;
-
-import java.util.concurrent.atomic.AtomicInteger;
-import net.spy.memcached.MemcachedClient;
-import net.spy.memcached.transcoders.SerializingTranscoder;
-import org.qi4j.spi.cache.Cache;
-
-/**
- * Memcache Implementation.
- * Use Java Serialization under the hood.
- * @param <T> Parameterized Type of cached entries
- */
-/* package */ class MemcacheImpl<T>
-    implements Cache<T>
-{
-    private static final AtomicInteger INSTANCES = new AtomicInteger();
-    private final MemcachedClient client;
-    private final String cacheId;
-    private final String cachePrefix;
-    private final Class<T> valueType;
-    private final int expiration;
-    private int refCount;
-
-    /* package */ MemcacheImpl( MemcachedClient client, String cacheId, Class<T> valueType, int expiration )
-    {
-        this.client = client;
-        this.cacheId = cacheId;
-        this.cachePrefix = cacheId + "." + INSTANCES.incrementAndGet() + ".";
-        this.valueType = valueType;
-        this.expiration = expiration;
-    }
-
-    @Override
-    public T get( String key )
-    {
-        Object value = client.get( prefix( key ), new SerializingTranscoder() );
-        client.touch( prefix( key ), expiration );
-        if( value == null )
-        {
-            return null;
-        }
-        return valueType.cast( value );
-    }
-
-    @Override
-    public T remove( String key )
-    {
-        String prefixedKey = prefix( key );
-        Object old = client.get( prefixedKey, new SerializingTranscoder() );
-        if( old != null )
-        {
-            client.delete( prefixedKey );
-        }
-        return valueType.cast( old );
-    }
-
-    @Override
-    public void put( String key, T value )
-    {
-        client.set( prefix( key ), expiration, value, new SerializingTranscoder() );
-    }
-
-    @Override
-    public boolean exists( String key )
-    {
-        return client.get( prefix( key ) ) != null;
-    }
-
-    private String prefix( String key )
-    {
-        return cachePrefix + key;
-    }
-
-    synchronized void decRefCount()
-    {
-        refCount--;
-    }
-
-    synchronized void incRefCount()
-    {
-        refCount++;
-    }
-
-    synchronized boolean isNotUsed()
-    {
-        return refCount == 0;
-    }
-
-    public String cacheId()
-    {
-        return cacheId;
-    }
-}
diff --git a/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/MemcachePoolMixin.java b/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/MemcachePoolMixin.java
deleted file mode 100644
index c93f35e..0000000
--- a/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/MemcachePoolMixin.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.cache.memcache;
-
-import java.util.HashMap;
-import java.util.Map;
-import net.spy.memcached.AddrUtil;
-import net.spy.memcached.ConnectionFactoryBuilder;
-import net.spy.memcached.ConnectionFactoryBuilder.Protocol;
-import net.spy.memcached.MemcachedClient;
-import net.spy.memcached.auth.AuthDescriptor;
-import net.spy.memcached.auth.PlainCallbackHandler;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.spi.cache.Cache;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotEmpty;
-
-/**
- * Memcache CachePool Mixin.
- */
-public class MemcachePoolMixin
-    implements MemcachePoolService
-{
-    private final Map<String, MemcacheImpl<?>> caches = new HashMap<>();
-    @This @Optional
-    private Configuration<MemcacheConfiguration> configuration;
-    private MemcachedClient client;
-    private int expiration;
-
-    @Override
-    public void activateService()
-        throws Exception
-    {
-        if( configuration != null )
-        {
-            MemcacheConfiguration config = configuration.get();
-            expiration = ( config.expiration().get() == null )
-                         ? 3600
-                         : config.expiration().get();
-            String addresses = ( config.addresses().get() == null )
-                               ? "localhost:11211"
-                               : config.addresses().get();
-            Protocol protocol = ( config.protocol().get() == null )
-                                ? Protocol.TEXT
-                                : Protocol.valueOf( config.protocol().get().toUpperCase() );
-            String username = config.username().get();
-            String password = config.password().get();
-            String authMech = config.authMechanism().get() == null
-                              ? "PLAIN"
-                              : config.authMechanism().get();
-
-            ConnectionFactoryBuilder builder = new ConnectionFactoryBuilder();
-            builder.setProtocol( protocol );
-            if( username != null && !username.isEmpty() )
-            {
-                builder.setAuthDescriptor(
-                    new AuthDescriptor(
-                        new String[]
-                        {
-                            authMech
-                        },
-                        new PlainCallbackHandler( username, password )
-                    )
-                );
-            }
-
-            client = new MemcachedClient( builder.build(), AddrUtil.getAddresses( addresses ) );
-        }
-    }
-
-    @Override
-    public void passivateService()
-        throws Exception
-    {
-        if( client != null )
-        {
-            client.shutdown();
-        }
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public <T> Cache<T> fetchCache( String cacheId, Class<T> valueType )
-    {
-        validateNotEmpty( "cacheId", cacheId );
-        synchronized( caches )
-        {
-            MemcacheImpl<?> cache = caches.get( cacheId );
-            if( cache == null )
-            {
-                cache = new MemcacheImpl<>( client, cacheId, valueType, expiration );
-                caches.put( cacheId, cache );
-            }
-            cache.incRefCount();
-            return (Cache<T>) cache;
-        }
-    }
-
-    @Override
-    public void returnCache( Cache<?> cache )
-    {
-        MemcacheImpl<?> memcache = (MemcacheImpl<?>) cache;
-        memcache.decRefCount();
-        synchronized( caches )
-        {
-            if( memcache.isNotUsed() )
-            {
-                caches.remove( memcache.cacheId() );
-            }
-        }
-    }
-}
diff --git a/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/MemcachePoolService.java b/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/MemcachePoolService.java
deleted file mode 100644
index a953489..0000000
--- a/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/MemcachePoolService.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.cache.memcache;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.spi.cache.CachePool;
-
-/**
- * Memcache CachePool Service.
- */
-@Mixins( MemcachePoolMixin.class )
-public interface MemcachePoolService
-    extends CachePool, ServiceActivation
-{
-}
diff --git a/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/package.html b/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/package.html
deleted file mode 100644
index 75f2343..0000000
--- a/extensions/cache-memcache/src/main/java/org/qi4j/cache/memcache/package.html
+++ /dev/null
@@ -1,39 +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.
--->
-<html>
-    <body>
-        <h2>Memcache EntityStore CachePool.</h2>
-        <p>Memcache has no namespace support. In addition to that, the protocol disallow key listing.</p>
-        <p>The CachePool contract is to drop a cache once all of its references have been returned.</p>
-        <p>Therefore, all keys are prefixed, that way;</p>
-        <pre>cacheId.cacheInstanceId.key</pre>
-        <ul>
-            <li><code>cacheId</code> is the identity of the requested cache</li>
-            <li><code>cacheInstanceId</code> is an autogenerated cache instance identifier</li>
-            <li><code>key</code> is the original key</li>
-        </ul>
-        <p>
-            In other words and for a given <code>cacheId</code>, once all references of the Cache are returned to the
-            CachePool, the next <code>fetchCache(..)</code> invocation will generate a new Cache instance identifier and
-            hence use different prefixed keys.
-        </p>
-        <p>
-            All this allow the Memcache EntityStore CachePool to conform to the CachePool contract despite limitations
-            of the Memcache protocol.
-        </p>
-    </body>
-</html>
diff --git a/extensions/cache-memcache/src/test/java/org/apache/polygene/cache/memcache/MemcacheCachePoolTest.java b/extensions/cache-memcache/src/test/java/org/apache/polygene/cache/memcache/MemcacheCachePoolTest.java
new file mode 100644
index 0000000..7843eb3
--- /dev/null
+++ b/extensions/cache-memcache/src/test/java/org/apache/polygene/cache/memcache/MemcacheCachePoolTest.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.cache.memcache;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.cache.memcache.assembly.MemcacheAssembler;
+import org.apache.polygene.test.internal.DockerRule;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.cache.AbstractCachePoolTest;
+import org.junit.ClassRule;
+
+/**
+ * Memcache CachePool Test.
+ */
+public class MemcacheCachePoolTest
+    extends AbstractCachePoolTest
+{
+    @ClassRule
+    public static final DockerRule DOCKER = new DockerRule( "memcached", 11211 );
+
+    @Override
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // END SNIPPET: assembly
+        ModuleAssembly confModule = module.layer().module( "confModule" );
+        new EntityTestAssembler().visibleIn( Visibility.layer ).assemble( confModule );
+        // START SNIPPET: assembly
+        new MemcacheAssembler().
+            visibleIn( Visibility.module ).
+            withConfig( confModule, Visibility.layer ).
+            assemble( module );
+        // END SNIPPET: assembly
+        MemcacheConfiguration memcacheConf = confModule.forMixin( MemcacheConfiguration.class ).declareDefaults();
+        String dockerHost = DOCKER.getDockerHost();
+        int dockerPort = DOCKER.getExposedContainerPort( "11211/tcp" );
+        memcacheConf.addresses().set( dockerHost + ':' + dockerPort );
+        memcacheConf.protocol().set( "binary" );
+        // START SNIPPET: assembly
+    }
+    // END SNIPPET: assembly
+}
diff --git a/extensions/cache-memcache/src/test/java/org/qi4j/cache/memcache/MemcacheCachePoolTest.java b/extensions/cache-memcache/src/test/java/org/qi4j/cache/memcache/MemcacheCachePoolTest.java
deleted file mode 100644
index c1d6c5a..0000000
--- a/extensions/cache-memcache/src/test/java/org/qi4j/cache/memcache/MemcacheCachePoolTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.cache.memcache;
-
-import org.junit.BeforeClass;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.cache.AbstractCachePoolTest;
-
-import static org.qi4j.test.util.Assume.assumeConnectivity;
-
-/**
- * Memcache CachePool Test.
- */
-public class MemcacheCachePoolTest
-    extends AbstractCachePoolTest
-{
-    @BeforeClass
-    public static void beforeMemcacheCacheTests()
-    {
-        assumeConnectivity( "localhost", 11211 );
-    }
-
-    @Override
-    // START SNIPPET: assembly
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // END SNIPPET: assembly
-        ModuleAssembly confModule = module.layer().module( "confModule" );
-        new EntityTestAssembler().visibleIn( Visibility.layer ).assemble( confModule );
-        // START SNIPPET: assembly
-        new MemcacheAssembler().
-            visibleIn( Visibility.module ).
-            withConfig( confModule, Visibility.layer ).
-            assemble( module );
-        // END SNIPPET: assembly
-        MemcacheConfiguration memcacheConf = confModule.forMixin( MemcacheConfiguration.class ).declareDefaults();
-        memcacheConf.protocol().set( "binary" );
-        //memcacheConf.username().set( "foo" );
-        //memcacheConf.password().set( "bar" );
-        // START SNIPPET: assembly
-    }
-    // END SNIPPET: assembly
-}
diff --git a/extensions/entitystore-cassandra/build.gradle b/extensions/entitystore-cassandra/build.gradle
new file mode 100644
index 0000000..b1f32a8
--- /dev/null
+++ b/extensions/entitystore-cassandra/build.gradle
@@ -0,0 +1,39 @@
+/*
+ *  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.
+ *
+ *
+ */
+
+apply plugin: 'polygene-extension'
+
+description = "Apache Polygene™ Cassandra EntityStore Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - EntityStore - Cassandra" } }
+
+dependencies {
+  api polygene.core.bootstrap
+  api libraries.cassandra_client
+
+  implementation polygene.library( 'locking' )
+  implementation libraries.jackson_mapper
+
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.internals.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/extensions/entitystore-cassandra/dev-status.xml b/extensions/entitystore-cassandra/dev-status.xml
new file mode 100644
index 0000000..c0ac593
--- /dev/null
+++ b/extensions/entitystore-cassandra/dev-status.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
+  <status>
+        <!--none,early,beta,stable,mature-->
+        <codebase>early</codebase>
+
+        <!-- none, brief, good, complete -->
+        <documentation>good</documentation>
+
+        <!-- none, some, good, complete -->
+        <unittests>good</unittests>
+    </status>
+    <licenses>
+        <license>ALv2</license>
+    </licenses>
+</module>
diff --git a/extensions/entitystore-cassandra/src/docs/es-cassandra.txt b/extensions/entitystore-cassandra/src/docs/es-cassandra.txt
new file mode 100644
index 0000000..e28fe64
--- /dev/null
+++ b/extensions/entitystore-cassandra/src/docs/es-cassandra.txt
@@ -0,0 +1,117 @@
+///////////////////////////////////////////////////////////////
+ * 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.
+///////////////////////////////////////////////////////////////
+
+[[extension-es-cassandra,Cassandra EntityStore]]
+= Cassandra EntityStore =
+
+[devstatus]
+--------------
+source=extensions/entitystore-cassandra/dev-status.xml
+--------------
+
+EntityStore service backed by a http://cassandra.apache.org/ in which Entity state is stored in single rows of a
+single table.
+
+include::../../build/docs/buildinfo/artifact.txt[]
+
+== Assembly ==
+
+Assembly is done using the provided Assembler:
+
+[snippet,java]
+----
+source=extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/CassandraMapEntityStoreTest.java
+tag=assembly
+----
+
+=== Custom Cluster Client ===
+There are many options in Apache Cassandra on how the cluster is set up and how to connect to it. Instead of mapping
+all possible features, a ClusterBuilder type, which by default sets it up according to this page. By overriding the
+DefaultBuilder mixin, on the CassandraCluster composite, it is possible to provide your configuration.
+
+[snippet,java]
+----
+source=extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/DocSupport.java
+tag=assembly
+----
+
+And we then have a choice to override any of the provided extension points in DefaultBuilder. For instance;
+
+[snippet,java]
+----
+source=extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/DocSupport.java
+tag=builder
+----
+
+Of course, it is possible to simply override the entire Mixin and not subtype it at all.
+
+== Configuration ==
+
+Here are the configuration properties for the Cassandra EntityStore:
+
+[snippet,java]
+----
+source=extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreConfiguration.java
+tag=config
+----
+
+== Cassandra Authentication ==
+It is possible to configure Cassandra with many types of authentication. User/password is provided in this library's
+configuration, and for more advanced setups, you need to provide an implementation of com.datastax.driver.core.AuthProvider
+as a Polygene service (and visible to the ClusterBuilder as usual).
+
+== Cassandra Keyspace ==
+The Cassandra EntityStore can either use an existing Cassandra Keyspace, which is the default, OR create its own
+keyspace.
+
+The CassandraEntityStoreConfiguration#keyspaceName() defines the name of the keyspace to use, or to be created. If not
+defined, then the default name is "polygene".
+
+The CassandraEntityStoreConfiguration#createIfMissing() defines if new missing resources should be created or an
+Exception should be thrown if missing.
+
+If the keyspace is created, then the CassandraEntityStoreConfiguration#replicationFactor() will define the replication
+factor, defaults to 3, and the command to create the keyspace is;
+
+[source]
+-----------------
+    CREATE KEYSPACE &lt;keyspaceName&gt; WITH replication = {'class':'SimpleStrategy', 'replication_factor' : &lt;replicationFactor&gt; };
+-----------------
+
+== Polygene's Cassandra Table ==
+
+Polygene will store all entities in a single Cassandra TABLE
+
+[source]
+-----------------
+    CREATE TABLE &lt;tableName&gt; (
+        id text,
+        version text,
+        type text,
+        appversion text,
+        storeversion text,
+        usecase text,
+        modified timestamp,
+        properties map&lt;string,string&gt;
+        assocs map&lt;string,string&gt;
+        manyassocs map&lt;string,string&gt;
+        namedassocs map&lt;string,string&gt;
+        PRIMARY KEY ( id )
+    );
+-----------------
diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraCluster.java b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraCluster.java
new file mode 100644
index 0000000..c707652
--- /dev/null
+++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraCluster.java
@@ -0,0 +1,246 @@
+/*
+ *  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.polygene.entitystore.cassandra;
+
+import com.datastax.driver.core.AuthProvider;
+import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.KeyspaceMetadata;
+import com.datastax.driver.core.PreparedStatement;
+import com.datastax.driver.core.Session;
+import com.datastax.driver.core.exceptions.AlreadyExistsException;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+
+@Mixins( CassandraCluster.Mixin.class )
+public interface CassandraCluster
+{
+    String IDENTITY_COLUMN = "id";
+    String STORE_VERSION_COLUMN = "storeversion";
+    String VERSION_COLUMN = "version";
+    String APP_VERSION_COLUMN = "appversion";
+    String USECASE_COLUMN = "usecase";
+    String LASTMODIFIED_COLUMN = "modified";
+    String TYPE_COLUMN = "type";
+    String PROPERTIES_COLUMN = "props";
+    String ASSOCIATIONS_COLUMN = "assocs";
+    String MANYASSOCIATIONS_COLUMN = "manyassocs";
+    String NAMEDASSOCIATIONS_COLUMN = "namedassocs";
+
+    String tableName();
+
+    Session cassandraClientSession();
+
+    PreparedStatement entityRetrieveStatement();
+
+    PreparedStatement versionRetrieveStatement();
+
+    PreparedStatement entityUpdateStatement();
+
+    String keyspaceName();
+
+    void activate()
+        throws Exception;
+
+    void passivate()
+        throws Exception;
+
+    class Mixin
+        implements CassandraCluster
+    {
+        @This
+        private Configuration<CassandraEntityStoreConfiguration> configuration;
+
+        @Service
+        @Optional
+        private AuthProvider authProvider;
+
+        @This
+        private ClusterBuilder clusterBuilder;
+
+        private Cluster cluster;
+        private Session session;
+        private String keyspaceName;
+        private PreparedStatement getEntityStatement;
+        private PreparedStatement updateEntityStatement;
+        private PreparedStatement getVersionStatement;
+
+        @Override
+        public PreparedStatement entityRetrieveStatement()
+        {
+            return getEntityStatement;
+        }
+
+        @Override
+        public PreparedStatement versionRetrieveStatement()
+        {
+            return getVersionStatement;
+        }
+
+        @Override
+        public PreparedStatement entityUpdateStatement()
+        {
+            return updateEntityStatement;
+        }
+
+        @Override
+        public String keyspaceName()
+        {
+            return keyspaceName;
+        }
+
+        @Override
+        public Session cassandraClientSession()
+        {
+            return session;
+        }
+
+        public String tableName()
+        {
+            CassandraEntityStoreConfiguration config = configuration.get();
+            String tableName = config.entityTableName().get();
+            if( tableName == null || tableName.isEmpty() )
+            {
+                tableName = CassandraEntityStoreService.DEFAULT_TABLE_NAME;
+            }
+            return tableName;
+        }
+
+        public void activate()
+            throws Exception
+        {
+            configuration.refresh();
+            CassandraEntityStoreConfiguration config = configuration.get();
+            cluster = clusterBuilder.build( config );
+            keyspaceName = config.keySpace().get();
+            if( keyspaceName == null || keyspaceName.isEmpty() )
+            {
+                keyspaceName = CassandraEntityStoreService.DEFAULT_KEYSPACE_NAME;
+            }
+            String tableName = tableName();
+            KeyspaceMetadata keyspace = cluster.getMetadata().getKeyspace( keyspaceName );
+            boolean createIfMissing = config.createIfMissing().get();
+            if( keyspace == null )
+            {
+                if( createIfMissing )
+                {
+                    Integer replication = config.replicationFactor().get();
+                    if( replication == null || replication <= 0 )
+                    {
+                        replication = 3;
+                    }
+                    createKeyspace( keyspaceName, replication );
+                    session = cluster.connect( keyspaceName );
+                }
+                else
+                {
+                    throw new EntityStoreException( "Keyspace '" + keyspaceName + "' does not exist." );
+                }
+            }
+            else
+            {
+                session = cluster.connect( keyspaceName );
+            }
+            session.init();
+            if( createIfMissing )
+            {
+                createPolygeneStateTable( tableName );
+            }
+            getEntityStatement = session.prepare( "SELECT "
+                                                  + IDENTITY_COLUMN + ", "
+                                                  + VERSION_COLUMN + ", "
+                                                  + TYPE_COLUMN + ", "
+                                                  + APP_VERSION_COLUMN + ", "
+                                                  + STORE_VERSION_COLUMN + ", "
+                                                  + LASTMODIFIED_COLUMN + ", "
+                                                  + USECASE_COLUMN + ", "
+                                                  + PROPERTIES_COLUMN + ", "
+                                                  + ASSOCIATIONS_COLUMN + ", "
+                                                  + MANYASSOCIATIONS_COLUMN + ", "
+                                                  + NAMEDASSOCIATIONS_COLUMN
+                                                  + " FROM " + tableName
+                                                  + " WHERE "
+                                                  + IDENTITY_COLUMN + " = ?" );
+
+            getVersionStatement = session.prepare( "SELECT "
+                                                   + VERSION_COLUMN
+                                                   + " FROM " + tableName
+                                                   + " WHERE "
+                                                   + IDENTITY_COLUMN + " = ?" );
+
+            updateEntityStatement = session.prepare( "INSERT INTO " + tableName + "( "
+                                                     + IDENTITY_COLUMN + ", "               // id
+                                                     + VERSION_COLUMN + ", "                // version
+                                                     + TYPE_COLUMN + ", "                   // type
+                                                     + APP_VERSION_COLUMN + ", "            // appversion
+                                                     + STORE_VERSION_COLUMN + ", "          // storeversion
+                                                     + LASTMODIFIED_COLUMN + ", "           // lastmodified
+                                                     + USECASE_COLUMN + ", "                // usecase
+                                                     + PROPERTIES_COLUMN + ", "             // properties
+                                                     + ASSOCIATIONS_COLUMN + ", "           // associations
+                                                     + MANYASSOCIATIONS_COLUMN + ", "       // manyassociations
+                                                     + NAMEDASSOCIATIONS_COLUMN             // namedassociations
+                                                     + " ) VALUES (?,?,?,?,?,?,?,?,?,?,?)" );
+        }
+
+        private void createPolygeneStateTable( String tableName )
+        {
+            try
+            {
+                session.execute( "CREATE TABLE " + tableName + "(\n"
+                                 + "   " + IDENTITY_COLUMN + " text,\n"
+                                 + "   " + VERSION_COLUMN + " text,\n"
+                                 + "   " + TYPE_COLUMN + " text,\n"
+                                 + "   " + APP_VERSION_COLUMN + " text,\n"
+                                 + "   " + STORE_VERSION_COLUMN + " text,\n"
+                                 + "   " + LASTMODIFIED_COLUMN + " timestamp,\n"
+                                 + "   " + USECASE_COLUMN + " text,\n"
+                                 + "   " + PROPERTIES_COLUMN + " map<text,text>,\n"
+                                 + "   " + ASSOCIATIONS_COLUMN + " map<text,text>,\n"
+                                 + "   " + MANYASSOCIATIONS_COLUMN + " map<text,text>,\n"
+                                 + "   " + NAMEDASSOCIATIONS_COLUMN + " map<text,text>,\n"
+                                 + "   PRIMARY KEY ( " + IDENTITY_COLUMN + " )\n"
+                                 + "   )" );
+            }
+            catch( AlreadyExistsException e )
+            {
+                // This is OK, as we try to create on every connect().
+            }
+        }
+
+        private void createKeyspace( String keyspaceName, int replication )
+        {
+            try( Session defaultSession = cluster.connect() )
+            {
+                String query = "CREATE KEYSPACE " + keyspaceName + " WITH replication = {'class':'SimpleStrategy', 'replication_factor' : " + replication + "};";
+                defaultSession.execute( query );
+            }
+        }
+
+        public void passivate()
+            throws Exception
+        {
+            cluster.close();
+        }
+    }
+}
\ No newline at end of file
diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreConfiguration.java b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreConfiguration.java
new file mode 100644
index 0000000..ca257e8
--- /dev/null
+++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreConfiguration.java
@@ -0,0 +1,131 @@
+/*
+ *  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.polygene.entitystore.cassandra;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+// START SNIPPET: config
+public interface CassandraEntityStoreConfiguration
+{
+    /**
+     * A comma or space separated list of <code>hostname:port</code> to the Cassandra cluster.
+     * <p>
+     *     A small list of hostnames should be given, as the client is capable to discover the topology by itself
+     *     and only need one host that it can connect to.
+     * </p>
+     * <p>
+     *     Also not that Cassandra refuse to bind to all interfaces on a host, so you need to know which hostname
+     *     corresponds to the interface that Cassandra is bound to. This may not include 'localhost'.
+     * </p>
+     * @return A comma or space separated list of hostnames (and port) to use to connect to the Cassandra cluster.
+     */
+    @Optional
+    Property<String> hostnames();
+
+    /** The name of the cluster to connect to.
+     *
+     * @return The configured cluster name. Default: "polygene-cluster"
+     */
+    @Optional
+    Property<String> clusterName();
+
+    /** The replication factor to be used, if a KEYSPACE is created.
+     *
+     * @return The replication factor to use in the keyspace if a keyspace is created. Default: 3
+     */
+    @Optional
+    Property<Integer> replicationFactor();
+
+    /**
+     * Username for connecting the client to the Cassandra cluster.
+     * <p>
+     *     The Cassandra client uses the CQL interface.
+     * </p>
+     * @return The Username to use to connect to the Cassandra cluster. If empty, then no user name will be attempted.
+     */
+    @UseDefaults
+    Property<String> username();
+
+    /**
+     * Password for connecting the client to the Cassandra cluster.
+     * <p>
+     *     The Cassandra client uses the CQL interface.
+     * </p>
+     * @return The password to use to connect to the Cassandra cluster. If empty, then no password will be attempted.
+     */
+    @UseDefaults
+    Property<String> password();
+
+    /**
+     * The name of the KEYSPACE to be used.
+     *
+     * @return The name of the KEYSPACE to use If null, then the default <code>KEYSPACE polygene</code> will be used.
+     */
+    @UseDefaults
+    Property<String> keySpace();
+
+    /**
+     * The name of the entity TABLE to be used.
+     * <p>
+     * All entities are stored in the same table, with one entity per row. The required table schema is as follows;
+     * </p>
+     * <pre><code>
+     *     CREATE TABLE entitystore (
+     *         id text,
+     *         version text,
+     *         appversion text,
+     *         storeversion text,
+     *         modified timestamp,
+     *         usecase text,
+     *         props map&lt;text,text&gt;,
+     *         assocs map&lt;text,text&gt;,
+     *         manyassocs map&lt;text,text&gt;,
+     *         namedassocs map&lt;text,text^gt;,
+     *         PRIMARY KEY (id)
+     * );
+     *
+     * </code></pre>
+     *
+     * @return the name of the Entity table. If it returns null the default name of <code>entitystore</code> will be used.
+     */
+    @UseDefaults
+    Property<String> entityTableName();
+
+    /**
+     * Defines whether a KEYSPACE and entity TABLE should be created if not already present in the Cassandra cluster.
+     * <p>
+     * The default keyspace that could be created is defined as follows;
+     * </p>
+     * <pre><code>
+     *     CREATE KEYSPACE sensetif WITH replication = {'class':'SimpleStrategy', 'replication_factor' : $replicationFactor };
+     * </code></pre>
+     * <p>
+     *     The <code>$replicationFactor</code> refers to the {@link CassandraEntityStoreConfiguration#replicationFactor()}
+     *     configuration property above.
+     * </p>
+     *
+     * @return true if the KEYSPACE and TABLE should be created, false if an Exception should be thrown if it is missing.
+     */
+    @UseDefaults
+    Property<Boolean> createIfMissing();
+}
+// END SNIPPET: config
\ No newline at end of file
diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreMixin.java b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreMixin.java
new file mode 100644
index 0000000..80b638a
--- /dev/null
+++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreMixin.java
@@ -0,0 +1,474 @@
+/*
+ *  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.polygene.entitystore.cassandra;
+
+import com.datastax.driver.core.BoundStatement;
+import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.Session;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.IdentityGenerator;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.entity.ManyAssociationState;
+import org.apache.polygene.spi.entity.NamedAssociationState;
+import org.apache.polygene.spi.entitystore.DefaultEntityStoreUnitOfWork;
+import org.apache.polygene.spi.entitystore.EntityNotFoundException;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.EntityStoreSPI;
+import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork;
+import org.apache.polygene.spi.entitystore.StateCommitter;
+import org.apache.polygene.spi.entitystore.helpers.DefaultEntityState;
+import org.apache.polygene.spi.serialization.JsonSerialization;
+
+import static java.util.stream.StreamSupport.stream;
+import static org.apache.polygene.entitystore.cassandra.CassandraCluster.APP_VERSION_COLUMN;
+import static org.apache.polygene.entitystore.cassandra.CassandraCluster.ASSOCIATIONS_COLUMN;
+import static org.apache.polygene.entitystore.cassandra.CassandraCluster.IDENTITY_COLUMN;
+import static org.apache.polygene.entitystore.cassandra.CassandraCluster.LASTMODIFIED_COLUMN;
+import static org.apache.polygene.entitystore.cassandra.CassandraCluster.MANYASSOCIATIONS_COLUMN;
+import static org.apache.polygene.entitystore.cassandra.CassandraCluster.NAMEDASSOCIATIONS_COLUMN;
+import static org.apache.polygene.entitystore.cassandra.CassandraCluster.PROPERTIES_COLUMN;
+import static org.apache.polygene.entitystore.cassandra.CassandraCluster.STORE_VERSION_COLUMN;
+import static org.apache.polygene.entitystore.cassandra.CassandraCluster.TYPE_COLUMN;
+import static org.apache.polygene.entitystore.cassandra.CassandraCluster.USECASE_COLUMN;
+import static org.apache.polygene.entitystore.cassandra.CassandraCluster.VERSION_COLUMN;
+import static org.apache.polygene.entitystore.cassandra.CassandraEntityStoreService.CURRENT_STORAGE_VERSION;
+
+/**
+ * MongoDB implementation of MapEntityStore.
+ */
+public class CassandraEntityStoreMixin
+    implements EntityStore, EntityStoreSPI, ServiceActivation
+{
+
+    @This
+    private CassandraCluster cluster;
+
+    @Structure
+    private Application application;
+
+    @Optional
+    @Service
+    private CassandraMigration migration;
+
+    @Service
+    private JsonSerialization valueSerialization;
+
+    @Optional
+    @Service
+    private IdentityGenerator idGenerator;
+
+    @Override
+    public EntityState newEntityState( EntityStoreUnitOfWork unitOfWork, EntityReference reference, EntityDescriptor entityDescriptor )
+    {
+        return new DefaultEntityState( unitOfWork.currentTime(), reference, entityDescriptor );
+    }
+
+    @Override
+    public EntityState entityStateOf( EntityStoreUnitOfWork unitOfWork, ModuleDescriptor module, EntityReference reference )
+    {
+        return queryFor( cluster.entityRetrieveStatement().bind( reference.identity().toString() ), module, reference );
+    }
+
+    private EntityState queryFor( BoundStatement statement, ModuleDescriptor module, EntityReference reference )
+    {
+        ResultSet result = cluster.cassandraClientSession().execute( statement );
+        Row row = result.one();
+        if( row == null )
+        {
+            throw new EntityNotFoundException( reference );
+        }
+        return deserialize( row, module );
+    }
+
+    private EntityState deserialize( Row row, ModuleDescriptor module )
+    {
+        String version = row.getString( VERSION_COLUMN );
+        Instant lastModifed = row.getTimestamp( LASTMODIFIED_COLUMN ).toInstant();
+        EntityStatus[] status = new EntityStatus[ 1 ];
+        status[ 0 ] = EntityStatus.LOADED;
+
+        // Check if version is correct
+        String currentAppVersion = row.getString( APP_VERSION_COLUMN );
+        if( !currentAppVersion.equals( application.version() ) )
+        {
+            if( migration != null )
+            {
+                migration.migrate( row, application.version(), cluster.cassandraClientSession() );
+                // State may have changed
+                status[ 0 ] = EntityStatus.UPDATED;
+            }
+//            else
+//            {
+            // Do nothing ?? Should we update to newer version? Probably not...
+//            }
+        }
+        String type = row.getString( TYPE_COLUMN );
+
+        EntityDescriptor entityDescriptor = module.entityDescriptor( type );
+        if( entityDescriptor == null )
+        {
+            throw new NoSuchEntityTypeException( type, module.name(), module.typeLookup() );
+        }
+        Map<String, String> storedProperties = row.getMap( PROPERTIES_COLUMN, String.class, String.class );
+        Map<String, String> storedAssociations = row.getMap( ASSOCIATIONS_COLUMN, String.class, String.class );
+        Map<String, String> storedManyassociation = row.getMap( MANYASSOCIATIONS_COLUMN, String.class, String.class );
+        Map<String, String> storedNamedassociation = row.getMap( NAMEDASSOCIATIONS_COLUMN, String.class, String.class );
+
+        Map<QualifiedName, Object> properties = new HashMap<>();
+        entityDescriptor
+            .state()
+            .properties()
+            .forEach(
+                propertyDescriptor ->
+                {
+                    String storedValue;
+                    try
+                    {
+                        storedValue = storedProperties.get( propertyDescriptor.qualifiedName().name() );
+                        if( storedValue == null )
+                        {
+                            properties.remove( propertyDescriptor.qualifiedName() );
+                        }
+                        else
+                        {
+                            Object deserialized = valueSerialization.deserialize( module, propertyDescriptor.valueType(), storedValue );
+                            properties.put( propertyDescriptor.qualifiedName(), deserialized );
+                        }
+                    }
+                    catch( RuntimeException e )
+                    {
+                        // Value not found, or value is corrupt, default it. Is this correct behavior?
+                        Object initialValue = propertyDescriptor.resolveInitialValue( module );
+                        properties.put( propertyDescriptor.qualifiedName(), initialValue );
+                        status[ 0 ] = EntityStatus.UPDATED;
+                    }
+                } );
+
+        Map<QualifiedName, EntityReference> associations = new HashMap<>();
+        entityDescriptor
+            .state()
+            .associations()
+            .forEach(
+                associationType ->
+                {
+                    try
+                    {
+                        String storedValue = storedAssociations.get( associationType.qualifiedName().name() );
+                        EntityReference value = storedValue == null
+                                                ? null
+                                                : EntityReference.parseEntityReference( storedValue );
+                        associations.put( associationType.qualifiedName(), value );
+                    }
+                    catch( RuntimeException e )
+                    {
+                        // Association not found, default it to null
+                        associations.put( associationType.qualifiedName(), null );
+                        status[ 0 ] = EntityStatus.UPDATED;
+                    }
+                } );
+
+        Map<QualifiedName, List<EntityReference>> manyAssociations = new HashMap<>();
+        entityDescriptor
+            .state()
+            .manyAssociations()
+            .forEach(
+                manyAssociationType ->
+                {
+                    List<EntityReference> references = new ArrayList<>();
+                    try
+                    {
+                        String storedValue = storedManyassociation.get( manyAssociationType.qualifiedName().name() );
+                        if( storedValue != null )
+                        {
+                            String[] refs = storedValue.split( "," );
+                            for( String value : refs )
+                            {
+                                EntityReference ref = EntityReference.parseEntityReference( value );
+                                references.add( ref );
+                            }
+                            manyAssociations.put( manyAssociationType.qualifiedName(), references );
+                        }
+                    }
+                    catch( RuntimeException e )
+                    {
+                        // ManyAssociation not found, default to empty one
+                        manyAssociations.put( manyAssociationType.qualifiedName(), references );
+                    }
+                } );
+
+        Map<QualifiedName, Map<String, EntityReference>> namedAssociations = new HashMap<>();
+        entityDescriptor
+            .state()
+            .namedAssociations()
+            .forEach(
+                namedAssociationType ->
+                {
+                    Map<String, EntityReference> references = new LinkedHashMap<>();
+                    try
+                    {
+                        String storedValues = storedNamedassociation.get( namedAssociationType.qualifiedName().name() );
+                        if( storedValues != null )
+                        {
+                            @SuppressWarnings( "unchecked" )
+                            Map<String, String> namedRefs = new ObjectMapper().readValue( storedValues, Map.class );
+                            for( Map.Entry<String, String> entry : namedRefs.entrySet() )
+                            {
+                                String name = entry.getKey();
+                                String value = entry.getValue();
+                                EntityReference ref = EntityReference.parseEntityReference( value );
+                                references.put( name, ref );
+                            }
+                            namedAssociations.put( namedAssociationType.qualifiedName(), references );
+                        }
+                    }
+                    catch( Exception e )
+                    {
+                        // NamedAssociation not found, default to empty one
+                        namedAssociations.put( namedAssociationType.qualifiedName(), references );
+                    }
+                } );
+
+        EntityReference reference = EntityReference.parseEntityReference( storedProperties.get( "identity" ) );
+        return new DefaultEntityState( version,
+                                       lastModifed,
+                                       reference,
+                                       status[ 0 ],
+                                       entityDescriptor,
+                                       properties,
+                                       associations,
+                                       manyAssociations,
+                                       namedAssociations
+        );
+    }
+
+    @Override
+    public String versionOf( EntityStoreUnitOfWork unitOfWork, EntityReference reference )
+    {
+        ResultSet result = cluster.cassandraClientSession().execute( cluster.versionRetrieveStatement().bind( reference.identity().toString() ) );
+        Row row = result.one();
+        return row.getString( VERSION_COLUMN );
+    }
+
+    @Override
+    public StateCommitter applyChanges( EntityStoreUnitOfWork unitOfWork, Iterable<EntityState> state )
+    {
+        return new StateCommitter()
+        {
+            @Override
+            public void commit()
+            {
+
+                stream( state.spliterator(), false )
+                    .filter( entity -> entity.status() == EntityStatus.UPDATED || entity.status() == EntityStatus.NEW )
+                    .forEach(
+                        entityState ->
+                        {
+                            Map<String, String> props = new HashMap<>();
+                            Map<String, String> assocs = new HashMap<>();
+                            Map<String, String> many = new HashMap<>();
+                            Map<String, String> named = new HashMap<>();
+                            serializeProperties( entityState, props );
+                            serializeAssociations( entityState, assocs );
+                            serializeManyAssociations( entityState, many );
+                            serializeNamedAssociations( entityState, named );
+                            String identity = entityState.entityReference().identity().toString();
+                            String ver = entityState.version();
+                            if( entityState.status() == EntityStatus.NEW )
+                            {
+                                ver = "0";
+                            }
+                            else
+                            {
+                                ver = "" + ( Long.parseLong( ver ) + 1 );
+                            }
+                            String appVersion = application.version();
+                            String type = entityState.entityDescriptor().primaryType().getName();
+                            Usecase usecase = unitOfWork.usecase();
+                            String usecaseName = usecase.name();
+                            Instant lastModified = unitOfWork.currentTime();
+                            BoundStatement statement = cluster.entityUpdateStatement().bind(
+                                identity,
+                                ver,
+                                type,
+                                appVersion,
+                                CURRENT_STORAGE_VERSION,
+                                Date.from( lastModified ),
+                                usecaseName,
+                                props,
+                                assocs,
+                                many,
+                                named );
+                            ResultSet result = cluster.cassandraClientSession().execute( statement );
+                            System.out.println( result );
+                        } );
+                String ids = stream( state.spliterator(), false )
+                    .filter( entity -> entity.status() == EntityStatus.REMOVED )
+                    .map( entityState -> "'" + entityState.entityReference().identity().toString() + "'" )
+                    .collect( Collectors.joining( "," ) );
+                if( !ids.isEmpty() )
+                {
+                    cluster.cassandraClientSession().execute( "DELETE FROM " + cluster.tableName() + " WHERE id IN (" + ids + ");" );
+                }
+            }
+
+            private void serializeProperties( EntityState entityState, Map<String, String> props )
+            {
+                Stream<? extends PropertyDescriptor> properties = entityState.entityDescriptor().state().properties();
+                properties.forEach(
+                    descriptor ->
+                    {
+                        Object value = entityState.propertyValueOf( descriptor.qualifiedName() );
+                        if( value != null )
+                        {
+                            String serialized = valueSerialization.serialize( value );
+                            props.put( descriptor.qualifiedName().name(), serialized );
+                        }
+                    } );
+            }
+
+            private void serializeAssociations( EntityState entityState, Map<String, String> assocs )
+            {
+                Stream<? extends AssociationDescriptor> associations = entityState.entityDescriptor().state().associations();
+                associations.forEach(
+                    descriptor ->
+                    {
+                        EntityReference ref = entityState.associationValueOf( descriptor.qualifiedName() );
+                        if( ref != null )
+                        {
+                            assocs.put( descriptor.qualifiedName().name(), ref.toString() );
+                        }
+                    } );
+            }
+
+            private void serializeManyAssociations( EntityState entityState, Map<String, String> many )
+            {
+                Stream<? extends AssociationDescriptor> associations = entityState.entityDescriptor().state().manyAssociations();
+                associations.forEach(
+                    descriptor ->
+                    {
+                        ManyAssociationState references = entityState.manyAssociationValueOf( descriptor.qualifiedName() );
+                        String refs = references.stream().map( EntityReference::toString ).collect( Collectors.joining( "," ) );
+                        many.put( descriptor.qualifiedName().name(), refs );
+                    } );
+            }
+
+            private void serializeNamedAssociations( EntityState entityState, Map<String, String> named )
+            {
+                Stream<? extends AssociationDescriptor> associations = entityState.entityDescriptor().state().namedAssociations();
+                associations.forEach(
+                    descriptor ->
+                    {
+                        NamedAssociationState references = entityState.namedAssociationValueOf( descriptor.qualifiedName() );
+                        Map<String, String> refs =
+                            references.stream()
+                                      .collect(
+                                          Collectors.toMap( Map.Entry::getKey,
+                                                            entry -> entry.getValue().toString() ) );
+                        String serialized = valueSerialization.serialize( refs );
+                        named.put( descriptor.qualifiedName().name(), serialized );
+                    } );
+            }
+
+            @Override
+            public void cancel()
+            {
+            }
+        };
+    }
+
+    @Override
+    public EntityStoreUnitOfWork newUnitOfWork( ModuleDescriptor module, Usecase usecase, Instant currentTime )
+    {
+        Identity newIdentity;
+        if( idGenerator == null )
+        {
+            newIdentity = new StringIdentity( UUID.randomUUID().toString() );
+        }
+        else
+        {
+            newIdentity = idGenerator.generate( UnitOfWork.class );
+        }
+        return new DefaultEntityStoreUnitOfWork( module, this, newIdentity, usecase, currentTime );
+    }
+
+    @Override
+    public Stream<EntityState> entityStates( ModuleDescriptor module )
+    {
+        Session session = cluster.cassandraClientSession();
+        String tableName = cluster.tableName();
+        ResultSet resultSet = session.execute( "SELECT "
+                                               + IDENTITY_COLUMN + ", "
+                                               + VERSION_COLUMN + ", "
+                                               + TYPE_COLUMN + ", "
+                                               + APP_VERSION_COLUMN + ", "
+                                               + STORE_VERSION_COLUMN + ", "
+                                               + LASTMODIFIED_COLUMN + ", "
+                                               + USECASE_COLUMN + ", "
+                                               + PROPERTIES_COLUMN + ", "
+                                               + ASSOCIATIONS_COLUMN + ", "
+                                               + MANYASSOCIATIONS_COLUMN + ", "
+                                               + NAMEDASSOCIATIONS_COLUMN
+                                               + " FROM " + tableName );
+        return stream( resultSet.spliterator(), false ).map( row -> deserialize( row, module ) );
+    }
+
+    @Override
+    public void activateService()
+        throws Exception
+    {
+        cluster.activate();
+    }
+
+    @Override
+    public void passivateService()
+        throws Exception
+    {
+        cluster.passivate();
+    }
+}
diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreService.java b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreService.java
new file mode 100644
index 0000000..992f15e
--- /dev/null
+++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraEntityStoreService.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.entitystore.cassandra;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.library.locking.LockingAbstractComposite;
+import org.apache.polygene.spi.entitystore.ConcurrentModificationCheckConcern;
+import org.apache.polygene.spi.entitystore.EntityStateVersions;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.StateChangeNotificationConcern;
+
+/**
+ * Cassandra EntityStore service.
+ */
+@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
+@Mixins( { CassandraEntityStoreMixin.class } )
+public interface CassandraEntityStoreService
+    extends EntityStore,
+            EntityStateVersions,
+            ServiceActivation,
+            LockingAbstractComposite,
+            Configuration
+{
+    String CURRENT_STORAGE_VERSION = "1";
+    String DEFAULT_KEYSPACE_NAME = "polygene";
+    String DEFAULT_TABLE_NAME = "entitystore";
+
+}
diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraMigration.java b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraMigration.java
new file mode 100644
index 0000000..72b4060
--- /dev/null
+++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/CassandraMigration.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.entitystore.cassandra;
+
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.Session;
+
+public interface CassandraMigration
+{
+    Row migrate( Row existingRow, String toVersion, Session session );
+}
diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/ClusterBuilder.java b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/ClusterBuilder.java
new file mode 100644
index 0000000..0aced37
--- /dev/null
+++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/ClusterBuilder.java
@@ -0,0 +1,105 @@
+/*
+ *  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.polygene.entitystore.cassandra;
+
+import com.datastax.driver.core.Cluster;
+import java.net.InetSocketAddress;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.stream.Collectors;
+import org.apache.polygene.api.mixin.Mixins;
+
+@Mixins( ClusterBuilder.DefaultBuilder.class )
+public interface ClusterBuilder
+{
+    String DEFAULT_HOST_PORT = "localhost:9042";
+
+    Cluster build(CassandraEntityStoreConfiguration config);
+
+    class DefaultBuilder
+        implements ClusterBuilder
+    {
+
+        protected CassandraEntityStoreConfiguration config;
+
+        @Override
+        public Cluster build( CassandraEntityStoreConfiguration config )
+        {
+            this.config = config;
+            String clusterName = clusterName( config );
+            Collection<InetSocketAddress> connectionPoints = cassandraConnectionPoints();
+            Cluster.Builder builder =
+                Cluster.builder()
+                       .withClusterName( clusterName )
+                       .addContactPointsWithPorts(connectionPoints)
+                       .withCredentials( username(), password() );
+            builder = customConfiguration(builder);
+            return builder.build();
+        }
+
+        protected String clusterName( CassandraEntityStoreConfiguration config )
+        {
+            String clusterName = config.clusterName().get();
+            if( clusterName == null )
+            {
+                clusterName = "polygene-cluster";
+            }
+            return clusterName;
+        }
+
+        protected String username()
+        {
+            return config.username().get();
+        }
+
+        protected String password()
+        {
+            return config.password().get();
+        }
+
+        protected Collection<InetSocketAddress> cassandraConnectionPoints()
+        {
+            String hostnames = hostnames();
+            return Arrays.stream( hostnames.split( "(,| )" ) )
+                         .map( text ->
+                        {
+                            String[] strings = text.split( ":" );
+                            return new InetSocketAddress( strings[ 0 ], Integer.parseInt( strings[ 1 ] ) );
+                        }
+                      )
+                         .collect( Collectors.toList() );
+        }
+
+        protected String hostnames()
+        {
+            String hostnames = config.hostnames().get();
+            if( hostnames == null )
+            {
+                hostnames = DEFAULT_HOST_PORT;
+            }
+            return hostnames;
+        }
+
+        protected Cluster.Builder customConfiguration( Cluster.Builder builder )
+        {
+            return builder;
+        }
+    }
+}
diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/assembly/CassandraEntityStoreAssembler.java b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/assembly/CassandraEntityStoreAssembler.java
new file mode 100644
index 0000000..2736dfd
--- /dev/null
+++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/assembly/CassandraEntityStoreAssembler.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.entitystore.cassandra.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.cassandra.CassandraEntityStoreConfiguration;
+import org.apache.polygene.entitystore.cassandra.CassandraEntityStoreService;
+
+public class CassandraEntityStoreAssembler
+    extends Assemblers.VisibilityIdentityConfig<CassandraEntityStoreAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( CassandraEntityStoreService.class )
+              .visibleIn( visibility() )
+              .identifiedBy( identity() )
+              .instantiateOnStartup();
+
+        if( hasConfig() )
+        {
+            configModule().entities( CassandraEntityStoreConfiguration.class ).visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/package.html b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/package.html
new file mode 100644
index 0000000..f5fbec6
--- /dev/null
+++ b/extensions/entitystore-cassandra/src/main/java/org/apache/polygene/entitystore/cassandra/package.html
@@ -0,0 +1,69 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+<body>
+<h2>Casssandra EntityStore.</h2>
+<h3>Polygene's Cassandra Keyspace</h3>
+<p>
+    The Cassandra EntityStore can either use an existing Cassandra Keyspace, which is the default, OR create its own
+    keyspace.
+</p>
+<p>
+    The {@code CassandraEntityStoreConfiguration#keyspaceName()} defines the name of the keyspace to use, or to be
+    created.
+    If not defined, then the default name is "polygene".
+</p>
+<p>
+    The {@code CassandraEntityStoreConfiguration#createIfMissing()} defines if new missing resources should
+    be created or an Exception should be thrown if missing.
+</p>
+<p>
+    If it is created, then the {@code CassandraEntityStoreConfiguration#replicationFactor()} will define the replication
+    factor, and the command to create the keyspace is;
+</p>
+<code>
+    <pre>
+        CREATE KEYSPACE &lt;keyspaceName&gt; WITH replication = {'class':'SimpleStrategy', 'replication_factor' : &lt;replicationFactor&gt; };
+    </pre>
+</code>
+<h3>Polygene's Cassandra Table</h3>
+<p>
+    Polygene will store all entities in a single Cassandra TABLE
+</p>
+<code>
+    <pre>
+        CREATE TABLE &lt;tableName&gt; (
+            id text,
+            version text,
+            appversion text,
+            storeversion text,
+            usecase text,
+            modified timestamp,
+            properties map&lt;string,string&gt;
+            assocs map&lt;string,string&gt;
+            manyassocs map&lt;string,string&gt;
+            namedassocs map&lt;string,string&gt;
+            PRIMARY KEY ( id )
+        );
+    </pre>
+</code>
+
+</body>
+</html>
diff --git a/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/CassandraMapEntityStoreTest.java b/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/CassandraMapEntityStoreTest.java
new file mode 100644
index 0000000..08e5dfd
--- /dev/null
+++ b/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/CassandraMapEntityStoreTest.java
@@ -0,0 +1,83 @@
+/*
+ *  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.polygene.entitystore.cassandra;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.cassandra.assembly.CassandraEntityStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+import org.apache.polygene.test.entity.CanRemoveAll;
+import org.apache.polygene.test.internal.DockerRule;
+import org.junit.ClassRule;
+
+/**
+ * Test the CassandraEntityStoreService.
+ * <p>Installing Cassandra and starting it should suffice as the test use Cassandra defaults: 127.0.0.1:3000</p>
+ */
+public class CassandraMapEntityStoreTest
+    extends AbstractEntityStoreTest
+{
+    @ClassRule
+    public static final DockerRule DOCKER = new DockerRule( "cassandra", "Starting listening for CQL clients" );
+
+    @Override
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // END SNIPPET: assembly
+        super.assemble( module );
+
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+        module.services( CassandraEntityStoreService.class ).withTypes( CanRemoveAll.class ).withMixins( EmptyCassandraTableMixin.class );
+
+        // START SNIPPET: assembly
+        new CassandraEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+        // END SNIPPET: assembly
+
+        CassandraEntityStoreConfiguration cassandraConfig = config.forMixin( CassandraEntityStoreConfiguration.class ).declareDefaults();
+        String host = DOCKER.getDockerHost();
+        int port = DOCKER.getExposedContainerPort( "9042/tcp" );
+        System.out.println("Cassandra: " + host + ":" + port);
+        cassandraConfig.hostnames().set( host + ':' + port );
+        cassandraConfig.createIfMissing().set( true );
+        // START SNIPPET: assembly
+    }
+    // END SNIPPET: assembly
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+    }
+
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        CanRemoveAll cleaner = serviceFinder.findService( CanRemoveAll.class ).get();
+        cleaner.removeAll();
+        super.tearDown();
+    }
+}
diff --git a/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/DocSupport.java b/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/DocSupport.java
new file mode 100644
index 0000000..e1f281a
--- /dev/null
+++ b/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/DocSupport.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.entitystore.cassandra;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+
+public class DocSupport
+    implements Assembler
+{
+// START-SNIPPET: assembly
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+// END-SNIPPET: assembly
+        module.services( ClusterBuilder.class ).withMixins( MyClusterBuilder.class );
+// START-SNIPPET: assembly
+    }
+// END-SNIPPET: assembly
+
+// START-SNIPPET: builder
+    public class MyClusterBuilder extends ClusterBuilder.DefaultBuilder
+        implements ClusterBuilder
+    {
+        @Structure
+        private Application application;
+
+        @Override
+        protected String hostnames()
+        {
+            switch( application.mode() )
+            {
+            case development:
+                return "localhost:9042";
+            case staging:
+                return "cassandra.staging:9042";
+            case production:
+                return "cassandra1.prod:9042,cassandra2.prod:9042,cassandra3.prod:9042";
+            case test:
+            default:
+                return "cassandra.test:9042";
+            }
+        }
+    }
+// END-SNIPPET: builder
+}
diff --git a/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/EmptyCassandraTableMixin.java b/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/EmptyCassandraTableMixin.java
new file mode 100644
index 0000000..d7f9b99
--- /dev/null
+++ b/extensions/entitystore-cassandra/src/test/java/org/apache/polygene/entitystore/cassandra/EmptyCassandraTableMixin.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.entitystore.cassandra;
+
+import com.datastax.driver.core.querybuilder.Delete;
+import com.datastax.driver.core.querybuilder.QueryBuilder;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.test.entity.CanRemoveAll;
+
+public class EmptyCassandraTableMixin
+    implements CanRemoveAll
+{
+    @This
+    private CassandraCluster cluster;
+
+    @Override
+    public void removeAll()
+    {
+        cluster.cassandraClientSession().execute( "TRUNCATE TABLE " + cluster.tableName() + ";");
+    }
+}
diff --git a/extensions/entitystore-file/build.gradle b/extensions/entitystore-file/build.gradle
index 5ce6f63..b430e7d 100644
--- a/extensions/entitystore-file/build.gradle
+++ b/extensions/entitystore-file/build.gradle
@@ -1,35 +1,36 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-jar { manifest { name = "Apache Zest™ Extension - EntityStore - File system" }}
+apply plugin: 'polygene-extension'
+
+jar { manifest { name = "Apache Polygene™ Extension - EntityStore - File system" } }
 
 dependencies {
+  api polygene.core.bootstrap
+  api polygene.library( 'fileconfig' )
 
-    compile(project(":org.qi4j.core:org.qi4j.core.spi"))
-    compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-    compile(project(":org.qi4j.libraries:org.qi4j.library.constraints"))
-    compile(project(":org.qi4j.libraries:org.qi4j.library.locking"))
-    compile(project(":org.qi4j.libraries:org.qi4j.library.fileconfig"))
+  implementation polygene.library( 'locking' )
+  implementation polygene.library( 'constraints' )
 
-    testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-    testCompile(project(":org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson"))
+  runtimeOnly polygene.core.runtime
+  testImplementation polygene.core.testsupport
 
-    testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-    testRuntime(libraries.logback)
+  testRuntimeOnly libraries.logback
 }
diff --git a/extensions/entitystore-file/dev-status.xml b/extensions/entitystore-file/dev-status.xml
index 94d633f..8d582e2 100644
--- a/extensions/entitystore-file/dev-status.xml
+++ b/extensions/entitystore-file/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
         <!--none,early,beta,stable,mature-->
         <codebase>stable</codebase>
diff --git a/extensions/entitystore-file/src/docs/es-file.txt b/extensions/entitystore-file/src/docs/es-file.txt
index 1cf25cc..72946dc 100644
--- a/extensions/entitystore-file/src/docs/es-file.txt
+++ b/extensions/entitystore-file/src/docs/es-file.txt
@@ -37,7 +37,7 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-file/src/test/java/org/qi4j/entitystore/file/FileEntityStoreTest.java
+source=extensions/entitystore-file/src/test/java/org/apache/polygene/entitystore/file/FileEntityStoreTest.java
 tag=assembly
 ----
 
@@ -47,13 +47,13 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/FileEntityStoreConfiguration.java
+source=extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/FileEntityStoreConfiguration.java
 tag=config
 ----
 
 +directory+ is optional and represent the directory where the File EntityStore will keep its persisted state.
 
-It defaults to System.getProperty( "user.dir" ) + "/qi4j/filestore"
+It defaults to System.getProperty( "user.dir" ) + "/polygene/filestore"
 If the given path is not absolute, then it's relative to the current working directory.
 If you use the <<library-fileconfig>> then this property value is ignored and FileConfig is prefered.
 
diff --git a/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/FileEntityStoreActivation.java b/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/FileEntityStoreActivation.java
new file mode 100644
index 0000000..a23eeb6
--- /dev/null
+++ b/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/FileEntityStoreActivation.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.entitystore.file;
+
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.service.ServiceReference;
+
+/**
+ * Activation for FileEntityStoreMixin.
+ */
+@Activators( FileEntityStoreActivation.Activator.class )
+public interface FileEntityStoreActivation
+{
+
+    void initialize()
+            throws Exception;
+
+    class Activator
+            extends ActivatorAdapter<ServiceReference<FileEntityStoreActivation>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<FileEntityStoreActivation> activated )
+                throws Exception
+        {
+            activated.get().initialize();
+        }
+
+    }
+
+}
diff --git a/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/FileEntityStoreConfiguration.java b/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/FileEntityStoreConfiguration.java
new file mode 100644
index 0000000..e66a7a0
--- /dev/null
+++ b/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/FileEntityStoreConfiguration.java
@@ -0,0 +1,90 @@
+/*
+ *  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.polygene.entitystore.file;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.constraints.annotation.Range;
+
+/**
+ * Configuration for the FileEntityStoreService
+ */
+// START SNIPPET: config
+public interface FileEntityStoreConfiguration
+{
+    // END SNIPPET: config
+    /**
+     * The directory where the File Entity Store will be keep its persisted state.
+     * <p>
+     *     If no configuration is provided at all, then the default location is
+     *     {@code System.getProperty( "user.dir" ) + "/polygene/filestore"; }.
+     *     If a configuration is given, the entity store will be placed in the
+     *     DATA directory, which is operating system specific.
+     * </p>
+     * <table summary="Default locations">
+     *     <tr><th>OS</th><th>Location</th></tr>
+     *     <tr><td>Linux/Unix</td><td>{user}/.{application}/data</td></tr>
+     *     <tr><td>OSX</td><td>{user}/Library/Application Support/{application}</td></tr>
+     *     <tr><td>Windows</td><td>{user}/Application Data/{application}/data</td></tr>
+     * </table>
+     * <pre><code>
+     * where;
+     *   {user} = Current User's home directory
+     *   {application} = Application's name, as set in assembly.
+     * </code></pre>
+     * <p>
+     * Ignored if the FileConfiguration service is found.
+     * </p>
+     * <p>
+     * The content inside this directory should not be modified directly, and doing so may corrupt the data.
+     * </p>
+     *
+     * @return path to data file relative to current path
+     */
+    // START SNIPPET: config
+    @Optional
+    Property<String> directory();
+    // END SNIPPET: config
+
+    /** Defines how many slice directories the store should use.
+     * <p>
+     * Many operating systems run into performance problems when the number of files in a directory grows. If
+     * you expect a large number of entities in the file entity store, it is wise to set the number of slices
+     * (default is 1) to an approximation of the square root of number of expected entities.
+     * </p>
+     * <p>
+     * For instance, if you estimate that you will have 1 million entities in the file entity store, you should
+     * set the slices to 1000.
+     * </p>
+     * <p>
+     * There is an limit of minimum 1 slice and maximum 10,000 slices, and if more slices than that is needed, you
+     * are probably pushing this entitystore beyond its capabilities.
+     * </p>
+     * <p>
+     * Note that the slices() can not be changed once it has been set, as it would cause the entity store not to
+     * find the entities anymore.
+     * </p>
+     * @return the number of slices for the file entity store.
+     */
+    // START SNIPPET: config
+    @Optional @Range(min=1, max=10000)
+    Property<Integer> slices();
+}
+// END SNIPPET: config
diff --git a/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/FileEntityStoreMixin.java b/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/FileEntityStoreMixin.java
new file mode 100644
index 0000000..6a16a84
--- /dev/null
+++ b/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/FileEntityStoreMixin.java
@@ -0,0 +1,372 @@
+/*
+ *  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.polygene.entitystore.file;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.library.fileconfig.FileConfiguration;
+import org.apache.polygene.spi.entitystore.BackupRestore;
+import org.apache.polygene.spi.entitystore.EntityAlreadyExistsException;
+import org.apache.polygene.spi.entitystore.EntityNotFoundException;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+import org.apache.polygene.spi.entitystore.helpers.MapEntityStore;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+/**
+ * FileEntityStore implementation of MapEntityStore.
+ */
+public class FileEntityStoreMixin
+    implements FileEntityStoreActivation, MapEntityStore, BackupRestore
+{
+    @Optional
+    @Service
+    FileConfiguration fileConfiguration;
+
+    @This
+    private HasIdentity hasIdentity;
+
+    @This
+    private Configuration<FileEntityStoreConfiguration> config;
+
+    private String storeId;
+    private File dataDirectory;
+    private File tempDirectory;
+    private int slices;
+
+    @Override
+    public void initialize()
+        throws Exception
+    {
+        config.refresh();
+        storeId = hasIdentity.identity().get().toString();
+        String pathName = config.get().directory().get();
+        if( pathName == null )
+        {
+            if( fileConfiguration != null )
+            {
+                pathName = new File( fileConfiguration.dataDirectory(), storeId ).getAbsolutePath();
+            }
+            else
+            {
+                pathName = System.getProperty( "user.dir" ) + "/polygene/filestore/";
+            }
+        }
+        dataDirectory = new File( pathName ).getAbsoluteFile();
+        if( !dataDirectory.exists() )
+        {
+            Files.createDirectories( dataDirectory.toPath() );
+        }
+        tempDirectory = fileConfiguration != null
+                        ? new File( fileConfiguration.temporaryDirectory(), storeId )
+                        : new File( new File( System.getProperty( "java.io.tmpdir" ) ), storeId );
+        if( !tempDirectory.exists() )
+        {
+            Files.createDirectories( tempDirectory.toPath() );
+        }
+        File slicesFile = new File( dataDirectory, "slices" );
+        if( slicesFile.exists() )
+        {
+            slices = readIntegerInFile( slicesFile );
+        }
+        if( slices < 1 )
+        {
+            Integer slicesConf = config.get().slices().get();
+            if( slicesConf == null )
+            {
+                slices = 10;
+            }
+            else
+            {
+                slices = slicesConf;
+            }
+            writeIntegerToFile( slicesFile, slices );
+        }
+    }
+
+    private void writeIntegerToFile( File file, int value )
+        throws IOException
+    {
+        Files.write( file.toPath(), String.valueOf( value ).getBytes( UTF_8 ) );
+    }
+
+    private int readIntegerInFile( File file )
+        throws IOException
+    {
+        return Integer.parseInt( new String( Files.readAllBytes( file.toPath() ), UTF_8 ) );
+    }
+
+    @Override
+    public Reader get( EntityReference entityReference )
+        throws EntityStoreException
+    {
+        try
+        {
+            File f = getDataFile( entityReference );
+
+            if( !f.exists() )
+            {
+                throw new EntityNotFoundException( entityReference );
+            }
+
+            String serializedState = fetch( f );
+            return new StringReader( serializedState );
+        }
+        catch( FileNotFoundException e )
+        {
+            // Can't happen, but it does happen.
+            throw new EntityNotFoundException( entityReference );
+        }
+        catch( IOException e )
+        {
+            throw new EntityStoreException( e );
+        }
+    }
+
+    @Override
+    public void applyChanges( MapChanges changes )
+        throws Exception
+    {
+        try
+        {
+            changes.visitMap( new MapChanger()
+            {
+                @Override
+                public Writer newEntity( final EntityReference ref, EntityDescriptor descriptor )
+                    throws IOException
+                {
+                    return new StringWriter( 1000 )
+                    {
+                        @Override
+                        public void close()
+                            throws IOException
+                        {
+                            super.close();
+                            String state = this.toString();
+                            File dataFile = getDataFile( ref );
+                            if( dataFile.exists() )
+                            {
+                                throw new EntityAlreadyExistsException( ref );
+                            }
+                            store( dataFile, state );
+                        }
+                    };
+                }
+
+                @Override
+                public Writer updateEntity( MapChange mapChange )
+                    throws IOException
+                {
+                    return new StringWriter( 1000 )
+                    {
+                        @Override
+                        public void close()
+                            throws IOException
+                        {
+                            super.close();
+                            String state = this.toString();
+                            File dataFile = getDataFile( mapChange.reference() );
+                            store( dataFile, state );
+                        }
+                    };
+                }
+
+                @Override
+                public void removeEntity( EntityReference ref, EntityDescriptor descriptor )
+                    throws EntityNotFoundException
+                {
+                    File dataFile = getDataFile( ref );
+                    if( !dataFile.exists() )
+                    {
+                        throw new EntityNotFoundException( ref );
+                    }
+                    //noinspection ResultOfMethodCallIgnored
+                    dataFile.delete();
+                }
+            } );
+        }
+        catch( RuntimeException e )
+        {
+            if( e instanceof EntityStoreException )
+            {
+                throw e;
+            }
+            else
+            {
+                throw new IOException( e );
+            }
+        }
+    }
+
+    @Override
+    public Stream<Reader> entityStates()
+    {
+        return backup().map( StringReader::new );
+    }
+
+    @Override
+    public Stream<String> backup()
+    {
+        if( !dataDirectory.exists() )
+        {
+            return Stream.of();
+        }
+        try
+        {
+            return java.nio.file.Files.walk( dataDirectory.toPath(), 3 )
+                                      .skip( 1 )
+                                      .filter( path -> !"slices".equals( path.getFileName().toString() ) )
+                                      .map( Path::toFile )
+                                      .filter( file -> !file.isDirectory() )
+                                      .map( this::uncheckedFetch );
+        }
+        catch( IOException ex )
+        {
+            throw new EntityStoreException( ex );
+        }
+    }
+
+    @Override
+    public void restore( final Stream<String> stream )
+    {
+        stream.forEach(
+            item ->
+            {
+                String id = item.substring( "{\"reference\":\"".length() );
+                id = id.substring( 0, id.indexOf( '"' ) );
+                uncheckedStore( getDataFile( id ), item );
+            } );
+    }
+
+    private File getDataFile( String identity )
+    {
+        identity = replaceInvalidChars( identity );
+        String slice = "" + ( Math.abs( identity.hashCode() ) % slices );
+        File sliceDirectory = new File( dataDirectory, slice );
+        if( !sliceDirectory.exists() )
+        {
+            //noinspection ResultOfMethodCallIgnored
+            sliceDirectory.mkdirs();
+        }
+        return new File( sliceDirectory, identity + ".json" );
+    }
+
+    /**
+     * We need to replace all characters that some file system can't handle.
+     * <p>
+     * The resulting files should be portable across filesystems.
+     * </p>
+     *
+     * @param identity The reference that needs a file to be stored in.
+     *
+     * @return A filesystem-safe name.
+     */
+    private String replaceInvalidChars( String identity )
+    {
+        StringBuilder b = new StringBuilder( identity.length() + 30 );
+        for( int i = 0; i < identity.length(); i++ )
+        {
+            char ch = identity.charAt( i );
+            if( ( ch >= 'a' && ch <= 'z' )
+                || ( ch >= 'A' && ch <= 'Z' )
+                || ( ch >= '0' && ch <= '9' )
+                || ch == '_' || ch == '.' || ch == '-' )
+            {
+                b.append( ch );
+            }
+            else
+            {
+                int value = (int) ch;
+                b.append( '~' );
+                b.append( toHex( value ) );
+            }
+        }
+        return b.toString();
+    }
+
+    private String toHex( int value )
+    {
+        String result = "000" + Integer.toHexString( value );
+        return result.substring( result.length() - 4 );
+    }
+
+    private File getDataFile( EntityReference ref )
+    {
+        return getDataFile( ref.identity().toString() );
+    }
+
+    private String uncheckedFetch( File dataFile )
+    {
+        try
+        {
+            return fetch( dataFile );
+        }
+        catch( IOException e )
+        {
+            throw new EntityStoreException( e );
+        }
+    }
+
+    private void uncheckedStore( File dataFile, String state )
+    {
+        try
+        {
+            store( dataFile, state );
+        }
+        catch( IOException e )
+        {
+            throw new EntityStoreException( e );
+        }
+    }
+
+    private String fetch( File dataFile )
+        throws IOException
+    {
+        return new String( Files.readAllBytes( dataFile.toPath() ), UTF_8 );
+    }
+
+    private void store( File dataFile, String state )
+        throws IOException
+    {
+        // Write to temporary file first
+        Path tempFile = Files.createTempFile( tempDirectory.toPath(), storeId, "write" );
+        tempFile.toFile().deleteOnExit();
+        Files.write( tempFile, state.getBytes( UTF_8 ) );
+
+        // Replace old file
+        Files.move( tempFile, dataFile.toPath(), StandardCopyOption.REPLACE_EXISTING );
+    }
+}
\ No newline at end of file
diff --git a/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/FileEntityStoreService.java b/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/FileEntityStoreService.java
new file mode 100644
index 0000000..7088541
--- /dev/null
+++ b/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/FileEntityStoreService.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.entitystore.file;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.library.locking.LockingAbstractComposite;
+import org.apache.polygene.spi.entitystore.BackupRestore;
+import org.apache.polygene.spi.entitystore.ConcurrentModificationCheckConcern;
+import org.apache.polygene.spi.entitystore.EntityStateVersions;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.StateChangeNotificationConcern;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreActivation;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreMixin;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * EntityStore service backed by a source control friendly file system format.
+ * <p>Based on {@link JSONMapEntityStoreMixin}</p>
+ */
+@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
+@Mixins( { JSONMapEntityStoreMixin.class, FileEntityStoreMixin.class } )
+public interface FileEntityStoreService
+        extends JSONMapEntityStoreActivation,
+                FileEntityStoreActivation,
+                EntityStore,
+                EntityStateVersions,
+                StateStore,
+                BackupRestore,
+                LockingAbstractComposite,
+                Configuration
+{
+}
diff --git a/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/assembly/FileEntityStoreAssembler.java b/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/assembly/FileEntityStoreAssembler.java
new file mode 100644
index 0000000..26aec7f
--- /dev/null
+++ b/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/assembly/FileEntityStoreAssembler.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.entitystore.file.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.entitystore.file.FileEntityStoreConfiguration;
+import org.apache.polygene.entitystore.file.FileEntityStoreService;
+
+public class FileEntityStoreAssembler
+    extends Assemblers.VisibilityIdentityConfig<FileEntityStoreAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( FileEntityStoreService.class ).visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+        if( hasConfig() )
+        {
+            configModule().entities( FileEntityStoreConfiguration.class ).visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/assembly/package.html b/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/assembly/package.html
new file mode 100644
index 0000000..518d183
--- /dev/null
+++ b/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>File EntityStore Assembly.</h2>
+    </body>
+</html>
diff --git a/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/package.html b/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/package.html
new file mode 100644
index 0000000..125bf3c
--- /dev/null
+++ b/extensions/entitystore-file/src/main/java/org/apache/polygene/entitystore/file/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>File EntityStore.</h2>
+    </body>
+</html>
diff --git a/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/FileEntityStoreActivation.java b/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/FileEntityStoreActivation.java
deleted file mode 100644
index 5aa0d52..0000000
--- a/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/FileEntityStoreActivation.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2012 Paul Merlin.
- *
- * Licensed 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.qi4j.entitystore.file;
-
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.service.ServiceReference;
-
-/**
- * Activation for FileEntityStoreMixin.
- */
-@Activators( FileEntityStoreActivation.Activator.class )
-public interface FileEntityStoreActivation
-{
-
-    void initialize()
-            throws Exception;
-
-    class Activator
-            extends ActivatorAdapter<ServiceReference<FileEntityStoreActivation>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<FileEntityStoreActivation> activated )
-                throws Exception
-        {
-            activated.get().initialize();
-        }
-
-    }
-
-}
diff --git a/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/FileEntityStoreConfiguration.java b/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/FileEntityStoreConfiguration.java
deleted file mode 100644
index cf97af8..0000000
--- a/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/FileEntityStoreConfiguration.java
+++ /dev/null
@@ -1,91 +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.qi4j.entitystore.file;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.library.constraints.annotation.Range;
-
-/**
- * Configuration for the FileEntityStoreService
- */
-// START SNIPPET: config
-public interface FileEntityStoreConfiguration
-    extends ConfigurationComposite
-{
-    // END SNIPPET: config
-    /**
-     * The directory where the File Entity Store will be keep its persisted state.
-     * <p>
-     *     If no configuration is provided at all, then the default location is
-     *     {@code System.getProperty( "user.dir" ) + "/qi4j/filestore"; }.
-     *     If a configuration is given, the entity store will be placed in the
-     *     DATA directory, which is operating system specific.
-     * </p>
-     * <table summary="Default locations">
-     *     <tr><th>OS</th><th>Location</th></tr>
-     *     <tr><td>Linux/Unix</td><td>{user}/.{application}/data</td></tr>
-     *     <tr><td>OSX</td><td>{user}/Library/Application Support/{application}</td></tr>
-     *     <tr><td>Windows</td><td>{user}/Application Data/{application}/data</td></tr>
-     * </table>
-     * <pre><code>
-     * where;
-     *   {user} = Current User's home directory
-     *   {application} = Application's name, as set in assembly.
-     * </code></pre>
-     * <p>
-     * Ignored if the FileConfiguration service is found.
-     * </p>
-     * <p>
-     * The content inside this directory should not be modified directly, and doing so may corrupt the data.
-     * </p>
-     *
-     * @return path to data file relative to current path
-     */
-    // START SNIPPET: config
-    @Optional
-    Property<String> directory();
-    // END SNIPPET: config
-
-    /** Defines how many slice directories the store should use.
-     * <p>
-     * Many operating systems run into performance problems when the number of files in a directory grows. If
-     * you expect a large number of entities in the file entity store, it is wise to set the number of slices
-     * (default is 1) to an approximation of the square root of number of expected entities.
-     * </p>
-     * <p>
-     * For instance, if you estimate that you will have 1 million entities in the file entity store, you should
-     * set the slices to 1000.
-     * </p>
-     * <p>
-     * There is an limit of minimum 1 slice and maximum 10,000 slices, and if more slices than that is needed, you
-     * are probably pushing this entitystore beyond its capabilities.
-     * </p>
-     * <p>
-     * Note that the slices() can not be changed once it has been set, as it would cause the entity store not to
-     * find the entities anymore.
-     * </p>
-     * @return the number of slices for the file entity store.
-     */
-    // START SNIPPET: config
-    @Optional @Range(min=1, max=10000)
-    Property<Integer> slices();
-}
-// END SNIPPET: config
diff --git a/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/FileEntityStoreMixin.java b/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/FileEntityStoreMixin.java
deleted file mode 100644
index fa71ea7..0000000
--- a/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/FileEntityStoreMixin.java
+++ /dev/null
@@ -1,498 +0,0 @@
-/*  Copyright 2008 Rickard Öberg.
- *
- * Licensed 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.qi4j.entitystore.file;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.io.Files;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.library.fileconfig.FileConfiguration;
-import org.qi4j.spi.entitystore.BackupRestore;
-import org.qi4j.spi.entitystore.EntityAlreadyExistsException;
-import org.qi4j.spi.entitystore.EntityNotFoundException;
-import org.qi4j.spi.entitystore.EntityStoreException;
-import org.qi4j.spi.entitystore.helpers.MapEntityStore;
-
-/**
- * FileEntityStore implementation of MapEntityStore.
- */
-public class FileEntityStoreMixin
-    implements FileEntityStoreActivation, MapEntityStore, BackupRestore
-{
-    @Optional
-    @Service
-    FileConfiguration fileConfiguration;
-
-    @This
-    private Configuration<FileEntityStoreConfiguration> config;
-
-    private File dataDirectory;
-    private int slices;
-
-    @Override
-    public void initialize()
-        throws Exception
-    {
-        String pathName = config.get().directory().get();
-        if( pathName == null )
-        {
-            if( fileConfiguration != null )
-            {
-                String storeId = config.get().identity().get();
-                pathName = new File( fileConfiguration.dataDirectory(), storeId ).getAbsolutePath();
-            }
-            else
-            {
-                pathName = System.getProperty( "user.dir" ) + "/qi4j/filestore/";
-            }
-        }
-        dataDirectory = new File( pathName ).getAbsoluteFile();
-        if( !dataDirectory.exists() )
-        {
-            if( !dataDirectory.mkdirs() )
-            {
-                throw new IOException( "Unable to create directory " + dataDirectory );
-            }
-        }
-        File slicesFile = new File( dataDirectory, "slices" );
-        if( slicesFile.exists() )
-        {
-            slices = readIntegerInFile( slicesFile );
-        }
-        if( slices < 1 )
-        {
-            Integer slicesConf = config.get().slices().get();
-            if( slicesConf == null )
-            {
-                slices = 10;
-            }
-            else
-            {
-                slices = slicesConf;
-            }
-            writeIntegerToFile( slicesFile, slices );
-        }
-    }
-
-    private void writeIntegerToFile( File file, int value )
-        throws IOException
-    {
-        FileWriter fw = null;
-        BufferedWriter bw = null;
-        try
-        {
-            fw = new FileWriter( file );
-            bw = new BufferedWriter( fw );
-            bw.write( "" + value );
-            bw.flush();
-        }
-        finally
-        {
-            if( bw != null )
-            {
-                bw.close();
-            }
-            if( fw != null )
-            {
-                fw.close();
-            }
-        }
-    }
-
-    private int readIntegerInFile( File file )
-        throws IOException
-    {
-        FileReader fis = null;
-        BufferedReader br = null;
-        try
-        {
-            fis = new FileReader( file );
-            br = new BufferedReader( fis );
-            return Integer.parseInt( br.readLine() );
-        }
-        finally
-        {
-            if( br != null )
-            {
-                br.close();
-            }
-            if( fis != null )
-            {
-                fis.close();
-            }
-        }
-    }
-
-    @Override
-    public Reader get( EntityReference entityReference )
-        throws EntityStoreException
-    {
-        try
-        {
-            File f = getDataFile( entityReference );
-
-            if( !f.exists() )
-            {
-                throw new EntityNotFoundException( entityReference );
-            }
-
-            byte[] serializedState = fetch( f );
-            return new StringReader( new String( serializedState, "UTF-8" ) );
-        }
-        catch( IOException e )
-        {
-            throw new EntityStoreException( e );
-        }
-    }
-
-    private byte[] readDataFromStream( BufferedInputStream in, byte[] buf )
-        throws IOException
-    {
-        int size = in.read( buf );
-        ByteArrayOutputStream baos = new ByteArrayOutputStream( 2000 );
-        while( size > 0 )
-        {
-            baos.write( buf, 0, size );
-            size = in.read( buf );
-        }
-        return baos.toByteArray();
-    }
-
-    @Override
-    public void applyChanges( MapChanges changes )
-        throws IOException
-    {
-        try
-        {
-            changes.visitMap( new MapChanger()
-            {
-                @Override
-                public Writer newEntity( final EntityReference ref, EntityDescriptor descriptor )
-                    throws IOException
-                {
-                    return new StringWriter( 1000 )
-                    {
-                        @Override
-                        public void close()
-                            throws IOException
-                        {
-                            super.close();
-                            byte[] stateArray = this.toString().getBytes( "UTF-8" );
-                            File dataFile = getDataFile( ref );
-                            if( dataFile.exists() )
-                            {
-                                throw new EntityAlreadyExistsException( ref );
-                            }
-                            store( dataFile, stateArray );
-                        }
-                    };
-                }
-
-                @Override
-                public Writer updateEntity( final EntityReference ref, EntityDescriptor descriptor )
-                    throws IOException
-                {
-                    return new StringWriter( 1000 )
-                    {
-                        @Override
-                        public void close()
-                            throws IOException
-                        {
-                            super.close();
-                            byte[] stateArray = this.toString().getBytes( "UTF-8" );
-                            File dataFile = getDataFile( ref );
-                            store( dataFile, stateArray );
-                        }
-                    };
-                }
-
-                @Override
-                public void removeEntity( EntityReference ref, EntityDescriptor descriptor )
-                    throws EntityNotFoundException
-                {
-                    File dataFile = getDataFile( ref );
-                    if( !dataFile.exists() )
-                    {
-                        throw new EntityNotFoundException( ref );
-                    }
-                    //noinspection ResultOfMethodCallIgnored
-                    dataFile.delete();
-                }
-            } );
-        }
-        catch( RuntimeException e )
-        {
-            if( e instanceof EntityStoreException )
-            {
-                throw e;
-            }
-            else
-            {
-                throw new IOException( e );
-            }
-        }
-    }
-
-    @Override
-    public Input<String, IOException> backup()
-    {
-        return new Input<String, IOException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super String, ReceiverThrowableType> output )
-                throws IOException, ReceiverThrowableType
-            {
-                output.receiveFrom( new Sender<String, IOException>()
-                {
-                    @Override
-                    public <ThrowableType extends Throwable> void sendTo( Receiver<? super String, ThrowableType> receiver )
-                        throws ThrowableType, IOException
-                    {
-                        for( File sliceDirectory : dataDirectory.listFiles() )
-                        {
-                            for( File file : sliceDirectory.listFiles() )
-                            {
-                                byte[] stateArray = fetch( file );
-                                receiver.receive( new String( stateArray, "UTF-8" ) );
-                            }
-                        }
-                    }
-                } );
-            }
-        };
-    }
-
-    @Override
-    public Output<String, IOException> restore()
-    {
-        return new Output<String, IOException>()
-        {
-            @Override
-            public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends String, SenderThrowableType> sender )
-                throws IOException, SenderThrowableType
-            {
-                sender.sendTo( new Receiver<String, IOException>()
-                {
-                    @Override
-                    public void receive( String item )
-                        throws IOException
-                    {
-                        String id = item.substring( "{\"identity\":\"".length() );
-                        id = id.substring( 0, id.indexOf( '"' ) );
-                        byte[] stateArray = item.getBytes( "UTF-8" );
-                        store( getDataFile( id ), stateArray );
-                    }
-                } );
-            }
-        };
-    }
-
-    @Override
-    public Input<Reader, IOException> entityStates()
-    {
-        return new Input<Reader, IOException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super Reader, ReceiverThrowableType> output )
-                throws IOException, ReceiverThrowableType
-            {
-                output.receiveFrom( new Sender<Reader, IOException>()
-                {
-                    @Override
-                    public <ThrowableType extends Throwable> void sendTo( Receiver<? super Reader, ThrowableType> receiver )
-                        throws ThrowableType, IOException
-                    {
-                        for( File sliceDirectory : dataDirectory.listFiles() )
-                        {
-                            for( File file : sliceDirectory.listFiles() )
-                            {
-                                byte[] serializedState = fetch( file );
-                                receiver.receive( new StringReader( new String( serializedState, "UTF-8" ) ) );
-                            }
-                        }
-                    }
-                } );
-            }
-        };
-    }
-
-    private File getDataFile( String identity )
-    {
-        identity = replaceInvalidChars( identity );
-        String slice = "" + ( Math.abs( identity.hashCode() ) % slices );
-        File sliceDirectory = new File( dataDirectory, slice );
-        if( !sliceDirectory.exists() )
-        {
-            //noinspection ResultOfMethodCallIgnored
-            sliceDirectory.mkdirs();
-        }
-        return new File( sliceDirectory, identity + ".json" );
-    }
-
-    /**
-     * We need to replace all characters that some file system can't handle.
-     * <p>
-     * The resulting files should be portable across filesystems.
-     * </p>
-     *
-     * @param identity The identity that needs a file to be stored in.
-     *
-     * @return A filesystem-safe name.
-     */
-    private String replaceInvalidChars( String identity )
-    {
-        StringBuilder b = new StringBuilder( identity.length() + 30 );
-        for( int i = 0; i < identity.length(); i++ )
-        {
-            char ch = identity.charAt( i );
-            if( ( ch >= 'a' && ch <= 'z' )
-                || ( ch >= 'A' && ch <= 'Z' )
-                || ( ch >= '0' && ch <= '9' )
-                || ch == '_' || ch == '.' || ch == '-' )
-            {
-                b.append( ch );
-            }
-            else
-            {
-                int value = (int) ch;
-                b.append( '~' );
-                b.append( toHex( value ) );
-            }
-
-        }
-        return b.toString();
-    }
-
-    private String toHex( int value )
-    {
-        String result = "000" + Integer.toHexString( value );
-        return result.substring( result.length() - 4 );
-    }
-
-    private File getDataFile( EntityReference ref )
-    {
-        return getDataFile( ref.identity() );
-    }
-
-    private byte[] fetch( File dataFile )
-        throws IOException
-    {
-        byte[] buf = new byte[1000];
-        BufferedInputStream in = null;
-        FileInputStream fis = null;
-        try
-        {
-            fis = new FileInputStream( dataFile );
-            in = new BufferedInputStream( fis );
-            return readDataFromStream( in, buf );
-        }
-        finally
-        {
-            if( in != null )
-            {
-                try
-                {
-                    in.close();
-                }
-                catch( IOException e )
-                {
-                    // Ignore ??
-                }
-            }
-            if( fis != null )
-            {
-                try
-                {
-                    fis.close();
-                }
-                catch( IOException e )
-                {
-                    // ignore??
-                }
-            }
-        }
-    }
-
-    private void store( File dataFile, byte[] stateArray )
-        throws IOException
-    {
-        FileOutputStream fos = null;
-        BufferedOutputStream bos = null;
-
-        // Write to tempfile first
-        File tempFile = Files.createTemporayFileOf( dataFile );
-        tempFile.deleteOnExit();
-
-        try
-        {
-            fos = new FileOutputStream( tempFile, false );
-            bos = new BufferedOutputStream( fos );
-            bos.write( stateArray );
-        }
-        finally
-        {
-            if( bos != null )
-            {
-                try
-                {
-                    bos.close();
-                }
-                catch( IOException e )
-                {
-                    // ignore??
-                }
-            }
-            if( fos != null )
-            {
-                try
-                {
-                    fos.close();
-                }
-                catch( IOException e )
-                {
-                    // ignore??
-                }
-            }
-        }
-
-        // Replace old file
-        dataFile.delete();
-        tempFile.renameTo( dataFile );
-    }
-}
\ No newline at end of file
diff --git a/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/FileEntityStoreService.java b/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/FileEntityStoreService.java
deleted file mode 100644
index cded70f..0000000
--- a/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/FileEntityStoreService.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*  Copyright 2008 Rickard Öberg.
- *
- * Licensed 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.qi4j.entitystore.file;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.library.locking.LockingAbstractComposite;
-import org.qi4j.spi.entitystore.BackupRestore;
-import org.qi4j.spi.entitystore.ConcurrentModificationCheckConcern;
-import org.qi4j.spi.entitystore.EntityStateVersions;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.StateChangeNotificationConcern;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreActivation;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreMixin;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * EntityStore service backed by a source control friendly file system format.
- * <p>Based on {@link JSONMapEntityStoreMixin}</p>
- */
-@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
-@Mixins( { JSONMapEntityStoreMixin.class, FileEntityStoreMixin.class } )
-public interface FileEntityStoreService
-        extends JSONMapEntityStoreActivation,
-                FileEntityStoreActivation,
-                EntityStore,
-                EntityStateVersions,
-                StateStore,
-                BackupRestore,
-                ServiceComposite,
-                LockingAbstractComposite,
-                Configuration
-{
-}
diff --git a/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/assembly/FileEntityStoreAssembler.java b/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/assembly/FileEntityStoreAssembler.java
deleted file mode 100644
index 285f22e..0000000
--- a/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/assembly/FileEntityStoreAssembler.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.entitystore.file.assembly;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.entitystore.file.FileEntityStoreConfiguration;
-import org.qi4j.entitystore.file.FileEntityStoreService;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-
-public class FileEntityStoreAssembler
-    extends Assemblers.VisibilityIdentityConfig<FileEntityStoreAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( UuidIdentityGeneratorService.class ).visibleIn( visibility() );
-        ServiceDeclaration service = module.services( FileEntityStoreService.class ).visibleIn( visibility() );
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        if( hasConfig() )
-        {
-            configModule().entities( FileEntityStoreConfiguration.class ).visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/assembly/package.html b/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/assembly/package.html
deleted file mode 100644
index 43e5c08..0000000
--- a/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/assembly/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>File EntityStore Assembly.</h2>
-    </body>
-</html>
diff --git a/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/package.html b/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/package.html
deleted file mode 100644
index ef986c9..0000000
--- a/extensions/entitystore-file/src/main/java/org/qi4j/entitystore/file/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>File EntityStore.</h2>
-    </body>
-</html>
diff --git a/extensions/entitystore-file/src/test/java/org/apache/polygene/entitystore/file/FileEntityStoreTest.java b/extensions/entitystore-file/src/test/java/org/apache/polygene/entitystore/file/FileEntityStoreTest.java
new file mode 100644
index 0000000..d18be11
--- /dev/null
+++ b/extensions/entitystore-file/src/test/java/org/apache/polygene/entitystore/file/FileEntityStoreTest.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.entitystore.file;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.file.assembly.FileEntityStoreAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+public class FileEntityStoreTest
+    extends AbstractEntityStoreTest
+{
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // END SNIPPET: assembly
+        super.assemble( module );
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+        // START SNIPPET: assembly
+        new FileEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+    }
+    // END SNIPPET: assembly
+}
diff --git a/extensions/entitystore-file/src/test/java/org/apache/polygene/entitystore/file/FileEntityStoreWithCacheTest.java b/extensions/entitystore-file/src/test/java/org/apache/polygene/entitystore/file/FileEntityStoreWithCacheTest.java
new file mode 100644
index 0000000..95988da
--- /dev/null
+++ b/extensions/entitystore-file/src/test/java/org/apache/polygene/entitystore/file/FileEntityStoreWithCacheTest.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.entitystore.file;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.file.assembly.FileEntityStoreAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.cache.AbstractEntityStoreWithCacheTest;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+public class FileEntityStoreWithCacheTest
+    extends AbstractEntityStoreWithCacheTest
+{
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+        new FileEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+    }
+}
diff --git a/extensions/entitystore-file/src/test/java/org/qi4j/entitystore/file/FileEntityStoreTest.java b/extensions/entitystore-file/src/test/java/org/qi4j/entitystore/file/FileEntityStoreTest.java
deleted file mode 100644
index 14d1f7b..0000000
--- a/extensions/entitystore-file/src/test/java/org/qi4j/entitystore/file/FileEntityStoreTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*  Copyright 2008 Rickard Öberg.
- *
- * Licensed 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.qi4j.entitystore.file;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.file.assembly.FileEntityStoreAssembler;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class FileEntityStoreTest
-    extends AbstractEntityStoreTest
-{
-
-    @Override
-    // START SNIPPET: assembly
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // END SNIPPET: assembly
-        super.assemble( module );
-        module.services( FileConfigurationService.class );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        // START SNIPPET: assembly
-        new FileEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
-    }
-    // END SNIPPET: assembly
-}
diff --git a/extensions/entitystore-file/src/test/java/org/qi4j/entitystore/file/FileEntityStoreWithCacheTest.java b/extensions/entitystore-file/src/test/java/org/qi4j/entitystore/file/FileEntityStoreWithCacheTest.java
deleted file mode 100644
index 4fd31a5..0000000
--- a/extensions/entitystore-file/src/test/java/org/qi4j/entitystore/file/FileEntityStoreWithCacheTest.java
+++ /dev/null
@@ -1,42 +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.qi4j.entitystore.file;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.file.assembly.FileEntityStoreAssembler;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.cache.AbstractEntityStoreWithCacheTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class FileEntityStoreWithCacheTest
-    extends AbstractEntityStoreWithCacheTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        module.services( FileConfigurationService.class );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        new FileEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
-    }
-}
diff --git a/extensions/entitystore-geode/build.gradle b/extensions/entitystore-geode/build.gradle
new file mode 100644
index 0000000..5cf6185
--- /dev/null
+++ b/extensions/entitystore-geode/build.gradle
@@ -0,0 +1,38 @@
+/*
+ *  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.
+ *
+ *
+ */
+
+apply plugin: 'polygene-extension'
+
+description = "Apache Polygene™ Geode EntityStore Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - EntityStore - Geode" } }
+
+dependencies {
+  api polygene.core.bootstrap
+
+  implementation polygene.library( 'locking' )
+  implementation libraries.geode
+
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/extensions/entitystore-geode/dev-status.xml b/extensions/entitystore-geode/dev-status.xml
new file mode 100644
index 0000000..762e250
--- /dev/null
+++ b/extensions/entitystore-geode/dev-status.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
+  <status>
+        <!--none,early,beta,stable,mature-->
+        <codebase>stable</codebase>
+
+        <!-- none, brief, good, complete -->
+        <documentation>brief</documentation>
+
+        <!-- none, some, good, complete -->
+        <unittests>good</unittests>
+    </status>
+    <licenses>
+        <license>ALv2</license>
+    </licenses>
+</module>
diff --git a/extensions/entitystore-geode/src/docs/es-geode.txt b/extensions/entitystore-geode/src/docs/es-geode.txt
new file mode 100644
index 0000000..301fa21
--- /dev/null
+++ b/extensions/entitystore-geode/src/docs/es-geode.txt
@@ -0,0 +1,51 @@
+
+///////////////////////////////////////////////////////////////
+ * 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.
+///////////////////////////////////////////////////////////////
+
+[[extension-es-geode, Geode EntityStore]]
+= Geode EntityStore =
+
+[devstatus]
+--------------
+source=extensions/entitystore-geode/dev-status.xml
+--------------
+
+EntityStore service backed by the https://geode.incubator.apache.org/[Apache Geode] data grid.
+
+include::../../build/docs/buildinfo/artifact.txt[]
+
+== Assembly ==
+
+Assembly is done using the provided Assembler:
+
+[snippet,java]
+----
+source=extensions/entitystore-geode/src/test/java/org/apache/polygene/entitystore/geode/GeodeEntityStoreTest.java
+tag=assembly
+----
+
+== Configuration ==
+
+Here are the configuration properties for the Geode EntityStore:
+
+[snippet,java]
+----
+source=extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/GeodeConfiguration.java
+tag=config
+----
diff --git a/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/GeodeConfiguration.java b/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/GeodeConfiguration.java
new file mode 100644
index 0000000..4408bee
--- /dev/null
+++ b/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/GeodeConfiguration.java
@@ -0,0 +1,81 @@
+/*
+ *  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.polygene.entitystore.geode;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Geode Configuration.
+ */
+// START SNIPPET: config
+public interface GeodeConfiguration
+{
+    /**
+     * Geode Topology.
+     * Defaults to {@literal EMBEDDED}, see {@link GeodeTopology}.
+     *
+     * @return Geode Topology
+     */
+    @UseDefaults
+    Property<GeodeTopology> topology();
+
+    /**
+     * Geode Cache Name.
+     *
+     * @return Geode Cache Name
+     */
+    @UseDefaults( "polygene:cache" )
+    Property<String> cacheName();
+
+    /**
+     * Cache properties path, loaded from the classpath.
+     *
+     * @return Cache properties path
+     */
+    @Optional
+    Property<String> cachePropertiesPath();
+
+    /**
+     * Cache Region Shortcut.
+     *
+     * In {@literal EMBEDDED} {@link #topology()}, defaults to  {@literal LOCAL},
+     * see {@link org.apache.geode.cache.RegionShortcut}.
+     *
+     * In {@literal CLIENT_SERVER} {@link #topology()}, defaults to {@literal PROXY},
+     * see {@link org.apache.geode.cache.client.ClientRegionShortcut}.
+     *
+     * @return Cache Region Shortcut
+     */
+    @Optional
+    Property<String> regionShortcut();
+
+    /**
+     * Geode Region Name.
+     *
+     * Region names may only be alphanumeric and may contain hyphens or underscores.
+     *
+     * @return Geode Region Name
+     */
+    @UseDefaults( "polygene-entitystore-region" )
+    Property<String> regionName();
+}
+// END SNIPPET: config
diff --git a/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/GeodeEntityStoreMixin.java b/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/GeodeEntityStoreMixin.java
new file mode 100644
index 0000000..c140c28
--- /dev/null
+++ b/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/GeodeEntityStoreMixin.java
@@ -0,0 +1,200 @@
+/*
+ *  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.polygene.entitystore.geode;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Properties;
+import java.util.stream.Stream;
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.CacheFactory;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.RegionFactory;
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.cache.client.ClientCache;
+import org.apache.geode.cache.client.ClientCacheFactory;
+import org.apache.geode.cache.client.ClientRegionFactory;
+import org.apache.geode.cache.client.ClientRegionShortcut;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.spi.entitystore.EntityNotFoundException;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+import org.apache.polygene.spi.entitystore.helpers.MapEntityStore;
+
+/**
+ * Geode EntityStore Mixin.
+ */
+public class GeodeEntityStoreMixin
+        implements ServiceActivation, MapEntityStore
+{
+    @This
+    private Configuration<GeodeConfiguration> config;
+
+    private AutoCloseable closeable;
+    private Region<String, String> region;
+
+    @Override
+    public void activateService()
+            throws Exception
+    {
+        config.refresh();
+        GeodeConfiguration configuration = config.get();
+        switch( configuration.topology().get() )
+        {
+            case EMBEDDED:
+                activateEmbedded( configuration );
+                break;
+            case CLIENT_SERVER:
+                activateClientServer( configuration );
+                break;
+            default:
+                throw new IllegalStateException( "Invalid/Unsupported Geode Topology: "
+                                                 + configuration.topology().get() );
+        }
+    }
+
+    private void activateEmbedded( GeodeConfiguration configuration )
+            throws IOException
+    {
+        Properties cacheProperties = buildCacheProperties( configuration );
+        String regionShortcutName = configuration.regionShortcut().get();
+        RegionShortcut regionShortcut = regionShortcutName == null
+                                        ? RegionShortcut.LOCAL
+                                        : RegionShortcut.valueOf( regionShortcutName );
+        String regionName = configuration.regionName().get();
+
+        CacheFactory cacheFactory = new CacheFactory( cacheProperties );
+        Cache cache = cacheFactory.create();
+        RegionFactory<String, String> regionFactory = cache.createRegionFactory( regionShortcut );
+        region = regionFactory.create( regionName );
+        closeable = cache;
+    }
+
+    private void activateClientServer( GeodeConfiguration configuration )
+            throws IOException
+    {
+        Properties cacheProperties = buildCacheProperties( configuration );
+        String regionShortcutName = configuration.regionShortcut().get();
+        ClientRegionShortcut regionShortcut = regionShortcutName == null
+                                              ? ClientRegionShortcut.PROXY
+                                              : ClientRegionShortcut.valueOf( regionShortcutName );
+        String regionName = configuration.regionName().get();
+
+        ClientCacheFactory cacheFactory = new ClientCacheFactory( cacheProperties );
+        ClientCache cache = cacheFactory.create();
+        ClientRegionFactory<String, String> regionFactory = cache.createClientRegionFactory( regionShortcut );
+        region = regionFactory.create( regionName );
+        closeable = cache;
+    }
+
+    private Properties buildCacheProperties( GeodeConfiguration config )
+            throws IOException
+    {
+        Properties properties = new Properties();
+        String cachePropertiesPath = config.cachePropertiesPath().get();
+        if( cachePropertiesPath != null )
+        {
+            try( InputStream input = getClass().getResourceAsStream( cachePropertiesPath ) )
+            {
+                if( input == null )
+                {
+                    throw new IllegalStateException( "Geode Cache Properties could not be found: "
+                                                     + cachePropertiesPath );
+                }
+                properties.load( input );
+            }
+        }
+        properties.setProperty( "name", config.cacheName().get() );
+        return properties;
+    }
+
+    @Override
+    public void passivateService()
+            throws Exception
+    {
+        region = null;
+        if( closeable != null )
+        {
+            closeable.close();
+            closeable = null;
+        }
+    }
+
+    @Override
+    public Reader get( EntityReference entityReference ) throws EntityStoreException
+    {
+        String serializedState = region.get( entityReference.identity().toString() );
+        if( serializedState == null )
+        {
+            throw new EntityNotFoundException( entityReference );
+        }
+        return new StringReader( serializedState );
+    }
+
+    @Override
+    public void applyChanges( MapChanges changes ) throws Exception
+    {
+        changes.visitMap( new MapChanger()
+        {
+
+            @Override
+            public Writer newEntity( final EntityReference ref, EntityDescriptor entityDescriptor )
+                    throws IOException
+            {
+                return new StringWriter( 1000 )
+                {
+
+                    @Override
+                    public void close()
+                            throws IOException
+                    {
+                        super.close();
+                        region.put( ref.identity().toString(), toString() );
+                    }
+                };
+            }
+
+            @Override
+            public Writer updateEntity( MapChange mapChange )
+                    throws IOException
+            {
+                return newEntity( mapChange.reference(), mapChange.descriptor() );
+            }
+
+            @Override
+            public void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor )
+                    throws EntityNotFoundException
+            {
+                region.remove( ref.identity().toString() );
+            }
+        } );
+    }
+
+    @Override
+    public Stream<Reader> entityStates()
+    {
+        return region.values().stream().map( StringReader::new );
+    }
+}
diff --git a/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/GeodeEntityStoreService.java b/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/GeodeEntityStoreService.java
new file mode 100644
index 0000000..f46347d
--- /dev/null
+++ b/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/GeodeEntityStoreService.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.entitystore.geode;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.library.locking.LockingAbstractComposite;
+import org.apache.polygene.spi.entitystore.ConcurrentModificationCheckConcern;
+import org.apache.polygene.spi.entitystore.EntityStateVersions;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.StateChangeNotificationConcern;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreActivation;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreMixin;
+
+/**
+ * Geode EntityStore service.
+ * <p>Based on @{@link JSONMapEntityStoreMixin}.</p>
+ */
+@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
+@Mixins( { JSONMapEntityStoreMixin.class, GeodeEntityStoreMixin.class } )
+public interface GeodeEntityStoreService
+    extends ServiceActivation,
+            JSONMapEntityStoreActivation,
+            EntityStore,
+            EntityStateVersions,
+            LockingAbstractComposite,
+            Configuration
+{
+}
diff --git a/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/GeodeTopology.java b/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/GeodeTopology.java
new file mode 100644
index 0000000..4904e8f
--- /dev/null
+++ b/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/GeodeTopology.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.entitystore.geode;
+
+/**
+ * Geode Topology.
+ */
+public enum GeodeTopology
+{
+    EMBEDDED,
+    CLIENT_SERVER;
+}
diff --git a/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/assembly/GeodeEntityStoreAssembler.java b/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/assembly/GeodeEntityStoreAssembler.java
new file mode 100644
index 0000000..741d420
--- /dev/null
+++ b/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/assembly/GeodeEntityStoreAssembler.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.entitystore.geode.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.entitystore.geode.GeodeConfiguration;
+import org.apache.polygene.entitystore.geode.GeodeEntityStoreService;
+
+/**
+ * Assembler for the Geode EntityStore.
+ */
+public class GeodeEntityStoreAssembler
+    extends Assemblers.VisibilityIdentityConfig<GeodeEntityStoreAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( GeodeEntityStoreService.class ).visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+        if( hasConfig() )
+        {
+            configModule().entities( GeodeConfiguration.class ).visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/assembly/package.html b/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/assembly/package.html
new file mode 100644
index 0000000..2372b1c
--- /dev/null
+++ b/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Geode EntityStore Assembly.</h2>
+    </body>
+</html>
diff --git a/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/package.html b/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/package.html
new file mode 100644
index 0000000..e73b7b4
--- /dev/null
+++ b/extensions/entitystore-geode/src/main/java/org/apache/polygene/entitystore/geode/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Geode EntityStore.</h2>
+    </body>
+</html>
diff --git a/extensions/entitystore-geode/src/test/java/org/apache/polygene/entitystore/geode/GeodeEntityStoreTest.java b/extensions/entitystore-geode/src/test/java/org/apache/polygene/entitystore/geode/GeodeEntityStoreTest.java
new file mode 100644
index 0000000..a6aa1e1
--- /dev/null
+++ b/extensions/entitystore-geode/src/test/java/org/apache/polygene/entitystore/geode/GeodeEntityStoreTest.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.entitystore.geode;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.geode.assembly.GeodeEntityStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+
+public class GeodeEntityStoreTest
+    extends AbstractEntityStoreTest
+{
+    @Override
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // END SNIPPET: assembly
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+        // START SNIPPET: assembly
+        new GeodeEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+    }
+    // END SNIPPET: assembly
+}
diff --git a/extensions/entitystore-geode/src/test/java/org/apache/polygene/entitystore/geode/GeodeEntityStoreWithCacheTest.java b/extensions/entitystore-geode/src/test/java/org/apache/polygene/entitystore/geode/GeodeEntityStoreWithCacheTest.java
new file mode 100644
index 0000000..3b30a1b
--- /dev/null
+++ b/extensions/entitystore-geode/src/test/java/org/apache/polygene/entitystore/geode/GeodeEntityStoreWithCacheTest.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.entitystore.geode;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.geode.assembly.GeodeEntityStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.cache.AbstractEntityStoreWithCacheTest;
+
+public class GeodeEntityStoreWithCacheTest
+        extends AbstractEntityStoreWithCacheTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+            throws AssemblyException
+    {
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+        new GeodeEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+    }
+}
diff --git a/extensions/entitystore-hazelcast/README.persistent b/extensions/entitystore-hazelcast/README.persistent
index 43b9016..70bc272 100644
--- a/extensions/entitystore-hazelcast/README.persistent
+++ b/extensions/entitystore-hazelcast/README.persistent
@@ -17,7 +17,7 @@
 
     <?xml version="1.0" encoding="UTF-8"?>
     <hazelcast>
-        <map name="qi4j.data">
+        <map name="polygene.data">
             <map-store enabled="true">
                 <!--
                    Name of the class implementing MapLoader and/or MapStore.
diff --git a/extensions/entitystore-hazelcast/build.gradle b/extensions/entitystore-hazelcast/build.gradle
index edce38d..ae1046c 100644
--- a/extensions/entitystore-hazelcast/build.gradle
+++ b/extensions/entitystore-hazelcast/build.gradle
@@ -1,38 +1,38 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Hazelcast EntityStore Extension"
+apply plugin: 'polygene-extension'
 
-jar { manifest { name = "Apache Zest™ Extension - EntityStore - Hazelcast" }}
+description = "Apache Polygene™ Hazelcast EntityStore Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - EntityStore - Hazelcast" } }
 
 dependencies {
+  api polygene.core.bootstrap
+  api libraries.hazelcast
 
-    compile(project(":org.qi4j.core:org.qi4j.core.api"))
-    compile(project(":org.qi4j.core:org.qi4j.core.spi"))
-    compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-    compile(project(":org.qi4j.libraries:org.qi4j.library.locking"))
-    compile(libraries.hazelcast)
+  implementation polygene.library( 'locking' )
 
-    testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-    testCompile(project(":org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson"))
+  runtimeOnly polygene.core.runtime
 
-    testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-    testRuntime(libraries.logback)
+  testImplementation polygene.core.testsupport
 
+  testRuntimeOnly libraries.logback
 }
diff --git a/extensions/entitystore-hazelcast/dev-status.xml b/extensions/entitystore-hazelcast/dev-status.xml
index ac63cda..762e250 100644
--- a/extensions/entitystore-hazelcast/dev-status.xml
+++ b/extensions/entitystore-hazelcast/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
         <!--none,early,beta,stable,mature-->
         <codebase>stable</codebase>
diff --git a/extensions/entitystore-hazelcast/src/docs/es-hazelcast.txt b/extensions/entitystore-hazelcast/src/docs/es-hazelcast.txt
index e9b3dbf..1f3ef5a 100644
--- a/extensions/entitystore-hazelcast/src/docs/es-hazelcast.txt
+++ b/extensions/entitystore-hazelcast/src/docs/es-hazelcast.txt
@@ -35,7 +35,7 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-hazelcast/src/test/java/org/qi4j/entitystore/hazelcast/HazelcastEntityStoreTest.java
+source=extensions/entitystore-hazelcast/src/test/java/org/apache/polygene/entitystore/hazelcast/HazelcastEntityStoreTest.java
 tag=assembly
 ----
 
@@ -45,7 +45,7 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/HazelcastConfiguration.java
+source=extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/HazelcastConfiguration.java
 tag=config
 ----
 
diff --git a/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/HazelcastAccessors.java b/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/HazelcastAccessors.java
new file mode 100644
index 0000000..3924b8d
--- /dev/null
+++ b/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/HazelcastAccessors.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.entitystore.hazelcast;
+
+import com.hazelcast.core.HazelcastInstance;
+import com.hazelcast.core.IMap;
+
+public interface HazelcastAccessors
+{
+
+    HazelcastInstance hazelcastInstanceUsed();
+
+    IMap hazelcastMapUsed();
+
+}
diff --git a/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/HazelcastConfiguration.java b/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/HazelcastConfiguration.java
new file mode 100644
index 0000000..dd124b8
--- /dev/null
+++ b/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/HazelcastConfiguration.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.entitystore.hazelcast;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Configuration of HazelcastEntityStoreService.
+ */
+// START SNIPPET: config
+public interface HazelcastConfiguration
+{
+
+    @UseDefaults
+    Property<String> configXmlLocation();
+
+    @UseDefaults
+    Property<String> mapName();
+
+}
+// END SNIPPET: config
diff --git a/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/HazelcastEntityStoreMixin.java b/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/HazelcastEntityStoreMixin.java
new file mode 100644
index 0000000..749d980
--- /dev/null
+++ b/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/HazelcastEntityStoreMixin.java
@@ -0,0 +1,170 @@
+/*
+ *  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.polygene.entitystore.hazelcast;
+
+import com.hazelcast.config.ClasspathXmlConfig;
+import com.hazelcast.config.Config;
+import com.hazelcast.config.UrlXmlConfig;
+import com.hazelcast.core.Hazelcast;
+import com.hazelcast.core.HazelcastInstance;
+import com.hazelcast.core.IMap;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.stream.Stream;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.spi.entitystore.EntityNotFoundException;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+import org.apache.polygene.spi.entitystore.helpers.MapEntityStore;
+
+/**
+ * Hazelcast implementation of MapEntityStore.
+ */
+public class HazelcastEntityStoreMixin
+    implements ServiceActivation, HazelcastAccessors, MapEntityStore
+{
+
+    private static final String DEFAULT_MAPNAME = "polygene:entitystore:data";
+
+    @This
+    private Configuration<HazelcastConfiguration> config;
+
+    private IMap<String, String> stringMap;
+    private HazelcastInstance hazelcastInstance;
+
+    @Override
+    public void activateService()
+        throws Exception
+    {
+        HazelcastConfiguration configuration = config.get();
+        Config conf = createConfig( configuration );
+        hazelcastInstance = Hazelcast.newHazelcastInstance( conf );
+        String mapName = DEFAULT_MAPNAME;
+        if( configuration != null && configuration.mapName() != null )
+        {
+            mapName = configuration.mapName().get();
+        }
+        stringMap = hazelcastInstance.getMap( mapName );
+    }
+
+    @Override
+    public void passivateService()
+        throws Exception
+    {
+        stringMap = null;
+        hazelcastInstance.getLifecycleService().shutdown();
+    }
+
+    @Override
+    public HazelcastInstance hazelcastInstanceUsed()
+    {
+        return hazelcastInstance;
+    }
+
+    @Override
+    public IMap hazelcastMapUsed()
+    {
+        return stringMap;
+    }
+
+    @Override
+    public Reader get( EntityReference ref )
+        throws EntityStoreException
+    {
+        final String serializedState = stringMap.get( ref.identity().toString() );
+        if( serializedState == null )
+        {
+            throw new EntityNotFoundException( ref );
+        }
+        return new StringReader( serializedState );
+    }
+
+    @Override
+    public void applyChanges( MapChanges changes )
+        throws Exception
+    {
+        changes.visitMap( new MapChanger()
+        {
+
+            @Override
+            public Writer newEntity( final EntityReference ref, EntityDescriptor entityDescriptor )
+                throws IOException
+            {
+                return new StringWriter( 1000 )
+                {
+
+                    @Override
+                    public void close()
+                        throws IOException
+                    {
+                        super.close();
+                        stringMap.put( ref.identity().toString(), toString() );
+                    }
+                };
+            }
+
+            @Override
+            public Writer updateEntity( MapChange mapChange )
+                throws IOException
+            {
+                return newEntity( mapChange.reference(), mapChange.descriptor());
+            }
+
+            @Override
+            public void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor )
+                throws EntityNotFoundException
+            {
+                stringMap.remove( ref.identity().toString() );
+            }
+        } );
+    }
+
+    @Override
+    public Stream<Reader> entityStates()
+    {
+        return stringMap.values().stream().map( StringReader::new );
+    }
+
+    private Config createConfig( HazelcastConfiguration configuration )
+        throws IOException
+    {
+        String hzConfLocation = configuration.configXmlLocation().get();
+        if( hzConfLocation == null || hzConfLocation.isEmpty() )
+        {
+            hzConfLocation = "hazelcast-default.xml";
+        }
+        Config conf;
+        if( hzConfLocation.contains( ":" ) )
+        {
+            conf = new UrlXmlConfig( hzConfLocation );
+        }
+        else
+        {
+            conf = new ClasspathXmlConfig( hzConfLocation );
+        }
+        return conf;
+    }
+}
diff --git a/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/HazelcastEntityStoreService.java b/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/HazelcastEntityStoreService.java
new file mode 100644
index 0000000..b4f83dc
--- /dev/null
+++ b/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/HazelcastEntityStoreService.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.entitystore.hazelcast;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.library.locking.LockingAbstractComposite;
+import org.apache.polygene.spi.entitystore.ConcurrentModificationCheckConcern;
+import org.apache.polygene.spi.entitystore.EntityStateVersions;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.StateChangeNotificationConcern;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreActivation;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreMixin;
+
+/**
+ * Hazelcast EntityStore service.
+ * <p>Based on @{@link JSONMapEntityStoreMixin}.</p>
+ */
+@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
+@Mixins( { JSONMapEntityStoreMixin.class, HazelcastEntityStoreMixin.class } )
+public interface HazelcastEntityStoreService
+    extends ServiceActivation,
+            JSONMapEntityStoreActivation,
+            EntityStore,
+            EntityStateVersions,
+            LockingAbstractComposite,
+            Configuration,
+            HazelcastAccessors
+{
+}
diff --git a/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/assembly/HazelcastEntityStoreAssembler.java b/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/assembly/HazelcastEntityStoreAssembler.java
new file mode 100644
index 0000000..0fc1605
--- /dev/null
+++ b/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/assembly/HazelcastEntityStoreAssembler.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.entitystore.hazelcast.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.entitystore.hazelcast.HazelcastConfiguration;
+import org.apache.polygene.entitystore.hazelcast.HazelcastEntityStoreService;
+
+public class HazelcastEntityStoreAssembler
+    extends Assemblers.VisibilityIdentityConfig<HazelcastEntityStoreAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( HazelcastEntityStoreService.class ).
+            visibleIn( visibility() ).
+            instantiateOnStartup();
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+        if( hasConfig() )
+        {
+            configModule().entities( HazelcastConfiguration.class ).visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/assembly/package.html b/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/assembly/package.html
new file mode 100644
index 0000000..8ff97d0
--- /dev/null
+++ b/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Hazelcast EntityStore Assembly.</h2>
+    </body>
+</html>
diff --git a/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/package.html b/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/package.html
new file mode 100644
index 0000000..8ce54b6
--- /dev/null
+++ b/extensions/entitystore-hazelcast/src/main/java/org/apache/polygene/entitystore/hazelcast/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Hazelcast EntityStore.</h2>
+    </body>
+</html>
diff --git a/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/HazelcastAccessors.java b/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/HazelcastAccessors.java
deleted file mode 100644
index d760b79..0000000
--- a/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/HazelcastAccessors.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2009 Paul Merlin.
- * Copyright 2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.entitystore.hazelcast;
-
-import com.hazelcast.core.HazelcastInstance;
-import com.hazelcast.core.IMap;
-
-public interface HazelcastAccessors
-{
-
-    HazelcastInstance hazelcastInstanceUsed();
-
-    IMap hazelcastMapUsed();
-
-}
diff --git a/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/HazelcastConfiguration.java b/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/HazelcastConfiguration.java
deleted file mode 100644
index a3fa3e5..0000000
--- a/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/HazelcastConfiguration.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2009 Paul Merlin.
- * Copyright 2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.entitystore.hazelcast;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-/**
- * Configuration of HazelcastEntityStoreService.
- */
-// START SNIPPET: config
-public interface HazelcastConfiguration
-        extends ConfigurationComposite
-{
-
-    @UseDefaults
-    Property<String> configXmlLocation();
-
-    @UseDefaults
-    Property<String> mapName();
-
-}
-// END SNIPPET: config
diff --git a/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/HazelcastEntityStoreMixin.java b/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/HazelcastEntityStoreMixin.java
deleted file mode 100644
index ebc54a0..0000000
--- a/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/HazelcastEntityStoreMixin.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright 2009-2014 Paul Merlin.
- * Copyright 2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.entitystore.hazelcast;
-
-import com.hazelcast.config.ClasspathXmlConfig;
-import com.hazelcast.config.Config;
-import com.hazelcast.config.UrlXmlConfig;
-import com.hazelcast.core.Hazelcast;
-import com.hazelcast.core.HazelcastInstance;
-import com.hazelcast.core.IMap;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.Map;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.spi.entitystore.EntityNotFoundException;
-import org.qi4j.spi.entitystore.EntityStoreException;
-import org.qi4j.spi.entitystore.helpers.MapEntityStore;
-
-/**
- * Hazelcast implementation of MapEntityStore.
- */
-public class HazelcastEntityStoreMixin
-    implements ServiceActivation, HazelcastAccessors, MapEntityStore
-{
-
-    private static final String DEFAULT_MAPNAME = "qi4j:entitystore:data";
-
-    @This
-    private Configuration<HazelcastConfiguration> config;
-
-    private IMap<String, String> stringMap;
-    private HazelcastInstance hazelcastInstance;
-
-    @Override
-    public void activateService()
-        throws Exception
-    {
-        HazelcastConfiguration configuration = config.get();
-        Config conf = createConfig( configuration );
-        hazelcastInstance = Hazelcast.newHazelcastInstance( conf );
-        String mapName = DEFAULT_MAPNAME;
-        if( configuration != null && configuration.mapName() != null )
-        {
-            mapName = configuration.mapName().get();
-        }
-        stringMap = hazelcastInstance.getMap( mapName );
-    }
-
-    @Override
-    public void passivateService()
-        throws Exception
-    {
-        stringMap = null;
-        hazelcastInstance.getLifecycleService().shutdown();
-    }
-
-    @Override
-    public HazelcastInstance hazelcastInstanceUsed()
-    {
-        return hazelcastInstance;
-    }
-
-    @Override
-    public IMap hazelcastMapUsed()
-    {
-        return stringMap;
-    }
-
-    @Override
-    public Reader get( EntityReference ref )
-        throws EntityStoreException
-    {
-        final String serializedState = stringMap.get( ref.identity() );
-        if( serializedState == null )
-        {
-            throw new EntityNotFoundException( ref );
-        }
-        return new StringReader( serializedState );
-    }
-
-    @Override
-    public void applyChanges( MapChanges changes )
-        throws IOException
-    {
-        changes.visitMap( new MapChanger()
-        {
-
-            @Override
-            public Writer newEntity( final EntityReference ref, EntityDescriptor entityDescriptor )
-                throws IOException
-            {
-                return new StringWriter( 1000 )
-                {
-
-                    @Override
-                    public void close()
-                        throws IOException
-                    {
-                        super.close();
-                        stringMap.put( ref.identity(), toString() );
-                    }
-                };
-            }
-
-            @Override
-            public Writer updateEntity( EntityReference ref, EntityDescriptor entityDescriptor )
-                throws IOException
-            {
-                return newEntity( ref, entityDescriptor );
-            }
-
-            @Override
-            public void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor )
-                throws EntityNotFoundException
-            {
-                stringMap.remove( ref.identity() );
-            }
-        } );
-    }
-
-    @Override
-    public Input<Reader, IOException> entityStates()
-    {
-        return new Input<Reader, IOException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super Reader, ReceiverThrowableType> output )
-                throws IOException, ReceiverThrowableType
-            {
-                output.receiveFrom( new Sender<Reader, IOException>()
-                {
-                    @Override
-                    public <RTT extends Throwable> void sendTo( Receiver<? super Reader, RTT> receiver )
-                        throws RTT, IOException
-                    {
-                        for( Map.Entry<String, String> eachEntry : stringMap.entrySet() )
-                        {
-                            receiver.receive( new StringReader( eachEntry.getValue() ) );
-                        }
-                    }
-                } );
-            }
-        };
-    }
-
-    private Config createConfig( HazelcastConfiguration configuration )
-        throws IOException
-    {
-        String hzConfLocation = configuration.configXmlLocation().get();
-        if( hzConfLocation == null || hzConfLocation.isEmpty() )
-        {
-            hzConfLocation = "hazelcast-default.xml";
-        }
-        Config conf;
-        if( hzConfLocation.contains( ":" ) )
-        {
-            conf = new UrlXmlConfig( hzConfLocation );
-        }
-        else
-        {
-            conf = new ClasspathXmlConfig( hzConfLocation );
-        }
-        return conf;
-    }
-}
diff --git a/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/HazelcastEntityStoreService.java b/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/HazelcastEntityStoreService.java
deleted file mode 100644
index 70447ac..0000000
--- a/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/HazelcastEntityStoreService.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2009 Paul Merlin.
- * Copyright 2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.entitystore.hazelcast;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.library.locking.LockingAbstractComposite;
-import org.qi4j.spi.entitystore.ConcurrentModificationCheckConcern;
-import org.qi4j.spi.entitystore.EntityStateVersions;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.StateChangeNotificationConcern;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreActivation;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreMixin;
-
-/**
- * Hazelcast EntityStore service.
- * <p>Based on @{@link JSONMapEntityStoreMixin}.</p>
- */
-@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
-@Mixins( { JSONMapEntityStoreMixin.class, HazelcastEntityStoreMixin.class } )
-public interface HazelcastEntityStoreService
-    extends ServiceActivation,
-            JSONMapEntityStoreActivation,
-            EntityStore,
-            EntityStateVersions,
-            ServiceComposite,
-            LockingAbstractComposite,
-            Configuration,
-            HazelcastAccessors
-{
-}
diff --git a/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/assembly/HazelcastEntityStoreAssembler.java b/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/assembly/HazelcastEntityStoreAssembler.java
deleted file mode 100644
index 9d61280..0000000
--- a/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/assembly/HazelcastEntityStoreAssembler.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2009 Paul Merlin.
- * Copyright 2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.entitystore.hazelcast.assembly;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.entitystore.hazelcast.HazelcastConfiguration;
-import org.qi4j.entitystore.hazelcast.HazelcastEntityStoreService;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-
-public class HazelcastEntityStoreAssembler
-    extends Assemblers.VisibilityIdentityConfig<HazelcastEntityStoreAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( UuidIdentityGeneratorService.class ).visibleIn( visibility() );
-        ServiceDeclaration service = module.services( HazelcastEntityStoreService.class ).
-            visibleIn( visibility() ).
-            instantiateOnStartup();
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        if( hasConfig() )
-        {
-            configModule().entities( HazelcastConfiguration.class ).visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/assembly/package.html b/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/assembly/package.html
deleted file mode 100644
index 297a76b..0000000
--- a/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/assembly/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Hazelcast EntityStore Assembly.</h2>
-    </body>
-</html>
diff --git a/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/package.html b/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/package.html
deleted file mode 100644
index 9a06db0..0000000
--- a/extensions/entitystore-hazelcast/src/main/java/org/qi4j/entitystore/hazelcast/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Hazelcast EntityStore.</h2>
-    </body>
-</html>
diff --git a/extensions/entitystore-hazelcast/src/test/java/org/apache/polygene/entitystore/hazelcast/HazelcastEntityStoreTest.java b/extensions/entitystore-hazelcast/src/test/java/org/apache/polygene/entitystore/hazelcast/HazelcastEntityStoreTest.java
new file mode 100644
index 0000000..c2d705f
--- /dev/null
+++ b/extensions/entitystore-hazelcast/src/test/java/org/apache/polygene/entitystore/hazelcast/HazelcastEntityStoreTest.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.entitystore.hazelcast;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.hazelcast.assembly.HazelcastEntityStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+import org.junit.After;
+import org.junit.Test;
+
+public class HazelcastEntityStoreTest
+    extends AbstractEntityStoreTest
+{
+
+    @Override
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // END SNIPPET: assembly
+        super.assemble( module );
+        ModuleAssembly configModule = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( configModule );
+        // START SNIPPET: assembly
+        new HazelcastEntityStoreAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
+    }
+    // END SNIPPET: assembly
+
+    @Test
+    @Override
+    public void givenConcurrentUnitOfWorksWhenUoWCompletesThenCheckConcurrentModification()
+        throws UnitOfWorkCompletionException
+    {
+        super.givenConcurrentUnitOfWorksWhenUoWCompletesThenCheckConcurrentModification();
+    }
+
+    @After
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        super.tearDown();
+        // TODO : delete test data
+    }
+}
diff --git a/extensions/entitystore-hazelcast/src/test/java/org/apache/polygene/entitystore/hazelcast/HazelcastEntityStoreWithCacheTest.java b/extensions/entitystore-hazelcast/src/test/java/org/apache/polygene/entitystore/hazelcast/HazelcastEntityStoreWithCacheTest.java
new file mode 100644
index 0000000..2b0cfa1
--- /dev/null
+++ b/extensions/entitystore-hazelcast/src/test/java/org/apache/polygene/entitystore/hazelcast/HazelcastEntityStoreWithCacheTest.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.entitystore.hazelcast;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.hazelcast.assembly.HazelcastEntityStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.cache.AbstractEntityStoreWithCacheTest;
+
+public class HazelcastEntityStoreWithCacheTest
+    extends AbstractEntityStoreWithCacheTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+        new HazelcastEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+    }
+}
diff --git a/extensions/entitystore-hazelcast/src/test/java/org/qi4j/entitystore/hazelcast/HazelcastEntityStoreTest.java b/extensions/entitystore-hazelcast/src/test/java/org/qi4j/entitystore/hazelcast/HazelcastEntityStoreTest.java
deleted file mode 100644
index 8d6aedd..0000000
--- a/extensions/entitystore-hazelcast/src/test/java/org/qi4j/entitystore/hazelcast/HazelcastEntityStoreTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2009 Paul Merlin.
- * Copyright 2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.entitystore.hazelcast;
-
-import org.junit.After;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.hazelcast.assembly.HazelcastEntityStoreAssembler;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class HazelcastEntityStoreTest
-    extends AbstractEntityStoreTest
-{
-
-    @Override
-    // START SNIPPET: assembly
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // END SNIPPET: assembly
-        super.assemble( module );
-        ModuleAssembly configModule = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( configModule );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        // START SNIPPET: assembly
-        new HazelcastEntityStoreAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
-    }
-    // END SNIPPET: assembly
-
-    @Test
-    @Override
-    public void givenConcurrentUnitOfWorksWhenUoWCompletesThenCheckConcurrentModification()
-        throws UnitOfWorkCompletionException
-    {
-        super.givenConcurrentUnitOfWorksWhenUoWCompletesThenCheckConcurrentModification();
-    }
-
-    @After
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        super.tearDown();
-        // TODO : delete test data
-    }
-}
diff --git a/extensions/entitystore-hazelcast/src/test/java/org/qi4j/entitystore/hazelcast/HazelcastEntityStoreWithCacheTest.java b/extensions/entitystore-hazelcast/src/test/java/org/qi4j/entitystore/hazelcast/HazelcastEntityStoreWithCacheTest.java
deleted file mode 100644
index 8b8f032..0000000
--- a/extensions/entitystore-hazelcast/src/test/java/org/qi4j/entitystore/hazelcast/HazelcastEntityStoreWithCacheTest.java
+++ /dev/null
@@ -1,40 +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.qi4j.entitystore.hazelcast;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.hazelcast.assembly.HazelcastEntityStoreAssembler;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.cache.AbstractEntityStoreWithCacheTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class HazelcastEntityStoreWithCacheTest
-    extends AbstractEntityStoreWithCacheTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        new HazelcastEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
-    }
-}
diff --git a/extensions/entitystore-hazelcast/src/test/resources/org/apache/polygene/entitystore/hazelcast/HazelcastEntityStoreService.properties b/extensions/entitystore-hazelcast/src/test/resources/org/apache/polygene/entitystore/hazelcast/HazelcastEntityStoreService.properties
new file mode 100644
index 0000000..e898a18
--- /dev/null
+++ b/extensions/entitystore-hazelcast/src/test/resources/org/apache/polygene/entitystore/hazelcast/HazelcastEntityStoreService.properties
@@ -0,0 +1,21 @@
+#
+#  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.
+#
+#
+#
+
+mapName=polygene.data
\ No newline at end of file
diff --git a/extensions/entitystore-hazelcast/src/test/resources/org/apache/polygene/entitystore/hazelcast/hazelcast.xml b/extensions/entitystore-hazelcast/src/test/resources/org/apache/polygene/entitystore/hazelcast/hazelcast.xml
new file mode 100644
index 0000000..cc52305
--- /dev/null
+++ b/extensions/entitystore-hazelcast/src/test/resources/org/apache/polygene/entitystore/hazelcast/hazelcast.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<hazelcast>
+  <map name="polygene.data">
+    <map-store enabled="true">
+      <!--
+         Name of the class implementing MapLoader and/or MapStore.
+         The class should implement at least of these interfaces and
+         contain no-argument constructor.
+      -->
+      <class-name>TODO</class-name>
+      <!--
+         Number of seconds to delay to call the MapStore.store(key, value).
+         If the value is zero then it is write-through so MapStore.store(key, value)
+         will be called as soon as the entry is updated.
+         Otherwise it is write-behind so updates will be stored after write-delay-seconds
+         value by calling Hazelcast.storeAll(map). Default value is 0.
+      -->
+      <write-delay-seconds>0</write-delay-seconds>
+    </map-store>
+  </map>
+</hazelcast>
\ No newline at end of file
diff --git a/extensions/entitystore-hazelcast/src/test/resources/org/qi4j/entitystore/hazelcast/HazelcastEntityStoreService.properties b/extensions/entitystore-hazelcast/src/test/resources/org/qi4j/entitystore/hazelcast/HazelcastEntityStoreService.properties
deleted file mode 100644
index 69cf7eb..0000000
--- a/extensions/entitystore-hazelcast/src/test/resources/org/qi4j/entitystore/hazelcast/HazelcastEntityStoreService.properties
+++ /dev/null
@@ -1,16 +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.
-
-mapName=qi4j.data
\ No newline at end of file
diff --git a/extensions/entitystore-hazelcast/src/test/resources/org/qi4j/entitystore/hazelcast/hazelcast.xml b/extensions/entitystore-hazelcast/src/test/resources/org/qi4j/entitystore/hazelcast/hazelcast.xml
deleted file mode 100644
index 28b13fa..0000000
--- a/extensions/entitystore-hazelcast/src/test/resources/org/qi4j/entitystore/hazelcast/hazelcast.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<hazelcast>
-  <map name="qi4j.data">
-    <map-store enabled="true">
-      <!--
-         Name of the class implementing MapLoader and/or MapStore.
-         The class should implement at least of these interfaces and
-         contain no-argument constructor.
-      -->
-      <class-name>TODO</class-name>
-      <!--
-         Number of seconds to delay to call the MapStore.store(key, value).
-         If the value is zero then it is write-through so MapStore.store(key, value)
-         will be called as soon as the entry is updated.
-         Otherwise it is write-behind so updates will be stored after write-delay-seconds
-         value by calling Hazelcast.storeAll(map). Default value is 0.
-      -->
-      <write-delay-seconds>0</write-delay-seconds>
-    </map-store>
-  </map>
-</hazelcast>
\ No newline at end of file
diff --git a/extensions/entitystore-jclouds/build.gradle b/extensions/entitystore-jclouds/build.gradle
index 23596c3..8db7d5c 100644
--- a/extensions/entitystore-jclouds/build.gradle
+++ b/extensions/entitystore-jclouds/build.gradle
@@ -1,39 +1,43 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ JClouds EntityStore Extension"
+apply plugin: 'polygene-extension'
 
-jar { manifest { name = "Apache Zest™ Extension - EntityStore - JClouds" } }
+description = "Apache Polygene™ JClouds EntityStore Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - EntityStore - JClouds" } }
 
 dependencies {
+  api polygene.core.bootstrap
+  api polygene.library( 'fileconfig' )
 
-  compile project( ":org.qi4j.core:org.qi4j.core.bootstrap" )
-  compile project( ":org.qi4j.libraries:org.qi4j.library.locking" )
-  compile libraries.slf4j_api
-  compile libraries.jclouds_core
-  compile libraries.jclouds_blobstore
+  implementation polygene.library( 'locking' )
+  implementation libraries.slf4j_api
+  implementation libraries.jclouds_core
+  implementation libraries.jclouds_blobstore
 
-  testCompile project( ":org.qi4j.core:org.qi4j.core.testsupport" )
-  testCompile( project( ":org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson" ) )
-  testCompile libraries.jclouds_filesystem
+  runtimeOnly polygene.core.runtime
+  runtimeOnly libraries.jaxb_api
 
-  testRuntime project( ":org.qi4j.core:org.qi4j.core.runtime" )
-  testRuntime libraries.logback
+  testImplementation polygene.internals.testsupport
+  testImplementation libraries.jclouds_filesystem
+
+  testRuntimeOnly libraries.logback
 }
-
diff --git a/extensions/entitystore-jclouds/dev-status.xml b/extensions/entitystore-jclouds/dev-status.xml
index 7b2bb11..ff99de4 100644
--- a/extensions/entitystore-jclouds/dev-status.xml
+++ b/extensions/entitystore-jclouds/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
         <codebase>stable</codebase>
         <!--none,early,beta,stable,mature-->
diff --git a/extensions/entitystore-jclouds/src/docs/es-jclouds.txt b/extensions/entitystore-jclouds/src/docs/es-jclouds.txt
index baaddf2..7f8b053 100644
--- a/extensions/entitystore-jclouds/src/docs/es-jclouds.txt
+++ b/extensions/entitystore-jclouds/src/docs/es-jclouds.txt
@@ -44,7 +44,7 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-jclouds/src/test/java/org/qi4j/entitystore/jclouds/JCloudsTransientTest.java
+source=extensions/entitystore-jclouds/src/test/java/org/apache/polygene/entitystore/jclouds/JCloudsTransientTest.java
 tag=assembly
 ----
 
@@ -54,6 +54,6 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-jclouds/src/main/java/org/qi4j/entitystore/jclouds/JCloudsMapEntityStoreConfiguration.java
+source=extensions/entitystore-jclouds/src/main/java/org/apache/polygene/entitystore/jclouds/JCloudsMapEntityStoreConfiguration.java
 tag=config
 ----
diff --git a/extensions/entitystore-jclouds/src/main/java/org/apache/polygene/entitystore/jclouds/JCloudsMapEntityStoreConfiguration.java b/extensions/entitystore-jclouds/src/main/java/org/apache/polygene/entitystore/jclouds/JCloudsMapEntityStoreConfiguration.java
new file mode 100644
index 0000000..8782ec9
--- /dev/null
+++ b/extensions/entitystore-jclouds/src/main/java/org/apache/polygene/entitystore/jclouds/JCloudsMapEntityStoreConfiguration.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.entitystore.jclouds;
+
+import java.util.Map;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Configuration of JCloudsMapEntityStore service.
+ */
+public interface JCloudsMapEntityStoreConfiguration
+{
+    // START SNIPPET: config
+    /**
+     * Name of the JClouds provider to use. Defaults to 'transient'.
+     */
+    @Optional Property<String> provider();
+    @UseDefaults Property<String> identifier();
+    @UseDefaults Property<String> credential();
+    /**
+     * Use this to fine tune your provider implementation according to JClouds documentation.
+     */
+    @UseDefaults Property<Map<String, String>> properties();
+    /**
+     * Name of the JClouds container to use. Defaults to 'polygene-entities'.
+     */
+    @Optional Property<String> container();
+    /**
+     * Endpoint for the BlobStore provider.
+     */
+    @Optional Property<String> endpoint();
+    // END SNIPPET: config
+
+}
diff --git a/extensions/entitystore-jclouds/src/main/java/org/apache/polygene/entitystore/jclouds/JCloudsMapEntityStoreMixin.java b/extensions/entitystore-jclouds/src/main/java/org/apache/polygene/entitystore/jclouds/JCloudsMapEntityStoreMixin.java
new file mode 100644
index 0000000..2ab821b
--- /dev/null
+++ b/extensions/entitystore-jclouds/src/main/java/org/apache/polygene/entitystore/jclouds/JCloudsMapEntityStoreMixin.java
@@ -0,0 +1,284 @@
+/*
+ *  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.polygene.entitystore.jclouds;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+import com.google.common.io.ByteSource;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.stream.Stream;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.spi.entitystore.EntityNotFoundException;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+import org.apache.polygene.spi.entitystore.helpers.MapEntityStore;
+import org.jclouds.ContextBuilder;
+import org.jclouds.apis.ApiMetadata;
+import org.jclouds.apis.Apis;
+import org.jclouds.blobstore.BlobStore;
+import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.blobstore.domain.Blob;
+import org.jclouds.io.Payload;
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.providers.Providers;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.google.common.base.Charsets.UTF_8;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Iterables.contains;
+
+/**
+ * JClouds implementation of MapEntityStore.
+ */
+// TODO Expose Location in configuration
+//      To be done once JClouds 1.5 has stabilized their Location API.
+//      A list of ISO-3166 country codes.
+//      It defines where your entities are allowed to be stored.
+//      @UseDefaults Property<List<String>> geopoliticalBoundaries(); ???
+//      SEE  http://www.jclouds.org/documentation/reference/location-metadata-design
+public class JCloudsMapEntityStoreMixin
+    implements ServiceActivation, MapEntityStore
+{
+
+    private static final Logger LOGGER = LoggerFactory.getLogger( "org.apache.polygene.entitystore.jclouds" );
+
+    private static final Map<String, ApiMetadata> allApis = Maps.uniqueIndex(
+        Apis.viewableAs( BlobStoreContext.class ),
+        Apis.idFunction()
+    );
+
+    private static final Map<String, ProviderMetadata> appProviders = Maps.uniqueIndex(
+        Providers.viewableAs( BlobStoreContext.class ),
+        Providers.idFunction()
+    );
+
+    private static final Set<String> allKeys = ImmutableSet.copyOf(
+        Iterables.concat( appProviders.keySet(), allApis.keySet() )
+    );
+
+    @This
+    private Configuration<JCloudsMapEntityStoreConfiguration> configuration;
+
+    private BlobStoreContext storeContext;
+
+    private String container;
+
+    @Override
+    public void activateService()
+        throws Exception
+    {
+        configuration.refresh();
+        String provider = configuration.get().provider().get();
+        String identifier = configuration.get().identifier().get();
+        String credentials = configuration.get().credential().get();
+        String endpoint = configuration.get().endpoint().get();
+        Map<String, String> properties = configuration.get().properties().get();
+        container = configuration.get().container().get();
+        if( provider != null )
+        {
+            checkArgument( contains( allKeys, provider ), "provider %s not in supported list: %s", provider, allKeys );
+        }
+        else
+        {
+            provider = "transient";
+        }
+        if( container == null )
+        {
+            container = "polygene-entities";
+        }
+        storeContext = ContextBuilder.newBuilder( provider )
+                                     .endpoint( endpoint == null ? "" : endpoint )
+                                     .credentials( identifier, credentials )
+                                     .overrides( asProperties( properties ) )
+                                     .buildView( BlobStoreContext.class );
+        BlobStore blobStore = storeContext.getBlobStore();
+        if( !blobStore.containerExists( container ) )
+        {
+            if( !blobStore.createContainerInLocation( null, container ) )
+            {
+                throw new EntityStoreException( "Unable to create JClouds Blob Container, cannot continue." );
+            }
+            else
+            {
+                LOGGER.debug( "Created new container: {}", container );
+            }
+        }
+        LOGGER.info( "Activated using {} cloud provider [id:{}]", provider, identifier );
+    }
+
+    private Properties asProperties( Map<String, String> map )
+    {
+        Properties props = new Properties();
+        for( Map.Entry<String, String> eachEntry : map.entrySet() )
+        {
+            props.put( eachEntry.getKey(), eachEntry.getValue() );
+        }
+        return props;
+    }
+
+    @Override
+    public void passivateService()
+        throws Exception
+    {
+        if( storeContext != null )
+        {
+            storeContext.close();
+            storeContext = null;
+            container = null;
+        }
+    }
+
+    @Override
+    public Reader get( EntityReference entityReference )
+        throws EntityStoreException
+    {
+        Blob blob = storeContext.getBlobStore().getBlob( container, entityReference.identity().toString() );
+        if( blob == null )
+        {
+            throw new EntityNotFoundException( entityReference );
+        }
+        Payload payload = blob.getPayload();
+        if( payload == null )
+        {
+            throw new EntityNotFoundException( entityReference );
+        }
+        try( InputStream input = payload.openStream() )
+        {
+            String state = new Scanner( input, StandardCharsets.UTF_8.name() ).useDelimiter( "\\Z" ).next();
+            return new StringReader( state );
+        }
+        catch( IOException ex )
+        {
+            throw new EntityStoreException( "Unable to read entity state for: " + entityReference, ex );
+        }
+    }
+
+    @Override
+    public void applyChanges( MapChanges changes )
+        throws Exception
+    {
+        final BlobStore blobStore = storeContext.getBlobStore();
+        changes.visitMap(
+            new MapChanger()
+            {
+                @Override
+                public Writer newEntity( final EntityReference ref, EntityDescriptor entityDescriptor )
+                    throws IOException
+                {
+                    return new StringWriter()
+                    {
+                        @Override
+                        public void close()
+                            throws IOException
+                        {
+                            super.close();
+                            ByteSource payload = ByteSource.wrap( toString().getBytes( UTF_8 ) );
+                            Blob blob = blobStore.blobBuilder( ref.identity().toString() )
+                                                 .payload( payload )
+                                                 .contentLength( payload.size() )
+                                                 .build();
+                            blobStore.putBlob( container, blob );
+                        }
+                    };
+                }
+
+                @Override
+                public Writer updateEntity( MapChange mapChange )
+                    throws IOException
+                {
+                    String identity = mapChange.reference().identity().toString();
+                    if( !blobStore.blobExists( container, identity ) )
+                    {
+                        throw new EntityNotFoundException( mapChange.reference() );
+                    }
+                    return new StringWriter()
+                    {
+                        @Override
+                        public void close()
+                            throws IOException
+                        {
+                            super.close();
+                            ByteSource payload = ByteSource.wrap( toString().getBytes( UTF_8 ) );
+                            Blob blob = blobStore.blobBuilder( identity )
+                                                 .payload( payload )
+                                                 .contentLength( payload.size() )
+                                                 .build();
+                            blobStore.putBlob( container, blob );
+                        }
+                    };
+                }
+
+                @Override
+                public void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor )
+                    throws EntityNotFoundException
+                {
+                    if( !blobStore.blobExists( container, ref.identity().toString() ) )
+                    {
+                        throw new EntityNotFoundException( ref );
+                    }
+                    blobStore.removeBlob( container, ref.identity().toString() );
+                }
+            }
+        );
+    }
+
+    @Override
+    public Stream<Reader> entityStates()
+    {
+        return storeContext
+            .getBlobStore().list( container ).stream()
+            .map( metadata ->
+                  {
+                      Payload payload = storeContext.getBlobStore()
+                                                    .getBlob( container, metadata.getName() )
+                                                    .getPayload();
+                      if( payload == null )
+                      {
+                          EntityReference reference = EntityReference.parseEntityReference( metadata.getName() );
+                          throw new EntityNotFoundException( reference );
+                      }
+                      try( InputStream input = payload.openStream() )
+                      {
+                          String state = new Scanner( input, UTF_8.name() ).useDelimiter( "\\Z" ).next();
+                          return (Reader) new StringReader( state );
+                      }
+                      catch( IOException ex )
+                      {
+                          throw new EntityStoreException( ex );
+                      }
+                  } );
+    }
+}
diff --git a/extensions/entitystore-jclouds/src/main/java/org/apache/polygene/entitystore/jclouds/JCloudsMapEntityStoreService.java b/extensions/entitystore-jclouds/src/main/java/org/apache/polygene/entitystore/jclouds/JCloudsMapEntityStoreService.java
new file mode 100644
index 0000000..332be21
--- /dev/null
+++ b/extensions/entitystore-jclouds/src/main/java/org/apache/polygene/entitystore/jclouds/JCloudsMapEntityStoreService.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.entitystore.jclouds;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.library.locking.LockingAbstractComposite;
+import org.apache.polygene.spi.entitystore.ConcurrentModificationCheckConcern;
+import org.apache.polygene.spi.entitystore.EntityStateVersions;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.StateChangeNotificationConcern;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreActivation;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreMixin;
+
+/**
+ * JClouds EntityStore service.
+ * <p>Based on @{@link JSONMapEntityStoreMixin}.</p>
+ */
+@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
+@Mixins( { JSONMapEntityStoreMixin.class, JCloudsMapEntityStoreMixin.class } )
+public interface JCloudsMapEntityStoreService
+    extends ServiceActivation,
+            JSONMapEntityStoreActivation,
+            EntityStore,
+            EntityStateVersions,
+            LockingAbstractComposite,
+            Configuration
+{
+}
diff --git a/extensions/entitystore-jclouds/src/main/java/org/apache/polygene/entitystore/jclouds/assembly/JCloudsEntityStoreAssembler.java b/extensions/entitystore-jclouds/src/main/java/org/apache/polygene/entitystore/jclouds/assembly/JCloudsEntityStoreAssembler.java
new file mode 100644
index 0000000..304e7dd
--- /dev/null
+++ b/extensions/entitystore-jclouds/src/main/java/org/apache/polygene/entitystore/jclouds/assembly/JCloudsEntityStoreAssembler.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.entitystore.jclouds.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.entitystore.jclouds.JCloudsMapEntityStoreConfiguration;
+import org.apache.polygene.entitystore.jclouds.JCloudsMapEntityStoreService;
+
+public class JCloudsEntityStoreAssembler
+    extends Assemblers.VisibilityIdentityConfig<JCloudsEntityStoreAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( JCloudsMapEntityStoreService.class ).
+            visibleIn( visibility() ).
+            instantiateOnStartup();
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+        if( hasConfig() )
+        {
+            configModule().entities( JCloudsMapEntityStoreConfiguration.class ).visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/extensions/entitystore-jclouds/src/main/java/org/apache/polygene/entitystore/jclouds/package.html b/extensions/entitystore-jclouds/src/main/java/org/apache/polygene/entitystore/jclouds/package.html
new file mode 100644
index 0000000..fbac24f
--- /dev/null
+++ b/extensions/entitystore-jclouds/src/main/java/org/apache/polygene/entitystore/jclouds/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>JClouds BlobStore EntityStore.</h2>
+    </body>
+</html>
diff --git a/extensions/entitystore-jclouds/src/main/java/org/qi4j/entitystore/jclouds/JCloudsMapEntityStoreAssembler.java b/extensions/entitystore-jclouds/src/main/java/org/qi4j/entitystore/jclouds/JCloudsMapEntityStoreAssembler.java
deleted file mode 100644
index 095f01f..0000000
--- a/extensions/entitystore-jclouds/src/main/java/org/qi4j/entitystore/jclouds/JCloudsMapEntityStoreAssembler.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.jclouds;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-
-public class JCloudsMapEntityStoreAssembler
-    extends Assemblers.VisibilityIdentityConfig<JCloudsMapEntityStoreAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( UuidIdentityGeneratorService.class );
-        ServiceDeclaration service = module.services( JCloudsMapEntityStoreService.class ).
-            visibleIn( visibility() ).
-            instantiateOnStartup();
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        if( hasConfig() )
-        {
-            configModule().entities( JCloudsMapEntityStoreConfiguration.class ).visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/extensions/entitystore-jclouds/src/main/java/org/qi4j/entitystore/jclouds/JCloudsMapEntityStoreConfiguration.java b/extensions/entitystore-jclouds/src/main/java/org/qi4j/entitystore/jclouds/JCloudsMapEntityStoreConfiguration.java
deleted file mode 100644
index 0dcddf4..0000000
--- a/extensions/entitystore-jclouds/src/main/java/org/qi4j/entitystore/jclouds/JCloudsMapEntityStoreConfiguration.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.jclouds;
-
-import java.util.Map;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-/**
- * Configuration of JCloudsMapEntityStore service.
- */
-public interface JCloudsMapEntityStoreConfiguration
-        extends ConfigurationComposite
-{
-    // START SNIPPET: config
-    /**
-     * Name of the JClouds provider to use. Defaults to 'transient'.
-     */
-    @Optional Property<String> provider();
-    @UseDefaults Property<String> identifier();
-    @UseDefaults Property<String> credential();
-    /**
-     * Use this to fine tune your provider implementation according to JClouds documentation.
-     */
-    @UseDefaults Property<Map<String, String>> properties();
-    /**
-     * Name of the JClouds container to use. Defaults to 'qi4j-entities'.
-     */
-    @Optional Property<String> container();
-    // END SNIPPET: config
-
-}
diff --git a/extensions/entitystore-jclouds/src/main/java/org/qi4j/entitystore/jclouds/JCloudsMapEntityStoreMixin.java b/extensions/entitystore-jclouds/src/main/java/org/qi4j/entitystore/jclouds/JCloudsMapEntityStoreMixin.java
deleted file mode 100644
index c250dcd..0000000
--- a/extensions/entitystore-jclouds/src/main/java/org/qi4j/entitystore/jclouds/JCloudsMapEntityStoreMixin.java
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.jclouds;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
-import com.google.common.io.ByteSource;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import org.jclouds.ContextBuilder;
-import org.jclouds.apis.ApiMetadata;
-import org.jclouds.apis.Apis;
-import org.jclouds.blobstore.BlobStore;
-import org.jclouds.blobstore.BlobStoreContext;
-import org.jclouds.blobstore.domain.Blob;
-import org.jclouds.blobstore.domain.StorageMetadata;
-import org.jclouds.io.Payload;
-import org.jclouds.providers.ProviderMetadata;
-import org.jclouds.providers.Providers;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.io.Input;
-import org.qi4j.io.Inputs;
-import org.qi4j.io.Output;
-import org.qi4j.io.Outputs;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.spi.entitystore.EntityNotFoundException;
-import org.qi4j.spi.entitystore.EntityStoreException;
-import org.qi4j.spi.entitystore.helpers.MapEntityStore;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static com.google.common.base.Charsets.UTF_8;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Iterables.contains;
-import static org.qi4j.api.entity.EntityReference.parseEntityReference;
-
-/**
- * JClouds implementation of MapEntityStore.
- */
-// TODO Expose Location in configuration
-//      To be done once JClouds 1.5 has stabilized their Location API.
-//      A list of ISO-3166 country codes.
-//      It defines where your entities are allowed to be stored.
-//      @UseDefaults Property<List<String>> geopoliticalBoundaries(); ???
-//      SEE  http://www.jclouds.org/documentation/reference/location-metadata-design
-public class JCloudsMapEntityStoreMixin
-    implements ServiceActivation, MapEntityStore
-{
-
-    private static final Logger LOGGER = LoggerFactory.getLogger( "org.qi4j.entitystore.jclouds" );
-
-    private static final Map<String, ApiMetadata> allApis = Maps.uniqueIndex(
-        Apis.viewableAs( BlobStoreContext.class ),
-        Apis.idFunction()
-    );
-
-    private static final Map<String, ProviderMetadata> appProviders = Maps.uniqueIndex(
-        Providers.viewableAs( BlobStoreContext.class ),
-        Providers.idFunction()
-    );
-
-    private static final Set<String> allKeys = ImmutableSet.copyOf(
-        Iterables.concat( appProviders.keySet(), allApis.keySet() )
-    );
-
-    @This
-    private Configuration<JCloudsMapEntityStoreConfiguration> configuration;
-
-    private BlobStoreContext storeContext;
-
-    private String container;
-
-    @Override
-    public void activateService()
-        throws Exception
-    {
-        configuration.refresh();
-        String provider = configuration.get().provider().get();
-        String identifier = configuration.get().identifier().get();
-        String credentials = configuration.get().credential().get();
-        Map<String, String> properties = configuration.get().properties().get();
-        container = configuration.get().container().get();
-        if( provider != null )
-        {
-            checkArgument( contains( allKeys, provider ), "provider %s not in supported list: %s", provider, allKeys );
-        }
-        else
-        {
-            provider = "transient";
-        }
-        if( container == null )
-        {
-            container = "qi4j-entities";
-        }
-        storeContext = ContextBuilder.newBuilder( provider ).
-            credentials( identifier, credentials ).
-            overrides( asProperties( properties ) ).
-            buildView( BlobStoreContext.class );
-        BlobStore blobStore = storeContext.getBlobStore();
-        if( !blobStore.containerExists( container ) )
-        {
-            if( !blobStore.createContainerInLocation( null, container ) )
-            {
-                throw new EntityStoreException( "Unable to create JClouds Blob Container, cannot continue." );
-            }
-            else
-            {
-                LOGGER.debug( "Created new container: {}", container );
-            }
-        }
-        LOGGER.info( "Activated using {} cloud provider [id:{}]", provider, identifier );
-    }
-
-    private Properties asProperties( Map<String, String> map )
-    {
-        Properties props = new Properties();
-        for( Map.Entry<String, String> eachEntry : map.entrySet() )
-        {
-            props.put( eachEntry.getKey(), eachEntry.getValue() );
-        }
-        return props;
-    }
-
-    @Override
-    public void passivateService()
-        throws Exception
-    {
-        if( storeContext != null )
-        {
-            storeContext.close();
-            storeContext = null;
-            container = null;
-        }
-    }
-
-    @Override
-    public Reader get( EntityReference entityReference )
-        throws EntityStoreException
-    {
-        Blob blob = storeContext.getBlobStore().getBlob( container, entityReference.identity() );
-        if( blob == null )
-        {
-            throw new EntityNotFoundException( entityReference );
-        }
-        Payload payload = blob.getPayload();
-        if( payload == null )
-        {
-            throw new EntityNotFoundException( entityReference );
-        }
-        InputStream input = null;
-        try
-        {
-            input = payload.openStream();
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            Inputs.byteBuffer( input, 4096 ).transferTo( Outputs.byteBuffer( baos ) );
-            return new StringReader( baos.toString( "UTF-8" ) );
-        }
-        catch( IOException ex )
-        {
-            throw new EntityStoreException( "Unable to read entity state for: " + entityReference, ex );
-        }
-        finally
-        {
-            if( input != null )
-            {
-                try
-                {
-                    input.close();
-                }
-                catch( IOException ignored )
-                {
-                }
-            }
-        }
-    }
-
-    @Override
-    public void applyChanges( MapChanges changes )
-        throws IOException
-    {
-        final BlobStore blobStore = storeContext.getBlobStore();
-        changes.visitMap(
-            new MapChanger()
-            {
-                @Override
-                public Writer newEntity( final EntityReference ref, EntityDescriptor entityDescriptor )
-                    throws IOException
-                {
-                    return new StringWriter()
-                    {
-                        @Override
-                        public void close()
-                        throws IOException
-                        {
-                            super.close();
-                            Blob blob = blobStore.blobBuilder( ref.identity() )
-                                .payload( ByteSource.wrap( toString().getBytes( UTF_8 ) ) )
-                                .build();
-                            blobStore.putBlob( container, blob );
-                        }
-                    };
-                }
-
-                @Override
-                public Writer updateEntity( final EntityReference ref, EntityDescriptor entityDescriptor )
-                    throws IOException
-                {
-                    if( !blobStore.blobExists( container, ref.identity() ) )
-                    {
-                        throw new EntityNotFoundException( ref );
-                    }
-                    return new StringWriter()
-                    {
-                        @Override
-                        public void close()
-                        throws IOException
-                        {
-                            super.close();
-                            Blob blob = blobStore.blobBuilder( ref.identity() )
-                                .payload( ByteSource.wrap( toString().getBytes( UTF_8 ) ) )
-                                .build();
-                            blobStore.putBlob( container, blob );
-                        }
-                    };
-                }
-
-                @Override
-                public void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor )
-                    throws EntityNotFoundException
-                {
-                    if( !blobStore.blobExists( container, ref.identity() ) )
-                    {
-                        throw new EntityNotFoundException( ref );
-                    }
-                    blobStore.removeBlob( container, ref.identity() );
-                }
-            }
-        );
-    }
-
-    @Override
-    public Input<Reader, IOException> entityStates()
-    {
-        return new Input<Reader, IOException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super Reader, ReceiverThrowableType> output )
-                throws IOException, ReceiverThrowableType
-            {
-                output.receiveFrom(
-                    new Sender<Reader, IOException>()
-                    {
-                        @Override
-                        public <ReceiverThrowableType extends Throwable> void sendTo( Receiver<? super Reader, ReceiverThrowableType> receiver )
-                            throws ReceiverThrowableType, IOException
-                        {
-                            for( StorageMetadata stored : storeContext.getBlobStore().list() )
-                            {
-                                Payload payload = storeContext.getBlobStore().getBlob( container, stored.getName() ).getPayload();
-                                if( payload == null )
-                                {
-                                    throw new EntityNotFoundException( parseEntityReference( stored.getName() ) );
-                                }
-                                InputStream input = null;
-                                try
-                                {
-                                    input = payload.openStream();
-                                    receiver.receive( new InputStreamReader( input, "UTF-8" ) );
-                                }
-                                finally
-                                {
-                                    if( input != null )
-                                    {
-                                        try
-                                        {
-                                            input.close();
-                                        }
-                                        catch( IOException ignored )
-                                        {
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    }
-                );
-            }
-        };
-    }
-}
diff --git a/extensions/entitystore-jclouds/src/main/java/org/qi4j/entitystore/jclouds/JCloudsMapEntityStoreService.java b/extensions/entitystore-jclouds/src/main/java/org/qi4j/entitystore/jclouds/JCloudsMapEntityStoreService.java
deleted file mode 100644
index 515d702..0000000
--- a/extensions/entitystore-jclouds/src/main/java/org/qi4j/entitystore/jclouds/JCloudsMapEntityStoreService.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.jclouds;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.library.locking.LockingAbstractComposite;
-import org.qi4j.spi.entitystore.ConcurrentModificationCheckConcern;
-import org.qi4j.spi.entitystore.EntityStateVersions;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.StateChangeNotificationConcern;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreActivation;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreMixin;
-
-/**
- * JClouds EntityStore service.
- * <p>Based on @{@link JSONMapEntityStoreMixin}.</p>
- */
-@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
-@Mixins( { JSONMapEntityStoreMixin.class, JCloudsMapEntityStoreMixin.class } )
-public interface JCloudsMapEntityStoreService
-    extends ServiceActivation,
-            JSONMapEntityStoreActivation,
-            EntityStore,
-            EntityStateVersions,
-            ServiceComposite,
-            LockingAbstractComposite,
-            Configuration
-{
-}
diff --git a/extensions/entitystore-jclouds/src/main/java/org/qi4j/entitystore/jclouds/package.html b/extensions/entitystore-jclouds/src/main/java/org/qi4j/entitystore/jclouds/package.html
deleted file mode 100644
index d43de1a..0000000
--- a/extensions/entitystore-jclouds/src/main/java/org/qi4j/entitystore/jclouds/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>JClouds BlobStore EntityStore.</h2>
-    </body>
-</html>
diff --git a/extensions/entitystore-jclouds/src/test/java/org/apache/polygene/entitystore/jclouds/JCloudsFilesystemTest.java b/extensions/entitystore-jclouds/src/test/java/org/apache/polygene/entitystore/jclouds/JCloudsFilesystemTest.java
new file mode 100644
index 0000000..91abf14
--- /dev/null
+++ b/extensions/entitystore-jclouds/src/test/java/org/apache/polygene/entitystore/jclouds/JCloudsFilesystemTest.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.polygene.entitystore.jclouds;
+
+import java.util.Collections;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.jclouds.assembly.JCloudsEntityStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+import org.jclouds.filesystem.reference.FilesystemConstants;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+public class JCloudsFilesystemTest
+    extends AbstractEntityStoreTest
+{
+    @Rule
+    public TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+        new JCloudsEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+        JCloudsMapEntityStoreConfiguration defaults = config.forMixin( JCloudsMapEntityStoreConfiguration.class )
+                                                            .declareDefaults();
+        defaults.provider().set( "filesystem" );
+        defaults.properties().set( Collections.singletonMap( FilesystemConstants.PROPERTY_BASEDIR,
+                                                             tmpDir.getRoot().getAbsolutePath() ) );
+    }
+}
diff --git a/extensions/entitystore-jclouds/src/test/java/org/apache/polygene/entitystore/jclouds/JCloudsS3Test.java b/extensions/entitystore-jclouds/src/test/java/org/apache/polygene/entitystore/jclouds/JCloudsS3Test.java
new file mode 100644
index 0000000..720b072
--- /dev/null
+++ b/extensions/entitystore-jclouds/src/test/java/org/apache/polygene/entitystore/jclouds/JCloudsS3Test.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.entitystore.jclouds;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.jclouds.assembly.JCloudsEntityStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+import org.apache.polygene.test.internal.DockerRule;
+import org.junit.ClassRule;
+
+public class JCloudsS3Test extends AbstractEntityStoreTest
+{
+    @ClassRule
+    public static final DockerRule DOCKER = new DockerRule( "s3server", "server started" );
+
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+        new JCloudsEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+        JCloudsMapEntityStoreConfiguration defaults = config.forMixin( JCloudsMapEntityStoreConfiguration.class )
+                                                            .declareDefaults();
+        String host = DOCKER.getDockerHost();
+        int port = DOCKER.getExposedContainerPort( "8000/tcp" );
+        defaults.provider().set( "s3" );
+        defaults.endpoint().set( "http://" + host + ':' + port );
+        defaults.identifier().set( "dummyIdentifier" );
+        defaults.credential().set( "dummyCredential" );
+    }
+}
diff --git a/extensions/entitystore-jclouds/src/test/java/org/apache/polygene/entitystore/jclouds/JCloudsTransientTest.java b/extensions/entitystore-jclouds/src/test/java/org/apache/polygene/entitystore/jclouds/JCloudsTransientTest.java
new file mode 100644
index 0000000..266c0e1
--- /dev/null
+++ b/extensions/entitystore-jclouds/src/test/java/org/apache/polygene/entitystore/jclouds/JCloudsTransientTest.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.entitystore.jclouds;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.jclouds.assembly.JCloudsEntityStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+
+public class JCloudsTransientTest
+        extends AbstractEntityStoreTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+        // START SNIPPET: assembly
+        new JCloudsEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+        // END SNIPPET: assembly
+    }
+}
diff --git a/extensions/entitystore-jclouds/src/test/java/org/apache/polygene/entitystore/jclouds/JCloudsWithCacheTest.java b/extensions/entitystore-jclouds/src/test/java/org/apache/polygene/entitystore/jclouds/JCloudsWithCacheTest.java
new file mode 100644
index 0000000..72f89cf
--- /dev/null
+++ b/extensions/entitystore-jclouds/src/test/java/org/apache/polygene/entitystore/jclouds/JCloudsWithCacheTest.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.entitystore.jclouds;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.jclouds.assembly.JCloudsEntityStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.cache.AbstractEntityStoreWithCacheTest;
+
+public class JCloudsWithCacheTest
+    extends AbstractEntityStoreWithCacheTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+        new JCloudsEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+    }
+}
diff --git a/extensions/entitystore-jclouds/src/test/java/org/qi4j/entitystore/jclouds/JCloudsFilesystemTest.java b/extensions/entitystore-jclouds/src/test/java/org/qi4j/entitystore/jclouds/JCloudsFilesystemTest.java
deleted file mode 100644
index 80e6f60..0000000
--- a/extensions/entitystore-jclouds/src/test/java/org/qi4j/entitystore/jclouds/JCloudsFilesystemTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.jclouds;
-
-import java.util.HashMap;
-import java.util.Map;
-import org.jclouds.filesystem.reference.FilesystemConstants;
-import org.junit.AfterClass;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class JCloudsFilesystemTest
-        extends AbstractEntityStoreTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-            throws AssemblyException
-    {
-        super.assemble( module );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        new JCloudsMapEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
-        JCloudsMapEntityStoreConfiguration defaults = config.forMixin( JCloudsMapEntityStoreConfiguration.class ).declareDefaults();
-        defaults.provider().set( "filesystem" );
-        Map<String, String> props = new HashMap<String, String>();
-        props.put( FilesystemConstants.PROPERTY_BASEDIR, "build/tmp/" + getClass().getPackage().getName() + "/es-jclouds-" + System.currentTimeMillis() );
-        defaults.properties().set( props );
-    }
-
-    @AfterClass
-    public static void filesystemCleanup()
-    {
-        // TODO recursively delete "build/tmp/" + getClass().getPackage().getName()
-    }
-
-}
diff --git a/extensions/entitystore-jclouds/src/test/java/org/qi4j/entitystore/jclouds/JCloudsTransientTest.java b/extensions/entitystore-jclouds/src/test/java/org/qi4j/entitystore/jclouds/JCloudsTransientTest.java
deleted file mode 100644
index 25af35c..0000000
--- a/extensions/entitystore-jclouds/src/test/java/org/qi4j/entitystore/jclouds/JCloudsTransientTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.jclouds;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class JCloudsTransientTest
-        extends AbstractEntityStoreTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-            throws AssemblyException
-    {
-        super.assemble( module );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        // START SNIPPET: assembly
-        new JCloudsMapEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
-        // END SNIPPET: assembly
-    }
-
-}
diff --git a/extensions/entitystore-jclouds/src/test/java/org/qi4j/entitystore/jclouds/JCloudsWithCacheTest.java b/extensions/entitystore-jclouds/src/test/java/org/qi4j/entitystore/jclouds/JCloudsWithCacheTest.java
deleted file mode 100644
index ab473c7..0000000
--- a/extensions/entitystore-jclouds/src/test/java/org/qi4j/entitystore/jclouds/JCloudsWithCacheTest.java
+++ /dev/null
@@ -1,39 +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.qi4j.entitystore.jclouds;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.cache.AbstractEntityStoreWithCacheTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class JCloudsWithCacheTest
-    extends AbstractEntityStoreWithCacheTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        new JCloudsMapEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
-    }
-}
diff --git a/extensions/entitystore-jdbm/build.gradle b/extensions/entitystore-jdbm/build.gradle
index c317c15..c195e0c 100644
--- a/extensions/entitystore-jdbm/build.gradle
+++ b/extensions/entitystore-jdbm/build.gradle
@@ -1,37 +1,39 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ JDBM EntityStore Extension"
+apply plugin: 'polygene-extension'
 
-jar { manifest {name = "Apache Zest™ Extension - EntityStore - JDBM" }}
+description = "Apache Polygene™ JDBM EntityStore Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - EntityStore - JDBM" } }
 
 dependencies {
+  api polygene.core.bootstrap
+  api polygene.library( 'fileconfig' )
 
-  compile project( ":org.qi4j.core:org.qi4j.core.bootstrap" )
-  compile project( ":org.qi4j.libraries:org.qi4j.library.locking" )
-  compile project( ":org.qi4j.libraries:org.qi4j.library.fileconfig" )
-  compile libraries.jdbm
+  implementation polygene.library( 'locking' )
+  implementation libraries.jdbm
 
-  testCompile project( ":org.qi4j.core:org.qi4j.core.testsupport" )
-  testCompile(project(":org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson"))
+  runtimeOnly polygene.core.runtime
 
-  testRuntime project( ":org.qi4j.core:org.qi4j.core.runtime" )
-  testRuntime libraries.logback
+  testImplementation polygene.core.testsupport
 
-}
\ No newline at end of file
+  testRuntimeOnly libraries.logback
+}
diff --git a/extensions/entitystore-jdbm/dev-status.xml b/extensions/entitystore-jdbm/dev-status.xml
index ac63cda..762e250 100644
--- a/extensions/entitystore-jdbm/dev-status.xml
+++ b/extensions/entitystore-jdbm/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
         <!--none,early,beta,stable,mature-->
         <codebase>stable</codebase>
diff --git a/extensions/entitystore-jdbm/src/docs/es-jdbm.txt b/extensions/entitystore-jdbm/src/docs/es-jdbm.txt
index 7a90daa..c50edb5 100644
--- a/extensions/entitystore-jdbm/src/docs/es-jdbm.txt
+++ b/extensions/entitystore-jdbm/src/docs/es-jdbm.txt
@@ -35,7 +35,7 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-jdbm/src/test/java/org/qi4j/entitystore/jdbm/DocumentationSupport.java
+source=extensions/entitystore-jdbm/src/test/java/org/apache/polygene/entitystore/jdbm/DocumentationSupport.java
 tag=UsingAssembler
 ----
 
@@ -45,12 +45,12 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/JdbmConfiguration.java
+source=extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/JdbmConfiguration.java
 tag=config
 ----
 
 +file+ is optional and represent the file where the JDBM EntityStore will keep its persisted state.
 
-It defaults to System.getProperty( "user.dir" ) + "/qi4j/jdbmstore.data"
+It defaults to System.getProperty( "user.dir" ) + "/polygene/jdbmstore.data"
 If the given path is not absolute, then it's relative to the current working directory.
 If you use the <<library-fileconfig>> then this property value is ignored and FileConfig is prefered.
diff --git a/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/JdbmConfiguration.java b/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/JdbmConfiguration.java
new file mode 100644
index 0000000..03143a1
--- /dev/null
+++ b/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/JdbmConfiguration.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.polygene.entitystore.jdbm;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Configuration for the JdbmEntityStoreService.
+ */
+// START SNIPPET: config
+public interface JdbmConfiguration
+{
+    // END SNIPPET: config
+   /**
+    * The file where the JDBM data will be stored
+    * <p>
+    * Default: System.getProperty( "user.dir" ) + "/polygene/jdbmstore.data";
+    * </p>
+    * @return path to data file relative to current path
+    */
+    // START SNIPPET: config
+   @Optional
+   Property<String> file();
+
+   // JDBM RecordManager options
+
+   @UseDefaults
+   Property<Boolean> autoCommit();
+
+   @UseDefaults
+   Property<Boolean> disableTransactions();
+}
+// END SNIPPET: config
diff --git a/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreActivation.java b/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreActivation.java
new file mode 100644
index 0000000..9d07a96
--- /dev/null
+++ b/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreActivation.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.entitystore.jdbm;
+
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.service.ServiceReference;
+
+/**
+ * Activation for JdbmEntityStoreMixin.
+ */
+@Activators( { JdbmEntityStoreActivation.Activator.class } )
+public interface JdbmEntityStoreActivation
+{
+
+    void setUpJdbm()
+            throws Exception;
+
+    void tearDownJdbm()
+            throws Exception;
+
+    class Activator
+            extends ActivatorAdapter<ServiceReference<JdbmEntityStoreActivation>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<JdbmEntityStoreActivation> activated )
+                throws Exception
+        {
+            activated.get().setUpJdbm();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<JdbmEntityStoreActivation> passivating )
+                throws Exception
+        {
+            passivating.get().tearDownJdbm();
+        }
+
+    }
+
+}
diff --git a/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreMixin.java b/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreMixin.java
new file mode 100644
index 0000000..312c002
--- /dev/null
+++ b/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreMixin.java
@@ -0,0 +1,479 @@
+/*
+ *  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.polygene.entitystore.jdbm;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.UncheckedIOException;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.util.Properties;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import jdbm.RecordManager;
+import jdbm.RecordManagerFactory;
+import jdbm.RecordManagerOptions;
+import jdbm.Serializer;
+import jdbm.btree.BTree;
+import jdbm.helper.ByteArrayComparator;
+import jdbm.helper.DefaultSerializer;
+import jdbm.helper.Tuple;
+import jdbm.helper.TupleBrowser;
+import jdbm.recman.CacheRecordManager;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.library.fileconfig.FileConfiguration;
+import org.apache.polygene.library.locking.ReadLock;
+import org.apache.polygene.library.locking.WriteLock;
+import org.apache.polygene.spi.entitystore.BackupRestore;
+import org.apache.polygene.spi.entitystore.EntityNotFoundException;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+import org.apache.polygene.spi.entitystore.helpers.MapEntityStore;
+
+/**
+ * JDBM implementation of MapEntityStore.
+ */
+public class JdbmEntityStoreMixin
+    implements JdbmEntityStoreActivation, MapEntityStore, BackupRestore
+{
+    @Optional
+    @Service
+    FileConfiguration fileConfiguration;
+
+    @This
+    private Configuration<JdbmConfiguration> config;
+
+    @Uses
+    private ServiceDescriptor descriptor;
+
+    private RecordManager recordManager;
+    private BTree index;
+    private Serializer serializer;
+    private File tempDirectory;
+
+    @This
+    ReadWriteLock lock;
+
+    @Override
+    public void setUpJdbm()
+        throws Exception
+    {
+        initialize();
+    }
+
+    @Override
+    public void tearDownJdbm()
+        throws Exception
+    {
+        recordManager.close();
+    }
+
+    @ReadLock
+    @Override
+    public Reader get( EntityReference entityReference )
+        throws EntityStoreException
+    {
+        try
+        {
+            Long stateIndex = getStateIndex( entityReference.identity() );
+
+            if( stateIndex == null )
+            {
+                throw new EntityNotFoundException( entityReference );
+            }
+
+            byte[] serializedState = (byte[]) recordManager.fetch( stateIndex, serializer );
+
+            if( serializedState == null )
+            {
+                throw new EntityNotFoundException( entityReference );
+            }
+
+            return new StringReader( new String( serializedState, "UTF-8" ) );
+        }
+        catch( IOException e )
+        {
+            throw new EntityStoreException( e );
+        }
+    }
+
+    @WriteLock
+    @Override
+    public void applyChanges( MapChanges changes )
+        throws IOException
+    {
+        try
+        {
+            changes.visitMap( new MapChanger()
+            {
+                @Override
+                public Writer newEntity( EntityReference ref, EntityDescriptor descriptor )
+                    throws IOException
+                {
+                    return new StringWriter( 1000 )
+                    {
+                        @Override
+                        public void close()
+                            throws IOException
+                        {
+                            super.close();
+
+                            byte[] stateArray = toString().getBytes( "UTF-8" );
+                            long stateIndex = recordManager.insert( stateArray, serializer );
+                            String indexKey = ref.toString();
+                            index.insert( indexKey.getBytes( "UTF-8" ), stateIndex, false );
+                        }
+                    };
+                }
+
+                @Override
+                public Writer updateEntity( MapChange mapChange )
+                    throws IOException
+                {
+                    return new StringWriter( 1000 )
+                    {
+                        @Override
+                        public void close()
+                            throws IOException
+                        {
+                            super.close();
+
+                            Long stateIndex = getStateIndex( mapChange.reference().identity() );
+                            byte[] stateArray = toString().getBytes( "UTF-8" );
+                            recordManager.update( stateIndex, stateArray, serializer );
+                        }
+                    };
+                }
+
+                @Override
+                public void removeEntity( EntityReference ref, EntityDescriptor descriptor )
+                    throws EntityNotFoundException
+                {
+                    try
+                    {
+                        Long stateIndex = getStateIndex( ref.identity() );
+                        recordManager.delete( stateIndex );
+                        index.remove( ref.toString().getBytes( "UTF-8" ) );
+                    }
+                    catch( IOException e )
+                    {
+                        throw new EntityStoreException( e );
+                    }
+                }
+            } );
+
+            recordManager.commit();
+        }
+        catch( Exception e )
+        {
+            e.printStackTrace();
+            recordManager.rollback();
+            if( e instanceof IOException )
+            {
+                throw (IOException) e;
+            }
+            else if( e instanceof EntityStoreException )
+            {
+                throw (EntityStoreException) e;
+            }
+            else
+            {
+                throw new IOException( e );
+            }
+        }
+    }
+
+    @Override
+    public Stream<Reader> entityStates()
+    {
+        return backup().map( StringReader::new );
+    }
+
+    @Override
+    public Stream<String> backup()
+    {
+        lock.writeLock().lock();
+        TupleBrowser browser;
+        try
+        {
+            browser = index.browse();
+        }
+        catch( IOException ex )
+        {
+            lock.writeLock().unlock();
+            throw new EntityStoreException( ex );
+        }
+        return StreamSupport.stream(
+            new Spliterators.AbstractSpliterator<String>( Long.MAX_VALUE, Spliterator.ORDERED )
+            {
+                private final Tuple tuple = new Tuple();
+
+                @Override
+                public boolean tryAdvance( final Consumer<? super String> action )
+                {
+                    try
+                    {
+                        if( !browser.getNext( tuple ) )
+                        {
+                            return false;
+                        }
+                        Identity identity = new StringIdentity( (byte[]) tuple.getKey() );
+                        Long stateIndex = getStateIndex( identity );
+                        if( stateIndex == null )
+                        {
+                            return false;
+                        }
+                        byte[] serializedState = (byte[]) recordManager.fetch( stateIndex, serializer );
+                        String state = new String( serializedState, "UTF-8" );
+                        action.accept( state );
+                        return true;
+                    }
+                    catch( IOException ex )
+                    {
+                        lock.writeLock().unlock();
+                        throw new EntityStoreException( ex );
+                    }
+                }
+            },
+            false
+        ).onClose( () -> lock.writeLock().unlock() );
+    }
+
+    @Override
+    public void restore( final Stream<String> states )
+    {
+        File dbFile = new File( getDatabaseName() + ".db" );
+        File lgFile = new File( getDatabaseName() + ".lg" );
+
+        // Create temporary store
+        File tempDatabase = createTemporaryDatabase();
+        final RecordManager recordManager;
+        final BTree index;
+        try
+        {
+            recordManager = RecordManagerFactory.createRecordManager( tempDatabase.getAbsolutePath(),
+                                                                      new Properties() );
+            ByteArrayComparator comparator = new ByteArrayComparator();
+            index = BTree.createInstance( recordManager, comparator, serializer, DefaultSerializer.INSTANCE, 16 );
+            recordManager.setNamedObject( "index", index.getRecid() );
+            recordManager.commit();
+        }
+        catch( IOException ex )
+        {
+            throw new EntityStoreException( ex );
+        }
+        try
+        {
+            // TODO NO NEED TO SYNCHRONIZE HERE
+            AtomicLong counter = new AtomicLong();
+            Consumer<String> stateConsumer = state ->
+            {
+                try
+                {
+                    // Commit one batch
+                    if( ( counter.incrementAndGet() % 1000 ) == 0 )
+                    {
+                        recordManager.commit();
+                    }
+
+                    String id = state.substring( "{\"reference\":\"".length() );
+                    id = id.substring( 0, id.indexOf( '"' ) );
+
+                    // Insert
+                    byte[] stateArray = state.getBytes( "UTF-8" );
+                    long stateIndex = recordManager.insert( stateArray, serializer );
+                    index.insert( id.getBytes( "UTF-8" ), stateIndex, false );
+                }
+                catch( IOException ex )
+                {
+                    throw new UncheckedIOException( ex );
+                }
+            };
+            states.forEach( stateConsumer );
+            // Import went ok - continue
+            recordManager.commit();
+            // close file handles otherwise Microsoft Windows will fail to rename database files.
+            recordManager.close();
+        }
+        catch( IOException | UncheckedIOException ex )
+        {
+            try
+            {
+                recordManager.close();
+            }
+            catch( IOException ignore ) { }
+            tempDatabase.delete();
+            throw new EntityStoreException( ex );
+        }
+        try
+        {
+
+            lock.writeLock().lock();
+            try
+            {
+                // Replace old database with new
+                JdbmEntityStoreMixin.this.recordManager.close();
+
+                boolean deletedOldDatabase = true;
+                deletedOldDatabase &= dbFile.delete();
+                deletedOldDatabase &= lgFile.delete();
+                if( !deletedOldDatabase )
+                {
+                    throw new EntityStoreException( "Could not remove old database" );
+                }
+
+                boolean renamedTempDatabase = true;
+                renamedTempDatabase &= new File( tempDatabase.getAbsolutePath() + ".db" ).renameTo( dbFile );
+                renamedTempDatabase &= new File( tempDatabase.getAbsolutePath() + ".lg" ).renameTo( lgFile );
+
+                if( !renamedTempDatabase )
+                {
+                    throw new EntityStoreException( "Could not replace database with temp database" );
+                }
+
+                // Start up again
+                initialize();
+            }
+            finally
+            {
+                lock.writeLock().unlock();
+            }
+        }
+        catch( IOException ex )
+        {
+            tempDatabase.delete();
+            throw new EntityStoreException( ex );
+        }
+    }
+
+    private String getDatabaseName()
+    {
+        String pathname = config.get().file().get();
+        if( pathname == null )
+        {
+            if( fileConfiguration != null )
+            {
+                File dataDir = fileConfiguration.dataDirectory();
+                File jdbmDir = new File( dataDir, descriptor.identity() + "/jdbm.data" );
+                pathname = jdbmDir.getAbsolutePath();
+            }
+            else
+            {
+                pathname = System.getProperty( "user.dir" ) + "/polygene/jdbm.data";
+            }
+        }
+        File dataFile = new File( pathname );
+        File directory = dataFile.getAbsoluteFile().getParentFile();
+        directory.mkdirs();
+        String name = dataFile.getAbsolutePath();
+        return name;
+    }
+
+    private File createTemporaryDatabase()
+    {
+        try
+        {
+            File tempDatabase = Files.createTempFile( getTemporaryDirectory().toPath(),
+                                                      descriptor.identity().toString(),
+                                                      "write" ).toFile();
+            tempDatabase.deleteOnExit();
+            return tempDatabase;
+        }
+        catch( IOException ex )
+        {
+            throw new UncheckedIOException( ex );
+        }
+    }
+
+    private File getTemporaryDirectory() throws IOException
+    {
+        if( tempDirectory != null )
+        {
+            return tempDirectory;
+        }
+        String storeId = descriptor.identity().toString();
+        tempDirectory = fileConfiguration != null
+                        ? new File( fileConfiguration.temporaryDirectory(), storeId )
+                        : new File( new File( System.getProperty( "java.io.tmpdir" ) ),
+                                    storeId );
+        if( !tempDirectory.exists() )
+        {
+            java.nio.file.Files.createDirectories( tempDirectory.toPath() );
+        }
+        return tempDirectory;
+    }
+
+    private Properties getProperties()
+    {
+        JdbmConfiguration config = this.config.get();
+
+        Properties properties = new Properties();
+
+        properties.put( RecordManagerOptions.AUTO_COMMIT, config.autoCommit().get().toString() );
+        properties.put( RecordManagerOptions.DISABLE_TRANSACTIONS, config.disableTransactions().get().toString() );
+
+        return properties;
+    }
+
+    private Long getStateIndex( Identity identity )
+        throws IOException
+    {
+        return (Long) index.find( identity.toBytes() );
+    }
+
+    private void initialize()
+        throws IOException
+    {
+        String name = getDatabaseName();
+        Properties properties = getProperties();
+
+        recordManager = RecordManagerFactory.createRecordManager( name, properties );
+        serializer = DefaultSerializer.INSTANCE;
+        recordManager = new CacheRecordManager( recordManager, 1000, false );
+        long recid = recordManager.getNamedObject( "index" );
+        if( recid != 0 )
+        {
+            index = BTree.load( recordManager, recid );
+        }
+        else
+        {
+            ByteArrayComparator comparator = new ByteArrayComparator();
+            index = BTree.createInstance( recordManager, comparator, serializer, DefaultSerializer.INSTANCE, 16 );
+            recordManager.setNamedObject( "index", index.getRecid() );
+        }
+        recordManager.commit();
+    }
+}
\ No newline at end of file
diff --git a/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreService.java b/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreService.java
new file mode 100644
index 0000000..e9d9d94
--- /dev/null
+++ b/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreService.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.entitystore.jdbm;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.library.locking.LockingAbstractComposite;
+import org.apache.polygene.library.locking.ReadLockConcern;
+import org.apache.polygene.library.locking.WriteLockConcern;
+import org.apache.polygene.spi.entitystore.*;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreActivation;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreMixin;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * EntityStore service backed by JDBM store.
+ * <p>Based on @{@link JSONMapEntityStoreMixin}.</p>
+ */
+@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class, ReadLockConcern.class, WriteLockConcern.class } )
+@Mixins( { JSONMapEntityStoreMixin.class, JdbmEntityStoreMixin.class } )
+public interface JdbmEntityStoreService
+    extends JdbmEntityStoreActivation,
+            JSONMapEntityStoreActivation,
+            EntityStore,
+            EntityStateVersions,
+            StateStore,
+            BackupRestore,
+            LockingAbstractComposite,
+            Configuration<JdbmConfiguration>
+{
+}
diff --git a/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/assembly/JdbmEntityStoreAssembler.java b/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/assembly/JdbmEntityStoreAssembler.java
new file mode 100644
index 0000000..f62e792
--- /dev/null
+++ b/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/assembly/JdbmEntityStoreAssembler.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.entitystore.jdbm.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.entitystore.jdbm.JdbmConfiguration;
+import org.apache.polygene.entitystore.jdbm.JdbmEntityStoreService;
+
+public class JdbmEntityStoreAssembler
+    extends Assemblers.VisibilityIdentityConfig<JdbmEntityStoreAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( JdbmEntityStoreService.class ).visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+        if( hasConfig() )
+        {
+            configModule().entities( JdbmConfiguration.class ).visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/assembly/package.html b/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/assembly/package.html
new file mode 100644
index 0000000..37bf41f
--- /dev/null
+++ b/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>JDBM EntityStore Assembly.</h2>
+    </body>
+</html>
diff --git a/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/package.html b/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/package.html
new file mode 100644
index 0000000..fdf0272
--- /dev/null
+++ b/extensions/entitystore-jdbm/src/main/java/org/apache/polygene/entitystore/jdbm/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>JDBM EntityStore.</h2>
+    </body>
+</html>
diff --git a/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/JdbmConfiguration.java b/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/JdbmConfiguration.java
deleted file mode 100644
index a50b3b5..0000000
--- a/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/JdbmConfiguration.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*  Copyright 2008 Rickard Öberg.
- *
- * Licensed 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.qi4j.entitystore.jdbm;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-/**
- * Configuration for the JdbmEntityStoreService.
- */
-// START SNIPPET: config
-public interface JdbmConfiguration
-        extends ConfigurationComposite
-{
-    // END SNIPPET: config
-   /**
-    * The file where the JDBM data will be stored
-    * <p>
-    * Default: System.getProperty( "user.dir" ) + "/qi4j/jdbmstore.data";
-    * </p>
-    * @return path to data file relative to current path
-    */
-    // START SNIPPET: config
-   @Optional
-   Property<String> file();
-
-   // JDBM RecordManager options
-
-   @UseDefaults
-   Property<Boolean> autoCommit();
-
-   @UseDefaults
-   Property<Boolean> disableTransactions();
-}
-// END SNIPPET: config
diff --git a/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/JdbmEntityStoreActivation.java b/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/JdbmEntityStoreActivation.java
deleted file mode 100644
index c56443f..0000000
--- a/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/JdbmEntityStoreActivation.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*  Copyright 2008 Rickard Öberg.
- *
- * Licensed 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.qi4j.entitystore.jdbm;
-
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.service.ServiceReference;
-
-/**
- * Activation for JdbmEntityStoreMixin.
- */
-@Activators( { JdbmEntityStoreActivation.Activator.class } )
-public interface JdbmEntityStoreActivation
-{
-
-    void setUpJdbm()
-            throws Exception;
-
-    void tearDownJdbm()
-            throws Exception;
-
-    public class Activator
-            extends ActivatorAdapter<ServiceReference<JdbmEntityStoreActivation>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<JdbmEntityStoreActivation> activated )
-                throws Exception
-        {
-            activated.get().setUpJdbm();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<JdbmEntityStoreActivation> passivating )
-                throws Exception
-        {
-            passivating.get().tearDownJdbm();
-        }
-
-    }
-
-}
diff --git a/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/JdbmEntityStoreMixin.java b/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/JdbmEntityStoreMixin.java
deleted file mode 100644
index 4eade07..0000000
--- a/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/JdbmEntityStoreMixin.java
+++ /dev/null
@@ -1,468 +0,0 @@
-/*  Copyright 2008 Rickard Öberg.
- *
- * Licensed 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.qi4j.entitystore.jdbm;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.Properties;
-import java.util.concurrent.locks.ReadWriteLock;
-import jdbm.RecordManager;
-import jdbm.RecordManagerFactory;
-import jdbm.RecordManagerOptions;
-import jdbm.Serializer;
-import jdbm.btree.BTree;
-import jdbm.helper.ByteArrayComparator;
-import jdbm.helper.DefaultSerializer;
-import jdbm.helper.Tuple;
-import jdbm.helper.TupleBrowser;
-import jdbm.recman.CacheRecordManager;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.io.Files;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.library.fileconfig.FileConfiguration;
-import org.qi4j.library.locking.ReadLock;
-import org.qi4j.library.locking.WriteLock;
-import org.qi4j.spi.entitystore.BackupRestore;
-import org.qi4j.spi.entitystore.EntityNotFoundException;
-import org.qi4j.spi.entitystore.EntityStoreException;
-import org.qi4j.spi.entitystore.helpers.MapEntityStore;
-
-/**
- * JDBM implementation of MapEntityStore.
- */
-public class JdbmEntityStoreMixin
-    implements JdbmEntityStoreActivation, MapEntityStore, BackupRestore
-{
-    @Optional
-    @Service
-    FileConfiguration fileConfiguration;
-
-    @This
-    private Configuration<JdbmConfiguration> config;
-
-    @Uses
-    private ServiceDescriptor descriptor;
-
-    private RecordManager recordManager;
-    private BTree index;
-    private Serializer serializer;
-
-    @This
-    ReadWriteLock lock;
-
-    @Override
-    public void setUpJdbm()
-        throws Exception
-    {
-        initialize();
-    }
-
-    @Override
-    public void tearDownJdbm()
-        throws Exception
-    {
-        recordManager.close();
-    }
-
-    @ReadLock
-    @Override
-    public Reader get( EntityReference entityReference )
-        throws EntityStoreException
-    {
-        try
-        {
-            Long stateIndex = getStateIndex( entityReference.identity() );
-
-            if( stateIndex == null )
-            {
-                throw new EntityNotFoundException( entityReference );
-            }
-
-            byte[] serializedState = (byte[]) recordManager.fetch( stateIndex, serializer );
-
-            if( serializedState == null )
-            {
-                throw new EntityNotFoundException( entityReference );
-            }
-
-            return new StringReader( new String( serializedState, "UTF-8" ) );
-        }
-        catch( IOException e )
-        {
-            throw new EntityStoreException( e );
-        }
-    }
-
-    @WriteLock
-    @Override
-    public void applyChanges( MapChanges changes )
-        throws IOException
-    {
-        try
-        {
-            changes.visitMap( new MapChanger()
-            {
-                @Override
-                public Writer newEntity( final EntityReference ref, EntityDescriptor descriptor )
-                    throws IOException
-                {
-                    return new StringWriter( 1000 )
-                    {
-                        @Override
-                        public void close()
-                            throws IOException
-                        {
-                            super.close();
-
-                            byte[] stateArray = toString().getBytes( "UTF-8" );
-                            long stateIndex = recordManager.insert( stateArray, serializer );
-                            String indexKey = ref.toString();
-                            index.insert( indexKey.getBytes( "UTF-8" ), stateIndex, false );
-                        }
-                    };
-                }
-
-                @Override
-                public Writer updateEntity( final EntityReference ref, EntityDescriptor descriptor )
-                    throws IOException
-                {
-                    return new StringWriter( 1000 )
-                    {
-                        @Override
-                        public void close()
-                            throws IOException
-                        {
-                            super.close();
-
-                            Long stateIndex = getStateIndex( ref.toString() );
-                            byte[] stateArray = toString().getBytes( "UTF-8" );
-                            recordManager.update( stateIndex, stateArray, serializer );
-                        }
-                    };
-                }
-
-                @Override
-                public void removeEntity( EntityReference ref, EntityDescriptor descriptor )
-                    throws EntityNotFoundException
-                {
-                    try
-                    {
-                        Long stateIndex = getStateIndex( ref.toString() );
-                        recordManager.delete( stateIndex );
-                        index.remove( ref.toString().getBytes( "UTF-8" ) );
-                    }
-                    catch( IOException e )
-                    {
-                        throw new EntityStoreException( e );
-                    }
-                }
-            } );
-
-            recordManager.commit();
-        }
-        catch( Exception e )
-        {
-            e.printStackTrace();
-            recordManager.rollback();
-            if( e instanceof IOException )
-            {
-                throw (IOException) e;
-            }
-            else if( e instanceof EntityStoreException )
-            {
-                throw (EntityStoreException) e;
-            }
-            else
-            {
-                throw new IOException( e );
-            }
-        }
-    }
-
-    @Override
-    public Input<Reader, IOException> entityStates()
-    {
-        return new Input<Reader, IOException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super Reader, ReceiverThrowableType> output )
-                throws IOException, ReceiverThrowableType
-            {
-                lock.writeLock().lock();
-
-                try
-                {
-                    output.receiveFrom( new Sender<Reader, IOException>()
-                    {
-                        @Override
-                        public <ReceiverThrowableType extends Throwable> void sendTo( Receiver<? super Reader, ReceiverThrowableType> receiver )
-                            throws ReceiverThrowableType, IOException
-                        {
-                            final TupleBrowser browser = index.browse();
-                            final Tuple tuple = new Tuple();
-
-                            while( browser.getNext( tuple ) )
-                            {
-                                String id = new String( (byte[]) tuple.getKey(), "UTF-8" );
-
-                                Long stateIndex = getStateIndex( id );
-
-                                if( stateIndex == null )
-                                {
-                                    continue;
-                                } // Skip this one
-
-                                byte[] serializedState = (byte[]) recordManager.fetch( stateIndex, serializer );
-
-                                receiver.receive( new StringReader( new String( serializedState, "UTF-8" ) ) );
-                            }
-                        }
-                    } );
-                }
-                finally
-                {
-                    lock.writeLock().unlock();
-                }
-            }
-        };
-    }
-
-    @Override
-    public Input<String, IOException> backup()
-    {
-        return new Input<String, IOException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super String, ReceiverThrowableType> output )
-                throws IOException, ReceiverThrowableType
-            {
-                lock.readLock().lock();
-
-                try
-                {
-                    output.receiveFrom( new Sender<String, IOException>()
-                    {
-                        @Override
-                        public <ReceiverThrowableType extends Throwable> void sendTo( Receiver<? super String, ReceiverThrowableType> receiver )
-                            throws ReceiverThrowableType, IOException
-                        {
-                            final TupleBrowser browser = index.browse();
-                            final Tuple tuple = new Tuple();
-
-                            while( browser.getNext( tuple ) )
-                            {
-                                String id = new String( (byte[]) tuple.getKey(), "UTF-8" );
-
-                                Long stateIndex = getStateIndex( id );
-
-                                if( stateIndex == null )
-                                {
-                                    continue;
-                                } // Skip this one
-
-                                byte[] serializedState = (byte[]) recordManager.fetch( stateIndex, serializer );
-
-                                receiver.receive( new String( serializedState, "UTF-8" ) );
-                            }
-                        }
-                    } );
-                }
-                finally
-                {
-                    lock.readLock().unlock();
-                }
-            }
-        };
-    }
-
-    @Override
-    public Output<String, IOException> restore()
-    {
-        return new Output<String, IOException>()
-        {
-            @Override
-            public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends String, SenderThrowableType> sender )
-                throws IOException, SenderThrowableType
-            {
-                File dbFile = new File( getDatabaseName() + ".db" );
-                File lgFile = new File( getDatabaseName() + ".lg" );
-
-                // Create temporary store
-                File tempDatabase = Files.createTemporayFileOf( dbFile );
-
-                final RecordManager recordManager = RecordManagerFactory.createRecordManager( tempDatabase.getAbsolutePath(), new Properties() );
-                ByteArrayComparator comparator = new ByteArrayComparator();
-                final BTree index = BTree.createInstance( recordManager, comparator, serializer, DefaultSerializer.INSTANCE, 16 );
-                recordManager.setNamedObject( "index", index.getRecid() );
-                recordManager.commit();
-
-                try
-                {
-                    sender.sendTo( new Receiver<String, IOException>()
-                    {
-                        int counter = 0;
-
-                        @Override
-                        public void receive( String item )
-                            throws IOException
-                        {
-                            // Commit one batch
-                            if( ( counter++ % 1000 ) == 0 )
-                            {
-                                recordManager.commit();
-                            }
-
-                            String id = item.substring( "{\"identity\":\"".length() );
-                            id = id.substring( 0, id.indexOf( '"' ) );
-
-                            // Insert
-                            byte[] stateArray = item.getBytes( "UTF-8" );
-                            long stateIndex = recordManager.insert( stateArray, serializer );
-                            index.insert( id.getBytes( "UTF-8" ), stateIndex, false );
-                        }
-                    } );
-                }
-                catch( IOException e )
-                {
-                    recordManager.close();
-                    tempDatabase.delete();
-                    throw e;
-                }
-                catch( Throwable senderThrowableType )
-                {
-                    recordManager.close();
-                    tempDatabase.delete();
-                    throw (SenderThrowableType) senderThrowableType;
-                }
-
-                // Import went ok - continue
-                recordManager.commit();
-                // close file handles otherwise Microsoft Windows will fail to rename database files.
-                recordManager.close();
-
-                lock.writeLock().lock();
-                try
-                {
-                    // Replace old database with new
-                    JdbmEntityStoreMixin.this.recordManager.close();
-
-                    boolean deletedOldDatabase = true;
-                    deletedOldDatabase &= dbFile.delete();
-                    deletedOldDatabase &= lgFile.delete();
-                    if( !deletedOldDatabase )
-                    {
-                        throw new IOException( "Could not remove old database" );
-                    }
-
-                    boolean renamedTempDatabase = true;
-                    renamedTempDatabase &= new File( tempDatabase.getAbsolutePath() + ".db" ).renameTo( dbFile );
-                    renamedTempDatabase &= new File( tempDatabase.getAbsolutePath() + ".lg" ).renameTo( lgFile );
-
-                    if( !renamedTempDatabase )
-                    {
-                        throw new IOException( "Could not replace database with temp database" );
-                    }
-
-                    // Start up again
-                    initialize();
-                }
-                finally
-                {
-                    lock.writeLock().unlock();
-                }
-            }
-        };
-    }
-
-    private String getDatabaseName()
-    {
-        String pathname = config.get().file().get();
-        if( pathname == null )
-        {
-            if( fileConfiguration != null )
-            {
-                File dataDir = fileConfiguration.dataDirectory();
-                File jdbmDir = new File( dataDir, descriptor.identity() + "/jdbm.data" );
-                pathname = jdbmDir.getAbsolutePath();
-            }
-            else
-            {
-                pathname = System.getProperty( "user.dir" ) + "/qi4j/jdbm.data";
-            }
-        }
-        File dataFile = new File( pathname );
-        File directory = dataFile.getAbsoluteFile().getParentFile();
-        directory.mkdirs();
-        String name = dataFile.getAbsolutePath();
-        return name;
-    }
-
-    private Properties getProperties()
-    {
-        JdbmConfiguration config = this.config.get();
-
-        Properties properties = new Properties();
-
-        properties.put( RecordManagerOptions.AUTO_COMMIT, config.autoCommit().get().toString() );
-        properties.put( RecordManagerOptions.DISABLE_TRANSACTIONS, config.disableTransactions().get().toString() );
-
-        return properties;
-    }
-
-    private Long getStateIndex( String identity )
-        throws IOException
-    {
-        return (Long) index.find( identity.getBytes( "UTF-8" ) );
-    }
-
-    private void initialize()
-        throws IOException
-    {
-        String name = getDatabaseName();
-        Properties properties = getProperties();
-
-        recordManager = RecordManagerFactory.createRecordManager( name, properties );
-        serializer = DefaultSerializer.INSTANCE;
-        recordManager = new CacheRecordManager( recordManager, 1000, false );
-        long recid = recordManager.getNamedObject( "index" );
-        if( recid != 0 )
-        {
-            index = BTree.load( recordManager, recid );
-        }
-        else
-        {
-            ByteArrayComparator comparator = new ByteArrayComparator();
-            index = BTree.createInstance( recordManager, comparator, serializer, DefaultSerializer.INSTANCE, 16 );
-            recordManager.setNamedObject( "index", index.getRecid() );
-        }
-        recordManager.commit();
-    }
-}
\ No newline at end of file
diff --git a/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/JdbmEntityStoreService.java b/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/JdbmEntityStoreService.java
deleted file mode 100644
index 9b8b4d9..0000000
--- a/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/JdbmEntityStoreService.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*  Copyright 2008 Rickard Öberg.
- *
- * Licensed 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.qi4j.entitystore.jdbm;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.library.locking.LockingAbstractComposite;
-import org.qi4j.library.locking.ReadLockConcern;
-import org.qi4j.library.locking.WriteLockConcern;
-import org.qi4j.spi.entitystore.*;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreActivation;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreMixin;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * EntityStore service backed by JDBM store.
- * <p>Based on @{@link JSONMapEntityStoreMixin}.</p>
- */
-@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class, ReadLockConcern.class, WriteLockConcern.class } )
-@Mixins( { JSONMapEntityStoreMixin.class, JdbmEntityStoreMixin.class } )
-public interface JdbmEntityStoreService
-    extends JdbmEntityStoreActivation,
-            JSONMapEntityStoreActivation,
-            EntityStore,
-            EntityStateVersions,
-            StateStore,
-            BackupRestore,
-            ServiceComposite,
-            LockingAbstractComposite,
-            Configuration<JdbmConfiguration>
-{
-}
diff --git a/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/assembly/JdbmEntityStoreAssembler.java b/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/assembly/JdbmEntityStoreAssembler.java
deleted file mode 100644
index e860baa..0000000
--- a/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/assembly/JdbmEntityStoreAssembler.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.entitystore.jdbm.assembly;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.entitystore.jdbm.JdbmConfiguration;
-import org.qi4j.entitystore.jdbm.JdbmEntityStoreService;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-
-public class JdbmEntityStoreAssembler
-    extends Assemblers.VisibilityIdentityConfig<JdbmEntityStoreAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( JdbmEntityStoreService.class ).visibleIn( visibility() );
-        ServiceDeclaration service = module.services( UuidIdentityGeneratorService.class ).visibleIn( visibility() );
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        if( hasConfig() )
-        {
-            configModule().entities( JdbmConfiguration.class ).visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/assembly/package.html b/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/assembly/package.html
deleted file mode 100644
index ebb37ee..0000000
--- a/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/assembly/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>JDBM EntityStore Assembly.</h2>
-    </body>
-</html>
diff --git a/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/package.html b/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/package.html
deleted file mode 100644
index 8a0ef8f..0000000
--- a/extensions/entitystore-jdbm/src/main/java/org/qi4j/entitystore/jdbm/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>JDBM EntityStore.</h2>
-    </body>
-</html>
diff --git a/extensions/entitystore-jdbm/src/test/java/org/apache/polygene/entitystore/jdbm/DocumentationSupport.java b/extensions/entitystore-jdbm/src/test/java/org/apache/polygene/entitystore/jdbm/DocumentationSupport.java
new file mode 100644
index 0000000..467bc9c
--- /dev/null
+++ b/extensions/entitystore-jdbm/src/test/java/org/apache/polygene/entitystore/jdbm/DocumentationSupport.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.entitystore.jdbm;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.jdbm.assembly.JdbmEntityStoreAssembler;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+public class DocumentationSupport extends AbstractPolygeneTest
+{
+    
+    // START SNIPPET: UsingAssembler
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new JdbmEntityStoreAssembler().assemble( module );
+    }
+    // END SNIPPET: UsingAssembler
+}
diff --git a/extensions/entitystore-jdbm/src/test/java/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreTest.java b/extensions/entitystore-jdbm/src/test/java/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreTest.java
new file mode 100644
index 0000000..bd3cef4
--- /dev/null
+++ b/extensions/entitystore-jdbm/src/test/java/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreTest.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.entitystore.jdbm;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.jdbm.assembly.JdbmEntityStoreAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+public class JdbmEntityStoreTest
+    extends AbstractEntityStoreTest
+{
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+        new JdbmEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+    }
+}
diff --git a/extensions/entitystore-jdbm/src/test/java/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreWithCacheTest.java b/extensions/entitystore-jdbm/src/test/java/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreWithCacheTest.java
new file mode 100644
index 0000000..b6bed70
--- /dev/null
+++ b/extensions/entitystore-jdbm/src/test/java/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreWithCacheTest.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.entitystore.jdbm;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.jdbm.assembly.JdbmEntityStoreAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.cache.AbstractEntityStoreWithCacheTest;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+public class JdbmEntityStoreWithCacheTest
+    extends AbstractEntityStoreWithCacheTest
+{
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+        new JdbmEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+    }
+}
diff --git a/extensions/entitystore-jdbm/src/test/java/org/qi4j/entitystore/jdbm/DocumentationSupport.java b/extensions/entitystore-jdbm/src/test/java/org/qi4j/entitystore/jdbm/DocumentationSupport.java
deleted file mode 100644
index ace505f..0000000
--- a/extensions/entitystore-jdbm/src/test/java/org/qi4j/entitystore/jdbm/DocumentationSupport.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.jdbm;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.jdbm.assembly.JdbmEntityStoreAssembler;
-import org.qi4j.test.AbstractQi4jTest;
-
-public class DocumentationSupport extends AbstractQi4jTest
-{
-    
-    // START SNIPPET: UsingAssembler
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new JdbmEntityStoreAssembler().assemble( module );
-    }
-    // END SNIPPET: UsingAssembler
-}
diff --git a/extensions/entitystore-jdbm/src/test/java/org/qi4j/entitystore/jdbm/JdbmEntityStoreTest.java b/extensions/entitystore-jdbm/src/test/java/org/qi4j/entitystore/jdbm/JdbmEntityStoreTest.java
deleted file mode 100644
index 7b4b441..0000000
--- a/extensions/entitystore-jdbm/src/test/java/org/qi4j/entitystore/jdbm/JdbmEntityStoreTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*  Copyright 2008 Rickard Öberg.
- *
- * Licensed 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.qi4j.entitystore.jdbm;
-
-import org.junit.Before;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.jdbm.assembly.JdbmEntityStoreAssembler;
-import org.qi4j.library.fileconfig.FileConfiguration;
-import org.qi4j.library.fileconfig.FileConfigurationDataWiper;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class JdbmEntityStoreTest
-    extends AbstractEntityStoreTest
-{
-
-    @Before
-    public void testDataCleanup()
-    {
-        FileConfiguration fileConfig = module.findService( FileConfiguration.class ).get();
-        FileConfigurationDataWiper.registerApplicationPassivationDataWiper( fileConfig, application );
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-
-        ModuleAssembly config = module.layer().module( "config" );
-        config.services( FileConfigurationService.class ).visibleIn( Visibility.layer ).instantiateOnStartup();
-        new EntityTestAssembler().assemble( config );
-
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        new JdbmEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
-    }
-
-}
diff --git a/extensions/entitystore-jdbm/src/test/java/org/qi4j/entitystore/jdbm/JdbmEntityStoreWithCacheTest.java b/extensions/entitystore-jdbm/src/test/java/org/qi4j/entitystore/jdbm/JdbmEntityStoreWithCacheTest.java
deleted file mode 100644
index f5ded45..0000000
--- a/extensions/entitystore-jdbm/src/test/java/org/qi4j/entitystore/jdbm/JdbmEntityStoreWithCacheTest.java
+++ /dev/null
@@ -1,54 +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.qi4j.entitystore.jdbm;
-
-import org.junit.Before;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.jdbm.assembly.JdbmEntityStoreAssembler;
-import org.qi4j.library.fileconfig.FileConfiguration;
-import org.qi4j.library.fileconfig.FileConfigurationDataWiper;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.cache.AbstractEntityStoreWithCacheTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class JdbmEntityStoreWithCacheTest
-    extends AbstractEntityStoreWithCacheTest
-{
-    @Before
-    public void testDataCleanup()
-    {
-        FileConfiguration fileConfig = module.findService( FileConfiguration.class ).get();
-        FileConfigurationDataWiper.registerApplicationPassivationDataWiper( fileConfig, application );
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-
-        ModuleAssembly config = module.layer().module( "config" );
-        config.services( FileConfigurationService.class ).visibleIn( Visibility.layer ).instantiateOnStartup();
-        new EntityTestAssembler().assemble( config );
-
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        new JdbmEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
-    }
-}
diff --git a/extensions/entitystore-leveldb/build.gradle b/extensions/entitystore-leveldb/build.gradle
index de2a431..98b8460 100644
--- a/extensions/entitystore-leveldb/build.gradle
+++ b/extensions/entitystore-leveldb/build.gradle
@@ -1,40 +1,41 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ LevelDB EntityStore Extension"
+apply plugin: 'polygene-extension'
 
-jar { manifest { name = "Apache Zest™ Extension - EntityStore - LevelDB" }}
+description = "Apache Polygene™ LevelDB EntityStore Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - EntityStore - LevelDB" } }
 
 dependencies {
+  api polygene.core.bootstrap
+  api polygene.library( 'fileconfig' )
 
-    compile project( ":org.qi4j.core:org.qi4j.core.bootstrap" )
-    compile project( ":org.qi4j.libraries:org.qi4j.library.locking" )
-    compile project( ":org.qi4j.libraries:org.qi4j.library.fileconfig" )
-    compile libraries.leveldb_api
+  implementation polygene.library( 'locking' )
+  implementation libraries.leveldb_api
 
-    runtime libraries.leveldb_java
-    runtime libraries.leveldb_jni_all
+  runtimeOnly polygene.core.runtime
+  runtimeOnly libraries.leveldb_java
+  runtimeOnly libraries.leveldb_jni_all
 
-    testCompile project( ":org.qi4j.core:org.qi4j.core.testsupport" )
-    testCompile(project(":org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson"))
+  testImplementation polygene.core.testsupport
 
-    testRuntime project( ":org.qi4j.core:org.qi4j.core.runtime" )
-    testRuntime libraries.logback
-
+  testRuntimeOnly libraries.logback
 }
diff --git a/extensions/entitystore-leveldb/dev-status.xml b/extensions/entitystore-leveldb/dev-status.xml
index 91d4a63..762e250 100644
--- a/extensions/entitystore-leveldb/dev-status.xml
+++ b/extensions/entitystore-leveldb/dev-status.xml
@@ -1,27 +1,30 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
         <!--none,early,beta,stable,mature-->
-        <codebase>beta</codebase>
+        <codebase>stable</codebase>
 
         <!-- none, brief, good, complete -->
         <documentation>brief</documentation>
diff --git a/extensions/entitystore-leveldb/src/docs/es-leveldb.txt b/extensions/entitystore-leveldb/src/docs/es-leveldb.txt
index ffbc16a..940a645 100644
--- a/extensions/entitystore-leveldb/src/docs/es-leveldb.txt
+++ b/extensions/entitystore-leveldb/src/docs/es-leveldb.txt
@@ -43,7 +43,7 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-leveldb/src/test/java/org/qi4j/entitystore/leveldb/JavaLevelDBEntityStoreTest.java
+source=extensions/entitystore-leveldb/src/test/java/org/apache/polygene/entitystore/leveldb/JavaLevelDBEntityStoreTest.java
 tag=assembly
 ----
 
@@ -53,7 +53,7 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-leveldb/src/main/java/org/qi4j/entitystore/leveldb/LevelDBEntityStoreConfiguration.java
+source=extensions/entitystore-leveldb/src/main/java/org/apache/polygene/entitystore/leveldb/LevelDBEntityStoreConfiguration.java
 tag=config
 ----
 
diff --git a/extensions/entitystore-leveldb/src/main/java/org/apache/polygene/entitystore/leveldb/LevelDBEntityStoreConfiguration.java b/extensions/entitystore-leveldb/src/main/java/org/apache/polygene/entitystore/leveldb/LevelDBEntityStoreConfiguration.java
new file mode 100644
index 0000000..1042b69
--- /dev/null
+++ b/extensions/entitystore-leveldb/src/main/java/org/apache/polygene/entitystore/leveldb/LevelDBEntityStoreConfiguration.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.entitystore.leveldb;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Configuration for LevelDBEntityStoreService.
+ */
+// START SNIPPET: config
+public interface LevelDBEntityStoreConfiguration
+{
+    /**
+     * LevelDB flavour, can be 'java' or 'jni'.
+     * By default, tries 'jni' and fallback to 'java'.
+     */
+    @Optional
+    Property<String> flavour();
+
+    @Optional
+    Property<Integer> blockRestartInterval();
+
+    @Optional
+    Property<Integer> blockSize();
+
+    @Optional
+    Property<Long> cacheSize();
+
+    @Optional
+    Property<Boolean> compression();
+
+    @Optional
+    Property<Integer> maxOpenFiles();
+
+    @Optional
+    Property<Boolean> paranoidChecks();
+
+    @Optional
+    Property<Boolean> verifyChecksums();
+
+    @Optional
+    Property<Integer> writeBufferSize();
+}
+// END SNIPPET: config
diff --git a/extensions/entitystore-leveldb/src/main/java/org/apache/polygene/entitystore/leveldb/LevelDBEntityStoreMixin.java b/extensions/entitystore-leveldb/src/main/java/org/apache/polygene/entitystore/leveldb/LevelDBEntityStoreMixin.java
new file mode 100644
index 0000000..1db246e
--- /dev/null
+++ b/extensions/entitystore-leveldb/src/main/java/org/apache/polygene/entitystore/leveldb/LevelDBEntityStoreMixin.java
@@ -0,0 +1,300 @@
+/*
+ *  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.polygene.entitystore.leveldb;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.library.fileconfig.FileConfiguration;
+import org.apache.polygene.spi.entitystore.EntityNotFoundException;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+import org.apache.polygene.spi.entitystore.helpers.MapEntityStore;
+import org.iq80.leveldb.CompressionType;
+import org.iq80.leveldb.DB;
+import org.iq80.leveldb.DBFactory;
+import org.iq80.leveldb.DBIterator;
+import org.iq80.leveldb.Options;
+import org.iq80.leveldb.WriteBatch;
+
+/**
+ * LevelDB implementation of MapEntityStore.
+ */
+public class LevelDBEntityStoreMixin
+    implements ServiceActivation, MapEntityStore
+{
+
+    @Service
+    private FileConfiguration fileConfig;
+    @This
+    private Configuration<LevelDBEntityStoreConfiguration> configuration;
+    @Uses
+    private ServiceDescriptor descriptor;
+    private Charset charset;
+    private DB db;
+
+    @Override
+    public void activateService()
+        throws Exception
+    {
+        charset = Charset.forName( "UTF-8" );
+        configuration.refresh();
+        LevelDBEntityStoreConfiguration config = configuration.get();
+
+        // Choose flavour
+        String flavour = config.flavour().get();
+        DBFactory factory;
+        if( "jni".equalsIgnoreCase( flavour ) )
+        {
+            factory = newJniDBFactory();
+        }
+        else if( "java".equalsIgnoreCase( flavour ) )
+        {
+            factory = newJavaDBFactory();
+        }
+        else
+        {
+            factory = newDBFactory();
+        }
+
+        // Apply configuration
+        Options options = new Options();
+        options.createIfMissing( true );
+        if( config.blockRestartInterval().get() != null )
+        {
+            options.blockRestartInterval( config.blockRestartInterval().get() );
+        }
+        if( config.blockSize().get() != null )
+        {
+            options.blockSize( config.blockSize().get() );
+        }
+        if( config.cacheSize().get() != null )
+        {
+            options.cacheSize( config.cacheSize().get() );
+        }
+        if( config.compression().get() != null )
+        {
+            options.compressionType( config.compression().get()
+                                     ? CompressionType.SNAPPY
+                                     : CompressionType.NONE );
+        }
+        if( config.maxOpenFiles().get() != null )
+        {
+            options.maxOpenFiles( config.maxOpenFiles().get() );
+        }
+        if( config.paranoidChecks().get() != null )
+        {
+            options.paranoidChecks( config.paranoidChecks().get() );
+        }
+        if( config.verifyChecksums().get() != null )
+        {
+            options.verifyChecksums( config.verifyChecksums().get() );
+        }
+        if( config.writeBufferSize().get() != null )
+        {
+            options.writeBufferSize( config.writeBufferSize().get() );
+        }
+
+        // Open/Create the database
+        File dbFile = new File( fileConfig.dataDirectory(), descriptor.identity().toString() );
+        db = factory.open( dbFile, options );
+    }
+
+    /**
+     * Tries in order: JNI and then pure Java LevelDB implementations.
+     */
+    private DBFactory newDBFactory()
+    {
+        try
+        {
+            return newJniDBFactory();
+        }
+        catch( Exception ex )
+        {
+            try
+            {
+                return newJavaDBFactory();
+            }
+            catch( Exception ex2 )
+            {
+                throw new RuntimeException( "Unable to create a LevelDB DBFactory instance. "
+                                            + "Tried JNI and pure Java. "
+                                            + "The stacktrace is the pure Java attempt.", ex2 );
+            }
+        }
+    }
+
+    private DBFactory newJniDBFactory()
+        throws Exception
+    {
+        return (DBFactory) Class.forName( "org.fusesource.leveldbjni.JniDBFactory" ).newInstance();
+    }
+
+    private DBFactory newJavaDBFactory()
+        throws Exception
+    {
+        return (DBFactory) Class.forName( "org.iq80.leveldb.impl.Iq80DBFactory" ).newInstance();
+    }
+
+    @Override
+    public void passivateService()
+        throws Exception
+    {
+        try
+        {
+            db.close();
+        }
+        finally
+        {
+            db = null;
+            charset = null;
+        }
+    }
+
+    @Override
+    public Reader get( EntityReference entityReference )
+        throws EntityStoreException
+    {
+        byte[] state = db.get( entityReference.identity().toString().getBytes( charset ) );
+        if( state == null )
+        {
+            throw new EntityNotFoundException( entityReference );
+        }
+        String jsonState = new String( state, charset );
+        return new StringReader( jsonState );
+    }
+
+    @Override
+    public Stream<Reader> entityStates()
+    {
+        DBIterator iterator = db.iterator();
+        iterator.seekToFirst();
+        return StreamSupport.stream(
+            new Spliterators.AbstractSpliterator<Reader>( Long.MAX_VALUE, Spliterator.ORDERED )
+            {
+                @Override
+                public boolean tryAdvance( final Consumer<? super Reader> action )
+                {
+                    if( !iterator.hasNext() )
+                    {
+                        return false;
+                    }
+                    action.accept( new StringReader( new String( iterator.next().getValue(), charset ) ) );
+                    return true;
+                }
+            },
+            false
+        ).onClose(
+            () ->
+            {
+                try
+                {
+                    iterator.close();
+                }
+                catch( IOException ex )
+                {
+                    throw new EntityStoreException( "Unable to close DB iterator" );
+                }
+            }
+        );
+    }
+
+    @Override
+    public void applyChanges( MapChanges changes )
+        throws Exception
+    {
+        final WriteBatch writeBatch = db.createWriteBatch();
+        try
+        {
+            changes.visitMap( new MapChanger()
+            {
+
+                @Override
+                public Writer newEntity( EntityReference ref, EntityDescriptor entityDescriptor )
+                    throws IOException
+                {
+                    return new StringWriter( 1000 )
+                    {
+
+                        @Override
+                        public void close()
+                            throws IOException
+                        {
+                            super.close();
+                            String jsonState = toString();
+                            writeBatch.put( ref.identity().toString().getBytes( charset ), jsonState.getBytes( charset ) );
+                        }
+
+                    };
+                }
+
+                @Override
+                public Writer updateEntity( MapChange mapChange )
+                    throws IOException
+                {
+                    return new StringWriter( 1000 )
+                    {
+
+                        @Override
+                        public void close()
+                            throws IOException
+                        {
+                            super.close();
+                            String jsonState = toString();
+                            writeBatch.put( mapChange.reference().identity().toString().getBytes( charset ),
+                                            jsonState.getBytes( charset ) );
+                        }
+
+                    };
+                }
+
+                @Override
+                public void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor )
+                    throws EntityNotFoundException
+                {
+                    writeBatch.delete( ref.identity().toString().getBytes( charset ) );
+                }
+
+            } );
+            db.write( writeBatch );
+        }
+        finally
+        {
+            writeBatch.close();
+        }
+    }
+
+}
diff --git a/extensions/entitystore-leveldb/src/main/java/org/apache/polygene/entitystore/leveldb/LevelDBEntityStoreService.java b/extensions/entitystore-leveldb/src/main/java/org/apache/polygene/entitystore/leveldb/LevelDBEntityStoreService.java
new file mode 100644
index 0000000..8eca2f6
--- /dev/null
+++ b/extensions/entitystore-leveldb/src/main/java/org/apache/polygene/entitystore/leveldb/LevelDBEntityStoreService.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.entitystore.leveldb;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.library.locking.LockingAbstractComposite;
+import org.apache.polygene.spi.entitystore.ConcurrentModificationCheckConcern;
+import org.apache.polygene.spi.entitystore.EntityStateVersions;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.StateChangeNotificationConcern;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreActivation;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreMixin;
+
+/**
+ * LevelDB EntityStore service.
+ * <p>Based on @{@link JSONMapEntityStoreMixin}.</p>
+ */
+@Concerns(
+{
+    StateChangeNotificationConcern.class,
+    ConcurrentModificationCheckConcern.class
+} )
+@Mixins(
+{
+    JSONMapEntityStoreMixin.class,
+    LevelDBEntityStoreMixin.class
+} )
+public interface LevelDBEntityStoreService
+    extends EntityStore,
+            EntityStateVersions,
+            ServiceActivation,
+            JSONMapEntityStoreActivation,
+            LockingAbstractComposite,
+            Configuration
+{
+}
diff --git a/extensions/entitystore-leveldb/src/main/java/org/apache/polygene/entitystore/leveldb/assembly/LevelDBEntityStoreAssembler.java b/extensions/entitystore-leveldb/src/main/java/org/apache/polygene/entitystore/leveldb/assembly/LevelDBEntityStoreAssembler.java
new file mode 100644
index 0000000..aec01be
--- /dev/null
+++ b/extensions/entitystore-leveldb/src/main/java/org/apache/polygene/entitystore/leveldb/assembly/LevelDBEntityStoreAssembler.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.entitystore.leveldb.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.entitystore.leveldb.LevelDBEntityStoreConfiguration;
+import org.apache.polygene.entitystore.leveldb.LevelDBEntityStoreService;
+
+/**
+ * LevelDB EntityStore assembly.
+ */
+public class LevelDBEntityStoreAssembler
+    extends Assemblers.VisibilityIdentityConfig<LevelDBEntityStoreAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( LevelDBEntityStoreService.class ).visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+        if( hasConfig() )
+        {
+            configModule().entities( LevelDBEntityStoreConfiguration.class ).visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/extensions/entitystore-leveldb/src/main/java/org/apache/polygene/entitystore/leveldb/package.html b/extensions/entitystore-leveldb/src/main/java/org/apache/polygene/entitystore/leveldb/package.html
new file mode 100644
index 0000000..bda6cf6
--- /dev/null
+++ b/extensions/entitystore-leveldb/src/main/java/org/apache/polygene/entitystore/leveldb/package.html
@@ -0,0 +1,39 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>LevelDB EntityStore.</h2>
+        <blockquote>
+            LevelDB is a fast key-value storage library written at Google that provides an ordered mapping from string
+            keys to string values.
+        </blockquote>
+        <p>
+            By default use the native implementation through JNI bindings and fallback to the pure java implementation
+            if not available on the current platform. Used implementation can be forced using the
+            {@link org.apache.polygene.entitystore.leveldb.LevelDBEntityStoreConfiguration#flavour()} property.
+        </p>
+        <p>See:</p>
+        <ul>
+            <li>LevelDB <a href="https://code.google.com/p/leveldb/">https://code.google.com/p/leveldb/</a></li>
+            <li>JNI bindings <a href="https://github.com/fusesource/leveldbjni">https://github.com/fusesource/leveldbjni</a></li>
+            <li>Pure Java implementation <a href="https://github.com/dain/leveldb">https://github.com/dain/leveldb</a></li>
+        </ul>
+    </body>
+</html>
diff --git a/extensions/entitystore-leveldb/src/main/java/org/qi4j/entitystore/leveldb/LevelDBEntityStoreAssembler.java b/extensions/entitystore-leveldb/src/main/java/org/qi4j/entitystore/leveldb/LevelDBEntityStoreAssembler.java
deleted file mode 100644
index 8a7c34b..0000000
--- a/extensions/entitystore-leveldb/src/main/java/org/qi4j/entitystore/leveldb/LevelDBEntityStoreAssembler.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2012, Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.leveldb;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-
-/**
- * LevelDB EntityStore assembly.
- */
-public class LevelDBEntityStoreAssembler
-    extends Assemblers.VisibilityIdentityConfig<LevelDBEntityStoreAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( UuidIdentityGeneratorService.class );
-        ServiceDeclaration service = module.services( LevelDBEntityStoreService.class ).visibleIn( visibility() );
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        if( hasConfig() )
-        {
-            configModule().entities( LevelDBEntityStoreConfiguration.class ).visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/extensions/entitystore-leveldb/src/main/java/org/qi4j/entitystore/leveldb/LevelDBEntityStoreConfiguration.java b/extensions/entitystore-leveldb/src/main/java/org/qi4j/entitystore/leveldb/LevelDBEntityStoreConfiguration.java
deleted file mode 100644
index ea94fe4..0000000
--- a/extensions/entitystore-leveldb/src/main/java/org/qi4j/entitystore/leveldb/LevelDBEntityStoreConfiguration.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2012, Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.leveldb;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-/**
- * Configuration for LevelDBEntityStoreService.
- */
-// START SNIPPET: config
-public interface LevelDBEntityStoreConfiguration
-    extends ConfigurationComposite
-{
-
-    /**
-     * LevelDB flavour, can be 'java' or 'jni'.
-     * By default, tries 'jni' and fallback to 'java'.
-     */
-    @Optional
-    Property<String> flavour();
-
-    @Optional
-    Property<Integer> blockRestartInterval();
-
-    @Optional
-    Property<Integer> blockSize();
-
-    @Optional
-    Property<Long> cacheSize();
-
-    @Optional
-    Property<Boolean> compression();
-
-    @Optional
-    Property<Integer> maxOpenFiles();
-
-    @Optional
-    Property<Boolean> paranoidChecks();
-
-    @Optional
-    Property<Boolean> verifyChecksums();
-
-    @Optional
-    Property<Integer> writeBufferSize();
-
-}
-// END SNIPPET: config
diff --git a/extensions/entitystore-leveldb/src/main/java/org/qi4j/entitystore/leveldb/LevelDBEntityStoreMixin.java b/extensions/entitystore-leveldb/src/main/java/org/qi4j/entitystore/leveldb/LevelDBEntityStoreMixin.java
deleted file mode 100644
index d71c033..0000000
--- a/extensions/entitystore-leveldb/src/main/java/org/qi4j/entitystore/leveldb/LevelDBEntityStoreMixin.java
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright 2012, Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.leveldb;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.nio.charset.Charset;
-import org.iq80.leveldb.CompressionType;
-import org.iq80.leveldb.DB;
-import org.iq80.leveldb.DBFactory;
-import org.iq80.leveldb.DBIterator;
-import org.iq80.leveldb.Options;
-import org.iq80.leveldb.WriteBatch;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.library.fileconfig.FileConfiguration;
-import org.qi4j.spi.entitystore.EntityNotFoundException;
-import org.qi4j.spi.entitystore.EntityStoreException;
-import org.qi4j.spi.entitystore.helpers.MapEntityStore;
-
-/**
- * LevelDB implementation of MapEntityStore.
- */
-public class LevelDBEntityStoreMixin
-    implements ServiceActivation, MapEntityStore
-{
-
-    @Service
-    private FileConfiguration fileConfig;
-    @This
-    private Configuration<LevelDBEntityStoreConfiguration> configuration;
-    @Uses
-    private ServiceDescriptor descriptor;
-    private Charset charset;
-    private DB db;
-
-    @Override
-    public void activateService()
-        throws Exception
-    {
-        charset = Charset.forName( "UTF-8" );
-        configuration.refresh();
-        LevelDBEntityStoreConfiguration config = configuration.get();
-
-        // Choose flavour
-        String flavour = config.flavour().get();
-        DBFactory factory;
-        if( "jni".equalsIgnoreCase( flavour ) )
-        {
-            factory = newJniDBFactory();
-        }
-        else if( "java".equalsIgnoreCase( flavour ) )
-        {
-            factory = newJavaDBFactory();
-        }
-        else
-        {
-            factory = newDBFactory();
-        }
-
-        // Apply configuration
-        Options options = new Options();
-        options.createIfMissing( true );
-        if( config.blockRestartInterval().get() != null )
-        {
-            options.blockRestartInterval( config.blockRestartInterval().get() );
-        }
-        if( config.blockSize().get() != null )
-        {
-            options.blockSize( config.blockSize().get() );
-        }
-        if( config.cacheSize().get() != null )
-        {
-            options.cacheSize( config.cacheSize().get() );
-        }
-        if( config.compression().get() != null )
-        {
-            options.compressionType( config.compression().get()
-                                     ? CompressionType.SNAPPY
-                                     : CompressionType.NONE );
-        }
-        if( config.maxOpenFiles().get() != null )
-        {
-            options.maxOpenFiles( config.maxOpenFiles().get() );
-        }
-        if( config.paranoidChecks().get() != null )
-        {
-            options.paranoidChecks( config.paranoidChecks().get() );
-        }
-        if( config.verifyChecksums().get() != null )
-        {
-            options.verifyChecksums( config.verifyChecksums().get() );
-        }
-        if( config.writeBufferSize().get() != null )
-        {
-            options.writeBufferSize( config.writeBufferSize().get() );
-        }
-
-        // Open/Create the database
-        File dbFile = new File( fileConfig.dataDirectory(), descriptor.identity() );
-        db = factory.open( dbFile, options );
-    }
-
-    /**
-     * Tries in order: JNI and then pure Java LevelDB implementations.
-     */
-    private DBFactory newDBFactory()
-    {
-        try
-        {
-            return newJniDBFactory();
-        }
-        catch( Exception ex )
-        {
-            try
-            {
-                return newJavaDBFactory();
-            }
-            catch( Exception ex2 )
-            {
-                throw new RuntimeException( "Unable to create a LevelDB DBFactory instance. "
-                                            + "Tried JNI and pure Java. "
-                                            + "The stacktrace is the pure Java attempt.", ex2 );
-            }
-        }
-    }
-
-    private DBFactory newJniDBFactory()
-        throws Exception
-    {
-        return (DBFactory) Class.forName( "org.fusesource.leveldbjni.JniDBFactory" ).newInstance();
-    }
-
-    private DBFactory newJavaDBFactory()
-        throws Exception
-    {
-        return (DBFactory) Class.forName( "org.iq80.leveldb.impl.Iq80DBFactory" ).newInstance();
-    }
-
-    @Override
-    public void passivateService()
-        throws Exception
-    {
-        try
-        {
-            db.close();
-        }
-        finally
-        {
-            db = null;
-            charset = null;
-        }
-    }
-
-    @Override
-    public Reader get( EntityReference entityReference )
-        throws EntityStoreException
-    {
-        byte[] state = db.get( entityReference.identity().getBytes( charset ) );
-        if( state == null )
-        {
-            throw new EntityNotFoundException( entityReference );
-        }
-        String jsonState = new String( state, charset );
-        return new StringReader( jsonState );
-    }
-
-    @Override
-    public Input<Reader, IOException> entityStates()
-    {
-        return new Input<Reader, IOException>()
-        {
-
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super Reader, ReceiverThrowableType> output )
-                throws IOException, ReceiverThrowableType
-            {
-                output.receiveFrom( new Sender<Reader, IOException>()
-                {
-
-                    @Override
-                    public <ReceiverThrowableType extends Throwable> void sendTo( Receiver<? super Reader, ReceiverThrowableType> receiver )
-                        throws ReceiverThrowableType, IOException
-                    {
-                        DBIterator iterator = db.iterator();
-                        try
-                        {
-                            for( iterator.seekToFirst(); iterator.hasNext(); iterator.next() )
-                            {
-                                byte[] state = iterator.peekNext().getValue();
-                                String jsonState = new String( state, charset );
-                                receiver.receive( new StringReader( jsonState ) );
-                            }
-                        }
-                        finally
-                        {
-                            iterator.close();
-                        }
-                    }
-
-                } );
-            }
-
-        };
-    }
-
-    @Override
-    public void applyChanges( MapChanges changes )
-        throws IOException
-    {
-        final WriteBatch writeBatch = db.createWriteBatch();
-        try
-        {
-            changes.visitMap( new MapChanger()
-            {
-
-                @Override
-                public Writer newEntity( final EntityReference ref, EntityDescriptor entityDescriptor )
-                    throws IOException
-                {
-                    return new StringWriter( 1000 )
-                    {
-
-                        @Override
-                        public void close()
-                            throws IOException
-                        {
-                            super.close();
-                            String jsonState = toString();
-                            writeBatch.put( ref.identity().getBytes( charset ), jsonState.getBytes( charset ) );
-                        }
-
-                    };
-                }
-
-                @Override
-                public Writer updateEntity( final EntityReference ref, EntityDescriptor entityDescriptor )
-                    throws IOException
-                {
-                    return new StringWriter( 1000 )
-                    {
-
-                        @Override
-                        public void close()
-                            throws IOException
-                        {
-                            super.close();
-                            String jsonState = toString();
-                            writeBatch.put( ref.identity().getBytes( charset ), jsonState.getBytes( charset ) );
-                        }
-
-                    };
-                }
-
-                @Override
-                public void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor )
-                    throws EntityNotFoundException
-                {
-                    writeBatch.delete( ref.identity().getBytes( charset ) );
-                }
-
-            } );
-            db.write( writeBatch );
-        }
-        finally
-        {
-            writeBatch.close();
-        }
-    }
-
-}
diff --git a/extensions/entitystore-leveldb/src/main/java/org/qi4j/entitystore/leveldb/LevelDBEntityStoreService.java b/extensions/entitystore-leveldb/src/main/java/org/qi4j/entitystore/leveldb/LevelDBEntityStoreService.java
deleted file mode 100644
index 98199e7..0000000
--- a/extensions/entitystore-leveldb/src/main/java/org/qi4j/entitystore/leveldb/LevelDBEntityStoreService.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2012, Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.leveldb;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.library.locking.LockingAbstractComposite;
-import org.qi4j.spi.entitystore.ConcurrentModificationCheckConcern;
-import org.qi4j.spi.entitystore.EntityStateVersions;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.StateChangeNotificationConcern;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreActivation;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreMixin;
-
-/**
- * LevelDB EntityStore service.
- * <p>Based on @{@link JSONMapEntityStoreMixin}.</p>
- */
-@Concerns(
-{
-    StateChangeNotificationConcern.class,
-    ConcurrentModificationCheckConcern.class
-} )
-@Mixins(
-{
-    JSONMapEntityStoreMixin.class,
-    LevelDBEntityStoreMixin.class
-} )
-public interface LevelDBEntityStoreService
-    extends EntityStore,
-            EntityStateVersions,
-            ServiceComposite,
-            ServiceActivation,
-            JSONMapEntityStoreActivation,
-            LockingAbstractComposite,
-            Configuration
-{
-}
diff --git a/extensions/entitystore-leveldb/src/main/java/org/qi4j/entitystore/leveldb/package.html b/extensions/entitystore-leveldb/src/main/java/org/qi4j/entitystore/leveldb/package.html
deleted file mode 100644
index 720a3ff..0000000
--- a/extensions/entitystore-leveldb/src/main/java/org/qi4j/entitystore/leveldb/package.html
+++ /dev/null
@@ -1,36 +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.
--->
-<html>
-    <body>
-        <h2>LevelDB EntityStore.</h2>
-        <blockquote>
-            LevelDB is a fast key-value storage library written at Google that provides an ordered mapping from string
-            keys to string values.
-        </blockquote>
-        <p>
-            By default use the native implementation through JNI bindings and fallback to the pure java implementation
-            if not available on the current platform. Used implementation can be forced using the
-            {@link org.qi4j.entitystore.leveldb.LevelDBEntityStoreConfiguration#flavour()} property.
-        </p>
-        <p>See:</p>
-        <ul>
-            <li>LevelDB <a href="https://code.google.com/p/leveldb/">https://code.google.com/p/leveldb/</a></li>
-            <li>JNI bindings <a href="https://github.com/fusesource/leveldbjni">https://github.com/fusesource/leveldbjni</a></li>
-            <li>Pure Java implementation <a href="https://github.com/dain/leveldb">https://github.com/dain/leveldb</a></li>
-        </ul>
-    </body>
-</html>
diff --git a/extensions/entitystore-leveldb/src/test/java/org/apache/polygene/entitystore/leveldb/JavaLevelDBEntityStoreTest.java b/extensions/entitystore-leveldb/src/test/java/org/apache/polygene/entitystore/leveldb/JavaLevelDBEntityStoreTest.java
new file mode 100644
index 0000000..c5d4cdc
--- /dev/null
+++ b/extensions/entitystore-leveldb/src/test/java/org/apache/polygene/entitystore/leveldb/JavaLevelDBEntityStoreTest.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.entitystore.leveldb;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.leveldb.assembly.LevelDBEntityStoreAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+public class JavaLevelDBEntityStoreTest
+    extends AbstractEntityStoreTest
+{
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // END SNIPPET: assembly
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().visibleIn( Visibility.module ).assemble( config );
+
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+
+        // START SNIPPET: assembly
+        new LevelDBEntityStoreAssembler()
+            .withConfig( config, Visibility.layer )
+            .identifiedBy( "java-leveldb-entitystore" )
+            .assemble( module );
+        // END SNIPPET: assembly
+
+        config.forMixin( LevelDBEntityStoreConfiguration.class ).declareDefaults().flavour().set( "java" );
+        // START SNIPPET: assembly
+    }
+    // END SNIPPET: assembly
+}
diff --git a/extensions/entitystore-leveldb/src/test/java/org/apache/polygene/entitystore/leveldb/JniLevelDBEntityStoreTest.java b/extensions/entitystore-leveldb/src/test/java/org/apache/polygene/entitystore/leveldb/JniLevelDBEntityStoreTest.java
new file mode 100644
index 0000000..819d930
--- /dev/null
+++ b/extensions/entitystore-leveldb/src/test/java/org/apache/polygene/entitystore/leveldb/JniLevelDBEntityStoreTest.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.entitystore.leveldb;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.leveldb.assembly.LevelDBEntityStoreAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+public class JniLevelDBEntityStoreTest
+    extends AbstractEntityStoreTest
+{
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().visibleIn( Visibility.module ).assemble( config );
+
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+
+        new LevelDBEntityStoreAssembler()
+            .withConfig( config, Visibility.layer )
+            .identifiedBy( "jni-leveldb-entitystore" )
+            .assemble( module );
+
+        config.forMixin( LevelDBEntityStoreConfiguration.class ).declareDefaults().flavour().set( "jni" );
+    }
+}
diff --git a/extensions/entitystore-leveldb/src/test/java/org/apache/polygene/entitystore/leveldb/LevelDBEntityStoreWithCacheTest.java b/extensions/entitystore-leveldb/src/test/java/org/apache/polygene/entitystore/leveldb/LevelDBEntityStoreWithCacheTest.java
new file mode 100644
index 0000000..9840501
--- /dev/null
+++ b/extensions/entitystore-leveldb/src/test/java/org/apache/polygene/entitystore/leveldb/LevelDBEntityStoreWithCacheTest.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.entitystore.leveldb;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.leveldb.assembly.LevelDBEntityStoreAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.cache.AbstractEntityStoreWithCacheTest;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+public class LevelDBEntityStoreWithCacheTest
+    extends AbstractEntityStoreWithCacheTest
+{
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().visibleIn( Visibility.module ).assemble( config );
+
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+
+        new LevelDBEntityStoreAssembler().
+                                             withConfig( config, Visibility.layer ).
+                                             identifiedBy( "java-leveldb-entitystore" ).
+                                             assemble( module );
+    }
+}
diff --git a/extensions/entitystore-leveldb/src/test/java/org/qi4j/entitystore/leveldb/JavaLevelDBEntityStoreTest.java b/extensions/entitystore-leveldb/src/test/java/org/qi4j/entitystore/leveldb/JavaLevelDBEntityStoreTest.java
deleted file mode 100644
index d2811d5..0000000
--- a/extensions/entitystore-leveldb/src/test/java/org/qi4j/entitystore/leveldb/JavaLevelDBEntityStoreTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2012, Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.leveldb;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class JavaLevelDBEntityStoreTest
-    extends AbstractEntityStoreTest
-{
-
-    @Override
-    // START SNIPPET: assembly
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // END SNIPPET: assembly
-        super.assemble( module );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().visibleIn( Visibility.module ).assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-
-        module.services( FileConfigurationService.class );
-
-        // START SNIPPET: assembly
-        new LevelDBEntityStoreAssembler().
-            withConfig( config, Visibility.layer ).
-            identifiedBy( "java-leveldb-entitystore" ).
-            assemble( module );
-        // END SNIPPET: assembly
-
-        config.forMixin( LevelDBEntityStoreConfiguration.class ).declareDefaults().flavour().set( "java" );
-        // START SNIPPET: assembly
-    }
-    // END SNIPPET: assembly
-}
diff --git a/extensions/entitystore-leveldb/src/test/java/org/qi4j/entitystore/leveldb/JniLevelDBEntityStoreTest.java b/extensions/entitystore-leveldb/src/test/java/org/qi4j/entitystore/leveldb/JniLevelDBEntityStoreTest.java
deleted file mode 100644
index 9356434..0000000
--- a/extensions/entitystore-leveldb/src/test/java/org/qi4j/entitystore/leveldb/JniLevelDBEntityStoreTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2012, Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.leveldb;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class JniLevelDBEntityStoreTest
-    extends AbstractEntityStoreTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().visibleIn( Visibility.module ).assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-
-        module.services( FileConfigurationService.class );
-
-        new LevelDBEntityStoreAssembler().
-            withConfig( config, Visibility.layer ).
-            identifiedBy( "jni-leveldb-entitystore" ).
-            assemble( module );
-
-        config.forMixin( LevelDBEntityStoreConfiguration.class ).declareDefaults().flavour().set( "jni" );
-    }
-}
diff --git a/extensions/entitystore-leveldb/src/test/java/org/qi4j/entitystore/leveldb/LevelDBEntityStoreWithCacheTest.java b/extensions/entitystore-leveldb/src/test/java/org/qi4j/entitystore/leveldb/LevelDBEntityStoreWithCacheTest.java
deleted file mode 100644
index 71b7bdf..0000000
--- a/extensions/entitystore-leveldb/src/test/java/org/qi4j/entitystore/leveldb/LevelDBEntityStoreWithCacheTest.java
+++ /dev/null
@@ -1,46 +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.qi4j.entitystore.leveldb;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.cache.AbstractEntityStoreWithCacheTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class LevelDBEntityStoreWithCacheTest
-    extends AbstractEntityStoreWithCacheTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().visibleIn( Visibility.module ).assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-
-        module.services( FileConfigurationService.class );
-
-        new LevelDBEntityStoreAssembler().
-            withConfig( config, Visibility.layer ).
-            identifiedBy( "java-leveldb-entitystore" ).
-            assemble( module );
-    }
-}
diff --git a/extensions/entitystore-memory/build.gradle b/extensions/entitystore-memory/build.gradle
index 97f1f31..f46ae73 100644
--- a/extensions/entitystore-memory/build.gradle
+++ b/extensions/entitystore-memory/build.gradle
@@ -1,32 +1,33 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-jar { manifest { name = "Apache Zest™ Extension - EntityStore - Memory" }}
+apply plugin: 'polygene-extension'
+
+jar { manifest { name = "Apache Polygene™ Extension - EntityStore - Memory" } }
 
 dependencies {
+  api polygene.core.bootstrap
 
-    compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
+  runtimeOnly polygene.core.runtime
 
-    testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-    testCompile(project(":org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson"))
+  testImplementation polygene.core.testsupport
 
-    testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-    testRuntime(libraries.logback)
-
+  testRuntimeOnly libraries.logback
 }
diff --git a/extensions/entitystore-memory/dev-status.xml b/extensions/entitystore-memory/dev-status.xml
index 73ed2b0..b307e0b 100644
--- a/extensions/entitystore-memory/dev-status.xml
+++ b/extensions/entitystore-memory/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <codebase>stable</codebase>
     <!--none,early,beta,stable,mature-->
diff --git a/extensions/entitystore-memory/src/docs/es-memory.txt b/extensions/entitystore-memory/src/docs/es-memory.txt
index 93da628..f2adf4a 100644
--- a/extensions/entitystore-memory/src/docs/es-memory.txt
+++ b/extensions/entitystore-memory/src/docs/es-memory.txt
@@ -35,7 +35,7 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-memory/src/test/java/org/qi4j/entitystore/memory/MemoryEntityStoreTest.java
+source=extensions/entitystore-memory/src/test/java/org/apache/polygene/entitystore/memory/MemoryEntityStoreTest.java
 tag=assembly
 ----
 
diff --git a/extensions/entitystore-memory/src/main/java/org/apache/polygene/entitystore/memory/assembly/MemoryEntityStoreAssembler.java b/extensions/entitystore-memory/src/main/java/org/apache/polygene/entitystore/memory/assembly/MemoryEntityStoreAssembler.java
new file mode 100644
index 0000000..80cd4c3
--- /dev/null
+++ b/extensions/entitystore-memory/src/main/java/org/apache/polygene/entitystore/memory/assembly/MemoryEntityStoreAssembler.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.entitystore.memory.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+
+/**
+ * Assemble an in-memory EntityStore.
+ */
+public class MemoryEntityStoreAssembler
+    extends Assemblers.VisibilityIdentityConfig<MemoryEntityStoreAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( MemoryEntityStoreService.class ).visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+    }
+}
diff --git a/extensions/entitystore-memory/src/main/java/org/apache/polygene/entitystore/memory/package.html b/extensions/entitystore-memory/src/main/java/org/apache/polygene/entitystore/memory/package.html
new file mode 100644
index 0000000..eb9e94e
--- /dev/null
+++ b/extensions/entitystore-memory/src/main/java/org/apache/polygene/entitystore/memory/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>In-Memory EntityStore.</h2>
+    </body>
+</html>
diff --git a/extensions/entitystore-memory/src/main/java/org/qi4j/entitystore/memory/MemoryEntityStoreAssembler.java b/extensions/entitystore-memory/src/main/java/org/qi4j/entitystore/memory/MemoryEntityStoreAssembler.java
deleted file mode 100644
index 15cfc73..0000000
--- a/extensions/entitystore-memory/src/main/java/org/qi4j/entitystore/memory/MemoryEntityStoreAssembler.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2013 Paul Merlin.
- *
- * Licensed 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.qi4j.entitystore.memory;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-
-/**
- * Assemble an in-memory EntityStore.
- */
-public class MemoryEntityStoreAssembler
-    extends Assemblers.VisibilityIdentity<MemoryEntityStoreAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( UuidIdentityGeneratorService.class ).visibleIn( visibility() );
-        ServiceDeclaration service = module.services( MemoryEntityStoreService.class ).visibleIn( visibility() );
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-    }
-}
diff --git a/extensions/entitystore-memory/src/main/java/org/qi4j/entitystore/memory/package.html b/extensions/entitystore-memory/src/main/java/org/qi4j/entitystore/memory/package.html
deleted file mode 100644
index d907b6c..0000000
--- a/extensions/entitystore-memory/src/main/java/org/qi4j/entitystore/memory/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>In-Memory EntityStore.</h2>
-    </body>
-</html>
diff --git a/extensions/entitystore-memory/src/test/java/org/apache/polygene/entitystore/memory/MemoryEntityStoreTest.java b/extensions/entitystore-memory/src/test/java/org/apache/polygene/entitystore/memory/MemoryEntityStoreTest.java
new file mode 100644
index 0000000..f36cca5
--- /dev/null
+++ b/extensions/entitystore-memory/src/test/java/org/apache/polygene/entitystore/memory/MemoryEntityStoreTest.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.entitystore.memory;
+
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.assembly.MemoryEntityStoreAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+
+public class MemoryEntityStoreTest
+    extends AbstractEntityStoreTest
+{
+    // START SNIPPET: assembly
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        new MemoryEntityStoreAssembler().assemble( module );
+        // END SNIPPET: assembly
+        super.assemble( module );
+        // START SNIPPET: assembly
+    }
+    // END SNIPPET: assembly
+}
diff --git a/extensions/entitystore-memory/src/test/java/org/apache/polygene/entitystore/memory/MemoryEntityStoreWithCacheTest.java b/extensions/entitystore-memory/src/test/java/org/apache/polygene/entitystore/memory/MemoryEntityStoreWithCacheTest.java
new file mode 100644
index 0000000..28dc102
--- /dev/null
+++ b/extensions/entitystore-memory/src/test/java/org/apache/polygene/entitystore/memory/MemoryEntityStoreWithCacheTest.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.entitystore.memory;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.assembly.MemoryEntityStoreAssembler;
+import org.apache.polygene.test.cache.AbstractEntityStoreWithCacheTest;
+
+public class MemoryEntityStoreWithCacheTest
+    extends AbstractEntityStoreWithCacheTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+        new MemoryEntityStoreAssembler().assemble( module );
+    }
+}
diff --git a/extensions/entitystore-memory/src/test/java/org/qi4j/entitystore/memory/MemoryEntityStoreTest.java b/extensions/entitystore-memory/src/test/java/org/qi4j/entitystore/memory/MemoryEntityStoreTest.java
deleted file mode 100644
index 9f99595..0000000
--- a/extensions/entitystore-memory/src/test/java/org/qi4j/entitystore/memory/MemoryEntityStoreTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2013 Paul Merlin.
- *
- * Licensed 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.qi4j.entitystore.memory;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class MemoryEntityStoreTest
-    extends AbstractEntityStoreTest
-{
-
-    // START SNIPPET: assembly
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new MemoryEntityStoreAssembler().assemble( module );
-        // END SNIPPET: assembly
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        super.assemble( module );
-        // START SNIPPET: assembly
-    }
-    // END SNIPPET: assembly
-}
diff --git a/extensions/entitystore-memory/src/test/java/org/qi4j/entitystore/memory/MemoryEntityStoreWithCacheTest.java b/extensions/entitystore-memory/src/test/java/org/qi4j/entitystore/memory/MemoryEntityStoreWithCacheTest.java
deleted file mode 100644
index 3a1c72c..0000000
--- a/extensions/entitystore-memory/src/test/java/org/qi4j/entitystore/memory/MemoryEntityStoreWithCacheTest.java
+++ /dev/null
@@ -1,35 +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.qi4j.entitystore.memory;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.cache.AbstractEntityStoreWithCacheTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class MemoryEntityStoreWithCacheTest
-    extends AbstractEntityStoreWithCacheTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        new MemoryEntityStoreAssembler().assemble( module );
-    }
-}
diff --git a/extensions/entitystore-mongodb/build.gradle b/extensions/entitystore-mongodb/build.gradle
index 9570a1f..8ace38e 100644
--- a/extensions/entitystore-mongodb/build.gradle
+++ b/extensions/entitystore-mongodb/build.gradle
@@ -1,36 +1,39 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ MongoDB EntityStore Extension"
+apply plugin: 'polygene-extension'
 
-jar { manifest { name = "Apache Zest™ Extension - EntityStore - MongoDB" }}
+description = "Apache Polygene™ MongoDB EntityStore Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - EntityStore - MongoDB" } }
 
 dependencies {
+  api polygene.core.bootstrap
+  api libraries.mongodb
 
-    compile project( ":org.qi4j.core:org.qi4j.core.bootstrap" )
-    compile project( ":org.qi4j.libraries:org.qi4j.library.locking" )
-    compile libraries.mongodb
+  implementation polygene.library( 'locking' )
 
-    testCompile project( ":org.qi4j.core:org.qi4j.core.testsupport" )
-    testCompile(project(":org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson"))
+  runtimeOnly polygene.core.runtime
 
-    testRuntime project( ":org.qi4j.core:org.qi4j.core.runtime" )
-    testRuntime libraries.logback
+  testImplementation polygene.core.testsupport
+  testImplementation libraries.embed_mongo
 
+  testRuntimeOnly libraries.logback
 }
diff --git a/extensions/entitystore-mongodb/dev-status.xml b/extensions/entitystore-mongodb/dev-status.xml
index ac63cda..762e250 100644
--- a/extensions/entitystore-mongodb/dev-status.xml
+++ b/extensions/entitystore-mongodb/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
         <!--none,early,beta,stable,mature-->
         <codebase>stable</codebase>
diff --git a/extensions/entitystore-mongodb/src/docs/es-mongodb.txt b/extensions/entitystore-mongodb/src/docs/es-mongodb.txt
index c24746f..658e2a9 100644
--- a/extensions/entitystore-mongodb/src/docs/es-mongodb.txt
+++ b/extensions/entitystore-mongodb/src/docs/es-mongodb.txt
@@ -36,7 +36,7 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-mongodb/src/test/java/org/qi4j/entitystore/mongodb/MongoMapEntityStoreTest.java
+source=extensions/entitystore-mongodb/src/test/java/org/apache/polygene/entitystore/mongodb/MongoMapEntityStoreTest.java
 tag=assembly
 ----
 
@@ -46,6 +46,6 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/MongoEntityStoreConfiguration.java
+source=extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/MongoEntityStoreConfiguration.java
 tag=config
 ----
diff --git a/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/MongoAccessors.java b/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/MongoAccessors.java
new file mode 100644
index 0000000..2d3ddd8
--- /dev/null
+++ b/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/MongoAccessors.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.entitystore.mongodb;
+
+import com.mongodb.MongoClient;
+import com.mongodb.client.MongoDatabase;
+
+public interface MongoAccessors
+{
+    MongoClient mongoInstanceUsed();
+
+    MongoDatabase dbInstanceUsed();
+
+    String collectionUsed();
+}
diff --git a/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/MongoEntityStoreConfiguration.java b/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/MongoEntityStoreConfiguration.java
new file mode 100644
index 0000000..75c95ac
--- /dev/null
+++ b/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/MongoEntityStoreConfiguration.java
@@ -0,0 +1,92 @@
+/*
+ *  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.polygene.entitystore.mongodb;
+
+import java.util.List;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+// START SNIPPET: config
+public interface MongoEntityStoreConfiguration
+{
+
+    @Optional
+    Property<String> hostname();
+
+    @Optional
+    Property<Integer> port();
+
+    @UseDefaults
+    Property<List<String>> nodes();
+
+    @UseDefaults
+    Property<String> username();
+
+    @UseDefaults
+    Property<String> password();
+
+    @Optional
+    Property<String> database();
+
+    @Optional
+    Property<String> collection();
+
+    @UseDefaults
+    Property<WriteConcern> writeConcern();
+
+    enum WriteConcern
+    {
+        /**
+         *  Write operations that use this write concern will wait for acknowledgement,
+         *  using the default write concern configured on the server.
+         *  This is the default value.
+         */
+        ACKNOWLEDGED,
+        /**
+         * Write operations that use this write concern will wait for acknowledgement from a single member.
+         */
+        W1,
+        /**
+         * Write operations that use this write concern will wait for acknowledgement from two members.
+         */
+        W2,
+        /**
+         * Write operations that use this write concern will wait for acknowledgement from three members.
+         */
+        W3,
+        /**
+         * Write operations that use this write concern will return as soon as the message is written to the socket.
+         * Exceptions are raised for network issues, but not server errors.
+         */
+        UNACKNOWLEDGED,
+        /**
+         * Write operations wait for the server to group commit to the journal file on disk.
+         */
+        JOURNALED,
+        /**
+         * Exceptions are raised for network issues, and server errors;
+         * waits on a majority of servers for the write operation.
+         */
+        MAJORITY
+
+    }
+}
+// END SNIPPET: config
\ No newline at end of file
diff --git a/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/MongoMapEntityStoreMixin.java b/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/MongoMapEntityStoreMixin.java
new file mode 100644
index 0000000..3766b82
--- /dev/null
+++ b/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/MongoMapEntityStoreMixin.java
@@ -0,0 +1,322 @@
+/*
+ *  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.polygene.entitystore.mongodb;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.MongoClient;
+import com.mongodb.MongoClientOptions;
+import com.mongodb.MongoCredential;
+import com.mongodb.ServerAddress;
+import com.mongodb.WriteConcern;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoCursor;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.util.JSON;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.spi.entitystore.EntityNotFoundException;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+import org.apache.polygene.spi.entitystore.helpers.MapEntityStore;
+import org.bson.Document;
+import org.bson.conversions.Bson;
+
+import static com.mongodb.client.model.Filters.eq;
+import static java.util.stream.Collectors.toList;
+
+/**
+ * MongoDB implementation of MapEntityStore.
+ */
+public class MongoMapEntityStoreMixin
+    implements ServiceActivation, MapEntityStore, MongoAccessors
+{
+    private static final String DEFAULT_DATABASE_NAME = "polygene:entitystore";
+    private static final String DEFAULT_COLLECTION_NAME = "polygene:entitystore:entities";
+    public static final String IDENTITY_COLUMN = "_id";
+    public static final String STATE_COLUMN = "state";
+    @This
+    private Configuration<MongoEntityStoreConfiguration> configuration;
+    private List<ServerAddress> serverAddresses;
+    private String databaseName;
+    private String collectionName;
+    private WriteConcern writeConcern;
+    private String username;
+    private char[] password;
+    private MongoClient mongo;
+    private MongoDatabase db;
+
+    @Override
+    public void activateService()
+        throws Exception
+    {
+        loadConfiguration();
+
+        // Create Mongo driver and open the database
+        MongoClientOptions options = MongoClientOptions.builder().writeConcern( writeConcern ).build();
+        if( username.isEmpty() )
+        {
+            mongo = new MongoClient( serverAddresses, options );
+        }
+        else
+        {
+            MongoCredential credential = MongoCredential.createMongoCRCredential( username, databaseName, password );
+            mongo = new MongoClient( serverAddresses, Collections.singletonList( credential ), options );
+        }
+        db = mongo.getDatabase( databaseName );
+
+        // Create index if needed
+        MongoCollection<Document> entities = db.getCollection( collectionName );
+        if( !entities.listIndexes().iterator().hasNext() )
+        {
+            entities.createIndex( new BasicDBObject( IDENTITY_COLUMN, 1 ) );
+        }
+    }
+
+    private void loadConfiguration()
+        throws UnknownHostException
+    {
+        configuration.refresh();
+        MongoEntityStoreConfiguration config = configuration.get();
+
+        // Combine hostname, port and nodes configuration properties
+        // If no configuration, use 127.0.0.1:27017
+        serverAddresses = new ArrayList<>();
+        int port = config.port().get() == null ? 27017 : config.port().get();
+        List<String> nodes = config.nodes().get();
+        if( nodes.isEmpty() )
+        {
+            String hostname = config.hostname().get() == null ? "127.0.0.1" : config.hostname().get();
+            serverAddresses.add( new ServerAddress( hostname, port ) );
+        }
+        else
+        {
+            if( config.hostname().get() != null && !config.hostname().get().isEmpty() )
+            {
+                serverAddresses.add( new ServerAddress( config.hostname().get(), port ) );
+            }
+            serverAddresses.addAll( nodes.stream()
+                                         .map( this::parseNode )
+                                         .collect( toList() )
+                                  );
+        }
+
+        // If database name not configured, set it to polygene:entitystore
+        databaseName = config.database().get();
+        if( databaseName == null )
+        {
+            databaseName = DEFAULT_DATABASE_NAME;
+        }
+
+        // If collection name not configured, set it to polygene:entitystore:entities
+        collectionName = config.collection().get();
+        if( collectionName == null )
+        {
+            collectionName = DEFAULT_COLLECTION_NAME;
+        }
+
+        // If write concern not configured, set it to normal
+        switch( config.writeConcern().get() )
+        {
+        case W1:
+            writeConcern = WriteConcern.W1;
+            break;
+        case W2:
+            writeConcern = WriteConcern.W2;
+            break;
+        case W3:
+            writeConcern = WriteConcern.W3;
+            break;
+        case UNACKNOWLEDGED:
+            writeConcern = WriteConcern.UNACKNOWLEDGED;
+            break;
+        case JOURNALED:
+            writeConcern = WriteConcern.JOURNALED;
+            break;
+        case MAJORITY:
+            writeConcern = WriteConcern.MAJORITY;
+            break;
+        case ACKNOWLEDGED:
+        default:
+            writeConcern = WriteConcern.ACKNOWLEDGED;
+        }
+
+        // Username and password are defaulted to empty strings
+        username = config.username().get();
+        password = config.password().get().toCharArray();
+    }
+
+    private <R> ServerAddress parseNode( String nodeString )
+    {
+        String[] parts = nodeString.split( ":" );
+        String host = parts[ 0 ];
+        if( parts.length == 2 )
+        {
+            int port = Integer.parseInt( parts[ 1 ] );
+            return new ServerAddress( host, port );
+        }
+        return new ServerAddress( host );
+    }
+
+    @Override
+    public void passivateService()
+        throws Exception
+    {
+        mongo.close();
+        mongo = null;
+        databaseName = null;
+        collectionName = null;
+        writeConcern = null;
+        username = null;
+        Arrays.fill( password, ' ' );
+        password = null;
+        db = null;
+    }
+
+    @Override
+    public MongoClient mongoInstanceUsed()
+    {
+        return mongo;
+    }
+
+    @Override
+    public MongoDatabase dbInstanceUsed()
+    {
+        return db;
+    }
+
+    @Override
+    public String collectionUsed()
+    {
+        return collectionName;
+    }
+
+    @Override
+    public Reader get( EntityReference entityReference )
+        throws EntityStoreException
+    {
+        MongoCursor<Document> cursor = db.getCollection( collectionName )
+                                         .find( byIdentity( entityReference ) )
+                                         .limit( 1 ).iterator();
+        if( !cursor.hasNext() )
+        {
+            throw new EntityNotFoundException( entityReference );
+        }
+        Document bsonState = (Document) cursor.next().get( STATE_COLUMN );
+        String jsonState = JSON.serialize( bsonState );
+        return new StringReader( jsonState );
+    }
+
+    @Override
+    public void applyChanges( MapChanges changes )
+        throws Exception
+    {
+        final MongoCollection<Document> entities = db.getCollection( collectionName );
+
+        changes.visitMap( new MapChanger()
+        {
+            @Override
+            public Writer newEntity( EntityReference ref, EntityDescriptor entityDescriptor )
+                throws IOException
+            {
+                return new StringWriter( 1000 )
+                {
+                    @Override
+                    public void close()
+                        throws IOException
+                    {
+                        super.close();
+                        Document bsonState = Document.parse( toString() );
+                        Document entity = new Document();
+                        entity.put( IDENTITY_COLUMN, ref.identity().toString() );
+                        entity.put( STATE_COLUMN, bsonState );
+                        entities.insertOne( entity );
+                    }
+                };
+            }
+
+            @Override
+            public Writer updateEntity( MapChange mapChange )
+                throws IOException
+            {
+                return new StringWriter( 1000 )
+                {
+                    @Override
+                    public void close()
+                        throws IOException
+                    {
+                        super.close();
+                        Document bsonState = Document.parse( toString() );
+                        Document entity = new Document();
+                        entity.put( IDENTITY_COLUMN, mapChange.reference().identity().toString() );
+                        entity.put( STATE_COLUMN, bsonState );
+                        entities.replaceOne( byIdentity( mapChange.reference() ), entity );
+                    }
+                };
+            }
+
+            @Override
+            public void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor )
+                throws EntityNotFoundException
+            {
+                Bson byIdFilter = byIdentity( ref );
+                MongoCursor<Document> cursor = db.getCollection( collectionName )
+                                                 .find( byIdFilter )
+                                                 .limit( 1 ).iterator();
+                if( !cursor.hasNext() )
+                {
+                    throw new EntityNotFoundException( ref );
+                }
+                entities.deleteOne( byIdFilter );
+            }
+        } );
+    }
+
+    @Override
+    public Stream<Reader> entityStates()
+    {
+        return StreamSupport
+            .stream( db.getCollection( collectionName ).find().spliterator(), false )
+            .map( eachEntity ->
+                  {
+                      Document bsonState = (Document) eachEntity.get( STATE_COLUMN );
+                      String jsonState = JSON.serialize( bsonState );
+                      return new StringReader( jsonState );
+                  } );
+    }
+
+    private Bson byIdentity( EntityReference entityReference )
+    {
+        return eq( IDENTITY_COLUMN, entityReference.identity().toString() );
+    }
+}
diff --git a/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/MongoMapEntityStoreService.java b/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/MongoMapEntityStoreService.java
new file mode 100644
index 0000000..2145544
--- /dev/null
+++ b/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/MongoMapEntityStoreService.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.entitystore.mongodb;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.library.locking.LockingAbstractComposite;
+import org.apache.polygene.spi.entitystore.ConcurrentModificationCheckConcern;
+import org.apache.polygene.spi.entitystore.EntityStateVersions;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.StateChangeNotificationConcern;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreActivation;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreMixin;
+
+/**
+ * MongoDB EntityStore service.
+ * <p>Based on @{@link JSONMapEntityStoreMixin}.</p>
+ */
+@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
+@Mixins( { JSONMapEntityStoreMixin.class, MongoMapEntityStoreMixin.class } )
+public interface MongoMapEntityStoreService
+    extends EntityStore,
+            EntityStateVersions,
+            ServiceActivation,
+            JSONMapEntityStoreActivation,
+            LockingAbstractComposite,
+            Configuration,
+            MongoAccessors
+{
+}
diff --git a/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/assembly/MongoDBEntityStoreAssembler.java b/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/assembly/MongoDBEntityStoreAssembler.java
new file mode 100644
index 0000000..a270305
--- /dev/null
+++ b/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/assembly/MongoDBEntityStoreAssembler.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.entitystore.mongodb.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.entitystore.mongodb.MongoEntityStoreConfiguration;
+import org.apache.polygene.entitystore.mongodb.MongoMapEntityStoreService;
+
+public class MongoDBEntityStoreAssembler
+    extends Assemblers.VisibilityIdentityConfig<MongoDBEntityStoreAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( MongoMapEntityStoreService.class ).visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+        if( hasConfig() )
+        {
+            configModule().entities( MongoEntityStoreConfiguration.class ).visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/package.html b/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/package.html
new file mode 100644
index 0000000..fd847ef
--- /dev/null
+++ b/extensions/entitystore-mongodb/src/main/java/org/apache/polygene/entitystore/mongodb/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>MongoDB EntityStore.</h2>
+    </body>
+</html>
diff --git a/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/MongoAccessors.java b/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/MongoAccessors.java
deleted file mode 100644
index db8c82b..0000000
--- a/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/MongoAccessors.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2012, Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.mongodb;
-
-import com.mongodb.DB;
-import com.mongodb.MongoClient;
-
-public interface MongoAccessors
-{
-
-    MongoClient mongoInstanceUsed();
-
-    DB dbInstanceUsed();
-
-    String collectionUsed();
-
-}
diff --git a/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/MongoEntityStoreConfiguration.java b/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/MongoEntityStoreConfiguration.java
deleted file mode 100644
index 6b26cab..0000000
--- a/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/MongoEntityStoreConfiguration.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2011 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.mongodb;
-
-import com.mongodb.ServerAddress;
-import java.util.List;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-// START SNIPPET: config
-public interface MongoEntityStoreConfiguration
-    extends ConfigurationComposite
-{
-
-    @Optional
-    Property<String> hostname();
-
-    @Optional
-    Property<Integer> port();
-
-    @UseDefaults
-    Property<List<ServerAddress>> nodes();
-
-    @UseDefaults
-    Property<String> username();
-
-    @UseDefaults
-    Property<String> password();
-
-    @Optional
-    Property<String> database();
-
-    @Optional
-    Property<String> collection();
-
-    @UseDefaults
-    Property<WriteConcern> writeConcern();
-
-    enum WriteConcern
-    {
-
-        /** Exceptions are raised for network issues, but not server errors */
-        NORMAL,
-        /** Exceptions are raised for network issues, and server errors; waits on a server for the write operation */
-        SAFE,
-        /** Exceptions are raised for network issues, and server errors; waits on a majority of servers for the write operation */
-        MAJORITY,
-        /** Exceptions are raised for network issues, and server errors; the write operation waits for the server to flush the data to disk*/
-        FSYNC_SAFE,
-        /** Exceptions are raised for network issues, and server errors; the write operation waits for the server to group commit to the journal file on disk*/
-        JOURNAL_SAFE,
-        /** Exceptions are raised for network issues, and server errors; waits for at least 2 servers for the write operation*/
-        REPLICAS_SAFE;
-
-    }
-
-}
-// END SNIPPET: config
\ No newline at end of file
diff --git a/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/MongoMapEntityStoreAssembler.java b/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/MongoMapEntityStoreAssembler.java
deleted file mode 100644
index ca083e7..0000000
--- a/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/MongoMapEntityStoreAssembler.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2011 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.mongodb;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-
-public class MongoMapEntityStoreAssembler
-    extends Assemblers.VisibilityIdentityConfig<MongoMapEntityStoreAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( UuidIdentityGeneratorService.class ).visibleIn( visibility() );
-        ServiceDeclaration service = module.services( MongoMapEntityStoreService.class ).visibleIn( visibility() );
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        if( hasConfig() )
-        {
-            configModule().entities( MongoEntityStoreConfiguration.class ).visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/MongoMapEntityStoreMixin.java b/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/MongoMapEntityStoreMixin.java
deleted file mode 100644
index 361f953..0000000
--- a/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/MongoMapEntityStoreMixin.java
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright 2011 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.mongodb;
-
-import com.mongodb.BasicDBObject;
-import com.mongodb.DB;
-import com.mongodb.DBCollection;
-import com.mongodb.DBCursor;
-import com.mongodb.DBObject;
-import com.mongodb.MongoClient;
-import com.mongodb.MongoCredential;
-import com.mongodb.ServerAddress;
-import com.mongodb.WriteConcern;
-import com.mongodb.util.JSON;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.spi.entitystore.EntityNotFoundException;
-import org.qi4j.spi.entitystore.EntityStoreException;
-import org.qi4j.spi.entitystore.helpers.MapEntityStore;
-
-/**
- * MongoDB implementation of MapEntityStore.
- */
-public class MongoMapEntityStoreMixin
-    implements ServiceActivation, MapEntityStore, MongoAccessors
-{
-    private static final String DEFAULT_DATABASE_NAME = "qi4j:entitystore";
-    private static final String DEFAULT_COLLECTION_NAME = "qi4j:entitystore:entities";
-    public static final String IDENTITY_COLUMN = "_id";
-    public static final String STATE_COLUMN = "state";
-    @This
-    private Configuration<MongoEntityStoreConfiguration> configuration;
-    private List<ServerAddress> serverAddresses;
-    private String databaseName;
-    private String collectionName;
-    private WriteConcern writeConcern;
-    private String username;
-    private char[] password;
-    private MongoClient mongo;
-    private DB db;
-
-    @Override
-    public void activateService()
-        throws Exception
-    {
-        loadConfiguration();
-
-        // Create Mongo driver and open the database
-        if( username.isEmpty() )
-        {
-            mongo = new MongoClient( serverAddresses );
-        }
-        else
-        {
-            MongoCredential credential = MongoCredential.createMongoCRCredential( username, databaseName, password );
-            mongo = new MongoClient( serverAddresses, Arrays.asList( credential ) );
-        }
-        db = mongo.getDB( databaseName );
-
-        // Create index if needed
-        db.requestStart();
-        DBCollection entities = db.getCollection( collectionName );
-        if( entities.getIndexInfo().isEmpty() )
-        {
-            entities.createIndex( new BasicDBObject( IDENTITY_COLUMN, 1 ) );
-        }
-        db.requestDone();
-    }
-
-    private void loadConfiguration()
-        throws UnknownHostException
-    {
-        configuration.refresh();
-        MongoEntityStoreConfiguration config = configuration.get();
-
-        // Combine hostname, port and nodes configuration properties
-        // If no configuration, use 127.0.0.1:27017
-        serverAddresses = new ArrayList<>();
-        int port = config.port().get() == null ? 27017 : config.port().get();
-        if( config.nodes().get().isEmpty() )
-        {
-            String hostname = config.hostname().get() == null ? "127.0.0.1" : config.hostname().get();
-            serverAddresses.add( new ServerAddress( hostname, port ) );
-        }
-        else
-        {
-            if( config.hostname().get() != null && !config.hostname().get().isEmpty() )
-            {
-                serverAddresses.add( new ServerAddress( config.hostname().get(), port ) );
-            }
-            serverAddresses.addAll( config.nodes().get() );
-        }
-
-        // If database name not configured, set it to qi4j:entitystore
-        databaseName = config.database().get();
-        if( databaseName == null )
-        {
-            databaseName = DEFAULT_DATABASE_NAME;
-        }
-
-        // If collection name not configured, set it to qi4j:entitystore:entities
-        collectionName = config.collection().get();
-        if( collectionName == null )
-        {
-            collectionName = DEFAULT_COLLECTION_NAME;
-        }
-
-        // If write concern not configured, set it to normal
-        switch( config.writeConcern().get() )
-        {
-            case FSYNC_SAFE:
-                writeConcern = WriteConcern.FSYNC_SAFE;
-                break;
-            case JOURNAL_SAFE:
-                writeConcern = WriteConcern.JOURNAL_SAFE;
-                break;
-            case MAJORITY:
-                writeConcern = WriteConcern.MAJORITY;
-                break;
-            case REPLICAS_SAFE:
-                writeConcern = WriteConcern.REPLICAS_SAFE;
-                break;
-            case SAFE:
-                writeConcern = WriteConcern.SAFE;
-                break;
-            case NORMAL:
-            default:
-                writeConcern = WriteConcern.NORMAL;
-        }
-
-        // Username and password are defaulted to empty strings
-        username = config.username().get();
-        password = config.password().get().toCharArray();
-    }
-
-    @Override
-    public void passivateService()
-        throws Exception
-    {
-        mongo.close();
-        mongo = null;
-        databaseName = null;
-        collectionName = null;
-        writeConcern = null;
-        username = null;
-        Arrays.fill( password, ' ' );
-        password = null;
-        db = null;
-    }
-
-    @Override
-    public MongoClient mongoInstanceUsed()
-    {
-        return mongo;
-    }
-
-    @Override
-    public DB dbInstanceUsed()
-    {
-        return db;
-    }
-
-    @Override
-    public String collectionUsed()
-    {
-        return collectionName;
-    }
-
-    @Override
-    public Reader get( EntityReference entityReference )
-        throws EntityStoreException
-    {
-        db.requestStart();
-
-        DBObject entity = db.getCollection( collectionName ).findOne( byIdentity( entityReference ) );
-        if( entity == null )
-        {
-            throw new EntityNotFoundException( entityReference );
-        }
-        DBObject bsonState = (DBObject) entity.get( STATE_COLUMN );
-
-        db.requestDone();
-
-        String jsonState = JSON.serialize( bsonState );
-        return new StringReader( jsonState );
-    }
-
-    @Override
-    public void applyChanges( MapChanges changes )
-        throws IOException
-    {
-        db.requestStart();
-        final DBCollection entities = db.getCollection( collectionName );
-
-        changes.visitMap( new MapChanger()
-        {
-            @Override
-            public Writer newEntity( final EntityReference ref, EntityDescriptor entityDescriptor )
-                throws IOException
-            {
-                return new StringWriter( 1000 )
-                {
-                    @Override
-                    public void close()
-                        throws IOException
-                    {
-                        super.close();
-
-                        String jsonState = toString();
-                        DBObject bsonState = (DBObject) JSON.parse( jsonState );
-
-                        BasicDBObject entity = new BasicDBObject();
-                        entity.put( IDENTITY_COLUMN, ref.identity() );
-                        entity.put( STATE_COLUMN, bsonState );
-                        entities.insert( entity, writeConcern );
-                    }
-                };
-            }
-
-            @Override
-            public Writer updateEntity( final EntityReference ref, EntityDescriptor entityDescriptor )
-                throws IOException
-            {
-                return new StringWriter( 1000 )
-                {
-                    @Override
-                    public void close()
-                        throws IOException
-                    {
-                        super.close();
-
-                        DBObject bsonState = (DBObject) JSON.parse( toString() );
-
-                        BasicDBObject entity = new BasicDBObject();
-                        entity.put( IDENTITY_COLUMN, ref.identity() );
-                        entity.put( STATE_COLUMN, bsonState );
-                        entities.update( byIdentity( ref ), entity, false, false, writeConcern );
-                    }
-                };
-            }
-
-            @Override
-            public void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor )
-                throws EntityNotFoundException
-            {
-                DBObject entity = entities.findOne( byIdentity( ref ) );
-                if( entity == null )
-                {
-                    throw new EntityNotFoundException( ref );
-                }
-                entities.remove( entity, writeConcern );
-            }
-        } );
-
-        db.requestDone();
-    }
-
-    @Override
-    public Input<Reader, IOException> entityStates()
-    {
-        return new Input<Reader, IOException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo(
-                Output<? super Reader, ReceiverThrowableType> output )
-                throws IOException, ReceiverThrowableType
-            {
-                output.receiveFrom( new Sender<Reader, IOException>()
-                {
-                    @Override
-                    public <ReceiverThrowableType extends Throwable> void sendTo(
-                        Receiver<? super Reader, ReceiverThrowableType> receiver )
-                        throws ReceiverThrowableType, IOException
-                    {
-                        db.requestStart();
-
-                        DBCursor cursor = db.getCollection( collectionName ).find();
-                        while( cursor.hasNext() )
-                        {
-                            DBObject eachEntity = cursor.next();
-                            DBObject bsonState = (DBObject) eachEntity.get( STATE_COLUMN );
-                            String jsonState = JSON.serialize( bsonState );
-                            receiver.receive( new StringReader( jsonState ) );
-                        }
-
-                        db.requestDone();
-                    }
-                } );
-            }
-        };
-    }
-
-    private DBObject byIdentity( EntityReference entityReference )
-    {
-        return new BasicDBObject( IDENTITY_COLUMN, entityReference.identity() );
-    }
-}
diff --git a/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/MongoMapEntityStoreService.java b/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/MongoMapEntityStoreService.java
deleted file mode 100644
index d3fcda5..0000000
--- a/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/MongoMapEntityStoreService.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2011 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.mongodb;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.library.locking.LockingAbstractComposite;
-import org.qi4j.spi.entitystore.ConcurrentModificationCheckConcern;
-import org.qi4j.spi.entitystore.EntityStateVersions;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.StateChangeNotificationConcern;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreActivation;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreMixin;
-
-/**
- * MongoDB EntityStore service.
- * <p>Based on @{@link JSONMapEntityStoreMixin}.</p>
- */
-@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
-@Mixins( { JSONMapEntityStoreMixin.class, MongoMapEntityStoreMixin.class } )
-public interface MongoMapEntityStoreService
-    extends EntityStore,
-            EntityStateVersions,
-            ServiceComposite,
-            ServiceActivation,
-            JSONMapEntityStoreActivation,
-            LockingAbstractComposite,
-            Configuration,
-            MongoAccessors
-{
-}
diff --git a/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/package.html b/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/package.html
deleted file mode 100644
index 0e9cc54..0000000
--- a/extensions/entitystore-mongodb/src/main/java/org/qi4j/entitystore/mongodb/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>MongoDB EntityStore.</h2>
-    </body>
-</html>
diff --git a/extensions/entitystore-mongodb/src/test/java/org/apache/polygene/entitystore/mongodb/EmbedMongoMapEntityStoreTest.java b/extensions/entitystore-mongodb/src/test/java/org/apache/polygene/entitystore/mongodb/EmbedMongoMapEntityStoreTest.java
new file mode 100644
index 0000000..5a65389
--- /dev/null
+++ b/extensions/entitystore-mongodb/src/test/java/org/apache/polygene/entitystore/mongodb/EmbedMongoMapEntityStoreTest.java
@@ -0,0 +1,88 @@
+/*
+ *  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.polygene.entitystore.mongodb;
+
+import de.flapdoodle.embed.mongo.MongodExecutable;
+import de.flapdoodle.embed.mongo.MongodStarter;
+import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
+import de.flapdoodle.embed.mongo.config.Net;
+import de.flapdoodle.embed.mongo.distribution.Version;
+import de.flapdoodle.embed.process.runtime.Network;
+import java.io.IOException;
+import java.util.Collections;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.mongodb.assembly.MongoDBEntityStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+import org.apache.polygene.test.util.FreePortFinder;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.rules.TestName;
+
+public class EmbedMongoMapEntityStoreTest extends AbstractEntityStoreTest
+{
+    private static final MongodStarter MONGO_STARTER = MongodStarter.getDefaultInstance();
+
+    @Rule
+    public TestName testName = new TestName();
+    private static int port;
+    private static MongodExecutable mongod;
+
+    @BeforeClass
+    public static void startEmbedMongo()
+        throws IOException
+    {
+        port = FreePortFinder.findFreePortOnLoopback();
+        mongod = MONGO_STARTER.prepare( new MongodConfigBuilder()
+                                            .version( Version.Main.PRODUCTION )
+                                            .net( new Net( "localhost", port, Network.localhostIsIPv6() ) )
+                                            .build() );
+        mongod.start();
+    }
+
+    @AfterClass
+    public static void stopEmbedMongo()
+    {
+        if( mongod != null )
+        {
+            mongod.stop();
+        }
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+
+        new MongoDBEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+
+        MongoEntityStoreConfiguration mongoConfig = config.forMixin( MongoEntityStoreConfiguration.class )
+                                                          .declareDefaults();
+        mongoConfig.writeConcern().set( MongoEntityStoreConfiguration.WriteConcern.MAJORITY );
+        mongoConfig.database().set( "polygene-test" );
+        mongoConfig.collection().set( testName.getMethodName() );
+        mongoConfig.nodes().set( Collections.singletonList( "localhost:" + port ) );
+    }
+}
diff --git a/extensions/entitystore-mongodb/src/test/java/org/apache/polygene/entitystore/mongodb/MongoMapEntityStoreTest.java b/extensions/entitystore-mongodb/src/test/java/org/apache/polygene/entitystore/mongodb/MongoMapEntityStoreTest.java
new file mode 100644
index 0000000..9c48fe5
--- /dev/null
+++ b/extensions/entitystore-mongodb/src/test/java/org/apache/polygene/entitystore/mongodb/MongoMapEntityStoreTest.java
@@ -0,0 +1,88 @@
+/*
+ *  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.polygene.entitystore.mongodb;
+
+import com.mongodb.Mongo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.mongodb.assembly.MongoDBEntityStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+import org.junit.BeforeClass;
+
+import static org.apache.polygene.test.util.Assume.assumeConnectivity;
+
+/**
+ * Test the MongoMapEntityStoreService.
+ * <p>Installing mongodb and starting it should suffice as the test use mongodb defaults: 127.0.0.1:27017</p>
+ */
+public class MongoMapEntityStoreTest extends AbstractEntityStoreTest
+{
+    @BeforeClass
+    public static void beforeRedisMapEntityStoreTests()
+    {
+        assumeConnectivity( "localhost", 27017 );
+    }
+
+    @Override
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // END SNIPPET: assembly
+        super.assemble( module );
+
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+
+        // START SNIPPET: assembly
+        new MongoDBEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+        // END SNIPPET: assembly
+
+        MongoEntityStoreConfiguration mongoConfig = config.forMixin( MongoEntityStoreConfiguration.class ).declareDefaults();
+        mongoConfig.writeConcern().set( MongoEntityStoreConfiguration.WriteConcern.MAJORITY );
+        mongoConfig.database().set( "polygene:test" );
+        mongoConfig.collection().set( "polygene:test:entities" );
+        // START SNIPPET: assembly
+    }
+
+    // END SNIPPET: assembly
+    private Mongo mongo;
+    private String dbName;
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        MongoMapEntityStoreService es = serviceFinder.findService( MongoMapEntityStoreService.class ).get();
+        mongo = es.mongoInstanceUsed();
+        dbName = es.dbInstanceUsed().getName();
+    }
+
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        mongo.dropDatabase( dbName );
+        super.tearDown();
+    }
+}
diff --git a/extensions/entitystore-mongodb/src/test/java/org/apache/polygene/entitystore/mongodb/MongoMapEntityStoreWithCacheTest.java b/extensions/entitystore-mongodb/src/test/java/org/apache/polygene/entitystore/mongodb/MongoMapEntityStoreWithCacheTest.java
new file mode 100644
index 0000000..cad95ea
--- /dev/null
+++ b/extensions/entitystore-mongodb/src/test/java/org/apache/polygene/entitystore/mongodb/MongoMapEntityStoreWithCacheTest.java
@@ -0,0 +1,84 @@
+/*
+ *  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.polygene.entitystore.mongodb;
+
+import com.mongodb.Mongo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.mongodb.assembly.MongoDBEntityStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.cache.AbstractEntityStoreWithCacheTest;
+import org.junit.BeforeClass;
+
+import static org.apache.polygene.test.util.Assume.assumeConnectivity;
+
+/**
+ * Test the MongoMapEntityStoreService usage with a CachePool.
+ * <p>Installing mongodb and starting it should suffice as the test use mongodb defaults: 127.0.0.1:27017</p>
+ */
+public class MongoMapEntityStoreWithCacheTest
+    extends AbstractEntityStoreWithCacheTest
+{
+    @BeforeClass
+    public static void beforeRedisMapEntityStoreTests()
+    {
+        assumeConnectivity( "localhost", 27017 );
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+
+        new MongoDBEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+
+        MongoEntityStoreConfiguration mongoConfig = config.forMixin( MongoEntityStoreConfiguration.class ).declareDefaults();
+        mongoConfig.writeConcern().set( MongoEntityStoreConfiguration.WriteConcern.MAJORITY );
+        mongoConfig.database().set( "polygene:test" );
+        mongoConfig.collection().set( "polygene:test:entities" );
+    }
+
+    private Mongo mongo;
+    private String dbName;
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        MongoMapEntityStoreService es = serviceFinder.findService( MongoMapEntityStoreService.class ).get();
+        mongo = es.mongoInstanceUsed();
+        dbName = es.dbInstanceUsed().getName();
+
+    }
+
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        mongo.dropDatabase( dbName );
+        super.tearDown();
+    }
+}
diff --git a/extensions/entitystore-mongodb/src/test/java/org/qi4j/entitystore/mongodb/MongoMapEntityStoreTest.java b/extensions/entitystore-mongodb/src/test/java/org/qi4j/entitystore/mongodb/MongoMapEntityStoreTest.java
deleted file mode 100644
index af2723c..0000000
--- a/extensions/entitystore-mongodb/src/test/java/org/qi4j/entitystore/mongodb/MongoMapEntityStoreTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2011 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.mongodb;
-
-import com.mongodb.Mongo;
-import org.junit.BeforeClass;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-import static org.qi4j.test.util.Assume.assumeConnectivity;
-
-/**
- * Test the MongoMapEntityStoreService.
- * <p>Installing mongodb and starting it should suffice as the test use mongodb defaults: 127.0.0.1:27017</p>
- */
-public class MongoMapEntityStoreTest
-    extends AbstractEntityStoreTest
-{
-    @BeforeClass
-    public static void beforeRedisMapEntityStoreTests()
-    {
-        assumeConnectivity( "localhost", 27017 );
-    }
-
-    @Override
-    // START SNIPPET: assembly
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // END SNIPPET: assembly
-        super.assemble( module );
-
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-
-        new OrgJsonValueSerializationAssembler().assemble( module );
-
-        // START SNIPPET: assembly
-        new MongoMapEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
-        // END SNIPPET: assembly
-
-        MongoEntityStoreConfiguration mongoConfig = config.forMixin( MongoEntityStoreConfiguration.class ).declareDefaults();
-        mongoConfig.writeConcern().set( MongoEntityStoreConfiguration.WriteConcern.FSYNC_SAFE );
-        mongoConfig.database().set( "qi4j:test" );
-        mongoConfig.collection().set( "qi4j:test:entities" );
-        // START SNIPPET: assembly
-    }
-    // END SNIPPET: assembly
-    private Mongo mongo;
-    private String dbName;
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        MongoMapEntityStoreService es = module.findService( MongoMapEntityStoreService.class ).get();
-        mongo = es.mongoInstanceUsed();
-        dbName = es.dbInstanceUsed().getName();
-
-    }
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        mongo.dropDatabase( dbName );
-        super.tearDown();
-    }
-}
diff --git a/extensions/entitystore-mongodb/src/test/java/org/qi4j/entitystore/mongodb/MongoMapEntityStoreWithCacheTest.java b/extensions/entitystore-mongodb/src/test/java/org/qi4j/entitystore/mongodb/MongoMapEntityStoreWithCacheTest.java
deleted file mode 100644
index 7daec24..0000000
--- a/extensions/entitystore-mongodb/src/test/java/org/qi4j/entitystore/mongodb/MongoMapEntityStoreWithCacheTest.java
+++ /dev/null
@@ -1,83 +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.qi4j.entitystore.mongodb;
-
-import com.mongodb.Mongo;
-import org.junit.BeforeClass;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.cache.AbstractEntityStoreWithCacheTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-import static org.qi4j.test.util.Assume.assumeConnectivity;
-
-/**
- * Test the MongoMapEntityStoreService usage with a CachePool.
- * <p>Installing mongodb and starting it should suffice as the test use mongodb defaults: 127.0.0.1:27017</p>
- */
-public class MongoMapEntityStoreWithCacheTest
-    extends AbstractEntityStoreWithCacheTest
-{
-    @BeforeClass
-    public static void beforeRedisMapEntityStoreTests()
-    {
-        assumeConnectivity( "localhost", 27017 );
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-
-        new OrgJsonValueSerializationAssembler().assemble( module );
-
-        new MongoMapEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
-
-        MongoEntityStoreConfiguration mongoConfig = config.forMixin( MongoEntityStoreConfiguration.class ).declareDefaults();
-        mongoConfig.writeConcern().set( MongoEntityStoreConfiguration.WriteConcern.FSYNC_SAFE );
-        mongoConfig.database().set( "qi4j:test" );
-        mongoConfig.collection().set( "qi4j:test:entities" );
-    }
-
-    private Mongo mongo;
-    private String dbName;
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        MongoMapEntityStoreService es = module.findService( MongoMapEntityStoreService.class ).get();
-        mongo = es.mongoInstanceUsed();
-        dbName = es.dbInstanceUsed().getName();
-
-    }
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        mongo.dropDatabase( dbName );
-        super.tearDown();
-    }
-}
diff --git a/extensions/entitystore-preferences/build.gradle b/extensions/entitystore-preferences/build.gradle
index 5d52095..f875219 100644
--- a/extensions/entitystore-preferences/build.gradle
+++ b/extensions/entitystore-preferences/build.gradle
@@ -1,35 +1,35 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Preferences EntityStore Extension"
+apply plugin: 'polygene-extension'
 
-jar { manifest { name = "Apache Zest™ Extension - EntityStore - Preferences" } }
+description = "Apache Polygene™ Preferences EntityStore Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - EntityStore - Preferences" } }
 
 dependencies {
+  api polygene.core.bootstrap
 
-  compile( project( ":org.qi4j.core:org.qi4j.core.bootstrap" ) )
-  compile libraries.slf4j_api
+  runtimeOnly polygene.core.runtime
 
-  testCompile( project( ":org.qi4j.core:org.qi4j.core.testsupport" ) )
-  testCompile( project( ":org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson" ) )
+  testImplementation polygene.core.testsupport
 
-  testRuntime( project( ":org.qi4j.core:org.qi4j.core.runtime" ) )
-  testRuntime( libraries.logback )
+  testRuntimeOnly libraries.logback
 }
-
diff --git a/extensions/entitystore-preferences/dev-status.xml b/extensions/entitystore-preferences/dev-status.xml
index ac63cda..762e250 100644
--- a/extensions/entitystore-preferences/dev-status.xml
+++ b/extensions/entitystore-preferences/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
         <!--none,early,beta,stable,mature-->
         <codebase>stable</codebase>
diff --git a/extensions/entitystore-preferences/src/docs/es-preferences.txt b/extensions/entitystore-preferences/src/docs/es-preferences.txt
index 5727b5f..e93e26d 100644
--- a/extensions/entitystore-preferences/src/docs/es-preferences.txt
+++ b/extensions/entitystore-preferences/src/docs/es-preferences.txt
@@ -37,6 +37,6 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-preferences/src/test/java/org/qi4j/entitystore/DocumentationSupport.java
+source=extensions/entitystore-preferences/src/test/java/org/apache/polygene/entitystore/DocumentationSupport.java
 tag=assembly
 ----
diff --git a/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/ListPreferencesNodes.java b/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/ListPreferencesNodes.java
new file mode 100644
index 0000000..ad30f02
--- /dev/null
+++ b/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/ListPreferencesNodes.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.entitystore.preferences;
+
+import java.util.prefs.BackingStoreException;
+import java.util.prefs.Preferences;
+
+public class ListPreferencesNodes
+{
+    public static void main( String[] args )
+        throws Exception
+    {
+        Preferences preferences = Preferences.userRoot();
+        printNode( preferences, "" );
+    }
+
+    private static void printNode( Preferences node, String indent )
+        throws BackingStoreException
+    {
+        System.out.print( indent );
+        String name = node.name();
+        if( "".equals( name ) )
+        {
+            name = "/";
+        }
+
+        System.out.print( name );
+        String[] nodes = node.keys();
+        if( nodes.length > 0 )
+        {
+            System.out.print( "  { " );
+            boolean first = true;
+            for( String key : nodes )
+            {
+                if( !first )
+                {
+                    System.out.print( ", " );
+                }
+                first = false;
+                System.out.print( key );
+            }
+            System.out.print( " }" );
+        }
+        System.out.println();
+        for( String childName : node.childrenNames() )
+        {
+            Preferences child = node.node( childName );
+            printNode( child, indent + "  " );
+        }
+    }
+}
diff --git a/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/PreferencesEntityStoreInfo.java b/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/PreferencesEntityStoreInfo.java
new file mode 100644
index 0000000..f1ca941
--- /dev/null
+++ b/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/PreferencesEntityStoreInfo.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.entitystore.preferences;
+
+import java.util.prefs.Preferences;
+
+/**
+ * @author edward.yakop@gmail.com
+ */
+public final class PreferencesEntityStoreInfo
+{
+    private Preferences rootNode;
+
+    public PreferencesEntityStoreInfo( Preferences aRootNode )
+    {
+        rootNode = aRootNode;
+    }
+
+    /**
+     * @return root preference node to use.
+     */
+    public Preferences rootNode()
+    {
+        return rootNode;
+    }
+}
\ No newline at end of file
diff --git a/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/PreferencesEntityStoreMixin.java b/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/PreferencesEntityStoreMixin.java
new file mode 100644
index 0000000..7958840
--- /dev/null
+++ b/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/PreferencesEntityStoreMixin.java
@@ -0,0 +1,650 @@
+/*
+ *  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.polygene.entitystore.preferences;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.prefs.BackingStoreException;
+import java.util.prefs.Preferences;
+import java.util.stream.Stream;
+import org.apache.polygene.api.cache.CacheOptions;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.IdentityGenerator;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.time.SystemTime;
+import org.apache.polygene.api.type.CollectionType;
+import org.apache.polygene.api.type.EnumType;
+import org.apache.polygene.api.type.MapType;
+import org.apache.polygene.api.type.ValueCompositeType;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.entitystore.DefaultEntityStoreUnitOfWork;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+import org.apache.polygene.spi.entitystore.EntityStoreSPI;
+import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork;
+import org.apache.polygene.spi.entitystore.StateCommitter;
+import org.apache.polygene.spi.entitystore.helpers.DefaultEntityState;
+
+/**
+ * Implementation of EntityStore that is backed by the Preferences API.
+ *
+ * <p>@see Preferences</p>
+ * <p>
+ * Associations are stored as the reference of the referenced Entity, ManyAssociations are stored as multi-line strings
+ * (one reference per line), and NamedAssociations are stored as multi-line strings (one name on a line, reference on the
+ * next line).
+ * </p>
+ * <p>Nested ValuesComposites, Collections and Maps are stored using available StateSerialization service.</p>
+ */
+public class PreferencesEntityStoreMixin
+    implements ServiceActivation, EntityStore, EntityStoreSPI
+{
+    @Structure
+    private PolygeneSPI spi;
+
+    @This
+    private EntityStoreSPI entityStoreSpi;
+
+    @Uses
+    private ServiceDescriptor descriptor;
+
+    @Structure
+    private Application application;
+
+    @Service
+    private Serialization serialization;
+
+    private Preferences root;
+
+    public ScheduledThreadPoolExecutor reloadExecutor;
+
+    @Service
+    private IdentityGenerator identityGenerator;
+
+    @Override
+    public void activateService()
+        throws Exception
+    {
+        root = getApplicationRoot();
+
+        // Reload underlying store every 60 seconds
+        reloadExecutor = new ScheduledThreadPoolExecutor( 1 );
+        reloadExecutor.setExecuteExistingDelayedTasksAfterShutdownPolicy( false );
+        reloadExecutor.scheduleAtFixedRate( () -> {
+            try
+            {
+                //noinspection SynchronizeOnNonFinalField
+                synchronized( root )
+                {
+                    root.sync();
+                }
+            }
+            catch( BackingStoreException e )
+            {
+                throw new EntityStoreException( "Could not reload preferences", e );
+            }
+        }, 0, 60, TimeUnit.SECONDS );
+    }
+
+    private Preferences getApplicationRoot()
+    {
+        PreferencesEntityStoreInfo storeInfo = descriptor.metaInfo( PreferencesEntityStoreInfo.class );
+
+        Preferences preferences;
+        if( storeInfo == null )
+        {
+            // Default to use system root + application name
+            preferences = Preferences.systemRoot();
+            String name = application.name();
+            preferences = preferences.node( name );
+        }
+        else
+        {
+            preferences = storeInfo.rootNode();
+        }
+
+        return preferences;
+    }
+
+    @Override
+    public void passivateService()
+        throws Exception
+    {
+        reloadExecutor.shutdown();
+        reloadExecutor.awaitTermination( 10, TimeUnit.SECONDS );
+    }
+
+    @Override
+    public EntityStoreUnitOfWork newUnitOfWork( ModuleDescriptor module, Usecase usecase, Instant currentTime )
+    {
+        return new DefaultEntityStoreUnitOfWork( module, entityStoreSpi, newUnitOfWorkId(), usecase, currentTime );
+    }
+
+    @Override
+    public Stream<EntityState> entityStates( final ModuleDescriptor module )
+    {
+        UsecaseBuilder builder = UsecaseBuilder.buildUsecase( "polygene.entitystore.preferences.visit" );
+        Usecase visitUsecase = builder.withMetaInfo( CacheOptions.NEVER ).newUsecase();
+        EntityStoreUnitOfWork uow = newUnitOfWork( module, visitUsecase, SystemTime.now() );
+
+        try
+        {
+            return Stream.of( root.childrenNames() )
+                         .map( EntityReference::parseEntityReference )
+                         .map( ref -> uow.entityStateOf( module, ref ) )
+                         .onClose( uow::discard );
+        }
+        catch( BackingStoreException e )
+        {
+            throw new EntityStoreException( e );
+        }
+    }
+
+    @Override
+    public EntityState newEntityState( EntityStoreUnitOfWork unitOfWork,
+                                       EntityReference reference,
+                                       EntityDescriptor entityDescriptor
+    )
+    {
+        return new DefaultEntityState( unitOfWork.currentTime(), reference, entityDescriptor );
+    }
+
+    @Override
+    public EntityState entityStateOf( EntityStoreUnitOfWork unitOfWork,
+                                      ModuleDescriptor module,
+                                      EntityReference reference
+    )
+    {
+        try
+        {
+            if( !root.nodeExists( reference.identity().toString() ) )
+            {
+                throw new NoSuchEntityException( reference, UnknownType.class, unitOfWork.usecase() );
+            }
+
+            Preferences entityPrefs = root.node( reference.identity().toString() );
+
+            String type = entityPrefs.get( "type", null );
+            EntityStatus status = EntityStatus.LOADED;
+
+            EntityDescriptor entityDescriptor = module.entityDescriptor( type );
+            if( entityDescriptor == null )
+            {
+                throw new NoSuchEntityTypeException( type, module.name(), module.typeLookup() );
+            }
+
+            Map<QualifiedName, Object> properties = new HashMap<>();
+            final Preferences propsPrefs = entityPrefs.node( "properties" );
+            entityDescriptor.state().properties().forEach(
+                persistentPropertyDescriptor ->
+                {
+                    if( persistentPropertyDescriptor.qualifiedName().name().equals( "reference" ) )
+                    {
+                        // Fake reference property
+                        properties.put( persistentPropertyDescriptor.qualifiedName(), reference.identity().toString() );
+                    }
+                    else
+                    {
+                        ValueType propertyType = persistentPropertyDescriptor.valueType();
+                        Class<?> primaryType = propertyType.primaryType();
+                        if( Number.class.isAssignableFrom( primaryType ) )
+                        {
+                            if( primaryType.equals( Long.class ) )
+                            {
+                                properties.put( persistentPropertyDescriptor.qualifiedName(),
+                                                this.getNumber( propsPrefs, module, persistentPropertyDescriptor, LONG_PARSER ) );
+                            }
+                            else if( primaryType.equals( Integer.class ) )
+                            {
+                                properties.put( persistentPropertyDescriptor.qualifiedName(),
+                                                this.getNumber( propsPrefs, module, persistentPropertyDescriptor, INT_PARSER ) );
+                            }
+                            else if( primaryType.equals( Double.class ) )
+                            {
+                                properties.put( persistentPropertyDescriptor.qualifiedName(),
+                                                this.getNumber( propsPrefs, module, persistentPropertyDescriptor, DOUBLE_PARSER ) );
+                            }
+                            else if( primaryType.equals( Float.class ) )
+                            {
+                                properties.put( persistentPropertyDescriptor.qualifiedName(),
+                                                this.getNumber( propsPrefs, module, persistentPropertyDescriptor, FLOAT_PARSER ) );
+                            }
+                            else
+                            {
+                                // Load as string even though it's a number
+                                String string = propsPrefs.get( persistentPropertyDescriptor.qualifiedName()
+                                                                                            .name(), null );
+                                Object value;
+                                if( string == null )
+                                {
+                                    value = null;
+                                }
+                                else
+                                {
+                                    value = serialization.deserialize( module, propertyType, string );
+                                }
+                                properties.put( persistentPropertyDescriptor.qualifiedName(), value );
+                            }
+                        }
+                        else if( primaryType.equals( Boolean.class ) )
+                        {
+                            Boolean initialValue = (Boolean) persistentPropertyDescriptor.resolveInitialValue(module);
+                            properties.put( persistentPropertyDescriptor.qualifiedName(),
+                                            propsPrefs.getBoolean( persistentPropertyDescriptor.qualifiedName().name(),
+                                                                   initialValue == null ? false : initialValue ) );
+                        }
+                        else if( propertyType instanceof ValueCompositeType
+                                 || propertyType instanceof MapType
+                                 || propertyType instanceof CollectionType
+                                 || propertyType instanceof EnumType )
+                        {
+                            String string = propsPrefs.get( persistentPropertyDescriptor.qualifiedName().name(), null );
+                            Object value;
+                            if( string == null )
+                            {
+                                value = null;
+                            }
+                            else
+                            {
+                                value = serialization.deserialize( module, propertyType, string );
+                            }
+                            properties.put( persistentPropertyDescriptor.qualifiedName(), value );
+                        }
+                        else
+                        {
+                            String string = propsPrefs.get( persistentPropertyDescriptor.qualifiedName().name(), null );
+                            if( string == null )
+                            {
+                                if( persistentPropertyDescriptor.resolveInitialValue( module ) != null )
+                                {
+                                    properties.put( persistentPropertyDescriptor.qualifiedName(),
+                                                    persistentPropertyDescriptor.resolveInitialValue( module ) );
+                                }
+                                else
+                                {
+                                    properties.put( persistentPropertyDescriptor.qualifiedName(), null );
+                                }
+                            }
+                            else
+                            {
+                                Object value = serialization.deserialize( module, propertyType, string );
+                                properties.put( persistentPropertyDescriptor.qualifiedName(), value );
+                            }
+                        }
+                    }
+                } );
+
+            // Associations
+            Map<QualifiedName, EntityReference> associations = new HashMap<>();
+            final Preferences assocs = entityPrefs.node( "associations" );
+            entityDescriptor.state().associations().forEach( associationType -> {
+                String associatedEntity = assocs.get( associationType.qualifiedName().name(), null );
+                EntityReference value = associatedEntity == null
+                                        ? null
+                                        : EntityReference.parseEntityReference( associatedEntity );
+                associations.put( associationType.qualifiedName(), value );
+            } );
+
+            // ManyAssociations
+            Map<QualifiedName, List<EntityReference>> manyAssociations = new HashMap<>();
+            Preferences manyAssocs = entityPrefs.node( "manyassociations" );
+            entityDescriptor.state().manyAssociations().forEach( manyAssociationType -> {
+                List<EntityReference> references = new ArrayList<>();
+                String entityReferences = manyAssocs.get( manyAssociationType
+                                                              .qualifiedName()
+                                                              .name(), null );
+                if( entityReferences == null )
+                {
+                    // ManyAssociation not found, default to empty one
+                    manyAssociations.put( manyAssociationType.qualifiedName(), references );
+                }
+                else
+                {
+                    String[] refs = entityReferences.split( "\n" );
+                    for( String ref : refs )
+                    {
+                        EntityReference value = ref == null
+                                                ? null
+                                                : EntityReference.parseEntityReference( ref );
+                        references.add( value );
+                    }
+                    manyAssociations.put( manyAssociationType.qualifiedName(), references );
+                }
+            } );
+
+            // NamedAssociations
+            Map<QualifiedName, Map<String, EntityReference>> namedAssociations = new HashMap<>();
+            Preferences namedAssocs = entityPrefs.node( "namedassociations" );
+            entityDescriptor.state().namedAssociations().forEach( namedAssociationType -> {
+                Map<String, EntityReference> references = new LinkedHashMap<>();
+                String entityReferences = namedAssocs.get( namedAssociationType.qualifiedName().name(), null );
+                if( entityReferences == null )
+                {
+                    // NamedAssociation not found, default to empty one
+                    namedAssociations.put( namedAssociationType.qualifiedName(), references );
+                }
+                else
+                {
+                    String[] namedRefs = entityReferences.split( "\n" );
+                    if( namedRefs.length % 2 != 0 )
+                    {
+                        throw new EntityStoreException( "Invalid NamedAssociation storage format" );
+                    }
+                    for( int idx = 0; idx < namedRefs.length; idx += 2 )
+                    {
+                        String name = namedRefs[ idx ];
+                        String ref = namedRefs[ idx + 1 ];
+                        references.put( name, EntityReference.parseEntityReference( ref ) );
+                    }
+                    namedAssociations.put( namedAssociationType.qualifiedName(), references );
+                }
+            } );
+
+            return new DefaultEntityState( entityPrefs.get( "version", "" ),
+                                           Instant.ofEpochMilli(entityPrefs.getLong( "modified", unitOfWork.currentTime().toEpochMilli() )),
+                                           reference,
+                                           status,
+                                           entityDescriptor,
+                                           properties,
+                                           associations,
+                                           manyAssociations,
+                                           namedAssociations
+            );
+        }
+        catch( SerializationException | BackingStoreException e )
+        {
+            throw new EntityStoreException( e );
+        }
+    }
+
+    @Override
+    public String versionOf( EntityStoreUnitOfWork unitOfWork, EntityReference reference )
+    {
+        try
+        {
+            if( !root.nodeExists( reference.identity().toString() ) )
+            {
+                throw new NoSuchEntityException( reference, UnknownType.class, unitOfWork.usecase() );
+            }
+
+            Preferences entityPrefs = root.node( reference.identity().toString() );
+            return entityPrefs.get( "version", "" );
+        }
+        catch( BackingStoreException e )
+        {
+            throw new EntityStoreException( e );
+        }
+    }
+
+    @Override
+    public StateCommitter applyChanges( final EntityStoreUnitOfWork unitofwork, final Iterable<EntityState> state )
+    {
+        return new StateCommitter()
+        {
+            @SuppressWarnings( "SynchronizeOnNonFinalField" )
+            @Override
+            public void commit()
+            {
+                try
+                {
+                    synchronized( root )
+                    {
+                        for( EntityState entityState : state )
+                        {
+                            DefaultEntityState state = (DefaultEntityState) entityState;
+                            if( state.status().equals( EntityStatus.NEW ) )
+                            {
+                                Preferences entityPrefs = root.node( state.entityReference().identity().toString() );
+                                writeEntityState( state, entityPrefs, unitofwork.identity(), unitofwork.currentTime() );
+                            }
+                            else if( state.status().equals( EntityStatus.UPDATED ) )
+                            {
+                                Preferences entityPrefs = root.node( state.entityReference().identity().toString() );
+                                writeEntityState( state, entityPrefs, unitofwork.identity(), unitofwork.currentTime() );
+                            }
+                            else if( state.status().equals( EntityStatus.REMOVED ) )
+                            {
+                                root.node( state.entityReference().identity().toString() ).removeNode();
+                            }
+                        }
+                        root.flush();
+                    }
+                }
+                catch( BackingStoreException e )
+                {
+                    throw new EntityStoreException( e );
+                }
+            }
+
+            @Override
+            public void cancel()
+            {
+            }
+        };
+    }
+
+    protected void writeEntityState( DefaultEntityState state,
+                                     Preferences entityPrefs,
+                                     Identity identity,
+                                     Instant lastModified
+    )
+        throws EntityStoreException
+    {
+        try
+        {
+            // Store into Preferences API
+            entityPrefs.put( "type", state.entityDescriptor().types().findFirst().get().getName() );
+            entityPrefs.put( "version", identity.toString() );
+            entityPrefs.putLong( "modified", lastModified.toEpochMilli() );
+
+            // Properties
+            Preferences propsPrefs = entityPrefs.node( "properties" );
+            state.entityDescriptor().state().properties()
+                .filter( property -> !property.qualifiedName().name().equals( "reference" ) )
+                .forEach( persistentProperty ->
+                          {
+                              Object value = state.properties().get( persistentProperty.qualifiedName() );
+
+                              if( value == null )
+                              {
+                                  propsPrefs.remove( persistentProperty.qualifiedName().name() );
+                              }
+                              else
+                              {
+                                  ValueType valueType = persistentProperty.valueType();
+                                  Class<?> primaryType = valueType.primaryType();
+                                  if( Number.class.isAssignableFrom( primaryType ) )
+                                  {
+                                      if( primaryType.equals( Long.class ) )
+                                      {
+                                          propsPrefs.putLong( persistentProperty.qualifiedName().name(), (Long) value );
+                                      }
+                                      else if( primaryType.equals( Integer.class ) )
+                                      {
+                                          propsPrefs.putInt( persistentProperty.qualifiedName()
+                                                                 .name(), (Integer) value );
+                                      }
+                                      else if( primaryType.equals( Double.class ) )
+                                      {
+                                          propsPrefs.putDouble( persistentProperty.qualifiedName()
+                                                                    .name(), (Double) value );
+                                      }
+                                      else if( primaryType.equals( Float.class ) )
+                                      {
+                                          propsPrefs.putFloat( persistentProperty.qualifiedName()
+                                                                   .name(), (Float) value );
+                                      }
+                                      else
+                                      {
+                                          // Store as string even though it's a number
+                                          String string = serialization.serialize( value );
+                                          propsPrefs.put( persistentProperty.qualifiedName().name(), string );
+                                      }
+                                  }
+                                  else if( primaryType.equals( Boolean.class ) )
+                                  {
+                                      propsPrefs.putBoolean( persistentProperty.qualifiedName()
+                                                                 .name(), (Boolean) value );
+                                  }
+                                  else if( valueType instanceof ValueCompositeType
+                                           || valueType instanceof MapType
+                                           || valueType instanceof CollectionType
+                                           || valueType instanceof EnumType )
+                                  {
+                                      String string = serialization.serialize( value );
+                                      propsPrefs.put( persistentProperty.qualifiedName().name(), string );
+                                  }
+                                  else
+                                  {
+                                      String string = serialization.serialize( value );
+                                      propsPrefs.put( persistentProperty.qualifiedName().name(), string );
+                                  }
+                              }
+                          } );
+
+            // Associations
+            if( !state.associations().isEmpty() )
+            {
+                Preferences assocsPrefs = entityPrefs.node( "associations" );
+                for( Map.Entry<QualifiedName, EntityReference> association : state.associations().entrySet() )
+                {
+                    if( association.getValue() == null )
+                    {
+                        assocsPrefs.remove( association.getKey().name() );
+                    }
+                    else
+                    {
+                        assocsPrefs.put( association.getKey().name(), association.getValue().identity().toString() );
+                    }
+                }
+            }
+
+            // ManyAssociations
+            if( !state.manyAssociations().isEmpty() )
+            {
+                Preferences manyAssocsPrefs = entityPrefs.node( "manyassociations" );
+                for( Map.Entry<QualifiedName, List<EntityReference>> manyAssociation : state.manyAssociations()
+                    .entrySet() )
+                {
+                    StringBuilder manyAssocs = new StringBuilder();
+                    for( EntityReference entityReference : manyAssociation.getValue() )
+                    {
+                        if( manyAssocs.length() > 0 )
+                        {
+                            manyAssocs.append( "\n" );
+                        }
+                        manyAssocs.append( entityReference.identity().toString() );
+                    }
+                    if( manyAssocs.length() > 0 )
+                    {
+                        manyAssocsPrefs.put( manyAssociation.getKey().name(), manyAssocs.toString() );
+                    }
+                }
+            }
+
+            // NamedAssociations
+            if( !state.namedAssociations().isEmpty() )
+            {
+                Preferences namedAssocsPrefs = entityPrefs.node( "namedassociations" );
+                for( Map.Entry<QualifiedName, Map<String, EntityReference>> namedAssociation : state.namedAssociations()
+                    .entrySet() )
+                {
+                    StringBuilder namedAssocs = new StringBuilder();
+                    for( Map.Entry<String, EntityReference> namedRef : namedAssociation.getValue().entrySet() )
+                    {
+                        if( namedAssocs.length() > 0 )
+                        {
+                            namedAssocs.append( "\n" );
+                        }
+                        namedAssocs.append( namedRef.getKey() ).append( "\n" ).append( namedRef.getValue().identity().toString() );
+                    }
+                    if( namedAssocs.length() > 0 )
+                    {
+                        namedAssocsPrefs.put( namedAssociation.getKey().name(), namedAssocs.toString() );
+                    }
+                }
+            }
+        }
+        catch( SerializationException e )
+        {
+            throw new EntityStoreException( "Could not store EntityState", e );
+        }
+    }
+
+    protected Identity newUnitOfWorkId()
+    {
+        return identityGenerator.generate(EntityStore.class);
+    }
+
+    private interface NumberParser<T>
+    {
+        T parse( String str );
+    }
+
+    private static final NumberParser<Long> LONG_PARSER = Long::parseLong;
+
+    private static final NumberParser<Integer> INT_PARSER = Integer::parseInt;
+
+    private static final NumberParser<Double> DOUBLE_PARSER = Double::parseDouble;
+
+    private static final NumberParser<Float> FLOAT_PARSER = Float::parseFloat;
+
+    private <T> T getNumber( Preferences prefs, ModuleDescriptor module, PropertyDescriptor pDesc, NumberParser<T> parser )
+    {
+        Object initialValue = pDesc.resolveInitialValue( module );
+        String str = prefs.get( pDesc.qualifiedName().name(), initialValue == null ? null : initialValue.toString() );
+        T result = null;
+        if( str != null )
+        {
+            result = parser.parse( str );
+        }
+        return result;
+    }
+
+    private static class UnknownType
+    {
+    }
+}
diff --git a/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/PreferencesEntityStoreService.java b/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/PreferencesEntityStoreService.java
new file mode 100644
index 0000000..8af7d17
--- /dev/null
+++ b/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/PreferencesEntityStoreService.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.entitystore.preferences;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.spi.entitystore.ConcurrentModificationCheckConcern;
+import org.apache.polygene.spi.entitystore.EntityStateVersions;
+import org.apache.polygene.spi.entitystore.EntityStore;
+
+/**
+ * EntityStore backed by Preferences API.
+ * <p>
+ * A root node is created in the System preferences, whose name
+ * is the same as the Application name (default:"Application").
+ * </p>
+ * <p>
+ * Each entity is stored under its identity name.
+ * </p>
+ * <p>
+ * Property types are converted to native Preferences API types
+ * as much as possible. All others will be serialized to a string using JSON.
+ * </p>
+ * <p>
+ * Associations are stored as the identity of the referenced Entity, ManyAssociations are stored as multi-line strings
+ * (one reference per line), and NamedAssociations are stored as multi-line strings (one name on a line, reference on the
+ * next line).
+ * </p>
+ * <p>
+ * The main use of the EntityStore is for storage of ConfigurationComposites for ServiceComposites.
+ * </p>
+ * @see org.apache.polygene.api.service.ServiceComposite
+ * @see org.apache.polygene.api.configuration.Configuration
+ */
+@Concerns( ConcurrentModificationCheckConcern.class )
+@Mixins( PreferencesEntityStoreMixin.class )
+public interface PreferencesEntityStoreService
+    extends EntityStore, EntityStateVersions, ServiceActivation
+{
+}
diff --git a/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/assembly/PreferencesEntityStoreAssembler.java b/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/assembly/PreferencesEntityStoreAssembler.java
new file mode 100644
index 0000000..53ea9de
--- /dev/null
+++ b/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/assembly/PreferencesEntityStoreAssembler.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.entitystore.preferences.assembly;
+
+import java.util.prefs.Preferences;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.entitystore.preferences.PreferencesEntityStoreInfo;
+import org.apache.polygene.entitystore.preferences.PreferencesEntityStoreService;
+
+public class PreferencesEntityStoreAssembler
+    extends Assemblers.VisibilityIdentityConfig<PreferencesEntityStoreAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        String applicationName = module.layer().application().name();
+
+        Preferences root = Preferences.userRoot();
+        Preferences node = root.node( applicationName );
+        PreferencesEntityStoreInfo info = new PreferencesEntityStoreInfo( node );
+        ServiceDeclaration service = module.services( PreferencesEntityStoreService.class )
+            .setMetaInfo( info )
+            .visibleIn( visibility() )
+            .instantiateOnStartup();
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+    }
+}
diff --git a/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/assembly/package.html b/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/assembly/package.html
new file mode 100644
index 0000000..564de79
--- /dev/null
+++ b/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Preferences EntityStore Assembly.</h2>
+    </body>
+</html>
diff --git a/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/package.html b/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/package.html
new file mode 100644
index 0000000..8e39337
--- /dev/null
+++ b/extensions/entitystore-preferences/src/main/java/org/apache/polygene/entitystore/preferences/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Preferences EntityStore.</h2>
+    </body>
+</html>
diff --git a/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/ListPreferencesNodes.java b/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/ListPreferencesNodes.java
deleted file mode 100644
index 31306ba..0000000
--- a/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/ListPreferencesNodes.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.entitystore.prefs;
-
-import java.util.prefs.BackingStoreException;
-import java.util.prefs.Preferences;
-
-public class ListPreferencesNodes
-{
-    public static void main( String[] args )
-        throws Exception
-    {
-        Preferences preferences = Preferences.userRoot();
-        printNode( preferences, "" );
-    }
-
-    private static void printNode( Preferences node, String indent )
-        throws BackingStoreException
-    {
-        System.out.print( indent );
-        String name = node.name();
-        if( "".equals( name ) )
-        {
-            name = "/";
-        }
-
-        System.out.print( name );
-        String[] nodes = node.keys();
-        if( nodes.length > 0 )
-        {
-            System.out.print( "  { " );
-            boolean first = true;
-            for( String key : nodes )
-            {
-                if( !first )
-                {
-                    System.out.print( ", " );
-                }
-                first = false;
-                System.out.print( key );
-            }
-            System.out.print( " }" );
-        }
-        System.out.println();
-        for( String childName : node.childrenNames() )
-        {
-            Preferences child = node.node( childName );
-            printNode( child, indent + "  " );
-        }
-    }
-}
diff --git a/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/PreferencesEntityStoreInfo.java b/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/PreferencesEntityStoreInfo.java
deleted file mode 100644
index bc2febb..0000000
--- a/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/PreferencesEntityStoreInfo.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.entitystore.prefs;
-
-import java.io.Serializable;
-import java.util.prefs.Preferences;
-
-/**
- * @author edward.yakop@gmail.com
- */
-public final class PreferencesEntityStoreInfo
-    implements Serializable
-{
-    private Preferences rootNode;
-
-    public PreferencesEntityStoreInfo( Preferences aRootNode )
-    {
-        rootNode = aRootNode;
-    }
-
-    /**
-     * @return root preference node to use.
-     */
-    public Preferences rootNode()
-    {
-        return rootNode;
-    }
-}
\ No newline at end of file
diff --git a/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/PreferencesEntityStoreMixin.java b/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/PreferencesEntityStoreMixin.java
deleted file mode 100644
index b47b376..0000000
--- a/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/PreferencesEntityStoreMixin.java
+++ /dev/null
@@ -1,715 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.entitystore.prefs;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.prefs.BackingStoreException;
-import java.util.prefs.Preferences;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.cache.CacheOptions;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.service.qualifier.Tagged;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.type.CollectionType;
-import org.qi4j.api.type.EnumType;
-import org.qi4j.api.type.MapType;
-import org.qi4j.api.type.ValueCompositeType;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.api.unitofwork.EntityTypeNotFoundException;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.api.value.ValueSerializationException;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.spi.Qi4jSPI;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.EntityStatus;
-import org.qi4j.spi.entitystore.DefaultEntityStoreUnitOfWork;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.EntityStoreException;
-import org.qi4j.spi.entitystore.EntityStoreSPI;
-import org.qi4j.spi.entitystore.EntityStoreUnitOfWork;
-import org.qi4j.spi.entitystore.ModuleEntityStoreUnitOfWork;
-import org.qi4j.spi.entitystore.StateCommitter;
-import org.qi4j.spi.entitystore.helpers.DefaultEntityState;
-import org.qi4j.spi.module.ModelModule;
-import org.qi4j.spi.module.ModuleSpi;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.map;
-
-/**
- * Implementation of EntityStore that is backed by the Preferences API.
- *
- * <p>@see Preferences</p>
- * <p>
- * Associations are stored as the identity of the referenced Entity, ManyAssociations are stored as multi-line strings
- * (one identity per line), and NamedAssociations are stored as multi-line strings (one name on a line, identity on the
- * next line).
- * </p>
- * <p>Nested ValuesComposites, Collections and Maps are stored using available ValueSerialization service.</p>
- */
-public class PreferencesEntityStoreMixin
-    implements ServiceActivation, EntityStore, EntityStoreSPI
-{
-    @Structure
-    private Qi4jSPI spi;
-
-    @This
-    private EntityStoreSPI entityStoreSpi;
-
-    @Uses
-    private ServiceDescriptor descriptor;
-
-    @Structure
-    private Application application;
-
-    @Service
-    @Tagged( ValueSerialization.Formats.JSON )
-    private ValueSerialization valueSerialization;
-
-    private Preferences root;
-    protected String uuid;
-    private int count;
-    public Logger logger;
-    public ScheduledThreadPoolExecutor reloadExecutor;
-
-    @Override
-    public void activateService()
-        throws Exception
-    {
-        root = getApplicationRoot();
-        logger = LoggerFactory.getLogger( PreferencesEntityStoreService.class.getName() );
-        logger.info( "Preferences store:" + root.absolutePath() );
-        uuid = UUID.randomUUID().toString() + "-";
-
-        // Reload underlying store every 60 seconds
-        reloadExecutor = new ScheduledThreadPoolExecutor( 1 );
-        reloadExecutor.setExecuteExistingDelayedTasksAfterShutdownPolicy( false );
-        reloadExecutor.scheduleAtFixedRate( new Runnable()
-        {
-            @Override
-            public void run()
-            {
-                try
-                {
-                    synchronized( root )
-                    {
-                        root.sync();
-                    }
-                }
-                catch( BackingStoreException e )
-                {
-                    logger.warn( "Could not reload preferences", e );
-                }
-            }
-        }, 0, 60, TimeUnit.SECONDS );
-    }
-
-    private Preferences getApplicationRoot()
-    {
-        PreferencesEntityStoreInfo storeInfo = descriptor.metaInfo( PreferencesEntityStoreInfo.class );
-
-        Preferences preferences;
-        if( storeInfo == null )
-        {
-            // Default to use system root + application name
-            preferences = Preferences.systemRoot();
-            String name = application.name();
-            preferences = preferences.node( name );
-        }
-        else
-        {
-            preferences = storeInfo.rootNode();
-        }
-
-        return preferences;
-    }
-
-    @Override
-    public void passivateService()
-        throws Exception
-    {
-        reloadExecutor.shutdown();
-        reloadExecutor.awaitTermination( 10, TimeUnit.SECONDS );
-    }
-
-    @Override
-    public EntityStoreUnitOfWork newUnitOfWork( Usecase usecase, ModuleSpi module, long currentTime )
-    {
-        EntityStoreUnitOfWork storeUnitOfWork = new DefaultEntityStoreUnitOfWork( entityStoreSpi, newUnitOfWorkId(), usecase, currentTime );
-        storeUnitOfWork = new ModuleEntityStoreUnitOfWork( module, storeUnitOfWork );
-        return storeUnitOfWork;
-    }
-
-    @Override
-    public Input<EntityState, EntityStoreException> entityStates( final ModuleSpi module )
-    {
-        return new Input<EntityState, EntityStoreException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super EntityState, ReceiverThrowableType> output )
-                throws EntityStoreException, ReceiverThrowableType
-            {
-                output.receiveFrom( new Sender<EntityState, EntityStoreException>()
-                {
-                    @Override
-                    public <ReceiverThrowableType extends Throwable> void sendTo( Receiver<? super EntityState, ReceiverThrowableType> receiver )
-                        throws ReceiverThrowableType, EntityStoreException
-                    {
-                        UsecaseBuilder builder = UsecaseBuilder.buildUsecase( "qi4j.entitystore.preferences.visit" );
-                        Usecase visitUsecase = builder.withMetaInfo( CacheOptions.NEVER ).newUsecase();
-                        final EntityStoreUnitOfWork uow =
-                            newUnitOfWork( visitUsecase, module, System.currentTimeMillis() );
-
-                        try
-                        {
-                            String[] identities = root.childrenNames();
-                            for( String identity : identities )
-                            {
-                                EntityReference reference = EntityReference.parseEntityReference( identity );
-                                EntityState entityState = uow.entityStateOf( module, reference );
-                                receiver.receive( entityState );
-                            }
-                        }
-                        catch( BackingStoreException e )
-                        {
-                            throw new EntityStoreException( e );
-                        }
-                    }
-                } );
-            }
-        };
-    }
-
-    @Override
-    public EntityState newEntityState( EntityStoreUnitOfWork unitOfWork,
-                                       ModuleSpi module,
-                                       EntityReference identity,
-                                       EntityDescriptor entityDescriptor
-    )
-    {
-        return new DefaultEntityState( unitOfWork.currentTime(), identity, entityDescriptor );
-    }
-
-    @Override
-    public EntityState entityStateOf( EntityStoreUnitOfWork unitOfWork, ModuleSpi module, EntityReference identity )
-    {
-        try
-        {
-            if( !root.nodeExists( identity.identity() ) )
-            {
-                throw new NoSuchEntityException( identity, UnknownType.class, unitOfWork.usecase() );
-            }
-
-            Preferences entityPrefs = root.node( identity.identity() );
-
-            String type = entityPrefs.get( "type", null );
-            EntityStatus status = EntityStatus.LOADED;
-
-            EntityDescriptor entityDescriptor = module.entityDescriptor( type );
-            if( entityDescriptor == null )
-            {
-                throw new EntityTypeNotFoundException( type,
-                                                       module.name(),
-                                                       map( ModelModule.toStringFunction,
-                                                            module.findVisibleEntityTypes()
-                                                       ) );
-            }
-
-            Map<QualifiedName, Object> properties = new HashMap<>();
-            Preferences propsPrefs = null;
-            for( PropertyDescriptor persistentPropertyDescriptor : entityDescriptor.state().properties() )
-            {
-                if( persistentPropertyDescriptor.qualifiedName().name().equals( "identity" ) )
-                {
-                    // Fake identity property
-                    properties.put( persistentPropertyDescriptor.qualifiedName(), identity.identity() );
-                    continue;
-                }
-
-                if( propsPrefs == null )
-                {
-                    propsPrefs = entityPrefs.node( "properties" );
-                }
-
-                ValueType propertyType = persistentPropertyDescriptor.valueType();
-                Class<?> mainType = propertyType.mainType();
-                if( Number.class.isAssignableFrom( mainType ) )
-                {
-                    if( mainType.equals( Long.class ) )
-                    {
-                        properties.put( persistentPropertyDescriptor.qualifiedName(),
-                                        this.getNumber( propsPrefs, persistentPropertyDescriptor, LONG_PARSER ) );
-                    }
-                    else if( mainType.equals( Integer.class ) )
-                    {
-                        properties.put( persistentPropertyDescriptor.qualifiedName(),
-                                        this.getNumber( propsPrefs, persistentPropertyDescriptor, INT_PARSER ) );
-                    }
-                    else if( mainType.equals( Double.class ) )
-                    {
-                        properties.put( persistentPropertyDescriptor.qualifiedName(),
-                                        this.getNumber( propsPrefs, persistentPropertyDescriptor, DOUBLE_PARSER ) );
-                    }
-                    else if( mainType.equals( Float.class ) )
-                    {
-                        properties.put( persistentPropertyDescriptor.qualifiedName(),
-                                        this.getNumber( propsPrefs, persistentPropertyDescriptor, FLOAT_PARSER ) );
-                    }
-                    else
-                    {
-                        // Load as string even though it's a number
-                        String json = propsPrefs.get( persistentPropertyDescriptor.qualifiedName().name(), null );
-                        Object value;
-                        if( json == null )
-                        {
-                            value = null;
-                        }
-                        else
-                        {
-                            value = valueSerialization.deserialize( persistentPropertyDescriptor.valueType(), json );
-                        }
-                        properties.put( persistentPropertyDescriptor.qualifiedName(), value );
-                    }
-                }
-                else if( mainType.equals( Boolean.class ) )
-                {
-                    Boolean initialValue = (Boolean) persistentPropertyDescriptor.initialValue( module );
-                    properties.put( persistentPropertyDescriptor.qualifiedName(),
-                                    propsPrefs.getBoolean( persistentPropertyDescriptor.qualifiedName().name(),
-                                                           initialValue == null ? false : initialValue ) );
-                }
-                else if( propertyType instanceof ValueCompositeType
-                         || propertyType instanceof MapType
-                         || propertyType instanceof CollectionType
-                         || propertyType instanceof EnumType )
-                {
-                    String json = propsPrefs.get( persistentPropertyDescriptor.qualifiedName().name(), null );
-                    Object value;
-                    if( json == null )
-                    {
-                        value = null;
-                    }
-                    else
-                    {
-                        value = valueSerialization.deserialize( persistentPropertyDescriptor.valueType(), json );
-                    }
-                    properties.put( persistentPropertyDescriptor.qualifiedName(), value );
-                }
-                else
-                {
-                    String json = propsPrefs.get( persistentPropertyDescriptor.qualifiedName().name(), null );
-                    if( json == null )
-                    {
-                        if( persistentPropertyDescriptor.initialValue( module ) != null )
-                        {
-                            properties.put( persistentPropertyDescriptor.qualifiedName(), persistentPropertyDescriptor.initialValue( module ) );
-                        }
-                        else
-                        {
-                            properties.put( persistentPropertyDescriptor.qualifiedName(), null );
-                        }
-                    }
-                    else
-                    {
-                        Object value = valueSerialization.deserialize( propertyType, json );
-                        properties.put( persistentPropertyDescriptor.qualifiedName(), value );
-                    }
-                }
-            }
-
-            // Associations
-            Map<QualifiedName, EntityReference> associations = new HashMap<>();
-            Preferences assocs = null;
-            for( AssociationDescriptor associationType : entityDescriptor.state().associations() )
-            {
-                if( assocs == null )
-                {
-                    assocs = entityPrefs.node( "associations" );
-                }
-
-                String associatedEntity = assocs.get( associationType.qualifiedName().name(), null );
-                EntityReference value = associatedEntity == null
-                                        ? null
-                                        : EntityReference.parseEntityReference( associatedEntity );
-                associations.put( associationType.qualifiedName(), value );
-            }
-
-            // ManyAssociations
-            Map<QualifiedName, List<EntityReference>> manyAssociations = new HashMap<>();
-            Preferences manyAssocs = null;
-            for( AssociationDescriptor manyAssociationType : entityDescriptor.state().manyAssociations() )
-            {
-                if( manyAssocs == null )
-                {
-                    manyAssocs = entityPrefs.node( "manyassociations" );
-                }
-
-                List<EntityReference> references = new ArrayList<>();
-                String entityReferences = manyAssocs.get( manyAssociationType.qualifiedName().name(), null );
-                if( entityReferences == null )
-                {
-                    // ManyAssociation not found, default to empty one
-                    manyAssociations.put( manyAssociationType.qualifiedName(), references );
-                }
-                else
-                {
-                    String[] refs = entityReferences.split( "\n" );
-                    for( String ref : refs )
-                    {
-                        EntityReference value = ref == null
-                                                ? null
-                                                : EntityReference.parseEntityReference( ref );
-                        references.add( value );
-                    }
-                    manyAssociations.put( manyAssociationType.qualifiedName(), references );
-                }
-            }
-
-            // NamedAssociations
-            Map<QualifiedName, Map<String, EntityReference>> namedAssociations = new HashMap<>();
-            Preferences namedAssocs = null;
-            for( AssociationDescriptor namedAssociationType : entityDescriptor.state().namedAssociations() )
-            {
-                if( namedAssocs == null )
-                {
-                    namedAssocs = entityPrefs.node( "namedassociations" );
-                }
-
-                Map<String, EntityReference> references = new LinkedHashMap<>();
-                String entityReferences = namedAssocs.get( namedAssociationType.qualifiedName().name(), null );
-                if( entityReferences == null )
-                {
-                    // NamedAssociation not found, default to empty one
-                    namedAssociations.put( namedAssociationType.qualifiedName(), references );
-                }
-                else
-                {
-                    String[] namedRefs = entityReferences.split( "\n" );
-                    if( namedRefs.length % 2 != 0 )
-                    {
-                        throw new EntityStoreException( "Invalid NamedAssociation storage format" );
-                    }
-                    for( int idx = 0; idx < namedRefs.length; idx += 2 )
-                    {
-                        String name = namedRefs[ idx ];
-                        String ref = namedRefs[ idx + 1 ];
-                        references.put( name, EntityReference.parseEntityReference( ref ) );
-                    }
-                    namedAssociations.put( namedAssociationType.qualifiedName(), references );
-                }
-            }
-
-            return new DefaultEntityState( entityPrefs.get( "version", "" ),
-                                           entityPrefs.getLong( "modified", unitOfWork.currentTime() ),
-                                           identity,
-                                           status,
-                                           entityDescriptor,
-                                           properties,
-                                           associations,
-                                           manyAssociations,
-                                           namedAssociations
-            );
-        }
-        catch( ValueSerializationException | BackingStoreException e )
-        {
-            throw new EntityStoreException( e );
-        }
-    }
-
-    @Override
-    public StateCommitter applyChanges( final EntityStoreUnitOfWork unitofwork, final Iterable<EntityState> state )
-    {
-        return new StateCommitter()
-        {
-            @SuppressWarnings( "SynchronizeOnNonFinalField" )
-            @Override
-            public void commit()
-            {
-                try
-                {
-                    synchronized( root )
-                    {
-                        for( EntityState entityState : state )
-                        {
-                            DefaultEntityState state = (DefaultEntityState) entityState;
-                            if( state.status().equals( EntityStatus.NEW ) )
-                            {
-                                Preferences entityPrefs = root.node( state.identity().identity() );
-                                writeEntityState( state, entityPrefs, unitofwork.identity(), unitofwork.currentTime() );
-                            }
-                            else if( state.status().equals( EntityStatus.UPDATED ) )
-                            {
-                                Preferences entityPrefs = root.node( state.identity().identity() );
-                                writeEntityState( state, entityPrefs, unitofwork.identity(), unitofwork.currentTime() );
-                            }
-                            else if( state.status().equals( EntityStatus.REMOVED ) )
-                            {
-                                root.node( state.identity().identity() ).removeNode();
-                            }
-                        }
-                        root.flush();
-                    }
-                }
-                catch( BackingStoreException e )
-                {
-                    throw new EntityStoreException( e );
-                }
-            }
-
-            @Override
-            public void cancel()
-            {
-            }
-        };
-    }
-
-    protected void writeEntityState( DefaultEntityState state,
-                                     Preferences entityPrefs,
-                                     String identity,
-                                     long lastModified
-    )
-        throws EntityStoreException
-    {
-        try
-        {
-            // Store into Preferences API
-            entityPrefs.put( "type", first( state.entityDescriptor().types() ).getName() );
-            entityPrefs.put( "version", identity );
-            entityPrefs.putLong( "modified", lastModified );
-
-            // Properties
-            Preferences propsPrefs = entityPrefs.node( "properties" );
-            for( PropertyDescriptor persistentProperty : state.entityDescriptor().state().properties() )
-            {
-                if( persistentProperty.qualifiedName().name().equals( "identity" ) )
-                {
-                    continue; // Skip Identity.identity()
-                }
-
-                Object value = state.properties().get( persistentProperty.qualifiedName() );
-
-                if( value == null )
-                {
-                    propsPrefs.remove( persistentProperty.qualifiedName().name() );
-                }
-                else
-                {
-                    ValueType valueType = persistentProperty.valueType();
-                    Class<?> mainType = valueType.mainType();
-                    if( Number.class.isAssignableFrom( mainType ) )
-                    {
-                        if( mainType.equals( Long.class ) )
-                        {
-                            propsPrefs.putLong( persistentProperty.qualifiedName().name(), (Long) value );
-                        }
-                        else if( mainType.equals( Integer.class ) )
-                        {
-                            propsPrefs.putInt( persistentProperty.qualifiedName().name(), (Integer) value );
-                        }
-                        else if( mainType.equals( Double.class ) )
-                        {
-                            propsPrefs.putDouble( persistentProperty.qualifiedName().name(), (Double) value );
-                        }
-                        else if( mainType.equals( Float.class ) )
-                        {
-                            propsPrefs.putFloat( persistentProperty.qualifiedName().name(), (Float) value );
-                        }
-                        else
-                        {
-                            // Store as string even though it's a number
-                            String jsonString = valueSerialization.serialize( value );
-                            propsPrefs.put( persistentProperty.qualifiedName().name(), jsonString );
-                        }
-                    }
-                    else if( mainType.equals( Boolean.class ) )
-                    {
-                        propsPrefs.putBoolean( persistentProperty.qualifiedName().name(), (Boolean) value );
-                    }
-                    else if( valueType instanceof ValueCompositeType
-                             || valueType instanceof MapType
-                             || valueType instanceof CollectionType
-                             || valueType instanceof EnumType )
-                    {
-                        String jsonString = valueSerialization.serialize( value );
-                        propsPrefs.put( persistentProperty.qualifiedName().name(), jsonString );
-                    }
-                    else
-                    {
-                        String jsonString = valueSerialization.serialize( value );
-                        propsPrefs.put( persistentProperty.qualifiedName().name(), jsonString );
-                    }
-                }
-            }
-
-            // Associations
-            if( !state.associations().isEmpty() )
-            {
-                Preferences assocsPrefs = entityPrefs.node( "associations" );
-                for( Map.Entry<QualifiedName, EntityReference> association : state.associations().entrySet() )
-                {
-                    if( association.getValue() == null )
-                    {
-                        assocsPrefs.remove( association.getKey().name() );
-                    }
-                    else
-                    {
-                        assocsPrefs.put( association.getKey().name(), association.getValue().identity() );
-                    }
-                }
-            }
-
-            // ManyAssociations
-            if( !state.manyAssociations().isEmpty() )
-            {
-                Preferences manyAssocsPrefs = entityPrefs.node( "manyassociations" );
-                for( Map.Entry<QualifiedName, List<EntityReference>> manyAssociation : state.manyAssociations()
-                    .entrySet() )
-                {
-                    StringBuilder manyAssocs = new StringBuilder();
-                    for( EntityReference entityReference : manyAssociation.getValue() )
-                    {
-                        if( manyAssocs.length() > 0 )
-                        {
-                            manyAssocs.append( "\n" );
-                        }
-                        manyAssocs.append( entityReference.identity() );
-                    }
-                    if( manyAssocs.length() > 0 )
-                    {
-                        manyAssocsPrefs.put( manyAssociation.getKey().name(), manyAssocs.toString() );
-                    }
-                }
-            }
-
-            // NamedAssociations
-            if( !state.namedAssociations().isEmpty() )
-            {
-                Preferences namedAssocsPrefs = entityPrefs.node( "namedassociations" );
-                for( Map.Entry<QualifiedName, Map<String, EntityReference>> namedAssociation : state.namedAssociations()
-                    .entrySet() )
-                {
-                    StringBuilder namedAssocs = new StringBuilder();
-                    for( Map.Entry<String, EntityReference> namedRef : namedAssociation.getValue().entrySet() )
-                    {
-                        if( namedAssocs.length() > 0 )
-                        {
-                            namedAssocs.append( "\n" );
-                        }
-                        namedAssocs.append( namedRef.getKey() ).append( "\n" ).append( namedRef.getValue().identity() );
-                    }
-                    if( namedAssocs.length() > 0 )
-                    {
-                        namedAssocsPrefs.put( namedAssociation.getKey().name(), namedAssocs.toString() );
-                    }
-                }
-            }
-        }
-        catch( ValueSerializationException e )
-        {
-            throw new EntityStoreException( "Could not store EntityState", e );
-        }
-    }
-
-    protected String newUnitOfWorkId()
-    {
-        return uuid + Integer.toHexString( count++ );
-    }
-
-    private interface NumberParser<T>
-    {
-        T parse( String str );
-    }
-
-    private static final NumberParser<Long> LONG_PARSER = new NumberParser<Long>()
-    {
-        @Override
-        public Long parse( String str )
-        {
-            return Long.parseLong( str );
-        }
-    };
-
-    private static final NumberParser<Integer> INT_PARSER = new NumberParser<Integer>()
-    {
-        @Override
-        public Integer parse( String str )
-        {
-            return Integer.parseInt( str );
-        }
-    };
-
-    private static final NumberParser<Double> DOUBLE_PARSER = new NumberParser<Double>()
-    {
-        @Override
-        public Double parse( String str )
-        {
-            return Double.parseDouble( str );
-        }
-    };
-
-    private static final NumberParser<Float> FLOAT_PARSER = new NumberParser<Float>()
-    {
-        @Override
-        public Float parse( String str )
-        {
-            return Float.parseFloat( str );
-        }
-    };
-
-    private <T> T getNumber( Preferences prefs, PropertyDescriptor pDesc, NumberParser<T> parser )
-    {
-        Object initialValue = pDesc.initialValue( null );
-        String str = prefs.get( pDesc.qualifiedName().name(), initialValue == null ? null : initialValue.toString() );
-        T result = null;
-        if( str != null )
-        {
-            result = parser.parse( str );
-        }
-        return result;
-    }
-
-    private static class UnknownType
-    {
-    }
-}
diff --git a/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/PreferencesEntityStoreService.java b/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/PreferencesEntityStoreService.java
deleted file mode 100644
index b0958ff..0000000
--- a/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/PreferencesEntityStoreService.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.prefs;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.spi.entitystore.ConcurrentModificationCheckConcern;
-import org.qi4j.spi.entitystore.EntityStateVersions;
-import org.qi4j.spi.entitystore.EntityStore;
-
-/**
- * EntityStore backed by Preferences API.
- * <p>
- * A root node is created in the System preferences, whose name
- * is the same as the Application name (default:"Application").
- * </p>
- * <p>
- * Each entity is stored under its identity name.
- * </p>
- * <p>
- * Property types are converted to native Preferences API types
- * as much as possible. All others will be serialized to a string using JSON.
- * </p>
- * <p>
- * Associations are stored as the identity of the referenced Entity, ManyAssociations are stored as multi-line strings
- * (one identity per line), and NamedAssociations are stored as multi-line strings (one name on a line, identity on the
- * next line).
- * </p>
- * <p>
- * The main use of the EntityStore is for storage of ConfigurationComposites for ServiceComposites.
- * </p>
- * @see org.qi4j.api.service.ServiceComposite
- * @see org.qi4j.api.configuration.Configuration
- */
-@Concerns( ConcurrentModificationCheckConcern.class )
-@Mixins( PreferencesEntityStoreMixin.class )
-public interface PreferencesEntityStoreService
-    extends EntityStore, ServiceComposite, EntityStateVersions, ServiceActivation
-{
-}
diff --git a/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/assembly/PreferenceEntityStoreAssembler.java b/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/assembly/PreferenceEntityStoreAssembler.java
deleted file mode 100644
index 6e3ff9b..0000000
--- a/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/assembly/PreferenceEntityStoreAssembler.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.entitystore.prefs.assembly;
-
-import java.util.prefs.Preferences;
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.entitystore.prefs.PreferencesEntityStoreInfo;
-import org.qi4j.entitystore.prefs.PreferencesEntityStoreService;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-
-public class PreferenceEntityStoreAssembler
-    extends Assemblers.VisibilityIdentity<PreferenceEntityStoreAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        String applicationName = module.layer().application().name();
-
-        Preferences root = Preferences.userRoot();
-        Preferences node = root.node( applicationName );
-        PreferencesEntityStoreInfo info = new PreferencesEntityStoreInfo( node );
-        ServiceDeclaration service = module.services( PreferencesEntityStoreService.class )
-            .setMetaInfo( info )
-            .visibleIn( visibility() )
-            .instantiateOnStartup();
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        module.services( UuidIdentityGeneratorService.class ).visibleIn( visibility() );
-    }
-}
diff --git a/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/assembly/package.html b/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/assembly/package.html
deleted file mode 100644
index 81fa32c..0000000
--- a/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/assembly/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Preferences EntityStore Assembly.</h2>
-    </body>
-</html>
diff --git a/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/package.html b/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/package.html
deleted file mode 100644
index 079026d..0000000
--- a/extensions/entitystore-preferences/src/main/java/org/qi4j/entitystore/prefs/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Preferences EntityStore.</h2>
-    </body>
-</html>
diff --git a/extensions/entitystore-preferences/src/test/java/org/apache/polygene/entitystore/DocumentationSupport.java b/extensions/entitystore-preferences/src/test/java/org/apache/polygene/entitystore/DocumentationSupport.java
new file mode 100644
index 0000000..53f049a
--- /dev/null
+++ b/extensions/entitystore-preferences/src/test/java/org/apache/polygene/entitystore/DocumentationSupport.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.entitystore;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.preferences.assembly.PreferencesEntityStoreAssembler;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+public class DocumentationSupport
+    extends AbstractPolygeneTest
+{
+
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+            throws AssemblyException
+    {
+        new PreferencesEntityStoreAssembler().assemble( module );
+    }
+    // END SNIPPET: assembly
+
+}
diff --git a/extensions/entitystore-preferences/src/test/java/org/apache/polygene/entitystore/preferences/PreferencesEntityStoreTest.java b/extensions/entitystore-preferences/src/test/java/org/apache/polygene/entitystore/preferences/PreferencesEntityStoreTest.java
new file mode 100644
index 0000000..9801ded
--- /dev/null
+++ b/extensions/entitystore-preferences/src/test/java/org/apache/polygene/entitystore/preferences/PreferencesEntityStoreTest.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.entitystore.preferences;
+
+import java.util.prefs.Preferences;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.preferences.PreferencesEntityStoreInfo;
+import org.apache.polygene.entitystore.preferences.PreferencesEntityStoreService;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+public class PreferencesEntityStoreTest
+    extends AbstractEntityStoreTest
+{
+    @Rule
+    public TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.layer().application().setName( "PreferencesTest" );
+
+        super.assemble( module );
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        Thread.currentThread().setContextClassLoader( null );
+        Preferences node = Preferences.userNodeForPackage( getClass() )
+                                      .node( "integtest" )
+                                      .node( tmpDir.getRoot().getName() )
+                                      .node( "PreferencesEntityStoreTest" );
+        PreferencesEntityStoreInfo metaInfo = new PreferencesEntityStoreInfo( node );
+        Thread.currentThread().setContextClassLoader( cl );
+        module.services( PreferencesEntityStoreService.class ).setMetaInfo( metaInfo ).instantiateOnStartup();
+    }
+}
diff --git a/extensions/entitystore-preferences/src/test/java/org/qi4j/entitystore/DocumentationSupport.java b/extensions/entitystore-preferences/src/test/java/org/qi4j/entitystore/DocumentationSupport.java
deleted file mode 100644
index 2278312..0000000
--- a/extensions/entitystore-preferences/src/test/java/org/qi4j/entitystore/DocumentationSupport.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin
- *
- * Licensed  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.qi4j.entitystore;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.prefs.assembly.PreferenceEntityStoreAssembler;
-import org.qi4j.test.AbstractQi4jTest;
-
-public class DocumentationSupport
-        extends AbstractQi4jTest
-{
-
-    // START SNIPPET: assembly
-    public void assemble( ModuleAssembly module )
-            throws AssemblyException
-    {
-        new PreferenceEntityStoreAssembler().assemble( module );
-    }
-    // END SNIPPET: assembly
-
-}
diff --git a/extensions/entitystore-preferences/src/test/java/org/qi4j/entitystore/PreferencesEntityStoreTest.java b/extensions/entitystore-preferences/src/test/java/org/qi4j/entitystore/PreferencesEntityStoreTest.java
deleted file mode 100644
index 01bb36d..0000000
--- a/extensions/entitystore-preferences/src/test/java/org/qi4j/entitystore/PreferencesEntityStoreTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore;
-
-import java.util.prefs.Preferences;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.prefs.PreferencesEntityStoreInfo;
-import org.qi4j.entitystore.prefs.PreferencesEntityStoreService;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class PreferencesEntityStoreTest
-    extends AbstractEntityStoreTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.layer().application().setName( "PreferencesTest" );
-
-        super.assemble( module );
-        ClassLoader cl = Thread.currentThread().getContextClassLoader();
-        Thread.currentThread().setContextClassLoader( null );
-        PreferencesEntityStoreInfo metaInfo = new PreferencesEntityStoreInfo( Preferences.userNodeForPackage( getClass() ) );
-        Thread.currentThread().setContextClassLoader( cl );
-        module.services( PreferencesEntityStoreService.class ).setMetaInfo( metaInfo ).instantiateOnStartup();
-        new OrgJsonValueSerializationAssembler().assemble( module );
-    }
-}
diff --git a/extensions/entitystore-redis/build.gradle b/extensions/entitystore-redis/build.gradle
index 50e6c36..da29e7d 100644
--- a/extensions/entitystore-redis/build.gradle
+++ b/extensions/entitystore-redis/build.gradle
@@ -1,37 +1,38 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Redis EntityStore Extension"
+apply plugin: 'polygene-extension'
 
-jar { manifest { name = "Apache Zest™ Extension - EntityStore - Redis" }}
+description = "Apache Polygene™ Redis EntityStore Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - EntityStore - Redis" } }
 
 dependencies {
-    
-    compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-    compile(project(":org.qi4j.libraries:org.qi4j.library.locking"))
-    compile(libraries.jedis)
+  api polygene.core.bootstrap
 
-    testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-    testCompile(project(":org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson"))
+  implementation polygene.library( 'locking' )
+  implementation libraries.jedis
 
-    testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-    testRuntime(libraries.logback)
+  runtimeOnly polygene.core.runtime
 
+  testImplementation polygene.internals.testsupport
+
+  testRuntimeOnly libraries.logback
 }
-
diff --git a/extensions/entitystore-redis/dev-status.xml b/extensions/entitystore-redis/dev-status.xml
index 169068f..8d582e2 100644
--- a/extensions/entitystore-redis/dev-status.xml
+++ b/extensions/entitystore-redis/dev-status.xml
@@ -1,27 +1,30 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
         <!--none,early,beta,stable,mature-->
-        <codebase>beta</codebase>
+        <codebase>stable</codebase>
 
         <!-- none, brief, good, complete -->
         <documentation>good</documentation>
diff --git a/extensions/entitystore-redis/src/docs/es-redis.txt b/extensions/entitystore-redis/src/docs/es-redis.txt
index dae3644..20ac8e1 100644
--- a/extensions/entitystore-redis/src/docs/es-redis.txt
+++ b/extensions/entitystore-redis/src/docs/es-redis.txt
@@ -35,7 +35,7 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-redis/src/test/java/org/qi4j/entitystore/redis/RedisMapEntityStoreTest.java
+source=extensions/entitystore-redis/src/test/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreTest.java
 tag=assembly
 ----
 
@@ -46,6 +46,6 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/RedisEntityStoreConfiguration.java
+source=extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/RedisEntityStoreConfiguration.java
 tag=config
 ----
diff --git a/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/RedisAccessors.java b/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/RedisAccessors.java
new file mode 100644
index 0000000..b20581b
--- /dev/null
+++ b/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/RedisAccessors.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.entitystore.redis;
+
+import redis.clients.jedis.JedisPool;
+
+public interface RedisAccessors
+{
+
+    JedisPool jedisPool();
+
+}
diff --git a/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/RedisEntityStoreConfiguration.java b/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/RedisEntityStoreConfiguration.java
new file mode 100644
index 0000000..c3ba3f1
--- /dev/null
+++ b/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/RedisEntityStoreConfiguration.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.entitystore.redis;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Configuration for RedisMapEntityStoreService.
+ */
+// START SNIPPET: config
+public interface RedisEntityStoreConfiguration
+{
+
+    /**
+     * Redis host.
+     *
+     * Defaulted to 127.0.0.1.
+     */
+    @Optional
+    Property<String> host();
+
+    /**
+     * Redis port.
+     *
+     * Defaulted to 6379.
+     */
+    @Optional
+    Property<Integer> port();
+
+    /**
+     * Connection timeout in milliseconds.
+     *
+     * Defaulted to 2000.
+     */
+    @Optional
+    Property<Integer> timeout();
+
+    /**
+     * Redis password.
+     */
+    @Optional
+    Property<String> password();
+
+    /**
+     * Redis database.
+     *
+     * Defaulted to 0.
+     */
+    @Optional
+    Property<Integer> database();
+
+}
+// END SNIPPET: config
diff --git a/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreMixin.java b/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreMixin.java
new file mode 100644
index 0000000..0fcb2c5
--- /dev/null
+++ b/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreMixin.java
@@ -0,0 +1,177 @@
+/*
+ *  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.polygene.entitystore.redis;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.stream.Stream;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.spi.entitystore.EntityAlreadyExistsException;
+import org.apache.polygene.spi.entitystore.EntityNotFoundException;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+import org.apache.polygene.spi.entitystore.helpers.MapEntityStore;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
+import redis.clients.jedis.Protocol;
+
+/**
+ * Redis implementation of MapEntityStore.
+ */
+public class RedisMapEntityStoreMixin
+    implements ServiceActivation, RedisAccessors, MapEntityStore
+{
+    private static final String DEFAULT_HOST = "127.0.0.1";
+    private static final String NIL = "nil";
+    @This
+    private Configuration<RedisEntityStoreConfiguration> configuration;
+    private JedisPool pool;
+
+    @Override
+    public void activateService()
+        throws Exception
+    {
+        configuration.refresh();
+        RedisEntityStoreConfiguration config = configuration.get();
+
+        String host = config.host().get() == null ? DEFAULT_HOST : config.host().get();
+        int port = config.port().get() == null ? Protocol.DEFAULT_PORT : config.port().get();
+        int timeout = config.timeout().get() == null ? Protocol.DEFAULT_TIMEOUT : config.timeout().get();
+        String password = config.password().get();
+        int database = config.database().get() == null ? Protocol.DEFAULT_DATABASE : config.database().get();
+
+        pool = new JedisPool( new JedisPoolConfig(), host, port, timeout, password, database );
+    }
+
+    @Override
+    public void passivateService()
+        throws Exception
+    {
+        pool.destroy();
+        pool = null;
+    }
+
+    @Override
+    public JedisPool jedisPool()
+    {
+        return pool;
+    }
+
+    @Override
+    public Reader get( EntityReference entityReference )
+        throws EntityStoreException
+    {
+        try( Jedis jedis = pool.getResource() )
+        {
+            String jsonState = jedis.get( entityReference.identity().toString() );
+            if( notFound( jsonState ) )
+            {
+                throw new EntityNotFoundException( entityReference );
+            }
+            return new StringReader( jsonState );
+        }
+    }
+
+    @Override
+    public void applyChanges( MapChanges changes )
+        throws Exception
+    {
+        try( Jedis jedis = pool.getResource() )
+        {
+            changes.visitMap( new MapChanger()
+            {
+                @Override
+                public Writer newEntity( EntityReference ref, EntityDescriptor entityDescriptor )
+                    throws IOException
+                {
+                    return new StringWriter( 1000 )
+                    {
+                        @Override
+                        public void close()
+                            throws IOException
+                        {
+                            super.close();
+                            String statusCode = jedis.set( ref.identity().toString(), toString(), "NX" );
+                            if( !"OK".equals( statusCode ) )
+                            {
+                                throw new EntityAlreadyExistsException( ref );
+                            }
+                        }
+                    };
+                }
+
+                @Override
+                public Writer updateEntity( MapChange mapChange )
+                    throws IOException
+                {
+                    return new StringWriter( 1000 )
+                    {
+                        @Override
+                        public void close()
+                            throws IOException
+                        {
+                            super.close();
+                            String statusCode = jedis.set( mapChange.reference().identity().toString(),
+                                                           toString(),
+                                                           "XX" );
+                            if( !"OK".equals( statusCode ) )
+                            {
+                                throw new EntityNotFoundException( mapChange.reference() );
+                            }
+                        }
+                    };
+                }
+
+                @Override
+                public void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor )
+                    throws EntityNotFoundException
+                {
+                    String jsonState = jedis.get( ref.identity().toString() );
+                    if( notFound( jsonState ) )
+                    {
+                        throw new EntityNotFoundException( ref );
+                    }
+                    jedis.del( ref.identity().toString() );
+                }
+            } );
+        }
+    }
+
+    @Override
+    public Stream<Reader> entityStates()
+    {
+        Jedis jedis = pool.getResource();
+        return jedis.keys( "*" ).stream()
+                    .map( key -> (Reader) new StringReader( jedis.get( key ) ) )
+                    .onClose( jedis::close );
+    }
+
+    private static boolean notFound( String jsonState )
+    {
+        return jsonState == null || NIL.equals( jsonState );
+    }
+}
diff --git a/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreService.java b/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreService.java
new file mode 100644
index 0000000..0ebaa52
--- /dev/null
+++ b/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreService.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.entitystore.redis;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.library.locking.LockingAbstractComposite;
+import org.apache.polygene.spi.entitystore.ConcurrentModificationCheckConcern;
+import org.apache.polygene.spi.entitystore.EntityStateVersions;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.StateChangeNotificationConcern;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreActivation;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreMixin;
+
+/**
+ * Redis EntityStore service.
+ * <p>Based on @{@link JSONMapEntityStoreMixin}.</p>
+ */
+@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
+@Mixins( { JSONMapEntityStoreMixin.class, RedisMapEntityStoreMixin.class } )
+public interface RedisMapEntityStoreService
+        extends EntityStore,
+                EntityStateVersions,
+                ServiceActivation,
+                JSONMapEntityStoreActivation,
+                LockingAbstractComposite,
+                Configuration,
+                RedisAccessors
+{
+}
diff --git a/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/assembly/RedisEntityStoreAssembler.java b/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/assembly/RedisEntityStoreAssembler.java
new file mode 100644
index 0000000..a0d8f04
--- /dev/null
+++ b/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/assembly/RedisEntityStoreAssembler.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.entitystore.redis.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.entitystore.redis.RedisEntityStoreConfiguration;
+import org.apache.polygene.entitystore.redis.RedisMapEntityStoreService;
+
+/**
+ * Redis EntityStore assembly.
+ */
+public class RedisEntityStoreAssembler
+    extends Assemblers.VisibilityIdentityConfig<RedisEntityStoreAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( RedisMapEntityStoreService.class ).visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+        if( hasConfig() )
+        {
+            configModule().entities( RedisEntityStoreConfiguration.class ).visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/package.html b/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/package.html
new file mode 100644
index 0000000..eb511b2
--- /dev/null
+++ b/extensions/entitystore-redis/src/main/java/org/apache/polygene/entitystore/redis/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Redis EntityStore.</h2>
+    </body>
+</html>
diff --git a/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/RedisAccessors.java b/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/RedisAccessors.java
deleted file mode 100644
index 5eb91cb..0000000
--- a/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/RedisAccessors.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.redis;
-
-import redis.clients.jedis.JedisPool;
-
-public interface RedisAccessors
-{
-
-    JedisPool jedisPool();
-
-}
diff --git a/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/RedisEntityStoreConfiguration.java b/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/RedisEntityStoreConfiguration.java
deleted file mode 100644
index e48ca8d..0000000
--- a/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/RedisEntityStoreConfiguration.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.redis;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-/**
- * Configuration for RedisMapEntityStoreService.
- */
-// START SNIPPET: config
-public interface RedisEntityStoreConfiguration
-        extends ConfigurationComposite
-{
-
-    /**
-     * Redis host.
-     *
-     * Defaulted to 127.0.0.1.
-     */
-    @Optional
-    Property<String> host();
-
-    /**
-     * Redis port.
-     *
-     * Defaulted to 6379.
-     */
-    @Optional
-    Property<Integer> port();
-
-    /**
-     * Connection timeout in milliseconds.
-     *
-     * Defaulted to 2000.
-     */
-    @Optional
-    Property<Integer> timeout();
-
-    /**
-     * Redis password.
-     */
-    @Optional
-    Property<String> password();
-
-    /**
-     * Redis database.
-     *
-     * Defaulted to 0.
-     */
-    @Optional
-    Property<Integer> database();
-
-}
-// END SNIPPET: config
diff --git a/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/RedisMapEntityStoreAssembler.java b/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/RedisMapEntityStoreAssembler.java
deleted file mode 100644
index 3aa83b2..0000000
--- a/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/RedisMapEntityStoreAssembler.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.redis;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-
-/**
- * Redis EntityStore assembly.
- */
-public class RedisMapEntityStoreAssembler
-    extends Assemblers.VisibilityIdentityConfig<RedisMapEntityStoreAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( UuidIdentityGeneratorService.class ).visibleIn( visibility() );
-        ServiceDeclaration service = module.services( RedisMapEntityStoreService.class ).visibleIn( visibility() );
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        if( hasConfig() )
-        {
-            configModule().entities( RedisEntityStoreConfiguration.class ).visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/RedisMapEntityStoreMixin.java b/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/RedisMapEntityStoreMixin.java
deleted file mode 100644
index fe55569..0000000
--- a/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/RedisMapEntityStoreMixin.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.redis;
-
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.Set;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.spi.entitystore.EntityAlreadyExistsException;
-import org.qi4j.spi.entitystore.EntityNotFoundException;
-import org.qi4j.spi.entitystore.EntityStoreException;
-import org.qi4j.spi.entitystore.helpers.MapEntityStore;
-import redis.clients.jedis.Jedis;
-import redis.clients.jedis.JedisPool;
-import redis.clients.jedis.JedisPoolConfig;
-import redis.clients.jedis.Protocol;
-
-/**
- * Redis implementation of MapEntityStore.
- */
-public class RedisMapEntityStoreMixin
-    implements ServiceActivation, RedisAccessors, MapEntityStore
-{
-    private static final String DEFAULT_HOST = "127.0.0.1";
-    private static final String NIL = "nil";
-    @This
-    private Configuration<RedisEntityStoreConfiguration> configuration;
-    private JedisPool pool;
-
-    @Override
-    public void activateService()
-        throws Exception
-    {
-        configuration.refresh();
-        RedisEntityStoreConfiguration config = configuration.get();
-
-        String host = config.host().get() == null ? DEFAULT_HOST : config.host().get();
-        int port = config.port().get() == null ? Protocol.DEFAULT_PORT : config.port().get();
-        int timeout = config.timeout().get() == null ? Protocol.DEFAULT_TIMEOUT : config.timeout().get();
-        String password = config.password().get();
-        int database = config.database().get() == null ? Protocol.DEFAULT_DATABASE : config.database().get();
-
-        pool = new JedisPool( new JedisPoolConfig(), host, port, timeout, password, database );
-    }
-
-    @Override
-    public void passivateService()
-        throws Exception
-    {
-        pool.destroy();
-        pool = null;
-    }
-
-    @Override
-    public JedisPool jedisPool()
-    {
-        return pool;
-    }
-
-    @Override
-    public Reader get( EntityReference entityReference )
-        throws EntityStoreException
-    {
-        Jedis jedis = pool.getResource();
-        try
-        {
-            String jsonState = jedis.get( entityReference.identity() );
-            if( notFound( jsonState ) )
-            {
-                throw new EntityNotFoundException( entityReference );
-            }
-            return new StringReader( jsonState );
-        }
-        finally
-        {
-            pool.returnResource( jedis );
-        }
-    }
-
-    @Override
-    public void applyChanges( MapChanges changes )
-        throws IOException
-    {
-        final Jedis jedis = pool.getResource();
-        try
-        {
-            changes.visitMap( new MapChanger()
-            {
-                @Override
-                public Writer newEntity( final EntityReference ref, EntityDescriptor entityDescriptor )
-                    throws IOException
-                {
-                    return new StringWriter( 1000 )
-                    {
-                        @Override
-                        public void close()
-                            throws IOException
-                        {
-                            super.close();
-                            String statusCode = jedis.set( ref.identity(), toString(), "NX" );
-                            if( !"OK".equals( statusCode ) )
-                            {
-                                throw new EntityAlreadyExistsException( ref );
-                            }
-                        }
-                    };
-                }
-
-                @Override
-                public Writer updateEntity( final EntityReference ref, EntityDescriptor entityDescriptor )
-                    throws IOException
-                {
-                    return new StringWriter( 1000 )
-                    {
-                        @Override
-                        public void close()
-                            throws IOException
-                        {
-                            super.close();
-                            String statusCode = jedis.set( ref.identity(), toString(), "XX" );
-                            if( !"OK".equals( statusCode ) )
-                            {
-                                throw new EntityNotFoundException( ref );
-                            }
-                        }
-                    };
-                }
-
-                @Override
-                public void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor )
-                    throws EntityNotFoundException
-                {
-                    String jsonState = jedis.get( ref.identity() );
-                    if( notFound( jsonState ) )
-                    {
-                        throw new EntityNotFoundException( ref );
-                    }
-                    jedis.del( ref.identity() );
-                }
-            } );
-        }
-        finally
-        {
-            pool.returnResource( jedis );
-        }
-    }
-
-    @Override
-    public Input<Reader, IOException> entityStates()
-    {
-        return new Input<Reader, IOException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super Reader, ReceiverThrowableType> output )
-                throws IOException, ReceiverThrowableType
-            {
-                output.receiveFrom( new Sender<Reader, IOException>()
-                {
-                    @Override
-                    public <ReceiverThrowableType extends Throwable> void sendTo( Receiver<? super Reader, ReceiverThrowableType> receiver )
-                        throws ReceiverThrowableType, IOException
-                    {
-                        Jedis jedis = pool.getResource();
-                        try
-                        {
-                            Set<String> keys = jedis.keys( "*" );
-                            for( String key : keys )
-                            {
-                                String jsonState = jedis.get( key );
-                                receiver.receive( new StringReader( jsonState ) );
-                            }
-                        }
-                        finally
-                        {
-                            pool.returnResource( jedis );
-                        }
-                    }
-                } );
-            }
-        };
-    }
-
-    private static boolean notFound( String jsonState )
-    {
-        return jsonState == null || NIL.equals( jsonState );
-    }
-}
diff --git a/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/RedisMapEntityStoreService.java b/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/RedisMapEntityStoreService.java
deleted file mode 100644
index 0ec6570..0000000
--- a/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/RedisMapEntityStoreService.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.redis;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.library.locking.LockingAbstractComposite;
-import org.qi4j.spi.entitystore.ConcurrentModificationCheckConcern;
-import org.qi4j.spi.entitystore.EntityStateVersions;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.StateChangeNotificationConcern;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreActivation;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreMixin;
-
-/**
- * Redis EntityStore service.
- * <p>Based on @{@link JSONMapEntityStoreMixin}.</p>
- */
-@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
-@Mixins( { JSONMapEntityStoreMixin.class, RedisMapEntityStoreMixin.class } )
-public interface RedisMapEntityStoreService
-        extends EntityStore,
-                EntityStateVersions,
-                ServiceComposite,
-                ServiceActivation,
-                JSONMapEntityStoreActivation,
-                LockingAbstractComposite,
-                Configuration,
-                RedisAccessors
-{
-}
diff --git a/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/package.html b/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/package.html
deleted file mode 100644
index 2f89959..0000000
--- a/extensions/entitystore-redis/src/main/java/org/qi4j/entitystore/redis/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Redis EntityStore.</h2>
-    </body>
-</html>
diff --git a/extensions/entitystore-redis/src/test/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreTest.java b/extensions/entitystore-redis/src/test/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreTest.java
new file mode 100644
index 0000000..e654afc
--- /dev/null
+++ b/extensions/entitystore-redis/src/test/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreTest.java
@@ -0,0 +1,80 @@
+/*
+ *  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.polygene.entitystore.redis;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.redis.assembly.RedisEntityStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+import org.apache.polygene.test.internal.DockerRule;
+import org.junit.ClassRule;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisPool;
+
+public class RedisMapEntityStoreTest
+    extends AbstractEntityStoreTest
+{
+    @ClassRule
+    public static final DockerRule DOCKER = new DockerRule( "redis", 6379 );
+
+    @Override
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // END SNIPPET: assembly
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+        // START SNIPPET: assembly
+        new RedisEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+        // END SNIPPET: assembly
+        RedisEntityStoreConfiguration redisConfig = config.forMixin( RedisEntityStoreConfiguration.class )
+                                                          .declareDefaults();
+        redisConfig.host().set( DOCKER.getDockerHost() );
+        redisConfig.port().set( DOCKER.getExposedContainerPort( "6379/tcp" ) );
+        // START SNIPPET: assembly
+    }
+    // END SNIPPET: assembly
+
+    private JedisPool jedisPool;
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        RedisMapEntityStoreService es = serviceFinder.findService( RedisMapEntityStoreService.class ).get();
+        jedisPool = es.jedisPool();
+    }
+
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        try( Jedis jedis = jedisPool.getResource() )
+        {
+            jedis.flushDB();
+        }
+        super.tearDown();
+    }
+}
diff --git a/extensions/entitystore-redis/src/test/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreWithCacheTest.java b/extensions/entitystore-redis/src/test/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreWithCacheTest.java
new file mode 100644
index 0000000..1dba76a
--- /dev/null
+++ b/extensions/entitystore-redis/src/test/java/org/apache/polygene/entitystore/redis/RedisMapEntityStoreWithCacheTest.java
@@ -0,0 +1,74 @@
+/*
+ *  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.polygene.entitystore.redis;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.redis.assembly.RedisEntityStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.cache.AbstractEntityStoreWithCacheTest;
+import org.apache.polygene.test.internal.DockerRule;
+import org.junit.ClassRule;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisPool;
+
+public class RedisMapEntityStoreWithCacheTest
+    extends AbstractEntityStoreWithCacheTest
+{
+    @ClassRule
+    public static final DockerRule DOCKER = new DockerRule( "redis", 6379 );
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+        new RedisEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+        RedisEntityStoreConfiguration redisConfig = config.forMixin( RedisEntityStoreConfiguration.class )
+                                                          .declareDefaults();
+        redisConfig.host().set( DOCKER.getDockerHost() );
+        redisConfig.port().set( DOCKER.getExposedContainerPort( "6379/tcp" ) );
+    }
+
+    private JedisPool jedisPool;
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        RedisMapEntityStoreService es = serviceFinder.findService( RedisMapEntityStoreService.class ).get();
+        jedisPool = es.jedisPool();
+    }
+
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        try( Jedis jedis = jedisPool.getResource() )
+        {
+            jedis.flushDB();
+        }
+        super.tearDown();
+    }
+}
diff --git a/extensions/entitystore-redis/src/test/java/org/qi4j/entitystore/redis/RedisMapEntityStoreTest.java b/extensions/entitystore-redis/src/test/java/org/qi4j/entitystore/redis/RedisMapEntityStoreTest.java
deleted file mode 100644
index 4340ff6..0000000
--- a/extensions/entitystore-redis/src/test/java/org/qi4j/entitystore/redis/RedisMapEntityStoreTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.redis;
-
-import org.junit.BeforeClass;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-import redis.clients.jedis.Jedis;
-import redis.clients.jedis.JedisPool;
-
-import static org.qi4j.test.util.Assume.assumeConnectivity;
-
-public class RedisMapEntityStoreTest
-    extends AbstractEntityStoreTest
-{
-    @BeforeClass
-    public static void beforeRedisMapEntityStoreTests()
-    {
-        assumeConnectivity( "localhost", 6379 );
-    }
-
-    @Override
-    // START SNIPPET: assembly
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // END SNIPPET: assembly
-        super.assemble( module );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        // START SNIPPET: assembly
-        new RedisMapEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
-    }
-    // END SNIPPET: assembly
-    private JedisPool jedisPool;
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        RedisMapEntityStoreService es = module.findService( RedisMapEntityStoreService.class ).get();
-        jedisPool = es.jedisPool();
-
-    }
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        Jedis jedis = jedisPool.getResource();
-        try
-        {
-            jedis.flushDB();
-        }
-        finally
-        {
-            jedisPool.returnResource( jedis );
-        }
-        super.tearDown();
-    }
-}
diff --git a/extensions/entitystore-redis/src/test/java/org/qi4j/entitystore/redis/RedisMapEntityStoreWithCacheTest.java b/extensions/entitystore-redis/src/test/java/org/qi4j/entitystore/redis/RedisMapEntityStoreWithCacheTest.java
deleted file mode 100644
index ab15743..0000000
--- a/extensions/entitystore-redis/src/test/java/org/qi4j/entitystore/redis/RedisMapEntityStoreWithCacheTest.java
+++ /dev/null
@@ -1,78 +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.qi4j.entitystore.redis;
-
-import org.junit.BeforeClass;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.cache.AbstractEntityStoreWithCacheTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-import redis.clients.jedis.Jedis;
-import redis.clients.jedis.JedisPool;
-
-import static org.qi4j.test.util.Assume.assumeConnectivity;
-
-public class RedisMapEntityStoreWithCacheTest
-    extends AbstractEntityStoreWithCacheTest
-{
-    @BeforeClass
-    public static void beforeRedisMapEntityStoreTests()
-    {
-        assumeConnectivity( "localhost", 6379 );
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        new RedisMapEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
-    }
-
-    private JedisPool jedisPool;
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        RedisMapEntityStoreService es = module.findService( RedisMapEntityStoreService.class ).get();
-        jedisPool = es.jedisPool();
-
-    }
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        Jedis jedis = jedisPool.getResource();
-        try
-        {
-            jedis.flushDB();
-        }
-        finally
-        {
-            jedisPool.returnResource( jedis );
-        }
-        super.tearDown();
-    }
-}
diff --git a/extensions/entitystore-riak/build.gradle b/extensions/entitystore-riak/build.gradle
index ebdef59..98200ac 100644
--- a/extensions/entitystore-riak/build.gradle
+++ b/extensions/entitystore-riak/build.gradle
@@ -1,37 +1,40 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Riak EntityStore Extension"
+apply plugin: 'polygene-extension'
 
-jar { manifest { name = "Apache Zest™ Extension - EntityStore - Riak" } }
+description = "Apache Polygene™ Riak EntityStore Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - EntityStore - Riak" } }
 
 dependencies {
+  api polygene.core.bootstrap
 
-  compile( project( ":org.qi4j.core:org.qi4j.core.bootstrap" ) )
-  compile( project( ":org.qi4j.libraries:org.qi4j.library.locking" ) )
-  compile libraries.slf4j_api
-  compile( libraries.riak )
+  implementation polygene.library( 'locking' )
+  implementation polygene.library( 'constraints' )
+  implementation libraries.riak
 
-  testCompile( project( ":org.qi4j.core:org.qi4j.core.testsupport" ) )
-  testCompile( project( ":org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson" ) )
+  runtimeOnly polygene.core.runtime
 
-  testRuntime( project( ":org.qi4j.core:org.qi4j.core.runtime" ) )
-  testRuntime( libraries.logback )
+  testImplementation polygene.internals.testsupport
+  testImplementation libraries.awaitility
+
+  testRuntimeOnly libraries.logback
 }
-
diff --git a/extensions/entitystore-riak/dev-status.xml b/extensions/entitystore-riak/dev-status.xml
index 169068f..8d582e2 100644
--- a/extensions/entitystore-riak/dev-status.xml
+++ b/extensions/entitystore-riak/dev-status.xml
@@ -1,27 +1,30 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
         <!--none,early,beta,stable,mature-->
-        <codebase>beta</codebase>
+        <codebase>stable</codebase>
 
         <!-- none, brief, good, complete -->
         <documentation>good</documentation>
diff --git a/extensions/entitystore-riak/src/docs/es-riak.txt b/extensions/entitystore-riak/src/docs/es-riak.txt
index 62e3cca..834410a 100644
--- a/extensions/entitystore-riak/src/docs/es-riak.txt
+++ b/extensions/entitystore-riak/src/docs/es-riak.txt
@@ -27,44 +27,34 @@
 
 EntityStore service backed by a http://basho.com/[Riak] bucket.
 
-The EntityStore comes in two flavours: HTTP or ProtocolBuffer based. See the Riak documentation.
+The EntityStore only supports accessing Riak using protocol buffers.
+HTTP is not supported since the 2.x serie of the Riak Java client.
+See the Riak documentation.
 
 include::../../build/docs/buildinfo/artifact.txt[]
 
 == Assembly ==
 
-Assembly is done using the provided Assemblers.
-
-For HTTP based Riak client:
+Assembly is done using the provided Assembler:
 
 [snippet,java]
 ----
-source=extensions/entitystore-riak/src/test/java/org/qi4j/entitystore/riak/RiakHttpMapEntityStoreTest.java
-tag=assembly
-----
-
-For ProtocolBuffer based Riak client:
-
-[snippet,java]
-----
-source=extensions/entitystore-riak/src/test/java/org/qi4j/entitystore/riak/RiakProtobufMapEntityStoreTest.java
+source=extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreTest.java
 tag=assembly
 ----
 
 == Configuration ==
 
-Here are the configuration properties for the HTTP based Riak client:
+Here are the available configuration properties:
 
 [snippet,java]
 ----
-source=extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakHttpEntityStoreConfiguration.java
+source=extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakEntityStoreConfiguration.java
 tag=config
 ----
 
-Here are the configuration properties for the ProtocolBuffer based Riak client:
-
-[snippet,java]
-----
-source=extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakProtobufEntityStoreConfiguration.java
-tag=config
-----
+All authentication related properties are optional.
+By default no authentication is used.
+As soon as you provide a `username`, authentication is set up.
+Please note that you should then at least provide `truststoreType`, `truststorePath` and `truststorePassword`.
+To use client certificate authentication, set `keystoreType`, `keystorePath`, `keystorePassword` and `keyPassword`.
diff --git a/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakAccessors.java b/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakAccessors.java
new file mode 100644
index 0000000..3efef81
--- /dev/null
+++ b/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakAccessors.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.entitystore.riak;
+
+import com.basho.riak.client.api.RiakClient;
+import com.basho.riak.client.core.query.Namespace;
+
+public interface RiakAccessors
+{
+    RiakClient riakClient();
+
+    Namespace riakNamespace();
+}
diff --git a/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakEntityStoreConfiguration.java b/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakEntityStoreConfiguration.java
new file mode 100644
index 0000000..0ed7055
--- /dev/null
+++ b/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakEntityStoreConfiguration.java
@@ -0,0 +1,178 @@
+/*
+ *  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.polygene.entitystore.riak;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.constraints.annotation.OneOf;
+
+import java.util.List;
+
+/**
+ * Configuration for RiakEntityStoreService.
+ */
+// START SNIPPET: config
+public interface RiakEntityStoreConfiguration
+{
+    /**
+     * List of Riak Protocol Buffer hosts.
+     *
+     * Each entry can contain either an IP address / hostname
+     * or an IP address / hostname followed by a column and the host's port.
+     *
+     * Defaulted to 127.0.0.1 if empty.
+     *
+     * @return List of Riak nodes
+     */
+    @UseDefaults
+    Property<List<String>> hosts();
+
+    /**
+     * User name to use for authentication.
+     *
+     * @return Authentication user name
+     */
+    @Optional
+    Property<String> username();
+
+    /**
+     * Password to use for authentication.
+     *
+     * @return Authentication password
+     */
+    @Optional
+    Property<String> password();
+
+    /**
+     * Type of the keystore used for server certificate authentication.
+     *
+     * @return Type of the keystore used for server certificate authentication
+     */
+    @Optional
+    @OneOf( { "PKCS12", "JCEKS", "JKS" } )
+    Property<String> truststoreType();
+
+    /**
+     * Path of the keystore used for server certificate authentication.
+     *
+     * @return Path of the keystore used for server certificate authentication
+     */
+    @Optional
+    Property<String> truststorePath();
+
+    /**
+     * Password of the keystore used for server certificate authentication.
+     *
+     * @return Password of the keystore used for server certificate authentication
+     */
+    @Optional
+    Property<String> truststorePassword();
+
+    /**
+     * Type of the keystore used for client certificate authentication.
+     *
+     * @return Type of the keystore used for client certificate authentication
+     */
+    @Optional
+    @OneOf( { "PKCS12", "JCEKS", "JKS" } )
+    Property<String> keystoreType();
+
+    /**
+     * Path of the keystore used for client certificate authentication.
+     *
+     * @return Path of the keystore used for client certificate authentication
+     */
+    @Optional
+    Property<String> keystorePath();
+
+    /**
+     * Password of the keystore used for client certificate authentication.
+     *
+     * @return Password of the keystore used for client certificate authentication
+     */
+    @Optional
+    Property<String> keystorePassword();
+
+    /**
+     * Password of the key used for client certificate authentication.
+     *
+     * @return Password of the key used for client certificate authentication
+     */
+    @Optional
+    Property<String> keyPassword();
+
+    /**
+     * Riak Bucket where Entities state will be stored.
+     *
+     * Defaulted to "polygene:entities".
+     *
+     * @return Riak bucket name
+     */
+    @UseDefaults( "polygene:entities" )
+    Property<String> bucket();
+
+    /**
+     * Cluster execution attempts.
+     *
+     * @return Cluster execution attempts
+     */
+    @Optional
+    Property<Integer> clusterExecutionAttempts();
+
+    /**
+     * Minimum connections per node.
+     *
+     * @return Minimum connections per node
+     */
+    @Optional
+    Property<Integer> minConnections();
+
+    /**
+     * Maximum connections per node.
+     *
+     * @return Maximum connections per node
+     */
+    @Optional
+    Property<Integer> maxConnections();
+
+    /**
+     * Block on maximum connections.
+     *
+     * @return Block on maximum connections
+     */
+    @UseDefaults
+    Property<Boolean> blockOnMaxConnections();
+
+    /**
+     * Connection timeout.
+     *
+     * @return Connection timeout
+     */
+    @Optional
+    Property<Integer> connectionTimeout();
+
+    /**
+     * Idle timeout.
+     *
+     * @return idle timeout
+     */
+    @Optional
+    Property<Integer> idleTimeout();
+}
+// END SNIPPET: config
diff --git a/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreMixin.java b/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreMixin.java
new file mode 100644
index 0000000..9417df5
--- /dev/null
+++ b/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreMixin.java
@@ -0,0 +1,384 @@
+/*
+ *  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.polygene.entitystore.riak;
+
+import com.basho.riak.client.api.RiakClient;
+import com.basho.riak.client.api.commands.buckets.StoreBucketProperties;
+import com.basho.riak.client.api.commands.kv.DeleteValue;
+import com.basho.riak.client.api.commands.kv.FetchValue;
+import com.basho.riak.client.api.commands.kv.ListKeys;
+import com.basho.riak.client.api.commands.kv.StoreValue;
+import com.basho.riak.client.core.RiakCluster;
+import com.basho.riak.client.core.RiakNode;
+import com.basho.riak.client.core.query.Location;
+import com.basho.riak.client.core.query.Namespace;
+import com.basho.riak.client.core.util.HostAndPort;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.Provider;
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.common.InvalidApplicationException;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.spi.entitystore.EntityNotFoundException;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+import org.apache.polygene.spi.entitystore.helpers.MapEntityStore;
+
+/**
+ * Riak Protobuf implementation of MapEntityStore.
+ */
+public class RiakMapEntityStoreMixin implements ServiceActivation, MapEntityStore, RiakAccessors
+{
+    private static final String DEFAULT_HOST = "127.0.0.1";
+    private static final int DEFAULT_PORT = 8087;
+
+    @This
+    private Configuration<RiakEntityStoreConfiguration> configuration;
+
+    private RiakClient riakClient;
+    private Namespace namespace;
+
+    @Override
+    public void activateService() throws Exception
+    {
+        // Load configuration
+        configuration.refresh();
+        RiakEntityStoreConfiguration config = configuration.get();
+        String bucketName = config.bucket().get();
+        List<String> hosts = config.hosts().get();
+
+        // Setup Riak Cluster Client
+        List<HostAndPort> hostsAndPorts = parseHosts( hosts );
+        RiakNode.Builder nodeBuilder = new RiakNode.Builder();
+        nodeBuilder = configureNodes( config, nodeBuilder );
+        nodeBuilder = configureAuthentication( config, nodeBuilder );
+        List<RiakNode> nodes = new ArrayList<>();
+        for( HostAndPort host : hostsAndPorts )
+        {
+            nodes.add( nodeBuilder.withRemoteAddress( host ).build() );
+        }
+        RiakCluster.Builder clusterBuilder = RiakCluster.builder( nodes );
+        clusterBuilder = configureCluster( config, clusterBuilder );
+
+        // Start Riak Cluster
+        RiakCluster cluster = clusterBuilder.build();
+        cluster.start();
+        namespace = new Namespace( bucketName );
+        riakClient = new RiakClient( cluster );
+
+        // Initialize Bucket
+        riakClient.execute( new StoreBucketProperties.Builder( namespace ).build() );
+    }
+
+    private RiakNode.Builder configureNodes( RiakEntityStoreConfiguration config, RiakNode.Builder nodeBuilder )
+    {
+        Integer minConnections = config.minConnections().get();
+        Integer maxConnections = config.maxConnections().get();
+        Boolean blockOnMaxConnections = config.blockOnMaxConnections().get();
+        Integer connectionTimeout = config.connectionTimeout().get();
+        Integer idleTimeout = config.idleTimeout().get();
+        if( minConnections != null )
+        {
+            nodeBuilder = nodeBuilder.withMinConnections( minConnections );
+        }
+        if( maxConnections != null )
+        {
+            nodeBuilder = nodeBuilder.withMaxConnections( maxConnections );
+        }
+        nodeBuilder = nodeBuilder.withBlockOnMaxConnections( blockOnMaxConnections );
+        if( connectionTimeout != null )
+        {
+            nodeBuilder = nodeBuilder.withConnectionTimeout( connectionTimeout );
+        }
+        if( idleTimeout != null )
+        {
+            nodeBuilder = nodeBuilder.withIdleTimeout( idleTimeout );
+        }
+        return nodeBuilder;
+    }
+
+    private RiakNode.Builder configureAuthentication( RiakEntityStoreConfiguration config,
+                                                      RiakNode.Builder nodeBuilder )
+        throws IOException, GeneralSecurityException
+    {
+        String username = config.username().get();
+        String password = config.password().get();
+        String truststoreType = config.truststoreType().get();
+        String truststorePath = config.truststorePath().get();
+        String truststorePassword = config.truststorePassword().get();
+        String keystoreType = config.keystoreType().get();
+        String keystorePath = config.keystorePath().get();
+        String keystorePassword = config.keystorePassword().get();
+        String keyPassword = config.keyPassword().get();
+        if( username != null )
+        {
+            // Eventually load BouncyCastle to support PKCS12
+            if( "PKCS12".equals( keystoreType ) || "PKCS12".equals( truststoreType ) )
+            {
+                Provider bc = Security.getProvider( "BC" );
+                if( bc == null )
+                {
+                    try
+                    {
+                        Class<?> bcType = Class.forName( "org.bouncycastle.jce.provider.BouncyCastleProvider" );
+                        Security.addProvider( (Provider) bcType.newInstance() );
+                    }
+                    catch( Exception ex )
+                    {
+                        throw new InvalidApplicationException(
+                            "Need to open a PKCS#12 but unable to register BouncyCastle, check your classpath", ex );
+                    }
+                }
+            }
+            KeyStore truststore = loadStore( truststoreType, truststorePath, truststorePassword );
+            if( keystorePath != null )
+            {
+                KeyStore keyStore = loadStore( keystoreType, keystorePath, keystorePassword );
+                nodeBuilder = nodeBuilder.withAuth( username, password, truststore, keyStore, keyPassword );
+            }
+            else
+            {
+                nodeBuilder = nodeBuilder.withAuth( username, password, truststore );
+            }
+        }
+        return nodeBuilder;
+    }
+
+    private KeyStore loadStore( String type, String path, String password )
+        throws IOException, GeneralSecurityException
+    {
+        try( InputStream keystoreInput = new FileInputStream( new File( path ) ) )
+        {
+            KeyStore keyStore = KeyStore.getInstance( type );
+            keyStore.load( keystoreInput, password.toCharArray() );
+            return keyStore;
+        }
+    }
+
+    private RiakCluster.Builder configureCluster( RiakEntityStoreConfiguration config,
+                                                  RiakCluster.Builder clusterBuilder )
+    {
+        Integer clusterExecutionAttempts = config.clusterExecutionAttempts().get();
+        if( clusterExecutionAttempts != null )
+        {
+            clusterBuilder = clusterBuilder.withExecutionAttempts( clusterExecutionAttempts );
+        }
+        return clusterBuilder;
+    }
+
+    @Override
+    public void passivateService() throws Exception
+    {
+        riakClient.shutdown();
+        riakClient = null;
+        namespace = null;
+    }
+
+    @Override
+    public RiakClient riakClient()
+    {
+        return riakClient;
+    }
+
+    @Override
+    public Namespace riakNamespace()
+    {
+        return namespace;
+    }
+
+    @Override
+    public Reader get( EntityReference entityReference )
+    {
+        try
+        {
+            Location location = new Location( namespace, entityReference.identity().toString() );
+            FetchValue fetch = new FetchValue.Builder( location ).build();
+            FetchValue.Response response = riakClient.execute( fetch );
+            if( response.isNotFound() )
+            {
+                throw new EntityNotFoundException( entityReference );
+            }
+            String jsonState = response.getValue( String.class );
+            return new StringReader( jsonState );
+        }
+        catch( InterruptedException | ExecutionException ex )
+        {
+            throw new EntityStoreException( "Unable to get Entity " + entityReference.identity(), ex );
+        }
+    }
+
+    @Override
+    public void applyChanges( MapChanges changes )
+    {
+        try
+        {
+            changes.visitMap( new MapChanger()
+            {
+                @Override
+                public Writer newEntity( EntityReference ref, EntityDescriptor entityDescriptor )
+                {
+                    return new StringWriter( 1000 )
+                    {
+                        @Override
+                        public void close() throws IOException
+                        {
+                            try
+                            {
+                                super.close();
+                                StoreValue store = new StoreValue.Builder( toString() )
+                                    .withLocation( new Location( namespace, ref.identity().toString() ) )
+                                    .build();
+                                riakClient.execute( store );
+                            }
+                            catch( InterruptedException | ExecutionException ex )
+                            {
+                                throw new EntityStoreException( "Unable to apply entity change: newEntity", ex );
+                            }
+                        }
+                    };
+                }
+
+                @Override
+                public Writer updateEntity( MapChange mapChange )
+                {
+                    return new StringWriter( 1000 )
+                    {
+                        @Override
+                        public void close() throws IOException
+                        {
+                            try
+                            {
+                                super.close();
+                                EntityReference reference = mapChange.reference();
+                                Location location = new Location( namespace, reference.identity().toString() );
+                                FetchValue fetch = new FetchValue.Builder( location ).build();
+                                FetchValue.Response response = riakClient.execute( fetch );
+                                if( response.isNotFound() )
+                                {
+                                    throw new EntityNotFoundException( reference );
+                                }
+                                StoreValue store = new StoreValue.Builder( toString() )
+                                    .withLocation( location )
+                                    .build();
+                                riakClient.execute( store );
+                            }
+                            catch( InterruptedException | ExecutionException ex )
+                            {
+                                throw new EntityStoreException( "Unable to apply entity change: updateEntity", ex );
+                            }
+                        }
+                    };
+                }
+
+                @Override
+                public void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor )
+                {
+                    try
+                    {
+                        Location location = new Location( namespace, ref.identity().toString() );
+                        FetchValue fetch = new FetchValue.Builder( location ).build();
+                        FetchValue.Response response = riakClient.execute( fetch );
+                        if( response.isNotFound() )
+                        {
+                            throw new EntityNotFoundException( ref );
+                        }
+                        DeleteValue delete = new DeleteValue.Builder( location ).build();
+                        riakClient.execute( delete );
+                    }
+                    catch( InterruptedException | ExecutionException ex )
+                    {
+                        throw new EntityStoreException( "Unable to apply entity change: removeEntity", ex );
+                    }
+                }
+            } );
+        }
+        catch( Exception ex )
+        {
+            throw new EntityStoreException( "Unable to apply entity changes.", ex );
+        }
+    }
+
+    @Override
+    public Stream<Reader> entityStates()
+    {
+        try
+        {
+            ListKeys listKeys = new ListKeys.Builder( namespace ).build();
+            ListKeys.Response listKeysResponse = riakClient.execute( listKeys );
+            return StreamSupport
+                .stream( listKeysResponse.spliterator(), false )
+                .map( location ->
+                      {
+                          try
+                          {
+                              FetchValue fetch = new FetchValue.Builder( location ).build();
+                              FetchValue.Response response = riakClient.execute( fetch );
+                              return response.getValue( String.class );
+                          }
+                          catch( InterruptedException | ExecutionException ex )
+                          {
+                              throw new EntityStoreException( "Unable to get entity states.", ex );
+                          }
+                      } )
+                .filter( Objects::nonNull )
+                .map( StringReader::new );
+        }
+        catch( InterruptedException | ExecutionException ex )
+        {
+            throw new EntityStoreException( "Unable to get entity states.", ex );
+        }
+    }
+
+    private List<HostAndPort> parseHosts( List<String> hosts )
+    {
+        if( hosts.isEmpty() )
+        {
+            hosts.add( DEFAULT_HOST );
+        }
+        List<HostAndPort> addresses = new ArrayList<>( hosts.size() );
+        for( String host : hosts )
+        {
+            String[] splitted = host.split( ":" );
+            int port = DEFAULT_PORT;
+            if( splitted.length > 1 )
+            {
+                host = splitted[ 0 ];
+                port = Integer.valueOf( splitted[ 1 ] );
+            }
+            addresses.add( HostAndPort.fromParts( host, port ) );
+        }
+        return addresses;
+    }
+}
diff --git a/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreService.java b/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreService.java
new file mode 100644
index 0000000..8965a59
--- /dev/null
+++ b/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreService.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.entitystore.riak;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.library.locking.LockingAbstractComposite;
+import org.apache.polygene.spi.entitystore.ConcurrentModificationCheckConcern;
+import org.apache.polygene.spi.entitystore.EntityStateVersions;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.StateChangeNotificationConcern;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreActivation;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreMixin;
+import org.apache.polygene.spi.entitystore.helpers.MapEntityStoreActivation;
+import org.apache.polygene.spi.entitystore.helpers.MapEntityStoreMixin;
+
+/**
+ * Riak EntityStore service.
+ * <p>Can be used with Riak implementations of MapEntityStore.</p>
+ * <p>Based on {@link JSONMapEntityStoreMixin}</p>
+ */
+@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
+@Mixins( { JSONMapEntityStoreMixin.class, MapEntityStoreMixin.class } )
+public interface RiakMapEntityStoreService
+    extends EntityStore,
+            EntityStateVersions,
+            MapEntityStoreActivation,
+            JSONMapEntityStoreActivation,
+            ServiceActivation,
+            LockingAbstractComposite,
+            Configuration,
+            RiakAccessors
+{
+}
diff --git a/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/assembly/RiakEntityStoreAssembler.java b/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/assembly/RiakEntityStoreAssembler.java
new file mode 100644
index 0000000..8174ed9
--- /dev/null
+++ b/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/assembly/RiakEntityStoreAssembler.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.entitystore.riak.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.entitystore.riak.RiakEntityStoreConfiguration;
+import org.apache.polygene.entitystore.riak.RiakMapEntityStoreMixin;
+import org.apache.polygene.entitystore.riak.RiakMapEntityStoreService;
+
+/**
+ * Riak EntityStore assembly.
+ */
+public class RiakEntityStoreAssembler
+        extends Assemblers.VisibilityIdentityConfig<RiakEntityStoreAssembler>
+{
+    @Override
+    public void assemble(ModuleAssembly module) throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( RiakMapEntityStoreService.class ).
+                withMixins( RiakMapEntityStoreMixin.class ).
+                visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+        if( hasConfig() )
+        {
+            configModule().entities( RiakEntityStoreConfiguration.class ).
+                    visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/package.html b/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/package.html
new file mode 100644
index 0000000..ae4be1b
--- /dev/null
+++ b/extensions/entitystore-riak/src/main/java/org/apache/polygene/entitystore/riak/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Riak EntityStore.</h2>
+    </body>
+</html>
diff --git a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/AbstractRiakMapEntityStore.java b/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/AbstractRiakMapEntityStore.java
deleted file mode 100644
index b8517af..0000000
--- a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/AbstractRiakMapEntityStore.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.riak;
-
-import com.basho.riak.client.IRiakClient;
-import com.basho.riak.client.IRiakObject;
-import com.basho.riak.client.RiakException;
-import com.basho.riak.client.RiakRetryFailedException;
-import com.basho.riak.client.bucket.Bucket;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.spi.entitystore.EntityNotFoundException;
-import org.qi4j.spi.entitystore.EntityStoreException;
-import org.qi4j.spi.entitystore.helpers.MapEntityStore;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Base Riak implementation of MapEntityStore.
- */
-/* package */ abstract class AbstractRiakMapEntityStore
-    implements ServiceActivation, MapEntityStore, RiakAccessors
-{
-
-    protected static final Logger LOGGER = LoggerFactory.getLogger( "org.qi4j.entitystore.riak" );
-    protected static final int DEFAULT_MAX_CONNECTIONS = 50;
-
-    /* package */ static final String DEFAULT_BUCKET_KEY = "qi4j:entities";
-    protected IRiakClient riakClient;
-    protected String bucketKey;
-
-    @Override
-    public void passivateService()
-        throws Exception
-    {
-        riakClient.shutdown();
-        riakClient = null;
-        bucketKey = null;
-    }
-
-    @Override
-    public IRiakClient riakClient()
-    {
-        return riakClient;
-    }
-
-    @Override
-    public String bucket()
-    {
-        return bucketKey;
-    }
-
-    @Override
-    public Reader get( EntityReference entityReference )
-        throws EntityStoreException
-    {
-        try
-        {
-
-            Bucket bucket = riakClient.fetchBucket( bucketKey ).execute();
-            IRiakObject entity = bucket.fetch( entityReference.identity() ).execute();
-            if( entity == null )
-            {
-                throw new EntityNotFoundException( entityReference );
-            }
-            String jsonState = entity.getValueAsString();
-            return new StringReader( jsonState );
-
-        }
-        catch( RiakRetryFailedException ex )
-        {
-            throw new EntityStoreException( "Unable to get Entity " + entityReference.identity(), ex );
-        }
-    }
-
-    @Override
-    public void applyChanges( MapChanges changes )
-        throws IOException
-    {
-        try
-        {
-            final Bucket bucket = riakClient.fetchBucket( bucketKey ).execute();
-
-            changes.visitMap( new MapChanger()
-            {
-
-                @Override
-                public Writer newEntity( final EntityReference ref, EntityDescriptor entityDescriptor )
-                    throws IOException
-                {
-                    return new StringWriter( 1000 )
-                    {
-
-                        @Override
-                        public void close()
-                            throws IOException
-                        {
-                            try
-                            {
-                                super.close();
-                                bucket.store( ref.identity(), toString() ).execute();
-                            }
-                            catch( RiakException ex )
-                            {
-                                throw new EntityStoreException( "Unable to apply entity change: newEntity", ex );
-                            }
-                        }
-
-                    };
-                }
-
-                @Override
-                public Writer updateEntity( final EntityReference ref, EntityDescriptor entityDescriptor )
-                    throws IOException
-                {
-                    return new StringWriter( 1000 )
-                    {
-
-                        @Override
-                        public void close()
-                            throws IOException
-                        {
-                            try
-                            {
-                                super.close();
-                                IRiakObject entity = bucket.fetch( ref.identity() ).execute();
-                                if( entity == null )
-                                {
-                                    throw new EntityNotFoundException( ref );
-                                }
-                                bucket.store( ref.identity(), toString() ).execute();
-                            }
-                            catch( RiakException ex )
-                            {
-                                throw new EntityStoreException( "Unable to apply entity change: updateEntity", ex );
-                            }
-                        }
-
-                    };
-                }
-
-                @Override
-                public void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor )
-                    throws EntityNotFoundException
-                {
-                    try
-                    {
-                        IRiakObject entity = bucket.fetch( ref.identity() ).execute();
-                        if( entity == null )
-                        {
-                            throw new EntityNotFoundException( ref );
-                        }
-                        bucket.delete( ref.identity() ).execute();
-                    }
-                    catch( RiakException ex )
-                    {
-                        throw new EntityStoreException( "Unable to apply entity change: removeEntity", ex );
-                    }
-                }
-
-            } );
-
-        }
-        catch( RiakRetryFailedException ex )
-        {
-            throw new EntityStoreException( "Unable to apply entity changes.", ex );
-        }
-    }
-
-    @Override
-    public Input<Reader, IOException> entityStates()
-    {
-        return new Input<Reader, IOException>()
-        {
-
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super Reader, ReceiverThrowableType> output )
-                throws IOException, ReceiverThrowableType
-            {
-                output.receiveFrom( new Sender<Reader, IOException>()
-                {
-
-                    @Override
-                    public <ReceiverThrowableType extends Throwable> void sendTo( Receiver<? super Reader, ReceiverThrowableType> receiver )
-                        throws ReceiverThrowableType, IOException
-                    {
-                        try
-                        {
-                            final Bucket bucket = riakClient.fetchBucket( bucketKey ).execute();
-                            for( String key : bucket.keys() )
-                            {
-                                String jsonState = bucket.fetch( key ).execute().getValueAsString();
-                                receiver.receive( new StringReader( jsonState ) );
-                            }
-                        }
-                        catch( RiakException ex )
-                        {
-                            throw new EntityStoreException( "Unable to apply entity changes.", ex );
-                        }
-                    }
-
-                } );
-            }
-
-        };
-    }
-
-}
diff --git a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakAccessors.java b/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakAccessors.java
deleted file mode 100644
index ffe56ca..0000000
--- a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakAccessors.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.riak;
-
-import com.basho.riak.client.IRiakClient;
-
-public interface RiakAccessors
-{
-
-    IRiakClient riakClient();
-
-    String bucket();
-
-}
diff --git a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakHttpEntityStoreConfiguration.java b/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakHttpEntityStoreConfiguration.java
deleted file mode 100644
index efc6c6e..0000000
--- a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakHttpEntityStoreConfiguration.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.riak;
-
-import java.util.List;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-/**
- * Configuration for RiakHttpEntityStoreService.
- */
-// START SNIPPET: config
-public interface RiakHttpEntityStoreConfiguration
-        extends ConfigurationComposite
-{
-
-    /**
-     * List of Riak URLs.
-     *
-     * Defaulted to http://127.0.0.1:8098/riak if empty.
-     */
-    @UseDefaults
-    Property<List<String>> urls();
-
-    /**
-     * Riak Bucket where Entities state will be stored.
-     *
-     * Defaulted to "qi4j:entities".
-     */
-    @Optional
-    Property<String> bucket();
-
-    /**
-     * Maximum total connections.
-     *
-     * Defaulted to 50. Use 0 for infinite number of connections.
-     */
-    @Optional
-    Property<Integer> maxConnections();
-
-    /**
-     * The connection, socket read and pooled connection acquisition timeout in milliseconds.
-     *
-     * Defaulted to 0 (infinite).
-     */
-    @UseDefaults
-    Property<Integer> timeout();
-
-}
-// END SNIPPET: config
\ No newline at end of file
diff --git a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakHttpMapEntityStoreAssembler.java b/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakHttpMapEntityStoreAssembler.java
deleted file mode 100644
index 3c42468..0000000
--- a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakHttpMapEntityStoreAssembler.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.riak;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-
-/**
- * Riak Http EntityStore assembly.
- */
-public class RiakHttpMapEntityStoreAssembler
-    extends Assemblers.VisibilityIdentityConfig<RiakHttpMapEntityStoreAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( UuidIdentityGeneratorService.class ).
-            visibleIn( visibility() );
-        ServiceDeclaration service = module.services( RiakMapEntityStoreService.class ).
-            withMixins( RiakHttpMapEntityStoreMixin.class ).
-            visibleIn( visibility() );
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        if( hasConfig() )
-        {
-            configModule().entities( RiakHttpEntityStoreConfiguration.class ).
-                visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakHttpMapEntityStoreMixin.java b/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakHttpMapEntityStoreMixin.java
deleted file mode 100644
index f3e9471..0000000
--- a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakHttpMapEntityStoreMixin.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.riak;
-
-import com.basho.riak.client.RiakFactory;
-import com.basho.riak.client.raw.http.HTTPClientConfig;
-import com.basho.riak.client.raw.http.HTTPClusterConfig;
-import java.util.List;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.This;
-
-/**
- * Riak Http implementation of MapEntityStore.
- */
-public class RiakHttpMapEntityStoreMixin
-    extends AbstractRiakMapEntityStore
-{
-
-    private static final String DEFAULT_URL = "http://127.0.0.1:8098/riak";
-    @This
-    private Configuration<RiakHttpEntityStoreConfiguration> configuration;
-
-    @Override
-    public void activateService()
-        throws Exception
-    {
-        configuration.refresh();
-        RiakHttpEntityStoreConfiguration config = configuration.get();
-
-        int maxConnections = config.maxConnections().get() == null ? DEFAULT_MAX_CONNECTIONS : config.maxConnections().get();
-        int timeoutMillis = config.timeout().get();
-        List<String> urls = config.urls().get();
-        if( urls.isEmpty() )
-        {
-            urls.add( DEFAULT_URL );
-        }
-        bucketKey = config.bucket().get() == null ? DEFAULT_BUCKET_KEY : config.bucket().get();
-
-        HTTPClusterConfig httpClusterConfig = new HTTPClusterConfig( maxConnections );
-        for( String url : urls )
-        {
-            HTTPClientConfig clientConfig = new HTTPClientConfig.Builder().withTimeout( timeoutMillis ).withUrl( url ).build();
-            httpClusterConfig.addClient( clientConfig );
-        }
-        riakClient = RiakFactory.newClient( httpClusterConfig );
-
-        if( !riakClient.listBuckets().contains( bucketKey ) )
-        {
-            riakClient.createBucket( bucketKey ).execute();
-        }
-    }
-
-}
diff --git a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakMapEntityStoreService.java b/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakMapEntityStoreService.java
deleted file mode 100644
index 7707921..0000000
--- a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakMapEntityStoreService.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.riak;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.library.locking.LockingAbstractComposite;
-import org.qi4j.spi.entitystore.ConcurrentModificationCheckConcern;
-import org.qi4j.spi.entitystore.EntityStateVersions;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.StateChangeNotificationConcern;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreActivation;
-import org.qi4j.spi.entitystore.helpers.JSONMapEntityStoreMixin;
-import org.qi4j.spi.entitystore.helpers.MapEntityStoreActivation;
-import org.qi4j.spi.entitystore.helpers.MapEntityStoreMixin;
-
-/**
- * Riak EntityStore service.
- * <p>Can be used with Riak implementations of MapEntityStore.</p>
- * <p>Based on {@link JSONMapEntityStoreMixin}</p>
- */
-@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
-@Mixins( { JSONMapEntityStoreMixin.class, MapEntityStoreMixin.class } )
-public interface RiakMapEntityStoreService
-    extends EntityStore,
-            EntityStateVersions,
-            ServiceComposite,
-            MapEntityStoreActivation,
-            JSONMapEntityStoreActivation,
-            ServiceActivation,
-            LockingAbstractComposite,
-            Configuration,
-            RiakAccessors
-{
-}
diff --git a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakProtobufEntityStoreConfiguration.java b/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakProtobufEntityStoreConfiguration.java
deleted file mode 100644
index 9f5a82f..0000000
--- a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakProtobufEntityStoreConfiguration.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.riak;
-
-import java.util.List;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-/**
- * Configuration for RiakProtobufEntityStore service.
- */
-// START SNIPPET: config
-public interface RiakProtobufEntityStoreConfiguration
-    extends ConfigurationComposite
-{
-
-    /**
-     * List of Riak Protocol Buffer hosts.
-     *
-     * Each entry can contain either an IP address / hostname
-     * or an IP address / hostname followed by a column and the host's port.
-     *
-     * Defaulted to 127.0.0.1 if empty.
-     */
-    @UseDefaults
-    Property<List<String>> hosts();
-
-    /**
-     * Riak Bucket where Entities state will be stored.
-     *
-     * Defaulted to "qi4j:entities".
-     */
-    @Optional
-    Property<String> bucket();
-
-    /**
-     * Maximum total connections.
-     *
-     * Defaulted to 50. Use 0 for infinite number of connections.
-     */
-    @Optional
-    Property<Integer> maxConnections();
-
-    /**
-     * The connection timeout in milliseconds.
-     *
-     * Defaulted to 1000.
-     */
-    @Optional
-    Property<Integer> connectionTimeout();
-
-    /**
-     * Idle connection time to live in milliseconds.
-     *
-     * Defaulted to 1000.
-     */
-    @Optional
-    Property<Integer> idleConnectionTTL();
-
-    /**
-     * Max pool size.
-     *
-     * Defaulted to 0 (unlimited).
-     */
-    @UseDefaults
-    Property<Integer> maxPoolSize();
-
-    /**
-     * Initial pool size.
-     *
-     * Defaulted to 0.
-     */
-    @UseDefaults
-    Property<Integer> initialPoolSize();
-
-    /**
-     * Socket buffer size in KB.
-     *
-     * Defaulted to 16.
-     */
-    @Optional
-    Property<Integer> socketBufferSizeKb();
-
-}
-// END SNIPPET: config
\ No newline at end of file
diff --git a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakProtobufMapEntityStoreAssembler.java b/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakProtobufMapEntityStoreAssembler.java
deleted file mode 100644
index f7e3e77..0000000
--- a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakProtobufMapEntityStoreAssembler.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.riak;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-
-/**
- * Riak Protobuf EntityStore assembly.
- */
-public class RiakProtobufMapEntityStoreAssembler
-    extends Assemblers.VisibilityIdentityConfig<RiakProtobufMapEntityStoreAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( UuidIdentityGeneratorService.class ).
-            visibleIn( visibility() );
-        ServiceDeclaration service = module.services( RiakMapEntityStoreService.class ).
-            withMixins( RiakProtobufMapEntityStoreMixin.class ).
-            visibleIn( visibility() );
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        if( hasConfig() )
-        {
-            configModule().entities( RiakProtobufEntityStoreConfiguration.class ).
-                visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakProtobufMapEntityStoreMixin.java b/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakProtobufMapEntityStoreMixin.java
deleted file mode 100644
index 0de6a5a..0000000
--- a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/RiakProtobufMapEntityStoreMixin.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.riak;
-
-import com.basho.riak.client.RiakFactory;
-import com.basho.riak.client.raw.pbc.PBClientConfig;
-import com.basho.riak.client.raw.pbc.PBClusterConfig;
-import java.util.List;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.This;
-
-/**
- * Riak Protobuf implementation of MapEntityStore.
- */
-public class RiakProtobufMapEntityStoreMixin
-    extends AbstractRiakMapEntityStore
-{
-
-    private static final int DEFAULT_CONNECTION_TIMEOUT = 1000;
-    private static final int DEFAULT_IDLE_CONNECTION_TTL = 1000;
-    private static final int DEFAULT_SOCKET_BUFFER_SIZE_KB = 16;
-    private static final String DEFAULT_HOST = "127.0.0.1";
-    private static final int DEFAULT_PORT = 8087;
-    @This
-    private Configuration<RiakProtobufEntityStoreConfiguration> configuration;
-
-    @Override
-    public void activateService()
-        throws Exception
-    {
-        configuration.refresh();
-        RiakProtobufEntityStoreConfiguration config = configuration.get();
-
-        int maxConnections = config.maxConnections().get() == null ? DEFAULT_MAX_CONNECTIONS : config.maxConnections().get();
-        int connectionTimeout = config.connectionTimeout().get() == null ? DEFAULT_CONNECTION_TIMEOUT : config.connectionTimeout().get();
-        int idleConnectionTTL = config.idleConnectionTTL().get() == null ? DEFAULT_IDLE_CONNECTION_TTL : config.idleConnectionTTL().get();
-        int maxPoolSize = config.maxPoolSize().get();
-        int initialPoolSize = config.initialPoolSize().get();
-        int socketBufferSize = config.socketBufferSizeKb().get() == null ? DEFAULT_SOCKET_BUFFER_SIZE_KB : config.socketBufferSizeKb().get();
-        List<String> hosts = config.hosts().get();
-        if( hosts.isEmpty() )
-        {
-            hosts.add( DEFAULT_HOST );
-        }
-        bucketKey = config.bucket().get() == null ? DEFAULT_BUCKET_KEY : config.bucket().get();
-
-        PBClusterConfig pbClusterConfig = new PBClusterConfig( maxConnections );
-        for( String host : hosts )
-        {
-            String[] splitted = host.split( ":" );
-            int port = DEFAULT_PORT;
-            if( splitted.length > 1 )
-            {
-                host = splitted[0];
-                port = Integer.valueOf( splitted[1] );
-            }
-            PBClientConfig clientConfig = new PBClientConfig.Builder().withConnectionTimeoutMillis( connectionTimeout ).
-                withIdleConnectionTTLMillis( idleConnectionTTL ).
-                withPoolSize( maxPoolSize ).
-                withInitialPoolSize( initialPoolSize ).
-                withSocketBufferSizeKb( socketBufferSize ).
-                withHost( host ).withPort( port ).build();
-            pbClusterConfig.addClient( clientConfig );
-        }
-        riakClient = RiakFactory.newClient( pbClusterConfig );
-
-        if( !riakClient.listBuckets().contains( bucketKey ) )
-        {
-            riakClient.createBucket( bucketKey ).execute();
-        }
-    }
-
-}
diff --git a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/package.html b/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/package.html
deleted file mode 100644
index 9e3ef24..0000000
--- a/extensions/entitystore-riak/src/main/java/org/qi4j/entitystore/riak/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Riak EntityStore.</h2>
-    </body>
-</html>
diff --git a/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakFixture.java b/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakFixture.java
new file mode 100644
index 0000000..4e05602
--- /dev/null
+++ b/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakFixture.java
@@ -0,0 +1,108 @@
+/*
+ *  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.polygene.entitystore.riak;
+
+import com.basho.riak.client.api.RiakClient;
+import com.basho.riak.client.api.commands.kv.DeleteValue;
+import com.basho.riak.client.api.commands.kv.ListKeys;
+import com.basho.riak.client.api.commands.kv.StoreValue;
+import com.basho.riak.client.core.query.Location;
+import com.basho.riak.client.core.query.Namespace;
+import java.time.Instant;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import org.awaitility.Awaitility;
+import org.awaitility.Duration;
+
+class RiakFixture
+{
+    private final RiakClient client;
+    private final Namespace namespace;
+
+    RiakFixture( RiakClient client, Namespace namespace )
+    {
+        this.client = client;
+        this.namespace = namespace;
+    }
+
+    void waitUntilReady()
+    {
+        System.out.println( ">> Riak HealthCheck BEGIN" );
+        Instant start = Instant.now();
+        Awaitility.await()
+                  .pollDelay( Duration.ZERO )
+                  .pollInterval( Duration.ONE_SECOND )
+                  .timeout( Duration.ONE_MINUTE )
+                  .until( new HealthCheck() );
+        System.out.println( ">> Riak HealthCheck END, took " + java.time.Duration.between( start, Instant.now() ) );
+    }
+
+    void deleteTestData() throws ExecutionException, InterruptedException
+    {
+        // Riak doesn't expose bucket deletion in its API so we empty it
+        if( namespace != null )
+        {
+            ListKeys listKeys = new ListKeys.Builder( namespace ).build();
+            ListKeys.Response listKeysResponse = client.execute( listKeys );
+            for( Location location : listKeysResponse )
+            {
+                DeleteValue delete = new DeleteValue.Builder( location ).build();
+                client.execute( delete );
+            }
+        }
+    }
+
+    private class HealthCheck implements Callable<Boolean>
+    {
+        @Override
+        public Boolean call()
+        {
+            boolean inserted = false;
+            boolean deleted = false;
+            Location location = new Location( namespace, "HEALTH_CHECK_ID" );
+            try
+            {
+                StoreValue store = new StoreValue.Builder( "DATA" ).withLocation( location ).build();
+                client.execute( store );
+                inserted = true;
+            }
+            catch( Throwable ex )
+            {
+                ex.printStackTrace();
+                return false;
+            }
+            finally
+            {
+                if( inserted )
+                {
+                    try
+                    {
+                        DeleteValue delete = new DeleteValue.Builder( location ).build();
+                        client.execute( delete );
+                        deleted = true;
+                    }
+                    catch( Throwable ex )
+                    {
+                        ex.printStackTrace();
+                    }
+                }
+            }
+            return inserted && deleted;
+        }
+    }
+}
diff --git a/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreTest.java b/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreTest.java
new file mode 100644
index 0000000..c43d846
--- /dev/null
+++ b/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreTest.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.entitystore.riak;
+
+import java.util.Collections;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.riak.assembly.RiakEntityStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+import org.apache.polygene.test.internal.DockerRule;
+import org.junit.ClassRule;
+
+public class RiakMapEntityStoreTest extends AbstractEntityStoreTest
+{
+    @ClassRule
+    public static final DockerRule DOCKER = new DockerRule( "riak","riak_auth_mods started on node");
+
+    private RiakFixture riakFixture;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        RiakMapEntityStoreService es = serviceFinder.findService( RiakMapEntityStoreService.class ).get();
+        riakFixture = new RiakFixture( es.riakClient(), es.riakNamespace() );
+        riakFixture.waitUntilReady();
+    }
+
+    @Override
+    public void tearDown() throws Exception
+    {
+        riakFixture.deleteTestData();
+        super.tearDown();
+    }
+
+    @Override
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+    {
+        // END SNIPPET: assembly
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+        // START SNIPPET: assembly
+        new RiakEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+        // END SNIPPET: assembly
+        RiakEntityStoreConfiguration riakConfig = config.forMixin( RiakEntityStoreConfiguration.class )
+                                                        .declareDefaults();
+        String host = DOCKER.getDockerHost();
+        int port = DOCKER.getExposedContainerPort( "8087/tcp" );
+        riakConfig.hosts().set( Collections.singletonList( host + ':' + port ) );
+        // START SNIPPET: assembly
+    }
+    // END SNIPPET: assembly
+}
diff --git a/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreWithCacheTest.java b/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreWithCacheTest.java
new file mode 100644
index 0000000..ac4f3ec
--- /dev/null
+++ b/extensions/entitystore-riak/src/test/java/org/apache/polygene/entitystore/riak/RiakMapEntityStoreWithCacheTest.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.entitystore.riak;
+
+import java.util.Collections;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.riak.assembly.RiakEntityStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.cache.AbstractEntityStoreWithCacheTest;
+import org.apache.polygene.test.internal.DockerRule;
+import org.junit.ClassRule;
+
+public class RiakMapEntityStoreWithCacheTest extends AbstractEntityStoreWithCacheTest
+{
+    @ClassRule
+    public static final DockerRule DOCKER = new DockerRule( "riak","riak_auth_mods started on node");
+
+    private RiakFixture riakFixture;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        RiakMapEntityStoreService es = serviceFinder.findService( RiakMapEntityStoreService.class ).get();
+        riakFixture = new RiakFixture( es.riakClient(), es.riakNamespace() );
+        riakFixture.waitUntilReady();
+    }
+
+    @Override
+    public void tearDown() throws Exception
+    {
+        riakFixture.deleteTestData();
+        super.tearDown();
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+        new RiakEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
+        RiakEntityStoreConfiguration riakConfig = config.forMixin( RiakEntityStoreConfiguration.class )
+                                                        .declareDefaults();
+        String host = DOCKER.getDockerHost();
+        int port = DOCKER.getExposedContainerPort( "8087/tcp" );
+        riakConfig.hosts().set( Collections.singletonList( host + ':' + port ) );
+    }
+}
diff --git a/extensions/entitystore-riak/src/test/java/org/qi4j/entitystore/riak/RiakHttpMapEntityStoreTest.java b/extensions/entitystore-riak/src/test/java/org/qi4j/entitystore/riak/RiakHttpMapEntityStoreTest.java
deleted file mode 100644
index 3ab6bd5..0000000
--- a/extensions/entitystore-riak/src/test/java/org/qi4j/entitystore/riak/RiakHttpMapEntityStoreTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.riak;
-
-import com.basho.riak.client.IRiakClient;
-import com.basho.riak.client.bucket.Bucket;
-import org.junit.BeforeClass;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-import static org.qi4j.test.util.Assume.assumeConnectivity;
-
-public class RiakHttpMapEntityStoreTest
-    extends AbstractEntityStoreTest
-{
-    @BeforeClass
-    public static void beforeRiakHttpMapEntityStoreTests()
-    {
-        assumeConnectivity( "localhost", 8087 );
-    }
-
-    @Override
-    // START SNIPPET: assembly
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // END SNIPPET: assembly
-        super.assemble( module );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        // START SNIPPET: assembly
-        new RiakHttpMapEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
-    }
-    // END SNIPPET: assembly
-    private IRiakClient riakClient;
-    private String bucketKey;
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        RiakMapEntityStoreService es = module.findService( RiakMapEntityStoreService.class ).get();
-        riakClient = es.riakClient();
-        bucketKey = es.bucket();
-    }
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        // Riak don't expose bucket deletion in its API so we empty the Zest Entities bucket.
-        Bucket bucket = riakClient.fetchBucket( bucketKey ).execute();
-        for( String key : bucket.keys() )
-        {
-            bucket.delete( key ).execute();
-        }
-        super.tearDown();
-    }
-}
diff --git a/extensions/entitystore-riak/src/test/java/org/qi4j/entitystore/riak/RiakMapEntityStoreWithCacheTest.java b/extensions/entitystore-riak/src/test/java/org/qi4j/entitystore/riak/RiakMapEntityStoreWithCacheTest.java
deleted file mode 100644
index 5a0e6b3..0000000
--- a/extensions/entitystore-riak/src/test/java/org/qi4j/entitystore/riak/RiakMapEntityStoreWithCacheTest.java
+++ /dev/null
@@ -1,76 +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.qi4j.entitystore.riak;
-
-import com.basho.riak.client.IRiakClient;
-import com.basho.riak.client.bucket.Bucket;
-import org.junit.BeforeClass;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.cache.AbstractEntityStoreWithCacheTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-import static org.qi4j.test.util.Assume.assumeConnectivity;
-
-public class RiakMapEntityStoreWithCacheTest
-    extends AbstractEntityStoreWithCacheTest
-{
-    @BeforeClass
-    public static void beforeRiakProtobufMapEntityStoreTests()
-    {
-        assumeConnectivity( "localhost", 8087 );
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        new RiakProtobufMapEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
-    }
-
-    private IRiakClient riakClient;
-    private String bucketKey;
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        RiakMapEntityStoreService es = module.findService( RiakMapEntityStoreService.class ).get();
-        riakClient = es.riakClient();
-        bucketKey = es.bucket();
-    }
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        // Riak don't expose bucket deletion in its API so we empty the Zest Entities bucket.
-        Bucket bucket = riakClient.fetchBucket( bucketKey ).execute();
-        for( String key : bucket.keys() )
-        {
-            bucket.delete( key ).execute();
-        }
-        super.tearDown();
-    }
-}
diff --git a/extensions/entitystore-riak/src/test/java/org/qi4j/entitystore/riak/RiakProtobufMapEntityStoreTest.java b/extensions/entitystore-riak/src/test/java/org/qi4j/entitystore/riak/RiakProtobufMapEntityStoreTest.java
deleted file mode 100644
index ef94011..0000000
--- a/extensions/entitystore-riak/src/test/java/org/qi4j/entitystore/riak/RiakProtobufMapEntityStoreTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.entitystore.riak;
-
-import com.basho.riak.client.IRiakClient;
-import com.basho.riak.client.bucket.Bucket;
-import org.junit.BeforeClass;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-import static org.qi4j.test.util.Assume.assumeConnectivity;
-
-public class RiakProtobufMapEntityStoreTest
-    extends AbstractEntityStoreTest
-{
-    @BeforeClass
-    public static void beforeRiakProtobufMapEntityStoreTests()
-    {
-        assumeConnectivity( "localhost", 8087 );
-    }
-
-    @Override
-    // START SNIPPET: assembly
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // END SNIPPET: assembly
-        super.assemble( module );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        // START SNIPPET: assembly
-        new RiakProtobufMapEntityStoreAssembler().withConfig( config, Visibility.layer ).assemble( module );
-    }
-    // END SNIPPET: assembly
-    private IRiakClient riakClient;
-    private String bucketKey;
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        RiakMapEntityStoreService es = module.findService( RiakMapEntityStoreService.class ).get();
-        riakClient = es.riakClient();
-        bucketKey = es.bucket();
-    }
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        // Riak don't expose bucket deletion in its API so we empty the Zest Entities bucket.
-        Bucket bucket = riakClient.fetchBucket( bucketKey ).execute();
-        for( String key : bucket.keys() )
-        {
-            bucket.delete( key ).execute();
-        }
-        super.tearDown();
-    }
-}
diff --git a/extensions/entitystore-sql/build.gradle b/extensions/entitystore-sql/build.gradle
index f8a0849..223e85b 100644
--- a/extensions/entitystore-sql/build.gradle
+++ b/extensions/entitystore-sql/build.gradle
@@ -1,45 +1,46 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ SQL EntityStore Extension"
+apply plugin: 'polygene-extension'
 
-jar { manifest { name = "Apache Zest™ Extension - EntityStore - SQL" }}
+description = "Apache Polygene™ SQL EntityStore Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - EntityStore - SQL" } }
 
 dependencies {
+  api polygene.core.bootstrap
+  api polygene.library( 'sql' )
+  api libraries.jooq
 
-  compile project(":org.qi4j.core:org.qi4j.core.bootstrap")
-  compile project(":org.qi4j.libraries:org.qi4j.library.sql")
-  compile libraries.javaSqlGenerator
-  compile( libraries.javaSqlGeneratorImpl ) { 
-      exclude group: 'junit'
-  }
+  implementation polygene.library( 'sql-liquibase' )
 
-  testCompile project(":org.qi4j.core:org.qi4j.core.testsupport")
-  testCompile project(":org.qi4j.libraries:org.qi4j.library.sql-dbcp")
-  testCompile(project(":org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson"))
-  testCompile libraries.derby // Needed at compile time for polite test shutdown
+  runtimeOnly polygene.core.runtime
 
-  testRuntime project(":org.qi4j.core:org.qi4j.core.runtime")
-  testRuntime libraries.logback
-  testRuntime libraries.h2
-  testRuntime libraries.mysql_connector
-  testRuntime libraries.postgres
-  testRuntime libraries.sqlite
+  testImplementation polygene.internals.testsupport
+  testImplementation polygene.library( 'sql-dbcp' )
+  testImplementation libraries.docker_junit
 
+  testRuntimeOnly libraries.logback
+  testRuntimeOnly libraries.derby
+  testRuntimeOnly libraries.h2
+  testRuntimeOnly libraries.mysql_connector
+  testRuntimeOnly libraries.postgres
+  testRuntimeOnly libraries.sqlite
 }
diff --git a/extensions/entitystore-sql/dev-status.xml b/extensions/entitystore-sql/dev-status.xml
index 94d633f..8d582e2 100644
--- a/extensions/entitystore-sql/dev-status.xml
+++ b/extensions/entitystore-sql/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
         <!--none,early,beta,stable,mature-->
         <codebase>stable</codebase>
diff --git a/extensions/entitystore-sql/src/docs/es-sql.txt b/extensions/entitystore-sql/src/docs/es-sql.txt
index caa2659..e0328a1 100644
--- a/extensions/entitystore-sql/src/docs/es-sql.txt
+++ b/extensions/entitystore-sql/src/docs/es-sql.txt
@@ -30,6 +30,8 @@
 This extension fully leverage the <<library-sql>> meaning that you must use it to assemble your DataSource and that you
 get <<library-circuitbreaker,Circuit Breaker>> and <<library-jmx, JMX>> integration for free.
 
+The database schema is managed using <<library-sql-liquibase>>.
+
 TIP: See the <<sample-sql-support>> that demonstrate combined use of <<library-sql>>, <<extension-es-sql>> and
 <<extension-indexing-sql>>.
 
@@ -44,15 +46,17 @@
 Each entity state is stored as a single row so maximum number of entities is the maximum number of rows per table
 supported by the underlying SQL database.
 
-Implementations per database Vendor share a generic codebase but can override about everything SQL. As a consequence
-they can have strong differences in terms of performance if they use vendor specific extensions.
-
 include::../../build/docs/buildinfo/artifact.txt[]
 
 == Configuration ==
 
-SQL EntityStore Configuration is optional and provides only one configuration property: `schemaName` defaulted to
-'qi4j_es'. On SQL databases that don't support schemas this configuration property is simply ignored.
+Here are the available configuration properties:
+
+[snippet,java]
+----
+source=extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreConfiguration.java
+tag=config
+----
 
 The assembly snippets below show the DataSource assembly alongside the SQL EntityStore assembly. Remember to configure
 the DataSource properly, see <<library-sql>> and <<howto-configure-service>>.
@@ -66,7 +70,7 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/PostgreSQLEntityStoreTest.java
+source=extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/PostgreSQLEntityStoreTest.java
 tag=assembly
 ----
 
@@ -86,7 +90,7 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/MySQLEntityStoreTest.java
+source=extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MySQLEntityStoreTest.java
 tag=assembly
 ----
 
@@ -109,7 +113,7 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/SQLiteEntityStoreTest.java
+source=extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/SQLiteEntityStoreTest.java
 tag=assembly
 ----
 
@@ -129,7 +133,7 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/H2SQLEntityStoreTest.java
+source=extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/H2SQLEntityStoreTest.java
 tag=assembly
 ----
 
@@ -150,7 +154,7 @@
 
 [snippet,java]
 ----
-source=extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/DerbySQLEntityStoreTest.java
+source=extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/DerbySQLEntityStoreTest.java
 tag=assembly
 ----
 
diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreConfiguration.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreConfiguration.java
new file mode 100644
index 0000000..cd832c0
--- /dev/null
+++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreConfiguration.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.entitystore.sql;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.sql.common.SQLConfiguration;
+
+// START SNIPPET: config
+public interface SQLMapEntityStoreConfiguration extends SQLConfiguration
+{
+    /**
+     * Name of the database schema to use.
+     * Ignored on SQL databases that don't support schemas.
+     */
+    @UseDefaults( "POLYGENE_ES" )
+    @Override
+    Property<String> schemaName();
+
+    /**
+     * Name of the entities table.
+     */
+    @UseDefaults( "POLYGENE_ENTITIES" )
+    Property<String> entityTableName();
+
+    /**
+     * Defines whether the database schema and table should be created if not already present.
+     */
+    @UseDefaults( "true" )
+    Property<Boolean> createIfMissing();
+}
+// END SNIPPET: config
diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreMixin.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreMixin.java
new file mode 100644
index 0000000..682a5f7
--- /dev/null
+++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreMixin.java
@@ -0,0 +1,244 @@
+/*
+ *  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.polygene.entitystore.sql;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import javax.sql.DataSource;
+import liquibase.Contexts;
+import liquibase.Liquibase;
+import liquibase.database.Database;
+import liquibase.database.ObjectQuotingStrategy;
+import liquibase.exception.LiquibaseException;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.library.sql.liquibase.LiquibaseService;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.spi.entitystore.EntityNotFoundException;
+import org.apache.polygene.spi.entitystore.helpers.JSONKeys;
+import org.apache.polygene.spi.entitystore.helpers.MapEntityStore;
+import org.jooq.DSLContext;
+import org.jooq.Field;
+import org.jooq.Query;
+import org.jooq.Record;
+import org.jooq.SQLDialect;
+import org.jooq.Schema;
+import org.jooq.Table;
+import org.jooq.conf.Settings;
+import org.jooq.impl.DSL;
+
+public class SQLMapEntityStoreMixin
+    implements ServiceActivation, MapEntityStore
+{
+    private static final String TABLE_NAME_LIQUIBASE_PARAMETER = "es-sql.table";
+    private static final String IDENTITY_COLUMN_NAME = "ENTITY_IDENTITY";
+    private static final String VERSION_COLUMN_NAME = "ENTITY_VERSION";
+    private static final String STATE_COLUMN_NAME = "ENTITY_STATE";
+
+    @Service
+    private DataSource dataSource;
+
+    @Service
+    private LiquibaseService liquibaseService;
+
+    @Service
+    private JavaxJsonFactories jsonFactories;
+
+    @Uses
+    private ServiceDescriptor descriptor;
+
+    @This
+    private Configuration<SQLMapEntityStoreConfiguration> configuration;
+
+    private Schema schema;
+    private Table<Record> table;
+    private Field<String> identityColumn;
+    private Field<String> versionColumn;
+    private Field<String> stateColumn;
+    private DSLContext dsl;
+
+    @Override
+    public void activateService() throws Exception
+    {
+        configuration.refresh();
+        SQLMapEntityStoreConfiguration config = configuration.get();
+
+        // Prepare jooq DSL
+        SQLDialect dialect = descriptor.metaInfo( SQLDialect.class );
+        Settings settings = descriptor.metaInfo( Settings.class );
+        String schemaName = config.schemaName().get();
+        String tableName = config.entityTableName().get();
+        schema = DSL.schema( DSL.name( schemaName ) );
+        table = DSL.table(
+            dialect.equals( SQLDialect.SQLITE )
+            ? DSL.name( tableName )
+            : DSL.name( schema.getName(), tableName )
+        );
+        identityColumn = DSL.field( DSL.name( IDENTITY_COLUMN_NAME ), String.class );
+        versionColumn = DSL.field( DSL.name( VERSION_COLUMN_NAME ), String.class );
+        stateColumn = DSL.field( DSL.name( STATE_COLUMN_NAME ), String.class );
+        dsl = DSL.using( dataSource, dialect, settings );
+
+        // Eventually create schema and apply Liquibase changelog
+        if( config.createIfMissing().get() )
+        {
+            if( !dialect.equals( SQLDialect.SQLITE )
+                && dsl.meta().getSchemas().stream().noneMatch( s -> schema.getName().equalsIgnoreCase( s.getName() ) ) )
+            {
+                dsl.createSchema( schema ).execute();
+            }
+
+            applyLiquibaseChangelog( dialect );
+        }
+    }
+
+    private void applyLiquibaseChangelog( SQLDialect dialect ) throws SQLException, LiquibaseException
+    {
+        Liquibase liquibase = liquibaseService.newConnectedLiquibase();
+        Database db = liquibase.getDatabase();
+        db.setObjectQuotingStrategy( ObjectQuotingStrategy.QUOTE_ALL_OBJECTS );
+        try
+        {
+            if( !dialect.equals( SQLDialect.SQLITE ) )
+            {
+                if( db.supportsSchemas() )
+                {
+                    db.setDefaultSchemaName( schema.getName() );
+                    db.setLiquibaseSchemaName( schema.getName() );
+                }
+                if( db.supportsCatalogs() )
+                {
+                    db.setDefaultCatalogName( schema.getName() );
+                    db.setLiquibaseCatalogName( schema.getName() );
+                }
+            }
+            liquibase.getChangeLogParameters().set( TABLE_NAME_LIQUIBASE_PARAMETER, table.getName() );
+            liquibase.update( new Contexts() );
+        }
+        finally
+        {
+            db.close();
+        }
+    }
+
+    @Override
+    public void passivateService() throws Exception
+    {
+        dsl = null;
+        schema = null;
+        table = null;
+        identityColumn = null;
+        versionColumn = null;
+        stateColumn = null;
+    }
+
+    @Override
+    public Reader get( EntityReference entityReference )
+    {
+        String state = dsl.select( stateColumn )
+                          .from( table )
+                          .where( identityColumn.equal( entityReference.identity().toString() ) )
+                          .fetchOptional( stateColumn )
+                          .orElseThrow( () -> new EntityNotFoundException( entityReference ) );
+        return new StringReader( state );
+    }
+
+    @Override
+    public Stream<Reader> entityStates()
+    {
+        return dsl.select( stateColumn )
+                  .from( table )
+                  .fetch( stateColumn )
+                  .stream()
+                  .map( StringReader::new );
+    }
+
+    @Override
+    public void applyChanges( MapChanges changes ) throws Exception
+    {
+        List<Query> operations = new ArrayList<>();
+        changes.visitMap( new MapChanger()
+        {
+            @Override
+            public Writer newEntity( EntityReference ref, EntityDescriptor entityDescriptor )
+            {
+                return new StringWriter( 1000 )
+                {
+                    @Override
+                    public void close() throws IOException
+                    {
+                        super.close();
+                        String state = toString();
+                        String version = jsonFactories.readerFactory().createReader( new StringReader( state ) )
+                                                      .readObject()
+                                                      .getString( JSONKeys.VERSION );
+                        operations.add(
+                            dsl.insertInto( table )
+                               .columns( identityColumn, versionColumn, stateColumn )
+                               .values( ref.identity().toString(), version, state )
+                        );
+                    }
+                };
+            }
+
+            @Override
+            public Writer updateEntity( MapChange mapChange )
+            {
+                return new StringWriter( 1000 )
+                {
+                    @Override
+                    public void close() throws IOException
+                    {
+                        super.close();
+                        String state = toString();
+                        operations.add(
+                            dsl.update( table )
+                               .set( versionColumn, mapChange.newVersion() )
+                               .set( stateColumn, state )
+                               .where( identityColumn.equal( mapChange.reference().identity().toString() ) )
+                               .and( versionColumn.equal( mapChange.previousVersion() ) )
+                        );
+                    }
+                };
+            }
+
+            @Override
+            public void removeEntity( EntityReference ref, EntityDescriptor entityDescriptor )
+            {
+                operations.add(
+                    dsl.deleteFrom( table )
+                       .where( identityColumn.equal( ref.identity().toString() ) )
+                );
+            }
+        } );
+        dsl.batch( operations ).execute();
+    }
+}
diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreService.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreService.java
new file mode 100644
index 0000000..341de3b
--- /dev/null
+++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreService.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.entitystore.sql;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.spi.entitystore.ConcurrentModificationCheckConcern;
+import org.apache.polygene.spi.entitystore.EntityStateVersions;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.StateChangeNotificationConcern;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreActivation;
+import org.apache.polygene.spi.entitystore.helpers.JSONMapEntityStoreMixin;
+
+/**
+ * SQL EntityStore service.
+ */
+@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
+@Mixins( { JSONMapEntityStoreMixin.class, SQLMapEntityStoreMixin.class } )
+public interface SQLMapEntityStoreService
+    extends ServiceActivation,
+    JSONMapEntityStoreActivation,
+    EntityStore,
+    EntityStateVersions,
+    Configuration
+{
+}
diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/AbstractSQLMapEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/AbstractSQLMapEntityStoreAssembler.java
new file mode 100644
index 0000000..aac6dfc
--- /dev/null
+++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/AbstractSQLMapEntityStoreAssembler.java
@@ -0,0 +1,97 @@
+/*
+ *  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.polygene.entitystore.sql.assembly;
+
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.sql.SQLMapEntityStoreConfiguration;
+import org.apache.polygene.entitystore.sql.SQLMapEntityStoreService;
+import org.apache.polygene.library.sql.liquibase.LiquibaseAssembler;
+import org.apache.polygene.library.sql.liquibase.LiquibaseConfiguration;
+import org.jooq.SQLDialect;
+import org.jooq.conf.RenderNameStyle;
+import org.jooq.conf.Settings;
+
+/**
+ * Base SQL EntityStore assembly.
+ */
+public abstract class AbstractSQLMapEntityStoreAssembler<AssemblerType>
+    extends Assemblers.VisibilityIdentityConfig<AssemblerType>
+{
+    public static final Identity DEFAULT_ENTITYSTORE_IDENTITY = new StringIdentity( "entitystore-sql" );
+    private static final String DEFAULT_CHANGELOG_PATH = "org/apache/polygene/entitystore/sql/changelog.xml";
+
+    private String changelogPath = DEFAULT_CHANGELOG_PATH;
+
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        SQLDialect dialect = getSQLDialect();
+        if( dialect == null )
+        {
+            throw new AssemblyException( "SQLDialect must not be null" );
+        }
+        Settings settings = getSettings();
+        if( settings == null )
+        {
+            throw new AssemblyException( "Settings must not be null" );
+        }
+
+        String identity = ( hasIdentity() ? identity() : DEFAULT_ENTITYSTORE_IDENTITY ).toString();
+
+        LiquibaseAssembler liquibase = new LiquibaseAssembler().identifiedBy( identity + "-liquibase" );
+        if( hasConfig() )
+        {
+            liquibase.withConfig( configModule(), configVisibility() );
+            LiquibaseConfiguration liquibaseconfig = configModule().forMixin( LiquibaseConfiguration.class )
+                                                                   .declareDefaults();
+            liquibaseconfig.changeLog().set( changelogPath );
+        }
+        liquibase.assemble( module );
+
+        module.services( SQLMapEntityStoreService.class )
+              .identifiedBy( identity )
+              .visibleIn( visibility() )
+              .setMetaInfo( dialect )
+              .setMetaInfo( settings );
+
+        if( hasConfig() )
+        {
+            configModule().entities( SQLMapEntityStoreConfiguration.class ).visibleIn( configVisibility() );
+        }
+    }
+
+    public AssemblerType withLiquibaseChangelog( String changelogPath )
+    {
+        this.changelogPath = changelogPath;
+        return (AssemblerType) this;
+    }
+
+    protected Settings getSettings()
+    {
+        return new Settings().withRenderNameStyle( RenderNameStyle.QUOTED );
+    }
+
+    protected SQLDialect getSQLDialect()
+    {
+        return SQLDialect.DEFAULT;
+    }
+}
diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/DerbySQLEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/DerbySQLEntityStoreAssembler.java
new file mode 100644
index 0000000..6288d85
--- /dev/null
+++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/DerbySQLEntityStoreAssembler.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.entitystore.sql.assembly;
+
+import org.jooq.SQLDialect;
+
+/**
+ * Derby EntityStore assembly.
+ */
+public class DerbySQLEntityStoreAssembler
+    extends AbstractSQLMapEntityStoreAssembler<DerbySQLEntityStoreAssembler>
+{
+    @Override
+    protected SQLDialect getSQLDialect()
+    {
+        return SQLDialect.DERBY;
+    }
+}
diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/H2SQLEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/H2SQLEntityStoreAssembler.java
new file mode 100644
index 0000000..018251e
--- /dev/null
+++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/H2SQLEntityStoreAssembler.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.entitystore.sql.assembly;
+
+import org.jooq.SQLDialect;
+
+/**
+ * H2 EntityStore assembly.
+ */
+public class H2SQLEntityStoreAssembler
+    extends AbstractSQLMapEntityStoreAssembler<H2SQLEntityStoreAssembler>
+{
+    @Override
+    protected SQLDialect getSQLDialect()
+    {
+        return SQLDialect.H2;
+    }
+}
diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/MySQLEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/MySQLEntityStoreAssembler.java
new file mode 100644
index 0000000..ff46c82
--- /dev/null
+++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/MySQLEntityStoreAssembler.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.entitystore.sql.assembly;
+
+import org.jooq.SQLDialect;
+
+/**
+ * MySQL EntityStore assembly.
+ */
+public class MySQLEntityStoreAssembler
+    extends AbstractSQLMapEntityStoreAssembler<MySQLEntityStoreAssembler>
+{
+    @Override
+    protected SQLDialect getSQLDialect()
+    {
+        return SQLDialect.MYSQL;
+    }
+}
diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/PostgreSQLEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/PostgreSQLEntityStoreAssembler.java
new file mode 100644
index 0000000..4400b8e
--- /dev/null
+++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/PostgreSQLEntityStoreAssembler.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.entitystore.sql.assembly;
+
+import org.jooq.SQLDialect;
+
+/**
+ * PostgreSQL EntityStore assembly.
+ */
+public class PostgreSQLEntityStoreAssembler
+    extends AbstractSQLMapEntityStoreAssembler<PostgreSQLEntityStoreAssembler>
+{
+    @Override
+    protected SQLDialect getSQLDialect()
+    {
+        return SQLDialect.POSTGRES;
+    }
+}
diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/SQLEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/SQLEntityStoreAssembler.java
new file mode 100644
index 0000000..1477c6b
--- /dev/null
+++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/SQLEntityStoreAssembler.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.entitystore.sql.assembly;
+
+/**
+ * This is a dummy Assembler to support the Yeoman Polygene Generator, which require naming conventions for
+ * the systems that it supports.
+ */
+public class SQLEntityStoreAssembler extends H2SQLEntityStoreAssembler
+{}
+
diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/SQLiteEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/SQLiteEntityStoreAssembler.java
new file mode 100644
index 0000000..1b7fa5e
--- /dev/null
+++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/SQLiteEntityStoreAssembler.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.entitystore.sql.assembly;
+
+import org.jooq.SQLDialect;
+
+/**
+ * SQLite EntityStore assembly.
+ */
+public class SQLiteEntityStoreAssembler
+    extends AbstractSQLMapEntityStoreAssembler<SQLiteEntityStoreAssembler>
+{
+    @Override
+    protected SQLDialect getSQLDialect()
+    {
+        return SQLDialect.SQLITE;
+    }
+}
diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/package.html b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/package.html
new file mode 100644
index 0000000..a93cf6f
--- /dev/null
+++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL EntityStore Assembly.</h2>
+    </body>
+</html>
diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/package.html b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/package.html
new file mode 100644
index 0000000..a90af3e
--- /dev/null
+++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL EntityStore.</h2>
+    </body>
+</html>
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/SQLEntityStoreMixin.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/SQLEntityStoreMixin.java
deleted file mode 100644
index b57dcf0..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/SQLEntityStoreMixin.java
+++ /dev/null
@@ -1,629 +0,0 @@
-/*
- * Copyright (c) 2010-2012, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2010-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicInteger;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.json.JSONTokener;
-import org.json.JSONWriter;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.cache.CacheOptions;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.service.qualifier.Tagged;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.api.unitofwork.EntityTypeNotFoundException;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.entitystore.sql.internal.DatabaseSQLService;
-import org.qi4j.entitystore.sql.internal.DatabaseSQLService.EntityValueResult;
-import org.qi4j.entitystore.sql.internal.SQLEntityState;
-import org.qi4j.entitystore.sql.internal.SQLEntityState.DefaultSQLEntityState;
-import org.qi4j.functional.Visitor;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.qi4j.spi.Qi4jSPI;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.EntityStatus;
-import org.qi4j.spi.entitystore.DefaultEntityStoreUnitOfWork;
-import org.qi4j.spi.entitystore.EntityNotFoundException;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.EntityStoreException;
-import org.qi4j.spi.entitystore.EntityStoreSPI;
-import org.qi4j.spi.entitystore.EntityStoreUnitOfWork;
-import org.qi4j.spi.entitystore.ModuleEntityStoreUnitOfWork;
-import org.qi4j.spi.entitystore.StateCommitter;
-import org.qi4j.spi.entitystore.helpers.DefaultEntityState;
-import org.qi4j.spi.entitystore.helpers.JSONKeys;
-import org.qi4j.spi.entitystore.helpers.Migration;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-import org.qi4j.spi.module.ModelModule;
-import org.qi4j.spi.module.ModuleSpi;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.map;
-
-/**
- * SQL EntityStore core Mixin.
- */
-// TODO Rewrite reusing JSONMapEntityStoreMixin
-// Old notes:
-//      Most of this code is copy-paste from {@link org.qi4j.spi.entitystore.helpers.MapEntityStoreMixin}.
-//      Refactor stuff that has to do with general things than actual MapEntityStore from MapEntityStoreMixin
-//      so that this class could extend some "AbstractJSONEntityStoreMixin".
-public class SQLEntityStoreMixin
-    implements EntityStore, EntityStoreSPI, StateStore, ServiceActivation
-{
-
-    private static final Logger LOGGER = LoggerFactory.getLogger( SQLEntityStoreMixin.class );
-
-    @Service
-    private DatabaseSQLService database;
-
-    @This
-    private EntityStoreSPI entityStoreSPI;
-
-    @Structure
-    private Qi4jSPI spi;
-
-    @Structure
-    private Application application;
-
-    @Service
-    @Tagged( ValueSerialization.Formats.JSON )
-    private ValueSerialization valueSerialization;
-
-    @Optional
-    @Service
-    private Migration migration;
-
-    private String uuid;
-
-    private final AtomicInteger count = new AtomicInteger();
-
-    @Override
-    public void activateService()
-        throws Exception
-    {
-        uuid = UUID.randomUUID().toString() + "-";
-        count.set( 0 );
-        database.startDatabase();
-    }
-
-    @Override
-    public void passivateService()
-        throws Exception
-    {
-        database.stopDatabase();
-    }
-
-    @Override
-    public StateCommitter applyChanges( final EntityStoreUnitOfWork unitofwork, final Iterable<EntityState> states )
-    {
-        return new StateCommitter()
-        {
-            @Override
-            public void commit()
-            {
-                Connection connection = null;
-                PreparedStatement insertPS = null;
-                PreparedStatement updatePS = null;
-                PreparedStatement removePS = null;
-                try
-                {
-                    connection = database.getConnection();
-                    connection.setAutoCommit( false );
-                    insertPS = database.prepareInsertEntityStatement( connection );
-                    updatePS = database.prepareUpdateEntityStatement( connection );
-                    removePS = database.prepareRemoveEntityStatement( connection );
-                    for( EntityState state : states )
-                    {
-                        EntityStatus status = state.status();
-                        DefaultEntityState defState = ( (SQLEntityState) state ).getDefaultEntityState();
-                        Long entityPK = ( (SQLEntityState) state ).getEntityPK();
-                        if( EntityStatus.REMOVED.equals( status ) )
-                        {
-                            database.populateRemoveEntityStatement( removePS, entityPK, state.identity() );
-                            removePS.addBatch();
-                        }
-                        else
-                        {
-                            StringWriter writer = new StringWriter();
-                            writeEntityState( defState, writer, unitofwork.identity() );
-                            writer.flush();
-                            if( EntityStatus.UPDATED.equals( status ) )
-                            {
-                                Long entityOptimisticLock = ( (SQLEntityState) state ).getEntityOptimisticLock();
-                                database.populateUpdateEntityStatement( updatePS, entityPK, entityOptimisticLock,
-                                                                        defState.identity(), writer.toString(),
-                                                                        unitofwork.currentTime() );
-                                updatePS.addBatch();
-                            }
-                            else if( EntityStatus.NEW.equals( status ) )
-                            {
-                                database.populateInsertEntityStatement( insertPS, defState.identity(),
-                                                                        writer.toString(), unitofwork.currentTime() );
-                                insertPS.addBatch();
-                            }
-                        }
-                    }
-
-                    removePS.executeBatch();
-                    insertPS.executeBatch();
-                    updatePS.executeBatch();
-
-                    connection.commit();
-                }
-                catch( SQLException sqle )
-                {
-                    SQLUtil.rollbackQuietly( connection );
-                    if( LOGGER.isDebugEnabled() )
-                    {
-                        StringWriter sb = new StringWriter();
-                        sb.append(
-                            "SQLException during commit, logging nested exceptions before throwing EntityStoreException:\n" );
-                        SQLException e = sqle;
-                        while( e != null )
-                        {
-                            e.printStackTrace( new PrintWriter( sb, true ) );
-                            e = e.getNextException();
-                        }
-                        LOGGER.debug( sb.toString() );
-                    }
-                    throw new EntityStoreException( sqle );
-                }
-                catch( RuntimeException re )
-                {
-                    SQLUtil.rollbackQuietly( connection );
-                    throw new EntityStoreException( re );
-                }
-                finally
-                {
-                    SQLUtil.closeQuietly( insertPS );
-                    SQLUtil.closeQuietly( updatePS );
-                    SQLUtil.closeQuietly( removePS );
-                    SQLUtil.closeQuietly( connection );
-                }
-            }
-
-            @Override
-            public void cancel()
-            {
-            }
-        };
-    }
-
-    @Override
-    public EntityState entityStateOf( EntityStoreUnitOfWork unitOfWork, ModuleSpi module, EntityReference entityRef )
-    {
-        EntityValueResult valueResult = getValue( entityRef );
-        DefaultEntityState state = readEntityState( module, valueResult.getReader() );
-        return new DefaultSQLEntityState( state, valueResult.getEntityPK(), valueResult.getEntityOptimisticLock() );
-    }
-
-    @Override
-    public EntityState newEntityState( EntityStoreUnitOfWork unitOfWork,
-                                       ModuleSpi module,
-                                       EntityReference entityRef,
-                                       EntityDescriptor entityDescriptor
-    )
-    {
-        return new DefaultSQLEntityState( new DefaultEntityState( unitOfWork.currentTime(), entityRef, entityDescriptor ) );
-    }
-
-    @Override
-    public EntityStoreUnitOfWork newUnitOfWork( Usecase usecase, ModuleSpi module, long currentTime )
-    {
-        EntityStoreUnitOfWork storeUnitOfWork =
-            new DefaultEntityStoreUnitOfWork( entityStoreSPI, newUnitOfWorkId(), usecase, currentTime );
-        storeUnitOfWork = new ModuleEntityStoreUnitOfWork( module, storeUnitOfWork );
-        return storeUnitOfWork;
-    }
-
-    @Override
-    public Input<EntityState, EntityStoreException> entityStates( final ModuleSpi module )
-    {
-        return new Input<EntityState, EntityStoreException>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super EntityState, ReceiverThrowableType> output )
-                throws EntityStoreException, ReceiverThrowableType
-            {
-                output.receiveFrom( new Sender<EntityState, EntityStoreException>()
-                {
-                    @Override
-                    public <ReceiverThrowableType extends Throwable> void sendTo( final Receiver<? super EntityState, ReceiverThrowableType> receiver )
-                        throws ReceiverThrowableType, EntityStoreException
-                    {
-                        queryAllEntities( module, new EntityStatesVisitor()
-                        {
-                            @Override
-                            public boolean visit( EntityState visited )
-                                throws SQLException
-                            {
-                                try
-                                {
-                                    receiver.receive( visited );
-                                }
-                                catch( Throwable receiverThrowableType )
-                                {
-                                    throw new SQLException( receiverThrowableType );
-                                }
-                                return true;
-                            }
-                        } );
-                    }
-                } );
-            }
-        };
-    }
-
-    private void queryAllEntities( ModuleSpi module, EntityStatesVisitor entityStatesVisitor )
-    {
-        Connection connection = null;
-        PreparedStatement ps = null;
-        ResultSet rs = null;
-        UsecaseBuilder builder = UsecaseBuilder.buildUsecase( "qi4j.entitystore.sql.visit" );
-        Usecase usecase = builder.withMetaInfo( CacheOptions.NEVER ).newUsecase();
-        final ModuleEntityStoreUnitOfWork uow =
-            (ModuleEntityStoreUnitOfWork) newUnitOfWork( usecase, module, System.currentTimeMillis() );
-        try
-        {
-            connection = database.getConnection();
-            ps = database.prepareGetAllEntitiesStatement( connection );
-            database.populateGetAllEntitiesStatement( ps );
-            rs = ps.executeQuery();
-            while( rs.next() )
-            {
-                DefaultEntityState entityState = readEntityState( module, database.getEntityValue( rs ).getReader() );
-                if( !entityStatesVisitor.visit( entityState ) )
-                {
-                    return;
-                }
-            }
-        }
-        catch( SQLException ex )
-        {
-            throw new EntityStoreException( ex );
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( rs );
-            SQLUtil.closeQuietly( ps );
-            SQLUtil.closeQuietly( connection );
-        }
-    }
-
-    private interface EntityStatesVisitor
-        extends Visitor<EntityState, SQLException>
-    {
-    }
-
-    protected String newUnitOfWorkId()
-    {
-        return uuid + Integer.toHexString( count.incrementAndGet() );
-    }
-
-    protected DefaultEntityState readEntityState( ModuleSpi module, Reader entityState )
-        throws EntityStoreException
-    {
-        try
-        {
-            JSONObject jsonObject = new JSONObject( new JSONTokener( entityState ) );
-            EntityStatus status = EntityStatus.LOADED;
-
-            String version = jsonObject.getString( JSONKeys.VERSION );
-            long modified = jsonObject.getLong( JSONKeys.MODIFIED );
-            String identity = jsonObject.getString( JSONKeys.IDENTITY );
-
-            // Check if version is correct
-            String currentAppVersion = jsonObject.optString( JSONKeys.APPLICATION_VERSION, "0.0" );
-            if( !currentAppVersion.equals( application.version() ) )
-            {
-                if( migration != null )
-                {
-                    migration.migrate( jsonObject, application.version(), this );
-                }
-                else
-                {
-                    // Do nothing - set version to be correct
-                    jsonObject.put( JSONKeys.APPLICATION_VERSION, application.version() );
-                }
-
-                LOGGER.trace( "Updated version nr on {} from {} to {}",
-                              identity, currentAppVersion, application.version() );
-
-                // State changed
-                status = EntityStatus.UPDATED;
-            }
-
-            String type = jsonObject.getString( JSONKeys.TYPE );
-
-            EntityDescriptor entityDescriptor = module.entityDescriptor( type );
-            if( entityDescriptor == null )
-            {
-                throw new EntityTypeNotFoundException( type,
-                                                       module.name(),
-                                                       map( ModelModule.toStringFunction,
-                                                            module.findVisibleEntityTypes()
-                                                       ) );
-            }
-
-            Map<QualifiedName, Object> properties = new HashMap<>();
-            JSONObject props = jsonObject.getJSONObject( JSONKeys.PROPERTIES );
-            for( PropertyDescriptor propertyDescriptor : entityDescriptor.state().properties() )
-            {
-                Object jsonValue;
-                try
-                {
-                    jsonValue = props.get( propertyDescriptor.qualifiedName().name() );
-                }
-                catch( JSONException e )
-                {
-                    // Value not found, default it
-                    Object initialValue = propertyDescriptor.initialValue( module );
-                    properties.put( propertyDescriptor.qualifiedName(), initialValue );
-                    status = EntityStatus.UPDATED;
-                    continue;
-                }
-                if( JSONObject.NULL.equals( jsonValue ) )
-                {
-                    properties.put( propertyDescriptor.qualifiedName(), null );
-                }
-                else
-                {
-                    Object value = valueSerialization.deserialize( propertyDescriptor.valueType(), jsonValue.toString() );
-                    properties.put( propertyDescriptor.qualifiedName(), value );
-                }
-            }
-
-            Map<QualifiedName, EntityReference> associations = new HashMap<>();
-            JSONObject assocs = jsonObject.getJSONObject( JSONKeys.ASSOCIATIONS );
-            for( AssociationDescriptor associationType : entityDescriptor.state().associations() )
-            {
-                try
-                {
-                    Object jsonValue = assocs.get( associationType.qualifiedName().name() );
-                    EntityReference value = jsonValue == JSONObject.NULL ? null : EntityReference.parseEntityReference(
-                        (String) jsonValue );
-                    associations.put( associationType.qualifiedName(), value );
-                }
-                catch( JSONException e )
-                {
-                    // Association not found, default it to null
-                    associations.put( associationType.qualifiedName(), null );
-                    status = EntityStatus.UPDATED;
-                }
-            }
-
-            JSONObject manyAssocs = jsonObject.getJSONObject( JSONKeys.MANY_ASSOCIATIONS );
-            Map<QualifiedName, List<EntityReference>> manyAssociations = new HashMap<>();
-            for( AssociationDescriptor manyAssociationType : entityDescriptor.state().manyAssociations() )
-            {
-                List<EntityReference> references = new ArrayList<>();
-                try
-                {
-                    JSONArray jsonValues = manyAssocs.getJSONArray( manyAssociationType.qualifiedName().name() );
-                    for( int i = 0; i < jsonValues.length(); i++ )
-                    {
-                        Object jsonValue = jsonValues.getString( i );
-                        EntityReference value = jsonValue == JSONObject.NULL ? null : EntityReference.parseEntityReference(
-                            (String) jsonValue );
-                        references.add( value );
-                    }
-                    manyAssociations.put( manyAssociationType.qualifiedName(), references );
-                }
-                catch( JSONException e )
-                {
-                    // ManyAssociation not found, default to empty one
-                    manyAssociations.put( manyAssociationType.qualifiedName(), references );
-                }
-            }
-
-            JSONObject namedAssocs = jsonObject.has( JSONKeys.NAMED_ASSOCIATIONS )
-                                     ? jsonObject.getJSONObject( JSONKeys.NAMED_ASSOCIATIONS )
-                                     : new JSONObject();
-            Map<QualifiedName, Map<String, EntityReference>> namedAssociations = new HashMap<>();
-            for( AssociationDescriptor namedAssociationType : entityDescriptor.state().namedAssociations() )
-            {
-                Map<String, EntityReference> references = new LinkedHashMap<>();
-                try
-                {
-                    JSONObject jsonValues = namedAssocs.getJSONObject( namedAssociationType.qualifiedName().name() );
-                    JSONArray names = jsonValues.names();
-                    if( names != null )
-                    {
-                        for( int idx = 0; idx < names.length(); idx++ )
-                        {
-                            String name = names.getString( idx );
-                            String jsonValue = jsonValues.getString( name );
-                            references.put( name, EntityReference.parseEntityReference( jsonValue ) );
-                        }
-                    }
-                    namedAssociations.put( namedAssociationType.qualifiedName(), references );
-                }
-                catch( JSONException e )
-                {
-                    // NamedAssociation not found, default to empty one
-                    namedAssociations.put( namedAssociationType.qualifiedName(), references );
-                }
-            }
-
-            return new DefaultEntityState( version, modified,
-                                           EntityReference.parseEntityReference( identity ), status, entityDescriptor,
-                                           properties, associations, manyAssociations, namedAssociations );
-        }
-        catch( JSONException e )
-        {
-            throw new EntityStoreException( e );
-        }
-    }
-
-    @Override
-    public JSONObject jsonStateOf( String id )
-        throws IOException
-    {
-        JSONObject jsonObject;
-        try (Reader reader = getValue( EntityReference.parseEntityReference( id ) ).getReader())
-        {
-            jsonObject = new JSONObject( new JSONTokener( reader ) );
-        }
-        catch( JSONException e )
-        {
-            throw new IOException( e );
-        }
-        return jsonObject;
-    }
-
-    protected EntityValueResult getValue( EntityReference ref )
-    {
-        Connection connection = null;
-        PreparedStatement ps = null;
-        ResultSet rs = null;
-        try
-        {
-            connection = database.getConnection();
-            ps = database.prepareGetEntityStatement( connection );
-            database.populateGetEntityStatement( ps, ref );
-            rs = ps.executeQuery();
-            if( !rs.next() )
-            {
-                throw new EntityNotFoundException( ref );
-            }
-            return database.getEntityValue( rs );
-        }
-        catch( SQLException sqle )
-        {
-            throw new EntityStoreException( "Unable to get Entity " + ref, sqle );
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( rs );
-            SQLUtil.closeQuietly( ps );
-            SQLUtil.closeQuietly( connection );
-        }
-    }
-
-    protected void writeEntityState( DefaultEntityState state, Writer writer, String version )
-        throws EntityStoreException
-    {
-        try
-        {
-            JSONWriter json = new JSONWriter( writer );
-            JSONWriter properties = json.object().
-                key( JSONKeys.IDENTITY ).value( state.identity().identity() ).
-                key( JSONKeys.APPLICATION_VERSION ).value( application.version() ).
-                key( JSONKeys.TYPE ).value( first( state.entityDescriptor().types() ).getName() ).
-                key( JSONKeys.VERSION ).value( version ).
-                key( JSONKeys.MODIFIED ).value( state.lastModified() ).
-                key( JSONKeys.PROPERTIES ).object();
-
-            for( PropertyDescriptor persistentProperty : state.entityDescriptor().state().properties() )
-            {
-                Object value = state.properties().get( persistentProperty.qualifiedName() );
-                json.key( persistentProperty.qualifiedName().name() );
-                if( value == null || ValueType.isPrimitiveValue( value ) )
-                {
-                    json.value( value );
-                }
-                else
-                {
-                    String serialized = valueSerialization.serialize( value );
-                    if( serialized.startsWith( "{" ) )
-                    {
-                        json.value( new JSONObject( serialized ) );
-                    }
-                    else if( serialized.startsWith( "[" ) )
-                    {
-                        json.value( new JSONArray( serialized ) );
-                    }
-                    else
-                    {
-                        json.value( serialized );
-                    }
-                }
-            }
-
-            JSONWriter associations = properties.endObject().key( JSONKeys.ASSOCIATIONS ).object();
-            for( Map.Entry<QualifiedName, EntityReference> stateNameEntityReferenceEntry : state.associations()
-                .entrySet() )
-            {
-                EntityReference value = stateNameEntityReferenceEntry.getValue();
-                associations.key( stateNameEntityReferenceEntry.getKey().name() ).
-                    value( value != null ? value.identity() : null );
-            }
-
-            JSONWriter manyAssociations = associations.endObject().key( JSONKeys.MANY_ASSOCIATIONS ).object();
-            for( Map.Entry<QualifiedName, List<EntityReference>> stateNameListEntry : state.manyAssociations()
-                .entrySet() )
-            {
-                JSONWriter assocs = manyAssociations.key( stateNameListEntry.getKey().name() ).array();
-                for( EntityReference entityReference : stateNameListEntry.getValue() )
-                {
-                    assocs.value( entityReference.identity() );
-                }
-                assocs.endArray();
-            }
-
-            JSONWriter namedAssociations = manyAssociations.endObject().key( JSONKeys.NAMED_ASSOCIATIONS ).object();
-            for( Map.Entry<QualifiedName, Map<String, EntityReference>> stateNameMapEntry : state.namedAssociations()
-                .entrySet() )
-            {
-                JSONWriter assocs = namedAssociations.key( stateNameMapEntry.getKey().name() ).object();
-                for( Map.Entry<String, EntityReference> entry : stateNameMapEntry.getValue().entrySet() )
-                {
-                    assocs.key( entry.getKey() ).value( entry.getValue().identity() );
-                }
-                assocs.endObject();
-            }
-            namedAssociations.endObject().endObject();
-        }
-        catch( JSONException e )
-        {
-            throw new EntityStoreException( "Could not store EntityState", e );
-        }
-    }
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/SQLEntityStoreService.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/SQLEntityStoreService.java
deleted file mode 100644
index 9e3eb3b..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/SQLEntityStoreService.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.spi.entitystore.ConcurrentModificationCheckConcern;
-import org.qi4j.spi.entitystore.EntityStateVersions;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.StateChangeNotificationConcern;
-
-/**
- * SQL EntityStore service.
- */
-@Concerns( { StateChangeNotificationConcern.class, ConcurrentModificationCheckConcern.class } )
-@Mixins( { SQLEntityStoreMixin.class } )
-public interface SQLEntityStoreService
-    extends EntityStore, EntityStateVersions, ServiceComposite, ServiceActivation
-{
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/AbstractSQLEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/AbstractSQLEntityStoreAssembler.java
deleted file mode 100644
index 09ffc39..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/AbstractSQLEntityStoreAssembler.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql.assembly;
-
-import java.io.IOException;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.sql.SQLEntityStoreService;
-import org.qi4j.entitystore.sql.internal.DatabaseSQLService.DatabaseSQLServiceComposite;
-import org.qi4j.entitystore.sql.internal.DatabaseSQLServiceCoreMixin;
-import org.qi4j.entitystore.sql.internal.DatabaseSQLServiceSpi;
-import org.qi4j.entitystore.sql.internal.DatabaseSQLServiceStatementsMixin;
-import org.qi4j.entitystore.sql.internal.DatabaseSQLStringsBuilder;
-import org.qi4j.library.sql.common.SQLConfiguration;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.sql.generation.api.vendor.SQLVendor;
-import org.sql.generation.api.vendor.SQLVendorProvider;
-
-/**
- * Base SQL EntityStore assembly.
- */
-@SuppressWarnings( "unchecked" )
-abstract class AbstractSQLEntityStoreAssembler<AssemblerType>
-    extends Assemblers.VisibilityIdentityConfig<AssemblerType>
-{
-
-    public static final String DEFAULT_ENTITYSTORE_IDENTITY = "entitystore-sql";
-
-    protected SQLVendor getSQLVendor()
-        throws IOException
-    {
-        return SQLVendorProvider.createVendor( SQLVendor.class );
-    }
-
-    protected Class<?> getDatabaseStringBuilderMixin()
-    {
-        return DatabaseSQLStringsBuilder.CommonMixin.class;
-    }
-
-    protected abstract Class<?> getDatabaseSQLServiceSpecializationMixin();
-
-    @Override
-    public final void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        try
-        {
-            SQLVendor sqlVendor = this.getSQLVendor();
-            if( sqlVendor == null )
-            {
-                throw new AssemblyException( "SQL Vendor could not be determined." );
-            }
-            module.services( DatabaseSQLServiceComposite.class ).
-                withMixins( DatabaseSQLServiceCoreMixin.class,
-                            DatabaseSQLServiceSpi.CommonMixin.class,
-                            getDatabaseStringBuilderMixin(),
-                            DatabaseSQLServiceStatementsMixin.class,
-                            getDatabaseSQLServiceSpecializationMixin() ).
-                identifiedBy( hasIdentity() ? identity() : DEFAULT_ENTITYSTORE_IDENTITY ).
-                visibleIn( Visibility.module ).
-                setMetaInfo( sqlVendor );
-        }
-        catch( IOException ioe )
-        {
-            throw new AssemblyException( ioe );
-        }
-        module.services( SQLEntityStoreService.class,
-                         UuidIdentityGeneratorService.class ).
-            visibleIn( visibility() );
-        if( hasConfig() )
-        {
-            configModule().entities( SQLConfiguration.class ).
-                visibleIn( configVisibility() );
-        }
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/DerbySQLEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/DerbySQLEntityStoreAssembler.java
deleted file mode 100644
index 4518024..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/DerbySQLEntityStoreAssembler.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*

- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.

- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.

- *

- * Licensed 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.qi4j.entitystore.sql.assembly;

-

-import java.io.IOException;

-import org.qi4j.entitystore.sql.internal.DerbySQLDatabaseSQLServiceMixin;

-import org.sql.generation.api.vendor.DerbyVendor;

-import org.sql.generation.api.vendor.SQLVendor;

-import org.sql.generation.api.vendor.SQLVendorProvider;

-

-/**

- * Derby EntityStore assembly.

- */

-public class DerbySQLEntityStoreAssembler

-        extends AbstractSQLEntityStoreAssembler<DerbySQLEntityStoreAssembler>

-{

-

-    @Override

-    protected Class<?> getDatabaseSQLServiceSpecializationMixin()

-    {

-        return DerbySQLDatabaseSQLServiceMixin.class;

-    }

-

-    @Override

-    protected SQLVendor getSQLVendor()

-            throws IOException

-    {

-        return SQLVendorProvider.createVendor( DerbyVendor.class );

-    }

-

-}

diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/H2SQLEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/H2SQLEntityStoreAssembler.java
deleted file mode 100644
index cad982a..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/H2SQLEntityStoreAssembler.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.entitystore.sql.assembly;
-
-import java.io.IOException;
-import org.qi4j.entitystore.sql.internal.H2SQLDatabaseSQLServiceMixin;
-import org.sql.generation.api.vendor.H2Vendor;
-import org.sql.generation.api.vendor.SQLVendor;
-import org.sql.generation.api.vendor.SQLVendorProvider;
-
-/**
- * H2 EntityStore assembly.
- */
-public class H2SQLEntityStoreAssembler
-        extends AbstractSQLEntityStoreAssembler<H2SQLEntityStoreAssembler>
-{
-
-    @Override
-    protected Class<?> getDatabaseSQLServiceSpecializationMixin()
-    {
-        return H2SQLDatabaseSQLServiceMixin.class;
-    }
-
-    @Override
-    protected SQLVendor getSQLVendor()
-            throws IOException
-    {
-        return SQLVendorProvider.createVendor( H2Vendor.class );
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/MySQLEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/MySQLEntityStoreAssembler.java
deleted file mode 100644
index 9d05e82..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/MySQLEntityStoreAssembler.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql.assembly;
-
-import java.io.IOException;
-import org.qi4j.entitystore.sql.internal.MySQLDatabaseSQLServiceMixin;
-import org.sql.generation.api.vendor.MySQLVendor;
-import org.sql.generation.api.vendor.SQLVendor;
-import org.sql.generation.api.vendor.SQLVendorProvider;
-
-/**
- * MySQL EntityStore assembly.
- */
-public class MySQLEntityStoreAssembler
-        extends AbstractSQLEntityStoreAssembler<MySQLEntityStoreAssembler>
-{
-
-    @Override
-    protected Class<?> getDatabaseSQLServiceSpecializationMixin()
-    {
-        return MySQLDatabaseSQLServiceMixin.class;
-    }
-
-    @Override
-    protected SQLVendor getSQLVendor()
-            throws IOException
-    {
-        return SQLVendorProvider.createVendor( MySQLVendor.class );
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/PostgreSQLEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/PostgreSQLEntityStoreAssembler.java
deleted file mode 100644
index d15cf02..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/PostgreSQLEntityStoreAssembler.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql.assembly;
-
-import java.io.IOException;
-import org.qi4j.entitystore.sql.internal.PostgreSQLDatabaseSQLServiceMixin;
-import org.qi4j.entitystore.sql.internal.PostgreSQLStringBuilderMixin;
-import org.sql.generation.api.vendor.PostgreSQLVendor;
-import org.sql.generation.api.vendor.SQLVendor;
-import org.sql.generation.api.vendor.SQLVendorProvider;
-
-/**
- * PostgreSQL EntityStore assembly.
- */
-public class PostgreSQLEntityStoreAssembler
-        extends AbstractSQLEntityStoreAssembler<PostgreSQLEntityStoreAssembler>
-{
-
-    @Override
-    protected Class<?> getDatabaseSQLServiceSpecializationMixin()
-    {
-        return PostgreSQLDatabaseSQLServiceMixin.class;
-    }
-
-    @Override
-    protected Class<?> getDatabaseStringBuilderMixin()
-    {
-        return PostgreSQLStringBuilderMixin.class;
-    }
-
-    @Override
-    protected SQLVendor getSQLVendor()
-            throws IOException
-    {
-        return SQLVendorProvider.createVendor( PostgreSQLVendor.class );
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/SQLiteEntityStoreAssembler.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/SQLiteEntityStoreAssembler.java
deleted file mode 100644
index 3201b24..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/SQLiteEntityStoreAssembler.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.entitystore.sql.assembly;
-
-import java.io.IOException;
-import org.qi4j.entitystore.sql.internal.SQLiteDatabaseSQLServiceMixin;
-import org.sql.generation.api.vendor.SQLVendor;
-import org.sql.generation.api.vendor.SQLVendorProvider;
-import org.sql.generation.api.vendor.SQLiteVendor;
-
-/**
- * SQLite EntityStore assembly.
- */
-public class SQLiteEntityStoreAssembler
-        extends AbstractSQLEntityStoreAssembler<SQLiteEntityStoreAssembler>
-{
-
-    @Override
-    protected Class<?> getDatabaseSQLServiceSpecializationMixin()
-    {
-        return SQLiteDatabaseSQLServiceMixin.class;
-    }
-
-    @Override
-    protected SQLVendor getSQLVendor()
-            throws IOException
-    {
-        return SQLVendorProvider.createVendor( SQLiteVendor.class );
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/package.html b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/package.html
deleted file mode 100644
index 09579ad..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/assembly/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL EntityStore Assembly.</h2>
-    </body>
-</html>
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLService.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLService.java
deleted file mode 100644
index cdbbe0f..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLService.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql.internal;
-
-import java.io.Reader;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.service.ServiceComposite;
-
-@SuppressWarnings( "PublicInnerClass" )
-public interface DatabaseSQLService
-{
-
-    public interface DatabaseSQLServiceComposite
-        extends DatabaseSQLService, ServiceComposite
-    {
-    }
-
-    public final class EntityValueResult
-    {
-
-        private final Long entityPK;
-
-        private final Long entityOptimisticLock;
-
-        private final Reader reader;
-
-        public EntityValueResult( Long entityPK, Long entityOptimisticLock, Reader reader )
-        {
-            this.entityPK = entityPK;
-            this.entityOptimisticLock = entityOptimisticLock;
-            this.reader = reader;
-        }
-
-        /**
-         * @return the entityPK
-         */
-        public Long getEntityPK()
-        {
-            return entityPK;
-        }
-
-        /**
-         * @return the entityOptimisticLock
-         */
-        public Long getEntityOptimisticLock()
-        {
-            return entityOptimisticLock;
-        }
-
-        /**
-         * @return the reader
-         */
-        public Reader getReader()
-        {
-            return reader;
-        }
-
-    }
-
-    void startDatabase()
-        throws Exception;
-
-    void stopDatabase()
-        throws Exception;
-
-    Connection getConnection()
-        throws SQLException;
-
-    PreparedStatement prepareGetEntityStatement( Connection connection )
-        throws SQLException;
-
-    PreparedStatement prepareGetAllEntitiesStatement( Connection connection )
-        throws SQLException;
-
-    PreparedStatement prepareInsertEntityStatement( Connection connection )
-        throws SQLException;
-
-    PreparedStatement prepareUpdateEntityStatement( Connection connection )
-        throws SQLException;
-
-    PreparedStatement prepareRemoveEntityStatement( Connection connection )
-        throws SQLException;
-
-    void populateGetEntityStatement( PreparedStatement ps, EntityReference ref )
-        throws SQLException;
-
-    void populateGetAllEntitiesStatement( PreparedStatement ps )
-        throws SQLException;
-
-    void populateInsertEntityStatement( PreparedStatement ps, EntityReference ref, String entity, Long lastModified )
-        throws SQLException;
-
-    void populateUpdateEntityStatement( PreparedStatement ps, Long entityPK, Long entityOptimisticLock, EntityReference ref, String entity, Long lastModified )
-        throws SQLException;
-
-    void populateRemoveEntityStatement( PreparedStatement ps, Long entityPK, EntityReference ref )
-        throws SQLException;
-
-    EntityValueResult getEntityValue( ResultSet rs )
-        throws SQLException;
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLServiceCoreMixin.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLServiceCoreMixin.java
deleted file mode 100644
index 94c82c0..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLServiceCoreMixin.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql.internal;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.Statement;
-import javax.sql.DataSource;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Application.Mode;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.library.sql.common.SQLConfiguration;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.qi4j.spi.entitystore.EntityStoreException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sql.generation.api.vendor.SQLVendor;
-
-@SuppressWarnings( "ProtectedField" )
-public abstract class DatabaseSQLServiceCoreMixin
-        implements DatabaseSQLService
-{
-
-    private static final Logger LOGGER = LoggerFactory.getLogger( DatabaseSQLServiceCoreMixin.class );
-
-    @Structure
-    private Application application;
-
-    @Service
-    private DataSource dataSource;
-
-    @This
-    private DatabaseSQLServiceState state;
-
-    @This
-    protected DatabaseSQLServiceSpi spi;
-
-    @This
-    private DatabaseSQLStringsBuilder sqlStrings;
-
-    @Uses
-    private ServiceDescriptor descriptor;
-
-    @This
-    private Configuration<SQLConfiguration> configuration;
-
-    @Override
-    public Connection getConnection()
-            throws SQLException
-    {
-        return dataSource.getConnection();
-    }
-
-    @Override
-    public void startDatabase()
-            throws Exception
-    {
-        Connection connection = getConnection();
-        String schema = this.getConfiguredSchemaName( SQLs.DEFAULT_SCHEMA_NAME );
-        if ( schema == null ) {
-            throw new EntityStoreException( "Schema name must not be null." );
-        } else {
-            state.schemaName().set( schema );
-            state.vendor().set( this.descriptor.metaInfo( SQLVendor.class ) );
-
-            sqlStrings.init();
-
-            if ( !spi.schemaExists( connection ) ) {
-                LOGGER.debug( "Database Schema '{}' NOT found!", schema );
-                Statement stmt = null;
-                try {
-                    stmt = connection.createStatement();
-                    for ( String sql : sqlStrings.buildSQLForSchemaCreation() ) {
-                        stmt.execute( sql );
-                    }
-                } finally {
-                    SQLUtil.closeQuietly( stmt );
-                }
-                LOGGER.debug( "Database Schema '{}' created", schema );
-            }
-
-            if ( !spi.tableExists( connection ) ) {
-                Statement stmt = null;
-                try {
-                    stmt = connection.createStatement();
-                    for ( String sql : sqlStrings.buildSQLForTableCreation() ) {
-                        stmt.execute( sql );
-                    }
-                    for ( String sql : sqlStrings.buildSQLForIndexCreation() ) {
-                        stmt.execute( sql );
-                    }
-                } finally {
-                    SQLUtil.closeQuietly( stmt );
-                }
-                LOGGER.trace( "Table {} created", SQLs.TABLE_NAME );
-            }
-
-            connection.setAutoCommit( false );
-
-        }
-
-        SQLUtil.closeQuietly( connection );
-
-    }
-
-    @Override
-    public void stopDatabase()
-            throws Exception
-    {
-        if ( Mode.production == application.mode() ) {
-            // NOOP
-        }
-    }
-
-    /**
-     * Configuration is optional at both assembly and runtime.
-     */
-    protected String getConfiguredSchemaName( String defaultSchemaName )
-    {
-        if ( configuration == null ) {
-            NullArgumentException.validateNotNull( "default schema name", defaultSchemaName );
-            LOGGER.debug( "No configuration, will use default schema name: '{}'", defaultSchemaName );
-            return defaultSchemaName;
-        }
-        String result = configuration.get().schemaName().get();
-        if ( result == null ) {
-            NullArgumentException.validateNotNull( "default schema name", defaultSchemaName );
-            result = defaultSchemaName;
-            LOGGER.debug( "No database schema name in configuration, will use default: '{}'", defaultSchemaName );
-        } else {
-            LOGGER.debug( "Will use configured database schema name: '{}'", result );
-        }
-        return result;
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLServiceSpi.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLServiceSpi.java
deleted file mode 100644
index acfdc32..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLServiceSpi.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql.internal;
-
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public interface DatabaseSQLServiceSpi
-{
-
-    boolean schemaExists( Connection connection )
-            throws SQLException;
-
-    String getCurrentSchemaName();
-
-    boolean tableExists( Connection connection )
-            throws SQLException;
-
-    @SuppressWarnings( "PublicInnerClass" )
-    public abstract class CommonMixin
-            implements DatabaseSQLServiceSpi
-    {
-
-        private static final Logger LOGGER = LoggerFactory.getLogger( DatabaseSQLServiceSpi.class );
-
-        @This
-        private DatabaseSQLServiceState state;
-
-        @Override
-        public boolean schemaExists( Connection connection )
-                throws SQLException
-        {
-            ResultSet rs = null;
-            try {
-                Boolean schemaFound = false;
-                rs = connection.getMetaData().getSchemas();
-                String schemaName = this.getCurrentSchemaName();
-
-                while ( rs.next() && !schemaFound ) {
-                    String eachResult = rs.getString( 1 );
-                    LOGGER.trace( "Schema candidate: {}", eachResult );
-                    schemaFound = eachResult.equalsIgnoreCase( schemaName );
-                }
-                LOGGER.trace( "Schema {} found? {}", schemaName, schemaFound );
-                return schemaFound;
-            } finally {
-                SQLUtil.closeQuietly( rs );
-            }
-        }
-
-        @Override
-        public String getCurrentSchemaName()
-        {
-            return this.state.schemaName().get();
-        }
-
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLServiceState.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLServiceState.java
deleted file mode 100644
index 33f8c97..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLServiceState.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql.internal;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-import org.sql.generation.api.vendor.SQLVendor;
-
-public interface DatabaseSQLServiceState
-{
-
-    @Optional
-    public Property<String> schemaName();
-
-    @Optional
-    public Property<SQLVendor> vendor();
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLServiceStatementsMixin.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLServiceStatementsMixin.java
deleted file mode 100644
index 532b788..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLServiceStatementsMixin.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql.internal;
-
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.This;
-
-public abstract class DatabaseSQLServiceStatementsMixin
-        implements DatabaseSQLService
-{
-
-    @This
-    private DatabaseSQLStringsBuilder sqlStrings;
-
-    //
-    // Used by the EntityStore, will probably remain the same even if we support several sql servers
-    //
-    @Override
-    public PreparedStatement prepareGetAllEntitiesStatement( Connection connection )
-            throws SQLException
-    {
-        return connection.prepareStatement( sqlStrings.buildSQLForSelectAllEntitiesStatement() );
-    }
-
-    @Override
-    public PreparedStatement prepareGetEntityStatement( Connection connection )
-            throws SQLException
-    {
-        return connection.prepareStatement( sqlStrings.buildSQLForSelectEntityStatement() );
-    }
-
-    @Override
-    public PreparedStatement prepareInsertEntityStatement( Connection connection )
-            throws SQLException
-    {
-        return connection.prepareStatement( sqlStrings.buildSQLForInsertEntityStatement() );
-    }
-
-    @Override
-    public PreparedStatement prepareRemoveEntityStatement( Connection connection )
-            throws SQLException
-    {
-        return connection.prepareStatement( sqlStrings.buildSQLForRemoveEntityStatement() );
-    }
-
-    @Override
-    public PreparedStatement prepareUpdateEntityStatement( Connection connection )
-            throws SQLException
-    {
-        return connection.prepareStatement( sqlStrings.buildSQLForUpdateEntityStatement() );
-    }
-
-    //
-    // Populate statement methods, to move in a separated fragment if needed for multi sql server support
-    //
-    @Override
-    public void populateGetAllEntitiesStatement( PreparedStatement ps )
-            throws SQLException
-    {
-        // Nothing to do.
-    }
-
-    @Override
-    public void populateGetEntityStatement( PreparedStatement ps, EntityReference ref )
-            throws SQLException
-    {
-        ps.setString( 1, ref.identity() );
-    }
-
-    @Override
-    public void populateInsertEntityStatement( PreparedStatement ps, EntityReference ref, String entity, Long lastModified )
-            throws SQLException
-    {
-        ps.setString( 1, ref.identity() );
-        ps.setString( 2, entity );
-        ps.setLong( 3, lastModified );
-    }
-
-    @Override
-    public void populateRemoveEntityStatement( PreparedStatement ps, Long entityPK, EntityReference ref )
-            throws SQLException
-    {
-        ps.setLong( 1, entityPK );
-    }
-
-    @Override
-    public void populateUpdateEntityStatement( PreparedStatement ps, Long entityPK, Long entityOptimisticLock, EntityReference ref, String entity, Long lastModified )
-            throws SQLException
-    {
-        ps.setLong( 1, entityOptimisticLock + 1 );
-        ps.setString( 2, entity );
-        ps.setLong( 3, lastModified );
-        ps.setLong( 4, entityPK );
-        ps.setLong( 5, entityOptimisticLock );
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLStringsBuilder.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLStringsBuilder.java
deleted file mode 100644
index aeb03ae..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DatabaseSQLStringsBuilder.java
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql.internal;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.injection.scope.This;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sql.generation.api.grammar.builders.modification.DeleteBySearchBuilder;
-import org.sql.generation.api.grammar.builders.modification.UpdateBySearchBuilder;
-import org.sql.generation.api.grammar.common.SQLStatement;
-import org.sql.generation.api.grammar.common.datatypes.SQLDataType;
-import org.sql.generation.api.grammar.definition.table.AutoGenerationPolicy;
-import org.sql.generation.api.grammar.definition.table.UniqueSpecification;
-import org.sql.generation.api.grammar.factories.BooleanFactory;
-import org.sql.generation.api.grammar.factories.ColumnsFactory;
-import org.sql.generation.api.grammar.factories.DefinitionFactory;
-import org.sql.generation.api.grammar.factories.LiteralFactory;
-import org.sql.generation.api.grammar.factories.ModificationFactory;
-import org.sql.generation.api.grammar.factories.QueryFactory;
-import org.sql.generation.api.grammar.factories.TableReferenceFactory;
-import org.sql.generation.api.vendor.SQLVendor;
-
-public interface DatabaseSQLStringsBuilder
-{
-    void init();
-
-    String[] buildSQLForSchemaCreation();
-
-    String[] buildSQLForIndexCreation();
-
-    String[] buildSQLForTableCreation();
-
-    String buildSQLForSelectAllEntitiesStatement();
-
-    String buildSQLForSelectEntityStatement();
-
-    String buildSQLForInsertEntityStatement();
-
-    String buildSQLForUpdateEntityStatement();
-
-    String buildSQLForRemoveEntityStatement();
-
-    @SuppressWarnings("PublicInnerClass")
-    abstract class CommonMixin
-        implements DatabaseSQLStringsBuilder
-    {
-
-        private static final Logger LOGGER = LoggerFactory.getLogger( DatabaseSQLStringsBuilder.class );
-
-        @This
-        private DatabaseSQLServiceState _state;
-
-        private SQLVendor vendor;
-
-        private String schemaName;
-
-        private String[] schemaCreationSQLs;
-
-        private String[] indexCreationSQLs;
-
-        private String[] tableCreationSQLs;
-
-        private String selectAllEntitiesSQL;
-
-        private String selectEntitySQL;
-
-        private String insertEntitySQL;
-
-        private String updateEntitySQL;
-
-        private String removeEntitySQL;
-
-        @Override
-        public void init()
-        {
-            this.vendor = this._state.vendor().get();
-
-            this.schemaName = this._state.schemaName().get();
-
-            this.schemaCreationSQLs = this.toString( this.createSchemaStatements( this.vendor ) );
-            LOGGER.trace( "SQL for schema creation: {}", this.schemaCreationSQLs );
-
-            this.indexCreationSQLs = this.toString( this.createIndicesStatements( this.vendor ) );
-            LOGGER.trace( "SQL for index creation: {}", this.indexCreationSQLs );
-
-            this.tableCreationSQLs = this.toString( this.createTableStatements( this.vendor ) );
-            LOGGER.trace( "SQL for table creation: {}", this.tableCreationSQLs );
-
-            this.selectAllEntitiesSQL = this.vendor.toString( this.createSelectAllEntitiesStatement( this.vendor ) );
-            LOGGER.trace( "SQL for select all entities: {}", this.selectAllEntitiesSQL );
-
-            this.selectEntitySQL = this.vendor.toString( this.createSelectEntityStatement( this.vendor ) );
-            LOGGER.trace( "SQL for select entity: {}", this.selectEntitySQL );
-
-            this.insertEntitySQL = this.vendor.toString( this.createInsertEntityStatement( this.vendor ) );
-            LOGGER.trace( "SQL for insert entity: {}", this.insertEntitySQL );
-
-            this.updateEntitySQL = this.vendor.toString( this.createUpdateEntityStatement( this.vendor ) );
-            LOGGER.trace( "SQL for update entity: {}", this.updateEntitySQL );
-
-            this.removeEntitySQL = this.vendor.toString( this.createRemoveEntityStatement( this.vendor ) );
-            LOGGER.trace( "SQL for remove entity: {}", this.removeEntitySQL );
-        }
-
-        protected String[] toString( SQLStatement[] stmts )
-        {
-            List<String> result = new ArrayList<String>();
-            if( stmts != null )
-            {
-                for( Integer idx = 0; idx < stmts.length; ++idx )
-                {
-                    SQLStatement statement = stmts[idx];
-                    if( statement != null )
-                    {
-                        String stringStatement = this.vendor.toString( statement );
-                        if( stringStatement != null && stringStatement.length() > 0 )
-                        {
-                            result.add( this.vendor.toString( statement ) );
-                        }
-                    }
-                }
-            }
-            return result.toArray( new String[ result.size() ] );
-        }
-
-        protected SQLVendor getVendor()
-        {
-            return this.vendor;
-        }
-
-        protected String getSchemaName()
-        {
-            return this.schemaName;
-        }
-
-        protected SQLStatement[] createSchemaStatements( SQLVendor vendor )
-        {
-            // @formatter:off
-            return new SQLStatement[]
-            {
-                vendor.getDefinitionFactory().createSchemaDefinitionBuilder()
-                .setSchemaName( this.schemaName )
-                .createExpression()
-            };
-            // @formatter:on
-        }
-
-        protected SQLStatement[] createIndicesStatements( SQLVendor vendor )
-        {
-            // TODO
-            return new SQLStatement[] {};
-        }
-
-        protected SQLStatement[] createTableStatements( SQLVendor vendor )
-        {
-            DefinitionFactory d = vendor.getDefinitionFactory();
-            TableReferenceFactory t = vendor.getTableReferenceFactory();
-
-
-            // @formatter:off
-            return new SQLStatement[]
-            {
-                d.createTableDefinitionBuilder()
-                    .setTableName( t.tableName( this.getSchemaName(), SQLs.TABLE_NAME ) )
-                    .setTableContentsSource( d.createTableElementListBuilder()
-                        .addTableElement( d.createColumnDefinition( SQLs.ENTITY_PK_COLUMN_NAME, this.getPKType(), false, AutoGenerationPolicy.BY_DEFAULT ) )
-                        .addTableElement( d.createColumnDefinition( SQLs.ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME, this.getOptimisticLockType(), false ) )
-                        .addTableElement( d.createColumnDefinition( SQLs.ENTITY_IDENTITY_COLUMN_NAME, this.getIDType(), false ) )
-                        .addTableElement( d.createColumnDefinition( SQLs.ENTITY_STATE_COLUMN_NAME, this.getStateType(), false ) )
-                        .addTableElement( d.createColumnDefinition( SQLs.ENTITY_LAST_MODIFIED_COLUMN_NAME, this.getLastModifiedType(), false ) )
-                        .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
-                            .setUniqueness( UniqueSpecification.PRIMARY_KEY )
-                            .addColumns( SQLs.ENTITY_PK_COLUMN_NAME )
-                            .createExpression() ) )
-                        .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
-                            .setUniqueness( UniqueSpecification.UNIQUE )
-                            .addColumns( SQLs.ENTITY_IDENTITY_COLUMN_NAME )
-                            .createExpression() ) )
-                        .createExpression()
-                        )
-                   .createExpression()
-            };
-            // @formatter:on
-        }
-
-        protected SQLStatement createSelectAllEntitiesStatement( SQLVendor vendor )
-        {
-            QueryFactory q = vendor.getQueryFactory();
-            TableReferenceFactory t = vendor.getTableReferenceFactory();
-
-            // @formatter:off
-            return q.simpleQueryBuilder()
-                .select( SQLs.ENTITY_PK_COLUMN_NAME, SQLs.ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME, SQLs.ENTITY_STATE_COLUMN_NAME )
-                .from( t.tableName( this.schemaName, SQLs.TABLE_NAME ) )
-                .createExpression();
-            // @formatter:on
-        }
-
-        protected SQLStatement createSelectEntityStatement( SQLVendor vendor )
-        {
-            QueryFactory q = vendor.getQueryFactory();
-            TableReferenceFactory t = vendor.getTableReferenceFactory();
-            BooleanFactory b = vendor.getBooleanFactory();
-            ColumnsFactory c = vendor.getColumnsFactory();
-            LiteralFactory l = vendor.getLiteralFactory();
-
-            // @formatter:off
-            return q.simpleQueryBuilder()
-                .select( SQLs.ENTITY_PK_COLUMN_NAME, SQLs.ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME, SQLs.ENTITY_STATE_COLUMN_NAME )
-                .from( t.tableName( this.schemaName, SQLs.TABLE_NAME ) )
-                .where( b.eq( c.colName( SQLs.ENTITY_IDENTITY_COLUMN_NAME ), l.param() ) )
-                .createExpression();
-            // @formatter:on
-        }
-
-        protected SQLStatement createInsertEntityStatement( SQLVendor vendor )
-        {
-            ModificationFactory m = vendor.getModificationFactory();
-            TableReferenceFactory t = vendor.getTableReferenceFactory();
-            LiteralFactory l = vendor.getLiteralFactory();
-
-            // @formatter:off
-            return m.insert()
-                .setTableName( t.tableName( this.schemaName, SQLs.TABLE_NAME ) )
-                .setColumnSource( m.columnSourceByValues()
-                    .addColumnNames(
-                        SQLs.ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME,
-                        SQLs.ENTITY_IDENTITY_COLUMN_NAME,
-                        SQLs.ENTITY_STATE_COLUMN_NAME,
-                        SQLs.ENTITY_LAST_MODIFIED_COLUMN_NAME
-                        )
-                    .addValues(
-                        l.n( 0 ),
-                        l.param(),
-                        l.param(),
-                        l.param()
-                        )
-                    .createExpression()
-                    )
-                 .createExpression();
-            // @formatter:on
-        }
-
-        protected SQLStatement createUpdateEntityStatement( SQLVendor vendor )
-        {
-            ModificationFactory m = vendor.getModificationFactory();
-            TableReferenceFactory t = vendor.getTableReferenceFactory();
-            LiteralFactory l = vendor.getLiteralFactory();
-            BooleanFactory b = vendor.getBooleanFactory();
-            ColumnsFactory c = vendor.getColumnsFactory();
-
-            // @formatter:off
-            UpdateBySearchBuilder builder = m.updateBySearch()
-                .setTargetTable( m.createTargetTable( t.tableName( this.schemaName, SQLs.TABLE_NAME ) ) )
-                .addSetClauses(
-                    m.setClause( SQLs.ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME, m.updateSourceByExp( l.param() ) ),
-                    m.setClause( SQLs.ENTITY_STATE_COLUMN_NAME, m.updateSourceByExp( l.param() ) ),
-                    m.setClause( SQLs.ENTITY_LAST_MODIFIED_COLUMN_NAME, m.updateSourceByExp( l.param() ) )
-                    );
-            builder
-                .getWhereBuilder()
-                    .reset( b.eq( c.colName( SQLs.ENTITY_PK_COLUMN_NAME ), l.param() ) )
-                    .and( b.eq( c.colName( SQLs.ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME ), l.param() ) );
-            return builder.createExpression();
-            // @formatter:on
-        }
-
-        protected SQLStatement createRemoveEntityStatement( SQLVendor vendor )
-        {
-            ModificationFactory m = vendor.getModificationFactory();
-            TableReferenceFactory t = vendor.getTableReferenceFactory();
-            LiteralFactory l = vendor.getLiteralFactory();
-            BooleanFactory b = vendor.getBooleanFactory();
-            ColumnsFactory c = vendor.getColumnsFactory();
-
-            // @formatter:off
-            DeleteBySearchBuilder builder = m.deleteBySearch()
-                .setTargetTable( m.createTargetTable( t.tableName( this.schemaName, SQLs.TABLE_NAME ) ) );
-            builder.getWhere()
-                .reset( b.eq( c.colName( SQLs.ENTITY_PK_COLUMN_NAME ), l.param() ) );
-            return builder.createExpression();
-            // @formatter:on
-        }
-
-        protected SQLDataType getPKType()
-        {
-            return this.vendor.getDataTypeFactory().bigInt();
-        }
-
-        protected SQLDataType getOptimisticLockType()
-        {
-            return this.vendor.getDataTypeFactory().bigInt();
-        }
-
-        protected SQLDataType getIDType()
-        {
-            return this.vendor.getDataTypeFactory().sqlVarChar( 64 );
-        }
-
-        protected SQLDataType getStateType()
-        {
-            return this.vendor.getDataTypeFactory().sqlVarChar( 10000 );
-        }
-
-        protected SQLDataType getLastModifiedType()
-        {
-            return this.vendor.getDataTypeFactory().bigInt();
-        }
-
-        @Override
-        public String[] buildSQLForSchemaCreation()
-        {
-            return this.schemaCreationSQLs;
-        }
-
-        @Override
-        public String[] buildSQLForIndexCreation()
-        {
-            return this.indexCreationSQLs;
-        }
-
-        @Override
-        public String buildSQLForSelectAllEntitiesStatement()
-        {
-            return this.selectAllEntitiesSQL;
-        }
-
-        @Override
-        public String buildSQLForSelectEntityStatement()
-        {
-            return this.selectEntitySQL;
-        }
-
-        @Override
-        public String buildSQLForInsertEntityStatement()
-        {
-            return this.insertEntitySQL;
-        }
-
-        @Override
-        public String buildSQLForUpdateEntityStatement()
-        {
-            return this.updateEntitySQL;
-        }
-
-        @Override
-        public String buildSQLForRemoveEntityStatement()
-        {
-            return this.removeEntitySQL;
-        }
-
-        @Override
-        public String[] buildSQLForTableCreation()
-        {
-            return this.tableCreationSQLs;
-        }
-
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DerbySQLDatabaseSQLServiceMixin.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DerbySQLDatabaseSQLServiceMixin.java
deleted file mode 100644
index 6b48a89..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/DerbySQLDatabaseSQLServiceMixin.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql.internal;
-
-import java.io.StringReader;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@SuppressWarnings("ProtectedField")
-public abstract class DerbySQLDatabaseSQLServiceMixin
-    implements DatabaseSQLService, DatabaseSQLStringsBuilder, DatabaseSQLServiceSpi
-{
-
-    private static final Logger LOGGER = LoggerFactory.getLogger( DerbySQLDatabaseSQLServiceMixin.class );
-
-    @This
-    protected DatabaseSQLServiceSpi spi;
-
-    @Override
-    public boolean tableExists( Connection connection )
-        throws SQLException
-    {
-        ResultSet rs = null;
-        try
-        {
-            String tableNameForQuery = SQLs.TABLE_NAME.toUpperCase();
-            rs = connection.getMetaData().getTables( null, null, tableNameForQuery, new String[]
-            {
-                "TABLE"
-            } );
-            boolean tableExists = rs.next();
-            LOGGER.trace( "Found table {}? {}", tableNameForQuery, tableExists );
-            return tableExists;
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( rs );
-        }
-    }
-
-    @Override
-    public EntityValueResult getEntityValue( ResultSet rs )
-        throws SQLException
-    {
-        return new EntityValueResult( rs.getLong( SQLs.ENTITY_PK_COLUMN_NAME ),
-            rs.getLong( SQLs.ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME ), new StringReader(
-                rs.getString( SQLs.ENTITY_STATE_COLUMN_NAME ) ) );
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/H2SQLDatabaseSQLServiceMixin.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/H2SQLDatabaseSQLServiceMixin.java
deleted file mode 100644
index 1f54353..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/H2SQLDatabaseSQLServiceMixin.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.entitystore.sql.internal;
-
-import java.io.StringReader;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public abstract class H2SQLDatabaseSQLServiceMixin
-        implements DatabaseSQLService, DatabaseSQLStringsBuilder, DatabaseSQLServiceSpi
-{
-
-    private static final Logger LOGGER = LoggerFactory.getLogger( H2SQLDatabaseSQLServiceMixin.class );
-
-    @This
-    protected DatabaseSQLServiceSpi spi;
-
-    public boolean tableExists( Connection connection )
-            throws SQLException
-    {
-        ResultSet rs = null;
-        try {
-            String tableNameForQuery = SQLs.TABLE_NAME.toUpperCase();
-            rs = connection.getMetaData().getTables( null, null, tableNameForQuery, new String[]{ "TABLE" } );
-            boolean tableExists = rs.next();
-            LOGGER.trace( "Found table {}? {}", tableNameForQuery, tableExists );
-            return tableExists;
-        } finally {
-            SQLUtil.closeQuietly( rs );
-        }
-    }
-
-    public EntityValueResult getEntityValue( ResultSet rs )
-            throws SQLException
-    {
-        return new EntityValueResult( rs.getLong( SQLs.ENTITY_PK_COLUMN_NAME ),
-                                      rs.getLong( SQLs.ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME ),
-                                      new StringReader( rs.getString( SQLs.ENTITY_STATE_COLUMN_NAME ) ) );
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/MySQLDatabaseSQLServiceMixin.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/MySQLDatabaseSQLServiceMixin.java
deleted file mode 100644
index ba8210f..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/MySQLDatabaseSQLServiceMixin.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql.internal;
-
-import java.io.StringReader;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@SuppressWarnings("ProtectedField")
-public abstract class MySQLDatabaseSQLServiceMixin
-    implements DatabaseSQLService, DatabaseSQLStringsBuilder, DatabaseSQLServiceSpi
-{
-
-    private static final Logger LOGGER = LoggerFactory.getLogger( MySQLDatabaseSQLServiceMixin.class );
-
-    @This
-    protected DatabaseSQLServiceSpi spi;
-
-    @Override
-    public boolean tableExists( Connection connection )
-        throws SQLException
-    {
-        ResultSet rs = null;
-        try
-        {
-            String tableNameForQuery = SQLs.TABLE_NAME.toUpperCase();
-            rs = connection.getMetaData().getTables( null, null, tableNameForQuery, new String[]
-            {
-                "TABLE"
-            } );
-            boolean tableExists = rs.next();
-            LOGGER.trace( "Found table {}? {}", tableNameForQuery, tableExists );
-            return tableExists;
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( rs );
-        }
-    }
-
-    @Override
-    public EntityValueResult getEntityValue( ResultSet rs )
-        throws SQLException
-    {
-        return new EntityValueResult( rs.getLong( SQLs.ENTITY_PK_COLUMN_NAME ),
-            rs.getLong( SQLs.ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME ), new StringReader(
-                rs.getString( SQLs.ENTITY_STATE_COLUMN_NAME ) ) );
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/PostgreSQLDatabaseSQLServiceMixin.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/PostgreSQLDatabaseSQLServiceMixin.java
deleted file mode 100644
index 197b2da..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/PostgreSQLDatabaseSQLServiceMixin.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql.internal;
-
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public abstract class PostgreSQLDatabaseSQLServiceMixin
-        implements DatabaseSQLServiceSpi, DatabaseSQLStringsBuilder, DatabaseSQLService
-{
-
-    private static final Logger LOGGER = LoggerFactory.getLogger( PostgreSQLDatabaseSQLServiceMixin.class );
-
-    @This
-    protected DatabaseSQLServiceSpi spi;
-
-    @Override
-    public boolean tableExists( Connection connection )
-            throws SQLException
-    {
-        ResultSet rs = null;
-        try {
-
-            rs = connection.getMetaData().getTables( null,
-                                                     this.spi.getCurrentSchemaName(),
-                                                     SQLs.TABLE_NAME,
-                                                     new String[]{ "TABLE" } );
-            boolean tableExists = rs.next();
-            LOGGER.trace( "Found table {}? {}", SQLs.TABLE_NAME, tableExists );
-            return tableExists;
-
-        } finally {
-            SQLUtil.closeQuietly( rs );
-        }
-    }
-
-    @Override
-    public EntityValueResult getEntityValue( ResultSet rs )
-            throws SQLException
-    {
-        return new EntityValueResult( rs.getLong( SQLs.ENTITY_PK_COLUMN_NAME ),
-                                      rs.getLong( SQLs.ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME ),
-                                      rs.getCharacterStream( SQLs.ENTITY_STATE_COLUMN_NAME ) );
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/PostgreSQLStringBuilderMixin.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/PostgreSQLStringBuilderMixin.java
deleted file mode 100644
index ea6d06b..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/PostgreSQLStringBuilderMixin.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql.internal;
-
-import org.qi4j.entitystore.sql.internal.DatabaseSQLStringsBuilder.CommonMixin;
-import org.sql.generation.api.grammar.common.datatypes.SQLDataType;
-import org.sql.generation.api.vendor.PostgreSQLVendor;
-
-/**
- * 
- * @author Stanislav Muhametsin
- */
-public class PostgreSQLStringBuilderMixin extends CommonMixin
-{
-
-    @Override
-    protected SQLDataType getIDType()
-    {
-        return ((PostgreSQLVendor) this.getVendor()).getDataTypeFactory().text();
-    }
-
-    @Override
-    protected SQLDataType getStateType()
-    {
-        return ((PostgreSQLVendor) this.getVendor()).getDataTypeFactory().text();
-    }
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/SQLEntityState.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/SQLEntityState.java
deleted file mode 100644
index 1286049..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/SQLEntityState.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql.internal;
-
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.EntityStatus;
-import org.qi4j.spi.entity.ManyAssociationState;
-import org.qi4j.spi.entity.NamedAssociationState;
-import org.qi4j.spi.entitystore.helpers.DefaultEntityState;
-
-public interface SQLEntityState
-        extends EntityState
-{
-
-    public Long getEntityPK();
-
-    public Long getEntityOptimisticLock();
-
-    public DefaultEntityState getDefaultEntityState();
-
-    @SuppressWarnings( "PublicInnerClass" )
-    public final class DefaultSQLEntityState
-            implements SQLEntityState
-    {
-
-        private final DefaultEntityState state;
-
-        private final Long entityPK;
-
-        private final Long entityOptimisticLock;
-
-        public DefaultSQLEntityState( DefaultEntityState state )
-        {
-            NullArgumentException.validateNotNull( "Entity state", state );
-            this.state = state;
-            this.entityPK = null;
-            this.entityOptimisticLock = null;
-        }
-
-        public DefaultSQLEntityState( DefaultEntityState state, Long entityPK, Long entityOptimisticLock )
-        {
-            NullArgumentException.validateNotNull( "Entity state", state );
-            NullArgumentException.validateNotNull( "Entity PK", entityPK );
-            NullArgumentException.validateNotNull( "Entity OptimisticLock", entityOptimisticLock );
-            this.state = state;
-            this.entityPK = entityPK;
-            this.entityOptimisticLock = entityOptimisticLock;
-        }
-
-        @Override
-        public Long getEntityPK()
-        {
-            return entityPK;
-        }
-
-        @Override
-        public Long getEntityOptimisticLock()
-        {
-            return entityOptimisticLock;
-        }
-
-        @Override
-        public DefaultEntityState getDefaultEntityState()
-        {
-            return state;
-        }
-
-        @Override
-        public EntityDescriptor entityDescriptor()
-        {
-            return state.entityDescriptor();
-        }
-
-        @Override
-        public EntityReference associationValueOf( QualifiedName stateName )
-        {
-            return state.associationValueOf( stateName );
-        }
-
-        @Override
-        public ManyAssociationState manyAssociationValueOf( QualifiedName stateName )
-        {
-            return state.manyAssociationValueOf( stateName );
-        }
-
-        @Override
-        public NamedAssociationState namedAssociationValueOf( QualifiedName stateName )
-        {
-            return state.namedAssociationValueOf( stateName );
-        }
-
-        @Override
-        public Object propertyValueOf( QualifiedName stateName )
-        {
-            return state.propertyValueOf( stateName );
-        }
-
-        @Override
-        public EntityReference identity()
-        {
-            return state.identity();
-        }
-
-        @Override
-        public boolean isAssignableTo( Class<?> type )
-        {
-            return state.isAssignableTo( type );
-        }
-
-        @Override
-        public long lastModified()
-        {
-            return state.lastModified();
-        }
-
-        @Override
-        public void remove()
-        {
-            state.remove();
-        }
-
-        @Override
-        public void setAssociationValue( QualifiedName stateName, EntityReference newEntity )
-        {
-            state.setAssociationValue( stateName, newEntity );
-        }
-
-        @Override
-        public void setPropertyValue( QualifiedName stateName, Object json )
-        {
-            state.setPropertyValue( stateName, json );
-        }
-
-        @Override
-        public EntityStatus status()
-        {
-            return state.status();
-        }
-
-        @Override
-        public String version()
-        {
-            return state.version();
-        }
-
-        @Override
-        @SuppressWarnings( "EqualsWhichDoesntCheckParameterClass" )
-        public boolean equals( Object obj )
-        {
-            return state.equals( obj );
-        }
-
-        @Override
-        public int hashCode()
-        {
-            return state.hashCode();
-        }
-
-        @Override
-        public String toString()
-        {
-            return state.toString();
-        }
-
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/SQLiteDatabaseSQLServiceMixin.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/SQLiteDatabaseSQLServiceMixin.java
deleted file mode 100644
index b4858ea..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/SQLiteDatabaseSQLServiceMixin.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.entitystore.sql.internal;
-
-import java.io.StringReader;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public abstract class SQLiteDatabaseSQLServiceMixin
-        implements DatabaseSQLService, DatabaseSQLStringsBuilder, DatabaseSQLServiceSpi
-{
-
-    private static final Logger LOGGER = LoggerFactory.getLogger( SQLiteDatabaseSQLServiceMixin.class );
-
-    @This
-    protected DatabaseSQLServiceSpi spi;
-
-    @Override
-    public boolean tableExists( Connection connection )
-            throws SQLException
-    {
-        ResultSet rs = null;
-        try {
-            String tableNameForQuery = SQLs.TABLE_NAME.toUpperCase();
-            rs = connection.getMetaData().getTables( null, null, tableNameForQuery, new String[]{ "TABLE" } );
-            boolean tableExists = rs.next();
-            LOGGER.trace( "Found table {}? {}", tableNameForQuery, tableExists );
-            return tableExists;
-        } finally {
-            SQLUtil.closeQuietly( rs );
-        }
-    }
-
-    @Override
-    public EntityValueResult getEntityValue( ResultSet rs )
-            throws SQLException
-    {
-        return new EntityValueResult( rs.getLong( SQLs.ENTITY_PK_COLUMN_NAME ),
-                                      rs.getLong( SQLs.ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME ),
-                                      new StringReader( rs.getString( SQLs.ENTITY_STATE_COLUMN_NAME ) ) );
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/SQLs.java b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/SQLs.java
deleted file mode 100644
index db5eccb..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/SQLs.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql.internal;
-
-public interface SQLs
-{
-
-    String DEFAULT_SCHEMA_NAME = "qi4j_es";
-
-    String TABLE_NAME = "qi4j_entities";
-
-    String ENTITY_PK_COLUMN_NAME = "entity_pk";
-
-    String ENTITY_IDENTITY_COLUMN_NAME = "entity_id";
-
-    String ENTITY_STATE_COLUMN_NAME = "entity_state";
-
-    String ENTITY_OPTIMISTIC_LOCK_COLUMN_NAME = "entity_optimistic_lock";
-
-    String ENTITY_LAST_MODIFIED_COLUMN_NAME = "entity_last_modified";
-
-}
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/package.html b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/package.html
deleted file mode 100644
index c8ccb16..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/internal/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL EntityStore Internal Package.</h2>
-    </body>
-</html>
diff --git a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/package.html b/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/package.html
deleted file mode 100644
index c7e5688..0000000
--- a/extensions/entitystore-sql/src/main/java/org/qi4j/entitystore/sql/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL EntityStore.</h2>
-    </body>
-</html>
diff --git a/extensions/entitystore-sql/src/main/resources/org/apache/polygene/entitystore/sql/changelog.xml b/extensions/entitystore-sql/src/main/resources/org/apache/polygene/entitystore/sql/changelog.xml
new file mode 100644
index 0000000..47ef554
--- /dev/null
+++ b/extensions/entitystore-sql/src/main/resources/org/apache/polygene/entitystore/sql/changelog.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  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.
+  -->
+<databaseChangeLog
+        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.0.xsd"
+        objectQuotingStrategy="QUOTE_ALL_OBJECTS">
+    <changeSet id="0" author="paul">
+        <createTable tableName="${es-sql.table}">
+            <column name="ENTITY_IDENTITY" type="varchar(64)">
+                <constraints primaryKey="true" nullable="false"/>
+            </column>
+            <column name="ENTITY_VERSION" type="varchar(64)">
+                <constraints nullable="false"/>
+            </column>
+            <column name="ENTITY_STATE" type="varchar(10240)">
+                <constraints nullable="false"/>
+            </column>
+        </createTable>
+    </changeSet>
+</databaseChangeLog>
diff --git a/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/DerbySQLEntityStoreTest.java b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/DerbySQLEntityStoreTest.java
new file mode 100644
index 0000000..f66ca9c
--- /dev/null
+++ b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/DerbySQLEntityStoreTest.java
@@ -0,0 +1,101 @@
+/*
+ *  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.polygene.entitystore.sql;
+
+import java.sql.Connection;
+import java.sql.Statement;
+import javax.sql.DataSource;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.sql.assembly.DerbySQLEntityStoreAssembler;
+import org.apache.polygene.library.sql.assembly.DataSourceAssembler;
+import org.apache.polygene.library.sql.dbcp.DBCPDataSourceServiceAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+
+import static org.apache.polygene.entitystore.sql.assembly.DerbySQLEntityStoreAssembler.DEFAULT_ENTITYSTORE_IDENTITY;
+
+public class DerbySQLEntityStoreTest
+    extends AbstractEntityStoreTest
+{
+    @Override
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // END SNIPPET: assembly
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+
+        // START SNIPPET: assembly
+        // DataSourceService
+        new DBCPDataSourceServiceAssembler()
+            .identifiedBy( "derby-datasource-service" )
+            .visibleIn( Visibility.module )
+            .withConfig( config, Visibility.layer )
+            .assemble( module );
+
+        // DataSource
+        new DataSourceAssembler()
+            .withDataSourceServiceIdentity( "derby-datasource-service" )
+            .identifiedBy( "derby-datasource" )
+            .visibleIn( Visibility.module )
+            .withCircuitBreaker()
+            .assemble( module );
+
+        // SQL EntityStore
+        new DerbySQLEntityStoreAssembler()
+            .visibleIn( Visibility.application )
+            .withConfig( config, Visibility.layer )
+            .assemble( module );
+    }
+    // END SNIPPET: assembly
+
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        UnitOfWork uow = this.unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase(
+            "Delete " + getClass().getSimpleName() + " test data" ) );
+        try
+        {
+            SQLMapEntityStoreConfiguration config = uow.get( SQLMapEntityStoreConfiguration.class,
+                                                             DEFAULT_ENTITYSTORE_IDENTITY );
+            Connection connection = serviceFinder.findService( DataSource.class ).get().getConnection();
+            connection.setAutoCommit( false );
+            try( Statement stmt = connection.createStatement() )
+            {
+                stmt.execute( String.format( "DELETE FROM %s.%s",
+                                             config.schemaName().get(),
+                                             config.entityTableName().get() ) );
+                connection.commit();
+            }
+        }
+        finally
+        {
+            uow.discard();
+            super.tearDown();
+        }
+    }
+}
diff --git a/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/H2SQLEntityStoreTest.java b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/H2SQLEntityStoreTest.java
new file mode 100644
index 0000000..1aed71f
--- /dev/null
+++ b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/H2SQLEntityStoreTest.java
@@ -0,0 +1,67 @@
+/*
+ *  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.polygene.entitystore.sql;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.sql.assembly.H2SQLEntityStoreAssembler;
+import org.apache.polygene.library.sql.assembly.DataSourceAssembler;
+import org.apache.polygene.library.sql.dbcp.DBCPDataSourceServiceAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+
+public class H2SQLEntityStoreTest
+    extends AbstractEntityStoreTest
+{
+    @Override
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // END SNIPPET: assembly
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+
+        // START SNIPPET: assembly
+        // DataSourceService
+        new DBCPDataSourceServiceAssembler()
+            .identifiedBy( "h2-datasource-service" )
+            .visibleIn( Visibility.module )
+            .withConfig( config, Visibility.layer )
+            .assemble( module );
+
+        // DataSource
+        new DataSourceAssembler()
+            .withDataSourceServiceIdentity( "h2-datasource-service" )
+            .identifiedBy( "h2-datasource" )
+            .visibleIn( Visibility.module )
+            .withCircuitBreaker()
+            .assemble( module );
+
+        // SQL EntityStore
+        new H2SQLEntityStoreAssembler()
+            .visibleIn( Visibility.application )
+            .withConfig( config, Visibility.layer )
+            .assemble( module );
+    }
+    // END SNIPPET: assembly
+}
diff --git a/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MySQLEntityStoreTest.java b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MySQLEntityStoreTest.java
new file mode 100644
index 0000000..c82bd61
--- /dev/null
+++ b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MySQLEntityStoreTest.java
@@ -0,0 +1,127 @@
+/*
+ *  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.polygene.entitystore.sql;
+
+import java.sql.Connection;
+import java.sql.Statement;
+import java.util.HashMap;
+import javax.sql.DataSource;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.sql.assembly.MySQLEntityStoreAssembler;
+import org.apache.polygene.library.sql.assembly.DataSourceAssembler;
+import org.apache.polygene.library.sql.datasource.DataSourceConfiguration;
+import org.apache.polygene.library.sql.dbcp.DBCPDataSourceServiceAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+import org.apache.polygene.test.internal.DockerRule;
+import org.junit.ClassRule;
+
+import static org.apache.polygene.entitystore.sql.assembly.MySQLEntityStoreAssembler.DEFAULT_ENTITYSTORE_IDENTITY;
+
+public class MySQLEntityStoreTest
+    extends AbstractEntityStoreTest
+{
+    @ClassRule
+    public static final DockerRule DOCKER = new DockerRule(
+        "mysql",
+        new HashMap<String, String>()
+        {{
+            put( "MYSQL_ROOT_PASSWORD", "" );
+            put( "MYSQL_ALLOW_EMPTY_PASSWORD", "yes" );
+            put( "MYSQL_DATABASE", "jdbc_test_db" );
+            put( "MYSQL_ROOT_HOST", "172.17.0.1" );
+        }},
+        30000L
+//        , "mysqld: ready for connections"   TODO: add this after next release of tdomzal/junit-docker-rule
+    );
+
+    @Override
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // END SNIPPET: assembly
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+
+        // START SNIPPET: assembly
+        // DataSourceService
+        new DBCPDataSourceServiceAssembler()
+            .identifiedBy( "mysql-datasource-service" )
+            .visibleIn( Visibility.module )
+            .withConfig( config, Visibility.layer )
+            .assemble( module );
+
+        // DataSource
+        new DataSourceAssembler()
+            .withDataSourceServiceIdentity( "mysql-datasource-service" )
+            .identifiedBy( "mysql-datasource" )
+            .visibleIn( Visibility.module )
+            .withCircuitBreaker()
+            .assemble( module );
+
+        // SQL EntityStore
+        new MySQLEntityStoreAssembler()
+            .visibleIn( Visibility.application )
+            .withConfig( config, Visibility.layer )
+            .assemble( module );
+        // END SNIPPET: assembly
+        String mysqlHost = DOCKER.getDockerHost();
+        int mysqlPort = DOCKER.getExposedContainerPort( "3306/tcp" );
+        config.forMixin( DataSourceConfiguration.class ).declareDefaults()
+              .url().set( "jdbc:mysql://" + mysqlHost + ":" + mysqlPort
+                          + "/jdbc_test_db?profileSQL=false&useLegacyDatetimeCode=false&serverTimezone=UTC"
+                          + "&nullCatalogMeansCurrent=true&nullNamePatternMatchesAll=true" );
+        // START SNIPPET: assembly
+    }
+    // END SNIPPET: assembly
+
+    @Override
+    public void tearDown() throws Exception
+    {
+        UnitOfWork uow = this.unitOfWorkFactory.newUnitOfWork(
+            UsecaseBuilder.newUsecase( "Delete " + getClass().getSimpleName() + " test data" )
+        );
+        try
+        {
+            Connection connection = serviceFinder.findService( DataSource.class ).get().getConnection();
+            SQLMapEntityStoreConfiguration configuration = uow.get( SQLMapEntityStoreConfiguration.class,
+                                                                    DEFAULT_ENTITYSTORE_IDENTITY );
+            connection.setAutoCommit( false );
+            try( Statement stmt = connection.createStatement() )
+            {
+                stmt.execute( String.format( "TRUNCATE %s.%s",
+                                             configuration.schemaName().get(),
+                                             configuration.entityTableName().get() ) );
+                connection.commit();
+            }
+        }
+        finally
+        {
+            uow.discard();
+            super.tearDown();
+        }
+    }
+}
diff --git a/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/PostgreSQLEntityStoreTest.java b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/PostgreSQLEntityStoreTest.java
new file mode 100644
index 0000000..1da7b58
--- /dev/null
+++ b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/PostgreSQLEntityStoreTest.java
@@ -0,0 +1,149 @@
+/*
+ *  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.polygene.entitystore.sql;
+
+import java.sql.Connection;
+import java.sql.Statement;
+import javax.sql.DataSource;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.sql.assembly.PostgreSQLEntityStoreAssembler;
+import org.apache.polygene.library.sql.assembly.DataSourceAssembler;
+import org.apache.polygene.library.sql.common.SQLConfiguration;
+import org.apache.polygene.library.sql.datasource.DataSourceConfiguration;
+import org.apache.polygene.library.sql.dbcp.DBCPDataSourceServiceAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+import org.apache.polygene.test.internal.DockerRule;
+import org.junit.ClassRule;
+
+import static org.apache.polygene.entitystore.sql.assembly.PostgreSQLEntityStoreAssembler.DEFAULT_ENTITYSTORE_IDENTITY;
+
+/**
+ * WARN This test run only if localhost:5432 is listening.
+ *
+ * To run it you need to have a user & database set up in postgresql. Here are two snippets to create and drop the
+ * needed test environment.
+ *
+ * Use 'password' as password for the jdbc_test_login user.
+ *
+ * Eventually create a database cluster:
+ *
+ * <pre>
+ * initdb -D /usr/local/pgsql/data
+ * </pre>
+ *
+ * Start PostgreSQL. Then, create test user and database:
+ *
+ * <pre>
+ * createuser -A -D -P -E -W jdbc_test_login
+ * createdb -O jdbc_test_login -W jdbc_test_db
+ * </pre>
+ *
+ * To clear the data:
+ *
+ * <pre>
+ * dropdb -W jdbc_test_db
+ * createdb -O jdbc_test_login -W jdbc_test_db
+ * </pre>
+ *
+ * To remove the test user:
+ *
+ * <pre>
+ * dropuser -W jdbc_test_login
+ * </pre>
+ */
+public class PostgreSQLEntityStoreTest
+    extends AbstractEntityStoreTest
+{
+    @ClassRule
+    public static final DockerRule DOCKER = new DockerRule( "postgres",
+                                                            3000L,
+                                                            "PostgreSQL init process complete; ready for start up." );
+
+    @Override
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // END SNIPPET: assembly
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+
+        // START SNIPPET: assembly
+        // DataSourceService
+        new DBCPDataSourceServiceAssembler()
+            .identifiedBy( "postgresql-datasource-service" )
+            .visibleIn( Visibility.module )
+            .withConfig( config, Visibility.layer )
+            .assemble( module );
+
+        // DataSource
+        new DataSourceAssembler()
+            .withDataSourceServiceIdentity( "postgresql-datasource-service" )
+            .identifiedBy( "postgresql-datasource" )
+            .visibleIn( Visibility.module )
+            .withCircuitBreaker()
+            .assemble( module );
+
+        // SQL EntityStore
+        new PostgreSQLEntityStoreAssembler()
+            .visibleIn( Visibility.application )
+            .withConfig( config, Visibility.layer )
+            .assemble( module );
+        // END SNIPPET: assembly
+        String host = DOCKER.getDockerHost();
+        int port = DOCKER.getExposedContainerPort( "5432/tcp" );
+        config.forMixin( DataSourceConfiguration.class ).declareDefaults()
+              .url().set( "jdbc:postgresql://" + host + ":" + port + "/jdbc_test_db" );
+        // START SNIPPET: assembly
+    }
+    // END SNIPPET: assembly
+
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork(
+            UsecaseBuilder.newUsecase( "Delete " + getClass().getSimpleName() + " test data" )
+        );
+        try
+        {
+            SQLConfiguration config = uow.get( SQLConfiguration.class, DEFAULT_ENTITYSTORE_IDENTITY );
+            Connection connection = serviceFinder.findService( DataSource.class ).get().getConnection();
+            connection.setAutoCommit( false );
+            String schemaName = config.schemaName().get();
+            try( Statement stmt = connection.createStatement() )
+            {
+                stmt.execute( String.format( "DROP SCHEMA \"%s\" CASCADE", schemaName ) );
+                connection.commit();
+            }
+        }
+        finally
+        {
+            uow.discard();
+            super.tearDown();
+        }
+    }
+}
diff --git a/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/SQLiteEntityStoreTest.java b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/SQLiteEntityStoreTest.java
new file mode 100644
index 0000000..07402b5
--- /dev/null
+++ b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/SQLiteEntityStoreTest.java
@@ -0,0 +1,75 @@
+/*
+ *  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.polygene.entitystore.sql;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.sql.assembly.SQLiteEntityStoreAssembler;
+import org.apache.polygene.library.sql.assembly.DataSourceAssembler;
+import org.apache.polygene.library.sql.dbcp.DBCPDataSourceServiceAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.entity.AbstractEntityStoreTest;
+import org.junit.BeforeClass;
+
+import static org.apache.polygene.test.util.Assume.assumeNoIbmJdk;
+
+public class SQLiteEntityStoreTest extends AbstractEntityStoreTest
+{
+    @BeforeClass
+    public static void beforeClass_IBMJDK()
+    {
+        assumeNoIbmJdk();
+    }
+
+    @Override
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // END SNIPPET: assembly
+        super.assemble( module );
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+
+        // START SNIPPET: assembly
+        // DataSourceService
+        new DBCPDataSourceServiceAssembler()
+            .identifiedBy( "sqlite-datasource-service" )
+            .visibleIn( Visibility.module )
+            .withConfig( config, Visibility.layer )
+            .assemble( module );
+
+        // DataSource
+        new DataSourceAssembler()
+            .withDataSourceServiceIdentity( "sqlite-datasource-service" )
+            .identifiedBy( "sqlite-datasource" )
+            .visibleIn( Visibility.module )
+            .withCircuitBreaker()
+            .assemble( module );
+
+        // SQL EntityStore
+        new SQLiteEntityStoreAssembler()
+            .visibleIn( Visibility.application )
+            .withConfig( config, Visibility.layer )
+            .assemble( module );
+    }
+    // END SNIPPET: assembly
+}
diff --git a/extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/DerbySQLEntityStoreTest.java b/extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/DerbySQLEntityStoreTest.java
deleted file mode 100644
index 31da42c..0000000
--- a/extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/DerbySQLEntityStoreTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql;
-
-import java.io.File;
-import java.sql.Connection;
-import java.sql.Statement;
-import javax.sql.DataSource;
-import org.apache.derby.iapi.services.io.FileUtil;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.sql.assembly.DerbySQLEntityStoreAssembler;
-import org.qi4j.entitystore.sql.internal.SQLs;
-import org.qi4j.library.sql.assembly.DataSourceAssembler;
-import org.qi4j.library.sql.common.SQLConfiguration;
-import org.qi4j.library.sql.dbcp.DBCPDataSourceServiceAssembler;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class DerbySQLEntityStoreTest
-    extends AbstractEntityStoreTest
-{
-    @Override
-    // START SNIPPET: assembly
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // END SNIPPET: assembly
-        super.assemble( module );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-
-        // START SNIPPET: assembly
-        // DataSourceService
-        new DBCPDataSourceServiceAssembler().
-            identifiedBy( "derby-datasource-service" ).
-            visibleIn( Visibility.module ).
-            withConfig( config, Visibility.layer ).
-            assemble( module );
-
-        // DataSource
-        new DataSourceAssembler().
-            withDataSourceServiceIdentity( "derby-datasource-service" ).
-            identifiedBy( "derby-datasource" ).
-            visibleIn( Visibility.module ).
-            withCircuitBreaker().
-            assemble( module );
-
-        // SQL EntityStore
-        new DerbySQLEntityStoreAssembler().
-            visibleIn( Visibility.application ).
-            withConfig( config, Visibility.layer ).
-            assemble( module );
-    }
-    // END SNIPPET: assembly
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        UnitOfWork uow = this.module.newUnitOfWork( UsecaseBuilder.newUsecase(
-            "Delete " + getClass().getSimpleName() + " test data" ) );
-        try
-        {
-            SQLConfiguration config = uow.get( SQLConfiguration.class,
-                                               DerbySQLEntityStoreAssembler.DEFAULT_ENTITYSTORE_IDENTITY );
-            Connection connection = module.findService( DataSource.class ).get().getConnection();
-            connection.setAutoCommit( false );
-            String schemaName = config.schemaName().get();
-            if( schemaName == null )
-            {
-                schemaName = SQLs.DEFAULT_SCHEMA_NAME;
-            }
-            try( Statement stmt = connection.createStatement() )
-            {
-                stmt.execute( String.format( "DELETE FROM %s." + SQLs.TABLE_NAME, schemaName ) );
-                connection.commit();
-            }
-            FileUtil.removeDirectory( new File( "target/qi4j-data" ) );
-        }
-        finally
-        {
-            uow.discard();
-            super.tearDown();
-        }
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/H2SQLEntityStoreTest.java b/extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/H2SQLEntityStoreTest.java
deleted file mode 100644
index dc3e8b2..0000000
--- a/extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/H2SQLEntityStoreTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.entitystore.sql;
-
-import java.io.File;
-import org.apache.derby.iapi.services.io.FileUtil;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.sql.assembly.H2SQLEntityStoreAssembler;
-import org.qi4j.library.sql.assembly.DataSourceAssembler;
-import org.qi4j.library.sql.dbcp.DBCPDataSourceServiceAssembler;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class H2SQLEntityStoreTest
-    extends AbstractEntityStoreTest
-{
-    @Override
-    // START SNIPPET: assembly
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // END SNIPPET: assembly
-        super.assemble( module );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-
-        // START SNIPPET: assembly
-        // DataSourceService
-        new DBCPDataSourceServiceAssembler().
-            identifiedBy( "h2-datasource-service" ).
-            visibleIn( Visibility.module ).
-            withConfig( config, Visibility.layer ).
-            assemble( module );
-
-        // DataSource
-        new DataSourceAssembler().
-            withDataSourceServiceIdentity( "h2-datasource-service" ).
-            identifiedBy( "h2-datasource" ).
-            visibleIn( Visibility.module ).
-            withCircuitBreaker().
-            assemble( module );
-
-        // SQL EntityStore
-        new H2SQLEntityStoreAssembler().
-            visibleIn( Visibility.application ).
-            withConfig( config, Visibility.layer ).
-            assemble( module );
-    }
-    // END SNIPPET: assembly
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        try
-        {
-            FileUtil.removeDirectory( new File( "target/qi4j-data" ) );
-        }
-        finally
-        {
-            super.tearDown();
-        }
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/MySQLEntityStoreTest.java b/extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/MySQLEntityStoreTest.java
deleted file mode 100644
index 1008287..0000000
--- a/extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/MySQLEntityStoreTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql;
-
-import java.sql.Connection;
-import java.sql.Statement;
-import javax.sql.DataSource;
-import org.junit.BeforeClass;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.sql.assembly.MySQLEntityStoreAssembler;
-import org.qi4j.entitystore.sql.internal.SQLs;
-import org.qi4j.library.sql.assembly.DataSourceAssembler;
-import org.qi4j.library.sql.common.SQLConfiguration;
-import org.qi4j.library.sql.dbcp.DBCPDataSourceServiceAssembler;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-import static org.qi4j.test.util.Assume.assumeConnectivity;
-
-public class MySQLEntityStoreTest
-    extends AbstractEntityStoreTest
-{
-    @BeforeClass
-    public static void beforeMySQLEntityStoreTests()
-    {
-        assumeConnectivity( "localhost", 3306 );
-    }
-
-    @Override
-    // START SNIPPET: assembly
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // END SNIPPET: assembly
-        super.assemble( module );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-
-        // START SNIPPET: assembly
-        // DataSourceService
-        new DBCPDataSourceServiceAssembler().
-            identifiedBy( "mysql-datasource-service" ).
-            visibleIn( Visibility.module ).
-            withConfig( config, Visibility.layer ).
-            assemble( module );
-
-        // DataSource
-        new DataSourceAssembler().
-            withDataSourceServiceIdentity( "mysql-datasource-service" ).
-            identifiedBy( "mysql-datasource" ).
-            visibleIn( Visibility.module ).
-            withCircuitBreaker().
-            assemble( module );
-
-        // SQL EntityStore
-        new MySQLEntityStoreAssembler().
-            visibleIn( Visibility.application ).
-            withConfig( config, Visibility.layer ).
-            assemble( module );
-    }
-    // END SNIPPET: assembly
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        if( true )
-        {
-            return;
-        }
-        UnitOfWork uow = this.module.newUnitOfWork(
-            UsecaseBuilder.newUsecase( "Delete " + getClass().getSimpleName() + " test data" )
-        );
-        try
-        {
-            SQLConfiguration config = uow.get( SQLConfiguration.class,
-                                               MySQLEntityStoreAssembler.DEFAULT_ENTITYSTORE_IDENTITY );
-            Connection connection = module.findService( DataSource.class ).get().getConnection();
-            connection.setAutoCommit( false );
-            String schemaName = config.schemaName().get();
-            if( schemaName == null )
-            {
-                schemaName = SQLs.DEFAULT_SCHEMA_NAME;
-            }
-            try( Statement stmt = connection.createStatement() )
-            {
-                stmt.execute( String.format( "DELETE FROM %s." + SQLs.TABLE_NAME, schemaName ) );
-                connection.commit();
-            }
-        }
-        finally
-        {
-            uow.discard();
-            super.tearDown();
-        }
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/PostgreSQLEntityStoreTest.java b/extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/PostgreSQLEntityStoreTest.java
deleted file mode 100644
index 7a6337f..0000000
--- a/extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/PostgreSQLEntityStoreTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.entitystore.sql;
-
-import java.sql.Connection;
-import java.sql.Statement;
-import javax.sql.DataSource;
-import org.junit.BeforeClass;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.sql.assembly.PostgreSQLEntityStoreAssembler;
-import org.qi4j.entitystore.sql.internal.SQLs;
-import org.qi4j.library.sql.assembly.DataSourceAssembler;
-import org.qi4j.library.sql.common.SQLConfiguration;
-import org.qi4j.library.sql.dbcp.DBCPDataSourceServiceAssembler;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-import static org.qi4j.test.util.Assume.assumeConnectivity;
-
-/**
- * WARN This test run only if localhost:5432 is listening.
- *
- * To run it you need to have a user & database set up in postgresql. Here are two snippets to create and drop the
- * needed test environment.
- *
- * Use 'password' as password for the jdbc_test_login user.
- *
- * <pre>
- * createuser -A -D -P -E -W jdbc_test_login
- * createdb -O jdbc_test_login -W jdbc_test_db
- * psql -d jdbc_testdb
- * CREATE EXTENSION ltree;
- * </pre>
- *
- * To clear the data:
- *
- * <pre>
- * dropdb -W jdbc_test_db
- * createdb -O jdbc_test_login -W jdbc_test_db
- * psql -d jdbc_test_db
- * CREATE EXTENSION ltree;
- * </pre>
- *
- * To remove the test user:
- *
- * <pre>
- * dropuser -W jdbc_test_login
- * </pre>
- */
-public class PostgreSQLEntityStoreTest
-    extends AbstractEntityStoreTest
-{
-    @BeforeClass
-    public static void beforePostgreSQLEntityStoreTests()
-    {
-        assumeConnectivity( "localhost", 5432 );
-    }
-
-    @Override
-    // START SNIPPET: assembly
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // END SNIPPET: assembly
-        super.assemble( module );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-
-        // START SNIPPET: assembly
-        // DataSourceService
-        new DBCPDataSourceServiceAssembler().
-            identifiedBy( "postgresql-datasource-service" ).
-            visibleIn( Visibility.module ).
-            withConfig( config, Visibility.layer ).
-            assemble( module );
-
-        // DataSource
-        new DataSourceAssembler().
-            withDataSourceServiceIdentity( "postgresql-datasource-service" ).
-            identifiedBy( "postgresql-datasource" ).
-            visibleIn( Visibility.module ).
-            withCircuitBreaker().
-            assemble( module );
-
-        // SQL EntityStore
-        new PostgreSQLEntityStoreAssembler().
-            visibleIn( Visibility.application ).
-            withConfig( config, Visibility.layer ).
-            assemble( module );
-    }
-    // END SNIPPET: assembly
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        UnitOfWork uow = module.newUnitOfWork(
-            UsecaseBuilder.newUsecase( "Delete " + getClass().getSimpleName() + " test data" )
-        );
-        try
-        {
-            SQLConfiguration config = uow.get( SQLConfiguration.class,
-                                               PostgreSQLEntityStoreAssembler.DEFAULT_ENTITYSTORE_IDENTITY );
-            Connection connection = module.findService( DataSource.class ).get().getConnection();
-            connection.setAutoCommit( false );
-            String schemaName = config.schemaName().get();
-            if( schemaName == null )
-            {
-                schemaName = SQLs.DEFAULT_SCHEMA_NAME;
-            }
-            try( Statement stmt = connection.createStatement() )
-            {
-                stmt.execute( String.format( "DELETE FROM %s." + SQLs.TABLE_NAME, schemaName ) );
-                connection.commit();
-            }
-        }
-        finally
-        {
-            uow.discard();
-            super.tearDown();
-        }
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/SQLiteEntityStoreTest.java b/extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/SQLiteEntityStoreTest.java
deleted file mode 100644
index 5e4d5d1..0000000
--- a/extensions/entitystore-sql/src/test/java/org/qi4j/entitystore/sql/SQLiteEntityStoreTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.entitystore.sql;
-
-import java.io.File;
-import org.apache.derby.iapi.services.io.FileUtil;
-import org.junit.BeforeClass;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.sql.assembly.SQLiteEntityStoreAssembler;
-import org.qi4j.library.sql.assembly.DataSourceAssembler;
-import org.qi4j.library.sql.dbcp.DBCPDataSourceServiceAssembler;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.entity.AbstractEntityStoreTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-import static org.qi4j.test.util.Assume.assumeNoIbmJdk;
-
-public class SQLiteEntityStoreTest
-    extends AbstractEntityStoreTest
-{
-    @BeforeClass
-    public static void beforeClass_IBMJDK()
-    {
-        assumeNoIbmJdk();
-    }
-
-    @Override
-    // START SNIPPET: assembly
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // END SNIPPET: assembly
-        super.assemble( module );
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-
-        // START SNIPPET: assembly
-        // DataSourceService
-        new DBCPDataSourceServiceAssembler().
-            identifiedBy( "sqlite-datasource-service" ).
-            visibleIn( Visibility.module ).
-            withConfig( config, Visibility.layer ).
-            assemble( module );
-
-        // DataSource
-        new DataSourceAssembler().
-            withDataSourceServiceIdentity( "sqlite-datasource-service" ).
-            identifiedBy( "sqlite-datasource" ).
-            visibleIn( Visibility.module ).
-            withCircuitBreaker().
-            assemble( module );
-
-        // SQL EntityStore
-        new SQLiteEntityStoreAssembler().
-            visibleIn( Visibility.application ).
-            withConfig( config, Visibility.layer ).
-            assemble( module );
-    }
-    // END SNIPPET: assembly
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        try
-        {
-            FileUtil.removeDirectory( new File( "target/qi4j-data" ) );
-        }
-        finally
-        {
-            super.tearDown();
-        }
-    }
-
-}
diff --git a/extensions/entitystore-sql/src/test/resources/derby-datasource.properties b/extensions/entitystore-sql/src/test/resources/derby-datasource.properties
index 8fc9229..35261ab 100644
--- a/extensions/entitystore-sql/src/test/resources/derby-datasource.properties
+++ b/extensions/entitystore-sql/src/test/resources/derby-datasource.properties
@@ -1,17 +1,22 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 enabled=true
 url=jdbc:derby:memory:testdb;create=true
diff --git a/extensions/entitystore-sql/src/test/resources/h2-datasource.properties b/extensions/entitystore-sql/src/test/resources/h2-datasource.properties
index b928cd9..74abf51 100644
--- a/extensions/entitystore-sql/src/test/resources/h2-datasource.properties
+++ b/extensions/entitystore-sql/src/test/resources/h2-datasource.properties
@@ -1,17 +1,22 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 enabled=true
 url=jdbc:h2:mem:test
diff --git a/extensions/entitystore-sql/src/test/resources/logback.xml b/extensions/entitystore-sql/src/test/resources/logback.xml
index 52bf1c5..03fb4dd 100644
--- a/extensions/entitystore-sql/src/test/resources/logback.xml
+++ b/extensions/entitystore-sql/src/test/resources/logback.xml
@@ -1,20 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <configuration>
 
     <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
@@ -27,8 +30,6 @@
         <appender-ref ref="stdout" />
     </root>
 
-    <logger name="org.qi4j.entitystore.sql" level="trace"/>
-    <!-- Put this one to trace level to see all SQL strings -->
-    <logger name="org.qi4j.entitystore.sql.internal.database.DatabaseSQLStringsBuilder" level="debug"/>
+    <logger name="org.apache.polygene.entitystore.sql" level="debug"/>
 
 </configuration>
\ No newline at end of file
diff --git a/extensions/entitystore-sql/src/test/resources/mysql-datasource.properties b/extensions/entitystore-sql/src/test/resources/mysql-datasource.properties
index 4cb7dba..a2f4175 100644
--- a/extensions/entitystore-sql/src/test/resources/mysql-datasource.properties
+++ b/extensions/entitystore-sql/src/test/resources/mysql-datasource.properties
@@ -1,20 +1,25 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 enabled=true
-url=jdbc:mysql://localhost:3306/jdbc_test_db?profileSQL=true
-driver=com.mysql.jdbc.Driver
+#url=jdbc:mysql://localhost:3306/jdbc_test_db?profileSQL=false&useLegacyDatetimeCode=false&serverTimezone=UTC&nullCatalogMeansCurrent=true&nullNamePatternMatchesAll=true
+driver=com.mysql.cj.jdbc.Driver
 username=root
 password=
diff --git a/extensions/entitystore-sql/src/test/resources/postgresql-datasource.properties b/extensions/entitystore-sql/src/test/resources/postgresql-datasource.properties
index f7d7ad5..bdda284 100644
--- a/extensions/entitystore-sql/src/test/resources/postgresql-datasource.properties
+++ b/extensions/entitystore-sql/src/test/resources/postgresql-datasource.properties
@@ -1,20 +1,24 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 enabled=true
-url=jdbc:postgresql://localhost:5432/jdbc_test_db
 driver=org.postgresql.Driver
 username=jdbc_test_login
 password=password
diff --git a/extensions/entitystore-sql/src/test/resources/sqlite-datasource.properties b/extensions/entitystore-sql/src/test/resources/sqlite-datasource.properties
index 36ac155..17e52b5 100644
--- a/extensions/entitystore-sql/src/test/resources/sqlite-datasource.properties
+++ b/extensions/entitystore-sql/src/test/resources/sqlite-datasource.properties
@@ -1,17 +1,22 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 enabled=true
 url=jdbc:sqlite::memory:
diff --git a/extensions/indexing-elasticsearch/build.gradle b/extensions/indexing-elasticsearch/build.gradle
index f413afd..fac6eec 100644
--- a/extensions/indexing-elasticsearch/build.gradle
+++ b/extensions/indexing-elasticsearch/build.gradle
@@ -1,37 +1,39 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ ElasticSearch Index/Query Extension"
+apply plugin: 'polygene-extension'
 
-jar { manifest { name = "Apache Zest™ Extension - Index/Query - ElasticSearch" } }
+description = "Apache Polygene™ ElasticSearch Index/Query Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - Index/Query - ElasticSearch" } }
 
 dependencies {
+  api polygene.core.bootstrap
 
-  compile project(":org.qi4j.core:org.qi4j.core.bootstrap")
-  compile project(":org.qi4j.libraries:org.qi4j.library.fileconfig")
-  compile libraries.slf4j_api
-  compile libraries.elasticsearch
+  implementation polygene.library( 'fileconfig' )
+  implementation libraries.elasticsearch
+  implementation libraries.slf4j_api
 
-  testCompile project(":org.qi4j.core:org.qi4j.core.testsupport")
+  runtimeOnly polygene.core.runtime
 
-  testRuntime project(":org.qi4j.core:org.qi4j.core.runtime")
-  testRuntime libraries.logback
+  testImplementation polygene.core.testsupport
 
+  testRuntimeOnly libraries.logback
 }
-
diff --git a/extensions/indexing-elasticsearch/dev-status.xml b/extensions/indexing-elasticsearch/dev-status.xml
index e6ddc55..a8ce0d7 100644
--- a/extensions/indexing-elasticsearch/dev-status.xml
+++ b/extensions/indexing-elasticsearch/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
     <status>
         <!--none,early,beta,stable,mature-->
         <codebase>beta</codebase>
diff --git a/extensions/indexing-elasticsearch/src/docs/index-elasticsearch.txt b/extensions/indexing-elasticsearch/src/docs/index-elasticsearch.txt
index bced084..3bb1feb 100644
--- a/extensions/indexing-elasticsearch/src/docs/index-elasticsearch.txt
+++ b/extensions/indexing-elasticsearch/src/docs/index-elasticsearch.txt
@@ -34,31 +34,18 @@
 
 Three modes of operation are supported:
 
-- in-memory ;
-- on-filesystem ;
-- clustered.
+- embedded local only filesystem based node ;
+- managed cluster client ;
+- with a provided client.
+
+In any case, Lucene hard limits apply.
+See the https://lucene.apache.org/core/6_1_0/core/org/apache/lucene/codecs/lucene60/package-summary.html#Limitations[Lucene File Format]
+documentation about maximum index size and document count.
+Moreover, each field cannot be larger than 32766 bytes in its serialized form.
 
 include::../../build/docs/buildinfo/artifact.txt[]
 
-== Embedded: in Memory or on FileSystem ==
-
-Both in-memory and on-filesystem assemblies share the same configuration properties, see below.
-
-=== In Memory Assembly ===
-
-In-memory ElasticSearch Index/Query service relies on the <<library-fileconfig>> to decide where it stores its
-transaction logs as there's no in-memory transaction log implementation in ElasticSearch.
-
-Assembly is done using the provided Assembler:
-
-[snippet,java]
-----
-source=extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/DocumentationSupport.java
-tag=memory
-----
-
-
-=== On FileSystem Assembly ===
+== Embedded on local file system ==
 
 Filesystem based ElasticSearch Index/Query service relies on the <<library-fileconfig>> to decide where it stores its
 index data, transaction logs etc...
@@ -67,7 +54,7 @@
 
 [snippet,java]
 ----
-source=extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/DocumentationSupport.java
+source=extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/DocumentationSupport.java
 tag=filesystem
 ----
 
@@ -76,11 +63,11 @@
 IMPORTANT: By default queries can only traverse Aggregated Associations, if you want to be able to traverse all
 Associations set the `indexNonAggregatedAssociations` configuration property to `TRUE`.
 
-Here are the configuration properties for both the in-memory and on-filesystem ElasticSearch Index/Query services:
+Here are the configuration properties for the filesystem ElasticSearch Index/Query services:
 
 [snippet,java]
 ----
-source=extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchConfiguration.java
+source=extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchConfiguration.java
 tag=config
 ----
 
@@ -95,7 +82,7 @@
 
 [snippet,java]
 ----
-source=extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/DocumentationSupport.java
+source=extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/DocumentationSupport.java
 tag=cluster
 ----
 
@@ -103,11 +90,38 @@
 === Configuration ===
 
 Here are the configuration properties for the clustered ElasticSearch Index/Query service. Note that it inherits the
-properties defined in the in-memory or on-filesystem configuration, see above.
+properties defined in the filesystem configuration, see above.
 
 [snippet,java]
 ----
-source=extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchClusterConfiguration.java
+source=extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchClusterConfiguration.java
+tag=config
+----
+
+Again, all configuration properties are defaulted meaning that you can use ElasticSearch Index/Query service without
+configuration.
+
+== Using a provided client ==
+
+=== Assembly ===
+
+Assembly is done using the provided Assembler:
+
+[snippet,java]
+----
+source=extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/DocumentationSupport.java
+tag=client
+----
+
+
+=== Configuration ===
+
+Here are the configuration properties for the ElasticSearch Index/Query service using a provided client.
+Note that the `clusterName` is ignored as this is managed by the client.
+
+[snippet,java]
+----
+source=extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchConfiguration.java
 tag=config
 ----
 
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchClusterConfiguration.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchClusterConfiguration.java
new file mode 100644
index 0000000..346a58d
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchClusterConfiguration.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.index.elasticsearch;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+// START SNIPPET: config
+public interface ElasticSearchClusterConfiguration
+        extends ElasticSearchConfiguration
+{
+
+    /**
+     * Coma separated list of nodes host:port.
+     * Defaults to '127.0.0.1:9300'.
+     */
+    @Optional Property<String> nodes();
+
+    /**
+     * Allows client to sniff the rest of the cluster, and add those into its list of machines to use.
+     * In this case, note that the ip addresses used will be the ones that the other nodes were started
+     * with (the “publish” address).
+     * Defaults to FALSE.
+     */
+    @UseDefaults Property<Boolean> clusterSniff();
+
+    /**
+     * Set to true to ignore cluster name validation of connected nodes.
+     * Defaults to FALSE.
+     */
+    @UseDefaults Property<Boolean> ignoreClusterName();
+
+    /**
+     * The time to wait for a ping response from a node.
+     * Defaults to 5s.
+     */
+    @Optional Property<String> pingTimeout();
+
+    /**
+     * How often to sample / ping the nodes listed and connected.
+     * Defaults to 5s.
+     */
+    @Optional Property<String> samplerInterval();
+
+}
+// END SNIPPET: config
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchConfiguration.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchConfiguration.java
new file mode 100644
index 0000000..df0c96a
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchConfiguration.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.index.elasticsearch;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+// START SNIPPET: config
+public interface ElasticSearchConfiguration
+{
+
+    /**
+     * Cluster name.
+     * Defaults to 'polygene_cluster'.
+     */
+    @Optional Property<String> clusterName();
+
+    /**
+     * Index name.
+     * Defaults to 'polygene_index'.
+     */
+    @Optional Property<String> index();
+
+    /**
+     * Set to true to index non aggregated associations as if they were aggregated.
+     * WARN: Don't use this if your domain model contains circular dependencies.
+     * Defaults to 'FALSE'.
+     */
+    @UseDefaults Property<Boolean> indexNonAggregatedAssociations();
+
+}
+// END SNIPPET: config
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchFinder.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchFinder.java
new file mode 100644
index 0000000..18c49eb
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchFinder.java
@@ -0,0 +1,523 @@
+/*
+ *  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.polygene.index.elasticsearch;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.query.grammar.AndPredicate;
+import org.apache.polygene.api.query.grammar.AssociationNotNullPredicate;
+import org.apache.polygene.api.query.grammar.AssociationNullPredicate;
+import org.apache.polygene.api.query.grammar.BinaryPredicate;
+import org.apache.polygene.api.query.grammar.ComparisonPredicate;
+import org.apache.polygene.api.query.grammar.ContainsAllPredicate;
+import org.apache.polygene.api.query.grammar.ContainsPredicate;
+import org.apache.polygene.api.query.grammar.EqPredicate;
+import org.apache.polygene.api.query.grammar.GePredicate;
+import org.apache.polygene.api.query.grammar.GtPredicate;
+import org.apache.polygene.api.query.grammar.LePredicate;
+import org.apache.polygene.api.query.grammar.LtPredicate;
+import org.apache.polygene.api.query.grammar.ManyAssociationContainsPredicate;
+import org.apache.polygene.api.query.grammar.MatchesPredicate;
+import org.apache.polygene.api.query.grammar.NamedAssociationContainsNamePredicate;
+import org.apache.polygene.api.query.grammar.NamedAssociationContainsPredicate;
+import org.apache.polygene.api.query.grammar.NePredicate;
+import org.apache.polygene.api.query.grammar.Notpredicate;
+import org.apache.polygene.api.query.grammar.OrPredicate;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.api.query.grammar.PropertyNotNullPredicate;
+import org.apache.polygene.api.query.grammar.PropertyNullPredicate;
+import org.apache.polygene.api.query.grammar.QuerySpecification;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.index.elasticsearch.ElasticSearchFinderSupport.ComplexTypeSupport;
+import org.apache.polygene.spi.query.EntityFinder;
+import org.apache.polygene.spi.query.EntityFinderException;
+import org.elasticsearch.action.search.SearchRequestBuilder;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.index.query.BoolQueryBuilder;
+import org.elasticsearch.index.query.QueryBuilder;
+import org.elasticsearch.search.sort.SortOrder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.polygene.index.elasticsearch.ElasticSearchFinderSupport.resolveVariable;
+import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
+import static org.elasticsearch.index.query.QueryBuilders.existsQuery;
+import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
+import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
+import static org.elasticsearch.index.query.QueryBuilders.regexpQuery;
+import static org.elasticsearch.index.query.QueryBuilders.termQuery;
+import static org.elasticsearch.index.query.QueryBuilders.wrapperQuery;
+
+@Mixins( ElasticSearchFinder.Mixin.class )
+public interface ElasticSearchFinder
+    extends EntityFinder
+{
+    class Mixin
+        implements EntityFinder
+    {
+        private static final Logger LOGGER = LoggerFactory.getLogger( ElasticSearchFinder.class );
+        private static final Map<Class<?>, ComplexTypeSupport> COMPLEX_TYPE_SUPPORTS = new HashMap<>( 0 );
+
+        @This
+        private ElasticSearchSupport support;
+
+        @Override
+        public Stream<EntityReference> findEntities( Class<?> resultType,
+                                                     Predicate<Composite> whereClause,
+                                                     List<OrderBy> orderBySegments,
+                                                     Integer firstResult,
+                                                     Integer maxResults,
+                                                     Map<String, Object> variables ) throws EntityFinderException
+        {
+            // Prepare request
+            SearchRequestBuilder request = support.client().prepareSearch( support.index() );
+
+            BoolQueryBuilder baseQueryBuilder = baseQuery( resultType );
+            QueryBuilder whereQueryBuilder = processWhereSpecification( baseQueryBuilder, whereClause, variables );
+
+            request.setQuery( boolQuery().must( whereQueryBuilder ).filter( baseQueryBuilder ) );
+            if( firstResult != null )
+            {
+                request.setFrom( firstResult );
+            }
+            if( maxResults != null )
+            {
+                request.setSize( maxResults );
+            }
+            else
+            {
+                //request.setSize( Integer.MAX_VALUE ); // TODO Use scrolls?
+            }
+            if( orderBySegments != null )
+            {
+                for( OrderBy order : orderBySegments )
+                {
+                    request.addSort( order.property().toString(),
+                                     order.order() == OrderBy.Order.ASCENDING ? SortOrder.ASC : SortOrder.DESC );
+                }
+            }
+
+            // Log
+            LOGGER.debug( "Will search Entities: {}", request );
+
+            // Execute
+            SearchResponse response = request.execute().actionGet();
+
+            return StreamSupport.stream( response.getHits().spliterator(), false )
+                                .map( hit -> EntityReference.parseEntityReference( hit.id() ) );
+        }
+
+        @Override
+        public EntityReference findEntity( Class<?> resultType,
+                                           Predicate<Composite> whereClause,
+                                           Map<String, Object> variables )
+            throws EntityFinderException
+        {
+            // Prepare request
+            SearchRequestBuilder request = support.client().prepareSearch( support.index() );
+
+            BoolQueryBuilder baseQueryBuilder = baseQuery( resultType );
+            QueryBuilder whereQueryBuilder = processWhereSpecification( baseQueryBuilder, whereClause, variables );
+
+            request.setQuery( boolQuery().must( whereQueryBuilder ).filter( baseQueryBuilder ) );
+            request.setSize( 1 );
+
+            // Log
+            LOGGER.debug( "Will search Entity: {}", request );
+
+            // Execute
+            SearchResponse response = request.execute().actionGet();
+
+            if( response.getHits().totalHits() == 1 )
+            {
+                return EntityReference.parseEntityReference( response.getHits().getAt( 0 ).id() );
+            }
+
+            return null;
+        }
+
+        @Override
+        public long countEntities( Class<?> resultType,
+                                   Predicate<Composite> whereClause,
+                                   Map<String, Object> variables )
+            throws EntityFinderException
+        {
+            // Prepare request
+            SearchRequestBuilder request = support.client().prepareSearch( support.index() ).setSize( 0 );
+
+            BoolQueryBuilder baseQueryBuilder = baseQuery( resultType );
+            QueryBuilder whereQueryBuilder = processWhereSpecification( baseQueryBuilder, whereClause, variables );
+
+            request.setQuery( boolQuery().must( whereQueryBuilder ).filter( baseQueryBuilder ) );
+
+            // Log
+            LOGGER.debug( "Will count Entities: {}", request );
+
+            // Execute
+            SearchResponse count = request.execute().actionGet();
+
+            return count.getHits().getTotalHits();
+        }
+
+        private static BoolQueryBuilder baseQuery( Class<?> resultType )
+        {
+            return boolQuery().must( termQuery( "_types", resultType.getName() ) );
+        }
+
+        private QueryBuilder processWhereSpecification( BoolQueryBuilder queryBuilder,
+                                                        Predicate<Composite> spec,
+                                                        Map<String, Object> variables )
+            throws EntityFinderException
+        {
+            if( spec == null )
+            {
+                return matchAllQuery();
+            }
+
+            if( spec instanceof QuerySpecification )
+            {
+                return wrapperQuery( ( (QuerySpecification) spec ).query() );
+            }
+
+            processSpecification( queryBuilder, spec, variables );
+            return matchAllQuery();
+        }
+
+        private void processSpecification( BoolQueryBuilder queryBuilder,
+                                           Predicate<Composite> spec,
+                                           Map<String, Object> variables )
+            throws EntityFinderException
+        {
+            if( spec instanceof BinaryPredicate )
+            {
+                BinaryPredicate binSpec = (BinaryPredicate) spec;
+                processBinarySpecification( queryBuilder, binSpec, variables );
+            }
+            else if( spec instanceof Notpredicate )
+            {
+                Notpredicate notSpec = (Notpredicate) spec;
+                processNotSpecification( queryBuilder, notSpec, variables );
+            }
+            else if( spec instanceof ComparisonPredicate )
+            {
+                ComparisonPredicate<?> compSpec = (ComparisonPredicate<?>) spec;
+                processComparisonSpecification( queryBuilder, compSpec, variables );
+            }
+            else if( spec instanceof ContainsAllPredicate )
+            {
+                ContainsAllPredicate<?> contAllSpec = (ContainsAllPredicate) spec;
+                processContainsAllSpecification( queryBuilder, contAllSpec, variables );
+            }
+            else if( spec instanceof ContainsPredicate )
+            {
+                ContainsPredicate<?> contSpec = (ContainsPredicate) spec;
+                processContainsSpecification( queryBuilder, contSpec, variables );
+            }
+            else if( spec instanceof MatchesPredicate )
+            {
+                MatchesPredicate matchSpec = (MatchesPredicate) spec;
+                processMatchesSpecification( queryBuilder, matchSpec, variables );
+            }
+            else if( spec instanceof PropertyNotNullPredicate )
+            {
+                PropertyNotNullPredicate<?> propNotNullSpec = (PropertyNotNullPredicate) spec;
+                processPropertyNotNullSpecification( queryBuilder, propNotNullSpec );
+            }
+            else if( spec instanceof PropertyNullPredicate )
+            {
+                PropertyNullPredicate<?> propNullSpec = (PropertyNullPredicate) spec;
+                processPropertyNullSpecification( queryBuilder, propNullSpec );
+            }
+            else if( spec instanceof AssociationNotNullPredicate )
+            {
+                AssociationNotNullPredicate<?> assNotNullSpec = (AssociationNotNullPredicate) spec;
+                processAssociationNotNullSpecification( queryBuilder, assNotNullSpec );
+            }
+            else if( spec instanceof AssociationNullPredicate )
+            {
+                AssociationNullPredicate<?> assNullSpec = (AssociationNullPredicate) spec;
+                processAssociationNullSpecification( queryBuilder, assNullSpec );
+            }
+            else if( spec instanceof ManyAssociationContainsPredicate )
+            {
+                ManyAssociationContainsPredicate<?> manyAssContSpec = (ManyAssociationContainsPredicate) spec;
+                processManyAssociationContainsSpecification( queryBuilder, manyAssContSpec, variables );
+            }
+            else if( spec instanceof NamedAssociationContainsPredicate )
+            {
+
+                NamedAssociationContainsPredicate<?> namedAssContSpec = (NamedAssociationContainsPredicate) spec;
+                processNamedAssociationContainsSpecification( queryBuilder, namedAssContSpec, variables );
+            }
+            else if( spec instanceof NamedAssociationContainsNamePredicate )
+            {
+
+                NamedAssociationContainsNamePredicate<?> namedAssContNameSpec
+                    = (NamedAssociationContainsNamePredicate) spec;
+                processNamedAssociationContainsNameSpecification( queryBuilder, namedAssContNameSpec, variables );
+            }
+            else
+            {
+                throw new UnsupportedOperationException( "Query specification unsupported by Elastic Search "
+                                                         + "(New Query API support missing?): "
+                                                         + spec.getClass() + ": " + spec );
+            }
+        }
+
+        private void processBinarySpecification( BoolQueryBuilder queryBuilder,
+                                                 BinaryPredicate spec,
+                                                 Map<String, Object> variables )
+            throws EntityFinderException
+        {
+            LOGGER.trace( "Processing BinarySpecification {}", spec );
+            Iterable<Predicate<Composite>> operands = spec.operands();
+
+            if( spec instanceof AndPredicate )
+            {
+                BoolQueryBuilder andBuilder = boolQuery();
+                for( Predicate<Composite> operand : operands )
+                {
+                    processSpecification( andBuilder, operand, variables );
+                }
+                queryBuilder.must( andBuilder );
+            }
+            else if( spec instanceof OrPredicate )
+            {
+                BoolQueryBuilder orBuilder = boolQuery();
+                for( Predicate<Composite> operand : operands )
+                {
+                    BoolQueryBuilder shouldBuilder = boolQuery();
+                    processSpecification( shouldBuilder, operand, variables );
+                    orBuilder.should( shouldBuilder );
+                }
+                orBuilder.minimumShouldMatch( 1 );
+                queryBuilder.must( orBuilder );
+            }
+            else
+            {
+                throw new UnsupportedOperationException( "Binary Query specification is nor an AndSpecification "
+                                                         + "nor an OrSpecification, cannot continue." );
+            }
+        }
+
+        private void processNotSpecification( BoolQueryBuilder queryBuilder,
+                                              Notpredicate spec,
+                                              Map<String, Object> variables )
+            throws EntityFinderException
+        {
+            LOGGER.trace( "Processing NotSpecification {}", spec );
+            BoolQueryBuilder operandBuilder = boolQuery();
+            processSpecification( operandBuilder, spec.operand(), variables );
+            queryBuilder.mustNot( operandBuilder );
+        }
+
+        private void processComparisonSpecification( BoolQueryBuilder queryBuilder,
+                                                     ComparisonPredicate<?> spec,
+                                                     Map<String, Object> variables )
+        {
+            LOGGER.trace( "Processing ComparisonSpecification {}", spec );
+
+            if( spec.value() instanceof ValueComposite )
+            {
+                // Query by "example value"
+                throw new UnsupportedOperationException( "ElasticSearch Index/Query does not support complex "
+                                                         + "queries, ie. queries by 'example value'." );
+            }
+            else if( COMPLEX_TYPE_SUPPORTS.get( spec.value().getClass() ) != null )
+            {
+                // Query on complex type property
+                ComplexTypeSupport support = COMPLEX_TYPE_SUPPORTS.get( spec.value().getClass() );
+                queryBuilder.must( support.comparison( spec, variables ) );
+            }
+            else
+            {
+                // Query by simple property value
+                String name = spec.property().toString();
+                Object value = resolveVariable( spec.value(), variables );
+                if( spec instanceof EqPredicate )
+                {
+                    queryBuilder.must( termQuery( name, value ) );
+                }
+                else if( spec instanceof NePredicate )
+                {
+                    queryBuilder.must( existsQuery( name ) ).mustNot( termQuery( name, value ) );
+                }
+                else if( spec instanceof GePredicate )
+                {
+                    queryBuilder.must( rangeQuery( name ).gte( value ) );
+                }
+                else if( spec instanceof GtPredicate )
+                {
+                    queryBuilder.must( rangeQuery( name ).gt( value ) );
+                }
+                else if( spec instanceof LePredicate )
+                {
+                    queryBuilder.must( rangeQuery( name ).lte( value ) );
+                }
+                else if( spec instanceof LtPredicate )
+                {
+                    queryBuilder.must( rangeQuery( name ).lt( value ) );
+                }
+                else
+                {
+                    throw new UnsupportedOperationException( "Query specification unsupported by Elastic Search "
+                                                             + "(New Query API support missing?): "
+                                                             + spec.getClass() + ": " + spec );
+                }
+            }
+        }
+
+        private void processContainsAllSpecification( BoolQueryBuilder queryBuilder,
+                                                      ContainsAllPredicate<?> spec,
+                                                      Map<String, Object> variables )
+        {
+            LOGGER.trace( "Processing ContainsAllSpecification {}", spec );
+            Collection<?> values = spec.containedValues();
+            if( values.isEmpty() )
+            {
+                // Ignore empty contains all spec
+                return;
+            }
+            Object firstValue = values.iterator().next();
+            if( firstValue instanceof ValueComposite )
+            {
+                // Query by complex property "example value"
+                throw new UnsupportedOperationException( "ElasticSearch Index/Query does not support complex "
+                                                         + "queries, ie. queries by 'example value'." );
+            }
+            else if( COMPLEX_TYPE_SUPPORTS.get( firstValue.getClass() ) != null )
+            {
+                ComplexTypeSupport support = COMPLEX_TYPE_SUPPORTS.get( firstValue.getClass() );
+                queryBuilder.must( support.containsAll( spec, variables ) );
+            }
+            else
+            {
+                String name = spec.collectionProperty().toString();
+                BoolQueryBuilder contAllBuilder = boolQuery();
+                for( Object value : values )
+                {
+                    contAllBuilder.must( termQuery( name, resolveVariable( value, variables ) ) );
+                }
+                queryBuilder.must( contAllBuilder );
+            }
+        }
+
+        private void processContainsSpecification( BoolQueryBuilder queryBuilder,
+                                                   ContainsPredicate<?> spec,
+                                                   Map<String, Object> variables )
+        {
+            LOGGER.trace( "Processing ContainsSpecification {}", spec );
+            String name = spec.collectionProperty().toString();
+            if( spec.value() instanceof ValueComposite )
+            {
+                // Query by complex property "example value"
+                throw new UnsupportedOperationException( "ElasticSearch Index/Query does not support complex "
+                                                         + "queries, ie. queries by 'example value'." );
+            }
+            else if( COMPLEX_TYPE_SUPPORTS.get( spec.value().getClass() ) != null )
+            {
+                ComplexTypeSupport support = COMPLEX_TYPE_SUPPORTS.get( spec.value().getClass() );
+                queryBuilder.must( support.contains( spec, variables ) );
+            }
+            else
+            {
+                Object value = resolveVariable( spec.value(), variables );
+                queryBuilder.must( termQuery( name, value ) );
+            }
+        }
+
+        private void processMatchesSpecification( BoolQueryBuilder queryBuilder,
+                                                  MatchesPredicate spec,
+                                                  Map<String, Object> variables )
+        {
+            LOGGER.trace( "Processing MatchesSpecification {}", spec );
+            String name = spec.property().toString();
+            String regexp = resolveVariable( spec.regexp(), variables ).toString();
+            queryBuilder.must( regexpQuery( name, regexp ) );
+        }
+
+        private void processPropertyNotNullSpecification( BoolQueryBuilder queryBuilder,
+                                                          PropertyNotNullPredicate<?> spec )
+        {
+            LOGGER.trace( "Processing PropertyNotNullSpecification {}", spec );
+            queryBuilder.must( existsQuery( spec.property().toString() ) );
+        }
+
+        private void processPropertyNullSpecification( BoolQueryBuilder queryBuilder,
+                                                       PropertyNullPredicate<?> spec )
+        {
+            LOGGER.trace( "Processing PropertyNullSpecification {}", spec );
+            queryBuilder.mustNot( existsQuery( ( spec.property().toString() ) ) );
+        }
+
+        private void processAssociationNotNullSpecification( BoolQueryBuilder queryBuilder,
+                                                             AssociationNotNullPredicate<?> spec )
+        {
+            LOGGER.trace( "Processing AssociationNotNullSpecification {}", spec );
+            queryBuilder.must( existsQuery( spec.association().toString() + ".identity" ) );
+        }
+
+        private void processAssociationNullSpecification( BoolQueryBuilder queryBuilder,
+                                                          AssociationNullPredicate<?> spec )
+        {
+            LOGGER.trace( "Processing AssociationNullSpecification {}", spec );
+            queryBuilder.mustNot( existsQuery( ( spec.association().toString() + ".identity" ) ) );
+        }
+
+        private void processManyAssociationContainsSpecification( BoolQueryBuilder queryBuilder,
+                                                                  ManyAssociationContainsPredicate<?> spec,
+                                                                  Map<String, Object> variables )
+        {
+            LOGGER.trace( "Processing ManyAssociationContainsSpecification {}", spec );
+            String name = spec.manyAssociation().toString() + ".identity";
+            Object value = resolveVariable( spec.value(), variables );
+            queryBuilder.must( termQuery( name, value ) );
+        }
+
+        private void processNamedAssociationContainsSpecification( BoolQueryBuilder queryBuilder,
+                                                                   NamedAssociationContainsPredicate<?> spec,
+                                                                   Map<String, Object> variables )
+        {
+            LOGGER.trace( "Processing NamedAssociationContainsSpecification {}", spec );
+            String name = spec.namedAssociation().toString() + ".identity";
+            Object value = resolveVariable( spec.value(), variables );
+            queryBuilder.must( termQuery( name, value ) );
+        }
+
+        private void processNamedAssociationContainsNameSpecification( BoolQueryBuilder queryBuilder,
+                                                                       NamedAssociationContainsNamePredicate<?> spec,
+                                                                       Map<String, Object> variables )
+        {
+            LOGGER.trace( "Processing NamedAssociationContainsNameSpecification {}", spec );
+            String name = spec.namedAssociation().toString() + "._named";
+            Object value = resolveVariable( spec.name(), variables );
+            queryBuilder.must( termQuery( name, value ) );
+        }
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchFinderSupport.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchFinderSupport.java
new file mode 100644
index 0000000..c94bbb6
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchFinderSupport.java
@@ -0,0 +1,67 @@
+/*
+ *  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.polygene.index.elasticsearch;
+
+import java.util.Map;
+import org.apache.polygene.api.query.grammar.ComparisonPredicate;
+import org.apache.polygene.api.query.grammar.ContainsAllPredicate;
+import org.apache.polygene.api.query.grammar.ContainsPredicate;
+import org.apache.polygene.api.query.grammar.Variable;
+import org.elasticsearch.index.query.QueryBuilder;
+
+
+/* package */ final class ElasticSearchFinderSupport
+{
+
+    /* package */ static Object resolveVariable( Object value, Map<String, Object> variables )
+    {
+        if( value == null )
+        {
+            return null;
+        }
+        if( value instanceof Variable )
+        {
+            Variable var = (Variable) value;
+            Object realValue = variables.get( var.variableName() );
+            if( realValue == null )
+            {
+                throw new IllegalArgumentException( "Variable " + var.variableName() + " not bound" );
+            }
+            return realValue;
+        }
+        return value;
+    }
+
+    /* package */ interface ComplexTypeSupport
+    {
+
+        QueryBuilder comparison( ComparisonPredicate<?> spec, Map<String, Object> variables );
+
+        QueryBuilder contains( ContainsPredicate<?> spec, Map<String, Object> variables );
+
+        QueryBuilder containsAll( ContainsAllPredicate<?> spec, Map<String, Object> variables );
+
+    }
+
+    private ElasticSearchFinderSupport()
+    {
+    }
+
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchIndexException.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchIndexException.java
new file mode 100644
index 0000000..b792a17
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchIndexException.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.index.elasticsearch;
+
+public class ElasticSearchIndexException
+        extends RuntimeException
+{
+
+    public ElasticSearchIndexException( String string )
+    {
+        super( string );
+    }
+
+    public ElasticSearchIndexException( String string, Throwable thrwbl )
+    {
+        super( string, thrwbl );
+    }
+
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchIndexExporter.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchIndexExporter.java
new file mode 100644
index 0000000..41ba67a
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchIndexExporter.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.index.elasticsearch;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.spi.query.IndexExporter;
+
+@Mixins( ElasticSearchIndexExporter.Mixin.class )
+public interface ElasticSearchIndexExporter
+        extends IndexExporter
+{
+
+    class Mixin
+            implements ElasticSearchIndexExporter
+    {
+
+        @Override
+        public void exportReadableToStream( PrintStream out )
+                throws IOException, UnsupportedOperationException
+        {
+            exportFormalToWriter( new PrintWriter( out ) );
+        }
+
+        @Override
+        public void exportFormalToWriter( PrintWriter out )
+                throws IOException, UnsupportedOperationException
+        {
+            // TODO
+        }
+
+    }
+
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchIndexer.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchIndexer.java
new file mode 100644
index 0000000..c8caa7d
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchIndexer.java
@@ -0,0 +1,332 @@
+/*
+ *  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.polygene.index.elasticsearch;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonValue;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.time.SystemTime;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.entity.ManyAssociationState;
+import org.apache.polygene.spi.entity.NamedAssociationState;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork;
+import org.apache.polygene.spi.entitystore.StateChangeListener;
+import org.apache.polygene.spi.serialization.JsonSerializer;
+import org.elasticsearch.action.bulk.BulkRequestBuilder;
+import org.elasticsearch.action.bulk.BulkResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Listen to Entity state changes and index them in ElasticSearch.
+ *
+ * QUID Use two indices, one for strict queries, one for full text and fuzzy search?
+ */
+@Mixins( ElasticSearchIndexer.Mixin.class )
+public interface ElasticSearchIndexer extends StateChangeListener
+{
+    class Mixin
+        implements StateChangeListener
+    {
+        private static final Logger LOGGER = LoggerFactory.getLogger( ElasticSearchIndexer.class );
+
+        @Structure
+        private ModuleDescriptor module;
+
+        @Service
+        private EntityStore entityStore;
+
+        @Service
+        private JsonSerializer jsonSerializer;
+
+        @Service
+        private JavaxJsonFactories jsonFactories;
+
+        @This
+        private ElasticSearchSupport support;
+
+        public void emptyIndex()
+        {
+            support.client().admin().indices().prepareDelete( support.index() ).execute().actionGet();
+        }
+
+        @Override
+        public void notifyChanges( Iterable<EntityState> changedStates )
+        {
+            // All updated or new states
+            Map<String, EntityState> newStates = new HashMap<>();
+            for( EntityState eState : changedStates )
+            {
+                if( eState.status() == EntityStatus.UPDATED || eState.status() == EntityStatus.NEW )
+                {
+                    newStates.put( eState.entityReference().identity().toString(), eState );
+                }
+            }
+
+            EntityStoreUnitOfWork uow = entityStore.newUnitOfWork(
+                module,
+                UsecaseBuilder.newUsecase( "Load associations for indexing" ),
+                SystemTime.now()
+            );
+
+            // Bulk index request builder
+            BulkRequestBuilder bulkBuilder = support.client().prepareBulk();
+
+            // Handle changed entity states
+            for( EntityState changedState : changedStates )
+            {
+                if( changedState.entityDescriptor().queryable() )
+                {
+                    switch( changedState.status() )
+                    {
+                        case REMOVED:
+                            LOGGER.trace( "Removing Entity State from Index: {}", changedState );
+                            remove( bulkBuilder, changedState.entityReference().identity().toString() );
+                            break;
+                        case UPDATED:
+                            LOGGER.trace( "Updating Entity State in Index: {}", changedState );
+                            remove( bulkBuilder, changedState.entityReference().identity().toString() );
+                            String updatedJson = toJSON( changedState, newStates, uow ).toString();
+                            LOGGER.trace( "Will index: {}", updatedJson );
+                            index( bulkBuilder, changedState.entityReference().identity().toString(), updatedJson );
+                            break;
+                        case NEW:
+                            LOGGER.trace( "Creating Entity State in Index: {}", changedState );
+                            String newJson = toJSON( changedState, newStates, uow ).toString();
+                            LOGGER.trace( "Will index: {}", newJson );
+                            index( bulkBuilder, changedState.entityReference().identity().toString(), newJson );
+                            break;
+                        case LOADED:
+                        default:
+                            // Ignored
+                            break;
+                    }
+                }
+            }
+
+            uow.discard();
+
+            if( bulkBuilder.numberOfActions() > 0 )
+            {
+
+                // Execute bulk actions
+                BulkResponse bulkResponse = bulkBuilder.execute().actionGet();
+
+                // Handle errors
+                if( bulkResponse.hasFailures() )
+                {
+                    throw new ElasticSearchIndexException( bulkResponse.buildFailureMessage() );
+                }
+
+                LOGGER.debug( "Indexing changed Entity states took {}ms", bulkResponse.getTookInMillis() );
+
+                // Refresh index
+                support.client().admin().indices().prepareRefresh( support.index() ).execute().actionGet();
+            }
+        }
+
+        private void remove( BulkRequestBuilder bulkBuilder, String identity )
+        {
+            bulkBuilder.add( support.client().
+                prepareDelete( support.index(), support.entitiesType(), identity ) );
+        }
+
+        private void index( BulkRequestBuilder bulkBuilder, String identity, String json )
+        {
+            bulkBuilder.add( support.client().
+                prepareIndex( support.index(), support.entitiesType(), identity ).
+                                        setSource( json ) );
+        }
+
+        /**
+         * <pre>
+         * {
+         *  "_identity": "ENTITY-IDENTITY",
+         *  "_types": [ "All", "Entity", "types" ],
+         *  "property.name": property.value,
+         *  "association.name": { "reference": "ASSOCIATED-IDENTITY" }
+         *  "manyassociation.name": [ { "reference": "ASSOCIATED" }, { "reference": "IDENTITIES" } ]
+         *  "namedassociation.name": [ { "_named": "NAMED", "reference": "IDENTITY" } }
+         * }
+         * </pre>
+         */
+        private JsonObject toJSON( EntityState state, Map<String, EntityState> newStates, EntityStoreUnitOfWork uow )
+        {
+            JsonObjectBuilder builder = jsonFactories.builderFactory().createObjectBuilder();
+
+            builder.add( "_identity", state.entityReference().identity().toString() );
+
+            JsonArrayBuilder typesBuilder = jsonFactories.builderFactory().createArrayBuilder();
+            state.entityDescriptor().mixinTypes().map( Classes.toClassName() ).forEach( typesBuilder::add );
+            builder.add( "_types", typesBuilder.build() );
+
+            EntityDescriptor entityType = state.entityDescriptor();
+
+            // Properties
+            entityType.state().properties().forEach(
+                propDesc ->
+                {
+                    if( propDesc.queryable() )
+                    {
+                        String key = propDesc.qualifiedName().name();
+                        Object value = state.propertyValueOf( propDesc.qualifiedName() );
+                        JsonValue jsonValue = jsonSerializer.toJson( Serializer.Options.NO_TYPE_INFO, value );
+                        builder.add( key, jsonValue );
+                    }
+                } );
+
+            // Associations
+            entityType.state().associations().forEach(
+                assocDesc ->
+                {
+                    if( assocDesc.queryable() )
+                    {
+                        String key = assocDesc.qualifiedName().name();
+                        EntityReference associated = state.associationValueOf( assocDesc.qualifiedName() );
+                        if( associated == null )
+                        {
+                            builder.add( key, JsonValue.NULL );
+                        }
+                        else
+                        {
+                            if( assocDesc.isAggregated() || support.indexNonAggregatedAssociations() )
+                            {
+                                if( newStates.containsKey( associated.identity().toString() ) )
+                                {
+                                    builder.add( key, toJSON( newStates.get( associated.identity().toString() ),
+                                                              newStates, uow ) );
+                                }
+                                else
+                                {
+                                    EntityReference reference = EntityReference.create( associated.identity() );
+                                    EntityState assocState = uow.entityStateOf( entityType.module(), reference );
+                                    builder.add( key, toJSON( assocState, newStates, uow ) );
+                                }
+                            }
+                            else
+                            {
+                                builder.add( key, jsonFactories.builderFactory().createObjectBuilder()
+                                                               .add( "reference", associated.identity().toString() ) );
+                            }
+                        }
+                    }
+                } );
+
+            // ManyAssociations
+            entityType.state().manyAssociations().forEach(
+                manyAssocDesc ->
+                {
+                    if( manyAssocDesc.queryable() )
+                    {
+                        String key = manyAssocDesc.qualifiedName().name();
+                        JsonArrayBuilder assBuilder = jsonFactories.builderFactory().createArrayBuilder();
+                        ManyAssociationState assocs = state.manyAssociationValueOf( manyAssocDesc.qualifiedName() );
+                        for( EntityReference associated : assocs )
+                        {
+                            if( manyAssocDesc.isAggregated() || support.indexNonAggregatedAssociations() )
+                            {
+                                if( newStates.containsKey( associated.identity().toString() ) )
+                                {
+                                    assBuilder.add( toJSON( newStates.get( associated.identity().toString() ),
+                                                            newStates, uow ) );
+                                }
+                                else
+                                {
+                                    EntityReference reference = EntityReference.create( associated.identity() );
+                                    EntityState assocState = uow.entityStateOf( entityType.module(), reference );
+                                    assBuilder.add( toJSON( assocState, newStates, uow ) );
+                                }
+                            }
+                            else
+                            {
+                                assBuilder.add( jsonFactories.builderFactory().createObjectBuilder()
+                                                             .add( "reference",
+                                                                   associated.identity().toString() ) );
+                            }
+                        }
+                        builder.add( key, assBuilder.build() );
+                    }
+                } );
+
+            // NamedAssociations
+            entityType.state().namedAssociations().forEach(
+                namedAssocDesc ->
+                {
+                    if( namedAssocDesc.queryable() )
+                    {
+                        String key = namedAssocDesc.qualifiedName().name();
+                        JsonArrayBuilder assBuilder = jsonFactories.builderFactory().createArrayBuilder();
+                        NamedAssociationState assocs = state.namedAssociationValueOf(
+                            namedAssocDesc.qualifiedName() );
+                        for( String name : assocs )
+                        {
+                            Identity identity = assocs.get( name ).identity();
+                            if( namedAssocDesc.isAggregated() || support.indexNonAggregatedAssociations() )
+                            {
+                                String identityString = identity.toString();
+                                if( newStates.containsKey( identityString ) )
+                                {
+                                    assBuilder.add(
+                                        jsonFactories.cloneBuilder( toJSON( newStates.get( identityString ),
+                                                                            newStates, uow ) )
+                                                     .add( "_named", name )
+                                                     .build() );
+                                }
+                                else
+                                {
+                                    EntityReference reference = EntityReference.create( identity );
+                                    EntityState assocState = uow.entityStateOf( entityType.module(), reference );
+                                    assBuilder.add(
+                                        jsonFactories.cloneBuilder( toJSON( assocState, newStates, uow ) )
+                                                     .add( "_named", name ).build() );
+                                }
+                            }
+                            else
+                            {
+                                assBuilder.add( jsonFactories.builderFactory().createObjectBuilder()
+                                                             .add( "_named", name )
+                                                             .add( "reference", identity.toString() )
+                                                             .build() );
+                            }
+                        }
+                        builder.add( key, assBuilder.build() );
+                    }
+                } );
+            return builder.build();
+        }
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchSupport.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchSupport.java
new file mode 100644
index 0000000..36331d8
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchSupport.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.index.elasticsearch;
+
+import org.elasticsearch.client.Client;
+import org.apache.polygene.api.service.ServiceActivation;
+
+public interface ElasticSearchSupport
+        extends ServiceActivation
+{
+
+    Client client();
+
+    String index();
+
+    String entitiesType();
+
+    boolean indexNonAggregatedAssociations();
+
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/assembly/ESClientIndexQueryAssembler.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/assembly/ESClientIndexQueryAssembler.java
new file mode 100644
index 0000000..c6a0bdc
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/assembly/ESClientIndexQueryAssembler.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.index.elasticsearch.assembly;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.elasticsearch.ElasticSearchConfiguration;
+import org.apache.polygene.index.elasticsearch.client.ESClientIndexQueryService;
+import org.apache.polygene.index.elasticsearch.internal.AbstractElasticSearchAssembler;
+import org.elasticsearch.client.Client;
+
+public class ESClientIndexQueryAssembler
+    extends AbstractElasticSearchAssembler<ESClientIndexQueryAssembler>
+{
+    private final Client client;
+
+    public ESClientIndexQueryAssembler( final Client client )
+    {
+        this.client = client;
+    }
+
+    @Override
+    public void assemble( final ModuleAssembly module ) throws AssemblyException
+    {
+        module.services( ESClientIndexQueryService.class )
+              .taggedWith( "elasticsearch", "query", "indexing" )
+              .identifiedBy( identity() )
+              .setMetaInfo( client )
+              .visibleIn( visibility() )
+              .instantiateOnStartup();
+
+        if( hasConfig() )
+        {
+            configModule().entities( ElasticSearchConfiguration.class )
+                          .visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/assembly/ESClusterIndexQueryAssembler.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/assembly/ESClusterIndexQueryAssembler.java
new file mode 100644
index 0000000..f2d803d
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/assembly/ESClusterIndexQueryAssembler.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.index.elasticsearch.assembly;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.elasticsearch.ElasticSearchClusterConfiguration;
+import org.apache.polygene.index.elasticsearch.cluster.ESClusterIndexQueryService;
+import org.apache.polygene.index.elasticsearch.internal.AbstractElasticSearchAssembler;
+
+public class ESClusterIndexQueryAssembler
+    extends AbstractElasticSearchAssembler<ESClusterIndexQueryAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( ESClusterIndexQueryService.class )
+              .taggedWith( "elasticsearch", "query", "indexing" )
+              .identifiedBy( identity() )
+              .visibleIn( visibility() )
+              .instantiateOnStartup();
+
+        if( hasConfig() )
+        {
+            configModule().entities( ElasticSearchClusterConfiguration.class ).
+                visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/assembly/ESFilesystemIndexQueryAssembler.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/assembly/ESFilesystemIndexQueryAssembler.java
new file mode 100644
index 0000000..1998fd8
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/assembly/ESFilesystemIndexQueryAssembler.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.index.elasticsearch.assembly;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.elasticsearch.ElasticSearchConfiguration;
+import org.apache.polygene.index.elasticsearch.filesystem.ESFilesystemIndexQueryService;
+import org.apache.polygene.index.elasticsearch.internal.AbstractElasticSearchAssembler;
+
+public class ESFilesystemIndexQueryAssembler
+    extends AbstractElasticSearchAssembler<ESFilesystemIndexQueryAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( ESFilesystemIndexQueryService.class )
+              .taggedWith( "elasticsearch", "query", "indexing" )
+              .identifiedBy( identity() )
+              .visibleIn( visibility() )
+              .instantiateOnStartup();
+
+        if( hasConfig() )
+        {
+            configModule().entities( ElasticSearchConfiguration.class ).
+                visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/assembly/ElasticSearchIndexingAssembler.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/assembly/ElasticSearchIndexingAssembler.java
new file mode 100644
index 0000000..d13e790
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/assembly/ElasticSearchIndexingAssembler.java
@@ -0,0 +1,26 @@
+/*
+ *  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.polygene.index.elasticsearch.assembly;
+
+/**
+ * This is a dummy Assembler to support the Yeoman Polygene Generator, which require naming conventions for
+ * the systems that it supports.
+ */
+public class ElasticSearchIndexingAssembler extends ESFilesystemIndexQueryAssembler
+{
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/assembly/package.html b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/assembly/package.html
new file mode 100644
index 0000000..e663787
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ElasticSearch Index/Query Assembly.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/client/ESClientIndexQueryService.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/client/ESClientIndexQueryService.java
new file mode 100644
index 0000000..822cf82
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/client/ESClientIndexQueryService.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.index.elasticsearch.client;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.index.elasticsearch.ElasticSearchFinder;
+import org.apache.polygene.index.elasticsearch.ElasticSearchIndexer;
+import org.apache.polygene.index.elasticsearch.ElasticSearchSupport;
+
+@Mixins( ESClientSupport.class )
+public interface ESClientIndexQueryService
+    extends ElasticSearchIndexer, ElasticSearchFinder, ElasticSearchSupport
+{
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/client/ESClientSupport.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/client/ESClientSupport.java
new file mode 100644
index 0000000..24ee996
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/client/ESClientSupport.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.index.elasticsearch.client;
+
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.index.elasticsearch.ElasticSearchConfiguration;
+import org.apache.polygene.index.elasticsearch.internal.AbstractElasticSearchSupport;
+import org.elasticsearch.client.Client;
+
+public class ESClientSupport extends AbstractElasticSearchSupport
+{
+    @This
+    private Configuration<ElasticSearchConfiguration> configuration;
+
+    @Uses
+    private ServiceDescriptor descriptor;
+
+    @Override
+    protected void activateElasticSearch() throws Exception
+    {
+        configuration.refresh();
+        ElasticSearchConfiguration config = configuration.get();
+
+        index = config.index().get() == null ? DEFAULT_INDEX_NAME : config.index().get();
+        indexNonAggregatedAssociations = config.indexNonAggregatedAssociations().get();
+
+        client = descriptor.metaInfo( Client.class );
+    }
+
+    @Override
+    protected void passivateClient()
+    {
+        client = null;
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/client/package.html b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/client/package.html
new file mode 100644
index 0000000..cfb999e
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/client/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ElasticSearch Index/Query Client Support.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/cluster/ESClusterIndexQueryService.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/cluster/ESClusterIndexQueryService.java
new file mode 100644
index 0000000..ccec65d
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/cluster/ESClusterIndexQueryService.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.index.elasticsearch.cluster;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.index.elasticsearch.ElasticSearchFinder;
+import org.apache.polygene.index.elasticsearch.ElasticSearchIndexer;
+import org.apache.polygene.index.elasticsearch.ElasticSearchSupport;
+
+@Mixins( ESClusterSupport.class )
+public interface ESClusterIndexQueryService
+        extends ElasticSearchIndexer, ElasticSearchFinder, ElasticSearchSupport
+{
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/cluster/ESClusterSupport.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/cluster/ESClusterSupport.java
new file mode 100644
index 0000000..75d6a5c
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/cluster/ESClusterSupport.java
@@ -0,0 +1,77 @@
+/*
+ *  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.polygene.index.elasticsearch.cluster;
+
+import org.elasticsearch.client.transport.TransportClient;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.transport.InetSocketTransportAddress;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.index.elasticsearch.ElasticSearchClusterConfiguration;
+import org.apache.polygene.index.elasticsearch.internal.AbstractElasticSearchSupport;
+import org.elasticsearch.transport.client.PreBuiltTransportClient;
+
+import java.net.InetSocketAddress;
+
+public class ESClusterSupport
+    extends AbstractElasticSearchSupport
+{
+    @This
+    private Configuration<ElasticSearchClusterConfiguration> configuration;
+
+    @Override
+    protected void activateElasticSearch()
+        throws Exception
+    {
+        configuration.refresh();
+        ElasticSearchClusterConfiguration config = configuration.get();
+
+        String clusterName = config.clusterName().get() == null ? DEFAULT_CLUSTER_NAME : config.clusterName().get();
+        index = config.index().get() == null ? DEFAULT_INDEX_NAME : config.index().get();
+        indexNonAggregatedAssociations = config.indexNonAggregatedAssociations().get();
+
+        String[] nodes = config.nodes().get() == null
+                         ? new String[] { "localhost:9300" }
+                         : config.nodes().get().split( "," );
+        boolean clusterSniff = config.clusterSniff().get();
+        boolean ignoreClusterName = config.ignoreClusterName().get();
+        String pingTimeout = config.pingTimeout().get() == null ? "5s" : config.pingTimeout().get();
+        String samplerInterval = config.samplerInterval().get() == null ? "5s" : config.samplerInterval().get();
+
+        Settings settings = Settings.builder()
+                                    .put( "cluster.name", clusterName )
+                                    .put( "client.transport.sniff", clusterSniff )
+                                    .put( "client.transport.ignore_cluster_name", ignoreClusterName )
+                                    .put( "client.transport.ping_timeout", pingTimeout )
+                                    .put( "client.transport.nodes_sampler_interval", samplerInterval )
+                                    .build();
+        TransportClient transportClient = new PreBuiltTransportClient( settings );
+        for( String node : nodes )
+        {
+            String[] split = node.split( ":" );
+            String host = split[ 0 ];
+            int port = Integer.valueOf( split[ 1 ] );
+            InetSocketAddress socketAddress = new InetSocketAddress( host, port );
+            transportClient.addTransportAddress( new InetSocketTransportAddress( socketAddress ) );
+        }
+
+        client = transportClient;
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/cluster/package.html b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/cluster/package.html
new file mode 100644
index 0000000..d4eb385
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/cluster/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ElasticSearch Index/Query Cluster Support.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/filesystem/ESFilesystemIndexQueryService.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/filesystem/ESFilesystemIndexQueryService.java
new file mode 100644
index 0000000..e6780c3
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/filesystem/ESFilesystemIndexQueryService.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.index.elasticsearch.filesystem;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.index.elasticsearch.ElasticSearchFinder;
+import org.apache.polygene.index.elasticsearch.ElasticSearchIndexer;
+import org.apache.polygene.index.elasticsearch.ElasticSearchSupport;
+
+@Mixins( ESFilesystemSupport.class )
+public interface ESFilesystemIndexQueryService
+        extends ElasticSearchIndexer, ElasticSearchFinder, ElasticSearchSupport
+{
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/filesystem/ESFilesystemSupport.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/filesystem/ESFilesystemSupport.java
new file mode 100644
index 0000000..99d581f
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/filesystem/ESFilesystemSupport.java
@@ -0,0 +1,87 @@
+/*
+ *  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.polygene.index.elasticsearch.filesystem;
+
+import java.io.File;
+import java.util.stream.Stream;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.index.elasticsearch.ElasticSearchConfiguration;
+import org.apache.polygene.index.elasticsearch.internal.AbstractElasticSearchSupport;
+import org.apache.polygene.library.fileconfig.FileConfiguration;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.node.Node;
+
+public class ESFilesystemSupport
+    extends AbstractElasticSearchSupport
+{
+    @This
+    private Configuration<ElasticSearchConfiguration> configuration;
+
+    @This
+    private HasIdentity hasIdentity;
+
+    @Service
+    private FileConfiguration fileConfig;
+
+    private Node node;
+
+    @Override
+    protected void activateElasticSearch()
+        throws Exception
+    {
+        configuration.refresh();
+        ElasticSearchConfiguration config = configuration.get();
+
+        String clusterName = config.clusterName().get() == null ? DEFAULT_CLUSTER_NAME : config.clusterName().get();
+        index = config.index().get() == null ? DEFAULT_INDEX_NAME : config.index().get();
+        indexNonAggregatedAssociations = config.indexNonAggregatedAssociations().get();
+
+        Identity identity = hasIdentity.identity().get();
+        File homeDir = new File( new File( fileConfig.temporaryDirectory(), identity.toString() ), "home" );
+        File logsDir = new File( fileConfig.logDirectory(), identity.toString() );
+        File dataDir = new File( fileConfig.dataDirectory(), identity.toString() );
+        File confDir = new File( fileConfig.configurationDirectory(), identity.toString() );
+        Stream.of( homeDir, logsDir, dataDir, confDir ).forEach( File::mkdirs );
+        Settings settings = Settings.builder()
+                                    .put( "cluster.name", clusterName )
+                                    .put( "path.home", homeDir.getAbsolutePath() )
+                                    .put( "path.logs", logsDir.getAbsolutePath() )
+                                    .put( "path.data", dataDir.getAbsolutePath() )
+                                    .put( "path.conf", confDir.getAbsolutePath() )
+                                    .put( "transport.type", "local" )
+                                    .put( "http.enabled", false )
+                                    .build();
+        node = new Node( settings );
+        node.start();
+        client = node.client();
+    }
+
+    @Override
+    public void passivateElasticSearch()
+        throws Exception
+    {
+        node.close();
+        node = null;
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/filesystem/package.html b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/filesystem/package.html
new file mode 100644
index 0000000..744d8f1
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/filesystem/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ElasticSearch Index/Query Filesystem Support.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/internal/AbstractElasticSearchAssembler.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/internal/AbstractElasticSearchAssembler.java
new file mode 100644
index 0000000..afbe407
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/internal/AbstractElasticSearchAssembler.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.index.elasticsearch.internal;
+
+import org.apache.polygene.bootstrap.Assemblers;
+
+public abstract class AbstractElasticSearchAssembler<AssemblerType>
+    extends Assemblers.VisibilityIdentityConfig<AssemblerType>
+{
+    public AbstractElasticSearchAssembler()
+    {
+        identifiedBy( "es-indexing" );
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/internal/AbstractElasticSearchSupport.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/internal/AbstractElasticSearchSupport.java
new file mode 100644
index 0000000..d899958
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/internal/AbstractElasticSearchSupport.java
@@ -0,0 +1,154 @@
+/*
+ *  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.polygene.index.elasticsearch.internal;
+
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.apache.polygene.index.elasticsearch.ElasticSearchSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractElasticSearchSupport
+    implements ElasticSearchSupport
+{
+    protected static final Logger LOGGER = LoggerFactory.getLogger( ElasticSearchSupport.class );
+    protected static final String DEFAULT_CLUSTER_NAME = "polygene_cluster";
+    protected static final String DEFAULT_INDEX_NAME = "polygene_index";
+    protected static final String ENTITIES_TYPE = "polygene_entities";
+
+    protected Client client;
+    protected String index;
+    protected boolean indexNonAggregatedAssociations;
+
+    @Override
+    public final void activateService()
+        throws Exception
+    {
+        activateElasticSearch();
+
+        // Wait for yellow status: the primary shard is allocated but replicas may not be yet
+        client.admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet();
+
+        if( !client.admin().indices().prepareExists( index ).setIndices( index ).execute().actionGet().isExists() )
+        {
+            // Create empty index
+            LOGGER.info( "Will create '{}' index as it does not exists.", index );
+            Settings.Builder indexSettings = Settings.builder().loadFromSource(
+                XContentFactory.jsonBuilder()
+                               .startObject()
+                                   .field( "refresh_interval", -1 )
+                                   .startObject( "mapper" )
+                                       .field( "dynamic", false )
+                                   .endObject()
+                                   .startObject( "analysis" )
+                                       .startObject( "analyzer" )
+                                           .startObject( "default" )
+                                               .field( "type", "keyword" )
+                                           .endObject()
+                                           .endObject()
+                                   .endObject()
+                               .endObject()
+                               .string() );
+            XContentBuilder mapping = XContentFactory.jsonBuilder()
+                                                     .startObject()
+                                                         .startObject( entitiesType() )
+                                                             .startArray( "dynamic_templates" )
+                                                                 .startObject()
+                                                                     .startObject( entitiesType() )
+                                                                         .field( "match", "*" )
+                                                                         .field( "match_mapping_type", "string" )
+                                                                         .startObject( "mapping" )
+                                                                             .field( "type", "string" )
+                                                                             .field( "index", "not_analyzed" )
+                                                                         .endObject()
+                                                                     .endObject()
+                                                                 .endObject()
+                                                             .endArray()
+                                                         .endObject()
+                                                     .endObject();
+            client.admin().indices().prepareCreate( index )
+                  .setIndex( index )
+                  .setSettings( indexSettings )
+                  .addMapping( entitiesType(), mapping )
+                  .execute()
+                  .actionGet();
+            LOGGER.info( "Index '{}' created.", index );
+        }
+
+        // Ensure index is fresh
+        client.admin().indices().prepareRefresh( index ).execute().actionGet();
+
+        // Wait for yellow status: the primary shard is allocated but replicas may not be yet
+        client.admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet();
+
+        LOGGER.info( "Index/Query connected to Elastic Search" );
+    }
+
+    protected abstract void activateElasticSearch()
+        throws Exception;
+
+    @Override
+    public final void passivateService()
+        throws Exception
+    {
+        passivateClient();
+        index = null;
+        indexNonAggregatedAssociations = false;
+        passivateElasticSearch();
+    }
+
+    protected void passivateClient()
+    {
+        client.close();
+        client = null;
+    }
+
+    protected void passivateElasticSearch()
+        throws Exception
+    {
+        // NOOP
+    }
+
+    @Override
+    public final Client client()
+    {
+        return client;
+    }
+
+    @Override
+    public final String index()
+    {
+        return index;
+    }
+
+    @Override
+    public final String entitiesType()
+    {
+        return ENTITIES_TYPE;
+    }
+
+    @Override
+    public final boolean indexNonAggregatedAssociations()
+    {
+        return indexNonAggregatedAssociations;
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/internal/package.html b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/internal/package.html
new file mode 100644
index 0000000..6f75412
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/internal/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ElasticSearch Index/Query Internal Package.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/package.html b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/package.html
new file mode 100644
index 0000000..8b4117f
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ElasticSearch Index/Query.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchClusterConfiguration.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchClusterConfiguration.java
deleted file mode 100644
index 5960a06..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchClusterConfiguration.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-
-// START SNIPPET: config
-public interface ElasticSearchClusterConfiguration
-        extends ElasticSearchConfiguration
-{
-
-    /**
-     * Coma separated list of nodes host:port.
-     * Defaults to '127.0.0.1:9300'.
-     */
-    @Optional Property<String> nodes();
-
-    /**
-     * Allows client to sniff the rest of the cluster, and add those into its list of machines to use.
-     * In this case, note that the ip addresses used will be the ones that the other nodes were started
-     * with (the “publish” address).
-     * Defaults to FALSE.
-     */
-    @UseDefaults Property<Boolean> clusterSniff();
-
-    /**
-     * Set to true to ignore cluster name validation of connected nodes.
-     * Defaults to FALSE.
-     */
-    @UseDefaults Property<Boolean> ignoreClusterName();
-
-    /**
-     * The time to wait for a ping response from a node.
-     * Defaults to 5s.
-     */
-    @Optional Property<String> pingTimeout();
-
-    /**
-     * How often to sample / ping the nodes listed and connected.
-     * Defaults to 5s.
-     */
-    @Optional Property<String> samplerInterval();
-
-}
-// END SNIPPET: config
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchConfiguration.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchConfiguration.java
deleted file mode 100644
index d4bbcc5..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchConfiguration.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-// START SNIPPET: config
-public interface ElasticSearchConfiguration
-        extends ConfigurationComposite
-{
-
-    /**
-     * Cluster name.
-     * Defaults to 'qi4j_cluster'.
-     */
-    @Optional Property<String> clusterName();
-
-    /**
-     * Index name.
-     * Defaults to 'qi4j_index'.
-     */
-    @Optional Property<String> index();
-
-    /**
-     * Set to true to index non aggregated associations as if they were aggregated.
-     * WARN: Don't use this if your domain model contains circular dependencies.
-     * Defaults to 'FALSE'.
-     */
-    @UseDefaults Property<Boolean> indexNonAggregatedAssociations();
-
-}
-// END SNIPPET: config
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchFinder.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchFinder.java
deleted file mode 100644
index c74083e..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchFinder.java
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- * Copyright 2012-2014 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch;
-
-import java.util.HashMap;
-import java.util.Map;
-import org.elasticsearch.action.count.CountRequestBuilder;
-import org.elasticsearch.action.count.CountResponse;
-import org.elasticsearch.action.search.SearchRequestBuilder;
-import org.elasticsearch.action.search.SearchResponse;
-import org.elasticsearch.index.query.AndFilterBuilder;
-import org.elasticsearch.index.query.FilterBuilder;
-import org.elasticsearch.index.query.OrFilterBuilder;
-import org.elasticsearch.index.query.QueryBuilder;
-import org.elasticsearch.search.SearchHit;
-import org.elasticsearch.search.sort.SortOrder;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.query.grammar.AndSpecification;
-import org.qi4j.api.query.grammar.AssociationNotNullSpecification;
-import org.qi4j.api.query.grammar.AssociationNullSpecification;
-import org.qi4j.api.query.grammar.BinarySpecification;
-import org.qi4j.api.query.grammar.ComparisonSpecification;
-import org.qi4j.api.query.grammar.ContainsAllSpecification;
-import org.qi4j.api.query.grammar.ContainsSpecification;
-import org.qi4j.api.query.grammar.EqSpecification;
-import org.qi4j.api.query.grammar.GeSpecification;
-import org.qi4j.api.query.grammar.GtSpecification;
-import org.qi4j.api.query.grammar.LeSpecification;
-import org.qi4j.api.query.grammar.LtSpecification;
-import org.qi4j.api.query.grammar.ManyAssociationContainsSpecification;
-import org.qi4j.api.query.grammar.MatchesSpecification;
-import org.qi4j.api.query.grammar.NamedAssociationContainsNameSpecification;
-import org.qi4j.api.query.grammar.NamedAssociationContainsSpecification;
-import org.qi4j.api.query.grammar.NeSpecification;
-import org.qi4j.api.query.grammar.NotSpecification;
-import org.qi4j.api.query.grammar.OrSpecification;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.api.query.grammar.PropertyNotNullSpecification;
-import org.qi4j.api.query.grammar.PropertyNullSpecification;
-import org.qi4j.api.query.grammar.QuerySpecification;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.index.elasticsearch.ElasticSearchFinderSupport.ComplexTypeSupport;
-import org.qi4j.spi.query.EntityFinder;
-import org.qi4j.spi.query.EntityFinderException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.elasticsearch.index.query.FilterBuilders.andFilter;
-import static org.elasticsearch.index.query.FilterBuilders.existsFilter;
-import static org.elasticsearch.index.query.FilterBuilders.missingFilter;
-import static org.elasticsearch.index.query.FilterBuilders.notFilter;
-import static org.elasticsearch.index.query.FilterBuilders.rangeFilter;
-import static org.elasticsearch.index.query.FilterBuilders.regexpFilter;
-import static org.elasticsearch.index.query.FilterBuilders.termFilter;
-import static org.elasticsearch.index.query.QueryBuilders.filteredQuery;
-import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
-import static org.elasticsearch.index.query.QueryBuilders.wrapperQuery;
-import static org.qi4j.index.elasticsearch.ElasticSearchFinderSupport.resolveVariable;
-
-@Mixins( ElasticSearchFinder.Mixin.class )
-public interface ElasticSearchFinder
-    extends EntityFinder
-{
-    class Mixin
-        implements EntityFinder
-    {
-        private static final Logger LOGGER = LoggerFactory.getLogger( ElasticSearchFinder.class );
-        private static final Map<Class<?>, ComplexTypeSupport> COMPLEX_TYPE_SUPPORTS = new HashMap<>( 0 );
-
-        @This
-        private ElasticSearchSupport support;
-
-        @Override
-        public Iterable<EntityReference> findEntities( Class<?> resultType,
-                                                       Specification<Composite> whereClause,
-                                                       OrderBy[] orderBySegments,
-                                                       Integer firstResult, Integer maxResults,
-                                                       Map<String, Object> variables )
-            throws EntityFinderException
-        {
-            // Prepare request
-            SearchRequestBuilder request = support.client().prepareSearch( support.index() );
-
-            AndFilterBuilder filterBuilder = baseFilters( resultType );
-            QueryBuilder queryBuilder = processWhereSpecification( filterBuilder, whereClause, variables );
-
-            request.setQuery( filteredQuery( queryBuilder, filterBuilder ) );
-            if( firstResult != null )
-            {
-                request.setFrom( firstResult );
-            }
-            if( maxResults != null )
-            {
-                request.setSize( maxResults );
-            }
-            else
-            {
-                //request.setSize( Integer.MAX_VALUE ); // TODO Use scrolls?
-            }
-            if( orderBySegments != null )
-            {
-                for( OrderBy order : orderBySegments )
-                {
-                    request.addSort( order.property().toString(),
-                                     order.order() == OrderBy.Order.ASCENDING ? SortOrder.ASC : SortOrder.DESC );
-                }
-            }
-
-            // Log
-            LOGGER.debug( "Will search Entities: {}", request );
-
-            // Execute
-            SearchResponse response = request.execute().actionGet();
-
-            return Iterables.map( new Function<SearchHit, EntityReference>()
-            {
-                @Override
-                public EntityReference map( SearchHit from )
-                {
-                    return EntityReference.parseEntityReference( from.id() );
-                }
-
-            }, response.getHits() );
-        }
-
-        @Override
-        public EntityReference findEntity( Class<?> resultType,
-                                           Specification<Composite> whereClause,
-                                           Map<String, Object> variables )
-            throws EntityFinderException
-        {
-            // Prepare request
-            SearchRequestBuilder request = support.client().prepareSearch( support.index() );
-
-            AndFilterBuilder filterBuilder = baseFilters( resultType );
-            QueryBuilder queryBuilder = processWhereSpecification( filterBuilder, whereClause, variables );
-
-            request.setQuery( filteredQuery( queryBuilder, filterBuilder ) );
-            request.setSize( 1 );
-
-            // Log
-            LOGGER.debug( "Will search Entity: {}", request );
-
-            // Execute
-            SearchResponse response = request.execute().actionGet();
-
-            if( response.getHits().totalHits() == 1 )
-            {
-                return EntityReference.parseEntityReference( response.getHits().getAt( 0 ).id() );
-            }
-
-            return null;
-        }
-
-        @Override
-        public long countEntities( Class<?> resultType,
-                                   Specification<Composite> whereClause,
-                                   Map<String, Object> variables )
-            throws EntityFinderException
-        {
-            // Prepare request
-            CountRequestBuilder request = support.client().prepareCount( support.index() );
-
-            AndFilterBuilder filterBuilder = baseFilters( resultType );
-            QueryBuilder queryBuilder = processWhereSpecification( filterBuilder, whereClause, variables );
-
-            request.setQuery( filteredQuery( queryBuilder, filterBuilder ) );
-
-            // Log
-            LOGGER.debug( "Will count Entities: {}", request );
-
-            // Execute
-            CountResponse count = request.execute().actionGet();
-
-            return count.getCount();
-        }
-
-        private static AndFilterBuilder baseFilters( Class<?> resultType )
-        {
-            return andFilter( termFilter( "_types", resultType.getName() ) );
-        }
-
-        private QueryBuilder processWhereSpecification( AndFilterBuilder filterBuilder,
-                                                        Specification<Composite> spec,
-                                                        Map<String, Object> variables )
-            throws EntityFinderException
-        {
-            if( spec == null )
-            {
-                return matchAllQuery();
-            }
-
-            if( spec instanceof QuerySpecification )
-            {
-                return wrapperQuery( ( (QuerySpecification) spec ).query() );
-            }
-
-            processSpecification( filterBuilder, spec, variables );
-            return matchAllQuery();
-        }
-
-        private void processSpecification( FilterBuilder filterBuilder,
-                                           Specification<Composite> spec,
-                                           Map<String, Object> variables )
-            throws EntityFinderException
-        {
-            if( spec instanceof BinarySpecification )
-            {
-                BinarySpecification binSpec = (BinarySpecification) spec;
-                processBinarySpecification( filterBuilder, binSpec, variables );
-            }
-            else if( spec instanceof NotSpecification )
-            {
-                NotSpecification notSpec = (NotSpecification) spec;
-                processNotSpecification( filterBuilder, notSpec, variables );
-            }
-            else if( spec instanceof ComparisonSpecification )
-            {
-                ComparisonSpecification<?> compSpec = (ComparisonSpecification<?>) spec;
-                processComparisonSpecification( filterBuilder, compSpec, variables );
-            }
-            else if( spec instanceof ContainsAllSpecification )
-            {
-                ContainsAllSpecification<?> contAllSpec = (ContainsAllSpecification) spec;
-                processContainsAllSpecification( filterBuilder, contAllSpec, variables );
-            }
-            else if( spec instanceof ContainsSpecification )
-            {
-                ContainsSpecification<?> contSpec = (ContainsSpecification) spec;
-                processContainsSpecification( filterBuilder, contSpec, variables );
-            }
-            else if( spec instanceof MatchesSpecification )
-            {
-                MatchesSpecification matchSpec = (MatchesSpecification) spec;
-                processMatchesSpecification( filterBuilder, matchSpec, variables );
-            }
-            else if( spec instanceof PropertyNotNullSpecification )
-            {
-                PropertyNotNullSpecification<?> propNotNullSpec = (PropertyNotNullSpecification) spec;
-                processPropertyNotNullSpecification( filterBuilder, propNotNullSpec );
-            }
-            else if( spec instanceof PropertyNullSpecification )
-            {
-                PropertyNullSpecification<?> propNullSpec = (PropertyNullSpecification) spec;
-                processPropertyNullSpecification( filterBuilder, propNullSpec );
-            }
-            else if( spec instanceof AssociationNotNullSpecification )
-            {
-                AssociationNotNullSpecification<?> assNotNullSpec = (AssociationNotNullSpecification) spec;
-                processAssociationNotNullSpecification( filterBuilder, assNotNullSpec );
-            }
-            else if( spec instanceof AssociationNullSpecification )
-            {
-                AssociationNullSpecification<?> assNullSpec = (AssociationNullSpecification) spec;
-                processAssociationNullSpecification( filterBuilder, assNullSpec );
-            }
-            else if( spec instanceof ManyAssociationContainsSpecification )
-            {
-                ManyAssociationContainsSpecification<?> manyAssContSpec = (ManyAssociationContainsSpecification) spec;
-                processManyAssociationContainsSpecification( filterBuilder, manyAssContSpec, variables );
-            }
-            else if( spec instanceof NamedAssociationContainsSpecification )
-            {
-
-                NamedAssociationContainsSpecification<?> namedAssContSpec = (NamedAssociationContainsSpecification) spec;
-                processNamedAssociationContainsSpecification( filterBuilder, namedAssContSpec, variables );
-
-            }
-            else if( spec instanceof NamedAssociationContainsNameSpecification )
-            {
-
-                NamedAssociationContainsNameSpecification<?> namedAssContNameSpec = (NamedAssociationContainsNameSpecification) spec;
-                processNamedAssociationContainsNameSpecification( filterBuilder, namedAssContNameSpec, variables );
-
-            }
-            else
-            {
-                throw new UnsupportedOperationException( "Query specification unsupported by Elastic Search "
-                                                         + "(New Query API support missing?): "
-                                                         + spec.getClass() + ": " + spec );
-            }
-        }
-
-        private static void addFilter( FilterBuilder filter, FilterBuilder into )
-        {
-            if( into instanceof AndFilterBuilder )
-            {
-                ( (AndFilterBuilder) into ).add( filter );
-            }
-            else if( into instanceof OrFilterBuilder )
-            {
-                ( (OrFilterBuilder) into ).add( filter );
-            }
-            else
-            {
-                throw new UnsupportedOperationException( "FilterBuilder is nor an AndFB nor an OrFB, cannot continue." );
-            }
-        }
-
-        private void processBinarySpecification( FilterBuilder filterBuilder,
-                                                 BinarySpecification spec,
-                                                 Map<String, Object> variables )
-            throws EntityFinderException
-        {
-            LOGGER.trace( "Processing BinarySpecification {}", spec );
-            Iterable<Specification<Composite>> operands = spec.operands();
-
-            if( spec instanceof AndSpecification )
-            {
-                AndFilterBuilder andFilterBuilder = new AndFilterBuilder();
-                for( Specification<Composite> operand : operands )
-                {
-                    processSpecification( andFilterBuilder, operand, variables );
-                }
-                addFilter( andFilterBuilder, filterBuilder );
-            }
-            else if( spec instanceof OrSpecification )
-            {
-                OrFilterBuilder orFilterBuilder = new OrFilterBuilder();
-                for( Specification<Composite> operand : operands )
-                {
-                    processSpecification( orFilterBuilder, operand, variables );
-                }
-                addFilter( orFilterBuilder, filterBuilder );
-            }
-            else
-            {
-                throw new UnsupportedOperationException( "Binary Query specification is nor an AndSpecification "
-                                                         + "nor an OrSpecification, cannot continue." );
-            }
-        }
-
-        private void processNotSpecification( FilterBuilder filterBuilder,
-                                              NotSpecification spec,
-                                              Map<String, Object> variables )
-            throws EntityFinderException
-        {
-            LOGGER.trace( "Processing NotSpecification {}", spec );
-            AndFilterBuilder operandFilter = new AndFilterBuilder();
-            processSpecification( operandFilter, spec.operand(), variables );
-            addFilter( notFilter( operandFilter ), filterBuilder );
-        }
-
-        private void processComparisonSpecification( FilterBuilder filterBuilder,
-                                                     ComparisonSpecification<?> spec,
-                                                     Map<String, Object> variables )
-        {
-            LOGGER.trace( "Processing ComparisonSpecification {}", spec );
-
-            if( spec.value() instanceof ValueComposite )
-            {
-                // Query by "example value"
-                throw new UnsupportedOperationException( "ElasticSearch Index/Query does not support complex "
-                                                         + "queries, ie. queries by 'example value'." );
-            }
-            else if( COMPLEX_TYPE_SUPPORTS.get( spec.value().getClass() ) != null )
-            {
-                // Query on complex type property
-                ComplexTypeSupport support = COMPLEX_TYPE_SUPPORTS.get( spec.value().getClass() );
-                addFilter( support.comparison( spec, variables ), filterBuilder );
-            }
-            else
-            {
-                // Query by simple property value
-                String name = spec.property().toString();
-                Object value = resolveVariable( spec.value(), variables );
-                if( spec instanceof EqSpecification )
-                {
-                    addFilter( termFilter( name, value ), filterBuilder );
-                }
-                else if( spec instanceof NeSpecification )
-                {
-                    addFilter( andFilter( existsFilter( name ),
-                                          notFilter( termFilter( name, value ) ) ),
-                               filterBuilder );
-                }
-                else if( spec instanceof GeSpecification )
-                {
-                    addFilter( rangeFilter( name ).gte( value ), filterBuilder );
-                }
-                else if( spec instanceof GtSpecification )
-                {
-                    addFilter( rangeFilter( name ).gt( value ), filterBuilder );
-                }
-                else if( spec instanceof LeSpecification )
-                {
-                    addFilter( rangeFilter( name ).lte( value ), filterBuilder );
-                }
-                else if( spec instanceof LtSpecification )
-                {
-                    addFilter( rangeFilter( name ).lt( value ), filterBuilder );
-                }
-                else
-                {
-                    throw new UnsupportedOperationException( "Query specification unsupported by Elastic Search "
-                                                             + "(New Query API support missing?): "
-                                                             + spec.getClass() + ": " + spec );
-                }
-            }
-        }
-
-        private void processContainsAllSpecification( FilterBuilder filterBuilder,
-                                                      ContainsAllSpecification<?> spec,
-                                                      Map<String, Object> variables )
-        {
-            LOGGER.trace( "Processing ContainsAllSpecification {}", spec );
-            Object firstValue = Iterables.first( spec.containedValues() );
-            if( firstValue instanceof ValueComposite )
-            {
-                // Query by complex property "example value"
-                throw new UnsupportedOperationException( "ElasticSearch Index/Query does not support complex "
-                                                         + "queries, ie. queries by 'example value'." );
-            }
-            else if( COMPLEX_TYPE_SUPPORTS.get( firstValue.getClass() ) != null )
-            {
-                ComplexTypeSupport support = COMPLEX_TYPE_SUPPORTS.get( firstValue.getClass() );
-                addFilter( support.containsAll( spec, variables ), filterBuilder );
-            }
-            else
-            {
-                String name = spec.collectionProperty().toString();
-                AndFilterBuilder contAllFilter = new AndFilterBuilder();
-                for( Object value : spec.containedValues() )
-                {
-                    contAllFilter.add( termFilter( name, resolveVariable( value, variables ) ) );
-                }
-                addFilter( contAllFilter, filterBuilder );
-            }
-        }
-
-        private void processContainsSpecification( FilterBuilder filterBuilder,
-                                                   ContainsSpecification<?> spec,
-                                                   Map<String, Object> variables )
-        {
-            LOGGER.trace( "Processing ContainsSpecification {}", spec );
-            String name = spec.collectionProperty().toString();
-            if( spec.value() instanceof ValueComposite )
-            {
-                // Query by complex property "example value"
-                throw new UnsupportedOperationException( "ElasticSearch Index/Query does not support complex "
-                                                         + "queries, ie. queries by 'example value'." );
-            }
-            else if( COMPLEX_TYPE_SUPPORTS.get( spec.value().getClass() ) != null )
-            {
-                ComplexTypeSupport support = COMPLEX_TYPE_SUPPORTS.get( spec.value().getClass() );
-                addFilter( support.contains( spec, variables ), filterBuilder );
-            }
-            else
-            {
-                Object value = resolveVariable( spec.value(), variables );
-                addFilter( termFilter( name, value ), filterBuilder );
-            }
-        }
-
-        private void processMatchesSpecification( FilterBuilder filterBuilder,
-                                                  MatchesSpecification spec,
-                                                  Map<String, Object> variables )
-        {
-            LOGGER.trace( "Processing MatchesSpecification {}", spec );
-            String name = spec.property().toString();
-            String regexp = resolveVariable( spec.regexp(), variables ).toString();
-            addFilter( regexpFilter( name, regexp ), filterBuilder );
-        }
-
-        private void processPropertyNotNullSpecification( FilterBuilder filterBuilder,
-                                                          PropertyNotNullSpecification<?> spec )
-        {
-            LOGGER.trace( "Processing PropertyNotNullSpecification {}", spec );
-            addFilter( existsFilter( spec.property().toString() ), filterBuilder );
-        }
-
-        private void processPropertyNullSpecification( FilterBuilder filterBuilder,
-                                                       PropertyNullSpecification<?> spec )
-        {
-            LOGGER.trace( "Processing PropertyNullSpecification {}", spec );
-            addFilter( missingFilter( spec.property().toString() ), filterBuilder );
-        }
-
-        private void processAssociationNotNullSpecification( FilterBuilder filterBuilder,
-                                                             AssociationNotNullSpecification<?> spec )
-        {
-            LOGGER.trace( "Processing AssociationNotNullSpecification {}", spec );
-            addFilter( existsFilter( spec.association().toString() + ".identity" ), filterBuilder );
-        }
-
-        private void processAssociationNullSpecification( FilterBuilder filterBuilder,
-                                                          AssociationNullSpecification<?> spec )
-        {
-            LOGGER.trace( "Processing AssociationNullSpecification {}", spec );
-            addFilter( missingFilter( spec.association().toString() + ".identity" ), filterBuilder );
-        }
-
-        private void processManyAssociationContainsSpecification( FilterBuilder filterBuilder,
-                                                                  ManyAssociationContainsSpecification<?> spec,
-                                                                  Map<String, Object> variables )
-        {
-            LOGGER.trace( "Processing ManyAssociationContainsSpecification {}", spec );
-            String name = spec.manyAssociation().toString() + ".identity";
-            Object value = resolveVariable( spec.value(), variables );
-            addFilter( termFilter( name, value ), filterBuilder );
-        }
-
-        private void processNamedAssociationContainsSpecification( FilterBuilder filterBuilder,
-                                                                   NamedAssociationContainsSpecification<?> spec,
-                                                                   Map<String, Object> variables )
-        {
-            LOGGER.trace( "Processing NamedAssociationContainsSpecification {}", spec );
-            String name = spec.namedAssociation().toString() + ".identity";
-            Object value = resolveVariable( spec.value(), variables );
-            addFilter( termFilter( name, value ), filterBuilder );
-        }
-
-        private void processNamedAssociationContainsNameSpecification( FilterBuilder filterBuilder,
-                                                                       NamedAssociationContainsNameSpecification<?> spec,
-                                                                       Map<String, Object> variables )
-        {
-            LOGGER.trace( "Processing NamedAssociationContainsNameSpecification {}", spec );
-            String name = spec.namedAssociation().toString() + "._named";
-            Object value = resolveVariable( spec.name(), variables );
-            addFilter( termFilter( name, value ), filterBuilder );
-        }
-    }
-
-}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchFinderSupport.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchFinderSupport.java
deleted file mode 100644
index 6316dde..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchFinderSupport.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch;
-
-import java.util.Map;
-import org.elasticsearch.index.query.FilterBuilder;
-import org.qi4j.api.query.grammar.ComparisonSpecification;
-import org.qi4j.api.query.grammar.ContainsAllSpecification;
-import org.qi4j.api.query.grammar.ContainsSpecification;
-import org.qi4j.api.query.grammar.Variable;
-
-
-/* package */ final class ElasticSearchFinderSupport
-{
-
-    /* package */ static Object resolveVariable( Object value, Map<String, Object> variables )
-    {
-        if( value == null )
-        {
-            return null;
-        }
-        if( value instanceof Variable )
-        {
-            Variable var = (Variable) value;
-            Object realValue = variables.get( var.variableName() );
-            if( realValue == null )
-            {
-                throw new IllegalArgumentException( "Variable " + var.variableName() + " not bound" );
-            }
-            return realValue;
-        }
-        return value;
-    }
-
-    /* package */ static interface ComplexTypeSupport
-    {
-
-        FilterBuilder comparison( ComparisonSpecification<?> spec, Map<String, Object> variables );
-
-        FilterBuilder contains( ContainsSpecification<?> spec, Map<String, Object> variables );
-
-        FilterBuilder containsAll( ContainsAllSpecification<?> spec, Map<String, Object> variables );
-
-    }
-
-    private ElasticSearchFinderSupport()
-    {
-    }
-
-}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchIndexException.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchIndexException.java
deleted file mode 100644
index 9cecf37..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchIndexException.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch;
-
-public class ElasticSearchIndexException
-        extends RuntimeException
-{
-
-    public ElasticSearchIndexException( String string )
-    {
-        super( string );
-    }
-
-    public ElasticSearchIndexException( String string, Throwable thrwbl )
-    {
-        super( string, thrwbl );
-    }
-
-}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchIndexExporter.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchIndexExporter.java
deleted file mode 100644
index a739a15..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchIndexExporter.java
+++ /dev/null
@@ -1,52 +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.qi4j.index.elasticsearch;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.spi.query.IndexExporter;
-
-@Mixins( ElasticSearchIndexExporter.Mixin.class )
-public interface ElasticSearchIndexExporter
-        extends IndexExporter
-{
-
-    class Mixin
-            implements ElasticSearchIndexExporter
-    {
-
-        @Override
-        public void exportReadableToStream( PrintStream out )
-                throws IOException, UnsupportedOperationException
-        {
-            exportFormalToWriter( new PrintWriter( out ) );
-        }
-
-        @Override
-        public void exportFormalToWriter( PrintWriter out )
-                throws IOException, UnsupportedOperationException
-        {
-            // TODO
-        }
-
-    }
-
-}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchIndexer.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchIndexer.java
deleted file mode 100644
index 329c8e5..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchIndexer.java
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright 2012-2014 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import org.elasticsearch.action.bulk.BulkRequestBuilder;
-import org.elasticsearch.action.bulk.BulkResponse;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.service.qualifier.Tagged;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.api.util.Classes;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.api.value.ValueSerializer;
-import org.qi4j.api.value.ValueSerializer.Options;
-import org.qi4j.functional.Iterables;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.EntityStatus;
-import org.qi4j.spi.entity.ManyAssociationState;
-import org.qi4j.spi.entity.NamedAssociationState;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.EntityStoreUnitOfWork;
-import org.qi4j.spi.entitystore.StateChangeListener;
-import org.qi4j.spi.module.ModuleSpi;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Listen to Entity state changes and index them in ElasticSearch.
- *
- * QUID Use two indices, one for strict queries, one for full text and fuzzy search?
- */
-@Mixins( ElasticSearchIndexer.Mixin.class )
-public interface ElasticSearchIndexer
-    extends StateChangeListener
-{
-
-    class Mixin
-        implements StateChangeListener
-    {
-
-        private static final Logger LOGGER = LoggerFactory.getLogger( ElasticSearchIndexer.class );
-
-        @Structure
-        private ModuleSpi module;
-
-        @Service
-        private EntityStore entityStore;
-
-        @Service
-        @Tagged( ValueSerialization.Formats.JSON )
-        private ValueSerializer valueSerializer;
-
-        @This
-        private ElasticSearchSupport support;
-
-        public void emptyIndex()
-        {
-            support.client().admin().indices().prepareDelete( support.index() ).execute().actionGet();
-        }
-
-        @Override
-        public void notifyChanges( Iterable<EntityState> changedStates )
-        {
-            // All updated or new states
-            Map<String, EntityState> newStates = new HashMap<>();
-            for( EntityState eState : changedStates )
-            {
-                if( eState.status() == EntityStatus.UPDATED || eState.status() == EntityStatus.NEW )
-                {
-                    newStates.put( eState.identity().identity(), eState );
-                }
-            }
-
-            EntityStoreUnitOfWork uow = entityStore.newUnitOfWork(
-                UsecaseBuilder.newUsecase( "Load associations for indexing" ),
-                module,
-                System.currentTimeMillis()
-            );
-
-            // Bulk index request builder
-            BulkRequestBuilder bulkBuilder = support.client().prepareBulk();
-
-            // Handle changed entity states
-            for( EntityState changedState : changedStates )
-            {
-                if( changedState.entityDescriptor().queryable() )
-                {
-                    switch( changedState.status() )
-                    {
-                    case REMOVED:
-                        LOGGER.trace( "Removing Entity State from Index: {}", changedState );
-                        remove( bulkBuilder, changedState.identity().identity() );
-                        break;
-                    case UPDATED:
-                        LOGGER.trace( "Updating Entity State in Index: {}", changedState );
-                        remove( bulkBuilder, changedState.identity().identity() );
-                        String updatedJson = toJSON( changedState, newStates, uow );
-                        LOGGER.trace( "Will index: {}", updatedJson );
-                        index( bulkBuilder, changedState.identity().identity(), updatedJson );
-                        break;
-                    case NEW:
-                        LOGGER.trace( "Creating Entity State in Index: {}", changedState );
-                        String newJson = toJSON( changedState, newStates, uow );
-                        LOGGER.trace( "Will index: {}", newJson );
-                        index( bulkBuilder, changedState.identity().identity(), newJson );
-                        break;
-                    case LOADED:
-                    default:
-                        // Ignored
-                        break;
-                    }
-                }
-            }
-
-            uow.discard();
-
-            if( bulkBuilder.numberOfActions() > 0 )
-            {
-
-                // Execute bulk actions
-                BulkResponse bulkResponse = bulkBuilder.execute().actionGet();
-
-                // Handle errors
-                if( bulkResponse.hasFailures() )
-                {
-                    throw new ElasticSearchIndexException( bulkResponse.buildFailureMessage() );
-                }
-
-                LOGGER.debug( "Indexing changed Entity states took {}ms", bulkResponse.getTookInMillis() );
-
-                // Refresh index
-                support.client().admin().indices().prepareRefresh( support.index() ).execute().actionGet();
-            }
-        }
-
-        private void remove( BulkRequestBuilder bulkBuilder, String identity )
-        {
-            bulkBuilder.add( support.client().
-                prepareDelete( support.index(), support.entitiesType(), identity ) );
-        }
-
-        private void index( BulkRequestBuilder bulkBuilder, String identity, String json )
-        {
-            bulkBuilder.add( support.client().
-                prepareIndex( support.index(), support.entitiesType(), identity ).
-                setSource( json ) );
-        }
-
-        /**
-         * <pre>
-         * {
-         *  "_identity": "ENTITY-IDENTITY",
-         *  "_types": [ "All", "Entity", "types" ],
-         *  "property.name": property.value,
-         *  "association.name": { "identity": "ASSOCIATED-IDENTITY" }
-         *  "manyassociation.name": [ { "identity": "ASSOCIATED" }, { "identity": "IDENTITIES" } ]
-         *  "namedassociation.name": [ { "_named": "NAMED", "identity": "IDENTITY" } }
-         * }
-         * </pre>
-         */
-        private String toJSON( EntityState state, Map<String, EntityState> newStates, EntityStoreUnitOfWork uow )
-        {
-            try
-            {
-                JSONObject json = new JSONObject();
-
-                json.put( "_identity", state.identity().identity() );
-                json.put( "_types", Iterables.toList( Iterables.map( Classes.toClassName(), state.entityDescriptor()
-                    .mixinTypes() ) ) );
-
-                EntityDescriptor entityType = state.entityDescriptor();
-
-                // Properties
-                for( PropertyDescriptor propDesc : entityType.state().properties() )
-                {
-                    if( propDesc.queryable() )
-                    {
-                        String key = propDesc.qualifiedName().name();
-                        Object value = state.propertyValueOf( propDesc.qualifiedName() );
-                        if( value == null || ValueType.isPrimitiveValue( value ) )
-                        {
-                            json.put( key, value );
-                        }
-                        else
-                        {
-                            String serialized = valueSerializer.serialize( new Options().withoutTypeInfo(), value );
-                            // TODO Theses tests are pretty fragile, find a better way to fix this, Jackson API should behave better
-                            if( serialized.startsWith( "{" ) )
-                            {
-                                json.put( key, new JSONObject( serialized ) );
-                            }
-                            else if( serialized.startsWith( "[" ) )
-                            {
-                                json.put( key, new JSONArray( serialized ) );
-                            }
-                            else
-                            {
-                                json.put( key, serialized );
-                            }
-                        }
-                    }
-                }
-
-                // Associations
-                for( AssociationDescriptor assocDesc : entityType.state().associations() )
-                {
-                    if( assocDesc.queryable() )
-                    {
-                        String key = assocDesc.qualifiedName().name();
-                        EntityReference associated = state.associationValueOf( assocDesc.qualifiedName() );
-                        Object value;
-                        if( associated == null )
-                        {
-                            value = null;
-                        }
-                        else
-                        {
-                            if( assocDesc.isAggregated() || support.indexNonAggregatedAssociations() )
-                            {
-                                if( newStates.containsKey( associated.identity() ) )
-                                {
-                                    value = new JSONObject( toJSON( newStates.get( associated.identity() ), newStates, uow ) );
-                                }
-                                else
-                                {
-                                    EntityReference reference = EntityReference.parseEntityReference( associated.identity() );
-                                    EntityState assocState = uow.entityStateOf( module, reference );
-                                    value = new JSONObject( toJSON( assocState, newStates, uow ) );
-                                }
-                            }
-                            else
-                            {
-                                value = new JSONObject( Collections.singletonMap( "identity", associated.identity() ) );
-                            }
-                        }
-                        json.put( key, value );
-                    }
-                }
-
-                // ManyAssociations
-                for( AssociationDescriptor manyAssocDesc : entityType.state().manyAssociations() )
-                {
-                    if( manyAssocDesc.queryable() )
-                    {
-                        String key = manyAssocDesc.qualifiedName().name();
-                        JSONArray array = new JSONArray();
-                        ManyAssociationState associateds = state.manyAssociationValueOf( manyAssocDesc.qualifiedName() );
-                        for( EntityReference associated : associateds )
-                        {
-                            if( manyAssocDesc.isAggregated() || support.indexNonAggregatedAssociations() )
-                            {
-                                if( newStates.containsKey( associated.identity() ) )
-                                {
-                                    array.put( new JSONObject( toJSON( newStates.get( associated.identity() ), newStates, uow ) ) );
-                                }
-                                else
-                                {
-                                    EntityReference reference = EntityReference.parseEntityReference( associated.identity() );
-                                    EntityState assocState = uow.entityStateOf( module, reference );
-                                    array.put( new JSONObject( toJSON( assocState, newStates, uow ) ) );
-                                }
-                            }
-                            else
-                            {
-                                array.put( new JSONObject( Collections.singletonMap( "identity", associated.identity() ) ) );
-                            }
-                        }
-                        json.put( key, array );
-                    }
-                }
-
-                // NamedAssociations
-                for( AssociationDescriptor namedAssocDesc : entityType.state().namedAssociations() )
-                {
-                    if( namedAssocDesc.queryable() )
-                    {
-                        String key = namedAssocDesc.qualifiedName().name();
-                        JSONArray array = new JSONArray();
-                        NamedAssociationState associateds = state.namedAssociationValueOf( namedAssocDesc.qualifiedName() );
-                        for( String name : associateds )
-                        {
-                            if( namedAssocDesc.isAggregated() || support.indexNonAggregatedAssociations() )
-                            {
-                                String identity = associateds.get( name ).identity();
-                                if( newStates.containsKey( identity ) )
-                                {
-                                    JSONObject obj = new JSONObject( toJSON( newStates.get( identity ), newStates, uow ) );
-                                    obj.put( "_named", name );
-                                    array.put( obj );
-                                }
-                                else
-                                {
-                                    EntityReference reference = EntityReference.parseEntityReference( identity );
-                                    EntityState assocState = uow.entityStateOf( module, reference );
-                                    JSONObject obj = new JSONObject( toJSON( assocState, newStates, uow ) );
-                                    obj.put( "_named", name );
-                                    array.put( obj );
-                                }
-                            }
-                            else
-                            {
-                                JSONObject obj = new JSONObject();
-                                obj.put( "_named", name );
-                                obj.put( "identity", associateds.get( name ).identity() );
-                                array.put( obj );
-                            }
-                        }
-                        json.put( key, array );
-                    }
-                }
-
-                return json.toString();
-            }
-            catch( JSONException e )
-            {
-                throw new ElasticSearchIndexException( "Could not index EntityState", e );
-            }
-        }
-    }
-}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchSupport.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchSupport.java
deleted file mode 100644
index bf31ee8..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/ElasticSearchSupport.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch;
-
-import org.elasticsearch.client.Client;
-import org.qi4j.api.service.ServiceActivation;
-
-public interface ElasticSearchSupport
-        extends ServiceActivation
-{
-
-    Client client();
-
-    String index();
-
-    String entitiesType();
-
-    boolean indexNonAggregatedAssociations();
-
-}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/assembly/ESClusterIndexQueryAssembler.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/assembly/ESClusterIndexQueryAssembler.java
deleted file mode 100644
index 6cf04b9..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/assembly/ESClusterIndexQueryAssembler.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch.assembly;
-
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.elasticsearch.ElasticSearchClusterConfiguration;
-import org.qi4j.index.elasticsearch.cluster.ESClusterIndexQueryService;
-import org.qi4j.index.elasticsearch.internal.AbstractElasticSearchAssembler;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-public class ESClusterIndexQueryAssembler
-    extends AbstractElasticSearchAssembler<ESClusterIndexQueryAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( ESClusterIndexQueryService.class ).
-            identifiedBy( identity() ).
-            visibleIn( visibility() ).
-            instantiateOnStartup();
-
-        module.services( OrgJsonValueSerializationService.class ).
-            taggedWith( ValueSerialization.Formats.JSON );
-
-        if( hasConfig() )
-        {
-            configModule().entities( ElasticSearchClusterConfiguration.class ).
-                visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/assembly/ESFilesystemIndexQueryAssembler.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/assembly/ESFilesystemIndexQueryAssembler.java
deleted file mode 100644
index bcb8df9..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/assembly/ESFilesystemIndexQueryAssembler.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch.assembly;
-
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.elasticsearch.ElasticSearchConfiguration;
-import org.qi4j.index.elasticsearch.filesystem.ESFilesystemIndexQueryService;
-import org.qi4j.index.elasticsearch.internal.AbstractElasticSearchAssembler;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-public class ESFilesystemIndexQueryAssembler
-    extends AbstractElasticSearchAssembler<ESFilesystemIndexQueryAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( ESFilesystemIndexQueryService.class ).
-            identifiedBy( identity() ).
-            visibleIn( visibility() ).
-            instantiateOnStartup();
-
-        module.services( OrgJsonValueSerializationService.class ).
-            taggedWith( ValueSerialization.Formats.JSON );
-
-        if( hasConfig() )
-        {
-            configModule().entities( ElasticSearchConfiguration.class ).
-                visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/assembly/ESMemoryIndexQueryAssembler.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/assembly/ESMemoryIndexQueryAssembler.java
deleted file mode 100644
index f6153ff..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/assembly/ESMemoryIndexQueryAssembler.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch.assembly;
-
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.elasticsearch.ElasticSearchConfiguration;
-import org.qi4j.index.elasticsearch.internal.AbstractElasticSearchAssembler;
-import org.qi4j.index.elasticsearch.memory.ESMemoryIndexQueryService;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-public class ESMemoryIndexQueryAssembler
-    extends AbstractElasticSearchAssembler<ESMemoryIndexQueryAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( ESMemoryIndexQueryService.class ).
-            identifiedBy( identity() ).
-            visibleIn( visibility() ).
-            instantiateOnStartup();
-
-        module.services( OrgJsonValueSerializationService.class ).
-            taggedWith( ValueSerialization.Formats.JSON );
-
-        if( hasConfig() )
-        {
-            configModule().entities( ElasticSearchConfiguration.class ).
-                visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/assembly/package.html b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/assembly/package.html
deleted file mode 100644
index f3edf8f..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/assembly/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ElasticSearch Index/Query Assembly.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/cluster/ESClusterIndexQueryService.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/cluster/ESClusterIndexQueryService.java
deleted file mode 100644
index 166272d..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/cluster/ESClusterIndexQueryService.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch.cluster;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.index.elasticsearch.ElasticSearchFinder;
-import org.qi4j.index.elasticsearch.ElasticSearchIndexer;
-import org.qi4j.index.elasticsearch.ElasticSearchSupport;
-
-@Mixins( ESClusterSupport.class )
-public interface ESClusterIndexQueryService
-        extends ElasticSearchIndexer, ElasticSearchFinder, ElasticSearchSupport, ServiceComposite
-{
-}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/cluster/ESClusterSupport.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/cluster/ESClusterSupport.java
deleted file mode 100644
index c0c1264..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/cluster/ESClusterSupport.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch.cluster;
-
-import org.elasticsearch.client.transport.TransportClient;
-import org.elasticsearch.common.settings.ImmutableSettings;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.common.transport.InetSocketTransportAddress;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.index.elasticsearch.ElasticSearchClusterConfiguration;
-import org.qi4j.index.elasticsearch.internal.AbstractElasticSearchSupport;
-
-public class ESClusterSupport
-        extends AbstractElasticSearchSupport
-{
-
-    @This
-    private Configuration<ElasticSearchClusterConfiguration> configuration;
-
-    @Override
-    protected void activateElasticSearch()
-            throws Exception
-    {
-        configuration.refresh();
-        ElasticSearchClusterConfiguration config = configuration.get();
-
-        String clusterName = config.clusterName().get() == null ? DEFAULT_CLUSTER_NAME : config.clusterName().get();
-        index = config.index().get() == null ? DEFAULT_INDEX_NAME : config.index().get();
-        indexNonAggregatedAssociations = config.indexNonAggregatedAssociations().get();
-
-        String[] nodes = config.nodes().get() == null ? new String[]{ "localhost:9300" } : config.nodes().get().split( "," );
-        boolean clusterSniff = config.clusterSniff().get();
-        boolean ignoreClusterName = config.ignoreClusterName().get();
-        String pingTimeout = config.pingTimeout().get() == null ? "5s" : config.pingTimeout().get();
-        String samplerInterval = config.samplerInterval().get() == null ? "5s" : config.samplerInterval().get();
-
-        Settings settings = ImmutableSettings.settingsBuilder().
-                put( "cluster.name", clusterName ).
-                put( "client.transport.sniff", clusterSniff ).
-                put( "client.transport.ignore_cluster_name", ignoreClusterName ).
-                put( "client.transport.ping_timeout", pingTimeout ).
-                put( "client.transport.nodes_sampler_interval", samplerInterval ).
-                build();
-        TransportClient transportClient = new TransportClient( settings );
-        for ( String node : nodes ) {
-            String[] split = node.split( ":" );
-            String host = split[0];
-            int port = Integer.valueOf( split[1] );
-            transportClient.addTransportAddress( new InetSocketTransportAddress( host, port ) );
-        }
-
-        client = transportClient;
-    }
-
-}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/cluster/package.html b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/cluster/package.html
deleted file mode 100644
index 3110da8..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/cluster/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ElasticSearch Index/Query Cluster Support.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/filesystem/ESFilesystemIndexQueryService.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/filesystem/ESFilesystemIndexQueryService.java
deleted file mode 100644
index 8cfb232..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/filesystem/ESFilesystemIndexQueryService.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch.filesystem;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.index.elasticsearch.ElasticSearchFinder;
-import org.qi4j.index.elasticsearch.ElasticSearchIndexer;
-import org.qi4j.index.elasticsearch.ElasticSearchSupport;
-
-@Mixins( ESFilesystemSupport.class )
-public interface ESFilesystemIndexQueryService
-        extends ElasticSearchIndexer, ElasticSearchFinder, ElasticSearchSupport, ServiceComposite
-{
-}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/filesystem/ESFilesystemSupport.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/filesystem/ESFilesystemSupport.java
deleted file mode 100644
index aaf4754..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/filesystem/ESFilesystemSupport.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch.filesystem;
-
-import java.io.File;
-import org.elasticsearch.common.settings.ImmutableSettings;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.node.Node;
-import org.elasticsearch.node.NodeBuilder;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.index.elasticsearch.ElasticSearchConfiguration;
-import org.qi4j.index.elasticsearch.internal.AbstractElasticSearchSupport;
-import org.qi4j.library.fileconfig.FileConfiguration;
-
-public class ESFilesystemSupport
-        extends AbstractElasticSearchSupport
-{
-
-    @This
-    private Configuration<ElasticSearchConfiguration> configuration;
-
-    @This
-    private Identity hasIdentity;
-
-    @Service
-    private FileConfiguration fileConfig;
-
-    private Node node;
-
-    @Override
-    protected void activateElasticSearch()
-            throws Exception
-    {
-        configuration.refresh();
-        ElasticSearchConfiguration config = configuration.get();
-
-        String clusterName = config.clusterName().get() == null ? DEFAULT_CLUSTER_NAME : config.clusterName().get();
-        index = config.index().get() == null ? DEFAULT_INDEX_NAME : config.index().get();
-        indexNonAggregatedAssociations = config.indexNonAggregatedAssociations().get();
-
-        String identity = hasIdentity.identity().get();
-        Settings settings = ImmutableSettings.settingsBuilder().
-                put( "path.work", new File( fileConfig.temporaryDirectory(), identity ).getAbsolutePath() ).
-                put( "path.logs", new File( fileConfig.logDirectory(), identity ).getAbsolutePath() ).
-                put( "path.data", new File( fileConfig.dataDirectory(), identity ).getAbsolutePath() ).
-                put( "path.conf", new File( fileConfig.configurationDirectory(), identity ).getAbsolutePath() ).
-                put( "gateway.type", "local" ).
-                put( "http.enabled", false ).
-                put( "index.cache.type", "weak" ).
-                put( "index.number_of_shards", 1 ).
-                put( "index.number_of_replicas", 0 ).
-                put( "index.refresh_interval", -1 ). // Controlled by ElasticSearchIndexer
-                build();
-        node = NodeBuilder.nodeBuilder().
-                clusterName( clusterName ).
-                settings( settings ).
-                local( true ).
-                node();
-        client = node.client();
-    }
-
-    @Override
-    public void passivateElasticSearch()
-            throws Exception
-    {
-        node.close();
-        node = null;
-    }
-
-}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/filesystem/package.html b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/filesystem/package.html
deleted file mode 100644
index c5ca09e..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/filesystem/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ElasticSearch Index/Query Filesystem Support.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/internal/AbstractElasticSearchAssembler.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/internal/AbstractElasticSearchAssembler.java
deleted file mode 100644
index 7654968..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/internal/AbstractElasticSearchAssembler.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch.internal;
-
-import org.qi4j.bootstrap.Assemblers;
-
-public abstract class AbstractElasticSearchAssembler<AssemblerType>
-    extends Assemblers.VisibilityIdentityConfig<AssemblerType>
-{
-    public AbstractElasticSearchAssembler()
-    {
-        identifiedBy( "es-indexing" );
-    }
-}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/internal/AbstractElasticSearchSupport.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/internal/AbstractElasticSearchSupport.java
deleted file mode 100644
index 7fc2a4d..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/internal/AbstractElasticSearchSupport.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2012-2015 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch.internal;
-
-import org.elasticsearch.client.Client;
-import org.elasticsearch.common.settings.ImmutableSettings;
-import org.elasticsearch.common.xcontent.XContentFactory;
-import org.qi4j.index.elasticsearch.ElasticSearchSupport;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public abstract class AbstractElasticSearchSupport
-        implements ElasticSearchSupport
-{
-
-    protected static final Logger LOGGER = LoggerFactory.getLogger( ElasticSearchSupport.class );
-
-    protected static final String DEFAULT_CLUSTER_NAME = "qi4j_cluster";
-
-    protected static final String DEFAULT_INDEX_NAME = "qi4j_index";
-
-    protected static final String ENTITIES_TYPE = "qi4j_entities";
-
-    protected Client client;
-
-    protected String index;
-
-    protected boolean indexNonAggregatedAssociations;
-
-    @Override
-    public final void activateService()
-            throws Exception
-    {
-        activateElasticSearch();
-
-        // Wait for yellow status: the primary shard is allocated but replicas may not be yet
-        client.admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet();
-
-        if ( !client.admin().indices().prepareExists( index ).setIndices( index ).execute().actionGet().isExists() ) {
-            // Create empty index
-            LOGGER.info( "Will create '{}' index as it does not exists.", index );
-            ImmutableSettings.Builder indexSettings = ImmutableSettings.settingsBuilder().loadFromSource( XContentFactory.jsonBuilder().
-                    startObject().
-                    startObject( "analysis" ).
-                    startObject( "analyzer" ).
-                    //
-                    startObject( "default" ).
-                    field( "type", "keyword" ). // Globally disable analysis, content is treated as a single keyword
-                    endObject().
-                    //
-                    endObject().
-                    endObject().
-                    endObject().
-                    string() );
-            client.admin().indices().prepareCreate( index ).
-                    setIndex( index ).
-                    setSettings( indexSettings ).
-                    execute().
-                    actionGet();
-            LOGGER.info( "Index '{}' created.", index );
-        }
-
-        // Ensure index is fresh
-        client.admin().indices().prepareRefresh( index ).execute().actionGet();
-
-        // Wait for yellow status: the primary shard is allocated but replicas may not be yet
-        client.admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet();
-
-        LOGGER.info( "Index/Query connected to Elastic Search" );
-    }
-
-    protected abstract void activateElasticSearch()
-            throws Exception;
-
-    @Override
-    public final void passivateService()
-            throws Exception
-    {
-        client.close();
-        client = null;
-        index = null;
-        indexNonAggregatedAssociations = false;
-        passivateElasticSearch();
-    }
-
-    protected void passivateElasticSearch()
-            throws Exception
-    {
-        // NOOP
-    }
-
-    @Override
-    public final Client client()
-    {
-        return client;
-    }
-
-    @Override
-    public final String index()
-    {
-        return index;
-    }
-
-    @Override
-    public final String entitiesType()
-    {
-        return ENTITIES_TYPE;
-    }
-
-    @Override
-    public final boolean indexNonAggregatedAssociations()
-    {
-        return indexNonAggregatedAssociations;
-    }
-
-}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/internal/package.html b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/internal/package.html
deleted file mode 100644
index bb32379..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/internal/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ElasticSearch Index/Query Internal Package.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/memory/ESMemoryIndexQueryService.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/memory/ESMemoryIndexQueryService.java
deleted file mode 100644
index 797d144..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/memory/ESMemoryIndexQueryService.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch.memory;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.index.elasticsearch.ElasticSearchFinder;
-import org.qi4j.index.elasticsearch.ElasticSearchIndexer;
-import org.qi4j.index.elasticsearch.ElasticSearchSupport;
-
-@Mixins( ESMemorySupport.class )
-public interface ESMemoryIndexQueryService
-        extends ElasticSearchIndexer, ElasticSearchFinder, ElasticSearchSupport, ServiceComposite
-{
-}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/memory/ESMemorySupport.java b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/memory/ESMemorySupport.java
deleted file mode 100644
index 46e7d2d..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/memory/ESMemorySupport.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch.memory;
-
-import java.io.File;
-import org.elasticsearch.common.settings.ImmutableSettings;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.node.Node;
-import org.elasticsearch.node.NodeBuilder;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.index.elasticsearch.ElasticSearchConfiguration;
-import org.qi4j.index.elasticsearch.internal.AbstractElasticSearchSupport;
-import org.qi4j.library.fileconfig.FileConfiguration;
-
-public class ESMemorySupport
-        extends AbstractElasticSearchSupport
-{
-
-    @This
-    private Configuration<ElasticSearchConfiguration> configuration;
-
-    @This
-    private Identity hasIdentity;
-
-    @Service
-    private FileConfiguration fileConfig;
-
-    private Node node;
-
-    @Override
-    protected void activateElasticSearch()
-            throws Exception
-    {
-        configuration.refresh();
-        ElasticSearchConfiguration config = configuration.get();
-
-        String clusterName = config.clusterName().get() == null ? DEFAULT_CLUSTER_NAME : config.clusterName().get();
-        index = config.index().get() == null ? DEFAULT_INDEX_NAME : config.index().get();
-        indexNonAggregatedAssociations = config.indexNonAggregatedAssociations().get();
-
-        String identity = hasIdentity.identity().get();
-        Settings settings = ImmutableSettings.settingsBuilder().
-                put( "path.work", new File( fileConfig.temporaryDirectory(), identity ).getAbsolutePath() ).
-                put( "path.logs", new File( fileConfig.logDirectory(), identity ).getAbsolutePath() ).
-                put( "path.data", new File( fileConfig.dataDirectory(), identity ).getAbsolutePath() ).
-                put( "path.conf", new File( fileConfig.configurationDirectory(), identity ).getAbsolutePath() ).
-                put( "gateway.type", "none" ).
-                put( "http.enabled", false ).
-                put( "index.cache.type", "weak" ).
-                put( "index.store.type", "memory" ).
-                put( "index.number_of_shards", 1 ).
-                put( "index.number_of_replicas", 0 ).
-                put( "index.refresh_interval", -1 ). // Controlled by ElasticSearchIndexer
-                build();
-        node = NodeBuilder.nodeBuilder().
-                clusterName( clusterName ).
-                settings( settings ).
-                local( true ).
-                node();
-        client = node.client();
-    }
-
-    @Override
-    public void passivateElasticSearch()
-            throws Exception
-    {
-        node.close();
-        node = null;
-    }
-
-}
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/memory/package.html b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/memory/package.html
deleted file mode 100644
index 9ecb6b6..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/memory/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ElasticSearch Index/Query In-Memory Support.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/package.html b/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/package.html
deleted file mode 100644
index 0eaf4cd..0000000
--- a/extensions/indexing-elasticsearch/src/main/java/org/qi4j/index/elasticsearch/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ElasticSearch Index/Query.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/DocumentationSupport.java b/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/DocumentationSupport.java
new file mode 100644
index 0000000..80f4d76
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/DocumentationSupport.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.index.elasticsearch;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.elasticsearch.assembly.ESClientIndexQueryAssembler;
+import org.apache.polygene.index.elasticsearch.assembly.ESClusterIndexQueryAssembler;
+import org.apache.polygene.index.elasticsearch.assembly.ESFilesystemIndexQueryAssembler;
+import org.elasticsearch.client.Client;
+
+public class DocumentationSupport
+    implements Assembler
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ModuleAssembly configModule = module;
+        Visibility configVisibility = Visibility.module;
+
+        // START SNIPPET: filesystem
+        new ESFilesystemIndexQueryAssembler()
+            .withConfig( configModule, configVisibility )
+            .assemble( module );
+        // END SNIPPET: filesystem
+
+        // START SNIPPET: cluster
+        new ESClusterIndexQueryAssembler()
+            .withConfig( configModule, configVisibility )
+            .assemble( module );
+        // END SNIPPET: cluster
+
+        Client client = null;
+        // START SNIPPET: client
+        new ESClientIndexQueryAssembler( client )
+            .withConfig( configModule, configVisibility )
+            .assemble( module );
+        // END SNIPPET: client
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ESEmbeddedRule.java b/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ESEmbeddedRule.java
new file mode 100644
index 0000000..df3e422
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ESEmbeddedRule.java
@@ -0,0 +1,134 @@
+/*
+ *  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.polygene.index.elasticsearch;
+
+import java.util.Locale;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.index.elasticsearch.assembly.ESFilesystemIndexQueryAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.elasticsearch.client.Client;
+import org.junit.rules.TemporaryFolder;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Embedded Elasticsearch JUnit Rule.
+ *
+ * Starting from Elasticsearch 5, startup is way slower.
+ * Reuse an embedded instance across tests.
+ */
+public class ESEmbeddedRule implements TestRule
+{
+    private final TemporaryFolder tmpDir;
+    private Client client;
+
+    public ESEmbeddedRule( TemporaryFolder tmpDir )
+    {
+        this.tmpDir = tmpDir;
+    }
+
+    public Client client()
+    {
+        client.admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet();
+        return client;
+    }
+
+    public String indexName( String className, String methodName )
+    {
+        String indexName = className;
+        if( methodName != null )
+        {
+            indexName += '-' + methodName;
+        }
+        return indexName.toLowerCase( Locale.US );
+    }
+
+    @Override
+    public Statement apply( final Statement base, final Description description )
+    {
+        return new Statement()
+        {
+            @Override
+            public void evaluate() throws Throwable
+            {
+                String name = indexName( description.getClassName(), description.getMethodName() );
+                SingletonAssembler assembler = activateEmbeddedElasticsearch( name );
+                Application application = assembler.application();
+                client = findClient( assembler.module() );
+                try
+                {
+                    base.evaluate();
+                }
+                finally
+                {
+                    application.passivate();
+                    client.close();
+                    client = null;
+                }
+            }
+        };
+    }
+
+    private SingletonAssembler activateEmbeddedElasticsearch( final String name )
+    {
+        try
+        {
+            return new SingletonAssembler()
+            {
+                @Override
+                public void assemble( final ModuleAssembly module ) throws AssemblyException
+                {
+                    module.layer().application().setName( name );
+                    ModuleAssembly config = module.layer().module( "config" );
+                    new EntityTestAssembler().assemble( config );
+                    new EntityTestAssembler().assemble( module );
+                    new FileConfigurationAssembler()
+                        .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+                        .assemble( module );
+                    new ESFilesystemIndexQueryAssembler()
+                        .identifiedBy( name )
+                        .withConfig( config, Visibility.layer )
+                        .assemble( module );
+                }
+            };
+        }
+        catch( ActivationException | AssemblyException ex )
+        {
+            throw new RuntimeException( "Embedded Elasticsearch Rule - Failed to activate", ex );
+        }
+    }
+
+    private Client findClient( Module module )
+    {
+        Client client = module.serviceFinder().findService( ElasticSearchSupport.class ).get().client();
+        if( client == null )
+        {
+            throw new IllegalStateException( "Embedded Elasticsearch Rule - Failed to find client" );
+        }
+        return client;
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ElasticSearchComplexQueryTest.java b/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ElasticSearchComplexQueryTest.java
new file mode 100644
index 0000000..8dcea1b
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ElasticSearchComplexQueryTest.java
@@ -0,0 +1,83 @@
+/*
+ *  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.polygene.index.elasticsearch;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.elasticsearch.assembly.ESClientIndexQueryAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.indexing.AbstractComplexQueryTest;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+import org.junit.rules.TestName;
+
+import static org.apache.polygene.test.util.Assume.assumeNoIbmJdk;
+
+@Ignore( "ElasticSearch Index/Query do not support Complex Queries, ie. queries by 'example values'" )
+public class ElasticSearchComplexQueryTest
+    extends AbstractComplexQueryTest
+{
+    @ClassRule
+    public static final TemporaryFolder ELASTIC_SEARCH_DIR = new TemporaryFolder();
+
+    @ClassRule
+    public static final ESEmbeddedRule ELASTIC_SEARCH = new ESEmbeddedRule( ELASTIC_SEARCH_DIR );
+
+    @Rule
+    public final TestName testName = new TestName();
+
+    @Rule
+    public TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @BeforeClass
+    public static void beforeClass_IBMJDK()
+    {
+        assumeNoIbmJdk();
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+
+        // Config module
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+
+        // Index/Query
+        new ESClientIndexQueryAssembler( ELASTIC_SEARCH.client() )
+            .withConfig( config, Visibility.layer )
+            .assemble( module );
+        ElasticSearchConfiguration esConfig = config.forMixin( ElasticSearchConfiguration.class ).declareDefaults();
+        esConfig.index().set( ELASTIC_SEARCH.indexName( ElasticSearchQueryTest.class.getName(),
+                                                        testName.getMethodName() ) );
+        esConfig.indexNonAggregatedAssociations().set( Boolean.TRUE );
+
+        // FileConfig
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ElasticSearchFinderTest.java b/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ElasticSearchFinderTest.java
new file mode 100644
index 0000000..61d26dd
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ElasticSearchFinderTest.java
@@ -0,0 +1,87 @@
+/*
+ *  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.polygene.index.elasticsearch;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.elasticsearch.assembly.ESClientIndexQueryAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.indexing.AbstractEntityFinderTest;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+import org.junit.rules.TestName;
+
+import static org.apache.polygene.test.util.Assume.assumeNoIbmJdk;
+
+public class ElasticSearchFinderTest
+    extends AbstractEntityFinderTest
+{
+    @ClassRule
+    public static final TemporaryFolder ELASTIC_SEARCH_DIR = new TemporaryFolder();
+
+    @ClassRule
+    public static final ESEmbeddedRule ELASTIC_SEARCH = new ESEmbeddedRule( ELASTIC_SEARCH_DIR );
+
+    @Rule
+    public final TestName testName = new TestName();
+
+    @Rule
+    public TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @BeforeClass
+    public static void beforeClass_IBMJDK()
+    {
+        assumeNoIbmJdk();
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+
+        // Config module
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+
+        // Index/Query
+        new ESClientIndexQueryAssembler( ELASTIC_SEARCH.client() )
+            .withConfig( config, Visibility.layer )
+            .assemble( module );
+        ElasticSearchConfiguration esConfig = config.forMixin( ElasticSearchConfiguration.class ).declareDefaults();
+        esConfig.index().set( ELASTIC_SEARCH.indexName( ElasticSearchQueryTest.class.getName(),
+                                                        testName.getMethodName() ) );
+        esConfig.indexNonAggregatedAssociations().set( Boolean.TRUE );
+
+        // FileConfig
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+    }
+
+    @Override
+    public void showNetwork()
+    {
+        // IndexExporter not supported by ElasticSearch
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ElasticSearchQueryMultimoduleTest.java b/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ElasticSearchQueryMultimoduleTest.java
new file mode 100644
index 0000000..a55ff31
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ElasticSearchQueryMultimoduleTest.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.index.elasticsearch;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.apache.polygene.index.elasticsearch.assembly.ESClientIndexQueryAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.EntityTestAssembler;
+
+public class ElasticSearchQueryMultimoduleTest extends ElasticSearchQueryTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        assembleEntities( module, Visibility.module );
+        assembleValues( module, Visibility.layer );
+
+        module = module.layer().module( "module2" );
+        new EntityTestAssembler().visibleIn( Visibility.layer ).assemble( module );
+        new DefaultUnitOfWorkAssembler().assemble( module );
+
+        // Config module
+        LayerAssembly configLayer = module.layer().application().layer( "config" );
+        module.layer().uses( configLayer );
+        ModuleAssembly config = configLayer.module( "config" );
+        new EntityTestAssembler().assemble( config );
+
+        // Index/Query
+        new ESClientIndexQueryAssembler( ELASTIC_SEARCH.client() )
+            .withConfig( config, Visibility.application )
+            .visibleIn( Visibility.layer )
+            .assemble( module );
+        ElasticSearchConfiguration esConfig = config.forMixin( ElasticSearchConfiguration.class ).declareDefaults();
+        esConfig.index().set( ELASTIC_SEARCH.indexName( ElasticSearchQueryTest.class.getName(),
+                                                        testName.getMethodName() ) );
+        esConfig.indexNonAggregatedAssociations().set( Boolean.TRUE );
+
+        // FileConfig
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ElasticSearchQueryTest.java b/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ElasticSearchQueryTest.java
new file mode 100644
index 0000000..6b6feab
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ElasticSearchQueryTest.java
@@ -0,0 +1,114 @@
+/*
+ *  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.polygene.index.elasticsearch;
+
+import java.io.IOException;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.elasticsearch.assembly.ESClientIndexQueryAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.indexing.AbstractQueryTest;
+import org.apache.polygene.test.util.NotYetImplemented;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.rules.TestName;
+
+import static org.apache.polygene.test.util.Assume.assumeNoIbmJdk;
+
+public class ElasticSearchQueryTest extends AbstractQueryTest
+{
+    @BeforeClass
+    public static void beforeClass_IBMJDK()
+    {
+        assumeNoIbmJdk();
+    }
+
+    @ClassRule
+    public static final TemporaryFolder ELASTIC_SEARCH_DIR = new TemporaryFolder();
+
+    @ClassRule
+    public static final ESEmbeddedRule ELASTIC_SEARCH = new ESEmbeddedRule( ELASTIC_SEARCH_DIR );
+
+    @Rule
+    public final TestName testName = new TestName();
+
+    @Rule
+    public TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+
+        // Config module
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+
+        // Index/Query
+        new ESClientIndexQueryAssembler( ELASTIC_SEARCH.client() )
+            .withConfig( config, Visibility.layer )
+            .assemble( module );
+        ElasticSearchConfiguration esConfig = config.forMixin( ElasticSearchConfiguration.class ).declareDefaults();
+        esConfig.index().set( ELASTIC_SEARCH.indexName( ElasticSearchQueryTest.class.getName(),
+                                                        testName.getMethodName() ) );
+        esConfig.indexNonAggregatedAssociations().set( Boolean.TRUE );
+
+        // FileConfig
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+    }
+
+    @NotYetImplemented( reason = "IndexExporter service not implemented" )
+    @Test
+    @Override
+    public void showNetwork()
+        throws IOException
+    {
+        super.showNetwork();
+    }
+
+    @NotYetImplemented( reason = "oneOf() Query Expression not implemented" )
+    @Test
+    @Override
+    public void script23()
+    {
+        super.script23();
+    }
+
+    @NotYetImplemented(
+        reason = "ElasticSearch perform automatic TimeZone resolution when querying on dates, "
+                 + "this test assert that the underlying Index/Query engine do not."
+    )
+    @Test
+    @Override
+    public void script42_DateTime()
+    {
+        super.script42_DateTime();
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ElasticSearchTest.java b/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ElasticSearchTest.java
new file mode 100644
index 0000000..a52babb
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ElasticSearchTest.java
@@ -0,0 +1,249 @@
+/*
+ *  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.polygene.index.elasticsearch;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.entity.Aggregated;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.elasticsearch.assembly.ESClientIndexQueryAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.rules.TestName;
+
+import static org.apache.polygene.api.query.QueryExpressions.eq;
+import static org.apache.polygene.api.query.QueryExpressions.ne;
+import static org.apache.polygene.api.query.QueryExpressions.not;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+import static org.apache.polygene.test.util.Assume.assumeNoIbmJdk;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class ElasticSearchTest
+    extends AbstractPolygeneTest
+{
+    @BeforeClass
+    public static void beforeClass_IBMJDK()
+    {
+        assumeNoIbmJdk();
+    }
+
+    @ClassRule
+    public static final TemporaryFolder ELASTIC_SEARCH_DIR = new TemporaryFolder();
+
+    @ClassRule
+    public static final ESEmbeddedRule ELASTIC_SEARCH = new ESEmbeddedRule( ELASTIC_SEARCH_DIR );
+
+    @Rule
+    public final TestName testName = new TestName();
+
+    @Rule
+    public TemporaryFolder tmpDir = new TemporaryFolder();
+
+    public interface Post
+        extends HasIdentity
+    {
+        Property<String> title();
+
+        @UseDefaults
+        Property<String> body();
+
+        Property<Tagline> tagline();
+
+        Association<Author> author();
+
+        @Aggregated
+        @UseDefaults
+        ManyAssociation<Comment> comments();
+    }
+
+    public interface Page
+        extends HasIdentity
+    {
+        Property<String> title();
+
+        @UseDefaults
+        Property<String> body();
+
+        Property<Tagline> tagline();
+
+        Association<Author> author();
+    }
+
+    public interface Tagline
+    {
+        @UseDefaults
+        Property<String> tags();
+    }
+
+    public interface Author
+        extends HasIdentity
+    {
+        Property<String> nickname();
+    }
+
+    public interface Comment
+        extends HasIdentity
+    {
+        Property<String> content();
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // Config module
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+
+        // EntityStore
+        new EntityTestAssembler().assemble( module );
+
+        // Index/Query
+        new ESClientIndexQueryAssembler( ELASTIC_SEARCH.client() )
+            .withConfig( config, Visibility.layer )
+            .assemble( module );
+        ElasticSearchConfiguration esConfig = config.forMixin( ElasticSearchConfiguration.class ).declareDefaults();
+        esConfig.index().set( ELASTIC_SEARCH.indexName( ElasticSearchQueryTest.class.getName(),
+                                                        testName.getMethodName() ) );
+        esConfig.indexNonAggregatedAssociations().set( Boolean.TRUE );
+
+        // FileConfig
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+
+        // Entities & Values
+        module.entities( Post.class, Page.class, Author.class, Comment.class );
+        module.values( Tagline.class );
+    }
+
+    @Test
+    public void test()
+        throws UnitOfWorkCompletionException
+    {
+        String title = "Foo Bar Bazar!";
+
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+
+        EntityBuilder<Author> authorBuilder = uow.newEntityBuilder( Author.class );
+        Author author = authorBuilder.instance();
+        author.nickname().set( "eskatos" );
+        author = authorBuilder.newInstance();
+
+        EntityBuilder<Comment> commentBuilder = uow.newEntityBuilder( Comment.class );
+        Comment comment1 = commentBuilder.instance();
+        comment1.content().set( "Comment One" );
+        comment1 = commentBuilder.newInstance();
+
+        commentBuilder = uow.newEntityBuilder( Comment.class );
+        Comment comment2 = commentBuilder.instance();
+        comment2.content().set( "Comment Two" );
+        comment2 = commentBuilder.newInstance();
+
+        EntityBuilder<Post> postBuilder = uow.newEntityBuilder( Post.class );
+        Post post = postBuilder.instance();
+        post.title().set( title );
+        post.author().set( author );
+        post.tagline().set( valueBuilderFactory.newValue( Tagline.class ) );
+        post.comments().add( comment1 );
+        post.comments().add( comment2 );
+        post = postBuilder.newInstance();
+
+        EntityBuilder<Page> pageBuilder = uow.newEntityBuilder( Page.class );
+        Page page = pageBuilder.instance();
+        page.title().set( title );
+        page.author().set( author );
+        page.tagline().set( valueBuilderFactory.newValue( Tagline.class ) );
+        page = pageBuilder.newInstance();
+
+        System.out.println( "########################################" );
+        System.out.println( "Post Identity: " + post.identity().get() );
+        System.out.println( "Page Identity: " + page.identity().get() );
+        System.out.println( "########################################" );
+
+        uow.complete();
+
+        uow = unitOfWorkFactory.newUnitOfWork();
+
+        QueryBuilder<Post> queryBuilder = queryBuilderFactory.newQueryBuilder( Post.class );
+        Query<Post> query = uow.newQuery( queryBuilder );
+        assertEquals( 1, query.count() );
+        post = query.find();
+        assertNotNull( post );
+        assertEquals( title, post.title().get() );
+
+        post = templateFor( Post.class );
+        queryBuilder = queryBuilderFactory.newQueryBuilder( Post.class ).where( eq( post.title(), title ) );
+        query = uow.newQuery( queryBuilder );
+        assertEquals( 1, query.count() );
+        post = query.find();
+        assertNotNull( post );
+        assertEquals( title, post.title().get() );
+
+        post = templateFor( Post.class );
+        queryBuilder = queryBuilderFactory.newQueryBuilder( Post.class )
+                                          .where( eq( post.title(), "Not available" ) );
+        query = uow.newQuery( queryBuilder );
+        assertEquals( 0, query.count() );
+
+        post = templateFor( Post.class );
+        queryBuilder = queryBuilderFactory.newQueryBuilder( Post.class )
+                                          .where( ne( post.title(), "Not available" ) );
+        query = uow.newQuery( queryBuilder );
+        assertEquals( 1, query.count() );
+
+        post = templateFor( Post.class );
+        queryBuilder = queryBuilderFactory.newQueryBuilder( Post.class )
+                                          .where( not( eq( post.title(), "Not available" ) ) );
+        query = uow.newQuery( queryBuilder );
+        post = query.find();
+        assertNotNull( post );
+        assertEquals( title, post.title().get() );
+
+        post = templateFor( Post.class );
+        queryBuilder = queryBuilderFactory.newQueryBuilder( Post.class )
+                                          .where( eq( post.author().get().nickname(), "eskatos" ) );
+        query = uow.newQuery( queryBuilder );
+        assertEquals( 1, query.count() );
+        post = query.find();
+        assertNotNull( post );
+        assertEquals( title, post.title().get() );
+
+        uow.discard();
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ImmenseTermTest.java b/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ImmenseTermTest.java
new file mode 100644
index 0000000..a8bd09b
--- /dev/null
+++ b/extensions/indexing-elasticsearch/src/test/java/org/apache/polygene/index/elasticsearch/ImmenseTermTest.java
@@ -0,0 +1,149 @@
+/*
+ *  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.polygene.index.elasticsearch;
+
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.elasticsearch.assembly.ESClientIndexQueryAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.rules.TestName;
+
+import static org.apache.polygene.api.query.QueryExpressions.eq;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+import static org.apache.polygene.test.util.Assume.assumeNoIbmJdk;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * ImmenseTermTest.
+ * <p>
+ * See <a href="https://ops4j1.jira.com/browse/QI-412">QI-412</a>.
+ */
+public class ImmenseTermTest
+    extends AbstractPolygeneTest
+{
+    @ClassRule
+    public static final TemporaryFolder ELASTIC_SEARCH_DIR = new TemporaryFolder();
+
+    @ClassRule
+    public static final ESEmbeddedRule ELASTIC_SEARCH = new ESEmbeddedRule( ELASTIC_SEARCH_DIR );
+
+    @Rule
+    public final TestName testName = new TestName();
+
+    @Rule
+    public TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @BeforeClass
+    public static void beforeClass_IBMJDK()
+    {
+        assumeNoIbmJdk();
+    }
+
+    public interface TestEntity
+        extends EntityComposite
+    {
+        @Queryable( false )
+        ManyAssociation<TestEntity2> manyAssociation();
+    }
+
+    public interface TestEntity2
+        extends EntityComposite
+    {
+        @Optional
+        Property<String> property();
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // Config module
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+
+        // EntityStore
+        new EntityTestAssembler().assemble( module );
+
+        // Index/Query
+        new ESClientIndexQueryAssembler( ELASTIC_SEARCH.client() )
+            .withConfig( config, Visibility.layer )
+            .assemble( module );
+        ElasticSearchConfiguration esConfig = config.forMixin( ElasticSearchConfiguration.class ).declareDefaults();
+        esConfig.index().set( ELASTIC_SEARCH.indexName( ElasticSearchQueryTest.class.getName(),
+                                                        testName.getMethodName() ) );
+        esConfig.indexNonAggregatedAssociations().set( Boolean.TRUE );
+
+        // FileConfig
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+
+        // Entities & Values
+        module.entities( TestEntity.class, TestEntity2.class );
+    }
+
+    @Test
+    public void testManyAssociation()
+        throws Exception
+    {
+        int count = 10_000;
+        TestEntity testEntity;
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            testEntity = uow.newEntity( TestEntity.class );
+            for( int i = 0; i < count; i++ )
+            {
+                TestEntity2 testEntity2 = unitOfWorkFactory.currentUnitOfWork().newEntity( TestEntity2.class );
+                testEntity2.property().set( "test" );
+                testEntity.manyAssociation().add( testEntity2 );
+            }
+            uow.complete();
+        }
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            testEntity = uow.get( testEntity );
+            Query<TestEntity2> query = uow.newQuery(
+                queryBuilderFactory.newQueryBuilder( TestEntity2.class ).where(
+                    eq( templateFor( TestEntity2.class ).property(), "test" )
+                )
+            );
+            assertThat( (int) query.count(), is( count ) );
+            assertThat( testEntity.manyAssociation().count(), is( count ) );
+        }
+    }
+}
diff --git a/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/DocumentationSupport.java b/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/DocumentationSupport.java
deleted file mode 100644
index d4c5c54..0000000
--- a/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/DocumentationSupport.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.elasticsearch.assembly.ESClusterIndexQueryAssembler;
-import org.qi4j.index.elasticsearch.assembly.ESFilesystemIndexQueryAssembler;
-import org.qi4j.index.elasticsearch.assembly.ESMemoryIndexQueryAssembler;
-
-public class DocumentationSupport
-    implements Assembler
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ModuleAssembly configModule = module;
-        Visibility configVisibility = Visibility.module;
-
-        // START SNIPPET: memory
-        new ESMemoryIndexQueryAssembler().withConfig( configModule, configVisibility ).assemble( module );
-        // END SNIPPET: memory
-
-        // START SNIPPET: filesystem
-        new ESFilesystemIndexQueryAssembler().withConfig( configModule, configVisibility ).assemble( module );
-        // END SNIPPET: filesystem
-
-        // START SNIPPET: cluster
-        new ESClusterIndexQueryAssembler().withConfig( configModule, configVisibility ).assemble( module );
-        // END SNIPPET: cluster
-
-    }
-
-}
diff --git a/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/ElasticSearchComplexQueryTest.java b/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/ElasticSearchComplexQueryTest.java
deleted file mode 100644
index 5504e9b..0000000
--- a/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/ElasticSearchComplexQueryTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch;
-
-import java.io.File;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Rule;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.elasticsearch.assembly.ESFilesystemIndexQueryAssembler;
-import org.qi4j.library.fileconfig.FileConfigurationOverride;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.indexing.AbstractComplexQueryTest;
-import org.qi4j.test.util.DelTreeAfter;
-
-import static org.qi4j.test.util.Assume.assumeNoIbmJdk;
-
-@Ignore( "ElasticSearch Index/Query do not support Complex Queries, ie. queries by 'example values'" )
-public class ElasticSearchComplexQueryTest
-    extends AbstractComplexQueryTest
-{
-
-    private static final File DATA_DIR = new File( "build/tmp/es-complex-query-test" );
-    @Rule
-    public final DelTreeAfter delTreeAfter = new DelTreeAfter( DATA_DIR );
-
-    @BeforeClass
-    public static void beforeClass_IBMJDK()
-    {
-        assumeNoIbmJdk();
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-
-        // Config module
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-
-        // Index/Query
-        new ESFilesystemIndexQueryAssembler().
-            withConfig( config, Visibility.layer ).
-            assemble( module );
-        ElasticSearchConfiguration esConfig = config.forMixin( ElasticSearchConfiguration.class ).declareDefaults();
-        esConfig.indexNonAggregatedAssociations().set( Boolean.TRUE );
-
-        // FileConfig
-        FileConfigurationOverride override = new FileConfigurationOverride().
-            withData( new File( DATA_DIR, "qi4j-data" ) ).
-            withLog( new File( DATA_DIR, "qi4j-logs" ) ).
-            withTemporary( new File( DATA_DIR, "qi4j-temp" ) );
-        module.services( FileConfigurationService.class ).setMetaInfo( override );
-    }
-
-    @Override
-    public void showNetwork()
-    {
-        // IndexExporter not supported by ElasticSearch
-    }
-
-}
diff --git a/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/ElasticSearchFinderTest.java b/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/ElasticSearchFinderTest.java
deleted file mode 100644
index 3766545..0000000
--- a/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/ElasticSearchFinderTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch;
-
-import java.io.File;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.elasticsearch.assembly.ESFilesystemIndexQueryAssembler;
-import org.qi4j.library.fileconfig.FileConfigurationOverride;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.indexing.AbstractEntityFinderTest;
-import org.qi4j.test.util.DelTreeAfter;
-
-import static org.qi4j.test.util.Assume.assumeNoIbmJdk;
-
-public class ElasticSearchFinderTest
-    extends AbstractEntityFinderTest
-{
-    private static final File DATA_DIR = new File( "build/tmp/es-finder-test" );
-    @Rule
-    public final DelTreeAfter delTreeAfter = new DelTreeAfter( DATA_DIR );
-
-    @BeforeClass
-    public static void beforeClass_IBMJDK()
-    {
-        assumeNoIbmJdk();
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-
-        // Config module
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-
-        // Index/Query
-        new ESFilesystemIndexQueryAssembler().
-            withConfig( config, Visibility.layer ).
-            assemble( module );
-        ElasticSearchConfiguration esConfig = config.forMixin( ElasticSearchConfiguration.class ).declareDefaults();
-        esConfig.indexNonAggregatedAssociations().set( Boolean.TRUE );
-
-        // FileConfig
-        FileConfigurationOverride override = new FileConfigurationOverride().
-            withData( new File( DATA_DIR, "qi4j-data" ) ).
-            withLog( new File( DATA_DIR, "qi4j-logs" ) ).
-            withTemporary( new File( DATA_DIR, "qi4j-temp" ) );
-        module.services( FileConfigurationService.class ).
-            setMetaInfo( override );
-    }
-
-    @Override
-    public void showNetwork()
-    {
-        // IndexExporter not supported by ElasticSearch
-    }
-
-}
diff --git a/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/ElasticSearchQueryTest.java b/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/ElasticSearchQueryTest.java
deleted file mode 100644
index debafea..0000000
--- a/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/ElasticSearchQueryTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2012-2014 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch;
-
-import java.io.File;
-import java.io.IOException;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Rule;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.elasticsearch.assembly.ESFilesystemIndexQueryAssembler;
-import org.qi4j.library.fileconfig.FileConfigurationOverride;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.spi.query.EntityFinderException;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.indexing.AbstractQueryTest;
-import org.qi4j.test.util.DelTreeAfter;
-
-import static org.qi4j.test.util.Assume.assumeNoIbmJdk;
-
-public class ElasticSearchQueryTest
-    extends AbstractQueryTest
-{
-
-    private static final File DATA_DIR = new File( "build/tmp/es-query-test" );
-    @Rule
-    public final DelTreeAfter delTreeAfter = new DelTreeAfter( DATA_DIR );
-
-    @BeforeClass
-    public static void beforeClass_IBMJDK()
-    {
-        assumeNoIbmJdk();
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-
-        // Config module
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-
-        // Index/Query
-        new ESFilesystemIndexQueryAssembler().
-            withConfig( config, Visibility.layer ).
-            assemble( module );
-        ElasticSearchConfiguration esConfig = config.forMixin( ElasticSearchConfiguration.class ).declareDefaults();
-        esConfig.indexNonAggregatedAssociations().set( Boolean.TRUE );
-
-        // FileConfig
-        FileConfigurationOverride override = new FileConfigurationOverride().
-            withData( new File( DATA_DIR, "qi4j-data" ) ).
-            withLog( new File( DATA_DIR, "qi4j-logs" ) ).
-            withTemporary( new File( DATA_DIR, "qi4j-temp" ) );
-        module.services( FileConfigurationService.class ).
-            setMetaInfo( override );
-    }
-
-    @Test
-    @Ignore( "IndexExporter not supported by ElasticSearch Indexing" )
-    @Override
-    public void showNetwork()
-        throws IOException
-    {
-        super.showNetwork();
-    }
-
-    @Test
-    @Ignore( "oneOf() Query Expression not supported by ElasticSearch Indexing" )
-    @Override
-    public void script23()
-        throws EntityFinderException
-    {
-        super.script23();
-    }
-
-    @Test
-    @Ignore(
-         "ElasticSearch perform automatic TimeZone resolution when querying on dates, this test assert that the "
-         + "underlying Index/Query engine do not."
-    )
-    @Override
-    public void script42_DateTime()
-    {
-        super.script42_DateTime();
-    }
-}
diff --git a/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/ElasticSearchTest.java b/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/ElasticSearchTest.java
deleted file mode 100644
index 4bd673e..0000000
--- a/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/ElasticSearchTest.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.elasticsearch;
-
-import java.io.File;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.entity.Aggregated;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.elasticsearch.assembly.ESFilesystemIndexQueryAssembler;
-import org.qi4j.library.fileconfig.FileConfigurationOverride;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.util.DelTreeAfter;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.qi4j.api.query.QueryExpressions.eq;
-import static org.qi4j.api.query.QueryExpressions.ne;
-import static org.qi4j.api.query.QueryExpressions.not;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-import static org.qi4j.test.util.Assume.assumeNoIbmJdk;
-
-public class ElasticSearchTest
-    extends AbstractQi4jTest
-{
-
-    private static final File DATA_DIR = new File( "build/tmp/es-test" );
-    @Rule
-    public final DelTreeAfter delTreeAfter = new DelTreeAfter( DATA_DIR );
-
-    @BeforeClass
-    public static void beforeClass_IBMJDK()
-    {
-        assumeNoIbmJdk();
-    }
-
-    public interface Post
-        extends Identity
-    {
-
-        Property<String> title();
-
-        @UseDefaults
-        Property<String> body();
-
-        Property<Tagline> tagline();
-
-        Association<Author> author();
-
-        @Aggregated
-        @UseDefaults
-        ManyAssociation<Comment> comments();
-
-    }
-
-    public interface Page
-        extends Identity
-    {
-
-        Property<String> title();
-
-        @UseDefaults
-        Property<String> body();
-
-        Property<Tagline> tagline();
-
-        Association<Author> author();
-
-    }
-
-    public interface Tagline
-    {
-
-        @UseDefaults
-        Property<String> tags();
-
-    }
-
-    public interface Author
-        extends Identity
-    {
-
-        Property<String> nickname();
-
-    }
-
-    public interface Comment
-        extends Identity
-    {
-
-        Property<String> content();
-
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // Config module
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-
-        // EntityStore
-        new EntityTestAssembler().assemble( module );
-
-        // Index/Query
-        new ESFilesystemIndexQueryAssembler().
-            withConfig( config, Visibility.layer ).
-            assemble( module );
-        ElasticSearchConfiguration esConfig = config.forMixin( ElasticSearchConfiguration.class ).declareDefaults();
-        esConfig.indexNonAggregatedAssociations().set( Boolean.TRUE );
-
-        // FileConfig
-        FileConfigurationOverride override = new FileConfigurationOverride().
-            withData( new File( DATA_DIR, "qi4j-data" ) ).
-            withLog( new File( DATA_DIR, "qi4j-logs" ) ).
-            withTemporary( new File( DATA_DIR, "qi4j-temp" ) );
-        module.services( FileConfigurationService.class ).
-            setMetaInfo( override );
-
-        // Entities & Values
-        module.entities( Post.class, Page.class, Author.class, Comment.class );
-        module.values( Tagline.class );
-    }
-
-    @Test
-    public void test()
-        throws UnitOfWorkCompletionException
-    {
-        String title = "Foo Bar Bazar!";
-
-        UnitOfWork uow = module.newUnitOfWork();
-
-        EntityBuilder<Author> authorBuilder = uow.newEntityBuilder( Author.class );
-        Author author = authorBuilder.instance();
-        author.nickname().set( "eskatos" );
-        author = authorBuilder.newInstance();
-
-        EntityBuilder<Comment> commentBuilder = uow.newEntityBuilder( Comment.class );
-        Comment comment1 = commentBuilder.instance();
-        comment1.content().set( "Comment One" );
-        comment1 = commentBuilder.newInstance();
-
-        commentBuilder = uow.newEntityBuilder( Comment.class );
-        Comment comment2 = commentBuilder.instance();
-        comment2.content().set( "Comment Two" );
-        comment2 = commentBuilder.newInstance();
-
-        EntityBuilder<Post> postBuilder = uow.newEntityBuilder( Post.class );
-        Post post = postBuilder.instance();
-        post.title().set( title );
-        post.author().set( author );
-        post.tagline().set( module.newValue( Tagline.class ) );
-        post.comments().add( comment1 );
-        post.comments().add( comment2 );
-        post = postBuilder.newInstance();
-
-        EntityBuilder<Page> pageBuilder = uow.newEntityBuilder( Page.class );
-        Page page = pageBuilder.instance();
-        page.title().set( title );
-        page.author().set( author );
-        page.tagline().set( module.newValue( Tagline.class ) );
-        page = pageBuilder.newInstance();
-
-        System.out.println( "########################################" );
-        System.out.println( "Post Identity: " + post.identity().get() );
-        System.out.println( "Page Identity: " + page.identity().get() );
-        System.out.println( "########################################" );
-
-        uow.complete();
-
-        uow = module.newUnitOfWork();
-
-        QueryBuilder<Post> queryBuilder = module.newQueryBuilder( Post.class );
-        Query<Post> query = uow.newQuery( queryBuilder );
-        assertEquals( 1, query.count() );
-        post = query.find();
-        assertNotNull( post );
-        assertEquals( title, post.title().get() );
-
-        post = templateFor( Post.class );
-        queryBuilder = module.newQueryBuilder( Post.class ).where( eq( post.title(), title ) );
-        query = uow.newQuery( queryBuilder );
-        assertEquals( 1, query.count() );
-        post = query.find();
-        assertNotNull( post );
-        assertEquals( title, post.title().get() );
-
-        post = templateFor( Post.class );
-        queryBuilder = module.newQueryBuilder( Post.class ).where( eq( post.title(), "Not available" ) );
-        query = uow.newQuery( queryBuilder );
-        assertEquals( 0, query.count() );
-
-        post = templateFor( Post.class );
-        queryBuilder = module.newQueryBuilder( Post.class ).where( ne( post.title(), "Not available" ) );
-        query = uow.newQuery( queryBuilder );
-        assertEquals( 1, query.count() );
-
-        post = templateFor( Post.class );
-        queryBuilder = module.newQueryBuilder( Post.class ).where( not( eq( post.title(), "Not available" ) ) );
-        query = uow.newQuery( queryBuilder );
-        post = query.find();
-        assertNotNull( post );
-        assertEquals( title, post.title().get() );
-
-        post = templateFor( Post.class );
-        queryBuilder = module.newQueryBuilder( Post.class ).where( eq( post.author().get().nickname(), "eskatos" ) );
-        query = uow.newQuery( queryBuilder );
-        assertEquals( 1, query.count() );
-        post = query.find();
-        assertNotNull( post );
-        assertEquals( title, post.title().get() );
-
-        uow.discard();
-    }
-
-}
diff --git a/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/ImmenseTermTest.java b/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/ImmenseTermTest.java
deleted file mode 100644
index 6308f40..0000000
--- a/extensions/indexing-elasticsearch/src/test/java/org/qi4j/index/elasticsearch/ImmenseTermTest.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2014 the original author or authors
- *
- * Licensed 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.qi4j.index.elasticsearch;
-
-import java.io.File;
-import java.util.List;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.Test;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.elasticsearch.assembly.ESFilesystemIndexQueryAssembler;
-import org.qi4j.library.fileconfig.FileConfigurationOverride;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.util.DelTreeAfter;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.api.query.QueryExpressions.eq;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-import static org.qi4j.test.util.Assume.assumeNoIbmJdk;
-
-/**
- * ImmenseTermTest.
- * <p>
- * See <a href="https://ops4j1.jira.com/browse/QI-412">QI-412</a>.
- */
-public class ImmenseTermTest
-    extends AbstractQi4jTest
-{
-    private static final File DATA_DIR = new File( "build/tmp/immense-term-test" );
-    @Rule
-    public final DelTreeAfter delTreeAfter = new DelTreeAfter( DATA_DIR );
-
-    @BeforeClass
-    public static void beforeClass_IBMJDK()
-    {
-        assumeNoIbmJdk();
-    }
-
-    public interface TestEntity
-        extends EntityComposite
-    {
-        @Optional
-        Property<String> property();
-
-        @Queryable( false )
-        ManyAssociation<TestEntity2> manyAssociation();
-    }
-
-    public interface TestEntity2
-        extends EntityComposite
-    {
-        @Optional
-        Property<String> property();
-
-        @Optional
-        Property<List<Byte>> binaryProperty();
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // Config module
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-
-        // EntityStore
-        new EntityTestAssembler().assemble( module );
-
-        // Index/Query
-        new ESFilesystemIndexQueryAssembler().
-            withConfig( config, Visibility.layer ).
-            assemble( module );
-        ElasticSearchConfiguration esConfig = config.forMixin( ElasticSearchConfiguration.class ).declareDefaults();
-        esConfig.indexNonAggregatedAssociations().set( Boolean.TRUE );
-
-        // FileConfig
-        FileConfigurationOverride override = new FileConfigurationOverride().
-            withData( new File( DATA_DIR, "qi4j-data" ) ).
-            withLog( new File( DATA_DIR, "qi4j-logs" ) ).
-            withTemporary( new File( DATA_DIR, "qi4j-temp" ) );
-        module.services( FileConfigurationService.class ).
-            setMetaInfo( override );
-
-        // Entities & Values
-        module.entities( TestEntity.class, TestEntity2.class );
-    }
-
-    @Test
-    public void testManyAssociation()
-        throws Exception
-    {
-        long count = 10_000L;
-        TestEntity testEntity;
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            testEntity = uow.newEntity( TestEntity.class );
-            for( long i = 0; i < count; i++ )
-            {
-                TestEntity2 testEntity2 = module.currentUnitOfWork().newEntity( TestEntity2.class );
-                testEntity2.property().set( "test" );
-                testEntity.manyAssociation().add( testEntity2 );
-            }
-            uow.complete();
-        }
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            testEntity = uow.get( testEntity );
-            Query<TestEntity2> query = uow.newQuery(
-                module.newQueryBuilder( TestEntity2.class ).where(
-                    eq( templateFor( TestEntity2.class ).property(), "test" )
-                )
-            );
-            assertThat( query.count(), is( count ) );
-            assertThat( testEntity.manyAssociation().count(), is( (int) count ) );
-        }
-    }
-}
diff --git a/extensions/indexing-elasticsearch/src/test/resources/logback-test.xml b/extensions/indexing-elasticsearch/src/test/resources/logback-test.xml
index 00ad4d8..5e5016d 100644
--- a/extensions/indexing-elasticsearch/src/test/resources/logback-test.xml
+++ b/extensions/indexing-elasticsearch/src/test/resources/logback-test.xml
@@ -1,20 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <configuration>
 
     <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
@@ -27,6 +30,6 @@
         <appender-ref ref="stdout" />
     </root>
 
-    <logger name="org.qi4j.index" level="trace"/>
+    <logger name="org.apache.polygene.index" level="trace"/>
 
 </configuration>
diff --git a/extensions/indexing-rdf/build.gradle b/extensions/indexing-rdf/build.gradle
index a612974..73ebf31 100644
--- a/extensions/indexing-rdf/build.gradle
+++ b/extensions/indexing-rdf/build.gradle
@@ -1,40 +1,40 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ RDF Index/Query Extension"
+apply plugin: 'polygene-extension'
 
-jar { manifest { name = "Apache Zest™ Extension - Index/Query - RDF" } }
+description = "Apache Polygene™ RDF Index/Query Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - Index/Query - RDF" } }
 
 dependencies {
+  api polygene.core.bootstrap
+  api polygene.library( 'rdf' )
 
-    compile project( ":org.qi4j.core:org.qi4j.core.bootstrap" )
-    compile project( ":org.qi4j.libraries:org.qi4j.library.rdf" )
-    compile libraries.sesame
-    compile libraries.commons_lang
-    compile libraries.slf4j_api
+  implementation libraries.commons_lang
 
-    testCompile project( ':org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson' )
-    testCompile project( ':org.qi4j.extensions:org.qi4j.extension.entitystore-preferences' )
-    testCompile project( ':org.qi4j.extensions:org.qi4j.extension.entitystore-jdbm' )
-    testCompile project( ":org.qi4j.core:org.qi4j.core.testsupport" )
+  runtimeOnly polygene.core.runtime
 
-    testRuntime project( ":org.qi4j.core:org.qi4j.core.runtime" )
-    testRuntime libraries.logback
+  testImplementation polygene.core.testsupport
+  testImplementation polygene.extension( 'entitystore-preferences' )
+  testImplementation polygene.extension( 'entitystore-jdbm' )
 
+  testRuntimeOnly libraries.logback
 }
diff --git a/extensions/indexing-rdf/dev-status.xml b/extensions/indexing-rdf/dev-status.xml
index ac63cda..762e250 100644
--- a/extensions/indexing-rdf/dev-status.xml
+++ b/extensions/indexing-rdf/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
         <!--none,early,beta,stable,mature-->
         <codebase>stable</codebase>
diff --git a/extensions/indexing-rdf/src/docs/index-rdf.txt b/extensions/indexing-rdf/src/docs/index-rdf.txt
index 620a071..20ce6d1 100644
--- a/extensions/indexing-rdf/src/docs/index-rdf.txt
+++ b/extensions/indexing-rdf/src/docs/index-rdf.txt
@@ -35,7 +35,7 @@
 
 [snippet,java]
 ----
-source=extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/DocumentationSupport.java
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/DocumentationSupport.java
 tag=memory
 ----
 
@@ -49,7 +49,7 @@
 
 [snippet,java]
 ----
-source=extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/DocumentationSupport.java
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/DocumentationSupport.java
 tag=native
 ----
 
@@ -59,7 +59,7 @@
 
 [snippet,java]
 ----
-source=libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/NativeConfiguration.java
+source=libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/NativeConfiguration.java
 tag=config
 ----
 
@@ -72,7 +72,7 @@
 
 [snippet,java]
 ----
-source=extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/DocumentationSupport.java
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/DocumentationSupport.java
 tag=rdbms
 ----
 
@@ -82,6 +82,151 @@
 
 [snippet,java]
 ----
-source=libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/RdbmsRepositoryConfiguration.java
+source=libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/RdbmsRepositoryConfiguration.java
 tag=config
 ----
+
+== Named RDF Queries ==
+RDF queries are rather difficult to create manually. Not only do you need to learn a difficult language and a new
+syntax, but also need to understand the indexing model that happens in Apache Polygene RDF indexing system.
+
+Below follows a large set of working queries, which can be used as a starting point. See the testcases for
+details of the Entity model that is being indexed.
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query1
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query2
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query3
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query4
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query5
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query6
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query7
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query8
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query9
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query10
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query11
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query12
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query13
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query14
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query15
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query16
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query17
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query18
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query19
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query20
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query21
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query22
+----
+
+[snippet,java]
+----
+source=extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
+tag=query24
+----
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/RdfIndexingEngineService.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/RdfIndexingEngineService.java
new file mode 100644
index 0000000..089c255
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/RdfIndexingEngineService.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.index.rdf;
+
+import org.apache.polygene.index.rdf.indexing.RdfExporter;
+import org.apache.polygene.index.rdf.indexing.RdfIndexingService;
+import org.apache.polygene.index.rdf.query.RdfQueryService;
+
+public interface RdfIndexingEngineService
+    extends RdfQueryService, RdfIndexingService, RdfExporter
+{
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/UnsupportedLanguageException.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/UnsupportedLanguageException.java
new file mode 100644
index 0000000..3e02eb9
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/UnsupportedLanguageException.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.index.rdf;
+
+import org.openrdf.query.QueryLanguage;
+
+public class UnsupportedLanguageException
+    extends RuntimeException
+{
+    private QueryLanguage language;
+
+    public UnsupportedLanguageException( QueryLanguage language )
+    {
+        super( "Unsupported RDF Query Language: " + language );
+        this.language = language;
+    }
+
+    public QueryLanguage language()
+    {
+        return language;
+    }
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/AbstractRdfIndexingAssembler.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/AbstractRdfIndexingAssembler.java
new file mode 100644
index 0000000..0bea34a
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/AbstractRdfIndexingAssembler.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.index.rdf.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+
+@SuppressWarnings( "WeakerAccess" )
+public abstract class AbstractRdfIndexingAssembler<AssemblerType>
+    extends Assemblers.VisibilityIdentityConfig<AssemblerType>
+{
+    public AbstractRdfIndexingAssembler()
+    {
+        identifiedBy( "rdf-indexing" );
+    }
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/RdfIndexingAssembler.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/RdfIndexingAssembler.java
new file mode 100644
index 0000000..05fcc42
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/RdfIndexingAssembler.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.index.rdf.assembly;
+
+/**
+ * This is a dummy Assembler to support the Yeoman Polygene Generator, which require naming conventions for
+ * the systems that it supports.
+ */
+@SuppressWarnings( "unused" )
+public class RdfIndexingAssembler extends RdfNativeSesameStoreAssembler
+{
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/RdfMemoryStoreAssembler.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/RdfMemoryStoreAssembler.java
new file mode 100644
index 0000000..b4738db
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/RdfMemoryStoreAssembler.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.index.rdf.assembly;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.rdf.RdfIndexingEngineService;
+import org.apache.polygene.index.rdf.query.RdfQueryParserFactory;
+import org.apache.polygene.library.rdf.entity.EntityStateSerializer;
+import org.apache.polygene.library.rdf.entity.EntityTypeSerializer;
+import org.apache.polygene.library.rdf.repository.MemoryRepositoryService;
+
+public class RdfMemoryStoreAssembler extends AbstractRdfIndexingAssembler<RdfNativeSesameStoreAssembler>
+{
+    private Visibility repositoryVisibility;
+
+    public RdfMemoryStoreAssembler()
+    {
+        this(Visibility.application, Visibility.module);
+    }
+
+    public RdfMemoryStoreAssembler( Visibility indexingVisibility, Visibility repositoryVisibility )
+    {
+        this.repositoryVisibility = repositoryVisibility;
+        visibleIn( indexingVisibility );
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( MemoryRepositoryService.class )
+              .visibleIn( repositoryVisibility )
+              .instantiateOnStartup();
+        module.services( RdfIndexingEngineService.class )
+              .taggedWith( "rdf", "query", "indexing" )
+              .visibleIn( visibility() )
+              .instantiateOnStartup();
+        module.services( RdfQueryParserFactory.class ).visibleIn( visibility() );
+        module.objects( EntityStateSerializer.class, EntityTypeSerializer.class );
+    }
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/RdfNativeSesameStoreAssembler.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/RdfNativeSesameStoreAssembler.java
new file mode 100644
index 0000000..57173db
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/RdfNativeSesameStoreAssembler.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.index.rdf.assembly;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.rdf.RdfIndexingEngineService;
+import org.apache.polygene.index.rdf.query.RdfQueryParserFactory;
+import org.apache.polygene.library.rdf.entity.EntityStateSerializer;
+import org.apache.polygene.library.rdf.entity.EntityTypeSerializer;
+import org.apache.polygene.library.rdf.repository.NativeConfiguration;
+import org.apache.polygene.library.rdf.repository.NativeRepositoryService;
+
+public class RdfNativeSesameStoreAssembler extends AbstractRdfIndexingAssembler<RdfNativeSesameStoreAssembler>
+{
+    private Visibility repositoryVisibility;
+
+    public RdfNativeSesameStoreAssembler()
+    {
+        visibleIn( Visibility.application );
+        this.repositoryVisibility = Visibility.module;
+    }
+
+    public RdfNativeSesameStoreAssembler( Visibility indexingVisibility, Visibility repositoryVisibility )
+    {
+        visibleIn( indexingVisibility );
+        this.repositoryVisibility = repositoryVisibility;
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( NativeRepositoryService.class )
+              .visibleIn( repositoryVisibility )
+              .instantiateOnStartup();
+        module.services( RdfIndexingEngineService.class )
+              .taggedWith( "rdf", "query", "indexing" )
+              .visibleIn( visibility() )
+              .instantiateOnStartup();
+        module.services( RdfQueryParserFactory.class ).visibleIn( visibility() );
+        module.objects( EntityStateSerializer.class, EntityTypeSerializer.class );
+
+        if( hasConfig() )
+        {
+            configModule().entities( NativeConfiguration.class ).
+                visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/RdfRdbmsSesameStoreAssembler.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/RdfRdbmsSesameStoreAssembler.java
new file mode 100644
index 0000000..5629697
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/RdfRdbmsSesameStoreAssembler.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.index.rdf.assembly;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.rdf.RdfIndexingEngineService;
+import org.apache.polygene.index.rdf.query.RdfQueryParserFactory;
+import org.apache.polygene.library.rdf.entity.EntityStateSerializer;
+import org.apache.polygene.library.rdf.entity.EntityTypeSerializer;
+import org.apache.polygene.library.rdf.repository.RdbmsRepositoryConfiguration;
+import org.apache.polygene.library.rdf.repository.RdbmsRepositoryService;
+
+public class RdfRdbmsSesameStoreAssembler  extends AbstractRdfIndexingAssembler<RdfNativeSesameStoreAssembler>
+{
+    private Visibility repositoryVisibility;
+
+    public RdfRdbmsSesameStoreAssembler()
+    {
+        this( Visibility.application, Visibility.module );
+    }
+
+    @SuppressWarnings( "WeakerAccess" )
+    public RdfRdbmsSesameStoreAssembler( Visibility indexingVisibility, Visibility repositoryVisibility )
+    {
+        visibleIn( indexingVisibility );
+        this.repositoryVisibility = repositoryVisibility;
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( RdbmsRepositoryService.class )
+              .visibleIn( repositoryVisibility )
+              .instantiateOnStartup();
+        module.services( RdfIndexingEngineService.class )
+              .taggedWith( "rdf", "query", "indexing" )
+              .visibleIn( visibility() )
+              .instantiateOnStartup();
+        module.services( RdfQueryParserFactory.class ).visibleIn( visibility() );
+        module.objects( EntityStateSerializer.class, EntityTypeSerializer.class );
+
+        if( hasConfig() )
+        {
+            configModule().entities( RdbmsRepositoryConfiguration.class ).
+                visibleIn( configVisibility() );
+        }
+    }
+}
\ No newline at end of file
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/package.html b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/package.html
new file mode 100644
index 0000000..d86fcfe
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>RDF Index/Query Assembly.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/indexing/RdfExporter.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/indexing/RdfExporter.java
new file mode 100644
index 0000000..a69c017
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/indexing/RdfExporter.java
@@ -0,0 +1,106 @@
+/*
+ *  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.polygene.index.rdf.indexing;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import org.openrdf.repository.Repository;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.rio.RDFFormat;
+import org.openrdf.rio.RDFWriter;
+import org.openrdf.rio.Rio;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.spi.query.IndexExporter;
+
+/**
+ * JAVADOC
+ */
+@Mixins( RdfExporter.RdfExporterMixin.class )
+public interface RdfExporter
+    extends IndexExporter
+{
+    /**
+     * JAVADOC
+     */
+    class RdfExporterMixin
+        implements IndexExporter
+    {
+        @Service
+        private Repository repository;
+
+        @Override
+        public void exportReadableToStream( PrintStream out )
+            throws IOException
+        {
+            RDFWriter rdfWriter = Rio.createWriter( RDFFormat.TRIG, out );
+            try
+            {
+                final RepositoryConnection connection = repository.getConnection();
+                try
+                {
+                    connection.export( rdfWriter );
+                }
+                catch( Exception e )
+                {
+                    e.printStackTrace();
+                }
+                finally
+                {
+                    connection.close();
+                }
+            }
+            catch( RepositoryException e )
+            {
+                throw new IOException( e );
+            }
+        }
+
+        @Override
+        public void exportFormalToWriter( PrintWriter out )
+            throws IOException
+        {
+            RDFWriter rdfWriter = Rio.createWriter( RDFFormat.RDFXML, out );
+            try
+            {
+                final RepositoryConnection connection = repository.getConnection();
+                try
+                {
+                    connection.export( rdfWriter );
+                }
+                catch( Exception e )
+                {
+                    e.printStackTrace();
+                }
+                finally
+                {
+                    connection.close();
+                }
+            }
+            catch( RepositoryException e )
+            {
+                throw new IOException( e );
+            }
+        }
+    }
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/indexing/RdfIndexingService.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/indexing/RdfIndexingService.java
new file mode 100644
index 0000000..11c5ce7
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/indexing/RdfIndexingService.java
@@ -0,0 +1,240 @@
+/*
+ *  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.polygene.index.rdf.indexing;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.library.rdf.entity.EntityStateSerializer;
+import org.apache.polygene.library.rdf.entity.EntityTypeSerializer;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.entitystore.StateChangeListener;
+import org.openrdf.model.Graph;
+import org.openrdf.model.Resource;
+import org.openrdf.model.Statement;
+import org.openrdf.model.URI;
+import org.openrdf.model.ValueFactory;
+import org.openrdf.model.impl.GraphImpl;
+import org.openrdf.repository.Repository;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+
+@Mixins( RdfIndexingService.RdfEntityIndexerMixin.class )
+@Activators( RdfIndexingService.Activator.class )
+public interface RdfIndexingService
+    extends StateChangeListener
+{
+    void initialize();
+
+    File dataDir();
+
+    class Activator extends ActivatorAdapter<ServiceReference<RdfIndexingService>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<RdfIndexingService> activated )
+            throws Exception
+        {
+            activated.get().initialize();
+        }
+    }
+
+    /**
+     * JAVADOC Add JavaDoc
+     */
+    abstract class RdfEntityIndexerMixin
+        implements RdfIndexingService
+    {
+        @Service
+        private ServiceReference<Repository> repository;
+
+        @Uses
+        private EntityStateSerializer stateSerializer;
+
+        @Uses
+        private EntityTypeSerializer typeSerializer;
+
+        private Set<EntityDescriptor> indexedEntityTypes;
+        private ValueFactory valueFactory;
+
+        @Override
+        public void initialize()
+        {
+            indexedEntityTypes = new HashSet<>();
+        }
+
+        @Override
+        public void notifyChanges( Iterable<EntityState> entityStates )
+        {
+            try
+            {
+                if( repository == null || !repository.isActive() ) // has been shut down, or not yet started...
+                {
+                    return;
+                }
+                final RepositoryConnection connection = repository.get().getConnection();
+                // The Repository is being initialized and not ready yet.
+                // This happens when the Repository is being initialized and it is accessing its own configuration.
+                if( connection == null )
+                {
+                    return;
+                }
+                connection.setAutoCommit( false );
+                try
+                {
+                    removeEntityStates( entityStates, connection );
+                    connection.commit();
+                    final Set<EntityDescriptor> entityTypes = indexUpdates( entityStates, connection );
+                    indexNewTypes( connection, entityTypes );
+                }
+                finally
+                {
+                    connection.commit();
+                    connection.close();
+                }
+            }
+            catch( Throwable e )
+            {
+                e.printStackTrace();
+                //TODO What shall we do with the exception?
+            }
+        }
+
+        private void indexNewTypes( RepositoryConnection connection, Set<EntityDescriptor> entityTypes )
+            throws RepositoryException
+        {
+            // Index new types
+            for( EntityDescriptor entityType : entityTypes )
+            {
+                if( !indexedEntityTypes.contains( entityType ) )
+                {
+                    indexEntityType( entityType, connection );
+                    indexedEntityTypes.add( entityType );
+                }
+            }
+        }
+
+        private Set<EntityDescriptor> indexUpdates( Iterable<EntityState> entityStates,
+                                                    RepositoryConnection connection
+        )
+            throws RepositoryException
+        {
+            // Figure out what to update
+            final Set<EntityDescriptor> entityTypes = new HashSet<>();
+            for( EntityState entityState : entityStates )
+            {
+                if( entityState.status().equals( EntityStatus.UPDATED ) )
+                {
+                    indexEntityState( entityState, connection );
+                    entityTypes.add( entityState.entityDescriptor() );
+                }
+                else if( entityState.status().equals( EntityStatus.NEW ) )
+                {
+                    indexEntityState( entityState, connection );
+                    entityTypes.add( entityState.entityDescriptor() );
+                }
+            }
+            return entityTypes;
+        }
+
+        private void removeEntityStates( Iterable<EntityState> entityStates, RepositoryConnection connection )
+            throws RepositoryException
+        {
+            List<URI> removedStates = new ArrayList<>();
+            for( EntityState entityState : entityStates )
+            {
+                if( entityState.status().equals( EntityStatus.REMOVED ) )
+                {
+                    removedStates.add( stateSerializer.createEntityURI( getValueFactory(), entityState.entityReference() ) );
+                }
+                else if( entityState.status().equals( EntityStatus.UPDATED ) )
+                {
+                    removedStates.add( stateSerializer.createEntityURI( getValueFactory(), entityState.entityReference() ) );
+                }
+            }
+
+            if( !removedStates.isEmpty() )
+            {
+                Resource[] resources = removedStates.toArray( new Resource[ removedStates.size() ] );
+                connection.remove( null, null, null, resources );
+            }
+        }
+
+        private void indexEntityState( final EntityState entityState,
+                                       final RepositoryConnection connection
+        )
+            throws RepositoryException
+        {
+            if( entityState.entityDescriptor().queryable() )
+            {
+                EntityReference reference = entityState.entityReference();
+                final URI entityURI = stateSerializer.createEntityURI( getValueFactory(), reference);
+                Graph graph = new GraphImpl();
+                stateSerializer.serialize( entityState, false, graph );
+                connection.add( graph, entityURI );
+            }
+        }
+
+        private void indexEntityType( final EntityDescriptor entityType,
+                                      final RepositoryConnection connection
+        )
+            throws RepositoryException
+        {
+            if( entityType.queryable() )
+            {
+                String uri = Classes.toURI(entityType.types().findFirst().orElse(null));
+                final URI compositeURI = getValueFactory().createURI( uri );
+                // remove composite type if already present
+                connection.clear( compositeURI );
+
+                Iterable<Statement> statements = typeSerializer.serialize( entityType );
+                connection.add( statements, compositeURI );
+            }
+        }
+
+        private ValueFactory getValueFactory()
+        {
+            if( valueFactory == null )
+            {
+                valueFactory = repository.get().getValueFactory();
+            }
+            return valueFactory;
+        }
+
+        @Override
+        public File dataDir()
+        {
+            return repository.get().getDataDir();
+        }
+    }
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/indexing/package.html b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/indexing/package.html
new file mode 100644
index 0000000..d21012e
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/indexing/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>RDF Index.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/package.html b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/package.html
new file mode 100644
index 0000000..e6ec248
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>RDF Index/Query.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/CollectingQualifiedIdentityResultCallback.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/CollectingQualifiedIdentityResultCallback.java
new file mode 100644
index 0000000..c77f471
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/CollectingQualifiedIdentityResultCallback.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.index.rdf.query;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import org.apache.polygene.api.entity.EntityReference;
+
+public class CollectingQualifiedIdentityResultCallback
+    implements QualifiedIdentityResultCallback
+{
+    private final Collection<EntityReference> entities = new ArrayList<>();
+
+    @Override
+    public boolean processRow( long row, EntityReference entityReference )
+    {
+        entities.add( entityReference );
+        return true;
+    }
+
+    public Collection<EntityReference> entities()
+    {
+        return entities;
+    }
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/QualifiedIdentityResultCallback.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/QualifiedIdentityResultCallback.java
new file mode 100644
index 0000000..5303d50
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/QualifiedIdentityResultCallback.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.index.rdf.query;
+
+import org.apache.polygene.api.entity.EntityReference;
+
+public interface QualifiedIdentityResultCallback
+{
+    /**
+     * @param row             the current row of the resultset
+     * @param entityReference The entity reference found via the query.
+     *
+     * @return true if resultset processing should stop.
+     */
+    boolean processRow( long row, EntityReference entityReference );
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/RdfQueryParser.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/RdfQueryParser.java
new file mode 100644
index 0000000..5296ed3
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/RdfQueryParser.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.index.rdf.query;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.query.grammar.OrderBy;
+
+public interface RdfQueryParser
+{
+    String constructQuery( Class<?> resultType,
+                           Predicate<Composite> whereClause,
+                           List<OrderBy> orderBySegments,
+                           Integer firstResult,
+                           Integer maxResults,
+                           Map<String, Object> variables
+    );
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/RdfQueryParserFactory.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/RdfQueryParserFactory.java
new file mode 100644
index 0000000..ab7d1e1
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/RdfQueryParserFactory.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.index.rdf.query;
+
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.index.rdf.UnsupportedLanguageException;
+import org.apache.polygene.index.rdf.query.internal.RdfQueryParserImpl;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.apache.polygene.spi.serialization.JsonSerializer;
+import org.openrdf.query.QueryLanguage;
+
+@Mixins( RdfQueryParserFactory.RdfQueryParserFactoryMixin.class )
+public interface RdfQueryParserFactory
+{
+    RdfQueryParser newQueryParser( QueryLanguage language );
+
+    abstract class RdfQueryParserFactoryMixin
+        implements RdfQueryParserFactory
+    {
+        @Structure
+        private PolygeneSPI spi;
+
+        @Service
+        private JsonSerializer stateSerializer;
+
+        @Override
+        public RdfQueryParser newQueryParser( QueryLanguage language )
+        {
+            if( language.equals( QueryLanguage.SPARQL ) )
+            {
+                return new RdfQueryParserImpl( spi, stateSerializer );
+            }
+            throw new UnsupportedLanguageException( language );
+        }
+    }
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/RdfQueryService.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/RdfQueryService.java
new file mode 100644
index 0000000..7c3fdf7
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/RdfQueryService.java
@@ -0,0 +1,123 @@
+/*
+ *  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.polygene.index.rdf.query;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.api.query.grammar.QuerySpecification;
+import org.apache.polygene.spi.query.EntityFinder;
+import org.apache.polygene.spi.query.EntityFinderException;
+import org.openrdf.query.QueryLanguage;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+@Mixins( { RdfQueryService.RdfEntityFinderMixin.class } )
+public interface RdfQueryService
+    extends EntityFinder, RdfQueryParserFactory
+{
+    /**
+     * JAVADOC Add JavaDoc
+     */
+    class RdfEntityFinderMixin
+        implements EntityFinder
+    {
+
+        private static final QueryLanguage language = QueryLanguage.SPARQL;
+
+        @Service
+        private RdfQueryParserFactory queryParserFactory;
+
+        @This
+        TupleQueryExecutor tupleExecutor;
+
+        @Override
+        public Stream<EntityReference> findEntities( Class<?> resultType,
+                                                     Predicate<Composite> whereClause,
+                                                     List<OrderBy> orderBySegments,
+                                                     Integer firstResult,
+                                                     Integer maxResults,
+                                                     Map<String, Object> variables ) throws EntityFinderException
+        {
+            CollectingQualifiedIdentityResultCallback collectingCallback = new CollectingQualifiedIdentityResultCallback();
+
+            if( QuerySpecification.isQueryLanguage( "SERQL", whereClause ))
+            {
+                String query = ((QuerySpecification)whereClause).query();
+                tupleExecutor.performTupleQuery( QueryLanguage.SERQL, query, variables, collectingCallback );
+                return collectingCallback.entities().stream();
+
+            } else
+            {
+                RdfQueryParser rdfQueryParser = queryParserFactory.newQueryParser( language );
+                String query = rdfQueryParser.constructQuery( resultType, whereClause, orderBySegments, firstResult, maxResults, variables );
+
+                tupleExecutor.performTupleQuery( language, query, variables, collectingCallback );
+                return collectingCallback.entities().stream();
+            }
+        }
+
+        @Override
+        public EntityReference findEntity( Class<?> resultType, Predicate<Composite> whereClause, Map<String, Object> variables )
+            throws EntityFinderException
+        {
+            final SingleQualifiedIdentityResultCallback singleCallback = new SingleQualifiedIdentityResultCallback();
+
+            if (QuerySpecification.isQueryLanguage( "SERQL", whereClause))
+            {
+                String query = ((QuerySpecification)whereClause).query();
+                tupleExecutor.performTupleQuery( QueryLanguage.SERQL, query, variables, singleCallback );
+                return singleCallback.qualifiedIdentity();
+            } else
+            {
+                RdfQueryParser rdfQueryParser = queryParserFactory.newQueryParser( language );
+                String query = rdfQueryParser.constructQuery( resultType, whereClause, null, null, null, variables );
+                tupleExecutor.performTupleQuery( QueryLanguage.SPARQL, query, variables, singleCallback );
+                return singleCallback.qualifiedIdentity();
+            }
+        }
+
+        @Override
+        public long countEntities( Class<?> resultType, Predicate<Composite> whereClause, Map<String, Object> variables )
+            throws EntityFinderException
+        {
+            if (QuerySpecification.isQueryLanguage( "SERQL", whereClause ))
+            {
+                String query = ((QuerySpecification)whereClause).query();
+                return tupleExecutor.performTupleQuery( QueryLanguage.SERQL, query, variables, null );
+
+            } else
+            {
+                RdfQueryParser rdfQueryParser = queryParserFactory.newQueryParser( language );
+                String query = rdfQueryParser.constructQuery( resultType, whereClause, null, null, null, variables );
+                return tupleExecutor.performTupleQuery( language, query, variables, null );
+            }
+        }
+    }
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/SesameExpressions.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/SesameExpressions.java
new file mode 100644
index 0000000..50910f8
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/SesameExpressions.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.index.rdf.query;
+
+import org.apache.polygene.api.query.grammar.QuerySpecification;
+
+/**
+ * Sesame specific operators to be used with QueryBuilder.where().
+ */
+public class SesameExpressions
+{
+    public static QuerySpecification sparql(String sparql)
+    {
+        return new QuerySpecification("SPARQL", sparql);
+    }
+
+    public static QuerySpecification serql(String serql)
+    {
+        return new QuerySpecification("SERQL", serql);
+    }
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/SingleQualifiedIdentityResultCallback.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/SingleQualifiedIdentityResultCallback.java
new file mode 100644
index 0000000..6192e2a
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/SingleQualifiedIdentityResultCallback.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.index.rdf.query;
+
+import org.apache.polygene.api.entity.EntityReference;
+
+public class SingleQualifiedIdentityResultCallback
+    implements QualifiedIdentityResultCallback
+{
+    private EntityReference entityReference;
+
+    @Override
+    public boolean processRow( long row, EntityReference entityReference )
+    {
+        this.entityReference = entityReference;
+        return false;
+    }
+
+    public EntityReference qualifiedIdentity()
+    {
+        return entityReference;
+    }
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/TupleQueryExecutor.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/TupleQueryExecutor.java
new file mode 100644
index 0000000..2d80bd8
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/TupleQueryExecutor.java
@@ -0,0 +1,150 @@
+/*
+ *  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.polygene.index.rdf.query;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.openrdf.model.Value;
+import org.openrdf.model.impl.ValueFactoryImpl;
+import org.openrdf.query.*;
+import org.openrdf.repository.Repository;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.spi.query.EntityFinderException;
+
+@Mixins( TupleQueryExecutor.TupleQueryExecutorMixin.class )
+public interface TupleQueryExecutor
+{
+    long performTupleQuery( QueryLanguage language, String query, @Optional Map<String, Object> bindings, @Optional QualifiedIdentityResultCallback callback )
+        throws EntityFinderException;
+
+    class TupleQueryExecutorMixin
+        implements TupleQueryExecutor
+    {
+        @Service
+        private Repository repository;
+
+        @Override
+        public long performTupleQuery( QueryLanguage language, String query, Map<String, Object> bindings, QualifiedIdentityResultCallback callback )
+            throws EntityFinderException
+        {
+            try
+            {
+                RepositoryConnection connection = repository.getConnection();
+                TupleQueryResult result = null;
+                try
+                {
+
+                    TupleQuery tupleQuery = connection.prepareTupleQuery( language, query );
+
+                    for (Map.Entry<String, Value> stringValueEntry : getBindings( bindings ).entrySet())
+                    {
+                        tupleQuery.setBinding(stringValueEntry.getKey(), stringValueEntry.getValue());
+                    }
+
+                    tupleQuery.setIncludeInferred( false );
+                    result = tupleQuery.evaluate();
+                    long row = 0;
+                    while( result.hasNext() )
+                    {
+                        if( handleCallbacks( callback, result, row ) )
+                        {
+                            break;
+                        }
+                        row++;
+                    }
+                    return row;
+                }
+                finally
+                {
+                    if( result != null )
+                    {
+                        result.close();
+                    }
+                    if( connection != null )
+                    {
+                        connection.close();
+                    }
+                }
+            }
+            catch( RepositoryException e )
+            {
+                throw new EntityFinderException( e );
+            }
+            catch( MalformedQueryException e )
+            {
+                throw new EntityFinderException( e );
+            }
+            catch( QueryEvaluationException e )
+            {
+                throw new EntityFinderException( e );
+            }
+            catch( Exception e )
+            {
+                throw new EntityFinderException( e );
+            }
+        }
+
+        private boolean handleCallbacks( QualifiedIdentityResultCallback callback, TupleQueryResult result, long row )
+            throws Exception
+        {
+            BindingSet bindingSet = result.next();
+            if( callback != null )
+            {
+                if( !processRow( row, bindingSet, callback ) )
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        private boolean processRow( long row, BindingSet bindingSet, QualifiedIdentityResultCallback callback )
+        {
+            final Value identifier = bindingSet.getValue( "reference" );
+
+            //TODO Shall we throw an exception if there is no binding for identifier = query parser is not right
+            if( identifier == null )
+            {
+                return true;
+            }
+
+            final String identity = identifier.stringValue();
+
+            final EntityReference entityReference = EntityReference.parseEntityReference( identity );
+            return callback.processRow( row, entityReference );
+        }
+
+        private Map<String, Value> getBindings(Map<String, Object> variables)
+        {
+            Map<String, Value> bindings = new HashMap<>();
+            for (Map.Entry<String, Object> stringObjectEntry : variables.entrySet())
+            {
+                if (!stringObjectEntry.getValue().getClass().equals(Object.class))
+                    bindings.put(stringObjectEntry.getKey(), ValueFactoryImpl.getInstance().createLiteral(stringObjectEntry.getValue().toString()));
+            }
+            return bindings;
+        }
+    }
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/internal/Namespaces.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/internal/Namespaces.java
new file mode 100644
index 0000000..47527fa
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/internal/Namespaces.java
@@ -0,0 +1,86 @@
+/*
+ *  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.polygene.index.rdf.query.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static java.lang.String.format;
+
+public class Namespaces
+{
+    private int namespaceCounter = 0;
+
+    /**
+     * Mapping between namespace and prefix.
+     */
+    private final Map<String, String> namespaces = new HashMap<>();
+
+    public Namespaces()
+    {
+        addDefaultNamespaces();
+    }
+
+    private void addDefaultNamespaces()
+    {
+        addNamespace( "rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#" );
+        addNamespace( "rdfs", "http://www.w3.org/2000/01/rdf-schema#" );
+    }
+
+    public Iterable<? extends String> namespaces()
+    {
+        return namespaces.keySet();
+    }
+
+    public String addNamespace( final String namespace )
+    {
+        String prefix = namespacePrefix( namespace );
+        if( prefix != null )
+        {
+            return prefix;
+        }
+        prefix = "ns" + namespaceCounter++;
+        return addNamespace( prefix, namespace );
+    }
+
+    public String namespacePrefix( String namespace )
+    {
+        return namespaces.get( namespace );
+    }
+
+    public String addNamespace( final String prefix,
+                                final String namespace
+    )
+    {
+        namespaces.put( namespace, prefix );
+        return prefix;
+    }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+        for( String namespace : namespaces() )
+        {
+            sb.append( format( "%s:%s%n", namespacePrefix( namespace ), namespace ) );
+        }
+        return sb.toString();
+    }
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/internal/RdfQueryParserImpl.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/internal/RdfQueryParserImpl.java
new file mode 100644
index 0000000..c0bec0d
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/internal/RdfQueryParserImpl.java
@@ -0,0 +1,555 @@
+/*
+ *  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.polygene.index.rdf.query.internal;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.query.grammar.AndPredicate;
+import org.apache.polygene.api.query.grammar.AssociationNotNullPredicate;
+import org.apache.polygene.api.query.grammar.AssociationNullPredicate;
+import org.apache.polygene.api.query.grammar.ComparisonPredicate;
+import org.apache.polygene.api.query.grammar.ContainsAllPredicate;
+import org.apache.polygene.api.query.grammar.ContainsPredicate;
+import org.apache.polygene.api.query.grammar.EqPredicate;
+import org.apache.polygene.api.query.grammar.GePredicate;
+import org.apache.polygene.api.query.grammar.GtPredicate;
+import org.apache.polygene.api.query.grammar.LePredicate;
+import org.apache.polygene.api.query.grammar.LtPredicate;
+import org.apache.polygene.api.query.grammar.ManyAssociationContainsPredicate;
+import org.apache.polygene.api.query.grammar.MatchesPredicate;
+import org.apache.polygene.api.query.grammar.NePredicate;
+import org.apache.polygene.api.query.grammar.Notpredicate;
+import org.apache.polygene.api.query.grammar.OrPredicate;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.api.query.grammar.PropertyNotNullPredicate;
+import org.apache.polygene.api.query.grammar.PropertyNullPredicate;
+import org.apache.polygene.api.query.grammar.QuerySpecification;
+import org.apache.polygene.api.query.grammar.Variable;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.index.rdf.query.RdfQueryParser;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.apache.polygene.spi.serialization.JsonSerializer;
+import org.slf4j.LoggerFactory;
+
+import static java.lang.String.format;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+public class RdfQueryParserImpl
+    implements RdfQueryParser
+{
+    private static final Map<Class<? extends ComparisonPredicate>, String> OPERATORS;
+    private static final Set<Character> RESERVED_CHARS;
+
+    private final Namespaces namespaces = new Namespaces();
+    private final Triples triples = new Triples( namespaces );
+    private final PolygeneSPI spi;
+    private final JsonSerializer stateSerializer;
+    private Map<String, Object> variables;
+
+    static
+    {
+        OPERATORS = new HashMap<>( 6 );
+        OPERATORS.put( EqPredicate.class, "=" );
+        OPERATORS.put( GePredicate.class, ">=" );
+        OPERATORS.put( GtPredicate.class, ">" );
+        OPERATORS.put( LePredicate.class, "<=" );
+        OPERATORS.put( LtPredicate.class, "<" );
+        OPERATORS.put( NePredicate.class, "!=" );
+
+        RESERVED_CHARS = new HashSet<>( Arrays.asList(
+            '\"', '^', '.', '\\', '?', '*', '+', '{', '}', '(', ')', '|', '$', '[', ']'
+        ) );
+    }
+
+    public RdfQueryParserImpl( PolygeneSPI spi, JsonSerializer stateSerializer )
+    {
+        this.spi = spi;
+        this.stateSerializer = stateSerializer;
+    }
+
+    @Override
+    public String constructQuery( final Class<?> resultType,
+                                  final Predicate<Composite> specification,
+                                  final List<OrderBy> orderBySegments,
+                                  final Integer firstResult,
+                                  final Integer maxResults,
+                                  final Map<String, Object> variables
+    )
+    {
+        this.variables = variables;
+
+        if( QuerySpecification.isQueryLanguage( "SPARQL", specification ) )
+        {
+            // Custom query
+            StringBuilder queryBuilder = new StringBuilder();
+            String query = ( (QuerySpecification) specification ).query();
+            queryBuilder.append( query );
+
+            if( orderBySegments != null )
+            {
+                queryBuilder.append( "\nORDER BY " );
+                processOrderBy( orderBySegments, queryBuilder );
+            }
+            if( firstResult != null )
+            {
+                queryBuilder.append( "\nOFFSET " ).append( firstResult );
+            }
+            if( maxResults != null )
+            {
+                queryBuilder.append( "\nLIMIT " ).append( maxResults );
+            }
+
+            return queryBuilder.toString();
+        }
+        else
+        {
+            // Add type+reference triples last. This makes queries faster since the query engine can reduce the number
+            // of triples to check faster
+            triples.addDefaultTriples( resultType.getName() );
+        }
+
+        // and collect namespaces
+        StringBuilder filter = new StringBuilder();
+        processFilter( specification, true, filter );
+        StringBuilder orderBy = new StringBuilder();
+        processOrderBy( orderBySegments, orderBy );
+
+        StringBuilder query = new StringBuilder();
+
+        for( String namespace : namespaces.namespaces() )
+        {
+            query.append( format( "PREFIX %s: <%s> %n", namespaces.namespacePrefix( namespace ), namespace ) );
+        }
+        query.append( "SELECT DISTINCT ?reference\n" );
+        if( triples.hasTriples() )
+        {
+            query.append( "WHERE {\n" );
+            StringBuilder optional = new StringBuilder();
+            for( Triples.Triple triple : triples )
+            {
+                final String subject = triple.subject();
+                final String predicate = triple.predicate();
+                final String value = triple.value();
+
+                if( triple.isOptional() )
+                {
+                    optional.append( format( "OPTIONAL {%s %s %s}. ", subject, predicate, value ) );
+                    optional.append( '\n' );
+                }
+                else
+                {
+                    query.append( format( "%s %s %s. ", subject, predicate, value ) );
+                    query.append( '\n' );
+                }
+            }
+
+            // Add OPTIONAL statements last
+            if( optional.length() > 0 )
+            {
+                query.append( optional.toString() );
+            }
+
+            if( filter.length() > 0 )
+            {
+                query.append( "FILTER " ).append( filter );
+            }
+            query.append( "\n}" );
+        }
+        if( orderBy.length() > 0 )
+        {
+            query.append( "\nORDER BY " ).append( orderBy );
+        }
+        if( firstResult != null )
+        {
+            query.append( "\nOFFSET " ).append( firstResult );
+        }
+        if( maxResults != null )
+        {
+            query.append( "\nLIMIT " ).append( maxResults );
+        }
+
+        LoggerFactory.getLogger( getClass() ).debug( "Query:\n" + query );
+        return query.toString();
+    }
+
+    private void processFilter( final Predicate<Composite> expression, boolean allowInline, StringBuilder builder )
+    {
+        if( expression == null )
+        {
+            return;
+        }
+
+        if( expression instanceof AndPredicate )
+        {
+            final AndPredicate conjunction = (AndPredicate) expression;
+
+            int start = builder.length();
+            boolean first = true;
+            for( Predicate<Composite> operand : conjunction.operands() )
+            {
+                int size = builder.length();
+                processFilter( operand, allowInline, builder );
+                if( builder.length() > size )
+                {
+                    if( first )
+                    {
+                        first = false;
+                    }
+                    else
+                    {
+                        builder.insert( size, " && " );
+                    }
+                }
+            }
+
+            if( builder.length() > start )
+            {
+                builder.insert( start, '(' );
+                builder.append( ')' );
+            }
+        }
+        else if( expression instanceof OrPredicate )
+        {
+            final OrPredicate disjunction = (OrPredicate) expression;
+
+            int start = builder.length();
+            boolean first = true;
+            for( Predicate<Composite> operand : disjunction.operands() )
+            {
+                int size = builder.length();
+                processFilter( operand, false, builder );
+                if( builder.length() > size )
+                {
+                    if( first )
+                    {
+                        first = false;
+                    }
+                    else
+                    {
+                        builder.insert( size, "||" );
+                    }
+                }
+            }
+
+            if( builder.length() > start )
+            {
+                builder.insert( start, '(' );
+                builder.append( ')' );
+            }
+        }
+        else if( expression instanceof Notpredicate )
+        {
+            builder.insert( 0, "(!" );
+            processFilter( ( (Notpredicate) expression ).operand(), false, builder );
+            builder.append( ")" );
+        }
+        else if( expression instanceof ComparisonPredicate )
+        {
+            processComparisonPredicate( expression, allowInline, builder );
+        }
+        else if( expression instanceof ContainsAllPredicate )
+        {
+            processContainsAllPredicate( (ContainsAllPredicate) expression, builder );
+        }
+        else if( expression instanceof ContainsPredicate<?> )
+        {
+            processContainsPredicate( (ContainsPredicate<?>) expression, builder );
+        }
+        else if( expression instanceof MatchesPredicate )
+        {
+            processMatchesPredicate( (MatchesPredicate) expression, builder );
+        }
+        else if( expression instanceof PropertyNotNullPredicate<?> )
+        {
+            processNotNullPredicate( (PropertyNotNullPredicate) expression, builder );
+        }
+        else if( expression instanceof PropertyNullPredicate<?> )
+        {
+            processNullPredicate( (PropertyNullPredicate) expression, builder );
+        }
+        else if( expression instanceof AssociationNotNullPredicate<?> )
+        {
+            processNotNullPredicate( (AssociationNotNullPredicate) expression, builder );
+        }
+        else if( expression instanceof AssociationNullPredicate<?> )
+        {
+            processNullPredicate( (AssociationNullPredicate) expression, builder );
+        }
+        else if( expression instanceof ManyAssociationContainsPredicate<?> )
+        {
+            processManyAssociationContainsPredicate( (ManyAssociationContainsPredicate) expression, allowInline, builder );
+        }
+        else
+        {
+            throw new UnsupportedOperationException( "Expression " + expression + " is not supported" );
+        }
+    }
+
+    private static void join( String[] strings, String delimiter, StringBuilder builder )
+    {
+        for( Integer x = 0; x < strings.length; ++x )
+        {
+            builder.append( strings[ x] );
+            if( x + 1 < strings.length )
+            {
+                builder.append( delimiter );
+            }
+        }
+    }
+
+    private String createAndEscapeJSONString( Object value )
+    {
+        String serialized = stateSerializer.serialize( Serializer.Options.NO_TYPE_INFO, value );
+        return escapeJSONString( serialized );
+    }
+
+    private String createRegexStringForContaining( String valueVariable, String containedString )
+    {
+        // The matching value must start with [, then contain something (possibly nothing),
+        // then our value, then again something (possibly nothing), and end with ]
+        return format( "regex(str(%s), \"^\\\\u005B.*%s.*\\\\u005D$\", \"s\")", valueVariable, containedString );
+    }
+
+    private String escapeJSONString( String jsonStr )
+    {
+        StringBuilder builder = new StringBuilder();
+        char[] chars = jsonStr.toCharArray();
+        for( int i = 0; i < chars.length; i++ )
+        {
+            char c = chars[ i];
+
+            /*
+             if ( reservedJsonChars.contains( c ))
+             {
+             builder.append( "\\\\u" ).append( format( "%04X", (int) '\\' ) );
+             }
+             */
+            if( RESERVED_CHARS.contains( c ) )
+            {
+                builder.append( "\\\\u" ).append( format( "%04X", (int) c ) );
+            }
+            else
+            {
+                builder.append( c );
+            }
+        }
+
+        return builder.toString();
+    }
+
+    private void processContainsAllPredicate( final ContainsAllPredicate<?> predicate, StringBuilder builder )
+    {
+        Collection<?> values = predicate.containedValues();
+        String valueVariable = triples.addTriple( predicate.collectionProperty(), false ).value();
+        String[] strings = new String[ values.size() ];
+        Integer x = 0;
+        for( Object item : values )
+        {
+            String jsonStr = "";
+            if( item != null )
+            {
+                String serialized = stateSerializer.serialize( Serializer.Options.NO_TYPE_INFO, item );
+                if( item instanceof String )
+                {
+                    serialized = "\"" + StringEscapeUtils.escapeJava( serialized ) + "\"";
+                }
+                jsonStr = escapeJSONString( serialized );
+            }
+            strings[ x] = this.createRegexStringForContaining( valueVariable, jsonStr );
+            x++;
+        }
+
+        if( strings.length > 0 )
+        {
+            // For some reason, just "FILTER ()" causes error in SPARQL query
+            builder.append( "(" );
+            join( strings, " && ", builder );
+            builder.append( ")" );
+        }
+        else
+        {
+            builder.append( this.createRegexStringForContaining( valueVariable, "" ) );
+        }
+    }
+
+    private void processContainsPredicate( final ContainsPredicate<?> predicate, StringBuilder builder )
+    {
+        Object value = predicate.value();
+        String valueVariable = triples.addTriple( predicate.collectionProperty(), false ).value();
+        builder.append( this.createRegexStringForContaining(
+            valueVariable,
+            this.createAndEscapeJSONString( value )
+        ) );
+    }
+
+    private void processMatchesPredicate( final MatchesPredicate predicate, StringBuilder builder )
+    {
+        String valueVariable = triples.addTriple( predicate.property(), false ).value();
+        builder.append( format( "regex(%s,\"%s\")", valueVariable, predicate.regexp() ) );
+    }
+
+    private void processComparisonPredicate( final Predicate<Composite> predicate,
+                                             boolean allowInline,
+                                             StringBuilder builder
+    )
+    {
+        if( predicate instanceof ComparisonPredicate )
+        {
+            ComparisonPredicate<?> comparisonPredicate = (ComparisonPredicate<?>) predicate;
+            Triples.Triple triple = triples.addTriple( comparisonPredicate.property(), false );
+
+            // Don't use FILTER for equals-comparison. Do direct match instead
+            if( predicate instanceof EqPredicate && allowInline )
+            {
+                triple.setValue( "\"" + toString( comparisonPredicate.value() ) + "\"" );
+            }
+            else
+            {
+                String valueVariable = triple.value();
+                builder.append( String.format(
+                    "(%s %s \"%s\")",
+                    valueVariable,
+                    getOperator( comparisonPredicate.getClass() ),
+                    toString( comparisonPredicate.value() ) ) );
+            }
+        }
+        else
+        {
+            throw new UnsupportedOperationException( "Operator " + predicate.getClass()
+                .getName() + " is not supported" );
+        }
+    }
+
+    private void processNullPredicate( final PropertyNullPredicate<?> predicate, StringBuilder builder )
+    {
+        final String value = triples.addTriple( predicate.property(), true ).value();
+        builder.append( format( "(! bound(%s))", value ) );
+    }
+
+    private void processNotNullPredicate( final PropertyNotNullPredicate<?> predicate, StringBuilder builder )
+    {
+        final String value = triples.addTriple( predicate.property(), true ).value();
+        builder.append( format( "(bound(%s))", value ) );
+    }
+
+    private void processNullPredicate( final AssociationNullPredicate<?> predicate, StringBuilder builder )
+    {
+        final String value = triples.addTripleAssociation( predicate.association(), true ).value();
+        builder.append( format( "(! bound(%s))", value ) );
+    }
+
+    private void processNotNullPredicate( final AssociationNotNullPredicate<?> predicate, StringBuilder builder )
+    {
+        final String value = triples.addTripleAssociation( predicate.association(), true ).value();
+        builder.append( format( "(bound(%s))", value ) );
+    }
+
+    private void processManyAssociationContainsPredicate( ManyAssociationContainsPredicate<?> predicate,
+                                                          boolean allowInline, StringBuilder builder
+    )
+    {
+        Triples.Triple triple = triples.addTripleManyAssociation( predicate.manyAssociation(), false );
+
+        if( allowInline )
+        {
+            triple.setValue( "<" + toString( predicate.value() ) + ">" );
+        }
+        else
+        {
+            String valueVariable = triple.value();
+            builder.append( String.format( "(%s %s <%s>)", valueVariable, "=", toString( predicate.value() ) ) );
+        }
+    }
+
+    private void processOrderBy( List<OrderBy> orderBySegments, StringBuilder builder )
+    {
+        if( orderBySegments != null && orderBySegments.size() > 0 )
+        {
+            for( OrderBy orderBySegment : orderBySegments )
+            {
+                processOrderBy( builder, orderBySegment );
+            }
+        }
+    }
+
+    private void processOrderBy( StringBuilder builder, OrderBy orderBySegment )
+    {
+        if( orderBySegment != null )
+        {
+            final String valueVariable = triples.addTriple( orderBySegment.property(), false ).value();
+            if( orderBySegment.order() == OrderBy.Order.ASCENDING )
+            {
+                builder.append( format( "ASC(%s)", valueVariable ) );
+            }
+            else
+            {
+                builder.append( format( "DESC(%s)", valueVariable ) );
+            }
+        }
+    }
+
+    private String getOperator( final Class<? extends ComparisonPredicate> predicateClass )
+    {
+        String operator = OPERATORS.get( predicateClass );
+        if( operator == null )
+        {
+            throw new UnsupportedOperationException( "Predicate [" + predicateClass.getName() + "] is not supported" );
+        }
+        return operator;
+    }
+
+    private String toString( Object value )
+    {
+        if( value == null )
+        {
+            return null;
+        }
+        if( value instanceof EntityComposite )
+        {
+            return "urn:polygene:entity:" + value.toString();
+        }
+        if( value instanceof Variable )
+        {
+            Object realValue = variables.get( ( (Variable) value ).variableName() );
+
+            if( realValue == null )
+            {
+                throw new IllegalArgumentException( "Variable " + ( (Variable) value ).variableName() + " not bound" );
+            }
+
+            return toString( realValue );
+        }
+        else
+        {
+            return value.toString();
+        }
+    }
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/internal/Triples.java b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/internal/Triples.java
new file mode 100644
index 0000000..499ec41
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/internal/Triples.java
@@ -0,0 +1,287 @@
+/*
+ *  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.polygene.index.rdf.query.internal;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.query.grammar.AssociationFunction;
+import org.apache.polygene.api.query.grammar.ManyAssociationFunction;
+import org.apache.polygene.api.query.grammar.PropertyFunction;
+import org.apache.polygene.api.util.Classes;
+
+import static java.lang.String.format;
+
+public class Triples
+    implements Iterable<Triples.Triple>
+{
+    private int valueCounter = 0;
+    private final List<Triple> triples = new ArrayList<>();
+    private final Namespaces namespaces;
+
+    public Triples( Namespaces namespaces )
+    {
+        this.namespaces = namespaces;
+    }
+
+    public void addDefaultTriples( String resultType )
+    {
+        triples.add(
+            new Triple(
+                "?entityType",
+                "rdfs:subClassOf",
+                "<" + Classes.toURI( resultType ) + ">",
+                false )
+        );
+        triples.add(
+            new Triple(
+                "?entity",
+                "rdf:type",
+                "?entityType",
+                false )
+        );
+        triples.add(
+            new Triple(
+                "?entity",
+                addNamespace( QualifiedName.fromClass( HasIdentity.class, "identity" ).toNamespace() ) + ":identity",
+                "?reference",
+                false
+            )
+        );
+    }
+
+    private String addNamespace( String namespace )
+    {
+        return namespaces.addNamespace( namespace );
+    }
+
+    public Triple addTriple( final PropertyFunction<?> propertyFunction, boolean optional )
+    {
+        String subject = "?entity";
+        if( propertyFunction.traversedAssociation() != null )
+        {
+            subject = addTripleAssociation( propertyFunction.traversedAssociation(), false ).value;
+        }
+        else if( propertyFunction.traversedProperty() != null )
+        {
+            subject = addTriple( propertyFunction.traversedProperty(), false ).value;
+        }
+        QualifiedName qualifiedName = QualifiedName.fromAccessor( propertyFunction.accessor() );
+        String prefix = addNamespace( qualifiedName.toNamespace() );
+        return addTriple( subject, prefix + ":" + qualifiedName.name(), optional );
+    }
+
+    public Triple addTripleAssociation( AssociationFunction<?> associationReference, boolean optional )
+    {
+        String subject = "?entity";
+        if( associationReference.traversedAssociation() != null )
+        {
+            subject = addTripleAssociation( associationReference.traversedAssociation(), false ).value;
+        }
+        QualifiedName qualifiedName = QualifiedName.fromAccessor( associationReference.accessor() );
+        String prefix = addNamespace( qualifiedName.toNamespace() );
+        return addTriple( subject, prefix + ":" + qualifiedName.name(), optional );
+    }
+
+    public Triple addTripleManyAssociation( final ManyAssociationFunction<?> manyAssociationReference,
+                                            final boolean optional
+    )
+    {
+        AssociationFunction<?> traversedAssociation = manyAssociationReference.traversedAssociation();
+        String subject = "?entity";
+        if( traversedAssociation != null )
+        {
+            subject = addTripleAssociation( traversedAssociation, false ).value;
+        }
+        QualifiedName qualifiedName = QualifiedName.fromAccessor( manyAssociationReference.accessor() );
+        String predicatePrefix = addNamespace( qualifiedName.toNamespace() );
+        String predicate = predicatePrefix + ":" + qualifiedName.name();
+        Triple collectionTriple = addTriple( subject, predicate, optional );
+
+        String liSubject = collectionTriple.value;
+        return addTriple( liSubject, "rdf:li", false );
+    }
+
+    private Triple addTriple( final String subject,
+                              final String predicate,
+                              final boolean optional
+    )
+    {
+        Triple triple = getTriple( subject, predicate );
+        if( triple == null )
+        {
+            final String value = "?v" + valueCounter++;
+            triple = new Triple( subject, predicate, value, optional );
+            triples.add( triple );
+        }
+        if( !optional && triple.optional )
+        {
+            triple.optional = false;
+        }
+        return triple;
+    }
+
+    private Triple getTriple( final String subject,
+                              final String predicate
+    )
+    {
+        for( Triple triple : triples )
+        {
+            if( triple.subject.equals( subject )
+                && triple.predicate.equals( predicate ) )
+            {
+                return triple;
+            }
+        }
+        return null;
+    }
+
+    public boolean hasTriples()
+    {
+        return !triples.isEmpty();
+    }
+
+    @Override
+    public Iterator<Triple> iterator()
+    {
+        return triples.iterator();
+    }
+
+    public String toSparql()
+    {
+        StringBuilder sparql = new StringBuilder();
+        for( Triple triple : triples )
+        {
+            sparql.append( triple.toSparql() );
+        }
+        return sparql.toString();
+    }
+
+    public static class Triple
+    {
+        private final String subject;
+        private final String predicate;
+        private String value;
+        private boolean optional;
+
+        private Triple( final String subject,
+                        final String predicate,
+                        final String value,
+                        final boolean optional
+        )
+        {
+            this.subject = subject;
+            this.predicate = predicate;
+            this.value = value;
+            this.optional = optional;
+        }
+
+        @Override
+        public boolean equals( Object otherObject )
+        {
+            if( this == otherObject )
+            {
+                return true;
+            }
+            if( otherObject == null || getClass() != otherObject.getClass() )
+            {
+                return false;
+            }
+
+            Triple other = (Triple) otherObject;
+
+            if( predicate != null ? !predicate.equals( other.predicate ) : other.predicate != null )
+            {
+                return false;
+            }
+            if( subject != null ? !subject.equals( other.subject ) : other.subject != null )
+            {
+                return false;
+            }
+            if( value != null )
+            {
+                return value.equals( other.value );
+            }
+            else
+            {
+                return other.value == null;
+            }
+        }
+
+        @Override
+        public int hashCode()
+        {
+            int result;
+            result = ( subject != null ? subject.hashCode() : 0 );
+            result = 31 * result + ( predicate != null ? predicate.hashCode() : 0 );
+            result = 31 * result + ( value != null ? value.hashCode() : 0 );
+            return result;
+        }
+
+        @Override
+        public String toString()
+        {
+            return toSparql();
+        }
+
+        public String toSparql()
+        {
+
+            if( optional )
+            {
+                return format( "OPTIONAL {%s %s %s}.", subject, predicate, value );
+            }
+            return format( "%s %s %s.", subject, predicate, value );
+        }
+
+        public String subject()
+        {
+            return subject;
+        }
+
+        public String predicate()
+        {
+            return predicate;
+        }
+
+        public String value()
+        {
+            return value;
+        }
+
+        public void setValue( String value )
+        {
+            this.value = value;
+        }
+
+        public boolean isOptional()
+        {
+            return optional;
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        return triples.toString();
+    }
+}
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/internal/package.html b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/internal/package.html
new file mode 100644
index 0000000..690b710
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/internal/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>RDF Query Internal Package.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/package.html b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/package.html
new file mode 100644
index 0000000..becfa83
--- /dev/null
+++ b/extensions/indexing-rdf/src/main/java/org/apache/polygene/index/rdf/query/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>RDF Query.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/RdfIndexingEngineService.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/RdfIndexingEngineService.java
deleted file mode 100644
index 7102b65..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/RdfIndexingEngineService.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.index.rdf;
-
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.index.rdf.indexing.RdfExporter;
-import org.qi4j.index.rdf.indexing.RdfIndexingService;
-import org.qi4j.index.rdf.query.RdfQueryService;
-
-public interface RdfIndexingEngineService
-    extends RdfQueryService, RdfIndexingService, RdfExporter, ServiceComposite
-{
-}
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/UnsupportedLanguageException.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/UnsupportedLanguageException.java
deleted file mode 100644
index d9ade3f..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/UnsupportedLanguageException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.index.rdf;
-
-import org.openrdf.query.QueryLanguage;
-
-public class UnsupportedLanguageException
-    extends RuntimeException
-{
-    private QueryLanguage language;
-
-    public UnsupportedLanguageException( QueryLanguage language )
-    {
-        super( "Unsupported RDF Query Language: " + language );
-        this.language = language;
-    }
-
-    public QueryLanguage language()
-    {
-        return language;
-    }
-}
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/assembly/RdfMemoryStoreAssembler.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/assembly/RdfMemoryStoreAssembler.java
deleted file mode 100644
index 88f5a28..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/assembly/RdfMemoryStoreAssembler.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.index.rdf.assembly;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.rdf.RdfIndexingEngineService;
-import org.qi4j.index.rdf.query.RdfQueryParserFactory;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.library.rdf.entity.EntityTypeSerializer;
-import org.qi4j.library.rdf.repository.MemoryRepositoryService;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-public class RdfMemoryStoreAssembler
-    implements Assembler
-{
-    private Visibility indexingVisibility;
-    private Visibility repositoryVisibility;
-
-    public RdfMemoryStoreAssembler()
-    {
-        this( Visibility.application, Visibility.module );
-    }
-
-    public RdfMemoryStoreAssembler(
-                                    Visibility indexingVisibility,
-                                    Visibility repositoryVisibility
-    )
-    {
-        this.indexingVisibility = indexingVisibility;
-        this.repositoryVisibility = repositoryVisibility;
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( MemoryRepositoryService.class )
-            .visibleIn( repositoryVisibility )
-            .instantiateOnStartup()
-            .identifiedBy( "rdf-repository" );
-        module.services( RdfIndexingEngineService.class )
-            .visibleIn( indexingVisibility )
-            .instantiateOnStartup();
-        module.services( RdfQueryParserFactory.class ).visibleIn( indexingVisibility );
-        module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
-        module.objects( EntityStateSerializer.class, EntityTypeSerializer.class );
-    }
-}
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/assembly/RdfNativeSesameStoreAssembler.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/assembly/RdfNativeSesameStoreAssembler.java
deleted file mode 100644
index 15782a6..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/assembly/RdfNativeSesameStoreAssembler.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.index.rdf.assembly;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.rdf.RdfIndexingEngineService;
-import org.qi4j.index.rdf.query.RdfQueryParserFactory;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.library.rdf.entity.EntityTypeSerializer;
-import org.qi4j.library.rdf.repository.NativeConfiguration;
-import org.qi4j.library.rdf.repository.NativeRepositoryService;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-public class RdfNativeSesameStoreAssembler
-    implements Assembler
-{
-    private Visibility indexingVisibility;
-    private Visibility repositoryVisibility;
-
-    public RdfNativeSesameStoreAssembler()
-    {
-        this( Visibility.application, Visibility.module );
-    }
-
-    public RdfNativeSesameStoreAssembler( Visibility indexingVisibility,
-                                          Visibility repositoryVisibility
-    )
-    {
-        this.indexingVisibility = indexingVisibility;
-        this.repositoryVisibility = repositoryVisibility;
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( NativeRepositoryService.class )
-            .visibleIn( repositoryVisibility )
-            .instantiateOnStartup()
-            .identifiedBy( "rdf-indexing" );
-        module.services( RdfIndexingEngineService.class )
-            .visibleIn( indexingVisibility )
-            .instantiateOnStartup();
-        module.services( RdfQueryParserFactory.class ).visibleIn( indexingVisibility );
-        module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
-        module.objects( EntityStateSerializer.class, EntityTypeSerializer.class );
-    }
-}
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/assembly/RdfRdbmsSesameStoreAssembler.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/assembly/RdfRdbmsSesameStoreAssembler.java
deleted file mode 100644
index 5e8fe35..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/assembly/RdfRdbmsSesameStoreAssembler.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.index.rdf.assembly;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.rdf.RdfIndexingEngineService;
-import org.qi4j.index.rdf.query.RdfQueryParserFactory;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.library.rdf.entity.EntityTypeSerializer;
-import org.qi4j.library.rdf.repository.RdbmsRepositoryService;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-public class RdfRdbmsSesameStoreAssembler
-    implements Assembler
-{
-    private Visibility indexingVisibility;
-    private Visibility repositoryVisibility;
-
-    public RdfRdbmsSesameStoreAssembler()
-    {
-        this( Visibility.application, Visibility.module );
-    }
-
-    public RdfRdbmsSesameStoreAssembler(
-                                         Visibility indexingVisibility,
-                                         Visibility repositoryVisibility
-    )
-    {
-        this.indexingVisibility = indexingVisibility;
-        this.repositoryVisibility = repositoryVisibility;
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( RdbmsRepositoryService.class )
-            .visibleIn( repositoryVisibility )
-            .instantiateOnStartup()
-            .identifiedBy( "rdf-indexing" );
-        module.services( RdfIndexingEngineService.class )
-            .visibleIn( indexingVisibility )
-            .instantiateOnStartup();
-        module.services( RdfQueryParserFactory.class ).visibleIn( indexingVisibility );
-        module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
-        module.objects( EntityStateSerializer.class, EntityTypeSerializer.class );
-    }
-}
\ No newline at end of file
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/assembly/package.html b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/assembly/package.html
deleted file mode 100644
index 6739021..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/assembly/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>RDF Index/Query Assembly.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/indexing/RdfExporter.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/indexing/RdfExporter.java
deleted file mode 100644
index 7b099c1..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/indexing/RdfExporter.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.index.rdf.indexing;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import org.openrdf.repository.Repository;
-import org.openrdf.repository.RepositoryConnection;
-import org.openrdf.repository.RepositoryException;
-import org.openrdf.rio.RDFFormat;
-import org.openrdf.rio.RDFWriter;
-import org.openrdf.rio.Rio;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.spi.query.IndexExporter;
-
-/**
- * JAVADOC
- */
-@Mixins( RdfExporter.RdfExporterMixin.class )
-public interface RdfExporter
-    extends IndexExporter
-{
-    /**
-     * JAVADOC
-     */
-    class RdfExporterMixin
-        implements IndexExporter
-    {
-        @Service
-        private Repository repository;
-
-        @Override
-        public void exportReadableToStream( PrintStream out )
-            throws IOException
-        {
-            RDFWriter rdfWriter = Rio.createWriter( RDFFormat.TRIG, out );
-            try
-            {
-                final RepositoryConnection connection = repository.getConnection();
-                try
-                {
-                    connection.export( rdfWriter );
-                }
-                catch( Exception e )
-                {
-                    e.printStackTrace();
-                }
-                finally
-                {
-                    connection.close();
-                }
-            }
-            catch( RepositoryException e )
-            {
-                throw new IOException( e );
-            }
-        }
-
-        @Override
-        public void exportFormalToWriter( PrintWriter out )
-            throws IOException
-        {
-            RDFWriter rdfWriter = Rio.createWriter( RDFFormat.RDFXML, out );
-            try
-            {
-                final RepositoryConnection connection = repository.getConnection();
-                try
-                {
-                    connection.export( rdfWriter );
-                }
-                catch( Exception e )
-                {
-                    e.printStackTrace();
-                }
-                finally
-                {
-                    connection.close();
-                }
-            }
-            catch( RepositoryException e )
-            {
-                throw new IOException( e );
-            }
-        }
-    }
-}
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/indexing/RdfIndexingService.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/indexing/RdfIndexingService.java
deleted file mode 100644
index 444aa17..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/indexing/RdfIndexingService.java
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.index.rdf.indexing;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import org.openrdf.model.*;
-import org.openrdf.model.impl.GraphImpl;
-import org.openrdf.repository.Repository;
-import org.openrdf.repository.RepositoryConnection;
-import org.openrdf.repository.RepositoryException;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.util.Classes;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.library.rdf.entity.EntityTypeSerializer;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.EntityStatus;
-import org.qi4j.spi.entitystore.StateChangeListener;
-
-import static org.qi4j.functional.Iterables.first;
-
-@Mixins( RdfIndexingService.RdfEntityIndexerMixin.class )
-@Activators( RdfIndexingService.Activator.class )
-public interface RdfIndexingService
-    extends StateChangeListener
-{
-    void initialize();
-
-    File dataDir();
-
-    class Activator extends ActivatorAdapter<ServiceReference<RdfIndexingService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<RdfIndexingService> activated )
-                throws Exception
-        {
-            activated.get().initialize();
-        }
-
-    }
-
-    /**
-     * JAVADOC Add JavaDoc
-     */
-    abstract class RdfEntityIndexerMixin
-        implements RdfIndexingService
-    {
-        @Service
-        private ServiceReference<Repository> repository;
-
-        @Uses
-        private EntityStateSerializer stateSerializer;
-
-        @Uses
-        private EntityTypeSerializer typeSerializer;
-
-        private Set<EntityDescriptor> indexedEntityTypes;
-        private ValueFactory valueFactory;
-
-        @Override
-        public void initialize()
-        {
-            indexedEntityTypes = new HashSet<>();
-        }
-
-        @Override
-        public void notifyChanges( Iterable<EntityState> entityStates )
-        {
-            try
-            {
-                if( repository == null || !repository.isActive() ) // has been shut down, or not yet started...
-                {
-                    return;
-                }
-                final RepositoryConnection connection = repository.get().getConnection();
-                // The Repository is being initialized and not ready yet.
-                // This happens when the Repository is being initialized and it is accessing its own configuration.
-                if( connection == null )
-                {
-                    return;
-                }
-                connection.setAutoCommit( false );
-                try
-                {
-                    removeEntityStates( entityStates, connection );
-                    connection.commit();
-                    final Set<EntityDescriptor> entityTypes = indexUpdates( entityStates, connection );
-                    indexNewTypes( connection, entityTypes );
-                }
-                finally
-                {
-                    connection.commit();
-                    connection.close();
-                }
-            }
-            catch( Throwable e )
-            {
-                e.printStackTrace();
-                //TODO What shall we do with the exception?
-            }
-        }
-
-        private void indexNewTypes( RepositoryConnection connection, Set<EntityDescriptor> entityTypes )
-            throws RepositoryException
-        {
-            // Index new types
-            for( EntityDescriptor entityType : entityTypes )
-            {
-                if( !indexedEntityTypes.contains( entityType ) )
-                {
-                    indexEntityType( entityType, connection );
-                    indexedEntityTypes.add( entityType );
-                }
-            }
-        }
-
-        private Set<EntityDescriptor> indexUpdates( Iterable<EntityState> entityStates, RepositoryConnection connection )
-            throws RepositoryException
-        {
-            // Figure out what to update
-            final Set<EntityDescriptor> entityTypes = new HashSet<EntityDescriptor>();
-            for( EntityState entityState : entityStates )
-            {
-                if( entityState.status().equals( EntityStatus.UPDATED ) )
-                {
-                    indexEntityState( entityState, connection );
-                    entityTypes.add( entityState.entityDescriptor() );
-                }
-                else if( entityState.status().equals( EntityStatus.NEW ) )
-                {
-                    indexEntityState( entityState, connection );
-                    entityTypes.add( entityState.entityDescriptor() );
-                }
-            }
-            return entityTypes;
-        }
-
-        private void removeEntityStates( Iterable<EntityState> entityStates, RepositoryConnection connection )
-            throws RepositoryException
-        {
-            List<URI> removedStates = new ArrayList<URI>();
-            for( EntityState entityState : entityStates )
-            {
-                if( entityState.status().equals( EntityStatus.REMOVED ) )
-                {
-                    removedStates.add( stateSerializer.createEntityURI( getValueFactory(), entityState.identity() ) );
-                }
-                else if( entityState.status().equals( EntityStatus.UPDATED ) )
-                {
-                    removedStates.add( stateSerializer.createEntityURI( getValueFactory(), entityState.identity() ) );
-                }
-            }
-
-            if( !removedStates.isEmpty() )
-            {
-                Resource[] resources = removedStates.toArray( new Resource[ removedStates.size() ] );
-                connection.remove( null, null, null, resources );
-            }
-        }
-
-        private void indexEntityState( final EntityState entityState,
-                                       final RepositoryConnection connection
-        )
-            throws RepositoryException
-        {
-            if( entityState.entityDescriptor().queryable() )
-            {
-                final URI entityURI = stateSerializer.createEntityURI( getValueFactory(), entityState.identity() );
-                Graph graph = new GraphImpl();
-                stateSerializer.serialize( entityState, false, graph );
-                connection.add( graph, entityURI );
-            }
-        }
-
-        private void indexEntityType( final EntityDescriptor entityType,
-                                      final RepositoryConnection connection
-        )
-            throws RepositoryException
-        {
-            if( entityType.queryable() )
-            {
-                final URI compositeURI = getValueFactory().createURI( Classes.toURI(first( entityType.types() )) );
-                // remove composite type if already present
-                connection.clear( compositeURI );
-
-                Iterable<Statement> statements = typeSerializer.serialize( entityType );
-                connection.add( statements, compositeURI );
-            }
-        }
-
-        private ValueFactory getValueFactory()
-        {
-            if( valueFactory == null )
-            {
-                valueFactory = repository.get().getValueFactory();
-            }
-            return valueFactory;
-        }
-
-        @Override
-        public File dataDir()
-        {
-            return repository.get().getDataDir();
-        }
-    }
-}
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/indexing/package.html b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/indexing/package.html
deleted file mode 100644
index 7fb977e..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/indexing/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>RDF Index.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/package.html b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/package.html
deleted file mode 100644
index 8d4eac0..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>RDF Index/Query.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/CollectingQualifiedIdentityResultCallback.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/CollectingQualifiedIdentityResultCallback.java
deleted file mode 100644
index 4dc8f58..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/CollectingQualifiedIdentityResultCallback.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2008 Michael Hunger.
- *
- * Licensed  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.qi4j.index.rdf.query;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import org.qi4j.api.entity.EntityReference;
-
-public class CollectingQualifiedIdentityResultCallback
-    implements QualifiedIdentityResultCallback
-{
-    private final Collection<EntityReference> entities = new ArrayList<EntityReference>();
-
-    @Override
-    public boolean processRow( long row, EntityReference entityReference )
-    {
-        entities.add( entityReference );
-        return true;
-    }
-
-    public Collection<EntityReference> entities()
-    {
-        return entities;
-    }
-}
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/QualifiedIdentityResultCallback.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/QualifiedIdentityResultCallback.java
deleted file mode 100644
index 7bb699a..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/QualifiedIdentityResultCallback.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2008 Michael Hunger.
- *
- * Licensed  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.qi4j.index.rdf.query;
-
-import org.qi4j.api.entity.EntityReference;
-
-public interface QualifiedIdentityResultCallback
-{
-    /**
-     * @param row             the current row of the resultset
-     * @param entityReference The entity reference found via the query.
-     *
-     * @return true if resultset processing should stop.
-     */
-    boolean processRow( long row, EntityReference entityReference );
-}
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/RdfQueryParser.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/RdfQueryParser.java
deleted file mode 100644
index ba2b99a..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/RdfQueryParser.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.index.rdf.query;
-
-import java.util.Map;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.functional.Specification;
-
-public interface RdfQueryParser
-{
-    String constructQuery( Class<?> resultType,
-                           Specification<Composite> whereClause,
-                           OrderBy[] orderBySegments,
-                           Integer firstResult,
-                           Integer maxResults,
-                           Map<String, Object> variables
-    );
-}
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/RdfQueryParserFactory.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/RdfQueryParserFactory.java
deleted file mode 100644
index 93515e7..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/RdfQueryParserFactory.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.index.rdf.query;
-
-import org.openrdf.query.QueryLanguage;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.qualifier.Tagged;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.api.value.ValueSerializer;
-import org.qi4j.index.rdf.UnsupportedLanguageException;
-import org.qi4j.index.rdf.query.internal.RdfQueryParserImpl;
-import org.qi4j.spi.Qi4jSPI;
-
-@Mixins( RdfQueryParserFactory.RdfQueryParserFactoryMixin.class )
-public interface RdfQueryParserFactory
-    extends ServiceComposite
-{
-    RdfQueryParser newQueryParser( QueryLanguage language );
-
-    abstract class RdfQueryParserFactoryMixin
-        implements RdfQueryParserFactory
-    {
-        @Structure
-        private Qi4jSPI spi;
-        @Service
-        @Tagged( ValueSerialization.Formats.JSON )
-        private ValueSerializer valueSerializer;
-
-        @Override
-        public RdfQueryParser newQueryParser( QueryLanguage language )
-        {
-            if( language.equals( QueryLanguage.SPARQL ) )
-            {
-                return new RdfQueryParserImpl( spi, valueSerializer );
-            }
-            throw new UnsupportedLanguageException( language );
-        }
-    }
-}
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/RdfQueryService.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/RdfQueryService.java
deleted file mode 100644
index bb8b454..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/RdfQueryService.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.index.rdf.query;
-
-import java.util.Map;
-import org.openrdf.query.QueryLanguage;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.api.query.grammar.QuerySpecification;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.functional.Specification;
-import org.qi4j.spi.query.EntityFinder;
-import org.qi4j.spi.query.EntityFinderException;
-
-/**
- * JAVADOC Add JavaDoc
- */
-@Mixins( { RdfQueryService.RdfEntityFinderMixin.class } )
-public interface RdfQueryService
-    extends EntityFinder, RdfQueryParserFactory, ServiceComposite
-{
-    /**
-     * JAVADOC Add JavaDoc
-     */
-    public static class RdfEntityFinderMixin
-        implements EntityFinder
-    {
-
-        private static final QueryLanguage language = QueryLanguage.SPARQL;
-
-        @Service
-        private RdfQueryParserFactory queryParserFactory;
-
-        @This
-        TupleQueryExecutor tupleExecutor;
-
-        @Override
-        public Iterable<EntityReference> findEntities( Class<?> resultType,
-                                                       Specification<Composite> whereClause,
-                                                       OrderBy[] orderBySegments,
-                                                       Integer firstResult,
-                                                       Integer maxResults,
-                                                       Map<String, Object> variables
-        )
-            throws EntityFinderException
-        {
-            CollectingQualifiedIdentityResultCallback collectingCallback = new CollectingQualifiedIdentityResultCallback();
-
-            if( QuerySpecification.isQueryLanguage( "SERQL", whereClause ))
-            {
-                String query = ((QuerySpecification)whereClause).query();
-                tupleExecutor.performTupleQuery( QueryLanguage.SERQL, query, variables, collectingCallback );
-                return collectingCallback.entities();
-
-            } else
-            {
-                RdfQueryParser rdfQueryParser = queryParserFactory.newQueryParser( language );
-                String query = rdfQueryParser.constructQuery( resultType, whereClause, orderBySegments, firstResult, maxResults, variables );
-
-                tupleExecutor.performTupleQuery( language, query, variables, collectingCallback );
-                return collectingCallback.entities();
-            }
-        }
-
-        @Override
-        public EntityReference findEntity( Class<?> resultType, Specification<Composite> whereClause, Map<String, Object> variables )
-            throws EntityFinderException
-        {
-            final SingleQualifiedIdentityResultCallback singleCallback = new SingleQualifiedIdentityResultCallback();
-
-            if (QuerySpecification.isQueryLanguage( "SERQL", whereClause))
-            {
-                String query = ((QuerySpecification)whereClause).query();
-                tupleExecutor.performTupleQuery( QueryLanguage.SERQL, query, variables, singleCallback );
-                return singleCallback.qualifiedIdentity();
-            } else
-            {
-                RdfQueryParser rdfQueryParser = queryParserFactory.newQueryParser( language );
-                String query = rdfQueryParser.constructQuery( resultType, whereClause, null, null, null, variables );
-                tupleExecutor.performTupleQuery( QueryLanguage.SPARQL, query, variables, singleCallback );
-                return singleCallback.qualifiedIdentity();
-            }
-        }
-
-        @Override
-        public long countEntities( Class<?> resultType, Specification<Composite> whereClause, Map<String, Object> variables )
-            throws EntityFinderException
-        {
-            if (QuerySpecification.isQueryLanguage( "SERQL", whereClause ))
-            {
-                String query = ((QuerySpecification)whereClause).query();
-                return tupleExecutor.performTupleQuery( QueryLanguage.SERQL, query, variables, null );
-
-            } else
-            {
-                RdfQueryParser rdfQueryParser = queryParserFactory.newQueryParser( language );
-                String query = rdfQueryParser.constructQuery( resultType, whereClause, null, null, null, variables );
-                return tupleExecutor.performTupleQuery( language, query, variables, null );
-            }
-        }
-    }
-}
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/SesameExpressions.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/SesameExpressions.java
deleted file mode 100644
index 7bd4404..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/SesameExpressions.java
+++ /dev/null
@@ -1,37 +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.qi4j.index.rdf.query;
-
-import org.qi4j.api.query.grammar.QuerySpecification;
-
-/**
- * Sesame specific operators to be used with QueryBuilder.where().
- */
-public class SesameExpressions
-{
-    public static QuerySpecification sparql(String sparql)
-    {
-        return new QuerySpecification("SPARQL", sparql);
-    }
-
-    public static QuerySpecification serql(String serql)
-    {
-        return new QuerySpecification("SERQL", serql);
-    }
-}
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/SingleQualifiedIdentityResultCallback.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/SingleQualifiedIdentityResultCallback.java
deleted file mode 100644
index 2b05d14..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/SingleQualifiedIdentityResultCallback.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2008 Michael Hunger.
- *
- * Licensed  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.qi4j.index.rdf.query;
-
-import org.qi4j.api.entity.EntityReference;
-
-public class SingleQualifiedIdentityResultCallback
-    implements QualifiedIdentityResultCallback
-{
-    private EntityReference entityReference;
-
-    @Override
-    public boolean processRow( long row, EntityReference entityReference )
-    {
-        this.entityReference = entityReference;
-        return false;
-    }
-
-    public EntityReference qualifiedIdentity()
-    {
-        return entityReference;
-    }
-}
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/TupleQueryExecutor.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/TupleQueryExecutor.java
deleted file mode 100644
index 8072603..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/TupleQueryExecutor.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.index.rdf.query;
-
-import java.util.HashMap;
-import java.util.Map;
-import org.openrdf.model.Value;
-import org.openrdf.model.impl.ValueFactoryImpl;
-import org.openrdf.query.*;
-import org.openrdf.repository.Repository;
-import org.openrdf.repository.RepositoryConnection;
-import org.openrdf.repository.RepositoryException;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.spi.query.EntityFinderException;
-
-@Mixins( TupleQueryExecutor.TupleQueryExecutorMixin.class )
-public interface TupleQueryExecutor
-{
-    long performTupleQuery( QueryLanguage language, String query, @Optional Map<String, Object> bindings, @Optional QualifiedIdentityResultCallback callback )
-        throws EntityFinderException;
-
-    class TupleQueryExecutorMixin
-        implements TupleQueryExecutor
-    {
-        @Service
-        private Repository repository;
-
-        @Override
-        public long performTupleQuery( QueryLanguage language, String query, Map<String, Object> bindings, QualifiedIdentityResultCallback callback )
-            throws EntityFinderException
-        {
-            try
-            {
-                RepositoryConnection connection = repository.getConnection();
-                TupleQueryResult result = null;
-                try
-                {
-
-                    TupleQuery tupleQuery = connection.prepareTupleQuery( language, query );
-
-                    for (Map.Entry<String, Value> stringValueEntry : getBindings( bindings ).entrySet())
-                    {
-                        tupleQuery.setBinding(stringValueEntry.getKey(), stringValueEntry.getValue());
-                    }
-
-                    tupleQuery.setIncludeInferred( false );
-                    result = tupleQuery.evaluate();
-                    long row = 0;
-                    while( result.hasNext() )
-                    {
-                        if( handleCallbacks( callback, result, row ) )
-                        {
-                            break;
-                        }
-                        row++;
-                    }
-                    return row;
-                }
-                finally
-                {
-                    if( result != null )
-                    {
-                        result.close();
-                    }
-                    if( connection != null )
-                    {
-                        connection.close();
-                    }
-                }
-            }
-            catch( RepositoryException e )
-            {
-                throw new EntityFinderException( e );
-            }
-            catch( MalformedQueryException e )
-            {
-                throw new EntityFinderException( e );
-            }
-            catch( QueryEvaluationException e )
-            {
-                throw new EntityFinderException( e );
-            }
-            catch( Exception e )
-            {
-                throw new EntityFinderException( e );
-            }
-        }
-
-        private boolean handleCallbacks( QualifiedIdentityResultCallback callback, TupleQueryResult result, long row )
-            throws Exception
-        {
-            BindingSet bindingSet = result.next();
-            if( callback != null )
-            {
-                if( !processRow( row, bindingSet, callback ) )
-                {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        private boolean processRow( long row, BindingSet bindingSet, QualifiedIdentityResultCallback callback )
-        {
-            final Value identifier = bindingSet.getValue( "identity" );
-
-            //TODO Shall we throw an exception if there is no binding for identifier = query parser is not right
-            if( identifier == null )
-            {
-                return true;
-            }
-
-            final String identity = identifier.stringValue();
-
-            final EntityReference entityReference = new EntityReference( identity );
-            return callback.processRow( row, entityReference );
-        }
-
-        private Map<String, Value> getBindings(Map<String, Object> variables)
-        {
-            Map<String, Value> bindings = new HashMap<String, Value>();
-            for (Map.Entry<String, Object> stringObjectEntry : variables.entrySet())
-            {
-                if (!stringObjectEntry.getValue().getClass().equals(Object.class))
-                    bindings.put(stringObjectEntry.getKey(), ValueFactoryImpl.getInstance().createLiteral(stringObjectEntry.getValue().toString()));
-            }
-            return bindings;
-        }
-    }
-}
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/internal/Namespaces.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/internal/Namespaces.java
deleted file mode 100644
index e5e5937..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/internal/Namespaces.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2008 Michael Hunger.
- *
- * Licensed  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.qi4j.index.rdf.query.internal;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static java.lang.String.format;
-
-public class Namespaces
-{
-    private int namespaceCounter = 0;
-
-    /**
-     * Mapping between namespace and prefix.
-     */
-    private final Map<String, String> namespaces = new HashMap<String, String>();
-
-    public Namespaces()
-    {
-        addDefaultNamespaces();
-    }
-
-    private void addDefaultNamespaces()
-    {
-        addNamespace( "rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#" );
-        addNamespace( "rdfs", "http://www.w3.org/2000/01/rdf-schema#" );
-    }
-
-    public Iterable<? extends String> namespaces()
-    {
-        return namespaces.keySet();
-    }
-
-    public String addNamespace( final String namespace )
-    {
-        String prefix = namespacePrefix( namespace );
-        if( prefix != null )
-        {
-            return prefix;
-        }
-        prefix = "ns" + namespaceCounter++;
-        return addNamespace( prefix, namespace );
-    }
-
-    public String namespacePrefix( String namespace )
-    {
-        return namespaces.get( namespace );
-    }
-
-    public String addNamespace( final String prefix,
-                                final String namespace
-    )
-    {
-        namespaces.put( namespace, prefix );
-        return prefix;
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder();
-        for( String namespace : namespaces() )
-        {
-            sb.append( format( "%s:%s%n", namespacePrefix( namespace ), namespace ) );
-        }
-        return sb.toString();
-    }
-}
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/internal/RdfQueryParserImpl.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/internal/RdfQueryParserImpl.java
deleted file mode 100644
index 122ce01..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/internal/RdfQueryParserImpl.java
+++ /dev/null
@@ -1,581 +0,0 @@
-/*
- * Copyright 2011 Rickard Öberg.
- *
- * Licensed  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.qi4j.index.rdf.query.internal;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.TimeZone;
-import org.apache.commons.lang.StringEscapeUtils;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.query.grammar.AndSpecification;
-import org.qi4j.api.query.grammar.AssociationNotNullSpecification;
-import org.qi4j.api.query.grammar.AssociationNullSpecification;
-import org.qi4j.api.query.grammar.ComparisonSpecification;
-import org.qi4j.api.query.grammar.ContainsAllSpecification;
-import org.qi4j.api.query.grammar.ContainsSpecification;
-import org.qi4j.api.query.grammar.EqSpecification;
-import org.qi4j.api.query.grammar.GeSpecification;
-import org.qi4j.api.query.grammar.GtSpecification;
-import org.qi4j.api.query.grammar.LeSpecification;
-import org.qi4j.api.query.grammar.LtSpecification;
-import org.qi4j.api.query.grammar.ManyAssociationContainsSpecification;
-import org.qi4j.api.query.grammar.MatchesSpecification;
-import org.qi4j.api.query.grammar.NeSpecification;
-import org.qi4j.api.query.grammar.NotSpecification;
-import org.qi4j.api.query.grammar.OrSpecification;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.api.query.grammar.PropertyFunction;
-import org.qi4j.api.query.grammar.PropertyNotNullSpecification;
-import org.qi4j.api.query.grammar.PropertyNullSpecification;
-import org.qi4j.api.query.grammar.QuerySpecification;
-import org.qi4j.api.query.grammar.Variable;
-import org.qi4j.api.value.ValueSerializer;
-import org.qi4j.api.value.ValueSerializer.Options;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.index.rdf.query.RdfQueryParser;
-import org.qi4j.spi.Qi4jSPI;
-import org.slf4j.LoggerFactory;
-
-import static java.lang.String.format;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public class RdfQueryParserImpl
-    implements RdfQueryParser
-{
-    private static final ThreadLocal<DateFormat> ISO8601_UTC = new ThreadLocal<DateFormat>()
-    {
-        @Override
-        protected DateFormat initialValue()
-        {
-            SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" );
-            dateFormat.setTimeZone( TimeZone.getTimeZone( "UTC" ) );
-            return dateFormat;
-        }
-    };
-
-    private static final Map<Class<? extends ComparisonSpecification>, String> OPERATORS;
-    private static final Set<Character> RESERVED_CHARS;
-
-    private final Namespaces namespaces = new Namespaces();
-    private final Triples triples = new Triples( namespaces );
-    private final Qi4jSPI spi;
-    private final ValueSerializer valueSerializer;
-    private Map<String, Object> variables;
-
-    static
-    {
-        OPERATORS = new HashMap<>( 6 );
-        OPERATORS.put( EqSpecification.class, "=" );
-        OPERATORS.put( GeSpecification.class, ">=" );
-        OPERATORS.put( GtSpecification.class, ">" );
-        OPERATORS.put( LeSpecification.class, "<=" );
-        OPERATORS.put( LtSpecification.class, "<" );
-        OPERATORS.put( NeSpecification.class, "!=" );
-
-        RESERVED_CHARS = new HashSet<>( Arrays.asList(
-            '\"', '^', '.', '\\', '?', '*', '+', '{', '}', '(', ')', '|', '$', '[', ']'
-        ) );
-    }
-
-    public RdfQueryParserImpl( Qi4jSPI spi, ValueSerializer valueSerializer )
-    {
-        this.spi = spi;
-        this.valueSerializer = valueSerializer;
-    }
-
-    @Override
-    public String constructQuery( final Class<?> resultType,
-                                  final Specification<Composite> specification,
-                                  final OrderBy[] orderBySegments,
-                                  final Integer firstResult,
-                                  final Integer maxResults,
-                                  final Map<String, Object> variables
-    )
-    {
-        this.variables = variables;
-
-        if( QuerySpecification.isQueryLanguage( "SPARQL", specification ) )
-        {
-            // Custom query
-            StringBuilder queryBuilder = new StringBuilder();
-            String query = ( (QuerySpecification) specification ).query();
-            queryBuilder.append( query );
-
-            if( orderBySegments != null )
-            {
-                queryBuilder.append( "\nORDER BY " );
-                processOrderBy( orderBySegments, queryBuilder );
-            }
-            if( firstResult != null )
-            {
-                queryBuilder.append( "\nOFFSET " ).append( firstResult );
-            }
-            if( maxResults != null )
-            {
-                queryBuilder.append( "\nLIMIT " ).append( maxResults );
-            }
-
-            return queryBuilder.toString();
-        }
-        else
-        {
-            // Add type+identity triples last. This makes queries faster since the query engine can reduce the number
-            // of triples to check faster
-            triples.addDefaultTriples( resultType.getName() );
-        }
-
-        // and collect namespaces
-        StringBuilder filter = new StringBuilder();
-        processFilter( specification, true, filter );
-        StringBuilder orderBy = new StringBuilder();
-        processOrderBy( orderBySegments, orderBy );
-
-        StringBuilder query = new StringBuilder();
-
-        for( String namespace : namespaces.namespaces() )
-        {
-            query.append( format( "PREFIX %s: <%s> %n", namespaces.namespacePrefix( namespace ), namespace ) );
-        }
-        query.append( "SELECT DISTINCT ?identity\n" );
-        if( triples.hasTriples() )
-        {
-            query.append( "WHERE {\n" );
-            StringBuilder optional = new StringBuilder();
-            for( Triples.Triple triple : triples )
-            {
-                final String subject = triple.subject();
-                final String predicate = triple.predicate();
-                final String value = triple.value();
-
-                if( triple.isOptional() )
-                {
-                    optional.append( format( "OPTIONAL {%s %s %s}. ", subject, predicate, value ) );
-                    optional.append( '\n' );
-                }
-                else
-                {
-                    query.append( format( "%s %s %s. ", subject, predicate, value ) );
-                    query.append( '\n' );
-                }
-            }
-
-            // Add OPTIONAL statements last
-            if( optional.length() > 0 )
-            {
-                query.append( optional.toString() );
-            }
-
-            if( filter.length() > 0 )
-            {
-                query.append( "FILTER " ).append( filter );
-            }
-            query.append( "\n}" );
-        }
-        if( orderBy.length() > 0 )
-        {
-            query.append( "\nORDER BY " ).append( orderBy );
-        }
-        if( firstResult != null )
-        {
-            query.append( "\nOFFSET " ).append( firstResult );
-        }
-        if( maxResults != null )
-        {
-            query.append( "\nLIMIT " ).append( maxResults );
-        }
-
-        LoggerFactory.getLogger( getClass() ).debug( "Query:\n" + query );
-        return query.toString();
-    }
-
-    private void processFilter( final Specification<Composite> expression, boolean allowInline, StringBuilder builder )
-    {
-        if( expression == null )
-        {
-            return;
-        }
-
-        if( expression instanceof AndSpecification )
-        {
-            final AndSpecification conjunction = (AndSpecification) expression;
-
-            int start = builder.length();
-            boolean first = true;
-            for( Specification<Composite> operand : conjunction.operands() )
-            {
-                int size = builder.length();
-                processFilter( operand, allowInline, builder );
-                if( builder.length() > size )
-                {
-                    if( first )
-                    {
-                        first = false;
-                    }
-                    else
-                    {
-                        builder.insert( size, " && " );
-                    }
-                }
-            }
-
-            if( builder.length() > start )
-            {
-                builder.insert( start, '(' );
-                builder.append( ')' );
-            }
-        }
-        else if( expression instanceof OrSpecification )
-        {
-            final OrSpecification disjunction = (OrSpecification) expression;
-
-            int start = builder.length();
-            boolean first = true;
-            for( Specification<Composite> operand : disjunction.operands() )
-            {
-                int size = builder.length();
-                processFilter( operand, false, builder );
-                if( builder.length() > size )
-                {
-                    if( first )
-                    {
-                        first = false;
-                    }
-                    else
-                    {
-                        builder.insert( size, "||" );
-                    }
-                }
-            }
-
-            if( builder.length() > start )
-            {
-                builder.insert( start, '(' );
-                builder.append( ')' );
-            }
-        }
-        else if( expression instanceof NotSpecification )
-        {
-            builder.insert( 0, "(!" );
-            processFilter( ( (NotSpecification) expression ).operand(), false, builder );
-            builder.append( ")" );
-        }
-        else if( expression instanceof ComparisonSpecification )
-        {
-            processComparisonPredicate( expression, allowInline, builder );
-        }
-        else if( expression instanceof ContainsAllSpecification )
-        {
-            processContainsAllPredicate( (ContainsAllSpecification) expression, builder );
-        }
-        else if( expression instanceof ContainsSpecification<?> )
-        {
-            processContainsPredicate( (ContainsSpecification<?>) expression, builder );
-        }
-        else if( expression instanceof MatchesSpecification )
-        {
-            processMatchesPredicate( (MatchesSpecification) expression, builder );
-        }
-        else if( expression instanceof PropertyNotNullSpecification<?> )
-        {
-            processNotNullPredicate( (PropertyNotNullSpecification) expression, builder );
-        }
-        else if( expression instanceof PropertyNullSpecification<?> )
-        {
-            processNullPredicate( (PropertyNullSpecification) expression, builder );
-        }
-        else if( expression instanceof AssociationNotNullSpecification<?> )
-        {
-            processNotNullPredicate( (AssociationNotNullSpecification) expression, builder );
-        }
-        else if( expression instanceof AssociationNullSpecification<?> )
-        {
-            processNullPredicate( (AssociationNullSpecification) expression, builder );
-        }
-        else if( expression instanceof ManyAssociationContainsSpecification<?> )
-        {
-            processManyAssociationContainsPredicate( (ManyAssociationContainsSpecification) expression, allowInline, builder );
-        }
-        else
-        {
-            throw new UnsupportedOperationException( "Expression " + expression + " is not supported" );
-        }
-    }
-
-    private static void join( String[] strings, String delimiter, StringBuilder builder )
-    {
-        for( Integer x = 0; x < strings.length; ++x )
-        {
-            builder.append( strings[ x] );
-            if( x + 1 < strings.length )
-            {
-                builder.append( delimiter );
-            }
-        }
-    }
-
-    private String createAndEscapeJSONString( Object value )
-    {
-        return escapeJSONString( valueSerializer.serialize( new Options().withoutTypeInfo(), value ) );
-    }
-
-    private String createRegexStringForContaining( String valueVariable, String containedString )
-    {
-        // The matching value must start with [, then contain something (possibly nothing),
-        // then our value, then again something (possibly nothing), and end with ]
-        return format( "regex(str(%s), \"^\\\\u005B.*%s.*\\\\u005D$\", \"s\")", valueVariable, containedString );
-    }
-
-    private String escapeJSONString( String jsonStr )
-    {
-        StringBuilder builder = new StringBuilder();
-        char[] chars = jsonStr.toCharArray();
-        for( int i = 0; i < chars.length; i++ )
-        {
-            char c = chars[ i];
-
-            /*
-             if ( reservedJsonChars.contains( c ))
-             {
-             builder.append( "\\\\u" ).append( format( "%04X", (int) '\\' ) );
-             }
-             */
-            if( RESERVED_CHARS.contains( c ) )
-            {
-                builder.append( "\\\\u" ).append( format( "%04X", (int) c ) );
-            }
-            else
-            {
-                builder.append( c );
-            }
-        }
-
-        return builder.toString();
-    }
-
-    private void processContainsAllPredicate( final ContainsAllSpecification<?> predicate, StringBuilder builder )
-    {
-        Iterable<?> values = predicate.containedValues();
-        String valueVariable = triples.addTriple( predicate.collectionProperty(), false ).value();
-        String[] strings;
-        if( values instanceof Collection )
-        {
-            strings = new String[ ( (Collection<?>) values ).size() ];
-        }
-        else
-        {
-            strings = new String[ ( (int) Iterables.count( values ) ) ];
-        }
-        Integer x = 0;
-        for( Object item : (Collection<?>) values )
-        {
-            String jsonStr = "";
-            if( item != null )
-            {
-                String serialized = valueSerializer.serialize( item, false );
-                if( item instanceof String )
-                {
-                    serialized = "\"" + StringEscapeUtils.escapeJava( serialized ) + "\"";
-                }
-                jsonStr = escapeJSONString( serialized );
-            }
-            strings[ x] = this.createRegexStringForContaining( valueVariable, jsonStr );
-            x++;
-        }
-
-        if( strings.length > 0 )
-        {
-            // For some reason, just "FILTER ()" causes error in SPARQL query
-            builder.append( "(" );
-            join( strings, " && ", builder );
-            builder.append( ")" );
-        }
-        else
-        {
-            builder.append( this.createRegexStringForContaining( valueVariable, "" ) );
-        }
-    }
-
-    private void processContainsPredicate( final ContainsSpecification<?> predicate, StringBuilder builder )
-    {
-        Object value = predicate.value();
-        String valueVariable = triples.addTriple( predicate.collectionProperty(), false ).value();
-        builder.append( this.createRegexStringForContaining(
-            valueVariable,
-            this.createAndEscapeJSONString( value )
-        ) );
-    }
-
-    private void processMatchesPredicate( final MatchesSpecification predicate, StringBuilder builder )
-    {
-        String valueVariable = triples.addTriple( predicate.property(), false ).value();
-        builder.append( format( "regex(%s,\"%s\")", valueVariable, predicate.regexp() ) );
-    }
-
-    private void processComparisonPredicate( final Specification<Composite> predicate,
-                                             boolean allowInline,
-                                             StringBuilder builder
-    )
-    {
-        if( predicate instanceof ComparisonSpecification )
-        {
-            ComparisonSpecification<?> comparisonSpecification = (ComparisonSpecification<?>) predicate;
-            Triples.Triple triple = triples.addTriple( (PropertyFunction) comparisonSpecification.property(), false );
-
-            // Don't use FILTER for equals-comparison. Do direct match instead
-            if( predicate instanceof EqSpecification && allowInline )
-            {
-                triple.setValue( "\"" + toString( comparisonSpecification.value() ) + "\"" );
-            }
-            else
-            {
-                String valueVariable = triple.value();
-                builder.append( String.format(
-                    "(%s %s \"%s\")",
-                    valueVariable,
-                    getOperator( comparisonSpecification.getClass() ),
-                    toString( comparisonSpecification.value() ) ) );
-            }
-        }
-        else
-        {
-            throw new UnsupportedOperationException( "Operator " + predicate.getClass()
-                .getName() + " is not supported" );
-        }
-    }
-
-    private void processNullPredicate( final PropertyNullSpecification<?> predicate, StringBuilder builder )
-    {
-        final String value = triples.addTriple( predicate.property(), true ).value();
-        builder.append( format( "(! bound(%s))", value ) );
-    }
-
-    private void processNotNullPredicate( final PropertyNotNullSpecification<?> predicate, StringBuilder builder )
-    {
-        final String value = triples.addTriple( predicate.property(), true ).value();
-        builder.append( format( "(bound(%s))", value ) );
-    }
-
-    private void processNullPredicate( final AssociationNullSpecification<?> predicate, StringBuilder builder )
-    {
-        final String value = triples.addTripleAssociation( predicate.association(), true ).value();
-        builder.append( format( "(! bound(%s))", value ) );
-    }
-
-    private void processNotNullPredicate( final AssociationNotNullSpecification<?> predicate, StringBuilder builder )
-    {
-        final String value = triples.addTripleAssociation( predicate.association(), true ).value();
-        builder.append( format( "(bound(%s))", value ) );
-    }
-
-    private void processManyAssociationContainsPredicate( ManyAssociationContainsSpecification<?> predicate,
-                                                          boolean allowInline, StringBuilder builder
-    )
-    {
-        Triples.Triple triple = triples.addTripleManyAssociation( predicate.manyAssociation(), false );
-
-        if( allowInline )
-        {
-            triple.setValue( "<" + toString( predicate.value() ) + ">" );
-        }
-        else
-        {
-            String valueVariable = triple.value();
-            builder.append( String.format( "(%s %s <%s>)", valueVariable, "=", toString( predicate.value() ) ) );
-        }
-    }
-
-    private void processOrderBy( OrderBy[] orderBySegments, StringBuilder builder )
-    {
-        if( orderBySegments != null && orderBySegments.length > 0 )
-        {
-            for( OrderBy orderBySegment : orderBySegments )
-            {
-                processOrderBy( builder, orderBySegment );
-            }
-        }
-    }
-
-    private void processOrderBy( StringBuilder builder, OrderBy orderBySegment )
-    {
-        if( orderBySegment != null )
-        {
-            final String valueVariable = triples.addTriple( orderBySegment.property(), false ).value();
-            if( orderBySegment.order() == OrderBy.Order.ASCENDING )
-            {
-                builder.append( format( "ASC(%s)", valueVariable ) );
-            }
-            else
-            {
-                builder.append( format( "DESC(%s)", valueVariable ) );
-            }
-        }
-    }
-
-    private String getOperator( final Class<? extends ComparisonSpecification> predicateClass )
-    {
-        String operator = OPERATORS.get( predicateClass );
-        if( operator == null )
-        {
-            throw new UnsupportedOperationException( "Predicate [" + predicateClass.getName() + "] is not supported" );
-        }
-        return operator;
-    }
-
-    private String toString( Object value )
-    {
-        if( value == null )
-        {
-            return null;
-        }
-
-        if( value instanceof Date )
-        {
-            return ISO8601_UTC.get().format( (Date) value );
-        }
-        else if( value instanceof EntityComposite )
-        {
-            return "urn:qi4j:entity:" + value.toString();
-        }
-        else if( value instanceof Variable )
-        {
-            Object realValue = variables.get( ( (Variable) value ).variableName() );
-
-            if( realValue == null )
-            {
-                throw new IllegalArgumentException( "Variable " + ( (Variable) value ).variableName() + " not bound" );
-            }
-
-            return toString( realValue );
-        }
-        else
-        {
-            return value.toString();
-        }
-    }
-}
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/internal/Triples.java b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/internal/Triples.java
deleted file mode 100644
index b738292..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/internal/Triples.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright 2008 Michael Hunger.
- *
- * Licensed  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.qi4j.index.rdf.query.internal;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.query.grammar.AssociationFunction;
-import org.qi4j.api.query.grammar.ManyAssociationFunction;
-import org.qi4j.api.query.grammar.PropertyFunction;
-import org.qi4j.api.util.Classes;
-
-import static java.lang.String.format;
-
-public class Triples
-    implements Iterable<Triples.Triple>
-{
-    private int valueCounter = 0;
-    private final List<Triple> triples = new ArrayList<>();
-    private final Namespaces namespaces;
-
-    public Triples( Namespaces namespaces )
-    {
-        this.namespaces = namespaces;
-    }
-
-    public void addDefaultTriples( String resultType )
-    {
-        triples.add(
-            new Triple(
-                "?entityType",
-                "rdfs:subClassOf",
-                "<" + Classes.toURI( resultType ) + ">",
-                false )
-        );
-        triples.add(
-            new Triple(
-                "?entity",
-                "rdf:type",
-                "?entityType",
-                false )
-        );
-        triples.add(
-            new Triple(
-                "?entity",
-                addNamespace( QualifiedName.fromClass( Identity.class, "identity" ).toNamespace() ) + ":identity",
-                "?identity",
-                false
-            )
-        );
-    }
-
-    private String addNamespace( String namespace )
-    {
-        return namespaces.addNamespace( namespace );
-    }
-
-    public Triple addTriple( final PropertyFunction<?> propertyFunction, boolean optional )
-    {
-        String subject = "?entity";
-        if( propertyFunction.traversedAssociation() != null )
-        {
-            subject = addTripleAssociation( propertyFunction.traversedAssociation(), false ).value;
-        }
-        else if( propertyFunction.traversedProperty() != null )
-        {
-            subject = addTriple( propertyFunction.traversedProperty(), false ).value;
-        }
-        QualifiedName qualifiedName = QualifiedName.fromAccessor( propertyFunction.accessor() );
-        String prefix = addNamespace( qualifiedName.toNamespace() );
-        return addTriple( subject, prefix + ":" + qualifiedName.name(), optional );
-    }
-
-    public Triple addTripleAssociation( AssociationFunction<?> associationReference, boolean optional )
-    {
-        String subject = "?entity";
-        if( associationReference.traversedAssociation() != null )
-        {
-            subject = addTripleAssociation( associationReference.traversedAssociation(), false ).value;
-        }
-        QualifiedName qualifiedName = QualifiedName.fromAccessor( associationReference.accessor() );
-        String prefix = addNamespace( qualifiedName.toNamespace() );
-        return addTriple( subject, prefix + ":" + qualifiedName.name(), optional );
-    }
-
-    public Triple addTripleManyAssociation( final ManyAssociationFunction<?> manyAssociationReference,
-                                            final boolean optional
-    )
-    {
-        AssociationFunction<?> traversedAssociation = manyAssociationReference.traversedAssociation();
-        String subject = "?entity";
-        if( traversedAssociation != null )
-        {
-            subject = addTripleAssociation( traversedAssociation, false ).value;
-        }
-        QualifiedName qualifiedName = QualifiedName.fromAccessor( manyAssociationReference.accessor() );
-        String predicatePrefix = addNamespace( qualifiedName.toNamespace() );
-        String predicate = predicatePrefix + ":" + qualifiedName.name();
-        Triple collectionTriple = addTriple( subject, predicate, optional );
-
-        String liSubject = collectionTriple.value;
-        return addTriple( liSubject, "rdf:li", false );
-    }
-
-    private Triple addTriple( final String subject,
-                              final String predicate,
-                              final boolean optional
-    )
-    {
-        Triple triple = getTriple( subject, predicate );
-        if( triple == null )
-        {
-            final String value = "?v" + valueCounter++;
-            triple = new Triple( subject, predicate, value, optional );
-            triples.add( triple );
-        }
-        if( !optional && triple.optional )
-        {
-            triple.optional = false;
-        }
-        return triple;
-    }
-
-    private Triple getTriple( final String subject,
-                              final String predicate
-    )
-    {
-        for( Triple triple : triples )
-        {
-            if( triple.subject.equals( subject )
-                && triple.predicate.equals( predicate ) )
-            {
-                return triple;
-            }
-        }
-        return null;
-    }
-
-    public boolean hasTriples()
-    {
-        return !triples.isEmpty();
-    }
-
-    @Override
-    public Iterator<Triple> iterator()
-    {
-        return triples.iterator();
-    }
-
-    public String toSparql()
-    {
-        StringBuilder sparql = new StringBuilder();
-        for( Triple triple : triples )
-        {
-            sparql.append( triple.toSparql() );
-        }
-        return sparql.toString();
-    }
-
-    public static class Triple
-    {
-        private final String subject;
-        private final String predicate;
-        private String value;
-        private boolean optional;
-
-        private Triple( final String subject,
-                        final String predicate,
-                        final String value,
-                        final boolean optional
-        )
-        {
-            this.subject = subject;
-            this.predicate = predicate;
-            this.value = value;
-            this.optional = optional;
-        }
-
-        @Override
-        public boolean equals( Object otherObject )
-        {
-            if( this == otherObject )
-            {
-                return true;
-            }
-            if( otherObject == null || getClass() != otherObject.getClass() )
-            {
-                return false;
-            }
-
-            Triple other = (Triple) otherObject;
-
-            if( predicate != null ? !predicate.equals( other.predicate ) : other.predicate != null )
-            {
-                return false;
-            }
-            if( subject != null ? !subject.equals( other.subject ) : other.subject != null )
-            {
-                return false;
-            }
-            if( value != null )
-            {
-                return value.equals( other.value );
-            }
-            else
-            {
-                return other.value == null;
-            }
-        }
-
-        @Override
-        public int hashCode()
-        {
-            int result;
-            result = ( subject != null ? subject.hashCode() : 0 );
-            result = 31 * result + ( predicate != null ? predicate.hashCode() : 0 );
-            result = 31 * result + ( value != null ? value.hashCode() : 0 );
-            return result;
-        }
-
-        @Override
-        public String toString()
-        {
-            return toSparql();
-        }
-
-        public String toSparql()
-        {
-
-            if( optional )
-            {
-                return format( "OPTIONAL {%s %s %s}.", subject, predicate, value );
-            }
-            return format( "%s %s %s.", subject, predicate, value );
-        }
-
-        public String subject()
-        {
-            return subject;
-        }
-
-        public String predicate()
-        {
-            return predicate;
-        }
-
-        public String value()
-        {
-            return value;
-        }
-
-        public void setValue( String value )
-        {
-            this.value = value;
-        }
-
-        public boolean isOptional()
-        {
-            return optional;
-        }
-    }
-
-    @Override
-    public String toString()
-    {
-        return triples.toString();
-    }
-}
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/internal/package.html b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/internal/package.html
deleted file mode 100644
index c1772a4..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/internal/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>RDF Query Internal Package.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/package.html b/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/package.html
deleted file mode 100644
index d0e38e8..0000000
--- a/extensions/indexing-rdf/src/main/java/org/qi4j/index/rdf/query/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>RDF Query.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/ContainsAllTest.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/ContainsAllTest.java
new file mode 100644
index 0000000..3d7fb36
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/ContainsAllTest.java
@@ -0,0 +1,347 @@
+/*
+ *  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.polygene.index.rdf;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryExpressions;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.rdf.assembly.RdfNativeSesameStoreAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.library.rdf.repository.NativeConfiguration;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+// A test to verify that containsAll QueryExpression works properly.
+public class ContainsAllTest
+    extends AbstractPolygeneTest
+{
+    @Rule
+    public TemporaryFolder tmpDir = new TemporaryFolder();
+
+    public static final String TEST_STRING_1 = "TestString1";
+    public static final String TEST_STRING_2 = "Some\\Weird\"$String/[]";
+    public static final String TEST_STRING_3 = "TestString3";
+    public static final String TEST_STRING_4 = "TestSTring4";
+
+    public interface ExampleValue2
+        extends ValueComposite
+    {
+        Property<String> stringProperty();
+    }
+
+    public interface ExampleValue
+        extends ValueComposite
+    {
+        Property<ExampleValue2> valueProperty();
+    }
+
+    public interface ExampleEntity
+        extends EntityComposite
+    {
+        Property<Set<String>> strings();
+
+        Property<Set<ExampleValue>> complexValue();
+    }
+
+    // This test creates a one-layer, two-module application, with one module
+    // being testing module, and another for retrieving configuration for
+    // services from preferences. This test assumes that those configurations
+    // already exist in preference ES.
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+        ModuleAssembly prefModule = module.layer().module( "PrefModule" );
+        prefModule.entities( NativeConfiguration.class ).visibleIn( Visibility.application );
+        prefModule.forMixin( NativeConfiguration.class ).declareDefaults()
+                  .dataDirectory().set( new File( tmpDir.getRoot(), "rdf-data" ).getAbsolutePath() );
+        new EntityTestAssembler().assemble( prefModule );
+
+        module.entities( ExampleEntity.class );
+        module.values( ExampleValue.class, ExampleValue2.class );
+
+        EntityTestAssembler testAss = new EntityTestAssembler();
+        testAss.assemble( module );
+
+        RdfNativeSesameStoreAssembler rdfAssembler = new RdfNativeSesameStoreAssembler();
+        rdfAssembler.assemble( module );
+    }
+
+    public static ExampleEntity createEntityWithStrings( UnitOfWork uow, ValueBuilderFactory vbf, String... strings )
+    {
+        EntityBuilder<ExampleEntity> builder = uow.newEntityBuilder( ExampleEntity.class );
+
+        populateStrings( builder.instance(), strings );
+        populateComplexValue( builder.instance(), vbf );
+
+        return builder.newInstance();
+    }
+
+    public static ExampleEntity createEntityWithComplexValues( UnitOfWork uow,
+                                                               ValueBuilderFactory vbf,
+                                                               String... valueStrings
+    )
+    {
+        EntityBuilder<ExampleEntity> builder = uow.newEntityBuilder( ExampleEntity.class );
+
+        populateStrings( builder.instance() );
+        populateComplexValue( builder.instance(), vbf, valueStrings );
+
+        return builder.newInstance();
+    }
+
+    private static void populateStrings( ExampleEntity proto, String... strings )
+    {
+        proto.strings().set( setOf( strings ) );
+    }
+
+    private static void populateComplexValue( ExampleEntity proto, ValueBuilderFactory vbf, String... valueStrings )
+    {
+        Set<ExampleValue> values = new HashSet<>();
+        for( String value : valueStrings )
+        {
+            ValueBuilder<ExampleValue2> vBuilder = vbf.newValueBuilder( ExampleValue2.class );
+            vBuilder.prototype().stringProperty().set( value );
+
+            ValueBuilder<ExampleValue> vBuilder2 = vbf.newValueBuilder( ExampleValue.class );
+            vBuilder2.prototype().valueProperty().set( vBuilder.newInstance() );
+            values.add( vBuilder2.newInstance() );
+        }
+
+        proto.complexValue().set( values );
+    }
+
+    @Test
+    public void simpleContainsAllQuerySuccessTest()
+        throws Exception
+    {
+        ExampleEntity result = this.performContainsAllStringsTest(
+            setOf( TEST_STRING_1, TEST_STRING_2, TEST_STRING_3 ),
+            setOf( TEST_STRING_1, TEST_STRING_2 )
+        );
+
+        Assert.assertTrue( "The entity must have been found.", result != null );
+    }
+
+    @Test
+    public void fullContainsAllQuerySuccessTest()
+        throws Exception
+    {
+        ExampleEntity result = this.performContainsAllStringsTest(
+            setOf( TEST_STRING_1, TEST_STRING_2, TEST_STRING_3 ),
+            setOf( TEST_STRING_1, TEST_STRING_2, TEST_STRING_3 )
+        );
+
+        Assert.assertTrue( "The entity must have been found.", result != null );
+    }
+
+    @Test
+    public void simpleContainsAllQueryFailTest()
+        throws Exception
+    {
+        ExampleEntity result = this.performContainsAllStringsTest(
+            setOf( TEST_STRING_1, TEST_STRING_2, TEST_STRING_3 ),
+            setOf( TEST_STRING_1, TEST_STRING_2, TEST_STRING_3, TEST_STRING_4 )
+        );
+
+        Assert.assertTrue( "The entity must not have been found.", result == null );
+    }
+
+    @Test
+    public void simpleContainsAllQueryWithNullsTest()
+        throws Exception
+    {
+        ExampleEntity result = this.performContainsAllStringsTest(
+            setOf( TEST_STRING_1, TEST_STRING_2, TEST_STRING_3 ),
+            setOf( TEST_STRING_1, null, TEST_STRING_2 )
+        );
+
+        Assert.assertTrue( "The entity must have been found.", result != null );
+    }
+
+    @Test
+    public void emptyContainsAllQueryTest()
+        throws Exception
+    {
+        ExampleEntity result = this.performContainsAllStringsTest(
+            setOf( TEST_STRING_1, TEST_STRING_2 ),
+            setOf()
+        );
+
+        Assert.assertTrue( "The entity must have been found.", result != null );
+    }
+
+    @Test
+    public void complexContainsAllSuccessTest()
+        throws Exception
+    {
+        ExampleEntity result = this.performContainsAllStringValueTest(
+            setOf( TEST_STRING_1, TEST_STRING_2 ),
+            setOf( TEST_STRING_1 )
+        );
+
+        Assert.assertTrue( "The entity must have been found.", result != null );
+    }
+
+    @Test
+    public void fullComplexContainsAllSuccessTest()
+        throws Exception
+    {
+        ExampleEntity result = this.performContainsAllStringValueTest(
+            setOf( TEST_STRING_1, TEST_STRING_2 ),
+            setOf( TEST_STRING_1, TEST_STRING_2 )
+        );
+
+        Assert.assertTrue( "The entity must have been found", result != null );
+    }
+
+    @Test
+    public void complexContainsAllFailTest()
+        throws Exception
+    {
+        ExampleEntity result = this.performContainsAllStringValueTest(
+            setOf( TEST_STRING_1, TEST_STRING_2 ),
+            setOf( TEST_STRING_1, TEST_STRING_2, TEST_STRING_3 )
+        );
+
+        Assert.assertTrue( "The entity must not have been found.", result == null );
+    }
+
+    @Test
+    public void complexEmptyContainsAllTest()
+        throws Exception
+    {
+        ExampleEntity result = this.performContainsAllStringValueTest(
+            setOf( TEST_STRING_1, TEST_STRING_2 ),
+            setOf()
+        );
+
+        Assert.assertTrue( "The entity must have been found.", result != null );
+    }
+
+    private ExampleEntity findEntity( String... strings )
+    {
+        QueryBuilder<ExampleEntity> builder = this.queryBuilderFactory.newQueryBuilder( ExampleEntity.class );
+
+        builder = builder.where( QueryExpressions.containsAll(
+            QueryExpressions.templateFor( ExampleEntity.class ).strings(),
+            Arrays.asList( strings ) ) );
+        return this.unitOfWorkFactory.currentUnitOfWork().newQuery( builder ).find();
+    }
+
+    private ExampleEntity findEntityBasedOnValueStrings( String... valueStrings )
+    {
+        Set<ExampleValue> values = new HashSet<ExampleValue>();
+        for( String value : valueStrings )
+        {
+            ValueBuilder<ExampleValue2> vBuilder = this.valueBuilderFactory.newValueBuilder( ExampleValue2.class );
+            vBuilder.prototype().stringProperty().set( value );
+
+            ValueBuilder<ExampleValue> vBuilder2 = this.valueBuilderFactory.newValueBuilder( ExampleValue.class );
+            vBuilder2.prototype().valueProperty().set( vBuilder.newInstance() );
+            values.add( vBuilder2.newInstance() );
+        }
+
+        return this.createComplexQuery( values ).find();
+    }
+
+    private Query<ExampleEntity> createComplexQuery( Set<ExampleValue> valuez )
+    {
+        QueryBuilder<ExampleEntity> builder = this.queryBuilderFactory.newQueryBuilder( ExampleEntity.class );
+        builder = builder.where( QueryExpressions.containsAll(
+            QueryExpressions.templateFor( ExampleEntity.class ).complexValue(),
+            valuez
+                                 )
+        );
+
+        return this.unitOfWorkFactory.currentUnitOfWork().newQuery( builder );
+    }
+
+    private ExampleEntity performContainsAllStringsTest( Set<String> entityStrings, Set<String> queryableStrings )
+        throws Exception
+    {
+        UnitOfWork creatingUOW = this.unitOfWorkFactory.newUnitOfWork();
+        String[] entityStringsArray = new String[ entityStrings.size() ];
+        createEntityWithStrings( creatingUOW, this.valueBuilderFactory, entityStrings.toArray( entityStringsArray ) );
+        creatingUOW.complete();
+
+        UnitOfWork queryingUOW = this.unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            String[] queryableStringsArray = new String[ queryableStrings.size() ];
+            ExampleEntity entity = this.findEntity( queryableStrings.toArray( queryableStringsArray ) );
+            return entity;
+        }
+        finally
+        {
+            queryingUOW.discard();
+        }
+    }
+
+    private ExampleEntity performContainsAllStringValueTest( Set<String> entityStrings, Set<String> queryableStrings )
+        throws Exception
+    {
+        UnitOfWork creatingUOW = this.unitOfWorkFactory.newUnitOfWork();
+        String[] entityStringsArray = new String[ entityStrings.size() ];
+        createEntityWithComplexValues( creatingUOW, this.valueBuilderFactory,
+                                       entityStrings.toArray( entityStringsArray ) );
+        creatingUOW.complete();
+
+        UnitOfWork queryingUOW = this.unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            String[] queryableStringsArray = new String[ queryableStrings.size() ];
+            ExampleEntity entity = this.findEntityBasedOnValueStrings(
+                queryableStrings.toArray( queryableStringsArray ) );
+            return entity;
+        }
+        finally
+        {
+            queryingUOW.discard();
+        }
+    }
+
+    static <T> Set<T> setOf( T... elements )
+    {
+        return new HashSet<T>( Arrays.asList( elements ) );
+    }
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/ContainsTest.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/ContainsTest.java
new file mode 100644
index 0000000..cf33cca
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/ContainsTest.java
@@ -0,0 +1,200 @@
+/*
+ *  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.polygene.index.rdf;
+
+import java.io.File;
+import java.util.Set;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryExpressions;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.rdf.ContainsAllTest.ExampleEntity;
+import org.apache.polygene.index.rdf.ContainsAllTest.ExampleValue;
+import org.apache.polygene.index.rdf.ContainsAllTest.ExampleValue2;
+import org.apache.polygene.index.rdf.assembly.RdfNativeSesameStoreAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.library.rdf.repository.NativeConfiguration;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import static org.apache.polygene.index.rdf.ContainsAllTest.TEST_STRING_1;
+import static org.apache.polygene.index.rdf.ContainsAllTest.TEST_STRING_2;
+import static org.apache.polygene.index.rdf.ContainsAllTest.TEST_STRING_3;
+import static org.apache.polygene.index.rdf.ContainsAllTest.TEST_STRING_4;
+import static org.apache.polygene.index.rdf.ContainsAllTest.setOf;
+
+public class ContainsTest extends AbstractPolygeneTest
+{
+    @Rule
+    public TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    public void assemble( ModuleAssembly module ) throws AssemblyException
+    {
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+        ModuleAssembly prefModule = module.layer().module( "PrefModule" );
+        prefModule.entities( NativeConfiguration.class ).visibleIn( Visibility.application );
+        prefModule.forMixin( NativeConfiguration.class ).declareDefaults()
+                  .dataDirectory().set( new File( tmpDir.getRoot(), "rdf-data" ).getAbsolutePath() );
+        new EntityTestAssembler().assemble( prefModule );
+
+        module.entities( ExampleEntity.class );
+        module.values( ExampleValue.class, ExampleValue2.class );
+
+        EntityTestAssembler testAss = new EntityTestAssembler();
+        testAss.assemble( module );
+
+        RdfNativeSesameStoreAssembler rdfAssembler = new RdfNativeSesameStoreAssembler();
+        rdfAssembler.assemble( module );
+    }
+
+    @Test
+    public void simpleContainsSuccessTest() throws Exception
+    {
+        ExampleEntity result = this.performContainsStringTest(
+            setOf( TEST_STRING_1, TEST_STRING_2, TEST_STRING_3 ),
+            TEST_STRING_3
+        );
+
+        Assert.assertTrue( "The entity must have been found", result != null );
+    }
+
+    @Test
+    public void simpleContainsSuccessFailTest() throws Exception
+    {
+        ExampleEntity result = this.performContainsStringTest(
+            setOf( TEST_STRING_1, TEST_STRING_2, TEST_STRING_3 ),
+            TEST_STRING_4
+        );
+
+        Assert.assertTrue( "The entity must not have been found", result == null );
+    }
+
+    @Test( expected = NullPointerException.class )
+    public void simpleContainsNullTest() throws Exception
+    {
+        this.performContainsStringTest(
+            setOf( TEST_STRING_1, TEST_STRING_2, TEST_STRING_3 ),
+            null
+        );
+    }
+
+    @Test
+    public void simpleContainsStringValueSuccessTest() throws Exception
+    {
+        ExampleEntity result = this.performContainsStringValueTest(
+            setOf( TEST_STRING_1, TEST_STRING_2, TEST_STRING_3 ),
+            TEST_STRING_3
+        );
+
+        Assert.assertTrue( "The entity must have been found", result != null );
+    }
+
+    @Test
+    public void simpleContainsStringValueFailTest() throws Exception
+    {
+        ExampleEntity result = this.performContainsStringTest(
+            setOf( TEST_STRING_1, TEST_STRING_2, TEST_STRING_3 ),
+            TEST_STRING_4
+        );
+
+        Assert.assertTrue( "The entity must not have been found", result == null );
+    }
+
+    private ExampleEntity findEntity( String string )
+    {
+        QueryBuilder<ExampleEntity> builder = this.queryBuilderFactory.newQueryBuilder( ExampleEntity.class );
+
+        builder = builder.where(
+            QueryExpressions.contains( QueryExpressions.templateFor( ExampleEntity.class ).strings(), string ) );
+        return this.unitOfWorkFactory.currentUnitOfWork().newQuery( builder ).find();
+    }
+
+    private ExampleEntity findEntityBasedOnValueString( String valueString )
+    {
+        ValueBuilder<ExampleValue2> vBuilder = this.valueBuilderFactory.newValueBuilder( ExampleValue2.class );
+        vBuilder.prototype().stringProperty().set( valueString );
+
+        ValueBuilder<ExampleValue> vBuilder2 = this.valueBuilderFactory.newValueBuilder( ExampleValue.class );
+        vBuilder2.prototype().valueProperty().set( vBuilder.newInstance() );
+
+        return this.createComplexQuery( vBuilder2.newInstance() ).find();
+    }
+
+    private Query<ExampleEntity> createComplexQuery( ExampleValue value )
+    {
+        QueryBuilder<ExampleEntity> builder = this.queryBuilderFactory.newQueryBuilder( ExampleEntity.class );
+        builder = builder.where(
+            QueryExpressions.contains( QueryExpressions.templateFor( ExampleEntity.class ).complexValue(), value ) );
+
+        return this.unitOfWorkFactory.currentUnitOfWork().newQuery( builder );
+    }
+
+    private ExampleEntity performContainsStringTest( Set<String> entityStrings, String queryableString )
+        throws Exception
+    {
+        UnitOfWork creatingUOW = this.unitOfWorkFactory.newUnitOfWork();
+        String[] entityStringsArray = new String[ entityStrings.size() ];
+        ContainsAllTest.createEntityWithStrings( creatingUOW, this.valueBuilderFactory,
+                                                 entityStrings.toArray( entityStringsArray ) );
+        creatingUOW.complete();
+
+        UnitOfWork queryingUOW = this.unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            return this.findEntity( queryableString );
+        }
+        finally
+        {
+            queryingUOW.discard();
+        }
+    }
+
+    private ExampleEntity performContainsStringValueTest( Set<String> entityStrings, String queryableString )
+        throws Exception
+    {
+        UnitOfWork creatingUOW = this.unitOfWorkFactory.newUnitOfWork();
+        String[] entityStringsArray = new String[ entityStrings.size() ];
+        ContainsAllTest.createEntityWithComplexValues( creatingUOW, this.valueBuilderFactory,
+                                                       entityStrings.toArray( entityStringsArray ) );
+        creatingUOW.complete();
+
+        UnitOfWork queryingUOW = this.unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            return this.findEntityBasedOnValueString( queryableString );
+        }
+        finally
+        {
+            queryingUOW.discard();
+        }
+    }
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/DocumentationSupport.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/DocumentationSupport.java
new file mode 100644
index 0000000..94122ea
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/DocumentationSupport.java
@@ -0,0 +1,77 @@
+/*
+ *  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.polygene.index.rdf;
+
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.rdf.assembly.RdfMemoryStoreAssembler;
+import org.apache.polygene.index.rdf.assembly.RdfNativeSesameStoreAssembler;
+import org.apache.polygene.index.rdf.assembly.RdfRdbmsSesameStoreAssembler;
+
+public class DocumentationSupport
+{
+
+    class InMemoryAssembler
+            implements Assembler
+    {
+
+        @Override
+        public void assemble( ModuleAssembly module )
+                throws AssemblyException
+        {
+            // START SNIPPET: memory
+            new RdfMemoryStoreAssembler().assemble( module );
+            // END SNIPPET: memory
+        }
+
+    }
+
+    class NativeMemoryAssembler
+            implements Assembler
+    {
+
+        @Override
+        public void assemble( ModuleAssembly module )
+                throws AssemblyException
+        {
+            // START SNIPPET: native
+            new RdfNativeSesameStoreAssembler().assemble( module );
+            // END SNIPPET: native
+        }
+
+    }
+
+    class RDBMSMemoryAssembler
+            implements Assembler
+    {
+
+        @Override
+        public void assemble( ModuleAssembly module )
+                throws AssemblyException
+        {
+            // START SNIPPET: rdbms
+            new RdfRdbmsSesameStoreAssembler().assemble( module );
+            // END SNIPPET: rdbms
+        }
+
+    }
+
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/MultiLayeredTest.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/MultiLayeredTest.java
new file mode 100644
index 0000000..6230b92
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/MultiLayeredTest.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.index.rdf;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.index.rdf.assembly.RdfMemoryStoreAssembler;
+import org.apache.polygene.test.indexing.layered.AbstractMultiLayeredIndexingTest;
+import org.junit.Ignore;
+
+@Ignore("Disabled until the new Query sturcture is in place, properly supporting multilayered applications.")
+public class MultiLayeredTest extends AbstractMultiLayeredIndexingTest
+{
+    public MultiLayeredTest()
+    {
+        super( IndexingModuleAssembler.class );
+    }
+
+    static class IndexingModuleAssembler
+        implements ModuleAssembler
+    {
+        @Override
+        public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+            throws AssemblyException
+        {
+            new RdfMemoryStoreAssembler( Visibility.application, Visibility.module ).assemble( module );
+            return module;
+        }
+    }
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RDFPerformanceTest.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RDFPerformanceTest.java
new file mode 100644
index 0000000..014d8fb
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RDFPerformanceTest.java
@@ -0,0 +1,265 @@
+/*
+ *  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.polygene.index.rdf;
+
+/**
+ * JAVADOC
+ */
+
+import java.io.File;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryExpressions;
+import org.apache.polygene.api.time.SystemTime;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.rdf.assembly.RdfNativeSesameStoreAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.library.rdf.repository.NativeConfiguration;
+import org.apache.polygene.spi.query.IndexExporter;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RDFPerformanceTest extends AbstractPolygeneTest
+{
+    private static final Logger LOG = LoggerFactory.getLogger( RDFPerformanceTest.class );
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    public interface ExampleEntity extends EntityComposite
+    {
+        @UseDefaults
+        Property<String> someProperty();
+
+        ManyAssociation<ExampleEntity> manyAssoc();
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module ) throws AssemblyException
+    {
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+        ModuleAssembly prefModule = module.layer().module( "PrefModule" );
+        prefModule.entities( NativeConfiguration.class ).visibleIn( Visibility.application );
+        prefModule.forMixin( NativeConfiguration.class ).declareDefaults()
+                  .tripleIndexes().set( "spoc,cspo" );
+        prefModule.forMixin( NativeConfiguration.class ).declareDefaults()
+                  .dataDirectory().set( new File( tmpDir.getRoot(), "rdf-data" ).getAbsolutePath() );
+        new EntityTestAssembler().assemble( prefModule );
+
+        module.entities( ExampleEntity.class );
+
+        EntityTestAssembler testAss = new EntityTestAssembler();
+        testAss.assemble( module );
+
+        Assembler rdfAssembler = new RdfNativeSesameStoreAssembler();
+        rdfAssembler.assemble( module );
+    }
+
+
+    private List<ExampleEntity> doCreate( int howMany )
+    {
+        List<ExampleEntity> result = new ArrayList<ExampleEntity>( howMany );
+
+        List<ExampleEntity> entities = new ArrayList<ExampleEntity>();
+        for (Integer x = 0; x < howMany; ++x)
+        {
+            ExampleEntity exampleEntity = this.unitOfWorkFactory.currentUnitOfWork().newEntity( ExampleEntity.class, new StringIdentity( "entity" + x ) );
+
+            for (ExampleEntity entity : entities)
+            {
+                exampleEntity.manyAssoc().add( entity );
+            }
+
+            entities.add( exampleEntity );
+            if (entities.size() > 10)
+                entities.remove( 0 );
+
+            result.add( exampleEntity );
+        }
+
+        return result;
+    }
+
+    private void doRemoveAll( List<ExampleEntity> entities )
+    {
+        for (ExampleEntity entity : entities)
+        {
+            this.unitOfWorkFactory.currentUnitOfWork().remove( this.unitOfWorkFactory.currentUnitOfWork().get( entity ) );
+        }
+    }
+
+    private List<ExampleEntity> doList( int howMany )
+    {
+        List<ExampleEntity> list = new ArrayList<ExampleEntity>();
+        UnitOfWork uow = this.unitOfWorkFactory.newUnitOfWork();
+        Iterator<ExampleEntity> iter = uow.newQuery( this.queryBuilderFactory.newQueryBuilder( ExampleEntity.class ) ).iterator();
+        int found = 0;
+        while (iter.hasNext())
+        {
+            found++;
+            ExampleEntity exampleEntity = iter.next();
+            if (exampleEntity != null)
+                list.add( exampleEntity );
+        }
+
+        uow.discard();
+
+        if (found != howMany)
+        {
+            LOG.warn( "Found " + found + " entities instead of " + howMany + "." );
+        }
+
+        return list;
+    }
+
+
+    private void doRemove( int howMany )
+    {
+        Iterator<ExampleEntity> iter = this.unitOfWorkFactory.currentUnitOfWork().newQuery( this.queryBuilderFactory.newQueryBuilder( ExampleEntity.class )).maxResults( howMany ).iterator();
+        Integer removed = 0;
+        while (iter.hasNext())
+        {
+            this.unitOfWorkFactory.currentUnitOfWork().remove( iter.next() );
+            ++removed;
+        }
+
+        if (removed != howMany)
+        {
+            LOG.warn( "Removed " + removed + " entities instead of " + howMany + "." );
+        }
+    }
+
+    private void performTest( int howMany ) throws Exception
+    {
+        Instant startTest = SystemTime.now();
+
+        UnitOfWork creatingUOW = this.unitOfWorkFactory.newUnitOfWork();
+        Instant startingTime = SystemTime.now();
+        List<ExampleEntity> entities = this.doCreate( howMany );
+        LOG.info( "Time to create " + howMany + " entities: " + Duration.between(startingTime, SystemTime.now() ) );
+
+        startingTime = SystemTime.now();
+        creatingUOW.complete();
+        LOG.info( "Time to complete creation uow: " + Duration.between(startingTime, SystemTime.now() ) );
+
+
+        List<ExampleEntity> entityList = this.doList( howMany );
+
+        startingTime = SystemTime.now();
+        UnitOfWork uow = this.unitOfWorkFactory.newUnitOfWork();
+        for (int i = 0; i < 1000; i++)
+        {
+            ExampleEntity entity50 = uow.get(ExampleEntity.class, new StringIdentity( "entity50" ) );
+            Query<ExampleEntity> query = uow.newQuery( this.queryBuilderFactory.newQueryBuilder( ExampleEntity.class ).
+                    where( QueryExpressions.contains( QueryExpressions.templateFor( ExampleEntity.class ).manyAssoc(), entity50) ));
+            System.out.println(query.count());
+        }
+
+        Instant endTest = SystemTime.now();
+        LOG.info( "Time to query " + howMany + " entities: " + Duration.between(startTest, endTest) );
+
+        UnitOfWork deletingUOW = this.unitOfWorkFactory.newUnitOfWork();
+        startingTime = SystemTime.now();
+        this.doRemoveAll( entityList );
+//      this.doRemove(200);
+        LOG.info( "Time to delete " + howMany + " entities: " + Duration.between(startingTime, SystemTime.now() ) );
+
+        startingTime = SystemTime.now();
+        deletingUOW.complete();
+
+        endTest = SystemTime.now();
+        LOG.info( "time to complete deletion uow: " + Duration.between(startingTime, endTest ) );
+        LOG.info( "time to complete test: " + Duration.between(startingTime, endTest ) );
+
+    }
+
+    @Test
+    public void dummy()
+    {
+        // Dummy test to make Maven happy
+    }
+
+    // @Test
+    public void performanceTest200() throws Exception
+    {
+        this.performTest( 200 );
+        this.performTest( 200 );
+        this.performTest( 200 );
+        this.performTest( 200 );
+        this.performTest( 200 );
+        this.performTest( 200 );
+        this.performTest( 200 );
+        this.performTest( 200 );
+
+        IndexExporter indexerExporter =
+                serviceFinder.findService( IndexExporter.class ).get();
+        indexerExporter.exportReadableToStream( System.out );
+    }
+
+    @Ignore
+    @Test
+    public void performanceTest1000() throws Exception
+    {
+        this.performTest( 1000 );
+    }
+
+    @Ignore
+    @Test
+    public void performanceTest5000() throws Exception
+    {
+        this.performTest( 5000 );
+    }
+
+    @Ignore
+    @Test
+    public void performanceTest10000() throws Exception
+    {
+        this.performTest( 10000 );
+    }
+
+    @Ignore
+    @Test
+    public void performanceTest100000() throws Exception
+    {
+        this.performTest( 100000 );
+    }
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfComplexQueryTest.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfComplexQueryTest.java
new file mode 100644
index 0000000..31c2d3c
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfComplexQueryTest.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.index.rdf;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.rdf.entity.EntityStateSerializer;
+import org.apache.polygene.library.rdf.entity.EntityTypeSerializer;
+import org.apache.polygene.library.rdf.repository.MemoryRepositoryService;
+import org.apache.polygene.test.indexing.AbstractComplexQueryTest;
+import org.junit.Ignore;
+
+@Ignore( "RDF Index/Query do not support Complex Queries, ie. queries by 'example values'" )
+public class RdfComplexQueryTest
+        extends AbstractComplexQueryTest
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+            throws AssemblyException
+    {
+        super.assemble( module );
+        module.services( RdfIndexingEngineService.class ).instantiateOnStartup();
+        module.objects( EntityStateSerializer.class, EntityTypeSerializer.class );
+        module.services( MemoryRepositoryService.class ).identifiedBy( "rdf-indexing" ).instantiateOnStartup();
+    }
+
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfEntityFinderTest.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfEntityFinderTest.java
new file mode 100644
index 0000000..86723ce
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfEntityFinderTest.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.index.rdf;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.rdf.entity.EntityStateSerializer;
+import org.apache.polygene.library.rdf.entity.EntityTypeSerializer;
+import org.apache.polygene.library.rdf.repository.MemoryRepositoryService;
+import org.apache.polygene.test.indexing.AbstractEntityFinderTest;
+
+public class RdfEntityFinderTest extends AbstractEntityFinderTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+        module.objects( EntityStateSerializer.class, EntityTypeSerializer.class );
+        module.services( RdfIndexingEngineService.class ).instantiateOnStartup();
+        module.services( MemoryRepositoryService.class ).identifiedBy( "rdf-indexing" ).instantiateOnStartup();
+        // module.services( NativeRdfRepositoryService.class ).identifiedBy( "rdf-indexing" );
+        // module.addComposites( NativeRdfConfiguration.class );
+    }
+}
\ No newline at end of file
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryMultimoduleTest.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryMultimoduleTest.java
new file mode 100644
index 0000000..23c8f13
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryMultimoduleTest.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.polygene.index.rdf;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.apache.polygene.index.rdf.assembly.RdfMemoryStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+
+public class RdfNamedQueryMultimoduleTest
+    extends RdfNamedQueryTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        LayerAssembly layer = module.layer();
+        assembleEntities( module, Visibility.module );
+        assembleValues( module, Visibility.module );
+
+        ModuleAssembly storeModule = layer.module( "store" );
+        new DefaultUnitOfWorkAssembler().assemble( storeModule );
+        new EntityTestAssembler().visibleIn( Visibility.layer ).assemble( storeModule );
+        assembleValues( storeModule, Visibility.module );
+
+        ModuleAssembly indexModule = layer.module( "index" );
+        new DefaultUnitOfWorkAssembler().assemble( indexModule );
+        new RdfMemoryStoreAssembler( Visibility.layer, Visibility.module ).assemble( indexModule );
+    }
+
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
new file mode 100644
index 0000000..40591fa
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfNamedQueryTest.java
@@ -0,0 +1,293 @@
+/*
+ *  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.polygene.index.rdf;
+
+import java.util.function.Predicate;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.rdf.assembly.RdfMemoryStoreAssembler;
+import org.apache.polygene.index.rdf.query.SesameExpressions;
+import org.apache.polygene.test.indexing.AbstractNamedQueryTest;
+
+public class RdfNamedQueryTest extends AbstractNamedQueryTest
+{
+    @Override
+    protected String[] queryStrings()
+    {
+        return queryStrings;
+    }
+
+    @Override
+    protected Predicate<Composite> createNamedQueryDescriptor( String queryName, String queryString )
+    {
+        return SesameExpressions.sparql( queryString );
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+        new RdfMemoryStoreAssembler( Visibility.module, Visibility.module ).assemble( module );
+    }
+
+    private static String[] queryStrings =
+    {
+// START SNIPPET: query1
+        "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Person>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n" + "\n" + "}", // script01
+// END SNIPPET: query1
+
+// START SNIPPET: query2
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Nameable#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Domain>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n" + "?entity ns1:name ?v0. \n"
+            + "FILTER (?v0 = \"Gaming\")\n" + "}", // script02
+// END SNIPPET: query2
+
+// START SNIPPET: query3
+        "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Nameable>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n" + "\n" + "}", // script03
+// END SNIPPET: query3
+
+// START SNIPPET: query4
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Person#> \n"
+            + "PREFIX ns2: <urn:polygene:type:org.apache.polygene.test.model.Nameable#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Person>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n"
+            + "?entity ns1:placeOfBirth ?v0. \n" + "?v0 ns2:name ?v1. \n" + "FILTER (?v1 = \"Kuala Lumpur\")\n" + "}", // script04
+// END SNIPPET: query4
+
+// START SNIPPET: query5
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Person#> \n"
+            + "PREFIX ns2: <urn:polygene:type:org.apache.polygene.test.model.Nameable#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Person>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n" + "?entity ns1:mother ?v0. \n"
+            + "?v0 ns1:placeOfBirth ?v1. \n" + "?v1 ns2:name ?v2. \n" + "FILTER (?v2 = \"Kuala Lumpur\")\n" + "}", // script05
+// END SNIPPET: query5
+
+// START SNIPPET: query6
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Person#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Person>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n"
+            + "?entity ns1:yearOfBirth ?v0. \n" + "FILTER (?v0 >= \"1973\")\n" + "}", // script06
+// END SNIPPET: query6
+
+// START SNIPPET: query7
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Person#> \n"
+            + "PREFIX ns2: <urn:polygene:type:org.apache.polygene.test.model.Nameable#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Nameable>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n"
+            + "?entity ns1:yearOfBirth ?v0. \n" + "?entity ns1:placeOfBirth ?v1. \n" + "?v1 ns2:name ?v2. \n"
+            + "FILTER ((?v0 >= \"1900\") && (?v2 = \"Penang\"))\n" + "}", // script07
+// END SNIPPET: query7
+
+// START SNIPPET: query8
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Person#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Person>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n"
+            + "?entity ns1:yearOfBirth ?v0. \n" + "FILTER ((?v0 = \"1970\") || (?v0 = \"1975\"))\n" + "}", // script08
+// END SNIPPET: query8
+
+// START SNIPPET: query9
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Person#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Female>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n"
+            + "?entity ns1:yearOfBirth ?v0. \n" + "FILTER ((?v0 = \"1970\") || (?v0 = \"1975\"))\n" + "}", // script09
+// END SNIPPET: query9
+
+// START SNIPPET: query10
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Person#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Person>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n"
+            + "?entity ns1:yearOfBirth ?v0. \n" + "FILTER (!(?v0 = \"1975\"))\n" + "}", // script10
+// END SNIPPET: query10
+
+// START SNIPPET: query11
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Person#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Person>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n"
+            + "OPTIONAL {?entity ns1:email ?v0}. \n" + "FILTER (bound(?v0))\n" + "}", // script11
+// END SNIPPET: query11
+
+// START SNIPPET: query12
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Person#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Person>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n"
+            + "OPTIONAL {?entity ns1:email ?v0}. \n" + "FILTER (! bound(?v0))\n" + "}", // script12
+// END SNIPPET: query12
+
+// START SNIPPET: query13
+        "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Male#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Person>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n"
+            + "OPTIONAL {?entity ns1:wife ?v0}. \n" + "FILTER (bound(?v0))\n" + "}", // script13
+// END SNIPPET: query13
+
+// START SNIPPET: query14
+        "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Male#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Male>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n"
+            + "OPTIONAL {?entity ns1:wife ?v0}. \n" + "FILTER (! bound(?v0))\n" + "}", // script14
+// END SNIPPET: query14
+
+// START SNIPPET: query15
+        "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Male#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Person>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n"
+            + "OPTIONAL {?entity ns1:wife ?v0}. \n" + "FILTER (! bound(?v0))\n" + "}", // script15
+// END SNIPPET: query15
+
+// START SNIPPET: query16
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Nameable#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Nameable>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n" + "?entity ns1:name ?v0. \n"
+            + "\n" + "}", // script16
+// END SNIPPET: query16
+
+// START SNIPPET: query17
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Nameable#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Nameable>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n" + "?entity ns1:name ?v0. \n"
+            + "\n" + "} ", // script17
+// END SNIPPET: query17
+
+// START SNIPPET: query18
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Nameable#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Nameable>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n" + "?entity ns1:name ?v0. \n"
+            + "\n" + "}\n", // script18
+// END SNIPPET: query18
+
+// START SNIPPET: query19
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Nameable#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Nameable>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n" + "?entity ns1:name ?v0. \n"
+            + "FILTER (?v0 > \"D\")\n" + "} ", // script19
+// END SNIPPET: query19
+
+// START SNIPPET: query20
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Person#> \n"
+            + "PREFIX ns2: <urn:polygene:type:org.apache.polygene.test.model.Nameable#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Person>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n"
+            + "?entity ns1:yearOfBirth ?v0. \n" + "?entity ns2:name ?v1. \n" + "FILTER (?v0 > \"1973\")\n" + "}\n"
+            , // script20
+// END SNIPPET: query20
+
+// START SNIPPET: query21
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Person#> \n"
+            + "PREFIX ns2: <urn:polygene:type:org.apache.polygene.test.model.Nameable#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Person>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n"
+            + "?entity ns1:placeOfBirth ?v0. \n" + "?v0 ns2:name ?v1. \n" + "?entity ns1:yearOfBirth ?v2. \n" + "\n"
+            + "}", // script21
+// END SNIPPET: query21
+
+// START SNIPPET: query22
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Nameable#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Nameable>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n" + "?entity ns1:name ?v0. \n"
+            + "FILTER regex(?v0,\"J.*Doe\")\n" + "}", // script22
+// END SNIPPET: query22
+
+// START SNIPPET: query23
+        "", // script23
+// END SNIPPET: query23
+
+// START SNIPPET: query24
+        "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.model.Nameable#> \n"
+            + "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?reference\n"
+            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.model.Domain>. \n"
+            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?reference. \n" + "?entity ns1:name ?v0. \n"
+            + "FILTER (?v0 = ?domain)\n" + "}" // script24
+// END SNIPPET: query24
+    };
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfQueryMultimoduleTest.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfQueryMultimoduleTest.java
new file mode 100644
index 0000000..0ed4774
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfQueryMultimoduleTest.java
@@ -0,0 +1,67 @@
+/*
+ *  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.polygene.index.rdf;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.apache.polygene.index.rdf.assembly.RdfNativeSesameStoreAssembler;
+import org.apache.polygene.library.rdf.repository.NativeConfiguration;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+public class RdfQueryMultimoduleTest
+    extends RdfQueryTest
+{
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        LayerAssembly layer = module.layer();
+        assembleValues( module, Visibility.module );
+        assembleEntities( module, Visibility.module );
+
+        ModuleAssembly storeModule = layer.module( "store" );
+        new EntityTestAssembler().visibleIn( Visibility.layer ).assemble( storeModule );
+        assembleValues( storeModule, Visibility.module );
+        new DefaultUnitOfWorkAssembler().assemble( storeModule );
+
+        ModuleAssembly indexModule = layer.module( "index" );
+        new RdfNativeSesameStoreAssembler( Visibility.layer, Visibility.module ).assemble( indexModule );
+        new DefaultUnitOfWorkAssembler().assemble( indexModule );
+
+        LayerAssembly configLayer = module.layer().application().layer( "config" );
+        module.layer().uses( configLayer );
+        ModuleAssembly config = configLayer.module( "config" );
+        config.entities( NativeConfiguration.class ).visibleIn( Visibility.application );
+        config.forMixin( NativeConfiguration.class ).declareDefaults()
+              .dataDirectory().set( tmpDir.getRoot().getAbsolutePath() );
+        new EntityTestAssembler().assemble( config );
+        new DefaultUnitOfWorkAssembler().assemble( config );
+    }
+
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfQueryTest.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfQueryTest.java
new file mode 100644
index 0000000..ae49da8
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/RdfQueryTest.java
@@ -0,0 +1,89 @@
+/*
+ *  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.polygene.index.rdf;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.apache.polygene.index.rdf.assembly.RdfNativeSesameStoreAssembler;
+import org.apache.polygene.library.rdf.repository.NativeConfiguration;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.indexing.AbstractQueryTest;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+public class RdfQueryTest
+    extends AbstractQueryTest
+{
+
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+        new RdfNativeSesameStoreAssembler( Visibility.module, Visibility.module ).assemble( module );
+
+        ModuleAssembly config = module.layer().module( "Config" );
+        config.entities( NativeConfiguration.class ).visibleIn( Visibility.layer );
+        config.forMixin( NativeConfiguration.class ).declareDefaults()
+              .dataDirectory().set( tmpDir.getRoot().getAbsolutePath() );
+        new EntityTestAssembler().assemble( config );
+        new DefaultUnitOfWorkAssembler().assemble( config );
+    }
+
+    @Test
+    @Ignore( "oneOf() Query Expression not supported by RDF Indexing" )
+    @Override
+    public void script23()
+    {
+        super.script23();
+    }
+
+    @Test
+    @Ignore( "Deep queries in complex values are not supported by RDF Indexing" )
+    @Override
+    public void script29()
+    {
+        super.script29();
+    }
+
+    @Test
+    @Ignore( "NamedAssociation are not supported by RDF Indexing" )
+    @Override
+    public void script35()
+    {
+        super.script35();
+    }
+
+    @Test
+    @Ignore( "NamedAssociation are not supported by RDF Indexing" )
+    @Override
+    public void script36()
+    {
+        super.script36();
+    }
+
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi173/Qi173IssueTest.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi173/Qi173IssueTest.java
new file mode 100644
index 0000000..9e87d92
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi173/Qi173IssueTest.java
@@ -0,0 +1,133 @@
+/*
+ *  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.polygene.index.rdf.qi173;
+
+import org.apache.polygene.api.identity.Identity;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryExpressions;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.rdf.assembly.RdfMemoryStoreAssembler;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import java.util.Iterator;
+
+import static org.apache.polygene.api.query.QueryExpressions.orderBy;
+
+public class Qi173IssueTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( CarEntity.class );
+        new RdfMemoryStoreAssembler().assemble( module );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Test
+    public void testPersistence()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            createCar( "Volvo", "S80", 2007 );
+            createCar( "Volvo", "C70", 2006 );
+            createCar( "Ford", "Transit", 2007 );
+            createCar( "Ford", "Mustang", 2007 );
+            createCar( "Ford", "Mustang", 2006 );
+            createCar( "Ford", "Mustang", 2005 );
+            uow.complete();
+        }
+        catch( ConcurrentEntityModificationException e )
+        {
+            // Can not happen.
+            e.printStackTrace();
+        }
+        catch( UnitOfWorkCompletionException e )
+        {
+            e.printStackTrace();
+        }
+
+        uow = unitOfWorkFactory.newUnitOfWork();
+        QueryBuilder<Car> qb = queryBuilderFactory.newQueryBuilder( Car.class );
+        Car template = QueryExpressions.templateFor( Car.class );
+        qb = qb.where( QueryExpressions.eq( template.year(), 2007 ) );
+
+        Query<Car> query = uow.newQuery( qb );
+        query.orderBy( orderBy( template.manufacturer() ), orderBy( template.model() ) );
+        Iterator<Car> cars = query.iterator();
+        Assert.assertTrue( cars.hasNext() );
+        Car car1 = cars.next();
+        Assert.assertEquals( car1.manufacturer().get(), "Ford" );
+        Assert.assertEquals( car1.model().get(), "Mustang" );
+        Assert.assertEquals( (int) car1.year().get(), 2007 );
+        Car car2 = cars.next();
+        Assert.assertEquals( car2.manufacturer().get(), "Ford" );
+        Assert.assertEquals( car2.model().get(), "Transit" );
+        Assert.assertEquals( (int) car2.year().get(), 2007 );
+        Car car3 = cars.next();
+        Assert.assertEquals( car3.manufacturer().get(), "Volvo" );
+        Assert.assertEquals( car3.model().get(), "S80" );
+        Assert.assertEquals( (int) car3.year().get(), 2007 );
+        for( Car car : query )
+        {
+            System.out.println( car.manufacturer().get() + " " + car.model().get() + ", " + car.year().get() );
+        }
+
+        uow.discard();
+    }
+
+    private Identity createCar(String manufacturer, String model, int year )
+    {
+        UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+        EntityBuilder<Car> builder = uow.newEntityBuilder( Car.class );
+        Car prototype = builder.instanceFor( Car.class );
+        prototype.manufacturer().set( manufacturer );
+        prototype.model().set( model );
+        prototype.year().set( year );
+        CarEntity entity = (CarEntity) builder.newInstance();
+        return entity.identity().get();
+    }
+
+    public interface CarEntity
+        extends Car, EntityComposite
+    {
+    }
+
+    public static interface Car
+    {
+        Property<String> manufacturer();
+
+        Property<String> model();
+
+        Property<Integer> year();
+    }
+}
\ No newline at end of file
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/AbstractIssueTest.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/AbstractIssueTest.java
new file mode 100644
index 0000000..e15842d
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/AbstractIssueTest.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.index.rdf.qi64;
+
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.rdf.repository.MemoryRepositoryService;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+public abstract class AbstractIssueTest
+    extends AbstractPolygeneTest
+{
+    private static final String DEFAULT_ACCOUNT_NAME = "polygene";
+
+    /**
+     * Creates a new Apaxhe Polygene account.
+     *
+     * @return The new account reference.
+     *
+     * @throws org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException
+     *          Thrown if creational fail.
+     */
+    protected final Identity newPolygeneAccount()
+        throws UnitOfWorkCompletionException
+    {
+        UnitOfWork work = unitOfWorkFactory.newUnitOfWork();
+        EntityBuilder<AccountComposite> entityBuilder = work.newEntityBuilder( AccountComposite.class );
+        AccountComposite accountComposite = entityBuilder.instance();
+        accountComposite.name().set( DEFAULT_ACCOUNT_NAME );
+        accountComposite = entityBuilder.newInstance();
+
+        Identity identity = accountComposite.identity().get();
+        work.complete();
+        return identity;
+    }
+
+    public final void assemble( ModuleAssembly aModuleAssembly )
+        throws AssemblyException
+    {
+        aModuleAssembly.entities( AccountComposite.class );
+        new EntityTestAssembler().assemble( aModuleAssembly );
+        aModuleAssembly.services( MemoryRepositoryService.class );
+        onAssemble( aModuleAssembly );
+    }
+
+    protected abstract void onAssemble( ModuleAssembly aModuleAssembly )
+        throws AssemblyException;
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/Account.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/Account.java
new file mode 100644
index 0000000..3b1b7c7
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/Account.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.index.rdf.qi64;
+
+public interface Account
+    extends HasName
+{
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/AccountComposite.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/AccountComposite.java
new file mode 100644
index 0000000..2674ded
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/AccountComposite.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.index.rdf.qi64;
+
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.index.rdf.qi66.Account;
+
+public interface AccountComposite
+    extends EntityComposite, Account
+{
+}
\ No newline at end of file
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/HasName.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/HasName.java
new file mode 100644
index 0000000..53c5a98
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/HasName.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.index.rdf.qi64;
+
+import org.apache.polygene.api.property.Property;
+
+public interface HasName
+{
+    Property<String> name();
+}
\ No newline at end of file
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationMandatory/AccountService.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationMandatory/AccountService.java
new file mode 100644
index 0000000..65df5c9
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationMandatory/AccountService.java
@@ -0,0 +1,65 @@
+/*
+ *  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.polygene.index.rdf.qi64.withPropagationMandatory;
+
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation;
+import org.apache.polygene.index.rdf.qi64.AccountComposite;
+
+import static org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation.Propagation.MANDATORY;
+import static org.apache.polygene.index.rdf.qi64.withPropagationMandatory.AccountService.AccountServiceMixin;
+
+@Mixins( AccountServiceMixin.class )
+public interface AccountService
+{
+    @UnitOfWorkPropagation( MANDATORY )
+    AccountComposite getAccountById( Identity anId );
+
+    public class AccountServiceMixin
+        implements AccountService
+    {
+        @Structure
+        UnitOfWorkFactory uowf;
+
+        @Structure
+        Module module;
+
+        public AccountComposite getAccountById( Identity anId )
+        {
+            // Use current unit of work
+            UnitOfWork work = uowf.currentUnitOfWork();
+
+            AccountComposite account = work.get( AccountComposite.class, anId );
+
+            if( account != null )
+            {
+                // Required to get around QI-66 bug
+                account.name().get();
+            }
+
+            return account;
+        }
+    }
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationMandatory/AccountServiceComposite.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationMandatory/AccountServiceComposite.java
new file mode 100644
index 0000000..53ebfea
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationMandatory/AccountServiceComposite.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.index.rdf.qi64.withPropagationMandatory;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkConcern;
+
+@Concerns( UnitOfWorkConcern.class )
+public interface AccountServiceComposite
+    extends ServiceComposite, AccountService
+{
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationMandatory/IssueTest.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationMandatory/IssueTest.java
new file mode 100644
index 0000000..3a9928d
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationMandatory/IssueTest.java
@@ -0,0 +1,94 @@
+/*
+ *  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.polygene.index.rdf.qi64.withPropagationMandatory;
+
+import org.apache.polygene.api.identity.Identity;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.rdf.qi64.AbstractIssueTest;
+import org.apache.polygene.index.rdf.qi64.AccountComposite;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public final class IssueTest
+    extends AbstractIssueTest
+{
+    private AccountService accountService;
+
+    @Before
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        accountService = serviceFinder.findService( AccountService.class ).get();
+    }
+
+    @Test( expected = IllegalStateException.class )
+    public final void testUnitOfWorkWithUnitOfWorkNotInitialized()
+        throws Throwable
+    {
+        // Bootstrap the account
+        Identity id = newPolygeneAccount();
+
+        // Make sure there's no unit of work
+        assertNull( unitOfWorkFactory.currentUnitOfWork() );
+
+        accountService.getAccountById( id );
+    }
+
+    @Test
+    public final void testUnitOfWorkWithUnitOfWorkInitialized()
+        throws Throwable
+    {
+        // Bootstrap the account
+        Identity id = newPolygeneAccount();
+
+        // Make sure there's no unit of work
+        assertFalse( unitOfWorkFactory.isUnitOfWorkActive() );
+
+        UnitOfWork parentUnitOfWork = unitOfWorkFactory.newUnitOfWork();
+
+        AccountComposite account = accountService.getAccountById( id );
+        assertNotNull( account );
+
+        UnitOfWork currentUnitOfWork = unitOfWorkFactory.currentUnitOfWork();
+        assertEquals( parentUnitOfWork, currentUnitOfWork );
+
+        assertTrue( currentUnitOfWork.isOpen() );
+
+        // Close the parent unit of work
+        parentUnitOfWork.complete();
+    }
+
+    protected final void onAssemble( ModuleAssembly aModuleAssembly )
+        throws AssemblyException
+    {
+        aModuleAssembly.services( AccountServiceComposite.class );
+    }
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequired/AccountService.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequired/AccountService.java
new file mode 100644
index 0000000..30c2e54
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequired/AccountService.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.index.rdf.qi64.withPropagationRequired;
+
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation;
+import org.apache.polygene.index.rdf.qi64.AccountComposite;
+
+import static org.apache.polygene.index.rdf.qi64.withPropagationRequired.AccountService.AccountServiceMixin;
+
+@Mixins( AccountServiceMixin.class )
+public interface AccountService
+{
+    @UnitOfWorkPropagation
+    AccountComposite getAccountById( Identity anId );
+
+    public class AccountServiceMixin
+        implements AccountService
+    {
+        @Structure
+        UnitOfWorkFactory uowf;
+
+        @Structure
+        Module module;
+
+        public AccountComposite getAccountById( Identity anId )
+        {
+            // Use current unit of work
+            UnitOfWork work = uowf.currentUnitOfWork();
+
+            AccountComposite account = work.get( AccountComposite.class, anId );
+
+            if( account != null )
+            {
+                // Required to get around QI-66 bug
+                account.name().get();
+            }
+
+            return account;
+        }
+    }
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequired/AccountServiceComposite.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequired/AccountServiceComposite.java
new file mode 100644
index 0000000..9327946
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequired/AccountServiceComposite.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.index.rdf.qi64.withPropagationRequired;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkConcern;
+
+@Concerns( UnitOfWorkConcern.class )
+public interface AccountServiceComposite
+    extends ServiceComposite, AccountService
+{
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequired/IssueTest.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequired/IssueTest.java
new file mode 100644
index 0000000..08b79e1
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequired/IssueTest.java
@@ -0,0 +1,94 @@
+/*
+ *  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.polygene.index.rdf.qi64.withPropagationRequired;
+
+import org.apache.polygene.api.identity.Identity;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.rdf.qi64.AbstractIssueTest;
+import org.apache.polygene.index.rdf.qi64.AccountComposite;
+
+import static org.junit.Assert.*;
+
+public final class IssueTest
+    extends AbstractIssueTest
+{
+    private AccountService accountService;
+
+    @Before
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        accountService = serviceFinder.findService( AccountService.class ).get();
+    }
+
+    @Test
+    public final void testUnitOfWorkWithUnitOfWorkNotInitialized()
+        throws Throwable
+    {
+        // Bootstrap the account
+        Identity id = newPolygeneAccount();
+
+        // Make sure there's no unit of work
+        assertFalse( unitOfWorkFactory.isUnitOfWorkActive() );
+
+        AccountComposite account = accountService.getAccountById( id );
+        assertNotNull( account );
+
+        assertFalse( unitOfWorkFactory.isUnitOfWorkActive() );
+    }
+
+    @Test
+    public final void testUnitOfWorkWithUnitOfWorkInitialized()
+        throws Throwable
+    {
+        // Bootstrap the account
+        Identity id = newPolygeneAccount();
+
+        // Make sure there's no unit of work
+        assertFalse( unitOfWorkFactory.isUnitOfWorkActive() );
+
+        UnitOfWork parentUnitOfWork = unitOfWorkFactory.newUnitOfWork();
+
+        AccountComposite account = accountService.getAccountById( id );
+        assertNotNull( account );
+
+        UnitOfWork currentUnitOfWork = unitOfWorkFactory.currentUnitOfWork();
+        assertEquals( parentUnitOfWork, currentUnitOfWork );
+
+        assertTrue( currentUnitOfWork.isOpen() );
+
+        // Close the parent unit of work
+        parentUnitOfWork.complete();
+    }
+
+    @Override
+    public final void onAssemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( AccountServiceComposite.class );
+    }
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequiresNew/AccountService.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequiresNew/AccountService.java
new file mode 100644
index 0000000..de1806b
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequiresNew/AccountService.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.index.rdf.qi64.withPropagationRequiresNew;
+
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation;
+import org.apache.polygene.index.rdf.qi64.AccountComposite;
+
+import static org.apache.polygene.index.rdf.qi64.withPropagationRequiresNew.AccountService.AccountServiceMixin;
+
+@Mixins( AccountServiceMixin.class )
+public interface AccountService
+{
+    @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRES_NEW )
+    AccountComposite getAccountById( Identity anId );
+
+    public class AccountServiceMixin
+        implements AccountService
+    {
+        @Structure
+        UnitOfWorkFactory uowf;
+
+        @Structure
+        Module module;
+
+        public AccountComposite getAccountById( Identity anId )
+        {
+            // Use current unit of work
+            UnitOfWork work = uowf.currentUnitOfWork();
+
+            AccountComposite account = work.get( AccountComposite.class, anId );
+
+            if( account != null )
+            {
+                // Required to get around QI-66 bug
+                account.name().get();
+            }
+
+            return account;
+        }
+    }
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequiresNew/AccountServiceComposite.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequiresNew/AccountServiceComposite.java
new file mode 100644
index 0000000..8123ee3
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequiresNew/AccountServiceComposite.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.index.rdf.qi64.withPropagationRequiresNew;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkConcern;
+
+@Concerns( UnitOfWorkConcern.class )
+public interface AccountServiceComposite
+    extends ServiceComposite, AccountService
+{
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequiresNew/IssueTest.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequiresNew/IssueTest.java
new file mode 100644
index 0000000..ef2de77
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi64/withPropagationRequiresNew/IssueTest.java
@@ -0,0 +1,94 @@
+/*
+ *  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.polygene.index.rdf.qi64.withPropagationRequiresNew;
+
+import org.apache.polygene.api.identity.Identity;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.rdf.qi64.AbstractIssueTest;
+import org.apache.polygene.index.rdf.qi64.AccountComposite;
+
+import static org.junit.Assert.*;
+
+public class IssueTest
+    extends AbstractIssueTest
+{
+    private AccountService accountService;
+
+    @Before
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+
+        accountService = serviceFinder.findService( AccountService.class ).get();
+    }
+
+    @Test
+    public final void testUnitOfWorkNotInitialized()
+        throws Throwable
+    {
+        // Bootstrap the account
+        Identity id = newPolygeneAccount();
+
+        // Make sure there's no unit of work
+        assertFalse( unitOfWorkFactory.isUnitOfWorkActive() );
+
+        AccountComposite account = accountService.getAccountById( id );
+        assertNotNull( account );
+
+        assertFalse( unitOfWorkFactory.isUnitOfWorkActive() );
+    }
+
+    @Test
+    public final void testUnitOfWorkInitialized()
+        throws Throwable
+    {
+        // Bootstrap the account
+        Identity id = newPolygeneAccount();
+
+        // Make sure there's no unit of work
+        assertFalse( unitOfWorkFactory.isUnitOfWorkActive() );
+
+        UnitOfWork parentUnitOfWork = unitOfWorkFactory.newUnitOfWork();
+
+        AccountComposite account = accountService.getAccountById( id );
+        assertNotNull( account );
+
+        UnitOfWork currentUnitOfWork = unitOfWorkFactory.currentUnitOfWork();
+        assertEquals( parentUnitOfWork, currentUnitOfWork );
+
+        assertTrue( currentUnitOfWork.isOpen() );
+
+        // Close the parent unit of work
+        parentUnitOfWork.complete();
+    }
+
+    protected final void onAssemble( ModuleAssembly aModuleAssembly )
+        throws AssemblyException
+    {
+        aModuleAssembly.services( AccountServiceComposite.class );
+    }
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi66/Account.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi66/Account.java
new file mode 100644
index 0000000..e5c4caf
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi66/Account.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.index.rdf.qi66;
+
+public interface Account
+    extends HasName
+{
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi66/AccountComposite.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi66/AccountComposite.java
new file mode 100644
index 0000000..f5cb20d
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi66/AccountComposite.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.index.rdf.qi66;
+
+import org.apache.polygene.api.entity.EntityComposite;
+
+public interface AccountComposite
+    extends EntityComposite, Account
+{
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi66/HasName.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi66/HasName.java
new file mode 100644
index 0000000..7514805
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi66/HasName.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.index.rdf.qi66;
+
+import org.apache.polygene.api.property.Property;
+
+public interface HasName
+{
+    Property<String> name();
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi66/Qi66IssueTest.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi66/Qi66IssueTest.java
new file mode 100644
index 0000000..d5a385c
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi66/Qi66IssueTest.java
@@ -0,0 +1,100 @@
+/*
+ *  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.polygene.index.rdf.qi66;
+
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.rdf.query.RdfQueryParserFactory;
+import org.apache.polygene.index.rdf.query.RdfQueryService;
+import org.apache.polygene.library.rdf.entity.EntityStateSerializer;
+import org.apache.polygene.library.rdf.entity.EntityTypeSerializer;
+import org.apache.polygene.library.rdf.repository.MemoryRepositoryService;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+/**
+ * Test for Qi-66
+ */
+public class Qi66IssueTest
+    extends AbstractPolygeneTest
+{
+    private static final String ACCOUNT_NAME = "polygene";
+
+    @Test
+    public final void testCompleteAfterFind()
+        throws Exception
+    {
+        Identity accountIdentity = newPolygeneAccount();
+
+        UnitOfWork work = unitOfWorkFactory.newUnitOfWork();
+        AccountComposite account = work.get( AccountComposite.class, accountIdentity );
+        assertNotNull( account );
+
+        try
+        {
+            work.complete();
+        }
+        catch( Throwable e )
+        {
+            e.printStackTrace();
+            fail( "No exception can be thrown." );
+        }
+    }
+
+    /**
+     * Creates a new Apache Polygene account.
+     *
+     * @return The reference of Polygene account.
+     *
+     * @throws UnitOfWorkCompletionException Thrown if creational fail.
+     */
+    private Identity newPolygeneAccount()
+        throws UnitOfWorkCompletionException
+    {
+        UnitOfWork work = unitOfWorkFactory.newUnitOfWork();
+        EntityBuilder<AccountComposite> entityBuilder = work.newEntityBuilder( AccountComposite.class );
+        AccountComposite accountComposite = entityBuilder.instance();
+        accountComposite.name().set( ACCOUNT_NAME );
+        accountComposite = entityBuilder.newInstance();
+        Identity accoutnIdentity = accountComposite.identity().get();
+        work.complete();
+
+        return accoutnIdentity;
+    }
+
+    public final void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( AccountComposite.class );
+        new EntityTestAssembler().assemble( module );
+        module.services( RdfQueryService.class,
+                         RdfQueryParserFactory.class,
+                         MemoryRepositoryService.class );
+        module.objects( EntityStateSerializer.class, EntityTypeSerializer.class );
+    }
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi95/Qi95IssueTest.java b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi95/Qi95IssueTest.java
new file mode 100644
index 0000000..2694153
--- /dev/null
+++ b/extensions/indexing-rdf/src/test/java/org/apache/polygene/index/rdf/qi95/Qi95IssueTest.java
@@ -0,0 +1,398 @@
+/*
+ *  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.polygene.index.rdf.qi95;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.jdbm.JdbmConfiguration;
+import org.apache.polygene.entitystore.jdbm.assembly.JdbmEntityStoreAssembler;
+import org.apache.polygene.index.rdf.assembly.RdfMemoryStoreAssembler;
+import org.apache.polygene.index.rdf.assembly.RdfNativeSesameStoreAssembler;
+import org.apache.polygene.library.rdf.repository.NativeConfiguration;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import static org.junit.Assert.assertTrue;
+
+public class Qi95IssueTest
+{
+
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Test
+    public void canCreateAndQueryWithNativeRdfAndJdbm()
+        throws Exception
+    {
+        Application application = createApplication( nativeRdf, jdbmStore, domain );
+        try
+        {
+            application.activate();
+            Module domain = application.findModule( "Domain", "Domain" );
+            UnitOfWorkFactory unitOfWorkFactory = domain.unitOfWorkFactory();
+            createABunchOfStuffAndDoQueries( unitOfWorkFactory, domain );
+        }
+        finally
+        {
+            application.passivate();
+        }
+    }
+
+    @Test
+    public void canCreateAndQueryWithAllInMemory()
+        throws Exception
+    {
+        Application application = createApplication( inMemoryRdf, inMemoryStore, domain );
+        try
+        {
+            application.activate();
+            Module domain = application.findModule( "Domain", "Domain" );
+            UnitOfWorkFactory unitOfWorkFactory = domain.unitOfWorkFactory();
+            createABunchOfStuffAndDoQueries( unitOfWorkFactory, domain );
+        }
+        finally
+        {
+            application.passivate();
+        }
+    }
+
+    @Test
+    public void canCreateAndQueryWithNativeRdfWithInMemoryStore()
+        throws Exception
+    {
+        Application application = createApplication( nativeRdf, inMemoryStore, domain );
+        try
+        {
+            application.activate();
+            Module domain = application.findModule( "Domain", "Domain" );
+            UnitOfWorkFactory unitOfWorkFactory = domain.unitOfWorkFactory();
+            createABunchOfStuffAndDoQueries( unitOfWorkFactory, domain );
+        }
+        finally
+        {
+            application.passivate();
+        }
+    }
+
+    @Test
+    public void canCreateAndQueryWithInMemoryRdfWithJdbm()
+        throws Exception
+    {
+        Application application = createApplication( inMemoryRdf, jdbmStore, domain );
+        try
+        {
+            application.activate();
+
+            Module domain = application.findModule( "Domain", "Domain" );
+            UnitOfWorkFactory unitOfWorkFactory = domain.unitOfWorkFactory();
+            createABunchOfStuffAndDoQueries( unitOfWorkFactory, domain );
+        }
+        finally
+        {
+            application.passivate();
+        }
+    }
+
+    public void createABunchOfStuffAndDoQueries( UnitOfWorkFactory unitOfWorkFactory,
+                                                 QueryBuilderFactory queryBuilderFactory
+    )
+        throws Exception
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        newItemType( uow, "Band" );
+        newItemType( uow, "Bracelet" );
+        newItemType( uow, "Necklace" );
+        uow.complete();
+
+        uow = unitOfWorkFactory.newUnitOfWork();
+        QueryBuilder<ItemType> qb = queryBuilderFactory.newQueryBuilder( ItemType.class );
+        Iterable<ItemType> initialList = copyOf( uow.newQuery( qb ));
+
+        assertTrue( "Band is not in the initial list", hasItemTypeNamed( "Band", initialList ) );
+        assertTrue( "Bracelet is not in the initial list", hasItemTypeNamed( "Bracelet", initialList ) );
+        assertTrue( "Necklace is not in the initial list", hasItemTypeNamed( "Necklace", initialList ) );
+
+        newItemType( uow, "Watch" );
+        uow.complete();
+
+        uow = unitOfWorkFactory.newUnitOfWork();
+        qb = queryBuilderFactory.newQueryBuilder( ItemType.class );
+        Iterable<ItemType> listAfterFirstQueryAndAdd = copyOf( uow.newQuery( qb ) );
+
+        assertTrue( "Band is not in the list after the first query and add", hasItemTypeNamed( "Band", listAfterFirstQueryAndAdd ) );
+        assertTrue( "Bracelet is not in the list after the first query and add", hasItemTypeNamed( "Bracelet", listAfterFirstQueryAndAdd ) );
+        assertTrue( "Necklace is not in the list after the first query and add", hasItemTypeNamed( "Necklace", listAfterFirstQueryAndAdd ) );
+        assertTrue( "Watch is not in the list after the first query and add", hasItemTypeNamed( "Watch", listAfterFirstQueryAndAdd ) );
+
+        newItemType( uow, "Ear ring" );
+        uow.complete();
+
+        uow = unitOfWorkFactory.newUnitOfWork();
+        Iterable<ItemType> finalList = copyOf( uow.newQuery( qb ) );
+        assertTrue( "Band is not in the final list", hasItemTypeNamed( "Band", finalList ) );
+        assertTrue( "Bracelet is not in the final list", hasItemTypeNamed( "Bracelet", finalList ) );
+        assertTrue( "Necklace is not in the final list", hasItemTypeNamed( "Necklace", finalList ) );
+        assertTrue( "Watch is not in the final list", hasItemTypeNamed( "Watch", finalList ) );
+        assertTrue( "Ear ring is not in the final list", hasItemTypeNamed( "Ear ring", finalList ) );
+        uow.complete();
+    }
+
+    private Application createApplication( final ModuleAssemblyBuilder queryServiceModuleBuilder,
+                                              final ModuleAssemblyBuilder entityStoreModuleBuilder,
+                                              final LayerAssemblyBuilder domainLayerBuilder
+    )
+        throws AssemblyException
+    {
+        Energy4Java polygene = new Energy4Java();
+        Application application = polygene.newApplication( new ApplicationAssembler()
+        {
+            @Override
+            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+                throws AssemblyException
+            {
+                ApplicationAssembly applicationAssembly = applicationFactory.newApplicationAssembly();
+
+                LayerAssembly configLayer = applicationAssembly.layer( "Config" );
+                configModule.buildModuleAssembly( configLayer, "Configuration" );
+
+                LayerAssembly infrastructureLayer = applicationAssembly.layer( "Infrastructure" );
+                infrastructureLayer.uses( configLayer );
+
+                queryServiceModuleBuilder.buildModuleAssembly( infrastructureLayer, "Query Service" );
+                entityStoreModuleBuilder.buildModuleAssembly( infrastructureLayer, "Entity Store" );
+
+                LayerAssembly domainLayer = domainLayerBuilder.buildLayerAssembly( applicationAssembly );
+                domainLayer.uses( infrastructureLayer );
+                return applicationAssembly;
+            }
+        } );
+        return application;
+    }
+
+    interface LayerAssemblyBuilder
+    {
+        LayerAssembly buildLayerAssembly( ApplicationAssembly appAssembly )
+            throws AssemblyException;
+    }
+
+    interface ModuleAssemblyBuilder
+    {
+        ModuleAssembly buildModuleAssembly( LayerAssembly layer, String name )
+            throws AssemblyException;
+    }
+
+    final ModuleAssemblyBuilder nativeRdf = new ModuleAssemblyBuilder()
+    {
+        @Override
+        public ModuleAssembly buildModuleAssembly( LayerAssembly layer, String name )
+            throws AssemblyException
+        {
+            return addModule( layer, name, new RdfNativeSesameStoreAssembler() );
+        }
+    };
+
+    final ModuleAssemblyBuilder inMemoryStore = new ModuleAssemblyBuilder()
+    {
+        @Override
+        public ModuleAssembly buildModuleAssembly( LayerAssembly layer, String name )
+            throws AssemblyException
+        {
+            return addModule( layer, name, new EntityTestAssembler().visibleIn( Visibility.application ) );
+        }
+    };
+
+    final ModuleAssemblyBuilder inMemoryRdf = new ModuleAssemblyBuilder()
+    {
+        @Override
+        public ModuleAssembly buildModuleAssembly( LayerAssembly layer, String name )
+            throws AssemblyException
+        {
+            return addModule( layer, name, new RdfMemoryStoreAssembler() );
+        }
+    };
+
+    final ModuleAssemblyBuilder jdbmStore = new ModuleAssemblyBuilder()
+    {
+        @Override
+        public ModuleAssembly buildModuleAssembly( LayerAssembly layer, String name )
+            throws AssemblyException
+        {
+            return addModule( layer, name, jdbmEntityStoreAssembler() );
+        }
+    };
+
+    final ModuleAssemblyBuilder configModule = new ModuleAssemblyBuilder()
+    {
+        @Override
+        public ModuleAssembly buildModuleAssembly( LayerAssembly layer, String name )
+            throws AssemblyException
+        {
+            return addModule( layer, name, entityStoreConfigAssembler() );
+        }
+    };
+
+    final LayerAssemblyBuilder domain = new LayerAssemblyBuilder()
+    {
+        @Override
+        public LayerAssembly buildLayerAssembly( ApplicationAssembly appAssembly )
+            throws AssemblyException
+        {
+            LayerAssembly domainLayer = appAssembly.layer( "Domain" );
+            addModule( domainLayer, "Domain", new Assembler()
+            {
+                @Override
+                @SuppressWarnings( "unchecked" )
+                public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+                {
+                    module.entities( ItemTypeEntity.class );
+                }
+            } );
+            return domainLayer;
+        }
+    };
+
+    private Assembler entityStoreConfigAssembler()
+    {
+        return new Assembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                new EntityTestAssembler().assemble( module );
+
+                module.entities( NativeConfiguration.class ).visibleIn( Visibility.application );
+                module.forMixin( NativeConfiguration.class )
+                    .declareDefaults()
+                    .dataDirectory()
+                    .set( rdfDirectory().getAbsolutePath() );
+
+                module.entities( JdbmConfiguration.class ).visibleIn( Visibility.application );
+                module.forMixin( JdbmConfiguration.class )
+                    .declareDefaults()
+                    .file()
+                    .set( jdbmDirectory().getAbsolutePath() );
+            }
+        };
+    }
+
+    private Assembler jdbmEntityStoreAssembler()
+    {
+        return new Assembler()
+        {
+            @Override
+            @SuppressWarnings( "unchecked" )
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                new JdbmEntityStoreAssembler().visibleIn( Visibility.application ).assemble( module );
+            }
+        };
+    }
+
+    private ModuleAssembly addModule( LayerAssembly layerAssembly, String name, Assembler assembler )
+        throws AssemblyException
+    {
+        ModuleAssembly moduleAssembly = layerAssembly.module( name );
+        assembler.assemble( moduleAssembly );
+        return moduleAssembly;
+    }
+
+    private File rdfDirectory()
+    {
+        return createTempDirectory( "rdf-index" );
+    }
+
+    private File jdbmDirectory()
+    {
+        return createTempDirectory( "jdbm-store" );
+    }
+
+    private File createTempDirectory( String name )
+    {
+        File t = new File( tmpDir.getRoot(), name );
+        t.mkdirs();
+        return t;
+    }
+
+    boolean hasItemTypeNamed( String name, Iterable<ItemType> list )
+    {
+        for( ItemType i : list )
+        {
+            Property<String> nameProperty = i.name();
+            String entityName = nameProperty.get();
+            if( entityName.equals( name ) )
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private Iterable<ItemType> copyOf( Iterable<ItemType> iterable )
+    {
+        Collection<ItemType> copy = new ArrayList<ItemType>();
+        for( ItemType i : iterable )
+        {
+            copy.add( i );
+        }
+        return Collections.unmodifiableCollection( copy );
+    }
+
+    private ItemType newItemType( UnitOfWork uow, String name )
+    {
+        EntityBuilder<ItemType> builder = uow.newEntityBuilder( ItemType.class );
+        builder.instance().name().set( name );
+        return builder.newInstance();
+    }
+
+    interface ItemType
+    {
+        Property<String> name();
+    }
+
+    interface ItemTypeEntity
+        extends ItemType, EntityComposite
+    {
+    }
+}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/ContainsAllTest.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/ContainsAllTest.java
deleted file mode 100644
index 312aa36..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/ContainsAllTest.java
+++ /dev/null
@@ -1,387 +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.qi4j.index.rdf;
-
-import java.io.File;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.QueryExpressions;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Iterables;
-import org.qi4j.index.rdf.assembly.RdfNativeSesameStoreAssembler;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.library.rdf.repository.NativeConfiguration;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-import org.junit.Rule;
-import org.qi4j.test.util.DelTreeAfter;
-
-// A test to verify that containsAll QueryExpression works properly.
-public class ContainsAllTest
-    extends AbstractQi4jTest
-{
-    private static final File DATA_DIR = new File( "build/tmp/contains-all-test" );
-    @Rule
-    public final DelTreeAfter delTreeAfter = new DelTreeAfter( DATA_DIR );
-
-    public static final String TEST_STRING_1 = "TestString1";
-    public static final String TEST_STRING_2 = "Some\\Weird\"$String/[]";
-    public static final String TEST_STRING_3 = "TestString3";
-    public static final String TEST_STRING_4 = "TestSTring4";
-
-    public interface ExampleValue2
-        extends ValueComposite
-    {
-        Property<String> stringProperty();
-    }
-
-    public interface ExampleValue
-        extends ValueComposite
-    {
-        Property<ExampleValue2> valueProperty();
-    }
-
-    public interface ExampleEntity
-        extends EntityComposite
-    {
-        Property<Set<String>> strings();
-
-        Property<Set<ExampleValue>> complexValue();
-    }
-
-    // This test creates a one-layer, two-module application, with one module
-    // being testing module, and another for retrieving configuration for
-    // services from preferences. This test assumes that those configurations
-    // already exist in preference ES.
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( FileConfigurationService.class );
-        ModuleAssembly prefModule = module.layer().module( "PrefModule" );
-        prefModule.entities( NativeConfiguration.class ).visibleIn( Visibility.application );
-        prefModule.forMixin( NativeConfiguration.class ).declareDefaults().dataDirectory().set( DATA_DIR.getAbsolutePath() );
-        new EntityTestAssembler().assemble( prefModule );
-
-        module.entities( ExampleEntity.class );
-        module.values( ExampleValue.class, ExampleValue2.class );
-
-        EntityTestAssembler testAss = new EntityTestAssembler();
-        testAss.assemble( module );
-
-        RdfNativeSesameStoreAssembler rdfAssembler = new RdfNativeSesameStoreAssembler();
-        rdfAssembler.assemble( module );
-    }
-
-    public static ExampleEntity createEntityWithStrings( UnitOfWork uow, ValueBuilderFactory vbf, String... strings )
-    {
-        EntityBuilder<ExampleEntity> builder = uow.newEntityBuilder( ExampleEntity.class );
-
-        populateStrings( builder.instance(), strings );
-        populateComplexValue( builder.instance(), vbf );
-
-        return builder.newInstance();
-    }
-
-    public static ExampleEntity createEntityWithComplexValues( UnitOfWork uow,
-                                                               ValueBuilderFactory vbf,
-                                                               String... valueStrings
-    )
-    {
-        EntityBuilder<ExampleEntity> builder = uow.newEntityBuilder( ExampleEntity.class );
-
-        populateStrings( builder.instance() );
-        populateComplexValue( builder.instance(), vbf, valueStrings );
-
-        return builder.newInstance();
-    }
-
-    private static void populateStrings( ExampleEntity proto, String... strings )
-    {
-        proto.strings().set( new HashSet<String>( Arrays.asList( strings ) ) );
-    }
-
-    private static void populateComplexValue( ExampleEntity proto, ValueBuilderFactory vbf, String... valueStrings )
-    {
-        Set<ExampleValue> values = new HashSet<ExampleValue>();
-        for( String value : valueStrings )
-        {
-            ValueBuilder<ExampleValue2> vBuilder = vbf.newValueBuilder( ExampleValue2.class );
-            vBuilder.prototype().stringProperty().set( value );
-
-            ValueBuilder<ExampleValue> vBuilder2 = vbf.newValueBuilder( ExampleValue.class );
-            vBuilder2.prototype().valueProperty().set( vBuilder.newInstance() );
-            values.add( vBuilder2.newInstance() );
-        }
-
-        proto.complexValue().set( values );
-    }
-
-    @Test
-    public void simpleContainsAllQuerySuccessTest()
-        throws Exception
-    {
-
-        ExampleEntity result = this.performContainsAllStringsTest(
-            new HashSet<String>( Arrays.asList(
-                TEST_STRING_1, TEST_STRING_2, TEST_STRING_3
-            )
-            ),
-            new HashSet<String>( Arrays.asList(
-                TEST_STRING_1, TEST_STRING_2
-            )
-            )
-        );
-
-        Assert.assertTrue( "The entity must have been found.", result != null );
-    }
-
-    @Test
-    public void fullContainsAllQuerySuccessTest()
-        throws Exception
-    {
-        ExampleEntity result = this.performContainsAllStringsTest(
-            new HashSet<String>( Arrays.asList(
-                TEST_STRING_1, TEST_STRING_2, TEST_STRING_3
-            )
-            ),
-            new HashSet<String>( Arrays.asList(
-                TEST_STRING_1, TEST_STRING_2, TEST_STRING_3
-            )
-            )
-        );
-
-        Assert.assertTrue( "The entity must have been found.", result != null );
-    }
-
-    @Test
-    public void simpleContainsAllQueryFailTest()
-        throws Exception
-    {
-        ExampleEntity result = this.performContainsAllStringsTest(
-            new HashSet<String>( Arrays.asList(
-                TEST_STRING_1, TEST_STRING_2, TEST_STRING_3
-            )
-            ),
-            new HashSet<String>( Arrays.asList(
-                TEST_STRING_1, TEST_STRING_2, TEST_STRING_3, TEST_STRING_4
-            )
-            )
-        );
-
-        Assert.assertTrue( "The entity must not have been found.", result == null );
-    }
-
-    @Test
-    public void simpleContainsAllQueryWithNullsTest()
-        throws Exception
-    {
-        ExampleEntity result = this.performContainsAllStringsTest(
-            new HashSet<String>( Arrays.asList(
-                TEST_STRING_1, TEST_STRING_2, TEST_STRING_3
-            )
-            ),
-            new HashSet<String>( Arrays.asList(
-                TEST_STRING_1, null, TEST_STRING_2
-            )
-            )
-        );
-
-        Assert.assertTrue( "The entity must have been found.", result != null );
-    }
-
-    @Test
-    public void emptyContainsAllQueryTest()
-        throws Exception
-    {
-        ExampleEntity result = this.performContainsAllStringsTest(
-            new HashSet<String>( Arrays.asList(
-                TEST_STRING_1, TEST_STRING_2
-            )
-            ),
-            new HashSet<String>()
-        );
-
-        Assert.assertTrue( "The entity must have been found.", result != null );
-    }
-
-    @Test
-    public void complexContainsAllSuccessTest()
-        throws Exception
-    {
-        ExampleEntity result = this.performContainsAllStringValueTest(
-            new HashSet<String>( Arrays.asList(
-                TEST_STRING_1, TEST_STRING_2
-            )
-            ),
-            new HashSet<String>( Arrays.asList(
-                TEST_STRING_1
-            )
-            )
-        );
-
-        Assert.assertTrue( "The entity must have been found.", result != null );
-    }
-
-    @Test
-    public void fullComplexContainsAllSuccessTest()
-        throws Exception
-    {
-        ExampleEntity result = this.performContainsAllStringValueTest(
-            new HashSet<String>( Arrays.asList(
-                TEST_STRING_1, TEST_STRING_2
-            )
-            ),
-            new HashSet<String>( Arrays.asList(
-                TEST_STRING_1, TEST_STRING_2
-            )
-            )
-        );
-
-        Assert.assertTrue( "The entity must have been found", result != null );
-    }
-
-    @Test
-    public void complexContainsAllFailTest()
-        throws Exception
-    {
-        ExampleEntity result = this.performContainsAllStringValueTest(
-            new HashSet<String>( Arrays.asList(
-                TEST_STRING_1, TEST_STRING_2
-            )
-            ),
-            new HashSet<String>( Arrays.asList(
-                TEST_STRING_1, TEST_STRING_2, TEST_STRING_3
-            )
-            )
-        );
-
-        Assert.assertTrue( "The entity must not have been found.", result == null );
-    }
-
-    @Test
-    public void complexEmptyContainsAllTest()
-        throws Exception
-    {
-        ExampleEntity result = this.performContainsAllStringValueTest(
-            new HashSet<String>( Arrays.asList(
-                TEST_STRING_1, TEST_STRING_2
-            )
-            ),
-            new HashSet<String>()
-        );
-
-        Assert.assertTrue( "The entity must have been found.", result != null );
-    }
-
-    private ExampleEntity findEntity( String... strings )
-    {
-        QueryBuilder<ExampleEntity> builder = this.module.newQueryBuilder( ExampleEntity.class );
-
-        builder = builder.where( QueryExpressions.containsAll(
-                QueryExpressions.templateFor( ExampleEntity.class ).strings(),
-                Iterables.iterable( strings ) ) );
-        return this.module.currentUnitOfWork().newQuery( builder ).find();
-    }
-
-    private ExampleEntity findEntityBasedOnValueStrings( String... valueStrings )
-    {
-        Set<ExampleValue> values = new HashSet<ExampleValue>();
-        for( String value : valueStrings )
-        {
-            ValueBuilder<ExampleValue2> vBuilder = this.module.newValueBuilder( ExampleValue2.class );
-            vBuilder.prototype().stringProperty().set( value );
-
-            ValueBuilder<ExampleValue> vBuilder2 = this.module.newValueBuilder( ExampleValue.class );
-            vBuilder2.prototype().valueProperty().set( vBuilder.newInstance() );
-            values.add( vBuilder2.newInstance() );
-        }
-
-        return this.createComplexQuery( values ).find();
-    }
-
-    private Query<ExampleEntity> createComplexQuery( Set<ExampleValue> valuez )
-    {
-        QueryBuilder<ExampleEntity> builder = this.module.newQueryBuilder( ExampleEntity.class );
-        builder = builder.where( QueryExpressions.containsAll(
-                QueryExpressions.templateFor( ExampleEntity.class ).complexValue(),
-                valuez
-        )
-        );
-
-        return this.module.currentUnitOfWork().newQuery( builder );
-    }
-
-    private ExampleEntity performContainsAllStringsTest( Set<String> entityStrings, Set<String> queryableStrings )
-        throws Exception
-    {
-        UnitOfWork creatingUOW = this.module.newUnitOfWork();
-        String[] entityStringsArray = new String[entityStrings.size()];
-        createEntityWithStrings( creatingUOW, this.module, entityStrings.toArray( entityStringsArray ) );
-        creatingUOW.complete();
-
-        UnitOfWork queryingUOW = this.module.newUnitOfWork();
-        try
-        {
-            String[] queryableStringsArray = new String[queryableStrings.size()];
-            ExampleEntity entity = this.findEntity( queryableStrings.toArray( queryableStringsArray ) );
-            return entity;
-        }
-        finally
-        {
-            queryingUOW.discard();
-        }
-    }
-
-    private ExampleEntity performContainsAllStringValueTest( Set<String> entityStrings, Set<String> queryableStrings )
-        throws Exception
-    {
-        UnitOfWork creatingUOW = this.module.newUnitOfWork();
-        String[] entityStringsArray = new String[entityStrings.size()];
-        createEntityWithComplexValues( creatingUOW, this.module, entityStrings.toArray( entityStringsArray ) );
-        creatingUOW.complete();
-
-        UnitOfWork queryingUOW = this.module.newUnitOfWork();
-        try
-        {
-            String[] queryableStringsArray = new String[queryableStrings.size()];
-            ExampleEntity entity = this.findEntityBasedOnValueStrings( queryableStrings.toArray( queryableStringsArray ) );
-            return entity;
-        }
-        finally
-        {
-            queryingUOW.discard();
-        }
-    }
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/ContainsTest.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/ContainsTest.java
deleted file mode 100644
index bafebdd..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/ContainsTest.java
+++ /dev/null
@@ -1,210 +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.qi4j.index.rdf;
-
-import java.io.File;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.QueryExpressions;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.rdf.ContainsAllTest.ExampleEntity;
-import org.qi4j.index.rdf.ContainsAllTest.ExampleValue;
-import org.qi4j.index.rdf.ContainsAllTest.ExampleValue2;
-import org.qi4j.index.rdf.assembly.RdfNativeSesameStoreAssembler;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.library.rdf.repository.NativeConfiguration;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-import org.junit.Rule;
-import org.qi4j.test.util.DelTreeAfter;
-
-public class ContainsTest extends AbstractQi4jTest
-{
-
-   private static final File DATA_DIR = new File( "build/tmp/contains-test" );
-   @Rule
-   public final DelTreeAfter delTreeAfter = new DelTreeAfter( DATA_DIR );
-
-   @Override
-   public void assemble(ModuleAssembly module) throws AssemblyException
-   {
-       module.services( FileConfigurationService.class );
-      ModuleAssembly prefModule = module.layer().module( "PrefModule" );
-      prefModule.entities( NativeConfiguration.class ).visibleIn(Visibility.application);
-      prefModule.forMixin( NativeConfiguration.class ).declareDefaults().dataDirectory().set( DATA_DIR.getAbsolutePath() );
-      new EntityTestAssembler().assemble( prefModule );
-
-      module.entities( ExampleEntity.class );
-      module.values( ExampleValue.class, ExampleValue2.class );
-
-      EntityTestAssembler testAss = new EntityTestAssembler();
-      testAss.assemble(module);
-
-      RdfNativeSesameStoreAssembler rdfAssembler = new RdfNativeSesameStoreAssembler();
-      rdfAssembler.assemble(module);
-   }
-
-   @Test
-   public void simpleContainsSuccessTest() throws Exception
-   {
-      ExampleEntity result = this.performContainsStringTest(
-            new HashSet<String>(Arrays.asList(
-                  ContainsAllTest.TEST_STRING_1, ContainsAllTest.TEST_STRING_2, ContainsAllTest.TEST_STRING_3
-                  )),
-            ContainsAllTest.TEST_STRING_3
-            );
-
-      Assert.assertTrue("The entity must have been found", result != null);
-   }
-
-   @Test
-   public void simpleContainsSuccessFailTest() throws Exception
-   {
-      ExampleEntity result = this.performContainsStringTest(
-            new HashSet<String>(Arrays.asList(
-                  ContainsAllTest.TEST_STRING_1, ContainsAllTest.TEST_STRING_2, ContainsAllTest.TEST_STRING_3
-                  )),
-            ContainsAllTest.TEST_STRING_4
-            );
-
-      Assert.assertTrue("The entity must not have been found", result == null);
-   }
-
-   @Test(expected = IllegalArgumentException.class)
-   public void simplecontainsNullTest() throws Exception
-   {
-      this.performContainsStringTest(
-            new HashSet<String>(Arrays.asList(
-                  ContainsAllTest.TEST_STRING_1, ContainsAllTest.TEST_STRING_2, ContainsAllTest.TEST_STRING_3
-                  )),
-            null
-            );
-
-   }
-
-   @Test
-   public void simpleContainsStringValueSuccessTest() throws Exception
-   {
-      ExampleEntity result = this.performContainsStringValueTest(
-            new HashSet<String>(Arrays.asList(
-                  ContainsAllTest.TEST_STRING_1, ContainsAllTest.TEST_STRING_2, ContainsAllTest.TEST_STRING_3
-                  )),
-            ContainsAllTest.TEST_STRING_3
-            );
-
-      Assert.assertTrue("The entity must have been found", result != null);
-   }
-
-   @Test
-   public void simpleContainsStringValueFailTest() throws Exception
-   {
-      ExampleEntity result = this.performContainsStringTest(
-            new HashSet<String>(Arrays.asList(
-                  ContainsAllTest.TEST_STRING_1, ContainsAllTest.TEST_STRING_2, ContainsAllTest.TEST_STRING_3
-                  )),
-            ContainsAllTest.TEST_STRING_4
-            );
-
-      Assert.assertTrue("The entity must not have been found", result == null);
-   }
-
-   private ExampleEntity findEntity(String string)
-   {
-      QueryBuilder<ExampleEntity> builder = this.module.newQueryBuilder(ExampleEntity.class);
-
-      builder = builder.where(QueryExpressions.contains(
-            QueryExpressions.templateFor(ExampleEntity.class).strings(),
-            string
-            )
-      );
-      return this.module.currentUnitOfWork().newQuery( builder ).find();
-
-   }
-
-   private ExampleEntity findEntityBasedOnValueString(String valueString)
-   {
-      ValueBuilder<ExampleValue2> vBuilder = this.module.newValueBuilder(ExampleValue2.class);
-         vBuilder.prototype().stringProperty().set(valueString);
-
-         ValueBuilder<ExampleValue> vBuilder2 = this.module.newValueBuilder(ExampleValue.class);
-         vBuilder2.prototype().valueProperty().set(vBuilder.newInstance());
-
-      return this.createComplexQuery(vBuilder2.newInstance()).find();
-   }
-
-   private Query<ExampleEntity> createComplexQuery(ExampleValue value)
-   {
-      QueryBuilder<ExampleEntity> builder = this.module.newQueryBuilder(ExampleEntity.class);
-      builder = builder.where(QueryExpressions.contains(
-            QueryExpressions.templateFor(ExampleEntity.class).complexValue(),
-            value
-            )
-         );
-
-      return this.module.currentUnitOfWork().newQuery( builder);
-   }
-
-   private ExampleEntity performContainsStringTest(Set<String> entityStrings, String queryableString) throws Exception
-   {
-      UnitOfWork creatingUOW = this.module.newUnitOfWork();
-      String[] entityStringsArray = new String[entityStrings.size()];
-      ContainsAllTest.createEntityWithStrings(creatingUOW, this.module, entityStrings.toArray(entityStringsArray));
-      creatingUOW.complete();
-
-      UnitOfWork queryingUOW = this.module.newUnitOfWork();
-      try
-      {
-         ExampleEntity entity = this.findEntity(queryableString);
-         return entity;
-      }
-      finally
-      {
-         queryingUOW.discard();
-      }
-   }
-
-   private ExampleEntity performContainsStringValueTest(Set<String> entityStrings, String queryableString) throws Exception
-   {
-      UnitOfWork creatingUOW = this.module.newUnitOfWork();
-      String[] entityStringsArray = new String[entityStrings.size()];
-      ContainsAllTest.createEntityWithComplexValues(creatingUOW, this.module, entityStrings.toArray(entityStringsArray));
-      creatingUOW.complete();
-
-      UnitOfWork queryingUOW = this.module.newUnitOfWork();
-      try
-      {
-         ExampleEntity entity = this.findEntityBasedOnValueString(queryableString);
-         return entity;
-      }
-      finally
-      {
-         queryingUOW.discard();
-      }
-   }
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/DocumentationSupport.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/DocumentationSupport.java
deleted file mode 100644
index ec12ce9..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/DocumentationSupport.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.index.rdf;
-
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.rdf.assembly.RdfMemoryStoreAssembler;
-import org.qi4j.index.rdf.assembly.RdfNativeSesameStoreAssembler;
-import org.qi4j.index.rdf.assembly.RdfRdbmsSesameStoreAssembler;
-
-public class DocumentationSupport
-{
-
-    class InMemoryAssembler
-            implements Assembler
-    {
-
-        @Override
-        public void assemble( ModuleAssembly module )
-                throws AssemblyException
-        {
-            // START SNIPPET: memory
-            new RdfMemoryStoreAssembler().assemble( module );
-            // END SNIPPET: memory
-        }
-
-    }
-
-    class NativeMemoryAssembler
-            implements Assembler
-    {
-
-        @Override
-        public void assemble( ModuleAssembly module )
-                throws AssemblyException
-        {
-            // START SNIPPET: native
-            new RdfNativeSesameStoreAssembler().assemble( module );
-            // END SNIPPET: native
-        }
-
-    }
-
-    class RDBMSMemoryAssembler
-            implements Assembler
-    {
-
-        @Override
-        public void assemble( ModuleAssembly module )
-                throws AssemblyException
-        {
-            // START SNIPPET: rdbms
-            new RdfRdbmsSesameStoreAssembler().assemble( module );
-            // END SNIPPET: rdbms
-        }
-
-    }
-
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/RDFPerformanceTest.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/RDFPerformanceTest.java
deleted file mode 100644
index 2f0747d..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/RDFPerformanceTest.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.index.rdf;
-
-/**
- * JAVADOC
- */
-
-import java.io.File;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryExpressions;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.rdf.assembly.RdfNativeSesameStoreAssembler;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.library.rdf.repository.NativeConfiguration;
-import org.qi4j.spi.query.IndexExporter;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import org.junit.Rule;
-import org.qi4j.test.util.DelTreeAfter;
-
-public class RDFPerformanceTest extends AbstractQi4jTest
-{
-    private static final Logger LOG = LoggerFactory.getLogger( RDFPerformanceTest.class );
-    private static final File DATA_DIR = new File( "build/tmp/rdf-performance-test" );
-    @Rule
-    public final DelTreeAfter delTreeAfter = new DelTreeAfter( DATA_DIR );
-
-    public interface ExampleEntity extends EntityComposite
-    {
-        @UseDefaults
-        Property<String> someProperty();
-
-        ManyAssociation<ExampleEntity> manyAssoc();
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module ) throws AssemblyException
-    {
-        module.services( FileConfigurationService.class );
-        ModuleAssembly prefModule = module.layer().module( "PrefModule" );
-        prefModule.entities( NativeConfiguration.class ).visibleIn( Visibility.application );
-        prefModule.forMixin( NativeConfiguration.class ).declareDefaults().tripleIndexes().set( "spoc,cspo" );
-        prefModule.forMixin( NativeConfiguration.class ).declareDefaults().dataDirectory().set( DATA_DIR.getAbsolutePath() );
-        new EntityTestAssembler().assemble( prefModule );
-
-        module.entities( ExampleEntity.class );
-
-        EntityTestAssembler testAss = new EntityTestAssembler();
-        testAss.assemble( module );
-
-        Assembler rdfAssembler = new RdfNativeSesameStoreAssembler();
-        rdfAssembler.assemble( module );
-    }
-
-
-    private List<ExampleEntity> doCreate( int howMany )
-    {
-        List<ExampleEntity> result = new ArrayList<ExampleEntity>( howMany );
-
-        List<ExampleEntity> entities = new ArrayList<ExampleEntity>();
-        for (Integer x = 0; x < howMany; ++x)
-        {
-            ExampleEntity exampleEntity = this.module.currentUnitOfWork().newEntity( ExampleEntity.class, "entity" + x );
-
-            for (ExampleEntity entity : entities)
-            {
-                exampleEntity.manyAssoc().add( entity );
-            }
-
-            entities.add( exampleEntity );
-            if (entities.size() > 10)
-                entities.remove( 0 );
-
-            result.add( exampleEntity );
-        }
-
-        return result;
-    }
-
-    private void doRemoveAll( List<ExampleEntity> entities )
-    {
-        for (ExampleEntity entity : entities)
-        {
-            this.module.currentUnitOfWork().remove( this.module.currentUnitOfWork().get( entity ) );
-        }
-    }
-
-    private List<ExampleEntity> doList( int howMany )
-    {
-        List<ExampleEntity> list = new ArrayList<ExampleEntity>();
-        UnitOfWork uow = this.module.newUnitOfWork();
-        Iterator<ExampleEntity> iter = uow.newQuery( this.module.newQueryBuilder( ExampleEntity.class ) ).iterator();
-        int found = 0;
-        while (iter.hasNext())
-        {
-            found++;
-            ExampleEntity exampleEntity = iter.next();
-            if (exampleEntity != null)
-                list.add( exampleEntity );
-        }
-
-        uow.discard();
-
-        if (found != howMany)
-        {
-            LOG.warn( "Found " + found + " entities instead of " + howMany + "." );
-        }
-
-        return list;
-    }
-
-
-    private void doRemove( int howMany )
-    {
-        Iterator<ExampleEntity> iter = this.module.currentUnitOfWork().newQuery( this.module.newQueryBuilder( ExampleEntity.class )).maxResults( howMany ).iterator();
-        Integer removed = 0;
-        while (iter.hasNext())
-        {
-            this.module.currentUnitOfWork().remove( iter.next() );
-            ++removed;
-        }
-
-        if (removed != howMany)
-        {
-            LOG.warn( "Removed " + removed + " entities instead of " + howMany + "." );
-        }
-    }
-
-    private void performTest( int howMany ) throws Exception
-    {
-        long startTest = System.currentTimeMillis();
-
-        UnitOfWork creatingUOW = this.module.newUnitOfWork();
-        Long startingTime = System.currentTimeMillis();
-        List<ExampleEntity> entities = this.doCreate( howMany );
-        LOG.info( "Time to create " + howMany + " entities (ms): " + (System.currentTimeMillis() - startingTime) );
-
-        startingTime = System.currentTimeMillis();
-        creatingUOW.complete();
-        LOG.info( "Time to complete creation uow (ms): " + (System.currentTimeMillis() - startingTime) );
-
-
-        List<ExampleEntity> entityList = this.doList( howMany );
-
-        startingTime = System.currentTimeMillis();
-        UnitOfWork uow = this.module.newUnitOfWork();
-        for (int i = 0; i < 1000; i++)
-        {
-            Query<ExampleEntity> query = uow.newQuery( this.module.newQueryBuilder( ExampleEntity.class ).
-                    where( QueryExpressions.contains( QueryExpressions.templateFor( ExampleEntity.class ).manyAssoc(), uow.get( ExampleEntity.class, "entity50" ) ) ));
-            System.out.println(query.count());
-        }
-
-        long endTest = System.currentTimeMillis();
-        LOG.info( "Time to query " + howMany + " entities (ms): " + (endTest - startingTime) );
-
-        UnitOfWork deletingUOW = this.module.newUnitOfWork();
-        startingTime = System.currentTimeMillis();
-        this.doRemoveAll( entityList );
-//      this.doRemove(200);
-        LOG.info( "Time to delete " + howMany + " entities (ms): " + (System.currentTimeMillis() - startingTime) );
-
-        startingTime = System.currentTimeMillis();
-        deletingUOW.complete();
-
-        endTest = System.currentTimeMillis();
-
-        LOG.info( "time to complete deletion uow (ms): " + (endTest - startingTime) );
-
-        LOG.info( "time to complete test (ms): " + (endTest - startTest) );
-
-    }
-
-    @Test
-    public void dummy()
-    {
-        // Dummy test to make Maven happy
-    }
-
-    // @Test
-    public void performanceTest200() throws Exception
-    {
-        this.performTest( 200 );
-        this.performTest( 200 );
-        this.performTest( 200 );
-        this.performTest( 200 );
-        this.performTest( 200 );
-        this.performTest( 200 );
-        this.performTest( 200 );
-        this.performTest( 200 );
-
-        IndexExporter indexerExporter =
-                module.findService( IndexExporter.class ).get();
-        indexerExporter.exportReadableToStream( System.out );
-    }
-
-    @Ignore
-    @Test
-    public void performanceTest1000() throws Exception
-    {
-        this.performTest( 1000 );
-    }
-
-    @Ignore
-    @Test
-    public void performanceTest5000() throws Exception
-    {
-        this.performTest( 5000 );
-    }
-
-    @Ignore
-    @Test
-    public void performanceTest10000() throws Exception
-    {
-        this.performTest( 10000 );
-    }
-
-    @Ignore
-    @Test
-    public void performanceTest100000() throws Exception
-    {
-        this.performTest( 100000 );
-    }
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/RdfComplexQueryTest.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/RdfComplexQueryTest.java
deleted file mode 100644
index 2460d78..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/RdfComplexQueryTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.rdf;
-
-import org.junit.Ignore;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.library.rdf.entity.EntityTypeSerializer;
-import org.qi4j.library.rdf.repository.MemoryRepositoryService;
-import org.qi4j.test.indexing.AbstractComplexQueryTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-@Ignore( "RDF Index/Query do not support Complex Queries, ie. queries by 'example values'" )
-public class RdfComplexQueryTest
-        extends AbstractComplexQueryTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-            throws AssemblyException
-    {
-        super.assemble( module );
-        module.services( RdfIndexingEngineService.class ).instantiateOnStartup();
-        module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
-        module.objects( EntityStateSerializer.class, EntityTypeSerializer.class );
-        module.services( MemoryRepositoryService.class ).identifiedBy( "rdf-indexing" ).instantiateOnStartup();
-    }
-
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/RdfEntityFinderTest.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/RdfEntityFinderTest.java
deleted file mode 100644
index 8572664..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/RdfEntityFinderTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.index.rdf;
-
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.library.rdf.entity.EntityTypeSerializer;
-import org.qi4j.library.rdf.repository.MemoryRepositoryService;
-import org.qi4j.test.indexing.AbstractEntityFinderTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-public class RdfEntityFinderTest extends AbstractEntityFinderTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        module.objects( EntityStateSerializer.class, EntityTypeSerializer.class );
-        module.services( RdfIndexingEngineService.class ).instantiateOnStartup();
-        module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
-        module.services( MemoryRepositoryService.class ).identifiedBy( "rdf-indexing" ).instantiateOnStartup();
-        // module.services( NativeRdfRepositoryService.class ).identifiedBy( "rdf-indexing" );
-        // module.addComposites( NativeRdfConfiguration.class );
-    }
-}
\ No newline at end of file
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/RdfNamedQueryTest.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/RdfNamedQueryTest.java
deleted file mode 100644
index bdd2725..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/RdfNamedQueryTest.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.index.rdf;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Specification;
-import org.qi4j.index.rdf.query.RdfQueryParserFactory;
-import org.qi4j.index.rdf.query.SesameExpressions;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.library.rdf.entity.EntityTypeSerializer;
-import org.qi4j.library.rdf.repository.MemoryRepositoryService;
-import org.qi4j.test.indexing.AbstractNamedQueryTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-public class RdfNamedQueryTest extends AbstractNamedQueryTest
-{
-    @Override
-    protected String[] queryStrings()
-    {
-        return queryStrings;
-    }
-
-    @Override
-    protected Specification<Composite> createNamedQueryDescriptor( String queryName, String queryString )
-    {
-        return SesameExpressions.sparql( queryString );
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        module.services( MemoryRepositoryService.class, RdfQueryParserFactory.class ).instantiateOnStartup();
-        module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
-        module.objects( EntityStateSerializer.class, EntityTypeSerializer.class );
-        module.services( RdfIndexingEngineService.class );
-    }
-
-    private static String[] queryStrings =
-    {
-        "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Person>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n" + "\n" + "}", // script01
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Domain>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n" + "?entity ns1:name ?v0. \n"
-            + "FILTER (?v0 = \"Gaming\")\n" + "}", // script02
-
-        "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n" + "\n" + "}", // script03
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Person#> \n"
-            + "PREFIX ns2: <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Person>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n"
-            + "?entity ns1:placeOfBirth ?v0. \n" + "?v0 ns2:name ?v1. \n" + "FILTER (?v1 = \"Kuala Lumpur\")\n" + "}", // script04
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Person#> \n"
-            + "PREFIX ns2: <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Person>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n" + "?entity ns1:mother ?v0. \n"
-            + "?v0 ns1:placeOfBirth ?v1. \n" + "?v1 ns2:name ?v2. \n" + "FILTER (?v2 = \"Kuala Lumpur\")\n" + "}", // script05
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Person#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Person>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n"
-            + "?entity ns1:yearOfBirth ?v0. \n" + "FILTER (?v0 >= \"1973\")\n" + "}", // script06
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Person#> \n"
-            + "PREFIX ns2: <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n"
-            + "?entity ns1:yearOfBirth ?v0. \n" + "?entity ns1:placeOfBirth ?v1. \n" + "?v1 ns2:name ?v2. \n"
-            + "FILTER ((?v0 >= \"1900\") && (?v2 = \"Penang\"))\n" + "}", // script07
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Person#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Person>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n"
-            + "?entity ns1:yearOfBirth ?v0. \n" + "FILTER ((?v0 = \"1970\") || (?v0 = \"1975\"))\n" + "}", // script08
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Person#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Female>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n"
-            + "?entity ns1:yearOfBirth ?v0. \n" + "FILTER ((?v0 = \"1970\") || (?v0 = \"1975\"))\n" + "}", // script09
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Person#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Person>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n"
-            + "?entity ns1:yearOfBirth ?v0. \n" + "FILTER (!(?v0 = \"1975\"))\n" + "}", // script10
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Person#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Person>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n"
-            + "OPTIONAL {?entity ns1:email ?v0}. \n" + "FILTER (bound(?v0))\n" + "}", // script11
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Person#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Person>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n"
-            + "OPTIONAL {?entity ns1:email ?v0}. \n" + "FILTER (! bound(?v0))\n" + "}", // script12
-
-        "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Male#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Person>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n"
-            + "OPTIONAL {?entity ns1:wife ?v0}. \n" + "FILTER (bound(?v0))\n" + "}", // script13
-
-        "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Male#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Male>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n"
-            + "OPTIONAL {?entity ns1:wife ?v0}. \n" + "FILTER (! bound(?v0))\n" + "}", // script14
-
-        "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Male#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Person>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n"
-            + "OPTIONAL {?entity ns1:wife ?v0}. \n" + "FILTER (! bound(?v0))\n" + "}", // script15
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n" + "?entity ns1:name ?v0. \n"
-            + "\n" + "}", // script16
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n" + "?entity ns1:name ?v0. \n"
-            + "\n" + "} ", // script17
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n" + "?entity ns1:name ?v0. \n"
-            + "\n" + "}\n", // script18
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n" + "?entity ns1:name ?v0. \n"
-            + "FILTER (?v0 > \"D\")\n" + "} ", // script19
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Person#> \n"
-            + "PREFIX ns2: <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Person>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n"
-            + "?entity ns1:yearOfBirth ?v0. \n" + "?entity ns2:name ?v1. \n" + "FILTER (?v0 > \"1973\")\n" + "}\n"
-            , // script20
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Person#> \n"
-            + "PREFIX ns2: <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Person>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n"
-            + "?entity ns1:placeOfBirth ?v0. \n" + "?v0 ns2:name ?v1. \n" + "?entity ns1:yearOfBirth ?v2. \n" + "\n"
-            + "}", // script21
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n" + "?entity ns1:name ?v0. \n"
-            + "FILTER regex(?v0,\"J.*Doe\")\n" + "}", // script22
-
-        "", // script23
-
-        "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.indexing.model.Nameable#> \n"
-            + "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-            + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-            + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n" + "SELECT DISTINCT ?identity\n"
-            + "WHERE {\n" + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.indexing.model.Domain>. \n"
-            + "?entity rdf:type ?entityType. \n" + "?entity ns0:identity ?identity. \n" + "?entity ns1:name ?v0. \n"
-            + "FILTER (?v0 = ?domain)\n" + "}" // script24
-
-    };
-}
\ No newline at end of file
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/RdfQueryTest.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/RdfQueryTest.java
deleted file mode 100644
index d0e3a83..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/RdfQueryTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.index.rdf;
-
-import java.io.File;
-import org.junit.Ignore;
-import org.junit.Rule;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.rdf.query.RdfQueryParserFactory;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.library.rdf.entity.EntityTypeSerializer;
-import org.qi4j.library.rdf.repository.NativeConfiguration;
-import org.qi4j.library.rdf.repository.NativeRepositoryService;
-import org.qi4j.spi.query.EntityFinderException;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.indexing.AbstractQueryTest;
-import org.qi4j.test.util.DelTreeAfter;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-public class RdfQueryTest
-    extends AbstractQueryTest
-{
-
-    private static final File DATA_DIR = new File( "build/tmp/rdf-query-test" );
-    @Rule
-    public final DelTreeAfter delTreeAfter = new DelTreeAfter( DATA_DIR );
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        module.services( FileConfigurationService.class );
-        module.services( NativeRepositoryService.class, RdfQueryParserFactory.class ).instantiateOnStartup();
-        module.services( RdfIndexingEngineService.class ).instantiateOnStartup();
-        module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
-        module.objects( EntityStateSerializer.class, EntityTypeSerializer.class );
-
-        ModuleAssembly config = module.layer().module( "Config" );
-        config.entities( NativeConfiguration.class ).visibleIn( Visibility.layer );
-        config.forMixin( NativeConfiguration.class ).declareDefaults().dataDirectory().set( DATA_DIR.getAbsolutePath() );
-        new EntityTestAssembler().assemble( config );
-    }
-
-    @Test
-    @Ignore( "oneOf() Query Expression not supported by RDF Indexing" )
-    @Override
-    public void script23()
-        throws EntityFinderException
-    {
-        super.script23();
-    }
-
-    @Test
-    @Ignore( "Deep queries in complex values are not supported by RDF Indexing" )
-    @Override
-    public void script29()
-    {
-        super.script29();
-    }
-
-    @Test
-    @Ignore( "NamedAssociation are not supported by RDF Indexing" )
-    @Override
-    public void script35()
-    {
-        super.script35();
-    }
-
-    @Test
-    @Ignore( "NamedAssociation are not supported by RDF Indexing" )
-    @Override
-    public void script36()
-    {
-        super.script36();
-    }
-
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi173/Qi173IssueTest.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi173/Qi173IssueTest.java
deleted file mode 100644
index 94814d7..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi173/Qi173IssueTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.index.rdf.qi173;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.QueryExpressions;
-import org.qi4j.api.unitofwork.ConcurrentEntityModificationException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.rdf.assembly.RdfMemoryStoreAssembler;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import java.util.Iterator;
-
-import static org.qi4j.api.query.QueryExpressions.orderBy;
-
-public class Qi173IssueTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( CarEntity.class );
-        new RdfMemoryStoreAssembler().assemble( module );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Test
-    public void testPersistence()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            createCar( "Volvo", "S80", 2007 );
-            createCar( "Volvo", "C70", 2006 );
-            createCar( "Ford", "Transit", 2007 );
-            createCar( "Ford", "Mustang", 2007 );
-            createCar( "Ford", "Mustang", 2006 );
-            createCar( "Ford", "Mustang", 2005 );
-            uow.complete();
-        }
-        catch( ConcurrentEntityModificationException e )
-        {
-            // Can not happen.
-            e.printStackTrace();
-        }
-        catch( UnitOfWorkCompletionException e )
-        {
-            e.printStackTrace();
-        }
-
-        uow = module.newUnitOfWork();
-        QueryBuilder<Car> qb = module.newQueryBuilder( Car.class );
-        Car template = QueryExpressions.templateFor( Car.class );
-        qb = qb.where( QueryExpressions.eq( template.year(), 2007 ) );
-
-        Query<Car> query = uow.newQuery( qb );
-        query.orderBy( orderBy( template.manufacturer() ), orderBy( template.model() ) );
-        Iterator<Car> cars = query.iterator();
-        Assert.assertTrue( cars.hasNext() );
-        Car car1 = cars.next();
-        Assert.assertEquals( car1.manufacturer().get(), "Ford" );
-        Assert.assertEquals( car1.model().get(), "Mustang" );
-        Assert.assertEquals( (int) car1.year().get(), 2007 );
-        Car car2 = cars.next();
-        Assert.assertEquals( car2.manufacturer().get(), "Ford" );
-        Assert.assertEquals( car2.model().get(), "Transit" );
-        Assert.assertEquals( (int) car2.year().get(), 2007 );
-        Car car3 = cars.next();
-        Assert.assertEquals( car3.manufacturer().get(), "Volvo" );
-        Assert.assertEquals( car3.model().get(), "S80" );
-        Assert.assertEquals( (int) car3.year().get(), 2007 );
-        for( Car car : query )
-        {
-            System.out.println( car.manufacturer().get() + " " + car.model().get() + ", " + car.year().get() );
-        }
-
-        uow.discard();
-    }
-
-    private String createCar( String manufacturer, String model, int year )
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        EntityBuilder<Car> builder = uow.newEntityBuilder( Car.class );
-        Car prototype = builder.instanceFor( Car.class );
-        prototype.manufacturer().set( manufacturer );
-        prototype.model().set( model );
-        prototype.year().set( year );
-        CarEntity entity = (CarEntity) builder.newInstance();
-        return entity.identity().get();
-    }
-
-    public interface CarEntity
-        extends Car, EntityComposite
-    {
-    }
-
-    public static interface Car
-    {
-        Property<String> manufacturer();
-
-        Property<String> model();
-
-        Property<Integer> year();
-    }
-}
\ No newline at end of file
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/AbstractIssueTest.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/AbstractIssueTest.java
deleted file mode 100644
index 2cc903e..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/AbstractIssueTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.index.rdf.qi64;
-
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.rdf.repository.MemoryRepositoryService;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-public abstract class AbstractIssueTest
-    extends AbstractQi4jTest
-{
-    private static final String DEFAULT_ACCOUNT_NAME = "qi4j";
-
-    /**
-     * Creates a new qi4j account.
-     *
-     * @return The new account identity.
-     *
-     * @throws org.qi4j.api.unitofwork.UnitOfWorkCompletionException
-     *          Thrown if creational fail.
-     */
-    protected final String newQi4jAccount()
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork work = module.newUnitOfWork();
-        EntityBuilder<AccountComposite> entityBuilder = work.newEntityBuilder( AccountComposite.class );
-        AccountComposite accountComposite = entityBuilder.instance();
-        accountComposite.name().set( DEFAULT_ACCOUNT_NAME );
-        accountComposite = entityBuilder.newInstance();
-
-        String identity = accountComposite.identity().get();
-        work.complete();
-        return identity;
-    }
-
-    public final void assemble( ModuleAssembly aModuleAssembly )
-        throws AssemblyException
-    {
-        aModuleAssembly.entities( AccountComposite.class );
-        new EntityTestAssembler().assemble( aModuleAssembly );
-        aModuleAssembly.services( MemoryRepositoryService.class );
-        onAssemble( aModuleAssembly );
-    }
-
-    protected abstract void onAssemble( ModuleAssembly aModuleAssembly )
-        throws AssemblyException;
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/Account.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/Account.java
deleted file mode 100644
index 48c4972..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/Account.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.index.rdf.qi64;
-
-public interface Account
-    extends HasName
-{
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/AccountComposite.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/AccountComposite.java
deleted file mode 100644
index f1ebfd8..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/AccountComposite.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.index.rdf.qi64;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.index.rdf.qi66.Account;
-
-public interface AccountComposite
-    extends EntityComposite, Account
-{
-}
\ No newline at end of file
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/HasName.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/HasName.java
deleted file mode 100644
index e71112f..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/HasName.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.index.rdf.qi64;
-
-import org.qi4j.api.property.Property;
-
-public interface HasName
-{
-    Property<String> name();
-}
\ No newline at end of file
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationMandatory/AccountService.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationMandatory/AccountService.java
deleted file mode 100644
index c672a7e..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationMandatory/AccountService.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.index.rdf.qi64.withPropagationMandatory;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.unitofwork.concern.UnitOfWorkPropagation;
-import org.qi4j.index.rdf.qi64.AccountComposite;
-
-import static org.qi4j.api.unitofwork.concern.UnitOfWorkPropagation.Propagation.MANDATORY;
-import static org.qi4j.index.rdf.qi64.withPropagationMandatory.AccountService.AccountServiceMixin;
-
-@Mixins( AccountServiceMixin.class )
-public interface AccountService
-{
-    @UnitOfWorkPropagation( MANDATORY )
-    AccountComposite getAccountById( String anId );
-
-    public class AccountServiceMixin
-        implements AccountService
-    {
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        @Structure
-        Module module;
-
-        public AccountComposite getAccountById( String anId )
-        {
-            // Use current unit of work
-            UnitOfWork work = uowf.currentUnitOfWork();
-
-            AccountComposite account = work.get( AccountComposite.class, anId );
-
-            if( account != null )
-            {
-                // Required to get around QI-66 bug
-                account.name().get();
-            }
-
-            return account;
-        }
-    }
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationMandatory/AccountServiceComposite.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationMandatory/AccountServiceComposite.java
deleted file mode 100644
index e1a5e94..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationMandatory/AccountServiceComposite.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.index.rdf.qi64.withPropagationMandatory;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.unitofwork.concern.UnitOfWorkConcern;
-
-@Concerns( UnitOfWorkConcern.class )
-public interface AccountServiceComposite
-    extends ServiceComposite, AccountService
-{
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationMandatory/IssueTest.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationMandatory/IssueTest.java
deleted file mode 100644
index 2e63e4b..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationMandatory/IssueTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.index.rdf.qi64.withPropagationMandatory;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.rdf.qi64.AbstractIssueTest;
-import org.qi4j.index.rdf.qi64.AccountComposite;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-public final class IssueTest
-    extends AbstractIssueTest
-{
-    private AccountService accountService;
-
-    @Before
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-
-        accountService = module.findService( AccountService.class ).get();
-    }
-
-    @Test( expected = IllegalStateException.class )
-    public final void testUnitOfWorkWithUnitOfWorkNotInitialized()
-        throws Throwable
-    {
-        // Bootstrap the account
-        String id = newQi4jAccount();
-
-        // Make sure there's no unit of work
-        assertNull( module.currentUnitOfWork() );
-
-        accountService.getAccountById( id );
-    }
-
-    @Test
-    public final void testUnitOfWorkWithUnitOfWorkInitialized()
-        throws Throwable
-    {
-        // Bootstrap the account
-        String id = newQi4jAccount();
-
-        // Make sure there's no unit of work
-        assertFalse( module.isUnitOfWorkActive() );
-
-        UnitOfWork parentUnitOfWork = module.newUnitOfWork();
-
-        AccountComposite account = accountService.getAccountById( id );
-        assertNotNull( account );
-
-        UnitOfWork currentUnitOfWork = module.currentUnitOfWork();
-        assertEquals( parentUnitOfWork, currentUnitOfWork );
-
-        assertTrue( currentUnitOfWork.isOpen() );
-
-        // Close the parent unit of work
-        parentUnitOfWork.complete();
-    }
-
-    protected final void onAssemble( ModuleAssembly aModuleAssembly )
-        throws AssemblyException
-    {
-        aModuleAssembly.services( AccountServiceComposite.class );
-    }
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequired/AccountService.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequired/AccountService.java
deleted file mode 100644
index f5b6676..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequired/AccountService.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.index.rdf.qi64.withPropagationRequired;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.unitofwork.concern.UnitOfWorkPropagation;
-import org.qi4j.index.rdf.qi64.AccountComposite;
-
-import static org.qi4j.index.rdf.qi64.withPropagationRequired.AccountService.AccountServiceMixin;
-
-@Mixins( AccountServiceMixin.class )
-public interface AccountService
-{
-    @UnitOfWorkPropagation
-    AccountComposite getAccountById( String anId );
-
-    public class AccountServiceMixin
-        implements AccountService
-    {
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        @Structure
-        Module module;
-
-        public AccountComposite getAccountById( String anId )
-        {
-            // Use current unit of work
-            UnitOfWork work = uowf.currentUnitOfWork();
-
-            AccountComposite account = work.get( AccountComposite.class, anId );
-
-            if( account != null )
-            {
-                // Required to get around QI-66 bug
-                account.name().get();
-            }
-
-            return account;
-        }
-    }
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequired/AccountServiceComposite.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequired/AccountServiceComposite.java
deleted file mode 100644
index 941e12d..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequired/AccountServiceComposite.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.index.rdf.qi64.withPropagationRequired;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.unitofwork.concern.UnitOfWorkConcern;
-
-@Concerns( UnitOfWorkConcern.class )
-public interface AccountServiceComposite
-    extends ServiceComposite, AccountService
-{
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequired/IssueTest.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequired/IssueTest.java
deleted file mode 100644
index b0adb1c..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequired/IssueTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.index.rdf.qi64.withPropagationRequired;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.rdf.qi64.AbstractIssueTest;
-import org.qi4j.index.rdf.qi64.AccountComposite;
-
-import static org.junit.Assert.*;
-
-public final class IssueTest
-    extends AbstractIssueTest
-{
-    private AccountService accountService;
-
-    @Before
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-
-        accountService = module.findService( AccountService.class ).get();
-    }
-
-    @Test
-    public final void testUnitOfWorkWithUnitOfWorkNotInitialized()
-        throws Throwable
-    {
-        // Bootstrap the account
-        String id = newQi4jAccount();
-
-        // Make sure there's no unit of work
-        assertFalse( module.isUnitOfWorkActive() );
-
-        AccountComposite account = accountService.getAccountById( id );
-        assertNotNull( account );
-
-        assertFalse( module.isUnitOfWorkActive() );
-    }
-
-    @Test
-    public final void testUnitOfWorkWithUnitOfWorkInitialized()
-        throws Throwable
-    {
-        // Bootstrap the account
-        String id = newQi4jAccount();
-
-        // Make sure there's no unit of work
-        assertFalse( module.isUnitOfWorkActive() );
-
-        UnitOfWork parentUnitOfWork = module.newUnitOfWork();
-
-        AccountComposite account = accountService.getAccountById( id );
-        assertNotNull( account );
-
-        UnitOfWork currentUnitOfWork = module.currentUnitOfWork();
-        assertEquals( parentUnitOfWork, currentUnitOfWork );
-
-        assertTrue( currentUnitOfWork.isOpen() );
-
-        // Close the parent unit of work
-        parentUnitOfWork.complete();
-    }
-
-    @Override
-    public final void onAssemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( AccountServiceComposite.class );
-    }
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequiresNew/AccountService.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequiresNew/AccountService.java
deleted file mode 100644
index 209b6cb..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequiresNew/AccountService.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.index.rdf.qi64.withPropagationRequiresNew;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.unitofwork.concern.UnitOfWorkPropagation;
-import org.qi4j.index.rdf.qi64.AccountComposite;
-
-import static org.qi4j.index.rdf.qi64.withPropagationRequiresNew.AccountService.AccountServiceMixin;
-
-@Mixins( AccountServiceMixin.class )
-public interface AccountService
-{
-    @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRES_NEW )
-    AccountComposite getAccountById( String anId );
-
-    public class AccountServiceMixin
-        implements AccountService
-    {
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        @Structure
-        Module module;
-
-        public AccountComposite getAccountById( String anId )
-        {
-            // Use current unit of work
-            UnitOfWork work = uowf.currentUnitOfWork();
-
-            AccountComposite account = work.get( AccountComposite.class, anId );
-
-            if( account != null )
-            {
-                // Required to get around QI-66 bug
-                account.name().get();
-            }
-
-            return account;
-        }
-    }
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequiresNew/AccountServiceComposite.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequiresNew/AccountServiceComposite.java
deleted file mode 100644
index 2040cdb..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequiresNew/AccountServiceComposite.java
+++ /dev/null
@@ -1,29 +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.qi4j.index.rdf.qi64.withPropagationRequiresNew;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.unitofwork.concern.UnitOfWorkConcern;
-
-@Concerns( UnitOfWorkConcern.class )
-public interface AccountServiceComposite
-    extends ServiceComposite, AccountService
-{
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequiresNew/IssueTest.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequiresNew/IssueTest.java
deleted file mode 100644
index 2f3df98..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi64/withPropagationRequiresNew/IssueTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.index.rdf.qi64.withPropagationRequiresNew;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.rdf.qi64.AbstractIssueTest;
-import org.qi4j.index.rdf.qi64.AccountComposite;
-
-import static org.junit.Assert.*;
-
-public class IssueTest
-    extends AbstractIssueTest
-{
-    private AccountService accountService;
-
-    @Before
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-
-        accountService = module.findService( AccountService.class ).get();
-    }
-
-    @Test
-    public final void testUnitOfWorkNotInitialized()
-        throws Throwable
-    {
-        // Bootstrap the account
-        String id = newQi4jAccount();
-
-        // Make sure there's no unit of work
-        assertFalse( module.isUnitOfWorkActive() );
-
-        AccountComposite account = accountService.getAccountById( id );
-        assertNotNull( account );
-
-        assertFalse( module.isUnitOfWorkActive() );
-    }
-
-    @Test
-    public final void testUnitOfWorkInitialized()
-        throws Throwable
-    {
-        // Bootstrap the account
-        String id = newQi4jAccount();
-
-        // Make sure there's no unit of work
-        assertFalse( module.isUnitOfWorkActive() );
-
-        UnitOfWork parentUnitOfWork = module.newUnitOfWork();
-
-        AccountComposite account = accountService.getAccountById( id );
-        assertNotNull( account );
-
-        UnitOfWork currentUnitOfWork = module.currentUnitOfWork();
-        assertEquals( parentUnitOfWork, currentUnitOfWork );
-
-        assertTrue( currentUnitOfWork.isOpen() );
-
-        // Close the parent unit of work
-        parentUnitOfWork.complete();
-    }
-
-    protected final void onAssemble( ModuleAssembly aModuleAssembly )
-        throws AssemblyException
-    {
-        aModuleAssembly.services( AccountServiceComposite.class );
-    }
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi66/Account.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi66/Account.java
deleted file mode 100644
index e9e0f74..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi66/Account.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.index.rdf.qi66;
-
-public interface Account
-    extends HasName
-{
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi66/AccountComposite.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi66/AccountComposite.java
deleted file mode 100644
index c39ec18..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi66/AccountComposite.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.index.rdf.qi66;
-
-import org.qi4j.api.entity.EntityComposite;
-
-public interface AccountComposite
-    extends EntityComposite, Account
-{
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi66/HasName.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi66/HasName.java
deleted file mode 100644
index bc208f4..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi66/HasName.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.index.rdf.qi66;
-
-import org.qi4j.api.property.Property;
-
-public interface HasName
-{
-    Property<String> name();
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi66/Qi66IssueTest.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi66/Qi66IssueTest.java
deleted file mode 100644
index b16111d..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi66/Qi66IssueTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.index.rdf.qi66;
-
-import org.junit.Test;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.rdf.query.RdfQueryParserFactory;
-import org.qi4j.index.rdf.query.RdfQueryService;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.library.rdf.entity.EntityTypeSerializer;
-import org.qi4j.library.rdf.repository.MemoryRepositoryService;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-/**
- * Test for Qi-66
- */
-public class Qi66IssueTest
-    extends AbstractQi4jTest
-{
-    private static final String ACCOUNT_NAME = "qi4j";
-
-    @Test
-    public final void testCompleteAfterFind()
-        throws Exception
-    {
-        String accountIdentity = newQi4jAccount();
-
-        UnitOfWork work = module.newUnitOfWork();
-        AccountComposite account = work.get( AccountComposite.class, accountIdentity );
-        assertNotNull( account );
-
-        try
-        {
-            work.complete();
-        }
-        catch( Throwable e )
-        {
-            e.printStackTrace();
-            fail( "No exception can be thrown." );
-        }
-    }
-
-    /**
-     * Creates a new qi4j account.
-     *
-     * @return The identity of qi4j account.
-     *
-     * @throws UnitOfWorkCompletionException Thrown if creational fail.
-     */
-    private String newQi4jAccount()
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork work = module.newUnitOfWork();
-        EntityBuilder<AccountComposite> entityBuilder = work.newEntityBuilder( AccountComposite.class );
-        AccountComposite accountComposite = entityBuilder.instance();
-        accountComposite.name().set( ACCOUNT_NAME );
-        accountComposite = entityBuilder.newInstance();
-        String accoutnIdentity = accountComposite.identity().get();
-        work.complete();
-
-        return accoutnIdentity;
-    }
-
-    public final void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( AccountComposite.class );
-        new EntityTestAssembler().assemble( module );
-        module.services( RdfQueryService.class,
-                         RdfQueryParserFactory.class,
-                         MemoryRepositoryService.class );
-        module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
-        module.objects( EntityStateSerializer.class, EntityTypeSerializer.class );
-    }
-}
diff --git a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi95/Qi95IssueTest.java b/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi95/Qi95IssueTest.java
deleted file mode 100644
index 535a9ad..0000000
--- a/extensions/indexing-rdf/src/test/java/org/qi4j/index/rdf/qi95/Qi95IssueTest.java
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Copyright 2008 Richard Wallace. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.rdf.qi95;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import org.junit.Rule;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.QueryBuilderFactory;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.bootstrap.*;
-import org.qi4j.entitystore.jdbm.JdbmConfiguration;
-import org.qi4j.entitystore.jdbm.assembly.JdbmEntityStoreAssembler;
-import org.qi4j.index.rdf.assembly.RdfMemoryStoreAssembler;
-import org.qi4j.index.rdf.assembly.RdfNativeSesameStoreAssembler;
-import org.qi4j.library.rdf.repository.NativeConfiguration;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.util.DelTreeAfter;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-import static org.junit.Assert.assertTrue;
-
-public class Qi95IssueTest
-{
-
-    private static final File DATA_DIR = new File( "build/tmp/qi95-issue-test" );
-    @Rule
-    public final DelTreeAfter delTreeAfter = new DelTreeAfter( DATA_DIR );
-
-    @Test
-    public void canCreateAndQueryWithNativeRdfAndJdbm()
-        throws Exception
-    {
-        Application application = createApplication( nativeRdf, jdbmStore, domain );
-        try
-        {
-            application.activate();
-            Module domain = application.findModule( "Domain", "Domain" );
-            UnitOfWorkFactory unitOfWorkFactory = domain;
-            createABunchOfStuffAndDoQueries( unitOfWorkFactory, domain );
-        }
-        finally
-        {
-            application.passivate();
-        }
-    }
-
-    @Test
-    public void canCreateAndQueryWithAllInMemory()
-        throws Exception
-    {
-        Application application = createApplication( inMemoryRdf, inMemoryStore, domain );
-        try
-        {
-            application.activate();
-            Module domain = application.findModule( "Domain", "Domain" );
-            UnitOfWorkFactory unitOfWorkFactory = domain;
-            createABunchOfStuffAndDoQueries( unitOfWorkFactory, domain );
-        }
-        finally
-        {
-            application.passivate();
-        }
-    }
-
-    @Test
-    public void canCreateAndQueryWithNativeRdfWithInMemoryStore()
-        throws Exception
-    {
-        Application application = createApplication( nativeRdf, inMemoryStore, domain );
-        try
-        {
-            application.activate();
-            Module domain = application.findModule( "Domain", "Domain" );
-            UnitOfWorkFactory unitOfWorkFactory = domain;
-            createABunchOfStuffAndDoQueries( unitOfWorkFactory, domain );
-        }
-        finally
-        {
-            application.passivate();
-        }
-    }
-
-    @Test
-    public void canCreateAndQueryWithInMemoryRdfWithJdbm()
-        throws Exception
-    {
-        Application application = createApplication( inMemoryRdf, jdbmStore, domain );
-        try
-        {
-            application.activate();
-
-            Module domain = application.findModule( "Domain", "Domain" );
-            UnitOfWorkFactory unitOfWorkFactory = domain;
-            createABunchOfStuffAndDoQueries( unitOfWorkFactory, domain );
-        }
-        finally
-        {
-            application.passivate();
-        }
-    }
-
-    public void createABunchOfStuffAndDoQueries( UnitOfWorkFactory unitOfWorkFactory,
-                                                 QueryBuilderFactory queryBuilderFactory
-    )
-        throws Exception
-    {
-        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
-        newItemType( uow, "Band" );
-        newItemType( uow, "Bracelet" );
-        newItemType( uow, "Necklace" );
-        uow.complete();
-
-        uow = unitOfWorkFactory.newUnitOfWork();
-        QueryBuilder<ItemType> qb = queryBuilderFactory.newQueryBuilder( ItemType.class );
-        Iterable<ItemType> initialList = copyOf( uow.newQuery( qb ));
-
-        assertTrue( "Band is not in the initial list", hasItemTypeNamed( "Band", initialList ) );
-        assertTrue( "Bracelet is not in the initial list", hasItemTypeNamed( "Bracelet", initialList ) );
-        assertTrue( "Necklace is not in the initial list", hasItemTypeNamed( "Necklace", initialList ) );
-
-        newItemType( uow, "Watch" );
-        uow.complete();
-
-        uow = unitOfWorkFactory.newUnitOfWork();
-        qb = queryBuilderFactory.newQueryBuilder( ItemType.class );
-        Iterable<ItemType> listAfterFirstQueryAndAdd = copyOf( uow.newQuery( qb ) );
-
-        assertTrue( "Band is not in the list after the first query and add", hasItemTypeNamed( "Band", listAfterFirstQueryAndAdd ) );
-        assertTrue( "Bracelet is not in the list after the first query and add", hasItemTypeNamed( "Bracelet", listAfterFirstQueryAndAdd ) );
-        assertTrue( "Necklace is not in the list after the first query and add", hasItemTypeNamed( "Necklace", listAfterFirstQueryAndAdd ) );
-        assertTrue( "Watch is not in the list after the first query and add", hasItemTypeNamed( "Watch", listAfterFirstQueryAndAdd ) );
-
-        newItemType( uow, "Ear ring" );
-        uow.complete();
-
-        uow = unitOfWorkFactory.newUnitOfWork();
-        Iterable<ItemType> finalList = copyOf( uow.newQuery( qb ) );
-        assertTrue( "Band is not in the final list", hasItemTypeNamed( "Band", finalList ) );
-        assertTrue( "Bracelet is not in the final list", hasItemTypeNamed( "Bracelet", finalList ) );
-        assertTrue( "Necklace is not in the final list", hasItemTypeNamed( "Necklace", finalList ) );
-        assertTrue( "Watch is not in the final list", hasItemTypeNamed( "Watch", finalList ) );
-        assertTrue( "Ear ring is not in the final list", hasItemTypeNamed( "Ear ring", finalList ) );
-        uow.complete();
-    }
-
-    private Application createApplication( final ModuleAssemblyBuilder queryServiceModuleBuilder,
-                                              final ModuleAssemblyBuilder entityStoreModuleBuilder,
-                                              final LayerAssemblyBuilder domainLayerBuilder
-    )
-        throws AssemblyException
-    {
-        Energy4Java qi4j = new Energy4Java();
-        Application application = qi4j.newApplication( new ApplicationAssembler()
-        {
-            @Override
-            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-                throws AssemblyException
-            {
-                ApplicationAssembly applicationAssembly = applicationFactory.newApplicationAssembly();
-
-                LayerAssembly configLayer = applicationAssembly.layer( "Config" );
-                configModule.buildModuleAssembly( configLayer, "Configuration" );
-
-                LayerAssembly infrastructureLayer = applicationAssembly.layer( "Infrastructure" );
-                infrastructureLayer.uses( configLayer );
-
-                queryServiceModuleBuilder.buildModuleAssembly( infrastructureLayer, "Query Service" );
-                entityStoreModuleBuilder.buildModuleAssembly( infrastructureLayer, "Entity Store" );
-
-                LayerAssembly domainLayer = domainLayerBuilder.buildLayerAssembly( applicationAssembly );
-                domainLayer.uses( infrastructureLayer );
-                return applicationAssembly;
-            }
-        } );
-        return application;
-    }
-
-    interface LayerAssemblyBuilder
-    {
-        LayerAssembly buildLayerAssembly( ApplicationAssembly appAssembly )
-            throws AssemblyException;
-    }
-
-    interface ModuleAssemblyBuilder
-    {
-        ModuleAssembly buildModuleAssembly( LayerAssembly layer, String name )
-            throws AssemblyException;
-    }
-
-    final ModuleAssemblyBuilder nativeRdf = new ModuleAssemblyBuilder()
-    {
-        @Override
-        public ModuleAssembly buildModuleAssembly( LayerAssembly layer, String name )
-            throws AssemblyException
-        {
-            return addModule( layer, name, new RdfNativeSesameStoreAssembler() );
-        }
-    };
-
-    final ModuleAssemblyBuilder inMemoryStore = new ModuleAssemblyBuilder()
-    {
-        @Override
-        public ModuleAssembly buildModuleAssembly( LayerAssembly layer, String name )
-            throws AssemblyException
-        {
-            return addModule( layer, name, new EntityTestAssembler().visibleIn( Visibility.application ) );
-        }
-    };
-
-    final ModuleAssemblyBuilder inMemoryRdf = new ModuleAssemblyBuilder()
-    {
-        @Override
-        public ModuleAssembly buildModuleAssembly( LayerAssembly layer, String name )
-            throws AssemblyException
-        {
-            return addModule( layer, name, new RdfMemoryStoreAssembler() );
-        }
-    };
-
-    final ModuleAssemblyBuilder jdbmStore = new ModuleAssemblyBuilder()
-    {
-        @Override
-        public ModuleAssembly buildModuleAssembly( LayerAssembly layer, String name )
-            throws AssemblyException
-        {
-            return addModule( layer, name, jdbmEntityStoreAssembler() );
-        }
-    };
-
-    final ModuleAssemblyBuilder configModule = new ModuleAssemblyBuilder()
-    {
-        @Override
-        public ModuleAssembly buildModuleAssembly( LayerAssembly layer, String name )
-            throws AssemblyException
-        {
-            return addModule( layer, name, entityStoreConfigAssembler() );
-        }
-    };
-
-    final LayerAssemblyBuilder domain = new LayerAssemblyBuilder()
-    {
-        @Override
-        public LayerAssembly buildLayerAssembly( ApplicationAssembly appAssembly )
-            throws AssemblyException
-        {
-            LayerAssembly domainLayer = appAssembly.layer( "Domain" );
-            addModule( domainLayer, "Domain", new Assembler()
-            {
-                @Override
-                @SuppressWarnings( "unchecked" )
-                public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-                {
-                    module.entities( ItemTypeEntity.class );
-                }
-            } );
-            return domainLayer;
-        }
-    };
-
-    private Assembler entityStoreConfigAssembler()
-    {
-        return new Assembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                new EntityTestAssembler().assemble( module );
-
-                module.entities( NativeConfiguration.class ).visibleIn( Visibility.application );
-                module.forMixin( NativeConfiguration.class )
-                    .declareDefaults()
-                    .dataDirectory()
-                    .set( rdfDirectory().getAbsolutePath() );
-
-                module.entities( JdbmConfiguration.class ).visibleIn( Visibility.application );
-                module.forMixin( JdbmConfiguration.class )
-                    .declareDefaults()
-                    .file()
-                    .set( jdbmDirectory().getAbsolutePath() );
-            }
-        };
-    }
-
-    private Assembler jdbmEntityStoreAssembler()
-    {
-        return new Assembler()
-        {
-            @Override
-            @SuppressWarnings( "unchecked" )
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                new OrgJsonValueSerializationAssembler().assemble( module );
-                new JdbmEntityStoreAssembler().visibleIn( Visibility.application ).assemble( module );
-            }
-        };
-    }
-
-    private ModuleAssembly addModule( LayerAssembly layerAssembly, String name, Assembler assembler )
-        throws AssemblyException
-    {
-        ModuleAssembly moduleAssembly = layerAssembly.module( name );
-        assembler.assemble( moduleAssembly );
-        return moduleAssembly;
-    }
-
-    private File rdfDirectory()
-    {
-        return createTempDirectory( "rdf-index" );
-    }
-
-    private File jdbmDirectory()
-    {
-        return createTempDirectory( "jdbm-store" );
-    }
-
-    private File createTempDirectory( String name )
-    {
-        File t = new File( DATA_DIR, name );
-        t.mkdirs();
-        return t;
-    }
-
-    boolean hasItemTypeNamed( String name, Iterable<ItemType> list )
-    {
-        for( ItemType i : list )
-        {
-            Property<String> nameProperty = i.name();
-            String entityName = nameProperty.get();
-            if( entityName.equals( name ) )
-            {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private Iterable<ItemType> copyOf( Iterable<ItemType> iterable )
-    {
-        Collection<ItemType> copy = new ArrayList<ItemType>();
-        for( ItemType i : iterable )
-        {
-            copy.add( i );
-        }
-        return Collections.unmodifiableCollection( copy );
-    }
-
-    private ItemType newItemType( UnitOfWork uow, String name )
-    {
-        EntityBuilder<ItemType> builder = uow.newEntityBuilder( ItemType.class );
-        builder.instance().name().set( name );
-        return builder.newInstance();
-    }
-
-    interface ItemType
-    {
-        Property<String> name();
-    }
-
-    interface ItemTypeEntity
-        extends ItemType, EntityComposite
-    {
-    }
-}
diff --git a/extensions/indexing-solr/build.gradle b/extensions/indexing-solr/build.gradle
index 944d851..df06bc6 100644
--- a/extensions/indexing-solr/build.gradle
+++ b/extensions/indexing-solr/build.gradle
@@ -1,36 +1,40 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Solr Indexing Extension"
+apply plugin: 'polygene-extension'
 
-jar { manifest {name = "Apache Zest™ Extension - Indexing - Solr" }}
+description = "Apache Polygene™ Solr Indexing Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - Indexing - Solr" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile(project(":org.qi4j.libraries:org.qi4j.library.fileconfig"))
-  compile(project(":org.qi4j.libraries:org.qi4j.library.rdf"))
-  compile(libraries.solr)
-  compile libraries.slf4j_api
+  api polygene.core.bootstrap
+  api polygene.library( 'fileconfig' )
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
+  implementation polygene.library( 'rdf' )
+  implementation libraries.solr
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.servlet_api)
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+  testRuntimeOnly libraries.servlet_api
+}
diff --git a/extensions/indexing-solr/dev-status.xml b/extensions/indexing-solr/dev-status.xml
index 9052325..e6cf5af 100644
--- a/extensions/indexing-solr/dev-status.xml
+++ b/extensions/indexing-solr/dev-status.xml
@@ -1,27 +1,30 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
         <!--none,early,beta,stable,mature-->
-        <codebase>stable</codebase>
+        <codebase>beta</codebase>
 
         <!-- none, brief, good, complete -->
         <documentation>brief</documentation>
diff --git a/extensions/indexing-solr/src/docs/index-solr.txt b/extensions/indexing-solr/src/docs/index-solr.txt
index e964831..b79a0a0 100644
--- a/extensions/indexing-solr/src/docs/index-solr.txt
+++ b/extensions/indexing-solr/src/docs/index-solr.txt
@@ -27,7 +27,7 @@
 
 Index/Query services backed by an embedded http://lucene.apache.org/solr/[Apache Solr Search].
 
-WARNING: Solr Index/Query service do not support the Zest™ Query API but only native Solr queries.
+WARNING: Solr Index/Query service do not support the Polygene™ Query API but only native Solr queries.
 
 include::../../build/docs/buildinfo/artifact.txt[]
 
@@ -37,7 +37,7 @@
 
 [snippet,java]
 ----
-source=extensions/indexing-solr/src/test/java/org/qi4j/index/solr/SolrQueryServiceTest.java
+source=extensions/indexing-solr/src/test/java/org/apache/polygene/index/solr/SolrQueryServiceTest.java
 tag=assembly
 ----
 
diff --git a/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/EmbeddedSolrService.java b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/EmbeddedSolrService.java
new file mode 100644
index 0000000..29653a3
--- /dev/null
+++ b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/EmbeddedSolrService.java
@@ -0,0 +1,133 @@
+/*
+ *  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.polygene.index.solr;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import org.apache.solr.client.solrj.SolrServer;
+import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.core.SolrConfig;
+import org.apache.solr.core.SolrCore;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.library.fileconfig.FileConfiguration;
+
+@Mixins( EmbeddedSolrService.Mixin.class )
+@Activators( EmbeddedSolrService.Activator.class )
+public interface EmbeddedSolrService
+{
+   SolrServer solrServer();
+
+   SolrCore solrCore();
+
+    void activateSolr()
+            throws Exception;
+
+    void passivateSolr()
+            throws Exception;
+
+    class Activator extends ActivatorAdapter<ServiceReference<EmbeddedSolrService>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<EmbeddedSolrService> activated )
+                throws Exception
+        {
+            activated.get().activateSolr();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<EmbeddedSolrService> passivating )
+                throws Exception
+        {
+            passivating.get().passivateSolr();
+        }
+
+    }
+
+   abstract class Mixin
+         implements EmbeddedSolrService
+   {
+      @Service
+      FileConfiguration fileConfig;
+      public CoreContainer coreContainer;
+      public EmbeddedSolrServer server;
+
+      @Uses
+      ServiceDescriptor descriptor;
+
+      private SolrCore core;
+
+      @Override
+      public void activateSolr() throws Exception
+      {
+         ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
+         Thread.currentThread().setContextClassLoader( getClass().getClassLoader() );
+
+         try
+         {
+            File directory = new File( fileConfig.dataDirectory(), descriptor.identity().toString() );
+            directory.mkdirs();
+
+            System.setProperty( "solr.solr.home", directory.getAbsolutePath() );
+
+            CoreContainer.Initializer initializer = new CoreContainer.Initializer();
+            coreContainer = initializer.initialize();
+            server = new EmbeddedSolrServer( coreContainer, "" );
+            core = coreContainer.getCore( "" );
+         } finally
+         {
+            Thread.currentThread().setContextClassLoader( oldCl );
+         }
+      }
+
+      @Override
+      public void passivateSolr() throws Exception
+      {
+         core.closeSearcher();
+         coreContainer.shutdown();
+
+         // Clear instance fields for GC purposes
+         Field instanceField = SolrCore.class.getDeclaredField( "instance" );
+         instanceField.setAccessible( true );
+         instanceField.set( null, null );
+
+         SolrConfig.config = null;
+      }
+
+       @Override
+      public SolrServer solrServer()
+      {
+         return server;
+      }
+
+       @Override
+      public SolrCore solrCore()
+      {
+         return core;
+      }
+   }
+}
diff --git a/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/SolrExpressions.java b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/SolrExpressions.java
new file mode 100644
index 0000000..86746f9
--- /dev/null
+++ b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/SolrExpressions.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.index.solr;
+
+import org.apache.polygene.api.query.grammar.QuerySpecification;
+
+/**
+ * TODO
+ */
+public class SolrExpressions
+{
+    public static QuerySpecification search(String queryString)
+    {
+        return new QuerySpecification( "solr", queryString );
+    }
+}
diff --git a/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/SolrQueryService.java b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/SolrQueryService.java
new file mode 100644
index 0000000..445f7ea
--- /dev/null
+++ b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/SolrQueryService.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.index.solr;
+
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.index.solr.internal.SolrEntityIndexerMixin;
+import org.apache.polygene.index.solr.internal.SolrEntityQueryMixin;
+import org.apache.polygene.spi.entitystore.StateChangeListener;
+import org.apache.polygene.spi.query.EntityFinder;
+
+/**
+ * JAVADOC
+ */
+@Mixins( { SolrEntityIndexerMixin.class, SolrEntityQueryMixin.class } )
+@Activators( SolrQueryService.Activator.class )
+public interface SolrQueryService
+        extends EntityFinder, StateChangeListener, SolrSearch
+{
+
+    void inflateSolrSchema();
+
+    void releaseSolrSchema();
+
+    class Activator
+            extends ActivatorAdapter<ServiceReference<SolrQueryService>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<SolrQueryService> activated )
+                throws Exception
+        {
+            activated.get().inflateSolrSchema();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<SolrQueryService> passivating )
+                throws Exception
+        {
+            passivating.get().releaseSolrSchema();
+        }
+
+    }
+
+}
diff --git a/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/SolrSearch.java b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/SolrSearch.java
new file mode 100644
index 0000000..8f25cfe
--- /dev/null
+++ b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/SolrSearch.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.index.solr;
+
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.common.SolrDocumentList;
+
+/**
+ * JAVADOC
+ */
+public interface SolrSearch
+{
+   SolrDocumentList search( String queryString ) throws SolrServerException;
+}
diff --git a/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/assembly/SolrIndexingAssembler.java b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/assembly/SolrIndexingAssembler.java
new file mode 100644
index 0000000..4932cdc
--- /dev/null
+++ b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/assembly/SolrIndexingAssembler.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.index.solr.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.solr.EmbeddedSolrService;
+import org.apache.polygene.index.solr.SolrQueryService;
+import org.apache.polygene.library.rdf.entity.EntityStateSerializer;
+
+public class SolrIndexingAssembler extends Assemblers.VisibilityIdentityConfig<SolrIndexingAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        module.services( EmbeddedSolrService.class ).identifiedBy( "solr" ).instantiateOnStartup();
+        module.services( SolrQueryService.class )
+              .taggedWith( "solr", "search", "indexing", "query" )
+              .identifiedBy( identity() )
+              .visibleIn( visibility() )
+              .instantiateOnStartup();
+        module.objects( EntityStateSerializer.class );
+    }
+}
diff --git a/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/SingleTokenTokenizer.java b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/SingleTokenTokenizer.java
new file mode 100644
index 0000000..d5de2a6
--- /dev/null
+++ b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/SingleTokenTokenizer.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.index.solr.internal;
+
+import org.apache.lucene.analysis.WhitespaceTokenizer;
+import org.apache.lucene.util.AttributeSource;
+
+import java.io.Reader;
+
+public class SingleTokenTokenizer
+      extends WhitespaceTokenizer
+{
+   public SingleTokenTokenizer( Reader in )
+   {
+      super( in );
+   }
+
+   public SingleTokenTokenizer( AttributeSource source, Reader in )
+   {
+      super( source, in );
+   }
+
+   @Override
+   protected boolean isTokenChar( char c )
+   {
+      return true;
+   }
+}
diff --git a/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/SingleTokenTokenizerFactory.java b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/SingleTokenTokenizerFactory.java
new file mode 100644
index 0000000..2259cb5
--- /dev/null
+++ b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/SingleTokenTokenizerFactory.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.index.solr.internal;
+
+import java.io.Reader;
+import org.apache.solr.analysis.BaseTokenizerFactory;
+
+public class SingleTokenTokenizerFactory
+      extends BaseTokenizerFactory
+{
+   @Override
+   public SingleTokenTokenizer create( Reader input )
+   {
+      return new SingleTokenTokenizer( input );
+   }
+}
diff --git a/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/SolrEntityIndexerMixin.java b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/SolrEntityIndexerMixin.java
new file mode 100644
index 0000000..1c4e372
--- /dev/null
+++ b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/SolrEntityIndexerMixin.java
@@ -0,0 +1,292 @@
+/*
+ *  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.polygene.index.solr.internal;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import javax.json.JsonArray;
+import javax.json.JsonNumber;
+import javax.json.JsonObject;
+import javax.json.JsonReader;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+import javax.json.stream.JsonParser;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.index.solr.EmbeddedSolrService;
+import org.apache.polygene.index.solr.SolrQueryService;
+import org.apache.polygene.library.rdf.entity.EntityStateSerializer;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.solr.client.solrj.SolrServer;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.common.SolrInputDocument;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.schema.SchemaField;
+import org.openrdf.model.BNode;
+import org.openrdf.model.Graph;
+import org.openrdf.model.Literal;
+import org.openrdf.model.Resource;
+import org.openrdf.model.Statement;
+import org.openrdf.model.URI;
+import org.openrdf.model.impl.GraphImpl;
+import org.openrdf.model.impl.URIImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * JAVADOC
+ */
+public abstract class SolrEntityIndexerMixin
+    implements SolrQueryService
+{
+    @Service
+    private EmbeddedSolrService solr;
+
+    @Service
+    private JavaxJsonFactories jsonFactories;
+
+    @Uses
+    private EntityStateSerializer stateSerializer;
+
+//    private ValueFactory valueFactory = new ValueFactoryImpl();
+
+    private SolrServer server;
+    private Map<String, SchemaField> indexedFields;
+
+    Logger logger = LoggerFactory.getLogger( getClass() );
+
+    @Override
+    public void inflateSolrSchema()
+    {
+        server = solr.solrServer();
+        SolrCore solrCore = solr.solrCore();
+        try
+        {
+            indexedFields = solrCore.getSchema().getFields();
+        }
+        finally
+        {
+            solrCore.close();
+        }
+    }
+
+    @Override
+    public void releaseSolrSchema()
+    {
+        server = null;
+        indexedFields = null;
+    }
+
+    @Override
+    public void notifyChanges( Iterable<EntityState> entityStates )
+    {
+        try
+        {
+            try
+            {
+                // Figure out what to update
+                List<String> deleted = null;
+                List<SolrInputDocument> added = new ArrayList<>();
+                for( EntityState entityState : entityStates )
+                {
+                    if( entityState.entityDescriptor().queryable() )
+                    {
+                        if( entityState.status().equals( EntityStatus.REMOVED ) )
+                        {
+                            if( deleted == null )
+                            {
+                                deleted = new ArrayList<>();
+                            }
+                            deleted.add( entityState.entityReference().identity().toString() );
+                        }
+                        else if( entityState.status().equals( EntityStatus.UPDATED ) )
+                        {
+                            added.add( indexEntityState( entityState ) );
+                        }
+                        else if( entityState.status().equals( EntityStatus.NEW ) )
+                        {
+                            added.add( indexEntityState( entityState ) );
+                        }
+                    }
+                }
+
+                // Send changes to Solr
+                if( deleted != null )
+                {
+                    server.deleteById( deleted );
+                }
+                if( !added.isEmpty() )
+                {
+                    server.add( added );
+                }
+            }
+            finally
+            {
+                if( server != null )
+                {
+                    server.commit( false, false );
+                }
+            }
+        }
+        catch( Throwable e )
+        {
+            logger.error( "Could not update Solr", e );
+            //TODO What shall we do with the exception?
+        }
+    }
+
+    private SolrInputDocument indexEntityState( final EntityState entityState )
+        throws IOException, SolrServerException
+    {
+        Graph graph = new GraphImpl();
+        stateSerializer.serialize( entityState, false, graph );
+
+        SolrInputDocument input = new SolrInputDocument();
+        input.addField( "id", entityState.entityReference().identity() );
+        input.addField( "type", entityState.entityDescriptor().types().findFirst().get().getName() );
+        input.addField( "lastModified", java.util.Date.from( entityState.lastModified() ) );
+
+        for( Statement statement : graph )
+        {
+            SchemaField field = indexedFields.get( statement.getPredicate().getLocalName() );
+            if( field != null )
+            {
+                if( statement.getObject() instanceof Literal )
+                {
+                    String value = statement.getObject().stringValue();
+                    if( field.getType().getTypeName().equals( "json" ) )
+                    {
+                        try( JsonParser parser = jsonFactories.parserFactory()
+                                                              .createParser( new StringReader( value ) ) )
+                        {
+                            JsonParser.Event event = parser.next();
+                            switch( event )
+                            {
+                                case START_ARRAY:
+                                    try( JsonReader reader = jsonFactories.readerFactory()
+                                                                          .createReader( new StringReader( value ) ) )
+                                    {
+                                        indexJson( input, reader.readArray() );
+                                    }
+                                    break;
+                                case START_OBJECT:
+                                    try( JsonReader reader = jsonFactories.readerFactory()
+                                                                          .createReader( new StringReader( value ) ) )
+                                    {
+                                        indexJson( input, reader.readObject() );
+                                    }
+                                    break;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        input.addField( field.getName(), value );
+                    }
+                }
+                else if( statement.getObject() instanceof URI && !"type".equals( field.getName() ) )
+                {
+                    String value = statement.getObject().stringValue();
+                    value = value.substring( value.lastIndexOf( ':' ) + 1, value.length() );
+                    String name = field.getName();
+                    input.addField( name, value );
+                }
+                else if( statement.getObject() instanceof BNode )
+                {
+                    Resource resource = (Resource) statement.getObject();
+                    URIImpl uri = new URIImpl( "http://www.w3.org/1999/02/22-rdf-syntax-ns#li" );
+                    Iterator<Statement> seq = graph.match( resource, uri, null, (Resource) null );
+                    while( seq.hasNext() )
+                    {
+                        Statement seqStatement = seq.next();
+                        String value = seqStatement.getObject().stringValue();
+                        value = value.substring( value.lastIndexOf( ':' ) + 1, value.length() );
+
+                        input.addField( field.getName(), value );
+                    }
+                }
+            }
+        }
+
+        return input;
+    }
+
+    private void indexJson( SolrInputDocument input, Object object )
+    {
+        if( object instanceof JsonArray )
+        {
+            JsonArray array = (JsonArray) object;
+            for( int i = 0; i < array.size(); i++ )
+            {
+                indexJson( input, array.get( i ) );
+            }
+        }
+        else
+        {
+            JsonObject jsonObject = (JsonObject) object;
+            for( String name : jsonObject.keySet() )
+            {
+                JsonValue jsonValue = jsonObject.get( name );
+                if( jsonValue.getValueType() == JsonValue.ValueType.OBJECT
+                    || jsonValue.getValueType() == JsonValue.ValueType.ARRAY )
+                {
+                    indexJson( input, jsonValue );
+                }
+                else
+                {
+                    SchemaField field = indexedFields.get( name );
+                    if( field != null )
+                    {
+                        Object value;
+                        switch( jsonValue.getValueType() )
+                        {
+                            case NULL:
+                                value = null;
+                                break;
+                            case STRING:
+                                value = ( (JsonString) jsonValue ).getString();
+                                break;
+                            case NUMBER:
+                                JsonNumber jsonNumber = (JsonNumber) jsonValue;
+                                value = jsonNumber.isIntegral() ? jsonNumber.longValue() : jsonNumber.doubleValue();
+                                break;
+                            case TRUE:
+                                value = Boolean.TRUE;
+                                break;
+                            case FALSE:
+                                value = Boolean.FALSE;
+                                break;
+                            default:
+                                value = jsonValue.toString();
+                        }
+                        input.addField( name, value );
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/SolrEntityQueryMixin.java b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/SolrEntityQueryMixin.java
new file mode 100644
index 0000000..bbad9a6
--- /dev/null
+++ b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/SolrEntityQueryMixin.java
@@ -0,0 +1,137 @@
+/*
+ *  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.polygene.index.solr.internal;
+
+import java.lang.reflect.Member;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.solr.client.solrj.SolrServer;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.common.SolrDocument;
+import org.apache.solr.common.SolrDocumentList;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.NamedList;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.api.query.grammar.QuerySpecification;
+import org.apache.polygene.index.solr.EmbeddedSolrService;
+import org.apache.polygene.index.solr.SolrSearch;
+import org.apache.polygene.spi.query.EntityFinder;
+import org.apache.polygene.spi.query.EntityFinderException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * JAVADOC
+ */
+public class SolrEntityQueryMixin
+        implements EntityFinder, SolrSearch
+{
+    @Service
+    private EmbeddedSolrService solr;
+
+    private Logger logger = LoggerFactory.getLogger( SolrEntityQueryMixin.class );
+
+    @Override
+    public Stream<EntityReference> findEntities( Class<?> resultType,
+                                                 Predicate<Composite> whereClause,
+                                                 List<OrderBy> orderBySegments,
+                                                 Integer firstResult,
+                                                 Integer maxResults,
+                                                 Map<String, Object> variables ) throws EntityFinderException
+    {
+        try
+        {
+            QuerySpecification expr = (QuerySpecification) whereClause;
+
+            SolrServer server = solr.solrServer();
+
+            NamedList<Object> list = new NamedList<>();
+
+            list.add( "q", expr.query() );
+            list.add( "rows", maxResults != 0 ? maxResults : 10000 );
+            list.add( "start", firstResult );
+
+            if( orderBySegments != null && orderBySegments.size() > 0 )
+            {
+                for( OrderBy orderBySegment : orderBySegments )
+                {
+                    String propName = ((Member)orderBySegment.property().accessor()).getName() + "_for_sort";
+                    String order = orderBySegment.order() == OrderBy.Order.ASCENDING ? "asc" : "desc";
+                    list.add( "sort", propName + " " + order );
+
+                }
+            }
+
+            SolrParams solrParams = SolrParams.toSolrParams( list );
+            logger.debug( "Search:" + list.toString() );
+
+            QueryResponse query = server.query( solrParams );
+
+            SolrDocumentList results = query.getResults();
+
+            List<EntityReference> references = new ArrayList<>( results.size() );
+            for( SolrDocument result : results )
+            {
+                references.add( EntityReference.parseEntityReference( result.getFirstValue( "id" ).toString() ) );
+            }
+            return references.stream();
+
+        } catch( SolrServerException e )
+        {
+            throw new EntityFinderException( e );
+        }
+    }
+
+    @Override
+    public EntityReference findEntity( Class<?> resultType, @Optional Predicate<Composite> whereClause, Map<String, Object> variables ) throws EntityFinderException
+    {
+        return findEntities( resultType, whereClause, null, 0, 1, variables )
+            .findFirst().orElse( null );
+    }
+
+    @Override
+    public long countEntities( Class<?> resultType, @Optional Predicate<Composite> whereClause, Map<String, Object> variables ) throws EntityFinderException
+    {
+        return findEntities( resultType, whereClause, null, 0, 1, variables )
+            .count();
+    }
+
+    @Override
+    public SolrDocumentList search( String queryString ) throws SolrServerException
+    {
+        SolrServer server = solr.solrServer();
+
+        NamedList<Object> list = new NamedList<>();
+
+        list.add( "q", queryString );
+
+        QueryResponse query = server.query( SolrParams.toSolrParams( list ) );
+        return query.getResults();
+    }
+}
diff --git a/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/package.html b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/package.html
new file mode 100644
index 0000000..c37a9ee
--- /dev/null
+++ b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Solr Index/Query Internal Package.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/package.html b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/package.html
new file mode 100644
index 0000000..c881915
--- /dev/null
+++ b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Solr Index/Query.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/EmbeddedSolrService.java b/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/EmbeddedSolrService.java
deleted file mode 100644
index f21f7fa..0000000
--- a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/EmbeddedSolrService.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.index.solr;
-
-import java.io.File;
-import java.lang.reflect.Field;
-import org.apache.solr.client.solrj.SolrServer;
-import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
-import org.apache.solr.core.CoreContainer;
-import org.apache.solr.core.SolrConfig;
-import org.apache.solr.core.SolrCore;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.library.fileconfig.FileConfiguration;
-
-@Mixins( EmbeddedSolrService.Mixin.class )
-@Activators( EmbeddedSolrService.Activator.class )
-public interface EmbeddedSolrService extends ServiceComposite
-{
-   SolrServer solrServer();
-
-   SolrCore solrCore();
-
-    void activateSolr()
-            throws Exception;
-
-    void passivateSolr()
-            throws Exception;
-
-    class Activator extends ActivatorAdapter<ServiceReference<EmbeddedSolrService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<EmbeddedSolrService> activated )
-                throws Exception
-        {
-            activated.get().activateSolr();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<EmbeddedSolrService> passivating )
-                throws Exception
-        {
-            passivating.get().passivateSolr();
-        }
-
-    }
-
-   abstract class Mixin
-         implements EmbeddedSolrService
-   {
-      @Service
-      FileConfiguration fileConfig;
-      public CoreContainer coreContainer;
-      public EmbeddedSolrServer server;
-
-      @Uses
-      ServiceDescriptor descriptor;
-
-      private SolrCore core;
-
-      @Override
-      public void activateSolr() throws Exception
-      {
-         ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
-         Thread.currentThread().setContextClassLoader( getClass().getClassLoader() );
-
-         try
-         {
-            File directory = new File( fileConfig.dataDirectory(), descriptor.identity() );
-            directory.mkdir();
-
-            System.setProperty( "solr.solr.home", directory.getAbsolutePath() );
-
-            CoreContainer.Initializer initializer = new CoreContainer.Initializer();
-            coreContainer = initializer.initialize();
-            server = new EmbeddedSolrServer( coreContainer, "" );
-            core = coreContainer.getCore( "" );
-         } finally
-         {
-            Thread.currentThread().setContextClassLoader( oldCl );
-         }
-      }
-
-      @Override
-      public void passivateSolr() throws Exception
-      {
-         core.closeSearcher();
-         coreContainer.shutdown();
-
-         // Clear instance fields for GC purposes
-         Field instanceField = SolrCore.class.getDeclaredField( "instance" );
-         instanceField.setAccessible( true );
-         instanceField.set( null, null );
-
-         SolrConfig.config = null;
-      }
-
-       @Override
-      public SolrServer solrServer()
-      {
-         return server;
-      }
-
-       @Override
-      public SolrCore solrCore()
-      {
-         return core;
-      }
-   }
-}
diff --git a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/SolrAssembler.java b/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/SolrAssembler.java
deleted file mode 100644
index 36742aa..0000000
--- a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/SolrAssembler.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.index.solr;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-/**
- * JAVADOC
- */
-public class SolrAssembler
-   implements Assembler
-{
-    @Override
-   public void assemble( ModuleAssembly module ) throws AssemblyException
-   {
-      module.services( EmbeddedSolrService.class ).identifiedBy( "solr" ).instantiateOnStartup();
-
-      module.services( SolrQueryService.class ).
-            taggedWith( "solr", "search" ).
-            identifiedBy( "solrquery" ).
-            visibleIn( Visibility.application );
-      module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
-      module.objects( EntityStateSerializer.class );
-   }
-}
diff --git a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/SolrExpressions.java b/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/SolrExpressions.java
deleted file mode 100644
index ee941d1..0000000
--- a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/SolrExpressions.java
+++ /dev/null
@@ -1,32 +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.qi4j.index.solr;
-
-import org.qi4j.api.query.grammar.QuerySpecification;
-
-/**
- * TODO
- */
-public class SolrExpressions
-{
-    public static QuerySpecification search(String queryString)
-    {
-        return new QuerySpecification( "solr", queryString );
-    }
-}
diff --git a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/SolrQueryService.java b/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/SolrQueryService.java
deleted file mode 100644
index 63b6f5f..0000000
--- a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/SolrQueryService.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.index.solr;
-
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.index.solr.internal.SolrEntityIndexerMixin;
-import org.qi4j.index.solr.internal.SolrEntityQueryMixin;
-import org.qi4j.spi.entitystore.StateChangeListener;
-import org.qi4j.spi.query.EntityFinder;
-
-/**
- * JAVADOC
- */
-@Mixins( { SolrEntityIndexerMixin.class, SolrEntityQueryMixin.class } )
-@Activators( SolrQueryService.Activator.class )
-public interface SolrQueryService
-        extends EntityFinder, StateChangeListener, SolrSearch, ServiceComposite
-{
-
-    void inflateSolrSchema();
-
-    void releaseSolrSchema();
-
-    class Activator
-            extends ActivatorAdapter<ServiceReference<SolrQueryService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<SolrQueryService> activated )
-                throws Exception
-        {
-            activated.get().inflateSolrSchema();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<SolrQueryService> passivating )
-                throws Exception
-        {
-            passivating.get().releaseSolrSchema();
-        }
-
-    }
-
-}
diff --git a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/SolrSearch.java b/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/SolrSearch.java
deleted file mode 100644
index 8e1eba4..0000000
--- a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/SolrSearch.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.index.solr;
-
-import org.apache.solr.client.solrj.SolrServerException;
-import org.apache.solr.common.SolrDocumentList;
-
-/**
- * JAVADOC
- */
-public interface SolrSearch
-{
-   public SolrDocumentList search( String queryString ) throws SolrServerException;
-}
diff --git a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/internal/SingleTokenTokenizer.java b/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/internal/SingleTokenTokenizer.java
deleted file mode 100644
index f8c7770..0000000
--- a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/internal/SingleTokenTokenizer.java
+++ /dev/null
@@ -1,44 +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.qi4j.index.solr.internal;
-
-import org.apache.lucene.analysis.WhitespaceTokenizer;
-import org.apache.lucene.util.AttributeSource;
-
-import java.io.Reader;
-
-public class SingleTokenTokenizer
-      extends WhitespaceTokenizer
-{
-   public SingleTokenTokenizer( Reader in )
-   {
-      super( in );
-   }
-
-   public SingleTokenTokenizer( AttributeSource source, Reader in )
-   {
-      super( source, in );
-   }
-
-   @Override
-   protected boolean isTokenChar( char c )
-   {
-      return true;
-   }
-}
diff --git a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/internal/SingleTokenTokenizerFactory.java b/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/internal/SingleTokenTokenizerFactory.java
deleted file mode 100644
index 48769a8..0000000
--- a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/internal/SingleTokenTokenizerFactory.java
+++ /dev/null
@@ -1,32 +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.qi4j.index.solr.internal;
-
-import java.io.Reader;
-import org.apache.solr.analysis.BaseTokenizerFactory;
-
-public class SingleTokenTokenizerFactory
-      extends BaseTokenizerFactory
-{
-   @Override
-   public SingleTokenTokenizer create( Reader input )
-   {
-      return new SingleTokenTokenizer( input );
-   }
-}
diff --git a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/internal/SolrEntityIndexerMixin.java b/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/internal/SolrEntityIndexerMixin.java
deleted file mode 100644
index 824354b..0000000
--- a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/internal/SolrEntityIndexerMixin.java
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.index.solr.internal;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import org.apache.solr.client.solrj.SolrServer;
-import org.apache.solr.client.solrj.SolrServerException;
-import org.apache.solr.common.SolrInputDocument;
-import org.apache.solr.core.SolrCore;
-import org.apache.solr.schema.SchemaField;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.openrdf.model.BNode;
-import org.openrdf.model.Graph;
-import org.openrdf.model.Literal;
-import org.openrdf.model.Resource;
-import org.openrdf.model.Statement;
-import org.openrdf.model.URI;
-import org.openrdf.model.ValueFactory;
-import org.openrdf.model.impl.GraphImpl;
-import org.openrdf.model.impl.URIImpl;
-import org.openrdf.model.impl.ValueFactoryImpl;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.index.solr.EmbeddedSolrService;
-import org.qi4j.index.solr.SolrQueryService;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.EntityStatus;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * JAVADOC
- */
-public abstract class SolrEntityIndexerMixin
-        implements SolrQueryService
-{
-    @Service
-    private EmbeddedSolrService solr;
-
-    @Uses
-    private EntityStateSerializer stateSerializer;
-
-    private ValueFactory valueFactory = new ValueFactoryImpl();
-
-    private SolrServer server;
-    private Map<String, SchemaField> indexedFields;
-
-    Logger logger = LoggerFactory.getLogger( getClass() );
-
-    @Override
-    public void inflateSolrSchema()
-    {
-        server = solr.solrServer();
-        SolrCore solrCore = solr.solrCore();
-        try
-        {
-            indexedFields = solrCore.getSchema().getFields();
-        } finally
-        {
-            solrCore.close();
-        }
-    }
-
-    @Override
-    public void releaseSolrSchema()
-    {
-        server = null;
-        indexedFields = null;
-    }
-
-    @Override
-    public void notifyChanges( Iterable<EntityState> entityStates )
-    {
-        try
-        {
-            try
-            {
-                // Figure out what to update
-                List<String> deleted = null;
-                List<SolrInputDocument> added = new ArrayList<SolrInputDocument>();
-                for( EntityState entityState : entityStates )
-                {
-                    if( entityState.entityDescriptor().queryable() )
-                    {
-                        if( entityState.status().equals( EntityStatus.REMOVED ) )
-                        {
-                            if( deleted == null )
-                                deleted = new ArrayList<String>();
-                            deleted.add( entityState.identity().identity() );
-                        } else if( entityState.status().equals( EntityStatus.UPDATED ) )
-                        {
-                            added.add( indexEntityState( entityState, server ) );
-                        } else if( entityState.status().equals( EntityStatus.NEW ) )
-                        {
-                            added.add( indexEntityState( entityState, server ) );
-                        }
-                    }
-                }
-
-                // Send changes to Solr
-                if( deleted != null )
-                    server.deleteById( deleted );
-                if( !added.isEmpty() )
-                    server.add( added );
-            } finally
-            {
-                if( server != null )
-                {
-                    server.commit( false, false );
-                }
-            }
-        } catch( Throwable e )
-        {
-            logger.error( "Could not update Solr", e );
-            //TODO What shall we do with the exception?
-        }
-    }
-
-    private SolrInputDocument indexEntityState( final EntityState entityState,
-                                                final SolrServer server )
-            throws IOException, SolrServerException, JSONException
-    {
-        Graph graph = new GraphImpl();
-        stateSerializer.serialize( entityState, false, graph );
-
-        SolrInputDocument input = new SolrInputDocument();
-        input.addField( "id", entityState.identity().identity() );
-        input.addField( "type", first(entityState.entityDescriptor().types()).getName() );
-        input.addField( "lastModified", new Date( entityState.lastModified() ) );
-
-        for( Statement statement : graph )
-        {
-            SchemaField field = indexedFields.get( statement.getPredicate().getLocalName() );
-            if( field != null )
-            {
-                if( statement.getObject() instanceof Literal )
-                {
-                    String value = statement.getObject().stringValue();
-                    if( field.getType().getTypeName().equals( "json" ) )
-                    {
-                        if( value.charAt( 0 ) == '[' )
-                        {
-                            JSONArray array = new JSONArray( value );
-                            indexJson( input, array );
-                        } else if( value.charAt( 0 ) == '{' )
-                        {
-                            JSONObject object = new JSONObject( value );
-                            indexJson( input, object );
-                        }
-                    } else
-                    {
-                        input.addField( field.getName(), value );
-                    }
-                } else if( statement.getObject() instanceof URI && !"type".equals( field.getName() ) )
-                {
-                    String value = statement.getObject().stringValue();
-                    value = value.substring( value.lastIndexOf( ':' ) + 1, value.length() );
-                    String name = field.getName();
-                    input.addField( name, value );
-                } else if( statement.getObject() instanceof BNode )
-                {
-                    Resource resource = (Resource) statement.getObject();
-                    URIImpl uri = new URIImpl( "http://www.w3.org/1999/02/22-rdf-syntax-ns#li" );
-                    Iterator<Statement> seq = graph.match( resource, uri, null, (Resource) null );
-                    while( seq.hasNext() )
-                    {
-                        Statement seqStatement = seq.next();
-                        String value = seqStatement.getObject().stringValue();
-                        value = value.substring( value.lastIndexOf( ':' ) + 1, value.length() );
-
-                        input.addField( field.getName(), value );
-                    }
-                }
-            }
-
-        }
-
-        return input;
-    }
-
-    private void indexJson( SolrInputDocument input, Object object ) throws JSONException
-    {
-        if( object instanceof JSONArray )
-        {
-            JSONArray array = (JSONArray) object;
-            for( int i = 0; i < array.length(); i++ )
-                indexJson( input, array.get( i ) );
-        } else
-        {
-            JSONObject jsonObject = (JSONObject) object;
-            Iterator keys = jsonObject.keys();
-            while( keys.hasNext() )
-            {
-                Object name = keys.next();
-                Object value = jsonObject.get( name.toString() );
-                if( value instanceof JSONObject || value instanceof JSONArray )
-                {
-                    indexJson( input, value );
-                } else
-                {
-                    SchemaField field = indexedFields.get( name.toString() );
-                    if( field != null )
-                    {
-                        input.addField( name.toString(), jsonObject.get( name.toString() ) );
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/internal/SolrEntityQueryMixin.java b/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/internal/SolrEntityQueryMixin.java
deleted file mode 100644
index 73e4988..0000000
--- a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/internal/SolrEntityQueryMixin.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.index.solr.internal;
-
-import java.lang.reflect.Member;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import org.apache.solr.client.solrj.SolrServer;
-import org.apache.solr.client.solrj.SolrServerException;
-import org.apache.solr.client.solrj.response.QueryResponse;
-import org.apache.solr.common.SolrDocument;
-import org.apache.solr.common.SolrDocumentList;
-import org.apache.solr.common.params.SolrParams;
-import org.apache.solr.common.util.NamedList;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.api.query.grammar.QuerySpecification;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.index.solr.EmbeddedSolrService;
-import org.qi4j.index.solr.SolrSearch;
-import org.qi4j.spi.query.EntityFinder;
-import org.qi4j.spi.query.EntityFinderException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * JAVADOC
- */
-public class SolrEntityQueryMixin
-        implements EntityFinder, SolrSearch
-{
-    @Service
-    private EmbeddedSolrService solr;
-
-    private Logger logger = LoggerFactory.getLogger( SolrEntityQueryMixin.class );
-
-    @Override
-    public Iterable<EntityReference> findEntities( Class<?> resultType, @Optional Specification<Composite> whereClause, @Optional OrderBy[] orderBySegments, @Optional Integer firstResult, @Optional Integer maxResults, Map<String, Object> variables ) throws EntityFinderException
-    {
-        try
-        {
-            QuerySpecification expr = (QuerySpecification) whereClause;
-
-            SolrServer server = solr.solrServer();
-
-            NamedList<Object> list = new NamedList<Object>();
-
-            list.add( "q", expr.query() );
-            list.add( "rows", maxResults != 0 ? maxResults : 10000 );
-            list.add( "start", firstResult );
-
-            if( orderBySegments != null && orderBySegments.length > 0 )
-            {
-                for( OrderBy orderBySegment : orderBySegments )
-                {
-                    String propName = ((Member)orderBySegment.property().accessor()).getName() + "_for_sort";
-                    String order = orderBySegment.order() == OrderBy.Order.ASCENDING ? "asc" : "desc";
-                    list.add( "sort", propName + " " + order );
-
-                }
-            }
-
-            SolrParams solrParams = SolrParams.toSolrParams( list );
-            logger.debug( "Search:" + list.toString() );
-
-            QueryResponse query = server.query( solrParams );
-
-            SolrDocumentList results = query.getResults();
-
-            List<EntityReference> references = new ArrayList<EntityReference>( results.size() );
-            for( SolrDocument result : results )
-            {
-                references.add( EntityReference.parseEntityReference( result.getFirstValue( "id" ).toString() ) );
-            }
-            return references;
-
-        } catch( SolrServerException e )
-        {
-            throw new EntityFinderException( e );
-        }
-    }
-
-    @Override
-    public EntityReference findEntity( Class<?> resultType, @Optional Specification<Composite> whereClause, Map<String, Object> variables ) throws EntityFinderException
-    {
-        Iterator<EntityReference> iter = findEntities( resultType, whereClause, null, 0, 1, variables ).iterator();
-
-        if( iter.hasNext() )
-            return iter.next();
-        else
-            return null;
-    }
-
-    @Override
-    public long countEntities( Class<?> resultType, @Optional Specification<Composite> whereClause, Map<String, Object> variables ) throws EntityFinderException
-    {
-        return Iterables.count( findEntities( resultType, whereClause, null, 0, 1, variables ) );
-    }
-
-    @Override
-    public SolrDocumentList search( String queryString ) throws SolrServerException
-    {
-        SolrServer server = solr.solrServer();
-
-        NamedList<Object> list = new NamedList<Object>();
-
-        list.add( "q", queryString );
-
-        QueryResponse query = server.query( SolrParams.toSolrParams( list ) );
-        return query.getResults();
-    }
-}
diff --git a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/internal/package.html b/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/internal/package.html
deleted file mode 100644
index 9fcb0a8..0000000
--- a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/internal/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Solr Index/Query Internal Package.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/package.html b/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/package.html
deleted file mode 100644
index 0a43c68..0000000
--- a/extensions/indexing-solr/src/main/java/org/qi4j/index/solr/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Solr Index/Query.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-solr/src/test/java/org/apache/polygene/index/solr/SolrEntityFinderTest.java b/extensions/indexing-solr/src/test/java/org/apache/polygene/index/solr/SolrEntityFinderTest.java
new file mode 100644
index 0000000..c67e70b
--- /dev/null
+++ b/extensions/indexing-solr/src/test/java/org/apache/polygene/index/solr/SolrEntityFinderTest.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.index.solr;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.solr.assembly.SolrIndexingAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.indexing.AbstractEntityFinderTest;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+@Ignore( "SOLR Index/Query is not working at all" )
+public class SolrEntityFinderTest
+    extends AbstractEntityFinderTest
+{
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+        new SolrIndexingAssembler().assemble( module );
+    }
+}
diff --git a/extensions/indexing-solr/src/test/java/org/apache/polygene/index/solr/SolrNamedQueryTest.java b/extensions/indexing-solr/src/test/java/org/apache/polygene/index/solr/SolrNamedQueryTest.java
new file mode 100644
index 0000000..daba9b3
--- /dev/null
+++ b/extensions/indexing-solr/src/test/java/org/apache/polygene/index/solr/SolrNamedQueryTest.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.index.solr;
+
+import java.util.function.Predicate;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.solr.assembly.SolrIndexingAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.indexing.AbstractNamedQueryTest;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+@Ignore( "SOLR Index/Query is not working at all" )
+public class SolrNamedQueryTest
+    extends AbstractNamedQueryTest
+{
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+        new SolrIndexingAssembler().assemble( module );
+    }
+
+    @Override
+    protected String[] queryStrings()
+    {
+        return new String[] {}; // TODO Write example Solr named queries
+    }
+
+    @Override
+    protected Predicate<Composite> createNamedQueryDescriptor( String queryName, String queryString )
+    {
+        return SolrExpressions.search( queryString );
+    }
+}
diff --git a/extensions/indexing-solr/src/test/java/org/apache/polygene/index/solr/SolrQueryServiceTest.java b/extensions/indexing-solr/src/test/java/org/apache/polygene/index/solr/SolrQueryServiceTest.java
new file mode 100644
index 0000000..01d3440
--- /dev/null
+++ b/extensions/indexing-solr/src/test/java/org/apache/polygene/index/solr/SolrQueryServiceTest.java
@@ -0,0 +1,125 @@
+/*
+ *  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.polygene.index.solr;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.index.solr.assembly.SolrIndexingAssembler;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.common.SolrDocument;
+import org.apache.solr.common.SolrDocumentList;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+
+public class SolrQueryServiceTest
+    extends AbstractPolygeneTest
+{
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.layer().application().setMode( Application.Mode.test );
+
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+
+        new EntityTestAssembler().assemble( module );
+        // START SNIPPET: assembly
+        new SolrIndexingAssembler().assemble( module );
+        // END SNIPPET: assembly
+
+        module.entities( TestEntity.class );
+    }
+
+    @Before
+    public void index()
+        throws UnitOfWorkCompletionException, InterruptedException
+    {
+        // Create and index an entity
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        TestEntity test = uow.newEntity( TestEntity.class );
+        test.name().set( "Hello World" );
+        uow.complete();
+        Thread.sleep( 140 );
+    }
+
+    @Test
+    public void testQuery()
+        throws UnitOfWorkCompletionException
+    {
+        // Search for it
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            Query<TestEntity> query = uow.newQuery( queryBuilderFactory.newQueryBuilder( TestEntity.class )
+                                                                       .where( SolrExpressions.search( "hello" ) ) );
+
+            TestEntity test = query.find();
+            Assert.assertThat( test.name().get(), equalTo( "Hello World" ) );
+        }
+    }
+
+    @Test
+    public void testSearch()
+        throws UnitOfWorkCompletionException, SolrServerException
+    {
+        // Search for it using search interface
+        SolrSearch search = serviceFinder.findService( SolrSearch.class ).get();
+
+        SolrDocumentList results = search.search( "hello" );
+
+        List<String> lookAhead = new ArrayList<String>();
+        for( SolrDocument result : results )
+        {
+            lookAhead.add( result.getFieldValue( "name" ).toString() );
+        }
+
+        Assert.assertThat( lookAhead.toString(), equalTo( "[Hello World]" ) );
+    }
+
+    public interface TestEntity
+        extends EntityComposite
+    {
+
+        @UseDefaults
+        Property<String> name();
+    }
+}
diff --git a/extensions/indexing-solr/src/test/java/org/apache/polygene/index/solr/SolrQueryTest.java b/extensions/indexing-solr/src/test/java/org/apache/polygene/index/solr/SolrQueryTest.java
new file mode 100644
index 0000000..f61b665
--- /dev/null
+++ b/extensions/indexing-solr/src/test/java/org/apache/polygene/index/solr/SolrQueryTest.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.index.solr;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.solr.assembly.SolrIndexingAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.indexing.AbstractQueryTest;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+@Ignore( "SOLR Index/Query is not working at all" )
+public class SolrQueryTest
+    extends AbstractQueryTest
+{
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        super.assemble( module );
+        new FileConfigurationAssembler()
+            .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+            .assemble( module );
+        new SolrIndexingAssembler().assemble( module );
+    }
+}
diff --git a/extensions/indexing-solr/src/test/java/org/qi4j/index/solr/SolrEntityFinderTest.java b/extensions/indexing-solr/src/test/java/org/qi4j/index/solr/SolrEntityFinderTest.java
deleted file mode 100644
index c1e3048..0000000
--- a/extensions/indexing-solr/src/test/java/org/qi4j/index/solr/SolrEntityFinderTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.solr;
-
-import java.io.File;
-import org.junit.Ignore;
-import org.junit.Rule;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.fileconfig.FileConfigurationOverride;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.test.indexing.AbstractEntityFinderTest;
-import org.qi4j.test.util.DelTreeAfter;
-
-@Ignore( "SOLR Index/Query is not working at all" )
-public class SolrEntityFinderTest
-    extends AbstractEntityFinderTest
-{
-
-    private static final File DATA_DIR = new File( "build/tmp/solr-named-query-test" );
-    @Rule
-    public final DelTreeAfter delTreeAfter = new DelTreeAfter( DATA_DIR );
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        FileConfigurationOverride override = new FileConfigurationOverride().withData( new File( DATA_DIR, "qi4j-data" ) ).
-            withLog( new File( DATA_DIR, "qi4j-logs" ) ).withTemporary( new File( DATA_DIR, "qi4j-temp" ) );
-        module.services( FileConfigurationService.class ).
-            setMetaInfo( override );
-        new SolrAssembler().assemble( module );
-    }
-
-}
diff --git a/extensions/indexing-solr/src/test/java/org/qi4j/index/solr/SolrNamedQueryTest.java b/extensions/indexing-solr/src/test/java/org/qi4j/index/solr/SolrNamedQueryTest.java
deleted file mode 100644
index d64de1e..0000000
--- a/extensions/indexing-solr/src/test/java/org/qi4j/index/solr/SolrNamedQueryTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.solr;
-
-import java.io.File;
-import org.junit.Ignore;
-import org.junit.Rule;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Specification;
-import org.qi4j.library.fileconfig.FileConfigurationOverride;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.test.indexing.AbstractNamedQueryTest;
-import org.qi4j.test.util.DelTreeAfter;
-
-@Ignore( "SOLR Index/Query is not working at all" )
-public class SolrNamedQueryTest
-    extends AbstractNamedQueryTest
-{
-
-    private static final File DATA_DIR = new File( "build/tmp/solr-named-query-test" );
-    @Rule
-    public final DelTreeAfter delTreeAfter = new DelTreeAfter( DATA_DIR );
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        FileConfigurationOverride override = new FileConfigurationOverride().withData( new File( DATA_DIR, "qi4j-data" ) ).
-            withLog( new File( DATA_DIR, "qi4j-logs" ) ).withTemporary( new File( DATA_DIR, "qi4j-temp" ) );
-        module.services( FileConfigurationService.class ).
-            setMetaInfo( override );
-        new SolrAssembler().assemble( module );
-    }
-
-    @Override
-    protected String[] queryStrings()
-    {
-        return new String[]
-        {
-        }; // TODO Write example Solr named queries
-    }
-
-    @Override
-    protected Specification<Composite> createNamedQueryDescriptor( String queryName, String queryString )
-    {
-        return SolrExpressions.search( queryString );
-    }
-
-}
diff --git a/extensions/indexing-solr/src/test/java/org/qi4j/index/solr/SolrQueryServiceTest.java b/extensions/indexing-solr/src/test/java/org/qi4j/index/solr/SolrQueryServiceTest.java
deleted file mode 100644
index c949649..0000000
--- a/extensions/indexing-solr/src/test/java/org/qi4j/index/solr/SolrQueryServiceTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.index.solr;
-
-import java.io.File;
-import org.apache.solr.client.solrj.SolrServerException;
-import org.apache.solr.common.SolrDocument;
-import org.apache.solr.common.SolrDocumentList;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.junit.Rule;
-import org.qi4j.library.fileconfig.FileConfigurationOverride;
-import org.qi4j.test.util.DelTreeAfter;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-
-public class SolrQueryServiceTest
-    extends AbstractQi4jTest
-{
-
-    private static final File DATA_DIR = new File( "build/tmp/solr-query-service-test" );
-    @Rule
-    public final DelTreeAfter delTreeAfter = new DelTreeAfter( DATA_DIR );
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.layer().application().setMode( Application.Mode.test );
-
-        FileConfigurationOverride override = new FileConfigurationOverride().withData( new File( DATA_DIR, "qi4j-data" ) ).
-            withLog( new File( DATA_DIR, "qi4j-logs" ) ).withTemporary( new File( DATA_DIR, "qi4j-temp" ) );
-        module.services( FileConfigurationService.class ).
-            setMetaInfo( override );
-
-        new EntityTestAssembler().assemble( module );
-        // START SNIPPET: assembly
-        new SolrAssembler().assemble( module );
-        // END SNIPPET: assembly
-
-        module.entities( TestEntity.class );
-    }
-
-    @Before
-    public void index()
-        throws UnitOfWorkCompletionException, InterruptedException
-    {
-        // Create and index an entity
-        UnitOfWork uow = module.newUnitOfWork();
-        TestEntity test = uow.newEntity( TestEntity.class );
-        test.name().set( "Hello World" );
-        uow.complete();
-        Thread.sleep( 40 );
-    }
-
-    @Test
-    public void testQuery()
-        throws UnitOfWorkCompletionException
-    {
-        // Search for it
-        UnitOfWork uow = module.newUnitOfWork();
-        Query<TestEntity> query = uow.newQuery( module.newQueryBuilder( TestEntity.class ).where( SolrExpressions.search( "hello" ) ) );
-
-        TestEntity test = query.find();
-        Assert.assertThat( test.name().get(), equalTo( "Hello World" ) );
-
-        uow.discard();
-    }
-
-    @Test
-    public void testSearch()
-        throws UnitOfWorkCompletionException, SolrServerException
-    {
-        // Search for it using search interface
-        SolrSearch search = (SolrSearch) module.findService( SolrSearch.class ).get();
-
-        SolrDocumentList results = search.search( "hello" );
-
-        List<String> lookAhead = new ArrayList<String>();
-        for( SolrDocument result : results )
-        {
-            lookAhead.add( result.getFieldValue( "name" ).toString() );
-        }
-
-        Assert.assertThat( lookAhead.toString(), equalTo( "[Hello World]" ) );
-    }
-
-    public interface TestEntity
-        extends EntityComposite
-    {
-
-        @UseDefaults
-        Property<String> name();
-
-    }
-
-}
diff --git a/extensions/indexing-solr/src/test/java/org/qi4j/index/solr/SolrQueryTest.java b/extensions/indexing-solr/src/test/java/org/qi4j/index/solr/SolrQueryTest.java
deleted file mode 100644
index 1e88066..0000000
--- a/extensions/indexing-solr/src/test/java/org/qi4j/index/solr/SolrQueryTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.index.solr;
-
-import java.io.File;
-import org.junit.Ignore;
-import org.junit.Rule;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.fileconfig.FileConfigurationOverride;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.test.indexing.AbstractQueryTest;
-import org.qi4j.test.util.DelTreeAfter;
-
-@Ignore( "SOLR Index/Query is not working at all" )
-public class SolrQueryTest
-    extends AbstractQueryTest
-{
-
-    private static final File DATA_DIR = new File( "build/tmp/solr-query-test" );
-    @Rule
-    public final DelTreeAfter delTreeAfter = new DelTreeAfter( DATA_DIR );
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        FileConfigurationOverride override = new FileConfigurationOverride().withData( new File( DATA_DIR, "qi4j-data" ) ).
-            withLog( new File( DATA_DIR, "qi4j-logs" ) ).withTemporary( new File( DATA_DIR, "qi4j-temp" ) );
-        module.services( FileConfigurationService.class ).
-            setMetaInfo( override );
-        new SolrAssembler().assemble( module );
-    }
-
-}
diff --git a/extensions/indexing-solr/src/test/resources/schema.xml b/extensions/indexing-solr/src/test/resources/schema.xml
index d9e5ae1..d7f70fb 100644
--- a/extensions/indexing-solr/src/test/resources/schema.xml
+++ b/extensions/indexing-solr/src/test/resources/schema.xml
@@ -1,20 +1,23 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <!--
  This is the Solr schema file. This file should be named "schema.xml" and
  should be in the conf directory under the solr home
@@ -258,12 +261,12 @@
 
         <fieldType name="phone" class="solr.TextField" positionIncrementGap="100">
             <analyzer type="index">
-                <tokenizer class="org.qi4j.index.solr.internal.SingleTokenTokenizerFactory"/>
+                <tokenizer class="org.apache.polygene.index.solr.internal.SingleTokenTokenizerFactory"/>
                 <filter class="solr.WordDelimiterFilterFactory" generateWordParts="0" generateNumberParts="0"
                         catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="0"/>
             </analyzer>
             <analyzer type="query">
-                <tokenizer class="org.qi4j.index.solr.internal.SingleTokenTokenizerFactory"/>
+                <tokenizer class="org.apache.polygene.index.solr.internal.SingleTokenTokenizerFactory"/>
                 <filter class="solr.WordDelimiterFilterFactory" generateWordParts="0" generateNumberParts="0"
                         catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="0"/>
             </analyzer>
@@ -400,7 +403,7 @@
             "encoder" - how to encode the following value into a playload
                float -> org.apache.lucene.analysis.payloads.FloatEncoder,
                integer -> o.a.l.a.p.IntegerEncoder
-               identity -> o.a.l.a.p.IdentityEncoder
+               reference -> o.a.l.a.p.IdentityEncoder
                    Fully Qualified class name implementing PayloadEncoder, Encoder must have a no arg constructor.
                 -->
                 <filter class="solr.DelimitedPayloadTokenFilterFactory" encoder="float"/>
diff --git a/extensions/indexing-solr/src/test/resources/solrconfig.xml b/extensions/indexing-solr/src/test/resources/solrconfig.xml
index f3cfd16..a8f7527 100644
--- a/extensions/indexing-solr/src/test/resources/solrconfig.xml
+++ b/extensions/indexing-solr/src/test/resources/solrconfig.xml
@@ -1,20 +1,23 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <!--
      For more details about configurations options that may appear in this
      file, see http://wiki.apache.org/solr/SolrConfigXml.
diff --git a/extensions/indexing-sql/build.gradle b/extensions/indexing-sql/build.gradle
index 9330210..5d6f71e 100644
--- a/extensions/indexing-sql/build.gradle
+++ b/extensions/indexing-sql/build.gradle
@@ -1,45 +1,45 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ SQL Indexing Extension"
+apply plugin: 'polygene-extension'
 
-jar {manifest {name = "Apache Zest™ Extension - Indexing - SQL"}}
+description = "Apache Polygene™ SQL Indexing Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - Indexing - SQL" } }
 
 dependencies {
+  api polygene.core.bootstrap
+  api polygene.library( 'sql' )
 
-  compile project(":org.qi4j.core:org.qi4j.core.bootstrap")
-  compile project(":org.qi4j.libraries:org.qi4j.library.sql")
-  compile project(':org.qi4j.extensions:org.qi4j.extension.reindexer')
-  compile libraries.javaSqlGenerator
-  compile( libraries.javaSqlGeneratorImpl ) { 
-      exclude group: 'junit'
-  }
+  implementation polygene.library( 'sql-generator' )
+  implementation polygene.extension( 'reindexer' )
 
-  testCompile project(":org.qi4j.core:org.qi4j.core.testsupport")
-  testCompile project(":org.qi4j.libraries:org.qi4j.library.sql-dbcp")
+  runtimeOnly polygene.core.runtime
 
-  testRuntime project(":org.qi4j.core:org.qi4j.core.runtime")
-  testRuntime libraries.logback
-  testRuntime libraries.derby
-  testRuntime libraries.h2
-  testRuntime libraries.mysql_connector
-  testRuntime libraries.postgres
-  testRuntime libraries.sqlite
+  testImplementation polygene.internals.testsupport
+  testImplementation polygene.library( 'sql-dbcp' )
 
+  testRuntimeOnly libraries.logback
+  testRuntimeOnly libraries.derby
+  testRuntimeOnly libraries.h2
+  testRuntimeOnly libraries.mysql_connector
+  testRuntimeOnly libraries.postgres
+  testRuntimeOnly libraries.sqlite
 }
diff --git a/extensions/indexing-sql/dev-status.xml b/extensions/indexing-sql/dev-status.xml
index ac63cda..762e250 100644
--- a/extensions/indexing-sql/dev-status.xml
+++ b/extensions/indexing-sql/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
         <!--none,early,beta,stable,mature-->
         <codebase>stable</codebase>
diff --git a/extensions/indexing-sql/instructions.txt b/extensions/indexing-sql/instructions.txt
index 3b38bca..0f45830 100644
--- a/extensions/indexing-sql/instructions.txt
+++ b/extensions/indexing-sql/instructions.txt
@@ -17,18 +17,18 @@
  * under the License.
 ///////////////////////////////////////////////////////////////
 
-These instructions are for preparing your out-of-box PostgreSQL installation so it would be usable with PostgreSQL indexing of Zest.
+These instructions are for preparing your out-of-box PostgreSQL installation so it would be usable with PostgreSQL indexing of Polygene.
 
 1. Creating login role and database
-1.1. Using pgAdmin, connect to PostgreSQL database, and create database you intend to use to store Zest™ entity data, and login role for Zest™ application to use when it connects to database.
+1.1. Using pgAdmin, connect to PostgreSQL database, and create database you intend to use to store Polygene™ entity data, and login role for Polygene™ application to use when it connects to database.
 1.1. Update these values into your .properties file, if necessary.
 
 2. Adding ltree as type
-2.1. Using pgAdmin, connect to PostgreSQL database, and navigate to database which is intended to be used for Zest. (Click on it)
+2.1. Using pgAdmin, connect to PostgreSQL database, and navigate to database which is intended to be used for Polygene. (Click on it)
 2.2. Executing arbitary SQL queries should be possible, click that button (button with SQL text on it, next to trash bin).
 2.3. This will open new window, erase any text which pgAdmin generates there for you.
 2.4. Then navigate to your PostgreSQL installation directory, then into 'share', and then into 'contrib'. Open file 'ltree.sql' in your favorite text editor.
 2.5. Select all text, copy it, and paste to SQL query window which you opened in stage 2.2.
-2.6. If you know what you are doing, you may change the line 'SET search_path = public;' to make search_path be 'pg_catalog', or name of schema that Zest™ application will use ('qi4j' by default). It's ok to leave it to 'public' though.
+2.6. If you know what you are doing, you may change the line 'SET search_path = public;' to make search_path be 'pg_catalog', or name of schema that Polygene™ application will use ('polygene' by default). It's ok to leave it to 'public' though.
 2.7. Hit F5 or go Query -> Execute Query to execute the SQL. It should print some notices into output window but no errors nor warnings should be present.
 2.8. Ltree type should be now installed to your PostgreSQL installation.
diff --git a/extensions/indexing-sql/src/docs/index-sql.txt b/extensions/indexing-sql/src/docs/index-sql.txt
index 5d6fc57..7de12dd 100644
--- a/extensions/indexing-sql/src/docs/index-sql.txt
+++ b/extensions/indexing-sql/src/docs/index-sql.txt
@@ -43,7 +43,7 @@
 == Configuration ==
 
 SQL Index/Query Configuration is optional and provides only one configuration property: `schemaName` defaulted to
-'qi4j_es'. On SQL databases that don't support schemas this configuration property is simply ignored.
+'polygene_es'. On SQL databases that don't support schemas this configuration property is simply ignored.
 
 The assembly snippets below show the DataSource assembly alongside the SQL Index/Query assembly. Remember to configure
 the DataSource properly, see <<library-sql>> and <<howto-configure-service>>.
@@ -55,7 +55,7 @@
 
 [snippet,java]
 ----
-source=extensions/indexing-sql/src/test/java/org/qi4j/index/sql/postgresql/SQLTestHelper.java
+source=extensions/indexing-sql/src/test/java/org/apache/polygene/index/sql/postgresql/SQLTestHelper.java
 tag=assembly
 ----
 
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/SQLIndexingEngineConfiguration.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/SQLIndexingEngineConfiguration.java
new file mode 100644
index 0000000..5920ed6
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/SQLIndexingEngineConfiguration.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.index.sql;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.sql.common.SQLConfiguration;
+
+public interface SQLIndexingEngineConfiguration extends SQLConfiguration
+{
+    @UseDefaults( "POLYGENE_INDEX" )
+    @Override
+    Property<String> schemaName();
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/SQLIndexingEngineService.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/SQLIndexingEngineService.java
new file mode 100644
index 0000000..e43d465
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/SQLIndexingEngineService.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.index.sql;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.index.sql.internal.SQLEntityFinder;
+import org.apache.polygene.index.sql.internal.SQLStateChangeListener;
+import org.apache.polygene.spi.entitystore.StateChangeListener;
+import org.apache.polygene.spi.query.EntityFinder;
+
+/**
+ * This is actual service responsible of managing indexing and queries and creating database structure.
+ * <p>
+ * The reason why all these components are in one single service is that they all require some data about
+ * the database structure. Rather than exposing all of that data publicly to be available via another service,
+ * it is stored in a state-style private mixin. Thus all the database-related data is available only to this
+ * service, and no one else.
+ * </p>
+ */
+@Mixins( {
+    SQLEntityFinder.class,
+    SQLStateChangeListener.class
+} )
+public interface SQLIndexingEngineService
+        extends StateChangeListener, EntityFinder
+{
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/assembly/AbstractSQLIndexQueryAssembler.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/assembly/AbstractSQLIndexQueryAssembler.java
new file mode 100644
index 0000000..776c3c9
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/assembly/AbstractSQLIndexQueryAssembler.java
@@ -0,0 +1,99 @@
+/*
+ *  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.polygene.index.sql.assembly;
+
+import java.io.IOException;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.reindexer.ReindexerConfiguration;
+import org.apache.polygene.index.reindexer.ReindexerService;
+import org.apache.polygene.index.sql.SQLIndexingEngineConfiguration;
+import org.apache.polygene.index.sql.support.common.ReindexingStrategy;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+
+public abstract class AbstractSQLIndexQueryAssembler<AssemblerType>
+    extends Assemblers.VisibilityIdentityConfig<AssemblerType>
+{
+    public static final Identity DEFAULT_IDENTITY = new StringIdentity( "indexing-sql" );
+
+    private Class<? extends ReindexingStrategy> reindexingStrategy = ReindexingStrategy.NeverNeed.class;
+
+    public AbstractSQLIndexQueryAssembler()
+    {
+        identifiedBy( DEFAULT_IDENTITY.toString() );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    public AssemblerType withReindexingStrategy( Class<? extends ReindexingStrategy> reindexingStrategy )
+    {
+        this.reindexingStrategy = reindexingStrategy;
+        return (AssemblerType) this;
+    }
+
+    protected SQLVendor getSQLVendor()
+        throws IOException
+    {
+        return SQLVendorProvider.createVendor( SQLVendor.class );
+    }
+
+    protected abstract Class<?> getIndexQueryServiceType();
+
+    @Override
+    public final void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        try
+        {
+            SQLVendor sqlVendor = getSQLVendor();
+            if( sqlVendor == null )
+            {
+                throw new AssemblyException( "SQL Vendor could not be determined." );
+            }
+            module.services( getIndexQueryServiceType() )
+                  .taggedWith( "sql", "query", "indexing" )
+                  .identifiedBy( identity() )
+                  .setMetaInfo( sqlVendor )
+                  .visibleIn( visibility() )
+                  .instantiateOnStartup();
+        }
+        catch( IOException ex )
+        {
+            throw new AssemblyException( "SQL Vendor could not be created", ex );
+        }
+
+        module.services( ReindexerService.class ).
+            visibleIn( Visibility.module );
+        module.services( ReindexingStrategy.class ).
+            withMixins( reindexingStrategy ).
+                  visibleIn( Visibility.module );
+
+        if( hasConfig() )
+        {
+            configModule().entities( SQLIndexingEngineConfiguration.class,
+                                     ReindexerConfiguration.class ).
+                              visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/assembly/PostgreSQLIndexQueryAssembler.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/assembly/PostgreSQLIndexQueryAssembler.java
new file mode 100644
index 0000000..b5e8cc6
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/assembly/PostgreSQLIndexQueryAssembler.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.index.sql.assembly;
+
+import java.io.IOException;
+import org.apache.polygene.index.sql.support.postgresql.PostgreSQLService;
+import org.apache.polygene.library.sql.generator.vendor.PostgreSQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+
+public class PostgreSQLIndexQueryAssembler
+    extends AbstractSQLIndexQueryAssembler<PostgreSQLIndexQueryAssembler>
+{
+
+    @Override
+    protected SQLVendor getSQLVendor()
+        throws IOException
+    {
+        return SQLVendorProvider.createVendor( PostgreSQLVendor.class );
+    }
+
+    @Override
+    protected Class<?> getIndexQueryServiceType()
+    {
+        return PostgreSQLService.class;
+    }
+
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/assembly/SQLIndexingAssembler.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/assembly/SQLIndexingAssembler.java
new file mode 100644
index 0000000..af137de
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/assembly/SQLIndexingAssembler.java
@@ -0,0 +1,24 @@
+/*
+ *  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.polygene.index.sql.assembly;
+
+public class SQLIndexingAssembler extends PostgreSQLIndexQueryAssembler
+{
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/assembly/package.html b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/assembly/package.html
new file mode 100644
index 0000000..89cec89
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL Index/Query Assembly.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/internal/SQLEntityFinder.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/internal/SQLEntityFinder.java
new file mode 100644
index 0000000..c074425
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/internal/SQLEntityFinder.java
@@ -0,0 +1,256 @@
+/*
+ *  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.polygene.index.sql.internal;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import javax.sql.DataSource;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.index.sql.support.api.SQLQuerying;
+import org.apache.polygene.library.sql.common.SQLUtil;
+import org.apache.polygene.spi.query.EntityFinder;
+import org.apache.polygene.spi.query.EntityFinderException;
+
+public class SQLEntityFinder
+    implements EntityFinder
+{
+    @Service
+    private SQLQuerying parser;
+
+    @Service
+    private DataSource _dataSource;
+
+    /**
+     * Helper interface to perform some SQL query. Using this simplifies the structure of some of the methods.
+     *
+     * @param <ReturnType> The return type of something to be done.
+     */
+    private interface DoQuery<ReturnType>
+    {
+        ReturnType doIt( Connection connection )
+            throws SQLException;
+    }
+
+    @Override
+    public long countEntities( Class<?> resultType, @Optional Predicate<Composite> whereClause, Map<String, Object> variables )
+        throws EntityFinderException
+    {
+        final List<Object> values = new ArrayList<>();
+        final List<Integer> valueSQLTypes = new ArrayList<>();
+        final String query = this.parser.constructQuery( resultType, whereClause, null, null, null, variables, values,
+                                                         valueSQLTypes, true );
+
+        return this.performQuery( new DoQuery<Long>()
+        {
+
+            @Override
+            public Long doIt( Connection connection )
+                throws SQLException
+            {
+                PreparedStatement ps = null;
+                ResultSet rs = null;
+                try
+                {
+                    ps = createPS( connection, query, values, valueSQLTypes );
+                    rs = ps.executeQuery();
+                    rs.next();
+                    return rs.getLong( 1 );
+                }
+                finally
+                {
+                    SQLUtil.closeQuietly( rs );
+                    SQLUtil.closeQuietly( ps );
+                }
+            }
+        } );
+    }
+
+    @Override
+    public Stream<EntityReference> findEntities( Class<?> resultType,
+                                                 Predicate<Composite> whereClause,
+                                                 List<OrderBy> orderBySegments,
+                                                 Integer firstResult,
+                                                 Integer maxResults,
+                                                 Map<String, Object> variables ) throws EntityFinderException
+    {
+        // TODO what is Polygene's policy on negative firstResult and/or maxResults? JDBC has its own way of interpreting
+        // these values - does it match with Polygene's way?
+        if( maxResults == null || maxResults > 0 )
+        {
+            final List<Object> values = new ArrayList<>();
+            final List<Integer> valueSQLTypes = new ArrayList<>();
+            final String query = this.parser.constructQuery( resultType, whereClause, orderBySegments, firstResult,
+                                                             maxResults, variables, values, valueSQLTypes, false );
+
+            List<EntityReference> result = this.performQuery( new DoQuery<List<EntityReference>>()
+            {
+                @Override
+                public List<EntityReference> doIt( Connection connection )
+                    throws SQLException
+                {
+                    PreparedStatement ps = null;
+                    ResultSet rs = null;
+                    List<EntityReference> resultList = new ArrayList<>( maxResults == null ? 100 : maxResults );
+                    try
+                    {
+                        // TODO possibility to further optimize by setting fetch size (not too small not too little).
+                        Integer rsType = parser.getResultSetType( firstResult, maxResults );
+                        ps = createPS( connection, query, values, valueSQLTypes,
+                                       rsType, ResultSet.CLOSE_CURSORS_AT_COMMIT );
+                        rs = ps.executeQuery();
+                        if( firstResult != null
+                            && !parser.isFirstResultSettingSupported()
+                            && rsType != ResultSet.TYPE_FORWARD_ONLY )
+                        {
+                            rs.absolute( firstResult );
+                        }
+                        Integer i = 0;
+                        while( rs.next() && ( maxResults == null || i < maxResults ) )
+                        {
+                            resultList.add( EntityReference.parseEntityReference( rs.getString( 1 ) ) );
+                            ++i;
+                        }
+                    }
+                    finally
+                    {
+                        SQLUtil.closeQuietly( rs );
+                        SQLUtil.closeQuietly( ps );
+                    }
+
+                    return resultList;
+                }
+            } );
+            return result.stream();
+        }
+        else
+        {
+            return Stream.of();
+        }
+    }
+
+    @Override
+    public EntityReference findEntity( Class<?> resultType,
+                                       @Optional Predicate<Composite> whereClause,
+                                       Map<String, Object> variables )
+        throws EntityFinderException
+    {
+        final List<Object> values = new ArrayList<>();
+        final List<Integer> valueSQLTypes = new ArrayList<>();
+        final String query = this.parser.constructQuery( resultType, whereClause, null, null, null, variables, values,
+                                                         valueSQLTypes, false );
+
+        return this.performQuery( new DoQuery<EntityReference>()
+        {
+            @Override
+            public EntityReference doIt( Connection connection )
+                throws SQLException
+            {
+                PreparedStatement ps = null;
+                ResultSet rs = null;
+                EntityReference result = null;
+                try
+                {
+                    ps = createPS( connection, query, values, valueSQLTypes );
+                    ps.setFetchSize( 1 );
+                    ps.setMaxRows( 1 );
+                    rs = ps.executeQuery();
+                    if( rs.next() )
+                    {
+                        result = EntityReference.parseEntityReference( rs.getString( 1 ) );
+                    }
+                }
+                finally
+                {
+                    SQLUtil.closeQuietly( rs );
+                    SQLUtil.closeQuietly( ps );
+                }
+
+                return result;
+            }
+        } );
+    }
+
+    private PreparedStatement createPS( Connection connection, String query,
+                                        List<Object> values, List<Integer> valueSQLTypes )
+        throws SQLException
+    {
+        return this.createPS( connection, query, values, valueSQLTypes,
+                              ResultSet.TYPE_FORWARD_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT );
+    }
+
+    private PreparedStatement createPS( Connection connection, String query,
+                                        List<Object> values, List<Integer> valueSQLTypes,
+                                        Integer resultSetType, Integer resultSetHoldability )
+        throws SQLException
+    {
+        PreparedStatement ps = connection.prepareStatement( query, resultSetType,
+                                                            ResultSet.CONCUR_READ_ONLY, resultSetHoldability );
+        if( values.size() != valueSQLTypes.size() )
+        {
+            throw new InternalError( "There was either too little or too much sql types for values [values="
+                                     + values.size() + ", types=" + valueSQLTypes.size() + "]." );
+        }
+
+        for( Integer x = 0; x < values.size(); ++x )
+        {
+            ps.setObject( x + 1, values.get( x ), valueSQLTypes.get( x ) );
+        }
+
+        return ps;
+    }
+
+    // Helper method to perform SQL queries and handle things if/when something happens
+    private <ReturnType> ReturnType performQuery( DoQuery<ReturnType> doQuery )
+        throws EntityFinderException
+    {
+        ReturnType result = null;
+        Connection connection = null;
+        try
+        {
+            connection = this._dataSource.getConnection();
+            connection.setReadOnly( true );
+
+            result = doQuery.doIt( connection );
+
+        }
+        catch( SQLException sqle )
+        {
+            throw new EntityFinderException( SQLUtil.withAllSQLExceptions( sqle ) );
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( connection );
+        }
+
+        return result;
+    }
+
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/internal/SQLStateChangeListener.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/internal/SQLStateChangeListener.java
new file mode 100644
index 0000000..fb6376a
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/internal/SQLStateChangeListener.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.index.sql.internal;
+
+import java.sql.SQLException;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.unitofwork.UnitOfWorkException;
+import org.apache.polygene.index.sql.support.api.SQLIndexing;
+import org.apache.polygene.library.sql.common.SQLUtil;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entitystore.StateChangeListener;
+
+public class SQLStateChangeListener
+    implements StateChangeListener
+{
+    @Service
+    private SQLIndexing _indexing;
+
+    @Override
+    public void notifyChanges( Iterable<EntityState> changedStates )
+    {
+        try
+        {
+            this._indexing.indexEntities( changedStates );
+        }
+        catch( SQLException sqle )
+        {
+            // TODO is UoWException right one for this?
+            throw new UnitOfWorkException( SQLUtil.withAllSQLExceptions( sqle ) );
+        }
+    }
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/internal/package.html b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/internal/package.html
new file mode 100644
index 0000000..1e4e030
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/internal/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL Index/Query Internal Package.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/package.html b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/package.html
new file mode 100644
index 0000000..8a5d434
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL Index/Query.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/api/SQLAppStartup.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/api/SQLAppStartup.java
new file mode 100644
index 0000000..a50ab83
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/api/SQLAppStartup.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.index.sql.support.api;
+
+import java.sql.SQLException;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.service.ServiceReference;
+
+/**
+ * This is the interface which is called by SQL-Indexing when it is activated. This allows implementation specific
+ * initializations for RDBMS (for example, possibly re-building database structure).
+ */
+@Activators( SQLAppStartup.Activator.class )
+public interface SQLAppStartup
+{
+
+    /**
+     * This method is called when connection may be safely initialized - for example, possibly (re-)building database
+     * structure.
+     * 
+     * @throws SQLException If SQL error.
+     */
+    void initConnection()
+        throws SQLException;
+
+    class Activator
+        extends ActivatorAdapter<ServiceReference<SQLAppStartup>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<SQLAppStartup> activated )
+            throws Exception
+        {
+            activated.get().initConnection();
+        }
+
+    }
+
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/api/SQLIndexing.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/api/SQLIndexing.java
new file mode 100644
index 0000000..fd4fcba
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/api/SQLIndexing.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.index.sql.support.api;
+
+import java.sql.SQLException;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * This is the interface used by SQL-Indexing whenever
+ */
+public interface SQLIndexing
+{
+    /**
+     * This method is called when states need to be indexed.
+     * 
+     * @param changedStates The states which changed.
+     * @throws SQLException If SQL.
+     */
+    void indexEntities( Iterable<EntityState> changedStates )
+        throws SQLException;
+
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/api/SQLQuerying.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/api/SQLQuerying.java
new file mode 100644
index 0000000..e5722df
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/api/SQLQuerying.java
@@ -0,0 +1,75 @@
+/*
+ *  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.polygene.index.sql.support.api;
+
+import java.sql.PreparedStatement;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.spi.query.EntityFinderException;
+
+/**
+ * This interface provides parsing support from Polygene queries to SQL queries. The idea is that this interface produces
+ * SQL which can be used when creating a {@link PreparedStatement}.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SQLQuerying
+{
+    /**
+     * This method will be called when parsing needs to be done from Polygene query to SQL query. This method is supposed to
+     * return one single SQL query, which can be used with {@link PreparedStatement}.
+     *
+     * @param resultType The result type of Polygene query.
+     * @param whereClause The where clause of Polygene query.
+     * @param orderBySegments The order by segments of Polygene query.
+     * @param firstResult The first result index of Polygene query.
+     * @param maxResults The max amount of returned results.
+     * @param values Values to put into {@link PreparedStatement}, in the order of the list. This List is created from
+     *            the outside and this method is supposed to fill it with necessary values, if any.
+     * @param valueSqlTypes The SQL types of the objects in {@code values}. Each SQL type at index {@code x} is
+     *            interpreted as type of value at index {@code x} of the {@code values} -list.
+     * @param countOnly True if this query should return only the number of matching entities, false otherwise.
+     * @return The SQL query, which may be used with {@link PreparedStatement}.
+     * @throws EntityFinderException If SQLException or something else bad happens.
+     */
+    String constructQuery( //
+        Class<?> resultType, //
+        @Optional Predicate<Composite> whereClause, //
+        @Optional List<OrderBy> orderBySegments, //
+        @Optional Integer firstResult, //
+        @Optional Integer maxResults, //
+        Map<String, Object> variables,
+        List<Object> values, //
+        List<Integer> valueSqlTypes, //
+        Boolean countOnly //
+    )
+        throws EntityFinderException;
+
+    Boolean isFirstResultSettingSupported();
+
+    Integer getResultSetType( //
+        @Optional Integer firstResult, //
+        @Optional Integer maxResults //
+    );
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/api/SQLTypeInfo.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/api/SQLTypeInfo.java
new file mode 100644
index 0000000..62ff3df
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/api/SQLTypeInfo.java
@@ -0,0 +1,58 @@
+/*
+ *  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.polygene.index.sql.support.api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+/**
+ * The annotation, which tells the parameters for SQL type. Only applyable to certain typed properties, like for now,
+ * {@link String}, {@link BigInteger}, and {@link BigDecimal}.
+ *
+ * Example of usage, where we want to limit the datatype of column storing this value in RDBMS to be 100 characters of
+ * max length:
+ * <pre>@SQLTypeInfo(maxLength=100)
+ * public Property&lt;String&gt; myStringProperty();</pre>
+ *
+ * The purpose of this class is to optimize performance for people who know for certain that they will be using
+ * SQL-Indexing in their application.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( ElementType.METHOD )
+public @interface SQLTypeInfo
+{
+    /**
+     * For {@link String}s, this is the max character length as specified by {@code VARCHAR(length)}. For {@link BigInteger}s and {@link BigDecimal}s,
+     * this is the precision of a {@code NUMERIC}.
+     * @return Maximum length for SQL data type representing some property type.
+     */
+    int maxLength();
+
+    /**
+     * For {@link String}s and {@link BigInteger}s, this value is ignored. For {@link BigDecimal}s, this is the scale of {@code NUMERIC}, default being {@code 50}.
+     *
+     * @return The scale of SQL data type representing some property type.
+     */
+    int scale() default 50;
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/api/package.html b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/api/package.html
new file mode 100644
index 0000000..131ebbd
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/api/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL Index/Query Vendors Support API.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/DBNames.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/DBNames.java
new file mode 100644
index 0000000..0676f65
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/DBNames.java
@@ -0,0 +1,95 @@
+/*
+ *  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.polygene.index.sql.support.common;
+
+/**
+ * This is helper class to contain all the SQL constants used throughout the SQL Indexing.
+ * 
+ * @author Stanislav Muhametsin
+ * 
+ */
+public class DBNames
+{
+
+    public static final String QNAME_TABLE_NAME_PREFIX = "qname_";
+
+    public static final String QNAME_TABLE_VALUE_COLUMN_NAME = "qname_value";
+
+    public static final String QNAME_TABLE_ASSOCIATION_INDEX_COLUMN_NAME = "asso_index";
+
+    public static final String QNAME_TABLE_PARENT_QNAME_COLUMN_NAME = "parent_qname";
+
+    public static final String QNAME_TABLE_COLLECTION_PATH_COLUMN_NAME = "collection_path";
+
+    public static final String QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME = "Top";
+
+    public static final String QNAME_TABLE_COLLECTION_PATH_SEPARATOR = ".";
+
+    public static final String ALL_QNAMES_TABLE_NAME = "all_qnames";
+
+    public static final String ALL_QNAMES_TABLE_PK_COLUMN_NAME = "qname_id";
+
+    public static final String USED_CLASSES_TABLE_NAME = "used_classes";
+
+    public static final String USED_CLASSES_TABLE_PK_COLUMN_NAME = "used_class_id";
+
+    public static final String USED_CLASSES_TABLE_CLASS_NAME_COLUMN_NAME = "class_name";
+
+    public static final String USED_QNAMES_TABLE_NAME = "used_qnames";
+
+    public static final String USED_QNAMES_TABLE_QNAME_COLUMN_NAME = "qname";
+
+    public static final String USED_QNAMES_TABLE_TABLE_NAME_COLUMN_NAME = "table_name";
+
+    public static final String ENTITY_TYPES_TABLE_PK_COLUMN_NAME = "entity_type_id";
+
+    public static final String ENTITY_TYPES_TABLE_TYPE_NAME_COLUMN_NAME = "entity_type_name";
+
+    public static final String ENTITY_TYPES_TABLE_NAME = "entity_types";
+
+    public static final String ENTITY_TABLE_NAME = "indexing_entities";
+
+    public static final String ENTITY_TABLE_PK_COLUMN_NAME = "entity_pk";
+
+    public static final String ENTITY_TABLE_IDENTITY_COLUMN_NAME = "entity_identity";
+
+    public static final String ENTITY_TABLE_MODIFIED_COLUMN_NAME = "modified";
+
+    public static final String ENTITY_TABLE_VERSION_COLUMN_NAME = "entity_version";
+
+    public static final String ENTITY_TABLE_APPLICATION_VERSION_COLUMN_NAME = "application_version";
+
+    public static final String ENTITY_TYPES_JOIN_TABLE_NAME = ENTITY_TABLE_NAME + "_" + ENTITY_TYPES_TABLE_NAME;
+
+    public static final String APP_VERSION_TABLE_NAME = "app_version";
+
+    public static final String APP_VERSION_PK_COLUMN_NAME = "app_version";
+
+    public static final String ENUM_LOOKUP_TABLE_NAME = "enum_lookup";
+
+    public static final String ENUM_LOOKUP_TABLE_PK_COLUMN_NAME = "enum_id";
+
+    public static final String ENUM_LOOKUP_TABLE_ENUM_VALUE_NAME = "enum_value";
+
+    private DBNames()
+    {
+    }
+
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/GenericDatabaseExplorer.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/GenericDatabaseExplorer.java
new file mode 100644
index 0000000..d6128fd
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/GenericDatabaseExplorer.java
@@ -0,0 +1,456 @@
+/*
+ *  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.polygene.index.sql.support.common;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.polygene.library.sql.common.SQLUtil;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.QuerySpecificationBuilder;
+import org.apache.polygene.library.sql.generator.grammar.factories.QueryFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.TableReferenceFactory;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.spi.query.IndexExporter;
+
+/**
+ * This is a helper class to traverse through all content in specified tables in database. Typical usecase would be by
+ * {@link IndexExporter} implementation.
+ */
+public final class GenericDatabaseExplorer
+{
+    public enum IntegrityActions
+    {
+        CASCADE,
+        NO_ACTION,
+        RESTRICT,
+        SET_DEFAULT,
+        SET_NULL
+    }
+
+    public enum Deferrability
+    {
+        INITIALLY_DEFERRED,
+        INITIALLY_IMMEDIATE,
+        NOT_DEFERRABLE
+    }
+
+    private static final Map<Integer, IntegrityActions> INTEGRITY_ACTIONS;
+
+    private static final Map<Integer, Deferrability> DEFERRABILITIES;
+
+    static
+    {
+        DEFERRABILITIES = new HashMap<>( 3 );
+        DEFERRABILITIES.put( DatabaseMetaData.importedKeyInitiallyDeferred, Deferrability.INITIALLY_DEFERRED );
+        DEFERRABILITIES.put( DatabaseMetaData.importedKeyInitiallyImmediate, Deferrability.INITIALLY_IMMEDIATE );
+        DEFERRABILITIES.put( DatabaseMetaData.importedKeyNotDeferrable, Deferrability.NOT_DEFERRABLE );
+
+        INTEGRITY_ACTIONS = new HashMap<>( 5 );
+        INTEGRITY_ACTIONS.put( DatabaseMetaData.importedKeyCascade, IntegrityActions.CASCADE );
+        INTEGRITY_ACTIONS.put( DatabaseMetaData.importedKeyNoAction, IntegrityActions.NO_ACTION );
+        INTEGRITY_ACTIONS.put( DatabaseMetaData.importedKeyRestrict, IntegrityActions.RESTRICT );
+        INTEGRITY_ACTIONS.put( DatabaseMetaData.importedKeySetDefault, IntegrityActions.SET_DEFAULT );
+        INTEGRITY_ACTIONS.put( DatabaseMetaData.importedKeySetNull, IntegrityActions.SET_NULL );
+    }
+
+    public static class ColumnInfo
+    {
+
+        private final String _name;
+
+        private final Integer _sqlType;
+
+        private final String _typeName;
+
+        private final Integer _size;
+
+        private final Integer _scale;
+
+        private final String _nullable;
+
+        private final String _defaultValue;
+
+        private final String _remarks;
+
+        private ColumnInfo( String name, Integer sqlType, String typeName, Integer size, Integer scale,
+                            String nullable, String defaultValue, String remarks )
+        {
+            this._name = name;
+            this._sqlType = sqlType;
+            this._typeName = typeName;
+            this._size = size;
+            this._scale = scale;
+            this._nullable = nullable;
+            this._defaultValue = defaultValue;
+            this._remarks = remarks;
+        }
+
+        public String getName()
+        {
+            return this._name;
+        }
+
+        public String getTypeName()
+        {
+            return this._typeName;
+        }
+
+        public Integer getSize()
+        {
+            return this._size;
+        }
+
+        public Integer getScale()
+        {
+            return this._scale;
+        }
+
+        public String getNullable()
+        {
+            return this._nullable;
+        }
+
+        public String getDefaultValue()
+        {
+            return this._defaultValue;
+        }
+
+        public String getRemarks()
+        {
+            return this._remarks;
+        }
+
+        public Integer getSQLType()
+        {
+            return this._sqlType;
+        }
+    }
+
+    public static class ForeignKeyInfo
+    {
+
+        private final String _pkSchemaName;
+
+        private final String _pkTableName;
+
+        private final String _pkTablePKColumnName;
+
+        private final IntegrityActions _onUpdateAction;
+
+        private final IntegrityActions _onDeleteAction;
+
+        private final Deferrability _deferrability;
+
+        private ForeignKeyInfo( String pkSchemaName, String pkTableName, String pkTablePKColumnName, short onUpdate,
+                                short onDelete, short deferrability )
+        {
+            this._pkSchemaName = pkSchemaName;
+            this._pkTableName = pkTableName;
+            this._pkTablePKColumnName = pkTablePKColumnName;
+            this._onUpdateAction = INTEGRITY_ACTIONS.get( (int) onUpdate );
+            this._onDeleteAction = INTEGRITY_ACTIONS.get( (int) onDelete );
+            this._deferrability = DEFERRABILITIES.get( (int) deferrability );
+        }
+
+        public String getPkSchemaName()
+        {
+            return this._pkSchemaName;
+        }
+
+        public String getPkTableName()
+        {
+            return this._pkTableName;
+        }
+
+        public String getPkTablePKColumnName()
+        {
+            return this._pkTablePKColumnName;
+        }
+
+        public IntegrityActions getOnUpdateAction()
+        {
+            return this._onUpdateAction;
+        }
+
+        public IntegrityActions getOnDeleteAction()
+        {
+            return this._onDeleteAction;
+        }
+
+        public Deferrability getDeferrability()
+        {
+            return this._deferrability;
+        }
+
+    }
+
+    public interface DatabaseProcessor
+    {
+        void beginProcessSchemaInfo( String schemaName );
+
+        void endProcessSchemaInfo( String schemaName );
+
+        void beginProcessTableInfo( String schemaName, String tableName, String remarks );
+
+        void endProcessTableInfo( String schemaName, String tableName, String remarks );
+
+        void beginProcessColumns( String schemaName, String tableName, String tableRemarks );
+
+        void beginProcessColumnInfo( String schemaName, String tableName,
+                                     ColumnInfo colInfo, ForeignKeyInfo fkInfo );
+
+        void endProcessColumnInfo( String schemaName, String tableName,
+                                   ColumnInfo colInfo, ForeignKeyInfo fkInfo );
+
+        void endProcessColumns( String schemaName, String tableName, String tableRemarks );
+
+        void beginProcessRows( String schemaName, String tableName, String tableRemarks );
+
+        void beginProcessRowInfo( String schemaName, String tableName, Object[] rowContents );
+
+        void endProcessRowInfo( String schemaName, String tableName, Object[] rowContents );
+
+        void endProcessRows( String schemaName, String tableName, String tableRemarks );
+    }
+
+    public static abstract class DatabaseProcessorAdapter
+        implements DatabaseProcessor
+    {
+
+        @Override
+        public void beginProcessColumnInfo( String schemaName, String tableName,
+                                            ColumnInfo colInfo, ForeignKeyInfo fkInfo )
+        {
+        }
+
+        @Override
+        public void beginProcessColumns( String schemaName, String tableName, String tableRemarks )
+        {
+        }
+
+        @Override
+        public void beginProcessRowInfo( String schemaName, String tableName, Object[] rowContents )
+        {
+        }
+
+        @Override
+        public void beginProcessRows( String schemaName, String tableName, String tableRemarks )
+        {
+        }
+
+        @Override
+        public void beginProcessSchemaInfo( String schemaName )
+        {
+        }
+
+        @Override
+        public void beginProcessTableInfo( String schemaName, String tableName, String remarks )
+        {
+        }
+
+        @Override
+        public void endProcessColumnInfo( String schemaName, String tableName,
+                                          ColumnInfo colInfo, ForeignKeyInfo fkInfo )
+        {
+        }
+
+        @Override
+        public void endProcessColumns( String schemaName, String tableName, String tableRemarks )
+        {
+        }
+
+        @Override
+        public void endProcessRowInfo( String schemaName, String tableName, Object[] rowContents )
+        {
+        }
+
+        @Override
+        public void endProcessRows( String schemaName, String tableName, String tableRemarks )
+        {
+        }
+
+        @Override
+        public void endProcessSchemaInfo( String schemaName )
+        {
+        }
+
+        @Override
+        public void endProcessTableInfo( String schemaName, String tableName, String remarks )
+        {
+        }
+
+    }
+
+    public static void visitDatabaseTables( Connection connection, String catalogName,
+                                            String schemaNamePattern, String tableNamePattern,
+                                            DatabaseProcessor processor, SQLVendor sqlSyntaxVendor )
+        throws SQLException
+    {
+        DatabaseMetaData metaData = connection.getMetaData();
+        connection.setReadOnly( true );
+        ResultSet rs = metaData.getTables( catalogName, schemaNamePattern, tableNamePattern, new String[]
+        {
+            "TABLE"
+        } );
+        try
+        {
+            while( rs.next() )
+            {
+                String schemaName = rs.getString( 2 );
+                try
+                {
+                    processor.beginProcessSchemaInfo( schemaName );
+                    String tableName = rs.getString( 3 );
+                    String tableRemarks = rs.getString( 5 );
+                    try
+                    {
+                        processor.beginProcessTableInfo( schemaName, tableName, tableRemarks );
+                        List<ColumnInfo> colInfos = new ArrayList<>();
+                        ResultSet rsCols = metaData.getColumns( null, schemaName, tableName, null );
+                        try
+                        {
+                            while( rsCols.next() )
+                            {
+                                String nullable = rsCols.getString( 18 );
+                                colInfos.add( new ColumnInfo(
+                                    rsCols.getString( 4 ),
+                                    rsCols.getInt( 5 ),
+                                    rsCols.getString( 6 ),
+                                    rsCols.getInt( 7 ),
+                                    rsCols.getInt( 9 ),
+                                    nullable.length() > 0 ? Boolean.toString( nullable.equals( "YES" ) ) : "unknown",
+                                    rsCols.getString( 13 ),
+                                    rsCols.getString( 12 ) ) );
+                            }
+                        }
+                        finally
+                        {
+                            rsCols.close();
+                        }
+
+                        rsCols = metaData.getImportedKeys( null, schemaName, tableName );
+                        Map<String, ForeignKeyInfo> fkInfos = new HashMap<>();
+                        try
+                        {
+                            while( rsCols.next() )
+                            {
+                                fkInfos.put(
+                                    //
+                                    rsCols.getString( 8 ), //
+                                    new ForeignKeyInfo( rsCols.getString( 2 ), rsCols.getString( 3 ), rsCols
+                                    .getString( 4 ), rsCols.getShort( 10 ), rsCols.getShort( 11 ), rsCols
+                                    .getShort( 14 ) ) );
+                            }
+                        }
+                        finally
+                        {
+                            rsCols.close();
+                        }
+
+                        try
+                        {
+                            processor.beginProcessColumns( schemaName, tableName, tableRemarks );
+                            for( ColumnInfo colInfo : colInfos )
+                            {
+                                try
+                                {
+                                    processor.beginProcessColumnInfo( schemaName, tableName, colInfo,
+                                                                      fkInfos.get( colInfo._name ) );
+                                }
+                                finally
+                                {
+                                    processor.endProcessColumnInfo( schemaName, tableName, colInfo,
+                                                                    fkInfos.get( colInfo._name ) );
+                                }
+                            }
+                        }
+                        finally
+                        {
+                            processor.endProcessColumns( schemaName, tableName, tableRemarks );
+                        }
+
+                        QueryFactory q = sqlSyntaxVendor.getQueryFactory();
+                        TableReferenceFactory t = sqlSyntaxVendor.getTableReferenceFactory();
+                        QuerySpecificationBuilder builda = q.querySpecificationBuilder();
+                        builda.getSelect().selectAll();
+                        builda.getFrom().addTableReferences(
+                            t.tableBuilder( t.table( t.tableName( schemaName, tableName ) ) ) );
+                        String sql = sqlSyntaxVendor.toString( q.createQuery( builda.createExpression() ) );
+                        Statement stmt = connection.createStatement();
+                        ResultSet rowsRs = null;
+                        try
+                        {
+                            rowsRs = stmt.executeQuery( sql );
+                            processor.beginProcessRows( schemaName, tableName, tableRemarks );
+                            while( rowsRs.next() )
+                            {
+                                Object[] rowContents = new Object[ colInfos.size() ];
+                                for( Integer x = 0; x < rowContents.length; ++x )
+                                {
+                                    rowContents[x] = rowsRs.getObject( x + 1 );
+                                }
+
+                                try
+                                {
+                                    processor.beginProcessRowInfo( schemaName, tableName, rowContents );
+                                }
+                                finally
+                                {
+                                    processor.endProcessRowInfo( schemaName, tableName, rowContents );
+                                }
+                            }
+                        }
+                        finally
+                        {
+                            processor.endProcessRows( schemaName, tableName, tableRemarks );
+                            if( rowsRs != null )
+                            {
+                                rowsRs.close();
+                            }
+                            stmt.close();
+                        }
+                    }
+                    finally
+                    {
+                        processor.endProcessTableInfo( schemaName, tableName, tableRemarks );
+                    }
+                }
+                finally
+                {
+                    processor.endProcessSchemaInfo( schemaName );
+                }
+            }
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( rs );
+        }
+    }
+
+    private GenericDatabaseExplorer()
+    {
+    }
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/QNameInfo.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/QNameInfo.java
new file mode 100644
index 0000000..f35ef25
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/QNameInfo.java
@@ -0,0 +1,351 @@
+/*
+ *  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.polygene.index.sql.support.common;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.Period;
+import java.time.ZonedDateTime;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.property.PropertyDescriptor;
+
+/**
+ * A helper interface to encapsulate information about qualified name and how it appears in
+ * database.
+ *
+ * @author Stanislav Muhametsin
+ */
+public final class QNameInfo
+{
+    /**
+     * Currently all possible types of qualified names: {@link #PROPERTY} for properties,
+     * {@link #ASSOCIATION} for associations, and {@link #MANY_ASSOCIATION} for many-associations.
+     */
+    public enum QNameType
+    {
+        PROPERTY,
+        ASSOCIATION,
+        MANY_ASSOCIATION
+    }
+
+    private static final List<Class<?>> EMPTY_COLL_CLASSES = new ArrayList<>();
+
+    private String _tableName;
+
+    /**
+     * Store also information about collection types - in case it is required in future.
+     */
+    private final List<Class<?>> _collectionClasses;
+
+    private final QualifiedName _qName;
+
+    private final QNameType _qNameType;
+
+    private final Type _finalType;
+
+    private final Boolean _isFinalTypePrimitive;
+
+    private final PropertyDescriptor _propertyDescriptor;
+
+    private final AssociationDescriptor _associationDescriptor;
+
+    private final AssociationDescriptor _manyAssociationDescriptor;
+
+    private QNameInfo( QualifiedName qName, //
+                       QNameType qNameType, //
+                       List<Class<?>> collectionClasses, //
+                       String tableName, //
+                       Type finalType, //
+                       PropertyDescriptor propertyDescriptor, //
+                       AssociationDescriptor associationDescriptor, //
+                       AssociationDescriptor manyAssociationDescriptor //
+    )
+    {
+        if( ( propertyDescriptor != null && associationDescriptor == null && manyAssociationDescriptor == null )
+            || ( propertyDescriptor == null && associationDescriptor != null && manyAssociationDescriptor == null )
+            || ( propertyDescriptor == null && associationDescriptor == null && manyAssociationDescriptor != null ) )
+        {
+            this._propertyDescriptor = propertyDescriptor;
+            this._associationDescriptor = associationDescriptor;
+            this._manyAssociationDescriptor = manyAssociationDescriptor;
+        }
+        else
+        {
+            throw new IllegalArgumentException(
+                "Exactly one of property, association, or many-association descriptors must be non-null." );
+        }
+        this._qName = qName;
+        this._qNameType = qNameType;
+        this._collectionClasses = ( collectionClasses == null || collectionClasses.isEmpty()
+                                    ? EMPTY_COLL_CLASSES
+                                    : collectionClasses );
+        this._tableName = tableName;
+        this._finalType = finalType;
+        Boolean isFinalTypePrimitive = false;
+        if( finalType instanceof Class<?> )
+        {
+            Class<?> finalClass = (Class<?>) finalType;
+            isFinalTypePrimitive = //
+                Number.class.isAssignableFrom( finalClass )//
+                || Boolean.class.isAssignableFrom( finalClass ) //
+                || Character.class.isAssignableFrom( finalClass ) //
+                || LocalDate.class.isAssignableFrom( finalClass ) //
+                || LocalTime.class.isAssignableFrom( finalClass ) //
+                || LocalDateTime.class.isAssignableFrom( finalClass ) //
+                || ZonedDateTime.class.isAssignableFrom( finalClass ) //
+                || OffsetDateTime.class.isAssignableFrom( finalClass ) //
+                || Instant.class.isAssignableFrom( finalClass ) //
+                || Duration.class.isAssignableFrom( finalClass ) //
+                || Period.class.isAssignableFrom( finalClass ) //
+                || Enum.class.isAssignableFrom( finalClass ) //
+                || String.class.isAssignableFrom( finalClass )//
+                ;
+        }
+        this._isFinalTypePrimitive = isFinalTypePrimitive;
+    }
+
+    /**
+     * If qualified name represented by this interface is a property with collection as type,
+     * returns the {@code amount of nested collections + 1}. That is, assuming {@code X} is not a
+     * collection, for type {@code Property<Set<X>>} this returns {@code 1}, for
+     * {@code Property<Set<Set<X>>>} this returns {@code 2}, etc. If qualified name represented by
+     * this interface is not a property or a property with no collection type, this method returns
+     * {@code 0}.
+     *
+     * @return The collection depth ({@code > 0}) of qualified name, if this interface represents
+     *         qualified name with collection property; {@code 0} otherwise.
+     */
+    public Integer getCollectionDepth()
+    {
+        return this._collectionClasses.size();
+    }
+
+    /**
+     * Returns the non-collection type of this qualified name. That is, for {@code Property<X>} this
+     * returns {@code X} if {@code X} is not a collection type, and for {@code Property<Set<Y>>}
+     * this returns {@code Y} if {@code Y} is not a collection type.
+     *
+     * @return The non-collection type of this qualified name.
+     */
+    public Type getFinalType()
+    {
+        return this._finalType;
+    }
+
+    /**
+     * Gets the qualified name this interface represents.
+     *
+     * @return The qualified name this interface represents.
+     * @see QualifiedName
+     */
+    public QualifiedName getQName()
+    {
+        return this._qName;
+    }
+
+    /**
+     * Gets the table name in database, used to store values of the qualified name this interface
+     * represents.
+     *
+     * @return The table name in database, used to store values of the qualified name this interface
+     *         represents. May be {@code null} if it is not yet decided.
+     */
+    public String getTableName()
+    {
+        return this._tableName;
+    }
+
+    /**
+     * Sets the previously undecided table name to some specific one. This method only works when
+     * argument is {@code non-null} and current table name is {@code null}.
+     *
+     * @param tableName The new table name. Must be {@code non-null}.
+     * @throws IllegalArgumentException If {@code tableName} is {@code null}.
+     * @throws IllegalStateException If current table name is {@code non-null}.
+     */
+    public void setTableName( String tableName )
+    {
+        if( tableName == null )
+        {
+            throw new IllegalArgumentException( "Table name must not be null." );
+        }
+        if( this._tableName == null )
+        {
+            this._tableName = tableName;
+        }
+        else
+        {
+            throw new IllegalStateException( "Can only set table name when it is null." );
+        }
+    }
+
+    /**
+     * Returns whether the final (non-collection) type of this qualified name is not seen as value
+     * composite. Always returns {@code false} for qualified names of type
+     * {@link QNameType#ASSOCIATION} and {@link QNameType#MANY_ASSOCIATION}.
+     *
+     * @return {@code true} if {@link #getFinalType()} is not seen as value composite type;
+     *         {@code false} otherwise.
+     */
+    public Boolean isFinalTypePrimitive()
+    {
+        return this._isFinalTypePrimitive;
+    }
+
+    /**
+     * Returns {@link PropertyDescriptor} associated with this property, if this qualified name info
+     * represents a property. Returns {@code null} otherwise.
+     *
+     * @return {@link PropertyDescriptor} if this qualified name info is associated with property,
+     *         {@code null} otherwise.
+     */
+    public PropertyDescriptor getPropertyDescriptor()
+    {
+        return this._propertyDescriptor;
+    }
+
+    /**
+     * Returns {@link AssociationDescriptor} associated with this association, if this qualified
+     * name info represents an association. Returns {@code null} otherwise.
+     *
+     * @return {@link AssociationDescriptor} if this qualified name info is associated with
+     *         association, {@code null} otherwise.
+     */
+    public AssociationDescriptor getAssociationDescriptor()
+    {
+        return this._associationDescriptor;
+    }
+
+    /**
+     * Returns {@link AssociationDescriptor} associated with this many-association, if this
+     * qualified name info represents a many-association. Returns {@code null} otherwise.
+     *
+     * @return {@link AssociationDescriptor} if this qualified name info is associated with
+     *         many-association, {@code null} otherwise.
+     */
+    public AssociationDescriptor getManyAssociationDescriptor()
+    {
+        return this._manyAssociationDescriptor;
+    }
+
+    /**
+     * Gets the type of represented qualified name: either {@link QNameType#PROPERTY} for
+     * properties, {@link QNameType#ASSOCIATION} for associations, or
+     * {@link QNameType#MANY_ASSOCIATION} for many-associations.
+     *
+     * @return The type of represented qualified name: either {@link QNameType#PROPERTY},
+     *         {@link QNameType#ASSOCIATION}, or {@link QNameType#MANY_ASSOCIATION}.
+     */
+    public QNameType getQNameType()
+    {
+        return this._qNameType;
+    }
+
+    /**
+     * Creates information about specified qualified name which represents a property.
+     *
+     * @param qName The qualified name of property.
+     * @param tableName The table name where the values of all instances of propertiy with this
+     *        qualified name will be stored. May be {@code null} if it is to be decided later.
+     * @param propertyDescriptor {@link PropertyDescriptor} of this property.
+     * @return An object representing information about property with this qualified name, and how
+     *         instances of this property are stored in database.
+     */
+    public static QNameInfo fromProperty( //
+        QualifiedName qName, //
+        String tableName, //
+        PropertyDescriptor propertyDescriptor //
+    )
+    {
+        Type vType = propertyDescriptor.type();
+        List<Class<?>> collectionClasses = new ArrayList<>();
+        while( vType instanceof ParameterizedType
+               && Collection.class.isAssignableFrom( (Class<?>) ( (ParameterizedType) vType )
+            .getRawType() ) )
+        {
+            collectionClasses.add( (Class<?>) ( (ParameterizedType) vType ).getRawType() );
+            vType = ( (ParameterizedType) vType ).getActualTypeArguments()[0];
+        }
+
+        return new QNameInfo( qName, QNameType.PROPERTY, collectionClasses, tableName, vType,
+                              propertyDescriptor, null,
+                              null );
+    }
+
+    /**
+     * Creates information about specified qualified name which represents an association.
+     *
+     * @param qName The qualified name of the association.
+     * @param tableName The table name where the values of all instances of association with this
+     *        qualified name will be stored. May be {@code null} if it is to be decided later.
+     * @param assoDescriptor {@link AssociationDescriptor} of this association.
+     * @return An object representing information about association with this qualified name, and
+     *         how instances of this association are stored in database.
+     */
+    public static QNameInfo fromAssociation( //
+        QualifiedName qName, //
+        String tableName, //
+        AssociationDescriptor assoDescriptor //
+    )
+    {
+        return new QNameInfo( qName, QNameType.ASSOCIATION, null, tableName, assoDescriptor.type(),
+                              null,
+                              assoDescriptor, null );
+    }
+
+    /**
+     * Creates information about specified qualified name which represents a many-association.
+     *
+     * @param qName The qualified name of the many-association.
+     * @param tableName The table name where the values of all instances of many-association with
+     *        this qualified name will be stored. May be {@code null} if it is to be decided later.
+     * @param manyAssoDescriptor {@link AssociationDescriptor} of this many-association.
+     * @return An object representing information about many-association with this qualified name,
+     *         and how instances of this many-association are stored in database.
+     */
+    public static QNameInfo fromManyAssociation( //
+        QualifiedName qName, //
+        String tableName, //
+        AssociationDescriptor manyAssoDescriptor //
+    )
+    {
+        return new QNameInfo( qName, QNameType.MANY_ASSOCIATION, null, tableName,
+                              manyAssoDescriptor.type(), null,
+                              null, manyAssoDescriptor );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "[table: " + this._tableName + ", final type: " + this._finalType + ", qNameType: "
+               + this._qNameType + ", qName: " + this._qName + "]";
+    }
+
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/RebuildingStrategy.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/RebuildingStrategy.java
new file mode 100644
index 0000000..3d76262
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/RebuildingStrategy.java
@@ -0,0 +1,78 @@
+/*
+ *  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.polygene.index.sql.support.common;
+
+/**
+ * Helper interface to let the user of SQL-Indexing decide when to re-build SQL schema. Rebuilding
+ * means first deleting all tables that are going to be used, and then creating them. Useful for
+ * tests or when your app is in dev mode.
+ *
+ * You can decide your application's re-building policy for example like this:
+ * {@code mainModule.addServices(RebuildingStrategy.class).withMixins(RebuildingStrategy.AlwaysNeed.class);}
+ * . This way your application will always re-build all index data at startup.
+ */
+public interface RebuildingStrategy
+{
+    boolean rebuildingRequired( String dbAppVersion, String currentAppVersion );
+
+    /**
+     * The re-building strategy which ALWAYS re-builds the database schema. Useful with tests and
+     * during early development stage of application.
+     */
+    class AlwaysNeed
+        implements RebuildingStrategy
+    {
+        @Override
+        public boolean rebuildingRequired( String dbAppVersion, String currentAppVersion )
+        {
+            return true;
+        }
+    }
+
+    /**
+     * The re-building strategy which NEVER re-builds the database schema. Useful when current
+     * Polygene-related database schema structure must be preserved at all costs.
+     */
+    class NeverNeed
+        implements RebuildingStrategy
+    {
+        @Override
+        public boolean rebuildingRequired( String dbAppVersion, String currentAppVersion )
+        {
+            return false;
+        }
+    }
+
+    /**
+     * The re-building strategy, which re-builds everything when application version changes. Useful
+     * when migration from versions is implemented, or when application structure changes along with
+     * version (but not during same version).
+     */
+    class NeedOnChange
+        implements RebuildingStrategy
+    {
+        @Override
+        public boolean rebuildingRequired( String dbAppVersion, String currentAppVersion )
+        {
+            return !dbAppVersion.equals( currentAppVersion );
+        }
+    }
+
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/ReindexingStrategy.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/ReindexingStrategy.java
new file mode 100644
index 0000000..7606cdf
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/ReindexingStrategy.java
@@ -0,0 +1,78 @@
+/*
+ *  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.polygene.index.sql.support.common;
+
+/**
+ * Service to decide when complete re-indexing is needed, along with default implementations. TODO
+ * maybe add {@code void beganReindexing()} and {@code void finishedReindexing()} methods? For
+ * example, for UI interaction.
+ *
+ * You can decide your application's re-indexing policy for example like this:
+ * {@code mainModule.addServices(ReindexingStrategy.class).withMixins(ReindexingStrategy.AlwaysNeed.class);}
+ * . This way your application will always re-index all entity store data at startup.
+ */
+public interface ReindexingStrategy
+{
+    boolean reindexingNeeded( String dbAppVersion, String currentAppVersion );
+
+    /**
+     * The re-indexing strategy which ALWAYS re-indexes everything. Useful with tests and during
+     * early development stage of application.
+     */
+    class AlwaysNeed
+        implements ReindexingStrategy
+    {
+        @Override
+        public boolean reindexingNeeded( String dbAppVersion, String currentAppVersion )
+        {
+            return true;
+        }
+    }
+
+    /**
+     * The re-indexing strategy which NEVER re-indexes anything. Useful when deleting and re-reading
+     * data is something to be avoided at all costs.
+     */
+    class NeverNeed
+        implements ReindexingStrategy
+    {
+        @Override
+        public boolean reindexingNeeded( String dbAppVersion, String currentAppVersion )
+        {
+            return false;
+        }
+    }
+
+    /**
+     * The re-indexing strategy, which re-indexes everything when application version changes.
+     * Useful when migration from versions is implemented, or when application structure changes
+     * along with version (but not during same version).
+     */
+    class NeedOnChange
+        implements ReindexingStrategy
+    {
+        @Override
+        public boolean reindexingNeeded( String dbAppVersion, String currentAppVersion )
+        {
+            return !dbAppVersion.equals( currentAppVersion );
+        }
+    }
+
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/package.html b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/package.html
new file mode 100644
index 0000000..76f6b34
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/common/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL Index/Query Vendors Common Support.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/derby/package.html b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/derby/package.html
new file mode 100644
index 0000000..d70ac26
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/derby/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL Index/Query Apache Derby Support.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLAppStartup.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLAppStartup.java
new file mode 100644
index 0000000..ef6e746
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLAppStartup.java
@@ -0,0 +1,109 @@
+/*
+ *  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.polygene.index.sql.support.postgresql;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Map;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.index.sql.support.skeletons.AbstractSQLStartup;
+import org.apache.polygene.library.sql.common.SQLUtil;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDataType;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableScope;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.pgsql.PgSQLTableCommitAction;
+import org.apache.polygene.library.sql.generator.grammar.factories.DataTypeFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.DefinitionFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.TableReferenceFactory;
+import org.apache.polygene.library.sql.generator.vendor.PostgreSQLVendor;
+
+public class PostgreSQLAppStartup
+    extends AbstractSQLStartup
+{
+
+    private final PostgreSQLVendor _vendor;
+
+    public PostgreSQLAppStartup( @Uses ServiceDescriptor descriptor )
+    {
+        super( descriptor );
+
+        this._vendor = descriptor.metaInfo( PostgreSQLVendor.class );
+    }
+
+    @Override
+    protected void modifyPrimitiveTypes( Map<Class<?>, SQLDataType> primitiveTypes,
+                                         Map<Class<?>, Integer> jdbcTypes )
+    {
+        // Set TEXT as default type for strings, since PgSQL can optimize that better than some
+        // VARCHAR with weird max
+        // length
+        primitiveTypes.put( String.class, this._vendor.getDataTypeFactory().text() );
+    }
+
+    @Override
+    protected void testRequiredCapabilities( Connection connection )
+        throws SQLException
+    {
+        // If collection structure matching will ever be needed, using ltree as path to each leaf
+        // item in
+        // collection-generated tree will be very useful
+        // ltree module provides specific datatype for such path, which may be indexed in order to
+        // greatly improve
+        // performance
+
+        Statement stmt = connection.createStatement();
+        try
+        {
+            DefinitionFactory d = this._vendor.getDefinitionFactory();
+            TableReferenceFactory t = this._vendor.getTableReferenceFactory();
+            DataTypeFactory dt = this._vendor.getDataTypeFactory();
+
+            stmt.execute( this._vendor.toString( d
+                .createTableDefinitionBuilder()
+                .setTableScope( TableScope.LOCAL_TEMPORARY )
+                .setTableName( t.tableName( "ltree_test" ) )
+                .setCommitAction( PgSQLTableCommitAction.DROP )
+                .setTableContentsSource(
+                    d.createTableElementListBuilder()
+                    .addTableElement(
+                        d.createColumnDefinition( "test_column", dt.userDefined( "ltree" ) ) )
+                    .createExpression() ).createExpression() ) );
+        }
+        catch( SQLException sqle )
+        {
+            throw new InternalError( "It seems that your database doesn't have ltree as type. It is needed to store "
+                                     + "collections. Please refer to hopefully supplied instructions on how to add "
+                                     + "ltree type (hint: run <pg_install_dir>/share/contrib/ltree.sql script or "
+                                     + "command 'CREATE EXTENSION ltree;').", SQLUtil.withAllSQLExceptions( sqle ) );
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( stmt );
+        }
+    }
+
+    @Override
+    protected SQLDataType getCollectionPathDataType()
+    {
+        return this._vendor.getDataTypeFactory().userDefined( "ltree" );
+    }
+
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLIndexExporter.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLIndexExporter.java
new file mode 100644
index 0000000..2dd7408
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLIndexExporter.java
@@ -0,0 +1,341 @@
+/*
+ *  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.polygene.index.sql.support.postgresql;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.HashMap;
+import java.util.Map;
+import javax.sql.DataSource;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.index.sql.support.common.GenericDatabaseExplorer;
+import org.apache.polygene.index.sql.support.common.GenericDatabaseExplorer.ColumnInfo;
+import org.apache.polygene.index.sql.support.common.GenericDatabaseExplorer.DatabaseProcessor;
+import org.apache.polygene.index.sql.support.common.GenericDatabaseExplorer.ForeignKeyInfo;
+import org.apache.polygene.index.sql.support.skeletons.SQLDBState;
+import org.apache.polygene.library.sql.common.SQLUtil;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.spi.query.IndexExporter;
+
+public class PostgreSQLIndexExporter
+    implements IndexExporter
+{
+
+    @This
+    private SQLDBState _state;
+
+    @Uses
+    private ServiceDescriptor descriptor;
+
+    @Service
+    private DataSource _dataSource;
+
+    private static final String SEPARATOR = "-----------------------------------------------";
+
+    private static final Map<Integer, String> TYPE_STRINGS;
+
+    static
+    {
+        TYPE_STRINGS = new HashMap<>( 16 );
+        TYPE_STRINGS.put( Types.BIGINT, "BIGINT" );
+        TYPE_STRINGS.put( Types.BOOLEAN, "BOOLEAN" );
+        TYPE_STRINGS.put( Types.CHAR, "CHAR" );
+        TYPE_STRINGS.put( Types.DATE, "DATE" );
+        TYPE_STRINGS.put( Types.DECIMAL, "DECIMAL" );
+        TYPE_STRINGS.put( Types.DOUBLE, "DOUBLE" );
+        TYPE_STRINGS.put( Types.FLOAT, "FLOAT" );
+        TYPE_STRINGS.put( Types.INTEGER, "INTEGER" );
+        TYPE_STRINGS.put( Types.NULL, "NULL" );
+        TYPE_STRINGS.put( Types.NUMERIC, "NUMERIC" );
+        TYPE_STRINGS.put( Types.REAL, "REAL" );
+        TYPE_STRINGS.put( Types.SMALLINT, "SMALLINT" );
+        TYPE_STRINGS.put( Types.TIME, "TIME" );
+        TYPE_STRINGS.put( Types.TIMESTAMP, "TIMESTAMP" );
+        TYPE_STRINGS.put( Types.VARCHAR, "VARCHAR" );
+        TYPE_STRINGS.put( Types.VARBINARY, "VARBINARY" );
+    }
+
+    @Override
+    public void exportFormalToWriter( final PrintWriter out )
+        throws IOException, UnsupportedOperationException
+    {
+        Connection connection = null;
+        try
+        {
+            connection = this._dataSource.getConnection();
+            GenericDatabaseExplorer.visitDatabaseTables( connection, null,
+                                                         this._state.schemaName().get(), null, new DatabaseProcessor()
+            {
+
+                @Override
+                public void endProcessColumns( String schemaName, String tableName, String tableRemarks )
+                {
+                    out.write( "</columns>" + "\n" );
+                }
+
+                @Override
+                public void endProcessRows( String schemaName, String tableName, String tableRemarks )
+                {
+                    out.write( "</rows>" + "\n" );
+                }
+
+                @Override
+                public void endProcessTableInfo( String schemaName, String tableName, String tableRemarks )
+                {
+                    out.write( "</table>" + "\n" );
+                }
+
+                @Override
+                public void endProcessSchemaInfo( String schemaName )
+                {
+                    out.write( "</schema>" + "\n" );
+                }
+
+                @Override
+                public void endProcessRowInfo( String schemaName, String tableName, Object[] rowContents )
+                {
+                    out.write( "</row>" + "\n" );
+                }
+
+                @Override
+                public void endProcessColumnInfo( String schemaName, String tableName, ColumnInfo colInfo,
+                                                  ForeignKeyInfo fkInfo )
+                {
+                }
+
+                @Override
+                public void beginProcessTableInfo( String schemaName, String tableName, String tableRemarks )
+                {
+                    out.write( "<table name=\"" + tableName + "\" remarks=\"" + tableRemarks + "\">" + "\n" );
+                }
+
+                @Override
+                public void beginProcessColumns( String schemaName, String tableName, String tableRemarks )
+                {
+                    out.write( "<columns>" + "\n" );
+                }
+
+                @Override
+                public void beginProcessColumnInfo( String schemaName, String tableName, ColumnInfo colInfo,
+                                                    ForeignKeyInfo fkInfo )
+                {
+                    String defaultValue = colInfo.getDefaultValue();
+                    if( defaultValue.startsWith( "'" ) )
+                    {
+                        defaultValue = defaultValue.substring( 1, defaultValue.length() - 1 );
+                    }
+                    out.write( "<column name=\"" + colInfo.getName() + "\" colType=\"" + colInfo.getTypeName()
+                               + "\" colSize=\"" + colInfo.getSize() + "\" colScale=\""
+                               + //
+                        colInfo.getScale() + "\" nullable=\"" + colInfo.getNullable() + "\" default=\""
+                               + defaultValue + "\" " //
+                    );
+                    if( fkInfo != null )
+                    {
+                        out.write( "refSchemaName=\"" + fkInfo.getPkSchemaName() + "\" refTableName=\""
+                                   + fkInfo.getPkTableName() + "\" refPKColumnName=\""
+                                   + fkInfo.getPkTablePKColumnName()
+                                   + //
+                            "\" onUpdate=\"" + fkInfo.getOnUpdateAction() + "\" onDelete=\""
+                                   + fkInfo.getOnDeleteAction() + "\" deferrability=\"" + fkInfo.getDeferrability()
+                                   + "\" " //
+                        );
+                    }
+
+                    out.write( "/>" + "\n" );
+                }
+
+                @Override
+                public void beginProcessSchemaInfo( String schemaName )
+                {
+                    out.write( "<schema name=\"" + schemaName + "\">" + "\n" );
+                }
+
+                @Override
+                public void beginProcessRows( String schemaName, String tableName, String tableRemarks )
+                {
+                    out.write( "<rows>" + "\n" );
+                }
+
+                @Override
+                public void beginProcessRowInfo( String schemaName, String tableName, Object[] rowContents )
+                {
+                    out.write( "<row>" + "\n" );
+                    for( Integer x = 0; x < rowContents.length; ++x )
+                    {
+                        out.write( "<value index=\"" + x + "\" >" + rowContents[x] + "</value>" + "\n" );
+                    }
+                }
+            }, this.descriptor.metaInfo( SQLVendor.class ) );
+        }
+        catch( SQLException sqle )
+        {
+            throw new IOException( SQLUtil.withAllSQLExceptions( sqle ) );
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( connection );
+        }
+    }
+
+    @Override
+    public void exportReadableToStream( final PrintStream out )
+        throws IOException, UnsupportedOperationException
+    {
+        Connection connection = null;
+        try
+        {
+            connection = this._dataSource.getConnection();
+            GenericDatabaseExplorer.visitDatabaseTables( connection, null,
+                                                         this._state.schemaName().get(), null, new DatabaseProcessor()
+            {
+
+                @Override
+                public void endProcessTableInfo( String schemaName, String tableName, String tableRemarks )
+                {
+                    out.print( "\n\n\n" );
+                }
+
+                @Override
+                public void endProcessSchemaInfo( String schemaName )
+                {
+                    out.print( "\n\n" );
+                }
+
+                @Override
+                public void endProcessRowInfo( String schemaName, String tableName, Object[] rowContents )
+                {
+
+                }
+
+                @Override
+                public void endProcessColumnInfo( String schemaName, String tableName, ColumnInfo colInfo,
+                                                  ForeignKeyInfo fkInfo )
+                {
+
+                }
+
+                @Override
+                public void endProcessColumns( String schemaName, String tableName, String tableRemarks )
+                {
+                    out.print( SEPARATOR + "\n" + SEPARATOR + "\n" );
+                }
+
+                @Override
+                public void endProcessRows( String schemaName, String tableName, String tableRemarks )
+                {
+                    out.print( SEPARATOR + "\n" + SEPARATOR + "\n" );
+                }
+
+                private String parseSQLType( ColumnInfo colInfo )
+                {
+                    String result = colInfo.getTypeName();
+                    Integer sqlType = colInfo.getSQLType();
+                    if( TYPE_STRINGS.containsKey( sqlType ) )
+                    {
+                        result = TYPE_STRINGS.get( sqlType );
+                        if( sqlType == Types.DECIMAL || sqlType == Types.NUMERIC )
+                        {
+                            result = result + "(" + colInfo.getSize() + ", " + colInfo.getScale() + ")";
+                        }
+                        else if( sqlType == Types.VARCHAR || sqlType == Types.VARBINARY )
+                        {
+                            result = result + "(" + colInfo.getSize() + ")";
+                        }
+                    }
+                    return result;
+                }
+
+                @Override
+                public void beginProcessColumnInfo( String schemaName, String tableName, ColumnInfo colInfo,
+                                                    ForeignKeyInfo fkInfo )
+                {
+                    out.print( colInfo.getName() + ":" + this.parseSQLType( colInfo ) + "[nullable:"
+                               + colInfo.getNullable() + "; default: " + colInfo.getDefaultValue() + "]" );
+                    if( fkInfo != null )
+                    {
+                        out.print( " -> " + fkInfo.getPkSchemaName() + "." + fkInfo.getPkTableName() + "("
+                                   + fkInfo.getPkTablePKColumnName() + ")[ON UPDATE " + fkInfo.getOnUpdateAction()
+                                   + ", ON DELETE " + fkInfo.getOnDeleteAction() + ", " + fkInfo.getDeferrability() + "]" );
+                    }
+                    out.print( "\n" );
+                }
+
+                @Override
+                public void beginProcessTableInfo( String schemaName, String tableName, String tableRemarks )
+                {
+                    out.print( "Table: " + schemaName + "." + tableName
+                               + ( tableRemarks == null ? "" : " (" + tableRemarks + ")" ) + "\n" );
+                }
+
+                @Override
+                public void beginProcessSchemaInfo( String schemaName )
+                {
+                    out.print( //
+                        "\n\n" + "Schema: " + schemaName + "\n" + //
+                        SEPARATOR + "\n\n\n" //
+                    );
+                }
+
+                @Override
+                public void beginProcessRowInfo( String schemaName, String tableName, Object[] rowContents )
+                {
+                    for( Integer x = 0; x < rowContents.length; ++x )
+                    {
+                        Object value = rowContents[x];
+                        out.print( value == null ? "NULL" : ( "\"" + value + "\"" ) );
+                        if( x + 1 < rowContents.length )
+                        {
+                            out.print( " ; " );
+                        }
+                    }
+                    out.print( "\n" );
+                }
+
+                @Override
+                public void beginProcessColumns( String schemaName, String tableName, String tableRemarks )
+                {
+                    out.print( SEPARATOR + "\n" + SEPARATOR + "\n" );
+                }
+
+                @Override
+                public void beginProcessRows( String schemaName, String tableName, String tableRemarks )
+                {
+
+                }
+            }, this.descriptor.metaInfo( SQLVendor.class ) );
+        }
+        catch( SQLException sqle )
+        {
+            throw new IOException( SQLUtil.withAllSQLExceptions( sqle ) );
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( connection );
+        }
+    }
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLIndexing.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLIndexing.java
new file mode 100644
index 0000000..ec39e99
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLIndexing.java
@@ -0,0 +1,89 @@
+/*
+ *  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.polygene.index.sql.support.postgresql;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import org.apache.polygene.index.sql.support.common.DBNames;
+import org.apache.polygene.index.sql.support.skeletons.AbstractSQLIndexing;
+import org.apache.polygene.library.sql.common.SQLUtil;
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.ColumnSourceByValuesBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.pgsql.PgSQLInsertStatementBuilder;
+import org.apache.polygene.library.sql.generator.grammar.factories.ColumnsFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.LiteralFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.ModificationFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.TableReferenceFactory;
+import org.apache.polygene.library.sql.generator.grammar.modification.InsertStatement;
+import org.apache.polygene.library.sql.generator.grammar.modification.ValueSource;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.spi.entity.EntityState;
+
+public class PostgreSQLIndexing
+    extends AbstractSQLIndexing
+{
+
+    @Override
+    protected long getPKFromAutoGeneratedIDInsert( EntityState state,
+                                                   PreparedStatement autoGeneratedIDStatement,
+                                                   SQLVendor vendor, Connection connection )
+        throws SQLException
+    {
+        this.addEntityInfoToInsertToEntityTablePS( state, autoGeneratedIDStatement, 1 );
+        ResultSet rs = autoGeneratedIDStatement.executeQuery();
+        try
+        {
+            rs.next();
+            return rs.getLong( 1 );
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( rs );
+        }
+    }
+
+    @Override
+    protected InsertStatement createInsertStatementWithAutoGeneratedIDForEntitiesTable(
+        String schemaName, String tableName, SQLVendor vendor )
+    {
+        ModificationFactory m = vendor.getModificationFactory();
+        LiteralFactory l = vendor.getLiteralFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+        ColumnsFactory c = vendor.getColumnsFactory();
+
+        ColumnSourceByValuesBuilder columnBuilder = m.columnSourceByValues();
+        columnBuilder.addValues( ValueSource.Default.INSTANCE );
+        for( Integer x = 1; x < AMOUNT_OF_COLUMNS_IN_ENTITY_TABLE; ++x )
+        {
+            columnBuilder.addValues( l.param() );
+        }
+
+        return ( (PgSQLInsertStatementBuilder) m.insert() )
+            .setReturningClause(
+                vendor.getQueryFactory().columnsBuilder()
+                .addUnnamedColumns( c.colName( DBNames.ENTITY_TABLE_PK_COLUMN_NAME ) )
+                .createExpression()
+            )
+            .setTableName( t.tableName( schemaName, tableName ) )
+            .setColumnSource( columnBuilder.createExpression() )
+            .createExpression();
+    }
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLQuerying.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLQuerying.java
new file mode 100644
index 0000000..939c718
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLQuerying.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.index.sql.support.postgresql;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.index.sql.support.skeletons.AbstractSQLQuerying;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.QuerySpecificationBuilder;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+public class PostgreSQLQuerying
+        extends AbstractSQLQuerying
+{
+
+    @Override
+    protected QueryExpression finalizeQuery(
+            SQLVendor sqlVendor, QuerySpecificationBuilder specBuilder,
+            Class<?> resultType,
+            Predicate<Composite> whereClause,
+            List<OrderBy> orderBySegments,
+            Integer firstResult,
+            Integer maxResults,
+            Map<String, Object> variables,
+            List<Object> values,
+            List<Integer> valueSQLTypes,
+            Boolean countOnly )
+    {
+        Boolean needOffset = firstResult != null && firstResult > 0;
+        Boolean needLimit = maxResults != null && maxResults > 0;
+
+        if ( needOffset ) {
+            specBuilder.offset( firstResult );
+        }
+        if ( needLimit ) {
+            specBuilder.limit( maxResults );
+        }
+
+        return sqlVendor.getQueryFactory().createQuery( specBuilder.createExpression() );
+    }
+
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLService.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLService.java
new file mode 100644
index 0000000..6f05878
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLService.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.index.sql.support.postgresql;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.index.sql.SQLIndexingEngineService;
+import org.apache.polygene.index.sql.internal.SQLEntityFinder;
+import org.apache.polygene.index.sql.internal.SQLStateChangeListener;
+import org.apache.polygene.index.sql.support.api.SQLAppStartup;
+import org.apache.polygene.index.sql.support.api.SQLIndexing;
+import org.apache.polygene.index.sql.support.api.SQLQuerying;
+import org.apache.polygene.index.sql.support.postgresql.PostgreSQLTypeHelper.SQLTypeHelperMixin;
+import org.apache.polygene.spi.query.IndexExporter;
+
+/**
+ * This is actual service responsible of managing indexing and queries and creating database structure.
+ * 
+ * The reason why all these components are in one single service is that they all require some data about the database
+ * structure. Rather than exposing all of that data publicly to be available via another service, it is stored in a
+ * state-style private mixin. Thus all the database-related data is available only to this service, and no one else.
+ */
+@Mixins(
+{
+    SQLEntityFinder.class,
+    SQLStateChangeListener.class,
+    PostgreSQLAppStartup.class,//
+    PostgreSQLIndexing.class,//
+    PostgreSQLQuerying.class,//
+    SQLTypeHelperMixin.class,//
+    PostgreSQLIndexExporter.class
+})
+public interface PostgreSQLService
+    extends SQLAppStartup, SQLIndexing, SQLQuerying, IndexExporter, SQLIndexingEngineService
+{
+
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLTypeHelper.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLTypeHelper.java
new file mode 100644
index 0000000..f3c4b4d
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/PostgreSQLTypeHelper.java
@@ -0,0 +1,129 @@
+/*
+ *  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.polygene.index.sql.support.postgresql;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.index.sql.support.skeletons.SQLDBState;
+
+/**
+ * A little helper interface to convert java types to SQL types when inserting objects to prepared statements. It will
+ * first preprocess the object and possibly convert it to something else (like Character to Integer). Then it will use
+ * the {@link SQLDBState#javaTypes2SQLTypes()} mapping to determine which SQL datatype to use when inserting the
+ * object to prepared statement.
+ */
+@Mixins( PostgreSQLTypeHelper.SQLTypeHelperMixin.class )
+public interface PostgreSQLTypeHelper
+{
+
+    /**
+     * Adds the specified object at specified index in specified prepared statement.
+     *
+     * @param ps The prepared statement.
+     * @param index The index for the object to be inserted in prepared statemtent ({@code > 0}).
+     * @param primitive The object to insert.
+     * @param primitiveType The type of object.
+     * @throws SQLException If something underlying throws it.
+     */
+    void addPrimitiveToPS( PreparedStatement ps, Integer index, @Optional Object primitive, Type primitiveType )
+        throws SQLException;
+
+    Integer getSQLType( Object primitive );
+
+    class SQLTypeHelperMixin
+        implements PostgreSQLTypeHelper
+    {
+
+        @This
+        private SQLDBState _state;
+
+        public Object processJavaPrimitiveBeforeUsingInStatement( Object primitive )
+        {
+            if( primitive != null )
+            {
+                if( primitive instanceof Character )
+                {
+                    primitive = Character.codePointAt( new char[]
+                    {
+                        (Character) primitive
+                    }, 0 );
+                }
+//                else if( primitive instanceof Date )
+//                {
+//                    primitive = new Timestamp( ( (Date) primitive ).getTime() );
+//                }
+                else if( primitive instanceof Byte )
+                {
+                    primitive = (short) (Byte) primitive;
+                }
+                else if( primitive instanceof Short )
+                {
+                    primitive = (int) (Short) primitive;
+                }
+            }
+            return primitive;
+        }
+
+        @Override
+        public void addPrimitiveToPS( PreparedStatement ps, Integer index, Object primitive, Type primitiveType )
+            throws SQLException
+        {
+            primitive = processJavaPrimitiveBeforeUsingInStatement( primitive );
+            Integer sqlType = this.getSQLType( primitiveType );
+            ps.setObject( index, primitive, sqlType );
+        }
+
+        @Override
+        public Integer getSQLType( Object primitive )
+        {
+            primitive = processJavaPrimitiveBeforeUsingInStatement( primitive );
+
+            return this.getSQLType( primitive.getClass() );
+        }
+
+        private Integer getSQLType( Type primitiveType )
+        {
+            if( primitiveType instanceof ParameterizedType )
+            {
+                primitiveType = ( (ParameterizedType) primitiveType ).getRawType();
+            }
+
+            Class<?> primitiveClass = (Class<?>) primitiveType;
+
+            if( Enum.class.isAssignableFrom( primitiveClass ) )
+            {
+                primitiveClass = Enum.class;
+            }
+            Integer sqlType = this._state.javaTypes2SQLTypes().get().get( primitiveClass );
+            if( sqlType == null )
+            {
+                throw new InternalError( "Could not find mapping from " + primitiveClass + " to SQL type." );
+            }
+
+            return sqlType;
+        }
+    }
+
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/package.html b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/package.html
new file mode 100644
index 0000000..2f46f06
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/postgresql/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL Index/Query PostgreSQL Support.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/AbstractSQLIndexing.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/AbstractSQLIndexing.java
new file mode 100644
index 0000000..47e0503
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/AbstractSQLIndexing.java
@@ -0,0 +1,1067 @@
+/*
+ *  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.polygene.index.sql.support.skeletons;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+import javax.sql.DataSource;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.index.sql.support.api.SQLIndexing;
+import org.apache.polygene.index.sql.support.common.DBNames;
+import org.apache.polygene.index.sql.support.common.QNameInfo;
+import org.apache.polygene.index.sql.support.common.QNameInfo.QNameType;
+import org.apache.polygene.index.sql.support.postgresql.PostgreSQLTypeHelper;
+import org.apache.polygene.index.sql.support.skeletons.SQLSkeletonUtil.Lazy;
+import org.apache.polygene.library.sql.common.SQLUtil;
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.ColumnSourceByValuesBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.DeleteBySearchBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.UpdateBySearchBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.QuerySpecificationBuilder;
+import org.apache.polygene.library.sql.generator.grammar.factories.BooleanFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.ColumnsFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.LiteralFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.ModificationFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.QueryFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.TableReferenceFactory;
+import org.apache.polygene.library.sql.generator.grammar.modification.DeleteStatement;
+import org.apache.polygene.library.sql.generator.grammar.modification.InsertStatement;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateSourceByExpression;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateStatement;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+
+import static org.apache.polygene.index.sql.support.common.DBNames.ENTITY_TABLE_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.ENTITY_TYPES_JOIN_TABLE_NAME;
+
+/**
+ * TODO SQL-Generator now has support for auto-generated columns. Use it in indexing ( should make
+ * some things quite faster and simpler ).
+ */
+public abstract class AbstractSQLIndexing
+    implements SQLIndexing
+{
+
+    public static final Integer AMOUNT_OF_COLUMNS_IN_ENTITY_TABLE = 5;
+
+    public static final Integer AMOUNT_OF_COLUMNS_IN_ALL_QNAMES_TABLE = 2;
+
+    public static final Integer AMOUNT_OF_COLUMNS_IN_ASSO_TABLE = 2;
+
+    public static final Integer AMOUNT_OF_COLUMNS_IN_MANY_ASSO_TABLE = 3;
+
+    @Structure
+    private Application _app;
+
+    @Structure
+    private PolygeneSPI _qi4SPI;
+
+    @This
+    private SQLDBState _state;
+
+    @This
+    private PostgreSQLTypeHelper _sqlTypeHelper;
+
+    @Uses
+    private ServiceDescriptor descriptor;
+
+    @Service
+    private DataSource _dataSource;
+
+    @Override
+    public void indexEntities( Iterable<EntityState> changedStates )
+        throws SQLException
+    {
+        final String schemaName = this._state.schemaName().get();
+        final SQLVendor vendor = this.descriptor.metaInfo( SQLVendor.class );
+        Connection connectionTest = AbstractSQLStartup.CONNECTION_FOR_REINDEXING.get();
+        boolean connectionFromStartupWasNull = connectionTest == null;
+        boolean wasAutoCommit = false;
+        boolean wasReadOnly = false;
+        if( connectionFromStartupWasNull )
+        {
+            connectionTest = this._dataSource.getConnection();
+        }
+        else
+        {
+            wasAutoCommit = connectionTest.getAutoCommit();
+            wasReadOnly = connectionTest.isReadOnly();
+        }
+        final Connection connection = connectionTest;
+
+        PreparedStatement updateEntityTablePS = null;
+        PreparedStatement removeEntityPS = null;
+        PreparedStatement insertToPropertyQNamesPS = null;
+        PreparedStatement clearEntityDataPS = null;
+        Lazy<PreparedStatement, SQLException> queryEntityPKPS = new Lazy<>(
+            () -> connection.prepareStatement(
+                vendor.toString( createQueryEntityPkByIdentityStatement( schemaName, vendor ) ) ) );
+        Lazy<PreparedStatement, SQLException> insertToEntityTableAutoGenerated = new Lazy<>(
+            () -> connection.prepareStatement(
+                createInsertStatementWithAutoGeneratedIDForEntitiesTable( schemaName,
+                                                                          ENTITY_TABLE_NAME,
+                                                                          vendor ).toString() ) );
+        Lazy<PreparedStatement, SQLException> insertToEntityTypeTablePS = new Lazy<>(
+            () -> connection.prepareStatement(
+                createInsertEntityTypeStatement( schemaName, vendor ).toString() ) );
+        Map<QualifiedName, PreparedStatement> qNameInsertPSs = new HashMap<>();
+
+        try
+        {
+            connection.setAutoCommit( false );
+            connection.setReadOnly( false );
+
+            // TODO cache all queries.
+            updateEntityTablePS = connection.prepareStatement(
+                this.createUpdateEntityTableStatement( schemaName, vendor ).toString() );
+            removeEntityPS = connection.prepareStatement(
+                this.createDeleteFromEntityTableStatement( schemaName, vendor ).toString() );
+            insertToPropertyQNamesPS = connection.prepareStatement(
+                vendor.toString( this.createInsertStatement( schemaName,
+                                                             DBNames.ALL_QNAMES_TABLE_NAME,
+                                                             AMOUNT_OF_COLUMNS_IN_ALL_QNAMES_TABLE,
+                                                             vendor ) ) );
+            clearEntityDataPS = connection.prepareStatement(
+                this.createClearEntityDataStatement( schemaName, vendor ).toString() );
+
+            Map<Long, EntityState> statesByPK = new HashMap<>();
+            Map<Long, Integer> qNamePKs = new HashMap<>();
+
+            Iterable<EntityState> relatedStates = StreamSupport.stream( changedStates.spliterator(), false )
+                                                               .filter( state -> state.entityDescriptor().queryable() )
+                                                               .map( SQLCompatEntityStateWrapper.WRAP )
+                                                               .collect( Collectors.toList() );
+
+            for( EntityState eState : relatedStates )
+            {
+                EntityStatus status = eState.status();
+                Long pk = null;
+                boolean needToInsert = status.equals( EntityStatus.NEW );
+                if( !needToInsert )
+                {
+                    if( status.equals( EntityStatus.UPDATED ) )
+                    {
+                        pk = this.findEntityPK( eState, queryEntityPKPS );
+                        if( pk == null )
+                        {
+                            // Happens when reindexing
+                            needToInsert = true;
+                        }
+                        else
+                        {
+                            // TODO if multiple applications with different application model use
+                            // indexing, need to sync type-table.
+                            this.updateEntityInfoAndProperties( connection, qNameInsertPSs,
+                                                                insertToPropertyQNamesPS,
+                                                                clearEntityDataPS,
+                                                                updateEntityTablePS,
+                                                                eState,
+                                                                pk, qNamePKs );
+                        }
+                    }
+                    else if( status.equals( EntityStatus.REMOVED ) )
+                    {
+                        this.removeEntity( eState, removeEntityPS );
+                    }
+//                    else
+//                    {
+//                        // TODO possibly handle LOADED state somehow
+//                        // throw new
+//                        // UnsupportedOperationException("Did not understand what to do with state [id = "
+//                        // +
+//                        // eState.reference().reference() + ", status = " + status + "].");
+//                    }
+                }
+
+                if( needToInsert )
+                {
+                    pk = this.getPKFromAutoGeneratedIDInsert(
+                        eState,
+                        insertToEntityTableAutoGenerated.getValue(),
+                        vendor,
+                        connection );
+                    insertPropertyType( insertToEntityTypeTablePS.getValue(), eState, pk );
+                    insertProperties( connection, qNameInsertPSs, insertToPropertyQNamesPS, eState, pk, qNamePKs );
+                }
+                if( pk != null )
+                {
+                    statesByPK.put( pk, eState );
+                }
+            }
+
+            removeEntityPS.executeBatch();
+            updateEntityTablePS.executeBatch();
+            clearEntityDataPS.executeBatch();
+            if( insertToEntityTypeTablePS.hasValue() )
+            {
+                insertToEntityTypeTablePS.getValue().executeBatch();
+            }
+
+            for( Map.Entry<Long, EntityState> entry : statesByPK.entrySet() )
+            {
+                EntityState eState = entry.getValue();
+                Long pk = entry.getKey();
+                this.insertAssoAndManyAssoQNames( qNameInsertPSs, insertToPropertyQNamesPS,
+                                                  eState,
+                                                  qNamePKs.get( pk ), pk );
+            }
+
+            insertToPropertyQNamesPS.executeBatch();
+
+            for( PreparedStatement ps : qNameInsertPSs.values() )
+            {
+                ps.executeBatch();
+            }
+
+            connection.commit();
+        }
+        catch( SQLException sqle )
+        {
+            sqle = SQLUtil.withAllSQLExceptions( sqle );
+            SQLUtil.rollbackQuietly( connection, sqle );
+            throw sqle;
+        }
+        finally
+        {
+            try
+            {
+                if( queryEntityPKPS.hasValue() )
+                {
+                    SQLUtil.closeQuietly( queryEntityPKPS.getValue() );
+                }
+                if( insertToEntityTableAutoGenerated.hasValue() )
+                {
+                    SQLUtil.closeQuietly( insertToEntityTableAutoGenerated.getValue() );
+                }
+                SQLUtil.closeQuietly( updateEntityTablePS );
+                SQLUtil.closeQuietly( removeEntityPS );
+                SQLUtil.closeQuietly( insertToPropertyQNamesPS );
+                SQLUtil.closeQuietly( clearEntityDataPS );
+                qNameInsertPSs.values().forEach( SQLUtil::closeQuietly );
+            }
+            finally
+            {
+                if( connectionFromStartupWasNull )
+                {
+                    SQLUtil.closeQuietly( connection );
+                }
+                else
+                {
+                    connection.setReadOnly( wasReadOnly );
+                    connection.setAutoCommit( wasAutoCommit );
+                }
+            }
+        }
+    }
+
+    protected InsertStatement createInsertStatement( String schemaName, String tableName,
+                                                     Integer amountOfColumns,
+                                                     SQLVendor vendor
+    )
+    {
+        ModificationFactory m = vendor.getModificationFactory();
+        LiteralFactory l = vendor.getLiteralFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+
+        ColumnSourceByValuesBuilder columnBuilder = m.columnSourceByValues();
+        for( Integer x = 0; x < amountOfColumns; ++x )
+        {
+            columnBuilder.addValues( l.param() );
+        }
+
+        return m.insert().setTableName( t.tableName( schemaName, tableName ) )
+            .setColumnSource( columnBuilder.createExpression() ).createExpression();
+    }
+
+    protected abstract InsertStatement createInsertStatementWithAutoGeneratedIDForEntitiesTable(
+        String schemaName, String tableName, SQLVendor vendor
+    );
+
+    protected void addEntityInfoToInsertToEntityTablePS( EntityState state, PreparedStatement ps,
+                                                         int startingIndex
+    )
+        throws SQLException
+    {
+        ps.setString( startingIndex, state.entityReference().identity().toString() );
+        ps.setTimestamp( startingIndex + 1, Timestamp.from( state.lastModified() ) );
+        ps.setString( startingIndex + 2, state.version() );
+        ps.setString( startingIndex + 3, this._app.version() );
+    }
+
+    protected Long findEntityPK( EntityState state,
+                                 Lazy<PreparedStatement, SQLException> queryPKPS
+    )
+        throws SQLException
+    {
+        // TODO build cache: Polygene Identity -> PK
+        Long entityPK = null;
+        PreparedStatement ps = queryPKPS.getValue();
+        ps.setString( 1, state.entityReference().identity().toString() );
+        ResultSet rs = null;
+        try
+        {
+            rs = ps.executeQuery();
+
+            if( rs.next() )
+            {
+                entityPK = rs.getLong( 1 );
+            }
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( rs );
+        }
+
+        return entityPK;
+    }
+
+    protected abstract long getPKFromAutoGeneratedIDInsert(
+        EntityState state, PreparedStatement autoGeneratedIDStatement, SQLVendor vendor,
+        Connection connection
+    )
+        throws SQLException;
+
+    protected UpdateStatement
+    createUpdateEntityTableStatement( String schemaName, SQLVendor vendor )
+    {
+        ModificationFactory m = vendor.getModificationFactory();
+        BooleanFactory b = vendor.getBooleanFactory();
+        LiteralFactory l = vendor.getLiteralFactory();
+        ColumnsFactory c = vendor.getColumnsFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+
+        // "UPDATE " + "%s" + "." + ENTITY_TABLE_NAME + "\n" + //
+        // "SET " + ENTITY_TABLE_IDENTITY_COLUMN_NAME + " = ?, " + //
+        // ENTITY_TABLE_MODIFIED_COLUMN_NAME + " = ?, " + //
+        // ENTITY_TABLE_VERSION_COLUMN_NAME + " = ?, " + //
+        // ENTITY_TABLE_APPLICATION_VERSION_COLUMN_NAME + " = ?" + "\n" + //
+        // "WHERE " + ENTITY_TABLE_PK_COLUMN_NAME + " = ?" + "\n" + //
+        // ";" //
+        UpdateSourceByExpression paramSource = m.updateSourceByExp( l.param() );
+        UpdateBySearchBuilder builder = m.updateBySearch();
+        builder
+            .setTargetTable(
+                m.createTargetTable( t.tableName( schemaName, DBNames.ENTITY_TABLE_NAME ) ) )
+            .addSetClauses( m.setClause( DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME, paramSource ),
+                            m.setClause( DBNames.ENTITY_TABLE_MODIFIED_COLUMN_NAME, paramSource ),
+                            m.setClause( DBNames.ENTITY_TABLE_VERSION_COLUMN_NAME, paramSource ),
+                            m.setClause( DBNames.ENTITY_TABLE_APPLICATION_VERSION_COLUMN_NAME, paramSource ) )
+            .getWhereBuilder()
+            .reset( b.eq( c.colName( DBNames.ENTITY_TABLE_PK_COLUMN_NAME ), l.param() ) );
+
+        return builder.createExpression();
+    }
+
+    protected QueryExpression createQueryEntityPkByIdentityStatement( String schemaName,
+                                                                      SQLVendor vendor
+    )
+    {
+        BooleanFactory b = vendor.getBooleanFactory();
+        LiteralFactory l = vendor.getLiteralFactory();
+        ColumnsFactory c = vendor.getColumnsFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+        QueryFactory q = vendor.getQueryFactory();
+
+        // "SELECT " + ENTITY_TABLE_PK_COLUMN_NAME + "\n" + //
+        // "FROM " + "%s" + "." + ENTITY_TABLE_NAME + "\n" + //
+        // "WHERE " + ENTITY_TABLE_IDENTITY_COLUMN_NAME + " = ?" + "\n" + //
+        // ";" //
+        QuerySpecificationBuilder query = q.querySpecificationBuilder();
+        query.getSelect().addUnnamedColumns( c.colName( DBNames.ENTITY_TABLE_PK_COLUMN_NAME ) );
+        query.getFrom().addTableReferences(
+            t.tableBuilder( t.table( t.tableName( schemaName, DBNames.ENTITY_TABLE_NAME ) ) ) );
+        query.getWhere().reset(
+            b.eq( c.colName( DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME ), l.param() ) );
+
+        return q.createQuery( query.createExpression() );
+    }
+
+    protected DeleteStatement createDeleteFromEntityTableStatement( String schemaName,
+                                                                    SQLVendor vendor
+    )
+    {
+        return this.createDeleteFromTableStatement( schemaName, DBNames.ENTITY_TABLE_NAME,
+                                                    DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME, vendor );
+    }
+
+    protected DeleteStatement
+    createClearEntityDataStatement( String schemaName, SQLVendor vendor )
+    {
+        return this.createDeleteFromTableStatement( schemaName, DBNames.ALL_QNAMES_TABLE_NAME,
+                                                    DBNames.ENTITY_TABLE_PK_COLUMN_NAME, vendor );
+    }
+
+    protected DeleteStatement createDeleteFromTableStatement( String schemaName, String tableName,
+                                                              String columnName,
+                                                              SQLVendor vendor
+    )
+    {
+        ModificationFactory m = vendor.getModificationFactory();
+        BooleanFactory b = vendor.getBooleanFactory();
+        LiteralFactory l = vendor.getLiteralFactory();
+        ColumnsFactory c = vendor.getColumnsFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+
+        // "DELETE FROM " + "%s" + "." + "%s" + "\n" + //
+        // "WHERE " + "%s" + " = ? " + "\n" + //
+        // ";" //
+        DeleteBySearchBuilder delete = m.deleteBySearch();
+        delete.setTargetTable( m.createTargetTable( t.tableName( schemaName, tableName ) ) )
+            .getWhere()
+            .reset( b.eq( c.colName( columnName ), l.param() ) );
+
+        return delete.createExpression();
+    }
+
+    protected InsertStatement createPropertyInsert( QNameInfo qNameInfo, SQLVendor vendor )
+    {
+        String tableName = qNameInfo.getTableName();
+        ModificationFactory m = vendor.getModificationFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+        LiteralFactory l = vendor.getLiteralFactory();
+
+        ColumnSourceByValuesBuilder columnBuilder = m.columnSourceByValues()
+            .addValues( l.param(), l.param(), l.param() );
+        if( qNameInfo.getCollectionDepth() > 0 )
+        {
+            columnBuilder.addValues( l.func( "text2ltree", l.param() ) );
+        }
+        columnBuilder.addValues( l.param() );
+
+        return m.insert().setTableName( t.tableName( this._state.schemaName().get(), tableName ) )
+            .setColumnSource( columnBuilder.createExpression() ).createExpression();
+    }
+
+    protected InsertStatement createAssoInsert( QNameInfo qNameInfo, SQLVendor vendor,
+                                                Integer amountOfParams
+    )
+    {
+        ModificationFactory m = vendor.getModificationFactory();
+        LiteralFactory l = vendor.getLiteralFactory();
+        ColumnsFactory c = vendor.getColumnsFactory();
+        QueryFactory q = vendor.getQueryFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+        BooleanFactory b = vendor.getBooleanFactory();
+        String schemaName = this._state.schemaName().get();
+
+        // "INSERT INTO " + "%s" + "." + "%s" + "\n" + //
+        // "SELECT " + "?, " + "?, " + ENTITY_TABLE_PK_COLUMN_NAME + "\n" + // <-- here is 4 params
+        // when many-asso
+        // "FROM " + "%s" + "." + ENTITY_TABLE_NAME + "\n" + //
+        // "WHERE " + ENTITY_TABLE_IDENTITY_COLUMN_NAME + " = " + "?";
+        QuerySpecificationBuilder qBuilder = q.querySpecificationBuilder();
+        for( Integer x = 0; x < amountOfParams; ++x )
+        {
+            qBuilder.getSelect().addUnnamedColumns( c.colExp( l.param() ) );
+        }
+        qBuilder.getSelect().addUnnamedColumns( c.colName( DBNames.ENTITY_TABLE_PK_COLUMN_NAME ) );
+        qBuilder.getFrom().addTableReferences(
+            t.tableBuilder( t.table( t.tableName( schemaName, DBNames.ENTITY_TABLE_NAME ) ) ) );
+        qBuilder.getWhere().reset(
+            b.eq( c.colName( DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME ), l.param() ) );
+
+        return m
+            .insert()
+            .setTableName( t.tableName( schemaName, qNameInfo.getTableName() ) )
+            .setColumnSource( m.columnSourceByQuery( q.createQuery( qBuilder.createExpression() ) ) )
+            .createExpression();
+    }
+
+    protected InsertStatement createInsertEntityTypeStatement( String schemaName, SQLVendor vendor )
+    {
+        return this.createInsertStatement( schemaName, ENTITY_TYPES_JOIN_TABLE_NAME, 2, vendor );
+    }
+
+    private void syncQNamesInsertPSs( Connection connection,
+                                      Map<QualifiedName, PreparedStatement> qNameInsertPSs,
+                                      Set<QualifiedName> qNames
+    )
+        throws SQLException
+    {
+        Set<QualifiedName> copy = new HashSet<>( qNames );
+        copy.removeAll( qNameInsertPSs.keySet() );
+        for( QualifiedName qName : copy )
+        {
+            QNameInfo info = this._state.qNameInfos().get().get( qName );
+            if( info == null )
+            {
+                throw new InternalError(
+                    "Could not find database information about qualified name [" + qName + "]" );
+            }
+
+            QNameType type = info.getQNameType();
+            if( type.equals( QNameType.PROPERTY ) )
+            {
+                qNameInsertPSs.put( qName, this.createInsertPropertyPS( connection, info ) );
+            }
+            else if( type.equals( QNameType.ASSOCIATION ) )
+            {
+                qNameInsertPSs.put( qName, this.createInsertAssociationPS( connection, info ) );
+            }
+            else if( type.equals( QNameType.MANY_ASSOCIATION ) )
+            {
+                qNameInsertPSs.put( qName, this.createInsertManyAssociationPS( connection, info ) );
+            }
+            else
+            {
+                throw new IllegalArgumentException( "Did not know what to do with QName of type "
+                                                    + type + "." );
+            }
+        }
+    }
+
+    private PreparedStatement createInsertPropertyPS( Connection connection, QNameInfo qNameInfo )
+        throws SQLException
+    {
+        SQLVendor vendor = this.descriptor.metaInfo( SQLVendor.class );
+        return connection.prepareStatement( vendor.toString( this.createPropertyInsert( qNameInfo,
+                                                                                        vendor ) ) );
+    }
+
+    private PreparedStatement
+    createInsertAssociationPS( Connection connection, QNameInfo qNameInfo )
+        throws SQLException
+    {
+        SQLVendor vendor = this.descriptor.metaInfo( SQLVendor.class );
+        return connection.prepareStatement( vendor.toString( this.createAssoInsert( qNameInfo,
+                                                                                    vendor,
+                                                                                    AMOUNT_OF_COLUMNS_IN_ASSO_TABLE ) ) );
+    }
+
+    private PreparedStatement createInsertManyAssociationPS( Connection connection,
+                                                             QNameInfo qNameInfo
+    )
+        throws SQLException
+    {
+        SQLVendor vendor = this.descriptor.metaInfo( SQLVendor.class );
+        return connection.prepareStatement( vendor.toString( this.createAssoInsert( qNameInfo,
+                                                                                    vendor,
+                                                                                    AMOUNT_OF_COLUMNS_IN_MANY_ASSO_TABLE ) ) );
+    }
+
+    private void clearAllEntitysQNames( PreparedStatement clearPropertiesPS, Long pk )
+        throws SQLException
+    {
+        clearPropertiesPS.setLong( 1, pk );
+        clearPropertiesPS.addBatch();
+    }
+
+    private Integer insertPropertyQNames( Connection connection,
+                                          Map<QualifiedName, PreparedStatement> qNameInsertPSs,
+                                          PreparedStatement insertAllQNamesPS, EntityState state, Long entityPK
+    )
+        throws SQLException
+    {
+        Set<QualifiedName> qNames = this._state.entityUsedQNames().get().get( state.entityDescriptor() );
+        this.syncQNamesInsertPSs( connection, qNameInsertPSs, qNames );
+        final Integer propertyPK[] = {0};
+        state.entityDescriptor().state().properties()
+            .filter( pDesc -> SQLSkeletonUtil.isQueryable( pDesc.accessor() ) )
+            .forEach( pDesc -> {
+                try
+                {
+                    propertyPK[0] = this.insertProperty(
+                        qNameInsertPSs,
+                        insertAllQNamesPS,
+                        propertyPK[0],
+                        entityPK,
+                        pDesc.qualifiedName(),
+                        state.propertyValueOf( pDesc.qualifiedName() ),
+                        null //
+                    );
+                }
+                catch( SQLException e )
+                {
+                    throw new EntityStoreException( "Underlying exception when inserting property " + pDesc,
+                                                    SQLUtil.withAllSQLExceptions( e ) );
+                }
+            } );
+        return propertyPK[0];
+    }
+
+    private void insertAssoAndManyAssoQNames( Map<QualifiedName, PreparedStatement> qNameInsertPSs,
+                                              PreparedStatement insertToAllQNamesPS,
+                                              EntityState state,
+                                              final Integer localPK,
+                                              Long entityPK
+    )
+        throws SQLException
+    {
+        final Integer[] qNamePK = {localPK};
+        state.entityDescriptor().state().associations()
+            .filter( aDesc -> SQLSkeletonUtil.isQueryable( aDesc.accessor() ) )
+            .forEach( aDesc -> {
+                try
+                {
+                    QualifiedName qName = aDesc.qualifiedName();
+                    PreparedStatement ps = qNameInsertPSs.get( qName );
+                    EntityReference ref = state.associationValueOf( qName );
+                    if( ref != null )
+                    {
+                        insertToAllQNamesPS.setInt( 1, qNamePK[0] );
+                        insertToAllQNamesPS.setLong( 2, entityPK );
+                        insertToAllQNamesPS.addBatch();
+
+                        ps.setInt( 1, qNamePK[0] );
+                        ps.setLong( 2, entityPK );
+                        ps.setString( 3, ref.identity().toString() );
+                        ps.addBatch();
+
+                        qNamePK[0] += 1;
+                    }
+                }
+                catch( SQLException e )
+                {
+                    throw new EntityStoreException( "Underlying exception when inserting association " + aDesc,
+                                                    SQLUtil.withAllSQLExceptions( e ) );
+                }
+            } );
+
+        state.entityDescriptor().state().manyAssociations()
+            .filter( mDesc -> SQLSkeletonUtil.isQueryable( mDesc.accessor() ) )
+            .forEach( mDesc -> {
+                try
+                {
+                    QualifiedName qName = mDesc.qualifiedName();
+                    PreparedStatement ps = qNameInsertPSs.get( qName );
+                    Integer index = 0;
+                    for( EntityReference ref : state.manyAssociationValueOf( qName ) )
+                    {
+                        if( ref != null )
+                        {
+                            insertToAllQNamesPS.setInt( 1, qNamePK[0] );
+                            insertToAllQNamesPS.setLong( 2, entityPK );
+                            insertToAllQNamesPS.addBatch();
+
+                            ps.setInt( 1, qNamePK[0] );
+                            ps.setLong( 2, entityPK );
+                            ps.setInt( 3, index );
+                            ps.setString( 4, ref.identity().toString() );
+                            ps.addBatch();
+                            qNamePK[0] += 1;
+                        }
+                        ++index;
+                    }
+                }
+                catch( SQLException e )
+                {
+                    throw new EntityStoreException( "Underlying exception when inserting manyassociation " + mDesc,
+                                                    SQLUtil.withAllSQLExceptions( e ) );
+                }
+            } );
+    }
+
+    private Integer insertProperty(
+        Map<QualifiedName, PreparedStatement> qNameInsertPSs,
+        PreparedStatement insertAllQNamesPS,
+        Integer propertyPK,
+        Long entityPK,
+        QualifiedName qName,
+        Object property,
+        Integer parentQNameID
+    )
+        throws SQLException
+    {
+        Integer result = propertyPK;
+        if( property != null )
+        {
+            if( !qName.type().equals( HasIdentity.class.getName() ) )
+            {
+                QNameInfo info = this._state.qNameInfos().get().get( qName );
+                if( info.getCollectionDepth() > 0 )
+                {
+                    result = this.storeCollectionProperty( qNameInsertPSs, insertAllQNamesPS,
+                                                           propertyPK, entityPK,
+                                                           qName, (Collection<?>) property, parentQNameID );
+                }
+                else if( info.isFinalTypePrimitive() )
+                {
+                    result = this.storePrimitiveProperty( qNameInsertPSs, insertAllQNamesPS, propertyPK,
+                                                          entityPK,
+                                                          qName, property, parentQNameID );
+                }
+                else
+                {
+                    result = this.storeValueCompositeProperty( qNameInsertPSs, insertAllQNamesPS,
+                                                               propertyPK, entityPK,
+                                                               qName, property, parentQNameID );
+                }
+            }
+        }
+        return result;
+    }
+
+    private Integer storeCollectionProperty(
+        Map<QualifiedName, PreparedStatement> qNameInsertPSs,
+        PreparedStatement insertAllQNamesPS,
+        Integer propertyPK,
+        Long entityPK,
+        QualifiedName qName,
+        Collection<?> property,
+        Integer parentQNameID
+    )
+        throws SQLException
+    {
+        QNameInfo info = this._state.qNameInfos().get().get( qName );
+        PreparedStatement ps = qNameInsertPSs.get( qName );
+        propertyPK = this.storeCollectionInfo( insertAllQNamesPS, propertyPK, entityPK, parentQNameID, ps,
+                                               info );
+
+        propertyPK = this.storeCollectionItems( qNameInsertPSs, property, insertAllQNamesPS,
+                                                DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME, ps,
+                                                propertyPK, entityPK,
+                                                parentQNameID, info.getFinalType(), info.isFinalTypePrimitive() );
+        return propertyPK;
+    }
+
+    private Integer storeCollectionInfo( PreparedStatement insertAllQNamesPS, Integer propertyPK,
+                                         Long entityPK,
+                                         Integer parentQNameID, PreparedStatement ps, QNameInfo info
+    )
+        throws SQLException
+    {
+        insertAllQNamesPS.setInt( 1, propertyPK );
+        insertAllQNamesPS.setLong( 2, entityPK );
+        insertAllQNamesPS.addBatch();
+
+        ps.setInt( 1, propertyPK );
+        ps.setLong( 2, entityPK );
+        ps.setObject( 3, parentQNameID, Types.BIGINT );
+
+        //noinspection SuspiciousNameCombination
+        ps.setString( 4, DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME );
+        if( info.isFinalTypePrimitive() )
+        {
+            this.storePrimitiveUsingPS( ps, 5, null, info.getFinalType() );
+        }
+        else
+        {
+            this.storeVCClassIDUsingPS( ps, 5, null );
+        }
+        ps.addBatch();
+
+        return propertyPK + 1;
+    }
+
+    private Integer storeCollectionItems( Map<QualifiedName, PreparedStatement> qNameInsertPSs,
+                                          Collection<?> collection,
+                                          PreparedStatement insertAllQNamesPS,
+                                          String path,
+                                          PreparedStatement ps,
+                                          Integer propertyPK,
+                                          Long entityPK,
+                                          Integer parentPK,
+                                          Type finalType,
+                                          Boolean isFinalTypePrimitive
+    )
+        throws SQLException
+    {
+        Integer index = 0;
+        for( Object o : collection )
+        {
+            String itemPath = path + DBNames.QNAME_TABLE_COLLECTION_PATH_SEPARATOR + index;
+            if( o instanceof Collection<?> )
+            {
+                propertyPK = this.storeCollectionItems(
+                    qNameInsertPSs, (Collection<?>) o,
+                    insertAllQNamesPS, itemPath,
+                    ps, propertyPK, entityPK, parentPK, finalType,
+                    isFinalTypePrimitive );
+            }
+            else
+            {
+                propertyPK = this.storeCollectionItem(
+                    qNameInsertPSs, ps, insertAllQNamesPS, propertyPK,
+                    entityPK,
+                    parentPK, itemPath, o, isFinalTypePrimitive, finalType );
+                ps.addBatch();
+            }
+            ++index;
+        }
+        return propertyPK;
+    }
+
+    private Integer storeCollectionItem(
+        Map<QualifiedName, PreparedStatement> qNameInsertPSs, PreparedStatement ps,
+        PreparedStatement insertAllQNamesPS,
+        Integer propertyPK,
+        Long entityPK,
+        Integer parentPK,
+        String path,
+        Object item,
+        Boolean isFinalTypePrimitive,
+        Type finalType
+    )
+        throws SQLException
+    {
+        insertAllQNamesPS.setInt( 1, propertyPK );
+        insertAllQNamesPS.setLong( 2, entityPK );
+        insertAllQNamesPS.addBatch();
+
+        ps.setInt( 1, propertyPK );
+        ps.setLong( 2, entityPK );
+        ps.setObject( 3, parentPK, Types.INTEGER );
+        ps.setString( 4, path );
+        if( isFinalTypePrimitive )
+        {
+            this.storePrimitiveUsingPS( ps, 5, item, finalType );
+            ++propertyPK;
+        }
+        else
+        {
+            this.storeVCClassIDUsingPS( ps, 5, item );
+            propertyPK = this.storePropertiesOfVC( qNameInsertPSs, insertAllQNamesPS, propertyPK, entityPK, item );
+        }
+
+        return propertyPK;
+    }
+
+    private Integer storePrimitiveProperty(
+        Map<QualifiedName, PreparedStatement> qNameInsertPSs,
+        PreparedStatement insertAllQNamesPS,
+        Integer propertyPK,
+        Long entityPK,
+        QualifiedName qName,
+        Object property,
+        Integer parentQNameID
+    )
+        throws SQLException
+    {
+        QNameInfo info = this._state.qNameInfos().get().get( qName );
+        insertAllQNamesPS.setInt( 1, propertyPK );
+        insertAllQNamesPS.setLong( 2, entityPK );
+        insertAllQNamesPS.addBatch();
+
+        PreparedStatement ps = qNameInsertPSs.get( qName );
+        ps.setInt( 1, propertyPK );
+        ps.setLong( 2, entityPK );
+        ps.setObject( 3, parentQNameID, Types.INTEGER );
+        Type type = info.getFinalType();
+        this.storePrimitiveUsingPS( ps, 4, property, type );
+        ps.addBatch();
+
+        return propertyPK + 1;
+    }
+
+    private Integer storeValueCompositeProperty(
+        Map<QualifiedName, PreparedStatement> qNameInsertPSs,
+        PreparedStatement insertAllQNamesPS,
+        Integer propertyPK,
+        Long entityPK,
+        QualifiedName qName,
+        Object property,
+        Integer parentQNameID
+    )
+        throws SQLException
+    {
+
+        PreparedStatement ps = qNameInsertPSs.get( qName );
+        insertAllQNamesPS.setInt( 1, propertyPK );
+        insertAllQNamesPS.setLong( 2, entityPK );
+        insertAllQNamesPS.addBatch();
+
+        ps.setInt( 1, propertyPK );
+        ps.setLong( 2, entityPK );
+        ps.setObject( 3, parentQNameID, Types.INTEGER );
+        this.storeVCClassIDUsingPS( ps, 4, property );
+        ps.addBatch();
+
+        return this.storePropertiesOfVC( qNameInsertPSs, insertAllQNamesPS, propertyPK, entityPK,
+                                         property );
+    }
+
+    private Integer storePropertiesOfVC( Map<QualifiedName, PreparedStatement> qNameInsertPSs,
+                                         PreparedStatement insertAllQNamesPS,
+                                         Integer localPK,
+                                         Long entityPK,
+                                         Object property
+    )
+        throws SQLException
+    {
+        ValueDescriptor vDesc = this._qi4SPI.valueDescriptorFor( property );
+        StateHolder state = PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF.apply( (ValueComposite) property ).state();
+        Integer propertyPK[] = { localPK + 1 };
+        vDesc.state().properties().forEach( pDesc -> {
+
+            try
+            {
+                propertyPK[0] = this.insertProperty(
+                    qNameInsertPSs,
+                    insertAllQNamesPS,
+                    propertyPK[0],
+                    entityPK,
+                    pDesc.qualifiedName(),
+                    state.propertyFor( pDesc.accessor() ).get(),
+                    localPK
+                );
+            }
+            catch( SQLException e )
+            {
+                throw new EntityStoreException( "Underlying exception when inserting property " + pDesc + " in value " + vDesc,
+                                                SQLUtil.withAllSQLExceptions( e ) );
+            }
+        } );
+
+        return propertyPK[0];
+    }
+
+    private void storePrimitiveUsingPS( PreparedStatement ps, Integer nextFreeIndex,
+                                        Object primitive,
+                                        Type primitiveType
+    )
+        throws SQLException
+    {
+        if( primitiveType instanceof ParameterizedType )
+        {
+            primitiveType = ( (ParameterizedType) primitiveType ).getRawType();
+        }
+
+        if( primitiveType instanceof Class<?>
+            && Enum.class.isAssignableFrom( (Class<?>) primitiveType ) )
+        {
+            ps.setInt(
+                nextFreeIndex,
+                this._state.enumPKs().get().get(
+                    QualifiedName.fromClass( (Class<?>) primitiveType, primitive.toString() ).toString() )
+            );
+        }
+        else
+        {
+            this._sqlTypeHelper.addPrimitiveToPS( ps, nextFreeIndex, primitive, primitiveType );
+        }
+    }
+
+    private void storeVCClassIDUsingPS( PreparedStatement ps, Integer nextFreeIndex, Object vc )
+        throws SQLException
+    {
+        if( vc == null )
+        {
+            ps.setNull( nextFreeIndex, Types.INTEGER );
+        }
+        else
+        {
+            ValueDescriptor vDesc = this._qi4SPI.valueDescriptorFor( vc );
+            Integer classID = this._state.usedClassesPKs().get().get( vDesc );
+            ps.setInt( nextFreeIndex, classID );
+        }
+    }
+
+    private void updateEntityInfoAndProperties( Connection connection,
+                                                Map<QualifiedName, PreparedStatement> qNameInsertPSs,
+                                                PreparedStatement insertAllQNamesPS,
+                                                PreparedStatement clearPropertiesPS,
+                                                PreparedStatement ps,
+                                                EntityState state,
+                                                Long entityPK,
+                                                Map<Long, Integer> qNamePKs
+    )
+        throws SQLException
+    {
+
+        this.clearAllEntitysQNames( clearPropertiesPS, entityPK );
+
+        // Update state
+        ps.setString( 1, state.entityReference().identity().toString() );
+        ps.setTimestamp( 2, Timestamp.from( state.lastModified() ) );
+        ps.setString( 3, state.version() );
+        ps.setString( 4, this._app.version() );
+        ps.setLong( 5, entityPK );
+        ps.addBatch();
+
+        Integer nextUsableQNamePK = this.insertPropertyQNames( connection, qNameInsertPSs, insertAllQNamesPS,
+                                                               state, entityPK );
+        qNamePKs.put( entityPK, nextUsableQNamePK );
+    }
+
+    private void insertProperties( Connection connection,
+                                   Map<QualifiedName, PreparedStatement> qNameInsertPSs,
+                                   PreparedStatement insertAllQNamesPS,
+                                   EntityState state,
+                                   Long entityPK,
+                                   Map<Long, Integer> qNamePKs
+    )
+        throws SQLException
+    {
+        Integer nextQnamePK = this.insertPropertyQNames( connection,
+                                                         qNameInsertPSs, insertAllQNamesPS,
+                                                         state, entityPK );
+        qNamePKs.put( entityPK, nextQnamePK );
+    }
+
+    private void removeEntity( EntityState state, PreparedStatement ps )
+        throws SQLException
+    {
+        ps.setString( 1, state.entityReference().identity().toString() );
+        ps.addBatch();
+    }
+
+    private void insertPropertyType( PreparedStatement insertPropertyTypePS, EntityState state, Long entityPK )
+        throws SQLException
+    {
+        state.entityDescriptor().types().forEach( clazz -> {
+            Integer typePK = this._state.entityTypePKs().get().get( clazz.getName() );
+            if( typePK == null )
+            {
+                throw new InternalError( "Tried to get entity : " + clazz
+                                         + ", but only aware of the following entities: "
+                                         + this._state.entityTypePKs().get().keySet() );
+            }
+            try
+            {
+                insertPropertyTypePS.setLong( 1, entityPK );
+                insertPropertyTypePS.setInt( 2, typePK );
+                insertPropertyTypePS.addBatch();
+            }
+            catch( SQLException e )
+            {
+                throw new EntityStoreException( "Underlying Exception when inserting " + entityPK,
+                                                SQLUtil.withAllSQLExceptions( e ) );
+            }
+        } );
+    }
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/AbstractSQLQuerying.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/AbstractSQLQuerying.java
new file mode 100644
index 0000000..1e8d0c0
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/AbstractSQLQuerying.java
@@ -0,0 +1,1884 @@
+/*
+ *  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.polygene.index.sql.support.skeletons;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.sql.ResultSet;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+import java.util.function.Predicate;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.query.grammar.AndPredicate;
+import org.apache.polygene.api.query.grammar.AssociationFunction;
+import org.apache.polygene.api.query.grammar.AssociationNotNullPredicate;
+import org.apache.polygene.api.query.grammar.AssociationNullPredicate;
+import org.apache.polygene.api.query.grammar.ComparisonPredicate;
+import org.apache.polygene.api.query.grammar.ContainsAllPredicate;
+import org.apache.polygene.api.query.grammar.ContainsPredicate;
+import org.apache.polygene.api.query.grammar.EqPredicate;
+import org.apache.polygene.api.query.grammar.GePredicate;
+import org.apache.polygene.api.query.grammar.GtPredicate;
+import org.apache.polygene.api.query.grammar.LePredicate;
+import org.apache.polygene.api.query.grammar.LtPredicate;
+import org.apache.polygene.api.query.grammar.ManyAssociationContainsPredicate;
+import org.apache.polygene.api.query.grammar.ManyAssociationFunction;
+import org.apache.polygene.api.query.grammar.MatchesPredicate;
+import org.apache.polygene.api.query.grammar.NePredicate;
+import org.apache.polygene.api.query.grammar.Notpredicate;
+import org.apache.polygene.api.query.grammar.OrPredicate;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.api.query.grammar.OrderBy.Order;
+import org.apache.polygene.api.query.grammar.PropertyFunction;
+import org.apache.polygene.api.query.grammar.PropertyNotNullPredicate;
+import org.apache.polygene.api.query.grammar.PropertyNullPredicate;
+import org.apache.polygene.api.query.grammar.Variable;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.index.sql.support.api.SQLQuerying;
+import org.apache.polygene.index.sql.support.common.DBNames;
+import org.apache.polygene.index.sql.support.common.QNameInfo;
+import org.apache.polygene.index.sql.support.postgresql.PostgreSQLTypeHelper;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.builders.booleans.BooleanBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.booleans.InBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.GroupByBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.QueryBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.QuerySpecificationBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.TableReferenceBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLFunctions;
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+import org.apache.polygene.library.sql.generator.grammar.factories.BooleanFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.ColumnsFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.LiteralFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.QueryFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.TableReferenceFactory;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReference;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferenceByName;
+import org.apache.polygene.library.sql.generator.grammar.query.Ordering;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.QuerySpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferenceByName;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinType;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.apache.polygene.spi.query.EntityFinderException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractSQLQuerying
+    implements SQLQuerying
+{
+
+    @This
+    private SQLDBState _state;
+
+    @This
+    private PostgreSQLTypeHelper _typeHelper;
+
+    @Structure
+    private UnitOfWorkFactory uowf;
+
+    @Structure
+    private PolygeneSPI spi;
+
+    private static class TraversedAssoOrManyAssoRef
+    {
+        private final AssociationFunction<?> _traversedAsso;
+        private final ManyAssociationFunction<?> _traversedManyAsso;
+        private final boolean _hasRefs;
+
+        private TraversedAssoOrManyAssoRef( AssociationFunction<?> func )
+        {
+            this( func.traversedAssociation(), func.traversedManyAssociation() );
+        }
+
+        private TraversedAssoOrManyAssoRef( PropertyFunction<?> func )
+        {
+            this( func.traversedAssociation(), func.traversedManyAssociation() );
+        }
+
+        private TraversedAssoOrManyAssoRef( ManyAssociationFunction<?> func )
+        {
+            this( func.traversedAssociation(), func.traversedManyAssociation() );
+        }
+
+        private TraversedAssoOrManyAssoRef( AssociationNullPredicate<?> spec )
+        {
+            this( spec.association(), null );
+        }
+
+        private TraversedAssoOrManyAssoRef( AssociationNotNullPredicate<?> spec )
+        {
+            this( spec.association(), null );
+        }
+
+        private TraversedAssoOrManyAssoRef( ManyAssociationContainsPredicate<?> spec )
+        {
+            this( null, spec.manyAssociation() );
+        }
+
+        private TraversedAssoOrManyAssoRef( AssociationFunction<?> traversedAsso,
+                                            ManyAssociationFunction<?> traversedManyAsso
+        )
+        {
+            this._traversedAsso = traversedAsso;
+            this._traversedManyAsso = traversedManyAsso;
+            this._hasRefs = this._traversedAsso != null || this._traversedManyAsso != null;
+        }
+
+        private TraversedAssoOrManyAssoRef getTraversedAssociation()
+        {
+            return this._traversedAsso == null
+                   ? new TraversedAssoOrManyAssoRef( this._traversedManyAsso )
+                   : new TraversedAssoOrManyAssoRef( this._traversedAsso );
+        }
+
+        private AccessibleObject getAccessor()
+        {
+            return this._traversedAsso == null
+                   ? this._traversedManyAsso.accessor()
+                   : this._traversedAsso.accessor();
+        }
+
+        @Override
+        public String toString()
+        {
+            return "[hasRefs="
+                   + this._hasRefs
+                   + ", ref:"
+                   + ( this._hasRefs ? getTraversedAssociations() : "null" )
+                   + "]";
+        }
+
+        private Object getTraversedAssociations()
+        {
+            return this._traversedAsso == null ? this._traversedManyAsso : this._traversedAsso;
+        }
+    }
+
+    public interface SQLBooleanCreator
+    {
+        BooleanExpression getExpression(
+            BooleanFactory factory,
+            NonBooleanExpression left, NonBooleanExpression right
+                                       );
+    }
+
+    private interface BooleanExpressionProcessor
+    {
+        QueryBuilder processBooleanExpression(
+            AbstractSQLQuerying thisObject,
+            Predicate<Composite> expression,
+            Boolean negationActive,
+            SQLVendor vendor,
+            BooleanExpression entityTypeCondition,
+            Map<String, Object> variables,
+            List<Object> values,
+            List<Integer> valueSQLTypes
+                                             );
+    }
+
+    private static final Map<Class<? extends Predicate>, SQLBooleanCreator> SQL_OPERATORS;
+
+    private static final Map<Class<? extends Predicate>, JoinType> JOIN_STYLES;
+
+    private static final Map<Class<? extends Predicate>, JoinType> NEGATED_JOIN_STYLES;
+
+    private static final Map<Class<?>, BooleanExpressionProcessor> EXPRESSION_PROCESSORS;
+
+    private static final String TABLE_NAME_PREFIX = "t";
+
+    private static final String TYPE_TABLE_SUFFIX = "_types";
+
+    private static final Logger LOGGER = LoggerFactory.getLogger( AbstractSQLQuerying.class.getName() );
+
+    static
+    {
+        SQL_OPERATORS = new HashMap<>( 9 );
+        SQL_OPERATORS.put( EqPredicate.class, new SQLBooleanCreator()
+        {
+            @Override
+            public BooleanExpression getExpression(
+                BooleanFactory factory,
+                NonBooleanExpression left, NonBooleanExpression right
+                                                  )
+            {
+                return factory.eq( left, right );
+            }
+        } );
+        SQL_OPERATORS.put( GePredicate.class, new SQLBooleanCreator()
+        {
+            @Override
+            public BooleanExpression getExpression(
+                BooleanFactory factory,
+                NonBooleanExpression left, NonBooleanExpression right
+                                                  )
+            {
+                return factory.geq( left, right );
+            }
+        } );
+        SQL_OPERATORS.put( GtPredicate.class, new SQLBooleanCreator()
+        {
+            @Override
+            public BooleanExpression getExpression(
+                BooleanFactory factory,
+                NonBooleanExpression left, NonBooleanExpression right
+                                                  )
+            {
+                return factory.gt( left, right );
+            }
+        } );
+        SQL_OPERATORS.put( LePredicate.class, new SQLBooleanCreator()
+        {
+            @Override
+            public BooleanExpression getExpression(
+                BooleanFactory factory,
+                NonBooleanExpression left, NonBooleanExpression right
+                                                  )
+            {
+                return factory.leq( left, right );
+            }
+        } );
+        SQL_OPERATORS.put( LtPredicate.class, new SQLBooleanCreator()
+        {
+            @Override
+            public BooleanExpression getExpression(
+                BooleanFactory factory,
+                NonBooleanExpression left, NonBooleanExpression right
+                                                  )
+            {
+                return factory.lt( left, right );
+            }
+        } );
+        SQL_OPERATORS.put( ManyAssociationContainsPredicate.class, new SQLBooleanCreator()
+        {
+            @Override
+            public BooleanExpression getExpression(
+                BooleanFactory factory,
+                NonBooleanExpression left, NonBooleanExpression right
+                                                  )
+            {
+                return factory.eq( left, right );
+            }
+        } );
+        SQL_OPERATORS.put( MatchesPredicate.class, new SQLBooleanCreator()
+        {
+            @Override
+            public BooleanExpression getExpression(
+                BooleanFactory factory,
+                NonBooleanExpression left, NonBooleanExpression right
+                                                  )
+            {
+                return factory.regexp( left, right );
+            }
+        } );
+        SQL_OPERATORS.put( ContainsPredicate.class, new SQLBooleanCreator()
+        {
+            @Override
+            public BooleanExpression getExpression(
+                BooleanFactory factory,
+                NonBooleanExpression left, NonBooleanExpression right
+                                                  )
+            {
+                return factory.eq( left, right );
+            }
+        } );
+        SQL_OPERATORS.put( ContainsAllPredicate.class, new SQLBooleanCreator()
+        {
+            @Override
+            public BooleanExpression getExpression(
+                BooleanFactory factory,
+                NonBooleanExpression left, NonBooleanExpression right
+                                                  )
+            {
+                return factory.eq( left, right );
+            }
+        } );
+
+        JOIN_STYLES = new HashMap<>( 13 );
+        JOIN_STYLES.put( EqPredicate.class, JoinType.INNER );
+        JOIN_STYLES.put( GePredicate.class, JoinType.INNER );
+        JOIN_STYLES.put( GtPredicate.class, JoinType.INNER );
+        JOIN_STYLES.put( LePredicate.class, JoinType.INNER );
+        JOIN_STYLES.put( LtPredicate.class, JoinType.INNER );
+        JOIN_STYLES.put( PropertyNullPredicate.class, JoinType.LEFT_OUTER );
+        JOIN_STYLES.put( PropertyNotNullPredicate.class, JoinType.INNER );
+        JOIN_STYLES.put( AssociationNullPredicate.class, JoinType.LEFT_OUTER );
+        JOIN_STYLES.put( AssociationNotNullPredicate.class, JoinType.INNER );
+        JOIN_STYLES.put( ManyAssociationContainsPredicate.class, JoinType.INNER );
+        JOIN_STYLES.put( MatchesPredicate.class, JoinType.INNER );
+        JOIN_STYLES.put( ContainsPredicate.class, JoinType.INNER );
+        JOIN_STYLES.put( ContainsAllPredicate.class, JoinType.INNER );
+
+        NEGATED_JOIN_STYLES = new HashMap<>( 13 );
+        NEGATED_JOIN_STYLES.put( EqPredicate.class, JoinType.LEFT_OUTER );
+        NEGATED_JOIN_STYLES.put( GePredicate.class, JoinType.LEFT_OUTER );
+        NEGATED_JOIN_STYLES.put( GtPredicate.class, JoinType.LEFT_OUTER );
+        NEGATED_JOIN_STYLES.put( LePredicate.class, JoinType.LEFT_OUTER );
+        NEGATED_JOIN_STYLES.put( LtPredicate.class, JoinType.LEFT_OUTER );
+        NEGATED_JOIN_STYLES.put( PropertyNullPredicate.class, JoinType.INNER );
+        NEGATED_JOIN_STYLES.put( PropertyNotNullPredicate.class, JoinType.LEFT_OUTER );
+        NEGATED_JOIN_STYLES.put( AssociationNullPredicate.class, JoinType.INNER );
+        NEGATED_JOIN_STYLES.put( AssociationNotNullPredicate.class, JoinType.LEFT_OUTER );
+        NEGATED_JOIN_STYLES.put( ManyAssociationContainsPredicate.class, JoinType.INNER );
+        NEGATED_JOIN_STYLES.put( MatchesPredicate.class, JoinType.LEFT_OUTER );
+        NEGATED_JOIN_STYLES.put( ContainsPredicate.class, JoinType.LEFT_OUTER );
+        NEGATED_JOIN_STYLES.put( ContainsAllPredicate.class, JoinType.LEFT_OUTER );
+
+        EXPRESSION_PROCESSORS = new HashMap<>( 17 );
+        EXPRESSION_PROCESSORS.put( AndPredicate.class, new BooleanExpressionProcessor()
+        {
+            @Override
+            public QueryBuilder processBooleanExpression(
+                AbstractSQLQuerying thisObject,
+                Predicate<Composite> expression, Boolean negationActive, SQLVendor vendor,
+                BooleanExpression entityTypeCondition, Map<String, Object> variables,
+                List<Object> values,
+                List<Integer> valueSQLTypes
+            )
+            {
+                QueryBuilder result = null;
+                AndPredicate conjunction = (AndPredicate) expression;
+                for( Predicate<Composite> entitySpecification : conjunction.operands() )
+                {
+                    if( result == null )
+                    {
+                        result = thisObject.processBooleanExpression(
+                            entitySpecification,
+                            negationActive, vendor,
+                            entityTypeCondition, variables, values, valueSQLTypes );
+                    }
+                    else
+                    {
+                        result = result.intersect( thisObject.processBooleanExpression(
+                            entitySpecification, negationActive, vendor,
+                            entityTypeCondition, variables, values, valueSQLTypes )
+                                                       .createExpression() );
+                    }
+                }
+                return result;
+            }
+        } );
+        EXPRESSION_PROCESSORS.put( OrPredicate.class, new BooleanExpressionProcessor()
+        {
+            @Override
+            public QueryBuilder processBooleanExpression(
+                AbstractSQLQuerying thisObject,
+                Predicate<Composite> expression, Boolean negationActive, SQLVendor vendor,
+                BooleanExpression entityTypeCondition, Map<String, Object> variables,
+                List<Object> values,
+                List<Integer> valueSQLTypes
+            )
+            {
+                QueryBuilder result = null;
+                OrPredicate conjunction = (OrPredicate) expression;
+                for( Predicate<Composite> entitySpecification : conjunction.operands() )
+                {
+                    if( result == null )
+                    {
+                        result = thisObject.processBooleanExpression(
+                            entitySpecification,
+                            negationActive, vendor,
+                            entityTypeCondition, variables, values, valueSQLTypes );
+                    }
+                    else
+                    {
+                        result
+                            = result.union( thisObject.processBooleanExpression(
+                            entitySpecification,
+                            negationActive, vendor,
+                            entityTypeCondition, variables, values, valueSQLTypes )
+                                                .createExpression() );
+                    }
+                }
+                return result;
+            }
+        } );
+        EXPRESSION_PROCESSORS.put( Notpredicate.class, new BooleanExpressionProcessor()
+        {
+            @Override
+            public QueryBuilder processBooleanExpression(
+                AbstractSQLQuerying thisObject,
+                Predicate<Composite> expression, Boolean negationActive, SQLVendor vendor,
+                BooleanExpression entityTypeCondition, Map<String, Object> variables,
+                List<Object> values,
+                List<Integer> valueSQLTypes
+            )
+            {
+                return thisObject.processBooleanExpression(
+                    ( (Notpredicate) expression ).operand(), !negationActive, vendor,
+                    entityTypeCondition, variables, values, valueSQLTypes );
+            }
+        } );
+        EXPRESSION_PROCESSORS.put( MatchesPredicate.class, new BooleanExpressionProcessor()
+        {
+            @Override
+            public QueryBuilder processBooleanExpression(
+                AbstractSQLQuerying thisObject,
+                Predicate<Composite> expression, Boolean negationActive, SQLVendor vendor,
+                BooleanExpression entityTypeCondition, Map<String, Object> variables,
+                List<Object> values,
+                List<Integer> valueSQLTypes
+            )
+            {
+                return thisObject.processMatchesPredicate( (MatchesPredicate) expression,
+                                                           negationActive, vendor,
+                                                           entityTypeCondition, variables, values, valueSQLTypes );
+            }
+        } );
+        EXPRESSION_PROCESSORS.put( ManyAssociationContainsPredicate.class, new BooleanExpressionProcessor()
+        {
+            @Override
+            public QueryBuilder processBooleanExpression(
+                AbstractSQLQuerying thisObject,
+                Predicate<Composite> expression, Boolean negationActive,
+                SQLVendor vendor,
+                BooleanExpression entityTypeCondition, Map<String, Object> variables,
+                List<Object> values,
+                List<Integer> valueSQLTypes
+            )
+            {
+                return thisObject.processManyAssociationContainsPredicate(
+                    (ManyAssociationContainsPredicate<?>) expression, negationActive,
+                    vendor, entityTypeCondition,
+                    variables, values, valueSQLTypes );
+            }
+        } );
+        EXPRESSION_PROCESSORS.put( PropertyNullPredicate.class, new BooleanExpressionProcessor()
+        {
+            @Override
+            public QueryBuilder processBooleanExpression(
+                AbstractSQLQuerying thisObject,
+                Predicate<Composite> expression, Boolean negationActive,
+                SQLVendor vendor,
+                BooleanExpression entityTypeCondition, Map<String, Object> variables,
+                List<Object> values,
+                List<Integer> valueSQLTypes
+            )
+            {
+                return thisObject.processPropertyNullPredicate(
+                    (PropertyNullPredicate<?>) expression, negationActive,
+                    vendor, entityTypeCondition );
+            }
+        } );
+        EXPRESSION_PROCESSORS.put( PropertyNotNullPredicate.class, new BooleanExpressionProcessor()
+        {
+            @Override
+            public QueryBuilder processBooleanExpression(
+                AbstractSQLQuerying thisObject,
+                Predicate<Composite> expression, Boolean negationActive,
+                SQLVendor vendor,
+                BooleanExpression entityTypeCondition, Map<String, Object> variables,
+                List<Object> values,
+                List<Integer> valueSQLTypes
+            )
+            {
+                return thisObject.processPropertyNotNullPredicate(
+                    (PropertyNotNullPredicate<?>) expression, negationActive,
+                    vendor, entityTypeCondition );
+            }
+        } );
+        EXPRESSION_PROCESSORS.put( AssociationNullPredicate.class, new BooleanExpressionProcessor()
+        {
+            @Override
+            public QueryBuilder processBooleanExpression(
+                AbstractSQLQuerying thisObject,
+                Predicate<Composite> expression, Boolean negationActive,
+                SQLVendor vendor,
+                BooleanExpression entityTypeCondition, Map<String, Object> variables,
+                List<Object> values,
+                List<Integer> valueSQLTypes
+            )
+            {
+                return thisObject.processAssociationNullPredicate(
+                    (AssociationNullPredicate<?>) expression, negationActive,
+                    vendor, entityTypeCondition );
+            }
+        } );
+        EXPRESSION_PROCESSORS.put( AssociationNotNullPredicate.class, new BooleanExpressionProcessor()
+        {
+            @Override
+            public QueryBuilder processBooleanExpression( AbstractSQLQuerying thisObject,
+                                                          Predicate<Composite> expression,
+                                                          Boolean negationActive,
+                                                          SQLVendor vendor,
+                                                          BooleanExpression entityTypeCondition,
+                                                          Map<String, Object> variables,
+                                                          List<Object> values,
+                                                          List<Integer> valueSQLTypes
+            )
+            {
+                return thisObject.processAssociationNotNullPredicate(
+                    (AssociationNotNullPredicate<?>) expression, negationActive,
+                    vendor, entityTypeCondition );
+            }
+        } );
+        EXPRESSION_PROCESSORS.put( ContainsPredicate.class, new BooleanExpressionProcessor()
+        {
+            @Override
+            public QueryBuilder processBooleanExpression(
+                AbstractSQLQuerying thisObject,
+                Predicate<Composite> expression, Boolean negationActive, SQLVendor vendor,
+                BooleanExpression entityTypeCondition, Map<String, Object> variables,
+                List<Object> values,
+                List<Integer> valueSQLTypes
+            )
+            {
+                return thisObject.processContainsPredicate( (ContainsPredicate<?>) expression,
+                                                            negationActive, vendor,
+                                                            entityTypeCondition, variables, values, valueSQLTypes );
+            }
+        } );
+        EXPRESSION_PROCESSORS.put( ContainsAllPredicate.class, new BooleanExpressionProcessor()
+        {
+            @Override
+            public QueryBuilder processBooleanExpression(
+                AbstractSQLQuerying thisObject,
+                Predicate<Composite> expression, Boolean negationActive, SQLVendor vendor,
+                BooleanExpression entityTypeCondition, Map<String, Object> variables,
+                List<Object> values,
+                List<Integer> valueSQLTypes
+            )
+            {
+                return thisObject.processContainsAllPredicate(
+                    (ContainsAllPredicate<?>) expression, negationActive,
+                    vendor, entityTypeCondition, variables, values, valueSQLTypes );
+            }
+        } );
+        BooleanExpressionProcessor comparisonProcessor = new BooleanExpressionProcessor()
+        {
+            @Override
+            public QueryBuilder processBooleanExpression(
+                AbstractSQLQuerying thisObject,
+                Predicate<Composite> expression, Boolean negationActive, SQLVendor vendor,
+                BooleanExpression entityTypeCondition, Map<String, Object> variables,
+                List<Object> values,
+                List<Integer> valueSQLTypes
+            )
+            {
+                return thisObject.processComparisonPredicate(
+                    (ComparisonPredicate<?>) expression, negationActive, vendor,
+                    entityTypeCondition, variables, values, valueSQLTypes );
+            }
+        };
+        EXPRESSION_PROCESSORS.put( EqPredicate.class, comparisonProcessor );
+        EXPRESSION_PROCESSORS.put( NePredicate.class, comparisonProcessor );
+        EXPRESSION_PROCESSORS.put( GePredicate.class, comparisonProcessor );
+        EXPRESSION_PROCESSORS.put( GtPredicate.class, comparisonProcessor );
+        EXPRESSION_PROCESSORS.put( LePredicate.class, comparisonProcessor );
+        EXPRESSION_PROCESSORS.put( LtPredicate.class, comparisonProcessor );
+    }
+
+    private interface WhereClauseProcessor
+    {
+        void processWhereClause( QuerySpecificationBuilder builder,
+                                 BooleanBuilder afterWhere,
+                                 JoinType joinStyle, Integer firstTableIndex, Integer lastTableIndex
+                               );
+    }
+
+    private static class PropertyNullWhereClauseProcessor
+        implements WhereClauseProcessor
+    {
+        private final boolean negationActive;
+        private final SQLVendor vendor;
+        private final SQLDBState state;
+        private final PropertyFunction<?> propFunction;
+
+        private PropertyNullWhereClauseProcessor( SQLDBState pState, SQLVendor pVendor,
+                                                  PropertyFunction<?> pPropFunction,
+                                                  boolean pNegationActive
+        )
+        {
+            this.state = pState;
+            this.vendor = pVendor;
+            this.negationActive = pNegationActive;
+            this.propFunction = pPropFunction;
+        }
+
+        @Override
+        public void processWhereClause( QuerySpecificationBuilder builder,
+                                        BooleanBuilder afterWhere,
+                                        JoinType joinStyle, Integer firstTableIndex, Integer lastTableIndex
+        )
+        {
+            if( !this.negationActive )
+            {
+                ColumnsFactory c = this.vendor.getColumnsFactory();
+                BooleanFactory b = this.vendor.getBooleanFactory();
+
+                QNameInfo info = this.state
+                    .qNameInfos()
+                    .get()
+                    .get(
+                        QualifiedName.fromAccessor( this.propFunction.accessor() ) );
+                String colName;
+                if( info.getCollectionDepth() > 0 )
+                {
+                    colName = DBNames.ALL_QNAMES_TABLE_PK_COLUMN_NAME;
+                }
+                else
+                {
+                    colName = DBNames.QNAME_TABLE_VALUE_COLUMN_NAME;
+                }
+                // Last table column might be null because of left joins
+                builder.getWhere().reset(
+                    b.isNull( c.colName( TABLE_NAME_PREFIX + lastTableIndex, colName ) ) );
+            }
+        }
+    }
+
+    private static class AssociationNullWhereClauseProcessor
+        implements WhereClauseProcessor
+    {
+        private final boolean negationActive;
+        private final SQLVendor vendor;
+
+        private AssociationNullWhereClauseProcessor( SQLVendor pVendor, boolean pNegationActive )
+        {
+            this.vendor = pVendor;
+            this.negationActive = pNegationActive;
+        }
+
+        @Override
+        public void processWhereClause( QuerySpecificationBuilder builder,
+                                        BooleanBuilder afterWhere,
+                                        JoinType joinStyle, Integer firstTableIndex, Integer lastTableIndex
+        )
+        {
+            if( !negationActive )
+            {
+                ColumnsFactory c = vendor.getColumnsFactory();
+                BooleanFactory b = vendor.getBooleanFactory();
+
+                // Last table column might be null because of left joins
+                builder.getWhere().reset(
+                    b.isNull( c.colName( TABLE_NAME_PREFIX + lastTableIndex,
+                                         DBNames.QNAME_TABLE_VALUE_COLUMN_NAME ) ) );
+            }
+        }
+    }
+
+    private static class ModifiableInt
+    {
+        private int _int;
+
+        private ModifiableInt( Integer integer )
+        {
+            this._int = integer;
+        }
+
+        private int getInt()
+        {
+            return this._int;
+        }
+
+        private void setInt( int integer )
+        {
+            this._int = integer;
+        }
+
+        @Override
+        public String toString()
+        {
+            return Integer.toString( this._int );
+        }
+    }
+
+    private static class QNameJoin
+    {
+        private final QualifiedName _sourceQName;
+
+        private final QualifiedName _targetQName;
+
+        private final Integer _sourceTableIndex;
+
+        private final Integer _targetTableIndex;
+
+        private QNameJoin( QualifiedName sourceQName, QualifiedName targetQName,
+                           Integer sourceTableIndex,
+                           Integer targetTableIndex
+        )
+        {
+            this._sourceQName = sourceQName;
+            this._targetQName = targetQName;
+            this._sourceTableIndex = sourceTableIndex;
+            this._targetTableIndex = targetTableIndex;
+        }
+
+        private QualifiedName getSourceQName()
+        {
+            return this._sourceQName;
+        }
+
+        private QualifiedName getTargetQName()
+        {
+            return this._targetQName;
+        }
+
+        private Integer getSourceTableIndex()
+        {
+            return this._sourceTableIndex;
+        }
+
+        private Integer getTargetTableIndex()
+        {
+            return this._targetTableIndex;
+        }
+    }
+
+    @Override
+    public Integer getResultSetType( Integer firstResult, Integer maxResults )
+    {
+        return ResultSet.TYPE_FORWARD_ONLY;
+    }
+
+    @Override
+    public Boolean isFirstResultSettingSupported()
+    {
+        return true;
+    }
+
+    @Uses
+    private ServiceDescriptor descriptor;
+
+    @Override
+    public String constructQuery( Class<?> resultType, //
+                                  Predicate<Composite> whereClause, //
+                                  List<OrderBy> orderBySegments, //
+                                  Integer firstResult, //
+                                  Integer maxResults, //
+                                  Map<String, Object> variables, //
+                                  List<Object> values, //
+                                  List<Integer> valueSQLTypes, //
+                                  Boolean countOnly //
+    )
+        throws EntityFinderException
+    {
+        SQLVendor vendor = this.descriptor.metaInfo( SQLVendor.class );
+
+        QueryFactory q = vendor.getQueryFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+        LiteralFactory l = vendor.getLiteralFactory();
+        ColumnsFactory c = vendor.getColumnsFactory();
+
+        ColumnReference mainColumn = c.colName( TABLE_NAME_PREFIX + "0", DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME );
+        if( countOnly )
+        {
+            mainColumn = c.colExp( l.func( SQLFunctions.COUNT, mainColumn ) );
+        }
+
+        QueryBuilder innerBuilder = this.processBooleanExpression(
+            whereClause, false, vendor,
+            this.createTypeCondition( resultType, vendor ), variables, values, valueSQLTypes );
+
+        QuerySpecificationBuilder mainQuery = q.querySpecificationBuilder();
+        mainQuery.getSelect().addUnnamedColumns( mainColumn );
+        mainQuery.getFrom().addTableReferences(
+            t.tableBuilder( t.table( q.createQuery( innerBuilder.createExpression() ),
+                                     t.tableAlias( TABLE_NAME_PREFIX + "0" ) ) ) );
+
+        this.processOrderBySegments( orderBySegments, vendor, mainQuery );
+
+        QueryExpression finalMainQuery = this.finalizeQuery(
+            vendor, mainQuery, resultType, whereClause,
+            orderBySegments, firstResult, maxResults, variables, values, valueSQLTypes,
+            countOnly );
+
+        String result = vendor.toString( finalMainQuery );
+
+        LOGGER.info( "SQL query:\n" + result );
+        return result;
+    }
+
+    protected BooleanExpression createTypeCondition(
+        Class<?> resultType,
+        SQLVendor vendor
+                                                   )
+    {
+        BooleanFactory b = vendor.getBooleanFactory();
+        LiteralFactory l = vendor.getLiteralFactory();
+        ColumnsFactory c = vendor.getColumnsFactory();
+
+        List<Integer> typeIDs = this.getEntityTypeIDs( resultType );
+        InBuilder in = b.inBuilder( c.colName( TABLE_NAME_PREFIX + TYPE_TABLE_SUFFIX,
+                                               DBNames.ENTITY_TYPES_TABLE_PK_COLUMN_NAME ) );
+        for( Integer i : typeIDs )
+        {
+            in.addValues( l.n( i ) );
+        }
+
+        return in.createExpression();
+    }
+
+    protected abstract QueryExpression finalizeQuery(
+        SQLVendor sqlVendor, QuerySpecificationBuilder specBuilder,
+        Class<?> resultType,
+        Predicate<Composite> whereClause,
+        List<OrderBy> orderBySegments,
+        Integer firstResult,
+        Integer maxResults,
+        Map<String, Object> variables,
+        List<Object> values,
+        List<Integer> valueSQLTypes,
+        Boolean countOnly
+    );
+
+    protected QueryBuilder processBooleanExpression(
+        Predicate<Composite> expression,
+        Boolean negationActive,
+        SQLVendor vendor,
+        BooleanExpression entityTypeCondition,
+        Map<String, Object> variables,
+        List<Object> values,
+        List<Integer> valueSQLTypes
+    )
+    {
+        QueryBuilder result = null;
+        if( expression == null )
+        {
+            QueryFactory q = vendor.getQueryFactory();
+            result = q.queryBuilder(
+                this.selectAllEntitiesOfCorrectType( vendor, entityTypeCondition ).createExpression() );
+        }
+        else
+        {
+            if( EXPRESSION_PROCESSORS.containsKey( expression.getClass() ) )
+            {
+                result = EXPRESSION_PROCESSORS.get( expression.getClass() ).processBooleanExpression(
+                    this, expression,
+                    negationActive, vendor, entityTypeCondition, variables, values,
+                    valueSQLTypes );
+            }
+            else
+            {
+                throw new UnsupportedOperationException( "Expression " + expression + " of type "
+                                                         + expression.getClass() + " is not supported" );
+            }
+        }
+        return result;
+    }
+
+    protected QuerySpecificationBuilder selectAllEntitiesOfCorrectType(
+        SQLVendor vendor,
+        BooleanExpression entityTypeCondition
+    )
+    {
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+
+        String tableAlias = TABLE_NAME_PREFIX + "0";
+        TableReferenceBuilder from = t.tableBuilder( t.table(
+            t.tableName( this._state.schemaName().get(), DBNames.ENTITY_TABLE_NAME ),
+            t.tableAlias( tableAlias ) ) );
+
+        this.addTypeJoin( vendor, from, 0 );
+
+        QuerySpecificationBuilder query = this.getBuilderForPredicate( vendor, tableAlias );
+        query.getFrom().addTableReferences( from );
+        query.getWhere().reset( entityTypeCondition );
+
+        return query;
+    }
+
+    protected QueryBuilder processMatchesPredicate(
+        final MatchesPredicate predicate,
+        final Boolean negationActive,
+        final SQLVendor vendor,
+        BooleanExpression entityTypeCondition,
+        final Map<String, Object> variables, final List<Object> values,
+        final List<Integer> valueSQLTypes
+    )
+    {
+        return this.singleQuery(
+            predicate,
+            predicate.property(),
+            null,
+            null,
+            negationActive,
+            vendor,
+            entityTypeCondition,
+            new WhereClauseProcessor()
+            {
+
+                @Override
+                public void processWhereClause( QuerySpecificationBuilder builder,
+                                                BooleanBuilder afterWhere,
+                                                JoinType joinStyle, Integer firstTableIndex, Integer lastTableIndex
+                )
+                {
+                    LiteralFactory l = vendor.getLiteralFactory();
+                    ColumnsFactory c = vendor.getColumnsFactory();
+
+                    builder.getWhere().reset(
+                        vendor.getBooleanFactory().regexp(
+                            c.colName( TABLE_NAME_PREFIX + lastTableIndex,
+                                       DBNames.QNAME_TABLE_VALUE_COLUMN_NAME ),
+                            l.param() ) );
+
+                    Object value = predicate.value();
+                    if( value instanceof Variable )
+                    {
+                        value = variables.get( ( (Variable) value ).variableName() );
+                    }
+                    values.add( translateJavaRegexpToPGSQLRegexp( value.toString() ) );
+                    valueSQLTypes.add( Types.VARCHAR );
+                }
+            } //
+        );
+    }
+
+    protected QueryBuilder processComparisonPredicate(
+        final ComparisonPredicate<?> predicate,
+        final Boolean negationActive, final SQLVendor vendor,
+        BooleanExpression entityTypeCondition,
+        final Map<String, Object> variables,
+        final List<Object> values, final List<Integer> valueSQLTypes
+    )
+    {
+        return this.singleQuery(
+            predicate,
+            predicate.property(),
+            null,
+            null,
+            negationActive,
+            vendor,
+            entityTypeCondition,
+            new WhereClauseProcessor()
+            {
+
+                @Override
+                public void processWhereClause( QuerySpecificationBuilder builder,
+                                                BooleanBuilder afterWhere,
+                                                JoinType joinStyle, Integer firstTableIndex, Integer lastTableIndex
+                )
+                {
+                    QualifiedName qName
+                        = QualifiedName.fromAccessor( predicate.property().accessor() );
+                    String columnName;
+                    Object value;
+                    if( qName.type().equals( HasIdentity.class.getName() ) )
+                    {
+                        columnName = DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME;
+                        value = predicate.value().toString();
+                    }
+                    else
+                    {
+                        columnName = DBNames.QNAME_TABLE_VALUE_COLUMN_NAME;
+                        value = predicate.value();
+                    }
+                    modifyFromClauseAndWhereClauseToGetValue(
+                        qName, value, predicate,
+                        negationActive, lastTableIndex,
+                        new ModifiableInt( lastTableIndex ), columnName,
+                        DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME, vendor,
+                        builder.getWhere(), afterWhere,
+                        builder.getFrom().getTableReferences().iterator().next(),
+                        builder.getGroupBy(),
+                        builder.getHaving(), new ArrayList<QNameJoin>(), variables, values,
+                        valueSQLTypes );
+                }
+            } //
+        );
+    }
+
+    protected QueryBuilder processManyAssociationContainsPredicate(
+        final ManyAssociationContainsPredicate<?> predicate, final Boolean negationActive,
+        final SQLVendor vendor,
+        BooleanExpression entityTypeCondition,
+        Map<String, Object> variables,
+        final List<Object> values, final List<Integer> valueSQLTypes
+    )
+    {
+        return this.singleQuery(
+            predicate,
+            null,
+            new TraversedAssoOrManyAssoRef( predicate ), // not sure about this, was 'null' before but I think this is needed.
+            true,
+            negationActive,
+            vendor,
+            entityTypeCondition,
+            new WhereClauseProcessor()
+            {
+
+                @Override
+                public void processWhereClause( QuerySpecificationBuilder builder,
+                                                BooleanBuilder afterWhere,
+                                                JoinType joinStyle, Integer firstTableIndex, Integer lastTableIndex
+                )
+                {
+                    LiteralFactory l = vendor.getLiteralFactory();
+                    ColumnsFactory c = vendor.getColumnsFactory();
+                    BooleanFactory b = vendor.getBooleanFactory();
+
+                    builder.getWhere().reset(
+                        getOperator( predicate ).getExpression(
+                            b,
+                            c.colName( TABLE_NAME_PREFIX + lastTableIndex,
+                                       DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME ),
+                            l.param() ) );
+
+                    Object value = predicate.value();
+                    // TODO Is it really certain that this value is always instance of
+                    // EntityComposite?
+                    if( value instanceof EntityComposite )
+                    {
+                        value = uowf.currentUnitOfWork().get(
+                            (EntityComposite) value ).identity().get().toString();
+                    }
+                    else
+                    {
+                        value = value.toString();
+                    }
+                    values.add( value );
+                    valueSQLTypes.add( Types.VARCHAR );
+                }
+            }
+        );
+    }
+
+    protected QueryBuilder processPropertyNullPredicate(
+        final PropertyNullPredicate<?> predicate,
+        final Boolean negationActive, final SQLVendor vendor,
+        BooleanExpression entityTypeCondition
+    )
+    {
+        return this.singleQuery(
+            predicate,
+            predicate.property(),
+            null,
+            null,
+            negationActive,
+            vendor,
+            entityTypeCondition,
+            new PropertyNullWhereClauseProcessor( this._state, vendor, predicate.property(), negationActive )
+        );
+    }
+
+    protected QueryBuilder processPropertyNotNullPredicate(
+        PropertyNotNullPredicate<?> predicate,
+        boolean negationActive, SQLVendor vendor,
+        BooleanExpression entityTypeCondition
+    )
+    {
+        return this.singleQuery(
+            predicate,
+            predicate.property(),
+            null,
+            null,
+            negationActive,
+            vendor,
+            entityTypeCondition,
+            new PropertyNullWhereClauseProcessor( this._state, vendor, predicate.property(), !negationActive )
+        );
+    }
+
+    protected QueryBuilder processAssociationNullPredicate(
+        final AssociationNullPredicate<?> predicate,
+        final Boolean negationActive, final SQLVendor vendor,
+        BooleanExpression entityTypeCondition
+    )
+    {
+        return this.singleQuery(
+            predicate, //
+            null, //
+            new TraversedAssoOrManyAssoRef( predicate ), //
+            false, //
+            negationActive, //
+            vendor, //
+            entityTypeCondition, //
+            new AssociationNullWhereClauseProcessor( vendor, negationActive )
+        );
+    }
+
+    protected QueryBuilder processAssociationNotNullPredicate(
+        final AssociationNotNullPredicate<?> predicate,
+        final Boolean negationActive, final SQLVendor vendor,
+        BooleanExpression entityTypeCondition
+    )
+    {
+        return this.singleQuery(
+            predicate, //
+            null, //
+            new TraversedAssoOrManyAssoRef( predicate ), //
+            false, //
+            negationActive, //
+            vendor, //
+            entityTypeCondition, //
+            new AssociationNullWhereClauseProcessor( vendor, !negationActive )
+        );
+    }
+
+    protected QueryBuilder processContainsPredicate(
+        final ContainsPredicate<?> predicate,
+        final Boolean negationActive, final SQLVendor vendor,
+        BooleanExpression entityTypeCondition,
+        final Map<String, Object> variables,
+        final List<Object> values, final List<Integer> valueSQLTypes
+    )
+    {
+        // Path: Top.* (star without braces), value = value
+        // ASSUMING value is NOT collection (ie, find all entities, which collection property has
+        // value x as leaf item,
+        // no matter collection depth)
+        QuerySpecification contains = this.constructQueryForPredicate(
+            predicate, //
+            predicate.collectionProperty(), //
+            null, //
+            null, //
+            false, //
+            vendor, //
+            entityTypeCondition, //
+            new WhereClauseProcessor()
+            {
+                @Override
+                public void processWhereClause( QuerySpecificationBuilder builder,
+                                                BooleanBuilder afterWhere,
+                                                JoinType joinStyle, Integer firstTableIndex, Integer lastTableIndex
+                )
+                {
+                    BooleanFactory b = vendor.getBooleanFactory();
+                    LiteralFactory l = vendor.getLiteralFactory();
+                    ColumnsFactory c = vendor.getColumnsFactory();
+
+                    builder.getWhere().reset(
+                        b.regexp( c.colName( TABLE_NAME_PREFIX + lastTableIndex,
+                                             DBNames.QNAME_TABLE_COLLECTION_PATH_COLUMN_NAME ), l
+                                      .s( DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME + ".*{1,}" ) ) );
+
+                    Object value = predicate.value();
+                    if( value instanceof Collection<?> )
+                    {
+                        throw new IllegalArgumentException(
+                            "ContainsPredicate may have only either primitive or value composite as value." );
+                    }
+                    BooleanBuilder condition = b.booleanBuilder();
+                    modifyFromClauseAndWhereClauseToGetValue(
+                        QualifiedName.fromAccessor( predicate.collectionProperty().accessor() ), value, predicate,
+                        false, lastTableIndex, new ModifiableInt( lastTableIndex ),
+                        DBNames.QNAME_TABLE_VALUE_COLUMN_NAME,
+                        DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME,
+                        vendor, condition, afterWhere, builder.getFrom().getTableReferences()
+                            .iterator().next(),
+                        builder.getGroupBy(), builder.getHaving(), new ArrayList<QNameJoin>(),
+                        variables, values, valueSQLTypes );
+                    builder.getWhere().and( condition.createExpression() );
+                }
+            } //
+        );
+
+        return this.finalizeContainsQuery( vendor, contains, entityTypeCondition, negationActive );
+    }
+
+    protected QueryBuilder finalizeContainsQuery(
+        SQLVendor vendor, QuerySpecification contains,
+        BooleanExpression entityTypeCondition,
+        Boolean negationActive
+    )
+    {
+        QueryFactory q = vendor.getQueryFactory();
+        QueryBuilder result;
+
+        if( negationActive )
+        {
+            result = q.queryBuilder(
+                this.selectAllEntitiesOfCorrectType( vendor, entityTypeCondition )
+                    .createExpression() ).except(
+                contains );
+        }
+        else
+        {
+            result = q.queryBuilder( contains );
+        }
+
+        return result;
+    }
+
+    protected QueryBuilder processContainsAllPredicate(
+        final ContainsAllPredicate<?> predicate, final Boolean negationActive,
+        final SQLVendor vendor,
+        BooleanExpression entityTypeCondition,
+        final Map<String, Object> variables, final List<Object> values,
+        final List<Integer> valueSQLTypes
+    )
+    {
+        // has all leaf items in specified collection
+
+        QuerySpecification contains = this.constructQueryForPredicate(
+            predicate, //
+            predicate.collectionProperty(), //
+            null, //
+            null, //
+            false, //
+            vendor, //
+            entityTypeCondition, //
+            new WhereClauseProcessor()
+            {
+
+                @Override
+                public void processWhereClause( QuerySpecificationBuilder builder,
+                                                BooleanBuilder afterWhere,
+                                                JoinType joinStyle, Integer firstTableIndex, Integer lastTableIndex
+                )
+                {
+                    BooleanFactory b = vendor.getBooleanFactory();
+                    LiteralFactory l = vendor.getLiteralFactory();
+                    ColumnsFactory c = vendor.getColumnsFactory();
+
+                    Collection<?> collection = predicate.containedValues();
+                    List<QNameJoin> joins = new ArrayList<>();
+                    for( Object value : collection )
+                    {
+                        if( value instanceof Collection<?> )
+                        {
+                            throw new IllegalArgumentException(
+                                "ContainsAllPredicate may not have nested collections as value." );
+                        }
+
+                        BooleanBuilder conditionForItem = b.booleanBuilder(
+                            b.regexp( c.colName( TABLE_NAME_PREFIX + lastTableIndex,
+                                                 DBNames.QNAME_TABLE_COLLECTION_PATH_COLUMN_NAME ),
+                                      l.s( DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME + ".*{1,}" ) ) );
+                        modifyFromClauseAndWhereClauseToGetValue(
+                            QualifiedName.fromAccessor( predicate.collectionProperty().accessor() ),
+                            value, predicate, false, lastTableIndex,
+                            new ModifiableInt( lastTableIndex ),
+                            DBNames.QNAME_TABLE_VALUE_COLUMN_NAME,
+                            DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME, vendor,
+                            conditionForItem, afterWhere,
+                            builder.getFrom().getTableReferences().iterator().next(),
+                            builder.getGroupBy(), builder.getHaving(),
+                            joins, variables, values, valueSQLTypes );
+                        builder.getWhere().or( conditionForItem.createExpression() );
+                    }
+
+                    builder.getHaving()
+                        .and(
+                            b.geq(
+                                l.func( "COUNT", c.colName( TABLE_NAME_PREFIX + lastTableIndex,
+                                                            DBNames.QNAME_TABLE_VALUE_COLUMN_NAME ) ),
+                                l.n( collection.size() ) ) );
+                }
+            } //
+        );
+
+        return this.finalizeContainsQuery( vendor, contains, entityTypeCondition, negationActive );
+    }
+
+    protected QueryBuilder singleQuery(
+        Predicate<Composite> predicate, //
+        PropertyFunction<?> propRef, //
+        TraversedAssoOrManyAssoRef assoRef, //
+        Boolean includeLastAssoPathTable, //
+        Boolean negationActive, //
+        SQLVendor vendor, //
+        BooleanExpression entityTypeCondition, //
+        WhereClauseProcessor whereClauseGenerator//
+    )
+    {
+        return vendor.getQueryFactory().queryBuilder(
+            this.constructQueryForPredicate( predicate, propRef, assoRef, includeLastAssoPathTable,
+                                             negationActive,
+                                             vendor, entityTypeCondition, whereClauseGenerator ) );
+    }
+
+    protected QuerySpecification constructQueryForPredicate(
+        Predicate<Composite> predicate, //
+        PropertyFunction<?> propRef, //
+        TraversedAssoOrManyAssoRef assoRef, //
+        Boolean includeLastAssoPathTable, //
+        Boolean negationActive, //
+        SQLVendor vendor, //
+        BooleanExpression entityTypeCondition, //
+        WhereClauseProcessor whereClauseGenerator//
+    )
+    {
+        Integer startingIndex = 0;
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+
+        QuerySpecificationBuilder builder = this.getBuilderForPredicate( vendor, TABLE_NAME_PREFIX + startingIndex );
+        TableReferenceBuilder from = t.tableBuilder( t.table(
+            t.tableName( this._state.schemaName().get(), DBNames.ENTITY_TABLE_NAME ),
+            t.tableAlias( TABLE_NAME_PREFIX + startingIndex ) ) );
+
+        this.addTypeJoin( vendor, from, startingIndex );
+
+        Integer lastTableIndex = null;
+        JoinType joinStyle = this.getTableJoinStyle( predicate, negationActive );
+        if( propRef == null && assoRef != null && assoRef._hasRefs )
+        {
+            lastTableIndex = this.traverseAssociationPath( assoRef, startingIndex, startingIndex + 1, vendor, from,
+                                                           joinStyle, includeLastAssoPathTable );
+        }
+        else if( assoRef == null || !assoRef._hasRefs )
+        {
+            lastTableIndex = this.traversePropertyPath( propRef, startingIndex, startingIndex + 1, vendor, from,
+                                                        joinStyle );
+        }
+        else
+        {
+            throw new InternalError(
+                "Can not have both property reference and association reference (non-)nulls [propRef=" + propRef
+                + ", assoRef=" + assoRef + ", predicate=" + predicate + "]." );
+        }
+
+        builder.getFrom().addTableReferences( from );
+
+        BooleanBuilder afterWhere = vendor.getBooleanFactory().booleanBuilder();
+        whereClauseGenerator.processWhereClause( builder, afterWhere, joinStyle, startingIndex, lastTableIndex );
+
+        BooleanBuilder where = builder.getWhere();
+        if( negationActive )
+        {
+            where.not();
+        }
+        where.and( afterWhere.createExpression() );
+
+        where.and( entityTypeCondition );
+
+        builder.trimGroupBy();
+
+        return builder.createExpression();
+    }
+
+    protected void addTypeJoin( SQLVendor vendor, TableReferenceBuilder from, int startingIndex )
+    {
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+        BooleanFactory b = vendor.getBooleanFactory();
+        ColumnsFactory c = vendor.getColumnsFactory();
+
+        from.addQualifiedJoin(
+            JoinType.INNER,
+            t.table(
+                t.tableName( this._state.schemaName().get(), DBNames.ENTITY_TYPES_JOIN_TABLE_NAME ),
+                t.tableAlias( TABLE_NAME_PREFIX + TYPE_TABLE_SUFFIX ) ),
+            t.jc( b.eq(
+                c.colName( TABLE_NAME_PREFIX + startingIndex, DBNames.ENTITY_TABLE_PK_COLUMN_NAME ),
+                c.colName( TABLE_NAME_PREFIX + TYPE_TABLE_SUFFIX, DBNames.ENTITY_TABLE_PK_COLUMN_NAME ) ) )
+        );
+    }
+
+    protected SQLBooleanCreator getOperator( Predicate<Composite> predicate )
+    {
+        return this.findFromLookupTables( SQL_OPERATORS, null, predicate, false );
+    }
+
+    protected JoinType getTableJoinStyle( Predicate<Composite> predicate, Boolean negationActive )
+    {
+        return this.findFromLookupTables( JOIN_STYLES, NEGATED_JOIN_STYLES, predicate,
+                                          negationActive );
+    }
+
+    protected <ReturnType> ReturnType findFromLookupTables(
+        Map<Class<? extends Predicate>, ReturnType> normal,
+        Map<Class<? extends Predicate>, ReturnType> negated,
+        Predicate<Composite> predicate, Boolean negationActive
+    )
+    {
+        Class<? extends Predicate> predicateClass = predicate.getClass();
+        ReturnType result = null;
+        Set<Map.Entry<Class<? extends Predicate>, ReturnType>> entries = negationActive
+                                                                         ? negated.entrySet()
+                                                                         : normal.entrySet();
+        for( Map.Entry<Class<? extends Predicate>, ReturnType> entry : entries )
+        {
+            if( entry.getKey().isAssignableFrom( predicateClass ) )
+            {
+                result = entry.getValue();
+                break;
+            }
+        }
+
+        if( result == null )
+        {
+            throw new UnsupportedOperationException( "Predicate [" + predicateClass.getName() + "] is not supported" );
+        }
+
+        return result;
+    }
+
+    protected QuerySpecificationBuilder getBuilderForPredicate( SQLVendor vendor, String tableAlias )
+    {
+        QueryFactory q = vendor.getQueryFactory();
+        ColumnsFactory c = vendor.getColumnsFactory();
+        QuerySpecificationBuilder result = q.querySpecificationBuilder();
+        result
+            .getSelect()
+            .setSetQuantifier( SetQuantifier.DISTINCT )
+            .addUnnamedColumns( c.colName( tableAlias, DBNames.ENTITY_TABLE_PK_COLUMN_NAME ),
+                                c.colName( tableAlias, DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME ) );
+
+        return result;
+    }
+
+    protected String translateJavaRegexpToPGSQLRegexp( String javaRegexp )
+    {
+        // TODO
+        // Yo dawg, I heard you like regular expressions, so we made a regexp about your regexp so
+        // you can match while
+        // you match!
+        // Meaning, probably best way to translate java regexp into pg-sql regexp is by... regexp.
+        return javaRegexp;
+    }
+
+    protected void processOrderBySegments( List<OrderBy> orderBy, SQLVendor vendor,
+                                           QuerySpecificationBuilder builder
+    )
+    {
+        if( orderBy != null )
+        {
+            QNameInfo[] qNames = new QNameInfo[ orderBy.size() ];
+
+            QueryFactory q = vendor.getQueryFactory();
+            ColumnsFactory c = vendor.getColumnsFactory();
+
+            Integer tableIndex = 0;
+            for( Integer idx = 0; idx < orderBy.size(); ++idx )
+            {
+                if( orderBy.get( idx ) != null )
+                {
+                    PropertyFunction<?> ref = orderBy.get( idx ).property();
+                    QualifiedName qName = QualifiedName.fromAccessor( ref.accessor() );
+                    QNameInfo info = this._state.qNameInfos().get().get( qName );
+                    qNames[ idx ] = info;
+                    if( info == null )
+                    {
+                        throw new InternalError( "No qName info found for qName [" + qName + "]." );
+                    }
+                    tableIndex
+                        = this.traversePropertyPath( ref, 0, tableIndex + 1, vendor, builder
+                        .getFrom()
+                        .getTableReferences().iterator().next(), JoinType.LEFT_OUTER );
+                    Class<?> declaringType = ( (Member) ref.accessor() ).getDeclaringClass();
+                    String colName;
+                    Integer tableIdx;
+                    if( HasIdentity.class.equals( declaringType ) )
+                    {
+                        colName = DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME;
+                        tableIdx = tableIndex - 1;
+                    }
+                    else
+                    {
+                        colName = DBNames.QNAME_TABLE_VALUE_COLUMN_NAME;
+                        tableIdx = tableIndex;
+                    }
+                    Ordering ordering = Ordering.ASCENDING;
+                    if( orderBy.get( idx ).order() == Order.DESCENDING )
+                    {
+                        ordering = Ordering.DESCENDING;
+                    }
+                    builder.getOrderBy().addSortSpecs(
+                        q.sortSpec( c.colName( TABLE_NAME_PREFIX + tableIdx, colName ), ordering ) );
+                }
+            }
+        }
+    }
+
+    protected Integer traversePropertyPath( PropertyFunction<?> reference, Integer lastTableIndex,
+                                            Integer nextAvailableIndex, SQLVendor vendor, TableReferenceBuilder builder,
+                                            JoinType joinStyle
+    )
+    {
+
+        Stack<QualifiedName> qNameStack = new Stack<>();
+        Stack<PropertyFunction<?>> refStack = new Stack<>();
+
+        while( reference != null )
+        {
+            qNameStack.add( QualifiedName.fromAccessor( reference.accessor() ) );
+            refStack.add( reference );
+            if( reference.traversedProperty() == null
+                && ( reference.traversedAssociation() != null
+                     || reference.traversedManyAssociation() != null ) )
+            {
+                Integer lastAssoTableIndex = this.traverseAssociationPath(
+                    new TraversedAssoOrManyAssoRef( reference ),
+                    lastTableIndex, nextAvailableIndex, vendor, builder, joinStyle, true );
+                if( lastAssoTableIndex > lastTableIndex )
+                {
+                    lastTableIndex = lastAssoTableIndex;
+                    nextAvailableIndex = lastTableIndex + 1;
+                }
+            }
+
+            reference = reference.traversedProperty();
+        }
+
+        PropertyFunction<?> prevRef = null;
+        String schemaName = this._state.schemaName().get();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+        BooleanFactory b = vendor.getBooleanFactory();
+        ColumnsFactory c = vendor.getColumnsFactory();
+
+        while( !qNameStack.isEmpty() )
+        {
+            QualifiedName qName = qNameStack.pop();
+            PropertyFunction<?> ref = refStack.pop();
+            if( !qName.type().equals( HasIdentity.class.getName() ) )
+            {
+                QNameInfo info = this._state.qNameInfos().get().get( qName );
+                if( info == null )
+                {
+                    throw new InternalError( "No qName info found for qName [" + qName + "]." );
+                }
+
+                String prevTableAlias = TABLE_NAME_PREFIX + lastTableIndex;
+                String nextTableAlias = TABLE_NAME_PREFIX + nextAvailableIndex;
+                TableReferenceByName nextTable = t.table( t.tableName( schemaName, info.getTableName() ),
+                                                          t.tableAlias( nextTableAlias ) );
+                // @formatter:off
+                if( prevRef == null )
+                {
+                    builder.addQualifiedJoin(
+                        joinStyle,
+                        nextTable,
+                        t.jc(
+                            b.booleanBuilder(
+                                b.eq(
+                                    c.colName( prevTableAlias, DBNames.ENTITY_TABLE_PK_COLUMN_NAME ),
+                                    c.colName( nextTableAlias, DBNames.ENTITY_TABLE_PK_COLUMN_NAME )
+                                )
+                            )
+                                .and(
+                                    b.isNull( c.colName( nextTableAlias, DBNames.QNAME_TABLE_PARENT_QNAME_COLUMN_NAME ) )
+                                )
+                                .createExpression()
+                        )
+                    );
+                }
+                else
+                {
+                    builder.addQualifiedJoin(
+                        joinStyle,
+                        nextTable,
+                        t.jc(
+                            b.booleanBuilder(
+                                b.eq(
+                                    c.colName( prevTableAlias, DBNames.ALL_QNAMES_TABLE_PK_COLUMN_NAME ),
+                                    c.colName( nextTableAlias, DBNames.QNAME_TABLE_PARENT_QNAME_COLUMN_NAME ) )
+                            )
+                                .and(
+                                    b.eq(
+                                        c.colName( prevTableAlias, DBNames.ENTITY_TABLE_PK_COLUMN_NAME ),
+                                        c.colName( nextTableAlias, DBNames.ENTITY_TABLE_PK_COLUMN_NAME )
+                                    )
+                                )
+                                .createExpression()
+                        )
+                    );
+                }
+                // @formatter:on
+                lastTableIndex = nextAvailableIndex;
+                ++nextAvailableIndex;
+                prevRef = ref;
+            }
+        }
+
+        return lastTableIndex;
+    }
+
+    protected Integer traverseAssociationPath( TraversedAssoOrManyAssoRef reference,
+                                               Integer lastTableIndex,
+                                               Integer nextAvailableIndex,
+                                               SQLVendor vendor,
+                                               TableReferenceBuilder builder,
+                                               JoinType joinStyle,
+                                               Boolean includeLastTable
+    )
+    {
+        Stack<QualifiedName> qNameStack = new Stack<>();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+        BooleanFactory b = vendor.getBooleanFactory();
+        ColumnsFactory c = vendor.getColumnsFactory();
+        String schemaName = this._state.schemaName().get();
+
+        while( reference._hasRefs )
+        {
+            qNameStack.add( QualifiedName.fromAccessor( reference.getAccessor() ) );
+            reference = reference.getTraversedAssociation();
+        }
+        while( !qNameStack.isEmpty() )
+        {
+            QualifiedName qName = qNameStack.pop();
+            QNameInfo info = this._state.qNameInfos().get().get( qName );
+            if( info == null )
+            {
+                throw new InternalError( "No qName info found for qName [" + qName + "]." );
+            }
+            // @formatter:off
+            builder.addQualifiedJoin(
+                joinStyle,
+                t.table( t.tableName( schemaName, info.getTableName() ), t.tableAlias( TABLE_NAME_PREFIX
+                                                                                       + nextAvailableIndex ) ),
+                t.jc(
+                    b.eq(
+                        c.colName( TABLE_NAME_PREFIX + lastTableIndex, DBNames.ENTITY_TABLE_PK_COLUMN_NAME ),
+                        c.colName( TABLE_NAME_PREFIX + nextAvailableIndex, DBNames.ENTITY_TABLE_PK_COLUMN_NAME ) )
+                ) );
+            lastTableIndex = nextAvailableIndex;
+            ++nextAvailableIndex;
+            if( includeLastTable || !qNameStack.isEmpty() )
+            {
+                builder.addQualifiedJoin(
+                    joinStyle,
+                    t.table( t.tableName( schemaName, DBNames.ENTITY_TABLE_NAME ), t.tableAlias( TABLE_NAME_PREFIX + nextAvailableIndex ) ),
+                    t.jc(
+                        b.eq(
+                            c.colName( TABLE_NAME_PREFIX + lastTableIndex, DBNames.QNAME_TABLE_VALUE_COLUMN_NAME ),
+                            c.colName( TABLE_NAME_PREFIX + nextAvailableIndex, DBNames.ENTITY_TABLE_PK_COLUMN_NAME )
+                        )
+                    )
+                );
+                lastTableIndex = nextAvailableIndex;
+                ++nextAvailableIndex;
+            }
+            // @formatter:on
+        }
+
+        return lastTableIndex;
+    }
+
+    protected List<Integer> getEntityTypeIDs( Class<?> entityType )
+    {
+        List<Integer> result = new ArrayList<>();
+        for( Map.Entry<String, Integer> entry : this._state.entityTypePKs().get().entrySet() )
+        {
+            Class<?> clazz = null;
+            try
+            {
+                clazz = Class.forName( entry.getKey() );
+            }
+            catch( Throwable t )
+            {
+                // Ignore
+            }
+            if( clazz != null && entityType.isAssignableFrom( clazz ) )
+            {
+                result.add( entry.getValue() );
+            }
+        }
+
+        return result;
+    }
+
+    // TODO refactor this monster of a method to something more understandable
+    protected Integer modifyFromClauseAndWhereClauseToGetValue(
+        final QualifiedName qName,
+        Object value,
+        final Predicate<Composite> predicate, final Boolean negationActive,
+        final Integer currentTableIndex,
+        final ModifiableInt maxTableIndex, final String columnName,
+        final String collectionPath,
+        final SQLVendor vendor, final BooleanBuilder whereClause,
+        final BooleanBuilder afterWhere,
+        final TableReferenceBuilder fromClause, final GroupByBuilder groupBy,
+        final BooleanBuilder having,
+        final List<QNameJoin> qNameJoins, Map<String, Object> variables,
+        final List<Object> values, final List<Integer> valueSQLTypes
+    )
+    {
+        if( value instanceof Variable )
+        {
+            value = variables.get( ( (Variable) value ).variableName() );
+        }
+
+        final String schemaName = this._state.schemaName().get();
+        Integer result = 1;
+
+        final BooleanFactory b = vendor.getBooleanFactory();
+        final LiteralFactory l = vendor.getLiteralFactory();
+        final ColumnsFactory c = vendor.getColumnsFactory();
+        final QueryFactory q = vendor.getQueryFactory();
+        final TableReferenceFactory t = vendor.getTableReferenceFactory();
+
+        if( value instanceof Collection<?> )
+        {
+            // Collection
+            Integer collectionIndex = 0;
+            Boolean collectionIsSet = value instanceof Set<?>;
+            Boolean topLevel = collectionPath.equals( DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME );
+            String collTable = TABLE_NAME_PREFIX + currentTableIndex;
+            String collCol = DBNames.QNAME_TABLE_COLLECTION_PATH_COLUMN_NAME;
+            ColumnReferenceByName collColExp = c.colName( collTable, collCol );
+
+            BooleanBuilder collectionCondition = b.booleanBuilder();
+
+            if( topLevel && negationActive )
+            {
+                afterWhere
+                    .and( b
+                              .booleanBuilder(
+                                  b.neq( collColExp,
+                                         l.s( DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME ) ) )
+                              .or( b.isNull( collColExp ) ).createExpression() );
+            }
+
+            Integer totalItemsProcessed = 0;
+            for( Object item : (Collection<?>) value )
+            {
+                String path = collectionPath + DBNames.QNAME_TABLE_COLLECTION_PATH_SEPARATOR
+                              + ( collectionIsSet ? "*{1,}" : collectionIndex );
+                Boolean isCollection = ( item instanceof Collection<?> );
+                BooleanBuilder newWhere = b.booleanBuilder();
+                if( !isCollection )
+                {
+                    newWhere.reset( b.regexp( collColExp, l.s( path ) ) );
+                }
+                totalItemsProcessed
+                    = totalItemsProcessed
+                      + modifyFromClauseAndWhereClauseToGetValue( qName, item, predicate,
+                                                                  negationActive,
+                                                                  currentTableIndex, maxTableIndex, columnName, path, vendor,
+                                                                  newWhere, afterWhere, fromClause,
+                                                                  groupBy, having, qNameJoins, variables, values, valueSQLTypes );
+
+                ++collectionIndex;
+                collectionCondition.or( newWhere.createExpression() );
+            }
+            result = totalItemsProcessed;
+
+            if( topLevel )
+            {
+                if( totalItemsProcessed == 0 )
+                {
+                    collectionCondition.and( b.isNotNull( collColExp ) )
+                        .and(
+                            b.eq( collColExp,
+                                  l.l( DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME ) ) );
+                }
+                else if( !negationActive )
+                {
+                    groupBy.addGroupingElements( q.groupingElement( c.colName( TABLE_NAME_PREFIX
+                                                                               + currentTableIndex,
+                                                                               DBNames.ENTITY_TABLE_PK_COLUMN_NAME ) ) );
+                    having
+                        .and( b.eq(
+                            l.func( SQLFunctions.COUNT,
+                                    c.colName( TABLE_NAME_PREFIX + currentTableIndex,
+                                               DBNames.QNAME_TABLE_VALUE_COLUMN_NAME ) ),
+                            l.n( totalItemsProcessed ) ) );
+                }
+            }
+
+            whereClause.and( collectionCondition.createExpression() );
+        }
+        else if( value instanceof ValueComposite )
+        {
+            // Visit all properties with recursion and make joins as necessary
+            // @formatter:off
+            PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF.apply( (ValueComposite) value )
+                .state().properties()
+                .forEach( property -> {
+                    Boolean qNameJoinDone = false;
+                    Integer sourceIndex = maxTableIndex.getInt();
+                    Integer targetIndex = sourceIndex + 1;
+                    for( QNameJoin join : qNameJoins )
+                    {
+                        if( join.getSourceQName().equals( qName ) )
+                        {
+                            sourceIndex = join.getSourceTableIndex();
+                            if( join.getTargetQName().equals( spi.propertyDescriptorFor( property ).qualifiedName() ) )
+                            {
+                                // This join has already been done once
+                                qNameJoinDone = true;
+                                targetIndex = join.getTargetTableIndex();
+                                break;
+                            }
+                        }
+                    }
+
+                    if( !qNameJoinDone )
+                    {
+                        // @formatter:off
+                        QNameInfo info = _state.qNameInfos()
+                            .get()
+                            .get( spi.propertyDescriptorFor( property ).qualifiedName() );
+                        String prevTableName = TABLE_NAME_PREFIX + sourceIndex;
+                        String nextTableName = TABLE_NAME_PREFIX + targetIndex;
+                        fromClause.addQualifiedJoin(
+                            JoinType.LEFT_OUTER,
+                            t.table( t.tableName( schemaName, info.getTableName() ), t.tableAlias( TABLE_NAME_PREFIX + targetIndex ) ),
+                            t.jc(
+                                b.booleanBuilder( b.eq(
+                                    c.colName( prevTableName, DBNames.ALL_QNAMES_TABLE_PK_COLUMN_NAME ),
+                                    c.colName( nextTableName, DBNames.QNAME_TABLE_PARENT_QNAME_COLUMN_NAME )
+                                ) )
+                                    .and( b.eq(
+                                        c.colName( prevTableName, DBNames.ENTITY_TABLE_PK_COLUMN_NAME ),
+                                        c.colName( nextTableName, DBNames.ENTITY_TABLE_PK_COLUMN_NAME )
+                                    ) ).createExpression()
+                            )
+                        );
+                        // @formatter:on
+
+                        qNameJoins.add( new QNameJoin( qName, spi.propertyDescriptorFor( property )
+                            .qualifiedName(), sourceIndex, targetIndex ) );
+                        maxTableIndex.setInt( maxTableIndex.getInt() + 1 );
+                    }
+                    modifyFromClauseAndWhereClauseToGetValue( spi.propertyDescriptorFor( property )
+                                                                  .qualifiedName(), property.get(), predicate, negationActive,
+                                                              targetIndex, maxTableIndex, columnName, collectionPath, vendor, whereClause,
+                                                              afterWhere,
+                                                              fromClause, groupBy, having, qNameJoins, variables, values, valueSQLTypes );
+                } );
+
+            // @formatter:on
+        }
+        else
+        {
+            // Primitive
+            ColumnReferenceByName valueCol = c.colName( TABLE_NAME_PREFIX + currentTableIndex, columnName );
+            if( value == null )
+            {
+                whereClause.and( b.isNull( valueCol ) );
+            }
+            else
+            {
+                Object dbValue = value;
+                if( Enum.class.isAssignableFrom( value.getClass() ) )
+                {
+                    dbValue = this._state.enumPKs().get().get( value.getClass().getName() );
+                }
+                whereClause.and( b.and( b.isNotNull( valueCol ),
+                                        this.getOperator( predicate ).getExpression( b, valueCol, l.param() ) ) );
+                values.add( dbValue );
+                valueSQLTypes.add( _typeHelper.getSQLType( value ) );
+                LOGGER.info( TABLE_NAME_PREFIX + currentTableIndex + "." + columnName + " is " + dbValue );
+            }
+        }
+
+        return result;
+    }
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/AbstractSQLStartup.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/AbstractSQLStartup.java
new file mode 100644
index 0000000..e2d2cc6
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/AbstractSQLStartup.java
@@ -0,0 +1,1736 @@
+/*
+ *  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.polygene.index.sql.support.skeletons;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.Period;
+import java.time.ZonedDateTime;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import javax.sql.DataSource;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitorAdapter;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.index.reindexer.Reindexer;
+import org.apache.polygene.index.sql.support.api.SQLAppStartup;
+import org.apache.polygene.index.sql.support.api.SQLTypeInfo;
+import org.apache.polygene.index.sql.support.common.DBNames;
+import org.apache.polygene.index.sql.support.common.QNameInfo;
+import org.apache.polygene.index.sql.support.common.QNameInfo.QNameType;
+import org.apache.polygene.index.sql.support.common.RebuildingStrategy;
+import org.apache.polygene.index.sql.support.common.ReindexingStrategy;
+import org.apache.polygene.library.sql.common.SQLConfiguration;
+import org.apache.polygene.library.sql.common.SQLUtil;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.TableElementListBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDataType;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.AutoGenerationPolicy;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ConstraintCharacteristics;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ReferentialAction;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.UniqueSpecification;
+import org.apache.polygene.library.sql.generator.grammar.factories.DataTypeFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.DefinitionFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.LiteralFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.ModificationFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.QueryFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.TableReferenceFactory;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropBehaviour;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.ObjectType;
+import org.apache.polygene.library.sql.generator.grammar.modification.DeleteBySearch;
+import org.apache.polygene.library.sql.generator.grammar.modification.InsertStatement;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.polygene.index.sql.support.common.DBNames.ALL_QNAMES_TABLE_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.ALL_QNAMES_TABLE_PK_COLUMN_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.APP_VERSION_PK_COLUMN_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.APP_VERSION_TABLE_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.ENTITY_TABLE_APPLICATION_VERSION_COLUMN_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.ENTITY_TABLE_MODIFIED_COLUMN_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.ENTITY_TABLE_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.ENTITY_TABLE_PK_COLUMN_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.ENTITY_TABLE_VERSION_COLUMN_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.ENTITY_TYPES_JOIN_TABLE_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.ENTITY_TYPES_TABLE_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.ENTITY_TYPES_TABLE_PK_COLUMN_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.ENTITY_TYPES_TABLE_TYPE_NAME_COLUMN_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.ENUM_LOOKUP_TABLE_ENUM_VALUE_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.ENUM_LOOKUP_TABLE_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.ENUM_LOOKUP_TABLE_PK_COLUMN_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.QNAME_TABLE_ASSOCIATION_INDEX_COLUMN_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.QNAME_TABLE_COLLECTION_PATH_COLUMN_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.QNAME_TABLE_NAME_PREFIX;
+import static org.apache.polygene.index.sql.support.common.DBNames.QNAME_TABLE_PARENT_QNAME_COLUMN_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.QNAME_TABLE_VALUE_COLUMN_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.USED_CLASSES_TABLE_CLASS_NAME_COLUMN_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.USED_CLASSES_TABLE_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.USED_CLASSES_TABLE_PK_COLUMN_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.USED_QNAMES_TABLE_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.USED_QNAMES_TABLE_QNAME_COLUMN_NAME;
+import static org.apache.polygene.index.sql.support.common.DBNames.USED_QNAMES_TABLE_TABLE_NAME_COLUMN_NAME;
+
+public abstract class AbstractSQLStartup
+    implements SQLAppStartup
+{
+    private interface SQLTypeCustomizer
+    {
+        SQLDataType customizeType( Type propertyType, SQLTypeInfo sqlTypeInfo );
+    }
+
+    private static final Class<?> ENTITY_PK_TYPE = Long.class;
+    private static final Class<?> ENTITY_TYPE_PK_TYPE = Integer.class;
+
+    private static final Logger LOGGER = LoggerFactory.getLogger( AbstractSQLStartup.class.getName() );
+
+    static final ThreadLocal<Connection> CONNECTION_FOR_REINDEXING = new ThreadLocal<Connection>()
+    {
+        @Override
+        protected Connection initialValue()
+        {
+            return null;
+        }
+    };
+
+    @This
+    private SQLDBState _state;
+
+    @This
+    private Configuration<SQLConfiguration> _configuration;
+
+    @Service
+    @Optional
+    private ReindexingStrategy _reindexingStrategy;
+
+    @Service
+    @Optional
+    private RebuildingStrategy _rebuildingStrategy;
+
+    @Service
+    private DataSource _dataSource;
+
+    @Service
+    private Reindexer _reindexer;
+
+    @Structure
+    private Application _app;
+
+    private final SQLVendor _vendor;
+
+    private Map<Class<?>, SQLTypeCustomizer> _customizableTypes;
+
+    private Map<Class<?>, SQLDataType> _primitiveTypes;
+
+    public AbstractSQLStartup( @Uses ServiceDescriptor descriptor )
+    {
+        this._vendor = descriptor.metaInfo( SQLVendor.class );
+    }
+
+    @Override
+    public void initConnection()
+        throws SQLException
+    {
+        this._configuration.refresh();
+
+        this.initTypes();
+        this.modifyPrimitiveTypes( this._primitiveTypes, this._state.javaTypes2SQLTypes().get() );
+
+        String schemaName = this._configuration.get().schemaName().get().toLowerCase();
+        this.checkSchemaName( schemaName );
+        LOGGER.debug( "Will use '{}' as schema name", schemaName );
+
+        this._state.schemaName().set( schemaName );
+        this._state.entityTypePKs().set( new HashMap<>() );
+        this._state.usedClassesPKs().set( new HashMap<>() );
+        this._state.entityUsedQNames().set( new HashMap<>() );
+        this._state.qNameInfos().set( new HashMap<>() );
+        this._state.enumPKs().set( new HashMap<>() );
+
+        Connection connection = this._dataSource.getConnection();
+        try
+        {
+            connection.setAutoCommit( true );
+            connection.setReadOnly( false );
+            this.syncDB( connection );
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( connection );
+        }
+
+        if( LOGGER.isDebugEnabled() )
+        {
+
+            String newline = "\n";
+            String tab = "\t";
+            String colonspace = ": ";
+            StringBuilder report = new StringBuilder();
+
+            report.append( "schemaName: " ).append( _state.schemaName().get() ).append( newline );
+
+            report.append( "qNameInfos: " ).append( newline );
+            for( Map.Entry<QualifiedName, QNameInfo> entry : _state.qNameInfos().get().entrySet() )
+            {
+                report.append( tab ).append( entry.getKey() ).append( colonspace )
+                      .append( entry.getValue() ).append( newline );
+            }
+
+            report.append( "entityUsedQNames:" ).append( newline );
+            for( Map.Entry<EntityDescriptor, Set<QualifiedName>> entry : _state.entityUsedQNames()
+                                                                               .get()
+                                                                               .entrySet() )
+            {
+                report.append( tab ).append( entry.getKey() ).append( colonspace )
+                      .append( entry.getValue() ).append( newline );
+            }
+
+            report.append( "usedClassesPKs:" ).append( newline );
+            for( Map.Entry<CompositeDescriptor, Integer> entry : _state.usedClassesPKs().get()
+                                                                       .entrySet() )
+            {
+                report.append( tab ).append( entry.getKey() ).append( colonspace )
+                      .append( entry.getValue() ).append( newline );
+            }
+
+            report.append( "javaTypes2SQLTypes:" ).append( newline );
+            for( Map.Entry<Class<?>, Integer> entry : _state.javaTypes2SQLTypes().get().entrySet() )
+            {
+                report.append( tab ).append( entry.getKey() ).append( colonspace )
+                      .append( entry.getValue() ).append( newline );
+            }
+
+            report.append( "entityTypePKs:" ).append( newline );
+            for( Map.Entry<String, Integer> entry : _state.entityTypePKs().get().entrySet() )
+            {
+                report.append( tab ).append( entry.getKey() ).append( colonspace )
+                      .append( entry.getValue() ).append( newline );
+            }
+
+            report.append( "enumPKs:" ).append( newline );
+            for( Map.Entry<String, Integer> entry : _state.enumPKs().get().entrySet() )
+            {
+                report.append( tab ).append( entry.getKey() ).append( colonspace )
+                      .append( entry.getValue() ).append( newline );
+            }
+
+            LOGGER.debug( "SQLDBState after initConnection:\n{}", report.toString() );
+        }
+    }
+
+    private void initTypes()
+    {
+
+        DataTypeFactory dt = this._vendor.getDataTypeFactory();
+
+        this._primitiveTypes = new HashMap<>();
+        this._primitiveTypes.put( Boolean.class, dt.sqlBoolean() );
+        this._primitiveTypes.put( Byte.class, dt.smallInt() );
+        this._primitiveTypes.put( Short.class, dt.smallInt() );
+        this._primitiveTypes.put( Integer.class, dt.integer() );
+        this._primitiveTypes.put( Long.class, dt.bigInt() );
+        this._primitiveTypes.put( Float.class, dt.real() );
+        this._primitiveTypes.put( Double.class, dt.doublePrecision() );
+        this._primitiveTypes.put( LocalDate.class, dt.timeStamp( false ) );
+        this._primitiveTypes.put( LocalTime.class, dt.timeStamp( false ) );
+        this._primitiveTypes.put( LocalDateTime.class, dt.timeStamp( false ) );
+        this._primitiveTypes.put( ZonedDateTime.class, dt.timeStamp( true ) );
+        this._primitiveTypes.put( OffsetDateTime.class, dt.timeStamp( true ) );
+        this._primitiveTypes.put( Instant.class, dt.timeStamp( true ) );
+        this._primitiveTypes.put( Character.class, dt.integer() );
+        this._primitiveTypes.put( String.class, dt.sqlVarChar( 5000 ) );
+        this._primitiveTypes.put( BigInteger.class, dt.decimal() );
+        this._primitiveTypes.put( BigDecimal.class, dt.decimal() );
+
+        Map<Class<?>, Integer> jdbcTypes = new HashMap<>();
+        jdbcTypes.put( Boolean.class, Types.BOOLEAN );
+        jdbcTypes.put( Byte.class, Types.SMALLINT );
+        jdbcTypes.put( Short.class, Types.SMALLINT );
+        jdbcTypes.put( Integer.class, Types.INTEGER );
+        jdbcTypes.put( Long.class, Types.BIGINT );
+        jdbcTypes.put( Float.class, Types.REAL );
+        jdbcTypes.put( Double.class, Types.DOUBLE );
+        jdbcTypes.put( Instant.class, Types.TIMESTAMP );
+        jdbcTypes.put( LocalDate.class, Types.DATE );
+        jdbcTypes.put( LocalTime.class, Types.TIME );
+        jdbcTypes.put( ZonedDateTime.class, Types.TIMESTAMP_WITH_TIMEZONE );
+        jdbcTypes.put( OffsetDateTime.class, Types.TIMESTAMP_WITH_TIMEZONE );
+        jdbcTypes.put( Duration.class, Types.VARCHAR );
+        jdbcTypes.put( Period.class, Types.VARCHAR );
+        jdbcTypes.put( Character.class, Types.INTEGER );
+        jdbcTypes.put( String.class, Types.VARCHAR );
+        jdbcTypes.put( BigInteger.class, Types.NUMERIC );
+        jdbcTypes.put( BigDecimal.class, Types.NUMERIC );
+        this._state.javaTypes2SQLTypes().set( jdbcTypes );
+
+        this._customizableTypes = new HashMap<>();
+        this._customizableTypes.put(
+            String.class,
+            ( propertyType, sqlTypeInfo ) -> _vendor.getDataTypeFactory().sqlVarChar( sqlTypeInfo.maxLength() )
+                                   );
+        this._customizableTypes.put(
+            BigInteger.class,
+            ( propertyType, sqlTypeInfo ) -> _vendor.getDataTypeFactory().decimal( sqlTypeInfo.maxLength() )
+                                   );
+        this._customizableTypes.put(
+            BigDecimal.class,
+            ( propertyType, sqlTypeInfo ) -> _vendor.getDataTypeFactory().decimal( sqlTypeInfo.maxLength() )
+                                   );
+    }
+
+    protected void checkSchemaName( String schemaName )
+    {
+        // By default, we accept alphanumeric strings with underscores in them
+        if( !Pattern.matches( "^\\p{L}(_|\\p{L}|\\p{N})*$", schemaName ) )
+        {
+            throw new IllegalStateException( "Illegal schema name: " + schemaName + "." );
+        }
+    }
+
+    private static class ApplicationInfo
+    {
+
+        private final Map<String, EntityDescriptor> entityDescriptors = new HashMap<>();
+
+        private final Set<CompositeDescriptorInfo> usedValueComposites = new HashSet<>();
+
+        private final Set<String> enumValues = new HashSet<>();
+    }
+
+    private static class CompositeDescriptorInfo
+    {
+        final LayerDescriptor layer;
+        final ModuleDescriptor module;
+        final CompositeDescriptor composite;
+
+        private CompositeDescriptorInfo( LayerDescriptor theLayer, ModuleDescriptor theModule,
+                                         CompositeDescriptor theComposite )
+        {
+            this.layer = theLayer;
+            this.module = theModule;
+            this.composite = theComposite;
+        }
+
+        @Override
+        public boolean equals( Object obj )
+        {
+            return this == obj
+                   || ( obj instanceof CompositeDescriptorInfo && this.composite
+                .equals( ( (CompositeDescriptorInfo) obj ).composite ) );
+        }
+
+        @Override
+        public int hashCode()
+        {
+            return this.composite.hashCode();
+        }
+    }
+
+    private void syncDB( Connection connection )
+        throws SQLException
+    {
+        String schemaName = this._state.schemaName().get();
+        String appVersion = this._app.version();
+        String dbAppVersion = this.readAppVersionFromDB( connection, schemaName );
+
+        // Rebuild if needed
+        boolean rebuildingNeeded = dbAppVersion == null;
+
+        if( !rebuildingNeeded && this._rebuildingStrategy != null )
+        {
+            rebuildingNeeded = this._rebuildingStrategy.rebuildingRequired( dbAppVersion, appVersion );
+        }
+
+        ApplicationInfo appInfo = this.constructApplicationInfo( !rebuildingNeeded );
+
+        if( rebuildingNeeded )
+        {
+            LOGGER.debug( "(Re)building schema " + schemaName );
+            this.destroyNeededSchemaTables( connection, schemaName, this._state.qNameInfos().get().size() );
+
+            Map<String, Long> tablePKs = new HashMap<>();
+            this.createSchemaAndRequiredTables( connection, schemaName, tablePKs );
+            this.writeAppMetadataToDB( connection, appInfo, tablePKs );
+        }
+        else
+        {
+            this.testRequiredCapabilities( connection );
+            this.readAppMetadataFromDB( connection );
+            LOGGER.debug( "Application metadata loaded from database" );
+        }
+
+        boolean reindexingNeeded = dbAppVersion == null;
+        if( !reindexingNeeded && this._reindexingStrategy != null )
+        {
+            reindexingNeeded = this._reindexingStrategy.reindexingNeeded( dbAppVersion, appVersion );
+        }
+
+        if( reindexingNeeded )
+        {
+            LOGGER.debug( "(Re)indexing entitystore, using schema " + schemaName );
+            this.performReindex( connection );
+        }
+    }
+
+    private void createSchemaAndRequiredTables( Connection connection, String schemaName,
+                                                Map<String, Long> tablePKs )
+        throws SQLException
+    {
+        boolean schemaFound = false;
+
+        ResultSet rs = connection.getMetaData().getSchemas();
+        try
+        {
+            while( rs.next() && !schemaFound )
+            {
+                schemaFound = rs.getString( 1 ).equals( schemaName );
+            }
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( rs );
+        }
+
+        SQLVendor vendor = this._vendor;
+        DefinitionFactory d = vendor.getDefinitionFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+
+        Statement stmt = connection.createStatement();
+
+        // @formatter:off
+        try
+        {
+            if( !schemaFound )
+            {
+                stmt.execute(
+                    vendor.toString(
+                        d
+                            .createSchemaDefinitionBuilder()
+                            .setSchemaName( schemaName )
+                            .createExpression()
+                                   )
+                            );
+                LOGGER.debug( "Database schema created" );
+            }
+
+            this.testRequiredCapabilities( connection );
+            LOGGER.debug( "Underlying database fullfill required capabilities" );
+
+            stmt.execute(
+                vendor.toString(
+                    d.createTableDefinitionBuilder()
+                     .setTableName( t.tableName( schemaName, USED_CLASSES_TABLE_NAME ) )
+                     .setTableContentsSource(
+                         d.createTableElementListBuilder()
+                          .addTableElement( d.createColumnDefinition( USED_CLASSES_TABLE_PK_COLUMN_NAME, this._primitiveTypes
+                              .get( Integer.class ), false ) )
+                          .addTableElement( d.createColumnDefinition( USED_CLASSES_TABLE_CLASS_NAME_COLUMN_NAME, this._primitiveTypes
+                              .get( String.class ), false ) )
+                          .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
+                                                                                .setUniqueness( UniqueSpecification.PRIMARY_KEY )
+                                                                                .addColumns( USED_CLASSES_TABLE_PK_COLUMN_NAME )
+                                                                                .createExpression()
+                                                                             ) )
+                          .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
+                                                                                .setUniqueness( UniqueSpecification.UNIQUE )
+                                                                                .addColumns( USED_CLASSES_TABLE_CLASS_NAME_COLUMN_NAME )
+                                                                                .createExpression()
+                                                                             ) )
+                          .createExpression()
+                                            )
+                     .createExpression()
+                               )
+                        );
+
+            tablePKs.put( USED_CLASSES_TABLE_NAME, 0L );
+
+            stmt.execute(
+                vendor.toString(
+                    d.createTableDefinitionBuilder()
+                     .setTableName( t.tableName( schemaName, ENTITY_TYPES_TABLE_NAME ) )
+                     .setTableContentsSource(
+                         d.createTableElementListBuilder()
+                          .addTableElement( d.createColumnDefinition( ENTITY_TYPES_TABLE_PK_COLUMN_NAME, this._primitiveTypes
+                              .get( ENTITY_TYPE_PK_TYPE ), false ) )
+                          .addTableElement( d.createColumnDefinition( ENTITY_TYPES_TABLE_TYPE_NAME_COLUMN_NAME, this._primitiveTypes
+                              .get( String.class ), false ) )
+                          .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
+                                                                                .setUniqueness( UniqueSpecification.PRIMARY_KEY )
+                                                                                .addColumns( ENTITY_TYPES_TABLE_PK_COLUMN_NAME )
+                                                                                .createExpression()
+                                                                             ) )
+                          .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
+                                                                                .setUniqueness( UniqueSpecification.UNIQUE )
+                                                                                .addColumns( ENTITY_TYPES_TABLE_TYPE_NAME_COLUMN_NAME )
+                                                                                .createExpression()
+                                                                             ) )
+                          .createExpression()
+                                            )
+                     .createExpression()
+                               )
+                        );
+
+            tablePKs.put( ENTITY_TYPES_TABLE_NAME, 0L );
+
+            stmt.execute(
+                vendor.toString(
+                    d.createTableDefinitionBuilder()
+                     .setTableName( t.tableName( schemaName, ENTITY_TABLE_NAME ) )
+                     .setTableContentsSource(
+                         d.createTableElementListBuilder()
+                          .addTableElement( d.createColumnDefinition( ENTITY_TABLE_PK_COLUMN_NAME, this._primitiveTypes
+                              .get( ENTITY_PK_TYPE ), false, AutoGenerationPolicy.BY_DEFAULT ) )
+                          .addTableElement( d.createColumnDefinition( ENTITY_TABLE_IDENTITY_COLUMN_NAME, this._primitiveTypes
+                              .get( String.class ), false ) )
+                          .addTableElement( d.createColumnDefinition( ENTITY_TABLE_MODIFIED_COLUMN_NAME, this._primitiveTypes
+                              .get( Instant.class ), false ) )
+                          .addTableElement( d.createColumnDefinition( ENTITY_TABLE_VERSION_COLUMN_NAME, this._primitiveTypes
+                              .get( String.class ), false ) )
+                          .addTableElement( d.createColumnDefinition( ENTITY_TABLE_APPLICATION_VERSION_COLUMN_NAME, this._primitiveTypes
+                              .get( String.class ), false ) )
+                          .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
+                                                                                .setUniqueness( UniqueSpecification.PRIMARY_KEY )
+                                                                                .addColumns( ENTITY_TABLE_PK_COLUMN_NAME )
+                                                                                .createExpression()
+                                                                             ) )
+                          .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
+                                                                                .setUniqueness( UniqueSpecification.UNIQUE )
+                                                                                .addColumns( ENTITY_TABLE_IDENTITY_COLUMN_NAME )
+                                                                                .createExpression()
+                                                                             ) )
+                          .createExpression()
+                                            )
+                     .createExpression()
+                               )
+                        );
+            tablePKs.put( ENTITY_TABLE_NAME, 0L );
+
+            stmt.execute(
+                d.createTableDefinitionBuilder()
+                 .setTableName( t.tableName( schemaName, ENTITY_TYPES_JOIN_TABLE_NAME ) )
+                 .setTableContentsSource(
+                     d.createTableElementListBuilder()
+                      .addTableElement( d.createColumnDefinition( ENTITY_TABLE_PK_COLUMN_NAME, this._primitiveTypes
+                          .get( ENTITY_PK_TYPE ), false ) )
+                      .addTableElement( d.createColumnDefinition( ENTITY_TYPES_TABLE_PK_COLUMN_NAME, this._primitiveTypes
+                          .get( ENTITY_TYPE_PK_TYPE ), false ) )
+                      .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
+                                                                            .setUniqueness( UniqueSpecification.PRIMARY_KEY )
+                                                                            .addColumns( ENTITY_TABLE_PK_COLUMN_NAME, ENTITY_TYPES_TABLE_PK_COLUMN_NAME )
+                                                                            .createExpression()
+                                                                         ) )
+                      .addTableElement( d.createTableConstraintDefinition( d.createForeignKeyConstraintBuilder()
+                                                                            .addSourceColumns( ENTITY_TABLE_PK_COLUMN_NAME )
+                                                                            .setTargetTableName( t.tableName( schemaName, ENTITY_TABLE_NAME ) )
+                                                                            .addTargetColumns( ENTITY_TABLE_PK_COLUMN_NAME )
+                                                                            .setOnDelete( ReferentialAction.CASCADE )
+                                                                            .setOnUpdate( ReferentialAction.CASCADE )
+                                                                            .createExpression(), ConstraintCharacteristics.INITIALLY_DEFERRED_DEFERRABLE
+                                                                         ) )
+                      .addTableElement( d.createTableConstraintDefinition( d.createForeignKeyConstraintBuilder()
+                                                                            .addSourceColumns( ENTITY_TYPES_TABLE_PK_COLUMN_NAME )
+                                                                            .setTargetTableName( t.tableName( schemaName, ENTITY_TYPES_TABLE_NAME ) )
+                                                                            .addTargetColumns( ENTITY_TYPES_TABLE_PK_COLUMN_NAME )
+                                                                            .setOnDelete( ReferentialAction.RESTRICT )
+                                                                            .setOnDelete( ReferentialAction.CASCADE )
+                                                                            .createExpression(), ConstraintCharacteristics.NOT_DEFERRABLE ) )
+                      .createExpression()
+                                        ).createExpression()
+                 .toString()
+                        );
+
+            stmt.execute(
+                vendor.toString(
+                    d.createTableDefinitionBuilder()
+                     .setTableName( t.tableName( schemaName, ENUM_LOOKUP_TABLE_NAME ) )
+                     .setTableContentsSource(
+                         d.createTableElementListBuilder()
+                          .addTableElement( d.createColumnDefinition( ENUM_LOOKUP_TABLE_PK_COLUMN_NAME, this._primitiveTypes
+                              .get( Integer.class ), false ) )
+                          .addTableElement( d.createColumnDefinition( ENUM_LOOKUP_TABLE_ENUM_VALUE_NAME, this._primitiveTypes
+                              .get( String.class ), false ) )
+                          .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
+                                                                                .setUniqueness( UniqueSpecification.PRIMARY_KEY )
+                                                                                .addColumns( ENUM_LOOKUP_TABLE_PK_COLUMN_NAME )
+                                                                                .createExpression()
+                                                                             ) )
+                          .createExpression()
+                                            )
+                     .createExpression()
+                               )
+                        );
+
+            tablePKs.put( ENUM_LOOKUP_TABLE_NAME, 0L );
+
+            stmt.execute(
+                vendor.toString(
+                    d.createTableDefinitionBuilder()
+                     .setTableName( t.tableName( schemaName, USED_QNAMES_TABLE_NAME ) )
+                     .setTableContentsSource(
+                         d.createTableElementListBuilder()
+                          .addTableElement( d.createColumnDefinition( USED_QNAMES_TABLE_QNAME_COLUMN_NAME, this._primitiveTypes
+                              .get( String.class ), false ) )
+                          .addTableElement( d.createColumnDefinition( USED_QNAMES_TABLE_TABLE_NAME_COLUMN_NAME, this._primitiveTypes
+                              .get( String.class ), false ) )
+                          .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
+                                                                                .setUniqueness( UniqueSpecification.PRIMARY_KEY )
+                                                                                .addColumns( USED_QNAMES_TABLE_QNAME_COLUMN_NAME, USED_QNAMES_TABLE_TABLE_NAME_COLUMN_NAME )
+                                                                                .createExpression()
+                                                                             ) )
+                          .createExpression()
+                                            )
+                     .createExpression()
+                               )
+                        );
+
+            stmt.execute(
+                vendor.toString(
+                    d.createTableDefinitionBuilder()
+                     .setTableName( t.tableName( schemaName, ALL_QNAMES_TABLE_NAME ) )
+                     .setTableContentsSource(
+                         d.createTableElementListBuilder()
+                          .addTableElement( d.createColumnDefinition( ALL_QNAMES_TABLE_PK_COLUMN_NAME, this._primitiveTypes
+                              .get( Integer.class ), false ) )
+                          .addTableElement( d.createColumnDefinition( ENTITY_TABLE_PK_COLUMN_NAME, this._primitiveTypes
+                              .get( ENTITY_PK_TYPE ), false ) )
+                          .addTableElement( d.createTableConstraintDefinition(
+                              d.createUniqueConstraintBuilder()
+                               .setUniqueness( UniqueSpecification.PRIMARY_KEY )
+                               .addColumns( ALL_QNAMES_TABLE_PK_COLUMN_NAME, ENTITY_TABLE_PK_COLUMN_NAME )
+                               .createExpression()
+                                                                             ) )
+                          .addTableElement( d.createTableConstraintDefinition(
+                              d.createForeignKeyConstraintBuilder()
+                               .addSourceColumns( ENTITY_TABLE_PK_COLUMN_NAME )
+                               .setTargetTableName( t.tableName( schemaName, ENTITY_TABLE_NAME ) )
+                               .addTargetColumns( ENTITY_TABLE_PK_COLUMN_NAME )
+                               .setOnUpdate( ReferentialAction.CASCADE )
+                               .setOnDelete( ReferentialAction.CASCADE )
+                               .createExpression(), ConstraintCharacteristics.INITIALLY_DEFERRED_DEFERRABLE
+                                                                             ) )
+                          .createExpression()
+                                            )
+                     .createExpression()
+                               )
+                        );
+
+            tablePKs.put( ALL_QNAMES_TABLE_NAME, 0L );
+
+            stmt.execute(
+                vendor.toString(
+                    d.createTableDefinitionBuilder()
+                     .setTableName( t.tableName( schemaName, APP_VERSION_TABLE_NAME ) )
+                     .setTableContentsSource(
+                         d.createTableElementListBuilder()
+                          .addTableElement( d.createColumnDefinition( APP_VERSION_PK_COLUMN_NAME, this._primitiveTypes
+                              .get( String.class ), false ) )
+                          .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
+                                                                                .setUniqueness( UniqueSpecification.PRIMARY_KEY )
+                                                                                .addColumns( APP_VERSION_PK_COLUMN_NAME )
+                                                                                .createExpression()
+                                                                             ) )
+                          .createExpression()
+                                            )
+                     .createExpression()
+                               )
+                        );
+
+            ModificationFactory m = vendor.getModificationFactory();
+
+            PreparedStatement ps = connection.prepareStatement(
+                vendor.toString(
+                    m.insert()
+                     .setTableName( t.tableName( schemaName, APP_VERSION_TABLE_NAME ) )
+                     .setColumnSource(
+                         m.columnSourceByValues()
+                          .addValues( vendor.getLiteralFactory().param() )
+                          .createExpression()
+                                     )
+                     .createExpression()
+                               )
+                                                              );
+            ps.setString( 1, this._app.version() );
+            ps.execute();
+
+            // TODO INDICES!!!!
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( stmt );
+        }
+
+        // @formatter:on
+        LOGGER.debug( "Indexing SQL database tables created" );
+    }
+
+    private void performReindex( Connection connection )
+        throws SQLException
+    {
+        LOGGER.info( "Performing reindexing..." );
+        // @formatter:off
+        // First delete all entity data
+        DeleteBySearch clearEntityData = this._vendor.getModificationFactory().deleteBySearch()
+                                                     .setTargetTable(
+                                                         this._vendor.getModificationFactory().createTargetTable(
+                                                             this._vendor.getTableReferenceFactory().tableName(
+                                                                 this._state.schemaName().get(),
+                                                                 ENTITY_TABLE_NAME
+                                                                                                              )
+                                                                                                                )
+                                                                    ).createExpression();
+        connection.prepareStatement( this._vendor.toString( clearEntityData ) ).execute();
+        // @formatter:on
+
+        CONNECTION_FOR_REINDEXING.set( connection );
+        try
+        {
+            this._reindexer.reindex();
+        }
+        finally
+        {
+            CONNECTION_FOR_REINDEXING.set( null );
+        }
+
+        LOGGER.info( "Reindexing complete." );
+    }
+
+    private void readAppMetadataFromDB( Connection connection )
+        throws SQLException
+    {
+
+        String schemaName = this._state.schemaName().get();
+        Statement stmt = connection.createStatement();
+
+        SQLVendor vendor = this._vendor;
+        QueryFactory q = vendor.getQueryFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+
+        try
+        {
+            // @formatter:off
+
+            q.simpleQueryBuilder()
+             .select( ENTITY_TYPES_TABLE_PK_COLUMN_NAME, ENTITY_TYPES_TABLE_TYPE_NAME_COLUMN_NAME )
+             .from( t.tableName( schemaName, ENTITY_TYPES_TABLE_NAME ) )
+             .createExpression();
+
+            ResultSet rs = stmt.executeQuery(
+                vendor.toString(
+                    q.simpleQueryBuilder()
+                     .select( ENTITY_TYPES_TABLE_PK_COLUMN_NAME, ENTITY_TYPES_TABLE_TYPE_NAME_COLUMN_NAME )
+                     .from( t.tableName( schemaName, ENTITY_TYPES_TABLE_NAME ) )
+                     .createExpression()
+                               )
+                                            );
+
+            long pk;
+            try
+            {
+                while( rs.next() )
+                {
+                    pk = rs.getInt( 1 );
+                    String entityTypeName = rs.getString( 2 );
+                    this._state.entityTypePKs().get().put( entityTypeName, (int) pk );
+//                    this._state.entityTypeInfos().get()
+//                        .put( entityTypeName, new EntityTypeInfo( entityDescriptors.get( entityTypeName ), (int) pk ) );
+                }
+            }
+            finally
+            {
+                SQLUtil.closeQuietly( rs );
+            }
+            rs = stmt.executeQuery(
+                vendor.toString(
+                    q.simpleQueryBuilder()
+                     .select( USED_CLASSES_TABLE_PK_COLUMN_NAME, USED_CLASSES_TABLE_CLASS_NAME_COLUMN_NAME )
+                     .from( t.tableName( schemaName, USED_CLASSES_TABLE_NAME ) )
+                     .createExpression()
+                               )
+                                  );
+
+            try
+            {
+                while( rs.next() )
+                {
+                    pk = rs.getInt( 1 );
+                    String descriptorTextualFormat = rs.getString( 2 );
+                    this._state.usedClassesPKs().get().put(
+                        stringToCompositeDescriptor( ValueDescriptor.class,
+                                                     this._app.descriptor(),
+                                                     descriptorTextualFormat ),
+                        (int) pk );
+                }
+            }
+            finally
+            {
+                SQLUtil.closeQuietly( rs );
+            }
+
+            rs = stmt.executeQuery(
+                vendor.toString(
+                    q.simpleQueryBuilder()
+                     .select( ENUM_LOOKUP_TABLE_PK_COLUMN_NAME, ENUM_LOOKUP_TABLE_ENUM_VALUE_NAME )
+                     .from( t.tableName( schemaName, ENUM_LOOKUP_TABLE_NAME ) )
+                     .createExpression()
+                               )
+                                  );
+
+            try
+            {
+                while( rs.next() )
+                {
+                    pk = rs.getInt( 1 );
+                    String enumName = rs.getString( 2 );
+                    this._state.enumPKs().get().put( enumName, (int) pk );
+                }
+            }
+            finally
+            {
+                SQLUtil.closeQuietly( rs );
+            }
+
+            rs = stmt.executeQuery(
+                q.simpleQueryBuilder()
+                 .select( USED_QNAMES_TABLE_QNAME_COLUMN_NAME, USED_QNAMES_TABLE_TABLE_NAME_COLUMN_NAME )
+                 .from( t.tableName( schemaName, USED_QNAMES_TABLE_NAME ) )
+                 .createExpression()
+                 .toString()
+                                  );
+            try
+            {
+                while( rs.next() )
+                {
+                    String qName = rs.getString( 1 );
+                    String tableName = rs.getString( 2 );
+                    this._state.qNameInfos().get().get( QualifiedName.fromFQN( qName ) ).setTableName( tableName );
+                }
+            }
+            finally
+            {
+                SQLUtil.closeQuietly( rs );
+            }
+
+            // @formatter:on
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( stmt );
+        }
+    }
+
+    private void writeAppMetadataToDB( Connection connection, ApplicationInfo appInfo,
+                                       Map<String, Long> tablePKs )
+        throws SQLException
+    {
+        String schemaName = this._state.schemaName().get();
+
+        SQLVendor vendor = this._vendor;
+        ModificationFactory m = vendor.getModificationFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+        LiteralFactory l = vendor.getLiteralFactory();
+
+        // @formatter:off
+        final PreparedStatement st = connection.prepareStatement(
+            vendor.toString(
+                m.insert()
+                 .setTableName( t.tableName( schemaName, ENTITY_TYPES_TABLE_NAME ) )
+                 .setColumnSource( m.columnSourceByValues()
+                                    .addValues( l.param(), l.param() )
+                                    .createExpression()
+                                 )
+                 .createExpression()
+                           )
+                                                                );
+
+        try
+        {
+            Set<String> insertedTypeNames = new HashSet<>();
+            for( EntityDescriptor descriptor : appInfo.entityDescriptors.values() )
+            {
+                descriptor.types().forEach( entityType ->
+                                            {
+                                                String entityTypeName = entityType.getName();
+                                                if( !insertedTypeNames.contains( entityTypeName ) )
+                                                {
+                                                    long pk = tablePKs.get( ENTITY_TYPES_TABLE_NAME );
+                                                    try
+                                                    {
+                                                        st.setInt( 1, (int) pk );
+                                                        st.setString( 2, entityTypeName );
+                                                        st.executeUpdate();
+                                                    }
+                                                    catch( SQLException e )
+                                                    {
+                                                        throw new EntityStoreException( "Underlying exception when setting " + pk,
+                                                                                        SQLUtil.withAllSQLExceptions( e ) );
+                                                    }
+                                                    this._state.entityTypePKs().get().put( entityTypeName, (int) pk );
+//                      this._state.entityTypeInfos().get().put( entityTypeName, new EntityTypeInfo( descriptor, (int) pk ) );
+                                                    tablePKs.put( ENTITY_TYPES_TABLE_NAME, pk + 1 );
+                                                    insertedTypeNames.add( entityTypeName );
+                                                }
+                                            } );
+            }
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( st );
+        }
+
+        PreparedStatement ps = connection.prepareStatement(
+            vendor.toString(
+                m.insert()
+                 .setTableName( t.tableName( schemaName, USED_CLASSES_TABLE_NAME ) )
+                 .setColumnSource(
+                     m.columnSourceByValues()
+                      .addValues( l.param(), l.param() )
+                      .createExpression()
+                                 )
+                 .createExpression()
+                           )
+                                                          );
+
+        try
+        {
+            for( CompositeDescriptorInfo descInfo : appInfo.usedValueComposites )
+            {
+                String vDescStr = compositeDescriptorToString( descInfo.layer, descInfo.module, descInfo.composite );
+                long pk = tablePKs.get( USED_CLASSES_TABLE_NAME );
+                ps.setInt( 1, (int) pk );
+                ps.setString( 2, vDescStr );
+                ps.executeUpdate();
+                this._state.usedClassesPKs().get().put( descInfo.composite, (int) pk );
+                tablePKs.put( USED_CLASSES_TABLE_NAME, pk + 1 );
+            }
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( ps );
+        }
+
+        ps = connection.prepareStatement(
+            vendor.toString(
+                m.insert()
+                 .setTableName( t.tableName( schemaName, ENUM_LOOKUP_TABLE_NAME ) )
+                 .setColumnSource( m.columnSourceByValues()
+                                    .addValues( l.param(), l.param() )
+                                    .createExpression()
+                                 )
+                 .createExpression()
+                           )
+                                        );
+
+        try
+        {
+            for( String enumValue : appInfo.enumValues )
+            {
+                long pk = tablePKs.get( ENUM_LOOKUP_TABLE_NAME );
+                ps.setInt( 1, (int) pk );
+                ps.setString( 2, enumValue );
+                ps.executeUpdate();
+                this._state.enumPKs().get().put( enumValue, (int) pk );
+                tablePKs.put( ENUM_LOOKUP_TABLE_NAME, pk + 1 );
+            }
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( ps );
+        }
+
+        Statement stmt = connection.createStatement();
+        ps = connection.prepareStatement(
+            this.createInsertStatementForQNameInfo( schemaName, vendor ).toString()
+                                        );
+
+        try
+        {
+            DefinitionFactory d = vendor.getDefinitionFactory();
+
+            for( QNameInfo qNameInfo : this._state.qNameInfos().get().values() )
+            {
+                QNameType type = qNameInfo.getQNameType();
+
+                TableElementListBuilder builder = d.createTableElementListBuilder();
+                builder
+                    .addTableElement( d.createColumnDefinition( ALL_QNAMES_TABLE_PK_COLUMN_NAME, this._primitiveTypes
+                        .get( Integer.class ), false ) )
+                    .addTableElement( d.createColumnDefinition( ENTITY_TABLE_PK_COLUMN_NAME, this._primitiveTypes
+                        .get( ENTITY_PK_TYPE ), false ) );
+
+                if( type.equals( QNameType.PROPERTY ) )
+                {
+                    builder.addTableElement( d.createColumnDefinition( QNAME_TABLE_PARENT_QNAME_COLUMN_NAME, this._primitiveTypes
+                        .get( Integer.class ), true ) );
+
+                    if( qNameInfo.getCollectionDepth() > 0 )
+                    {
+                        builder.addTableElement( d.createColumnDefinition( QNAME_TABLE_COLLECTION_PATH_COLUMN_NAME, this
+                            .getCollectionPathDataType(), false ) );
+                    }
+
+                    this.appendColumnDefinitionsForProperty( builder, qNameInfo );
+
+                    builder.addTableElement( d.createTableConstraintDefinition( d.createForeignKeyConstraintBuilder()
+                                                                                 .addSourceColumns( QNAME_TABLE_PARENT_QNAME_COLUMN_NAME, ENTITY_TABLE_PK_COLUMN_NAME )
+                                                                                 .setTargetTableName( t.tableName( schemaName, ALL_QNAMES_TABLE_NAME ) )
+                                                                                 .addTargetColumns( ALL_QNAMES_TABLE_PK_COLUMN_NAME, ENTITY_TABLE_PK_COLUMN_NAME )
+                                                                                 .setOnUpdate( ReferentialAction.CASCADE )
+                                                                                 .setOnDelete( ReferentialAction.CASCADE )
+                                                                                 .createExpression(), ConstraintCharacteristics.INITIALLY_DEFERRED_DEFERRABLE
+                                                                              ) );
+                }
+                else
+                {
+                    if( type.equals( QNameType.ASSOCIATION ) )
+                    {
+                        builder
+                            .addTableElement( d.createColumnDefinition( QNAME_TABLE_VALUE_COLUMN_NAME, this._primitiveTypes
+                                .get( ENTITY_PK_TYPE ), false ) )
+                            .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
+                                                                                  .setUniqueness( UniqueSpecification.PRIMARY_KEY )
+                                                                                  .addColumns( ALL_QNAMES_TABLE_PK_COLUMN_NAME, ENTITY_TABLE_PK_COLUMN_NAME )
+                                                                                  .createExpression()
+                                                                               ) );
+                    }
+                    else if( type.equals( QNameType.MANY_ASSOCIATION ) )
+                    {
+                        builder
+                            .addTableElement( d.createColumnDefinition( QNAME_TABLE_ASSOCIATION_INDEX_COLUMN_NAME, this._primitiveTypes
+                                .get( Integer.class ), false ) )
+                            .addTableElement( d.createColumnDefinition( QNAME_TABLE_VALUE_COLUMN_NAME, this._primitiveTypes
+                                .get( ENTITY_PK_TYPE ), false ) )
+                            .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
+                                                                                  .setUniqueness( UniqueSpecification.PRIMARY_KEY )
+                                                                                  .addColumns( ALL_QNAMES_TABLE_PK_COLUMN_NAME, ENTITY_TABLE_PK_COLUMN_NAME )
+                                                                                  .createExpression()
+                                                                               ) );
+                    }
+                    else
+                    {
+                        throw new IllegalArgumentException( "Did not how to create table for qName type: " + type + "." );
+                    }
+
+                    builder
+                        .addTableElement( d.createTableConstraintDefinition( d.createForeignKeyConstraintBuilder()
+                                                                              .addSourceColumns( QNAME_TABLE_VALUE_COLUMN_NAME )
+                                                                              .setTargetTableName( t.tableName( schemaName, ENTITY_TABLE_NAME ) )
+                                                                              .addTargetColumns( ENTITY_TABLE_PK_COLUMN_NAME )
+                                                                              .setOnUpdate( ReferentialAction.CASCADE )
+                                                                              .setOnDelete( ReferentialAction.CASCADE )
+                                                                              .createExpression(), ConstraintCharacteristics.INITIALLY_DEFERRED_DEFERRABLE
+                                                                           )
+                                        );
+
+                    tablePKs.put( qNameInfo.getTableName(), 0L );
+                }
+
+                builder
+                    .addTableElement(
+                        d.createTableConstraintDefinition( d.createForeignKeyConstraintBuilder()
+                                                            .addSourceColumns( ALL_QNAMES_TABLE_PK_COLUMN_NAME, ENTITY_TABLE_PK_COLUMN_NAME )
+                                                            .setTargetTableName( t.tableName( schemaName, ALL_QNAMES_TABLE_NAME ) )
+                                                            .addTargetColumns( ALL_QNAMES_TABLE_PK_COLUMN_NAME, ENTITY_TABLE_PK_COLUMN_NAME )
+                                                            .setOnUpdate( ReferentialAction.CASCADE )
+                                                            .setOnDelete( ReferentialAction.CASCADE )
+                                                            .createExpression(), ConstraintCharacteristics.INITIALLY_DEFERRED_DEFERRABLE
+                                                         )
+                                    );
+
+                stmt.execute( this._vendor.toString( d.createTableDefinitionBuilder()
+                                                      .setTableName( t.tableName( schemaName, qNameInfo.getTableName() ) )
+                                                      .setTableContentsSource( builder.createExpression() )
+                                                      .createExpression()
+                                                   ) );
+
+                //                stmt.execute( "COMMENT ON TABLE " + schemaName + "." + qNameInfo.getTableName() + " IS '"
+                //                    + qNameInfo.getQName() + "'" );
+                ps.setString( 1, qNameInfo.getQName().toString() );
+                ps.setString( 2, qNameInfo.getTableName() );
+                ps.execute();
+            }
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( stmt );
+            SQLUtil.closeQuietly( ps );
+        }
+
+        // @formatter:off
+    }
+
+    private InsertStatement createInsertStatementForQNameInfo( String schemaName, SQLVendor vendor )
+    {
+        ModificationFactory m = vendor.getModificationFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+        LiteralFactory l = vendor.getLiteralFactory();
+
+        return m.insert()
+                .setTableName( t.tableName( schemaName, USED_QNAMES_TABLE_NAME ) )
+                .setColumnSource( m.columnSourceByValues()
+                                   .addValues( l.param(), l.param() )
+                                   .createExpression()
+                                ).createExpression();
+    }
+
+    private void appendColumnDefinitionsForProperty( TableElementListBuilder builder,
+                                                     QNameInfo qNameInfo )
+    {
+        Type finalType = qNameInfo.getFinalType();
+        if( finalType instanceof ParameterizedType )
+        {
+            finalType = ( (ParameterizedType) finalType ).getRawType();
+        }
+        Class<?> finalClass = (Class<?>) finalType;
+        SQLDataType sqlType;
+        String valueRefTableName = null;
+        String valueRefTablePKColumnName = null;
+        if( qNameInfo.isFinalTypePrimitive() )
+        {
+
+            if( this._customizableTypes.keySet().contains( finalClass )
+                && qNameInfo.getPropertyDescriptor().accessor()
+                            .isAnnotationPresent( SQLTypeInfo.class ) )
+            {
+                sqlType = this._customizableTypes.get( finalClass ).customizeType( finalClass,
+                                                                                   qNameInfo.getPropertyDescriptor()
+                                                                                            .accessor()
+                                                                                            .getAnnotation( SQLTypeInfo.class ) );
+            }
+            else if( Enum.class.isAssignableFrom( finalClass ) )
+            {
+                // Enum - reference the lookup table
+                sqlType = this._primitiveTypes.get( Integer.class );
+                valueRefTableName = ENUM_LOOKUP_TABLE_NAME;
+                valueRefTablePKColumnName = ENUM_LOOKUP_TABLE_PK_COLUMN_NAME;
+            }
+            else
+            {
+                // Primitive type, default sqlType
+                sqlType = this._primitiveTypes.get( finalClass );
+            }
+
+            if( sqlType == null )
+            {
+                throw new InternalError( "Could not find sql type for java type [" + finalType + "]" );
+            }
+        }
+        else
+        {
+            // Value composite - just need used class
+            sqlType = this._primitiveTypes.get( Integer.class );
+            valueRefTableName = USED_CLASSES_TABLE_NAME;
+            valueRefTablePKColumnName = USED_CLASSES_TABLE_PK_COLUMN_NAME;
+        }
+
+        SQLVendor vendor = this._vendor;
+        DefinitionFactory d = vendor.getDefinitionFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+
+        builder
+            .addTableElement(
+                d.createColumnDefinition( QNAME_TABLE_VALUE_COLUMN_NAME, sqlType,
+                                          qNameInfo.getCollectionDepth() > 0 ) )
+            .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
+                                                                  .setUniqueness( UniqueSpecification.PRIMARY_KEY )
+                                                                  .addColumns( ALL_QNAMES_TABLE_PK_COLUMN_NAME, ENTITY_TABLE_PK_COLUMN_NAME )
+                                                                  .createExpression()
+                                                               ) );
+
+        if( valueRefTableName != null /* && valueRefTablePKColumnName != null  is always true if valueRefTableName!=null */ )
+        {
+            builder
+                .addTableElement( d.createTableConstraintDefinition( d
+                                                                         .createForeignKeyConstraintBuilder()
+                                                                         .addSourceColumns( QNAME_TABLE_VALUE_COLUMN_NAME )
+                                                                         .setTargetTableName( t.tableName( this._state
+                                                                                                               .schemaName()
+                                                                                                               .get(), valueRefTableName ) )
+                                                                         .addTargetColumns( valueRefTablePKColumnName )
+                                                                         .setOnUpdate( ReferentialAction.CASCADE )
+                                                                         .setOnDelete( ReferentialAction.RESTRICT )
+                                                                         .createExpression(), ConstraintCharacteristics.NOT_DEFERRABLE
+                                                                   ) );
+        }
+    }
+
+//    protected Long getNextPK( Statement stmt, String schemaName, String columnName,
+//                              String tableName, Long defaultPK
+//    )
+//        throws SQLException
+//    {
+//        ResultSet rs = null;
+//        Long result = defaultPK;
+//        try
+//        {
+//            SQLVendor vendor = this._vendor;
+//            QueryFactory q = vendor.getQueryFactory();
+//            // Let's cheat a bit on SQL functions, so we won't need to use heavy query builder.
+//            // Also, currently there are no arithmetic statements
+//            rs = stmt.executeQuery(
+//                vendor
+//                    .toString(
+//                        q.simpleQueryBuilder()
+//                            .select( "COUNT(" + columnName + ")", "MAX(" + columnName + ") + 1" )
+//                            .from(
+//                                vendor.getTableReferenceFactory().tableName( schemaName, tableName ) )
+//                            .createExpression()
+//                    )
+//            );
+//            if( rs.next() )
+//            {
+//                Long count = rs.getLong( 1 );
+//                if( count > 0 )
+//                {
+//                    result = rs.getLong( 2 );
+//                }
+//            }
+//        }
+//        finally
+//        {
+//            SQLUtil.closeQuietly( rs );
+//        }
+//
+//        return result;
+//    }
+
+//    // This method assume that the schema exists
+//    private Boolean isReindexingNeeded( Connection connection )
+//        throws SQLException
+//    {
+//        Boolean result = true;
+//        String schemaName = this._state.schemaName().get();
+//        Statement stmt = connection.createStatement();
+//        try
+//        {
+//            QueryExpression getAppVersionQuery
+//                            = this._vendor
+//                .getQueryFactory()
+//                .simpleQueryBuilder()
+//                .select( APP_VERSION_PK_COLUMN_NAME )
+//                .from(
+//                    this._vendor.getTableReferenceFactory().tableName( schemaName,
+//                                                                       APP_VERSION_TABLE_NAME ) )
+//                .createExpression();
+//            ResultSet rs = null;
+//            try
+//            {
+//                rs = stmt.executeQuery( this._vendor.toString( getAppVersionQuery ) );
+//            }
+//            catch( SQLException sqle )
+//            {
+//                // Sometimes meta data claims table exists, even when it really doesn't exist
+//            }
+//
+//            if( rs != null )
+//            {
+//                result = !rs.next();
+//
+//                if( !result )
+//                {
+//
+//                    String dbAppVersion = rs.getString( 1 );
+//                    if( this._reindexingStrategy != null )
+//                    {
+//                        result
+//                        = this._reindexingStrategy.reindexingNeeded( dbAppVersion,
+//                                                                     this._app.version() );
+//                    }
+//                }
+//            }
+//        }
+//        finally
+//        {
+//            SQLUtil.closeQuietly( stmt );
+//        }
+//
+//        return result;
+//    }
+
+    private String readAppVersionFromDB( Connection connection, String schemaName )
+        throws SQLException
+    {
+        Statement stmt = connection.createStatement();
+        String result = null;
+        try
+        {
+            QueryExpression getAppVersionQuery
+                = this._vendor
+                .getQueryFactory()
+                .simpleQueryBuilder()
+                .select( APP_VERSION_PK_COLUMN_NAME )
+                .from(
+                    this._vendor.getTableReferenceFactory().tableName( schemaName,
+                                                                       APP_VERSION_TABLE_NAME ) )
+                .createExpression();
+            ResultSet rs = null;
+            try
+            {
+                rs = stmt.executeQuery( getAppVersionQuery.toString() );
+
+                if( rs.next() )
+                {
+                    result = rs.getString( 1 );
+                }
+            }
+            catch( SQLException sqle )
+            {
+                // Sometimes meta data claims table exists, even when it really doesn't exist
+            }
+            finally
+            {
+                SQLUtil.closeQuietly( rs );
+            }
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( stmt );
+        }
+
+        return result;
+    }
+
+    //    private static void clearSchema( Connection connection, String schemaName, SQLVendor vendor )
+//        throws SQLException
+//    {
+//        ModificationFactory m = vendor.getModificationFactory();
+//        Statement stmt = null;
+//        try
+//        {
+//            connection.setReadOnly( false );
+//            stmt = connection.createStatement();
+//            stmt.execute( m.deleteBySearch().setTargetTable( m.createTargetTable(
+//                vendor.getTableReferenceFactory().tableName( schemaName, DBNames.ENTITY_TABLE_NAME ) ) )
+//                .createExpression().toString()
+//            );
+//            connection.commit();
+//        }
+//        finally
+//        {
+//            SQLUtil.closeQuietly( stmt );
+//        }
+//    }
+//
+    private void destroyNeededSchemaTables( Connection connection, String schemaName, int maxQNameUsed )
+        throws SQLException
+    {
+        Statement stmt = connection.createStatement();
+        try
+        {
+            this.dropTablesIfExist( schemaName, ENTITY_TABLE_NAME, stmt );
+            this.dropTablesIfExist( schemaName, ALL_QNAMES_TABLE_NAME, stmt );
+            this.dropTablesIfExist( schemaName, APP_VERSION_TABLE_NAME, stmt );
+            this.dropTablesIfExist( schemaName, ENTITY_TYPES_TABLE_NAME, stmt );
+            this.dropTablesIfExist( schemaName, ENTITY_TYPES_JOIN_TABLE_NAME, stmt );
+            this.dropTablesIfExist( schemaName, ENUM_LOOKUP_TABLE_NAME, stmt );
+            this.dropTablesIfExist( schemaName, USED_CLASSES_TABLE_NAME, stmt );
+            this.dropTablesIfExist( schemaName, USED_QNAMES_TABLE_NAME, stmt );
+
+            for( int x = 0; x <= maxQNameUsed; ++x )
+            {
+                this.dropTablesIfExist( schemaName, DBNames.QNAME_TABLE_NAME_PREFIX
+                                                    + x, stmt );
+            }
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( stmt );
+        }
+    }
+
+    private ApplicationInfo constructApplicationInfo( Boolean setQNameTableNameToNull )
+        throws SQLException
+    {
+        final ApplicationInfo appInfo = new ApplicationInfo();
+        final List<CompositeDescriptorInfo> valueDescriptors = new ArrayList<>();
+        final Deque<Object> currentPath = new ArrayDeque<>();
+        _app.descriptor().accept(
+            new HierarchicalVisitorAdapter<Object, Object, RuntimeException>()
+            {
+                @Override
+                public boolean visitEnter( Object visited )
+                    throws RuntimeException
+                {
+                    if( visited instanceof LayerDescriptor || visited instanceof ModuleDescriptor )
+                    {
+                        currentPath.push( visited );
+                    }
+                    if( visited instanceof EntityDescriptor || visited instanceof ValueDescriptor )
+                    {
+                        // TODO filter non-visible descriptors away.
+                        if( visited instanceof EntityDescriptor )
+                        {
+                            EntityDescriptor entityDescriptor = (EntityDescriptor) visited;
+                            if( entityDescriptor.queryable() )
+                            {
+                                LOGGER.debug( "THIS ONE WORKS: {}", entityDescriptor );
+                                appInfo.entityDescriptors.put(
+                                    entityDescriptor.types().findFirst().get().getName(), entityDescriptor );
+                            }
+                        }
+                        else
+                        {
+                            valueDescriptors.add( new CompositeDescriptorInfo(
+                                (LayerDescriptor) currentPath.stream().skip( 1 ).findFirst().orElse( null ),
+                                (ModuleDescriptor) currentPath.stream().findFirst().orElse( null ),
+                                (CompositeDescriptor) visited ) );
+                        }
+
+                        return false;
+                    }
+
+                    return true;
+                }
+
+                @Override
+                public boolean visitLeave( Object visited )
+                {
+                    if( visited instanceof LayerDescriptor || visited instanceof ModuleDescriptor )
+                    {
+                        currentPath.pop();
+                    }
+                    return true;
+                }
+            } );
+
+        for( EntityDescriptor descriptor : appInfo.entityDescriptors.values() )
+        {
+            Set<QualifiedName> newQNames = new HashSet<>();
+            this.extractPropertyQNames( descriptor, this._state.qNameInfos().get(), newQNames,
+                                        valueDescriptors,
+                                        appInfo.enumValues, setQNameTableNameToNull );
+            this.extractAssociationQNames( descriptor, this._state.qNameInfos().get(), newQNames,
+                                           setQNameTableNameToNull );
+            this.extractManyAssociationQNames( descriptor, this._state.qNameInfos().get(),
+                                               newQNames,
+                                               setQNameTableNameToNull );
+            this._state.entityUsedQNames().get().put( descriptor, newQNames );
+        }
+
+        appInfo.usedValueComposites.addAll( valueDescriptors );
+        return appInfo;
+    }
+
+    private void processPropertyTypeForQNames( PropertyDescriptor pType,
+                                               Map<QualifiedName, QNameInfo> qNameInfos,
+                                               Set<QualifiedName> newQNames,
+                                               List<CompositeDescriptorInfo> vDescriptors,
+                                               Set<String> enumValues,
+                                               Boolean setQNameTableNameToNull
+                                             )
+    {
+        QualifiedName qName = pType.qualifiedName();
+        if( !newQNames.contains( qName ) && !qName.name().equals( HasIdentity.class.getName() ) )
+        {
+            newQNames.add( qName );
+            QNameInfo info = qNameInfos.computeIfAbsent( qName, n ->
+            {
+                String tableName = null;
+                if( !setQNameTableNameToNull )
+                {
+                    tableName = QNAME_TABLE_NAME_PREFIX + qNameInfos.size();
+                }
+                return QNameInfo.fromProperty( n, tableName, pType );
+            } );
+            Type vType = info.getFinalType();
+            while( vType instanceof ParameterizedType )
+            {
+                vType = ( (ParameterizedType) vType ).getRawType();
+            }
+            if( vType instanceof Class<?> ) //
+            {
+                final Class<?> vTypeClass = (Class<?>) vType;
+                if( ( (Class<?>) vType ).isInterface() )
+                {
+                    for( CompositeDescriptorInfo descInfo : vDescriptors )
+                    {
+                        CompositeDescriptor desc = descInfo.composite;
+                        if( desc instanceof ValueDescriptor )
+                        {
+                            ValueDescriptor vDesc = (ValueDescriptor) desc;
+                            // TODO this doesn't understand, say, Map<String, String>, or indeed,
+                            // any other Serializable
+                            if( vDesc.types().anyMatch( vTypeClass::isAssignableFrom ) )
+                            {
+                                vDesc.state().properties().forEach( subPDesc ->
+                                                                    {
+                                                                        this.processPropertyTypeForQNames(
+                                                                            subPDesc,
+                                                                            qNameInfos,
+                                                                            newQNames,
+                                                                            vDescriptors,
+                                                                            enumValues,
+                                                                            setQNameTableNameToNull
+                                                                                                         );
+                                                                    } );
+                            }
+                        }
+                    }
+                }
+                else if( Enum.class.isAssignableFrom( (Class<?>) vType ) )
+                {
+                    for( Object value : ( (Class<?>) vType ).getEnumConstants() )
+                    {
+                        enumValues.add( QualifiedName
+                                            .fromClass( (Class<?>) vType, value.toString() ).toString() );
+                    }
+                }
+            }
+        }
+    }
+
+    private void extractPropertyQNames( EntityDescriptor entityDesc,
+                                        Map<QualifiedName, QNameInfo> qNameInfos,
+                                        Set<QualifiedName> newQNames,
+                                        List<CompositeDescriptorInfo> vDescriptors,
+                                        Set<String> enumValues,
+                                        Boolean setQNameTableNameToNull
+                                      )
+    {
+        entityDesc.state().properties().forEach( pDesc ->
+                                                 {
+                                                     if( SQLSkeletonUtil.isQueryable( pDesc.accessor() ) )
+                                                     {
+                                                         this.processPropertyTypeForQNames(
+                                                             pDesc,
+                                                             qNameInfos,
+                                                             newQNames,
+                                                             vDescriptors,
+                                                             enumValues,
+                                                             setQNameTableNameToNull //
+                                                                                          );
+                                                     }
+                                                 } );
+    }
+
+    private void extractAssociationQNames( EntityDescriptor entityDesc,
+                                           Map<QualifiedName, QNameInfo> extractedQNames,
+                                           Set<QualifiedName> newQNames, Boolean setQNameTableNameToNull
+                                         )
+    {
+        entityDesc.state().associations().forEach( assoDesc ->
+                                                   {
+                                                       if( SQLSkeletonUtil.isQueryable( assoDesc.accessor() ) )
+                                                       {
+                                                           QualifiedName qName = assoDesc.qualifiedName();
+                                                           if( !extractedQNames.containsKey( qName ) )
+                                                           {
+                                                               extractedQNames.put( qName,//
+                                                                                    QNameInfo.fromAssociation( //
+                                                                                                               qName, //
+                                                                                                               setQNameTableNameToNull ? null
+                                                                                                                                       : ( QNAME_TABLE_NAME_PREFIX + extractedQNames
+                                                                                                                   .size() ), //
+                                                                                                               assoDesc //
+                                                                                                             ) //
+                                                                                  );
+                                                               newQNames.add( qName );
+                                                           }
+                                                       }
+                                                   } );
+    }
+
+    private void extractManyAssociationQNames( EntityDescriptor entityDesc,
+                                               Map<QualifiedName, QNameInfo> extractedQNames,
+                                               Set<QualifiedName> newQNames,
+                                               Boolean setQNameTableNameToNull
+                                             )
+    {
+        entityDesc.state().manyAssociations().forEach( mAssoDesc ->
+                                                       {
+                                                           QualifiedName qName = mAssoDesc.qualifiedName();
+                                                           if( SQLSkeletonUtil.isQueryable( mAssoDesc.accessor() ) )
+                                                           {
+                                                               if( !extractedQNames.containsKey( qName ) )
+                                                               {
+                                                                   extractedQNames.put( //
+                                                                                        qName, //
+                                                                                        QNameInfo.fromManyAssociation( //
+                                                                                                                       qName, //
+                                                                                                                       setQNameTableNameToNull ? null
+                                                                                                                                               : ( QNAME_TABLE_NAME_PREFIX + extractedQNames.size() ), //
+                                                                                                                       mAssoDesc //
+                                                                                                                     ) //
+                                                                                      );
+                                                                   newQNames.add( qName );
+                                                               }
+                                                           }
+                                                       } );
+    }
+
+    protected abstract void testRequiredCapabilities( Connection connection )
+        throws SQLException;
+
+    protected boolean dropTablesIfExist(
+        String schemaName,
+        String tableName,
+        Statement stmt
+                                       )
+        throws SQLException
+    {
+        boolean result = false;
+        try
+        {
+            stmt.execute( this._vendor.toString( this._vendor.getManipulationFactory()
+                                                             .createDropTableOrViewStatement(
+                                                                 this._vendor
+                                                                     .getTableReferenceFactory()
+                                                                     .tableName( schemaName, tableName ), ObjectType.TABLE,
+                                                                 DropBehaviour.CASCADE
+                                                                                            ) ) );
+            result = true;
+        }
+        catch( SQLException sqle )
+        {
+            // Ignore
+        }
+        return result;
+    }
+
+    private static final String DESCRIPTOR_COMPONENT_SEPARATOR_START = "{";
+    private static final String DESCRIPTOR_COMPONENT_SEPARATOR_END = "}";
+    private static final String DESCRIPTOR_TYPE_SEPARATOR = ",";
+    private static final Pattern DESCRIPTOR_TYPES_REGEXP = Pattern.compile(
+        "[^" + Pattern.quote( DESCRIPTOR_TYPE_SEPARATOR ) + "]+" );
+    private static final Pattern DESCRIPTOR_TEXTUAL_REGEXP = Pattern.compile(
+        "^"
+        + Pattern.quote( DESCRIPTOR_COMPONENT_SEPARATOR_START ) + "(.*)"
+        + Pattern.quote( DESCRIPTOR_COMPONENT_SEPARATOR_END )
+        + Pattern.quote( DESCRIPTOR_COMPONENT_SEPARATOR_START ) + "(.*)"
+        + Pattern.quote( DESCRIPTOR_COMPONENT_SEPARATOR_END )
+        + Pattern.quote( DESCRIPTOR_COMPONENT_SEPARATOR_START ) + "(" + "[^"
+        + Pattern.quote( DESCRIPTOR_COMPONENT_SEPARATOR_END + DESCRIPTOR_TYPE_SEPARATOR )
+        + "]+)" + Pattern.quote( DESCRIPTOR_COMPONENT_SEPARATOR_END ) + "$" );
+
+    protected static String compositeDescriptorToString( LayerDescriptor layer,
+                                                         ModuleDescriptor module, CompositeDescriptor descriptor )
+    {
+        return DESCRIPTOR_COMPONENT_SEPARATOR_START + layer.name()
+               + DESCRIPTOR_COMPONENT_SEPARATOR_END + DESCRIPTOR_COMPONENT_SEPARATOR_START
+               + module.name() + DESCRIPTOR_COMPONENT_SEPARATOR_END
+               + DESCRIPTOR_COMPONENT_SEPARATOR_START
+               + descriptor.types().map( Object::toString ).collect( Collectors.joining( DESCRIPTOR_TYPE_SEPARATOR ) )
+               + DESCRIPTOR_COMPONENT_SEPARATOR_END;
+    }
+
+    protected static <TCompositeDescriptor extends CompositeDescriptor> TCompositeDescriptor
+    stringToCompositeDescriptor( final Class<TCompositeDescriptor> descriptorClass,
+                                 ApplicationDescriptor appDesc, String str )
+    {
+        Matcher matcher = DESCRIPTOR_TEXTUAL_REGEXP.matcher( str );
+        if( !matcher.matches() )
+        {
+            throw new IllegalArgumentException( "Descriptor textual description " + str
+                                                + " was invalid." );
+        }
+
+        final String layerName = matcher.group( 1 );
+        final String moduleName = matcher.group( 2 );
+        final Set<String> classNames = new HashSet<>();
+        Matcher typesMatcher = DESCRIPTOR_TYPES_REGEXP.matcher( matcher.group( 3 ) );
+        while( typesMatcher.find() )
+        {
+            classNames.add( typesMatcher.group( 0 ) );
+        }
+        final CompositeDescriptor[] result = new CompositeDescriptor[ 1 ];
+
+        appDesc.accept( new HierarchicalVisitorAdapter<Object, Object, RuntimeException>()
+        {
+            @Override
+            public boolean visitEnter( Object visited )
+            {
+                boolean thisResult = true;
+                if( visited instanceof LayerDescriptor )
+                {
+                    thisResult = ( (LayerDescriptor) visited ).name().equals( layerName );
+                }
+                else if( visited instanceof ModuleDescriptor )
+                {
+                    thisResult = ( (ModuleDescriptor) visited ).name().equals( moduleName );
+                }
+                else if( descriptorClass.isAssignableFrom( visited.getClass() ) )
+                {
+                    CompositeDescriptor desc = (CompositeDescriptor) visited;
+                    Set<String> names = desc.types().map( Class::getName ).collect( Collectors.toSet() );
+                    if( classNames.equals( names ) )
+                    {
+                        result[ 0 ] = desc;
+                        thisResult = false;
+                    }
+                }
+                return thisResult;
+            }
+
+            @Override
+            public boolean visitLeave( Object visited )
+            {
+                return result[ 0 ] == null;
+            }
+        } );
+
+        //noinspection unchecked
+        return (TCompositeDescriptor) result[ 0 ];
+    }
+
+    protected abstract void modifyPrimitiveTypes( Map<Class<?>, SQLDataType> primitiveTypes,
+                                                  Map<Class<?>, Integer> jdbcTypes
+                                                );
+
+    protected abstract SQLDataType getCollectionPathDataType();
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/SQLCompatEntityStateWrapper.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/SQLCompatEntityStateWrapper.java
new file mode 100644
index 0000000..bf665c6
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/SQLCompatEntityStateWrapper.java
@@ -0,0 +1,389 @@
+/*
+ *  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.polygene.index.sql.support.skeletons;
+
+import java.time.Instant;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.AssociationStateDescriptor;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.CollectionType;
+import org.apache.polygene.api.type.EntityCompositeType;
+import org.apache.polygene.api.type.ValueCompositeType;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.entity.ManyAssociationState;
+import org.apache.polygene.spi.entity.NamedAssociationState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * EntityState wrapper used by AbstractSQLIndexing to filter out unsupported properties.
+ *
+ * <p>This allows to disable unsupported properties indexing to prevent failures in the SQL Index/Query engine.</p>
+ * <p>When an unsupported Property is found it is logged at WARN level.</p>
+ */
+class SQLCompatEntityStateWrapper
+    implements EntityState
+{
+    private static final Logger LOGGER = LoggerFactory.getLogger( SQLCompatEntityStateWrapper.class.getName() );
+
+    /* package */ static final Function<EntityState, EntityState> WRAP = SQLCompatEntityStateWrapper::new;
+
+    private static final Predicate<PropertyDescriptor> PROPERTY_SPEC = new Predicate<PropertyDescriptor>()
+    {
+
+        @Override
+        public boolean test( PropertyDescriptor propertyDescriptor )
+        {
+            boolean supported = isSupported( propertyDescriptor.valueType() );
+            if( !supported )
+            {
+                LOGGER.warn( "Unsupported Property type: " + propertyDescriptor );
+            }
+            return supported;
+        }
+
+        private boolean isSupported( ValueType valueType )
+        {
+            if( valueType instanceof CollectionType )
+            {
+                CollectionType collectionType = (CollectionType) valueType;
+                return isSupported( collectionType.collectedType() );
+            }
+            Class<?> primaryType = valueType.primaryType();
+            return Number.class.isAssignableFrom( primaryType )
+                   || Boolean.class.isAssignableFrom( primaryType )
+                   || Character.class.isAssignableFrom( primaryType )
+                   || Enum.class.isAssignableFrom( primaryType )
+                   || String.class.isAssignableFrom( primaryType )
+                   || Identity.class.isAssignableFrom( primaryType )
+                   // TODO javax.time support in indexing-sql
+                   // || Date.class.isAssignableFrom( primaryType )
+                   // || DateTime.class.isAssignableFrom( primaryType )
+                   // || LocalDateTime.class.isAssignableFrom( primaryType )
+                   // || LocalDate.class.isAssignableFrom( primaryType )
+                   || valueType.hasType( ValueComposite.class );
+        }
+    };
+
+    private final EntityState wrappedEntityState;
+
+    /* package */ SQLCompatEntityStateWrapper( EntityState wrapped )
+    {
+        this.wrappedEntityState = wrapped;
+    }
+
+    @Override
+    public EntityReference entityReference()
+    {
+        return wrappedEntityState.entityReference();
+    }
+
+    @Override
+    public String version()
+    {
+        return wrappedEntityState.version();
+    }
+
+    @Override
+    public Instant lastModified()
+    {
+        return wrappedEntityState.lastModified();
+    }
+
+    @Override
+    public void remove()
+    {
+        wrappedEntityState.remove();
+    }
+
+    @Override
+    public EntityStatus status()
+    {
+        return wrappedEntityState.status();
+    }
+
+    @Override
+    public boolean isAssignableTo( Class<?> type )
+    {
+        return wrappedEntityState.isAssignableTo( type );
+    }
+
+    @Override
+    public EntityDescriptor entityDescriptor()
+    {
+        return new CompatEntityDescriptorWrapper( wrappedEntityState.entityDescriptor() );
+    }
+
+    @Override
+    public Object propertyValueOf( QualifiedName stateName )
+    {
+        return wrappedEntityState.propertyValueOf( stateName );
+    }
+
+    @Override
+    public void setPropertyValue( QualifiedName stateName, Object json )
+    {
+        wrappedEntityState.setPropertyValue( stateName, json );
+    }
+
+    @Override
+    public EntityReference associationValueOf( QualifiedName stateName )
+    {
+        return wrappedEntityState.associationValueOf( stateName );
+    }
+
+    @Override
+    public void setAssociationValue( QualifiedName stateName, EntityReference newEntity )
+    {
+        wrappedEntityState.setAssociationValue( stateName, newEntity );
+    }
+
+    @Override
+    public ManyAssociationState manyAssociationValueOf( QualifiedName stateName )
+    {
+        return wrappedEntityState.manyAssociationValueOf( stateName );
+    }
+
+    @Override
+    public NamedAssociationState namedAssociationValueOf( QualifiedName stateName )
+    {
+        return wrappedEntityState.namedAssociationValueOf( stateName );
+    }
+
+    @Override
+    @SuppressWarnings( "EqualsWhichDoesntCheckParameterClass" )
+    public boolean equals( Object obj )
+    {
+        return wrappedEntityState.equals( obj );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return wrappedEntityState.hashCode();
+    }
+
+    @Override
+    public String toString()
+    {
+        return wrappedEntityState.toString();
+    }
+
+    private static class CompatEntityDescriptorWrapper
+        implements EntityDescriptor
+    {
+        private final EntityDescriptor wrappedEntityDescriptor;
+
+        private CompatEntityDescriptorWrapper( EntityDescriptor wrappedEntityDescriptor )
+        {
+            this.wrappedEntityDescriptor = wrappedEntityDescriptor;
+        }
+
+        @Override
+        public EntityCompositeType valueType()
+        {
+            return wrappedEntityDescriptor.valueType();
+        }
+
+        @Override
+        public ModuleDescriptor module()
+        {
+            return wrappedEntityDescriptor.module();
+        }
+
+        @Override
+        public AssociationStateDescriptor state()
+        {
+            return new CompatAssociationStateDescriptorWrapper( wrappedEntityDescriptor.state() );
+        }
+
+        @Override
+        public boolean queryable()
+        {
+            return wrappedEntityDescriptor.queryable();
+        }
+
+        @Override
+        public Class<?> primaryType()
+        {
+            return wrappedEntityDescriptor.primaryType();
+        }
+
+        @Override
+        public Stream<Class<?>> mixinTypes()
+        {
+            return wrappedEntityDescriptor.mixinTypes();
+        }
+
+        @Override
+        public Visibility visibility()
+        {
+            return wrappedEntityDescriptor.visibility();
+        }
+
+        @Override
+        public boolean isAssignableTo( Class<?> type )
+        {
+            return wrappedEntityDescriptor.isAssignableTo( type );
+        }
+
+        @Override
+        public Stream<Class<?>> types()
+        {
+            return wrappedEntityDescriptor.types();
+        }
+
+        @Override
+        public <T> T metaInfo( Class<T> infoType )
+        {
+            return wrappedEntityDescriptor.metaInfo( infoType );
+        }
+
+        @Override
+        @SuppressWarnings( "EqualsWhichDoesntCheckParameterClass" )
+        public boolean equals( Object obj )
+        {
+            return wrappedEntityDescriptor.equals( obj );
+        }
+
+        @Override
+        public int hashCode()
+        {
+            return wrappedEntityDescriptor.hashCode();
+        }
+    }
+
+    private static class CompatAssociationStateDescriptorWrapper
+        implements AssociationStateDescriptor
+    {
+        private final AssociationStateDescriptor wrappedAssociationStateDescriptor;
+
+        private CompatAssociationStateDescriptorWrapper( AssociationStateDescriptor wrappedAssociationStateDescriptor )
+        {
+            this.wrappedAssociationStateDescriptor = wrappedAssociationStateDescriptor;
+        }
+
+        @Override
+        public AssociationDescriptor getAssociationByName( String name )
+            throws IllegalArgumentException
+        {
+            return wrappedAssociationStateDescriptor.getAssociationByName( name );
+        }
+
+        @Override
+        public AssociationDescriptor getAssociationByQualifiedName( QualifiedName name )
+            throws IllegalArgumentException
+        {
+            return wrappedAssociationStateDescriptor.getAssociationByQualifiedName( name );
+        }
+
+        @Override
+        public AssociationDescriptor getManyAssociationByName( String name )
+            throws IllegalArgumentException
+        {
+            return wrappedAssociationStateDescriptor.getManyAssociationByName( name );
+        }
+
+        @Override
+        public AssociationDescriptor getManyAssociationByQualifiedName( QualifiedName name )
+            throws IllegalArgumentException
+        {
+            return wrappedAssociationStateDescriptor.getManyAssociationByQualifiedName( name );
+        }
+
+        @Override
+        public AssociationDescriptor getNamedAssociationByName( String name )
+            throws IllegalArgumentException
+        {
+            return wrappedAssociationStateDescriptor.getNamedAssociationByName( name );
+        }
+
+        @Override
+        public AssociationDescriptor getNamedAssociationByQualifiedName( QualifiedName name )
+            throws IllegalArgumentException
+        {
+            return wrappedAssociationStateDescriptor.getNamedAssociationByQualifiedName( name );
+        }
+
+        @Override
+        public Stream<? extends AssociationDescriptor> associations()
+        {
+            return wrappedAssociationStateDescriptor.associations();
+        }
+
+        @Override
+        public Stream<? extends AssociationDescriptor> manyAssociations()
+        {
+            return wrappedAssociationStateDescriptor.manyAssociations();
+        }
+
+        @Override
+        public Stream<? extends AssociationDescriptor> namedAssociations()
+        {
+            return wrappedAssociationStateDescriptor.namedAssociations();
+        }
+
+        @Override
+        public PropertyDescriptor findPropertyModelByName( String name )
+            throws IllegalArgumentException
+        {
+            return wrappedAssociationStateDescriptor.findPropertyModelByName( name );
+        }
+
+        @Override
+        public PropertyDescriptor findPropertyModelByQualifiedName( QualifiedName name )
+            throws IllegalArgumentException
+        {
+            return wrappedAssociationStateDescriptor.findPropertyModelByQualifiedName( name );
+        }
+
+        @Override
+        public Stream<? extends PropertyDescriptor> properties()
+        {
+            return wrappedAssociationStateDescriptor.properties().filter( PROPERTY_SPEC );
+        }
+
+        @Override
+        @SuppressWarnings( "EqualsWhichDoesntCheckParameterClass" )
+        public boolean equals( Object obj )
+        {
+            return wrappedAssociationStateDescriptor.equals( obj );
+        }
+
+        @Override
+        public int hashCode()
+        {
+            return wrappedAssociationStateDescriptor.hashCode();
+        }
+    }
+
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/SQLDBState.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/SQLDBState.java
new file mode 100644
index 0000000..b94beb4
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/SQLDBState.java
@@ -0,0 +1,90 @@
+/*
+ *  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.polygene.index.sql.support.skeletons;
+
+import java.sql.Types;
+import java.util.Map;
+import java.util.Set;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.index.sql.support.api.SQLIndexing;
+import org.apache.polygene.index.sql.support.common.QNameInfo;
+
+/**
+ * The state-type interface containing some important database-related data, in order to create
+ * proper SQL statements in indexing ({@link SQLIndexing}), querying (
+ * {@link org.apache.polygene.index.sql.support.api.SQLQuerying}) and application startup (
+ * {@link org.apache.polygene.index.sql.support.api.SQLAppStartup}.
+ */
+public interface SQLDBState
+{
+    /**
+     * The schema name where all the required tables are located.
+     *
+     * @return The schema name where all the required tables are located.
+     */
+    @Optional
+    Property<String> schemaName();
+
+    /**
+     * Information about all used qualified names.
+     *
+     * @return Information about all used qualified names.
+     * @see QNameInfo
+     */
+    @Optional
+    Property<Map<QualifiedName, QNameInfo>> qNameInfos();
+
+    /**
+     * Information about all used qualified names in a certain entity type. The interface name of
+     * entity type serves as the key.
+     *
+     * @return Information about all used qualified names in a certain entity type.
+     */
+    @Optional
+    Property<Map<EntityDescriptor, Set<QualifiedName>>> entityUsedQNames();
+
+    /**
+     * Primary keys of all used composites in all entities of this application. (Value) Composite
+     * descriptor is the key.
+     *
+     * @return Primary keys of all used classes (of value composites) in all entity types.
+     */
+    @Optional
+    Property<Map<CompositeDescriptor, Integer>> usedClassesPKs();
+
+    @Optional
+    Property<Map<String, Integer>> entityTypePKs();
+
+    /**
+     * A mapping between java type and the ones in {@link Types}. The class of java type is the key.
+     *
+     * @return A mapping between java type and the ones in {@link Types}.
+     */
+    @Optional
+    Property<Map<Class<?>, Integer>> javaTypes2SQLTypes();
+
+    @Optional
+    Property<Map<String, Integer>> enumPKs();
+
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/SQLSkeletonUtil.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/SQLSkeletonUtil.java
new file mode 100644
index 0000000..d508443
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/SQLSkeletonUtil.java
@@ -0,0 +1,97 @@
+/*
+ *  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.polygene.index.sql.support.skeletons;
+
+import java.lang.reflect.AccessibleObject;
+import org.apache.polygene.api.entity.Queryable;
+
+/* package */ final class SQLSkeletonUtil
+{
+
+    /* package */ static boolean isQueryable( AccessibleObject accessor )
+    {
+        Queryable q = accessor.getAnnotation( Queryable.class );
+        return q == null || q.value();
+    }
+
+    private SQLSkeletonUtil()
+    {
+    }
+
+    /**
+     * Required for Lazy.
+     *
+     * @param <T> The result variable type.
+     */
+    public static interface LazyInit<T, TException extends Throwable>
+    {
+        T create()
+            throws TException;
+    }
+
+    /**
+     * Non-threadsafe implementation of C#'s Lazy&lt;T&gt;. I wonder if Java has something like this
+     * already done?
+     *
+     * @param <T> The result variable type.
+     */
+    public static final class Lazy<T, TException extends Throwable>
+    {
+        private final LazyInit<T, TException> m_init;
+        private T m_cachedValue;
+
+        public Lazy( LazyInit<T, TException> init )
+        {
+            this.m_init = init;
+            this.m_cachedValue = null;
+        }
+
+        public T getValue()
+            throws TException
+        {
+            if( this.m_cachedValue == null )
+            {
+                this.m_cachedValue = this.m_init.create();
+            }
+            return this.m_cachedValue;
+        }
+
+        public boolean hasValue()
+        {
+            return this.m_cachedValue != null;
+        }
+    }
+
+    public static final class Reference<T>
+    {
+        private T m_reference;
+
+        public void setReference( T reference )
+        {
+            this.m_reference = reference;
+        }
+
+        public T getReference()
+        {
+            return this.m_reference;
+        }
+    }
+
+}
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/package.html b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/package.html
new file mode 100644
index 0000000..3b7e269
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL Index/Query Vendors Support Skeletons.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/sqlite/package.html b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/sqlite/package.html
new file mode 100644
index 0000000..9cca9de
--- /dev/null
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/sqlite/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL Index/Query SQLite Support.</h2>
+    </body>
+</html>
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/SQLIndexingEngineService.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/SQLIndexingEngineService.java
deleted file mode 100644
index ad0c2b1..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/SQLIndexingEngineService.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.index.sql.internal.SQLEntityFinder;
-import org.qi4j.index.sql.internal.SQLStateChangeListener;
-import org.qi4j.spi.entitystore.StateChangeListener;
-import org.qi4j.spi.query.EntityFinder;
-
-/**
- * This is actual service responsible of managing indexing and queries and creating database structure.
- * <p>
- * The reason why all these components are in one single service is that they all require some data about
- * the database structure. Rather than exposing all of that data publicly to be available via another service,
- * it is stored in a state-style private mixin. Thus all the database-related data is available only to this
- * service, and no one else.
- * </p>
- */
-@Mixins( {
-    SQLEntityFinder.class,
-    SQLStateChangeListener.class
-} )
-public interface SQLIndexingEngineService
-        extends StateChangeListener, EntityFinder, ServiceComposite
-{
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/assembly/AbstractSQLIndexQueryAssembler.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/assembly/AbstractSQLIndexQueryAssembler.java
deleted file mode 100644
index 41e7463..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/assembly/AbstractSQLIndexQueryAssembler.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.assembly;
-
-import java.io.IOException;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.reindexer.ReindexerConfiguration;
-import org.qi4j.index.reindexer.ReindexerService;
-import org.qi4j.index.sql.support.common.ReindexingStrategy;
-import org.qi4j.library.sql.common.SQLConfiguration;
-import org.sql.generation.api.vendor.SQLVendor;
-import org.sql.generation.api.vendor.SQLVendorProvider;
-
-public abstract class AbstractSQLIndexQueryAssembler<AssemblerType>
-    extends Assemblers.VisibilityIdentityConfig<AssemblerType>
-{
-    public static final String DEFAULT_IDENTITY = "indexing-sql";
-
-    private Class<? extends ReindexingStrategy> reindexingStrategy = ReindexingStrategy.NeverNeed.class;
-
-    public AbstractSQLIndexQueryAssembler()
-    {
-        identifiedBy( DEFAULT_IDENTITY );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public AssemblerType withReindexingStrategy( Class<? extends ReindexingStrategy> reindexingStrategy )
-    {
-        this.reindexingStrategy = reindexingStrategy;
-        return (AssemblerType) this;
-    }
-
-    protected SQLVendor getSQLVendor()
-        throws IOException
-    {
-        return SQLVendorProvider.createVendor( SQLVendor.class );
-    }
-
-    protected abstract Class<?> getIndexQueryServiceType();
-
-    @Override
-    public final void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        try
-        {
-            SQLVendor sqlVendor = getSQLVendor();
-            if( sqlVendor == null )
-            {
-                throw new AssemblyException( "SQL Vendor could not be determined." );
-            }
-            module.services( getIndexQueryServiceType() )
-                .identifiedBy( identity() )
-                .setMetaInfo( sqlVendor )
-                .visibleIn( visibility() )
-                .instantiateOnStartup();
-        }
-        catch( IOException ex )
-        {
-            throw new AssemblyException( "SQL Vendor could not be created", ex );
-        }
-
-        module.services( ReindexerService.class ).
-            visibleIn( Visibility.module );
-        module.services( ReindexingStrategy.class ).
-            withMixins( reindexingStrategy ).
-            visibleIn( Visibility.module );
-
-        if( hasConfig() )
-        {
-            configModule().entities( SQLConfiguration.class,
-                                     ReindexerConfiguration.class ).
-                visibleIn( configVisibility() );
-        }
-    }
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/assembly/PostgreSQLIndexQueryAssembler.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/assembly/PostgreSQLIndexQueryAssembler.java
deleted file mode 100644
index 756c773..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/assembly/PostgreSQLIndexQueryAssembler.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.assembly;
-
-import java.io.IOException;
-import org.qi4j.index.sql.support.postgresql.PostgreSQLService;
-import org.sql.generation.api.vendor.PostgreSQLVendor;
-import org.sql.generation.api.vendor.SQLVendor;
-import org.sql.generation.api.vendor.SQLVendorProvider;
-
-public class PostgreSQLIndexQueryAssembler
-    extends AbstractSQLIndexQueryAssembler<PostgreSQLIndexQueryAssembler>
-{
-
-    @Override
-    protected SQLVendor getSQLVendor()
-        throws IOException
-    {
-        return SQLVendorProvider.createVendor( PostgreSQLVendor.class );
-    }
-
-    @Override
-    protected Class<?> getIndexQueryServiceType()
-    {
-        return PostgreSQLService.class;
-    }
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/assembly/package.html b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/assembly/package.html
deleted file mode 100644
index f62c7ab..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/assembly/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL Index/Query Assembly.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/internal/SQLEntityFinder.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/internal/SQLEntityFinder.java
deleted file mode 100644
index 7036afd..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/internal/SQLEntityFinder.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.internal;
-
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import javax.sql.DataSource;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.functional.Specification;
-import org.qi4j.index.sql.support.api.SQLQuerying;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.qi4j.spi.query.EntityFinder;
-import org.qi4j.spi.query.EntityFinderException;
-
-public class SQLEntityFinder
-    implements EntityFinder
-{
-    @Service
-    private SQLQuerying parser;
-
-    @Service
-    private DataSource _dataSource;
-
-    /**
-     * Helper interface to perform some SQL query. Using this simplifies the structure of some of the methods.
-     *
-     * @param <ReturnType> The return type of something to be done.
-     */
-    private interface DoQuery<ReturnType>
-    {
-        ReturnType doIt( Connection connection )
-            throws SQLException;
-    }
-
-    @Override
-    public long countEntities( Class<?> resultType, @Optional Specification<Composite> whereClause, Map<String, Object> variables )
-        throws EntityFinderException
-    {
-        final List<Object> values = new ArrayList<>();
-        final List<Integer> valueSQLTypes = new ArrayList<>();
-        final String query = this.parser.constructQuery( resultType, whereClause, null, null, null, variables, values,
-                                                         valueSQLTypes, true );
-
-        return this.performQuery( new DoQuery<Long>()
-        {
-
-            @Override
-            public Long doIt( Connection connection )
-                throws SQLException
-            {
-                PreparedStatement ps = null;
-                ResultSet rs = null;
-                try
-                {
-                    ps = createPS( connection, query, values, valueSQLTypes );
-                    rs = ps.executeQuery();
-                    rs.next();
-                    return rs.getLong( 1 );
-                }
-                finally
-                {
-                    SQLUtil.closeQuietly( rs );
-                    SQLUtil.closeQuietly( ps );
-                }
-            }
-        } );
-    }
-
-    @Override
-    public Iterable<EntityReference> findEntities( Class<?> resultType,
-                                                   @Optional Specification<Composite> whereClause,
-                                                   @Optional OrderBy[] orderBySegments,
-                                                   @Optional final Integer firstResult,
-                                                   @Optional final Integer maxResults,
-                                                   Map<String, Object> variables )
-        throws EntityFinderException
-    {
-        // TODO what is Zest's policy on negative firstResult and/or maxResults? JDBC has its own way of interpreting
-        // these values - does it match with Zest's way?
-        Iterable<EntityReference> result;
-        if( maxResults == null || maxResults > 0 )
-        {
-            final List<Object> values = new ArrayList<>();
-            final List<Integer> valueSQLTypes = new ArrayList<>();
-            final String query = this.parser.constructQuery( resultType, whereClause, orderBySegments, firstResult,
-                                                             maxResults, variables, values, valueSQLTypes, false );
-
-            result = this.performQuery( new DoQuery<Iterable<EntityReference>>()
-            {
-                @Override
-                public Iterable<EntityReference> doIt( Connection connection )
-                    throws SQLException
-                {
-                    PreparedStatement ps = null;
-                    ResultSet rs = null;
-                    List<EntityReference> resultList = new ArrayList<>( maxResults == null ? 100 : maxResults );
-                    try
-                    {
-                        // TODO possibility to further optimize by setting fetch size (not too small not too little).
-                        Integer rsType = parser.getResultSetType( firstResult, maxResults );
-                        ps = createPS( connection, query, values, valueSQLTypes,
-                                       rsType, ResultSet.CLOSE_CURSORS_AT_COMMIT );
-                        rs = ps.executeQuery();
-                        if( firstResult != null
-                            && !parser.isFirstResultSettingSupported()
-                            && rsType != ResultSet.TYPE_FORWARD_ONLY )
-                        {
-                            rs.absolute( firstResult );
-                        }
-                        Integer i = 0;
-                        while( rs.next() && ( maxResults == null || i < maxResults ) )
-                        {
-                            resultList.add( new EntityReference( rs.getString( 1 ) ) );
-                            ++i;
-                        }
-                    }
-                    finally
-                    {
-                        SQLUtil.closeQuietly( rs );
-                        SQLUtil.closeQuietly( ps );
-                    }
-
-                    return resultList;
-                }
-
-            } );
-
-        }
-        else
-        {
-            result = new ArrayList<>( 0 );
-        }
-
-        return result;
-    }
-
-    @Override
-    public EntityReference findEntity( Class<?> resultType,
-                                       @Optional Specification<Composite> whereClause,
-                                       Map<String, Object> variables )
-        throws EntityFinderException
-    {
-        final List<Object> values = new ArrayList<>();
-        final List<Integer> valueSQLTypes = new ArrayList<>();
-        final String query = this.parser.constructQuery( resultType, whereClause, null, null, null, variables, values,
-                                                         valueSQLTypes, false );
-
-        return this.performQuery( new DoQuery<EntityReference>()
-        {
-            @Override
-            public EntityReference doIt( Connection connection )
-                throws SQLException
-            {
-                PreparedStatement ps = null;
-                ResultSet rs = null;
-                EntityReference result = null;
-                try
-                {
-                    ps = createPS( connection, query, values, valueSQLTypes );
-                    ps.setFetchSize( 1 );
-                    ps.setMaxRows( 1 );
-                    rs = ps.executeQuery();
-                    if( rs.next() )
-                    {
-                        result = new EntityReference( rs.getString( 1 ) );
-                    }
-                }
-                finally
-                {
-                    SQLUtil.closeQuietly( rs );
-                    SQLUtil.closeQuietly( ps );
-                }
-
-                return result;
-            }
-        } );
-    }
-
-    private PreparedStatement createPS( Connection connection, String query,
-                                        List<Object> values, List<Integer> valueSQLTypes )
-        throws SQLException
-    {
-        return this.createPS( connection, query, values, valueSQLTypes,
-                              ResultSet.TYPE_FORWARD_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT );
-    }
-
-    private PreparedStatement createPS( Connection connection, String query,
-                                        List<Object> values, List<Integer> valueSQLTypes,
-                                        Integer resultSetType, Integer resultSetHoldability )
-        throws SQLException
-    {
-        PreparedStatement ps = connection.prepareStatement( query, resultSetType,
-                                                            ResultSet.CONCUR_READ_ONLY, resultSetHoldability );
-        if( values.size() != valueSQLTypes.size() )
-        {
-            throw new InternalError( "There was either too little or too much sql types for values [values="
-                                     + values.size() + ", types=" + valueSQLTypes.size() + "]." );
-        }
-
-        for( Integer x = 0; x < values.size(); ++x )
-        {
-            ps.setObject( x + 1, values.get( x ), valueSQLTypes.get( x ) );
-        }
-
-        return ps;
-    }
-
-    // Helper method to perform SQL queries and handle things if/when something happens
-    private <ReturnType> ReturnType performQuery( DoQuery<ReturnType> doQuery )
-        throws EntityFinderException
-    {
-        ReturnType result = null;
-        Connection connection = null;
-        try
-        {
-            connection = this._dataSource.getConnection();
-            connection.setReadOnly( true );
-
-            result = doQuery.doIt( connection );
-
-        }
-        catch( SQLException sqle )
-        {
-            throw new EntityFinderException( sqle );
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( connection );
-        }
-
-        return result;
-    }
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/internal/SQLStateChangeListener.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/internal/SQLStateChangeListener.java
deleted file mode 100644
index 7bae484..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/internal/SQLStateChangeListener.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.internal;
-
-import java.sql.SQLException;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.unitofwork.UnitOfWorkException;
-import org.qi4j.index.sql.support.api.SQLIndexing;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entitystore.StateChangeListener;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class SQLStateChangeListener
-    implements StateChangeListener
-{
-
-    private static final Logger LOGGER = LoggerFactory.getLogger( SQLStateChangeListener.class );
-
-    @Service
-    private SQLIndexing _indexing;
-
-    @Override
-    public void notifyChanges( Iterable<EntityState> changedStates )
-    {
-        try
-        {
-            this._indexing.indexEntities( changedStates );
-        }
-        catch( SQLException sqle )
-        {
-            SQLException lastException = sqle;
-            while( sqle.getNextException() != null )
-            {
-                sqle = sqle.getNextException();
-            }
-            LOGGER.error( "Error when indexing entities", sqle );
-
-            // TODO is UoWException right one for this?
-            throw new UnitOfWorkException( lastException );
-        }
-    }
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/internal/package.html b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/internal/package.html
deleted file mode 100644
index 8e98e9f..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/internal/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL Index/Query Internal Package.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/package.html b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/package.html
deleted file mode 100644
index 0128b99..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL Index/Query.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/api/SQLAppStartup.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/api/SQLAppStartup.java
deleted file mode 100644
index 2dc219e..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/api/SQLAppStartup.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.api;
-
-import java.sql.SQLException;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.service.ServiceReference;
-
-/**
- * This is the interface which is called by SQL-Indexing when it is activated. This allows implementation specific
- * initializations for RDBMS (for example, possibly re-building database structure).
- */
-@Activators( SQLAppStartup.Activator.class )
-public interface SQLAppStartup
-{
-
-    /**
-     * This method is called when connection may be safely initialized - for example, possibly (re-)building database
-     * structure.
-     * 
-     * @throws SQLException If SQL error.
-     */
-    void initConnection()
-        throws SQLException;
-
-    class Activator
-        extends ActivatorAdapter<ServiceReference<SQLAppStartup>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<SQLAppStartup> activated )
-            throws Exception
-        {
-            activated.get().initConnection();
-        }
-
-    }
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/api/SQLIndexing.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/api/SQLIndexing.java
deleted file mode 100644
index df38bb7..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/api/SQLIndexing.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.api;
-
-import java.sql.SQLException;
-import org.qi4j.spi.entity.EntityState;
-
-/**
- * This is the interface used by SQL-Indexing whenever
- */
-public interface SQLIndexing
-{
-    /**
-     * This method is called when states need to be indexed.
-     * 
-     * @param changedStates The states which changed.
-     * @throws SQLException If SQL.
-     */
-    void indexEntities( Iterable<EntityState> changedStates )
-        throws SQLException;
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/api/SQLQuerying.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/api/SQLQuerying.java
deleted file mode 100644
index 351b822..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/api/SQLQuerying.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.api;
-
-import java.sql.PreparedStatement;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.functional.Specification;
-import org.qi4j.spi.query.EntityFinderException;
-
-/**
- * This interface provides parsing support from Zest queries to SQL queries. The idea is that this interface produces
- * SQL which can be used when creating a {@link PreparedStatement}.
- *
- * @author Stanislav Muhametsin
- */
-public interface SQLQuerying
-{
-    /**
-     * This method will be called when parsing needs to be done from Zest query to SQL query. This method is supposed to
-     * return one single SQL query, which can be used with {@link PreparedStatement}.
-     *
-     * @param resultType The result type of Zest query.
-     * @param whereClause The where clause of Zest query.
-     * @param orderBySegments The order by segments of Zest query.
-     * @param firstResult The first result index of Zest query.
-     * @param maxResults The max amount of returned results.
-     * @param values Values to put into {@link PreparedStatement}, in the order of the list. This List is created from
-     *            the outside and this method is supposed to fill it with necessary values, if any.
-     * @param valueSqlTypes The SQL types of the objects in {@code values}. Each SQL type at index {@code x} is
-     *            interpreted as type of value at index {@code x} of the {@code values} -list.
-     * @param countOnly True if this query should return only the number of matching entities, false otherwise.
-     * @return The SQL query, which may be used with {@link PreparedStatement}.
-     * @throws EntityFinderException If SQLException or something else bad happens.
-     */
-    public String constructQuery( //
-        Class<?> resultType, //
-        @Optional Specification<Composite> whereClause, //
-        @Optional OrderBy[] orderBySegments, //
-        @Optional Integer firstResult, //
-        @Optional Integer maxResults, //
-        Map<String, Object> variables,
-        List<Object> values, //
-        List<Integer> valueSqlTypes, //
-        Boolean countOnly //
-    )
-        throws EntityFinderException;
-
-    public Boolean isFirstResultSettingSupported();
-
-    public Integer getResultSetType( //
-        @Optional Integer firstResult, //
-        @Optional Integer maxResults //
-    );
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/api/SQLTypeInfo.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/api/SQLTypeInfo.java
deleted file mode 100644
index 4f76555..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/api/SQLTypeInfo.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.api;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-
-/**
- * The annotation, which tells the parameters for SQL type. Only applyable to certain typed properties, like for now,
- * {@link String}, {@link BigInteger}, and {@link BigDecimal}.
- *
- * Example of usage, where we want to limit the datatype of column storing this value in RDBMS to be 100 characters of
- * max length:
- * <pre>@SQLTypeInfo(maxLength=100)
- * public Property&lt;String&gt; myStringProperty();</pre>
- *
- * The purpose of this class is to optimize performance for people who know for certain that they will be using
- * SQL-Indexing in their application.
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( ElementType.METHOD )
-public @interface SQLTypeInfo
-{
-    /**
-     * For {@link String}s, this is the max character length as specified by {@code VARCHAR(length)}. For {@link BigInteger}s and {@link BigDecimal}s,
-     * this is the precision of a {@code NUMERIC}.
-     * @return Maximum length for SQL data type representing some property type.
-     */
-    int maxLength();
-
-    /**
-     * For {@link String}s and {@link BigInteger}s, this value is ignored. For {@link BigDecimal}s, this is the scale of {@code NUMERIC}, default being {@code 50}.
-     *
-     * @return The scale of SQL data type representing some property type.
-     */
-    int scale() default 50;
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/api/package.html b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/api/package.html
deleted file mode 100644
index e5940ac..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/api/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL Index/Query Vendors Support API.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/DBNames.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/DBNames.java
deleted file mode 100644
index a19a706..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/DBNames.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.common;
-
-/**
- * This is helper class to contain all the SQL constants used throughout the SQL Indexing.
- * 
- * @author Stanislav Muhametsin
- * 
- */
-public class DBNames
-{
-
-    public static final String QNAME_TABLE_NAME_PREFIX = "qname_";
-
-    public static final String QNAME_TABLE_VALUE_COLUMN_NAME = "qname_value";
-
-    public static final String QNAME_TABLE_ASSOCIATION_INDEX_COLUMN_NAME = "asso_index";
-
-    public static final String QNAME_TABLE_PARENT_QNAME_COLUMN_NAME = "parent_qname";
-
-    public static final String QNAME_TABLE_COLLECTION_PATH_COLUMN_NAME = "collection_path";
-
-    public static final String QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME = "Top";
-
-    public static final String QNAME_TABLE_COLLECTION_PATH_SEPARATOR = ".";
-
-    public static final String ALL_QNAMES_TABLE_NAME = "all_qnames";
-
-    public static final String ALL_QNAMES_TABLE_PK_COLUMN_NAME = "qname_id";
-
-    public static final String USED_CLASSES_TABLE_NAME = "used_classes";
-
-    public static final String USED_CLASSES_TABLE_PK_COLUMN_NAME = "used_class_id";
-
-    public static final String USED_CLASSES_TABLE_CLASS_NAME_COLUMN_NAME = "class_name";
-
-    public static final String USED_QNAMES_TABLE_NAME = "used_qnames";
-
-    public static final String USED_QNAMES_TABLE_QNAME_COLUMN_NAME = "qname";
-
-    public static final String USED_QNAMES_TABLE_TABLE_NAME_COLUMN_NAME = "table_name";
-
-    public static final String ENTITY_TYPES_TABLE_PK_COLUMN_NAME = "entity_type_id";
-
-    public static final String ENTITY_TYPES_TABLE_TYPE_NAME_COLUMN_NAME = "entity_type_name";
-
-    public static final String ENTITY_TYPES_TABLE_NAME = "entity_types";
-
-    public static final String ENTITY_TABLE_NAME = "indexing_entities";
-
-    public static final String ENTITY_TABLE_PK_COLUMN_NAME = "entity_pk";
-
-    public static final String ENTITY_TABLE_IDENTITY_COLUMN_NAME = "entity_identity";
-
-    public static final String ENTITY_TABLE_MODIFIED_COLUMN_NAME = "modified";
-
-    public static final String ENTITY_TABLE_VERSION_COLUMN_NAME = "entity_version";
-
-    public static final String ENTITY_TABLE_APPLICATION_VERSION_COLUMN_NAME = "application_version";
-
-    public static final String ENTITY_TYPES_JOIN_TABLE_NAME = ENTITY_TABLE_NAME + "_" + ENTITY_TYPES_TABLE_NAME;
-
-    public static final String APP_VERSION_TABLE_NAME = "app_version";
-
-    public static final String APP_VERSION_PK_COLUMN_NAME = "app_version";
-
-    public static final String ENUM_LOOKUP_TABLE_NAME = "enum_lookup";
-
-    public static final String ENUM_LOOKUP_TABLE_PK_COLUMN_NAME = "enum_id";
-
-    public static final String ENUM_LOOKUP_TABLE_ENUM_VALUE_NAME = "enum_value";
-
-    private DBNames()
-    {
-    }
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/GenericDatabaseExplorer.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/GenericDatabaseExplorer.java
deleted file mode 100644
index 9131dae..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/GenericDatabaseExplorer.java
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.common;
-
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.qi4j.spi.query.IndexExporter;
-import org.sql.generation.api.grammar.builders.query.QuerySpecificationBuilder;
-import org.sql.generation.api.grammar.factories.QueryFactory;
-import org.sql.generation.api.grammar.factories.TableReferenceFactory;
-import org.sql.generation.api.vendor.SQLVendor;
-
-/**
- * This is a helper class to traverse through all content in specified tables in database. Typical usecase would be by
- * {@link IndexExporter} implementation.
- */
-public final class GenericDatabaseExplorer
-{
-    public static enum IntegrityActions
-    {
-        CASCADE,
-        NO_ACTION,
-        RESTRICT,
-        SET_DEFAULT,
-        SET_NULL
-    }
-
-    public static enum Deferrability
-    {
-        INITIALLY_DEFERRED,
-        INITIALLY_IMMEDIATE,
-        NOT_DEFERRABLE
-    }
-
-    private static final Map<Integer, IntegrityActions> INTEGRITY_ACTIONS;
-
-    private static final Map<Integer, Deferrability> DEFERRABILITIES;
-
-    static
-    {
-        DEFERRABILITIES = new HashMap<>( 3 );
-        DEFERRABILITIES.put( DatabaseMetaData.importedKeyInitiallyDeferred, Deferrability.INITIALLY_DEFERRED );
-        DEFERRABILITIES.put( DatabaseMetaData.importedKeyInitiallyImmediate, Deferrability.INITIALLY_IMMEDIATE );
-        DEFERRABILITIES.put( DatabaseMetaData.importedKeyNotDeferrable, Deferrability.NOT_DEFERRABLE );
-
-        INTEGRITY_ACTIONS = new HashMap<>( 5 );
-        INTEGRITY_ACTIONS.put( DatabaseMetaData.importedKeyCascade, IntegrityActions.CASCADE );
-        INTEGRITY_ACTIONS.put( DatabaseMetaData.importedKeyNoAction, IntegrityActions.NO_ACTION );
-        INTEGRITY_ACTIONS.put( DatabaseMetaData.importedKeyRestrict, IntegrityActions.RESTRICT );
-        INTEGRITY_ACTIONS.put( DatabaseMetaData.importedKeySetDefault, IntegrityActions.SET_DEFAULT );
-        INTEGRITY_ACTIONS.put( DatabaseMetaData.importedKeySetNull, IntegrityActions.SET_NULL );
-    }
-
-    public static class ColumnInfo
-    {
-
-        private final String _name;
-
-        private final Integer _sqlType;
-
-        private final String _typeName;
-
-        private final Integer _size;
-
-        private final Integer _scale;
-
-        private final String _nullable;
-
-        private final String _defaultValue;
-
-        private final String _remarks;
-
-        private ColumnInfo( String name, Integer sqlType, String typeName, Integer size, Integer scale,
-                            String nullable, String defaultValue, String remarks )
-        {
-            this._name = name;
-            this._sqlType = sqlType;
-            this._typeName = typeName;
-            this._size = size;
-            this._scale = scale;
-            this._nullable = nullable;
-            this._defaultValue = defaultValue;
-            this._remarks = remarks;
-        }
-
-        public String getName()
-        {
-            return this._name;
-        }
-
-        public String getTypeName()
-        {
-            return this._typeName;
-        }
-
-        public Integer getSize()
-        {
-            return this._size;
-        }
-
-        public Integer getScale()
-        {
-            return this._scale;
-        }
-
-        public String getNullable()
-        {
-            return this._nullable;
-        }
-
-        public String getDefaultValue()
-        {
-            return this._defaultValue;
-        }
-
-        public String getRemarks()
-        {
-            return this._remarks;
-        }
-
-        public Integer getSQLType()
-        {
-            return this._sqlType;
-        }
-    }
-
-    public static class ForeignKeyInfo
-    {
-
-        private final String _pkSchemaName;
-
-        private final String _pkTableName;
-
-        private final String _pkTablePKColumnName;
-
-        private final IntegrityActions _onUpdateAction;
-
-        private final IntegrityActions _onDeleteAction;
-
-        private final Deferrability _deferrability;
-
-        private ForeignKeyInfo( String pkSchemaName, String pkTableName, String pkTablePKColumnName, short onUpdate,
-                                short onDelete, short deferrability )
-        {
-            this._pkSchemaName = pkSchemaName;
-            this._pkTableName = pkTableName;
-            this._pkTablePKColumnName = pkTablePKColumnName;
-            this._onUpdateAction = INTEGRITY_ACTIONS.get( (int) onUpdate );
-            this._onDeleteAction = INTEGRITY_ACTIONS.get( (int) onDelete );
-            this._deferrability = DEFERRABILITIES.get( (int) deferrability );
-        }
-
-        public String getPkSchemaName()
-        {
-            return this._pkSchemaName;
-        }
-
-        public String getPkTableName()
-        {
-            return this._pkTableName;
-        }
-
-        public String getPkTablePKColumnName()
-        {
-            return this._pkTablePKColumnName;
-        }
-
-        public IntegrityActions getOnUpdateAction()
-        {
-            return this._onUpdateAction;
-        }
-
-        public IntegrityActions getOnDeleteAction()
-        {
-            return this._onDeleteAction;
-        }
-
-        public Deferrability getDeferrability()
-        {
-            return this._deferrability;
-        }
-
-    }
-
-    public static interface DatabaseProcessor
-    {
-        public void beginProcessSchemaInfo( String schemaName );
-
-        public void endProcessSchemaInfo( String schemaName );
-
-        public void beginProcessTableInfo( String schemaName, String tableName, String remarks );
-
-        public void endProcessTableInfo( String schemaName, String tableName, String remarks );
-
-        public void beginProcessColumns( String schemaName, String tableName, String tableRemarks );
-
-        public void beginProcessColumnInfo( String schemaName, String tableName,
-                                            ColumnInfo colInfo, ForeignKeyInfo fkInfo );
-
-        public void endProcessColumnInfo( String schemaName, String tableName,
-                                          ColumnInfo colInfo, ForeignKeyInfo fkInfo );
-
-        public void endProcessColumns( String schemaName, String tableName, String tableRemarks );
-
-        public void beginProcessRows( String schemaName, String tableName, String tableRemarks );
-
-        public void beginProcessRowInfo( String schemaName, String tableName, Object[] rowContents );
-
-        public void endProcessRowInfo( String schemaName, String tableName, Object[] rowContents );
-
-        public void endProcessRows( String schemaName, String tableName, String tableRemarks );
-    }
-
-    public static abstract class DatabaseProcessorAdapter
-        implements DatabaseProcessor
-    {
-
-        @Override
-        public void beginProcessColumnInfo( String schemaName, String tableName,
-                                            ColumnInfo colInfo, ForeignKeyInfo fkInfo )
-        {
-        }
-
-        @Override
-        public void beginProcessColumns( String schemaName, String tableName, String tableRemarks )
-        {
-        }
-
-        @Override
-        public void beginProcessRowInfo( String schemaName, String tableName, Object[] rowContents )
-        {
-        }
-
-        @Override
-        public void beginProcessRows( String schemaName, String tableName, String tableRemarks )
-        {
-        }
-
-        @Override
-        public void beginProcessSchemaInfo( String schemaName )
-        {
-        }
-
-        @Override
-        public void beginProcessTableInfo( String schemaName, String tableName, String remarks )
-        {
-        }
-
-        @Override
-        public void endProcessColumnInfo( String schemaName, String tableName,
-                                          ColumnInfo colInfo, ForeignKeyInfo fkInfo )
-        {
-        }
-
-        @Override
-        public void endProcessColumns( String schemaName, String tableName, String tableRemarks )
-        {
-        }
-
-        @Override
-        public void endProcessRowInfo( String schemaName, String tableName, Object[] rowContents )
-        {
-        }
-
-        @Override
-        public void endProcessRows( String schemaName, String tableName, String tableRemarks )
-        {
-        }
-
-        @Override
-        public void endProcessSchemaInfo( String schemaName )
-        {
-        }
-
-        @Override
-        public void endProcessTableInfo( String schemaName, String tableName, String remarks )
-        {
-        }
-
-    }
-
-    public static void visitDatabaseTables( Connection connection, String catalogName,
-                                            String schemaNamePattern, String tableNamePattern,
-                                            DatabaseProcessor processor, SQLVendor sqlSyntaxVendor )
-        throws SQLException
-    {
-        DatabaseMetaData metaData = connection.getMetaData();
-        connection.setReadOnly( true );
-        ResultSet rs = metaData.getTables( catalogName, schemaNamePattern, tableNamePattern, new String[]
-        {
-            "TABLE"
-        } );
-        try
-        {
-            while( rs.next() )
-            {
-                String schemaName = rs.getString( 2 );
-                try
-                {
-                    processor.beginProcessSchemaInfo( schemaName );
-                    String tableName = rs.getString( 3 );
-                    String tableRemarks = rs.getString( 5 );
-                    try
-                    {
-                        processor.beginProcessTableInfo( schemaName, tableName, tableRemarks );
-                        List<ColumnInfo> colInfos = new ArrayList<>();
-                        ResultSet rsCols = metaData.getColumns( null, schemaName, tableName, null );
-                        try
-                        {
-                            while( rsCols.next() )
-                            {
-                                String nullable = rsCols.getString( 18 );
-                                colInfos.add( new ColumnInfo(
-                                    rsCols.getString( 4 ),
-                                    rsCols.getInt( 5 ),
-                                    rsCols.getString( 6 ),
-                                    rsCols.getInt( 7 ),
-                                    rsCols.getInt( 9 ),
-                                    nullable.length() > 0 ? Boolean.toString( nullable.equals( "YES" ) ) : "unknown",
-                                    rsCols.getString( 13 ),
-                                    rsCols.getString( 12 ) ) );
-                            }
-                        }
-                        finally
-                        {
-                            rsCols.close();
-                        }
-
-                        rsCols = metaData.getImportedKeys( null, schemaName, tableName );
-                        Map<String, ForeignKeyInfo> fkInfos = new HashMap<>();
-                        try
-                        {
-                            while( rsCols.next() )
-                            {
-                                fkInfos.put(
-                                    //
-                                    rsCols.getString( 8 ), //
-                                    new ForeignKeyInfo( rsCols.getString( 2 ), rsCols.getString( 3 ), rsCols
-                                    .getString( 4 ), rsCols.getShort( 10 ), rsCols.getShort( 11 ), rsCols
-                                    .getShort( 14 ) ) );
-                            }
-                        }
-                        finally
-                        {
-                            rsCols.close();
-                        }
-
-                        try
-                        {
-                            processor.beginProcessColumns( schemaName, tableName, tableRemarks );
-                            for( ColumnInfo colInfo : colInfos )
-                            {
-                                try
-                                {
-                                    processor.beginProcessColumnInfo( schemaName, tableName, colInfo,
-                                                                      fkInfos.get( colInfo._name ) );
-                                }
-                                finally
-                                {
-                                    processor.endProcessColumnInfo( schemaName, tableName, colInfo,
-                                                                    fkInfos.get( colInfo._name ) );
-                                }
-                            }
-                        }
-                        finally
-                        {
-                            processor.endProcessColumns( schemaName, tableName, tableRemarks );
-                        }
-
-                        QueryFactory q = sqlSyntaxVendor.getQueryFactory();
-                        TableReferenceFactory t = sqlSyntaxVendor.getTableReferenceFactory();
-                        QuerySpecificationBuilder builda = q.querySpecificationBuilder();
-                        builda.getSelect().selectAll();
-                        builda.getFrom().addTableReferences(
-                            t.tableBuilder( t.table( t.tableName( schemaName, tableName ) ) ) );
-                        String sql = sqlSyntaxVendor.toString( q.createQuery( builda.createExpression() ) );
-                        Statement stmt = connection.createStatement();
-                        ResultSet rowsRs = null;
-                        try
-                        {
-                            rowsRs = stmt.executeQuery( sql );
-                            processor.beginProcessRows( schemaName, tableName, tableRemarks );
-                            while( rowsRs.next() )
-                            {
-                                Object[] rowContents = new Object[ colInfos.size() ];
-                                for( Integer x = 0; x < rowContents.length; ++x )
-                                {
-                                    rowContents[x] = rowsRs.getObject( x + 1 );
-                                }
-
-                                try
-                                {
-                                    processor.beginProcessRowInfo( schemaName, tableName, rowContents );
-                                }
-                                finally
-                                {
-                                    processor.endProcessRowInfo( schemaName, tableName, rowContents );
-                                }
-                            }
-                        }
-                        finally
-                        {
-                            processor.endProcessRows( schemaName, tableName, tableRemarks );
-                            if( rowsRs != null )
-                            {
-                                rowsRs.close();
-                            }
-                            stmt.close();
-                        }
-                    }
-                    finally
-                    {
-                        processor.endProcessTableInfo( schemaName, tableName, tableRemarks );
-                    }
-                }
-                finally
-                {
-                    processor.endProcessSchemaInfo( schemaName );
-                }
-            }
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( rs );
-        }
-    }
-
-    private GenericDatabaseExplorer()
-    {
-    }
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/QNameInfo.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/QNameInfo.java
deleted file mode 100644
index 265b52f..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/QNameInfo.java
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.common;
-
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.property.PropertyDescriptor;
-
-/**
- * A helper interface to encapsulate information about qualified name and how it appears in
- * database.
- *
- * @author Stanislav Muhametsin
- */
-public final class QNameInfo
-{
-    /**
-     * Currently all possible types of qualified names: {@link #PROPERTY} for properties,
-     * {@link #ASSOCIATION} for associations, and {@link #MANY_ASSOCIATION} for many-associations.
-     */
-    public enum QNameType
-    {
-        PROPERTY,
-        ASSOCIATION,
-        MANY_ASSOCIATION
-    }
-
-    private static final List<Class<?>> EMPTY_COLL_CLASSES = new ArrayList<>();
-
-    private String _tableName;
-
-    /**
-     * Store also information about collection types - in case it is required in future.
-     */
-    private final List<Class<?>> _collectionClasses;
-
-    private final QualifiedName _qName;
-
-    private final QNameType _qNameType;
-
-    private final Type _finalType;
-
-    private final Boolean _isFinalTypePrimitive;
-
-    private final PropertyDescriptor _propertyDescriptor;
-
-    private final AssociationDescriptor _associationDescriptor;
-
-    private final AssociationDescriptor _manyAssociationDescriptor;
-
-    private QNameInfo( QualifiedName qName, //
-                       QNameType qNameType, //
-                       List<Class<?>> collectionClasses, //
-                       String tableName, //
-                       Type finalType, //
-                       PropertyDescriptor propertyDescriptor, //
-                       AssociationDescriptor associationDescriptor, //
-                       AssociationDescriptor manyAssociationDescriptor //
-    )
-    {
-        if( ( propertyDescriptor != null && associationDescriptor == null && manyAssociationDescriptor == null )
-            || ( propertyDescriptor == null && associationDescriptor != null && manyAssociationDescriptor == null )
-            || ( propertyDescriptor == null && associationDescriptor == null && manyAssociationDescriptor != null ) )
-        {
-            this._propertyDescriptor = propertyDescriptor;
-            this._associationDescriptor = associationDescriptor;
-            this._manyAssociationDescriptor = manyAssociationDescriptor;
-        }
-        else
-        {
-            throw new IllegalArgumentException(
-                "Exactly one of property, association, or many-association descriptors must be non-null." );
-        }
-        this._qName = qName;
-        this._qNameType = qNameType;
-        this._collectionClasses = ( collectionClasses == null || collectionClasses.isEmpty()
-                                    ? EMPTY_COLL_CLASSES
-                                    : collectionClasses );
-        this._tableName = tableName;
-        this._finalType = finalType;
-        Boolean isFinalTypePrimitive = false;
-        if( finalType instanceof Class<?> )
-        {
-            Class<?> finalClass = (Class<?>) finalType;
-            isFinalTypePrimitive = //
-                Number.class.isAssignableFrom( finalClass )//
-                || Boolean.class.isAssignableFrom( finalClass ) //
-                || Character.class.isAssignableFrom( finalClass ) //
-                || Date.class.isAssignableFrom( finalClass ) //
-                || Enum.class.isAssignableFrom( finalClass ) //
-                || String.class.isAssignableFrom( finalClass )//
-                ;
-        }
-        this._isFinalTypePrimitive = isFinalTypePrimitive;
-    }
-
-    /**
-     * If qualified name represented by this interface is a property with collection as type,
-     * returns the {@code amount of nested collections + 1}. That is, assuming {@code X} is not a
-     * collection, for type {@code Property<Set<X>>} this returns {@code 1}, for
-     * {@code Property<Set<Set<X>>>} this returns {@code 2}, etc. If qualified name represented by
-     * this interface is not a property or a property with no collection type, this method returns
-     * {@code 0}.
-     *
-     * @return The collection depth ({@code > 0}) of qualified name, if this interface represents
-     *         qualified name with collection property; {@code 0} otherwise.
-     */
-    public Integer getCollectionDepth()
-    {
-        return this._collectionClasses.size();
-    }
-
-    /**
-     * Returns the non-collection type of this qualified name. That is, for {@code Property<X>} this
-     * returns {@code X} if {@code X} is not a collection type, and for {@code Property<Set<Y>>}
-     * this returns {@code Y} if {@code Y} is not a collection type.
-     *
-     * @return The non-collection type of this qualified name.
-     */
-    public Type getFinalType()
-    {
-        return this._finalType;
-    }
-
-    /**
-     * Gets the qualified name this interface represents.
-     *
-     * @return The qualified name this interface represents.
-     * @see QualifiedName
-     */
-    public QualifiedName getQName()
-    {
-        return this._qName;
-    }
-
-    /**
-     * Gets the table name in database, used to store values of the qualified name this interface
-     * represents.
-     *
-     * @return The table name in database, used to store values of the qualified name this interface
-     *         represents. May be {@code null} if it is not yet decided.
-     */
-    public String getTableName()
-    {
-        return this._tableName;
-    }
-
-    /**
-     * Sets the previously undecided table name to some specific one. This method only works when
-     * argument is {@code non-null} and current table name is {@code null}.
-     *
-     * @param tableName The new table name. Must be {@code non-null}.
-     * @throws IllegalArgumentException If {@code tableName} is {@code null}.
-     * @throws IllegalStateException If current table name is {@code non-null}.
-     */
-    public void setTableName( String tableName )
-    {
-        if( tableName == null )
-        {
-            throw new IllegalArgumentException( "Table name must not be null." );
-        }
-        if( this._tableName == null )
-        {
-            this._tableName = tableName;
-        }
-        else
-        {
-            throw new IllegalStateException( "Can only set table name when it is null." );
-        }
-    }
-
-    /**
-     * Returns whether the final (non-collection) type of this qualified name is not seen as value
-     * composite. Always returns {@code false} for qualified names of type
-     * {@link QNameType#ASSOCIATION} and {@link QNameType#MANY_ASSOCIATION}.
-     *
-     * @return {@code true} if {@link #getFinalType()} is not seen as value composite type;
-     *         {@code false} otherwise.
-     */
-    public Boolean isFinalTypePrimitive()
-    {
-        return this._isFinalTypePrimitive;
-    }
-
-    /**
-     * Returns {@link PropertyDescriptor} associated with this property, if this qualified name info
-     * represents a property. Returns {@code null} otherwise.
-     *
-     * @return {@link PropertyDescriptor} if this qualified name info is associated with property,
-     *         {@code null} otherwise.
-     */
-    public PropertyDescriptor getPropertyDescriptor()
-    {
-        return this._propertyDescriptor;
-    }
-
-    /**
-     * Returns {@link AssociationDescriptor} associated with this association, if this qualified
-     * name info represents an association. Returns {@code null} otherwise.
-     *
-     * @return {@link AssociationDescriptor} if this qualified name info is associated with
-     *         association, {@code null} otherwise.
-     */
-    public AssociationDescriptor getAssociationDescriptor()
-    {
-        return this._associationDescriptor;
-    }
-
-    /**
-     * Returns {@link AssociationDescriptor} associated with this many-association, if this
-     * qualified name info represents a many-association. Returns {@code null} otherwise.
-     *
-     * @return {@link AssociationDescriptor} if this qualified name info is associated with
-     *         many-association, {@code null} otherwise.
-     */
-    public AssociationDescriptor getManyAssociationDescriptor()
-    {
-        return this._manyAssociationDescriptor;
-    }
-
-    /**
-     * Gets the type of represented qualified name: either {@link QNameType#PROPERTY} for
-     * properties, {@link QNameType#ASSOCIATION} for associations, or
-     * {@link QNameType#MANY_ASSOCIATION} for many-associations.
-     *
-     * @return The type of represented qualified name: either {@link QNameType#PROPERTY},
-     *         {@link QNameType#ASSOCIATION}, or {@link QNameType#MANY_ASSOCIATION}.
-     */
-    public QNameType getQNameType()
-    {
-        return this._qNameType;
-    }
-
-    /**
-     * Creates information about specified qualified name which represents a property.
-     *
-     * @param qName The qualified name of property.
-     * @param tableName The table name where the values of all instances of propertiy with this
-     *        qualified name will be stored. May be {@code null} if it is to be decided later.
-     * @param propertyDescriptor {@link PropertyDescriptor} of this property.
-     * @return An object representing information about property with this qualified name, and how
-     *         instances of this property are stored in database.
-     */
-    public static QNameInfo fromProperty( //
-        QualifiedName qName, //
-        String tableName, //
-        PropertyDescriptor propertyDescriptor //
-    )
-    {
-        Type vType = propertyDescriptor.type();
-        List<Class<?>> collectionClasses = new ArrayList<>();
-        while( vType instanceof ParameterizedType
-               && Collection.class.isAssignableFrom( (Class<?>) ( (ParameterizedType) vType )
-            .getRawType() ) )
-        {
-            collectionClasses.add( (Class<?>) ( (ParameterizedType) vType ).getRawType() );
-            vType = ( (ParameterizedType) vType ).getActualTypeArguments()[0];
-        }
-
-        return new QNameInfo( qName, QNameType.PROPERTY, collectionClasses, tableName, vType,
-                              propertyDescriptor, null,
-                              null );
-    }
-
-    /**
-     * Creates information about specified qualified name which represents an association.
-     *
-     * @param qName The qualified name of the association.
-     * @param tableName The table name where the values of all instances of association with this
-     *        qualified name will be stored. May be {@code null} if it is to be decided later.
-     * @param assoDescriptor {@link AssociationDescriptor} of this association.
-     * @return An object representing information about association with this qualified name, and
-     *         how instances of this association are stored in database.
-     */
-    public static QNameInfo fromAssociation( //
-        QualifiedName qName, //
-        String tableName, //
-        AssociationDescriptor assoDescriptor //
-    )
-    {
-        return new QNameInfo( qName, QNameType.ASSOCIATION, null, tableName, assoDescriptor.type(),
-                              null,
-                              assoDescriptor, null );
-    }
-
-    /**
-     * Creates information about specified qualified name which represents a many-association.
-     *
-     * @param qName The qualified name of the many-association.
-     * @param tableName The table name where the values of all instances of many-association with
-     *        this qualified name will be stored. May be {@code null} if it is to be decided later.
-     * @param manyAssoDescriptor {@link AssociationDescriptor} of this many-association.
-     * @return An object representing information about many-association with this qualified name,
-     *         and how instances of this many-association are stored in database.
-     */
-    public static QNameInfo fromManyAssociation( //
-        QualifiedName qName, //
-        String tableName, //
-        AssociationDescriptor manyAssoDescriptor //
-    )
-    {
-        return new QNameInfo( qName, QNameType.MANY_ASSOCIATION, null, tableName,
-                              manyAssoDescriptor.type(), null,
-                              null, manyAssoDescriptor );
-    }
-
-    @Override
-    public String toString()
-    {
-        return "[table: " + this._tableName + ", final type: " + this._finalType + ", qNameType: "
-               + this._qNameType + ", qName: " + this._qName + "]";
-    }
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/RebuildingStrategy.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/RebuildingStrategy.java
deleted file mode 100644
index c897a9c..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/RebuildingStrategy.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.common;
-
-/**
- * Helper interface to let the user of SQL-Indexing decide when to re-build SQL schema. Rebuilding
- * means first deleting all tables that are going to be used, and then creating them. Useful for
- * tests or when your app is in dev mode.
- *
- * You can decide your application's re-building policy for example like this:
- * {@code mainModule.addServices(RebuildingStrategy.class).withMixins(RebuildingStrategy.AlwaysNeed.class);}
- * . This way your application will always re-build all index data at startup.
- */
-public interface RebuildingStrategy
-{
-    boolean rebuildingRequired( String dbAppVersion, String currentAppVersion );
-
-    /**
-     * The re-building strategy which ALWAYS re-builds the database schema. Useful with tests and
-     * during early development stage of application.
-     */
-    public class AlwaysNeed
-        implements RebuildingStrategy
-    {
-        @Override
-        public boolean rebuildingRequired( String dbAppVersion, String currentAppVersion )
-        {
-            return true;
-        }
-    }
-
-    /**
-     * The re-building strategy which NEVER re-builds the database schema. Useful when current
-     * Zest-related database schema structure must be preserved at all costs.
-     */
-    public class NeverNeed
-        implements RebuildingStrategy
-    {
-        @Override
-        public boolean rebuildingRequired( String dbAppVersion, String currentAppVersion )
-        {
-            return false;
-        }
-    }
-
-    /**
-     * The re-building strategy, which re-builds everything when application version changes. Useful
-     * when migration from versions is implemented, or when application structure changes along with
-     * version (but not during same version).
-     */
-    public class NeedOnChange
-        implements RebuildingStrategy
-    {
-        @Override
-        public boolean rebuildingRequired( String dbAppVersion, String currentAppVersion )
-        {
-            return !dbAppVersion.equals( currentAppVersion );
-        }
-    }
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/ReindexingStrategy.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/ReindexingStrategy.java
deleted file mode 100644
index 868d891..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/ReindexingStrategy.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.common;
-
-/**
- * Service to decide when complete re-indexing is needed, along with default implementations. TODO
- * maybe add {@code void beganReindexing()} and {@code void finishedReindexing()} methods? For
- * example, for UI interaction.
- *
- * You can decide your application's re-indexing policy for example like this:
- * {@code mainModule.addServices(ReindexingStrategy.class).withMixins(ReindexingStrategy.AlwaysNeed.class);}
- * . This way your application will always re-index all entity store data at startup.
- */
-public interface ReindexingStrategy
-{
-    boolean reindexingNeeded( String dbAppVersion, String currentAppVersion );
-
-    /**
-     * The re-indexing strategy which ALWAYS re-indexes everything. Useful with tests and during
-     * early development stage of application.
-     */
-    public class AlwaysNeed
-        implements ReindexingStrategy
-    {
-        @Override
-        public boolean reindexingNeeded( String dbAppVersion, String currentAppVersion )
-        {
-            return true;
-        }
-    }
-
-    /**
-     * The re-indexing strategy which NEVER re-indexes anything. Useful when deleting and re-reading
-     * data is something to be avoided at all costs.
-     */
-    public class NeverNeed
-        implements ReindexingStrategy
-    {
-        @Override
-        public boolean reindexingNeeded( String dbAppVersion, String currentAppVersion )
-        {
-            return false;
-        }
-    }
-
-    /**
-     * The re-indexing strategy, which re-indexes everything when application version changes.
-     * Useful when migration from versions is implemented, or when application structure changes
-     * along with version (but not during same version).
-     */
-    public class NeedOnChange
-        implements ReindexingStrategy
-    {
-        @Override
-        public boolean reindexingNeeded( String dbAppVersion, String currentAppVersion )
-        {
-            return !dbAppVersion.equals( currentAppVersion );
-        }
-    }
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/package.html b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/package.html
deleted file mode 100644
index ce04662..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/common/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL Index/Query Vendors Common Support.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/derby/package.html b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/derby/package.html
deleted file mode 100644
index c5899ba..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/derby/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL Index/Query Apache Derby Support.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLAppStartup.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLAppStartup.java
deleted file mode 100644
index ae77354..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLAppStartup.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.postgresql;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.Map;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.index.sql.support.skeletons.AbstractSQLStartup;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.sql.generation.api.grammar.common.datatypes.SQLDataType;
-import org.sql.generation.api.grammar.definition.table.TableScope;
-import org.sql.generation.api.grammar.definition.table.pgsql.PgSQLTableCommitAction;
-import org.sql.generation.api.grammar.factories.DataTypeFactory;
-import org.sql.generation.api.grammar.factories.DefinitionFactory;
-import org.sql.generation.api.grammar.factories.TableReferenceFactory;
-import org.sql.generation.api.vendor.PostgreSQLVendor;
-
-public class PostgreSQLAppStartup
-    extends AbstractSQLStartup
-{
-
-    private final PostgreSQLVendor _vendor;
-
-    public PostgreSQLAppStartup( @Uses ServiceDescriptor descriptor )
-    {
-        super( descriptor );
-
-        this._vendor = descriptor.metaInfo( PostgreSQLVendor.class );
-    }
-
-    @Override
-    protected void modifyPrimitiveTypes( Map<Class<?>, SQLDataType> primitiveTypes,
-                                         Map<Class<?>, Integer> jdbcTypes )
-    {
-        // Set TEXT as default type for strings, since PgSQL can optimize that better than some
-        // VARCHAR with weird max
-        // length
-        primitiveTypes.put( String.class, this._vendor.getDataTypeFactory().text() );
-    }
-
-    @Override
-    protected void testRequiredCapabilities( Connection connection )
-        throws SQLException
-    {
-        // If collection structure matching will ever be needed, using ltree as path to each leaf
-        // item in
-        // collection-generated tree will be very useful
-        // ltree module provides specific datatype for such path, which may be indexed in order to
-        // greatly improve
-        // performance
-
-        Statement stmt = connection.createStatement();
-        try
-        {
-            DefinitionFactory d = this._vendor.getDefinitionFactory();
-            TableReferenceFactory t = this._vendor.getTableReferenceFactory();
-            DataTypeFactory dt = this._vendor.getDataTypeFactory();
-
-            stmt.execute( this._vendor.toString( d
-                .createTableDefinitionBuilder()
-                .setTableScope( TableScope.LOCAL_TEMPORARY )
-                .setTableName( t.tableName( "ltree_test" ) )
-                .setCommitAction( PgSQLTableCommitAction.DROP )
-                .setTableContentsSource(
-                    d.createTableElementListBuilder()
-                    .addTableElement(
-                        d.createColumnDefinition( "test_column", dt.userDefined( "ltree" ) ) )
-                    .createExpression() ).createExpression() ) );
-        }
-        catch( SQLException sqle )
-        {
-            throw new InternalError( "It seems that your database doesn't have ltree as type. It is needed to store "
-                                     + "collections. Please refer to hopefully supplied instructions on how to add "
-                                     + "ltree type (hint: run <pg_install_dir>/share/contrib/ltree.sql script or "
-                                     + "command 'CREATE EXTENSION ltree;')." );
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( stmt );
-        }
-    }
-
-    @Override
-    protected SQLDataType getCollectionPathDataType()
-    {
-        return this._vendor.getDataTypeFactory().userDefined( "ltree" );
-    }
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLIndexExporter.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLIndexExporter.java
deleted file mode 100644
index 6f1bf53..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLIndexExporter.java
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.postgresql;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.Types;
-import java.util.HashMap;
-import java.util.Map;
-import javax.sql.DataSource;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.index.sql.support.common.GenericDatabaseExplorer;
-import org.qi4j.index.sql.support.common.GenericDatabaseExplorer.ColumnInfo;
-import org.qi4j.index.sql.support.common.GenericDatabaseExplorer.DatabaseProcessor;
-import org.qi4j.index.sql.support.common.GenericDatabaseExplorer.ForeignKeyInfo;
-import org.qi4j.index.sql.support.skeletons.SQLDBState;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.qi4j.spi.query.IndexExporter;
-import org.sql.generation.api.vendor.SQLVendor;
-
-public class PostgreSQLIndexExporter
-    implements IndexExporter
-{
-
-    @This
-    private SQLDBState _state;
-
-    @Uses
-    private ServiceDescriptor descriptor;
-
-    @Service
-    private DataSource _dataSource;
-
-    private static final String SEPARATOR = "-----------------------------------------------";
-
-    private static final Map<Integer, String> TYPE_STRINGS;
-
-    static
-    {
-        TYPE_STRINGS = new HashMap<>( 16 );
-        TYPE_STRINGS.put( Types.BIGINT, "BIGINT" );
-        TYPE_STRINGS.put( Types.BOOLEAN, "BOOLEAN" );
-        TYPE_STRINGS.put( Types.CHAR, "CHAR" );
-        TYPE_STRINGS.put( Types.DATE, "DATE" );
-        TYPE_STRINGS.put( Types.DECIMAL, "DECIMAL" );
-        TYPE_STRINGS.put( Types.DOUBLE, "DOUBLE" );
-        TYPE_STRINGS.put( Types.FLOAT, "FLOAT" );
-        TYPE_STRINGS.put( Types.INTEGER, "INTEGER" );
-        TYPE_STRINGS.put( Types.NULL, "NULL" );
-        TYPE_STRINGS.put( Types.NUMERIC, "NUMERIC" );
-        TYPE_STRINGS.put( Types.REAL, "REAL" );
-        TYPE_STRINGS.put( Types.SMALLINT, "SMALLINT" );
-        TYPE_STRINGS.put( Types.TIME, "TIME" );
-        TYPE_STRINGS.put( Types.TIMESTAMP, "TIMESTAMP" );
-        TYPE_STRINGS.put( Types.VARCHAR, "VARCHAR" );
-        TYPE_STRINGS.put( Types.VARBINARY, "VARBINARY" );
-    }
-
-    @Override
-    public void exportFormalToWriter( final PrintWriter out )
-        throws IOException, UnsupportedOperationException
-    {
-        Connection connection = null;
-        try
-        {
-            connection = this._dataSource.getConnection();
-            GenericDatabaseExplorer.visitDatabaseTables( connection, null,
-                                                         this._state.schemaName().get(), null, new DatabaseProcessor()
-            {
-
-                @Override
-                public void endProcessColumns( String schemaName, String tableName, String tableRemarks )
-                {
-                    out.write( "</columns>" + "\n" );
-                }
-
-                @Override
-                public void endProcessRows( String schemaName, String tableName, String tableRemarks )
-                {
-                    out.write( "</rows>" + "\n" );
-                }
-
-                @Override
-                public void endProcessTableInfo( String schemaName, String tableName, String tableRemarks )
-                {
-                    out.write( "</table>" + "\n" );
-                }
-
-                @Override
-                public void endProcessSchemaInfo( String schemaName )
-                {
-                    out.write( "</schema>" + "\n" );
-                }
-
-                @Override
-                public void endProcessRowInfo( String schemaName, String tableName, Object[] rowContents )
-                {
-                    out.write( "</row>" + "\n" );
-                }
-
-                @Override
-                public void endProcessColumnInfo( String schemaName, String tableName, ColumnInfo colInfo,
-                                                  ForeignKeyInfo fkInfo )
-                {
-                }
-
-                @Override
-                public void beginProcessTableInfo( String schemaName, String tableName, String tableRemarks )
-                {
-                    out.write( "<table name=\"" + tableName + "\" remarks=\"" + tableRemarks + "\">" + "\n" );
-                }
-
-                @Override
-                public void beginProcessColumns( String schemaName, String tableName, String tableRemarks )
-                {
-                    out.write( "<columns>" + "\n" );
-                }
-
-                @Override
-                public void beginProcessColumnInfo( String schemaName, String tableName, ColumnInfo colInfo,
-                                                    ForeignKeyInfo fkInfo )
-                {
-                    String defaultValue = colInfo.getDefaultValue();
-                    if( defaultValue.startsWith( "'" ) )
-                    {
-                        defaultValue = defaultValue.substring( 1, defaultValue.length() - 1 );
-                    }
-                    out.write( "<column name=\"" + colInfo.getName() + "\" colType=\"" + colInfo.getTypeName()
-                               + "\" colSize=\"" + colInfo.getSize() + "\" colScale=\""
-                               + //
-                        colInfo.getScale() + "\" nullable=\"" + colInfo.getNullable() + "\" default=\""
-                               + defaultValue + "\" " //
-                    );
-                    if( fkInfo != null )
-                    {
-                        out.write( "refSchemaName=\"" + fkInfo.getPkSchemaName() + "\" refTableName=\""
-                                   + fkInfo.getPkTableName() + "\" refPKColumnName=\""
-                                   + fkInfo.getPkTablePKColumnName()
-                                   + //
-                            "\" onUpdate=\"" + fkInfo.getOnUpdateAction() + "\" onDelete=\""
-                                   + fkInfo.getOnDeleteAction() + "\" deferrability=\"" + fkInfo.getDeferrability()
-                                   + "\" " //
-                        );
-                    }
-
-                    out.write( "/>" + "\n" );
-                }
-
-                @Override
-                public void beginProcessSchemaInfo( String schemaName )
-                {
-                    out.write( "<schema name=\"" + schemaName + "\">" + "\n" );
-                }
-
-                @Override
-                public void beginProcessRows( String schemaName, String tableName, String tableRemarks )
-                {
-                    out.write( "<rows>" + "\n" );
-                }
-
-                @Override
-                public void beginProcessRowInfo( String schemaName, String tableName, Object[] rowContents )
-                {
-                    out.write( "<row>" + "\n" );
-                    for( Integer x = 0; x < rowContents.length; ++x )
-                    {
-                        out.write( "<value index=\"" + x + "\" >" + rowContents[x] + "</value>" + "\n" );
-                    }
-                }
-            }, this.descriptor.metaInfo( SQLVendor.class ) );
-        }
-        catch( SQLException sqle )
-        {
-            // TODO Just wrap around for now...
-            throw new IOException( sqle );
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( connection );
-        }
-    }
-
-    @Override
-    public void exportReadableToStream( final PrintStream out )
-        throws IOException, UnsupportedOperationException
-    {
-        Connection connection = null;
-        try
-        {
-            connection = this._dataSource.getConnection();
-            GenericDatabaseExplorer.visitDatabaseTables( connection, null,
-                                                         this._state.schemaName().get(), null, new DatabaseProcessor()
-            {
-
-                @Override
-                public void endProcessTableInfo( String schemaName, String tableName, String tableRemarks )
-                {
-                    out.print( "\n\n\n" );
-                }
-
-                @Override
-                public void endProcessSchemaInfo( String schemaName )
-                {
-                    out.print( "\n\n" );
-                }
-
-                @Override
-                public void endProcessRowInfo( String schemaName, String tableName, Object[] rowContents )
-                {
-
-                }
-
-                @Override
-                public void endProcessColumnInfo( String schemaName, String tableName, ColumnInfo colInfo,
-                                                  ForeignKeyInfo fkInfo )
-                {
-
-                }
-
-                @Override
-                public void endProcessColumns( String schemaName, String tableName, String tableRemarks )
-                {
-                    out.print( SEPARATOR + "\n" + SEPARATOR + "\n" );
-                }
-
-                @Override
-                public void endProcessRows( String schemaName, String tableName, String tableRemarks )
-                {
-                    out.print( SEPARATOR + "\n" + SEPARATOR + "\n" );
-                }
-
-                private String parseSQLType( ColumnInfo colInfo )
-                {
-                    String result = colInfo.getTypeName();
-                    Integer sqlType = colInfo.getSQLType();
-                    if( TYPE_STRINGS.containsKey( sqlType ) )
-                    {
-                        result = TYPE_STRINGS.get( sqlType );
-                        if( sqlType == Types.DECIMAL || sqlType == Types.NUMERIC )
-                        {
-                            result = result + "(" + colInfo.getSize() + ", " + colInfo.getScale() + ")";
-                        }
-                        else if( sqlType == Types.VARCHAR || sqlType == Types.VARBINARY )
-                        {
-                            result = result + "(" + colInfo.getSize() + ")";
-                        }
-                    }
-                    return result;
-                }
-
-                @Override
-                public void beginProcessColumnInfo( String schemaName, String tableName, ColumnInfo colInfo,
-                                                    ForeignKeyInfo fkInfo )
-                {
-                    out.print( colInfo.getName() + ":" + this.parseSQLType( colInfo ) + "[nullable:"
-                               + colInfo.getNullable() + "; default: " + colInfo.getDefaultValue() + "]" );
-                    if( fkInfo != null )
-                    {
-                        out.print( " -> " + fkInfo.getPkSchemaName() + "." + fkInfo.getPkTableName() + "("
-                                   + fkInfo.getPkTablePKColumnName() + ")[ON UPDATE " + fkInfo.getOnUpdateAction()
-                                   + ", ON DELETE " + fkInfo.getOnDeleteAction() + ", " + fkInfo.getDeferrability() + "]" );
-                    }
-                    out.print( "\n" );
-                }
-
-                @Override
-                public void beginProcessTableInfo( String schemaName, String tableName, String tableRemarks )
-                {
-                    out.print( "Table: " + schemaName + "." + tableName
-                               + ( tableRemarks == null ? "" : " (" + tableRemarks + ")" ) + "\n" );
-                }
-
-                @Override
-                public void beginProcessSchemaInfo( String schemaName )
-                {
-                    out.print( //
-                        "\n\n" + "Schema: " + schemaName + "\n" + //
-                        SEPARATOR + "\n\n\n" //
-                    );
-                }
-
-                @Override
-                public void beginProcessRowInfo( String schemaName, String tableName, Object[] rowContents )
-                {
-                    for( Integer x = 0; x < rowContents.length; ++x )
-                    {
-                        Object value = rowContents[x];
-                        out.print( value == null ? "NULL" : ( "\"" + value + "\"" ) );
-                        if( x + 1 < rowContents.length )
-                        {
-                            out.print( " ; " );
-                        }
-                    }
-                    out.print( "\n" );
-                }
-
-                @Override
-                public void beginProcessColumns( String schemaName, String tableName, String tableRemarks )
-                {
-                    out.print( SEPARATOR + "\n" + SEPARATOR + "\n" );
-                }
-
-                @Override
-                public void beginProcessRows( String schemaName, String tableName, String tableRemarks )
-                {
-
-                }
-            }, this.descriptor.metaInfo( SQLVendor.class ) );
-        }
-        catch( SQLException sqle )
-        {
-            // TODO Just wrap around for now...
-            throw new IOException( sqle );
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( connection );
-        }
-    }
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLIndexing.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLIndexing.java
deleted file mode 100644
index e932df1..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLIndexing.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.postgresql;
-
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import org.qi4j.index.sql.support.common.DBNames;
-import org.qi4j.index.sql.support.skeletons.AbstractSQLIndexing;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.qi4j.spi.entity.EntityState;
-import org.sql.generation.api.grammar.builders.modification.ColumnSourceByValuesBuilder;
-import org.sql.generation.api.grammar.builders.modification.pgsql.PgSQLInsertStatementBuilder;
-import org.sql.generation.api.grammar.factories.ColumnsFactory;
-import org.sql.generation.api.grammar.factories.LiteralFactory;
-import org.sql.generation.api.grammar.factories.ModificationFactory;
-import org.sql.generation.api.grammar.factories.TableReferenceFactory;
-import org.sql.generation.api.grammar.modification.InsertStatement;
-import org.sql.generation.api.grammar.modification.ValueSource;
-import org.sql.generation.api.vendor.SQLVendor;
-
-public class PostgreSQLIndexing
-    extends AbstractSQLIndexing
-{
-
-    @Override
-    protected long getPKFromAutoGeneratedIDInsert( EntityState state,
-                                                   PreparedStatement autoGeneratedIDStatement,
-                                                   SQLVendor vendor, Connection connection )
-        throws SQLException
-    {
-        this.addEntityInfoToInsertToEntityTablePS( state, autoGeneratedIDStatement, 1 );
-        ResultSet rs = autoGeneratedIDStatement.executeQuery();
-        try
-        {
-            rs.next();
-            return rs.getLong( 1 );
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( rs );
-        }
-    }
-
-    @Override
-    protected InsertStatement createInsertStatementWithAutoGeneratedIDForEntitiesTable(
-        String schemaName, String tableName, SQLVendor vendor )
-    {
-        ModificationFactory m = vendor.getModificationFactory();
-        LiteralFactory l = vendor.getLiteralFactory();
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-        ColumnsFactory c = vendor.getColumnsFactory();
-
-        ColumnSourceByValuesBuilder columnBuilder = m.columnSourceByValues();
-        columnBuilder.addValues( ValueSource.Default.INSTANCE );
-        for( Integer x = 1; x < AMOUNT_OF_COLUMNS_IN_ENTITY_TABLE; ++x )
-        {
-            columnBuilder.addValues( l.param() );
-        }
-
-        return ( (PgSQLInsertStatementBuilder) m.insert() )
-            .setReturningClause(
-                vendor.getQueryFactory().columnsBuilder()
-                .addUnnamedColumns( c.colName( DBNames.ENTITY_TABLE_PK_COLUMN_NAME ) )
-                .createExpression()
-            )
-            .setTableName( t.tableName( schemaName, tableName ) )
-            .setColumnSource( columnBuilder.createExpression() )
-            .createExpression();
-    }
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLQuerying.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLQuerying.java
deleted file mode 100644
index 9f8733f..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLQuerying.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.postgresql;
-
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.functional.Specification;
-import org.qi4j.index.sql.support.skeletons.AbstractSQLQuerying;
-import org.sql.generation.api.grammar.builders.query.QuerySpecificationBuilder;
-import org.sql.generation.api.grammar.query.QueryExpression;
-import org.sql.generation.api.vendor.SQLVendor;
-
-public class PostgreSQLQuerying
-        extends AbstractSQLQuerying
-{
-
-    @Override
-    protected QueryExpression finalizeQuery(
-            SQLVendor sqlVendor, QuerySpecificationBuilder specBuilder,
-            Class<?> resultType,
-            Specification<Composite> whereClause,
-            OrderBy[] orderBySegments,
-            Integer firstResult,
-            Integer maxResults,
-            Map<String, Object> variables,
-            List<Object> values,
-            List<Integer> valueSQLTypes,
-            Boolean countOnly )
-    {
-        Boolean needOffset = firstResult != null && firstResult > 0;
-        Boolean needLimit = maxResults != null && maxResults > 0;
-
-        if ( needOffset ) {
-            specBuilder.offset( firstResult );
-        }
-        if ( needLimit ) {
-            specBuilder.limit( maxResults );
-        }
-
-        return sqlVendor.getQueryFactory().createQuery( specBuilder.createExpression() );
-    }
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLService.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLService.java
deleted file mode 100644
index 95676db..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLService.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.postgresql;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.index.sql.SQLIndexingEngineService;
-import org.qi4j.index.sql.internal.SQLEntityFinder;
-import org.qi4j.index.sql.internal.SQLStateChangeListener;
-import org.qi4j.index.sql.support.api.SQLAppStartup;
-import org.qi4j.index.sql.support.api.SQLIndexing;
-import org.qi4j.index.sql.support.api.SQLQuerying;
-import org.qi4j.index.sql.support.postgresql.PostgreSQLTypeHelper.SQLTypeHelperMixin;
-import org.qi4j.spi.query.IndexExporter;
-
-/**
- * This is actual service responsible of managing indexing and queries and creating database structure.
- * 
- * The reason why all these components are in one single service is that they all require some data about the database
- * structure. Rather than exposing all of that data publicly to be available via another service, it is stored in a
- * state-style private mixin. Thus all the database-related data is available only to this service, and no one else.
- */
-@Mixins(
-{
-    SQLEntityFinder.class,
-    SQLStateChangeListener.class,
-    PostgreSQLAppStartup.class,//
-    PostgreSQLIndexing.class,//
-    PostgreSQLQuerying.class,//
-    SQLTypeHelperMixin.class,//
-    PostgreSQLIndexExporter.class
-})
-public interface PostgreSQLService
-    extends SQLAppStartup, SQLIndexing, SQLQuerying, IndexExporter, SQLIndexingEngineService
-{
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLTypeHelper.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLTypeHelper.java
deleted file mode 100644
index e85bba2..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/PostgreSQLTypeHelper.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.postgresql;
-
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.sql.Timestamp;
-import java.util.Date;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.index.sql.support.skeletons.SQLDBState;
-
-/**
- * A little helper interface to convert java types to SQL types when inserting objects to prepared statements. It will
- * first preprocess the object and possibly convert it to something else (like Character to Integer). Then it will use
- * the {@link SQLDBState#javaTypes2SQLTypes()} mapping to determine which SQL datatype to use when inserting the
- * object to prepared statement.
- */
-@Mixins( PostgreSQLTypeHelper.SQLTypeHelperMixin.class )
-public interface PostgreSQLTypeHelper
-{
-
-    /**
-     * Adds the specified object at specified index in specified prepared statement.
-     *
-     * @param ps The prepared statement.
-     * @param index The index for the object to be inserted in prepared statemtent ({@code > 0}).
-     * @param primitive The object to insert.
-     * @param primitiveType The type of object.
-     * @throws SQLException If something underlying throws it.
-     */
-    void addPrimitiveToPS( PreparedStatement ps, Integer index, @Optional Object primitive, Type primitiveType )
-        throws SQLException;
-
-    Integer getSQLType( Object primitive );
-
-    public class SQLTypeHelperMixin
-        implements PostgreSQLTypeHelper
-    {
-
-        @This
-        private SQLDBState _state;
-
-        public Object processJavaPrimitiveBeforeUsingInStatement( Object primitive )
-        {
-            if( primitive != null )
-            {
-                if( primitive instanceof Character )
-                {
-                    primitive = Character.codePointAt( new char[]
-                    {
-                        (Character) primitive
-                    }, 0 );
-                }
-                else if( primitive instanceof Date )
-                {
-                    primitive = new Timestamp( ( (Date) primitive ).getTime() );
-                }
-                else if( primitive instanceof Byte )
-                {
-                    primitive = (short) (Byte) primitive;
-                }
-                else if( primitive instanceof Short )
-                {
-                    primitive = (int) (Short) primitive;
-                }
-            }
-            return primitive;
-        }
-
-        @Override
-        public void addPrimitiveToPS( PreparedStatement ps, Integer index, Object primitive, Type primitiveType )
-            throws SQLException
-        {
-            primitive = processJavaPrimitiveBeforeUsingInStatement( primitive );
-            Integer sqlType = this.getSQLType( primitiveType );
-            ps.setObject( index, primitive, sqlType );
-        }
-
-        @Override
-        public Integer getSQLType( Object primitive )
-        {
-            primitive = processJavaPrimitiveBeforeUsingInStatement( primitive );
-
-            return this.getSQLType( primitive.getClass() );
-        }
-
-        private Integer getSQLType( Type primitiveType )
-        {
-            if( primitiveType instanceof ParameterizedType )
-            {
-                primitiveType = ( (ParameterizedType) primitiveType ).getRawType();
-            }
-
-            Class<?> primitiveClass = (Class<?>) primitiveType;
-
-            if( Enum.class.isAssignableFrom( primitiveClass ) )
-            {
-                primitiveClass = Enum.class;
-            }
-            Integer sqlType = this._state.javaTypes2SQLTypes().get().get( primitiveClass );
-            if( sqlType == null )
-            {
-                throw new InternalError( "Could not find mapping from " + primitiveClass + " to SQL type." );
-            }
-
-            return sqlType;
-        }
-    }
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/package.html b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/package.html
deleted file mode 100644
index a1bec15..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/postgresql/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL Index/Query PostgreSQL Support.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/AbstractSQLIndexing.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/AbstractSQLIndexing.java
deleted file mode 100644
index 3a4a1d9..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/AbstractSQLIndexing.java
+++ /dev/null
@@ -1,1058 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.skeletons;
-
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Timestamp;
-import java.sql.Types;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import javax.sql.DataSource;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.property.StateHolder;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.index.sql.support.api.SQLIndexing;
-import org.qi4j.index.sql.support.common.DBNames;
-import org.qi4j.index.sql.support.common.QNameInfo;
-import org.qi4j.index.sql.support.common.QNameInfo.QNameType;
-import org.qi4j.index.sql.support.postgresql.PostgreSQLTypeHelper;
-import org.qi4j.index.sql.support.skeletons.SQLSkeletonUtil.Lazy;
-import org.qi4j.index.sql.support.skeletons.SQLSkeletonUtil.LazyInit;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.qi4j.spi.Qi4jSPI;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.EntityStatus;
-import org.sql.generation.api.grammar.builders.modification.ColumnSourceByValuesBuilder;
-import org.sql.generation.api.grammar.builders.modification.DeleteBySearchBuilder;
-import org.sql.generation.api.grammar.builders.modification.UpdateBySearchBuilder;
-import org.sql.generation.api.grammar.builders.query.QuerySpecificationBuilder;
-import org.sql.generation.api.grammar.factories.BooleanFactory;
-import org.sql.generation.api.grammar.factories.ColumnsFactory;
-import org.sql.generation.api.grammar.factories.LiteralFactory;
-import org.sql.generation.api.grammar.factories.ModificationFactory;
-import org.sql.generation.api.grammar.factories.QueryFactory;
-import org.sql.generation.api.grammar.factories.TableReferenceFactory;
-import org.sql.generation.api.grammar.modification.DeleteStatement;
-import org.sql.generation.api.grammar.modification.InsertStatement;
-import org.sql.generation.api.grammar.modification.UpdateSourceByExpression;
-import org.sql.generation.api.grammar.modification.UpdateStatement;
-import org.sql.generation.api.grammar.query.QueryExpression;
-import org.sql.generation.api.vendor.SQLVendor;
-
-import static org.qi4j.index.sql.support.common.DBNames.ENTITY_TABLE_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.ENTITY_TYPES_JOIN_TABLE_NAME;
-
-/**
- * TODO SQL-Generator now has support for auto-generated columns. Use it in indexing ( should make
- * some things quite faster and simpler ).
- */
-public abstract class AbstractSQLIndexing
-    implements SQLIndexing
-{
-
-    public static final Integer AMOUNT_OF_COLUMNS_IN_ENTITY_TABLE = 5;
-
-    public static final Integer AMOUNT_OF_COLUMNS_IN_ALL_QNAMES_TABLE = 2;
-
-    public static final Integer AMOUNT_OF_COLUMNS_IN_ASSO_TABLE = 2;
-
-    public static final Integer AMOUNT_OF_COLUMNS_IN_MANY_ASSO_TABLE = 3;
-
-    @Structure
-    private Application _app;
-
-    @Structure
-    private Qi4jSPI _qi4SPI;
-
-    @This
-    private SQLDBState _state;
-
-    @This
-    private PostgreSQLTypeHelper _sqlTypeHelper;
-
-    @Uses
-    private ServiceDescriptor descriptor;
-
-    @Service
-    private DataSource _dataSource;
-
-    @Override
-    public void indexEntities( Iterable<EntityState> changedStates )
-        throws SQLException
-    {
-        final String schemaName = this._state.schemaName().get();
-        final SQLVendor vendor = this.descriptor.metaInfo( SQLVendor.class );
-        Connection connectionTest = AbstractSQLStartup.CONNECTION_FOR_REINDEXING.get();
-        boolean connectionFromStartupWasNull = connectionTest == null;
-        boolean wasAutoCommit = false;
-        boolean wasReadOnly = false;
-        if( connectionFromStartupWasNull )
-        {
-            connectionTest = this._dataSource.getConnection();
-        }
-        else
-        {
-            wasAutoCommit = connectionTest.getAutoCommit();
-            wasReadOnly = connectionTest.isReadOnly();
-        }
-        final Connection connection = connectionTest;
-
-        PreparedStatement updateEntityTablePS = null;
-        PreparedStatement removeEntityPS = null;
-        PreparedStatement insertToPropertyQNamesPS = null;
-        PreparedStatement clearEntityDataPS = null;
-        Lazy<PreparedStatement, SQLException> queryEntityPKPS = new Lazy<>(
-            new LazyInit<PreparedStatement, SQLException>()
-            {
-                @Override
-                public PreparedStatement create()
-                throws SQLException
-                {
-                    return connection.prepareStatement(
-                        vendor.toString( createQueryEntityPkByIdentityStatement( schemaName, vendor ) ) );
-                }
-            } );
-        Lazy<PreparedStatement, SQLException> insertToEntityTableAutoGenerated = new Lazy<>(
-            new LazyInit<PreparedStatement, SQLException>()
-            {
-                @Override
-                public PreparedStatement create()
-                throws SQLException
-                {
-                    return connection.prepareStatement(
-                        createInsertStatementWithAutoGeneratedIDForEntitiesTable( schemaName,
-                                                                                  ENTITY_TABLE_NAME,
-                                                                                  vendor ).toString() );
-                }
-            } );
-        Lazy<PreparedStatement, SQLException> insertToEntityTypeTablePS = new Lazy<>(
-            new LazyInit<PreparedStatement, SQLException>()
-            {
-                @Override
-                public PreparedStatement create()
-                throws SQLException
-                {
-                    return connection.prepareStatement(
-                        createInsertEntityTypeStatement( schemaName, vendor ).toString() );
-                }
-            } );
-        Map<QualifiedName, PreparedStatement> qNameInsertPSs = new HashMap<>();
-
-        try
-        {
-            connection.setAutoCommit( false );
-            connection.setReadOnly( false );
-
-            // TODO cache all queries.
-            updateEntityTablePS = connection.prepareStatement(
-                this.createUpdateEntityTableStatement( schemaName, vendor ).toString() );
-            removeEntityPS = connection.prepareStatement(
-                this.createDeleteFromEntityTableStatement( schemaName, vendor ).toString() );
-            insertToPropertyQNamesPS = connection.prepareStatement(
-                vendor.toString( this.createInsertStatement( schemaName,
-                                                             DBNames.ALL_QNAMES_TABLE_NAME,
-                                                             AMOUNT_OF_COLUMNS_IN_ALL_QNAMES_TABLE,
-                                                             vendor ) ) );
-            clearEntityDataPS = connection.prepareStatement(
-                this.createClearEntityDataStatement( schemaName, vendor ).toString() );
-
-            Map<Long, EntityState> statesByPK = new HashMap<>();
-            Map<Long, Integer> qNamePKs = new HashMap<>();
-
-            Iterable<EntityState> relatedStates = Iterables.filter( new Specification<EntityState>()
-            {
-                @Override
-                public boolean satisfiedBy( EntityState item )
-                {
-                    return item.entityDescriptor().queryable();
-                }
-            }, Iterables.map( SQLCompatEntityStateWrapper.WRAP, changedStates ) );
-
-            for( EntityState eState : relatedStates )
-            {
-                EntityStatus status = eState.status();
-                Long pk = null;
-                boolean needToInsert = status.equals( EntityStatus.NEW );
-                if( !needToInsert )
-                {
-                    if( status.equals( EntityStatus.UPDATED ) )
-                    {
-                        pk = this.findEntityPK( eState, queryEntityPKPS );
-                        if( pk == null )
-                        {
-                            // Happens when reindexing
-                            needToInsert = true;
-                        }
-                        else
-                        {
-                            // TODO if multiple applications with different application model use
-                            // indexing, need to sync type-table.
-                            this.updateEntityInfoAndProperties( connection, qNameInsertPSs,
-                                                                insertToPropertyQNamesPS,
-                                                                clearEntityDataPS,
-                                                                updateEntityTablePS,
-                                                                eState,
-                                                                pk, qNamePKs );
-                        }
-                    }
-                    else if( status.equals( EntityStatus.REMOVED ) )
-                    {
-                        this.removeEntity( eState, removeEntityPS );
-                    }
-                    else
-                    {
-                        // TODO possibly handle LOADED state somehow
-                        // throw new
-                        // UnsupportedOperationException("Did not understand what to do with state [id = "
-                        // +
-                        // eState.identity().identity() + ", status = " + status + "].");
-                    }
-                }
-
-                if( needToInsert )
-                {
-                    pk = this.getPKFromAutoGeneratedIDInsert( eState,
-                                                              insertToEntityTableAutoGenerated.getValue(),
-                                                              vendor,
-                                                              connection );
-                    this.insertPropertyType( connection, insertToEntityTypeTablePS.getValue(),
-                                             eState, pk );
-                    this.insertProperties( connection, qNameInsertPSs,
-                                           insertToPropertyQNamesPS, eState, pk, qNamePKs );
-                }
-                if( pk != null )
-                {
-                    statesByPK.put( pk, eState );
-                }
-            }
-
-            removeEntityPS.executeBatch();
-            updateEntityTablePS.executeBatch();
-            clearEntityDataPS.executeBatch();
-            if( insertToEntityTypeTablePS.hasValue() )
-            {
-                insertToEntityTypeTablePS.getValue().executeBatch();
-            }
-
-            for( Map.Entry<Long, EntityState> entry : statesByPK.entrySet() )
-            {
-                EntityState eState = entry.getValue();
-                Long pk = entry.getKey();
-                this.insertAssoAndManyAssoQNames( qNameInsertPSs, insertToPropertyQNamesPS,
-                                                  eState,
-                                                  qNamePKs.get( pk ), pk );
-            }
-
-            insertToPropertyQNamesPS.executeBatch();
-
-            for( PreparedStatement ps : qNameInsertPSs.values() )
-            {
-                ps.executeBatch();
-            }
-
-            connection.commit();
-        }
-        catch( SQLException sqle )
-        {
-            SQLUtil.rollbackQuietly( connection );
-            throw sqle;
-        }
-        finally
-        {
-            try
-            {
-                if( queryEntityPKPS.hasValue() )
-                {
-                    SQLUtil.closeQuietly( queryEntityPKPS.getValue() );
-                }
-                if( insertToEntityTableAutoGenerated.hasValue() )
-                {
-                    SQLUtil.closeQuietly( insertToEntityTableAutoGenerated.getValue() );
-                }
-                SQLUtil.closeQuietly( updateEntityTablePS );
-                SQLUtil.closeQuietly( removeEntityPS );
-                SQLUtil.closeQuietly( insertToPropertyQNamesPS );
-                SQLUtil.closeQuietly( clearEntityDataPS );
-                for( PreparedStatement ps : qNameInsertPSs.values() )
-                {
-                    SQLUtil.closeQuietly( ps );
-                }
-            }
-            finally
-            {
-                if( connectionFromStartupWasNull )
-                {
-                    SQLUtil.closeQuietly( connection );
-                }
-                else
-                {
-                    connection.setReadOnly( wasReadOnly );
-                    connection.setAutoCommit( wasAutoCommit );
-                }
-            }
-        }
-    }
-
-    protected InsertStatement createInsertStatement( String schemaName, String tableName,
-                                                     Integer amountOfColumns,
-                                                     SQLVendor vendor
-    )
-    {
-        ModificationFactory m = vendor.getModificationFactory();
-        LiteralFactory l = vendor.getLiteralFactory();
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-
-        ColumnSourceByValuesBuilder columnBuilder = m.columnSourceByValues();
-        for( Integer x = 0; x < amountOfColumns; ++x )
-        {
-            columnBuilder.addValues( l.param() );
-        }
-
-        return m.insert().setTableName( t.tableName( schemaName, tableName ) )
-            .setColumnSource( columnBuilder.createExpression() ).createExpression();
-    }
-
-    protected abstract InsertStatement createInsertStatementWithAutoGeneratedIDForEntitiesTable(
-        String schemaName, String tableName, SQLVendor vendor );
-
-    protected void addEntityInfoToInsertToEntityTablePS( EntityState state, PreparedStatement ps,
-                                                         int startingIndex )
-        throws SQLException
-    {
-        ps.setString( startingIndex, state.identity().identity() );
-        ps.setTimestamp( startingIndex + 1, new Timestamp( state.lastModified() ) );
-        ps.setString( startingIndex + 2, state.version() );
-        ps.setString( startingIndex + 3, this._app.version() );
-    }
-
-    protected Long findEntityPK( EntityState state,
-                                 Lazy<PreparedStatement, SQLException> queryPKPS )
-        throws SQLException
-    {
-        // TODO build cache: Zest Identity -> PK
-        Long entityPK = null;
-        PreparedStatement ps = queryPKPS.getValue();
-        ps.setString( 1, state.identity().identity() );
-        ResultSet rs = null;
-        try
-        {
-            rs = ps.executeQuery();
-
-            if( rs.next() )
-            {
-                entityPK = rs.getLong( 1 );
-            }
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( rs );
-        }
-
-        return entityPK;
-    }
-
-    protected abstract long getPKFromAutoGeneratedIDInsert(
-        EntityState state, PreparedStatement autoGeneratedIDStatement, SQLVendor vendor,
-        Connection connection )
-        throws SQLException;
-
-    protected UpdateStatement
-        createUpdateEntityTableStatement( String schemaName, SQLVendor vendor )
-    {
-        ModificationFactory m = vendor.getModificationFactory();
-        BooleanFactory b = vendor.getBooleanFactory();
-        LiteralFactory l = vendor.getLiteralFactory();
-        ColumnsFactory c = vendor.getColumnsFactory();
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-
-        // "UPDATE " + "%s" + "." + ENTITY_TABLE_NAME + "\n" + //
-        // "SET " + ENTITY_TABLE_IDENTITY_COLUMN_NAME + " = ?, " + //
-        // ENTITY_TABLE_MODIFIED_COLUMN_NAME + " = ?, " + //
-        // ENTITY_TABLE_VERSION_COLUMN_NAME + " = ?, " + //
-        // ENTITY_TABLE_APPLICATION_VERSION_COLUMN_NAME + " = ?" + "\n" + //
-        // "WHERE " + ENTITY_TABLE_PK_COLUMN_NAME + " = ?" + "\n" + //
-        // ";" //
-        UpdateSourceByExpression paramSource = m.updateSourceByExp( l.param() );
-        UpdateBySearchBuilder builder = m.updateBySearch();
-        builder
-            .setTargetTable(
-                m.createTargetTable( t.tableName( schemaName, DBNames.ENTITY_TABLE_NAME ) ) )
-            .addSetClauses( m.setClause( DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME, paramSource ),
-                            m.setClause( DBNames.ENTITY_TABLE_MODIFIED_COLUMN_NAME, paramSource ),
-                            m.setClause( DBNames.ENTITY_TABLE_VERSION_COLUMN_NAME, paramSource ),
-                            m.setClause( DBNames.ENTITY_TABLE_APPLICATION_VERSION_COLUMN_NAME, paramSource ) )
-            .getWhereBuilder()
-            .reset( b.eq( c.colName( DBNames.ENTITY_TABLE_PK_COLUMN_NAME ), l.param() ) );
-
-        return builder.createExpression();
-    }
-
-    protected QueryExpression createQueryEntityPkByIdentityStatement( String schemaName,
-                                                                      SQLVendor vendor )
-    {
-        BooleanFactory b = vendor.getBooleanFactory();
-        LiteralFactory l = vendor.getLiteralFactory();
-        ColumnsFactory c = vendor.getColumnsFactory();
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-        QueryFactory q = vendor.getQueryFactory();
-
-        // "SELECT " + ENTITY_TABLE_PK_COLUMN_NAME + "\n" + //
-        // "FROM " + "%s" + "." + ENTITY_TABLE_NAME + "\n" + //
-        // "WHERE " + ENTITY_TABLE_IDENTITY_COLUMN_NAME + " = ?" + "\n" + //
-        // ";" //
-        QuerySpecificationBuilder query = q.querySpecificationBuilder();
-        query.getSelect().addUnnamedColumns( c.colName( DBNames.ENTITY_TABLE_PK_COLUMN_NAME ) );
-        query.getFrom().addTableReferences(
-            t.tableBuilder( t.table( t.tableName( schemaName, DBNames.ENTITY_TABLE_NAME ) ) ) );
-        query.getWhere().reset(
-            b.eq( c.colName( DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME ), l.param() ) );
-
-        return q.createQuery( query.createExpression() );
-    }
-
-    protected DeleteStatement createDeleteFromEntityTableStatement( String schemaName,
-                                                                    SQLVendor vendor )
-    {
-        return this.createDeleteFromTableStatement( schemaName, DBNames.ENTITY_TABLE_NAME,
-                                                    DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME, vendor );
-    }
-
-    protected DeleteStatement
-        createClearEntityDataStatement( String schemaName, SQLVendor vendor )
-    {
-        return this.createDeleteFromTableStatement( schemaName, DBNames.ALL_QNAMES_TABLE_NAME,
-                                                    DBNames.ENTITY_TABLE_PK_COLUMN_NAME, vendor );
-    }
-
-    protected DeleteStatement createDeleteFromTableStatement( String schemaName, String tableName,
-                                                              String columnName,
-                                                              SQLVendor vendor
-    )
-    {
-        ModificationFactory m = vendor.getModificationFactory();
-        BooleanFactory b = vendor.getBooleanFactory();
-        LiteralFactory l = vendor.getLiteralFactory();
-        ColumnsFactory c = vendor.getColumnsFactory();
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-
-        // "DELETE FROM " + "%s" + "." + "%s" + "\n" + //
-        // "WHERE " + "%s" + " = ? " + "\n" + //
-        // ";" //
-        DeleteBySearchBuilder delete = m.deleteBySearch();
-        delete.setTargetTable( m.createTargetTable( t.tableName( schemaName, tableName ) ) )
-            .getWhere()
-            .reset( b.eq( c.colName( columnName ), l.param() ) );
-
-        return delete.createExpression();
-    }
-
-    protected InsertStatement createPropertyInsert( QNameInfo qNameInfo, SQLVendor vendor )
-    {
-        String tableName = qNameInfo.getTableName();
-        ModificationFactory m = vendor.getModificationFactory();
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-        LiteralFactory l = vendor.getLiteralFactory();
-
-        ColumnSourceByValuesBuilder columnBuilder = m.columnSourceByValues()
-            .addValues( l.param(), l.param(), l.param() );
-        if( qNameInfo.getCollectionDepth() > 0 )
-        {
-            columnBuilder.addValues( l.func( "text2ltree", l.param() ) );
-        }
-        columnBuilder.addValues( l.param() );
-
-        return m.insert().setTableName( t.tableName( this._state.schemaName().get(), tableName ) )
-            .setColumnSource( columnBuilder.createExpression() ).createExpression();
-    }
-
-    protected InsertStatement createAssoInsert( QNameInfo qNameInfo, SQLVendor vendor,
-                                                Integer amountOfParams )
-    {
-        ModificationFactory m = vendor.getModificationFactory();
-        LiteralFactory l = vendor.getLiteralFactory();
-        ColumnsFactory c = vendor.getColumnsFactory();
-        QueryFactory q = vendor.getQueryFactory();
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-        BooleanFactory b = vendor.getBooleanFactory();
-        String schemaName = this._state.schemaName().get();
-
-        // "INSERT INTO " + "%s" + "." + "%s" + "\n" + //
-        // "SELECT " + "?, " + "?, " + ENTITY_TABLE_PK_COLUMN_NAME + "\n" + // <-- here is 4 params
-        // when many-asso
-        // "FROM " + "%s" + "." + ENTITY_TABLE_NAME + "\n" + //
-        // "WHERE " + ENTITY_TABLE_IDENTITY_COLUMN_NAME + " = " + "?";
-        QuerySpecificationBuilder qBuilder = q.querySpecificationBuilder();
-        for( Integer x = 0; x < amountOfParams; ++x )
-        {
-            qBuilder.getSelect().addUnnamedColumns( c.colExp( l.param() ) );
-        }
-        qBuilder.getSelect().addUnnamedColumns( c.colName( DBNames.ENTITY_TABLE_PK_COLUMN_NAME ) );
-        qBuilder.getFrom().addTableReferences(
-            t.tableBuilder( t.table( t.tableName( schemaName, DBNames.ENTITY_TABLE_NAME ) ) ) );
-        qBuilder.getWhere().reset(
-            b.eq( c.colName( DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME ), l.param() ) );
-
-        return m
-            .insert()
-            .setTableName( t.tableName( schemaName, qNameInfo.getTableName() ) )
-            .setColumnSource( m.columnSourceByQuery( q.createQuery( qBuilder.createExpression() ) ) )
-            .createExpression();
-    }
-
-    protected InsertStatement createInsertEntityTypeStatement( String schemaName, SQLVendor vendor )
-    {
-        return this.createInsertStatement( schemaName, ENTITY_TYPES_JOIN_TABLE_NAME, 2, vendor );
-    }
-
-    private void syncQNamesInsertPSs( Connection connection,
-                                      Map<QualifiedName, PreparedStatement> qNameInsertPSs,
-                                      Set<QualifiedName> qNames
-    )
-        throws SQLException
-    {
-        Set<QualifiedName> copy = new HashSet<QualifiedName>( qNames );
-        copy.removeAll( qNameInsertPSs.keySet() );
-        for( QualifiedName qName : copy )
-        {
-            QNameInfo info = this._state.qNameInfos().get().get( qName );
-            if( info == null )
-            {
-                throw new InternalError(
-                    "Could not find database information about qualified name [" + qName + "]" );
-            }
-
-            QNameType type = info.getQNameType();
-            if( type.equals( QNameType.PROPERTY ) )
-            {
-                qNameInsertPSs.put( qName, this.createInsertPropertyPS( connection, info ) );
-            }
-            else if( type.equals( QNameType.ASSOCIATION ) )
-            {
-                qNameInsertPSs.put( qName, this.createInsertAssociationPS( connection, info ) );
-            }
-            else if( type.equals( QNameType.MANY_ASSOCIATION ) )
-            {
-                qNameInsertPSs.put( qName, this.createInsertManyAssociationPS( connection, info ) );
-            }
-            else
-            {
-                throw new IllegalArgumentException( "Did not know what to do with QName of type "
-                                                    + type + "." );
-            }
-        }
-    }
-
-    private PreparedStatement createInsertPropertyPS( Connection connection, QNameInfo qNameInfo )
-        throws SQLException
-    {
-        SQLVendor vendor = this.descriptor.metaInfo( SQLVendor.class );
-        return connection.prepareStatement( vendor.toString( this.createPropertyInsert( qNameInfo,
-                                                                                        vendor ) ) );
-    }
-
-    private PreparedStatement
-        createInsertAssociationPS( Connection connection, QNameInfo qNameInfo )
-        throws SQLException
-    {
-        SQLVendor vendor = this.descriptor.metaInfo( SQLVendor.class );
-        return connection.prepareStatement( vendor.toString( this.createAssoInsert( qNameInfo,
-                                                                                    vendor,
-                                                                                    AMOUNT_OF_COLUMNS_IN_ASSO_TABLE ) ) );
-    }
-
-    private PreparedStatement createInsertManyAssociationPS( Connection connection,
-                                                             QNameInfo qNameInfo )
-        throws SQLException
-    {
-        SQLVendor vendor = this.descriptor.metaInfo( SQLVendor.class );
-        return connection.prepareStatement( vendor.toString( this.createAssoInsert( qNameInfo,
-                                                                                    vendor,
-                                                                                    AMOUNT_OF_COLUMNS_IN_MANY_ASSO_TABLE ) ) );
-    }
-
-    private void clearAllEntitysQNames( PreparedStatement clearPropertiesPS, Long pk )
-        throws SQLException
-    {
-        clearPropertiesPS.setLong( 1, pk );
-        clearPropertiesPS.addBatch();
-    }
-
-    private Integer insertPropertyQNames( Connection connection,
-                                          Map<QualifiedName, PreparedStatement> qNameInsertPSs,
-                                          PreparedStatement insertAllQNamesPS, EntityState state, Long entityPK
-    )
-        throws SQLException
-    {
-        Set<QualifiedName> qNames = this._state.entityUsedQNames().get().get( state.entityDescriptor() );
-        this.syncQNamesInsertPSs( connection, qNameInsertPSs, qNames );
-        Integer propertyPK = 0;
-        for( PropertyDescriptor pDesc : state.entityDescriptor().state().properties() )
-        {
-            if( SQLSkeletonUtil.isQueryable( pDesc.accessor() ) )
-            {
-                propertyPK = this.insertProperty(
-                    qNameInsertPSs,
-                    insertAllQNamesPS,
-                    propertyPK,
-                    entityPK,
-                    pDesc.qualifiedName(),
-                    state.propertyValueOf( pDesc.qualifiedName() ),
-                    null //
-                );
-            }
-        }
-
-        return propertyPK;
-    }
-
-    private void insertAssoAndManyAssoQNames( Map<QualifiedName, PreparedStatement> qNameInsertPSs,
-                                              PreparedStatement insertToAllQNamesPS,
-                                              EntityState state,
-                                              Integer qNamePK,
-                                              Long entityPK
-    )
-        throws SQLException
-    {
-        for( AssociationDescriptor aDesc : state.entityDescriptor().state().associations() )
-        {
-            if( SQLSkeletonUtil.isQueryable( aDesc.accessor() ) )
-            {
-                QualifiedName qName = aDesc.qualifiedName();
-                PreparedStatement ps = qNameInsertPSs.get( qName );
-                EntityReference ref = state.associationValueOf( qName );
-                if( ref != null )
-                {
-                    insertToAllQNamesPS.setInt( 1, qNamePK );
-                    insertToAllQNamesPS.setLong( 2, entityPK );
-                    insertToAllQNamesPS.addBatch();
-
-                    ps.setInt( 1, qNamePK );
-                    ps.setLong( 2, entityPK );
-                    ps.setString( 3, ref.identity() );
-                    ps.addBatch();
-
-                    ++qNamePK;
-                }
-            }
-        }
-
-        for( AssociationDescriptor mDesc : state.entityDescriptor().state().manyAssociations() )
-        {
-            if( SQLSkeletonUtil.isQueryable( mDesc.accessor() ) )
-            {
-                QualifiedName qName = mDesc.qualifiedName();
-                PreparedStatement ps = qNameInsertPSs.get( qName );
-                Integer index = 0;
-                for( EntityReference ref : state.manyAssociationValueOf( qName ) )
-                {
-                    if( ref != null )
-                    {
-                        insertToAllQNamesPS.setInt( 1, qNamePK );
-                        insertToAllQNamesPS.setLong( 2, entityPK );
-                        insertToAllQNamesPS.addBatch();
-
-                        ps.setInt( 1, qNamePK );
-                        ps.setLong( 2, entityPK );
-                        ps.setInt( 3, index );
-                        ps.setString( 4, ref.identity() );
-                        ps.addBatch();
-                        ++qNamePK;
-                    }
-                    ++index;
-                }
-            }
-        }
-    }
-
-    private Integer insertProperty(
-        Map<QualifiedName, PreparedStatement> qNameInsertPSs,
-        PreparedStatement insertAllQNamesPS,
-        Integer propertyPK,
-        Long entityPK,
-        QualifiedName qName,
-        Object property,
-        Integer parentQNameID
-    )
-        throws SQLException
-    {
-        Integer result = propertyPK;
-        if( property != null )
-        {
-            if( !qName.type().equals( Identity.class.getName() ) )
-            {
-                QNameInfo info = this._state.qNameInfos().get().get( qName );
-                if( info.getCollectionDepth() > 0 )
-                {
-                    result = this.storeCollectionProperty( qNameInsertPSs, insertAllQNamesPS,
-                                                           propertyPK, entityPK,
-                                                           qName, (Collection<?>) property, parentQNameID );
-                }
-                else if( info.isFinalTypePrimitive() )
-                {
-                    result = this.storePrimitiveProperty( qNameInsertPSs, insertAllQNamesPS, propertyPK,
-                                                          entityPK,
-                                                          qName, property, parentQNameID );
-                }
-                else
-                {
-                    result = this.storeValueCompositeProperty( qNameInsertPSs, insertAllQNamesPS,
-                                                               propertyPK, entityPK,
-                                                               qName, property, parentQNameID );
-                }
-            }
-        }
-        return result;
-    }
-
-    private Integer storeCollectionProperty(
-        Map<QualifiedName, PreparedStatement> qNameInsertPSs,
-        PreparedStatement insertAllQNamesPS,
-        Integer propertyPK,
-        Long entityPK,
-        QualifiedName qName,
-        Collection<?> property,
-        Integer parentQNameID
-    )
-        throws SQLException
-    {
-        QNameInfo info = this._state.qNameInfos().get().get( qName );
-        PreparedStatement ps = qNameInsertPSs.get( qName );
-        propertyPK = this.storeCollectionInfo( insertAllQNamesPS, propertyPK, entityPK, parentQNameID, ps,
-                                               info );
-
-        propertyPK = this.storeCollectionItems( qNameInsertPSs, property, insertAllQNamesPS,
-                                                DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME, ps, info.getTableName(),
-                                                propertyPK, entityPK,
-                                                parentQNameID, info.getFinalType(), info.isFinalTypePrimitive() );
-        return propertyPK;
-    }
-
-    private Integer storeCollectionInfo( PreparedStatement insertAllQNamesPS, Integer propertyPK,
-                                         Long entityPK,
-                                         Integer parentQNameID, PreparedStatement ps, QNameInfo info
-    )
-        throws SQLException
-    {
-        insertAllQNamesPS.setInt( 1, propertyPK );
-        insertAllQNamesPS.setLong( 2, entityPK );
-        insertAllQNamesPS.addBatch();
-
-        ps.setInt( 1, propertyPK );
-        ps.setLong( 2, entityPK );
-        ps.setObject( 3, parentQNameID, Types.BIGINT );
-        ps.setString( 4, DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME );
-        if( info.isFinalTypePrimitive() )
-        {
-            this.storePrimitiveUsingPS( ps, 5, null, info.getFinalType() );
-        }
-        else
-        {
-            this.storeVCClassIDUsingPS( ps, 5, null );
-        }
-        ps.addBatch();
-
-        return propertyPK + 1;
-    }
-
-    private Integer storeCollectionItems( Map<QualifiedName, PreparedStatement> qNameInsertPSs,
-                                          Collection<?> collection,
-                                          PreparedStatement insertAllQNamesPS,
-                                          String path,
-                                          PreparedStatement ps,
-                                          String tableName,
-                                          Integer propertyPK,
-                                          Long entityPK,
-                                          Integer parentPK,
-                                          Type finalType,
-                                          Boolean isFinalTypePrimitive
-    )
-        throws SQLException
-    {
-        Integer index = 0;
-        for( Object o : collection )
-        {
-            String itemPath = path + DBNames.QNAME_TABLE_COLLECTION_PATH_SEPARATOR + index;
-            if( o instanceof Collection<?> )
-            {
-                propertyPK = this.storeCollectionItems( qNameInsertPSs, (Collection<?>) o,
-                                                        insertAllQNamesPS, itemPath,
-                                                        ps, tableName, propertyPK, entityPK, parentPK, finalType,
-                                                        isFinalTypePrimitive );
-            }
-            else
-            {
-                propertyPK = this.storeCollectionItem( qNameInsertPSs, ps, insertAllQNamesPS, propertyPK,
-                                                       entityPK,
-                                                       parentPK, itemPath, o, isFinalTypePrimitive, finalType );
-                ps.addBatch();
-            }
-            ++index;
-        }
-        return propertyPK;
-    }
-
-    private Integer storeCollectionItem(
-        Map<QualifiedName, PreparedStatement> qNameInsertPSs, PreparedStatement ps,
-        PreparedStatement insertAllQNamesPS,
-        Integer propertyPK,
-        Long entityPK,
-        Integer parentPK,
-        String path,
-        Object item,
-        Boolean isFinalTypePrimitive,
-        Type finalType
-    )
-        throws SQLException
-    {
-        insertAllQNamesPS.setInt( 1, propertyPK );
-        insertAllQNamesPS.setLong( 2, entityPK );
-        insertAllQNamesPS.addBatch();
-
-        ps.setInt( 1, propertyPK );
-        ps.setLong( 2, entityPK );
-        ps.setObject( 3, parentPK, Types.INTEGER );
-        ps.setString( 4, path );
-        if( isFinalTypePrimitive )
-        {
-            this.storePrimitiveUsingPS( ps, 5, item, finalType );
-            ++propertyPK;
-        }
-        else
-        {
-            this.storeVCClassIDUsingPS( ps, 5, item );
-            propertyPK = this.storePropertiesOfVC( qNameInsertPSs, insertAllQNamesPS, propertyPK, entityPK, item );
-        }
-
-        return propertyPK;
-    }
-
-    private Integer storePrimitiveProperty(
-        Map<QualifiedName, PreparedStatement> qNameInsertPSs,
-        PreparedStatement insertAllQNamesPS,
-        Integer propertyPK,
-        Long entityPK,
-        QualifiedName qName,
-        Object property,
-        Integer parentQNameID
-    )
-        throws SQLException
-    {
-        QNameInfo info = this._state.qNameInfos().get().get( qName );
-        insertAllQNamesPS.setInt( 1, propertyPK );
-        insertAllQNamesPS.setLong( 2, entityPK );
-        insertAllQNamesPS.addBatch();
-
-        PreparedStatement ps = qNameInsertPSs.get( qName );
-        ps.setInt( 1, propertyPK );
-        ps.setLong( 2, entityPK );
-        ps.setObject( 3, parentQNameID, Types.INTEGER );
-        Type type = info.getFinalType();
-        this.storePrimitiveUsingPS( ps, 4, property, type );
-        ps.addBatch();
-
-        return propertyPK + 1;
-    }
-
-    private Integer storeValueCompositeProperty(
-        Map<QualifiedName, PreparedStatement> qNameInsertPSs,
-        PreparedStatement insertAllQNamesPS,
-        Integer propertyPK,
-        Long entityPK,
-        QualifiedName qName,
-        Object property,
-        Integer parentQNameID
-    )
-        throws SQLException
-    {
-
-        PreparedStatement ps = qNameInsertPSs.get( qName );
-        insertAllQNamesPS.setInt( 1, propertyPK );
-        insertAllQNamesPS.setLong( 2, entityPK );
-        insertAllQNamesPS.addBatch();
-
-        ps.setInt( 1, propertyPK );
-        ps.setLong( 2, entityPK );
-        ps.setObject( 3, parentQNameID, Types.INTEGER );
-        this.storeVCClassIDUsingPS( ps, 4, property );
-        ps.addBatch();
-
-        return this.storePropertiesOfVC( qNameInsertPSs, insertAllQNamesPS, propertyPK, entityPK,
-                                         property );
-    }
-
-    private Integer storePropertiesOfVC( Map<QualifiedName, PreparedStatement> qNameInsertPSs,
-                                         PreparedStatement insertAllQNamesPS,
-                                         Integer propertyPK,
-                                         Long entityPK,
-                                         Object property
-    )
-        throws SQLException
-    {
-        ValueDescriptor vDesc = this._qi4SPI.valueDescriptorFor( (ValueComposite) property );
-        StateHolder state = Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF.map( (ValueComposite) property ).state();
-        Integer originalPropertyPK = propertyPK;
-        ++propertyPK;
-        for( PropertyDescriptor pDesc : vDesc.state().properties() )
-        {
-
-            propertyPK = this.insertProperty(
-                qNameInsertPSs,
-                insertAllQNamesPS,
-                propertyPK,
-                entityPK,
-                pDesc.qualifiedName(),
-                state.propertyFor( pDesc.accessor() ).get(),
-                originalPropertyPK
-            );
-        }
-
-        return propertyPK;
-    }
-
-    private void storePrimitiveUsingPS( PreparedStatement ps, Integer nextFreeIndex,
-                                        Object primitive,
-                                        Type primitiveType
-    )
-        throws SQLException
-    {
-        if( primitiveType instanceof ParameterizedType )
-        {
-            primitiveType = ( (ParameterizedType) primitiveType ).getRawType();
-        }
-
-        if( primitiveType instanceof Class<?>
-            && Enum.class.isAssignableFrom( (Class<?>) primitiveType ) )
-        {
-            ps.setInt(
-                nextFreeIndex,
-                this._state.enumPKs().get().get(
-                QualifiedName.fromClass( (Class<?>) primitiveType, primitive.toString() ).toString() )
-            );
-        }
-        else
-        {
-            this._sqlTypeHelper.addPrimitiveToPS( ps, nextFreeIndex, primitive, primitiveType );
-        }
-    }
-
-    private void storeVCClassIDUsingPS( PreparedStatement ps, Integer nextFreeIndex, Object vc )
-        throws SQLException
-    {
-        if( vc == null )
-        {
-            ps.setNull( nextFreeIndex, Types.INTEGER );
-        }
-        else
-        {
-            ValueDescriptor vDesc = this._qi4SPI.valueDescriptorFor( vc );
-            Integer classID = this._state.usedClassesPKs().get().get( vDesc );
-            ps.setInt( nextFreeIndex, classID );
-        }
-    }
-
-    private void updateEntityInfoAndProperties( Connection connection,
-                                                Map<QualifiedName, PreparedStatement> qNameInsertPSs,
-                                                PreparedStatement insertAllQNamesPS,
-                                                PreparedStatement clearPropertiesPS,
-                                                PreparedStatement ps,
-                                                EntityState state,
-                                                Long entityPK,
-                                                Map<Long, Integer> qNamePKs
-    )
-        throws SQLException
-    {
-
-        this.clearAllEntitysQNames( clearPropertiesPS, entityPK );
-
-        // Update state
-        ps.setString( 1, state.identity().identity() );
-        ps.setTimestamp( 2, new Timestamp( state.lastModified() ) );
-        ps.setString( 3, state.version() );
-        ps.setString( 4, this._app.version() );
-        ps.setLong( 5, entityPK );
-        ps.addBatch();
-
-        Integer nextUsableQNamePK = this.insertPropertyQNames( connection, qNameInsertPSs, insertAllQNamesPS,
-                                                               state, entityPK );
-        qNamePKs.put( entityPK, nextUsableQNamePK );
-    }
-
-    private void insertProperties( Connection connection,
-                                   Map<QualifiedName, PreparedStatement> qNameInsertPSs,
-                                   PreparedStatement insertAllQNamesPS,
-                                   EntityState state,
-                                   Long entityPK,
-                                   Map<Long, Integer> qNamePKs
-    )
-        throws SQLException
-    {
-        Integer nextQnamePK = this.insertPropertyQNames( connection,
-                                                         qNameInsertPSs, insertAllQNamesPS,
-                                                         state, entityPK );
-        qNamePKs.put( entityPK, nextQnamePK );
-    }
-
-    private void removeEntity( EntityState state, PreparedStatement ps )
-        throws SQLException
-    {
-        ps.setString( 1, state.identity().identity() );
-        ps.addBatch();
-    }
-
-    private void insertPropertyType( Connection connection, PreparedStatement insertPropertyTypePS,
-                                     EntityState state, Long entityPK )
-        throws SQLException
-    {
-        for( Class<?> clazz : state.entityDescriptor().types() )
-        {
-            Integer typePK = this._state.entityTypePKs().get().get( clazz.getName() );
-            if( typePK == null )
-            {
-                throw new InternalError( "Tried to get entity : " + clazz
-                                         + ", but only aware of the following entities: " + this._state
-                    .entityTypePKs().get().keySet() );
-            }
-            insertPropertyTypePS.setLong( 1, entityPK );
-            insertPropertyTypePS.setInt( 2, typePK );
-            insertPropertyTypePS.addBatch();
-        }
-    }
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/AbstractSQLQuerying.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/AbstractSQLQuerying.java
deleted file mode 100644
index 79ad2e2..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/AbstractSQLQuerying.java
+++ /dev/null
@@ -1,1831 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.skeletons;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Member;
-import java.sql.ResultSet;
-import java.sql.Types;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Stack;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.grammar.AndSpecification;
-import org.qi4j.api.query.grammar.AssociationFunction;
-import org.qi4j.api.query.grammar.AssociationNotNullSpecification;
-import org.qi4j.api.query.grammar.AssociationNullSpecification;
-import org.qi4j.api.query.grammar.ComparisonSpecification;
-import org.qi4j.api.query.grammar.ContainsAllSpecification;
-import org.qi4j.api.query.grammar.ContainsSpecification;
-import org.qi4j.api.query.grammar.EqSpecification;
-import org.qi4j.api.query.grammar.GeSpecification;
-import org.qi4j.api.query.grammar.GtSpecification;
-import org.qi4j.api.query.grammar.LeSpecification;
-import org.qi4j.api.query.grammar.LtSpecification;
-import org.qi4j.api.query.grammar.ManyAssociationContainsSpecification;
-import org.qi4j.api.query.grammar.ManyAssociationFunction;
-import org.qi4j.api.query.grammar.MatchesSpecification;
-import org.qi4j.api.query.grammar.NeSpecification;
-import org.qi4j.api.query.grammar.NotSpecification;
-import org.qi4j.api.query.grammar.OrSpecification;
-import org.qi4j.api.query.grammar.OrderBy;
-import org.qi4j.api.query.grammar.OrderBy.Order;
-import org.qi4j.api.query.grammar.PropertyFunction;
-import org.qi4j.api.query.grammar.PropertyNotNullSpecification;
-import org.qi4j.api.query.grammar.PropertyNullSpecification;
-import org.qi4j.api.query.grammar.Variable;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.index.sql.support.api.SQLQuerying;
-import org.qi4j.index.sql.support.common.DBNames;
-import org.qi4j.index.sql.support.common.QNameInfo;
-import org.qi4j.index.sql.support.postgresql.PostgreSQLTypeHelper;
-import org.qi4j.spi.Qi4jSPI;
-import org.qi4j.spi.query.EntityFinderException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sql.generation.api.grammar.booleans.BooleanExpression;
-import org.sql.generation.api.grammar.builders.booleans.BooleanBuilder;
-import org.sql.generation.api.grammar.builders.booleans.InBuilder;
-import org.sql.generation.api.grammar.builders.query.GroupByBuilder;
-import org.sql.generation.api.grammar.builders.query.QueryBuilder;
-import org.sql.generation.api.grammar.builders.query.QuerySpecificationBuilder;
-import org.sql.generation.api.grammar.builders.query.TableReferenceBuilder;
-import org.sql.generation.api.grammar.common.NonBooleanExpression;
-import org.sql.generation.api.grammar.common.SQLFunctions;
-import org.sql.generation.api.grammar.common.SetQuantifier;
-import org.sql.generation.api.grammar.factories.BooleanFactory;
-import org.sql.generation.api.grammar.factories.ColumnsFactory;
-import org.sql.generation.api.grammar.factories.LiteralFactory;
-import org.sql.generation.api.grammar.factories.QueryFactory;
-import org.sql.generation.api.grammar.factories.TableReferenceFactory;
-import org.sql.generation.api.grammar.query.ColumnReference;
-import org.sql.generation.api.grammar.query.ColumnReferenceByName;
-import org.sql.generation.api.grammar.query.Ordering;
-import org.sql.generation.api.grammar.query.QueryExpression;
-import org.sql.generation.api.grammar.query.QuerySpecification;
-import org.sql.generation.api.grammar.query.TableReferenceByName;
-import org.sql.generation.api.grammar.query.joins.JoinType;
-import org.sql.generation.api.vendor.SQLVendor;
-
-public abstract class AbstractSQLQuerying
-    implements SQLQuerying
-{
-
-    @This
-    private SQLDBState _state;
-
-    @This
-    private PostgreSQLTypeHelper _typeHelper;
-
-    @Structure
-    private Module module;
-
-    @Structure
-    private Qi4jSPI spi;
-
-    private static class TraversedAssoOrManyAssoRef
-    {
-        private final AssociationFunction<?> _traversedAsso;
-        private final ManyAssociationFunction<?> _traversedManyAsso;
-        private final boolean _hasRefs;
-
-        private TraversedAssoOrManyAssoRef( AssociationFunction<?> func )
-        {
-            this( func.traversedAssociation(), func.traversedManyAssociation() );
-        }
-
-        private TraversedAssoOrManyAssoRef( PropertyFunction<?> func )
-        {
-            this( func.traversedAssociation(), func.traversedManyAssociation() );
-        }
-
-        private TraversedAssoOrManyAssoRef( ManyAssociationFunction<?> func )
-        {
-            this( func.traversedAssociation(), func.traversedManyAssociation() );
-        }
-
-        private TraversedAssoOrManyAssoRef( AssociationNullSpecification<?> spec )
-        {
-            this( spec.association(), null );
-        }
-
-        private TraversedAssoOrManyAssoRef( AssociationNotNullSpecification<?> spec )
-        {
-            this( spec.association(), null );
-        }
-
-        private TraversedAssoOrManyAssoRef( ManyAssociationContainsSpecification<?> spec )
-        {
-            this( null, spec.manyAssociation() );
-        }
-
-        private TraversedAssoOrManyAssoRef( AssociationFunction<?> traversedAsso,
-                                            ManyAssociationFunction<?> traversedManyAsso )
-        {
-            this._traversedAsso = traversedAsso;
-            this._traversedManyAsso = traversedManyAsso;
-            this._hasRefs = this._traversedAsso != null || this._traversedManyAsso != null;
-        }
-
-        private TraversedAssoOrManyAssoRef getTraversedAssociation()
-        {
-            return this._traversedAsso == null
-                   ? new TraversedAssoOrManyAssoRef( this._traversedManyAsso )
-                   : new TraversedAssoOrManyAssoRef( this._traversedAsso );
-        }
-
-        private AccessibleObject getAccessor()
-        {
-            return this._traversedAsso == null
-                   ? this._traversedManyAsso.accessor()
-                   : this._traversedAsso.accessor();
-        }
-
-        @Override
-        public String toString()
-        {
-            return "[hasRefs="
-                   + this._hasRefs
-                   + ", ref:"
-                   + ( this._hasRefs
-                       ? ( this._traversedAsso == null ? this._traversedManyAsso : this._traversedAsso )
-                       : "null" )
-                   + "]";
-        }
-    }
-
-    public static interface SQLBooleanCreator
-    {
-        public org.sql.generation.api.grammar.booleans.BooleanExpression getExpression(
-            BooleanFactory factory,
-            NonBooleanExpression left, NonBooleanExpression right );
-    }
-
-    private static interface BooleanExpressionProcessor
-    {
-        public QueryBuilder processBooleanExpression(
-            AbstractSQLQuerying thisObject,
-            Specification<Composite> expression,
-            Boolean negationActive,
-            SQLVendor vendor,
-            org.sql.generation.api.grammar.booleans.BooleanExpression entityTypeCondition,
-            Map<String, Object> variables,
-            List<Object> values,
-            List<Integer> valueSQLTypes
-        );
-    }
-
-    private static final Map<Class<? extends Specification>, SQLBooleanCreator> SQL_OPERATORS;
-
-    private static final Map<Class<? extends Specification>, JoinType> JOIN_STYLES;
-
-    private static final Map<Class<? extends Specification>, JoinType> NEGATED_JOIN_STYLES;
-
-    private static final Map<Class<?>, BooleanExpressionProcessor> EXPRESSION_PROCESSORS;
-
-    private static final String TABLE_NAME_PREFIX = "t";
-
-    private static final String TYPE_TABLE_SUFFIX = "_types";
-
-    private static final Logger LOGGER = LoggerFactory.getLogger( AbstractSQLQuerying.class.getName() );
-
-    static
-    {
-        SQL_OPERATORS = new HashMap<>( 9 );
-        SQL_OPERATORS.put( EqSpecification.class, new SQLBooleanCreator()
-        {
-            @Override
-            public org.sql.generation.api.grammar.booleans.BooleanExpression getExpression(
-                BooleanFactory factory,
-                NonBooleanExpression left, NonBooleanExpression right )
-            {
-                return factory.eq( left, right );
-            }
-        } );
-        SQL_OPERATORS.put( GeSpecification.class, new SQLBooleanCreator()
-        {
-            @Override
-            public org.sql.generation.api.grammar.booleans.BooleanExpression getExpression(
-                BooleanFactory factory,
-                NonBooleanExpression left, NonBooleanExpression right )
-            {
-                return factory.geq( left, right );
-            }
-        } );
-        SQL_OPERATORS.put( GtSpecification.class, new SQLBooleanCreator()
-        {
-            @Override
-            public org.sql.generation.api.grammar.booleans.BooleanExpression getExpression(
-                BooleanFactory factory,
-                NonBooleanExpression left, NonBooleanExpression right )
-            {
-                return factory.gt( left, right );
-            }
-        } );
-        SQL_OPERATORS.put( LeSpecification.class, new SQLBooleanCreator()
-        {
-            @Override
-            public org.sql.generation.api.grammar.booleans.BooleanExpression getExpression(
-                BooleanFactory factory,
-                NonBooleanExpression left, NonBooleanExpression right )
-            {
-                return factory.leq( left, right );
-            }
-        } );
-        SQL_OPERATORS.put( LtSpecification.class, new SQLBooleanCreator()
-        {
-            @Override
-            public org.sql.generation.api.grammar.booleans.BooleanExpression getExpression(
-                BooleanFactory factory,
-                NonBooleanExpression left, NonBooleanExpression right )
-            {
-                return factory.lt( left, right );
-            }
-        } );
-        SQL_OPERATORS.put( ManyAssociationContainsSpecification.class, new SQLBooleanCreator()
-        {
-            @Override
-            public org.sql.generation.api.grammar.booleans.BooleanExpression getExpression(
-                BooleanFactory factory,
-                NonBooleanExpression left, NonBooleanExpression right )
-            {
-                return factory.eq( left, right );
-            }
-        } );
-        SQL_OPERATORS.put( MatchesSpecification.class, new SQLBooleanCreator()
-        {
-            @Override
-            public org.sql.generation.api.grammar.booleans.BooleanExpression getExpression(
-                BooleanFactory factory,
-                NonBooleanExpression left, NonBooleanExpression right )
-            {
-                return factory.regexp( left, right );
-            }
-        } );
-        SQL_OPERATORS.put( ContainsSpecification.class, new SQLBooleanCreator()
-        {
-            @Override
-            public org.sql.generation.api.grammar.booleans.BooleanExpression getExpression(
-                BooleanFactory factory,
-                NonBooleanExpression left, NonBooleanExpression right )
-            {
-                return factory.eq( left, right );
-            }
-        } );
-        SQL_OPERATORS.put( ContainsAllSpecification.class, new SQLBooleanCreator()
-        {
-            @Override
-            public org.sql.generation.api.grammar.booleans.BooleanExpression getExpression(
-                BooleanFactory factory,
-                NonBooleanExpression left, NonBooleanExpression right )
-            {
-                return factory.eq( left, right );
-            }
-        } );
-
-        JOIN_STYLES = new HashMap<>( 13 );
-        JOIN_STYLES.put( EqSpecification.class, JoinType.INNER );
-        JOIN_STYLES.put( GeSpecification.class, JoinType.INNER );
-        JOIN_STYLES.put( GtSpecification.class, JoinType.INNER );
-        JOIN_STYLES.put( LeSpecification.class, JoinType.INNER );
-        JOIN_STYLES.put( LtSpecification.class, JoinType.INNER );
-        JOIN_STYLES.put( PropertyNullSpecification.class, JoinType.LEFT_OUTER );
-        JOIN_STYLES.put( PropertyNotNullSpecification.class, JoinType.INNER );
-        JOIN_STYLES.put( AssociationNullSpecification.class, JoinType.LEFT_OUTER );
-        JOIN_STYLES.put( AssociationNotNullSpecification.class, JoinType.INNER );
-        JOIN_STYLES.put( ManyAssociationContainsSpecification.class, JoinType.INNER );
-        JOIN_STYLES.put( MatchesSpecification.class, JoinType.INNER );
-        JOIN_STYLES.put( ContainsSpecification.class, JoinType.INNER );
-        JOIN_STYLES.put( ContainsAllSpecification.class, JoinType.INNER );
-
-        NEGATED_JOIN_STYLES = new HashMap<>( 13 );
-        NEGATED_JOIN_STYLES.put( EqSpecification.class, JoinType.LEFT_OUTER );
-        NEGATED_JOIN_STYLES.put( GeSpecification.class, JoinType.LEFT_OUTER );
-        NEGATED_JOIN_STYLES.put( GtSpecification.class, JoinType.LEFT_OUTER );
-        NEGATED_JOIN_STYLES.put( LeSpecification.class, JoinType.LEFT_OUTER );
-        NEGATED_JOIN_STYLES.put( LtSpecification.class, JoinType.LEFT_OUTER );
-        NEGATED_JOIN_STYLES.put( PropertyNullSpecification.class, JoinType.INNER );
-        NEGATED_JOIN_STYLES.put( PropertyNotNullSpecification.class, JoinType.LEFT_OUTER );
-        NEGATED_JOIN_STYLES.put( AssociationNullSpecification.class, JoinType.INNER );
-        NEGATED_JOIN_STYLES.put( AssociationNotNullSpecification.class, JoinType.LEFT_OUTER );
-        NEGATED_JOIN_STYLES.put( ManyAssociationContainsSpecification.class, JoinType.INNER );
-        NEGATED_JOIN_STYLES.put( MatchesSpecification.class, JoinType.LEFT_OUTER );
-        NEGATED_JOIN_STYLES.put( ContainsSpecification.class, JoinType.LEFT_OUTER );
-        NEGATED_JOIN_STYLES.put( ContainsAllSpecification.class, JoinType.LEFT_OUTER );
-
-        EXPRESSION_PROCESSORS = new HashMap<>( 17 );
-        EXPRESSION_PROCESSORS.put( AndSpecification.class, new BooleanExpressionProcessor()
-        {
-            @Override
-            public QueryBuilder processBooleanExpression(
-                AbstractSQLQuerying thisObject,
-                Specification<Composite> expression, Boolean negationActive, SQLVendor vendor,
-                BooleanExpression entityTypeCondition, Map<String, Object> variables,
-                List<Object> values,
-                List<Integer> valueSQLTypes )
-            {
-                QueryBuilder result = null;
-                AndSpecification conjunction = (AndSpecification) expression;
-                for( Specification<Composite> entitySpecification : conjunction.operands() )
-                {
-                    if( result == null )
-                    {
-                        result = thisObject.processBooleanExpression(
-                            entitySpecification,
-                            negationActive, vendor,
-                            entityTypeCondition, variables, values, valueSQLTypes );
-                    }
-                    else
-                    {
-                        result = result.intersect( thisObject.processBooleanExpression(
-                            entitySpecification, negationActive, vendor,
-                            entityTypeCondition, variables, values, valueSQLTypes )
-                            .createExpression() );
-                    }
-                }
-                return result;
-            }
-        } );
-        EXPRESSION_PROCESSORS.put( OrSpecification.class, new BooleanExpressionProcessor()
-        {
-            @Override
-            public QueryBuilder processBooleanExpression(
-                AbstractSQLQuerying thisObject,
-                Specification<Composite> expression, Boolean negationActive, SQLVendor vendor,
-                BooleanExpression entityTypeCondition, Map<String, Object> variables,
-                List<Object> values,
-                List<Integer> valueSQLTypes )
-            {
-                QueryBuilder result = null;
-                OrSpecification conjunction = (OrSpecification) expression;
-                for( Specification<Composite> entitySpecification : conjunction.operands() )
-                {
-                    if( result == null )
-                    {
-                        result = thisObject.processBooleanExpression(
-                            entitySpecification,
-                            negationActive, vendor,
-                            entityTypeCondition, variables, values, valueSQLTypes );
-                    }
-                    else
-                    {
-                        result
-                        = result.union( thisObject.processBooleanExpression(
-                            entitySpecification,
-                            negationActive, vendor,
-                            entityTypeCondition, variables, values, valueSQLTypes )
-                            .createExpression() );
-                    }
-                }
-                return result;
-            }
-        } );
-        EXPRESSION_PROCESSORS.put( NotSpecification.class, new BooleanExpressionProcessor()
-        {
-            @Override
-            public QueryBuilder processBooleanExpression(
-                AbstractSQLQuerying thisObject,
-                Specification<Composite> expression, Boolean negationActive, SQLVendor vendor,
-                BooleanExpression entityTypeCondition, Map<String, Object> variables,
-                List<Object> values,
-                List<Integer> valueSQLTypes )
-            {
-                return thisObject.processBooleanExpression(
-                    ( (NotSpecification) expression ).operand(), !negationActive, vendor,
-                    entityTypeCondition, variables, values, valueSQLTypes );
-            }
-        } );
-        EXPRESSION_PROCESSORS.put( MatchesSpecification.class, new BooleanExpressionProcessor()
-        {
-            @Override
-            public QueryBuilder processBooleanExpression(
-                AbstractSQLQuerying thisObject,
-                Specification<Composite> expression, Boolean negationActive, SQLVendor vendor,
-                BooleanExpression entityTypeCondition, Map<String, Object> variables,
-                List<Object> values,
-                List<Integer> valueSQLTypes )
-            {
-                return thisObject.processMatchesPredicate( (MatchesSpecification) expression,
-                                                           negationActive, vendor,
-                                                           entityTypeCondition, variables, values, valueSQLTypes );
-            }
-        } );
-        EXPRESSION_PROCESSORS.put( ManyAssociationContainsSpecification.class, new BooleanExpressionProcessor()
-        {
-            @Override
-            public QueryBuilder processBooleanExpression(
-                AbstractSQLQuerying thisObject,
-                Specification<Composite> expression, Boolean negationActive,
-                SQLVendor vendor,
-                BooleanExpression entityTypeCondition, Map<String, Object> variables,
-                List<Object> values,
-                List<Integer> valueSQLTypes )
-            {
-                return thisObject.processManyAssociationContainsPredicate(
-                    (ManyAssociationContainsSpecification<?>) expression, negationActive,
-                    vendor, entityTypeCondition,
-                    variables, values, valueSQLTypes );
-            }
-        } );
-        EXPRESSION_PROCESSORS.put( PropertyNullSpecification.class, new BooleanExpressionProcessor()
-        {
-            @Override
-            public QueryBuilder processBooleanExpression(
-                AbstractSQLQuerying thisObject,
-                Specification<Composite> expression, Boolean negationActive,
-                SQLVendor vendor,
-                BooleanExpression entityTypeCondition, Map<String, Object> variables,
-                List<Object> values,
-                List<Integer> valueSQLTypes )
-            {
-                return thisObject.processPropertyNullPredicate(
-                    (PropertyNullSpecification<?>) expression, negationActive,
-                    vendor, entityTypeCondition );
-            }
-        } );
-        EXPRESSION_PROCESSORS.put( PropertyNotNullSpecification.class, new BooleanExpressionProcessor()
-        {
-            @Override
-            public QueryBuilder processBooleanExpression(
-                AbstractSQLQuerying thisObject,
-                Specification<Composite> expression, Boolean negationActive,
-                SQLVendor vendor,
-                BooleanExpression entityTypeCondition, Map<String, Object> variables,
-                List<Object> values,
-                List<Integer> valueSQLTypes )
-            {
-                return thisObject.processPropertyNotNullPredicate(
-                    (PropertyNotNullSpecification<?>) expression, negationActive,
-                    vendor, entityTypeCondition );
-            }
-        } );
-        EXPRESSION_PROCESSORS.put( AssociationNullSpecification.class, new BooleanExpressionProcessor()
-        {
-            @Override
-            public QueryBuilder processBooleanExpression(
-                AbstractSQLQuerying thisObject,
-                Specification<Composite> expression, Boolean negationActive,
-                SQLVendor vendor,
-                BooleanExpression entityTypeCondition, Map<String, Object> variables,
-                List<Object> values,
-                List<Integer> valueSQLTypes )
-            {
-                return thisObject.processAssociationNullPredicate(
-                    (AssociationNullSpecification<?>) expression, negationActive,
-                    vendor, entityTypeCondition );
-            }
-        } );
-        EXPRESSION_PROCESSORS.put( AssociationNotNullSpecification.class, new BooleanExpressionProcessor()
-        {
-            @Override
-            public QueryBuilder processBooleanExpression( AbstractSQLQuerying thisObject,
-                                                          Specification<Composite> expression, Boolean negationActive,
-                                                          SQLVendor vendor,
-                                                          BooleanExpression entityTypeCondition, Map<String, Object> variables,
-                                                          List<Object> values,
-                                                          List<Integer> valueSQLTypes )
-            {
-                return thisObject.processAssociationNotNullPredicate(
-                    (AssociationNotNullSpecification<?>) expression, negationActive,
-                    vendor, entityTypeCondition );
-            }
-        } );
-        EXPRESSION_PROCESSORS.put( ContainsSpecification.class, new BooleanExpressionProcessor()
-        {
-            @Override
-            public QueryBuilder processBooleanExpression(
-                AbstractSQLQuerying thisObject,
-                Specification<Composite> expression, Boolean negationActive, SQLVendor vendor,
-                BooleanExpression entityTypeCondition, Map<String, Object> variables,
-                List<Object> values,
-                List<Integer> valueSQLTypes )
-            {
-                return thisObject.processContainsPredicate( (ContainsSpecification<?>) expression,
-                                                            negationActive, vendor,
-                                                            entityTypeCondition, variables, values, valueSQLTypes );
-            }
-        } );
-        EXPRESSION_PROCESSORS.put( ContainsAllSpecification.class, new BooleanExpressionProcessor()
-        {
-            @Override
-            public QueryBuilder processBooleanExpression(
-                AbstractSQLQuerying thisObject,
-                Specification<Composite> expression, Boolean negationActive, SQLVendor vendor,
-                BooleanExpression entityTypeCondition, Map<String, Object> variables,
-                List<Object> values,
-                List<Integer> valueSQLTypes )
-            {
-                return thisObject.processContainsAllPredicate(
-                    (ContainsAllSpecification<?>) expression, negationActive,
-                    vendor, entityTypeCondition, variables, values, valueSQLTypes );
-            }
-        } );
-        BooleanExpressionProcessor comparisonProcessor = new BooleanExpressionProcessor()
-        {
-            @Override
-            public QueryBuilder processBooleanExpression(
-                AbstractSQLQuerying thisObject,
-                Specification<Composite> expression, Boolean negationActive, SQLVendor vendor,
-                BooleanExpression entityTypeCondition, Map<String, Object> variables,
-                List<Object> values,
-                List<Integer> valueSQLTypes )
-            {
-                return thisObject.processComparisonPredicate(
-                    (ComparisonSpecification<?>) expression, negationActive, vendor,
-                    entityTypeCondition, variables, values, valueSQLTypes );
-            }
-        };
-        EXPRESSION_PROCESSORS.put( EqSpecification.class, comparisonProcessor );
-        EXPRESSION_PROCESSORS.put( NeSpecification.class, comparisonProcessor );
-        EXPRESSION_PROCESSORS.put( GeSpecification.class, comparisonProcessor );
-        EXPRESSION_PROCESSORS.put( GtSpecification.class, comparisonProcessor );
-        EXPRESSION_PROCESSORS.put( LeSpecification.class, comparisonProcessor );
-        EXPRESSION_PROCESSORS.put( LtSpecification.class, comparisonProcessor );
-    }
-
-    private interface WhereClauseProcessor
-    {
-        public void processWhereClause( QuerySpecificationBuilder builder,
-                                        BooleanBuilder afterWhere,
-                                        JoinType joinStyle, Integer firstTableIndex, Integer lastTableIndex );
-    }
-
-    private static class PropertyNullWhereClauseProcessor
-        implements WhereClauseProcessor
-    {
-        private final boolean negationActive;
-        private final SQLVendor vendor;
-        private final SQLDBState state;
-        private final PropertyFunction<?> propFunction;
-
-        private PropertyNullWhereClauseProcessor( SQLDBState pState, SQLVendor pVendor,
-                                                  PropertyFunction<?> pPropFunction,
-                                                  boolean pNegationActive )
-        {
-            this.state = pState;
-            this.vendor = pVendor;
-            this.negationActive = pNegationActive;
-            this.propFunction = pPropFunction;
-        }
-
-        @Override
-        public void processWhereClause( QuerySpecificationBuilder builder,
-                                        BooleanBuilder afterWhere,
-                                        JoinType joinStyle, Integer firstTableIndex, Integer lastTableIndex )
-        {
-            if( !this.negationActive )
-            {
-                ColumnsFactory c = this.vendor.getColumnsFactory();
-                BooleanFactory b = this.vendor.getBooleanFactory();
-
-                QNameInfo info = this.state
-                    .qNameInfos()
-                    .get()
-                    .get(
-                        QualifiedName.fromAccessor( this.propFunction.accessor() ) );
-                String colName;
-                if( info.getCollectionDepth() > 0 )
-                {
-                    colName = DBNames.ALL_QNAMES_TABLE_PK_COLUMN_NAME;
-                }
-                else
-                {
-                    colName = DBNames.QNAME_TABLE_VALUE_COLUMN_NAME;
-                }
-                // Last table column might be null because of left joins
-                builder.getWhere().reset(
-                    b.isNull( c.colName( TABLE_NAME_PREFIX + lastTableIndex, colName ) ) );
-            }
-        }
-    }
-
-    private static class AssociationNullWhereClauseProcessor
-        implements WhereClauseProcessor
-    {
-        private final boolean negationActive;
-        private final SQLVendor vendor;
-
-        private AssociationNullWhereClauseProcessor( SQLVendor pVendor, boolean pNegationActive )
-        {
-            this.vendor = pVendor;
-            this.negationActive = pNegationActive;
-        }
-
-        @Override
-        public void processWhereClause( QuerySpecificationBuilder builder,
-                                        BooleanBuilder afterWhere,
-                                        JoinType joinStyle, Integer firstTableIndex, Integer lastTableIndex )
-        {
-            if( !negationActive )
-            {
-                ColumnsFactory c = vendor.getColumnsFactory();
-                BooleanFactory b = vendor.getBooleanFactory();
-
-                // Last table column might be null because of left joins
-                builder.getWhere().reset(
-                    b.isNull( c.colName( TABLE_NAME_PREFIX + lastTableIndex,
-                                         DBNames.QNAME_TABLE_VALUE_COLUMN_NAME ) ) );
-            }
-        }
-    }
-
-    private static class ModifiableInt
-    {
-        private int _int;
-
-        private ModifiableInt( Integer integer )
-        {
-            this._int = integer;
-        }
-
-        private int getInt()
-        {
-            return this._int;
-        }
-
-        private void setInt( int integer )
-        {
-            this._int = integer;
-        }
-
-        @Override
-        public String toString()
-        {
-            return Integer.toString( this._int );
-        }
-    }
-
-    private static class QNameJoin
-    {
-        private final QualifiedName _sourceQName;
-
-        private final QualifiedName _targetQName;
-
-        private final Integer _sourceTableIndex;
-
-        private final Integer _targetTableIndex;
-
-        private QNameJoin( QualifiedName sourceQName, QualifiedName targetQName,
-                           Integer sourceTableIndex,
-                           Integer targetTableIndex )
-        {
-            this._sourceQName = sourceQName;
-            this._targetQName = targetQName;
-            this._sourceTableIndex = sourceTableIndex;
-            this._targetTableIndex = targetTableIndex;
-        }
-
-        private QualifiedName getSourceQName()
-        {
-            return this._sourceQName;
-        }
-
-        private QualifiedName getTargetQName()
-        {
-            return this._targetQName;
-        }
-
-        private Integer getSourceTableIndex()
-        {
-            return this._sourceTableIndex;
-        }
-
-        private Integer getTargetTableIndex()
-        {
-            return this._targetTableIndex;
-        }
-    }
-
-    @Override
-    public Integer getResultSetType( Integer firstResult, Integer maxResults )
-    {
-        return ResultSet.TYPE_FORWARD_ONLY;
-    }
-
-    @Override
-    public Boolean isFirstResultSettingSupported()
-    {
-        return true;
-    }
-
-    @Uses
-    private ServiceDescriptor descriptor;
-
-    @Override
-    public String constructQuery( Class<?> resultType, //
-                                  Specification<Composite> whereClause, //
-                                  OrderBy[] orderBySegments, //
-                                  Integer firstResult, //
-                                  Integer maxResults, //
-                                  Map<String, Object> variables, //
-                                  List<Object> values, //
-                                  List<Integer> valueSQLTypes, //
-                                  Boolean countOnly //
-    )
-        throws EntityFinderException
-    {
-        SQLVendor vendor = this.descriptor.metaInfo( SQLVendor.class );
-
-        QueryFactory q = vendor.getQueryFactory();
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-        LiteralFactory l = vendor.getLiteralFactory();
-        ColumnsFactory c = vendor.getColumnsFactory();
-
-        ColumnReference mainColumn = c.colName( TABLE_NAME_PREFIX + "0", DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME );
-        if( countOnly )
-        {
-            mainColumn = c.colExp( l.func( SQLFunctions.COUNT, mainColumn ) );
-        }
-
-        QueryBuilder innerBuilder = this.processBooleanExpression(
-            whereClause, false, vendor,
-            this.createTypeCondition( resultType, vendor ), variables, values, valueSQLTypes );
-
-        QuerySpecificationBuilder mainQuery = q.querySpecificationBuilder();
-        mainQuery.getSelect().addUnnamedColumns( mainColumn );
-        mainQuery.getFrom().addTableReferences(
-            t.tableBuilder( t.table( q.createQuery( innerBuilder.createExpression() ),
-                                     t.tableAlias( TABLE_NAME_PREFIX + "0" ) ) ) );
-
-        this.processOrderBySegments( orderBySegments, vendor, mainQuery );
-
-        QueryExpression finalMainQuery = this.finalizeQuery(
-            vendor, mainQuery, resultType, whereClause,
-            orderBySegments, firstResult, maxResults, variables, values, valueSQLTypes,
-            countOnly );
-
-        String result = vendor.toString( finalMainQuery );
-
-        LOGGER.info( "SQL query:\n" + result );
-        return result;
-    }
-
-    protected org.sql.generation.api.grammar.booleans.BooleanExpression createTypeCondition(
-        Class<?> resultType,
-        SQLVendor vendor )
-    {
-        BooleanFactory b = vendor.getBooleanFactory();
-        LiteralFactory l = vendor.getLiteralFactory();
-        ColumnsFactory c = vendor.getColumnsFactory();
-
-        List<Integer> typeIDs = this.getEntityTypeIDs( resultType );
-        InBuilder in = b.inBuilder( c.colName( TABLE_NAME_PREFIX + TYPE_TABLE_SUFFIX,
-                                               DBNames.ENTITY_TYPES_TABLE_PK_COLUMN_NAME ) );
-        for( Integer i : typeIDs )
-        {
-            in.addValues( l.n( i ) );
-        }
-
-        return in.createExpression();
-    }
-
-    protected abstract QueryExpression finalizeQuery(
-        SQLVendor sqlVendor, QuerySpecificationBuilder specBuilder,
-        Class<?> resultType,
-        Specification<Composite> whereClause,
-        OrderBy[] orderBySegments,
-        Integer firstResult,
-        Integer maxResults,
-        Map<String, Object> variables,
-        List<Object> values,
-        List<Integer> valueSQLTypes,
-        Boolean countOnly );
-
-    protected QueryBuilder processBooleanExpression(
-        Specification<Composite> expression,
-        Boolean negationActive,
-        SQLVendor vendor,
-        org.sql.generation.api.grammar.booleans.BooleanExpression entityTypeCondition,
-        Map<String, Object> variables,
-        List<Object> values,
-        List<Integer> valueSQLTypes
-    )
-    {
-        QueryBuilder result = null;
-        if( expression == null )
-        {
-            QueryFactory q = vendor.getQueryFactory();
-            result = q.queryBuilder(
-                this.selectAllEntitiesOfCorrectType( vendor, entityTypeCondition ).createExpression() );
-        }
-        else
-        {
-            if( EXPRESSION_PROCESSORS.containsKey( expression.getClass() ) )
-            {
-                result = EXPRESSION_PROCESSORS.get( expression.getClass() ).processBooleanExpression(
-                    this, expression,
-                    negationActive, vendor, entityTypeCondition, variables, values,
-                    valueSQLTypes );
-            }
-            else
-            {
-                throw new UnsupportedOperationException( "Expression " + expression + " of type "
-                                                         + expression.getClass() + " is not supported" );
-            }
-        }
-        return result;
-    }
-
-    protected QuerySpecificationBuilder selectAllEntitiesOfCorrectType(
-        SQLVendor vendor,
-        org.sql.generation.api.grammar.booleans.BooleanExpression entityTypeCondition )
-    {
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-
-        String tableAlias = TABLE_NAME_PREFIX + "0";
-        TableReferenceBuilder from = t.tableBuilder( t.table(
-            t.tableName( this._state.schemaName().get(), DBNames.ENTITY_TABLE_NAME ),
-            t.tableAlias( tableAlias ) ) );
-
-        this.addTypeJoin( vendor, from, 0 );
-
-        QuerySpecificationBuilder query = this.getBuilderForPredicate( vendor, tableAlias );
-        query.getFrom().addTableReferences( from );
-        query.getWhere().reset( entityTypeCondition );
-
-        return query;
-    }
-
-    protected QueryBuilder processMatchesPredicate(
-        final MatchesSpecification predicate,
-        final Boolean negationActive,
-        final SQLVendor vendor,
-        org.sql.generation.api.grammar.booleans.BooleanExpression entityTypeCondition,
-        final Map<String, Object> variables, final List<Object> values,
-        final List<Integer> valueSQLTypes )
-    {
-        return this.singleQuery(
-            predicate,
-            predicate.property(),
-            null,
-            null,
-            negationActive,
-            vendor,
-            entityTypeCondition,
-            new WhereClauseProcessor()
-        {
-
-            @Override
-            public void processWhereClause( QuerySpecificationBuilder builder,
-                                            BooleanBuilder afterWhere,
-                                            JoinType joinStyle, Integer firstTableIndex, Integer lastTableIndex )
-            {
-                LiteralFactory l = vendor.getLiteralFactory();
-                ColumnsFactory c = vendor.getColumnsFactory();
-
-                builder.getWhere().reset(
-                    vendor.getBooleanFactory().regexp(
-                        c.colName( TABLE_NAME_PREFIX + lastTableIndex,
-                                   DBNames.QNAME_TABLE_VALUE_COLUMN_NAME ),
-                        l.param() ) );
-
-                Object value = predicate.value();
-                if( value instanceof Variable )
-                {
-                    value = variables.get( ( (Variable) value ).variableName() );
-                }
-                values.add( translateJavaRegexpToPGSQLRegexp( value.toString() ) );
-                valueSQLTypes.add( Types.VARCHAR );
-            }
-            } //
-        );
-    }
-
-    protected QueryBuilder processComparisonPredicate(
-        final ComparisonSpecification<?> predicate,
-        final Boolean negationActive, final SQLVendor vendor,
-        org.sql.generation.api.grammar.booleans.BooleanExpression entityTypeCondition,
-        final Map<String, Object> variables,
-        final List<Object> values, final List<Integer> valueSQLTypes )
-    {
-        return this.singleQuery(
-            predicate,
-            predicate.property(),
-            null,
-            null,
-            negationActive,
-            vendor,
-            entityTypeCondition,
-            new WhereClauseProcessor()
-        {
-
-            @Override
-            public void processWhereClause( QuerySpecificationBuilder builder,
-                                            BooleanBuilder afterWhere,
-                                            JoinType joinStyle, Integer firstTableIndex, Integer lastTableIndex )
-            {
-                QualifiedName qName
-                              = QualifiedName.fromAccessor( predicate.property().accessor() );
-                String columnName;
-                if( qName.type().equals( Identity.class.getName() ) )
-                {
-                    columnName = DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME;
-                }
-                else
-                {
-                    columnName = DBNames.QNAME_TABLE_VALUE_COLUMN_NAME;
-                }
-                Object value = predicate.value();
-                modifyFromClauseAndWhereClauseToGetValue(
-                    qName, value, predicate,
-                    negationActive, lastTableIndex,
-                    new ModifiableInt( lastTableIndex ), columnName,
-                    DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME, vendor,
-                    builder.getWhere(), afterWhere,
-                    builder.getFrom().getTableReferences().iterator().next(),
-                    builder.getGroupBy(),
-                    builder.getHaving(), new ArrayList<QNameJoin>(), variables, values,
-                    valueSQLTypes );
-            }
-
-            } //
-        );
-    }
-
-    protected QueryBuilder processManyAssociationContainsPredicate(
-        final ManyAssociationContainsSpecification<?> predicate, final Boolean negationActive,
-        final SQLVendor vendor,
-        org.sql.generation.api.grammar.booleans.BooleanExpression entityTypeCondition,
-        Map<String, Object> variables,
-        final List<Object> values, final List<Integer> valueSQLTypes )
-    {
-        return this.singleQuery(
-            predicate,
-            null,
-            new TraversedAssoOrManyAssoRef( predicate ), // not sure about this, was 'null' before but I think this is needed.
-            true,
-            negationActive,
-            vendor,
-            entityTypeCondition,
-            new WhereClauseProcessor()
-        {
-
-            @Override
-            public void processWhereClause( QuerySpecificationBuilder builder,
-                                            BooleanBuilder afterWhere,
-                                            JoinType joinStyle, Integer firstTableIndex, Integer lastTableIndex )
-            {
-                LiteralFactory l = vendor.getLiteralFactory();
-                ColumnsFactory c = vendor.getColumnsFactory();
-                BooleanFactory b = vendor.getBooleanFactory();
-
-                builder.getWhere().reset(
-                    getOperator( predicate ).getExpression(
-                        b,
-                        c.colName( TABLE_NAME_PREFIX + lastTableIndex,
-                                   DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME ),
-                        l.param() ) );
-
-                Object value = predicate.value();
-                // TODO Is it really certain that this value is always instance of
-                // EntityComposite?
-                if( value instanceof EntityComposite )
-                {
-                    value = module.currentUnitOfWork().get(
-                        (EntityComposite) value ).identity().get();
-                }
-                else
-                {
-                    value = value.toString();
-                }
-                values.add( value );
-                valueSQLTypes.add( Types.VARCHAR );
-            }
-            }
-        );
-    }
-
-    protected QueryBuilder processPropertyNullPredicate(
-        final PropertyNullSpecification<?> predicate,
-        final Boolean negationActive, final SQLVendor vendor,
-        org.sql.generation.api.grammar.booleans.BooleanExpression entityTypeCondition )
-    {
-        return this.singleQuery(
-            predicate,
-            predicate.property(),
-            null,
-            null,
-            negationActive,
-            vendor,
-            entityTypeCondition,
-            new PropertyNullWhereClauseProcessor( this._state, vendor, predicate.property(), negationActive )
-        );
-    }
-
-    protected QueryBuilder processPropertyNotNullPredicate(
-        PropertyNotNullSpecification<?> predicate,
-        boolean negationActive, SQLVendor vendor,
-        org.sql.generation.api.grammar.booleans.BooleanExpression entityTypeCondition )
-    {
-        return this.singleQuery(
-            predicate,
-            predicate.property(),
-            null,
-            null,
-            negationActive,
-            vendor,
-            entityTypeCondition,
-            new PropertyNullWhereClauseProcessor( this._state, vendor, predicate.property(), !negationActive )
-        );
-    }
-
-    protected QueryBuilder processAssociationNullPredicate(
-        final AssociationNullSpecification<?> predicate,
-        final Boolean negationActive, final SQLVendor vendor,
-        org.sql.generation.api.grammar.booleans.BooleanExpression entityTypeCondition )
-    {
-        return this.singleQuery(
-            predicate, //
-            null, //
-            new TraversedAssoOrManyAssoRef( predicate ), //
-            false, //
-            negationActive, //
-            vendor, //
-            entityTypeCondition, //
-            new AssociationNullWhereClauseProcessor( vendor, negationActive )
-        );
-    }
-
-    protected QueryBuilder processAssociationNotNullPredicate(
-        final AssociationNotNullSpecification<?> predicate,
-        final Boolean negationActive, final SQLVendor vendor,
-        org.sql.generation.api.grammar.booleans.BooleanExpression entityTypeCondition )
-    {
-        return this.singleQuery(
-            predicate, //
-            null, //
-            new TraversedAssoOrManyAssoRef( predicate ), //
-            false, //
-            negationActive, //
-            vendor, //
-            entityTypeCondition, //
-            new AssociationNullWhereClauseProcessor( vendor, !negationActive )
-        );
-    }
-
-    protected QueryBuilder processContainsPredicate(
-        final ContainsSpecification<?> predicate,
-        final Boolean negationActive, final SQLVendor vendor,
-        org.sql.generation.api.grammar.booleans.BooleanExpression entityTypeCondition,
-        final Map<String, Object> variables,
-        final List<Object> values, final List<Integer> valueSQLTypes )
-    {
-        // Path: Top.* (star without braces), value = value
-        // ASSUMING value is NOT collection (ie, find all entities, which collection property has
-        // value x as leaf item,
-        // no matter collection depth)
-        QuerySpecification contains = this.constructQueryForPredicate(
-            predicate, //
-            predicate.collectionProperty(), //
-            null, //
-            null, //
-            false, //
-            vendor, //
-            entityTypeCondition, //
-            new WhereClauseProcessor()
-        {
-            @Override
-            public void processWhereClause( QuerySpecificationBuilder builder,
-                                            BooleanBuilder afterWhere,
-                                            JoinType joinStyle, Integer firstTableIndex, Integer lastTableIndex )
-            {
-                BooleanFactory b = vendor.getBooleanFactory();
-                LiteralFactory l = vendor.getLiteralFactory();
-                ColumnsFactory c = vendor.getColumnsFactory();
-
-                builder.getWhere().reset(
-                    b.regexp( c.colName( TABLE_NAME_PREFIX + lastTableIndex,
-                                         DBNames.QNAME_TABLE_COLLECTION_PATH_COLUMN_NAME ), l
-                        .s( DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME + ".*{1,}" ) ) );
-
-                Object value = predicate.value();
-                if( value instanceof Collection<?> )
-                {
-                    throw new IllegalArgumentException(
-                        "ContainsPredicate may have only either primitive or value composite as value." );
-                }
-                BooleanBuilder condition = b.booleanBuilder();
-                modifyFromClauseAndWhereClauseToGetValue(
-                    QualifiedName.fromAccessor( predicate.collectionProperty().accessor() ), value, predicate,
-                    false, lastTableIndex, new ModifiableInt( lastTableIndex ),
-                    DBNames.QNAME_TABLE_VALUE_COLUMN_NAME,
-                    DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME,
-                    vendor, condition, afterWhere, builder.getFrom().getTableReferences()
-                    .iterator().next(),
-                    builder.getGroupBy(), builder.getHaving(), new ArrayList<QNameJoin>(),
-                    variables, values, valueSQLTypes );
-                builder.getWhere().and( condition.createExpression() );
-            }
-            } //
-        );
-
-        return this.finalizeContainsQuery( vendor, contains, entityTypeCondition, negationActive );
-    }
-
-    protected QueryBuilder finalizeContainsQuery(
-        SQLVendor vendor, QuerySpecification contains,
-        org.sql.generation.api.grammar.booleans.BooleanExpression entityTypeCondition,
-        Boolean negationActive )
-    {
-        QueryFactory q = vendor.getQueryFactory();
-        QueryBuilder result;
-
-        if( negationActive )
-        {
-            result = q.queryBuilder(
-                this.selectAllEntitiesOfCorrectType( vendor, entityTypeCondition )
-                .createExpression() ).except(
-                    contains );
-        }
-        else
-        {
-            result = q.queryBuilder( contains );
-        }
-
-        return result;
-    }
-
-    protected QueryBuilder processContainsAllPredicate(
-        final ContainsAllSpecification<?> predicate, final Boolean negationActive,
-        final SQLVendor vendor,
-        org.sql.generation.api.grammar.booleans.BooleanExpression entityTypeCondition,
-        final Map<String, Object> variables, final List<Object> values,
-        final List<Integer> valueSQLTypes )
-    {
-        // has all leaf items in specified collection
-
-        QuerySpecification contains = this.constructQueryForPredicate(
-            predicate, //
-            predicate.collectionProperty(), //
-            null, //
-            null, //
-            false, //
-            vendor, //
-            entityTypeCondition, //
-            new WhereClauseProcessor()
-        {
-
-            @Override
-            public void processWhereClause( QuerySpecificationBuilder builder,
-                                            BooleanBuilder afterWhere,
-                                            JoinType joinStyle, Integer firstTableIndex, Integer lastTableIndex )
-            {
-                BooleanFactory b = vendor.getBooleanFactory();
-                LiteralFactory l = vendor.getLiteralFactory();
-                ColumnsFactory c = vendor.getColumnsFactory();
-
-                Iterable<?> collection = predicate.containedValues();
-                List<QNameJoin> joins = new ArrayList<>();
-                for( Object value : collection )
-                {
-                    if( value instanceof Collection<?> )
-                    {
-                        throw new IllegalArgumentException(
-                            "ContainsAllPredicate may not have nested collections as value." );
-                    }
-
-                    BooleanBuilder conditionForItem = b.booleanBuilder(
-                        b.regexp( c.colName( TABLE_NAME_PREFIX + lastTableIndex,
-                                             DBNames.QNAME_TABLE_COLLECTION_PATH_COLUMN_NAME ),
-                                  l.s( DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME + ".*{1,}" ) ) );
-                    modifyFromClauseAndWhereClauseToGetValue(
-                        QualifiedName.fromAccessor( predicate.collectionProperty().accessor() ),
-                        value, predicate, false, lastTableIndex,
-                        new ModifiableInt( lastTableIndex ),
-                        DBNames.QNAME_TABLE_VALUE_COLUMN_NAME,
-                        DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME, vendor,
-                        conditionForItem, afterWhere,
-                        builder.getFrom().getTableReferences().iterator().next(),
-                        builder.getGroupBy(), builder.getHaving(),
-                        joins, variables, values, valueSQLTypes );
-                    builder.getWhere().or( conditionForItem.createExpression() );
-
-                }
-
-                builder.getHaving()
-                    .and(
-                        b.geq(
-                            l.func( "COUNT", c.colName( TABLE_NAME_PREFIX + lastTableIndex,
-                                                        DBNames.QNAME_TABLE_VALUE_COLUMN_NAME ) ),
-                            l.n( Iterables.count( collection ) ) ) );
-            }
-
-            } //
-        );
-
-        return this.finalizeContainsQuery( vendor, contains, entityTypeCondition, negationActive );
-    }
-
-    protected QueryBuilder singleQuery(
-        Specification<Composite> predicate, //
-        PropertyFunction<?> propRef, //
-        TraversedAssoOrManyAssoRef assoRef, //
-        Boolean includeLastAssoPathTable, //
-        Boolean negationActive, //
-        SQLVendor vendor, //
-        org.sql.generation.api.grammar.booleans.BooleanExpression entityTypeCondition, //
-        WhereClauseProcessor whereClauseGenerator//
-    )
-    {
-        return vendor.getQueryFactory().queryBuilder(
-            this.constructQueryForPredicate( predicate, propRef, assoRef, includeLastAssoPathTable,
-                                             negationActive,
-                                             vendor, entityTypeCondition, whereClauseGenerator ) );
-    }
-
-    protected QuerySpecification constructQueryForPredicate(
-        Specification<Composite> predicate, //
-        PropertyFunction<?> propRef, //
-        TraversedAssoOrManyAssoRef assoRef, //
-        Boolean includeLastAssoPathTable, //
-        Boolean negationActive, //
-        SQLVendor vendor, //
-        org.sql.generation.api.grammar.booleans.BooleanExpression entityTypeCondition, //
-        WhereClauseProcessor whereClauseGenerator//
-    )
-    {
-        Integer startingIndex = 0;
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-
-        QuerySpecificationBuilder builder = this.getBuilderForPredicate( vendor, TABLE_NAME_PREFIX + startingIndex );
-        TableReferenceBuilder from = t.tableBuilder( t.table(
-            t.tableName( this._state.schemaName().get(), DBNames.ENTITY_TABLE_NAME ),
-            t.tableAlias( TABLE_NAME_PREFIX + startingIndex ) ) );
-
-        this.addTypeJoin( vendor, from, startingIndex );
-
-        Integer lastTableIndex = null;
-        JoinType joinStyle = this.getTableJoinStyle( predicate, negationActive );
-        if( propRef == null && assoRef != null && assoRef._hasRefs )
-        {
-            lastTableIndex = this.traverseAssociationPath( assoRef, startingIndex, startingIndex + 1, vendor, from,
-                                                           joinStyle, includeLastAssoPathTable );
-        }
-        else if( assoRef == null || !assoRef._hasRefs )
-        {
-            lastTableIndex = this.traversePropertyPath( propRef, startingIndex, startingIndex + 1, vendor, from,
-                                                        joinStyle );
-        }
-        else
-        {
-            throw new InternalError(
-                "Can not have both property reference and association reference (non-)nulls [propRef=" + propRef
-                + ", assoRef=" + assoRef + ", predicate=" + predicate + "]." );
-        }
-
-        builder.getFrom().addTableReferences( from );
-
-        BooleanBuilder afterWhere = vendor.getBooleanFactory().booleanBuilder();
-        whereClauseGenerator.processWhereClause( builder, afterWhere, joinStyle, startingIndex, lastTableIndex );
-
-        BooleanBuilder where = builder.getWhere();
-        if( negationActive )
-        {
-            where.not();
-        }
-        where.and( afterWhere.createExpression() );
-
-        where.and( entityTypeCondition );
-
-        builder.trimGroupBy();
-
-        return builder.createExpression();
-    }
-
-    protected void addTypeJoin( SQLVendor vendor, TableReferenceBuilder from, int startingIndex )
-    {
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-        BooleanFactory b = vendor.getBooleanFactory();
-        ColumnsFactory c = vendor.getColumnsFactory();
-
-        from.addQualifiedJoin(
-            JoinType.INNER,
-            t.table(
-            t.tableName( this._state.schemaName().get(), DBNames.ENTITY_TYPES_JOIN_TABLE_NAME ),
-            t.tableAlias( TABLE_NAME_PREFIX + TYPE_TABLE_SUFFIX ) ),
-            t.jc( b.eq(
-            c.colName( TABLE_NAME_PREFIX + startingIndex, DBNames.ENTITY_TABLE_PK_COLUMN_NAME ),
-            c.colName( TABLE_NAME_PREFIX + TYPE_TABLE_SUFFIX, DBNames.ENTITY_TABLE_PK_COLUMN_NAME ) ) )
-        );
-    }
-
-    protected SQLBooleanCreator getOperator( Specification<Composite> predicate )
-    {
-        return this.findFromLookupTables( SQL_OPERATORS, null, predicate, false );
-    }
-
-    protected JoinType
-        getTableJoinStyle( Specification<Composite> predicate, Boolean negationActive )
-    {
-        return this.findFromLookupTables( JOIN_STYLES, NEGATED_JOIN_STYLES, predicate,
-                                          negationActive );
-    }
-
-    protected <ReturnType> ReturnType findFromLookupTables(
-        Map<Class<? extends Specification>, ReturnType> normal,
-        Map<Class<? extends Specification>, ReturnType> negated,
-        Specification<Composite> predicate, Boolean negationActive )
-    {
-        Class<? extends Specification> predicateClass = predicate.getClass();
-        ReturnType result = null;
-        Set<Map.Entry<Class<? extends Specification>, ReturnType>> entries = negationActive
-                                                                             ? negated.entrySet()
-                                                                             : normal.entrySet();
-        for( Map.Entry<Class<? extends Specification>, ReturnType> entry : entries )
-        {
-            if( entry.getKey().isAssignableFrom( predicateClass ) )
-            {
-                result = entry.getValue();
-                break;
-            }
-        }
-
-        if( result == null )
-        {
-            throw new UnsupportedOperationException( "Predicate [" + predicateClass.getName() + "] is not supported" );
-        }
-
-        return result;
-    }
-
-    protected QuerySpecificationBuilder
-        getBuilderForPredicate( SQLVendor vendor, String tableAlias )
-    {
-        QueryFactory q = vendor.getQueryFactory();
-        ColumnsFactory c = vendor.getColumnsFactory();
-        QuerySpecificationBuilder result = q.querySpecificationBuilder();
-        result
-            .getSelect()
-            .setSetQuantifier( SetQuantifier.DISTINCT )
-            .addUnnamedColumns( c.colName( tableAlias, DBNames.ENTITY_TABLE_PK_COLUMN_NAME ),
-                                c.colName( tableAlias, DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME ) );
-
-        return result;
-    }
-
-    protected String translateJavaRegexpToPGSQLRegexp( String javaRegexp )
-    {
-        // TODO
-        // Yo dawg, I heard you like regular expressions, so we made a regexp about your regexp so
-        // you can match while
-        // you match!
-        // Meaning, probably best way to translate java regexp into pg-sql regexp is by... regexp.
-        return javaRegexp;
-    }
-
-    protected void processOrderBySegments( OrderBy[] orderBy, SQLVendor vendor,
-                                           QuerySpecificationBuilder builder )
-    {
-        if( orderBy != null )
-        {
-            QNameInfo[] qNames = new QNameInfo[ orderBy.length ];
-
-            QueryFactory q = vendor.getQueryFactory();
-            ColumnsFactory c = vendor.getColumnsFactory();
-
-            Integer tableIndex = 0;
-            for( Integer idx = 0; idx < orderBy.length; ++idx )
-            {
-                if( orderBy[idx] != null )
-                {
-                    PropertyFunction<?> ref = orderBy[idx].property();
-                    QualifiedName qName = QualifiedName.fromAccessor( ref.accessor() );
-                    QNameInfo info = this._state.qNameInfos().get().get( qName );
-                    qNames[idx] = info;
-                    if( info == null )
-                    {
-                        throw new InternalError( "No qName info found for qName [" + qName + "]." );
-                    }
-                    tableIndex
-                    = this.traversePropertyPath( ref, 0, tableIndex + 1, vendor, builder
-                        .getFrom()
-                        .getTableReferences().iterator().next(), JoinType.LEFT_OUTER );
-                    Class<?> declaringType = ( (Member) ref.accessor() ).getDeclaringClass();
-                    String colName;
-                    Integer tableIdx;
-                    if( Identity.class.equals( declaringType ) )
-                    {
-                        colName = DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME;
-                        tableIdx = tableIndex - 1;
-                    }
-                    else
-                    {
-                        colName = DBNames.QNAME_TABLE_VALUE_COLUMN_NAME;
-                        tableIdx = tableIndex;
-                    }
-                    Ordering ordering = Ordering.ASCENDING;
-                    if( orderBy[idx].order() == Order.DESCENDING )
-                    {
-                        ordering = Ordering.DESCENDING;
-                    }
-                    builder.getOrderBy().addSortSpecs(
-                        q.sortSpec( c.colName( TABLE_NAME_PREFIX + tableIdx, colName ), ordering ) );
-                }
-            }
-        }
-
-    }
-
-    protected Integer traversePropertyPath( PropertyFunction<?> reference, Integer lastTableIndex,
-                                            Integer nextAvailableIndex, SQLVendor vendor, TableReferenceBuilder builder,
-                                            JoinType joinStyle )
-    {
-
-        Stack<QualifiedName> qNameStack = new Stack<>();
-        Stack<PropertyFunction<?>> refStack = new Stack<>();
-
-        while( reference != null )
-        {
-            qNameStack.add( QualifiedName.fromAccessor( reference.accessor() ) );
-            refStack.add( reference );
-            if( reference.traversedProperty() == null
-                && ( reference.traversedAssociation() != null
-                     || reference.traversedManyAssociation() != null ) )
-            {
-                Integer lastAssoTableIndex = this.traverseAssociationPath(
-                    new TraversedAssoOrManyAssoRef( reference ),
-                    lastTableIndex, nextAvailableIndex, vendor, builder, joinStyle, true );
-                if( lastAssoTableIndex > lastTableIndex )
-                {
-                    lastTableIndex = lastAssoTableIndex;
-                    nextAvailableIndex = lastTableIndex + 1;
-                }
-            }
-
-            reference = reference.traversedProperty();
-        }
-
-        PropertyFunction<?> prevRef = null;
-        String schemaName = this._state.schemaName().get();
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-        BooleanFactory b = vendor.getBooleanFactory();
-        ColumnsFactory c = vendor.getColumnsFactory();
-
-        while( !qNameStack.isEmpty() )
-        {
-            QualifiedName qName = qNameStack.pop();
-            PropertyFunction<?> ref = refStack.pop();
-            if( !qName.type().equals( Identity.class.getName() ) )
-            {
-                QNameInfo info = this._state.qNameInfos().get().get( qName );
-                if( info == null )
-                {
-                    throw new InternalError( "No qName info found for qName [" + qName + "]." );
-                }
-
-                String prevTableAlias = TABLE_NAME_PREFIX + lastTableIndex;
-                String nextTableAlias = TABLE_NAME_PREFIX + nextAvailableIndex;
-                TableReferenceByName nextTable = t.table( t.tableName( schemaName, info.getTableName() ),
-                                                          t.tableAlias( nextTableAlias ) );
-                // @formatter:off
-                if( prevRef == null )
-                {
-                    builder.addQualifiedJoin(
-                        joinStyle,
-                        nextTable,
-                        t.jc(
-                        b.booleanBuilder(
-                            b.eq(
-                                c.colName( prevTableAlias, DBNames.ENTITY_TABLE_PK_COLUMN_NAME ),
-                                c.colName( nextTableAlias, DBNames.ENTITY_TABLE_PK_COLUMN_NAME )
-                            )
-                        )
-                        .and(
-                            b.isNull( c.colName( nextTableAlias, DBNames.QNAME_TABLE_PARENT_QNAME_COLUMN_NAME ) )
-                        )
-                        .createExpression()
-                    )
-                    );
-                }
-                else
-                {
-                    builder.addQualifiedJoin(
-                        joinStyle,
-                        nextTable,
-                        t.jc(
-                        b.booleanBuilder(
-                            b.eq(
-                                c.colName( prevTableAlias, DBNames.ALL_QNAMES_TABLE_PK_COLUMN_NAME ),
-                                c.colName( nextTableAlias, DBNames.QNAME_TABLE_PARENT_QNAME_COLUMN_NAME ) )
-                        )
-                        .and(
-                            b.eq(
-                                c.colName( prevTableAlias, DBNames.ENTITY_TABLE_PK_COLUMN_NAME ),
-                                c.colName( nextTableAlias, DBNames.ENTITY_TABLE_PK_COLUMN_NAME )
-                            )
-                        )
-                        .createExpression()
-                    )
-                    );
-                }
-                // @formatter:on
-                lastTableIndex = nextAvailableIndex;
-                ++nextAvailableIndex;
-                prevRef = ref;
-            }
-        }
-
-        return lastTableIndex;
-    }
-
-    protected Integer traverseAssociationPath( TraversedAssoOrManyAssoRef reference,
-                                               Integer lastTableIndex,
-                                               Integer nextAvailableIndex, SQLVendor vendor, TableReferenceBuilder builder,
-                                               JoinType joinStyle,
-                                               Boolean includeLastTable )
-    {
-        Stack<QualifiedName> qNameStack = new Stack<>();
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-        BooleanFactory b = vendor.getBooleanFactory();
-        ColumnsFactory c = vendor.getColumnsFactory();
-        String schemaName = this._state.schemaName().get();
-
-        while( reference._hasRefs )
-        {
-            qNameStack.add( QualifiedName.fromAccessor( reference.getAccessor() ) );
-            reference = reference.getTraversedAssociation();
-        }
-        while( !qNameStack.isEmpty() )
-        {
-            QualifiedName qName = qNameStack.pop();
-            QNameInfo info = this._state.qNameInfos().get().get( qName );
-            if( info == null )
-            {
-                throw new InternalError( "No qName info found for qName [" + qName + "]." );
-            }
-            // @formatter:off
-            builder.addQualifiedJoin(
-                joinStyle,
-                t.table( t.tableName( schemaName, info.getTableName() ), t.tableAlias( TABLE_NAME_PREFIX
-                                                                                       + nextAvailableIndex ) ),
-                t.jc(
-                b.eq(
-                    c.colName( TABLE_NAME_PREFIX + lastTableIndex, DBNames.ENTITY_TABLE_PK_COLUMN_NAME ),
-                    c.colName( TABLE_NAME_PREFIX + nextAvailableIndex, DBNames.ENTITY_TABLE_PK_COLUMN_NAME ) )
-            ) );
-            lastTableIndex = nextAvailableIndex;
-            ++nextAvailableIndex;
-            if( includeLastTable || !qNameStack.isEmpty() )
-            {
-                builder.addQualifiedJoin(
-                    joinStyle,
-                    t.table( t.tableName( schemaName, DBNames.ENTITY_TABLE_NAME ), t.tableAlias( TABLE_NAME_PREFIX + nextAvailableIndex ) ),
-                    t.jc(
-                    b.eq(
-                        c.colName( TABLE_NAME_PREFIX + lastTableIndex, DBNames.QNAME_TABLE_VALUE_COLUMN_NAME ),
-                        c.colName( TABLE_NAME_PREFIX + nextAvailableIndex, DBNames.ENTITY_TABLE_PK_COLUMN_NAME )
-                    )
-                )
-                );
-                lastTableIndex = nextAvailableIndex;
-                ++nextAvailableIndex;
-            }
-            // @formatter:on
-        }
-
-        return lastTableIndex;
-    }
-
-    protected List<Integer> getEntityTypeIDs( Class<?> entityType )
-    {
-        List<Integer> result = new ArrayList<>();
-        for( Map.Entry<String, Integer> entry : this._state.entityTypePKs().get().entrySet() )
-        {
-            Class<?> clazz = null;
-            try
-            {
-                clazz = Class.forName( entry.getKey() );
-            }
-            catch( Throwable t )
-            {
-                // Ignore
-            }
-            if( clazz != null && entityType.isAssignableFrom( clazz ) )
-            {
-                result.add( entry.getValue() );
-            }
-        }
-
-        return result;
-    }
-
-    // TODO refactor this monster of a method to something more understandable
-    protected Integer modifyFromClauseAndWhereClauseToGetValue(
-        final QualifiedName qName,
-        Object value,
-        final Specification<Composite> predicate, final Boolean negationActive,
-        final Integer currentTableIndex,
-        final ModifiableInt maxTableIndex, final String columnName,
-        final String collectionPath,
-        final SQLVendor vendor, final BooleanBuilder whereClause,
-        final BooleanBuilder afterWhere,
-        final TableReferenceBuilder fromClause, final GroupByBuilder groupBy,
-        final BooleanBuilder having,
-        final List<QNameJoin> qNameJoins, Map<String, Object> variables,
-        final List<Object> values, final List<Integer> valueSQLTypes )
-    {
-        if( value instanceof Variable )
-        {
-            value = variables.get( ( (Variable) value ).variableName() );
-        }
-
-        final String schemaName = this._state.schemaName().get();
-        Integer result = 1;
-
-        final BooleanFactory b = vendor.getBooleanFactory();
-        final LiteralFactory l = vendor.getLiteralFactory();
-        final ColumnsFactory c = vendor.getColumnsFactory();
-        final QueryFactory q = vendor.getQueryFactory();
-        final TableReferenceFactory t = vendor.getTableReferenceFactory();
-
-        if( value instanceof Collection<?> )
-        {
-            // Collection
-            Integer collectionIndex = 0;
-            Boolean collectionIsSet = value instanceof Set<?>;
-            Boolean topLevel = collectionPath.equals( DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME );
-            String collTable = TABLE_NAME_PREFIX + currentTableIndex;
-            String collCol = DBNames.QNAME_TABLE_COLLECTION_PATH_COLUMN_NAME;
-            ColumnReferenceByName collColExp = c.colName( collTable, collCol );
-
-            BooleanBuilder collectionCondition = b.booleanBuilder();
-
-            if( topLevel && negationActive )
-            {
-                afterWhere
-                    .and( b
-                        .booleanBuilder(
-                            b.neq( collColExp,
-                                   l.s( DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME ) ) )
-                        .or( b.isNull( collColExp ) ).createExpression() );
-            }
-
-            Integer totalItemsProcessed = 0;
-            for( Object item : (Collection<?>) value )
-            {
-                String path = collectionPath + DBNames.QNAME_TABLE_COLLECTION_PATH_SEPARATOR
-                              + ( collectionIsSet ? "*{1,}" : collectionIndex );
-                Boolean isCollection = ( item instanceof Collection<?> );
-                BooleanBuilder newWhere = b.booleanBuilder();
-                if( !isCollection )
-                {
-                    newWhere.reset( b.regexp( collColExp, l.s( path ) ) );
-                }
-                totalItemsProcessed
-                = totalItemsProcessed
-                  + modifyFromClauseAndWhereClauseToGetValue( qName, item, predicate,
-                                                              negationActive,
-                                                              currentTableIndex, maxTableIndex, columnName, path, vendor,
-                                                              newWhere, afterWhere, fromClause,
-                                                              groupBy, having, qNameJoins, variables, values, valueSQLTypes );
-
-                ++collectionIndex;
-                collectionCondition.or( newWhere.createExpression() );
-            }
-            result = totalItemsProcessed;
-
-            if( topLevel )
-            {
-                if( totalItemsProcessed == 0 )
-                {
-                    collectionCondition.and( b.isNotNull( collColExp ) )
-                        .and(
-                            b.eq( collColExp,
-                                  l.l( DBNames.QNAME_TABLE_COLLECTION_PATH_TOP_LEVEL_NAME ) ) );
-                }
-                else if( !negationActive )
-                {
-                    groupBy.addGroupingElements( q.groupingElement( c.colName( TABLE_NAME_PREFIX
-                                                                               + currentTableIndex,
-                                                                               DBNames.ENTITY_TABLE_PK_COLUMN_NAME ) ) );
-                    having
-                        .and( b.eq(
-                                l.func( SQLFunctions.COUNT,
-                                        c.colName( TABLE_NAME_PREFIX + currentTableIndex,
-                                                   DBNames.QNAME_TABLE_VALUE_COLUMN_NAME ) ),
-                                l.n( totalItemsProcessed ) ) );
-
-                }
-            }
-
-            whereClause.and( collectionCondition.createExpression() );
-
-        }
-        else if( value instanceof ValueComposite )
-        {
-            // Visit all properties with recursion and make joins as necessary
-            // @formatter:off
-            for( Property<?> property
-                 : Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF.map( (ValueComposite) value ).state().properties() )
-            {
-                Boolean qNameJoinDone = false;
-                Integer sourceIndex = maxTableIndex.getInt();
-                Integer targetIndex = sourceIndex + 1;
-                for( QNameJoin join : qNameJoins )
-                {
-                    if( join.getSourceQName().equals( qName ) )
-                    {
-                        sourceIndex = join.getSourceTableIndex();
-                        if( join.getTargetQName().equals( spi.propertyDescriptorFor( property ).qualifiedName() ) )
-                        {
-                            // This join has already been done once
-                            qNameJoinDone = true;
-                            targetIndex = join.getTargetTableIndex();
-                            break;
-                        }
-                    }
-                }
-
-                if( !qNameJoinDone )
-                {
-                    // @formatter:off
-                    QNameInfo info = _state.qNameInfos().get().get( spi.propertyDescriptorFor( property ).qualifiedName() );
-                    String prevTableName = TABLE_NAME_PREFIX + sourceIndex;
-                    String nextTableName = TABLE_NAME_PREFIX + targetIndex;
-                    fromClause.addQualifiedJoin(
-                        JoinType.LEFT_OUTER,
-                        t.table( t.tableName( schemaName, info.getTableName() ), t.tableAlias( TABLE_NAME_PREFIX + targetIndex ) ),
-                        t.jc(
-                        b.booleanBuilder( b.eq(
-                                c.colName( prevTableName, DBNames.ALL_QNAMES_TABLE_PK_COLUMN_NAME ),
-                                c.colName( nextTableName, DBNames.QNAME_TABLE_PARENT_QNAME_COLUMN_NAME )
-                            ) )
-                        .and( b.eq(
-                                c.colName( prevTableName, DBNames.ENTITY_TABLE_PK_COLUMN_NAME ),
-                                c.colName( nextTableName, DBNames.ENTITY_TABLE_PK_COLUMN_NAME )
-                            ) ).createExpression()
-                    )
-                    );
-                    // @formatter:on
-
-                    qNameJoins.add( new QNameJoin( qName, spi.propertyDescriptorFor( property )
-                        .qualifiedName(), sourceIndex, targetIndex ) );
-                    maxTableIndex.setInt( maxTableIndex.getInt() + 1 );
-                }
-                modifyFromClauseAndWhereClauseToGetValue( spi.propertyDescriptorFor( property )
-                    .qualifiedName(), property.get(), predicate, negationActive,
-                                                          targetIndex, maxTableIndex, columnName, collectionPath, vendor, whereClause,
-                                                          afterWhere,
-                                                          fromClause, groupBy, having, qNameJoins, variables, values, valueSQLTypes );
-            }
-
-            // @formatter:on
-        }
-        else
-        {
-            // Primitive
-            ColumnReferenceByName valueCol = c.colName( TABLE_NAME_PREFIX + currentTableIndex, columnName );
-            if( value == null )
-            {
-                whereClause.and( b.isNull( valueCol ) );
-            }
-            else
-            {
-                Object dbValue = value;
-                if( Enum.class.isAssignableFrom( value.getClass() ) )
-                {
-                    dbValue = this._state.enumPKs().get().get( value.getClass().getName() );
-                }
-                whereClause.and( b.and( b.isNotNull( valueCol ),
-                                        this.getOperator( predicate ).getExpression( b, valueCol, l.param() ) ) );
-                values.add( dbValue );
-                valueSQLTypes.add( _typeHelper.getSQLType( value ) );
-                LOGGER.info( TABLE_NAME_PREFIX + currentTableIndex + "." + columnName + " is " + dbValue );
-            }
-        }
-
-        return result;
-    }
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/AbstractSQLStartup.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/AbstractSQLStartup.java
deleted file mode 100644
index 5d35236..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/AbstractSQLStartup.java
+++ /dev/null
@@ -1,1769 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.skeletons;
-
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.sql.Types;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.sql.DataSource;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.api.structure.LayerDescriptor;
-import org.qi4j.api.structure.ModuleDescriptor;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.HierarchicalVisitorAdapter;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.index.reindexer.Reindexer;
-import org.qi4j.index.sql.support.api.SQLAppStartup;
-import org.qi4j.index.sql.support.api.SQLTypeInfo;
-import org.qi4j.index.sql.support.common.DBNames;
-import org.qi4j.index.sql.support.common.QNameInfo;
-import org.qi4j.index.sql.support.common.QNameInfo.QNameType;
-import org.qi4j.index.sql.support.common.RebuildingStrategy;
-import org.qi4j.index.sql.support.common.ReindexingStrategy;
-import org.qi4j.library.sql.common.SQLConfiguration;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sql.generation.api.grammar.builders.definition.TableElementListBuilder;
-import org.sql.generation.api.grammar.common.datatypes.SQLDataType;
-import org.sql.generation.api.grammar.definition.table.AutoGenerationPolicy;
-import org.sql.generation.api.grammar.definition.table.ConstraintCharacteristics;
-import org.sql.generation.api.grammar.definition.table.ReferentialAction;
-import org.sql.generation.api.grammar.definition.table.UniqueSpecification;
-import org.sql.generation.api.grammar.factories.DataTypeFactory;
-import org.sql.generation.api.grammar.factories.DefinitionFactory;
-import org.sql.generation.api.grammar.factories.LiteralFactory;
-import org.sql.generation.api.grammar.factories.ModificationFactory;
-import org.sql.generation.api.grammar.factories.QueryFactory;
-import org.sql.generation.api.grammar.factories.TableReferenceFactory;
-import org.sql.generation.api.grammar.manipulation.DropBehaviour;
-import org.sql.generation.api.grammar.manipulation.ObjectType;
-import org.sql.generation.api.grammar.modification.DeleteBySearch;
-import org.sql.generation.api.grammar.modification.InsertStatement;
-import org.sql.generation.api.grammar.query.QueryExpression;
-import org.sql.generation.api.vendor.SQLVendor;
-
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.index.sql.support.common.DBNames.ALL_QNAMES_TABLE_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.ALL_QNAMES_TABLE_PK_COLUMN_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.APP_VERSION_PK_COLUMN_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.APP_VERSION_TABLE_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.ENTITY_TABLE_APPLICATION_VERSION_COLUMN_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.ENTITY_TABLE_IDENTITY_COLUMN_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.ENTITY_TABLE_MODIFIED_COLUMN_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.ENTITY_TABLE_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.ENTITY_TABLE_PK_COLUMN_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.ENTITY_TABLE_VERSION_COLUMN_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.ENTITY_TYPES_JOIN_TABLE_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.ENTITY_TYPES_TABLE_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.ENTITY_TYPES_TABLE_PK_COLUMN_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.ENTITY_TYPES_TABLE_TYPE_NAME_COLUMN_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.ENUM_LOOKUP_TABLE_ENUM_VALUE_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.ENUM_LOOKUP_TABLE_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.ENUM_LOOKUP_TABLE_PK_COLUMN_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.QNAME_TABLE_ASSOCIATION_INDEX_COLUMN_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.QNAME_TABLE_COLLECTION_PATH_COLUMN_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.QNAME_TABLE_NAME_PREFIX;
-import static org.qi4j.index.sql.support.common.DBNames.QNAME_TABLE_PARENT_QNAME_COLUMN_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.QNAME_TABLE_VALUE_COLUMN_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.USED_CLASSES_TABLE_CLASS_NAME_COLUMN_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.USED_CLASSES_TABLE_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.USED_CLASSES_TABLE_PK_COLUMN_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.USED_QNAMES_TABLE_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.USED_QNAMES_TABLE_QNAME_COLUMN_NAME;
-import static org.qi4j.index.sql.support.common.DBNames.USED_QNAMES_TABLE_TABLE_NAME_COLUMN_NAME;
-
-public abstract class AbstractSQLStartup
-    implements SQLAppStartup
-{
-    private interface SQLTypeCustomizer
-    {
-        SQLDataType customizeType( Type propertyType, SQLTypeInfo sqlTypeInfo );
-    }
-
-    public static final String DEFAULT_SCHEMA_NAME = "qi4j";
-
-    private static final Class<?> ENTITY_PK_TYPE = Long.class;
-    private static final Class<?> ENTITY_TYPE_PK_TYPE = Integer.class;
-
-    private static final Logger LOGGER = LoggerFactory.getLogger( AbstractSQLStartup.class.getName() );
-
-    static final ThreadLocal<Connection> CONNECTION_FOR_REINDEXING = new ThreadLocal<Connection>()
-    {
-        @Override
-        protected Connection initialValue()
-        {
-            return null;
-        }
-    };
-
-    @This
-    private SQLDBState _state;
-
-    @This
-    private Configuration<SQLConfiguration> _configuration;
-
-    @Service
-    @Optional
-    private ReindexingStrategy _reindexingStrategy;
-
-    @Service
-    @Optional
-    private RebuildingStrategy _rebuildingStrategy;
-
-    @Service
-    private DataSource _dataSource;
-
-    @Service
-    private Reindexer _reindexer;
-
-    @Structure
-    private Application _app;
-
-    private final SQLVendor _vendor;
-
-    private Map<Class<?>, SQLTypeCustomizer> _customizableTypes;
-
-    private Map<Class<?>, SQLDataType> _primitiveTypes;
-
-    public AbstractSQLStartup( @Uses ServiceDescriptor descriptor )
-    {
-        this._vendor = descriptor.metaInfo( SQLVendor.class );
-    }
-
-    @Override
-    public void initConnection()
-        throws SQLException
-    {
-        this._configuration.refresh();
-
-        this.initTypes();
-        this.modifyPrimitiveTypes( this._primitiveTypes, this._state.javaTypes2SQLTypes().get() );
-
-        String schemaName = this._configuration.get().schemaName().get();
-        if( schemaName == null )
-        {
-            schemaName = DEFAULT_SCHEMA_NAME;
-        }
-        else
-        {
-            this.checkSchemaName( schemaName );
-        }
-        LOGGER.debug( "Will use '{}' as schema name", schemaName );
-
-        this._state.schemaName().set( schemaName );
-        this._state.entityTypePKs().set( new HashMap<String, Integer>() );
-        this._state.usedClassesPKs().set( new HashMap<CompositeDescriptor, Integer>() );
-        this._state.entityUsedQNames().set( new HashMap<EntityDescriptor, Set<QualifiedName>>() );
-        this._state.qNameInfos().set( new HashMap<QualifiedName, QNameInfo>() );
-        this._state.enumPKs().set( new HashMap<String, Integer>() );
-
-        Connection connection = this._dataSource.getConnection();
-        try
-        {
-            connection.setAutoCommit( true );
-            connection.setReadOnly( false );
-            this.syncDB( connection );
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( connection );
-        }
-
-        if( LOGGER.isDebugEnabled() )
-        {
-
-            String newline = "\n";
-            String tab = "\t";
-            String colonspace = ": ";
-            StringBuilder report = new StringBuilder();
-
-            report.append( "schemaName: " ).append( _state.schemaName().get() ).append( newline );
-
-            report.append( "qNameInfos: " ).append( newline );
-            for( Map.Entry<QualifiedName, QNameInfo> entry : _state.qNameInfos().get().entrySet() )
-            {
-                report.append( tab ).append( entry.getKey() ).append( colonspace )
-                    .append( entry.getValue() ).append( newline );
-            }
-
-            report.append( "entityUsedQNames:" ).append( newline );
-            for( Map.Entry<EntityDescriptor, Set<QualifiedName>> entry : _state.entityUsedQNames()
-                .get()
-                .entrySet() )
-            {
-                report.append( tab ).append( entry.getKey() ).append( colonspace )
-                    .append( entry.getValue() ).append( newline );
-            }
-
-            report.append( "usedClassesPKs:" ).append( newline );
-            for( Map.Entry<CompositeDescriptor, Integer> entry : _state.usedClassesPKs().get()
-                .entrySet() )
-            {
-                report.append( tab ).append( entry.getKey() ).append( colonspace )
-                    .append( entry.getValue() ).append( newline );
-            }
-
-            report.append( "javaTypes2SQLTypes:" ).append( newline );
-            for( Map.Entry<Class<?>, Integer> entry : _state.javaTypes2SQLTypes().get().entrySet() )
-            {
-                report.append( tab ).append( entry.getKey() ).append( colonspace )
-                    .append( entry.getValue() ).append( newline );
-            }
-
-            report.append( "entityTypePKs:" ).append( newline );
-            for( Map.Entry<String, Integer> entry : _state.entityTypePKs().get().entrySet() )
-            {
-                report.append( tab ).append( entry.getKey() ).append( colonspace )
-                    .append( entry.getValue() ).append( newline );
-            }
-
-            report.append( "enumPKs:" ).append( newline );
-            for( Map.Entry<String, Integer> entry : _state.enumPKs().get().entrySet() )
-            {
-                report.append( tab ).append( entry.getKey() ).append( colonspace )
-                    .append( entry.getValue() ).append( newline );
-            }
-
-            LOGGER.debug( "SQLDBState after initConnection:\n{}", report.toString() );
-        }
-    }
-
-    private void initTypes()
-    {
-
-        DataTypeFactory dt = this._vendor.getDataTypeFactory();
-
-        this._primitiveTypes = new HashMap<>();
-        this._primitiveTypes.put( Boolean.class, dt.sqlBoolean() );
-        this._primitiveTypes.put( Byte.class, dt.smallInt() );
-        this._primitiveTypes.put( Short.class, dt.smallInt() );
-        this._primitiveTypes.put( Integer.class, dt.integer() );
-        this._primitiveTypes.put( Long.class, dt.bigInt() );
-        this._primitiveTypes.put( Float.class, dt.real() );
-        this._primitiveTypes.put( Double.class, dt.doublePrecision() );
-        this._primitiveTypes.put( Date.class, dt.timeStamp( true ) );
-        this._primitiveTypes.put( Character.class, dt.integer() );
-        this._primitiveTypes.put( String.class, dt.sqlVarChar( 5000 ) );
-        this._primitiveTypes.put( BigInteger.class, dt.decimal() );
-        this._primitiveTypes.put( BigDecimal.class, dt.decimal() );
-
-        Map<Class<?>, Integer> jdbcTypes = new HashMap<>();
-        jdbcTypes.put( Boolean.class, Types.BOOLEAN );
-        jdbcTypes.put( Byte.class, Types.SMALLINT );
-        jdbcTypes.put( Short.class, Types.SMALLINT );
-        jdbcTypes.put( Integer.class, Types.INTEGER );
-        jdbcTypes.put( Long.class, Types.BIGINT );
-        jdbcTypes.put( Float.class, Types.REAL );
-        jdbcTypes.put( Double.class, Types.DOUBLE );
-        jdbcTypes.put( Date.class, Types.TIMESTAMP );
-        jdbcTypes.put( Character.class, Types.INTEGER );
-        jdbcTypes.put( String.class, Types.VARCHAR );
-        jdbcTypes.put( BigInteger.class, Types.NUMERIC );
-        jdbcTypes.put( BigDecimal.class, Types.NUMERIC );
-        this._state.javaTypes2SQLTypes().set( jdbcTypes );
-
-        this._customizableTypes = new HashMap<>();
-        this._customizableTypes.put( //
-            String.class, //
-            new SQLTypeCustomizer()
-        {
-            @Override
-            public SQLDataType customizeType( Type propertyType, SQLTypeInfo sqlTypeInfo )
-            {
-                return _vendor.getDataTypeFactory().sqlVarChar( sqlTypeInfo.maxLength() );
-            }
-            } //
-        );
-        this._customizableTypes.put( //
-            BigInteger.class, //
-            new SQLTypeCustomizer()
-        {
-            @Override
-            public SQLDataType customizeType( Type propertyType, SQLTypeInfo sqlTypeInfo )
-            {
-                return _vendor.getDataTypeFactory().decimal( sqlTypeInfo.maxLength() );
-            }
-            } //
-        );
-        this._customizableTypes.put( //
-            BigDecimal.class, //
-            new SQLTypeCustomizer()
-        {
-            @Override
-            public SQLDataType customizeType( Type propertyType, SQLTypeInfo sqlTypeInfo )
-            {
-                return _vendor.getDataTypeFactory().decimal( sqlTypeInfo.maxLength() );
-            }
-            } //
-        );
-    }
-
-    protected void checkSchemaName( String schemaName )
-    {
-        // By default, we accept alphanumeric strings with underscores in them
-        if( !Pattern.matches( "^\\p{L}(\\_|\\p{L}|\\p{N})*$", schemaName ) )
-        {
-            throw new IllegalStateException( "Illegal schema name: " + schemaName + "." );
-        }
-    }
-
-    private static class ApplicationInfo
-    {
-
-        private final Map<String, EntityDescriptor> entityDescriptors = new HashMap<>();
-
-        private final Set<CompositeDescriptorInfo> usedValueComposites = new HashSet<>();
-
-        private final Set<String> enumValues = new HashSet<>();
-
-    }
-
-    private static class CompositeDescriptorInfo
-    {
-        final LayerDescriptor layer;
-        final ModuleDescriptor module;
-        final CompositeDescriptor composite;
-
-        private CompositeDescriptorInfo( LayerDescriptor theLayer, ModuleDescriptor theModule,
-                                         CompositeDescriptor theComposite )
-        {
-            this.layer = theLayer;
-            this.module = theModule;
-            this.composite = theComposite;
-        }
-
-        @Override
-        public boolean equals( Object obj )
-        {
-            return this == obj
-                   || ( obj instanceof CompositeDescriptorInfo && this.composite
-                       .equals( ( (CompositeDescriptorInfo) obj ).composite ) );
-        }
-
-        @Override
-        public int hashCode()
-        {
-            return this.composite.hashCode();
-        }
-    }
-
-    private void syncDB( Connection connection )
-        throws SQLException
-    {
-        String schemaName = this._state.schemaName().get();
-        String appVersion = this._app.version();
-        String dbAppVersion = this.readAppVersionFromDB( connection, schemaName );
-
-        // Rebuild if needed
-        boolean rebuildingNeeded = dbAppVersion == null;
-
-        if( !rebuildingNeeded && this._rebuildingStrategy != null )
-        {
-            rebuildingNeeded = this._rebuildingStrategy.rebuildingRequired( dbAppVersion, appVersion );
-        }
-
-        ApplicationInfo appInfo = this.constructApplicationInfo( !rebuildingNeeded );
-
-        if( rebuildingNeeded )
-        {
-            LOGGER.debug( "(Re)building schema " + schemaName );
-            this.destroyNeededSchemaTables( connection, schemaName, this._state.qNameInfos().get().size() );
-
-            Map<String, Long> tablePKs = new HashMap<>();
-            this.createSchemaAndRequiredTables( connection, schemaName, tablePKs );
-            this.writeAppMetadataToDB( connection, appInfo, tablePKs );
-        }
-        else
-        {
-            this.testRequiredCapabilities( connection );
-            this.readAppMetadataFromDB( connection, appInfo.entityDescriptors );
-            LOGGER.debug( "Application metadata loaded from database" );
-        }
-
-        boolean reindexingNeeded = dbAppVersion == null;
-        if( !reindexingNeeded && this._reindexingStrategy != null )
-        {
-            reindexingNeeded = this._reindexingStrategy.reindexingNeeded( dbAppVersion, appVersion );
-        }
-
-        if( reindexingNeeded )
-        {
-            LOGGER.debug( "(Re)indexing entitystore, using schema " + schemaName );
-            this.performReindex( connection );
-        }
-    }
-
-    private void createSchemaAndRequiredTables( Connection connection, String schemaName,
-                                                Map<String, Long> tablePKs )
-        throws SQLException
-    {
-        boolean schemaFound = false;
-
-        ResultSet rs = connection.getMetaData().getSchemas();
-        try
-        {
-            while( rs.next() && !schemaFound )
-            {
-                schemaFound = rs.getString( 1 ).equals( schemaName );
-            }
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( rs );
-        }
-
-        SQLVendor vendor = this._vendor;
-        DefinitionFactory d = vendor.getDefinitionFactory();
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-
-        Statement stmt = connection.createStatement();
-
-        // @formatter:off
-        try
-        {
-            if( !schemaFound )
-            {
-                stmt.execute(
-                    vendor.toString(
-                        d
-                        .createSchemaDefinitionBuilder()
-                        .setSchemaName( schemaName )
-                        .createExpression()
-                    )
-                );
-                LOGGER.debug( "Database schema created" );
-            }
-
-            this.testRequiredCapabilities( connection );
-            LOGGER.debug( "Underlying database fullfill required capabilities" );
-
-            stmt.execute(
-                vendor.toString(
-                    d.createTableDefinitionBuilder()
-                    .setTableName( t.tableName( schemaName, USED_CLASSES_TABLE_NAME ) )
-                    .setTableContentsSource(
-                        d.createTableElementListBuilder()
-                        .addTableElement( d.createColumnDefinition( USED_CLASSES_TABLE_PK_COLUMN_NAME, this._primitiveTypes
-                                .get( Integer.class ), false ) )
-                        .addTableElement( d.createColumnDefinition( USED_CLASSES_TABLE_CLASS_NAME_COLUMN_NAME, this._primitiveTypes
-                                .get( String.class ), false ) )
-                        .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
-                                .setUniqueness( UniqueSpecification.PRIMARY_KEY )
-                                .addColumns( USED_CLASSES_TABLE_PK_COLUMN_NAME )
-                                .createExpression()
-                            ) )
-                        .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
-                                .setUniqueness( UniqueSpecification.UNIQUE )
-                                .addColumns( USED_CLASSES_TABLE_CLASS_NAME_COLUMN_NAME )
-                                .createExpression()
-                            ) )
-                        .createExpression()
-                    )
-                    .createExpression()
-                )
-            );
-
-            tablePKs.put( USED_CLASSES_TABLE_NAME, 0L );
-
-            stmt.execute(
-                vendor.toString(
-                    d.createTableDefinitionBuilder()
-                    .setTableName( t.tableName( schemaName, ENTITY_TYPES_TABLE_NAME ) )
-                    .setTableContentsSource(
-                        d.createTableElementListBuilder()
-                        .addTableElement( d.createColumnDefinition( ENTITY_TYPES_TABLE_PK_COLUMN_NAME, this._primitiveTypes
-                                .get( ENTITY_TYPE_PK_TYPE ), false ) )
-                        .addTableElement( d.createColumnDefinition( ENTITY_TYPES_TABLE_TYPE_NAME_COLUMN_NAME, this._primitiveTypes
-                                .get( String.class ), false ) )
-                        .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
-                                .setUniqueness( UniqueSpecification.PRIMARY_KEY )
-                                .addColumns( ENTITY_TYPES_TABLE_PK_COLUMN_NAME )
-                                .createExpression()
-                            ) )
-                        .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
-                                .setUniqueness( UniqueSpecification.UNIQUE )
-                                .addColumns( ENTITY_TYPES_TABLE_TYPE_NAME_COLUMN_NAME )
-                                .createExpression()
-                            ) )
-                        .createExpression()
-                    )
-                    .createExpression()
-                )
-            );
-
-            tablePKs.put( ENTITY_TYPES_TABLE_NAME, 0L );
-
-            stmt.execute(
-                vendor.toString(
-                    d.createTableDefinitionBuilder()
-                    .setTableName( t.tableName( schemaName, ENTITY_TABLE_NAME ) )
-                    .setTableContentsSource(
-                        d.createTableElementListBuilder()
-                        .addTableElement( d.createColumnDefinition( ENTITY_TABLE_PK_COLUMN_NAME, this._primitiveTypes
-                                .get( ENTITY_PK_TYPE ), false, AutoGenerationPolicy.BY_DEFAULT ) )
-                        .addTableElement( d.createColumnDefinition( ENTITY_TABLE_IDENTITY_COLUMN_NAME, this._primitiveTypes
-                                .get( String.class ), false ) )
-                        .addTableElement( d.createColumnDefinition( ENTITY_TABLE_MODIFIED_COLUMN_NAME, this._primitiveTypes
-                                .get( Date.class ), false ) )
-                        .addTableElement( d.createColumnDefinition( ENTITY_TABLE_VERSION_COLUMN_NAME, this._primitiveTypes
-                                .get( String.class ), false ) )
-                        .addTableElement( d.createColumnDefinition( ENTITY_TABLE_APPLICATION_VERSION_COLUMN_NAME, this._primitiveTypes
-                                .get( String.class ), false ) )
-                        .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
-                                .setUniqueness( UniqueSpecification.PRIMARY_KEY )
-                                .addColumns( ENTITY_TABLE_PK_COLUMN_NAME )
-                                .createExpression()
-                            ) )
-                        .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
-                                .setUniqueness( UniqueSpecification.UNIQUE )
-                                .addColumns( ENTITY_TABLE_IDENTITY_COLUMN_NAME )
-                                .createExpression()
-                            ) )
-                        .createExpression()
-                    )
-                    .createExpression()
-                )
-            );
-            tablePKs.put( ENTITY_TABLE_NAME, 0L );
-
-            stmt.execute(
-                d.createTableDefinitionBuilder()
-                .setTableName( t.tableName( schemaName, ENTITY_TYPES_JOIN_TABLE_NAME ) )
-                .setTableContentsSource(
-                    d.createTableElementListBuilder()
-                    .addTableElement( d.createColumnDefinition( ENTITY_TABLE_PK_COLUMN_NAME, this._primitiveTypes
-                            .get( ENTITY_PK_TYPE ), false ) )
-                    .addTableElement( d.createColumnDefinition( ENTITY_TYPES_TABLE_PK_COLUMN_NAME, this._primitiveTypes
-                            .get( ENTITY_TYPE_PK_TYPE ), false ) )
-                    .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
-                            .setUniqueness( UniqueSpecification.PRIMARY_KEY )
-                            .addColumns( ENTITY_TABLE_PK_COLUMN_NAME, ENTITY_TYPES_TABLE_PK_COLUMN_NAME )
-                            .createExpression()
-                        ) )
-                    .addTableElement( d.createTableConstraintDefinition( d.createForeignKeyConstraintBuilder()
-                            .addSourceColumns( ENTITY_TABLE_PK_COLUMN_NAME )
-                            .setTargetTableName( t.tableName( schemaName, ENTITY_TABLE_NAME ) )
-                            .addTargetColumns( ENTITY_TABLE_PK_COLUMN_NAME )
-                            .setOnDelete( ReferentialAction.CASCADE )
-                            .setOnUpdate( ReferentialAction.CASCADE )
-                            .createExpression(), ConstraintCharacteristics.INITIALLY_DEFERRED_DEFERRABLE
-                        ) )
-                    .addTableElement( d.createTableConstraintDefinition( d.createForeignKeyConstraintBuilder()
-                            .addSourceColumns( ENTITY_TYPES_TABLE_PK_COLUMN_NAME )
-                            .setTargetTableName( t.tableName( schemaName, ENTITY_TYPES_TABLE_NAME ) )
-                            .addTargetColumns( ENTITY_TYPES_TABLE_PK_COLUMN_NAME )
-                            .setOnDelete( ReferentialAction.RESTRICT )
-                            .setOnDelete( ReferentialAction.CASCADE )
-                            .createExpression(), ConstraintCharacteristics.NOT_DEFERRABLE ) )
-                    .createExpression()
-                ).createExpression()
-                .toString()
-            );
-
-            stmt.execute(
-                vendor.toString(
-                    d.createTableDefinitionBuilder()
-                    .setTableName( t.tableName( schemaName, ENUM_LOOKUP_TABLE_NAME ) )
-                    .setTableContentsSource(
-                        d.createTableElementListBuilder()
-                        .addTableElement( d.createColumnDefinition( ENUM_LOOKUP_TABLE_PK_COLUMN_NAME, this._primitiveTypes
-                                .get( Integer.class ), false ) )
-                        .addTableElement( d.createColumnDefinition( ENUM_LOOKUP_TABLE_ENUM_VALUE_NAME, this._primitiveTypes
-                                .get( String.class ), false ) )
-                        .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
-                                .setUniqueness( UniqueSpecification.PRIMARY_KEY )
-                                .addColumns( ENUM_LOOKUP_TABLE_PK_COLUMN_NAME )
-                                .createExpression()
-                            ) )
-                        .createExpression()
-                    )
-                    .createExpression()
-                )
-            );
-
-            tablePKs.put( ENUM_LOOKUP_TABLE_NAME, 0L );
-
-            stmt.execute(
-                vendor.toString(
-                    d.createTableDefinitionBuilder()
-                    .setTableName( t.tableName( schemaName, USED_QNAMES_TABLE_NAME ) )
-                    .setTableContentsSource(
-                        d.createTableElementListBuilder()
-                        .addTableElement( d.createColumnDefinition( USED_QNAMES_TABLE_QNAME_COLUMN_NAME, this._primitiveTypes
-                                .get( String.class ), false ) )
-                        .addTableElement( d.createColumnDefinition( USED_QNAMES_TABLE_TABLE_NAME_COLUMN_NAME, this._primitiveTypes
-                                .get( String.class ), false ) )
-                        .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
-                                .setUniqueness( UniqueSpecification.PRIMARY_KEY )
-                                .addColumns( USED_QNAMES_TABLE_QNAME_COLUMN_NAME, USED_QNAMES_TABLE_TABLE_NAME_COLUMN_NAME )
-                                .createExpression()
-                            ) )
-                        .createExpression()
-                    )
-                    .createExpression()
-                )
-            );
-
-            stmt.execute(
-                vendor.toString(
-                    d.createTableDefinitionBuilder()
-                    .setTableName( t.tableName( schemaName, ALL_QNAMES_TABLE_NAME ) )
-                    .setTableContentsSource(
-                        d.createTableElementListBuilder()
-                        .addTableElement( d.createColumnDefinition( ALL_QNAMES_TABLE_PK_COLUMN_NAME, this._primitiveTypes
-                                .get( Integer.class ), false ) )
-                        .addTableElement( d.createColumnDefinition( ENTITY_TABLE_PK_COLUMN_NAME, this._primitiveTypes
-                                .get( ENTITY_PK_TYPE ), false ) )
-                        .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
-                                .setUniqueness( UniqueSpecification.PRIMARY_KEY )
-                                .addColumns( ALL_QNAMES_TABLE_PK_COLUMN_NAME, ENTITY_TABLE_PK_COLUMN_NAME )
-                                .createExpression()
-                            ) )
-                        .addTableElement( d.createTableConstraintDefinition( d.createForeignKeyConstraintBuilder()
-                                .addSourceColumns( ENTITY_TABLE_PK_COLUMN_NAME )
-                                .setTargetTableName( t.tableName( schemaName, ENTITY_TABLE_NAME ) )
-                                .addTargetColumns( ENTITY_TABLE_PK_COLUMN_NAME )
-                                .setOnUpdate( ReferentialAction.CASCADE )
-                                .setOnDelete( ReferentialAction.CASCADE )
-                                .createExpression(), ConstraintCharacteristics.INITIALLY_DEFERRED_DEFERRABLE
-                            ) )
-                        .createExpression()
-                    )
-                    .createExpression()
-                )
-            );
-
-            tablePKs.put( ALL_QNAMES_TABLE_NAME, 0L );
-
-            stmt.execute(
-                vendor.toString(
-                    d.createTableDefinitionBuilder()
-                    .setTableName( t.tableName( schemaName, APP_VERSION_TABLE_NAME ) )
-                    .setTableContentsSource(
-                        d.createTableElementListBuilder()
-                        .addTableElement( d.createColumnDefinition( APP_VERSION_PK_COLUMN_NAME, this._primitiveTypes
-                                .get( String.class ), false ) )
-                        .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
-                                .setUniqueness( UniqueSpecification.PRIMARY_KEY )
-                                .addColumns( APP_VERSION_PK_COLUMN_NAME )
-                                .createExpression()
-                            ) )
-                        .createExpression()
-                    )
-                    .createExpression()
-                )
-            );
-
-            ModificationFactory m = vendor.getModificationFactory();
-
-            PreparedStatement ps = connection.prepareStatement(
-                vendor.toString(
-                    m.insert()
-                    .setTableName( t.tableName( schemaName, APP_VERSION_TABLE_NAME ) )
-                    .setColumnSource(
-                        m.columnSourceByValues()
-                        .addValues( vendor.getLiteralFactory().param() )
-                        .createExpression()
-                    )
-                    .createExpression()
-                )
-            );
-            ps.setString( 1, this._app.version() );
-            ps.execute();
-
-            // TODO INDICES!!!!
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( stmt );
-        }
-
-        // @formatter:on
-        LOGGER.debug( "Indexing SQL database tables created" );
-    }
-
-    private void performReindex( Connection connection )
-        throws SQLException
-    {
-        LOGGER.info( "Performing reindexing..." );
-        // @formatter:off
-        // First delete all entity data
-        DeleteBySearch clearEntityData = this._vendor.getModificationFactory().deleteBySearch()
-            .setTargetTable(
-                this._vendor.getModificationFactory().createTargetTable(
-                    this._vendor.getTableReferenceFactory().tableName(
-                        this._state.schemaName().get(),
-                        ENTITY_TABLE_NAME
-                    )
-                )
-            ).createExpression();
-        connection.prepareStatement( this._vendor.toString( clearEntityData ) ).execute();
-        // @formatter:on
-
-        CONNECTION_FOR_REINDEXING.set( connection );
-        try
-        {
-            this._reindexer.reindex();
-        }
-        finally
-        {
-            CONNECTION_FOR_REINDEXING.set( null );
-        }
-
-        LOGGER.info( "Reindexing complete." );
-    }
-
-    private void readAppMetadataFromDB( Connection connection,
-                                        Map<String, EntityDescriptor> entityDescriptors )
-        throws SQLException
-    {
-
-        String schemaName = this._state.schemaName().get();
-        Statement stmt = connection.createStatement();
-
-        SQLVendor vendor = this._vendor;
-        QueryFactory q = vendor.getQueryFactory();
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-
-        try
-        {
-            // @formatter:off
-
-            q.simpleQueryBuilder()
-                .select( ENTITY_TYPES_TABLE_PK_COLUMN_NAME, ENTITY_TYPES_TABLE_TYPE_NAME_COLUMN_NAME )
-                .from( t.tableName( schemaName, ENTITY_TYPES_TABLE_NAME ) )
-                .createExpression();
-
-            ResultSet rs = stmt.executeQuery(
-                vendor.toString(
-                    q.simpleQueryBuilder()
-                    .select( ENTITY_TYPES_TABLE_PK_COLUMN_NAME, ENTITY_TYPES_TABLE_TYPE_NAME_COLUMN_NAME )
-                    .from( t.tableName( schemaName, ENTITY_TYPES_TABLE_NAME ) )
-                    .createExpression()
-                )
-            );
-
-            long pk;
-            try
-            {
-                while( rs.next() )
-                {
-                    pk = rs.getInt( 1 );
-                    String entityTypeName = rs.getString( 2 );
-                    this._state.entityTypePKs().get().put( entityTypeName, (int) pk );
-//                    this._state.entityTypeInfos().get()
-//                        .put( entityTypeName, new EntityTypeInfo( entityDescriptors.get( entityTypeName ), (int) pk ) );
-                }
-            }
-            finally
-            {
-                SQLUtil.closeQuietly( rs );
-            }
-            rs = stmt.executeQuery(
-                vendor.toString(
-                    q.simpleQueryBuilder()
-                    .select( USED_CLASSES_TABLE_PK_COLUMN_NAME, USED_CLASSES_TABLE_CLASS_NAME_COLUMN_NAME )
-                    .from( t.tableName( schemaName, USED_CLASSES_TABLE_NAME ) )
-                    .createExpression()
-                )
-            );
-
-            try
-            {
-                while( rs.next() )
-                {
-                    pk = rs.getInt( 1 );
-                    String descriptorTextualFormat = rs.getString( 2 );
-                    this._state.usedClassesPKs().get().put(
-                        stringToCompositeDescriptor( ValueDescriptor.class,
-                                                     this._app.descriptor(),
-                                                     descriptorTextualFormat ),
-                        (int) pk );
-                }
-            }
-            finally
-            {
-                SQLUtil.closeQuietly( rs );
-            }
-
-            rs = stmt.executeQuery(
-                vendor.toString(
-                    q.simpleQueryBuilder()
-                    .select( ENUM_LOOKUP_TABLE_PK_COLUMN_NAME, ENUM_LOOKUP_TABLE_ENUM_VALUE_NAME )
-                    .from( t.tableName( schemaName, ENUM_LOOKUP_TABLE_NAME ) )
-                    .createExpression()
-                )
-            );
-
-            try
-            {
-                while( rs.next() )
-                {
-                    pk = rs.getInt( 1 );
-                    String enumName = rs.getString( 2 );
-                    this._state.enumPKs().get().put( enumName, (int) pk );
-                }
-            }
-            finally
-            {
-                SQLUtil.closeQuietly( rs );
-            }
-
-            rs = stmt.executeQuery(
-                q.simpleQueryBuilder()
-                .select( USED_QNAMES_TABLE_QNAME_COLUMN_NAME, USED_QNAMES_TABLE_TABLE_NAME_COLUMN_NAME )
-                .from( t.tableName( schemaName, USED_QNAMES_TABLE_NAME ) )
-                .createExpression()
-                .toString()
-            );
-            try
-            {
-                while( rs.next() )
-                {
-                    String qName = rs.getString( 1 );
-                    String tableName = rs.getString( 2 );
-                    this._state.qNameInfos().get().get( QualifiedName.fromFQN( qName ) ).setTableName( tableName );
-                }
-            }
-            finally
-            {
-                SQLUtil.closeQuietly( rs );
-            }
-
-            // @formatter:on
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( stmt );
-        }
-    }
-
-    private void writeAppMetadataToDB( Connection connection, ApplicationInfo appInfo,
-                                       Map<String, Long> tablePKs )
-        throws SQLException
-    {
-        String schemaName = this._state.schemaName().get();
-
-        SQLVendor vendor = this._vendor;
-        ModificationFactory m = vendor.getModificationFactory();
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-        LiteralFactory l = vendor.getLiteralFactory();
-
-        // @formatter:off
-        PreparedStatement ps = connection.prepareStatement(
-            vendor.toString(
-                m.insert()
-                .setTableName( t.tableName( schemaName, ENTITY_TYPES_TABLE_NAME ) )
-                .setColumnSource( m.columnSourceByValues()
-                    .addValues( l.param(), l.param() )
-                    .createExpression()
-                )
-                .createExpression()
-            )
-        );
-
-        try
-        {
-            Set<String> insertedTypeNames = new HashSet<>();
-            for( EntityDescriptor descriptor : appInfo.entityDescriptors.values() )
-            {
-                for( Class<?> entityType : descriptor.types() )
-                {
-                    String entityTypeName = entityType.getName();
-                    if( !insertedTypeNames.contains( entityTypeName ) )
-                    {
-                        long pk = tablePKs.get( ENTITY_TYPES_TABLE_NAME );
-                        ps.setInt( 1, (int) pk );
-                        ps.setString( 2, entityTypeName );
-                        ps.executeUpdate();
-                        this._state.entityTypePKs().get().put( entityTypeName, (int) pk );
-//                      this._state.entityTypeInfos().get().put( entityTypeName, new EntityTypeInfo( descriptor, (int) pk ) );
-                        tablePKs.put( ENTITY_TYPES_TABLE_NAME, pk + 1 );
-                    }
-                }
-            }
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( ps );
-        }
-
-        ps = connection.prepareStatement(
-            vendor.toString(
-                m.insert()
-                .setTableName( t.tableName( schemaName, USED_CLASSES_TABLE_NAME ) )
-                .setColumnSource( m.columnSourceByValues()
-                    .addValues( l.param(), l.param() )
-                    .createExpression()
-                )
-                .createExpression()
-            )
-        );
-
-        try
-        {
-            for( CompositeDescriptorInfo descInfo : appInfo.usedValueComposites )
-            {
-                String vDescStr = compositeDescriptorToString( descInfo.layer, descInfo.module, descInfo.composite );
-                long pk = tablePKs.get( USED_CLASSES_TABLE_NAME );
-                ps.setInt( 1, (int) pk );
-                ps.setString( 2, vDescStr );
-                ps.executeUpdate();
-                this._state.usedClassesPKs().get().put( descInfo.composite, (int) pk );
-                tablePKs.put( USED_CLASSES_TABLE_NAME, pk + 1 );
-            }
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( ps );
-        }
-
-        ps = connection.prepareStatement(
-            vendor.toString(
-                m.insert()
-                .setTableName( t.tableName( schemaName, ENUM_LOOKUP_TABLE_NAME ) )
-                .setColumnSource( m.columnSourceByValues()
-                    .addValues( l.param(), l.param() )
-                    .createExpression()
-                )
-                .createExpression()
-            )
-        );
-
-        try
-        {
-            for( String enumValue : appInfo.enumValues )
-            {
-                long pk = tablePKs.get( ENUM_LOOKUP_TABLE_NAME );
-                ps.setInt( 1, (int) pk );
-                ps.setString( 2, enumValue );
-                ps.executeUpdate();
-                this._state.enumPKs().get().put( enumValue, (int) pk );
-                tablePKs.put( ENUM_LOOKUP_TABLE_NAME, pk + 1 );
-            }
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( ps );
-        }
-
-        Statement stmt = connection.createStatement();
-        ps = connection.prepareStatement(
-            this.createInsertStatementForQNameInfo( connection, schemaName, vendor ).toString()
-        );
-
-        try
-        {
-            DefinitionFactory d = vendor.getDefinitionFactory();
-
-            for( QNameInfo qNameInfo : this._state.qNameInfos().get().values() )
-            {
-                QNameType type = qNameInfo.getQNameType();
-
-                TableElementListBuilder builder = d.createTableElementListBuilder();
-                builder
-                    .addTableElement( d.createColumnDefinition( ALL_QNAMES_TABLE_PK_COLUMN_NAME, this._primitiveTypes
-                            .get( Integer.class ), false ) )
-                    .addTableElement( d.createColumnDefinition( ENTITY_TABLE_PK_COLUMN_NAME, this._primitiveTypes
-                            .get( ENTITY_PK_TYPE ), false ) );
-
-                if( type.equals( QNameType.PROPERTY ) )
-                {
-                    builder.addTableElement( d.createColumnDefinition( QNAME_TABLE_PARENT_QNAME_COLUMN_NAME, this._primitiveTypes
-                        .get( Integer.class ), true ) );
-
-                    if( qNameInfo.getCollectionDepth() > 0 )
-                    {
-                        builder.addTableElement( d.createColumnDefinition( QNAME_TABLE_COLLECTION_PATH_COLUMN_NAME, this
-                            .getCollectionPathDataType(), false ) );
-                    }
-
-                    this.appendColumnDefinitionsForProperty( builder, qNameInfo );
-
-                    builder.addTableElement( d.createTableConstraintDefinition( d.createForeignKeyConstraintBuilder()
-                        .addSourceColumns( QNAME_TABLE_PARENT_QNAME_COLUMN_NAME, ENTITY_TABLE_PK_COLUMN_NAME )
-                        .setTargetTableName( t.tableName( schemaName, ALL_QNAMES_TABLE_NAME ) )
-                        .addTargetColumns( ALL_QNAMES_TABLE_PK_COLUMN_NAME, ENTITY_TABLE_PK_COLUMN_NAME )
-                        .setOnUpdate( ReferentialAction.CASCADE )
-                        .setOnDelete( ReferentialAction.CASCADE )
-                        .createExpression(), ConstraintCharacteristics.INITIALLY_DEFERRED_DEFERRABLE
-                    ) );
-                }
-                else
-                {
-                    if( type.equals( QNameType.ASSOCIATION ) )
-                    {
-                        builder
-                            .addTableElement( d.createColumnDefinition( QNAME_TABLE_VALUE_COLUMN_NAME, this._primitiveTypes
-                                    .get( ENTITY_PK_TYPE ), false ) )
-                            .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
-                                    .setUniqueness( UniqueSpecification.PRIMARY_KEY )
-                                    .addColumns( ALL_QNAMES_TABLE_PK_COLUMN_NAME, ENTITY_TABLE_PK_COLUMN_NAME )
-                                    .createExpression()
-                                ) );
-                    }
-                    else if( type.equals( QNameType.MANY_ASSOCIATION ) )
-                    {
-                        builder
-                            .addTableElement( d.createColumnDefinition( QNAME_TABLE_ASSOCIATION_INDEX_COLUMN_NAME, this._primitiveTypes
-                                    .get( Integer.class ), false ) )
-                            .addTableElement( d.createColumnDefinition( QNAME_TABLE_VALUE_COLUMN_NAME, this._primitiveTypes
-                                    .get( ENTITY_PK_TYPE ), false ) )
-                            .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
-                                    .setUniqueness( UniqueSpecification.PRIMARY_KEY )
-                                    .addColumns( ALL_QNAMES_TABLE_PK_COLUMN_NAME, ENTITY_TABLE_PK_COLUMN_NAME )
-                                    .createExpression()
-                                ) );
-                    }
-                    else
-                    {
-                        throw new IllegalArgumentException( "Did not how to create table for qName type: " + type + "." );
-                    }
-
-                    builder
-                        .addTableElement( d.createTableConstraintDefinition( d.createForeignKeyConstraintBuilder()
-                                .addSourceColumns( QNAME_TABLE_VALUE_COLUMN_NAME )
-                                .setTargetTableName( t.tableName( schemaName, ENTITY_TABLE_NAME ) )
-                                .addTargetColumns( ENTITY_TABLE_PK_COLUMN_NAME )
-                                .setOnUpdate( ReferentialAction.CASCADE )
-                                .setOnDelete( ReferentialAction.CASCADE )
-                                .createExpression(), ConstraintCharacteristics.INITIALLY_DEFERRED_DEFERRABLE
-                            )
-                        );
-
-                    tablePKs.put( qNameInfo.getTableName(), 0L );
-                }
-
-                builder
-                    .addTableElement(
-                        d.createTableConstraintDefinition( d.createForeignKeyConstraintBuilder()
-                            .addSourceColumns( ALL_QNAMES_TABLE_PK_COLUMN_NAME, ENTITY_TABLE_PK_COLUMN_NAME )
-                            .setTargetTableName( t.tableName( schemaName, ALL_QNAMES_TABLE_NAME ) )
-                            .addTargetColumns( ALL_QNAMES_TABLE_PK_COLUMN_NAME, ENTITY_TABLE_PK_COLUMN_NAME )
-                            .setOnUpdate( ReferentialAction.CASCADE )
-                            .setOnDelete( ReferentialAction.CASCADE )
-                            .createExpression(), ConstraintCharacteristics.INITIALLY_DEFERRED_DEFERRABLE
-                        )
-                    );
-
-                stmt.execute( this._vendor.toString( d.createTableDefinitionBuilder()
-                    .setTableName( t.tableName( schemaName, qNameInfo.getTableName() ) )
-                    .setTableContentsSource( builder.createExpression() )
-                    .createExpression()
-                ) );
-
-                //                stmt.execute( "COMMENT ON TABLE " + schemaName + "." + qNameInfo.getTableName() + " IS '"
-                //                    + qNameInfo.getQName() + "'" );
-                ps.setString( 1, qNameInfo.getQName().toString() );
-                ps.setString( 2, qNameInfo.getTableName() );
-                ps.execute();
-            }
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( stmt );
-            SQLUtil.closeQuietly( ps );
-        }
-
-        // @formatter:off
-    }
-
-    private InsertStatement createInsertStatementForQNameInfo( Connection connection,
-                                                               String schemaName, SQLVendor vendor )
-    {
-        ModificationFactory m = vendor.getModificationFactory();
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-        LiteralFactory l = vendor.getLiteralFactory();
-
-        return m.insert()
-            .setTableName( t.tableName( schemaName, USED_QNAMES_TABLE_NAME ) )
-            .setColumnSource( m.columnSourceByValues()
-                .addValues( l.param(), l.param() )
-                .createExpression()
-            ).createExpression();
-    }
-
-    private void appendColumnDefinitionsForProperty( TableElementListBuilder builder,
-                                                     QNameInfo qNameInfo )
-    {
-        Type finalType = qNameInfo.getFinalType();
-        if( finalType instanceof ParameterizedType )
-        {
-            finalType = ( (ParameterizedType) finalType ).getRawType();
-        }
-        Class<?> finalClass = (Class<?>) finalType;
-        SQLDataType sqlType = null;
-        String valueRefTableName = null;
-        String valueRefTablePKColumnName = null;
-        if( qNameInfo.isFinalTypePrimitive() )
-        {
-
-            if( this._customizableTypes.keySet().contains( finalClass )
-                && qNameInfo.getPropertyDescriptor().accessor()
-                .isAnnotationPresent( SQLTypeInfo.class ) )
-            {
-                sqlType = this._customizableTypes.get( finalClass ).customizeType( finalClass,
-                                                                                   qNameInfo.getPropertyDescriptor()
-                    .accessor()
-                    .getAnnotation( SQLTypeInfo.class ) );
-            }
-            else if( Enum.class.isAssignableFrom( finalClass ) )
-            {
-                // Enum - reference the lookup table
-                sqlType = this._primitiveTypes.get( Integer.class );
-                valueRefTableName = ENUM_LOOKUP_TABLE_NAME;
-                valueRefTablePKColumnName = ENUM_LOOKUP_TABLE_PK_COLUMN_NAME;
-            }
-            else
-            {
-                // Primitive type, default sqlType
-                sqlType = this._primitiveTypes.get( finalClass );
-            }
-
-            if( sqlType == null )
-            {
-                throw new InternalError( "Could not find sql type for java type [" + finalType + "]" );
-            }
-        }
-        else
-        {
-            // Value composite - just need used class
-            sqlType = this._primitiveTypes.get( Integer.class );
-            valueRefTableName = USED_CLASSES_TABLE_NAME;
-            valueRefTablePKColumnName = USED_CLASSES_TABLE_PK_COLUMN_NAME;
-        }
-
-        SQLVendor vendor = this._vendor;
-        DefinitionFactory d = vendor.getDefinitionFactory();
-        TableReferenceFactory t = vendor.getTableReferenceFactory();
-
-        builder
-            .addTableElement(
-                d.createColumnDefinition( QNAME_TABLE_VALUE_COLUMN_NAME, sqlType,
-                                          qNameInfo.getCollectionDepth() > 0 ) )
-            .addTableElement( d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
-                    .setUniqueness( UniqueSpecification.PRIMARY_KEY )
-                    .addColumns( ALL_QNAMES_TABLE_PK_COLUMN_NAME, ENTITY_TABLE_PK_COLUMN_NAME )
-                    .createExpression()
-                ) );
-
-        if( valueRefTableName != null && valueRefTablePKColumnName != null )
-        {
-            builder
-                .addTableElement( d.createTableConstraintDefinition( d
-                        .createForeignKeyConstraintBuilder()
-                        .addSourceColumns( QNAME_TABLE_VALUE_COLUMN_NAME )
-                        .setTargetTableName( t.tableName( this._state
-                                .schemaName()
-                                .get(), valueRefTableName ) )
-                        .addTargetColumns( valueRefTablePKColumnName )
-                        .setOnUpdate( ReferentialAction.CASCADE )
-                        .setOnDelete( ReferentialAction.RESTRICT )
-                        .createExpression(), ConstraintCharacteristics.NOT_DEFERRABLE
-                    ) );
-        }
-    }
-
-    protected Long getNextPK( Statement stmt, String schemaName, String columnName,
-                              String tableName, Long defaultPK
-    )
-        throws SQLException
-    {
-        ResultSet rs = null;
-        Long result = defaultPK;
-        try
-        {
-            SQLVendor vendor = this._vendor;
-            QueryFactory q = vendor.getQueryFactory();
-            // Let's cheat a bit on SQL functions, so we won't need to use heavy query builder.
-            // Also, currently there are no arithmetic statements
-            rs
-            = stmt.executeQuery(
-                vendor
-                .toString(
-                    q.simpleQueryBuilder()
-                    .select( "COUNT(" + columnName + ")", "MAX(" + columnName + ") + 1" )
-                    .from(
-                        vendor.getTableReferenceFactory().tableName( schemaName, tableName ) )
-                    .createExpression()
-                )
-            );
-            if( rs.next() )
-            {
-                Long count = rs.getLong( 1 );
-                if( count > 0 )
-                {
-                    result = rs.getLong( 2 );
-                }
-            }
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( rs );
-        }
-
-        return result;
-    }
-
-    // This method assume that the schema exists
-    private Boolean isReindexingNeeded( Connection connection )
-        throws SQLException
-    {
-        Boolean result = true;
-        String schemaName = this._state.schemaName().get();
-        Statement stmt = connection.createStatement();
-        try
-        {
-            QueryExpression getAppVersionQuery
-                            = this._vendor
-                .getQueryFactory()
-                .simpleQueryBuilder()
-                .select( APP_VERSION_PK_COLUMN_NAME )
-                .from(
-                    this._vendor.getTableReferenceFactory().tableName( schemaName,
-                                                                       APP_VERSION_TABLE_NAME ) )
-                .createExpression();
-            ResultSet rs = null;
-            try
-            {
-                rs = stmt.executeQuery( this._vendor.toString( getAppVersionQuery ) );
-            }
-            catch( SQLException sqle )
-            {
-                // Sometimes meta data claims table exists, even when it really doesn't exist
-            }
-
-            if( rs != null )
-            {
-                result = !rs.next();
-
-                if( !result )
-                {
-
-                    String dbAppVersion = rs.getString( 1 );
-                    if( this._reindexingStrategy != null )
-                    {
-                        result
-                        = this._reindexingStrategy.reindexingNeeded( dbAppVersion,
-                                                                     this._app.version() );
-                    }
-                }
-            }
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( stmt );
-        }
-
-        return result;
-    }
-
-    private String readAppVersionFromDB( Connection connection, String schemaName )
-        throws SQLException
-    {
-        Statement stmt = connection.createStatement();
-        String result = null;
-        try
-        {
-            QueryExpression getAppVersionQuery
-                            = this._vendor
-                .getQueryFactory()
-                .simpleQueryBuilder()
-                .select( APP_VERSION_PK_COLUMN_NAME )
-                .from(
-                    this._vendor.getTableReferenceFactory().tableName( schemaName,
-                                                                       APP_VERSION_TABLE_NAME ) )
-                .createExpression();
-            ResultSet rs = null;
-            try
-            {
-                rs = stmt.executeQuery( getAppVersionQuery.toString() );
-
-                if( rs.next() )
-                {
-                    result = rs.getString( 1 );
-                }
-            }
-            catch( SQLException sqle )
-            {
-                // Sometimes meta data claims table exists, even when it really doesn't exist
-            }
-            finally
-            {
-                SQLUtil.closeQuietly( rs );
-            }
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( stmt );
-        }
-
-        return result;
-    }
-
-    private static void clearSchema( Connection connection, String schemaName, SQLVendor vendor )
-        throws SQLException
-    {
-        ModificationFactory m = vendor.getModificationFactory();
-        Statement stmt = null;
-        try
-        {
-            connection.setReadOnly( false );
-            stmt = connection.createStatement();
-            stmt.execute( m.deleteBySearch().setTargetTable( m.createTargetTable(
-                vendor.getTableReferenceFactory().tableName( schemaName, DBNames.ENTITY_TABLE_NAME ) ) )
-                .createExpression().toString()
-            );
-            connection.commit();
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( stmt );
-        }
-    }
-
-    private void destroyNeededSchemaTables( Connection connection, String schemaName, int maxQNameUsed )
-        throws SQLException
-    {
-        Statement stmt = connection.createStatement();
-        try
-        {
-            this.dropTablesIfExist( schemaName, ENTITY_TABLE_NAME, stmt );
-            this.dropTablesIfExist( schemaName, ALL_QNAMES_TABLE_NAME, stmt );
-            this.dropTablesIfExist( schemaName, APP_VERSION_TABLE_NAME, stmt );
-            this.dropTablesIfExist( schemaName, ENTITY_TYPES_TABLE_NAME, stmt );
-            this.dropTablesIfExist( schemaName, ENTITY_TYPES_JOIN_TABLE_NAME, stmt );
-            this.dropTablesIfExist( schemaName, ENUM_LOOKUP_TABLE_NAME, stmt );
-            this.dropTablesIfExist( schemaName, USED_CLASSES_TABLE_NAME, stmt );
-            this.dropTablesIfExist( schemaName, USED_QNAMES_TABLE_NAME, stmt );
-
-            for( int x = 0; x <= maxQNameUsed; ++x )
-            {
-                this.dropTablesIfExist( schemaName, DBNames.QNAME_TABLE_NAME_PREFIX
-                                                    + x, stmt );
-            }
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( stmt );
-        }
-    }
-
-    private ApplicationInfo constructApplicationInfo( Boolean setQNameTableNameToNull )
-        throws SQLException
-    {
-        final ApplicationInfo appInfo = new ApplicationInfo();
-        final List<CompositeDescriptorInfo> valueDescriptors = new ArrayList<>();
-        final Deque<Object> currentPath = new ArrayDeque<>();
-        _app.descriptor().accept(
-            new HierarchicalVisitorAdapter<Object, Object, RuntimeException>()
-            {
-                @Override
-                public boolean visitEnter( Object visited )
-                throws RuntimeException
-                {
-                    if( visited instanceof LayerDescriptor || visited instanceof ModuleDescriptor )
-                    {
-                        currentPath.push( visited );
-                    }
-                    if( visited instanceof EntityDescriptor || visited instanceof ValueDescriptor )
-                    {
-                        // TODO filter non-visible descriptors away.
-                        if( visited instanceof EntityDescriptor )
-                        {
-                            EntityDescriptor entityDescriptor = (EntityDescriptor) visited;
-                            if( entityDescriptor.queryable() )
-                            {
-                                LOGGER.debug( "THIS ONE WORKS: {}", entityDescriptor );
-                                appInfo.entityDescriptors.put( first( entityDescriptor.types() )
-                                    .getName(), entityDescriptor );
-                            }
-                        }
-                        else
-                        {
-                            valueDescriptors.add( new CompositeDescriptorInfo(
-                                    (LayerDescriptor) Iterables
-                                    .first( Iterables.skip( 1, currentPath ) ),
-                                    (ModuleDescriptor) Iterables.first( currentPath ),
-                                    (CompositeDescriptor) visited ) );
-                        }
-
-                        return false;
-                    }
-
-                    return true;
-                }
-
-                @Override
-                public boolean visitLeave( Object visited )
-                {
-                    if( visited instanceof LayerDescriptor || visited instanceof ModuleDescriptor )
-                    {
-                        currentPath.pop();
-                    }
-                    return true;
-                }
-            } );
-
-        for( EntityDescriptor descriptor : appInfo.entityDescriptors.values() )
-        {
-            Set<QualifiedName> newQNames = new HashSet<>();
-            this.extractPropertyQNames( descriptor, this._state.qNameInfos().get(), newQNames,
-                                        valueDescriptors,
-                                        appInfo.enumValues, setQNameTableNameToNull );
-            this.extractAssociationQNames( descriptor, this._state.qNameInfos().get(), newQNames,
-                                           setQNameTableNameToNull );
-            this.extractManyAssociationQNames( descriptor, this._state.qNameInfos().get(),
-                                               newQNames,
-                                               setQNameTableNameToNull );
-            this._state.entityUsedQNames().get().put( descriptor, newQNames );
-        }
-
-        appInfo.usedValueComposites.addAll( valueDescriptors );
-        return appInfo;
-    }
-
-    private void processPropertyTypeForQNames( PropertyDescriptor pType,
-                                               Map<QualifiedName, QNameInfo> qNameInfos,
-                                               Set<QualifiedName> newQNames,
-                                               List<CompositeDescriptorInfo> vDescriptors,
-                                               Set<String> enumValues,
-                                               Boolean setQNameTableNameToNull
-    )
-    {
-        QualifiedName qName = pType.qualifiedName();
-        if( !newQNames.contains( qName ) && !qName.name().equals( Identity.class.getName() ) )
-        {
-            newQNames.add( qName );
-            QNameInfo info = qNameInfos.get( qName );
-            if( info == null )
-            {
-                info
-                = QNameInfo.fromProperty(
-                    //
-                    qName, //
-                    setQNameTableNameToNull ? null : ( QNAME_TABLE_NAME_PREFIX + qNameInfos
-                                                      .size() ), //
-                    pType//
-                );
-                qNameInfos.put( qName, info );
-            }
-            Type vType = info.getFinalType();
-
-            while( vType instanceof ParameterizedType )
-            {
-                vType = ( (ParameterizedType) vType ).getRawType();
-            }
-            if( vType instanceof Class<?> ) //
-            {
-                final Class<?> vTypeClass = (Class<?>) vType;
-                if( ( (Class<?>) vType ).isInterface() )
-                {
-                    for( CompositeDescriptorInfo descInfo : vDescriptors )
-                    {
-                        CompositeDescriptor desc = descInfo.composite;
-                        if( desc instanceof ValueDescriptor )
-                        {
-                            ValueDescriptor vDesc = (ValueDescriptor) desc;
-                            // TODO this doesn't understand, say, Map<String, String>, or indeed,
-                            // any
-                            // other Serializable
-                            if( Iterables.matchesAny( new Specification<Class<?>>()
-                            {
-                                @Override
-                                public boolean satisfiedBy( Class<?> item )
-                                {
-                                    return vTypeClass.isAssignableFrom( item );
-                                }
-                            }, vDesc.types() ) )
-                            {
-                                for( PropertyDescriptor subPDesc : vDesc.state().properties() )
-                                {
-                                    this.processPropertyTypeForQNames( //
-                                        subPDesc, //
-                                        qNameInfos, //
-                                        newQNames, //
-                                        vDescriptors, //
-                                        enumValues, //
-                                        setQNameTableNameToNull //
-                                    );
-                                }
-                            }
-                        }
-                    }
-                }
-                else if( Enum.class.isAssignableFrom( (Class<?>) vType ) )
-                {
-                    for( Object value : ( (Class<?>) vType ).getEnumConstants() )
-                    {
-                        enumValues.add( QualifiedName
-                            .fromClass( (Class<?>) vType, value.toString() ).toString() );
-                    }
-                }
-            }
-        }
-    }
-
-    private void extractPropertyQNames( EntityDescriptor entityDesc,
-                                        Map<QualifiedName, QNameInfo> qNameInfos,
-                                        Set<QualifiedName> newQNames,
-                                        List<CompositeDescriptorInfo> vDescriptors,
-                                        Set<String> enumValues,
-                                        Boolean setQNameTableNameToNull
-    )
-    {
-        for( PropertyDescriptor pDesc : entityDesc.state().properties() )
-        {
-            if( SQLSkeletonUtil.isQueryable( pDesc.accessor() ) )
-            {
-                this.processPropertyTypeForQNames( //
-                    pDesc, //
-                    qNameInfos, //
-                    newQNames, //
-                    vDescriptors, //
-                    enumValues, //
-                    setQNameTableNameToNull //
-                );
-            }
-        }
-    }
-
-    private void extractAssociationQNames( EntityDescriptor entityDesc,
-                                           Map<QualifiedName, QNameInfo> extractedQNames,
-                                           Set<QualifiedName> newQNames, Boolean setQNameTableNameToNull
-    )
-    {
-        for( AssociationDescriptor assoDesc : entityDesc.state().associations() )
-        {
-            if( SQLSkeletonUtil.isQueryable( assoDesc.accessor() ) )
-            {
-                QualifiedName qName = assoDesc.qualifiedName();
-                if( !extractedQNames.containsKey( qName ) )
-                {
-                    extractedQNames.put( qName,//
-                                         QNameInfo.fromAssociation( //
-                        qName, //
-                        setQNameTableNameToNull ? null
-                        : ( QNAME_TABLE_NAME_PREFIX + extractedQNames
-                           .size() ), //
-                        assoDesc //
-                    ) //
-                    );
-                    newQNames.add( qName );
-                }
-            }
-        }
-    }
-
-    private void extractManyAssociationQNames( EntityDescriptor entityDesc,
-                                               Map<QualifiedName, QNameInfo> extractedQNames,
-                                               Set<QualifiedName> newQNames,
-                                               Boolean setQNameTableNameToNull
-    )
-    {
-        for( AssociationDescriptor mAssoDesc : entityDesc.state().manyAssociations() )
-        {
-            QualifiedName qName = mAssoDesc.qualifiedName();
-            if( SQLSkeletonUtil.isQueryable( mAssoDesc.accessor() ) )
-            {
-                if( !extractedQNames.containsKey( qName ) )
-                {
-                    extractedQNames.put( //
-                        qName, //
-                        QNameInfo.fromManyAssociation( //
-                        qName, //
-                        setQNameTableNameToNull ? null
-                        : ( QNAME_TABLE_NAME_PREFIX + extractedQNames
-                           .size() ), //
-                        mAssoDesc //
-                    ) //
-                    );
-                    newQNames.add( qName );
-                }
-            }
-        }
-    }
-
-    protected abstract void testRequiredCapabilities( Connection connection )
-        throws SQLException;
-
-    protected boolean dropTablesIfExist(
-        String schemaName,
-        String tableName,
-        Statement stmt
-    )
-        throws SQLException
-    {
-        boolean result = false;
-        try
-        {
-            stmt.execute( this._vendor.toString( this._vendor.getManipulationFactory()
-                .createDropTableOrViewStatement(
-                    this._vendor
-                    .getTableReferenceFactory()
-                    .tableName( schemaName, tableName ), ObjectType.TABLE,
-                    DropBehaviour.CASCADE
-                ) ) );
-            result = true;
-        }
-        catch( SQLException sqle )
-        {
-            // Ignore
-        }
-        return result;
-    }
-
-    private static final String DESCRIPTOR_COMPONENT_SEPARATOR_START = "{";
-    private static final String DESCRIPTOR_COMPONENT_SEPARATOR_END = "}";
-    private static final String DESCRIPTOR_TYPE_SEPARATOR = ",";
-    private static final Pattern DESCRIPTOR_TYPES_REGEXP = Pattern.compile(
-        "[^" + Pattern.quote( DESCRIPTOR_TYPE_SEPARATOR ) + "]+" );
-    private static final Pattern DESCRIPTOR_TEXTUAL_REGEXP = Pattern.compile(
-        "^"
-        + Pattern.quote( DESCRIPTOR_COMPONENT_SEPARATOR_START ) + "(.*)"
-        + Pattern.quote( DESCRIPTOR_COMPONENT_SEPARATOR_END )
-        + Pattern.quote( DESCRIPTOR_COMPONENT_SEPARATOR_START ) + "(.*)"
-        + Pattern.quote( DESCRIPTOR_COMPONENT_SEPARATOR_END )
-        + Pattern.quote( DESCRIPTOR_COMPONENT_SEPARATOR_START ) + "(" + "[^"
-        + Pattern.quote( DESCRIPTOR_COMPONENT_SEPARATOR_END + DESCRIPTOR_TYPE_SEPARATOR )
-        + "]+)" + Pattern.quote( DESCRIPTOR_COMPONENT_SEPARATOR_END ) + "$" );
-
-    protected static String compositeDescriptorToString( LayerDescriptor layer,
-                                                         ModuleDescriptor module, CompositeDescriptor descriptor )
-    {
-        return DESCRIPTOR_COMPONENT_SEPARATOR_START + layer.name()
-               + DESCRIPTOR_COMPONENT_SEPARATOR_END + DESCRIPTOR_COMPONENT_SEPARATOR_START
-               + module.name() + DESCRIPTOR_COMPONENT_SEPARATOR_END
-               + DESCRIPTOR_COMPONENT_SEPARATOR_START
-               + Iterables.toString( descriptor.types(), new Function<Class<?>, String>()
-        {
-            @Override
-            public String map( Class<?> item )
-            {
-                return item.getName();
-            }
-        }, DESCRIPTOR_TYPE_SEPARATOR ) + DESCRIPTOR_COMPONENT_SEPARATOR_END;
-    }
-
-    protected static <TCompositeDescriptor extends CompositeDescriptor> TCompositeDescriptor
-        stringToCompositeDescriptor( final Class<TCompositeDescriptor> descriptorClass,
-                                     ApplicationDescriptor appDesc, String str )
-    {
-        Matcher matcher = DESCRIPTOR_TEXTUAL_REGEXP.matcher( str );
-        if( !matcher.matches() )
-        {
-            throw new IllegalArgumentException( "Descriptor textual description " + str
-                                                + " was invalid." );
-        }
-
-        final String layerName = matcher.group( 1 );
-        final String moduleName = matcher.group( 2 );
-        final Set<String> classNames = new HashSet<>();
-        Matcher typesMatcher = DESCRIPTOR_TYPES_REGEXP.matcher( matcher.group( 3 ) );
-        while( typesMatcher.find() )
-        {
-            classNames.add( typesMatcher.group( 0 ) );
-        }
-        final CompositeDescriptor[] result = new CompositeDescriptor[ 1 ];
-
-        appDesc.accept( new HierarchicalVisitorAdapter<Object, Object, RuntimeException>()
-        {
-            @Override
-            public boolean visitEnter( Object visited )
-            {
-                boolean thisResult = true;
-                if( visited instanceof LayerDescriptor )
-                {
-                    thisResult = ( (LayerDescriptor) visited ).name().equals( layerName );
-                }
-                else if( visited instanceof ModuleDescriptor )
-                {
-                    thisResult = ( (ModuleDescriptor) visited ).name().equals( moduleName );
-                }
-                else if( descriptorClass.isAssignableFrom( visited.getClass() ) )
-                {
-                    CompositeDescriptor desc = (CompositeDescriptor) visited;
-                    if( classNames.equals( new HashSet<>( Iterables.toList( Iterables.map(
-                        new Function<Class<?>, String>()
-                        {
-                            @Override
-                            public String map( Class<?> from )
-                            {
-                                return from.getName();
-                            }
-                        }, desc.types() ) ) ) ) )
-                    {
-                        result[0] = desc;
-                        thisResult = false;
-                    }
-                }
-                return thisResult;
-            }
-
-            @Override
-            public boolean visitLeave( Object visited )
-            {
-                return result[0] == null;
-            }
-        } );
-
-        return (TCompositeDescriptor) result[0];
-    }
-
-    protected abstract void modifyPrimitiveTypes( Map<Class<?>, SQLDataType> primitiveTypes,
-                                                  Map<Class<?>, Integer> jdbcTypes
-    );
-
-    protected abstract SQLDataType getCollectionPathDataType();
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/SQLCompatEntityStateWrapper.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/SQLCompatEntityStateWrapper.java
deleted file mode 100644
index 2dad7f1..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/SQLCompatEntityStateWrapper.java
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.skeletons;
-
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationStateDescriptor;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.type.CollectionType;
-import org.qi4j.api.type.ValueCompositeType;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.EntityStatus;
-import org.qi4j.spi.entity.ManyAssociationState;
-import org.qi4j.spi.entity.NamedAssociationState;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * EntityState wrapper used by AbstractSQLIndexing to filter out unsupported properties.
- *
- * <p>This allows to disable unsupported properties indexing to prevent failures in the SQL Index/Query engine.</p>
- * <p>When an unsupported Property is found it is logged at WARN level.</p>
- */
-/* package */ class SQLCompatEntityStateWrapper
-    implements EntityState
-{
-    private static final Logger LOGGER = LoggerFactory.getLogger( SQLCompatEntityStateWrapper.class.getName() );
-
-    /* package */ static final Function<EntityState, EntityState> WRAP = new Function<EntityState, EntityState>()
-    {
-
-        @Override
-        public EntityState map( EntityState from )
-        {
-            return new SQLCompatEntityStateWrapper( from );
-        }
-    };
-    private static final Specification<PropertyDescriptor> PROPERTY_SPEC = new Specification<PropertyDescriptor>()
-    {
-
-        @Override
-        public boolean satisfiedBy( PropertyDescriptor propertyDescriptor )
-        {
-            boolean supported = isSupported( propertyDescriptor.valueType() );
-            if( !supported )
-            {
-                LOGGER.warn( "Unsupported Property type: " + propertyDescriptor );
-            }
-            return supported;
-        }
-
-        private boolean isSupported( ValueType valueType )
-        {
-            if( valueType instanceof CollectionType )
-            {
-                CollectionType collectionType = (CollectionType) valueType;
-                return isSupported( collectionType.collectedType() );
-            }
-            Class<?> mainType = valueType.mainType();
-            return Number.class.isAssignableFrom( mainType )
-                   || Boolean.class.isAssignableFrom( mainType )
-                   || Character.class.isAssignableFrom( mainType )
-                   || Enum.class.isAssignableFrom( mainType )
-                   || String.class.isAssignableFrom( mainType )
-                   // || Date.class.isAssignableFrom( mainType )
-                   // || DateTime.class.isAssignableFrom( mainType )
-                   // || LocalDateTime.class.isAssignableFrom( mainType )
-                   // || LocalDate.class.isAssignableFrom( mainType )
-                   || valueType instanceof ValueCompositeType;
-        }
-    };
-
-    private final EntityState wrappedEntityState;
-
-    /* package */ SQLCompatEntityStateWrapper( EntityState wrapped )
-    {
-        this.wrappedEntityState = wrapped;
-    }
-
-    @Override
-    public EntityReference identity()
-    {
-        return wrappedEntityState.identity();
-    }
-
-    @Override
-    public String version()
-    {
-        return wrappedEntityState.version();
-    }
-
-    @Override
-    public long lastModified()
-    {
-        return wrappedEntityState.lastModified();
-    }
-
-    @Override
-    public void remove()
-    {
-        wrappedEntityState.remove();
-    }
-
-    @Override
-    public EntityStatus status()
-    {
-        return wrappedEntityState.status();
-    }
-
-    @Override
-    public boolean isAssignableTo( Class<?> type )
-    {
-        return wrappedEntityState.isAssignableTo( type );
-    }
-
-    @Override
-    public EntityDescriptor entityDescriptor()
-    {
-        return new CompatEntityDescriptorWrapper( wrappedEntityState.entityDescriptor() );
-    }
-
-    @Override
-    public Object propertyValueOf( QualifiedName stateName )
-    {
-        return wrappedEntityState.propertyValueOf( stateName );
-    }
-
-    @Override
-    public void setPropertyValue( QualifiedName stateName, Object json )
-    {
-        wrappedEntityState.setPropertyValue( stateName, json );
-    }
-
-    @Override
-    public EntityReference associationValueOf( QualifiedName stateName )
-    {
-        return wrappedEntityState.associationValueOf( stateName );
-    }
-
-    @Override
-    public void setAssociationValue( QualifiedName stateName, EntityReference newEntity )
-    {
-        wrappedEntityState.setAssociationValue( stateName, newEntity );
-    }
-
-    @Override
-    public ManyAssociationState manyAssociationValueOf( QualifiedName stateName )
-    {
-        return wrappedEntityState.manyAssociationValueOf( stateName );
-    }
-
-    @Override
-    public NamedAssociationState namedAssociationValueOf( QualifiedName stateName )
-    {
-        return wrappedEntityState.namedAssociationValueOf( stateName );
-    }
-
-    @Override
-    @SuppressWarnings( "EqualsWhichDoesntCheckParameterClass" )
-    public boolean equals( Object obj )
-    {
-        return wrappedEntityState.equals( obj );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return wrappedEntityState.hashCode();
-    }
-
-    private static class CompatEntityDescriptorWrapper
-        implements EntityDescriptor
-    {
-        private final EntityDescriptor wrappedEntityDescriptor;
-
-        private CompatEntityDescriptorWrapper( EntityDescriptor wrappedEntityDescriptor )
-        {
-            this.wrappedEntityDescriptor = wrappedEntityDescriptor;
-        }
-
-        @Override
-        public AssociationStateDescriptor state()
-        {
-            return new CompatAssociationStateDescriptorWrapper( wrappedEntityDescriptor.state() );
-        }
-
-        @Override
-        public boolean queryable()
-        {
-            return wrappedEntityDescriptor.queryable();
-        }
-
-        @Override
-        public Class<?> primaryType()
-        {
-            return wrappedEntityDescriptor.primaryType();
-        }
-
-        @Override
-        public Iterable<Class<?>> mixinTypes()
-        {
-            return wrappedEntityDescriptor.mixinTypes();
-        }
-
-        @Override
-        public Visibility visibility()
-        {
-            return wrappedEntityDescriptor.visibility();
-        }
-
-        @Override
-        public boolean isAssignableTo( Class<?> type )
-        {
-            return wrappedEntityDescriptor.isAssignableTo( type );
-        }
-
-        @Override
-        public Iterable<Class<?>> types()
-        {
-            return wrappedEntityDescriptor.types();
-        }
-
-        @Override
-        public <T> T metaInfo( Class<T> infoType )
-        {
-            return wrappedEntityDescriptor.metaInfo( infoType );
-        }
-
-        @Override
-        @SuppressWarnings( "EqualsWhichDoesntCheckParameterClass" )
-        public boolean equals( Object obj )
-        {
-            return wrappedEntityDescriptor.equals( obj );
-        }
-
-        @Override
-        public int hashCode()
-        {
-            return wrappedEntityDescriptor.hashCode();
-        }
-    }
-
-    private static class CompatAssociationStateDescriptorWrapper
-        implements AssociationStateDescriptor
-    {
-        private final AssociationStateDescriptor wrappedAssociationStateDescriptor;
-
-        private CompatAssociationStateDescriptorWrapper( AssociationStateDescriptor wrappedAssociationStateDescriptor )
-        {
-            this.wrappedAssociationStateDescriptor = wrappedAssociationStateDescriptor;
-        }
-
-        @Override
-        public AssociationDescriptor getAssociationByName( String name )
-            throws IllegalArgumentException
-        {
-            return wrappedAssociationStateDescriptor.getAssociationByName( name );
-        }
-
-        @Override
-        public AssociationDescriptor getAssociationByQualifiedName( QualifiedName name )
-            throws IllegalArgumentException
-        {
-            return wrappedAssociationStateDescriptor.getAssociationByQualifiedName( name );
-        }
-
-        @Override
-        public AssociationDescriptor getManyAssociationByName( String name )
-            throws IllegalArgumentException
-        {
-            return wrappedAssociationStateDescriptor.getManyAssociationByName( name );
-        }
-
-        @Override
-        public AssociationDescriptor getManyAssociationByQualifiedName( QualifiedName name )
-            throws IllegalArgumentException
-        {
-            return wrappedAssociationStateDescriptor.getManyAssociationByQualifiedName( name );
-        }
-
-        @Override
-        public AssociationDescriptor getNamedAssociationByName( String name )
-            throws IllegalArgumentException
-        {
-            return wrappedAssociationStateDescriptor.getNamedAssociationByName( name );
-        }
-
-        @Override
-        public AssociationDescriptor getNamedAssociationByQualifiedName( QualifiedName name )
-            throws IllegalArgumentException
-        {
-            return wrappedAssociationStateDescriptor.getNamedAssociationByQualifiedName( name );
-        }
-
-        @Override
-        public Iterable<? extends AssociationDescriptor> associations()
-        {
-            return wrappedAssociationStateDescriptor.associations();
-        }
-
-        @Override
-        public Iterable<? extends AssociationDescriptor> manyAssociations()
-        {
-            return wrappedAssociationStateDescriptor.manyAssociations();
-        }
-
-        @Override
-        public Iterable<? extends AssociationDescriptor> namedAssociations()
-        {
-            return wrappedAssociationStateDescriptor.namedAssociations();
-        }
-
-        @Override
-        public PropertyDescriptor findPropertyModelByName( String name )
-            throws IllegalArgumentException
-        {
-            return wrappedAssociationStateDescriptor.findPropertyModelByName( name );
-        }
-
-        @Override
-        public PropertyDescriptor findPropertyModelByQualifiedName( QualifiedName name )
-            throws IllegalArgumentException
-        {
-            return wrappedAssociationStateDescriptor.findPropertyModelByQualifiedName( name );
-        }
-
-        @Override
-        public Iterable<? extends PropertyDescriptor> properties()
-        {
-            return Iterables.filter( PROPERTY_SPEC, wrappedAssociationStateDescriptor.properties() );
-        }
-
-        @Override
-        @SuppressWarnings( "EqualsWhichDoesntCheckParameterClass" )
-        public boolean equals( Object obj )
-        {
-            return wrappedAssociationStateDescriptor.equals( obj );
-        }
-
-        @Override
-        public int hashCode()
-        {
-            return wrappedAssociationStateDescriptor.hashCode();
-        }
-    }
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/SQLDBState.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/SQLDBState.java
deleted file mode 100644
index 06bc31d..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/SQLDBState.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.skeletons;
-
-import java.sql.Types;
-import java.util.Map;
-import java.util.Set;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.property.Property;
-import org.qi4j.index.sql.support.api.SQLIndexing;
-import org.qi4j.index.sql.support.common.QNameInfo;
-
-/**
- * The state-type interface containing some important database-related data, in order to create
- * proper SQL statements in indexing ({@link SQLIndexing}), querying (
- * {@link org.qi4j.index.sql.support.api.SQLQuerying}) and application startup (
- * {@link org.qi4j.index.sql.support.api.SQLAppStartup}.
- */
-public interface SQLDBState
-{
-    /**
-     * The schema name where all the required tables are located.
-     *
-     * @return The schema name where all the required tables are located.
-     */
-    @Optional
-    Property<String> schemaName();
-
-    /**
-     * Information about all used qualified names.
-     *
-     * @return Information about all used qualified names.
-     * @see QNameInfo
-     */
-    @Optional
-    Property<Map<QualifiedName, QNameInfo>> qNameInfos();
-
-    /**
-     * Information about all used qualified names in a certain entity type. The interface name of
-     * entity type serves as the key.
-     *
-     * @return Information about all used qualified names in a certain entity type.
-     */
-    @Optional
-    Property<Map<EntityDescriptor, Set<QualifiedName>>> entityUsedQNames();
-
-    /**
-     * Primary keys of all used composites in all entities of this application. (Value) Composite
-     * descriptor is the key.
-     *
-     * @return Primary keys of all used classes (of value composites) in all entity types.
-     */
-    @Optional
-    Property<Map<CompositeDescriptor, Integer>> usedClassesPKs();
-
-    @Optional
-    Property<Map<String, Integer>> entityTypePKs();
-
-    /**
-     * A mapping between java type and the ones in {@link Types}. The class of java type is the key.
-     *
-     * @return A mapping between java type and the ones in {@link Types}.
-     */
-    @Optional
-    Property<Map<Class<?>, Integer>> javaTypes2SQLTypes();
-
-    @Optional
-    Property<Map<String, Integer>> enumPKs();
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/SQLSkeletonUtil.java b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/SQLSkeletonUtil.java
deleted file mode 100644
index 69b132a..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/SQLSkeletonUtil.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- *
- * Licensed  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.qi4j.index.sql.support.skeletons;
-
-import java.lang.reflect.AccessibleObject;
-import org.qi4j.api.entity.Queryable;
-
-/* package */ final class SQLSkeletonUtil
-{
-
-    /* package */ static boolean isQueryable( AccessibleObject accessor )
-    {
-        Queryable q = accessor.getAnnotation( Queryable.class );
-        return q == null || q.value();
-    }
-
-    private SQLSkeletonUtil()
-    {
-    }
-
-    /**
-     * Required for Lazy.
-     *
-     * @param <T> The result variable type.
-     */
-    public static interface LazyInit<T, TException extends Throwable>
-    {
-        T create()
-            throws TException;
-    }
-
-    /**
-     * Non-threadsafe implementation of C#'s Lazy&lt;T&gt;. I wonder if Java has something like this
-     * already done?
-     *
-     * @param <T> The result variable type.
-     */
-    public static final class Lazy<T, TException extends Throwable>
-    {
-        private final LazyInit<T, TException> m_init;
-        private T m_cachedValue;
-
-        public Lazy( LazyInit<T, TException> init )
-        {
-            this.m_init = init;
-            this.m_cachedValue = null;
-        }
-
-        public T getValue()
-            throws TException
-        {
-            if( this.m_cachedValue == null )
-            {
-                this.m_cachedValue = this.m_init.create();
-            }
-            return this.m_cachedValue;
-        }
-
-        public boolean hasValue()
-        {
-            return this.m_cachedValue != null;
-        }
-    }
-
-    public static final class Reference<T>
-    {
-        private T m_reference;
-
-        public void setReference( T reference )
-        {
-            this.m_reference = reference;
-        }
-
-        public T getReference()
-        {
-            return this.m_reference;
-        }
-    }
-
-}
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/package.html b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/package.html
deleted file mode 100644
index 63053cf..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/skeletons/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL Index/Query Vendors Support Skeletons.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/sqlite/package.html b/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/sqlite/package.html
deleted file mode 100644
index 7564503..0000000
--- a/extensions/indexing-sql/src/main/java/org/qi4j/index/sql/support/sqlite/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL Index/Query SQLite Support.</h2>
-    </body>
-</html>
diff --git a/extensions/indexing-sql/src/test/java/org/apache/polygene/index/sql/postgresql/PostgreSQLComplexQueryTest.java b/extensions/indexing-sql/src/test/java/org/apache/polygene/index/sql/postgresql/PostgreSQLComplexQueryTest.java
new file mode 100644
index 0000000..da9e217
--- /dev/null
+++ b/extensions/indexing-sql/src/test/java/org/apache/polygene/index/sql/postgresql/PostgreSQLComplexQueryTest.java
@@ -0,0 +1,65 @@
+/*
+ *  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.polygene.index.sql.postgresql;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.internal.DockerRule;
+import org.apache.polygene.test.indexing.AbstractComplexQueryTest;
+import org.junit.ClassRule;
+
+public class PostgreSQLComplexQueryTest
+    extends AbstractComplexQueryTest
+{
+    @ClassRule
+    public static final DockerRule DOCKER = new DockerRule( "postgres", 3000L, "PostgreSQL init process complete; ready for start up." );
+
+    @Override
+    public void assemble( ModuleAssembly mainModule )
+        throws AssemblyException
+    {
+        super.assemble( mainModule );
+        String host = DOCKER.getDockerHost();
+        int port = DOCKER.getExposedContainerPort( "5432/tcp" );
+        SQLTestHelper.assembleWithMemoryEntityStore( mainModule, host, port );
+    }
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        try
+        {
+            super.setUp();
+        }
+        catch( Exception e )
+        {
+            // Let's check if exception was because database was not available
+            if( this.module != null )
+            {
+                SQLTestHelper.setUpTest( this.serviceFinder );
+            }
+
+            // If we got this far, the database must have been available, and exception must have
+            // had other reason!
+            throw e;
+        }
+    }
+}
diff --git a/extensions/indexing-sql/src/test/java/org/apache/polygene/index/sql/postgresql/PostgreSQLDBIntegrityTest.java b/extensions/indexing-sql/src/test/java/org/apache/polygene/index/sql/postgresql/PostgreSQLDBIntegrityTest.java
new file mode 100644
index 0000000..58869a6
--- /dev/null
+++ b/extensions/indexing-sql/src/test/java/org/apache/polygene/index/sql/postgresql/PostgreSQLDBIntegrityTest.java
@@ -0,0 +1,143 @@
+/*
+ *  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.polygene.index.sql.postgresql;
+
+import java.sql.Connection;
+import javax.sql.DataSource;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.sql.assembly.PostgreSQLIndexQueryAssembler;
+import org.apache.polygene.index.sql.support.common.DBNames;
+import org.apache.polygene.index.sql.support.common.GenericDatabaseExplorer;
+import org.apache.polygene.index.sql.support.common.GenericDatabaseExplorer.DatabaseProcessorAdapter;
+import org.apache.polygene.library.sql.common.SQLConfiguration;
+import org.apache.polygene.library.sql.common.SQLUtil;
+import org.apache.polygene.library.sql.generator.vendor.PostgreSQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.internal.DockerRule;
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+public class PostgreSQLDBIntegrityTest
+    extends AbstractPolygeneTest
+{
+    @ClassRule
+    public static final DockerRule DOCKER = new DockerRule( "postgres", 3000L, "PostgreSQL init process complete; ready for start up." );
+
+    public interface TestEntity
+        extends EntityComposite
+    {
+        @UseDefaults
+        Property<String> testString();
+
+        @UseDefaults
+        Property<Integer> testInt();
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        String host = DOCKER.getDockerHost();
+        int port = DOCKER.getExposedContainerPort( "5432/tcp" );
+        SQLTestHelper.assembleWithMemoryEntityStore( module, host, port );
+        module.entities( TestEntity.class );
+    }
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        if( this.module != null )
+        {
+            SQLTestHelper.setUpTest( this.serviceFinder );
+        }
+    }
+
+    @Test
+    public void createAndRemoveEntityAndVerifyNoExtraDataLeftInDB()
+        throws Exception
+    {
+        UnitOfWork uow = this.unitOfWorkFactory.newUnitOfWork();
+        TestEntity entity = uow.newEntity( TestEntity.class );
+        uow.complete();
+
+        uow = this.unitOfWorkFactory.newUnitOfWork();
+        entity = uow.get( entity );
+        SQLConfiguration config = uow.get( SQLConfiguration.class, PostgreSQLIndexQueryAssembler.DEFAULT_IDENTITY );
+        String schemaName = config.schemaName().get().toLowerCase();
+        uow.remove( entity );
+        uow.complete();
+
+        Connection connection = this.serviceFinder.findService( DataSource.class ).get().getConnection();
+        try
+        {
+            GenericDatabaseExplorer.visitDatabaseTables(
+                connection, null, schemaName, null,
+                new DatabaseProcessorAdapter()
+            {
+                @Override
+                public void beginProcessRowInfo( String schemaNamee, String tableName, Object[] rowContents )
+                {
+                    if( ( tableName.startsWith( DBNames.QNAME_TABLE_NAME_PREFIX )
+                          && ( tableName.equals( DBNames.QNAME_TABLE_NAME_PREFIX + 0 )
+                               || tableName.equals( DBNames.QNAME_TABLE_NAME_PREFIX + 1 ) ) )
+                        || tableName.equals( DBNames.ALL_QNAMES_TABLE_NAME )
+                        || tableName.equals( DBNames.ENTITY_TABLE_NAME ) )
+                    {
+                        throw new RuntimeException( "Table: " + schemaNamee + "." + tableName );
+                    }
+                }
+                },
+                SQLVendorProvider.createVendor( PostgreSQLVendor.class ) );
+        }
+        finally
+        {
+            SQLUtil.closeQuietly( connection );
+        }
+    }
+
+    @Test
+    public void createAndModifyEntity()
+        throws Exception
+    {
+        UnitOfWork uow = this.unitOfWorkFactory.newUnitOfWork();
+        TestEntity entity = uow.newEntity( TestEntity.class );
+        uow.complete();
+
+        uow = this.unitOfWorkFactory.newUnitOfWork();
+        entity = uow.get( entity );
+        entity.testString().set( "NewTestString" );
+        uow.complete();
+
+        uow = this.unitOfWorkFactory.newUnitOfWork();
+        entity = uow.get( entity );
+        Assert.assertEquals( "New value did not store in indexing.", "NewTestString", entity
+            .testString().get() );
+        uow.discard();
+    }
+}
diff --git a/extensions/indexing-sql/src/test/java/org/apache/polygene/index/sql/postgresql/PostgreSQLEntityFinderTest.java b/extensions/indexing-sql/src/test/java/org/apache/polygene/index/sql/postgresql/PostgreSQLEntityFinderTest.java
new file mode 100644
index 0000000..e909827
--- /dev/null
+++ b/extensions/indexing-sql/src/test/java/org/apache/polygene/index/sql/postgresql/PostgreSQLEntityFinderTest.java
@@ -0,0 +1,65 @@
+/*
+ *  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.polygene.index.sql.postgresql;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.indexing.AbstractEntityFinderTest;
+import org.apache.polygene.test.internal.DockerRule;
+import org.junit.ClassRule;
+
+public class PostgreSQLEntityFinderTest
+    extends AbstractEntityFinderTest
+{
+    @ClassRule
+    public static final DockerRule DOCKER = new DockerRule( "postgres", 3000L, "PostgreSQL init process complete; ready for start up." );
+
+    @Override
+    public void assemble( ModuleAssembly mainModule )
+        throws AssemblyException
+    {
+        super.assemble( mainModule );
+        String host = DOCKER.getDockerHost();
+        int port = DOCKER.getExposedContainerPort( "5432/tcp" );
+        SQLTestHelper.assembleWithMemoryEntityStore( mainModule, host, port );
+    }
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        try
+        {
+            super.setUp();
+        }
+        catch( Exception e )
+        {
+            // Let's check if exception was because database was not available
+            if( this.module != null )
+            {
+                SQLTestHelper.setUpTest( this.serviceFinder );
+            }
+
+            // If we got this far, the database must have been available, and exception must have
+            // had other reason!
+            throw e;
+        }
+    }
+}
diff --git a/extensions/indexing-sql/src/test/java/org/apache/polygene/index/sql/postgresql/PostgreSQLQueryTest.java b/extensions/indexing-sql/src/test/java/org/apache/polygene/index/sql/postgresql/PostgreSQLQueryTest.java
new file mode 100644
index 0000000..2d4dde5
--- /dev/null
+++ b/extensions/indexing-sql/src/test/java/org/apache/polygene/index/sql/postgresql/PostgreSQLQueryTest.java
@@ -0,0 +1,266 @@
+/*
+ *  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.polygene.index.sql.postgresql;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.internal.DockerRule;
+import org.apache.polygene.test.indexing.AbstractQueryTest;
+import org.junit.ClassRule;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * PostgreSQL Query Tests.
+ * <p>Many features are not supported.</p>
+ */
+// See org.apache.polygene.index.sql.support.skeletons.SQLCompatEntityStateWrapper that filter out unsupported properties.
+public class PostgreSQLQueryTest
+    extends AbstractQueryTest
+{
+    @ClassRule
+    public static final DockerRule DOCKER = new DockerRule( "postgres",
+                                                            10000L,
+                                                            "PostgreSQL init process complete; ready for start up." );
+
+    @Override
+    public void assemble( ModuleAssembly mainModule )
+        throws AssemblyException
+    {
+        super.assemble( mainModule );
+        String host = DOCKER.getDockerHost();
+        int port = DOCKER.getExposedContainerPort( "5432/tcp" );
+        SQLTestHelper.assembleWithMemoryEntityStore( mainModule, host, port );
+    }
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        try
+        {
+            super.setUp();
+        }
+        catch( Exception e )
+        {
+            // Let's check if exception was because database was not available
+            if( this.module != null )
+            {
+                SQLTestHelper.setUpTest( this.serviceFinder );
+            }
+
+            // If we got this far, the database must have been available, and exception must have
+            // had other reason!
+            throw e;
+        }
+    }
+
+    @Test
+    @Ignore( "NeSpecification is not supported by SQL Indexing" )
+    @Override
+    public void script04_ne()
+    {
+        super.script04_ne();
+    }
+
+    @Test
+    @Ignore( "NeSpecification is not supported by SQL Indexing" )
+    @Override
+    public void script12_ne()
+    {
+        super.script04_ne();
+    }
+
+    @Test
+    @Ignore( "NamedAssociation are not supported by SQL Indexing" )
+    @Override
+    public void script35()
+    {
+        super.script35();
+    }
+
+    @Test
+    @Ignore( "NamedAssociation are not supported by SQL Indexing" )
+    @Override
+    public void script36()
+    {
+        super.script36();
+    }
+
+    @Test
+    @Ignore( "Queries on Enums are not supported by SQL Indexing" )
+    @Override
+    public void script38()
+    {
+        super.script38();
+    }
+
+    @Test
+    @Ignore( "Queries on Enums and NeSpecification are not supported by SQL Indexing" )
+    @Override
+    public void script39()
+    {
+        super.script39();
+    }
+
+    @Test
+    @Ignore( "Date is not supported by SQL Indexing" )
+    @Override
+    public void script40_Date()
+    {
+        super.script40_Date();
+    }
+
+    @Test
+    @Ignore( "DateTime is not supported by SQL Indexing" )
+    @Override
+    public void script40_DateTime()
+    {
+        super.script40_DateTime();
+    }
+
+    @Test
+    @Ignore( "LocalDate is not supported by SQL Indexing" )
+    @Override
+    public void script40_LocalDate()
+    {
+        super.script40_LocalDate();
+    }
+
+    @Test
+    @Ignore( "LocalDateTime is not supported by SQL Indexing" )
+    @Override
+    public void script40_LocalDateTime()
+    {
+        super.script40_LocalDateTime();
+    }
+
+    @Test
+    @Ignore( "NeSpecification is not supported by SQL Indexing" )
+    @Override
+    public void script41_Instant()
+    {
+        super.script41_Instant();
+    }
+
+    @Test
+    @Ignore( "NeSpecification is not supported by SQL Indexing" )
+    @Override
+    public void script41_DateTime()
+    {
+        super.script41_DateTime();
+    }
+
+    @Test
+    @Ignore( "NeSpecification is not supported by SQL Indexing" )
+    @Override
+    public void script41_LocalDate()
+    {
+        super.script41_LocalDate();
+    }
+
+    @Test
+    @Ignore( "NeSpecification is not supported by SQL Indexing" )
+    @Override
+    public void script41_LocalDateTime()
+    {
+        super.script41_LocalDateTime();
+    }
+
+    @Test
+    @Ignore( "NeSpecification is not supported by SQL Indexing" )
+    @Override
+    public void script42_Instant()
+    {
+        super.script42_Instant();
+    }
+
+    @Test
+    @Ignore( "NeSpecification is not supported by SQL Indexing" )
+    @Override
+    public void script42_DateTime()
+    {
+        super.script42_DateTime();
+    }
+
+    @Test
+    @Ignore( "NeSpecification is not supported by SQL Indexing" )
+    @Override
+    public void script42_LocalDate()
+    {
+        super.script42_LocalDate();
+    }
+
+    @Test
+    @Ignore( "NeSpecification is not supported by SQL Indexing" )
+    @Override
+    public void script42_LocalDateTime()
+    {
+        super.script42_LocalDateTime();
+    }
+
+    @Test
+    @Ignore( "Date is not supported by SQL Indexing" )
+    @Override
+    public void script43_Date()
+    {
+        super.script43_Date();
+    }
+
+    @Test
+    @Ignore( "DateTime is not supported by SQL Indexing" )
+    @Override
+    public void script43_DateTime()
+    {
+        super.script43_DateTime();
+    }
+
+    @Test
+    @Ignore( "LocalDate is not supported by SQL Indexing" )
+    @Override
+    public void script43_LocalDate()
+    {
+        super.script43_LocalDate();
+    }
+
+    @Test
+    @Ignore( "LocalDateTime is not supported by SQL Indexing" )
+    @Override
+    public void script43_LocalDateTime()
+    {
+        super.script43_LocalDateTime();
+    }
+
+    @Test
+    @Ignore( "NeSpecification is not supported by SQL Indexing" )
+    @Override
+    public void script51_BigInteger()
+    {
+        super.script51_BigInteger();
+    }
+
+    @Test
+    @Ignore( "NeSpecification is not supported by SQL Indexing" )
+    @Override
+    public void script51_BigDecimal()
+    {
+        super.script51_BigDecimal();
+    }
+}
diff --git a/extensions/indexing-sql/src/test/java/org/apache/polygene/index/sql/postgresql/SQLTestHelper.java b/extensions/indexing-sql/src/test/java/org/apache/polygene/index/sql/postgresql/SQLTestHelper.java
new file mode 100644
index 0000000..be5727d
--- /dev/null
+++ b/extensions/indexing-sql/src/test/java/org/apache/polygene/index/sql/postgresql/SQLTestHelper.java
@@ -0,0 +1,126 @@
+/*
+ *  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.polygene.index.sql.postgresql;
+
+import java.sql.Connection;
+import javax.sql.DataSource;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.library.sql.datasource.DataSourceConfiguration;
+import org.junit.Assume;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.reindexer.ReindexerConfiguration;
+import org.apache.polygene.index.sql.assembly.PostgreSQLIndexQueryAssembler;
+import org.apache.polygene.index.sql.support.common.RebuildingStrategy;
+import org.apache.polygene.index.sql.support.common.ReindexingStrategy;
+import org.apache.polygene.library.sql.assembly.DataSourceAssembler;
+import org.apache.polygene.library.sql.common.SQLUtil;
+import org.apache.polygene.library.sql.dbcp.DBCPDataSourceServiceAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+
+class SQLTestHelper
+{
+    static void assembleWithMemoryEntityStore( ModuleAssembly mainModule, String host, int port )
+        throws AssemblyException
+    {
+        // EntityStore
+        new EntityTestAssembler().visibleIn( Visibility.application ).assemble( mainModule );
+
+        doCommonAssembling( mainModule, host, port );
+    }
+
+    private static void doCommonAssembling( ModuleAssembly mainModule, String host, int port )
+        throws AssemblyException
+    {
+        ModuleAssembly config = mainModule.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+
+        // START SNIPPET: assembly
+        // DataSourceService
+        new DBCPDataSourceServiceAssembler().
+            identifiedBy( "postgres-datasource-service" ).
+            visibleIn( Visibility.module ).
+            withConfig( config, Visibility.layer ).
+            assemble( mainModule );
+
+        // DataSource
+        new DataSourceAssembler().
+            withDataSourceServiceIdentity( "postgres-datasource-service" ).
+            identifiedBy( "postgres-datasource" ).
+            visibleIn( Visibility.module ).
+            withCircuitBreaker().
+            assemble( mainModule );
+
+        // SQL Index/Query
+        new PostgreSQLIndexQueryAssembler().
+            visibleIn( Visibility.module ).
+            withConfig( config, Visibility.layer ).
+            assemble( mainModule );
+        // END SNIPPET: assembly
+
+        config.forMixin( DataSourceConfiguration.class ).declareDefaults()
+              .url().set( "jdbc:postgresql://" + host + ":" + port + "/jdbc_test_db" );
+
+        // Always re-build schema in test scenarios because of possibly different app structure in
+        // various tests
+        mainModule.services( RebuildingStrategy.class ).
+            withMixins( RebuildingStrategy.AlwaysNeed.class ).
+            visibleIn( Visibility.module );
+
+        // Always re-index in test scenarios
+        mainModule.services( ReindexingStrategy.class ).
+            withMixins( ReindexingStrategy.AlwaysNeed.class ).
+            visibleIn( Visibility.module );
+        config.entities( ReindexerConfiguration.class ).
+            visibleIn( Visibility.layer );
+    }
+
+    static void setUpTest( ServiceFinder serviceFinder )
+    {
+        Connection connection = null;
+        try
+        {
+
+            DataSource ds = serviceFinder.findService( DataSource.class ).get();
+            connection = ds.getConnection();
+            Assume.assumeNotNull( connection );
+
+        }
+        catch( Throwable t )
+        {
+
+            t.printStackTrace();
+            Assume.assumeNoException( t );
+
+        }
+        finally
+        {
+
+            SQLUtil.closeQuietly( connection );
+
+        }
+    }
+
+    private SQLTestHelper()
+    {
+    }
+
+}
diff --git a/extensions/indexing-sql/src/test/java/org/qi4j/index/sql/postgresql/PostgreSQLComplexQueryTest.java b/extensions/indexing-sql/src/test/java/org/qi4j/index/sql/postgresql/PostgreSQLComplexQueryTest.java
deleted file mode 100644
index 5f4f290..0000000
--- a/extensions/indexing-sql/src/test/java/org/qi4j/index/sql/postgresql/PostgreSQLComplexQueryTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.index.sql.postgresql;
-
-import org.junit.BeforeClass;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.indexing.AbstractComplexQueryTest;
-
-import static org.qi4j.test.util.Assume.assumeConnectivity;
-
-public class PostgreSQLComplexQueryTest
-    extends AbstractComplexQueryTest
-{
-    @BeforeClass
-    public static void beforePostgreSQLQueryTests()
-    {
-        assumeConnectivity( "localhost", 5432 );
-    }
-
-    @Override
-    public void assemble( ModuleAssembly mainModule )
-        throws AssemblyException
-    {
-        super.assemble( mainModule );
-        SQLTestHelper.assembleWithMemoryEntityStore( mainModule );
-    }
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        try
-        {
-            super.setUp();
-        }
-        catch( Exception e )
-        {
-            // Let's check if exception was because database was not available
-            if( this.module != null )
-            {
-                SQLTestHelper.setUpTest( this.module );
-            }
-
-            // If we got this far, the database must have been available, and exception must have
-            // had other reason!
-            throw e;
-        }
-    }
-}
diff --git a/extensions/indexing-sql/src/test/java/org/qi4j/index/sql/postgresql/PostgreSQLDBIntegrityTest.java b/extensions/indexing-sql/src/test/java/org/qi4j/index/sql/postgresql/PostgreSQLDBIntegrityTest.java
deleted file mode 100644
index 8ca57c4..0000000
--- a/extensions/indexing-sql/src/test/java/org/qi4j/index/sql/postgresql/PostgreSQLDBIntegrityTest.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.index.sql.postgresql;
-
-import java.sql.Connection;
-import javax.sql.DataSource;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.sql.assembly.PostgreSQLIndexQueryAssembler;
-import org.qi4j.index.sql.support.common.DBNames;
-import org.qi4j.index.sql.support.common.GenericDatabaseExplorer;
-import org.qi4j.index.sql.support.common.GenericDatabaseExplorer.DatabaseProcessorAdapter;
-import org.qi4j.index.sql.support.postgresql.PostgreSQLAppStartup;
-import org.qi4j.library.sql.common.SQLConfiguration;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.qi4j.test.AbstractQi4jTest;
-import org.sql.generation.api.vendor.PostgreSQLVendor;
-import org.sql.generation.api.vendor.SQLVendorProvider;
-
-import static org.qi4j.test.util.Assume.assumeConnectivity;
-
-public class PostgreSQLDBIntegrityTest
-    extends AbstractQi4jTest
-{
-    @BeforeClass
-    public static void beforePostgreSQLQueryTests()
-    {
-        assumeConnectivity( "localhost", 5432 );
-    }
-
-    public static interface TestEntity
-        extends EntityComposite
-    {
-        @UseDefaults
-        public Property<String> testString();
-
-        @UseDefaults
-        public Property<Integer> testInt();
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        SQLTestHelper.assembleWithMemoryEntityStore( module );
-        module.entities( TestEntity.class );
-    }
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        if( this.module != null )
-        {
-            SQLTestHelper.setUpTest( this.module );
-        }
-    }
-
-    @Test
-    public void createAndRemoveEntityAndVerifyNoExtraDataLeftInDB()
-        throws Exception
-    {
-        UnitOfWork uow = this.module.newUnitOfWork();
-        TestEntity entity = uow.newEntity( TestEntity.class );
-        uow.complete();
-
-        uow = this.module.newUnitOfWork();
-        entity = uow.get( entity );
-        SQLConfiguration config = uow.get( SQLConfiguration.class, PostgreSQLIndexQueryAssembler.DEFAULT_IDENTITY );
-        String schemaName = config.schemaName().get();
-        if( schemaName == null )
-        {
-            schemaName = PostgreSQLAppStartup.DEFAULT_SCHEMA_NAME;
-        }
-        uow.remove( entity );
-        uow.complete();
-
-        Connection connection = this.module.findService( DataSource.class ).get().getConnection();
-        try
-        {
-            GenericDatabaseExplorer.visitDatabaseTables(
-                connection, null, schemaName, null,
-                new DatabaseProcessorAdapter()
-            {
-                @Override
-                public void beginProcessRowInfo( String schemaNamee, String tableName, Object[] rowContents )
-                {
-                    if( ( tableName.startsWith( DBNames.QNAME_TABLE_NAME_PREFIX )
-                          && ( tableName.equals( DBNames.QNAME_TABLE_NAME_PREFIX + 0 )
-                               || tableName.equals( DBNames.QNAME_TABLE_NAME_PREFIX + 1 ) ) )
-                        || tableName.equals( DBNames.ALL_QNAMES_TABLE_NAME )
-                        || tableName.equals( DBNames.ENTITY_TABLE_NAME ) )
-                    {
-                        throw new RuntimeException( "Table: " + schemaNamee + "." + tableName );
-                    }
-                }
-                },
-                SQLVendorProvider.createVendor( PostgreSQLVendor.class ) );
-        }
-        finally
-        {
-            SQLUtil.closeQuietly( connection );
-        }
-    }
-
-    @Test
-    public void createAndModifyEntity()
-        throws Exception
-    {
-        UnitOfWork uow = this.module.newUnitOfWork();
-        TestEntity entity = uow.newEntity( TestEntity.class );
-        uow.complete();
-
-        uow = this.module.newUnitOfWork();
-        entity = uow.get( entity );
-        entity.testString().set( "NewTestString" );
-        uow.complete();
-
-        uow = this.module.newUnitOfWork();
-        entity = uow.get( entity );
-        Assert.assertEquals( "New value did not store in indexing.", "NewTestString", entity
-            .testString().get() );
-        uow.discard();
-    }
-}
diff --git a/extensions/indexing-sql/src/test/java/org/qi4j/index/sql/postgresql/PostgreSQLEntityFinderTest.java b/extensions/indexing-sql/src/test/java/org/qi4j/index/sql/postgresql/PostgreSQLEntityFinderTest.java
deleted file mode 100644
index 2831c7d..0000000
--- a/extensions/indexing-sql/src/test/java/org/qi4j/index/sql/postgresql/PostgreSQLEntityFinderTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.index.sql.postgresql;
-
-import org.junit.BeforeClass;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.indexing.AbstractEntityFinderTest;
-
-import static org.qi4j.test.util.Assume.assumeConnectivity;
-
-public class PostgreSQLEntityFinderTest
-    extends AbstractEntityFinderTest
-{
-    @BeforeClass
-    public static void beforePostgreSQLQueryTests()
-    {
-        assumeConnectivity( "localhost", 5432 );
-    }
-
-    @Override
-    public void assemble( ModuleAssembly mainModule )
-        throws AssemblyException
-    {
-        super.assemble( mainModule );
-        SQLTestHelper.assembleWithMemoryEntityStore( mainModule );
-    }
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        try
-        {
-            super.setUp();
-        }
-        catch( Exception e )
-        {
-            // Let's check if exception was because database was not available
-            if( this.module != null )
-            {
-                SQLTestHelper.setUpTest( this.module );
-            }
-
-            // If we got this far, the database must have been available, and exception must have
-            // had other reason!
-            throw e;
-        }
-    }
-}
diff --git a/extensions/indexing-sql/src/test/java/org/qi4j/index/sql/postgresql/PostgreSQLQueryTest.java b/extensions/indexing-sql/src/test/java/org/qi4j/index/sql/postgresql/PostgreSQLQueryTest.java
deleted file mode 100644
index e794d30..0000000
--- a/extensions/indexing-sql/src/test/java/org/qi4j/index/sql/postgresql/PostgreSQLQueryTest.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.index.sql.postgresql;
-
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.spi.query.EntityFinderException;
-import org.qi4j.test.indexing.AbstractQueryTest;
-
-import static org.qi4j.test.util.Assume.assumeConnectivity;
-
-/**
- * PostgreSQL Query Tests.
- * <p>Many features are not supported.</p>
- */
-// See org.qi4j.index.sql.support.skeletons.SQLCompatEntityStateWrapper that filter out unsupported properties.
-public class PostgreSQLQueryTest
-    extends AbstractQueryTest
-{
-    @BeforeClass
-    public static void beforePostgreSQLQueryTests()
-    {
-        assumeConnectivity( "localhost", 5432 );
-    }
-
-    @Override
-    public void assemble( ModuleAssembly mainModule )
-        throws AssemblyException
-    {
-        super.assemble( mainModule );
-        SQLTestHelper.assembleWithMemoryEntityStore( mainModule );
-    }
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        try
-        {
-            super.setUp();
-        }
-        catch( Exception e )
-        {
-            // Let's check if exception was because database was not available
-            if( this.module != null )
-            {
-                SQLTestHelper.setUpTest( this.module );
-            }
-
-            // If we got this far, the database must have been available, and exception must have
-            // had other reason!
-            throw e;
-        }
-    }
-
-    @Test
-    @Ignore( "NeSpecification is not supported by SQL Indexing" )
-    @Override
-    public void script04_ne()
-        throws EntityFinderException
-    {
-        super.script04_ne();
-    }
-
-    @Test
-    @Ignore( "NeSpecification is not supported by SQL Indexing" )
-    @Override
-    public void script12_ne()
-        throws EntityFinderException
-    {
-        super.script04_ne();
-    }
-
-    @Test
-    @Ignore( "NamedAssociation are not supported by SQL Indexing" )
-    @Override
-    public void script35()
-    {
-        super.script35();
-    }
-
-    @Test
-    @Ignore( "NamedAssociation are not supported by SQL Indexing" )
-    @Override
-    public void script36()
-    {
-        super.script36();
-    }
-
-    @Test
-    @Ignore( "Queries on Enums are not supported by SQL Indexing" )
-    @Override
-    public void script38()
-    {
-        super.script38();
-    }
-
-    @Test
-    @Ignore( "Queries on Enums and NeSpecification are not supported by SQL Indexing" )
-    @Override
-    public void script39()
-    {
-        super.script39();
-    }
-
-    @Test
-    @Ignore( "Date is not supported by SQL Indexing" )
-    @Override
-    public void script40_Date()
-    {
-        super.script40_Date();
-    }
-
-    @Test
-    @Ignore( "DateTime is not supported by SQL Indexing" )
-    @Override
-    public void script40_DateTime()
-    {
-        super.script40_DateTime();
-    }
-
-    @Test
-    @Ignore( "LocalDate is not supported by SQL Indexing" )
-    @Override
-    public void script40_LocalDate()
-    {
-        super.script40_LocalDate();
-    }
-
-    @Test
-    @Ignore( "LocalDateTime is not supported by SQL Indexing" )
-    @Override
-    public void script40_LocalDateTime()
-    {
-        super.script40_LocalDateTime();
-    }
-
-    @Test
-    @Ignore( "NeSpecification is not supported by SQL Indexing" )
-    @Override
-    public void script41_Date()
-    {
-        super.script41_Date();
-    }
-
-    @Test
-    @Ignore( "NeSpecification is not supported by SQL Indexing" )
-    @Override
-    public void script41_DateTime()
-    {
-        super.script41_DateTime();
-    }
-
-    @Test
-    @Ignore( "NeSpecification is not supported by SQL Indexing" )
-    @Override
-    public void script41_LocalDate()
-    {
-        super.script41_LocalDate();
-    }
-
-    @Test
-    @Ignore( "NeSpecification is not supported by SQL Indexing" )
-    @Override
-    public void script41_LocalDateTime()
-    {
-        super.script41_LocalDateTime();
-    }
-
-    @Test
-    @Ignore( "NeSpecification is not supported by SQL Indexing" )
-    @Override
-    public void script42_Date()
-    {
-        super.script42_Date();
-    }
-
-    @Test
-    @Ignore( "NeSpecification is not supported by SQL Indexing" )
-    @Override
-    public void script42_DateTime()
-    {
-        super.script42_DateTime();
-    }
-
-    @Test
-    @Ignore( "NeSpecification is not supported by SQL Indexing" )
-    @Override
-    public void script42_LocalDate()
-    {
-        super.script42_LocalDate();
-    }
-
-    @Test
-    @Ignore( "NeSpecification is not supported by SQL Indexing" )
-    @Override
-    public void script42_LocalDateTime()
-    {
-        super.script42_LocalDateTime();
-    }
-
-    @Test
-    @Ignore( "Date is not supported by SQL Indexing" )
-    @Override
-    public void script43_Date()
-    {
-        super.script43_Date();
-    }
-
-    @Test
-    @Ignore( "DateTime is not supported by SQL Indexing" )
-    @Override
-    public void script43_DateTime()
-    {
-        super.script43_DateTime();
-    }
-
-    @Test
-    @Ignore( "LocalDate is not supported by SQL Indexing" )
-    @Override
-    public void script43_LocalDate()
-    {
-        super.script43_LocalDate();
-    }
-
-    @Test
-    @Ignore( "LocalDateTime is not supported by SQL Indexing" )
-    @Override
-    public void script43_LocalDateTime()
-    {
-        super.script43_LocalDateTime();
-    }
-
-    @Test
-    @Ignore( "NeSpecification is not supported by SQL Indexing" )
-    @Override
-    public void script51_BigInteger()
-    {
-        super.script51_BigInteger();
-    }
-
-    @Test
-    @Ignore( "NeSpecification is not supported by SQL Indexing" )
-    @Override
-    public void script51_BigDecimal()
-    {
-        super.script51_BigDecimal();
-    }
-}
diff --git a/extensions/indexing-sql/src/test/java/org/qi4j/index/sql/postgresql/SQLTestHelper.java b/extensions/indexing-sql/src/test/java/org/qi4j/index/sql/postgresql/SQLTestHelper.java
deleted file mode 100644
index 4b0a4e7..0000000
--- a/extensions/indexing-sql/src/test/java/org/qi4j/index/sql/postgresql/SQLTestHelper.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.index.sql.postgresql;
-
-import java.sql.Connection;
-import javax.sql.DataSource;
-import org.junit.Assume;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.structure.Module;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.reindexer.ReindexerConfiguration;
-import org.qi4j.index.sql.assembly.PostgreSQLIndexQueryAssembler;
-import org.qi4j.index.sql.support.common.RebuildingStrategy;
-import org.qi4j.index.sql.support.common.ReindexingStrategy;
-import org.qi4j.library.sql.assembly.DataSourceAssembler;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.qi4j.library.sql.dbcp.DBCPDataSourceServiceAssembler;
-import org.qi4j.test.EntityTestAssembler;
-
-public class SQLTestHelper
-{
-
-    public static final String SEPARATE_MODULE_NAME = "actual_module";
-
-    public static void assembleWithMemoryEntityStore( ModuleAssembly mainModule )
-        throws AssemblyException
-    {
-        // EntityStore
-        new EntityTestAssembler().visibleIn( Visibility.application ).assemble( mainModule );
-
-        doCommonAssembling( mainModule );
-    }
-
-    protected static void doCommonAssembling( ModuleAssembly mainModule )
-        throws AssemblyException
-    {
-        ModuleAssembly config = mainModule.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-
-        // START SNIPPET: assembly
-        // DataSourceService
-        new DBCPDataSourceServiceAssembler().
-            identifiedBy( "postgres-datasource-service" ).
-            visibleIn( Visibility.module ).
-            withConfig( config, Visibility.layer ).
-            assemble( mainModule );
-
-        // DataSource
-        new DataSourceAssembler().
-            withDataSourceServiceIdentity( "postgres-datasource-service" ).
-            identifiedBy( "postgres-datasource" ).
-            visibleIn( Visibility.module ).
-            withCircuitBreaker().
-            assemble( mainModule );
-
-        // SQL Index/Query
-        new PostgreSQLIndexQueryAssembler().
-            visibleIn( Visibility.module ).
-            withConfig( config, Visibility.layer ).
-            assemble( mainModule );
-        // END SNIPPET: assembly
-
-        // Always re-build schema in test scenarios because of possibly different app structure in
-        // various tests
-        mainModule.services( RebuildingStrategy.class ).
-            withMixins( RebuildingStrategy.AlwaysNeed.class ).
-            visibleIn( Visibility.module );
-
-        // Always re-index in test scenarios
-        mainModule.services( ReindexingStrategy.class ).
-            withMixins( ReindexingStrategy.AlwaysNeed.class ).
-            visibleIn( Visibility.module );
-        config.entities( ReindexerConfiguration.class ).
-            visibleIn( Visibility.layer );
-    }
-
-    public static void setUpTest( Module module )
-    {
-        Connection connection = null;
-        try
-        {
-
-            DataSource ds = module.findService( DataSource.class ).get();
-            connection = ds.getConnection();
-            Assume.assumeNotNull( connection );
-
-        }
-        catch( Throwable t )
-        {
-
-            t.printStackTrace();
-            Assume.assumeNoException( t );
-
-        }
-        finally
-        {
-
-            SQLUtil.closeQuietly( connection );
-
-        }
-    }
-
-    private SQLTestHelper()
-    {
-    }
-
-}
diff --git a/extensions/indexing-sql/src/test/resources/logback.xml b/extensions/indexing-sql/src/test/resources/logback.xml
index 94eb92c..23028d4 100644
--- a/extensions/indexing-sql/src/test/resources/logback.xml
+++ b/extensions/indexing-sql/src/test/resources/logback.xml
@@ -1,20 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <configuration>
 
     <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
@@ -27,6 +30,6 @@
         <appender-ref ref="stdout" />
     </root>
 
-    <logger name="org.qi4j.index.sql" level="trace"/>
+    <logger name="org.apache.polygene.index.sql" level="trace"/>
 
 </configuration>
\ No newline at end of file
diff --git a/extensions/indexing-sql/src/test/resources/postgres-datasource.properties b/extensions/indexing-sql/src/test/resources/postgres-datasource.properties
index f7d7ad5..1766e3e 100644
--- a/extensions/indexing-sql/src/test/resources/postgres-datasource.properties
+++ b/extensions/indexing-sql/src/test/resources/postgres-datasource.properties
@@ -1,20 +1,25 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 enabled=true
-url=jdbc:postgresql://localhost:5432/jdbc_test_db
+#url=jdbc:postgresql://localhost:5432/jdbc_test_db
 driver=org.postgresql.Driver
 username=jdbc_test_login
 password=password
diff --git a/extensions/metrics-codahale/build.gradle b/extensions/metrics-codahale/build.gradle
new file mode 100644
index 0000000..4b7fd20
--- /dev/null
+++ b/extensions/metrics-codahale/build.gradle
@@ -0,0 +1,37 @@
+/*
+ *  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.
+ *
+ *
+ */
+
+apply plugin: 'polygene-extension'
+
+description = "Apache Polygene™ Codahale Metrics Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - Metrics - Codahale" } }
+
+dependencies {
+  api polygene.core.bootstrap
+  api libraries.codahale_metrics
+
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+  testImplementation polygene.library( 'jmx' )
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/extensions/metrics-codahale/dev-status.xml b/extensions/metrics-codahale/dev-status.xml
new file mode 100644
index 0000000..bd10cdc
--- /dev/null
+++ b/extensions/metrics-codahale/dev-status.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
+  <status>
+        <!--none,early,beta,stable,mature-->
+        <codebase>stable</codebase>
+
+        <!-- none, brief, good, complete -->
+        <documentation>brief</documentation>
+
+        <!-- none, some, good, complete -->
+        <unittests>some</unittests>
+    </status>
+    <licenses>
+        <license>ALv2</license>
+    </licenses>
+</module>
\ No newline at end of file
diff --git a/extensions/metrics-codahale/src/docs/metrics-codahale.txt b/extensions/metrics-codahale/src/docs/metrics-codahale.txt
new file mode 100644
index 0000000..06409b2
--- /dev/null
+++ b/extensions/metrics-codahale/src/docs/metrics-codahale.txt
@@ -0,0 +1,55 @@
+///////////////////////////////////////////////////////////////
+ * 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.
+///////////////////////////////////////////////////////////////
+
+[[extension-metrics-metrics, Codahale Metrics]]
+= Codahale Metrics =
+
+[devstatus]
+--------------
+source=extensions/metrics-codahale/dev-status.xml
+--------------
+
+Metrics extension backed by the http://metrics.dropwizard.io/[Codahale] metrics library
+maintained by the http://www.dropwizard.io/[Dropwizard] folks.
+
+include::../../build/docs/buildinfo/artifact.txt[]
+
+== Assembly ==
+
+Assembly is done using the provided Assembler:
+
+[snippet,java]
+----
+source=extensions/metrics-codahale/src/test/java/org/apache/polygene/metrics/codahale/CodahaleMetricsTest.java
+tag=assembly
+----
+
+== Reporting to Ganglia or Graphite ==
+
+Dropwizard provide metrics reporter for Ganglia or Graphite, see the http://metrics.dropwizard.io/[official documentation]
+for details.
+
+To register reporters you need a handle to the underlying `MetricsRegistry`, the `CodahaleMetricsProvider` service
+provide accessor to it:
+
+[snippet,java]
+----
+source=extensions/metrics-codahale/src/test/java/org/apache/polygene/metrics/codahale/CodahaleMetricsTest.java
+tag=registry
+----
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleCounter.java b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleCounter.java
new file mode 100644
index 0000000..88ef606
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleCounter.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.metrics.codahale;
+
+import com.codahale.metrics.Counter;
+import org.apache.polygene.api.metrics.MetricsCounter;
+
+public class CodahaleCounter
+    implements MetricsCounter
+{
+    private Counter counter;
+
+    public CodahaleCounter( Counter counter )
+    {
+
+        this.counter = counter;
+    }
+
+    @Override
+    public void increment()
+    {
+        counter.inc();
+    }
+
+    @Override
+    public void increment( int steps )
+    {
+        counter.inc( steps );
+    }
+
+    @Override
+    public void decrement()
+    {
+        counter.dec();
+    }
+
+    @Override
+    public void decrement( int steps )
+    {
+        counter.dec( steps );
+    }
+}
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleGauge.java b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleGauge.java
new file mode 100644
index 0000000..df542eb
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleGauge.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.metrics.codahale;
+
+import com.codahale.metrics.Gauge;
+import org.apache.polygene.api.metrics.MetricsGauge;
+
+public class CodahaleGauge<T>
+    implements MetricsGauge<T>
+{
+    private Gauge<T> gauge;
+
+    public CodahaleGauge( Gauge<T> gauge )
+    {
+        this.gauge = gauge;
+    }
+
+    @Override
+    public T value()
+    {
+        return gauge.getValue();
+    }
+}
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleHealthCheck.java b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleHealthCheck.java
new file mode 100644
index 0000000..ebe8b5c
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleHealthCheck.java
@@ -0,0 +1,76 @@
+/*
+ *  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.polygene.metrics.codahale;
+
+import com.codahale.metrics.health.HealthCheck;
+import org.apache.polygene.api.metrics.MetricsHealthCheck;
+
+public class CodahaleHealthCheck
+    implements MetricsHealthCheck
+{
+    private final MetricsHealthCheck check;
+
+    public CodahaleHealthCheck( MetricsHealthCheck check )
+    {
+        this.check = check;
+    }
+
+    @Override
+    public Result check()
+        throws Exception
+    {
+        return check.check();
+    }
+
+    static Result wrap( HealthCheck.Result result )
+    {
+        if( result.isHealthy() )
+        {
+            return Result.healthOk();
+        }
+        String message = result.getMessage();
+        Throwable error = result.getError();
+        if( error != null )
+        {
+            return Result.exception( message, error );
+        }
+        return Result.unhealthy( message );
+    }
+
+    static HealthCheck.Result unwrap( Result result )
+    {
+        String message = result.getMessage();
+        if( result.isHealthy() )
+        {
+            if( message != null )
+            {
+                return HealthCheck.Result.healthy( message );
+            }
+            return HealthCheck.Result.healthy();
+        }
+        Throwable error = result.getException();
+        if( error != null )
+        {
+            return HealthCheck.Result.unhealthy( error );
+        }
+        return HealthCheck.Result.unhealthy( message );
+    }
+}
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleHistogram.java b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleHistogram.java
new file mode 100644
index 0000000..68873d6
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleHistogram.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.metrics.codahale;
+
+import com.codahale.metrics.Histogram;
+import org.apache.polygene.api.metrics.MetricsHistogram;
+
+public class CodahaleHistogram
+    implements MetricsHistogram
+{
+    private Histogram histogram;
+
+    public CodahaleHistogram( Histogram histogram )
+    {
+        this.histogram = histogram;
+    }
+
+    @Override
+    public void update( long newValue )
+    {
+        histogram.update( newValue );
+    }
+}
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMeter.java b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMeter.java
new file mode 100644
index 0000000..462e42d
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMeter.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.metrics.codahale;
+
+import com.codahale.metrics.Meter;
+import org.apache.polygene.api.metrics.MetricsMeter;
+
+public class CodahaleMeter
+    implements MetricsMeter
+{
+    private Meter meter;
+
+    public CodahaleMeter( Meter meter )
+    {
+        this.meter = meter;
+    }
+
+    @Override
+    public void mark()
+    {
+        meter.mark();
+    }
+
+    @Override
+    public void mark( int numberOfEvents )
+    {
+        meter.mark( numberOfEvents );
+    }
+}
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsMixin.java b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsMixin.java
new file mode 100644
index 0000000..5ccfdfd
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsMixin.java
@@ -0,0 +1,270 @@
+/*
+ *  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.polygene.metrics.codahale;
+
+import com.codahale.metrics.Gauge;
+import com.codahale.metrics.JmxReporter;
+import com.codahale.metrics.MetricFilter;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.Reporter;
+import com.codahale.metrics.health.HealthCheck;
+import com.codahale.metrics.health.HealthCheckRegistry;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.metrics.Metric;
+import org.apache.polygene.api.metrics.MetricsCounter;
+import org.apache.polygene.api.metrics.MetricsCounterFactory;
+import org.apache.polygene.api.metrics.MetricsGauge;
+import org.apache.polygene.api.metrics.MetricsGaugeFactory;
+import org.apache.polygene.api.metrics.MetricsHealthCheck;
+import org.apache.polygene.api.metrics.MetricsHealthCheckFactory;
+import org.apache.polygene.api.metrics.MetricsHistogram;
+import org.apache.polygene.api.metrics.MetricsHistogramFactory;
+import org.apache.polygene.api.metrics.MetricsMeter;
+import org.apache.polygene.api.metrics.MetricsMeterFactory;
+import org.apache.polygene.api.metrics.MetricsTimer;
+import org.apache.polygene.api.metrics.MetricsTimerFactory;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.metrics.codahale.assembly.CodahaleMetricsDeclaration;
+import org.apache.polygene.spi.metrics.MetricsProviderAdapter;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import static com.codahale.metrics.MetricRegistry.name;
+
+public class CodahaleMetricsMixin extends MetricsProviderAdapter
+    implements CodahaleMetricsProvider
+{
+    @Structure
+    private Application app;
+
+    @Uses
+    private ServiceDescriptor descriptor;
+
+    private final List<Reporter> reporters = new ArrayList<>();
+
+    private MetricRegistry metricRegistry;
+    private HealthCheckRegistry healthCheckRegistry;
+    private String prefix;
+    private boolean fqcn;
+
+    @Override
+    public void activateService() {
+        metricRegistry = new MetricRegistry();
+        healthCheckRegistry = new HealthCheckRegistry();
+        CodahaleMetricsDeclaration declaration = descriptor.metaInfo( CodahaleMetricsDeclaration.class );
+        prefix = declaration.prefix() != null ? declaration.prefix() : app.name();
+        fqcn = declaration.fqcn();
+        if( declaration.jmx() )
+        {
+            JmxReporter jmxReporter = JmxReporter.forRegistry( metricRegistry ).build();
+            jmxReporter.start();
+            reporters.add( jmxReporter );
+        }
+        for( Function<MetricRegistry, Reporter> reporterFactory : declaration.reportersFactories())
+        {
+            reporters.add( reporterFactory.apply( metricRegistry ) );
+        }
+    }
+
+    @Override
+    public void passivateService() throws PassivationException {
+        List<Exception> errors = new ArrayList<>();
+        for( Reporter reporter : reporters )
+        {
+            if( Closeable.class.isAssignableFrom( reporter.getClass() ) )
+            try
+            {
+                ( (Closeable) reporter ).close();
+            }
+            catch ( IOException ex )
+            {
+                errors.add( ex );
+            }
+        }
+        reporters.clear();
+        try
+        {
+            metricRegistry.removeMatching( MetricFilter.ALL );
+        }
+        catch( Exception ex )
+        {
+            errors.add( ex );
+        }
+        metricRegistry = null;
+        for( String healthCheckName : healthCheckRegistry.getNames() )
+        {
+            healthCheckRegistry.unregister( healthCheckName );
+        }
+        healthCheckRegistry = null;
+        prefix = null;
+        if( !errors.isEmpty() )
+        {
+            throw new PassivationException( errors );
+        }
+    }
+
+    @Override
+    public MetricRegistry metricRegistry()
+    {
+        return metricRegistry;
+    }
+
+    @Override
+    public HealthCheckRegistry healthCheckRegistry()
+    {
+        return healthCheckRegistry;
+    }
+
+    @Override
+    protected MetricsTimerFactory createMetricsTimerFactory()
+    {
+        return new MetricsTimerFactory()
+        {
+            @Override
+            public MetricsTimer createTimer( String name )
+            {
+                return new CodahaleTimer( metricRegistry.timer( name( prefix, name ) ) );
+            }
+
+            @Override
+            public Stream<Metric> registered()
+            {
+                return metricRegistry.getTimers().values().stream().map( CodahaleTimer::new );
+            }
+        };
+    }
+
+    @Override
+    protected MetricsMeterFactory createMetricsMeterFactory()
+    {
+        return new MetricsMeterFactory()
+        {
+            @Override
+            public MetricsMeter createMeter( String name )
+            {
+                return new CodahaleMeter( metricRegistry.meter( name( prefix, name ) ) );
+            }
+
+            @Override
+            public Stream<Metric> registered()
+            {
+                return metricRegistry.getMeters().values().stream().map( CodahaleMeter::new );
+            }
+        };
+    }
+
+    @Override
+    protected MetricsHistogramFactory createMetricsHistogramFactory()
+    {
+        return new MetricsHistogramFactory()
+        {
+            @Override
+            public MetricsHistogram createHistogram( String name )
+            {
+                return new CodahaleHistogram( metricRegistry.histogram( name( prefix, name ) ) );
+            }
+
+            @Override
+            public Stream<Metric> registered()
+            {
+                return metricRegistry.getHistograms().values().stream().map( CodahaleHistogram::new );
+            }
+        };
+    }
+
+    @Override
+    protected MetricsHealthCheckFactory createMetricsHealthCheckFactory()
+    {
+        return new MetricsHealthCheckFactory()
+        {
+            @Override
+            public MetricsHealthCheck registerHealthCheck( String name, MetricsHealthCheck check )
+            {
+                HealthCheck codahaleCheck = new HealthCheck() {
+                    @Override
+                    protected Result check() throws Exception {
+                        return CodahaleHealthCheck.unwrap( check.check() );
+                    }
+                };
+                healthCheckRegistry.register( name( prefix, name ), codahaleCheck );
+                return new CodahaleHealthCheck( check );
+            }
+
+            @Override
+            public Stream<Metric> registered()
+            {
+                return healthCheckRegistry.getNames().stream().map( name -> new MetricsHealthCheck() {
+                    @Override
+                    public Result check() throws Exception {
+                        return CodahaleHealthCheck.wrap( healthCheckRegistry.runHealthCheck( name ) );
+                    }
+                });
+            }
+        };
+    }
+
+    @Override
+    protected MetricsGaugeFactory createMetricsGaugeFactory()
+    {
+        return new MetricsGaugeFactory()
+        {
+            @Override
+            public <T> MetricsGauge<T> registerGauge( String name, final MetricsGauge<T> gauge )
+            {
+                Gauge<T> codahaleGauge = gauge::value;
+                metricRegistry.register( name( prefix, name ), codahaleGauge );
+                return new CodahaleGauge<>( codahaleGauge );
+            }
+
+            @Override
+            @SuppressWarnings( "unchecked" )
+            public Stream<Metric> registered()
+            {
+                return metricRegistry.getGauges().values().stream().map( CodahaleGauge::new );
+            }
+        };
+    }
+
+    @Override
+    protected MetricsCounterFactory createMetricsCounterFactory()
+    {
+        return new MetricsCounterFactory()
+        {
+            @Override
+            public MetricsCounter createCounter( String name )
+            {
+                return new CodahaleCounter( metricRegistry.counter( name( prefix, name) ) );
+            }
+
+            @Override
+            public Stream<Metric> registered()
+            {
+                return metricRegistry.getCounters().values().stream().map( CodahaleCounter::new );
+            }
+        };
+    }
+
+}
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsProvider.java b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsProvider.java
new file mode 100644
index 0000000..18a5483
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleMetricsProvider.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.metrics.codahale;
+
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.health.HealthCheckRegistry;
+import org.apache.polygene.api.metrics.MetricsProvider;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+
+@Mixins( CodahaleMetricsMixin.class )
+public interface CodahaleMetricsProvider
+        extends MetricsProvider, ServiceActivation
+{
+    MetricRegistry metricRegistry();
+
+    HealthCheckRegistry healthCheckRegistry();
+}
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleTimer.java b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleTimer.java
new file mode 100644
index 0000000..4f06ede
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/CodahaleTimer.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.metrics.codahale;
+
+import com.codahale.metrics.Timer;
+import org.apache.polygene.api.metrics.MetricsTimer;
+
+public class CodahaleTimer
+    implements MetricsTimer
+{
+    private Timer timer;
+
+    public CodahaleTimer( Timer timer )
+    {
+        this.timer = timer;
+    }
+
+    @Override
+    public Context start()
+    {
+        return timer.time()::stop;
+    }
+}
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/assembly/CodahaleMetricsAssembler.java b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/assembly/CodahaleMetricsAssembler.java
new file mode 100644
index 0000000..a737c06
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/assembly/CodahaleMetricsAssembler.java
@@ -0,0 +1,124 @@
+/*
+ *  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.polygene.metrics.codahale.assembly;
+
+import com.codahale.metrics.ConsoleReporter;
+import com.codahale.metrics.CsvReporter;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.Reporter;
+import com.codahale.metrics.Slf4jReporter;
+import java.io.File;
+import java.io.PrintStream;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.metrics.codahale.CodahaleMetricsProvider;
+
+public class CodahaleMetricsAssembler
+    extends Assemblers.VisibilityIdentityConfig<CodahaleMetricsAssembler>
+{
+    private final CodahaleMetricsDeclaration declaration = new CodahaleMetricsDeclaration();
+
+    public CodahaleMetricsAssembler withPrefix( String prefix )
+    {
+        declaration.prefix = prefix;
+        return this;
+    }
+
+    public CodahaleMetricsAssembler withFullyQualifiedClassNames()
+    {
+        declaration.fqcn = true;
+        return this;
+    }
+
+    public CodahaleMetricsAssembler withSimpleClassNames()
+    {
+        declaration.fqcn = false;
+        return this;
+    }
+
+    public CodahaleMetricsAssembler withJmx()
+    {
+        declaration.jmx = true;
+        return this;
+    }
+
+    public CodahaleMetricsAssembler withoutJmx()
+    {
+        declaration.jmx = false;
+        return this;
+    }
+
+    public CodahaleMetricsAssembler withConsoleReporter( PrintStream out, long period, TimeUnit timeunit )
+    {
+        declaration.reportersFactories.add( metricRegistry -> {
+            ConsoleReporter reporter = ConsoleReporter.forRegistry( metricRegistry ).outputTo( out ).build();
+            reporter.start( period, timeunit );
+            return reporter;
+        });
+        return this;
+    }
+
+    public CodahaleMetricsAssembler withSlf4jReporter( Slf4jReporter.LoggingLevel level, long period, TimeUnit timeunit )
+    {
+        declaration.reportersFactories.add( metricRegistry -> {
+            Slf4jReporter reporter = Slf4jReporter.forRegistry( metricRegistry ).withLoggingLevel( level ).build();
+            reporter.start( period, timeunit );
+            return reporter;
+        });
+        return this;
+    }
+
+    public CodahaleMetricsAssembler withCsvReporter( File outDirectory, long period, TimeUnit timeunit )
+    {
+        declaration.reportersFactories.add( metricRegistry -> {
+            CsvReporter reporter = CsvReporter.forRegistry( metricRegistry ).build( outDirectory );
+            reporter.start( period, timeunit );
+            return reporter;
+        });
+        return this;
+    }
+
+    public CodahaleMetricsAssembler withReporter( Function<MetricRegistry, Reporter> factory )
+    {
+        declaration.reportersFactories.add( factory );
+        return this;
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+            throws AssemblyException
+    {
+        ServiceDeclaration service =
+            module.services( CodahaleMetricsProvider.class )
+                  .setMetaInfo( declaration )
+                  .instantiateOnStartup()
+                  .identifiedBy( identity() )
+                  .visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+    }
+}
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/assembly/CodahaleMetricsDeclaration.java b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/assembly/CodahaleMetricsDeclaration.java
new file mode 100644
index 0000000..0b5cdb6
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/assembly/CodahaleMetricsDeclaration.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.metrics.codahale.assembly;
+
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.Reporter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+
+public class CodahaleMetricsDeclaration
+{
+    String prefix;
+
+    boolean fqcn = false;
+
+    boolean jmx = true;
+
+    final List<Function<MetricRegistry, Reporter>> reportersFactories = new ArrayList<>();
+
+
+    public String prefix()
+    {
+        return prefix;
+    }
+
+    public boolean fqcn()
+    {
+        return fqcn;
+    }
+
+    public boolean jmx()
+    {
+        return jmx;
+    }
+
+    public List<Function<MetricRegistry, Reporter>> reportersFactories()
+    {
+        return reportersFactories;
+    }
+}
diff --git a/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/package.html b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/package.html
new file mode 100644
index 0000000..5a46cfb
--- /dev/null
+++ b/extensions/metrics-codahale/src/main/java/org/apache/polygene/metrics/codahale/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Codahale Metrics.</h2>
+    </body>
+</html>
diff --git a/extensions/metrics-codahale/src/test/java/org/apache/polygene/metrics/codahale/CodahaleMetricsTest.java b/extensions/metrics-codahale/src/test/java/org/apache/polygene/metrics/codahale/CodahaleMetricsTest.java
new file mode 100644
index 0000000..35fa19b
--- /dev/null
+++ b/extensions/metrics-codahale/src/test/java/org/apache/polygene/metrics/codahale/CodahaleMetricsTest.java
@@ -0,0 +1,81 @@
+/*
+ *  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.polygene.metrics.codahale;
+
+import com.codahale.metrics.MetricRegistry;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.metrics.codahale.assembly.CodahaleMetricsAssembler;
+import org.apache.polygene.test.metrics.AbstractPolygeneMetricsTest;
+
+import org.apache.polygene.test.metrics.MetricValuesProvider;
+import org.junit.Test;
+
+import java.util.Collection;
+
+public class CodahaleMetricsTest extends AbstractPolygeneMetricsTest
+{
+    @Override
+    protected Assemblers.Visible<? extends Assembler> metricsAssembler()
+    {
+        // START SNIPPET: assembly
+        return new CodahaleMetricsAssembler();
+        // END SNIPPET: assembly
+    }
+
+    @Test
+    public void uowTimerCodahale() throws PassivationException, ActivationException
+    {
+        assertUowTimer( codahaleMetricValuesProvider() );
+    }
+
+    @Test
+    public void timingCaptureCodahale() throws PassivationException, ActivationException
+    {
+        assertTimingCapture( codahaleMetricValuesProvider() );
+    }
+
+    private MetricValuesProvider codahaleMetricValuesProvider()
+    {
+        Module module = metricsModule();
+        // START SNIPPET: registry
+        CodahaleMetricsProvider metricsProvider = module.findService( CodahaleMetricsProvider.class ).get();
+        // END SNIPPET: registry
+        return new MetricValuesProvider()
+        {
+            @Override
+            public Collection<String> registeredMetricNames()
+            {
+                // START SNIPPET: registry
+                MetricRegistry metricRegistry = metricsProvider.metricRegistry();
+                // END SNIPPET: registry
+                return metricRegistry.getNames();
+            }
+
+            @Override
+            public long timerCount( String timerName )
+            {
+                MetricRegistry metricRegistry = metricsProvider.metricRegistry();
+                return metricRegistry.timer( timerName ).getCount();
+            }
+        };
+    }
+}
diff --git a/extensions/metrics-codahale/src/test/java/org/apache/polygene/metrics/codahale/CodahaleTimingCaptureTest.java b/extensions/metrics-codahale/src/test/java/org/apache/polygene/metrics/codahale/CodahaleTimingCaptureTest.java
new file mode 100644
index 0000000..fa88caa
--- /dev/null
+++ b/extensions/metrics-codahale/src/test/java/org/apache/polygene/metrics/codahale/CodahaleTimingCaptureTest.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.metrics.codahale;
+
+import com.codahale.metrics.MetricRegistry;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.metrics.codahale.assembly.CodahaleMetricsAssembler;
+import org.apache.polygene.test.metrics.AbstractTimingCaptureTest;
+import org.apache.polygene.test.metrics.MetricValuesProvider;
+
+import java.util.Collection;
+
+import static org.apache.polygene.api.common.Visibility.application;
+
+public class CodahaleTimingCaptureTest extends AbstractTimingCaptureTest
+{
+    @Override
+    protected Assemblers.Visible<? extends Assembler> metricsAssembler()
+    {
+        return new CodahaleMetricsAssembler();
+    }
+
+    @Override
+    protected MetricValuesProvider metricValuesProvider()
+    {
+        CodahaleMetricsProvider metricsProvider = serviceFinder.findService( CodahaleMetricsProvider.class ).get();
+        MetricRegistry metricRegistry = metricsProvider.metricRegistry();
+        return new MetricValuesProvider()
+        {
+            @Override
+            public Collection<String> registeredMetricNames()
+            {
+                return metricRegistry.getNames();
+            }
+
+            @Override
+            public long timerCount( String timerName )
+            {
+                return metricRegistry.timer( application.name() + '.' + timerName ).getCount();
+            }
+        };
+    }
+}
diff --git a/extensions/metrics-yammer/build.gradle b/extensions/metrics-yammer/build.gradle
deleted file mode 100644
index c89eba1..0000000
--- a/extensions/metrics-yammer/build.gradle
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.
- */
-
-description = "Apache Zest™ Metrics Extension"
-
-jar { manifest { name = "Apache Zest™ Extension - Metrics" }}
-
-dependencies {
-
-  compile project(":org.qi4j.core:org.qi4j.core.bootstrap")
-  compile libraries.yammer_metrics
-
-  testCompile project( ":org.qi4j.core:org.qi4j.core.testsupport" )
-
-  testRuntime project( ":org.qi4j.core:org.qi4j.core.runtime" )
-  testRuntime libraries.logback
-
-}
diff --git a/extensions/metrics-yammer/dev-status.xml b/extensions/metrics-yammer/dev-status.xml
deleted file mode 100644
index 9c6bbae..0000000
--- a/extensions/metrics-yammer/dev-status.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  ~ Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
-  ~
-  ~ Licensed 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.
-  -->
-
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
-  <status>
-        <!--none,early,beta,stable,mature-->
-        <codebase>stable</codebase>
-
-        <!-- none, brief, good, complete -->
-        <documentation>none</documentation>
-
-        <!-- none, some, good, complete -->
-        <unittests>some</unittests>
-    </status>
-    <licenses>
-        <license>ALv2</license>
-    </licenses>
-</module>
\ No newline at end of file
diff --git a/extensions/metrics-yammer/src/docs/metrics-yammer.txt b/extensions/metrics-yammer/src/docs/metrics-yammer.txt
deleted file mode 100644
index 621a9c4..0000000
--- a/extensions/metrics-yammer/src/docs/metrics-yammer.txt
+++ /dev/null
@@ -1,32 +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.
-///////////////////////////////////////////////////////////////
-
-[[extension-metrics-yammer, Yammer Metrics]]
-= Yammer Metrics =
-
-[devstatus]
---------------
-source=extensions/metrics-yammer/dev-status.xml
---------------
-
-Yammer Metrics
-
-NOTE: This Extension has no documentation yet. Learn how to contribute in <<community-docs>>.
-
-include::../../build/docs/buildinfo/artifact.txt[]
diff --git a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerCounter.java b/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerCounter.java
deleted file mode 100644
index 87e7c9c..0000000
--- a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerCounter.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.metrics.yammer;
-
-import com.yammer.metrics.core.Counter;
-import org.qi4j.api.metrics.MetricsCounter;
-
-public class YammerCounter
-    implements MetricsCounter
-{
-    private Counter counter;
-
-    public YammerCounter( Counter counter )
-    {
-
-        this.counter = counter;
-    }
-
-    @Override
-    public void increment()
-    {
-        counter.inc();
-    }
-
-    @Override
-    public void increment( int steps )
-    {
-        counter.inc( steps );
-    }
-
-    @Override
-    public void decrement()
-    {
-        counter.dec();
-    }
-
-    @Override
-    public void decrement( int steps )
-    {
-        counter.dec( steps );
-    }
-}
diff --git a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerGauge.java b/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerGauge.java
deleted file mode 100644
index 0347745..0000000
--- a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerGauge.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.metrics.yammer;
-
-import com.yammer.metrics.core.Gauge;
-import org.qi4j.api.metrics.MetricsGauge;
-
-public class YammerGauge<T>
-    implements MetricsGauge<T>
-{
-    private Gauge<T> gauge;
-
-    public YammerGauge( Gauge<T> gauge )
-    {
-        this.gauge = gauge;
-    }
-
-    @Override
-    public T value()
-    {
-        return gauge.value();
-    }
-}
diff --git a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerHealthCheck.java b/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerHealthCheck.java
deleted file mode 100644
index e6710b2..0000000
--- a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerHealthCheck.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.metrics.yammer;
-
-import com.yammer.metrics.HealthChecks;
-import com.yammer.metrics.core.HealthCheck;
-import org.qi4j.api.metrics.MetricsHealthCheck;
-
-public class YammerHealthCheck
-    implements MetricsHealthCheck
-{
-    private MetricsHealthCheck check;
-
-    public YammerHealthCheck( Class<?> origin, String name, final MetricsHealthCheck check )
-    {
-        this.check = check;
-        HealthChecks.register( new HealthCheck( name )
-        {
-            @Override
-            protected Result check()
-                throws Exception
-            {
-                MetricsHealthCheck.Result result = check.check();
-                String message = result.getMessage();
-                if( result.isHealthy() )
-                {
-                    if( message != null )
-                    {
-                        return Result.healthy( message );
-                    }
-                    return Result.healthy();
-                }
-                Throwable exception = result.getException();
-                if( exception != null )
-                {
-                    return Result.unhealthy( exception );
-                }
-                return Result.unhealthy( message );
-            }
-        } );
-    }
-
-    @Override
-    public Result check()
-        throws Exception
-    {
-        return check.check();
-    }
-}
diff --git a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerHistogram.java b/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerHistogram.java
deleted file mode 100644
index 9b26e3b..0000000
--- a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerHistogram.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.metrics.yammer;
-
-import com.yammer.metrics.core.Histogram;
-import org.qi4j.api.metrics.MetricsHistogram;
-
-public class YammerHistogram
-    implements MetricsHistogram
-{
-    private Histogram histogram;
-
-    public YammerHistogram( Histogram histogram )
-    {
-        this.histogram = histogram;
-    }
-
-    @Override
-    public void update( long newValue )
-    {
-        histogram.update( newValue );
-    }
-}
diff --git a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerMeter.java b/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerMeter.java
deleted file mode 100644
index 699ba24..0000000
--- a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerMeter.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.metrics.yammer;
-
-import com.yammer.metrics.core.Meter;
-import org.qi4j.api.metrics.MetricsMeter;
-
-public class YammerMeter
-    implements MetricsMeter
-{
-    private Meter meter;
-
-    public YammerMeter( Meter meter )
-    {
-        this.meter = meter;
-    }
-
-    @Override
-    public void mark()
-    {
-        meter.mark();
-    }
-
-    @Override
-    public void mark( int numberOfEvents )
-    {
-        meter.mark( numberOfEvents );
-    }
-}
diff --git a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerMetricsAssembler.java b/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerMetricsAssembler.java
deleted file mode 100644
index 3f34d81..0000000
--- a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerMetricsAssembler.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.metrics.yammer;
-
-import com.yammer.metrics.Metrics;
-import com.yammer.metrics.reporting.AbstractPollingReporter;
-import com.yammer.metrics.reporting.ConsoleReporter;
-import com.yammer.metrics.reporting.CsvReporter;
-import java.io.File;
-import java.io.PrintStream;
-import java.util.concurrent.TimeUnit;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-public class YammerMetricsAssembler
-    implements Assembler
-{
-
-    private AbstractPollingReporter reporter;
-
-    /**
-     * Default constructor only creates a Yammer JMXReporter
-     */
-    public YammerMetricsAssembler()
-    {
-    }
-
-    /**
-     * Creates a ConsoleReporter and sends the output to the given PrintStream.
-     *
-     * @param out      The PrintStream to receive the output.
-     * @param period   The reporting interval.
-     * @param timeunit The TimeUnit for the reporting interval.
-     */
-    public YammerMetricsAssembler( PrintStream out, long period, TimeUnit timeunit )
-    {
-        reporter = new ConsoleReporter( out );
-        try
-        {
-            reporter.start( period, timeunit );
-        }
-        catch( RuntimeException e )
-        {
-            e.printStackTrace();
-            throw e;
-        }
-    }
-
-    /**
-     * Creates a CSV reporter and writes the result to the given directory
-     *
-     * @param outDirectory The directory to write the result to.
-     * @param period       The reporting interval.
-     * @param timeunit     The TimeUnit for the reporting interval.
-     */
-    public YammerMetricsAssembler( File outDirectory, long period, TimeUnit timeunit )
-    {
-        reporter = new CsvReporter( Metrics.defaultRegistry(), outDirectory );
-        reporter.start( period, timeunit );
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( YammerMetricsProvider.class )
-            .instantiateOnStartup()
-            .visibleIn( Visibility.application );
-    }
-
-    /**
-     * Closing any Reporter that has been started.
-     */
-    public void shutdown()
-    {
-        reporter.shutdown();
-    }
-}
diff --git a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerMetricsMixin.java b/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerMetricsMixin.java
deleted file mode 100644
index 16a8091..0000000
--- a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerMetricsMixin.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.metrics.yammer;
-
-import com.yammer.metrics.Metrics;
-import com.yammer.metrics.core.Counter;
-import com.yammer.metrics.core.Gauge;
-import java.util.concurrent.TimeUnit;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.metrics.Metric;
-import org.qi4j.api.metrics.MetricsCounter;
-import org.qi4j.api.metrics.MetricsCounterFactory;
-import org.qi4j.api.metrics.MetricsGauge;
-import org.qi4j.api.metrics.MetricsGaugeFactory;
-import org.qi4j.api.metrics.MetricsHealthCheck;
-import org.qi4j.api.metrics.MetricsHealthCheckFactory;
-import org.qi4j.api.metrics.MetricsHistogram;
-import org.qi4j.api.metrics.MetricsHistogramFactory;
-import org.qi4j.api.metrics.MetricsMeter;
-import org.qi4j.api.metrics.MetricsMeterFactory;
-import org.qi4j.api.metrics.MetricsTimer;
-import org.qi4j.api.metrics.MetricsTimerFactory;
-import org.qi4j.api.structure.Application;
-import org.qi4j.functional.Iterables;
-import org.qi4j.spi.metrics.MetricsProviderAdapter;
-
-public class YammerMetricsMixin extends MetricsProviderAdapter
-    implements YammerMetricsProvider
-{
-    @Structure
-    private Application app;
-
-    @Override
-    protected MetricsTimerFactory createMetricsTimerFactory()
-    {
-        return new MetricsTimerFactory()
-        {
-            @Override
-            public MetricsTimer createTimer( Class<?> origin, String name, TimeUnit duration, TimeUnit rate )
-            {
-                return new YammerTimer( Metrics.newTimer( origin, name, app.name(), duration, rate ) );
-            }
-
-            @Override
-            public Iterable<Metric> registered()
-            {
-                return Iterables.empty();
-            }
-        };
-    }
-
-    @Override
-    protected MetricsMeterFactory createMetricsMeterFactory()
-    {
-        return new MetricsMeterFactory()
-        {
-            @Override
-            public MetricsMeter createMeter( Class<?> origin, String name, String eventType, TimeUnit rate )
-            {
-                return new YammerMeter( Metrics.newMeter( origin, name, app.name(), eventType, rate ) );
-            }
-
-            @Override
-            public Iterable<Metric> registered()
-            {
-                return Iterables.empty();
-            }
-        };
-    }
-
-    @Override
-    protected MetricsHistogramFactory createMetricsHistogramFactory()
-    {
-        return new MetricsHistogramFactory()
-        {
-            @Override
-            public MetricsHistogram createHistogram( Class<?> origin, String name )
-            {
-                return new YammerHistogram( Metrics.newHistogram( origin, name, app.name() ) );
-            }
-
-            @Override
-            public Iterable<Metric> registered()
-            {
-                return Iterables.empty();
-            }
-        };
-    }
-
-    @Override
-    protected MetricsHealthCheckFactory createMetricsHealthCheckFactory()
-    {
-        return new MetricsHealthCheckFactory()
-        {
-            @Override
-            public MetricsHealthCheck registerHealthCheck( Class<?> origin, String name, MetricsHealthCheck check )
-            {
-                return new YammerHealthCheck( origin, name, check );
-            }
-
-            @Override
-            public Iterable<Metric> registered()
-            {
-                return Iterables.empty();
-            }
-        };
-    }
-
-    @Override
-    protected MetricsGaugeFactory createMetricsGaugeFactory()
-    {
-        return new MetricsGaugeFactory()
-        {
-            @Override
-            public <T> MetricsGauge<T> registerGauge( Class<?> origin, String name, final MetricsGauge<T> gauge )
-            {
-                Gauge<T> yammer = Metrics.newGauge( origin, name, app.name(), new Gauge<T>()
-                {
-
-                    @Override
-                    public T value()
-                    {
-                        return gauge.value();
-                    }
-                } );
-                return new YammerGauge<>( yammer );
-            }
-
-            @Override
-            public Iterable<Metric> registered()
-            {
-                return Iterables.empty();
-            }
-        };
-    }
-
-    @Override
-    protected MetricsCounterFactory createMetricsCounterFactory()
-    {
-        return new MetricsCounterFactory()
-        {
-            @Override
-            public MetricsCounter createCounter( Class<?> origin, String name )
-            {
-                Counter counter = Metrics.newCounter( origin, name, app.name() );
-                return new YammerCounter( counter );
-            }
-
-            @Override
-            public Iterable<Metric> registered()
-            {
-                return Iterables.empty();
-            }
-        };
-    }
-
-    @Override
-    public void shutdownMetrics()
-        throws Exception
-    {
-        Metrics.shutdown();
-    }
-
-}
diff --git a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerMetricsProvider.java b/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerMetricsProvider.java
deleted file mode 100644
index 9db147c..0000000
--- a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerMetricsProvider.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.metrics.yammer;
-
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.metrics.MetricsProvider;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceReference;
-
-@Mixins( YammerMetricsMixin.class )
-@Activators( YammerMetricsProvider.Activator.class )
-public interface YammerMetricsProvider
-        extends MetricsProvider
-{
-
-    void shutdownMetrics()
-            throws Exception;
-
-    class Activator
-            extends ActivatorAdapter<ServiceReference<YammerMetricsProvider>>
-    {
-
-        @Override
-        public void beforePassivation( ServiceReference<YammerMetricsProvider> passivating )
-                throws Exception
-        {
-            passivating.get().shutdownMetrics();
-        }
-
-    }
-
-}
diff --git a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerTimer.java b/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerTimer.java
deleted file mode 100644
index 1a82ed3..0000000
--- a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/YammerTimer.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.metrics.yammer;
-
-import com.yammer.metrics.core.Timer;
-import com.yammer.metrics.core.TimerContext;
-import org.qi4j.api.metrics.MetricsTimer;
-
-public class YammerTimer
-    implements MetricsTimer
-{
-    private Timer timer;
-
-    public YammerTimer( Timer timer )
-    {
-        this.timer = timer;
-    }
-
-    @Override
-    public Context start()
-    {
-        final TimerContext context = timer.time();
-        return new Context()
-        {
-            @Override
-            public void stop()
-            {
-                context.stop();
-            }
-        };
-    }
-}
diff --git a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/package.html b/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/package.html
deleted file mode 100644
index 2b44d24..0000000
--- a/extensions/metrics-yammer/src/main/java/org/qi4j/metrics/yammer/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Yamer Metrics.</h2>
-    </body>
-</html>
diff --git a/extensions/metrics-yammer/src/test/java/org/qi4j/metrics/yammer/NoMetricsInstalledTest.java b/extensions/metrics-yammer/src/test/java/org/qi4j/metrics/yammer/NoMetricsInstalledTest.java
deleted file mode 100644
index 9d93f89..0000000
--- a/extensions/metrics-yammer/src/test/java/org/qi4j/metrics/yammer/NoMetricsInstalledTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.metrics.yammer;
-
-import com.yammer.metrics.Metrics;
-import com.yammer.metrics.core.MetricPredicate;
-import com.yammer.metrics.reporting.ConsoleReporter;
-import java.util.concurrent.TimeUnit;
-import org.junit.Test;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-public class NoMetricsInstalledTest extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( Person.class );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Test
-    public void givenMetricsEnabledQi4jWhenManyEntityChangesExpectCounterToBeOneOrZeroAndChangeRateHigh()
-        throws UnitOfWorkCompletionException
-    {
-        ConsoleReporter reporter = new ConsoleReporter( Metrics.defaultRegistry(), System.out, MetricPredicate.ALL );
-        reporter.start( 100, TimeUnit.MILLISECONDS );
-        for( int i=0; i < 20000; i++ )
-        {
-            createEntity(i);
-        }
-        for( int i=0; i < 20000; i++ )
-        {
-            readEntity( i );
-        }
-    }
-
-    private void readEntity( int id )
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            Person p = uow.get( Person.class, "" + id );
-        }
-        finally
-        {
-            if( uow.isOpen())
-                uow.discard();
-        }
-    }
-
-    private void createEntity( int id )
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            uow.newEntity( Person.class, "" + id );
-            uow.complete();
-        }
-        finally
-        {
-            if( uow.isOpen())
-                uow.discard();
-        }
-    }
-
-    public interface Person extends EntityComposite
-    {
-        @Optional
-        Property<String> name();
-
-    }
-}
diff --git a/extensions/metrics-yammer/src/test/java/org/qi4j/metrics/yammer/YammerTest.java b/extensions/metrics-yammer/src/test/java/org/qi4j/metrics/yammer/YammerTest.java
deleted file mode 100644
index eb55091..0000000
--- a/extensions/metrics-yammer/src/test/java/org/qi4j/metrics/yammer/YammerTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.metrics.yammer;
-
-import com.yammer.metrics.Metrics;
-import com.yammer.metrics.core.MetricPredicate;
-import com.yammer.metrics.reporting.ConsoleReporter;
-import java.util.concurrent.TimeUnit;
-import org.junit.Test;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-public class YammerTest extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( Person.class );
-        new EntityTestAssembler().assemble( module );
-        new YammerMetricsAssembler().assemble( module );
-    }
-
-    @Test
-    public void givenMetricsEnabledQi4jWhenManyEntityChangesExpectCounterToBeOneOrZeroAndChangeRateHigh()
-        throws UnitOfWorkCompletionException
-    {
-        ConsoleReporter reporter = new ConsoleReporter( Metrics.defaultRegistry(), System.out, MetricPredicate.ALL );
-        reporter.start( 100, TimeUnit.MILLISECONDS );
-        for( int i=0; i < 20000; i++ )
-        {
-            createEntity(i);
-        }
-        for( int i=0; i < 20000; i++ )
-        {
-            readEntity( i );
-        }
-    }
-
-    private void readEntity( int id )
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            Person p = uow.get( Person.class, "" + id );
-        }
-        finally
-        {
-            if( uow.isOpen())
-                uow.discard();
-        }
-    }
-
-    private void createEntity( int id )
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            uow.newEntity( Person.class, "" + id );
-            uow.complete();
-        }
-        finally
-        {
-            if( uow.isOpen())
-                uow.discard();
-        }
-    }
-
-    public interface Person extends EntityComposite
-    {
-        @Optional
-        Property<String> name();
-
-    }
-}
diff --git a/extensions/migration/build.gradle b/extensions/migration/build.gradle
index fa3072a..15f9cfb 100644
--- a/extensions/migration/build.gradle
+++ b/extensions/migration/build.gradle
@@ -1,32 +1,37 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Migration Extension"
+apply plugin: 'polygene-extension'
 
-jar { manifest { name = "Apache Zest™ Extension - Migration" }}
+description = "Apache Polygene™ Migration Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - Migration" }}
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.spi"))
-  compile libraries.slf4j_api
+  api polygene.core.spi
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
+  implementation libraries.slf4j_api
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/extensions/migration/dev-status.xml b/extensions/migration/dev-status.xml
index f6b60e4..9cf2f2a 100644
--- a/extensions/migration/dev-status.xml
+++ b/extensions/migration/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
         <!--none,early,beta,stable,mature-->
         <codebase>stable</codebase>
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/MigrationConfiguration.java b/extensions/migration/src/main/java/org/apache/polygene/migration/MigrationConfiguration.java
new file mode 100644
index 0000000..0ad6d48
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/MigrationConfiguration.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.migration;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * JAVADOC
+ */
+public interface MigrationConfiguration
+{
+    @UseDefaults
+    Property<String> lastStartupVersion();
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/MigrationEventLogger.java b/extensions/migration/src/main/java/org/apache/polygene/migration/MigrationEventLogger.java
new file mode 100644
index 0000000..bc6be75
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/MigrationEventLogger.java
@@ -0,0 +1,112 @@
+/*
+ *  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.polygene.migration;
+
+import java.util.Arrays;
+import java.util.Map;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * MigrationEvents implementation that logs the events.
+ */
+public class MigrationEventLogger
+    implements MigrationEvents
+{
+    protected Logger logger = LoggerFactory.getLogger( getClass().getName() );
+
+    @Override
+    public void propertyAdded( String entity, String name, Object value )
+    {
+        logger.info( "Added property " + name + " with value " + ( value == null ? "null" : value.toString() ) + " in " + entity );
+    }
+
+    @Override
+    public void propertyRemoved( String entity, String name )
+    {
+        logger.info( "Removed property " + name + " in " + entity );
+    }
+
+    @Override
+    public void propertyRenamed( String entity, String from, String to )
+    {
+        logger.info( "Renamed property from " + from + " to " + to + " in " + entity );
+    }
+
+    @Override
+    public void associationAdded( String entity, String name, String value )
+    {
+        logger.info( "Added association " + name + " with value " + value + " in " + entity );
+    }
+
+    @Override
+    public void associationRemoved( String entity, String name )
+    {
+        logger.info( "Removed association " + name + " in " + entity );
+    }
+
+    @Override
+    public void associationRenamed( String entity, String from, String to )
+    {
+        logger.info( "Renamed association from " + from + " to " + to + " in " + entity );
+    }
+
+    @Override
+    public void manyAssociationAdded( String entity, String name, String... value )
+    {
+        logger.info( "Added many-association " + name + " with values " + Arrays.asList( value ) + " in " + entity );
+    }
+
+    @Override
+    public void manyAssociationRemoved( String entity, String name )
+    {
+        logger.info( "Removed many-association " + name + " in " + entity );
+    }
+
+    @Override
+    public void manyAssociationRenamed( String entity, String from, String to )
+    {
+        logger.info( "Renamed many-association from " + from + " to " + to + " in " + entity );
+    }
+
+    @Override
+    public void namedAssociationAdded( String entity, String name, Map<String, String> value )
+    {
+        logger.info( "Added named-association " + name + " with values " + value + " in " + entity );
+    }
+
+    @Override
+    public void namedAssociationRemoved( String entity, String name )
+    {
+        logger.info( "Removed named-association " + name + " in " + entity );
+    }
+
+    @Override
+    public void namedAssociationRenamed( String entity, String from, String to )
+    {
+        logger.info( "Renamed named-association from " + from + " to " + to + " in " + entity );
+    }
+
+    @Override
+    public void entityTypeChanged( String entity, String newEntityType )
+    {
+        logger.info( "Changed entitytype to " + newEntityType + " in " + entity );
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/MigrationEvents.java b/extensions/migration/src/main/java/org/apache/polygene/migration/MigrationEvents.java
new file mode 100644
index 0000000..a6c8386
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/MigrationEvents.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.migration;
+
+import java.util.Map;
+
+/**
+ * Implement this as a service to receive events from the Migration process.
+ */
+public interface MigrationEvents
+{
+    void propertyAdded( String entity, String name, Object value );
+
+    void propertyRemoved( String entity, String name );
+
+    void propertyRenamed( String entity, String from, String to );
+
+    void associationAdded( String entity, String name, String defaultReference );
+
+    void associationRemoved( String entity, String name );
+
+    void associationRenamed( String entity, String from, String to );
+
+    void manyAssociationAdded( String entity, String name, String... defaultReferences );
+
+    void manyAssociationRemoved( String entity, String name );
+
+    void manyAssociationRenamed( String entity, String from, String to );
+
+    void namedAssociationAdded( String entity, String name, Map<String, String> defaultReferences );
+
+    void namedAssociationRemoved( String entity, String name );
+
+    void namedAssociationRenamed( String entity, String from, String to );
+
+    void entityTypeChanged( String entity, String newEntityType );
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/MigrationService.java b/extensions/migration/src/main/java/org/apache/polygene/migration/MigrationService.java
new file mode 100644
index 0000000..f361801
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/MigrationService.java
@@ -0,0 +1,590 @@
+/*
+ *  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.polygene.migration;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonException;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonValue;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.migration.assembly.EntityMigrationRule;
+import org.apache.polygene.migration.assembly.MigrationBuilder;
+import org.apache.polygene.migration.assembly.MigrationContext;
+import org.apache.polygene.migration.assembly.MigrationRule;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.helpers.JSONKeys;
+import org.apache.polygene.spi.entitystore.helpers.Migration;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+import org.apache.polygene.spi.serialization.JsonSerialization;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static java.util.Arrays.asList;
+
+/**
+ * Migration service. This is used by MapEntityStore EntityStore implementations to
+ * migrate JSON state for Entities. To use it register the service so that the EntityStore
+ * can access it, and then create MigrationRules during the assembly of your application,
+ * which is registered as metainfo for this service.
+ *
+ * The rules invoke operations, which in turn invoke the Migrator interface to perform the actual
+ * migration. If the Migrator accepts a migration command the change is performed, and an event
+ * is triggered. These events can be received by implementing the MigrationEvents interface in a service
+ * that is visible by this MigrationService.
+ */
+@Mixins( MigrationService.MigrationMixin.class )
+@Activators( MigrationService.Activator.class )
+public interface MigrationService
+    extends Migration
+{
+    void initialize()
+        throws Exception;
+
+    class Activator
+        extends ActivatorAdapter<ServiceReference<MigrationService>>
+    {
+        @Override
+        public void afterActivation( ServiceReference<MigrationService> activated )
+            throws Exception
+        {
+            activated.get().initialize();
+        }
+    }
+
+    class MigrationMixin
+        implements MigrationService, Migrator
+    {
+        private static final Logger LOGGER = LoggerFactory.getLogger( MigrationService.class );
+
+        @Structure
+        private Application app;
+
+        @This
+        private Configuration<MigrationConfiguration> config;
+
+        @Uses
+        private ServiceDescriptor descriptor;
+
+        @Service
+        private StateStore store;
+
+        @Service
+        private EntityStore entityStore;
+
+        @Service
+        private JsonSerialization serialization;
+
+        @Service
+        private JavaxJsonFactories jsonFactories;
+
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @This
+        private Migrator migrator;
+
+        @Service
+        private Iterable<MigrationEvents> migrationEvents;
+
+        private MigrationBuilder builder;
+
+
+        @Override
+        public void initialize()
+            throws Exception
+        {
+            builder = descriptor.metaInfo( MigrationBuilder.class );
+
+            String version = app.version();
+            String lastVersion = config.get().lastStartupVersion().get();
+
+            // Run general rules if version has changed
+            if( !app.version().equals( lastVersion ) )
+            {
+                Iterable<MigrationRule> rules = builder.migrationRules().rulesBetweenVersions( lastVersion, version );
+                List<MigrationRule> executedRules = new ArrayList<>();
+                try
+                {
+                    if( rules != null )
+                    {
+                        for( MigrationRule rule : rules )
+                        {
+                            rule.upgrade( store, this );
+                            executedRules.add( rule );
+                            LOGGER.debug( rule.toString() );
+                        }
+
+                        LOGGER.info( "Migrated to " + version );
+                    }
+
+                    config.get().lastStartupVersion().set( version );
+                    config.save();
+                }
+                catch( Exception e )
+                {
+                    LOGGER.error( "Upgrade failed", e );
+
+                    // Downgrade the migrated rules
+                    for( MigrationRule executedRule : executedRules )
+                    {
+                        executedRule.downgrade( store, this );
+                    }
+                }
+            }
+        }
+
+        @Override
+        public JsonObject migrate( final JsonObject state, String toVersion, StateStore stateStore )
+            throws JsonException
+        {
+            // Get current version
+            String fromVersion = state.getString( JSONKeys.APPLICATION_VERSION, "0.0" );
+
+            Iterable<EntityMigrationRule> matchedRules = builder.entityMigrationRules()
+                                                                .rulesBetweenVersions( fromVersion, toVersion );
+
+            JsonObject migratedState = state;
+            boolean changed = false;
+            List<String> failures = new ArrayList<>();
+            if( matchedRules != null )
+            {
+                for( EntityMigrationRule matchedRule : matchedRules )
+                {
+                    MigrationContext context = new MigrationContext();
+
+                    migratedState = matchedRule.upgrade( context, migratedState, stateStore, migrator );
+
+                    if( context.isSuccess() && context.hasChanged() && LOGGER.isDebugEnabled() )
+                    {
+                        LOGGER.debug( matchedRule.toString() );
+                    }
+
+                    failures.addAll( context.failures() );
+                    changed = context.hasChanged() || changed;
+                }
+            }
+
+            JsonObjectBuilder appVersionBuilder = jsonFactories.builderFactory().createObjectBuilder();
+            for( Map.Entry<String, JsonValue> entry : migratedState.entrySet() )
+            {
+                appVersionBuilder.add( entry.getKey(), entry.getValue() );
+            }
+            appVersionBuilder.add( JSONKeys.APPLICATION_VERSION, toVersion );
+            migratedState = appVersionBuilder.build();
+
+            if( failures.size() > 0 )
+            {
+                LOGGER.warn( "Migration of {} from {} to {} aborted, failed operation(s):\n{}",
+                             state.getString( JSONKeys.IDENTITY ), fromVersion, toVersion,
+                             String.join( "\n\t", failures ) );
+                return state;
+            }
+
+            if( changed )
+            {
+                LOGGER.info( "Migrated {} from {} to {}",
+                             migratedState.getString( JSONKeys.IDENTITY ), fromVersion, toVersion );
+                return migratedState;
+            }
+
+            // Nothing done
+            return state;
+        }
+
+        // Migrator implementation
+        @Override
+        public JsonObject addProperty( MigrationContext context, JsonObject state, String name, Object defaultValue )
+            throws JsonException
+        {
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( !valueState.containsKey( name ) )
+            {
+                valueState = jsonFactories.cloneBuilder( valueState )
+                                          .add( name, serialization.toJson( defaultValue ) )
+                                          .build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
+
+                for( MigrationEvents migrationEvent : migrationEvents )
+                {
+                    migrationEvent.propertyAdded( state.getString( JSONKeys.IDENTITY ), name, defaultValue );
+                }
+
+                return migratedState;
+            }
+            else
+            {
+                context.addFailure( "Add property " + name + ", default:" + defaultValue );
+                return state;
+            }
+        }
+
+        @Override
+        public JsonObject removeProperty( MigrationContext context, JsonObject state, String name )
+            throws JsonException
+        {
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( valueState.containsKey( name ) )
+            {
+                valueState = jsonFactories.cloneBuilderExclude( valueState, name ).build();
+                JsonObject migratedState = jsonFactories
+                    .cloneBuilderExclude( state, JSONKeys.VALUE )
+                    .add( JSONKeys.VALUE, valueState )
+                    .build();
+                context.markAsChanged();
+                for( MigrationEvents migrationEvent : migrationEvents )
+                {
+                    migrationEvent.propertyRemoved( state.getString( JSONKeys.IDENTITY ), name );
+                }
+                return migratedState;
+            }
+            else
+            {
+                context.addFailure( "Remove property " + name );
+                return state;
+            }
+        }
+
+        @Override
+        public JsonObject renameProperty( MigrationContext context, JsonObject state, String from, String to )
+            throws JsonException
+        {
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( valueState.containsKey( from ) )
+            {
+                JsonValue jsonValue = valueState.get( from );
+                valueState = jsonFactories.cloneBuilderExclude( valueState, from )
+                                          .add( to, jsonValue )
+                                          .build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
+                for( MigrationEvents migrationEvent : migrationEvents )
+                {
+                    migrationEvent.propertyRenamed( state.getString( JSONKeys.IDENTITY ), from, to );
+                }
+                return migratedState;
+            }
+            else
+            {
+                context.addFailure( "Rename property " + from + " to " + to );
+                return state;
+            }
+        }
+
+        @Override
+        public JsonObject addAssociation( MigrationContext context, JsonObject state, String name,
+                                          String defaultReference )
+            throws JsonException
+        {
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( !valueState.containsKey( name ) )
+            {
+                valueState = jsonFactories.cloneBuilder( valueState )
+                                          .add( name, defaultReference )
+                                          .build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
+                for( MigrationEvents migrationEvent : migrationEvents )
+                {
+                    migrationEvent.associationAdded( state.getString( JSONKeys.IDENTITY ), name, defaultReference );
+                }
+                return migratedState;
+            }
+            else
+            {
+                context.addFailure( "Add association " + name + ", default:" + defaultReference );
+                return state;
+            }
+        }
+
+        @Override
+        public JsonObject removeAssociation( MigrationContext context, JsonObject state, String name )
+            throws JsonException
+        {
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( valueState.containsKey( name ) )
+            {
+                valueState = jsonFactories.cloneBuilderExclude( valueState, name ).build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
+                for( MigrationEvents migrationEvent : migrationEvents )
+                {
+                    migrationEvent.associationRemoved( state.getString( JSONKeys.IDENTITY ), name );
+                }
+                return migratedState;
+            }
+            else
+            {
+                context.addFailure( "Remove association " + name );
+                return state;
+            }
+        }
+
+        @Override
+        public JsonObject renameAssociation( MigrationContext context, JsonObject state, String from, String to )
+            throws JsonException
+        {
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( valueState.containsKey( from ) )
+            {
+                JsonValue jsonValue = valueState.get( from );
+                valueState = jsonFactories.cloneBuilderExclude( valueState, from )
+                                          .add( to, jsonValue )
+                                          .build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
+                for( MigrationEvents migrationEvent : migrationEvents )
+                {
+                    migrationEvent.associationRenamed( state.getString( JSONKeys.IDENTITY ), from, to );
+                }
+                return migratedState;
+            }
+            else
+            {
+                context.addFailure( "Rename association " + from + " to " + to );
+                return state;
+            }
+        }
+
+        @Override
+        public JsonObject addManyAssociation( MigrationContext context, JsonObject state, String name,
+                                              String... defaultReferences )
+            throws JsonException
+        {
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( !valueState.containsKey( name ) )
+            {
+                JsonArrayBuilder refArrayBuilder = jsonFactories.builderFactory().createArrayBuilder();
+                for( String ref : defaultReferences )
+                {
+                    refArrayBuilder.add( ref );
+                }
+                valueState = jsonFactories.cloneBuilder( valueState )
+                                          .add( name, refArrayBuilder.build() )
+                                          .build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
+                for( MigrationEvents migrationEvent : migrationEvents )
+                {
+                    migrationEvent.manyAssociationAdded( state.getString( JSONKeys.IDENTITY ), name,
+                                                         defaultReferences );
+                }
+                return migratedState;
+            }
+            else
+            {
+                context.addFailure( "Add many-association " + name + ", default:" + asList( defaultReferences ) );
+                return state;
+            }
+        }
+
+        @Override
+        public JsonObject removeManyAssociation( MigrationContext context, JsonObject state, String name )
+            throws JsonException
+        {
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( valueState.containsKey( name ) )
+            {
+                valueState = jsonFactories.cloneBuilderExclude( valueState, name ).build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
+                for( MigrationEvents migrationEvent : migrationEvents )
+                {
+                    migrationEvent.manyAssociationRemoved( state.getString( JSONKeys.IDENTITY ), name );
+                }
+                return migratedState;
+            }
+            else
+            {
+                context.addFailure( "Remove many-association " + name );
+                return state;
+            }
+        }
+
+        @Override
+        public JsonObject renameManyAssociation( MigrationContext context, JsonObject state, String from, String to )
+            throws JsonException
+        {
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( valueState.containsKey( from ) )
+            {
+                JsonValue jsonValue = valueState.get( from );
+                valueState = jsonFactories.cloneBuilderExclude( valueState, from )
+                                          .add( to, jsonValue )
+                                          .build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
+                for( MigrationEvents migrationEvent : migrationEvents )
+                {
+                    migrationEvent.manyAssociationRenamed( state.getString( JSONKeys.IDENTITY ), from, to );
+                }
+                return migratedState;
+            }
+            else
+            {
+                context.addFailure( "Rename many-association " + from + " to " + to );
+                return state;
+            }
+        }
+
+        @Override
+        public JsonObject addNamedAssociation( MigrationContext context, JsonObject state, String name,
+                                               Map<String, String> defaultReferences )
+            throws JsonException
+        {
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( !valueState.containsKey( name ) )
+            {
+                JsonObjectBuilder refBuilder = jsonFactories.builderFactory().createObjectBuilder();
+                for( Map.Entry<String, String> entry : defaultReferences.entrySet() )
+                {
+                    refBuilder.add( entry.getKey(), entry.getValue() );
+                }
+                valueState = jsonFactories.cloneBuilder( valueState )
+                                          .add( name, refBuilder.build() )
+                                          .build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
+                for( MigrationEvents migrationEvent : migrationEvents )
+                {
+                    migrationEvent.namedAssociationAdded( state.getString( JSONKeys.IDENTITY ), name,
+                                                          defaultReferences );
+                }
+                return migratedState;
+            }
+            else
+            {
+                context.addFailure( "Add named-association " + name + ", default:" + defaultReferences );
+                return state;
+            }
+        }
+
+        @Override
+        public JsonObject removeNamedAssociation( MigrationContext context, JsonObject state, String name )
+            throws JsonException
+        {
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( !valueState.containsKey( name ) )
+            {
+                valueState = jsonFactories.cloneBuilderExclude( valueState, name ).build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
+                for( MigrationEvents migrationEvent : migrationEvents )
+                {
+                    migrationEvent.namedAssociationRemoved( state.getString( JSONKeys.IDENTITY ), name );
+                }
+                return migratedState;
+            }
+            else
+            {
+                context.addFailure( "Remove named-association " + name );
+                return state;
+            }
+        }
+
+        @Override
+        public JsonObject renameNamedAssociation( MigrationContext context, JsonObject state, String from, String to )
+            throws JsonException
+        {
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( valueState.containsKey( from ) )
+            {
+                JsonValue jsonValue = valueState.get( from );
+                valueState = jsonFactories.cloneBuilderExclude( valueState, from )
+                                          .add( to, jsonValue )
+                                          .build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
+                for( MigrationEvents migrationEvent : migrationEvents )
+                {
+                    migrationEvent.namedAssociationRenamed( state.getString( JSONKeys.IDENTITY ), from, to );
+                }
+                return migratedState;
+            }
+            else
+            {
+                context.addFailure( "Rename named-association " + from + " to " + to );
+                return state;
+            }
+        }
+
+        @Override
+        public JsonObject changeEntityType( MigrationContext context, JsonObject state,
+                                            String fromType, String toType )
+            throws JsonException
+        {
+            String currentType = state.getString( JSONKeys.TYPE );
+            if( fromType.equals( currentType ) )
+            {
+                JsonObject migratedState = jsonFactories.cloneBuilder( state )
+                                                        .add( JSONKeys.TYPE, toType )
+                                                        .build();
+                for( MigrationEvents migrationEvent : migrationEvents )
+                {
+                    migrationEvent.entityTypeChanged( state.getString( JSONKeys.IDENTITY ), toType );
+                }
+                return migratedState;
+            }
+            else
+            {
+                context.addFailure( "Change entity type from " + fromType + " to " + toType );
+                return state;
+            }
+        }
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/Migrator.java b/extensions/migration/src/main/java/org/apache/polygene/migration/Migrator.java
new file mode 100644
index 0000000..a09b891
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/Migrator.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.migration;
+
+import java.util.Map;
+import javax.json.JsonObject;
+import org.apache.polygene.migration.assembly.MigrationContext;
+
+/**
+ * The Migrator implements this interface, which is invoked by MigrationOperation implementations
+ * to perform changes to EntityState during a version migration.
+ */
+public interface Migrator
+{
+    JsonObject addProperty( MigrationContext content, JsonObject state,
+                            String name, Object defaultValue );
+
+    JsonObject removeProperty( MigrationContext content, JsonObject state,
+                               String name );
+
+    JsonObject renameProperty( MigrationContext content, JsonObject state,
+                               String from, String to );
+
+    JsonObject addAssociation( MigrationContext content, JsonObject state,
+                               String name, String defaultReference );
+
+    JsonObject removeAssociation( MigrationContext content, JsonObject state,
+                                  String name );
+
+    JsonObject renameAssociation( MigrationContext content, JsonObject state,
+                                  String from, String to );
+
+    JsonObject addManyAssociation( MigrationContext content, JsonObject state,
+                                   String name, String... defaultReferences );
+
+    JsonObject removeManyAssociation( MigrationContext content, JsonObject state,
+                                      String name );
+
+    JsonObject renameManyAssociation( MigrationContext content, JsonObject state,
+                                      String from, String to );
+
+    JsonObject addNamedAssociation( MigrationContext content, JsonObject state,
+                                    String name, Map<String, String> defaultReferences );
+
+    JsonObject removeNamedAssociation( MigrationContext content, JsonObject state,
+                                       String name );
+
+    JsonObject renameNamedAssociation( MigrationContext content, JsonObject state,
+                                       String from, String to );
+
+    JsonObject changeEntityType( MigrationContext content, JsonObject state,
+                                 String fromType, String toType );
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/AbstractMigrationRule.java b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/AbstractMigrationRule.java
new file mode 100644
index 0000000..df5e929
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/AbstractMigrationRule.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.polygene.migration.assembly;
+
+/**
+ * Base class for migration rules.
+ */
+public class AbstractMigrationRule
+{
+    protected String fromVersion;
+    protected String toVersion;
+
+    public AbstractMigrationRule( String fromVersion, String toVersion )
+    {
+        this.fromVersion = fromVersion;
+        this.toVersion = toVersion;
+    }
+
+    public String fromVersion()
+    {
+        return fromVersion;
+    }
+
+    public String toVersion()
+    {
+        return toVersion;
+    }
+
+    @Override
+    public String toString()
+    {
+        return fromVersion + "=>" + toVersion + ": " + getClass();
+    }
+}
\ No newline at end of file
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationBuilder.java b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationBuilder.java
new file mode 100644
index 0000000..b4e610c
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationBuilder.java
@@ -0,0 +1,306 @@
+/*
+ *  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.polygene.migration.assembly;
+
+import java.util.Map;
+import org.apache.polygene.migration.operation.AddAssociation;
+import org.apache.polygene.migration.operation.AddManyAssociation;
+import org.apache.polygene.migration.operation.AddNamedAssociation;
+import org.apache.polygene.migration.operation.AddProperty;
+import org.apache.polygene.migration.operation.RemoveAssociation;
+import org.apache.polygene.migration.operation.RemoveManyAssociation;
+import org.apache.polygene.migration.operation.RemoveNamedAssociation;
+import org.apache.polygene.migration.operation.RemoveProperty;
+import org.apache.polygene.migration.operation.RenameAssociation;
+import org.apache.polygene.migration.operation.RenameManyAssociation;
+import org.apache.polygene.migration.operation.RenameNamedAssociation;
+import org.apache.polygene.migration.operation.RenameProperty;
+
+/**
+ * Fluent API for creating migration rules for specific entity types.
+ */
+public class EntityMigrationBuilder
+{
+    private final VersionMigrationBuilder migrationBuilder;
+    private final String[] entityTypes;
+
+    public EntityMigrationBuilder( VersionMigrationBuilder migrationBuilder, String[] entityTypes )
+    {
+        this.migrationBuilder = migrationBuilder;
+        this.entityTypes = entityTypes;
+    }
+
+    /**
+     * Return the version builder
+     *
+     * @return current version builder
+     */
+    public VersionMigrationBuilder end()
+    {
+        return migrationBuilder;
+    }
+
+    // Operations on entities
+    /**
+     * Add rule to rename an Entity property.
+     *
+     * @param from property name
+     * @param to   property name
+     *
+     * @return the builder
+     */
+    public EntityMigrationBuilder renameProperty( String from, String to )
+    {
+        migrationBuilder.builder.entityMigrationRules().
+            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
+                                              migrationBuilder.toVersion,
+                                              entityTypes,
+                                              new RenameProperty( from, to ) ) );
+
+        return this;
+    }
+
+    /**
+     * Add rule to add an Entity property.
+     *
+     * @param property     to be added
+     * @param defaultValue default value
+     *
+     * @return the builder
+     */
+    public EntityMigrationBuilder addProperty( String property, Object defaultValue )
+    {
+        migrationBuilder.builder.entityMigrationRules().
+            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
+                                              migrationBuilder.toVersion,
+                                              entityTypes,
+                                              new AddProperty( property, defaultValue ) ) );
+
+        return this;
+    }
+
+    /**
+     * Add rule to remove an Entity property
+     *
+     * @param property     to be removed
+     * @param defaultValue default value (used for downgrading)
+     *
+     * @return the builder
+     */
+    public EntityMigrationBuilder removeProperty( String property, String defaultValue )
+    {
+        migrationBuilder.builder.entityMigrationRules().
+            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
+                                              migrationBuilder.toVersion,
+                                              entityTypes,
+                                              new RemoveProperty( property, defaultValue ) ) );
+
+        return this;
+    }
+
+    /**
+     * Add rule to rename an Entity association.
+     *
+     * @param from assocation name
+     * @param to   association name
+     *
+     * @return the builder
+     */
+    public EntityMigrationBuilder renameAssociation( String from, String to )
+    {
+        migrationBuilder.builder.entityMigrationRules().
+            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
+                                              migrationBuilder.toVersion,
+                                              entityTypes,
+                                              new RenameAssociation( from, to ) ) );
+
+        return this;
+    }
+
+    /**
+     * Add rule to add an Entity association.
+     *
+     * @param association      to be added
+     * @param defaultReference default reference
+     *
+     * @return the builder
+     */
+    public EntityMigrationBuilder addAssociation( String association, String defaultReference )
+    {
+        migrationBuilder.builder.entityMigrationRules().
+            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
+                                              migrationBuilder.toVersion,
+                                              entityTypes,
+                                              new AddAssociation( association, defaultReference ) ) );
+
+        return this;
+    }
+
+    /**
+     * Add rule to remove an Entity association
+     *
+     * @param association      to be removed
+     * @param defaultReference default value (used for downgrading)
+     *
+     * @return the builder
+     */
+    public EntityMigrationBuilder removeAssociation( String association, String defaultReference )
+    {
+        migrationBuilder.builder.entityMigrationRules().
+            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
+                                              migrationBuilder.toVersion,
+                                              entityTypes,
+                                              new RemoveAssociation( association, defaultReference ) ) );
+
+        return this;
+    }
+
+    /**
+     * Add rule to add an Entity many-association.
+     *
+     * @param association       to be added
+     * @param defaultReferences default references
+     *
+     * @return the builder
+     */
+    public EntityMigrationBuilder addManyAssociation( String association, String... defaultReferences )
+    {
+        migrationBuilder.builder.entityMigrationRules().
+            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
+                                              migrationBuilder.toVersion,
+                                              entityTypes,
+                                              new AddManyAssociation( association, defaultReferences ) ) );
+
+        return this;
+    }
+
+    /**
+     * Add rule to remove an Entity many-association
+     *
+     * @param association       to be removed
+     * @param defaultReferences default value (used for downgrading)
+     *
+     * @return the builder
+     */
+    public EntityMigrationBuilder removeManyAssociation( String association, String... defaultReferences )
+    {
+        migrationBuilder.builder.entityMigrationRules().
+            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
+                                              migrationBuilder.toVersion,
+                                              entityTypes,
+                                              new RemoveManyAssociation( association, defaultReferences ) ) );
+
+        return this;
+    }
+
+    /**
+     * Add rule to rename an Entity many-association.
+     *
+     * @param from many-assocation name
+     * @param to   many-association name
+     *
+     * @return the builder
+     */
+    public EntityMigrationBuilder renameManyAssociation( String from, String to )
+    {
+        migrationBuilder.builder.entityMigrationRules().
+            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
+                                              migrationBuilder.toVersion,
+                                              entityTypes,
+                                              new RenameManyAssociation( from, to ) ) );
+
+        return this;
+    }
+
+    /**
+     * Add rule to add an Entity named-association.
+     *
+     * @param association       to be added
+     * @param defaultReferences default references
+     *
+     * @return the builder
+     */
+    public EntityMigrationBuilder addNamedAssociation( String association, Map<String, String> defaultReferences )
+    {
+        migrationBuilder.builder.entityMigrationRules().
+            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
+                                              migrationBuilder.toVersion,
+                                              entityTypes,
+                                              new AddNamedAssociation( association, defaultReferences ) ) );
+
+        return this;
+    }
+
+    /**
+     * Add rule to remove an Entity named-association
+     *
+     * @param association       to be removed
+     * @param defaultReferences default value (used for downgrading)
+     *
+     * @return the builder
+     */
+    public EntityMigrationBuilder removeNamedAssociation( String association, Map<String, String> defaultReferences )
+    {
+        migrationBuilder.builder.entityMigrationRules().
+            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
+                                              migrationBuilder.toVersion,
+                                              entityTypes,
+                                              new RemoveNamedAssociation( association, defaultReferences ) ) );
+
+        return this;
+    }
+
+    /**
+     * Add rule to rename an Entity named-association.
+     *
+     * @param from many-assocation name
+     * @param to   many-association name
+     *
+     * @return the builder
+     */
+    public EntityMigrationBuilder renameNamedAssociation( String from, String to )
+    {
+        migrationBuilder.builder.entityMigrationRules().
+            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
+                                              migrationBuilder.toVersion,
+                                              entityTypes,
+                                              new RenameNamedAssociation( from, to ) ) );
+
+        return this;
+    }
+
+    /**
+     * Add rule to perform a custom operation
+     *
+     * @param operationEntity the custom operation to be performed during migration
+     *
+     * @return the builder
+     */
+    public EntityMigrationBuilder custom( EntityMigrationOperation operationEntity )
+    {
+        migrationBuilder.builder.entityMigrationRules().
+            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
+                                              migrationBuilder.toVersion,
+                                              entityTypes,
+                                              operationEntity ) );
+
+        return this;
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationOperation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationOperation.java
new file mode 100644
index 0000000..a5b5741
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationOperation.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.migration.assembly;
+
+import javax.json.JsonException;
+import javax.json.JsonObject;
+import org.apache.polygene.migration.Migrator;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * Migration operation for a specific entity.
+ */
+public interface EntityMigrationOperation
+{
+    JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+        throws JsonException;
+
+    JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+        throws JsonException;
+}
\ No newline at end of file
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationRule.java b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationRule.java
new file mode 100644
index 0000000..291ae0d
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationRule.java
@@ -0,0 +1,96 @@
+/*
+ *  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.polygene.migration.assembly;
+
+import java.util.Arrays;
+import javax.json.JsonObject;
+import org.apache.polygene.migration.Migrator;
+import org.apache.polygene.spi.entitystore.helpers.JSONKeys;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * Migration rule for a specific set of entity types
+ */
+public class EntityMigrationRule
+    extends AbstractMigrationRule
+{
+    private final String[] entityTypes;
+    private final EntityMigrationOperation entityOperation;
+
+    public EntityMigrationRule( String fromVersion,
+                                String toVersion,
+                                String[] entityTypes,
+                                EntityMigrationOperation entityOperation
+    )
+    {
+        super( fromVersion, toVersion );
+        this.entityTypes = entityTypes;
+        this.entityOperation = entityOperation;
+    }
+
+    public String[] entityTypes()
+    {
+        return entityTypes;
+    }
+
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        if( appliesTo( state.getString( JSONKeys.TYPE ) ) )
+        {
+            return entityOperation.upgrade( context, state, stateStore, migrator );
+        }
+        else
+        {
+            context.addFailure( entityOperation.toString() );
+            return state;
+        }
+    }
+
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        if( appliesTo( state.getString( JSONKeys.TYPE ) ) )
+        {
+            return entityOperation.downgrade( context, state, stateStore, migrator );
+        }
+        else
+        {
+            context.addFailure( entityOperation.toString() );
+            return state;
+        }
+    }
+
+    public boolean appliesTo( String entityType )
+    {
+        for( String type : entityTypes )
+        {
+            if( entityType.equals( type ) )
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString()
+    {
+        return fromVersion + "=>" + toVersion + ": on " + Arrays.asList( entityTypes ) + " do " + entityOperation;
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationBuilder.java b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationBuilder.java
new file mode 100644
index 0000000..1b02746
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationBuilder.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.migration.assembly;
+
+/**
+ * Builder for set of migration rules. This needs to be passed in as metadata to the MigrationService.
+ */
+public class MigrationBuilder
+{
+    private MigrationRules<EntityMigrationRule> entityRules;
+    private MigrationRules<MigrationRule> rules;
+
+    private String fromVersion;
+
+    public MigrationBuilder( String fromVersion )
+    {
+        this.entityRules = new MigrationRules<>();
+        this.rules = new MigrationRules<>();
+        this.fromVersion = fromVersion;
+    }
+
+    public VersionMigrationBuilder toVersion( String toVersion )
+    {
+        return new VersionMigrationBuilder( this, fromVersion, toVersion );
+    }
+
+    public MigrationRules<EntityMigrationRule> entityMigrationRules()
+    {
+        return entityRules;
+    }
+
+    public MigrationRules<MigrationRule> migrationRules()
+    {
+        return rules;
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationContext.java b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationContext.java
new file mode 100644
index 0000000..8ee057f
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationContext.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.migration.assembly;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class MigrationContext
+{
+    private boolean changed;
+    private final List<String> failures = new ArrayList<>();
+
+    public boolean hasChanged()
+    {
+        return changed;
+    }
+
+    public void markAsChanged()
+    {
+        changed = true;
+    }
+
+    public boolean isSuccess()
+    {
+        return failures.isEmpty();
+    }
+
+    public boolean hasFailures()
+    {
+        return failures.size() > 0;
+    }
+
+    public List<String> failures()
+    {
+        return Collections.unmodifiableList( failures );
+    }
+
+    public void addFailure( String operation )
+    {
+        failures.add( operation );
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationOperation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationOperation.java
new file mode 100644
index 0000000..939e517
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationOperation.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.migration.assembly;
+
+import java.io.IOException;
+import org.apache.polygene.migration.Migrator;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * Non-entity specific migration operation. These operations
+ * may perform anything necessary to migrate the application. This
+ * could include performing disk operations and other non-entity related
+ * tasks.
+ */
+public interface MigrationOperation
+{
+    void upgrade( StateStore stateStore, Migrator migrator )
+        throws IOException;
+
+    void downgrade( StateStore stateStore, Migrator migrator )
+        throws IOException;
+}
\ No newline at end of file
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationRule.java b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationRule.java
new file mode 100644
index 0000000..7064195
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationRule.java
@@ -0,0 +1,58 @@
+/*
+ *  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.polygene.migration.assembly;
+
+import java.io.IOException;
+import org.apache.polygene.migration.Migrator;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * Migration rule that does not apply to a specific entity type
+ */
+public class MigrationRule
+    extends AbstractMigrationRule
+{
+    private MigrationOperation operation;
+
+    public MigrationRule( String fromVersion, String toVersion, MigrationOperation operation )
+    {
+        super( fromVersion, toVersion );
+        this.operation = operation;
+    }
+
+    public void upgrade( StateStore stateStore, Migrator migrator )
+        throws IOException
+    {
+        operation.upgrade( stateStore, migrator );
+    }
+
+    public void downgrade( StateStore stateStore, Migrator migrator )
+        throws IOException
+    {
+        operation.downgrade( stateStore, migrator );
+    }
+
+    @Override
+    public String toString()
+    {
+        return fromVersion + "->" + toVersion + ":" + operation;
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationRules.java b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationRules.java
new file mode 100644
index 0000000..0109388
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationRules.java
@@ -0,0 +1,124 @@
+/*
+ *  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.polygene.migration.assembly;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.polygene.migration.util.ListMap;
+
+/**
+ * Set of migration rules.
+ */
+public class MigrationRules<T extends AbstractMigrationRule>
+{
+    // to-version -> List of from-versions
+    private ListMap<String, String> versionChanges = new ListMap<>();
+
+    // key=fromversion->toversion value=list of rules for that transition
+    private ListMap<String, T> rules = new ListMap<>();
+
+    public void addRule( T migrationRule )
+    {
+        versionChanges.add( migrationRule.toVersion(), migrationRule.fromVersion() );
+        rules.add( migrationRule.fromVersion() + "->" + migrationRule.toVersion(), migrationRule );
+    }
+
+    public Iterable<T> rulesBetweenVersions( String fromVersion, String toVersion )
+    {
+        try
+        {
+            String ruleToVersion = findHighestToVersion( toVersion );
+
+            return migrationRules( fromVersion, ruleToVersion );
+        }
+        catch( IllegalArgumentException e )
+        {
+            return null;
+        }
+    }
+
+    private List<T> migrationRules( String fromVersion, String toVersion )
+    {
+        List<String> list = versionChanges.get( toVersion );
+
+        if( list == null )
+        {
+            return null; // No possible rules for this transition
+        }
+
+        for( String possibleFromVersion : list )
+        {
+            if( fromVersion.equals( possibleFromVersion ) )
+            {
+                // We found the end of the version transitions - return rules, but filter on entity type
+                return new ArrayList<>( getRulesForTransition( fromVersion, toVersion ) );
+            }
+            else
+            {
+                List<T> migrationRules = migrationRules( fromVersion, possibleFromVersion );
+                if( migrationRules == null )
+                {
+                    continue; // Wrong transition - try another one
+                }
+
+                // Add entity-filtered rules from this part of the version transition
+                migrationRules.addAll( getRulesForTransition( possibleFromVersion, toVersion ) );
+                return migrationRules;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Find highest version below the given to-version for which there are rules registered.
+     *
+     * @param toVersion The ending toVersion in the search.
+     *
+     * @return The highest version below the given version for which there are rules registered.
+     */
+    private String findHighestToVersion( String toVersion )
+    {
+        if( versionChanges.get( toVersion ) == null )
+        {
+            List<String> toVersions = new ArrayList<>(versionChanges.keySet());
+            toVersions.sort(Collections.reverseOrder());
+            for( String version : toVersions )
+            {
+                if( version.compareTo( toVersion ) <= 0 )
+                {
+                    // Found version to change to
+                    return version;
+                }
+            }
+            throw new IllegalArgumentException( "No version found in rules that matches the given to-version:" + toVersion );
+        }
+        else
+        {
+            return toVersion;
+        }
+    }
+
+    private List<T> getRulesForTransition( String fromVersion, String toVersion )
+    {
+        return rules.get( fromVersion + "->" + toVersion );
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/PackageMigrationBuilder.java b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/PackageMigrationBuilder.java
new file mode 100644
index 0000000..3872fe1
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/PackageMigrationBuilder.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.migration.assembly;
+
+import org.apache.polygene.migration.operation.RenameEntity;
+
+/**
+ * JAVADOC
+ */
+public class PackageMigrationBuilder
+{
+    private MigrationBuilder builder;
+    private VersionMigrationBuilder version;
+    private String fromVersion;
+    private String toVersion;
+    private String fromName;
+    private String toName;
+
+    public PackageMigrationBuilder( MigrationBuilder builder,
+                                    VersionMigrationBuilder version,
+                                    String fromVersion,
+                                    String toVersion,
+                                    String fromName,
+                                    String toName
+    )
+    {
+        this.builder = builder;
+        this.version = version;
+        this.fromVersion = fromVersion;
+        this.toVersion = toVersion;
+        this.fromName = fromName;
+        this.toName = toName;
+    }
+
+    public VersionMigrationBuilder end()
+    {
+        return version;
+    }
+
+    public PackageMigrationBuilder withEntities( String... entitySimpleNames )
+    {
+        for( String entitySimpleName : entitySimpleNames )
+        {
+            builder.entityMigrationRules().addRule( new EntityMigrationRule(
+                fromVersion,
+                toVersion,
+                new String[]{ fromName + "." + entitySimpleName },
+                new RenameEntity( fromName + "." + entitySimpleName, toName + "." + entitySimpleName ) ) );
+        }
+
+        return this;
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/VersionMigrationBuilder.java b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/VersionMigrationBuilder.java
new file mode 100644
index 0000000..b5f288e
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/VersionMigrationBuilder.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.migration.assembly;
+
+import org.apache.polygene.migration.operation.RenameEntity;
+
+/**
+ * Migration builder for a specific to-version.
+ */
+public class VersionMigrationBuilder
+{
+    MigrationBuilder builder;
+
+    String fromVersion;
+    String toVersion;
+
+    public VersionMigrationBuilder( MigrationBuilder builder, String fromVersion, String toVersion )
+    {
+        this.builder = builder;
+        this.fromVersion = fromVersion;
+        this.toVersion = toVersion;
+    }
+
+    public VersionMigrationBuilder toVersion( String toVersion )
+    {
+        return new VersionMigrationBuilder( builder, this.toVersion, toVersion );
+    }
+
+    public VersionMigrationBuilder renameEntity( String fromName, String toName )
+    {
+        builder.entityMigrationRules()
+            .addRule( new EntityMigrationRule( fromVersion, toVersion, new String[]{ fromName }, new RenameEntity( fromName, toName ) ) );
+
+        return this;
+    }
+
+    public PackageMigrationBuilder renamePackage( String fromName, String toName )
+    {
+        return new PackageMigrationBuilder( builder, this, fromVersion, toVersion, fromName, toName );
+    }
+
+    public VersionMigrationBuilder atStartup( MigrationOperation operation )
+    {
+        builder.migrationRules().addRule( new MigrationRule( fromVersion, toVersion, operation ) );
+
+        return this;
+    }
+
+    public EntityMigrationBuilder forEntities( String... entityTypes )
+    {
+        return new EntityMigrationBuilder( this, entityTypes );
+    }
+}
\ No newline at end of file
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/package.html b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/package.html
new file mode 100644
index 0000000..8280280
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Entities Migration Assembly.</h2>
+    </body>
+</html>
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddAssociation.java
new file mode 100644
index 0000000..471843b
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddAssociation.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.migration.operation;
+
+import javax.json.JsonObject;
+import org.apache.polygene.migration.assembly.MigrationContext;
+import org.apache.polygene.migration.Migrator;
+import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * Add an association
+ */
+public class AddAssociation
+    implements EntityMigrationOperation
+{
+    private String association;
+    private String defaultValue;
+
+    public AddAssociation( String association, String defaultReference )
+    {
+        this.association = association;
+        this.defaultValue = defaultReference;
+    }
+
+    @Override
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.addAssociation( context, state, association, defaultValue );
+    }
+
+    @Override
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.removeAssociation( context, state, association );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Add association " + association + ", default:" + defaultValue;
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddManyAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddManyAssociation.java
new file mode 100644
index 0000000..82610fe
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddManyAssociation.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.migration.operation;
+
+import java.util.Arrays;
+import javax.json.JsonObject;
+import org.apache.polygene.migration.assembly.MigrationContext;
+import org.apache.polygene.migration.Migrator;
+import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * Add a many-association
+ */
+public class AddManyAssociation
+    implements EntityMigrationOperation
+{
+    private String association;
+    private String[] defaultReferences;
+
+    public AddManyAssociation( String association, String... defaultReferences )
+    {
+        this.association = association;
+        this.defaultReferences = defaultReferences;
+    }
+
+    @Override
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.addManyAssociation( context, state, association, defaultReferences );
+    }
+
+    @Override
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.removeManyAssociation( context, state, association );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Add many-association " + association + ", default:" + Arrays.asList( defaultReferences );
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddNamedAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddNamedAssociation.java
new file mode 100644
index 0000000..90725e8
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddNamedAssociation.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.migration.operation;
+
+import java.util.Map;
+import javax.json.JsonObject;
+import org.apache.polygene.migration.assembly.MigrationContext;
+import org.apache.polygene.migration.Migrator;
+import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * Add a named-association
+ */
+public class AddNamedAssociation
+    implements EntityMigrationOperation
+{
+    private final String association;
+    private final Map<String, String> defaultReferences;
+
+    public AddNamedAssociation( String association, Map<String, String> defaultReferences )
+    {
+        this.association = association;
+        this.defaultReferences = defaultReferences;
+    }
+
+    @Override
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.addNamedAssociation( context, state, association, defaultReferences );
+    }
+
+    @Override
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.removeNamedAssociation( context, state, association );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Add named-association " + association + ", default:" + defaultReferences;
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddProperty.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddProperty.java
new file mode 100644
index 0000000..8f8898a
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddProperty.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.migration.operation;
+
+import javax.json.JsonObject;
+import org.apache.polygene.migration.assembly.MigrationContext;
+import org.apache.polygene.migration.Migrator;
+import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * Add a property
+ */
+public class AddProperty
+    implements EntityMigrationOperation
+{
+    private String property;
+    private Object defaultValue;
+
+    public AddProperty( String property, Object defaultValue )
+    {
+        this.property = property;
+        this.defaultValue = defaultValue;
+    }
+
+    @Override
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.addProperty( context, state, property, defaultValue );
+    }
+
+    @Override
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.removeProperty( context, state, property );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Add property " + property + ", default:" + defaultValue;
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveAssociation.java
new file mode 100644
index 0000000..d1f8771
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveAssociation.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.migration.operation;
+
+import javax.json.JsonObject;
+import org.apache.polygene.migration.Migrator;
+import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.migration.assembly.MigrationContext;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * Remove an association. Downgrading this operation will reset
+ * the property to the default value.
+ */
+public class RemoveAssociation
+    implements EntityMigrationOperation
+{
+    private String association;
+    private String defaultValue;
+
+    public RemoveAssociation( String association, String defaultReference )
+    {
+        this.association = association;
+        this.defaultValue = defaultReference;
+    }
+
+    @Override
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.removeAssociation( context, state, association );
+    }
+
+    @Override
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.addAssociation( context, state, association, defaultValue );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Remove association " + association + ", default:" + defaultValue;
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveManyAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveManyAssociation.java
new file mode 100644
index 0000000..d063338
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveManyAssociation.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.migration.operation;
+
+import java.util.Arrays;
+import javax.json.JsonObject;
+import org.apache.polygene.migration.Migrator;
+import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.migration.assembly.MigrationContext;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * Add a many-association
+ */
+public class RemoveManyAssociation
+    implements EntityMigrationOperation
+{
+    private String association;
+    private String[] defaultReferences;
+
+    public RemoveManyAssociation( String association, String... defaultReferences )
+    {
+        this.association = association;
+        this.defaultReferences = defaultReferences;
+    }
+
+    @Override
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.removeManyAssociation( context, state, association );
+    }
+
+    @Override
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.addManyAssociation( context, state, association, defaultReferences );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Remove many-association " + association + ", default:" + Arrays.asList( defaultReferences );
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveNamedAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveNamedAssociation.java
new file mode 100644
index 0000000..f97dbea
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveNamedAssociation.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.migration.operation;
+
+import java.util.Map;
+import javax.json.JsonObject;
+import org.apache.polygene.migration.Migrator;
+import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.migration.assembly.MigrationContext;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * Add a named-association
+ */
+public class RemoveNamedAssociation
+    implements EntityMigrationOperation
+{
+    private final String association;
+    private final Map<String, String> defaultReferences;
+
+    public RemoveNamedAssociation( String association, Map<String, String> defaultReferences )
+    {
+        this.association = association;
+        this.defaultReferences = defaultReferences;
+    }
+
+    @Override
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.removeNamedAssociation( context, state, association );
+    }
+
+    @Override
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.addNamedAssociation( context, state, association, defaultReferences );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Remove named-association " + association + ", default:" + defaultReferences;
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveProperty.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveProperty.java
new file mode 100644
index 0000000..9ad8673
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveProperty.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.migration.operation;
+
+import javax.json.JsonObject;
+import org.apache.polygene.migration.assembly.MigrationContext;
+import org.apache.polygene.migration.Migrator;
+import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * Remove a property. Downgrading this operation will reset
+ * the property to the default value.
+ */
+public class RemoveProperty
+    implements EntityMigrationOperation
+{
+    private String property;
+    private String defaultValue;
+
+    public RemoveProperty( String property, String defaultValue )
+    {
+        this.property = property;
+        this.defaultValue = defaultValue;
+    }
+
+    @Override
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.removeProperty( context, state, property );
+    }
+
+    @Override
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.addProperty( context, state, property, defaultValue );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Remove property " + property + ", default:" + defaultValue;
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameAssociation.java
new file mode 100644
index 0000000..277de57
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameAssociation.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.migration.operation;
+
+import javax.json.JsonObject;
+import org.apache.polygene.migration.Migrator;
+import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.migration.assembly.MigrationContext;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * Rename an Association
+ */
+public class RenameAssociation
+    implements EntityMigrationOperation
+{
+    String from;
+    String to;
+
+    public RenameAssociation( String from, String to )
+    {
+        this.from = from;
+        this.to = to;
+    }
+
+    @Override
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.renameAssociation( context, state, from, to );
+    }
+
+    @Override
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.renameAssociation( context, state, to, from );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Rename association " + from + " to " + to;
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameEntity.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameEntity.java
new file mode 100644
index 0000000..716a6b1
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameEntity.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.migration.operation;
+
+import javax.json.JsonObject;
+import org.apache.polygene.migration.Migrator;
+import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.migration.assembly.MigrationContext;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * Rename an Entity type
+ */
+public class RenameEntity
+    implements EntityMigrationOperation
+{
+    String fromName;
+    String toName;
+
+    public RenameEntity( String fromName, String toName )
+    {
+        this.fromName = fromName;
+        this.toName = toName;
+    }
+
+    @Override
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.changeEntityType( context, state, fromName, toName );
+    }
+
+    @Override
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.changeEntityType( context, state, fromName, fromName );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Rename entity " + fromName + " to " + toName;
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameManyAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameManyAssociation.java
new file mode 100644
index 0000000..cfc12c5
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameManyAssociation.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.migration.operation;
+
+import javax.json.JsonObject;
+import org.apache.polygene.migration.Migrator;
+import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.migration.assembly.MigrationContext;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * Rename a ManyAssociation
+ */
+public class RenameManyAssociation
+    implements EntityMigrationOperation
+{
+    String from;
+    String to;
+
+    public RenameManyAssociation( String from, String to )
+    {
+        this.from = from;
+        this.to = to;
+    }
+
+    @Override
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.renameManyAssociation( context, state, from, to );
+    }
+
+    @Override
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.renameManyAssociation( context, state, to, from );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Rename many-association " + from + " to " + to;
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameNamedAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameNamedAssociation.java
new file mode 100644
index 0000000..05fb92a
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameNamedAssociation.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.migration.operation;
+
+import javax.json.JsonObject;
+import org.apache.polygene.migration.Migrator;
+import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.migration.assembly.MigrationContext;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * Rename a NamedAssociation
+ */
+public class RenameNamedAssociation
+    implements EntityMigrationOperation
+{
+    private final String from;
+    private final String to;
+
+    public RenameNamedAssociation( String from, String to )
+    {
+        this.from = from;
+        this.to = to;
+    }
+
+    @Override
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.renameNamedAssociation( context, state, from, to );
+    }
+
+    @Override
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.renameNamedAssociation( context, state, to, from );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Rename named-association " + from + " to " + to;
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameProperty.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameProperty.java
new file mode 100644
index 0000000..4f0b80c
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameProperty.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.migration.operation;
+
+import javax.json.JsonObject;
+import org.apache.polygene.migration.assembly.MigrationContext;
+import org.apache.polygene.migration.Migrator;
+import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+
+/**
+ * Rename a property
+ */
+public class RenameProperty
+    implements EntityMigrationOperation
+{
+    String fromProperty;
+    String toProperty;
+
+    public RenameProperty( String fromProperty, String toProperty )
+    {
+        this.fromProperty = fromProperty;
+        this.toProperty = toProperty;
+    }
+
+    @Override
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.renameProperty( context, state, fromProperty, toProperty );
+    }
+
+    @Override
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+    {
+        return migrator.renameProperty( context, state, toProperty, fromProperty );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "Rename property " + fromProperty + " to " + toProperty;
+    }
+}
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/package.html b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/package.html
new file mode 100644
index 0000000..2439235
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Entities Migration Operations.</h2>
+    </body>
+</html>
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/package.html b/extensions/migration/src/main/java/org/apache/polygene/migration/package.html
new file mode 100644
index 0000000..95819a4
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Entities Migration Extension.</h2>
+    </body>
+</html>
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/util/ListMap.java b/extensions/migration/src/main/java/org/apache/polygene/migration/util/ListMap.java
new file mode 100644
index 0000000..aafc8ce
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/util/ListMap.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.migration.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Map whose values are Lists of things. Create
+ * one ArrayList for each key that is added. The list does not allow
+ * duplicates.
+ */
+public final class ListMap<K, V>
+    extends HashMap<K, List<V>>
+{
+    public void add( K key, V value )
+    {
+        List<V> list = get( key );
+        if( list == null )
+        {
+            list = new ArrayList<V>();
+            put( key, list );
+        }
+        if( !list.contains( value ) )
+        {
+            list.add( value );
+        }
+    }
+}
\ No newline at end of file
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/util/package.html b/extensions/migration/src/main/java/org/apache/polygene/migration/util/package.html
new file mode 100644
index 0000000..65edf4f
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/util/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Entities Migration Utilities.</h2>
+    </body>
+</html>
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/MigrationConfiguration.java b/extensions/migration/src/main/java/org/qi4j/migration/MigrationConfiguration.java
deleted file mode 100644
index a9c8a9a..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/MigrationConfiguration.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-/**
- * JAVADOC
- */
-public interface MigrationConfiguration
-    extends ConfigurationComposite
-{
-    @UseDefaults
-    Property<String> lastStartupVersion();
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/MigrationEventLogger.java b/extensions/migration/src/main/java/org/qi4j/migration/MigrationEventLogger.java
deleted file mode 100644
index e554aaa..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/MigrationEventLogger.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration;
-
-import java.util.Arrays;
-import java.util.Map;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * MigrationEvents implementation that logs the events.
- */
-public class MigrationEventLogger
-    implements MigrationEvents
-{
-    protected Logger logger = LoggerFactory.getLogger( getClass().getName() );
-
-    @Override
-    public void propertyAdded( String entity, String name, Object value )
-    {
-        logger.info( "Added property " + name + " with value " + ( value == null ? "null" : value.toString() ) + " in " + entity );
-    }
-
-    @Override
-    public void propertyRemoved( String entity, String name )
-    {
-        logger.info( "Removed property " + name + " in " + entity );
-    }
-
-    @Override
-    public void propertyRenamed( String entity, String from, String to )
-    {
-        logger.info( "Renamed property from " + from + " to " + to + " in " + entity );
-    }
-
-    @Override
-    public void associationAdded( String entity, String name, String value )
-    {
-        logger.info( "Added association " + name + " with value " + value + " in " + entity );
-    }
-
-    @Override
-    public void associationRemoved( String entity, String name )
-    {
-        logger.info( "Removed association " + name + " in " + entity );
-    }
-
-    @Override
-    public void associationRenamed( String entity, String from, String to )
-    {
-        logger.info( "Renamed association from " + from + " to " + to + " in " + entity );
-    }
-
-    @Override
-    public void manyAssociationAdded( String entity, String name, String... value )
-    {
-        logger.info( "Added many-association " + name + " with values " + Arrays.asList( value ) + " in " + entity );
-    }
-
-    @Override
-    public void manyAssociationRemoved( String entity, String name )
-    {
-        logger.info( "Removed many-association " + name + " in " + entity );
-    }
-
-    @Override
-    public void manyAssociationRenamed( String entity, String from, String to )
-    {
-        logger.info( "Renamed many-association from " + from + " to " + to + " in " + entity );
-    }
-
-    @Override
-    public void namedAssociationAdded( String entity, String name, Map<String, String> value )
-    {
-        logger.info( "Added named-association " + name + " with values " + value + " in " + entity );
-    }
-
-    @Override
-    public void namedAssociationRemoved( String entity, String name )
-    {
-        logger.info( "Removed named-association " + name + " in " + entity );
-    }
-
-    @Override
-    public void namedAssociationRenamed( String entity, String from, String to )
-    {
-        logger.info( "Renamed named-association from " + from + " to " + to + " in " + entity );
-    }
-
-    @Override
-    public void entityTypeChanged( String entity, String newEntityType )
-    {
-        logger.info( "Changed entitytype to " + newEntityType + " in " + entity );
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/MigrationEvents.java b/extensions/migration/src/main/java/org/qi4j/migration/MigrationEvents.java
deleted file mode 100644
index 69d1003..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/MigrationEvents.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration;
-
-import java.util.Map;
-
-/**
- * Implement this as a service to receive events from the Migration process.
- */
-public interface MigrationEvents
-{
-    void propertyAdded( String entity, String name, Object value );
-
-    void propertyRemoved( String entity, String name );
-
-    void propertyRenamed( String entity, String from, String to );
-
-    void associationAdded( String entity, String name, String defaultReference );
-
-    void associationRemoved( String entity, String name );
-
-    void associationRenamed( String entity, String from, String to );
-
-    void manyAssociationAdded( String entity, String name, String... defaultReferences );
-
-    void manyAssociationRemoved( String entity, String name );
-
-    void manyAssociationRenamed( String entity, String from, String to );
-
-    void namedAssociationAdded( String entity, String name, Map<String, String> defaultReferences );
-
-    void namedAssociationRemoved( String entity, String name );
-
-    void namedAssociationRenamed( String entity, String from, String to );
-
-    void entityTypeChanged( String entity, String newEntityType );
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/MigrationService.java b/extensions/migration/src/main/java/org/qi4j/migration/MigrationService.java
deleted file mode 100644
index 62fd400..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/MigrationService.java
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Copyright (c) 2009-2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed  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.qi4j.migration;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.migration.assembly.EntityMigrationRule;
-import org.qi4j.migration.assembly.MigrationBuilder;
-import org.qi4j.migration.assembly.MigrationRule;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.helpers.JSONKeys;
-import org.qi4j.spi.entitystore.helpers.Migration;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Migration service. This is used by MapEntityStore EntityStore implementations to
- * migrate JSON state for Entities. To use it register the service so that the EntityStore
- * can access it, and then create MigrationRules during the assembly of your application,
- * which is registered as metainfo for this service.
- *
- * The rules invoke operations, which in turn invoke the Migrator interface to perform the actual
- * migration. If the Migrator accepts a migration command the change is performed, and an event
- * is triggered. These events can be received by implementing the MigrationEvents interface in a service
- * that is visible by this MigrationService.
- */
-@Mixins( MigrationService.MigrationMixin.class )
-@Activators( MigrationService.Activator.class )
-public interface MigrationService
-    extends Migration
-{
-
-    void initialize()
-        throws Exception;
-
-    class Activator
-        extends ActivatorAdapter<ServiceReference<MigrationService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<MigrationService> activated )
-            throws Exception
-        {
-            activated.get().initialize();
-        }
-
-    }
-
-    public class MigrationMixin
-        implements MigrationService, Migrator
-    {
-        @Structure
-        Application app;
-
-        @This
-        Configuration<MigrationConfiguration> config;
-
-        @Uses
-        ServiceDescriptor descriptor;
-
-        @Service
-        StateStore store;
-        @Service
-        EntityStore entityStore;
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        @This
-        Migrator migrator;
-
-        public MigrationBuilder builder;
-        public Logger log;
-
-        @Service
-        Iterable<MigrationEvents> migrationEvents;
-
-        @Override
-        public boolean migrate( JSONObject state, String toVersion, StateStore stateStore )
-            throws JSONException
-        {
-            // Get current version
-            String fromVersion = state.optString( JSONKeys.APPLICATION_VERSION, "0.0" );
-
-            Iterable<EntityMigrationRule> matchedRules = builder.entityMigrationRules().rulesBetweenVersions( fromVersion, toVersion );
-
-            boolean changed = false;
-            if( matchedRules != null )
-            {
-                for( EntityMigrationRule matchedRule : matchedRules )
-                {
-                    boolean ruleExecuted = matchedRule.upgrade( state, stateStore, migrator );
-
-                    if( ruleExecuted && log.isDebugEnabled() )
-                    {
-                        log.debug( matchedRule.toString() );
-                    }
-
-                    changed = ruleExecuted || changed;
-                }
-            }
-
-            state.put( JSONKeys.APPLICATION_VERSION, toVersion );
-
-            if( changed )
-            {
-                log.info( "Migrated " + state.getString( JSONKeys.IDENTITY ) + " from " + fromVersion + " to " + toVersion );
-            }
-
-            return changed;
-        }
-
-        @Override
-        public void initialize()
-            throws Exception
-        {
-            builder = descriptor.metaInfo( MigrationBuilder.class );
-
-            log = LoggerFactory.getLogger( MigrationService.class );
-
-            String version = app.version();
-            String lastVersion = config.get().lastStartupVersion().get();
-
-            // Run general rules if version has changed
-            if( !app.version().equals( lastVersion ) )
-            {
-                Iterable<MigrationRule> rules = builder.migrationRules().rulesBetweenVersions( lastVersion, version );
-                List<MigrationRule> executedRules = new ArrayList<>();
-                try
-                {
-                    if( rules != null )
-                    {
-                        for( MigrationRule rule : rules )
-                        {
-                            rule.upgrade( store, this );
-                            executedRules.add( rule );
-                            log.debug( rule.toString() );
-                        }
-
-                        log.info( "Migrated to " + version );
-                    }
-
-                    config.get().lastStartupVersion().set( version );
-                    config.save();
-                }
-                catch( Exception e )
-                {
-                    log.error( "Upgrade failed", e );
-
-                    // Downgrade the migrated rules
-                    for( MigrationRule executedRule : executedRules )
-                    {
-                        executedRule.downgrade( store, this );
-                    }
-                }
-            }
-        }
-
-        // Migrator implementation
-        @Override
-        public boolean addProperty( JSONObject state, String name, Object defaultValue )
-            throws JSONException
-        {
-            JSONObject properties = state.getJSONObject( JSONKeys.PROPERTIES );
-            if( !properties.has( name ) )
-            {
-                if( defaultValue == null )
-                {
-                    properties.put( name, JSONObject.NULL );
-                }
-                else
-                {
-                    properties.put( name, defaultValue );
-                }
-
-                for( MigrationEvents migrationEvent : migrationEvents )
-                {
-                    migrationEvent.propertyAdded( state.getString( JSONKeys.IDENTITY ), name, defaultValue );
-                }
-
-                return true;
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        @Override
-        public boolean removeProperty( JSONObject state, String name )
-            throws JSONException
-        {
-            JSONObject properties = state.getJSONObject( JSONKeys.PROPERTIES );
-            if( properties.has( name ) )
-            {
-                properties.remove( name );
-                for( MigrationEvents migrationEvent : migrationEvents )
-                {
-                    migrationEvent.propertyRemoved( state.getString( JSONKeys.IDENTITY ), name );
-                }
-
-                return true;
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        @Override
-        public boolean renameProperty( JSONObject state, String from, String to )
-            throws JSONException
-        {
-            JSONObject properties = state.getJSONObject( JSONKeys.PROPERTIES );
-            if( properties.has( from ) )
-            {
-                Object value = properties.remove( from );
-                properties.put( to, value );
-                for( MigrationEvents migrationEvent : migrationEvents )
-                {
-                    migrationEvent.propertyRenamed( state.getString( JSONKeys.IDENTITY ), from, to );
-                }
-
-                return true;
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        @Override
-        public boolean addAssociation( JSONObject state, String name, String defaultReference )
-            throws JSONException
-        {
-            JSONObject associations = state.getJSONObject( JSONKeys.ASSOCIATIONS );
-            if( !associations.has( name ) )
-            {
-                if( defaultReference == null )
-                {
-                    associations.put( name, JSONObject.NULL );
-                }
-                else
-                {
-                    associations.put( name, defaultReference );
-                }
-
-                for( MigrationEvents migrationEvent : migrationEvents )
-                {
-                    migrationEvent.associationAdded( state.getString( JSONKeys.IDENTITY ), name, defaultReference );
-                }
-
-                return true;
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        @Override
-        public boolean removeAssociation( JSONObject state, String name )
-            throws JSONException
-        {
-            JSONObject associations = state.getJSONObject( JSONKeys.ASSOCIATIONS );
-            if( associations.has( name ) )
-            {
-                associations.remove( name );
-                for( MigrationEvents migrationEvent : migrationEvents )
-                {
-                    migrationEvent.associationRemoved( state.getString( JSONKeys.IDENTITY ), name );
-                }
-
-                return true;
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        @Override
-        public boolean renameAssociation( JSONObject state, String from, String to )
-            throws JSONException
-        {
-            JSONObject associations = state.getJSONObject( JSONKeys.ASSOCIATIONS );
-            if( associations.has( from ) )
-            {
-                Object value = associations.remove( from );
-                associations.put( to, value );
-
-                for( MigrationEvents migrationEvent : migrationEvents )
-                {
-                    migrationEvent.associationRenamed( state.getString( JSONKeys.IDENTITY ), from, to );
-                }
-
-                return true;
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        @Override
-        public boolean addManyAssociation( JSONObject state, String name, String... defaultReferences )
-            throws JSONException
-        {
-            JSONObject manyAssociations = state.getJSONObject( JSONKeys.MANY_ASSOCIATIONS );
-            if( !manyAssociations.has( name ) )
-            {
-                JSONArray references = new JSONArray();
-                for( String reference : defaultReferences )
-                {
-                    references.put( reference );
-                }
-                manyAssociations.put( name, references );
-
-                for( MigrationEvents migrationEvent : migrationEvents )
-                {
-                    migrationEvent.manyAssociationAdded( state.getString( JSONKeys.IDENTITY ), name, defaultReferences );
-                }
-
-                return true;
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        @Override
-        public boolean removeManyAssociation( JSONObject state, String name )
-            throws JSONException
-        {
-            JSONObject manyAssociations = state.getJSONObject( JSONKeys.MANY_ASSOCIATIONS );
-            if( manyAssociations.has( name ) )
-            {
-                manyAssociations.remove( name );
-                for( MigrationEvents migrationEvent : migrationEvents )
-                {
-                    migrationEvent.manyAssociationRemoved( state.getString( JSONKeys.IDENTITY ), name );
-                }
-
-                return true;
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        @Override
-        public boolean renameManyAssociation( JSONObject state, String from, String to )
-            throws JSONException
-        {
-            JSONObject manyAssociations = state.getJSONObject( JSONKeys.MANY_ASSOCIATIONS );
-            if( manyAssociations.has( from ) )
-            {
-                Object value = manyAssociations.remove( from );
-                manyAssociations.put( to, value );
-
-                for( MigrationEvents migrationEvent : migrationEvents )
-                {
-                    migrationEvent.manyAssociationRenamed( state.getString( JSONKeys.IDENTITY ), from, to );
-                }
-
-                return true;
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        @Override
-        public boolean addNamedAssociation( JSONObject state, String name, Map<String, String> defaultReferences )
-            throws JSONException
-        {
-            JSONObject namedAssociations = state.getJSONObject( JSONKeys.NAMED_ASSOCIATIONS );
-            if( !namedAssociations.has( name ) )
-            {
-                JSONObject references = new JSONObject();
-                for( Map.Entry<String, String> namedRef : defaultReferences.entrySet() )
-                {
-                    references.put( namedRef.getKey(), namedRef.getValue() );
-                }
-                namedAssociations.put( name, references );
-
-                for( MigrationEvents migrationEvent : migrationEvents )
-                {
-                    migrationEvent.namedAssociationAdded( state.getString( JSONKeys.IDENTITY ), name, defaultReferences );
-                }
-
-                return true;
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        @Override
-        public boolean removeNamedAssociation( JSONObject state, String name )
-            throws JSONException
-        {
-            JSONObject namedAssociations = state.getJSONObject( JSONKeys.NAMED_ASSOCIATIONS );
-            if( namedAssociations.has( name ) )
-            {
-                namedAssociations.remove( name );
-
-                for( MigrationEvents migrationEvent : migrationEvents )
-                {
-                    migrationEvent.namedAssociationRemoved( state.getString( JSONKeys.IDENTITY ), name );
-                }
-
-                return true;
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        @Override
-        public boolean renameNamedAssociation( JSONObject state, String from, String to )
-            throws JSONException
-        {
-            JSONObject namedAssociations = state.getJSONObject( JSONKeys.NAMED_ASSOCIATIONS );
-            if( namedAssociations.has( from ) )
-            {
-                Object value = namedAssociations.remove( from );
-                namedAssociations.put( to, value );
-
-                for( MigrationEvents migrationEvent : migrationEvents )
-                {
-                    migrationEvent.namedAssociationRenamed( state.getString( JSONKeys.IDENTITY ), from, to );
-                }
-
-                return true;
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        @Override
-        public void changeEntityType( JSONObject state, String newEntityType )
-            throws JSONException
-        {
-            state.put( JSONKeys.TYPE, newEntityType );
-
-            for( MigrationEvents migrationEvent : migrationEvents )
-            {
-                migrationEvent.entityTypeChanged( state.getString( JSONKeys.IDENTITY ), newEntityType );
-            }
-        }
-    }
-
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/Migrator.java b/extensions/migration/src/main/java/org/qi4j/migration/Migrator.java
deleted file mode 100644
index 102789e..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/Migrator.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration;
-
-import java.util.Map;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-/**
- * The Migrator implements this interface, which is invoked by MigrationOperation implementations
- * to perform changes to EntityState during a version migration.
- */
-public interface Migrator
-{
-    boolean addProperty( JSONObject state, String name, Object defaultValue )
-        throws JSONException;
-
-    boolean removeProperty( JSONObject state, String name )
-        throws JSONException;
-
-    boolean renameProperty( JSONObject state, String from, String to )
-        throws JSONException;
-
-    boolean addAssociation( JSONObject state, String name, String defaultReference )
-        throws JSONException;
-
-    boolean removeAssociation( JSONObject state, String name )
-        throws JSONException;
-
-    boolean renameAssociation( JSONObject state, String from, String to )
-        throws JSONException;
-
-    boolean addManyAssociation( JSONObject state, String name, String... defaultReferences )
-        throws JSONException;
-
-    boolean removeManyAssociation( JSONObject state, String name )
-        throws JSONException;
-
-    boolean renameManyAssociation( JSONObject state, String from, String to )
-        throws JSONException;
-
-    boolean addNamedAssociation( JSONObject state, String name, Map<String, String> defaultReferences )
-        throws JSONException;
-
-    boolean removeNamedAssociation( JSONObject state, String name )
-        throws JSONException;
-
-    boolean renameNamedAssociation( JSONObject state, String from, String to )
-        throws JSONException;
-
-    void changeEntityType( JSONObject state, String newEntityType )
-        throws JSONException;
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/assembly/AbstractMigrationRule.java b/extensions/migration/src/main/java/org/qi4j/migration/assembly/AbstractMigrationRule.java
deleted file mode 100644
index 91adc01..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/assembly/AbstractMigrationRule.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.assembly;
-
-/**
- * Base class for migration rules.
- */
-public class AbstractMigrationRule
-{
-    protected String fromVersion;
-    protected String toVersion;
-
-    public AbstractMigrationRule( String fromVersion, String toVersion )
-    {
-        this.fromVersion = fromVersion;
-        this.toVersion = toVersion;
-    }
-
-    public String fromVersion()
-    {
-        return fromVersion;
-    }
-
-    public String toVersion()
-    {
-        return toVersion;
-    }
-}
\ No newline at end of file
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/assembly/EntityMigrationBuilder.java b/extensions/migration/src/main/java/org/qi4j/migration/assembly/EntityMigrationBuilder.java
deleted file mode 100644
index ec75a27..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/assembly/EntityMigrationBuilder.java
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.assembly;
-
-import java.util.Map;
-import org.qi4j.migration.operation.AddAssociation;
-import org.qi4j.migration.operation.AddManyAssociation;
-import org.qi4j.migration.operation.AddNamedAssociation;
-import org.qi4j.migration.operation.AddProperty;
-import org.qi4j.migration.operation.RemoveAssociation;
-import org.qi4j.migration.operation.RemoveManyAssociation;
-import org.qi4j.migration.operation.RemoveNamedAssociation;
-import org.qi4j.migration.operation.RemoveProperty;
-import org.qi4j.migration.operation.RenameAssociation;
-import org.qi4j.migration.operation.RenameManyAssociation;
-import org.qi4j.migration.operation.RenameNamedAssociation;
-import org.qi4j.migration.operation.RenameProperty;
-
-/**
- * Fluent API for creating migration rules for specific entity types.
- */
-public class EntityMigrationBuilder
-{
-    private final VersionMigrationBuilder migrationBuilder;
-    private final String[] entityTypes;
-
-    public EntityMigrationBuilder( VersionMigrationBuilder migrationBuilder, String[] entityTypes )
-    {
-        this.migrationBuilder = migrationBuilder;
-        this.entityTypes = entityTypes;
-    }
-
-    /**
-     * Return the version builder
-     *
-     * @return current version builder
-     */
-    public VersionMigrationBuilder end()
-    {
-        return migrationBuilder;
-    }
-
-    // Operations on entities
-    /**
-     * Add rule to rename an Entity property.
-     *
-     * @param from property name
-     * @param to   property name
-     *
-     * @return the builder
-     */
-    public EntityMigrationBuilder renameProperty( String from, String to )
-    {
-        migrationBuilder.builder.entityMigrationRules().
-            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
-                                              migrationBuilder.toVersion,
-                                              entityTypes,
-                                              new RenameProperty( from, to ) ) );
-
-        return this;
-    }
-
-    /**
-     * Add rule to add an Entity property.
-     *
-     * @param property     to be added
-     * @param defaultValue default value
-     *
-     * @return the builder
-     */
-    public EntityMigrationBuilder addProperty( String property, Object defaultValue )
-    {
-        migrationBuilder.builder.entityMigrationRules().
-            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
-                                              migrationBuilder.toVersion,
-                                              entityTypes,
-                                              new AddProperty( property, defaultValue ) ) );
-
-        return this;
-    }
-
-    /**
-     * Add rule to remove an Entity property
-     *
-     * @param property     to be removed
-     * @param defaultValue default value (used for downgrading)
-     *
-     * @return the builder
-     */
-    public EntityMigrationBuilder removeProperty( String property, String defaultValue )
-    {
-        migrationBuilder.builder.entityMigrationRules().
-            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
-                                              migrationBuilder.toVersion,
-                                              entityTypes,
-                                              new RemoveProperty( property, defaultValue ) ) );
-
-        return this;
-    }
-
-    /**
-     * Add rule to rename an Entity association.
-     *
-     * @param from assocation name
-     * @param to   association name
-     *
-     * @return the builder
-     */
-    public EntityMigrationBuilder renameAssociation( String from, String to )
-    {
-        migrationBuilder.builder.entityMigrationRules().
-            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
-                                              migrationBuilder.toVersion,
-                                              entityTypes,
-                                              new RenameAssociation( from, to ) ) );
-
-        return this;
-    }
-
-    /**
-     * Add rule to add an Entity association.
-     *
-     * @param association      to be added
-     * @param defaultReference default reference
-     *
-     * @return the builder
-     */
-    public EntityMigrationBuilder addAssociation( String association, String defaultReference )
-    {
-        migrationBuilder.builder.entityMigrationRules().
-            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
-                                              migrationBuilder.toVersion,
-                                              entityTypes,
-                                              new AddAssociation( association, defaultReference ) ) );
-
-        return this;
-    }
-
-    /**
-     * Add rule to remove an Entity association
-     *
-     * @param association      to be removed
-     * @param defaultReference default value (used for downgrading)
-     *
-     * @return the builder
-     */
-    public EntityMigrationBuilder removeAssociation( String association, String defaultReference )
-    {
-        migrationBuilder.builder.entityMigrationRules().
-            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
-                                              migrationBuilder.toVersion,
-                                              entityTypes,
-                                              new RemoveAssociation( association, defaultReference ) ) );
-
-        return this;
-    }
-
-    /**
-     * Add rule to add an Entity many-association.
-     *
-     * @param association       to be added
-     * @param defaultReferences default references
-     *
-     * @return the builder
-     */
-    public EntityMigrationBuilder addManyAssociation( String association, String... defaultReferences )
-    {
-        migrationBuilder.builder.entityMigrationRules().
-            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
-                                              migrationBuilder.toVersion,
-                                              entityTypes,
-                                              new AddManyAssociation( association, defaultReferences ) ) );
-
-        return this;
-    }
-
-    /**
-     * Add rule to remove an Entity many-association
-     *
-     * @param association       to be removed
-     * @param defaultReferences default value (used for downgrading)
-     *
-     * @return the builder
-     */
-    public EntityMigrationBuilder removeManyAssociation( String association, String... defaultReferences )
-    {
-        migrationBuilder.builder.entityMigrationRules().
-            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
-                                              migrationBuilder.toVersion,
-                                              entityTypes,
-                                              new RemoveManyAssociation( association, defaultReferences ) ) );
-
-        return this;
-    }
-
-    /**
-     * Add rule to rename an Entity many-association.
-     *
-     * @param from many-assocation name
-     * @param to   many-association name
-     *
-     * @return the builder
-     */
-    public EntityMigrationBuilder renameManyAssociation( String from, String to )
-    {
-        migrationBuilder.builder.entityMigrationRules().
-            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
-                                              migrationBuilder.toVersion,
-                                              entityTypes,
-                                              new RenameManyAssociation( from, to ) ) );
-
-        return this;
-    }
-
-    /**
-     * Add rule to add an Entity named-association.
-     *
-     * @param association       to be added
-     * @param defaultReferences default references
-     *
-     * @return the builder
-     */
-    public EntityMigrationBuilder addNamedAssociation( String association, Map<String, String> defaultReferences )
-    {
-        migrationBuilder.builder.entityMigrationRules().
-            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
-                                              migrationBuilder.toVersion,
-                                              entityTypes,
-                                              new AddNamedAssociation( association, defaultReferences ) ) );
-
-        return this;
-    }
-
-    /**
-     * Add rule to remove an Entity named-association
-     *
-     * @param association       to be removed
-     * @param defaultReferences default value (used for downgrading)
-     *
-     * @return the builder
-     */
-    public EntityMigrationBuilder removeNamedAssociation( String association, Map<String, String> defaultReferences )
-    {
-        migrationBuilder.builder.entityMigrationRules().
-            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
-                                              migrationBuilder.toVersion,
-                                              entityTypes,
-                                              new RemoveNamedAssociation( association, defaultReferences ) ) );
-
-        return this;
-    }
-
-    /**
-     * Add rule to rename an Entity named-association.
-     *
-     * @param from many-assocation name
-     * @param to   many-association name
-     *
-     * @return the builder
-     */
-    public EntityMigrationBuilder renameNamedAssociation( String from, String to )
-    {
-        migrationBuilder.builder.entityMigrationRules().
-            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
-                                              migrationBuilder.toVersion,
-                                              entityTypes,
-                                              new RenameNamedAssociation( from, to ) ) );
-
-        return this;
-    }
-
-    /**
-     * Add rule to perform a custom operation
-     *
-     * @param operationEntity the custom operation to be performed during migration
-     *
-     * @return the builder
-     */
-    public EntityMigrationBuilder custom( EntityMigrationOperation operationEntity )
-    {
-        migrationBuilder.builder.entityMigrationRules().
-            addRule( new EntityMigrationRule( migrationBuilder.fromVersion,
-                                              migrationBuilder.toVersion,
-                                              entityTypes,
-                                              operationEntity ) );
-
-        return this;
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/assembly/EntityMigrationOperation.java b/extensions/migration/src/main/java/org/qi4j/migration/assembly/EntityMigrationOperation.java
deleted file mode 100644
index 1b5657d..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/assembly/EntityMigrationOperation.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.assembly;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.migration.Migrator;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * Migration operation for a specific entity.
- */
-public interface EntityMigrationOperation
-{
-    boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException;
-
-    boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException;
-}
\ No newline at end of file
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/assembly/EntityMigrationRule.java b/extensions/migration/src/main/java/org/qi4j/migration/assembly/EntityMigrationRule.java
deleted file mode 100644
index 208170f..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/assembly/EntityMigrationRule.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.assembly;
-
-import java.util.Arrays;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.migration.Migrator;
-import org.qi4j.spi.entitystore.helpers.JSONKeys;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * Migration rule for a specific set of entity types
- */
-public class EntityMigrationRule
-    extends AbstractMigrationRule
-{
-    private final String[] entityTypes;
-    private final EntityMigrationOperation operationEntity;
-
-    public EntityMigrationRule( String fromVersion,
-                                String toVersion,
-                                String[] entityTypes,
-                                EntityMigrationOperation operationEntity
-    )
-    {
-        super( fromVersion, toVersion );
-        this.entityTypes = entityTypes;
-        this.operationEntity = operationEntity;
-    }
-
-    public String[] entityTypes()
-    {
-        return entityTypes;
-    }
-
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        if( appliesTo( state.getString( JSONKeys.TYPE ) ) )
-        {
-            return operationEntity.upgrade( state, stateStore, migrator );
-        }
-        else
-        {
-            return false;
-        }
-    }
-
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        if( appliesTo( state.getString( JSONKeys.TYPE ) ) )
-        {
-            return operationEntity.downgrade( state, stateStore, migrator );
-        }
-        else
-        {
-            return false;
-        }
-    }
-
-    public boolean appliesTo( String entityType )
-    {
-        for( String type : entityTypes )
-        {
-            if( entityType.equals( type ) )
-            {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public String toString()
-    {
-        return fromVersion + "->" + toVersion + ": on " + Arrays.asList( entityTypes ) + " do " + operationEntity;
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/assembly/MigrationBuilder.java b/extensions/migration/src/main/java/org/qi4j/migration/assembly/MigrationBuilder.java
deleted file mode 100644
index 56cab99..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/assembly/MigrationBuilder.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.assembly;
-
-/**
- * Builder for set of migration rules. This needs to be passed in as metadata to the MigrationService.
- */
-public class MigrationBuilder
-{
-    MigrationRules<EntityMigrationRule> entityRules;
-    MigrationRules<MigrationRule> rules;
-
-    String fromVersion;
-
-    public MigrationBuilder( String fromVersion )
-    {
-        this.entityRules = new MigrationRules<EntityMigrationRule>();
-        this.rules = new MigrationRules<MigrationRule>();
-        this.fromVersion = fromVersion;
-    }
-
-    public VersionMigrationBuilder toVersion( String toVersion )
-    {
-        return new VersionMigrationBuilder( this, fromVersion, toVersion );
-    }
-
-    public MigrationRules<EntityMigrationRule> entityMigrationRules()
-    {
-        return entityRules;
-    }
-
-    public MigrationRules<MigrationRule> migrationRules()
-    {
-        return rules;
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/assembly/MigrationOperation.java b/extensions/migration/src/main/java/org/qi4j/migration/assembly/MigrationOperation.java
deleted file mode 100644
index a34d080..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/assembly/MigrationOperation.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.assembly;
-
-import java.io.IOException;
-import org.qi4j.migration.Migrator;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * Non-entity specific migration operation. These operations
- * may perform anything necessary to migrate the application. This
- * could include performing disk operations and other non-entity related
- * tasks.
- */
-public interface MigrationOperation
-{
-    void upgrade( StateStore stateStore, Migrator migrator )
-        throws IOException;
-
-    void downgrade( StateStore stateStore, Migrator migrator )
-        throws IOException;
-}
\ No newline at end of file
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/assembly/MigrationRule.java b/extensions/migration/src/main/java/org/qi4j/migration/assembly/MigrationRule.java
deleted file mode 100644
index 7bdf885..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/assembly/MigrationRule.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.assembly;
-
-import java.io.IOException;
-import org.qi4j.migration.Migrator;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * Migration rule that does not apply to a specific entity type
- */
-public class MigrationRule
-    extends AbstractMigrationRule
-{
-    private MigrationOperation operation;
-
-    public MigrationRule( String fromVersion, String toVersion, MigrationOperation operation )
-    {
-        super( fromVersion, toVersion );
-        this.operation = operation;
-    }
-
-    public void upgrade( StateStore stateStore, Migrator migrator )
-        throws IOException
-    {
-        operation.upgrade( stateStore, migrator );
-    }
-
-    public void downgrade( StateStore stateStore, Migrator migrator )
-        throws IOException
-    {
-        operation.downgrade( stateStore, migrator );
-    }
-
-    @Override
-    public String toString()
-    {
-        return fromVersion + "->" + toVersion + ":" + operation;
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/assembly/MigrationRules.java b/extensions/migration/src/main/java/org/qi4j/migration/assembly/MigrationRules.java
deleted file mode 100644
index 57a4ac2..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/assembly/MigrationRules.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.assembly;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import org.qi4j.api.util.ListMap;
-
-/**
- * Set of migration rules.
- */
-public class MigrationRules<T extends AbstractMigrationRule>
-{
-    // to-version -> List of from-versions
-    ListMap<String, String> versionChanges = new ListMap<String, String>();
-
-    // key=fromversion->toversion value=list of rules for that transition
-    ListMap<String, T> rules = new ListMap<String, T>();
-
-    public void addRule( T migrationRule )
-    {
-        versionChanges.add( migrationRule.toVersion(), migrationRule.fromVersion() );
-        rules.add( migrationRule.fromVersion() + "->" + migrationRule.toVersion(), migrationRule );
-    }
-
-    public Iterable<T> rulesBetweenVersions( String fromVersion, String toVersion )
-    {
-        try
-        {
-            String ruleToVersion = findHighestToVersion( toVersion );
-
-            return migrationRules( fromVersion, ruleToVersion );
-        }
-        catch( IllegalArgumentException e )
-        {
-            return null;
-        }
-    }
-
-    private List<T> migrationRules( String fromVersion, String toVersion )
-    {
-        List<String> list = versionChanges.get( toVersion );
-
-        if( list == null )
-        {
-            return null; // No possible rules for this transition
-        }
-
-        for( String possibleFromVersion : list )
-        {
-            if( fromVersion.equals( possibleFromVersion ) )
-            {
-                // We found the end of the version transitions - return rules, but filter on entity type
-                return new ArrayList<T>( getRulesForTransition( fromVersion, toVersion ) );
-            }
-            else
-            {
-                List<T> migrationRules = migrationRules( fromVersion, possibleFromVersion );
-                if( migrationRules == null )
-                {
-                    continue; // Wrong transition - try another one
-                }
-
-                // Add entity-filtered rules from this part of the version transition
-                migrationRules.addAll( getRulesForTransition( possibleFromVersion, toVersion ) );
-                return migrationRules;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Find highest version below the given to-version for which there are rules registered.
-     *
-     * @param toVersion The ending toVersion in the search.
-     *
-     * @return The highest version below the given version for which there are rules registered.
-     */
-    private String findHighestToVersion( String toVersion )
-    {
-        if( versionChanges.get( toVersion ) == null )
-        {
-            List<String> toVersions = new ArrayList<String>( versionChanges.keySet() );
-            Collections.sort( toVersions, Collections.reverseOrder() );
-            for( String version : toVersions )
-            {
-                if( version.compareTo( toVersion ) <= 0 )
-                {
-                    // Found version to change to
-                    return version;
-                }
-            }
-            throw new IllegalArgumentException( "No version found in rules that matches the given to-version:" + toVersion );
-        }
-        else
-        {
-            return toVersion;
-        }
-    }
-
-    private List<T> getRulesForTransition( String fromVersion, String toVersion )
-    {
-        return rules.get( fromVersion + "->" + toVersion );
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/assembly/PackageMigrationBuilder.java b/extensions/migration/src/main/java/org/qi4j/migration/assembly/PackageMigrationBuilder.java
deleted file mode 100644
index d674811..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/assembly/PackageMigrationBuilder.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.assembly;
-
-import org.qi4j.migration.operation.RenameEntity;
-
-/**
- * JAVADOC
- */
-public class PackageMigrationBuilder
-{
-    private MigrationBuilder builder;
-    private VersionMigrationBuilder version;
-    private String fromVersion;
-    private String toVersion;
-    private String fromName;
-    private String toName;
-
-    public PackageMigrationBuilder( MigrationBuilder builder,
-                                    VersionMigrationBuilder version,
-                                    String fromVersion,
-                                    String toVersion,
-                                    String fromName,
-                                    String toName
-    )
-    {
-        this.builder = builder;
-        this.version = version;
-        this.fromVersion = fromVersion;
-        this.toVersion = toVersion;
-        this.fromName = fromName;
-        this.toName = toName;
-    }
-
-    public VersionMigrationBuilder end()
-    {
-        return version;
-    }
-
-    public PackageMigrationBuilder withEntities( String... entitySimpleNames )
-    {
-        for( String entitySimpleName : entitySimpleNames )
-        {
-            builder.entityMigrationRules().addRule( new EntityMigrationRule(
-                fromVersion,
-                toVersion,
-                new String[]{ fromName + "." + entitySimpleName },
-                new RenameEntity( fromName + "." + entitySimpleName, toName + "." + entitySimpleName ) ) );
-        }
-
-        return this;
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/assembly/VersionMigrationBuilder.java b/extensions/migration/src/main/java/org/qi4j/migration/assembly/VersionMigrationBuilder.java
deleted file mode 100644
index 8b456fe..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/assembly/VersionMigrationBuilder.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.assembly;
-
-import org.qi4j.migration.operation.RenameEntity;
-
-/**
- * Migration builder for a specific to-version.
- */
-public class VersionMigrationBuilder
-{
-    MigrationBuilder builder;
-
-    String fromVersion;
-    String toVersion;
-
-    public VersionMigrationBuilder( MigrationBuilder builder, String fromVersion, String toVersion )
-    {
-        this.builder = builder;
-        this.fromVersion = fromVersion;
-        this.toVersion = toVersion;
-    }
-
-    public VersionMigrationBuilder toVersion( String toVersion )
-    {
-        return new VersionMigrationBuilder( builder, this.toVersion, toVersion );
-    }
-
-    public VersionMigrationBuilder renameEntity( String fromName, String toName )
-    {
-        builder.entityMigrationRules()
-            .addRule( new EntityMigrationRule( fromVersion, toVersion, new String[]{ fromName }, new RenameEntity( fromName, toName ) ) );
-
-        return this;
-    }
-
-    public PackageMigrationBuilder renamePackage( String fromName, String toName )
-    {
-        return new PackageMigrationBuilder( builder, this, fromVersion, toVersion, fromName, toName );
-    }
-
-    public VersionMigrationBuilder atStartup( MigrationOperation operation )
-    {
-        builder.migrationRules().addRule( new MigrationRule( fromVersion, toVersion, operation ) );
-
-        return this;
-    }
-
-    public EntityMigrationBuilder forEntities( String... entityTypes )
-    {
-        return new EntityMigrationBuilder( this, entityTypes );
-    }
-}
\ No newline at end of file
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/assembly/package.html b/extensions/migration/src/main/java/org/qi4j/migration/assembly/package.html
deleted file mode 100644
index 9dad115..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/assembly/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Entities Migration Assembly.</h2>
-    </body>
-</html>
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/operation/AddAssociation.java b/extensions/migration/src/main/java/org/qi4j/migration/operation/AddAssociation.java
deleted file mode 100644
index 1e31f70..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/operation/AddAssociation.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.operation;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.migration.Migrator;
-import org.qi4j.migration.assembly.EntityMigrationOperation;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * Add an association
- */
-public class AddAssociation
-    implements EntityMigrationOperation
-{
-    private String association;
-    private String defaultValue;
-
-    public AddAssociation( String association, String defaultReference )
-    {
-        this.association = association;
-        this.defaultValue = defaultReference;
-    }
-
-    @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.addAssociation( state, association, defaultValue );
-    }
-
-    @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.removeAssociation( state, association );
-    }
-
-    @Override
-    public String toString()
-    {
-        return "Add association " + association + ", default:" + defaultValue;
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/operation/AddManyAssociation.java b/extensions/migration/src/main/java/org/qi4j/migration/operation/AddManyAssociation.java
deleted file mode 100644
index 5d465cd..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/operation/AddManyAssociation.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.operation;
-
-import java.util.Arrays;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.migration.Migrator;
-import org.qi4j.migration.assembly.EntityMigrationOperation;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * Add a many-association
- */
-public class AddManyAssociation
-    implements EntityMigrationOperation
-{
-    private String association;
-    private String[] defaultReferences;
-
-    public AddManyAssociation( String association, String... defaultReferences )
-    {
-        this.association = association;
-        this.defaultReferences = defaultReferences;
-    }
-
-    @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.addManyAssociation( state, association, defaultReferences );
-    }
-
-    @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.removeManyAssociation( state, association );
-    }
-
-    @Override
-    public String toString()
-    {
-        return "Add many-association " + association + ", default:" + Arrays.asList( defaultReferences );
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/operation/AddNamedAssociation.java b/extensions/migration/src/main/java/org/qi4j/migration/operation/AddNamedAssociation.java
deleted file mode 100644
index 46ffa1e..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/operation/AddNamedAssociation.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.migration.operation;
-
-import java.util.Map;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.migration.Migrator;
-import org.qi4j.migration.assembly.EntityMigrationOperation;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * Add a named-association
- */
-public class AddNamedAssociation
-    implements EntityMigrationOperation
-{
-    private final String association;
-    private final Map<String, String> defaultReferences;
-
-    public AddNamedAssociation( String association, Map<String, String> defaultReferences )
-    {
-        this.association = association;
-        this.defaultReferences = defaultReferences;
-    }
-
-    @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.addNamedAssociation( state, association, defaultReferences );
-    }
-
-    @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.removeNamedAssociation( state, association );
-    }
-
-    @Override
-    public String toString()
-    {
-        return "Add named-association " + association + ", default:" + defaultReferences;
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/operation/AddProperty.java b/extensions/migration/src/main/java/org/qi4j/migration/operation/AddProperty.java
deleted file mode 100644
index 8d09bf1..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/operation/AddProperty.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.operation;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.migration.Migrator;
-import org.qi4j.migration.assembly.EntityMigrationOperation;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * Add a property
- */
-public class AddProperty
-    implements EntityMigrationOperation
-{
-    private String property;
-    private Object defaultValue;
-
-    public AddProperty( String property, Object defaultValue )
-    {
-        this.property = property;
-        this.defaultValue = defaultValue;
-    }
-
-    @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.addProperty( state, property, defaultValue );
-    }
-
-    @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.removeProperty( state, property );
-    }
-
-    @Override
-    public String toString()
-    {
-        return "Add property " + property + ", default:" + defaultValue;
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/operation/RemoveAssociation.java b/extensions/migration/src/main/java/org/qi4j/migration/operation/RemoveAssociation.java
deleted file mode 100644
index ba166ab..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/operation/RemoveAssociation.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.operation;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.migration.Migrator;
-import org.qi4j.migration.assembly.EntityMigrationOperation;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * Remove an association. Downgrading this operation will reset
- * the property to the default value.
- */
-public class RemoveAssociation
-    implements EntityMigrationOperation
-{
-    private String association;
-    private String defaultValue;
-
-    public RemoveAssociation( String association, String defaultReference )
-    {
-        this.association = association;
-        this.defaultValue = defaultReference;
-    }
-
-    @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.removeAssociation( state, association );
-    }
-
-    @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.addAssociation( state, association, defaultValue );
-    }
-
-    @Override
-    public String toString()
-    {
-        return "Remove association " + association + ", default:" + defaultValue;
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/operation/RemoveManyAssociation.java b/extensions/migration/src/main/java/org/qi4j/migration/operation/RemoveManyAssociation.java
deleted file mode 100644
index 070cd6f..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/operation/RemoveManyAssociation.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.operation;
-
-import java.util.Arrays;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.migration.Migrator;
-import org.qi4j.migration.assembly.EntityMigrationOperation;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * Add a many-association
- */
-public class RemoveManyAssociation
-    implements EntityMigrationOperation
-{
-    private String association;
-    private String[] defaultReferences;
-
-    public RemoveManyAssociation( String association, String... defaultReferences )
-    {
-        this.association = association;
-        this.defaultReferences = defaultReferences;
-    }
-
-    @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.removeManyAssociation( state, association );
-    }
-
-    @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.addManyAssociation( state, association, defaultReferences );
-    }
-
-    @Override
-    public String toString()
-    {
-        return "Remove many-association " + association + ", default:" + Arrays.asList( defaultReferences );
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/operation/RemoveNamedAssociation.java b/extensions/migration/src/main/java/org/qi4j/migration/operation/RemoveNamedAssociation.java
deleted file mode 100644
index aec973e..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/operation/RemoveNamedAssociation.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.migration.operation;
-
-import java.util.Map;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.migration.Migrator;
-import org.qi4j.migration.assembly.EntityMigrationOperation;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * Add a named-association
- */
-public class RemoveNamedAssociation
-    implements EntityMigrationOperation
-{
-    private final String association;
-    private final Map<String, String> defaultReferences;
-
-    public RemoveNamedAssociation( String association, Map<String, String> defaultReferences )
-    {
-        this.association = association;
-        this.defaultReferences = defaultReferences;
-    }
-
-    @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.removeNamedAssociation( state, association );
-    }
-
-    @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.addNamedAssociation( state, association, defaultReferences );
-    }
-
-    @Override
-    public String toString()
-    {
-        return "Remove named-association " + association + ", default:" + defaultReferences;
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/operation/RemoveProperty.java b/extensions/migration/src/main/java/org/qi4j/migration/operation/RemoveProperty.java
deleted file mode 100644
index 91afb46..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/operation/RemoveProperty.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.operation;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.migration.Migrator;
-import org.qi4j.migration.assembly.EntityMigrationOperation;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * Remove a property. Downgrading this operation will reset
- * the property to the default value.
- */
-public class RemoveProperty
-    implements EntityMigrationOperation
-{
-    private String property;
-    private String defaultValue;
-
-    public RemoveProperty( String property, String defaultValue )
-    {
-        this.property = property;
-        this.defaultValue = defaultValue;
-    }
-
-    @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.removeProperty( state, property );
-    }
-
-    @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.addProperty( state, property, defaultValue );
-    }
-
-    @Override
-    public String toString()
-    {
-        return "Remove property " + property + ", default:" + defaultValue;
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/operation/RenameAssociation.java b/extensions/migration/src/main/java/org/qi4j/migration/operation/RenameAssociation.java
deleted file mode 100644
index bee3934..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/operation/RenameAssociation.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.operation;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.migration.Migrator;
-import org.qi4j.migration.assembly.EntityMigrationOperation;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * Rename an Association
- */
-public class RenameAssociation
-    implements EntityMigrationOperation
-{
-    String from;
-    String to;
-
-    public RenameAssociation( String from, String to )
-    {
-        this.from = from;
-        this.to = to;
-    }
-
-    @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.renameAssociation( state, from, to );
-    }
-
-    @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.renameAssociation( state, to, from );
-    }
-
-    @Override
-    public String toString()
-    {
-        return "Rename association " + from + " to " + to;
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/operation/RenameEntity.java b/extensions/migration/src/main/java/org/qi4j/migration/operation/RenameEntity.java
deleted file mode 100644
index df17925..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/operation/RenameEntity.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.operation;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.migration.Migrator;
-import org.qi4j.migration.assembly.EntityMigrationOperation;
-import org.qi4j.spi.entitystore.helpers.JSONKeys;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * Rename an Entity type
- */
-public class RenameEntity
-    implements EntityMigrationOperation
-{
-    String fromName;
-    String toName;
-
-    public RenameEntity( String fromName, String toName )
-    {
-        this.fromName = fromName;
-        this.toName = toName;
-    }
-
-    @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        String type = state.getString( JSONKeys.TYPE );
-
-        if( type.equals( fromName ) )
-        {
-            migrator.changeEntityType( state, toName );
-            return true;
-        }
-        else
-        {
-            return false;
-        }
-    }
-
-    @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        String type = state.getString( JSONKeys.TYPE );
-
-        if( type.equals( toName ) )
-        {
-            migrator.changeEntityType( state, fromName );
-            return true;
-        }
-        else
-        {
-            return false;
-        }
-    }
-
-    @Override
-    public String toString()
-    {
-        return "Rename entity " + fromName + " to " + toName;
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/operation/RenameManyAssociation.java b/extensions/migration/src/main/java/org/qi4j/migration/operation/RenameManyAssociation.java
deleted file mode 100644
index 9a6e041..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/operation/RenameManyAssociation.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.operation;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.migration.Migrator;
-import org.qi4j.migration.assembly.EntityMigrationOperation;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * Rename a ManyAssociation
- */
-public class RenameManyAssociation
-    implements EntityMigrationOperation
-{
-    String from;
-    String to;
-
-    public RenameManyAssociation( String from, String to )
-    {
-        this.from = from;
-        this.to = to;
-    }
-
-    @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.renameManyAssociation( state, from, to );
-    }
-
-    @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.renameManyAssociation( state, to, from );
-    }
-
-    @Override
-    public String toString()
-    {
-        return "Rename many-association " + from + " to " + to;
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/operation/RenameNamedAssociation.java b/extensions/migration/src/main/java/org/qi4j/migration/operation/RenameNamedAssociation.java
deleted file mode 100644
index 6f1fff1..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/operation/RenameNamedAssociation.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.migration.operation;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.migration.Migrator;
-import org.qi4j.migration.assembly.EntityMigrationOperation;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * Rename a NamedAssociation
- */
-public class RenameNamedAssociation
-    implements EntityMigrationOperation
-{
-    private final String from;
-    private final String to;
-
-    public RenameNamedAssociation( String from, String to )
-    {
-        this.from = from;
-        this.to = to;
-    }
-
-    @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.renameNamedAssociation( state, from, to );
-    }
-
-    @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.renameNamedAssociation( state, to, from );
-    }
-
-    @Override
-    public String toString()
-    {
-        return "Rename named-association " + from + " to " + to;
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/operation/RenameProperty.java b/extensions/migration/src/main/java/org/qi4j/migration/operation/RenameProperty.java
deleted file mode 100644
index 99d6fbf..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/operation/RenameProperty.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.operation;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.migration.Migrator;
-import org.qi4j.migration.assembly.EntityMigrationOperation;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-
-/**
- * Rename a property
- */
-public class RenameProperty
-    implements EntityMigrationOperation
-{
-    String fromProperty;
-    String toProperty;
-
-    public RenameProperty( String fromProperty, String toProperty )
-    {
-        this.fromProperty = fromProperty;
-        this.toProperty = toProperty;
-    }
-
-    @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.renameProperty( state, fromProperty, toProperty );
-    }
-
-    @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
-    {
-        return migrator.renameProperty( state, toProperty, fromProperty );
-    }
-
-    @Override
-    public String toString()
-    {
-        return "Rename property " + fromProperty + " to " + toProperty;
-    }
-}
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/operation/package.html b/extensions/migration/src/main/java/org/qi4j/migration/operation/package.html
deleted file mode 100644
index 77115b0..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/operation/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Entities Migration Operations.</h2>
-    </body>
-</html>
diff --git a/extensions/migration/src/main/java/org/qi4j/migration/package.html b/extensions/migration/src/main/java/org/qi4j/migration/package.html
deleted file mode 100644
index 3eec608..0000000
--- a/extensions/migration/src/main/java/org/qi4j/migration/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Entities Migration Extension.</h2>
-    </body>
-</html>
diff --git a/extensions/migration/src/test/java/org/apache/polygene/migration/MigrationTest.java b/extensions/migration/src/test/java/org/apache/polygene/migration/MigrationTest.java
new file mode 100644
index 0000000..27fe187
--- /dev/null
+++ b/extensions/migration/src/test/java/org/apache/polygene/migration/MigrationTest.java
@@ -0,0 +1,259 @@
+/*
+ *  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.polygene.migration;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.stream.Stream;
+import javax.json.JsonObject;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.service.importer.NewObjectImporter;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.migration.assembly.MigrationBuilder;
+import org.apache.polygene.migration.assembly.MigrationContext;
+import org.apache.polygene.migration.assembly.MigrationOperation;
+import org.apache.polygene.spi.entitystore.BackupRestore;
+import org.apache.polygene.spi.entitystore.helpers.JSONKeys;
+import org.apache.polygene.spi.entitystore.helpers.StateStore;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Test;
+
+import static java.util.stream.Collectors.toList;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+/**
+ * JAVADOC
+ */
+public class MigrationTest
+    extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        new DefaultUnitOfWorkAssembler().assemble( module );
+
+        module.objects( MigrationEventLogger.class );
+        module.importedServices( MigrationEventLogger.class ).importedBy( NewObjectImporter.class );
+
+        module.entities( TestEntity1_0.class,
+                         TestEntity1_1.class,
+                         TestEntity2_0.class,
+                         org.apache.polygene.migration.moved.TestEntity2_0.class );
+
+        MigrationBuilder migration = new MigrationBuilder( "1.0" );
+        migration.
+            toVersion( "1.1" ).
+            renameEntity( TestEntity1_0.class.getName(), TestEntity1_1.class.getName() ).
+            atStartup( new CustomFixOperation( "Fix for 1.1" ) ).
+            forEntities( TestEntity1_1.class.getName() ).
+            renameProperty( "foo", "newFoo" ).
+            renameManyAssociation( "fooManyAssoc", "newFooManyAssoc" ).
+            renameAssociation( "fooAssoc", "newFooAssoc" ).
+            end().
+            toVersion( "2.0" ).
+            renameEntity( TestEntity1_1.class.getName(), TestEntity2_0.class.getName() ).
+            atStartup( new CustomFixOperation( "Fix for 2.0, 1" ) ).
+            atStartup( new CustomFixOperation( "Fix for 2.0, 2" ) ).
+            forEntities( TestEntity2_0.class.getName() ).
+            addProperty( "bar", "Some value" ).
+            removeProperty( "newFoo", "Some value" ).
+            custom( new CustomBarOperation() ).
+            end().
+            toVersion( "3.0" ).
+            renamePackage( "org.apache.polygene.migration", "org.apache.polygene.migration.moved" ).
+            withEntities( "TestEntity2_0" ).
+            end();
+
+        module.services( MigrationService.class ).setMetaInfo( migration );
+        module.entities( MigrationConfiguration.class );
+        module.forMixin( MigrationConfiguration.class ).declareDefaults().lastStartupVersion().set( "1.0" );
+    }
+
+    @Test
+    public void testMigration()
+        throws UnitOfWorkCompletionException, IOException, ActivationException, AssemblyException
+    {
+        Identity id;
+        // Set up version 1
+        List<String> data_v1;
+        {
+            SingletonAssembler v1 = new SingletonAssembler()
+            {
+                @Override
+                public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+                {
+                    MigrationTest.this.assemble( module );
+                    module.layer().application().setVersion( "1.0" );
+                }
+            };
+
+            UnitOfWork uow = v1.module().unitOfWorkFactory().newUnitOfWork();
+            TestEntity1_0 entity = uow.newEntity( TestEntity1_0.class );
+            entity.foo().set( "Some value" );
+            entity.fooManyAssoc().add( entity );
+            entity.fooAssoc().set( entity );
+            id = entity.identity().get();
+            uow.complete();
+
+            BackupRestore backupRestore = v1.module().findService( BackupRestore.class ).get();
+            try( Stream<String> backup = backupRestore.backup() )
+            {
+                data_v1 = backup.collect( toList() );
+            }
+        }
+
+        // Set up version 1.1
+        List<String> data_v1_1;
+        {
+            SingletonAssembler v1_1 = new SingletonAssembler()
+            {
+                @Override
+                public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+                {
+                    MigrationTest.this.assemble( module );
+                    module.layer().application().setVersion( "1.1" );
+                }
+            };
+
+            BackupRestore testData = v1_1.module().findService( BackupRestore.class ).get();
+            testData.restore( data_v1.stream() );
+
+            UnitOfWork uow = v1_1.module().unitOfWorkFactory().newUnitOfWork();
+            TestEntity1_1 entity = uow.get( TestEntity1_1.class, id );
+            assertThat( "Property has been renamed", entity.newFoo().get(), equalTo( "Some value" ) );
+            assertThat( "ManyAssociation has been renamed", entity.newFooManyAssoc().count(), equalTo( 1 ) );
+            assertThat( "Association has been renamed", entity.newFooAssoc().get(), equalTo( entity ) );
+            uow.complete();
+
+            try( Stream<String> backup = testData.backup() )
+            {
+                data_v1_1 = backup.collect( toList() );
+            }
+        }
+
+        // Set up version 2.0
+        {
+            SingletonAssembler v2_0 = new SingletonAssembler()
+            {
+                @Override
+                public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+                {
+                    MigrationTest.this.assemble( module );
+                    module.layer().application().setVersion( "2.0" );
+                }
+            };
+
+            BackupRestore testData = v2_0.module().findService( BackupRestore.class ).get();
+
+            // Test migration from 1.0 -> 2.0
+            {
+                testData.restore( data_v1.stream() );
+                UnitOfWork uow = v2_0.module().unitOfWorkFactory().newUnitOfWork();
+                TestEntity2_0 entity = uow.get( TestEntity2_0.class, id );
+                assertThat( "Property has been created", entity.bar().get(), equalTo( "Some value" ) );
+                assertThat( "Custom Property has been created", entity.customBar().get(), equalTo( "Hello Some value" ) );
+                assertThat( "ManyAssociation has been renamed", entity.newFooManyAssoc().count(), equalTo( 1 ) );
+                assertThat( "Association has been renamed", entity.newFooAssoc().get(), equalTo( entity ) );
+                uow.complete();
+            }
+        }
+
+        // Set up version 3.0
+        {
+            SingletonAssembler v3_0 = new SingletonAssembler()
+            {
+                @Override
+                public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+                {
+                    MigrationTest.this.assemble( module );
+                    module.layer().application().setVersion( "3.0" );
+                }
+            };
+
+            BackupRestore testData = v3_0.module().findService( BackupRestore.class ).get();
+            testData.restore( data_v1_1.stream() );
+
+            // Test migration from 1.0 -> 3.0
+            {
+                testData.restore( data_v1.stream() );
+                UnitOfWork uow = v3_0.module().unitOfWorkFactory().newUnitOfWork();
+                org.apache.polygene.migration.moved.TestEntity2_0 entity = uow.get( org.apache.polygene.migration.moved.TestEntity2_0.class, id );
+                uow.complete();
+            }
+        }
+    }
+
+    private static class CustomBarOperation
+        implements EntityMigrationOperation
+    {
+        @Override
+        public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore store, Migrator migrator )
+        {
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            return migrator.addProperty( context, state, "customBar", "Hello " + valueState.getString( "bar" ) );
+        }
+
+        @Override
+        public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore store, Migrator migrator )
+        {
+            return migrator.removeProperty( context, state, "customBar" );
+        }
+    }
+
+    private static class CustomFixOperation
+        implements MigrationOperation
+    {
+        String msg;
+
+        private CustomFixOperation( String msg )
+        {
+            this.msg = msg;
+        }
+
+        @Override
+        public void upgrade( StateStore stateStore, Migrator migrator )
+            throws IOException
+        {
+            System.out.println( msg );
+        }
+
+        @Override
+        public void downgrade( StateStore stateStore, Migrator migrator )
+            throws IOException
+        {
+            System.out.println( msg );
+        }
+    }
+}
diff --git a/extensions/migration/src/test/java/org/apache/polygene/migration/TestEntity1_0.java b/extensions/migration/src/test/java/org/apache/polygene/migration/TestEntity1_0.java
new file mode 100644
index 0000000..957b53d
--- /dev/null
+++ b/extensions/migration/src/test/java/org/apache/polygene/migration/TestEntity1_0.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.migration;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * JAVADOC
+ */
+public interface TestEntity1_0
+    extends EntityComposite
+{
+    @UseDefaults
+    Property<String> foo();
+
+    ManyAssociation<TestEntity1_0> fooManyAssoc();
+
+    @Optional
+    Association<TestEntity1_0> fooAssoc();
+}
diff --git a/extensions/migration/src/test/java/org/apache/polygene/migration/TestEntity1_1.java b/extensions/migration/src/test/java/org/apache/polygene/migration/TestEntity1_1.java
new file mode 100644
index 0000000..001eeb4
--- /dev/null
+++ b/extensions/migration/src/test/java/org/apache/polygene/migration/TestEntity1_1.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.migration;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * JAVADOC
+ */
+public interface TestEntity1_1
+    extends EntityComposite
+{
+    @UseDefaults
+    Property<String> newFoo();
+
+    ManyAssociation<TestEntity1_1> newFooManyAssoc();
+
+    @Optional
+    Association<TestEntity1_1> newFooAssoc();
+}
\ No newline at end of file
diff --git a/extensions/migration/src/test/java/org/apache/polygene/migration/TestEntity2_0.java b/extensions/migration/src/test/java/org/apache/polygene/migration/TestEntity2_0.java
new file mode 100644
index 0000000..08a72c4
--- /dev/null
+++ b/extensions/migration/src/test/java/org/apache/polygene/migration/TestEntity2_0.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.migration;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * JAVADOC
+ */
+public interface TestEntity2_0
+    extends EntityComposite
+{
+    @UseDefaults
+    Property<String> bar();
+
+    ManyAssociation<TestEntity2_0> newFooManyAssoc();
+
+    @Optional
+    Association<TestEntity2_0> newFooAssoc();
+
+    Property<String> customBar();
+}
\ No newline at end of file
diff --git a/extensions/migration/src/test/java/org/apache/polygene/migration/moved/TestEntity2_0.java b/extensions/migration/src/test/java/org/apache/polygene/migration/moved/TestEntity2_0.java
new file mode 100644
index 0000000..9f47833
--- /dev/null
+++ b/extensions/migration/src/test/java/org/apache/polygene/migration/moved/TestEntity2_0.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.migration.moved;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Moved from base package to here
+ */
+public interface TestEntity2_0
+    extends EntityComposite
+{
+    @UseDefaults
+    Property<String> bar();
+
+    ManyAssociation<TestEntity2_0> newFooManyAssoc();
+
+    @Optional
+    Association<TestEntity2_0> newFooAssoc();
+
+    Property<String> customBar();
+}
\ No newline at end of file
diff --git a/extensions/migration/src/test/java/org/qi4j/migration/MigrationTest.java b/extensions/migration/src/test/java/org/qi4j/migration/MigrationTest.java
deleted file mode 100644
index 5b6cbb7..0000000
--- a/extensions/migration/src/test/java/org/qi4j/migration/MigrationTest.java
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.StringReader;
-import org.hamcrest.CoreMatchers;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.service.importer.NewObjectImporter;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.migration.assembly.EntityMigrationOperation;
-import org.qi4j.migration.assembly.MigrationBuilder;
-import org.qi4j.migration.assembly.MigrationOperation;
-import org.qi4j.spi.entitystore.BackupRestore;
-import org.qi4j.spi.entitystore.helpers.JSONKeys;
-import org.qi4j.spi.entitystore.helpers.StateStore;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.assertThat;
-
-/**
- * JAVADOC
- */
-public class MigrationTest
-    extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-
-        module.objects( MigrationEventLogger.class );
-        module.importedServices( MigrationEventLogger.class ).importedBy( NewObjectImporter.class );
-
-        module.entities( TestEntity1_0.class,
-                         TestEntity1_1.class,
-                         TestEntity2_0.class,
-                         org.qi4j.migration.moved.TestEntity2_0.class );
-
-        MigrationBuilder migration = new MigrationBuilder( "1.0" );
-        migration.
-            toVersion( "1.1" ).
-            renameEntity( TestEntity1_0.class.getName(), TestEntity1_1.class.getName() ).
-            atStartup( new CustomFixOperation( "Fix for 1.1" ) ).
-            forEntities( TestEntity1_1.class.getName() ).
-            renameProperty( "foo", "newFoo" ).
-            renameManyAssociation( "fooManyAssoc", "newFooManyAssoc" ).
-            renameAssociation( "fooAssoc", "newFooAssoc" ).
-            end().
-            toVersion( "2.0" ).
-            renameEntity( TestEntity1_1.class.getName(), TestEntity2_0.class.getName() ).
-            atStartup( new CustomFixOperation( "Fix for 2.0, 1" ) ).
-            atStartup( new CustomFixOperation( "Fix for 2.0, 2" ) ).
-            forEntities( TestEntity2_0.class.getName() ).
-            addProperty( "bar", "Some value" ).
-            removeProperty( "newFoo", "Some value" ).
-            custom( new CustomBarOperation() ).
-            end().
-            toVersion( "3.0" ).
-            renamePackage( "org.qi4j.migration", "org.qi4j.migration.moved" ).
-            withEntities( "TestEntity2_0" ).
-            end();
-
-        module.services( MigrationService.class ).setMetaInfo( migration );
-        module.entities( MigrationConfiguration.class );
-        module.forMixin( MigrationConfiguration.class ).declareDefaults().lastStartupVersion().set( "1.0" );
-    }
-
-    @Test
-    public void testMigration()
-        throws UnitOfWorkCompletionException, IOException, ActivationException, AssemblyException
-    {
-        // Set up version 1
-        String id;
-        StringInputOutput data_v1 = new StringInputOutput();
-        {
-            SingletonAssembler v1 = new SingletonAssembler()
-            {
-                @Override
-                public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-                {
-                    MigrationTest.this.assemble( module );
-                    module.layer().application().setVersion( "1.0" );
-                }
-            };
-
-            UnitOfWork uow = v1.module().newUnitOfWork();
-            TestEntity1_0 entity = uow.newEntity( TestEntity1_0.class );
-            entity.foo().set( "Some value" );
-            entity.fooManyAssoc().add( entity );
-            entity.fooAssoc().set( entity );
-            id = entity.identity().get();
-            uow.complete();
-
-            BackupRestore backupRestore = v1.module()
-                .findService( BackupRestore.class )
-                .get();
-            backupRestore.backup().transferTo( data_v1 );
-        }
-
-        // Set up version 1.1
-        StringInputOutput data_v1_1 = new StringInputOutput();
-        {
-            SingletonAssembler v1_1 = new SingletonAssembler()
-            {
-                @Override
-                public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-                {
-                    MigrationTest.this.assemble( module );
-                    module.layer().application().setVersion( "1.1" );
-                }
-            };
-
-            BackupRestore testData = v1_1.module().findService( BackupRestore.class ).get();
-            data_v1.transferTo( testData.restore() );
-
-            UnitOfWork uow = v1_1.module().newUnitOfWork();
-            TestEntity1_1 entity = uow.get( TestEntity1_1.class, id );
-            assertThat( "Property has been renamed", entity.newFoo().get(), CoreMatchers.equalTo( "Some value" ) );
-            assertThat( "ManyAssociation has been renamed", entity.newFooManyAssoc().count(), CoreMatchers.equalTo( 1 ) );
-            assertThat( "Association has been renamed", entity.newFooAssoc().get(), CoreMatchers.equalTo( entity ) );
-            uow.complete();
-
-            testData.backup().transferTo( data_v1_1 );
-        }
-
-        // Set up version 2.0
-        {
-            SingletonAssembler v2_0 = new SingletonAssembler()
-            {
-                @Override
-                public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-                {
-                    MigrationTest.this.assemble( module );
-                    module.layer().application().setVersion( "2.0" );
-                }
-            };
-
-            BackupRestore testData = v2_0.module().findService( BackupRestore.class ).get();
-
-            // Test migration from 1.0 -> 2.0
-            {
-                data_v1.transferTo( testData.restore() );
-                UnitOfWork uow = v2_0.module().newUnitOfWork();
-                TestEntity2_0 entity = uow.get( TestEntity2_0.class, id );
-                assertThat( "Property has been created", entity.bar().get(), CoreMatchers.equalTo( "Some value" ) );
-                assertThat( "Custom Property has been created", entity.customBar().get(), CoreMatchers.equalTo( "Hello Some value" ) );
-                assertThat( "ManyAssociation has been renamed", entity.newFooManyAssoc().count(), CoreMatchers.equalTo( 1 ) );
-                assertThat( "Association has been renamed", entity.newFooAssoc().get(), CoreMatchers.equalTo( entity ) );
-                uow.complete();
-            }
-        }
-
-        // Set up version 3.0
-        {
-            SingletonAssembler v3_0 = new SingletonAssembler()
-            {
-                @Override
-                public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-                {
-                    MigrationTest.this.assemble( module );
-                    module.layer().application().setVersion( "3.0" );
-                }
-            };
-
-            BackupRestore testData = v3_0.module().findService( BackupRestore.class ).get();
-            data_v1_1.transferTo( testData.restore() );
-
-            // Test migration from 1.0 -> 3.0
-            {
-                data_v1.transferTo( testData.restore() );
-                UnitOfWork uow = v3_0.module().newUnitOfWork();
-                org.qi4j.migration.moved.TestEntity2_0 entity = uow.get( org.qi4j.migration.moved.TestEntity2_0.class, id );
-                uow.complete();
-            }
-        }
-    }
-
-    private static class CustomBarOperation
-        implements EntityMigrationOperation
-    {
-        @Override
-        public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-            throws JSONException
-        {
-            JSONObject properties = (JSONObject) state.get( JSONKeys.PROPERTIES );
-
-            return migrator.addProperty( state, "customBar", "Hello " + properties.getString( "bar" ) );
-        }
-
-        @Override
-        public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-            throws JSONException
-        {
-            return migrator.removeProperty( state, "customBar" );
-        }
-    }
-
-    private static class CustomFixOperation
-        implements MigrationOperation
-    {
-        String msg;
-
-        private CustomFixOperation( String msg )
-        {
-            this.msg = msg;
-        }
-
-        @Override
-        public void upgrade( StateStore stateStore, Migrator migrator )
-            throws IOException
-        {
-            System.out.println( msg );
-        }
-
-        @Override
-        public void downgrade( StateStore stateStore, Migrator migrator )
-            throws IOException
-        {
-            System.out.println( msg );
-        }
-    }
-
-    private static class StringInputOutput
-        implements Output<String, IOException>, Input<String, IOException>
-    {
-        final StringBuilder builder = new StringBuilder();
-
-        @Override
-        public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends String, SenderThrowableType> sender )
-            throws IOException, SenderThrowableType
-        {
-            sender.sendTo( new Receiver<String, IOException>()
-            {
-                @Override
-                public void receive( String item )
-                    throws IOException
-                {
-                    builder.append( item ).append( "\n" );
-                }
-            } );
-        }
-
-        @Override
-        public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super String, ReceiverThrowableType> output )
-            throws IOException, ReceiverThrowableType
-        {
-            output.receiveFrom( new Sender<String, IOException>()
-            {
-                @Override
-                public <ReceiverThrowableType extends Throwable> void sendTo( Receiver<? super String, ReceiverThrowableType> receiver )
-                    throws ReceiverThrowableType, IOException
-                {
-                    BufferedReader reader = new BufferedReader( new StringReader( builder.toString() ) );
-                    String line;
-                    try
-                    {
-                        while( ( line = reader.readLine() ) != null )
-                        {
-                            receiver.receive( line );
-                        }
-                    }
-                    finally
-                    {
-                        reader.close();
-                    }
-                }
-            } );
-        }
-
-        @Override
-        public String toString()
-        {
-            return builder.toString();
-        }
-    }
-
-}
diff --git a/extensions/migration/src/test/java/org/qi4j/migration/TestEntity1_0.java b/extensions/migration/src/test/java/org/qi4j/migration/TestEntity1_0.java
deleted file mode 100644
index 86d8907..0000000
--- a/extensions/migration/src/test/java/org/qi4j/migration/TestEntity1_0.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-
-/**
- * JAVADOC
- */
-public interface TestEntity1_0
-    extends EntityComposite
-{
-    @UseDefaults
-    Property<String> foo();
-
-    ManyAssociation<TestEntity1_0> fooManyAssoc();
-
-    @Optional
-    Association<TestEntity1_0> fooAssoc();
-}
diff --git a/extensions/migration/src/test/java/org/qi4j/migration/TestEntity1_1.java b/extensions/migration/src/test/java/org/qi4j/migration/TestEntity1_1.java
deleted file mode 100644
index 23492e1..0000000
--- a/extensions/migration/src/test/java/org/qi4j/migration/TestEntity1_1.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-
-/**
- * JAVADOC
- */
-public interface TestEntity1_1
-    extends EntityComposite
-{
-    @UseDefaults
-    Property<String> newFoo();
-
-    ManyAssociation<TestEntity1_1> newFooManyAssoc();
-
-    @Optional
-    Association<TestEntity1_1> newFooAssoc();
-}
\ No newline at end of file
diff --git a/extensions/migration/src/test/java/org/qi4j/migration/TestEntity2_0.java b/extensions/migration/src/test/java/org/qi4j/migration/TestEntity2_0.java
deleted file mode 100644
index aa2bda5..0000000
--- a/extensions/migration/src/test/java/org/qi4j/migration/TestEntity2_0.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.property.Property;
-
-/**
- * JAVADOC
- */
-public interface TestEntity2_0
-    extends EntityComposite
-{
-    @UseDefaults
-    Property<String> bar();
-
-    ManyAssociation<TestEntity2_0> newFooManyAssoc();
-
-    @Optional
-    Association<TestEntity2_0> newFooAssoc();
-
-    Property<String> customBar();
-}
\ No newline at end of file
diff --git a/extensions/migration/src/test/java/org/qi4j/migration/moved/TestEntity2_0.java b/extensions/migration/src/test/java/org/qi4j/migration/moved/TestEntity2_0.java
deleted file mode 100644
index 018e286..0000000
--- a/extensions/migration/src/test/java/org/qi4j/migration/moved/TestEntity2_0.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.migration.moved;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.property.Property;
-
-/**
- * Moved from base package to here
- */
-public interface TestEntity2_0
-    extends EntityComposite
-{
-    @UseDefaults
-    Property<String> bar();
-
-    ManyAssociation<TestEntity2_0> newFooManyAssoc();
-
-    @Optional
-    Association<TestEntity2_0> newFooAssoc();
-
-    Property<String> customBar();
-}
\ No newline at end of file
diff --git a/extensions/reindexer/build.gradle b/extensions/reindexer/build.gradle
index 018ace0..f956f60 100644
--- a/extensions/reindexer/build.gradle
+++ b/extensions/reindexer/build.gradle
@@ -1,32 +1,37 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-jar { manifest { description = "Apache Zest™ Reindexer Extension" }}
+apply plugin: 'polygene-extension'
+
+jar { manifest { description = "Apache Polygene™ Reindexer Extension" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.spi"))
-  compile(libraries.slf4j_api)
+  api polygene.core.spi
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-  testCompile(project(':org.qi4j.extensions:org.qi4j.extension.entitystore-jdbm'))
-  testCompile(project(':org.qi4j.extensions:org.qi4j.extension.indexing-rdf'))
+  implementation libraries.slf4j_api
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+  testImplementation polygene.extension( 'entitystore-jdbm' )
+  testImplementation polygene.extension( 'indexing-rdf' )
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/extensions/reindexer/dev-status.xml b/extensions/reindexer/dev-status.xml
index f6b60e4..40cdc31 100644
--- a/extensions/reindexer/dev-status.xml
+++ b/extensions/reindexer/dev-status.xml
@@ -1,30 +1,33 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
         <!--none,early,beta,stable,mature-->
         <codebase>stable</codebase>
 
         <!-- none, brief, good, complete -->
-        <documentation>none</documentation>
+        <documentation>brief</documentation>
 
         <!-- none, some, good, complete -->
         <unittests>some</unittests>
diff --git a/extensions/reindexer/src/docs/reindexer.txt b/extensions/reindexer/src/docs/reindexer.txt
index 7e8a73b..e8f19ed 100644
--- a/extensions/reindexer/src/docs/reindexer.txt
+++ b/extensions/reindexer/src/docs/reindexer.txt
@@ -25,8 +25,40 @@
 source=extensions/reindexer/dev-status.xml
 --------------
 
-Reindexer
-
-NOTE: This Extension has no documentation yet. Learn how to contribute in <<community-docs>>.
+This extension allows you to trigger a complete indexing of EntityStores into Index/Query systems.
 
 include::../../build/docs/buildinfo/artifact.txt[]
+
+The `Reindexer` is totally under your control and doesn't kick in automatically in any way or form.
+
+[snippet,java]
+----
+source=extensions/reindexer/src/test/java/org/apache/polygene/index/reindexer/ReindexerTest.java
+tag=assembly
+----
+
+It will be bound to the `EntityStore` that is Visible, ask for all Entities, by calling
+`entityStates()` and forward those to all `StateChangeListeners` that are Visible.
+
+[snippet,java]
+----
+source=extensions/reindexer/src/test/java/org/apache/polygene/index/reindexer/ReindexerTest.java
+tag=usage
+----
+
+So, you call `reindex()` on the `Reindexer`. If you have many reindexers, you could call
+`reindexAll()` which will locate all reindexers and call `reindex()`
+on each. This is useful when there are many modules of entity stores.
+
+There are two general issues that you need to keep in mind;
+
+1. Not all entity stores implements `entityStates()`, mostly because the
+   underlying store doesn't provide a convenient mechanism to iterate
+   everything.
+
+2. Unless you first clear all in the Index, deletions will not be
+   detected, and therefor the index might contain to many entity references in
+   that case.
+
+Additionally, reindexing is not really thread safe, so need to bring the
+system down while reindexing is happening.
diff --git a/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/ReindexAllService.java b/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/ReindexAllService.java
new file mode 100644
index 0000000..5f1cffe
--- /dev/null
+++ b/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/ReindexAllService.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.index.reindexer;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.index.reindexer.internal.ReindexAllMixin;
+
+@Mixins( ReindexAllMixin.class )
+public interface ReindexAllService
+    extends Reindexer
+{
+}
diff --git a/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/Reindexer.java b/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/Reindexer.java
new file mode 100644
index 0000000..76eb9c2
--- /dev/null
+++ b/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/Reindexer.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.index.reindexer;
+
+/**
+ * Service to re-index all visible EntityStores against all visible StateChangeListeners (i.e. Indexers).
+ */
+public interface Reindexer
+{
+    void reindex();
+}
diff --git a/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/ReindexerConfiguration.java b/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/ReindexerConfiguration.java
new file mode 100644
index 0000000..18ace74
--- /dev/null
+++ b/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/ReindexerConfiguration.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.index.reindexer;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+
+public interface ReindexerConfiguration
+{
+    /**
+     * How many EntityStates should be sent to the indexer at a time.
+     * High value improves performance, but risks of running out of memory.
+     *
+     * If not specified, the value of 50 will be used.
+     *
+     * @return the property containing the loadValue.
+     */
+    @Optional
+    Property<Integer> loadValue();
+}
diff --git a/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/ReindexerService.java b/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/ReindexerService.java
new file mode 100644
index 0000000..0c6a2da
--- /dev/null
+++ b/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/ReindexerService.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.index.reindexer;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.index.reindexer.internal.ReindexerMixin;
+
+@Mixins( ReindexerMixin.class )
+public interface ReindexerService
+    extends Reindexer
+{
+}
diff --git a/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/internal/ReindexAllMixin.java b/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/internal/ReindexAllMixin.java
new file mode 100644
index 0000000..5c5357e
--- /dev/null
+++ b/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/internal/ReindexAllMixin.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.index.reindexer.internal;
+
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.index.reindexer.Reindexer;
+
+public class ReindexAllMixin
+    implements Reindexer
+{
+    @Service
+    private Iterable<ServiceReference<Reindexer>> reindexers;
+    @Uses
+    private ServiceDescriptor descriptor;
+
+    @Override
+    public void reindex()
+    {
+        for( ServiceReference<Reindexer> ref : reindexers )
+        {
+            if( !ref.identity().equals( descriptor.identity() ) )
+            {
+                ref.get().reindex();
+            }
+        }
+    }
+}
diff --git a/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/internal/ReindexerMixin.java b/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/internal/ReindexerMixin.java
new file mode 100644
index 0000000..8342323
--- /dev/null
+++ b/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/internal/ReindexerMixin.java
@@ -0,0 +1,113 @@
+/*
+ *  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.polygene.index.reindexer.internal;
+
+import java.util.ArrayList;
+import java.util.stream.Stream;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.index.reindexer.Reindexer;
+import org.apache.polygene.index.reindexer.ReindexerConfiguration;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.StateChangeListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ReindexerMixin
+    implements Reindexer
+{
+    @This
+    private Configuration<ReindexerConfiguration> configuration;
+
+    @Service
+    private EntityStore store;
+
+    @Service
+    private Iterable<ServiceReference<StateChangeListener>> listeners;
+
+    @Structure
+    private ModuleDescriptor module;
+
+    private Logger logger = LoggerFactory.getLogger( Reindexer.class );
+
+    @Override
+    public void reindex()
+    {
+        configuration.refresh();
+        ReindexerConfiguration conf = configuration.get();
+        Integer loadValue = conf.loadValue().get();
+        if( loadValue == null )
+        {
+            loadValue = 50;
+        }
+        ReindexerHelper helper = new ReindexerHelper( loadValue );
+        helper.reindex( store );
+    }
+
+    private class ReindexerHelper
+    {
+        private int count;
+        private int loadValue;
+        private ArrayList<EntityState> states;
+
+        private ReindexerHelper( int loadValue )
+        {
+            this.loadValue = loadValue;
+            states = new ArrayList<>();
+        }
+
+        private void reindex( EntityStore store )
+        {
+            try( Stream<EntityState> entityStates = store.entityStates( module ) )
+            {
+                entityStates
+                    .forEach( entityState ->
+                              {
+                                  count++;
+                                  entityState.setPropertyValue( HasIdentity.IDENTITY_STATE_NAME,
+                                                                entityState.entityReference().identity() );
+                                  states.add( entityState );
+                                  if( states.size() >= loadValue )
+                                  {
+                                      reindexState();
+                                  }
+                              } );
+            }
+            reindexState();
+        }
+
+        private void reindexState()
+        {
+            for( ServiceReference<StateChangeListener> listener : listeners )
+            {
+                listener.get().notifyChanges( states );
+            }
+            states.clear();
+            logger.debug( "Reindexed " + count + " entities" );
+        }
+    }
+}
diff --git a/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/internal/package.html b/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/internal/package.html
new file mode 100644
index 0000000..0db3803
--- /dev/null
+++ b/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/internal/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Entities Reindexer Extension Internal Package.</h2>
+    </body>
+</html>
diff --git a/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/package.html b/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/package.html
new file mode 100644
index 0000000..a4c0550
--- /dev/null
+++ b/extensions/reindexer/src/main/java/org/apache/polygene/index/reindexer/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Entities Reindexer Extension.</h2>
+    </body>
+</html>
diff --git a/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/ReindexAllService.java b/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/ReindexAllService.java
deleted file mode 100644
index 7ba931b..0000000
--- a/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/ReindexAllService.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.index.reindexer;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.index.reindexer.internal.ReindexAllMixin;
-
-@Mixins( ReindexAllMixin.class )
-public interface ReindexAllService
-    extends Reindexer, ServiceComposite
-{
-}
diff --git a/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/Reindexer.java b/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/Reindexer.java
deleted file mode 100644
index adb5d3c..0000000
--- a/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/Reindexer.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.index.reindexer;
-
-/**
- * Service to re-index all visible EntityStores against all visible StateChangeListeners (i.e. Indexers).
- */
-public interface Reindexer
-{
-    void reindex();
-}
diff --git a/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/ReindexerConfiguration.java b/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/ReindexerConfiguration.java
deleted file mode 100644
index 57d7d12..0000000
--- a/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/ReindexerConfiguration.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.index.reindexer;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-public interface ReindexerConfiguration
-    extends ConfigurationComposite
-{
-    /**
-     * How many EntityStates should be sent to the indexer at a time.
-     * High value improves performance, but risks of running out of memory.
-     *
-     * If not specified, the value of 50 will be used.
-     *
-     * @return the property containing the loadValue.
-     */
-    @Optional
-    Property<Integer> loadValue();
-}
diff --git a/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/ReindexerService.java b/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/ReindexerService.java
deleted file mode 100644
index fac3888..0000000
--- a/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/ReindexerService.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.index.reindexer;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.index.reindexer.internal.ReindexerMixin;
-
-@Mixins( ReindexerMixin.class )
-public interface ReindexerService
-    extends Reindexer, ServiceComposite
-{
-}
diff --git a/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/internal/ReindexAllMixin.java b/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/internal/ReindexAllMixin.java
deleted file mode 100644
index a948d10..0000000
--- a/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/internal/ReindexAllMixin.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.index.reindexer.internal;
-
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.index.reindexer.Reindexer;
-
-public class ReindexAllMixin
-    implements Reindexer
-{
-    @Service
-    private Iterable<ServiceReference<Reindexer>> reindexers;
-    @Uses
-    private ServiceDescriptor descriptor;
-
-    @Override
-    public void reindex()
-    {
-        for( ServiceReference<Reindexer> ref : reindexers )
-        {
-            if( !ref.identity().equals( descriptor.identity() ) )
-            {
-                ref.get().reindex();
-            }
-        }
-    }
-}
diff --git a/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/internal/ReindexerMixin.java b/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/internal/ReindexerMixin.java
deleted file mode 100644
index 5638cd3..0000000
--- a/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/internal/ReindexerMixin.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.index.reindexer.internal;
-
-import java.util.ArrayList;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.index.reindexer.Reindexer;
-import org.qi4j.index.reindexer.ReindexerConfiguration;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.StateChangeListener;
-import org.qi4j.spi.module.ModuleSpi;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ReindexerMixin
-    implements Reindexer
-{
-    private static QualifiedName identityQN;
-
-    static
-    {
-        try
-        {
-            identityQN = QualifiedName.fromAccessor( Identity.class.getMethod( "identity" ) );
-        }
-        catch( NoSuchMethodException e )
-        {
-            throw new InternalError( "Zest Core Runtime codebase is corrupted. Contact Zest team: ReindexerMixin" );
-        }
-    }
-
-    @This
-    private Configuration<ReindexerConfiguration> configuration;
-
-    @Service
-    private EntityStore store;
-
-    @Service
-    private Iterable<ServiceReference<StateChangeListener>> listeners;
-
-    @Structure
-    private ModuleSpi module;
-
-    private Logger logger = LoggerFactory.getLogger( Reindexer.class );
-
-    @Override
-    public void reindex()
-    {
-        configuration.refresh();
-        ReindexerConfiguration conf = configuration.get();
-        Integer loadValue = conf.loadValue().get();
-        if( loadValue == null )
-        {
-            loadValue = 50;
-        }
-        new ReindexerOutput( loadValue ).reindex( store );
-    }
-
-    private class ReindexerOutput
-        implements Output<EntityState, RuntimeException>, Receiver<EntityState, RuntimeException>
-    {
-        private int count;
-        private int loadValue;
-        private ArrayList<EntityState> states;
-
-        public ReindexerOutput( Integer loadValue )
-        {
-            this.loadValue = loadValue;
-            states = new ArrayList<>();
-        }
-
-        public void reindex( EntityStore store )
-        {
-
-            store.entityStates( module ).transferTo( this );
-            reindexState();
-        }
-
-        @Override
-        public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends EntityState, SenderThrowableType> sender )
-            throws RuntimeException, SenderThrowableType
-        {
-            sender.sendTo( this );
-            reindexState();
-        }
-
-        @Override
-        public void receive( EntityState item )
-            throws RuntimeException
-        {
-            count++;
-            item.setPropertyValue( identityQN, item.identity().identity() );
-            states.add( item );
-
-            if( states.size() >= loadValue )
-            {
-                reindexState();
-            }
-        }
-
-        public void reindexState()
-        {
-            for( ServiceReference<StateChangeListener> listener : listeners )
-            {
-                listener.get().notifyChanges( states );
-            }
-            states.clear();
-            logger.debug( "Reindexed " + count + " entities" );
-        }
-    }
-}
diff --git a/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/internal/package.html b/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/internal/package.html
deleted file mode 100644
index 0d52529..0000000
--- a/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/internal/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Entities Reindexer Extension Internal Package.</h2>
-    </body>
-</html>
diff --git a/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/package.html b/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/package.html
deleted file mode 100644
index 5a02687..0000000
--- a/extensions/reindexer/src/main/java/org/qi4j/index/reindexer/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Entities Reindexer Extension.</h2>
-    </body>
-</html>
diff --git a/extensions/reindexer/src/test/java/org/apache/polygene/index/reindexer/ReindexerTest.java b/extensions/reindexer/src/test/java/org/apache/polygene/index/reindexer/ReindexerTest.java
new file mode 100644
index 0000000..38c91a8
--- /dev/null
+++ b/extensions/reindexer/src/test/java/org/apache/polygene/index/reindexer/ReindexerTest.java
@@ -0,0 +1,138 @@
+/*
+ *  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.polygene.index.reindexer;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.jdbm.JdbmConfiguration;
+import org.apache.polygene.entitystore.jdbm.assembly.JdbmEntityStoreAssembler;
+import org.apache.polygene.index.rdf.assembly.RdfNativeSesameStoreAssembler;
+import org.apache.polygene.library.rdf.repository.NativeConfiguration;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import static org.apache.polygene.api.query.QueryExpressions.eq;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+import static org.junit.Assert.assertEquals;
+
+public class ReindexerTest
+    extends AbstractPolygeneTest
+{
+    private static final String ENTITIES_DIR = "polygene-entities";
+    private static final String INDEX_DIR = "polygene-index";
+
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // JDBM EntityStore
+        new JdbmEntityStoreAssembler().assemble( module );
+
+        // Native Sesame EntityFinder
+        new RdfNativeSesameStoreAssembler().assemble( module );
+
+        // Reindexer
+        // START SNIPPET: assembly
+        module.services( ReindexerService.class );
+        // END SNIPPET: assembly
+
+        // Configuration
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+        config.entities( JdbmConfiguration.class, NativeConfiguration.class, ReindexerConfiguration.class )
+              .visibleIn( Visibility.layer );
+        config.forMixin( JdbmConfiguration.class ).declareDefaults()
+              .file().set( new File( tmpDir.getRoot(), ENTITIES_DIR ).getAbsolutePath() );
+        config.forMixin( NativeConfiguration.class ).declareDefaults()
+              .dataDirectory().set( new File( tmpDir.getRoot(), INDEX_DIR ).getAbsolutePath() );
+
+        // Test entity
+        module.entities( MyEntity.class );
+    }
+
+    private static final String TEST_NAME = "foo";
+
+    public interface MyEntity extends EntityComposite
+    {
+
+        Property<String> name();
+    }
+
+    @Test
+    public void createDataWipeIndexReindexAndAssertData()
+        throws UnitOfWorkCompletionException, IOException
+    {
+
+        // ----> Create data and wipe index
+
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+
+        EntityBuilder<MyEntity> eBuilder = uow.newEntityBuilder( MyEntity.class );
+        MyEntity e = eBuilder.instance();
+        e.name().set( TEST_NAME );
+        e = eBuilder.newInstance();
+
+        uow.complete();
+
+        // Wipe the index data on disk
+        try( Stream<Path> files = Files.walk( new File( tmpDir.getRoot(), INDEX_DIR ).getAbsoluteFile().toPath() ) )
+        {
+            files.map( Path::toFile ).forEach( File::delete );
+        }
+
+
+        // ----> Reindex and assert data
+
+        // START SNIPPET: usage
+        Reindexer reindexer = serviceFinder.findService( Reindexer.class ).get();
+        reindexer.reindex();
+        // END SNIPPET: usage
+
+        uow = unitOfWorkFactory.newUnitOfWork();
+
+        QueryBuilder<MyEntity> qBuilder = queryBuilderFactory.newQueryBuilder( MyEntity.class );
+        qBuilder = qBuilder.where( eq( templateFor( MyEntity.class ).name(), TEST_NAME ) );
+        Query<MyEntity> q = uow.newQuery( qBuilder );
+
+        assertEquals( 1, q.count() );
+        assertEquals( TEST_NAME, q.iterator().next().name().get() );
+
+        uow.complete();
+    }
+}
diff --git a/extensions/reindexer/src/test/java/org/qi4j/index/reindexer/ReindexerTest.java b/extensions/reindexer/src/test/java/org/qi4j/index/reindexer/ReindexerTest.java
deleted file mode 100644
index 923151d..0000000
--- a/extensions/reindexer/src/test/java/org/qi4j/index/reindexer/ReindexerTest.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright 2010 Paul Merlin.
- *
- * Licensed  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.qi4j.index.reindexer;
-
-import info.aduna.io.FileUtil;
-import java.io.File;
-import org.apache.tools.ant.util.FileUtils;
-import org.junit.AfterClass;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.jdbm.JdbmConfiguration;
-import org.qi4j.entitystore.jdbm.assembly.JdbmEntityStoreAssembler;
-import org.qi4j.index.rdf.assembly.RdfNativeSesameStoreAssembler;
-import org.qi4j.library.rdf.repository.NativeConfiguration;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.api.query.QueryExpressions.eq;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-@SuppressWarnings( "PublicInnerClass" )
-public class ReindexerTest
-        extends AbstractQi4jTest
-{
-
-    @SuppressWarnings( "unchecked" )
-    public void assemble( ModuleAssembly module )
-            throws AssemblyException
-    {
-        // JDBM EntityStore
-        new JdbmEntityStoreAssembler().assemble( module );
-
-        // Native Sesame EntityFinder
-        new RdfNativeSesameStoreAssembler().assemble( module );
-
-        // Reindexer
-        module.services( ReindexerService.class );
-
-        // Configuration
-        ModuleAssembly config = module.layer().module( "config" );
-        new EntityTestAssembler().assemble( config );
-        config.entities( JdbmConfiguration.class, NativeConfiguration.class, ReindexerConfiguration.class ).visibleIn( Visibility.layer );
-
-        // Test entity
-        module.entities( MyEntity.class );
-
-    }
-
-    private static final String TEST_NAME = "foo";
-
-    public static interface MyEntity
-            extends EntityComposite
-    {
-
-        Property<String> name();
-
-    }
-
-    @Test
-    public void createDataWipeIndexReindexAndAssertData()
-            throws UnitOfWorkCompletionException
-    {
-        File rdfDir = new File( System.getProperty( "user.dir" ), "build/testdata/qi4j-index" ).getAbsoluteFile();
-        rdfDir.mkdirs();
-        assertThat( rdfDir.exists(), is(true) );
-
-        // ----> Create data and wipe index
-
-        UnitOfWork uow = module.newUnitOfWork();
-
-        EntityBuilder<MyEntity> eBuilder = uow.newEntityBuilder( MyEntity.class );
-        MyEntity e = eBuilder.instance();
-        e.name().set( TEST_NAME );
-        e = eBuilder.newInstance();
-
-        uow.complete();
-
-        deleteIndexData(); // Wipe the index data on disk
-        rdfDir.mkdirs();
-
-
-        // ----> Reindex and assert data
-
-        module.<ReindexerService>findService( ReindexerService.class ).get().reindex(); // Reindex
-
-        uow = module.newUnitOfWork();
-
-        QueryBuilder<MyEntity> qBuilder = module.newQueryBuilder( MyEntity.class );
-        qBuilder = qBuilder.where( eq( templateFor( MyEntity.class ).name(), TEST_NAME ) );
-        Query<MyEntity> q = uow.newQuery( qBuilder );
-
-        assertEquals( 1, q.count() );
-        assertEquals( TEST_NAME, q.iterator().next().name().get() );
-
-        uow.complete();
-    }
-
-    @AfterClass
-    @SuppressWarnings( "AssignmentReplaceableWithOperatorAssignment" )
-    public static void afterClass()
-            throws Exception
-    {
-        boolean success = true;
-        success = deleteEntitiesData();
-        success = success & deleteIndexData();
-        if ( !success ) {
-            throw new Exception( "Could not delete test data" );
-        }
-
-    }
-
-    private static boolean deleteEntitiesData()
-    {
-        boolean success = true;
-        File esDir = new File( System.getProperty( "user.dir" ), "build/testdata/qi4j-entities" ).getAbsoluteFile();
-        if ( esDir.exists() ) {
-            success = FileUtil.deltree( esDir );
-        }
-        return success;
-    }
-
-    private static boolean deleteIndexData()
-    {
-        boolean success = true;
-        File rdfDir = new File( System.getProperty( "user.dir" ), "build/testdata/qi4j-index" ).getAbsoluteFile();
-        if ( rdfDir.exists() ) {
-            FileUtils.delete( rdfDir );
-            success = FileUtil.deltree( rdfDir );
-        }
-        return success;
-    }
-
-}
diff --git a/extensions/reindexer/src/test/resources/org/qi4j/entitystore/jdbm/JdbmEntityStoreService.properties b/extensions/reindexer/src/test/resources/org/qi4j/entitystore/jdbm/JdbmEntityStoreService.properties
deleted file mode 100644
index 514c133..0000000
--- a/extensions/reindexer/src/test/resources/org/qi4j/entitystore/jdbm/JdbmEntityStoreService.properties
+++ /dev/null
@@ -1,16 +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.
-
-file=build/testdata/qi4j-entities/qi4j-entities
\ No newline at end of file
diff --git a/extensions/reindexer/src/test/resources/org/qi4j/library/rdf/repository/rdf-indexing.properties b/extensions/reindexer/src/test/resources/org/qi4j/library/rdf/repository/rdf-indexing.properties
deleted file mode 100644
index ddd352d..0000000
--- a/extensions/reindexer/src/test/resources/org/qi4j/library/rdf/repository/rdf-indexing.properties
+++ /dev/null
@@ -1,16 +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.
-
-dataDirectory=build/testdata/qi4j-index
\ No newline at end of file
diff --git a/extensions/serialization-javaxjson/build.gradle b/extensions/serialization-javaxjson/build.gradle
new file mode 100644
index 0000000..e93e5fc
--- /dev/null
+++ b/extensions/serialization-javaxjson/build.gradle
@@ -0,0 +1,34 @@
+/*
+ *  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.
+ */
+
+apply plugin: 'polygene-extension'
+
+description = "Apache Polygene™ javax.json Serialization Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - Serialization - javax.json" } }
+
+dependencies {
+  api polygene.core.bootstrap
+
+  runtimeOnly polygene.core.runtime
+  runtimeOnly libraries.johnzon
+
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/extensions/serialization-javaxjson/dev-status.xml b/extensions/serialization-javaxjson/dev-status.xml
new file mode 100644
index 0000000..a36ce79
--- /dev/null
+++ b/extensions/serialization-javaxjson/dev-status.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
+    <status>
+        <!--none,early,beta,stable,mature-->
+        <codebase>beta</codebase>
+
+        <!-- none, brief, good, complete -->
+        <documentation>brief</documentation>
+
+        <!-- none, some, good, complete -->
+        <unittests>good</unittests>
+    </status>
+    <licenses>
+        <license>ALv2</license>
+    </licenses>
+</module>
\ No newline at end of file
diff --git a/extensions/serialization-javaxjson/src/docs/serialization-javaxjson.txt b/extensions/serialization-javaxjson/src/docs/serialization-javaxjson.txt
new file mode 100644
index 0000000..60cfa30
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/docs/serialization-javaxjson.txt
@@ -0,0 +1,49 @@
+///////////////////////////////////////////////////////////////
+ * 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.
+///////////////////////////////////////////////////////////////
+
+[[extension-serialization-javaxjson,javax.json serialization]]
+= javax.json serialization =
+
+[devstatus]
+--------------
+source=extensions/serialization-javaxjson/dev-status.xml
+--------------
+
+`Serialization` service backed by `javax.json` types.
+See <<core-api-serialization>> and <<core-spi-serialization>>.
+
+include::../../build/docs/buildinfo/artifact.txt[]
+
+This extension comes with https://johnzon.apache.org/[Apache Johnzon] as a default `javax.json` provider.
+You can exclude its dependency and replace it by the one of your choice.
+
+// TODO Include sample model and its output from test code & resources
+
+== Assembly ==
+
+Assembly is done using the provided Assembler:
+
+[snippet,java]
+----
+source=extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonValueCompositeSerializationTest.java
+tag=assembly
+----
+
+Note that this assembler is optional as Polygene assemble this service by default if no Serialization service is declared.
+
diff --git a/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/assembly/JavaxJsonSerializationAssembler.java b/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/assembly/JavaxJsonSerializationAssembler.java
new file mode 100644
index 0000000..10a8622
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/assembly/JavaxJsonSerializationAssembler.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.serialization.javaxjson.assembly;
+
+import org.apache.polygene.api.serialization.Converters;
+import org.apache.polygene.api.serialization.Deserializer;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonAdapters;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonSerialization;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonSettings;
+import org.apache.polygene.spi.serialization.JsonDeserializer;
+import org.apache.polygene.spi.serialization.JsonSerialization;
+import org.apache.polygene.spi.serialization.JsonSerializer;
+
+public class JavaxJsonSerializationAssembler extends Assemblers.VisibilityIdentity<JavaxJsonSerializationAssembler>
+{
+    private JavaxJsonSettings settings;
+
+    public JavaxJsonSerializationAssembler withJsonSettings( JavaxJsonSettings settings )
+    {
+        this.settings = settings;
+        return this;
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        ServiceDeclaration declaration = module.services( JavaxJsonSerialization.class )
+                                               .withTypes( Serialization.class,
+                                                           Serializer.class, Deserializer.class,
+                                                           Converters.class,
+                                                           JsonSerialization.class,
+                                                           JsonSerializer.class, JsonDeserializer.class,
+                                                           JavaxJsonFactories.class, JavaxJsonAdapters.class )
+                                               .taggedWith( Serialization.Format.JSON )
+                                               .visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            declaration.identifiedBy( identity() );
+        }
+        if( settings != null )
+        {
+            declaration.setMetaInfo( settings );
+        }
+    }
+}
diff --git a/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/assembly/package.html b/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/assembly/package.html
new file mode 100644
index 0000000..06888ed
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>javax.json Serialization Assembly.</h2>
+    </body>
+</html>
diff --git a/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/package.html b/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/package.html
new file mode 100644
index 0000000..43db1d9
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>javax.json Serialization.</h2>
+    </body>
+</html>
diff --git a/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/CustomJsonAdapterTest.java b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/CustomJsonAdapterTest.java
new file mode 100644
index 0000000..85db21e
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/CustomJsonAdapterTest.java
@@ -0,0 +1,182 @@
+/*
+ *  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.polygene.serialization.javaxjson;
+
+import java.time.LocalDate;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import javax.json.JsonObject;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.type.ValueCompositeType;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxjson.assembly.JavaxJsonSerializationAssembler;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class CustomJsonAdapterTest extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        new JavaxJsonSerializationAssembler()
+            .withJsonSettings( new JavaxJsonSettings().withJsonAdapter( new CustomValueAdapter() )
+                                                      .withJsonAdapter( new CustomStructureAdapter() ) )
+            .assemble( module );
+        module.values( SomeValue.class );
+    }
+
+    interface SomeValue
+    {
+        Property<CustomValue> customValue();
+
+        Property<CustomStructure> customStructure();
+    }
+
+    static class CustomValue
+    {
+        String state;
+
+        CustomValue( String state )
+        {
+            this.state = state;
+        }
+    }
+
+    static class CustomStructure
+    {
+        String foo;
+        LocalDate bar;
+
+        CustomStructure( String foo, LocalDate bar )
+        {
+            this.foo = foo;
+            this.bar = bar;
+        }
+    }
+
+    static class CustomValueAdapter implements JavaxJsonAdapter<CustomValue>
+    {
+        @Override
+        public Class<CustomValue> type() { return CustomValue.class; }
+
+        @Override
+        public JsonValue serialize( JavaxJsonFactories jsonFactories,
+                                    Object object, Function<Object, JsonValue> serialize )
+        {
+            return jsonFactories.toJsonString( type().cast( object ).state );
+        }
+
+        @Override
+        public CustomValue deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserialize )
+        {
+            switch( json.getValueType() )
+            {
+                case STRING:
+                    return new CustomValue( ( (JsonString) json ).getString() );
+                default:
+                    throw new SerializationException( "Don't know how to deserialize CustomValue from " + json );
+            }
+        }
+    }
+
+    static class CustomStructureAdapter implements JavaxJsonAdapter<CustomStructure>
+    {
+        @Override
+        public Class<CustomStructure> type() { return CustomStructure.class; }
+
+        @Override
+        public JsonValue serialize( JavaxJsonFactories jsonFactories,
+                                    Object object, Function<Object, JsonValue> serialize )
+        {
+            CustomStructure customStructure = type().cast( object );
+            return jsonFactories.builderFactory().createObjectBuilder()
+                                .add( "foo", customStructure.foo )
+                                .add( "bar", serialize.apply( customStructure.bar ) )
+                                .build();
+        }
+
+        @Override
+        public CustomStructure deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserialize )
+        {
+            if( json.getValueType() != JsonValue.ValueType.OBJECT )
+            {
+                throw new SerializationException( "Don't know how to deserialize CustomStructure from " + json );
+            }
+            JsonObject jsonObject = (JsonObject) json;
+            String foo = jsonObject.getString( "foo" );
+            LocalDate bar = (LocalDate) deserialize.apply( jsonObject.get( "bar" ), ValueType.of( LocalDate.class ) );
+            return new CustomStructure( foo, bar );
+        }
+    }
+
+    @Service
+    private JavaxJsonSerialization serialization;
+
+    @Test
+    public void customJsonAdapterForPropertyValue()
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        builder.prototype().customValue().set( new CustomValue( "custom-value-state" ) );
+        builder.prototype().customStructure().set( new CustomStructure( "foo", LocalDate.of( 2017, 1, 1 ) ) );
+        SomeValue someValue = builder.newInstance();
+
+        System.out.println( someValue.toString() );
+
+        JsonValue serialized = serialization.toJson( someValue );
+        assertThat( serialized.getValueType(), is( JsonValue.ValueType.OBJECT ) );
+
+        JsonObject jsonObject = (JsonObject) serialized;
+        assertThat( jsonObject.getString( "customValue" ), equalTo( "custom-value-state" ) );
+        JsonObject structure = jsonObject.getJsonObject( "customStructure" );
+        assertThat( structure.getString( "foo" ), equalTo( "foo" ) );
+        assertThat( structure.getString( "bar" ), equalTo( "2017-01-01" ) );
+
+        SomeValue deserialized = serialization.fromJson( module, ValueCompositeType.of( SomeValue.class ), serialized );
+
+        assertThat( deserialized.customValue().get().state, equalTo( "custom-value-state" ) );
+        assertThat( deserialized.customStructure().get().foo, equalTo( "foo" ) );
+        assertThat( deserialized.customStructure().get().bar, equalTo( LocalDate.of( 2017, 1, 1 ) ) );
+    }
+
+    @Test
+    public void customJsonAdapterForDirectObject()
+    {
+        CustomValue customValueObject = new CustomValue( "custom-value-state" );
+        JsonValue serialized = serialization.toJson( customValueObject );
+        assertThat( serialized.getValueType(), is( JsonValue.ValueType.STRING ) );
+        JsonString jsonString = (JsonString) serialized;
+        assertThat( jsonString.getString(), equalTo( "custom-value-state" ) );
+
+        CustomStructure customStructureObject = new CustomStructure( "foo", LocalDate.of( 2017, 1, 1 ) );
+        serialized = serialization.toJson( customStructureObject );
+        assertThat( serialized.getValueType(), is( JsonValue.ValueType.OBJECT ) );
+        JsonObject jsonObject = (JsonObject) serialized;
+        assertThat( jsonObject.getString( "foo" ), equalTo( "foo" ) );
+        assertThat( jsonObject.getString( "bar" ), equalTo( "2017-01-01" ) );
+    }
+}
diff --git a/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/HandCraftedJsonTest.java b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/HandCraftedJsonTest.java
new file mode 100644
index 0000000..e26d15d
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/HandCraftedJsonTest.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.serialization.javaxjson;
+
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.serialization.Deserializer;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxjson.assembly.JavaxJsonSerializationAssembler;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class HandCraftedJsonTest extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        new JavaxJsonSerializationAssembler().assemble( module );
+        module.values( SomeValue.class );
+    }
+
+    public interface SomeValue
+    {
+        Property<String> foo();
+    }
+
+    @Service
+    private Deserializer deserializer;
+
+    @Test
+    public void canReadSingleLineJson()
+    {
+        String json = "  {  \"foo\"  :  \"bar\"  }  ";
+        assertThat( deserializer.deserialize( module, SomeValue.class, json ).foo().get(),
+                    equalTo( "bar" ) );
+    }
+
+    @Test
+    public void canReadFormattedMultiLineJson()
+    {
+        String json = "  \n {  \n\t\"foo\"  :  \"bar\"  \n }\n  ";
+        assertThat( deserializer.deserialize( module, SomeValue.class, json ).foo().get(),
+                    equalTo( "bar" ) );
+    }
+
+    @Test
+    public void canReadCommentedJson()
+    {
+        String json = "// One comment\n {  \n\t\"foo\"  :  \"bar\"  \n/* Two comments */ }\n  ";
+        assertThat( deserializer.deserialize( module, SomeValue.class, json ).foo().get(),
+                    equalTo( "bar" ) );
+    }
+}
diff --git a/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonCollectionSerializationTest.java b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonCollectionSerializationTest.java
new file mode 100644
index 0000000..e6beebd
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonCollectionSerializationTest.java
@@ -0,0 +1,196 @@
+/*
+ *  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.polygene.serialization.javaxjson;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonValue;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.type.MapType;
+import org.apache.polygene.api.type.ValueCompositeType;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxjson.assembly.JavaxJsonSerializationAssembler;
+import org.apache.polygene.spi.serialization.JsonSerialization;
+import org.apache.polygene.test.serialization.AbstractCollectionSerializationTest;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class JavaxJsonCollectionSerializationTest extends AbstractCollectionSerializationTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        new JavaxJsonSerializationAssembler().assemble( module );
+        module.values( SomeValue.class );
+        super.assemble( module );
+    }
+
+    public interface SomeValue
+    {
+        Property<String> foo();
+    }
+
+    @Service
+    private JsonSerialization jsonSerialization;
+
+    @Service
+    private JavaxJsonFactories jsonFactories;
+
+    @Test
+    public void serializeMapWithStringKeysAsJsonObject()
+    {
+        Map<String, String> map = new HashMap<>();
+        map.put( "foo", "bar" );
+        map.put( "baz", "bazar" );
+
+        JsonValue json = jsonSerialization.toJson( map );
+        assertThat( json.getValueType(), is( JsonValue.ValueType.OBJECT ) );
+
+        JsonObject jsonObject = (JsonObject) json;
+        assertThat( jsonObject.getString( "foo" ), equalTo( "bar" ) );
+        assertThat( jsonObject.getString( "baz" ), equalTo( "bazar" ) );
+
+        MapType mapType = MapType.of( ValueType.STRING, ValueType.STRING );
+        Map<String, String> map2 = jsonSerialization.fromJson( module, mapType, json );
+        assertThat( map2, equalTo( map ) );
+    }
+
+    @Test
+    public void deserializeJsonArrayOfEntryObjectsAsMapWithStringKeys()
+    {
+        JsonObjectBuilder fooEntryBuilder = jsonFactories.builderFactory().createObjectBuilder();
+        fooEntryBuilder.add( "key", "foo" );
+        fooEntryBuilder.add( "value", "bar" );
+        JsonObject fooEntry = fooEntryBuilder.build();
+
+        JsonObjectBuilder bazEntryBuilder = jsonFactories.builderFactory().createObjectBuilder();
+        bazEntryBuilder.add( "key", "baz" );
+        bazEntryBuilder.add( "value", "bazar" );
+        JsonObject bazEntry = bazEntryBuilder.build();
+
+        JsonArrayBuilder arrayBuilder = jsonFactories.builderFactory().createArrayBuilder();
+        arrayBuilder.add( fooEntry );
+        arrayBuilder.add( bazEntry );
+        JsonArray jsonArray = arrayBuilder.build();
+
+        MapType mapType = MapType.of( ValueType.STRING, ValueType.STRING );
+        Map<String, String> map = jsonSerialization.fromJson( module, mapType, jsonArray );
+
+        assertThat( map.get( "foo" ), equalTo( "bar" ) );
+        assertThat( map.get( "baz" ), equalTo( "bazar" ) );
+    }
+
+    @Test
+    public void serializeMapWithComplexKeyToJsonArrayOfEntryObjects()
+    {
+        Map<SomeValue, String> map = new LinkedHashMap<>();
+        map.put( newSomeValue( "foo" ), "bar" );
+        map.put( newSomeValue( "baz" ), "bazar" );
+
+        JsonValue json = jsonSerialization.toJson( map );
+        assertThat( json.getValueType(), is( JsonValue.ValueType.ARRAY ) );
+
+        JsonArray jsonArray = (JsonArray) json;
+        JsonObject fooEntry = jsonArray.getJsonObject( 0 );
+        JsonObject bazEntry = jsonArray.getJsonObject( 1 );
+        assertThat( fooEntry.getJsonObject( "key" ).getString( "foo" ), equalTo( "foo" ) );
+        assertThat( fooEntry.getString( "value" ), equalTo( "bar" ) );
+        assertThat( bazEntry.getJsonObject( "key" ).getString( "foo" ), equalTo( "baz" ) );
+        assertThat( bazEntry.getString( "value" ), equalTo( "bazar" ) );
+
+        MapType mapType = MapType.of( ValueCompositeType.of( api.valueDescriptorFor( map.keySet().iterator().next() ) ),
+                                      ValueType.STRING );
+        Map<SomeValue, String> map2 = jsonSerialization.fromJson( module, mapType, json );
+        assertThat( map2, equalTo( map ) );
+    }
+
+    @Test
+    public void serializeMapWithMixedKeysAsJsonArrayOfEntryObjects()
+    {
+        Map<Object, String> map = new LinkedHashMap<>();
+        map.put( "foo", "bar" );
+        map.put( newSomeValue( "baz" ), "bazar" );
+
+        JsonValue json = jsonSerialization.toJson( map );
+        assertThat( json.getValueType(), is( JsonValue.ValueType.ARRAY ) );
+
+        JsonArray jsonArray = (JsonArray) json;
+        JsonObject fooEntry = jsonArray.getJsonObject( 0 );
+        JsonObject bazEntry = jsonArray.getJsonObject( 1 );
+        assertThat( fooEntry.getString( "key" ), equalTo( "foo" ) );
+        assertThat( fooEntry.getString( "value" ), equalTo( "bar" ) );
+        assertThat( bazEntry.getJsonObject( "key" ).getString( "foo" ), equalTo( "baz" ) );
+        assertThat( bazEntry.getString( "value" ), equalTo( "bazar" ) );
+    }
+
+    @Test
+    public void dontKnowHowToDeserializeMapWithMixedKeys()
+    {
+        JsonObjectBuilder fooKeyBuilder = jsonFactories.builderFactory().createObjectBuilder();
+        fooKeyBuilder.add( "foo", "foo" );
+        fooKeyBuilder.add( "_type", SomeValue.class.getName() );
+        JsonObject fooKey = fooKeyBuilder.build();
+
+        JsonObjectBuilder fooEntryBuilder = jsonFactories.builderFactory().createObjectBuilder();
+        fooEntryBuilder.add( "key", fooKey );
+        fooEntryBuilder.add( "value", "bar" );
+        JsonObject fooEntry = fooEntryBuilder.build();
+
+        JsonObjectBuilder bazEntryBuilder = jsonFactories.builderFactory().createObjectBuilder();
+        bazEntryBuilder.add( "key", "baz" );
+        bazEntryBuilder.add( "value", "bazar" );
+        JsonObject bazEntry = bazEntryBuilder.build();
+
+        JsonArrayBuilder arrayBuilder = jsonFactories.builderFactory().createArrayBuilder();
+        arrayBuilder.add( fooEntry );
+        arrayBuilder.add( bazEntry );
+        JsonArray jsonArray = arrayBuilder.build();
+
+        MapType mapType = MapType.of( ValueType.OBJECT, ValueType.STRING );
+        try
+        {
+            jsonSerialization.fromJson( module, mapType, jsonArray );
+            fail( "Should have failed deserialization" );
+        }
+        catch( SerializationException ex )
+        {
+            assertThat( ex.getMessage(),
+                        equalTo( "Don't know how to deserialize java.lang.Object from \"baz\"" ) );
+        }
+    }
+
+    private SomeValue newSomeValue( String foo )
+    {
+        ValueBuilder<SomeValue> builder = valueBuilderFactory.newValueBuilder( SomeValue.class );
+        builder.prototype().foo().set( foo );
+        return builder.newInstance();
+    }
+}
diff --git a/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonConfigurationDeserializationTest.java b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonConfigurationDeserializationTest.java
new file mode 100644
index 0000000..f054561
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonConfigurationDeserializationTest.java
@@ -0,0 +1,24 @@
+/*
+ *  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.polygene.serialization.javaxjson;
+
+import org.apache.polygene.test.entity.AbstractConfigurationDeserializationTest;
+
+public class JavaxJsonConfigurationDeserializationTest extends AbstractConfigurationDeserializationTest
+{
+}
diff --git a/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonConvertersSerializationTest.java b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonConvertersSerializationTest.java
new file mode 100644
index 0000000..6076faf
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonConvertersSerializationTest.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.serialization.javaxjson;
+
+import java.io.StringReader;
+import javax.json.JsonObject;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxjson.assembly.JavaxJsonSerializationAssembler;
+import org.apache.polygene.test.serialization.AbstractConvertersSerializationTest;
+
+public class JavaxJsonConvertersSerializationTest extends AbstractConvertersSerializationTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        new JavaxJsonSerializationAssembler().assemble( module );
+        super.assemble( module );
+    }
+
+    @Service
+    private JavaxJsonFactories jsonFactories;
+
+    @Override
+    protected String getStringFromValueState( String state, String key ) throws Exception
+    {
+        JsonObject jsonObject = jsonFactories.readerFactory().createReader( new StringReader( state ) ).readObject();
+        return jsonObject.getString( key );
+    }
+}
diff --git a/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonPlainValueSerializationTest.java b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonPlainValueSerializationTest.java
new file mode 100644
index 0000000..e099f22
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonPlainValueSerializationTest.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.serialization.javaxjson;
+
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxjson.assembly.JavaxJsonSerializationAssembler;
+import org.apache.polygene.test.serialization.AbstractPlainValueSerializationTest;
+
+public class JavaxJsonPlainValueSerializationTest extends AbstractPlainValueSerializationTest
+{
+    @Override
+    public void assemble( final ModuleAssembly module )
+    {
+        new JavaxJsonSerializationAssembler()
+            .withJsonSettings( withTestSettings( new JavaxJsonSettings() ) )
+            .assemble( module );
+    }
+
+    @Override
+    protected String getSingleStringRawState( String state )
+    {
+        return state;
+    }
+}
diff --git a/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonValueCompositeSerializationTest.java b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonValueCompositeSerializationTest.java
new file mode 100644
index 0000000..d628cb2
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonValueCompositeSerializationTest.java
@@ -0,0 +1,83 @@
+/*
+ *  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.polygene.serialization.javaxjson;
+
+import java.io.StringReader;
+import javax.json.JsonObject;
+import javax.json.JsonValue;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxjson.assembly.JavaxJsonSerializationAssembler;
+import org.apache.polygene.spi.serialization.JsonSerialization;
+import org.apache.polygene.test.serialization.AbstractValueCompositeSerializationTest;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class JavaxJsonValueCompositeSerializationTest extends AbstractValueCompositeSerializationTest
+{
+    // START SNIPPET: assembly
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        new JavaxJsonSerializationAssembler().assemble( module );
+        // END SNIPPET: assembly
+        super.assemble( module );
+        // START SNIPPET: assembly
+    }
+    // END SNIPPET: assembly
+
+    // START SNIPPET: json-serialization
+    @Service
+    JsonSerialization jsonSerialization;
+    // END SNIPPET: json-serialization
+
+    @Service
+    JavaxJsonFactories jsonFactories;
+
+    @Test
+    public void valueCompositeJsonEquality()
+    {
+        // START SNIPPET: json-serialization
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            Some valueInstance = buildSomeValue( moduleInstance, uow, "42" );
+
+            // Serialize using injected service
+            JsonValue serializedJson = jsonSerialization.toJson( valueInstance );
+            System.out.println( serializedJson.toString() );
+
+            // Deserialize using Module API
+            Some valueFromSerializedState = moduleInstance.newValueFromSerializedState( Some.class, serializedJson.toString() );
+            assertThat( "Deserialized Value equality", valueInstance, equalTo( valueFromSerializedState ) );
+            // END SNIPPET: json-serialization
+
+            // value.toString()
+            JsonValue valueJsonWithoutTypeInfo = jsonSerialization.toJson( Serializer.Options.NO_TYPE_INFO, valueFromSerializedState );
+            JsonObject valueToStringJson = jsonFactories.readerFactory()
+                                                        .createReader( new StringReader( valueFromSerializedState.toString() ) )
+                                                        .readObject();
+            assertThat( "value.toString() JSON equality", valueJsonWithoutTypeInfo, equalTo( valueToStringJson ) );
+            // START SNIPPET: json-serialization
+        }
+        // END SNIPPET: json-serialization
+    }
+}
diff --git a/extensions/serialization-javaxjson/src/test/resources/configtest.json b/extensions/serialization-javaxjson/src/test/resources/configtest.json
new file mode 100644
index 0000000..4c5600b
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/test/resources/configtest.json
@@ -0,0 +1,8 @@
+{
+  "identity": "configtest",
+  "host": {
+    "ip": "12.23.34.45",
+    "port": 1234
+  },
+  "name": "main"
+}
diff --git a/extensions/serialization-javaxxml/build.gradle b/extensions/serialization-javaxxml/build.gradle
new file mode 100644
index 0000000..4c095f9
--- /dev/null
+++ b/extensions/serialization-javaxxml/build.gradle
@@ -0,0 +1,34 @@
+/*
+ *  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.
+ */
+
+apply plugin: 'polygene-extension'
+
+description = "Apache Polygene™ javax.xml Serialization Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - Serialization - javax.xml" } }
+
+dependencies {
+  api polygene.core.bootstrap
+
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+  testImplementation libraries.xmlunit
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/extensions/serialization-javaxxml/dev-status.xml b/extensions/serialization-javaxxml/dev-status.xml
new file mode 100644
index 0000000..a36ce79
--- /dev/null
+++ b/extensions/serialization-javaxxml/dev-status.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
+    <status>
+        <!--none,early,beta,stable,mature-->
+        <codebase>beta</codebase>
+
+        <!-- none, brief, good, complete -->
+        <documentation>brief</documentation>
+
+        <!-- none, some, good, complete -->
+        <unittests>good</unittests>
+    </status>
+    <licenses>
+        <license>ALv2</license>
+    </licenses>
+</module>
\ No newline at end of file
diff --git a/extensions/serialization-javaxxml/src/docs/serialization-javaxxml.txt b/extensions/serialization-javaxxml/src/docs/serialization-javaxxml.txt
new file mode 100644
index 0000000..aef6392
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/docs/serialization-javaxxml.txt
@@ -0,0 +1,46 @@
+///////////////////////////////////////////////////////////////
+ * 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.
+///////////////////////////////////////////////////////////////
+
+[[extension-serialization-javaxxml,javax.xml serialization]]
+= javax.xml serialization =
+
+[devstatus]
+--------------
+source=extensions/serialization-javaxxml/dev-status.xml
+--------------
+
+`Serialization` service backed by `javax.xml` types.
+See <<core-api-serialization>> and <<core-spi-serialization>>.
+
+include::../../build/docs/buildinfo/artifact.txt[]
+
+This extension make use of the Java runtime default `javax.xml` provider.
+You can add dependencies to replace it by the one of your choice.
+
+// TODO Include sample model and its output from test code & resources
+
+== Assembly ==
+
+Assembly is done using the provided Assembler:
+
+[snippet,java]
+----
+source=extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlValueCompositeSerializationTest.java
+tag=assembly
+----
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXml.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXml.java
new file mode 100644
index 0000000..3289d30
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXml.java
@@ -0,0 +1,161 @@
+/*
+ *  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.polygene.serialization.javaxxml;
+
+import java.util.Optional;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * javax.xml utilities.
+ */
+public class JavaxXml
+{
+    /**
+     * Find child elements.
+     *
+     * @param parent the parent node
+     * @return a stream of elements
+     */
+    public static Stream<Element> childElements( Node parent )
+    {
+        return toStream( parent.getChildNodes() ).filter( JavaxXml::isElement )
+                                                 .map( JavaxXml::castToElement );
+    }
+
+    /**
+     * Find the first child element.
+     *
+     * @param parent the parent node
+     * @return an optional element
+     */
+    public static Optional<Element> firstChildElement( Node parent )
+    {
+        return childElements( parent ).findFirst();
+    }
+
+    /**
+     * Find child elements named {@literal tagName}.
+     *
+     * @param parent the parent node
+     * @param tagName the tag name
+     * @return a stream of elements named {@literal tagName}
+     */
+    public static Stream<Element> childElementsNamed( Node parent, String tagName )
+    {
+        return childElements( parent ).filter( element -> tagName.equals( element.getTagName() ) );
+    }
+
+    /**
+     * Find the first child element named {@literal tagName}.
+     *
+     * @param parent the parent node
+     * @param tagName the tag name
+     * @return an optional element named {@literal tagName}
+     */
+    public static Optional<Element> firstChildElementNamed( Node parent, String tagName )
+    {
+        return childElementsNamed( parent, tagName ).findFirst();
+    }
+
+    /**
+     * Find child nodes holding state.
+     *
+     * @param parent the parent node
+     * @return a stream or child state nodes
+     */
+    public static Stream<Node> stateChildNodes( Node parent )
+    {
+        return toStream( parent.getChildNodes() ).filter( JavaxXml::isStateNode );
+    }
+
+    /**
+     * Find the first child node holding state.
+     *
+     * @param parent the parent node
+     * @return an optional child state node
+     */
+    public static Optional<Node> firstStateChildNode( Node parent )
+    {
+        return stateChildNodes( parent ).findFirst();
+    }
+
+    /**
+     * Test if a node holds state.
+     *
+     * Types of nodes holding state:
+     * <ul>
+     * <li>{@link Node#ELEMENT_NODE}</li>
+     * <li>{@link Node#CDATA_SECTION_NODE}</li>
+     * <li>{@link Node#TEXT_NODE}</li>
+     * </ul>
+     *
+     * @param node the node
+     * @return {@literal true} if {@literal node} holds state
+     */
+    public static boolean isStateNode( Node node )
+    {
+        switch( node.getNodeType() )
+        {
+            case Node.ELEMENT_NODE:
+            case Node.CDATA_SECTION_NODE:
+            case Node.TEXT_NODE:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    private static boolean isElement( Node node )
+    {
+        return node.getNodeType() == Node.ELEMENT_NODE;
+    }
+
+    private static Element castToElement( Node node )
+    {
+        return (Element) node;
+    }
+
+    private static Stream<Node> toStream( NodeList nodeList )
+    {
+        return StreamSupport.stream( new Spliterators.AbstractSpliterator<Node>( Long.MAX_VALUE, Spliterator.ORDERED )
+        {
+            private int nextIndex = 0;
+
+            @Override
+            public boolean tryAdvance( Consumer<? super Node> action )
+            {
+                if( nextIndex >= nodeList.getLength() )
+                {
+                    return false;
+                }
+                action.accept( nodeList.item( nextIndex ) );
+                nextIndex++;
+                return true;
+            }
+        }, false );
+    }
+
+    private JavaxXml() {}
+}
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdapter.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdapter.java
new file mode 100644
index 0000000..b255daa
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdapter.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.serialization.javaxxml;
+
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import org.apache.polygene.api.type.ValueType;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * Adapter for XML (de)serialization.
+ *
+ * @param <T> the adapted type
+ */
+public interface JavaxXmlAdapter<T>
+{
+    /**
+     * @return the adapted type
+     */
+    Class<T> type();
+
+    /**
+     * Serialize.
+     *
+     * @param document the Document to use as a Node factory
+     * @param object Object to serialize, never null
+     * @param serialize Serialization function for nested structure serialization
+     * @return Serialized XML representation
+     */
+    Node serialize( Document document, Object object, Function<Object, Node> serialize );
+
+    /**
+     * Deserialize.
+     *
+     * @param node XML to deserialize from, never null
+     * @param deserialize Deserialization function for nested structure deserialization
+     * @return Deserialized object
+     */
+    T deserialize( Node node, BiFunction<Node, ValueType, Object> deserialize );
+}
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdapters.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdapters.java
new file mode 100644
index 0000000..716be65
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdapters.java
@@ -0,0 +1,227 @@
+/*
+ *  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.polygene.serialization.javaxxml;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.serialization.Converters;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.spi.serialization.BuiltInConverters;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import static org.apache.polygene.api.type.HasTypesCollectors.closestType;
+import static org.apache.polygene.serialization.javaxxml.JavaxXmlSettings.orDefault;
+
+@Mixins( JavaxXmlAdapters.Mixin.class )
+public interface JavaxXmlAdapters
+{
+    void registerAdapter( ValueType valueType, JavaxXmlAdapter<?> adapter );
+
+    <T> JavaxXmlAdapter<T> adapterFor( ValueType valueType );
+
+    default <T> JavaxXmlAdapter<T> adapterFor( Class<T> type )
+    {
+        return adapterFor( ValueType.of( type ) );
+    }
+
+    class Mixin implements JavaxXmlAdapters, Initializable
+    {
+        private Map<ValueType, JavaxXmlAdapter<?>> adapters = new LinkedHashMap<>();
+
+        @Uses
+        private ServiceDescriptor descriptor;
+
+        @This
+        private BuiltInConverters builtInConverters;
+
+        @This
+        private Converters converters;
+
+        @Override
+        public void initialize() throws Exception
+        {
+            JavaxXmlSettings settings = orDefault( descriptor.metaInfo( JavaxXmlSettings.class ) );
+            settings.getConverters()
+                    .forEach( ( type, converter ) -> converters.registerConverter( type, converter ) );
+            builtInConverters.registerBuiltInConverters( converters );
+            settings.getAdapters().forEach( adapters::put );
+            registerBaseJavaxXmlAdapters();
+        }
+
+        @Override
+        public void registerAdapter( final ValueType valueType, final JavaxXmlAdapter<?> adapter )
+        {
+            adapters.put( valueType, adapter );
+        }
+
+        @Override
+        public <T> JavaxXmlAdapter<T> adapterFor( final ValueType valueType )
+        {
+            return castAdapter( adapters.keySet().stream()
+                                        .collect( closestType( valueType ) )
+                                        .map( adapters::get )
+                                        .orElse( null ) );
+        }
+
+        @SuppressWarnings( "unchecked" )
+        private <T> JavaxXmlAdapter<T> castAdapter( JavaxXmlAdapter<?> adapter )
+        {
+            return (JavaxXmlAdapter<T>) adapter;
+        }
+
+        private void registerBaseJavaxXmlAdapters()
+        {
+            // Primitive Value types
+            adapters.put( ValueType.STRING, new StringAdapter() );
+            adapters.put( ValueType.CHARACTER, new CharacterAdapter() );
+            adapters.put( ValueType.BOOLEAN, new BooleanAdapter() );
+            adapters.put( ValueType.INTEGER, new IntegerAdapter() );
+            adapters.put( ValueType.LONG, new LongAdapter() );
+            adapters.put( ValueType.SHORT, new ShortAdapter() );
+            adapters.put( ValueType.BYTE, new ByteAdapter() );
+            adapters.put( ValueType.FLOAT, new FloatAdapter() );
+            adapters.put( ValueType.DOUBLE, new DoubleAdapter() );
+        }
+
+        private static abstract class ToStringTextNodeAdapter<T> implements JavaxXmlAdapter<T>
+        {
+            @Override
+            public Node serialize( Document document, Object object, Function<Object, Node> serialize )
+            {
+                return document.createTextNode( object.toString() );
+            }
+        }
+
+        private static class StringAdapter extends ToStringTextNodeAdapter<String>
+        {
+            @Override
+            public Class<String> type() { return String.class; }
+
+            @Override
+            public String deserialize( Node node, BiFunction<Node, ValueType, Object> deserialize )
+            {
+                return node.getNodeValue();
+            }
+        }
+
+        private static class CharacterAdapter extends ToStringTextNodeAdapter<Character>
+        {
+            @Override
+            public Class<Character> type() { return Character.class; }
+
+            @Override
+            public Character deserialize( Node node, BiFunction<Node, ValueType, Object> deserialize )
+            {
+                String string = node.getNodeValue();
+                return string.isEmpty() ? null : string.charAt( 0 );
+            }
+        }
+
+        private static class BooleanAdapter extends ToStringTextNodeAdapter<Boolean>
+        {
+            @Override
+            public Class<Boolean> type() { return Boolean.class; }
+
+            @Override
+            public Boolean deserialize( Node node, BiFunction<Node, ValueType, Object> deserialize )
+            {
+                return Boolean.valueOf( node.getNodeValue() );
+            }
+        }
+
+        private static class IntegerAdapter extends ToStringTextNodeAdapter<Integer>
+        {
+            @Override
+            public Class<Integer> type() { return Integer.class; }
+
+            @Override
+            public Integer deserialize( Node node, BiFunction<Node, ValueType, Object> deserialize )
+            {
+                return Integer.valueOf( node.getNodeValue() );
+            }
+        }
+
+        private static class LongAdapter extends ToStringTextNodeAdapter<Long>
+        {
+            @Override
+            public Class<Long> type() { return Long.class; }
+
+            @Override
+            public Long deserialize( Node node, BiFunction<Node, ValueType, Object> deserialize )
+            {
+                return Long.valueOf( node.getNodeValue() );
+            }
+        }
+
+        private static class ShortAdapter extends ToStringTextNodeAdapter<Short>
+        {
+            @Override
+            public Class<Short> type() { return Short.class; }
+
+            @Override
+            public Short deserialize( Node node, BiFunction<Node, ValueType, Object> deserialize )
+            {
+                return Short.valueOf( node.getNodeValue() );
+            }
+        }
+
+        private static class ByteAdapter extends ToStringTextNodeAdapter<Byte>
+        {
+            @Override
+            public Class<Byte> type() { return Byte.class; }
+
+            @Override
+            public Byte deserialize( Node node, BiFunction<Node, ValueType, Object> deserialize )
+            {
+                return Byte.valueOf( node.getNodeValue() );
+            }
+        }
+
+        private static class FloatAdapter extends ToStringTextNodeAdapter<Float>
+        {
+            @Override
+            public Class<Float> type() { return Float.class; }
+
+            @Override
+            public Float deserialize( Node node, BiFunction<Node, ValueType, Object> deserialize )
+            {
+                return Float.valueOf( node.getNodeValue() );
+            }
+        }
+
+        private static class DoubleAdapter extends ToStringTextNodeAdapter<Double>
+        {
+            @Override
+            public Class<Double> type() { return Double.class; }
+
+            @Override
+            public Double deserialize( Node node, BiFunction<Node, ValueType, Object> deserialize )
+            {
+                return Double.valueOf( node.getNodeValue() );
+            }
+        }
+    }
+}
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlDeserializer.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlDeserializer.java
new file mode 100644
index 0000000..1c9d64e
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlDeserializer.java
@@ -0,0 +1,376 @@
+/*
+ *  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.polygene.serialization.javaxxml;
+
+import java.io.Reader;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.stream.StreamSource;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.StatefulAssociationCompositeDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.serialization.Converter;
+import org.apache.polygene.api.serialization.Converters;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ArrayType;
+import org.apache.polygene.api.type.CollectionType;
+import org.apache.polygene.api.type.EnumType;
+import org.apache.polygene.api.type.MapType;
+import org.apache.polygene.api.type.StatefulAssociationValueType;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.spi.serialization.AbstractTextDeserializer;
+import org.apache.polygene.spi.serialization.XmlDeserializer;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.Collections.unmodifiableList;
+import static java.util.Collections.unmodifiableMap;
+import static java.util.Collections.unmodifiableSet;
+import static org.apache.polygene.api.util.Collectors.toMapWithNullValues;
+
+public class JavaxXmlDeserializer extends AbstractTextDeserializer
+    implements XmlDeserializer, Initializable
+{
+    private static final String NULL_ELEMENT_NAME = "null";
+
+    @This
+    private JavaxXmlFactories xmlFactories;
+
+    @This
+    private Converters converters;
+
+    @This
+    private JavaxXmlAdapters adapters;
+
+    @Uses
+    private ServiceDescriptor descriptor;
+
+    private JavaxXmlSettings settings;
+
+    @Override
+    public void initialize() throws Exception
+    {
+        settings = JavaxXmlSettings.orDefault( descriptor.metaInfo( JavaxXmlSettings.class ) );
+    }
+
+    @Override
+    public <T> T deserialize( ModuleDescriptor module, ValueType valueType, Reader state )
+    {
+        try
+        {
+            DOMResult domResult = new DOMResult();
+            xmlFactories.normalizationTransformer().transform( new StreamSource( state ), domResult );
+            Node node = domResult.getNode();
+            return fromXml( module, valueType, node );
+        }
+        catch( TransformerException ex )
+        {
+            throw new SerializationException( "Unable to read XML document", ex );
+        }
+    }
+
+    @Override
+    public <T> T fromXml( ModuleDescriptor module, ValueType valueType, Node state )
+    {
+        Optional<Element> stateElement = JavaxXml.firstChildElementNamed( state, settings.getRootTagName() );
+        if( stateElement.isPresent() )
+        {
+            Optional<Node> stateNode = JavaxXml.firstStateChildNode( stateElement.get() );
+            return doDeserialize( module, valueType, stateNode.orElse( null ) );
+        }
+        return null;
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private <T> T doDeserialize( ModuleDescriptor module, ValueType valueType, Node xml )
+    {
+        if( xml == null )
+        {
+            return valueType.hasType( String.class ) ? (T) "" : null;
+        }
+        if( xml.getNodeType() == Node.ELEMENT_NODE && NULL_ELEMENT_NAME.equals( ( (Element) xml ).getTagName() ) )
+        {
+            return null;
+        }
+        Converter<Object> converter = converters.converterFor( valueType );
+        if( converter != null )
+        {
+            return (T) converter.fromString( doDeserialize( module, ValueType.STRING, xml ).toString() );
+        }
+        JavaxXmlAdapter<?> adapter = adapters.adapterFor( valueType );
+        if( adapter != null )
+        {
+            return (T) adapter.deserialize( xml, ( element, type ) -> doDeserialize( module, type, element ) );
+        }
+        Class<? extends ValueType> valueTypeClass = valueType.getClass();
+        if( EnumType.class.isAssignableFrom( valueTypeClass ) )
+        {
+            return (T) Enum.valueOf( (Class) valueType.primaryType(), xml.getNodeValue() );
+        }
+        if( ArrayType.class.isAssignableFrom( valueTypeClass ) )
+        {
+            return (T) deserializeArray( module, (ArrayType) valueType, xml );
+        }
+        if( CollectionType.class.isAssignableFrom( valueTypeClass ) )
+        {
+            return (T) deserializeCollection( module, (CollectionType) valueType, xml );
+        }
+        if( MapType.class.isAssignableFrom( valueTypeClass ) )
+        {
+            return (T) deserializeMap( module, (MapType) valueType, xml );
+        }
+        if( StatefulAssociationValueType.class.isAssignableFrom( valueTypeClass ) )
+        {
+            return (T) deserializeStatefulAssociationValue( module, (StatefulAssociationValueType<?>) valueType, xml );
+        }
+        return (T) doGuessDeserialize( module, valueType, xml );
+    }
+
+    private Object deserializeStatefulAssociationValue( ModuleDescriptor module,
+                                                        StatefulAssociationValueType<?> valueType, Node xml )
+    {
+        Optional<String> typeInfo = getTypeInfo( xml );
+        if( typeInfo.isPresent() )
+        {
+            StatefulAssociationCompositeDescriptor descriptor = statefulCompositeDescriptorFor( module,
+                                                                                                typeInfo.get() );
+            if( descriptor == null )
+            {
+                String typeInfoName = settings.getTypeInfoTagName();
+                throw new SerializationException(
+                    typeInfoName + ": " + typeInfo.get() + " could not be resolved while deserializing " + xml );
+            }
+            valueType = descriptor.valueType();
+        }
+        ValueBuilder builder = module.instance().newValueBuilderWithState(
+            valueType.primaryType(),
+            propertyFunction( valueType.module(), xml ),
+            associationFunction( valueType.module(), xml ),
+            manyAssociationFunction( valueType.module(), xml ),
+            namedAssociationFunction( valueType.module(), xml ) );
+        return builder.newInstance();
+    }
+
+    private Function<PropertyDescriptor, Object> propertyFunction( ModuleDescriptor module, Node xml )
+    {
+        return property ->
+        {
+            Optional<Element> element = JavaxXml.firstChildElementNamed( xml, property.qualifiedName().name() );
+            if( element.isPresent() )
+            {
+                Node valueNode = JavaxXml.firstStateChildNode( element.get() ).orElse( null );
+                Object value;
+                Converter<Object> converter = converters.converterFor( property );
+                if( converter != null )
+                {
+                    value = converter.fromString( doDeserialize( module, ValueType.STRING, valueNode ) );
+                }
+                else
+                {
+                    value = doDeserialize( module, property.valueType(), valueNode );
+                }
+                if( property.isImmutable() )
+                {
+                    if( value instanceof Set )
+                    {
+                        return unmodifiableSet( (Set<?>) value );
+                    }
+                    else if( value instanceof List )
+                    {
+                        return unmodifiableList( (List<?>) value );
+                    }
+                    else if( value instanceof Map )
+                    {
+                        return unmodifiableMap( (Map<?, ?>) value );
+                    }
+                }
+                return value;
+            }
+            return property.resolveInitialValue( module );
+        };
+    }
+
+    private Function<AssociationDescriptor, EntityReference> associationFunction( ModuleDescriptor module, Node xml )
+    {
+        return association ->
+            (EntityReference) JavaxXml.firstChildElementNamed( xml, association.qualifiedName().name() )
+                                      .map( element -> doDeserialize( module,
+                                                                      ValueType.ENTITY_REFERENCE,
+                                                                      JavaxXml.firstStateChildNode( element )
+                                                                              .orElse( null ) ) )
+                                      .orElse( null );
+    }
+
+    private Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction( ModuleDescriptor module,
+                                                                                              Node xml )
+    {
+        return association ->
+            JavaxXml.firstChildElementNamed( xml, association.qualifiedName().name() )
+                    .map( element -> (List) doDeserialize( module,
+                                                           ENTITY_REF_LIST_VALUE_TYPE,
+                                                           JavaxXml.firstStateChildNode( element )
+                                                                   .orElse( null ) ) )
+                    .map( List::stream )
+                    .orElse( Stream.empty() );
+    }
+
+    private Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction(
+        ModuleDescriptor module, Node xml )
+    {
+        return association ->
+            (Stream) JavaxXml.firstChildElementNamed( xml, association.qualifiedName().name() )
+                             .map( element -> (Map) doDeserialize( module,
+                                                                   ENTITY_REF_MAP_VALUE_TYPE,
+                                                                   JavaxXml.firstStateChildNode( element )
+                                                                           .orElse( null ) ) )
+                             .map( Map::entrySet ).map( Set::stream )
+                             .orElse( Stream.empty() );
+    }
+
+
+    private Object deserializeArray( ModuleDescriptor module, ArrayType arrayType, Node xml )
+    {
+        if( arrayType.isArrayOfPrimitiveBytes() )
+        {
+            return Base64.getDecoder().decode( xml.getNodeValue().getBytes( UTF_8 ) );
+        }
+        CollectionType collectionType = CollectionType.listOf( arrayType.collectedType() );
+        List collection = (List) deserializeCollection( module, collectionType, xml );
+        Object array = Array.newInstance( arrayType.collectedType().primaryType(), collection.size() );
+        for( int idx = 0; idx < collection.size(); idx++ )
+        {
+            Array.set( array, idx, collection.get( idx ) );
+        }
+        return array;
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private Collection deserializeCollection( ModuleDescriptor module, CollectionType collectionType, Node xml )
+    {
+        Supplier<Collection> collectionSupplier = () -> collectionType.isSet()
+                                                        ? new LinkedHashSet<>()
+                                                        : new ArrayList<>();
+        if( !xml.hasChildNodes() )
+        {
+            return collectionSupplier.get();
+        }
+        return JavaxXml
+            .childElements( xml )
+            .map( element ->
+                  {
+                      if( settings.getCollectionElementTagName().equals( element.getTagName() ) )
+                      {
+                          return doDeserialize( module, collectionType.collectedType(),
+                                                JavaxXml.firstStateChildNode( element ).get() );
+                      }
+                      return doDeserialize( module, collectionType.collectedType(), element );
+                  } )
+            .collect( Collectors.toCollection( collectionSupplier ) );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private Map deserializeMap( ModuleDescriptor module, MapType mapType, Node xml )
+    {
+        if( !xml.hasChildNodes() )
+        {
+            return new LinkedHashMap<>();
+        }
+        Predicate<Element> complexMapping = element -> settings.getMapEntryTagName().equals( element.getTagName() )
+                                                       && JavaxXml.firstChildElementNamed( element, "key" )
+                                                                  .isPresent();
+        // This allows deserializing mixed simple/complex mappings for a given map
+        return JavaxXml.childElements( xml ).map(
+            element ->
+            {
+                if( complexMapping.test( element ) )
+                {
+                    Node keyNode = JavaxXml.firstChildElementNamed( element, "key" )
+                                           .flatMap( JavaxXml::firstStateChildNode )
+                                           .get();
+                    Optional<Node> valueNode = JavaxXml.firstChildElementNamed( element, "value" )
+                                                       .flatMap( JavaxXml::firstStateChildNode );
+                    Object key = doDeserialize( module, mapType.keyType(), keyNode );
+                    Object value = valueNode.map( node -> doDeserialize( module, mapType.valueType(), node ) )
+                                            .orElse( null );
+                    return new HashMap.SimpleImmutableEntry<>( key, value );
+                }
+                String key = element.getTagName();
+                Object value = JavaxXml.firstStateChildNode( element )
+                                       .map( node -> doDeserialize( module, mapType.valueType(), node ) )
+                                       .orElse( null );
+                return (Map.Entry) new HashMap.SimpleImmutableEntry<>( key, value );
+            }
+        ).collect( toMapWithNullValues( LinkedHashMap::new ) );
+    }
+
+    private Object doGuessDeserialize( ModuleDescriptor module, ValueType valueType, Node xml )
+    {
+        // TODO Could do better by detecting <collection/>, <map/> and <value/>
+        Optional<String> typeInfo = getTypeInfo( xml );
+        if( typeInfo.isPresent() )
+        {
+            StatefulAssociationCompositeDescriptor descriptor = statefulCompositeDescriptorFor( module,
+                                                                                                typeInfo.get() );
+            if( descriptor != null )
+            {
+                return deserializeStatefulAssociationValue( ( (CompositeDescriptor) descriptor ).module(),
+                                                            descriptor.valueType(), xml );
+            }
+        }
+        throw new SerializationException( "Don't know how to deserialize " + valueType + " from " + xml );
+    }
+
+    private Optional<String> getTypeInfo( Node xml )
+    {
+        if( xml.getNodeType() != Node.ELEMENT_NODE )
+        {
+            return Optional.empty();
+        }
+        String typeInfo = ( (Element) xml ).getAttribute( settings.getTypeInfoTagName() );
+        if( typeInfo.isEmpty() )
+        {
+            return Optional.empty();
+        }
+        return Optional.of( typeInfo );
+    }
+}
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlFactories.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlFactories.java
new file mode 100644
index 0000000..613d62d
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlFactories.java
@@ -0,0 +1,167 @@
+/*
+ *  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.polygene.serialization.javaxxml;
+
+import java.io.InputStream;
+import java.util.Map;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamSource;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.w3c.dom.Document;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+@Mixins( JavaxXmlFactories.Mixin.class )
+public interface JavaxXmlFactories
+{
+    DocumentBuilderFactory documentBuilderFactory();
+
+    Document newDocumentForSerialization();
+
+    TransformerFactory transformerFactory();
+
+    Transformer serializationTransformer();
+
+    Transformer normalizationTransformer();
+
+    class Mixin implements JavaxXmlFactories, Initializable
+    {
+        @Uses
+        private ServiceDescriptor descriptor;
+
+        private DocumentBuilderFactory documentBuilderFactory;
+        private TransformerFactory transformerFactory;
+
+        private Transformer serializationTransformer;
+        private Transformer normalizationTransformer;
+
+        @Override
+        public void initialize()
+        {
+            JavaxXmlSettings settings = JavaxXmlSettings.orDefault( descriptor.metaInfo( JavaxXmlSettings.class ) );
+
+            try
+            {
+                String documentBuilderFactoryClassName = settings.getDocumentBuilderFactoryClassName();
+                documentBuilderFactory = documentBuilderFactoryClassName == null
+                                         ? DocumentBuilderFactory.newInstance()
+                                         : DocumentBuilderFactory.newInstance( documentBuilderFactoryClassName,
+                                                                               getClass().getClassLoader() );
+                documentBuilderFactory.setValidating( false );
+                documentBuilderFactory.setNamespaceAware( false );
+                documentBuilderFactory.setIgnoringComments( true );
+                for( Map.Entry<String, Boolean> feature : settings.getDocumentBuilderFactoryFeatures().entrySet() )
+                {
+                    documentBuilderFactory.setFeature( feature.getKey(), feature.getValue() );
+                }
+                for( Map.Entry<String, Object> attributes : settings.getDocumentBuilderFactoryAttributes().entrySet() )
+                {
+                    documentBuilderFactory.setAttribute( attributes.getKey(), attributes.getValue() );
+                }
+
+                String transformerFactoryClassName = settings.getTransformerFactoryClassName();
+                transformerFactory = transformerFactoryClassName == null
+                                     ? TransformerFactory.newInstance()
+                                     : TransformerFactory.newInstance( transformerFactoryClassName,
+                                                                       getClass().getClassLoader() );
+                for( Map.Entry<String, Boolean> feature : settings.getTransformerFactoryFeatures().entrySet() )
+                {
+                    transformerFactory.setFeature( feature.getKey(), feature.getValue() );
+                }
+                for( Map.Entry<String, Object> attributes : settings.getTransformerFactoryAttributes().entrySet() )
+                {
+                    transformerFactory.setAttribute( attributes.getKey(), attributes.getValue() );
+                }
+
+                serializationTransformer = transformerFactory.newTransformer();
+                serializationTransformer.setOutputProperty( OutputKeys.METHOD, "xml" );
+                serializationTransformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "no" );
+                serializationTransformer.setOutputProperty( OutputKeys.VERSION, "1.1" );
+                serializationTransformer.setOutputProperty( OutputKeys.STANDALONE, "yes" );
+                serializationTransformer.setOutputProperty( OutputKeys.ENCODING, UTF_8.name() );
+                serializationTransformer.setOutputProperty( OutputKeys.INDENT, "no" );
+
+                String xslPath = "/org/apache/polygene/serialization/javaxxml/deserializer-normalization.xsl";
+                InputStream xsltStream = getClass().getResourceAsStream( xslPath );
+                normalizationTransformer = transformerFactory.newTransformer( new StreamSource( xsltStream ) );
+                normalizationTransformer.setOutputProperty( OutputKeys.METHOD, "xml" );
+                normalizationTransformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "no" );
+                normalizationTransformer.setOutputProperty( OutputKeys.VERSION, "1.1" );
+                normalizationTransformer.setOutputProperty( OutputKeys.STANDALONE, "yes" );
+                normalizationTransformer.setOutputProperty( OutputKeys.ENCODING, UTF_8.name() );
+                normalizationTransformer.setOutputProperty( OutputKeys.INDENT, "no" );
+            }
+            catch( ParserConfigurationException | TransformerConfigurationException ex )
+            {
+                throw new SerializationException( "Unable to setup the XML subsystem", ex );
+            }
+        }
+
+        @Override
+        public DocumentBuilderFactory documentBuilderFactory()
+        {
+            return documentBuilderFactory;
+        }
+
+        @Override
+        public Document newDocumentForSerialization()
+        {
+            try
+            {
+                DocumentBuilder docBuilder = documentBuilderFactory.newDocumentBuilder();
+                Document doc = docBuilder.newDocument();
+                doc.setXmlVersion( "1.1" );
+                doc.setXmlStandalone( true );
+                return doc;
+            }
+            catch( ParserConfigurationException ex )
+            {
+                throw new SerializationException( "Unable to create XML document. "
+                                                  + "Is your javax.xml subsystem correctly set up?", ex );
+            }
+        }
+
+        @Override
+        public TransformerFactory transformerFactory()
+        {
+            return transformerFactory;
+        }
+
+        @Override
+        public Transformer serializationTransformer()
+        {
+            return serializationTransformer;
+        }
+
+        @Override
+        public Transformer normalizationTransformer()
+        {
+            return normalizationTransformer;
+        }
+    }
+}
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerialization.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerialization.java
new file mode 100644
index 0000000..529bdee
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerialization.java
@@ -0,0 +1,88 @@
+/*
+ *  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.polygene.serialization.javaxxml;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.spi.serialization.XmlSerialization;
+
+/**
+ * javax.xml state serialization.
+ *
+ * The XML representations consumed and produced by this service are, by default, verbose, and safe to deserialize.
+ * This is because the default mapping is purely structural.
+ * You can customize the XML representations using {@link JavaxXmlSettings} and {@link JavaxXmlAdapters}.
+ *
+ * The following describe how state is represented by default.
+ *
+ * Because a valid XML document can only contain a single node and it must be an element, all
+ * {@link org.w3c.dom.Document}s have a root element {@literal &lt;state/&gt;}. This serialization implementation
+ * also impose that the root element can only contain a single node, of any type.
+ *
+ * {@literal null} is represented as {@literal &lt;null/&gt;}.
+ * Plain values are represented as {@link org.w3c.dom.Text} nodes.
+ * Iterables and Streams are represented as {@literal &lt;collection/&gt;} {@link org.w3c.dom.Element}s.
+ * Maps are represented as {@literal &lt;dictionary/&gt;} {@link org.w3c.dom.Element}s.
+ *
+ * This is how a {@literal null} plain value is represented: {@literal &lt;state&gt;&lt;null/&gt;&lt;/state&gt;}.
+ * And a plain {@literal LocalDate}: {@literal &lt;state&gt;2017-01-01&lt;/state&gt;}
+ *
+ * This is how a fictional value including a collection and a map is represented:
+ * <code>
+ *     &lt;state&gt;
+ *         &lt;stringProperty&gt;and it's value&lt;/stringProperty&gt;
+ *         &lt;bigDecimalProperty&gt;4.22376931348623157E+310&lt;/bigDecimalProperty&gt;
+ *         &lt;nullProperty&gt;&lt;null/&gt;&lt;/nullProperty&gt;
+ *         &lt;booleanProperty&gt;false&lt;/booleanProperty&gt;
+ *         &lt;stringCollectionProperty&gt;
+ *             &lt;collection&gt;
+ *                  item1
+ *                  item2 &lt;!-- As multiple text nodes --&gt;
+ *             &lt;/collection&gt;
+ *         &lt;/stringCollectionProperty&gt;
+ *         &lt;mapProperty&gt;
+ *             &lt;map&gt;
+ *                 &lt;foo&gt;bar&lt;/foo&gt;
+ *                 &lt;bazar&gt;cathedral&lt;/bazar&gt;
+ *             &lt;/map&gt;
+ *         &lt;/mapProperty&gt;
+ *         &lt;complexKeyMapProperty&gt;
+ *             &lt;map&gt;
+ *                 &lt;entry&gt;
+ *                     &lt;key&gt;
+ *                         &lt;foo&gt;bar&lt;/foo&gt;
+ *                         &lt;bazar&gt;cathedral&lt;/bazar&gt;
+ *                     &lt;/key&gt;
+ *                     &lt;value&gt;23&lt;/value&gt;
+ *                 &lt;/entry&gt;
+ *                 &lt;entry&gt;
+ *                     &lt;key&gt;
+ *                         &lt;foo&gt;baz&lt;/foo&gt;
+ *                         &lt;bazar&gt;bar&lt;/bazar&gt;
+ *                     &lt;/key&gt;
+ *                     &lt;value&gt;42&lt;/value&gt;
+ *                 &lt;/entry&gt;
+ *             &lt;/map&gt;
+ *         &lt;/complexKeyMapProperty&gt;
+ *     &lt;/state&gt;
+ * </code>
+ *
+ */
+@Mixins( { JavaxXmlSerializer.class, JavaxXmlDeserializer.class } )
+public interface JavaxXmlSerialization extends XmlSerialization
+{
+}
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializer.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializer.java
new file mode 100644
index 0000000..d1f8beb
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializer.java
@@ -0,0 +1,319 @@
+/*
+ *  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.polygene.serialization.javaxxml;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.io.Writer;
+import java.util.Base64;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.composite.StatefulAssociationCompositeDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.serialization.Converter;
+import org.apache.polygene.api.serialization.Converters;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.type.ArrayType;
+import org.apache.polygene.api.type.EnumType;
+import org.apache.polygene.api.type.MapType;
+import org.apache.polygene.api.type.StatefulAssociationValueType;
+import org.apache.polygene.spi.serialization.AbstractTextSerializer;
+import org.apache.polygene.spi.serialization.XmlSerializer;
+import org.apache.polygene.spi.util.ArrayIterable;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.polygene.api.util.Collectors.toMap;
+
+/**
+ * XML Serializer.
+ */
+public class JavaxXmlSerializer extends AbstractTextSerializer
+    implements XmlSerializer, Initializable
+{
+    private static final String NULL_ELEMENT_NAME = "null";
+
+    @This
+    private JavaxXmlFactories xmlFactories;
+
+    @This
+    private Converters converters;
+
+    @This
+    private JavaxXmlAdapters adapters;
+
+    @Uses
+    private ServiceDescriptor descriptor;
+
+    private JavaxXmlSettings settings;
+
+    @Override
+    public void initialize() throws Exception
+    {
+        settings = JavaxXmlSettings.orDefault( descriptor.metaInfo( JavaxXmlSettings.class ) );
+    }
+
+    @Override
+    public void serialize( Options options, Writer writer, @Optional Object object )
+    {
+        Document xmlDocument = toXml( options, object );
+        if( xmlDocument == null )
+        {
+            return;
+        }
+        try
+        {
+            // We want plain text nodes to be serialized without surrounding elements
+            if( xmlDocument.getNodeType() == Node.TEXT_NODE )
+            {
+                writer.write( xmlDocument.getNodeValue() );
+            }
+            else
+            {
+                xmlFactories.serializationTransformer().transform( new DOMSource( xmlDocument ),
+                                                                   new StreamResult( writer ) );
+            }
+        }
+        catch( IOException ex )
+        {
+            throw new UncheckedIOException( ex );
+        }
+        catch( TransformerException ex )
+        {
+            throw new SerializationException( "Unable to transform XML Document to String", ex );
+        }
+    }
+
+    @Override
+    public <T> Function<T, Document> toXmlFunction( Options options )
+    {
+        return object -> doSerializeRoot( options, object );
+    }
+
+    private <T> Document doSerializeRoot( Options options, T object )
+    {
+        Document doc = xmlFactories.newDocumentForSerialization();
+        Element stateElement = doc.createElement( settings.getRootTagName() );
+        Node node = doSerialize( doc, options, object, true );
+        stateElement.appendChild( node );
+        doc.appendChild( stateElement );
+        return doc;
+    }
+
+    private <T> Node doSerialize( Document document, Options options, T object, boolean root )
+    {
+        if( object == null )
+        {
+            return document.createElement( NULL_ELEMENT_NAME );
+        }
+        Class<?> objectClass = object.getClass();
+        Converter<Object> converter = converters.converterFor( objectClass );
+        if( converter != null )
+        {
+            return doSerialize( document, options, converter.toString( object ), false );
+        }
+        JavaxXmlAdapter<?> adapter = adapters.adapterFor( objectClass );
+        if( adapter != null )
+        {
+            return adapter.serialize( document, object, value -> doSerialize( document, options, value, false ) );
+        }
+        if( EnumType.isEnum( objectClass ) )
+        {
+            return document.createTextNode( object.toString() );
+        }
+        if( StatefulAssociationValueType.isStatefulAssociationValue( objectClass ) )
+        {
+            return serializeStatefulAssociationValue( document, options, object, root );
+        }
+        if( MapType.isMap( objectClass ) )
+        {
+            return serializeMap( document, options, (Map<?, ?>) object );
+        }
+        if( ArrayType.isArray( objectClass ) )
+        {
+            return serializeArray( document, options, object );
+        }
+        if( Iterable.class.isAssignableFrom( objectClass ) )
+        {
+            return serializeIterable( document, options, (Iterable<?>) object );
+        }
+        if( Stream.class.isAssignableFrom( objectClass ) )
+        {
+            return serializeStream( document, options, (Stream<?>) object );
+        }
+        throw new SerializationException( "Don't know how to serialize " + object );
+    }
+
+    private <T> Node serializeStatefulAssociationValue( Document document, Options options, T composite, boolean root )
+    {
+        CompositeInstance instance = PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF.apply( (Composite) composite );
+        StatefulAssociationCompositeDescriptor descriptor =
+            (StatefulAssociationCompositeDescriptor) instance.descriptor();
+        AssociationStateHolder state = (AssociationStateHolder) instance.state();
+        StatefulAssociationValueType<?> valueType = descriptor.valueType();
+
+        Element valueElement = document.createElement( settings.getValueTagName() );
+        valueType.properties().forEach(
+            property ->
+            {
+                Object value = state.propertyFor( property.accessor() ).get();
+                Converter<Object> converter = converters.converterFor( property );
+                if( converter != null )
+                {
+                    value = converter.toString( value );
+                }
+                Element element = document.createElement( property.qualifiedName().name() );
+                element.appendChild( doSerialize( document, options, value, false ) );
+                valueElement.appendChild( element );
+            } );
+        valueType.associations().forEach(
+            association ->
+            {
+                EntityReference value = state.associationFor( association.accessor() ).reference();
+                Element element = document.createElement( association.qualifiedName().name() );
+                element.appendChild( doSerialize( document, options, value, false ) );
+                valueElement.appendChild( element );
+            }
+        );
+        valueType.manyAssociations().forEach(
+            association ->
+            {
+                Stream<EntityReference> value = state.manyAssociationFor( association.accessor() ).references();
+                Element element = document.createElement( association.qualifiedName().name() );
+                element.appendChild( doSerialize( document, options, value, false ) );
+                valueElement.appendChild( element );
+            }
+        );
+        valueType.namedAssociations().forEach(
+            association ->
+            {
+                Map<String, EntityReference> value = state.namedAssociationFor( association.accessor() ).references()
+                                                          .collect( toMap() );
+                Element element = document.createElement( association.qualifiedName().name() );
+                element.appendChild( doSerialize( document, options, value, false ) );
+                valueElement.appendChild( element );
+            }
+        );
+        if( ( root && options.rootTypeInfo() ) || ( !root && options.nestedTypeInfo() ) )
+        {
+            valueElement.setAttribute( settings.getTypeInfoTagName(), valueType.primaryType().getName() );
+        }
+        return valueElement;
+    }
+
+    private Node serializeMap( Document document, Options options, Map<?, ?> map )
+    {
+        Element mapElement = document.createElement( settings.getMapTagName() );
+        if( map.isEmpty() )
+        {
+            return mapElement;
+        }
+        Function<Map.Entry, Node> complexMapping = entry ->
+        {
+            Element entryElement = document.createElement( settings.getMapEntryTagName() );
+
+            Element keyElement = document.createElement( "key" );
+            keyElement.appendChild( doSerialize( document, options, entry.getKey(), false ) );
+            entryElement.appendChild( keyElement );
+
+            Element valueElement = document.createElement( "value" );
+            valueElement.appendChild( doSerialize( document, options, entry.getValue(), false ) );
+            entryElement.appendChild( valueElement );
+
+            return entryElement;
+        };
+
+        if( map.keySet().iterator().next() instanceof CharSequence )
+        {
+            map.entrySet().stream()
+               .map( entry ->
+                     {
+                         try
+                         {
+                             Element element = document.createElement( entry.getKey().toString() );
+                             element.appendChild( doSerialize( document, options, entry.getValue(), false ) );
+                             return element;
+                         }
+                         catch( DOMException ex )
+                         {
+                             // The key name cannot be encoded as a tag name, fallback to complex mapping
+                             // Tag names cannot start with a digit, some characters cannot be escaped etc...
+                             return complexMapping.apply( entry );
+                         }
+                     } )
+               .forEach( mapElement::appendChild );
+        }
+        else
+        {
+            map.entrySet().stream()
+               .map( complexMapping )
+               .forEach( mapElement::appendChild );
+        }
+        return mapElement;
+    }
+
+    private <T> Node serializeArray( Document document, Options options, T object )
+    {
+        ArrayType valueType = ArrayType.of( object.getClass() );
+        if( valueType.isArrayOfPrimitiveBytes() )
+        {
+            byte[] base64 = Base64.getEncoder().encode( (byte[]) object );
+            return document.createCDATASection( new String( base64, UTF_8 ) );
+        }
+        if( valueType.isArrayOfPrimitives() )
+        {
+            return serializeIterable( document, options, new ArrayIterable( object ) );
+        }
+        return serializeStream( document, options, Stream.of( (Object[]) object ) );
+    }
+
+    private Node serializeIterable( Document document, Options options, Iterable<?> object )
+    {
+        return serializeStream( document, options, StreamSupport.stream( object.spliterator(), false ) );
+    }
+
+    private Node serializeStream( Document document, Options options, Stream<?> object )
+    {
+        Element collectionElement = document.createElement( settings.getCollectionTagName() );
+        object.map( each -> doSerialize( document, options, each, false ) )
+              .forEach( itemValueNode ->
+                        {
+                            Element itemElement = document.createElement( settings.getCollectionElementTagName() );
+                            itemElement.appendChild( itemValueNode );
+                            collectionElement.appendChild( itemElement );
+                        } );
+        return collectionElement;
+    }
+}
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSettings.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSettings.java
new file mode 100644
index 0000000..ab7448c
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSettings.java
@@ -0,0 +1,222 @@
+/*
+ *  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.polygene.serialization.javaxxml;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import javax.xml.XMLConstants;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.spi.serialization.SerializationSettings;
+
+/**
+ * javax.xml settings.
+ *
+ * Must be registered as meta-info at assembly time.
+ */
+public class JavaxXmlSettings extends SerializationSettings<JavaxXmlSettings>
+{
+    public static final JavaxXmlSettings DEFAULT = new JavaxXmlSettings();
+
+    public static JavaxXmlSettings orDefault( JavaxXmlSettings settings )
+    {
+        return settings != null ? settings : DEFAULT;
+    }
+
+    private String documentBuilderFactoryClassName;
+    private Map<String, Boolean> documentBuilderFactoryFeatures;
+    private Map<String, Object> documentBuilderFactoryAttributes;
+
+    private String transformerFactoryClassName;
+    private Map<String, Boolean> transformerFactoryFeatures;
+    private Map<String, Object> transformerFactoryAttributes;
+
+    private String rootTagName;
+    private String collectionTagName;
+    private String collectionElementTagName;
+    private String mapTagName;
+    private String mapEntryTagName;
+    private String valueTagName;
+    private String typeInfoTagName;
+
+    private Map<ValueType, JavaxXmlAdapter<?>> adapters;
+
+    public JavaxXmlSettings()
+    {
+        documentBuilderFactoryFeatures = new HashMap<String, Boolean>()
+        {{
+            put( XMLConstants.FEATURE_SECURE_PROCESSING, true );
+        }};
+        documentBuilderFactoryAttributes = new HashMap<>();
+
+        transformerFactoryFeatures = new HashMap<String, Boolean>()
+        {{
+            put( XMLConstants.FEATURE_SECURE_PROCESSING, true );
+        }};
+        transformerFactoryAttributes = new HashMap<String, Object>()
+        {{
+            put( XMLConstants.ACCESS_EXTERNAL_DTD, "" );
+            put( XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "" );
+        }};
+
+        rootTagName = "state";
+        collectionTagName = "collection";
+        collectionElementTagName = "element";
+        mapTagName = "map";
+        mapEntryTagName = "entry";
+        valueTagName = "value";
+        typeInfoTagName = "_type";
+
+        adapters = new LinkedHashMap<>();
+    }
+
+    public String getDocumentBuilderFactoryClassName()
+    {
+        return documentBuilderFactoryClassName;
+    }
+
+    public void setDocumentBuilderFactoryClassName( String documentBuilderFactoryClassName )
+    {
+        this.documentBuilderFactoryClassName = documentBuilderFactoryClassName;
+    }
+
+    public Map<String, Boolean> getDocumentBuilderFactoryFeatures()
+    {
+        return documentBuilderFactoryFeatures;
+    }
+
+    public void setDocumentBuilderFactoryFeatures( Map<String, Boolean> documentBuilderFactoryFeatures )
+    {
+        this.documentBuilderFactoryFeatures = documentBuilderFactoryFeatures;
+    }
+
+    public Map<String, Object> getDocumentBuilderFactoryAttributes()
+    {
+        return documentBuilderFactoryAttributes;
+    }
+
+    public void setDocumentBuilderFactoryAttributes( Map<String, Object> documentBuilderFactoryAttributes )
+    {
+        this.documentBuilderFactoryAttributes = documentBuilderFactoryAttributes;
+    }
+
+    public String getTransformerFactoryClassName()
+    {
+        return transformerFactoryClassName;
+    }
+
+    public void setTransformerFactoryClassName( String transformerFactoryClassName )
+    {
+        this.transformerFactoryClassName = transformerFactoryClassName;
+    }
+
+    public Map<String, Boolean> getTransformerFactoryFeatures()
+    {
+        return transformerFactoryFeatures;
+    }
+
+    public void setTransformerFactoryFeatures( Map<String, Boolean> transformerFactoryFeatures )
+    {
+        this.transformerFactoryFeatures = transformerFactoryFeatures;
+    }
+
+    public Map<String, Object> getTransformerFactoryAttributes()
+    {
+        return transformerFactoryAttributes;
+    }
+
+    public void setTransformerFactoryAttributes( Map<String, Object> transformerFactoryAttributes )
+    {
+        this.transformerFactoryAttributes = transformerFactoryAttributes;
+    }
+
+    public String getRootTagName()
+    {
+        return rootTagName;
+    }
+
+    public void setRootTagName( final String rootTagName )
+    {
+        this.rootTagName = rootTagName;
+    }
+
+    public String getCollectionTagName()
+    {
+        return collectionTagName;
+    }
+
+    public void setCollectionTagName( final String collectionTagName )
+    {
+        this.collectionTagName = collectionTagName;
+    }
+
+    public String getCollectionElementTagName()
+    {
+        return collectionElementTagName;
+    }
+
+    public void setCollectionElementTagName( final String collectionElementTagName )
+    {
+        this.collectionElementTagName = collectionElementTagName;
+    }
+
+    public String getMapTagName()
+    {
+        return mapTagName;
+    }
+
+    public void setMapTagName( final String mapTagName )
+    {
+        this.mapTagName = mapTagName;
+    }
+
+    public String getMapEntryTagName()
+    {
+        return mapEntryTagName;
+    }
+
+    public void setMapEntryTagName( final String mapEntryTagName )
+    {
+        this.mapEntryTagName = mapEntryTagName;
+    }
+
+    public String getValueTagName()
+    {
+        return valueTagName;
+    }
+
+    public void setValueTagName( final String valueTagName )
+    {
+        this.valueTagName = valueTagName;
+    }
+
+    public String getTypeInfoTagName()
+    {
+        return typeInfoTagName;
+    }
+
+    public void setTypeInfoTagName( final String typeInfoTagName )
+    {
+        this.typeInfoTagName = typeInfoTagName;
+    }
+
+    public Map<ValueType, JavaxXmlAdapter<?>> getAdapters()
+    {
+        return adapters;
+    }
+}
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/assembly/JavaxXmlSerializationAssembler.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/assembly/JavaxXmlSerializationAssembler.java
new file mode 100644
index 0000000..e6a69f5
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/assembly/JavaxXmlSerializationAssembler.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.serialization.javaxxml.assembly;
+
+import org.apache.polygene.api.serialization.Converters;
+import org.apache.polygene.api.serialization.Deserializer;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.serialization.javaxxml.JavaxXmlAdapters;
+import org.apache.polygene.serialization.javaxxml.JavaxXmlFactories;
+import org.apache.polygene.serialization.javaxxml.JavaxXmlSerialization;
+import org.apache.polygene.serialization.javaxxml.JavaxXmlSettings;
+import org.apache.polygene.spi.serialization.XmlDeserializer;
+import org.apache.polygene.spi.serialization.XmlSerialization;
+import org.apache.polygene.spi.serialization.XmlSerializer;
+
+public class JavaxXmlSerializationAssembler extends Assemblers.VisibilityIdentity<JavaxXmlSerializationAssembler>
+{
+    private JavaxXmlSettings settings;
+
+    public JavaxXmlSerializationAssembler withXmlSettings( JavaxXmlSettings settings )
+    {
+        this.settings = settings;
+        return this;
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        ServiceDeclaration declaration = module.services( JavaxXmlSerialization.class )
+                                               .withTypes( Serialization.class,
+                                                           Serializer.class, Deserializer.class,
+                                                           Converters.class,
+                                                           XmlSerialization.class,
+                                                           XmlSerializer.class, XmlDeserializer.class,
+                                                           JavaxXmlFactories.class, JavaxXmlAdapters.class )
+                                               .taggedWith( Serialization.Format.XML )
+                                               .visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            declaration.identifiedBy( identity() );
+        }
+        if( settings != null )
+        {
+            declaration.setMetaInfo( settings );
+        }
+    }
+}
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/assembly/package.html b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/assembly/package.html
new file mode 100644
index 0000000..fa00039
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>javax.xml Serialization Assembly.</h2>
+    </body>
+</html>
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/package.html b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/package.html
new file mode 100644
index 0000000..f81a030
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>javax.xml Serialization.</h2>
+    </body>
+</html>
diff --git a/extensions/serialization-javaxxml/src/main/resources/org/apache/polygene/serialization/javaxxml/deserializer-normalization.xsl b/extensions/serialization-javaxxml/src/main/resources/org/apache/polygene/serialization/javaxxml/deserializer-normalization.xsl
new file mode 100644
index 0000000..e7495d7
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/main/resources/org/apache/polygene/serialization/javaxxml/deserializer-normalization.xsl
@@ -0,0 +1,26 @@
+<?xml version="1.1" encoding="UTF-8" standalone="yes"?>
+<!--
+  ~  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.
+  -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+    <xsl:strip-space elements="*"/>
+    <xsl:template match="@*|node()">
+        <xsl:copy>
+            <xsl:apply-templates select="@*|node()"/>
+        </xsl:copy>
+    </xsl:template>
+</xsl:stylesheet>
diff --git a/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/HandCraftedXmlTest.java b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/HandCraftedXmlTest.java
new file mode 100644
index 0000000..18f251a
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/HandCraftedXmlTest.java
@@ -0,0 +1,146 @@
+/*
+ *  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.polygene.serialization.javaxxml;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.serialization.Deserializer;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxxml.assembly.JavaxXmlSerializationAssembler;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+public class HandCraftedXmlTest extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        new JavaxXmlSerializationAssembler().assemble( module );
+        module.values( SomeValue.class );
+    }
+
+    public interface SomeValue
+    {
+        @Optional
+        Property<String> foo();
+    }
+
+    @Service
+    private Deserializer deserializer;
+
+    @Test
+    public void canReadSingleLineXml()
+    {
+        String xml = "<state><value><foo>bar</foo></value></state>";
+        assertThat( deserializer.deserialize( module, SomeValue.class, xml ).foo().get(),
+                    equalTo( "bar" ) );
+    }
+
+    @Test
+    public void canReadMultiLineXml()
+    {
+        String xml = "<state>\n<value>\n<foo>bar</foo>\n</value>\n</state>";
+        assertThat( deserializer.deserialize( module, SomeValue.class, xml ).foo().get(),
+                    equalTo( "bar" ) );
+    }
+
+    @Test
+    public void canReadIndentedMultiLineXml()
+    {
+        String xml = "<state>\n\t<value>\n\t\t<foo>bar</foo>\n\t</value>\n</state>";
+        assertThat( deserializer.deserialize( module, SomeValue.class, xml ).foo().get(),
+                    equalTo( "bar" ) );
+    }
+
+    @Test
+    public void canReadSingleLineXmlWithMultilineStringValue()
+    {
+        String xml = "<state><value><foo>bar\nbaz\n</foo></value></state>";
+        assertThat( deserializer.deserialize( module, SomeValue.class, xml ).foo().get(),
+                    equalTo( "bar\nbaz\n" ) );
+    }
+
+    @Test
+    public void canReadMultiLineXmlWithMultilineStringValue()
+    {
+        String xml = "<state>\n<value>\n<foo>bar\nbaz\n</foo>\n</value>\n</state>";
+        assertThat( deserializer.deserialize( module, SomeValue.class, xml ).foo().get(),
+                    equalTo( "bar\nbaz\n" ) );
+    }
+
+    @Test
+    public void canReadIndentedMultiLineXmlWithMultilineStringValue()
+    {
+        String xml = "<state>\n\t<value>\n\t\t<foo>bar\nbaz\n</foo>\n\t</value>\n</state>";
+        assertThat( deserializer.deserialize( module, SomeValue.class, xml ).foo().get(),
+                    equalTo( "bar\nbaz\n" ) );
+    }
+
+    @Test
+    public void canReadCommentedXml()
+    {
+        String xml = "<state><value><!-- Some comment --><foo>bar</foo></value></state>";
+        assertThat( deserializer.deserialize( module, SomeValue.class, xml ).foo().get(),
+                    equalTo( "bar" ) );
+    }
+
+    @Test
+    public void canReadMultilineCommentedXml()
+    {
+        String xml = "<state>\n<value>\n<!-- Some comment -->\n<foo>bar</foo>\n</value>\n</state>";
+        assertThat( deserializer.deserialize( module, SomeValue.class, xml ).foo().get(),
+                    equalTo( "bar" ) );
+    }
+
+    @Test
+    public void canReadIndentedMultilineCommentedXml()
+    {
+        String xml = "<state>\n\t<value>\n\t\t<!-- Some comment -->\n\t\t<foo>bar</foo>\n\t</value>\n</state>";
+        assertThat( deserializer.deserialize( module, SomeValue.class, xml ).foo().get(),
+                    equalTo( "bar" ) );
+    }
+
+    @Test
+    public void canReadIndentedMultilineCommentedXmlWithMultilineStringValue()
+    {
+        String xml = "<state>\n\t<value>\n\t\t<!-- Some comment -->\n\t\t<foo>bar\nbaz\n</foo>\n\t</value>\n</state>";
+        assertThat( deserializer.deserialize( module, SomeValue.class, xml ).foo().get(),
+                    equalTo( "bar\nbaz\n" ) );
+    }
+
+    @Test
+    public void canReadIndentedMultilineCommentedXmlWithTextValueStartingWithNewLine()
+    {
+        String xml
+            = "<state>\n\t<value>\n\t\t<!-- Some comment -->\n\t\t<foo>\n\t\t\tbar\n\t\t\tbaz\n</foo>\n\t</value>\n</state>";
+        assertThat( deserializer.deserialize( module, SomeValue.class, xml ).foo().get(),
+                    equalTo( "\n\t\t\tbar\n\t\t\tbaz\n" ) );
+    }
+
+    @Test
+    public void canReadIndentedMultilineXmlWithNullValues()
+    {
+        String xml = "<state>\n\t<value>\n\t\t<foo>\n<null/>\n</foo>\n\t</value>\n</state>";
+        assertThat( deserializer.deserialize( module, SomeValue.class, xml ).foo().get(), nullValue() );
+    }
+}
diff --git a/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdaptersTest.java b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdaptersTest.java
new file mode 100644
index 0000000..f68ccb4
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlAdaptersTest.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.serialization.javaxxml;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxxml.assembly.JavaxXmlSerializationAssembler;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class JavaxXmlAdaptersTest extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        new JavaxXmlSerializationAssembler().assemble( module );
+        module.services( JavaxXmlSerialization.class )
+              .withTypes( JavaxXmlAdapters.class );
+    }
+
+    @Service
+    private JavaxXmlAdapters adapters;
+
+    @Test
+    public void test() throws ParserConfigurationException
+    {
+        JavaxXmlAdapter<String> adapter = adapters.adapterFor( String.class );
+        Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+        String original = "Cou<cou>€ôÙÔ#‰¥Ô";
+        Node node = adapter.serialize( doc, original, null );
+        assertThat( node.getNodeValue(), equalTo( original ) );
+        String result = adapter.deserialize( node, null );
+        assertThat( result, equalTo( original ) );
+    }
+}
diff --git a/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlCollectionTest.java b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlCollectionTest.java
new file mode 100644
index 0000000..a78ea9b
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlCollectionTest.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.serialization.javaxxml;
+
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxxml.assembly.JavaxXmlSerializationAssembler;
+import org.apache.polygene.test.serialization.AbstractCollectionSerializationTest;
+
+public class JavaxXmlCollectionTest extends AbstractCollectionSerializationTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        new JavaxXmlSerializationAssembler().assemble( module );
+        super.assemble( module );
+    }
+}
diff --git a/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlConfigurationDeserializationTest.java b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlConfigurationDeserializationTest.java
new file mode 100644
index 0000000..6e1a236
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlConfigurationDeserializationTest.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.serialization.javaxxml;
+
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxxml.assembly.JavaxXmlSerializationAssembler;
+import org.apache.polygene.test.entity.AbstractConfigurationDeserializationTest;
+
+public class JavaxXmlConfigurationDeserializationTest extends AbstractConfigurationDeserializationTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        new JavaxXmlSerializationAssembler().assemble( module );
+        super.assemble( module );
+    }
+}
diff --git a/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlConvertersSerializationTest.java b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlConvertersSerializationTest.java
new file mode 100644
index 0000000..1562665
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlConvertersSerializationTest.java
@@ -0,0 +1,67 @@
+/*
+ *  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.polygene.serialization.javaxxml;
+
+import java.io.StringReader;
+import java.util.Optional;
+import javax.xml.parsers.DocumentBuilder;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxxml.assembly.JavaxXmlSerializationAssembler;
+import org.apache.polygene.test.serialization.AbstractConvertersSerializationTest;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+
+public class JavaxXmlConvertersSerializationTest extends AbstractConvertersSerializationTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        new JavaxXmlSerializationAssembler().assemble( module );
+        super.assemble( module );
+    }
+
+    @Service
+    private JavaxXmlFactories xmlFactories;
+
+    @Override
+    protected String getStringFromValueState( String state, String key ) throws Exception
+    {
+        JavaxXmlSettings settings = serviceFinder.findService( JavaxXmlSerialization.class )
+                                                 .metaInfo( JavaxXmlSettings.class );
+        settings = JavaxXmlSettings.orDefault( settings );
+        DocumentBuilder docBuilder = xmlFactories.documentBuilderFactory().newDocumentBuilder();
+        Document doc = docBuilder.parse( new InputSource( new StringReader( state ) ) );
+        Optional<Element> stateElement = JavaxXml.firstChildElementNamed( doc, settings.getRootTagName() );
+        if( stateElement.isPresent() )
+        {
+            Optional<Element> valueNode = JavaxXml.firstChildElementNamed( stateElement.get(),
+                                                                           settings.getValueTagName() );
+            if( valueNode.isPresent() )
+            {
+                Optional<Element> element = JavaxXml.firstChildElementNamed( valueNode.get(), key );
+                if( element.isPresent() )
+                {
+                    return element.get().getFirstChild().getNodeValue();
+                }
+            }
+        }
+        return null;
+    }
+}
diff --git a/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlPlainValueSerializationTest.java b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlPlainValueSerializationTest.java
new file mode 100644
index 0000000..dd55670
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlPlainValueSerializationTest.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.serialization.javaxxml;
+
+import java.io.StringReader;
+import java.util.Optional;
+import javax.xml.parsers.DocumentBuilder;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxxml.assembly.JavaxXmlSerializationAssembler;
+import org.apache.polygene.test.serialization.AbstractPlainValueSerializationTest;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.InputSource;
+
+public class JavaxXmlPlainValueSerializationTest extends AbstractPlainValueSerializationTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        new JavaxXmlSerializationAssembler().withXmlSettings( withTestSettings( new JavaxXmlSettings() ) )
+                                            .assemble( module );
+    }
+
+    @Service
+    private JavaxXmlFactories xmlFactories;
+
+    @Override
+    protected String getSingleStringRawState( String state ) throws Exception
+    {
+        JavaxXmlSettings settings = serviceFinder.findService( JavaxXmlSerialization.class )
+                                                 .metaInfo( JavaxXmlSettings.class );
+        settings = JavaxXmlSettings.orDefault( settings );
+        DocumentBuilder docBuilder = xmlFactories.documentBuilderFactory().newDocumentBuilder();
+        Document doc = docBuilder.parse( new InputSource( new StringReader( state ) ) );
+        Optional<Element> stateElement = JavaxXml.firstChildElementNamed( doc, settings.getRootTagName() );
+        if( stateElement.isPresent() )
+        {
+            Optional<Node> stateNode = JavaxXml.firstStateChildNode( stateElement.get() );
+            return stateNode.map( Node::getNodeValue ).orElse( "" );
+        }
+        return null;
+    }
+}
diff --git a/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlValueCompositeSerializationTest.java b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlValueCompositeSerializationTest.java
new file mode 100644
index 0000000..7ded112
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlValueCompositeSerializationTest.java
@@ -0,0 +1,81 @@
+/*
+ *  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.polygene.serialization.javaxxml;
+
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxxml.assembly.JavaxXmlSerializationAssembler;
+import org.apache.polygene.spi.serialization.XmlSerialization;
+import org.apache.polygene.test.serialization.AbstractValueCompositeSerializationTest;
+import org.junit.Test;
+import org.xmlunit.diff.DefaultNodeMatcher;
+import org.xmlunit.diff.ElementSelectors;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.xmlunit.matchers.CompareMatcher.isSimilarTo;
+
+public class JavaxXmlValueCompositeSerializationTest extends AbstractValueCompositeSerializationTest
+{
+    // START SNIPPET: assembly
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        new JavaxXmlSerializationAssembler().assemble( module );
+        // END SNIPPET: assembly
+        super.assemble( module );
+        // START SNIPPET: assembly
+    }
+    // END SNIPPET: assembly
+
+    // START SNIPPET: xml-serialization
+    @Service
+    XmlSerialization xmlSerialization;
+    // END SNIPPET: xml-serialization
+
+    @Test
+    public void valueCompositeXmlEquality()
+    {
+        // START SNIPPET: xml-serialization
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            Some valueInstance = buildSomeValue( moduleInstance, uow, "42" );
+
+            // Serialize using injected service
+            String serializedXml = xmlSerialization.serialize( valueInstance );
+            System.out.println( serializedXml );
+
+            // Deserialize using Module API
+            Some valueFromSerializedState = moduleInstance.newValueFromSerializedState( Some.class, serializedXml );
+            assertThat( "Deserialized Value equality", valueInstance, equalTo( valueFromSerializedState ) );
+            // END SNIPPET: xml-serialization
+
+            // value.toString()
+            // Need to loosely compare because of HashMaps not retaining order
+            String valueXmlWithoutTypeInfo = xmlSerialization.serialize( Serializer.Options.NO_TYPE_INFO, valueFromSerializedState );
+            assertThat( "value.toString() XML equality",
+                        valueFromSerializedState.toString(),
+                        isSimilarTo( valueXmlWithoutTypeInfo )
+                            .withNodeMatcher( new DefaultNodeMatcher( ElementSelectors.byNameAndAllAttributes ) ) );
+            // START SNIPPET: xml-serialization
+        }
+        // END SNIPPET: xml-serialization
+    }
+}
diff --git a/extensions/serialization-javaxxml/src/test/resources/configtest.xml b/extensions/serialization-javaxxml/src/test/resources/configtest.xml
new file mode 100644
index 0000000..5bb3a3b
--- /dev/null
+++ b/extensions/serialization-javaxxml/src/test/resources/configtest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.1" encoding="UTF-8" standalone="yes"?>
+<!--
+  ~  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.
+  -->
+<state>
+    <value>
+        <identity>configtest</identity>
+        <host>
+            <value _type="org.apache.polygene.test.entity.AbstractConfigurationDeserializationTest$Host">
+                <ip>12.23.34.45</ip>
+                <port>1234</port>
+            </value>
+        </host>
+        <name>main</name>
+    </value>
+</state>
diff --git a/extensions/serialization-messagepack/build.gradle b/extensions/serialization-messagepack/build.gradle
new file mode 100644
index 0000000..6f51948
--- /dev/null
+++ b/extensions/serialization-messagepack/build.gradle
@@ -0,0 +1,36 @@
+/*
+ *  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.
+ */
+
+apply plugin: 'polygene-extension'
+
+description = "Apache Polygene™ MessagePack Serialization Extension"
+
+jar { manifest { name = "Apache Polygene™ Extension - Serialization - MessagePack" } }
+
+dependencies {
+  api polygene.core.bootstrap
+  api libraries.msgpack
+
+  implementation libraries.commons_lang
+
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/extensions/serialization-messagepack/dev-status.xml b/extensions/serialization-messagepack/dev-status.xml
new file mode 100644
index 0000000..a36ce79
--- /dev/null
+++ b/extensions/serialization-messagepack/dev-status.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
+    <status>
+        <!--none,early,beta,stable,mature-->
+        <codebase>beta</codebase>
+
+        <!-- none, brief, good, complete -->
+        <documentation>brief</documentation>
+
+        <!-- none, some, good, complete -->
+        <unittests>good</unittests>
+    </status>
+    <licenses>
+        <license>ALv2</license>
+    </licenses>
+</module>
\ No newline at end of file
diff --git a/extensions/serialization-messagepack/src/docs/serialization-messagepack.txt b/extensions/serialization-messagepack/src/docs/serialization-messagepack.txt
new file mode 100644
index 0000000..95ea7db
--- /dev/null
+++ b/extensions/serialization-messagepack/src/docs/serialization-messagepack.txt
@@ -0,0 +1,43 @@
+///////////////////////////////////////////////////////////////
+ * 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.
+///////////////////////////////////////////////////////////////
+
+[[extension-serialization-messagepack,MessagePack serialization]]
+= MessagePack serialization =
+
+[devstatus]
+--------------
+source=extensions/serialization-messagepack/dev-status.xml
+--------------
+
+`Serialization` service backed by http://msgpack.org/[MessagePack] that produce and consume binary payloads.
+See <<core-api-serialization>> and <<core-spi-serialization>>.
+
+include::../../build/docs/buildinfo/artifact.txt[]
+
+// TODO Include sample model and its output from test code & resources
+
+== Assembly ==
+
+Assembly is done using the provided Assembler:
+
+[snippet,java]
+----
+source=extensions/serialization-messagepack/src/test/java/org/apache/polygene/serialization/messagepack/MessagePackValueCompositeSerializationTest.java
+tag=assembly
+----
diff --git a/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackAdapter.java b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackAdapter.java
new file mode 100644
index 0000000..a2a5763
--- /dev/null
+++ b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackAdapter.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.serialization.messagepack;
+
+import java.io.IOException;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import org.apache.polygene.api.type.ValueType;
+import org.msgpack.value.Value;
+
+/**
+ * Adapter for MessagePack (de)serialization.
+ *
+ * @param <T> the adapted type
+ */
+public interface MessagePackAdapter<T>
+{
+    /**
+     * @return the adapted type
+     */
+    Class<T> type();
+
+    /**
+     * Serialize.
+     *
+     * @param object Object to serialize, never null
+     * @param serialize Serialization function for nested structure serialization
+     * @return MessagePack Value
+     */
+    Value serialize( Object object, Function<Object, Value> serialize )
+        throws IOException;
+
+    /**
+     * Deserialize.
+     *
+     * @param value MessagePack value
+     * @param deserialize Deserialization function for nested structure deserialization
+     * @return Deserialized object
+     */
+    T deserialize( Value value, BiFunction<Value, ValueType, Object> deserialize )
+        throws IOException;
+}
diff --git a/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackAdapters.java b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackAdapters.java
new file mode 100644
index 0000000..2b16ed7
--- /dev/null
+++ b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackAdapters.java
@@ -0,0 +1,269 @@
+/*
+ *  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.polygene.serialization.messagepack;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.serialization.Converters;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.spi.serialization.BuiltInConverters;
+import org.msgpack.value.Value;
+import org.msgpack.value.ValueFactory;
+
+import static org.apache.polygene.api.type.HasTypesCollectors.closestType;
+import static org.apache.polygene.serialization.messagepack.MessagePackSettings.orDefault;
+
+@Mixins( MessagePackAdapters.Mixin.class )
+public interface MessagePackAdapters
+{
+    void registerAdapter( ValueType valueType, MessagePackAdapter<?> adapter );
+
+    <T> MessagePackAdapter<T> adapterFor( ValueType valueType );
+
+    default <T> MessagePackAdapter<T> adapterFor( Class<T> type )
+    {
+        return adapterFor( ValueType.of( type ) );
+    }
+
+    class Mixin implements MessagePackAdapters, Initializable
+    {
+        private Map<ValueType, MessagePackAdapter<?>> adapters = new LinkedHashMap<>();
+
+        @Uses
+        private ServiceDescriptor descriptor;
+
+        @This
+        private BuiltInConverters builtInConverters;
+
+        @This
+        private Converters converters;
+
+        @Override
+        public void initialize()
+        {
+            MessagePackSettings settings = orDefault( descriptor.metaInfo( MessagePackSettings.class ) );
+            settings.getConverters()
+                    .forEach( ( type, converter ) -> converters.registerConverter( type, converter ) );
+            builtInConverters.registerBuiltInConverters( converters );
+            settings.getAdapters().forEach( adapters::put );
+            registerBaseMessagePackAdapters();
+        }
+
+        @Override
+        public void registerAdapter( ValueType valueType, MessagePackAdapter<?> adapter )
+        {
+            adapters.put( valueType, adapter );
+        }
+
+        @Override
+        public <T> MessagePackAdapter<T> adapterFor( final ValueType valueType )
+        {
+            return castAdapter( adapters.keySet().stream()
+                                        .collect( closestType( valueType ) )
+                                        .map( adapters::get )
+                                        .orElse( null ) );
+        }
+
+        @SuppressWarnings( "unchecked" )
+        private <T> MessagePackAdapter<T> castAdapter( MessagePackAdapter<?> adapter )
+        {
+            return (MessagePackAdapter<T>) adapter;
+        }
+
+        private void registerBaseMessagePackAdapters()
+        {
+            // Primitive Value types
+            adapters.put( ValueType.STRING, new StringAdapter() );
+            adapters.put( ValueType.CHARACTER, new CharacterAdapter() );
+            adapters.put( ValueType.BOOLEAN, new BooleanAdapter() );
+            adapters.put( ValueType.INTEGER, new IntegerAdapter() );
+            adapters.put( ValueType.LONG, new LongAdapter() );
+            adapters.put( ValueType.SHORT, new ShortAdapter() );
+            adapters.put( ValueType.BYTE, new ByteAdapter() );
+            adapters.put( ValueType.FLOAT, new FloatAdapter() );
+            adapters.put( ValueType.DOUBLE, new DoubleAdapter() );
+        }
+
+        private static abstract class ToStringAdapter<T> implements MessagePackAdapter<T>
+        {
+            @Override
+            public Value serialize( Object object, Function<Object, Value> serialize )
+            {
+                return ValueFactory.newString( object.toString() );
+            }
+        }
+
+        private static class StringAdapter extends ToStringAdapter<String>
+        {
+            @Override
+            public Class<String> type() { return String.class; }
+
+            @Override
+            public String deserialize( Value value, BiFunction<Value, ValueType, Object> deserialize )
+            {
+                return value.asStringValue().asString();
+            }
+        }
+
+        private static class CharacterAdapter extends ToStringAdapter<Character>
+        {
+            @Override
+            public Class<Character> type() { return Character.class; }
+
+            @Override
+            public Character deserialize( Value value, BiFunction<Value, ValueType, Object> deserialize )
+            {
+                String string = value.asStringValue().asString();
+                return string.isEmpty() ? null : string.charAt( 0 );
+            }
+        }
+
+        private static class BooleanAdapter implements MessagePackAdapter<Boolean>
+        {
+            @Override
+            public Class<Boolean> type() { return Boolean.class; }
+
+            @Override
+            public Value serialize( Object object, Function<Object, Value> serialize )
+            {
+                return ValueFactory.newBoolean( (Boolean) object );
+            }
+
+            @Override
+            public Boolean deserialize( Value value, BiFunction<Value, ValueType, Object> deserialize )
+            {
+                return value.asBooleanValue().getBoolean();
+            }
+        }
+
+        private static class IntegerAdapter implements MessagePackAdapter<Integer>
+        {
+            @Override
+            public Class<Integer> type() { return Integer.class; }
+
+            @Override
+            public Value serialize( Object object, Function<Object, Value> serialize )
+            {
+                return ValueFactory.newInteger( (Integer) object );
+            }
+
+            @Override
+            public Integer deserialize( Value value, BiFunction<Value, ValueType, Object> deserialize )
+            {
+                return value.asIntegerValue().asInt();
+            }
+        }
+
+        private static class LongAdapter implements MessagePackAdapter<Long>
+        {
+            @Override
+            public Class<Long> type() { return Long.class; }
+
+            @Override
+            public Value serialize( Object object, Function<Object, Value> serialize )
+            {
+                return ValueFactory.newInteger( (Long) object );
+            }
+
+            @Override
+            public Long deserialize( Value value, BiFunction<Value, ValueType, Object> deserialize )
+            {
+                return value.asIntegerValue().asLong();
+            }
+        }
+
+        private static class ShortAdapter implements MessagePackAdapter<Short>
+        {
+            @Override
+            public Class<Short> type() { return Short.class; }
+
+            @Override
+            public Value serialize( Object object, Function<Object, Value> serialize )
+            {
+                return ValueFactory.newInteger( (Short) object );
+            }
+
+            @Override
+            public Short deserialize( Value value, BiFunction<Value, ValueType, Object> deserialize )
+            {
+                return value.asIntegerValue().asShort();
+            }
+        }
+
+        private static class ByteAdapter implements MessagePackAdapter<Byte>
+        {
+            @Override
+            public Class<Byte> type() { return Byte.class; }
+
+            @Override
+            public Value serialize( Object object, Function<Object, Value> serialize )
+            {
+                return ValueFactory.newInteger( (Byte) object );
+            }
+
+            @Override
+            public Byte deserialize( Value value, BiFunction<Value, ValueType, Object> deserialize )
+            {
+                return value.asIntegerValue().asByte();
+            }
+        }
+
+        private static class FloatAdapter implements MessagePackAdapter<Float>
+        {
+            @Override
+            public Class<Float> type() { return Float.class; }
+
+            @Override
+            public Value serialize( Object object, Function<Object, Value> serialize )
+            {
+                return ValueFactory.newFloat( (Float) object );
+            }
+
+            @Override
+            public Float deserialize( Value value, BiFunction<Value, ValueType, Object> deserialize )
+            {
+                return value.asFloatValue().toFloat();
+            }
+        }
+
+        private static class DoubleAdapter implements MessagePackAdapter<Double>
+        {
+            @Override
+            public Class<Double> type() { return Double.class; }
+
+            @Override
+            public Value serialize( Object object, Function<Object, Value> serialize )
+            {
+                return ValueFactory.newFloat( (Double) object );
+            }
+
+            @Override
+            public Double deserialize( Value value, BiFunction<Value, ValueType, Object> deserialize )
+            {
+                return value.asFloatValue().toDouble();
+            }
+        }
+    }
+}
diff --git a/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackDeserializer.java b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackDeserializer.java
new file mode 100644
index 0000000..90d9586
--- /dev/null
+++ b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackDeserializer.java
@@ -0,0 +1,328 @@
+/*
+ *  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.polygene.serialization.messagepack;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Array;
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.StatefulAssociationCompositeDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.serialization.Converter;
+import org.apache.polygene.api.serialization.Converters;
+import org.apache.polygene.api.serialization.Deserializer;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ArrayType;
+import org.apache.polygene.api.type.CollectionType;
+import org.apache.polygene.api.type.EnumType;
+import org.apache.polygene.api.type.MapType;
+import org.apache.polygene.api.type.StatefulAssociationValueType;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.spi.serialization.AbstractBinaryDeserializer;
+import org.msgpack.core.MessagePack;
+import org.msgpack.core.MessageUnpacker;
+import org.msgpack.value.ArrayValue;
+import org.msgpack.value.ImmutableValue;
+import org.msgpack.value.MapValue;
+import org.msgpack.value.Value;
+
+import static java.util.Collections.unmodifiableList;
+import static java.util.Collections.unmodifiableMap;
+import static java.util.Collections.unmodifiableSet;
+import static org.apache.polygene.api.util.Collectors.toMap;
+
+@Mixins( MessagePackDeserializer.Mixin.class )
+public interface MessagePackDeserializer extends Deserializer
+{
+    class Mixin extends AbstractBinaryDeserializer
+    {
+        @This
+        private Converters converters;
+
+        @This
+        private MessagePackAdapters adapters;
+
+        @Override
+        public <T> T deserialize( ModuleDescriptor module, ValueType valueType, InputStream state )
+        {
+            try( MessageUnpacker unpacker = MessagePack.newDefaultUnpacker( state ) )
+            {
+                if( !unpacker.hasNext() )
+                {
+                    return null;
+                }
+                ImmutableValue value = unpacker.unpackValue();
+                return doDeserialize( module, valueType, value );
+            }
+            catch( IOException ex )
+            {
+                throw new SerializationException( "Unable to deserialize " + valueType, ex );
+            }
+        }
+
+        @SuppressWarnings( "unchecked" )
+        private <T> T doDeserialize( ModuleDescriptor module, ValueType valueType, Value value )
+        {
+            try
+            {
+                if( value == null || value.isNilValue() )
+                {
+                    return null;
+                }
+                Converter<Object> converter = converters.converterFor( valueType );
+                if( converter != null )
+                {
+                    return (T) converter.fromString( doDeserialize( module, ValueType.STRING, value ).toString() );
+                }
+                MessagePackAdapter<?> adapter = adapters.adapterFor( valueType );
+                if( adapter != null )
+                {
+                    return (T) adapter.deserialize( value, ( val, type ) -> doDeserialize( module, valueType, val ) );
+                }
+                Class<? extends ValueType> valueTypeClass = valueType.getClass();
+                if( EnumType.class.isAssignableFrom( valueTypeClass ) )
+                {
+                    return (T) Enum.valueOf( (Class) valueType.primaryType(), value.asStringValue().asString() );
+                }
+                if( ArrayType.class.isAssignableFrom( valueTypeClass ) )
+                {
+                    return (T) deserializeArray( module, (ArrayType) valueType, value );
+                }
+                if( CollectionType.class.isAssignableFrom( valueTypeClass ) )
+                {
+                    return (T) deserializeCollection( module, (CollectionType) valueType, value.asArrayValue() );
+                }
+                if( MapType.class.isAssignableFrom( valueTypeClass ) )
+                {
+                    return (T) deserializeMap( module, (MapType) valueType, value.asMapValue() );
+                }
+                if( StatefulAssociationValueType.class.isAssignableFrom( valueTypeClass ) )
+                {
+                    return (T) deserializeStatefulAssociationValue( module,
+                                                                    (StatefulAssociationValueType<?>) valueType,
+                                                                    value.asMapValue() );
+                }
+                return (T) doGuessDeserialize( module, valueType, value );
+            }
+            catch( IOException | ClassNotFoundException ex )
+            {
+                throw new SerializationException( "Unable to deserialize " + valueType + " from: " + value );
+            }
+        }
+
+        private Object deserializeArray( ModuleDescriptor module, ArrayType arrayType, Value value ) throws IOException
+        {
+            if( arrayType.isArrayOfPrimitiveBytes() )
+            {
+                return value.asBinaryValue().asByteArray();
+            }
+            CollectionType collectionType = CollectionType.listOf( arrayType.collectedType() );
+            List collection = (List) deserializeCollection( module, collectionType, value.asArrayValue() );
+            Object array = Array.newInstance( arrayType.collectedType().primaryType(), collection.size() );
+            for( int idx = 0; idx < collection.size(); idx++ )
+            {
+                Array.set( array, idx, collection.get( idx ) );
+            }
+            return array;
+        }
+
+        private Collection<?> deserializeCollection( ModuleDescriptor module, CollectionType collectionType,
+                                                     ArrayValue value ) throws IOException
+        {
+            Collection<?> collection = collectionType.isSet() ? new LinkedHashSet( value.size() )
+                                                              : new ArrayList( value.size() );
+            for( Value element : value.list() )
+            {
+                collection.add( doDeserialize( module, collectionType.collectedType(), element ) );
+            }
+            return collection;
+        }
+
+        private Map<Object, Object> deserializeMap( ModuleDescriptor module, MapType mapType, MapValue value )
+            throws IOException
+        {
+            Map<Object, Object> map = new LinkedHashMap<>( value.size() );
+            for( Map.Entry<Value, Value> entry : value.entrySet() )
+            {
+                Object key = doDeserialize( module, mapType.keyType(), entry.getKey() );
+                Object val = doDeserialize( module, mapType.valueType(), entry.getValue() );
+                map.put( key, val );
+            }
+            return map;
+        }
+
+        private Object deserializeStatefulAssociationValue( ModuleDescriptor module,
+                                                            StatefulAssociationValueType<?> valueType,
+                                                            MapValue value ) throws IOException
+        {
+            Map<String, Value> namedValues = value.map().entrySet().stream().map(
+                entry ->
+                {
+                    String key = doDeserialize( module, ValueType.STRING, entry.getKey() );
+                    return new AbstractMap.SimpleImmutableEntry<>( key, entry.getValue() );
+                }
+            ).collect( toMap( HashMap::new ) );
+
+            String typeInfo = null;
+            if( namedValues.containsKey( "_type" ) )
+            {
+                typeInfo = doDeserialize( module, ValueType.STRING, namedValues.get( "_type" ) );
+            }
+            if( typeInfo != null )
+            {
+                // TODO What to do with typeInfo? Value or Entity ?
+                StatefulAssociationCompositeDescriptor descriptor = statefulCompositeDescriptorFor( module, typeInfo );
+                if( descriptor == null )
+                {
+                    throw new SerializationException(
+                        "_type: " + typeInfo + " could not be resolved while deserializing " + value );
+                }
+                valueType = descriptor.valueType();
+            }
+
+            ValueBuilder builder = module.instance().newValueBuilderWithState(
+                valueType.primaryType(),
+                propertyFunction( valueType.module(), namedValues ),
+                associationFunction( valueType.module(), namedValues ),
+                manyAssociationFunction( valueType.module(), namedValues ),
+                namedAssociationFunction( valueType.module(), namedValues ) );
+            return builder.newInstance();
+        }
+
+        private Function<PropertyDescriptor, Object> propertyFunction( ModuleDescriptor module,
+                                                                       Map<String, Value> namedValues )
+        {
+            return property ->
+            {
+                Value messagePackValue = namedValues.get( property.qualifiedName().name() );
+                if( messagePackValue != null )
+                {
+                    Object value;
+                    Converter<Object> converter = converters.converterFor( property );
+                    if( converter != null )
+                    {
+                        value = converter.fromString( doDeserialize( module, ValueType.STRING, messagePackValue ) );
+                    }
+                    else
+                    {
+                        value = doDeserialize( module, property.valueType(), messagePackValue );
+                    }
+                    if( property.isImmutable() )
+                    {
+                        if( value instanceof Set )
+                        {
+                            return unmodifiableSet( (Set<?>) value );
+                        }
+                        else if( value instanceof List )
+                        {
+                            return unmodifiableList( (List<?>) value );
+                        }
+                        else if( value instanceof Map )
+                        {
+                            return unmodifiableMap( (Map<?, ?>) value );
+                        }
+                    }
+                    return value;
+                }
+                return property.resolveInitialValue( module );
+            };
+        }
+
+        private Function<AssociationDescriptor, EntityReference> associationFunction( ModuleDescriptor module,
+                                                                                      Map<String, Value> namedValues )
+        {
+            return association -> doDeserialize( module, ValueType.ENTITY_REFERENCE,
+                                                 namedValues.get( association.qualifiedName().name() ) );
+        }
+
+        private Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction(
+            ModuleDescriptor module, Map<String, Value> namedValues )
+        {
+            return association ->
+            {
+                List list = doDeserialize( module, ENTITY_REF_LIST_VALUE_TYPE,
+                                           namedValues.get( association.qualifiedName().name() ) );
+                return list == null ? Stream.empty() : list.stream();
+            };
+        }
+
+        private Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction(
+            ModuleDescriptor module, Map<String, Value> namedValues )
+        {
+            return association ->
+            {
+                Map map = doDeserialize( module, ENTITY_REF_MAP_VALUE_TYPE,
+                                         namedValues.get( association.qualifiedName().name() ) );
+                return map == null ? Stream.empty() : map.entrySet().stream();
+            };
+        }
+
+        private Object doGuessDeserialize( ModuleDescriptor module, ValueType valueType, Value value )
+            throws IOException, ClassNotFoundException
+        {
+            switch( value.getValueType() )
+            {
+                case MAP:
+                    MapValue mapValue = value.asMapValue();
+                    Optional<String> typeInfo = mapValue
+                        .entrySet().stream()
+                        .filter( entry -> entry.getKey().isStringValue() )
+                        .map( entry ->
+                              {
+                                  String key = doDeserialize( module, ValueType.STRING, entry.getKey() );
+                                  return new AbstractMap.SimpleImmutableEntry<>( key, entry.getValue() );
+                              } )
+                        .filter( entry -> "_type".equals( entry.getKey() ) )
+                        .findFirst()
+                        .map( entry -> doDeserialize( module, ValueType.STRING, entry.getValue() ) );
+                    if( typeInfo.isPresent() )
+                    {
+                        StatefulAssociationCompositeDescriptor descriptor = statefulCompositeDescriptorFor(
+                            module, typeInfo.get() );
+                        if( descriptor != null )
+                        {
+                            return deserializeStatefulAssociationValue( ( (CompositeDescriptor) descriptor ).module(),
+                                                                        descriptor.valueType(),
+                                                                        mapValue );
+                        }
+                    }
+                default:
+                    throw new SerializationException( "Don't know how to deserialize " + valueType + " from " + value
+                                                      + " (" + value.getValueType() + ")" );
+            }
+        }
+    }
+}
diff --git a/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackSerialization.java b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackSerialization.java
new file mode 100644
index 0000000..32b680c
--- /dev/null
+++ b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackSerialization.java
@@ -0,0 +1,22 @@
+/*
+ *  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.polygene.serialization.messagepack;
+
+public interface MessagePackSerialization extends MessagePackSerializer, MessagePackDeserializer
+{
+}
diff --git a/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackSerializer.java b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackSerializer.java
new file mode 100644
index 0000000..68c9a99
--- /dev/null
+++ b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackSerializer.java
@@ -0,0 +1,210 @@
+/*
+ *  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.polygene.serialization.messagepack;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Map;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.composite.StatefulAssociationCompositeDescriptor;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.serialization.Converter;
+import org.apache.polygene.api.serialization.Converters;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.api.type.ArrayType;
+import org.apache.polygene.api.type.EnumType;
+import org.apache.polygene.api.type.MapType;
+import org.apache.polygene.api.type.StatefulAssociationValueType;
+import org.apache.polygene.spi.serialization.AbstractBinarySerializer;
+import org.apache.polygene.spi.util.ArrayIterable;
+import org.msgpack.core.MessagePack;
+import org.msgpack.core.MessagePacker;
+import org.msgpack.value.ArrayValue;
+import org.msgpack.value.MapValue;
+import org.msgpack.value.Value;
+import org.msgpack.value.ValueFactory;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.polygene.api.util.Collectors.toMap;
+
+@Mixins( MessagePackSerializer.Mixin.class )
+public interface MessagePackSerializer extends Serializer
+{
+    class Mixin extends AbstractBinarySerializer
+    {
+        @This
+        private Converters converters;
+
+        @This
+        private MessagePackAdapters adapters;
+
+        @Override
+        public void serialize( Options options, OutputStream output, @Optional Object object )
+        {
+            try( MessagePacker packer = MessagePack.newDefaultPacker( output ) )
+            {
+                Value value = doSerialize( options, object, true );
+                packer.packValue( value );
+                packer.flush();
+            }
+            catch( IOException ex )
+            {
+                throw new SerializationException( "Unable to serialize " + object, ex );
+            }
+        }
+
+        private Value doSerialize( Options options, Object object, boolean root )
+        {
+            try
+            {
+                if( object == null )
+                {
+                    return ValueFactory.newNil();
+                }
+                Class<?> objectClass = object.getClass();
+                Converter<Object> converter = converters.converterFor( objectClass );
+                if( converter != null )
+                {
+                    return doSerialize( options, converter.toString( object ), false );
+                }
+                MessagePackAdapter<?> adapter = adapters.adapterFor( objectClass );
+                if( adapter != null )
+                {
+                    return adapter.serialize( object, obj -> doSerialize( options, obj, false ) );
+                }
+                if( EnumType.isEnum( objectClass ) )
+                {
+                    return ValueFactory.newString( object.toString() );
+                }
+                if( StatefulAssociationValueType.isStatefulAssociationValue( objectClass ) )
+                {
+                    return serializeStatefulAssociationValue( options, object, root );
+                }
+                if( MapType.isMap( objectClass ) )
+                {
+                    return serializeMap( options, (Map<?, ?>) object );
+                }
+                if( ArrayType.isArray( objectClass ) )
+                {
+                    return serializeArray( options, object );
+                }
+                if( Iterable.class.isAssignableFrom( objectClass ) )
+                {
+                    return serializeIterable( options, (Iterable<?>) object );
+                }
+                if( Stream.class.isAssignableFrom( objectClass ) )
+                {
+                    return serializeStream( options, (Stream<?>) object );
+                }
+                throw new SerializationException( "Don't know how to serialize " + object );
+            }
+            catch( IOException ex )
+            {
+                throw new SerializationException( "Unable to serialize " + object, ex );
+            }
+        }
+
+        private MapValue serializeStatefulAssociationValue( Options options, Object composite, boolean root )
+        {
+            CompositeInstance instance = PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF.apply( (Composite) composite );
+            StatefulAssociationCompositeDescriptor descriptor =
+                (StatefulAssociationCompositeDescriptor) instance.descriptor();
+            AssociationStateHolder state = (AssociationStateHolder) instance.state();
+            StatefulAssociationValueType<?> valueType = descriptor.valueType();
+
+            ValueFactory.MapBuilder builder = ValueFactory.newMapBuilder();
+            valueType.properties().forEach(
+                property ->
+                {
+                    Object value = state.propertyFor( property.accessor() ).get();
+                    Converter<Object> converter = converters.converterFor( property );
+                    if( converter != null )
+                    {
+                        value = converter.toString( value );
+                    }
+                    builder.put(
+                        ValueFactory.newString( property.qualifiedName().name() ),
+                        doSerialize( options, value, false ) );
+                } );
+            valueType.associations().forEach(
+                association -> builder.put(
+                    ValueFactory.newString( association.qualifiedName().name() ),
+                    doSerialize( options, state.associationFor( association.accessor() ).reference(), false ) ) );
+            valueType.manyAssociations().forEach(
+                association -> builder.put(
+                    ValueFactory.newString( association.qualifiedName().name() ),
+                    doSerialize( options,
+                                 state.manyAssociationFor( association.accessor() ).references().collect( toList() ),
+                                 false ) ) );
+            valueType.namedAssociations().forEach(
+                association -> builder.put(
+                    ValueFactory.newString( association.qualifiedName().name() ),
+                    doSerialize( options,
+                                 state.namedAssociationFor( association.accessor() ).references().collect( toMap() ),
+                                 false ) ) );
+
+            if( ( root && options.rootTypeInfo() ) || ( !root && options.nestedTypeInfo() ) )
+            {
+                builder.put( ValueFactory.newString( "_type" ),
+                             ValueFactory.newString( valueType.primaryType().getName() ) );
+            }
+            return builder.build();
+        }
+
+        private MapValue serializeMap( Options options, Map<?, ?> map )
+        {
+            ValueFactory.MapBuilder builder = ValueFactory.newMapBuilder();
+            map.forEach( ( key, value ) -> builder.put( doSerialize( options, key, false ),
+                                                        doSerialize( options, value, false ) ) );
+            return builder.build();
+        }
+
+        private Value serializeArray( Options options, Object object )
+        {
+            ArrayType valueType = ArrayType.of( object.getClass() );
+            if( valueType.isArrayOfPrimitiveBytes() )
+            {
+                return ValueFactory.newBinary( (byte[]) object );
+            }
+            if( valueType.isArrayOfPrimitives() )
+            {
+                return serializeIterable( options, new ArrayIterable( object ) );
+            }
+            return serializeStream( options, Stream.of( (Object[]) object ) );
+        }
+
+        private ArrayValue serializeIterable( Options options, Iterable<?> iterable )
+        {
+            return serializeStream( options, StreamSupport.stream( iterable.spliterator(), false ) );
+        }
+
+        private ArrayValue serializeStream( Options options, Stream<?> stream )
+        {
+            return ValueFactory.newArray( stream.map( element -> doSerialize( options, element, false ) )
+                                                .collect( toList() ) );
+        }
+    }
+}
diff --git a/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackSettings.java b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackSettings.java
new file mode 100644
index 0000000..9c5d20c
--- /dev/null
+++ b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/MessagePackSettings.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.serialization.messagepack;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.spi.serialization.SerializationSettings;
+
+public class MessagePackSettings extends SerializationSettings<MessagePackSettings>
+{
+    public static final MessagePackSettings DEFAULT = new MessagePackSettings();
+
+    public static MessagePackSettings orDefault( MessagePackSettings settings )
+    {
+        return settings != null ? settings : DEFAULT;
+    }
+
+    private Map<ValueType, MessagePackAdapter<?>> adapters;
+
+    public MessagePackSettings()
+    {
+        adapters = new LinkedHashMap<>();
+    }
+
+    public Map<ValueType, MessagePackAdapter<?>> getAdapters()
+    {
+        return adapters;
+    }
+}
diff --git a/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/assembly/MessagePackSerializationAssembler.java b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/assembly/MessagePackSerializationAssembler.java
new file mode 100644
index 0000000..7f87458
--- /dev/null
+++ b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/assembly/MessagePackSerializationAssembler.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.serialization.messagepack.assembly;
+
+import org.apache.polygene.api.serialization.Converters;
+import org.apache.polygene.api.serialization.Deserializer;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.serialization.messagepack.MessagePackAdapters;
+import org.apache.polygene.serialization.messagepack.MessagePackSerialization;
+import org.apache.polygene.serialization.messagepack.MessagePackSettings;
+
+public class MessagePackSerializationAssembler extends Assemblers.VisibilityIdentity<MessagePackSerializationAssembler>
+{
+    private MessagePackSettings settings;
+
+    public MessagePackSerializationAssembler withMessagePackSettings( MessagePackSettings settings )
+    {
+        this.settings = settings;
+        return this;
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        ServiceDeclaration declaration = module.services( MessagePackSerialization.class )
+                                               .withTypes( Serialization.class,
+                                                           Serializer.class, Deserializer.class,
+                                                           Converters.class,
+                                                           MessagePackAdapters.class )
+                                               .visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            declaration.identifiedBy( identity() );
+        }
+        if( settings != null )
+        {
+            declaration.setMetaInfo( settings );
+        }
+    }
+}
diff --git a/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/assembly/package.html b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/assembly/package.html
new file mode 100644
index 0000000..82eab62
--- /dev/null
+++ b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>MessagePack Serialization Assembly.</h2>
+    </body>
+</html>
diff --git a/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/package.html b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/package.html
new file mode 100644
index 0000000..16c905a
--- /dev/null
+++ b/extensions/serialization-messagepack/src/main/java/org/apache/polygene/serialization/messagepack/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>MessagePack Serialization.</h2>
+    </body>
+</html>
diff --git a/extensions/serialization-messagepack/src/test/java/org/apache/polygene/serialization/messagepack/MessagePackCollectionSerializationTest.java b/extensions/serialization-messagepack/src/test/java/org/apache/polygene/serialization/messagepack/MessagePackCollectionSerializationTest.java
new file mode 100644
index 0000000..f8cc562
--- /dev/null
+++ b/extensions/serialization-messagepack/src/test/java/org/apache/polygene/serialization/messagepack/MessagePackCollectionSerializationTest.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.serialization.messagepack;
+
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.messagepack.assembly.MessagePackSerializationAssembler;
+import org.apache.polygene.test.serialization.AbstractCollectionSerializationTest;
+
+public class MessagePackCollectionSerializationTest extends AbstractCollectionSerializationTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        new MessagePackSerializationAssembler().assemble( module );
+        super.assemble( module );
+    }
+}
diff --git a/extensions/serialization-messagepack/src/test/java/org/apache/polygene/serialization/messagepack/MessagePackConvertersSerializationTest.java b/extensions/serialization-messagepack/src/test/java/org/apache/polygene/serialization/messagepack/MessagePackConvertersSerializationTest.java
new file mode 100644
index 0000000..305d958
--- /dev/null
+++ b/extensions/serialization-messagepack/src/test/java/org/apache/polygene/serialization/messagepack/MessagePackConvertersSerializationTest.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.serialization.messagepack;
+
+import java.util.Base64;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.messagepack.assembly.MessagePackSerializationAssembler;
+import org.apache.polygene.test.serialization.AbstractConvertersSerializationTest;
+import org.msgpack.core.MessagePack;
+import org.msgpack.value.ValueFactory;
+
+public class MessagePackConvertersSerializationTest extends AbstractConvertersSerializationTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        new MessagePackSerializationAssembler().assemble( module );
+        super.assemble( module );
+    }
+
+    @Override
+    protected String getStringFromValueState( String state, String key ) throws Exception
+    {
+        return MessagePack.newDefaultUnpacker( Base64.getDecoder().decode( state ) )
+                          .unpackValue().asMapValue()
+                          .map().get( ValueFactory.newString( key ) )
+                          .asStringValue().asString();
+    }
+}
diff --git a/extensions/serialization-messagepack/src/test/java/org/apache/polygene/serialization/messagepack/MessagePackPlainValueSerializationTest.java b/extensions/serialization-messagepack/src/test/java/org/apache/polygene/serialization/messagepack/MessagePackPlainValueSerializationTest.java
new file mode 100644
index 0000000..2a0d1b4
--- /dev/null
+++ b/extensions/serialization-messagepack/src/test/java/org/apache/polygene/serialization/messagepack/MessagePackPlainValueSerializationTest.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.serialization.messagepack;
+
+import java.util.Base64;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.messagepack.assembly.MessagePackSerializationAssembler;
+import org.apache.polygene.test.serialization.AbstractPlainValueSerializationTest;
+import org.msgpack.core.MessagePack;
+
+public class MessagePackPlainValueSerializationTest extends AbstractPlainValueSerializationTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        new MessagePackSerializationAssembler().withMessagePackSettings( withTestSettings( new MessagePackSettings() ) )
+                                               .assemble( module );
+    }
+
+    @Override
+    protected String getSingleStringRawState( String state ) throws Exception
+    {
+        return MessagePack.newDefaultUnpacker( Base64.getDecoder().decode( state ) )
+                          .unpackValue().asStringValue().asString();
+    }
+}
diff --git a/extensions/serialization-messagepack/src/test/java/org/apache/polygene/serialization/messagepack/MessagePackValueCompositeSerializationTest.java b/extensions/serialization-messagepack/src/test/java/org/apache/polygene/serialization/messagepack/MessagePackValueCompositeSerializationTest.java
new file mode 100644
index 0000000..b1491f8
--- /dev/null
+++ b/extensions/serialization-messagepack/src/test/java/org/apache/polygene/serialization/messagepack/MessagePackValueCompositeSerializationTest.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.serialization.messagepack;
+
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.messagepack.assembly.MessagePackSerializationAssembler;
+import org.apache.polygene.test.serialization.AbstractValueCompositeSerializationTest;
+
+public class MessagePackValueCompositeSerializationTest extends AbstractValueCompositeSerializationTest
+{
+    // START SNIPPET: assembly
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        new MessagePackSerializationAssembler().assemble( module );
+        // END SNIPPET: assembly
+        super.assemble( module );
+        // START SNIPPET: assembly
+    }
+    // END SNIPPET: assembly
+}
diff --git a/extensions/valueserialization-jackson/build.gradle b/extensions/valueserialization-jackson/build.gradle
deleted file mode 100644
index 616e01b..0000000
--- a/extensions/valueserialization-jackson/build.gradle
+++ /dev/null
@@ -1,35 +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.
- */
-
-description = "Apache Zest™ Jackson ValueSerialization Extension"
-
-jar { manifest { name = "Apache Zest™ Extension - ValueSerialization - Jackson" } }
-
-dependencies {
-
-    compile project(":org.qi4j.core:org.qi4j.core.bootstrap")
-    compile libraries.jackson_mapper
-
-    testCompile project(":org.qi4j.core:org.qi4j.core.testsupport")
-
-    testRuntime project(":org.qi4j.core:org.qi4j.core.runtime")
-    testRuntime libraries.slf4j_simple
-
-}
-
diff --git a/extensions/valueserialization-jackson/dev-status.xml b/extensions/valueserialization-jackson/dev-status.xml
deleted file mode 100644
index cbf512f..0000000
--- a/extensions/valueserialization-jackson/dev-status.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
-  <status>
-    <codebase>beta</codebase>
-    <!--none,early,beta,stable,mature-->
-    <documentation>good</documentation>
-    <!-- none, brief, good, complete -->
-    <unittests>complete</unittests>
-    <!-- none, some, good, complete -->
-  </status>
-  <licenses>
-    <license>ALv2</license>
-  </licenses>
-</module>
\ No newline at end of file
diff --git a/extensions/valueserialization-jackson/src/docs/vs-jackson.txt b/extensions/valueserialization-jackson/src/docs/vs-jackson.txt
deleted file mode 100644
index 898a8d7..0000000
--- a/extensions/valueserialization-jackson/src/docs/vs-jackson.txt
+++ /dev/null
@@ -1,43 +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.
-///////////////////////////////////////////////////////////////
-
-[[extension-vs-jackson, Jackson ValueSerialization]]
-= Jackson ValueSerialization =
-
-[devstatus]
---------------
-source=extensions/valueserialization-jackson/dev-status.xml
---------------
-
-ValueSerialization Service backed by http://wiki.fasterxml.com/JacksonHome[Jackson].
-
-include::../../build/docs/buildinfo/artifact.txt[]
-
-== Assembly ==
-
-Assembly is done as follows:
-
-[snippet,java]
-----
-source=extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonPlainValueSerializationTest.java
-tag=assembly
-----
-
-See the ValueSerialization <<core-api-value,API>> and <<core-spi-valueserialization,SPI>> documentation for details and
-usage.
diff --git a/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/JacksonValueDeserializer.java b/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/JacksonValueDeserializer.java
deleted file mode 100644
index 3d82f43..0000000
--- a/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/JacksonValueDeserializer.java
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.jackson;
-
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.MappingJsonFactory;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import java.io.InputStream;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.api.value.ValueDeserializer;
-import org.qi4j.api.value.ValueSerializationException;
-import org.qi4j.functional.Function;
-import org.qi4j.spi.value.ValueDeserializerAdapter;
-
-/**
- * ValueDeserializer reading Values from JSON documents using Jackson.
- */
-public class JacksonValueDeserializer
-    extends ValueDeserializerAdapter<JsonParser, JsonNode>
-{
-
-    private final JsonFactory jsonFactory = new MappingJsonFactory();
-
-    public JacksonValueDeserializer( @Structure Application application,
-                                     @Structure Module module,
-                                     @Service ServiceReference<ValueDeserializer> serviceRef )
-    {
-        super( application, module, serviceRef );
-    }
-
-    @Override
-    protected JsonParser adaptInput( InputStream input )
-        throws Exception
-    {
-        return jsonFactory.createParser( input );
-    }
-
-    @Override
-    protected void onDeserializationEnd( ValueType valueType, JsonParser input )
-        throws Exception
-    {
-        input.close();
-    }
-
-    @Override
-    protected Object readPlainValue( JsonParser input )
-        throws Exception
-    {
-        JsonNode jsonNode = input.readValueAsTree();
-        if( jsonNode.isArray() || jsonNode.isObject() )
-        {
-            throw new ValueSerializationException( "Asked for a Value but found an Object or an Array at "
-                                                   + input.getCurrentLocation().toString() );
-        }
-        if( jsonNode.isDouble() )
-        {
-            return jsonNode.asDouble();
-        }
-        if( jsonNode.isLong() )
-        {
-            return jsonNode.asLong();
-        }
-        if( jsonNode.isInt() )
-        {
-            return jsonNode.asInt();
-        }
-        if( jsonNode.isBoolean() )
-        {
-            return jsonNode.asBoolean();
-        }
-        if( jsonNode.isNull() )
-        {
-            return null;
-        }
-        return jsonNode.asText();
-    }
-
-    @Override
-    protected <T> Collection<T> readArrayInCollection( JsonParser input,
-                                                       Function<JsonParser, T> deserializer,
-                                                       Collection<T> collection )
-        throws Exception
-    {
-        JsonToken token = input.getCurrentToken();
-        if( token == JsonToken.VALUE_NULL )
-        {
-            return null;
-        }
-        if( token != JsonToken.START_ARRAY )
-        {
-            token = input.nextToken();
-        }
-        if( token == JsonToken.VALUE_NULL )
-        {
-            return null;
-        }
-        if( token != JsonToken.START_ARRAY )
-        {
-            throw new ValueSerializationException( "Expected an array start at "
-                                                   + input.getCurrentLocation().toString() );
-        }
-        while( input.nextToken() != JsonToken.END_ARRAY )
-        {
-            T element = deserializer.map( input );
-            collection.add( element );
-        }
-        return collection;
-    }
-
-    @Override
-    protected <K, V> Map<K, V> readMapInMap( JsonParser input,
-                                             Function<JsonParser, K> keyDeserializer,
-                                             Function<JsonParser, V> valueDeserializer,
-                                             Map<K, V> map )
-        throws Exception
-    {
-        JsonToken token = input.getCurrentToken();
-        if( token == JsonToken.VALUE_NULL )
-        {
-            return null;
-        }
-        if( token != JsonToken.START_ARRAY )
-        {
-            token = input.nextToken();
-        }
-        if( token == JsonToken.VALUE_NULL )
-        {
-            return null;
-        }
-        if( token != JsonToken.START_ARRAY )
-        {
-            throw new ValueSerializationException( "Expected an array start at "
-                                                   + input.getCurrentLocation().toString() );
-        }
-        JsonToken currentToken = input.nextToken();
-        while( currentToken != JsonToken.END_ARRAY )
-        {
-            if( currentToken != JsonToken.START_OBJECT )
-            {
-                throw new ValueSerializationException( "Expected an object start at "
-                                                       + input.getCurrentLocation().toString() );
-            }
-            currentToken = input.nextToken();
-            K key = null;
-            V value = null;
-            while( currentToken != JsonToken.END_OBJECT )
-            {
-                String objectKey = input.getCurrentName();
-                input.nextToken();
-                if( "key".equals( objectKey ) )
-                {
-                    key = keyDeserializer.map( input );
-                }
-                else if( "value".equals( objectKey ) )
-                {
-                    value = valueDeserializer.map( input );
-                }
-                else
-                {
-                    //input.nextToken();
-                    input.skipChildren();
-                }
-                currentToken = input.nextToken();
-            }
-            if( key != null )
-            {
-                map.put( key, value );
-            }
-            currentToken = input.nextToken();
-        }
-        return map;
-    }
-
-    @Override
-    protected ObjectNode readObjectTree( JsonParser input )
-        throws Exception
-    {
-        JsonToken token = input.getCurrentToken();
-        if( token == JsonToken.VALUE_NULL )
-        {
-            return null;
-        }
-        if( token != JsonToken.START_OBJECT )
-        {
-            token = input.nextToken();
-        }
-        if( token != JsonToken.START_OBJECT )
-        {
-            throw new ValueSerializationException( "Expected an object start at "
-                                                   + input.getCurrentLocation().toString() );
-        }
-        return (ObjectNode) input.readValueAsTree();
-    }
-
-    @Override
-    protected Object asSimpleValue( JsonNode inputNode )
-        throws Exception
-    {
-        if( isNullOrMissing( inputNode ) )
-        {
-            return null;
-        }
-        if( !inputNode.isValueNode() )
-        {
-            throw new ValueSerializationException( "Expected a value node but got a container node " + inputNode );
-        }
-        if( inputNode.isDouble() )
-        {
-            return inputNode.asDouble();
-        }
-        if( inputNode.isLong() )
-        {
-            return inputNode.asLong();
-        }
-        if( inputNode.isInt() )
-        {
-            return inputNode.asInt();
-        }
-        if( inputNode.isBoolean() )
-        {
-            return inputNode.asBoolean();
-        }
-        return inputNode.asText();
-    }
-
-    @Override
-    protected boolean isObjectValue( JsonNode inputNode )
-        throws Exception
-    {
-        if( isNullOrMissing( inputNode ) )
-        {
-            return false;
-        }
-        return inputNode.isObject();
-    }
-
-    @Override
-    protected boolean objectHasField( JsonNode inputNode, String key )
-        throws Exception
-    {
-        if( isNullOrMissing( inputNode ) )
-        {
-            return false;
-        }
-        if( !inputNode.isObject() )
-        {
-            throw new ValueSerializationException( "Expected an object but got " + inputNode );
-        }
-        return inputNode.has( key );
-    }
-
-    @Override
-    protected <T> T getObjectFieldValue( JsonNode inputNode, String key, Function<JsonNode, T> valueDeserializer )
-        throws Exception
-    {
-        JsonNode valueNode = inputNode.get( key );
-        if( isNullOrMissing( valueNode ) )
-        {
-            return null;
-        }
-        T value = valueDeserializer.map( valueNode );
-        return value;
-    }
-
-    @Override
-    protected <T> void putArrayNodeInCollection( JsonNode inputNode,
-                                                 Function<JsonNode, T> deserializer,
-                                                 Collection<T> collection )
-        throws Exception
-    {
-        if( isNullOrMissing( inputNode ) )
-        {
-            return;
-        }
-        if( !inputNode.isArray() )
-        {
-            throw new ValueSerializationException( "Expected an array but got " + inputNode );
-        }
-        ArrayNode array = (ArrayNode) inputNode;
-        for( JsonNode item : array )
-        {
-            T value = deserializer.map( item );
-            collection.add( value );
-        }
-    }
-
-    @Override
-    protected <K, V> void putArrayNodeInMap( JsonNode inputNode,
-                                             Function<JsonNode, K> keyDeserializer,
-                                             Function<JsonNode, V> valueDeserializer,
-                                             Map<K, V> map )
-        throws Exception
-    {
-        if( isNullOrMissing( inputNode ) )
-        {
-            return;
-        }
-        if( !inputNode.isArray() )
-        {
-            throw new ValueSerializationException( "Expected an array but got " + inputNode );
-        }
-        ArrayNode array = (ArrayNode) inputNode;
-        for( JsonNode item : array )
-        {
-            if( !item.isObject() )
-            {
-                throw new ValueSerializationException( "Expected an object but got " + inputNode );
-            }
-            JsonNode keyNode = item.get( "key" );
-            JsonNode valueNode = item.get( "value" );
-            K key = keyDeserializer.map( keyNode );
-            V value = valueDeserializer.map( valueNode );
-            if( key != null )
-            {
-                map.put( key, value );
-            }
-        }
-    }
-
-    @Override
-    protected <V> void putObjectNodeInMap( JsonNode inputNode,
-                                           Function<JsonNode, V> valueDeserializer,
-                                           Map<String, V> map
-    )
-        throws Exception
-    {
-        if( isNullOrMissing( inputNode ) )
-        {
-            return;
-        }
-        if( !inputNode.isObject() )
-        {
-            throw new ValueSerializationException( "Expected an object but got " + inputNode );
-        }
-        ObjectNode object = (ObjectNode) inputNode;
-        Iterator<Map.Entry<String, JsonNode>> fields = object.fields();
-        while( fields.hasNext() )
-        {
-            Map.Entry<String, JsonNode> entry = fields.next();
-            V value = valueDeserializer.map( entry.getValue() );
-            map.put( entry.getKey(), value );
-        }
-    }
-
-    private static boolean isNullOrMissing( JsonNode inputNode )
-    {
-        return inputNode == null || inputNode.isNull() || inputNode.isMissingNode();
-    }
-}
diff --git a/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/JacksonValueSerializationAssembler.java b/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/JacksonValueSerializationAssembler.java
deleted file mode 100644
index a0ee430..0000000
--- a/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/JacksonValueSerializationAssembler.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2013, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.jackson;
-
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Function;
-
-/**
- * Assemble a ValueSerialization Service producing and consuming JSON documents.
- */
-public class JacksonValueSerializationAssembler
-    extends Assemblers.Visibility<JacksonValueSerializationAssembler>
-{
-    private Function<Application, Module> valuesModuleFinder;
-
-    public JacksonValueSerializationAssembler withValuesModuleFinder( Function<Application, Module> valuesModuleFinder )
-    {
-        this.valuesModuleFinder = valuesModuleFinder;
-        return this;
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        if( valuesModuleFinder == null )
-        {
-            module.services( JacksonValueSerializationService.class ).
-                visibleIn( visibility() ).
-                taggedWith( ValueSerialization.Formats.JSON );
-        }
-        else
-        {
-            module.services( JacksonValueSerializationService.class ).
-                visibleIn( visibility() ).
-                taggedWith( ValueSerialization.Formats.JSON ).
-                setMetaInfo( valuesModuleFinder );
-        }
-    }
-}
diff --git a/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/JacksonValueSerializationService.java b/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/JacksonValueSerializationService.java
deleted file mode 100644
index 7aa6574..0000000
--- a/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/JacksonValueSerializationService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.jackson;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.value.ValueSerialization;
-
-/**
- * ValueSerialization Service producing and consuming JSON documents using Jackson.
- */
-@Mixins( { JacksonValueSerializer.class, JacksonValueDeserializer.class } )
-public interface JacksonValueSerializationService
-    extends ValueSerialization
-{
-}
diff --git a/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/JacksonValueSerializer.java b/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/JacksonValueSerializer.java
deleted file mode 100644
index dc028a8..0000000
--- a/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/JacksonValueSerializer.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.jackson;
-
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.MappingJsonFactory;
-import java.io.OutputStream;
-import org.qi4j.spi.value.ValueSerializerAdapter;
-
-/**
- * ValueSerializer producing Values state as JSON documents using Jackson.
- */
-public class JacksonValueSerializer
-    extends ValueSerializerAdapter<JsonGenerator>
-{
-
-    private final JsonFactory jsonFactory = new MappingJsonFactory();
-
-    @Override
-    protected JsonGenerator adaptOutput( OutputStream output )
-        throws Exception
-    {
-        return jsonFactory.createGenerator( output );
-    }
-
-    @Override
-    protected void onSerializationEnd( Object object, JsonGenerator output )
-        throws Exception
-    {
-        output.close();
-    }
-
-    @Override
-    protected void onArrayStart( JsonGenerator output )
-        throws Exception
-    {
-        output.writeStartArray();
-    }
-
-    @Override
-    protected void onArrayEnd( JsonGenerator output )
-        throws Exception
-    {
-        output.writeEndArray();
-    }
-
-    @Override
-    protected void onObjectStart( JsonGenerator output )
-        throws Exception
-    {
-        output.writeStartObject();
-    }
-
-    @Override
-    protected void onObjectEnd( JsonGenerator output )
-        throws Exception
-    {
-        output.writeEndObject();
-    }
-
-    @Override
-    protected void onFieldStart( JsonGenerator output, String fieldName )
-        throws Exception
-    {
-        output.writeFieldName( fieldName );
-    }
-
-    @Override
-    protected void onValue( JsonGenerator output, Object value )
-        throws Exception
-    {
-        output.writeObject( value );
-    }
-}
diff --git a/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/package.html b/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/package.html
deleted file mode 100644
index 0de7293..0000000
--- a/extensions/valueserialization-jackson/src/main/java/org/qi4j/valueserialization/jackson/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Jackson Value Serializer.</h2>
-    </body>
-</html>
diff --git a/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonCollectionSerializationTest.java b/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonCollectionSerializationTest.java
deleted file mode 100644
index 08fd937..0000000
--- a/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonCollectionSerializationTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.jackson;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.value.AbstractCollectionSerializationTest;
-
-public class JacksonCollectionSerializationTest
-    extends AbstractCollectionSerializationTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        new JacksonValueSerializationAssembler().assemble( module );
-    }
-}
diff --git a/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonConfigurationDeserializationTest.java b/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonConfigurationDeserializationTest.java
deleted file mode 100644
index 1209abf..0000000
--- a/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonConfigurationDeserializationTest.java
+++ /dev/null
@@ -1,36 +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.qi4j.valueserialization.jackson;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.entity.AbstractConfigurationDeserializationTest;
-
-public class JacksonConfigurationDeserializationTest
-    extends AbstractConfigurationDeserializationTest
-{
-    @Override
-    public void assemble( final ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        new JacksonValueSerializationAssembler()
-            .assemble( module );
-    }
-}
diff --git a/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonJsonDateFormatTest.java b/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonJsonDateFormatTest.java
deleted file mode 100644
index 3ec53c2..0000000
--- a/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonJsonDateFormatTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.jackson;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.value.AbstractJsonDateFormatTest;
-
-public class JacksonJsonDateFormatTest
-    extends AbstractJsonDateFormatTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        new JacksonValueSerializationAssembler().assemble( module );
-    }
-}
diff --git a/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonPlainValueSerializationTest.java b/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonPlainValueSerializationTest.java
deleted file mode 100644
index 0f496dc..0000000
--- a/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonPlainValueSerializationTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.jackson;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.value.AbstractPlainValueSerializationTest;
-
-public class JacksonPlainValueSerializationTest
-    extends AbstractPlainValueSerializationTest
-{
-
-    // START SNIPPET: assembly
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new JacksonValueSerializationAssembler().assemble( module );
-    }
-    // END SNIPPET: assembly
-}
diff --git a/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonValueCompositeSerializationTest.java b/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonValueCompositeSerializationTest.java
deleted file mode 100644
index 54479d3..0000000
--- a/extensions/valueserialization-jackson/src/test/java/org/qi4j/valueserialization/jackson/JacksonValueCompositeSerializationTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.jackson;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.value.AbstractValueCompositeSerializationTest;
-
-public class JacksonValueCompositeSerializationTest
-    extends AbstractValueCompositeSerializationTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        new JacksonValueSerializationAssembler().assemble( module );
-    }
-}
diff --git a/extensions/valueserialization-jackson/src/test/resources/configtest.json b/extensions/valueserialization-jackson/src/test/resources/configtest.json
deleted file mode 100644
index d48a241..0000000
--- a/extensions/valueserialization-jackson/src/test/resources/configtest.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "identity" : "configtest",
-  "host": {
-    "ip": "12.23.34.45",
-    "port": 1234
-  },
-  "name": "main"
-}
\ No newline at end of file
diff --git a/extensions/valueserialization-orgjson/build.gradle b/extensions/valueserialization-orgjson/build.gradle
deleted file mode 100644
index a919f4e..0000000
--- a/extensions/valueserialization-orgjson/build.gradle
+++ /dev/null
@@ -1,34 +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.
- */
-
-description = "Apache Zest™ org.json ValueSerialization Extension"
-
-jar { manifest { name = "Apache Zest™ Extension - ValueSerialization - org.json" } }
-
-dependencies {
-
-    compile project(":org.qi4j.core:org.qi4j.core.bootstrap")
-
-    testCompile project(":org.qi4j.core:org.qi4j.core.testsupport")
-
-    testRuntime project(":org.qi4j.core:org.qi4j.core.runtime")
-    testRuntime libraries.slf4j_simple
-
-}
-
diff --git a/extensions/valueserialization-orgjson/dev-status.xml b/extensions/valueserialization-orgjson/dev-status.xml
deleted file mode 100644
index b41b4f7..0000000
--- a/extensions/valueserialization-orgjson/dev-status.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
-  <status>
-    <codebase>stable</codebase>
-    <!--none,early,beta,stable,mature-->
-    <documentation>good</documentation>
-    <!-- none, brief, good, complete -->
-    <unittests>complete</unittests>
-    <!-- none, some, good, complete -->
-  </status>
-  <licenses>
-    <license>ALv2</license>
-  </licenses>
-</module>
diff --git a/extensions/valueserialization-orgjson/src/docs/vs-orgjson.txt b/extensions/valueserialization-orgjson/src/docs/vs-orgjson.txt
deleted file mode 100644
index a893ac0..0000000
--- a/extensions/valueserialization-orgjson/src/docs/vs-orgjson.txt
+++ /dev/null
@@ -1,43 +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.
-///////////////////////////////////////////////////////////////
-
-[[extension-vs-orgjson, org.json ValueSerialization]]
-= org.json ValueSerialization =
-
-[devstatus]
---------------
-source=extensions/valueserialization-orgjson/dev-status.xml
---------------
-
-ValueSerialization Service backed by https://github.com/douglascrockford/JSON-java[org.json].
-
-include::../../build/docs/buildinfo/artifact.txt[]
-
-== Assembly ==
-
-Assembly is done as follows:
-
-[snippet,java]
-----
-source=extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonPlainValueSerializationTest.java
-tag=assembly
-----
-
-See the ValueSerialization <<core-api-value,API>> and <<core-spi-valueserialization,SPI>> documentation for details and
-usage.
diff --git a/extensions/valueserialization-orgjson/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueSerializationAssembler.java b/extensions/valueserialization-orgjson/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueSerializationAssembler.java
deleted file mode 100644
index 82ed416..0000000
--- a/extensions/valueserialization-orgjson/src/main/java/org/qi4j/valueserialization/orgjson/OrgJsonValueSerializationAssembler.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.orgjson;
-
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Function;
-
-/**
- * Assemble a ValueSerialization Service producing and consuming JSON documents.
- */
-public class OrgJsonValueSerializationAssembler
-    extends Assemblers.Visibility<OrgJsonValueSerializationAssembler>
-{
-    private Function<Application, Module> valuesModuleFinder;
-
-    public OrgJsonValueSerializationAssembler withValuesModuleFinder( Function<Application, Module> valuesModuleFinder )
-    {
-        this.valuesModuleFinder = valuesModuleFinder;
-        return this;
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        if( valuesModuleFinder == null )
-        {
-            module.services( OrgJsonValueSerializationService.class ).
-                visibleIn( visibility() ).
-                taggedWith( ValueSerialization.Formats.JSON );
-        }
-        else
-        {
-            module.services( OrgJsonValueSerializationService.class ).
-                visibleIn( visibility() ).
-                taggedWith( ValueSerialization.Formats.JSON ).
-                setMetaInfo( valuesModuleFinder );
-        }
-    }
-}
diff --git a/extensions/valueserialization-orgjson/src/main/java/org/qi4j/valueserialization/orgjson/package.html b/extensions/valueserialization-orgjson/src/main/java/org/qi4j/valueserialization/orgjson/package.html
deleted file mode 100644
index f88bff8..0000000
--- a/extensions/valueserialization-orgjson/src/main/java/org/qi4j/valueserialization/orgjson/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>org.json Value Serialization.</h2>
-    </body>
-</html>
diff --git a/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonCollectionSerializationTest.java b/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonCollectionSerializationTest.java
deleted file mode 100644
index f3b3ce6..0000000
--- a/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonCollectionSerializationTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.orgjson;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.value.AbstractCollectionSerializationTest;
-
-public class OrgJsonCollectionSerializationTest
-    extends AbstractCollectionSerializationTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-    }
-}
diff --git a/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonConfigurationDeserializationTest.java b/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonConfigurationDeserializationTest.java
deleted file mode 100644
index 3d9cd3e..0000000
--- a/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonConfigurationDeserializationTest.java
+++ /dev/null
@@ -1,36 +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.qi4j.valueserialization.orgjson;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.entity.AbstractConfigurationDeserializationTest;
-
-public class OrgJsonConfigurationDeserializationTest
-    extends AbstractConfigurationDeserializationTest
-{
-    @Override
-    public void assemble( final ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        new OrgJsonValueSerializationAssembler()
-            .assemble( module );
-    }
-}
diff --git a/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonDateFormatTest.java b/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonDateFormatTest.java
deleted file mode 100644
index 8bd0da2..0000000
--- a/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonDateFormatTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.orgjson;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.value.AbstractJsonDateFormatTest;
-
-public class OrgJsonDateFormatTest
-    extends AbstractJsonDateFormatTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-    }
-}
diff --git a/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonPlainValueSerializationTest.java b/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonPlainValueSerializationTest.java
deleted file mode 100644
index 0f124e0..0000000
--- a/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonPlainValueSerializationTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.orgjson;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.value.AbstractPlainValueSerializationTest;
-
-public class OrgJsonPlainValueSerializationTest
-    extends AbstractPlainValueSerializationTest
-{
-
-    // START SNIPPET: assembly
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new OrgJsonValueSerializationAssembler().assemble( module );
-    }
-    // END SNIPPET: assembly
-}
diff --git a/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonValueCompositeSerializationTest.java b/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonValueCompositeSerializationTest.java
deleted file mode 100644
index 1b2f7eb..0000000
--- a/extensions/valueserialization-orgjson/src/test/java/org/qi4j/valueserialization/orgjson/OrgJsonValueCompositeSerializationTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.orgjson;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.value.AbstractValueCompositeSerializationTest;
-
-public class OrgJsonValueCompositeSerializationTest
-    extends AbstractValueCompositeSerializationTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-    }
-}
diff --git a/extensions/valueserialization-orgjson/src/test/resources/configtest.json b/extensions/valueserialization-orgjson/src/test/resources/configtest.json
deleted file mode 100644
index d48a241..0000000
--- a/extensions/valueserialization-orgjson/src/test/resources/configtest.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "identity" : "configtest",
-  "host": {
-    "ip": "12.23.34.45",
-    "port": 1234
-  },
-  "name": "main"
-}
\ No newline at end of file
diff --git a/extensions/valueserialization-stax/build.gradle b/extensions/valueserialization-stax/build.gradle
deleted file mode 100644
index ea05136..0000000
--- a/extensions/valueserialization-stax/build.gradle
+++ /dev/null
@@ -1,35 +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.
- */
-
-description = "Apache Zest™ StaX ValueSerialization Extension"
-
-jar { manifest { name = "Apache Zest™ Extension - ValueSerialization - StaX" } }
-
-dependencies {
-
-    compile project(":org.qi4j.core:org.qi4j.core.bootstrap")
-    compile libraries.commons_lang
-
-    testCompile project(":org.qi4j.core:org.qi4j.core.testsupport")
-
-    testRuntime project(":org.qi4j.core:org.qi4j.core.runtime")
-    testRuntime libraries.slf4j_simple
-
-}
-
diff --git a/extensions/valueserialization-stax/dev-status.xml b/extensions/valueserialization-stax/dev-status.xml
deleted file mode 100644
index cbf512f..0000000
--- a/extensions/valueserialization-stax/dev-status.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
-  <status>
-    <codebase>beta</codebase>
-    <!--none,early,beta,stable,mature-->
-    <documentation>good</documentation>
-    <!-- none, brief, good, complete -->
-    <unittests>complete</unittests>
-    <!-- none, some, good, complete -->
-  </status>
-  <licenses>
-    <license>ALv2</license>
-  </licenses>
-</module>
\ No newline at end of file
diff --git a/extensions/valueserialization-stax/src/docs/vs-stax.txt b/extensions/valueserialization-stax/src/docs/vs-stax.txt
deleted file mode 100644
index 7302a47..0000000
--- a/extensions/valueserialization-stax/src/docs/vs-stax.txt
+++ /dev/null
@@ -1,43 +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.
-///////////////////////////////////////////////////////////////
-
-[[extension-vs-stax, StAX ValueSerialization]]
-= StAX ValueSerialization =
-
-[devstatus]
---------------
-source=extensions/valueserialization-stax/dev-status.xml
---------------
-
-ValueSerialization Service backed by http://jcp.org/en/jsr/detail?id=173[StAX].
-
-include::../../build/docs/buildinfo/artifact.txt[]
-
-== Assembly ==
-
-Assembly is done as follows:
-
-[snippet,java]
-----
-source=extensions/valueserialization-stax/src/test/java/org/qi4j/valueserialization/stax/StaxPlainValueSerializationTest.java
-tag=assembly
-----
-
-See the ValueSerialization <<core-api-value,API>> and <<core-spi-valueserialization,SPI>> documentation for details and
-usage.
diff --git a/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/StaxValueDeserializer.java b/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/StaxValueDeserializer.java
deleted file mode 100644
index 6c61ffb..0000000
--- a/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/StaxValueDeserializer.java
+++ /dev/null
@@ -1,509 +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.qi4j.valueserialization.stax;
-
-import java.io.InputStream;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.Collection;
-import java.util.Map;
-import javax.xml.stream.XMLEventReader;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.events.XMLEvent;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMResult;
-import javax.xml.transform.stream.StreamSource;
-import org.apache.commons.lang.StringEscapeUtils;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueDeserializer;
-import org.qi4j.api.value.ValueSerializationException;
-import org.qi4j.functional.Function;
-import org.qi4j.spi.value.ValueDeserializerAdapter;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-/**
- * ValueDeserializer reading Values from XML documents.
- */
-public class StaxValueDeserializer
-    extends ValueDeserializerAdapter<XMLEventReader, Node>
-{
-
-    private final XMLInputFactory inputFactory = XMLInputFactory.newInstance();
-    private final TransformerFactory transformerFactory = TransformerFactory.newInstance();
-
-    public StaxValueDeserializer( @Structure Application application,
-                                  @Structure Module module,
-                                  @Service ServiceReference<ValueDeserializer> serviceRef )
-    {
-        super( application, module, serviceRef );
-        // Input Factory setup
-        inputFactory.setProperty( "javax.xml.stream.isValidating", Boolean.FALSE );
-        inputFactory.setProperty( "javax.xml.stream.isNamespaceAware", Boolean.FALSE );
-        inputFactory.setProperty( "javax.xml.stream.supportDTD", Boolean.FALSE );
-        inputFactory.setProperty( "javax.xml.stream.isCoalescing", Boolean.TRUE );
-        inputFactory.setProperty( "javax.xml.stream.isReplacingEntityReferences", Boolean.FALSE );
-    }
-
-    @Override
-    protected XMLEventReader adaptInput( InputStream input )
-        throws Exception
-    {
-        return inputFactory.createXMLEventReader( input, "UTF-8" );
-    }
-
-    @Override
-    protected Object readPlainValue( XMLEventReader input )
-        throws Exception
-    {
-        if( !input.hasNext() )
-        {
-            return null;
-        }
-        XMLEvent nextEvent = input.nextEvent();
-        if( nextEvent.getEventType() == XMLEvent.START_ELEMENT
-            && "null".equals( nextEvent.asStartElement().getName().getLocalPart() ) )
-        {
-            input.nextTag();
-            return null;
-        }
-        if( nextEvent.getEventType() != XMLEvent.CHARACTERS )
-        {
-            throw new ValueSerializationException( "Expected characters but got: " + nextEvent );
-        }
-        String stringValue = nextEvent.asCharacters().getData();
-        return detectAndConvertStringValue( stringValue );
-    }
-
-    @Override
-    protected <T> Collection<T> readArrayInCollection( XMLEventReader input,
-                                                       Function<XMLEventReader, T> deserializer,
-                                                       Collection<T> collection )
-        throws Exception
-    {
-        if( !input.hasNext() )
-        {
-            return null;
-        }
-        XMLEvent nextTag = input.nextTag();
-        if( nextTag.isStartElement() && "null".equals( nextTag.asStartElement().getName().getLocalPart() ) )
-        {
-            input.nextTag();
-            return null;
-        }
-        if( !nextTag.isStartElement() || !"array".equals( nextTag.asStartElement().getName().getLocalPart() ) )
-        {
-            throw new ValueSerializationException( "Expected an <array/> but got: " + nextTag );
-        }
-        WHILE:
-        while( input.hasNext() )
-        {
-            XMLEvent currentTag = input.nextTag();
-            if( currentTag.isEndElement() )
-            {
-                String endElementName = currentTag.asEndElement().getName().getLocalPart();
-                switch( endElementName )
-                {
-                    case "array":
-                        break WHILE;
-                    case "value":
-                        continue;
-                }
-            }
-            if( !"value".equals( currentTag.asStartElement().getName().getLocalPart() ) )
-            {
-                throw new ValueSerializationException( "Expected a <value/> but got: " + currentTag );
-            }
-            T item = deserializer.map( input );
-            collection.add( item );
-        }
-        return collection;
-    }
-
-    @Override
-    protected <K, V> Map<K, V> readMapInMap( XMLEventReader input,
-                                             Function<XMLEventReader, K> keyDeserializer,
-                                             Function<XMLEventReader, V> valueDeserializer,
-                                             Map<K, V> map )
-        throws Exception
-    {
-        if( !input.hasNext() )
-        {
-            return null;
-        }
-        XMLEvent nextTag = input.nextTag();
-        if( nextTag.isStartElement() && "null".equals( nextTag.asStartElement().getName().getLocalPart() ) )
-        {
-            input.nextTag();
-            return null;
-        }
-        if( !nextTag.isStartElement() || !"array".equals( nextTag.asStartElement().getName().getLocalPart() ) )
-        {
-            throw new ValueSerializationException( "Expected an <array/> but got: " + nextTag );
-        }
-        XMLEvent currentTag = input.nextTag(); // <object>
-        while( !currentTag.isEndElement() || !"array".equals( currentTag.asEndElement().getName().getLocalPart() ) )
-        {
-            if( !currentTag.isStartElement() || !"object".equals( currentTag.asStartElement().getName().getLocalPart() ) )
-            {
-                throw new ValueSerializationException( "Expected an <object/> but got: " + nextTag );
-            }
-            currentTag = input.nextTag(); // <field>
-            K key = null;
-            V value = null;
-            while( !currentTag.isEndElement() || !"object".equals( currentTag.asEndElement().getName().getLocalPart() ) )
-            {
-                input.nextTag(); // <name>
-                String keyOrValue = input.nextEvent().asCharacters().getData();
-                input.nextTag(); // </name>
-                input.nextTag(); // <value>
-                switch( keyOrValue )
-                {
-                    case "key":
-                        key = keyDeserializer.map( input );
-                        break;
-                    case "value":
-                        value = valueDeserializer.map( input );
-                        break;
-                    default:
-                        readObjectTree( input );
-                        break;
-                }
-                input.nextTag(); // </value>
-                input.nextTag(); // </field>
-                currentTag = input.nextTag();
-            }
-            if( key != null )
-            {
-                map.put( key, value );
-            }
-            currentTag = input.nextTag();
-        }
-        return map;
-    }
-
-    @Override
-    protected Node readObjectTree( XMLEventReader input )
-        throws Exception
-    {
-        XMLEvent peek = input.peek();
-        if( peek.isStartElement() && "null".equals( peek.asStartElement().getName().getLocalPart() ) )
-        {
-            input.nextTag();// <null>
-            input.nextTag();// </null>
-            return null;
-        }
-        String elementBody = readElementBody( input );
-        Transformer transformer = transformerFactory.newTransformer();
-        DOMResult domResult = new DOMResult();
-        transformer.transform( new StreamSource( new StringReader( elementBody ) ), domResult );
-        return ( (Document) domResult.getNode() ).getDocumentElement();
-
-    }
-
-    private static String readElementBody( XMLEventReader input )
-        throws XMLStreamException
-    {
-        StringWriter buf = new StringWriter( 1024 );
-        int depth = 0;
-        while( input.hasNext() )
-        {
-            // peek event
-            XMLEvent xmlEvent = input.peek();
-            if( xmlEvent.isStartElement() )
-            {
-                ++depth;
-            }
-            else if( xmlEvent.isEndElement() )
-            {
-                --depth;
-                // reached END_ELEMENT tag?
-                // break loop, leave event in stream
-                if( depth < 0 )
-                {
-                    break;
-                }
-            }
-            // consume event
-            xmlEvent = input.nextEvent();
-            // print out event
-            xmlEvent.writeAsEncodedUnicode( buf );
-        }
-        return buf.getBuffer().toString();
-    }
-
-    @Override
-    protected Object asSimpleValue( Node inputNode )
-        throws Exception
-    {
-        if( inputNode == null )
-        {
-            return null;
-        }
-        if( inputNode.getNodeType() == Node.ELEMENT_NODE && "null".equals( inputNode.getLocalName() ) )
-        {
-            return null;
-        }
-        if( inputNode.getNodeType() != Node.TEXT_NODE && inputNode.getNodeType() != Node.CDATA_SECTION_NODE )
-        {
-            throw new ValueSerializationException( "Expected a TEXT or CDATA node but got " + inputNode );
-        }
-        String stringValue = inputNode.getNodeValue();
-        return detectAndConvertStringValue( stringValue );
-    }
-
-    @Override
-    protected boolean isObjectValue( Node inputNode )
-        throws Exception
-    {
-        if( inputNode == null )
-        {
-            return false;
-        }
-        if( "object".equals( inputNode.getLocalName() ) )
-        {
-            return true;
-        }
-        if( !"value".equals( inputNode.getLocalName() ) )
-        {
-            return false;
-        }
-        return getDirectChildNode( inputNode, "object" ) != null;
-    }
-
-    @Override
-    protected boolean objectHasField( Node inputNode, String key )
-        throws Exception
-    {
-        if( inputNode == null )
-        {
-            return false;
-        }
-        Node objectNode;
-        if( "value".equals( inputNode.getLocalName() ) )
-        {
-            objectNode = getDirectChildNode( inputNode, "object" );
-        }
-        else
-        {
-            objectNode = inputNode;
-        }
-        if( objectNode == null )
-        {
-            return false;
-        }
-        if( !"object".equals( objectNode.getLocalName() ) )
-        {
-            throw new ValueSerializationException( "Expected an object value but got: " + objectNode );
-        }
-        return getObjectFieldNode( objectNode, key ) != null;
-    }
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    protected <T> T getObjectFieldValue( Node inputNode,
-                                         String key,
-                                         Function<Node, T> valueDeserializer )
-        throws Exception
-    {
-        if( inputNode == null )
-        {
-            return null;
-        }
-        Node objectNode;
-        if( "value".equals( inputNode.getLocalName() ) )
-        {
-            objectNode = getDirectChildNode( inputNode, "object" );
-        }
-        else
-        {
-            objectNode = inputNode;
-        }
-        if( objectNode == null )
-        {
-            return null;
-        }
-        if( !"object".equals( objectNode.getLocalName() ) )
-        {
-            throw new ValueSerializationException( "Expected an object value but got: " + objectNode );
-        }
-        Node fieldNode = getObjectFieldNode( objectNode, key );
-        if( fieldNode == null )
-        {
-            return null;
-        }
-        Node valueElement = getDirectChildNode( fieldNode, "value" );
-        Node valueNode = valueElement.getFirstChild();
-        if( valueNode == null )
-        {
-            return (T) "";
-        }
-        if( valueNode.getNodeType() == Node.ELEMENT_NODE && "null".equals( valueNode.getLocalName() ) )
-        {
-            return null;
-        }
-        T value = valueDeserializer.map( valueNode );
-        return value;
-    }
-
-    @Override
-    protected <T> void putArrayNodeInCollection( Node inputNode,
-                                                 Function<Node, T> deserializer,
-                                                 Collection<T> collection )
-        throws Exception
-    {
-        if( inputNode == null )
-        {
-            return;
-        }
-        if( !( inputNode instanceof Element ) )
-        {
-            throw new ValueSerializationException( "Expected an Element but got " + inputNode );
-        }
-        NodeList arrayValues = inputNode.getChildNodes();
-        for( int arrayValuesIndex = 0; arrayValuesIndex < arrayValues.getLength(); arrayValuesIndex++ )
-        {
-            Node arrayValue = arrayValues.item( arrayValuesIndex );
-            T value = deserializer.map( arrayValue.getFirstChild() );
-            collection.add( value );
-        }
-    }
-
-    @Override
-    protected <K, V> void putArrayNodeInMap( Node inputNode,
-                                             Function<Node, K> keyDeserializer,
-                                             Function<Node, V> valueDeserializer, Map<K, V> map )
-        throws Exception
-    {
-        if( inputNode == null )
-        {
-            return;
-        }
-        if( !"array".equals( inputNode.getLocalName() ) )
-        {
-            throw new ValueSerializationException( "Expected an <array/> but got " + inputNode );
-        }
-        NodeList entriesNodes = inputNode.getChildNodes();
-        for( int idx = 0; idx < entriesNodes.getLength(); idx++ )
-        {
-            Node entryNode = entriesNodes.item( idx );
-            K key = getObjectFieldValue( entryNode, "key", keyDeserializer );
-            V value = getObjectFieldValue( entryNode, "value", valueDeserializer );
-            if( key != null )
-            {
-                map.put( key, value );
-            }
-        }
-    }
-
-    @Override
-    protected <V> void putObjectNodeInMap( Node inputNode,
-                                           Function<Node, V> valueDeserializer,
-                                           Map<String, V> map )
-        throws Exception
-    {
-        if( inputNode == null )
-        {
-            return;
-        }
-        if( !"object".equals( inputNode.getLocalName() ) )
-        {
-            throw new ValueSerializationException( "Expected an <object/> but got " + inputNode );
-        }
-        NodeList fieldsNodes = inputNode.getChildNodes();
-        for( int idx = 0; idx < fieldsNodes.getLength(); idx++ )
-        {
-            Node fieldNode = fieldsNodes.item( idx );
-            String key = getDirectChildNode( fieldNode, "name" ).getTextContent();
-            if( key != null && key.length() > 0 )
-            {
-                V value = getObjectFieldValue( inputNode, key, valueDeserializer );
-                map.put( key, value );
-            }
-        }
-    }
-
-    @SuppressWarnings( "AssignmentToMethodParameter" )
-    private Object detectAndConvertStringValue( String stringValue )
-    {
-        if( stringValue == null || stringValue.length() == 0 )
-        {
-            return "";
-        }
-        stringValue = StringEscapeUtils.unescapeXml( stringValue );
-        if( stringValue.matches( "[+-]?\\d+(\\.\\d+)?([eE][+-]?\\d+(\\.\\d+)?)?" ) )
-        {
-            if( stringValue.indexOf( '.' ) != -1 )
-            {
-                return new BigDecimal( stringValue );
-            }
-            return new BigInteger( stringValue );
-        }
-        if( "true".equalsIgnoreCase( stringValue ) || "false".equalsIgnoreCase( stringValue ) )
-        {
-            return Boolean.parseBoolean( stringValue );
-        }
-        return stringValue;
-    }
-
-    private static Node getObjectFieldNode( Node inputNode, String key )
-    {
-        if( inputNode == null )
-        {
-            return null;
-        }
-        if( !( inputNode instanceof Element ) )
-        {
-            throw new ValueSerializationException( "Excpected an Element but got " + inputNode );
-        }
-        NodeList fieldNodes = inputNode.getChildNodes();
-        for( int idx = 0; idx < fieldNodes.getLength(); idx++ )
-        {
-            Node fieldNode = fieldNodes.item( idx );
-            Node nameNode = getDirectChildNode( fieldNode, "name" );
-            if( nameNode != null && key.equals( nameNode.getTextContent() ) )
-            {
-                return fieldNode;
-            }
-        }
-        return null;
-    }
-
-    private static Node getDirectChildNode( Node parent, String name )
-    {
-        for( Node child = parent.getFirstChild(); child != null; child = child.getNextSibling() )
-        {
-            if( name.equals( child.getNodeName() ) )
-            {
-                return child;
-            }
-        }
-        return null;
-    }
-}
diff --git a/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/StaxValueSerializationAssembler.java b/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/StaxValueSerializationAssembler.java
deleted file mode 100644
index 84c8f21..0000000
--- a/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/StaxValueSerializationAssembler.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.stax;
-
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Function;
-
-/**
- * Assemble a ValueSerialization Service producing and consuming XML documents.
- */
-public class StaxValueSerializationAssembler
-    extends Assemblers.Visibility<StaxValueSerializationAssembler>
-{
-    private Function<Application, Module> valuesModuleFinder;
-
-    public StaxValueSerializationAssembler withValuesModuleFinder( Function<Application, Module> valuesModuleFinder )
-    {
-        this.valuesModuleFinder = valuesModuleFinder;
-        return this;
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        if( valuesModuleFinder == null )
-        {
-            module.services( StaxValueSerializationService.class ).
-                visibleIn( visibility() ).
-                taggedWith( ValueSerialization.Formats.XML );
-        }
-        else
-        {
-            module.services( StaxValueSerializationService.class ).
-                visibleIn( visibility() ).
-                taggedWith( ValueSerialization.Formats.XML ).
-                setMetaInfo( valuesModuleFinder );
-        }
-    }
-}
diff --git a/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/StaxValueSerializationService.java b/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/StaxValueSerializationService.java
deleted file mode 100644
index 6c8a378..0000000
--- a/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/StaxValueSerializationService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.stax;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.value.ValueSerialization;
-
-/**
- * ValueSerialization Service producing and consuming XML documents.
- */
-@Mixins( { StaxValueSerializer.class, StaxValueDeserializer.class } )
-public interface StaxValueSerializationService
-    extends ValueSerialization
-{
-}
diff --git a/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/StaxValueSerializer.java b/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/StaxValueSerializer.java
deleted file mode 100644
index 35b83a3..0000000
--- a/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/StaxValueSerializer.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.stax;
-
-import java.io.OutputStream;
-import javax.xml.stream.XMLOutputFactory;
-import javax.xml.stream.XMLStreamWriter;
-import org.apache.commons.lang.StringEscapeUtils;
-import org.qi4j.spi.value.ValueSerializerAdapter;
-
-/**
- * ValueSerializer producing Values state as XML documents.
- */
-public class StaxValueSerializer
-    extends ValueSerializerAdapter<XMLStreamWriter>
-{
-
-    private final XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
-
-    public StaxValueSerializer()
-    {
-        // Output Factory setup
-        outputFactory.setProperty( "javax.xml.stream.isRepairingNamespaces", Boolean.FALSE );
-    }
-
-    @Override
-    protected XMLStreamWriter adaptOutput( OutputStream output )
-        throws Exception
-    {
-        XMLStreamWriter xmlStreamWriter = outputFactory.createXMLStreamWriter( output, "UTF-8" );
-        xmlStreamWriter.writeStartDocument( "utf-8", "1.1" );
-        return xmlStreamWriter;
-    }
-
-    @Override
-    protected void onSerializationEnd( Object object, XMLStreamWriter output )
-        throws Exception
-    {
-        output.writeEndDocument();
-        output.flush();
-        output.close();
-    }
-
-    @Override
-    protected void onArrayStart( XMLStreamWriter output )
-        throws Exception
-    {
-        output.writeStartElement( "array" );
-    }
-
-    @Override
-    protected void onArrayEnd( XMLStreamWriter output )
-        throws Exception
-    {
-        output.writeEndElement();
-    }
-
-    @Override
-    protected void onObjectStart( XMLStreamWriter output )
-        throws Exception
-    {
-        output.writeStartElement( "object" );
-    }
-
-    @Override
-    protected void onObjectEnd( XMLStreamWriter output )
-        throws Exception
-    {
-        output.writeEndElement();
-    }
-
-    @Override
-    protected void onFieldStart( XMLStreamWriter output, String key )
-        throws Exception
-    {
-        output.writeStartElement( "field" );
-        output.writeStartElement( "name" );
-        output.writeCharacters( key );
-        output.writeEndElement();
-    }
-
-    @Override
-    protected void onFieldEnd( XMLStreamWriter output )
-        throws Exception
-    {
-        output.writeEndElement();
-    }
-
-    @Override
-    protected void onValueStart( XMLStreamWriter output )
-        throws Exception
-    {
-        output.writeStartElement( "value" );
-    }
-
-    @Override
-    protected void onValue( XMLStreamWriter output, Object value )
-        throws Exception
-    {
-        if( value == null )
-        {
-            output.writeStartElement( "null" );
-            output.writeEndElement();
-        }
-        else
-        {
-            output.writeCharacters( StringEscapeUtils.escapeXml( value.toString() ) );
-        }
-    }
-
-    @Override
-    protected void onValueEnd( XMLStreamWriter output )
-        throws Exception
-    {
-        output.writeEndElement();
-    }
-}
diff --git a/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/package.html b/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/package.html
deleted file mode 100644
index 2d3a1dd..0000000
--- a/extensions/valueserialization-stax/src/main/java/org/qi4j/valueserialization/stax/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>XML StAX Value Serializer.</h2>
-    </body>
-</html>
diff --git a/extensions/valueserialization-stax/src/test/java/org/qi4j/valueserialization/stax/StaxCollectionSerializationTest.java b/extensions/valueserialization-stax/src/test/java/org/qi4j/valueserialization/stax/StaxCollectionSerializationTest.java
deleted file mode 100644
index bae5e19..0000000
--- a/extensions/valueserialization-stax/src/test/java/org/qi4j/valueserialization/stax/StaxCollectionSerializationTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.stax;
-
-import org.junit.BeforeClass;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.value.AbstractCollectionSerializationTest;
-
-import static org.qi4j.test.util.Assume.assumeNoIbmJdk;
-
-public class StaxCollectionSerializationTest
-    extends AbstractCollectionSerializationTest
-{
-
-    @BeforeClass
-    public static void beforeClass_IBMJDK()
-    {
-        assumeNoIbmJdk();
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        new StaxValueSerializationAssembler().assemble( module );
-    }
-}
diff --git a/extensions/valueserialization-stax/src/test/java/org/qi4j/valueserialization/stax/StaxConfigurationDeserializationTest.java b/extensions/valueserialization-stax/src/test/java/org/qi4j/valueserialization/stax/StaxConfigurationDeserializationTest.java
deleted file mode 100644
index 4f32986..0000000
--- a/extensions/valueserialization-stax/src/test/java/org/qi4j/valueserialization/stax/StaxConfigurationDeserializationTest.java
+++ /dev/null
@@ -1,65 +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.qi4j.valueserialization.stax;
-
-import org.junit.Ignore;
-import org.junit.Test;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.entity.AbstractConfigurationDeserializationTest;
-
-@Ignore( "Complex configurations are not yet support in Stax ValueSerialization, due to handling arrays with Java serialization.")
-public class StaxConfigurationDeserializationTest
-    extends AbstractConfigurationDeserializationTest
-{
-    @Service
-    private ValueSerialization valueSerialization;
-
-    @Override
-    public void assemble( final ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        new StaxValueSerializationAssembler()
-            .assemble( module );
-    }
-
-    @Test
-    public void serializeTest()
-    {
-        ValueBuilder<ConfigSerializationConfig> builder = module.newValueBuilder( ConfigSerializationConfig.class );
-        builder.prototype().name().set( "main" );
-        builder.prototype().host().set( createHost() );
-        builder.prototype().identity().set( "configtest" );
-        ConfigSerializationConfig value = builder.newInstance();
-
-        valueSerialization.serialize( value, System.out );
-    }
-
-    private Host createHost()
-    {
-        ValueBuilder<Host> builder = module.newValueBuilder( Host.class );
-        builder.prototype().ip().set( "12.23.34.45" );
-        builder.prototype().port().set( 1234 );
-        return builder.newInstance();
-    }
-}
diff --git a/extensions/valueserialization-stax/src/test/java/org/qi4j/valueserialization/stax/StaxPlainValueSerializationTest.java b/extensions/valueserialization-stax/src/test/java/org/qi4j/valueserialization/stax/StaxPlainValueSerializationTest.java
deleted file mode 100644
index a124c28..0000000
--- a/extensions/valueserialization-stax/src/test/java/org/qi4j/valueserialization/stax/StaxPlainValueSerializationTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.stax;
-
-import org.junit.BeforeClass;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.value.AbstractPlainValueSerializationTest;
-
-import static org.qi4j.test.util.Assume.assumeNoIbmJdk;
-
-public class StaxPlainValueSerializationTest
-    extends AbstractPlainValueSerializationTest
-{
-
-    @BeforeClass
-    public static void beforeClass_IBMJDK()
-    {
-        assumeNoIbmJdk();
-    }
-
-    // START SNIPPET: assembly
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new StaxValueSerializationAssembler().assemble( module );
-    }
-    // END SNIPPET: assembly
-}
diff --git a/extensions/valueserialization-stax/src/test/java/org/qi4j/valueserialization/stax/StaxValueCompositeSerializationTest.java b/extensions/valueserialization-stax/src/test/java/org/qi4j/valueserialization/stax/StaxValueCompositeSerializationTest.java
deleted file mode 100644
index 34536e4..0000000
--- a/extensions/valueserialization-stax/src/test/java/org/qi4j/valueserialization/stax/StaxValueCompositeSerializationTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.valueserialization.stax;
-
-import org.junit.BeforeClass;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.value.AbstractValueCompositeSerializationTest;
-
-import static org.qi4j.test.util.Assume.assumeNoIbmJdk;
-
-public class StaxValueCompositeSerializationTest
-    extends AbstractValueCompositeSerializationTest
-{
-
-    @BeforeClass
-    public static void beforeClass_IBMJDK()
-    {
-        assumeNoIbmJdk();
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        super.assemble( module );
-        new StaxValueSerializationAssembler().assemble( module );
-    }
-}
diff --git a/extensions/valueserialization-stax/src/test/resources/configtest.xml b/extensions/valueserialization-stax/src/test/resources/configtest.xml
deleted file mode 100644
index 90d2d23..0000000
--- a/extensions/valueserialization-stax/src/test/resources/configtest.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.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.
-  ~
-  -->
-
-<object>
-  <field>
-    <name>name</name>
-    <value>main</value>
-  </field>
-  <field>
-    <name>host</name>
-    <value>
-      <object>
-        <field>
-          <name>_type</name>
-          <value>org.qi4j.test.entity.AbstractConfigurationDeserializationTest$Host</value>
-        </field>
-        <field>
-          <name>port</name>
-          <value>1234</value>
-        </field>
-        <field>
-          <name>ip</name>
-          <value>12.23.34.45</value>
-        </field>
-      </object>
-    </value>
-  </field>
-  <field>
-    <name>identity</name>
-    <value>configtest</value>
-  </field>
-</object>
diff --git a/gradle-profiler.scenarios b/gradle-profiler.scenarios
new file mode 100644
index 0000000..4b85032
--- /dev/null
+++ b/gradle-profiler.scenarios
@@ -0,0 +1,11 @@
+# Configuration
+help {
+    tasks = ["help"]
+}
+
+# Verification from a clean working copy
+clean_check {
+    gradle-args = ["--parallel"]
+    tasks = ["check"]
+    cleanup-tasks = ["clean"]
+}
diff --git a/gradle.properties b/gradle.properties
index 455a465..ee0e41c 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,14 +1,19 @@
-# 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
+#  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
 #
-# 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.
+#       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.
+#
+
+org.gradle.jvmargs=-Xms2g -Xmx2g
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 0087cd3..51288f9 100644
--- a/gradle/wrapper/gradle-wrapper.jar
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 48f202a..2271d9f 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,24 @@
-#Mon Jul 06 10:43:59 EEST 2015
+#
+#  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.
+#
+
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-all.zip
+
diff --git a/gradlew b/gradlew
index 91a7e26..4453cce 100755
--- a/gradlew
+++ b/gradlew
@@ -1,4 +1,4 @@
-#!/usr/bin/env bash
+#!/usr/bin/env sh
 
 ##############################################################################
 ##
@@ -6,12 +6,30 @@
 ##
 ##############################################################################
 
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
 
 APP_NAME="Gradle"
 APP_BASE_NAME=`basename "$0"`
 
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
 # Use the maximum available, or set MAX_FD != -1 to use that value.
 MAX_FD="maximum"
 
@@ -30,6 +48,7 @@
 cygwin=false
 msys=false
 darwin=false
+nonstop=false
 case "`uname`" in
   CYGWIN* )
     cygwin=true
@@ -40,31 +59,11 @@
   MINGW* )
     msys=true
     ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
 esac
 
-# For Cygwin, ensure paths are in UNIX format before anything is touched.
-if $cygwin ; then
-    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
-fi
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >&-
-APP_HOME="`pwd -P`"
-cd "$SAVED" >&-
-
 CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 
 # Determine the Java command to use to start the JVM.
@@ -90,7 +89,7 @@
 fi
 
 # Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
     MAX_FD_LIMIT=`ulimit -H -n`
     if [ $? -eq 0 ] ; then
         if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@@ -114,6 +113,7 @@
 if $cygwin ; then
     APP_HOME=`cygpath --path --mixed "$APP_HOME"`
     CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
 
     # We build the pattern for arguments to be converted via cygpath
     ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
@@ -154,11 +154,19 @@
     esac
 fi
 
-# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
-function splitJvmOpts() {
-    JVM_OPTS=("$@")
+# Escape application args
+save ( ) {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
 }
-eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
-JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+APP_ARGS=$(save "$@")
 
-exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
index aec9973..e95643d 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -8,14 +8,14 @@
 @rem Set local scope for the variables with windows NT shell

 if "%OS%"=="Windows_NT" setlocal

 

-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.

-set DEFAULT_JVM_OPTS=

-

 set DIRNAME=%~dp0

 if "%DIRNAME%" == "" set DIRNAME=.

 set APP_BASE_NAME=%~n0

 set APP_HOME=%DIRNAME%

 

+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.

+set DEFAULT_JVM_OPTS=

+

 @rem Find java.exe

 if defined JAVA_HOME goto findJavaFromJavaHome

 

@@ -46,10 +46,9 @@
 goto fail

 

 :init

-@rem Get command-line arguments, handling Windowz variants

+@rem Get command-line arguments, handling Windows variants

 

 if not "%OS%" == "Windows_NT" goto win9xME_args

-if "%@eval[2+2]" == "4" goto 4NT_args

 

 :win9xME_args

 @rem Slurp the command line arguments.

@@ -60,11 +59,6 @@
 if "x%~1" == "x" goto execute

 

 set CMD_LINE_ARGS=%*

-goto execute

-

-:4NT_args

-@rem Get arguments from the 4NT Shell from JP Software

-set CMD_LINE_ARGS=%$

 

 :execute

 @rem Setup the command line

diff --git a/internals/testsupport-internal/build.gradle b/internals/testsupport-internal/build.gradle
new file mode 100644
index 0000000..a38d41c
--- /dev/null
+++ b/internals/testsupport-internal/build.gradle
@@ -0,0 +1,32 @@
+/*
+ *  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.
+ */
+
+apply plugin: 'polygene-internal'
+apply plugin: 'polygene-internal-docker'
+
+description = "Apache Polygene™ Internal Test Support"
+
+jar { manifest { name = "Apache Polygene™ Internals - Test Support" } }
+
+dependencies {
+  api polygene.core.testsupport
+
+  implementation libraries.docker_junit
+
+  runtimeOnly polygene.core.runtime
+}
diff --git a/internals/testsupport-internal/src/main/docker/cassandra/Dockerfile b/internals/testsupport-internal/src/main/docker/cassandra/Dockerfile
new file mode 100644
index 0000000..11d22b4
--- /dev/null
+++ b/internals/testsupport-internal/src/main/docker/cassandra/Dockerfile
@@ -0,0 +1,16 @@
+# 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.
+
+FROM @cassandra@
diff --git a/internals/testsupport-internal/src/main/docker/memcached/Dockerfile b/internals/testsupport-internal/src/main/docker/memcached/Dockerfile
new file mode 100644
index 0000000..0b1a4b2
--- /dev/null
+++ b/internals/testsupport-internal/src/main/docker/memcached/Dockerfile
@@ -0,0 +1,16 @@
+# 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.
+
+FROM @memcached@
diff --git a/internals/testsupport-internal/src/main/docker/mysql/Dockerfile b/internals/testsupport-internal/src/main/docker/mysql/Dockerfile
new file mode 100644
index 0000000..967d45d
--- /dev/null
+++ b/internals/testsupport-internal/src/main/docker/mysql/Dockerfile
@@ -0,0 +1,16 @@
+# 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.
+
+FROM @mariadb@
\ No newline at end of file
diff --git a/internals/testsupport-internal/src/main/docker/postgres/Dockerfile b/internals/testsupport-internal/src/main/docker/postgres/Dockerfile
new file mode 100644
index 0000000..d3dad53
--- /dev/null
+++ b/internals/testsupport-internal/src/main/docker/postgres/Dockerfile
@@ -0,0 +1,17 @@
+# 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.
+
+FROM @postgres@
+COPY init-test-db.sh /docker-entrypoint-initdb.d/init-test-db.sh
diff --git a/internals/testsupport-internal/src/main/docker/postgres/init-test-db.sh b/internals/testsupport-internal/src/main/docker/postgres/init-test-db.sh
new file mode 100755
index 0000000..347d78d
--- /dev/null
+++ b/internals/testsupport-internal/src/main/docker/postgres/init-test-db.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+# 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.
+
+set -e
+
+# Create test user and database
+psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
+    CREATE USER jdbc_test_login;
+    CREATE DATABASE jdbc_test_db;
+    GRANT ALL PRIVILEGES ON DATABASE jdbc_test_db TO jdbc_test_login;
+EOSQL
+
+# Enable ltree extension on test database
+psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" -d jdbc_test_db <<-EOSQL
+    CREATE EXTENSION ltree;
+EOSQL
diff --git a/internals/testsupport-internal/src/main/docker/redis/Dockerfile b/internals/testsupport-internal/src/main/docker/redis/Dockerfile
new file mode 100644
index 0000000..d0e67fc
--- /dev/null
+++ b/internals/testsupport-internal/src/main/docker/redis/Dockerfile
@@ -0,0 +1,16 @@
+# 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.
+
+FROM @redis@
diff --git a/internals/testsupport-internal/src/main/docker/riak/Dockerfile b/internals/testsupport-internal/src/main/docker/riak/Dockerfile
new file mode 100644
index 0000000..776d7af
--- /dev/null
+++ b/internals/testsupport-internal/src/main/docker/riak/Dockerfile
@@ -0,0 +1,16 @@
+# 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.
+
+FROM @riak@
diff --git a/internals/testsupport-internal/src/main/docker/s3server/Dockerfile b/internals/testsupport-internal/src/main/docker/s3server/Dockerfile
new file mode 100644
index 0000000..a4bff87
--- /dev/null
+++ b/internals/testsupport-internal/src/main/docker/s3server/Dockerfile
@@ -0,0 +1,20 @@
+# 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.
+
+FROM @s3server@
+
+# See https://github.com/scality/S3/blob/master/DOCKER.md
+ENV SCALITY_ACCESS_KEY_ID dummyIdentifier
+ENV SCALITY_SECRET_ACCESS_KEY dummyCredential
diff --git a/internals/testsupport-internal/src/main/java/org/apache/polygene/test/internal/DelayChecker.java b/internals/testsupport-internal/src/main/java/org/apache/polygene/test/internal/DelayChecker.java
new file mode 100644
index 0000000..574381d
--- /dev/null
+++ b/internals/testsupport-internal/src/main/java/org/apache/polygene/test/internal/DelayChecker.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.test.internal;
+
+import pl.domzal.junit.docker.rule.wait.StartCondition;
+import pl.domzal.junit.docker.rule.wait.StartConditionCheck;
+
+class DelayChecker
+    implements StartCondition
+{
+
+    private final long millis;
+    private final long doneAt;
+
+    DelayChecker( long millis )
+    {
+        this.millis = millis;
+        this.doneAt = System.currentTimeMillis() + millis;
+    }
+
+    @Override
+    public StartConditionCheck build( pl.domzal.junit.docker.rule.DockerRule currentRule )
+    {
+        return new StartConditionCheck()
+        {
+
+            @Override
+            public boolean check()
+            {
+                return System.currentTimeMillis() > doneAt;
+            }
+
+            @Override
+            public String describe()
+            {
+                return String.format( "delay check %d ms", millis );
+            }
+
+            @Override
+            public void after()
+            {
+            }
+        };
+    }
+}
diff --git a/internals/testsupport-internal/src/main/java/org/apache/polygene/test/internal/DockerRule.java b/internals/testsupport-internal/src/main/java/org/apache/polygene/test/internal/DockerRule.java
new file mode 100644
index 0000000..35b4f12
--- /dev/null
+++ b/internals/testsupport-internal/src/main/java/org/apache/polygene/test/internal/DockerRule.java
@@ -0,0 +1,156 @@
+/*
+ *  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.polygene.test.internal;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+import pl.domzal.junit.docker.rule.DockerRuleBuilder;
+import pl.domzal.junit.docker.rule.WaitFor;
+import pl.domzal.junit.docker.rule.wait.LineListener;
+import pl.domzal.junit.docker.rule.wait.StartCondition;
+import pl.domzal.junit.docker.rule.wait.StartConditionCheck;
+
+import static java.util.stream.Collectors.joining;
+import static org.junit.Assume.assumeFalse;
+
+public class DockerRule
+    implements TestRule
+{
+    private final boolean dockerDisabled = Boolean.valueOf( System.getProperty( "DOCKER_DISABLED", "false" ) );
+    private final pl.domzal.junit.docker.rule.DockerRule dockerRule;
+
+    public DockerRule( String image, int... portsToWaitFor )
+    {
+        this( image, null, WaitFor.tcpPort( portsToWaitFor ) );
+    }
+
+    public DockerRule( String image, String... logMessageSequenceToWaitFor )
+    {
+        this( image, null, WaitFor.logMessageSequence( logMessageSequenceToWaitFor ) );
+    }
+
+    public DockerRule( String image, Map<String, String> environment, String... logMessageSequnceToWaitFor )
+    {
+        this( image, environment, WaitFor.logMessageSequence( logMessageSequnceToWaitFor ) );
+    }
+
+    public DockerRule( String image, Long delay, int... portsToWaitFor )
+    {
+        this( image, null, new DelayChecker( delay ), WaitFor.tcpPort( portsToWaitFor ), new DelayChecker( delay ) );
+    }
+
+    public DockerRule( String image, Long delay, String... logMessageSequenceToWaitFor )
+    {
+        this( image, null, WaitFor.logMessageSequence( logMessageSequenceToWaitFor ), new DelayChecker( delay ) );
+    }
+
+    public DockerRule( String image, Map<String, String> environment, Long delay, String... logMessageSequnceToWaitFor )
+    {
+        this( image, environment, WaitFor.logMessageSequence( logMessageSequnceToWaitFor ), new DelayChecker( delay ) );
+    }
+
+    public DockerRule( String image, Map<String, String> environment, StartCondition... waitFor )
+    {
+        if( environment == null )
+        {
+            environment = Collections.emptyMap();
+        }
+        if( dockerDisabled )
+        {
+            dockerRule = null;
+        }
+        else
+        {
+            DockerRuleBuilder builder = pl.domzal.junit.docker.rule.DockerRule
+                .builder()
+                .imageName( "org.apache.polygene:org.apache.polygene.internal.docker-" + image )
+                .publishAllPorts( true )
+                .waitForTimeout( 60000 )
+                .waitFor( rule -> new AndChecker( rule, waitFor ) );
+            environment.forEach( builder::env );
+            dockerRule = builder.build();
+        }
+    }
+
+    @Override
+    public Statement apply( Statement base, Description description )
+    {
+        assumeFalse( dockerDisabled );
+        return dockerRule.apply( base, description );
+    }
+
+    public String getDockerHost()
+    {
+        return dockerRule.getDockerHost();
+    }
+
+    public int getExposedContainerPort( String containerPort )
+    {
+        return Integer.valueOf( dockerRule.getExposedContainerPort( containerPort ) );
+    }
+
+    public class AndChecker
+        implements StartConditionCheck, LineListener
+    {
+        private List<StartConditionCheck> allOf;
+
+        public AndChecker( pl.domzal.junit.docker.rule.DockerRule rule, StartCondition... allOf )
+        {
+            this.allOf = Arrays.stream( allOf ).map( cond -> cond.build( rule ) ).collect( Collectors.toList() );
+        }
+
+        @Override
+        public boolean check()
+        {
+            return allOf.stream()
+                        .allMatch( StartConditionCheck::check );
+        }
+
+        @Override
+        public String describe()
+        {
+            return allOf.stream()
+                        .map( StartConditionCheck::describe )
+                        .collect( joining( ",", "and(", ")" ) );
+        }
+
+        @Override
+        public void after()
+        {
+            allOf.forEach( StartConditionCheck::after );
+        }
+
+        @Override
+        public void nextLine( String line )
+        {
+            allOf.forEach( listener ->
+                           {
+                               if( listener instanceof LineListener )
+                               {
+                                   ( (LineListener) listener ).nextLine( line );
+                               }
+                           } );
+        }
+    }
+}
diff --git a/internals/testsupport-internal/src/main/java/org/apache/polygene/test/internal/package.html b/internals/testsupport-internal/src/main/java/org/apache/polygene/test/internal/package.html
new file mode 100644
index 0000000..6288f30
--- /dev/null
+++ b/internals/testsupport-internal/src/main/java/org/apache/polygene/test/internal/package.html
@@ -0,0 +1,25 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
+<html>
+<body>
+<h1>Polygene Internal TestSupport.</h1>
+</body>
+</html>
\ No newline at end of file
diff --git a/libraries.gradle b/libraries.gradle
deleted file mode 100644
index 1507bc8..0000000
--- a/libraries.gradle
+++ /dev/null
@@ -1,296 +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.
- */
-
-// Versions of Dependencies;
-def asmVersion = '5.0.4'
-def bonecpVersion = '0.8.0.RELEASE'
-def bouncyVersion = '1.52'
-def commonsDbcpVersion = '1.4' // Should be moved to commons-dbcp2
-def commonsLangVersion = '2.6' // Should be moved to commons-lang3
-def derbyVersion = '10.11.1.1'
-def dnsJavaVersion = '2.1.7'
-def ehcacheVersion = '2.10.0'
-def elasticsearchVersion = '1.6.0'
-def freemarkerVersion = '2.3.22'
-def groovyVersion = '2.4.3'
-def h2Version = '1.4.187'
-def hazelcastVersion = '3.5'
-def httpClientVersion = '4.2.2' // 4.3.4 exists
-def jacksonVersion = '2.5.4'
-def javascriptVersion = '1.7.7'
-def javasqlgeneratorVersion = '0.3.2'
-def jcloudsVersion = '1.9.0'
-def jdbmVersion = '2.4'
-def jedisVersion = '2.7.2'
-def jettyVersion = '9.2.11.v20150529' // 9.3.x Tests fail!
-def jgoodiesLooksVersion = '2.5.3'
-def jodaMoneyVersion = '0.10.0'
-def jodaTimeVersion = '2.8.1'
-def jtaVersion = '1.1'
-def leveldbVersion = '0.7'
-def leveldbJniVersion = '1.8'
-def liquibaseVersion = '3.4.0'
-def logbackVersion = '1.1.3'
-def mongodbVersion = '2.13.2' // 3.0.x Fails to compile!
-def mysqlVersion = '5.1.35'
-def orgJsonVersion = '20130213'
-def osgiVersion = '4.2.0' // 4.3.0 Fails to compile! - 5.0.0 exists
-def pdfboxVersion = '1.8.5'
-def postgresqlVersion = '9.4-1201-jdbc41'
-def prefuseVersion = '0.21'
-def restletVersion = '2.0.15' // 2.2.1 Fails to compile!
-def rdfVersion = '2.7.9'
-def riakVersion = '1.4.4' // 2.0.x Fails to compile!
-def scalaVersion = '2.11.6'
-def servletVersion = '3.1.0'
-def shiroVersion = '1.2.3'
-def skedVersion = '2.1'
-def slf4jVersion = '1.7.12'
-def solrVersion = "1.4.1" // 4.8.1 Fails to compile!
-def springVersion = '4.1.7.RELEASE'
-def spymemcachedVersion = '2.12.0'
-def sqliteVersion = '3.8.10.1'
-def velocityVersion = '1.7'
-def wicketVersion = '1.5.8' // 6.15.0 Samples fails to compile!
-def wicketStatelessVersion = '1.5.0'
-def woodstoxVersion = '4.4.1'
-def yammerMetricsVersion = '2.2.0'
-
-def antVersion = '1.9.5'
-def awaitilityVersion = '1.6.3'
-def easyMockVersion = '3.3.1'
-def jmockVersion = '2.8.1'
-def junitVersion = '4.11'
-def mockitoVersion = '1.10.19'
-def testNgVersion = '6.9.4'
-def restAssuredVersion= '2.4.1'
-def xmlunitVersion = '1.6'
-
-// build a map of the dependency artifacts to use.  Allows centralized definition of the version of artifacts to
-// use.  In that respect it serves a role similar to <dependencyManagement> in Maven
-
-rootProject.ext {
-  libraries = [
-          // Ant
-          ant: "org.apache.ant:ant:$antVersion",
-          ant_junit: "org.apache.ant:ant-junit:$antVersion",
-
-          // ASM
-          asm: "org.ow2.asm:asm:$asmVersion",
-          asm_util: "org.ow2.asm:asm-util:$asmVersion",
-          asm_commons: "org.ow2.asm:asm-commons:$asmVersion",
-
-          // OSGi
-          osgi_core: "org.osgi:org.osgi.core:$osgiVersion",
-          osgi_compendium: "org.osgi:org.osgi.compendium:$osgiVersion",
-          osgi_enterprise: "org.osgi:org.osgi.enterprise:$osgiVersion",
-
-          // logging
-          slf4j_api: "org.slf4j:slf4j-api:$slf4jVersion",
-          slf4j_simple: "org.slf4j:slf4j-simple:$slf4jVersion",
-          logback: 'ch.qos.logback:logback-classic:' + logbackVersion,
-          jcl_slf4j: "org.slf4j:jcl-over-slf4j:$slf4jVersion",
-          jcl_api: 'commons-logging:commons-logging-api:99.0-does-not-exist',  //ensure it is never used.
-          jcl: 'commons-logging:commons-logging:99.0-does-not-exist',  // ensure it is never used.
-
-          // org.json
-          org_json: "org.codeartisans:org.json:$orgJsonVersion",
-
-          // Restlet
-          restlet: [
-                  "org.restlet.jee:org.restlet:$restletVersion",
-                  "org.restlet.jee:org.restlet.ext.ssl:$restletVersion",
-                  "org.restlet.jee:org.restlet.ext.atom:$restletVersion",
-                  "org.restlet.jee:org.restlet.ext.servlet:$restletVersion",
-                  "org.restlet.jee:org.restlet.ext.slf4j:$restletVersion"
-          ],
-
-          // Scala
-          scala:  "org.scala-lang:scala-library:$scalaVersion",
-
-          // Spring
-          spring_core: [
-                  "org.springframework:spring-beans:$springVersion",
-                  "org.springframework:spring-context:$springVersion"
-          ],
-
-          spring_testsupport: [
-                  "org.springframework:spring-test:$springVersion"
-          ],
-
-          // RDF
-          sesame: [ "org.openrdf.sesame:sesame-model:$rdfVersion",
-                  "org.openrdf.sesame:sesame-queryparser-sparql:$rdfVersion",
-                  "org.openrdf.sesame:sesame-repository-dataset:$rdfVersion",
-                  "org.openrdf.sesame:sesame-repository-http:$rdfVersion",
-                  "org.openrdf.sesame:sesame-rio-api:$rdfVersion",
-                  "org.openrdf.sesame:sesame-rio-n3:$rdfVersion",
-                  "org.openrdf.sesame:sesame-rio-ntriples:$rdfVersion",
-                  "org.openrdf.sesame:sesame-rio-rdfxml:$rdfVersion",
-                  "org.openrdf.sesame:sesame-rio-trig:$rdfVersion",
-                  "org.openrdf.sesame:sesame-rio-trix:$rdfVersion",
-                  "org.openrdf.sesame:sesame-rio-turtle:$rdfVersion",
-                  "org.openrdf.sesame:sesame-sail-api:$rdfVersion",
-                  "org.openrdf.sesame:sesame-sail-memory:$rdfVersion",
-                  "org.openrdf.sesame:sesame-sail-nativerdf:$rdfVersion",
-                  "org.openrdf.sesame:sesame-sail-rdbms:$rdfVersion"
-          ],
-          sparql: [
-                  "org.openrdf.sesame:sesame-queryresultio-sparqlxml:$rdfVersion",
-                  "org.openrdf.sesame:sesame-queryresultio-sparqljson:$rdfVersion"
-          ],
-
-          // SOLR
-          solr: [ "org.apache.solr:solr-core:$solrVersion",
-                  "org.apache.solr:solr-solrj:$solrVersion"
-          ],
-
-          // Jetty
-          jetty_server: "org.eclipse.jetty:jetty-server:$jettyVersion",
-          jetty_webapp: "org.eclipse.jetty:jetty-webapp:$jettyVersion",
-          jetty_servlet: "org.eclipse.jetty:jetty-servlet:$jettyVersion",
-          jetty_http: "org.eclipse.jetty:jetty-http:$jettyVersion",
-          jetty_io: "org.eclipse.jetty:jetty-io:$jettyVersion",
-          jetty_jmx: "org.eclipse.jetty:jetty-jmx:$jettyVersion",
-          jetty_security: "org.eclipse.jetty:jetty-security:$jettyVersion",
-          jetty_jsp: "org.eclipse.jetty:jetty-jsp:$jettyVersion",
-          jetty_util: "org.eclipse.jetty:jetty-util:$jettyVersion",
-          jetty_continuation: "org.eclipse.jetty:jetty-continuation:$jettyVersion",
-          jetty_client: "org.eclipse.jetty:jetty-client:$jettyVersion",
-          jetty_xml: "org.eclipse.jetty:jetty-xml:$jettyVersion",
-
-          // Scripting
-          groovy: "org.codehaus.groovy:groovy-all:$groovyVersion",
-
-          javascript: "org.mozilla:rhino:$javascriptVersion",
-
-          // Wicket
-          wicket: [ "org.apache.wicket:wicket-core:$wicketVersion",
-                  "org.apache.wicket:wicket-datetime:$wicketVersion",
-                  "org.apache.wicket:wicket-extensions:$wicketVersion"
-          ],
-          wicket_devutils: "org.apache.wicket:wicket-devutils:$wicketVersion",
-          wicket_stateless: "com.jolira:wicket-stateless:$wicketStatelessVersion",
-
-          // Library & Extension dependencies
-          jackson_mapper: "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion",
-          jodamoney: "org.joda:joda-money:$jodaMoneyVersion",
-          jodatime: "joda-time:joda-time:$jodaTimeVersion",
-          ehcache: "net.sf.ehcache:ehcache:$ehcacheVersion",
-          elasticsearch: "org.elasticsearch:elasticsearch:$elasticsearchVersion",
-          h2: "com.h2database:h2:$h2Version",
-          hazelcast: "com.hazelcast:hazelcast:$hazelcastVersion",
-          jclouds_core: "org.apache.jclouds:jclouds-core:$jcloudsVersion",
-          jclouds_blobstore: "org.apache.jclouds:jclouds-allblobstore:$jcloudsVersion",
-          jclouds_filesystem: "org.apache.jclouds.api:filesystem:$jcloudsVersion",
-          jdbm: "jdbm:jdbm:$jdbmVersion",
-          jedis: "redis.clients:jedis:$jedisVersion",
-          jgoodies_looks: "com.jgoodies:jgoodies-looks:$jgoodiesLooksVersion",
-          leveldb_api: "org.iq80.leveldb:leveldb-api:$leveldbVersion",
-          leveldb_java: "org.iq80.leveldb:leveldb:$leveldbVersion",
-          leveldb_jni_all: "org.fusesource.leveldbjni:leveldbjni-all:$leveldbJniVersion",
-          mongodb: "org.mongodb:mongo-java-driver:$mongodbVersion",
-          riak: "com.basho.riak:riak-client:$riakVersion",
-          jta: "javax.transaction:jta:$jtaVersion",
-          javaSqlGenerator: "org.java-sql-generator:org.java-sql-generator.api:$javasqlgeneratorVersion",
-          javaSqlGeneratorImpl: "org.java-sql-generator:org.java-sql-generator.implementation:$javasqlgeneratorVersion",
-          velocity: "org.apache.velocity:velocity:$velocityVersion",
-          commons_dbcp: "commons-dbcp:commons-dbcp:$commonsDbcpVersion",
-          commons_lang: "commons-lang:commons-lang:$commonsLangVersion",
-          servlet_api: "javax.servlet:javax.servlet-api:$servletVersion",
-          http_client: "org.apache.httpcomponents:httpclient:$httpClientVersion",
-          woodstox: "org.codehaus.woodstox:woodstox-core-asl:$woodstoxVersion",
-          restlet_xml: "org.restlet.jee:org.restlet.ext.xml:$restletVersion",
-          bouncy_castle: "org.bouncycastle:bcprov-jdk15on:$bouncyVersion",
-          dnsjava: "dnsjava:dnsjava:$dnsJavaVersion",
-          freemarker: "org.freemarker:freemarker:$freemarkerVersion",
-          shiro: "org.apache.shiro:shiro-core:$shiroVersion",
-          shiro_web: "org.apache.shiro:shiro-web:$shiroVersion",
-          bonecp: "com.jolbox:bonecp:$bonecpVersion",
-          liquibase: "org.liquibase:liquibase-core:$liquibaseVersion",
-          sked: "org.codeartisans:sked:$skedVersion",
-          yammer_metrics: "com.yammer.metrics:metrics-core:$yammerMetricsVersion",
-          pdfbox: "org.apache.pdfbox:pdfbox:$pdfboxVersion",
-          prefuse: "de.sciss:prefuse-core:$prefuseVersion",
-          spymemcached: "net.spy:spymemcached:$spymemcachedVersion",
-
-          // Testing
-          junit: "junit:junit:$junitVersion",
-          awaitility: "com.jayway.awaitility:awaitility:$awaitilityVersion",
-          easymock: "org.easymock:easymock:$easyMockVersion",
-          jmock: "org.jmock:jmock:$jmockVersion",
-          mockito: "org.mockito:mockito-core:$mockitoVersion",
-          rest_assured: "com.jayway.restassured:rest-assured:$restAssuredVersion",
-          testng: "org.testng:testng:$testNgVersion",
-          xmlunit: "xmlunit:xmlunit:$xmlunitVersion",
-          
-          // Tests dependencies
-          derby: "org.apache.derby:derby:$derbyVersion",
-          derbyclient: "org.apache.derby:derbyclient:$derbyVersion",
-          derbynet: "org.apache.derby:derbynet:$derbyVersion",
-          postgres: "org.postgresql:postgresql:$postgresqlVersion",
-          mysql_connector: "mysql:mysql-connector-java:$mysqlVersion",
-          sqlite: "org.xerial:sqlite-jdbc:$sqliteVersion",
-  ]
-}
-
-// Global transitive dependencies substitution rules
-// See https://docs.gradle.org/current/userguide/dependency_management.html#dependency_substitution_rules
-// See https://docs.gradle.org/current/dsl/org.gradle.api.artifacts.DependencySubstitutions.html
-allprojects {
-  configurations.all {
-    resolutionStrategy.dependencySubstitution.all { DependencySubstitution dep ->
-      if( dep.requested instanceof ModuleComponentSelector ) {
-        // Always resolve SLF4J to the same version
-        if( dep.requested.group == 'org.slf4j' ) {
-          dep.useTarget group: dep.requested.group, name: dep.requested.module, version: slf4jVersion
-        }
-        // Always resolve ASM to the same version
-        if( dep.requested.group == 'org.ow2.asm' ) {
-          dep.useTarget group: dep.requested.group, name: dep.requested.module, version: asmVersion
-        }
-        // Always resolve OSGi to the same version
-        if( dep.requested.group == 'org.osgi' ) {
-          dep.useTarget group: dep.requested.group, name: dep.requested.module, version: osgiVersion
-        }
-        // Always resolve Jackson to the same version
-        if( dep.requested.group.startsWith( 'com.fasterxml.jackson' ) ) {
-          dep.useTarget group: dep.requested.group, name: dep.requested.module, version: jacksonVersion
-        }
-        // woodstox:wstx-asl is broken (no pom), use org.codehaus.woodstox:wstx-asl instead
-        if( dep.requested.group == 'woodstox' && dep.requested.module == 'wstx-asl' ) {
-          dep.useTarget group: 'org.codehaus.woodstox', name: 'wstx-asl', version: dep.requested.version
-        }
-        // some bad citizens have SNAPSHOT parents ...
-        if( dep.requested.module == 'commons-sandbox-parent' && dep.requested.version == '3-SNAPSHOT') {
-          dep.useTarget group: dep.requested.group, name: dep.requested.module, version: '3'
-        }
-        // GSON 2.3 POM is invalid, use 2.3.1 instead .. see https://github.com/google/gson/issues/588
-        if( dep.requested.group == 'com.google.code.gson' && dep.requested.module == 'gson' && dep.requested.version == '2.3' ) {
-          dep.useTarget group: dep.requested.group, name: dep.requested.module, version: '2.3.1'
-        }
-        // Findbugs Annotation is LGPL, use https://github.com/stephenc/findbugs-annotations which is
-        // Apache 2 licensed instead
-        if( dep.requested.group == 'net.sourceforge.findbugs' && dep.requested.module == 'annotations' ) {
-          dep.useTarget group: 'com.github.stephenc.findbugs', name: 'findbugs-annotations', version: '1.3.9-1'
-        }
-      }
-    }
-  }
-}
diff --git a/libraries/alarm/build.gradle b/libraries/alarm/build.gradle
index 72f0fb1..fcd7f53 100644
--- a/libraries/alarm/build.gradle
+++ b/libraries/alarm/build.gradle
@@ -1,31 +1,35 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Alarm Library provides industrial automation style alarm point workflow semantics."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - Alarm - APi" }}
+description = "Apache Polygene™ Alarm Library provides industrial automation style alarm point workflow semantics."
+
+jar { manifest { name = "Apache Polygene™ Library - Alarm - APi" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
+  api polygene.core.bootstrap
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
+  runtimeOnly polygene.core.runtime
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/libraries/alarm/dev-status.xml b/libraries/alarm/dev-status.xml
index f754146..c65f229 100644
--- a/libraries/alarm/dev-status.xml
+++ b/libraries/alarm/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/alarm/src/docs/alarm.txt b/libraries/alarm/src/docs/alarm.txt
index c0c7a59..372adb2 100644
--- a/libraries/alarm/src/docs/alarm.txt
+++ b/libraries/alarm/src/docs/alarm.txt
@@ -1,16 +1,19 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
+ *  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
  *
- * Licensed 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.
+ *       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.
 //////////////////////
 
 [[library-alarm, Alarm Library]]
@@ -34,7 +37,7 @@
 world of today, where _Alarm Points_ allows for fine-grained notification and view into the health of one or more
 systems.
 
-In Zest, we are building upon this powerful abstraction, from decades of field experience.
+In Polygene, we are building upon this powerful abstraction, from decades of field experience.
 
 include::../../build/docs/buildinfo/artifact.txt[]
 
@@ -73,12 +76,12 @@
 
 [snippet,java]
 --------------
-source=libraries/alarm/src/test/java/org/qi4j/library/alarm/AlarmProxyTest.java
+source=libraries/alarm/src/test/java/org/apache/polygene/library/alarm/AlarmProxyTest.java
 tag=documentation
 --------------
 
 == Alarm Models ==
-The Zest™ Alarm library comes with 3 _Alarm Models_ which should be sufficient for most uses. These are based on decades
+The Polygene™ Alarm library comes with 3 _Alarm Models_ which should be sufficient for most uses. These are based on decades
 of experience from the industrial automation industry and user feedback.
 
 == Simple Alarm Model ==
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmCategory.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmCategory.java
new file mode 100644
index 0000000..e3dd78a
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmCategory.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.alarm;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * AlarmCategory is intended to be sub-interfaced, to create an explicit type for the domain where it is used.
+ * <p>
+ * AlarmCategory is used to provide a categorization of Alarms for grouping purposes, which in turn can drive
+ * {@link AlarmEvent} forwarding routed by category. Category can be extended to contain additional state, which
+ * will be associated with the AlarmPoint and related events.
+ * </p>
+ */
+public interface AlarmCategory extends ValueComposite
+{
+    Property<String> name();
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmClass.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmClass.java
new file mode 100644
index 0000000..9ef0c51
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmClass.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.library.alarm;
+
+/** AlarmClass is required attribute for Alarms, to indicate the urgency of the AlarmPoint.
+ *
+ */
+public enum AlarmClass
+{
+    /**
+     * A-alarms requires immediate attention, no matter time of day or day of year. In the enterprise world, they
+     * indicate issue with mission-critical, 24/7, functions.
+     */
+    A,
+
+    /** B-alarms require attention during working hours.
+     *
+     */
+    B,
+
+    /** C-alarm indicate things that needs to be attended to during regular maintenance cycles or when spare time is
+     * available.
+     */
+    C,
+
+    /** D-alarms are used for notifications that indicates smaller issues, or things that can not be dealt with
+     * by humans and will self-correct over time. They are also used to produce events for general notifications
+     * that are informative in nature, such as reports.
+     */
+    D
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmEvent.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmEvent.java
new file mode 100644
index 0000000..89e7006
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmEvent.java
@@ -0,0 +1,122 @@
+/*
+ *  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.polygene.library.alarm;
+
+import java.time.Instant;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceComposite;
+
+/**
+ * Event for indicating change of AlarmStatus of an AlarmPoint.
+ *
+ * @author Niclas Hedhman
+ */
+@Mixins( AlarmEvent.Mixin.class )
+public interface AlarmEvent
+    extends HasIdentity
+{
+    /**
+     * Returns the reference of the AlarmPoint that generated the event.
+     *
+     * @return the AlarmPoint causing this event.
+     */
+    Property<Identity> identity();
+
+    /**
+     * Returns the AlarmStatus prior to the Event.
+     *
+     * @return the old AlarmStatus prior to this event.
+     */
+    Property<AlarmStatus> oldStatus();
+
+    /**
+     * Returns the AlarmStatus after the Event.
+     *
+     * @return the new AlarmStatus of the AlarmPoint after this event.
+     */
+    Property<AlarmStatus> newStatus();
+
+    /**
+     * Returns the Time when the event occurred.
+     *
+     * @return the timestamp when this event occurred.
+     */
+    Property<Instant> eventTime();
+
+    /**
+     * Returns the Name of the event.
+     * This normally returns the human readable name of the Event, such as
+     * activate, deactivate and acknowledge, in the default locale.
+     *
+     * @return the name of this event in the default locale.
+     */
+    Property<String> systemName();
+
+    /**
+     * Returns the Name of the event.
+     * This normally returns the human readable name of the Event, such as
+     * activate, deactivate and acknowledge, in the given locale.
+     *
+     * @param locale the locale that the name should be returned in.
+     *
+     * @return the name of the event in the given locale.
+     */
+    String name( Locale locale );
+
+    /**
+     * Returns a Description of the event in the specified locale.
+     * This normally returns a brief description of the event type, but could/should
+     * allow for AlarmPoint specific descriptions for humans to be better informed.
+     *
+     * @param locale the locale that the description should be returned in.
+     *
+     * @return the description of the event in the given locale.
+     */
+    String description( Locale locale );
+
+    abstract class Mixin
+        implements AlarmEvent
+    {
+        @Service
+        private AlarmModel model;
+
+        @Override
+        public String name( Locale locale )
+        {
+            ResourceBundle bundle = ResourceBundle.getBundle( ((ServiceComposite) model).identity().get().toString(), locale );
+            return bundle.getString( systemName().get() );
+        }
+
+        @Override
+        public String description( Locale locale )
+        {
+            ResourceBundle bundle = ResourceBundle.getBundle( ((ServiceComposite) model).identity().get().toString(), locale );
+            String eventDescriptionId = "EVENT_" + systemName().get().toUpperCase() + "_DESCRIPTION";
+            return bundle.getString( eventDescriptionId );
+        }
+    }
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmHistory.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmHistory.java
new file mode 100644
index 0000000..6e10975
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmHistory.java
@@ -0,0 +1,269 @@
+/*
+ *  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.polygene.library.alarm;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * History of an AlarmPoint.
+ * AlarmPoint system <i>should</i> implement <code>AlarmHistory</code> classes to
+ * record the events of an <code>AlarmPoint</code>.
+ *
+ */
+@Mixins( AlarmHistory.AlarmHistoryMixin.class )
+public interface AlarmHistory
+{
+
+    /**
+     * Returns the newest recorded <code>AlarmEvent</code>.
+     *
+     * @return the last AlarmEvent in the buffer. This is the newest event.
+     */
+    AlarmEvent lastEvent();
+
+    /**
+     * Returns the oldest recorded <code>AlarmEvent</code>.
+     *
+     * @return the first AlarmEvent in the buffer. This is the oldest event.
+     */
+    AlarmEvent firstEvent();
+
+    /**
+     * Returns the recorded <code>AlarmEvent</code> at the given position
+     * in the buffer.
+     *
+     * @param position the position in the buffer, counted from the beginning to obtain the AlarmEvent from.
+     *                 0 means the first element.
+     *
+     * @return the recorded <code>AlarmEvent</code> at the given position in the buffer.
+     */
+    AlarmEvent eventAt( int position );
+
+    /**
+     * Returns the recorded <code>AlarmEvent</code> at the given position
+     * in the buffer counted from the end.
+     *
+     * @param position the position in the buffer, counted from the end to obtain the AlarmEvent from.
+     *                 0 means the last element.
+     *
+     * @return the recorded <code>AlarmEvent</code> at the given position in the buffer counted from the end.
+     */
+    AlarmEvent eventAtEnd( int position );
+
+    /**
+     * Returns a <code>java.util.List</code> of all recorded <code>AlarmEvents</code>.
+     *
+     * @return a <code>java.util.List</code> of all recorded <code>AlarmEvents</code>.
+     */
+    @UseDefaults
+    Property<List<AlarmEvent>> allAlarmEvents();
+
+    /**
+     * The maximum size of the history buffer.
+     * If the sizes shrinks, the oldest <code>AlarmEvents</code> should be removed
+     * so that the number of stored events are equal to the new <i>MaxSize</i>.
+     *
+     * @return The maxSize Property instance.
+     */
+    @UseDefaults
+    Property<Integer> maxSize();
+
+    /**
+     * Returns all the Counters of triggers.
+     * Each time the <code>trigger()</code> method is called,
+     * a Counter is incremented. That means that after the first
+     * time the following the sequence is called
+     * <pre>
+     * <code>activate();
+     * acknowledge();
+     * deactivate();
+     * </code></pre>, the Map contains
+     * <table summary="Triggers">
+     * <tr><td>(String) activate</td><td>(Integer) 1</td></tr>
+     * <tr><td>(String) deactivate</td><td>(Integer) 1</td></tr>
+     * <tr><td>(String) acknowledge</td><td>(Integer) 1</td></tr>
+     * </table>
+     *
+     * @return all the Counters of triggers.
+     */
+    @UseDefaults
+    Property<Map<String, Integer>> counters();
+
+    /**
+     * Resets all counters.
+     */
+    void resetAllCounters();
+
+    /**
+     * Returns the Counter of activate triggers.
+     * This method will return the number of times the
+     * <code>activate()</code> method and the <code>trigger()</code>
+     * method with an activate trigger is called.
+     *
+     * @return the Counter of activate triggers.
+     */
+    int activateCounter();
+
+    /**
+     * Resets the Activate counter.
+     */
+    void resetActivateCounter();
+
+    void addEvent( AlarmEvent event, String trigger );
+
+    abstract class AlarmHistoryMixin
+        implements AlarmHistory
+    {
+        @Override
+        public AlarmEvent firstEvent()
+        {
+            List<AlarmEvent> eventList = allAlarmEvents().get();
+            if( eventList.isEmpty() )
+            {
+                return null;
+            }
+            return eventList.get( 0 );
+        }
+
+        @Override
+        public AlarmEvent lastEvent()
+        {
+            List<AlarmEvent> eventList = allAlarmEvents().get();
+            if( eventList.isEmpty() )
+            {
+                return null;
+            }
+            return eventList.get( eventList.size() - 1 );
+        }
+
+        @Override
+        public AlarmEvent eventAt( final int position )
+        {
+            List<AlarmEvent> eventList = allAlarmEvents().get();
+            if( eventList.size() <= position || position < 0 )
+            {
+                return null;
+            }
+            return eventList.get( position );
+        }
+
+        @Override
+        public AlarmEvent eventAtEnd( final int position )
+        {
+            List<AlarmEvent> eventList = allAlarmEvents().get();
+            int size = eventList.size();
+            if( size <= position || position < 0 )
+            {
+                return null;
+            }
+            return eventList.get( size - position - 1 );
+        }
+
+        @Override
+        public void addEvent( AlarmEvent event, String trigger )
+        {
+            List<AlarmEvent> eventList = allAlarmEvents().get();
+            eventList.add( event );
+            purge();
+            allAlarmEvents().set( eventList );
+            Map<String, Integer> counters = counters().get();
+            Integer counter = counters.get( trigger );
+            if( counter == null )
+            {
+                counter = 1;
+            }
+            else
+            {
+                counter = counter + 1;
+            }
+            counters.put( trigger, counter );
+            counters().set( counters );
+        }
+
+        @Override
+        public String toString()
+        {
+            StringBuilder buf = new StringBuilder();
+            buf.append( "history[maxsize=" );
+            buf.append( maxSize().get() );
+            buf.append( ", size=" );
+            buf.append( allAlarmEvents().get().size() );
+
+            for( Map.Entry<String, Integer> entry : counters().get().entrySet() )
+            {
+                String type = entry.getKey();
+                Integer counts = entry.getValue();
+                buf.append( ", " );
+                buf.append( type );
+                buf.append( "=" );
+                buf.append( counts );
+            }
+            buf.append( "]" );
+            return buf.toString();
+        }
+
+        private void purge()
+        {
+            List<AlarmEvent> eventList = allAlarmEvents().get();
+            Integer maxSize = maxSize().get();
+            if( maxSize <= 0 )
+            {
+                eventList.clear();
+            }
+
+            while( eventList.size() > maxSize )
+            {
+                eventList.remove( 0 );
+            }
+        }
+
+        @Override
+        public void resetAllCounters()
+        {
+            Map<String, Integer> counters = counters().get();
+            counters.clear();
+            counters().set(counters);
+        }
+
+        @Override
+        public int activateCounter()
+        {
+            Integer counter = counters().get().get( AlarmPoint.TRIGGER_ACTIVATE );
+            if( counter == null )
+            {
+                return 0;
+            }
+            return counter;
+        }
+
+        @Override
+        public void resetActivateCounter()
+        {
+            Map<String, Integer> counters = counters().get();
+            counters.remove( AlarmPoint.TRIGGER_ACTIVATE );
+            counters().set( counters );
+        }
+    }
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmListener.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmListener.java
new file mode 100644
index 0000000..93a6bb5
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmListener.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.alarm;
+
+/**
+ * Listener for AlarmEvents.
+ * <code>AlarmPoint</code> classes will fire an <code>AlarmEvent</code> whenever
+ * its <code>AlarmStatus</code> is altered.
+ * <p><strong>Note:</strong>Since <code>AlarmStatus</code> of an <code>AlarmPoint</code>
+ * may change <i>implicitly</i>, e.g. without proper execution of tha Java
+ * Virtual Machine, there are situations when the sequence of <i>old state</i>
+ * and <i>new state</i> in <code>AlarmEvents</code> will not match.
+ *
+ * @author Niclas Hedhman
+ */
+public interface AlarmListener
+{
+
+    /**
+     * Method signature of the AlarmListener.
+     *
+     * @param event the event being fired.
+     */
+    void alarmFired( AlarmEvent event );
+}
+
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmModel.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmModel.java
new file mode 100644
index 0000000..6a05631
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmModel.java
@@ -0,0 +1,133 @@
+/*
+ *  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.polygene.library.alarm;
+
+import java.util.List;
+import java.util.Locale;
+import org.apache.polygene.api.common.Optional;
+
+/**
+ * Definition of the behaviour of the alarm model.
+ * <p>
+ * The AlarmModel is basically the state machine of the AlarmPoint system,
+ * and it is possible to define different <code>AlarmModel</code>s
+ * for each and every alarm. Alarms that are assigned the default
+ * <code>AlarmModel</code> of the <code>AlarmSystem</code> can be
+ * re-assigned another <code>AlarmModel</code> in runtime, just by
+ * changing the default <code>AlarmModel</code> in the
+ * <code>AlarmSystem</code>. Alarms can also change the
+ * <code>AlarmModel</code> by calling the <code>setAlarmModel</code>
+ * in each alarm individually.
+ * </p>
+ *
+ * @see AlarmSystem
+ */
+public interface AlarmModel
+{
+    String MODEL_BUNDLE_NAME = "org.apache.polygene.library.alarm.AlarmResources";
+
+    /**
+     * Execute the required changes upon an AlarmTrigger.
+     * The AlarmSystem calls this method. The AlarmModel must NOT update the AlarmPoint itself, and only return the
+     * resulting event, and the AlarmSystem will update the AlarmStatus accordingly.
+     *
+     * @param alarm   The AlarmPoint the trigger is for.
+     * @param trigger the AlarmTrigger that was used.
+     *
+     * @return An AlarmEvent representing the state change for the given trigger.
+     *
+     * @throws IllegalArgumentException If the trigger given is not supported by this alarm model.
+     */
+    AlarmEvent evaluate( AlarmPoint alarm, String trigger )
+        throws IllegalArgumentException;
+
+    List<String> statusList();
+
+    /**
+     * Returns an array of alarm triggers valid for this AlarmModel.
+     * Alarms are triggered by alarm triggers, which are predefined
+     * java.lang.Strings. The AlarmModel advertise which alarm trigger
+     * strings it supports with this method.
+     *
+     * @return an array of alarm triggers valid for this AlarmModel.
+     */
+    List<String> alarmTriggers();
+
+//    /**
+//     * Adds a new <i>Property</i> to <strong>all</strong> <code>Alarms</code>.
+//     * The <code>defaultvalue</code> will be added to all present and future
+//     * <code>Alarms</code> created through this AlarmModel. In case any existing
+//     * <code>Alarms</code> already have this property defined, the existing value
+//     * should not be overwritten.
+//     *
+//     * @param name         The name of the global property to add.
+//     * @param defaultvalue the default value of the global property.
+//     */
+//    void addProperty( String name, String defaultvalue );
+//
+//    /**
+//     * Removes the <i>Property</i> from all <code>Alarms</code>.
+//     *
+//     * @param name the name of the global property to remove.
+//     */
+//    void removeProperty( String name );
+//
+//    /**
+//     * Returns a <code>java.util.Map</code> of all global default <i>Properties</i>.
+//     *
+//     * @return a <code>java.util.Map</code> of all global default <i>Properties</i>.
+//     */
+//    Map<String,String> defaultProperties();
+
+    String computeTrigger( AlarmStatus status, boolean condition );
+
+    boolean computeCondition( AlarmStatus status );
+
+    /**
+     * Returns the Name of the AlarmModel.
+     * This normally returns the human readable technical name of
+     * the AlarmModel.
+     *
+     * @return The system name of this alarm model.
+     */
+    String modelName();
+
+    /**
+     * Returns a Description of the AlarmModel in the default Locale.
+     * This normally returns a full Description of the AlarmModel in the
+     * default Locale.
+     *
+     * @return the description of the ModelProvider, in the default locale.
+     */
+    String modelDescription();
+
+    /**
+     * Returns a Description of the AlarmModel.
+     * This normally returns a full Description of the AlarmModel in the
+     * Locale. If Locale is <code><b>null</b></code>, then the
+     * default Locale is used.
+     *
+     * @param locale The locale that should be used for the description, or null for the default locale.
+     *
+     * @return The human readable, in the given locale, description of this alarm model.
+     */
+    String modelDescription( @Optional Locale locale );
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmModelDescriptor.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmModelDescriptor.java
new file mode 100644
index 0000000..7d7eebe
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmModelDescriptor.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.alarm;
+
+public class AlarmModelDescriptor
+{
+    private String name;
+
+    private boolean isDefault;
+
+    public AlarmModelDescriptor( String name, boolean aDefault )
+    {
+        this.name = name;
+        isDefault = aDefault;
+    }
+
+    public boolean isDefaultModel()
+    {
+        return isDefault;
+    }
+
+    public String modelName()
+    {
+        return name;
+    }
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmNameFormat.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmNameFormat.java
new file mode 100644
index 0000000..3a65d06
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmNameFormat.java
@@ -0,0 +1,73 @@
+/*
+ *  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.polygene.library.alarm;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+
+/**
+ * The definition of the format of AlarmPoint system names.
+ * <p>
+ * AlarmPoint Names must contain characters. The default is 5 characters but can possibly be overridden. It must also
+ * not only contain white spaces.
+ *
+ *
+ * To override the default minimumLength, specify the <b>minimumLength</b> value in the annotation, such as;
+ * </p>
+ * <pre><code>
+ *
+ * public interface ExpressiveAlarm extends AlarmPoint
+ * {
+ *     &#64;AlarmNameFormat(minimumLength=25)
+ *     Property&lt;String&gt; systemName();
+ * }
+ * </code></pre>
+ * <p>
+ * The obvious downside is that the Property become publicly visible to the users of AlarmPoint.
+ * </p>
+ */
+@ConstraintDeclaration
+@Retention( RetentionPolicy.RUNTIME )
+@Constraints( AlarmNameFormat.AlarmNameConstraint.class )
+public @interface AlarmNameFormat
+{
+    int minimumLength() default 5;
+
+    class AlarmNameConstraint
+        implements Constraint<AlarmNameFormat, String>
+    {
+        @Override
+        public boolean isValid( AlarmNameFormat annotation, String value )
+        {
+            int length = annotation.minimumLength();
+            if( length < 1 )
+            {
+                length = 1;
+            }
+            String trimmed = value.trim();
+            boolean lengthConstraint = trimmed.length() >= length;
+            boolean whiteSpaceConstraint = trimmed.length() > 0;
+            return lengthConstraint && whiteSpaceConstraint;
+        }
+    }
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmPoint.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmPoint.java
new file mode 100644
index 0000000..8b1b7fd
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmPoint.java
@@ -0,0 +1,479 @@
+/*
+ *  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.polygene.library.alarm;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Defines the basic AlarmPoint interface.
+ * <p>
+ * This is the basic interface for the whole AlarmPoint System. The AlarmPoint
+ * is created by calling <code>createAlarm()</code> method in the
+ * <code>AlarmSystem</code> or the <code>AlarmModel</code>.
+ * </p>
+ * <ul>
+ * <li>All alarms carries a set of attributes, runtime extendable.</li>
+ * <li>All alarms can be activated (on), deactivated (off) and acknowledged.</li>
+ * <li>All alarms have an AlarmStatus.</li>
+ * <li>All alarms generates AlarmEvents.</li>
+ * <li>The behaviour of the AlarmPoint is defined by an AlarmModel.</li>
+ * <li>Every AlarmPoint can have its own AlarmModel.</li>
+ * <li>Any number of AlarmStates and AlarmEvents can be defined in an AlarmModel.</li>
+ * </ul>
+ * <p>
+ * Alarms can be triggered by an standard trigger, which are java.lang.Strings.
+ * 3 triggers are pre-defined; <i>activate</i>,<i>deactivate</i> and
+ * <i>acknowledge</i> and must be present in all standard systems and standard impl.
+ * </p>
+ * <p>
+ * The basic usage looks like this;
+ * <pre><code>
+ *     // Creation
+ *     AlarmPoint ala1 = alarmService.createAlarm( "My AlarmPoint" );
+ *       :
+ *       :
+ *     // use
+ *     if( alarmcondition )  // The condition should only detect transitions.
+ *         ala1.trigger( this, "activate" );
+ * </code></pre>
+ * <p>
+ * It is important to know that every call to <code>trigger()</code>
+ * will generate an AlarmEvent, so the <code>trigger()</code> should
+ * only be called when the standard condition changes. For this purpose, there is
+ * a convenience method, that will create/generate the <code>trigger</code>
+ * method calls when a boolean standard condition changes. The usage is fairly
+ * simple.
+ * </p>
+ * <p>
+ * Example;
+ * </p>
+ * <pre><code>
+ *     ala1.updateCondition( value &gt; highlimit );
+ * </code></pre>
+ * <p>
+ * It is possible to mix and match the usage of <code>updateCondition()</code>
+ * and <code>trigger()</code> methods without any concerns.
+ * </p>
+ * <p>
+ * To create alarms with different AlarmModels, other than the
+ * default as shown above, you need to retrieve the AlarmModel that
+ * fulfill the needs required. This can be done in the following manner;
+ * </p>
+ * <pre><code>
+ *     AlarmModel[] impl = alarmService.getAlarmModelsAvailable();
+ *     // selection algorithm
+ *     AlarmPoint ala2 = impl[selected].createAlarm( "My AlarmPoint" );
+ * </code></pre>
+ * <p>
+ * The default AlarmModel can be changed by a call to the
+ * <code>AlarmSystem.setDefaultAlarmModel()</code> and
+ * ALL ALARMS that has the old AlarmModel assigned to it, will be
+ * transferred to the new default AlarmModel. It is important to
+ * understand that this is done irregardless of whether the AlarmPoint was
+ * created from the <code>AlarmSystem.createAlarm()</code> method or
+ * the <code>AlarmModel.createAlarm()</code> method. If distinct different
+ * behaviours are required for certain Alarms, and yet want to allow
+ * users to freely select AlarmModel for all other Alarms, one need
+ * to create two instances of the same AlarmModels, one used solely
+ * for the pre-defined AlarmPoint behaviours, and the others for the rest of
+ * the Alarms.
+ * </p>
+ */
+public interface AlarmPoint extends HasIdentity
+{
+    String STATUS_NORMAL = "Normal";
+    String STATUS_ACTIVATED = "Activated";
+    String STATUS_DEACTIVATED = "Deactivated";
+    String STATUS_REACTIVATED = "Reactivated";
+    String STATUS_ACKNOWLEDGED = "Acknowledged";
+    String STATUS_DISABLED = "Disabled";
+    String STATUS_BLOCKED = "Blocked";
+
+    String EVENT_ENABLING = "enabled";
+    String EVENT_DISABLING = "disabled";
+    String EVENT_BLOCKING = "blocked";
+    String EVENT_UNBLOCKING = "unblocked";
+    String EVENT_ACTIVATION = "activation";
+    String EVENT_DEACTIVATION = "deactivation";
+    String EVENT_ACKNOWLEDGEMENT = "acknowledgement";
+
+    String TRIGGER_ACTIVATE = "activate";
+    String TRIGGER_DEACTIVATE = "deactivate";
+    String TRIGGER_ACKNOWLEDGE = "acknowledge";
+    String TRIGGER_BLOCK = "block";
+    String TRIGGER_UNBLOCK = "unblock";
+    String TRIGGER_ENABLE = "enable";
+    String TRIGGER_DISABLE = "disable";
+
+    /**
+     * Trigger a state change.
+     * <p>
+     * When the AlarmPoint object receives a trigger, it must consult the
+     * AlarmModel and figure out if there is an actual state change
+     * occurring and if any AlarmEvents should be fired.
+     * </p>
+     *
+     * @param trigger The trigger to execute if existing in the AlarmModel.
+     *
+     * @throws IllegalArgumentException if a trigger is not a known one.
+     */
+    void trigger( String trigger )
+        throws IllegalArgumentException;
+
+    /**
+     * Activates an AlarmPoint.
+     * <p>
+     * Convenience method for:
+     * </p>
+     * <pre><code>
+     *       trigger( "activate" );
+     * </code>
+     * </pre>
+     */
+    void activate();
+
+    /**
+     * Deactivates an AlarmPoint.
+     * Convinience method for:<pre>
+     *     trigger( "deactivate" );
+     * </pre>
+     */
+    void deactivate();
+
+    /**
+     * Acknowledges an AlarmPoint.
+     * Convinience method for:<pre>
+     *     trigger( source, "acknowledge" );
+     * </pre>
+     */
+    void acknowledge();
+
+    /**
+     * Get AlarmPoint condition.
+     * To reduce AlarmPoint condition calculations for Implementors, each AlarmPoint should
+     * be able to work with a "true/false" trigger. Only changes to this trigger
+     * will cause an event.
+     *
+     * @return The condition of the AlarmPoint, which is used to simplify trigging of activate and deactivate.
+     */
+    boolean currentCondition();
+
+    /**
+     * Set AlarmPoint condition.
+     * To reduce AlarmPoint condition calculations for Implementors, each AlarmPoint should
+     * be able to work with a "true/false" trigger. Only changes to this trigger
+     * will cause an event.
+     * Causes an Activation or Deactivation if state of condition changes.
+     *
+     * @param condition Sets the AlarmPoint condition.
+     */
+    void updateCondition( boolean condition );
+
+    /**
+     * Returns the current state of the standard.
+     *
+     * @return The AlarmStatus (interface) object
+     */
+    AlarmStatus currentStatus();
+
+    /**
+     * Returns the AlarmHistory of the standard.
+     *
+     * @return The AlarmHistory object, or null if AlarmHistory is not supported.
+     */
+    AlarmHistory history();
+
+    /**
+     * Return all attribute names
+     *
+     * @return the names of the attributes of this AlarmPoint.
+     */
+    List<String> attributeNames();
+
+    /**
+     * Return the attribute of the given name.
+     *
+     * @param name The name of the attribute to return.
+     *
+     * @return the named attribute of this AlarmPoint.
+     */
+    String attribute( String name );
+
+    /**
+     * Sets the attribute of the given name.
+     *
+     * @param name  The name of the attribute to set.
+     * @param value The value to set the named attribute to.
+     */
+    void setAttribute( String name, @Optional String value );
+
+    /**
+     * Returns the Name of the AlarmPoint.
+     * This normally returns the human readable technical name of the AlarmPoint.
+     *
+     * @return the name of the AlarmPoint.
+     */
+    String name();
+
+    /**
+     * Returns a Description of the AlarmPoint.
+     * This normally returns a full Description of the AlarmPoint in the
+     * default Locale.
+     *
+     * @return a human-readable description of the AlarmPoint in the default locale.
+     */
+    String descriptionInDefaultLocale();
+
+    /**
+     * Returns a Description of the AlarmPoint.
+     * This normally returns a full Description of the AlarmPoint in the
+     * Locale. If Locale is <code><b>null</b></code>, then the
+     * default Locale is used.
+     *
+     * @param locale The locale to return the description in, or null to use default locale.
+     *
+     * @return a human-readable description of the AlarmPoint in the given locale.
+     */
+    String description( Locale locale );
+
+    /**
+     * The {@link AlarmClass} of the AlarmPoint.
+     *
+     * The {@link AlarmClass} indicates the urgency of {@link AlarmEvent}s emitted from the AlarmPoint. The property
+     * has {@link UseDefaults} annotation so that the application developer can set the default during assembly.
+     * The default {@link org.apache.polygene.bootstrap.Assembler} in this library defaults alarms to {@link AlarmClass} <b>B</b>.
+     *
+     * @return the property instance that contains the {@link AlarmClass}.
+     */
+    @UseDefaults
+    Property<AlarmClass> alarmClass();
+
+    /**
+     * The {@link AlarmCategory} of this AlarmPoint.
+     *
+     * AlarmCategory is used to group Alarms together, which can be used to forward {@link AlarmEvent} to different
+     * destinations, produce reports for different target audiences or separation of aggregation.
+     *
+     * @return the property instance that contains the {@link AlarmCategory}.
+     */
+    Property<AlarmCategory> category();
+
+    /**
+     * The AlarmState is an internal type, used inside the AlarmPoint for all state that needs to be persisted on disk
+     * and/or transferred across networks.
+     */
+    interface AlarmState
+    {
+        @AlarmNameFormat
+        Property<String> systemName();
+
+        @Optional
+        Property<String> description();
+
+        @UseDefaults
+        Property<Map<String, String>> attributes();
+
+        Property<AlarmStatus> currentStatus();
+    }
+
+    abstract class AlarmPointMixin
+        implements AlarmPoint
+    {
+        @Service
+        private AlarmModel model;
+
+        @Service
+        private AlarmSystem alarmSystem;
+
+        @This
+        private AlarmPoint me;
+
+        @This
+        private AlarmState state;
+
+        @This
+        private AlarmHistory history;
+
+        @Override
+        public void setAttribute( String name, String value )
+        {
+            Map<String, String> properties = state.attributes().get();
+            if( value == null )
+            {
+                properties.remove( name );
+            }
+            else
+            {
+                properties.put( name, value );
+            }
+            state.attributes().set( properties );
+        }
+
+        @Override
+        public String attribute( String name )
+        {
+            return state.attributes().get().get( name );
+        }
+
+        @Override
+        public List<String> attributeNames()
+        {
+            ArrayList<String> result = new ArrayList<>();
+            result.addAll( state.attributes().get().keySet() );
+            return result;
+        }
+
+        private void fireAlarm( AlarmEvent event )
+        {
+            // TODO: Should possibly just be delegated to AlarmSystem
+            for( AlarmListener listener : alarmSystem.alarmListeners() )
+            {
+                try
+                {
+                    listener.alarmFired( event );
+                }
+                catch( Exception e )
+                {
+
+                    // ignore.
+                }
+            }
+        }
+
+        @Override
+        public String toString()
+        {
+            return "AlarmPoint[" + name() + " : " + state.currentStatus().get().name(null)
+                   + "  : " + descriptionInDefaultLocale() + "]";
+        }
+
+        @Override
+        public void trigger( String trigger )
+        {
+            AlarmEvent event;
+            synchronized( this )
+            {
+                event = model.evaluate( me, trigger );
+                if( event == null )
+                {
+                    return;
+                }
+                state.currentStatus().set( event.newStatus().get() );
+                history.addEvent( event, trigger );
+            }
+            fireAlarm( event );
+        }
+
+        @Override
+        public void activate()
+        {
+            trigger( AlarmPoint.TRIGGER_ACTIVATE );
+        }
+
+        @Override
+        public void deactivate()
+        {
+            trigger( AlarmPoint.TRIGGER_DEACTIVATE );
+        }
+
+        @Override
+        public void acknowledge()
+        {
+            trigger( AlarmPoint.TRIGGER_ACKNOWLEDGE );
+        }
+
+        @Override
+        public AlarmHistory history()
+        {
+            return history;
+        }
+
+        @Override
+        public AlarmStatus currentStatus()
+        {
+            return state.currentStatus().get();
+        }
+
+        /**
+         * Returns the Name of the AlarmPoint.
+         * This normally returns the human readable technical name of the AlarmPoint.
+         */
+        @Override
+        public String name()
+        {
+            return state.systemName().get();
+        }
+
+        /**
+         * Returns a Description of the AlarmPoint.
+         * This normally returns a full Description of the AlarmPoint in the
+         * default Locale.
+         */
+        @Override
+        public String descriptionInDefaultLocale()
+        {
+            return description( null );
+        }
+
+        /**
+         * Returns a Description of the AlarmPoint.
+         * This normally returns a full Description of the AlarmPoint in the
+         * Locale. If Locale is <code><b>null</b></code>, then the
+         * default Locale is used.
+         */
+        @Override
+        public String description( Locale locale )
+        {
+            if( locale == null )
+            {
+                locale = Locale.getDefault();
+            }
+            ResourceBundle rb = ResourceBundle.getBundle( "org.apache.polygene.library.alarm.user.AlarmDescriptions", locale );
+            return rb.getString( name() );
+        }
+
+        @Override
+        public void updateCondition( boolean condition )
+        {
+            String trig = model.computeTrigger( state.currentStatus().get(), condition );
+            if( trig != null )
+            {
+                trigger( trig );
+            }
+        }
+
+        @Override
+        public boolean currentCondition()
+        {
+            return model.computeCondition( state.currentStatus().get() );
+        }
+    }
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmPointEntity.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmPointEntity.java
new file mode 100644
index 0000000..531a04b
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmPointEntity.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.library.alarm;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+@Mixins(AlarmPoint.AlarmPointMixin.class)
+public interface AlarmPointEntity extends AlarmPoint
+{
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmPointFactory.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmPointFactory.java
new file mode 100644
index 0000000..1905e2e
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmPointFactory.java
@@ -0,0 +1,77 @@
+/*
+ *  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.polygene.library.alarm;
+
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+@Mixins( AlarmPointFactory.Mixin.class )
+public interface AlarmPointFactory
+{
+    AlarmPoint create(Identity identity, String systemName, String categoryName, AlarmClass alarmClass );
+
+    abstract class Mixin
+        implements AlarmPointFactory
+    {
+
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @Structure
+        private ValueBuilderFactory vbf;
+
+        @Override
+        public AlarmPoint create( Identity identity, String systemName, String categoryName, AlarmClass alarmClass )
+        {
+            UnitOfWork uow = uowf.currentUnitOfWork();
+            EntityBuilder<AlarmPoint> builder = uow.newEntityBuilder( AlarmPoint.class, identity );
+            builder.instance().category().set( createCategory( categoryName ) );
+            builder.instance().alarmClass().set( alarmClass );
+
+            AlarmPoint.AlarmState prototype = builder.instanceFor( AlarmPoint.AlarmState.class );
+            AlarmStatus normal = createNormalAlarmStatus();
+            prototype.systemName().set( systemName );
+            prototype.currentStatus().set( normal );
+
+            return builder.newInstance();
+        }
+
+        private AlarmStatus createNormalAlarmStatus()
+        {
+            ValueBuilder<AlarmStatus> builder = vbf.newValueBuilder( AlarmStatus.class );
+            builder.prototypeFor( AlarmStatus.State.class ).name().set( AlarmPoint.STATUS_NORMAL );
+            return builder.newInstance();
+        }
+
+        private AlarmCategory createCategory( String categoryName )
+        {
+            ValueBuilder<AlarmCategory> builder = vbf.newValueBuilder( AlarmCategory.class );
+            builder.prototype().name().set( categoryName );
+            return builder.newInstance();
+        }
+    }
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmProxy.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmProxy.java
new file mode 100644
index 0000000..3efdb7f
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmProxy.java
@@ -0,0 +1,210 @@
+/*
+ *  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.polygene.library.alarm;
+
+import java.util.List;
+import java.util.Locale;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkConcern;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation;
+
+@Concerns( UnitOfWorkConcern.class )
+@Mixins( AlarmProxy.Mixin.class )
+public interface AlarmProxy extends AlarmPoint
+{
+    @Mixins( FactoryMixin.class )
+    interface Factory extends ServiceComposite
+    {
+        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
+        AlarmProxy create( Identity identity, String systemName, String categoryName, AlarmClass alarmClass );
+    }
+
+    abstract class FactoryMixin
+        implements Factory
+    {
+        @Structure
+        private TransientBuilderFactory tbf;
+
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @Service
+        private AlarmPointFactory factory;
+
+        @Override
+        public AlarmProxy create( Identity identity, String systemName, String categoryName, AlarmClass alarmClass )
+        {
+            UnitOfWork unitOfWork = uowf.currentUnitOfWork();
+            AlarmPoint alarmPoint;
+            try
+            {
+                alarmPoint = unitOfWork.get( AlarmPoint.class, identity );
+            }
+            catch( NoSuchEntityException e )
+            {
+                alarmPoint = factory.create( identity, systemName, categoryName, alarmClass );
+            }
+            TransientBuilder<AlarmProxy> builder = tbf.newTransientBuilder( AlarmProxy.class );
+            builder.prototype().identity().set(identity);
+            builder.prototype().category().set( alarmPoint.category().get() );
+            builder.prototype().alarmClass().set( alarmClass );
+            builder.use( identity );
+            return builder.newInstance();
+        }
+    }
+
+    abstract class Mixin
+        implements AlarmPoint
+    {
+
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @Override
+        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
+        public void trigger( String trigger )
+            throws IllegalArgumentException
+        {
+            AlarmPoint alarmPoint = findAlarmPoint();
+            alarmPoint.trigger( trigger );
+        }
+
+        @Override
+        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
+        public void activate()
+        {
+            AlarmPoint alarmPoint = findAlarmPoint();
+            alarmPoint.activate();
+        }
+
+        @Override
+        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
+        public void deactivate()
+        {
+            AlarmPoint alarmPoint = findAlarmPoint();
+            alarmPoint.deactivate();
+        }
+
+        @Override
+        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
+        public void acknowledge()
+        {
+            AlarmPoint alarmPoint = findAlarmPoint();
+            alarmPoint.acknowledge();
+        }
+
+        @Override
+        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
+        public boolean currentCondition()
+        {
+            AlarmPoint alarmPoint = findAlarmPoint();
+            return alarmPoint.currentCondition();
+        }
+
+        @Override
+        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
+        public void updateCondition( boolean condition )
+        {
+            AlarmPoint alarmPoint = findAlarmPoint();
+            alarmPoint.updateCondition( condition );
+        }
+
+        @Override
+        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
+        public AlarmStatus currentStatus()
+        {
+            AlarmPoint alarmPoint = findAlarmPoint();
+            return alarmPoint.currentStatus();
+        }
+
+        @Override
+        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
+        public AlarmHistory history()
+        {
+            AlarmPoint alarmPoint = findAlarmPoint();
+            return alarmPoint.history();
+        }
+
+        @Override
+        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
+        public List<String> attributeNames()
+        {
+            AlarmPoint alarmPoint = findAlarmPoint();
+            return alarmPoint.attributeNames();
+        }
+
+        @Override
+        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
+        public String attribute( String name )
+        {
+            AlarmPoint alarmPoint = findAlarmPoint();
+            return alarmPoint.attribute( name );
+        }
+
+        @Override
+        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
+        public void setAttribute( String name, @Optional String value )
+        {
+            AlarmPoint alarmPoint = findAlarmPoint();
+            alarmPoint.setAttribute( name, value );
+        }
+
+        @Override
+        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
+        public String name()
+        {
+            AlarmPoint alarmPoint = findAlarmPoint();
+            return alarmPoint.name();
+        }
+
+        @Override
+        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
+        public String descriptionInDefaultLocale()
+        {
+            AlarmPoint alarmPoint = findAlarmPoint();
+            return alarmPoint.descriptionInDefaultLocale();
+        }
+
+        @Override
+        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
+        public String description( Locale locale )
+        {
+            AlarmPoint alarmPoint = findAlarmPoint();
+            return alarmPoint.description( locale );
+        }
+
+        private AlarmPoint findAlarmPoint()
+        {
+            return uowf.currentUnitOfWork().get( AlarmPoint.class, identity().get() );
+        }
+    }
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmStatus.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmStatus.java
new file mode 100644
index 0000000..f10ae23
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmStatus.java
@@ -0,0 +1,107 @@
+/*
+ *  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.polygene.library.alarm;
+
+import java.time.Instant;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Status of an AlarmPoint.
+ *
+ * @author Niclas Hedhman
+ */
+@Mixins( AlarmStatus.AlarmStatusMixin.class )
+public interface AlarmStatus
+{
+
+    /**
+     * Returns the Name of the AlarmStatus in a locale.
+     * This is the technical name of the AlarmStatus, such as Normal,
+     * Activated and so forth in a locale specific form.
+     *
+     * @param locale the locale to return the name in.
+     *
+     * @return the name of the AlarmStatus in the given locale.
+     *
+     * @see State#name()
+     */
+    String name( @Optional Locale locale );
+
+    interface State
+    {
+
+        /**
+         * Returns the Date/Time of when this state was created.
+         *
+         * @return the timestamp of when the state was created.
+         */
+        @Optional
+        Property<Instant> creationDate();
+
+        /**
+         * Returns the Name of the AlarmStatus.
+         * This is the technical name of the AlarmStatus, such as Normal,
+         * Activated and so forth in non-locale specific form.
+         *
+         * @return the name of the AlarmStatus in the default locale.
+         *
+         * @see #name(Locale)
+         */
+        Property<String> name();
+    }
+
+    abstract class AlarmStatusMixin
+        implements AlarmStatus, Initializable
+    {
+        @This
+        private State state;
+
+        @Override
+        public String name( Locale locale )
+        {
+            if( locale == null )
+            {
+                return state.name().get();
+            }
+            ResourceBundle bundle = ResourceBundle.getBundle( "AlarmResources", locale );
+            if( bundle == null )
+            {
+                return state.name().get();
+            }
+            return bundle.getString( state.name().get() );
+        }
+
+        @Override
+        public void initialize()
+        {
+            if( state.creationDate().get() == null )
+            {
+                state.creationDate().set( Instant.now() );
+            }
+        }
+    }
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmSystem.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmSystem.java
new file mode 100644
index 0000000..c205f64
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmSystem.java
@@ -0,0 +1,297 @@
+/*
+ *  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.polygene.library.alarm;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+/**
+ * Defines the AlarmSystem interface.
+ *
+ * <p>
+ * The <code>AlarmSystem</code> is a central registry/handler for all
+ * <code>AlarmPoint</code> objects. By registering <code>AlarmListener</code>s
+ * to the AlarmSystem, objects are able to 'ignore' the fact that there
+ * are many <code>AlarmPoint</code> objects in the system.
+ * </p>
+ * <p>
+ * Also, new attributes registered with the AlarmSystem will propagate into
+ * all existing and future <code>AlarmPoint</code>s, whereas attributes at <code>
+ * AlarmPoint</code> level is individual to an <code>AlarmPoint</code>.
+ * </p>
+ * <p>
+ * Many different AlarmModels can co-exist in the same application.
+ * In fact, every AlarmPoint can have its own AlarmModel, and the AlarmModel
+ * can be changed in runtime, for unrivaled flexibility. However, typically
+ * the AlarmModel is set in the AlarmSystem only, and all Alarms will
+ * use the default model.
+ * </p>
+ * <p>The default alarm model is a service set by during assembly;
+ * </p>
+ * <pre><code>
+ *   public void assemble( ModuleAssembly module )
+ *       throws AssemblyException
+ *   {
+ *       module.addServices( AlarmSystemService.class );
+ *       module.addServices( StandardAlarmModelService.class );
+ *   }
+ * </code></pre>
+ *
+ * @author Niclas Hedhman
+ */
+@Mixins( AlarmSystemService.AlarmSystemMixin.class )
+public interface AlarmSystem
+{
+
+    /**
+     * Returns all the AlarmModels that has been installed.
+     *
+     * @return all the AlarmModels that has been installed.
+     */
+    List<AlarmModelDescriptor> alarmModels();
+
+    /**
+     * Returns the default AlarmModel.
+     *
+     * @return the default AlarmModel in this AlarmSystem.
+     */
+    AlarmModel defaultAlarmModel();
+
+    /**
+     * Returns a list of all Alarms registered to the service.
+     * <p>
+     * The returned Collection may not be modified in any way. The
+     * implementation is free to return a clone, but not required to do
+     * so, and may decide to terminate if the collection is modified.
+     * </p>
+     *
+     * @return a list of all Alarms registered to the service.
+     */
+    Query<AlarmPoint> alarmList();
+
+    /**
+     * Creates an AlarmPoint with the default AlarmModel.
+     *
+     * @param name the name of the AlarmPoint to be created.
+     *
+     * @param category The category the created AlarmPoint should belong to.
+     *
+     * @return the created AlarmPoint with the given name using the default AlarmModel.
+     */
+    AlarmPoint createAlarm( String name, AlarmCategory category );
+
+    /**
+     * Register AlarmListener to recieve <code>AlarmEvents</code> from all
+     * <code>Alarms</code> managed by this <code>AlarmSystem</code>.
+     *
+     * @param listener the global listener to be added.
+     */
+    void addAlarmListener( AlarmListener listener );
+
+    /**
+     * Remove the <code>AlarmListener</code> from the <code>AlarmSystem</code>.
+     *
+     * @param listener the global listener to be removed.
+     */
+    void removeAlarmListener( AlarmListener listener );
+
+    /**
+     * Returns an immmutable list of all AlarmListeners registered to the service.
+     *
+     * @return a list of all AlarmListeners registered to the service.
+     */
+    List<AlarmListener> alarmListeners();
+
+    /**
+     * AlarmSystem implementation.
+     */
+    class AlarmSystemMixin
+        implements AlarmSystem
+    {
+        @Service
+        private Iterable<ServiceReference<AlarmModel>> models;
+
+        private final CopyOnWriteArrayList<AlarmListener> alarmListeners;
+
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @Structure
+        private ValueBuilderFactory vbf;
+
+        @Structure
+        private QueryBuilderFactory qbf;
+
+        public AlarmSystemMixin()
+        {
+            alarmListeners = new CopyOnWriteArrayList<>();
+        }
+
+        /**
+         * Returns all the AlarmModels that has been installed.
+         */
+        @Override
+        public List<AlarmModelDescriptor> alarmModels()
+        {
+            List<AlarmModelDescriptor> descriptors = new ArrayList<>();
+            for( ServiceReference<AlarmModel> model : models )
+            {
+                descriptors.add( model.metaInfo( AlarmModelDescriptor.class ) );
+            }
+            return descriptors;
+        }
+
+        /**
+         * Returns the default AlarmModel.
+         */
+        @Override
+        public AlarmModel defaultAlarmModel()
+        {
+            AlarmModelDescriptor defaultDefault = null;
+            for( AlarmModelDescriptor descriptor : alarmModels() )
+            {
+                if( descriptor.isDefaultModel() )
+                {
+                    return alarmModel( descriptor );
+                }
+                defaultDefault = descriptor;
+            }
+            return alarmModel( defaultDefault );
+        }
+
+        private AlarmModel alarmModel( AlarmModelDescriptor descriptor )
+        {
+            for( ServiceReference<AlarmModel> model : models )
+            {
+                if( model.metaInfo( AlarmModelDescriptor.class ).equals( descriptor ) )
+                {
+                    return model.get();
+                }
+            }
+            return null;
+        }
+
+        /**
+         * Creates an AlarmPoint with the default AlarmModel.
+         * @param name The system name of the AlarmPoint.
+         * @param category The AlarmPoint Category the created alarm should belong to.
+         */
+        @Override
+        public AlarmPoint createAlarm( String name, AlarmCategory category )
+        {
+            UnitOfWork uow = uowf.currentUnitOfWork();
+            EntityBuilder<AlarmPoint> builder = uow.newEntityBuilder( AlarmPoint.class, new StringIdentity( name ) );
+            builder.instance().category().set( category );
+            AlarmPoint.AlarmState state = builder.instanceFor( AlarmPoint.AlarmState.class );
+            state.systemName().set( name );
+            state.currentStatus().set( createStatus( AlarmPoint.STATUS_NORMAL ) );
+            return builder.newInstance();
+        }
+
+        private AlarmStatus createStatus( String status )
+        {
+            ValueBuilder<AlarmStatus> builder = vbf.newValueBuilder( AlarmStatus.class );
+            AlarmStatus.State statePrototype = builder.prototypeFor( AlarmStatus.State.class );
+            statePrototype.name().set( status );
+            statePrototype.creationDate().set( Instant.now() );
+            return builder.newInstance();
+        }
+
+        /**
+         * Register AlarmListener to recieve <code>AlarmEvents</code> from all
+         * <code>Alarms</code> managed by this <code>AlarmSystem</code>.
+         */
+        @Override
+        public void addAlarmListener( AlarmListener listener )
+        {
+            alarmListeners.add( listener );
+        }
+
+        /**
+         * Remove the <code>AlarmListener</code> from the <code>AlarmSystem</code>.
+         */
+        @Override
+        public void removeAlarmListener( AlarmListener listener )
+        {
+            alarmListeners.remove( listener );
+        }
+
+        /**
+         * Returns a list of all Alarms registered to the service.
+         */
+        @Override
+        public Query<AlarmPoint> alarmList()
+        {
+            UnitOfWork uow = uowf.currentUnitOfWork();
+            QueryBuilder<AlarmPoint> builder = qbf.newQueryBuilder( AlarmPoint.class );
+            return uow.newQuery( builder );
+        }
+
+        @Override
+        public List<AlarmListener> alarmListeners()
+        {
+            synchronized( alarmListeners )
+            {
+                return alarmListeners;
+            }
+        }
+
+        public void alarmFired( AlarmEvent event )
+        {
+            Iterator list;
+            //noinspection SynchronizeOnNonFinalField
+            synchronized( alarmListeners )
+            {
+                list = alarmListeners.iterator();
+            }
+            while( list.hasNext() )
+            {
+                AlarmListener listener = (AlarmListener) list.next();
+                try
+                {
+                    listener.alarmFired( event );
+                }
+                catch( Exception e )
+                {
+                    // TODO: Utilize a logger system instead.
+                    System.err.println( "Exception in AlarmListener: " + listener );
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmSystemAssembler.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmSystemAssembler.java
new file mode 100644
index 0000000..8386b52
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmSystemAssembler.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.library.alarm;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+
+public class AlarmSystemAssembler
+    extends Assemblers.VisibilityIdentity<AlarmSystemAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration alarmSystem = module.services( AlarmSystemService.class ).visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            alarmSystem.identifiedBy( identity() );
+        }
+        module.services( SimpleAlarmModelService.class ).setMetaInfo( new AlarmModelDescriptor( "Simple", false ) );
+        module.services( StandardAlarmModelService.class ).setMetaInfo( new AlarmModelDescriptor( "Standard", true ) );
+        module.services( ExtendedAlarmModelService.class ).setMetaInfo( new AlarmModelDescriptor( "Extended", false ) );
+        module.services( AlarmPointFactory.class );
+        module.entities( AlarmPointEntity.class );
+
+        module.values( AlarmEvent.class );
+        module.values( AlarmStatus.class );
+        module.values( AlarmCategory.class );
+        module.values( SimpleAlarmCategory.class );
+
+        module.transients( AlarmProxy.class );
+        module.services( AlarmProxy.Factory.class );
+        module.forMixin( AlarmPoint.class ).declareDefaults().alarmClass().set( AlarmClass.B );
+    }
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmSystemService.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmSystemService.java
new file mode 100644
index 0000000..ee46af2
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/AlarmSystemService.java
@@ -0,0 +1,24 @@
+/*
+ *  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.polygene.library.alarm;
+
+public interface AlarmSystemService extends AlarmSystem
+{
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/ExtendedAlarmModelService.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/ExtendedAlarmModelService.java
new file mode 100644
index 0000000..5c8bfc2
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/ExtendedAlarmModelService.java
@@ -0,0 +1,430 @@
+/*
+ *  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.polygene.library.alarm;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+/**
+ * The Standard Model is centered around the Normal, Activated, Acknowledged
+ * Deactivated, Reactivated, Blocked and Disabled states, and the triggers "activate", "deactivate",
+ * "acknowledge", "block", "unblock", "enable" and "disable". The following matrix details the
+ * resulting grid.
+ * <table summary="Transitions">
+ * <tr><th>Initial State</th><th>Trigger</th><th>Resulting State</th><th>Event Generated</th></tr>
+ * <tr><td>Normal</td><td>activate</td><td>Activated</td><td>activation</td></tr>
+ * <tr><td>Normal</td><td>deactivate</td><td>Normal</td><td>-</td></tr>
+ * <tr><td>Normal</td><td>acknowledge</td><td>Normal</td><td>-</td></tr>
+ * <tr><td>Normal</td><td>block</td><td>Blocked</td><td>block</td></tr>
+ * <tr><td>Normal</td><td>unblock</td><td>Normal</td><td>-</td></tr>
+ * <tr><td>Activated</td><td>activate</td><td>Activated</td><td>-</td></tr>
+ * <tr><td>Activated</td><td>deactivate</td><td>Deactivated</td><td>deactivation</td></tr>
+ * <tr><td>Activated</td><td>acknowledge</td><td>Acknowledged</td><td>acknowledge</td></tr>
+ * <tr><td>Activated</td><td>block</td><td>Blocked</td><td>block</td></tr>
+ * <tr><td>Activated</td><td>unblock</td><td>Activated</td><td>-</td></tr>
+ * <tr><td>Deactivated</td><td>activate</td><td>Activated</td><td>activation</td></tr>
+ * <tr><td>Deactivated</td><td>deactivate</td><td>Deativated</td><td>-</td></tr>
+ * <tr><td>Deactivated</td><td>acknowledge</td><td>Normal</td><td>acknowledge</td></tr>
+ * <tr><td>Deactivated</td><td>block</td><td>Blocked</td><td>block</td></tr>
+ * <tr><td>Deactivated</td><td>unblock</td><td>Deactivated</td><td>-</td></tr>
+ * <tr><td>Acknowledged</td><td>activate</td><td>Acknowledged</td><td>-</td></tr>
+ * <tr><td>Acknowledged</td><td>deactivate</td><td>Normal</td><td>deactivation</td></tr>
+ * <tr><td>Acknowledged</td><td>acknowledge</td><td>Acknowledged</td><td>-</td></tr>
+ * <tr><td>Acknowledged</td><td>block</td><td>Blocked</td><td>block</td></tr>
+ * <tr><td>Acknowledged</td><td>unblock</td><td>Acknowledged</td><td>-</td></tr>
+ * <tr><td>Blocked</td><td>activate</td><td>Blocked</td><td>-</td></tr>
+ * <tr><td>Blocked</td><td>deactivate</td><td>Blocked</td><td>-</td></tr>
+ * <tr><td>Blocked</td><td>acknowledge</td><td>Blocked</td><td>-</td></tr>
+ * <tr><td>Blocked</td><td>block</td><td>Blocked</td><td>-</td></tr>
+ * <tr><td>Blocked</td><td>unblock</td><td>Normal</td><td>unblock</td></tr>
+ * <tr><td>Normal</td><td>disable</td><td>Disabled</td><td>disable</td></tr>
+ * <tr><td>Blocked</td><td>disable</td><td>Disabled</td><td>disable</td></tr>
+ * <tr><td>Deactivated</td><td>disable</td><td>Disabled</td><td>disable</td></tr>
+ * <tr><td>Acknowledged</td><td>disable</td><td>Disabled</td><td>disable</td></tr>
+ * <tr><td>Activated</td><td>disable</td><td>Disabled</td><td>disable</td></tr>
+ * <tr><td>Reactivated</td><td>disable</td><td>Disabled</td><td>disable</td></tr>
+ * <tr><td>Disabled</td><td>disable</td><td>Disabled</td><td>-</td></tr>
+ * <tr><td>Normal</td><td>enable</td><td>Normal</td><td>-</td></tr>
+ * <tr><td>Blocked</td><td>enable</td><td>Blocked</td><td>-</td></tr>
+ * <tr><td>Deactivated</td><td>enable</td><td>Deactivated</td><td>-</td></tr>
+ * <tr><td>Acknowledged</td><td>enable</td><td>Acknowledged</td><td>-</td></tr>
+ * <tr><td>Activated</td><td>enable</td><td>Activated</td><td>-</td></tr>
+ * <tr><td>Reactivated</td><td>enable</td><td>Reactivated</td><td>-</td></tr>
+ * <tr><td>Disabled</td><td>enable</td><td>Normal</td><td>enable</td></tr>
+ * </table>
+ */
+
+@Mixins(ExtendedAlarmModelService.ExtendedAlarmModelMixin.class)
+public interface ExtendedAlarmModelService
+    extends AlarmModel
+{
+    class ExtendedAlarmModelMixin
+        implements AlarmModel
+    {
+        private final static List<String> TRIGGER_LIST;
+
+        private static final List<String> STATUS_LIST;
+
+        @Structure
+        private ValueBuilderFactory vbf;
+
+        static
+        {
+            List<String> list1 = new ArrayList<>();
+            list1.add( AlarmPoint.STATUS_NORMAL );
+            list1.add( AlarmPoint.STATUS_ACTIVATED );
+            list1.add( AlarmPoint.STATUS_DEACTIVATED );
+            list1.add( AlarmPoint.STATUS_ACKNOWLEDGED );
+            list1.add( AlarmPoint.STATUS_REACTIVATED );
+            list1.add( AlarmPoint.STATUS_BLOCKED );
+            list1.add( AlarmPoint.STATUS_DISABLED );
+            STATUS_LIST = Collections.unmodifiableList( list1 );
+
+            List<String> list2 = new ArrayList<>();
+            list2.add( AlarmPoint.TRIGGER_ACTIVATE );
+            list2.add( AlarmPoint.TRIGGER_DEACTIVATE );
+            list2.add( AlarmPoint.TRIGGER_ACKNOWLEDGE );
+            list2.add( AlarmPoint.TRIGGER_BLOCK );
+            list2.add( AlarmPoint.TRIGGER_UNBLOCK );
+            list2.add( AlarmPoint.TRIGGER_DISABLE);
+            list2.add( AlarmPoint.TRIGGER_ENABLE );
+            TRIGGER_LIST = Collections.unmodifiableList( list2 );
+        }
+
+        static ResourceBundle getResourceBundle( Locale locale )
+        {
+            if( locale == null )
+            {
+                locale = Locale.getDefault();
+            }
+            ClassLoader cl = ExtendedAlarmModelMixin.class.getClassLoader();
+            return ResourceBundle.getBundle( MODEL_BUNDLE_NAME, locale, cl );
+        }
+
+        /**
+         * Returns the Name of the AlarmModel.
+         * This normally returns the human readable technical name of
+         * the AlarmModel.
+         *
+         * @return The system name of this alarm model.
+         */
+        @Override
+        public String modelName()
+        {
+            return "org.apache.polygene.library.alarm.model.extended";
+        }
+
+        /**
+         * Returns a Description of the AlarmModel in the default Locale.
+         * This normally returns a full Description of the AlarmModel in the
+         * default Locale.
+         *
+         * @return the description of the ModelProvider, in the default locale.
+         */
+        @Override
+        public String modelDescription()
+        {
+            return modelDescription( null );
+        }
+
+        /**
+         * Returns a Description of the AlarmModel.
+         * This normally returns a full Description of the AlarmModel in the
+         * Locale. If Locale is <code><b>null</b></code>, then the
+         * default Locale is used.
+         *
+         * @param locale The locale that should be used for the description, or null for the default locale.
+         *
+         * @return The human readable, in the given locale, description of this alarm model.
+         */
+        @Override
+        public String modelDescription( Locale locale )
+        {
+            ResourceBundle rb = getResourceBundle( locale );
+            return rb.getString( "MODEL_DESCRIPTION_EXTENDED" );
+        }
+
+        /**
+         * Execute the required changes upon an AlarmTrigger.
+         * The AlarmSystem calls this method, for the AlarmStatus
+         * in the the AlarmPoint to be updated, as well as an AlarmEvent
+         * to be created.
+         *
+         * @param alarm   the AlarmPoint object to be updated.
+         * @param trigger the AlarmTrigger that was used.
+         */
+        @Override
+        public AlarmEvent evaluate( AlarmPoint alarm, String trigger )
+        {
+            if( trigger.equals( AlarmPoint.TRIGGER_ACTIVATE ) )
+            {
+                return activation( alarm );
+            }
+            else if( trigger.equals( AlarmPoint.TRIGGER_DEACTIVATE ) )
+            {
+                return deactivation( alarm );
+            }
+            else if( trigger.equals( AlarmPoint.TRIGGER_ACKNOWLEDGE ) )
+            {
+                return acknowledge( alarm );
+            }
+            else if( trigger.equals( AlarmPoint.TRIGGER_BLOCK ) )
+            {
+                return block( alarm );
+            }
+            else if( trigger.equals( AlarmPoint.TRIGGER_UNBLOCK ) )
+            {
+                return unblock( alarm );
+            }
+            else if( trigger.equals( AlarmPoint.TRIGGER_ENABLE ) )
+            {
+                return enable( alarm );
+            }
+            else if( trigger.equals( AlarmPoint.TRIGGER_DISABLE ) )
+            {
+                return disable( alarm );
+            }
+            else
+            {
+                throw new IllegalArgumentException( "'" + trigger + "' is not supported by this AlarmModel." );
+            }
+        }
+
+        /**
+         * Returns all the supported AlarmPoint triggers.
+         *
+         * @return The AlarmPoint triggers that this AlarmModel supports.
+         */
+        @Override
+        public List<String> alarmTriggers()
+        {
+            return TRIGGER_LIST;
+        }
+
+        @Override
+        public List<String> statusList()
+        {
+            return STATUS_LIST;  //To change body of implemented methods use File | Settings | File Templates.
+        }
+
+        @Override
+        public String computeTrigger( AlarmStatus status, boolean condition )
+        {
+            if( condition )
+            {
+                if( ( status.name(null).equals( AlarmPoint.STATUS_DEACTIVATED ) ) ||
+                    ( status.name(null).equals( AlarmPoint.STATUS_NORMAL ) ) )
+                {
+                    return AlarmPoint.TRIGGER_ACTIVATE;
+                }
+            }
+            else
+            {
+                if( ( status.name(null).equals( AlarmPoint.STATUS_ACTIVATED ) ) ||
+                    ( status.name(null).equals( AlarmPoint.STATUS_REACTIVATED ) ) ||
+                    ( status.name(null).equals( AlarmPoint.STATUS_ACKNOWLEDGED ) ) )
+                {
+                    return AlarmPoint.TRIGGER_DEACTIVATE;
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public boolean computeCondition( AlarmStatus status )
+        {
+            return ( status.name(null).equals( AlarmPoint.STATUS_ACTIVATED ) ) ||
+                   ( status.name(null).equals( AlarmPoint.STATUS_REACTIVATED ) ) ||
+                   ( status.name(null).equals( AlarmPoint.STATUS_ACKNOWLEDGED ) );
+        }
+
+        /**
+         * StateMachine change for activate trigger.
+         *
+         * @param alarm the alarm that is being triggered.
+         *
+         * @return The event to be fired on activation.
+         */
+        private AlarmEvent activation( AlarmPoint alarm )
+        {
+            AlarmStatus status = alarm.currentStatus();
+            if( ( status.name(null).equals( AlarmPoint.STATUS_NORMAL ) ) ||
+                ( status.name(null).equals( AlarmPoint.STATUS_DEACTIVATED ) ) )
+            {
+                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_ACTIVATED );
+                return createEvent( alarm.identity().get(), status, newStatus, AlarmPoint.EVENT_ACTIVATION );
+            }
+            return null;
+        }
+
+        /**
+         * StateMachine change for activate trigger.
+         *
+         * @param alarm the alarm that is being triggered.
+         *
+         * @return The event to be fired on deactivation.
+         */
+        private AlarmEvent deactivation( AlarmPoint alarm )
+        {
+            AlarmStatus status = alarm.currentStatus();
+            if( status.name(null).equals( AlarmPoint.STATUS_ACKNOWLEDGED ) )
+            {
+                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_NORMAL );
+                return createEvent( alarm.identity().get(), status, newStatus, AlarmPoint.EVENT_DEACTIVATION );
+            }
+            else if( status.name(null).equals( AlarmPoint.STATUS_ACTIVATED ) )
+            {
+                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_DEACTIVATED );
+                return createEvent( alarm.identity().get(), status, newStatus, AlarmPoint.EVENT_DEACTIVATION );
+            }
+            return null;
+        }
+
+        /**
+         * StateMachine change for activate trigger.
+         *
+         * @param alarm the alarm that is being triggered.
+         *
+         * @return The event to be fired on acknowledge.
+         */
+        private AlarmEvent acknowledge( AlarmPoint alarm )
+        {
+            AlarmStatus status = alarm.currentStatus();
+            if( status.name(null).equals( AlarmPoint.STATUS_DEACTIVATED ) )
+            {
+                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_NORMAL );
+                return createEvent( alarm.identity().get(), status, newStatus, AlarmPoint.EVENT_ACKNOWLEDGEMENT );
+            }
+            else if( status.name(null).equals( AlarmPoint.STATUS_ACTIVATED ) )
+            {
+                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_ACKNOWLEDGED );
+                return createEvent( alarm.identity().get(), status, newStatus, AlarmPoint.EVENT_ACKNOWLEDGEMENT );
+            }
+            return null;
+        }
+
+        /**
+         * StateMachine change for block trigger.
+         *
+         * @param alarm the alarm that is being triggered.
+         *
+         * @return The event to be fired on acknowledge.
+         */
+        private AlarmEvent block( AlarmPoint alarm )
+        {
+            AlarmStatus status = alarm.currentStatus();
+            if( status.name(null).equals( AlarmPoint.STATUS_BLOCKED ) ||
+                status.name(null).equals( AlarmPoint.STATUS_DISABLED ) )
+            {
+                return null;
+            }
+            AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_BLOCKED );
+            return createEvent( alarm.identity().get(), status, newStatus, AlarmPoint.EVENT_BLOCKING );
+        }
+
+        /**
+         * StateMachine change for unblock trigger.
+         *
+         * @param alarm the alarm that is being triggered.
+         *
+         * @return The event to be fired on acknowledge.
+         */
+        private AlarmEvent unblock( AlarmPoint alarm )
+        {
+            AlarmStatus status = alarm.currentStatus();
+            if( status.name(null).equals( AlarmPoint.STATUS_BLOCKED ) )
+            {
+                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_NORMAL );
+                return createEvent( alarm.identity().get(), status, newStatus, AlarmPoint.EVENT_UNBLOCKING );
+            }
+            return null;
+        }
+
+        /**
+         * StateMachine change for disable trigger.
+         *
+         * @param alarm the alarm that is being triggered.
+         *
+         * @return The event to be fired on acknowledge.
+         */
+        private AlarmEvent disable( AlarmPoint alarm )
+        {
+            AlarmStatus status = alarm.currentStatus();
+            if( status.name(null).equals( AlarmPoint.STATUS_DISABLED ) )
+            {
+                return null;
+            }
+            AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_DISABLED );
+            return createEvent( alarm.identity().get() , status, newStatus, AlarmPoint.EVENT_DISABLING );
+        }
+
+        /**
+         * StateMachine change for unblock trigger.
+         *
+         * @param alarm the alarm that is being triggered.
+         *
+         * @return The event to be fired on acknowledge.
+         */
+        private AlarmEvent enable( AlarmPoint alarm )
+        {
+            AlarmStatus status = alarm.currentStatus();
+            if( status.name(null).equals( AlarmPoint.STATUS_DISABLED ) )
+            {
+                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_NORMAL );
+                return createEvent( ( alarm.identity().get() ), status, newStatus, AlarmPoint.EVENT_ENABLING );
+            }
+            return null;
+        }
+
+        private AlarmStatus createStatus( String status )
+        {
+            ValueBuilder<AlarmStatus> builder = vbf.newValueBuilder( AlarmStatus.class );
+            AlarmStatus.State prototype = builder.prototypeFor(AlarmStatus.State.class);
+            prototype.name().set( status );
+            prototype.creationDate().set( Instant.now() );
+            return builder.newInstance();
+        }
+
+        private AlarmEvent createEvent( Identity alarmId,
+                                        AlarmStatus oldStatus,
+                                        AlarmStatus newStatus,
+                                        String eventSystemName
+        )
+        {
+            ValueBuilder<AlarmEvent> builder = vbf.newValueBuilder( AlarmEvent.class );
+            AlarmEvent prototype = builder.prototype();
+            prototype.identity().set( alarmId );
+            prototype.eventTime().set( Instant.now() );
+            prototype.newStatus().set( newStatus );
+            prototype.oldStatus().set( oldStatus );
+            prototype.systemName().set( eventSystemName );
+            return builder.newInstance();
+        }
+    }
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/SimpleAlarmCategory.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/SimpleAlarmCategory.java
new file mode 100644
index 0000000..26a8c0d
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/SimpleAlarmCategory.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.alarm;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * The SimpleAlarmCategory only defines an optional Description property, and is provided more as an example
+ * of how {@link AlarmCategory} may be extended.
+ *
+ * Note that this {@link AlarmCategory} is registered in the default {@link org.apache.polygene.bootstrap.Assembler} with a
+ * Layer {@link org.apache.polygene.api.common.Visibility}, so if you subtype this, it is likely you need to create your own
+ * {@link org.apache.polygene.bootstrap.Assembler}
+ */
+public interface SimpleAlarmCategory
+    extends AlarmCategory
+{
+
+    @Optional
+    Property<String> description();
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/SimpleAlarmModelService.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/SimpleAlarmModelService.java
new file mode 100644
index 0000000..3a74108
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/SimpleAlarmModelService.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.polygene.library.alarm;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+@Mixins( SimpleAlarmModelService.SimpleAlarmModelMixin.class)
+public interface SimpleAlarmModelService extends AlarmModel
+{
+    /**
+     * The Simple AlarmPoint Model is centered around the Normal and Activated.
+     * The triggers "activate" and "deactivate". The following matrix details the
+     * resulting grid.
+     * <table summary="Transitions">
+     * <tr><th>Initial State</th><th>Trigger</th><th>Resulting State</th><th>Event Generated</th></tr>
+     * <tr><td>Normal</td><td>activate</td><td>Activated</td><td>activation</td></tr>
+     * <tr><td>Normal</td><td>deactivate</td><td>Normal</td><td>-</td></tr>
+     * <tr><td>Activated</td><td>activate</td><td>Activated</td><td>-</td></tr>
+     * <tr><td>Activated</td><td>deactivate</td><td>Deactivated</td><td>deactivation</td></tr>
+     * </table>
+     */
+    class SimpleAlarmModelMixin
+        implements AlarmModel
+    {
+        private static final List<String> ALARM_TRIGGERS;
+        private static final List<String> ALARM_STATUSES;
+
+        static
+        {
+            List<String> list1 = new ArrayList<>();
+
+            list1.add( AlarmPoint.TRIGGER_ACTIVATE );
+            list1.add( AlarmPoint.TRIGGER_DEACTIVATE );
+            ALARM_TRIGGERS = Collections.unmodifiableList( list1 );
+
+            List<String> list2 = new ArrayList<>();
+            list2.add( AlarmPoint.STATUS_NORMAL );
+            list2.add( AlarmPoint.STATUS_ACTIVATED );
+            ALARM_STATUSES = Collections.unmodifiableList( list2 );
+        }
+
+        @Structure
+        private ValueBuilderFactory vbf;
+
+        static ResourceBundle getResourceBundle( Locale locale )
+        {
+            if( locale == null )
+            {
+                locale = Locale.getDefault();
+            }
+            ClassLoader cl = SimpleAlarmModelMixin.class.getClassLoader();
+            return ResourceBundle.getBundle( MODEL_BUNDLE_NAME, locale, cl );
+        }
+
+
+        /**
+         * Returns the Name of the AlarmModel.
+         * This normally returns the human readable technical name of
+         * the AlarmModel.
+         *
+         * @return The system name of this AlarmPoint Model.
+         */
+        @Override
+        public String modelName()
+        {
+            return "org.apache.polygene.library.alarm.model.simple";
+        }
+
+        /**
+         * Returns a Description of the AlarmModel in the default Locale.
+         * This normally returns a full Description of the AlarmModel in the
+         * default Locale.
+         *
+         * @return the description of the ModelProvider.
+         */
+        @Override
+        public String modelDescription()
+        {
+            return modelDescription( null );
+        }
+
+        /**
+         * Returns a Description of the AlarmModel.
+         * This normally returns a full Description of the AlarmModel in the
+         * Locale. If Locale is <code><b>null</b></code>, then the
+         * default Locale is used.
+         *
+         * @param locale The locale for which the description is wanted.
+         *
+         * @return the description of th
+         */
+        @Override
+        public String modelDescription( Locale locale )
+        {
+            ResourceBundle rb = getResourceBundle( locale );
+            return rb.getString( "MODEL_DESCRIPTION_SIMPLE" );
+        }
+
+        @Override
+        public List<String> statusList()
+        {
+            return ALARM_STATUSES;
+        }
+
+        /**
+         * Execute the required changes upon an AlarmTrigger.
+         * The AlarmSystem calls this method, for the AlarmStatus
+         * in the the AlarmPoint to be updated, as well as an AlarmEvent
+         * to be created.
+         *
+         * @param trigger the AlarmTrigger that was used.
+         */
+        @Override
+        public AlarmEvent evaluate( AlarmPoint alarm, String trigger )
+        {
+            if( trigger.equals( AlarmPoint.TRIGGER_ACTIVATE ) )
+            {
+                return activation( alarm );
+            }
+            else if( trigger.equals( AlarmPoint.TRIGGER_DEACTIVATE ) )
+            {
+                return deactivation( alarm );
+            }
+            else
+            {
+                throw new IllegalArgumentException( "'" + trigger + "' is not supported by this AlarmModel." );
+            }
+        }
+
+        /**
+         * Returns all the supported AlarmPoint triggers.
+         */
+        @Override
+        public List<String> alarmTriggers()
+        {
+            return ALARM_TRIGGERS;
+        }
+
+        @Override
+        public String computeTrigger( AlarmStatus status, boolean condition )
+        {
+            if( condition )
+            {
+                if( AlarmPoint.STATUS_NORMAL.equals( status.name(null) ) )
+                {
+                    return AlarmPoint.TRIGGER_ACTIVATE;
+                }
+            }
+            else
+            {
+                if( AlarmPoint.STATUS_ACTIVATED.equals( status.name(null) ) )
+                {
+                    return AlarmPoint.TRIGGER_DEACTIVATE;
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public boolean computeCondition( AlarmStatus status )
+        {
+            return status.name(null).equals( AlarmPoint.STATUS_ACTIVATED );
+        }
+
+        /**
+         * StateMachine change for activate trigger.
+         *
+         * @param alarm the AlarmPoint that the activation is done on.
+         *
+         * @return the resulting AlarmEvent of the activation, or null if no change.
+         */
+        private AlarmEvent activation( AlarmPoint alarm )
+        {
+            AlarmStatus oldStatus = alarm.currentStatus();
+            if( oldStatus.name(null).equals( AlarmPoint.STATUS_NORMAL ) )
+            {
+                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_ACTIVATED );
+                return createEvent( alarm.identity().get(), oldStatus, newStatus, AlarmPoint.EVENT_ACTIVATION );
+            }
+            return null;
+        }
+
+        /**
+         * StateMachine change for activate trigger.
+         *
+         * @param alarm the alarm that is causing the activation.
+         *
+         * @return the resulting AlarmEvent of the activation.
+         */
+        private AlarmEvent deactivation( AlarmPoint alarm )
+        {
+            AlarmStatus oldStatus = alarm.currentStatus();
+            if( oldStatus.name(null).equals( AlarmPoint.STATUS_ACTIVATED ) )
+            {
+                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_NORMAL );
+                return createEvent( alarm.identity().get(), oldStatus, newStatus, AlarmPoint.EVENT_DEACTIVATION );
+            }
+            return null;
+        }
+
+        private AlarmStatus createStatus( String status )
+        {
+            ValueBuilder<AlarmStatus> builder = vbf.newValueBuilder( AlarmStatus.class );
+            AlarmStatus.State prototype = builder.prototypeFor(AlarmStatus.State.class);
+            prototype.name().set( status );
+            prototype.creationDate().set( Instant.now() );
+            return builder.newInstance();
+        }
+
+        private AlarmEvent createEvent( Identity alarmId,
+                                        AlarmStatus oldStatus,
+                                        AlarmStatus newStatus, String eventSystemName
+        )
+        {
+            ValueBuilder<AlarmEvent> builder = vbf.newValueBuilder( AlarmEvent.class );
+            AlarmEvent prototype = builder.prototype();
+            prototype.identity().set( alarmId );
+            prototype.eventTime().set( Instant.now() );
+            prototype.newStatus().set( newStatus );
+            prototype.oldStatus().set( oldStatus );
+            prototype.systemName().set( eventSystemName );
+            return builder.newInstance();
+        }
+    }
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/StandardAlarmModelService.java b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/StandardAlarmModelService.java
new file mode 100644
index 0000000..98258ad
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/StandardAlarmModelService.java
@@ -0,0 +1,298 @@
+/*
+ *  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.polygene.library.alarm;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+/**
+ * The Standard AlarmPoint Model is centered around the Normal, Activated, Acknowledged
+ * and Deactivated states, and the triggers "activate", "deactivate",
+ * and "acknowledge".
+ * <p>
+ * The following matrix details the resulting grid.
+ * </p>
+ * <table summary="Transitions">
+ * <tr><th>Initial State</th><th>Trigger</th><th>Resulting State</th><th>Event Generated</th></tr>
+ * <tr><td>Normal</td><td>activate</td><td>Activated</td><td>activation</td></tr>
+ * <tr><td>Normal</td><td>deactivate</td><td>Normal</td><td>-</td></tr>
+ * <tr><td>Normal</td><td>acknowledge</td><td>Normal</td><td>-</td></tr>
+ * <tr><td>Activated</td><td>activate</td><td>Activated</td><td>-</td></tr>
+ * <tr><td>Activated</td><td>deactivate</td><td>Deactivated</td><td>deactivation</td></tr>
+ * <tr><td>Activated</td><td>acknowledge</td><td>Acknowledged</td><td>acknowledge</td></tr>
+ * <tr><td>Deactivated</td><td>activate</td><td>Activated</td><td>activation</td></tr>
+ * <tr><td>Deactivated</td><td>deactivate</td><td>Deativated</td><td>-</td></tr>
+ * <tr><td>Deactivated</td><td>acknowledge</td><td>Normal</td><td>acknowledge</td></tr>
+ * <tr><td>Acknowledged</td><td>activate</td><td>Acknowledged</td><td>-</td></tr>
+ * <tr><td>Acknowledged</td><td>deactivate</td><td>Normal</td><td>deactivation</td></tr>
+ * <tr><td>Acknowledged</td><td>acknowledge</td><td>Acknowledged</td><td>-</td></tr>
+ * </table>
+ */
+
+@Mixins( StandardAlarmModelService.StandardAlarmModelMixin.class )
+public interface StandardAlarmModelService extends AlarmModel
+{
+    class StandardAlarmModelMixin
+        implements AlarmModel
+    {
+        private static final List<String> TRIGGER_LIST;
+
+        private static final List<String> STATUS_LIST;
+
+        static
+        {
+            List<String> list1 = new ArrayList<>();
+            list1.add( AlarmPoint.STATUS_NORMAL );
+            list1.add( AlarmPoint.STATUS_ACTIVATED );
+            list1.add( AlarmPoint.STATUS_DEACTIVATED );
+            list1.add( AlarmPoint.STATUS_ACKNOWLEDGED );
+            STATUS_LIST = Collections.unmodifiableList( list1 );
+
+            List<String> list2 = new ArrayList<>();
+            list2.add( AlarmPoint.TRIGGER_ACTIVATE );
+            list2.add( AlarmPoint.TRIGGER_DEACTIVATE );
+            list2.add( AlarmPoint.TRIGGER_ACKNOWLEDGE );
+            TRIGGER_LIST = Collections.unmodifiableList( list2 );
+        }
+
+        @Structure
+        private ValueBuilderFactory vbf;
+
+        static ResourceBundle getResourceBundle( Locale locale )
+        {
+            if( locale == null )
+            {
+                locale = Locale.getDefault();
+            }
+            ClassLoader cl = StandardAlarmModelMixin.class.getClassLoader();
+            return ResourceBundle.getBundle( MODEL_BUNDLE_NAME, locale, cl );
+        }
+
+        /**
+         * Returns the Name of the AlarmModel.
+         * This normally returns the human readable technical name of
+         * the AlarmModel.
+         */
+        @Override
+        public String modelName()
+        {
+            return "org.apache.polygene.library.alarm.model.standard";
+        }
+
+        /**
+         * Returns a Description of the AlarmModel in the default Locale.
+         * This normally returns a full Description of the AlarmModel in the
+         * default Locale.
+         *
+         * @return the description of the ModelProvider.
+         */
+        @Override
+        public String modelDescription()
+        {
+            return modelDescription( null );
+        }
+
+        /**
+         * Returns a Description of the AlarmModel.
+         * This normally returns a full Description of the AlarmModel in the
+         * Locale. If Locale is <code><b>null</b></code>, then the
+         * default Locale is used.
+         */
+        @Override
+        public String modelDescription( Locale locale )
+        {
+            ResourceBundle rb = getResourceBundle( locale );
+            return rb.getString( "MODEL_DESCRIPTION_STANDARD" );
+        }
+
+        /**
+         * Execute the required changes upon an AlarmTrigger.
+         * The AlarmSystem calls this method, for the AlarmStatus
+         * in the the AlarmPoint to be updated, as well as an AlarmEvent
+         * to be created.
+         *
+         * @param alarm   the AlarmPoint object to be updated.
+         * @param trigger the AlarmTrigger that was used.
+         */
+        @Override
+        public AlarmEvent evaluate( AlarmPoint alarm, String trigger )
+        {
+            if( trigger.equals( AlarmPoint.TRIGGER_ACTIVATE ) )
+            {
+                return activation( alarm );
+            }
+            else if( trigger.equals( AlarmPoint.TRIGGER_DEACTIVATE ) )
+            {
+                return deactivation( alarm );
+            }
+            else if( trigger.equals( AlarmPoint.TRIGGER_ACKNOWLEDGE ) )
+            {
+                return acknowledge( alarm );
+            }
+            else
+            {
+                throw new IllegalArgumentException( "'" + trigger + "' is not supported by this AlarmModel." );
+            }
+        }
+
+        /**
+         * Returns all the supported AlarmPoint triggers.
+         */
+        @Override
+        public List<String> alarmTriggers()
+        {
+            return TRIGGER_LIST;
+        }
+
+        @Override
+        public List<String> statusList()
+        {
+            return STATUS_LIST;
+        }
+
+        @Override
+        public String computeTrigger( AlarmStatus status, boolean condition )
+        {
+            if( condition )
+            {
+                if( ( status.name( null ).equals( AlarmPoint.STATUS_DEACTIVATED ) ) ||
+                    ( status.name( null ).equals( AlarmPoint.STATUS_NORMAL ) ) )
+                {
+                    return AlarmPoint.TRIGGER_ACTIVATE;
+                }
+            }
+            else
+            {
+                if( ( status.name( null ).equals( AlarmPoint.STATUS_ACTIVATED ) ) ||
+                    ( status.name( null ).equals( AlarmPoint.STATUS_ACKNOWLEDGED ) ) )
+                {
+                    return AlarmPoint.TRIGGER_DEACTIVATE;
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public boolean computeCondition( AlarmStatus status )
+        {
+            return ( status.name( null ).equals( AlarmPoint.STATUS_ACTIVATED ) ) ||
+                   ( status.name( null ).equals( AlarmPoint.STATUS_ACKNOWLEDGED ) );
+        }
+
+        /**
+         * StateMachine change for activate trigger.
+         *
+         * @param alarm the alarm that is being triggered.
+         *
+         * @return The event to be fired on activation.
+         */
+        private AlarmEvent activation( AlarmPoint alarm )
+        {
+            AlarmStatus oldStatus = alarm.currentStatus();
+            if( ( oldStatus.name( null ).equals( AlarmPoint.STATUS_NORMAL ) ) ||
+                ( oldStatus.name( null ).equals( AlarmPoint.STATUS_DEACTIVATED ) ) )
+            {
+                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_ACTIVATED );
+                return createEvent( alarm.identity().get(), oldStatus, newStatus, AlarmPoint.EVENT_ACTIVATION );
+            }
+            return null;
+        }
+
+        /**
+         * StateMachine change for activate trigger.
+         *
+         * @param alarm the alarm that is being triggered.
+         *
+         * @return The event to be fired on deactivation.
+         */
+        private AlarmEvent deactivation( AlarmPoint alarm )
+        {
+            AlarmStatus oldStatus = alarm.currentStatus();
+            if( oldStatus.name( null ).equals( AlarmPoint.STATUS_ACKNOWLEDGED ) )
+            {
+                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_NORMAL );
+                return createEvent( alarm.identity().get(), oldStatus, newStatus, AlarmPoint.EVENT_DEACTIVATION );
+            }
+            else if( oldStatus.name( null ).equals( AlarmPoint.STATUS_ACTIVATED ) )
+            {
+                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_DEACTIVATED );
+                return createEvent( alarm.identity().get(), oldStatus, newStatus, AlarmPoint.EVENT_DEACTIVATION );
+            }
+            return null;
+        }
+
+        /**
+         * StateMachine change for activate trigger.
+         *
+         * @param alarm the alarm that is being triggered.
+         *
+         * @return The event to be fired on acknowledge.
+         */
+        private AlarmEvent acknowledge( AlarmPoint alarm )
+        {
+            AlarmStatus oldStatus = alarm.currentStatus();
+            if( oldStatus.name( null ).equals( AlarmPoint.STATUS_DEACTIVATED ) )
+            {
+                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_NORMAL );
+                return createEvent( alarm.identity().get(), oldStatus, newStatus, AlarmPoint.EVENT_ACKNOWLEDGEMENT );
+            }
+            else if( oldStatus.name( null ).equals( AlarmPoint.STATUS_ACTIVATED ) )
+            {
+                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_ACKNOWLEDGED );
+                return createEvent( alarm.identity().get(), oldStatus, newStatus, AlarmPoint.EVENT_ACKNOWLEDGEMENT );
+            }
+            return null;
+        }
+
+        private AlarmStatus createStatus( String status )
+        {
+            ValueBuilder<AlarmStatus> builder = vbf.newValueBuilder( AlarmStatus.class );
+            AlarmStatus.State prototype = builder.prototypeFor( AlarmStatus.State.class );
+            prototype.name().set( status );
+            prototype.creationDate().set( Instant.now() );
+            return builder.newInstance();
+        }
+
+        private AlarmEvent createEvent( Identity alarmId,
+                                        AlarmStatus oldStatus,
+                                        AlarmStatus newStatus,
+                                        String eventSystemName
+        )
+        {
+            ValueBuilder<AlarmEvent> builder = vbf.newValueBuilder( AlarmEvent.class );
+            AlarmEvent prototype = builder.prototype();
+            prototype.identity().set( alarmId );
+            prototype.eventTime().set( Instant.now() );
+            prototype.newStatus().set( newStatus );
+            prototype.oldStatus().set( oldStatus );
+            prototype.systemName().set( eventSystemName );
+            return builder.newInstance();
+        }
+    }
+}
diff --git a/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/package.html b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/package.html
new file mode 100644
index 0000000..826cc9d
--- /dev/null
+++ b/libraries/alarm/src/main/java/org/apache/polygene/library/alarm/package.html
@@ -0,0 +1,122 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
+<html>
+<body>
+<h1>Alarm Systems.</h1>
+
+<p>
+    Alarm Systems are originally used in Industrial Automation and Process Control systems, to monitor the health
+    of external devices and software functions in large scale plants. The semantics in an Alarm system are well-defined
+    and allows for excellent aggregation and overviews, fine-grained workflow of system health issues and
+    rich data sets around any issues.
+</p>
+
+<p>
+    This Alarm System, that is based on Polygene's excellent persistence support, is an attempt at bringing a first-class
+    model from the industrial automation world into the enterprise of large-scale software systems, that nowadays
+    are so large and un-wieldly that log files, syslog and emails can no longer cope with the burden of management
+    needs.
+</p>
+
+<h1>The Conceptual Model</h1>
+
+<p>
+    Although the inner details of an alarm system can be hard to fully understand, the conceptual model is fairly
+    straight forward, and can be described with <i>Alarm</i>,<i>Alarm Trigger</i>, <i>Alarm Status</i> and <i>
+    Alarm Event</i>. The behavior of the Alarm state machine, hence the workflow, is dictated by an <i>Alarm Model</i>.
+</p>
+
+<p>
+    Looking at each of these in greater detail.
+</p>
+
+<h2>Alarm</h2>
+
+<p>
+    An Alarm is a tiny state-machine that tracks the <i>Alarm Status</i> (see below). An Alarm has certain attributes
+    that
+    are always present and custom attributes that are suitable for the domain in which the Alarm is being used. The
+    <i>Alarm Class</i> and <i>Alarm Category</i> are attributes that are always present, together with an <i>Alarm
+    Name</i> and an <i>Alarm Description</i>.
+</p>
+
+<h2>Alarm Class</h2>
+
+<p>
+    There are 4 <i>Alarm Classes</i>, A to D, indicating the urgency if an <i>Alarm Event</i> is occurring on the Alarm.
+</p>
+
+<h2>Alarm Category</h2>
+
+<p>
+    <i>Alarm Category</i> is a required attribute on the Alarm to indicate the target audience that needs to be informed
+    about it. This can be used to differentiate between infrastructure concerns versus domain model issues, or direct
+    <i>Alarm Events</i> to different recipients.
+</p>
+
+<h2>Alarm Model</h2>
+<p>
+    The <i>Alarm Model</i> defines which <i>Alarm Status</i> types, <i>Alarm Event</i> types, <i>Alarm Triggers</i> and
+    the behavior of the state machine in the <i>Alarm</i> itself.
+</p>
+<p>
+    The <i>Alarm Model</i> is an Polygene™ <code>Service</code> and located via the normal <code>Visibility</code> rules,
+    making it possible to have a different <i>Alarm Model</i> in each Polygene™ module.
+</p>
+
+<h2>Alarm Status</h2>
+<p>
+    The <i>Alarm</i> always has an <i>Alarm Status</i>. Most <i>Alarm Models</i> will have a <b>Normal</b> status which
+    the <i>Alarm</i> is set to initially, and <b>Activated</b> is likely to be present as well. The <i>Alarm Status</i>
+    only changes from one status to another through the use of an <i>Alarm Trigger</i>, but all triggers doesn't
+    cause the <i>Alarm Status</i> to change.
+</p>
+<h2>Alarm Event</h2>
+<p>
+    Whenever an <i>Alarm</i> changes its <i>Alarm Status</i> an <i>Alarm Event</i> is sent to all <i>Alarm
+    Listeners</i>. <i>Alarm Listeners</i> are registered to the <i>Alarm System</i>. <i>Alarm Event</i> types are
+    defined by the <i>Alarm Model</i>. Some common <i>Alarm Event</i> types/names are "activation", "acknowledgement"
+    and "deactivation".
+
+</p>
+<h2>Alarm Trigger</h2>
+<p>
+    <i>Alarm Triggers</i> are used to forward the workflow. The <i>Alarm Model</i> defines the available <i>Alarm
+    Triggers</i> which are all plain Strings. <i>Alarm Triggers</i> are "commanding" such as "block", "activate" and
+    "disable".
+</p>
+<h1>State Management</h1>
+<p>
+    <i>Alarm</i> instances are Polygene™ Entities, so the <i>Alarm Status</i> is preserved over time in persisted storage.
+    This in turn means that the <i>Alarm</i> must be accessed within a <code>UnitOfWork</code> and the Alarm is not valid
+    outside the <code>UnitOfWork</code>.
+    </p>
+<p>
+    For Entities that needs Alarms, this is fairly straight forward, by making an
+    <code>@Aggregated Association&lt;Alarm&gt; alarm;</code> and have it being created in the <i>Entity</i>
+    <code>LifeCycle</code>. For non-entities, this becomes a little bit trickier. After the <i>Alarm</i> is created
+    the <code>Identity</code> of the <i>Alarm</i> needs to be preserved and used to retrieve the <i>Alarm</i> when
+    it needs to be <i>Triggered</i>. It is NOT possible to put an <i>Alarm</i> <code>Association</code> in a Service's
+   <code>configuration</code>, since you will not be able to access the <code>Configuration</code> members within the
+    <code>UnitOfWork</code> managed by the configuration system.
+</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmCategory.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmCategory.java
deleted file mode 100644
index d0cb55b..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmCategory.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2011, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.alarm;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * AlarmCategory is intended to be sub-interfaced, to create an explicit type for the domain where it is used.
- * <p>
- * AlarmCategory is used to provide a categorization of Alarms for grouping purposes, which in turn can drive
- * {@link AlarmEvent} forwarding routed by category. Category can be extended to contain additional state, which
- * will be associated with the AlarmPoint and related events.
- * </p>
- */
-public interface AlarmCategory extends ValueComposite
-{
-    Property<String> name();
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmClass.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmClass.java
deleted file mode 100644
index 1ce01c9..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmClass.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2011, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.alarm;
-
-/** AlarmClass is required attribute for Alarms, to indicate the urgency of the AlarmPoint.
- *
- */
-public enum AlarmClass
-{
-    /**
-     * A-alarms requires immediate attention, no matter time of day or day of year. In the enterprise world, they
-     * indicate issue with mission-critical, 24/7, functions.
-     */
-    A,
-
-    /** B-alarms require attention during working hours.
-     *
-     */
-    B,
-
-    /** C-alarm indicate things that needs to be attended to during regular maintenance cycles or when spare time is
-     * available.
-     */
-    C,
-
-    /** D-alarms are used for notifications that indicates smaller issues, or things that can not be dealt with
-     * by humans and will self-correct over time. They are also used to produce events for general notifications
-     * that are informative in nature, such as reports.
-     */
-    D
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmEvent.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmEvent.java
deleted file mode 100644
index 7d6ea26..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmEvent.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright 1996-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import java.util.Date;
-import java.util.Locale;
-import java.util.ResourceBundle;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * Event for indicating change of AlarmStatus of an AlarmPoint.
- *
- * @author Niclas Hedhman
- */
-@Mixins( AlarmEvent.Mixin.class )
-public interface AlarmEvent
-    extends ValueComposite
-{
-    /**
-     * Returns the identity of the AlarmPoint that generated the event.
-     *
-     * @return the AlarmPoint causing this event.
-     */
-    Property<String> alarmIdentity();
-
-    /**
-     * Returns the AlarmStatus prior to the Event.
-     *
-     * @return the old AlarmStatus prior to this event.
-     */
-    Property<AlarmStatus> oldStatus();
-
-    /**
-     * Returns the AlarmStatus after the Event.
-     *
-     * @return the new AlarmStatus of the AlarmPoint after this event.
-     */
-    Property<AlarmStatus> newStatus();
-
-    /**
-     * Returns the Time when the event occurred.
-     *
-     * @return the timestamp when this event occurred.
-     */
-    Property<Date> eventTime();
-
-    /**
-     * Returns the Name of the event.
-     * This normally returns the human readable name of the Event, such as
-     * activate, deactivate and acknowledge, in the default locale.
-     *
-     * @return the name of this event in the default locale.
-     */
-    Property<String> systemName();
-
-    /**
-     * Returns the Name of the event.
-     * This normally returns the human readable name of the Event, such as
-     * activate, deactivate and acknowledge, in the given locale.
-     *
-     * @param locale the locale that the name should be returned in.
-     *
-     * @return the name of the event in the given locale.
-     */
-    String name( Locale locale );
-
-    /**
-     * Returns a Description of the event in the specified locale.
-     * This normally returns a brief description of the event type, but could/should
-     * allow for AlarmPoint specific descriptions for humans to be better informed.
-     *
-     * @param locale the locale that the description should be returned in.
-     *
-     * @return the description of the event in the given locale.
-     */
-    String description( Locale locale );
-
-    abstract class Mixin
-        implements AlarmEvent
-    {
-        @Service
-        private AlarmModel model;
-
-        @Override
-        public String name( Locale locale )
-        {
-            ResourceBundle bundle = ResourceBundle.getBundle( ((ServiceComposite) model).identity().get(), locale );
-            return bundle.getString( systemName().get() );
-        }
-
-        @Override
-        public String description( Locale locale )
-        {
-            ResourceBundle bundle = ResourceBundle.getBundle( ((ServiceComposite) model).identity().get(), locale );
-            String eventDescriptionId = "EVENT_" + systemName().get().toUpperCase() + "_DESCRIPTION";
-            return bundle.getString( eventDescriptionId );
-        }
-    }
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmHistory.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmHistory.java
deleted file mode 100644
index 9aea62e..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmHistory.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright 1996-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-
-/**
- * History of an AlarmPoint.
- * AlarmPoint system <i>should</i> implement <code>AlarmHistory</code> classes to
- * record the events of an <code>AlarmPoint</code>.
- *
- */
-@Mixins( AlarmHistory.AlarmHistoryMixin.class )
-public interface AlarmHistory
-{
-
-    /**
-     * Returns the newest recorded <code>AlarmEvent</code>.
-     *
-     * @return the last AlarmEvent in the buffer. This is the newest event.
-     */
-    AlarmEvent lastEvent();
-
-    /**
-     * Returns the oldest recorded <code>AlarmEvent</code>.
-     *
-     * @return the first AlarmEvent in the buffer. This is the oldest event.
-     */
-    AlarmEvent firstEvent();
-
-    /**
-     * Returns the recorded <code>AlarmEvent</code> at the given position
-     * in the buffer.
-     *
-     * @param position the position in the buffer, counted from the beginning to obtain the AlarmEvent from.
-     *                 0 means the first element.
-     *
-     * @return the recorded <code>AlarmEvent</code> at the given position in the buffer.
-     */
-    AlarmEvent eventAt( int position );
-
-    /**
-     * Returns the recorded <code>AlarmEvent</code> at the given position
-     * in the buffer counted from the end.
-     *
-     * @param position the position in the buffer, counted from the end to obtain the AlarmEvent from.
-     *                 0 means the last element.
-     *
-     * @return the recorded <code>AlarmEvent</code> at the given position in the buffer counted from the end.
-     */
-    AlarmEvent eventAtEnd( int position );
-
-    /**
-     * Returns a <code>java.util.List</code> of all recorded <code>AlarmEvents</code>.
-     *
-     * @return a <code>java.util.List</code> of all recorded <code>AlarmEvents</code>.
-     */
-    @UseDefaults
-    Property<List<AlarmEvent>> allAlarmEvents();
-
-    /**
-     * The maximum size of the history buffer.
-     * If the sizes shrinks, the oldest <code>AlarmEvents</code> should be removed
-     * so that the number of stored events are equal to the new <i>MaxSize</i>.
-     *
-     * @return The maxSize Property instance.
-     */
-    @UseDefaults
-    Property<Integer> maxSize();
-
-    /**
-     * Returns all the Counters of triggers.
-     * Each time the <code>trigger()</code> method is called,
-     * a Counter is incremented. That means that after the first
-     * time the following the sequence is called
-     * <pre>
-     * <code>activate();
-     * acknowledge();
-     * deactivate();
-     * </code></pre>, the Map contains
-     * <table summary="Triggers">
-     * <tr><td>(String) activate</td><td>(Integer) 1</td></tr>
-     * <tr><td>(String) deactivate</td><td>(Integer) 1</td></tr>
-     * <tr><td>(String) acknowledge</td><td>(Integer) 1</td></tr>
-     * </table>
-     *
-     * @return all the Counters of triggers.
-     */
-    @UseDefaults
-    Property<Map<String, Integer>> counters();
-
-    /**
-     * Resets all counters.
-     */
-    void resetAllCounters();
-
-    /**
-     * Returns the Counter of activate triggers.
-     * This method will return the number of times the
-     * <code>activate()</code> method and the <code>trigger()</code>
-     * method with an activate trigger is called.
-     *
-     * @return the Counter of activate triggers.
-     */
-    int activateCounter();
-
-    /**
-     * Resets the Activate counter.
-     */
-    void resetActivateCounter();
-
-    void addEvent( AlarmEvent event, String trigger );
-
-    abstract class AlarmHistoryMixin
-        implements AlarmHistory
-    {
-        @Override
-        public AlarmEvent firstEvent()
-        {
-            List<AlarmEvent> eventList = allAlarmEvents().get();
-            if( eventList.isEmpty() )
-            {
-                return null;
-            }
-            return eventList.get( 0 );
-        }
-
-        @Override
-        public AlarmEvent lastEvent()
-        {
-            List<AlarmEvent> eventList = allAlarmEvents().get();
-            if( eventList.isEmpty() )
-            {
-                return null;
-            }
-            return eventList.get( eventList.size() - 1 );
-        }
-
-        @Override
-        public AlarmEvent eventAt( final int position )
-        {
-            List<AlarmEvent> eventList = allAlarmEvents().get();
-            if( eventList.size() <= position || position < 0 )
-            {
-                return null;
-            }
-            return eventList.get( position );
-        }
-
-        @Override
-        public AlarmEvent eventAtEnd( final int position )
-        {
-            List<AlarmEvent> eventList = allAlarmEvents().get();
-            int size = eventList.size();
-            if( size <= position || position < 0 )
-            {
-                return null;
-            }
-            return eventList.get( size - position - 1 );
-        }
-
-        @Override
-        public void addEvent( AlarmEvent event, String trigger )
-        {
-            List<AlarmEvent> eventList = allAlarmEvents().get();
-            eventList.add( event );
-            purge();
-            allAlarmEvents().set( eventList );
-            Map<String, Integer> counters = counters().get();
-            Integer counter = counters.get( trigger );
-            if( counter == null )
-            {
-                counter = 1;
-            }
-            else
-            {
-                counter = counter + 1;
-            }
-            counters.put( trigger, counter );
-            counters().set( counters );
-        }
-
-        @Override
-        public String toString()
-        {
-            StringBuilder buf = new StringBuilder();
-            buf.append( "history[maxsize=" );
-            buf.append( maxSize().get() );
-            buf.append( ", size=" );
-            buf.append( allAlarmEvents().get().size() );
-
-            for( Map.Entry<String, Integer> entry : counters().get().entrySet() )
-            {
-                String type = entry.getKey();
-                Integer counts = entry.getValue();
-                buf.append( ", " );
-                buf.append( type );
-                buf.append( "=" );
-                buf.append( counts );
-            }
-            buf.append( "]" );
-            return buf.toString();
-        }
-
-        private void purge()
-        {
-            List<AlarmEvent> eventList = allAlarmEvents().get();
-            Integer maxSize = maxSize().get();
-            if( maxSize <= 0 )
-            {
-                eventList.clear();
-            }
-
-            while( eventList.size() > maxSize )
-            {
-                eventList.remove( 0 );
-            }
-        }
-
-        @Override
-        public void resetAllCounters()
-        {
-            Map<String, Integer> counters = counters().get();
-            counters.clear();
-            counters().set(counters);
-        }
-
-        @Override
-        public int activateCounter()
-        {
-            Integer counter = counters().get().get( AlarmPoint.TRIGGER_ACTIVATE );
-            if( counter == null )
-            {
-                return 0;
-            }
-            return counter;
-        }
-
-        @Override
-        public void resetActivateCounter()
-        {
-            Map<String, Integer> counters = counters().get();
-            counters.remove( AlarmPoint.TRIGGER_ACTIVATE );
-            counters().set( counters );
-        }
-    }
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmListener.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmListener.java
deleted file mode 100644
index a18759d..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmListener.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 1996-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-/**
- * Listener for AlarmEvents.
- * <code>AlarmPoint</code> classes will fire an <code>AlarmEvent</code> whenever
- * its <code>AlarmStatus</code> is altered.
- * <p><strong>Note:</strong>Since <code>AlarmStatus</code> of an <code>AlarmPoint</code>
- * may change <i>implicitly</i>, e.g. without proper execution of tha Java
- * Virtual Machine, there are situations when the sequence of <i>old state</i>
- * and <i>new state</i> in <code>AlarmEvents</code> will not match.
- *
- * @author Niclas Hedhman
- */
-public interface AlarmListener
-{
-
-    /**
-     * Method signature of the AlarmListener.
-     *
-     * @param event the event being fired.
-     */
-    void alarmFired( AlarmEvent event );
-}
-
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmModel.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmModel.java
deleted file mode 100644
index 911117d..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmModel.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 1996-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import java.util.List;
-import java.util.Locale;
-import org.qi4j.api.common.Optional;
-
-/**
- * Definition of the behaviour of the alarm model.
- * <p>
- * The AlarmModel is basically the state machine of the AlarmPoint system,
- * and it is possible to define different <code>AlarmModel</code>s
- * for each and every alarm. Alarms that are assigned the default
- * <code>AlarmModel</code> of the <code>AlarmSystem</code> can be
- * re-assigned another <code>AlarmModel</code> in runtime, just by
- * changing the default <code>AlarmModel</code> in the
- * <code>AlarmSystem</code>. Alarms can also change the
- * <code>AlarmModel</code> by calling the <code>setAlarmModel</code>
- * in each alarm individually.
- * </p>
- *
- * @see AlarmSystem
- */
-public interface AlarmModel
-{
-    String MODEL_BUNDLE_NAME = "org.qi4j.library.alarm.AlarmResources";
-
-    /**
-     * Execute the required changes upon an AlarmTrigger.
-     * The AlarmSystem calls this method. The AlarmModel must NOT update the AlarmPoint itself, and only return the
-     * resulting event, and the AlarmSystem will update the AlarmStatus accordingly.
-     *
-     * @param alarm   The AlarmPoint the trigger is for.
-     * @param trigger the AlarmTrigger that was used.
-     *
-     * @return An AlarmEvent representing the state change for the given trigger.
-     *
-     * @throws IllegalArgumentException If the trigger given is not supported by this alarm model.
-     */
-    AlarmEvent evaluate( AlarmPoint alarm, String trigger )
-        throws IllegalArgumentException;
-
-    List<String> statusList();
-
-    /**
-     * Returns an array of alarm triggers valid for this AlarmModel.
-     * Alarms are triggered by alarm triggers, which are predefined
-     * java.lang.Strings. The AlarmModel advertise which alarm trigger
-     * strings it supports with this method.
-     *
-     * @return an array of alarm triggers valid for this AlarmModel.
-     */
-    List<String> alarmTriggers();
-
-//    /**
-//     * Adds a new <i>Property</i> to <strong>all</strong> <code>Alarms</code>.
-//     * The <code>defaultvalue</code> will be added to all present and future
-//     * <code>Alarms</code> created through this AlarmModel. In case any existing
-//     * <code>Alarms</code> already have this property defined, the existing value
-//     * should not be overwritten.
-//     *
-//     * @param name         The name of the global property to add.
-//     * @param defaultvalue the default value of the global property.
-//     */
-//    void addProperty( String name, String defaultvalue );
-//
-//    /**
-//     * Removes the <i>Property</i> from all <code>Alarms</code>.
-//     *
-//     * @param name the name of the global property to remove.
-//     */
-//    void removeProperty( String name );
-//
-//    /**
-//     * Returns a <code>java.util.Map</code> of all global default <i>Properties</i>.
-//     *
-//     * @return a <code>java.util.Map</code> of all global default <i>Properties</i>.
-//     */
-//    Map<String,String> defaultProperties();
-
-    String computeTrigger( AlarmStatus status, boolean condition );
-
-    boolean computeCondition( AlarmStatus status );
-
-    /**
-     * Returns the Name of the AlarmModel.
-     * This normally returns the human readable technical name of
-     * the AlarmModel.
-     *
-     * @return The system name of this alarm model.
-     */
-    String modelName();
-
-    /**
-     * Returns a Description of the AlarmModel in the default Locale.
-     * This normally returns a full Description of the AlarmModel in the
-     * default Locale.
-     *
-     * @return the description of the ModelProvider, in the default locale.
-     */
-    String modelDescription();
-
-    /**
-     * Returns a Description of the AlarmModel.
-     * This normally returns a full Description of the AlarmModel in the
-     * Locale. If Locale is <code><b>null</b></code>, then the
-     * default Locale is used.
-     *
-     * @param locale The locale that should be used for the description, or null for the default locale.
-     *
-     * @return The human readable, in the given locale, description of this alarm model.
-     */
-    String modelDescription( @Optional Locale locale );
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmModelDescriptor.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmModelDescriptor.java
deleted file mode 100644
index 65cd73f..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmModelDescriptor.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 1996-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-public class AlarmModelDescriptor
-{
-    private String name;
-
-    private boolean isDefault;
-
-    public AlarmModelDescriptor( String name, boolean aDefault )
-    {
-        this.name = name;
-        isDefault = aDefault;
-    }
-
-    public boolean isDefaultModel()
-    {
-        return isDefault;
-    }
-
-    public String modelName()
-    {
-        return name;
-    }
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmNameFormat.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmNameFormat.java
deleted file mode 100644
index c37fdc7..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmNameFormat.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 1996-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-
-/**
- * The definition of the format of AlarmPoint system names.
- * <p>
- * AlarmPoint Names must contain characters. The default is 5 characters but can possibly be overridden. It must also
- * not only contain white spaces.
- *
- *
- * To override the default minimumLength, specify the <b>minimumLength</b> value in the annotation, such as;
- * </p>
- * <pre><code>
- *
- * public interface ExpressiveAlarm extends AlarmPoint
- * {
- *     &#64;AlarmNameFormat(minimumLength=25)
- *     Property&lt;String&gt; systemName();
- * }
- * </code></pre>
- * <p>
- * The obvious downside is that the Property become publicly visible to the users of AlarmPoint.
- * </p>
- */
-@ConstraintDeclaration
-@Retention( RetentionPolicy.RUNTIME )
-@Constraints( AlarmNameFormat.AlarmNameConstraint.class )
-public @interface AlarmNameFormat
-{
-    int minimumLength() default 5;
-
-    class AlarmNameConstraint
-        implements Constraint<AlarmNameFormat, String>
-    {
-        @Override
-        public boolean isValid( AlarmNameFormat annotation, String value )
-        {
-            int length = annotation.minimumLength();
-            if( length < 1 )
-            {
-                length = 1;
-            }
-            String trimmed = value.trim();
-            boolean lengthConstraint = trimmed.length() >= length;
-            boolean whiteSpaceConstraint = trimmed.length() > 0;
-            return lengthConstraint && whiteSpaceConstraint;
-        }
-    }
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmPoint.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmPoint.java
deleted file mode 100644
index 81b98fd..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmPoint.java
+++ /dev/null
@@ -1,479 +0,0 @@
-/*
- * Copyright 1996-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.ResourceBundle;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.property.Property;
-
-/**
- * Defines the basic AlarmPoint interface.
- * <p>
- * This is the basic interface for the whole AlarmPoint System. The AlarmPoint
- * is created by calling <code>createAlarm()</code> method in the
- * <code>AlarmSystem</code> or the <code>AlarmModel</code>.
- * </p>
- * <ul>
- * <li>All alarms carries a set of attributes, runtime extendable.</li>
- * <li>All alarms can be activated (on), deactivated (off) and acknowledged.</li>
- * <li>All alarms have an AlarmStatus.</li>
- * <li>All alarms generates AlarmEvents.</li>
- * <li>The behaviour of the AlarmPoint is defined by an AlarmModel.</li>
- * <li>Every AlarmPoint can have its own AlarmModel.</li>
- * <li>Any number of AlarmStates and AlarmEvents can be defined in an AlarmModel.</li>
- * </ul>
- * <p>
- * Alarms can be triggered by an standard trigger, which are java.lang.Strings.
- * 3 triggers are pre-defined; <i>activate</i>,<i>deactivate</i> and
- * <i>acknowledge</i> and must be present in all standard systems and standard impl.
- * </p>
- * <p>
- * The basic usage looks like this;
- * <pre><code>
- *     // Creation
- *     AlarmPoint ala1 = alarmService.createAlarm( "My AlarmPoint" );
- *       :
- *       :
- *     // use
- *     if( alarmcondition )  // The condition should only detect transitions.
- *         ala1.trigger( this, "activate" );
- * </code></pre>
- * <p>
- * It is important to know that every call to <code>trigger()</code>
- * will generate an AlarmEvent, so the <code>trigger()</code> should
- * only be called when the standard condition changes. For this purpose, there is
- * a convenience method, that will create/generate the <code>trigger</code>
- * method calls when a boolean standard condition changes. The usage is fairly
- * simple.
- * </p>
- * <p>
- * Example;
- * </p>
- * <pre><code>
- *     ala1.updateCondition( value &gt; highlimit );
- * </code></pre>
- * <p>
- * It is possible to mix and match the usage of <code>updateCondition()</code>
- * and <code>trigger()</code> methods without any concerns.
- * </p>
- * <p>
- * To create alarms with different AlarmModels, other than the
- * default as shown above, you need to retrieve the AlarmModel that
- * fulfill the needs required. This can be done in the following manner;
- * </p>
- * <pre><code>
- *     AlarmModel[] impl = alarmService.getAlarmModelsAvailable();
- *     // selection algorithm
- *     AlarmPoint ala2 = impl[selected].createAlarm( "My AlarmPoint" );
- * </code></pre>
- * <p>
- * The default AlarmModel can be changed by a call to the
- * <code>AlarmSystem.setDefaultAlarmModel()</code> and
- * ALL ALARMS that has the old AlarmModel assigned to it, will be
- * transferred to the new default AlarmModel. It is important to
- * understand that this is done irregardless of whether the AlarmPoint was
- * created from the <code>AlarmSystem.createAlarm()</code> method or
- * the <code>AlarmModel.createAlarm()</code> method. If distinct different
- * behaviours are required for certain Alarms, and yet want to allow
- * users to freely select AlarmModel for all other Alarms, one need
- * to create two instances of the same AlarmModels, one used solely
- * for the pre-defined AlarmPoint behaviours, and the others for the rest of
- * the Alarms.
- * </p>
- */
-public interface AlarmPoint
-{
-    String STATUS_NORMAL = "Normal";
-    String STATUS_ACTIVATED = "Activated";
-    String STATUS_DEACTIVATED = "Deactivated";
-    String STATUS_REACTIVATED = "Reactivated";
-    String STATUS_ACKNOWLEDGED = "Acknowledged";
-    String STATUS_DISABLED = "Disabled";
-    String STATUS_BLOCKED = "Blocked";
-
-    String EVENT_ENABLING = "enabled";
-    String EVENT_DISABLING = "disabled";
-    String EVENT_BLOCKING = "blocked";
-    String EVENT_UNBLOCKING = "unblocked";
-    String EVENT_ACTIVATION = "activation";
-    String EVENT_DEACTIVATION = "deactivation";
-    String EVENT_ACKNOWLEDGEMENT = "acknowledgement";
-
-    String TRIGGER_ACTIVATE = "activate";
-    String TRIGGER_DEACTIVATE = "deactivate";
-    String TRIGGER_ACKNOWLEDGE = "acknowledge";
-    String TRIGGER_BLOCK = "block";
-    String TRIGGER_UNBLOCK = "unblock";
-    String TRIGGER_ENABLE = "enable";
-    String TRIGGER_DISABLE = "disable";
-
-    /**
-     * Trigger a state change.
-     * <p>
-     * When the AlarmPoint object receives a trigger, it must consult the
-     * AlarmModel and figure out if there is an actual state change
-     * occurring and if any AlarmEvents should be fired.
-     * </p>
-     *
-     * @param trigger The trigger to execute if existing in the AlarmModel.
-     *
-     * @throws IllegalArgumentException if a trigger is not a known one.
-     */
-    void trigger( String trigger )
-        throws IllegalArgumentException;
-
-    /**
-     * Activates an AlarmPoint.
-     * <p>
-     * Convenience method for:
-     * </p>
-     * <pre><code>
-     *       trigger( "activate" );
-     * </code>
-     * </pre>
-     */
-    void activate();
-
-    /**
-     * Deactivates an AlarmPoint.
-     * Convinience method for:<pre>
-     *     trigger( "deactivate" );
-     * </pre>
-     */
-    void deactivate();
-
-    /**
-     * Acknowledges an AlarmPoint.
-     * Convinience method for:<pre>
-     *     trigger( source, "acknowledge" );
-     * </pre>
-     */
-    void acknowledge();
-
-    /**
-     * Get AlarmPoint condition.
-     * To reduce AlarmPoint condition calculations for Implementors, each AlarmPoint should
-     * be able to work with a "true/false" trigger. Only changes to this trigger
-     * will cause an event.
-     *
-     * @return The condition of the AlarmPoint, which is used to simplify trigging of activate and deactivate.
-     */
-    boolean currentCondition();
-
-    /**
-     * Set AlarmPoint condition.
-     * To reduce AlarmPoint condition calculations for Implementors, each AlarmPoint should
-     * be able to work with a "true/false" trigger. Only changes to this trigger
-     * will cause an event.
-     * Causes an Activation or Deactivation if state of condition changes.
-     *
-     * @param condition Sets the AlarmPoint condition.
-     */
-    void updateCondition( boolean condition );
-
-    /**
-     * Returns the current state of the standard.
-     *
-     * @return The AlarmStatus (interface) object
-     */
-    AlarmStatus currentStatus();
-
-    /**
-     * Returns the AlarmHistory of the standard.
-     *
-     * @return The AlarmHistory object, or null if AlarmHistory is not supported.
-     */
-    AlarmHistory history();
-
-    /**
-     * Return all attribute names
-     *
-     * @return the names of the attributes of this AlarmPoint.
-     */
-    List<String> attributeNames();
-
-    /**
-     * Return the attribute of the given name.
-     *
-     * @param name The name of the attribute to return.
-     *
-     * @return the named attribute of this AlarmPoint.
-     */
-    String attribute( String name );
-
-    /**
-     * Sets the attribute of the given name.
-     *
-     * @param name  The name of the attribute to set.
-     * @param value The value to set the named attribute to.
-     */
-    void setAttribute( String name, @Optional String value );
-
-    /**
-     * Returns the Name of the AlarmPoint.
-     * This normally returns the human readable technical name of the AlarmPoint.
-     *
-     * @return the name of the AlarmPoint.
-     */
-    String name();
-
-    /**
-     * Returns a Description of the AlarmPoint.
-     * This normally returns a full Description of the AlarmPoint in the
-     * default Locale.
-     *
-     * @return a human-readable description of the AlarmPoint in the default locale.
-     */
-    String descriptionInDefaultLocale();
-
-    /**
-     * Returns a Description of the AlarmPoint.
-     * This normally returns a full Description of the AlarmPoint in the
-     * Locale. If Locale is <code><b>null</b></code>, then the
-     * default Locale is used.
-     *
-     * @param locale The locale to return the description in, or null to use default locale.
-     *
-     * @return a human-readable description of the AlarmPoint in the given locale.
-     */
-    String description( Locale locale );
-
-    /**
-     * The {@link AlarmClass} of the AlarmPoint.
-     *
-     * The {@link AlarmClass} indicates the urgency of {@link AlarmEvent}s emitted from the AlarmPoint. The property
-     * has {@link UseDefaults} annotation so that the application developer can set the default during assembly.
-     * The default {@link org.qi4j.bootstrap.Assembler} in this library defaults alarms to {@link AlarmClass} <b>B</b>.
-     *
-     * @return the property instance that contains the {@link AlarmClass}.
-     */
-    @UseDefaults
-    Property<AlarmClass> alarmClass();
-
-    /**
-     * The {@link AlarmCategory} of this AlarmPoint.
-     *
-     * AlarmCategory is used to group Alarms together, which can be used to forward {@link AlarmEvent} to different
-     * destinations, produce reports for different target audiences or separation of aggregation.
-     *
-     * @return the property instance that contains the {@link AlarmCategory}.
-     */
-    Property<AlarmCategory> category();
-
-    /**
-     * The AlarmState is an internal type, used inside the AlarmPoint for all state that needs to be persisted on disk
-     * and/or transferred across networks.
-     */
-    interface AlarmState
-    {
-        @AlarmNameFormat
-        Property<String> systemName();
-
-        @Optional
-        Property<String> description();
-
-        @UseDefaults
-        Property<Map<String, String>> attributes();
-
-        Property<AlarmStatus> currentStatus();
-    }
-
-    abstract class AlarmPointMixin
-        implements AlarmPoint
-    {
-        @Service
-        private AlarmModel model;
-
-        @Service
-        private AlarmSystem alarmSystem;
-
-        @This
-        private AlarmPoint me;
-
-        @This
-        private AlarmState state;
-
-        @This
-        private AlarmHistory history;
-
-        @Override
-        public void setAttribute( String name, String value )
-        {
-            Map<String, String> properties = state.attributes().get();
-            if( value == null )
-            {
-                properties.remove( name );
-            }
-            else
-            {
-                properties.put( name, value );
-            }
-            state.attributes().set( properties );
-        }
-
-        @Override
-        public String attribute( String name )
-        {
-            return state.attributes().get().get( name );
-        }
-
-        @Override
-        public List<String> attributeNames()
-        {
-            ArrayList<String> result = new ArrayList<String>();
-            for( String name : state.attributes().get().keySet() )
-            {
-                result.add( name );
-            }
-            return result;
-        }
-
-        private void fireAlarm( AlarmEvent event )
-        {
-            // TODO: Should possibly just be delegated to AlarmSystem
-            for( AlarmListener listener : alarmSystem.alarmListeners() )
-            {
-                try
-                {
-                    listener.alarmFired( event );
-                }
-                catch( Exception e )
-                {
-
-                    // ignore.
-                }
-            }
-        }
-
-        @Override
-        public String toString()
-        {
-            return "AlarmPoint[" + name() + " : " + state.currentStatus().get().name(null)
-                   + "  : " + descriptionInDefaultLocale() + "]";
-        }
-
-        @Override
-        public void trigger( String trigger )
-        {
-            AlarmEvent event;
-            synchronized( this )
-            {
-                event = model.evaluate( me, trigger );
-                if( event == null )
-                {
-                    return;
-                }
-                state.currentStatus().set( event.newStatus().get() );
-                history.addEvent( event, trigger );
-            }
-            fireAlarm( event );
-        }
-
-        @Override
-        public void activate()
-        {
-            trigger( AlarmPoint.TRIGGER_ACTIVATE );
-        }
-
-        @Override
-        public void deactivate()
-        {
-            trigger( AlarmPoint.TRIGGER_DEACTIVATE );
-        }
-
-        @Override
-        public void acknowledge()
-        {
-            trigger( AlarmPoint.TRIGGER_ACKNOWLEDGE );
-        }
-
-        @Override
-        public AlarmHistory history()
-        {
-            return history;
-        }
-
-        @Override
-        public AlarmStatus currentStatus()
-        {
-            return state.currentStatus().get();
-        }
-
-        /**
-         * Returns the Name of the AlarmPoint.
-         * This normally returns the human readable technical name of the AlarmPoint.
-         */
-        @Override
-        public String name()
-        {
-            return state.systemName().get();
-        }
-
-        /**
-         * Returns a Description of the AlarmPoint.
-         * This normally returns a full Description of the AlarmPoint in the
-         * default Locale.
-         */
-        @Override
-        public String descriptionInDefaultLocale()
-        {
-            return description( null );
-        }
-
-        /**
-         * Returns a Description of the AlarmPoint.
-         * This normally returns a full Description of the AlarmPoint in the
-         * Locale. If Locale is <code><b>null</b></code>, then the
-         * default Locale is used.
-         */
-        @Override
-        public String description( Locale locale )
-        {
-            if( locale == null )
-            {
-                locale = Locale.getDefault();
-            }
-            ResourceBundle rb = ResourceBundle.getBundle( "org.qi4j.library.alarm.user.AlarmDescriptions", locale );
-            return rb.getString( name() );
-        }
-
-        @Override
-        public void updateCondition( boolean condition )
-        {
-            String trig = model.computeTrigger( state.currentStatus().get(), condition );
-            if( trig != null )
-            {
-                trigger( trig );
-            }
-        }
-
-        @Override
-        public boolean currentCondition()
-        {
-            return model.computeCondition( state.currentStatus().get() );
-        }
-    }
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmPointEntity.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmPointEntity.java
deleted file mode 100644
index 5d97fdb..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmPointEntity.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 1996-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.mixin.Mixins;
-
-@Mixins(AlarmPoint.AlarmPointMixin.class)
-public interface AlarmPointEntity extends AlarmPoint, EntityComposite
-{
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmPointFactory.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmPointFactory.java
deleted file mode 100644
index 34982e7..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmPointFactory.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.alarm;
-
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueBuilder;
-
-@Mixins(AlarmPointFactory.Mixin.class)
-public interface AlarmPointFactory extends ServiceComposite
-{
-    AlarmPoint create(String identity, String systemName, String categoryName, AlarmClass alarmClass );
-    
-    abstract class Mixin
-        implements AlarmPointFactory {
-
-        @Structure
-        private Module module;
-        
-        @Override
-        public AlarmPoint create( String identity, String systemName, String categoryName, AlarmClass alarmClass )
-        {
-            UnitOfWork uow = module.currentUnitOfWork();
-            EntityBuilder<AlarmPoint> builder = uow.newEntityBuilder( AlarmPoint.class, identity );
-            builder.instance().category().set( createCategory(categoryName) );
-            builder.instance().alarmClass().set( alarmClass );
-
-            AlarmPoint.AlarmState prototype = builder.instanceFor( AlarmPoint.AlarmState.class );
-            AlarmStatus normal = createNormalAlarmStatus();
-            prototype.systemName().set( systemName );
-            prototype.currentStatus().set( normal );
-
-            return builder.newInstance();
-        }
-
-        private AlarmStatus createNormalAlarmStatus()
-        {
-            ValueBuilder<AlarmStatus> builder = module.newValueBuilder( AlarmStatus.class );
-            builder.prototypeFor(AlarmStatus.State.class).name().set( AlarmPoint.STATUS_NORMAL );
-            return builder.newInstance();
-        }
-
-        private AlarmCategory createCategory( String categoryName )
-        {
-            ValueBuilder<AlarmCategory> builder = module.newValueBuilder( AlarmCategory.class );
-            builder.prototype().name().set( categoryName );
-            return builder.newInstance();
-        }
-    }
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmProxy.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmProxy.java
deleted file mode 100644
index 1c34c45..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmProxy.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.alarm;
-
-import java.util.List;
-import java.util.Locale;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.concern.UnitOfWorkConcern;
-import org.qi4j.api.unitofwork.concern.UnitOfWorkPropagation;
-
-@Concerns( UnitOfWorkConcern.class )
-@Mixins( AlarmProxy.Mixin.class )
-public interface AlarmProxy extends AlarmPoint, TransientComposite
-{
-    @Mixins( FactoryMixin.class )
-    public interface Factory extends ServiceComposite
-    {
-        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED)
-        AlarmProxy create( String identity, String systemName, String categoryName, AlarmClass alarmClass );
-    }
-
-    abstract class FactoryMixin
-        implements Factory
-    {
-        @Structure
-        private Module module;
-
-        @Service
-        private AlarmPointFactory factory;
-
-        @Override
-        public AlarmProxy create( String identity, String systemName, String categoryName, AlarmClass alarmClass )
-        {
-            UnitOfWork unitOfWork = module.currentUnitOfWork();
-            AlarmPoint alarmPoint;
-            try
-            {
-                alarmPoint = unitOfWork.get( AlarmPoint.class, identity );
-            }
-            catch( NoSuchEntityException e )
-            {
-                alarmPoint = factory.create( identity, systemName, categoryName, alarmClass );
-            }
-            TransientBuilder<AlarmProxy> builder = module.newTransientBuilder( AlarmProxy.class );
-            builder.prototype().category().set( alarmPoint.category().get() );
-            builder.prototype().alarmClass().set( alarmClass );
-            builder.use( identity );
-            return builder.newInstance();
-        }
-    }
-
-    abstract class Mixin
-        implements AlarmPoint
-    {
-
-        @Structure
-        private Module module;
-
-        @Uses
-        String identity;
-
-        @Override
-        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
-        public void trigger( String trigger )
-            throws IllegalArgumentException
-        {
-            AlarmPoint alarmPoint = findAlarmPoint();
-            alarmPoint.trigger( trigger );
-        }
-
-        @Override
-        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
-        public void activate()
-        {
-            AlarmPoint alarmPoint = findAlarmPoint();
-            alarmPoint.activate();
-        }
-
-        @Override
-        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
-        public void deactivate()
-        {
-            AlarmPoint alarmPoint = findAlarmPoint();
-            alarmPoint.deactivate();
-        }
-
-        @Override
-        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
-        public void acknowledge()
-        {
-            AlarmPoint alarmPoint = findAlarmPoint();
-            alarmPoint.acknowledge();
-        }
-
-        @Override
-        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
-        public boolean currentCondition()
-        {
-            AlarmPoint alarmPoint = findAlarmPoint();
-            return alarmPoint.currentCondition();
-        }
-
-        @Override
-        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
-        public void updateCondition( boolean condition )
-        {
-            AlarmPoint alarmPoint = findAlarmPoint();
-            alarmPoint.updateCondition( condition );
-        }
-
-        @Override
-        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
-        public AlarmStatus currentStatus()
-        {
-            AlarmPoint alarmPoint = findAlarmPoint();
-            return alarmPoint.currentStatus();
-        }
-
-        @Override
-        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
-        public AlarmHistory history()
-        {
-            AlarmPoint alarmPoint = findAlarmPoint();
-            return alarmPoint.history();
-        }
-
-        @Override
-        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
-        public List<String> attributeNames()
-        {
-            AlarmPoint alarmPoint = findAlarmPoint();
-            return alarmPoint.attributeNames();
-        }
-
-        @Override
-        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
-        public String attribute( String name )
-        {
-            AlarmPoint alarmPoint = findAlarmPoint();
-            return alarmPoint.attribute( name );
-        }
-
-        @Override
-        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
-        public void setAttribute( String name, @Optional String value )
-        {
-            AlarmPoint alarmPoint = findAlarmPoint();
-            alarmPoint.setAttribute( name, value );
-        }
-
-        @Override
-        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
-        public String name()
-        {
-            AlarmPoint alarmPoint = findAlarmPoint();
-            return alarmPoint.name();
-        }
-
-        @Override
-        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
-        public String descriptionInDefaultLocale()
-        {
-            AlarmPoint alarmPoint = findAlarmPoint();
-            return alarmPoint.descriptionInDefaultLocale();
-        }
-
-        @Override
-        @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.REQUIRED )
-        public String description( Locale locale )
-        {
-            AlarmPoint alarmPoint = findAlarmPoint();
-            return alarmPoint.description( locale );
-        }
-
-        private AlarmPoint findAlarmPoint()
-        {
-            return module.currentUnitOfWork().get( AlarmPoint.class, identity );
-        }
-    }
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmStatus.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmStatus.java
deleted file mode 100644
index d2c7df1..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmStatus.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 1996-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import java.util.Date;
-import java.util.Locale;
-import java.util.ResourceBundle;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Initializable;
-import org.qi4j.api.mixin.InitializationException;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * Status of an AlarmPoint.
- *
- * @author Niclas Hedhman
- */
-@Mixins( AlarmStatus.AlarmStatusMixin.class )
-public interface AlarmStatus extends ValueComposite
-{
-
-    /**
-     * Returns the Name of the AlarmStatus in a locale.
-     * This is the technical name of the AlarmStatus, such as Normal,
-     * Activated and so forth in a locale specific form.
-     *
-     * @param locale the locale to return the name in.
-     *
-     * @return the name of the AlarmStatus in the given locale.
-     *
-     * @see State#name()
-     */
-    String name( @Optional Locale locale );
-
-    interface State
-    {
-
-        /**
-         * Returns the Date/Time of when this state was created.
-         *
-         * @return the timestamp of when the state was created.
-         */
-        @Optional
-        Property<Date> creationDate();
-
-        /**
-         * Returns the Name of the AlarmStatus.
-         * This is the technical name of the AlarmStatus, such as Normal,
-         * Activated and so forth in non-locale specific form.
-         *
-         * @return the name of the AlarmStatus in the default locale.
-         *
-         * @see #name(Locale)
-         */
-        Property<String> name();
-    }
-
-    abstract class AlarmStatusMixin
-        implements AlarmStatus, Initializable
-    {
-        @This
-        private State state;
-
-        @Override
-        public String name( Locale locale )
-        {
-            if( locale == null )
-            {
-                return state.name().get();
-            }
-            ResourceBundle bundle = ResourceBundle.getBundle( "AlarmResources", locale );
-            if( bundle == null )
-            {
-                return state.name().get();
-            }
-            return bundle.getString( state.name().get() );
-        }
-
-        @Override
-        public void initialize()
-            throws InitializationException
-        {
-            if( state.creationDate().get() == null )
-            {
-                state.creationDate().set( new Date() );
-            }
-        }
-    }
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmSystem.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmSystem.java
deleted file mode 100644
index c3e3702..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmSystem.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright 1996-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.QueryBuilderFactory;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-
-/**
- * Defines the AlarmSystem interface.
- *
- * <p>
- * The <code>AlarmSystem</code> is a central registry/handler for all
- * <code>AlarmPoint</code> objects. By registering <code>AlarmListener</code>s
- * to the AlarmSystem, objects are able to 'ignore' the fact that there
- * are many <code>AlarmPoint</code> objects in the system.
- * </p>
- * <p>
- * Also, new attributes registered with the AlarmSystem will propagate into
- * all existing and future <code>AlarmPoint</code>s, whereas attributes at <code>
- * AlarmPoint</code> level is individual to an <code>AlarmPoint</code>.
- * </p>
- * <p>
- * Many different AlarmModels can co-exist in the same application.
- * In fact, every AlarmPoint can have its own AlarmModel, and the AlarmModel
- * can be changed in runtime, for unrivaled flexibility. However, typically
- * the AlarmModel is set in the AlarmSystem only, and all Alarms will
- * use the default model.
- * </p>
- * <p>The default alarm model is a service set by during assembly;
- * </p>
- * <pre><code>
- *   public void assemble( ModuleAssembly module )
- *       throws AssemblyException
- *   {
- *       module.addServices( AlarmSystemService.class );
- *       module.addServices( StandardAlarmModelService.class );
- *   }
- * </code></pre>
- *
- * @author Niclas Hedhman
- */
-@Mixins( AlarmSystemService.AlarmSystemMixin.class )
-public interface AlarmSystem
-{
-
-    /**
-     * Returns all the AlarmModels that has been installed.
-     *
-     * @return all the AlarmModels that has been installed.
-     */
-    List<AlarmModelDescriptor> alarmModels();
-
-    /**
-     * Returns the default AlarmModel.
-     *
-     * @return the default AlarmModel in this AlarmSystem.
-     */
-    AlarmModel defaultAlarmModel();
-
-    /**
-     * Returns a list of all Alarms registered to the service.
-     * <p>
-     * The returned Collection may not be modified in any way. The
-     * implementation is free to return a clone, but not required to do
-     * so, and may decide to terminate if the collection is modified.
-     * </p>
-     *
-     * @return a list of all Alarms registered to the service.
-     */
-    Query<AlarmPoint> alarmList();
-
-    /**
-     * Creates an AlarmPoint with the default AlarmModel.
-     *
-     * @param name the name of the AlarmPoint to be created.
-     *
-     * @param category The category the created AlarmPoint should belong to.
-     *
-     * @return the created AlarmPoint with the given name using the default AlarmModel.
-     */
-    AlarmPoint createAlarm( String name, AlarmCategory category );
-
-    /**
-     * Register AlarmListener to recieve <code>AlarmEvents</code> from all
-     * <code>Alarms</code> managed by this <code>AlarmSystem</code>.
-     *
-     * @param listener the global listener to be added.
-     */
-    void addAlarmListener( AlarmListener listener );
-
-    /**
-     * Remove the <code>AlarmListener</code> from the <code>AlarmSystem</code>.
-     *
-     * @param listener the global listener to be removed.
-     */
-    void removeAlarmListener( AlarmListener listener );
-
-    /**
-     * Returns an immmutable list of all AlarmListeners registered to the service.
-     *
-     * @return a list of all AlarmListeners registered to the service.
-     */
-    List<AlarmListener> alarmListeners();
-
-    /**
-     * AlarmSystem implementation.
-     */
-    class AlarmSystemMixin
-        implements AlarmSystem
-    {
-        @Service
-        private Iterable<ServiceReference<AlarmModel>> models;
-
-        private final CopyOnWriteArrayList<AlarmListener> alarmListeners;
-
-        @Structure
-        private UnitOfWorkFactory uowf;
-
-        @Structure
-        private ValueBuilderFactory vbf;
-
-        @Structure
-        private QueryBuilderFactory qbf;
-
-        public AlarmSystemMixin()
-        {
-            alarmListeners = new CopyOnWriteArrayList<AlarmListener>();
-        }
-
-        /**
-         * Returns all the AlarmModels that has been installed.
-         */
-        @Override
-        public List<AlarmModelDescriptor> alarmModels()
-        {
-            List<AlarmModelDescriptor> descriptors = new ArrayList<AlarmModelDescriptor>();
-            for( ServiceReference<AlarmModel> model : models )
-            {
-                descriptors.add( model.metaInfo( AlarmModelDescriptor.class ) );
-            }
-            return descriptors;
-        }
-
-        /**
-         * Returns the default AlarmModel.
-         */
-        @Override
-        public AlarmModel defaultAlarmModel()
-        {
-            AlarmModelDescriptor defaultDefault = null;
-            for( AlarmModelDescriptor descriptor : alarmModels() )
-            {
-                if( descriptor.isDefaultModel() )
-                {
-                    return alarmModel( descriptor );
-                }
-                defaultDefault = descriptor;
-            }
-            return alarmModel( defaultDefault );
-        }
-
-        private AlarmModel alarmModel( AlarmModelDescriptor descriptor )
-        {
-            for( ServiceReference<AlarmModel> model : models )
-            {
-                if( model.metaInfo( AlarmModelDescriptor.class ).equals( descriptor ) )
-                {
-                    return model.get();
-                }
-            }
-            return null;
-        }
-
-        /**
-         * Creates an AlarmPoint with the default AlarmModel.
-         * @param name The system name of the AlarmPoint.
-         * @param category The AlarmPoint Category the created alarm should belong to.
-         */
-        @Override
-        public AlarmPoint createAlarm( String name, AlarmCategory category )
-        {
-            UnitOfWork uow = uowf.currentUnitOfWork();
-            EntityBuilder<AlarmPoint> builder = uow.newEntityBuilder( AlarmPoint.class );
-            builder.instance().category().set( category );
-            AlarmPoint.AlarmState state = builder.instanceFor( AlarmPoint.AlarmState.class );
-            state.systemName().set( name );
-            state.currentStatus().set( createStatus( AlarmPoint.STATUS_NORMAL ) );
-            return builder.newInstance();
-        }
-
-        private AlarmStatus createStatus( String status )
-        {
-            ValueBuilder<AlarmStatus> builder = vbf.newValueBuilder( AlarmStatus.class );
-            AlarmStatus.State statePrototype = builder.prototypeFor( AlarmStatus.State.class );
-            statePrototype.name().set( status );
-            statePrototype.creationDate().set( new Date() );
-            return builder.newInstance();
-        }
-
-        /**
-         * Register AlarmListener to recieve <code>AlarmEvents</code> from all
-         * <code>Alarms</code> managed by this <code>AlarmSystem</code>.
-         */
-        @Override
-        public void addAlarmListener( AlarmListener listener )
-        {
-            alarmListeners.add( listener );
-        }
-
-        /**
-         * Remove the <code>AlarmListener</code> from the <code>AlarmSystem</code>.
-         */
-        @Override
-        public void removeAlarmListener( AlarmListener listener )
-        {
-            alarmListeners.remove( listener );
-        }
-
-        /**
-         * Returns a list of all Alarms registered to the service.
-         */
-        @Override
-        public Query<AlarmPoint> alarmList()
-        {
-            UnitOfWork uow = uowf.currentUnitOfWork();
-            QueryBuilder<AlarmPoint> builder = qbf.newQueryBuilder( AlarmPoint.class );
-            return uow.newQuery( builder );
-        }
-
-        @Override
-        public List<AlarmListener> alarmListeners()
-        {
-            synchronized( alarmListeners )
-            {
-                return alarmListeners;
-            }
-        }
-
-        public void alarmFired( AlarmEvent event )
-        {
-            Iterator list;
-            //noinspection SynchronizeOnNonFinalField
-            synchronized( alarmListeners )
-            {
-                list = alarmListeners.iterator();
-            }
-            while( list.hasNext() )
-            {
-                AlarmListener listener = (AlarmListener) list.next();
-                try
-                {
-                    listener.alarmFired( event );
-                }
-                catch( Exception e )
-                {
-                    // TODO: Utilize a logger system instead.
-                    System.err.println( "Exception in AlarmListener: " + listener );
-                    e.printStackTrace();
-                }
-            }
-        }
-    }
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmSystemAssembler.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmSystemAssembler.java
deleted file mode 100644
index d9eeb76..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmSystemAssembler.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2011, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.alarm;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-
-public class AlarmSystemAssembler
-    extends Assemblers.VisibilityIdentity<AlarmSystemAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ServiceDeclaration alarmSystem = module.services( AlarmSystemService.class ).visibleIn( visibility() );
-        if( hasIdentity() )
-        {
-            alarmSystem.identifiedBy( identity() );
-        }
-        module.services( SimpleAlarmModelService.class ).setMetaInfo( new AlarmModelDescriptor( "Simple", false ) );
-        module.services( StandardAlarmModelService.class ).setMetaInfo( new AlarmModelDescriptor( "Standard", true ) );
-        module.services( ExtendedAlarmModelService.class ).setMetaInfo( new AlarmModelDescriptor( "Extended", false ) );
-        module.services( AlarmPointFactory.class );
-        module.entities( AlarmPointEntity.class );
-
-        module.values( AlarmEvent.class );
-        module.values( AlarmStatus.class );
-        module.values( AlarmCategory.class );
-        module.values( SimpleAlarmCategory.class );
-
-        module.transients( AlarmProxy.class );
-        module.services( AlarmProxy.Factory.class );
-        module.forMixin( AlarmPoint.class ).declareDefaults().alarmClass().set( AlarmClass.B );
-    }
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmSystemService.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmSystemService.java
deleted file mode 100644
index a1b12df..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/AlarmSystemService.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 1996-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import org.qi4j.api.service.ServiceComposite;
-
-public interface AlarmSystemService extends AlarmSystem, ServiceComposite
-{
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/ExtendedAlarmModelService.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/ExtendedAlarmModelService.java
deleted file mode 100644
index dbb764e..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/ExtendedAlarmModelService.java
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * Copyright 1996-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import java.util.ResourceBundle;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-
-/**
- * The Standard Model is centered around the Normal, Activated, Acknowledged
- * Deactivated, Reactivated, Blocked and Disabled states, and the triggers "activate", "deactivate",
- * "acknowledge", "block", "unblock", "enable" and "disable". The following matrix details the
- * resulting grid.
- * <table summary="Transitions">
- * <tr><th>Initial State</th><th>Trigger</th><th>Resulting State</th><th>Event Generated</th></tr>
- * <tr><td>Normal</td><td>activate</td><td>Activated</td><td>activation</td></tr>
- * <tr><td>Normal</td><td>deactivate</td><td>Normal</td><td>-</td></tr>
- * <tr><td>Normal</td><td>acknowledge</td><td>Normal</td><td>-</td></tr>
- * <tr><td>Normal</td><td>block</td><td>Blocked</td><td>block</td></tr>
- * <tr><td>Normal</td><td>unblock</td><td>Normal</td><td>-</td></tr>
- * <tr><td>Activated</td><td>activate</td><td>Activated</td><td>-</td></tr>
- * <tr><td>Activated</td><td>deactivate</td><td>Deactivated</td><td>deactivation</td></tr>
- * <tr><td>Activated</td><td>acknowledge</td><td>Acknowledged</td><td>acknowledge</td></tr>
- * <tr><td>Activated</td><td>block</td><td>Blocked</td><td>block</td></tr>
- * <tr><td>Activated</td><td>unblock</td><td>Activated</td><td>-</td></tr>
- * <tr><td>Deactivated</td><td>activate</td><td>Activated</td><td>activation</td></tr>
- * <tr><td>Deactivated</td><td>deactivate</td><td>Deativated</td><td>-</td></tr>
- * <tr><td>Deactivated</td><td>acknowledge</td><td>Normal</td><td>acknowledge</td></tr>
- * <tr><td>Deactivated</td><td>block</td><td>Blocked</td><td>block</td></tr>
- * <tr><td>Deactivated</td><td>unblock</td><td>Deactivated</td><td>-</td></tr>
- * <tr><td>Acknowledged</td><td>activate</td><td>Acknowledged</td><td>-</td></tr>
- * <tr><td>Acknowledged</td><td>deactivate</td><td>Normal</td><td>deactivation</td></tr>
- * <tr><td>Acknowledged</td><td>acknowledge</td><td>Acknowledged</td><td>-</td></tr>
- * <tr><td>Acknowledged</td><td>block</td><td>Blocked</td><td>block</td></tr>
- * <tr><td>Acknowledged</td><td>unblock</td><td>Acknowledged</td><td>-</td></tr>
- * <tr><td>Blocked</td><td>activate</td><td>Blocked</td><td>-</td></tr>
- * <tr><td>Blocked</td><td>deactivate</td><td>Blocked</td><td>-</td></tr>
- * <tr><td>Blocked</td><td>acknowledge</td><td>Blocked</td><td>-</td></tr>
- * <tr><td>Blocked</td><td>block</td><td>Blocked</td><td>-</td></tr>
- * <tr><td>Blocked</td><td>unblock</td><td>Normal</td><td>unblock</td></tr>
- * <tr><td>Normal</td><td>disable</td><td>Disabled</td><td>disable</td></tr>
- * <tr><td>Blocked</td><td>disable</td><td>Disabled</td><td>disable</td></tr>
- * <tr><td>Deactivated</td><td>disable</td><td>Disabled</td><td>disable</td></tr>
- * <tr><td>Acknowledged</td><td>disable</td><td>Disabled</td><td>disable</td></tr>
- * <tr><td>Activated</td><td>disable</td><td>Disabled</td><td>disable</td></tr>
- * <tr><td>Reactivated</td><td>disable</td><td>Disabled</td><td>disable</td></tr>
- * <tr><td>Disabled</td><td>disable</td><td>Disabled</td><td>-</td></tr>
- * <tr><td>Normal</td><td>enable</td><td>Normal</td><td>-</td></tr>
- * <tr><td>Blocked</td><td>enable</td><td>Blocked</td><td>-</td></tr>
- * <tr><td>Deactivated</td><td>enable</td><td>Deactivated</td><td>-</td></tr>
- * <tr><td>Acknowledged</td><td>enable</td><td>Acknowledged</td><td>-</td></tr>
- * <tr><td>Activated</td><td>enable</td><td>Activated</td><td>-</td></tr>
- * <tr><td>Reactivated</td><td>enable</td><td>Reactivated</td><td>-</td></tr>
- * <tr><td>Disabled</td><td>enable</td><td>Normal</td><td>enable</td></tr>
- * </table>
- */
-
-@Mixins(ExtendedAlarmModelService.ExtendedAlarmModelMixin.class)
-public interface ExtendedAlarmModelService
-    extends AlarmModel, ServiceComposite
-{
-    class ExtendedAlarmModelMixin
-        implements AlarmModel
-    {
-        private final static List<String> TRIGGER_LIST;
-
-        private static final List<String> STATUS_LIST;
-
-        @Structure
-        private ValueBuilderFactory vbf;
-
-        static
-        {
-            List<String> list1 = new ArrayList<String>();
-            list1.add( AlarmPoint.STATUS_NORMAL );
-            list1.add( AlarmPoint.STATUS_ACTIVATED );
-            list1.add( AlarmPoint.STATUS_DEACTIVATED );
-            list1.add( AlarmPoint.STATUS_ACKNOWLEDGED );
-            list1.add( AlarmPoint.STATUS_REACTIVATED );
-            list1.add( AlarmPoint.STATUS_BLOCKED );
-            list1.add( AlarmPoint.STATUS_DISABLED );
-            STATUS_LIST = Collections.unmodifiableList( list1 );
-
-            List<String> list2 = new ArrayList<String>();
-            list2.add( AlarmPoint.TRIGGER_ACTIVATE );
-            list2.add( AlarmPoint.TRIGGER_DEACTIVATE );
-            list2.add( AlarmPoint.TRIGGER_ACKNOWLEDGE );
-            list2.add( AlarmPoint.TRIGGER_BLOCK );
-            list2.add( AlarmPoint.TRIGGER_UNBLOCK );
-            list2.add( AlarmPoint.TRIGGER_DISABLE);
-            list2.add( AlarmPoint.TRIGGER_ENABLE );
-            TRIGGER_LIST = Collections.unmodifiableList( list2 );
-        }
-
-        static ResourceBundle getResourceBundle( Locale locale )
-        {
-            if( locale == null )
-            {
-                locale = Locale.getDefault();
-            }
-            ClassLoader cl = ExtendedAlarmModelMixin.class.getClassLoader();
-            return ResourceBundle.getBundle( MODEL_BUNDLE_NAME, locale, cl );
-        }
-
-        /**
-         * Returns the Name of the AlarmModel.
-         * This normally returns the human readable technical name of
-         * the AlarmModel.
-         *
-         * @return The system name of this alarm model.
-         */
-        @Override
-        public String modelName()
-        {
-            return "org.qi4j.library.alarm.model.extended";
-        }
-
-        /**
-         * Returns a Description of the AlarmModel in the default Locale.
-         * This normally returns a full Description of the AlarmModel in the
-         * default Locale.
-         *
-         * @return the description of the ModelProvider, in the default locale.
-         */
-        @Override
-        public String modelDescription()
-        {
-            return modelDescription( null );
-        }
-
-        /**
-         * Returns a Description of the AlarmModel.
-         * This normally returns a full Description of the AlarmModel in the
-         * Locale. If Locale is <code><b>null</b></code>, then the
-         * default Locale is used.
-         *
-         * @param locale The locale that should be used for the description, or null for the default locale.
-         *
-         * @return The human readable, in the given locale, description of this alarm model.
-         */
-        @Override
-        public String modelDescription( Locale locale )
-        {
-            ResourceBundle rb = getResourceBundle( locale );
-            return rb.getString( "MODEL_DESCRIPTION_EXTENDED" );
-        }
-
-        /**
-         * Execute the required changes upon an AlarmTrigger.
-         * The AlarmSystem calls this method, for the AlarmStatus
-         * in the the AlarmPoint to be updated, as well as an AlarmEvent
-         * to be created.
-         *
-         * @param alarm   the AlarmPoint object to be updated.
-         * @param trigger the AlarmTrigger that was used.
-         */
-        @Override
-        public AlarmEvent evaluate( AlarmPoint alarm, String trigger )
-        {
-            if( trigger.equals( AlarmPoint.TRIGGER_ACTIVATE ) )
-            {
-                return activation( alarm );
-            }
-            else if( trigger.equals( AlarmPoint.TRIGGER_DEACTIVATE ) )
-            {
-                return deactivation( alarm );
-            }
-            else if( trigger.equals( AlarmPoint.TRIGGER_ACKNOWLEDGE ) )
-            {
-                return acknowledge( alarm );
-            }
-            else if( trigger.equals( AlarmPoint.TRIGGER_BLOCK ) )
-            {
-                return block( alarm );
-            }
-            else if( trigger.equals( AlarmPoint.TRIGGER_UNBLOCK ) )
-            {
-                return unblock( alarm );
-            }
-            else if( trigger.equals( AlarmPoint.TRIGGER_ENABLE ) )
-            {
-                return enable( alarm );
-            }
-            else if( trigger.equals( AlarmPoint.TRIGGER_DISABLE ) )
-            {
-                return disable( alarm );
-            }
-            else
-            {
-                throw new IllegalArgumentException( "'" + trigger + "' is not supported by this AlarmModel." );
-            }
-        }
-
-        /**
-         * Returns all the supported AlarmPoint triggers.
-         *
-         * @return The AlarmPoint triggers that this AlarmModel supports.
-         */
-        @Override
-        public List<String> alarmTriggers()
-        {
-            return TRIGGER_LIST;
-        }
-
-        @Override
-        public List<String> statusList()
-        {
-            return STATUS_LIST;  //To change body of implemented methods use File | Settings | File Templates.
-        }
-
-        @Override
-        public String computeTrigger( AlarmStatus status, boolean condition )
-        {
-            if( condition )
-            {
-                if( ( status.name(null).equals( AlarmPoint.STATUS_DEACTIVATED ) ) ||
-                    ( status.name(null).equals( AlarmPoint.STATUS_NORMAL ) ) )
-                {
-                    return AlarmPoint.TRIGGER_ACTIVATE;
-                }
-            }
-            else
-            {
-                if( ( status.name(null).equals( AlarmPoint.STATUS_ACTIVATED ) ) ||
-                    ( status.name(null).equals( AlarmPoint.STATUS_REACTIVATED ) ) ||
-                    ( status.name(null).equals( AlarmPoint.STATUS_ACKNOWLEDGED ) ) )
-                {
-                    return AlarmPoint.TRIGGER_DEACTIVATE;
-                }
-            }
-            return null;
-        }
-
-        @Override
-        public boolean computeCondition( AlarmStatus status )
-        {
-            return ( status.name(null).equals( AlarmPoint.STATUS_ACTIVATED ) ) ||
-                   ( status.name(null).equals( AlarmPoint.STATUS_REACTIVATED ) ) ||
-                   ( status.name(null).equals( AlarmPoint.STATUS_ACKNOWLEDGED ) );
-        }
-
-        /**
-         * StateMachine change for activate trigger.
-         *
-         * @param alarm the alarm that is being triggered.
-         *
-         * @return The event to be fired on activation.
-         */
-        private AlarmEvent activation( AlarmPoint alarm )
-        {
-            AlarmStatus status = alarm.currentStatus();
-            if( ( status.name(null).equals( AlarmPoint.STATUS_NORMAL ) ) ||
-                ( status.name(null).equals( AlarmPoint.STATUS_DEACTIVATED ) ) )
-            {
-                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_ACTIVATED );
-                return createEvent( ( (Identity) alarm ), status, newStatus, AlarmPoint.EVENT_ACTIVATION );
-            }
-            return null;
-        }
-
-        /**
-         * StateMachine change for activate trigger.
-         *
-         * @param alarm the alarm that is being triggered.
-         *
-         * @return The event to be fired on deactivation.
-         */
-        private AlarmEvent deactivation( AlarmPoint alarm )
-        {
-            AlarmStatus status = alarm.currentStatus();
-            if( status.name(null).equals( AlarmPoint.STATUS_ACKNOWLEDGED ) )
-            {
-                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_NORMAL );
-                return createEvent( ( (Identity) alarm ), status, newStatus, AlarmPoint.EVENT_DEACTIVATION );
-            }
-            else if( status.name(null).equals( AlarmPoint.STATUS_ACTIVATED ) )
-            {
-                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_DEACTIVATED );
-                return createEvent( ( (Identity) alarm ), status, newStatus, AlarmPoint.EVENT_DEACTIVATION );
-            }
-            return null;
-        }
-
-        /**
-         * StateMachine change for activate trigger.
-         *
-         * @param alarm the alarm that is being triggered.
-         *
-         * @return The event to be fired on acknowledge.
-         */
-        private AlarmEvent acknowledge( AlarmPoint alarm )
-        {
-            AlarmStatus status = alarm.currentStatus();
-            if( status.name(null).equals( AlarmPoint.STATUS_DEACTIVATED ) )
-            {
-                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_NORMAL );
-                return createEvent( ( (Identity) alarm ), status, newStatus, AlarmPoint.EVENT_ACKNOWLEDGEMENT );
-            }
-            else if( status.name(null).equals( AlarmPoint.STATUS_ACTIVATED ) )
-            {
-                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_ACKNOWLEDGED );
-                return createEvent( ( (Identity) alarm ), status, newStatus, AlarmPoint.EVENT_ACKNOWLEDGEMENT );
-            }
-            return null;
-        }
-
-        /**
-         * StateMachine change for block trigger.
-         *
-         * @param alarm the alarm that is being triggered.
-         *
-         * @return The event to be fired on acknowledge.
-         */
-        private AlarmEvent block( AlarmPoint alarm )
-        {
-            AlarmStatus status = alarm.currentStatus();
-            if( status.name(null).equals( AlarmPoint.STATUS_BLOCKED ) ||
-                status.name(null).equals( AlarmPoint.STATUS_DISABLED ) )
-            {
-                return null;
-            }
-            AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_BLOCKED );
-            return createEvent( ( (Identity) alarm ), status, newStatus, AlarmPoint.EVENT_BLOCKING );
-        }
-
-        /**
-         * StateMachine change for unblock trigger.
-         *
-         * @param alarm the alarm that is being triggered.
-         *
-         * @return The event to be fired on acknowledge.
-         */
-        private AlarmEvent unblock( AlarmPoint alarm )
-        {
-            AlarmStatus status = alarm.currentStatus();
-            if( status.name(null).equals( AlarmPoint.STATUS_BLOCKED ) )
-            {
-                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_NORMAL );
-                return createEvent( ( (Identity) alarm ), status, newStatus, AlarmPoint.EVENT_UNBLOCKING );
-            }
-            return null;
-        }
-
-        /**
-         * StateMachine change for disable trigger.
-         *
-         * @param alarm the alarm that is being triggered.
-         *
-         * @return The event to be fired on acknowledge.
-         */
-        private AlarmEvent disable( AlarmPoint alarm )
-        {
-            AlarmStatus status = alarm.currentStatus();
-            if( status.name(null).equals( AlarmPoint.STATUS_DISABLED ) )
-            {
-                return null;
-            }
-            AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_DISABLED );
-            return createEvent( ( (Identity) alarm ), status, newStatus, AlarmPoint.EVENT_DISABLING );
-        }
-
-        /**
-         * StateMachine change for unblock trigger.
-         *
-         * @param alarm the alarm that is being triggered.
-         *
-         * @return The event to be fired on acknowledge.
-         */
-        private AlarmEvent enable( AlarmPoint alarm )
-        {
-            AlarmStatus status = alarm.currentStatus();
-            if( status.name(null).equals( AlarmPoint.STATUS_DISABLED ) )
-            {
-                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_NORMAL );
-                return createEvent( ( (Identity) alarm ), status, newStatus, AlarmPoint.EVENT_ENABLING );
-            }
-            return null;
-        }
-
-        private AlarmStatus createStatus( String status )
-        {
-            ValueBuilder<AlarmStatus> builder = vbf.newValueBuilder( AlarmStatus.class );
-            AlarmStatus.State prototype = builder.prototypeFor(AlarmStatus.State.class);
-            prototype.name().set( status );
-            prototype.creationDate().set( new Date() );
-            return builder.newInstance();
-        }
-
-        private AlarmEvent createEvent( Identity alarmId,
-                                        AlarmStatus oldStatus,
-                                        AlarmStatus newStatus,
-                                        String eventSystemName
-        )
-        {
-            ValueBuilder<AlarmEvent> builder = vbf.newValueBuilder( AlarmEvent.class );
-            AlarmEvent prototype = builder.prototype();
-            prototype.alarmIdentity().set( alarmId.identity().get() );
-            prototype.eventTime().set( new Date() );
-            prototype.newStatus().set( newStatus );
-            prototype.oldStatus().set( oldStatus );
-            prototype.systemName().set( eventSystemName );
-            return builder.newInstance();
-        }
-    }
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/SimpleAlarmCategory.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/SimpleAlarmCategory.java
deleted file mode 100644
index 39f3917..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/SimpleAlarmCategory.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2011, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.alarm;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-
-/**
- * The SimpleAlarmCategory only defines an optional Description property, and is provided more as an example
- * of how {@link AlarmCategory} may be extended.
- *
- * Note that this {@link AlarmCategory} is registered in the default {@link org.qi4j.bootstrap.Assembler} with a
- * Layer {@link org.qi4j.api.common.Visibility}, so if you subtype this, it is likely you need to create your own
- * {@link org.qi4j.bootstrap.Assembler}
- */
-public interface SimpleAlarmCategory
-    extends AlarmCategory
-{
-
-    @Optional
-    Property<String> description();
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/SimpleAlarmModelService.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/SimpleAlarmModelService.java
deleted file mode 100644
index 378709e..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/SimpleAlarmModelService.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright 1996-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import java.util.ResourceBundle;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-
-@Mixins( SimpleAlarmModelService.SimpleAlarmModelMixin.class)
-public interface SimpleAlarmModelService extends AlarmModel, ServiceComposite
-{
-    /**
-     * The Simple AlarmPoint Model is centered around the Normal and Activated.
-     * The triggers "activate" and "deactivate". The following matrix details the
-     * resulting grid.
-     * <table summary="Transitions">
-     * <tr><th>Initial State</th><th>Trigger</th><th>Resulting State</th><th>Event Generated</th></tr>
-     * <tr><td>Normal</td><td>activate</td><td>Activated</td><td>activation</td></tr>
-     * <tr><td>Normal</td><td>deactivate</td><td>Normal</td><td>-</td></tr>
-     * <tr><td>Activated</td><td>activate</td><td>Activated</td><td>-</td></tr>
-     * <tr><td>Activated</td><td>deactivate</td><td>Deactivated</td><td>deactivation</td></tr>
-     * </table>
-     */
-    class SimpleAlarmModelMixin
-        implements AlarmModel
-    {
-        private static final List<String> ALARM_TRIGGERS;
-        private static final List<String> ALARM_STATUSES;
-
-        static
-        {
-            List<String> list1 = new ArrayList<String>();
-
-            list1.add( AlarmPoint.TRIGGER_ACTIVATE );
-            list1.add( AlarmPoint.TRIGGER_DEACTIVATE );
-            ALARM_TRIGGERS = Collections.unmodifiableList( list1 );
-
-            List<String> list2 = new ArrayList<String>();
-            list2.add( AlarmPoint.STATUS_NORMAL );
-            list2.add( AlarmPoint.STATUS_ACTIVATED );
-            ALARM_STATUSES = Collections.unmodifiableList( list2 );
-        }
-
-        @Structure
-        private ValueBuilderFactory vbf;
-
-        static ResourceBundle getResourceBundle( Locale locale )
-        {
-            if( locale == null )
-            {
-                locale = Locale.getDefault();
-            }
-            ClassLoader cl = SimpleAlarmModelMixin.class.getClassLoader();
-            return ResourceBundle.getBundle( MODEL_BUNDLE_NAME, locale, cl );
-        }
-
-
-        /**
-         * Returns the Name of the AlarmModel.
-         * This normally returns the human readable technical name of
-         * the AlarmModel.
-         *
-         * @return The system name of this AlarmPoint Model.
-         */
-        @Override
-        public String modelName()
-        {
-            return "org.qi4j.library.alarm.model.simple";
-        }
-
-        /**
-         * Returns a Description of the AlarmModel in the default Locale.
-         * This normally returns a full Description of the AlarmModel in the
-         * default Locale.
-         *
-         * @return the description of the ModelProvider.
-         */
-        @Override
-        public String modelDescription()
-        {
-            return modelDescription( null );
-        }
-
-        /**
-         * Returns a Description of the AlarmModel.
-         * This normally returns a full Description of the AlarmModel in the
-         * Locale. If Locale is <code><b>null</b></code>, then the
-         * default Locale is used.
-         *
-         * @param locale The locale for which the description is wanted.
-         *
-         * @return the description of th
-         */
-        @Override
-        public String modelDescription( Locale locale )
-        {
-            ResourceBundle rb = getResourceBundle( locale );
-            return rb.getString( "MODEL_DESCRIPTION_SIMPLE" );
-        }
-
-        @Override
-        public List<String> statusList()
-        {
-            return ALARM_STATUSES;
-        }
-
-        /**
-         * Execute the required changes upon an AlarmTrigger.
-         * The AlarmSystem calls this method, for the AlarmStatus
-         * in the the AlarmPoint to be updated, as well as an AlarmEvent
-         * to be created.
-         *
-         * @param trigger the AlarmTrigger that was used.
-         */
-        @Override
-        public AlarmEvent evaluate( AlarmPoint alarm, String trigger )
-        {
-            if( trigger.equals( AlarmPoint.TRIGGER_ACTIVATE ) )
-            {
-                return activation( alarm );
-            }
-            else if( trigger.equals( AlarmPoint.TRIGGER_DEACTIVATE ) )
-            {
-                return deactivation( alarm );
-            }
-            else
-            {
-                throw new IllegalArgumentException( "'" + trigger + "' is not supported by this AlarmModel." );
-            }
-        }
-
-        /**
-         * Returns all the supported AlarmPoint triggers.
-         */
-        @Override
-        public List<String> alarmTriggers()
-        {
-            return ALARM_TRIGGERS;
-        }
-
-        @Override
-        public String computeTrigger( AlarmStatus status, boolean condition )
-        {
-            if( condition )
-            {
-                if( AlarmPoint.STATUS_NORMAL.equals( status.name(null) ) )
-                {
-                    return AlarmPoint.TRIGGER_ACTIVATE;
-                }
-            }
-            else
-            {
-                if( AlarmPoint.STATUS_ACTIVATED.equals( status.name(null) ) )
-                {
-                    return AlarmPoint.TRIGGER_DEACTIVATE;
-                }
-            }
-            return null;
-        }
-
-        @Override
-        public boolean computeCondition( AlarmStatus status )
-        {
-            return status.name(null).equals( AlarmPoint.STATUS_ACTIVATED );
-        }
-
-        /**
-         * StateMachine change for activate trigger.
-         *
-         * @param alarm the AlarmPoint that the activation is done on.
-         *
-         * @return the resulting AlarmEvent of the activation, or null if no change.
-         */
-        private AlarmEvent activation( AlarmPoint alarm )
-        {
-            AlarmStatus oldStatus = alarm.currentStatus();
-            if( oldStatus.name(null).equals( AlarmPoint.STATUS_NORMAL ) )
-            {
-                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_ACTIVATED );
-                return createEvent( (Identity) alarm, oldStatus, newStatus, AlarmPoint.EVENT_ACTIVATION );
-            }
-            return null;
-        }
-
-        /**
-         * StateMachine change for activate trigger.
-         *
-         * @param alarm the alarm that is causing the activation.
-         *
-         * @return the resulting AlarmEvent of the activation.
-         */
-        private AlarmEvent deactivation( AlarmPoint alarm )
-        {
-            AlarmStatus oldStatus = alarm.currentStatus();
-            if( oldStatus.name(null).equals( AlarmPoint.STATUS_ACTIVATED ) )
-            {
-                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_NORMAL );
-                return createEvent( (Identity) alarm, oldStatus, newStatus, AlarmPoint.EVENT_DEACTIVATION );
-            }
-            return null;
-        }
-
-        private AlarmStatus createStatus( String status )
-        {
-            ValueBuilder<AlarmStatus> builder = vbf.newValueBuilder( AlarmStatus.class );
-            AlarmStatus.State prototype = builder.prototypeFor(AlarmStatus.State.class);
-            prototype.name().set( status );
-            prototype.creationDate().set( new Date() );
-            return builder.newInstance();
-        }
-
-        private AlarmEvent createEvent( Identity alarmId,
-                                        AlarmStatus oldStatus,
-                                        AlarmStatus newStatus, String eventSystemName
-        )
-        {
-            ValueBuilder<AlarmEvent> builder = vbf.newValueBuilder( AlarmEvent.class );
-            AlarmEvent prototype = builder.prototype();
-            prototype.alarmIdentity().set( alarmId.identity().get() );
-            prototype.eventTime().set( new Date() );
-            prototype.newStatus().set( newStatus );
-            prototype.oldStatus().set( oldStatus );
-            prototype.systemName().set( eventSystemName );
-            return builder.newInstance();
-        }
-    }
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/StandardAlarmModelService.java b/libraries/alarm/src/main/java/org/qi4j/library/alarm/StandardAlarmModelService.java
deleted file mode 100644
index 1911398..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/StandardAlarmModelService.java
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright 1996-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import java.util.ResourceBundle;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-
-/**
- * The Standard AlarmPoint Model is centered around the Normal, Activated, Acknowledged
- * and Deactivated states, and the triggers "activate", "deactivate",
- * and "acknowledge".
- * <p>
- * The following matrix details the resulting grid.
- * </p>
- * <table summary="Transitions">
- * <tr><th>Initial State</th><th>Trigger</th><th>Resulting State</th><th>Event Generated</th></tr>
- * <tr><td>Normal</td><td>activate</td><td>Activated</td><td>activation</td></tr>
- * <tr><td>Normal</td><td>deactivate</td><td>Normal</td><td>-</td></tr>
- * <tr><td>Normal</td><td>acknowledge</td><td>Normal</td><td>-</td></tr>
- * <tr><td>Activated</td><td>activate</td><td>Activated</td><td>-</td></tr>
- * <tr><td>Activated</td><td>deactivate</td><td>Deactivated</td><td>deactivation</td></tr>
- * <tr><td>Activated</td><td>acknowledge</td><td>Acknowledged</td><td>acknowledge</td></tr>
- * <tr><td>Deactivated</td><td>activate</td><td>Activated</td><td>activation</td></tr>
- * <tr><td>Deactivated</td><td>deactivate</td><td>Deativated</td><td>-</td></tr>
- * <tr><td>Deactivated</td><td>acknowledge</td><td>Normal</td><td>acknowledge</td></tr>
- * <tr><td>Acknowledged</td><td>activate</td><td>Acknowledged</td><td>-</td></tr>
- * <tr><td>Acknowledged</td><td>deactivate</td><td>Normal</td><td>deactivation</td></tr>
- * <tr><td>Acknowledged</td><td>acknowledge</td><td>Acknowledged</td><td>-</td></tr>
- * </table>
- */
-
-@Mixins( StandardAlarmModelService.StandardAlarmModelMixin.class )
-public interface StandardAlarmModelService extends AlarmModel, ServiceComposite
-{
-    class StandardAlarmModelMixin
-        implements AlarmModel
-    {
-        private static final List<String> TRIGGER_LIST;
-
-        private static final List<String> STATUS_LIST;
-
-        static
-        {
-            List<String> list1 = new ArrayList<String>();
-            list1.add( AlarmPoint.STATUS_NORMAL );
-            list1.add( AlarmPoint.STATUS_ACTIVATED );
-            list1.add( AlarmPoint.STATUS_DEACTIVATED );
-            list1.add( AlarmPoint.STATUS_ACKNOWLEDGED );
-            STATUS_LIST = Collections.unmodifiableList( list1 );
-
-            List<String> list2 = new ArrayList<String>();
-            list2.add( AlarmPoint.TRIGGER_ACTIVATE );
-            list2.add( AlarmPoint.TRIGGER_DEACTIVATE );
-            list2.add( AlarmPoint.TRIGGER_ACKNOWLEDGE );
-            TRIGGER_LIST = Collections.unmodifiableList( list2 );
-        }
-
-        @Structure
-        private ValueBuilderFactory vbf;
-
-        static ResourceBundle getResourceBundle( Locale locale )
-        {
-            if( locale == null )
-            {
-                locale = Locale.getDefault();
-            }
-            ClassLoader cl = StandardAlarmModelMixin.class.getClassLoader();
-            return ResourceBundle.getBundle( MODEL_BUNDLE_NAME, locale, cl );
-        }
-
-        /**
-         * Returns the Name of the AlarmModel.
-         * This normally returns the human readable technical name of
-         * the AlarmModel.
-         */
-        @Override
-        public String modelName()
-        {
-            return "org.qi4j.library.alarm.model.standard";
-        }
-
-        /**
-         * Returns a Description of the AlarmModel in the default Locale.
-         * This normally returns a full Description of the AlarmModel in the
-         * default Locale.
-         *
-         * @return the description of the ModelProvider.
-         */
-        @Override
-        public String modelDescription()
-        {
-            return modelDescription( null );
-        }
-
-        /**
-         * Returns a Description of the AlarmModel.
-         * This normally returns a full Description of the AlarmModel in the
-         * Locale. If Locale is <code><b>null</b></code>, then the
-         * default Locale is used.
-         */
-        @Override
-        public String modelDescription( Locale locale )
-        {
-            ResourceBundle rb = getResourceBundle( locale );
-            return rb.getString( "MODEL_DESCRIPTION_STANDARD" );
-        }
-
-        /**
-         * Execute the required changes upon an AlarmTrigger.
-         * The AlarmSystem calls this method, for the AlarmStatus
-         * in the the AlarmPoint to be updated, as well as an AlarmEvent
-         * to be created.
-         *
-         * @param alarm   the AlarmPoint object to be updated.
-         * @param trigger the AlarmTrigger that was used.
-         */
-        @Override
-        public AlarmEvent evaluate( AlarmPoint alarm, String trigger )
-        {
-            if( trigger.equals( AlarmPoint.TRIGGER_ACTIVATE ) )
-            {
-                return activation( alarm );
-            }
-            else if( trigger.equals( AlarmPoint.TRIGGER_DEACTIVATE ) )
-            {
-                return deactivation( alarm );
-            }
-            else if( trigger.equals( AlarmPoint.TRIGGER_ACKNOWLEDGE ) )
-            {
-                return acknowledge( alarm );
-            }
-            else
-            {
-                throw new IllegalArgumentException( "'" + trigger + "' is not supported by this AlarmModel." );
-            }
-        }
-
-        /**
-         * Returns all the supported AlarmPoint triggers.
-         */
-        @Override
-        public List<String> alarmTriggers()
-        {
-            return TRIGGER_LIST;
-        }
-
-        @Override
-        public List<String> statusList()
-        {
-            return STATUS_LIST;
-        }
-
-        @Override
-        public String computeTrigger( AlarmStatus status, boolean condition )
-        {
-            if( condition )
-            {
-                if( ( status.name( null ).equals( AlarmPoint.STATUS_DEACTIVATED ) ) ||
-                    ( status.name( null ).equals( AlarmPoint.STATUS_NORMAL ) ) )
-                {
-                    return AlarmPoint.TRIGGER_ACTIVATE;
-                }
-            }
-            else
-            {
-                if( ( status.name( null ).equals( AlarmPoint.STATUS_ACTIVATED ) ) ||
-                    ( status.name( null ).equals( AlarmPoint.STATUS_ACKNOWLEDGED ) ) )
-                {
-                    return AlarmPoint.TRIGGER_DEACTIVATE;
-                }
-            }
-            return null;
-        }
-
-        @Override
-        public boolean computeCondition( AlarmStatus status )
-        {
-            return ( status.name( null ).equals( AlarmPoint.STATUS_ACTIVATED ) ) ||
-                   ( status.name( null ).equals( AlarmPoint.STATUS_ACKNOWLEDGED ) );
-        }
-
-        /**
-         * StateMachine change for activate trigger.
-         *
-         * @param alarm the alarm that is being triggered.
-         *
-         * @return The event to be fired on activation.
-         */
-        private AlarmEvent activation( AlarmPoint alarm )
-        {
-            AlarmStatus oldStatus = alarm.currentStatus();
-            if( ( oldStatus.name( null ).equals( AlarmPoint.STATUS_NORMAL ) ) ||
-                ( oldStatus.name( null ).equals( AlarmPoint.STATUS_DEACTIVATED ) ) )
-            {
-                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_ACTIVATED );
-                return createEvent( ( (Identity) alarm ), oldStatus, newStatus, AlarmPoint.EVENT_ACTIVATION );
-            }
-            return null;
-        }
-
-        /**
-         * StateMachine change for activate trigger.
-         *
-         * @param alarm the alarm that is being triggered.
-         *
-         * @return The event to be fired on deactivation.
-         */
-        private AlarmEvent deactivation( AlarmPoint alarm )
-        {
-            AlarmStatus oldStatus = alarm.currentStatus();
-            if( oldStatus.name( null ).equals( AlarmPoint.STATUS_ACKNOWLEDGED ) )
-            {
-                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_NORMAL );
-                return createEvent( ( (Identity) alarm ), oldStatus, newStatus, AlarmPoint.EVENT_DEACTIVATION );
-            }
-            else if( oldStatus.name( null ).equals( AlarmPoint.STATUS_ACTIVATED ) )
-            {
-                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_DEACTIVATED );
-                return createEvent( ( (Identity) alarm ), oldStatus, newStatus, AlarmPoint.EVENT_DEACTIVATION );
-            }
-            return null;
-        }
-
-        /**
-         * StateMachine change for activate trigger.
-         *
-         * @param alarm the alarm that is being triggered.
-         *
-         * @return The event to be fired on acknowledge.
-         */
-        private AlarmEvent acknowledge( AlarmPoint alarm )
-        {
-            AlarmStatus oldStatus = alarm.currentStatus();
-            if( oldStatus.name( null ).equals( AlarmPoint.STATUS_DEACTIVATED ) )
-            {
-                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_NORMAL );
-                return createEvent( ( (Identity) alarm ), oldStatus, newStatus, AlarmPoint.EVENT_ACKNOWLEDGEMENT );
-            }
-            else if( oldStatus.name( null ).equals( AlarmPoint.STATUS_ACTIVATED ) )
-            {
-                AlarmStatus newStatus = createStatus( AlarmPoint.STATUS_ACKNOWLEDGED );
-                return createEvent( ( (Identity) alarm ), oldStatus, newStatus, AlarmPoint.EVENT_ACKNOWLEDGEMENT );
-            }
-            return null;
-        }
-
-        private AlarmStatus createStatus( String status )
-        {
-            ValueBuilder<AlarmStatus> builder = vbf.newValueBuilder( AlarmStatus.class );
-            AlarmStatus.State prototype = builder.prototypeFor( AlarmStatus.State.class );
-            prototype.name().set( status );
-            prototype.creationDate().set( new Date() );
-            return builder.newInstance();
-        }
-
-        private AlarmEvent createEvent( Identity alarmId,
-                                        AlarmStatus oldStatus,
-                                        AlarmStatus newStatus,
-                                        String eventSystemName
-        )
-        {
-            ValueBuilder<AlarmEvent> builder = vbf.newValueBuilder( AlarmEvent.class );
-            AlarmEvent prototype = builder.prototype();
-            prototype.alarmIdentity().set( alarmId.identity().get() );
-            prototype.eventTime().set( new Date() );
-            prototype.newStatus().set( newStatus );
-            prototype.oldStatus().set( oldStatus );
-            prototype.systemName().set( eventSystemName );
-            return builder.newInstance();
-        }
-    }
-}
diff --git a/libraries/alarm/src/main/java/org/qi4j/library/alarm/package.html b/libraries/alarm/src/main/java/org/qi4j/library/alarm/package.html
deleted file mode 100644
index dbd518b..0000000
--- a/libraries/alarm/src/main/java/org/qi4j/library/alarm/package.html
+++ /dev/null
@@ -1,115 +0,0 @@
-<!--
-  ~ Copyright (c) 2011, Niclas Hedhman. All Rights Reserved.
-  ~
-  ~ Licensed 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.
-  -->
-
-<html>
-<body>
-<h1>Alarm Systems.</h1>
-
-<p>
-    Alarm Systems are originally used in Industrial Automation and Process Control systems, to monitor the health
-    of external devices and software functions in large scale plants. The semantics in an Alarm system are well-defined
-    and allows for excellent aggregation and overviews, fine-grained workflow of system health issues and
-    rich data sets around any issues.
-</p>
-
-<p>
-    This Alarm System, that is based on Zest's excellent persistence support, is an attempt at bringing a first-class
-    model from the industrial automation world into the enterprise of large-scale software systems, that nowadays
-    are so large and un-wieldly that log files, syslog and emails can no longer cope with the burden of management
-    needs.
-</p>
-
-<h1>The Conceptual Model</h1>
-
-<p>
-    Although the inner details of an alarm system can be hard to fully understand, the conceptual model is fairly
-    straight forward, and can be described with <i>Alarm</i>,<i>Alarm Trigger</i>, <i>Alarm Status</i> and <i>
-    Alarm Event</i>. The behavior of the Alarm state machine, hence the workflow, is dictated by an <i>Alarm Model</i>.
-</p>
-
-<p>
-    Looking at each of these in greater detail.
-</p>
-
-<h2>Alarm</h2>
-
-<p>
-    An Alarm is a tiny state-machine that tracks the <i>Alarm Status</i> (see below). An Alarm has certain attributes
-    that
-    are always present and custom attributes that are suitable for the domain in which the Alarm is being used. The
-    <i>Alarm Class</i> and <i>Alarm Category</i> are attributes that are always present, together with an <i>Alarm
-    Name</i> and an <i>Alarm Description</i>.
-</p>
-
-<h2>Alarm Class</h2>
-
-<p>
-    There are 4 <i>Alarm Classes</i>, A to D, indicating the urgency if an <i>Alarm Event</i> is occurring on the Alarm.
-</p>
-
-<h2>Alarm Category</h2>
-
-<p>
-    <i>Alarm Category</i> is a required attribute on the Alarm to indicate the target audience that needs to be informed
-    about it. This can be used to differentiate between infrastructure concerns versus domain model issues, or direct
-    <i>Alarm Events</i> to different recipients.
-</p>
-
-<h2>Alarm Model</h2>
-<p>
-    The <i>Alarm Model</i> defines which <i>Alarm Status</i> types, <i>Alarm Event</i> types, <i>Alarm Triggers</i> and
-    the behavior of the state machine in the <i>Alarm</i> itself.
-</p>
-<p>
-    The <i>Alarm Model</i> is an Zest™ <code>Service</code> and located via the normal <code>Visibility</code> rules,
-    making it possible to have a different <i>Alarm Model</i> in each Zest™ module.
-</p>
-
-<h2>Alarm Status</h2>
-<p>
-    The <i>Alarm</i> always has an <i>Alarm Status</i>. Most <i>Alarm Models</i> will have a <b>Normal</b> status which
-    the <i>Alarm</i> is set to initially, and <b>Activated</b> is likely to be present as well. The <i>Alarm Status</i>
-    only changes from one status to another through the use of an <i>Alarm Trigger</i>, but all triggers doesn't
-    cause the <i>Alarm Status</i> to change.
-</p>
-<h2>Alarm Event</h2>
-<p>
-    Whenever an <i>Alarm</i> changes its <i>Alarm Status</i> an <i>Alarm Event</i> is sent to all <i>Alarm
-    Listeners</i>. <i>Alarm Listeners</i> are registered to the <i>Alarm System</i>. <i>Alarm Event</i> types are
-    defined by the <i>Alarm Model</i>. Some common <i>Alarm Event</i> types/names are "activation", "acknowledgement"
-    and "deactivation".
-
-</p>
-<h2>Alarm Trigger</h2>
-<p>
-    <i>Alarm Triggers</i> are used to forward the workflow. The <i>Alarm Model</i> defines the available <i>Alarm
-    Triggers</i> which are all plain Strings. <i>Alarm Triggers</i> are "commanding" such as "block", "activate" and
-    "disable".
-</p>
-<h1>State Management</h1>
-<p>
-    <i>Alarm</i> instances are Zest™ Entities, so the <i>Alarm Status</i> is preserved over time in persisted storage.
-    This in turn means that the <i>Alarm</i> must be accessed within a <code>UnitOfWork</code> and the Alarm is not valid
-    outside the <code>UnitOfWork</code>.
-    </p>
-<p>
-    For Entities that needs Alarms, this is fairly straight forward, by making an
-    <code>@Aggregated Association&lt;Alarm&gt; alarm;</code> and have it being created in the <i>Entity</i>
-    <code>LifeCycle</code>. For non-entities, this becomes a little bit trickier. After the <i>Alarm</i> is created
-    the <code>Identity</code> of the <i>Alarm</i> needs to be preserved and used to retrieve the <i>Alarm</i> when
-    it needs to be <i>Triggered</i>. It is NOT possible to put an <i>Alarm</i> <code>Association</code> in a Service's
-   <code>configuration</code>, since you will not be able to access the <code>Configuration</code> members within the
-    <code>UnitOfWork</code> managed by the configuration system.
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/libraries/alarm/src/main/resources/org/apache/polygene/library/alarm/AlarmResources.properties b/libraries/alarm/src/main/resources/org/apache/polygene/library/alarm/AlarmResources.properties
new file mode 100644
index 0000000..7b7c840
--- /dev/null
+++ b/libraries/alarm/src/main/resources/org/apache/polygene/library/alarm/AlarmResources.properties
@@ -0,0 +1,83 @@
+#
+#  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.
+#
+#
+#
+
+
+MODEL_DESCRIPTION_SIMPLE=AlarmModel for "activation" and "deactivation" events, "normal" and "activated" states.
+MODEL_DESCRIPTION_STANDARD=AlarmModel for "activation", "deactivation", "acknowledge", "block" and "unblock" events, "normal", "activated", "deactivated", "acknowledged" and "blocked" states.
+MODEL_DESCRIPTION_EXTENDED=AlarmModel for "activation", "deactivation", "reactivation", "acknowledge", "block", "unblock", "disable" and "enable" events, and "normal", "activated", "deactivated", "acknowledged", "blocked" and "disabled" states.
+
+STATE_NORMAL_NAME=normal
+STATE_NORMAL_DESCRIPTION=Normal status indicates everything is fine.
+STATE_NORMAL_TOSTRING=status[normal, {0,date, MM/dd/yyyy hh:mm:ss a}]
+
+STATE_ACTIVATED_NAME=activated
+STATE_ACTIVATED_DESCRIPTION=Activated status indicates that there is an non-acknowledged Alarm condition at the moment.
+STATE_ACTIVATED_TOSTRING=status[activated, {0,date, MM/dd/yyyy hh:mm:ss a}]
+
+STATE_DEACTIVATED_NAME=deactivated
+STATE_DEACTIVATED_DESCRIPTION=Deactivated status indicates that the Alarm condition is false, but the Alarm has not been acknowledged.
+STATE_DEACTIVATED_TOSTRING=status[deactivated, {0,date, MM/dd/yyyy hh:mm:ss a}]
+
+STATE_ACKNOWLEDGED_NAME=acknowledged
+STATE_ACKNOWLEDGED_DESCRIPTION=Acknowledged status indicates that there is an Alarm condition but it has been noted.
+STATE_ACKNOWLEDGED_TOSTRING=status[acknowledged, {0,date, MM/dd/yyyy hh:mm:ss a}]
+
+STATE_BLOCKED_NAME=blocked
+STATE_BLOCKED_DESCRIPTION=Blocked status indicates that no triggers will affect the Alarm. It is normally used to disable events while the problem is being fixed.
+STATE_BLOCKED_TOSTRING=status[blocked, {0,date, MM/dd/yyyy hh:mm:ss a}]
+
+STATE_DISABLED_NAME=disabled
+STATE_DISABLED_DESCRIPTION=Disabled status indicates that the Alarm should not be used at the moment. No events will occur, and Alarm severity is lowest.
+STATE_DISABLED_TOSTRING=status[disabled, {0,date, MM/dd/yyyy hh:mm:ss a}]
+
+EVENT_GENERIC_PART_TOSTRING={0}, time[{1,date, MM/dd/yyyy hh:mm:ss a}], oldstate[{2}], newstate[{3}]
+
+EVENT_ACTIVATION_NAME=activation
+EVENT_ACTIVATION_DESCRIPTION=An Alarm has been triggered.
+EVENT_ACTIVATION_TOSTRING=event[{0}, activation]
+
+EVENT_DEACTIVATION_NAME=deactivation
+EVENT_DEACTIVATION_DESCRIPTION=The triggering Alarm condition has been reset.
+EVENT_DEACTIVATION_TOSTRING=event[{0}, deactivation]
+
+EVENT_ACKNOWLEDGE_NAME=acknowledge
+EVENT_ACKNOWLEDGE_DESCRIPTION=An Alarm has been acknowledged.
+EVENT_ACKNOWLEDGE_TOSTRING=event[{0}, acknowledge]
+
+EVENT_REACTIVATION_NAME=reactivation
+EVENT_REACTIVATION_DESCRIPTION=An Alarm has been triggered again. Reactivation happens when an Alarm is triggered a second or more times before an Acknowledge.
+EVENT_REACTIVATION_TOSTRING=event[{0}, reactivation]
+
+EVENT_BLOCK_NAME=block
+EVENT_BLOCK_DESCRIPTION=An Alarm has been blocked.
+EVENT_BLOCK_TOSTRING=event[{0}, block]
+
+EVENT_UNBLOCK_NAME=unblock
+EVENT_UNBLOCK_DESCRIPTION=An Alarm has been unblocked.
+EVENT_UNBLOCK_TOSTRING=event[{0}, unblock]
+
+EVENT_DISABLE_NAME=disable
+EVENT_DISABLE_DESCRIPTION=An Alarm has been disabled.
+EVENT_DISABLE_TOSTRING=event[{0}, disable]
+
+EVENT_ENABLE_NAME=enable
+EVENT_ENABLE_DESCRIPTION=An Alarm has been enabled.
+EVENT_ENABLE_TOSTRING=event[{0}, enable]
+
diff --git a/libraries/alarm/src/main/resources/org/apache/polygene/library/alarm/AlarmResources_sv.properties b/libraries/alarm/src/main/resources/org/apache/polygene/library/alarm/AlarmResources_sv.properties
new file mode 100644
index 0000000..168568a
--- /dev/null
+++ b/libraries/alarm/src/main/resources/org/apache/polygene/library/alarm/AlarmResources_sv.properties
@@ -0,0 +1,82 @@
+#
+#  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.
+#
+#
+#
+
+MODEL_DESCRIPTION_SIMPLE=AlarmModel f\u00F6r "utl\u00F6sning" och "fr\u00E5ng\u00E5ng" h\u00E4ndelser, samt "normal" och "utl\u00F6st" tillst\u00E5nd.
+MODEL_DESCRIPTION_STANDARD=AlarmModel f\u00F6r "utl\u00F6sning", "fr\u00E5ng\u00E5ng", "kvittens", "blockering" och "avblockering" h\u00E4ndelser, samt "normal", "utl\u00F6st", "\u00E5terst\u00E4llt", "kvitterat" och "blockerat" tillst\u00E5nd.
+MODEL_DESCRIPTION_EXTENDED=AlarmModel f\u00F6r "utl\u00F6sning", "fr\u00E5ng\u00E5ng", "kvittens", "\u00E5terutl\u00F6sning", "blockering", "avblockering", "avst\u00E4ngning" och "p\u000E5slagning"  h\u00E4ndelser, samt "normal", "utl\u00F6st", "\u00E5terst\u00E4llt", "kvitterat", "\u00E5terutl\u00F6st", "blockerat" och "avst\u00E4ngt" tillst\u00E5nd.
+
+STATE_NORMAL_NAME=normal
+STATE_NORMAL_DESCRIPTION=Normaltillst\u00E5nd indikerar att allt \u00E4r Ok.
+STATE_NORMAL_TOSTRING=tillst\u00E5nd[normal, {0,date, yyyy-MMM-dd HH:mm:ss}]
+
+STATE_ACTIVATED_NAME=utl\u00F6st
+STATE_ACTIVATED_DESCRIPTION=Utl\u00F6st larmtillst\u00E5nd.
+STATE_ACTIVATED_TOSTRING=tillst\u00E5nd[utl\u00F6st, {0,date, yyyy-MMM-dd HH:mm:ss}]
+
+STATE_DEACTIVATED_NAME=\u00E5terst\u00E4llt
+STATE_DEACTIVATED_DESCRIPTION=\u00C5terst\u00E4llt larmtillst\u00E5nd, men ej ingen kvittens.
+STATE_DEACTIVATED_TOSTRING=tillst\u00E5nd[\u00E5terst\u00E4llt, {0,date, yyyy-MMM-dd HH:mm:ss}]
+
+STATE_ACKNOWLEDGED_NAME=kvitterat
+STATE_ACKNOWLEDGED_DESCRIPTION=Kvitterat larmtillst\u00E5nd.
+STATE_ACKNOWLEDGED_TOSTRING=tillst\u00E5nd[kvitterat, {0,date, yyyy-MMM-dd HH:mm:ss}]
+
+STATE_BLOCKED_NAME=blockerat
+STATE_BLOCKED_DESCRIPTION=Under Blockerat tillst\u00E5 sker inga larm h\u00E4ndelser.
+STATE_BLOCKED_TOSTRING=tillst\u00E5nd[blockerat, {0,date, MM/dd/yyyy hh:mm:ss a}]
+
+STATE_DISABLED_NAME=avst\u00E4ngt
+STATE_DISABLED_DESCRIPTION=Under avst\u00E4ngt tillst\u00E5nd sker inga h\u00E4ndelser, och allvarlighetsgraden \u00e4r l\u00e4gst.
+STATE_DISABLED_TOSTRING=tillst\u00E5nd[avst\u00E4ngt, {0,date, MM/dd/yyyy hh:mm:ss a}]
+
+EVENT_GENERIC_PART_TOSTRING={0}, tidpunkt[{1,date, MM/dd/yyyy hh:mm:ss a}], fr\u00E5n [{2}] till [{3}]
+
+EVENT_ACTIVATION_NAME=utl\u00F6sning
+EVENT_ACTIVATION_DESCRIPTION=Larmutl\u00F6sning
+EVENT_ACTIVATION_TOSTRING=h\u00E4ndelse[{1}, utl\u00F6sning]
+
+EVENT_DEACTIVATION_NAME=fr\u00E5ng\u00E5ng
+EVENT_DEACTIVATION_DESCRIPTION=Larmvillkor g\u00E5r ifr\u00E5n.
+EVENT_DEACTIVATION_TOSTRING=h\u00E4ndelse[{1}, fr\u00E5ng\u00E5ng]
+
+EVENT_ACKNOWLEDGE_NAME=kvittens
+EVENT_ACKNOWLEDGE_DESCRIPTION=Kvittering av larmtillst\u00E5nd.
+EVENT_ACKNOWLEDGE_TOSTRING=h\u00E4ndelse[{1}, kvittens]
+
+EVENT_REACTIVATION_NAME=\u00E5terutl\u00F6sning
+EVENT_REACTIVATION_DESCRIPTION=Larm har l\u00E4st ut igen, innan det har blivit kvitterat.
+EVENT_REACTIVATION_TOSTRING=h\u00E4ndelse[{0}, \u00E5terutl\u00F6sning]
+
+EVENT_BLOCK_NAME=blockering
+EVENT_BLOCK_DESCRIPTION=Larm har blivit blockerat.
+EVENT_BLOCK_TOSTRING=h\u00E4ndelse[{0}, blockering]
+
+EVENT_UNBLOCK_NAME=avblockering
+EVENT_UNBLOCK_DESCRIPTION=Larm has blivit avblockerat.
+EVENT_UNBLOCK_TOSTRING=h\u00E4ndelse[{0}, avblockering]
+
+EVENT_DISABLE_NAME=avst\u00E4ngning
+EVENT_DISABLE_DESCRIPTION=Larm har blivit avst\u00E4ngt.
+EVENT_DISABLE_TOSTRING=h\u00E4ndelse[{0}, avst\u00E4ngning]
+
+EVENT_ENABLE_NAME=p\u00E5slagning
+EVENT_ENABLE_DESCRIPTION=Larm har blivit p\u00E5slaget.
+EVENT_ENABLE_TOSTRING=h\u00E4ndelse[{0}, p\u00E5slagning]
+
diff --git a/libraries/alarm/src/main/resources/org/qi4j/library/alarm/AlarmResources.properties b/libraries/alarm/src/main/resources/org/qi4j/library/alarm/AlarmResources.properties
deleted file mode 100644
index a5c3806..0000000
--- a/libraries/alarm/src/main/resources/org/qi4j/library/alarm/AlarmResources.properties
+++ /dev/null
@@ -1,80 +0,0 @@
-#
-# Copyright 1996-2005 Niclas Hedhman.
-#
-# Licensed  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.
-#
-
-MODEL_DESCRIPTION_SIMPLE=AlarmModel for "activation" and "deactivation" events, "normal" and "activated" states.
-MODEL_DESCRIPTION_STANDARD=AlarmModel for "activation", "deactivation", "acknowledge", "block" and "unblock" events, "normal", "activated", "deactivated", "acknowledged" and "blocked" states.
-MODEL_DESCRIPTION_EXTENDED=AlarmModel for "activation", "deactivation", "reactivation", "acknowledge", "block", "unblock", "disable" and "enable" events, and "normal", "activated", "deactivated", "acknowledged", "blocked" and "disabled" states.
-
-STATE_NORMAL_NAME=normal
-STATE_NORMAL_DESCRIPTION=Normal status indicates everything is fine.
-STATE_NORMAL_TOSTRING=status[normal, {0,date, MM/dd/yyyy hh:mm:ss a}]
-
-STATE_ACTIVATED_NAME=activated
-STATE_ACTIVATED_DESCRIPTION=Activated status indicates that there is an non-acknowledged Alarm condition at the moment.
-STATE_ACTIVATED_TOSTRING=status[activated, {0,date, MM/dd/yyyy hh:mm:ss a}]
-
-STATE_DEACTIVATED_NAME=deactivated
-STATE_DEACTIVATED_DESCRIPTION=Deactivated status indicates that the Alarm condition is false, but the Alarm has not been acknowledged.
-STATE_DEACTIVATED_TOSTRING=status[deactivated, {0,date, MM/dd/yyyy hh:mm:ss a}]
-
-STATE_ACKNOWLEDGED_NAME=acknowledged
-STATE_ACKNOWLEDGED_DESCRIPTION=Acknowledged status indicates that there is an Alarm condition but it has been noted.
-STATE_ACKNOWLEDGED_TOSTRING=status[acknowledged, {0,date, MM/dd/yyyy hh:mm:ss a}]
-
-STATE_BLOCKED_NAME=blocked
-STATE_BLOCKED_DESCRIPTION=Blocked status indicates that no triggers will affect the Alarm. It is normally used to disable events while the problem is being fixed.
-STATE_BLOCKED_TOSTRING=status[blocked, {0,date, MM/dd/yyyy hh:mm:ss a}]
-
-STATE_DISABLED_NAME=disabled
-STATE_DISABLED_DESCRIPTION=Disabled status indicates that the Alarm should not be used at the moment. No events will occur, and Alarm severity is lowest.
-STATE_DISABLED_TOSTRING=status[disabled, {0,date, MM/dd/yyyy hh:mm:ss a}]
-
-EVENT_GENERIC_PART_TOSTRING={0}, time[{1,date, MM/dd/yyyy hh:mm:ss a}], oldstate[{2}], newstate[{3}]
-
-EVENT_ACTIVATION_NAME=activation
-EVENT_ACTIVATION_DESCRIPTION=An Alarm has been triggered.
-EVENT_ACTIVATION_TOSTRING=event[{0}, activation]
-
-EVENT_DEACTIVATION_NAME=deactivation
-EVENT_DEACTIVATION_DESCRIPTION=The triggering Alarm condition has been reset.
-EVENT_DEACTIVATION_TOSTRING=event[{0}, deactivation]
-
-EVENT_ACKNOWLEDGE_NAME=acknowledge
-EVENT_ACKNOWLEDGE_DESCRIPTION=An Alarm has been acknowledged.
-EVENT_ACKNOWLEDGE_TOSTRING=event[{0}, acknowledge]
-
-EVENT_REACTIVATION_NAME=reactivation
-EVENT_REACTIVATION_DESCRIPTION=An Alarm has been triggered again. Reactivation happens when an Alarm is triggered a second or more times before an Acknowledge.
-EVENT_REACTIVATION_TOSTRING=event[{0}, reactivation]
-
-EVENT_BLOCK_NAME=block
-EVENT_BLOCK_DESCRIPTION=An Alarm has been blocked.
-EVENT_BLOCK_TOSTRING=event[{0}, block]
-
-EVENT_UNBLOCK_NAME=unblock
-EVENT_UNBLOCK_DESCRIPTION=An Alarm has been unblocked.
-EVENT_UNBLOCK_TOSTRING=event[{0}, unblock]
-
-EVENT_DISABLE_NAME=disable
-EVENT_DISABLE_DESCRIPTION=An Alarm has been disabled.
-EVENT_DISABLE_TOSTRING=event[{0}, disable]
-
-EVENT_ENABLE_NAME=enable
-EVENT_ENABLE_DESCRIPTION=An Alarm has been enabled.
-EVENT_ENABLE_TOSTRING=event[{0}, enable]
-
diff --git a/libraries/alarm/src/main/resources/org/qi4j/library/alarm/AlarmResources_sv.properties b/libraries/alarm/src/main/resources/org/qi4j/library/alarm/AlarmResources_sv.properties
deleted file mode 100644
index 0c80bd5..0000000
--- a/libraries/alarm/src/main/resources/org/qi4j/library/alarm/AlarmResources_sv.properties
+++ /dev/null
@@ -1,80 +0,0 @@
-#
-# Copyright 1996-2005 Niclas Hedhman.
-#
-# Licensed  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.
-#
-
-MODEL_DESCRIPTION_SIMPLE=AlarmModel f\u00F6r "utl\u00F6sning" och "fr\u00E5ng\u00E5ng" h\u00E4ndelser, samt "normal" och "utl\u00F6st" tillst\u00E5nd.
-MODEL_DESCRIPTION_STANDARD=AlarmModel f\u00F6r "utl\u00F6sning", "fr\u00E5ng\u00E5ng", "kvittens", "blockering" och "avblockering" h\u00E4ndelser, samt "normal", "utl\u00F6st", "\u00E5terst\u00E4llt", "kvitterat" och "blockerat" tillst\u00E5nd.
-MODEL_DESCRIPTION_EXTENDED=AlarmModel f\u00F6r "utl\u00F6sning", "fr\u00E5ng\u00E5ng", "kvittens", "\u00E5terutl\u00F6sning", "blockering", "avblockering", "avst\u00E4ngning" och "p\u000E5slagning"  h\u00E4ndelser, samt "normal", "utl\u00F6st", "\u00E5terst\u00E4llt", "kvitterat", "\u00E5terutl\u00F6st", "blockerat" och "avst\u00E4ngt" tillst\u00E5nd.
-
-STATE_NORMAL_NAME=normal
-STATE_NORMAL_DESCRIPTION=Normaltillst\u00E5nd indikerar att allt \u00E4r Ok.
-STATE_NORMAL_TOSTRING=tillst\u00E5nd[normal, {0,date, yyyy-MMM-dd HH:mm:ss}]
-
-STATE_ACTIVATED_NAME=utl\u00F6st
-STATE_ACTIVATED_DESCRIPTION=Utl\u00F6st larmtillst\u00E5nd.
-STATE_ACTIVATED_TOSTRING=tillst\u00E5nd[utl\u00F6st, {0,date, yyyy-MMM-dd HH:mm:ss}]
-
-STATE_DEACTIVATED_NAME=\u00E5terst\u00E4llt
-STATE_DEACTIVATED_DESCRIPTION=\u00C5terst\u00E4llt larmtillst\u00E5nd, men ej ingen kvittens.
-STATE_DEACTIVATED_TOSTRING=tillst\u00E5nd[\u00E5terst\u00E4llt, {0,date, yyyy-MMM-dd HH:mm:ss}]
-
-STATE_ACKNOWLEDGED_NAME=kvitterat
-STATE_ACKNOWLEDGED_DESCRIPTION=Kvitterat larmtillst\u00E5nd.
-STATE_ACKNOWLEDGED_TOSTRING=tillst\u00E5nd[kvitterat, {0,date, yyyy-MMM-dd HH:mm:ss}]
-
-STATE_BLOCKED_NAME=blockerat
-STATE_BLOCKED_DESCRIPTION=Under Blockerat tillst\u00E5 sker inga larm h\u00E4ndelser.
-STATE_BLOCKED_TOSTRING=tillst\u00E5nd[blockerat, {0,date, MM/dd/yyyy hh:mm:ss a}]
-
-STATE_DISABLED_NAME=avst\u00E4ngt
-STATE_DISABLED_DESCRIPTION=Under avst\u00E4ngt tillst\u00E5nd sker inga h\u00E4ndelser, och allvarlighetsgraden \u00e4r l\u00e4gst.
-STATE_DISABLED_TOSTRING=tillst\u00E5nd[avst\u00E4ngt, {0,date, MM/dd/yyyy hh:mm:ss a}]
-
-EVENT_GENERIC_PART_TOSTRING={0}, tidpunkt[{1,date, MM/dd/yyyy hh:mm:ss a}], fr\u00E5n [{2}] till [{3}]
-
-EVENT_ACTIVATION_NAME=utl\u00F6sning
-EVENT_ACTIVATION_DESCRIPTION=Larmutl\u00F6sning
-EVENT_ACTIVATION_TOSTRING=h\u00E4ndelse[{1}, utl\u00F6sning]
-
-EVENT_DEACTIVATION_NAME=fr\u00E5ng\u00E5ng
-EVENT_DEACTIVATION_DESCRIPTION=Larmvillkor g\u00E5r ifr\u00E5n.
-EVENT_DEACTIVATION_TOSTRING=h\u00E4ndelse[{1}, fr\u00E5ng\u00E5ng]
-
-EVENT_ACKNOWLEDGE_NAME=kvittens
-EVENT_ACKNOWLEDGE_DESCRIPTION=Kvittering av larmtillst\u00E5nd.
-EVENT_ACKNOWLEDGE_TOSTRING=h\u00E4ndelse[{1}, kvittens]
-
-EVENT_REACTIVATION_NAME=\u00E5terutl\u00F6sning
-EVENT_REACTIVATION_DESCRIPTION=Larm har l\u00E4st ut igen, innan det har blivit kvitterat.
-EVENT_REACTIVATION_TOSTRING=h\u00E4ndelse[{0}, \u00E5terutl\u00F6sning]
-
-EVENT_BLOCK_NAME=blockering
-EVENT_BLOCK_DESCRIPTION=Larm har blivit blockerat.
-EVENT_BLOCK_TOSTRING=h\u00E4ndelse[{0}, blockering]
-
-EVENT_UNBLOCK_NAME=avblockering
-EVENT_UNBLOCK_DESCRIPTION=Larm has blivit avblockerat.
-EVENT_UNBLOCK_TOSTRING=h\u00E4ndelse[{0}, avblockering]
-
-EVENT_DISABLE_NAME=avst\u00E4ngning
-EVENT_DISABLE_DESCRIPTION=Larm har blivit avst\u00E4ngt.
-EVENT_DISABLE_TOSTRING=h\u00E4ndelse[{0}, avst\u00E4ngning]
-
-EVENT_ENABLE_NAME=p\u00E5slagning
-EVENT_ENABLE_DESCRIPTION=Larm har blivit p\u00E5slaget.
-EVENT_ENABLE_TOSTRING=h\u00E4ndelse[{0}, p\u00E5slagning]
-
diff --git a/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/AlarmHistoryImplTest.java b/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/AlarmHistoryImplTest.java
new file mode 100644
index 0000000..5bf2ac8
--- /dev/null
+++ b/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/AlarmHistoryImplTest.java
@@ -0,0 +1,301 @@
+/*
+ *  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.polygene.library.alarm;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import java.util.Map;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.*;
+
+public class AlarmHistoryImplTest
+    extends AbstractPolygeneTest
+    implements AlarmListener
+{
+    private int eventCounter = 0;
+    private AlarmSystem alarmSystem;
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( TestAlarmModel.class );
+        module.services( AlarmSystemService.class );
+        module.entities( AlarmPointEntity.class );
+        new EntityTestAssembler().assemble( module );
+        module.values( AlarmStatus.class );
+        module.values( AlarmCategory.class );
+        module.values( AlarmEvent.class );
+        module.entities( AlarmPointEntity.class );
+        module.forMixin( AlarmHistory.class ).declareDefaults().maxSize().set( 30 );
+    }
+
+    @Mixins( SimpleAlarmModelService.SimpleAlarmModelMixin.class )
+    public interface TestAlarmModel
+        extends AlarmModel, ServiceComposite
+    {
+    }
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        unitOfWorkFactory.newUnitOfWork();
+    }
+
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        if ( unitOfWorkFactory.isUnitOfWorkActive())
+        {
+            UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+            uow.discard();
+        }
+        super.tearDown();
+    }
+
+    @Test
+    public void testEmpty()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "testEmpty" );
+        AlarmHistory hist = underTest.history();
+        AlarmEvent event1 = hist.firstEvent();
+        AlarmEvent event2 = hist.lastEvent();
+        assertNull( event1 );
+        assertNull( event2 );
+        assertEquals( "Activate Counter", 0, hist.activateCounter() );
+    }
+
+    @Test
+    public void testFirstNotLast()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "testFirstNotLast" );
+        underTest.updateCondition( true );
+        underTest.updateCondition( false );
+        AlarmHistory hist = underTest.history();
+        AlarmEvent event1 = hist.firstEvent();
+        AlarmEvent event2 = hist.lastEvent();
+        assertFalse( event1.equals( event2 ) );
+        assertEquals( AlarmPoint.STATUS_ACTIVATED, event1.newStatus().get().name(null) );
+        assertEquals( AlarmPoint.STATUS_NORMAL, event2.newStatus().get().name(null) );
+    }
+
+    @Test
+    public void testGetPosition()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "testGetPosition" );
+        alarmSystem.addAlarmListener( this );
+        AlarmHistory hist = underTest.history();
+        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
+        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
+        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
+        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
+        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
+        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
+
+        assertEquals( 5, eventCounter );
+        assertEquals( 5, hist.allAlarmEvents().get().size() );
+
+        AlarmEvent event = hist.eventAt( -1 );
+        assertNull( event );
+        event = hist.eventAt( 5 );
+        assertNull( event );
+        event = hist.eventAt( 0 );
+        assertEquals( "activation", event.systemName().get() );
+        event = hist.eventAt( 1 );
+        assertEquals( "deactivation", event.systemName().get() );
+        event = hist.eventAt( 2 );
+        assertEquals( "activation", event.systemName().get() );
+        event = hist.eventAt( 3 );
+        assertEquals( "deactivation", event.systemName().get() );
+        event = hist.eventAt( 4 );
+        assertEquals( "activation", event.systemName().get() );
+    }
+
+    @Test
+    public void testGetPositionFromLast()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "testGetPositionFromLast" );
+        alarmSystem.addAlarmListener( this );
+        AlarmHistory hist = underTest.history();
+        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
+        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
+        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
+        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
+        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
+        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
+
+        assertEquals( 5, eventCounter );
+        assertEquals( 5, hist.allAlarmEvents().get().size() );
+
+        AlarmEvent event = hist.eventAtEnd( -1 );
+        assertNull( event );
+        event = hist.eventAtEnd( 5 );
+        assertNull( event );
+        event = hist.eventAtEnd( 4 );
+        assertEquals( "activation", event.systemName().get() );
+        event = hist.eventAtEnd( 3 );
+        assertEquals( "deactivation", event.systemName().get() );
+        event = hist.eventAtEnd( 2 );
+        assertEquals( "activation", event.systemName().get() );
+        event = hist.eventAtEnd( 1 );
+        assertEquals( "deactivation", event.systemName().get() );
+        event = hist.eventAtEnd( 0 );
+        assertEquals( "activation", event.systemName().get() );
+    }
+
+    @Test
+    public void testCounters()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "testCounters" );
+        AlarmHistory hist = underTest.history();
+        Map<String, Integer> counters = hist.counters().get();
+
+        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
+        verifyCounters( counters, 1, 0 );
+
+        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
+        verifyCounters( counters, 1, 1 );
+
+        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
+        verifyCounters( counters, 2, 1 );
+
+        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
+        verifyCounters( counters, 2, 2 );
+
+        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
+        verifyCounters( counters, 2, 2 );
+
+        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
+        verifyCounters( counters, 3, 2 );
+
+        int activateCounters = hist.activateCounter();
+        assertEquals( 3, activateCounters );
+
+        hist.resetActivateCounter();
+        verifyCounters( counters, 0, 2 );
+
+        hist.resetAllCounters();
+        verifyCounters( counters, 0, 0 );
+    }
+
+    private void verifyCounters( Map counters, int c1, int c2 )
+    {
+        Number n1 = (Number) counters.get( AlarmPoint.TRIGGER_ACTIVATE );
+        Number n2 = (Number) counters.get( AlarmPoint.TRIGGER_DEACTIVATE );
+        if( n1 == null )
+        {
+            assertEquals( 0, c1 );
+        }
+        else
+        {
+            assertEquals( c1, n1 );
+        }
+
+        if( n2 == null )
+        {
+            assertEquals( 0, c2 );
+        }
+        else
+        {
+            assertEquals( c2, n2 );
+        }
+    }
+
+    @Test
+    public void testSetMaxSize()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "testSetMaxSize" );
+        alarmSystem.addAlarmListener( this );
+        AlarmHistory hist = underTest.history();
+        assertEquals( 0, hist.allAlarmEvents().get().size() );
+        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
+        assertEquals( 1, hist.allAlarmEvents().get().size() );
+        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
+        assertEquals( 2, hist.allAlarmEvents().get().size() );
+        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
+        assertEquals( 3, hist.allAlarmEvents().get().size() );
+        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
+        assertEquals( 4, hist.allAlarmEvents().get().size() );
+
+        int maxsize = hist.maxSize().get();
+        assertEquals( 30, maxsize );
+
+        hist.maxSize().set( 3 );    // The Polygene version doesn't intercept the maxSize().set() method and purge the old
+        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE ); // so we do another event to purge.
+        assertEquals( 3, hist.allAlarmEvents().get().size() );
+
+        hist.maxSize().set( 0 );
+        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE ); // so we do another event to purge.
+        assertEquals( 0, hist.allAlarmEvents().get().size() );
+        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
+        assertEquals( 0, hist.allAlarmEvents().get().size() );
+        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
+        assertEquals( 0, hist.allAlarmEvents().get().size() );
+        hist.maxSize().set( 2 );
+        assertEquals( 0, hist.allAlarmEvents().get().size() );
+        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
+        assertEquals( 1, hist.allAlarmEvents().get().size() );
+        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
+        assertEquals( 2, hist.allAlarmEvents().get().size() );
+        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
+        assertEquals( 2, hist.allAlarmEvents().get().size() );
+        assertEquals( 11, eventCounter );
+    }
+
+    public void alarmFired( AlarmEvent event )
+    {
+        eventCounter++;
+    }
+
+    private AlarmPoint createAlarm( String name )
+    {
+        ServiceReference<AlarmSystem> ref = serviceFinder.findService( AlarmSystem.class );
+        alarmSystem = ref.get();
+        return alarmSystem.createAlarm( name, createCategory( "AlarmHistoryTest" ) );
+    }
+
+    private AlarmCategory createCategory( String name )
+    {
+        ValueBuilder<AlarmCategory> builder = valueBuilderFactory.newValueBuilder( AlarmCategory.class );
+        builder.prototype().name().set( name );
+        return builder.newInstance();
+    }
+
+
+}
diff --git a/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/AlarmPointImplTest.java b/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/AlarmPointImplTest.java
new file mode 100644
index 0000000..2281e34
--- /dev/null
+++ b/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/AlarmPointImplTest.java
@@ -0,0 +1,240 @@
+/*
+ *  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.polygene.library.alarm;
+
+import java.util.List;
+import java.util.Locale;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+public class AlarmPointImplTest extends AbstractPolygeneTest
+    implements AlarmListener
+{
+    private int fired;
+    private AlarmSystem alarmSystem;
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( TestAlarmModel.class );
+        module.services( AlarmSystemService.class );
+        module.entities( AlarmPointEntity.class );
+        module.values( AlarmEvent.class );
+        module.values( AlarmCategory.class );
+        module.values( AlarmStatus.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Mixins( SimpleAlarmModelService.SimpleAlarmModelMixin.class )
+    public interface TestAlarmModel
+        extends AlarmModel, ServiceComposite
+    {
+    }
+
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        unitOfWorkFactory.newUnitOfWork();
+    }
+
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        if( unitOfWorkFactory.isUnitOfWorkActive() )
+        {
+            UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+            uow.discard();
+        }
+        super.tearDown();
+    }
+
+    @Test
+    public void testCreationProblems()
+        throws Exception
+    {
+        try
+        {
+            createAlarm( null );
+            fail( "AlarmPoint created with null name." );
+        }
+        catch( ConstraintViolationException e )
+        {
+            // expected.
+        }
+        try
+        {
+            createAlarm( "" );
+            fail( "AlarmPoint created with empty string name." );
+        }
+        catch( ConstraintViolationException e )
+        {
+            // expected.
+        }
+        try
+        {
+            createAlarm( "\n \n" );
+            fail( "AlarmPoint created with white space name." );
+        }
+        catch( ConstraintViolationException e )
+        {
+            // expected.
+        }
+    }
+
+    @Test
+    public void testName()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "TestCase AlarmPoint" );
+        assertEquals( "TestCase AlarmPoint", underTest.name() );
+    }
+
+    @Test
+    public void testDescription()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "TestCase AlarmPoint" );
+//        assertEquals( "This is a default Locale description of a testcase AlarmPoint.", underTest.description() );
+
+        Locale swedish = new Locale( "sv" );
+        assertEquals( "Detta \u00E5r en svensk beskrivning av ett testlarm.", underTest.description( swedish ) );
+
+        Locale english = Locale.UK;
+        assertEquals( "This is a UK Locale description of a testcase Alarm.", underTest.description( english ) );
+    }
+
+    @Test
+    public void testState()
+    {
+        AlarmPoint underTest = createAlarm( "testState" );
+        assertEquals( AlarmPoint.STATUS_NORMAL, underTest.currentStatus().name( null ) );
+        boolean condition = underTest.currentCondition();
+        assertEquals( false, condition );
+    }
+
+    @Test
+    public void testAttributes()
+    {
+        AlarmPoint underTest = createAlarm( "TestCase AlarmPoint" );
+
+        String alarmText = underTest.attribute( "text" );
+        assertNull( alarmText );
+
+        underTest.setAttribute( "text", "TestCase AlarmPoint" );
+        assertEquals( "TestCase AlarmPoint", underTest.attribute( "text" ) );
+
+        List<String> names = underTest.attributeNames();
+        assertEquals( 1, names.size() );
+
+        underTest.setAttribute( "text", null );
+        names = underTest.attributeNames();
+        assertEquals( 0, names.size() );
+    }
+
+    @Test
+    public void testInvalidTrigger()
+        throws Exception
+    {
+        try
+        {
+            AlarmPoint underTest = createAlarm( "TestCase AlarmPoint" );
+            underTest.trigger( "my-special-trigger" );
+            fail( "IllegalArgumentException was not thrown." );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Expected.
+        }
+    }
+
+    @Test
+    public void testNoEvent()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "TestCase AlarmPoint" );
+        alarmSystem.addAlarmListener( this );
+        underTest.deactivate();
+        assertEquals( 0, fired );
+    }
+
+    @Test
+    public void testListener()
+    {
+        AlarmPoint underTest = createAlarm( "TestCase AlarmPoint" );
+        try
+        {
+            alarmSystem.removeAlarmListener( null );  // make sure it fails.
+            fail( "Could remove null listener" );
+        }
+        catch( ConstraintViolationException e )
+        {
+            // expected
+        }
+        alarmSystem.removeAlarmListener( this );  // make sure it doesn't fail.
+
+        alarmSystem.addAlarmListener( this );
+        underTest.activate();
+        assertEquals( 1, fired );
+        alarmSystem.addAlarmListener( this );
+        underTest.deactivate();
+        assertEquals( 3, fired );
+        alarmSystem.removeAlarmListener( this );
+        underTest.activate();
+        assertEquals( 4, fired );
+        alarmSystem.removeAlarmListener( this );
+        underTest.deactivate();
+        assertEquals( 4, fired );
+    }
+
+    public void alarmFired( AlarmEvent event )
+    {
+        fired++;
+    }
+
+    private AlarmPoint createAlarm( String name )
+    {
+        ServiceReference<AlarmSystem> ref = serviceFinder.findService( AlarmSystem.class );
+        alarmSystem = ref.get();
+        return alarmSystem.createAlarm( name, createCategory( "AlarmPointImplTest" ) );
+    }
+
+    private AlarmCategory createCategory( String name )
+    {
+        ValueBuilder<AlarmCategory> builder = valueBuilderFactory.newValueBuilder( AlarmCategory.class );
+        builder.prototype().name().set( name );
+        return builder.newInstance();
+    }
+}
diff --git a/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/AlarmProxyTest.java b/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/AlarmProxyTest.java
new file mode 100644
index 0000000..478ef93
--- /dev/null
+++ b/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/AlarmProxyTest.java
@@ -0,0 +1,84 @@
+/*
+ *  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.polygene.library.alarm;
+
+import org.apache.polygene.api.identity.StringIdentity;
+import org.junit.Test;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+public class AlarmProxyTest extends AbstractPolygeneTest
+{
+    // START SNIPPET: documentation
+    @Service
+    private AlarmProxy.Factory factory;
+
+    private AlarmProxy myAlarmPoint;
+    // END SNIPPET: documentation
+
+    // START SNIPPET: documentation
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new AlarmSystemAssembler().assemble( module );
+        // END SNIPPET: documentation
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Test
+    public void givenAlarmPointWhenActivateExpectActivationEvent()
+        throws Exception
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+// START SNIPPET: documentation
+            myAlarmPoint = factory.create( new StringIdentity( "This Alarm Identity" ), "ProActiveCRM", "Sales", AlarmClass.B );
+            myAlarmPoint.history().maxSize().set( 20 );
+// END SNIPPET: documentation
+
+// START SNIPPET: documentation
+            myAlarmPoint.activate();
+// END SNIPPET: documentation
+            uow.complete();
+            assertThat( myAlarmPoint.history().activateCounter(), equalTo( 1 ) );
+            AlarmEvent event = myAlarmPoint.history().firstEvent();
+            assertThat( event, notNullValue() );
+            assertThat( event.identity().get(), equalTo( new StringIdentity( "This Alarm Identity" ) ) );
+            assertThat( event.newStatus().get().name( null ), equalTo( "Activated" ) );
+            assertThat( event.oldStatus().get().name( null ), equalTo( "Normal" ) );
+        }
+        catch( Exception e )
+        {
+            uow.discard();
+            throw e;
+        }
+    }
+}
diff --git a/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/AlarmServiceTest.java b/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/AlarmServiceTest.java
new file mode 100644
index 0000000..43af0b6
--- /dev/null
+++ b/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/AlarmServiceTest.java
@@ -0,0 +1,229 @@
+/*
+ *  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.polygene.library.alarm;
+
+import org.junit.Test;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import java.util.List;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.*;
+
+public class AlarmServiceTest
+    extends AbstractPolygeneTest
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( TestAlarmModel1.class ).setMetaInfo( new AlarmModelDescriptor("Simple", false) );
+        module.services( TestAlarmModel2.class ).setMetaInfo( new AlarmModelDescriptor("Standard", true) );
+        module.services( AlarmSystemService.class );
+        module.entities( AlarmPointEntity.class );
+        module.values( AlarmStatus.class );
+        module.values( AlarmCategory.class );
+        module.values( AlarmEvent.class );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Mixins( SimpleAlarmModelService.SimpleAlarmModelMixin.class )
+    public interface TestAlarmModel1
+        extends AlarmModel, ServiceComposite
+    {
+    }
+
+    @Mixins( StandardAlarmModelService.StandardAlarmModelMixin.class )
+    public interface TestAlarmModel2
+        extends AlarmModel, ServiceComposite
+    {
+    }
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        unitOfWorkFactory.newUnitOfWork();
+    }
+
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        if ( unitOfWorkFactory.isUnitOfWorkActive())
+        {
+            UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+            uow.discard();
+        }
+        super.tearDown();
+    }
+
+    @Test
+    public void testGetAlarmModels()
+    {
+        AlarmSystem alarmService = serviceFinder.findService( AlarmSystem.class ).get();
+        List<AlarmModelDescriptor> models = alarmService.alarmModels();
+        assertNotNull( models );
+        assertEquals( 2, models.size() );
+    }
+
+    @Test
+    public void testDefaultModel()
+        throws Exception
+    {
+        AlarmSystem alarmService = serviceFinder.findService( AlarmSystem.class ).get();
+        List<AlarmModelDescriptor> models = alarmService.alarmModels();
+        assertNotNull( models );
+        assertEquals( 2, models.size() );
+
+        AlarmModel model = alarmService.defaultAlarmModel();
+        assertNotNull( model );
+    }
+
+    @Test
+    public void testListeners()
+        throws Exception
+    {
+        AlarmSystem alarmService = serviceFinder.findService( AlarmSystem.class ).get();
+        AlarmPoint alarm = alarmService.createAlarm( "TestAlarm", createCategory("AlarmServiceTest") );
+
+        CountingListener listener1 = new CountingListener();
+        ExceptionThrowingListener listener2 = new ExceptionThrowingListener();
+        ErrorThrowingListener listener3 = new ErrorThrowingListener();
+        alarmService.addAlarmListener( listener1 );
+        alarmService.addAlarmListener( listener3 );
+        alarmService.addAlarmListener( listener1 );
+        try
+        {
+            alarm.activate();
+            fail( "InternalError was expected to be thrown." );
+        }
+        catch( InternalError e )
+        {
+            // Expected. If an Error is thrown it should not be captured anywhere.
+        }
+        assertEquals( 1, listener1.getCounter() );      // One time, because the second listener would not be called.
+
+        alarmService.removeAlarmListener( listener3 );
+        alarmService.removeAlarmListener( listener1 );
+        alarmService.addAlarmListener( listener2 );
+        alarmService.addAlarmListener( listener1 );   // We should now have, 'counting', 'exception', 'counting' in the list.
+        alarm.deactivate();   // No Exception should be thrown. The fireAlarm() should swallow it and ensure that
+        // all listeners are called and then return.
+        assertEquals( 3, listener1.getCounter() );
+
+        List listeners = alarmService.alarmListeners();
+        assertEquals( "Listeners registered.", 3, listeners.size() );
+
+        alarmService.removeAlarmListener( listener1 );
+        listeners = alarmService.alarmListeners();
+        assertEquals( "Listeners registered.", 2, listeners.size() );
+
+        alarmService.removeAlarmListener( listener1 );
+        listeners = alarmService.alarmListeners();
+        assertEquals( "Listeners registered.", 1, listeners.size() );
+
+        alarmService.removeAlarmListener( listener1 );
+        listeners = alarmService.alarmListeners();
+        assertEquals( "Listeners registered.", 1, listeners.size() );
+
+        alarmService.removeAlarmListener( listener2 );
+        listeners = alarmService.alarmListeners();
+        System.out.println( listeners );
+        assertEquals( "Listeners registered.", 0, listeners.size() );
+
+        alarmService.removeAlarmListener( listener2 );
+        listeners = alarmService.alarmListeners();
+        assertEquals( "Listeners registered.", 0, listeners.size() );
+
+        try
+        {
+            alarmService.removeAlarmListener( null );
+            fail( "Should not be able to call removeAlarmListener with null argument." );
+        }
+        catch( ConstraintViolationException e )
+        {
+            // expected
+        }
+        listeners = alarmService.alarmListeners();
+        assertEquals( "Listeners registered.", 0, listeners.size() );
+    }
+
+    private AlarmCategory createCategory( String name )
+    {
+        ValueBuilder<AlarmCategory> builder = valueBuilderFactory.newValueBuilder( AlarmCategory.class );
+        builder.prototype().name().set( name );
+        return builder.newInstance();
+    }
+
+
+
+    private class CountingListener
+        implements AlarmListener
+    {
+
+        private int m_Counter;
+
+        public CountingListener()
+        {
+            m_Counter = 0;
+        }
+
+        public void alarmFired( AlarmEvent event )
+        {
+            m_Counter = getCounter() + 1;
+        }
+
+        public int getCounter()
+        {
+            return m_Counter;
+        }
+    }
+
+    private class ExceptionThrowingListener
+        implements AlarmListener
+    {
+
+        public void alarmFired( AlarmEvent event )
+            throws IllegalArgumentException
+        {
+            throw new IllegalArgumentException( "This is an intentional Exception, and it is not a sign of a problem." );
+        }
+    }
+
+    private class ErrorThrowingListener
+        implements AlarmListener
+    {
+
+        public void alarmFired( AlarmEvent event )
+        {
+            throw new InternalError( "This is an intentional java.lang.Error." );
+        }
+    }
+}
diff --git a/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/ExtendedAlarmModelTest.java b/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/ExtendedAlarmModelTest.java
new file mode 100644
index 0000000..69fb835
--- /dev/null
+++ b/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/ExtendedAlarmModelTest.java
@@ -0,0 +1,979 @@
+/*
+ *  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.polygene.library.alarm;
+
+import java.time.Instant;
+import java.util.List;
+import java.util.Locale;
+import org.apache.polygene.api.identity.Identity;
+import org.junit.Test;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class ExtendedAlarmModelTest
+    extends AbstractPolygeneTest
+{
+
+    @SuppressWarnings( { "unchecked" } )
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( TestAlarmModel.class );
+        module.services( AlarmSystemService.class );
+        new EntityTestAssembler().assemble( module );
+        module.entities( AlarmPointEntity.class );
+        module.forMixin( AlarmHistory.class ).declareDefaults().maxSize().set( 10 );
+        module.values( AlarmEvent.class );
+        module.values( AlarmCategory.class );
+        module.values( AlarmStatus.class );
+    }
+
+    @Mixins( ExtendedAlarmModelService.ExtendedAlarmModelMixin.class )
+    public interface TestAlarmModel
+        extends AlarmModel, ServiceComposite
+    {
+    }
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        unitOfWorkFactory.newUnitOfWork();
+    }
+
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+        if( uow != null )
+        {
+            uow.discard();
+        }
+        super.tearDown();
+    }
+
+    @Test
+    public void testDescription()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        boolean test1 = provider.modelDescription().toLowerCase().contains( "normal" );
+        boolean test2 = provider.modelDescription().toLowerCase().contains( "activated" );
+        boolean test3 = provider.modelDescription().toLowerCase().contains( "deactivated" );
+        boolean test4 = provider.modelDescription().toLowerCase().contains( "acknowledged" );
+        boolean test5 = provider.modelDescription().toLowerCase().contains( "activation" );
+        boolean test6 = provider.modelDescription().toLowerCase().contains( "deactivation" );
+        boolean test7 = provider.modelDescription().toLowerCase().contains( "acknowledge" );
+        boolean test8 = provider.modelDescription().toLowerCase().contains( "block" );
+        boolean test9 = provider.modelDescription().toLowerCase().contains( "unblock" );
+        boolean test10 = provider.modelDescription().toLowerCase().contains( "disable" );
+        boolean test11 = provider.modelDescription().toLowerCase().contains( "enable" );
+        assertTrue( test1 && test2 && test3 && test4 && test5 && test6 && test7 && test8 && test9 && test10 && test11 );
+
+        Locale english = new Locale( "en" );
+        test1 = provider.modelDescription( english ).toLowerCase().contains( "normal" );
+        test2 = provider.modelDescription( english ).toLowerCase().contains( "activated" );
+        test3 = provider.modelDescription( english ).toLowerCase().contains( "deactivated" );
+        test4 = provider.modelDescription( english ).toLowerCase().contains( "acknowledged" );
+        test5 = provider.modelDescription( english ).toLowerCase().contains( "activation" );
+        test6 = provider.modelDescription( english ).toLowerCase().contains( "deactivation" );
+        test7 = provider.modelDescription( english ).toLowerCase().contains( "acknowledge" );
+        test8 = provider.modelDescription( english ).toLowerCase().contains( "block" );
+        test9 = provider.modelDescription( english ).toLowerCase().contains( "unblock" );
+        test10 = provider.modelDescription( english ).toLowerCase().contains( "disable" );
+        test11 = provider.modelDescription( english ).toLowerCase().contains( "enable" );
+        assertTrue( test1 && test2 && test3 && test4 && test5 && test6 && test7 && test8 && test9 && test10 && test11 );
+    }
+
+    @Test
+    public void testTriggers()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        List<String> triggers = provider.alarmTriggers();
+        assertEquals( 7, triggers.size() );
+        int result = 0;
+        for( String trigger : triggers )
+        {
+            if( AlarmPoint.TRIGGER_ACTIVATE.equals( trigger ) )
+            {
+                result |= 1;
+            }
+            if( AlarmPoint.TRIGGER_DEACTIVATE.equals( trigger ) )
+            {
+                result |= 2;
+            }
+            if( AlarmPoint.TRIGGER_ACKNOWLEDGE.equals( trigger ) )
+            {
+                result |= 4;
+            }
+            if( AlarmPoint.TRIGGER_BLOCK.equals( trigger ) )
+            {
+                result |= 8;
+            }
+            if( AlarmPoint.TRIGGER_UNBLOCK.equals( trigger ) )
+            {
+                result |= 16;
+            }
+            if( AlarmPoint.TRIGGER_DISABLE.equals( trigger ) )
+            {
+                result |= 32;
+            }
+            if( AlarmPoint.TRIGGER_ENABLE.equals( trigger ) )
+            {
+                result |= 64;
+            }
+        }
+        assertEquals( 127, result );
+        assertEquals( AlarmPoint.STATUS_NORMAL, underTest.currentStatus().name( null ) );
+    }
+
+    @Test
+    public void testStateChangeFromNormal()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmPoint alarm = createAlarm( "Another 1" );
+        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
+        assertEquals( AlarmPoint.EVENT_ACTIVATION, event1.systemName().get() );
+
+        alarm = createAlarm( "Another 2" );
+        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
+        assertNull( event2 );
+
+        alarm = createAlarm( "Another 3" );
+        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
+        assertNull( event3 );
+
+        alarm = createAlarm( "Another 4" );
+        AlarmEvent event4 = provider.evaluate( alarm, AlarmPoint.TRIGGER_BLOCK );
+        assertEquals( AlarmPoint.EVENT_BLOCKING, event4.systemName().get() );
+
+        alarm = createAlarm( "Another 5" );
+        AlarmEvent event5 = provider.evaluate( alarm, AlarmPoint.TRIGGER_UNBLOCK );
+        assertNull( event5 );
+
+        alarm = createAlarm( "Another 6" );
+        AlarmEvent event6 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DISABLE );
+        assertEquals( AlarmPoint.EVENT_DISABLING, event6.systemName().get() );
+
+        alarm = createAlarm( "Another 7" );
+        AlarmEvent event7 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ENABLE );
+        assertNull( event7 );
+    }
+
+    @Test
+    public void testStateChangeFromActivated()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmPoint alarm = createAlarm( "Another 1" );
+        alarm.activate();
+
+        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
+        assertNull( event1 );
+
+        alarm = createAlarm( "Another 2" );
+        alarm.activate();
+        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
+        assertEquals( AlarmPoint.EVENT_DEACTIVATION, event2.systemName().get() );
+
+        alarm = createAlarm( "Another 3" );
+        alarm.activate();
+        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
+        assertEquals( AlarmPoint.EVENT_ACKNOWLEDGEMENT, event3.systemName().get() );
+
+        alarm = createAlarm( "Another 4" );
+        alarm.activate();
+        AlarmEvent event4 = provider.evaluate( alarm, AlarmPoint.TRIGGER_BLOCK );
+        assertEquals( AlarmPoint.EVENT_BLOCKING, event4.systemName().get() );
+
+        alarm = createAlarm( "Another 5" );
+        alarm.activate();
+        AlarmEvent event5 = provider.evaluate( alarm, AlarmPoint.TRIGGER_UNBLOCK );
+        assertNull( event5 );
+
+        alarm = createAlarm( "Another 6" );
+        alarm.activate();
+        AlarmEvent event6 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DISABLE );
+        assertEquals( AlarmPoint.EVENT_DISABLING, event6.systemName().get() );
+
+        alarm = createAlarm( "Another 7" );
+        alarm.activate();
+        AlarmEvent event7 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ENABLE );
+        assertNull( event7 );
+    }
+
+    @Test
+    public void testStateChangeFromAcknowledged()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmPoint alarm = createAlarm( "Another 1" );
+        alarm.activate();
+        alarm.acknowledge();
+
+        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
+        assertNull( event1 );
+
+        alarm = createAlarm( "Another 2" );
+        alarm.activate();
+        alarm.acknowledge();
+        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
+        assertEquals( AlarmPoint.EVENT_DEACTIVATION, event2.systemName().get() );
+
+        alarm = createAlarm( "Another 3" );
+        alarm.activate();
+        alarm.acknowledge();
+        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
+        assertNull( event3 );
+
+        alarm = createAlarm( "Another 4" );
+        alarm.activate();
+        alarm.acknowledge();
+        AlarmEvent event4 = provider.evaluate( alarm, AlarmPoint.TRIGGER_BLOCK );
+        assertEquals( AlarmPoint.EVENT_BLOCKING, event4.systemName().get() );
+
+        alarm = createAlarm( "Another 5" );
+        alarm.activate();
+        alarm.acknowledge();
+        AlarmEvent event5 = provider.evaluate( alarm, AlarmPoint.TRIGGER_UNBLOCK );
+        assertNull( event5 );
+
+        alarm = createAlarm( "Another 6" );
+        alarm.activate();
+        alarm.acknowledge();
+        AlarmEvent event6 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DISABLE );
+        assertEquals( AlarmPoint.EVENT_DISABLING, event6.systemName().get() );
+
+        alarm = createAlarm( "Another 7" );
+        alarm.activate();
+        alarm.acknowledge();
+        AlarmEvent event7 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ENABLE );
+        assertNull( event7 );
+    }
+
+    @Test
+    public void testStateChangeFromDeactivated()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmPoint alarm = createAlarm( "Another 1" );
+        alarm.activate();
+        alarm.deactivate();
+        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
+        assertEquals( AlarmPoint.EVENT_ACTIVATION, event1.systemName().get() );
+
+        alarm = createAlarm( "Another 2" );
+        alarm.activate();
+        alarm.deactivate();
+        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
+        assertNull( event2 );
+
+        alarm = createAlarm( "Another 3" );
+        alarm.activate();
+        alarm.deactivate();
+        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
+        assertEquals( AlarmPoint.EVENT_ACKNOWLEDGEMENT, event3.systemName().get() );
+
+        alarm = createAlarm( "Another 4" );
+        alarm.activate();
+        alarm.deactivate();
+        AlarmEvent event4 = provider.evaluate( alarm, AlarmPoint.TRIGGER_BLOCK );
+        assertEquals( AlarmPoint.EVENT_BLOCKING, event4.systemName().get() );
+
+        alarm = createAlarm( "Another 5" );
+        alarm.activate();
+        alarm.deactivate();
+        AlarmEvent event5 = provider.evaluate( alarm, AlarmPoint.TRIGGER_UNBLOCK );
+        assertNull( event5 );
+
+        alarm = createAlarm( "Another 6" );
+        alarm.activate();
+        alarm.deactivate();
+        AlarmEvent event6 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DISABLE );
+        assertEquals( AlarmPoint.EVENT_DISABLING, event6.systemName().get() );
+
+        alarm = createAlarm( "Another 7" );
+        alarm.activate();
+        alarm.deactivate();
+        AlarmEvent event7 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ENABLE );
+        assertNull( event7 );
+    }
+
+    @Test
+    public void testStateChangeFromBlocked()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmPoint alarm = createAlarm( "Another 1" );
+        alarm.activate();
+        alarm.trigger( "block" );
+        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
+        assertNull( event1 );
+
+        alarm = createAlarm( "Another 2" );
+        alarm.activate();
+        alarm.trigger( "block" );
+        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
+        assertNull( event2 );
+
+        alarm = createAlarm( "Another 3" );
+        alarm.activate();
+        alarm.trigger( "block" );
+        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
+        assertNull( event3 );
+
+        alarm = createAlarm( "Another 4" );
+        alarm.activate();
+        alarm.trigger( "block" );
+        AlarmEvent event4 = provider.evaluate( alarm, AlarmPoint.TRIGGER_BLOCK );
+        assertNull( event4 );
+
+        alarm = createAlarm( "Another 5" );
+        alarm.activate();
+        alarm.trigger( "block" );
+        AlarmEvent event5 = provider.evaluate( alarm, AlarmPoint.TRIGGER_UNBLOCK );
+        assertEquals( AlarmPoint.EVENT_UNBLOCKING, event5.systemName().get() );
+
+        alarm = createAlarm( "Another 6" );
+        alarm.activate();
+        alarm.trigger( "block" );
+        AlarmEvent event6 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DISABLE );
+        assertEquals( AlarmPoint.EVENT_DISABLING, event6.systemName().get() );
+
+        alarm = createAlarm( "Another 7" );
+        alarm.activate();
+        alarm.trigger( "block" );
+        AlarmEvent event7 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ENABLE );
+        assertNull( event7 );
+    }
+
+    @Test
+    public void testStateChangeFromDisabled()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmPoint alarm = createAlarm( "Another 1" );
+        alarm.activate();
+        alarm.trigger( "disable" );
+        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
+        assertNull( event1 );
+
+        alarm = createAlarm( "Another 2" );
+        alarm.activate();
+        alarm.trigger( "disable" );
+        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
+        assertNull( event2 );
+
+        alarm = createAlarm( "Another 3" );
+        alarm.activate();
+        alarm.trigger( "disable" );
+        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
+        assertNull( event3 );
+
+        alarm = createAlarm( "Another 4" );
+        alarm.activate();
+        alarm.trigger( "disable" );
+        AlarmEvent event4 = provider.evaluate( alarm, AlarmPoint.TRIGGER_BLOCK );
+        assertNull( event4 );
+
+        alarm = createAlarm( "Another 5" );
+        alarm.activate();
+        alarm.trigger( "disable" );
+        AlarmEvent event5 = provider.evaluate( alarm, AlarmPoint.TRIGGER_UNBLOCK );
+        assertNull( event5 );
+
+        alarm = createAlarm( "Another 6" );
+        alarm.activate();
+        alarm.trigger( "disable" );
+        AlarmEvent event6 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DISABLE );
+        assertNull( event6 );
+
+        alarm = createAlarm( "Another 7" );
+        alarm.activate();
+        alarm.trigger( "disable" );
+        AlarmEvent event7 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ENABLE );
+        assertEquals( AlarmPoint.EVENT_ENABLING, event7.systemName().get() );
+    }
+
+    @Test
+    public void testIllegalTrigger()
+        throws Exception
+    {
+        try
+        {
+            AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+            AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+            provider.evaluate( underTest, "my-trigger" );
+            fail( "IllegalArgumentException not thrown." );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Expected.
+        }
+    }
+
+    @Test
+    public void testNormalToActivated()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        underTest.activate();
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_NORMAL, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACTIVATED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testActivatedToDeactivated()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        underTest.activate();
+        underTest.deactivate();
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_DEACTIVATED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testActivatedToAcknowledged()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.activate();
+        underTest.acknowledge();
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACKNOWLEDGED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testDeactivatedToNormal()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.activate();
+        underTest.deactivate();
+        underTest.acknowledge();
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_DEACTIVATED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_NORMAL, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testAcknowledgedToNormal()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.activate();
+        underTest.acknowledge();
+        underTest.deactivate();
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACKNOWLEDGED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_NORMAL, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testDisabledToNormal()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.activate();
+        underTest.trigger( "disable" );
+        underTest.trigger( "enable" );
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_DISABLED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_NORMAL, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testBlockedToNormal()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.activate();
+        underTest.trigger( "block" );
+        underTest.trigger( "unblock" );
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_BLOCKED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_NORMAL, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testNormalToBlocked()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.trigger( "block" );
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_NORMAL, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_BLOCKED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testActivatedToBlocked()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.activate();
+        underTest.trigger( "block" );
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_BLOCKED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testDeactivatedToBlocked()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.activate();
+        underTest.deactivate();
+        underTest.trigger( "block" );
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_DEACTIVATED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_BLOCKED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testAcknowledgedToBlocked()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.activate();
+        underTest.acknowledge();
+        underTest.trigger( "block" );
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACKNOWLEDGED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_BLOCKED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testNormalToDisabled()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.trigger( "disable" );
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_NORMAL, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_DISABLED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testActivatedToDisabled()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.activate();
+        underTest.trigger( "disable" );
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_DISABLED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testDeactivatedToDisabled()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.activate();
+        underTest.deactivate();
+        underTest.trigger( "disable" );
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_DEACTIVATED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_DISABLED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testAcknowledgedToDisabled()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.activate();
+        underTest.acknowledge();
+        underTest.trigger( "disable" );
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACKNOWLEDGED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_DISABLED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testBlockedToDisabled()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.activate();
+        underTest.trigger( "block" );
+        underTest.trigger( "disable" );
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_BLOCKED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_DISABLED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testDisabledToBlocked()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.activate();
+        underTest.trigger( "disable" );
+        underTest.trigger( "block" );       // This trigger should be ignored.
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_DISABLED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testConditionChanges1()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.updateCondition( false );
+        AlarmEvent event = underTest.history().lastEvent();
+        assertNull( "Generated an event but should have not.", event );
+    }
+
+    @Test
+    public void testConditionChanges2()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.updateCondition( true );
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_NORMAL, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACTIVATED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testConditionChanges3()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+
+        underTest.updateCondition( true );
+        underTest.updateCondition( false );
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_DEACTIVATED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testComputeCondition()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmStatus s1 = createStatus( AlarmPoint.STATUS_NORMAL );
+        assertFalse( provider.computeCondition( s1 ) );
+        AlarmStatus s2 = createStatus( AlarmPoint.STATUS_ACTIVATED );
+        assertTrue( provider.computeCondition( s2 ) );
+        AlarmStatus s3 = createStatus( AlarmPoint.STATUS_DEACTIVATED );
+        assertFalse( provider.computeCondition( s3 ) );
+        AlarmStatus s4 = createStatus( AlarmPoint.STATUS_ACKNOWLEDGED );
+        assertTrue( provider.computeCondition( s4 ) );
+
+        AlarmStatus s5 = createStatus( AlarmPoint.STATUS_DISABLED );
+        assertFalse( provider.computeCondition( s5 ) );
+        AlarmStatus s6 = createStatus( AlarmPoint.STATUS_BLOCKED );
+        assertFalse( provider.computeCondition( s6 ) );
+        AlarmStatus s7 = createStatus( AlarmPoint.STATUS_REACTIVATED );
+        assertTrue( provider.computeCondition( s7 ) );
+    }
+
+    @Test
+    public void testComputeTriggerNormal()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmStatus status = createStatus( AlarmPoint.STATUS_NORMAL );
+        String trigger1 = provider.computeTrigger( status, true );
+        String trigger2 = provider.computeTrigger( status, false );
+        assertEquals( AlarmPoint.TRIGGER_ACTIVATE, trigger1 );
+        assertEquals( null, trigger2 );
+    }
+
+    @Test
+    public void testComputeTriggerActivated()
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmStatus status = createStatus( AlarmPoint.STATUS_ACTIVATED );
+        String trigger1 = provider.computeTrigger( status, true );
+        String trigger2 = provider.computeTrigger( status, false );
+        assertEquals( null, trigger1 );
+        assertEquals( AlarmPoint.TRIGGER_DEACTIVATE, trigger2 );
+    }
+
+    @Test
+    public void testComputeTRiggerDeactivated()
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmStatus status = createStatus( AlarmPoint.STATUS_DEACTIVATED );
+        String trigger1 = provider.computeTrigger( status, true );
+        String trigger2 = provider.computeTrigger( status, false );
+        assertEquals( AlarmPoint.TRIGGER_ACTIVATE, trigger1 );
+        assertEquals( null, trigger2 );
+    }
+
+    @Test
+    public void testComputeTriggerAcknowledged()
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmStatus status = createStatus( AlarmPoint.STATUS_ACKNOWLEDGED );
+        String trigger1 = provider.computeTrigger( status, true );
+        String trigger2 = provider.computeTrigger( status, false );
+        assertEquals( null, trigger1 );
+        assertEquals( AlarmPoint.TRIGGER_DEACTIVATE, trigger2 );
+    }
+
+    @Test
+    public void testComputeTriggerReactivated()
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmStatus status = createStatus( AlarmPoint.STATUS_REACTIVATED );
+        String trigger1 = provider.computeTrigger( status, true );
+        String trigger2 = provider.computeTrigger( status, false );
+        assertEquals( null, trigger1 );
+        assertEquals( AlarmPoint.TRIGGER_DEACTIVATE, trigger2 );
+    }
+
+    @Test
+    public void testComputeTriggerBlocked()
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmStatus status = createStatus( AlarmPoint.STATUS_BLOCKED );
+        String trigger1 = provider.computeTrigger( status, true );
+        String trigger2 = provider.computeTrigger( status, false );
+        assertEquals( null, trigger1 );
+        assertEquals( null, trigger2 );
+    }
+
+    @Test
+    public void testComputeTriggerDisabled()
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmStatus status = createStatus( AlarmPoint.STATUS_DISABLED );
+        String trigger1 = provider.computeTrigger( status, true );
+        String trigger2 = provider.computeTrigger( status, false );
+        assertEquals( null, trigger1 );
+        assertEquals( null, trigger2 );
+    }
+
+    private AlarmPoint createAlarm( String name )
+    {
+        UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+        EntityBuilder<AlarmPoint> builder = uow.newEntityBuilder( AlarmPoint.class );
+        builder.instance().category().set( createCategory( "Testing" ) );
+        AlarmPoint.AlarmState state = builder.instanceFor( AlarmPoint.AlarmState.class );
+        state.currentStatus().set( createStatus( AlarmPoint.STATUS_NORMAL ) );
+        state.description().set( "Test Description" );
+        state.systemName().set( name );
+        return builder.newInstance();
+    }
+
+    private AlarmCategory createCategory( String name )
+    {
+        ValueBuilder<AlarmCategory> builder = valueBuilderFactory.newValueBuilder( AlarmCategory.class );
+        builder.prototype().name().set( name );
+        return builder.newInstance();
+    }
+
+    private AlarmPoint getAlarm( Identity identity )
+    {
+        UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+        return uow.get( AlarmPoint.class, identity );
+    }
+
+    private AlarmStatus createStatus( String status )
+    {
+        ValueBuilder<AlarmStatus> builder = valueBuilderFactory.newValueBuilder( AlarmStatus.class );
+        AlarmStatus.State statePrototype = builder.prototypeFor( AlarmStatus.State.class );
+        statePrototype.name().set( status );
+        statePrototype.creationDate().set( Instant.now() );
+        return builder.newInstance();
+    }
+}
diff --git a/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/SimpleAlarmModelTest.java b/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/SimpleAlarmModelTest.java
new file mode 100644
index 0000000..a4c402f
--- /dev/null
+++ b/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/SimpleAlarmModelTest.java
@@ -0,0 +1,364 @@
+/*
+ *  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.polygene.library.alarm;
+
+import java.time.Instant;
+import java.util.List;
+import java.util.Locale;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class SimpleAlarmModelTest
+    extends AbstractPolygeneTest
+{
+
+    @SuppressWarnings( { "unchecked" } )
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( TestAlarmModel.class );
+        module.services( AlarmSystemService.class );
+        new EntityTestAssembler().assemble( module );
+        module.entities( AlarmPointEntity.class );
+        module.values( AlarmEvent.class );
+        module.values( AlarmCategory.class );
+        module.values( AlarmStatus.class );
+        module.forMixin( AlarmHistory.class ).declareDefaults().maxSize().set( 10 );
+    }
+
+    @Mixins( SimpleAlarmModelService.SimpleAlarmModelMixin.class )
+    public interface TestAlarmModel
+        extends AlarmModel, ServiceComposite
+    {
+    }
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        unitOfWorkFactory.newUnitOfWork();
+    }
+
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+        if( uow != null )
+        {
+            uow.discard();
+        }
+        super.tearDown();
+    }
+
+    @Test
+    public void testName()
+        throws Exception
+    {
+        SimpleAlarmModelService.SimpleAlarmModelMixin spi = new SimpleAlarmModelService.SimpleAlarmModelMixin();
+        assertEquals( "org.apache.polygene.library.alarm.model.simple", spi.modelName() );
+    }
+
+    @Test
+    public void testDescription()
+        throws Exception
+    {
+        SimpleAlarmModelService.SimpleAlarmModelMixin spi = new SimpleAlarmModelService.SimpleAlarmModelMixin();
+        boolean test1 = spi.modelDescription().toLowerCase().contains( "normal" );
+        boolean test2 = spi.modelDescription().toLowerCase().contains( "activated" );
+        boolean test3 = spi.modelDescription().toLowerCase().contains( "activation" );
+        boolean test4 = spi.modelDescription().toLowerCase().contains( "deactivation" );
+        assertTrue( test1 && test2 && test3 && test4 );
+
+        Locale english = new Locale( "en" );
+        test1 = spi.modelDescription( english ).toLowerCase().contains( "normal" );
+        test2 = spi.modelDescription( english ).toLowerCase().contains( "activated" );
+        test3 = spi.modelDescription( english ).toLowerCase().contains( "activation" );
+        test4 = spi.modelDescription( english ).toLowerCase().contains( "deactivation" );
+        assertTrue( test1 && test2 && test3 && test4 );
+    }
+
+    @Test
+    public void testTriggers()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        List<String> triggers = provider.alarmTriggers();
+        assertEquals( 2, triggers.size() );
+        int result = 0;
+        for( String trigger : triggers )
+        {
+            if( AlarmPoint.TRIGGER_ACTIVATE.equals( trigger ) )
+            {
+                result |= 1;
+            }
+            if( AlarmPoint.TRIGGER_DEACTIVATE.equals( trigger ) )
+            {
+                result |= 2;
+            }
+            if( AlarmPoint.TRIGGER_ACKNOWLEDGE.equals( trigger ) )
+            {
+                result |= 4;
+            }
+            if( AlarmPoint.TRIGGER_BLOCK.equals( trigger ) )
+            {
+                result |= 8;
+            }
+            if( AlarmPoint.TRIGGER_UNBLOCK.equals( trigger ) )
+            {
+                result |= 16;
+            }
+            if( AlarmPoint.TRIGGER_ENABLE.equals( trigger ) )
+            {
+                result |= 32;
+            }
+            if( AlarmPoint.TRIGGER_DISABLE.equals( trigger ) )
+            {
+                result |= 64;
+            }
+        }
+        assertEquals( 3, result );
+        assertEquals( AlarmPoint.STATUS_NORMAL, underTest.currentStatus().name(null) );
+    }
+
+    @Test
+    public void testStateChangeFromNormal()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmPoint alarm = createAlarm( "Another 1" );
+        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
+        assertEquals( AlarmPoint.EVENT_ACTIVATION, event1.systemName().get() );
+
+        alarm = createAlarm( "Another 2" );
+        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
+        assertNull( event2 );
+
+        try
+        {
+            alarm = createAlarm( "Another 3" );
+            AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
+            assertNull( event3 );
+            fail( "[Acknowledge] trigger should not be allowed on this model." );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // expected
+        }
+    }
+
+    @Test
+    public void testStateChangeFromActivated()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmPoint alarm = createAlarm( "Another 1" );
+        alarm.activate();
+
+        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
+        assertNull( event1 );
+
+        alarm = createAlarm( "Another 2" );
+        alarm.activate();
+        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
+        assertEquals( AlarmPoint.EVENT_DEACTIVATION, event2.systemName().get() );
+    }
+
+    @Test
+    public void testIllegalTrigger()
+        throws Exception
+    {
+        try
+        {
+            AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+            AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+            provider.evaluate( underTest, "my-trigger" );
+            fail( "IllegalArgumentException not thrown." );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Expected.
+        }
+    }
+
+    @Test
+    public void testNormalToActivated()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        underTest.activate();
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_NORMAL, oldstate.name(null) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACTIVATED, newstate.name(null) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testActivatedToNormal()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        underTest.activate();
+        underTest.deactivate();
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name(null) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_NORMAL, newstate.name(null) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testConditionChanges1()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        underTest.updateCondition( false );
+        AlarmEvent event = underTest.history().lastEvent();
+        assertNull( "Generated an event but should have not.", event );
+    }
+
+    @Test
+    public void testConditionChanges2()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        underTest.updateCondition( true );
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_NORMAL, oldstate.name(null) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACTIVATED, newstate.name(null) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testConditionChanges3()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        underTest.updateCondition( true );
+        underTest.updateCondition( false );
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name(null) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_NORMAL, newstate.name(null) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testComputeCondition()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmStatus s1 = createStatus( AlarmPoint.STATUS_NORMAL );
+        assertFalse( provider.computeCondition( s1 ) );
+        AlarmStatus s2 = createStatus( AlarmPoint.STATUS_ACTIVATED );
+        assertTrue( provider.computeCondition( s2 ) );
+    }
+
+    @Test
+    public void testComputeTrigger()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmStatus s1 = createStatus( AlarmPoint.STATUS_NORMAL );
+        AlarmStatus s2 = createStatus( AlarmPoint.STATUS_ACTIVATED );
+        String trigger1 = provider.computeTrigger( s1, true );
+        String trigger2 = provider.computeTrigger( s2, true );
+        String trigger5 = provider.computeTrigger( s1, false );
+        String trigger6 = provider.computeTrigger( s2, false );
+        assertEquals( AlarmPoint.TRIGGER_ACTIVATE, trigger1 );
+        assertEquals( null, trigger2 );
+        assertEquals( null, trigger5 );
+        assertEquals( AlarmPoint.TRIGGER_DEACTIVATE, trigger6 );
+    }
+
+    private AlarmPoint createAlarm( String name )
+    {
+        UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+        EntityBuilder<AlarmPoint> builder = uow.newEntityBuilder( AlarmPoint.class );
+        builder.instance().category().set( createCategory( "SimpleModelTest" ) );
+        AlarmPoint.AlarmState state = builder.instanceFor( AlarmPoint.AlarmState.class );
+        state.currentStatus().set( createStatus( AlarmPoint.STATUS_NORMAL ) );
+        state.description().set( "Test Description" );
+        state.systemName().set( name );
+        return builder.newInstance();
+    }
+
+    private AlarmCategory createCategory( String name )
+    {
+        ValueBuilder<AlarmCategory> builder = valueBuilderFactory.newValueBuilder( AlarmCategory.class );
+        builder.prototype().name().set( name );
+        return builder.newInstance();
+    }
+
+    private AlarmPoint getAlarm( Identity identity )
+    {
+        UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+        return uow.get( AlarmPoint.class, identity );
+    }
+
+    private AlarmStatus createStatus( String status )
+    {
+        ValueBuilder<AlarmStatus> builder = valueBuilderFactory.newValueBuilder( AlarmStatus.class );
+        AlarmStatus.State statePrototype = builder.prototypeFor( AlarmStatus.State.class );
+        statePrototype.name().set( status );
+        statePrototype.creationDate().set( Instant.now() );
+        return builder.newInstance();
+    }
+}
diff --git a/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/StandardAlarmModelTest.java b/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/StandardAlarmModelTest.java
new file mode 100644
index 0000000..deaa8fe
--- /dev/null
+++ b/libraries/alarm/src/test/java/org/apache/polygene/library/alarm/StandardAlarmModelTest.java
@@ -0,0 +1,491 @@
+/*
+ *  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.polygene.library.alarm;
+
+import java.time.Instant;
+import java.util.List;
+import java.util.Locale;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class StandardAlarmModelTest
+    extends AbstractPolygeneTest
+{
+
+    @SuppressWarnings( { "unchecked" } )
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( TestAlarmModel.class );
+        module.services( AlarmSystemService.class );
+        new EntityTestAssembler().assemble( module );
+        module.entities( AlarmPointEntity.class );
+        module.values( AlarmEvent.class );
+        module.values( AlarmCategory.class );
+        module.values( AlarmStatus.class );
+        module.forMixin( AlarmHistory.class ).declareDefaults().maxSize().set( 10 );
+    }
+
+    @Mixins( StandardAlarmModelService.StandardAlarmModelMixin.class )
+    public interface TestAlarmModel
+        extends AlarmModel, ServiceComposite
+    {
+    }
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        unitOfWorkFactory.newUnitOfWork();
+    }
+
+    @Override
+    public void tearDown()
+        throws Exception
+    {
+        UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+        if( uow != null )
+        {
+            uow.discard();
+        }
+        super.tearDown();
+    }
+
+    @Test
+    public void testName()
+        throws Exception
+    {
+        StandardAlarmModelService.StandardAlarmModelMixin spi = new StandardAlarmModelService.StandardAlarmModelMixin();
+        assertEquals( "org.apache.polygene.library.alarm.model.standard", spi.modelName() );
+    }
+
+    @Test
+    public void testDescription()
+        throws Exception
+    {
+        StandardAlarmModelService.StandardAlarmModelMixin spi = new StandardAlarmModelService.StandardAlarmModelMixin();
+        boolean test1 = spi.modelDescription().toLowerCase().contains( "normal" );
+        boolean test2 = spi.modelDescription().toLowerCase().contains( "activated" );
+        boolean test3 = spi.modelDescription().toLowerCase().contains( "deactivated" );
+        boolean test4 = spi.modelDescription().toLowerCase().contains( "acknowledged" );
+        boolean test5 = spi.modelDescription().toLowerCase().contains( "activation" );
+        boolean test6 = spi.modelDescription().toLowerCase().contains( "deactivation" );
+        boolean test7 = spi.modelDescription().toLowerCase().contains( "acknowledge" );
+        assertTrue( test1 && test2 && test3 && test4 && test5 && test6 && test7 );
+
+        Locale english = new Locale( "en" );
+        test1 = spi.modelDescription( english ).toLowerCase().contains( "normal" );
+        test2 = spi.modelDescription( english ).toLowerCase().contains( "activated" );
+        test3 = spi.modelDescription( english ).toLowerCase().contains( "deactivated" );
+        test4 = spi.modelDescription( english ).toLowerCase().contains( "acknowledged" );
+        test5 = spi.modelDescription( english ).toLowerCase().contains( "activation" );
+        test6 = spi.modelDescription( english ).toLowerCase().contains( "deactivation" );
+        test7 = spi.modelDescription( english ).toLowerCase().contains( "acknowledge" );
+        assertTrue( test1 && test2 && test3 && test4 && test5 && test6 && test7 );
+    }
+
+    @Test
+    public void testTriggers()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        List<String> triggers = provider.alarmTriggers();
+        assertEquals( 3, triggers.size() );
+        int result = 0;
+        for( String trigger : triggers )
+        {
+            if( AlarmPoint.TRIGGER_ACTIVATE.equals( trigger ) )
+            {
+                result |= 1;
+            }
+            if( AlarmPoint.TRIGGER_DEACTIVATE.equals( trigger ) )
+            {
+                result |= 2;
+            }
+            if( AlarmPoint.TRIGGER_ACKNOWLEDGE.equals( trigger ) )
+            {
+                result |= 4;
+            }
+            if( AlarmPoint.TRIGGER_BLOCK.equals( trigger ) )
+            {
+                result |= 8;
+            }
+            if( AlarmPoint.TRIGGER_UNBLOCK.equals( trigger ) )
+            {
+                result |= 16;
+            }
+            if( AlarmPoint.TRIGGER_DISABLE.equals( trigger ) )
+            {
+                result |= 32;
+            }
+            if( AlarmPoint.TRIGGER_ENABLE.equals( trigger ) )
+            {
+                result |= 64;
+            }
+        }
+        assertEquals( 7, result );
+        assertEquals( AlarmPoint.STATUS_NORMAL, underTest.currentStatus().name( null ) );
+    }
+
+    @Test
+    public void testStateChangeFromNormal()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmPoint alarm = createAlarm( "Another 1" );
+        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
+        assertEquals( AlarmPoint.EVENT_ACTIVATION, event1.systemName().get() );
+
+        alarm = createAlarm( "Another 2" );
+        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
+        assertNull( event2 );
+
+        alarm = createAlarm( "Another 3" );
+        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
+        assertNull( event3 );
+    }
+
+    @Test
+    public void testStateChangeFromActivated()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmPoint alarm = createAlarm( "Another 1" );
+        alarm.activate();
+
+        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
+        assertNull( event1 );
+
+        alarm = createAlarm( "Another 2" );
+        alarm.activate();
+        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
+        assertEquals( AlarmPoint.EVENT_DEACTIVATION, event2.systemName().get() );
+
+        alarm = createAlarm( "Another 3" );
+        alarm.activate();
+        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
+        assertEquals( AlarmPoint.EVENT_ACKNOWLEDGEMENT, event3.systemName().get() );
+    }
+
+    @Test
+    public void testStateChangeFromAcknowledged()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmPoint alarm = createAlarm( "Another 1" );
+        alarm.activate();
+        alarm.acknowledge();
+
+        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
+        assertNull( event1 );
+
+        alarm = createAlarm( "Another 2" );
+        alarm.activate();
+        alarm.acknowledge();
+        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
+        assertEquals( AlarmPoint.EVENT_DEACTIVATION, event2.systemName().get() );
+
+        alarm = createAlarm( "Another 3" );
+        alarm.activate();
+        alarm.acknowledge();
+        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
+        assertNull( event3 );
+    }
+
+    @Test
+    public void testStateChangeFromDeactivated()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmPoint alarm = createAlarm( "Another 1" );
+        alarm.activate();
+        alarm.deactivate();
+        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
+        assertEquals( AlarmPoint.EVENT_ACTIVATION, event1.systemName().get() );
+
+        alarm = createAlarm( "Another 2" );
+        alarm.activate();
+        alarm.deactivate();
+        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
+        assertNull( event2 );
+
+        alarm = createAlarm( "Another 3" );
+        alarm.activate();
+        alarm.deactivate();
+        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
+        assertEquals( AlarmPoint.EVENT_ACKNOWLEDGEMENT, event3.systemName().get() );
+    }
+
+    @Test
+    public void testIllegalTrigger()
+        throws Exception
+    {
+        try
+        {
+            AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+            AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+            provider.evaluate( underTest, "my-trigger" );
+            fail( "IllegalArgumentException not thrown." );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Expected.
+        }
+    }
+
+    @Test
+    public void testNormalToActivated()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        underTest.activate();
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        Assert.assertEquals( AlarmPoint.STATUS_NORMAL, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        Assert.assertEquals( AlarmPoint.STATUS_ACTIVATED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testActivatedToDeactivated()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        underTest.activate();
+        underTest.deactivate();
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        Assert.assertEquals( AlarmPoint.STATUS_DEACTIVATED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testActivatedToAcknowledged()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        underTest.activate();
+        underTest.acknowledge();
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        Assert.assertEquals( AlarmPoint.STATUS_ACKNOWLEDGED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testDeactivatedToNormal()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        underTest.activate();
+        underTest.deactivate();
+        underTest.acknowledge();
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_DEACTIVATED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_NORMAL, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testAcknowledgedToNormal()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        underTest.activate();
+        underTest.acknowledge();
+        underTest.deactivate();
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACKNOWLEDGED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_NORMAL, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testConditionChanges1()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        underTest.updateCondition( false );
+        AlarmEvent event = underTest.history().lastEvent();
+        assertNull( "Generated an event but should have not.", event );
+    }
+
+    @Test
+    public void testConditionChanges2()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        underTest.updateCondition( true );
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_NORMAL, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACTIVATED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testConditionChanges3()
+        throws Exception
+    {
+        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
+        underTest.updateCondition( true );
+        underTest.updateCondition( false );
+        AlarmEvent event = underTest.history().lastEvent();
+
+        AlarmStatus oldstate = event.oldStatus().get();
+        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
+
+        AlarmStatus newstate = event.newStatus().get();
+        assertEquals( AlarmPoint.STATUS_DEACTIVATED, newstate.name( null ) );
+
+        AlarmPoint eventalarm = getAlarm( event.identity().get() );
+        assertEquals( underTest, eventalarm );
+    }
+
+    @Test
+    public void testComputeCondition()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmStatus s1 = createStatus( AlarmPoint.STATUS_NORMAL );
+        assertFalse( provider.computeCondition( s1 ) );
+        AlarmStatus s2 = createStatus( AlarmPoint.STATUS_ACTIVATED );
+        assertTrue( provider.computeCondition( s2 ) );
+        AlarmStatus s3 = createStatus( AlarmPoint.STATUS_DEACTIVATED );
+        assertFalse( provider.computeCondition( s3 ) );
+        AlarmStatus s4 = createStatus( AlarmPoint.STATUS_ACKNOWLEDGED );
+        assertTrue( provider.computeCondition( s4 ) );
+    }
+
+    @Test
+    public void testComputeTrigger()
+        throws Exception
+    {
+        AlarmModel provider = serviceFinder.findService( AlarmModel.class ).get();
+        AlarmStatus s1 = createStatus( AlarmPoint.STATUS_NORMAL );
+        AlarmStatus s2 = createStatus( AlarmPoint.STATUS_ACTIVATED );
+        AlarmStatus s3 = createStatus( AlarmPoint.STATUS_DEACTIVATED );
+        AlarmStatus s4 = createStatus( AlarmPoint.STATUS_ACKNOWLEDGED );
+        String trigger1 = provider.computeTrigger( s1, true );
+        String trigger2 = provider.computeTrigger( s2, true );
+        String trigger3 = provider.computeTrigger( s3, true );
+        String trigger4 = provider.computeTrigger( s4, true );
+        String trigger5 = provider.computeTrigger( s1, false );
+        String trigger6 = provider.computeTrigger( s2, false );
+        String trigger7 = provider.computeTrigger( s3, false );
+        String trigger8 = provider.computeTrigger( s4, false );
+        assertEquals( AlarmPoint.TRIGGER_ACTIVATE, trigger1 );
+        assertEquals( null, trigger2 );
+        assertEquals( AlarmPoint.TRIGGER_ACTIVATE, trigger3 );
+        assertEquals( null, trigger4 );
+        assertEquals( null, trigger5 );
+        assertEquals( AlarmPoint.TRIGGER_DEACTIVATE, trigger6 );
+        assertEquals( null, trigger7 );
+        assertEquals( AlarmPoint.TRIGGER_DEACTIVATE, trigger8 );
+    }
+
+    private AlarmPoint createAlarm( String name )
+    {
+        UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+        EntityBuilder<AlarmPoint> builder = uow.newEntityBuilder( AlarmPoint.class );
+        builder.instance().category().set( createCategory( "StandardModelTest" ) );
+        AlarmPoint.AlarmState state = builder.instanceFor( AlarmPoint.AlarmState.class );
+        state.currentStatus().set( createStatus( AlarmPoint.STATUS_NORMAL ) );
+        state.description().set( "Test Description" );
+        state.systemName().set( name );
+        return builder.newInstance();
+    }
+
+    private AlarmCategory createCategory( String name )
+    {
+        ValueBuilder<AlarmCategory> builder = valueBuilderFactory.newValueBuilder( AlarmCategory.class );
+        builder.prototype().name().set( name );
+        return builder.newInstance();
+    }
+
+    private AlarmPoint getAlarm( Identity identity )
+    {
+        UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+        return uow.get( AlarmPoint.class, identity );
+    }
+
+    private AlarmStatus createStatus( String status )
+    {
+        ValueBuilder<AlarmStatus> builder = valueBuilderFactory.newValueBuilder( AlarmStatus.class );
+        AlarmStatus.State statePrototype = builder.prototypeFor( AlarmStatus.State.class );
+        statePrototype.name().set( status );
+        statePrototype.creationDate().set( Instant.now() );
+        return builder.newInstance();
+    }
+}
diff --git a/libraries/alarm/src/test/java/org/qi4j/library/alarm/AlarmHistoryImplTest.java b/libraries/alarm/src/test/java/org/qi4j/library/alarm/AlarmHistoryImplTest.java
deleted file mode 100644
index 58db8d9..0000000
--- a/libraries/alarm/src/test/java/org/qi4j/library/alarm/AlarmHistoryImplTest.java
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright 2005-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import org.junit.Test;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import java.util.Map;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.*;
-
-public class AlarmHistoryImplTest
-    extends AbstractQi4jTest
-    implements AlarmListener
-{
-    private int eventCounter = 0;
-    private AlarmSystem alarmSystem;
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( TestAlarmModel.class );
-        module.services( AlarmSystemService.class );
-        module.entities( AlarmPointEntity.class );
-        new EntityTestAssembler().assemble( module );
-        module.values( AlarmStatus.class );
-        module.values( AlarmCategory.class );
-        module.values( AlarmEvent.class );
-        module.entities( AlarmPointEntity.class );
-        module.forMixin( AlarmHistory.class ).declareDefaults().maxSize().set( 30 );
-    }
-
-    @Mixins( SimpleAlarmModelService.SimpleAlarmModelMixin.class )
-    public interface TestAlarmModel
-        extends AlarmModel, ServiceComposite
-    {
-    }
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        module.newUnitOfWork();
-    }
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        if (module.isUnitOfWorkActive())
-        {
-            UnitOfWork uow = module.currentUnitOfWork();
-            uow.discard();
-        }
-        super.tearDown();
-    }
-
-    @Test
-    public void testEmpty()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "testEmpty" );
-        AlarmHistory hist = underTest.history();
-        AlarmEvent event1 = hist.firstEvent();
-        AlarmEvent event2 = hist.lastEvent();
-        assertNull( event1 );
-        assertNull( event2 );
-        assertEquals( "Activate Counter", 0, hist.activateCounter() );
-    }
-
-    @Test
-    public void testFirstNotLast()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "testFirstNotLast" );
-        underTest.updateCondition( true );
-        underTest.updateCondition( false );
-        AlarmHistory hist = underTest.history();
-        AlarmEvent event1 = hist.firstEvent();
-        AlarmEvent event2 = hist.lastEvent();
-        assertFalse( event1.equals( event2 ) );
-        assertEquals( AlarmPoint.STATUS_ACTIVATED, event1.newStatus().get().name(null) );
-        assertEquals( AlarmPoint.STATUS_NORMAL, event2.newStatus().get().name(null) );
-    }
-
-    @Test
-    public void testGetPosition()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "testGetPosition" );
-        alarmSystem.addAlarmListener( this );
-        AlarmHistory hist = underTest.history();
-        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
-        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
-        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
-        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
-        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
-        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
-
-        assertEquals( 5, eventCounter );
-        assertEquals( 5, hist.allAlarmEvents().get().size() );
-
-        AlarmEvent event = hist.eventAt( -1 );
-        assertNull( event );
-        event = hist.eventAt( 5 );
-        assertNull( event );
-        event = hist.eventAt( 0 );
-        assertEquals( "activation", event.systemName().get() );
-        event = hist.eventAt( 1 );
-        assertEquals( "deactivation", event.systemName().get() );
-        event = hist.eventAt( 2 );
-        assertEquals( "activation", event.systemName().get() );
-        event = hist.eventAt( 3 );
-        assertEquals( "deactivation", event.systemName().get() );
-        event = hist.eventAt( 4 );
-        assertEquals( "activation", event.systemName().get() );
-    }
-
-    @Test
-    public void testGetPositionFromLast()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "testGetPositionFromLast" );
-        alarmSystem.addAlarmListener( this );
-        AlarmHistory hist = underTest.history();
-        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
-        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
-        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
-        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
-        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
-        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
-
-        assertEquals( 5, eventCounter );
-        assertEquals( 5, hist.allAlarmEvents().get().size() );
-
-        AlarmEvent event = hist.eventAtEnd( -1 );
-        assertNull( event );
-        event = hist.eventAtEnd( 5 );
-        assertNull( event );
-        event = hist.eventAtEnd( 4 );
-        assertEquals( "activation", event.systemName().get() );
-        event = hist.eventAtEnd( 3 );
-        assertEquals( "deactivation", event.systemName().get() );
-        event = hist.eventAtEnd( 2 );
-        assertEquals( "activation", event.systemName().get() );
-        event = hist.eventAtEnd( 1 );
-        assertEquals( "deactivation", event.systemName().get() );
-        event = hist.eventAtEnd( 0 );
-        assertEquals( "activation", event.systemName().get() );
-    }
-
-    @Test
-    public void testCounters()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "testCounters" );
-        AlarmHistory hist = underTest.history();
-        Map<String, Integer> counters = hist.counters().get();
-
-        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
-        verifyCounters( counters, 1, 0 );
-
-        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
-        verifyCounters( counters, 1, 1 );
-
-        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
-        verifyCounters( counters, 2, 1 );
-
-        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
-        verifyCounters( counters, 2, 2 );
-
-        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
-        verifyCounters( counters, 2, 2 );
-
-        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
-        verifyCounters( counters, 3, 2 );
-
-        int activateCounters = hist.activateCounter();
-        assertEquals( 3, activateCounters );
-
-        hist.resetActivateCounter();
-        verifyCounters( counters, 0, 2 );
-
-        hist.resetAllCounters();
-        verifyCounters( counters, 0, 0 );
-    }
-
-    private void verifyCounters( Map counters, int c1, int c2 )
-    {
-        Number n1 = (Number) counters.get( AlarmPoint.TRIGGER_ACTIVATE );
-        Number n2 = (Number) counters.get( AlarmPoint.TRIGGER_DEACTIVATE );
-        if( n1 == null )
-        {
-            assertEquals( 0, c1 );
-        }
-        else
-        {
-            assertEquals( c1, n1 );
-        }
-
-        if( n2 == null )
-        {
-            assertEquals( 0, c2 );
-        }
-        else
-        {
-            assertEquals( c2, n2 );
-        }
-    }
-
-    @Test
-    public void testSetMaxSize()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "testSetMaxSize" );
-        alarmSystem.addAlarmListener( this );
-        AlarmHistory hist = underTest.history();
-        assertEquals( 0, hist.allAlarmEvents().get().size() );
-        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
-        assertEquals( 1, hist.allAlarmEvents().get().size() );
-        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
-        assertEquals( 2, hist.allAlarmEvents().get().size() );
-        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
-        assertEquals( 3, hist.allAlarmEvents().get().size() );
-        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
-        assertEquals( 4, hist.allAlarmEvents().get().size() );
-
-        int maxsize = hist.maxSize().get();
-        assertEquals( 30, maxsize );
-
-        hist.maxSize().set( 3 );    // The Zest version doesn't intercept the maxSize().set() method and purge the old
-        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE ); // so we do another event to purge.
-        assertEquals( 3, hist.allAlarmEvents().get().size() );
-
-        hist.maxSize().set( 0 );
-        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE ); // so we do another event to purge.
-        assertEquals( 0, hist.allAlarmEvents().get().size() );
-        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
-        assertEquals( 0, hist.allAlarmEvents().get().size() );
-        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
-        assertEquals( 0, hist.allAlarmEvents().get().size() );
-        hist.maxSize().set( 2 );
-        assertEquals( 0, hist.allAlarmEvents().get().size() );
-        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
-        assertEquals( 1, hist.allAlarmEvents().get().size() );
-        underTest.trigger( AlarmPoint.TRIGGER_DEACTIVATE );
-        assertEquals( 2, hist.allAlarmEvents().get().size() );
-        underTest.trigger( AlarmPoint.TRIGGER_ACTIVATE );
-        assertEquals( 2, hist.allAlarmEvents().get().size() );
-        assertEquals( 11, eventCounter );
-    }
-
-    public void alarmFired( AlarmEvent event )
-    {
-        eventCounter++;
-    }
-
-    private AlarmPoint createAlarm( String name )
-    {
-        ServiceReference<AlarmSystem> ref = module.findService( AlarmSystem.class );
-        alarmSystem = ref.get();
-        return alarmSystem.createAlarm( name, createCategory( "AlarmHistoryTest" ) );
-    }
-
-    private AlarmCategory createCategory( String name )
-    {
-        ValueBuilder<AlarmCategory> builder = module.newValueBuilder( AlarmCategory.class );
-        builder.prototype().name().set( name );
-        return builder.newInstance();
-    }
-
-
-}
diff --git a/libraries/alarm/src/test/java/org/qi4j/library/alarm/AlarmPointImplTest.java b/libraries/alarm/src/test/java/org/qi4j/library/alarm/AlarmPointImplTest.java
deleted file mode 100644
index c1987a6..0000000
--- a/libraries/alarm/src/test/java/org/qi4j/library/alarm/AlarmPointImplTest.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright 2005-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import java.util.List;
-import java.util.Locale;
-import org.junit.Test;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-
-public class AlarmPointImplTest extends AbstractQi4jTest
-    implements AlarmListener
-{
-    private int fired;
-    private AlarmSystem alarmSystem;
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( TestAlarmModel.class );
-        module.services( AlarmSystemService.class );
-        module.entities( AlarmPointEntity.class );
-        module.values( AlarmEvent.class );
-        module.values( AlarmCategory.class );
-        module.values( AlarmStatus.class );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Mixins( SimpleAlarmModelService.SimpleAlarmModelMixin.class )
-    public interface TestAlarmModel
-        extends AlarmModel, ServiceComposite
-    {
-    }
-
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        module.newUnitOfWork();
-    }
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        if( module.isUnitOfWorkActive() )
-        {
-            UnitOfWork uow = module.currentUnitOfWork();
-            uow.discard();
-        }
-        super.tearDown();
-    }
-
-    @Test
-    public void testCreationProblems()
-        throws Exception
-    {
-        try
-        {
-            createAlarm( null );
-            fail( "AlarmPoint created with null name." );
-        }
-        catch( ConstraintViolationException e )
-        {
-            // expected.
-        }
-        try
-        {
-            createAlarm( "" );
-            fail( "AlarmPoint created with empty string name." );
-        }
-        catch( ConstraintViolationException e )
-        {
-            // expected.
-        }
-        try
-        {
-            createAlarm( "\n \n" );
-            fail( "AlarmPoint created with white space name." );
-        }
-        catch( ConstraintViolationException e )
-        {
-            // expected.
-        }
-    }
-
-    @Test
-    public void testName()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "TestCase AlarmPoint" );
-        assertEquals( "TestCase AlarmPoint", underTest.name() );
-    }
-
-    @Test
-    public void testDescription()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "TestCase AlarmPoint" );
-//        assertEquals( "This is a default Locale description of a testcase AlarmPoint.", underTest.description() );
-
-        Locale swedish = new Locale( "sv" );
-        assertEquals( "Detta \u00E5r en svensk beskrivning av ett testlarm.", underTest.description( swedish ) );
-
-        Locale english = Locale.UK;
-        assertEquals( "This is a UK Locale description of a testcase Alarm.", underTest.description( english ) );
-    }
-
-    @Test
-    public void testState()
-    {
-        AlarmPoint underTest = createAlarm( "testState" );
-        assertEquals( AlarmPoint.STATUS_NORMAL, underTest.currentStatus().name( null ) );
-        boolean condition = underTest.currentCondition();
-        assertEquals( false, condition );
-    }
-
-    @Test
-    public void testAttributes()
-    {
-        AlarmPoint underTest = createAlarm( "TestCase AlarmPoint" );
-
-        String alarmText = underTest.attribute( "text" );
-        assertNull( alarmText );
-
-        underTest.setAttribute( "text", "TestCase AlarmPoint" );
-        assertEquals( "TestCase AlarmPoint", underTest.attribute( "text" ) );
-
-        List<String> names = underTest.attributeNames();
-        assertEquals( 1, names.size() );
-
-        underTest.setAttribute( "text", null );
-        names = underTest.attributeNames();
-        assertEquals( 0, names.size() );
-    }
-
-    @Test
-    public void testInvalidTrigger()
-        throws Exception
-    {
-        try
-        {
-            AlarmPoint underTest = createAlarm( "TestCase AlarmPoint" );
-            underTest.trigger( "my-special-trigger" );
-            fail( "IllegalArgumentException was not thrown." );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Expected.
-        }
-    }
-
-    @Test
-    public void testNoEvent()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "TestCase AlarmPoint" );
-        alarmSystem.addAlarmListener( this );
-        underTest.deactivate();
-        assertEquals( 0, fired );
-    }
-
-    @Test
-    public void testListener()
-    {
-        AlarmPoint underTest = createAlarm( "TestCase AlarmPoint" );
-        try
-        {
-            alarmSystem.removeAlarmListener( null );  // make sure it fails.
-            fail( "Could remove null listener" );
-        }
-        catch( ConstraintViolationException e )
-        {
-            // expected
-        }
-        alarmSystem.removeAlarmListener( this );  // make sure it doesn't fail.
-
-        alarmSystem.addAlarmListener( this );
-        underTest.activate();
-        assertEquals( 1, fired );
-        alarmSystem.addAlarmListener( this );
-        underTest.deactivate();
-        assertEquals( 3, fired );
-        alarmSystem.removeAlarmListener( this );
-        underTest.activate();
-        assertEquals( 4, fired );
-        alarmSystem.removeAlarmListener( this );
-        underTest.deactivate();
-        assertEquals( 4, fired );
-    }
-
-    public void alarmFired( AlarmEvent event )
-    {
-        fired++;
-    }
-
-    private AlarmPoint createAlarm( String name )
-    {
-        ServiceReference<AlarmSystem> ref = module.findService( AlarmSystem.class );
-        alarmSystem = ref.get();
-        return alarmSystem.createAlarm( name, createCategory( "AlarmPointImplTest" ) );
-    }
-
-    private AlarmCategory createCategory( String name )
-    {
-        ValueBuilder<AlarmCategory> builder = module.newValueBuilder( AlarmCategory.class );
-        builder.prototype().name().set( name );
-        return builder.newInstance();
-    }
-}
diff --git a/libraries/alarm/src/test/java/org/qi4j/library/alarm/AlarmProxyTest.java b/libraries/alarm/src/test/java/org/qi4j/library/alarm/AlarmProxyTest.java
deleted file mode 100644
index 9afaa5d..0000000
--- a/libraries/alarm/src/test/java/org/qi4j/library/alarm/AlarmProxyTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.alarm;
-
-import org.junit.Test;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.junit.Assert.assertThat;
-
-public class AlarmProxyTest extends AbstractQi4jTest
-{
-    // START SNIPPET: documentation
-    @Service
-    private AlarmProxy.Factory factory;
-
-    private AlarmProxy myAlarmPoint;
-    // END SNIPPET: documentation
-
-    // START SNIPPET: documentation
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new AlarmSystemAssembler().assemble( module );
-        // END SNIPPET: documentation
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Test
-    public void givenAlarmPointWhenActivateExpectActivationEvent()
-        throws Exception
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-// START SNIPPET: documentation
-            myAlarmPoint = factory.create( "This Alarm Identity", "ProActiveCRM", "Sales", AlarmClass.B );
-            myAlarmPoint.history().maxSize().set( 20 );
-// END SNIPPET: documentation
-
-// START SNIPPET: documentation
-            myAlarmPoint.activate();
-// END SNIPPET: documentation
-            uow.complete();
-            assertThat( myAlarmPoint.history().activateCounter(), equalTo( 1 ) );
-            AlarmEvent event = myAlarmPoint.history().firstEvent();
-            assertThat( event, notNullValue() );
-            assertThat( event.alarmIdentity().get(), equalTo( "This Alarm Identity" ) );
-            assertThat( event.newStatus().get().name( null ), equalTo( "Activated" ) );
-            assertThat( event.oldStatus().get().name( null ), equalTo( "Normal" ) );
-        }
-        catch( Exception e )
-        {
-            uow.discard();
-            throw e;
-        }
-    }
-}
diff --git a/libraries/alarm/src/test/java/org/qi4j/library/alarm/AlarmServiceTest.java b/libraries/alarm/src/test/java/org/qi4j/library/alarm/AlarmServiceTest.java
deleted file mode 100644
index cd4483f..0000000
--- a/libraries/alarm/src/test/java/org/qi4j/library/alarm/AlarmServiceTest.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright 2005-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import org.junit.Test;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import java.util.List;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.*;
-
-public class AlarmServiceTest
-    extends AbstractQi4jTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( TestAlarmModel1.class ).setMetaInfo( new AlarmModelDescriptor("Simple", false) );
-        module.services( TestAlarmModel2.class ).setMetaInfo( new AlarmModelDescriptor("Standard", true) );
-        module.services( AlarmSystemService.class );
-        module.entities( AlarmPointEntity.class );
-        module.values( AlarmStatus.class );
-        module.values( AlarmCategory.class );
-        module.values( AlarmEvent.class );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    @Mixins( SimpleAlarmModelService.SimpleAlarmModelMixin.class )
-    public interface TestAlarmModel1
-        extends AlarmModel, ServiceComposite
-    {
-    }
-
-    @Mixins( StandardAlarmModelService.StandardAlarmModelMixin.class )
-    public interface TestAlarmModel2
-        extends AlarmModel, ServiceComposite
-    {
-    }
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        module.newUnitOfWork();
-    }
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        if (module.isUnitOfWorkActive())
-        {
-            UnitOfWork uow = module.currentUnitOfWork();
-            uow.discard();
-        }
-        super.tearDown();
-    }
-
-    @Test
-    public void testGetAlarmModels()
-    {
-        AlarmSystem alarmService = (AlarmSystem) module.findService( AlarmSystem.class ).get();
-        List<AlarmModelDescriptor> models = alarmService.alarmModels();
-        assertNotNull( models );
-        assertEquals( 2, models.size() );
-    }
-
-    @Test
-    public void testDefaultModel()
-        throws Exception
-    {
-        AlarmSystem alarmService = (AlarmSystem) module.findService( AlarmSystem.class ).get();
-        List<AlarmModelDescriptor> models = alarmService.alarmModels();
-        assertNotNull( models );
-        assertEquals( 2, models.size() );
-
-        AlarmModel model = alarmService.defaultAlarmModel();
-        assertNotNull( model );
-    }
-
-    @Test
-    public void testListeners()
-        throws Exception
-    {
-        AlarmSystem alarmService = (AlarmSystem) module.findService( AlarmSystem.class ).get();
-        AlarmPoint alarm = alarmService.createAlarm( "TestAlarm", createCategory("AlarmServiceTest") );
-
-        CountingListener listener1 = new CountingListener();
-        ExceptionThrowingListener listener2 = new ExceptionThrowingListener();
-        ErrorThrowingListener listener3 = new ErrorThrowingListener();
-        alarmService.addAlarmListener( listener1 );
-        alarmService.addAlarmListener( listener3 );
-        alarmService.addAlarmListener( listener1 );
-        try
-        {
-            alarm.activate();
-            fail( "InternalError was expected to be thrown." );
-        }
-        catch( InternalError e )
-        {
-            // Expected. If an Error is thrown it should not be captured anywhere.
-        }
-        assertEquals( 1, listener1.getCounter() );      // One time, because the second listener would not be called.
-
-        alarmService.removeAlarmListener( listener3 );
-        alarmService.removeAlarmListener( listener1 );
-        alarmService.addAlarmListener( listener2 );
-        alarmService.addAlarmListener( listener1 );   // We should now have, 'counting', 'exception', 'counting' in the list.
-        alarm.deactivate();   // No Exception should be thrown. The fireAlarm() should swallow it and ensure that
-        // all listeners are called and then return.
-        assertEquals( 3, listener1.getCounter() );
-
-        List listeners = alarmService.alarmListeners();
-        assertEquals( "Listeners registered.", 3, listeners.size() );
-
-        alarmService.removeAlarmListener( listener1 );
-        listeners = alarmService.alarmListeners();
-        assertEquals( "Listeners registered.", 2, listeners.size() );
-
-        alarmService.removeAlarmListener( listener1 );
-        listeners = alarmService.alarmListeners();
-        assertEquals( "Listeners registered.", 1, listeners.size() );
-
-        alarmService.removeAlarmListener( listener1 );
-        listeners = alarmService.alarmListeners();
-        assertEquals( "Listeners registered.", 1, listeners.size() );
-
-        alarmService.removeAlarmListener( listener2 );
-        listeners = alarmService.alarmListeners();
-        System.out.println( listeners );
-        assertEquals( "Listeners registered.", 0, listeners.size() );
-
-        alarmService.removeAlarmListener( listener2 );
-        listeners = alarmService.alarmListeners();
-        assertEquals( "Listeners registered.", 0, listeners.size() );
-
-        try
-        {
-            alarmService.removeAlarmListener( null );
-            fail( "Should not be able to call removeAlarmListener with null argument." );
-        }
-        catch( ConstraintViolationException e )
-        {
-            // expected
-        }
-        listeners = alarmService.alarmListeners();
-        assertEquals( "Listeners registered.", 0, listeners.size() );
-    }
-
-    private AlarmCategory createCategory( String name )
-    {
-        ValueBuilder<AlarmCategory> builder = module.newValueBuilder( AlarmCategory.class );
-        builder.prototype().name().set( name );
-        return builder.newInstance();
-    }
-
-
-
-    private class CountingListener
-        implements AlarmListener
-    {
-
-        private int m_Counter;
-
-        public CountingListener()
-        {
-            m_Counter = 0;
-        }
-
-        public void alarmFired( AlarmEvent event )
-        {
-            m_Counter = getCounter() + 1;
-        }
-
-        public int getCounter()
-        {
-            return m_Counter;
-        }
-    }
-
-    private class ExceptionThrowingListener
-        implements AlarmListener
-    {
-
-        public void alarmFired( AlarmEvent event )
-            throws IllegalArgumentException
-        {
-            throw new IllegalArgumentException( "This is an intentional Exception, and it is not a sign of a problem." );
-        }
-    }
-
-    private class ErrorThrowingListener
-        implements AlarmListener
-    {
-
-        public void alarmFired( AlarmEvent event )
-        {
-            throw new InternalError( "This is an intentional java.lang.Error." );
-        }
-    }
-}
diff --git a/libraries/alarm/src/test/java/org/qi4j/library/alarm/ExtendedAlarmModelTest.java b/libraries/alarm/src/test/java/org/qi4j/library/alarm/ExtendedAlarmModelTest.java
deleted file mode 100644
index 07dd367..0000000
--- a/libraries/alarm/src/test/java/org/qi4j/library/alarm/ExtendedAlarmModelTest.java
+++ /dev/null
@@ -1,976 +0,0 @@
-/*
- * Copyright 2006-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import org.junit.Test;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-public class ExtendedAlarmModelTest
-    extends AbstractQi4jTest
-{
-
-    @SuppressWarnings( { "unchecked" } )
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( TestAlarmModel.class );
-        module.services( AlarmSystemService.class );
-        new EntityTestAssembler().assemble( module );
-        module.entities( AlarmPointEntity.class );
-        module.forMixin( AlarmHistory.class ).declareDefaults().maxSize().set( 10 );
-        module.values( AlarmEvent.class );
-        module.values( AlarmCategory.class );
-        module.values( AlarmStatus.class );
-    }
-
-    @Mixins( ExtendedAlarmModelService.ExtendedAlarmModelMixin.class )
-    public interface TestAlarmModel
-        extends AlarmModel, ServiceComposite
-    {
-    }
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        module.newUnitOfWork();
-    }
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        if( uow != null )
-        {
-            uow.discard();
-        }
-        super.tearDown();
-    }
-
-    @Test
-    public void testDescription()
-        throws Exception
-    {
-        AlarmModel provider = module.findService( AlarmModel.class ).get();
-        boolean test1 = provider.modelDescription().toLowerCase().contains( "normal" );
-        boolean test2 = provider.modelDescription().toLowerCase().contains( "activated" );
-        boolean test3 = provider.modelDescription().toLowerCase().contains( "deactivated" );
-        boolean test4 = provider.modelDescription().toLowerCase().contains( "acknowledged" );
-        boolean test5 = provider.modelDescription().toLowerCase().contains( "activation" );
-        boolean test6 = provider.modelDescription().toLowerCase().contains( "deactivation" );
-        boolean test7 = provider.modelDescription().toLowerCase().contains( "acknowledge" );
-        boolean test8 = provider.modelDescription().toLowerCase().contains( "block" );
-        boolean test9 = provider.modelDescription().toLowerCase().contains( "unblock" );
-        boolean test10 = provider.modelDescription().toLowerCase().contains( "disable" );
-        boolean test11 = provider.modelDescription().toLowerCase().contains( "enable" );
-        assertTrue( test1 && test2 && test3 && test4 && test5 && test6 && test7 && test8 && test9 && test10 && test11 );
-
-        Locale english = new Locale( "en" );
-        test1 = provider.modelDescription( english ).toLowerCase().contains( "normal" );
-        test2 = provider.modelDescription( english ).toLowerCase().contains( "activated" );
-        test3 = provider.modelDescription( english ).toLowerCase().contains( "deactivated" );
-        test4 = provider.modelDescription( english ).toLowerCase().contains( "acknowledged" );
-        test5 = provider.modelDescription( english ).toLowerCase().contains( "activation" );
-        test6 = provider.modelDescription( english ).toLowerCase().contains( "deactivation" );
-        test7 = provider.modelDescription( english ).toLowerCase().contains( "acknowledge" );
-        test8 = provider.modelDescription( english ).toLowerCase().contains( "block" );
-        test9 = provider.modelDescription( english ).toLowerCase().contains( "unblock" );
-        test10 = provider.modelDescription( english ).toLowerCase().contains( "disable" );
-        test11 = provider.modelDescription( english ).toLowerCase().contains( "enable" );
-        assertTrue( test1 && test2 && test3 && test4 && test5 && test6 && test7 && test8 && test9 && test10 && test11 );
-    }
-
-    @Test
-    public void testTriggers()
-        throws Exception
-    {
-        AlarmModel provider = module.findService( AlarmModel.class ).get();
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        List<String> triggers = provider.alarmTriggers();
-        assertEquals( 7, triggers.size() );
-        int result = 0;
-        for( String trigger : triggers )
-        {
-            if( AlarmPoint.TRIGGER_ACTIVATE.equals( trigger ) )
-            {
-                result |= 1;
-            }
-            if( AlarmPoint.TRIGGER_DEACTIVATE.equals( trigger ) )
-            {
-                result |= 2;
-            }
-            if( AlarmPoint.TRIGGER_ACKNOWLEDGE.equals( trigger ) )
-            {
-                result |= 4;
-            }
-            if( AlarmPoint.TRIGGER_BLOCK.equals( trigger ) )
-            {
-                result |= 8;
-            }
-            if( AlarmPoint.TRIGGER_UNBLOCK.equals( trigger ) )
-            {
-                result |= 16;
-            }
-            if( AlarmPoint.TRIGGER_DISABLE.equals( trigger ) )
-            {
-                result |= 32;
-            }
-            if( AlarmPoint.TRIGGER_ENABLE.equals( trigger ) )
-            {
-                result |= 64;
-            }
-        }
-        assertEquals( 127, result );
-        assertEquals( AlarmPoint.STATUS_NORMAL, underTest.currentStatus().name( null ) );
-    }
-
-    @Test
-    public void testStateChangeFromNormal()
-        throws Exception
-    {
-        AlarmModel provider = module.findService( AlarmModel.class ).get();
-        AlarmPoint alarm = createAlarm( "Another 1" );
-        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
-        assertEquals( AlarmPoint.EVENT_ACTIVATION, event1.systemName().get() );
-
-        alarm = createAlarm( "Another 2" );
-        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
-        assertNull( event2 );
-
-        alarm = createAlarm( "Another 3" );
-        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
-        assertNull( event3 );
-
-        alarm = createAlarm( "Another 4" );
-        AlarmEvent event4 = provider.evaluate( alarm, AlarmPoint.TRIGGER_BLOCK );
-        assertEquals( AlarmPoint.EVENT_BLOCKING, event4.systemName().get() );
-
-        alarm = createAlarm( "Another 5" );
-        AlarmEvent event5 = provider.evaluate( alarm, AlarmPoint.TRIGGER_UNBLOCK );
-        assertNull( event5 );
-
-        alarm = createAlarm( "Another 6" );
-        AlarmEvent event6 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DISABLE );
-        assertEquals( AlarmPoint.EVENT_DISABLING, event6.systemName().get() );
-
-        alarm = createAlarm( "Another 7" );
-        AlarmEvent event7 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ENABLE );
-        assertNull( event7 );
-    }
-
-    @Test
-    public void testStateChangeFromActivated()
-        throws Exception
-    {
-        AlarmModel provider = module.findService( AlarmModel.class ).get();
-        AlarmPoint alarm = createAlarm( "Another 1" );
-        alarm.activate();
-
-        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
-        assertNull( event1 );
-
-        alarm = createAlarm( "Another 2" );
-        alarm.activate();
-        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
-        assertEquals( AlarmPoint.EVENT_DEACTIVATION, event2.systemName().get() );
-
-        alarm = createAlarm( "Another 3" );
-        alarm.activate();
-        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
-        assertEquals( AlarmPoint.EVENT_ACKNOWLEDGEMENT, event3.systemName().get() );
-
-        alarm = createAlarm( "Another 4" );
-        alarm.activate();
-        AlarmEvent event4 = provider.evaluate( alarm, AlarmPoint.TRIGGER_BLOCK );
-        assertEquals( AlarmPoint.EVENT_BLOCKING, event4.systemName().get() );
-
-        alarm = createAlarm( "Another 5" );
-        alarm.activate();
-        AlarmEvent event5 = provider.evaluate( alarm, AlarmPoint.TRIGGER_UNBLOCK );
-        assertNull( event5 );
-
-        alarm = createAlarm( "Another 6" );
-        alarm.activate();
-        AlarmEvent event6 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DISABLE );
-        assertEquals( AlarmPoint.EVENT_DISABLING, event6.systemName().get() );
-
-        alarm = createAlarm( "Another 7" );
-        alarm.activate();
-        AlarmEvent event7 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ENABLE );
-        assertNull( event7 );
-    }
-
-    @Test
-    public void testStateChangeFromAcknowledged()
-        throws Exception
-    {
-        AlarmModel provider = module.findService( AlarmModel.class ).get();
-        AlarmPoint alarm = createAlarm( "Another 1" );
-        alarm.activate();
-        alarm.acknowledge();
-
-        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
-        assertNull( event1 );
-
-        alarm = createAlarm( "Another 2" );
-        alarm.activate();
-        alarm.acknowledge();
-        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
-        assertEquals( AlarmPoint.EVENT_DEACTIVATION, event2.systemName().get() );
-
-        alarm = createAlarm( "Another 3" );
-        alarm.activate();
-        alarm.acknowledge();
-        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
-        assertNull( event3 );
-
-        alarm = createAlarm( "Another 4" );
-        alarm.activate();
-        alarm.acknowledge();
-        AlarmEvent event4 = provider.evaluate( alarm, AlarmPoint.TRIGGER_BLOCK );
-        assertEquals( AlarmPoint.EVENT_BLOCKING, event4.systemName().get() );
-
-        alarm = createAlarm( "Another 5" );
-        alarm.activate();
-        alarm.acknowledge();
-        AlarmEvent event5 = provider.evaluate( alarm, AlarmPoint.TRIGGER_UNBLOCK );
-        assertNull( event5 );
-
-        alarm = createAlarm( "Another 6" );
-        alarm.activate();
-        alarm.acknowledge();
-        AlarmEvent event6 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DISABLE );
-        assertEquals( AlarmPoint.EVENT_DISABLING, event6.systemName().get() );
-
-        alarm = createAlarm( "Another 7" );
-        alarm.activate();
-        alarm.acknowledge();
-        AlarmEvent event7 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ENABLE );
-        assertNull( event7 );
-    }
-
-    @Test
-    public void testStateChangeFromDeactivated()
-        throws Exception
-    {
-        AlarmModel provider = module.findService( AlarmModel.class ).get();
-        AlarmPoint alarm = createAlarm( "Another 1" );
-        alarm.activate();
-        alarm.deactivate();
-        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
-        assertEquals( AlarmPoint.EVENT_ACTIVATION, event1.systemName().get() );
-
-        alarm = createAlarm( "Another 2" );
-        alarm.activate();
-        alarm.deactivate();
-        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
-        assertNull( event2 );
-
-        alarm = createAlarm( "Another 3" );
-        alarm.activate();
-        alarm.deactivate();
-        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
-        assertEquals( AlarmPoint.EVENT_ACKNOWLEDGEMENT, event3.systemName().get() );
-
-        alarm = createAlarm( "Another 4" );
-        alarm.activate();
-        alarm.deactivate();
-        AlarmEvent event4 = provider.evaluate( alarm, AlarmPoint.TRIGGER_BLOCK );
-        assertEquals( AlarmPoint.EVENT_BLOCKING, event4.systemName().get() );
-
-        alarm = createAlarm( "Another 5" );
-        alarm.activate();
-        alarm.deactivate();
-        AlarmEvent event5 = provider.evaluate( alarm, AlarmPoint.TRIGGER_UNBLOCK );
-        assertNull( event5 );
-
-        alarm = createAlarm( "Another 6" );
-        alarm.activate();
-        alarm.deactivate();
-        AlarmEvent event6 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DISABLE );
-        assertEquals( AlarmPoint.EVENT_DISABLING, event6.systemName().get() );
-
-        alarm = createAlarm( "Another 7" );
-        alarm.activate();
-        alarm.deactivate();
-        AlarmEvent event7 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ENABLE );
-        assertNull( event7 );
-    }
-
-    @Test
-    public void testStateChangeFromBlocked()
-        throws Exception
-    {
-        AlarmModel provider = module.findService( AlarmModel.class ).get();
-        AlarmPoint alarm = createAlarm( "Another 1" );
-        alarm.activate();
-        alarm.trigger( "block" );
-        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
-        assertNull( event1 );
-
-        alarm = createAlarm( "Another 2" );
-        alarm.activate();
-        alarm.trigger( "block" );
-        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
-        assertNull( event2 );
-
-        alarm = createAlarm( "Another 3" );
-        alarm.activate();
-        alarm.trigger( "block" );
-        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
-        assertNull( event3 );
-
-        alarm = createAlarm( "Another 4" );
-        alarm.activate();
-        alarm.trigger( "block" );
-        AlarmEvent event4 = provider.evaluate( alarm, AlarmPoint.TRIGGER_BLOCK );
-        assertNull( event4 );
-
-        alarm = createAlarm( "Another 5" );
-        alarm.activate();
-        alarm.trigger( "block" );
-        AlarmEvent event5 = provider.evaluate( alarm, AlarmPoint.TRIGGER_UNBLOCK );
-        assertEquals( AlarmPoint.EVENT_UNBLOCKING, event5.systemName().get() );
-
-        alarm = createAlarm( "Another 6" );
-        alarm.activate();
-        alarm.trigger( "block" );
-        AlarmEvent event6 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DISABLE );
-        assertEquals( AlarmPoint.EVENT_DISABLING, event6.systemName().get() );
-
-        alarm = createAlarm( "Another 7" );
-        alarm.activate();
-        alarm.trigger( "block" );
-        AlarmEvent event7 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ENABLE );
-        assertNull( event7 );
-    }
-
-    @Test
-    public void testStateChangeFromDisabled()
-        throws Exception
-    {
-        AlarmModel provider = module.findService( AlarmModel.class ).get();
-        AlarmPoint alarm = createAlarm( "Another 1" );
-        alarm.activate();
-        alarm.trigger( "disable" );
-        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
-        assertNull( event1 );
-
-        alarm = createAlarm( "Another 2" );
-        alarm.activate();
-        alarm.trigger( "disable" );
-        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
-        assertNull( event2 );
-
-        alarm = createAlarm( "Another 3" );
-        alarm.activate();
-        alarm.trigger( "disable" );
-        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
-        assertNull( event3 );
-
-        alarm = createAlarm( "Another 4" );
-        alarm.activate();
-        alarm.trigger( "disable" );
-        AlarmEvent event4 = provider.evaluate( alarm, AlarmPoint.TRIGGER_BLOCK );
-        assertNull( event4 );
-
-        alarm = createAlarm( "Another 5" );
-        alarm.activate();
-        alarm.trigger( "disable" );
-        AlarmEvent event5 = provider.evaluate( alarm, AlarmPoint.TRIGGER_UNBLOCK );
-        assertNull( event5 );
-
-        alarm = createAlarm( "Another 6" );
-        alarm.activate();
-        alarm.trigger( "disable" );
-        AlarmEvent event6 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DISABLE );
-        assertNull( event6 );
-
-        alarm = createAlarm( "Another 7" );
-        alarm.activate();
-        alarm.trigger( "disable" );
-        AlarmEvent event7 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ENABLE );
-        assertEquals( AlarmPoint.EVENT_ENABLING, event7.systemName().get() );
-    }
-
-    @Test
-    public void testIllegalTrigger()
-        throws Exception
-    {
-        try
-        {
-            AlarmModel provider = module.findService( AlarmModel.class ).get();
-            AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-            provider.evaluate( underTest, "my-trigger" );
-            fail( "IllegalArgumentException not thrown." );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Expected.
-        }
-    }
-
-    @Test
-    public void testNormalToActivated()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        underTest.activate();
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_NORMAL, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACTIVATED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testActivatedToDeactivated()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        underTest.activate();
-        underTest.deactivate();
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_DEACTIVATED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testActivatedToAcknowledged()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.activate();
-        underTest.acknowledge();
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACKNOWLEDGED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testDeactivatedToNormal()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.activate();
-        underTest.deactivate();
-        underTest.acknowledge();
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_DEACTIVATED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_NORMAL, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testAcknowledgedToNormal()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.activate();
-        underTest.acknowledge();
-        underTest.deactivate();
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACKNOWLEDGED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_NORMAL, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testDisabledToNormal()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.activate();
-        underTest.trigger( "disable" );
-        underTest.trigger( "enable" );
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_DISABLED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_NORMAL, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testBlockedToNormal()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.activate();
-        underTest.trigger( "block" );
-        underTest.trigger( "unblock" );
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_BLOCKED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_NORMAL, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testNormalToBlocked()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.trigger( "block" );
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_NORMAL, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_BLOCKED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testActivatedToBlocked()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.activate();
-        underTest.trigger( "block" );
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_BLOCKED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testDeactivatedToBlocked()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.activate();
-        underTest.deactivate();
-        underTest.trigger( "block" );
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_DEACTIVATED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_BLOCKED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testAcknowledgedToBlocked()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.activate();
-        underTest.acknowledge();
-        underTest.trigger( "block" );
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACKNOWLEDGED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_BLOCKED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testNormalToDisabled()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.trigger( "disable" );
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_NORMAL, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_DISABLED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testActivatedToDisabled()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.activate();
-        underTest.trigger( "disable" );
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_DISABLED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testDeactivatedToDisabled()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.activate();
-        underTest.deactivate();
-        underTest.trigger( "disable" );
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_DEACTIVATED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_DISABLED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testAcknowledgedToDisabled()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.activate();
-        underTest.acknowledge();
-        underTest.trigger( "disable" );
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACKNOWLEDGED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_DISABLED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testBlockedToDisabled()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.activate();
-        underTest.trigger( "block" );
-        underTest.trigger( "disable" );
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_BLOCKED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_DISABLED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testDisabledToBlocked()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.activate();
-        underTest.trigger( "disable" );
-        underTest.trigger( "block" );       // This trigger should be ignored.
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_DISABLED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testConditionChanges1()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.updateCondition( false );
-        AlarmEvent event = underTest.history().lastEvent();
-        assertNull( "Generated an event but should have not.", event );
-    }
-
-    @Test
-    public void testConditionChanges2()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.updateCondition( true );
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_NORMAL, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACTIVATED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testConditionChanges3()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-
-        underTest.updateCondition( true );
-        underTest.updateCondition( false );
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_DEACTIVATED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testComputeCondition()
-        throws Exception
-    {
-        AlarmModel provider = module.findService( AlarmModel.class ).get();
-        AlarmStatus s1 = createStatus( AlarmPoint.STATUS_NORMAL );
-        assertFalse( provider.computeCondition( s1 ) );
-        AlarmStatus s2 = createStatus( AlarmPoint.STATUS_ACTIVATED );
-        assertTrue( provider.computeCondition( s2 ) );
-        AlarmStatus s3 = createStatus( AlarmPoint.STATUS_DEACTIVATED );
-        assertFalse( provider.computeCondition( s3 ) );
-        AlarmStatus s4 = createStatus( AlarmPoint.STATUS_ACKNOWLEDGED );
-        assertTrue( provider.computeCondition( s4 ) );
-
-        AlarmStatus s5 = createStatus( AlarmPoint.STATUS_DISABLED );
-        assertFalse( provider.computeCondition( s5 ) );
-        AlarmStatus s6 = createStatus( AlarmPoint.STATUS_BLOCKED );
-        assertFalse( provider.computeCondition( s6 ) );
-        AlarmStatus s7 = createStatus( AlarmPoint.STATUS_REACTIVATED );
-        assertTrue( provider.computeCondition( s7 ) );
-    }
-
-    @Test
-    public void testComputeTriggerNormal()
-        throws Exception
-    {
-        AlarmModel provider = module.findService( AlarmModel.class ).get();
-        AlarmStatus status = createStatus( AlarmPoint.STATUS_NORMAL );
-        String trigger1 = provider.computeTrigger( status, true );
-        String trigger2 = provider.computeTrigger( status, false );
-        assertEquals( AlarmPoint.TRIGGER_ACTIVATE, trigger1 );
-        assertEquals( null, trigger2 );
-    }
-
-    @Test
-    public void testComputeTriggerActivated()
-    {
-        AlarmModel provider = module.findService( AlarmModel.class ).get();
-        AlarmStatus status = createStatus( AlarmPoint.STATUS_ACTIVATED );
-        String trigger1 = provider.computeTrigger( status, true );
-        String trigger2 = provider.computeTrigger( status, false );
-        assertEquals( null, trigger1 );
-        assertEquals( AlarmPoint.TRIGGER_DEACTIVATE, trigger2 );
-    }
-
-    @Test
-    public void testComputeTRiggerDeactivated()
-    {
-        AlarmModel provider = module.findService( AlarmModel.class ).get();
-        AlarmStatus status = createStatus( AlarmPoint.STATUS_DEACTIVATED );
-        String trigger1 = provider.computeTrigger( status, true );
-        String trigger2 = provider.computeTrigger( status, false );
-        assertEquals( AlarmPoint.TRIGGER_ACTIVATE, trigger1 );
-        assertEquals( null, trigger2 );
-    }
-
-    @Test
-    public void testComputeTriggerAcknowledged()
-    {
-        AlarmModel provider = module.findService( AlarmModel.class ).get();
-        AlarmStatus status = createStatus( AlarmPoint.STATUS_ACKNOWLEDGED );
-        String trigger1 = provider.computeTrigger( status, true );
-        String trigger2 = provider.computeTrigger( status, false );
-        assertEquals( null, trigger1 );
-        assertEquals( AlarmPoint.TRIGGER_DEACTIVATE, trigger2 );
-    }
-
-    @Test
-    public void testComputeTriggerReactivated()
-    {
-        AlarmModel provider = module.findService( AlarmModel.class ).get();
-        AlarmStatus status = createStatus( AlarmPoint.STATUS_REACTIVATED );
-        String trigger1 = provider.computeTrigger( status, true );
-        String trigger2 = provider.computeTrigger( status, false );
-        assertEquals( null, trigger1 );
-        assertEquals( AlarmPoint.TRIGGER_DEACTIVATE, trigger2 );
-    }
-
-    @Test
-    public void testComputeTriggerBlocked()
-    {
-        AlarmModel provider = module.findService( AlarmModel.class ).get();
-        AlarmStatus status = createStatus( AlarmPoint.STATUS_BLOCKED );
-        String trigger1 = provider.computeTrigger( status, true );
-        String trigger2 = provider.computeTrigger( status, false );
-        assertEquals( null, trigger1 );
-        assertEquals( null, trigger2 );
-    }
-
-    @Test
-    public void testComputeTriggerDisabled()
-    {
-        AlarmModel provider = module.findService( AlarmModel.class ).get();
-        AlarmStatus status = createStatus( AlarmPoint.STATUS_DISABLED );
-        String trigger1 = provider.computeTrigger( status, true );
-        String trigger2 = provider.computeTrigger( status, false );
-        assertEquals( null, trigger1 );
-        assertEquals( null, trigger2 );
-    }
-
-    private AlarmPoint createAlarm( String name )
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        EntityBuilder<AlarmPoint> builder = uow.newEntityBuilder( AlarmPoint.class );
-        builder.instance().category().set( createCategory( "Testing" ) );
-        AlarmPoint.AlarmState state = builder.instanceFor( AlarmPoint.AlarmState.class );
-        state.currentStatus().set( createStatus( AlarmPoint.STATUS_NORMAL ) );
-        state.description().set( "Test Description" );
-        state.systemName().set( name );
-        return builder.newInstance();
-    }
-
-    private AlarmCategory createCategory( String name )
-    {
-        ValueBuilder<AlarmCategory> builder = module.newValueBuilder( AlarmCategory.class );
-        builder.prototype().name().set( name );
-        return builder.newInstance();
-    }
-
-    private AlarmPoint getAlarm( String identity )
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        return uow.get( AlarmPoint.class, identity );
-    }
-
-    private AlarmStatus createStatus( String status )
-    {
-        ValueBuilder<AlarmStatus> builder = module.newValueBuilder( AlarmStatus.class );
-        AlarmStatus.State statePrototype = builder.prototypeFor( AlarmStatus.State.class );
-        statePrototype.name().set( status );
-        statePrototype.creationDate().set( new Date() );
-        return builder.newInstance();
-    }
-}
diff --git a/libraries/alarm/src/test/java/org/qi4j/library/alarm/SimpleAlarmModelTest.java b/libraries/alarm/src/test/java/org/qi4j/library/alarm/SimpleAlarmModelTest.java
deleted file mode 100644
index 5276ac1..0000000
--- a/libraries/alarm/src/test/java/org/qi4j/library/alarm/SimpleAlarmModelTest.java
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * Copyright 2005-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import org.junit.Test;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-public class SimpleAlarmModelTest
-    extends AbstractQi4jTest
-{
-
-    @SuppressWarnings( { "unchecked" } )
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( TestAlarmModel.class );
-        module.services( AlarmSystemService.class );
-        new EntityTestAssembler().assemble( module );
-        module.entities( AlarmPointEntity.class );
-        module.values( AlarmEvent.class );
-        module.values( AlarmCategory.class );
-        module.values( AlarmStatus.class );
-        module.forMixin( AlarmHistory.class ).declareDefaults().maxSize().set( 10 );
-    }
-
-    @Mixins( SimpleAlarmModelService.SimpleAlarmModelMixin.class )
-    public interface TestAlarmModel
-        extends AlarmModel, ServiceComposite
-    {
-    }
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        module.newUnitOfWork();
-    }
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        if( uow != null )
-        {
-            uow.discard();
-        }
-        super.tearDown();
-    }
-
-    @Test
-    public void testName()
-        throws Exception
-    {
-        SimpleAlarmModelService.SimpleAlarmModelMixin spi = new SimpleAlarmModelService.SimpleAlarmModelMixin();
-        assertEquals( "org.qi4j.library.alarm.model.simple", spi.modelName() );
-    }
-
-    @Test
-    public void testDescription()
-        throws Exception
-    {
-        SimpleAlarmModelService.SimpleAlarmModelMixin spi = new SimpleAlarmModelService.SimpleAlarmModelMixin();
-        boolean test1 = spi.modelDescription().toLowerCase().contains( "normal" );
-        boolean test2 = spi.modelDescription().toLowerCase().contains( "activated" );
-        boolean test3 = spi.modelDescription().toLowerCase().contains( "activation" );
-        boolean test4 = spi.modelDescription().toLowerCase().contains( "deactivation" );
-        assertTrue( test1 && test2 && test3 && test4 );
-
-        Locale english = new Locale( "en" );
-        test1 = spi.modelDescription( english ).toLowerCase().contains( "normal" );
-        test2 = spi.modelDescription( english ).toLowerCase().contains( "activated" );
-        test3 = spi.modelDescription( english ).toLowerCase().contains( "activation" );
-        test4 = spi.modelDescription( english ).toLowerCase().contains( "deactivation" );
-        assertTrue( test1 && test2 && test3 && test4 );
-    }
-
-    @Test
-    public void testTriggers()
-        throws Exception
-    {
-        AlarmModel provider = (AlarmModel) module.findService( AlarmModel.class ).get();
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        List<String> triggers = provider.alarmTriggers();
-        assertEquals( 2, triggers.size() );
-        int result = 0;
-        for( String trigger : triggers )
-        {
-            if( AlarmPoint.TRIGGER_ACTIVATE.equals( trigger ) )
-            {
-                result |= 1;
-            }
-            if( AlarmPoint.TRIGGER_DEACTIVATE.equals( trigger ) )
-            {
-                result |= 2;
-            }
-            if( AlarmPoint.TRIGGER_ACKNOWLEDGE.equals( trigger ) )
-            {
-                result |= 4;
-            }
-            if( AlarmPoint.TRIGGER_BLOCK.equals( trigger ) )
-            {
-                result |= 8;
-            }
-            if( AlarmPoint.TRIGGER_UNBLOCK.equals( trigger ) )
-            {
-                result |= 16;
-            }
-            if( AlarmPoint.TRIGGER_ENABLE.equals( trigger ) )
-            {
-                result |= 32;
-            }
-            if( AlarmPoint.TRIGGER_DISABLE.equals( trigger ) )
-            {
-                result |= 64;
-            }
-        }
-        assertEquals( 3, result );
-        assertEquals( AlarmPoint.STATUS_NORMAL, underTest.currentStatus().name(null) );
-    }
-
-    @Test
-    public void testStateChangeFromNormal()
-        throws Exception
-    {
-        AlarmModel provider = (AlarmModel) module.findService( AlarmModel.class ).get();
-        AlarmPoint alarm = createAlarm( "Another 1" );
-        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
-        assertEquals( AlarmPoint.EVENT_ACTIVATION, event1.systemName().get() );
-
-        alarm = createAlarm( "Another 2" );
-        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
-        assertNull( event2 );
-
-        try
-        {
-            alarm = createAlarm( "Another 3" );
-            AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
-            assertNull( event3 );
-            fail( "[Acknowledge] trigger should not be allowed on this model." );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // expected
-        }
-    }
-
-    @Test
-    public void testStateChangeFromActivated()
-        throws Exception
-    {
-        AlarmModel provider = (AlarmModel) module.findService( AlarmModel.class ).get();
-        AlarmPoint alarm = createAlarm( "Another 1" );
-        alarm.activate();
-
-        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
-        assertNull( event1 );
-
-        alarm = createAlarm( "Another 2" );
-        alarm.activate();
-        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
-        assertEquals( AlarmPoint.EVENT_DEACTIVATION, event2.systemName().get() );
-    }
-
-    @Test
-    public void testIllegalTrigger()
-        throws Exception
-    {
-        try
-        {
-            AlarmModel provider = (AlarmModel) module.findService( AlarmModel.class ).get();
-            AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-            provider.evaluate( underTest, "my-trigger" );
-            fail( "IllegalArgumentException not thrown." );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Expected.
-        }
-    }
-
-    @Test
-    public void testNormalToActivated()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        underTest.activate();
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_NORMAL, oldstate.name(null) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACTIVATED, newstate.name(null) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testActivatedToNormal()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        underTest.activate();
-        underTest.deactivate();
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name(null) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_NORMAL, newstate.name(null) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testConditionChanges1()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        underTest.updateCondition( false );
-        AlarmEvent event = underTest.history().lastEvent();
-        assertNull( "Generated an event but should have not.", event );
-    }
-
-    @Test
-    public void testConditionChanges2()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        underTest.updateCondition( true );
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_NORMAL, oldstate.name(null) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACTIVATED, newstate.name(null) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testConditionChanges3()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        underTest.updateCondition( true );
-        underTest.updateCondition( false );
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name(null) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_NORMAL, newstate.name(null) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testComputeCondition()
-        throws Exception
-    {
-        AlarmModel provider = (AlarmModel) module.findService( AlarmModel.class ).get();
-        AlarmStatus s1 = createStatus( AlarmPoint.STATUS_NORMAL );
-        assertFalse( provider.computeCondition( s1 ) );
-        AlarmStatus s2 = createStatus( AlarmPoint.STATUS_ACTIVATED );
-        assertTrue( provider.computeCondition( s2 ) );
-    }
-
-    @Test
-    public void testComputeTrigger()
-        throws Exception
-    {
-        AlarmModel provider = (AlarmModel) module.findService( AlarmModel.class ).get();
-        AlarmStatus s1 = createStatus( AlarmPoint.STATUS_NORMAL );
-        AlarmStatus s2 = createStatus( AlarmPoint.STATUS_ACTIVATED );
-        String trigger1 = provider.computeTrigger( s1, true );
-        String trigger2 = provider.computeTrigger( s2, true );
-        String trigger5 = provider.computeTrigger( s1, false );
-        String trigger6 = provider.computeTrigger( s2, false );
-        assertEquals( AlarmPoint.TRIGGER_ACTIVATE, trigger1 );
-        assertEquals( null, trigger2 );
-        assertEquals( null, trigger5 );
-        assertEquals( AlarmPoint.TRIGGER_DEACTIVATE, trigger6 );
-    }
-
-    private AlarmPoint createAlarm( String name )
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        EntityBuilder<AlarmPoint> builder = uow.newEntityBuilder( AlarmPoint.class );
-        builder.instance().category().set( createCategory( "SimpleModelTest" ) );
-        AlarmPoint.AlarmState state = builder.instanceFor( AlarmPoint.AlarmState.class );
-        state.currentStatus().set( createStatus( AlarmPoint.STATUS_NORMAL ) );
-        state.description().set( "Test Description" );
-        state.systemName().set( name );
-        return builder.newInstance();
-    }
-
-    private AlarmCategory createCategory( String name )
-    {
-        ValueBuilder<AlarmCategory> builder = module.newValueBuilder( AlarmCategory.class );
-        builder.prototype().name().set( name );
-        return builder.newInstance();
-    }
-
-    private AlarmPoint getAlarm( String identity )
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        return uow.get( AlarmPoint.class, identity );
-    }
-
-    private AlarmStatus createStatus( String status )
-    {
-        ValueBuilder<AlarmStatus> builder = module.newValueBuilder( AlarmStatus.class );
-        AlarmStatus.State statePrototype = builder.prototypeFor( AlarmStatus.State.class );
-        statePrototype.name().set( status );
-        statePrototype.creationDate().set( new Date() );
-        return builder.newInstance();
-    }
-}
diff --git a/libraries/alarm/src/test/java/org/qi4j/library/alarm/StandardAlarmModelTest.java b/libraries/alarm/src/test/java/org/qi4j/library/alarm/StandardAlarmModelTest.java
deleted file mode 100644
index 59e32f5..0000000
--- a/libraries/alarm/src/test/java/org/qi4j/library/alarm/StandardAlarmModelTest.java
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- * Copyright 2005-2011 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.alarm;
-
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-public class StandardAlarmModelTest
-    extends AbstractQi4jTest
-{
-
-    @SuppressWarnings( { "unchecked" } )
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( TestAlarmModel.class );
-        module.services( AlarmSystemService.class );
-        new EntityTestAssembler().assemble( module );
-        module.entities( AlarmPointEntity.class );
-        module.values( AlarmEvent.class );
-        module.values( AlarmCategory.class );
-        module.values( AlarmStatus.class );
-        module.forMixin( AlarmHistory.class ).declareDefaults().maxSize().set( 10 );
-    }
-
-    @Mixins( StandardAlarmModelService.StandardAlarmModelMixin.class )
-    public interface TestAlarmModel
-        extends AlarmModel, ServiceComposite
-    {
-    }
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        module.newUnitOfWork();
-    }
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        if( uow != null )
-        {
-            uow.discard();
-        }
-        super.tearDown();
-    }
-
-    @Test
-    public void testName()
-        throws Exception
-    {
-        StandardAlarmModelService.StandardAlarmModelMixin spi = new StandardAlarmModelService.StandardAlarmModelMixin();
-        assertEquals( "org.qi4j.library.alarm.model.standard", spi.modelName() );
-    }
-
-    @Test
-    public void testDescription()
-        throws Exception
-    {
-        StandardAlarmModelService.StandardAlarmModelMixin spi = new StandardAlarmModelService.StandardAlarmModelMixin();
-        boolean test1 = spi.modelDescription().toLowerCase().contains( "normal" );
-        boolean test2 = spi.modelDescription().toLowerCase().contains( "activated" );
-        boolean test3 = spi.modelDescription().toLowerCase().contains( "deactivated" );
-        boolean test4 = spi.modelDescription().toLowerCase().contains( "acknowledged" );
-        boolean test5 = spi.modelDescription().toLowerCase().contains( "activation" );
-        boolean test6 = spi.modelDescription().toLowerCase().contains( "deactivation" );
-        boolean test7 = spi.modelDescription().toLowerCase().contains( "acknowledge" );
-        assertTrue( test1 && test2 && test3 && test4 && test5 && test6 && test7 );
-
-        Locale english = new Locale( "en" );
-        test1 = spi.modelDescription( english ).toLowerCase().contains( "normal" );
-        test2 = spi.modelDescription( english ).toLowerCase().contains( "activated" );
-        test3 = spi.modelDescription( english ).toLowerCase().contains( "deactivated" );
-        test4 = spi.modelDescription( english ).toLowerCase().contains( "acknowledged" );
-        test5 = spi.modelDescription( english ).toLowerCase().contains( "activation" );
-        test6 = spi.modelDescription( english ).toLowerCase().contains( "deactivation" );
-        test7 = spi.modelDescription( english ).toLowerCase().contains( "acknowledge" );
-        assertTrue( test1 && test2 && test3 && test4 && test5 && test6 && test7 );
-    }
-
-    @Test
-    public void testTriggers()
-        throws Exception
-    {
-        AlarmModel provider = (AlarmModel) module.findService( AlarmModel.class ).get();
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        List<String> triggers = provider.alarmTriggers();
-        assertEquals( 3, triggers.size() );
-        int result = 0;
-        for( String trigger : triggers )
-        {
-            if( AlarmPoint.TRIGGER_ACTIVATE.equals( trigger ) )
-            {
-                result |= 1;
-            }
-            if( AlarmPoint.TRIGGER_DEACTIVATE.equals( trigger ) )
-            {
-                result |= 2;
-            }
-            if( AlarmPoint.TRIGGER_ACKNOWLEDGE.equals( trigger ) )
-            {
-                result |= 4;
-            }
-            if( AlarmPoint.TRIGGER_BLOCK.equals( trigger ) )
-            {
-                result |= 8;
-            }
-            if( AlarmPoint.TRIGGER_UNBLOCK.equals( trigger ) )
-            {
-                result |= 16;
-            }
-            if( AlarmPoint.TRIGGER_DISABLE.equals( trigger ) )
-            {
-                result |= 32;
-            }
-            if( AlarmPoint.TRIGGER_ENABLE.equals( trigger ) )
-            {
-                result |= 64;
-            }
-        }
-        assertEquals( 7, result );
-        assertEquals( AlarmPoint.STATUS_NORMAL, underTest.currentStatus().name( null ) );
-    }
-
-    @Test
-    public void testStateChangeFromNormal()
-        throws Exception
-    {
-        AlarmModel provider = (AlarmModel) module.findService( AlarmModel.class ).get();
-        AlarmPoint alarm = createAlarm( "Another 1" );
-        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
-        assertEquals( AlarmPoint.EVENT_ACTIVATION, event1.systemName().get() );
-
-        alarm = createAlarm( "Another 2" );
-        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
-        assertNull( event2 );
-
-        alarm = createAlarm( "Another 3" );
-        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
-        assertNull( event3 );
-    }
-
-    @Test
-    public void testStateChangeFromActivated()
-        throws Exception
-    {
-        AlarmModel provider = (AlarmModel) module.findService( AlarmModel.class ).get();
-        AlarmPoint alarm = createAlarm( "Another 1" );
-        alarm.activate();
-
-        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
-        assertNull( event1 );
-
-        alarm = createAlarm( "Another 2" );
-        alarm.activate();
-        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
-        assertEquals( AlarmPoint.EVENT_DEACTIVATION, event2.systemName().get() );
-
-        alarm = createAlarm( "Another 3" );
-        alarm.activate();
-        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
-        assertEquals( AlarmPoint.EVENT_ACKNOWLEDGEMENT, event3.systemName().get() );
-    }
-
-    @Test
-    public void testStateChangeFromAcknowledged()
-        throws Exception
-    {
-        AlarmModel provider = (AlarmModel) module.findService( AlarmModel.class ).get();
-        AlarmPoint alarm = createAlarm( "Another 1" );
-        alarm.activate();
-        alarm.acknowledge();
-
-        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
-        assertNull( event1 );
-
-        alarm = createAlarm( "Another 2" );
-        alarm.activate();
-        alarm.acknowledge();
-        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
-        assertEquals( AlarmPoint.EVENT_DEACTIVATION, event2.systemName().get() );
-
-        alarm = createAlarm( "Another 3" );
-        alarm.activate();
-        alarm.acknowledge();
-        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
-        assertNull( event3 );
-    }
-
-    @Test
-    public void testStateChangeFromDeactivated()
-        throws Exception
-    {
-        AlarmModel provider = (AlarmModel) module.findService( AlarmModel.class ).get();
-        AlarmPoint alarm = createAlarm( "Another 1" );
-        alarm.activate();
-        alarm.deactivate();
-        AlarmEvent event1 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACTIVATE );
-        assertEquals( AlarmPoint.EVENT_ACTIVATION, event1.systemName().get() );
-
-        alarm = createAlarm( "Another 2" );
-        alarm.activate();
-        alarm.deactivate();
-        AlarmEvent event2 = provider.evaluate( alarm, AlarmPoint.TRIGGER_DEACTIVATE );
-        assertNull( event2 );
-
-        alarm = createAlarm( "Another 3" );
-        alarm.activate();
-        alarm.deactivate();
-        AlarmEvent event3 = provider.evaluate( alarm, AlarmPoint.TRIGGER_ACKNOWLEDGE );
-        assertEquals( AlarmPoint.EVENT_ACKNOWLEDGEMENT, event3.systemName().get() );
-    }
-
-    @Test
-    public void testIllegalTrigger()
-        throws Exception
-    {
-        try
-        {
-            AlarmModel provider = (AlarmModel) module.findService( AlarmModel.class ).get();
-            AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-            provider.evaluate( underTest, "my-trigger" );
-            fail( "IllegalArgumentException not thrown." );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Expected.
-        }
-    }
-
-    @Test
-    public void testNormalToActivated()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        underTest.activate();
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        Assert.assertEquals( AlarmPoint.STATUS_NORMAL, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        Assert.assertEquals( AlarmPoint.STATUS_ACTIVATED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testActivatedToDeactivated()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        underTest.activate();
-        underTest.deactivate();
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        Assert.assertEquals( AlarmPoint.STATUS_DEACTIVATED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testActivatedToAcknowledged()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        underTest.activate();
-        underTest.acknowledge();
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        Assert.assertEquals( AlarmPoint.STATUS_ACKNOWLEDGED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testDeactivatedToNormal()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        underTest.activate();
-        underTest.deactivate();
-        underTest.acknowledge();
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_DEACTIVATED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_NORMAL, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testAcknowledgedToNormal()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        underTest.activate();
-        underTest.acknowledge();
-        underTest.deactivate();
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACKNOWLEDGED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_NORMAL, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testConditionChanges1()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        underTest.updateCondition( false );
-        AlarmEvent event = underTest.history().lastEvent();
-        assertNull( "Generated an event but should have not.", event );
-    }
-
-    @Test
-    public void testConditionChanges2()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        underTest.updateCondition( true );
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_NORMAL, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACTIVATED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testConditionChanges3()
-        throws Exception
-    {
-        AlarmPoint underTest = createAlarm( "Test AlarmPoint" );
-        underTest.updateCondition( true );
-        underTest.updateCondition( false );
-        AlarmEvent event = underTest.history().lastEvent();
-
-        AlarmStatus oldstate = event.oldStatus().get();
-        assertEquals( AlarmPoint.STATUS_ACTIVATED, oldstate.name( null ) );
-
-        AlarmStatus newstate = event.newStatus().get();
-        assertEquals( AlarmPoint.STATUS_DEACTIVATED, newstate.name( null ) );
-
-        AlarmPoint eventalarm = getAlarm( event.alarmIdentity().get() );
-        assertEquals( underTest, eventalarm );
-    }
-
-    @Test
-    public void testComputeCondition()
-        throws Exception
-    {
-        AlarmModel provider = (AlarmModel) module.findService( AlarmModel.class ).get();
-        AlarmStatus s1 = createStatus( AlarmPoint.STATUS_NORMAL );
-        assertFalse( provider.computeCondition( s1 ) );
-        AlarmStatus s2 = createStatus( AlarmPoint.STATUS_ACTIVATED );
-        assertTrue( provider.computeCondition( s2 ) );
-        AlarmStatus s3 = createStatus( AlarmPoint.STATUS_DEACTIVATED );
-        assertFalse( provider.computeCondition( s3 ) );
-        AlarmStatus s4 = createStatus( AlarmPoint.STATUS_ACKNOWLEDGED );
-        assertTrue( provider.computeCondition( s4 ) );
-    }
-
-    @Test
-    public void testComputeTrigger()
-        throws Exception
-    {
-        AlarmModel provider = (AlarmModel) module.findService( AlarmModel.class ).get();
-        AlarmStatus s1 = createStatus( AlarmPoint.STATUS_NORMAL );
-        AlarmStatus s2 = createStatus( AlarmPoint.STATUS_ACTIVATED );
-        AlarmStatus s3 = createStatus( AlarmPoint.STATUS_DEACTIVATED );
-        AlarmStatus s4 = createStatus( AlarmPoint.STATUS_ACKNOWLEDGED );
-        String trigger1 = provider.computeTrigger( s1, true );
-        String trigger2 = provider.computeTrigger( s2, true );
-        String trigger3 = provider.computeTrigger( s3, true );
-        String trigger4 = provider.computeTrigger( s4, true );
-        String trigger5 = provider.computeTrigger( s1, false );
-        String trigger6 = provider.computeTrigger( s2, false );
-        String trigger7 = provider.computeTrigger( s3, false );
-        String trigger8 = provider.computeTrigger( s4, false );
-        assertEquals( AlarmPoint.TRIGGER_ACTIVATE, trigger1 );
-        assertEquals( null, trigger2 );
-        assertEquals( AlarmPoint.TRIGGER_ACTIVATE, trigger3 );
-        assertEquals( null, trigger4 );
-        assertEquals( null, trigger5 );
-        assertEquals( AlarmPoint.TRIGGER_DEACTIVATE, trigger6 );
-        assertEquals( null, trigger7 );
-        assertEquals( AlarmPoint.TRIGGER_DEACTIVATE, trigger8 );
-    }
-
-    private AlarmPoint createAlarm( String name )
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        EntityBuilder<AlarmPoint> builder = uow.newEntityBuilder( AlarmPoint.class );
-        builder.instance().category().set( createCategory( "StandardModelTest" ) );
-        AlarmPoint.AlarmState state = builder.instanceFor( AlarmPoint.AlarmState.class );
-        state.currentStatus().set( createStatus( AlarmPoint.STATUS_NORMAL ) );
-        state.description().set( "Test Description" );
-        state.systemName().set( name );
-        return builder.newInstance();
-    }
-
-    private AlarmCategory createCategory( String name )
-    {
-        ValueBuilder<AlarmCategory> builder = module.newValueBuilder( AlarmCategory.class );
-        builder.prototype().name().set( name );
-        return builder.newInstance();
-    }
-
-    private AlarmPoint getAlarm( String identity )
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        return uow.get( AlarmPoint.class, identity );
-    }
-
-    private AlarmStatus createStatus( String status )
-    {
-        ValueBuilder<AlarmStatus> builder = module.newValueBuilder( AlarmStatus.class );
-        AlarmStatus.State statePrototype = builder.prototypeFor( AlarmStatus.State.class );
-        statePrototype.name().set( status );
-        statePrototype.creationDate().set( new Date() );
-        return builder.newInstance();
-    }
-}
diff --git a/libraries/alarm/src/test/resources/org/apache/polygene/library/alarm/user/AlarmDescriptions.properties b/libraries/alarm/src/test/resources/org/apache/polygene/library/alarm/user/AlarmDescriptions.properties
new file mode 100644
index 0000000..0e1755a
--- /dev/null
+++ b/libraries/alarm/src/test/resources/org/apache/polygene/library/alarm/user/AlarmDescriptions.properties
@@ -0,0 +1,21 @@
+#
+#  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.
+#
+#
+#
+
+TestCase\ AlarmPoint=This is a default Locale description of a testcase Alarm.
\ No newline at end of file
diff --git a/libraries/alarm/src/test/resources/org/apache/polygene/library/alarm/user/AlarmDescriptions_en_GB.properties b/libraries/alarm/src/test/resources/org/apache/polygene/library/alarm/user/AlarmDescriptions_en_GB.properties
new file mode 100644
index 0000000..75db4ae
--- /dev/null
+++ b/libraries/alarm/src/test/resources/org/apache/polygene/library/alarm/user/AlarmDescriptions_en_GB.properties
@@ -0,0 +1,21 @@
+#
+#  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.
+#
+#
+#
+
+TestCase\ AlarmPoint=This is a UK Locale description of a testcase Alarm.
\ No newline at end of file
diff --git a/libraries/alarm/src/test/resources/org/apache/polygene/library/alarm/user/AlarmDescriptions_sv.properties b/libraries/alarm/src/test/resources/org/apache/polygene/library/alarm/user/AlarmDescriptions_sv.properties
new file mode 100644
index 0000000..9ee68ac
--- /dev/null
+++ b/libraries/alarm/src/test/resources/org/apache/polygene/library/alarm/user/AlarmDescriptions_sv.properties
@@ -0,0 +1,21 @@
+#
+#  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.
+#
+#
+#
+
+TestCase\ AlarmPoint=Detta \u00E5r en svensk beskrivning av ett testlarm.
\ No newline at end of file
diff --git a/libraries/alarm/src/test/resources/org/qi4j/library/alarm/user/AlarmDescriptions.properties b/libraries/alarm/src/test/resources/org/qi4j/library/alarm/user/AlarmDescriptions.properties
deleted file mode 100644
index d9dc523..0000000
--- a/libraries/alarm/src/test/resources/org/qi4j/library/alarm/user/AlarmDescriptions.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Copyright 2005 Niclas Hedhman.
-#
-# Licensed  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.
-#
-
-TestCase\ AlarmPoint=This is a default Locale description of a testcase Alarm.
\ No newline at end of file
diff --git a/libraries/alarm/src/test/resources/org/qi4j/library/alarm/user/AlarmDescriptions_en_GB.properties b/libraries/alarm/src/test/resources/org/qi4j/library/alarm/user/AlarmDescriptions_en_GB.properties
deleted file mode 100644
index 0254d37..0000000
--- a/libraries/alarm/src/test/resources/org/qi4j/library/alarm/user/AlarmDescriptions_en_GB.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Copyright 2005 Niclas Hedhman.
-#
-# Licensed  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.
-#
-
-TestCase\ AlarmPoint=This is a UK Locale description of a testcase Alarm.
\ No newline at end of file
diff --git a/libraries/alarm/src/test/resources/org/qi4j/library/alarm/user/AlarmDescriptions_sv.properties b/libraries/alarm/src/test/resources/org/qi4j/library/alarm/user/AlarmDescriptions_sv.properties
deleted file mode 100644
index 1fe64b5..0000000
--- a/libraries/alarm/src/test/resources/org/qi4j/library/alarm/user/AlarmDescriptions_sv.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Copyright 2005 Niclas Hedhman.
-#
-# Licensed  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.
-#
-
-TestCase\ AlarmPoint=Detta \u00E5r en svensk beskrivning av ett testlarm.
\ No newline at end of file
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/Browser.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/Browser.java
new file mode 100644
index 0000000..29c3d0f
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/Browser.java
@@ -0,0 +1,109 @@
+/*
+ * 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.polygene.library.appbrowser;
+
+import java.util.Stack;
+import org.json.JSONException;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+
+public class Browser
+{
+    private final ApplicationDescriptor application;
+    private final FormatterFactory factory;
+    private final Stack<Formatter> stack = new Stack<>();
+
+    public Browser( ApplicationDescriptor application, FormatterFactory factory )
+    {
+        this.application = application;
+        this.factory = factory;
+    }
+
+    public void toJson()
+        throws BrowserException
+    {
+        application.accept( new HierarchicalVisitor<Object, Object, BrowserException>()
+        {
+            @Override
+            public boolean visitEnter( Object visited )
+                throws BrowserException
+            {
+                String simpleName = visited.getClass().getSimpleName();
+                Formatter formatter = factory.create( simpleName );
+                stack.push(formatter);
+                if( formatter == null )
+                {
+                    System.err.println( "Unknown application component: " + visited.getClass() );
+                    return false;
+                }
+                try
+                {
+                    formatter.enter( visited );
+                }
+                catch( JSONException e )
+                {
+                    throw new BrowserException( "Formatting failed.", e );
+                }
+                return true;
+            }
+
+            @Override
+            public boolean visitLeave( Object visited )
+                throws BrowserException
+            {
+                Formatter formatter = stack.pop();
+                if( formatter == null )
+                {
+                    System.err.println( "Unknown application component: " + visited.getClass() );
+                    return false;
+                }
+                try
+                {
+                    formatter.leave( visited );
+                }
+                catch( JSONException e )
+                {
+                    throw new BrowserException( "Formatting failed.", e );
+                }
+                return true;
+            }
+
+            @Override
+            public boolean visit( Object visited )
+                throws BrowserException
+            {
+                Formatter formatter = stack.peek();
+                if( formatter == null )
+                {
+                    System.err.println( "Unknown application component: " + visited.getClass() );
+                    return false;
+                }
+                try
+                {
+                    formatter.visit( visited );
+                }
+                catch( JSONException e )
+                {
+                    throw new BrowserException( "Formatting failed.", e );
+                }
+                return true;
+            }
+        } );
+    }
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/BrowserException.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/BrowserException.java
new file mode 100644
index 0000000..126c198
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/BrowserException.java
@@ -0,0 +1,29 @@
+/*
+ * 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.polygene.library.appbrowser;
+
+import org.json.JSONException;
+
+public class BrowserException extends RuntimeException
+{
+    public BrowserException( String message, JSONException exception )
+    {
+        super( message, exception);
+    }
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/Formatter.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/Formatter.java
new file mode 100644
index 0000000..19355a7
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/Formatter.java
@@ -0,0 +1,34 @@
+/*
+ * 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.polygene.library.appbrowser;
+
+import org.json.JSONException;
+
+public interface Formatter<NODE, LEAF>
+{
+
+    void enter( NODE visited )
+        throws JSONException;
+
+    void leave( NODE visited )
+        throws JSONException;
+
+    void visit( LEAF visited )
+        throws JSONException;
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/FormatterFactory.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/FormatterFactory.java
new file mode 100644
index 0000000..d996e2a
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/FormatterFactory.java
@@ -0,0 +1,25 @@
+/*
+ * 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.polygene.library.appbrowser;
+
+public interface FormatterFactory
+{
+
+    Formatter create( String componentType );
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/AbstractJsonFormatter.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/AbstractJsonFormatter.java
new file mode 100644
index 0000000..7682097
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/AbstractJsonFormatter.java
@@ -0,0 +1,85 @@
+/*
+ * 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.polygene.library.appbrowser.json;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+import org.apache.polygene.library.appbrowser.Formatter;
+
+public abstract class AbstractJsonFormatter<NODE,LEAF>
+    implements Formatter<NODE, LEAF>
+{
+    private final JSONWriter writer;
+
+    public AbstractJsonFormatter( JSONWriter writer )
+    {
+        this.writer = writer;
+    }
+
+    protected void field( String name, String value )
+        throws JSONException
+    {
+        writer.key( name ).value(value);
+    }
+
+    protected void field( String name, boolean value )
+        throws JSONException
+    {
+        writer.key( name ).value(value);
+    }
+
+    protected void array( String name )
+        throws JSONException
+    {
+        writer.key(name);
+        writer.array();
+    }
+
+    protected void endArray()
+        throws JSONException
+    {
+        writer.endArray();
+    }
+
+    protected void object()
+        throws JSONException
+    {
+        writer.object();
+    }
+
+    protected void object(String name)
+        throws JSONException
+    {
+        writer.key(name);
+        writer.object();
+    }
+
+    protected void endObject()
+        throws JSONException
+    {
+        writer.endObject();
+    }
+
+    protected void value( Object value )
+        throws JSONException
+    {
+        writer.value( value );
+    }
+
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ApplicationModelFormatter.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ApplicationModelFormatter.java
new file mode 100644
index 0000000..c862021
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ApplicationModelFormatter.java
@@ -0,0 +1,56 @@
+/*
+ * 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.polygene.library.appbrowser.json;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.library.appbrowser.Formatter;
+
+public class ApplicationModelFormatter extends AbstractJsonFormatter<ApplicationDescriptor, Void>
+{
+
+    public ApplicationModelFormatter( JSONWriter writer )
+    {
+        super( writer );
+    }
+
+    @Override
+    public void enter( ApplicationDescriptor visited )
+        throws JSONException
+    {
+        object();
+        field( "name", visited.name() );
+        array("layers");
+    }
+
+    @Override
+    public void leave( ApplicationDescriptor visited )
+        throws JSONException
+    {
+        endArray();
+        endObject();
+    }
+
+    @Override
+    public void visit( Void visited )
+        throws JSONException
+    {
+    }
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ArrayFormatter.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ArrayFormatter.java
new file mode 100644
index 0000000..6c315d0
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ArrayFormatter.java
@@ -0,0 +1,56 @@
+/*
+ * 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.polygene.library.appbrowser.json;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+import org.apache.polygene.library.appbrowser.Formatter;
+
+public class ArrayFormatter extends AbstractJsonFormatter
+    implements Formatter
+{
+    private final String name;
+
+    public ArrayFormatter( JSONWriter writer, String name )
+    {
+        super(writer);
+        this.name = name;
+    }
+
+    @Override
+    public void enter( Object visited )
+        throws JSONException
+    {
+        array(name);
+    }
+
+    @Override
+    public void leave( Object visited )
+        throws JSONException
+    {
+        endArray();
+    }
+
+    @Override
+    public void visit( Object visited )
+        throws JSONException
+    {
+
+    }
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/CompositeMethodModelFormatter.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/CompositeMethodModelFormatter.java
new file mode 100644
index 0000000..e4328ea
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/CompositeMethodModelFormatter.java
@@ -0,0 +1,54 @@
+/*
+ * 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.polygene.library.appbrowser.json;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+import org.apache.polygene.api.composite.MethodDescriptor;
+import org.apache.polygene.library.appbrowser.Formatter;
+
+public class CompositeMethodModelFormatter extends AbstractJsonFormatter<MethodDescriptor, Void>
+{
+    public CompositeMethodModelFormatter( JSONWriter writer )
+    {
+        super(writer);
+    }
+
+    @Override
+    public void enter( MethodDescriptor visited )
+        throws JSONException
+    {
+        object();
+        field("method", visited.method().getName() );
+    }
+
+    @Override
+    public void leave( MethodDescriptor visited )
+        throws JSONException
+    {
+        endObject();
+    }
+
+    @Override
+    public void visit( Void visited )
+        throws JSONException
+    {
+
+    }
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ConstructorModelFormatter.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ConstructorModelFormatter.java
new file mode 100644
index 0000000..8f864dd
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ConstructorModelFormatter.java
@@ -0,0 +1,53 @@
+/*
+ * 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.polygene.library.appbrowser.json;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+import org.apache.polygene.api.composite.ConstructorDescriptor;
+
+public class ConstructorModelFormatter extends AbstractJsonFormatter<ConstructorDescriptor,Void>
+{
+    public ConstructorModelFormatter( JSONWriter writer )
+    {
+        super( writer );
+    }
+
+    @Override
+    public void enter( ConstructorDescriptor visited )
+        throws JSONException
+    {
+        object();
+        field( "name", visited.constructor().getName() );
+    }
+
+    @Override
+    public void leave( ConstructorDescriptor visited )
+        throws JSONException
+    {
+        endObject();
+    }
+
+    @Override
+    public void visit( Void visited )
+        throws JSONException
+    {
+
+    }
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/EntityModelFormatter.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/EntityModelFormatter.java
new file mode 100644
index 0000000..70d0d9e
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/EntityModelFormatter.java
@@ -0,0 +1,56 @@
+/*
+ * 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.polygene.library.appbrowser.json;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+import org.apache.polygene.api.entity.EntityDescriptor;
+
+public class EntityModelFormatter extends AbstractJsonFormatter<EntityDescriptor, Void>
+{
+
+    public EntityModelFormatter( JSONWriter writer )
+    {
+        super( writer );
+    }
+
+    @Override
+    public void enter( EntityDescriptor visited )
+        throws JSONException
+    {
+        object();
+        field( "type", visited.primaryType().getName() );
+        field( "visibility", visited.visibility().toString() );
+        field( "queryable", visited.queryable() );
+    }
+
+    @Override
+    public void leave( EntityDescriptor visited )
+        throws JSONException
+    {
+        endObject();
+    }
+
+    @Override
+    public void visit( Void visited )
+        throws JSONException
+    {
+
+    }
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/InjectedFieldModelFormatter.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/InjectedFieldModelFormatter.java
new file mode 100644
index 0000000..75a216e
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/InjectedFieldModelFormatter.java
@@ -0,0 +1,60 @@
+/*
+ * 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.polygene.library.appbrowser.json;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+import org.apache.polygene.api.composite.DependencyDescriptor;
+import org.apache.polygene.api.composite.InjectedFieldDescriptor;
+import org.apache.polygene.library.appbrowser.Formatter;
+
+public class InjectedFieldModelFormatter extends AbstractJsonFormatter<InjectedFieldDescriptor, DependencyDescriptor>
+{
+    public InjectedFieldModelFormatter( JSONWriter writer )
+    {
+        super(writer);
+    }
+
+    @Override
+    public void enter( InjectedFieldDescriptor visited )
+        throws JSONException
+    {
+        object();
+        field("name", visited.field().getName() );
+//        field( "optional", visited.optional() );
+//        field( "injectedclass", visited.injectedClass().getName() );
+//        field( "injectedannotation", visited.injectionAnnotation().toString() );
+//        field( "injectedtype", visited.injectionType().toString() );
+//        field( "rawinjectectiontype", visited.rawInjectionType().getName() );
+    }
+
+    @Override
+    public void leave( InjectedFieldDescriptor visited )
+        throws JSONException
+    {
+        endObject();
+    }
+
+    @Override
+    public void visit( DependencyDescriptor visited )
+        throws JSONException
+    {
+
+    }
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/JsonFormatterFactory.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/JsonFormatterFactory.java
new file mode 100644
index 0000000..5c7748a
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/JsonFormatterFactory.java
@@ -0,0 +1,107 @@
+/*
+ * 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.polygene.library.appbrowser.json;
+
+import java.io.Writer;
+import org.json.JSONWriter;
+import org.apache.polygene.library.appbrowser.Formatter;
+import org.apache.polygene.library.appbrowser.FormatterFactory;
+
+public class JsonFormatterFactory
+    implements FormatterFactory
+{
+    private static final NullFormatter NULL_FORMATTER = new NullFormatter();
+    private final JSONWriter writer;
+
+    public JsonFormatterFactory(Writer destination)
+    {
+        writer = new JSONWriter( destination );
+    }
+
+    @Override
+    public Formatter create( String componentType )
+    {
+        if( componentType.equalsIgnoreCase( "ApplicationModel" ))
+            return new ApplicationModelFormatter( writer );
+        if( componentType.equalsIgnoreCase( "LayerModel" ))
+            return new LayerModelFormatter( writer );
+        if( componentType.equalsIgnoreCase( "ModuleModel" ))
+            return new ModuleModelFormatter( writer );
+        if( componentType.equalsIgnoreCase( "TransientsModel" ))
+            return new ArrayFormatter(writer, "transients");
+        if( componentType.equalsIgnoreCase( "EntitiesModel" ))
+            return new ArrayFormatter(writer, "entities");
+        if( componentType.equalsIgnoreCase( "ServicesModel" ))
+            return new ArrayFormatter(writer, "services");
+        if( componentType.equalsIgnoreCase( "ServiceModel" ))
+            return new ServiceModelFormatter
+                (writer);
+        if( componentType.equalsIgnoreCase( "ValuesModel" ))
+            return new ArrayFormatter(writer, "values");
+        if( componentType.equalsIgnoreCase( "ValueModel" ))
+            return new ValueModelFormatter(writer);
+        if( componentType.equalsIgnoreCase( "ValueStateModel" ))
+            return NULL_FORMATTER;
+        if( componentType.equalsIgnoreCase( "EntityModel" ))
+            return new EntityModelFormatter( writer );
+        if( componentType.equalsIgnoreCase( "CompositeMethodsModel" ))
+            return new ArrayFormatter( writer, "methods" );
+        if( componentType.equalsIgnoreCase( "CompositeMethodModel" ))
+            return new CompositeMethodModelFormatter(writer);
+        if( componentType.equalsIgnoreCase( "ObjectsModel" ))
+            return new ArrayFormatter( writer, "objects" );
+        if( componentType.equalsIgnoreCase( "ConstraintsModel" ))
+            return new ArrayFormatter( writer, "constraints" );
+        if( componentType.equalsIgnoreCase( "SideEffectsModel" ))
+            return new ArrayFormatter( writer, "sideeffects" );
+        if( componentType.equalsIgnoreCase( "ConcernsModel" ))
+            return new ArrayFormatter( writer, "concerns" );
+        if( componentType.equalsIgnoreCase( "PropertiesModel" ))
+            return new ArrayFormatter( writer, "properties" );
+        if( componentType.equalsIgnoreCase( "ConstructorsModel" ))
+            return new ArrayFormatter( writer, "constructors" );
+        if( componentType.equalsIgnoreCase( "ConstructorModel" ))
+            return new ConstructorModelFormatter( writer );
+        if( componentType.equalsIgnoreCase( "EntityMixinsModel" ))
+            return new ArrayFormatter( writer, "mixins" );
+        if( componentType.equalsIgnoreCase( "MixinsModel" ))
+            return new ArrayFormatter( writer, "mixins" );
+        if( componentType.equalsIgnoreCase( "MixinModel" ))
+            return new MixinModelFormatter( writer );
+        if( componentType.equalsIgnoreCase( "AssociationsModel" ))
+            return new ArrayFormatter( writer, "associations" );
+        if( componentType.equalsIgnoreCase( "ManyAssociationsModel" ))
+            return new ArrayFormatter( writer, "manyassociations" );
+        if( componentType.equalsIgnoreCase( "InjectedFieldsModel" ))
+            return new ArrayFormatter( writer, "injectedfields" );
+        if( componentType.equalsIgnoreCase( "InjectedFieldModel" ))
+            return new InjectedFieldModelFormatter(writer);
+        if( componentType.equalsIgnoreCase( "InjectedMethodsModel" ))
+            return new ArrayFormatter( writer, "injectedmethods" );
+        if( componentType.equalsIgnoreCase( "InjectedParametersModel" ))
+            return new ArrayFormatter( writer, "injectedparameters" );
+        if( componentType.equalsIgnoreCase( "EntityStateModel" ))
+            return NULL_FORMATTER;
+        if( componentType.equalsIgnoreCase( "ObjectModel" ))
+            return new ObjectModelFormatter(writer);
+        if( componentType.equalsIgnoreCase( "ImportedServicesModel" ))
+            return NULL_FORMATTER;
+        return null;
+    }
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/LayerModelFormatter.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/LayerModelFormatter.java
new file mode 100644
index 0000000..f55c475
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/LayerModelFormatter.java
@@ -0,0 +1,62 @@
+/*
+ * 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.polygene.library.appbrowser.json;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.UsedLayersDescriptor;
+
+public class LayerModelFormatter extends AbstractJsonFormatter<LayerDescriptor, Void>
+{
+    public LayerModelFormatter( JSONWriter writer )
+    {
+        super( writer );
+    }
+
+    @Override
+    public void enter( LayerDescriptor visited )
+        throws JSONException
+    {
+        object();
+        field( "name", visited.name() );
+        array( "uses" );
+        UsedLayersDescriptor usedLayersDescriptor = visited.usedLayers();
+        for( LayerDescriptor used : usedLayersDescriptor.layers() )
+        {
+            value( used.name() );
+        }
+        endArray();
+        array( "modules" );
+    }
+
+    @Override
+    public void leave( LayerDescriptor visited )
+        throws JSONException
+    {
+        endArray();
+        endObject();
+    }
+
+    @Override
+    public void visit( Void visited )
+        throws JSONException
+    {
+    }
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/MixinModelFormatter.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/MixinModelFormatter.java
new file mode 100644
index 0000000..3254e58
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/MixinModelFormatter.java
@@ -0,0 +1,53 @@
+/*
+ * 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.polygene.library.appbrowser.json;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+import org.apache.polygene.api.mixin.MixinDescriptor;
+
+public class MixinModelFormatter extends AbstractJsonFormatter<MixinDescriptor, Void>
+{
+    public MixinModelFormatter( JSONWriter writer )
+    {
+        super( writer );
+    }
+
+    @Override
+    public void enter( MixinDescriptor visited )
+        throws JSONException
+    {
+        object();
+        field( "mixin", visited.mixinClass().getName() );
+    }
+
+    @Override
+    public void leave( MixinDescriptor visited )
+        throws JSONException
+    {
+        endObject();
+    }
+
+    @Override
+    public void visit( Void visited )
+        throws JSONException
+    {
+
+    }
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ModuleModelFormatter.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ModuleModelFormatter.java
new file mode 100644
index 0000000..1ea5c34
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ModuleModelFormatter.java
@@ -0,0 +1,54 @@
+/*
+ * 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.polygene.library.appbrowser.json;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.library.appbrowser.Formatter;
+
+public class ModuleModelFormatter extends AbstractJsonFormatter<ModuleDescriptor, Void>
+{
+
+    public ModuleModelFormatter( JSONWriter writer )
+    {
+        super( writer );
+    }
+
+    @Override
+    public void enter( ModuleDescriptor visited )
+        throws JSONException
+    {
+        object();
+        field( "name", visited.name() );
+    }
+
+    @Override
+    public void leave( ModuleDescriptor visited )
+        throws JSONException
+    {
+        endObject();
+    }
+
+    @Override
+    public void visit( Void visited )
+        throws JSONException
+    {
+    }
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/NullFormatter.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/NullFormatter.java
new file mode 100644
index 0000000..6cb3e59
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/NullFormatter.java
@@ -0,0 +1,48 @@
+/*
+ * 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.polygene.library.appbrowser.json;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+import org.apache.polygene.library.appbrowser.Formatter;
+
+public class NullFormatter
+    implements Formatter<Object, Object>
+{
+    @Override
+    public void enter( Object visited )
+        throws JSONException
+    {
+
+    }
+
+    @Override
+    public void leave( Object visited )
+        throws JSONException
+    {
+
+    }
+
+    @Override
+    public void visit( Object visited )
+        throws JSONException
+    {
+
+    }
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ObjectModelFormatter.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ObjectModelFormatter.java
new file mode 100644
index 0000000..959edad
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ObjectModelFormatter.java
@@ -0,0 +1,53 @@
+/*
+ * 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.polygene.library.appbrowser.json;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+import org.apache.polygene.api.object.ObjectDescriptor;
+
+public class ObjectModelFormatter extends AbstractJsonFormatter<ObjectDescriptor, Void>
+{
+    public ObjectModelFormatter( JSONWriter writer )
+    {
+        super(writer);
+    }
+
+    @Override
+    public void enter( ObjectDescriptor visited )
+        throws JSONException
+    {
+        object();
+        field( "visibility", visited.visibility().toString());
+    }
+
+    @Override
+    public void leave( ObjectDescriptor visited )
+        throws JSONException
+    {
+        endObject();
+    }
+
+    @Override
+    public void visit( Void visited )
+        throws JSONException
+    {
+
+    }
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ServiceModelFormatter.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ServiceModelFormatter.java
new file mode 100644
index 0000000..97a14e9
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ServiceModelFormatter.java
@@ -0,0 +1,61 @@
+/*
+ * 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.polygene.library.appbrowser.json;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+import org.apache.polygene.api.service.ServiceDescriptor;
+
+public class ServiceModelFormatter extends AbstractJsonFormatter<ServiceDescriptor, Void>
+{
+    public ServiceModelFormatter( JSONWriter writer )
+    {
+        super( writer );
+    }
+
+    @Override
+    public void enter( ServiceDescriptor visited )
+        throws JSONException
+    {
+        object();
+        field( "identity", visited.identity() );
+        field( "type", visited.primaryType().getName() );
+        field( "visibility", visited.visibility().toString() );
+        Class<Object> config = visited.configurationType();
+        if( config != null )
+        {
+            field( "configuration", config.getName() );
+        }
+        field( "instantiateOnStartup", visited.isInstantiateOnStartup() );
+    }
+
+    @Override
+    public void leave( ServiceDescriptor visited )
+        throws JSONException
+    {
+        endObject();
+    }
+
+    @Override
+    public void visit( Void visited )
+        throws JSONException
+    {
+
+    }
+}
diff --git a/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ValueModelFormatter.java b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ValueModelFormatter.java
new file mode 100644
index 0000000..48aa399
--- /dev/null
+++ b/libraries/appbrowser/src/main/java/org/apache/polygene/library/appbrowser/json/ValueModelFormatter.java
@@ -0,0 +1,55 @@
+/*
+ * 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.polygene.library.appbrowser.json;
+
+import org.json.JSONException;
+import org.json.JSONWriter;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.library.appbrowser.Formatter;
+
+public class ValueModelFormatter extends AbstractJsonFormatter<ValueDescriptor,Void>
+{
+    public ValueModelFormatter( JSONWriter writer )
+    {
+        super(writer);
+    }
+
+    @Override
+    public void enter( ValueDescriptor visited )
+        throws JSONException
+    {
+        object();
+        field( "type", visited.valueType().primaryType().getName() );
+        field( "visibility", visited.visibility().toString() );
+    }
+
+    @Override
+    public void leave( ValueDescriptor visited )
+        throws JSONException
+    {
+        endObject();
+    }
+
+    @Override
+    public void visit( Void visited )
+        throws JSONException
+    {
+
+    }
+}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/Browser.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/Browser.java
deleted file mode 100644
index ab3d00a..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/Browser.java
+++ /dev/null
@@ -1,109 +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.qi4j.library.appbrowser;
-
-import java.util.Stack;
-import org.json.JSONException;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.functional.HierarchicalVisitor;
-
-public class Browser
-{
-    private final ApplicationDescriptor application;
-    private final FormatterFactory factory;
-    private final Stack<Formatter> stack = new Stack<>();
-
-    public Browser( ApplicationDescriptor application, FormatterFactory factory )
-    {
-        this.application = application;
-        this.factory = factory;
-    }
-
-    public void toJson()
-        throws BrowserException
-    {
-        application.accept( new HierarchicalVisitor<Object, Object, BrowserException>()
-        {
-            @Override
-            public boolean visitEnter( Object visited )
-                throws BrowserException
-            {
-                String simpleName = visited.getClass().getSimpleName();
-                Formatter formatter = factory.create( simpleName );
-                stack.push(formatter);
-                if( formatter == null )
-                {
-                    System.err.println( "Unknown application component: " + visited.getClass() );
-                    return false;
-                }
-                try
-                {
-                    formatter.enter( visited );
-                }
-                catch( JSONException e )
-                {
-                    throw new BrowserException( "Formatting failed.", e );
-                }
-                return true;
-            }
-
-            @Override
-            public boolean visitLeave( Object visited )
-                throws BrowserException
-            {
-                Formatter formatter = stack.pop();
-                if( formatter == null )
-                {
-                    System.err.println( "Unknown application component: " + visited.getClass() );
-                    return false;
-                }
-                try
-                {
-                    formatter.leave( visited );
-                }
-                catch( JSONException e )
-                {
-                    throw new BrowserException( "Formatting failed.", e );
-                }
-                return true;
-            }
-
-            @Override
-            public boolean visit( Object visited )
-                throws BrowserException
-            {
-                Formatter formatter = stack.peek();
-                if( formatter == null )
-                {
-                    System.err.println( "Unknown application component: " + visited.getClass() );
-                    return false;
-                }
-                try
-                {
-                    formatter.visit( visited );
-                }
-                catch( JSONException e )
-                {
-                    throw new BrowserException( "Formatting failed.", e );
-                }
-                return true;
-            }
-        } );
-    }
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/BrowserException.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/BrowserException.java
deleted file mode 100644
index e6ff93c..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/BrowserException.java
+++ /dev/null
@@ -1,29 +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.qi4j.library.appbrowser;
-
-import org.json.JSONException;
-
-public class BrowserException extends RuntimeException
-{
-    public BrowserException( String message, JSONException exception )
-    {
-        super( message, exception);
-    }
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/Formatter.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/Formatter.java
deleted file mode 100644
index a7ccca3..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/Formatter.java
+++ /dev/null
@@ -1,34 +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.qi4j.library.appbrowser;
-
-import org.json.JSONException;
-
-public interface Formatter<NODE, LEAF>
-{
-
-    void enter( NODE visited )
-        throws JSONException;
-
-    void leave( NODE visited )
-        throws JSONException;
-
-    void visit( LEAF visited )
-        throws JSONException;
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/FormatterFactory.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/FormatterFactory.java
deleted file mode 100644
index ca77160..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/FormatterFactory.java
+++ /dev/null
@@ -1,25 +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.qi4j.library.appbrowser;
-
-public interface FormatterFactory
-{
-
-    Formatter create( String componentType );
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/AbstractJsonFormatter.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/AbstractJsonFormatter.java
deleted file mode 100644
index 46a419f..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/AbstractJsonFormatter.java
+++ /dev/null
@@ -1,85 +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.qi4j.library.appbrowser.json;
-
-import org.json.JSONException;
-import org.json.JSONWriter;
-import org.qi4j.library.appbrowser.Formatter;
-
-public abstract class AbstractJsonFormatter<NODE,LEAF>
-    implements Formatter<NODE, LEAF>
-{
-    private final JSONWriter writer;
-
-    public AbstractJsonFormatter( JSONWriter writer )
-    {
-        this.writer = writer;
-    }
-
-    protected void field( String name, String value )
-        throws JSONException
-    {
-        writer.key( name ).value(value);
-    }
-
-    protected void field( String name, boolean value )
-        throws JSONException
-    {
-        writer.key( name ).value(value);
-    }
-
-    protected void array( String name )
-        throws JSONException
-    {
-        writer.key(name);
-        writer.array();
-    }
-
-    protected void endArray()
-        throws JSONException
-    {
-        writer.endArray();
-    }
-
-    protected void object()
-        throws JSONException
-    {
-        writer.object();
-    }
-
-    protected void object(String name)
-        throws JSONException
-    {
-        writer.key(name);
-        writer.object();
-    }
-
-    protected void endObject()
-        throws JSONException
-    {
-        writer.endObject();
-    }
-
-    protected void value( Object value )
-        throws JSONException
-    {
-        writer.value( value );
-    }
-
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ApplicationModelFormatter.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ApplicationModelFormatter.java
deleted file mode 100644
index 73e963d..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ApplicationModelFormatter.java
+++ /dev/null
@@ -1,56 +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.qi4j.library.appbrowser.json;
-
-import org.json.JSONException;
-import org.json.JSONWriter;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.library.appbrowser.Formatter;
-
-public class ApplicationModelFormatter extends AbstractJsonFormatter<ApplicationDescriptor, Void>
-{
-
-    public ApplicationModelFormatter( JSONWriter writer )
-    {
-        super( writer );
-    }
-
-    @Override
-    public void enter( ApplicationDescriptor visited )
-        throws JSONException
-    {
-        object();
-        field( "name", visited.name() );
-        array("layers");
-    }
-
-    @Override
-    public void leave( ApplicationDescriptor visited )
-        throws JSONException
-    {
-        endArray();
-        endObject();
-    }
-
-    @Override
-    public void visit( Void visited )
-        throws JSONException
-    {
-    }
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ArrayFormatter.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ArrayFormatter.java
deleted file mode 100644
index 8314ea2..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ArrayFormatter.java
+++ /dev/null
@@ -1,56 +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.qi4j.library.appbrowser.json;
-
-import org.json.JSONException;
-import org.json.JSONWriter;
-import org.qi4j.library.appbrowser.Formatter;
-
-public class ArrayFormatter extends AbstractJsonFormatter
-    implements Formatter
-{
-    private final String name;
-
-    public ArrayFormatter( JSONWriter writer, String name )
-    {
-        super(writer);
-        this.name = name;
-    }
-
-    @Override
-    public void enter( Object visited )
-        throws JSONException
-    {
-        array(name);
-    }
-
-    @Override
-    public void leave( Object visited )
-        throws JSONException
-    {
-        endArray();
-    }
-
-    @Override
-    public void visit( Object visited )
-        throws JSONException
-    {
-
-    }
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/CompositeMethodModelFormatter.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/CompositeMethodModelFormatter.java
deleted file mode 100644
index 5ca24d2..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/CompositeMethodModelFormatter.java
+++ /dev/null
@@ -1,54 +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.qi4j.library.appbrowser.json;
-
-import org.json.JSONException;
-import org.json.JSONWriter;
-import org.qi4j.api.composite.MethodDescriptor;
-import org.qi4j.library.appbrowser.Formatter;
-
-public class CompositeMethodModelFormatter extends AbstractJsonFormatter<MethodDescriptor, Void>
-{
-    public CompositeMethodModelFormatter( JSONWriter writer )
-    {
-        super(writer);
-    }
-
-    @Override
-    public void enter( MethodDescriptor visited )
-        throws JSONException
-    {
-        object();
-        field("method", visited.method().getName() );
-    }
-
-    @Override
-    public void leave( MethodDescriptor visited )
-        throws JSONException
-    {
-        endObject();
-    }
-
-    @Override
-    public void visit( Void visited )
-        throws JSONException
-    {
-
-    }
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ConstructorModelFormatter.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ConstructorModelFormatter.java
deleted file mode 100644
index c94749f..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ConstructorModelFormatter.java
+++ /dev/null
@@ -1,53 +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.qi4j.library.appbrowser.json;
-
-import org.json.JSONException;
-import org.json.JSONWriter;
-import org.qi4j.api.composite.ConstructorDescriptor;
-
-public class ConstructorModelFormatter extends AbstractJsonFormatter<ConstructorDescriptor,Void>
-{
-    public ConstructorModelFormatter( JSONWriter writer )
-    {
-        super( writer );
-    }
-
-    @Override
-    public void enter( ConstructorDescriptor visited )
-        throws JSONException
-    {
-        object();
-        field( "name", visited.constructor().getName() );
-    }
-
-    @Override
-    public void leave( ConstructorDescriptor visited )
-        throws JSONException
-    {
-        endObject();
-    }
-
-    @Override
-    public void visit( Void visited )
-        throws JSONException
-    {
-
-    }
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/EntityModelFormatter.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/EntityModelFormatter.java
deleted file mode 100644
index 5211917..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/EntityModelFormatter.java
+++ /dev/null
@@ -1,56 +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.qi4j.library.appbrowser.json;
-
-import org.json.JSONException;
-import org.json.JSONWriter;
-import org.qi4j.api.entity.EntityDescriptor;
-
-public class EntityModelFormatter extends AbstractJsonFormatter<EntityDescriptor, Void>
-{
-
-    public EntityModelFormatter( JSONWriter writer )
-    {
-        super( writer );
-    }
-
-    @Override
-    public void enter( EntityDescriptor visited )
-        throws JSONException
-    {
-        object();
-        field( "type", visited.primaryType().getName() );
-        field( "visibility", visited.visibility().toString() );
-        field( "queryable", visited.queryable() );
-    }
-
-    @Override
-    public void leave( EntityDescriptor visited )
-        throws JSONException
-    {
-        endObject();
-    }
-
-    @Override
-    public void visit( Void visited )
-        throws JSONException
-    {
-
-    }
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/InjectedFieldModelFormatter.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/InjectedFieldModelFormatter.java
deleted file mode 100644
index 91334f1..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/InjectedFieldModelFormatter.java
+++ /dev/null
@@ -1,60 +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.qi4j.library.appbrowser.json;
-
-import org.json.JSONException;
-import org.json.JSONWriter;
-import org.qi4j.api.composite.DependencyDescriptor;
-import org.qi4j.api.composite.InjectedFieldDescriptor;
-import org.qi4j.library.appbrowser.Formatter;
-
-public class InjectedFieldModelFormatter extends AbstractJsonFormatter<InjectedFieldDescriptor, DependencyDescriptor>
-{
-    public InjectedFieldModelFormatter( JSONWriter writer )
-    {
-        super(writer);
-    }
-
-    @Override
-    public void enter( InjectedFieldDescriptor visited )
-        throws JSONException
-    {
-        object();
-        field("name", visited.field().getName() );
-//        field( "optional", visited.optional() );
-//        field( "injectedclass", visited.injectedClass().getName() );
-//        field( "injectedannotation", visited.injectionAnnotation().toString() );
-//        field( "injectedtype", visited.injectionType().toString() );
-//        field( "rawinjectectiontype", visited.rawInjectionType().getName() );
-    }
-
-    @Override
-    public void leave( InjectedFieldDescriptor visited )
-        throws JSONException
-    {
-        endObject();
-    }
-
-    @Override
-    public void visit( DependencyDescriptor visited )
-        throws JSONException
-    {
-
-    }
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/JsonFormatterFactory.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/JsonFormatterFactory.java
deleted file mode 100644
index 50d24e4..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/JsonFormatterFactory.java
+++ /dev/null
@@ -1,107 +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.qi4j.library.appbrowser.json;
-
-import java.io.Writer;
-import org.json.JSONWriter;
-import org.qi4j.library.appbrowser.Formatter;
-import org.qi4j.library.appbrowser.FormatterFactory;
-
-public class JsonFormatterFactory
-    implements FormatterFactory
-{
-    private static final NullFormatter NULL_FORMATTER = new NullFormatter();
-    private final JSONWriter writer;
-
-    public JsonFormatterFactory(Writer destination)
-    {
-        writer = new JSONWriter( destination );
-    }
-
-    @Override
-    public Formatter create( String componentType )
-    {
-        if( componentType.equalsIgnoreCase( "ApplicationModel" ))
-            return new ApplicationModelFormatter( writer );
-        if( componentType.equalsIgnoreCase( "LayerModel" ))
-            return new LayerModelFormatter( writer );
-        if( componentType.equalsIgnoreCase( "ModuleModel" ))
-            return new ModuleModelFormatter( writer );
-        if( componentType.equalsIgnoreCase( "TransientsModel" ))
-            return new ArrayFormatter(writer, "transients");
-        if( componentType.equalsIgnoreCase( "EntitiesModel" ))
-            return new ArrayFormatter(writer, "entities");
-        if( componentType.equalsIgnoreCase( "ServicesModel" ))
-            return new ArrayFormatter(writer, "services");
-        if( componentType.equalsIgnoreCase( "ServiceModel" ))
-            return new ServiceModelFormatter
-                (writer);
-        if( componentType.equalsIgnoreCase( "ValuesModel" ))
-            return new ArrayFormatter(writer, "values");
-        if( componentType.equalsIgnoreCase( "ValueModel" ))
-            return new ValueModelFormatter(writer);
-        if( componentType.equalsIgnoreCase( "ValueStateModel" ))
-            return NULL_FORMATTER;
-        if( componentType.equalsIgnoreCase( "EntityModel" ))
-            return new EntityModelFormatter( writer );
-        if( componentType.equalsIgnoreCase( "CompositeMethodsModel" ))
-            return new ArrayFormatter( writer, "methods" );
-        if( componentType.equalsIgnoreCase( "CompositeMethodModel" ))
-            return new CompositeMethodModelFormatter(writer);
-        if( componentType.equalsIgnoreCase( "ObjectsModel" ))
-            return new ArrayFormatter( writer, "objects" );
-        if( componentType.equalsIgnoreCase( "ConstraintsModel" ))
-            return new ArrayFormatter( writer, "constraints" );
-        if( componentType.equalsIgnoreCase( "SideEffectsModel" ))
-            return new ArrayFormatter( writer, "sideeffects" );
-        if( componentType.equalsIgnoreCase( "ConcernsModel" ))
-            return new ArrayFormatter( writer, "concerns" );
-        if( componentType.equalsIgnoreCase( "PropertiesModel" ))
-            return new ArrayFormatter( writer, "properties" );
-        if( componentType.equalsIgnoreCase( "ConstructorsModel" ))
-            return new ArrayFormatter( writer, "constructors" );
-        if( componentType.equalsIgnoreCase( "ConstructorModel" ))
-            return new ConstructorModelFormatter( writer );
-        if( componentType.equalsIgnoreCase( "EntityMixinsModel" ))
-            return new ArrayFormatter( writer, "mixins" );
-        if( componentType.equalsIgnoreCase( "MixinsModel" ))
-            return new ArrayFormatter( writer, "mixins" );
-        if( componentType.equalsIgnoreCase( "MixinModel" ))
-            return new MixinModelFormatter( writer );
-        if( componentType.equalsIgnoreCase( "AssociationsModel" ))
-            return new ArrayFormatter( writer, "associations" );
-        if( componentType.equalsIgnoreCase( "ManyAssociationsModel" ))
-            return new ArrayFormatter( writer, "manyassociations" );
-        if( componentType.equalsIgnoreCase( "InjectedFieldsModel" ))
-            return new ArrayFormatter( writer, "injectedfields" );
-        if( componentType.equalsIgnoreCase( "InjectedFieldModel" ))
-            return new InjectedFieldModelFormatter(writer);
-        if( componentType.equalsIgnoreCase( "InjectedMethodsModel" ))
-            return new ArrayFormatter( writer, "injectedmethods" );
-        if( componentType.equalsIgnoreCase( "InjectedParametersModel" ))
-            return new ArrayFormatter( writer, "injectedparameters" );
-        if( componentType.equalsIgnoreCase( "EntityStateModel" ))
-            return NULL_FORMATTER;
-        if( componentType.equalsIgnoreCase( "ObjectModel" ))
-            return new ObjectModelFormatter(writer);
-        if( componentType.equalsIgnoreCase( "ImportedServicesModel" ))
-            return NULL_FORMATTER;
-        return null;
-    }
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/LayerModelFormatter.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/LayerModelFormatter.java
deleted file mode 100644
index 4f9f2b7..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/LayerModelFormatter.java
+++ /dev/null
@@ -1,62 +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.qi4j.library.appbrowser.json;
-
-import org.json.JSONException;
-import org.json.JSONWriter;
-import org.qi4j.api.structure.LayerDescriptor;
-import org.qi4j.api.structure.UsedLayersDescriptor;
-
-public class LayerModelFormatter extends AbstractJsonFormatter<LayerDescriptor, Void>
-{
-    public LayerModelFormatter( JSONWriter writer )
-    {
-        super( writer );
-    }
-
-    @Override
-    public void enter( LayerDescriptor visited )
-        throws JSONException
-    {
-        object();
-        field( "name", visited.name() );
-        array( "uses" );
-        UsedLayersDescriptor usedLayersDescriptor = visited.usedLayers();
-        for( LayerDescriptor used : usedLayersDescriptor.layers() )
-        {
-            value( used.name() );
-        }
-        endArray();
-        array( "modules" );
-    }
-
-    @Override
-    public void leave( LayerDescriptor visited )
-        throws JSONException
-    {
-        endArray();
-        endObject();
-    }
-
-    @Override
-    public void visit( Void visited )
-        throws JSONException
-    {
-    }
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/MixinModelFormatter.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/MixinModelFormatter.java
deleted file mode 100644
index be7b1ad..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/MixinModelFormatter.java
+++ /dev/null
@@ -1,53 +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.qi4j.library.appbrowser.json;
-
-import org.json.JSONException;
-import org.json.JSONWriter;
-import org.qi4j.api.mixin.MixinDescriptor;
-
-public class MixinModelFormatter extends AbstractJsonFormatter<MixinDescriptor, Void>
-{
-    public MixinModelFormatter( JSONWriter writer )
-    {
-        super( writer );
-    }
-
-    @Override
-    public void enter( MixinDescriptor visited )
-        throws JSONException
-    {
-        object();
-        field( "mixin", visited.mixinClass().getName() );
-    }
-
-    @Override
-    public void leave( MixinDescriptor visited )
-        throws JSONException
-    {
-        endObject();
-    }
-
-    @Override
-    public void visit( Void visited )
-        throws JSONException
-    {
-
-    }
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ModuleModelFormatter.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ModuleModelFormatter.java
deleted file mode 100644
index 271fded..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ModuleModelFormatter.java
+++ /dev/null
@@ -1,54 +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.qi4j.library.appbrowser.json;
-
-import org.json.JSONException;
-import org.json.JSONWriter;
-import org.qi4j.api.structure.ModuleDescriptor;
-import org.qi4j.library.appbrowser.Formatter;
-
-public class ModuleModelFormatter extends AbstractJsonFormatter<ModuleDescriptor, Void>
-{
-
-    public ModuleModelFormatter( JSONWriter writer )
-    {
-        super( writer );
-    }
-
-    @Override
-    public void enter( ModuleDescriptor visited )
-        throws JSONException
-    {
-        object();
-        field( "name", visited.name() );
-    }
-
-    @Override
-    public void leave( ModuleDescriptor visited )
-        throws JSONException
-    {
-        endObject();
-    }
-
-    @Override
-    public void visit( Void visited )
-        throws JSONException
-    {
-    }
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/NullFormatter.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/NullFormatter.java
deleted file mode 100644
index 4eb9cea..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/NullFormatter.java
+++ /dev/null
@@ -1,48 +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.qi4j.library.appbrowser.json;
-
-import org.json.JSONException;
-import org.json.JSONWriter;
-import org.qi4j.library.appbrowser.Formatter;
-
-public class NullFormatter
-    implements Formatter<Object, Object>
-{
-    @Override
-    public void enter( Object visited )
-        throws JSONException
-    {
-
-    }
-
-    @Override
-    public void leave( Object visited )
-        throws JSONException
-    {
-
-    }
-
-    @Override
-    public void visit( Object visited )
-        throws JSONException
-    {
-
-    }
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ObjectModelFormatter.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ObjectModelFormatter.java
deleted file mode 100644
index fa3b5de..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ObjectModelFormatter.java
+++ /dev/null
@@ -1,53 +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.qi4j.library.appbrowser.json;
-
-import org.json.JSONException;
-import org.json.JSONWriter;
-import org.qi4j.api.object.ObjectDescriptor;
-
-public class ObjectModelFormatter extends AbstractJsonFormatter<ObjectDescriptor, Void>
-{
-    public ObjectModelFormatter( JSONWriter writer )
-    {
-        super(writer);
-    }
-
-    @Override
-    public void enter( ObjectDescriptor visited )
-        throws JSONException
-    {
-        object();
-        field( "visibility", visited.visibility().toString());
-    }
-
-    @Override
-    public void leave( ObjectDescriptor visited )
-        throws JSONException
-    {
-        endObject();
-    }
-
-    @Override
-    public void visit( Void visited )
-        throws JSONException
-    {
-
-    }
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ServiceModelFormatter.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ServiceModelFormatter.java
deleted file mode 100644
index 385cdc1..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ServiceModelFormatter.java
+++ /dev/null
@@ -1,61 +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.qi4j.library.appbrowser.json;
-
-import org.json.JSONException;
-import org.json.JSONWriter;
-import org.qi4j.api.service.ServiceDescriptor;
-
-public class ServiceModelFormatter extends AbstractJsonFormatter<ServiceDescriptor, Void>
-{
-    public ServiceModelFormatter( JSONWriter writer )
-    {
-        super( writer );
-    }
-
-    @Override
-    public void enter( ServiceDescriptor visited )
-        throws JSONException
-    {
-        object();
-        field( "identity", visited.identity() );
-        field( "type", visited.primaryType().getName() );
-        field( "visibility", visited.visibility().toString() );
-        Class<Object> config = visited.configurationType();
-        if( config != null )
-        {
-            field( "configuration", config.getName() );
-        }
-        field( "instantiateOnStartup", visited.isInstantiateOnStartup() );
-    }
-
-    @Override
-    public void leave( ServiceDescriptor visited )
-        throws JSONException
-    {
-        endObject();
-    }
-
-    @Override
-    public void visit( Void visited )
-        throws JSONException
-    {
-
-    }
-}
diff --git a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ValueModelFormatter.java b/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ValueModelFormatter.java
deleted file mode 100644
index baacb5f..0000000
--- a/libraries/appbrowser/src/main/java/org/qi4j/library/appbrowser/json/ValueModelFormatter.java
+++ /dev/null
@@ -1,55 +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.qi4j.library.appbrowser.json;
-
-import org.json.JSONException;
-import org.json.JSONWriter;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.library.appbrowser.Formatter;
-
-public class ValueModelFormatter extends AbstractJsonFormatter<ValueDescriptor,Void>
-{
-    public ValueModelFormatter( JSONWriter writer )
-    {
-        super(writer);
-    }
-
-    @Override
-    public void enter( ValueDescriptor visited )
-        throws JSONException
-    {
-        object();
-        field( "type", visited.valueType().mainType().getName() );
-        field( "visibility", visited.visibility().toString() );
-    }
-
-    @Override
-    public void leave( ValueDescriptor visited )
-        throws JSONException
-    {
-        endObject();
-    }
-
-    @Override
-    public void visit( Void visited )
-        throws JSONException
-    {
-
-    }
-}
diff --git a/libraries/appbrowser/src/test/java/org/apache/polygene/library/appbrowser/AppBrowserTest.java b/libraries/appbrowser/src/test/java/org/apache/polygene/library/appbrowser/AppBrowserTest.java
new file mode 100644
index 0000000..3c59c82
--- /dev/null
+++ b/libraries/appbrowser/src/test/java/org/apache/polygene/library/appbrowser/AppBrowserTest.java
@@ -0,0 +1,165 @@
+/*
+ * 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.polygene.library.appbrowser;
+
+import java.io.StringWriter;
+import java.io.Writer;
+import org.junit.Test;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+import org.apache.polygene.library.appbrowser.json.JsonFormatterFactory;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+public class AppBrowserTest extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( Person.class );
+        module.values( Age.class );
+        module.services( MemoryEntityStoreService.class );
+    }
+
+    @Test
+    public void testBrowser()
+        throws Exception
+    {
+        Writer output = new StringWriter();
+        FormatterFactory jsonFactory = new JsonFormatterFactory( output );
+        Browser browser = new Browser( applicationModel, jsonFactory );
+        browser.toJson();
+    }
+
+    @Mixins( Person.Mixin.class )
+    @Concerns( Person.AgeLimitConcern.class )
+    public interface Person extends HasIdentity
+    {
+        String name();
+
+        int yearsOld();
+
+        interface State
+        {
+            Property<String> name();
+
+            Property<Age> age();
+
+            @Optional
+            Association<Person> spouse();
+
+            ManyAssociation<Person> children();
+        }
+
+        abstract class Mixin
+            implements Person
+        {
+
+            @This
+            private State state;
+
+            @Override
+            public String name()
+            {
+                return state.name().get();
+            }
+
+            @Override
+            public int yearsOld()
+            {
+                return state.age().get().numberOfYearsOld();
+            }
+        }
+
+        abstract class AgeLimitConcern extends ConcernOf<Person>
+            implements Person
+        {
+            @This
+            private Person me;
+            @Service
+            private AgeCheckService ageCheck;
+
+            @Override
+            public int yearsOld()
+            {
+                int years = next.yearsOld();
+                if( ageCheck.checkAge( identity(), years ))
+                    throw new DeathException( "Person is dead.");
+                return 0;
+            }
+        }
+    }
+
+    @Mixins( Age.AgeMixin.class )
+    public interface Age
+    {
+        Property<Integer> birthYear();
+
+        int numberOfYearsOld();
+
+        abstract class AgeMixin
+            implements Age
+        {
+
+            @Override
+            public int numberOfYearsOld()
+            {
+                return DateTime.now().getYearOfEra() - birthYear().get();
+            }
+        }
+    }
+
+    public static class DeathException extends RuntimeException
+    {
+        public DeathException( String message )
+        {
+            super( message );
+        }
+    }
+
+    @Mixins(AgeCheckService.AgeCheckerMixin.class)
+    public interface AgeCheckService
+    {
+
+        boolean checkAge( Property<Identity> identity, int years );
+
+        class AgeCheckerMixin
+            implements AgeCheckService
+        {
+
+            @Override
+            public boolean checkAge( Property<Identity> identity, int years )
+            {
+                double probabiility = years/(Math.random()*120+1);
+                return probabiility < 0.9;
+            }
+        }
+    }
+}
diff --git a/libraries/appbrowser/src/test/java/org/qi4j/library/appbrowser/AppBrowserTest.java b/libraries/appbrowser/src/test/java/org/qi4j/library/appbrowser/AppBrowserTest.java
deleted file mode 100644
index 2079456..0000000
--- a/libraries/appbrowser/src/test/java/org/qi4j/library/appbrowser/AppBrowserTest.java
+++ /dev/null
@@ -1,168 +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.qi4j.library.appbrowser;
-
-import java.io.StringWriter;
-import java.io.Writer;
-import org.joda.time.DateTime;
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.library.appbrowser.json.JsonFormatterFactory;
-import org.qi4j.test.AbstractQi4jTest;
-
-public class AppBrowserTest extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( Person.class );
-        module.values( Age.class );
-        module.services( MemoryEntityStoreService.class );
-        module.importedServices( ValueSerialization.class );
-    }
-
-    @Test
-    public void testBrowser()
-        throws Exception
-    {
-        Writer output = new StringWriter();
-        FormatterFactory jsonFactory = new JsonFormatterFactory( output );
-        Browser browser = new Browser( applicationModel, jsonFactory );
-        browser.toJson();
-    }
-
-    @Mixins( Person.Mixin.class )
-    @Concerns( Person.AgeLimitConcern.class )
-    public interface Person extends Identity
-    {
-        String name();
-
-        int yearsOld();
-
-        interface State
-        {
-            Property<String> name();
-
-            Property<Age> age();
-
-            @Optional
-            Association<Person> spouse();
-
-            ManyAssociation<Person> children();
-        }
-
-        abstract class Mixin
-            implements Person
-        {
-
-            @This
-            private State state;
-
-            @Override
-            public String name()
-            {
-                return state.name().get();
-            }
-
-            @Override
-            public int yearsOld()
-            {
-                return state.age().get().numberOfYearsOld();
-            }
-        }
-
-        abstract class AgeLimitConcern extends ConcernOf<Person>
-            implements Person
-        {
-            @This
-            private Person me;
-            @Service
-            private AgeCheckService ageCheck;
-
-            @Override
-            public int yearsOld()
-            {
-                int years = next.yearsOld();
-                if( ageCheck.checkAge( identity(), years ))
-                    throw new DeathException( "Person is dead.");
-                return 0;
-            }
-        }
-    }
-
-    @Mixins( Age.AgeMixin.class )
-    public interface Age
-    {
-        Property<Integer> birthYear();
-
-        int numberOfYearsOld();
-
-        abstract class AgeMixin
-            implements Age
-        {
-
-            @Override
-            public int numberOfYearsOld()
-            {
-                return DateTime.now().getYearOfEra() - birthYear().get();
-            }
-        }
-    }
-
-    public static class DeathException extends RuntimeException
-    {
-        public DeathException( String message )
-        {
-            super( message );
-        }
-    }
-
-    @Mixins(AgeCheckService.AgeCheckerMixin.class)
-    public interface AgeCheckService
-    {
-
-        boolean checkAge( Property<String> identity, int years );
-
-        class AgeCheckerMixin
-            implements AgeCheckService
-        {
-
-            @Override
-            public boolean checkAge( Property<String> identity, int years )
-            {
-                double probabiility = years/(Math.random()*120+1);
-                return probabiility < 0.9;
-            }
-        }
-    }
-}
diff --git a/libraries/circuitbreaker/build.gradle b/libraries/circuitbreaker/build.gradle
index d91bfa8..f9973c4 100644
--- a/libraries/circuitbreaker/build.gradle
+++ b/libraries/circuitbreaker/build.gradle
@@ -1,39 +1,47 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
+import org.apache.polygene.gradle.TaskGroups
 
-description = "Apache Zest™ Circuit Breaker Library provides a framework for connecting external resources, so that they can be disabled during re-play of events."
+apply plugin: 'polygene-library'
 
-jar { manifest {name = "Apache Zest™ Library - Circuit Breaker"}}
+description = "Apache Polygene™ Circuit Breaker Library provides a framework for connecting external resources, so that they can be disabled during re-play of events."
+
+jar { manifest { name = "Apache Polygene™ Library - Circuit Breaker" } }
 
 dependencies {
-    compile project( ':org.qi4j.core:org.qi4j.core.api' )
-    compile project( ':org.qi4j.libraries:org.qi4j.library.jmx' )
-    compile libraries.slf4j_api
+  api polygene.core.bootstrap
 
-    testCompile project( ':org.qi4j.core:org.qi4j.core.testsupport' )
-    testCompile libraries.awaitility
+  implementation polygene.library( 'jmx' )
+  implementation libraries.slf4j_api
 
-    testRuntime project( ':org.qi4j.core:org.qi4j.core.runtime' )
-    testRuntime libraries.logback
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+  testImplementation libraries.awaitility
+
+  testRuntimeOnly libraries.logback
 }
 
-task( runSample, dependsOn: 'testClasses', type: JavaExec ) {
-    main = 'org.qi4j.library.circuitbreaker.jmx.CircuitBreakerManagementTest'
-    classpath = sourceSets.test.runtimeClasspath
+task( runCircuitBreakerSample, dependsOn: 'testClasses', type: JavaExec ) {
+  group = TaskGroups.SAMPLES
+  description = "Runs $project.name sample."
+  main = 'org.apache.polygene.library.circuitbreaker.jmx.CircuitBreakerManagementSample'
+  classpath = sourceSets.test.runtimeClasspath
 }
diff --git a/libraries/circuitbreaker/dev-status.xml b/libraries/circuitbreaker/dev-status.xml
index 7cd8719..b59299c 100644
--- a/libraries/circuitbreaker/dev-status.xml
+++ b/libraries/circuitbreaker/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
     <status>
         <!--none,early,beta,stable,mature-->
         <codebase>stable</codebase>
diff --git a/libraries/circuitbreaker/src/docs/circuitbreaker.txt b/libraries/circuitbreaker/src/docs/circuitbreaker.txt
index 6706bd5..473f536 100644
--- a/libraries/circuitbreaker/src/docs/circuitbreaker.txt
+++ b/libraries/circuitbreaker/src/docs/circuitbreaker.txt
@@ -27,7 +27,7 @@
 
 The Circuit Breaker library provides a way to guard your application
 against faulty external systems (e.g. mail servers  being down, web
-services being down). It is used by many Zest™ Extensions and Libraries.
+services being down).
 
 There's a couple of differences between this implementation and others
 seen on the net, but we've also heavily borrowed from others. The
@@ -44,7 +44,7 @@
 advanced ones allow exceptions that be excepted to be registered, but in
 real cases this is not enough. Case in point is JDBC exceptions where
 you want to fail on "connect exception" but not necessarily "invalid SQL
-syntax". So instead we've leveraged `Specification` from <<core-functional,Core Functional API>> where
+syntax". So instead we've leveraged `Predicate` where
 you get to provide your own specification that can use any logic to
 determine whether a particular exception is ok or not.
 
@@ -54,7 +54,7 @@
 breakers.
 
 Fourth, if an external system is unavailable due to a circuitbreaker
-tripping it should be possible to expose this to other Zest™ services.
+tripping it should be possible to expose this to other Polygene™ services.
 There is a standard implementation of the Availability interface that
 delegates to a circuit breaker and the Enabled configuration flag, which
 is what we'd suspect will be used in most cases where external systems
@@ -64,13 +64,13 @@
 
 == Direct usage ==
 
-The CircuitBreaker can be used directly, even without using anything else from the Zest™ SDK.
+The CircuitBreaker can be used directly, even without using anything else from the Polygene™ SDK.
 
 Here is a code snippet that demonstrate how to create a CircuitBreaker and how it behave:
 
 [snippet,java]
 ----
-source=libraries/circuitbreaker/src/test/java/org/qi4j/library/circuitbreaker/CircuitBreakerTest.java
+source=libraries/circuitbreaker/src/test/java/org/apache/polygene/library/circuitbreaker/CircuitBreakerTest.java
 tag=direct
 ----
 
@@ -88,7 +88,7 @@
 
 [snippet,java]
 ----
-source=libraries/circuitbreaker/src/test/java/org/qi4j/library/circuitbreaker/BreaksCircuitOnThrowableTest.java
+source=libraries/circuitbreaker/src/test/java/org/apache/polygene/library/circuitbreaker/BreaksCircuitOnThrowableTest.java
 tag=service
 ----
 
@@ -106,14 +106,14 @@
 
 [snippet,java]
 ----
-source=libraries/circuitbreaker/src/test/java/org/qi4j/library/circuitbreaker/jmx/CircuitBreakerManagementSample.java
+source=libraries/circuitbreaker/src/test/java/org/apache/polygene/library/circuitbreaker/jmx/CircuitBreakerManagementSample.java
 tag=jmx
 ----
 
 
 == Interactive sample ==
 
-A gradle task runSample is defined in this library as a shortcut to run a
+From the sources you can run the `runCircuitBreakerSample` Gradle task to run a
 simple interactive example. You'll need a MBean client to connect to the
 sample, VisualVM with its MBean plugin does the job. See <<build-system>>
 if you need some guidance.
diff --git a/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/CircuitBreaker.java b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/CircuitBreaker.java
new file mode 100644
index 0000000..72fbb0e
--- /dev/null
+++ b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/CircuitBreaker.java
@@ -0,0 +1,235 @@
+/*
+ *  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.polygene.library.circuitbreaker;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.beans.PropertyVetoException;
+import java.beans.VetoableChangeListener;
+import java.beans.VetoableChangeSupport;
+import java.time.Instant;
+import java.util.function.Predicate;
+
+/**
+ * Implementation of CircuitBreaker pattern
+ */
+public class CircuitBreaker
+{
+    public enum Status
+    {
+        off,
+        on
+    }
+
+    private int threshold;
+    private long timeout;
+    private Predicate<Throwable> allowedThrowables;
+
+    private int countDown;
+    private Instant trippedOn;
+    private Instant enableOn;
+
+    private Status status = Status.on;
+
+    private Throwable lastThrowable;
+
+    PropertyChangeSupport pcs = new PropertyChangeSupport( this );
+    VetoableChangeSupport vcs = new VetoableChangeSupport( this );
+
+    public CircuitBreaker( int threshold, long timeout, Predicate<Throwable> allowedThrowables )
+    {
+        this.threshold = threshold;
+        this.countDown = threshold;
+        this.timeout = timeout;
+        this.allowedThrowables = allowedThrowables;
+    }
+
+    public CircuitBreaker( int threshold, long timeout )
+    {
+        this( threshold, timeout, ( (Predicate<Throwable>) trip -> true ).negate() ); // Trip on all exceptions as default
+    }
+
+    public CircuitBreaker()
+    {
+        this( 1, 1000 * 60 * 5 ); // 5 minute timeout as default
+    }
+
+    public synchronized void trip()
+    {
+        if( status == Status.on )
+        {
+            if( countDown != 0 )
+            {
+                // If this was invoked manually, then set countDown to zero automatically
+                int oldCountDown = countDown;
+                countDown = 0;
+                pcs.firePropertyChange( "serviceLevel", ( oldCountDown ) / ( (double) threshold ), countDown / ( (double) threshold ) );
+            }
+
+            status = Status.off;
+            pcs.firePropertyChange( "status", Status.on, Status.off );
+
+            trippedOn = Instant.now();
+            enableOn = trippedOn.plusMillis( timeout );
+        }
+    }
+
+    public synchronized void turnOn()
+        throws PropertyVetoException
+    {
+        if( status == Status.off )
+        {
+            try
+            {
+                vcs.fireVetoableChange( "status", Status.off, Status.on );
+                status = Status.on;
+                countDown = threshold;
+                trippedOn = null;
+                enableOn = null;
+                lastThrowable = null;
+
+                pcs.firePropertyChange( "status", Status.off, Status.on );
+            }
+            catch( PropertyVetoException e )
+            {
+                // Reset timeout
+                enableOn = Instant.now().plusMillis( timeout );
+
+                if( e.getCause() != null )
+                {
+                    lastThrowable = e.getCause();
+                }
+                else
+                {
+                    lastThrowable = e;
+                }
+                throw e;
+            }
+        }
+    }
+
+    public int threshold()
+    {
+        return threshold;
+    }
+
+    public synchronized Throwable lastThrowable()
+    {
+        return lastThrowable;
+    }
+
+    public synchronized double serviceLevel()
+    {
+        return countDown / ( (double) threshold );
+    }
+
+    public synchronized Status status()
+    {
+        if( status == Status.off )
+        {
+            if( Instant.now().isAfter( enableOn ) )
+            {
+                try
+                {
+                    turnOn();
+                }
+                catch( PropertyVetoException e )
+                {
+                    if( e.getCause() != null )
+                    {
+                        lastThrowable = e.getCause();
+                    }
+                    else
+                    {
+                        lastThrowable = e;
+                    }
+                }
+            }
+        }
+
+        return status;
+    }
+
+    public Instant trippedOn()
+    {
+        return trippedOn;
+    }
+
+    public Instant enabledOn()
+    {
+        return enableOn;
+    }
+
+    public boolean isOn()
+    {
+        return status().equals( Status.on );
+    }
+
+    public synchronized void throwable( Throwable throwable )
+    {
+        if( status == Status.on )
+        {
+            if( allowedThrowables.test( throwable ) )
+            {
+                // Allowed throwable, so counts as success
+                success();
+            }
+            else
+            {
+                countDown--;
+                lastThrowable = throwable;
+                pcs.firePropertyChange( "serviceLevel", ( countDown + 1 ) / ( (double) threshold ), countDown / ( (double) threshold ) );
+                if( countDown == 0 )
+                {
+                    trip();
+                }
+            }
+        }
+    }
+
+    public synchronized void success()
+    {
+        if( status == Status.on && countDown < threshold )
+        {
+            countDown++;
+            pcs.firePropertyChange( "serviceLevel", ( countDown - 1 ) / ( (double) threshold ), countDown / ( (double) threshold ) );
+        }
+    }
+
+    public void addVetoableChangeListener( VetoableChangeListener vcl )
+    {
+        vcs.addVetoableChangeListener( vcl );
+    }
+
+    public void removeVetoableChangeListener( VetoableChangeListener vcl )
+    {
+        vcs.removeVetoableChangeListener( vcl );
+    }
+
+    public void addPropertyChangeListener( PropertyChangeListener pcl )
+    {
+        pcs.addPropertyChangeListener( pcl );
+    }
+
+    public void removePropertyChangeListener( PropertyChangeListener pcl )
+    {
+        pcs.removePropertyChangeListener( pcl );
+    }
+}
diff --git a/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/CircuitBreakers.java b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/CircuitBreakers.java
new file mode 100644
index 0000000..2ef559b
--- /dev/null
+++ b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/CircuitBreakers.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.library.circuitbreaker;
+
+import java.util.function.Predicate;
+
+/**
+ * CircuitBreaker helper methods.
+ */
+public class CircuitBreakers
+{
+   /**
+    * Allow all throwables that are equal to or subclasses of given list of throwables.
+    *
+    * @param throwables The Throwable types that are allowed.
+    * @return A Specification that specifies the allowed Throwables.
+    */
+   public static Predicate<Throwable> in( final Class<? extends Throwable>... throwables)
+   {
+      return item ->
+      {
+         Class<? extends Throwable> throwableClass = item.getClass();
+         for (Class<? extends Throwable> throwable : throwables)
+         {
+            if (throwable.isAssignableFrom( throwableClass ))
+               return true;
+         }
+         return false;
+      };
+   }
+
+   public static Predicate<Throwable> rootCause( final Predicate<Throwable> specification)
+   {
+      return item ->
+      {
+         Throwable cause = item.getCause();
+         if( cause != null )
+         {
+            return specification.test( cause );
+         }
+         else
+         {
+            return specification.test( item );
+         }
+      };
+   }
+}
diff --git a/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/jmx/CircuitBreakerJMX.java b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/jmx/CircuitBreakerJMX.java
new file mode 100644
index 0000000..14a32d3
--- /dev/null
+++ b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/jmx/CircuitBreakerJMX.java
@@ -0,0 +1,131 @@
+/*
+ *  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.polygene.library.circuitbreaker.jmx;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyVetoException;
+import java.time.Instant;
+import javax.management.MBeanNotificationInfo;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.ObjectName;
+import org.apache.polygene.api.time.SystemTime;
+import org.apache.polygene.library.circuitbreaker.CircuitBreaker;
+
+/**
+ * MBean for circuit breakers. Exposes CB properties and also the property changes as notifications.
+ */
+public class CircuitBreakerJMX
+        extends NotificationBroadcasterSupport
+        implements org.apache.polygene.library.circuitbreaker.jmx.CircuitBreakerJMXMBean
+{
+   CircuitBreaker circuitBreaker;
+
+   public CircuitBreakerJMX(CircuitBreaker circuitBreaker, final ObjectName mbeanObjectName)
+   {
+      super(new MBeanNotificationInfo(new String[]{"serviceLevel", "status"}, Notification.class.getName(), "Circuit breaker notifications"));
+
+      this.circuitBreaker = circuitBreaker;
+      circuitBreaker.addPropertyChangeListener(new PropertyChangeListener()
+      {
+         long sequenceNr = SystemTime.now().toEpochMilli();
+
+         @Override
+         public void propertyChange(PropertyChangeEvent evt)
+         {
+            long now = SystemTime.now().toEpochMilli();
+            Notification notification = new Notification(evt.getPropertyName(), mbeanObjectName, sequenceNr++, now, evt.getNewValue().toString());
+            sendNotification(notification);
+         }
+      });
+   }
+
+   @Override
+   public String getStatus()
+   {
+      return circuitBreaker.status().name();
+   }
+
+   @Override
+   public int getThreshold()
+   {
+      return circuitBreaker.threshold();
+   }
+
+   @Override
+   public double getServiceLevel()
+   {
+      return circuitBreaker.serviceLevel();
+   }
+
+   @Override
+   public String getLastErrorMessage()
+   {
+      return circuitBreaker.lastThrowable() == null ? "" : errorMessage(circuitBreaker.lastThrowable());
+   }
+
+   private String errorMessage(Throwable throwable)
+   {
+      String message = throwable.getMessage();
+      if (message == null)
+         message = throwable.getClass().getSimpleName();
+
+      if (throwable.getCause() != null)
+      {
+         return message + ":" + errorMessage(throwable.getCause());
+      } else
+         return message;
+   }
+
+   @Override
+   public String getTrippedOn()
+   {
+      Instant trippedOn = circuitBreaker.trippedOn();
+      return trippedOn == null ? "" : trippedOn.toString();
+   }
+
+   @Override
+   public String getEnableOn()
+   {
+      Instant trippedOn = circuitBreaker.enabledOn();
+      return trippedOn == null ? "" : trippedOn.toString();
+   }
+
+   @Override
+   public String turnOn()
+   {
+      try
+      {
+         circuitBreaker.turnOn();
+         return "Circuit breaker has been turned on";
+      } catch (PropertyVetoException e)
+      {
+         return "Could not turn on circuit breaker:" + getLastErrorMessage();
+      }
+   }
+
+   @Override
+   public void trip()
+   {
+      circuitBreaker.trip();
+   }
+}
diff --git a/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/jmx/CircuitBreakerJMXMBean.java b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/jmx/CircuitBreakerJMXMBean.java
new file mode 100644
index 0000000..e94dbda
--- /dev/null
+++ b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/jmx/CircuitBreakerJMXMBean.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.library.circuitbreaker.jmx;
+
+/**
+* MBean interface for circuit breakers
+*/
+public interface CircuitBreakerJMXMBean
+{
+   String getStatus();
+   int getThreshold();
+   double getServiceLevel();
+   String getLastErrorMessage();
+   String getTrippedOn();
+   String getEnableOn();
+
+   String turnOn();
+
+   void trip();
+}
diff --git a/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/jmx/CircuitBreakerManagement.java b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/jmx/CircuitBreakerManagement.java
new file mode 100644
index 0000000..d1ce2b1
--- /dev/null
+++ b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/jmx/CircuitBreakerManagement.java
@@ -0,0 +1,167 @@
+/*
+ *  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.polygene.library.circuitbreaker.jmx;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.management.JMException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.library.circuitbreaker.CircuitBreaker;
+import org.apache.polygene.library.circuitbreaker.service.ServiceCircuitBreaker;
+import org.apache.polygene.library.jmx.PolygeneMBeans;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * JMX service that exposes ServiceCircuitBreakers as MBeans.
+ * Logs exposed CircuitBreakers state changes.
+ */
+@Mixins( CircuitBreakerManagement.Mixin.class )
+@Activators( CircuitBreakerManagement.Activator.class )
+public interface CircuitBreakerManagement
+{
+
+    /**
+     * Expose all visible CircuitBreakers in JMX.
+     */
+    void registerCircuitBreakers()
+            throws JMException;
+
+    /**
+     * Unregister all exposed CircuitBreakers.
+     */
+    void unregisterCircuitBreakers()
+            throws JMException;
+
+    class Activator
+            extends ActivatorAdapter<ServiceReference<CircuitBreakerManagement>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<CircuitBreakerManagement> activated )
+                throws Exception
+        {
+            activated.get().registerCircuitBreakers();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<CircuitBreakerManagement> passivating )
+                throws Exception
+        {
+            passivating.get().unregisterCircuitBreakers();
+        }
+
+    }
+
+    abstract class Mixin
+            implements CircuitBreakerManagement
+    {
+
+        private static final Logger LOGGER = LoggerFactory.getLogger( CircuitBreakerManagement.class );
+
+        private final Map<CircuitBreaker, ObjectName> registeredCircuitBreakers = new HashMap<>();
+
+        @Structure
+        private Application application;
+
+        @Service
+        private MBeanServer server;
+
+        @Service
+        Iterable<ServiceReference<ServiceCircuitBreaker>> circuitBreakers;
+
+        @Override
+        public void registerCircuitBreakers()
+                throws JMException
+        {
+            for ( ServiceReference<ServiceCircuitBreaker> circuitBreaker : circuitBreakers )
+            {
+                registerCircuitBreaker( circuitBreaker.get().circuitBreaker(), circuitBreaker.identity() );
+            }
+        }
+
+        @Override
+        public void unregisterCircuitBreakers()
+                throws JMException
+        {
+            for ( ObjectName objectName : registeredCircuitBreakers.values() )
+            {
+                server.unregisterMBean( objectName );
+            }
+            registeredCircuitBreakers.clear();
+        }
+
+        private void registerCircuitBreaker( final CircuitBreaker circuitBreaker, final Identity name )
+                throws JMException
+        {
+            ObjectName mbeanObjectName;
+
+            ObjectName serviceName = PolygeneMBeans.findServiceName( server, application.name(), name.toString() );
+            if ( serviceName != null )
+            {
+                mbeanObjectName = new ObjectName( serviceName.toString() + ",name=Circuit breaker" );
+            }
+            else
+            {
+                try
+                {
+                    mbeanObjectName = new ObjectName( "CircuitBreaker:name=" + name );
+                }
+                catch ( MalformedObjectNameException e )
+                {
+                    throw new IllegalArgumentException( "Illegal name:" + name );
+                }
+            }
+
+            CircuitBreakerJMX bean = new CircuitBreakerJMX( circuitBreaker, mbeanObjectName );
+
+            server.registerMBean( bean, mbeanObjectName );
+            registeredCircuitBreakers.put( circuitBreaker, mbeanObjectName );
+
+            // Add logger
+            circuitBreaker.addPropertyChangeListener(evt ->
+            {
+                if ( "status".equals( evt.getPropertyName() ) )
+                {
+                    if ( CircuitBreaker.Status.on.equals( evt.getNewValue() ) )
+                    {
+                        LOGGER.info( "Circuit breaker " + name + " is now on" );
+                    }
+                    else
+                    {
+                        LOGGER.error( "Circuit breaker " + name + " is now off" );
+                    }
+                }
+            });
+        }
+
+    }
+
+}
diff --git a/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/jmx/package.html b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/jmx/package.html
new file mode 100644
index 0000000..7574996
--- /dev/null
+++ b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/jmx/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Circuit Breaker JMX Support.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/package.html b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/package.html
new file mode 100644
index 0000000..961ec31
--- /dev/null
+++ b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Circuit Breaker Library.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/AbstractBreakOnThrowable.java b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/AbstractBreakOnThrowable.java
new file mode 100644
index 0000000..8eb16aa
--- /dev/null
+++ b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/AbstractBreakOnThrowable.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.circuitbreaker.service;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.mixin.Mixins;
+
+/**
+ * Abstract composite that enables the service to use the @BreakCircuitOnThrowable annotation
+ * on methods.
+ */
+@Concerns(BreakCircuitConcern.class)
+@Mixins(ServiceCircuitBreakerMixin.class)
+public interface AbstractBreakOnThrowable
+   extends ServiceCircuitBreaker
+{
+}
diff --git a/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/AbstractEnabledCircuitBreakerAvailability.java b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/AbstractEnabledCircuitBreakerAvailability.java
new file mode 100644
index 0000000..f966a4d
--- /dev/null
+++ b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/AbstractEnabledCircuitBreakerAvailability.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.library.circuitbreaker.service;
+
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.configuration.Enabled;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.Availability;
+import org.apache.polygene.library.circuitbreaker.CircuitBreaker;
+
+/**
+ * Abstract composite that determines Availability by
+ * checking the Enabled configuration and a CircuitBreaker.
+ *
+ * To use this, the service must implement ServiceCircuitBreaker, and its ConfigurationComposite
+ * must extend Enabled.
+ */
+@Mixins( AbstractEnabledCircuitBreakerAvailability.Mixin.class )
+public interface AbstractEnabledCircuitBreakerAvailability
+        extends Availability
+{
+
+    class Mixin
+            implements Availability
+    {
+
+        @This
+        Configuration<Enabled> config;
+
+        @This
+        ServiceCircuitBreaker circuitBreaker;
+
+        @Override
+        public boolean isAvailable()
+        {
+            return config.get().enabled().get() && circuitBreaker.circuitBreaker().status() == CircuitBreaker.Status.on;
+        }
+
+    }
+
+}
diff --git a/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/BreakCircuitConcern.java b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/BreakCircuitConcern.java
new file mode 100644
index 0000000..d212d3d
--- /dev/null
+++ b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/BreakCircuitConcern.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.library.circuitbreaker.service;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.concern.GenericConcern;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.library.circuitbreaker.CircuitBreaker;
+
+/**
+ * This concern will update the circuit breaker on method invocation success
+ * and thrown exceptions.
+ */
+@AppliesTo( BreaksCircuitOnThrowable.class )
+public class BreakCircuitConcern
+        extends GenericConcern
+{
+
+    @This
+    ServiceCircuitBreaker serviceCircuitBreaker;
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+    {
+        CircuitBreaker circuitBreaker = serviceCircuitBreaker.circuitBreaker();
+        try
+        {
+            if( !circuitBreaker.isOn() )
+            {
+                throw circuitBreaker.lastThrowable();
+            }
+
+            Object result = next.invoke( proxy, method, args );
+            circuitBreaker.success();
+            return result;
+            
+        } catch( Throwable throwable )
+        {
+            circuitBreaker.throwable( throwable );
+            throw throwable;
+        }
+    }
+
+}
diff --git a/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/BreaksCircuitOnThrowable.java b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/BreaksCircuitOnThrowable.java
new file mode 100644
index 0000000..8debadd
--- /dev/null
+++ b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/BreaksCircuitOnThrowable.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.circuitbreaker.service;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotate methods which when they throw throwables should
+ * cause circuit breakers to trip
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface BreaksCircuitOnThrowable
+{
+}
diff --git a/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/ServiceCircuitBreaker.java b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/ServiceCircuitBreaker.java
new file mode 100644
index 0000000..f73946c
--- /dev/null
+++ b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/ServiceCircuitBreaker.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.library.circuitbreaker.service;
+
+import org.apache.polygene.library.circuitbreaker.CircuitBreaker;
+
+/**
+ * Services that have CircuitBreakers can implement this. The CB will
+ * then be exposable in JMX by CircuitBreakerManagement.
+ *
+ */
+public interface ServiceCircuitBreaker
+{
+
+    CircuitBreaker circuitBreaker();
+
+}
diff --git a/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/ServiceCircuitBreakerMixin.java b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/ServiceCircuitBreakerMixin.java
new file mode 100644
index 0000000..21a2b46
--- /dev/null
+++ b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/ServiceCircuitBreakerMixin.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.polygene.library.circuitbreaker.service;
+
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.library.circuitbreaker.CircuitBreaker;
+
+/**
+ * Helper implementation of ServiceCircuitBreaker. Fetches the CircuitBreaker from meta-info
+ * for the service.
+ */
+public class ServiceCircuitBreakerMixin
+        implements ServiceCircuitBreaker, Initializable
+{
+
+    @Uses
+    ServiceDescriptor descriptor;
+
+    CircuitBreaker circuitBreaker;
+
+    @Override
+    public void initialize()
+    {
+        circuitBreaker = descriptor.metaInfo( CircuitBreaker.class );
+    }
+
+    @Override
+    public CircuitBreaker circuitBreaker()
+    {
+        return circuitBreaker;
+    }
+
+}
diff --git a/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/package.html b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/package.html
new file mode 100644
index 0000000..8abf972
--- /dev/null
+++ b/libraries/circuitbreaker/src/main/java/org/apache/polygene/library/circuitbreaker/service/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Circuit Breaker Service.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/CircuitBreaker.java b/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/CircuitBreaker.java
deleted file mode 100644
index eacf53f..0000000
--- a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/CircuitBreaker.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.circuitbreaker;
-
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-import java.beans.PropertyVetoException;
-import java.beans.VetoableChangeListener;
-import java.beans.VetoableChangeSupport;
-import java.util.Date;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.Specifications;
-
-import static org.qi4j.functional.Specifications.not;
-
-/**
- * Implementation of CircuitBreaker pattern
- */
-public class CircuitBreaker
-{
-    public enum Status
-    {
-        off,
-        on
-    }
-
-    private int threshold;
-    private long timeout;
-    private Specification<Throwable> allowedThrowables;
-
-    private int countDown;
-    private long trippedOn = -1;
-    private long enableOn = -1;
-
-    private Status status = Status.on;
-
-    private Throwable lastThrowable;
-
-    PropertyChangeSupport pcs = new PropertyChangeSupport( this );
-    VetoableChangeSupport vcs = new VetoableChangeSupport( this );
-
-    public CircuitBreaker( int threshold, long timeout, Specification<Throwable> allowedThrowables )
-    {
-        this.threshold = threshold;
-        this.countDown = threshold;
-        this.timeout = timeout;
-        this.allowedThrowables = allowedThrowables;
-    }
-
-    public CircuitBreaker( int threshold, long timeout )
-    {
-        this( threshold, timeout, not( Specifications.<Throwable>TRUE() ) ); // Trip on all exceptions as default
-    }
-
-    public CircuitBreaker()
-    {
-        this( 1, 1000 * 60 * 5 ); // 5 minute timeout as default
-    }
-
-    public synchronized void trip()
-    {
-        if( status == Status.on )
-        {
-            if( countDown != 0 )
-            {
-                // If this was invoked manually, then set countDown to zero automatically
-                int oldCountDown = countDown;
-                countDown = 0;
-                pcs.firePropertyChange( "serviceLevel", ( oldCountDown ) / ( (double) threshold ), countDown / ( (double) threshold ) );
-            }
-
-            status = Status.off;
-            pcs.firePropertyChange( "status", Status.on, Status.off );
-
-            trippedOn = System.currentTimeMillis();
-            enableOn = trippedOn + timeout;
-        }
-    }
-
-    public synchronized void turnOn()
-        throws PropertyVetoException
-    {
-        if( status == Status.off )
-        {
-            try
-            {
-                vcs.fireVetoableChange( "status", Status.off, Status.on );
-                status = Status.on;
-                countDown = threshold;
-                trippedOn = -1;
-                enableOn = -1;
-                lastThrowable = null;
-
-                pcs.firePropertyChange( "status", Status.off, Status.on );
-            }
-            catch( PropertyVetoException e )
-            {
-                // Reset timeout
-                enableOn = System.currentTimeMillis() + timeout;
-
-                if( e.getCause() != null )
-                {
-                    lastThrowable = e.getCause();
-                }
-                else
-                {
-                    lastThrowable = e;
-                }
-                throw e;
-            }
-        }
-    }
-
-    public int threshold()
-    {
-        return threshold;
-    }
-
-    public synchronized Throwable lastThrowable()
-    {
-        return lastThrowable;
-    }
-
-    public synchronized double serviceLevel()
-    {
-        return countDown / ( (double) threshold );
-    }
-
-    public synchronized Status status()
-    {
-        if( status == Status.off )
-        {
-            if( System.currentTimeMillis() > enableOn )
-            {
-                try
-                {
-                    turnOn();
-                }
-                catch( PropertyVetoException e )
-                {
-                    if( e.getCause() != null )
-                    {
-                        lastThrowable = e.getCause();
-                    }
-                    else
-                    {
-                        lastThrowable = e;
-                    }
-                }
-            }
-        }
-
-        return status;
-    }
-
-    public Date trippedOn()
-    {
-        return trippedOn == -1 ? null : new Date( trippedOn );
-    }
-
-    public Date enabledOn()
-    {
-        return enableOn == -1 ? null : new Date( enableOn );
-    }
-
-    public boolean isOn()
-    {
-        return status().equals( Status.on );
-    }
-
-    public synchronized void throwable( Throwable throwable )
-    {
-        if( status == Status.on )
-        {
-            if( allowedThrowables.satisfiedBy( throwable ) )
-            {
-                // Allowed throwable, so counts as success
-                success();
-            }
-            else
-            {
-                countDown--;
-
-                lastThrowable = throwable;
-
-                pcs.firePropertyChange( "serviceLevel", ( countDown + 1 ) / ( (double) threshold ), countDown / ( (double) threshold ) );
-
-                if( countDown == 0 )
-                {
-                    trip();
-                }
-            }
-        }
-    }
-
-    public synchronized void success()
-    {
-        if( status == Status.on && countDown < threshold )
-        {
-            countDown++;
-
-            pcs.firePropertyChange( "serviceLevel", ( countDown - 1 ) / ( (double) threshold ), countDown / ( (double) threshold ) );
-        }
-    }
-
-    public void addVetoableChangeListener( VetoableChangeListener vcl )
-    {
-        vcs.addVetoableChangeListener( vcl );
-    }
-
-    public void removeVetoableChangeListener( VetoableChangeListener vcl )
-    {
-        vcs.removeVetoableChangeListener( vcl );
-    }
-
-    public void addPropertyChangeListener( PropertyChangeListener pcl )
-    {
-        pcs.addPropertyChangeListener( pcl );
-    }
-
-    public void removePropertyChangeListener( PropertyChangeListener pcl )
-    {
-        pcs.removePropertyChangeListener( pcl );
-    }
-}
diff --git a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/CircuitBreakers.java b/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/CircuitBreakers.java
deleted file mode 100644
index 3919907..0000000
--- a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/CircuitBreakers.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.circuitbreaker;
-
-import org.qi4j.functional.Specification;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-
-/**
- * CircuitBreaker helper methods.
- */
-public class CircuitBreakers
-{
-   public static <Item, ReceiverThrowable extends Throwable> Output<Item, ReceiverThrowable> withBreaker( final CircuitBreaker breaker, final Output<Item, ReceiverThrowable> output)
-   {
-      return new Output<Item, ReceiverThrowable>()
-      {
-         @Override
-         public <SenderThrowableType extends Throwable> void receiveFrom(final Sender<? extends Item, SenderThrowableType> sender) throws ReceiverThrowable, SenderThrowableType
-         {
-            output.receiveFrom( new Sender<Item, SenderThrowableType>()
-            {
-               @Override
-               public <ReceiverThrowableType extends Throwable> void sendTo(final Receiver<? super Item, ReceiverThrowableType> receiver) throws ReceiverThrowableType, SenderThrowableType
-               {
-                  // Check breaker first
-                  if (!breaker.isOn())
-                     throw (ReceiverThrowableType) breaker.lastThrowable();
-
-                  sender.sendTo( new Receiver<Item, ReceiverThrowableType>()
-                  {
-                     @Override
-                     public void receive( Item item ) throws ReceiverThrowableType
-                     {
-                        try
-                        {
-                           receiver.receive( item );
-
-                           // Notify breaker that it went well
-                           breaker.success();
-                        } catch (Throwable receiverThrowableType)
-                        {
-                           // Notify breaker of trouble
-                           breaker.throwable( receiverThrowableType );
-
-                           throw (ReceiverThrowableType) receiverThrowableType;
-                        }
-                     }
-                  });
-               }
-            });
-         }
-      };
-   }
-
-   /**
-    * Allow all throwables that are equal to or subclasses of given list of throwables.
-    *
-    * @param throwables The Throwable types that are allowed.
-    * @return A Specification that specifies the allowed Throwables.
-    */
-   public static Specification<Throwable> in( final Class<? extends Throwable>... throwables)
-   {
-      return new Specification<Throwable>()
-      {
-         @Override
-         public boolean satisfiedBy( Throwable item )
-         {
-            Class<? extends Throwable> throwableClass = item.getClass();
-            for (Class<? extends Throwable> throwable : throwables)
-            {
-               if (throwable.isAssignableFrom( throwableClass ))
-                  return true;
-            }
-            return false;
-         }
-      };
-   }
-
-   public static Specification<Throwable> rootCause( final Specification<Throwable> specification)
-   {
-      return new Specification<Throwable>()
-      {
-         @Override
-         public boolean satisfiedBy( Throwable item )
-         {
-            return specification.satisfiedBy( unwrap(item) );
-         }
-
-         private Throwable unwrap(Throwable item)
-         {
-            if (item.getCause() != null)
-               return item.getCause();
-            else
-               return item;
-         }
-      };
-   }
-}
diff --git a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/jmx/CircuitBreakerJMX.java b/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/jmx/CircuitBreakerJMX.java
deleted file mode 100644
index 72a9fd2..0000000
--- a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/jmx/CircuitBreakerJMX.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.circuitbreaker.jmx;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyVetoException;
-import java.text.DateFormat;
-import java.util.Date;
-import javax.management.MBeanNotificationInfo;
-import javax.management.Notification;
-import javax.management.NotificationBroadcasterSupport;
-import javax.management.ObjectName;
-import org.qi4j.library.circuitbreaker.CircuitBreaker;
-
-/**
- * MBean for circuit breakers. Exposes CB properties and also the property changes as notifications.
- */
-public class CircuitBreakerJMX
-        extends NotificationBroadcasterSupport
-        implements org.qi4j.library.circuitbreaker.jmx.CircuitBreakerJMXMBean
-{
-   CircuitBreaker circuitBreaker;
-
-   public CircuitBreakerJMX(CircuitBreaker circuitBreaker, final ObjectName mbeanObjectName)
-   {
-      super(new MBeanNotificationInfo(new String[]{"serviceLevel", "status"}, Notification.class.getName(), "Circuit breaker notifications"));
-
-      this.circuitBreaker = circuitBreaker;
-      circuitBreaker.addPropertyChangeListener(new PropertyChangeListener()
-      {
-         long sequenceNr = System.currentTimeMillis();
-
-         @Override
-         public void propertyChange(PropertyChangeEvent evt)
-         {
-            Notification notification = new Notification(evt.getPropertyName(), mbeanObjectName, sequenceNr++, System.currentTimeMillis(), evt.getNewValue().toString());
-            sendNotification(notification);
-         }
-      });
-   }
-
-   @Override
-   public String getStatus()
-   {
-      return circuitBreaker.status().name();
-   }
-
-   @Override
-   public int getThreshold()
-   {
-      return circuitBreaker.threshold();
-   }
-
-   @Override
-   public double getServiceLevel()
-   {
-      return circuitBreaker.serviceLevel();
-   }
-
-   @Override
-   public String getLastErrorMessage()
-   {
-      return circuitBreaker.lastThrowable() == null ? "" : errorMessage(circuitBreaker.lastThrowable());
-   }
-
-   private String errorMessage(Throwable throwable)
-   {
-      String message = throwable.getMessage();
-      if (message == null)
-         message = throwable.getClass().getSimpleName();
-
-      if (throwable.getCause() != null)
-      {
-         return message + ":" + errorMessage(throwable.getCause());
-      } else
-         return message;
-   }
-
-   @Override
-   public String getTrippedOn()
-   {
-      Date trippedOn = circuitBreaker.trippedOn();
-      return trippedOn == null ? "" : DateFormat.getDateTimeInstance().format(trippedOn);
-   }
-
-   @Override
-   public String getEnableOn()
-   {
-      Date trippedOn = circuitBreaker.enabledOn();
-      return trippedOn == null ? "" : DateFormat.getDateTimeInstance().format(trippedOn);
-   }
-
-   @Override
-   public String turnOn()
-   {
-      try
-      {
-         circuitBreaker.turnOn();
-         return "Circuit breaker has been turned on";
-      } catch (PropertyVetoException e)
-      {
-         return "Could not turn on circuit breaker:" + getLastErrorMessage();
-      }
-   }
-
-   @Override
-   public void trip()
-   {
-      circuitBreaker.trip();
-   }
-}
diff --git a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/jmx/CircuitBreakerJMXMBean.java b/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/jmx/CircuitBreakerJMXMBean.java
deleted file mode 100644
index 99c17b2..0000000
--- a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/jmx/CircuitBreakerJMXMBean.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.circuitbreaker.jmx;
-
-/**
-* MBean interface for circuit breakers
-*/
-public interface CircuitBreakerJMXMBean
-{
-   public String getStatus();
-   public int getThreshold();
-   public double getServiceLevel();
-   public String getLastErrorMessage();
-   public String getTrippedOn();
-   public String getEnableOn();
-
-   public String turnOn();
-
-   public void trip();
-}
diff --git a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/jmx/CircuitBreakerManagement.java b/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/jmx/CircuitBreakerManagement.java
deleted file mode 100644
index 0f5180f..0000000
--- a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/jmx/CircuitBreakerManagement.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- * Copyright 2012 Paul Merlin
- *
- * Licensed 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.qi4j.library.circuitbreaker.jmx;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.util.HashMap;
-import java.util.Map;
-import javax.management.JMException;
-import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
-import javax.management.ObjectName;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.library.circuitbreaker.CircuitBreaker;
-import org.qi4j.library.circuitbreaker.service.ServiceCircuitBreaker;
-import org.qi4j.library.jmx.Qi4jMBeans;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * JMX service that exposes ServiceCircuitBreakers as MBeans.
- * Logs exposed CircuitBreakers state changes.
- */
-@Mixins( CircuitBreakerManagement.Mixin.class )
-@Activators( CircuitBreakerManagement.Activator.class )
-public interface CircuitBreakerManagement
-        extends ServiceComposite
-{
-
-    /**
-     * Expose all visible CircuitBreakers in JMX.
-     */
-    void registerCircuitBreakers()
-            throws JMException;
-
-    /**
-     * Unregister all exposed CircuitBreakers.
-     */
-    void unregisterCircuitBreakers()
-            throws JMException;
-
-    class Activator
-            extends ActivatorAdapter<ServiceReference<CircuitBreakerManagement>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<CircuitBreakerManagement> activated )
-                throws Exception
-        {
-            activated.get().registerCircuitBreakers();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<CircuitBreakerManagement> passivating )
-                throws Exception
-        {
-            passivating.get().unregisterCircuitBreakers();
-        }
-
-    }
-
-    abstract class Mixin
-            implements CircuitBreakerManagement
-    {
-
-        private static final Logger LOGGER = LoggerFactory.getLogger( CircuitBreakerManagement.class );
-
-        private final Map<CircuitBreaker, ObjectName> registeredCircuitBreakers = new HashMap<CircuitBreaker, ObjectName>();
-
-        @Structure
-        private Application application;
-
-        @Service
-        private MBeanServer server;
-
-        @Service
-        Iterable<ServiceReference<ServiceCircuitBreaker>> circuitBreakers;
-
-        @Override
-        public void registerCircuitBreakers()
-                throws JMException
-        {
-            for ( ServiceReference<ServiceCircuitBreaker> circuitBreaker : circuitBreakers )
-            {
-                registerCircuitBreaker( circuitBreaker.get().circuitBreaker(), circuitBreaker.identity() );
-            }
-        }
-
-        @Override
-        public void unregisterCircuitBreakers()
-                throws JMException
-        {
-            for ( ObjectName objectName : registeredCircuitBreakers.values() )
-            {
-                server.unregisterMBean( objectName );
-            }
-            registeredCircuitBreakers.clear();
-        }
-
-        private void registerCircuitBreaker( final CircuitBreaker circuitBreaker, final String name )
-                throws JMException
-        {
-            ObjectName mbeanObjectName = null;
-
-            ObjectName serviceName = Qi4jMBeans.findServiceName( server, application.name(), name );
-            if ( serviceName != null )
-            {
-                mbeanObjectName = new ObjectName( serviceName.toString() + ",name=Circuit breaker" );
-            }
-            else
-            {
-                try
-                {
-                    mbeanObjectName = new ObjectName( "CircuitBreaker:name=" + name );
-                }
-                catch ( MalformedObjectNameException e )
-                {
-                    throw new IllegalArgumentException( "Illegal name:" + name );
-                }
-            }
-
-            CircuitBreakerJMX bean = new CircuitBreakerJMX( circuitBreaker, mbeanObjectName );
-
-            server.registerMBean( bean, mbeanObjectName );
-            registeredCircuitBreakers.put( circuitBreaker, mbeanObjectName );
-
-            // Add logger
-            circuitBreaker.addPropertyChangeListener( new PropertyChangeListener()
-            {
-
-                @Override
-                public void propertyChange( PropertyChangeEvent evt )
-                {
-                    if ( "status".equals( evt.getPropertyName() ) )
-                    {
-                        if ( CircuitBreaker.Status.on.equals( evt.getNewValue() ) )
-                        {
-                            LOGGER.info( "Circuit breaker " + name + " is now on" );
-                        }
-                        else
-                        {
-                            LOGGER.error( "Circuit breaker " + name + " is now off" );
-                        }
-                    }
-                }
-
-            } );
-        }
-
-    }
-
-}
diff --git a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/jmx/package.html b/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/jmx/package.html
deleted file mode 100644
index b3ca3a9..0000000
--- a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/jmx/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Circuit Breaker JMX Support.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/package.html b/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/package.html
deleted file mode 100644
index df4170c..0000000
--- a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Circuit Breaker Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/AbstractBreakOnThrowable.java b/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/AbstractBreakOnThrowable.java
deleted file mode 100644
index 9c16aba..0000000
--- a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/AbstractBreakOnThrowable.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.circuitbreaker.service;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-
-/**
- * Abstract composite that enables the service to use the @BreakCircuitOnThrowable annotation
- * on methods.
- */
-@Concerns(BreakCircuitConcern.class)
-@Mixins(ServiceCircuitBreakerMixin.class)
-public interface AbstractBreakOnThrowable
-   extends ServiceCircuitBreaker
-{
-}
diff --git a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/AbstractEnabledCircuitBreakerAvailability.java b/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/AbstractEnabledCircuitBreakerAvailability.java
deleted file mode 100644
index cb548ad..0000000
--- a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/AbstractEnabledCircuitBreakerAvailability.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.circuitbreaker.service;
-
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.configuration.Enabled;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.Availability;
-import org.qi4j.library.circuitbreaker.CircuitBreaker;
-
-/**
- * Abstract composite that determines Availability by
- * checking the Enabled configuration and a CircuitBreaker.
- *
- * To use this, the service must implement ServiceCircuitBreaker, and its ConfigurationComposite
- * must extend Enabled.
- */
-@Mixins( AbstractEnabledCircuitBreakerAvailability.Mixin.class )
-public interface AbstractEnabledCircuitBreakerAvailability
-        extends Availability
-{
-
-    class Mixin
-            implements Availability
-    {
-
-        @This
-        Configuration<Enabled> config;
-
-        @This
-        ServiceCircuitBreaker circuitBreaker;
-
-        @Override
-        public boolean isAvailable()
-        {
-            return config.get().enabled().get() && circuitBreaker.circuitBreaker().status() == CircuitBreaker.Status.on;
-        }
-
-    }
-
-}
diff --git a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/BreakCircuitConcern.java b/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/BreakCircuitConcern.java
deleted file mode 100644
index 0550c8d..0000000
--- a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/BreakCircuitConcern.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.circuitbreaker.service;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.concern.GenericConcern;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.library.circuitbreaker.CircuitBreaker;
-
-/**
- * This concern will update the circuit breaker on method invocation success
- * and thrown exceptions.
- */
-@AppliesTo( BreaksCircuitOnThrowable.class )
-public class BreakCircuitConcern
-        extends GenericConcern
-{
-
-    @This
-    ServiceCircuitBreaker serviceCircuitBreaker;
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-    {
-        CircuitBreaker circuitBreaker = serviceCircuitBreaker.circuitBreaker();
-        try
-        {
-            if( !circuitBreaker.isOn() )
-            {
-                throw circuitBreaker.lastThrowable();
-            }
-
-            Object result = next.invoke( proxy, method, args );
-            circuitBreaker.success();
-            return result;
-            
-        } catch( Throwable throwable )
-        {
-            circuitBreaker.throwable( throwable );
-            throw throwable;
-        }
-    }
-
-}
diff --git a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/BreaksCircuitOnThrowable.java b/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/BreaksCircuitOnThrowable.java
deleted file mode 100644
index e7efc69..0000000
--- a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/BreaksCircuitOnThrowable.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.circuitbreaker.service;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotate methods which when they throw throwables should
- * cause circuit breakers to trip
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface BreaksCircuitOnThrowable
-{
-}
diff --git a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/ServiceCircuitBreaker.java b/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/ServiceCircuitBreaker.java
deleted file mode 100644
index 7c7af3d..0000000
--- a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/ServiceCircuitBreaker.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.circuitbreaker.service;
-
-import org.qi4j.library.circuitbreaker.CircuitBreaker;
-
-/**
- * Services that have CircuitBreakers can implement this. The CB will
- * then be exposable in JMX by CircuitBreakerManagement.
- *
- */
-public interface ServiceCircuitBreaker
-{
-
-    CircuitBreaker circuitBreaker();
-
-}
diff --git a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/ServiceCircuitBreakerMixin.java b/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/ServiceCircuitBreakerMixin.java
deleted file mode 100644
index c3c4b82..0000000
--- a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/ServiceCircuitBreakerMixin.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.circuitbreaker.service;
-
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.mixin.Initializable;
-import org.qi4j.api.mixin.InitializationException;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.library.circuitbreaker.CircuitBreaker;
-
-/**
- * Helper implementation of ServiceCircuitBreaker. Fetches the CircuitBreaker from meta-info
- * for the service.
- */
-public class ServiceCircuitBreakerMixin
-        implements ServiceCircuitBreaker, Initializable
-{
-
-    @Uses
-    ServiceDescriptor descriptor;
-
-    CircuitBreaker circuitBreaker;
-
-    @Override
-    public void initialize()
-            throws InitializationException
-    {
-        circuitBreaker = descriptor.metaInfo( CircuitBreaker.class );
-    }
-
-    @Override
-    public CircuitBreaker circuitBreaker()
-    {
-        return circuitBreaker;
-    }
-
-}
diff --git a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/package.html b/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/package.html
deleted file mode 100644
index ce4dd71..0000000
--- a/libraries/circuitbreaker/src/main/java/org/qi4j/library/circuitbreaker/service/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Circuit Breaker Service.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/circuitbreaker/src/test/java/org/apache/polygene/library/circuitbreaker/BreaksCircuitOnThrowableTest.java b/libraries/circuitbreaker/src/test/java/org/apache/polygene/library/circuitbreaker/BreaksCircuitOnThrowableTest.java
new file mode 100644
index 0000000..6d944d5
--- /dev/null
+++ b/libraries/circuitbreaker/src/test/java/org/apache/polygene/library/circuitbreaker/BreaksCircuitOnThrowableTest.java
@@ -0,0 +1,125 @@
+/*
+ *  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.polygene.library.circuitbreaker;
+
+import java.beans.PropertyVetoException;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.circuitbreaker.service.AbstractBreakOnThrowable;
+import org.apache.polygene.library.circuitbreaker.service.BreaksCircuitOnThrowable;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+/**
+ * Test @BreaksCircuitOnThrowable annotation
+ */
+public class BreaksCircuitOnThrowableTest
+    extends AbstractPolygeneTest
+{
+
+    // START SNIPPET: service
+    public void assemble( ModuleAssembly module )
+            throws AssemblyException
+    {
+        module.services( TestService.class ).setMetaInfo( new CircuitBreaker() );
+    }
+    // END SNIPPET: service
+
+    @Test
+    public void testSuccess()
+    {
+        TestService service = serviceFinder.findService( TestService.class ).get();
+        service.successfulMethod();
+        service.successfulMethod();
+        service.successfulMethod();
+    }
+
+    @Test
+    public void testThrowable()
+    {
+        ServiceReference<TestService> serviceReference = serviceFinder.findService( TestService.class );
+        TestService service = serviceReference.get();
+        try {
+            service.throwingMethod();
+            Assert.fail( "Service should have thrown exception" );
+        } catch ( Exception e ) {
+            // Ok
+        }
+
+        try {
+            service.successfulMethod();
+            Assert.fail( "Circuit breaker should have tripped" );
+        } catch ( Exception e ) {
+            // Ok
+        }
+
+        try {
+            serviceReference.metaInfo( CircuitBreaker.class ).turnOn();
+        } catch ( PropertyVetoException e ) {
+            Assert.fail( "Should have been possible to turn on circuit breaker" );
+        }
+
+        try {
+            service.successfulMethod();
+        } catch ( Exception e ) {
+            Assert.fail( "Circuit breaker should have been turned on" );
+        }
+    }
+
+    @Mixins( TestService.Mixin.class )
+    // START SNIPPET: service
+    public interface TestService
+            extends AbstractBreakOnThrowable, ServiceComposite
+    {
+
+        @BreaksCircuitOnThrowable
+        int successfulMethod();
+
+        @BreaksCircuitOnThrowable
+        void throwingMethod();
+
+        // END SNIPPET: service
+        abstract class Mixin
+                implements TestService
+        {
+
+            int count = 0;
+
+            public void throwingMethod()
+            {
+                throw new IllegalArgumentException( "Failed" );
+            }
+
+            public int successfulMethod()
+            {
+                return count++;
+            }
+
+        }
+
+        // START SNIPPET: service
+    }
+    // END SNIPPET: service
+
+}
diff --git a/libraries/circuitbreaker/src/test/java/org/apache/polygene/library/circuitbreaker/CircuitBreakerTest.java b/libraries/circuitbreaker/src/test/java/org/apache/polygene/library/circuitbreaker/CircuitBreakerTest.java
new file mode 100644
index 0000000..cf47c91
--- /dev/null
+++ b/libraries/circuitbreaker/src/test/java/org/apache/polygene/library/circuitbreaker/CircuitBreakerTest.java
@@ -0,0 +1,226 @@
+/*
+ *  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.polygene.library.circuitbreaker;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyVetoException;
+import java.beans.VetoableChangeListener;
+import java.io.IOException;
+import java.util.concurrent.Callable;
+import org.hamcrest.CoreMatchers;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.awaitility.Awaitility.await;
+import static org.awaitility.Duration.ONE_SECOND;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * JAVADOC
+ */
+public class CircuitBreakerTest
+{
+
+    private CircuitBreaker cb;
+
+    @Before
+    public void createCircuitBreaker()
+    {
+        // START SNIPPET: direct
+        // Create a CircuitBreaker with a threshold of 3, a 250ms timeout, allowing IllegalArgumentExceptions
+        CircuitBreaker cb = new CircuitBreaker( 3, 250, CircuitBreakers.in( IllegalArgumentException.class ) );
+
+        // END SNIPPET: direct
+
+        cb.addPropertyChangeListener( new PropertyChangeListener()
+        {
+
+            public void propertyChange( PropertyChangeEvent evt )
+            {
+                System.out.println( evt.getSource() + ":" + evt.getPropertyName() + "=" + evt.getOldValue() + " -> " + evt.getNewValue() );
+            }
+
+        } );
+
+        this.cb = cb;
+    }
+
+    @Test
+    public void GivenCBWhenTripWithExceptionsAndTurnOnThenStatusIsOn()
+            throws PropertyVetoException
+    {
+
+        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
+
+        // START SNIPPET: direct
+        // Service levels goes down but does not cause a trip
+        cb.throwable( new IOException() );
+
+        // END SNIPPET: direct
+
+        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
+
+        // START SNIPPET: direct
+        // Service level goes down and causes a trip
+        cb.throwable( new IOException() );
+        cb.throwable( new IOException() );
+
+        // END SNIPPET: direct
+
+        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.off ) );
+
+        // START SNIPPET: direct
+        // Turn on the CB again
+        cb.turnOn();
+
+        // END SNIPPET: direct
+
+        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
+    }
+
+    @Test
+    public void GivenCBWhenAllowedExceptionsThenServiceLevelIsNormal()
+            throws PropertyVetoException
+    {
+
+        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
+
+        // Service level goes down
+        cb.throwable( new IOException() );
+
+        // Service levels goes up
+        cb.throwable( new IllegalArgumentException() );
+
+        assertThat( cb.serviceLevel(), CoreMatchers.equalTo( 1.0 ) );
+    }
+
+    @Test
+    public void GivenCBWhenTripCBWithExceptionsAndTimeoutThenStatusIsOn()
+            throws PropertyVetoException
+    {
+        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
+
+        // START SNIPPET: direct
+        // Service levels goes down and causes a trip
+        cb.throwable( new IOException() );
+        cb.throwable( new IOException() );
+        cb.throwable( new IOException() );
+
+        // END SNIPPET: direct
+
+        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.off ) );
+
+        // START SNIPPET: direct
+        // Wait until timeout
+
+        // END SNIPPET: direct
+        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.off ) );
+        System.out.println( "Wait..." );
+        await().atMost( ONE_SECOND ).until( circuitBreakerStatus(), is( CircuitBreaker.Status.on ) );
+
+        // START SNIPPET: direct
+        // CircuitBreaker is back on
+        
+        // END SNIPPET: direct
+        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
+    }
+    
+    private Callable<CircuitBreaker.Status> circuitBreakerStatus()
+    {
+        return new Callable<CircuitBreaker.Status>()
+        {
+            @Override
+            public CircuitBreaker.Status call() throws Exception
+            {
+                return cb.status();
+            }
+        };
+    }
+
+    @Test
+    public void GivenCBWhenExceptionsAndSuccessesThenStatusIsOn()
+            throws PropertyVetoException
+    {
+        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
+
+        // Service levels goes down and causes a trip
+        cb.throwable( new IOException() );
+        cb.throwable( new IOException() );
+        cb.success();
+        cb.success();
+        cb.throwable( new IOException() );
+        cb.throwable( new IOException() );
+
+        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
+    }
+
+    @Test
+    public void GivenCBWhenTripCBWithExceptionsAndSuccessesThenStatusIsOff()
+            throws PropertyVetoException
+    {
+        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
+
+        // Service levels goes down and causes a trip
+        cb.throwable( new IOException() );
+        cb.throwable( new IOException() );
+        cb.throwable( new IOException() );
+        cb.success();
+
+        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.off ) );
+    }
+
+    @Test
+    public void GivenCBWhenTripCBWithExceptionsAndGetStatusWithFailureThenStatusIsOff()
+            throws PropertyVetoException
+    {
+        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
+
+        cb.addVetoableChangeListener( new VetoableChangeListener()
+        {
+
+            public void vetoableChange( PropertyChangeEvent evt )
+                    throws PropertyVetoException
+            {
+                if ( evt.getNewValue() == CircuitBreaker.Status.on ) {
+                    throw new PropertyVetoException( "Service is down", evt );
+                }
+            }
+
+        } );
+
+        // Service levels goes down and causes a trip
+        cb.throwable( new IOException() );
+        cb.throwable( new IOException() );
+        cb.throwable( new IOException() );
+
+        try {
+            System.out.println( "Wait..." );
+            Thread.sleep( 300 );
+        } catch ( InterruptedException e ) {
+            // Ignore
+        }
+
+        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.off ) );
+        assertThat( cb.lastThrowable().getMessage(), CoreMatchers.equalTo( "Service is down" ) );
+    }
+
+}
diff --git a/libraries/circuitbreaker/src/test/java/org/apache/polygene/library/circuitbreaker/jmx/CircuitBreakerManagementSample.java b/libraries/circuitbreaker/src/test/java/org/apache/polygene/library/circuitbreaker/jmx/CircuitBreakerManagementSample.java
new file mode 100644
index 0000000..2f4b6ed
--- /dev/null
+++ b/libraries/circuitbreaker/src/test/java/org/apache/polygene/library/circuitbreaker/jmx/CircuitBreakerManagementSample.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.polygene.library.circuitbreaker.jmx;
+
+import java.util.Random;
+import javax.management.MBeanServer;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.library.circuitbreaker.CircuitBreaker;
+import org.apache.polygene.library.circuitbreaker.CircuitBreakers;
+import org.apache.polygene.library.circuitbreaker.service.ServiceCircuitBreaker;
+import org.apache.polygene.library.jmx.MBeanServerImporter;
+
+/**
+ * Run this as a program and connect with VisualVM. That way you can monitor changes in attributes, notifications, and
+ * execute operations on the CircuitBreaker through JMX.
+ */
+public class CircuitBreakerManagementSample
+{
+
+    public static void main( String[] args )
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+
+            @Override
+            // START SNIPPET: jmx
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                // END SNIPPET: jmx
+                CircuitBreaker cb = new CircuitBreaker( 3, 250, CircuitBreakers.in( IllegalArgumentException.class ) );
+
+                module.importedServices( TestService.class ).setMetaInfo( new TestService( cb ) );
+
+                // START SNIPPET: jmx
+                // JMX Library
+                module.importedServices( MBeanServer.class ).
+                    importedBy( MBeanServerImporter.class );
+                // CircuitBreakers in JMX
+                module.services( CircuitBreakerManagement.class ).
+                    instantiateOnStartup();
+            }
+            // END SNIPPET: jmx
+
+        };
+
+        TestService service = assembler.module().findService( TestService.class ).get();
+
+        int interval = 1; // Seconds
+        System.out.println( "CircuitBreaker JMX Support sample is now started." );
+        System.out.println();
+        System.out.println( "A Service that randomly output some text or fail is called through a CircuitBreaker every " + interval + " seconds." );
+        System.out.println( "In a few interval the CircuitBreaker will be turned off." );
+        System.out.println( "Connect with a MBean browser (eg. VisualVM + MBean plugin) to use the turnOn operation on the CircuitBreakers." );
+        System.out.println();
+        System.out.println( "Hit Ctrl-C to stop." );
+        System.out.println();
+
+        while ( true ) {
+            try {
+                Thread.sleep( interval * 1000 );
+            } catch ( InterruptedException e ) {
+                e.printStackTrace();
+            }
+
+            service.helloWorld();
+        }
+    }
+
+    public static class TestService
+            implements ServiceCircuitBreaker
+    {
+
+        CircuitBreaker cb;
+
+        Random random = new Random();
+
+        public TestService( CircuitBreaker cb )
+        {
+            this.cb = cb;
+        }
+
+        @Override
+        public CircuitBreaker circuitBreaker()
+        {
+            return cb;
+        }
+
+        public void helloWorld()
+        {
+            if ( random.nextDouble() > 0.3 ) {
+                cb.throwable( new Throwable( "Failed" ) );
+            } else {
+                cb.success();
+            }
+        }
+
+    }
+
+}
diff --git a/libraries/circuitbreaker/src/test/java/org/qi4j/library/circuitbreaker/BreaksCircuitOnThrowableTest.java b/libraries/circuitbreaker/src/test/java/org/qi4j/library/circuitbreaker/BreaksCircuitOnThrowableTest.java
deleted file mode 100644
index dd6b091..0000000
--- a/libraries/circuitbreaker/src/test/java/org/qi4j/library/circuitbreaker/BreaksCircuitOnThrowableTest.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.circuitbreaker;
-
-import java.beans.PropertyVetoException;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.circuitbreaker.service.AbstractBreakOnThrowable;
-import org.qi4j.library.circuitbreaker.service.BreaksCircuitOnThrowable;
-import org.qi4j.test.AbstractQi4jTest;
-
-/**
- * Test @BreaksCircuitOnThrowable annotation
- */
-public class BreaksCircuitOnThrowableTest
-        extends AbstractQi4jTest
-{
-
-    // START SNIPPET: service
-    public void assemble( ModuleAssembly module )
-            throws AssemblyException
-    {
-        module.services( TestService.class ).setMetaInfo( new CircuitBreaker() );
-    }
-    // END SNIPPET: service
-
-    @Test
-    public void testSuccess()
-    {
-        TestService service = ( TestService ) module.findService( TestService.class ).get();
-        service.successfulMethod();
-        service.successfulMethod();
-        service.successfulMethod();
-    }
-
-    @Test
-    public void testThrowable()
-    {
-        ServiceReference<TestService> serviceReference = module.findService( TestService.class );
-        TestService service = serviceReference.get();
-        try {
-            service.throwingMethod();
-            Assert.fail( "Service should have thrown exception" );
-        } catch ( Exception e ) {
-            // Ok
-        }
-
-        try {
-            service.successfulMethod();
-            Assert.fail( "Circuit breaker should have tripped" );
-        } catch ( Exception e ) {
-            // Ok
-        }
-
-        try {
-            serviceReference.metaInfo( CircuitBreaker.class ).turnOn();
-        } catch ( PropertyVetoException e ) {
-            Assert.fail( "Should have been possible to turn on circuit breaker" );
-        }
-
-        try {
-            service.successfulMethod();
-        } catch ( Exception e ) {
-            Assert.fail( "Circuit breaker should have been turned on" );
-        }
-    }
-
-    @Mixins( TestService.Mixin.class )
-    // START SNIPPET: service
-    public interface TestService
-            extends AbstractBreakOnThrowable, ServiceComposite
-    {
-
-        @BreaksCircuitOnThrowable
-        int successfulMethod();
-
-        @BreaksCircuitOnThrowable
-        void throwingMethod();
-
-        // END SNIPPET: service
-        abstract class Mixin
-                implements TestService
-        {
-
-            int count = 0;
-
-            public void throwingMethod()
-            {
-                throw new IllegalArgumentException( "Failed" );
-            }
-
-            public int successfulMethod()
-            {
-                return count++;
-            }
-
-        }
-
-        // START SNIPPET: service
-    }
-    // END SNIPPET: service
-
-}
diff --git a/libraries/circuitbreaker/src/test/java/org/qi4j/library/circuitbreaker/CircuitBreakerTest.java b/libraries/circuitbreaker/src/test/java/org/qi4j/library/circuitbreaker/CircuitBreakerTest.java
deleted file mode 100644
index b1c2ead..0000000
--- a/libraries/circuitbreaker/src/test/java/org/qi4j/library/circuitbreaker/CircuitBreakerTest.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.circuitbreaker;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyVetoException;
-import java.beans.VetoableChangeListener;
-import java.io.IOException;
-import java.util.concurrent.Callable;
-import org.hamcrest.CoreMatchers;
-import org.junit.Before;
-import org.junit.Test;
-
-import static com.jayway.awaitility.Awaitility.await;
-import static com.jayway.awaitility.Duration.ONE_SECOND;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-
-/**
- * JAVADOC
- */
-public class CircuitBreakerTest
-{
-
-    private CircuitBreaker cb;
-
-    @Before
-    public void createCircuitBreaker()
-    {
-        // START SNIPPET: direct
-        // Create a CircuitBreaker with a threshold of 3, a 250ms timeout, allowing IllegalArgumentExceptions
-        CircuitBreaker cb = new CircuitBreaker( 3, 250, CircuitBreakers.in( IllegalArgumentException.class ) );
-
-        // END SNIPPET: direct
-
-        cb.addPropertyChangeListener( new PropertyChangeListener()
-        {
-
-            public void propertyChange( PropertyChangeEvent evt )
-            {
-                System.out.println( evt.getSource() + ":" + evt.getPropertyName() + "=" + evt.getOldValue() + " -> " + evt.getNewValue() );
-            }
-
-        } );
-
-        this.cb = cb;
-    }
-
-    @Test
-    public void GivenCBWhenTripWithExceptionsAndTurnOnThenStatusIsOn()
-            throws PropertyVetoException
-    {
-
-        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
-
-        // START SNIPPET: direct
-        // Service levels goes down but does not cause a trip
-        cb.throwable( new IOException() );
-
-        // END SNIPPET: direct
-
-        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
-
-        // START SNIPPET: direct
-        // Service level goes down and causes a trip
-        cb.throwable( new IOException() );
-        cb.throwable( new IOException() );
-
-        // END SNIPPET: direct
-
-        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.off ) );
-
-        // START SNIPPET: direct
-        // Turn on the CB again
-        cb.turnOn();
-
-        // END SNIPPET: direct
-
-        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
-    }
-
-    @Test
-    public void GivenCBWhenAllowedExceptionsThenServiceLevelIsNormal()
-            throws PropertyVetoException
-    {
-
-        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
-
-        // Service level goes down
-        cb.throwable( new IOException() );
-
-        // Service levels goes up
-        cb.throwable( new IllegalArgumentException() );
-
-        assertThat( cb.serviceLevel(), CoreMatchers.equalTo( 1.0 ) );
-    }
-
-    @Test
-    public void GivenCBWhenTripCBWithExceptionsAndTimeoutThenStatusIsOn()
-            throws PropertyVetoException
-    {
-        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
-
-        // START SNIPPET: direct
-        // Service levels goes down and causes a trip
-        cb.throwable( new IOException() );
-        cb.throwable( new IOException() );
-        cb.throwable( new IOException() );
-
-        // END SNIPPET: direct
-
-        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.off ) );
-
-        // START SNIPPET: direct
-        // Wait until timeout
-
-        // END SNIPPET: direct
-        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.off ) );
-        System.out.println( "Wait..." );
-        await().atMost( ONE_SECOND ).until( circuitBreakerStatus(), is( CircuitBreaker.Status.on ) );
-
-        // START SNIPPET: direct
-        // CircuitBreaker is back on
-        
-        // END SNIPPET: direct
-        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
-    }
-    
-    private Callable<CircuitBreaker.Status> circuitBreakerStatus()
-    {
-        return new Callable<CircuitBreaker.Status>()
-        {
-            @Override
-            public CircuitBreaker.Status call() throws Exception
-            {
-                return cb.status();
-            }
-        };
-    }
-
-    @Test
-    public void GivenCBWhenExceptionsAndSuccessesThenStatusIsOn()
-            throws PropertyVetoException
-    {
-        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
-
-        // Service levels goes down and causes a trip
-        cb.throwable( new IOException() );
-        cb.throwable( new IOException() );
-        cb.success();
-        cb.success();
-        cb.throwable( new IOException() );
-        cb.throwable( new IOException() );
-
-        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
-    }
-
-    @Test
-    public void GivenCBWhenTripCBWithExceptionsAndSuccessesThenStatusIsOff()
-            throws PropertyVetoException
-    {
-        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
-
-        // Service levels goes down and causes a trip
-        cb.throwable( new IOException() );
-        cb.throwable( new IOException() );
-        cb.throwable( new IOException() );
-        cb.success();
-
-        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.off ) );
-    }
-
-    @Test
-    public void GivenCBWhenTripCBWithExceptionsAndGetStatusWithFailureThenStatusIsOff()
-            throws PropertyVetoException
-    {
-        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.on ) );
-
-        cb.addVetoableChangeListener( new VetoableChangeListener()
-        {
-
-            public void vetoableChange( PropertyChangeEvent evt )
-                    throws PropertyVetoException
-            {
-                if ( evt.getNewValue() == CircuitBreaker.Status.on ) {
-                    throw new PropertyVetoException( "Service is down", evt );
-                }
-            }
-
-        } );
-
-        // Service levels goes down and causes a trip
-        cb.throwable( new IOException() );
-        cb.throwable( new IOException() );
-        cb.throwable( new IOException() );
-
-        try {
-            System.out.println( "Wait..." );
-            Thread.sleep( 300 );
-        } catch ( InterruptedException e ) {
-            // Ignore
-        }
-
-        assertThat( cb.status(), CoreMatchers.equalTo( CircuitBreaker.Status.off ) );
-        assertThat( cb.lastThrowable().getMessage(), CoreMatchers.equalTo( "Service is down" ) );
-    }
-
-}
diff --git a/libraries/circuitbreaker/src/test/java/org/qi4j/library/circuitbreaker/jmx/CircuitBreakerManagementSample.java b/libraries/circuitbreaker/src/test/java/org/qi4j/library/circuitbreaker/jmx/CircuitBreakerManagementSample.java
deleted file mode 100644
index ef8a41d..0000000
--- a/libraries/circuitbreaker/src/test/java/org/qi4j/library/circuitbreaker/jmx/CircuitBreakerManagementSample.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.circuitbreaker.jmx;
-
-import java.util.Random;
-import javax.management.MBeanServer;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.library.circuitbreaker.CircuitBreaker;
-import org.qi4j.library.circuitbreaker.CircuitBreakers;
-import org.qi4j.library.circuitbreaker.service.ServiceCircuitBreaker;
-import org.qi4j.library.jmx.MBeanServerImporter;
-
-/**
- * Run this as a program and connect with VisualVM. That way you can monitor changes in attributes, notifications, and
- * execute operations on the CircuitBreaker through JMX.
- */
-public class CircuitBreakerManagementSample
-{
-
-    public static void main( String[] args )
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-
-            @Override
-            // START SNIPPET: jmx
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                // END SNIPPET: jmx
-                CircuitBreaker cb = new CircuitBreaker( 3, 250, CircuitBreakers.in( IllegalArgumentException.class ) );
-
-                module.importedServices( TestService.class ).setMetaInfo( new TestService( cb ) );
-
-                // START SNIPPET: jmx
-                // JMX Library
-                module.importedServices( MBeanServer.class ).
-                    importedBy( MBeanServerImporter.class );
-                // CircuitBreakers in JMX
-                module.services( CircuitBreakerManagement.class ).
-                    instantiateOnStartup();
-            }
-            // END SNIPPET: jmx
-
-        };
-
-        TestService service = assembler.module().<TestService>findService( TestService.class ).get();
-
-        int interval = 1; // Seconds
-        System.out.println( "CircuitBreaker JMX Support sample is now started." );
-        System.out.println();
-        System.out.println( "A Service that randomly output some text or fail is called through a CircuitBreaker every " + interval + " seconds." );
-        System.out.println( "In a few interval the CircuitBreaker will be turned off." );
-        System.out.println( "Connect with a MBean browser (eg. VisualVM + MBean plugin) to use the turnOn operation on the CircuitBreakers." );
-        System.out.println();
-        System.out.println( "Hit Ctrl-C to stop." );
-        System.out.println();
-
-        while ( true ) {
-            try {
-                Thread.sleep( interval * 1000 );
-            } catch ( InterruptedException e ) {
-                e.printStackTrace();
-            }
-
-            service.helloWorld();
-        }
-    }
-
-    public static class TestService
-            implements ServiceCircuitBreaker
-    {
-
-        CircuitBreaker cb;
-
-        Random random = new Random();
-
-        public TestService( CircuitBreaker cb )
-        {
-            this.cb = cb;
-        }
-
-        @Override
-        public CircuitBreaker circuitBreaker()
-        {
-            return cb;
-        }
-
-        public void helloWorld()
-        {
-            if ( random.nextDouble() > 0.3 ) {
-                cb.throwable( new Throwable( "Failed" ) );
-            } else {
-                cb.success();
-            }
-        }
-
-    }
-
-}
diff --git a/libraries/constraints/build.gradle b/libraries/constraints/build.gradle
index 826b73d..5181d76 100644
--- a/libraries/constraints/build.gradle
+++ b/libraries/constraints/build.gradle
@@ -1,31 +1,35 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Constraint Library provides common set of constraints."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - Constraints"}}
+description = "Apache Polygene™ Constraint Library provides common set of constraints."
+
+jar { manifest { name = "Apache Polygene™ Library - Constraints"}}
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
+  api polygene.core.bootstrap
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
+  runtimeOnly polygene.core.runtime
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/libraries/constraints/dev-status.xml b/libraries/constraints/dev-status.xml
index bdf00e7..0914c52 100644
--- a/libraries/constraints/dev-status.xml
+++ b/libraries/constraints/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/constraints/src/docs/constraints.txt b/libraries/constraints/src/docs/constraints.txt
index c358f75..aa5a1a3 100644
--- a/libraries/constraints/src/docs/constraints.txt
+++ b/libraries/constraints/src/docs/constraints.txt
@@ -26,7 +26,7 @@
 --------------
 
 The Constraints library provide a bunch of often used Constraints based on the
-Zest™ Constraints api described in <<def-constraint>>.
+Polygene™ Constraints api described in <<def-constraint>>.
 
 Remember that you are not limited to constraints presents in this library, you
 are encouraged to write your own constraints. See <<howto-create-constraint>>
@@ -41,7 +41,7 @@
 
 [snippet,java]
 ----
-source=libraries/constraints/src/test/java/org/qi4j/library/constraints/TestCaseComposite.java
+source=libraries/constraints/src/test/java/org/apache/polygene/library/constraints/TestCaseComposite.java
 tag=constraints
 ----
 
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/ContainsConstraint.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/ContainsConstraint.java
new file mode 100644
index 0000000..bc62ecd
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/ContainsConstraint.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.constraints;
+
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.library.constraints.annotation.Contains;
+
+/**
+ * Implement @Contains constraint for String.
+ */
+public class ContainsConstraint
+    implements Constraint<Contains, String>
+{
+    @Override
+    public boolean isValid( Contains annotation, String argument )
+    {
+        return argument.contains( annotation.value() );
+    }
+
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/GreaterThanConstraint.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/GreaterThanConstraint.java
new file mode 100644
index 0000000..e8469b1
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/GreaterThanConstraint.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.constraints;
+
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.library.constraints.annotation.GreaterThan;
+
+/**
+ * Implement @GreaterThan constraint.
+ */
+public class GreaterThanConstraint
+    implements Constraint<GreaterThan, Number>
+{
+    @Override
+    public boolean isValid( GreaterThan annotation, Number argument )
+    {
+        return argument.doubleValue() > annotation.value();
+    }
+
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/InstanceOfConstraint.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/InstanceOfConstraint.java
new file mode 100644
index 0000000..2d36e2f
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/InstanceOfConstraint.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.library.constraints;
+
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.library.constraints.annotation.InstanceOf;
+
+/**
+ * Implement @InstanceOf constraint.
+ */
+public class InstanceOfConstraint
+    implements Constraint<InstanceOf, Object>
+{
+    @Override
+    public boolean isValid( InstanceOf annotation, Object parameter )
+        throws NullPointerException
+    {
+        if( parameter != null )
+        {
+            for( Class aClass : annotation.value() )
+            {
+                if( !aClass.isInstance( parameter ) )
+                {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/LessThanConstraint.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/LessThanConstraint.java
new file mode 100644
index 0000000..432cb15
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/LessThanConstraint.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.constraints;
+
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.library.constraints.annotation.LessThan;
+
+/**
+ * Implement @LessThan constraint.
+ */
+public class LessThanConstraint
+    implements Constraint<LessThan, Number>
+{
+    @Override
+    public boolean isValid( LessThan annotation, Number argument )
+    {
+        return argument.doubleValue() < annotation.value();
+    }
+
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/MatchesConstraint.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/MatchesConstraint.java
new file mode 100644
index 0000000..d0b44fa
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/MatchesConstraint.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.constraints;
+
+import java.util.regex.Pattern;
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.library.constraints.annotation.Matches;
+
+/**
+ * Implement @Matches constraint.
+ */
+public class MatchesConstraint
+    implements Constraint<Matches, String>
+{
+    @Override
+    public boolean isValid( Matches annotation, String argument )
+    {
+        if( argument != null )
+        {
+            Pattern pattern = Pattern.compile( annotation.value() );
+            return pattern.matcher( argument ).matches();
+        }
+
+        return false;
+    }
+
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/MaxLengthConstraint.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/MaxLengthConstraint.java
new file mode 100644
index 0000000..5033f91
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/MaxLengthConstraint.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.constraints;
+
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.library.constraints.annotation.MaxLength;
+
+/**
+ * Implement @MaxLength constraint.
+ */
+public class MaxLengthConstraint
+    implements Constraint<MaxLength, String>
+{
+    @Override
+    public boolean isValid( MaxLength annotation, String argument )
+    {
+        if( argument != null )
+        {
+            return argument.length() <= annotation.value();
+        }
+        return false;
+    }
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/MinLengthConstraint.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/MinLengthConstraint.java
new file mode 100644
index 0000000..008306f
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/MinLengthConstraint.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.constraints;
+
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.library.constraints.annotation.MinLength;
+
+/**
+ * Implement @MinLength constraint.
+ */
+public class MinLengthConstraint
+    implements Constraint<MinLength, String>
+{
+    @Override
+    public boolean isValid( MinLength annotation, String parameter )
+        throws NullPointerException
+    {
+        if( parameter != null )
+        {
+            return parameter.length() >= annotation.value();
+        }
+        return false;
+    }
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/NotEmptyCollectionConstraint.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/NotEmptyCollectionConstraint.java
new file mode 100644
index 0000000..5675e05
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/NotEmptyCollectionConstraint.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.library.constraints;
+
+import java.util.Collection;
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.library.constraints.annotation.NotEmpty;
+
+/**
+ * Implement @NotEmtpy constraint for Collection.
+ */
+public class NotEmptyCollectionConstraint
+    implements Constraint<NotEmpty, Collection>
+{
+    @Override
+    public boolean isValid( NotEmpty annotation, Collection value )
+    {
+        return value.size() > 0;
+    }
+
+}
\ No newline at end of file
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/NotEmptyStringConstraint.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/NotEmptyStringConstraint.java
new file mode 100644
index 0000000..f00ef26
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/NotEmptyStringConstraint.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.constraints;
+
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.library.constraints.annotation.NotEmpty;
+
+/**
+ * Implement @NotEmpty constraint for String.
+ */
+public class NotEmptyStringConstraint
+    implements Constraint<NotEmpty, String>
+{
+    @Override
+    public boolean isValid( NotEmpty annotation, String value )
+    {
+        return value.trim().length() > 0;
+    }
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/OneOfConstraint.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/OneOfConstraint.java
new file mode 100644
index 0000000..4adce88
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/OneOfConstraint.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.library.constraints;
+
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.library.constraints.annotation.OneOf;
+
+/**
+ * Implement @OneOf constraint.
+ */
+public class OneOfConstraint
+    implements Constraint<OneOf, String>
+{
+    @Override
+    public boolean isValid( OneOf oneOf, String value )
+    {
+        for( int i = 0; i < oneOf.value().length; i++ )
+        {
+            String possibleValue = oneOf.value()[ i];
+            if( possibleValue.equals( value ) )
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
\ No newline at end of file
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/RangeConstraint.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/RangeConstraint.java
new file mode 100644
index 0000000..4a7d02d
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/RangeConstraint.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.constraints;
+
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.library.constraints.annotation.Range;
+
+/**
+ * Implement @Range constraint.
+ */
+public class RangeConstraint
+    implements Constraint<Range, Number>
+{
+    @Override
+    public boolean isValid( Range range, Number argument )
+    {
+        return argument.doubleValue() <= range.max() && argument.doubleValue() >= range.min();
+    }
+
+}
\ No newline at end of file
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/URIConstraint.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/URIConstraint.java
new file mode 100644
index 0000000..6ff0f88
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/URIConstraint.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.constraints;
+
+import java.net.URISyntaxException;
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.library.constraints.annotation.URI;
+
+public class URIConstraint
+    implements Constraint<URI, String>
+{
+    @Override
+    @SuppressWarnings( "ResultOfObjectAllocationIgnored" )
+    public boolean isValid( URI annotation, String value )
+    {
+        try
+        {
+            new java.net.URI( value );
+            return true;
+        }
+        catch( URISyntaxException ignored )
+        {
+            return false;
+        }
+    }
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/URLConstraint.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/URLConstraint.java
new file mode 100644
index 0000000..2e7d08c
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/URLConstraint.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.constraints;
+
+import java.net.MalformedURLException;
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.library.constraints.annotation.URL;
+
+public class URLConstraint
+    implements Constraint<URL, String>
+{
+    @Override
+    @SuppressWarnings( "ResultOfObjectAllocationIgnored" )
+    public boolean isValid( URL annotation, String value )
+    {
+        try
+        {
+            new java.net.URL( value );
+            return true;
+        }
+        catch( MalformedURLException ignored )
+        {
+            return false;
+        }
+    }
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/Contains.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/Contains.java
new file mode 100644
index 0000000..72efdc5
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/Contains.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.constraints.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.library.constraints.ContainsConstraint;
+
+/**
+ * Marks a property as being a string, non null, that contains the specified value.
+ */
+@ConstraintDeclaration
+@Retention( RetentionPolicy.RUNTIME )
+@Constraints( ContainsConstraint.class )
+public @interface Contains
+{
+    String value();
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/Email.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/Email.java
new file mode 100644
index 0000000..416d1ac
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/Email.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.constraints.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+
+/**
+ * Marks a property as being a string, non null, valid email.
+ */
+@ConstraintDeclaration
+@Retention( RetentionPolicy.RUNTIME )
+@NotEmpty
+@Contains( "@" )
+public @interface Email
+{
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/GreaterThan.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/GreaterThan.java
new file mode 100644
index 0000000..7939dc0
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/GreaterThan.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.constraints.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.library.constraints.GreaterThanConstraint;
+
+/**
+ * Marks a property as being a number, non null, greater than the specified value.
+ */
+@ConstraintDeclaration
+@Retention( RetentionPolicy.RUNTIME )
+@Constraints( GreaterThanConstraint.class )
+public @interface GreaterThan
+{
+    double value();
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/InstanceOf.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/InstanceOf.java
new file mode 100644
index 0000000..06d82dd
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/InstanceOf.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.library.constraints.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.library.constraints.InstanceOfConstraint;
+
+/**
+ * Marks a property as being an instance of all of the specified Classes.
+ */
+@ConstraintDeclaration
+@Retention( RetentionPolicy.RUNTIME )
+@Constraints( InstanceOfConstraint.class )
+public @interface InstanceOf
+{
+    Class[] value();
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/LessThan.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/LessThan.java
new file mode 100644
index 0000000..e451778
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/LessThan.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.constraints.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.library.constraints.LessThanConstraint;
+
+/**
+ * Marks a property as being a number, non null, less than the specified value.
+ */
+@ConstraintDeclaration
+@Retention( RetentionPolicy.RUNTIME )
+@Constraints( LessThanConstraint.class )
+public @interface LessThan
+{
+    double value();
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/Matches.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/Matches.java
new file mode 100644
index 0000000..426cbd8
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/Matches.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.constraints.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.library.constraints.MatchesConstraint;
+
+/**
+ * Marks a property as being a string, non null, matching the specified regular expression.
+ */
+@ConstraintDeclaration
+@Retention( RetentionPolicy.RUNTIME )
+@Constraints( MatchesConstraint.class )
+public @interface Matches
+{
+    String value();
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/MaxLength.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/MaxLength.java
new file mode 100644
index 0000000..46a86f7
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/MaxLength.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.constraints.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.library.constraints.MaxLengthConstraint;
+
+/**
+ * Marks a property as being a string, non null, of specified maximum length.
+ */
+@ConstraintDeclaration
+@Retention( RetentionPolicy.RUNTIME )
+@Constraints( MaxLengthConstraint.class )
+public @interface MaxLength
+{
+    int value();
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/MinLength.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/MinLength.java
new file mode 100644
index 0000000..a4cf7b8
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/MinLength.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.constraints.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.library.constraints.MinLengthConstraint;
+
+/**
+ * Marks a property as being a string, non null, of specified minimum length.
+ */
+@ConstraintDeclaration
+@Retention( RetentionPolicy.RUNTIME )
+@Constraints( MinLengthConstraint.class )
+public @interface MinLength
+{
+    int value();
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/NotEmpty.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/NotEmpty.java
new file mode 100644
index 0000000..7e0ac73
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/NotEmpty.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.constraints.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Collection;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.library.constraints.NotEmptyCollectionConstraint;
+import org.apache.polygene.library.constraints.NotEmptyStringConstraint;
+
+/**
+ * Marks a property as being a string or collection, non null, not empty.
+ */
+@ConstraintDeclaration
+@Retention( RetentionPolicy.RUNTIME )
+@InstanceOf( { String.class, Collection.class } )
+@Constraints( { NotEmptyStringConstraint.class, NotEmptyCollectionConstraint.class } )
+public @interface NotEmpty
+{
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/OneOf.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/OneOf.java
new file mode 100644
index 0000000..71bd4ba
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/OneOf.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.constraints.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.library.constraints.OneOfConstraint;
+
+/**
+ * Marks a property as being a string, non null, one of the specified strings.
+ */
+@ConstraintDeclaration
+@Retention( RetentionPolicy.RUNTIME )
+@Constraints( OneOfConstraint.class )
+public @interface OneOf
+{
+    String[] value();
+}
\ No newline at end of file
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/Range.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/Range.java
new file mode 100644
index 0000000..62874bc
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/Range.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.constraints.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.library.constraints.RangeConstraint;
+
+/**
+ * Marks a property as being a number, non null, in the specified range.
+ */
+@ConstraintDeclaration
+@Retention( RetentionPolicy.RUNTIME )
+@Constraints( RangeConstraint.class )
+public @interface Range
+{
+    double min();
+
+    double max();
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/URI.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/URI.java
new file mode 100644
index 0000000..1e7564c
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/URI.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.library.constraints.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.library.constraints.URLConstraint;
+
+/**
+ * Mark a property as being a valid, non null, Universal Resource Identifier.
+ */
+@ConstraintDeclaration
+@NotEmpty
+@Retention( RetentionPolicy.RUNTIME )
+@InstanceOf( String.class )
+@Constraints( URLConstraint.class )
+public @interface URI
+{
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/URL.java b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/URL.java
new file mode 100644
index 0000000..e5b2829
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/URL.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.constraints.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.library.constraints.URLConstraint;
+
+/**
+ * Mark a property as being a valid, non null, Universal Resource Locator.
+ */
+@ConstraintDeclaration
+@NotEmpty
+@Retention( RetentionPolicy.RUNTIME )
+@InstanceOf( String.class )
+@Constraints( URLConstraint.class )
+public @interface URL
+{
+}
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/package.html b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/package.html
new file mode 100644
index 0000000..53d8b27
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/annotation/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Constraints Annotations.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/package.html b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/package.html
new file mode 100644
index 0000000..80e2f62
--- /dev/null
+++ b/libraries/constraints/src/main/java/org/apache/polygene/library/constraints/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Constraints Library.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/ContainsConstraint.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/ContainsConstraint.java
deleted file mode 100644
index 248e040..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/ContainsConstraint.java
+++ /dev/null
@@ -1,39 +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.qi4j.library.constraints;
-
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.library.constraints.annotation.Contains;
-
-/**
- * Implement @Contains constraint for String.
- */
-public class ContainsConstraint
-    implements Constraint<Contains, String>
-{
-
-    private static final long serialVersionUID = 1L;
-
-    @Override
-    public boolean isValid( Contains annotation, String argument )
-    {
-        return argument.contains( annotation.value() );
-    }
-
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/GreaterThanConstraint.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/GreaterThanConstraint.java
deleted file mode 100644
index c28c110..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/GreaterThanConstraint.java
+++ /dev/null
@@ -1,39 +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.qi4j.library.constraints;
-
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.library.constraints.annotation.GreaterThan;
-
-/**
- * Implement @GreaterThan constraint.
- */
-public class GreaterThanConstraint
-    implements Constraint<GreaterThan, Number>
-{
-
-    private static final long serialVersionUID = 1L;
-
-    @Override
-    public boolean isValid( GreaterThan annotation, Number argument )
-    {
-        return argument.doubleValue() > annotation.value();
-    }
-
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/InstanceOfConstraint.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/InstanceOfConstraint.java
deleted file mode 100644
index 60d55e3..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/InstanceOfConstraint.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.constraints;
-
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.library.constraints.annotation.InstanceOf;
-
-/**
- * Implement @InstanceOf constraint.
- */
-public class InstanceOfConstraint
-    implements Constraint<InstanceOf, Object>
-{
-
-    private static final long serialVersionUID = 1L;
-
-    @Override
-    public boolean isValid( InstanceOf annotation, Object parameter )
-        throws NullPointerException
-    {
-        if( parameter != null )
-        {
-            for( Class aClass : annotation.value() )
-            {
-                if( !aClass.isInstance( parameter ) )
-                {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/LessThanConstraint.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/LessThanConstraint.java
deleted file mode 100644
index d6880e3..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/LessThanConstraint.java
+++ /dev/null
@@ -1,39 +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.qi4j.library.constraints;
-
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.library.constraints.annotation.LessThan;
-
-/**
- * Implement @LessThan constraint.
- */
-public class LessThanConstraint
-    implements Constraint<LessThan, Number>
-{
-
-    private static final long serialVersionUID = 1L;
-
-    @Override
-    public boolean isValid( LessThan annotation, Number argument )
-    {
-        return argument.doubleValue() < annotation.value();
-    }
-
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/MatchesConstraint.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/MatchesConstraint.java
deleted file mode 100644
index c0048a4..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/MatchesConstraint.java
+++ /dev/null
@@ -1,46 +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.qi4j.library.constraints;
-
-import java.util.regex.Pattern;
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.library.constraints.annotation.Matches;
-
-/**
- * Implement @Matches constraint.
- */
-public class MatchesConstraint
-    implements Constraint<Matches, String>
-{
-
-    private static final long serialVersionUID = 1L;
-
-    @Override
-    public boolean isValid( Matches annotation, String argument )
-    {
-        if( argument != null )
-        {
-            Pattern pattern = Pattern.compile( annotation.value() );
-            return pattern.matcher( argument ).matches();
-        }
-
-        return false;
-    }
-
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/MaxLengthConstraint.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/MaxLengthConstraint.java
deleted file mode 100644
index b837593..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/MaxLengthConstraint.java
+++ /dev/null
@@ -1,44 +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.qi4j.library.constraints;
-
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.library.constraints.annotation.MaxLength;
-
-/**
- * Implement @MaxLength constraint.
- */
-public class MaxLengthConstraint
-    implements Constraint<MaxLength, String>
-{
-
-    private static final long serialVersionUID = 1L;
-
-    @Override
-    public boolean isValid( MaxLength annotation, String argument )
-    {
-        if( argument != null )
-        {
-            return argument.length() <= annotation.value();
-        }
-
-        return false;
-    }
-
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/MinLengthConstraint.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/MinLengthConstraint.java
deleted file mode 100644
index 1efd39e..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/MinLengthConstraint.java
+++ /dev/null
@@ -1,45 +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.qi4j.library.constraints;
-
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.library.constraints.annotation.MinLength;
-
-/**
- * Implement @MinLength constraint.
- */
-public class MinLengthConstraint
-    implements Constraint<MinLength, String>
-{
-
-    private static final long serialVersionUID = 1L;
-
-    @Override
-    public boolean isValid( MinLength annotation, String parameter )
-        throws NullPointerException
-    {
-        if( parameter != null )
-        {
-            return parameter.length() >= annotation.value();
-        }
-
-        return false;
-    }
-
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/NotEmptyCollectionConstraint.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/NotEmptyCollectionConstraint.java
deleted file mode 100644
index 238329c..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/NotEmptyCollectionConstraint.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2008 Richard Wallace.
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.library.constraints;
-
-import java.util.Collection;
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.library.constraints.annotation.NotEmpty;
-
-/**
- * Implement @NotEmtpy constraint for Collection.
- */
-public class NotEmptyCollectionConstraint
-    implements Constraint<NotEmpty, Collection>
-{
-
-    private static final long serialVersionUID = 1L;
-
-    @Override
-    public boolean isValid( NotEmpty annotation, Collection value )
-    {
-        return value.size() > 0;
-    }
-
-}
\ No newline at end of file
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/NotEmptyStringConstraint.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/NotEmptyStringConstraint.java
deleted file mode 100644
index 350493a..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/NotEmptyStringConstraint.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2008 Richard Wallace.
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.library.constraints;
-
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.library.constraints.annotation.NotEmpty;
-
-/**
- * Implement @NotEmpty constraint for String.
- */
-public class NotEmptyStringConstraint
-    implements Constraint<NotEmpty, String>
-{
-
-    private static final long serialVersionUID = 1L;
-
-    @Override
-    public boolean isValid( NotEmpty annotation, String value )
-    {
-        return value.trim().length() > 0;
-    }
-
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/OneOfConstraint.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/OneOfConstraint.java
deleted file mode 100644
index a9c6d2b..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/OneOfConstraint.java
+++ /dev/null
@@ -1,47 +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.qi4j.library.constraints;
-
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.library.constraints.annotation.OneOf;
-
-/**
- * Implement @OneOf constraint.
- */
-public class OneOfConstraint
-    implements Constraint<OneOf, String>
-{
-
-    private static final long serialVersionUID = 1L;
-
-    @Override
-    public boolean isValid( OneOf oneOf, String value )
-    {
-        for( int i = 0; i < oneOf.value().length; i++ )
-        {
-            String possibleValue = oneOf.value()[ i];
-            if( possibleValue.equals( value ) )
-            {
-                return true;
-            }
-        }
-        return false;
-    }
-
-}
\ No newline at end of file
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/RangeConstraint.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/RangeConstraint.java
deleted file mode 100644
index e671ff0..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/RangeConstraint.java
+++ /dev/null
@@ -1,39 +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.qi4j.library.constraints;
-
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.library.constraints.annotation.Range;
-
-/**
- * Implement @Range constraint.
- */
-public class RangeConstraint
-    implements Constraint<Range, Number>
-{
-
-    private static final long serialVersionUID = 1L;
-
-    @Override
-    public boolean isValid( Range range, Number argument )
-    {
-        return argument.doubleValue() <= range.max() && argument.doubleValue() >= range.min();
-    }
-
-}
\ No newline at end of file
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/URIConstraint.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/URIConstraint.java
deleted file mode 100644
index 293bad1..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/URIConstraint.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.constraints;
-
-import java.net.URISyntaxException;
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.library.constraints.annotation.URI;
-
-public class URIConstraint
-    implements Constraint<URI, String>
-{
-
-    private static final long serialVersionUID = 1L;
-
-    @Override
-    @SuppressWarnings( "ResultOfObjectAllocationIgnored" )
-    public boolean isValid( URI annotation, String value )
-    {
-        try
-        {
-            new java.net.URI( value );
-            return true;
-        }
-        catch( URISyntaxException ignored )
-        {
-            return false;
-        }
-    }
-
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/URLConstraint.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/URLConstraint.java
deleted file mode 100644
index 2282621..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/URLConstraint.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.constraints;
-
-import java.net.MalformedURLException;
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.library.constraints.annotation.URL;
-
-public class URLConstraint
-    implements Constraint<URL, String>
-{
-
-    private static final long serialVersionUID = 1L;
-
-    @Override
-    @SuppressWarnings( "ResultOfObjectAllocationIgnored" )
-    public boolean isValid( URL annotation, String value )
-    {
-        try
-        {
-            new java.net.URL( value );
-            return true;
-        }
-        catch( MalformedURLException ignored )
-        {
-            return false;
-        }
-    }
-
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/Contains.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/Contains.java
deleted file mode 100644
index 8dd11be..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/Contains.java
+++ /dev/null
@@ -1,36 +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.qi4j.library.constraints.annotation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.library.constraints.ContainsConstraint;
-
-/**
- * Marks a property as being a string, non null, that contains the specified value.
- */
-@ConstraintDeclaration
-@Retention( RetentionPolicy.RUNTIME )
-@Constraints( ContainsConstraint.class )
-public @interface Contains
-{
-    String value();
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/Email.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/Email.java
deleted file mode 100644
index ddff359..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/Email.java
+++ /dev/null
@@ -1,34 +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.qi4j.library.constraints.annotation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-
-/**
- * Marks a property as being a string, non null, valid email.
- */
-@ConstraintDeclaration
-@Retention( RetentionPolicy.RUNTIME )
-@NotEmpty
-@Contains( "@" )
-public @interface Email
-{
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/GreaterThan.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/GreaterThan.java
deleted file mode 100644
index 3be628e..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/GreaterThan.java
+++ /dev/null
@@ -1,36 +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.qi4j.library.constraints.annotation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.library.constraints.GreaterThanConstraint;
-
-/**
- * Marks a property as being a number, non null, greater than the specified value.
- */
-@ConstraintDeclaration
-@Retention( RetentionPolicy.RUNTIME )
-@Constraints( GreaterThanConstraint.class )
-public @interface GreaterThan
-{
-    double value();
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/InstanceOf.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/InstanceOf.java
deleted file mode 100644
index 7f1ec9a..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/InstanceOf.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.constraints.annotation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.library.constraints.InstanceOfConstraint;
-
-/**
- * Marks a property as being an instance of all of the specified Classes.
- */
-@ConstraintDeclaration
-@Retention( RetentionPolicy.RUNTIME )
-@Constraints( InstanceOfConstraint.class )
-public @interface InstanceOf
-{
-    Class[] value();
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/LessThan.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/LessThan.java
deleted file mode 100644
index 339cf9b..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/LessThan.java
+++ /dev/null
@@ -1,36 +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.qi4j.library.constraints.annotation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.library.constraints.LessThanConstraint;
-
-/**
- * Marks a property as being a number, non null, less than the specified value.
- */
-@ConstraintDeclaration
-@Retention( RetentionPolicy.RUNTIME )
-@Constraints( LessThanConstraint.class )
-public @interface LessThan
-{
-    double value();
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/Matches.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/Matches.java
deleted file mode 100644
index aca9ca3..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/Matches.java
+++ /dev/null
@@ -1,36 +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.qi4j.library.constraints.annotation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.library.constraints.MatchesConstraint;
-
-/**
- * Marks a property as being a string, non null, matching the specified regular expression.
- */
-@ConstraintDeclaration
-@Retention( RetentionPolicy.RUNTIME )
-@Constraints( MatchesConstraint.class )
-public @interface Matches
-{
-    String value();
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/MaxLength.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/MaxLength.java
deleted file mode 100644
index c56e340..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/MaxLength.java
+++ /dev/null
@@ -1,36 +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.qi4j.library.constraints.annotation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.library.constraints.MaxLengthConstraint;
-
-/**
- * Marks a property as being a string, non null, of specified maximum length.
- */
-@ConstraintDeclaration
-@Retention( RetentionPolicy.RUNTIME )
-@Constraints( MaxLengthConstraint.class )
-public @interface MaxLength
-{
-    int value();
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/MinLength.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/MinLength.java
deleted file mode 100644
index a7bd859..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/MinLength.java
+++ /dev/null
@@ -1,36 +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.qi4j.library.constraints.annotation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.library.constraints.MinLengthConstraint;
-
-/**
- * Marks a property as being a string, non null, of specified minimum length.
- */
-@ConstraintDeclaration
-@Retention( RetentionPolicy.RUNTIME )
-@Constraints( MinLengthConstraint.class )
-public @interface MinLength
-{
-    int value();
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/NotEmpty.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/NotEmpty.java
deleted file mode 100644
index 477212c..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/NotEmpty.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2008 Rickard Oberg
- * Copyright 2008 Richard Wallace
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.library.constraints.annotation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Collection;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.library.constraints.NotEmptyCollectionConstraint;
-import org.qi4j.library.constraints.NotEmptyStringConstraint;
-
-/**
- * Marks a property as being a string or collection, non null, not empty.
- */
-@ConstraintDeclaration
-@Retention( RetentionPolicy.RUNTIME )
-@InstanceOf( { String.class, Collection.class } )
-@Constraints( { NotEmptyStringConstraint.class, NotEmptyCollectionConstraint.class } )
-public @interface NotEmpty
-{
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/OneOf.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/OneOf.java
deleted file mode 100644
index 6ab7bea..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/OneOf.java
+++ /dev/null
@@ -1,36 +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.qi4j.library.constraints.annotation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.library.constraints.OneOfConstraint;
-
-/**
- * Marks a property as being a string, non null, one of the specified strings.
- */
-@ConstraintDeclaration
-@Retention( RetentionPolicy.RUNTIME )
-@Constraints( OneOfConstraint.class )
-public @interface OneOf
-{
-    public String[] value();
-}
\ No newline at end of file
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/Range.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/Range.java
deleted file mode 100644
index 82403d7..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/Range.java
+++ /dev/null
@@ -1,38 +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.qi4j.library.constraints.annotation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.library.constraints.RangeConstraint;
-
-/**
- * Marks a property as being a number, non null, in the specified range.
- */
-@ConstraintDeclaration
-@Retention( RetentionPolicy.RUNTIME )
-@Constraints( RangeConstraint.class )
-public @interface Range
-{
-    double min();
-
-    double max();
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/URI.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/URI.java
deleted file mode 100644
index aeb98f6..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/URI.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.constraints.annotation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.library.constraints.URLConstraint;
-
-/**
- * Mark a property as being a valid, non null, Universal Resource Identifier.
- */
-@ConstraintDeclaration
-@NotEmpty
-@Retention( RetentionPolicy.RUNTIME )
-@InstanceOf( String.class )
-@Constraints( URLConstraint.class )
-public @interface URI
-{
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/URL.java b/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/URL.java
deleted file mode 100644
index 5b28b14..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/URL.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.constraints.annotation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.library.constraints.URLConstraint;
-
-/**
- * Mark a property as being a valid, non null, Universal Resource Locator.
- */
-@ConstraintDeclaration
-@NotEmpty
-@Retention( RetentionPolicy.RUNTIME )
-@InstanceOf( String.class )
-@Constraints( URLConstraint.class )
-public @interface URL
-{
-}
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/package.html b/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/package.html
deleted file mode 100644
index 17b22c5..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/annotation/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Constraints Annotations.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/constraints/src/main/java/org/qi4j/library/constraints/package.html b/libraries/constraints/src/main/java/org/qi4j/library/constraints/package.html
deleted file mode 100644
index d4c9bd0..0000000
--- a/libraries/constraints/src/main/java/org/qi4j/library/constraints/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Constraints Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/ConstraintTest.java b/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/ConstraintTest.java
new file mode 100644
index 0000000..2c526b5
--- /dev/null
+++ b/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/ConstraintTest.java
@@ -0,0 +1,284 @@
+/*
+ *  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.polygene.library.constraints;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.junit.Assert.fail;
+
+public class ConstraintTest
+    extends AbstractPolygeneTest
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( TestCaseComposite.class );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void testContainsFail()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().containsString().set( "bar" );
+    }
+
+    @Test
+    public void testContainsOk()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().containsString().set( "foo" );
+        cb.prototype().containsString().set( "xxxfooyyy" );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void testEmailFail()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().email().set( "foo.com" );
+    }
+
+    @Test
+    public void testEmailOk()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().email().set( "rickard@gmail.com" );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void testURLFail()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+        cb.prototype().url().set( "this is no url" );
+    }
+
+    @Test
+    public void testURLOk()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+        cb.prototype().url().set( "http://polygene.apache.org/path?query=string#fragment" );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void testURIFail()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+        cb.prototype().uri().set( "" );
+    }
+
+    @Test
+    public void testURIOk()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+        cb.prototype().uri().set( "http://polygene.apache.org/path?query=string#fragment" );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void testGreaterThanFail()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().greaterThan().set( 10 );
+    }
+
+    @Test
+    public void testGreaterThanOk()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().greaterThan().set( 11 );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void testInstanceOfFail()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().instanceOf().set( new HashSet() );
+    }
+
+    @Test
+    public void testInstanceOfOk()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().instanceOf().set( new ArrayList() );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void testLessThanFail()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().lessThan().set( 10 );
+    }
+
+    @Test
+    public void testLessThanOk()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().lessThan().set( 9 );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void testMatchesFail()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().matches().set( "cba" );
+    }
+
+    @Test
+    public void testMatchesOk()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().matches().set( "abbccc" );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void testMaxLengthFail()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().maxLength().set( "xxxxx" );
+    }
+
+    @Test
+    public void testMaxLengthOk()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().maxLength().set( "xxx" );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void testMinLengthFail()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().minLength().set( "xx" );
+    }
+
+    @Test
+    public void testMinLengthOk()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().minLength().set( "xxx" );
+    }
+
+    @Test
+    public void testNotEmptyFail()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+        try
+        {
+            cb.prototype().notEmptyString().set( "" );
+            fail( "Should have thrown exception" );
+        }
+        catch( ConstraintViolationException e )
+        {
+        }
+
+        try
+        {
+            cb.prototype().notEmptyCollection().set( new ArrayList() );
+            fail( "Should have thrown exception" );
+        }
+        catch( ConstraintViolationException e )
+        {
+        }
+
+        try
+        {
+            cb.prototype().notEmptyList().set( new ArrayList() );
+            fail( "Should have thrown exception" );
+        }
+        catch( ConstraintViolationException e )
+        {
+        }
+    }
+
+    @Test
+    public void testNotEmptyOk()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+        cb.prototype().notEmptyString().set( "X" );
+        cb.prototype().notEmptyCollection().set( Collections.singletonList( "X" ) );
+        cb.prototype().notEmptyList().set( Collections.singletonList( "X" ) );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void testOneOfFail()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().oneOf().set( "Foo" );
+    }
+
+    @Test
+    public void testOneOfOk()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().oneOf().set( "Bar" );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void testRangeFail()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().range().set( 101 );
+    }
+
+    @Test
+    public void testRangeOk()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+
+        cb.prototype().range().set( 0 );
+        cb.prototype().range().set( 50 );
+        cb.prototype().range().set( 100 );
+    }
+
+    @Test
+    public void testMethodParameters()
+    {
+        TransientBuilder<TestCaseComposite> cb = transientBuilderFactory.newTransientBuilder( TestCaseComposite.class );
+        cb.prototype().testParameters( 15 );
+    }
+
+}
\ No newline at end of file
diff --git a/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/TestCaseComposite.java b/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/TestCaseComposite.java
new file mode 100644
index 0000000..e8303c3
--- /dev/null
+++ b/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/TestCaseComposite.java
@@ -0,0 +1,78 @@
+/*
+ *  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.polygene.library.constraints;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+    // START SNIPPET: constraints
+    import org.apache.polygene.library.constraints.annotation.*;
+    // END SNIPPET: constraints
+
+/**
+ * Test composite with all the constraints
+ */
+@Mixins( TestCaseComposite.TestCaseMixin.class)
+public interface TestCaseComposite extends TransientComposite
+{
+    // START SNIPPET: constraints
+    @Contains( "foo" ) Property<String> containsString();
+
+    @Email Property<String> email();
+
+    @URL Property<String> url();
+
+    @URI Property<String> uri();
+
+    @GreaterThan( 10 ) Property<Integer> greaterThan();
+
+    @InstanceOf( List.class ) Property<Collection> instanceOf();
+
+    @LessThan( 10 ) Property<Integer> lessThan();
+
+    @Matches( "a*b*c*" ) Property<String> matches();
+
+    @MaxLength( 3 ) Property<String> maxLength();
+
+    @MinLength( 3 ) Property<String> minLength();
+
+    @NotEmpty Property<String> notEmptyString();
+
+    @NotEmpty Property<Collection> notEmptyCollection();
+
+    @NotEmpty Property<List> notEmptyList();
+
+    @Range( min = 0, max = 100 ) Property<Integer> range();
+
+    @OneOf( { "Bar", "Xyzzy" } ) Property<String> oneOf();
+
+    void testParameters( @GreaterThan( 10 ) Integer greaterThan );
+    // END SNIPPET: constraints
+
+    abstract class TestCaseMixin
+        implements TestCaseComposite
+    {
+        public void testParameters( @GreaterThan( 10 ) Integer greaterThan )
+        {
+        }
+    }
+}
diff --git a/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/qi70/IssueTest.java b/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/qi70/IssueTest.java
new file mode 100644
index 0000000..5f52393
--- /dev/null
+++ b/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/qi70/IssueTest.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.library.constraints.qi70;
+
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+public class IssueTest
+    extends AbstractPolygeneTest
+{
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( SampleComposite.class );
+    }
+
+    @Test( expected = ConstraintViolationException.class )
+    public void testNotEmpty()
+    {
+        TransientBuilder<Sample> cb = transientBuilderFactory.newTransientBuilder( Sample.class );
+        cb.prototypeFor( Sample.class ).stuff().set( null );
+    }
+}
diff --git a/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/qi70/Sample.java b/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/qi70/Sample.java
new file mode 100644
index 0000000..3f2af1f
--- /dev/null
+++ b/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/qi70/Sample.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.constraints.qi70;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.constraints.annotation.NotEmpty;
+
+public interface Sample
+{
+    @NotEmpty
+    Property<String> stuff();
+}
diff --git a/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/qi70/SampleComposite.java b/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/qi70/SampleComposite.java
new file mode 100644
index 0000000..4da8f9a
--- /dev/null
+++ b/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/qi70/SampleComposite.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.library.constraints.qi70;
+
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.mixin.Mixins;
+
+@Mixins( SampleMixin.class )
+public interface SampleComposite
+    extends Sample, TransientComposite
+{
+
+}
diff --git a/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/qi70/SampleMixin.java b/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/qi70/SampleMixin.java
new file mode 100644
index 0000000..486eaf7
--- /dev/null
+++ b/libraries/constraints/src/test/java/org/apache/polygene/library/constraints/qi70/SampleMixin.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.library.constraints.qi70;
+
+public class SampleMixin
+{
+
+}
diff --git a/libraries/constraints/src/test/java/org/qi4j/library/constraints/ConstraintTest.java b/libraries/constraints/src/test/java/org/qi4j/library/constraints/ConstraintTest.java
deleted file mode 100644
index 04312df..0000000
--- a/libraries/constraints/src/test/java/org/qi4j/library/constraints/ConstraintTest.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright 2008 Georg Ragaller. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.constraints;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.fail;
-
-public class ConstraintTest
-    extends AbstractQi4jTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TestCaseComposite.class );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void testContainsFail()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().containsString().set( "bar" );
-    }
-
-    @Test
-    public void testContainsOk()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().containsString().set( "foo" );
-        cb.prototype().containsString().set( "xxxfooyyy" );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void testEmailFail()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().email().set( "foo.com" );
-    }
-
-    @Test
-    public void testEmailOk()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().email().set( "rickard@gmail.com" );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void testURLFail()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-        cb.prototype().url().set( "this is no url" );
-    }
-
-    @Test
-    public void testURLOk()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-        cb.prototype().url().set( "http://qi4j.org/path?query=string#fragment" );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void testURIFail()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-        cb.prototype().uri().set( "" );
-    }
-
-    @Test
-    public void testURIOk()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-        cb.prototype().uri().set( "http://qi4j.org/path?query=string#fragment" );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void testGreaterThanFail()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().greaterThan().set( 10 );
-    }
-
-    @Test
-    public void testGreaterThanOk()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().greaterThan().set( 11 );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void testInstanceOfFail()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().instanceOf().set( new HashSet() );
-    }
-
-    @Test
-    public void testInstanceOfOk()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().instanceOf().set( new ArrayList() );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void testLessThanFail()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().lessThan().set( 10 );
-    }
-
-    @Test
-    public void testLessThanOk()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().lessThan().set( 9 );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void testMatchesFail()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().matches().set( "cba" );
-    }
-
-    @Test
-    public void testMatchesOk()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().matches().set( "abbccc" );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void testMaxLengthFail()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().maxLength().set( "xxxxx" );
-    }
-
-    @Test
-    public void testMaxLengthOk()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().maxLength().set( "xxx" );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void testMinLengthFail()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().minLength().set( "xx" );
-    }
-
-    @Test
-    public void testMinLengthOk()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().minLength().set( "xxx" );
-    }
-
-    @Test
-    public void testNotEmptyFail()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-        try
-        {
-            cb.prototype().notEmptyString().set( "" );
-            fail( "Should have thrown exception" );
-        }
-        catch( ConstraintViolationException e )
-        {
-        }
-
-        try
-        {
-            cb.prototype().notEmptyCollection().set( new ArrayList() );
-            fail( "Should have thrown exception" );
-        }
-        catch( ConstraintViolationException e )
-        {
-        }
-
-        try
-        {
-            cb.prototype().notEmptyList().set( new ArrayList() );
-            fail( "Should have thrown exception" );
-        }
-        catch( ConstraintViolationException e )
-        {
-        }
-    }
-
-    @Test
-    public void testNotEmptyOk()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-        cb.prototype().notEmptyString().set( "X" );
-        cb.prototype().notEmptyCollection().set( Arrays.asList( "X" ) );
-        cb.prototype().notEmptyList().set( Arrays.asList( "X" ) );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void testOneOfFail()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().oneOf().set( "Foo" );
-    }
-
-    @Test
-    public void testOneOfOk()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().oneOf().set( "Bar" );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void testRangeFail()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().range().set( 101 );
-    }
-
-    @Test
-    public void testRangeOk()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-
-        cb.prototype().range().set( 0 );
-        cb.prototype().range().set( 50 );
-        cb.prototype().range().set( 100 );
-    }
-
-    @Test
-    public void testMethodParameters()
-    {
-        TransientBuilder<TestCaseComposite> cb = module.newTransientBuilder( TestCaseComposite.class );
-        cb.prototype().testParameters( 15 );
-    }
-
-}
\ No newline at end of file
diff --git a/libraries/constraints/src/test/java/org/qi4j/library/constraints/TestCaseComposite.java b/libraries/constraints/src/test/java/org/qi4j/library/constraints/TestCaseComposite.java
deleted file mode 100644
index 68777f3..0000000
--- a/libraries/constraints/src/test/java/org/qi4j/library/constraints/TestCaseComposite.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2008 Georg Ragaller. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.constraints;
-
-import java.util.Collection;
-import java.util.List;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-    // START SNIPPET: constraints
-    import org.qi4j.library.constraints.annotation.*;
-    // END SNIPPET: constraints
-
-/**
- * Test composite with all the constraints
- */
-@Mixins( TestCaseComposite.TestCaseMixin.class)
-public interface TestCaseComposite extends TransientComposite
-{
-    // START SNIPPET: constraints
-    @Contains( "foo" ) Property<String> containsString();
-
-    @Email Property<String> email();
-
-    @URL Property<String> url();
-
-    @URI Property<String> uri();
-
-    @GreaterThan( 10 ) Property<Integer> greaterThan();
-
-    @InstanceOf( List.class ) Property<Collection> instanceOf();
-
-    @LessThan( 10 ) Property<Integer> lessThan();
-
-    @Matches( "a*b*c*" ) Property<String> matches();
-
-    @MaxLength( 3 ) Property<String> maxLength();
-
-    @MinLength( 3 ) Property<String> minLength();
-
-    @NotEmpty Property<String> notEmptyString();
-
-    @NotEmpty Property<Collection> notEmptyCollection();
-
-    @NotEmpty Property<List> notEmptyList();
-
-    @Range( min = 0, max = 100 ) Property<Integer> range();
-
-    @OneOf( { "Bar", "Xyzzy" } ) Property<String> oneOf();
-
-    void testParameters( @GreaterThan( 10 ) Integer greaterThan );
-    // END SNIPPET: constraints
-
-    abstract class TestCaseMixin
-        implements TestCaseComposite
-    {
-        public void testParameters( @GreaterThan( 10 ) Integer greaterThan )
-        {
-        }
-    }
-}
diff --git a/libraries/constraints/src/test/java/org/qi4j/library/constraints/qi70/IssueTest.java b/libraries/constraints/src/test/java/org/qi4j/library/constraints/qi70/IssueTest.java
deleted file mode 100644
index 9178aee..0000000
--- a/libraries/constraints/src/test/java/org/qi4j/library/constraints/qi70/IssueTest.java
+++ /dev/null
@@ -1,44 +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.qi4j.library.constraints.qi70;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-public class IssueTest
-    extends AbstractQi4jTest
-{
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( SampleComposite.class );
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void testNotEmpty()
-    {
-        TransientBuilder<Sample> cb = module.newTransientBuilder( Sample.class );
-        cb.prototypeFor( Sample.class ).stuff().set( null );
-    }
-}
diff --git a/libraries/constraints/src/test/java/org/qi4j/library/constraints/qi70/Sample.java b/libraries/constraints/src/test/java/org/qi4j/library/constraints/qi70/Sample.java
deleted file mode 100644
index ad92621..0000000
--- a/libraries/constraints/src/test/java/org/qi4j/library/constraints/qi70/Sample.java
+++ /dev/null
@@ -1,28 +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.qi4j.library.constraints.qi70;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.library.constraints.annotation.NotEmpty;
-
-public interface Sample
-{
-    @NotEmpty
-    Property<String> stuff();
-}
diff --git a/libraries/constraints/src/test/java/org/qi4j/library/constraints/qi70/SampleComposite.java b/libraries/constraints/src/test/java/org/qi4j/library/constraints/qi70/SampleComposite.java
deleted file mode 100644
index 924e2ff..0000000
--- a/libraries/constraints/src/test/java/org/qi4j/library/constraints/qi70/SampleComposite.java
+++ /dev/null
@@ -1,29 +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.qi4j.library.constraints.qi70;
-
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-
-@Mixins( SampleMixin.class )
-public interface SampleComposite
-    extends Sample, TransientComposite
-{
-
-}
diff --git a/libraries/constraints/src/test/java/org/qi4j/library/constraints/qi70/SampleMixin.java b/libraries/constraints/src/test/java/org/qi4j/library/constraints/qi70/SampleMixin.java
deleted file mode 100644
index 89202a2..0000000
--- a/libraries/constraints/src/test/java/org/qi4j/library/constraints/qi70/SampleMixin.java
+++ /dev/null
@@ -1,24 +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.qi4j.library.constraints.qi70;
-
-public class SampleMixin
-{
-
-}
diff --git a/libraries/conversion/build.gradle b/libraries/conversion/build.gradle
deleted file mode 100644
index 83a7ad7..0000000
--- a/libraries/conversion/build.gradle
+++ /dev/null
@@ -1,31 +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.
- */
-
-description = "Apache Zest™ Conversion Library has various generic services to manipulate Apache Zest™ ValueComposites, such as converting an Entity to a Value."
-
-jar { manifest { name = "Apache Zest™ Library - Conversion" }}
-
-dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
diff --git a/libraries/conversion/dev-status.xml b/libraries/conversion/dev-status.xml
deleted file mode 100644
index 515291a..0000000
--- a/libraries/conversion/dev-status.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
-  <status>
-    <!--none,early,beta,stable,mature-->
-    <codebase>stable</codebase>
-
-    <!-- none, brief, good, complete -->
-    <documentation>brief</documentation>
-
-    <!-- none, some, good, complete -->
-    <unittests>some</unittests>
-  </status>
-  <licenses>
-    <license>ALv2</license>
-  </licenses>
-</module>
diff --git a/libraries/conversion/src/docs/conversion.txt b/libraries/conversion/src/docs/conversion.txt
deleted file mode 100644
index 015f3e6..0000000
--- a/libraries/conversion/src/docs/conversion.txt
+++ /dev/null
@@ -1,129 +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.
-///////////////////////////////////////////////////////////////
-
-[[library-conversion, Conversion Library]]
-= Conversion - DEPRECATED =
-
-[devstatus]
---------------
-source=libraries/conversion/dev-status.xml
---------------
-
-The Conversion Library provides support for converting composite types.
-
-include::../../build/docs/buildinfo/artifact.txt[]
-
-
-[WARNING]
-.DEPRECATED
-====
-This functionality is now present in <<def-unitofwork>> as
-the two methods toEntity() and toValue(). Since this library was written
-assocations of all kinds are now fully supported in Values.
-====
-
-
-== Entities to Values ==
-
-To convert Entities to Values, use the EntityToValueService. It is easily assembled:
-
-[snippet,java]
-----
-source=libraries/conversion/src/test/java/org/qi4j/library/conversion/values/EntityToValueTest.java
-tag=assembly
-----
-
-Let's say we have an interface defining state:
-
-[snippet,java]
-----
-source=libraries/conversion/src/test/java/org/qi4j/library/conversion/values/TestModel.java
-tag=state
-----
-
-An EntityComposite using the state as a Private Mixin:
-
-[snippet,java]
-----
-source=libraries/conversion/src/test/java/org/qi4j/library/conversion/values/TestModel.java
-tag=entity
-----
-
-And a ValueComposite extending this very same state;
-
-[snippet,java]
-----
-source=libraries/conversion/src/test/java/org/qi4j/library/conversion/values/TestModel.java
-tag=value
-----
-
-Here is how to convert an EntityComposite to a ValueComposite:
-
-[snippet,java]
-----
-source=libraries/conversion/src/test/java/org/qi4j/library/conversion/values/EntityToValueTest.java
-tag=conversion
-----
-
-
-== Values to Entities ==
-
-Using the ValueToEntity service one can create new Entities or update existing ones from Values.
-It is easy assembled:
-
-[snippet,java]
-----
-source=libraries/conversion/src/test/java/org/qi4j/library/conversion/values/ValueToEntityTest.java
-tag=assembly
-----
-
-Let's say we have the exact same model as described above.
-
-Here is how to create an EntityComposite from a ValueComposite:
-
-[snippet,java]
-----
-source=libraries/conversion/src/test/java/org/qi4j/library/conversion/values/ValueToEntityTest.java
-tag=creation
-----
-
-Here is how to update an EntityComposite from a ValueComposite:
-
-[snippet,java]
-----
-source=libraries/conversion/src/test/java/org/qi4j/library/conversion/values/ValueToEntityTest.java
-tag=update
-----
-
-
-== Associations are converted to Identity strings ==
-
-If your Entities and Values cannot use the same state type, you can annotate the Value that is the target of the
-conversion with the `@Unqualified` annotation. Then, the lookup of the Value Property will be performed using the
-*unqualified* name only, and not via the default of the full qualified name. In other words, this means that the
-Property may be declared in the different interfaces and still be matched.
-
-Here is an example:
-
-[snippet,java]
-----
-source=libraries/conversion/src/test/java/org/qi4j/library/conversion/values/TestModel.java
-tag=unqualified
-----
-
diff --git a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValue.java b/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValue.java
deleted file mode 100644
index d09eb3e..0000000
--- a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValue.java
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- * Copyright 2010-2012 Niclas Hedhman.
- * Copyright 2011 Rickard Öberg.
- * Copyright 2013-2015 Paul Merlin.
- *
- * Licensed 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.qi4j.library.conversion.values;
-
-import java.lang.reflect.AccessibleObject;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationStateDescriptor;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.NoSuchValueException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.spi.Qi4jSPI;
-
-import static org.qi4j.library.conversion.values.Shared.STRING_COLLECTION_TYPE_SPEC;
-import static org.qi4j.library.conversion.values.Shared.STRING_MAP_TYPE_SPEC;
-import static org.qi4j.library.conversion.values.Shared.STRING_TYPE_SPEC;
-
-/**
- * @deprecated Please use {@link org.qi4j.api.unitofwork.UnitOfWork#toValue(Class, Identity)} instead.
- */
-@Mixins( EntityToValue.EntityToValueMixin.class )
-public interface EntityToValue
-{
-    /**
-     * Convert an entity to a value.
-     *
-     * @param <T> parametrized type of the value
-     * @param valueType type of the value
-     * @param entity the entity to convert to a value
-     * @return the resulting value
-     */
-    <T> T convert( Class<T> valueType, Object entity );
-
-    /**
-     * Convert an entity to a value with an opportunity to customize its prototype.
-     *
-     * @param <T> parametrized type of the value
-     * @param valueType type of the value
-     * @param entity the entity to convert to a value
-     * @param prototypeOpportunity a Function that will be mapped on the value prototype before instanciantion
-     * @return the resulting value
-     */
-    <T> T convert( Class<T> valueType, Object entity, Function<T, T> prototypeOpportunity );
-
-    /**
-     * Convert an iterable of entities to an iterable of values.
-     *
-     * @param <T> parametrized type of the value
-     * @param valueType type of the value
-     * @param entities the entities to convert to values
-     * @return the resulting values
-     */
-    <T> Iterable<T> convert( Class<T> valueType, Iterable<Object> entities );
-
-    /**
-     * Convert an iterable of entities to an iterable of values with an opportunity to customize their prototypes.
-     *
-     * @param <T> parametrized type of the value
-     * @param valueType type of the value
-     * @param entities the entities to convert to values
-     * @param prototypeOpportunity a Function that will be mapped on each of the value prototypes before instanciation.
-     * @return the resulting values
-     */
-    <T> Iterable<T> convert( Class<T> valueType, Iterable<Object> entities, Function<T, T> prototypeOpportunity );
-
-    static class EntityToValueMixin
-        implements EntityToValue
-    {
-
-        @Structure
-        private Qi4jSPI spi;
-        @Structure
-        private Module module;
-
-        @Override
-        public <T> T convert( final Class<T> valueType, Object entity )
-        {
-            return createInstance( doConversion( valueType, entity ) );
-        }
-
-        @Override
-        @SuppressWarnings( "unchecked" )
-        public <T> T convert( final Class<T> valueType, Object entity, Function<T, T> prototypeOpportunity )
-        {
-            ValueBuilder<?> builder = doConversion( valueType, entity );
-            prototypeOpportunity.map( (T) builder.prototype() );
-            return createInstance( builder );
-        }
-
-        @Override
-        public <T> Iterable<T> convert( final Class<T> valueType, Iterable<Object> entities )
-        {
-            return Iterables.map(
-                new Function<Object, T>()
-                {
-                    @Override
-                    public T map( Object entity )
-                    {
-                        return convert( valueType, entity );
-                    }
-                }, entities );
-        }
-
-        @Override
-        public <T> Iterable<T> convert( final Class<T> valueType, Iterable<Object> entities, final Function<T, T> prototypeOpportunity )
-        {
-            return Iterables.map(
-                new Function<Object, T>()
-                {
-                    @Override
-                    public T map( Object entity )
-                    {
-                        return convert( valueType, entity, prototypeOpportunity );
-                    }
-                }, entities );
-        }
-
-        private <T> ValueBuilder<?> doConversion( final Class<T> valueType, Object entity )
-        {
-            ValueDescriptor valueDescriptor = module.valueDescriptor( valueType.getName() );
-            if( valueDescriptor == null )
-            {
-                throw new NoSuchValueException( valueType.getName(), module.name() );
-            }
-            Unqualified unqualified = valueDescriptor.metaInfo( Unqualified.class );
-//            Iterable<? extends PropertyDescriptor> properties = valueDescriptor.state().properties();
-            final EntityComposite composite = (EntityComposite) entity;
-            final EntityDescriptor entityDescriptor = spi.entityDescriptorFor( composite );
-            final AssociationStateHolder associationState = spi.stateOf( composite );
-            ValueBuilder<?> builder;
-
-            if( unqualified == null || !unqualified.value() )
-            {
-                // Copy state using qualified names
-                builder = module.newValueBuilderWithState(
-                    valueType,
-                    new Function<PropertyDescriptor, Object>()
-                {
-                    @Override
-                    public Object map( PropertyDescriptor descriptor )
-                    {
-                        try
-                        {
-                            return associationState.propertyFor( descriptor.accessor() ).get();
-                        }
-                        catch( IllegalArgumentException e )
-                        {
-                            AssociationStateDescriptor entityState = entityDescriptor.state();
-                            String associationName = descriptor.qualifiedName().name();
-                            if( STRING_TYPE_SPEC.satisfiedBy( descriptor.valueType() ) )
-                            {
-                                // Find Association and convert to string
-                                AssociationDescriptor associationDescriptor;
-                                try
-                                {
-                                    associationDescriptor = entityState.getAssociationByName( associationName );
-                                }
-                                catch( IllegalArgumentException e1 )
-                                {
-                                    return null;
-                                }
-                                AccessibleObject associationMethod = associationDescriptor.accessor();
-                                Object entity = associationState.associationFor( associationMethod ).get();
-                                if( entity != null )
-                                {
-                                    return ( (Identity) entity ).identity().get();
-                                }
-                                else
-                                {
-                                    return null;
-                                }
-                            }
-                            else if( STRING_COLLECTION_TYPE_SPEC.satisfiedBy( descriptor.valueType() ) )
-                            {
-                                AssociationDescriptor associationDescriptor;
-                                try
-                                {
-                                    associationDescriptor = entityState.getManyAssociationByName( associationName );
-                                }
-                                catch( IllegalArgumentException e1 )
-                                {
-                                    return Collections.emptyList();
-                                }
-
-                                ManyAssociation<?> state = associationState.manyAssociationFor( associationDescriptor.accessor() );
-                                List<String> entities = new ArrayList<>( state.count() );
-                                for( Object entity : state )
-                                {
-                                    entities.add( ( (Identity) entity ).identity().get() );
-                                }
-                                return entities;
-                            }
-                            else if( STRING_MAP_TYPE_SPEC.satisfiedBy( descriptor.valueType() ) )
-                            {
-                                AssociationDescriptor associationDescriptor;
-                                try
-                                {
-                                    associationDescriptor = entityState.getNamedAssociationByName( associationName );
-                                }
-                                catch( IllegalArgumentException e1 )
-                                {
-                                    return Collections.emptyMap();
-                                }
-
-                                NamedAssociation<?> state = associationState.namedAssociationFor( associationDescriptor.accessor() );
-                                Map<String, String> entities = new LinkedHashMap<>( state.count() );
-                                for( String name : state )
-                                {
-                                    entities.put( name, ( (Identity) state.get( name ) ).identity().get() );
-                                }
-                                return entities;
-                            }
-
-                            return null;
-                        }
-                    }
-                    },
-                    new Function<AssociationDescriptor, EntityReference>()
-                    {
-                        @Override
-                        public EntityReference map( AssociationDescriptor associationDescriptor )
-                        {
-                            return EntityReference.entityReferenceFor(
-                                associationState.associationFor( associationDescriptor.accessor() ).get() );
-                        }
-                    },
-                    new Function<AssociationDescriptor, Iterable<EntityReference>>()
-                    {
-                        @Override
-                        public Iterable<EntityReference> map( AssociationDescriptor associationDescriptor )
-                        {
-                            ManyAssociation<?> state = associationState.manyAssociationFor( associationDescriptor.accessor() );
-                            List<EntityReference> refs = new ArrayList<>( state.count() );
-                            for( Object entity : state )
-                            {
-                                refs.add( EntityReference.entityReferenceFor( entity ) );
-                            }
-                            return refs;
-                        }
-                    },
-                    new Function<AssociationDescriptor, Map<String, EntityReference>>()
-                    {
-                        @Override
-                        public Map<String, EntityReference> map( AssociationDescriptor associationDescriptor )
-                        {
-                            NamedAssociation<?> assoc = associationState.namedAssociationFor( associationDescriptor.accessor() );
-                            Map<String, EntityReference> refs = new LinkedHashMap<>( assoc.count() );
-                            for( String name : assoc )
-                            {
-                                refs.put( name, EntityReference.entityReferenceFor( assoc.get( name ) ) );
-                            }
-                            return refs;
-                        }
-                    } );
-            }
-            else
-            {
-                builder = module.newValueBuilderWithState(valueType,
-                    new Function<PropertyDescriptor, Object>()
-                {
-                    @Override
-                    public Object map( final PropertyDescriptor descriptor )
-                    {
-                        AssociationStateDescriptor entityState = entityDescriptor.state();
-                        String propertyName = descriptor.qualifiedName().name();
-                        try
-                        {
-                            PropertyDescriptor propertyDescriptor = entityState.findPropertyModelByName( propertyName );
-                            return associationState.propertyFor( propertyDescriptor.accessor() ).get();
-                        }
-                        catch( IllegalArgumentException e )
-                        {
-                            if( STRING_TYPE_SPEC.satisfiedBy( descriptor.valueType() ) )
-                            {
-                                // Find Association and convert to string
-                                AssociationDescriptor associationDescriptor;
-                                try
-                                {
-                                    associationDescriptor = entityState.getAssociationByName( propertyName );
-                                }
-                                catch( IllegalArgumentException e1 )
-                                {
-                                    return null;
-                                }
-
-                                AccessibleObject associationMethod = associationDescriptor.accessor();
-                                Object entity = associationState.associationFor( associationMethod ).get();
-                                if( entity != null )
-                                {
-                                    return ( (Identity) entity ).identity().get();
-                                }
-                                else
-                                {
-                                    return null;
-                                }
-                            }
-                            else if( STRING_COLLECTION_TYPE_SPEC.satisfiedBy( descriptor.valueType() ) )
-                            {
-                                AssociationDescriptor associationDescriptor;
-                                try
-                                {
-                                    associationDescriptor = entityState.getManyAssociationByName( propertyName );
-                                }
-                                catch( IllegalArgumentException e1 )
-                                {
-                                    return null;
-                                }
-
-                                AccessibleObject associationMethod = associationDescriptor.accessor();
-                                ManyAssociation<?> state = associationState.manyAssociationFor( associationMethod );
-                                List<String> entities = new ArrayList<>( state.count() );
-                                for( Object entity : state )
-                                {
-                                    entities.add( ( (Identity) entity ).identity().get() );
-                                }
-                                return entities;
-                            }
-                            else if( STRING_MAP_TYPE_SPEC.satisfiedBy( descriptor.valueType() ) )
-                            {
-                                AssociationDescriptor associationDescriptor;
-                                try
-                                {
-                                    associationDescriptor = entityState.getNamedAssociationByName( propertyName );
-                                }
-                                catch( IllegalArgumentException e1 )
-                                {
-                                    return null;
-                                }
-
-                                AccessibleObject associationMethod = associationDescriptor.accessor();
-                                NamedAssociation<?> state = associationState.namedAssociationFor( associationMethod );
-                                Map<String, String> entities = new LinkedHashMap<>( state.count() );
-                                for( String name : state )
-                                {
-                                    entities.put( name, ( (Identity) state.get( name ) ).identity().get() );
-                                }
-                                return entities;
-                            }
-                            return null;
-                        }
-                    }
-                    },
-                    new Function<AssociationDescriptor, EntityReference>()
-                    {
-                        @Override
-                        public EntityReference map( AssociationDescriptor descriptor )
-                        {
-                            AssociationDescriptor associationDescriptor;
-                            try
-                            {
-                                associationDescriptor = entityDescriptor.state()
-                                    .getAssociationByName( descriptor.qualifiedName().name() );
-                            }
-                            catch( IllegalArgumentException e )
-                            {
-                                return null;
-                            }
-
-                            AccessibleObject associationMethod = associationDescriptor.accessor();
-                            Association<Object> association = associationState.associationFor( associationMethod );
-                            return EntityReference.entityReferenceFor( association.get() );
-                        }
-                    },
-                    new Function<AssociationDescriptor, Iterable<EntityReference>>()
-                    {
-                        @Override
-                        public Iterable<EntityReference> map( final AssociationDescriptor descriptor )
-                        {
-                            AssociationDescriptor associationDescriptor;
-                            try
-                            {
-                                String associationName = descriptor.qualifiedName().name();
-                                AssociationStateDescriptor entityState = entityDescriptor.state();
-                                associationDescriptor = entityState.getManyAssociationByName( associationName );
-                            }
-                            catch( IllegalArgumentException e )
-                            {
-                                return Iterables.empty();
-                            }
-
-                            ManyAssociation<?> state = associationState.manyAssociationFor( associationDescriptor.accessor() );
-                            List<EntityReference> refs = new ArrayList<>( state.count() );
-                            for( Object entity : state )
-                            {
-                                refs.add( EntityReference.entityReferenceFor( entity ) );
-                            }
-                            return refs;
-                        }
-                    },
-                    new Function<AssociationDescriptor, Map<String, EntityReference>>()
-                    {
-                        @Override
-                        public Map<String, EntityReference> map( AssociationDescriptor descriptor )
-                        {
-                            AssociationDescriptor associationDescriptor;
-                            try
-                            {
-                                String associationName = descriptor.qualifiedName().name();
-                                AssociationStateDescriptor entityState = entityDescriptor.state();
-                                associationDescriptor = entityState.getNamedAssociationByName( associationName );
-                            }
-                            catch( IllegalArgumentException e )
-                            {
-                                return Collections.emptyMap();
-                            }
-                            AccessibleObject associationMethod = associationDescriptor.accessor();
-                            NamedAssociation<Object> assoc = associationState.namedAssociationFor( associationMethod );
-                            Map<String, EntityReference> refs = new LinkedHashMap<>( assoc.count() );
-                            for( String name : assoc )
-                            {
-                                refs.put( name, EntityReference.entityReferenceFor( assoc.get( name ) ) );
-                            }
-                            return refs;
-                        }
-                    } );
-            }
-            return builder;
-        }
-
-        @SuppressWarnings( "unchecked" )
-        private <T> T createInstance( ValueBuilder<?> builder )
-        {
-            return (T) builder.newInstance();
-        }
-    }
-
-}
diff --git a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValueAssembler.java b/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValueAssembler.java
deleted file mode 100644
index 686204f..0000000
--- a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValueAssembler.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.library.conversion.values;
-
-import org.qi4j.api.entity.Identity;
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-
-/**
- * EntityToValue Service Assembler.
- * @deprecated Please use {@link org.qi4j.api.unitofwork.UnitOfWork#toValue(Class, Identity)} instead.
- */
-public class EntityToValueAssembler
-    extends Assemblers.VisibilityIdentity<EntityToValueAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ServiceDeclaration service = module.services( EntityToValueService.class ).visibleIn( visibility() );
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-    }
-}
diff --git a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValueService.java b/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValueService.java
deleted file mode 100644
index 19b4534..0000000
--- a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/EntityToValueService.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2010 Niclas Hedhman.
- *
- * Licensed 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.qi4j.library.conversion.values;
-
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.service.ServiceComposite;
-
-/** The EntityToValueService converts Entities to matching Values.
- * <p>
- * The main purpose of this service is to provide convenience to map entities to serializable values, for instance
- * to be transported across a network. The ValueComposite to convert the Entity to must closely match the Entity
- * for this mapping to work. The rules are fairly straight forward;
- * </p>
- * <ol>
- *  <li>Any Property in the EntityComposite to be mapped, must (by default) exist in the ValueComposite with the same
- *      fully qualified name, i.e. method declared in the same interface. If the ValueComposite is annotated with
- *      &#64;Unqualified then the Property method look up will only locate the properties with the name only,
- *      i.e. the methods may defined in different interfaces.</li>
- *  <li>For any Association in the EntityComposite, a Property&lt;String&gt; with the same <strong>unqualified</strong>
- *      name will be looked up in the ValueComposite. If found, the EntityReference of the Association will be
- *      converted to an URI and written to the String property.</li>
- *  <li>For any ManyAssociation in the EntityComposite, a Property&lt;List&lt;String&gt;&gt; with the same <strong>
- *      unqualified</strong> name will be looked up in the ValueComposite. If found, the EntityReferences in the
- *      ManyAssociation will be converted to URIs and placed into a List and set to the Property in ValueComposite.</li>
- *  <li>For any NamedAssociation in the EntityComposite, a Property&lt;Map&lt;String,String&gt;&gt; with the same
- *      <strong>unqualified</strong> name will be looked up in the ValueComposite. If found, the EntityReferences in
- *      the NamedAssociation will be converted to URIs and placed into a Map and set to the Property in ValueComposite.
- *      </li>
- *
- * </ol>
- * <p>
- * If a Property from the Entity is not found in the Value, then it is ignored.
- * </p>
- * @deprecated Please use {@link org.qi4j.api.unitofwork.UnitOfWork#toValue(Class, Identity)} instead.
- */
-public interface EntityToValueService extends EntityToValue, ServiceComposite
-{
-}
diff --git a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/PropertyNotPresentException.java b/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/PropertyNotPresentException.java
deleted file mode 100644
index 74ca600..0000000
--- a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/PropertyNotPresentException.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2010 Niclas Hedhman.
- *
- * Licensed 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.qi4j.library.conversion.values;
-
-import org.qi4j.api.entity.EntityComposite;
-
-public class PropertyNotPresentException extends RuntimeException
-{
-    private Class valueType;
-    private Class<? extends EntityComposite> entityType;
-
-    public PropertyNotPresentException( String message, Class valueType, Class<? extends EntityComposite> entityType )
-    {
-        super(message);
-        this.valueType = valueType;
-        this.entityType = entityType;
-    }
-
-    public Class valueType()
-    {
-        return valueType;
-    }
-
-    public Class entityType()
-    {
-        return entityType;
-    }
-}
diff --git a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/Shared.java b/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/Shared.java
deleted file mode 100644
index 5246014..0000000
--- a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/Shared.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2014-2015 Paul Merlin.
- *
- * Licensed 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.qi4j.library.conversion.values;
-
-import org.qi4j.api.type.CollectionType;
-import org.qi4j.api.type.MapType;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.functional.Specification;
-
-/**
- * Shared.
- */
-final class Shared
-{
-    static final Specification<ValueType> STRING_TYPE_SPEC;
-    static final Specification<ValueType> STRING_COLLECTION_TYPE_SPEC;
-    static final Specification<ValueType> STRING_MAP_TYPE_SPEC;
-
-    static
-    {
-        // Type Specifications
-        STRING_TYPE_SPEC = new Specification<ValueType>()
-        {
-            @Override
-            public boolean satisfiedBy( ValueType valueType )
-            {
-                return valueType.mainType().equals( String.class );
-            }
-        };
-        STRING_COLLECTION_TYPE_SPEC = new Specification<ValueType>()
-        {
-            @Override
-            public boolean satisfiedBy( ValueType valueType )
-            {
-                return valueType instanceof CollectionType
-                       && ( (CollectionType) valueType ).collectedType().mainType().equals( String.class );
-            }
-        };
-        STRING_MAP_TYPE_SPEC = new Specification<ValueType>()
-        {
-            @Override
-            public boolean satisfiedBy( ValueType valueType )
-            {
-                return valueType instanceof MapType
-                       && ( (MapType) valueType ).keyType().mainType().equals( String.class )
-                       && ( (MapType) valueType ).valueType().mainType().equals( String.class );
-            }
-        };
-    }
-
-    private Shared()
-    {
-    }
-}
diff --git a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/Unqualified.java b/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/Unqualified.java
deleted file mode 100644
index ff78993..0000000
--- a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/Unqualified.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2010 Niclas Hedhman.
- *
- * Licensed 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.qi4j.library.conversion.values;
-
-import java.lang.annotation.*;
-
-/** If the ValueComposite is annotated with this, it means that the lookup of the Value Property should be performed
- * using the <strong>unqualified</strong> name only, and not via the default of the full qualified name. This
- * means that the Property may be declared in the different interfaces and still be matched.
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( ElementType.TYPE )
-@Documented
-public @interface Unqualified
-{
-    boolean value() default true;
-}
diff --git a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/ValueToEntity.java b/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/ValueToEntity.java
deleted file mode 100644
index f42fb28..0000000
--- a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/ValueToEntity.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2014-2015 Paul Merlin.
- *
- * Licensed 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.qi4j.library.conversion.values;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.functional.Function;
-
-/**
- * Create or update Entities from matching Values.
- * @deprecated Please use {@link org.qi4j.api.unitofwork.UnitOfWork#toEntity(Class, Identity)} instead.
- */
-public interface ValueToEntity
-{
-    /**
-     * Create an Entity from a Value.
-     * <p>
-     * If the Value extends {@link Identity} the Entity identity is taken from the Value's state.
-     * Else, if the Value's state for {@code Identity} is absent, a new Identity is generated.
-     *
-     * @param <T>        Value Type
-     * @param entityType Entity Type
-     * @param value      Value
-     *
-     * @return the created Entity
-     */
-    <T> T create( Class<T> entityType, Object value );
-
-    /**
-     * Create an Entity from a Value.
-     * <p>
-     * If {@code identity} is not null, it is used as Entity identity.
-     * Else, if the Value extends {@link Identity} the Entity identity is taken from the Value's state.
-     * Else, if the Value's state for {@code Identity} is absent, a new Identity is generated.
-     *
-     * @param <T>        Value Type
-     * @param entityType Entity Type
-     * @param identity   Entity Identity, may be null
-     * @param value      Value
-     *
-     * @return the created Entity
-     */
-    <T> T create( Class<T> entityType, String identity, Object value );
-
-    /**
-     * Create an Entity from a Value.
-     * <p>
-     * If the Value extends {@link Identity} the Entity identity is taken from the Value's state.
-     * Else, if the Value's state for {@code Identity} is absent, a new Identity is generated.
-     *
-     * @param <T>                  Value Type
-     * @param entityType           Entity Type
-     * @param value                Value
-     * @param prototypeOpportunity A Function that will be mapped on the Entity prototype before instanciation
-     *
-     * @return the created Entity
-     */
-    <T> T create( Class<T> entityType, Object value, Function<T, T> prototypeOpportunity );
-
-    /**
-     * Create an Entity from a Value.
-     * <p>
-     * If {@code identity} is not null, it is used as Entity identity.
-     * Else, if the Value extends {@link Identity} the Entity identity is taken from the Value's state.
-     * Else, if the Value's state for {@code Identity} is absent, a new Identity is generated.
-     *
-     * @param <T>                  Value Type
-     * @param entityType           Entity Type
-     * @param identity             Entity Identity, may be null
-     * @param value                Value
-     * @param prototypeOpportunity A Function that will be mapped on the Entity prototype before instanciation
-     *
-     * @return the created Entity
-     */
-    <T> T create( Class<T> entityType, String identity, Object value, Function<T, T> prototypeOpportunity );
-
-    /**
-     * Create an Iterable of Entities from an Iterable of Values.
-     * <p>
-     * If a Value extends {@link Identity} the Entity identity is taken from the Value's state.
-     * Else, if a Value's state for {@code Identity} is absent, a new Identity is generated.
-     *
-     * @param <T>        Value Type
-     * @param entityType Entity Type
-     * @param values     An Iterable of Values
-     *
-     * @return the Iterable of created Entities
-     */
-    <T> Iterable<T> create( Class<T> entityType, Iterable<Object> values );
-
-    /**
-     * Create an Iterable of Entities from an Iterable of Values.
-     * <p>
-     * If a Value extends {@link Identity} the Entity identity is taken from the Value's state.
-     * Else, if a Value's state for {@code Identity} is absent, a new Identity is generated.
-     *
-     * @param <T>                  Value Type
-     * @param entityType           Entity Type
-     * @param values               An Iterable of Values
-     * @param prototypeOpportunity A Function that will be mapped on each Entity prototype before instanciation
-     *
-     * @return the Iterable of created Entities
-     */
-    <T> Iterable<T> create( Class<T> entityType, Iterable<Object> values, Function<T, T> prototypeOpportunity );
-
-    /**
-     * Update an Entity from a Value.
-     *
-     * @param entity Entity
-     * @param value  Value
-     *
-     * @throws ClassCastException    If {@code entity} is not an {@link EntityComposite}
-     *                               or if {@code value} is not a {@link ValueComposite}
-     * @throws NoSuchEntityException If some associated Entity is absent from the EntityStore/UoW
-     */
-    void update( Object entity, Object value )
-        throws ClassCastException, NoSuchEntityException;
-}
diff --git a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/ValueToEntityAssembler.java b/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/ValueToEntityAssembler.java
deleted file mode 100644
index be861ee..0000000
--- a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/ValueToEntityAssembler.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2014-2015 Paul Merlin.
- *
- * Licensed 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.qi4j.library.conversion.values;
-
-import org.qi4j.api.entity.Identity;
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-
-/**
- * ValueToEntity Service Assembler.
- * @deprecated Please use {@link org.qi4j.api.unitofwork.UnitOfWork#toEntity(Class, Identity)} instead.
- */
-public class ValueToEntityAssembler
-    extends Assemblers.VisibilityIdentity<ValueToEntityAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ServiceDeclaration service = module.services( ValueToEntityService.class ).visibleIn( visibility() );
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-    }
-}
diff --git a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/ValueToEntityMixin.java b/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/ValueToEntityMixin.java
deleted file mode 100644
index 73bae55..0000000
--- a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/ValueToEntityMixin.java
+++ /dev/null
@@ -1,838 +0,0 @@
-/*
- * Copyright (c) 2014-2015 Paul Merlin.
- *
- * Licensed 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.qi4j.library.conversion.values;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationStateDescriptor;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.common.QualifiedName;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.unitofwork.EntityTypeNotFoundException;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.spi.Qi4jSPI;
-import org.qi4j.spi.module.ModelModule;
-import org.qi4j.spi.module.ModuleSpi;
-
-import static org.qi4j.functional.Iterables.map;
-import static org.qi4j.library.conversion.values.Shared.STRING_COLLECTION_TYPE_SPEC;
-import static org.qi4j.library.conversion.values.Shared.STRING_MAP_TYPE_SPEC;
-import static org.qi4j.library.conversion.values.Shared.STRING_TYPE_SPEC;
-
-/**
- * ValueToEntity Mixin.
- *
- * @deprecated Please use {@link org.qi4j.api.unitofwork.UnitOfWork#toEntity(Class, Identity)} instead.
- */
-public class ValueToEntityMixin
-    implements ValueToEntity
-{
-    private static final QualifiedName IDENTITY_STATE_NAME;
-    private static final Function<ManyAssociation<?>, Iterable<EntityReference>> MANY_ASSOC_TO_ENTITY_REF_ITERABLE;
-    private static final Function<NamedAssociation<?>, Map<String, EntityReference>> NAMED_ASSOC_TO_ENTITY_REF_MAP;
-    private static final Function<Collection<String>, Iterable<EntityReference>> STRING_COLLEC_TO_ENTITY_REF_ITERABLE;
-    private static final Function<Map<String, String>, Map<String, EntityReference>> STRING_MAP_TO_ENTITY_REF_MAP;
-
-    static
-    {
-        try
-        {
-            IDENTITY_STATE_NAME = QualifiedName.fromAccessor( Identity.class.getMethod( "identity" ) );
-        }
-        catch( NoSuchMethodException e )
-        {
-            throw new InternalError( "Zest Core Runtime codebase is corrupted. Contact Zest team: ValueToEntityMixin" );
-        }
-        MANY_ASSOC_TO_ENTITY_REF_ITERABLE = new Function<ManyAssociation<?>, Iterable<EntityReference>>()
-        {
-            @Override
-            public Iterable<EntityReference> map( ManyAssociation<?> manyAssoc )
-            {
-                if( manyAssoc == null )
-                {
-                    return Iterables.empty();
-                }
-                List<EntityReference> refs = new ArrayList<>( manyAssoc.count() );
-                for( Object entity : manyAssoc )
-                {
-                    refs.add( EntityReference.entityReferenceFor( entity ) );
-                }
-                return refs;
-            }
-        };
-        NAMED_ASSOC_TO_ENTITY_REF_MAP = new Function<NamedAssociation<?>, Map<String, EntityReference>>()
-        {
-            @Override
-            public Map<String, EntityReference> map( NamedAssociation<?> namedAssoc )
-            {
-                if( namedAssoc == null )
-                {
-                    return Collections.emptyMap();
-                }
-                Map<String, EntityReference> refs = new LinkedHashMap<>( namedAssoc.count() );
-                for( String name : namedAssoc )
-                {
-                    refs.put( name, EntityReference.entityReferenceFor( namedAssoc.get( name ) ) );
-                }
-                return refs;
-            }
-        };
-        STRING_COLLEC_TO_ENTITY_REF_ITERABLE = new Function<Collection<String>, Iterable<EntityReference>>()
-        {
-            @Override
-            public Iterable<EntityReference> map( Collection<String> stringCollec )
-            {
-                if( stringCollec == null )
-                {
-                    return Iterables.empty();
-                }
-                List<EntityReference> refList = new ArrayList<>();
-                for( String assId : stringCollec )
-                {
-                    refList.add( EntityReference.parseEntityReference( assId ) );
-                }
-                return refList;
-            }
-        };
-        STRING_MAP_TO_ENTITY_REF_MAP = new Function<Map<String, String>, Map<String, EntityReference>>()
-        {
-            @Override
-            public Map<String, EntityReference> map( Map<String, String> stringMap )
-            {
-                if( stringMap == null )
-                {
-                    return Collections.emptyMap();
-                }
-                Map<String, EntityReference> refMap = new LinkedHashMap<>( stringMap.size() );
-                for( Map.Entry<String, String> entry : stringMap.entrySet() )
-                {
-                    refMap.put( entry.getKey(), EntityReference.parseEntityReference( entry.getValue() ) );
-                }
-                return refMap;
-            }
-        };
-    }
-
-    @Structure
-    private Qi4jSPI spi;
-
-    @Structure
-    private ModuleSpi module;
-
-    @Override
-    public <T> T create( Class<T> entityType, Object value )
-    {
-        return createInstance( doConversion( entityType, null, value ) );
-    }
-
-    @Override
-    public <T> T create( Class<T> entityType, String identity, Object value )
-    {
-        return createInstance( doConversion( entityType, identity, value ) );
-    }
-
-    @Override
-    public <T> T create( Class<T> entityType, Object value, Function<T, T> prototypeOpportunity )
-    {
-        EntityBuilder<?> builder = doConversion( entityType, null, value );
-        prototypeOpportunity.map( (T) builder.instance() );
-        return createInstance( builder );
-    }
-
-    @Override
-    public <T> T create( Class<T> entityType, String identity, Object value, Function<T, T> prototypeOpportunity )
-    {
-        EntityBuilder<?> builder = doConversion( entityType, identity, value );
-        prototypeOpportunity.map( (T) builder.instance() );
-        return createInstance( builder );
-    }
-
-    @Override
-    public <T> Iterable<T> create( final Class<T> entityType, final Iterable<Object> values )
-    {
-        return Iterables.map(
-            new Function<Object, T>()
-            {
-                @Override
-                public T map( Object value )
-                {
-                    return create( entityType, value );
-                }
-            },
-            values
-        );
-    }
-
-    @Override
-    public <T> Iterable<T> create( final Class<T> entityType,
-                                   final Iterable<Object> values,
-                                   final Function<T, T> prototypeOpportunity
-    )
-    {
-        return Iterables.map(
-            new Function<Object, T>()
-            {
-                @Override
-                public T map( Object value )
-                {
-                    return create( entityType, value, prototypeOpportunity );
-                }
-            },
-            values
-        );
-    }
-
-    private <T> EntityBuilder<?> doConversion( Class<T> entityType, String identity, Object value )
-    {
-        EntityDescriptor eDesc = module.entityDescriptor( entityType.getName() );
-        if( eDesc == null )
-        {
-            throw new EntityTypeNotFoundException( entityType.getName(),
-                                                   module.name(),
-                                                   map( ModelModule.toStringFunction,
-                                                        module.findVisibleEntityTypes()
-                                                   ) );
-        }
-
-        ValueComposite vComposite = (ValueComposite) value;
-
-        ValueDescriptor vDesc = spi.valueDescriptorFor( vComposite );
-        AssociationStateHolder vState = spi.stateOf( vComposite );
-        AssociationStateDescriptor vStateDesc = vDesc.state();
-
-        Unqualified unqualified = vDesc.metaInfo( Unqualified.class );
-        if( unqualified == null || !unqualified.value() )
-        {
-            return doQualifiedConversion( entityType, identity, vState, vStateDesc );
-        }
-        return doUnqualifiedConversion( entityType, identity, vState, vStateDesc );
-    }
-
-    private <T> EntityBuilder<?> doQualifiedConversion(
-        Class<T> entityType, String identity,
-        final AssociationStateHolder vState, final AssociationStateDescriptor vStateDesc
-    )
-    {
-        Function<PropertyDescriptor, Object> props
-            = new Function<PropertyDescriptor, Object>()
-        {
-            @Override
-            public Object map( PropertyDescriptor ePropDesc )
-            {
-                try
-                {
-                    return vState.propertyFor( ePropDesc.accessor() ).get();
-                }
-                catch( IllegalArgumentException propNotFoundOnValue )
-                {
-                    // Property not found
-                    return null;
-                }
-            }
-        };
-        Function<AssociationDescriptor, EntityReference> assocs
-            = new Function<AssociationDescriptor, EntityReference>()
-        {
-            @Override
-            public EntityReference map( AssociationDescriptor eAssocDesc )
-            {
-                try
-                {
-                    return EntityReference.entityReferenceFor( vState.associationFor( eAssocDesc.accessor() ) );
-                }
-                catch( IllegalArgumentException assocNotFoundOnValue )
-                {
-                    // Find String Property and convert to Association
-                    String propName = eAssocDesc.qualifiedName().name();
-                    try
-                    {
-                        PropertyDescriptor vPropDesc = vStateDesc.findPropertyModelByName( propName );
-                        if( STRING_TYPE_SPEC.satisfiedBy( vPropDesc.valueType() ) )
-                        {
-                            String assocState = (String) vState.propertyFor( vPropDesc.accessor() ).get();
-                            return EntityReference.parseEntityReference( assocState );
-                        }
-                        return null;
-                    }
-                    catch( IllegalArgumentException propNotFoundOnValue )
-                    {
-                        return null;
-                    }
-                }
-            }
-        };
-        Function<AssociationDescriptor, Iterable<EntityReference>> manyAssocs
-            = new Function<AssociationDescriptor, Iterable<EntityReference>>()
-        {
-            @Override
-            public Iterable<EntityReference> map( AssociationDescriptor eAssocDesc )
-            {
-                try
-                {
-                    ManyAssociation<Object> vAssocState = vState.manyAssociationFor( eAssocDesc.accessor() );
-                    return MANY_ASSOC_TO_ENTITY_REF_ITERABLE.map( vAssocState );
-                }
-                catch( IllegalArgumentException assocNotFoundOnValue )
-                {
-                    // Find Collection<String> Property and convert to ManyAssociation
-                    String propName = eAssocDesc.qualifiedName().name();
-                    try
-                    {
-                        PropertyDescriptor vPropDesc = vStateDesc.findPropertyModelByName( propName );
-                        if( STRING_COLLECTION_TYPE_SPEC.satisfiedBy( vPropDesc.valueType() ) )
-                        {
-                            Collection<String> vAssocState = (Collection) vState
-                                .propertyFor( vPropDesc.accessor() ).get();
-                            return STRING_COLLEC_TO_ENTITY_REF_ITERABLE.map( vAssocState );
-                        }
-                        return Iterables.empty();
-                    }
-                    catch( IllegalArgumentException propNotFoundOnValue )
-                    {
-                        return Iterables.empty();
-                    }
-                }
-            }
-        };
-        Function<AssociationDescriptor, Map<String, EntityReference>> namedAssocs
-            = new Function<AssociationDescriptor, Map<String, EntityReference>>()
-        {
-            @Override
-            public Map<String, EntityReference> map( AssociationDescriptor eAssocDesc )
-            {
-                try
-                {
-                    NamedAssociation<?> vAssocState = vState.namedAssociationFor( eAssocDesc.accessor() );
-                    return NAMED_ASSOC_TO_ENTITY_REF_MAP.map( vAssocState );
-                }
-                catch( IllegalArgumentException assocNotFoundOnValue )
-                {
-                    // Find Map<String,String> Property and convert to NamedAssociation
-                    String propName = eAssocDesc.qualifiedName().name();
-                    try
-                    {
-                        PropertyDescriptor vPropDesc = vStateDesc.findPropertyModelByName( propName );
-                        if( STRING_MAP_TYPE_SPEC.satisfiedBy( vPropDesc.valueType() ) )
-                        {
-                            Map<String, String> vAssocState = (Map) vState
-                                .propertyFor( vPropDesc.accessor() ).get();
-                            return STRING_MAP_TO_ENTITY_REF_MAP.map( vAssocState );
-                        }
-                        return Collections.EMPTY_MAP;
-                    }
-                    catch( IllegalArgumentException propNotFoundOnValue )
-                    {
-                        return Collections.EMPTY_MAP;
-                    }
-                }
-            }
-        };
-        return module.currentUnitOfWork().newEntityBuilderWithState(
-            entityType, identity, props, assocs, manyAssocs, namedAssocs
-        );
-    }
-
-    private <T> EntityBuilder<?> doUnqualifiedConversion(
-        Class<T> entityType, String identity,
-        final AssociationStateHolder vState, final AssociationStateDescriptor vStateDesc
-    )
-    {
-        Function<PropertyDescriptor, Object> props
-            = new Function<PropertyDescriptor, Object>()
-        {
-            @Override
-            public Object map( PropertyDescriptor ePropDesc )
-            {
-                String propName = ePropDesc.qualifiedName().name();
-                try
-                {
-                    PropertyDescriptor vPropDesc = vStateDesc.findPropertyModelByName( propName );
-                    return vState.propertyFor( vPropDesc.accessor() ).get();
-                }
-                catch( IllegalArgumentException propNotFoundOnValue )
-                {
-                    // Property not found on Value
-                    return null;
-                }
-            }
-        };
-        Function<AssociationDescriptor, EntityReference> assocs
-            = new Function<AssociationDescriptor, EntityReference>()
-        {
-            @Override
-            public EntityReference map( AssociationDescriptor eAssocDesc )
-            {
-                String assocName = eAssocDesc.qualifiedName().name();
-                try
-                {
-                    AssociationDescriptor vAssocDesc = vStateDesc.getAssociationByName( assocName );
-                    Object assocEntity = vState.associationFor( vAssocDesc.accessor() ).get();
-                    return assocEntity == null ? null : EntityReference.entityReferenceFor( assocEntity );
-                }
-                catch( IllegalArgumentException assocNotFoundOnValue )
-                {
-                    // Association not found on Value, find Property<String> and convert to Association
-                    try
-                    {
-                        PropertyDescriptor vPropDesc = vStateDesc.findPropertyModelByName( assocName );
-                        if( STRING_TYPE_SPEC.satisfiedBy( vPropDesc.valueType() ) )
-                        {
-                            String assocId = (String) vState.propertyFor( vPropDesc.accessor() ).get();
-                            return assocId == null ? null : EntityReference.parseEntityReference( assocId );
-                        }
-                        return null;
-                    }
-                    catch( IllegalArgumentException propNotFoundOnValue )
-                    {
-                        return null;
-                    }
-                }
-            }
-        };
-        Function<AssociationDescriptor, Iterable<EntityReference>> manyAssocs
-            = new Function<AssociationDescriptor, Iterable<EntityReference>>()
-        {
-            @Override
-            public Iterable<EntityReference> map( AssociationDescriptor eAssocDesc )
-            {
-                String assocName = eAssocDesc.qualifiedName().name();
-                try
-                {
-                    AssociationDescriptor vAssocDesc = vStateDesc.getManyAssociationByName( assocName );
-                    ManyAssociation<Object> vManyAssoc = vState.manyAssociationFor( vAssocDesc.accessor() );
-                    return MANY_ASSOC_TO_ENTITY_REF_ITERABLE.map( vManyAssoc );
-                }
-                catch( IllegalArgumentException assocNotFoundOnValue )
-                {
-                    // ManyAssociation not found on Value, find List<String> and convert to ManyAssociation
-                    try
-                    {
-                        PropertyDescriptor vPropDesc = vStateDesc.findPropertyModelByName( assocName );
-                        if( STRING_COLLECTION_TYPE_SPEC.satisfiedBy( vPropDesc.valueType() ) )
-                        {
-                            Collection<String> vAssocState = (Collection) vState
-                                .propertyFor( vPropDesc.accessor() ).get();
-                            return STRING_COLLEC_TO_ENTITY_REF_ITERABLE.map( vAssocState );
-                        }
-                        return Iterables.empty();
-                    }
-                    catch( IllegalArgumentException propNotFoundOnValue )
-                    {
-                        return Iterables.empty();
-                    }
-                }
-            }
-        };
-        Function<AssociationDescriptor, Map<String, EntityReference>> namedAssocs
-            = new Function<AssociationDescriptor, Map<String, EntityReference>>()
-        {
-            @Override
-            public Map<String, EntityReference> map( AssociationDescriptor eAssocDesc )
-            {
-                String assocName = eAssocDesc.qualifiedName().name();
-                try
-                {
-                    AssociationDescriptor vAssocDesc = vStateDesc.getNamedAssociationByName( assocName );
-                    NamedAssociation<Object> vAssocState = vState.namedAssociationFor( vAssocDesc.accessor() );
-                    return NAMED_ASSOC_TO_ENTITY_REF_MAP.map( vAssocState );
-                }
-                catch( IllegalArgumentException assocNotFoundOnValue )
-                {
-                    // Find Map<String,String> Property and convert to NamedAssociation
-                    try
-                    {
-                        PropertyDescriptor vPropDesc = vStateDesc.findPropertyModelByName( assocName );
-                        if( STRING_MAP_TYPE_SPEC.satisfiedBy( vPropDesc.valueType() ) )
-                        {
-                            Map<String, String> vAssocState = (Map) vState
-                                .propertyFor( vPropDesc.accessor() ).get();
-                            return STRING_MAP_TO_ENTITY_REF_MAP.map( vAssocState );
-                        }
-                        return Collections.EMPTY_MAP;
-                    }
-                    catch( IllegalArgumentException propNotFoundOnValue )
-                    {
-                        return Collections.EMPTY_MAP;
-                    }
-                }
-            }
-        };
-        return module.currentUnitOfWork().newEntityBuilderWithState(
-            entityType, identity, props, assocs, manyAssocs, namedAssocs
-        );
-    }
-
-    protected <T> T createInstance( EntityBuilder<?> builder )
-    {
-        return (T) builder.newInstance();
-    }
-
-    @Override
-    public void update( Object entity, Object value )
-        throws NoSuchEntityException
-    {
-        EntityComposite eComposite = (EntityComposite) entity;
-        ValueComposite vComposite = (ValueComposite) value;
-
-        EntityDescriptor eDesc = spi.entityDescriptorFor( eComposite );
-        AssociationStateHolder eState = spi.stateOf( eComposite );
-        AssociationStateDescriptor eStateDesc = eDesc.state();
-
-        ValueDescriptor vDesc = spi.valueDescriptorFor( vComposite );
-        AssociationStateHolder vState = spi.stateOf( vComposite );
-        AssociationStateDescriptor vStateDesc = vDesc.state();
-
-        Unqualified unqualified = vDesc.metaInfo( Unqualified.class );
-        if( unqualified == null || !unqualified.value() )
-        {
-            doQualifiedUpdate( eState, eStateDesc, vState, vStateDesc );
-        }
-        else
-        {
-            doUnQualifiedUpdate( eState, eStateDesc, vState, vStateDesc );
-        }
-    }
-
-    private void doQualifiedUpdate(
-        AssociationStateHolder eState, AssociationStateDescriptor eStateDesc,
-        AssociationStateHolder vState, AssociationStateDescriptor vStateDesc
-    )
-        throws NoSuchEntityException
-    {
-        for( PropertyDescriptor ePropDesc : eStateDesc.properties() )
-        {
-            if( IDENTITY_STATE_NAME.equals( ePropDesc.qualifiedName() ) )
-            {
-                // Ignore Identity, could be logged
-                continue;
-            }
-            try
-            {
-                PropertyDescriptor vPropDesc = vStateDesc.findPropertyModelByQualifiedName( ePropDesc.qualifiedName() );
-                eState.propertyFor( ePropDesc.accessor() ).set( vState.propertyFor( vPropDesc.accessor() ).get() );
-            }
-            catch( IllegalArgumentException propNotFoundOnValue )
-            {
-                // Property not found on Value, do nothing
-            }
-        }
-        for( AssociationDescriptor eAssocDesc : eStateDesc.associations() )
-        {
-            Association<Object> eAssoc = eState.associationFor( eAssocDesc.accessor() );
-            try
-            {
-                AssociationDescriptor vAssocDesc
-                    = vStateDesc.getAssociationByQualifiedName( eAssocDesc.qualifiedName() );
-                eAssoc.set( vState.associationFor( vAssocDesc.accessor() ).get() );
-            }
-            catch( IllegalArgumentException assocNotFoundOnValue )
-            {
-                // Association not found on Value, find Property<String> and load associated Entity
-                try
-                {
-                    PropertyDescriptor vPropDesc
-                        = vStateDesc.findPropertyModelByName( eAssocDesc.qualifiedName().name() );
-                    if( STRING_TYPE_SPEC.satisfiedBy( vPropDesc.valueType() ) )
-                    {
-                        String assocId = (String) vState.propertyFor( vPropDesc.accessor() ).get();
-                        if( assocId != null )
-                        {
-                            eAssoc.set( module.currentUnitOfWork().get( (Class) eAssocDesc.type(), assocId ) );
-                        }
-                        else
-                        {
-                            eAssoc.set( null );
-                        }
-                    }
-                }
-                catch( IllegalArgumentException propNotFoundOnValue )
-                {
-                    // Do nothing
-                }
-            }
-        }
-        for( AssociationDescriptor eAssocDesc : eStateDesc.manyAssociations() )
-        {
-            ManyAssociation<Object> eManyAssoc = eState.manyAssociationFor( eAssocDesc.accessor() );
-            try
-            {
-                AssociationDescriptor vAssocDesc
-                    = vStateDesc.getManyAssociationByQualifiedName( eAssocDesc.qualifiedName() );
-                ManyAssociation<Object> vManyAssoc = vState.manyAssociationFor( vAssocDesc.accessor() );
-                for( Object assoc : eManyAssoc.toList() )
-                {
-                    eManyAssoc.remove( assoc );
-                }
-                for( Object assoc : vManyAssoc.toList() )
-                {
-                    eManyAssoc.add( assoc );
-                }
-            }
-            catch( IllegalArgumentException assocNotFoundOnValue )
-            {
-                // ManyAssociation not found on Value, find Property<List<String>> and load associated Entities
-                try
-                {
-                    PropertyDescriptor vPropDesc
-                        = vStateDesc.findPropertyModelByName( eAssocDesc.qualifiedName().name() );
-                    if( STRING_COLLECTION_TYPE_SPEC.satisfiedBy( vPropDesc.valueType() ) )
-                    {
-                        Collection<String> vAssocState = (Collection) vState.propertyFor( vPropDesc.accessor() ).get();
-                        for( Object assoc : eManyAssoc.toList() )
-                        {
-                            eManyAssoc.remove( assoc );
-                        }
-                        if( vAssocState != null )
-                        {
-                            for( String eachAssoc : vAssocState )
-                            {
-                                eManyAssoc.add(
-                                    module.currentUnitOfWork().get( (Class) eAssocDesc.type(), eachAssoc )
-                                );
-                            }
-                        }
-                    }
-                }
-                catch( IllegalArgumentException propNotFoundOnValue )
-                {
-                    // Do nothing
-                }
-            }
-        }
-        for( AssociationDescriptor eAssocDesc : eStateDesc.namedAssociations() )
-        {
-            NamedAssociation<Object> eNamedAssoc = eState.namedAssociationFor( eAssocDesc.accessor() );
-            try
-            {
-                AssociationDescriptor vAssocDesc
-                    = vStateDesc.getNamedAssociationByQualifiedName( eAssocDesc.qualifiedName() );
-                NamedAssociation<Object> vNamedAssoc = vState.namedAssociationFor( vAssocDesc.accessor() );
-                for( String assocName : Iterables.toList( eNamedAssoc ) )
-                {
-                    eNamedAssoc.remove( assocName );
-                }
-                for( Map.Entry<String, Object> assocEntry : vNamedAssoc.toMap().entrySet() )
-                {
-                    eNamedAssoc.put( assocEntry.getKey(), assocEntry.getValue() );
-                }
-            }
-            catch( IllegalArgumentException assocNotFoundOnValue )
-            {
-                // NamedAssociation not found on Value, find Property<Map<String,String>> and load associated Entities
-                try
-                {
-                    PropertyDescriptor vPropDesc
-                        = vStateDesc.findPropertyModelByName( eAssocDesc.qualifiedName().name() );
-                    if( STRING_MAP_TYPE_SPEC.satisfiedBy( vPropDesc.valueType() ) )
-                    {
-                        Map<String, String> vAssocState = (Map) vState.propertyFor( vPropDesc.accessor() ).get();
-                        for( String assocName : Iterables.toList( eNamedAssoc ) )
-                        {
-                            eNamedAssoc.remove( assocName );
-                        }
-                        if( vAssocState != null )
-                        {
-                            for( Map.Entry<String, String> assocEntry : vAssocState.entrySet() )
-                            {
-                                eNamedAssoc.put(
-                                    assocEntry.getKey(),
-                                    module.currentUnitOfWork().get( (Class) eAssocDesc.type(), assocEntry.getValue() )
-                                );
-                            }
-                        }
-                    }
-                }
-                catch( IllegalArgumentException propNotFoundOnValue )
-                {
-                    // Do nothing
-                }
-            }
-        }
-    }
-
-    private void doUnQualifiedUpdate(
-        AssociationStateHolder eState, AssociationStateDescriptor eStateDesc,
-        AssociationStateHolder vState, AssociationStateDescriptor vStateDesc
-    )
-    {
-        for( PropertyDescriptor ePropDesc : eStateDesc.properties() )
-        {
-            if( IDENTITY_STATE_NAME.equals( ePropDesc.qualifiedName() ) )
-            {
-                // Ignore Identity, could be logged
-                continue;
-            }
-            try
-            {
-                PropertyDescriptor vPropDesc = vStateDesc.findPropertyModelByName( ePropDesc.qualifiedName().name() );
-                eState.propertyFor( ePropDesc.accessor() ).set( vState.propertyFor( vPropDesc.accessor() ).get() );
-            }
-            catch( IllegalArgumentException propNotFoundOnValue )
-            {
-                // Property not found on Value, do nothing
-            }
-        }
-        for( AssociationDescriptor eAssocDesc : eStateDesc.associations() )
-        {
-            Association<Object> eAssoc = eState.associationFor( eAssocDesc.accessor() );
-            try
-            {
-                AssociationDescriptor vAssocDesc = vStateDesc.getAssociationByName( eAssocDesc.qualifiedName().name() );
-                eAssoc.set( vState.associationFor( vAssocDesc.accessor() ).get() );
-            }
-            catch( IllegalArgumentException assocNotFoundOnValue )
-            {
-                // Association not found on Value, find Property<String> and load associated Entity
-                try
-                {
-                    PropertyDescriptor vPropDesc
-                        = vStateDesc.findPropertyModelByName( eAssocDesc.qualifiedName().name() );
-                    if( STRING_TYPE_SPEC.satisfiedBy( vPropDesc.valueType() ) )
-                    {
-                        String assocId = (String) vState.propertyFor( vPropDesc.accessor() ).get();
-                        if( assocId != null )
-                        {
-                            eAssoc.set( module.currentUnitOfWork().get( (Class) eAssocDesc.type(), assocId ) );
-                        }
-                        else
-                        {
-                            eAssoc.set( null );
-                        }
-                    }
-                }
-                catch( IllegalArgumentException propNotFoundOnValue )
-                {
-                    // Do nothing
-                }
-            }
-        }
-        for( AssociationDescriptor eAssocDesc : eStateDesc.manyAssociations() )
-        {
-            ManyAssociation<Object> eManyAssoc = eState.manyAssociationFor( eAssocDesc.accessor() );
-            try
-            {
-                AssociationDescriptor vAssDesc
-                    = vStateDesc.getManyAssociationByName( eAssocDesc.qualifiedName().name() );
-                ManyAssociation<Object> vManyAss = vState.manyAssociationFor( vAssDesc.accessor() );
-                for( Object ass : eManyAssoc.toList() )
-                {
-                    eManyAssoc.remove( ass );
-                }
-                for( Object ass : vManyAss.toList() )
-                {
-                    eManyAssoc.add( ass );
-                }
-            }
-            catch( IllegalArgumentException assNotFoundOnValue )
-            {
-                // ManyAssociation not found on Value, find Property<List<String>> and load associated Entities
-                try
-                {
-                    PropertyDescriptor vPropDesc
-                        = vStateDesc.findPropertyModelByName( eAssocDesc.qualifiedName().name() );
-                    if( STRING_COLLECTION_TYPE_SPEC.satisfiedBy( vPropDesc.valueType() ) )
-                    {
-                        Collection<String> vAssocState = (Collection) vState.propertyFor( vPropDesc.accessor() ).get();
-                        for( Object ass : eManyAssoc.toList() )
-                        {
-                            eManyAssoc.remove( ass );
-                        }
-                        if( vAssocState != null )
-                        {
-                            for( String eachAssoc : vAssocState )
-                            {
-                                eManyAssoc.add(
-                                    module.currentUnitOfWork().get( (Class) eAssocDesc.type(), eachAssoc )
-                                );
-                            }
-                        }
-                    }
-                }
-                catch( IllegalArgumentException propNotFoundOnValue )
-                {
-                    // Do nothing
-                }
-            }
-        }
-        for( AssociationDescriptor eAssocDesc : eStateDesc.namedAssociations() )
-        {
-            NamedAssociation<Object> eNamedAssoc = eState.namedAssociationFor( eAssocDesc.accessor() );
-            try
-            {
-                AssociationDescriptor vAssocDesc
-                    = vStateDesc.getNamedAssociationByName( eAssocDesc.qualifiedName().name() );
-                NamedAssociation<Object> vNamedAssoc = vState.namedAssociationFor( vAssocDesc.accessor() );
-                for( String assocName : Iterables.toList( eNamedAssoc ) )
-                {
-                    eNamedAssoc.remove( assocName );
-                }
-                for( Map.Entry<String, Object> assocEntry : vNamedAssoc.toMap().entrySet() )
-                {
-                    eNamedAssoc.put( assocEntry.getKey(), assocEntry.getValue() );
-                }
-            }
-            catch( IllegalArgumentException assocNotFoundOnValue )
-            {
-                // NamedAssociation not found on Value, find Property<Map<String,String>> and load associated Entities
-                try
-                {
-                    PropertyDescriptor vPropDesc
-                        = vStateDesc.findPropertyModelByName( eAssocDesc.qualifiedName().name() );
-                    if( STRING_MAP_TYPE_SPEC.satisfiedBy( vPropDesc.valueType() ) )
-                    {
-                        Map<String, String> vAssocState = (Map) vState.propertyFor( vPropDesc.accessor() ).get();
-                        for( String assocName : Iterables.toList( eNamedAssoc ) )
-                        {
-                            eNamedAssoc.remove( assocName );
-                        }
-                        if( vAssocState != null )
-                        {
-                            for( Map.Entry<String, String> assocEntry : vAssocState.entrySet() )
-                            {
-                                eNamedAssoc.put(
-                                    assocEntry.getKey(),
-                                    module.currentUnitOfWork().get( (Class) eAssocDesc.type(), assocEntry.getValue() )
-                                );
-                            }
-                        }
-                    }
-                }
-                catch( IllegalArgumentException propNotFoundOnValue )
-                {
-                    // Do nothing
-                }
-            }
-        }
-    }
-}
diff --git a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/ValueToEntityService.java b/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/ValueToEntityService.java
deleted file mode 100644
index 2d2fa7d..0000000
--- a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/ValueToEntityService.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2014-2015 Paul Merlin.
- *
- * Licensed 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.qi4j.library.conversion.values;
-
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.mixin.Mixins;
-
-/**
- * Service that creates or updates Entities from matching Values.
- * @deprecated Please use {@link org.qi4j.api.unitofwork.UnitOfWork#toEntity(Class, Identity)} instead.
- */
-@Mixins( ValueToEntityMixin.class )
-public interface ValueToEntityService
-    extends ValueToEntity
-{
-}
diff --git a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/package.html b/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/package.html
deleted file mode 100644
index e2be575..0000000
--- a/libraries/conversion/src/main/java/org/qi4j/library/conversion/values/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Entities to Values Conversion.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/conversion/src/test/java/org/qi4j/library/conversion/values/EntityToValueTest.java b/libraries/conversion/src/test/java/org/qi4j/library/conversion/values/EntityToValueTest.java
deleted file mode 100644
index a6e980c..0000000
--- a/libraries/conversion/src/test/java/org/qi4j/library/conversion/values/EntityToValueTest.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright 2010-2012 Niclas Hedhman.
- * Copyright 2011 Rickard Öberg.
- * Copyright 2013-2015 Paul Merlin.
- *
- * Licensed 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.qi4j.library.conversion.values;
-
-import java.util.Date;
-import org.junit.Test;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Function;
-import org.qi4j.library.conversion.values.TestModel.PersonEntity;
-import org.qi4j.library.conversion.values.TestModel.PersonValue;
-import org.qi4j.library.conversion.values.TestModel.PersonValue2;
-import org.qi4j.library.conversion.values.TestModel.PersonValue3;
-import org.qi4j.library.conversion.values.TestModel.PersonValue4;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.assertEquals;
-import static org.qi4j.library.conversion.values.TestModel.createBirthDate;
-import static org.qi4j.library.conversion.values.TestModel.createPerson;
-
-public class EntityToValueTest
-    extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // START SNIPPET: assembly
-        new EntityToValueAssembler().assemble( module );
-        // END SNIPPET: assembly
-        new EntityTestAssembler().assemble( module );
-        module.entities( PersonEntity.class );
-        module.values( PersonValue.class );
-        module.values( PersonValue2.class );
-        module.values( PersonValue3.class );
-        module.values( PersonValue4.class );
-    }
-
-    @Test
-    public void whenConvertingEntityToValueExpectCorrectValues()
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            PersonEntity entity = setupPersonEntities( uow );
-
-            // START SNIPPET: conversion
-            EntityToValueService conversion = module.findService( EntityToValueService.class ).get();
-            PersonValue value = conversion.convert( PersonValue.class, entity );
-            // END SNIPPET: conversion
-            assertEquals( "Niclas", value.firstName().get() );
-            assertEquals( "Hedhman", value.lastName().get() );
-            assertEquals( "id:Lis", value.spouse().get() );
-            assertEquals( "id:Eric", value.children().get().get( 0 ) );
-            uow.complete();
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void givenUnqualifiedValueWhenConvertingEntityExpectCorrectMapping()
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            PersonEntity niclas = setupPersonEntities( uow );
-
-            ServiceReference<EntityToValueService> reference = module.findService( EntityToValueService.class );
-            EntityToValueService service = reference.get();
-
-            PersonValue2 niclasValue = service.convert( PersonValue2.class, niclas );
-            assertEquals( "Niclas", niclasValue.firstName().get() );
-            assertEquals( "Hedhman", niclasValue.lastName().get() );
-            assertEquals( "id:Lis", niclasValue.spouse().get() );
-            assertEquals( "id:Eric", niclasValue.children().get().get( 0 ) );
-            uow.complete();
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void givenUnqualifiedValue2WhenConvertingEntityExpectCorrectMapping()
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            PersonEntity niclas = setupPersonEntities( uow );
-
-            ServiceReference<EntityToValueService> reference = module.findService( EntityToValueService.class );
-            EntityToValueService service = reference.get();
-
-            PersonValue3 niclasValue = service.convert( PersonValue3.class, niclas );
-            assertEquals( "Niclas", niclasValue.firstName().get() );
-            assertEquals( "Hedhman", niclasValue.lastName().get() );
-            assertEquals( "id:Lis", niclasValue.spouse().get() );
-            assertEquals( "id:Eric", niclasValue.children().get().get( 0 ) );
-            uow.complete();
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void givenQualifiedValueNotFromSameInterfaceWhenConvertingEntityExpectNonOptionalException()
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            PersonEntity niclas = setupPersonEntities( uow );
-
-            ServiceReference<EntityToValueService> reference = module.findService( EntityToValueService.class );
-            EntityToValueService service = reference.get();
-
-            PersonValue4 niclasValue = service.convert( PersonValue4.class, niclas );
-            uow.complete();
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void whenConvertingEntityToValueUsingPrototypeOpportunityExpectCorrectValues()
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            PersonEntity entity = setupPersonEntities( uow );
-
-            // START SNIPPET: prototypeOpportunity
-            EntityToValueService conversion = module.findService( EntityToValueService.class ).get();
-            PersonValue value = conversion.convert( PersonValue.class, entity, new Function<PersonValue, PersonValue>()
-            {
-                @Override
-                public PersonValue map( PersonValue prototype )
-                {
-                    prototype.firstName().set( "Prototype Opportunity" );
-                    return prototype;
-                }
-            } );
-            // END SNIPPET: prototypeOpportunity
-            assertEquals( "Prototype Opportunity", value.firstName().get() );
-            assertEquals( "Hedhman", value.lastName().get() );
-            assertEquals( "id:Lis", value.spouse().get() );
-            assertEquals( "id:Eric", value.children().get().get( 0 ) );
-            uow.complete();
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    private static PersonEntity setupPersonEntities( UnitOfWork uow )
-    {
-        PersonEntity niclas = createNiclas( uow );
-        PersonEntity lis = createLis( uow );
-        PersonEntity eric = createEric( uow );
-        niclas.spouse().set( lis );
-        niclas.children().add( eric );
-        lis.spouse().set( niclas );
-        lis.children().add( eric );
-        assertEquals( "Niclas", niclas.firstName() );
-        assertEquals( "Hedhman", niclas.lastName() );
-        assertEquals( "Lis", lis.firstName() );
-        assertEquals( "Gazi", lis.lastName() );
-        assertEquals( "Eric", eric.firstName() );
-        assertEquals( "Hedman", eric.lastName() );
-        return niclas;
-    }
-
-    private static PersonEntity createNiclas( UnitOfWork uow )
-    {
-        String firstName = "Niclas";
-        String lastName = "Hedhman";
-        Date birthTime = createBirthDate( 1964, 9, 25 );
-        return createPerson( uow, firstName, lastName, birthTime );
-    }
-
-    private static PersonEntity createLis( UnitOfWork uow )
-    {
-        String firstName = "Lis";
-        String lastName = "Gazi";
-        Date birthTime = createBirthDate( 1976, 2, 19 );
-        return createPerson( uow, firstName, lastName, birthTime );
-    }
-
-    private static PersonEntity createEric( UnitOfWork uow )
-    {
-        String firstName = "Eric";
-        String lastName = "Hedman";
-        Date birthTime = createBirthDate( 2004, 4, 8 );
-        return createPerson( uow, firstName, lastName, birthTime );
-    }
-}
diff --git a/libraries/conversion/src/test/java/org/qi4j/library/conversion/values/NestedValuesConversionTest.java b/libraries/conversion/src/test/java/org/qi4j/library/conversion/values/NestedValuesConversionTest.java
deleted file mode 100644
index 9e3f66d..0000000
--- a/libraries/conversion/src/test/java/org/qi4j/library/conversion/values/NestedValuesConversionTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.conversion.values;
-
-import java.util.Arrays;
-import java.util.List;
-import org.junit.Test;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
-
-public class NestedValuesConversionTest
-    extends AbstractQi4jTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly ma )
-        throws AssemblyException
-    {
-        new EntityToValueAssembler().assemble( ma );
-        new EntityTestAssembler().assemble( ma );
-
-        ma.entities( FooEntity.class );
-        ma.values( FooValue.class, BarValue.class );
-    }
-
-    @Test
-    public void testNestedValuesConversion()
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            FooEntity fooEntity = createFooEntity( uow, "Test nested values conversion" );
-            EntityToValueService conversion = module.findService( EntityToValueService.class ).get();
-            FooValue fooValue = conversion.convert( FooValue.class, fooEntity );
-            assertThat( fooValue.name().get(), equalTo( "Test nested values conversion" ) );
-            assertThat( fooValue.bar().get().bazar().get(), equalTo( "single" ) );
-            List<BarValue> barList = fooValue.barList().get();
-            assertThat( barList.size(), equalTo( 3 ) );
-            assertThat( barList.get( 0 ).bazar().get(), equalTo( "multi-one" ) );
-            assertThat( barList.get( 1 ).bazar().get(), equalTo( "multi-two" ) );
-            assertThat( barList.get( 2 ).bazar().get(), equalTo( "multi-three" ) );
-            uow.complete();
-            uow = null;
-        }
-        finally
-        {
-            if( uow != null )
-            {
-                uow.discard();
-            }
-        }
-    }
-
-    private FooEntity createFooEntity( UnitOfWork uow, String name )
-    {
-        EntityBuilder<FooEntity> builder = uow.newEntityBuilder( FooEntity.class );
-        builder.instance().name().set( name );
-        builder.instance().bar().set( createBarValue( "single" ) );
-        List<BarValue> bars = Arrays.asList( createBarValue( "multi-one" ),
-                                             createBarValue( "multi-two" ),
-                                             createBarValue( "multi-three" ) );
-        builder.instance().barList().set( bars );
-        return builder.newInstance();
-    }
-
-    private BarValue createBarValue( String bazar )
-    {
-        ValueBuilder<BarValue> builder = module.newValueBuilder( BarValue.class );
-        builder.prototype().bazar().set( bazar );
-        return builder.newInstance();
-    }
-
-    public interface FooState
-    {
-
-        Property<String> name();
-
-        Property<BarValue> bar();
-
-        Property<List<BarValue>> barList();
-    }
-
-    public interface FooValue
-        extends FooState, ValueComposite
-    {
-    }
-
-    public interface FooEntity
-        extends FooState, EntityComposite
-    {
-    }
-
-    public interface BarValue
-        extends ValueComposite
-    {
-
-        Property<String> bazar();
-    }
-
-}
diff --git a/libraries/conversion/src/test/java/org/qi4j/library/conversion/values/TestModel.java b/libraries/conversion/src/test/java/org/qi4j/library/conversion/values/TestModel.java
deleted file mode 100644
index 1361380..0000000
--- a/libraries/conversion/src/test/java/org/qi4j/library/conversion/values/TestModel.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright 2010-2012 Niclas Hedhman.
- * Copyright 2011 Rickard Öberg.
- * Copyright 2013-2015 Paul Merlin.
- *
- * Licensed 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.qi4j.library.conversion.values;
-
-import java.util.Calendar;
-import java.util.Date;
-import java.util.List;
-import java.util.TimeZone;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * Test Model.
- */
-final class TestModel
-{
-    static PersonEntity createPerson( UnitOfWork uow, String firstName, String lastName, Date birthTime )
-    {
-        EntityBuilder<PersonEntity> builder = uow.newEntityBuilder( PersonEntity.class, "id:" + firstName );
-        PersonState state = builder.instanceFor( PersonState.class );
-        state.firstName().set( firstName );
-        state.lastName().set( lastName );
-        state.dateOfBirth().set( birthTime );
-        return builder.newInstance();
-    }
-
-    static Date createBirthDate( int year, int month, int day )
-    {
-        Calendar calendar = Calendar.getInstance();
-        calendar.setTimeZone( TimeZone.getTimeZone( "UTC" ) );
-        calendar.set( year, month - 1, day, 12, 0, 0 );
-        return calendar.getTime();
-    }
-
-    // START SNIPPET: state
-    public interface PersonState
-    {
-
-        Property<String> firstName();
-
-        Property<String> lastName();
-
-        Property<Date> dateOfBirth();
-
-    }
-    // END SNIPPET: state
-
-    // START SNIPPET: value
-    public interface PersonValue
-        extends PersonState, ValueComposite
-    {
-
-        @Optional
-        Property<String> spouse();
-
-        @Optional
-        Property<List<String>> children();
-
-    }
-    // END SNIPPET: value
-
-    // START SNIPPET: entity
-    @Mixins( PersonMixin.class )
-    public interface PersonEntity
-        extends EntityComposite
-    {
-
-        String firstName();
-
-        String lastName();
-
-        Integer age();
-
-        @Optional
-        Association<PersonEntity> spouse();
-
-        ManyAssociation<PersonEntity> children();
-
-    }
-    // END SNIPPET: entity
-
-    // START SNIPPET: entity
-    public static abstract class PersonMixin
-        implements PersonEntity
-    {
-
-        @This
-        private PersonState state;
-        // END SNIPPET: entity
-
-        @Override
-        public String firstName()
-        {
-            return state.firstName().get();
-        }
-
-        @Override
-        public String lastName()
-        {
-            return state.lastName().get();
-        }
-
-        @Override
-        public Integer age()
-        {
-            long now = System.currentTimeMillis();
-            long birthdate = state.dateOfBirth().get().getTime();
-            return (int) ( ( now - birthdate ) / 1000 / 3600 / 24 / 365.25 );
-        }
-
-        // START SNIPPET: entity
-    }
-    // END SNIPPET: entity
-
-    // START SNIPPET: unqualified
-    @Unqualified
-    public interface PersonValue2
-        extends ValueComposite
-    {
-
-        Property<String> firstName();
-
-        Property<String> lastName();
-
-        Property<Date> dateOfBirth();
-
-        @Optional
-        Property<String> spouse();
-
-        @Optional
-        Property<List<String>> children();
-
-    }
-    // END SNIPPET: unqualified
-
-    @Unqualified( true )
-    public interface PersonValue3
-        extends ValueComposite
-    {
-
-        Property<String> firstName();
-
-        Property<String> lastName();
-
-        Property<Date> dateOfBirth();
-
-        @Optional
-        Property<String> spouse();
-
-        @Optional
-        Property<List<String>> children();
-
-    }
-
-    @Unqualified( false )
-    public interface PersonValue4
-        extends ValueComposite
-    {
-
-        Property<String> firstName();
-
-        Property<String> lastName();
-
-        Property<Date> dateOfBirth();
-
-        @Optional
-        Property<String> spouse();
-
-        @Optional
-        Property<List<String>> children();
-
-    }
-
-    private TestModel()
-    {
-    }
-}
diff --git a/libraries/conversion/src/test/java/org/qi4j/library/conversion/values/ValueToEntityTest.java b/libraries/conversion/src/test/java/org/qi4j/library/conversion/values/ValueToEntityTest.java
deleted file mode 100644
index 2f74d41..0000000
--- a/libraries/conversion/src/test/java/org/qi4j/library/conversion/values/ValueToEntityTest.java
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright (c) 2014-2015 Paul Merlin.
- *
- * Licensed 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.qi4j.library.conversion.values;
-
-import java.util.Arrays;
-import java.util.Date;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.library.conversion.values.TestModel.PersonEntity;
-import org.qi4j.library.conversion.values.TestModel.PersonValue;
-import org.qi4j.library.conversion.values.TestModel.PersonValue2;
-import org.qi4j.library.conversion.values.TestModel.PersonValue3;
-import org.qi4j.library.conversion.values.TestModel.PersonValue4;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.api.usecase.UsecaseBuilder.newUsecase;
-import static org.qi4j.library.conversion.values.TestModel.createBirthDate;
-import static org.qi4j.library.conversion.values.TestModel.createPerson;
-
-/**
- * ValueToEntity Service Test.
- */
-public class ValueToEntityTest
-    extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // START SNIPPET: assembly
-        new ValueToEntityAssembler().assemble( module );
-        // END SNIPPET: assembly
-        new EntityTestAssembler().assemble( module );
-        module.entities( PersonEntity.class );
-        module.values( PersonValue.class );
-        module.values( PersonValue2.class );
-        module.values( PersonValue3.class );
-        module.values( PersonValue4.class );
-    }
-
-    private Date someBirthDate;
-    private String ednaIdentity;
-    private String zekeIdentity;
-    private String fredIdentity;
-
-    @Before
-    public void setupInitialData()
-        throws UnitOfWorkCompletionException
-    {
-        // See http://en.wikipedia.org/wiki/Template:Flintstones_family_tree
-        someBirthDate = createBirthDate( 1, 1, 1 );
-        try( UnitOfWork uow = module.newUnitOfWork( newUsecase( "InitialData" ) ) )
-        {
-            ednaIdentity = createPerson( uow, "Edna", "Flintstone", someBirthDate ).identity().get();
-            zekeIdentity = createPerson( uow, "Zeke", "Flintstone", someBirthDate ).identity().get();
-            fredIdentity = createPerson( uow, "Fred", "Flintstone", someBirthDate ).identity().get();
-            uow.complete();
-        }
-    }
-
-    @Test
-    public void givenQualifiedValueWhenCreatingEntityExpectCorrectEntity()
-        throws UnitOfWorkCompletionException
-    {
-        ValueBuilder<PersonValue> builder = module.newValueBuilder( PersonValue.class );
-        builder.prototype().firstName().set( "Ed" );
-        builder.prototype().lastName().set( "Flintstone" );
-        builder.prototype().dateOfBirth().set( someBirthDate );
-        builder.prototype().spouse().set( ednaIdentity );
-        builder.prototype().children().set( Arrays.asList( zekeIdentity, fredIdentity ) );
-        PersonValue edValue = builder.newInstance();
-        try( UnitOfWork uow = module.newUnitOfWork( newUsecase( "CreatingEntityFromQualifiedValue" ) ) )
-        {
-            // START SNIPPET: creation
-            ValueToEntity conversion = module.findService( ValueToEntity.class ).get();
-            PersonEntity edEntity = conversion.create( PersonEntity.class, edValue );
-            // END SNIPPET: creation
-            assertThat( edEntity.firstName(), equalTo( "Ed" ) );
-            assertThat( edEntity.lastName(), equalTo( "Flintstone" ) );
-            assertThat( edEntity.spouse().get().firstName(), equalTo( "Edna" ) );
-            assertThat( Iterables.count( Iterables.filter( new Specification<PersonEntity>()
-            {
-                @Override
-                public boolean satisfiedBy( PersonEntity child )
-                {
-                    return "Zeke".equals( child.firstName() ) || "Fred".equals( child.firstName() );
-                }
-            }, edEntity.children() ) ), is( 2L ) );
-
-            uow.complete();
-        }
-    }
-
-    @Test
-    public void givenUnqualifiedValueWhenCreatingEntityExpectCorrectEntity()
-        throws UnitOfWorkCompletionException
-    {
-        ValueBuilder<PersonValue2> builder = module.newValueBuilder( PersonValue2.class );
-        builder.prototype().firstName().set( "Ed" );
-        builder.prototype().lastName().set( "Flintstone" );
-        builder.prototype().dateOfBirth().set( someBirthDate );
-        builder.prototype().spouse().set( ednaIdentity );
-        builder.prototype().children().set( Arrays.asList( zekeIdentity, fredIdentity ) );
-        PersonValue2 edValue = builder.newInstance();
-        try( UnitOfWork uow = module.newUnitOfWork( newUsecase( "CreatingEntityFromUnqualifiedValue" ) ) )
-        {
-            ValueToEntity conversion = module.findService( ValueToEntity.class ).get();
-
-            PersonEntity edEntity = conversion.create( PersonEntity.class, "id:Ed", edValue );
-
-            assertThat( edEntity.identity().get(), equalTo( "id:Ed" ) );
-            assertThat( edEntity.firstName(), equalTo( "Ed" ) );
-            assertThat( edEntity.lastName(), equalTo( "Flintstone" ) );
-            assertThat( edEntity.spouse().get().firstName(), equalTo( "Edna" ) );
-            assertThat( Iterables.count( Iterables.filter( new Specification<PersonEntity>()
-            {
-                @Override
-                public boolean satisfiedBy( PersonEntity child )
-                {
-                    return "Zeke".equals( child.firstName() ) || "Fred".equals( child.firstName() );
-                }
-            }, edEntity.children() ) ), is( 2L ) );
-
-            uow.complete();
-        }
-    }
-
-    @Test
-    public void givenUnqualifiedValue2WhenCreatingEntityExpectCorrectEntity()
-        throws UnitOfWorkCompletionException
-    {
-        ValueBuilder<PersonValue3> builder = module.newValueBuilder( PersonValue3.class );
-        builder.prototype().firstName().set( "Ed" );
-        builder.prototype().lastName().set( "Flintstone" );
-        builder.prototype().dateOfBirth().set( someBirthDate );
-        builder.prototype().spouse().set( ednaIdentity );
-        builder.prototype().children().set( Arrays.asList( zekeIdentity, fredIdentity ) );
-        PersonValue3 edValue = builder.newInstance();
-        try( UnitOfWork uow = module.newUnitOfWork( newUsecase( "CreatingEntityFromUnqualifiedValue" ) ) )
-        {
-            ValueToEntity conversion = module.findService( ValueToEntity.class ).get();
-
-            PersonEntity edEntity = conversion.create( PersonEntity.class, "id:Ed", edValue );
-
-            assertThat( edEntity.identity().get(), equalTo( "id:Ed" ) );
-            assertThat( edEntity.firstName(), equalTo( "Ed" ) );
-            assertThat( edEntity.lastName(), equalTo( "Flintstone" ) );
-            assertThat( edEntity.spouse().get().firstName(), equalTo( "Edna" ) );
-            assertThat( Iterables.count( Iterables.filter( new Specification<PersonEntity>()
-            {
-                @Override
-                public boolean satisfiedBy( PersonEntity child )
-                {
-                    return "Zeke".equals( child.firstName() ) || "Fred".equals( child.firstName() );
-                }
-            }, edEntity.children() ) ), is( 2L ) );
-
-            uow.complete();
-        }
-    }
-
-    @Test( expected = ConstraintViolationException.class )
-    public void givenQualifiedValueNotFromSameInterfaceWhenCreatingEntityExpectNonOptionalException()
-        throws UnitOfWorkCompletionException
-    {
-        ValueBuilder<PersonValue4> builder = module.newValueBuilder( PersonValue4.class );
-        builder.prototype().firstName().set( "Ed" );
-        builder.prototype().lastName().set( "Flintstone" );
-        builder.prototype().dateOfBirth().set( someBirthDate );
-        builder.prototype().spouse().set( ednaIdentity );
-        builder.prototype().children().set( Arrays.asList( zekeIdentity, fredIdentity ) );
-        PersonValue4 edValue = builder.newInstance();
-        try( UnitOfWork uow = module.newUnitOfWork( newUsecase( "CreatingEntityFromUnqualifiedValue" ) ) )
-        {
-            ValueToEntity conversion = module.findService( ValueToEntity.class ).get();
-
-            PersonEntity edEntity = conversion.create( PersonEntity.class, "id:Ed", edValue );
-
-            uow.complete();
-        }
-
-    }
-
-    @Test
-    public void givenQualifiedValueWhenUpdatingEntityExpectCorrectEntity()
-        throws UnitOfWorkCompletionException
-    {
-        String rickyIdentity;
-        try( UnitOfWork uow = module.newUnitOfWork( newUsecase( "CreateRickySlaghoopleWithTypo" ) ) )
-        {
-            PersonEntity ricky = createPerson( uow, "Ricky", "Slaghople", someBirthDate );
-            ricky.spouse().set( uow.get( PersonEntity.class, ednaIdentity ) );
-            ricky.children().add( uow.get( PersonEntity.class, zekeIdentity ) );
-            rickyIdentity = ricky.identity().get();
-            assertThat( ricky.spouse().get(), notNullValue() );
-            assertThat( ricky.children().count(), is( 1 ) );
-            uow.complete();
-        }
-        ValueBuilder<PersonValue> builder = module.newValueBuilder( PersonValue.class );
-        builder.prototype().firstName().set( "Ricky" );
-        builder.prototype().lastName().set( "Slaghoople" );
-        builder.prototype().dateOfBirth().set( someBirthDate );
-        PersonValue rickyNewStateValue = builder.newInstance();
-        try( UnitOfWork uow = module.newUnitOfWork( newUsecase( "UpdateRickySlaghoople" ) ) )
-        {
-            PersonEntity rickyEntity = uow.get( PersonEntity.class, rickyIdentity );
-            // START SNIPPET: update
-            ValueToEntity conversion = module.findService( ValueToEntity.class ).get();
-            conversion.update( rickyEntity, rickyNewStateValue );
-            // END SNIPPET: update
-
-            assertThat( rickyEntity.lastName(), equalTo( "Slaghoople" ) );
-            assertThat( rickyEntity.spouse().get(), nullValue() );
-            assertThat( rickyEntity.children().count(), is( 0 ) );
-
-            uow.complete();
-        }
-    }
-
-    @Test
-    public void givenUnqualifiedValueWhenUpdatingEntityExpectCorrectEntity()
-        throws UnitOfWorkCompletionException
-    {
-        String rickyIdentity;
-        try( UnitOfWork uow = module.newUnitOfWork( newUsecase( "CreateRickySlaghoopleWithTypo" ) ) )
-        {
-            PersonEntity ricky = createPerson( uow, "Ricky", "Slaghople", someBirthDate );
-            ricky.spouse().set( uow.get( PersonEntity.class, ednaIdentity ) );
-            ricky.children().add( uow.get( PersonEntity.class, zekeIdentity ) );
-            rickyIdentity = ricky.identity().get();
-            assertThat( ricky.spouse().get(), notNullValue() );
-            assertThat( ricky.children().count(), is( 1 ) );
-            uow.complete();
-        }
-        ValueBuilder<PersonValue2> builder = module.newValueBuilder( PersonValue2.class );
-        builder.prototype().firstName().set( "Ricky" );
-        builder.prototype().lastName().set( "Slaghoople" );
-        builder.prototype().dateOfBirth().set( someBirthDate );
-        PersonValue2 newStateValue = builder.newInstance();
-        try( UnitOfWork uow = module.newUnitOfWork( newUsecase( "UpdateRickySlaghoople" ) ) )
-        {
-            PersonEntity ricky = uow.get( PersonEntity.class, rickyIdentity );
-
-            ValueToEntity conversion = module.findService( ValueToEntity.class ).get();
-            conversion.update( ricky, newStateValue );
-
-            assertThat( ricky.lastName(), equalTo( "Slaghoople" ) );
-            assertThat( ricky.spouse().get(), nullValue() );
-            assertThat( ricky.children().count(), is( 0 ) );
-
-            uow.complete();
-        }
-    }
-
-    @Test
-    public void givenUnqualifiedValue2WhenUpdatingEntityExpectCorrectEntity()
-        throws UnitOfWorkCompletionException
-    {
-        String rickyIdentity;
-        try( UnitOfWork uow = module.newUnitOfWork( newUsecase( "CreateRickySlaghoopleWithTypo" ) ) )
-        {
-            PersonEntity ricky = createPerson( uow, "Ricky", "Slaghople", someBirthDate );
-            ricky.spouse().set( uow.get( PersonEntity.class, ednaIdentity ) );
-            ricky.children().add( uow.get( PersonEntity.class, zekeIdentity ) );
-            rickyIdentity = ricky.identity().get();
-            assertThat( ricky.spouse().get(), notNullValue() );
-            assertThat( ricky.children().count(), is( 1 ) );
-            uow.complete();
-        }
-        ValueBuilder<PersonValue3> builder = module.newValueBuilder( PersonValue3.class );
-        builder.prototype().firstName().set( "Ricky" );
-        builder.prototype().lastName().set( "Slaghoople" );
-        builder.prototype().dateOfBirth().set( someBirthDate );
-        PersonValue3 newStateValue = builder.newInstance();
-        try( UnitOfWork uow = module.newUnitOfWork( newUsecase( "UpdateRickySlaghoople" ) ) )
-        {
-            PersonEntity ricky = uow.get( PersonEntity.class, rickyIdentity );
-
-            ValueToEntity conversion = module.findService( ValueToEntity.class ).get();
-            conversion.update( ricky, newStateValue );
-
-            assertThat( ricky.lastName(), equalTo( "Slaghoople" ) );
-            assertThat( ricky.spouse().get(), nullValue() );
-            assertThat( ricky.children().count(), is( 0 ) );
-
-            uow.complete();
-        }
-    }
-
-    @Test
-    public void givenQualifiedValueNotFromSameInterfaceWhenUpdatingEntityExpectPropsNotUpdated()
-        throws UnitOfWorkCompletionException
-    {
-        String rickyIdentity;
-        try( UnitOfWork uow = module.newUnitOfWork( newUsecase( "CreateRickySlaghoopleWithTypo" ) ) )
-        {
-            PersonEntity ricky = createPerson( uow, "Ricky", "Slaghople", someBirthDate );
-            ricky.spouse().set( uow.get( PersonEntity.class, ednaIdentity ) );
-            ricky.children().add( uow.get( PersonEntity.class, zekeIdentity ) );
-            rickyIdentity = ricky.identity().get();
-            assertThat( ricky.spouse().get(), notNullValue() );
-            assertThat( ricky.children().count(), is( 1 ) );
-            uow.complete();
-        }
-        ValueBuilder<PersonValue4> builder = module.newValueBuilder( PersonValue4.class );
-        builder.prototype().firstName().set( "Ricky" );
-        builder.prototype().lastName().set( "Slaghoople" );
-        builder.prototype().dateOfBirth().set( someBirthDate );
-        PersonValue4 newStateValue = builder.newInstance();
-        try( UnitOfWork uow = module.newUnitOfWork( newUsecase( "UpdateRickySlaghoopleWontWork" ) ) )
-        {
-            PersonEntity ricky = uow.get( PersonEntity.class, rickyIdentity );
-
-            ValueToEntity conversion = module.findService( ValueToEntity.class ).get();
-            conversion.update( ricky, newStateValue );
-
-            assertThat( ricky.lastName(), equalTo( "Slaghople" ) );
-            assertThat( ricky.spouse().get(), nullValue() );
-            assertThat( ricky.children().count(), is( 0 ) );
-
-            uow.complete();
-        }
-    }
-}
diff --git a/libraries/eventsourcing-jdbm/build.gradle b/libraries/eventsourcing-jdbm/build.gradle
deleted file mode 100644
index f5d0f25..0000000
--- a/libraries/eventsourcing-jdbm/build.gradle
+++ /dev/null
@@ -1,35 +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.
- */
-
-description = "Extension to the Apache Zest™ Event Sourcing Library for providing a JDBM based event store."
-
-jar { manifest { name = "Apache Zest™ Library - Event Sourcing - JDBM" }}
-
-dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile(project(":org.qi4j.libraries:org.qi4j.library.eventsourcing"))
-  compile(project(":org.qi4j.libraries:org.qi4j.library.fileconfig"))
-  compile(libraries.jdbm)
-
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-  testCompile project( ':org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson' )
-
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
diff --git a/libraries/eventsourcing-jdbm/dev-status.xml b/libraries/eventsourcing-jdbm/dev-status.xml
deleted file mode 100644
index 5adebd7..0000000
--- a/libraries/eventsourcing-jdbm/dev-status.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
-  <status>
-    <!--none,early,beta,stable,mature-->
-    <codebase>beta</codebase>
-
-    <!-- none, brief, good, complete -->
-    <documentation>brief</documentation>
-
-    <!-- none, some, good, complete -->
-    <unittests>some</unittests>
-  </status>
-  <licenses>
-    <license>ALv2</license>
-  </licenses>
-</module>
diff --git a/libraries/eventsourcing-jdbm/src/main/java/org/qi4j/library/eventsourcing/domain/source/jdbm/JdbmEventStoreService.java b/libraries/eventsourcing-jdbm/src/main/java/org/qi4j/library/eventsourcing/domain/source/jdbm/JdbmEventStoreService.java
deleted file mode 100644
index 4448210..0000000
--- a/libraries/eventsourcing-jdbm/src/main/java/org/qi4j/library/eventsourcing/domain/source/jdbm/JdbmEventStoreService.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source.jdbm;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.util.Properties;
-import jdbm.RecordManager;
-import jdbm.RecordManagerFactory;
-import jdbm.RecordManagerOptions;
-import jdbm.Serializer;
-import jdbm.btree.BTree;
-import jdbm.helper.ByteArrayComparator;
-import jdbm.helper.DefaultSerializer;
-import jdbm.helper.Tuple;
-import jdbm.helper.TupleBrowser;
-import jdbm.recman.CacheRecordManager;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.qualifier.Tagged;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.functional.Function;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.io.Transforms;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-import org.qi4j.library.eventsourcing.domain.source.AbstractEventStoreMixin;
-import org.qi4j.library.eventsourcing.domain.source.EventManagement;
-import org.qi4j.library.eventsourcing.domain.source.EventSource;
-import org.qi4j.library.eventsourcing.domain.source.EventStore;
-import org.qi4j.library.eventsourcing.domain.source.EventStoreActivation;
-import org.qi4j.library.eventsourcing.domain.source.EventStream;
-import org.qi4j.library.fileconfig.FileConfiguration;
-
-/**
- * JAVADOC
- */
-@Mixins( JdbmEventStoreService.JdbmEventStoreMixin.class )
-@Activators( EventStoreActivation.Activator.class )
-public interface JdbmEventStoreService
-    extends EventSource, EventStore, EventStream, EventManagement, EventStoreActivation, ServiceComposite
-{
-
-    class JdbmEventStoreMixin
-        extends AbstractEventStoreMixin
-        implements EventManagement, EventSource
-    {
-        @Service
-        private FileConfiguration fileConfig;
-
-        @Service
-        @Tagged( ValueSerialization.Formats.JSON )
-        private ValueSerialization valueSerialization;
-
-        private RecordManager recordManager;
-        private BTree index;
-        private Serializer serializer;
-        private File dataFile;
-
-        private long currentCount;
-
-        @Override
-        public void activateEventStore()
-            throws Exception
-        {
-            super.activateEventStore();
-            dataFile = new File( fileConfig.dataDirectory(), identity.identity() + "/events" );
-            File directory = dataFile.getAbsoluteFile().getParentFile();
-            directory.mkdirs();
-            String name = dataFile.getAbsolutePath();
-            Properties properties = new Properties();
-            properties.put( RecordManagerOptions.AUTO_COMMIT, "false" );
-            properties.put( RecordManagerOptions.DISABLE_TRANSACTIONS, "false" );
-            initialize( name, properties );
-        }
-
-        @Override
-        public void passivateEventStore()
-                throws Exception
-        {
-            super.passivateEventStore();
-            recordManager.close();
-        }
-
-        @Override
-        public Output<String, IOException> restore()
-        {
-            // Commit every 1000 events, convert from string to value, and then store. Put a lock around the whole thing
-            Output<String, IOException> map = Transforms.map( new Transforms.ProgressLog<String>( 1000 )
-            {
-                @Override
-                protected void logProgress()
-                {
-                    try
-                    {
-                        recordManager.commit(); // Commit every 1000 transactions to avoid OutOfMemory issues
-                    }
-                    catch( IOException e )
-                    {
-                        throw new IllegalStateException( "Could not commit data", e );
-                    }
-                }
-            }, Transforms.map( new Function<String, UnitOfWorkDomainEventsValue>()
-            {
-                @Override
-                public UnitOfWorkDomainEventsValue map( String item )
-                {
-                    return valueSerialization.<UnitOfWorkDomainEventsValue>deserialize( eventsType, item );
-                }
-            }, storeEvents0() ) );
-
-            return Transforms.lock( JdbmEventStoreMixin.this.lock,
-                                    map );
-        }
-
-        // EventStore implementation
-        @Override
-        public Input<UnitOfWorkDomainEventsValue, IOException> events( final long offset, long limit )
-        {
-            return new Input<UnitOfWorkDomainEventsValue, IOException>()
-            {
-                @Override
-                public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super UnitOfWorkDomainEventsValue, ReceiverThrowableType> output )
-                    throws IOException, ReceiverThrowableType
-                {
-                    output.receiveFrom( new Sender<UnitOfWorkDomainEventsValue, IOException>()
-                    {
-                        @Override
-                        public <ReceiverThrowableType extends Throwable> void sendTo( Receiver<? super UnitOfWorkDomainEventsValue, ReceiverThrowableType> receiver )
-                            throws ReceiverThrowableType, IOException
-                        {
-                            // Lock datastore first
-                            lock();
-
-                            try
-                            {
-                                final TupleBrowser browser = index.browse( offset + 1 );
-
-                                Tuple tuple = new Tuple();
-
-                                while( browser.getNext( tuple ) )
-                                {
-                                    // Get next transaction
-                                    UnitOfWorkDomainEventsValue domainEvents = readTransactionEvents( tuple );
-
-                                    receiver.receive( domainEvents );
-                                }
-                            }
-                            catch( Exception e )
-                            {
-                                logger.warn( "Could not iterate events", e );
-                            }
-                            finally
-                            {
-                                lock.unlock();
-                            }
-                        }
-                    } );
-                }
-            };
-        }
-
-        @Override
-        public long count()
-        {
-            return currentCount;
-        }
-
-        @Override
-        protected Output<UnitOfWorkDomainEventsValue, IOException> storeEvents0()
-        {
-            return new Output<UnitOfWorkDomainEventsValue, IOException>()
-            {
-                @Override
-                public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends UnitOfWorkDomainEventsValue, SenderThrowableType> sender )
-                    throws IOException, SenderThrowableType
-                {
-                    try
-                    {
-                        sender.sendTo( new Receiver<UnitOfWorkDomainEventsValue, IOException>()
-                        {
-                            @Override
-                            public void receive( UnitOfWorkDomainEventsValue item )
-                                throws IOException
-                            {
-                                String jsonString = valueSerialization.serialize( item );
-                                currentCount++;
-                                index.insert( currentCount, jsonString.getBytes( "UTF-8" ), false );
-                            }
-                        } );
-                        recordManager.commit();
-                    }
-                    catch( IOException e )
-                    {
-                        recordManager.rollback();
-                        throw e;
-                    }
-                    catch( Throwable e )
-                    {
-                        recordManager.rollback();
-                        throw (SenderThrowableType) e;
-                    }
-                }
-            };
-        }
-
-        private void initialize( String name, Properties properties )
-            throws IOException
-        {
-            recordManager = RecordManagerFactory.createRecordManager( name, properties );
-            serializer = DefaultSerializer.INSTANCE;
-            recordManager = new CacheRecordManager( recordManager, 1000, false );
-            long recid = recordManager.getNamedObject( "index" );
-            if( recid != 0 )
-            {
-                index = BTree.load( recordManager, recid );
-                currentCount = index.size();
-            }
-            else
-            {
-                ByteArrayComparator comparator = new ByteArrayComparator();
-                index = BTree.createInstance( recordManager, comparator, serializer, DefaultSerializer.INSTANCE, 16 );
-                recordManager.setNamedObject( "index", index.getRecid() );
-                currentCount = 0;
-            }
-            recordManager.commit();
-        }
-
-        private UnitOfWorkDomainEventsValue readTransactionEvents( Tuple tuple )
-            throws UnsupportedEncodingException
-        {
-            byte[] eventData = (byte[]) tuple.getValue();
-            String eventJson = new String( eventData, "UTF-8" );
-            return valueSerialization.<UnitOfWorkDomainEventsValue>deserialize( eventsType, eventJson );
-        }
-    }
-}
diff --git a/libraries/eventsourcing-jdbm/src/main/java/org/qi4j/library/eventsourcing/domain/source/jdbm/package.html b/libraries/eventsourcing-jdbm/src/main/java/org/qi4j/library/eventsourcing/domain/source/jdbm/package.html
deleted file mode 100644
index 4951f57..0000000
--- a/libraries/eventsourcing-jdbm/src/main/java/org/qi4j/library/eventsourcing/domain/source/jdbm/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>JDBM EventStore.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/eventsourcing-jdbm/src/test/java/org/qi4j/library/eventsourcing/domain/source/jdbm/JdbmEventStoreServiceTest.java b/libraries/eventsourcing-jdbm/src/test/java/org/qi4j/library/eventsourcing/domain/source/jdbm/JdbmEventStoreServiceTest.java
deleted file mode 100644
index 0068c5f..0000000
--- a/libraries/eventsourcing-jdbm/src/test/java/org/qi4j/library/eventsourcing/domain/source/jdbm/JdbmEventStoreServiceTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source.jdbm;
-
-import java.io.IOException;
-import java.security.Principal;
-import org.junit.Test;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ImportedServiceDeclaration;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Function;
-import org.qi4j.io.Outputs;
-import org.qi4j.io.Transforms;
-import org.qi4j.library.eventsourcing.domain.api.DomainEvent;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-import org.qi4j.library.eventsourcing.domain.factory.CurrentUserUoWPrincipal;
-import org.qi4j.library.eventsourcing.domain.factory.DomainEventCreationConcern;
-import org.qi4j.library.eventsourcing.domain.factory.DomainEventFactoryService;
-import org.qi4j.library.eventsourcing.domain.source.EventSource;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class JdbmEventStoreServiceTest
-        extends AbstractQi4jTest
-    {
-        @Override
-        public void assemble( ModuleAssembly module ) throws AssemblyException
-        {
-            module.layer().application().setName( "JDBMEventStoreTest" );
-
-            new EntityTestAssembler(  ).assemble( module );
-
-            module.values( DomainEventValue.class, UnitOfWorkDomainEventsValue.class );
-            module.services( FileConfigurationService.class );
-            new OrgJsonValueSerializationAssembler().assemble( module );
-            module.services( JdbmEventStoreService.class );
-            module.services( DomainEventFactoryService.class );
-            module.importedServices( CurrentUserUoWPrincipal.class ).importedBy( ImportedServiceDeclaration.NEW_OBJECT );
-            module.objects( CurrentUserUoWPrincipal.class );
-
-            module.entities( TestEntity.class ).withConcerns(DomainEventCreationConcern.class);
-        }
-
-        @Test
-        public void testDomainEvent() throws UnitOfWorkCompletionException, IOException
-        {
-            UnitOfWork uow = module.newUnitOfWork( UsecaseBuilder.newUsecase( "Create entity" ));
-            TestEntity entity = uow.newEntity( TestEntity.class );
-            uow.complete();
-
-            int count = 10;
-            for (int i = 0; i < count; i++)
-            {
-                uow = module.newUnitOfWork( UsecaseBuilder.newUsecase( "Change description" ));
-                uow.setMetaInfo( new Principal()
-                {
-                    public String getName()
-                    {
-                        return "administrator";
-                    }
-                });
-
-                entity = uow.get( entity );
-                entity.changeDescription( "New description" );
-                uow.complete();
-            }
-
-            EventSource source = (EventSource) module.findService( EventSource.class ).get();
-
-            source.events( 0, Long.MAX_VALUE ).transferTo( Transforms.map( new Function<UnitOfWorkDomainEventsValue, String>()
-                    {
-                        public String map( UnitOfWorkDomainEventsValue unitOfWorkDomainEventsValue )
-                        {
-                            return unitOfWorkDomainEventsValue.toString();
-                        }
-                    }, Outputs.systemOut() ));
-        }
-
-        @Mixins( TestEntity.Mixin.class )
-        public interface TestEntity
-            extends EntityComposite
-        {
-            @UseDefaults
-            Property<String> description();
-
-            @DomainEvent
-            void changeDescription(String newName);
-
-            abstract class Mixin
-                implements TestEntity
-            {
-                public void changeDescription( String newName )
-                {
-                    description().set( newName );
-                }
-            }
-        }
-    }
diff --git a/libraries/eventsourcing-rest/build.gradle b/libraries/eventsourcing-rest/build.gradle
deleted file mode 100644
index ea1286a..0000000
--- a/libraries/eventsourcing-rest/build.gradle
+++ /dev/null
@@ -1,33 +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.
- */
-
-description = "Apache Zest™ Event Sourcing Library for Restful applications."
-
-jar { manifest { name = "Apache Zest™ Library - Event Sourcing - Rest" }}
-
-dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile(project(":org.qi4j.libraries:org.qi4j.library.eventsourcing"))
-  compile(libraries.restlet)
-
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
diff --git a/libraries/eventsourcing-rest/dev-status.xml b/libraries/eventsourcing-rest/dev-status.xml
deleted file mode 100644
index 5adebd7..0000000
--- a/libraries/eventsourcing-rest/dev-status.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
-  <status>
-    <!--none,early,beta,stable,mature-->
-    <codebase>beta</codebase>
-
-    <!-- none, brief, good, complete -->
-    <documentation>brief</documentation>
-
-    <!-- none, some, good, complete -->
-    <unittests>some</unittests>
-  </status>
-  <licenses>
-    <license>ALv2</license>
-  </licenses>
-</module>
diff --git a/libraries/eventsourcing-rest/src/main/java/org/qi4j/library/eventsourcing/domain/rest/server/DomainEventSourceResource.java b/libraries/eventsourcing-rest/src/main/java/org/qi4j/library/eventsourcing/domain/rest/server/DomainEventSourceResource.java
deleted file mode 100644
index dc63336..0000000
--- a/libraries/eventsourcing-rest/src/main/java/org/qi4j/library/eventsourcing/domain/rest/server/DomainEventSourceResource.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.rest.server;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.service.qualifier.Tagged;
-import org.qi4j.functional.Iterables;
-import org.qi4j.io.Outputs;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-import org.qi4j.library.eventsourcing.domain.source.EventSource;
-import org.restlet.Request;
-import org.restlet.Response;
-import org.restlet.Restlet;
-import org.restlet.data.CharacterSet;
-import org.restlet.data.MediaType;
-import org.restlet.data.Reference;
-import org.restlet.data.Status;
-import org.restlet.ext.atom.*;
-import org.restlet.representation.StringRepresentation;
-import org.restlet.representation.WriterRepresentation;
-import org.restlet.resource.ResourceException;
-
-import static org.qi4j.functional.Iterables.iterable;
-
-/**
- * Get events in various formats.
- * <p>
- * The feed is paged, with one
- * current set page, one working set page, and the rest being archive pages that never change. The links "next", "previous",
- * "first" and "last" are used as expected per the Atom spec.
- * </p>
- * <pre><code>
- * / = current set of most recent events (event range: count-pagesize to count)
- * /n,m = events from index n to index m. These are archive pages.
- * /n = working set page, where n is the first event index to be presented
- * </code></pre>
- */
-public class DomainEventSourceResource
-        extends Restlet
-{
-    EventSource source;
-
-    public DomainEventSourceResource( @Service @Tagged("domain") EventSource source )
-    {
-        this.source = source;
-    }
-
-    @Override
-    public void handle( Request request, Response response )
-    {
-        long eventCount = source.count();
-        long pageSize = 10;
-        long startEvent = -1;
-        long endEvent = -1;
-        long limit = pageSize;
-
-        final List<UnitOfWorkDomainEventsValue> eventsValues = new ArrayList<UnitOfWorkDomainEventsValue>();
-
-        final Feed feed = new Feed();
-        feed.setBaseReference( request.getResourceRef().getParentRef() );
-        List<Link> links = feed.getLinks();
-
-        String remainingPart = request.getResourceRef().getRemainingPart();
-        if (remainingPart.equals( "/" ))
-        {
-            // Current set - always contains the last "pageSize" events
-            startEvent = Math.max( 0, eventCount - pageSize - 1 );
-
-            feed.setTitle( new Text( "Current set" ) );
-
-            if (startEvent > 0)
-            {
-                long previousStart = Math.max(0, startEvent-pageSize);
-                long previousEnd = startEvent-1;
-
-                Link link = new Link( new Reference( previousStart+","+previousEnd ), new Relation( "previous" ), MediaType.APPLICATION_ATOM );
-                link.setTitle( "Previous page" );
-                links.add( link );
-            }
-
-        } else
-        {
-            // Archive
-            String[] indices = remainingPart.substring(1).split( "," );
-
-            if (indices.length == 1)
-            {
-                // Working set
-                startEvent = Long.parseLong( indices[0] );
-                endEvent = startEvent + pageSize - 1;
-                limit = pageSize;
-                feed.setTitle( new Text("Working set") );
-            } else if (indices.length == 2)
-            {
-                feed.setTitle( new Text("Archive page") );
-                startEvent = Long.parseLong( indices[0] );
-                endEvent = Long.parseLong( indices[1] );
-                limit = 1+endEvent-startEvent;
-
-            } else
-                throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
-
-            if (startEvent > 0)
-            {
-                long previousStart = Math.max(0, startEvent-pageSize);
-                long previousEnd = startEvent-1;
-
-                Link link = new Link( new Reference( previousStart+","+previousEnd ), new Relation( "previous" ), MediaType.APPLICATION_ATOM );
-                link.setTitle( "Previous page" );
-                links.add( link );
-            }
-
-            long nextStart = endEvent+1;
-            long nextEnd = nextStart+pageSize-1;
-
-            if (nextStart < eventCount)
-                if (nextEnd >= eventCount)
-                {
-                    Link next = new Link( new Reference( nextStart+"" ), new Relation( "next" ), MediaType.APPLICATION_ATOM );
-                    next.setTitle( "Working set" );
-                    links.add( next );
-                } else
-                {
-                    Link next = new Link( new Reference( nextStart+","+nextEnd ), new Relation( "next" ), MediaType.APPLICATION_ATOM );
-                    next.setTitle( "Next page" );
-                    links.add( next );
-                }
-        }
-
-        try
-        {
-            source.events( startEvent, limit ).transferTo( Outputs.collection( eventsValues ) );
-        } catch (Throwable throwable)
-        {
-            throw new ResourceException( Status.SERVER_ERROR_INTERNAL, throwable );
-        }
-
-        Link last = new Link( new Reference( "0,"+(pageSize-1) ), new Relation( "last" ), MediaType.APPLICATION_ATOM );
-        last.setTitle( "Last archive page" );
-        links.add( last );
-
-        Link first = new Link( new Reference( "." ), new Relation( "first" ), MediaType.APPLICATION_ATOM );
-        first.setTitle( "Current set" );
-        links.add( first );
-
-/*
-        if (previousPage != -1)
-        {
-            Link link = new Link( new Reference( ""+previousPage ), new Relation( "prev-archive" ), MediaType.APPLICATION_ATOM );
-            link.setTitle( "Previous archive page" );
-            links.add( link );
-        }
-        if (nextPage != -1)
-        {
-            Link link = new Link( new Reference( "" + nextPage ), new Relation( "next-archive" ), MediaType.APPLICATION_ATOM );
-            link.setTitle( "Next archive page" );
-            links.add( link );
-        }
-        else if (startEvent != workingSetOffset)
-        {
-            Link next = new Link( new Reference( "" ), new Relation( "next" ), MediaType.APPLICATION_ATOM );
-            next.setTitle( "Next page" );
-            links.add( next );
-        }
-*/
-
-        Date lastModified = null;
-        for (UnitOfWorkDomainEventsValue eventsValue : eventsValues)
-        {
-            Entry entry = new Entry();
-            entry.setTitle( new Text( eventsValue.usecase().get() + "(" + eventsValue.user().get() + ")" ) );
-            entry.setPublished( new Date( eventsValue.timestamp().get() ) );
-            entry.setModificationDate( lastModified = new Date( eventsValue.timestamp().get() ) );
-            entry.setId( Long.toString( startEvent + 1 ) );
-            startEvent++;
-            Content content = new Content();
-            content.setInlineContent( new StringRepresentation( eventsValue.toString(), MediaType.APPLICATION_JSON ) );
-            entry.setContent( content );
-            feed.getEntries().add( entry );
-        }
-
-        feed.setModificationDate( lastModified );
-
-        MediaType mediaType = request.getClientInfo().getPreferredMediaType( Iterables.toList( iterable( MediaType.TEXT_HTML, MediaType.APPLICATION_ATOM ) ));
-
-        if (MediaType.APPLICATION_ATOM.equals( mediaType ))
-        {
-            WriterRepresentation representation = new WriterRepresentation( MediaType.APPLICATION_ATOM )
-            {
-                @Override
-                public void write( final Writer writer ) throws IOException
-                {
-                    feed.write( writer );
-                }
-            };
-            representation.setCharacterSet( CharacterSet.UTF_8 );
-            response.setEntity( representation );
-        } else
-        {
-            WriterRepresentation representation = new WriterRepresentation(MediaType.TEXT_HTML)
-            {
-                @Override
-                public void write( Writer writer ) throws IOException
-                {
-                    writer.append( "<html><head><title>Events</title></head><body>" );
-
-                    for( Link link : feed.getLinks() )
-                    {
-                        writer.append( "<a href=\"").append( link.getHref().getPath()).append( "\">" );
-                        writer.append( link.getTitle() );
-                        writer.append( "</a><br/>" );
-                    }
-
-                    writer.append( "<ol>" );
-                    for( Entry entry : feed.getEntries() )
-                    {
-                        writer.append( "<li>" ).append( entry.getTitle().toString() ).append( "</li>" );
-                    }
-                    writer.append( "</ol></body>" );
-                }
-            };
-            representation.setCharacterSet( CharacterSet.UTF_8 );
-            response.setEntity( representation );
-        }
-
-/*
-        } else
-        {
-            throw new ResourceException( Status.CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE );
-        }
-*/
-    }
-}
diff --git a/libraries/eventsourcing-rest/src/main/java/org/qi4j/library/eventsourcing/domain/rest/server/package.html b/libraries/eventsourcing-rest/src/main/java/org/qi4j/library/eventsourcing/domain/rest/server/package.html
deleted file mode 100644
index 10862c4..0000000
--- a/libraries/eventsourcing-rest/src/main/java/org/qi4j/library/eventsourcing/domain/rest/server/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Restlet Resource exposing EventSourcing Events as Atom.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/eventsourcing-rest/src/test/java/org/qi4j/library/eventsourcing/domain/rest/server/DomainEventSourceResourceSample.java b/libraries/eventsourcing-rest/src/test/java/org/qi4j/library/eventsourcing/domain/rest/server/DomainEventSourceResourceSample.java
deleted file mode 100644
index d74c295..0000000
--- a/libraries/eventsourcing-rest/src/test/java/org/qi4j/library/eventsourcing/domain/rest/server/DomainEventSourceResourceSample.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.rest.server;
-
-import org.junit.Ignore;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ImportedServiceDeclaration;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.library.eventsourcing.domain.api.DomainEvent;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-import org.qi4j.library.eventsourcing.domain.factory.CurrentUserUoWPrincipal;
-import org.qi4j.library.eventsourcing.domain.factory.DomainEventCreationConcern;
-import org.qi4j.library.eventsourcing.domain.factory.DomainEventFactoryService;
-import org.qi4j.library.eventsourcing.domain.source.EventSource;
-import org.qi4j.library.eventsourcing.domain.source.memory.MemoryEventStoreService;
-import org.qi4j.test.EntityTestAssembler;
-import org.restlet.*;
-import org.restlet.data.Protocol;
-import org.restlet.data.Status;
-import org.restlet.representation.StringRepresentation;
-import org.restlet.resource.ResourceException;
-
-import java.security.Principal;
-
-/**
- * Start simple web server that exposes the Restlet resource. Test through browser.
- */
-public class DomainEventSourceResourceSample
-{
-    public static void main( String[] args ) throws Exception
-    {
-        Component component = new Component();
-        component.getServers().add( Protocol.HTTP, 8080 );
-
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module ) throws AssemblyException
-            {
-                new EntityTestAssembler().assemble( module );
-
-                module.values( DomainEventValue.class, UnitOfWorkDomainEventsValue.class );
-                module.services( MemoryEventStoreService.class ).taggedWith( "domain" );
-                module.services( DomainEventFactoryService.class );
-                module.importedServices( CurrentUserUoWPrincipal.class ).importedBy( ImportedServiceDeclaration.NEW_OBJECT );
-                module.objects( CurrentUserUoWPrincipal.class );
-
-                module.objects( DomainEventSourceResource.class, PingResource.class );
-
-                module.entities( TestEntity.class ).withConcerns( DomainEventCreationConcern.class );
-            }
-        };
-
-        component.getDefaultHost().attach( "/events", new TestApplication( assembler ) );
-        component.getDefaultHost().attach( "/ping", assembler.module().newObject( PingResource.class ) );
-        component.start();
-
-        generateTestData(assembler.module());
-    }
-
-    private static void generateTestData(UnitOfWorkFactory unitOfWorkFactory) throws UnitOfWorkCompletionException
-    {
-        // Set principal for the UoW
-        Principal administratorPrincipal = new Principal()
-        {
-            public String getName()
-            {
-                return "administrator";
-            }
-        };
-
-        // Perform UoW with usecase defined
-        for (int i = 0; i < 43; i++)
-        {
-            UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "Change description "+(i+1) ));
-            uow.setMetaInfo( administratorPrincipal );
-
-            TestEntity entity = uow.newEntity( TestEntity.class );
-            entity.changedDescription( "New description" );
-            uow.complete();
-        }
-    }
-
-    static class TestApplication
-        extends Application
-    {
-        private final SingletonAssembler assembler;
-
-        TestApplication(SingletonAssembler assembler)
-        {
-            this.assembler = assembler;
-        }
-
-        @Override
-        public Restlet createInboundRoot()
-        {
-            getTunnelService().setExtensionsTunnel( true );
-            return assembler.module().newObject(DomainEventSourceResource.class  );
-        }
-    }
-
-
-    @Mixins(TestEntity.Mixin.class)
-    public interface TestEntity
-            extends EntityComposite
-    {
-        @UseDefaults
-        Property<String> description();
-
-        @DomainEvent
-        void changedDescription( String newName );
-
-        abstract class Mixin
-                implements TestEntity
-        {
-            public void changedDescription( String newName )
-            {
-                description().set( newName );
-            }
-        }
-    }
-
-    // Used to create more events
-    public static class PingResource
-        extends Restlet
-    {
-        @Structure
-        UnitOfWorkFactory unitOfWorkFactory;
-
-        @Service
-        EventSource eventSource;
-
-        @Override
-        public void handle( Request request, Response response )
-        {
-            // Set principal for the UoW
-            Principal administratorPrincipal = new Principal()
-            {
-                public String getName()
-                {
-                    return "administrator";
-                }
-            };
-
-            // Perform UoW with usecase defined
-            try
-            {
-                UnitOfWork uow = unitOfWorkFactory.newUnitOfWork( UsecaseBuilder.newUsecase( "Change description "+(eventSource.count()) ));
-                uow.setMetaInfo( administratorPrincipal );
-
-                TestEntity entity = uow.newEntity( TestEntity.class );
-                entity.changedDescription( "New description" );
-                uow.complete();
-
-                response.setEntity( new StringRepresentation( "Event created" ) );
-                response.setStatus( Status.SUCCESS_OK );
-            } catch (UnitOfWorkCompletionException e)
-            {
-                throw new ResourceException(e);
-            }
-        }
-    }
-}
diff --git a/libraries/eventsourcing/build.gradle b/libraries/eventsourcing/build.gradle
deleted file mode 100644
index 05ed544..0000000
--- a/libraries/eventsourcing/build.gradle
+++ /dev/null
@@ -1,32 +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.
- */
-
-description = "Apache Zest™ Event Sourcing Library."
-
-jar { manifest { name = "Apache Zest™ Library - Event Sourcing" }}
-
-dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile libraries.slf4j_api
-
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
diff --git a/libraries/eventsourcing/dev-status.xml b/libraries/eventsourcing/dev-status.xml
deleted file mode 100644
index 5adebd7..0000000
--- a/libraries/eventsourcing/dev-status.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
-  <status>
-    <!--none,early,beta,stable,mature-->
-    <codebase>beta</codebase>
-
-    <!-- none, brief, good, complete -->
-    <documentation>brief</documentation>
-
-    <!-- none, some, good, complete -->
-    <unittests>some</unittests>
-  </status>
-  <licenses>
-    <license>ALv2</license>
-  </licenses>
-</module>
diff --git a/libraries/eventsourcing/src/docs/eventsourcing.txt b/libraries/eventsourcing/src/docs/eventsourcing.txt
deleted file mode 100644
index 6936ea5..0000000
--- a/libraries/eventsourcing/src/docs/eventsourcing.txt
+++ /dev/null
@@ -1,135 +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.
-///////////////////////////////////////////////////////////////
-
-[[library-eventsourcing, Event Sourcing Library]]
-= Event Sourcing =
-
-[devstatus]
---------------
-source=libraries/eventsourcing/dev-status.xml
---------------
-
-The Event Sourcing Library supports generating, storing and replaying two types of events: application-events and domain-events.
-
-Application events are bound to Usecase and are produced by execution of specific methods (ones with `ApplicationEvent` as their first parameter).
-Each application event holds information about Usecase, method name and JSON serialized values of method parameters.
-
-Domain events are bound to entity instances and are produced by execution of annotated (see `@DomainEvent`) methods that belongs to `EntityComposite`.
-Each domain event (see `DomainEventValue`) holds information about entity type, identity, method name and JSON serialized values of method parameters.
-
-Both application and domain events are captured during `UnitOfWork` lifetime and are stored in `EventStore` after successfully completed `UnitOfWork` as collection together (see `UnitOfWorkDomainEventsValue` and `TransactionApplicationEvents`).
-
-There is support for replaying events.
-When events are replayed the same code is executed but no new events are generated.
-
-There are helper classes that enables a service to easily track events feed, and for domain events there is `EventRouter` that allow to specify specification->receiver routes.
-
-include::../../build/docs/buildinfo/artifact.txt[]
-
-*JDBM backed store*
-
-EventStore supports indexed and streamed access to events feed.
-There is in-memory and JDBM backed implementations.
-
-[devstatus]
---------------
-source=libraries/eventsourcing-jdbm/dev-status.xml
---------------
-
-include::../../../eventsourcing-jdbm/build/docs/buildinfo/artifact.txt[]
-
-*REST access*
-
-For remote access to feed there is `eventsourcing-rest` library that exposes events as Atom feeds.
-
-[devstatus]
---------------
-source=libraries/eventsourcing-rest/dev-status.xml
---------------
-
-include::../../../eventsourcing-rest/build/docs/buildinfo/artifact.txt[]
-
-
-== Application Events ==
-
-Assembly is done as follows:
-
-[snippet,java]
-----
-source=libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/application/ApplicationEventTest.java
-tag=assemblyAE
-----
-
-Configure application events store:
-[snippet,java]
-----
-source=libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/application/ApplicationEventTest.java
-tag=storeAE
-----
-
-Actual method on composite which execution emits application event.
-First parameter is `null` on "normal" execution.
-If it is not `null`, then the method call is a replay of previously created events.
-[snippet,java]
-----
-source=libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/application/ApplicationEventTest.java
-tag=methodAE
-----
-
-To enable execution capturing, you have to configure composite with concern:
-[snippet,java]
-----
-source=libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/application/ApplicationEventTest.java
-tag=concernAE
-----
-
-== Domain Events ==
-
-Assembly:
-
-[snippet,java]
-----
-source=libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/DomainEventTest.java
-tag=assemblyDE
-----
-
-Configure domain events store:
-
-[snippet,java]
-----
-source=libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/DomainEventTest.java
-tag=storeDE
-----
-
-Annotate your entity state changing methods.
-Event methods may only change state.
-They may not fail or thrown exceptions:
-[snippet,java]
-----
-source=libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/DomainEventTest.java
-tag=methodDE
-----
-
-To enable method execution capturing, you have to configure entity with concern:
-
-[snippet,java]
-----
-source=libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/DomainEventTest.java
-tag=concernDE
-----
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/api/ApplicationEvent.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/api/ApplicationEvent.java
deleted file mode 100644
index efd02d8..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/api/ApplicationEvent.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.api;
-
-import java.util.Date;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * Representation of an application-event.
- * <p>
- * An application event is triggered by calling a method
- * that is of the form:
- * </p>
- * <pre><code>
- * void someName(ApplicationEvent event, SomeParam param);
- * </code></pre>
- * <p>
- * The "event" argument should be invoked with null, as it will be created during
- * the method call. If it is not null, then the method call is a replay of previously
- * created events.
- * </p>
- */
-public interface ApplicationEvent
-        extends ValueComposite, Identity
-{
-    // Usecase
-    Property<String> usecase();
-
-    // Name of method/event
-    Property<String> name();
-
-    // When the event was created
-    Property<Date> on();
-
-    // Method parameters as JSON
-    Property<String> parameters();
-
-    // Version of the application that created this event
-    Property<String> version();
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/api/TransactionApplicationEvents.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/api/TransactionApplicationEvents.java
deleted file mode 100644
index 37917f1..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/api/TransactionApplicationEvents.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.api;
-
-import java.util.List;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * List of events for a single transaction. Events must always be consumed
- * in transaction units, in order to ensure that the result is consistent
- * with what happened in that transaction.
- */
-public interface TransactionApplicationEvents
-        extends ValueComposite
-{
-    // Timestamp when the events were stored in the EventStore
-    // Note that if events are sent from one store to another this timestamp
-    // is updated when it is re-stored
-
-    Property<Long> timestamp();
-
-    // List of events for this transaction
-
-    @UseDefaults
-    Property<List<ApplicationEvent>> events();
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/api/package.html b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/api/package.html
deleted file mode 100644
index d759d34..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/api/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EventSourcing Application API.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/ApplicationEventCreationConcern.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/ApplicationEventCreationConcern.java
deleted file mode 100644
index 962ec57..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/ApplicationEventCreationConcern.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.factory;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.concern.GenericConcern;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.library.eventsourcing.application.api.ApplicationEvent;
-
-/**
- * Generate application event for event method
- */
-@AppliesTo(ApplicationEventMethodFilter.class)
-public class ApplicationEventCreationConcern
-        extends GenericConcern
-{
-    @Service
-    ApplicationEventFactory eventFactory;
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable
-    {
-        if (args[0] == null)
-        {
-            // Create application event
-            ApplicationEvent event = eventFactory.createEvent( method.getName(), args );
-            args[0] = event;
-        }
-
-        return next.invoke( proxy, method, args );
-    }
-}
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/ApplicationEventCreator.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/ApplicationEventCreator.java
deleted file mode 100644
index b1e4db9..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/ApplicationEventCreator.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.factory;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.mixin.NoopMixin;
-
-/**
- * JAVADOC
- */
-@Mixins(NoopMixin.class)
-@Concerns(ApplicationEventCreationConcern.class)
-public interface ApplicationEventCreator
-{
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/ApplicationEventFactory.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/ApplicationEventFactory.java
deleted file mode 100644
index 5f08b37..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/ApplicationEventFactory.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.factory;
-
-import org.qi4j.library.eventsourcing.application.api.ApplicationEvent;
-
-/**
- * Factory for ApplicationEvents
- */
-public interface ApplicationEventFactory
-{
-    ApplicationEvent createEvent( String name, Object[] args );
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/ApplicationEventFactoryService.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/ApplicationEventFactoryService.java
deleted file mode 100644
index e5c4e4f..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/ApplicationEventFactoryService.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.factory;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.json.JSONStringer;
-import org.json.JSONWriter;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.entity.IdentityGenerator;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.library.eventsourcing.application.api.ApplicationEvent;
-import org.qi4j.library.eventsourcing.domain.spi.CurrentUser;
-
-import java.util.Date;
-
-/**
- * DomainEventValue factory
- */
-@Concerns(TransactionNotificationConcern.class)
-@Mixins(ApplicationEventFactoryService.Mixin.class)
-public interface ApplicationEventFactoryService
-        extends ApplicationEventFactory, ServiceComposite
-{
-    class Mixin
-            implements ApplicationEventFactory
-    {
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        @Structure
-        ValueBuilderFactory vbf;
-
-        @Service
-        IdentityGenerator idGenerator;
-
-        @Service
-        CurrentUser currentUser;
-
-        String version;
-
-        public void init( @Structure Application application )
-        {
-            version = application.version();
-        }
-
-        @Override
-        public ApplicationEvent createEvent( String name, Object[] args )
-        {
-            ValueBuilder<ApplicationEvent> builder = vbf.newValueBuilder( ApplicationEvent.class );
-
-            ApplicationEvent prototype = builder.prototype();
-            prototype.name().set( name );
-            prototype.on().set( new Date() );
-
-            prototype.identity().set( idGenerator.generate( ApplicationEvent.class ) );
-
-            UnitOfWork uow = uowf.currentUnitOfWork();
-            prototype.usecase().set( uow.usecase().name() );
-            prototype.version().set( version );
-
-            // JSON-ify parameters
-            JSONStringer json = new JSONStringer();
-            try
-            {
-                JSONWriter params = json.object();
-                for (int i = 1; i < args.length; i++)
-                {
-                    params.key( "param" + i );
-                    if (args[i] == null)
-                        params.value( JSONObject.NULL );
-                    else
-                        params.value( args[i] );
-                }
-                json.endObject();
-            } catch (JSONException e)
-            {
-                throw new IllegalArgumentException( "Could not create event", e );
-            }
-
-            prototype.parameters().set( json.toString() );
-
-            ApplicationEvent event = builder.newInstance();
-
-            return event;
-        }
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/ApplicationEventMethodFilter.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/ApplicationEventMethodFilter.java
deleted file mode 100644
index d33aad4..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/ApplicationEventMethodFilter.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.factory;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesToFilter;
-import org.qi4j.library.eventsourcing.application.api.ApplicationEvent;
-
-/**
- * Filter for Event methods. Event methods
- * have ApplicationEvent as their first method parameter.
- */
-public class ApplicationEventMethodFilter
-        implements AppliesToFilter
-{
-    @Override
-    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
-    {
-        return method.getParameterTypes().length > 0 && method.getParameterTypes()[0].equals( ApplicationEvent.class );
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/TransactionNotificationConcern.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/TransactionNotificationConcern.java
deleted file mode 100644
index 4a3bee6..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/TransactionNotificationConcern.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.factory;
-
-import java.io.IOException;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCallback;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.library.eventsourcing.application.api.ApplicationEvent;
-import org.qi4j.library.eventsourcing.application.source.ApplicationEventStore;
-import org.qi4j.library.eventsourcing.domain.factory.DomainEventFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Notify transaction listeners when a complete transaction of domain events is available.
- */
-public class TransactionNotificationConcern
-    extends ConcernOf<ApplicationEventFactory>
-    implements ApplicationEventFactory
-{
-    @Service
-    ApplicationEventStore eventStore;
-
-    @Structure
-    UnitOfWorkFactory uowf;
-
-    Logger logger = LoggerFactory.getLogger( DomainEventFactory.class );
-
-    @Override
-    public ApplicationEvent createEvent( String name, Object[] args )
-    {
-        final UnitOfWork unitOfWork = uowf.currentUnitOfWork();
-
-        ApplicationEvent event = next.createEvent( name, args );
-
-        // Add event to list in UoW
-        UnitOfWorkApplicationEvents events = unitOfWork.metaInfo( UnitOfWorkApplicationEvents.class );
-        if( events == null )
-        {
-            events = new UnitOfWorkApplicationEvents();
-            unitOfWork.setMetaInfo( events );
-
-            unitOfWork.addUnitOfWorkCallback( new UnitOfWorkCallback()
-            {
-                @Override
-                public void beforeCompletion()
-                    throws UnitOfWorkCompletionException
-                {
-                }
-
-                @Override
-                public void afterCompletion( UnitOfWorkStatus status )
-                {
-                    if( status.equals( UnitOfWorkStatus.COMPLETED ) )
-                    {
-                        UnitOfWorkApplicationEvents events = unitOfWork.metaInfo( UnitOfWorkApplicationEvents.class );
-
-                        try
-                        {
-                            eventStore.storeEvents( events.getEvents() );
-                        }
-                        catch( IOException e )
-                        {
-                            logger.error( "Could not store events", e );
-                            // How do we handle this? This is a major error!
-                        }
-                    }
-                }
-            } );
-        }
-
-        events.add( event );
-
-        return event;
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/UnitOfWorkApplicationEvents.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/UnitOfWorkApplicationEvents.java
deleted file mode 100644
index 12cc6c2..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/UnitOfWorkApplicationEvents.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.factory;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.library.eventsourcing.application.api.ApplicationEvent;
-
-/**
- * List of events for the current UnitOfWork. This will be updated by the DomainEventFactory.
- */
-public class UnitOfWorkApplicationEvents
-{
-    private List<ApplicationEvent> events = new ArrayList<ApplicationEvent>();
-
-    public void add( ApplicationEvent event )
-    {
-        events.add( event );
-    }
-
-    public List<ApplicationEvent> getEvents()
-    {
-        return events;
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/package.html b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/package.html
deleted file mode 100644
index 6353ddb..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/factory/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EventSourcing Application Factory.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/replay/ApplicationEventPlayer.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/replay/ApplicationEventPlayer.java
deleted file mode 100644
index 075988c..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/replay/ApplicationEventPlayer.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.replay;
-
-import org.qi4j.library.eventsourcing.application.api.ApplicationEvent;
-
-/**
- * Service that can replay ApplicationEvents.
- */
-public interface ApplicationEventPlayer
-{
-    /**
-     * Invoke a domain event on a particular object. The object could
-     * be the original object, but could also be a service that wants
-     * to be invoked to handle the event.
-     *
-     * @param applicationEvent Application event
-     * @param object target
-     * @throws ApplicationEventReplayException if unable to play event
-     */
-    public void playEvent( ApplicationEvent applicationEvent, Object object )
-            throws ApplicationEventReplayException;
-}
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/replay/ApplicationEventPlayerService.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/replay/ApplicationEventPlayerService.java
deleted file mode 100644
index 51f892e..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/replay/ApplicationEventPlayerService.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.replay;
-
-import java.lang.reflect.Method;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import org.json.JSONObject;
-import org.json.JSONTokener;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.library.eventsourcing.application.api.ApplicationEvent;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * ApplicationEvent player
- */
-@Mixins(ApplicationEventPlayerService.Mixin.class)
-public interface ApplicationEventPlayerService
-        extends ApplicationEventPlayer, ServiceComposite
-{
-    class Mixin
-            implements ApplicationEventPlayer
-    {
-        final Logger logger = LoggerFactory.getLogger( ApplicationEventPlayer.class );
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        @Structure
-        Module module;
-
-        @Structure
-        Qi4j api;
-
-        SimpleDateFormat dateFormat = new SimpleDateFormat( "EEE MMM dd HH:mm:ss zzz yyyy" );
-
-        @Override
-        public void playEvent( ApplicationEvent applicationEvent, Object object )
-                throws ApplicationEventReplayException
-        {
-            UnitOfWork uow = uowf.currentUnitOfWork();
-            Class handlerType = object.getClass();
-
-            // Get method
-            Method eventMethod = getEventMethod( handlerType, applicationEvent.name().get() );
-
-            if (eventMethod == null)
-            {
-                logger.warn( "Could not find event method " + applicationEvent.name().get() + " in entity of type " + handlerType.getName() );
-                return;
-            }
-
-            // Build parameters
-            try
-            {
-                String jsonParameters = applicationEvent.parameters().get();
-                JSONObject parameters = (JSONObject) new JSONTokener( jsonParameters ).nextValue();
-                Object[] args = new Object[eventMethod.getParameterTypes().length];
-                for (int i = 1; i < eventMethod.getParameterTypes().length; i++)
-                {
-                    Class<?> parameterType = eventMethod.getParameterTypes()[i];
-
-                    String paramName = "param" + i;
-
-                    Object value = parameters.get( paramName );
-
-                    args[i] = getParameterArgument( parameterType, value, uow );
-                }
-
-                args[0] = applicationEvent;
-
-                // Invoke method
-                logger.debug( "Replay:" + applicationEvent + " on:" + object );
-
-                eventMethod.invoke( object, args );
-            } catch (Exception e)
-            {
-                throw new ApplicationEventReplayException( applicationEvent, e );
-            }
-        }
-
-        private Object getParameterArgument( Class<?> parameterType, Object value, UnitOfWork uow ) throws ParseException
-        {
-            if (value.equals( JSONObject.NULL ))
-                return null;
-
-            if (parameterType.equals( String.class ))
-            {
-                return (String) value;
-            } else if (parameterType.equals( Boolean.class ) || parameterType.equals( Boolean.TYPE ))
-            {
-                return (Boolean) value;
-            } else if (parameterType.equals( Long.class ) || parameterType.equals( Long.TYPE ))
-            {
-                return ((Number) value).longValue();
-            } else if (parameterType.equals( Integer.class ) || parameterType.equals( Integer.TYPE ))
-            {
-                return ((Number) value).intValue();
-            } else if (parameterType.equals( Date.class ))
-            {
-                return dateFormat.parse( (String) value );
-            } else if (ValueComposite.class.isAssignableFrom( parameterType ))
-            {
-                return module.newValueFromSerializedState( parameterType, (String) value );
-            } else if (parameterType.isInterface())
-            {
-                return uow.get( parameterType, (String) value );
-            } else if (parameterType.isEnum())
-            {
-                return Enum.valueOf( (Class<? extends Enum>) parameterType, value.toString() );
-            } else
-            {
-                throw new IllegalArgumentException( "Unknown parameter type:" + parameterType.getName() );
-            }
-        }
-
-        private Method getEventMethod( Class<?> aClass, String eventName )
-        {
-            for (Method method : aClass.getMethods())
-            {
-                if (method.getName().equals( eventName ))
-                {
-                    Class[] parameterTypes = method.getParameterTypes();
-                    if (parameterTypes.length > 0 && parameterTypes[0].equals( ApplicationEvent.class ))
-                        return method;
-                }
-            }
-            return null;
-        }
-    }
-}
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/replay/ApplicationEventReplayException.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/replay/ApplicationEventReplayException.java
deleted file mode 100644
index 4438c10..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/replay/ApplicationEventReplayException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.replay;
-
-import org.qi4j.library.eventsourcing.application.api.ApplicationEvent;
-
-/**
- * An event replay failed.
- */
-public class ApplicationEventReplayException
-        extends RuntimeException
-{
-    private ApplicationEvent event;
-
-    public ApplicationEventReplayException( ApplicationEvent event, Throwable cause )
-    {
-        super( cause );
-        this.event = event;
-    }
-
-    @Override
-    public String getMessage()
-    {
-        return "Could not replay event:" + event + ", caused by:" + getCause();
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/replay/package.html b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/replay/package.html
deleted file mode 100644
index 126e083..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/replay/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EventSourcing Application Replay.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/AbstractApplicationEventStoreMixin.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/AbstractApplicationEventStoreMixin.java
deleted file mode 100644
index eedc464..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/AbstractApplicationEventStoreMixin.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.source;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.functional.Iterables;
-import org.qi4j.io.Input;
-import org.qi4j.io.Inputs;
-import org.qi4j.io.Output;
-import org.qi4j.library.eventsourcing.application.api.ApplicationEvent;
-import org.qi4j.library.eventsourcing.application.api.TransactionApplicationEvents;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static java.util.Collections.synchronizedList;
-
-/**
- * Base implementation for ApplicationEventStores.
- */
-public abstract class AbstractApplicationEventStoreMixin
-        implements ApplicationEventStore, ApplicationEventStream, ApplicationEventStoreActivation
-{
-    @This
-    protected Identity identity;
-
-    protected Logger logger;
-    protected ValueType domainEventType;
-    protected ValueType transactionEventsType;
-
-    protected Lock lock = new ReentrantLock();
-
-    @Structure
-    protected Module module;
-
-    @Structure
-    private ValueBuilderFactory vbf;
-
-    private ExecutorService transactionNotifier;
-
-    final private List<Output<TransactionApplicationEvents, ? extends Throwable>> listeners = synchronizedList( new ArrayList<Output<TransactionApplicationEvents, ? extends Throwable>>() );
-
-    private long lastTimestamp = 0;
-
-    @Override
-    public void activateApplicationEventStore()
-            throws Exception
-    {
-        logger = LoggerFactory.getLogger( identity.identity().get() );
-
-        domainEventType = module.valueDescriptor( ApplicationEvent.class.getName() ).valueType();
-        transactionEventsType = module.valueDescriptor( TransactionApplicationEvents.class.getName() ).valueType();
-
-        transactionNotifier = Executors.newSingleThreadExecutor();
-    }
-
-    @Override
-    public void passivateApplicationEventStore()
-            throws Exception
-    {
-        transactionNotifier.shutdown();
-        transactionNotifier.awaitTermination( 10000, TimeUnit.MILLISECONDS );
-    }
-
-    // This is how transactions are put into the store
-    @Override
-    public TransactionApplicationEvents storeEvents( Iterable<ApplicationEvent> events ) throws IOException
-    {
-        // Create new TransactionApplicationEvents
-        ValueBuilder<TransactionApplicationEvents> builder = vbf.newValueBuilder( TransactionApplicationEvents.class );
-        Iterables.addAll( builder.prototype().events().get(), events );
-        builder.prototype().timestamp().set( getCurrentTimestamp() );
-
-        final TransactionApplicationEvents transactionDomain = builder.newInstance();
-
-        // Lock store so noone else can interrupt
-        lock();
-        try
-        {
-            storeEvents( transactionDomain );
-        } finally
-        {
-            lock.unlock();
-        }
-
-        // Notify listeners
-        transactionNotifier.submit( new Runnable()
-        {
-            @Override
-            public void run()
-            {
-                synchronized (listeners)
-                {
-                    Input<TransactionApplicationEvents, RuntimeException> input = Inputs.iterable( Collections.singleton( transactionDomain ) );
-                    for (Output<TransactionApplicationEvents, ? extends Throwable> listener : listeners)
-                    {
-                        try
-                        {
-                            input.transferTo( listener );
-                        } catch (Throwable e)
-                        {
-                            logger.warn( "Could not notify event listener", e );
-                        }
-                    }
-                }
-            }
-        } );
-
-        return transactionDomain;
-    }
-
-    // EventStream implementation
-
-
-    @Override
-    public void registerListener( Output<TransactionApplicationEvents, ? extends Throwable> listener )
-    {
-        listeners.add( listener );
-    }
-
-
-    @Override
-    public void unregisterListener( Output<TransactionApplicationEvents, ? extends Throwable> listener )
-    {
-        listeners.remove( listener );
-    }
-
-    abstract protected void rollback()
-            throws IOException;
-
-    abstract protected void commit()
-            throws IOException;
-
-    abstract protected void storeEvents( TransactionApplicationEvents transactionDomain )
-            throws IOException;
-
-    /**
-     * Fix for this bug:
-     * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6822370
-     */
-    protected void lock()
-    {
-        while (true)
-        {
-            try
-            {
-                lock.tryLock( 1000, TimeUnit.MILLISECONDS );
-                break;
-            } catch (InterruptedException e)
-            {
-                // Try again
-            }
-        }
-    }
-
-    private synchronized long getCurrentTimestamp()
-    {
-        long timestamp = System.currentTimeMillis();
-        if (timestamp <= lastTimestamp)
-            timestamp = lastTimestamp + 1; // Increase by one to ensure uniqueness
-        lastTimestamp = timestamp;
-        return timestamp;
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/ApplicationEventSource.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/ApplicationEventSource.java
deleted file mode 100644
index 0019e00..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/ApplicationEventSource.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.source;
-
-import java.io.IOException;
-import org.qi4j.io.Input;
-import org.qi4j.library.eventsourcing.application.api.TransactionApplicationEvents;
-
-/**
- * An ApplicationEventSource is a source of application events that can be pulled in chunks. Events are grouped in the transactions in which they were created.
- */
-public interface ApplicationEventSource
-{
-    /**
-     * Get list of event transactions after the given timestamp.
-     * <p>
-     * If they are on the exact same timestamp, they will not be included.
-     * <p>
-     * The method uses the visitor pattern, so a visitor is sent in which is given each transaction, one at a time.
-     *
-     * @param afterTimestamp timestamp of transactions
-     * @param maxTransactions maximum transactions
-     * @return list of event transactions
-     */
-    Input<TransactionApplicationEvents, IOException> transactionsAfter( long afterTimestamp, long maxTransactions );
-
-    /**
-     * Get list of event transactions before the given timestamp.
-     * <p>
-     * If they are on the exact same timestamp, they will not be included.
-     * <p>
-     * The method uses the visitor pattern, so a visitor is sent in which is given each transaction, one at a time.
-     * <p>
-     * The transactions are sent to the visitor with the latest transaction first, i.e. walking backwards in the stream.
-     *
-     * @param beforeTimestamp timestamp of transactions
-     * @param maxTransactions maximum transactions
-     * @return list of event transactions
-     */
-    Input<TransactionApplicationEvents, IOException> transactionsBefore( long beforeTimestamp, long maxTransactions );
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/ApplicationEventStore.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/ApplicationEventStore.java
deleted file mode 100644
index 5a6cd12..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/ApplicationEventStore.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.source;
-
-import java.io.IOException;
-import org.qi4j.library.eventsourcing.application.api.ApplicationEvent;
-import org.qi4j.library.eventsourcing.application.api.TransactionApplicationEvents;
-
-/**
- * Store of application-events.
- */
-public interface ApplicationEventStore
-{
-    TransactionApplicationEvents storeEvents( Iterable<ApplicationEvent> events ) throws IOException;
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/ApplicationEventStoreActivation.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/ApplicationEventStoreActivation.java
deleted file mode 100644
index e72eb1e..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/ApplicationEventStoreActivation.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.library.eventsourcing.application.source;
-
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.service.ServiceReference;
-
-public interface ApplicationEventStoreActivation
-{
-
-    void activateApplicationEventStore()
-            throws Exception;
-
-    void passivateApplicationEventStore()
-            throws Exception;
-
-    public static class Activator
-            extends ActivatorAdapter<ServiceReference<ApplicationEventStoreActivation>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<ApplicationEventStoreActivation> activated )
-                throws Exception
-        {
-            activated.get().activateApplicationEventStore();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<ApplicationEventStoreActivation> passivating )
-                throws Exception
-        {
-            passivating.get().passivateApplicationEventStore();
-        }
-
-    }
-
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/ApplicationEventStream.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/ApplicationEventStream.java
deleted file mode 100644
index 8b7daa1..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/ApplicationEventStream.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.source;
-
-import org.qi4j.io.Output;
-import org.qi4j.library.eventsourcing.application.api.TransactionApplicationEvents;
-
-/**
- * Stream of event transactions. Registering with a stream will
- * allow the subscriber to get callbacks when new transactions
- * are available. The callbacks are done asynchronously.
- */
-public interface ApplicationEventStream
-{
-    void registerListener( Output<TransactionApplicationEvents, ? extends Throwable> listener );
-
-    void unregisterListener( Output<TransactionApplicationEvents, ? extends Throwable> listener );
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/helper/ApplicationEventParameters.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/helper/ApplicationEventParameters.java
deleted file mode 100644
index 50e2e36..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/helper/ApplicationEventParameters.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.source.helper;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.library.eventsourcing.application.api.ApplicationEvent;
-
-/**
- * Utility class to pick out parameters by name or index as strings from a ApplicationEvent
- */
-public class ApplicationEventParameters
-{
-    /**
-     * Get the named parameter from an event.
-     *
-     * @param event event with parameters
-     * @param name  name of parameter
-     * @return the parameter with the given name or null
-     */
-    public static String getParameter( ApplicationEvent event, String name )
-    {
-        String parametersJson = event.parameters().get();
-        try
-        {
-            JSONObject jsonObject = new JSONObject( parametersJson );
-            return jsonObject.get( name ).toString();
-        } catch (JSONException e)
-        {
-            return null;
-        }
-    }
-
-    /**
-     * Get parameter with given index.
-     *
-     * @param event event with parameters
-     * @param idx   index of parameter
-     * @return the parameter with the given index or null
-     */
-    public static String getParameter( ApplicationEvent event, int idx )
-    {
-        try
-        {
-            String parametersJson = event.parameters().get();
-            JSONObject jsonObject = new JSONObject( parametersJson );
-            return jsonObject.get( "param" + idx ).toString();
-        } catch (JSONException e)
-        {
-            return null;
-        }
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/helper/ApplicationEvents.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/helper/ApplicationEvents.java
deleted file mode 100644
index 4205cd0..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/helper/ApplicationEvents.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.source.helper;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import org.qi4j.api.util.Methods;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.library.eventsourcing.application.api.ApplicationEvent;
-import org.qi4j.library.eventsourcing.application.api.TransactionApplicationEvents;
-import org.qi4j.library.eventsourcing.application.replay.ApplicationEventPlayer;
-import org.qi4j.library.eventsourcing.application.replay.ApplicationEventReplayException;
-
-/**
- * Helper methods for working with Iterables of DomainEvents and UnitOfWorkDomainEventsValue.
- */
-public class ApplicationEvents
-{
-    public static Iterable<ApplicationEvent> events( Iterable<TransactionApplicationEvents> transactions )
-    {
-        List<Iterable<ApplicationEvent>> events = new ArrayList<Iterable<ApplicationEvent>>();
-        for (TransactionApplicationEvents transactionDomain : transactions)
-        {
-            events.add( transactionDomain.events().get() );
-        }
-
-        Iterable<ApplicationEvent>[] iterables = (Iterable<ApplicationEvent>[]) new Iterable[events.size()];
-        return Iterables.flatten( events.<Iterable<ApplicationEvent>>toArray( iterables ) );
-    }
-
-    public static Iterable<ApplicationEvent> events( TransactionApplicationEvents... transactionDomains )
-    {
-        List<Iterable<ApplicationEvent>> events = new ArrayList<Iterable<ApplicationEvent>>();
-        for (TransactionApplicationEvents transactionDomain : transactionDomains)
-        {
-            events.add( transactionDomain.events().get() );
-        }
-
-        Iterable<ApplicationEvent>[] iterables = (Iterable<ApplicationEvent>[]) new Iterable[events.size()];
-        return Iterables.flatten( events.<Iterable<ApplicationEvent>>toArray( iterables ) );
-    }
-
-    public static boolean matches( Specification<ApplicationEvent> specification, Iterable<TransactionApplicationEvents> transactions )
-    {
-        return Iterables.filter( specification, events( transactions ) ).iterator().hasNext();
-    }
-
-    // Common specifications
-
-    public static Specification<ApplicationEvent> withNames( final Iterable<String> names )
-    {
-        return new Specification<ApplicationEvent>()
-        {
-            @Override
-            public boolean satisfiedBy( ApplicationEvent event )
-            {
-                for (String name : names)
-                {
-                    if (event.name().get().equals( name ))
-                        return true;
-                }
-                return false;
-            }
-        };
-    }
-
-    public static Specification<ApplicationEvent> withNames( final String... names )
-    {
-        return new Specification<ApplicationEvent>()
-        {
-            @Override
-            public boolean satisfiedBy( ApplicationEvent event )
-            {
-                for (String name : names)
-                {
-                    if (event.name().get().equals( name ))
-                        return true;
-                }
-                return false;
-            }
-        };
-    }
-
-    public static Specification<ApplicationEvent> withNames( final Class eventClass )
-    {
-        return ApplicationEvents.withNames( Iterables.map( new Function<Method, String>()
-        {
-            @Override
-            public String map( Method method )
-            {
-                return method.getName();
-            }
-        }, Iterables.toList( Methods.METHODS_OF.map( eventClass ) ) ));
-    }
-
-    public static Specification<ApplicationEvent> afterDate( final Date afterDate )
-    {
-        return new Specification<ApplicationEvent>()
-        {
-            @Override
-            public boolean satisfiedBy( ApplicationEvent event )
-            {
-                return event.on().get().after( afterDate );
-            }
-        };
-    }
-
-    public static Specification<ApplicationEvent> beforeDate( final Date beforeDate )
-    {
-        return new Specification<ApplicationEvent>()
-        {
-            @Override
-            public boolean satisfiedBy( ApplicationEvent event )
-            {
-                return event.on().get().before( beforeDate );
-            }
-        };
-    }
-
-    public static Specification<ApplicationEvent> withUsecases( final String... names )
-    {
-        return new Specification<ApplicationEvent>()
-        {
-            @Override
-            public boolean satisfiedBy( ApplicationEvent event )
-            {
-                for (String name : names)
-                {
-                    if (event.usecase().get().equals( name ))
-                        return true;
-                }
-                return false;
-            }
-        };
-    }
-
-    public static Specification<ApplicationEvent> paramIs( final String name, final String value )
-    {
-        return new Specification<ApplicationEvent>()
-        {
-            @Override
-            public boolean satisfiedBy( ApplicationEvent event )
-            {
-                return ApplicationEventParameters.getParameter( event, name ).equals( value );
-            }
-        };
-    }
-
-    public static Output<TransactionApplicationEvents, ApplicationEventReplayException> playEvents( final ApplicationEventPlayer player, final Object eventHandler )
-    {
-        final Specification<ApplicationEvent> specification = ApplicationEvents.withNames( eventHandler.getClass() );
-
-        return new Output<TransactionApplicationEvents, ApplicationEventReplayException>()
-        {
-           @Override
-           public <SenderThrowableType extends Throwable> void receiveFrom(Sender<? extends TransactionApplicationEvents, SenderThrowableType> sender) throws ApplicationEventReplayException, SenderThrowableType
-           {
-                sender.sendTo( new Receiver<TransactionApplicationEvents, ApplicationEventReplayException>()
-                {
-                    @Override
-                    public void receive( TransactionApplicationEvents item ) throws ApplicationEventReplayException
-                    {
-                        for (ApplicationEvent applicationEvent : events( item ))
-                        {
-                            if (specification.satisfiedBy( applicationEvent ))
-                                player.playEvent( applicationEvent, eventHandler );
-                        }
-                    }
-                } );
-            }
-        };
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/helper/ApplicationTransactionTracker.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/helper/ApplicationTransactionTracker.java
deleted file mode 100644
index 17f04e2..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/helper/ApplicationTransactionTracker.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.application.source.helper;
-
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.library.eventsourcing.application.api.TransactionApplicationEvents;
-import org.qi4j.library.eventsourcing.application.source.ApplicationEventSource;
-import org.qi4j.library.eventsourcing.application.source.ApplicationEventStream;
-import org.qi4j.library.eventsourcing.domain.source.helper.DomainEventTrackerConfiguration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Helper that enables a service to easily track transactions.
- * <p>
- * Upon startup the tracker will get all the transactions from the store since the last
- * check, and delegate them to the given Output. It will also register itself
- * with the store so that it can get continuous updates.
- * </p>
- * <p>
- * Then, as transactions come in from the store, they will be processed in real-time.
- * If a transaction is successfully handled the configuration of the service, which must
- * extend DomainEventTrackerConfiguration, will update the marker for the last successfully handled transaction.
- * </p>
- */
-public class ApplicationTransactionTracker<ReceiverThrowableType extends Throwable>
-{
-    private Configuration<? extends DomainEventTrackerConfiguration> configuration;
-    private Output<TransactionApplicationEvents, ReceiverThrowableType> output;
-    private ApplicationEventStream stream;
-    private ApplicationEventSource source;
-    private boolean started = false;
-    private boolean upToSpeed = false;
-    private Logger logger;
-    private Output<TransactionApplicationEvents, ReceiverThrowableType> trackerOutput;
-
-    public ApplicationTransactionTracker( ApplicationEventStream stream, ApplicationEventSource source,
-                                          Configuration<? extends DomainEventTrackerConfiguration> configuration,
-                                          Output<TransactionApplicationEvents, ReceiverThrowableType> output )
-    {
-        this.stream = stream;
-        this.configuration = configuration;
-        this.source = source;
-        this.output = output;
-
-        logger = LoggerFactory.getLogger( output.getClass() );
-    }
-
-    public void start()
-    {
-        if (!started)
-        {
-            started = true;
-
-            // Get events since last check
-            upToSpeed = true; // Pretend that we are up to speed from now on
-            trackerOutput = output();
-            try
-            {
-                source.transactionsAfter( configuration.get().lastOffset().get(), Long.MAX_VALUE ).transferTo( trackerOutput );
-            } catch (Throwable receiverThrowableType)
-            {
-                upToSpeed = false;
-            }
-
-            stream.registerListener( trackerOutput );
-        }
-    }
-
-    public void stop()
-    {
-        if (started)
-        {
-            started = false;
-            stream.unregisterListener( trackerOutput );
-            upToSpeed = false;
-        }
-    }
-
-    private Output<TransactionApplicationEvents, ReceiverThrowableType> output()
-    {
-        return new Output<TransactionApplicationEvents, ReceiverThrowableType>()
-        {
-           @Override
-           public <SenderThrowableType extends Throwable> void receiveFrom(final Sender<? extends TransactionApplicationEvents, SenderThrowableType> sender) throws ReceiverThrowableType, SenderThrowableType
-           {
-                if (!upToSpeed)
-                {
-                    // The tracker has not handled successfully all transactions before,
-                    // so it needs to get the backlog first
-
-                    upToSpeed = true; // Pretend that we are up to speed from now on
-
-                    // Get all transactions from last timestamp, including the one in this call
-                    try
-                    {
-                        source.transactionsAfter( configuration.get().lastOffset().get(), Long.MAX_VALUE ).transferTo( trackerOutput );
-                    } catch (Throwable e)
-                    {
-                        upToSpeed = false;
-                        throw (SenderThrowableType) e;
-                    }
-                }
-
-                try
-                {
-                    output.receiveFrom( new Sender<TransactionApplicationEvents, SenderThrowableType>()
-                    {
-                       @Override
-                       public <ReceiverThrowableType extends Throwable> void sendTo(final Receiver<? super TransactionApplicationEvents, ReceiverThrowableType> receiver) throws ReceiverThrowableType, SenderThrowableType
-                       {
-                            sender.sendTo( new Receiver<TransactionApplicationEvents, ReceiverThrowableType>()
-                            {
-                                @Override
-                                public void receive( TransactionApplicationEvents item ) throws ReceiverThrowableType
-                                {
-                                    receiver.receive( item );
-
-                                    // Events in this transactionDomain were handled successfully so store new marker
-                                    configuration.get().lastOffset().set( item.timestamp().get() );
-                                    configuration.save();
-                                }
-                            } );
-                        }
-                    } );
-                } catch (Throwable receiverThrowableType)
-                {
-                    upToSpeed = false;
-                    throw (ReceiverThrowableType) receiverThrowableType;
-                }
-            }
-        };
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/helper/package.html b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/helper/package.html
deleted file mode 100644
index 32f1092..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/helper/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EventSourcing Application Source Helpers.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/memory/MemoryApplicationEventStoreService.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/memory/MemoryApplicationEventStoreService.java
deleted file mode 100644
index 6fa2bce..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/memory/MemoryApplicationEventStoreService.java
+++ /dev/null
@@ -1,142 +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.qi4j.library.eventsourcing.application.source.memory;
-
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.library.eventsourcing.application.api.TransactionApplicationEvents;
-import org.qi4j.library.eventsourcing.application.source.*;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-
-import java.io.IOException;
-import java.util.*;
-
-/**
- * In-Memory ApplicationEventStore. Mainly used for testing.
- */
-@Mixins( MemoryApplicationEventStoreService.MemoryStoreMixin.class )
-@Activators( ApplicationEventStoreActivation.Activator.class )
-public interface MemoryApplicationEventStoreService
-    extends ApplicationEventSource, ApplicationEventStore, ApplicationEventStream, ApplicationEventStoreActivation, ServiceComposite
-{
-    abstract class MemoryStoreMixin
-        extends AbstractApplicationEventStoreMixin
-        implements ApplicationEventSource, ApplicationEventStoreActivation
-    {
-        // This list holds all transactions
-        private LinkedList<TransactionApplicationEvents> store = new LinkedList<TransactionApplicationEvents>();
-
-        @Override
-        public Input<TransactionApplicationEvents, IOException> transactionsAfter( final long afterTimestamp, final long maxTransactions )
-        {
-            return new Input<TransactionApplicationEvents, IOException>()
-            {
-                @Override
-                public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super TransactionApplicationEvents, ReceiverThrowableType> output )
-                    throws IOException, ReceiverThrowableType
-                {
-                    // Lock store first
-                    lock.lock();
-                    try
-                    {
-                        output.receiveFrom( new Sender<TransactionApplicationEvents, IOException>()
-                        {
-                            @Override
-                            public <ReceiverThrowableType extends Throwable> void sendTo( Receiver<? super TransactionApplicationEvents, ReceiverThrowableType> receiver )
-                                throws ReceiverThrowableType, IOException
-                            {
-                                Iterator<TransactionApplicationEvents> iterator = store.iterator();
-
-                                long count = 0;
-
-                                while( iterator.hasNext() && count < maxTransactions )
-                                {
-                                    TransactionApplicationEvents next = iterator.next();
-                                    if( next.timestamp().get() > afterTimestamp )
-                                    {
-                                        receiver.receive( next );
-                                        count++;
-                                    }
-                                }
-                            }
-                        });
-                    }
-                    finally
-                    {
-                        lock.unlock();
-                    }
-                }
-            };
-        }
-
-        @Override
-        public Input<TransactionApplicationEvents, IOException> transactionsBefore( final long beforeTimestamp, final long maxTransactions )
-        {
-            return new Input<TransactionApplicationEvents, IOException>()
-            {
-                @Override
-                public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super TransactionApplicationEvents, ReceiverThrowableType> output )
-                    throws IOException, ReceiverThrowableType
-                {
-                    // Lock store first
-                    lock.lock();
-                    try
-                    {
-                        output.receiveFrom( new Sender<TransactionApplicationEvents, IOException>()
-                        {
-                            @Override
-                            public <ReceiverThrowableType extends Throwable> void sendTo( Receiver<? super TransactionApplicationEvents, ReceiverThrowableType> receiver )
-                                throws ReceiverThrowableType, IOException
-                            {
-                                Iterator<TransactionApplicationEvents> iterator = store.descendingIterator();
-
-                                long count = 0;
-
-                                while( iterator.hasNext() && count < maxTransactions )
-                                {
-                                    TransactionApplicationEvents next = iterator.next();
-                                    if( next.timestamp().get() < beforeTimestamp )
-                                    {
-                                        receiver.receive( next );
-                                        count++;
-                                    }
-                                }
-                            }
-                        });
-                    }
-                    finally
-                    {
-                        lock.unlock();
-                    }
-                }
-            };
-        }
-
-        @Override
-        protected void storeEvents( TransactionApplicationEvents transactionDomain ) throws IOException
-        {
-            store.add( transactionDomain );
-        }
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/memory/package.html b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/memory/package.html
deleted file mode 100644
index b92be93..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/memory/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EventSourcing in-memory EventStore.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/package.html b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/package.html
deleted file mode 100644
index 533fa0d..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/application/source/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EventSourcing Application Source.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/bootstrap/EventsourcingAssembler.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/bootstrap/EventsourcingAssembler.java
deleted file mode 100644
index 228d6de..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/bootstrap/EventsourcingAssembler.java
+++ /dev/null
@@ -1,81 +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.qi4j.library.eventsourcing.bootstrap;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ImportedServiceDeclaration;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.eventsourcing.application.api.ApplicationEvent;
-import org.qi4j.library.eventsourcing.application.api.TransactionApplicationEvents;
-import org.qi4j.library.eventsourcing.application.factory.ApplicationEventFactoryService;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-import org.qi4j.library.eventsourcing.domain.factory.CurrentUserUoWPrincipal;
-import org.qi4j.library.eventsourcing.domain.factory.DomainEventFactoryService;
-
-public class EventsourcingAssembler
-    extends Assemblers.Visibility<EventsourcingAssembler>
-{
-    private boolean domainEvents;
-    private boolean applicationEvents;
-
-    private boolean uowPrincipal;
-
-    public EventsourcingAssembler withDomainEvents()
-    {
-        domainEvents = true;
-        return this;
-    }
-
-    public EventsourcingAssembler withApplicationEvents()
-    {
-        applicationEvents = true;
-        return this;
-    }
-
-    public EventsourcingAssembler withCurrentUserFromUOWPrincipal()
-    {
-        uowPrincipal = true;
-        return this;
-    }
-
-    @Override
-    public void assemble(ModuleAssembly module) throws AssemblyException
-    {
-        if( domainEvents )
-        {
-            module.values( DomainEventValue.class, UnitOfWorkDomainEventsValue.class );
-            module.services( DomainEventFactoryService.class).visibleIn(visibility() );
-        }
-
-        if( applicationEvents )
-        {
-            module.values( ApplicationEvent.class, TransactionApplicationEvents.class );
-            module.services( ApplicationEventFactoryService.class ).visibleIn( visibility() );
-        }
-
-        if( uowPrincipal )
-        {
-            module.importedServices( CurrentUserUoWPrincipal.class )
-                .importedBy( ImportedServiceDeclaration.NEW_OBJECT );
-            module.objects( CurrentUserUoWPrincipal.class );
-        }
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/bootstrap/package.html b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/bootstrap/package.html
deleted file mode 100644
index 2b9376f..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/bootstrap/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EventSourcing Assembly.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/api/DomainEvent.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/api/DomainEvent.java
deleted file mode 100644
index 5d36d3e..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/api/DomainEvent.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.api;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Annotate methods that should trigger domain events with this annotation. Example:
- * <pre>
- * &#64;DomainEvent
- * void changedDescription(String newDescription);
- * </pre>
- * Event methods may only change state. They may not fail or thrown exceptions. The name of the
- * method should be in past tense, as in something HAS already occurred, and the method is merely
- * reacting to it.
- */
-@Documented
-@Retention(RetentionPolicy.RUNTIME)
-public @interface DomainEvent
-{
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/api/DomainEventValue.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/api/DomainEventValue.java
deleted file mode 100644
index cf03741..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/api/DomainEventValue.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.api;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * Representation of a domain-event.
- * <p>An event is triggered by calling a method that is of the form:
- * </p>
- * <pre><code>
- * &#64;DomainEvent
- * void someName(SomeParam param, AnotherParam param2);
- * </code></pre>
- *
- */
-public interface DomainEventValue
-        extends ValueComposite
-{
-    // Type of the entity being invoked
-    Property<String> entityType();
-
-    // Id of the entity that generated the event
-    Property<String> entityId();
-
-    // Name of method/event
-    Property<String> name();
-
-    // Method parameters as JSON
-    Property<String> parameters();
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/api/DomainEvents.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/api/DomainEvents.java
deleted file mode 100644
index 146130b..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/api/DomainEvents.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.api;
-
-/**
- * This gives access to the current domain event. This is only usable within methods
- * marked with &#64;DomainEvent annotation.
- */
-public class DomainEvents
-{
-    private static ThreadLocal<DomainEventValue> event = new ThreadLocal<DomainEventValue>();
-
-    public static DomainEventValue currentEvent()
-    {
-        return event.get();
-    }
-
-    /**
-     * This is called by the EventSourcing library, either during creation or replay.
-     * Don't use in application code.
-     *
-     * @param currentEvent new current event
-     */
-    public static void setCurrentEvent(DomainEventValue currentEvent)
-    {
-        event.set( currentEvent );
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/api/UnitOfWorkDomainEventsValue.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/api/UnitOfWorkDomainEventsValue.java
deleted file mode 100644
index a587ac8..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/api/UnitOfWorkDomainEventsValue.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.api;
-
-import java.util.List;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * List of events for a single UnitOfWork. Events must always be consumed
- * in UoW units, in order to ensure that the result is consistent
- * with what happened in that UoW.
- *
- * Context that is common to all events in the UoW is stored here rather than
- * in the individual event.
- */
-public interface UnitOfWorkDomainEventsValue
-        extends ValueComposite
-{
-    // Version of the application that created these events
-    Property<String> version();
-
-    // Usecase name
-    Property<String> usecase();
-
-    // When the event occurred
-    Property<Long> timestamp();
-
-    // Who performed the event. Taken from CurrentUser service.
-    @Optional
-    Property<String> user();
-
-    // List of events for this transaction
-    @UseDefaults
-    Property<List<DomainEventValue>> events();
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/api/package.html b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/api/package.html
deleted file mode 100644
index e27864c..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/api/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EventSourcing Domain API.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/CurrentUserSubject.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/CurrentUserSubject.java
deleted file mode 100644
index 873eb55..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/CurrentUserSubject.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.factory;
-
-import java.security.AccessController;
-import javax.security.auth.Subject;
-import org.qi4j.library.eventsourcing.domain.spi.CurrentUser;
-
-/**
- * Uses thread-associated Subject to get the current user name. Default to "unknown".
- */
-public class CurrentUserSubject
-    implements CurrentUser
-{
-    @Override
-    public String getCurrentUser()
-    {
-        try
-        {
-            return Subject.getSubject( AccessController.getContext() ).getPrincipals().iterator().next().getName();
-        } catch (Exception e)
-        {
-            return "unknown";
-        }
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/CurrentUserUoWPrincipal.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/CurrentUserUoWPrincipal.java
deleted file mode 100644
index a617c06..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/CurrentUserUoWPrincipal.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.factory;
-
-import java.security.Principal;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.library.eventsourcing.domain.spi.CurrentUser;
-
-/**
- * CurrentUser implementation that gets a Principal object from the meta-info of the current UnitOfWork. Default to "unknown".
- */
-public class CurrentUserUoWPrincipal
-    implements CurrentUser
-{
-    @Structure
-    private UnitOfWorkFactory uowf;
-
-    @Override
-    public String getCurrentUser()
-    {
-        try
-        {
-            return uowf.currentUnitOfWork().metaInfo( Principal.class ).getName();
-        } catch (Exception e)
-        {
-            return "unknown";
-        }
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/DomainEventCreationConcern.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/DomainEventCreationConcern.java
deleted file mode 100644
index eca97f8..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/DomainEventCreationConcern.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.factory;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.concern.GenericConcern;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.library.eventsourcing.domain.api.DomainEvent;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-import org.qi4j.library.eventsourcing.domain.api.DomainEvents;
-
-/**
- * Generate event for event method
- */
-@AppliesTo(DomainEvent.class)
-public class DomainEventCreationConcern
-        extends GenericConcern
-{
-    @This
-    private EntityComposite entity;
-
-    @Service
-    private DomainEventFactory domainEventFactory;
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable
-    {
-        if (DomainEvents.currentEvent() == null)
-        {
-            // Create eventValue
-            DomainEventValue eventValue = domainEventFactory.createEvent( entity, method.getName(), args );
-            DomainEvents.setCurrentEvent( eventValue );
-            try
-            {
-                return next.invoke( proxy, method, args );
-            } finally
-            {
-                DomainEvents.setCurrentEvent( null );
-            }
-
-        } else
-        {
-            // This is probably a replay call
-            return next.invoke( proxy, method, args );
-        }
-    }
-}
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/DomainEventFactory.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/DomainEventFactory.java
deleted file mode 100644
index 8e7f598..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/DomainEventFactory.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.factory;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-
-/**
- * Factory for DomainEvents
- */
-public interface DomainEventFactory
-{
-    DomainEventValue createEvent( EntityComposite entity, String name, Object[] args );
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/DomainEventFactoryService.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/DomainEventFactoryService.java
deleted file mode 100644
index 00dafb8..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/DomainEventFactoryService.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.factory;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.json.JSONStringer;
-import org.json.JSONWriter;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * DomainEventValue factory
- */
-@Concerns(UnitOfWorkNotificationConcern.class)
-@Mixins(DomainEventFactoryService.DomainEventFactoryMixin.class)
-public interface DomainEventFactoryService
-        extends DomainEventFactory, ServiceComposite
-{
-    class DomainEventFactoryMixin
-            implements DomainEventFactory
-    {
-        @Structure
-        private ValueBuilderFactory vbf;
-
-        @Override
-        public DomainEventValue createEvent( EntityComposite entity, String name, Object[] args )
-        {
-            ValueBuilder<DomainEventValue> builder = vbf.newValueBuilder( DomainEventValue.class );
-
-            DomainEventValue prototype = builder.prototype();
-            prototype.name().set( name );
-            prototype.entityType().set( first( Qi4j.FUNCTION_DESCRIPTOR_FOR.map( entity ).types()).getName() );
-            prototype.entityId().set( entity.identity().get() );
-
-            // JSON-ify parameters
-            JSONStringer json = new JSONStringer();
-            try
-            {
-                JSONWriter params = json.object();
-                for (int i = 0; i < args.length; i++)
-                {
-                    params.key( "param" + i );
-                    if (args[i] == null)
-                        params.value( JSONObject.NULL );
-                    else
-                        params.value( args[i] );
-                }
-                json.endObject();
-            } catch (JSONException e)
-            {
-                throw new IllegalArgumentException( "Could not create eventValue", e );
-            }
-
-            prototype.parameters().set( json.toString() );
-
-            DomainEventValue eventValue = builder.newInstance();
-
-            return eventValue;
-        }
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/UnitOfWorkEvents.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/UnitOfWorkEvents.java
deleted file mode 100644
index 93093cc..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/UnitOfWorkEvents.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.factory;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-
-/**
- * List of eventValues for the current UnitOfWork. This will be updated by the DomainEventFactory.
- */
-class UnitOfWorkEvents
-{
-    private List<DomainEventValue> eventValues = new ArrayList<DomainEventValue>();
-
-    public void add( DomainEventValue eventValue )
-    {
-        eventValues.add( eventValue );
-    }
-
-    public List<DomainEventValue> getEventValues()
-    {
-        return eventValues;
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/UnitOfWorkNotificationConcern.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/UnitOfWorkNotificationConcern.java
deleted file mode 100644
index fda2a61..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/UnitOfWorkNotificationConcern.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.factory;
-
-import java.io.IOException;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCallback;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.functional.Iterables;
-import org.qi4j.io.Inputs;
-import org.qi4j.io.Output;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-import org.qi4j.library.eventsourcing.domain.source.EventStore;
-import org.qi4j.library.eventsourcing.domain.source.UnitOfWorkEventsVisitor;
-import org.qi4j.library.eventsourcing.domain.spi.CurrentUser;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Notify event listeners when a complete UoW of domain events is available.
- */
-public class UnitOfWorkNotificationConcern
-        extends ConcernOf<DomainEventFactory>
-        implements DomainEventFactory
-{
-    @Service
-    EventStore eventStore;
-
-    @Service
-    Iterable<UnitOfWorkEventsVisitor> transactionVisitors;
-
-    @Service
-    CurrentUser currentUser;
-
-    @Structure
-    ValueBuilderFactory vbf;
-
-    @Structure
-    UnitOfWorkFactory uowf;
-
-    @Structure
-    Qi4j api;
-
-    String version;
-
-    Logger logger = LoggerFactory.getLogger( DomainEventFactory.class );
-
-    Output<UnitOfWorkDomainEventsValue, IOException> eventOutput;
-
-    public void init( @Structure Application application )
-    {
-        version = application.version();
-        eventOutput = eventStore.storeEvents();
-    }
-
-    @Override
-    public DomainEventValue createEvent( EntityComposite entity, String name, Object[] args )
-    {
-        final UnitOfWork unitOfWork = uowf.currentUnitOfWork();
-
-        DomainEventValue eventValue = next.createEvent( api.dereference( entity ), name, args );
-
-        // Add eventValue to list in UoW
-        UnitOfWorkEvents events = unitOfWork.metaInfo(UnitOfWorkEvents.class );
-        if (events == null)
-        {
-            events = new UnitOfWorkEvents();
-            unitOfWork.setMetaInfo( events );
-
-            unitOfWork.addUnitOfWorkCallback( new UnitOfWorkCallback()
-            {
-                String user;
-
-                @Override
-                public void beforeCompletion() throws UnitOfWorkCompletionException
-                {
-                    user = currentUser.getCurrentUser();
-                }
-
-                @Override
-                public void afterCompletion( UnitOfWorkStatus status )
-                {
-                    if (status.equals( UnitOfWorkStatus.COMPLETED ))
-                    {
-                        UnitOfWorkEvents events = unitOfWork.metaInfo( UnitOfWorkEvents.class );
-
-                        ValueBuilder<UnitOfWorkDomainEventsValue> builder = vbf.newValueBuilder( UnitOfWorkDomainEventsValue.class );
-                        builder.prototype().user().set( user );
-                        builder.prototype().timestamp().set( System.currentTimeMillis() );
-                        builder.prototype().usecase().set( unitOfWork.usecase().name() );
-                        builder.prototype().version().set( version );
-                        builder.prototype().events().get().addAll( events.getEventValues() );
-
-                        try
-                        {
-                            final UnitOfWorkDomainEventsValue unitOfWorkDomainValue = builder.newInstance();
-                            Inputs.iterable( Iterables.iterable( unitOfWorkDomainValue ) ).transferTo( eventOutput );
-
-                            for (UnitOfWorkEventsVisitor unitOfWorkEventsVisitor : transactionVisitors)
-                            {
-                                try
-                                {
-                                    unitOfWorkEventsVisitor.visit( unitOfWorkDomainValue );
-                                } catch (Exception e)
-                                {
-                                    logger.warn( "Could not deliver events", e );
-
-                                }
-                            }
-                        } catch (IOException e)
-                        {
-                            logger.error( "Could not store events", e );
-                            // How do we handle this? This is a major error!
-                        }
-                    }
-                }
-            } );
-        }
-
-        events.add( eventValue );
-
-        return eventValue;
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/package.html b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/package.html
deleted file mode 100644
index ec26fb1..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/factory/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EventSourcing Domain Factory.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/replay/DomainEventPlayer.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/replay/DomainEventPlayer.java
deleted file mode 100644
index 05a5d67..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/replay/DomainEventPlayer.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.replay;
-
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-
-/**
- * Service that can replay transactions and individual domain events.
- */
-public interface DomainEventPlayer
-{
-    public void playTransaction( UnitOfWorkDomainEventsValue unitOfWorkDomainValue )
-            throws EventReplayException;
-
-    /**
-     * Invoke a domain event on a particular object. The object could
-     * be the original object, but could also be a service that wants
-     * to be invoked to handle the event.
-     *
-     * @param domainEventValue Domain event value
-     * @param object target
-     * @throws EventReplayException if unable to play event
-     */
-    public void playEvent( DomainEventValue domainEventValue, Object object )
-            throws EventReplayException;
-}
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/replay/DomainEventPlayerService.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/replay/DomainEventPlayerService.java
deleted file mode 100644
index c51cf5c..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/replay/DomainEventPlayerService.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.replay;
-
-import java.lang.reflect.Method;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import org.json.JSONObject;
-import org.json.JSONTokener;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-import org.qi4j.spi.Qi4jSPI;
-import org.qi4j.spi.entity.EntityState;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * DomainEventValue player
- */
-@Mixins(DomainEventPlayerService.Mixin.class)
-public interface DomainEventPlayerService
-        extends DomainEventPlayer, ServiceComposite
-{
-    class Mixin
-            implements DomainEventPlayer
-    {
-        final Logger logger = LoggerFactory.getLogger( DomainEventPlayer.class );
-
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        @Structure
-        Module module;
-
-        @Structure
-        Qi4jSPI spi;
-
-        SimpleDateFormat dateFormat = new SimpleDateFormat( "EEE MMM dd HH:mm:ss zzz yyyy" );
-
-        @Override
-        public void playTransaction( UnitOfWorkDomainEventsValue unitOfWorkDomainValue )
-                throws EventReplayException
-        {
-            UnitOfWork uow = uowf.newUnitOfWork( UsecaseBuilder.newUsecase( "Event replay" ) );
-            DomainEventValue currentEventValue = null;
-            try
-            {
-                for (DomainEventValue domainEventValue : unitOfWorkDomainValue.events().get())
-                {
-                    currentEventValue = domainEventValue;
-                    // Get the entity
-                    Class entityType = module.classLoader().loadClass( domainEventValue.entityType().get() );
-                    String id = domainEventValue.entityId().get();
-                    Object entity = null;
-                    try
-                    {
-                        entity = uow.get( entityType, id );
-                    } catch( NoSuchEntityException e )
-                    {
-                        // Event to play for an entity that doesn't yet exist - create a default instance
-                        entity = uow.newEntity( entityType, id );
-                    }
-
-                    // check if the event has already occured
-                    EntityState state = spi.entityStateOf( (EntityComposite) entity );
-                    if (state.lastModified() > unitOfWorkDomainValue.timestamp().get())
-                    {
-                        break; // don't rerun event in this unitOfWorkDomainValue
-                    }
-
-                    playEvent( domainEventValue, entity );
-                }
-                uow.complete();
-            } catch (Exception e)
-            {
-                uow.discard();
-                if (e instanceof EventReplayException)
-                    throw ((EventReplayException) e);
-                else
-                    throw new EventReplayException( currentEventValue, e );
-            }
-        }
-
-        @Override
-        public void playEvent( DomainEventValue domainEventValue, Object object )
-                throws EventReplayException
-        {
-            UnitOfWork uow = uowf.currentUnitOfWork();
-            Class entityType = object.getClass();
-
-            // Get method
-            Method eventMethod = getEventMethod( entityType, domainEventValue.name().get() );
-
-            if (eventMethod == null)
-            {
-                logger.warn( "Could not find event method " + domainEventValue.name().get() + " in entity of type " + entityType.getName() );
-                return;
-            }
-
-            // Build parameters
-            try
-            {
-                String jsonParameters = domainEventValue.parameters().get();
-                JSONObject parameters = (JSONObject) new JSONTokener( jsonParameters ).nextValue();
-                Object[] args = new Object[eventMethod.getParameterTypes().length];
-                for (int i = 1; i < eventMethod.getParameterTypes().length; i++)
-                {
-                    Class<?> parameterType = eventMethod.getParameterTypes()[i];
-
-                    String paramName = "param" + i;
-
-                    Object value = parameters.get( paramName );
-
-                    args[i] = getParameterArgument( parameterType, value, uow );
-                }
-
-                args[0] = domainEventValue;
-
-                // Invoke method
-                logger.debug( "Replay:" + domainEventValue + " on:" + object );
-
-                eventMethod.invoke( object, args );
-            } catch (Exception e)
-            {
-                throw new EventReplayException( domainEventValue, e );
-            }
-        }
-
-        private Object getParameterArgument( Class<?> parameterType, Object value, UnitOfWork uow ) throws ParseException
-        {
-            if (value.equals( JSONObject.NULL ))
-                return null;
-
-            if (parameterType.equals( String.class ))
-            {
-                return (String) value;
-            } else if (parameterType.equals( Boolean.class ) || parameterType.equals( Boolean.TYPE ))
-            {
-                return (Boolean) value;
-            } else if (parameterType.equals( Long.class ) || parameterType.equals( Long.TYPE ))
-            {
-                return ((Number) value).longValue();
-            } else if (parameterType.equals( Integer.class ) || parameterType.equals( Integer.TYPE ))
-            {
-                return ((Number) value).intValue();
-            } else if (parameterType.equals( Date.class ))
-            {
-                return dateFormat.parse( (String) value );
-            } else if (ValueComposite.class.isAssignableFrom( parameterType ))
-            {
-                return module.newValueFromSerializedState( parameterType, (String) value );
-            } else if (parameterType.isInterface())
-            {
-                return uow.get( parameterType, (String) value );
-            } else if (parameterType.isEnum())
-            {
-                return Enum.valueOf( (Class<? extends Enum>) parameterType, value.toString() );
-            } else
-            {
-                throw new IllegalArgumentException( "Unknown parameter type:" + parameterType.getName() );
-            }
-        }
-
-        private Method getEventMethod( Class<?> aClass, String eventName )
-        {
-            for (Method method : aClass.getMethods())
-            {
-                if (method.getName().equals( eventName ))
-                {
-                    Class[] parameterTypes = method.getParameterTypes();
-                    if (parameterTypes.length > 0 && parameterTypes[0].equals( DomainEventValue.class ))
-                        return method;
-                }
-            }
-            return null;
-        }
-    }
-}
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/replay/EventReplayException.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/replay/EventReplayException.java
deleted file mode 100644
index 4747ebf..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/replay/EventReplayException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.replay;
-
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-
-/**
- * An eventValue replay failed.
- */
-public class EventReplayException
-        extends RuntimeException
-{
-    private DomainEventValue eventValue;
-
-    public EventReplayException( DomainEventValue eventValue, Throwable cause )
-    {
-        super( cause );
-        this.eventValue = eventValue;
-    }
-
-    @Override
-    public String getMessage()
-    {
-        return "Could not replay event:" + eventValue + ", caused by:" + getCause();
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/replay/package.html b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/replay/package.html
deleted file mode 100644
index f0df716..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/replay/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EventSourcing Domain Replay.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/AbstractEventStoreMixin.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/AbstractEventStoreMixin.java
deleted file mode 100644
index bfbb367..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/AbstractEventStoreMixin.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static java.util.Collections.synchronizedList;
-
-/**
- * Base implementation for EventStores.
- */
-public abstract class AbstractEventStoreMixin
-        implements EventStore, EventStream, EventStoreActivation
-{
-    @This
-    protected Identity identity;
-
-    protected Logger logger;
-    protected ValueType domainEventType;
-    protected ValueType eventsType;
-
-    protected Lock lock = new ReentrantLock();
-
-    @Structure
-    protected Module module;
-
-    private ExecutorService transactionNotifier;
-
-    final private List<UnitOfWorkEventsListener> listeners = synchronizedList( new ArrayList<UnitOfWorkEventsListener>() );
-
-    @Override
-    public void activateEventStore() throws Exception
-    {
-        logger = LoggerFactory.getLogger( identity.identity().get() );
-
-        domainEventType = module.valueDescriptor( DomainEventValue.class.getName() ).valueType();
-        eventsType = module.valueDescriptor( UnitOfWorkDomainEventsValue.class.getName() ).valueType();
-
-        transactionNotifier = Executors.newSingleThreadExecutor();
-    }
-
-    @Override
-    public void passivateEventStore() throws Exception
-    {
-        transactionNotifier.shutdown();
-        transactionNotifier.awaitTermination( 10000, TimeUnit.MILLISECONDS );
-    }
-
-    // UnitOfWorkEventsVisitor implementation
-    // This is how transactions are put into the store
-
-
-    @Override
-    public Output<UnitOfWorkDomainEventsValue, IOException> storeEvents()
-    {
-        final Output<UnitOfWorkDomainEventsValue, IOException> storeOutput = storeEvents0();
-
-        return new Output<UnitOfWorkDomainEventsValue, IOException>()
-        {
-            @Override
-            public <SenderThrowableType extends Throwable> void receiveFrom( final Sender<? extends UnitOfWorkDomainEventsValue, SenderThrowableType> sender ) throws IOException, SenderThrowableType
-            {
-                final List<UnitOfWorkDomainEventsValue> events = new ArrayList<UnitOfWorkDomainEventsValue>(  );
-                lock();
-                try
-                {
-                    storeOutput.receiveFrom(new Sender<UnitOfWorkDomainEventsValue, SenderThrowableType>()
-                    {
-                        @Override
-                        public <ReceiverThrowableType extends Throwable> void sendTo( final Receiver<? super UnitOfWorkDomainEventsValue, ReceiverThrowableType> receiver ) throws ReceiverThrowableType, SenderThrowableType
-                        {
-                            sender.sendTo( new Receiver<UnitOfWorkDomainEventsValue, ReceiverThrowableType>()
-                            {
-                                @Override
-                                public void receive( UnitOfWorkDomainEventsValue item ) throws ReceiverThrowableType
-                                {
-                                    receiver.receive( item );
-                                    events.add( item );
-                                }
-                            });
-                        }
-                    });
-
-                } finally
-                {
-                    lock.unlock();
-                }
-
-                // Notify listeners
-                transactionNotifier.submit( new Runnable()
-                {
-                    @Override
-                    public void run()
-                    {
-                        synchronized(listeners)
-                        {
-                            for( UnitOfWorkEventsListener listener : listeners )
-                            {
-                                try
-                                {
-                                    listener.notifyTransactions( events );
-                                } catch( Exception e )
-                                {
-                                    logger.warn( "Could not notify event listener", e );
-                                }
-                            }
-                        }
-                    }
-                } );
-            }
-        };
-    }
-
-    // EventStream implementation
-    @Override
-    public void registerListener( UnitOfWorkEventsListener subscriber )
-    {
-        listeners.add( subscriber );
-    }
-
-    @Override
-    public void unregisterListener( UnitOfWorkEventsListener subscriber )
-    {
-        listeners.remove( subscriber );
-    }
-
-    abstract protected Output<UnitOfWorkDomainEventsValue, IOException> storeEvents0();
-
-    /**
-     * Fix for this bug:
-     * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6822370
-     */
-    protected void lock()
-    {
-        while (true)
-        {
-            try
-            {
-                lock.tryLock( 1000, TimeUnit.MILLISECONDS );
-                break;
-            } catch (InterruptedException e)
-            {
-                // Try again
-            }
-        }
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/EventManagement.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/EventManagement.java
deleted file mode 100644
index 3f994e0..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/EventManagement.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source;
-
-import java.io.IOException;
-import org.qi4j.io.Output;
-
-/**
- * Management interface for EventStores.
- */
-public interface EventManagement
-{
-    /**
-     * Output used to restore events from a backup
-     *
-     * @return The Output function to restore events from a backup.
-     */
-    Output<String, IOException> restore();
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/EventSource.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/EventSource.java
deleted file mode 100644
index 4bb5508..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/EventSource.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source;
-
-import java.io.IOException;
-import org.qi4j.io.Input;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-
-/**
- * An EventSource is a source of events. Events are grouped in the UnitOfWork in which they were created.
- */
-public interface EventSource
-{
-    /**
-     * Get list of UnitOfWorkDomainEventsValue after the given offset.
-     * <p>
-     * To get the first set of events, use 0 as offset parameter to get events from the start.
-     * </p>
-     *
-     * @param offset where in the list of events to start
-     * @param limit maximum number of events returned
-     * @return list of UnitOfWorkDomainEventsValue after the given offset
-     */
-    Input<UnitOfWorkDomainEventsValue, IOException> events( long offset, long limit );
-
-    long count();
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/EventStore.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/EventStore.java
deleted file mode 100644
index ad613fc..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/EventStore.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source;
-
-import java.io.IOException;
-import org.qi4j.io.Output;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-
-/**
- * Store of domain-events.
- */
-public interface EventStore
-{
-    Output<UnitOfWorkDomainEventsValue, IOException> storeEvents();
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/EventStoreActivation.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/EventStoreActivation.java
deleted file mode 100644
index aca9d42..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/EventStoreActivation.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source;
-
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.service.ServiceReference;
-
-public interface EventStoreActivation
-{
-
-    void activateEventStore()
-            throws Exception;
-
-    void passivateEventStore()
-            throws Exception;
-
-    public static class Activator
-            extends ActivatorAdapter<ServiceReference<EventStoreActivation>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<EventStoreActivation> activated )
-                throws Exception
-        {
-            activated.get().activateEventStore();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<EventStoreActivation> passivating )
-                throws Exception
-        {
-            passivating.get().passivateEventStore();
-        }
-
-    }
-
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/EventStream.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/EventStream.java
deleted file mode 100644
index 91f1524..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/EventStream.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source;
-
-/**
- * Stream of event transactions. Registering with a stream will
- * allow the subscriber to get callbacks when new transactions
- * are available. The callbacks are done asynchronously.
- */
-public interface EventStream
-{
-    void registerListener( UnitOfWorkEventsListener listener );
-
-    void unregisterListener( UnitOfWorkEventsListener listener );
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/UnitOfWorkEventsListener.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/UnitOfWorkEventsListener.java
deleted file mode 100644
index df1fbf7..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/UnitOfWorkEventsListener.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source;
-
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-
-/**
- * JAVADOC
- */
-public interface UnitOfWorkEventsListener
-{
-    void notifyTransactions( Iterable<UnitOfWorkDomainEventsValue> transactions );
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/UnitOfWorkEventsVisitor.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/UnitOfWorkEventsVisitor.java
deleted file mode 100644
index 63f0cae..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/UnitOfWorkEventsVisitor.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source;
-
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-
-/**
- * JAVADOC
- */
-public interface UnitOfWorkEventsVisitor
-{
-    boolean visit( UnitOfWorkDomainEventsValue unitOfWorkDomainValue );
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/DomainEventTracker.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/DomainEventTracker.java
deleted file mode 100644
index 4673dfc..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/DomainEventTracker.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source.helper;
-
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.io.Output;
-import org.qi4j.io.Transforms;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-import org.qi4j.library.eventsourcing.domain.source.EventSource;
-import org.qi4j.library.eventsourcing.domain.source.EventStream;
-import org.qi4j.library.eventsourcing.domain.source.UnitOfWorkEventsListener;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Helper that enables a service to easily track transactions.
- * <p>
- * Upon startup
- * the tracker will get all the transactions from the store since the last
- * check, and delegate them to the given Output. It will also register itself
- * with the store so that it can get continuous updates.
- * </p>
- * <p>
- * Then, as transactions come in from the store, they will be processed in real-time.
- * If a transaction is successfully handled the configuration of the service, which must
- * extend DomainEventTrackerConfiguration, will update the marker for the last successfully handled transaction.
- * </p>
- */
-public class DomainEventTracker
-        implements Runnable, UnitOfWorkEventsListener
-{
-    private Configuration<? extends DomainEventTrackerConfiguration> configuration;
-    private final Output<UnitOfWorkDomainEventsValue, ? extends Throwable> output;
-    private EventStream stream;
-    private EventSource source;
-    private boolean started = false;
-    private Logger logger;
-
-    public DomainEventTracker( EventStream stream, EventSource source,
-                               Configuration<? extends DomainEventTrackerConfiguration> configuration,
-                               Output<UnitOfWorkDomainEventsValue, ? extends Throwable> output )
-    {
-        this.stream = stream;
-        this.configuration = configuration;
-        this.output = output;
-        this.source = source;
-
-        logger = LoggerFactory.getLogger( configuration.get().identity().get() );
-    }
-
-    public synchronized void start()
-    {
-        if (!started)
-        {
-            started = true;
-
-            run();
-
-            stream.registerListener( this );
-        }
-    }
-
-    public synchronized void stop()
-    {
-        if (started)
-        {
-            started = false;
-            stream.unregisterListener( this );
-        }
-    }
-
-    @Override
-    public synchronized void run()
-    {
-        // TODO This should optionally use a CircuitBreaker
-        if (started && configuration.get().enabled().get())
-        {
-            Transforms.Counter counter = new Transforms.Counter();
-            try
-            {
-                long currentOffset = configuration.get().lastOffset().get();
-                source.events( currentOffset, Long.MAX_VALUE ).transferTo( Transforms.map( counter, output ) );
-
-                // Save new offset, to be used in next round
-                configuration.get().lastOffset().set( currentOffset+counter.count() );
-                configuration.save();
-            } catch (Throwable throwable)
-            {
-                logger.warn( "Event handling failed", throwable );
-            }
-        }
-    }
-
-    @Override
-    public void notifyTransactions( Iterable<UnitOfWorkDomainEventsValue> transactions )
-    {
-        run();
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/DomainEventTrackerConfiguration.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/DomainEventTrackerConfiguration.java
deleted file mode 100644
index 422ae3d..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/DomainEventTrackerConfiguration.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source.helper;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.configuration.Enabled;
-import org.qi4j.api.property.Property;
-
-/**
- * Configuration that a service doing event tracking must have. Let the configuration
- * of the service extend this one.
- */
-public interface DomainEventTrackerConfiguration
-        extends ConfigurationComposite, Enabled
-{
-    /**
-     * A count of how many events have been read already. Call EventStore.events(lastOffset,{limit}) to get
-     * the next set of events.
-     *
-     * @return count of how many events have been read already.
-     */
-    @UseDefaults
-    Property<Long> lastOffset();
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/EventParameters.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/EventParameters.java
deleted file mode 100644
index 536e68f..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/EventParameters.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source.helper;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-
-/**
- * Utility class to pick out parameters by name or index as strings from a DomainEventValue
- */
-public class EventParameters
-{
-    /**
-     * Get the named parameter from an eventValue.
-     *
-     * @param eventValue eventValue with parameters
-     * @param name  name of parameter
-     * @return the parameter with the given name or null
-     */
-    public static String getParameter( DomainEventValue eventValue, String name )
-    {
-        String parametersJson = eventValue.parameters().get();
-        try
-        {
-            JSONObject jsonObject = new JSONObject( parametersJson );
-            return jsonObject.get( name ).toString();
-        } catch (JSONException e)
-        {
-            return null;
-        }
-    }
-
-    /**
-     * Get parameter with given index.
-     *
-     * @param eventValue eventValue with parameters
-     * @param idx   index of parameter
-     * @return the parameter with the given index or null
-     */
-    public static String getParameter( DomainEventValue eventValue, int idx )
-    {
-        try
-        {
-            String parametersJson = eventValue.parameters().get();
-            JSONObject jsonObject = new JSONObject( parametersJson );
-            return jsonObject.get( "param" + idx ).toString();
-        } catch (JSONException e)
-        {
-            return null;
-        }
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/EventRouter.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/EventRouter.java
deleted file mode 100644
index eb20ab4..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/EventRouter.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source.helper;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-import org.qi4j.functional.Specification;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-
-/**
- * Event handling router. Add specification-&gt;receiver routes. When an event comes in
- * the router will ask each specification if it matches, and if so, delegate to the
- * receiver and return whether it successfully handled it or not. If no routes match,
- * delegate to the default receiver
- */
-public class EventRouter<T extends Throwable>
-        implements Output<DomainEventValue, T>, Receiver<UnitOfWorkDomainEventsValue, T>
-{
-    private Map<Specification<DomainEventValue>, Receiver<DomainEventValue, T>> routeEvent = new LinkedHashMap<Specification<DomainEventValue>, Receiver<DomainEventValue, T>>();
-
-    private Receiver<DomainEventValue, T> defaultReceiver = new Receiver<DomainEventValue, T>()
-    {
-        @Override
-        public void receive( DomainEventValue item ) throws T
-        {
-            // Do nothing;
-        }
-    };
-
-    public EventRouter route( Specification<DomainEventValue> specification, Receiver<DomainEventValue, T> receiver )
-    {
-        routeEvent.put( specification, receiver );
-
-        return this;
-    }
-
-    public EventRouter defaultReceiver( Receiver<DomainEventValue, T> defaultReceiver )
-    {
-        this.defaultReceiver = defaultReceiver;
-        return this;
-    }
-
-    @Override
-    public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends DomainEventValue, SenderThrowableType> sender ) throws T, SenderThrowableType
-    {
-        sender.sendTo( new Receiver<DomainEventValue, T>()
-        {
-            @Override
-            public void receive( DomainEventValue item ) throws T
-            {
-                for( Map.Entry<Specification<DomainEventValue>, Receiver<DomainEventValue, T>> specificationReceiverEntry : routeEvent.entrySet() )
-                {
-                    if( specificationReceiverEntry.getKey().satisfiedBy( item ) )
-                    {
-                        specificationReceiverEntry.getValue().receive( item );
-                        return;
-                    }
-                }
-
-                // No match, use default
-                defaultReceiver.receive( item );
-            }
-        } );
-    }
-
-    @Override
-    public void receive( final UnitOfWorkDomainEventsValue item ) throws T
-    {
-        receiveFrom( new Sender<DomainEventValue, T>()
-        {
-            @Override
-            public <ReceiverThrowableType extends Throwable> void sendTo( Receiver<? super DomainEventValue, ReceiverThrowableType> receiver ) throws ReceiverThrowableType, T
-            {
-
-                for( DomainEventValue domainEventValue : item.events().get() )
-                {
-                    receiver.receive( domainEventValue );
-                }
-            }
-        } );
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/Events.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/Events.java
deleted file mode 100644
index 238b85d..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/Events.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source.helper;
-
-import java.lang.reflect.Method;
-import java.util.Date;
-import org.qi4j.api.util.Methods;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-
-import static org.qi4j.functional.Iterables.map;
-
-/**
- * Helper methods for working with Iterables of DomainEvents and UnitOfWorkDomainEventsValue.
- */
-public class Events
-{
-    public static Iterable<DomainEventValue> events( Iterable<UnitOfWorkDomainEventsValue> transactions )
-    {
-        return Iterables.flattenIterables( Iterables.map( new Function<UnitOfWorkDomainEventsValue, Iterable<DomainEventValue>>()
-        {
-            @Override
-            public Iterable<DomainEventValue> map( UnitOfWorkDomainEventsValue unitOfWorkDomainEventsValue )
-            {
-                return unitOfWorkDomainEventsValue.events().get();
-            }
-        }, transactions ) );
-    }
-
-    public static Iterable<DomainEventValue> events( UnitOfWorkDomainEventsValue... unitOfWorkDomainValues )
-    {
-        return events( Iterables.iterable( unitOfWorkDomainValues ) );
-    }
-
-    // Common specifications
-    public static Specification<UnitOfWorkDomainEventsValue> afterDate( final Date afterDate )
-    {
-        return new Specification<UnitOfWorkDomainEventsValue>()
-        {
-            @Override
-            public boolean satisfiedBy( UnitOfWorkDomainEventsValue eventValue )
-            {
-                return eventValue.timestamp().get() > afterDate.getTime();
-            }
-        };
-    }
-
-    public static Specification<UnitOfWorkDomainEventsValue> beforeDate( final Date afterDate )
-    {
-        return new Specification<UnitOfWorkDomainEventsValue>()
-        {
-            @Override
-            public boolean satisfiedBy( UnitOfWorkDomainEventsValue eventValue )
-            {
-                return eventValue.timestamp().get() < afterDate.getTime();
-            }
-        };
-    }
-
-    public static Specification<UnitOfWorkDomainEventsValue> withUsecases( final String... names )
-    {
-        return new Specification<UnitOfWorkDomainEventsValue>()
-        {
-            @Override
-            public boolean satisfiedBy( UnitOfWorkDomainEventsValue eventValue )
-            {
-                for (String name : names)
-                {
-                    if (eventValue.usecase().get().equals( name ))
-                        return true;
-                }
-                return false;
-            }
-        };
-    }
-
-    public static Specification<UnitOfWorkDomainEventsValue> byUser( final String... by )
-    {
-        return new Specification<UnitOfWorkDomainEventsValue>()
-        {
-            @Override
-            public boolean satisfiedBy( UnitOfWorkDomainEventsValue eventValue )
-            {
-                for (String user : by)
-                {
-                    if (eventValue.user().get().equals( user ))
-                        return true;
-                }
-                return false;
-            }
-        };
-    }
-
-    public static Specification<DomainEventValue> withNames( final Iterable<String> names )
-    {
-        return new Specification<DomainEventValue>()
-        {
-            @Override
-            public boolean satisfiedBy( DomainEventValue eventValue )
-            {
-                for (String name : names)
-                {
-                    if (eventValue.name().get().equals( name ))
-                        return true;
-                }
-                return false;
-            }
-        };
-    }
-
-    public static Specification<DomainEventValue> withNames( final String... names )
-    {
-        return new Specification<DomainEventValue>()
-        {
-            @Override
-            public boolean satisfiedBy( DomainEventValue eventValue )
-            {
-                for (String name : names)
-                {
-                    if (eventValue.name().get().equals( name ))
-                        return true;
-                }
-                return false;
-            }
-        };
-    }
-
-    public static Specification<DomainEventValue> withNames( final Class eventClass )
-    {
-        return Events.withNames( map( new Function<Method, String>()
-        {
-            @Override
-            public String map( Method method )
-            {
-                return method.getName();
-            }
-        }, Iterables.toList( Methods.METHODS_OF.map( eventClass ) ) ));
-    }
-
-    public static Specification<DomainEventValue> onEntities( final String... entities )
-    {
-        return new Specification<DomainEventValue>()
-        {
-            @Override
-            public boolean satisfiedBy( DomainEventValue eventValue )
-            {
-                for (String entity : entities)
-                {
-                    if (eventValue.entityId().get().equals( entity ))
-                        return true;
-                }
-                return false;
-            }
-        };
-    }
-
-    public static Specification<DomainEventValue> onEntityTypes( final String... entityTypes )
-    {
-        return new Specification<DomainEventValue>()
-        {
-            @Override
-            public boolean satisfiedBy( DomainEventValue eventValue )
-            {
-                for (String entityType : entityTypes)
-                {
-                    if (eventValue.entityType().get().equals( entityType ))
-                        return true;
-                }
-                return false;
-            }
-        };
-    }
-
-    public static Specification<DomainEventValue> paramIs( final String name, final String value )
-    {
-        return new Specification<DomainEventValue>()
-        {
-            @Override
-            public boolean satisfiedBy( DomainEventValue eventValue )
-            {
-                return EventParameters.getParameter( eventValue, name ).equals( value );
-            }
-        };
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/UnitOfWorkRouter.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/UnitOfWorkRouter.java
deleted file mode 100644
index 0375b50..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/UnitOfWorkRouter.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source.helper;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-import org.qi4j.functional.Specification;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-
-/**
- * UnitOfWork handling router. Add specification-&gt;receiver routes. When a UnitOfWorkEDomainEventsValue comes in
- * the router will ask each specification if it matches, and if so, delegate to the
- * receiver. If no routes match, delegate to the default receiver.
- */
-public class UnitOfWorkRouter<T extends Throwable>
-    implements Output<UnitOfWorkDomainEventsValue, T>
-{
-    private Map<Specification<UnitOfWorkDomainEventsValue>, Receiver<UnitOfWorkDomainEventsValue, T>> routes = new LinkedHashMap<Specification<UnitOfWorkDomainEventsValue>, Receiver<UnitOfWorkDomainEventsValue, T>>(  );
-
-    private Receiver<UnitOfWorkDomainEventsValue, T> defaultReceiver = new Receiver<UnitOfWorkDomainEventsValue, T>()
-    {
-        @Override
-        public void receive( UnitOfWorkDomainEventsValue item ) throws T
-        {
-            // Do nothing;
-        }
-    };
-
-    public UnitOfWorkRouter route( Specification<UnitOfWorkDomainEventsValue> specification, Receiver<UnitOfWorkDomainEventsValue, T> receiver)
-    {
-        routes.put(specification, receiver);
-
-        return this;
-    }
-
-    public UnitOfWorkRouter defaultReceiver(Receiver<UnitOfWorkDomainEventsValue, T> defaultReceiver)
-    {
-        this.defaultReceiver = defaultReceiver;
-        return this;
-    }
-
-    @Override
-    public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends UnitOfWorkDomainEventsValue, SenderThrowableType> sender ) throws T, SenderThrowableType
-    {
-        sender.sendTo( new Receiver<UnitOfWorkDomainEventsValue, T>()
-        {
-            @Override
-            public void receive( UnitOfWorkDomainEventsValue item ) throws T
-            {
-                for( Map.Entry<Specification<UnitOfWorkDomainEventsValue>, Receiver<UnitOfWorkDomainEventsValue, T>> specificationReceiverEntry : routes.entrySet() )
-                {
-                    if (specificationReceiverEntry.getKey().satisfiedBy( item ))
-                    {
-                        specificationReceiverEntry.getValue().receive( item );
-                        return;
-                    }
-                }
-
-                // No match, use default
-                defaultReceiver.receive( item );
-            }
-        });
-    }
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/package.html b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/package.html
deleted file mode 100644
index 8bf2f63..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/helper/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EventSourcing Domain Source Helpers.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/memory/MemoryEventStoreService.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/memory/MemoryEventStoreService.java
deleted file mode 100644
index df30fa1..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/memory/MemoryEventStoreService.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source.memory;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-import org.qi4j.library.eventsourcing.domain.source.AbstractEventStoreMixin;
-import org.qi4j.library.eventsourcing.domain.source.EventSource;
-import org.qi4j.library.eventsourcing.domain.source.EventStore;
-import org.qi4j.library.eventsourcing.domain.source.EventStoreActivation;
-import org.qi4j.library.eventsourcing.domain.source.EventStream;
-
-/**
- * In-Memory EventStore. Mainly used for testing.
- */
-@Mixins(MemoryEventStoreService.MemoryEventStoreMixin.class)
-@Activators( EventStoreActivation.Activator.class )
-public interface MemoryEventStoreService
-        extends EventSource, EventStore, EventStream, EventStoreActivation, ServiceComposite
-{
-    abstract class MemoryEventStoreMixin
-            extends AbstractEventStoreMixin
-            implements EventSource, EventStoreActivation
-    {
-        // This list holds all transactions
-        private LinkedList<UnitOfWorkDomainEventsValue> store = new LinkedList<UnitOfWorkDomainEventsValue>();
-
-        private long currentCount = 0;
-
-        public Input<UnitOfWorkDomainEventsValue, IOException> events( final long offset, final long limit )
-        {
-            if (offset < 0 || offset > count())
-                throw new IllegalArgumentException( "Offset must be between 0 and current number of events in the store" );
-
-            if (limit <= 0 )
-                throw new IllegalArgumentException( "Limit must be above 0" );
-
-            return new Input<UnitOfWorkDomainEventsValue, IOException>()
-            {
-                @Override
-                public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super UnitOfWorkDomainEventsValue, ReceiverThrowableType> output ) throws IOException, ReceiverThrowableType
-                {
-                    // Lock store first
-                    lock.lock();
-                    try
-                    {
-                        output.receiveFrom( new Sender<UnitOfWorkDomainEventsValue, IOException>()
-                        {
-                            @Override
-                            public <ReceiverThrowableType extends Throwable> void sendTo( Receiver<? super UnitOfWorkDomainEventsValue, ReceiverThrowableType> receiver ) throws ReceiverThrowableType, IOException
-                            {
-                                ListIterator<UnitOfWorkDomainEventsValue> iterator = store.listIterator( (int) offset );
-
-                                long count = 0;
-
-                                while( iterator.hasNext() && count < limit )
-                                {
-                                    UnitOfWorkDomainEventsValue next = iterator.next();
-                                    receiver.receive( next );
-                                    count++;
-                                }
-                            }
-                        } );
-                    } finally
-                    {
-                        lock.unlock();
-                    }
-                }
-            };
-        }
-
-        @Override
-        public long count()
-        {
-            return currentCount;
-        }
-
-        @Override
-        protected Output<UnitOfWorkDomainEventsValue, IOException> storeEvents0()
-        {
-            return new Output<UnitOfWorkDomainEventsValue, IOException>()
-            {
-                @Override
-                public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends UnitOfWorkDomainEventsValue, SenderThrowableType> sender ) throws IOException, SenderThrowableType
-                {
-                    final List<UnitOfWorkDomainEventsValue> newEvents = new ArrayList<UnitOfWorkDomainEventsValue>(  );
-                    sender.sendTo( new Receiver<UnitOfWorkDomainEventsValue, IOException>()
-                    {
-                        @Override
-                        public void receive( UnitOfWorkDomainEventsValue item ) throws IOException
-                        {
-                            newEvents.add( item );
-                        }
-                    });
-                    store.addAll( newEvents );
-                    currentCount += newEvents.size();
-                }
-            };
-        }
-    }
-}
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/memory/package.html b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/memory/package.html
deleted file mode 100644
index 2fc27f2..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/memory/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>In-Memory EventStore.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/package.html b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/package.html
deleted file mode 100644
index c9754bb..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/source/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EventSourcing Domain Source.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/spi/CurrentUser.java b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/spi/CurrentUser.java
deleted file mode 100644
index ecfe05f..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/spi/CurrentUser.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.spi;
-
-/**
- * Return username of current user. This needs to be implemented and provided
- * as a service so that the DomainEventFactory can associate events with a particular user.
- */
-public interface CurrentUser
-{
-    String getCurrentUser();
-}
diff --git a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/spi/package.html b/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/spi/package.html
deleted file mode 100644
index 1ad52b2..0000000
--- a/libraries/eventsourcing/src/main/java/org/qi4j/library/eventsourcing/domain/spi/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>EventSourcing Domain SPI.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/application/ApplicationEventTest.java b/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/application/ApplicationEventTest.java
deleted file mode 100644
index 7ccf0a2..0000000
--- a/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/application/ApplicationEventTest.java
+++ /dev/null
@@ -1,227 +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.qi4j.library.eventsourcing.application;
-
-import org.junit.Test;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-import org.qi4j.library.eventsourcing.application.api.ApplicationEvent;
-import org.qi4j.library.eventsourcing.application.api.TransactionApplicationEvents;
-import org.qi4j.library.eventsourcing.application.factory.ApplicationEventCreationConcern;
-import org.qi4j.library.eventsourcing.application.source.ApplicationEventSource;
-import org.qi4j.library.eventsourcing.application.source.helper.ApplicationEventParameters;
-import org.qi4j.library.eventsourcing.application.source.memory.MemoryApplicationEventStoreService;
-import org.qi4j.library.eventsourcing.bootstrap.EventsourcingAssembler;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import java.io.IOException;
-import java.security.Principal;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * User signup usecase with optional mailing list subscription.
- * Subscription is not stored in domain model but is available via application events feed.
- */
-public class ApplicationEventTest
-    extends AbstractQi4jTest
-{
-    @Service
-    ApplicationEventSource eventSource;
-
-    @Override
-    public void assemble( ModuleAssembly module ) throws AssemblyException
-    {
-        // START SNIPPET: assemblyAE
-        new EventsourcingAssembler()
-                .withApplicationEvents()
-                .withCurrentUserFromUOWPrincipal()
-                .assemble(module);
-        // END SNIPPET: assemblyAE
-
-        // START SNIPPET: storeAE
-        module.services( MemoryApplicationEventStoreService.class );
-        // END SNIPPET: storeAE
-
-        new EntityTestAssembler().assemble( module );
-
-        // START SNIPPET: concernAE
-        module.transients( Users.class ).withConcerns( ApplicationEventCreationConcern.class );
-        // END SNIPPET: concernAE
-
-        module.entities( UserEntity.class );
-
-    }
-
-
-    @Test
-    public void testApplicationEvent() throws Exception
-    {
-        Users users = module.newTransient( Users.class );
-
-        Principal administratorPrincipal = new Principal()
-        {
-            @Override
-            public String getName()
-            {
-                return "administrator";
-            }
-        };
-
-        UnitOfWork uow1 = module.newUnitOfWork( UsecaseBuilder.newUsecase( "User signup" ) );
-        uow1.setMetaInfo( administratorPrincipal );
-        users.signup( null, "user1", Arrays.asList( "news-a", "news-b" ) );
-        uow1.complete();
-
-        Thread.sleep( 1 ); // For UoWs not getting the same `currentTime`
-
-        UnitOfWork uow2 = module.newUnitOfWork();
-        uow2.setMetaInfo( administratorPrincipal );
-        users.signup( null, "user2", Collections.EMPTY_LIST );
-        uow2.complete();
-
-        Thread.sleep( 1 ); // For UoWs not getting the same `currentTime`
-
-        UnitOfWork uow3 = module.newUnitOfWork();
-        uow3.setMetaInfo( administratorPrincipal );
-        users.signup( null, "user3", Collections.singletonList( "news-c" ) );
-        uow3.complete();
-
-        // receive events from uow2 and later forwards
-        EventsInbox afterInbox = new EventsInbox();
-        eventSource.transactionsAfter( uow2.currentTime() - 1, Integer.MAX_VALUE ).transferTo( afterInbox );
-
-        assertEquals( 2, afterInbox.getEvents().size() );
-
-        ApplicationEvent signupEvent2 = afterInbox.getEvents().get( 0 ).events().get().get( 0 );
-        ApplicationEvent signupEvent3 = afterInbox.getEvents().get( 1 ).events().get().get( 0 );
-
-        assertEquals( "signup", signupEvent2.name().get() );
-        assertEquals( "user2", ApplicationEventParameters.getParameter( signupEvent2, "param1" ) );
-        assertEquals( "[]", ApplicationEventParameters.getParameter( signupEvent2, "param2" ) );
-
-        assertEquals( "signup", signupEvent3.name().get() );
-        assertEquals( "user3", ApplicationEventParameters.getParameter( signupEvent3, "param1" ) );
-        assertEquals( "[\"news-c\"]", ApplicationEventParameters.getParameter( signupEvent3, "param2" ) );
-
-        // receive events from uow2 backwards
-        EventsInbox beforeInbox = new EventsInbox();
-        eventSource.transactionsBefore( uow3.currentTime(), Integer.MAX_VALUE ).transferTo( beforeInbox );
-
-        assertEquals( 2, beforeInbox.getEvents().size() );
-
-        signupEvent2 = beforeInbox.getEvents().get( 0 ).events().get().get( 0 );
-        ApplicationEvent signupEvent1 = beforeInbox.getEvents().get( 1 ).events().get().get( 0 );
-
-        assertEquals( "signup", signupEvent2.name().get() );
-        assertEquals( "user2", ApplicationEventParameters.getParameter( signupEvent2, "param1" ) );
-        assertEquals( "[]", ApplicationEventParameters.getParameter( signupEvent2, "param2" ) );
-
-        assertEquals( "signup", signupEvent1.name().get());
-        assertEquals( "user1", ApplicationEventParameters.getParameter( signupEvent1, "param1" ) );
-        assertEquals( "[\"news-a\",\"news-b\"]", ApplicationEventParameters.getParameter( signupEvent1, "param2" ) );
-    }
-
-    static class EventsInbox implements Output<TransactionApplicationEvents, RuntimeException>
-    {
-        private List<TransactionApplicationEvents> events = new LinkedList<>();
-
-        @Override
-        public <SenderThrowableType extends Throwable> void receiveFrom( Sender<? extends TransactionApplicationEvents, SenderThrowableType> sender )
-            throws RuntimeException, SenderThrowableType
-        {
-            try
-            {
-                sender.sendTo( new Receiver<TransactionApplicationEvents, Throwable>()
-                {
-                    @Override
-                    public void receive( TransactionApplicationEvents item ) throws Throwable
-                    {
-                        events.add(item);
-                    }
-                });
-
-            }
-            catch( Throwable throwable )
-            {
-                throwable.printStackTrace();
-            }
-        }
-
-        public List<TransactionApplicationEvents> getEvents()
-        {
-            return events;
-        }
-    }
-
-    // START SNIPPET: methodAE
-    @Mixins( Users.Mixin.class )
-    public interface Users extends TransientComposite
-    {
-        void signup( @Optional ApplicationEvent evt, String username, List<String> mailinglists );
-        // END SNIPPET: methodAE
-
-        abstract class Mixin implements Users
-        {
-            @Structure
-            UnitOfWorkFactory uowFactory;
-
-            @Override
-            public void signup( ApplicationEvent evt, String username, List<String> mailinglists )
-            {
-                if (evt == null)
-                {
-                    UnitOfWork uow = uowFactory.currentUnitOfWork();
-
-                    EntityBuilder<UserEntity> builder = uow.newEntityBuilder( UserEntity.class );
-                    builder.instance().username().set( username );
-                    builder.newInstance();
-                }
-            }
-        }
-    }
-
-    public interface UserEntity
-            extends EntityComposite
-    {
-        @UseDefaults
-        Property<String> username();
-    }
-}
diff --git a/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/DomainEventTest.java b/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/DomainEventTest.java
deleted file mode 100644
index 0d30d9e..0000000
--- a/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/DomainEventTest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.eventsourcing.domain;
-
-import org.junit.Test;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ImportedServiceDeclaration;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Function;
-import org.qi4j.io.Outputs;
-import org.qi4j.io.Transforms;
-import org.qi4j.library.eventsourcing.bootstrap.EventsourcingAssembler;
-import org.qi4j.library.eventsourcing.domain.api.DomainEvent;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-import org.qi4j.library.eventsourcing.domain.factory.CurrentUserUoWPrincipal;
-import org.qi4j.library.eventsourcing.domain.factory.DomainEventCreationConcern;
-import org.qi4j.library.eventsourcing.domain.factory.DomainEventFactoryService;
-import org.qi4j.library.eventsourcing.domain.source.EventSource;
-import org.qi4j.library.eventsourcing.domain.source.memory.MemoryEventStoreService;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import java.io.IOException;
-import java.security.Principal;
-
-/**
- * JAVADOC
- */
-public class DomainEventTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module ) throws AssemblyException
-    {
-        new EntityTestAssembler(  ).assemble( module );
-
-        // START SNIPPET: assemblyDE
-        new EventsourcingAssembler()
-                .withDomainEvents()
-                .withCurrentUserFromUOWPrincipal()
-                .assemble(module);
-        // END SNIPPET: assemblyDE
-
-        // START SNIPPET: storeDE
-        module.services( MemoryEventStoreService.class );
-        // END SNIPPET: storeDE
-
-        // START SNIPPET: concernDE
-        module.entities( TestEntity.class ).withConcerns(DomainEventCreationConcern.class);
-        // END SNIPPET: concernDE
-    }
-
-    @Test
-    public void testDomainEvent() throws UnitOfWorkCompletionException, IOException
-    {
-        // Set principal for the UoW
-        Principal administratorPrincipal = new Principal()
-        {
-            public String getName()
-            {
-                return "administrator";
-            }
-        };
-
-        // Perform UoW with usecase defined
-        UnitOfWork uow = module.newUnitOfWork( UsecaseBuilder.newUsecase( "Change description" ));
-        uow.setMetaInfo( administratorPrincipal );
-
-        TestEntity entity = uow.newEntity( TestEntity.class );
-        entity.changedDescription( "New description" );
-        uow.complete();
-
-        // Print events
-        EventSource source = (EventSource) module.findService( EventSource.class ).get();
-
-        source.events( 0, Long.MAX_VALUE ).transferTo( Transforms.map( new Function<UnitOfWorkDomainEventsValue, String>()
-                {
-                    public String map( UnitOfWorkDomainEventsValue unitOfWorkDomainEventsValue )
-                    {
-                        return unitOfWorkDomainEventsValue.toString();
-                    }
-                }, Outputs.systemOut() ));
-    }
-
-    // START SNIPPET: methodDE
-    @Mixins( TestEntity.Mixin.class )
-    public interface TestEntity
-        extends EntityComposite
-    {
-        @UseDefaults
-        Property<String> description();
-
-        @DomainEvent
-        void changedDescription( String newName );
-
-        abstract class Mixin
-            implements TestEntity
-        {
-            public void changedDescription( String newName )
-            {
-                description().set( newName );
-            }
-        }
-    }
-    // END SNIPPET: methodDE
-}
diff --git a/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/source/helper/DomainEventTrackerTest.java b/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/source/helper/DomainEventTrackerTest.java
deleted file mode 100644
index 6976a54..0000000
--- a/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/source/helper/DomainEventTrackerTest.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source.helper;
-
-import java.io.IOException;
-import java.security.Principal;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ImportedServiceDeclaration;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Function;
-import org.qi4j.io.Output;
-import org.qi4j.io.Outputs;
-import org.qi4j.io.Transforms;
-import org.qi4j.library.eventsourcing.domain.api.DomainEvent;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-import org.qi4j.library.eventsourcing.domain.factory.CurrentUserUoWPrincipal;
-import org.qi4j.library.eventsourcing.domain.factory.DomainEventCreationConcern;
-import org.qi4j.library.eventsourcing.domain.factory.DomainEventFactoryService;
-import org.qi4j.library.eventsourcing.domain.source.EventSource;
-import org.qi4j.library.eventsourcing.domain.source.EventStream;
-import org.qi4j.library.eventsourcing.domain.source.memory.MemoryEventStoreService;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-public class DomainEventTrackerTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module ) throws AssemblyException
-    {
-        new EntityTestAssembler(  ).assemble( module );
-
-        module.values( DomainEventValue.class, UnitOfWorkDomainEventsValue.class );
-        module.services( MemoryEventStoreService.class );
-        module.services( DomainEventFactoryService.class );
-        module.importedServices( CurrentUserUoWPrincipal.class ).importedBy( ImportedServiceDeclaration.NEW_OBJECT );
-        module.objects( CurrentUserUoWPrincipal.class );
-
-        module.entities( TestEntity.class ).withConcerns( DomainEventCreationConcern.class );
-
-        module.services( EventLoggingService.class ).instantiateOnStartup();
-        module.entities( DomainEventTrackerConfiguration.class );
-    }
-
-    @Test
-    public void testDomainEvent() throws UnitOfWorkCompletionException, IOException
-    {
-        UnitOfWork uow = module.newUnitOfWork( UsecaseBuilder.newUsecase( "Change description" ));
-        uow.setMetaInfo( new Principal()
-        {
-            public String getName()
-            {
-                return "administrator";
-            }
-        });
-
-        TestEntity entity = uow.newEntity( TestEntity.class );
-        entity.changeDescription( "New description" );
-        uow.complete();
-
-        try
-        {
-            Thread.sleep( 5000 );
-        } catch (InterruptedException e)
-        {
-            e.printStackTrace();
-        }
-    }
-
-    @Mixins( TestEntity.Mixin.class )
-    public interface TestEntity
-        extends EntityComposite
-    {
-        @UseDefaults
-        Property<String> description();
-
-        @DomainEvent
-        void changeDescription( String newName );
-
-        abstract class Mixin
-            implements TestEntity
-        {
-            public void changeDescription( String newName )
-            {
-                description().set( newName );
-            }
-        }
-    }
-
-    @Mixins(EventLoggingService.Mixin.class)
-    @Activators( EventLoggingService.Activator.class )
-    public interface EventLoggingService
-        extends ServiceComposite, Configuration<DomainEventTrackerConfiguration>
-    {
-        
-        void startTracker();
-        
-        void stopTracker();
-        
-        public class Activator
-                extends ActivatorAdapter<ServiceReference<EventLoggingService>>
-        {
-
-            @Override
-            public void afterActivation( ServiceReference<EventLoggingService> activated )
-                    throws Exception
-            {
-                activated.get().startTracker();
-            }
-
-            @Override
-            public void beforePassivation( ServiceReference<EventLoggingService> passivating )
-                    throws Exception
-            {
-                passivating.get().stopTracker();
-            }
-
-        }
-        
-        public abstract class Mixin implements EventLoggingService
-        {
-            DomainEventTracker tracker;
-
-            @This
-            Configuration<DomainEventTrackerConfiguration> config;
-
-            @Service
-            EventStream eventStream;
-
-            @Service
-            EventSource eventSource;
-
-            public void startTracker()
-            {
-                config.get().enabled().set( true );
-
-               Output<UnitOfWorkDomainEventsValue,RuntimeException> map = Transforms.map( new Function<UnitOfWorkDomainEventsValue, String>()
-                       {
-                           public String map( UnitOfWorkDomainEventsValue unitOfWorkDomainEventsValue )
-                           {
-                               return unitOfWorkDomainEventsValue.toString();
-                           }
-                       }, Outputs.systemOut() );
-               tracker = new DomainEventTracker(eventStream, eventSource, config, map);
-
-                tracker.start();
-            }
-
-            public void stopTracker()
-            {
-                tracker.stop();
-            }
-        }
-    }
-}
diff --git a/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/source/helper/EventRouterTest.java b/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/source/helper/EventRouterTest.java
deleted file mode 100644
index 76921fd..0000000
--- a/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/source/helper/EventRouterTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.eventsourcing.domain.source.helper;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.io.Inputs;
-import org.qi4j.io.Receiver;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-
-import static org.junit.Assert.assertEquals;
-import static org.qi4j.test.util.JSONAssert.jsonObjectsEquals;
-
-public class EventRouterTest
-{
-    private List<UnitOfWorkDomainEventsValue> list;
-
-    @Before
-    public void testData()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module ) throws AssemblyException
-            {
-                module.values( UnitOfWorkDomainEventsValue.class, DomainEventValue.class );
-            }
-        };
-
-        list = new ArrayList<UnitOfWorkDomainEventsValue>(  );
-        {
-            ValueBuilder<UnitOfWorkDomainEventsValue> builder = assembler.module().newValueBuilder( UnitOfWorkDomainEventsValue.class );
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test1" ) );
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test2" ) );
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test3" ) );
-            builder.prototype().version().set( "1.0" );
-            builder.prototype().timestamp().set( System.currentTimeMillis() );
-            builder.prototype().usecase().set( "Test" );
-            list.add( builder.newInstance() );
-        }
-        {
-            ValueBuilder<UnitOfWorkDomainEventsValue> builder = assembler.module().newValueBuilder( UnitOfWorkDomainEventsValue.class );
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test4" ) );
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test5" ) );
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test6" ) );
-            builder.prototype().version().set( "1.0" );
-            builder.prototype().timestamp().set( System.currentTimeMillis() );
-            builder.prototype().usecase().set( "Test2" );
-            list.add( builder.newInstance() );
-        }
-    }
-
-    private DomainEventValue newDomainEvent( SingletonAssembler assembler, String name )
-    {
-        ValueBuilder<DomainEventValue> eventBuilder = assembler.module().newValueBuilder( DomainEventValue.class );
-        eventBuilder.prototype().entityId().set( "123" );
-        eventBuilder.prototype().entityType().set( "Foo" );
-        eventBuilder.prototype().parameters().set( "{}" );
-        eventBuilder.prototype().name().set( name );
-        return eventBuilder.newInstance();
-    }
-
-    @Test
-    public void testRouter() throws IOException, JSONException
-    {
-        final List<DomainEventValue> matched = new ArrayList<DomainEventValue>(  );
-        EventRouter<IOException> router = new EventRouter<IOException>();
-        router.route( Events.withNames( "Test1", "Test2" ), new Receiver<DomainEventValue,IOException>()
-        {
-            @Override
-            public void receive( DomainEventValue item ) throws IOException
-            {
-                matched.add(item);
-            }
-        });
-
-        Inputs.iterable( Events.events( list ) ).transferTo( router );
-
-        assertEquals( 2, matched.size() );
-        jsonObjectsEquals( new JSONObject( matched.get( 0 ).toString() ),
-                                      new JSONObject( "{\"name\":\"Test1\",\"entityType\":\"Foo\",\"entityId\":\"123\",\"parameters\":\"{}\"}" ) );
-        jsonObjectsEquals( new JSONObject( matched.get( 1 ).toString() ),
-                                      new JSONObject( "{\"name\":\"Test2\",\"entityType\":\"Foo\",\"entityId\":\"123\",\"parameters\":\"{}\"}" ) );
-    }
-}
diff --git a/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/source/helper/EventsTest.java b/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/source/helper/EventsTest.java
deleted file mode 100644
index b21733d..0000000
--- a/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/source/helper/EventsTest.java
+++ /dev/null
@@ -1,101 +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.qi4j.library.eventsourcing.domain.source.helper;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.functional.Iterables.count;
-import static org.qi4j.io.Inputs.iterable;
-import static org.qi4j.io.Outputs.systemOut;
-import static org.qi4j.library.eventsourcing.domain.source.helper.Events.events;
-
-/**
- * TODO
- */
-public class EventsTest
-{
-    private List<UnitOfWorkDomainEventsValue> list;
-
-    @Before
-    public void testData()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module ) throws AssemblyException
-            {
-                module.values( UnitOfWorkDomainEventsValue.class, DomainEventValue.class );
-            }
-        };
-
-        list = new ArrayList<UnitOfWorkDomainEventsValue>(  );
-        {
-            ValueBuilder<UnitOfWorkDomainEventsValue> builder = assembler.module().newValueBuilder( UnitOfWorkDomainEventsValue.class );
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test1" ) );
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test2" ) );
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test3" ) );
-            builder.prototype().version().set( "1.0" );
-            builder.prototype().timestamp().set( System.currentTimeMillis() );
-            builder.prototype().usecase().set( "Test" );
-            list.add( builder.newInstance() );
-        }
-        {
-            ValueBuilder<UnitOfWorkDomainEventsValue> builder = assembler.module().newValueBuilder( UnitOfWorkDomainEventsValue.class );
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test4" ) );
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test5" ) );
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test6" ) );
-            builder.prototype().version().set( "1.0" );
-            builder.prototype().timestamp().set( System.currentTimeMillis() );
-            builder.prototype().usecase().set( "Test2" );
-            list.add( builder.newInstance() );
-        }
-    }
-
-    private DomainEventValue newDomainEvent( SingletonAssembler assembler, String name )
-    {
-        ValueBuilder<DomainEventValue> eventBuilder = assembler.module().newValueBuilder( DomainEventValue.class );
-        eventBuilder.prototype().entityId().set( "123" );
-        eventBuilder.prototype().entityType().set( "Foo" );
-        eventBuilder.prototype().parameters().set( "{}" );
-        eventBuilder.prototype().name().set( name );
-        return eventBuilder.newInstance();
-    }
-
-    @Test
-    public void testIterablesEvents()
-    {
-        assertThat( count( events( list ) ), equalTo( 6L ) );
-
-        iterable( events( list ) ).transferTo( systemOut() );
-    }
-}
diff --git a/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/source/helper/UnitOfWorkRouterTest.java b/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/source/helper/UnitOfWorkRouterTest.java
deleted file mode 100644
index 5fa3a06..0000000
--- a/libraries/eventsourcing/src/test/java/org/qi4j/library/eventsourcing/domain/source/helper/UnitOfWorkRouterTest.java
+++ /dev/null
@@ -1,153 +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.qi4j.library.eventsourcing.domain.source.helper;
-
-import org.hamcrest.CoreMatchers;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.io.Inputs;
-import org.qi4j.io.Receiver;
-import org.qi4j.library.eventsourcing.domain.api.DomainEventValue;
-import org.qi4j.library.eventsourcing.domain.api.UnitOfWorkDomainEventsValue;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * TODO
- */
-public class UnitOfWorkRouterTest
-{
-    private List<UnitOfWorkDomainEventsValue> list;
-
-    @Before
-    public void testData()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module ) throws AssemblyException
-            {
-                module.values( UnitOfWorkDomainEventsValue.class, DomainEventValue.class );
-            }
-        };
-
-        list = new ArrayList<UnitOfWorkDomainEventsValue>(  );
-        {
-            ValueBuilder<UnitOfWorkDomainEventsValue> builder = assembler.module().newValueBuilder( UnitOfWorkDomainEventsValue.class );
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test1" ));
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test2" ));
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test3" ));
-            builder.prototype().version().set( "1.0" );
-            builder.prototype().timestamp().set( System.currentTimeMillis() );
-            builder.prototype().usecase().set( "Test" );
-            list.add( builder.newInstance() );
-        }
-        {
-            ValueBuilder<UnitOfWorkDomainEventsValue> builder = assembler.module().newValueBuilder( UnitOfWorkDomainEventsValue.class );
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test4" ));
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test5" ));
-            builder.prototype().events().get().add( newDomainEvent( assembler, "Test6" ));
-            builder.prototype().version().set( "1.0" );
-            builder.prototype().timestamp().set( System.currentTimeMillis() );
-            builder.prototype().usecase().set( "Test2" );
-            list.add( builder.newInstance() );
-        }
-    }
-
-    private DomainEventValue newDomainEvent( SingletonAssembler assembler, String name )
-    {
-        ValueBuilder<DomainEventValue> eventBuilder = assembler.module().newValueBuilder( DomainEventValue.class );
-        eventBuilder.prototype().entityId().set( "123" );
-        eventBuilder.prototype().entityType().set( "Foo" );
-        eventBuilder.prototype().parameters().set( "{}" );
-        eventBuilder.prototype().name().set( name );
-        return eventBuilder.newInstance();
-    }
-
-    @Test
-    public void testRouter() throws IOException
-    {
-        final List<String> matched = new ArrayList<String>(  );
-        UnitOfWorkRouter<IOException> router = new UnitOfWorkRouter<IOException>();
-        router.route( Events.withUsecases( "Test" ), new Receiver<UnitOfWorkDomainEventsValue,IOException>()
-        {
-            @Override
-            public void receive( UnitOfWorkDomainEventsValue item ) throws IOException
-            {
-                matched.add(item.usecase().get());
-            }
-        });
-
-        EventRouter<IOException> eventRouter = new EventRouter<IOException>();
-        eventRouter.defaultReceiver(new Receiver<DomainEventValue, IOException>()
-        {
-            @Override
-            public void receive( DomainEventValue item ) throws IOException
-            {
-                System.out.println(item);
-            }
-        });
-
-        router.defaultReceiver(eventRouter);
-
-        Inputs.iterable( list ).transferTo( router );
-
-        Assert.assertThat( matched.toString(), CoreMatchers.equalTo( "[Test]" ) );
-    }
-
-    @Test(expected = IOException.class)
-    public void testRouterException() throws IOException
-    {
-        final List<String> matched = new ArrayList<String>(  );
-        UnitOfWorkRouter<IOException> router = new UnitOfWorkRouter<IOException>();
-        router.route( Events.withUsecases( "Test2" ), new Receiver<UnitOfWorkDomainEventsValue,IOException>()
-        {
-            @Override
-            public void receive( UnitOfWorkDomainEventsValue item ) throws IOException
-            {
-                throw new IOException("Failed");
-            }
-        });
-
-        EventRouter<IOException> eventRouter = new EventRouter<IOException>();
-        eventRouter.defaultReceiver(new Receiver<DomainEventValue, IOException>()
-        {
-            @Override
-            public void receive( DomainEventValue item ) throws IOException
-            {
-                System.out.println(item);
-            }
-        });
-
-        router.defaultReceiver(eventRouter);
-
-        Inputs.iterable( list ).transferTo( router );
-
-        Assert.assertThat( matched.toString(), CoreMatchers.equalTo( "[Test]" ) );
-    }
-}
diff --git a/libraries/fileconfig/build.gradle b/libraries/fileconfig/build.gradle
index 830117a..1e42d35 100644
--- a/libraries/fileconfig/build.gradle
+++ b/libraries/fileconfig/build.gradle
@@ -1,32 +1,37 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ File Configuration Library provides platform specific file locations."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - FileConfig" }}
+description = "Apache Polygene™ File Configuration Library provides platform specific file locations."
+
+jar { manifest { name = "Apache Polygene™ Library - FileConfig" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile libraries.slf4j_api
+  api polygene.core.bootstrap
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
+  implementation libraries.slf4j_api
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/libraries/fileconfig/dev-status.xml b/libraries/fileconfig/dev-status.xml
index bdf00e7..0914c52 100644
--- a/libraries/fileconfig/dev-status.xml
+++ b/libraries/fileconfig/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/fileconfig/src/docs/fileconfig.txt b/libraries/fileconfig/src/docs/fileconfig.txt
index ac973e6..437c972 100644
--- a/libraries/fileconfig/src/docs/fileconfig.txt
+++ b/libraries/fileconfig/src/docs/fileconfig.txt
@@ -27,7 +27,7 @@
 
 The FileConfig library provide a service for accessing application-specific directories.
 
-A lot of the Zest™ Libraries and Extensions make use of this library to locate files.
+A lot of the Polygene™ Libraries and Extensions make use of this library to locate files.
 
 include::../../build/docs/buildinfo/artifact.txt[]
 
@@ -35,7 +35,7 @@
 
 [snippet,java]
 ----
-source=libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/FileConfiguration.java
+source=libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/FileConfiguration.java
 tag=fileconfig
 ----
 
@@ -43,13 +43,13 @@
 
 [snippet,java]
 ----
-source=libraries/fileconfig/src/test/java/org/qi4j/library/fileconfig/FileConfigurationTest.java
+source=libraries/fileconfig/src/test/java/org/apache/polygene/library/fileconfig/FileConfigurationTest.java
 tag=simple
 ----
 
 These will default to the platform settings, but can be overridden manually, either one-by-one or as a whole.
 
-You can override defaults by adding org.qi4j.library.fileconfig.FileConfiguration_OS.properties files to your
+You can override defaults by adding org.apache.polygene.library.fileconfig.FileConfiguration_OS.properties files to your
 classpath where OS is one of win, mac or unix.
 
 You can also override all properties definitions at assembly time by setting a FileConfigurationOverride object
@@ -57,7 +57,7 @@
 
 [snippet,java]
 ----
-source=libraries/fileconfig/src/test/java/org/qi4j/library/fileconfig/FileConfigurationTest.java
+source=libraries/fileconfig/src/test/java/org/apache/polygene/library/fileconfig/FileConfigurationTest.java
 tag=override
 ----
 
diff --git a/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/FileConfiguration.java b/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/FileConfiguration.java
new file mode 100644
index 0000000..3abc35e
--- /dev/null
+++ b/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/FileConfiguration.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.library.fileconfig;
+
+import java.io.File;
+
+/**
+ * Service for accessing application-specific directories.
+ * 
+ * <p>
+ * These will default to the platform settings, but can be overridden manually, either one-by-one or as a whole.
+ * </p>
+ * <p>
+ * You can override defaults by adding org.apache.polygene.library.fileconfig.FileConfiguration_OS.properties files to your
+ * classpath where OS is one of win, mac or unix.
+ * </p>
+ * <p>
+ * You can also override all properties definitions at assembly time by setting a FileConfigurationOverride object
+ * as meta info of this service.
+ * </p>
+ * <p>
+ * Services will most likely want to create their own subdirectories in the directories accessed
+ * from here.
+ * </p>
+ */
+// START SNIPPET: fileconfig
+public interface FileConfiguration
+{
+// END SNIPPET: fileconfig
+
+    public enum OS
+    {
+        windows, unix, mac
+    }
+
+    OS os();
+
+    File user();
+
+    // START SNIPPET: fileconfig
+    File configurationDirectory();
+
+    File dataDirectory();
+
+    File temporaryDirectory();
+
+    File cacheDirectory();
+
+    File logDirectory();
+
+}
+// END SNIPPET: fileconfig
+
diff --git a/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/FileConfigurationAssembler.java b/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/FileConfigurationAssembler.java
new file mode 100644
index 0000000..36631c6
--- /dev/null
+++ b/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/FileConfigurationAssembler.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.library.fileconfig;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+
+/**
+ * FileConfiguration Service Assembler.
+ */
+public class FileConfigurationAssembler
+    extends Assemblers.VisibilityIdentity<FileConfigurationAssembler>
+{
+    private FileConfigurationOverride override;
+
+    public FileConfigurationAssembler withOverride( FileConfigurationOverride override )
+    {
+        this.override = override;
+        return this;
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( FileConfigurationService.class ).visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+        if( override != null )
+        {
+            service.setMetaInfo( override );
+        }
+    }
+}
diff --git a/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/FileConfigurationDataWiper.java b/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/FileConfigurationDataWiper.java
new file mode 100644
index 0000000..2a0799a
--- /dev/null
+++ b/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/FileConfigurationDataWiper.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.library.fileconfig;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.activation.ActivationEvent;
+import org.apache.polygene.api.structure.Application;
+
+public final class FileConfigurationDataWiper
+{
+    public static void registerApplicationPassivationDataWiper( FileConfiguration fileConfig, Application application )
+    {
+        final List<File> dataDirectories = new ArrayList<>();
+        dataDirectories.add( fileConfig.configurationDirectory() );
+        dataDirectories.add( fileConfig.cacheDirectory() );
+        dataDirectories.add( fileConfig.dataDirectory() );
+        dataDirectories.add( fileConfig.logDirectory() );
+        dataDirectories.add( fileConfig.temporaryDirectory() );
+        application.registerActivationEventListener(
+            event ->
+            {
+                if( event.type() == ActivationEvent.EventType.PASSIVATED
+                    && Application.class.isAssignableFrom( event.source().getClass() ) )
+                {
+                    for( File dataDir : dataDirectories )
+                    {
+                        if( !delete( dataDir ) )
+                        {
+                            System.err.println( "Unable to delete " + dataDir );
+                        }
+                    }
+                }
+            } );
+    }
+
+    private static boolean delete( File file )
+    {
+        if( !file.exists() )
+        {
+            return true;
+        }
+        if( file.isFile() )
+        {
+            return file.delete();
+        }
+        else
+        {
+            File[] files = file.listFiles();
+            if( files != null )
+            {
+                for( File childFile : files )
+                {
+                    if( !delete( childFile ) )
+                    {
+                        return false;
+                    }
+                }
+            }
+            return file.delete();
+        }
+    }
+
+    private FileConfigurationDataWiper()
+    {
+    }
+}
diff --git a/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/FileConfigurationOverride.java b/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/FileConfigurationOverride.java
new file mode 100644
index 0000000..20a2495
--- /dev/null
+++ b/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/FileConfigurationOverride.java
@@ -0,0 +1,125 @@
+/*
+ *  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.polygene.library.fileconfig;
+
+import java.io.File;
+
+/**
+ * Assembly time FileConfiguration override.
+ */
+public final class FileConfigurationOverride
+{
+    /**
+     * {@literal configuration}.
+     */
+    public static final String CONVENTIONAL_CONFIGURATION = "configuration";
+    /**
+     * {@literal data}.
+     */
+    public static final String CONVENTIONAL_DATA = "data";
+    /**
+     * {@literal temporary}.
+     */
+    public static final String CONVENTIONAL_TEMPORARY = "temporary";
+    /**
+     * {@literal cache}.
+     */
+    public static final String CONVENTIONAL_CACHE = "cache";
+    /**
+     * {@literal log}.
+     */
+    public static final String CONVENTIONAL_LOG = "log";
+
+    private File configuration;
+    private File data;
+    private File temporary;
+    private File cache;
+    private File log;
+
+    /**
+     * With all directories under the given root using conventional names.
+     * @param root Root file
+     * @return This
+     */
+    public FileConfigurationOverride withConventionalRoot( File root )
+    {
+        this.configuration = new File( root, CONVENTIONAL_CONFIGURATION );
+        this.data = new File( root, CONVENTIONAL_DATA );
+        this.temporary = new File( root, CONVENTIONAL_TEMPORARY );
+        this.cache = new File( root, CONVENTIONAL_CACHE );
+        this.log = new File( root, CONVENTIONAL_LOG );
+        return this;
+    }
+
+    public FileConfigurationOverride withConfiguration( File configuration )
+    {
+        this.configuration = configuration;
+        return this;
+    }
+
+    public FileConfigurationOverride withData( File data )
+    {
+        this.data = data;
+        return this;
+    }
+
+    public FileConfigurationOverride withTemporary( File temporary )
+    {
+        this.temporary = temporary;
+        return this;
+    }
+
+    public FileConfigurationOverride withCache( File cache )
+    {
+        this.cache = cache;
+        return this;
+    }
+
+    public FileConfigurationOverride withLog( File log )
+    {
+        this.log = log;
+        return this;
+    }
+
+    public File cache()
+    {
+        return cache;
+    }
+
+    public File configuration()
+    {
+        return configuration;
+    }
+
+    public File data()
+    {
+        return data;
+    }
+
+    public File log()
+    {
+        return log;
+    }
+
+    public File temporary()
+    {
+        return temporary;
+    }
+}
diff --git a/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/FileConfigurationService.java b/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/FileConfigurationService.java
new file mode 100644
index 0000000..f2d35e6
--- /dev/null
+++ b/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/FileConfigurationService.java
@@ -0,0 +1,292 @@
+/*
+ *  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.polygene.library.fileconfig;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Application;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Mixins( FileConfigurationService.Mixin.class )
+@Activators( FileConfigurationService.Activator.class )
+public interface FileConfigurationService
+        extends FileConfiguration
+{
+
+    void resolveFileConfiguration();
+
+    class Activator
+            extends ActivatorAdapter<ServiceReference<FileConfigurationService>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<FileConfigurationService> activated )
+                throws Exception
+        {
+            activated.get().resolveFileConfiguration();
+        }
+
+    }
+
+    interface Data
+    {
+
+        Property<OS> os();
+
+        Property<String> application();
+
+        Property<File> user();
+
+        Property<File> configuration();
+
+        Property<File> data();
+
+        Property<File> temporary();
+
+        Property<File> cache();
+
+        Property<File> log();
+
+    }
+
+    abstract class Mixin
+            implements FileConfigurationService
+    {
+
+        final Logger logger = LoggerFactory.getLogger( getClass().getName() );
+
+        @This
+        Data data;
+
+        @Uses
+        ServiceDescriptor descriptor;
+
+        @Structure
+        Application app;
+
+        @Override
+        public void resolveFileConfiguration()
+        {
+            OS os = detectOS();
+
+            data.os().set( os );
+            logger.info( "Operating system : " + os.name() );
+
+            // Get bundle with application name and configured directories
+            ResourceBundle bundle = ResourceBundle.getBundle( FileConfiguration.class.getName(), new Locale( os.name() ) );
+
+            Map arguments = getArguments( os );
+
+            data.configuration().set( new File( format( bundle.getString( "configuration" ), arguments ) ) );
+            data.data().set( new File( format( bundle.getString( "data" ), arguments ) ) );
+            data.temporary().set( new File( format( bundle.getString( "temporary" ), arguments ) ) );
+            data.cache().set( new File( format( bundle.getString( "cache" ), arguments ) ) );
+            data.log().set( new File( format( bundle.getString( "log" ), arguments ) ) );
+
+            applyOverride();
+            autoCreateDirectories();
+        }
+
+        private Map getArguments( OS os )
+        {
+            // Get user directory
+            String user = System.getenv( "USERPROFILE" ); // On Windows we use this instead of user.home
+            if ( user == null ) {
+                user = System.getProperty( "user.home" );
+            }
+
+            data.user().set( new File( user ) );
+
+            // Set application name. This is taken from the Polygene application but can be overriden by a system property
+            String application = System.getProperty( "application", app.name() );
+
+            if ( !app.mode().equals( Application.Mode.production ) ) {
+                application += "-" + app.mode().name();
+            }
+
+            data.application().set( application );
+
+            // Temp dir
+            String temp = System.getProperty( "java.io.tmpdir" );
+            if ( temp.endsWith( "/" ) ) {
+                temp = temp.substring( 0, temp.length() - 1 );
+            }
+
+            // Arguments available to use in directory specifications
+            Map<String, String> arguments = new HashMap<>();
+            arguments.put( "application", application );
+            arguments.put( "user", user );
+            arguments.put( "os", os.name() );
+            arguments.put( "temp", temp );
+
+            // Add environment variables
+            for ( Map.Entry<String, String> envVariable : System.getenv().entrySet() ) {
+                arguments.put( "environment." + envVariable.getKey(), envVariable.getValue() );
+            }
+            // Add system properties
+            for ( Map.Entry<Object, Object> envVariable : System.getProperties().entrySet() ) {
+                arguments.put( "system." + envVariable.getKey(), envVariable.getValue().toString() );
+            }
+
+            return arguments;
+        }
+
+        private void applyOverride()
+        {
+            FileConfigurationOverride override = descriptor.metaInfo( FileConfigurationOverride.class );
+            if ( override != null ) {
+                if ( override.configuration() != null ) {
+                    data.configuration().set( override.configuration() );
+                }
+                if ( override.data() != null ) {
+                    data.data().set( override.data() );
+                }
+                if ( override.temporary() != null ) {
+                    data.temporary().set( override.temporary() );
+                }
+                if ( override.cache() != null ) {
+                    data.cache().set( override.cache() );
+                }
+                if ( override.log() != null ) {
+                    data.log().set( override.log() );
+                }
+            }
+        }
+
+        @Override
+        public OS os()
+        {
+            return data.os().get();
+        }
+
+        @Override
+        public File user()
+        {
+            return data.user().get();
+        }
+
+        @Override
+        public File configurationDirectory()
+        {
+            return data.configuration().get();
+        }
+
+        @Override
+        public File dataDirectory()
+        {
+            return data.data().get();
+        }
+
+        @Override
+        public File temporaryDirectory()
+        {
+            return data.temporary().get();
+        }
+
+        @Override
+        public File cacheDirectory()
+        {
+            return data.cache().get();
+        }
+
+        @Override
+        public File logDirectory()
+        {
+            return data.log().get();
+        }
+
+        private OS detectOS()
+        {
+            String osName = System.getProperty( "os.name" ).toLowerCase();
+            OS os;
+            if ( osName.contains( "win" ) ) {
+                os = OS.windows;
+            } else if ( osName.contains( "mac" ) ) {
+                os = OS.mac;
+            } else {
+                os = OS.unix;
+            }
+            return os;
+        }
+
+        private void autoCreateDirectories()
+        {
+            // Create directories
+            if ( !configurationDirectory().exists() && !configurationDirectory().mkdirs() ) {
+                throw new IllegalStateException( "Could not create configuration directory(" + configurationDirectory() + ")" );
+            }
+            if ( !dataDirectory().exists() && !dataDirectory().mkdirs() ) {
+                throw new IllegalStateException( "Could not create data directory(" + dataDirectory() + ")" );
+            }
+            if ( !temporaryDirectory().exists() && !temporaryDirectory().mkdirs() ) {
+                throw new IllegalStateException( "Could not create temporary directory(" + temporaryDirectory() + ")" );
+            }
+            if ( !cacheDirectory().exists() && !cacheDirectory().mkdirs() ) {
+                throw new IllegalStateException( "Could not create cache directory(" + cacheDirectory() + ")" );
+            }
+            if ( !logDirectory().exists() && !logDirectory().mkdirs() ) {
+                throw new IllegalStateException( "Could not create log directory(" + logDirectory() + ")" );
+            }
+        }
+
+        private String format( String configuration, Map arguments )
+        {
+            Pattern paramPattern = Pattern.compile( "\\{(.*?)\\}" );
+
+            Matcher matcher = paramPattern.matcher( configuration );
+
+            StringBuilder buffer = new StringBuilder();
+            int lastEnd = 0;
+            while ( matcher.find() ) {
+                buffer.append( configuration.substring( lastEnd, matcher.start() ) );
+                lastEnd = matcher.end();
+
+                String var = matcher.group( 1 );
+                Object value = arguments.get( var );
+
+                if ( value != null ) {
+                    buffer.append( format( value.toString(), arguments ) );
+                } else {
+                    throw new IllegalArgumentException( "Illegal file configuration parameter:" + var );
+                }
+            }
+            buffer.append( configuration.substring( lastEnd ) );
+
+            return buffer.toString();
+        }
+
+    }
+
+}
diff --git a/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/package.html b/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/package.html
new file mode 100644
index 0000000..943c1d8
--- /dev/null
+++ b/libraries/fileconfig/src/main/java/org/apache/polygene/library/fileconfig/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>FileConfiguration Library.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/FileConfiguration.java b/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/FileConfiguration.java
deleted file mode 100644
index 17d4d9c..0000000
--- a/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/FileConfiguration.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- *
- * Copyright 2009-2010 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.fileconfig;
-
-import java.io.File;
-
-/**
- * Service for accessing application-specific directories.
- * 
- * <p>
- * These will default to the platform settings, but can be overridden manually, either one-by-one or as a whole.
- * </p>
- * <p>
- * You can override defaults by adding org.qi4j.library.fileconfig.FileConfiguration_OS.properties files to your
- * classpath where OS is one of win, mac or unix.
- * </p>
- * <p>
- * You can also override all properties definitions at assembly time by setting a FileConfigurationOverride object
- * as meta info of this service.
- * </p>
- * <p>
- * Services will most likely want to create their own subdirectories in the directories accessed
- * from here.
- * </p>
- */
-// START SNIPPET: fileconfig
-public interface FileConfiguration
-{
-// END SNIPPET: fileconfig
-
-    public enum OS
-    {
-        windows, unix, mac
-    }
-
-    OS os();
-
-    File user();
-
-    // START SNIPPET: fileconfig
-    File configurationDirectory();
-
-    File dataDirectory();
-
-    File temporaryDirectory();
-
-    File cacheDirectory();
-
-    File logDirectory();
-
-}
-// END SNIPPET: fileconfig
-
diff --git a/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/FileConfigurationAssembler.java b/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/FileConfigurationAssembler.java
deleted file mode 100644
index 0a0d8c7..0000000
--- a/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/FileConfigurationAssembler.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2014 Paul Merlin.
- *
- * Licensed  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.qi4j.library.fileconfig;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-
-/**
- * FileConfiguration Service Assembler.
- */
-public class FileConfigurationAssembler
-    extends Assemblers.VisibilityIdentity<FileConfigurationAssembler>
-{
-    private FileConfigurationOverride override;
-
-    public FileConfigurationAssembler withOverride( FileConfigurationOverride override )
-    {
-        this.override = override;
-        return this;
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ServiceDeclaration service = module.services( FileConfigurationService.class ).visibleIn( visibility() );
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        if( override != null )
-        {
-            service.setMetaInfo( override );
-        }
-    }
-}
diff --git a/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/FileConfigurationDataWiper.java b/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/FileConfigurationDataWiper.java
deleted file mode 100644
index 9b5531a..0000000
--- a/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/FileConfigurationDataWiper.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2013, Paul Merlin.
- *
- * Licensed  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.qi4j.library.fileconfig;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.activation.ActivationEvent;
-import org.qi4j.api.activation.ActivationEventListener;
-import org.qi4j.api.structure.Application;
-
-public final class FileConfigurationDataWiper
-{
-
-    public static void registerApplicationPassivationDataWiper( FileConfiguration fileConfig, Application application )
-    {
-        final List<File> dataDirectories = new ArrayList<File>();
-        dataDirectories.add( fileConfig.configurationDirectory() );
-        dataDirectories.add( fileConfig.cacheDirectory() );
-        dataDirectories.add( fileConfig.dataDirectory() );
-        dataDirectories.add( fileConfig.logDirectory() );
-        dataDirectories.add( fileConfig.temporaryDirectory() );
-        application.registerActivationEventListener( new ActivationEventListener()
-        {
-            @Override
-            public void onEvent( ActivationEvent event )
-            {
-                if( event.type() == ActivationEvent.EventType.PASSIVATED && Application.class.isAssignableFrom( event.source().getClass() ) )
-                {
-                    for( File dataDir : dataDirectories )
-                    {
-                        if( !delete( dataDir ) )
-                        {
-                            System.err.println( "Unable to delete " + dataDir );
-                        }
-                    }
-                }
-            }
-        } );
-    }
-
-    private static boolean delete( File file )
-    {
-        if( !file.exists() )
-        {
-            return true;
-        }
-        if( file.isFile() )
-        {
-            return file.delete();
-        }
-        else
-        {
-            for( File childFile : file.listFiles() )
-            {
-                if( !delete( childFile ) )
-                {
-                    return false;
-                }
-            }
-            return file.delete();
-        }
-    }
-
-    private FileConfigurationDataWiper()
-    {
-    }
-
-}
diff --git a/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/FileConfigurationOverride.java b/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/FileConfigurationOverride.java
deleted file mode 100644
index 71290a5..0000000
--- a/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/FileConfigurationOverride.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.fileconfig;
-
-import java.io.File;
-
-public final class FileConfigurationOverride
-{
-
-    private File configuration;
-    private File data;
-    private File temporary;
-    private File cache;
-    private File log;
-
-    public FileConfigurationOverride withConfiguration( File configuration )
-    {
-        this.configuration = configuration;
-        return this;
-    }
-
-    public FileConfigurationOverride withData( File data )
-    {
-        this.data = data;
-        return this;
-    }
-
-    public FileConfigurationOverride withTemporary( File temporary )
-    {
-        this.temporary = temporary;
-        return this;
-    }
-
-    public FileConfigurationOverride withCache( File cache )
-    {
-        this.cache = cache;
-        return this;
-    }
-
-    public FileConfigurationOverride withLog( File log )
-    {
-        this.log = log;
-        return this;
-    }
-
-    public File cache()
-    {
-        return cache;
-    }
-
-    public File configuration()
-    {
-        return configuration;
-    }
-
-    public File data()
-    {
-        return data;
-    }
-
-    public File log()
-    {
-        return log;
-    }
-
-    public File temporary()
-    {
-        return temporary;
-    }
-
-}
diff --git a/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/FileConfigurationService.java b/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/FileConfigurationService.java
deleted file mode 100644
index 9bc1941..0000000
--- a/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/FileConfigurationService.java
+++ /dev/null
@@ -1,292 +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.qi4j.library.fileconfig;
-
-import java.io.File;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import java.util.ResourceBundle;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Mixins( FileConfigurationService.Mixin.class )
-@Activators( FileConfigurationService.Activator.class )
-public interface FileConfigurationService
-        extends FileConfiguration, ServiceComposite
-{
-
-    void resolveFileConfiguration();
-
-    public static class Activator
-            extends ActivatorAdapter<ServiceReference<FileConfigurationService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<FileConfigurationService> activated )
-                throws Exception
-        {
-            activated.get().resolveFileConfiguration();
-        }
-
-    }
-
-    interface Data
-    {
-
-        Property<OS> os();
-
-        Property<String> application();
-
-        Property<File> user();
-
-        Property<File> configuration();
-
-        Property<File> data();
-
-        Property<File> temporary();
-
-        Property<File> cache();
-
-        Property<File> log();
-
-    }
-
-    abstract class Mixin
-            implements FileConfigurationService
-    {
-
-        final Logger logger = LoggerFactory.getLogger( getClass().getName() );
-
-        @This
-        Data data;
-
-        @Uses
-        ServiceDescriptor descriptor;
-
-        @Structure
-        Application app;
-
-        @Override
-        public void resolveFileConfiguration()
-        {
-            OS os = detectOS();
-
-            data.os().set( os );
-            logger.info( "Operating system : " + os.name() );
-
-            // Get bundle with application name and configured directories
-            ResourceBundle bundle = ResourceBundle.getBundle( FileConfiguration.class.getName(), new Locale( os.name() ) );
-
-            Map arguments = getArguments( os );
-
-            data.configuration().set( new File( format( bundle.getString( "configuration" ), arguments ) ) );
-            data.data().set( new File( format( bundle.getString( "data" ), arguments ) ) );
-            data.temporary().set( new File( format( bundle.getString( "temporary" ), arguments ) ) );
-            data.cache().set( new File( format( bundle.getString( "cache" ), arguments ) ) );
-            data.log().set( new File( format( bundle.getString( "log" ), arguments ) ) );
-
-            applyOverride();
-            autoCreateDirectories();
-        }
-
-        private Map getArguments( OS os )
-        {
-            // Get user directory
-            String user = System.getenv( "USERPROFILE" ); // On Windows we use this instead of user.home
-            if ( user == null ) {
-                user = System.getProperty( "user.home" );
-            }
-
-            data.user().set( new File( user ) );
-
-            // Set application name. This is taken from the Zest application but can be overriden by a system property
-            String application = System.getProperty( "application", app.name() );
-
-            if ( !app.mode().equals( Application.Mode.production ) ) {
-                application += "-" + app.mode().name();
-            }
-
-            data.application().set( application );
-
-            // Temp dir
-            String temp = System.getProperty( "java.io.tmpdir" );
-            if ( temp.endsWith( "/" ) ) {
-                temp = temp.substring( 0, temp.length() - 1 );
-            }
-
-            // Arguments available to use in directory specifications
-            Map<String, String> arguments = new HashMap<String, String>();
-            arguments.put( "application", application );
-            arguments.put( "user", user );
-            arguments.put( "os", os.name() );
-            arguments.put( "temp", temp );
-
-            // Add environment variables
-            for ( Map.Entry<String, String> envVariable : System.getenv().entrySet() ) {
-                arguments.put( "environment." + envVariable.getKey(), envVariable.getValue() );
-            }
-            // Add system properties
-            for ( Map.Entry<Object, Object> envVariable : System.getProperties().entrySet() ) {
-                arguments.put( "system." + envVariable.getKey(), envVariable.getValue().toString() );
-            }
-
-            return arguments;
-        }
-
-        private void applyOverride()
-        {
-            FileConfigurationOverride override = descriptor.metaInfo( FileConfigurationOverride.class );
-            if ( override != null ) {
-                if ( override.configuration() != null ) {
-                    data.configuration().set( override.configuration() );
-                }
-                if ( override.data() != null ) {
-                    data.data().set( override.data() );
-                }
-                if ( override.temporary() != null ) {
-                    data.temporary().set( override.temporary() );
-                }
-                if ( override.cache() != null ) {
-                    data.cache().set( override.cache() );
-                }
-                if ( override.log() != null ) {
-                    data.log().set( override.log() );
-                }
-            }
-        }
-
-        @Override
-        public OS os()
-        {
-            return data.os().get();
-        }
-
-        @Override
-        public File user()
-        {
-            return data.user().get();
-        }
-
-        @Override
-        public File configurationDirectory()
-        {
-            return data.configuration().get();
-        }
-
-        @Override
-        public File dataDirectory()
-        {
-            return data.data().get();
-        }
-
-        @Override
-        public File temporaryDirectory()
-        {
-            return data.temporary().get();
-        }
-
-        @Override
-        public File cacheDirectory()
-        {
-            return data.cache().get();
-        }
-
-        @Override
-        public File logDirectory()
-        {
-            return data.log().get();
-        }
-
-        private OS detectOS()
-        {
-            String osName = System.getProperty( "os.name" ).toLowerCase();
-            OS os;
-            if ( osName.indexOf( "win" ) != -1 ) {
-                os = OS.windows;
-            } else if ( osName.indexOf( "mac" ) != -1 ) {
-                os = OS.mac;
-            } else {
-                os = OS.unix;
-            }
-            return os;
-        }
-
-        private void autoCreateDirectories()
-        {
-            // Create directories
-            if ( !configurationDirectory().exists() && !configurationDirectory().mkdirs() ) {
-                throw new IllegalStateException( "Could not create configuration directory(" + configurationDirectory() + ")" );
-            }
-            if ( !dataDirectory().exists() && !dataDirectory().mkdirs() ) {
-                throw new IllegalStateException( "Could not create data directory(" + dataDirectory() + ")" );
-            }
-            if ( !temporaryDirectory().exists() && !temporaryDirectory().mkdirs() ) {
-                throw new IllegalStateException( "Could not create temporary directory(" + temporaryDirectory() + ")" );
-            }
-            if ( !cacheDirectory().exists() && !cacheDirectory().mkdirs() ) {
-                throw new IllegalStateException( "Could not create cache directory(" + cacheDirectory() + ")" );
-            }
-            if ( !logDirectory().exists() && !logDirectory().mkdirs() ) {
-                throw new IllegalStateException( "Could not create log directory(" + logDirectory() + ")" );
-            }
-        }
-
-        private String format( String configuration, Map arguments )
-        {
-            Pattern paramPattern = Pattern.compile( "\\{(.*?)\\}" );
-
-            Matcher matcher = paramPattern.matcher( configuration );
-
-            StringBuilder buffer = new StringBuilder();
-            int lastEnd = 0;
-            while ( matcher.find() ) {
-                buffer.append( configuration.substring( lastEnd, matcher.start() ) );
-                lastEnd = matcher.end();
-
-                String var = matcher.group( 1 );
-                Object value = arguments.get( var );
-
-                if ( value != null ) {
-                    buffer.append( format( value.toString(), arguments ) );
-                } else {
-                    throw new IllegalArgumentException( "Illegal file configuration parameter:" + var );
-                }
-            }
-            buffer.append( configuration.substring( lastEnd ) );
-
-            return buffer.toString();
-        }
-
-    }
-
-}
diff --git a/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/package.html b/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/package.html
deleted file mode 100644
index 03b5188..0000000
--- a/libraries/fileconfig/src/main/java/org/qi4j/library/fileconfig/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>FileConfiguration Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/fileconfig/src/main/resources/org/apache/polygene/library/fileconfig/FileConfiguration_mac.properties b/libraries/fileconfig/src/main/resources/org/apache/polygene/library/fileconfig/FileConfiguration_mac.properties
new file mode 100644
index 0000000..3f7b2fa
--- /dev/null
+++ b/libraries/fileconfig/src/main/resources/org/apache/polygene/library/fileconfig/FileConfiguration_mac.properties
@@ -0,0 +1,25 @@
+#
+#  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.
+#
+#
+#
+
+configuration={user}/Library/Preferences/{application}
+data={user}/Library/Application Support/{application}
+temporary={temp}/{application}
+cache={user}/Library/Caches/{application}
+log={user}/Library/Logs/{application}
diff --git a/libraries/fileconfig/src/main/resources/org/apache/polygene/library/fileconfig/FileConfiguration_unix.properties b/libraries/fileconfig/src/main/resources/org/apache/polygene/library/fileconfig/FileConfiguration_unix.properties
new file mode 100644
index 0000000..e4f8943
--- /dev/null
+++ b/libraries/fileconfig/src/main/resources/org/apache/polygene/library/fileconfig/FileConfiguration_unix.properties
@@ -0,0 +1,25 @@
+#
+#  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.
+#
+#
+#
+
+configuration={user}/.{application}/etc
+data={user}/.{application}/data
+temporary={temp}/{application}
+cache={user}/.{application}/cache
+log={user}/.{application}/log
diff --git a/libraries/fileconfig/src/main/resources/org/apache/polygene/library/fileconfig/FileConfiguration_windows.properties b/libraries/fileconfig/src/main/resources/org/apache/polygene/library/fileconfig/FileConfiguration_windows.properties
new file mode 100644
index 0000000..5dfa587
--- /dev/null
+++ b/libraries/fileconfig/src/main/resources/org/apache/polygene/library/fileconfig/FileConfiguration_windows.properties
@@ -0,0 +1,25 @@
+#
+#  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.
+#
+#
+#
+
+configuration={user}/Application Data/{application}/conf
+data={user}/Application Data/{application}/data
+temporary={temp}/{application}
+cache={temp}/{application}/cache
+log={user}/Application Data/{application}/log
diff --git a/libraries/fileconfig/src/main/resources/org/qi4j/library/fileconfig/FileConfiguration_mac.properties b/libraries/fileconfig/src/main/resources/org/qi4j/library/fileconfig/FileConfiguration_mac.properties
deleted file mode 100644
index 7afb96e..0000000
--- a/libraries/fileconfig/src/main/resources/org/qi4j/library/fileconfig/FileConfiguration_mac.properties
+++ /dev/null
@@ -1,20 +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.
-
-configuration={user}/Library/Preferences/{application}
-data={user}/Library/Application Support/{application}
-temporary={temp}/{application}
-cache={user}/Library/Caches/{application}
-log={user}/Library/Logs/{application}
diff --git a/libraries/fileconfig/src/main/resources/org/qi4j/library/fileconfig/FileConfiguration_unix.properties b/libraries/fileconfig/src/main/resources/org/qi4j/library/fileconfig/FileConfiguration_unix.properties
deleted file mode 100644
index 4ddf896..0000000
--- a/libraries/fileconfig/src/main/resources/org/qi4j/library/fileconfig/FileConfiguration_unix.properties
+++ /dev/null
@@ -1,20 +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.
-
-configuration={user}/.{application}/etc
-data={user}/.{application}/data
-temporary={temp}/{application}
-cache={user}/.{application}/cache
-log={user}/.{application}/log
diff --git a/libraries/fileconfig/src/main/resources/org/qi4j/library/fileconfig/FileConfiguration_windows.properties b/libraries/fileconfig/src/main/resources/org/qi4j/library/fileconfig/FileConfiguration_windows.properties
deleted file mode 100644
index d338484..0000000
--- a/libraries/fileconfig/src/main/resources/org/qi4j/library/fileconfig/FileConfiguration_windows.properties
+++ /dev/null
@@ -1,20 +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.
-
-configuration={user}/Application Data/{application}/conf
-data={user}/Application Data/{application}/data
-temporary={temp}/{application}
-cache={temp}/{application}/cache
-log={user}/Application Data/{application}/log
diff --git a/libraries/fileconfig/src/test/java/org/apache/polygene/library/fileconfig/FileConfigurationTest.java b/libraries/fileconfig/src/test/java/org/apache/polygene/library/fileconfig/FileConfigurationTest.java
new file mode 100644
index 0000000..6f34efb
--- /dev/null
+++ b/libraries/fileconfig/src/test/java/org/apache/polygene/library/fileconfig/FileConfigurationTest.java
@@ -0,0 +1,139 @@
+/*
+ *  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.polygene.library.fileconfig;
+
+import java.io.File;
+import java.io.IOException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.junit.rules.TemporaryFolder;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class FileConfigurationTest
+{
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Test
+    public void testFileConfiguration()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                // START SNIPPET: simple
+                new FileConfigurationAssembler().assemble( module );
+                // END SNIPPET: simple
+            }
+        };
+
+        FileConfiguration config = assembler.module().findService( FileConfiguration.class ).get();
+        assertNotNull( config.configurationDirectory() );
+        assertNotNull( config.dataDirectory() );
+        assertNotNull( config.temporaryDirectory() );
+        assertNotNull( config.cacheDirectory() );
+        assertNotNull( config.logDirectory() );
+        System.out.println( "FileConfiguration defaults:\n"
+                            + "\tconfiguration: " + config.configurationDirectory().getAbsolutePath() + "\n"
+                            + "\tdata:          " + config.configurationDirectory().getAbsolutePath() + "\n"
+                            + "\ttemporary:     " + config.configurationDirectory().getAbsolutePath() + "\n"
+                            + "\tcache:         " + config.configurationDirectory().getAbsolutePath() + "\n"
+                            + "\tlog:           " + config.configurationDirectory().getAbsolutePath() );
+    }
+
+    @Test
+    public void testFileConfigurationOverride()
+        throws IOException, ActivationException, AssemblyException
+    {
+        File testFile = tmpDir.getRoot();
+        final File confDir = testFile;
+        final File dataDir = testFile;
+        final File tempDir = testFile;
+        final File cacheDir = testFile;
+        final File logDir = testFile;
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                // START SNIPPET: override
+                FileConfigurationOverride override = new FileConfigurationOverride()
+                    .withConfiguration( confDir )
+                    .withData( dataDir )
+                    .withTemporary( tempDir )
+                    .withCache( cacheDir )
+                    .withLog( logDir );
+                new FileConfigurationAssembler().withOverride( override ).assemble( module );
+                // END SNIPPET: override
+            }
+        };
+
+        FileConfiguration config = assembler.module().findService( FileConfiguration.class ).get();
+
+        assertEquals( testFile.getAbsolutePath(), config.configurationDirectory().getAbsolutePath() );
+        assertEquals( testFile.getAbsolutePath(), config.dataDirectory().getAbsolutePath() );
+        assertEquals( testFile.getAbsolutePath(), config.temporaryDirectory().getAbsolutePath() );
+        assertEquals( testFile.getAbsolutePath(), config.cacheDirectory().getAbsolutePath() );
+        assertEquals( testFile.getAbsolutePath(), config.logDirectory().getAbsolutePath() );
+    }
+
+    @Test
+    public void testFileConfigurationOverrideConvention()
+        throws IOException, ActivationException, AssemblyException
+    {
+        File rootDir = tmpDir.getRoot();
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                // START SNIPPET: override-convention
+                new FileConfigurationAssembler()
+                    .withOverride( new FileConfigurationOverride().withConventionalRoot( rootDir ) )
+                    .assemble( module );
+                // END SNIPPET: override-convention
+            }
+        };
+
+        FileConfiguration config = assembler.module().findService( FileConfiguration.class ).get();
+
+        assertEquals( new File( rootDir, FileConfigurationOverride.CONVENTIONAL_CONFIGURATION ).getAbsolutePath(),
+                      config.configurationDirectory().getAbsolutePath() );
+        assertEquals( new File( rootDir, FileConfigurationOverride.CONVENTIONAL_DATA ).getAbsolutePath(),
+                      config.dataDirectory().getAbsolutePath() );
+        assertEquals( new File( rootDir, FileConfigurationOverride.CONVENTIONAL_TEMPORARY ).getAbsolutePath(),
+                      config.temporaryDirectory().getAbsolutePath() );
+        assertEquals( new File( rootDir, FileConfigurationOverride.CONVENTIONAL_CACHE ).getAbsolutePath(),
+                      config.cacheDirectory().getAbsolutePath() );
+        assertEquals( new File( rootDir, FileConfigurationOverride.CONVENTIONAL_LOG ).getAbsolutePath(),
+                      config.logDirectory().getAbsolutePath() );
+    }
+}
diff --git a/libraries/fileconfig/src/test/java/org/apache/polygene/library/fileconfig/FileConfiguration_mac.properties b/libraries/fileconfig/src/test/java/org/apache/polygene/library/fileconfig/FileConfiguration_mac.properties
new file mode 100644
index 0000000..16d4cb8
--- /dev/null
+++ b/libraries/fileconfig/src/test/java/org/apache/polygene/library/fileconfig/FileConfiguration_mac.properties
@@ -0,0 +1,28 @@
+#
+#  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.
+#
+#
+#
+
+# Get HOME from environment variables
+configuration={environment.HOME}/Library/Preferences/{application}
+
+# Get user.home from system properties
+data={system.user.home}/Library/Application Support/{application}
+temporary={temp}/{application}
+cache={user}/Library/Caches/{application}
+log={user}/Library/Logs/{application}
diff --git a/libraries/fileconfig/src/test/java/org/qi4j/library/fileconfig/FileConfigurationTest.java b/libraries/fileconfig/src/test/java/org/qi4j/library/fileconfig/FileConfigurationTest.java
deleted file mode 100644
index 2285d23..0000000
--- a/libraries/fileconfig/src/test/java/org/qi4j/library/fileconfig/FileConfigurationTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.fileconfig;
-
-import java.io.File;
-import java.io.IOException;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-import static org.junit.Assert.assertEquals;
-
-public class FileConfigurationTest
-{
-    @Test
-    public void testFileConfiguration()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                // START SNIPPET: simple
-                new FileConfigurationAssembler().assemble( module );
-                // END SNIPPET: simple
-            }
-        };
-
-        FileConfiguration config = assembler.module().findService( FileConfiguration.class ).get();
-
-        File confDir = config.configurationDirectory();
-        System.out.println( confDir );
-    }
-
-    @Test
-    public void testFileConfigurationOverride()
-        throws IOException, ActivationException, AssemblyException
-    {
-        File testFile = File.createTempFile( FileConfigurationTest.class.getName(), "" + System.currentTimeMillis() );
-        final File confDir = testFile;
-        final File dataDir = testFile;
-        final File tempDir = testFile;
-        final File cacheDir = testFile;
-        final File logDir = testFile;
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                // START SNIPPET: override
-                FileConfigurationOverride override = new FileConfigurationOverride().
-                    withConfiguration( confDir ).
-                    withData( dataDir ).
-                    withTemporary( tempDir ).
-                    withCache( cacheDir ).
-                    withLog( logDir );
-                new FileConfigurationAssembler().withOverride( override ).assemble( module );
-                // END SNIPPET: override
-            }
-        };
-
-        FileConfiguration config = assembler.module().findService( FileConfiguration.class ).get();
-
-        assertEquals( testFile.getAbsolutePath(), config.configurationDirectory().getAbsolutePath() );
-    }
-}
diff --git a/libraries/fileconfig/src/test/java/org/qi4j/library/fileconfig/FileConfiguration_mac.properties b/libraries/fileconfig/src/test/java/org/qi4j/library/fileconfig/FileConfiguration_mac.properties
deleted file mode 100644
index 0c28ceb..0000000
--- a/libraries/fileconfig/src/test/java/org/qi4j/library/fileconfig/FileConfiguration_mac.properties
+++ /dev/null
@@ -1,23 +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.
-
-# Get HOME from environment variables
-configuration={environment.HOME}/Library/Preferences/{application}
-
-# Get user.home from system properties
-data={system.user.home}/Library/Application Support/{application}
-temporary={temp}/{application}
-cache={user}/Library/Caches/{application}
-log={user}/Library/Logs/{application}
diff --git a/libraries/http/build.gradle b/libraries/http/build.gradle
index bf7489b..6002d53 100644
--- a/libraries/http/build.gradle
+++ b/libraries/http/build.gradle
@@ -1,45 +1,86 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Http Library provides embedded Jetty for Apache Zest™ application use."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - Http" }}
+description = "Apache Polygene™ Http Library provides embedded Jetty for Apache Polygene™ application use."
 
-test {
-  systemProperties 'networkaddress.cache.ttl': '0'
-  systemProperties 'sun.net.spi.nameservice.provider.1': 'dns,LocalManagedDns'
-}
+jar { manifest { name = "Apache Polygene™ Library - Http" } }
 
 dependencies {
+  api polygene.core.bootstrap
+  api libraries.servlet_api
 
-  compile( project( ":org.qi4j.core:org.qi4j.core.api" ) )
-  compile( project( ":org.qi4j.libraries:org.qi4j.library.constraints" ) )
-  compile( project( ":org.qi4j.libraries:org.qi4j.library.jmx" ) )
-  compile( libraries.bouncy_castle )
-  compile( libraries.jetty_webapp )
-  compile( libraries.jetty_jmx )
+  implementation polygene.library( 'jmx' )
+  implementation polygene.library( 'constraints' )
+  implementation libraries.bouncy_castle
+  implementation libraries.jetty_webapp
+  implementation libraries.jetty_jmx
 
-  testCompile( project( ":org.qi4j.core:org.qi4j.core.testsupport" ) )
-  testCompile( libraries.http_client )
-  testCompile( libraries.dnsjava )
+  runtimeOnly polygene.core.runtime
 
-  testRuntime( project( ":org.qi4j.core:org.qi4j.core.runtime" ) )
-  testRuntime( libraries.logback )
+  testImplementation polygene.core.testsupport
+  testImplementation libraries.http_client
+  testImplementation libraries.junit
 
+  testRuntimeOnly libraries.logback
+}
+
+// Do not run vhost tests on Java >= 9 because they use internal JDK apis
+if( JavaVersion.current() < JavaVersion.VERSION_1_9 )
+{
+  sourceSets {
+    vhostTest {
+      java {
+        compileClasspath += main.output + test.output
+        runtimeClasspath += main.output + test.output
+        srcDir file( 'src/vhost-test/java' )
+      }
+      resources {
+        srcDir file( 'src/vhost-test/resources' )
+      }
+    }
+  }
+  configurations {
+    vhostTestImplementation.extendsFrom testImplementation
+    vhostTestRuntimeOnly.extendsFrom testRuntimeOnly
+  }
+  dependencies {
+    vhostTestImplementation libraries.dnsjava
+  }
+  task vhostTest( type: Test ) {
+    // TODO Test JVM won't start when offline
+    try
+    {
+      new URL( 'https://polygene.apache.org/' ).text
+      enabled = true
+    }
+    catch( Exception ex )
+    {
+      enabled = false
+    }
+    testClassesDir = sourceSets.vhostTest.output.classesDir
+    classpath = sourceSets.vhostTest.runtimeClasspath
+    systemProperties 'networkaddress.cache.ttl': '0'
+    systemProperties 'sun.net.spi.nameservice.provider.1': 'dns,LocalManagedDns'
+  }
+  check.dependsOn vhostTest
+  vhostTest.mustRunAfter test
 }
diff --git a/libraries/http/dev-status.xml b/libraries/http/dev-status.xml
index bdf00e7..0914c52 100644
--- a/libraries/http/dev-status.xml
+++ b/libraries/http/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/http/src/docs/http.txt b/libraries/http/src/docs/http.txt
index 7e4b904..0856fa3 100644
--- a/libraries/http/src/docs/http.txt
+++ b/libraries/http/src/docs/http.txt
@@ -29,7 +29,7 @@
 filters assembly as Services.
 
 It's an easy way to embedd a servlet container and reuse everything that can be run in it (JAX-*, Restlet, Wicket,
-Vaadin, GWT etc..). If instead you want to run a Zest™ Application in a servlet container, see <<library-servlet>>.
+Vaadin, GWT etc..). If instead you want to run a Polygene™ Application in a servlet container, see <<library-servlet>>.
 
 include::../../build/docs/buildinfo/artifact.txt[]
 
@@ -39,7 +39,7 @@
 
 [snippet,java]
 ----
-source=libraries/http/src/test/java/org/qi4j/library/http/FooServletContextListenerService.java
+source=libraries/http/src/test/java/org/apache/polygene/library/http/FooServletContextListenerService.java
 tag=context-listener
 ----
 
@@ -49,7 +49,7 @@
 
 [snippet,java]
 ----
-source=libraries/http/src/test/java/org/qi4j/library/http/HelloWorldServletService.java
+source=libraries/http/src/test/java/org/apache/polygene/library/http/HelloWorldServletService.java
 tag=servletservice
 ----
 
@@ -59,7 +59,7 @@
 
 [snippet,java]
 ----
-source=libraries/http/src/main/java/org/qi4j/library/http/UnitOfWorkFilterService.java
+source=libraries/http/src/main/java/org/apache/polygene/library/http/UnitOfWorkFilterService.java
 tag=filterservice
 ----
 
@@ -71,7 +71,7 @@
 
 [snippet,java]
 ----
-source=libraries/http/src/test/java/org/qi4j/library/http/JettyServiceTest.java
+source=libraries/http/src/test/java/org/apache/polygene/library/http/JettyServiceTest.java
 tag=assembly
 ----
 
@@ -84,16 +84,16 @@
 
 [snippet,java]
 ----
-source=libraries/http/src/test/java/org/qi4j/library/http/JettyJMXStatisticsTest.java
+source=libraries/http/src/test/java/org/apache/polygene/library/http/JettyJMXStatisticsTest.java
 tag=jmx
 ----
 
 === Configuration ===
 
-Underlying Jetty engine configuration is exposed as a Zest™ Service Configuration.
+Underlying Jetty engine configuration is exposed as a Polygene™ Service Configuration.
 The only one that is mandatory is the port.
 
-See org.qi4j.library.http.JettyConfiguration for a reference of all available
+See org.apache.polygene.library.http.JettyConfiguration for a reference of all available
 configuration properties.
 
 == Secure Jetty Service ==
@@ -106,7 +106,7 @@
 
 [snippet,java]
 ----
-source=libraries/http/src/test/java/org/qi4j/library/http/SecureJettyServiceTest.java
+source=libraries/http/src/test/java/org/apache/polygene/library/http/SecureJettyServiceTest.java
 tag=assemblyssl
 ----
 
@@ -123,11 +123,11 @@
 
 [snippet,java]
 ----
-source=libraries/http/src/test/java/org/qi4j/library/http/MutualSecureJettyServiceTest.java
+source=libraries/http/src/test/java/org/apache/polygene/library/http/MutualSecureJettyServiceTest.java
 tag=config
 ----
 
-See org.qi4j.library.http.SecureJettyConfiguration for a reference of all available
+See org.apache.polygene.library.http.SecureJettyConfiguration for a reference of all available
 configuration properties.
 
 
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/AbstractJettyMixin.java b/libraries/http/src/main/java/org/apache/polygene/library/http/AbstractJettyMixin.java
new file mode 100644
index 0000000..adc3e97
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/AbstractJettyMixin.java
@@ -0,0 +1,190 @@
+/*
+ *  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.polygene.library.http;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import javax.management.MBeanServer;
+import javax.servlet.Filter;
+import javax.servlet.Servlet;
+import javax.servlet.ServletContextListener;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.library.http.Interface.Protocol;
+import org.eclipse.jetty.jmx.MBeanContainer;
+import org.eclipse.jetty.security.SecurityHandler;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.NetworkConnector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.handler.ErrorHandler;
+import org.eclipse.jetty.server.session.SessionHandler;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHandler;
+
+import static org.apache.polygene.library.http.JettyConfigurationHelper.addContextListeners;
+import static org.apache.polygene.library.http.JettyConfigurationHelper.addFilters;
+import static org.apache.polygene.library.http.JettyConfigurationHelper.addServlets;
+import static org.apache.polygene.library.http.JettyConfigurationHelper.configureConnector;
+import static org.apache.polygene.library.http.JettyConfigurationHelper.configureContext;
+import static org.apache.polygene.library.http.JettyConfigurationHelper.configureHttp;
+import static org.apache.polygene.library.http.JettyConfigurationHelper.configureServer;
+
+public abstract class AbstractJettyMixin
+    implements HttpService, JettyActivation
+{
+
+    private final Identity identity;
+
+    private final Iterable<ServiceReference<ServletContextListener>> contextListeners;
+
+    private final Iterable<ServiceReference<Servlet>> servlets;
+
+    private final Iterable<ServiceReference<Filter>> filters;
+
+    private final MBeanServer mBeanServer;
+
+    private Server server;
+
+    public AbstractJettyMixin(Identity identity, Server jettyServer,
+                              Iterable<ServiceReference<ServletContextListener>> contextListeners,
+                              Iterable<ServiceReference<Servlet>> servlets,
+                              Iterable<ServiceReference<Filter>> filters,
+                              MBeanServer mBeanServer )
+    {
+        this.identity = identity;
+        this.server = jettyServer;
+        this.contextListeners = contextListeners;
+        this.servlets = servlets;
+        this.filters = filters;
+        this.mBeanServer = mBeanServer;
+    }
+
+    @Override
+    public final void startJetty()
+        throws Exception
+    {
+        // Configure Server
+        configureServer( server, configuration() );
+
+        // Set up HTTP
+        HttpConfiguration httpConfig = new HttpConfiguration();
+        configureHttp( httpConfig, configuration() );
+        httpConfig = specializeHttp( httpConfig );
+
+        // Set up connector
+        ServerConnector connector = buildConnector( server, httpConfig );
+        configureConnector( connector, configuration() );
+
+        // Bind Connector to Server
+        server.addConnector( connector );
+        if( mBeanServer != null )
+        {
+            server.addEventListener( new MBeanContainer( mBeanServer ) );
+        }
+
+        // Prepare ServletContext
+        ServletContextHandler root = new ServletContextHandler( server,
+                                                                "/",
+                                                                new SessionHandler(),
+                                                                buildSecurityHandler(),
+                                                                new ServletHandler(),
+                                                                new ErrorHandler() );
+        root.setDisplayName( identity.toString() );
+        configureContext( root, configuration() );
+
+        // Register ContextListeners, Servlets and Filters
+        addContextListeners( root, contextListeners );
+        addServlets( root, servlets );
+        addFilters( root, filters );
+
+        // Start
+        server.start();
+    }
+
+    @Override
+    public final void stopJetty()
+        throws Exception
+    {
+        server.stop();
+        for( Connector connector : server.getConnectors() )
+        {
+            connector.stop();
+        }
+        server = null;
+    }
+
+    @Override
+    @SuppressWarnings( "ValueOfIncrementOrDecrementUsed" )
+    public final Interface[] interfacesServed()
+    {
+        Connector[] connectors = server.getConnectors();
+        Interface[] result = new Interface[ connectors.length ];
+        int index = 0;
+        for( Connector connector : connectors )
+        {
+            if( connector instanceof NetworkConnector )
+            {
+                NetworkConnector netConnector = (NetworkConnector) connector;
+                String host = configuration().hostName().get();
+                if( host == null )
+                {
+                    host = netConnector.getHost();
+                    if( host == null ) // If serving all interfaces.
+                    {
+                        try
+                        {
+                            host = InetAddress.getLocalHost().getHostAddress();
+                        }
+                        catch( UnknownHostException e )
+                        {
+                            throw new InternalError( "UnknownHost for local interface.", e );
+                        }
+                    }
+                }
+                result[ index++] = new InterfaceImpl( host, netConnector.getPort(), servedProtocol() );
+            }
+        }
+        return result;
+    }
+
+    protected abstract JettyConfiguration configuration();
+
+    @SuppressWarnings( "NoopMethodInAbstractClass" )
+    protected HttpConfiguration specializeHttp( HttpConfiguration httpConfig )
+    {
+        return httpConfig;
+    }
+
+    protected ServerConnector buildConnector( Server server, HttpConfiguration httpConfig )
+    {
+        return new ServerConnector( server, new HttpConnectionFactory( httpConfig ) );
+    }
+
+    protected SecurityHandler buildSecurityHandler()
+    {
+        return null;
+    }
+
+    protected abstract Protocol servedProtocol();
+
+}
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/ConstraintInfo.java b/libraries/http/src/main/java/org/apache/polygene/library/http/ConstraintInfo.java
new file mode 100644
index 0000000..0f1b7eb
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/ConstraintInfo.java
@@ -0,0 +1,77 @@
+/*
+ *  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.polygene.library.http;
+
+import java.io.Serializable;
+
+public class ConstraintInfo
+        implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    public enum Constraint
+    {
+    }
+
+    public enum HttpMethod
+    {
+
+        GET, POST, HEAD, PUT, OPTIONS, TRACE, DELETE;
+
+        public static String[] toStringArray( HttpMethod[] methods )
+        {
+            String[] result = new String[ methods.length ];
+            for ( int idx = 0; idx < methods.length; idx++ ) {
+                result[idx] = methods[idx].name();
+            }
+            return result;
+        }
+
+    }
+
+    private final String path;
+
+    private final Constraint constraint;
+
+    private final HttpMethod[] omittedHttpMethods;
+
+    ConstraintInfo( String path, Constraint constraint, HttpMethod[] omittedHttpMethods )
+    {
+        this.path = path;
+        this.constraint = constraint;
+        this.omittedHttpMethods = omittedHttpMethods;
+    }
+
+    public Constraint getConstraint()
+    {
+        return constraint;
+    }
+
+    public HttpMethod[] getOmittedHttpMethods()
+    {
+        return omittedHttpMethods;
+    }
+
+    public String getPath()
+    {
+        return path;
+    }
+
+}
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/ConstraintService.java b/libraries/http/src/main/java/org/apache/polygene/library/http/ConstraintService.java
new file mode 100644
index 0000000..10ab1b9
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/ConstraintService.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.library.http;
+
+import org.eclipse.jetty.security.ConstraintMapping;
+import org.eclipse.jetty.util.security.Constraint;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.library.http.ConstraintInfo.HttpMethod;
+
+@Mixins( ConstraintService.Mixin.class )
+public interface ConstraintService
+{
+
+    ConstraintMapping buildConstraintMapping();
+
+    abstract class Mixin
+            implements ConstraintService
+    {
+
+        @Service
+        private ServiceReference<ConstraintService> myRef;
+
+        @Override
+        public ConstraintMapping buildConstraintMapping()
+        {
+            ConstraintMapping csMapping = null;
+            ConstraintInfo constraintInfo = myRef.metaInfo( ConstraintInfo.class );
+            if ( constraintInfo != null && constraintInfo.getConstraint() != null ) {
+                Constraint constraint = new Constraint();
+                csMapping = new ConstraintMapping();
+                csMapping.setConstraint( constraint );
+                csMapping.setPathSpec( constraintInfo.getPath() );
+                if ( constraintInfo.getOmittedHttpMethods() != null && constraintInfo.getOmittedHttpMethods().length > 0 ) {
+                    csMapping.setMethodOmissions( HttpMethod.toStringArray( constraintInfo.getOmittedHttpMethods() ) );
+                }
+            }
+            return csMapping;
+        }
+
+    }
+
+}
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/ContextListenerInfo.java b/libraries/http/src/main/java/org/apache/polygene/library/http/ContextListenerInfo.java
new file mode 100644
index 0000000..4a01bcd
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/ContextListenerInfo.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.http;
+
+import java.io.Serializable;
+import java.util.Map;
+
+public class ContextListenerInfo
+        implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    private final Map<String, String> initParams;
+
+    public ContextListenerInfo( Map<String, String> initParams )
+    {
+        this.initParams = initParams;
+    }
+
+    public Map<String, String> initParams()
+    {
+        return initParams;
+    }
+}
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/FilterInfo.java b/libraries/http/src/main/java/org/apache/polygene/library/http/FilterInfo.java
new file mode 100644
index 0000000..87c8c08
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/FilterInfo.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.library.http;
+
+import java.io.Serializable;
+import java.util.EnumSet;
+import java.util.Map;
+import javax.servlet.DispatcherType;
+
+public class FilterInfo
+    implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    private final String path;
+    private final Map<String, String> initParameters;
+    private final EnumSet<DispatcherType> dispatchers;
+
+    public FilterInfo( String path, Map<String, String> initParameters, EnumSet<DispatcherType> dispatchers )
+    {
+        this.dispatchers = dispatchers;
+        this.initParameters = initParameters;
+        this.path = path;
+    }
+
+    public String getPath()
+    {
+        return path;
+    }
+
+    public Map<String, String> initParameters()
+    {
+        return initParameters;
+    }
+
+    public EnumSet<DispatcherType> dispatchers()
+    {
+        return dispatchers;
+    }
+}
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/HttpService.java b/libraries/http/src/main/java/org/apache/polygene/library/http/HttpService.java
new file mode 100644
index 0000000..16ee3db
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/HttpService.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.library.http;
+
+public interface HttpService
+{
+    Interface[] interfacesServed();
+}
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/Interface.java b/libraries/http/src/main/java/org/apache/polygene/library/http/Interface.java
new file mode 100644
index 0000000..a61e4da
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/Interface.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.library.http;
+
+public interface Interface
+{
+    String hostName();
+
+    int port();
+
+    Protocol protocol();
+
+    enum Protocol
+    {
+        http, https
+    }
+}
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/InterfaceImpl.java b/libraries/http/src/main/java/org/apache/polygene/library/http/InterfaceImpl.java
new file mode 100644
index 0000000..6b8e87f
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/InterfaceImpl.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.library.http;
+
+class InterfaceImpl
+        implements Interface
+{
+
+    private final String host;
+    private final int port;
+    private final Protocol protocol;
+
+    public InterfaceImpl( String host, int port, Protocol protocol )
+    {
+        this.host = host;
+        this.port = port;
+        this.protocol = protocol;
+    }
+
+    @Override
+    public String hostName()
+    {
+        return host;
+    }
+
+    @Override
+    public int port()
+    {
+        return port;
+    }
+
+    @Override
+    public Protocol protocol()
+    {
+        return protocol;
+    }
+
+}
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/JettyActivation.java b/libraries/http/src/main/java/org/apache/polygene/library/http/JettyActivation.java
new file mode 100644
index 0000000..d1088c1
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/JettyActivation.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.library.http;
+
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.service.ServiceReference;
+
+public interface JettyActivation
+{
+
+    void startJetty()
+            throws Exception;
+
+    void stopJetty()
+            throws Exception;
+
+    class Activator
+            extends ActivatorAdapter<ServiceReference<JettyActivation>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<JettyActivation> activated )
+                throws Exception
+        {
+            activated.get().startJetty();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<JettyActivation> passivating )
+                throws Exception
+        {
+            passivating.get().stopJetty();
+        }
+
+    }
+
+}
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/JettyConfiguration.java b/libraries/http/src/main/java/org/apache/polygene/library/http/JettyConfiguration.java
new file mode 100644
index 0000000..4e1b2c4
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/JettyConfiguration.java
@@ -0,0 +1,168 @@
+/*
+ *  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.polygene.library.http;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.constraints.annotation.GreaterThan;
+import org.apache.polygene.library.constraints.annotation.Range;
+
+/**
+ * Configuration of the JettyService.
+ * 
+ * The only mandatory property is port.
+ * Other properties are provided with a sensible default respecting the original Jetty defaults.
+ */
+// START SNIPPET: config
+public interface JettyConfiguration
+{
+
+    // ## Connector Configuration Properties ##################################
+    /**
+     * @return Port on which the {@link JettyService} will listen for incomming requests.
+     */
+    @Range( min = 0, max = 65535 )
+    Property<Integer> port();
+
+    /**
+     * Name or ip representing the interface on which the {@link JettyService} will bind the server socket.
+     * 
+     * If not set the {@link JettyService} will be bound to all interfaces.
+     * 
+     * @return Name or ip representing the interface on which the {@link JettyService} will bind the server socket.
+     */
+    @Optional
+    Property<String> hostName();
+
+    /**
+     * Defaults to false.
+     * 
+     * @return If the {@link JettyService} should collect statistics.
+     */
+    @UseDefaults
+    Property<Boolean> statistics();
+
+    /**
+     * @return Maximum Idle time for connections in milliseconds.
+     */
+    @Optional
+    Property<Integer> maxIdleTime();
+
+    /**
+     * @return Maximum Idle time for connections in milliseconds when resources are low.
+     */
+    @Optional
+    Property<Integer> lowResourceMaxIdleTime();
+
+    /**
+     * @return The size of the buffer to be used for request headers in bytes.
+     */
+    @Optional
+    @GreaterThan( 0 )
+    Property<Integer> requestHeaderSize();
+
+    /**
+     * @return The size of the buffer to be used for response headers in bytes.
+     */
+    @Optional
+    @GreaterThan( 0 )
+    Property<Integer> responseHeaderSize();
+
+    /**
+     * Size of the content buffer for sending responses in bytes.
+     * 
+     * These buffers are only used for active connections that are sending responses with bodies that will not fit
+     * within the header buffer.
+     * 
+     * @return The size of the content buffer for sending responses in bytes.
+     */
+    @Optional
+    @GreaterThan( 0 )
+    Property<Integer> responseBufferSize();
+
+    // ## ServletContext Configuration Properties #############################
+    /**
+     * url prefix of the {@link JettyService}.
+     * 
+     * Defaulted to "/".
+     * 
+     * @return The url prefix of the {@link JettyService}.
+     */
+    @Optional
+    Property<String> contextPath();
+
+    @Optional
+    Property<String> resourcePath();
+
+    /**
+     * Virtual hosts for this JettyService.
+     * 
+     * Coma separated list of hostnames.
+     * 
+     * @return Virtual hosts for this JettyService.
+     */
+    @Optional
+    Property<String> virtualHosts();
+
+    /**
+     * Welcome files names for this JettyService.
+     * 
+     * Coma separated list of welcome files.
+     * Defaulted to index.html.
+     * 
+     * @return Welcome files names for this JettyService.
+     */
+    @Optional
+    Property<String> welcomeFiles();
+
+    /**
+     * @return Maximum Form content size.
+     */
+    @Optional
+    @GreaterThan( 0 )
+    Property<Integer> maxFormContentSize();
+
+    // ## Server Configuration Properties #####################################
+    /**
+     * @return If {@link JettyService} populates http header with server date.
+     */
+    @Optional
+    Property<Boolean> sendDateHeader();
+
+    /**
+     * @return If {@link JettyService} expose it's implementation version.
+     */
+    @Optional
+    Property<Boolean> sendServerVersion();
+
+    /**
+     * Timeout use to wait for active requests to terminate on shutdown in milliseconds.
+     * 
+     * Jetty will stop gracefully only if this property is set.
+     * 
+     * @return Timeout use to wait for active requests to terminate on shutdown in milliseconds.
+     */
+    @Optional
+    @GreaterThan( 0 )
+    Property<Integer> gracefullShutdownTimeout();
+
+}
+// END SNIPPET: config
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/JettyConfigurationHelper.java b/libraries/http/src/main/java/org/apache/polygene/library/http/JettyConfigurationHelper.java
new file mode 100644
index 0000000..0eea7e3
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/JettyConfigurationHelper.java
@@ -0,0 +1,368 @@
+/*
+ *  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.polygene.library.http;
+
+import java.security.Provider;
+import java.security.Security;
+import java.util.Map;
+import javax.servlet.Filter;
+import javax.servlet.Servlet;
+import javax.servlet.ServletContextListener;
+import org.eclipse.jetty.server.ConnectorStatistics;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.LowResourceMonitor;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
+import org.eclipse.jetty.servlet.DefaultServlet;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.apache.polygene.api.common.InvalidApplicationException;
+import org.apache.polygene.api.service.ServiceReference;
+
+final class JettyConfigurationHelper
+{
+
+    private static final Integer DEFAULT_PORT = 8080;
+
+    private static final String[] DEFAULT_WELCOME_FILES = new String[]
+    {
+        "index.html"
+    };
+
+    private static final String COMA = ",";
+
+    static void configureServer( Server server, JettyConfiguration config )
+    {
+        // Shutdown
+        Integer gracefullShudownTimeout = config.gracefullShutdownTimeout().get();
+        if( gracefullShudownTimeout != null )
+        {
+            server.setStopTimeout( gracefullShudownTimeout );
+        }
+
+        // Low resource max idle time
+        Integer lowResourceMaxIdleTime = config.lowResourceMaxIdleTime().get();
+        if( lowResourceMaxIdleTime != null )
+        {
+            LowResourceMonitor lowResourceMonitor = new LowResourceMonitor( server );
+            lowResourceMonitor.setLowResourcesIdleTimeout( lowResourceMaxIdleTime );
+            server.addBean( lowResourceMonitor );
+        }
+
+        // Statistics
+        if( config.statistics().get() )
+        {
+            server.addBean( new ConnectorStatistics() );
+        }
+    }
+
+    static void configureHttp( HttpConfiguration httpConfig, JettyConfiguration config )
+    {
+        // Date header
+        Boolean sendDateHeader = config.sendDateHeader().get();
+        if( sendDateHeader != null )
+        {
+            httpConfig.setSendDateHeader( sendDateHeader );
+        }
+
+        // Server version
+        Boolean sendServerVersion = config.sendServerVersion().get();
+        if( sendServerVersion != null )
+        {
+            httpConfig.setSendServerVersion( sendServerVersion );
+        }
+
+        // Header sizes
+        Integer requestHeaderSize = config.requestHeaderSize().get();
+        if( requestHeaderSize != null )
+        {
+            httpConfig.setRequestHeaderSize( requestHeaderSize );
+        }
+        Integer responseHeaderSize = config.responseHeaderSize().get();
+        if( responseHeaderSize != null )
+        {
+            httpConfig.setResponseHeaderSize( responseHeaderSize );
+        }
+
+        // Buffer sizes
+        Integer responseBufferSize = config.responseBufferSize().get();
+        if( responseBufferSize != null )
+        {
+            httpConfig.setOutputBufferSize( responseBufferSize );
+        }
+
+    }
+
+    static void configureConnector( ServerConnector connector, JettyConfiguration config )
+    {
+        // Host and Port
+        connector.setHost( config.hostName().get() );
+        Integer port = config.port().get();
+        if( port == null )
+        {
+            port = DEFAULT_PORT;
+        }
+        connector.setPort( port );
+
+        // Max idle times
+        Integer maxIdleTime = config.maxIdleTime().get();
+        if( maxIdleTime != null )
+        {
+            connector.setIdleTimeout( maxIdleTime );
+        }
+    }
+
+    static void configureSsl( SslConnectionFactory sslConnFactory, SecureJettyConfiguration config )
+    {
+        SslContextFactory ssl = sslConnFactory.getSslContextFactory();
+
+        boolean needBouncyCastle = false;
+
+        // KeyStore
+        String keystoreType = config.keystoreType().get();
+        String keystorePath = config.keystorePath().get();
+        String keystorePassword = config.keystorePassword().get();
+        ssl.setKeyStoreType( keystoreType );
+        if( "PKCS12".equals( keystoreType ) )
+        {
+            ssl.setKeyStoreProvider( "BC" ); // WARN This one needs BouncyCastle on the classpath
+            needBouncyCastle = true;
+        }
+        ssl.setKeyStorePath( keystorePath );
+        ssl.setKeyStorePassword( keystorePassword );
+
+        // Certificate alias
+        String certAlias = config.certAlias().get();
+        if( certAlias != null )
+        {
+            ssl.setCertAlias( certAlias );
+        }
+
+        // TrustStore
+        String truststoreType = config.truststoreType().get();
+        String truststorePath = config.truststorePath().get();
+        String truststorePassword = config.truststorePassword().get();
+        if( truststoreType != null && truststorePath != null )
+        {
+            ssl.setTrustStoreType( truststoreType );
+            if( "PKCS12".equals( truststoreType ) )
+            {
+                ssl.setTrustStoreProvider( "BC" );
+                needBouncyCastle = true;
+            }
+            ssl.setTrustStorePath( truststorePath );
+            ssl.setTrustStorePassword( truststorePassword );
+        }
+
+        // Need / Want Client Auth
+        Boolean want = config.wantClientAuth().get();
+        if( want != null )
+        {
+            ssl.setWantClientAuth( want );
+        }
+        Boolean need = config.needClientAuth().get();
+        if( need != null )
+        {
+            ssl.setNeedClientAuth( need );
+        }
+
+        // Algorithms
+        String secureRandomAlgo = config.secureRandomAlgorithm().get();
+        if( secureRandomAlgo != null )
+        {
+            ssl.setSecureRandomAlgorithm( secureRandomAlgo );
+        }
+        String cipherExcludesConfigString = config.excludeCipherSuites().get();
+        if( cipherExcludesConfigString != null )
+        {
+            String[] cipherExcludes = cipherExcludesConfigString.split( COMA );
+            if( cipherExcludes.length > 0 )
+            {
+                ssl.setExcludeCipherSuites( cipherExcludes );
+            }
+        }
+        String cipherIncludesConfigString = config.includeCipherSuites().get();
+        if( cipherIncludesConfigString != null )
+        {
+            String[] cipherIncludes = cipherIncludesConfigString.split( COMA );
+            if( cipherIncludes.length > 0 )
+            {
+                ssl.setIncludeCipherSuites( cipherIncludes );
+            }
+        }
+
+        // SSL Handling
+        Boolean cacheSslSessions = config.cacheSslSessions().get();
+        if( cacheSslSessions != null )
+        {
+            ssl.setSessionCachingEnabled( cacheSslSessions );
+        }
+        ssl.setRenegotiationAllowed( config.allowRenegotiation().get() );
+
+        // Validation Flags
+        Integer maxCertPathLength = config.maxCertPathLength().get();
+        if( maxCertPathLength != null )
+        {
+            ssl.setMaxCertPathLength( maxCertPathLength );
+        }
+        ssl.setValidateCerts( config.validateServerCert().get() );
+        ssl.setValidatePeerCerts( config.validatePeerCerts().get() );
+
+        // Validation CRL
+        String crlFilePath = config.crlFilePath().get();
+        if( crlFilePath != null && crlFilePath.length() > 0 )
+        {
+            ssl.setCrlPath( crlFilePath );
+        }
+        ssl.setEnableCRLDP( config.enableCRLDP().get() );
+
+        // Validation OCSP
+        ssl.setEnableOCSP( config.enableOCSP().get() );
+        String ocspURL = config.ocspResponderURL().get();
+        if( ocspURL != null )
+        {
+            ssl.setOcspResponderURL( ocspURL );
+        }
+
+        // Load BouncyCastle ?
+        if( needBouncyCastle )
+        {
+            Provider bc = Security.getProvider( "BC" );
+            if( bc == null )
+            {
+                try
+                {
+                    Security.addProvider( (Provider) Class.forName( "org.bouncycastle.jce.provider.BouncyCastleProvider" ).newInstance() );
+                }
+                catch( Exception ex )
+                {
+                    throw new InvalidApplicationException( "Need to open a PKCS#12 but was unable to register BouncyCastle, check your classpath", ex );
+                }
+            }
+        }
+    }
+
+    static void configureContext( ServletContextHandler root, JettyConfiguration config )
+    {
+        // Context path
+        String contextPath = config.contextPath().get();
+        if( contextPath != null && contextPath.length() > 0 )
+        {
+            root.setContextPath( contextPath );
+        }
+
+        // Root resource base
+        String resourcePath = config.resourcePath().get();
+        if( resourcePath != null && resourcePath.length() > 0 )
+        {
+            root.addServlet( DefaultServlet.class, "/" );
+            root.setResourceBase( resourcePath );
+        }
+
+        // Max form content size
+        Integer maxFormContentSize = config.maxFormContentSize().get();
+        if( maxFormContentSize != null )
+        {
+            root.setMaxFormContentSize( maxFormContentSize );
+        }
+
+        // Virtual hosts
+        String virtualHostsConfigString = config.virtualHosts().get();
+        if( virtualHostsConfigString != null )
+        {
+            String[] virtualHosts = virtualHostsConfigString.split( COMA );
+            if( virtualHosts.length > 0 )
+            {
+                root.setVirtualHosts( virtualHosts );
+            }
+        }
+
+        // Welcome files
+        String welcomeFilesConfigString = config.welcomeFiles().get();
+        if( welcomeFilesConfigString == null )
+        {
+            root.setWelcomeFiles( DEFAULT_WELCOME_FILES );
+        }
+        else
+        {
+            String[] welcomeFiles = welcomeFilesConfigString.split( COMA );
+            if( welcomeFiles.length == 0 )
+            {
+                root.setWelcomeFiles( DEFAULT_WELCOME_FILES );
+            }
+            else
+            {
+                root.setWelcomeFiles( welcomeFiles );
+            }
+        }
+    }
+
+    static void addContextListeners( ServletContextHandler root, Iterable<ServiceReference<ServletContextListener>> contextListeners )
+    {
+        // Iterate the available context listeners and add them to the server
+        for( ServiceReference<ServletContextListener> contextListener : contextListeners )
+        {
+            ContextListenerInfo contextListenerInfo = contextListener.metaInfo( ContextListenerInfo.class );
+            Map<String, String> initParams = contextListenerInfo.initParams();
+            for( Map.Entry<String, String> entry : initParams.entrySet() )
+            {
+                root.setInitParameter( entry.getKey(), entry.getValue() );
+            }
+            root.addEventListener( contextListener.get() );
+        }
+    }
+
+    static void addServlets( ServletContextHandler root, Iterable<ServiceReference<Servlet>> servlets )
+    {
+        // Iterate the available servlets and add it to the server
+        for( ServiceReference<Servlet> servlet : servlets )
+        {
+            ServletInfo servletInfo = servlet.metaInfo( ServletInfo.class );
+            String servletPath = servletInfo.getPath();
+            Servlet servletInstance = servlet.get();
+            ServletHolder holder = new ServletHolder( servletInstance );
+            holder.setInitParameters( servletInfo.initParams() );
+            root.addServlet( holder, servletPath );
+        }
+    }
+
+    static void addFilters( ServletContextHandler root, Iterable<ServiceReference<Filter>> filters )
+    {
+        // Iterate the available filters and add them to the server
+        for( ServiceReference<Filter> filter : filters )
+        {
+            FilterInfo filterInfo = filter.metaInfo( FilterInfo.class );
+            String filterPath = filterInfo.getPath();
+
+            Filter filterInstance = filter.get();
+            FilterHolder holder = new FilterHolder( filterInstance );
+            holder.setInitParameters( filterInfo.initParameters() );
+            root.addFilter( holder, filterPath, filterInfo.dispatchers() );
+        }
+    }
+
+    private JettyConfigurationHelper()
+    {
+    }
+
+}
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/JettyMixin.java b/libraries/http/src/main/java/org/apache/polygene/library/http/JettyMixin.java
new file mode 100644
index 0000000..facf79e
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/JettyMixin.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.library.http;
+
+import javax.management.MBeanServer;
+import javax.servlet.Filter;
+import javax.servlet.Servlet;
+import javax.servlet.ServletContextListener;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.eclipse.jetty.server.Server;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.library.http.Interface.Protocol;
+
+public class JettyMixin
+        extends AbstractJettyMixin
+{
+
+    @This
+    private Configuration<JettyConfiguration> configuration;
+
+    public JettyMixin( @This HasIdentity meAsIdentity,
+                       @Service Server jettyServer,
+                       @Service Iterable<ServiceReference<ServletContextListener>> contextListeners,
+                       @Service Iterable<ServiceReference<Servlet>> servlets,
+                       @Service Iterable<ServiceReference<Filter>> filters,
+                       @Optional @Service MBeanServer mBeanServer )
+    {
+        super( meAsIdentity.identity().get(), jettyServer, contextListeners, servlets, filters, mBeanServer );
+    }
+
+    @Override
+    protected JettyConfiguration configuration()
+    {
+        return configuration.get();
+    }
+
+    @Override
+    protected Protocol servedProtocol()
+    {
+        return Protocol.http;
+    }
+
+}
\ No newline at end of file
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/JettyService.java b/libraries/http/src/main/java/org/apache/polygene/library/http/JettyService.java
new file mode 100644
index 0000000..683ac8e
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/JettyService.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.library.http;
+
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.mixin.Mixins;
+
+@Mixins( JettyMixin.class )
+@Activators( JettyActivation.Activator.class )
+public interface JettyService
+        extends HttpService, JettyActivation
+{
+}
\ No newline at end of file
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/JettyServiceAssembler.java b/libraries/http/src/main/java/org/apache/polygene/library/http/JettyServiceAssembler.java
new file mode 100644
index 0000000..8a7b765
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/JettyServiceAssembler.java
@@ -0,0 +1,95 @@
+/*
+ *  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.polygene.library.http;
+
+import org.eclipse.jetty.server.Server;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.service.importer.InstanceImporter;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ImportedServiceDeclaration;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+
+public class JettyServiceAssembler
+    extends Assemblers.VisibilityIdentityConfig<JettyServiceAssembler>
+{
+    protected ModuleAssembly serverModule;
+    protected Visibility serverVisibility = Visibility.module;
+    protected String serverIdentity;
+
+    /**
+     * @param serverModule Defaults to assembled module
+     * @param serverVisibility Defaults to {@link Visibility#module}
+     */
+    public JettyServiceAssembler withServer( ModuleAssembly serverModule, Visibility serverVisibility )
+    {
+        this.serverModule = serverModule;
+        this.serverVisibility = serverVisibility;
+        return this;
+    }
+
+    public JettyServiceAssembler serverIdentifiedBy( String serverIdentity )
+    {
+        this.serverIdentity = serverIdentity;
+        return this;
+    }
+
+    @Override
+    public final void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( httpService() ).
+            visibleIn( visibility() ).
+            instantiateOnStartup();
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+        if( hasConfig() )
+        {
+            configModule().entities( configurationEntity() ).visibleIn( configVisibility() );
+        }
+        assembleServer( module );
+    }
+
+    protected final void assembleServer( ModuleAssembly module )
+    {
+        serverModule = serverModule != null ? serverModule : module;
+        ImportedServiceDeclaration server = serverModule.importedServices( Server.class ).
+            importedBy( InstanceImporter.class ).
+            setMetaInfo( new Server() ).
+            visibleIn( serverVisibility );
+        if( serverIdentity != null )
+        {
+            server.identifiedBy( serverIdentity );
+        }
+    }
+
+    protected Class<? extends JettyConfiguration> configurationEntity()
+    {
+        return JettyConfiguration.class;
+    }
+
+    protected Class<? extends JettyService> httpService()
+    {
+        return JettyService.class;
+    }
+}
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/SecureJettyConfiguration.java b/libraries/http/src/main/java/org/apache/polygene/library/http/SecureJettyConfiguration.java
new file mode 100644
index 0000000..a75e296
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/SecureJettyConfiguration.java
@@ -0,0 +1,217 @@
+/*
+ *  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.polygene.library.http;
+
+import java.security.SecureRandom;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.constraints.annotation.GreaterThan;
+import org.apache.polygene.library.constraints.annotation.OneOf;
+
+/**
+ * Configuration for {@link SecureJettyMixin}.
+ *
+ * Only the three keystore related properties are mandatory, all the other ones have sensible defaults.
+ */
+// START SNIPPET: configssl
+public interface SecureJettyConfiguration
+        extends JettyConfiguration
+{
+
+    /**
+     * @return Type of the keystore that contains the {@link SecureJettyService} certificate.
+     */
+    @OneOf( { "PKCS12", "JCEKS", "JKS" } )
+    Property<String> keystoreType();
+
+    /**
+     * @return Path of the keystore that contains the {@link SecureJettyService} certificate.
+     */
+    Property<String> keystorePath();
+
+    /**
+     * @return Password of the keystore that contains the {@link SecureJettyService} certificate.
+     */
+    @UseDefaults
+    Property<String> keystorePassword();
+
+    /**
+     * Alias of the {@link SecureJettyService} certificate.
+     *
+     * If not set, the first certificate found in the keystore is used.
+     *
+     * @return Alias of the {@link SecureJettyService} certificate.
+     */
+    @Optional
+    Property<String> certAlias();
+
+    /**
+     * @return Type of the keystore that contains the certificates trusted by the {@link SecureJettyService}.
+     */
+    @Optional
+    @OneOf( { "PKCS12", "JCEKS", "JKS" } )
+    Property<String> truststoreType();
+
+    /**
+     * @return Path of the keystore that contains the certificates trusted by the {@link SecureJettyService}.
+     */
+    @Optional
+    Property<String> truststorePath();
+
+    /**
+     * @return Password of the keystore that contains the certificates trusted by the {@link SecureJettyService}.
+     */
+    @UseDefaults
+    Property<String> truststorePassword();
+
+    /**
+     * If the {@link SecureJettyService} wants client authentication.
+     *
+     * Defaults to false. If set to true, the {@link SecureJettyService} will expose the fact that it can handle client
+     * certificate based authentication.
+     *
+     * @return If the {@link SecureJettyService} wants client authentication.
+     */
+    @UseDefaults
+    Property<Boolean> wantClientAuth();
+
+    /**
+     * If the {@link SecureJettyService} needs client authentication.
+     *
+     * Defaults to false. If set to true, only mutually authentified connections will be accepted.
+     *
+     * @return If the {@link SecureJettyService} needs client authentication.
+     */
+    @UseDefaults
+    Property<Boolean> needClientAuth();
+
+    /**
+     * The algorithm used by {@link SecureRandom} for SSL operations.
+     *
+     * Default JVM algorithm is used if omitted.
+     *
+     * @return The algorithm used by {@link SecureRandom} for SSL operations.
+     */
+    @Optional
+    Property<String> secureRandomAlgorithm();
+
+    /**
+     * @return Coma separated list of included cipher suites.
+     */
+    @Optional
+    Property<String> includeCipherSuites();
+
+    /**
+     * @return Coma separated list of excluded cipher suites.
+     */
+    @Optional
+    Property<String> excludeCipherSuites();
+
+    /**
+     * If SSL Session caching is enabled.
+     *
+     * SSL Session caching is enabled by default.
+     *
+     * @return If SSL Session caching is enabled.
+     */
+    @Optional
+    Property<Boolean> cacheSslSessions();
+
+    /**
+     * If SSL/TLS renegotiation is allowed.
+     *
+     * Defaults to false. Setting this to true can open vulnerabilities, be sure of what you are doing.
+     *
+     * @return If SSL/TLS renegotiation is allowed.
+     */
+    @UseDefaults
+    Property<Boolean> allowRenegotiation();
+
+    /**
+     * Maximum number of intermediate certificates in the PKIX path.
+     *
+     * Set to -1 for unlimited. Defaulted to -1.
+     *
+     * @return Maximum number of intermediate certificates in the PKIX path
+     */
+    @Optional
+    @GreaterThan( -2 )
+    Property<Integer> maxCertPathLength();
+
+    /**
+     * If the {@link SecureJettyService} certificate MUST be PKIX validated.
+     *
+     * <p><b>IMPORTANT:</b></p>
+     * <ul>
+     *   <li>Server certificate validation do not use the configured truststore but the one of the JVM.</li>
+     *   <li>Server certificates validation behavior depends on CRL and OCSP related configuration properties.</li>
+     * </ul>
+     * <p>
+     * Defaults to false.
+     * </p>
+     * @return If the {@link SecureJettyService} certificate MUST be PKIX validated.
+     */
+    @UseDefaults
+    Property<Boolean> validateServerCert();
+
+    /**
+     * If client certificates PKIX validation MUST use either CRL or OCSP.
+     *
+     * <p><b>IMPORTANT:</b></p>
+     * <ul>
+     *   <li>Peer certificates validation use the configured truststore if present, the one of the JVM if not.</li>
+     *   <li>Peer certificates validation behavior depends on CRL and OCSP related configuration properties.</li>
+     * </ul>
+     * <p>
+     * Defaults to false.
+     * </p>
+     * @return If client certificates PKIX validation MUST use either CRL or OCSP.
+     */
+    @UseDefaults
+    Property<Boolean> validatePeerCerts();
+
+    /**
+     * @return The path of a local CRL file in PEM or DER format used during PKIX validations.
+     */
+    @Optional
+    Property<String> crlFilePath();
+
+    /**
+     * @return If PKIX validations use the CRL Distribution Points declared in CA certificates.
+     */
+    @UseDefaults
+    Property<Boolean> enableCRLDP();
+
+    /**
+     * @return If PKIX validations use the OCSP protocol against responders declared in CA certificates.
+     */
+    @UseDefaults
+    Property<Boolean> enableOCSP();
+
+    /**
+     * @return The URL of an OCSP responder to use during PKIX validations.
+     */
+    @Optional
+    Property<String> ocspResponderURL();
+
+}
+// END SNIPPET: configssl
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/SecureJettyMixin.java b/libraries/http/src/main/java/org/apache/polygene/library/http/SecureJettyMixin.java
new file mode 100644
index 0000000..570b94e
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/SecureJettyMixin.java
@@ -0,0 +1,116 @@
+/*
+ *  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.polygene.library.http;
+
+import javax.management.MBeanServer;
+import javax.servlet.Filter;
+import javax.servlet.Servlet;
+import javax.servlet.ServletContextListener;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.eclipse.jetty.security.ConstraintMapping;
+import org.eclipse.jetty.security.ConstraintSecurityHandler;
+import org.eclipse.jetty.security.SecurityHandler;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.SecureRequestCustomizer;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.library.http.Interface.Protocol;
+
+import static org.apache.polygene.library.http.JettyConfigurationHelper.configureSsl;
+
+public class SecureJettyMixin
+    extends AbstractJettyMixin
+{
+
+    @This
+    private Configuration<SecureJettyConfiguration> configuration;
+
+    @Optional
+    @Service
+    private Iterable<ConstraintService> constraintServices;
+
+    public SecureJettyMixin( @This HasIdentity meAsIdentity,
+                             @Service Server jettyServer,
+                             @Service Iterable<ServiceReference<ServletContextListener>> contextListeners,
+                             @Service Iterable<ServiceReference<Servlet>> servlets,
+                             @Service Iterable<ServiceReference<Filter>> filters,
+                             @Optional @Service MBeanServer mBeanServer )
+    {
+        super( meAsIdentity.identity().get(), jettyServer, contextListeners, servlets, filters, mBeanServer );
+    }
+
+    @Override
+    protected JettyConfiguration configuration()
+    {
+        return configuration.get();
+    }
+
+    @Override
+    protected HttpConfiguration specializeHttp( HttpConfiguration httpConfig )
+    {
+        HttpConfiguration httpsConfig = new HttpConfiguration( httpConfig );
+        httpsConfig.addCustomizer( new SecureRequestCustomizer() );
+        return httpsConfig;
+    }
+
+    @Override
+    protected SecurityHandler buildSecurityHandler()
+    {
+        if( constraintServices != null )
+        {
+            ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
+            for( ConstraintService eachConstraintService : constraintServices )
+            {
+                ConstraintMapping csMapping = eachConstraintService.buildConstraintMapping();
+                if( csMapping != null )
+                {
+                    securityHandler.addConstraintMapping( csMapping );
+                }
+            }
+            if( !securityHandler.getConstraintMappings().isEmpty() )
+            {
+                return securityHandler;
+            }
+        }
+        return super.buildSecurityHandler();
+    }
+
+    @Override
+    protected ServerConnector buildConnector( Server server, HttpConfiguration httpConfig )
+    {
+        SslConnectionFactory sslConnFactory = new SslConnectionFactory();
+        configureSsl( sslConnFactory, configuration.get() );
+        return new ServerConnector( server, sslConnFactory, new HttpConnectionFactory( httpConfig ) );
+    }
+
+    @Override
+    protected Protocol servedProtocol()
+    {
+        return Protocol.https;
+    }
+
+}
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/SecureJettyService.java b/libraries/http/src/main/java/org/apache/polygene/library/http/SecureJettyService.java
new file mode 100644
index 0000000..ccf7efc
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/SecureJettyService.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.library.http;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+@Mixins( SecureJettyMixin.class )
+public interface SecureJettyService
+        extends JettyService
+{
+}
\ No newline at end of file
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/SecureJettyServiceAssembler.java b/libraries/http/src/main/java/org/apache/polygene/library/http/SecureJettyServiceAssembler.java
new file mode 100644
index 0000000..150be10
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/SecureJettyServiceAssembler.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.library.http;
+
+public class SecureJettyServiceAssembler
+        extends JettyServiceAssembler
+{
+
+    @Override
+    protected Class<? extends JettyConfiguration> configurationEntity()
+    {
+        return SecureJettyConfiguration.class;
+    }
+
+    @Override
+    protected Class<? extends JettyService> httpService()
+    {
+        return SecureJettyService.class;
+    }
+
+}
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/ServletInfo.java b/libraries/http/src/main/java/org/apache/polygene/library/http/ServletInfo.java
new file mode 100644
index 0000000..5ad2136
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/ServletInfo.java
@@ -0,0 +1,58 @@
+/*
+ *  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.polygene.library.http;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * JAVADOC
+ */
+public class ServletInfo
+    implements Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    private final String path;
+    private final Map<String, String> initParams;
+
+    public ServletInfo( String mountPath )
+    {
+        this( mountPath, Collections.emptyMap() );
+    }
+
+    public ServletInfo( String mountPath, Map<String, String> initParams )
+    {
+        path = mountPath;
+        this.initParams = initParams;
+    }
+
+    public String getPath()
+    {
+        return path;
+    }
+
+    public Map<String, String> initParams()
+    {
+        return initParams;
+    }
+}
\ No newline at end of file
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/Servlets.java b/libraries/http/src/main/java/org/apache/polygene/library/http/Servlets.java
new file mode 100644
index 0000000..d04d914
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/Servlets.java
@@ -0,0 +1,322 @@
+/*
+ *  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.polygene.library.http;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.UUID;
+import javax.servlet.DispatcherType;
+import javax.servlet.Filter;
+import javax.servlet.Servlet;
+import javax.servlet.ServletContextListener;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.http.ConstraintInfo.Constraint;
+import org.apache.polygene.library.http.ConstraintInfo.HttpMethod;
+
+import static org.apache.polygene.api.common.Visibility.layer;
+
+public final class Servlets
+{
+
+    private Servlets()
+    {
+    }
+
+    public static ContextListenerDeclaration listen()
+    {
+        return new ContextListenerDeclaration();
+    }
+
+    public static ContextListenerAssembler addContextListeners( ContextListenerDeclaration... contextListenerDeclarations )
+    {
+        return new ContextListenerAssembler( contextListenerDeclarations );
+    }
+
+    public static class ContextListenerAssembler
+    {
+
+        final ContextListenerDeclaration[] contextListenerDeclarations;
+
+        ContextListenerAssembler( ContextListenerDeclaration... eventListenerDeclarations )
+        {
+            this.contextListenerDeclarations = eventListenerDeclarations;
+        }
+
+        public void to( ModuleAssembly module )
+                throws AssemblyException
+        {
+            for ( ContextListenerDeclaration contextListenerDeclaration : contextListenerDeclarations ) {
+                module.services( contextListenerDeclaration.contextListener() ).
+                        setMetaInfo( contextListenerDeclaration.contextListenerInfo() ).
+                        instantiateOnStartup().visibleIn( layer );
+            }
+        }
+
+    }
+
+    public static class ContextListenerDeclaration
+    {
+
+        Class<? extends ServletContextListener> contextListener;
+
+        Map<String, String> initParams = Collections.emptyMap();
+
+        public <T extends ServletContextListener> ContextListenerDeclaration with( Class<T> contextListener )
+        {
+            this.contextListener = contextListener;
+            return this;
+        }
+
+        public Class<? extends ServletContextListener> contextListener()
+        {
+            return contextListener;
+        }
+
+        public ContextListenerDeclaration withInitParams( Map<String, String> initParams )
+        {
+            this.initParams = initParams;
+            return this;
+        }
+
+        private ContextListenerInfo contextListenerInfo()
+        {
+            return new ContextListenerInfo( initParams );
+        }
+
+    }
+
+    public static ServletDeclaration serve( String path )
+    {
+        return new ServletDeclaration( path );
+    }
+
+    public static ServletAssembler addServlets( ServletDeclaration... servletDeclarations )
+    {
+        return new ServletAssembler( servletDeclarations );
+    }
+
+    public static class ServletAssembler
+    {
+
+        final ServletDeclaration[] servletDeclarations;
+
+        ServletAssembler( ServletDeclaration... servletDeclarations )
+        {
+            this.servletDeclarations = servletDeclarations;
+        }
+
+        public void to( ModuleAssembly module )
+                throws AssemblyException
+        {
+            for ( ServletDeclaration servletDeclaration : servletDeclarations ) {
+                module.services( servletDeclaration.servlet() ).
+                        setMetaInfo( servletDeclaration.servletInfo() ).
+                        instantiateOnStartup().visibleIn( layer );
+            }
+        }
+
+    }
+
+    public static class ServletDeclaration
+    {
+
+        String path;
+
+        Class<? extends Servlet> servlet;
+
+        Map<String, String> initParams = Collections.emptyMap();
+
+        ServletDeclaration( String path )
+        {
+            this.path = path;
+        }
+
+        public <T extends Servlet> ServletDeclaration with( Class<T> servlet )
+        {
+            this.servlet = servlet;
+            return this;
+        }
+
+        public ServletDeclaration withInitParams( Map<String, String> initParams )
+        {
+            this.initParams = initParams;
+            return this;
+        }
+
+        Class<? extends Servlet> servlet()
+        {
+            return servlet;
+        }
+
+        ServletInfo servletInfo()
+        {
+            return new ServletInfo( path, initParams );
+        }
+
+    }
+
+    public static FilterAssembler filter( String path )
+    {
+        return new FilterAssembler( path );
+    }
+
+    public static FilterDeclaration addFilters( FilterAssembler... filterAssemblers )
+    {
+        return new FilterDeclaration( filterAssemblers );
+    }
+
+    public static class FilterDeclaration
+    {
+
+        final FilterAssembler[] filterAssemblers;
+
+        FilterDeclaration( FilterAssembler... filterAssemblers )
+        {
+            this.filterAssemblers = filterAssemblers;
+        }
+
+        @SuppressWarnings( "unchecked" )
+        public void to( ModuleAssembly module )
+                throws AssemblyException
+        {
+            for ( FilterAssembler filterAssembler : filterAssemblers ) {
+                module.services( filterAssembler.filter() ).
+                        setMetaInfo( filterAssembler.filterInfo() ).
+                        instantiateOnStartup().visibleIn( layer );
+            }
+        }
+
+    }
+
+    public static class FilterAssembler
+    {
+
+        String path;
+
+        Class<? extends Filter> filter;
+
+        EnumSet<DispatcherType> dispatchers;
+
+        Map<String, String> initParams = Collections.emptyMap();
+
+        FilterAssembler( String path )
+        {
+            this.path = path;
+        }
+
+        public <T extends Filter> FilterAssembler through(
+                Class<T> filter )
+        {
+            this.filter = filter;
+            return this;
+        }
+
+        public FilterAssembler on( DispatcherType first, DispatcherType... rest )
+        {
+            dispatchers = EnumSet.of( first, rest );
+            return this;
+        }
+
+        public FilterAssembler withInitParams( Map<String, String> initParams )
+        {
+            this.initParams = initParams;
+            return this;
+        }
+
+        Class<? extends Filter> filter()
+        {
+            return filter;
+        }
+
+        FilterInfo filterInfo()
+        {
+            return new FilterInfo( path, initParams, dispatchers );
+        }
+
+    }
+
+    public static ConstraintAssembler constrain( String path )
+    {
+        return new ConstraintAssembler( path );
+    }
+
+    public static ConstraintDeclaration addConstraints( ConstraintAssembler... constraintAssemblers )
+    {
+        return new ConstraintDeclaration( constraintAssemblers );
+    }
+
+    public static class ConstraintDeclaration
+    {
+
+        private final ConstraintAssembler[] constraintAssemblers;
+
+        private ConstraintDeclaration( ConstraintAssembler[] constraintAssemblers )
+        {
+            this.constraintAssemblers = constraintAssemblers;
+        }
+
+        public void to( ModuleAssembly module )
+                throws AssemblyException
+        {
+            // TODO Refactor adding Map<ServiceAssembly,T> ServiceDeclaration.getMetaInfos( Class<T> type ); in bootstrap & runtime
+            // This would allow removing the ConstraintServices instances and this horrible hack with random UUIDs
+            for ( ConstraintAssembler eachAssembler : constraintAssemblers ) {
+                module.addServices( ConstraintService.class ).identifiedBy( UUID.randomUUID().toString() ).setMetaInfo( eachAssembler.constraintInfo() );
+            }
+        }
+
+    }
+
+    public static class ConstraintAssembler
+    {
+
+        private final String path;
+
+        private Constraint constraint;
+
+        private HttpMethod[] omittedHttpMethods = new HttpMethod[]{};
+
+        private ConstraintAssembler( String path )
+        {
+            this.path = path;
+        }
+
+        public ConstraintAssembler by( Constraint constraint )
+        {
+            this.constraint = constraint;
+            return this;
+        }
+
+        public ConstraintAssembler butNotOn( HttpMethod... omittedHttpMethods )
+        {
+            this.omittedHttpMethods = omittedHttpMethods;
+            return this;
+        }
+
+        ConstraintInfo constraintInfo()
+        {
+            return new ConstraintInfo( path, constraint, omittedHttpMethods );
+        }
+
+    }
+
+}
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/UnitOfWorkFilter.java b/libraries/http/src/main/java/org/apache/polygene/library/http/UnitOfWorkFilter.java
new file mode 100644
index 0000000..a415f67
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/UnitOfWorkFilter.java
@@ -0,0 +1,73 @@
+/*
+ *  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.polygene.library.http;
+
+import java.io.IOException;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+
+/**
+ * JAVADOC
+ */
+public class UnitOfWorkFilter
+    implements Filter
+{
+    @Structure private UnitOfWorkFactory uowf;
+
+    @Override
+    public void init( FilterConfig filterConfig )
+        throws ServletException
+    {
+    }
+
+    @Override
+    public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain )
+        throws IOException, ServletException
+    {
+        UnitOfWork unitOfWork = uowf.newUnitOfWork();
+        try
+        {
+            chain.doFilter( request, response );
+
+            if( unitOfWork.isOpen() )
+            {
+                unitOfWork.complete();
+            }
+        }
+        catch( Exception e )
+        {
+            unitOfWork.discard();
+        }
+
+    }
+
+    @Override
+    public void destroy()
+    {
+    }
+}
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/UnitOfWorkFilterService.java b/libraries/http/src/main/java/org/apache/polygene/library/http/UnitOfWorkFilterService.java
new file mode 100644
index 0000000..a52058a
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/UnitOfWorkFilterService.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.library.http;
+
+import javax.servlet.Filter;
+import org.apache.polygene.api.mixin.Mixins;
+
+/**
+ * JAVADOC
+ */
+// START SNIPPET: filterservice
+@Mixins( UnitOfWorkFilter.class )
+public interface UnitOfWorkFilterService extends Filter
+{
+}
+// END SNIPPET: filterservice
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/WelcomeServlet.java b/libraries/http/src/main/java/org/apache/polygene/library/http/WelcomeServlet.java
new file mode 100644
index 0000000..258a5d2
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/WelcomeServlet.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.library.http;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * JAVADOC
+ */
+public class WelcomeServlet
+    extends HttpServlet
+{
+    private static final long serialVersionUID = 1L;
+
+    @Override public void init() throws ServletException
+    {
+        super.init();
+    }
+
+    @Override protected void doGet( HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse ) throws ServletException, IOException
+    {
+        PrintWriter writer = httpServletResponse.getWriter();
+        writer.println( "Welcome!" );
+    }
+}
\ No newline at end of file
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/WelcomeServletService.java b/libraries/http/src/main/java/org/apache/polygene/library/http/WelcomeServletService.java
new file mode 100644
index 0000000..fa4ce38
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/WelcomeServletService.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.http;
+
+import javax.servlet.Servlet;
+import org.apache.polygene.api.mixin.Mixins;
+
+/**
+ * JAVADOC
+ */
+@Mixins( WelcomeServlet.class )
+public interface WelcomeServletService extends Servlet
+{
+}
\ No newline at end of file
diff --git a/libraries/http/src/main/java/org/apache/polygene/library/http/package.html b/libraries/http/src/main/java/org/apache/polygene/library/http/package.html
new file mode 100644
index 0000000..a265bc0
--- /dev/null
+++ b/libraries/http/src/main/java/org/apache/polygene/library/http/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>HTTP Library.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/AbstractJettyMixin.java b/libraries/http/src/main/java/org/qi4j/library/http/AbstractJettyMixin.java
deleted file mode 100644
index 5a57a13..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/AbstractJettyMixin.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import javax.management.MBeanServer;
-import javax.servlet.Filter;
-import javax.servlet.Servlet;
-import javax.servlet.ServletContextListener;
-import org.eclipse.jetty.jmx.MBeanContainer;
-import org.eclipse.jetty.security.SecurityHandler;
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.HttpConfiguration;
-import org.eclipse.jetty.server.HttpConnectionFactory;
-import org.eclipse.jetty.server.NetworkConnector;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.handler.ErrorHandler;
-import org.eclipse.jetty.server.session.SessionHandler;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHandler;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.functional.Iterables;
-import org.qi4j.library.http.Interface.Protocol;
-
-import static org.qi4j.library.http.JettyConfigurationHelper.addContextListeners;
-import static org.qi4j.library.http.JettyConfigurationHelper.addFilters;
-import static org.qi4j.library.http.JettyConfigurationHelper.addServlets;
-import static org.qi4j.library.http.JettyConfigurationHelper.configureConnector;
-import static org.qi4j.library.http.JettyConfigurationHelper.configureContext;
-import static org.qi4j.library.http.JettyConfigurationHelper.configureHttp;
-import static org.qi4j.library.http.JettyConfigurationHelper.configureServer;
-
-public abstract class AbstractJettyMixin
-    implements HttpService, JettyActivation
-{
-
-    private final String identity;
-
-    private final Iterable<ServiceReference<ServletContextListener>> contextListeners;
-
-    private final Iterable<ServiceReference<Servlet>> servlets;
-
-    private final Iterable<ServiceReference<Filter>> filters;
-
-    private final MBeanServer mBeanServer;
-
-    private Server server;
-
-    public AbstractJettyMixin( String identity, Server jettyServer,
-                               Iterable<ServiceReference<ServletContextListener>> contextListeners,
-                               Iterable<ServiceReference<Servlet>> servlets,
-                               Iterable<ServiceReference<Filter>> filters,
-                               MBeanServer mBeanServer )
-    {
-        this.identity = identity;
-        this.server = jettyServer;
-        this.contextListeners = Iterables.unique( contextListeners );
-        this.servlets = Iterables.unique( servlets );
-        this.filters = Iterables.unique( filters );
-        this.mBeanServer = mBeanServer;
-    }
-
-    @Override
-    public final void startJetty()
-        throws Exception
-    {
-        // Configure Server
-        configureServer( server, configuration() );
-
-        // Set up HTTP
-        HttpConfiguration httpConfig = new HttpConfiguration();
-        configureHttp( httpConfig, configuration() );
-        httpConfig = specializeHttp( httpConfig );
-
-        // Set up connector
-        ServerConnector connector = buildConnector( server, httpConfig );
-        configureConnector( connector, configuration() );
-
-        // Bind Connector to Server
-        server.addConnector( connector );
-        if( mBeanServer != null )
-        {
-            server.addEventListener( new MBeanContainer( mBeanServer ) );
-        }
-
-        // Prepare ServletContext
-        ServletContextHandler root = new ServletContextHandler( server,
-                                                                "/",
-                                                                new SessionHandler(),
-                                                                buildSecurityHandler(),
-                                                                new ServletHandler(),
-                                                                new ErrorHandler() );
-        root.setDisplayName( identity );
-        configureContext( root, configuration() );
-
-        // Register ContextListeners, Servlets and Filters
-        addContextListeners( root, contextListeners );
-        addServlets( root, servlets );
-        addFilters( root, filters );
-
-        // Start
-        server.start();
-    }
-
-    @Override
-    public final void stopJetty()
-        throws Exception
-    {
-        server.stop();
-        for( Connector connector : server.getConnectors() )
-        {
-            connector.stop();
-        }
-        server = null;
-    }
-
-    @Override
-    @SuppressWarnings( "ValueOfIncrementOrDecrementUsed" )
-    public final Interface[] interfacesServed()
-    {
-        Connector[] connectors = server.getConnectors();
-        Interface[] result = new Interface[ connectors.length ];
-        int index = 0;
-        for( Connector connector : connectors )
-        {
-            if( connector instanceof NetworkConnector )
-            {
-                NetworkConnector netConnector = (NetworkConnector) connector;
-                String host = configuration().hostName().get();
-                if( host == null )
-                {
-                    host = netConnector.getHost();
-                    if( host == null ) // If serving all interfaces.
-                    {
-                        try
-                        {
-                            host = InetAddress.getLocalHost().getHostAddress();
-                        }
-                        catch( UnknownHostException e )
-                        {
-                            InternalError error = new InternalError( "UnknownHost for local interface." );
-                            error.initCause( e );
-                            throw error;
-                        }
-                    }
-                }
-                result[ index++] = new InterfaceImpl( host, netConnector.getPort(), servedProtocol() );
-            }
-        }
-        return result;
-    }
-
-    protected abstract JettyConfiguration configuration();
-
-    @SuppressWarnings( "NoopMethodInAbstractClass" )
-    protected HttpConfiguration specializeHttp( HttpConfiguration httpConfig )
-    {
-        return httpConfig;
-    }
-
-    protected ServerConnector buildConnector( Server server, HttpConfiguration httpConfig )
-    {
-        return new ServerConnector( server, new HttpConnectionFactory( httpConfig ) );
-    }
-
-    protected SecurityHandler buildSecurityHandler()
-    {
-        return null;
-    }
-
-    protected abstract Protocol servedProtocol();
-
-}
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/ConstraintInfo.java b/libraries/http/src/main/java/org/qi4j/library/http/ConstraintInfo.java
deleted file mode 100644
index 4d1f4ca..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/ConstraintInfo.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import java.io.Serializable;
-
-public class ConstraintInfo
-        implements Serializable
-{
-
-    public static enum Constraint
-    {
-    }
-
-    public static enum HttpMethod
-    {
-
-        GET, POST, HEAD, PUT, OPTIONS, TRACE, DELETE;
-
-        public static String[] toStringArray( HttpMethod[] methods )
-        {
-            String[] result = new String[ methods.length ];
-            for ( int idx = 0; idx < methods.length; idx++ ) {
-                result[idx] = methods[idx].name();
-            }
-            return result;
-        }
-
-    }
-
-    private final String path;
-
-    private final Constraint constraint;
-
-    private final HttpMethod[] omittedHttpMethods;
-
-    ConstraintInfo( String path, Constraint constraint, HttpMethod[] omittedHttpMethods )
-    {
-        this.path = path;
-        this.constraint = constraint;
-        this.omittedHttpMethods = omittedHttpMethods;
-    }
-
-    public Constraint getConstraint()
-    {
-        return constraint;
-    }
-
-    public HttpMethod[] getOmittedHttpMethods()
-    {
-        return omittedHttpMethods;
-    }
-
-    public String getPath()
-    {
-        return path;
-    }
-
-}
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/ConstraintService.java b/libraries/http/src/main/java/org/qi4j/library/http/ConstraintService.java
deleted file mode 100644
index cb37d72..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/ConstraintService.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import org.eclipse.jetty.security.ConstraintMapping;
-import org.eclipse.jetty.util.security.Constraint;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.library.http.ConstraintInfo.HttpMethod;
-
-@Mixins( ConstraintService.Mixin.class )
-public interface ConstraintService
-        extends ServiceComposite
-{
-
-    ConstraintMapping buildConstraintMapping();
-
-    static abstract class Mixin
-            implements ConstraintService
-    {
-
-        @Service
-        private ServiceReference<ConstraintService> myRef;
-
-        @Override
-        public ConstraintMapping buildConstraintMapping()
-        {
-            ConstraintMapping csMapping = null;
-            ConstraintInfo constraintInfo = myRef.metaInfo( ConstraintInfo.class );
-            if ( constraintInfo != null && constraintInfo.getConstraint() != null ) {
-                Constraint constraint = new Constraint();
-                switch ( constraintInfo.getConstraint() ) {
-                }
-                csMapping = new ConstraintMapping();
-                csMapping.setConstraint( constraint );
-                csMapping.setPathSpec( constraintInfo.getPath() );
-                if ( constraintInfo.getOmittedHttpMethods() != null && constraintInfo.getOmittedHttpMethods().length > 0 ) {
-                    csMapping.setMethodOmissions( HttpMethod.toStringArray( constraintInfo.getOmittedHttpMethods() ) );
-                }
-            }
-            return csMapping;
-        }
-
-    }
-
-}
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/ContextListenerInfo.java b/libraries/http/src/main/java/org/qi4j/library/http/ContextListenerInfo.java
deleted file mode 100644
index 896e668..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/ContextListenerInfo.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import java.io.Serializable;
-import java.util.Map;
-
-public class ContextListenerInfo
-        implements Serializable
-{
-
-    private static final long serialVersionUID = 1L;
-
-    private final Map<String, String> initParams;
-
-    public ContextListenerInfo( Map<String, String> initParams )
-    {
-        this.initParams = initParams;
-    }
-
-    public Map<String, String> initParams()
-    {
-        return initParams;
-    }
-
-}
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/Dispatchers.java b/libraries/http/src/main/java/org/qi4j/library/http/Dispatchers.java
deleted file mode 100644
index c3fd645..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/Dispatchers.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2008 Richard Wallace.
- *
- * Licensed  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.qi4j.library.http;
-
-import java.io.Serializable;
-import java.util.EnumSet;
-import java.util.Iterator;
-
-public class Dispatchers
-    implements Iterable<Dispatchers.Dispatcher>, Serializable
-{
-    public enum Dispatcher
-    {
-        FORWARD, REQUEST
-    }
-
-    private final EnumSet<Dispatcher> dispatchers;
-
-    private Dispatchers( EnumSet<Dispatcher> dispatchers )
-    {
-        this.dispatchers = dispatchers;
-    }
-
-    @Override
-    public Iterator<Dispatcher> iterator()
-    {
-        return dispatchers.iterator();
-    }
-
-    public static Dispatchers dispatchers( Dispatcher first, Dispatcher... rest )
-    {
-        return new Dispatchers( EnumSet.of( first, rest ) );
-    }
-}
\ No newline at end of file
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/FilterInfo.java b/libraries/http/src/main/java/org/qi4j/library/http/FilterInfo.java
deleted file mode 100644
index 5032655..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/FilterInfo.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2008 Richard Wallace.
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.library.http;
-
-import java.io.Serializable;
-import java.util.EnumSet;
-import java.util.Map;
-import javax.servlet.DispatcherType;
-
-public class FilterInfo
-    implements Serializable
-{
-    private static final long serialVersionUID = 1L;
-
-    private final String path;
-    private final Map<String, String> initParameters;
-    private final EnumSet<DispatcherType> dispatchers;
-
-    public FilterInfo( String path, Map<String, String> initParameters, EnumSet<DispatcherType> dispatchers )
-    {
-        this.dispatchers = dispatchers;
-        this.initParameters = initParameters;
-        this.path = path;
-    }
-
-    public String getPath()
-    {
-        return path;
-    }
-
-    public Map<String, String> initParameters()
-    {
-        return initParameters;
-    }
-
-    public EnumSet<DispatcherType> dispatchers()
-    {
-        return dispatchers;
-    }
-}
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/HttpService.java b/libraries/http/src/main/java/org/qi4j/library/http/HttpService.java
deleted file mode 100644
index da71e21..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/HttpService.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.http;
-
-public interface HttpService
-{
-    Interface[] interfacesServed();
-}
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/Interface.java b/libraries/http/src/main/java/org/qi4j/library/http/Interface.java
deleted file mode 100644
index da5d294..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/Interface.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.http;
-
-public interface Interface
-{
-    String hostName();
-
-    int port();
-
-    Protocol protocol();
-
-    public enum Protocol
-    {
-        http, https
-    }
-}
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/InterfaceImpl.java b/libraries/http/src/main/java/org/qi4j/library/http/InterfaceImpl.java
deleted file mode 100644
index 2bf98c1..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/InterfaceImpl.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-class InterfaceImpl
-        implements Interface
-{
-
-    private final String host;
-    private final int port;
-    private final Protocol protocol;
-
-    public InterfaceImpl( String host, int port, Protocol protocol )
-    {
-        this.host = host;
-        this.port = port;
-        this.protocol = protocol;
-    }
-
-    @Override
-    public String hostName()
-    {
-        return host;
-    }
-
-    @Override
-    public int port()
-    {
-        return port;
-    }
-
-    @Override
-    public Protocol protocol()
-    {
-        return protocol;
-    }
-
-}
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/JettyActivation.java b/libraries/http/src/main/java/org/qi4j/library/http/JettyActivation.java
deleted file mode 100644
index cc50789..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/JettyActivation.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.service.ServiceReference;
-
-public interface JettyActivation
-{
-
-    void startJetty()
-            throws Exception;
-
-    void stopJetty()
-            throws Exception;
-
-    public class Activator
-            extends ActivatorAdapter<ServiceReference<JettyActivation>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<JettyActivation> activated )
-                throws Exception
-        {
-            activated.get().startJetty();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<JettyActivation> passivating )
-                throws Exception
-        {
-            passivating.get().stopJetty();
-        }
-
-    }
-
-}
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/JettyConfiguration.java b/libraries/http/src/main/java/org/qi4j/library/http/JettyConfiguration.java
deleted file mode 100644
index 2ad0d18..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/JettyConfiguration.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.library.constraints.annotation.GreaterThan;
-import org.qi4j.library.constraints.annotation.Range;
-
-/**
- * Configuration of the JettyService.
- * 
- * The only mandatory property is port.
- * Other properties are provided with a sensible default respecting the original Jetty defaults.
- */
-// START SNIPPET: config
-public interface JettyConfiguration
-        extends ConfigurationComposite
-{
-
-    // ## Connector Configuration Properties ##################################
-    /**
-     * @return Port on which the {@link JettyService} will listen for incomming requests.
-     */
-    @Range( min = 0, max = 65535 )
-    Property<Integer> port();
-
-    /**
-     * Name or ip representing the interface on which the {@link JettyService} will bind the server socket.
-     * 
-     * If not set the {@link JettyService} will be bound to all interfaces.
-     * 
-     * @return Name or ip representing the interface on which the {@link JettyService} will bind the server socket.
-     */
-    @Optional
-    Property<String> hostName();
-
-    /**
-     * Defaults to false.
-     * 
-     * @return If the {@link JettyService} should collect statistics.
-     */
-    @UseDefaults
-    Property<Boolean> statistics();
-
-    /**
-     * @return Maximum Idle time for connections in milliseconds.
-     */
-    @Optional
-    Property<Integer> maxIdleTime();
-
-    /**
-     * @return Maximum Idle time for connections in milliseconds when resources are low.
-     */
-    @Optional
-    Property<Integer> lowResourceMaxIdleTime();
-
-    /**
-     * @return The size of the buffer to be used for request headers in bytes.
-     */
-    @Optional
-    @GreaterThan( 0 )
-    Property<Integer> requestHeaderSize();
-
-    /**
-     * @return The size of the buffer to be used for response headers in bytes.
-     */
-    @Optional
-    @GreaterThan( 0 )
-    Property<Integer> responseHeaderSize();
-
-    /**
-     * Size of the content buffer for sending responses in bytes.
-     * 
-     * These buffers are only used for active connections that are sending responses with bodies that will not fit
-     * within the header buffer.
-     * 
-     * @return The size of the content buffer for sending responses in bytes.
-     */
-    @Optional
-    @GreaterThan( 0 )
-    Property<Integer> responseBufferSize();
-
-    // ## ServletContext Configuration Properties #############################
-    /**
-     * url prefix of the {@link JettyService}.
-     * 
-     * Defaulted to "/".
-     * 
-     * @return The url prefix of the {@link JettyService}.
-     */
-    @Optional
-    Property<String> contextPath();
-
-    @Optional
-    Property<String> resourcePath();
-
-    /**
-     * Virtual hosts for this JettyService.
-     * 
-     * Coma separated list of hostnames.
-     * 
-     * @return Virtual hosts for this JettyService.
-     */
-    @Optional
-    Property<String> virtualHosts();
-
-    /**
-     * Welcome files names for this JettyService.
-     * 
-     * Coma separated list of welcome files.
-     * Defaulted to index.html.
-     * 
-     * @return Welcome files names for this JettyService.
-     */
-    @Optional
-    Property<String> welcomeFiles();
-
-    /**
-     * @return Maximum Form content size.
-     */
-    @Optional
-    @GreaterThan( 0 )
-    Property<Integer> maxFormContentSize();
-
-    // ## Server Configuration Properties #####################################
-    /**
-     * @return If {@link JettyService} populates http header with server date.
-     */
-    @Optional
-    Property<Boolean> sendDateHeader();
-
-    /**
-     * @return If {@link JettyService} expose it's implementation version.
-     */
-    @Optional
-    Property<Boolean> sendServerVersion();
-
-    /**
-     * Timeout use to wait for active requests to terminate on shutdown in milliseconds.
-     * 
-     * Jetty will stop gracefully only if this property is set.
-     * 
-     * @return Timeout use to wait for active requests to terminate on shutdown in milliseconds.
-     */
-    @Optional
-    @GreaterThan( 0 )
-    Property<Integer> gracefullShutdownTimeout();
-
-}
-// END SNIPPET: config
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/JettyConfigurationHelper.java b/libraries/http/src/main/java/org/qi4j/library/http/JettyConfigurationHelper.java
deleted file mode 100644
index 884da24..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/JettyConfigurationHelper.java
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import java.security.Provider;
-import java.security.Security;
-import java.util.Map;
-import javax.servlet.Filter;
-import javax.servlet.Servlet;
-import javax.servlet.ServletContextListener;
-import org.eclipse.jetty.server.ConnectorStatistics;
-import org.eclipse.jetty.server.HttpConfiguration;
-import org.eclipse.jetty.server.LowResourceMonitor;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.SslConnectionFactory;
-import org.eclipse.jetty.servlet.DefaultServlet;
-import org.eclipse.jetty.servlet.FilterHolder;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-import org.qi4j.api.common.InvalidApplicationException;
-import org.qi4j.api.service.ServiceReference;
-
-final class JettyConfigurationHelper
-{
-
-    private static final Integer DEFAULT_PORT = 8080;
-
-    private static final String[] DEFAULT_WELCOME_FILES = new String[]
-    {
-        "index.html"
-    };
-
-    private static final String COMA = ",";
-
-    static void configureServer( Server server, JettyConfiguration config )
-    {
-        // Shutdown
-        Integer gracefullShudownTimeout = config.gracefullShutdownTimeout().get();
-        if( gracefullShudownTimeout != null )
-        {
-            server.setStopTimeout( gracefullShudownTimeout );
-        }
-
-        // Low resource max idle time
-        Integer lowResourceMaxIdleTime = config.lowResourceMaxIdleTime().get();
-        if( lowResourceMaxIdleTime != null )
-        {
-            LowResourceMonitor lowResourceMonitor = new LowResourceMonitor( server );
-            lowResourceMonitor.setLowResourcesIdleTimeout( lowResourceMaxIdleTime );
-            server.addBean( lowResourceMonitor );
-        }
-
-        // Statistics
-        if( config.statistics().get() )
-        {
-            server.addBean( new ConnectorStatistics() );
-        }
-    }
-
-    static void configureHttp( HttpConfiguration httpConfig, JettyConfiguration config )
-    {
-        // Date header
-        Boolean sendDateHeader = config.sendDateHeader().get();
-        if( sendDateHeader != null )
-        {
-            httpConfig.setSendDateHeader( sendDateHeader );
-        }
-
-        // Server version
-        Boolean sendServerVersion = config.sendServerVersion().get();
-        if( sendServerVersion != null )
-        {
-            httpConfig.setSendServerVersion( sendServerVersion );
-        }
-
-        // Header sizes
-        Integer requestHeaderSize = config.requestHeaderSize().get();
-        if( requestHeaderSize != null )
-        {
-            httpConfig.setRequestHeaderSize( requestHeaderSize );
-        }
-        Integer responseHeaderSize = config.responseHeaderSize().get();
-        if( responseHeaderSize != null )
-        {
-            httpConfig.setResponseHeaderSize( responseHeaderSize );
-        }
-
-        // Buffer sizes
-        Integer responseBufferSize = config.responseBufferSize().get();
-        if( responseBufferSize != null )
-        {
-            httpConfig.setOutputBufferSize( responseBufferSize );
-        }
-
-    }
-
-    static void configureConnector( ServerConnector connector, JettyConfiguration config )
-    {
-        // Host and Port
-        connector.setHost( config.hostName().get() );
-        Integer port = config.port().get();
-        if( port == null )
-        {
-            port = DEFAULT_PORT;
-        }
-        connector.setPort( port );
-
-        // Max idle times
-        Integer maxIdleTime = config.maxIdleTime().get();
-        if( maxIdleTime != null )
-        {
-            connector.setIdleTimeout( maxIdleTime );
-        }
-    }
-
-    static void configureSsl( SslConnectionFactory sslConnFactory, SecureJettyConfiguration config )
-    {
-        SslContextFactory ssl = sslConnFactory.getSslContextFactory();
-
-        boolean needBouncyCastle = false;
-
-        // KeyStore
-        String keystoreType = config.keystoreType().get();
-        String keystorePath = config.keystorePath().get();
-        String keystorePassword = config.keystorePassword().get();
-        ssl.setKeyStoreType( keystoreType );
-        if( "PKCS12".equals( keystoreType ) )
-        {
-            ssl.setKeyStoreProvider( "BC" ); // WARN This one needs BouncyCastle on the classpath
-            needBouncyCastle = true;
-        }
-        ssl.setKeyStorePath( keystorePath );
-        ssl.setKeyStorePassword( keystorePassword );
-
-        // Certificate alias
-        String certAlias = config.certAlias().get();
-        if( certAlias != null )
-        {
-            ssl.setCertAlias( certAlias );
-        }
-
-        // TrustStore
-        String truststoreType = config.truststoreType().get();
-        String truststorePath = config.truststorePath().get();
-        String truststorePassword = config.truststorePassword().get();
-        if( truststoreType != null && truststorePath != null )
-        {
-            ssl.setTrustStoreType( truststoreType );
-            if( "PKCS12".equals( truststoreType ) )
-            {
-                ssl.setTrustStoreProvider( "BC" );
-                needBouncyCastle = true;
-            }
-            ssl.setTrustStorePath( truststorePath );
-            ssl.setTrustStorePassword( truststorePassword );
-        }
-
-        // Need / Want Client Auth
-        Boolean want = config.wantClientAuth().get();
-        if( want != null )
-        {
-            ssl.setWantClientAuth( want );
-        }
-        Boolean need = config.needClientAuth().get();
-        if( need != null )
-        {
-            ssl.setNeedClientAuth( need );
-        }
-
-        // Algorithms
-        String secureRandomAlgo = config.secureRandomAlgorithm().get();
-        if( secureRandomAlgo != null )
-        {
-            ssl.setSecureRandomAlgorithm( secureRandomAlgo );
-        }
-        String cipherExcludesConfigString = config.excludeCipherSuites().get();
-        if( cipherExcludesConfigString != null )
-        {
-            String[] cipherExcludes = cipherExcludesConfigString.split( COMA );
-            if( cipherExcludes.length > 0 )
-            {
-                ssl.setExcludeCipherSuites( cipherExcludes );
-            }
-        }
-        String cipherIncludesConfigString = config.includeCipherSuites().get();
-        if( cipherIncludesConfigString != null )
-        {
-            String[] cipherIncludes = cipherIncludesConfigString.split( COMA );
-            if( cipherIncludes.length > 0 )
-            {
-                ssl.setIncludeCipherSuites( cipherIncludes );
-            }
-        }
-
-        // SSL Handling
-        Boolean cacheSslSessions = config.cacheSslSessions().get();
-        if( cacheSslSessions != null )
-        {
-            ssl.setSessionCachingEnabled( cacheSslSessions );
-        }
-        ssl.setRenegotiationAllowed( config.allowRenegotiation().get() );
-
-        // Validation Flags
-        Integer maxCertPathLength = config.maxCertPathLength().get();
-        if( maxCertPathLength != null )
-        {
-            ssl.setMaxCertPathLength( maxCertPathLength );
-        }
-        ssl.setValidateCerts( config.validateServerCert().get() );
-        ssl.setValidatePeerCerts( config.validatePeerCerts().get() );
-
-        // Validation CRL
-        String crlFilePath = config.crlFilePath().get();
-        if( crlFilePath != null && crlFilePath.length() > 0 )
-        {
-            ssl.setCrlPath( crlFilePath );
-        }
-        ssl.setEnableCRLDP( config.enableCRLDP().get() );
-
-        // Validation OCSP
-        ssl.setEnableOCSP( config.enableOCSP().get() );
-        String ocspURL = config.ocspResponderURL().get();
-        if( ocspURL != null )
-        {
-            ssl.setOcspResponderURL( ocspURL );
-        }
-
-        // Load BouncyCastle ?
-        if( needBouncyCastle )
-        {
-            Provider bc = Security.getProvider( "BC" );
-            if( bc == null )
-            {
-                try
-                {
-                    Security.addProvider( (Provider) Class.forName( "org.bouncycastle.jce.provider.BouncyCastleProvider" ).newInstance() );
-                }
-                catch( Exception ex )
-                {
-                    throw new InvalidApplicationException( "Need to open a PKCS#12 but was unable to register BouncyCastle, check your classpath", ex );
-                }
-            }
-        }
-    }
-
-    static void configureContext( ServletContextHandler root, JettyConfiguration config )
-    {
-        // Context path
-        String contextPath = config.contextPath().get();
-        if( contextPath != null && contextPath.length() > 0 )
-        {
-            root.setContextPath( contextPath );
-        }
-
-        // Root resource base
-        String resourcePath = config.resourcePath().get();
-        if( resourcePath != null && resourcePath.length() > 0 )
-        {
-            root.addServlet( DefaultServlet.class, "/" );
-            root.setResourceBase( resourcePath );
-        }
-
-        // Max form content size
-        Integer maxFormContentSize = config.maxFormContentSize().get();
-        if( maxFormContentSize != null )
-        {
-            root.setMaxFormContentSize( maxFormContentSize );
-        }
-
-        // Virtual hosts
-        String virtualHostsConfigString = config.virtualHosts().get();
-        if( virtualHostsConfigString != null )
-        {
-            String[] virtualHosts = virtualHostsConfigString.split( COMA );
-            if( virtualHosts.length > 0 )
-            {
-                root.setVirtualHosts( virtualHosts );
-            }
-        }
-
-        // Welcome files
-        String welcomeFilesConfigString = config.welcomeFiles().get();
-        if( welcomeFilesConfigString == null )
-        {
-            root.setWelcomeFiles( DEFAULT_WELCOME_FILES );
-        }
-        else
-        {
-            String[] welcomeFiles = welcomeFilesConfigString.split( COMA );
-            if( welcomeFiles.length == 0 )
-            {
-                root.setWelcomeFiles( DEFAULT_WELCOME_FILES );
-            }
-            else
-            {
-                root.setWelcomeFiles( welcomeFiles );
-            }
-        }
-    }
-
-    static void addContextListeners( ServletContextHandler root, Iterable<ServiceReference<ServletContextListener>> contextListeners )
-    {
-        // Iterate the available context listeners and add them to the server
-        for( ServiceReference<ServletContextListener> contextListener : contextListeners )
-        {
-            ContextListenerInfo contextListenerInfo = contextListener.metaInfo( ContextListenerInfo.class );
-            Map<String, String> initParams = contextListenerInfo.initParams();
-            for( Map.Entry<String, String> entry : initParams.entrySet() )
-            {
-                root.setInitParameter( entry.getKey(), entry.getValue() );
-            }
-            root.addEventListener( contextListener.get() );
-        }
-    }
-
-    static void addServlets( ServletContextHandler root, Iterable<ServiceReference<Servlet>> servlets )
-    {
-        // Iterate the available servlets and add it to the server
-        for( ServiceReference<Servlet> servlet : servlets )
-        {
-            ServletInfo servletInfo = servlet.metaInfo( ServletInfo.class );
-            String servletPath = servletInfo.getPath();
-            Servlet servletInstance = servlet.get();
-            ServletHolder holder = new ServletHolder( servletInstance );
-            holder.setInitParameters( servletInfo.initParams() );
-            root.addServlet( holder, servletPath );
-        }
-    }
-
-    static void addFilters( ServletContextHandler root, Iterable<ServiceReference<Filter>> filters )
-    {
-        // Iterate the available filters and add them to the server
-        for( ServiceReference<Filter> filter : filters )
-        {
-            FilterInfo filterInfo = filter.metaInfo( FilterInfo.class );
-            String filterPath = filterInfo.getPath();
-
-            Filter filterInstance = filter.get();
-            FilterHolder holder = new FilterHolder( filterInstance );
-            holder.setInitParameters( filterInfo.initParameters() );
-            root.addFilter( holder, filterPath, filterInfo.dispatchers() );
-        }
-    }
-
-    private JettyConfigurationHelper()
-    {
-    }
-
-}
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/JettyMixin.java b/libraries/http/src/main/java/org/qi4j/library/http/JettyMixin.java
deleted file mode 100644
index 2621935..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/JettyMixin.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import javax.management.MBeanServer;
-import javax.servlet.Filter;
-import javax.servlet.Servlet;
-import javax.servlet.ServletContextListener;
-import org.eclipse.jetty.server.Server;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.library.http.Interface.Protocol;
-
-public class JettyMixin
-        extends AbstractJettyMixin
-{
-
-    @This
-    private Configuration<JettyConfiguration> configuration;
-
-    public JettyMixin( @This Identity meAsIdentity,
-                       @Service Server jettyServer,
-                       @Service Iterable<ServiceReference<ServletContextListener>> contextListeners,
-                       @Service Iterable<ServiceReference<Servlet>> servlets,
-                       @Service Iterable<ServiceReference<Filter>> filters,
-                       @Optional @Service MBeanServer mBeanServer )
-    {
-        super( meAsIdentity.identity().get(), jettyServer, contextListeners, servlets, filters, mBeanServer );
-    }
-
-    @Override
-    protected JettyConfiguration configuration()
-    {
-        return configuration.get();
-    }
-
-    @Override
-    protected Protocol servedProtocol()
-    {
-        return Protocol.http;
-    }
-
-}
\ No newline at end of file
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/JettyService.java b/libraries/http/src/main/java/org/qi4j/library/http/JettyService.java
deleted file mode 100644
index f74a81b..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/JettyService.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-@Mixins( JettyMixin.class )
-@Activators( JettyActivation.Activator.class )
-public interface JettyService
-        extends HttpService, JettyActivation, ServiceComposite
-{
-}
\ No newline at end of file
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/JettyServiceAssembler.java b/libraries/http/src/main/java/org/qi4j/library/http/JettyServiceAssembler.java
deleted file mode 100644
index eebb784..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/JettyServiceAssembler.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2008 Edward Yakop.
- * Copyright 2011-2014 Paul Merlin.
- *
- * Licensed  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.qi4j.library.http;
-
-import org.eclipse.jetty.server.Server;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.service.importer.InstanceImporter;
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ImportedServiceDeclaration;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-
-public class JettyServiceAssembler
-    extends Assemblers.VisibilityIdentityConfig<JettyServiceAssembler>
-{
-    protected ModuleAssembly serverModule;
-    protected Visibility serverVisibility = Visibility.module;
-    protected String serverIdentity;
-
-    /**
-     * @param serverModule Defaults to assembled module
-     * @param serverVisibility Defaults to {@link Visibility#module}
-     */
-    public JettyServiceAssembler withServer( ModuleAssembly serverModule, Visibility serverVisibility )
-    {
-        this.serverModule = serverModule;
-        this.serverVisibility = serverVisibility;
-        return this;
-    }
-
-    public JettyServiceAssembler serverIdentifiedBy( String serverIdentity )
-    {
-        this.serverIdentity = serverIdentity;
-        return this;
-    }
-
-    @Override
-    public final void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ServiceDeclaration service = module.services( httpService() ).
-            visibleIn( visibility() ).
-            instantiateOnStartup();
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        if( hasConfig() )
-        {
-            configModule().entities( configurationEntity() ).visibleIn( configVisibility() );
-        }
-        assembleServer( module );
-    }
-
-    protected final void assembleServer( ModuleAssembly module )
-    {
-        serverModule = serverModule != null ? serverModule : module;
-        ImportedServiceDeclaration server = serverModule.importedServices( Server.class ).
-            importedBy( InstanceImporter.class ).
-            setMetaInfo( new Server() ).
-            visibleIn( serverVisibility );
-        if( serverIdentity != null )
-        {
-            server.identifiedBy( serverIdentity );
-        }
-    }
-
-    protected Class<? extends JettyConfiguration> configurationEntity()
-    {
-        return JettyConfiguration.class;
-    }
-
-    protected Class<? extends JettyService> httpService()
-    {
-        return JettyService.class;
-    }
-}
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/SecureJettyConfiguration.java b/libraries/http/src/main/java/org/qi4j/library/http/SecureJettyConfiguration.java
deleted file mode 100644
index ea26830..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/SecureJettyConfiguration.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import java.security.SecureRandom;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.library.constraints.annotation.GreaterThan;
-import org.qi4j.library.constraints.annotation.OneOf;
-
-/**
- * Configuration for {@link SecureJettyMixin}.
- *
- * Only the three keystore related properties are mandatory, all the other ones have sensible defaults.
- */
-// START SNIPPET: configssl
-public interface SecureJettyConfiguration
-        extends JettyConfiguration
-{
-
-    /**
-     * @return Type of the keystore that contains the {@link SecureJettyService} certificate.
-     */
-    @OneOf( { "PKCS12", "JCEKS", "JKS" } )
-    Property<String> keystoreType();
-
-    /**
-     * @return Path of the keystore that contains the {@link SecureJettyService} certificate.
-     */
-    Property<String> keystorePath();
-
-    /**
-     * @return Password of the keystore that contains the {@link SecureJettyService} certificate.
-     */
-    @UseDefaults
-    Property<String> keystorePassword();
-
-    /**
-     * Alias of the {@link SecureJettyService} certificate.
-     *
-     * If not set, the first certificate found in the keystore is used.
-     *
-     * @return Alias of the {@link SecureJettyService} certificate.
-     */
-    @Optional
-    Property<String> certAlias();
-
-    /**
-     * @return Type of the keystore that contains the certificates trusted by the {@link SecureJettyService}.
-     */
-    @Optional
-    @OneOf( { "PKCS12", "JCEKS", "JKS" } )
-    Property<String> truststoreType();
-
-    /**
-     * @return Path of the keystore that contains the certificates trusted by the {@link SecureJettyService}.
-     */
-    @Optional
-    Property<String> truststorePath();
-
-    /**
-     * @return Password of the keystore that contains the certificates trusted by the {@link SecureJettyService}.
-     */
-    @UseDefaults
-    Property<String> truststorePassword();
-
-    /**
-     * If the {@link SecureJettyService} wants client authentication.
-     *
-     * Defaults to false. If set to true, the {@link SecureJettyService} will expose the fact that it can handle client
-     * certificate based authentication.
-     *
-     * @return If the {@link SecureJettyService} wants client authentication.
-     */
-    @UseDefaults
-    Property<Boolean> wantClientAuth();
-
-    /**
-     * If the {@link SecureJettyService} needs client authentication.
-     *
-     * Defaults to false. If set to true, only mutually authentified connections will be accepted.
-     *
-     * @return If the {@link SecureJettyService} needs client authentication.
-     */
-    @UseDefaults
-    Property<Boolean> needClientAuth();
-
-    /**
-     * The algorithm used by {@link SecureRandom} for SSL operations.
-     *
-     * Default JVM algorithm is used if omitted.
-     *
-     * @return The algorithm used by {@link SecureRandom} for SSL operations.
-     */
-    @Optional
-    Property<String> secureRandomAlgorithm();
-
-    /**
-     * @return Coma separated list of included cipher suites.
-     */
-    @Optional
-    Property<String> includeCipherSuites();
-
-    /**
-     * @return Coma separated list of excluded cipher suites.
-     */
-    @Optional
-    Property<String> excludeCipherSuites();
-
-    /**
-     * If SSL Session caching is enabled.
-     *
-     * SSL Session caching is enabled by default.
-     *
-     * @return If SSL Session caching is enabled.
-     */
-    @Optional
-    Property<Boolean> cacheSslSessions();
-
-    /**
-     * If SSL/TLS renegotiation is allowed.
-     *
-     * Defaults to false. Setting this to true can open vulnerabilities, be sure of what you are doing.
-     *
-     * @return If SSL/TLS renegotiation is allowed.
-     */
-    @UseDefaults
-    Property<Boolean> allowRenegotiation();
-
-    /**
-     * Maximum number of intermediate certificates in the PKIX path.
-     *
-     * Set to -1 for unlimited. Defaulted to -1.
-     *
-     * @return Maximum number of intermediate certificates in the PKIX path
-     */
-    @Optional
-    @GreaterThan( -2 )
-    Property<Integer> maxCertPathLength();
-
-    /**
-     * If the {@link SecureJettyService} certificate MUST be PKIX validated.
-     *
-     * <p><b>IMPORTANT:</b></p>
-     * <ul>
-     *   <li>Server certificate validation do not use the configured truststore but the one of the JVM.</li>
-     *   <li>Server certificates validation behavior depends on CRL and OCSP related configuration properties.</li>
-     * </ul>
-     * <p>
-     * Defaults to false.
-     * </p>
-     * @return If the {@link SecureJettyService} certificate MUST be PKIX validated.
-     */
-    @UseDefaults
-    Property<Boolean> validateServerCert();
-
-    /**
-     * If client certificates PKIX validation MUST use either CRL or OCSP.
-     *
-     * <p><b>IMPORTANT:</b></p>
-     * <ul>
-     *   <li>Peer certificates validation use the configured truststore if present, the one of the JVM if not.</li>
-     *   <li>Peer certificates validation behavior depends on CRL and OCSP related configuration properties.</li>
-     * </ul>
-     * <p>
-     * Defaults to false.
-     * </p>
-     * @return If client certificates PKIX validation MUST use either CRL or OCSP.
-     */
-    @UseDefaults
-    Property<Boolean> validatePeerCerts();
-
-    /**
-     * @return The path of a local CRL file in PEM or DER format used during PKIX validations.
-     */
-    @Optional
-    Property<String> crlFilePath();
-
-    /**
-     * @return If PKIX validations use the CRL Distribution Points declared in CA certificates.
-     */
-    @UseDefaults
-    Property<Boolean> enableCRLDP();
-
-    /**
-     * @return If PKIX validations use the OCSP protocol against responders declared in CA certificates.
-     */
-    @UseDefaults
-    Property<Boolean> enableOCSP();
-
-    /**
-     * @return The URL of an OCSP responder to use during PKIX validations.
-     */
-    @Optional
-    Property<String> ocspResponderURL();
-
-}
-// END SNIPPET: configssl
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/SecureJettyMixin.java b/libraries/http/src/main/java/org/qi4j/library/http/SecureJettyMixin.java
deleted file mode 100644
index bab45d9..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/SecureJettyMixin.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import javax.management.MBeanServer;
-import javax.servlet.Filter;
-import javax.servlet.Servlet;
-import javax.servlet.ServletContextListener;
-import org.eclipse.jetty.security.ConstraintMapping;
-import org.eclipse.jetty.security.ConstraintSecurityHandler;
-import org.eclipse.jetty.security.SecurityHandler;
-import org.eclipse.jetty.server.HttpConfiguration;
-import org.eclipse.jetty.server.HttpConnectionFactory;
-import org.eclipse.jetty.server.SecureRequestCustomizer;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.SslConnectionFactory;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.library.http.Interface.Protocol;
-
-import static org.qi4j.library.http.JettyConfigurationHelper.configureSsl;
-
-public class SecureJettyMixin
-    extends AbstractJettyMixin
-{
-
-    @This
-    private Configuration<SecureJettyConfiguration> configuration;
-
-    @Optional
-    @Service
-    private Iterable<ConstraintService> constraintServices;
-
-    public SecureJettyMixin( @This Identity meAsIdentity,
-                             @Service Server jettyServer,
-                             @Service Iterable<ServiceReference<ServletContextListener>> contextListeners,
-                             @Service Iterable<ServiceReference<Servlet>> servlets,
-                             @Service Iterable<ServiceReference<Filter>> filters,
-                             @Optional @Service MBeanServer mBeanServer )
-    {
-        super( meAsIdentity.identity().get(), jettyServer, contextListeners, servlets, filters, mBeanServer );
-    }
-
-    @Override
-    protected JettyConfiguration configuration()
-    {
-        return configuration.get();
-    }
-
-    @Override
-    protected HttpConfiguration specializeHttp( HttpConfiguration httpConfig )
-    {
-        HttpConfiguration httpsConfig = new HttpConfiguration( httpConfig );
-        httpsConfig.addCustomizer( new SecureRequestCustomizer() );
-        return httpsConfig;
-    }
-
-    @Override
-    protected SecurityHandler buildSecurityHandler()
-    {
-        if( constraintServices != null )
-        {
-            ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
-            for( ConstraintService eachConstraintService : constraintServices )
-            {
-                ConstraintMapping csMapping = eachConstraintService.buildConstraintMapping();
-                if( csMapping != null )
-                {
-                    securityHandler.addConstraintMapping( csMapping );
-                }
-            }
-            if( !securityHandler.getConstraintMappings().isEmpty() )
-            {
-                return securityHandler;
-            }
-        }
-        return super.buildSecurityHandler();
-    }
-
-    @Override
-    protected ServerConnector buildConnector( Server server, HttpConfiguration httpConfig )
-    {
-        SslConnectionFactory sslConnFactory = new SslConnectionFactory();
-        configureSsl( sslConnFactory, configuration.get() );
-        return new ServerConnector( server, sslConnFactory, new HttpConnectionFactory( httpConfig ) );
-    }
-
-    @Override
-    protected Protocol servedProtocol()
-    {
-        return Protocol.https;
-    }
-
-}
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/SecureJettyService.java b/libraries/http/src/main/java/org/qi4j/library/http/SecureJettyService.java
deleted file mode 100644
index 8b03514..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/SecureJettyService.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import org.qi4j.api.mixin.Mixins;
-
-@Mixins( SecureJettyMixin.class )
-public interface SecureJettyService
-        extends JettyService
-{
-}
\ No newline at end of file
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/SecureJettyServiceAssembler.java b/libraries/http/src/main/java/org/qi4j/library/http/SecureJettyServiceAssembler.java
deleted file mode 100644
index a16b6c3..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/SecureJettyServiceAssembler.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-public class SecureJettyServiceAssembler
-        extends JettyServiceAssembler
-{
-
-    @Override
-    protected Class<? extends JettyConfiguration> configurationEntity()
-    {
-        return SecureJettyConfiguration.class;
-    }
-
-    @Override
-    protected Class<? extends JettyService> httpService()
-    {
-        return SecureJettyService.class;
-    }
-
-}
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/ServletInfo.java b/libraries/http/src/main/java/org/qi4j/library/http/ServletInfo.java
deleted file mode 100644
index 1281093..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/ServletInfo.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.Map;
-
-/**
- * JAVADOC
- */
-public class ServletInfo
-    implements Serializable
-{
-    private static final long serialVersionUID = 1L;
-
-    private final String path;
-    private final Map<String, String> initParams;
-
-    public ServletInfo( String mountPath )
-    {
-        this( mountPath, Collections.<String, String>emptyMap() );
-    }
-
-    public ServletInfo( String mountPath, Map<String, String> initParams )
-    {
-        path = mountPath;
-        this.initParams = initParams;
-    }
-
-    public String getPath()
-    {
-        return path;
-    }
-
-    public Map<String, String> initParams()
-    {
-        return initParams;
-    }
-}
\ No newline at end of file
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/Servlets.java b/libraries/http/src/main/java/org/qi4j/library/http/Servlets.java
deleted file mode 100644
index 9b4bb28..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/Servlets.java
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * Copyright (c) 2008, Richard Wallace. All Rights Reserved.
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.library.http;
-
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.Map;
-import java.util.UUID;
-import javax.servlet.DispatcherType;
-import javax.servlet.Filter;
-import javax.servlet.Servlet;
-import javax.servlet.ServletContextListener;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.http.ConstraintInfo.Constraint;
-import org.qi4j.library.http.ConstraintInfo.HttpMethod;
-import org.qi4j.library.http.Dispatchers.Dispatcher;
-
-import static org.qi4j.api.common.Visibility.layer;
-
-public final class Servlets
-{
-
-    private Servlets()
-    {
-    }
-
-    public static ContextListenerDeclaration listen()
-    {
-        return new ContextListenerDeclaration();
-    }
-
-    public static ContextListenerAssembler addContextListeners( ContextListenerDeclaration... contextListenerDeclarations )
-    {
-        return new ContextListenerAssembler( contextListenerDeclarations );
-    }
-
-    public static class ContextListenerAssembler
-    {
-
-        final ContextListenerDeclaration[] contextListenerDeclarations;
-
-        ContextListenerAssembler( ContextListenerDeclaration... eventListenerDeclarations )
-        {
-            this.contextListenerDeclarations = eventListenerDeclarations;
-        }
-
-        public void to( ModuleAssembly module )
-                throws AssemblyException
-        {
-            for ( ContextListenerDeclaration contextListenerDeclaration : contextListenerDeclarations ) {
-                module.services( contextListenerDeclaration.contextListener() ).
-                        setMetaInfo( contextListenerDeclaration.contextListenerInfo() ).
-                        instantiateOnStartup().visibleIn( layer );
-            }
-        }
-
-    }
-
-    public static class ContextListenerDeclaration
-    {
-
-        Class<? extends ServiceComposite> contextListener;
-
-        Map<String, String> initParams = Collections.emptyMap();
-
-        public <T extends ServletContextListener & ServiceComposite> ContextListenerDeclaration with( Class<T> contextListener )
-        {
-            this.contextListener = contextListener;
-            return this;
-        }
-
-        public Class<? extends ServiceComposite> contextListener()
-        {
-            return contextListener;
-        }
-
-        public ContextListenerDeclaration withInitParams( Map<String, String> initParams )
-        {
-            this.initParams = initParams;
-            return this;
-        }
-
-        private ContextListenerInfo contextListenerInfo()
-        {
-            return new ContextListenerInfo( initParams );
-        }
-
-    }
-
-    public static ServletDeclaration serve( String path )
-    {
-        return new ServletDeclaration( path );
-    }
-
-    public static ServletAssembler addServlets( ServletDeclaration... servletDeclarations )
-    {
-        return new ServletAssembler( servletDeclarations );
-    }
-
-    public static class ServletAssembler
-    {
-
-        final ServletDeclaration[] servletDeclarations;
-
-        ServletAssembler( ServletDeclaration... servletDeclarations )
-        {
-            this.servletDeclarations = servletDeclarations;
-        }
-
-        public void to( ModuleAssembly module )
-                throws AssemblyException
-        {
-            for ( ServletDeclaration servletDeclaration : servletDeclarations ) {
-                module.services( servletDeclaration.servlet() ).
-                        setMetaInfo( servletDeclaration.servletInfo() ).
-                        instantiateOnStartup().visibleIn( layer );
-            }
-        }
-
-    }
-
-    public static class ServletDeclaration
-    {
-
-        String path;
-
-        Class<? extends ServiceComposite> servlet;
-
-        Map<String, String> initParams = Collections.emptyMap();
-
-        ServletDeclaration( String path )
-        {
-            this.path = path;
-        }
-
-        public <T extends Servlet & ServiceComposite> ServletDeclaration with( Class<T> servlet )
-        {
-            this.servlet = servlet;
-            return this;
-        }
-
-        public ServletDeclaration withInitParams( Map<String, String> initParams )
-        {
-            this.initParams = initParams;
-            return this;
-        }
-
-        Class<? extends ServiceComposite> servlet()
-        {
-            return servlet;
-        }
-
-        ServletInfo servletInfo()
-        {
-            return new ServletInfo( path, initParams );
-        }
-
-    }
-
-    public static FilterAssembler filter( String path )
-    {
-        return new FilterAssembler( path );
-    }
-
-    public static FilterDeclaration addFilters( FilterAssembler... filterAssemblers )
-    {
-        return new FilterDeclaration( filterAssemblers );
-    }
-
-    public static class FilterDeclaration
-    {
-
-        final FilterAssembler[] filterAssemblers;
-
-        FilterDeclaration( FilterAssembler... filterAssemblers )
-        {
-            this.filterAssemblers = filterAssemblers;
-        }
-
-        @SuppressWarnings( "unchecked" )
-        public void to( ModuleAssembly module )
-                throws AssemblyException
-        {
-            for ( FilterAssembler filterAssembler : filterAssemblers ) {
-                module.services( filterAssembler.filter() ).
-                        setMetaInfo( filterAssembler.filterInfo() ).
-                        instantiateOnStartup().visibleIn( layer );
-            }
-        }
-
-    }
-
-    public static class FilterAssembler
-    {
-
-        String path;
-
-        Class<? extends ServiceComposite> filter;
-
-        EnumSet<DispatcherType> dispatchers;
-
-        Map<String, String> initParams = Collections.emptyMap();
-
-        FilterAssembler( String path )
-        {
-            this.path = path;
-        }
-
-        public <T extends Filter & ServiceComposite> FilterAssembler through(
-                Class<T> filter )
-        {
-            this.filter = filter;
-            return this;
-        }
-
-        public FilterAssembler on( DispatcherType first, DispatcherType... rest )
-        {
-            dispatchers = EnumSet.of( first, rest );
-            return this;
-        }
-
-        @Deprecated
-        public FilterAssembler on( Dispatcher first, Dispatcher... rest )
-        {
-            EnumSet<DispatcherType> dispatch = EnumSet.noneOf( DispatcherType.class );
-            for ( Dispatcher each : Dispatchers.dispatchers( first, rest ) ) {
-                switch ( each ) {
-                    case FORWARD:
-                        dispatch.add( DispatcherType.FORWARD );
-                        break;
-                    case REQUEST:
-                        dispatch.add( DispatcherType.REQUEST );
-                        break;
-                }
-            }
-            dispatchers = dispatch;
-            return this;
-        }
-
-        public FilterAssembler withInitParams( Map<String, String> initParams )
-        {
-            this.initParams = initParams;
-            return this;
-        }
-
-        Class<? extends ServiceComposite> filter()
-        {
-            return filter;
-        }
-
-        FilterInfo filterInfo()
-        {
-            return new FilterInfo( path, initParams, dispatchers );
-        }
-
-    }
-
-    public static ConstraintAssembler constrain( String path )
-    {
-        return new ConstraintAssembler( path );
-    }
-
-    public static ConstraintDeclaration addConstraints( ConstraintAssembler... constraintAssemblers )
-    {
-        return new ConstraintDeclaration( constraintAssemblers );
-    }
-
-    public static class ConstraintDeclaration
-    {
-
-        private final ConstraintAssembler[] constraintAssemblers;
-
-        private ConstraintDeclaration( ConstraintAssembler[] constraintAssemblers )
-        {
-            this.constraintAssemblers = constraintAssemblers;
-        }
-
-        public void to( ModuleAssembly module )
-                throws AssemblyException
-        {
-            // TODO Refactor adding Map<ServiceAssembly,T> ServiceDeclaration.getMetaInfos( Class<T> type ); in bootstrap & runtime
-            // This would allow removing the ConstraintServices instances and this horrible hack with random UUIDs
-            for ( ConstraintAssembler eachAssembler : constraintAssemblers ) {
-                module.addServices( ConstraintService.class ).identifiedBy( UUID.randomUUID().toString() ).setMetaInfo( eachAssembler.constraintInfo() );
-            }
-        }
-
-    }
-
-    public static class ConstraintAssembler
-    {
-
-        private final String path;
-
-        private Constraint constraint;
-
-        private HttpMethod[] omittedHttpMethods = new HttpMethod[]{};
-
-        private ConstraintAssembler( String path )
-        {
-            this.path = path;
-        }
-
-        public ConstraintAssembler by( Constraint constraint )
-        {
-            this.constraint = constraint;
-            return this;
-        }
-
-        public ConstraintAssembler butNotOn( HttpMethod... omittedHttpMethods )
-        {
-            this.omittedHttpMethods = omittedHttpMethods;
-            return this;
-        }
-
-        ConstraintInfo constraintInfo()
-        {
-            return new ConstraintInfo( path, constraint, omittedHttpMethods );
-        }
-
-    }
-
-}
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/UnitOfWorkFilter.java b/libraries/http/src/main/java/org/qi4j/library/http/UnitOfWorkFilter.java
deleted file mode 100644
index dce6d80..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/UnitOfWorkFilter.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import java.io.IOException;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-
-/**
- * JAVADOC
- */
-public class UnitOfWorkFilter
-    implements Filter
-{
-    @Structure private UnitOfWorkFactory uowf;
-
-    @Override
-    public void init( FilterConfig filterConfig )
-        throws ServletException
-    {
-    }
-
-    @Override
-    public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain )
-        throws IOException, ServletException
-    {
-        UnitOfWork unitOfWork = uowf.newUnitOfWork();
-        try
-        {
-            chain.doFilter( request, response );
-
-            if( unitOfWork.isOpen() )
-            {
-                unitOfWork.complete();
-            }
-        }
-        catch( Exception e )
-        {
-            unitOfWork.discard();
-        }
-
-    }
-
-    @Override
-    public void destroy()
-    {
-    }
-}
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/UnitOfWorkFilterService.java b/libraries/http/src/main/java/org/qi4j/library/http/UnitOfWorkFilterService.java
deleted file mode 100644
index 3b891ab..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/UnitOfWorkFilterService.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import javax.servlet.Filter;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-/**
- * JAVADOC
- */
-// START SNIPPET: filterservice
-@Mixins( UnitOfWorkFilter.class )
-public interface UnitOfWorkFilterService extends Filter, ServiceComposite
-{
-}
-// END SNIPPET: filterservice
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/WelcomeServlet.java b/libraries/http/src/main/java/org/qi4j/library/http/WelcomeServlet.java
deleted file mode 100644
index 1134780..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/WelcomeServlet.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * JAVADOC
- */
-public class WelcomeServlet
-    extends HttpServlet
-{
-    private static final long serialVersionUID = 1L;
-
-    @Override public void init() throws ServletException
-    {
-        super.init();
-    }
-
-    @Override protected void doGet( HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse ) throws ServletException, IOException
-    {
-        PrintWriter writer = httpServletResponse.getWriter();
-        writer.println( "Welcome!" );
-    }
-}
\ No newline at end of file
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/WelcomeServletService.java b/libraries/http/src/main/java/org/qi4j/library/http/WelcomeServletService.java
deleted file mode 100644
index 5deac30..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/WelcomeServletService.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import javax.servlet.Servlet;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-/**
- * JAVADOC
- */
-@Mixins( WelcomeServlet.class )
-public interface WelcomeServletService extends Servlet, ServiceComposite
-{
-}
\ No newline at end of file
diff --git a/libraries/http/src/main/java/org/qi4j/library/http/package.html b/libraries/http/src/main/java/org/qi4j/library/http/package.html
deleted file mode 100644
index 1451cf5..0000000
--- a/libraries/http/src/main/java/org/qi4j/library/http/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>HTTP Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/http/src/test/java/org/apache/polygene/library/http/AbstractJettyTest.java b/libraries/http/src/test/java/org/apache/polygene/library/http/AbstractJettyTest.java
new file mode 100644
index 0000000..bfa1c53
--- /dev/null
+++ b/libraries/http/src/test/java/org/apache/polygene/library/http/AbstractJettyTest.java
@@ -0,0 +1,76 @@
+/*
+ *  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.polygene.library.http;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.Security;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.ResponseHandler;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+
+public abstract class AbstractJettyTest
+    extends AbstractPolygeneTest
+{
+    protected CloseableHttpClient defaultHttpClient;
+    protected ResponseHandler<String> stringResponseHandler = new ResponseHandler<String>()
+    {
+        @Override
+        public String handleResponse( HttpResponse hr )
+            throws IOException
+        {
+            return EntityUtils.toString( hr.getEntity(), "UTF-8" );
+        }
+
+    };
+
+    @BeforeClass
+    public static void beforeJettyTestClass()
+    {
+        // Be sure that no test trigger a DNS cache, needed by VirtualHosts test plumbing
+        Security.setProperty( "networkaddress.cache.ttl", "0" );
+    }
+
+    @Before
+    public void before()
+        throws GeneralSecurityException, IOException
+    {
+        // Default HTTP Client
+        defaultHttpClient = HttpClients.createDefault();
+    }
+
+    @After
+    public void after()
+        throws IOException
+    {
+        if( defaultHttpClient != null )
+        {
+            defaultHttpClient.close();
+        }
+    }
+}
diff --git a/libraries/http/src/test/java/org/apache/polygene/library/http/AbstractSecureJettyTest.java b/libraries/http/src/test/java/org/apache/polygene/library/http/AbstractSecureJettyTest.java
new file mode 100644
index 0000000..4c43c2a
--- /dev/null
+++ b/libraries/http/src/test/java/org/apache/polygene/library/http/AbstractSecureJettyTest.java
@@ -0,0 +1,183 @@
+/*
+ *  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.polygene.library.http;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+/**
+ * Base class for SecureJettyMixin tests.
+ *
+ * Use HttpClient in order to easily use different {@link SSLContext}s between server and client.
+ */
+public abstract class AbstractSecureJettyTest
+    extends AbstractJettyTest
+{
+    protected static final String KS_PASSWORD = "changeit";
+    protected static final String CLIENT_KEYSTORE_FILENAME = "polygene-lib-http-unittests-client-cert.jceks";
+    protected static final String SERVER_KEYSTORE_FILENAME = "polygene-lib-http-unittests-server-cert.jceks";
+    protected static final String TRUSTSTORE_FILENAME = "polygene-lib-http-unittests-ca.jceks";
+
+    // These two clients use a HostnameVerifier that don't do any check, don't do this in production code
+    protected CloseableHttpClient trustHttpClient;
+    protected CloseableHttpClient mutualHttpClient;
+
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    @Before
+    public void beforeSecure()
+        throws GeneralSecurityException, IOException
+    {
+        // Trust HTTP Client
+        trustHttpClient = HttpClients.custom()
+                                     .setSSLHostnameVerifier( NoopHostnameVerifier.INSTANCE )
+                                     .setSSLContext( buildTrustSSLContext() )
+                                     .build();
+        // Mutual HTTP Client
+        mutualHttpClient = HttpClients.custom()
+                                      .setSSLHostnameVerifier( NoopHostnameVerifier.INSTANCE )
+                                      .setSSLContext( buildMutualSSLContext() )
+                                      .build();
+    }
+
+    @After
+    public void afterSecure()
+        throws IOException
+    {
+        if( trustHttpClient != null )
+        {
+            trustHttpClient.close();
+        }
+        if( mutualHttpClient != null )
+        {
+            mutualHttpClient.close();
+        }
+    }
+
+    private static HostnameVerifier defaultHostnameVerifier;
+    private static javax.net.ssl.SSLSocketFactory defaultSSLSocketFactory;
+
+    @BeforeClass
+    public static void beforeSecureClass()
+        throws IOException, GeneralSecurityException
+    {
+        defaultHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
+        defaultSSLSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
+        HttpsURLConnection.setDefaultHostnameVerifier( ( string, ssls ) -> true );
+        HttpsURLConnection.setDefaultSSLSocketFactory( buildTrustSSLContext().getSocketFactory() );
+    }
+
+    @AfterClass
+    public static void afterSecureClass()
+    {
+        HttpsURLConnection.setDefaultHostnameVerifier( defaultHostnameVerifier );
+        HttpsURLConnection.setDefaultSSLSocketFactory( defaultSSLSocketFactory );
+    }
+
+    protected static String getX509Algorithm()
+    {
+        return System.getProperty( "java.vendor" ).contains( "IBM" ) ? "IbmX509" : "SunX509";
+    }
+
+    private static SSLContext buildTrustSSLContext()
+        throws IOException, GeneralSecurityException
+    {
+        SSLContext sslCtx = SSLContext.getInstance( "TLS" );
+        TrustManagerFactory caTrustManagerFactory = TrustManagerFactory.getInstance( getX509Algorithm() );
+        caTrustManagerFactory.init( loadTrustStore() );
+        sslCtx.init( null, caTrustManagerFactory.getTrustManagers(), null );
+        return sslCtx;
+    }
+
+    private static SSLContext buildMutualSSLContext()
+        throws IOException, GeneralSecurityException
+    {
+        SSLContext sslCtx = SSLContext.getInstance( "TLS" );
+        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance( getX509Algorithm() );
+        keyManagerFactory.init( loadKeyStore(), KS_PASSWORD.toCharArray() );
+        TrustManagerFactory caTrustManagerFactory = TrustManagerFactory.getInstance( getX509Algorithm() );
+        caTrustManagerFactory.init( loadTrustStore() );
+        sslCtx.init( keyManagerFactory.getKeyManagers(), caTrustManagerFactory.getTrustManagers(), null );
+        return sslCtx;
+    }
+
+    private static KeyStore loadTrustStore()
+        throws IOException, GeneralSecurityException
+    {
+        KeyStore truststore = KeyStore.getInstance( "JCEKS" );
+        try( InputStream stream = AbstractSecureJettyTest.class.getResourceAsStream( TRUSTSTORE_FILENAME ) )
+        {
+            truststore.load( stream, KS_PASSWORD.toCharArray() );
+        }
+        return truststore;
+    }
+
+    private static KeyStore loadKeyStore()
+        throws IOException, GeneralSecurityException
+    {
+        KeyStore keystore = KeyStore.getInstance( "JCEKS" );
+        try( InputStream stream = AbstractSecureJettyTest.class.getResourceAsStream( CLIENT_KEYSTORE_FILENAME ) )
+        {
+            keystore.load( stream, KS_PASSWORD.toCharArray() );
+        }
+        return keystore;
+    }
+
+    protected synchronized File getKeyStoreFile( String filename )
+    {
+        try
+        {
+            File file = new File( tmpDir.getRoot(), filename );
+            if( file.exists() )
+            {
+                return file;
+            }
+            try( InputStream stream = AbstractSecureJettyTest.class.getResourceAsStream( filename ) )
+            {
+                Files.copy( stream, file.toPath() );
+            }
+            return file;
+        }
+        catch( IOException ex )
+        {
+            throw new UncheckedIOException( ex );
+        }
+    }
+}
diff --git a/libraries/http/src/test/java/org/apache/polygene/library/http/FooServletContextListener.java b/libraries/http/src/test/java/org/apache/polygene/library/http/FooServletContextListener.java
new file mode 100644
index 0000000..c3c3bb1
--- /dev/null
+++ b/libraries/http/src/test/java/org/apache/polygene/library/http/FooServletContextListener.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.http;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+public class FooServletContextListener
+        implements ServletContextListener
+{
+
+    public void contextInitialized( ServletContextEvent sce )
+    {
+        // Servlet Context Initialized
+    }
+
+    public void contextDestroyed( ServletContextEvent sce )
+    {
+        // Servlet Context Destroyed
+    }
+
+}
diff --git a/libraries/http/src/test/java/org/apache/polygene/library/http/FooServletContextListenerService.java b/libraries/http/src/test/java/org/apache/polygene/library/http/FooServletContextListenerService.java
new file mode 100644
index 0000000..1ba775f
--- /dev/null
+++ b/libraries/http/src/test/java/org/apache/polygene/library/http/FooServletContextListenerService.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.http;
+
+import javax.servlet.ServletContextListener;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+
+// START SNIPPET: context-listener
+@Mixins( FooServletContextListener.class )
+public interface FooServletContextListenerService
+        extends ServletContextListener, ServiceComposite
+{
+}
+// END SNIPPET: context-listener
diff --git a/libraries/http/src/test/java/org/apache/polygene/library/http/HelloWorldServlet.java b/libraries/http/src/test/java/org/apache/polygene/library/http/HelloWorldServlet.java
new file mode 100644
index 0000000..3ddfef8
--- /dev/null
+++ b/libraries/http/src/test/java/org/apache/polygene/library/http/HelloWorldServlet.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.library.http;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.security.cert.X509Certificate;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class HelloWorldServlet
+        extends HttpServlet
+{
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    protected final void doGet( HttpServletRequest req, HttpServletResponse resp )
+            throws ServletException, IOException
+    {
+        X509Certificate[] certs = ( X509Certificate[] ) req.getAttribute( "javax.servlet.request.X509Certificate" );
+        PrintWriter writer = resp.getWriter();
+        if ( certs != null && certs.length > 0 ) {
+            writer.append( "Hello Mutual World" );
+        } else {
+            writer.append( "Hello World" );
+        }
+    }
+}
diff --git a/libraries/http/src/test/java/org/apache/polygene/library/http/HelloWorldServletService.java b/libraries/http/src/test/java/org/apache/polygene/library/http/HelloWorldServletService.java
new file mode 100644
index 0000000..79b49d5
--- /dev/null
+++ b/libraries/http/src/test/java/org/apache/polygene/library/http/HelloWorldServletService.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.http;
+
+import javax.servlet.Servlet;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+
+// START SNIPPET: servletservice
+@Mixins( HelloWorldServlet.class )
+public interface HelloWorldServletService
+        extends Servlet, ServiceComposite
+{
+}
+// END SNIPPET: servletservice
diff --git a/libraries/http/src/test/java/org/apache/polygene/library/http/JettyJMXStatisticsTest.java b/libraries/http/src/test/java/org/apache/polygene/library/http/JettyJMXStatisticsTest.java
new file mode 100644
index 0000000..c8ba055
--- /dev/null
+++ b/libraries/http/src/test/java/org/apache/polygene/library/http/JettyJMXStatisticsTest.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.library.http;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.util.FreePortFinder;
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.jmx.JMXAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.apache.polygene.library.http.Servlets.addServlets;
+import static org.apache.polygene.library.http.Servlets.serve;
+
+public class JettyJMXStatisticsTest
+    extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ModuleAssembly configModule = module;
+        new EntityTestAssembler().assemble( configModule );
+        // START SNIPPET: jmx
+        new JettyServiceAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
+        new JMXAssembler().assemble( module ); // Assemble both JettyService and JMX
+
+        JettyConfiguration config = configModule.forMixin( JettyConfiguration.class ).declareDefaults();
+        config.hostName().set( "127.0.0.1" );
+        config.port().set( FreePortFinder.findFreePortOnLoopback() );
+        config.statistics().set( Boolean.TRUE ); // Set statistics default to TRUE in configuration
+
+        // Hello world servlet related assembly
+        addServlets( serve( "/hello" ).with( HelloWorldServletService.class ) ).to( module );
+        // END SNIPPET: jmx
+    }
+
+    /**
+     * Run this test with -Djmxtest make it to not return so you can connect to the JVM using a JMX client.
+     */
+    @Test
+    public void dummy()
+        throws InterruptedException
+    {
+        if( !"false".equals( System.getProperty( "jmxtest", "false" ) ) )
+        {
+            Thread.sleep( Long.MAX_VALUE );
+        }
+    }
+}
diff --git a/libraries/http/src/test/java/org/apache/polygene/library/http/JettyServiceTest.java b/libraries/http/src/test/java/org/apache/polygene/library/http/JettyServiceTest.java
new file mode 100644
index 0000000..6a258fb
--- /dev/null
+++ b/libraries/http/src/test/java/org/apache/polygene/library/http/JettyServiceTest.java
@@ -0,0 +1,92 @@
+/*
+ *  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.polygene.library.http;
+
+import java.util.Iterator;
+import java.util.stream.Collectors;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.polygene.test.util.FreePortFinder;
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static javax.servlet.DispatcherType.REQUEST;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.apache.polygene.library.http.Servlets.addFilters;
+import static org.apache.polygene.library.http.Servlets.addServlets;
+import static org.apache.polygene.library.http.Servlets.filter;
+import static org.apache.polygene.library.http.Servlets.serve;
+
+public final class JettyServiceTest
+    extends AbstractJettyTest
+{
+    private final int httpPort = FreePortFinder.findFreePortOnLoopback();
+
+    @Override
+    public final void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ModuleAssembly configModule = module;
+        new EntityTestAssembler().assemble( configModule );
+
+        // START SNIPPET: assembly
+        // Assemble the JettyService
+        new JettyServiceAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
+
+        // Set HTTP port as JettyConfiguration default
+        JettyConfiguration config = configModule.forMixin( JettyConfiguration.class ).declareDefaults();
+        config.hostName().set( "127.0.0.1" );
+        config.port().set( httpPort );
+
+        // Serve /helloWorld with HelloWorldServletService
+        addServlets( serve( "/helloWorld" ).with( HelloWorldServletService.class ) ).to( module );
+
+        // Filter requests on /* through provided UnitOfWorkFilterService
+        addFilters( filter( "/*" ).through( UnitOfWorkFilterService.class ).on( REQUEST ) ).to( module );
+        // END SNIPPET: assembly
+    }
+
+    @Test
+    public final void testInstantiation()
+        throws Throwable
+    {
+        Iterable<ServiceReference<JettyService>> services = serviceFinder.findServices( JettyService.class )
+                                                                         .collect( Collectors.toList() );
+        assertNotNull( services );
+
+        Iterator<ServiceReference<JettyService>> iterator = services.iterator();
+        assertTrue( iterator.hasNext() );
+
+        ServiceReference<JettyService> serviceRef = iterator.next();
+        assertNotNull( serviceRef );
+
+        JettyService jettyService = serviceRef.get();
+        assertNotNull( jettyService );
+
+        String output = defaultHttpClient.execute( new HttpGet( "http://127.0.0.1:" + httpPort + "/helloWorld" ),
+                                                   stringResponseHandler );
+        assertEquals( "Hello World", output );
+    }
+}
diff --git a/libraries/http/src/test/java/org/apache/polygene/library/http/JettyTestSuite.java b/libraries/http/src/test/java/org/apache/polygene/library/http/JettyTestSuite.java
new file mode 100644
index 0000000..c368750
--- /dev/null
+++ b/libraries/http/src/test/java/org/apache/polygene/library/http/JettyTestSuite.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.library.http;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith( Suite.class )
+@Suite.SuiteClasses( {
+    JettyServiceTest.class,
+    JettyJMXStatisticsTest.class,
+    SecureJettyServiceTest.class,
+    MutualSecureJettyServiceTest.class
+} )
+public class JettyTestSuite
+{
+}
diff --git a/libraries/http/src/test/java/org/apache/polygene/library/http/MutualSecureJettyServiceTest.java b/libraries/http/src/test/java/org/apache/polygene/library/http/MutualSecureJettyServiceTest.java
new file mode 100644
index 0000000..59dc186
--- /dev/null
+++ b/libraries/http/src/test/java/org/apache/polygene/library/http/MutualSecureJettyServiceTest.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.library.http;
+
+import java.io.IOException;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.polygene.test.util.FreePortFinder;
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.assertEquals;
+import static org.apache.polygene.library.http.Servlets.addServlets;
+import static org.apache.polygene.library.http.Servlets.serve;
+
+public class MutualSecureJettyServiceTest
+    extends AbstractSecureJettyTest
+{
+    private final int httpsPort = FreePortFinder.findFreePortOnLoopback();
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ModuleAssembly configModule = module;
+        new EntityTestAssembler().assemble( configModule );
+        new SecureJettyServiceAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
+        // START SNIPPET: config
+        SecureJettyConfiguration config = configModule.forMixin( SecureJettyConfiguration.class ).declareDefaults();
+        config.hostName().set( "127.0.0.1" );
+        config.port().set( httpsPort );
+
+        config.keystorePath().set( getKeyStoreFile( SERVER_KEYSTORE_FILENAME ).getAbsolutePath() );
+        config.keystoreType().set( "JCEKS" );
+        config.keystorePassword().set( KS_PASSWORD );
+
+        config.truststorePath().set( getKeyStoreFile( TRUSTSTORE_FILENAME ).getAbsolutePath() );
+        config.truststoreType().set( "JCEKS" );
+        config.truststorePassword().set( KS_PASSWORD );
+
+        config.wantClientAuth().set( Boolean.TRUE );
+        // END SNIPPET: config
+
+        addServlets( serve( "/hello" ).with( HelloWorldServletService.class ) ).to( module );
+    }
+
+    @Test
+    public void testWithoutClientCertificate()
+        throws IOException
+    {
+        // As we set wantClientAuth we can request without a client certificate ...
+        String output = trustHttpClient.execute( new HttpGet( "https://127.0.0.1:" + httpsPort + "/hello" ),
+                                                 stringResponseHandler );
+        assertEquals( "Hello World", output );
+    }
+
+    @Test
+    public void testWithClientCertificate()
+        throws IOException
+    {
+        // ... and with one
+        String output = mutualHttpClient.execute( new HttpGet( "https://127.0.0.1:" + httpsPort + "/hello" ),
+                                                  stringResponseHandler );
+        assertEquals( "Hello Mutual World", output );
+    }
+}
diff --git a/libraries/http/src/test/java/org/apache/polygene/library/http/SecureJettyServiceTest.java b/libraries/http/src/test/java/org/apache/polygene/library/http/SecureJettyServiceTest.java
new file mode 100644
index 0000000..20a567b
--- /dev/null
+++ b/libraries/http/src/test/java/org/apache/polygene/library/http/SecureJettyServiceTest.java
@@ -0,0 +1,98 @@
+/*
+ *  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.polygene.library.http;
+
+import java.io.IOException;
+import javax.net.ssl.SSLHandshakeException;
+import org.apache.http.NoHttpResponseException;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.polygene.test.util.FreePortFinder;
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static javax.servlet.DispatcherType.REQUEST;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.apache.polygene.library.http.Servlets.addFilters;
+import static org.apache.polygene.library.http.Servlets.addServlets;
+import static org.apache.polygene.library.http.Servlets.filter;
+import static org.apache.polygene.library.http.Servlets.serve;
+
+public class SecureJettyServiceTest
+    extends AbstractSecureJettyTest
+{
+    private final int httpsPort = FreePortFinder.findFreePortOnLoopback();
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ModuleAssembly configModule = module;
+        new EntityTestAssembler().assemble( configModule );
+        // START SNIPPET: assemblyssl
+        new SecureJettyServiceAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
+        // END SNIPPET: assemblyssl
+
+        // START SNIPPET: configssl
+        SecureJettyConfiguration config = configModule.forMixin( SecureJettyConfiguration.class ).declareDefaults();
+        config.hostName().set( "127.0.0.1" );
+        config.port().set( httpsPort );
+        config.keystorePath().set( getKeyStoreFile( SERVER_KEYSTORE_FILENAME ).getAbsolutePath() );
+        config.keystoreType().set( "JCEKS" );
+        config.keystorePassword().set( KS_PASSWORD );
+        // END SNIPPET: configssl
+
+        // START SNIPPET: assemblyssl
+        addServlets( serve( "/hello" ).with( HelloWorldServletService.class ) ).to( module );
+        addFilters( filter( "/*" ).through( UnitOfWorkFilterService.class ).on( REQUEST ) ).to( module );
+        // END SNIPPET: assemblyssl
+    }
+
+    @Test( expected = NoHttpResponseException.class )
+    // This test exists for demonstration purpose only, it do not test usefull things but it's on purpose
+    public void testNoSSL()
+        throws IOException
+    {
+        HttpGet get = new HttpGet( "http://127.0.0.1:" + httpsPort + "/hello" );
+        defaultHttpClient.execute( get );
+        fail( "We could reach the HTTPS connector using a HTTP url, that's no good" );
+    }
+
+    @Test( expected = SSLHandshakeException.class )
+    // This test exists for demonstration purpose only, it do not test useful things but it's on purpose
+    public void testNoTruststore()
+        throws IOException
+    {
+        defaultHttpClient.execute( new HttpGet( "https://127.0.0.1:" + httpsPort + "/hello" ) );
+        fail( "We could reach the HTTPS connector without proper truststore, this should not happen" );
+    }
+
+    @Test
+    public void testTrust()
+        throws IOException, InterruptedException
+    {
+        String output = trustHttpClient.execute( new HttpGet( "https://127.0.0.1:" + httpsPort + "/hello" ),
+                                                 stringResponseHandler );
+        assertEquals( "Hello World", output );
+    }
+}
diff --git a/libraries/http/src/test/java/org/qi4j/library/http/AbstractJettyTest.java b/libraries/http/src/test/java/org/qi4j/library/http/AbstractJettyTest.java
deleted file mode 100644
index caf64c5..0000000
--- a/libraries/http/src/test/java/org/qi4j/library/http/AbstractJettyTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import java.io.IOException;
-import java.security.GeneralSecurityException;
-import java.security.Security;
-
-import org.apache.http.HttpResponse;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.ResponseHandler;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.util.EntityUtils;
-
-import org.junit.Before;
-import org.junit.BeforeClass;
-
-import org.qi4j.test.AbstractQi4jTest;
-
-public abstract class AbstractJettyTest
-        extends AbstractQi4jTest
-{
-
-    protected static final int HTTP_PORT = 8041;
-    protected HttpClient defaultHttpClient;
-    protected ResponseHandler<String> stringResponseHandler = new ResponseHandler<String>()
-    {
-
-        public String handleResponse( HttpResponse hr )
-                throws ClientProtocolException, IOException
-        {
-            return EntityUtils.toString( hr.getEntity(), "UTF-8" );
-        }
-
-    };
-
-    @BeforeClass
-    public static void beforeJettyTestClass()
-    {
-        // Be sure that no test trigger a DNS cache, needed by VirtualHosts test plumbing
-        Security.setProperty( "networkaddress.cache.ttl", "0" );
-    }
-
-    @Before
-    public void before()
-            throws GeneralSecurityException, IOException
-    {
-        // Default HTTP Client
-        defaultHttpClient = new DefaultHttpClient();
-    }
-
-}
diff --git a/libraries/http/src/test/java/org/qi4j/library/http/AbstractSecureJettyTest.java b/libraries/http/src/test/java/org/qi4j/library/http/AbstractSecureJettyTest.java
deleted file mode 100644
index d2ef207..0000000
--- a/libraries/http/src/test/java/org/qi4j/library/http/AbstractSecureJettyTest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.TrustManagerFactory;
-import org.apache.http.client.HttpClient;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
-import org.apache.http.conn.ssl.SSLSocketFactory;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-
-/**
- * Base class for SecureJettyMixin tests.
- *
- * Use HttpClient in order to easily use different {@link SSLContext}s between server and client.
- */
-public abstract class AbstractSecureJettyTest
-        extends AbstractJettyTest
-{
-
-    private static final String HTTPS = "https";
-    protected static final int HTTPS_PORT = 8441;
-    protected static final String KS_PASSWORD = "changeit";
-    protected static final String CLIENT_KEYSTORE_PATH = "src/test/resources/org/qi4j/library/http/qi4j-lib-http-unittests-client-cert.jceks";
-    protected static final File CLIENT_KEYSTORE_FILE = new File( CLIENT_KEYSTORE_PATH );
-    protected static final String SERVER_KEYSTORE_PATH = "src/test/resources/org/qi4j/library/http/qi4j-lib-http-unittests-server-cert.jceks";
-    protected static final File SERVER_KEYSTORE_FILE = new File( SERVER_KEYSTORE_PATH );
-    protected static final String TRUSTSTORE_PATH = "src/test/resources/org/qi4j/library/http/qi4j-lib-http-unittests-ca.jceks";
-    protected static final File TRUSTSTORE_FILE = new File( TRUSTSTORE_PATH );
-    // These two clients use a HostnameVerifier that don't do any check, don't do this in production code
-    protected HttpClient trustHttpClient;
-    protected HttpClient mutualHttpClient;
-
-    @Before
-    public void beforeSecure()
-            throws GeneralSecurityException, IOException
-    {
-        // Trust HTTP Client
-        KeyStore truststore = KeyStore.getInstance( "JCEKS" );
-        truststore.load( new FileInputStream( TRUSTSTORE_FILE ), KS_PASSWORD.toCharArray() );
-
-        AllowAllHostnameVerifier verifier = new AllowAllHostnameVerifier();
-
-        DefaultHttpClient trustClient = new DefaultHttpClient();
-        SSLSocketFactory trustSslFactory = new SSLSocketFactory( truststore );
-        trustSslFactory.setHostnameVerifier( verifier );
-        SchemeRegistry trustSchemeRegistry = trustClient.getConnectionManager().getSchemeRegistry();
-        trustSchemeRegistry.unregister( HTTPS );
-        trustSchemeRegistry.register( new Scheme( HTTPS, HTTPS_PORT, trustSslFactory ) );
-        trustHttpClient = trustClient;
-
-        // Mutual HTTP Client
-        KeyStore keystore = KeyStore.getInstance( "JCEKS" );
-        keystore.load( new FileInputStream( CLIENT_KEYSTORE_FILE ), KS_PASSWORD.toCharArray() );
-
-        DefaultHttpClient mutualClient = new DefaultHttpClient();
-        SSLSocketFactory mutualSslFactory = new SSLSocketFactory( keystore, KS_PASSWORD, truststore );
-        mutualSslFactory.setHostnameVerifier( verifier );
-        SchemeRegistry mutualSchemeRegistry = mutualClient.getConnectionManager().getSchemeRegistry();
-        mutualSchemeRegistry.unregister( HTTPS );
-        mutualSchemeRegistry.register( new Scheme( HTTPS, HTTPS_PORT, mutualSslFactory ) );
-        mutualHttpClient = mutualClient;
-    }
-
-    private static HostnameVerifier defaultHostnameVerifier;
-    private static javax.net.ssl.SSLSocketFactory defaultSSLSocketFactory;
-
-    @BeforeClass
-    public static void beforeSecureClass()
-            throws IOException, GeneralSecurityException
-    {
-        defaultHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
-        defaultSSLSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
-        HttpsURLConnection.setDefaultHostnameVerifier( new HostnameVerifier()
-        {
-
-            public boolean verify( String string, SSLSession ssls )
-            {
-                return true;
-            }
-
-        } );
-        KeyStore truststore = KeyStore.getInstance( "JCEKS" );
-        truststore.load( new FileInputStream( TRUSTSTORE_FILE ), KS_PASSWORD.toCharArray() );
-        SSLContext sslCtx = SSLContext.getInstance( "TLS" );
-        TrustManagerFactory caTrustManagerFactory = TrustManagerFactory.getInstance( getX509Algorithm() );
-        caTrustManagerFactory.init( truststore );
-        sslCtx.init( null, caTrustManagerFactory.getTrustManagers(), null );
-        HttpsURLConnection.setDefaultSSLSocketFactory( sslCtx.getSocketFactory() );
-    }
-
-    @AfterClass
-    public static void afterSecureClass()
-    {
-        HttpsURLConnection.setDefaultHostnameVerifier( defaultHostnameVerifier );
-        HttpsURLConnection.setDefaultSSLSocketFactory( defaultSSLSocketFactory );
-    }
-
-    protected static String getX509Algorithm()
-    {
-        return System.getProperty( "java.vendor" ).contains( "IBM" ) ? "IbmX509" : "SunX509";
-    }
-
-}
diff --git a/libraries/http/src/test/java/org/qi4j/library/http/FooServletContextListener.java b/libraries/http/src/test/java/org/qi4j/library/http/FooServletContextListener.java
deleted file mode 100644
index 8ef80c8..0000000
--- a/libraries/http/src/test/java/org/qi4j/library/http/FooServletContextListener.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed 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.qi4j.library.http;
-
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-
-public class FooServletContextListener
-        implements ServletContextListener
-{
-
-    public void contextInitialized( ServletContextEvent sce )
-    {
-        // Servlet Context Initialized
-    }
-
-    public void contextDestroyed( ServletContextEvent sce )
-    {
-        // Servlet Context Destroyed
-    }
-
-}
diff --git a/libraries/http/src/test/java/org/qi4j/library/http/FooServletContextListenerService.java b/libraries/http/src/test/java/org/qi4j/library/http/FooServletContextListenerService.java
deleted file mode 100644
index 47c26a9..0000000
--- a/libraries/http/src/test/java/org/qi4j/library/http/FooServletContextListenerService.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed 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.qi4j.library.http;
-
-import javax.servlet.ServletContextListener;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-// START SNIPPET: context-listener
-@Mixins( FooServletContextListener.class )
-public interface FooServletContextListenerService
-        extends ServletContextListener, ServiceComposite
-{
-}
-// END SNIPPET: context-listener
diff --git a/libraries/http/src/test/java/org/qi4j/library/http/HelloWorldServlet.java b/libraries/http/src/test/java/org/qi4j/library/http/HelloWorldServlet.java
deleted file mode 100644
index 4bf3afb..0000000
--- a/libraries/http/src/test/java/org/qi4j/library/http/HelloWorldServlet.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/* 
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.security.cert.X509Certificate;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-public class HelloWorldServlet
-        extends HttpServlet
-{
-
-    private static final long serialVersionUID = 1L;
-
-    @Override
-    protected final void doGet( HttpServletRequest req, HttpServletResponse resp )
-            throws ServletException, IOException
-    {
-        X509Certificate[] certs = ( X509Certificate[] ) req.getAttribute( "javax.servlet.request.X509Certificate" );
-        PrintWriter writer = resp.getWriter();
-        if ( certs != null && certs.length > 0 ) {
-            writer.append( "Hello Mutual World" );
-        } else {
-            writer.append( "Hello World" );
-        }
-    }
-
-}
diff --git a/libraries/http/src/test/java/org/qi4j/library/http/HelloWorldServletService.java b/libraries/http/src/test/java/org/qi4j/library/http/HelloWorldServletService.java
deleted file mode 100644
index 2f0aacd..0000000
--- a/libraries/http/src/test/java/org/qi4j/library/http/HelloWorldServletService.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.library.http;
-
-import javax.servlet.Servlet;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-// START SNIPPET: servletservice
-@Mixins( HelloWorldServlet.class )
-public interface HelloWorldServletService
-        extends Servlet, ServiceComposite
-{
-}
-// END SNIPPET: servletservice
diff --git a/libraries/http/src/test/java/org/qi4j/library/http/JettyJMXStatisticsTest.java b/libraries/http/src/test/java/org/qi4j/library/http/JettyJMXStatisticsTest.java
deleted file mode 100644
index f9d89e9..0000000
--- a/libraries/http/src/test/java/org/qi4j/library/http/JettyJMXStatisticsTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.jmx.JMXAssembler;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.qi4j.library.http.Servlets.addServlets;
-import static org.qi4j.library.http.Servlets.serve;
-
-public class JettyJMXStatisticsTest
-    extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ModuleAssembly configModule = module;
-        new EntityTestAssembler().assemble( configModule );
-        // START SNIPPET: jmx
-        new JettyServiceAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
-        new JMXAssembler().assemble( module ); // Assemble both JettyService and JMX
-
-        JettyConfiguration config = configModule.forMixin( JettyConfiguration.class ).declareDefaults();
-        config.hostName().set( "127.0.0.1" );
-        config.port().set( 8441 );
-        config.statistics().set( Boolean.TRUE ); // Set statistics default to TRUE in configuration
-
-        // Hello world servlet related assembly
-        addServlets( serve( "/hello" ).with( HelloWorldServletService.class ) ).to( module );
-        // END SNIPPET: jmx
-    }
-
-    /**
-     * Run this test with -Djmxtest make it to not return so you can connect to the JVM using a JMX client.
-     */
-    @Test
-    public void dummy()
-        throws InterruptedException
-    {
-        if( !"false".equals( System.getProperty( "jmxtest", "false" ) ) )
-        {
-            Thread.sleep( Long.MAX_VALUE );
-        }
-    }
-}
diff --git a/libraries/http/src/test/java/org/qi4j/library/http/JettyServiceTest.java b/libraries/http/src/test/java/org/qi4j/library/http/JettyServiceTest.java
deleted file mode 100644
index 3c77166..0000000
--- a/libraries/http/src/test/java/org/qi4j/library/http/JettyServiceTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import java.util.Iterator;
-import org.apache.http.client.methods.HttpGet;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-
-import static javax.servlet.DispatcherType.REQUEST;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.qi4j.library.http.Servlets.addFilters;
-import static org.qi4j.library.http.Servlets.addServlets;
-import static org.qi4j.library.http.Servlets.filter;
-import static org.qi4j.library.http.Servlets.serve;
-
-public final class JettyServiceTest
-    extends AbstractJettyTest
-{
-
-    @Override
-    public final void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ModuleAssembly configModule = module;
-        new EntityTestAssembler().assemble( configModule );
-
-        // START SNIPPET: assembly
-        // Assemble the JettyService
-        new JettyServiceAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
-
-        // Set HTTP port as JettyConfiguration default
-        JettyConfiguration config = configModule.forMixin( JettyConfiguration.class ).declareDefaults();
-        config.hostName().set( "127.0.0.1" );
-        config.port().set( HTTP_PORT );
-
-        // Serve /helloWorld with HelloWorldServletService
-        addServlets( serve( "/helloWorld" ).with( HelloWorldServletService.class ) ).to( module );
-
-        // Filter requests on /* through provided UnitOfWorkFilterService
-        addFilters( filter( "/*" ).through( UnitOfWorkFilterService.class ).on( REQUEST ) ).to( module );
-        // END SNIPPET: assembly
-    }
-
-    @Test
-    public final void testInstantiation()
-        throws Throwable
-    {
-        Iterable<ServiceReference<JettyService>> services = module.findServices( JettyService.class );
-        assertNotNull( services );
-
-        Iterator<ServiceReference<JettyService>> iterator = services.iterator();
-        assertTrue( iterator.hasNext() );
-
-        ServiceReference<JettyService> serviceRef = iterator.next();
-        assertNotNull( serviceRef );
-
-        JettyService jettyService = serviceRef.get();
-        assertNotNull( jettyService );
-
-        String output = defaultHttpClient.execute( new HttpGet( "http://127.0.0.1:8041/helloWorld" ), stringResponseHandler );
-        assertEquals( "Hello World", output );
-    }
-}
diff --git a/libraries/http/src/test/java/org/qi4j/library/http/JettyTestSuite.java b/libraries/http/src/test/java/org/qi4j/library/http/JettyTestSuite.java
deleted file mode 100644
index 950ef03..0000000
--- a/libraries/http/src/test/java/org/qi4j/library/http/JettyTestSuite.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
-
-@RunWith( Suite.class )
-@Suite.SuiteClasses( {
-    VirtualHostJettyServiceTest.class,
-    JettyServiceTest.class,
-    JettyJMXStatisticsTest.class,
-    SecureJettyServiceTest.class,
-    MutualSecureJettyServiceTest.class
-} )
-public class JettyTestSuite
-{
-}
diff --git a/libraries/http/src/test/java/org/qi4j/library/http/MutualSecureJettyServiceTest.java b/libraries/http/src/test/java/org/qi4j/library/http/MutualSecureJettyServiceTest.java
deleted file mode 100644
index 44ef297..0000000
--- a/libraries/http/src/test/java/org/qi4j/library/http/MutualSecureJettyServiceTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import java.io.IOException;
-import org.apache.http.client.methods.HttpGet;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.assertEquals;
-import static org.qi4j.library.http.Servlets.addServlets;
-import static org.qi4j.library.http.Servlets.serve;
-
-public class MutualSecureJettyServiceTest
-    extends AbstractSecureJettyTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ModuleAssembly configModule = module;
-        new EntityTestAssembler().assemble( configModule );
-        new SecureJettyServiceAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
-        // START SNIPPET: config
-        SecureJettyConfiguration config = configModule.forMixin( SecureJettyConfiguration.class ).declareDefaults();
-        config.hostName().set( "127.0.0.1" );
-        config.port().set( HTTPS_PORT );
-
-        config.keystorePath().set( SERVER_KEYSTORE_PATH );
-        config.keystoreType().set( "JCEKS" );
-        config.keystorePassword().set( KS_PASSWORD );
-
-        config.truststorePath().set( TRUSTSTORE_PATH );
-        config.truststoreType().set( "JCEKS" );
-        config.truststorePassword().set( KS_PASSWORD );
-
-        config.wantClientAuth().set( Boolean.TRUE );
-        // END SNIPPET: config
-
-        addServlets( serve( "/hello" ).with( HelloWorldServletService.class ) ).to( module );
-    }
-
-    @Test
-    public void testWithoutClientCertificate()
-        throws IOException
-    {
-        // As we set wantClientAuth we can request without a client certificate ...
-        String output = trustHttpClient.execute( new HttpGet( "https://127.0.0.1:8441/hello" ), stringResponseHandler );
-        assertEquals( "Hello World", output );
-    }
-
-    @Test
-    public void testWithClientCertificate()
-        throws IOException
-    {
-        // ... and with one
-        String output = mutualHttpClient.execute( new HttpGet( "https://127.0.0.1:8441/hello" ), stringResponseHandler );
-        assertEquals( "Hello Mutual World", output );
-    }
-}
diff --git a/libraries/http/src/test/java/org/qi4j/library/http/SecureJettyServiceTest.java b/libraries/http/src/test/java/org/qi4j/library/http/SecureJettyServiceTest.java
deleted file mode 100644
index a15a60a..0000000
--- a/libraries/http/src/test/java/org/qi4j/library/http/SecureJettyServiceTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import java.io.IOException;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import org.apache.http.NoHttpResponseException;
-import org.apache.http.client.methods.HttpGet;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.EntityTestAssembler;
-
-import static javax.servlet.DispatcherType.REQUEST;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-import static org.qi4j.library.http.Servlets.addFilters;
-import static org.qi4j.library.http.Servlets.addServlets;
-import static org.qi4j.library.http.Servlets.filter;
-import static org.qi4j.library.http.Servlets.serve;
-
-public class SecureJettyServiceTest
-    extends AbstractSecureJettyTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ModuleAssembly configModule = module;
-        new EntityTestAssembler().assemble( configModule );
-        // START SNIPPET: assemblyssl
-        new SecureJettyServiceAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
-        // END SNIPPET: assemblyssl
-
-        // START SNIPPET: configssl
-        SecureJettyConfiguration config = configModule.forMixin( SecureJettyConfiguration.class ).declareDefaults();
-        config.hostName().set( "127.0.0.1" );
-        config.port().set( HTTPS_PORT );
-        config.keystorePath().set( SERVER_KEYSTORE_PATH );
-        config.keystoreType().set( "JCEKS" );
-        config.keystorePassword().set( KS_PASSWORD );
-        // END SNIPPET: configssl
-
-        // START SNIPPET: assemblyssl
-        addServlets( serve( "/hello" ).with( HelloWorldServletService.class ) ).to( module );
-        addFilters( filter( "/*" ).through( UnitOfWorkFilterService.class ).on( REQUEST ) ).to( module );
-        // END SNIPPET: assemblyssl
-    }
-
-    @Test
-    // This test exists for demonstration purpose only, it do not test usefull things but it's on purpose
-    public void testNoSSL()
-        throws IOException
-    {
-        try
-        {
-            HttpGet get = new HttpGet( "http://127.0.0.1:8441/hello" );
-            defaultHttpClient.execute( get );
-            fail( "We could reach the HTTPS connector using a HTTP url, that's no good" );
-        }
-        catch( NoHttpResponseException ex )
-        {
-            // Expected
-        }
-    }
-
-    @Test
-    // This test exists for demonstration purpose only, it do not test usefull things but it's on purpose
-    public void testNoTruststore()
-        throws IOException
-    {
-        try
-        {
-            defaultHttpClient.execute( new HttpGet( "https://127.0.0.1:8441/hello" ) );
-            fail( "We could reach the HTTPS connector without proper truststore, this should not happen" );
-        }
-        catch( SSLPeerUnverifiedException ex )
-        {
-            // Expected
-        }
-    }
-
-    @Test
-    public void testTrust()
-        throws IOException, InterruptedException
-    {
-        String output = trustHttpClient.execute( new HttpGet( "https://127.0.0.1:8441/hello" ), stringResponseHandler );
-        assertEquals( "Hello World", output );
-    }
-}
diff --git a/libraries/http/src/test/java/org/qi4j/library/http/VirtualHostJettyServiceTest.java b/libraries/http/src/test/java/org/qi4j/library/http/VirtualHostJettyServiceTest.java
deleted file mode 100644
index 149b41c..0000000
--- a/libraries/http/src/test/java/org/qi4j/library/http/VirtualHostJettyServiceTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http;
-
-import java.io.IOException;
-import org.apache.http.client.methods.HttpGet;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.http.dns.LocalManagedDns;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.assertEquals;
-import static org.qi4j.library.http.Servlets.addServlets;
-import static org.qi4j.library.http.Servlets.serve;
-import static org.qi4j.test.util.Assume.assumeNoIbmJdk;
-
-public class VirtualHostJettyServiceTest
-    extends AbstractJettyTest
-{
-    private static final String HOST1 = "host1.http.library.qi4j";
-    private static final String HOST2 = "host2.http.library.qi4j";
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ModuleAssembly configModule = module;
-        new EntityTestAssembler().assemble( configModule );
-        new JettyServiceAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
-
-        SecureJettyConfiguration config = configModule.forMixin( SecureJettyConfiguration.class ).declareDefaults();
-        config.hostName().set( "127.0.0.1" );
-        config.port().set( HTTP_PORT );
-        config.virtualHosts().set( HOST1 + "," + HOST2 );
-
-        addServlets( serve( "/hello" ).with( HelloWorldServletService.class ) ).to( module );
-    }
-
-    @BeforeClass
-    public static void beforeVirtualHostsClass()
-    {
-        assumeNoIbmJdk();
-        LocalManagedDns.putName( HOST1, "127.0.0.1" );
-        LocalManagedDns.putName( HOST2, "127.0.0.1" );
-    }
-
-    @AfterClass
-    public static void afterVirtualHostsClass()
-    {
-        LocalManagedDns.removeName( HOST1 );
-        LocalManagedDns.removeName( HOST2 );
-    }
-
-    @Test
-    public void test()
-        throws IOException
-    {
-        // Available on HOST1 and HOST2
-        String output = defaultHttpClient.execute( new HttpGet( "http://" + HOST1 + ":8041/hello" ),
-                                                   stringResponseHandler );
-        assertEquals( "Hello World", output );
-
-        output = defaultHttpClient.execute( new HttpGet( "http://" + HOST2 + ":8041/hello" ),
-                                            stringResponseHandler );
-        assertEquals( "Hello World", output );
-    }
-}
diff --git a/libraries/http/src/test/java/org/qi4j/library/http/dns/LocalManagedDns.java b/libraries/http/src/test/java/org/qi4j/library/http/dns/LocalManagedDns.java
deleted file mode 100644
index 0fd6dc8..0000000
--- a/libraries/http/src/test/java/org/qi4j/library/http/dns/LocalManagedDns.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http.dns;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import org.xbill.DNS.spi.DNSJavaNameServiceDescriptor;
-import sun.net.spi.nameservice.NameService;
-
-public class LocalManagedDns
-        implements NameService
-{
-
-    private static final NameService DEFAULT_DNS = new DNSJavaNameServiceDescriptor().createNameService();
-    private static final Map<String, String> NAMES = new ConcurrentHashMap<String, String>();
-
-    public static void clearNames()
-    {
-        NAMES.clear();
-    }
-
-    public static String putName( String name, String ip )
-    {
-        return NAMES.put( name, ip );
-    }
-
-    public static String removeName( String name )
-    {
-        return NAMES.remove( name );
-    }
-
-    public String getHostByAddr( byte[] bytes )
-            throws UnknownHostException
-    {
-        return DEFAULT_DNS.getHostByAddr( bytes );
-    }
-
-    public InetAddress[] lookupAllHostAddr( String name )
-            throws UnknownHostException
-    {
-        String log = "[CDNS] Lookup request";
-        String ip = NAMES.get( name );
-        InetAddress[] result = new InetAddress[ 0 ];
-        if ( ip != null && ip.length() > 0 ) {
-            log += " on managed name (" + name + ")";
-            byte[] ipBytes = ipStringToBytes( ip );
-            result = new InetAddress[]{ Inet4Address.getByAddress( ipBytes ) };
-        } else {
-            log += " on non-managed name (" + name + ")";
-            result = DEFAULT_DNS.lookupAllHostAddr( name );
-        }
-        return result;
-    }
-
-    private static byte[] ipStringToBytes( String ipString )
-    {
-        if ( ipString == null || ipString.length() == 0 ) {
-            return null;
-        }
-
-        int inetAddrSize = 4;
-        int octets;
-        char ch;
-        byte[] dst = new byte[ inetAddrSize ];
-        char[] srcb = ipString.toCharArray();
-        boolean saw_digit = false;
-
-        octets = 0;
-        int i = 0;
-        int cur = 0;
-        while ( i < srcb.length ) {
-            ch = srcb[i++];
-            if ( Character.isDigit( ch ) ) {
-                int sum = dst[cur] * 10 + ( Character.digit( ch, 10 ) & 0xff );
-
-                if ( sum > 255 ) {
-                    return null;
-                }
-
-                dst[cur] = ( byte ) ( sum & 0xff );
-                if ( !saw_digit ) {
-                    if ( ++octets > inetAddrSize ) {
-                        return null;
-                    }
-                    saw_digit = true;
-                }
-            } else if ( ch == '.' && saw_digit ) {
-                if ( octets == inetAddrSize ) {
-                    return null;
-                }
-                cur++;
-                dst[cur] = 0;
-                saw_digit = false;
-            } else {
-                return null;
-            }
-        }
-
-        if ( octets < inetAddrSize ) {
-            return null;
-        }
-        return dst;
-    }
-
-}
diff --git a/libraries/http/src/test/java/org/qi4j/library/http/dns/LocalManagedDnsDescriptor.java b/libraries/http/src/test/java/org/qi4j/library/http/dns/LocalManagedDnsDescriptor.java
deleted file mode 100644
index 3c0de74..0000000
--- a/libraries/http/src/test/java/org/qi4j/library/http/dns/LocalManagedDnsDescriptor.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.http.dns;
-
-import sun.net.spi.nameservice.NameService;
-import sun.net.spi.nameservice.NameServiceDescriptor;
-
-public class LocalManagedDnsDescriptor
-        implements NameServiceDescriptor
-{
-
-    public static final String PROVIDER_NAME = "LocalManagedDns";
-    private static final NameService nameService = new LocalManagedDns();
-
-    public NameService createNameService()
-            throws Exception
-    {
-        return nameService;
-    }
-
-    public String getProviderName()
-    {
-        return PROVIDER_NAME;
-    }
-
-    public String getType()
-    {
-        return "dns";
-    }
-
-}
diff --git a/libraries/http/src/test/resources/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor b/libraries/http/src/test/resources/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
deleted file mode 100644
index ab17218..0000000
--- a/libraries/http/src/test/resources/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
+++ /dev/null
@@ -1,16 +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.
-
-org.qi4j.library.http.dns.LocalManagedDnsDescriptor
\ No newline at end of file
diff --git a/libraries/http/src/test/resources/logback.xml b/libraries/http/src/test/resources/logback.xml
index dcbdae2..cacadbd 100644
--- a/libraries/http/src/test/resources/logback.xml
+++ b/libraries/http/src/test/resources/logback.xml
@@ -1,25 +1,28 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <configuration>
 
     <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
         <encoder>
-            <pattern>[QI4J] @%-20thread %-5level %logger{36} - %msg%n</pattern>
+            <pattern>[POLYGENE] @%-20thread %-5level %logger{36} - %msg%n</pattern>
         </encoder>
     </appender>
 
@@ -27,7 +30,7 @@
         <appender-ref ref="stdout" />
     </root>
 
-    <logger name="org.qi4j.library.http" level="trace"/>
+    <logger name="org.apache.polygene.library.http" level="trace"/>
     <logger name="org.eclipse.jetty" level="info"/>
     <logger name="org.jetty" level="info"/>
     
diff --git a/libraries/http/src/test/resources/org/qi4j/library/http/qi4j-lib-http-unittests-ca.jceks b/libraries/http/src/test/resources/org/apache/polygene/library/http/polygene-lib-http-unittests-ca.jceks
similarity index 100%
rename from libraries/http/src/test/resources/org/qi4j/library/http/qi4j-lib-http-unittests-ca.jceks
rename to libraries/http/src/test/resources/org/apache/polygene/library/http/polygene-lib-http-unittests-ca.jceks
Binary files differ
diff --git a/libraries/http/src/test/resources/org/qi4j/library/http/qi4j-lib-http-unittests-client-cert.jceks b/libraries/http/src/test/resources/org/apache/polygene/library/http/polygene-lib-http-unittests-client-cert.jceks
similarity index 100%
rename from libraries/http/src/test/resources/org/qi4j/library/http/qi4j-lib-http-unittests-client-cert.jceks
rename to libraries/http/src/test/resources/org/apache/polygene/library/http/polygene-lib-http-unittests-client-cert.jceks
Binary files differ
diff --git a/libraries/http/src/test/resources/org/qi4j/library/http/qi4j-lib-http-unittests-server-cert.jceks b/libraries/http/src/test/resources/org/apache/polygene/library/http/polygene-lib-http-unittests-server-cert.jceks
similarity index 100%
rename from libraries/http/src/test/resources/org/qi4j/library/http/qi4j-lib-http-unittests-server-cert.jceks
rename to libraries/http/src/test/resources/org/apache/polygene/library/http/polygene-lib-http-unittests-server-cert.jceks
Binary files differ
diff --git a/libraries/http/src/vhost-test/java/org/apache/polygene/library/http/VirtualHostJettyServiceTest.java b/libraries/http/src/vhost-test/java/org/apache/polygene/library/http/VirtualHostJettyServiceTest.java
new file mode 100644
index 0000000..88afe0e
--- /dev/null
+++ b/libraries/http/src/vhost-test/java/org/apache/polygene/library/http/VirtualHostJettyServiceTest.java
@@ -0,0 +1,91 @@
+/*
+ *  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.polygene.library.http;
+
+import java.io.IOException;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.http.dns.LocalManagedDns;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.util.FreePortFinder;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.apache.polygene.library.http.Servlets.addServlets;
+import static org.apache.polygene.library.http.Servlets.serve;
+import static org.apache.polygene.test.util.Assume.assumeNoIbmJdk;
+import static org.junit.Assert.assertEquals;
+
+public class VirtualHostJettyServiceTest
+    extends AbstractJettyTest
+{
+    private static final String HOST1 = "host1.http.library.polygene";
+    private static final String HOST2 = "host2.http.library.polygene";
+
+    private final int httpPort = FreePortFinder.findFreePortOnLoopback();
+
+    @BeforeClass
+    public static void beforeVirtualHostsClass()
+    {
+        assumeNoIbmJdk();
+        LocalManagedDns.putName( HOST1, "127.0.0.1" );
+        LocalManagedDns.putName( HOST2, "127.0.0.1" );
+    }
+
+    @AfterClass
+    public static void afterVirtualHostsClass()
+    {
+        LocalManagedDns.removeName( HOST1 );
+        LocalManagedDns.removeName( HOST2 );
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ModuleAssembly configModule = module;
+        new EntityTestAssembler().assemble( configModule );
+        new JettyServiceAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
+
+        SecureJettyConfiguration config = configModule.forMixin( SecureJettyConfiguration.class ).declareDefaults();
+        config.hostName().set( "127.0.0.1" );
+        config.port().set( httpPort );
+        config.virtualHosts().set( HOST1 + "," + HOST2 );
+
+        addServlets( serve( "/hello" ).with( HelloWorldServletService.class ) ).to( module );
+    }
+
+    @Test
+    public void test()
+        throws IOException
+    {
+        // Available on HOST1 and HOST2
+        String output = defaultHttpClient.execute( new HttpGet( "http://" + HOST1 + ":" + httpPort + "/hello" ),
+                                                   stringResponseHandler );
+        assertEquals( "Hello World", output );
+
+        output = defaultHttpClient.execute( new HttpGet( "http://" + HOST2 + ":" + httpPort + "/hello" ),
+                                            stringResponseHandler );
+        assertEquals( "Hello World", output );
+    }
+}
diff --git a/libraries/http/src/vhost-test/java/org/apache/polygene/library/http/dns/LocalManagedDns.java b/libraries/http/src/vhost-test/java/org/apache/polygene/library/http/dns/LocalManagedDns.java
new file mode 100644
index 0000000..065c35a
--- /dev/null
+++ b/libraries/http/src/vhost-test/java/org/apache/polygene/library/http/dns/LocalManagedDns.java
@@ -0,0 +1,125 @@
+/*
+ *  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.polygene.library.http.dns;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import org.xbill.DNS.spi.DNSJavaNameServiceDescriptor;
+import sun.net.spi.nameservice.NameService;
+
+public class LocalManagedDns
+        implements NameService
+{
+
+    private static final NameService DEFAULT_DNS = new DNSJavaNameServiceDescriptor().createNameService();
+    private static final Map<String, String> NAMES = new ConcurrentHashMap<String, String>();
+
+    public static void clearNames()
+    {
+        NAMES.clear();
+    }
+
+    public static String putName( String name, String ip )
+    {
+        return NAMES.put( name, ip );
+    }
+
+    public static String removeName( String name )
+    {
+        return NAMES.remove( name );
+    }
+
+    public String getHostByAddr( byte[] bytes )
+            throws UnknownHostException
+    {
+        return DEFAULT_DNS.getHostByAddr( bytes );
+    }
+
+    public InetAddress[] lookupAllHostAddr( String name )
+            throws UnknownHostException
+    {
+        String log = "[CDNS] Lookup request";
+        String ip = NAMES.get( name );
+        InetAddress[] result = new InetAddress[ 0 ];
+        if ( ip != null && ip.length() > 0 ) {
+            log += " on managed name (" + name + ")";
+            byte[] ipBytes = ipStringToBytes( ip );
+            result = new InetAddress[]{ Inet4Address.getByAddress( ipBytes ) };
+        } else {
+            log += " on non-managed name (" + name + ")";
+            result = DEFAULT_DNS.lookupAllHostAddr( name );
+        }
+        return result;
+    }
+
+    private static byte[] ipStringToBytes( String ipString )
+    {
+        if ( ipString == null || ipString.length() == 0 ) {
+            return null;
+        }
+
+        int inetAddrSize = 4;
+        int octets;
+        char ch;
+        byte[] dst = new byte[ inetAddrSize ];
+        char[] srcb = ipString.toCharArray();
+        boolean saw_digit = false;
+
+        octets = 0;
+        int i = 0;
+        int cur = 0;
+        while ( i < srcb.length ) {
+            ch = srcb[i++];
+            if ( Character.isDigit( ch ) ) {
+                int sum = dst[cur] * 10 + ( Character.digit( ch, 10 ) & 0xff );
+
+                if ( sum > 255 ) {
+                    return null;
+                }
+
+                dst[cur] = ( byte ) ( sum & 0xff );
+                if ( !saw_digit ) {
+                    if ( ++octets > inetAddrSize ) {
+                        return null;
+                    }
+                    saw_digit = true;
+                }
+            } else if ( ch == '.' && saw_digit ) {
+                if ( octets == inetAddrSize ) {
+                    return null;
+                }
+                cur++;
+                dst[cur] = 0;
+                saw_digit = false;
+            } else {
+                return null;
+            }
+        }
+
+        if ( octets < inetAddrSize ) {
+            return null;
+        }
+        return dst;
+    }
+
+}
diff --git a/libraries/http/src/vhost-test/java/org/apache/polygene/library/http/dns/LocalManagedDnsDescriptor.java b/libraries/http/src/vhost-test/java/org/apache/polygene/library/http/dns/LocalManagedDnsDescriptor.java
new file mode 100644
index 0000000..91af739
--- /dev/null
+++ b/libraries/http/src/vhost-test/java/org/apache/polygene/library/http/dns/LocalManagedDnsDescriptor.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.library.http.dns;
+
+import sun.net.spi.nameservice.NameService;
+import sun.net.spi.nameservice.NameServiceDescriptor;
+
+public class LocalManagedDnsDescriptor
+        implements NameServiceDescriptor
+{
+
+    public static final String PROVIDER_NAME = "LocalManagedDns";
+    private static final NameService nameService = new LocalManagedDns();
+
+    public NameService createNameService()
+            throws Exception
+    {
+        return nameService;
+    }
+
+    public String getProviderName()
+    {
+        return PROVIDER_NAME;
+    }
+
+    public String getType()
+    {
+        return "dns";
+    }
+
+}
diff --git a/libraries/http/src/vhost-test/resources/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor b/libraries/http/src/vhost-test/resources/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
new file mode 100644
index 0000000..093db66
--- /dev/null
+++ b/libraries/http/src/vhost-test/resources/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
@@ -0,0 +1,17 @@
+#  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.
+
+org.apache.polygene.library.http.dns.LocalManagedDnsDescriptor
diff --git a/libraries/http/src/vhost-test/resources/logback.xml b/libraries/http/src/vhost-test/resources/logback.xml
new file mode 100644
index 0000000..cacadbd
--- /dev/null
+++ b/libraries/http/src/vhost-test/resources/logback.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<configuration>
+
+    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>[POLYGENE] @%-20thread %-5level %logger{36} - %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <root level="info">
+        <appender-ref ref="stdout" />
+    </root>
+
+    <logger name="org.apache.polygene.library.http" level="trace"/>
+    <logger name="org.eclipse.jetty" level="info"/>
+    <logger name="org.jetty" level="info"/>
+    
+</configuration>
diff --git a/libraries/invocation-cache/build.gradle b/libraries/invocation-cache/build.gradle
index 332d3d3..96c6f77 100644
--- a/libraries/invocation-cache/build.gradle
+++ b/libraries/invocation-cache/build.gradle
@@ -1,32 +1,37 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Invocation Cache Library provides caching framework for methods."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - Invocation Cache" }}
+description = "Apache Polygene™ Invocation Cache Library provides caching framework for methods."
+
+jar { manifest { name = "Apache Polygene™ Library - Invocation Cache" } }
 
 dependencies {
-  compile( project(":org.qi4j.core:org.qi4j.core.api") )
-  compile( project(':org.qi4j.libraries:org.qi4j.library.jmx' ) )
+  api polygene.core.api
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
+  implementation polygene.library( 'jmx' )
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/libraries/invocation-cache/dev-status.xml b/libraries/invocation-cache/dev-status.xml
index 7ea746d..fd9e5a4 100644
--- a/libraries/invocation-cache/dev-status.xml
+++ b/libraries/invocation-cache/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/invocation-cache/src/docs/invocation-cache.txt b/libraries/invocation-cache/src/docs/invocation-cache.txt
index e613c6b..edb6ed2 100644
--- a/libraries/invocation-cache/src/docs/invocation-cache.txt
+++ b/libraries/invocation-cache/src/docs/invocation-cache.txt
@@ -63,7 +63,7 @@
 
 [snippet,java]
 ----
-source=libraries/invocation-cache/src/test/java/org/qi4j/library/invocationcache/DocumentationSupport.java
+source=libraries/invocation-cache/src/test/java/org/apache/polygene/library/invocationcache/DocumentationSupport.java
 tag=composite
 ----
 
@@ -73,7 +73,7 @@
 
 [snippet,java]
 ----
-source=libraries/invocation-cache/src/test/java/org/qi4j/library/invocationcache/DocumentationSupport.java
+source=libraries/invocation-cache/src/test/java/org/apache/polygene/library/invocationcache/DocumentationSupport.java
 tag=assembly
 ----
 
diff --git a/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/Cached.java b/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/Cached.java
new file mode 100644
index 0000000..1456a40
--- /dev/null
+++ b/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/Cached.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.library.invocationcache;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Mark interfaces or methods whose results should be cached with this annotation.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.METHOD, ElementType.TYPE } )
+@Documented
+@Inherited
+public @interface Cached
+{
+}
diff --git a/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/InvocationCache.java b/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/InvocationCache.java
new file mode 100644
index 0000000..fbf8259
--- /dev/null
+++ b/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/InvocationCache.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.invocationcache;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+/**
+ * Invocation Cache.
+ */
+@Mixins( SimpleInvocationCacheMixin.class )
+public interface InvocationCache
+{
+    Object setCachedValue( String name, Object aResult );
+
+    Object cachedValue( String name );
+
+    Object removeCachedValue( String name );
+
+    void clearCachedValues();
+
+    int currentCacheSize();
+}
diff --git a/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/ReturnCachedValueConcern.java b/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/ReturnCachedValueConcern.java
new file mode 100644
index 0000000..9e1abb3
--- /dev/null
+++ b/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/ReturnCachedValueConcern.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.library.invocationcache;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.injection.scope.This;
+
+/**
+ * Return value of @Cached calls if possible.
+ */
+@AppliesTo( Cached.class )
+public class ReturnCachedValueConcern
+    extends ConcernOf<InvocationHandler>
+    implements InvocationHandler
+{
+    @This @Optional
+    private InvocationCache cache;
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        boolean voidReturnType = method.getReturnType().equals( Void.TYPE );
+        if( cache != null || voidReturnType )
+        {
+            // Try cache
+            String cacheName = method.getName();
+            if( args != null )
+            {
+                cacheName += Arrays.asList( args );
+            }
+            Object result = cache.cachedValue( cacheName );
+            if( result != null )
+            {
+                return result;
+            }
+        }
+        // No cached value found or no InvocationCache defined - call method
+        return next.invoke( proxy, method, args );
+    }
+}
diff --git a/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/ReturnCachedValueOnExceptionConcern.java b/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/ReturnCachedValueOnExceptionConcern.java
new file mode 100644
index 0000000..a572f1a
--- /dev/null
+++ b/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/ReturnCachedValueOnExceptionConcern.java
@@ -0,0 +1,72 @@
+/*
+ *  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.polygene.library.invocationcache;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.injection.scope.This;
+
+/**
+ * Return value of @Cached calls on exceptions.
+ * <p>
+ * If an Exception occurs, try to reuse a previous result. Don't do anything on Throwables.
+ * </p>
+ */
+@AppliesTo( Cached.class )
+public class ReturnCachedValueOnExceptionConcern
+    extends ConcernOf<InvocationHandler>
+    implements InvocationHandler
+{
+    @This
+    private InvocationCache cache;
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        boolean voidReturnType = method.getReturnType().equals( Void.TYPE );
+        if( cache != null || voidReturnType ) // Skip if void return type or no InvocationCache has been defined.
+        {
+            String cacheName = method.getName();
+            if( args != null )
+            {
+                cacheName += Arrays.asList( args );
+            }
+            try
+            {
+                // Invoke method
+                Object result = next.invoke( proxy, method, args );
+                // update cache
+                cache.setCachedValue( cacheName, result );
+                return result;
+            }
+            catch( Exception e )
+            {
+                // Try cache
+                return cache.cachedValue( cacheName );
+            }
+        }
+        // if no InvocationCache is present.
+        return next.invoke( proxy, method, args );
+    }
+}
diff --git a/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/SimpleInvocationCacheMixin.java b/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/SimpleInvocationCacheMixin.java
new file mode 100644
index 0000000..c90fc3c
--- /dev/null
+++ b/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/SimpleInvocationCacheMixin.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.library.invocationcache;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Simple implementation of InvocationCache.
+ * <p>
+ * This {@link InvocationCache} should typically not be used at all, and only serves as an
+ * example. The @{code cachedValues} member is never emptied, so it constitutes a memory leak
+ * if the method arguments keep changing.
+ * </p>
+ * <p>
+ * <b>IMPORTANT: Only use this is you know that only a small set of arguments are used into your
+ * method(s).</b>
+ * </p>
+ */
+public class SimpleInvocationCacheMixin
+    implements InvocationCache
+{
+    private final Map<String, Object> cachedValues = new ConcurrentHashMap<>();
+
+    @Override
+    public Object setCachedValue( String name, Object aResult )
+    {
+        return cachedValues.put( name, aResult );
+    }
+
+    @Override
+    public Object cachedValue( String name )
+    {
+        return cachedValues.get( name );
+    }
+
+    @Override
+    public Object removeCachedValue( String name )
+    {
+        return cachedValues.remove( name );
+    }
+
+    @Override
+    public void clearCachedValues()
+    {
+        cachedValues.clear();
+    }
+
+    @Override
+    public int currentCacheSize()
+    {
+        return cachedValues.size();
+    }
+}
diff --git a/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/package.html b/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/package.html
new file mode 100644
index 0000000..b0ec655
--- /dev/null
+++ b/libraries/invocation-cache/src/main/java/org/apache/polygene/library/invocationcache/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Invocation Cache Library.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/Cached.java b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/Cached.java
deleted file mode 100644
index f2e26bc..0000000
--- a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/Cached.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg.
- *
- * Licensed  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.qi4j.library.invocationcache;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Mark interfaces or methods whose results should be cached with this annotation.
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.METHOD, ElementType.TYPE } )
-@Documented
-@Inherited
-public @interface Cached
-{
-}
diff --git a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvocationCache.java b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvocationCache.java
deleted file mode 100644
index 4ab8e9c..0000000
--- a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/InvocationCache.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg.
- *
- * Licensed  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.qi4j.library.invocationcache;
-
-import org.qi4j.api.mixin.Mixins;
-
-/**
- * Invocation Cache.
- */
-@Mixins( SimpleInvocationCacheMixin.class )
-public interface InvocationCache
-{
-    Object setCachedValue( String name, Object aResult );
-
-    Object cachedValue( String name );
-
-    Object removeCachedValue( String name );
-
-    void clearCachedValues();
-
-    int currentCacheSize();
-}
diff --git a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/ReturnCachedValueConcern.java b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/ReturnCachedValueConcern.java
deleted file mode 100644
index 9ad0d3f..0000000
--- a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/ReturnCachedValueConcern.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg.
- *
- * Licensed  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.qi4j.library.invocationcache;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.injection.scope.Invocation;
-import org.qi4j.api.injection.scope.This;
-
-/**
- * Return value of @Cached calls if possible.
- */
-@AppliesTo( Cached.class )
-public class ReturnCachedValueConcern
-    extends ConcernOf<InvocationHandler>
-    implements InvocationHandler
-{
-    @This @Optional
-    private InvocationCache cache;
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        boolean voidReturnType = method.getReturnType().equals( Void.TYPE );
-        if( cache != null || voidReturnType )
-        {
-            // Try cache
-            String cacheName = method.getName();
-            if( args != null )
-            {
-                cacheName += Arrays.asList( args );
-            }
-            Object result = cache.cachedValue( cacheName );
-            if( result != null )
-            {
-                return result;
-            }
-        }
-        // No cached value found or no InvocationCache defined - call method
-        return next.invoke( proxy, method, args );
-    }
-}
diff --git a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/ReturnCachedValueOnExceptionConcern.java b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/ReturnCachedValueOnExceptionConcern.java
deleted file mode 100644
index 1287b39..0000000
--- a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/ReturnCachedValueOnExceptionConcern.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg.
- *
- * Licensed  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.qi4j.library.invocationcache;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.injection.scope.This;
-
-/**
- * Return value of @Cached calls on exceptions.
- * <p>
- * If an Exception occurs, try to reuse a previous result. Don't do anything on Throwables.
- * </p>
- */
-@AppliesTo( Cached.class )
-public class ReturnCachedValueOnExceptionConcern
-    extends ConcernOf<InvocationHandler>
-    implements InvocationHandler
-{
-    @This
-    private InvocationCache cache;
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        boolean voidReturnType = method.getReturnType().equals( Void.TYPE );
-        if( cache != null || voidReturnType ) // Skip if void return type or no InvocationCache has been defined.
-        {
-            String cacheName = method.getName();
-            if( args != null )
-            {
-                cacheName += Arrays.asList( args );
-            }
-            try
-            {
-                // Invoke method
-                Object result = next.invoke( proxy, method, args );
-                // update cache
-                cache.setCachedValue( cacheName, result );
-                return result;
-            }
-            catch( Exception e )
-            {
-                // Try cache
-                return cache.cachedValue( cacheName );
-            }
-        }
-        // if no InvocationCache is present.
-        return next.invoke( proxy, method, args );
-    }
-}
diff --git a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/SimpleInvocationCacheMixin.java b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/SimpleInvocationCacheMixin.java
deleted file mode 100644
index 5897412..0000000
--- a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/SimpleInvocationCacheMixin.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg.
- *
- * Licensed  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.qi4j.library.invocationcache;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Simple implementation of InvocationCache.
- * <p>
- * This {@link InvocationCache} should typically not be used at all, and only serves as an
- * example. The @{code cachedValues} member is never emptied, so it constitutes a memory leak
- * if the method arguments keep changing.
- * </p>
- * <p>
- * <b>IMPORTANT: Only use this is you know that only a small set of arguments are used into your
- * method(s).</b>
- * </p>
- */
-public class SimpleInvocationCacheMixin
-    implements InvocationCache
-{
-    private final Map<String, Object> cachedValues = new ConcurrentHashMap<>();
-
-    @Override
-    public Object setCachedValue( String name, Object aResult )
-    {
-        return cachedValues.put( name, aResult );
-    }
-
-    @Override
-    public Object cachedValue( String name )
-    {
-        return cachedValues.get( name );
-    }
-
-    @Override
-    public Object removeCachedValue( String name )
-    {
-        return cachedValues.remove( name );
-    }
-
-    @Override
-    public void clearCachedValues()
-    {
-        cachedValues.clear();
-    }
-
-    @Override
-    public int currentCacheSize()
-    {
-        return cachedValues.size();
-    }
-}
diff --git a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/package.html b/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/package.html
deleted file mode 100644
index 09f0a48..0000000
--- a/libraries/invocation-cache/src/main/java/org/qi4j/library/invocationcache/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Invocation Cache Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/invocation-cache/src/test/java/org/apache/polygene/library/invocationcache/DocumentationSupport.java b/libraries/invocation-cache/src/test/java/org/apache/polygene/library/invocationcache/DocumentationSupport.java
new file mode 100644
index 0000000..64b68b6
--- /dev/null
+++ b/libraries/invocation-cache/src/test/java/org/apache/polygene/library/invocationcache/DocumentationSupport.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.polygene.library.invocationcache;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+
+public class DocumentationSupport
+{
+// START SNIPPET: composite
+    public interface ExpensiveOperation
+    {
+        @Cached
+        double compute( double... arguments );
+    }
+// END SNIPPET: composite
+
+// START SNIPPET: assembly
+    public class ExpensiveModuleAssembler
+        implements ModuleAssembler{
+
+        @Override
+        public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.services( ExpensiveOperation.class )
+                .withMixins( SimpleInvocationCacheMixin.class )
+                .withConcerns( ReturnCachedValueConcern.class );
+            return module;
+        }
+    }
+// END SNIPPET: assembly
+}
diff --git a/libraries/invocation-cache/src/test/java/org/qi4j/library/invocationcache/DocumentationSupport.java b/libraries/invocation-cache/src/test/java/org/qi4j/library/invocationcache/DocumentationSupport.java
deleted file mode 100644
index 782ce76..0000000
--- a/libraries/invocation-cache/src/test/java/org/qi4j/library/invocationcache/DocumentationSupport.java
+++ /dev/null
@@ -1,51 +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.qi4j.library.invocationcache;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.layered.ModuleAssembler;
-
-public class DocumentationSupport
-{
-// START SNIPPET: composite
-    public interface ExpensiveOperation
-    {
-        @Cached
-        double compute( double... arguments );
-    }
-// END SNIPPET: composite
-
-// START SNIPPET: assembly
-    public class ExpensiveModuleAssembler
-        implements ModuleAssembler{
-
-        @Override
-        public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.services( ExpensiveOperation.class )
-                .withMixins( SimpleInvocationCacheMixin.class )
-                .withConcerns( ReturnCachedValueConcern.class );
-            return module;
-        }
-    }
-// END SNIPPET: assembly
-}
diff --git a/libraries/jmx/build.gradle b/libraries/jmx/build.gradle
index 79193da..4dd6894 100644
--- a/libraries/jmx/build.gradle
+++ b/libraries/jmx/build.gradle
@@ -1,38 +1,45 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
+import org.apache.polygene.gradle.TaskGroups
 
-description = "Apache Zest™ JMX Library provides Java Management Extension (JMX) integration for Apache Zest™ applications."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - JMX" }}
+description = "Apache Polygene™ JMX Library provides Java Management Extension (JMX) integration for Apache Polygene™ applications."
+
+jar { manifest { name = "Apache Polygene™ Library - JMX" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile libraries.slf4j_api
+  api polygene.core.bootstrap
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
+  implementation libraries.slf4j_api
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
 }
 
-task(runSample, dependsOn: 'testClasses', type: JavaExec) {
-    main = 'org.qi4j.library.jmx.JMXTest'
-    classpath = sourceSets.test.runtimeClasspath
+task( runJmxSample, dependsOn: 'testClasses', type: JavaExec ) {
+  group = TaskGroups.SAMPLES
+  description = "Runs $project.name sample."
+  main = 'org.apache.polygene.library.jmx.JMXTest'
+  classpath = sourceSets.test.runtimeClasspath
 }
-
diff --git a/libraries/jmx/dev-status.xml b/libraries/jmx/dev-status.xml
index f549c99..97fd7ff 100644
--- a/libraries/jmx/dev-status.xml
+++ b/libraries/jmx/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/jmx/src/docs/jmx.txt b/libraries/jmx/src/docs/jmx.txt
index b8421a4..7817d72 100644
--- a/libraries/jmx/src/docs/jmx.txt
+++ b/libraries/jmx/src/docs/jmx.txt
@@ -25,21 +25,34 @@
 source=libraries/jmx/dev-status.xml
 --------------
 
-The JMX library provides a service that exposes a Zest™ app in
-JMX automatically, giving you an opportunity to inspect the app much as
+The JMX library provides a service that exposes a Polygene™ application in
+http://www.oracle.com/technetwork/articles/java/docs-jsp-135989.html[JMX]
+automatically, giving you an opportunity to inspect the application much as
 you would with the <<tools-envisage>> tool.
 
 include::../../build/docs/buildinfo/artifact.txt[]
 
-== Usage ==
+Services configuration is editable through their corresponding JMX beans.
+You can also restart your services so the new configuration is picked up.
+
+image:library-jmx.png[]
+
+
+
+== Assembly ==
+
+JMX Support for Polygene™ applications:
 
 [snippet,java]
 ----
-source=libraries/jmx/src/test/java/org/qi4j/library/jmx/JMXTest.java
+source=libraries/jmx/src/test/java/org/apache/polygene/library/jmx/JMXTest.java
 tag=assembly
 ----
 
-Note that you need to run it with -Dcom.sun.management.jmxremote so that the
-JVM starts the MBeanServer.
+Managing the MX Beans Server from your Polygene™ application using the `JMXConnectorService`:
 
-image:library-jmx.png[]
+[snippet,java]
+----
+source=libraries/jmx/src/test/java/org/apache/polygene/library/jmx/JMXTest.java
+tag=connector
+----
diff --git a/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/ApplicationManagerService.java b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/ApplicationManagerService.java
new file mode 100644
index 0000000..017567d
--- /dev/null
+++ b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/ApplicationManagerService.java
@@ -0,0 +1,379 @@
+/*
+ *  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.polygene.library.jmx;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+import java.util.stream.Collectors;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.modelmbean.ModelMBeanOperationInfo;
+import javax.management.modelmbean.RequiredModelMBean;
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitorAdapter;
+
+import static org.apache.polygene.api.service.qualifier.ServiceQualifier.withId;
+
+/**
+ * Expose the Polygene app as a "tree" of MBeans.
+ *
+ * Other services should reuse the object names and create
+ * nodes under the ones created here. For example:
+ * <pre>
+ * Polygene:application=MyApp,layer=Application,module=MyModule,class=Service,service=MyService
+ * </pre>
+ * is exported by this service, so another exporter showing some aspect related to this service should
+ * use this as base for the ObjectName, and add their own properties. Example:
+ * <pre>
+ * Polygene:application=MyApp,layer=Application,module=MyModule,class=Service,service=MyService,name=Configuration
+ * </pre>
+ * Use the following snippet to find the ObjectName of a service with a given reference:
+ * <pre>
+ * ObjectName serviceName = PolygeneMBeans.findService(mbeanServer, applicationName, serviceId);
+ * </pre>
+ */
+@Mixins( ApplicationManagerService.Mixin.class )
+@Activators( ApplicationManagerService.Activator.class )
+public interface ApplicationManagerService
+{
+
+    void exportApplicationStructure()
+        throws Exception;
+
+    void unexportApplicationStructure()
+        throws Exception;
+
+    class Activator
+        extends ActivatorAdapter<ServiceReference<ApplicationManagerService>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<ApplicationManagerService> activated )
+            throws Exception
+        {
+            activated.get().exportApplicationStructure();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<ApplicationManagerService> passivating )
+            throws Exception
+        {
+            passivating.get().unexportApplicationStructure();
+        }
+    }
+
+    abstract class Mixin
+        implements ApplicationManagerService
+    {
+        @Service
+        public MBeanServer server;
+
+        @Structure
+        public Application application;
+
+        private List<ObjectName> mbeans = new ArrayList<>();
+
+        @Override
+        public void exportApplicationStructure()
+            throws Exception
+        {
+            application.descriptor().accept( new HierarchicalVisitorAdapter<Object, Object, Exception>()
+            {
+                Layer layer;
+                Module module;
+                Stack<ObjectName> names = new Stack<>();
+
+                @Override
+                public boolean visitEnter( Object visited )
+                    throws Exception
+                {
+                    if( visited instanceof LayerDescriptor )
+                    {
+                        LayerDescriptor layerDescriptor = (LayerDescriptor) visited;
+                        layer = application.findLayer( layerDescriptor.name() );
+
+                        LayerBean layerBean = new LayerBean( layer, layerDescriptor );
+                        ObjectName objectName = new ObjectName( "Polygene:application=" + application.name() + ",layer=" + layer
+                            .name() );
+                        names.push( objectName );
+
+                        RequiredModelMBean mbean = new ModelMBeanBuilder( objectName, layerDescriptor.name(), LayerBean.class
+                            .getName() ).
+                            attribute( "uses", "Layer usages", String.class.getName(), "Other layers that this layer uses", "getUses", null )
+                            .operation( "restart", "Restart layer", String.class.getName(), MBeanOperationInfo.ACTION_INFO )
+                            .newModelMBean();
+
+                        mbean.setManagedResource( layerBean, "ObjectReference" );
+                        server.registerMBean( mbean, objectName );
+                        mbeans.add( objectName );
+                    }
+                    else if( visited instanceof ModuleDescriptor )
+                    {
+                        ModuleDescriptor moduleDescriptor = (ModuleDescriptor) visited;
+                        module = application.findModule( layer.name(), moduleDescriptor.name() );
+                        ObjectName objectName = new ObjectName( names.peek()
+                                                                    .toString() + ",module=" + moduleDescriptor.name() );
+                        names.push( objectName );
+                        RequiredModelMBean mbean = new ModelMBeanBuilder( objectName, moduleDescriptor.name(), moduleDescriptor
+                            .getClass()
+                            .getName() ).
+                            attribute( "name", "Module name", String.class.getName(), "Name of module", "name", null ).
+                            newModelMBean();
+
+                        mbean.setManagedResource( moduleDescriptor, "ObjectReference" );
+
+                        server.registerMBean( mbean, objectName );
+                        mbeans.add( objectName );
+                    }
+                    else if( visited instanceof ServiceDescriptor )
+                    {
+                        ServiceDescriptor serviceDescriptor = (ServiceDescriptor) visited;
+                        ObjectName objectName = new ObjectName( names.peek()
+                                                                    .toString() + ",class=Service,service=" + serviceDescriptor
+                                                                    .identity() );
+                        RequiredModelMBean mbean = new ModelMBeanBuilder( objectName, serviceDescriptor.identity().toString(), ServiceBean.class
+                            .getName() ).
+                            attribute( "Id", "Service id", String.class.getName(), "Id of service", "getId", null ).
+                            attribute( "Visibility", "Service visibility", String.class.getName(), "Visibility of service", "getVisibility", null )
+                            .
+                                attribute( "Type", "Service type", String.class.getName(), "Type of service", "getType", null )
+                            .
+                                attribute( "Active", "Service is active", Boolean.class.getName(), "Service is active", "isActive", null )
+                            .
+                                attribute( "Available", "Service is available", Boolean.class.getName(), "Service is available", "isAvailable", null )
+                            .
+                                operation( "restart", "Restart service", String.class.getName(), ModelMBeanOperationInfo.ACTION_INFO )
+                            .
+                                newModelMBean();
+
+                        mbean.setManagedResource( new ServiceBean( serviceDescriptor, module ), "ObjectReference" );
+
+                        server.registerMBean( mbean, objectName );
+                        mbeans.add( objectName );
+                    }
+                    else if( visited instanceof ImportedServiceDescriptor )
+                    {
+                        ImportedServiceDescriptor importedServiceDescriptor = (ImportedServiceDescriptor) visited;
+                        ObjectName objectName = new ObjectName( names.peek()
+                                                                    .toString() + ",class=Imported service,importedservice=" + importedServiceDescriptor
+                                                                    .identity() );
+                        RequiredModelMBean mbean = new ModelMBeanBuilder( objectName, importedServiceDescriptor.identity().toString(), ImportedServiceBean.class
+                            .getName() ).
+                            attribute( "Id", "Service id", String.class.getName(), "Id of service", "getId", null ).
+                            attribute( "Visibility", "Service visibility", String.class.getName(), "Visibility of service", "getVisibility", null )
+                            .
+                                attribute( "Type", "Service type", String.class.getName(), "Type of imported service", "getType", null )
+                            .
+                                newModelMBean();
+
+                        mbean.setManagedResource( new ImportedServiceBean( importedServiceDescriptor ), "ObjectReference" );
+
+                        server.registerMBean( mbean, objectName );
+                        mbeans.add( objectName );
+                    }
+
+                    return !( visited instanceof ModelDescriptor );
+                }
+
+                @Override
+                public boolean visitLeave( Object visited )
+                    throws Exception
+                {
+                    if( visited instanceof ModuleDescriptor || visited instanceof LayerDescriptor )
+                    {
+                        names.pop();
+                    }
+
+                    return true;
+                }
+            } );
+        }
+
+        @Override
+        public void unexportApplicationStructure()
+            throws Exception
+        {
+            for( ObjectName mbean : mbeans )
+            {
+                server.unregisterMBean( mbean );
+            }
+        }
+    }
+
+    class LayerBean
+    {
+        private final Layer layer;
+        private final LayerDescriptor layerDescriptor;
+        private String uses;
+
+        public LayerBean( Layer layer, LayerDescriptor layerDescriptor )
+        {
+            this.layer = layer;
+            this.layerDescriptor = layerDescriptor;
+
+            uses = layerDescriptor.usedLayers()
+                .layers()
+                .map( LayerDescriptor::name )
+                .collect( Collectors.joining(" ", "Uses: ", "") );
+        }
+
+        public String getUses()
+        {
+            return uses;
+        }
+
+        public String restart()
+            throws Exception
+        {
+            try
+            {
+                layer.passivate();
+                layer.activate();
+                return "Restarted layer";
+            }
+            catch( Exception e )
+            {
+                return "Could not restart layer:" + e.getMessage();
+            }
+        }
+    }
+
+    class ServiceBean
+    {
+        private final ServiceDescriptor serviceDescriptor;
+        private final Module module;
+
+        public ServiceBean( ServiceDescriptor serviceDescriptor, Module module )
+        {
+            this.serviceDescriptor = serviceDescriptor;
+            this.module = module;
+        }
+
+        public String getId()
+        {
+            return serviceDescriptor.identity().toString();
+        }
+
+        public String getVisibility()
+        {
+            return serviceDescriptor.visibility().name();
+        }
+
+        public String getType()
+        {
+            Class<?> first = serviceDescriptor.types().findFirst().orElse( null );
+            if( first == null )
+            {
+                return null;
+            }
+            return first.getName();
+        }
+
+        public boolean isActive()
+        {
+            Class<?> mainType = serviceDescriptor.types().findFirst().orElse( null );
+            ServiceReference<?> first = module.findServices( mainType )
+                                              .filter( withId( serviceDescriptor.identity().toString() ) )
+                                              .findFirst().orElse( null );
+            return first != null && first.isActive();
+        }
+
+        public boolean isAvailable()
+        {
+            Class<?> mainType = serviceDescriptor.types().findFirst().orElse( null );
+            ServiceReference<?> first = module.findServices( mainType )
+                                              .filter( withId( serviceDescriptor.identity().toString() ) )
+                                              .findFirst().orElse( null );
+            return first != null && first.isAvailable();
+        }
+
+        public String restart()
+        {
+            ServiceReference<?> serviceRef = module.findServices( serviceDescriptor.types()
+                                                                                   .findFirst().orElse( null ) )
+                                                   .filter( withId( serviceDescriptor.identity().toString() ) )
+                                                   .findFirst().orElse( null );
+            if( serviceRef != null )
+            {
+                try
+                {
+                    ( (Activation) serviceRef ).passivate();
+                    ( (Activation) serviceRef ).activate();
+                    return "Restarted service";
+                }
+                catch( Exception e )
+                {
+                    return "Could not restart service:" + e.getMessage();
+                }
+            }
+            else
+            {
+                return "Could not find service";
+            }
+        }
+    }
+
+    class ImportedServiceBean
+    {
+        private final ImportedServiceDescriptor serviceDescriptor;
+
+        public ImportedServiceBean( ImportedServiceDescriptor serviceDescriptor )
+        {
+            this.serviceDescriptor = serviceDescriptor;
+        }
+
+        public String getId()
+        {
+            return serviceDescriptor.identity().toString();
+        }
+
+        public String getVisibility()
+        {
+            return serviceDescriptor.visibility().name();
+        }
+
+        public String getType()
+        {
+            Class<?> mainType = serviceDescriptor.types().findFirst().orElse( null );
+            if( mainType == null )
+            {
+                return null;
+            }
+            return mainType.getName();
+        }
+    }
+}
diff --git a/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/ConfigurationManagerService.java b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/ConfigurationManagerService.java
new file mode 100644
index 0000000..50485d1
--- /dev/null
+++ b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/ConfigurationManagerService.java
@@ -0,0 +1,412 @@
+/*
+ *  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.polygene.library.jmx;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.Descriptor;
+import javax.management.DynamicMBean;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import javax.management.modelmbean.DescriptorSupport;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.EnumType;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.spi.PolygeneSPI;
+
+/**
+ * Expose ConfigurationComposites through JMX.
+ * Allow configurations to be edited, and the services to be restarted.
+ */
+@Mixins( ConfigurationManagerService.Mixin.class )
+@Activators( ConfigurationManagerService.Activator.class )
+public interface ConfigurationManagerService
+{
+    void exportConfigurableServices()
+            throws Exception;
+
+    void unexportConfigurableServices()
+            throws Exception;
+
+    class Activator
+            extends ActivatorAdapter<ServiceReference<ConfigurationManagerService>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<ConfigurationManagerService> activated )
+                throws Exception
+        {
+            activated.get().exportConfigurableServices();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<ConfigurationManagerService> passivating )
+                throws Exception
+        {
+            passivating.get().unexportConfigurableServices();
+        }
+
+    }
+
+    abstract class Mixin
+        implements ConfigurationManagerService
+    {
+        @Structure
+        UnitOfWorkFactory uowf;
+
+        @Service
+        MBeanServer server;
+
+        @Structure
+        Application application;
+
+        @Structure
+        PolygeneSPI spi;
+
+        @Service
+        Iterable<ServiceReference<?>> configurableServices;
+
+        private List<ObjectName> configurationNames = new ArrayList<>();
+
+        @Override
+        public void exportConfigurableServices()
+            throws NotCompliantMBeanException, MBeanRegistrationException, InstanceAlreadyExistsException, MalformedObjectNameException
+        {
+            for( ServiceReference<?> configurableService : configurableServices )
+            {
+                Object service = configurableService.get();
+
+                if( !( service instanceof Composite ) )
+                {
+                    continue; // Skip imported services
+                }
+
+                // Check if service has configuration
+                CompositeInstance compositeInstance = PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF.apply( (Composite) service );
+                try
+                {
+                    Configuration config = compositeInstance.newProxy( Configuration.class );
+                }
+                catch( Exception e )
+                {
+                    // Service does not have configuration
+                    continue;
+                }
+
+                String serviceClass = compositeInstance.types().findFirst().get().getName();
+                ServiceDescriptor serviceDescriptor = spi.serviceDescriptorFor( configurableService );
+                ModuleDescriptor module = spi.moduleOf( configurableService );
+                Class<Object> configurationClass = serviceDescriptor.configurationType();
+                if( configurationClass != null )
+                {
+                    EntityDescriptor descriptor = module.entityDescriptor( configurationClass.getName() );
+                    List<MBeanAttributeInfo> attributes = new ArrayList<>();
+                    Map<String, AccessibleObject> properties = new HashMap<>();
+                    descriptor.state().properties().forEach( persistentProperty -> {
+                        if( !persistentProperty.isImmutable() )
+                        {
+                            String propertyName = persistentProperty.qualifiedName().name();
+                            String type = persistentProperty.valueType().primaryType().getName();
+
+                            Descriptor attrDescriptor = new DescriptorSupport();
+                            attrDescriptor.setField( "name", propertyName );
+                            attrDescriptor.setField( "descriptorType", "attribute" );
+
+                            if( persistentProperty.valueType() instanceof EnumType )
+                            {
+                                type = String.class.getName();
+
+                                // Try to add legal values
+                                try
+                                {
+                                    Set<String> legalValues = new LinkedHashSet<>();
+                                    Class<?> enumType = getClass().getClassLoader()
+                                        .loadClass( persistentProperty.valueType().primaryType().getName() );
+                                    for( Field field : enumType.getFields() )
+                                    {
+                                        legalValues.add( field.getName() );
+                                    }
+                                    attrDescriptor.setField( "legalValues", legalValues );
+                                }
+                                catch( ClassNotFoundException e )
+                                {
+                                    // Ignore
+                                    e.printStackTrace();
+                                }
+                            }
+                            attributes.add( new MBeanAttributeInfo( propertyName, type, propertyName, true, true, type.equals( "java.lang.Boolean" ), attrDescriptor ) );
+                            properties.put( propertyName, persistentProperty.accessor() );
+                        }
+                    } );
+
+                    List<MBeanOperationInfo> operations = new ArrayList<>();
+                    operations.add( new MBeanOperationInfo( "restart", "Restart service", new MBeanParameterInfo[ 0 ], "java.lang.String", MBeanOperationInfo.ACTION_INFO ) );
+
+                    String mbeanName = configurableService.identity().toString();
+                    MBeanInfo mbeanInfo = new MBeanInfo( serviceClass, mbeanName, attributes.toArray( new MBeanAttributeInfo[ attributes
+                        .size() ] ), null, operations.toArray( new MBeanOperationInfo[ operations.size() ] ), null );
+                    Object mbean = new ConfigurableService( configurableService, mbeanInfo, mbeanName, properties );
+                    ObjectName configurableServiceName;
+                    ObjectName serviceName = PolygeneMBeans.findServiceName( server, application.name(), mbeanName );
+                    if( serviceName != null )
+                    {
+                        configurableServiceName = new ObjectName( serviceName.toString() + ",name=Configuration" );
+                    }
+                    else
+                    {
+                        configurableServiceName = new ObjectName( "Configuration:name=" + mbeanName );
+                    }
+
+                    server.registerMBean( mbean, configurableServiceName );
+                    configurationNames.add( configurableServiceName );
+                }
+            }
+        }
+
+        @Override
+        public void unexportConfigurableServices()
+            throws Exception
+        {
+            for( ObjectName configurableServiceName : configurationNames )
+            {
+                server.unregisterMBean( configurableServiceName );
+            }
+        }
+
+        abstract class EditableConfiguration
+            implements DynamicMBean
+        {
+            MBeanInfo info;
+            Identity identity;
+            Map<String, AccessibleObject> propertyNames;
+
+            EditableConfiguration( MBeanInfo info, String identity, Map<String, AccessibleObject> propertyNames )
+            {
+                this.info = info;
+                this.identity = new StringIdentity(identity);
+                this.propertyNames = propertyNames;
+            }
+
+            @Override
+            public Object getAttribute( String name )
+                throws AttributeNotFoundException, MBeanException, ReflectionException
+            {
+                UnitOfWork uow = uowf.newUnitOfWork();
+                try
+                {
+                    EntityComposite configuration = uow.get( EntityComposite.class, identity );
+                    AssociationStateHolder state = spi.stateOf( configuration );
+                    AccessibleObject accessor = propertyNames.get( name );
+                    Property<Object> property = state.propertyFor( accessor );
+                    Object object = property.get();
+                    if( object instanceof Enum )
+                    {
+                        object = object.toString();
+                    }
+                    return object;
+                }
+                catch( Exception ex )
+                {
+                    throw new ReflectionException( ex, "Could not get attribute " + name );
+                }
+                finally
+                {
+                    uow.discard();
+                }
+            }
+
+            @Override
+            public void setAttribute( Attribute attribute )
+                throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException
+            {
+                UnitOfWork uow = uowf.newUnitOfWork();
+                try
+                {
+                    EntityComposite configuration = uow.get( EntityComposite.class, identity );
+                    AssociationStateHolder state = spi.stateOf( configuration );
+                    AccessibleObject accessor = propertyNames.get( attribute.getName() );
+                    Property<Object> property = state.propertyFor( accessor );
+                    PropertyDescriptor propertyDescriptor = spi.propertyDescriptorFor( property );
+                    if( EnumType.isEnum( propertyDescriptor.type() ) )
+                    {
+                        //noinspection unchecked
+                        property.set( Enum.valueOf( (Class<Enum>) propertyDescriptor.type(),
+                                                    attribute.getValue().toString() ) );
+                    }
+                    else
+                    {
+                        property.set( attribute.getValue() );
+                    }
+
+                    try
+                    {
+                        uow.complete();
+                    }
+                    catch( UnitOfWorkCompletionException e )
+                    {
+                        throw new ReflectionException( e );
+                    }
+                }
+                finally
+                {
+                    uow.discard();
+                }
+            }
+
+            @Override
+            public AttributeList getAttributes( String[] names )
+            {
+                AttributeList list = new AttributeList();
+                for( String name : names )
+                {
+                    try
+                    {
+                        Object value = getAttribute( name );
+                        list.add( new Attribute( name, value ) );
+                    }
+                    catch( AttributeNotFoundException | MBeanException | ReflectionException e )
+                    {
+                        e.printStackTrace();
+                    }
+                }
+
+                return list;
+            }
+
+            @Override
+            public AttributeList setAttributes( AttributeList attributeList )
+            {
+                AttributeList list = new AttributeList();
+                for( int i = 0; i < list.size(); i++ )
+                {
+                    Attribute attribute = (Attribute) list.get( i );
+
+                    try
+                    {
+                        setAttribute( attribute );
+                        list.add( attribute );
+                    }
+                    catch( AttributeNotFoundException | InvalidAttributeValueException | ReflectionException | MBeanException e )
+                    {
+                        e.printStackTrace();
+                    }
+                }
+
+                return list;
+            }
+
+            @Override
+            public MBeanInfo getMBeanInfo()
+            {
+                return info;
+            }
+        }
+
+        class ConfigurableService
+            extends EditableConfiguration
+        {
+            private ServiceReference<?> serviceRef;
+
+            ConfigurableService( ServiceReference<?> serviceReference,
+                                 MBeanInfo info,
+                                 String identity,
+                                 Map<String, AccessibleObject> propertyNames
+            )
+            {
+                super( info, identity, propertyNames );
+                this.serviceRef = serviceReference;
+            }
+
+            @Override
+            public Object invoke( String s, Object[] objects, String[] strings )
+                throws MBeanException, ReflectionException
+            {
+                if( s.equals( "restart" ) )
+                {
+                    try
+                    {
+                        // Refresh and restart
+                        if( serviceRef.isActive() )
+                        {
+                            // Refresh configuration
+                            CompositeInstance compositeInstance = PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF
+                                .apply( (Composite) serviceRef.get() );
+                            compositeInstance.newProxy( Configuration.class ).refresh();
+
+                            ( (Activation) serviceRef ).passivate();
+                            ( (Activation) serviceRef ).activate();
+                        }
+
+                        return "Service restarted";
+                    }
+                    catch( Exception e )
+                    {
+                        return "Could not restart service:" + e.getMessage();
+                    }
+                }
+
+                return "Unknown operation";
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/JMXAssembler.java b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/JMXAssembler.java
new file mode 100644
index 0000000..616c68e
--- /dev/null
+++ b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/JMXAssembler.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.jmx;
+
+import javax.management.MBeanServer;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+/**
+ * Register JMX helpers in a module.
+ */
+public class JMXAssembler
+    implements Assembler
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.importedServices( MBeanServer.class ).importedBy( MBeanServerImporter.class );
+        module.services( ApplicationManagerService.class ).instantiateOnStartup();
+        module.services( ConfigurationManagerService.class ).instantiateOnStartup();
+
+    }
+}
diff --git a/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/JMXConnectorConfiguration.java b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/JMXConnectorConfiguration.java
new file mode 100644
index 0000000..c48a221
--- /dev/null
+++ b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/JMXConnectorConfiguration.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.jmx;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.configuration.Enabled;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Configuration for JMXConnector. Username+password is optional.
+ */
+public interface JMXConnectorConfiguration
+        extends Enabled
+{
+    // Set this to 1099 as default in assembly
+    @UseDefaults
+    Property<Integer> port();
+
+    @Optional
+    Property<String> username();
+
+    @Optional
+    Property<String> password();
+}
diff --git a/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/JMXConnectorService.java b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/JMXConnectorService.java
new file mode 100644
index 0000000..4d85d82
--- /dev/null
+++ b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/JMXConnectorService.java
@@ -0,0 +1,195 @@
+/*
+ *  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.polygene.library.jmx;
+
+import java.net.InetAddress;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import javax.management.MBeanServer;
+import javax.management.remote.*;
+import javax.security.auth.Subject;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This service starts a JMX RMI connector.
+ * <p>
+ * It also creates an RMI-registry
+ * to register the connector. The service is configured by changing the
+ * settings in the JMXConnectorConfiguration.
+ * </p>
+ * <p>
+ * Authentication is done with an optional username+password in the configuration.
+ * </p>
+ */
+@Mixins(JMXConnectorService.JmxConnectorMixin.class)
+@Activators( JMXConnectorService.Activator.class )
+public interface JMXConnectorService
+{
+
+    void startJMXConnector()
+            throws Exception;
+
+    void stopJMXConnector()
+            throws Exception;
+
+    class Activator
+            extends ActivatorAdapter<ServiceReference<JMXConnectorService>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<JMXConnectorService> activated )
+                throws Exception
+        {
+            activated.get().startJMXConnector();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<JMXConnectorService> passivating )
+                throws Exception
+        {
+            passivating.get().stopJMXConnector();
+        }
+
+    }
+
+    abstract class JmxConnectorMixin
+            implements JMXConnectorService
+    {
+        final Logger logger = LoggerFactory.getLogger( JMXConnectorService.class.getName() );
+
+        @This
+        Configuration<JMXConnectorConfiguration> config;
+
+        @Service
+        MBeanServer server;
+
+        Registry registry;
+        JMXConnectorServer connector;
+
+        @Override
+        public void startJMXConnector() throws Exception
+        {
+            if (config.get().enabled().get())
+            {
+                // see java.rmi.server.ObjID
+                System.setProperty( "java.rmi.server.randomIDs", "true" );
+
+                int jmxAgentPort = config.get().port().get();
+
+                registry = LocateRegistry.createRegistry( jmxAgentPort );
+
+                String hostName = InetAddress.getLocalHost().getHostName();
+                JMXServiceURL url = new JMXServiceURL(
+                        "service:jmx:rmi://" + hostName + ":" + jmxAgentPort
+                                + "/jndi/rmi://" + hostName + ":" + jmxAgentPort + "/jmxrmi" );
+                Map env = new HashMap();
+
+                if(config.get().username().get() != null)
+                    env.put( JMXConnectorServer.AUTHENTICATOR, new ConfigurationJmxAuthenticator() );
+
+                try
+                {
+                    connector = JMXConnectorServerFactory.newJMXConnectorServer( url, env, server );
+                    connector.start();
+                } catch (Exception e)
+                {
+                    logger.error( "Could not start JMX connector", e );
+                }
+            }
+        }
+
+        @Override
+        public void stopJMXConnector() throws Exception
+        {
+            // Stop connector
+            if (connector != null)
+            {
+                connector.stop();
+                connector = null;
+            }
+
+            // Remove registry
+            if (registry != null)
+            {
+                UnicastRemoteObject.unexportObject( registry, true );
+                registry = null;
+            }
+        }
+
+        class ConfigurationJmxAuthenticator implements JMXAuthenticator
+        {
+
+            @Override
+            public Subject authenticate( Object credentials )
+            {
+
+                Subject subject = null;
+
+                if (!(credentials instanceof String[]))
+                {
+                    // Special case for null so we get a more informative message
+                    if (credentials == null)
+                    {
+                        throw new SecurityException( "Credentials required" );
+                    }
+                    throw new SecurityException( "Credentials should be String[]" );
+                }
+
+                final String[] aCredentials = (String[]) credentials;
+                if (aCredentials.length != 2)
+                {
+                    throw new SecurityException( "Credentials should have 2 elements" );
+                }
+
+                String username = aCredentials[0];
+                String password = aCredentials[1];
+
+                String configUsername = config.get().username().get();
+
+                if (!(configUsername == null || (configUsername.equals( username ) && !password.equals( config.get().password().get() ))))
+                {
+                    throw new SecurityException( "User/password combination not valid." );
+                }
+
+
+                subject = new Subject( true,
+                        Collections.singleton( new JMXPrincipal( username ) ),
+                        Collections.EMPTY_SET,
+                        Collections.EMPTY_SET );
+
+                return subject;
+            }
+        }
+    }
+}
diff --git a/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/MBeanServerImporter.java b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/MBeanServerImporter.java
new file mode 100644
index 0000000..e038375
--- /dev/null
+++ b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/MBeanServerImporter.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.library.jmx;
+
+import java.lang.management.ManagementFactory;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.ServiceImporterException;
+
+/**
+ * Importer for the platform MBeanServer of the JVM.
+ */
+public class MBeanServerImporter
+    implements ServiceImporter
+{
+    @Override
+    public Object importService( ImportedServiceDescriptor serviceDescriptor )
+        throws ServiceImporterException
+    {
+        return ManagementFactory.getPlatformMBeanServer();
+    }
+
+    @Override
+    public boolean isAvailable( Object instance )
+    {
+        return true;
+    }
+}
diff --git a/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/MBeanTracker.java b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/MBeanTracker.java
new file mode 100644
index 0000000..43ffe03
--- /dev/null
+++ b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/MBeanTracker.java
@@ -0,0 +1,213 @@
+/*
+ *  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.polygene.library.jmx;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.management.*;
+import org.slf4j.LoggerFactory;
+
+/**
+ * TODO
+ */
+public class MBeanTracker
+{
+    private boolean started = false;
+    private ObjectName pattern;
+    private MBeanServer server;
+    private List<TrackerCallback> callbacks = new ArrayList<>();
+    private List<ObjectName> tracked = Collections.synchronizedList( new ArrayList<ObjectName>() );
+    private RegistrationListener registrationListener;
+
+    public MBeanTracker(ObjectName pattern, MBeanServer server)
+    {
+       this.pattern = pattern;
+       this.server = server;
+    }
+
+    public MBeanTracker registerCallback(TrackerCallback callback)
+    {
+       List<TrackerCallback> newList = new ArrayList<>( callbacks );
+       newList.add(callback);
+       callbacks = newList;
+       return this;
+    }
+
+    public MBeanTracker unregisterCallback(TrackerCallback callback)
+    {
+       List<TrackerCallback> newList = new ArrayList<>( callbacks );
+       newList.remove(callback);
+       callbacks = newList;
+       return this;
+    }
+
+    public Iterable<ObjectName> getTracked()
+    {
+       return tracked;
+    }
+
+    public void start()
+    {
+       if (!started)
+       {
+          try
+          {
+             registrationListener = new RegistrationListener();
+             server.addNotificationListener(new ObjectName("JMImplementation:type=MBeanServerDelegate"), registrationListener, null, null);
+
+             for (ObjectName objectName : server.queryNames(pattern, null))
+             {
+                for (TrackerCallback callback : callbacks)
+                {
+                   try
+                   {
+                      tracked.add(objectName);
+                      callback.addedMBean(objectName, server);
+                   } catch (Throwable throwable)
+                   {
+                      LoggerFactory.getLogger( MBeanTracker.class ).error("Tracker callback threw exception", throwable);
+                   }
+                }
+             }
+
+             started = true;
+          } catch (Exception e)
+          {
+             // Could not start
+          }
+       }
+    }
+
+    public void stop()
+    {
+       if (started)
+       {
+          try
+          {
+             server.removeNotificationListener(new ObjectName("JMImplementation:type=MBeanServerDelegate"), registrationListener);
+
+             for (ObjectName objectName : server.queryNames(pattern, null))
+             {
+                for (TrackerCallback callback : callbacks)
+                {
+                   try
+                   {
+                      callback.removedMBean(objectName, server);
+                      tracked.remove(objectName);
+                   } catch (Throwable throwable)
+                   {
+                      LoggerFactory.getLogger(MBeanTracker.class).error("Tracker callback threw exception", throwable);
+                   }
+                }
+             }
+
+             started = false;
+          } catch (Exception e)
+          {
+             // Could not start
+          }
+       }
+    }
+
+    /**
+     * Callback that is used to notify when MBeans matching the given pattern becomes
+     * added or removed.
+     */
+    public interface TrackerCallback
+    {
+       void addedMBean(ObjectName newMBean, MBeanServer server)
+          throws Throwable;
+
+       void removedMBean(ObjectName removedMBean, MBeanServer server)
+          throws Throwable;
+    }
+
+    /**
+     * Registers the given NotificationListener+NotificationFilter on tracked MBeans.
+     */
+    public static class NotificationTracker
+        implements TrackerCallback
+    {
+        private NotificationListener listener;
+        private NotificationFilter filter;
+
+        public NotificationTracker( NotificationListener listener, NotificationFilter filter )
+        {
+            this.listener = listener;
+            this.filter = filter;
+        }
+
+        @Override
+        public void addedMBean( ObjectName newMBean, MBeanServer server ) throws Throwable
+        {
+            server.addNotificationListener( newMBean, listener, filter,  null);
+        }
+
+        @Override
+        public void removedMBean( ObjectName removedMBean, MBeanServer server ) throws Throwable
+        {
+            server.removeNotificationListener( removedMBean, listener );
+        }
+    }
+
+    private class RegistrationListener
+       implements NotificationListener
+    {
+       @Override
+       public void handleNotification(Notification notification, Object o)
+       {
+          if (notification instanceof MBeanServerNotification )
+          {
+             MBeanServerNotification serverNotification = (MBeanServerNotification) notification;
+             if (pattern.apply(serverNotification.getMBeanName()))
+             {
+                if (serverNotification.getType().equals(MBeanServerNotification.REGISTRATION_NOTIFICATION))
+                {
+                   for (TrackerCallback callback : callbacks)
+                   {
+                      try
+                      {
+                         tracked.add(serverNotification.getMBeanName());
+                         callback.addedMBean(serverNotification.getMBeanName(), server);
+                      } catch (Throwable throwable)
+                      {
+                         LoggerFactory.getLogger(MBeanTracker.class).error("Tracker callback threw exception", throwable);
+                      }
+                   }
+                } else if (serverNotification.getType().equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION))
+                {
+                   for (TrackerCallback callback : callbacks)
+                   {
+                      try
+                      {
+                         callback.removedMBean(serverNotification.getMBeanName(), server);
+                         tracked.remove(serverNotification.getMBeanName());
+                      } catch (Throwable throwable)
+                      {
+                         LoggerFactory.getLogger(MBeanTracker.class).error("Tracker callback threw exception", throwable);
+                      }
+                   }
+                }
+             }
+          }
+       }
+    }
+}
diff --git a/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/ModelMBeanBuilder.java b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/ModelMBeanBuilder.java
new file mode 100644
index 0000000..fbdcef0
--- /dev/null
+++ b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/ModelMBeanBuilder.java
@@ -0,0 +1,135 @@
+/*
+ *  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.polygene.library.jmx;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.management.Descriptor;
+import javax.management.MBeanException;
+import javax.management.MBeanParameterInfo;
+import javax.management.ObjectName;
+import javax.management.modelmbean.*;
+
+/**
+ * Helper builder for ModelMBeans
+ */
+public class ModelMBeanBuilder
+{
+    List<ModelMBeanAttributeInfo> attributes = new ArrayList<>();
+    List<ModelMBeanConstructorInfo> constructors = new ArrayList<>();
+    List<ModelMBeanOperationInfo> operations = new ArrayList<>();
+    List<ModelMBeanNotificationInfo> notifications = new ArrayList<>();
+
+    ObjectName objectName;
+    String displayName;
+    private final String className;
+
+    public ModelMBeanBuilder( ObjectName objectName, String displayName, String className )
+    {
+        this.objectName = objectName;
+        this.displayName = displayName;
+        this.className = className;
+    }
+
+    public ModelMBeanBuilder attribute( String name, String displayName, String type, String description, String getMethod, String setMethod )
+    {
+        Descriptor stateDesc = new DescriptorSupport();
+        stateDesc.setField( "name", name );
+        stateDesc.setField( "descriptorType", "attribute" );
+        stateDesc.setField( "displayName", displayName );
+        if (getMethod != null)
+        {
+            stateDesc.setField( "getMethod", getMethod );
+
+            operation( getMethod, description, type, ModelMBeanOperationInfo.INFO );
+        }
+
+        if (setMethod != null)
+        {
+            stateDesc.setField( "setMethod", setMethod );
+            operation( setMethod, description, type, ModelMBeanOperationInfo.INFO, new MBeanParameterInfo("Value", type, description) );
+        }
+
+        ModelMBeanAttributeInfo attributeInfo = new ModelMBeanAttributeInfo(
+                name,
+                type,
+                description,
+                getMethod != null,
+                setMethod != null,
+                getMethod != null && getMethod.startsWith( "is" ),
+                stateDesc );
+        attributes.add( attributeInfo );
+
+        return this;
+    }
+
+    public ModelMBeanAttributeInfo getAttribute(String name)
+    {
+        for (ModelMBeanAttributeInfo attribute : attributes)
+        {
+            if (attribute.getName().equals(name))
+                return attribute;
+        }
+
+        return null;
+    }
+
+    public ModelMBeanBuilder operation( String name, String description, String returnType, int impact, MBeanParameterInfo... parameters)
+    {
+        Descriptor stateDesc = new DescriptorSupport();
+        stateDesc.setField( "name", name );
+        stateDesc.setField( "descriptorType", "operation" );
+        stateDesc.setField( "class", className );
+        stateDesc.setField( "role", "operation" );
+        stateDesc.setField( "targetType", "objectReference" );
+
+        ModelMBeanOperationInfo operationInfo = new ModelMBeanOperationInfo(
+                name,
+                description,
+                parameters,
+                returnType,
+                impact,
+                stateDesc);
+        operations.add( operationInfo );
+
+        return this;
+    }
+
+    public RequiredModelMBean newModelMBean() throws MBeanException
+    {
+        Descriptor mmbDesc = new DescriptorSupport();
+        mmbDesc.setField( "name", objectName.toString() );
+        mmbDesc.setField( "descriptorType", "mbean" );
+        mmbDesc.setField( "displayName", displayName );
+
+        ModelMBeanInfo modelMBeanInfo = new ModelMBeanInfoSupport(
+                className,
+                displayName,
+                attributes.toArray( new ModelMBeanAttributeInfo[attributes.size()]),
+                constructors.toArray( new ModelMBeanConstructorInfo[constructors.size()]),
+                operations.toArray( new ModelMBeanOperationInfo[operations.size()]),
+                notifications.toArray( new ModelMBeanNotificationInfo[notifications.size()]) );
+
+        modelMBeanInfo.setMBeanDescriptor( mmbDesc );
+
+        return new RequiredModelMBean(modelMBeanInfo);
+    }
+}
diff --git a/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/PolygeneMBeans.java b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/PolygeneMBeans.java
new file mode 100644
index 0000000..d7d5bd6
--- /dev/null
+++ b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/PolygeneMBeans.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.jmx;
+
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+/**
+ * Helper for working with Polygene MBeans.
+ */
+public class PolygeneMBeans
+{
+    public static ObjectName findServiceName( MBeanServer server, String applicationName, String serviceId )
+        throws MalformedObjectNameException
+    {
+        ObjectName objectName = new ObjectName( "Polygene:application=" + applicationName + ",*,service=" + serviceId );
+        return server.queryNames( objectName, null ).stream()
+                     .filter( item -> item.getKeyPropertyList().size() == 5 )
+                     .findFirst().orElse( null );
+    }
+}
diff --git a/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/package.html b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/package.html
new file mode 100644
index 0000000..8f003d7
--- /dev/null
+++ b/libraries/jmx/src/main/java/org/apache/polygene/library/jmx/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>JMX Library.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/jmx/src/main/java/org/qi4j/library/jmx/ApplicationManagerService.java b/libraries/jmx/src/main/java/org/qi4j/library/jmx/ApplicationManagerService.java
deleted file mode 100644
index 1c31255..0000000
--- a/libraries/jmx/src/main/java/org/qi4j/library/jmx/ApplicationManagerService.java
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.jmx;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Stack;
-import javax.management.MBeanOperationInfo;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-import javax.management.modelmbean.ModelMBeanOperationInfo;
-import javax.management.modelmbean.RequiredModelMBean;
-import org.qi4j.api.activation.Activation;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.composite.ModelDescriptor;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Layer;
-import org.qi4j.api.structure.LayerDescriptor;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.structure.ModuleDescriptor;
-import org.qi4j.functional.HierarchicalVisitorAdapter;
-
-import static org.qi4j.api.service.qualifier.ServiceQualifier.withId;
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Expose the Zest app as a "tree" of MBeans.
- *
- * Other services should reuse the object names and create
- * nodes under the ones created here. For example:
- * <pre>
- * Zest:application=MyApp,layer=Application,module=MyModule,class=Service,service=MyService
- * </pre>
- * is exported by this service, so another exporter showing some aspect related to this service should
- * use this as base for the ObjectName, and add their own properties. Example:
- * <pre>
- * Zest:application=MyApp,layer=Application,module=MyModule,class=Service,service=MyService,name=Configuration
- * </pre>
- * Use the following snippet to find the ObjectName of a service with a given identity:
- * <pre>
- * ObjectName serviceName = Qi4jMBeans.findService(mbeanServer, applicationName, serviceId);
- * </pre>
- */
-@Mixins( ApplicationManagerService.Mixin.class )
-@Activators( ApplicationManagerService.Activator.class )
-public interface ApplicationManagerService
-    extends ServiceComposite
-{
-
-    void exportApplicationStructure()
-        throws Exception;
-
-    void unexportApplicationStructure()
-        throws Exception;
-
-    class Activator
-        extends ActivatorAdapter<ServiceReference<ApplicationManagerService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<ApplicationManagerService> activated )
-            throws Exception
-        {
-            activated.get().exportApplicationStructure();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<ApplicationManagerService> passivating )
-            throws Exception
-        {
-            passivating.get().unexportApplicationStructure();
-        }
-    }
-
-    abstract class Mixin
-        implements ApplicationManagerService
-    {
-        @Service
-        public MBeanServer server;
-
-        @Structure
-        public Application application;
-
-        private List<ObjectName> mbeans = new ArrayList<>();
-
-        @Override
-        public void exportApplicationStructure()
-            throws Exception
-        {
-            application.descriptor().accept( new HierarchicalVisitorAdapter<Object, Object, Exception>()
-            {
-                Layer layer;
-                Module module;
-                Stack<ObjectName> names = new Stack<>();
-
-                @Override
-                public boolean visitEnter( Object visited )
-                    throws Exception
-                {
-                    if( visited instanceof LayerDescriptor )
-                    {
-                        LayerDescriptor layerDescriptor = (LayerDescriptor) visited;
-                        layer = application.findLayer( layerDescriptor.name() );
-
-                        LayerBean layerBean = new LayerBean( layer, layerDescriptor );
-                        ObjectName objectName = new ObjectName( "Zest:application=" + application.name() + ",layer=" + layer
-                            .name() );
-                        names.push( objectName );
-
-                        RequiredModelMBean mbean = new ModelMBeanBuilder( objectName, layerDescriptor.name(), LayerBean.class
-                            .getName() ).
-                            attribute( "uses", "Layer usages", String.class.getName(), "Other layers that this layer uses", "getUses", null )
-                            .operation( "restart", "Restart layer", String.class.getName(), MBeanOperationInfo.ACTION_INFO )
-                            .newModelMBean();
-
-                        mbean.setManagedResource( layerBean, "ObjectReference" );
-                        server.registerMBean( mbean, objectName );
-                        mbeans.add( objectName );
-                    }
-                    else if( visited instanceof ModuleDescriptor )
-                    {
-                        ModuleDescriptor moduleDescriptor = (ModuleDescriptor) visited;
-                        module = application.findModule( layer.name(), moduleDescriptor.name() );
-                        ObjectName objectName = new ObjectName( names.peek()
-                                                                    .toString() + ",module=" + moduleDescriptor.name() );
-                        names.push( objectName );
-                        RequiredModelMBean mbean = new ModelMBeanBuilder( objectName, moduleDescriptor.name(), moduleDescriptor
-                            .getClass()
-                            .getName() ).
-                            attribute( "name", "Module name", String.class.getName(), "Name of module", "name", null ).
-                            newModelMBean();
-
-                        mbean.setManagedResource( moduleDescriptor, "ObjectReference" );
-
-                        server.registerMBean( mbean, objectName );
-                        mbeans.add( objectName );
-                    }
-                    else if( visited instanceof ServiceDescriptor )
-                    {
-                        ServiceDescriptor serviceDescriptor = (ServiceDescriptor) visited;
-                        ObjectName objectName = new ObjectName( names.peek()
-                                                                    .toString() + ",class=Service,service=" + serviceDescriptor
-                                                                    .identity() );
-                        RequiredModelMBean mbean = new ModelMBeanBuilder( objectName, serviceDescriptor.identity(), ServiceBean.class
-                            .getName() ).
-                            attribute( "Id", "Service id", String.class.getName(), "Id of service", "getId", null ).
-                            attribute( "Visibility", "Service visibility", String.class.getName(), "Visibility of service", "getVisibility", null )
-                            .
-                                attribute( "Type", "Service type", String.class.getName(), "Type of service", "getType", null )
-                            .
-                                attribute( "Active", "Service is active", Boolean.class.getName(), "Service is active", "isActive", null )
-                            .
-                                attribute( "Available", "Service is available", Boolean.class.getName(), "Service is available", "isAvailable", null )
-                            .
-                                operation( "restart", "Restart service", String.class.getName(), ModelMBeanOperationInfo.ACTION_INFO )
-                            .
-                                newModelMBean();
-
-                        mbean.setManagedResource( new ServiceBean( serviceDescriptor, module ), "ObjectReference" );
-
-                        server.registerMBean( mbean, objectName );
-                        mbeans.add( objectName );
-                    }
-                    else if( visited instanceof ImportedServiceDescriptor )
-                    {
-                        ImportedServiceDescriptor importedServiceDescriptor = (ImportedServiceDescriptor) visited;
-                        ObjectName objectName = new ObjectName( names.peek()
-                                                                    .toString() + ",class=Imported service,importedservice=" + importedServiceDescriptor
-                                                                    .identity() );
-                        RequiredModelMBean mbean = new ModelMBeanBuilder( objectName, importedServiceDescriptor.identity(), ImportedServiceBean.class
-                            .getName() ).
-                            attribute( "Id", "Service id", String.class.getName(), "Id of service", "getId", null ).
-                            attribute( "Visibility", "Service visibility", String.class.getName(), "Visibility of service", "getVisibility", null )
-                            .
-                                attribute( "Type", "Service type", String.class.getName(), "Type of imported service", "getType", null )
-                            .
-                                newModelMBean();
-
-                        mbean.setManagedResource( new ImportedServiceBean( importedServiceDescriptor ), "ObjectReference" );
-
-                        server.registerMBean( mbean, objectName );
-                        mbeans.add( objectName );
-                    }
-
-                    return !( visited instanceof ModelDescriptor );
-                }
-
-                @Override
-                public boolean visitLeave( Object visited )
-                    throws Exception
-                {
-                    if( visited instanceof ModuleDescriptor || visited instanceof LayerDescriptor )
-                    {
-                        names.pop();
-                    }
-
-                    return true;
-                }
-            } );
-        }
-
-        @Override
-        public void unexportApplicationStructure()
-            throws Exception
-        {
-            for( ObjectName mbean : mbeans )
-            {
-                server.unregisterMBean( mbean );
-            }
-        }
-    }
-
-    class LayerBean
-    {
-        private final Layer layer;
-        private final LayerDescriptor layerDescriptor;
-        private String uses;
-
-        public LayerBean( Layer layer, LayerDescriptor layerDescriptor )
-        {
-            this.layer = layer;
-            this.layerDescriptor = layerDescriptor;
-
-            uses = "Uses: ";
-            for( LayerDescriptor usedLayer : layerDescriptor.usedLayers().layers() )
-            {
-                uses += usedLayer.name() + " ";
-            }
-        }
-
-        public String getUses()
-        {
-            return uses;
-        }
-
-        public String restart()
-            throws Exception
-        {
-            try
-            {
-                layer.passivate();
-                layer.activate();
-                return "Restarted layer";
-            }
-            catch( Exception e )
-            {
-                return "Could not restart layer:" + e.getMessage();
-            }
-        }
-    }
-
-    class ServiceBean
-    {
-        private final ServiceDescriptor serviceDescriptor;
-        private final Module module;
-
-        public ServiceBean( ServiceDescriptor serviceDescriptor, Module module )
-        {
-            this.serviceDescriptor = serviceDescriptor;
-            this.module = module;
-        }
-
-        public String getId()
-        {
-            return serviceDescriptor.identity();
-        }
-
-        public String getVisibility()
-        {
-            return serviceDescriptor.visibility().name();
-        }
-
-        public String getType()
-        {
-            Class<?> first = first( serviceDescriptor.types() );
-            if( first == null )
-            {
-                return null;
-            }
-            return first.getName();
-        }
-
-        public boolean isActive()
-        {
-            Class<?> mainType = first( serviceDescriptor.types() );
-            ServiceReference<?> first = first( filter( withId( serviceDescriptor.identity() ),
-                                                       module.findServices( mainType ) )
-            );
-            return first != null && first.isActive();
-        }
-
-        public boolean isAvailable()
-        {
-            Class<?> mainType = first( serviceDescriptor.types() );
-            ServiceReference<?> first = first( filter( withId( serviceDescriptor.identity() ),
-                                                       module.findServices( mainType ) )
-            );
-            return first != null && first.isAvailable();
-        }
-
-        public String restart()
-        {
-            Iterable<?> services = module.findServices( first( serviceDescriptor.types() ) );
-            ServiceReference<?> serviceRef = (ServiceReference) first( filter( withId( serviceDescriptor.identity() ),
-                                                                               services )
-            );
-            if( serviceRef != null )
-            {
-                try
-                {
-                    ( (Activation) serviceRef ).passivate();
-                    ( (Activation) serviceRef ).activate();
-                    return "Restarted service";
-                }
-                catch( Exception e )
-                {
-                    return "Could not restart service:" + e.getMessage();
-                }
-            }
-            else
-            {
-                return "Could not find service";
-            }
-        }
-    }
-
-    class ImportedServiceBean
-    {
-        private final ImportedServiceDescriptor serviceDescriptor;
-
-        public ImportedServiceBean( ImportedServiceDescriptor serviceDescriptor )
-        {
-            this.serviceDescriptor = serviceDescriptor;
-        }
-
-        public String getId()
-        {
-            return serviceDescriptor.identity();
-        }
-
-        public String getVisibility()
-        {
-            return serviceDescriptor.visibility().name();
-        }
-
-        public String getType()
-        {
-            Class<?> mainType = first( serviceDescriptor.types() );
-            if( mainType == null )
-            {
-                return null;
-            }
-            return mainType.getName();
-        }
-    }
-}
diff --git a/libraries/jmx/src/main/java/org/qi4j/library/jmx/ConfigurationManagerService.java b/libraries/jmx/src/main/java/org/qi4j/library/jmx/ConfigurationManagerService.java
deleted file mode 100644
index a5194bb..0000000
--- a/libraries/jmx/src/main/java/org/qi4j/library/jmx/ConfigurationManagerService.java
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.jmx;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.management.Attribute;
-import javax.management.AttributeList;
-import javax.management.AttributeNotFoundException;
-import javax.management.Descriptor;
-import javax.management.DynamicMBean;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InvalidAttributeValueException;
-import javax.management.MBeanAttributeInfo;
-import javax.management.MBeanException;
-import javax.management.MBeanInfo;
-import javax.management.MBeanOperationInfo;
-import javax.management.MBeanParameterInfo;
-import javax.management.MBeanRegistrationException;
-import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.ObjectName;
-import javax.management.ReflectionException;
-import javax.management.modelmbean.DescriptorSupport;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.activation.Activation;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.type.EnumType;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.spi.Qi4jSPI;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Expose ConfigurationComposites through JMX.
- * Allow configurations to be edited, and the services to be restarted.
- */
-@Mixins( ConfigurationManagerService.Mixin.class )
-@Activators( ConfigurationManagerService.Activator.class )
-public interface ConfigurationManagerService
-    extends ServiceComposite
-{
-    void exportConfigurableServices()
-            throws Exception;
-
-    void unexportConfigurableServices()
-            throws Exception;
-
-    class Activator
-            extends ActivatorAdapter<ServiceReference<ConfigurationManagerService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<ConfigurationManagerService> activated )
-                throws Exception
-        {
-            activated.get().exportConfigurableServices();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<ConfigurationManagerService> passivating )
-                throws Exception
-        {
-            passivating.get().unexportConfigurableServices();
-        }
-
-    }
-
-    abstract class Mixin
-        implements ConfigurationManagerService
-    {
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        @Service
-        MBeanServer server;
-
-        @Structure
-        Application application;
-
-        @Structure
-        Qi4jSPI spi;
-
-        @Service
-        Iterable<ServiceReference<?>> configurableServices;
-
-        private List<ObjectName> configurationNames = new ArrayList<ObjectName>();
-
-        @Override
-        public void exportConfigurableServices()
-            throws NotCompliantMBeanException, MBeanRegistrationException, InstanceAlreadyExistsException, MalformedObjectNameException
-        {
-            for( ServiceReference<?> configurableService : configurableServices )
-            {
-                Object service = configurableService.get();
-
-                if( !( service instanceof Composite ) )
-                {
-                    continue; // Skip imported services
-                }
-
-                // Check if service has configuration
-                CompositeInstance compositeInstance = Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF.map( (Composite) service );
-                try
-                {
-                    Configuration config = compositeInstance.newProxy( Configuration.class );
-                }
-                catch( Exception e )
-                {
-                    // Service does not have configuration
-                    continue;
-                }
-
-                String serviceClass = first(compositeInstance.types()).getName();
-                String name = configurableService.identity();
-                ServiceDescriptor serviceDescriptor = spi.serviceDescriptorFor( configurableService );
-                Module module = spi.moduleOf( configurableService );
-                Class<Object> configurationClass = serviceDescriptor.configurationType();
-                if( configurationClass != null )
-                {
-                    EntityDescriptor descriptor = module.entityDescriptor( configurationClass.getName() );
-                    List<MBeanAttributeInfo> attributes = new ArrayList<MBeanAttributeInfo>();
-                    Map<String, AccessibleObject> properties = new HashMap<String, AccessibleObject>();
-                    for( PropertyDescriptor persistentProperty : descriptor.state().properties() )
-                    {
-                        if( !persistentProperty.isImmutable() )
-                        {
-                            String propertyName = persistentProperty.qualifiedName().name();
-                            String type = persistentProperty.valueType().mainType().getName();
-
-                            Descriptor attrDescriptor = new DescriptorSupport();
-                            attrDescriptor.setField( "name", propertyName );
-                            attrDescriptor.setField( "descriptorType", "attribute" );
-
-                            if( persistentProperty.valueType() instanceof EnumType )
-                            {
-                                type = String.class.getName();
-
-                                // Try to add legal values
-                                try
-                                {
-                                    Set<String> legalValues = new LinkedHashSet();
-                                    Class<?> enumType = getClass().getClassLoader()
-                                        .loadClass( persistentProperty.valueType().mainType().getName() );
-                                    for( Field field : enumType.getFields() )
-                                    {
-                                        legalValues.add( field.getName() );
-                                    }
-                                    attrDescriptor.setField( "legalValues", legalValues );
-                                }
-                                catch( ClassNotFoundException e )
-                                {
-                                    // Ignore
-                                    e.printStackTrace();
-                                }
-                            }
-                            attributes.add( new MBeanAttributeInfo( propertyName, type, propertyName, true, true, type.equals( "java.lang.Boolean" ), attrDescriptor ) );
-                            properties.put( propertyName, persistentProperty.accessor() );
-                        }
-                    }
-
-                    List<MBeanOperationInfo> operations = new ArrayList<MBeanOperationInfo>();
-                    operations.add( new MBeanOperationInfo( "restart", "Restart service", new MBeanParameterInfo[ 0 ], "java.lang.String", MBeanOperationInfo.ACTION_INFO ) );
-
-                    MBeanInfo mbeanInfo = new MBeanInfo( serviceClass, name, attributes.toArray( new MBeanAttributeInfo[ attributes
-                        .size() ] ), null, operations.toArray( new MBeanOperationInfo[ operations.size() ] ), null );
-                    Object mbean = new ConfigurableService( configurableService, mbeanInfo, name, properties );
-                    ObjectName configurableServiceName;
-                    ObjectName serviceName = Qi4jMBeans.findServiceName( server, application.name(), name );
-                    if( serviceName != null )
-                    {
-                        configurableServiceName = new ObjectName( serviceName.toString() + ",name=Configuration" );
-                    }
-                    else
-                    {
-                        configurableServiceName = new ObjectName( "Configuration:name=" + name );
-                    }
-
-                    server.registerMBean( mbean, configurableServiceName );
-                    configurationNames.add( configurableServiceName );
-                }
-            }
-        }
-
-        @Override
-        public void unexportConfigurableServices()
-            throws Exception
-        {
-            for( ObjectName configurableServiceName : configurationNames )
-            {
-                server.unregisterMBean( configurableServiceName );
-            }
-        }
-
-        abstract class EditableConfiguration
-            implements DynamicMBean
-        {
-            MBeanInfo info;
-            String identity;
-            Map<String, AccessibleObject> propertyNames;
-
-            EditableConfiguration( MBeanInfo info, String identity, Map<String, AccessibleObject> propertyNames )
-            {
-                this.info = info;
-                this.identity = identity;
-                this.propertyNames = propertyNames;
-            }
-
-            @Override
-            public Object getAttribute( String name )
-                throws AttributeNotFoundException, MBeanException, ReflectionException
-            {
-                UnitOfWork uow = uowf.newUnitOfWork();
-                try
-                {
-                    EntityComposite configuration = uow.get( EntityComposite.class, identity );
-                    AssociationStateHolder state = spi.stateOf( configuration );
-                    AccessibleObject accessor = propertyNames.get( name );
-                    Property<Object> property = state.propertyFor( accessor );
-                    Object object = property.get();
-                    if( object instanceof Enum )
-                    {
-                        object = object.toString();
-                    }
-                    return object;
-                }
-                catch( Exception ex )
-                {
-                    throw new ReflectionException( ex, "Could not get attribute " + name );
-                }
-                finally
-                {
-                    uow.discard();
-                }
-            }
-
-            @Override
-            public void setAttribute( Attribute attribute )
-                throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException
-            {
-                UnitOfWork uow = uowf.newUnitOfWork();
-                try
-                {
-                    EntityComposite configuration = uow.get( EntityComposite.class, identity );
-                    AssociationStateHolder state = spi.stateOf( (EntityComposite) configuration );
-                    AccessibleObject accessor = propertyNames.get( attribute.getName() );
-                    Property<Object> property = state.propertyFor( accessor );
-                    PropertyDescriptor propertyDescriptor = spi.propertyDescriptorFor( property );
-                    if( EnumType.isEnum( propertyDescriptor.type() ) )
-                    {
-                        property.set( Enum.valueOf( (Class<Enum>) propertyDescriptor.type(), attribute.getValue()
-                            .toString() ) );
-                    }
-                    else
-                    {
-                        property.set( attribute.getValue() );
-                    }
-
-                    try
-                    {
-                        uow.complete();
-                    }
-                    catch( UnitOfWorkCompletionException e )
-                    {
-                        throw new ReflectionException( e );
-                    }
-                }
-                finally
-                {
-                    uow.discard();
-                }
-            }
-
-            @Override
-            public AttributeList getAttributes( String[] names )
-            {
-                AttributeList list = new AttributeList();
-                for( String name : names )
-                {
-                    try
-                    {
-                        Object value = getAttribute( name );
-                        list.add( new Attribute( name, value ) );
-                    }
-                    catch( AttributeNotFoundException e )
-                    {
-                        e.printStackTrace();
-                    }
-                    catch( MBeanException e )
-                    {
-                        e.printStackTrace();
-                    }
-                    catch( ReflectionException e )
-                    {
-                        e.printStackTrace();
-                    }
-                }
-
-                return list;
-            }
-
-            @Override
-            public AttributeList setAttributes( AttributeList attributeList )
-            {
-                AttributeList list = new AttributeList();
-                for( int i = 0; i < list.size(); i++ )
-                {
-                    Attribute attribute = (Attribute) list.get( i );
-
-                    try
-                    {
-                        setAttribute( attribute );
-                        list.add( attribute );
-                    }
-                    catch( AttributeNotFoundException e )
-                    {
-                        e.printStackTrace();
-                    }
-                    catch( InvalidAttributeValueException e )
-                    {
-                        e.printStackTrace();
-                    }
-                    catch( MBeanException e )
-                    {
-                        e.printStackTrace();
-                    }
-                    catch( ReflectionException e )
-                    {
-                        e.printStackTrace();
-                    }
-                }
-
-                return list;
-            }
-
-            @Override
-            public MBeanInfo getMBeanInfo()
-            {
-                return info;
-            }
-        }
-
-        class ConfigurableService
-            extends EditableConfiguration
-        {
-            private ServiceReference<?> serviceRef;
-
-            ConfigurableService( ServiceReference<?> serviceReference,
-                                 MBeanInfo info,
-                                 String identity,
-                                 Map<String, AccessibleObject> propertyNames
-            )
-            {
-                super( info, identity, propertyNames );
-                this.serviceRef = serviceReference;
-            }
-
-            @Override
-            public Object invoke( String s, Object[] objects, String[] strings )
-                throws MBeanException, ReflectionException
-            {
-                if( s.equals( "restart" ) )
-                {
-                    try
-                    {
-                        // Refresh and restart
-                        if( serviceRef.isActive() )
-                        {
-                            // Refresh configuration
-                            CompositeInstance compositeInstance = Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF
-                                .map( (Composite) serviceRef.get() );
-                            compositeInstance.newProxy( Configuration.class ).refresh();
-
-                            ( (Activation) serviceRef ).passivate();
-                            ( (Activation) serviceRef ).activate();
-                        }
-
-                        return "Service restarted";
-                    }
-                    catch( Exception e )
-                    {
-                        return "Could not restart service:" + e.getMessage();
-                    }
-                }
-
-                return "Unknown operation";
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/libraries/jmx/src/main/java/org/qi4j/library/jmx/JMXAssembler.java b/libraries/jmx/src/main/java/org/qi4j/library/jmx/JMXAssembler.java
deleted file mode 100644
index 7fded91..0000000
--- a/libraries/jmx/src/main/java/org/qi4j/library/jmx/JMXAssembler.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.jmx;
-
-import javax.management.MBeanServer;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-/**
- * Register JMX helpers in a module.
- */
-public class JMXAssembler
-    implements Assembler
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.importedServices( MBeanServer.class ).importedBy( MBeanServerImporter.class );
-        module.services( ApplicationManagerService.class ).instantiateOnStartup();
-        module.services( ConfigurationManagerService.class ).instantiateOnStartup();
-
-    }
-}
diff --git a/libraries/jmx/src/main/java/org/qi4j/library/jmx/JMXConnectorConfiguration.java b/libraries/jmx/src/main/java/org/qi4j/library/jmx/JMXConnectorConfiguration.java
deleted file mode 100644
index 41383d3..0000000
--- a/libraries/jmx/src/main/java/org/qi4j/library/jmx/JMXConnectorConfiguration.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.jmx;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.configuration.Enabled;
-import org.qi4j.api.property.Property;
-
-/**
- * Configuration for JMXConnector. Username+password is optional.
- */
-public interface JMXConnectorConfiguration
-        extends ConfigurationComposite, Enabled
-{
-    // Set this to 1099 as default in assembly
-    @UseDefaults
-    Property<Integer> port();
-
-    @Optional
-    Property<String> username();
-
-    @Optional
-    Property<String> password();
-}
diff --git a/libraries/jmx/src/main/java/org/qi4j/library/jmx/JMXConnectorService.java b/libraries/jmx/src/main/java/org/qi4j/library/jmx/JMXConnectorService.java
deleted file mode 100644
index 0d41a4f..0000000
--- a/libraries/jmx/src/main/java/org/qi4j/library/jmx/JMXConnectorService.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.jmx;
-
-import java.net.InetAddress;
-import java.rmi.registry.LocateRegistry;
-import java.rmi.registry.Registry;
-import java.rmi.server.UnicastRemoteObject;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import javax.management.MBeanServer;
-import javax.management.remote.*;
-import javax.security.auth.Subject;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This service starts a JMX RMI connector.
- * <p>
- * It also creates an RMI-registry
- * to register the connector. The service is configured by changing the
- * settings in the JMXConnectorConfiguration.
- * </p>
- * <p>
- * Authentication is done with an optional username+password in the configuration.
- * </p>
- */
-@Mixins(JMXConnectorService.JmxConnectorMixin.class)
-@Activators( JMXConnectorService.Activator.class )
-public interface JMXConnectorService
-        extends ServiceComposite
-{
-
-    void startJMXConnector()
-            throws Exception;
-
-    void stopJMXConnector()
-            throws Exception;
-
-    static class Activator
-            extends ActivatorAdapter<ServiceReference<JMXConnectorService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<JMXConnectorService> activated )
-                throws Exception
-        {
-            activated.get().startJMXConnector();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<JMXConnectorService> passivating )
-                throws Exception
-        {
-            passivating.get().stopJMXConnector();
-        }
-
-    }
-
-    abstract class JmxConnectorMixin
-            implements JMXConnectorService
-    {
-        final Logger logger = LoggerFactory.getLogger( JMXConnectorService.class.getName() );
-
-        @This
-        Configuration<JMXConnectorConfiguration> config;
-
-        @Service
-        MBeanServer server;
-
-        Registry registry;
-        JMXConnectorServer connector;
-
-        @Override
-        public void startJMXConnector() throws Exception
-        {
-            if (config.get().enabled().get())
-            {
-                // see java.rmi.server.ObjID
-                System.setProperty( "java.rmi.server.randomIDs", "true" );
-
-                int jmxAgentPort = config.get().port().get();
-
-                registry = LocateRegistry.createRegistry( jmxAgentPort );
-
-                String hostName = InetAddress.getLocalHost().getHostName();
-                JMXServiceURL url = new JMXServiceURL(
-                        "service:jmx:rmi://" + hostName + ":" + jmxAgentPort
-                                + "/jndi/rmi://" + hostName + ":" + jmxAgentPort + "/jmxrmi" );
-                Map env = new HashMap();
-
-                if(config.get().username().get() != null)
-                    env.put( JMXConnectorServer.AUTHENTICATOR, new ConfigurationJmxAuthenticator() );
-
-                try
-                {
-                    connector = JMXConnectorServerFactory.newJMXConnectorServer( url, env, server );
-                    connector.start();
-                } catch (Exception e)
-                {
-                    logger.error( "Could not start JMX connector", e );
-                }
-            }
-        }
-
-        @Override
-        public void stopJMXConnector() throws Exception
-        {
-            // Stop connector
-            if (connector != null)
-            {
-                connector.stop();
-                connector = null;
-            }
-
-            // Remove registry
-            if (registry != null)
-            {
-                UnicastRemoteObject.unexportObject( registry, true );
-                registry = null;
-            }
-        }
-
-        class ConfigurationJmxAuthenticator implements JMXAuthenticator
-        {
-
-            @Override
-            public Subject authenticate( Object credentials )
-            {
-
-                Subject subject = null;
-
-                if (!(credentials instanceof String[]))
-                {
-                    // Special case for null so we get a more informative message
-                    if (credentials == null)
-                    {
-                        throw new SecurityException( "Credentials required" );
-                    }
-                    throw new SecurityException( "Credentials should be String[]" );
-                }
-
-                final String[] aCredentials = (String[]) credentials;
-                if (aCredentials.length != 2)
-                {
-                    throw new SecurityException( "Credentials should have 2 elements" );
-                }
-
-                String username = aCredentials[0];
-                String password = aCredentials[1];
-
-                String configUsername = config.get().username().get();
-
-                if (!(configUsername == null || (configUsername.equals( username ) && !password.equals( config.get().password().get() ))))
-                {
-                    throw new SecurityException( "User/password combination not valid." );
-                }
-
-
-                subject = new Subject( true,
-                        Collections.singleton( new JMXPrincipal( username ) ),
-                        Collections.EMPTY_SET,
-                        Collections.EMPTY_SET );
-
-                return subject;
-            }
-        }
-    }
-}
diff --git a/libraries/jmx/src/main/java/org/qi4j/library/jmx/MBeanServerImporter.java b/libraries/jmx/src/main/java/org/qi4j/library/jmx/MBeanServerImporter.java
deleted file mode 100644
index a4abf31..0000000
--- a/libraries/jmx/src/main/java/org/qi4j/library/jmx/MBeanServerImporter.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.jmx;
-
-import java.lang.management.ManagementFactory;
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.service.ServiceImporterException;
-
-/**
- * Importer for the platform MBeanServer of the JVM.
- */
-public class MBeanServerImporter
-    implements ServiceImporter
-{
-    @Override
-    public Object importService( ImportedServiceDescriptor serviceDescriptor )
-        throws ServiceImporterException
-    {
-        return ManagementFactory.getPlatformMBeanServer();
-    }
-
-    @Override
-    public boolean isAvailable( Object instance )
-    {
-        return true;
-    }
-}
diff --git a/libraries/jmx/src/main/java/org/qi4j/library/jmx/MBeanTracker.java b/libraries/jmx/src/main/java/org/qi4j/library/jmx/MBeanTracker.java
deleted file mode 100644
index 5fe667c..0000000
--- a/libraries/jmx/src/main/java/org/qi4j/library/jmx/MBeanTracker.java
+++ /dev/null
@@ -1,212 +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.qi4j.library.jmx;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import javax.management.*;
-import org.slf4j.LoggerFactory;
-
-/**
- * TODO
- */
-public class MBeanTracker
-{
-    private boolean started = false;
-    private ObjectName pattern;
-    private MBeanServer server;
-    private List<TrackerCallback> callbacks = new ArrayList<TrackerCallback>();
-    private List<ObjectName> tracked = Collections.synchronizedList( new ArrayList<ObjectName>() );
-    private RegistrationListener registrationListener;
-
-    public MBeanTracker(ObjectName pattern, MBeanServer server)
-    {
-       this.pattern = pattern;
-       this.server = server;
-    }
-
-    public MBeanTracker registerCallback(TrackerCallback callback)
-    {
-       List<TrackerCallback> newList = new ArrayList<TrackerCallback>(callbacks);
-       newList.add(callback);
-       callbacks = newList;
-       return this;
-    }
-
-    public MBeanTracker unregisterCallback(TrackerCallback callback)
-    {
-       List<TrackerCallback> newList = new ArrayList<TrackerCallback>(callbacks);
-       newList.remove(callback);
-       callbacks = newList;
-       return this;
-    }
-
-    public Iterable<ObjectName> getTracked()
-    {
-       return tracked;
-    }
-
-    public void start()
-    {
-       if (!started)
-       {
-          try
-          {
-             registrationListener = new RegistrationListener();
-             server.addNotificationListener(new ObjectName("JMImplementation:type=MBeanServerDelegate"), registrationListener, null, null);
-
-             for (ObjectName objectName : server.queryNames(pattern, null))
-             {
-                for (TrackerCallback callback : callbacks)
-                {
-                   try
-                   {
-                      tracked.add(objectName);
-                      callback.addedMBean(objectName, server);
-                   } catch (Throwable throwable)
-                   {
-                      LoggerFactory.getLogger( MBeanTracker.class ).error("Tracker callback threw exception", throwable);
-                   }
-                }
-             }
-
-             started = true;
-          } catch (Exception e)
-          {
-             // Could not start
-          }
-       }
-    }
-
-    public void stop()
-    {
-       if (started)
-       {
-          try
-          {
-             server.removeNotificationListener(new ObjectName("JMImplementation:type=MBeanServerDelegate"), registrationListener);
-
-             for (ObjectName objectName : server.queryNames(pattern, null))
-             {
-                for (TrackerCallback callback : callbacks)
-                {
-                   try
-                   {
-                      callback.removedMBean(objectName, server);
-                      tracked.remove(objectName);
-                   } catch (Throwable throwable)
-                   {
-                      LoggerFactory.getLogger(MBeanTracker.class).error("Tracker callback threw exception", throwable);
-                   }
-                }
-             }
-
-             started = false;
-          } catch (Exception e)
-          {
-             // Could not start
-          }
-       }
-    }
-
-    /**
-     * Callback that is used to notify when MBeans matching the given pattern becomes
-     * added or removed.
-     */
-    public interface TrackerCallback
-    {
-       void addedMBean(ObjectName newMBean, MBeanServer server)
-          throws Throwable;
-
-       void removedMBean(ObjectName removedMBean, MBeanServer server)
-          throws Throwable;
-    }
-
-    /**
-     * Registers the given NotificationListener+NotificationFilter on tracked MBeans.
-     */
-    public static class NotificationTracker
-        implements TrackerCallback
-    {
-        private NotificationListener listener;
-        private NotificationFilter filter;
-
-        public NotificationTracker( NotificationListener listener, NotificationFilter filter )
-        {
-            this.listener = listener;
-            this.filter = filter;
-        }
-
-        @Override
-        public void addedMBean( ObjectName newMBean, MBeanServer server ) throws Throwable
-        {
-            server.addNotificationListener( newMBean, listener, filter,  null);
-        }
-
-        @Override
-        public void removedMBean( ObjectName removedMBean, MBeanServer server ) throws Throwable
-        {
-            server.removeNotificationListener( removedMBean, listener );
-        }
-    }
-
-    private class RegistrationListener
-       implements NotificationListener
-    {
-       @Override
-       public void handleNotification(Notification notification, Object o)
-       {
-          if (notification instanceof MBeanServerNotification )
-          {
-             MBeanServerNotification serverNotification = (MBeanServerNotification) notification;
-             if (pattern.apply(serverNotification.getMBeanName()))
-             {
-                if (serverNotification.getType().equals(MBeanServerNotification.REGISTRATION_NOTIFICATION))
-                {
-                   for (TrackerCallback callback : callbacks)
-                   {
-                      try
-                      {
-                         tracked.add(serverNotification.getMBeanName());
-                         callback.addedMBean(serverNotification.getMBeanName(), server);
-                      } catch (Throwable throwable)
-                      {
-                         LoggerFactory.getLogger(MBeanTracker.class).error("Tracker callback threw exception", throwable);
-                      }
-                   }
-                } else if (serverNotification.getType().equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION))
-                {
-                   for (TrackerCallback callback : callbacks)
-                   {
-                      try
-                      {
-                         callback.removedMBean(serverNotification.getMBeanName(), server);
-                         tracked.remove(serverNotification.getMBeanName());
-                      } catch (Throwable throwable)
-                      {
-                         LoggerFactory.getLogger(MBeanTracker.class).error("Tracker callback threw exception", throwable);
-                      }
-                   }
-                }
-             }
-          }
-       }
-    }
-}
diff --git a/libraries/jmx/src/main/java/org/qi4j/library/jmx/ModelMBeanBuilder.java b/libraries/jmx/src/main/java/org/qi4j/library/jmx/ModelMBeanBuilder.java
deleted file mode 100644
index 0df89dc..0000000
--- a/libraries/jmx/src/main/java/org/qi4j/library/jmx/ModelMBeanBuilder.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.jmx;
-
-import java.util.ArrayList;
-import java.util.List;
-import javax.management.Descriptor;
-import javax.management.MBeanException;
-import javax.management.MBeanParameterInfo;
-import javax.management.ObjectName;
-import javax.management.modelmbean.*;
-
-/**
- * Helper builder for ModelMBeans
- */
-public class ModelMBeanBuilder
-{
-    List<ModelMBeanAttributeInfo> attributes = new ArrayList<ModelMBeanAttributeInfo>();
-    List<ModelMBeanConstructorInfo> constructors = new ArrayList<ModelMBeanConstructorInfo>();
-    List<ModelMBeanOperationInfo> operations = new ArrayList<ModelMBeanOperationInfo>();
-    List<ModelMBeanNotificationInfo> notifications = new ArrayList<ModelMBeanNotificationInfo>();
-
-    ObjectName objectName;
-    String displayName;
-    private final String className;
-
-    public ModelMBeanBuilder( ObjectName objectName, String displayName, String className )
-    {
-        this.objectName = objectName;
-        this.displayName = displayName;
-        this.className = className;
-    }
-
-    public ModelMBeanBuilder attribute( String name, String displayName, String type, String description, String getMethod, String setMethod )
-    {
-        Descriptor stateDesc = new DescriptorSupport();
-        stateDesc.setField( "name", name );
-        stateDesc.setField( "descriptorType", "attribute" );
-        stateDesc.setField( "displayName", displayName );
-        if (getMethod != null)
-        {
-            stateDesc.setField( "getMethod", getMethod );
-
-            operation( getMethod, description, type, ModelMBeanOperationInfo.INFO );
-        }
-
-        if (setMethod != null)
-        {
-            stateDesc.setField( "setMethod", setMethod );
-            operation( setMethod, description, type, ModelMBeanOperationInfo.INFO, new MBeanParameterInfo("Value", type, description) );
-        }
-
-        ModelMBeanAttributeInfo attributeInfo = new ModelMBeanAttributeInfo(
-                name,
-                type,
-                description,
-                getMethod != null,
-                setMethod != null,
-                getMethod != null && getMethod.startsWith( "is" ),
-                stateDesc );
-        attributes.add( attributeInfo );
-
-        return this;
-    }
-
-    public ModelMBeanAttributeInfo getAttribute(String name)
-    {
-        for (ModelMBeanAttributeInfo attribute : attributes)
-        {
-            if (attribute.getName().equals(name))
-                return attribute;
-        }
-
-        return null;
-    }
-
-    public ModelMBeanBuilder operation( String name, String description, String returnType, int impact, MBeanParameterInfo... parameters)
-    {
-        Descriptor stateDesc = new DescriptorSupport();
-        stateDesc.setField( "name", name );
-        stateDesc.setField( "descriptorType", "operation" );
-        stateDesc.setField( "class", className );
-        stateDesc.setField( "role", "operation" );
-        stateDesc.setField( "targetType", "objectReference" );
-
-        ModelMBeanOperationInfo operationInfo = new ModelMBeanOperationInfo(
-                name,
-                description,
-                parameters,
-                returnType,
-                impact,
-                stateDesc);
-        operations.add( operationInfo );
-
-        return this;
-    }
-
-    public RequiredModelMBean newModelMBean() throws MBeanException
-    {
-        Descriptor mmbDesc = new DescriptorSupport();
-        mmbDesc.setField( "name", objectName.toString() );
-        mmbDesc.setField( "descriptorType", "mbean" );
-        mmbDesc.setField( "displayName", displayName );
-
-        ModelMBeanInfo modelMBeanInfo = new ModelMBeanInfoSupport(
-                className,
-                displayName,
-                attributes.toArray( new ModelMBeanAttributeInfo[attributes.size()]),
-                constructors.toArray( new ModelMBeanConstructorInfo[constructors.size()]),
-                operations.toArray( new ModelMBeanOperationInfo[operations.size()]),
-                notifications.toArray( new ModelMBeanNotificationInfo[notifications.size()]) );
-
-        modelMBeanInfo.setMBeanDescriptor( mmbDesc );
-
-        return new RequiredModelMBean(modelMBeanInfo);
-    }
-}
diff --git a/libraries/jmx/src/main/java/org/qi4j/library/jmx/Qi4jMBeans.java b/libraries/jmx/src/main/java/org/qi4j/library/jmx/Qi4jMBeans.java
deleted file mode 100644
index fd71a45..0000000
--- a/libraries/jmx/src/main/java/org/qi4j/library/jmx/Qi4jMBeans.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.jmx;
-
-import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
-import javax.management.ObjectName;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-
-/**
- * Helper for working with Zest MBeans.
- */
-public class Qi4jMBeans
-{
-
-    public static ObjectName findServiceName( MBeanServer server, String applicationName, String serviceId )
-            throws MalformedObjectNameException
-    {
-        return Iterables.first( Iterables.filter( new Specification<ObjectName>()
-        {
-            @Override
-            public boolean satisfiedBy( ObjectName item )
-            {
-                return item.getKeyPropertyList().size() == 5;
-            }
-
-        }, server.queryNames( new ObjectName( "Zest:application=" + applicationName + ",*,service=" + serviceId ), null ) ) );
-    }
-
-}
diff --git a/libraries/jmx/src/main/java/org/qi4j/library/jmx/package.html b/libraries/jmx/src/main/java/org/qi4j/library/jmx/package.html
deleted file mode 100644
index 474e84b..0000000
--- a/libraries/jmx/src/main/java/org/qi4j/library/jmx/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>JMX Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/jmx/src/test/java/org/apache/polygene/library/jmx/JMXTest.java b/libraries/jmx/src/test/java/org/apache/polygene/library/jmx/JMXTest.java
new file mode 100644
index 0000000..92a79f1
--- /dev/null
+++ b/libraries/jmx/src/test/java/org/apache/polygene/library/jmx/JMXTest.java
@@ -0,0 +1,220 @@
+/*
+ *  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.polygene.library.jmx;
+
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.configuration.ConfigurationComposite;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.util.JmxFixture;
+import org.junit.Test;
+
+/**
+ * Start a simple server so that it can be accessed through JMX remotely.
+ * Run this with -Dcom.sun.management.jmxremote so that the JVM starts the MBeanServer
+ */
+public class JMXTest extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble(ModuleAssembly module) throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        new DefaultUnitOfWorkAssembler().assemble( module );
+
+        module.services( TestService.class, TestService2.class, TestService3.class ).instantiateOnStartup();
+        module.entities( TestConfiguration.class );
+
+        module.values( TestValue.class );
+
+        module.objects( TestObject.class );
+
+        // START SNIPPET: assembly
+        new JMXAssembler().assemble( module );
+        // END SNIPPET: assembly
+
+        // START SNIPPET: connector
+        module.services( JMXConnectorService.class ).instantiateOnStartup();
+        module.entities( JMXConnectorConfiguration.class );
+        module.forMixin( JMXConnectorConfiguration.class ).declareDefaults().port().set( 1099 );
+        // END SNIPPET: connector
+    }
+
+    public static void main(String[] args )
+        throws InterruptedException, ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                    throws AssemblyException
+            {
+                new JMXTest().assemble(module);
+            }
+
+        };
+        // This allows user to connect using VisualVM/JConsole
+        while ( true ) {
+            Thread.sleep( 10_000 );
+        }
+    }
+
+
+
+    @Test
+    public void servicesAndConfiguration()
+    {
+        JmxFixture jmx = new JmxFixture("Polygene:application=Application,layer=Layer 1,module=Module 1,class=Service,");
+        jmx.assertObjectPresent("service=TestService");
+        jmx.assertObjectPresent("service=TestService,name=Configuration");
+        jmx.assertObjectPresent("service=TestService2");
+        jmx.assertObjectPresent("service=TestService2,name=Configuration");
+        jmx.assertObjectPresent("service=TestService3");
+        jmx.assertObjectPresent("service=TestService3,name=Configuration");
+    }
+
+    public interface TestActivation
+    {
+
+        void printConfig();
+
+    }
+
+    public static class TestActivator
+            extends ActivatorAdapter<ServiceReference<TestActivation>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<TestActivation> activated )
+                throws Exception
+        {
+            activated.get().printConfig();
+        }
+
+    }
+
+    @Mixins( TestService.Mixin.class )
+    @Activators( TestActivator.class )
+    public interface TestService
+            extends TestActivation, ServiceComposite
+    {
+
+        class Mixin
+                implements TestActivation
+        {
+
+            @This
+            Configuration<TestConfiguration> config;
+
+            public void printConfig()
+            {
+                System.out.println( "Activate service:" + config.get().stringConfig().get() );
+            }
+
+        }
+
+    }
+
+    @Mixins( TestService2.Mixin.class )
+    @Activators( TestActivator.class )
+    public interface TestService2
+            extends TestActivation, ServiceComposite
+    {
+
+        class Mixin
+                implements TestActivation
+        {
+
+            @This
+            Configuration<TestConfiguration> config;
+
+            public void printConfig()
+            {
+                System.out.println( "Activate service:" + config.get().stringConfig().get() );
+            }
+
+        }
+
+    }
+
+    @Mixins( TestService3.Mixin.class )
+    @Activators( TestActivator.class )
+    public interface TestService3
+            extends TestActivation, ServiceComposite
+    {
+
+        class Mixin
+                implements TestActivation
+        {
+
+            @This
+            Configuration<TestConfiguration> config;
+
+            public void printConfig()
+            {
+                System.out.println( "Activate service:" + config.get().stringConfig().get() );
+            }
+
+        }
+
+    }
+
+    public interface TestConfiguration
+            extends ConfigurationComposite
+    {
+
+        @UseDefaults
+        Property<String> stringConfig();
+
+        @UseDefaults
+        Property<TestEnum> enumConfig();
+
+    }
+
+    public enum TestEnum
+    {
+
+        Value1, Value2, Value3
+
+    }
+
+    public interface TestValue
+            extends ValueComposite
+    {
+    }
+
+    public static class TestObject
+    {
+    }
+
+}
diff --git a/libraries/jmx/src/test/java/org/qi4j/library/jmx/JMXTest.java b/libraries/jmx/src/test/java/org/qi4j/library/jmx/JMXTest.java
deleted file mode 100644
index 03a4b90..0000000
--- a/libraries/jmx/src/test/java/org/qi4j/library/jmx/JMXTest.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.jmx;
-
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.test.EntityTestAssembler;
-
-/**
- * Start a simple server so that it can be accessed through JMX remotely.
- * Run this with -Dcom.sun.management.jmxremote so that the JVM starts the MBeanServer
- */
-public class JMXTest
-{
-
-    public static void main( String[] args )
-        throws InterruptedException, ActivationException, AssemblyException
-    {
-        /*
-         Logger logger = Logger.getLogger( "" );
-         logger.setLevel( Level.FINE );
-         Logger.getLogger("sun.rmi").setLevel( Level.WARNING );
-
-         ConsoleHandler consoleHandler = new ConsoleHandler();
-         consoleHandler.setLevel( Level.FINE );
-         logger.addHandler( consoleHandler );
-         */
-
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            // START SNIPPET: assembly
-
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                // END SNIPPET: assembly
-                new EntityTestAssembler().assemble( module );
-
-                module.services( TestService.class, TestService2.class, TestService3.class ).instantiateOnStartup();
-                module.entities( TestConfiguration.class );
-
-                module.values( TestValue.class );
-
-                module.objects( TestObject.class );
-
-                // START SNIPPET: assembly
-                new JMXAssembler().assemble( module );
-
-                module.services( JMXConnectorService.class ).instantiateOnStartup();
-                module.entities( JMXConnectorConfiguration.class );
-                module.forMixin( JMXConnectorConfiguration.class ).declareDefaults().port().set( 1099 );
-            }
-            // END SNIPPET: assembly
-
-        };
-
-        // This allows user to connect using VisualVM/JConsole
-        while ( true ) {
-            Thread.sleep( 10000 );
-        }
-    }
-
-    @Test
-    public void dummy()
-    {
-    }
-
-    public interface TestActivation
-    {
-
-        void printConfig();
-
-    }
-
-    public static class TestActivator
-            extends ActivatorAdapter<ServiceReference<TestActivation>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<TestActivation> activated )
-                throws Exception
-        {
-            activated.get().printConfig();
-        }
-
-    }
-
-    @Mixins( TestService.Mixin.class )
-    @Activators( TestActivator.class )
-    interface TestService
-            extends TestActivation, ServiceComposite
-    {
-
-        class Mixin
-                implements TestActivation
-        {
-
-            @This
-            Configuration<TestConfiguration> config;
-
-            public void printConfig()
-            {
-                System.out.println( "Activate service:" + config.get().stringConfig().get() );
-            }
-
-        }
-
-    }
-
-    @Mixins( TestService2.Mixin.class )
-    @Activators( TestActivator.class )
-    interface TestService2
-            extends TestActivation, ServiceComposite
-    {
-
-        class Mixin
-                implements TestActivation
-        {
-
-            @This
-            Configuration<TestConfiguration> config;
-
-            public void printConfig()
-            {
-                System.out.println( "Activate service:" + config.get().stringConfig().get() );
-            }
-
-        }
-
-    }
-
-    @Mixins( TestService3.Mixin.class )
-    @Activators( TestActivator.class )
-    interface TestService3
-            extends TestActivation, ServiceComposite
-    {
-
-        class Mixin
-                implements TestActivation
-        {
-
-            @This
-            Configuration<TestConfiguration> config;
-
-            public void printConfig()
-            {
-                System.out.println( "Activate service:" + config.get().stringConfig().get() );
-            }
-
-        }
-
-    }
-
-    interface TestConfiguration
-            extends ConfigurationComposite
-    {
-
-        @UseDefaults
-        Property<String> stringConfig();
-
-        @UseDefaults
-        Property<TestEnum> enumConfig();
-
-    }
-
-    enum TestEnum
-    {
-
-        Value1, Value2, Value3
-
-    }
-
-    interface TestValue
-            extends ValueComposite
-    {
-    }
-
-    public static class TestObject
-    {
-    }
-
-}
diff --git a/libraries/lang-beanshell/README.txt b/libraries/lang-beanshell/README.txt
deleted file mode 100644
index aeee619..0000000
--- a/libraries/lang-beanshell/README.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-
-BeanShell is licensed under LGPL, and Apache Software Foundation
-doesn't allow the use of LGPL in Apache projects.
-
-Therefor, Apache Zest™ had to drop this library component, but
-it is still available for separate download at
-
-https://github.com/Qi4j/qi4j-sdk
-
-in the libraries/lang-beanshell directory.
diff --git a/libraries/lang-groovy/build.gradle b/libraries/lang-groovy/build.gradle
deleted file mode 100644
index 13f2578..0000000
--- a/libraries/lang-groovy/build.gradle
+++ /dev/null
@@ -1,34 +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.
- */
-
-description = "Apache Zest™ Groovy Library allows for Mixins to be implemented in Groovy scripts instead of directly in compiled Java."
-
-jar { manifest { name = "Apache Zest™ Library - Scripting - Groovy" }}
-
-apply plugin: 'groovy'
-
-dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile(libraries.groovy)
-
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
diff --git a/libraries/lang-groovy/dev-status.xml b/libraries/lang-groovy/dev-status.xml
deleted file mode 100644
index 2a02725..0000000
--- a/libraries/lang-groovy/dev-status.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
-  <status>
-    <!--none,early,beta,stable,mature-->
-    <codebase>beta</codebase>
-
-    <!-- none, brief, good, complete -->
-    <documentation>good</documentation>
-
-    <!-- none, some, good, complete -->
-    <unittests>good</unittests>
-  </status>
-  <licenses>
-    <license>ALv2</license>
-  </licenses>
-</module>
\ No newline at end of file
diff --git a/libraries/lang-groovy/src/docs/lang-groovy.txt b/libraries/lang-groovy/src/docs/lang-groovy.txt
deleted file mode 100644
index e5a006a..0000000
--- a/libraries/lang-groovy/src/docs/lang-groovy.txt
+++ /dev/null
@@ -1,109 +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.
-///////////////////////////////////////////////////////////////
-
-[[lang-groovy, Groovy Scripting Library]]
-= Groovy Scripting =
-
-[devstatus]
---------------
-source=libraries/lang-groovy/dev-status.xml
---------------
-
-Groovy Scripting Library
-
-include::../../build/docs/buildinfo/artifact.txt[]
-
-The Groovy Scripting Library is a Generic mixin that implements interfaces by delegating to Groovy code from classpath resources.
-
-But before looking at how to use the Scripting library we'll see that *you don't need this library at all if you simply need to use Groovy classes as Fragments*.
-Then we'll see how to use Groovy class scripts and method scripts.
-
-All examples below are based on this type:
-
-[snippet,java]
-----
-source=libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/HelloSpeaker.java
-tag=speaker
-----
-
-
-== Using compiled Groovy classes ==
-
-To directly use compiled Groovy classes as Fragments you don't need this library at all.
-
-Having this Groovy class compiled ;
-
-.HelloSpeakerMixin.groovy
-[snippet,groovy]
-----
-source=libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/HelloSpeakerMixin.groovy
-tag=direct
-----
-
-assemble it directly:
-
-[snippet,java]
-----
-source=libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/HelloSpeakerTest.java
-tag=direct
-----
-
-
-== Using Groovy class scripts ==
-
-Declare a Groovy class in a classpath resource file located in the same package as the implemented type with the name +<type>.groovy+:
-
-.HelloSpeaker.groovy
-[snippet,groovy]
-----
-source=libraries/lang-groovy/src/test/resources/org/qi4j/lang/groovy/HelloSpeaker.groovy
-tag=script
-----
-
-Then assemble it with the +GroovyMixin+:
-
-[snippet,java]
-----
-source=libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/HelloSpeakerTest.java
-tag=script
-----
-
-Groovy class scripts get +@This+ injection in a +This+ property if present.
-
-
-== Using Groovy method scripts ==
-
-Implement single composites methods, each in a classpath resource file located in the same package as the implemented type with the name +<type>.<method>.groovy+:
-
-.HelloSpeaker.sayHello.groovy
-[snippet,groovy]
-----
-source=libraries/lang-groovy/src/test/resources/org/qi4j/lang/groovy/HelloSpeaker.sayHello.groovy
-tag=script
-----
-
-Then assemble it with the +GroovyMixin+:
-
-[snippet,java]
-----
-source=libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/HelloSpeakerTest.java
-tag=script
-----
-
-Groovy method scripts get +@This+ injection as +This+ property and the methods arguments array as +args+.
diff --git a/libraries/lang-groovy/src/main/java/org/qi4j/lang/groovy/GroovyMixin.java b/libraries/lang-groovy/src/main/java/org/qi4j/lang/groovy/GroovyMixin.java
deleted file mode 100644
index d2d72eb..0000000
--- a/libraries/lang-groovy/src/main/java/org/qi4j/lang/groovy/GroovyMixin.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.lang.groovy;
-
-import groovy.lang.Binding;
-import groovy.lang.GroovyClassLoader;
-import groovy.lang.GroovyObject;
-import groovy.lang.GroovyShell;
-import groovy.lang.MissingPropertyException;
-import java.io.File;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.AppliesToFilter;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.io.Inputs;
-import org.qi4j.io.Outputs;
-
-/**
- * Generic mixin that implements interfaces by delegating to Groovy functions
- * using Groovy. Each method in an interface is declared by a Groovy method
- * in a file located in classpath with the name "&lt;interface&gt;.groovy",
- * where the interface name includes the package, and has "." replaced with "/".
- * <p>
- * Example:
- * </p>
- * <pre><code>
- * org/qi4j/samples/hello/domain/HelloWorldSpeaker.groovy
- * org/qi4j/samples/hello/domain/HelloWorldSpeaker.sayAgain.groovy
- * </code></pre>
- *
- */
-@AppliesTo( GroovyMixin.AppliesTo.class )
-public class GroovyMixin
-    implements InvocationHandler
-{
-
-    private @This
-    Composite me;
-    private final Map<Class, GroovyObject> groovyObjects;
-
-    public static class AppliesTo
-        implements AppliesToFilter
-    {
-
-        @Override
-        public boolean appliesTo( Method method, Class compositeType, Class mixin, Class modelClass )
-        {
-            return getFunctionResource( method ) != null;
-        }
-
-    }
-
-    public GroovyMixin()
-    {
-
-        groovyObjects = new HashMap<Class, GroovyObject>();
-    }
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        final FunctionResource groovySource = getFunctionResource( method );
-        if( groovySource != null )
-        {
-            if( groovySource.script )
-            {
-                return invokeAsObject( method, args, groovySource.url );
-            }
-            return invokeAsScript( method, args, groovySource.url );
-        }
-        throw new RuntimeException( "Internal error: Mixin invoked even if it does not apply" );
-    }
-
-    private Object invokeAsObject( Method method, Object[] args, URL groovySource )
-        throws Throwable
-    {
-        try
-        {
-            Class declaringClass = method.getDeclaringClass();
-            GroovyObject groovyObject = groovyObjects.get( declaringClass );
-            if( groovyObject == null )
-            {
-                InputStream is = null;
-                final Class groovyClass;
-                try
-                {
-                    is = groovySource.openStream();
-                    StringBuilder sourceBuilder = new StringBuilder();
-                    Inputs.text( groovySource ).transferTo( Outputs.text( sourceBuilder ) );
-                    GroovyClassLoader groovyClassLoader = new GroovyClassLoader( declaringClass.getClassLoader() );
-                    groovyClass = groovyClassLoader.parseClass( sourceBuilder.toString() );
-                }
-                finally
-                {
-                    if( is != null )
-                    {
-                        is.close();
-                    }
-                }
-                groovyObject = (GroovyObject) groovyClass.newInstance();
-                if( hasProperty( groovyObject, "This" ) )
-                {
-                    groovyObject.setProperty( "This", me );
-                }
-                groovyObjects.put( declaringClass, groovyObject );
-            }
-            return groovyObject.invokeMethod( method.getName(), args );
-        }
-        catch( Exception e )
-        {
-            e.printStackTrace();
-            throw e;
-        }
-    }
-
-    private boolean hasProperty( GroovyObject groovyObject, String propertyName )
-    {
-        try
-        {
-            groovyObject.getProperty( propertyName );
-            return true;
-        }
-        catch( MissingPropertyException ex )
-        {
-            return false;
-        }
-    }
-
-    private Object invokeAsScript( Method method, Object[] args, URL groovySource )
-        throws Throwable
-    {
-        try
-        {
-            Binding binding = new Binding();
-            binding.setVariable( "This", me );
-            binding.setVariable( "args", args );
-            GroovyShell shell = new GroovyShell( binding );
-            InputStream is = null;
-            try
-            {
-                is = groovySource.openStream();
-                return shell.evaluate( new InputStreamReader( is ) );
-            }
-            finally
-            {
-                if( is != null )
-                {
-                    is.close();
-                }
-            }
-        }
-        catch( Exception e )
-        {
-            e.printStackTrace();
-            throw e;
-        }
-    }
-
-    private static FunctionResource getFunctionResource( final Method method )
-    {
-        boolean script = false;
-        final String scriptPath = method.getDeclaringClass().getName().replace( '.', File.separatorChar );
-        String scriptFile = scriptPath + "." + method.getName() + ".groovy";
-        URL scriptUrl = method.getDeclaringClass().getClassLoader().getResource( scriptFile );
-        if( scriptUrl == null )
-        {
-            script = true;
-            scriptFile = scriptPath + ".groovy";
-            scriptUrl = method.getDeclaringClass().getClassLoader().getResource( scriptFile );
-        }
-        if( scriptUrl != null )
-        {
-            return new FunctionResource( script, scriptUrl );
-        }
-        return null;
-    }
-
-    private static class FunctionResource
-    {
-
-        URL url;
-        boolean script;
-
-        private FunctionResource( final boolean script, final URL url )
-        {
-            this.script = script;
-            this.url = url;
-        }
-
-    }
-
-}
\ No newline at end of file
diff --git a/libraries/lang-groovy/src/main/java/org/qi4j/lang/groovy/package.html b/libraries/lang-groovy/src/main/java/org/qi4j/lang/groovy/package.html
deleted file mode 100644
index 9425182..0000000
--- a/libraries/lang-groovy/src/main/java/org/qi4j/lang/groovy/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Groovy Language Support Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/GroovyComposite.java b/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/GroovyComposite.java
deleted file mode 100644
index 31765f8..0000000
--- a/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/GroovyComposite.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman
- * Licensed 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.qi4j.lang.groovy;
-
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-
-/**
- * JAVADOC
- */
-@Mixins( GroovyMixin.class )
-public interface GroovyComposite extends Mixin1, TransientComposite
-{
-}
\ No newline at end of file
diff --git a/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/GroovyMixinTest.java b/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/GroovyMixinTest.java
deleted file mode 100644
index 976f0bc..0000000
--- a/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/GroovyMixinTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2007-2008 Niclas Hedhman
- * Copyright 2007-2008 Rickard Öberg
- * Licensed 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.qi4j.lang.groovy;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-public class GroovyMixinTest extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( GroovyComposite.class );
-    }
-
-    @Test
-    public void testInvoke()
-    {
-        GroovyComposite domain1 = module.newTransient( GroovyComposite.class );
-        GroovyComposite domain2 = module.newTransient( GroovyComposite.class );
-        Assert.assertEquals( "do1() in Groovy:1", domain1.do1() );
-        Assert.assertEquals( "do1() in Groovy:2", domain1.do1() );
-        Assert.assertEquals( "do1() in Groovy:3", domain1.do1() );
-        Assert.assertEquals( "do1() in Groovy:4", domain1.do1() );
-        Assert.assertEquals( "do1() in Groovy:1", domain2.do1() );
-        Assert.assertEquals( "do1() in Groovy:2", domain2.do1() );
-        Assert.assertEquals( "do1() in Groovy:3", domain2.do1() );
-        Assert.assertEquals( "do1() in Groovy:4", domain2.do1() );
-        Assert.assertEquals( "do1() in Groovy:5", domain2.do1() );
-        Assert.assertEquals( "do1() in Groovy:6", domain2.do1() );
-        Assert.assertEquals( "do1() in Groovy:5", domain1.do1() );
-    }
-}
\ No newline at end of file
diff --git a/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/HelloSpeaker.java b/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/HelloSpeaker.java
deleted file mode 100644
index 9dc0388..0000000
--- a/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/HelloSpeaker.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg
- * Licensed 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.qi4j.lang.groovy;
-
-// START SNIPPET: speaker
-public interface HelloSpeaker
-{
-    String sayHello( String name );
-}
-// END SNIPPET: speaker
diff --git a/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/HelloSpeakerMixin.groovy b/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/HelloSpeakerMixin.groovy
deleted file mode 100644
index f1ba758..0000000
--- a/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/HelloSpeakerMixin.groovy
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2015 the original author or authors
- *
- * Licensed 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.qi4j.lang.groovy;
-
-// START SNIPPET: direct
-public class HelloSpeakerMixin implements HelloSpeaker {
-    public String sayHello( String name ) {
-        "Hello $name!"
-    }
-}
-// END SNIPPET: direct
diff --git a/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/HelloSpeakerTest.java b/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/HelloSpeakerTest.java
deleted file mode 100644
index 1ef9124..0000000
--- a/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/HelloSpeakerTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2015 the original author or authors
- *
- * Licensed 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.qi4j.lang.groovy;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-public class HelloSpeakerTest extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( HelloSpeaker.class ).withMixins( GroovyMixin.class );
-    }
-
-    @Test
-    public void testHello()
-    {
-        HelloSpeaker speaker = module.newTransient( HelloSpeaker.class );
-        Assert.assertEquals( "Hello World!", speaker.sayHello( "World" ) );
-    }
-
-    @Test
-    public void testGroovyScriptResourceMixin()
-        throws Exception
-    {
-        // START SNIPPET: script
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly assembly )
-                throws AssemblyException
-            {
-                assembly.transients( HelloSpeaker.class ).withMixins( GroovyMixin.class );
-            }
-        };
-        HelloSpeaker speaker = assembler.module().newTransient( HelloSpeaker.class );
-        Assert.assertEquals( "Hello World!", speaker.sayHello( "World" ) );
-        // END SNIPPET: script
-    }
-
-    @Test
-    public void testGroovyClassMixin()
-        throws Exception
-    {
-        // START SNIPPET: direct
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( HelloSpeaker.class ).withMixins( HelloSpeakerMixin.class );
-            }
-        };
-        HelloSpeaker speaker = assembler.module().newTransient( HelloSpeaker.class );
-        Assert.assertEquals( "Hello World!", speaker.sayHello( "World" ) );
-        // END SNIPPET: direct
-    }
-}
diff --git a/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/Mixin1.java b/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/Mixin1.java
deleted file mode 100644
index 1184a32..0000000
--- a/libraries/lang-groovy/src/test/groovy/org/qi4j/lang/groovy/Mixin1.java
+++ /dev/null
@@ -1,24 +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.qi4j.lang.groovy;

-

-public interface Mixin1

-{

-    String do1();

-}

diff --git a/libraries/lang-groovy/src/test/resources/org/qi4j/lang/groovy/HelloSpeaker.groovy b/libraries/lang-groovy/src/test/resources/org/qi4j/lang/groovy/HelloSpeaker.groovy
deleted file mode 100644
index eac3726..0000000
--- a/libraries/lang-groovy/src/test/resources/org/qi4j/lang/groovy/HelloSpeaker.groovy
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2015 the original author or authors
- *
- * Licensed 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.
- */
-// START SNIPPET: script
-class HelloSpeaker {
-  def This
-  def sayHello( name ) {
-    "Hello $name!".toString()
-  }
-}
-// END SNIPPET: script
diff --git a/libraries/lang-groovy/src/test/resources/org/qi4j/lang/groovy/HelloSpeaker.sayHello.groovy b/libraries/lang-groovy/src/test/resources/org/qi4j/lang/groovy/HelloSpeaker.sayHello.groovy
deleted file mode 100644
index 48a525e..0000000
--- a/libraries/lang-groovy/src/test/resources/org/qi4j/lang/groovy/HelloSpeaker.sayHello.groovy
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2015 the original author or authors
- *
- * Licensed 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.
- */
-// START SNIPPET: script
-"Hello ${args[0]}!".toString()
-// END SNIPPET: script
diff --git a/libraries/lang-groovy/src/test/resources/org/qi4j/lang/groovy/Mixin1.groovy b/libraries/lang-groovy/src/test/resources/org/qi4j/lang/groovy/Mixin1.groovy
deleted file mode 100644
index 29429cc..0000000
--- a/libraries/lang-groovy/src/test/resources/org/qi4j/lang/groovy/Mixin1.groovy
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg
- * Licensed 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.
-*/
-public class Mixin1
-{
-    def This
-    def counter = 0
-
-    public String do1()
-    {
-        counter = counter + 1
-        return "do1() in Groovy:" + counter
-    }
-}
diff --git a/libraries/lang-javascript/build.gradle b/libraries/lang-javascript/build.gradle
deleted file mode 100644
index 7500b34..0000000
--- a/libraries/lang-javascript/build.gradle
+++ /dev/null
@@ -1,34 +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.
- */
-
-description = "Apache Zest™ JavaScript Library allows for Mixins to be implemented in JavaScript instead of directly in compiled Java."
-
-jar { manifest { name = "Apache Zest™ Library - Scripting - JavaScript" }}
-
-
-dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile( project( ':org.qi4j.libraries:org.qi4j.library.scripting' ))
-  compile(libraries.javascript)
-
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
diff --git a/libraries/lang-javascript/dev-status.xml b/libraries/lang-javascript/dev-status.xml
deleted file mode 100644
index 58fda09..0000000
--- a/libraries/lang-javascript/dev-status.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
-  <status>
-    <!--none,early,beta,stable,mature-->
-    <codebase>beta</codebase>
-
-    <!-- none, brief, good, complete -->
-    <documentation>brief</documentation>
-
-    <!-- none, some, good, complete -->
-    <unittests>some</unittests>
-  </status>
-  <licenses>
-    <license>ALv2</license>
-  </licenses>
-</module>
\ No newline at end of file
diff --git a/libraries/lang-javascript/licenses/rhino.license b/libraries/lang-javascript/licenses/rhino.license
deleted file mode 100644
index 7714141..0000000
--- a/libraries/lang-javascript/licenses/rhino.license
+++ /dev/null
@@ -1,470 +0,0 @@
-                          MOZILLA PUBLIC LICENSE
-                                Version 1.1
-
-                              ---------------
-
-1. Definitions.
-
-     1.0.1. "Commercial Use" means distribution or otherwise making the
-     Covered Code available to a third party.
-
-     1.1. "Contributor" means each entity that creates or contributes to
-     the creation of Modifications.
-
-     1.2. "Contributor Version" means the combination of the Original
-     Code, prior Modifications used by a Contributor, and the Modifications
-     made by that particular Contributor.
-
-     1.3. "Covered Code" means the Original Code or Modifications or the
-     combination of the Original Code and Modifications, in each case
-     including portions thereof.
-
-     1.4. "Electronic Distribution Mechanism" means a mechanism generally
-     accepted in the software development community for the electronic
-     transfer of data.
-
-     1.5. "Executable" means Covered Code in any form other than Source
-     Code.
-
-     1.6. "Initial Developer" means the individual or entity identified
-     as the Initial Developer in the Source Code notice required by Exhibit
-     A.
-
-     1.7. "Larger Work" means a work which combines Covered Code or
-     portions thereof with code not governed by the terms of this License.
-
-     1.8. "License" means this document.
-
-     1.8.1. "Licensable" means having the right to grant, to the maximum
-     extent possible, whether at the time of the initial grant or
-     subsequently acquired, any and all of the rights conveyed herein.
-
-     1.9. "Modifications" means any addition to or deletion from the
-     substance or structure of either the Original Code or any previous
-     Modifications. When Covered Code is released as a series of files, a
-     Modification is:
-          A. Any addition to or deletion from the contents of a file
-          containing Original Code or previous Modifications.
-
-          B. Any new file that contains any part of the Original Code or
-          previous Modifications.
-
-     1.10. "Original Code" means Source Code of computer software code
-     which is described in the Source Code notice required by Exhibit A as
-     Original Code, and which, at the time of its release under this
-     License is not already Covered Code governed by this License.
-
-     1.10.1. "Patent Claims" means any patent claim(s), now owned or
-     hereafter acquired, including without limitation,  method, process,
-     and apparatus claims, in any patent Licensable by grantor.
-
-     1.11. "Source Code" means the preferred form of the Covered Code for
-     making modifications to it, including all modules it contains, plus
-     any associated interface definition files, scripts used to control
-     compilation and installation of an Executable, or source code
-     differential comparisons against either the Original Code or another
-     well known, available Covered Code of the Contributor's choice. The
-     Source Code can be in a compressed or archival form, provided the
-     appropriate decompression or de-archiving software is widely available
-     for no charge.
-
-     1.12. "You" (or "Your")  means an individual or a legal entity
-     exercising rights under, and complying with all of the terms of, this
-     License or a future version of this License issued under Section 6.1.
-     For legal entities, "You" includes any entity which controls, is
-     controlled by, or is under common control with You. For purposes of
-     this definition, "control" means (a) the power, direct or indirect,
-     to cause the direction or management of such entity, whether by
-     contract or otherwise, or (b) ownership of more than fifty percent
-     (50%) of the outstanding shares or beneficial ownership of such
-     entity.
-
-2. Source Code License.
-
-     2.1. The Initial Developer Grant.
-     The Initial Developer hereby grants You a world-wide, royalty-free,
-     non-exclusive license, subject to third party intellectual property
-     claims:
-          (a)  under intellectual property rights (other than patent or
-          trademark) Licensable by Initial Developer to use, reproduce,
-          modify, display, perform, sublicense and distribute the Original
-          Code (or portions thereof) with or without Modifications, and/or
-          as part of a Larger Work; and
-
-          (b) under Patents Claims infringed by the making, using or
-          selling of Original Code, to make, have made, use, practice,
-          sell, and offer for sale, and/or otherwise dispose of the
-          Original Code (or portions thereof).
-
-          (c) the licenses granted in this Section 2.1(a) and (b) are
-          effective on the date Initial Developer first distributes
-          Original Code under the terms of this License.
-
-          (d) Notwithstanding Section 2.1(b) above, no patent license is
-          granted: 1) for code that You delete from the Original Code; 2)
-          separate from the Original Code;  or 3) for infringements caused
-          by: i) the modification of the Original Code or ii) the
-          combination of the Original Code with other software or devices.
-
-     2.2. Contributor Grant.
-     Subject to third party intellectual property claims, each Contributor
-     hereby grants You a world-wide, royalty-free, non-exclusive license
-
-          (a)  under intellectual property rights (other than patent or
-          trademark) Licensable by Contributor, to use, reproduce, modify,
-          display, perform, sublicense and distribute the Modifications
-          created by such Contributor (or portions thereof) either on an
-          unmodified basis, with other Modifications, as Covered Code
-          and/or as part of a Larger Work; and
-
-          (b) under Patent Claims infringed by the making, using, or
-          selling of  Modifications made by that Contributor either alone
-          and/or in combination with its Contributor Version (or portions
-          of such combination), to make, use, sell, offer for sale, have
-          made, and/or otherwise dispose of: 1) Modifications made by that
-          Contributor (or portions thereof); and 2) the combination of
-          Modifications made by that Contributor with its Contributor
-          Version (or portions of such combination).
-
-          (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
-          effective on the date Contributor first makes Commercial Use of
-          the Covered Code.
-
-          (d)    Notwithstanding Section 2.2(b) above, no patent license is
-          granted: 1) for any code that Contributor has deleted from the
-          Contributor Version; 2)  separate from the Contributor Version;
-          3)  for infringements caused by: i) third party modifications of
-          Contributor Version or ii)  the combination of Modifications made
-          by that Contributor with other software  (except as part of the
-          Contributor Version) or other devices; or 4) under Patent Claims
-          infringed by Covered Code in the absence of Modifications made by
-          that Contributor.
-
-3. Distribution Obligations.
-
-     3.1. Application of License.
-     The Modifications which You create or to which You contribute are
-     governed by the terms of this License, including without limitation
-     Section 2.2. The Source Code version of Covered Code may be
-     distributed only under the terms of this License or a future version
-     of this License released under Section 6.1, and You must include a
-     copy of this License with every copy of the Source Code You
-     distribute. You may not offer or impose any terms on any Source Code
-     version that alters or restricts the applicable version of this
-     License or the recipients' rights hereunder. However, You may include
-     an additional document offering the additional rights described in
-     Section 3.5.
-
-     3.2. Availability of Source Code.
-     Any Modification which You create or to which You contribute must be
-     made available in Source Code form under the terms of this License
-     either on the same media as an Executable version or via an accepted
-     Electronic Distribution Mechanism to anyone to whom you made an
-     Executable version available; and if made available via Electronic
-     Distribution Mechanism, must remain available for at least twelve (12)
-     months after the date it initially became available, or at least six
-     (6) months after a subsequent version of that particular Modification
-     has been made available to such recipients. You are responsible for
-     ensuring that the Source Code version remains available even if the
-     Electronic Distribution Mechanism is maintained by a third party.
-
-     3.3. Description of Modifications.
-     You must cause all Covered Code to which You contribute to contain a
-     file documenting the changes You made to create that Covered Code and
-     the date of any change. You must include a prominent statement that
-     the Modification is derived, directly or indirectly, from Original
-     Code provided by the Initial Developer and including the name of the
-     Initial Developer in (a) the Source Code, and (b) in any notice in an
-     Executable version or related documentation in which You describe the
-     origin or ownership of the Covered Code.
-
-     3.4. Intellectual Property Matters
-          (a) Third Party Claims.
-          If Contributor has knowledge that a license under a third party's
-          intellectual property rights is required to exercise the rights
-          granted by such Contributor under Sections 2.1 or 2.2,
-          Contributor must include a text file with the Source Code
-          distribution titled "LEGAL" which describes the claim and the
-          party making the claim in sufficient detail that a recipient will
-          know whom to contact. If Contributor obtains such knowledge after
-          the Modification is made available as described in Section 3.2,
-          Contributor shall promptly modify the LEGAL file in all copies
-          Contributor makes available thereafter and shall take other steps
-          (such as notifying appropriate mailing lists or newsgroups)
-          reasonably calculated to inform those who received the Covered
-          Code that new knowledge has been obtained.
-
-          (b) Contributor APIs.
-          If Contributor's Modifications include an application programming
-          interface and Contributor has knowledge of patent licenses which
-          are reasonably necessary to implement that API, Contributor must
-          also include this information in the LEGAL file.
-
-               (c)    Representations.
-          Contributor represents that, except as disclosed pursuant to
-          Section 3.4(a) above, Contributor believes that Contributor's
-          Modifications are Contributor's original creation(s) and/or
-          Contributor has sufficient rights to grant the rights conveyed by
-          this License.
-
-     3.5. Required Notices.
-     You must duplicate the notice in Exhibit A in each file of the Source
-     Code.  If it is not possible to put such notice in a particular Source
-     Code file due to its structure, then You must include such notice in a
-     location (such as a relevant directory) where a user would be likely
-     to look for such a notice.  If You created one or more Modification(s)
-     You may add your name as a Contributor to the notice described in
-     Exhibit A.  You must also duplicate this License in any documentation
-     for the Source Code where You describe recipients' rights or ownership
-     rights relating to Covered Code.  You may choose to offer, and to
-     charge a fee for, warranty, support, indemnity or liability
-     obligations to one or more recipients of Covered Code. However, You
-     may do so only on Your own behalf, and not on behalf of the Initial
-     Developer or any Contributor. You must make it absolutely clear than
-     any such warranty, support, indemnity or liability obligation is
-     offered by You alone, and You hereby agree to indemnify the Initial
-     Developer and every Contributor for any liability incurred by the
-     Initial Developer or such Contributor as a result of warranty,
-     support, indemnity or liability terms You offer.
-
-     3.6. Distribution of Executable Versions.
-     You may distribute Covered Code in Executable form only if the
-     requirements of Section 3.1-3.5 have been met for that Covered Code,
-     and if You include a notice stating that the Source Code version of
-     the Covered Code is available under the terms of this License,
-     including a description of how and where You have fulfilled the
-     obligations of Section 3.2. The notice must be conspicuously included
-     in any notice in an Executable version, related documentation or
-     collateral in which You describe recipients' rights relating to the
-     Covered Code. You may distribute the Executable version of Covered
-     Code or ownership rights under a license of Your choice, which may
-     contain terms different from this License, provided that You are in
-     compliance with the terms of this License and that the license for the
-     Executable version does not attempt to limit or alter the recipient's
-     rights in the Source Code version from the rights set forth in this
-     License. If You distribute the Executable version under a different
-     license You must make it absolutely clear that any terms which differ
-     from this License are offered by You alone, not by the Initial
-     Developer or any Contributor. You hereby agree to indemnify the
-     Initial Developer and every Contributor for any liability incurred by
-     the Initial Developer or such Contributor as a result of any such
-     terms You offer.
-
-     3.7. Larger Works.
-     You may create a Larger Work by combining Covered Code with other code
-     not governed by the terms of this License and distribute the Larger
-     Work as a single product. In such a case, You must make sure the
-     requirements of this License are fulfilled for the Covered Code.
-
-4. Inability to Comply Due to Statute or Regulation.
-
-     If it is impossible for You to comply with any of the terms of this
-     License with respect to some or all of the Covered Code due to
-     statute, judicial order, or regulation then You must: (a) comply with
-     the terms of this License to the maximum extent possible; and (b)
-     describe the limitations and the code they affect. Such description
-     must be included in the LEGAL file described in Section 3.4 and must
-     be included with all distributions of the Source Code. Except to the
-     extent prohibited by statute or regulation, such description must be
-     sufficiently detailed for a recipient of ordinary skill to be able to
-     understand it.
-
-5. Application of this License.
-
-     This License applies to code to which the Initial Developer has
-     attached the notice in Exhibit A and to related Covered Code.
-
-6. Versions of the License.
-
-     6.1. New Versions.
-     Netscape Communications Corporation ("Netscape") may publish revised
-     and/or new versions of the License from time to time. Each version
-     will be given a distinguishing version number.
-
-     6.2. Effect of New Versions.
-     Once Covered Code has been published under a particular version of the
-     License, You may always continue to use it under the terms of that
-     version. You may also choose to use such Covered Code under the terms
-     of any subsequent version of the License published by Netscape. No one
-     other than Netscape has the right to modify the terms applicable to
-     Covered Code created under this License.
-
-     6.3. Derivative Works.
-     If You create or use a modified version of this License (which you may
-     only do in order to apply it to code which is not already Covered Code
-     governed by this License), You must (a) rename Your license so that
-     the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
-     "MPL", "NPL" or any confusingly similar phrase do not appear in your
-     license (except to note that your license differs from this License)
-     and (b) otherwise make it clear that Your version of the license
-     contains terms which differ from the Mozilla Public License and
-     Netscape Public License. (Filling in the name of the Initial
-     Developer, Original Code or Contributor in the notice described in
-     Exhibit A shall not of themselves be deemed to be modifications of
-     this License.)
-
-7. DISCLAIMER OF WARRANTY.
-
-     COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
-     WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
-     WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
-     DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
-     THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
-     IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
-     YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
-     COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
-     OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
-     ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
-
-8. TERMINATION.
-
-     8.1.  This License and the rights granted hereunder will terminate
-     automatically if You fail to comply with terms herein and fail to cure
-     such breach within 30 days of becoming aware of the breach. All
-     sublicenses to the Covered Code which are properly granted shall
-     survive any termination of this License. Provisions which, by their
-     nature, must remain in effect beyond the termination of this License
-     shall survive.
-
-     8.2.  If You initiate litigation by asserting a patent infringement
-     claim (excluding declatory judgment actions) against Initial Developer
-     or a Contributor (the Initial Developer or Contributor against whom
-     You file such action is referred to as "Participant")  alleging that:
-
-     (a)  such Participant's Contributor Version directly or indirectly
-     infringes any patent, then any and all rights granted by such
-     Participant to You under Sections 2.1 and/or 2.2 of this License
-     shall, upon 60 days notice from Participant terminate prospectively,
-     unless if within 60 days after receipt of notice You either: (i)
-     agree in writing to pay Participant a mutually agreeable reasonable
-     royalty for Your past and future use of Modifications made by such
-     Participant, or (ii) withdraw Your litigation claim with respect to
-     the Contributor Version against such Participant.  If within 60 days
-     of notice, a reasonable royalty and payment arrangement are not
-     mutually agreed upon in writing by the parties or the litigation claim
-     is not withdrawn, the rights granted by Participant to You under
-     Sections 2.1 and/or 2.2 automatically terminate at the expiration of
-     the 60 day notice period specified above.
-
-     (b)  any software, hardware, or device, other than such Participant's
-     Contributor Version, directly or indirectly infringes any patent, then
-     any rights granted to You by such Participant under Sections 2.1(b)
-     and 2.2(b) are revoked effective as of the date You first made, used,
-     sold, distributed, or had made, Modifications made by that
-     Participant.
-
-     8.3.  If You assert a patent infringement claim against Participant
-     alleging that such Participant's Contributor Version directly or
-     indirectly infringes any patent where such claim is resolved (such as
-     by license or settlement) prior to the initiation of patent
-     infringement litigation, then the reasonable value of the licenses
-     granted by such Participant under Sections 2.1 or 2.2 shall be taken
-     into account in determining the amount or value of any payment or
-     license.
-
-     8.4.  In the event of termination under Sections 8.1 or 8.2 above,
-     all end user license agreements (excluding distributors and resellers)
-     which have been validly granted by You or any distributor hereunder
-     prior to termination shall survive termination.
-
-9. LIMITATION OF LIABILITY.
-
-     UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
-     (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
-     DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
-     OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
-     ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
-     CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
-     WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
-     COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
-     INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
-     LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
-     RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
-     PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
-     EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
-     THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
-
-10. U.S. GOVERNMENT END USERS.
-
-     The Covered Code is a "commercial item," as that term is defined in
-     48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
-     software" and "commercial computer software documentation," as such
-     terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
-     C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
-     all U.S. Government End Users acquire Covered Code with only those
-     rights set forth herein.
-
-11. MISCELLANEOUS.
-
-     This License represents the complete agreement concerning subject
-     matter hereof. If any provision of this License is held to be
-     unenforceable, such provision shall be reformed only to the extent
-     necessary to make it enforceable. This License shall be governed by
-     California law provisions (except to the extent applicable law, if
-     any, provides otherwise), excluding its conflict-of-law provisions.
-     With respect to disputes in which at least one party is a citizen of,
-     or an entity chartered or registered to do business in the United
-     States of America, any litigation relating to this License shall be
-     subject to the jurisdiction of the Federal Courts of the Northern
-     District of California, with venue lying in Santa Clara County,
-     California, with the losing party responsible for costs, including
-     without limitation, court costs and reasonable attorneys' fees and
-     expenses. The application of the United Nations Convention on
-     Contracts for the International Sale of Goods is expressly excluded.
-     Any law or regulation which provides that the language of a contract
-     shall be construed against the drafter shall not apply to this
-     License.
-
-12. RESPONSIBILITY FOR CLAIMS.
-
-     As between Initial Developer and the Contributors, each party is
-     responsible for claims and damages arising, directly or indirectly,
-     out of its utilization of rights under this License and You agree to
-     work with Initial Developer and Contributors to distribute such
-     responsibility on an equitable basis. Nothing herein is intended or
-     shall be deemed to constitute any admission of liability.
-
-13. MULTIPLE-LICENSED CODE.
-
-     Initial Developer may designate portions of the Covered Code as
-     "Multiple-Licensed".  "Multiple-Licensed" means that the Initial
-     Developer permits you to utilize portions of the Covered Code under
-     Your choice of the NPL or the alternative licenses, if any, specified
-     by the Initial Developer in the file described in Exhibit A.
-
-EXHIBIT A -Mozilla Public License.
-
-     ``The contents of this file are subject to the Mozilla Public License
-     Version 1.1 (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.mozilla.org/MPL/
-
-     Software distributed under the License is distributed on an "AS IS"
-     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-     License for the specific language governing rights and limitations
-     under the License.
-
-     The Original Code is ______________________________________.
-
-     The Initial Developer of the Original Code is ________________________.
-     Portions created by ______________________ are Copyright (C) ______
-     _______________________. All Rights Reserved.
-
-     Contributor(s): ______________________________________.
-
-     Alternatively, the contents of this file may be used under the terms
-     of the _____ license (the  "[___] License"), in which case the
-     provisions of [______] License are applicable instead of those
-     above.  If you wish to allow use of your version of this file only
-     under the terms of the [____] License and not to allow others to use
-     your version of this file under the MPL, indicate your decision by
-     deleting  the provisions above and replace  them with the notice and
-     other provisions required by the [___] License.  If you do not delete
-     the provisions above, a recipient may use your version of this file
-     under either the MPL or the [___] License."
-
-     [NOTE: The text of this Exhibit A may differ slightly from the text of
-     the notices in the Source Code files of the Original Code. You should
-     use the text of this Exhibit A rather than the text found in the
-     Original Code Source Code for Your Modifications.]
-
diff --git a/libraries/lang-javascript/src/docs/lang-javascript.txt b/libraries/lang-javascript/src/docs/lang-javascript.txt
deleted file mode 100644
index ddd52e2..0000000
--- a/libraries/lang-javascript/src/docs/lang-javascript.txt
+++ /dev/null
@@ -1,55 +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.
-///////////////////////////////////////////////////////////////
-
-[[lang-javascript, Javascript Scripting Library]]
-= Javascript Scripting =
-
-[devstatus]
---------------
-source=libraries/lang-javascript/dev-status.xml
---------------
-
-The Javascript Scripting Library allows Mixin methods to be implemented in Javascript and loaded dynamically on first use.
-
-include::../../build/docs/buildinfo/artifact.txt[]
-
-The Javascript Scripting Library is a Generic mixin class that implements 
-Composite interfaces by delegating to JavaScript functions using Rhino. Each 
-method in an interface is declared as a JS function in a file located in 
-classpath with the name "<interface>.<method>.js", where the interface name 
-includes the package, and has "." replaced with "/".
-
-Example: 
-
-    org/qi4j/samples/hello/domain/HelloWorldSpeaker.say.js
-
-That means that the HelloWorldSpeaker.say.js file may be co-located with the 
-class files in the same package. It is currently not supported to place the 
-Javascript implementation of the mixin in a different package than the 
-interface it implements.
-
-To use Javascript to implement the Mixin functionality for a given interface, 
-simply declare the +JavaScriptMixin+ like any other mixin, either in the 
-interface or at assembly time.
-
-[snippet,java]
-----
-source=libraries/lang-javascript/src/test/java/org/qi4j/lang/javascript/HelloSpeaker.java
-tag=mixin
-----
diff --git a/libraries/lang-javascript/src/main/java/org/qi4j/lang/javascript/JavaScriptMixin.java b/libraries/lang-javascript/src/main/java/org/qi4j/lang/javascript/JavaScriptMixin.java
deleted file mode 100644
index 5575458..0000000
--- a/libraries/lang-javascript/src/main/java/org/qi4j/lang/javascript/JavaScriptMixin.java
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg
- * Licensed 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.qi4j.lang.javascript;
-
-import java.io.*;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.StringTokenizer;
-import org.mozilla.javascript.*;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.AppliesToFilter;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.composite.TransientBuilderFactory;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.library.scripting.ScriptException;
-import org.qi4j.library.scripting.ScriptReloadable;
-
-/**
- * Generic mixin that implements interfaces by delegating to JavaScript functions
- * using Rhino. Each method in an interface is declared as a JS function
- * in a file located in classpath with the name "&lt;interface&gt;.&lt;method&gt;.js",
- * where the interface name includes the package, and has "." replaced with "/".
- * <p>
- * Example:
- * </p>
- * <pre><code>
- * org/qi4j/samples/hello/domain/HelloWorldSpeaker.say.js
- * </code></pre>
- */
-@AppliesTo( JavaScriptMixin.AppliesTo.class )
-public class JavaScriptMixin
-    implements InvocationHandler, ScriptReloadable
-{
-    @This private Composite me;
-
-    static private Scriptable standardScope;
-
-    private HashMap<String, Function> cachedScripts;
-
-    @Structure private TransientBuilderFactory factory;
-    private Scriptable instanceScope;
-    
-    static
-    {
-        Context cx = Context.enter();
-        standardScope = cx.initStandardObjects();
-        Context.exit();
-    }
-
-    public JavaScriptMixin()
-    {
-        cachedScripts = new HashMap<String, Function>();
-        Context cx = Context.enter();
-        instanceScope = cx.newObject( standardScope );
-        instanceScope.setPrototype( standardScope );
-        Context.exit();
-
-    }
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable
-    {
-        Context cx = Context.enter();
-        try
-        {
-            Scriptable proxyScope = Context.toObject( proxy, instanceScope );
-            proxyScope.setPrototype( instanceScope );
-            proxyScope.put( "compositeBuilderFactory", proxyScope, factory );
-            proxyScope.put( "This", proxyScope, me );
-            Function fn = getFunction( cx, proxyScope, method );
-            Object result = fn.call( cx, instanceScope, proxyScope, args );
-
-            if( result instanceof Undefined )
-            {
-                return null;
-            }
-            else if( result instanceof Wrapper )
-            {
-                return ( (Wrapper) result ).unwrap();
-            }
-            else
-            {
-                return result;
-            }
-        }
-        finally
-        {
-            Context.exit();
-        }
-    }
-
-    @Override
-    public void reloadScripts()
-    {
-        cachedScripts.clear();
-    }
-
-    private Function getFunction( Context cx, Scriptable scope, Method method )
-        throws IOException
-    {
-        Class<?> declaringClass = method.getDeclaringClass();
-        String classname = declaringClass.getName();
-        String methodName = method.getName();
-        String requestedFunctionName = classname + ":" + methodName;
-
-        Function fx = cachedScripts.get( requestedFunctionName );
-        if( fx != null )
-        {
-            return fx;
-        }
-        compileScripts( cx, scope, method );
-        fx = cachedScripts.get( requestedFunctionName );
-        return fx;
-    }
-
-    private void compileScripts( Context cx, Scriptable scope, Method method )
-        throws IOException
-    {
-        URL scriptUrl = getFunctionResource( method );
-        if( scriptUrl == null )
-        {
-            throw new IOException( "No script found for method " + method.getName() );
-        }
-
-        InputStream in = scriptUrl.openStream();
-        BufferedReader scriptReader = new BufferedReader( new InputStreamReader( in ) );
-        int lineNo = 1;
-        String classname = method.getDeclaringClass().getName();
-        while( true )
-        {
-            ScriptFragment fragment = extractFunction( scriptReader );
-            if( "".equals( fragment.script.trim() ) )
-            {
-                break;
-            }
-            String functionName = parseFunctionName( fragment.script, scriptUrl.toString() );
-            Function function = cx.compileFunction( scope, fragment.script, "<" + scriptUrl.toString() + ">", lineNo, null );
-            cachedScripts.put( classname + ":" + functionName, function );
-            lineNo = lineNo + fragment.numberOfLines;
-        }
-    }
-
-    /**
-     * Extracts the function name.
-     * <p>
-     * Since the fragment has been stripped of all comments, the first non-whitespace word to appear
-     * should be "function" and the word after that should be the function name.
-     * </p>
-     *
-     * @param script     The script snippet.
-     * @param scriptName The name of the script being parsed.
-     * @return the name of the function declared in this snippet.
-     */
-    private String parseFunctionName( String script, String scriptName )
-    {
-        // TODO optimize with hardcoded parser??
-        StringTokenizer st = new StringTokenizer( script, " \t\n\r\f(){}", false );
-        if( !st.hasMoreTokens() )
-        {
-            throw new ScriptException( "The word \"function\" was not found in script: " + scriptName );
-        }
-        String fx = st.nextToken();
-        if( !"function".equals( fx ) )
-        {
-            throw new ScriptException( "The word \"function\" was not found in script: " + scriptName );
-        }
-        if( !st.hasMoreTokens() )
-        {
-            throw new ScriptException( "Invalid syntax in: " + scriptName + "\n No function name." );
-        }
-        return st.nextToken();
-    }
-
-    /**
-     * Returns ONE function, minus comments.
-     *
-     * @param scriptReader The Reader of the script
-     * @return A ScriptFragment containing the Script text for the function, and how many lines it is.
-     * @throws IOException If a problem in the Reader occurs.
-     */
-    private ScriptFragment extractFunction( Reader scriptReader )
-        throws IOException
-    {
-        ScriptFragment fragment = new ScriptFragment();
-        boolean inString = false;
-        boolean inChar = false;
-        boolean escaped = false;
-        boolean lineComment = false;
-        boolean blockComment = false;
-        char lastCh = '\0';
-        int braceCounter = 0;
-        boolean notStarted = true;
-        int b = scriptReader.read();
-        int skip = 0;
-        while( b != -1 && ( notStarted || braceCounter > 0 ) )
-        {
-            char ch = (char) b;
-            if( !blockComment && !lineComment )
-            {
-                fragment.script = fragment.script + ch;
-                if( !escaped )
-                {
-                    if( !inString && !inChar )
-                    {
-                        if( ch == '{' )
-                        {
-                            braceCounter++;
-                            notStarted = false;
-                        }
-                        if( ch == '}' )
-                        {
-                            braceCounter--;
-                        }
-                    }
-                    if( ch == '\"' )
-                    {
-                        inString = !inString;
-                    }
-                    if( ch == '\'' )
-                    {
-                        inChar = !inChar;
-                    }
-                    if( ch == '\\' )
-                    {
-                        escaped = true;
-                    }
-                    if( ch == '\n' )
-                    {
-                        fragment.numberOfLines++;
-                    }
-                    if( ch == '/' && lastCh == '/' )
-                    {
-                        lineComment = true;
-                        fragment.script = fragment.script.substring( 0, fragment.script.length() - 2 );
-                    }
-                    if( ch == '*' && lastCh == '/' )
-                    {
-                        blockComment = true;
-                        fragment.script = fragment.script.substring( 0, fragment.script.length() - 2 );
-                    }
-                }
-                else
-                {
-                    if( ch == 'u' )
-                    {
-                        skip = 4;
-                    }
-                    else if( skip > 0 )
-                    {
-                        skip--;
-                    }
-                    else
-                    {
-                        escaped = false;
-                    }
-                }
-            }
-            else
-            {
-                if( lineComment )
-                {
-                    if( ch == '\n' )
-                    {
-                        lineComment = false;
-                    }
-                }
-                if( blockComment )
-                {
-                    if( ch == '/' && lastCh == '*' )
-                    {
-                        blockComment = false;
-                    }
-                }
-            }
-            lastCh = ch;
-            b = scriptReader.read();
-        }
-        return fragment;
-    }
-
-    private static URL getFunctionResource( Method method )
-    {
-        String scriptName = getScriptName( method );
-        Class<?> declaringClass = method.getDeclaringClass();
-        ClassLoader loader = declaringClass.getClassLoader();
-        return loader.getResource( scriptName );
-    }
-
-    private static String getScriptName( Method method )
-    {
-        Class<?> declaringClass = method.getDeclaringClass();
-        String classname = declaringClass.getName();
-        return classname.replace( '.', '/' ) + ".js";
-    }
-
-    private static class ScriptFragment
-    {
-        String script = "";
-        int numberOfLines = 0;
-    }
-
-    public static class AppliesTo
-        implements AppliesToFilter
-    {
-
-        public boolean appliesTo( Method method, Class compositeType, Class mixin, Class modelClass )
-        {
-            return getFunctionResource( method ) != null;
-        }
-
-    }
-}
diff --git a/libraries/lang-javascript/src/main/java/org/qi4j/lang/javascript/package.html b/libraries/lang-javascript/src/main/java/org/qi4j/lang/javascript/package.html
deleted file mode 100644
index 0825404..0000000
--- a/libraries/lang-javascript/src/main/java/org/qi4j/lang/javascript/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>JavaScript Language Support Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/lang-javascript/src/test/java/org/qi4j/lang/javascript/DomainType.java b/libraries/lang-javascript/src/test/java/org/qi4j/lang/javascript/DomainType.java
deleted file mode 100644
index fbc58d5..0000000
--- a/libraries/lang-javascript/src/test/java/org/qi4j/lang/javascript/DomainType.java
+++ /dev/null
@@ -1,24 +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.qi4j.lang.javascript;

-

-public interface DomainType

-{

-    String do1();

-}
\ No newline at end of file
diff --git a/libraries/lang-javascript/src/test/java/org/qi4j/lang/javascript/HelloSpeaker.java b/libraries/lang-javascript/src/test/java/org/qi4j/lang/javascript/HelloSpeaker.java
deleted file mode 100644
index a7c1b9c..0000000
--- a/libraries/lang-javascript/src/test/java/org/qi4j/lang/javascript/HelloSpeaker.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg
- * Licensed 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.qi4j.lang.javascript;
-
-import org.qi4j.api.mixin.Mixins;
-
-// START SNIPPET: mixin
-import org.qi4j.lang.javascript.JavaScriptMixin;
-
-@Mixins(JavaScriptMixin.class)
-public interface HelloSpeaker
-{
-    void sayHello();
-}
-// END SNIPPET: mixin
diff --git a/libraries/lang-javascript/src/test/java/org/qi4j/lang/javascript/JavaScriptMixinTest.java b/libraries/lang-javascript/src/test/java/org/qi4j/lang/javascript/JavaScriptMixinTest.java
deleted file mode 100644
index dc34d91..0000000
--- a/libraries/lang-javascript/src/test/java/org/qi4j/lang/javascript/JavaScriptMixinTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg
- * Licensed 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.qi4j.lang.javascript;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-public class JavaScriptMixinTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( DomainType.class ).withMixins( JavaScriptMixin.class );
-    }
-
-    @Test
-    public void testInvoke() throws Throwable
-    {
-        DomainType domain = module.newTransient( DomainType.class );
-        Assert.assertEquals( "do1 script \" and ' for many cases is harder.", domain.do1() );
-    }
-}
\ No newline at end of file
diff --git a/libraries/lang-javascript/src/test/resources/org/qi4j/lang/javascript/DomainType.js b/libraries/lang-javascript/src/test/resources/org/qi4j/lang/javascript/DomainType.js
deleted file mode 100644
index 848ebfe..0000000
--- a/libraries/lang-javascript/src/test/resources/org/qi4j/lang/javascript/DomainType.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg
- * Licensed 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.
- */
-// This is a line comment.
-
-/* A block comment should not interfere */
-function /* not even here*/ do1()
-{
-    // {
-    // { are nasty...
-    return "do1 script \" and \' for many cases is harder.";
-}
-
-function do2()
-{
-    return "}";
-}
\ No newline at end of file
diff --git a/libraries/lang-jruby/README.txt b/libraries/lang-jruby/README.txt
deleted file mode 100644
index 3b2dcf5..0000000
--- a/libraries/lang-jruby/README.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-
-JRuby is licensed under LGPL, and Apache Software Foundation
-doesn't allow the use of LGPL in Apache projects.
-
-Therefor, Apache Zest™ had to drop this library component, but
-it is still available for separate download at
-
-https://github.com/Qi4j/qi4j-sdk
-
-in the libraries/lang-jruby directory.
diff --git a/libraries/lang-scala/build.gradle b/libraries/lang-scala/build.gradle
deleted file mode 100644
index 9ca2527..0000000
--- a/libraries/lang-scala/build.gradle
+++ /dev/null
@@ -1,44 +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.
- */
-
-description = "Apache Zest™ Scala Library allows for Mixins to be implemented in Scala."
-
-jar { manifest { name = "Apache Zest™ Library - Scripting - Scala" }}
-
-apply plugin: 'scala'
-
-tasks.withType(ScalaCompile) {
-    scalaCompileOptions.useAnt = true
-    scalaCompileOptions.fork = true
-    configure( scalaCompileOptions.forkOptions ) {
-        memoryMaximumSize = '1g'
-        jvmArgs = [ '-XX:MaxPermSize=512m' ]
-    }
-}
-
-dependencies {
-  compile project( ':org.qi4j.core:org.qi4j.core.bootstrap' )
-  compile libraries.scala
-
-  testCompile project( ':org.qi4j.core:org.qi4j.core.testsupport' )
-  testCompile project( ':org.qi4j.extensions:org.qi4j.extension.indexing-rdf' )
-
-  testRuntime project( ':org.qi4j.core:org.qi4j.core.runtime' )
-  testRuntime libraries.slf4j_simple
-}
diff --git a/libraries/lang-scala/dev-status.xml b/libraries/lang-scala/dev-status.xml
deleted file mode 100644
index 58fda09..0000000
--- a/libraries/lang-scala/dev-status.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
-  <status>
-    <!--none,early,beta,stable,mature-->
-    <codebase>beta</codebase>
-
-    <!-- none, brief, good, complete -->
-    <documentation>brief</documentation>
-
-    <!-- none, some, good, complete -->
-    <unittests>some</unittests>
-  </status>
-  <licenses>
-    <license>ALv2</license>
-  </licenses>
-</module>
\ No newline at end of file
diff --git a/libraries/lang-scala/src/docs/lang-scala.txt b/libraries/lang-scala/src/docs/lang-scala.txt
deleted file mode 100644
index c4b3a8f..0000000
--- a/libraries/lang-scala/src/docs/lang-scala.txt
+++ /dev/null
@@ -1,117 +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.
-///////////////////////////////////////////////////////////////
-
-[[lang-scala, Scala Library]]
-= Scala Support =
-
-[devstatus]
---------------
-source=libraries/lang-scala/dev-status.xml
---------------
-
-The Scala Support Library allows Fragments and Composites to be written as Scala traits.
-
-include::../../build/docs/buildinfo/artifact.txt[]
-
-The Scala Support Library is a Generic mixin class that implements  Composites by delegating to Scala traits.
-
-
-== Composition ==
-
-Example mixin declaration:
-[snippet,scala]
-----
-source=libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldMixin2.scala
-tag=mixin
-----
-
-Example composite declaration:
-[snippet,scala]
-----
-source=libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldComposite.scala
-tag=composite
-----
-
-Example typed concern:
-[snippet,scala]
-----
-source=libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloThereConcern.scala
-tag=typedconcern
-----
-
-Example generic concern with filter:
-[snippet,scala]
-----
-source=libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/ExclamationGenericConcern.scala
-tag=genericconcern
-----
-
-And the assembly code.
-Note that the `ScalaTraitMixin` must be added.
-[snippet,java]
-----
-source=libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldCompositeTest.java
-tag=composite
-----
-
-That pretty much covers the domain model part.
-Usage from Java is transparent, since it looks just like interfaces and classes.
-
-
-== Entity composites ==
-
-The following example separate between command interface (suggestions to change), events (after the fact), and data, so they are in three separate traits below.
-Only commands are called by client code.
-
-[snippet,scala]
-----
-source=libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/TestEntity.scala
-tag=entity
-----
-
-The `self` operator thing solves the `@This` injection requirements, although it doesn't do private injections (i.e. the Entity *has* to extend Events and Data for it to work).
-
-Everything is statically typed.
-
-And the corresponding assembly code:
-
-[snippet,java]
-----
-source=libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldCompositeTest.java
-tag=entity
-----
-
-
-== Services composites ==
-
-The following example is a pretty simple service written as a Scala trait:
-
-[snippet,scala]
-----
-source=libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/TestService.scala
-tag=service
-----
-
-And the corresponding assembly code:
-
-[snippet,java]
-----
-source=libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldCompositeTest.java
-tag=service
-----
diff --git a/libraries/lang-scala/src/main/java/org/qi4j/lang/scala/ScalaTraitMixin.java b/libraries/lang-scala/src/main/java/org/qi4j/lang/scala/ScalaTraitMixin.java
deleted file mode 100644
index 65912d9..0000000
--- a/libraries/lang-scala/src/main/java/org/qi4j/lang/scala/ScalaTraitMixin.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright 2011 Rickard Oberg.
- * Copyright 2012 Niclas Hedhman.
- *
- * Licensed  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.qi4j.lang.scala;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.HashMap;
-import java.util.Map;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.AppliesToFilter;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.composite.CompositeInstance;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.util.Classes;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-
-import static org.qi4j.api.util.Classes.interfacesOf;
-
-/**
- * Generic mixin that handles delegation to Scala trait implementations.
- */
-@AppliesTo( ScalaTraitMixin.TraitFilter.class )
-public class ScalaTraitMixin
-    implements InvocationHandler
-{
-    private static Map<Class<?>, Map<Method, InvocationHandler>> methods = new HashMap<>();
-
-    private Class<?> compositeType;
-
-    public ScalaTraitMixin( @This Composite composite )
-    {
-        compositeType = Qi4j.FUNCTION_DESCRIPTOR_FOR.map( composite ).primaryType();
-    }
-
-    @Override
-    public Object invoke( Object composite, Method method, Object[] args ) throws Throwable
-    {
-        InvocationHandler handler = methods.get( compositeType ).get( method );
-        return handler.invoke( composite, method, args );
-    }
-
-    public static class TraitFilter
-        implements AppliesToFilter
-    {
-        @Override
-        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
-        {
-            if( isScalaTrait( method.getDeclaringClass() ) )
-            {
-                // Service injection
-                if( method.getAnnotation( Service.class ) != null )
-                {
-                    if( method.getReturnType().equals( ServiceReference.class ) )
-                    {
-                        InvocationHandler handler = new InvocationHandler()
-                        {
-                            @Override
-                            public Object invoke( Object composite, Method method, Object[] objects ) throws Throwable
-                            {
-                                return ( (CompositeInstance) Proxy.getInvocationHandler( composite ) ).module()
-                                    .findService( method.getReturnType() );
-                            }
-                        };
-                        getHandlers( compositeType ).put( method, handler );
-                    }
-                    else
-                    {
-                        InvocationHandler handler = new InvocationHandler()
-                        {
-                            @Override
-                            public Object invoke( Object composite, Method method, Object[] objects ) throws Throwable
-                            {
-                                return ( (CompositeInstance) Proxy.getInvocationHandler( composite ) ).module()
-                                    .findService( method.getReturnType() ).get();
-                            }
-                        };
-                        getHandlers( compositeType ).put( method, handler );
-                    }
-                    return true;
-                }
-
-                // Map methods
-                final Class<?> declaringClass = method.getDeclaringClass();
-                Class traitClass = Iterables.last( Iterables.map( new Function<Class, Class>()
-                {
-                    Class current;
-
-                    @Override
-                    public Class map( Class aClass )
-                    {
-                        if( declaringClass.isAssignableFrom( aClass ) )
-                        {
-                            try
-                            {
-                                aClass.getClassLoader().loadClass( aClass.getName() + "$class" );
-
-                                if( current == null )
-                                {
-                                    current = aClass;
-                                }
-                                else
-                                {
-                                    current = current.isAssignableFrom( aClass ) ? aClass : current;
-                                }
-                            }
-                            catch( ClassNotFoundException e )
-                            {
-                                // Ignore - no trait implementation found
-                            }
-                        }
-
-                        return current;
-                    }
-                }, Iterables.map( Classes.RAW_CLASS, interfacesOf( compositeType ) ) ) );
-
-                if( traitClass == null )
-                {
-                    return false;
-                }
-
-                try
-                {
-                    Class traitMixin = traitClass.getClassLoader().loadClass( traitClass.getName() + "$class" );
-                    Class<?>[] methodParameterTypes = method.getParameterTypes();
-                    Class[] parameterTypes = new Class[1 + methodParameterTypes.length];
-                    parameterTypes[0] = traitClass;
-                    System.arraycopy( methodParameterTypes, 0, parameterTypes, 1, methodParameterTypes.length );
-                    final Method traitMethod = traitMixin.getMethod( method.getName(), parameterTypes );
-
-                    Map<Method,InvocationHandler> handlers = getHandlers( compositeType );
-
-                    handlers.put( method, new InvocationHandler()
-                    {
-                        @Override
-                        public Object invoke( Object composite, Method method, Object[] args ) throws Throwable
-                        {
-                            if( args != null )
-                            {
-                                Object[] params = new Object[args.length + 1];
-                                params[0] = composite;
-                                System.arraycopy( args, 0, params, 1, args.length );
-
-                                return traitMethod.invoke( null, params );
-                            }
-                            else
-                            {
-                                return traitMethod.invoke( null, composite );
-                            }
-                        }
-                    } );
-
-                    return true;
-                }
-                catch( ClassNotFoundException e )
-                {
-                    return false;
-                }
-                catch( NoSuchMethodException e )
-                {
-                    return false;
-                }
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        private boolean isScalaTrait( Class<?> declaringClass )
-        {
-            for( Annotation annotation : declaringClass.getAnnotations() )
-            {
-                if( annotation.annotationType().getSimpleName().equals( "ScalaSignature" ) )
-                {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        private Map<Method, InvocationHandler> getHandlers( Class<?> compositeType )
-        {
-            Map<Method,InvocationHandler> handlerMap = methods.get( compositeType );
-            if( handlerMap == null )
-            {
-                handlerMap = new HashMap<>();
-                methods.put( compositeType, handlerMap );
-            }
-            return handlerMap;
-        }
-    }
-}
diff --git a/libraries/lang-scala/src/main/java/org/qi4j/lang/scala/package.html b/libraries/lang-scala/src/main/java/org/qi4j/lang/scala/package.html
deleted file mode 100644
index bfba947..0000000
--- a/libraries/lang-scala/src/main/java/org/qi4j/lang/scala/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Scala Language Support Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/ExclamationGenericConcern.scala b/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/ExclamationGenericConcern.scala
deleted file mode 100644
index a87c91d..0000000
--- a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/ExclamationGenericConcern.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2011 Rickard Öberg
- * Licensed 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.qi4j.sample.scala
-
-import java.lang.reflect.Method
-import org.qi4j.api.concern.GenericConcern
-import org.qi4j.api.common.{AppliesToFilter, AppliesTo}
-
-/**
- * Add an exclamation mark to the returned string
- */
-// START SNIPPET: genericconcern
-@AppliesTo(Array(classOf[ StringFilter ]))
-class ExclamationGenericConcern
-  extends GenericConcern
-{
-  def invoke(composite: AnyRef, method: Method, args: Array[ AnyRef ] ) = next.invoke(composite, method, args) + "!"
-}
-
-class StringFilter
-  extends AppliesToFilter
-{
-  def appliesTo(method: Method, mixin: Class[ _ ], compositeType: Class[ _ ], fragmentClass: Class[ _ ] ) = method
-    .getReturnType
-    .equals(classOf[ String ])
-}
-// END SNIPPET: genericconcern
diff --git a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloThereConcern.scala b/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloThereConcern.scala
deleted file mode 100644
index 33e7981..0000000
--- a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloThereConcern.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2011 Rickard Öberg
- * Licensed 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.qi4j.sample.scala
-
-import org.qi4j.api.concern.ConcernOf
-
-// START SNIPPET: typedconcern
-class HelloThereConcern
-  extends ConcernOf[ HelloWorldMixin2 ] with HelloWorldMixin2
-{
-  override def sayHello(name: String ) = next.sayHello("there " + name)
-}
-// END SNIPPET: typedconcern
diff --git a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldComposite.scala b/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldComposite.scala
deleted file mode 100644
index 0a209d8..0000000
--- a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldComposite.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2011 Rickard Öberg
- * Licensed 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.qi4j.sample.scala
-
-import org.qi4j.api.composite.TransientComposite
-import org.qi4j.api.concern.Concerns
-
-// START SNIPPET: composite
-@Concerns(Array(classOf[ HelloThereConcern ]))
-trait HelloWorldComposite
-  extends TransientComposite with HelloWorldMixin with HelloWorldMixin2
-// END SNIPPET: composite
diff --git a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldComposite2.scala b/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldComposite2.scala
deleted file mode 100644
index 621143c..0000000
--- a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldComposite2.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright 2011 Rickard Öberg
- * Licensed 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.qi4j.sample.scala
-
-trait HelloWorldComposite2
-  extends HelloWorldComposite with HelloWorldMixin3
diff --git a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldCompositeTest.java b/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldCompositeTest.java
deleted file mode 100644
index e418bdd..0000000
--- a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldCompositeTest.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2011 Rickard Öberg
- * Licensed 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.qi4j.sample.scala;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.index.rdf.assembly.RdfMemoryStoreAssembler;
-import org.qi4j.lang.scala.ScalaTraitMixin;
-import org.qi4j.spi.query.IndexExporter;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.qi4j.api.query.QueryExpressions.eq;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-/**
- * TODO
- */
-public class HelloWorldCompositeTest
-{
-    @Test
-    public void testComposite()
-        throws Exception
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                // START SNIPPET: composite
-                module.transients( HelloWorldComposite.class, HelloWorldComposite2.class ).
-                    withMixins( ScalaTraitMixin.class ).
-                    withConcerns( ExclamationGenericConcern.class );
-                // END SNIPPET: composite
-            }
-        };
-
-        HelloWorldComposite composite = assembler.module().newTransient( HelloWorldComposite.class );
-        Assert.assertEquals( "Do stuff!", composite.doStuff() );
-        Assert.assertEquals( "Hello there World!", composite.sayHello( "World" ) );
-
-        try
-        {
-            composite.sayHello( "AReallyReallyLongName" );
-        }
-        catch( ConstraintViolationException e )
-        {
-            // Ok!
-        }
-
-        HelloWorldComposite2 composite2 = assembler.module().newTransient( HelloWorldComposite2.class );
-        Assert.assertEquals( "Do custom stuff!", composite2.doStuff() );
-    }
-
-    @Test
-    public void testEntity()
-        throws Exception
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                // START SNIPPET: entity
-                module.entities( TestEntity.class ).withMixins( ScalaTraitMixin.class );
-                // END SNIPPET: entity
-                // START SNIPPET: service
-                module.services( TestService.class ).withMixins( ScalaTraitMixin.class );
-                // END SNIPPET: service
-
-                new EntityTestAssembler().assemble( module );
-                new RdfMemoryStoreAssembler().assemble( module );
-            }
-        };
-
-        // Create and update Entity
-        UnitOfWork uow = assembler.module().newUnitOfWork();
-        try
-        {
-            Commands entity = uow.newEntity( Commands.class );
-            entity.updateFoo( "Foo" );
-
-            Data data = uow.get( Data.class, entity.toString() );
-
-            Assert.assertEquals( "FooFoo", data.foo().get() );
-        }
-        finally
-        {
-            uow.complete();
-        }
-
-        assembler.module().findService( IndexExporter.class ).get().exportReadableToStream( System.out );
-
-        // Find it
-        uow = assembler.module().newUnitOfWork();
-        try
-        {
-            Data data = uow.newQuery( assembler.module()
-                                          .newQueryBuilder( Data.class )
-                                          .where( eq( templateFor( Data.class ).foo(), "FooFoo" ) ) ).find();
-            Assert.assertEquals( "FooFoo", data.foo().get() );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-}
diff --git a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldMixin.scala b/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldMixin.scala
deleted file mode 100644
index e630f99..0000000
--- a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldMixin.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2011 Rickard Öberg
- * Licensed 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.qi4j.sample.scala
-
-trait HelloWorldMixin
-{
-  def doStuff(): String =
-  {
-    "Do stuff"
-  }
-}
\ No newline at end of file
diff --git a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldMixin2.scala b/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldMixin2.scala
deleted file mode 100644
index aeb8250..0000000
--- a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldMixin2.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2011 Rickard Öberg
- * Licensed 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.qi4j.sample.scala
-
-import org.qi4j.library.constraints.annotation.MaxLength
-
-// START SNIPPET: mixin
-trait HelloWorldMixin2
-{
-  def sayHello(@MaxLength(10) name: String ): String = "Hello " + name
-}
-// END SNIPPET: mixin
diff --git a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldMixin3.scala b/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldMixin3.scala
deleted file mode 100644
index 5b504bc..0000000
--- a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/HelloWorldMixin3.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2011 Rickard Öberg
- * Licensed 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.qi4j.sample.scala
-
-/**
- * TODO
- */
-
-trait HelloWorldMixin3
-  extends HelloWorldMixin
-{
-  override def doStuff() = "Do custom stuff"
-}
\ No newline at end of file
diff --git a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/TestEntity.scala b/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/TestEntity.scala
deleted file mode 100644
index 1440c8d..0000000
--- a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/TestEntity.scala
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2011 Rickard Öberg
- * Licensed 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.qi4j.sample.scala
-
-import org.qi4j.api.entity.EntityComposite
-import org.qi4j.api.injection.scope.Service
-import org.qi4j.api.common.UseDefaults
-import org.qi4j.api.property.Property
-
-/**
- * Test entity
- */
- // START SNIPPET: entity
-trait TestEntity
-  extends EntityComposite with Commands with Events with Data
-
-trait Commands
-{
-  self: Events =>
-  def updateFoo(newValue: String )
-  {
-    // Call "injected" service
-    val repeated = testService.repeat(newValue)
-
-    // Check here if input is ok
-    updatedFoo(repeated)
-  }
-
-  // Service injection - this is really a method call to the ServiceFinder of the composite
-  @Service
-  def testService: TestService
-}
-
-// Raw data of entity goes here
-trait Data
-{
-  @UseDefaults
-  def foo: Property[ String ]
-
-  // Define property
-  def foo_=(v: String ) { foo.set(v)  } // Operator overloading for =
-}
-
-trait Events
-{
-  self: Data =>
-  def updatedFoo(newValue: String )
-  {
-    // Register change by modifying state
-    foo = newValue
-  }
-}
-// END SNIPPET: entity
diff --git a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/TestService.scala b/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/TestService.scala
deleted file mode 100644
index 9c77111..0000000
--- a/libraries/lang-scala/src/test/scala/org/qi4j/sample/scala/TestService.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2011 Rickard Öberg
- * Licensed 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.qi4j.sample.scala
-
-import org.qi4j.api.service.ServiceComposite
-
-/**
- * Test service that repeats given string
- */
- // START SNIPPET: service
-trait TestService
-  extends ServiceComposite
-{
-  def repeat(input: String ): String = input + input
-}
-// END SNIPPET: service
diff --git a/libraries/locking/build.gradle b/libraries/locking/build.gradle
index b31c2a4..c9eb189 100644
--- a/libraries/locking/build.gradle
+++ b/libraries/locking/build.gradle
@@ -1,31 +1,35 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Locking Library provides lock management for methods."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - Locking" }}
+description = "Apache Polygene™ Locking Library provides lock management for methods."
+
+jar { manifest { name = "Apache Polygene™ Library - Locking" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.api"))
+  api polygene.core.api
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
+  runtimeOnly polygene.core.runtime
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/libraries/locking/dev-status.xml b/libraries/locking/dev-status.xml
index f549c99..97fd7ff 100644
--- a/libraries/locking/dev-status.xml
+++ b/libraries/locking/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/locking/src/docs/locking.txt b/libraries/locking/src/docs/locking.txt
index 6f1f9ee..9e100b9 100644
--- a/libraries/locking/src/docs/locking.txt
+++ b/libraries/locking/src/docs/locking.txt
@@ -61,7 +61,7 @@
 
 [snippet,java]
 ----
-source=libraries/locking/src/test/java/org/qi4j/library/locking/DocumentationSupport.java
+source=libraries/locking/src/test/java/org/apache/polygene/library/locking/DocumentationSupport.java
 tag=assembly
 ----
 
diff --git a/libraries/locking/src/main/java/org/apache/polygene/library/locking/LockMixin.java b/libraries/locking/src/main/java/org/apache/polygene/library/locking/LockMixin.java
new file mode 100644
index 0000000..941938b
--- /dev/null
+++ b/libraries/locking/src/main/java/org/apache/polygene/library/locking/LockMixin.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.locking;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+public class LockMixin
+    implements ReadWriteLock
+{
+    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+
+    @Override
+    public Lock readLock()
+    {
+        return lock.readLock();
+    }
+
+    @Override
+    public Lock writeLock()
+    {
+        return lock.writeLock();
+    }
+}
diff --git a/libraries/locking/src/main/java/org/apache/polygene/library/locking/LockingAbstractComposite.java b/libraries/locking/src/main/java/org/apache/polygene/library/locking/LockingAbstractComposite.java
new file mode 100644
index 0000000..52ae607
--- /dev/null
+++ b/libraries/locking/src/main/java/org/apache/polygene/library/locking/LockingAbstractComposite.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.locking;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.mixin.Mixins;
+
+/**
+ * JAVADOC
+ */
+@Concerns( { ReadLockConcern.class, WriteLockConcern.class } )
+@Mixins( LockMixin.class )
+public interface LockingAbstractComposite
+{
+}
diff --git a/libraries/locking/src/main/java/org/apache/polygene/library/locking/ReadLock.java b/libraries/locking/src/main/java/org/apache/polygene/library/locking/ReadLock.java
new file mode 100644
index 0000000..008121f
--- /dev/null
+++ b/libraries/locking/src/main/java/org/apache/polygene/library/locking/ReadLock.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.locking;
+
+import java.lang.annotation.*;
+
+/**
+ * Mark methods which should cause a read-lock with this annotation.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.METHOD } )
+@Documented
+@Inherited
+public @interface ReadLock
+{
+}
\ No newline at end of file
diff --git a/libraries/locking/src/main/java/org/apache/polygene/library/locking/ReadLockConcern.java b/libraries/locking/src/main/java/org/apache/polygene/library/locking/ReadLockConcern.java
new file mode 100644
index 0000000..059527a
--- /dev/null
+++ b/libraries/locking/src/main/java/org/apache/polygene/library/locking/ReadLockConcern.java
@@ -0,0 +1,91 @@
+/*
+ *  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.polygene.library.locking;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.injection.scope.This;
+
+/**
+ * Applies read-lock to Composite
+ */
+@AppliesTo( ReadLock.class )
+public class ReadLockConcern
+    extends ConcernOf<InvocationHandler>
+    implements InvocationHandler
+{
+    private
+    @This
+    ReadWriteLock lock;
+
+    @Override
+    public Object invoke( Object o, Method method, Object[] objects )
+        throws Throwable
+    {
+        Lock readLock = lock.readLock();
+        lock( readLock );
+        try
+        {
+            return next.invoke( o, method, objects );
+        }
+        finally
+        {
+            try
+            {
+                lock.readLock().unlock();
+            }
+            catch( Exception e )
+            {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * Fix for this bug:
+     * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6822370
+     *
+     * @param lock the lock to be acquired.
+     */
+    protected void lock( Lock lock )
+    {
+        while(true)
+        {
+            try
+            {
+                //noinspection StatementWithEmptyBody
+                while( !lock.tryLock( 1000, TimeUnit.MILLISECONDS ) )
+                {
+                    // On timeout, try again
+                }
+                return; // Finally got a lock
+            }
+            catch( InterruptedException e )
+            {
+                // Try again
+            }
+        }
+    }
+}
diff --git a/libraries/locking/src/main/java/org/apache/polygene/library/locking/WriteLock.java b/libraries/locking/src/main/java/org/apache/polygene/library/locking/WriteLock.java
new file mode 100644
index 0000000..5fbf741
--- /dev/null
+++ b/libraries/locking/src/main/java/org/apache/polygene/library/locking/WriteLock.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.locking;
+
+import java.lang.annotation.*;
+
+/**
+ * Mark methods which should cause a write-lock with this annotation.
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.METHOD } )
+@Documented
+@Inherited
+public @interface WriteLock
+{
+}
\ No newline at end of file
diff --git a/libraries/locking/src/main/java/org/apache/polygene/library/locking/WriteLockConcern.java b/libraries/locking/src/main/java/org/apache/polygene/library/locking/WriteLockConcern.java
new file mode 100644
index 0000000..53fd4e6
--- /dev/null
+++ b/libraries/locking/src/main/java/org/apache/polygene/library/locking/WriteLockConcern.java
@@ -0,0 +1,82 @@
+/*
+ *  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.polygene.library.locking;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.injection.scope.This;
+
+/**
+ * Applies write-lock to Composite
+ */
+@AppliesTo( WriteLock.class )
+public class WriteLockConcern
+    extends ConcernOf<InvocationHandler>
+    implements InvocationHandler
+{
+    private
+    @This
+    ReadWriteLock lock;
+
+    @Override
+    public Object invoke( Object o, Method method, Object[] objects )
+        throws Throwable
+    {
+        Lock writeLock = lock.writeLock();
+        lock(writeLock);
+        try
+        {
+            return next.invoke( o, method, objects );
+        }
+        finally
+        {
+            writeLock.unlock();
+        }
+    }
+
+    /**
+     * Fix for this bug:
+     * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6822370
+     */
+    protected void lock(Lock lock)
+    {
+        while(true)
+        {
+            try
+            {
+                //noinspection StatementWithEmptyBody
+                while( !lock.tryLock( 1000, TimeUnit.MILLISECONDS ) )
+                {
+                    // On timeout, try again
+                }
+                return; // Finally got a lock
+            }
+            catch( InterruptedException e )
+            {
+                // Try again
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries/locking/src/main/java/org/apache/polygene/library/locking/package.html b/libraries/locking/src/main/java/org/apache/polygene/library/locking/package.html
new file mode 100644
index 0000000..6e5359b
--- /dev/null
+++ b/libraries/locking/src/main/java/org/apache/polygene/library/locking/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Locking Library.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/locking/src/main/java/org/qi4j/library/locking/LockMixin.java b/libraries/locking/src/main/java/org/qi4j/library/locking/LockMixin.java
deleted file mode 100644
index a59bcc7..0000000
--- a/libraries/locking/src/main/java/org/qi4j/library/locking/LockMixin.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.locking;
-
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-public class LockMixin
-    implements ReadWriteLock
-{
-    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
-
-    @Override
-    public Lock readLock()
-    {
-        return lock.readLock();
-    }
-
-    @Override
-    public Lock writeLock()
-    {
-        return lock.writeLock();
-    }
-}
diff --git a/libraries/locking/src/main/java/org/qi4j/library/locking/LockingAbstractComposite.java b/libraries/locking/src/main/java/org/qi4j/library/locking/LockingAbstractComposite.java
deleted file mode 100644
index 0ff188f..0000000
--- a/libraries/locking/src/main/java/org/qi4j/library/locking/LockingAbstractComposite.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2007-2011 Rickard Oberg.
- * Copyright 2007-2012 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.locking;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-
-/**
- * JAVADOC
- */
-@Concerns( { ReadLockConcern.class, WriteLockConcern.class } )
-@Mixins( LockMixin.class )
-public interface LockingAbstractComposite
-{
-}
diff --git a/libraries/locking/src/main/java/org/qi4j/library/locking/ReadLock.java b/libraries/locking/src/main/java/org/qi4j/library/locking/ReadLock.java
deleted file mode 100644
index cbddbf4..0000000
--- a/libraries/locking/src/main/java/org/qi4j/library/locking/ReadLock.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg
- * Licensed 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.qi4j.library.locking;
-
-import java.lang.annotation.*;
-
-/**
- * Mark methods which should cause a read-lock with this annotation.
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.METHOD } )
-@Documented
-@Inherited
-public @interface ReadLock
-{
-}
\ No newline at end of file
diff --git a/libraries/locking/src/main/java/org/qi4j/library/locking/ReadLockConcern.java b/libraries/locking/src/main/java/org/qi4j/library/locking/ReadLockConcern.java
deleted file mode 100644
index 39e8a80..0000000
--- a/libraries/locking/src/main/java/org/qi4j/library/locking/ReadLockConcern.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2007-2011 Rickard Oberg.
- * Copyright 2007-2012 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.locking;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.injection.scope.This;
-
-/**
- * Applies read-lock to Composite
- */
-@AppliesTo( ReadLock.class )
-public class ReadLockConcern
-    extends ConcernOf<InvocationHandler>
-    implements InvocationHandler
-{
-    private
-    @This
-    ReadWriteLock lock;
-
-    @Override
-    public Object invoke( Object o, Method method, Object[] objects )
-        throws Throwable
-    {
-        Lock readLock = lock.readLock();
-        lock( readLock );
-        try
-        {
-            return next.invoke( o, method, objects );
-        }
-        finally
-        {
-            try
-            {
-                lock.readLock().unlock();
-            }
-            catch( Exception e )
-            {
-                e.printStackTrace();
-            }
-        }
-    }
-
-    /**
-     * Fix for this bug:
-     * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6822370
-     *
-     * @param lock the lock to be acquired.
-     */
-    protected void lock( Lock lock )
-    {
-        while(true)
-        {
-            try
-            {
-                //noinspection StatementWithEmptyBody
-                while( !lock.tryLock( 1000, TimeUnit.MILLISECONDS ) )
-                {
-                    // On timeout, try again
-                }
-                return; // Finally got a lock
-            }
-            catch( InterruptedException e )
-            {
-                // Try again
-            }
-        }
-    }
-}
diff --git a/libraries/locking/src/main/java/org/qi4j/library/locking/WriteLock.java b/libraries/locking/src/main/java/org/qi4j/library/locking/WriteLock.java
deleted file mode 100644
index 0d15e42..0000000
--- a/libraries/locking/src/main/java/org/qi4j/library/locking/WriteLock.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg
- * Licensed 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.qi4j.library.locking;
-
-import java.lang.annotation.*;
-
-/**
- * Mark methods which should cause a write-lock with this annotation.
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.METHOD } )
-@Documented
-@Inherited
-public @interface WriteLock
-{
-}
\ No newline at end of file
diff --git a/libraries/locking/src/main/java/org/qi4j/library/locking/WriteLockConcern.java b/libraries/locking/src/main/java/org/qi4j/library/locking/WriteLockConcern.java
deleted file mode 100644
index f391667..0000000
--- a/libraries/locking/src/main/java/org/qi4j/library/locking/WriteLockConcern.java
+++ /dev/null
@@ -1,81 +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.qi4j.library.locking;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.injection.scope.This;
-
-/**
- * Applies write-lock to Composite
- */
-@AppliesTo( WriteLock.class )
-public class WriteLockConcern
-    extends ConcernOf<InvocationHandler>
-    implements InvocationHandler
-{
-    private
-    @This
-    ReadWriteLock lock;
-
-    @Override
-    public Object invoke( Object o, Method method, Object[] objects )
-        throws Throwable
-    {
-        Lock writeLock = lock.writeLock();
-        lock(writeLock);
-        try
-        {
-            return next.invoke( o, method, objects );
-        }
-        finally
-        {
-            writeLock.unlock();
-        }
-    }
-
-    /**
-     * Fix for this bug:
-     * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6822370
-     */
-    protected void lock(Lock lock)
-    {
-        while(true)
-        {
-            try
-            {
-                //noinspection StatementWithEmptyBody
-                while( !lock.tryLock( 1000, TimeUnit.MILLISECONDS ) )
-                {
-                    // On timeout, try again
-                }
-                return; // Finally got a lock
-            }
-            catch( InterruptedException e )
-            {
-                // Try again
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/libraries/locking/src/main/java/org/qi4j/library/locking/package.html b/libraries/locking/src/main/java/org/qi4j/library/locking/package.html
deleted file mode 100644
index 8084dca..0000000
--- a/libraries/locking/src/main/java/org/qi4j/library/locking/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Locking Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/locking/src/test/java/org/apache/polygene/library/locking/DocumentationSupport.java b/libraries/locking/src/test/java/org/apache/polygene/library/locking/DocumentationSupport.java
new file mode 100644
index 0000000..9fba663
--- /dev/null
+++ b/libraries/locking/src/test/java/org/apache/polygene/library/locking/DocumentationSupport.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.locking;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+
+public class DocumentationSupport
+{
+// START SNIPPET: assembly
+    public class MyModuleAssembler
+        implements ModuleAssembler{
+
+        @Override
+        public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+            throws AssemblyException
+        {
+            module.services( MyService.class ).withTypes( LockingAbstractComposite.class );
+            return module;
+        }
+    }
+// END SNIPPET: assembly
+    public interface MyService {}
+}
diff --git a/libraries/locking/src/test/java/org/apache/polygene/library/locking/LockingTest.java b/libraries/locking/src/test/java/org/apache/polygene/library/locking/LockingTest.java
new file mode 100644
index 0000000..6ed836e
--- /dev/null
+++ b/libraries/locking/src/test/java/org/apache/polygene/library/locking/LockingTest.java
@@ -0,0 +1,132 @@
+/*
+ *  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.polygene.library.locking;
+
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * JAVADOC
+ */
+public class LockingTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( TestComposite.class );
+    }
+
+
+    @Test
+    public void testLocking()
+        throws InterruptedException
+    {
+        final TestComposite composite = transientBuilderFactory.newTransient( TestComposite.class );
+
+        ExecutorService executor = Executors.newFixedThreadPool( 2 );
+
+        executor.submit( new Runnable()
+        {
+            public void run()
+            {
+                System.out.println("Wait");
+                try
+                {
+                    composite.readAndWait();
+                    System.out.println("Wait done");
+                }
+                catch( Throwable e )
+                {
+                    e.printStackTrace();
+                }
+            }
+        });
+
+        executor.submit( new Runnable()
+        {
+            public void run()
+            {
+                System.out.println("Notify");
+                try
+                {
+                    composite.readAndNotify();
+                }
+                catch( Throwable e )
+                {
+                    e.printStackTrace();
+                }
+                System.out.println("Notified");
+            }
+        });
+
+        executor.shutdown();
+        System.out.println("Finished: "+executor.awaitTermination( 5000, TimeUnit.MILLISECONDS ));
+    }
+
+    @Mixins( TestComposite.Mixin.class)
+    public interface TestComposite
+        extends TransientComposite, LockingAbstractComposite
+    {
+        void writeAndWait();
+
+        void readAndWait()
+            throws InterruptedException;
+
+        void readAndNotify();
+
+        abstract class Mixin
+            implements TestComposite
+        {
+            @ReadLock
+            public void readAndNotify()
+            {
+                synchronized( this )
+                {
+                    this.notifyAll();
+                }
+            }
+
+            @ReadLock
+            public void readAndWait()
+                throws InterruptedException
+            {
+                synchronized( this )
+                {
+                    this.wait();
+                }
+            }
+
+            @WriteLock
+            public void writeAndWait()
+            {
+            }
+        }
+    }
+}
diff --git a/libraries/locking/src/test/java/org/qi4j/library/locking/DocumentationSupport.java b/libraries/locking/src/test/java/org/qi4j/library/locking/DocumentationSupport.java
deleted file mode 100644
index c227bb7..0000000
--- a/libraries/locking/src/test/java/org/qi4j/library/locking/DocumentationSupport.java
+++ /dev/null
@@ -1,42 +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.qi4j.library.locking;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.layered.ModuleAssembler;
-
-public class DocumentationSupport
-{
-// START SNIPPET: assembly
-    public class MyModuleAssembler
-        implements ModuleAssembler{
-
-        @Override
-        public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
-            throws AssemblyException
-        {
-            module.services( MyService.class ).withTypes( LockingAbstractComposite.class );
-            return module;
-        }
-    }
-// END SNIPPET: assembly
-    public interface MyService {}
-}
diff --git a/libraries/locking/src/test/java/org/qi4j/library/locking/LockingTest.java b/libraries/locking/src/test/java/org/qi4j/library/locking/LockingTest.java
deleted file mode 100644
index 05973f7..0000000
--- a/libraries/locking/src/test/java/org/qi4j/library/locking/LockingTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.locking;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-/**
- * JAVADOC
- */
-public class LockingTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( TestComposite.class );
-    }
-
-
-    @Test
-    public void testLocking()
-        throws InterruptedException
-    {
-        final TestComposite composite = module.newTransient( TestComposite.class );
-
-        ExecutorService executor = Executors.newFixedThreadPool( 2 );
-
-        executor.submit( new Runnable()
-        {
-            public void run()
-            {
-                System.out.println("Wait");
-                try
-                {
-                    composite.readAndWait();
-                    System.out.println("Wait done");
-                }
-                catch( Throwable e )
-                {
-                    e.printStackTrace();
-                }
-            }
-        });
-
-        executor.submit( new Runnable()
-        {
-            public void run()
-            {
-                System.out.println("Notify");
-                try
-                {
-                    composite.readAndNotify();
-                }
-                catch( Throwable e )
-                {
-                    e.printStackTrace();
-                }
-                System.out.println("Notified");
-            }
-        });
-
-        executor.shutdown();
-        System.out.println("Finished: "+executor.awaitTermination( 5000, TimeUnit.MILLISECONDS ));
-    }
-
-    @Mixins( TestComposite.Mixin.class)
-    public interface TestComposite
-        extends TransientComposite, LockingAbstractComposite
-    {
-        void writeAndWait();
-
-        void readAndWait()
-            throws InterruptedException;
-
-        void readAndNotify();
-
-        abstract class Mixin
-            implements TestComposite
-        {
-            @ReadLock
-            public void readAndNotify()
-            {
-                synchronized( this )
-                {
-                    this.notifyAll();
-                }
-            }
-
-            @ReadLock
-            public void readAndWait()
-                throws InterruptedException
-            {
-                synchronized( this )
-                {
-                    this.wait();
-                }
-            }
-
-            @WriteLock
-            public void writeAndWait()
-            {
-            }
-        }
-    }
-}
diff --git a/libraries/logging/build.gradle b/libraries/logging/build.gradle
index f2dde7e..18d1a67 100644
--- a/libraries/logging/build.gradle
+++ b/libraries/logging/build.gradle
@@ -1,33 +1,36 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Logging Library provides an advanced logging framework which separates trace, debug and log systems."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - Logging" }}
+description = "Apache Polygene™ Logging Library provides an advanced logging framework which separates trace, debug and log systems."
+
+jar { manifest { name = "Apache Polygene™ Library - Logging" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile( project( ':org.qi4j.libraries:org.qi4j.library.constraints' ))
+  api polygene.core.bootstrap
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-  testCompile(project(":org.qi4j.extensions:org.qi4j.extension.indexing-rdf"))
+  implementation polygene.library( 'constraints' )
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  testImplementation polygene.core.testsupport
+  testImplementation polygene.extension( 'indexing-rdf' )
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/libraries/logging/dev-status.xml b/libraries/logging/dev-status.xml
index bdf00e7..0914c52 100644
--- a/libraries/logging/dev-status.xml
+++ b/libraries/logging/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/logging/src/docs/logging.txt b/libraries/logging/src/docs/logging.txt
index ed7f6b6..3fc862f 100644
--- a/libraries/logging/src/docs/logging.txt
+++ b/libraries/logging/src/docs/logging.txt
@@ -1,16 +1,19 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
+ *  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
  *
- * Licensed 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.
+ *       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.
 //////////////////////
 
 [[library-logging, Logging Library]]
@@ -21,7 +24,7 @@
 source=libraries/logging/dev-status.xml
 --------------
 
-First of all, Zest™ is taking a fresh look at all things that we take for granted. Logging is one such thing.
+First of all, Polygene™ is taking a fresh look at all things that we take for granted. Logging is one such thing.
 
 It should (but is not) obvious that Logging are used for three very distinct purposes, and in our opinion the concepts
 are not related and should not be abstracted in the same fashion, as has been the norm in Log4j, JDK logging, Commons
@@ -58,7 +61,7 @@
 
 [snippet,java]
 -----------
-source=libraries/logging/src/test/java/org/qi4j/logging/docsupport/LoggingDocs.java
+source=libraries/logging/src/test/java/org/apache/polygene/library/logging/docsupport/LoggingDocs.java
 tag=logging1
 -----------
 
@@ -66,7 +69,7 @@
 
 [snippet,java]
 -----------
-source=libraries/logging/src/test/java/org/qi4j/logging/docsupport/LoggingDocs.java
+source=libraries/logging/src/test/java/org/apache/polygene/library/logging/docsupport/LoggingDocs.java
 tag=logging2
 -----------
 
@@ -80,7 +83,7 @@
 == Tracing ==
 
 Tracing is the process of tracking all the methods that has been called. There are two levels of tracing available in
-Zest. Either Trace All or trace where a annotation has been given.
+Polygene. Either Trace All or trace where a annotation has been given.
 
 If the TraceAllConcern is added to a composite, and there is a TraceService visible, then all method calls into that
 composite is traced.
@@ -90,7 +93,7 @@
 
 [snippet,java]
 -----------
-source=libraries/logging/src/test/java/org/qi4j/logging/docsupport/LoggingDocs.java
+source=libraries/logging/src/test/java/org/apache/polygene/library/logging/docsupport/LoggingDocs.java
 tag=logging3
 -----------
 
@@ -107,6 +110,6 @@
 
 [snippet,java]
 -----------
-source=libraries/logging/src/test/java/org/qi4j/logging/docsupport/LoggingDocs.java
+source=libraries/logging/src/test/java/org/apache/polygene/library/logging/docsupport/LoggingDocs.java
 tag=logging4
 -----------
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/Debug.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/Debug.java
new file mode 100644
index 0000000..77fcf70
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/Debug.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.library.logging.debug;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.mixin.NoopMixin;
+
+@Concerns( DebugConcern.class )
+@Mixins( NoopMixin.class )
+public interface Debug
+{
+    int OFF = Integer.MIN_VALUE;
+    int LOWLOW = -100;
+    int LOW = -50;
+    int NORMAL = 0;
+    int HIGH = 50;
+    int HIGHHIGH = 100;
+
+    Integer debugLevel();
+
+    void debug( int level, String message );
+
+    void debug( int level, String message, Object param1 );
+
+    void debug( int level, String message, Object param1, Object param2 );
+
+    void debug( int level, String message, Object... params );
+
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/DebugConcern.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/DebugConcern.java
new file mode 100644
index 0000000..261c640
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/DebugConcern.java
@@ -0,0 +1,100 @@
+/*
+ *  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.polygene.library.logging.debug;
+
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.library.logging.debug.service.DebuggingService;
+
+public class DebugConcern
+    implements Debug
+{
+    @Structure private PolygeneAPI api;
+    @Optional @Service private DebuggingService loggingService;
+    @This private Composite composite;
+
+    @Override
+    public Integer debugLevel()
+    {
+        if( loggingService != null )
+        {
+            return loggingService.debugLevel();
+        }
+        return OFF;
+    }
+
+    @Override
+    public void debug( int priority, String message )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        if( priority >= loggingService.debugLevel() )
+        {
+            Composite derefed = api.dereference( composite );
+            loggingService.debug( derefed, message );
+        }
+    }
+
+    @Override
+    public void debug( int priority, String message, Object param1 )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        if( priority >= loggingService.debugLevel() )
+        {
+            loggingService.debug( api.dereference( composite ), message, param1 );
+        }
+    }
+
+    @Override
+    public void debug( int priority, String message, Object param1, Object param2 )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        if( priority >= loggingService.debugLevel() )
+        {
+            loggingService.debug( api.dereference( composite ), message, param1, param2 );
+        }
+    }
+
+    @Override
+    public void debug( int priority, String message, Object... params )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        if( priority >= loggingService.debugLevel() )
+        {
+            loggingService.debug( api.dereference( composite ), message, params );
+        }
+    }
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/package.html b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/package.html
new file mode 100644
index 0000000..08688ad
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Debug Logging.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/records/CompositeDebugRecordEntity.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/records/CompositeDebugRecordEntity.java
new file mode 100644
index 0000000..082eb19
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/records/CompositeDebugRecordEntity.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.logging.debug.records;
+
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.property.Property;
+
+public interface CompositeDebugRecordEntity extends DebugRecord
+{
+    Property<Composite> source();
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/records/DebugRecord.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/records/DebugRecord.java
new file mode 100644
index 0000000..e776cf3
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/records/DebugRecord.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.library.logging.debug.records;
+
+import java.time.Instant;
+import java.util.List;
+import org.apache.polygene.api.property.Property;
+
+public interface DebugRecord
+{
+    Property<String> message();
+
+    Property<String> compositeTypeName();
+
+    Property<String> threadName();
+
+    Property<Instant> time();
+
+    Property<List<Object>> parameters();
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/records/EntityDebugRecordEntity.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/records/EntityDebugRecordEntity.java
new file mode 100644
index 0000000..e14d28b
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/records/EntityDebugRecordEntity.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.logging.debug.records;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.entity.EntityComposite;
+
+public interface EntityDebugRecordEntity extends DebugRecord
+{
+    Association<EntityComposite> source();
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/records/ServiceDebugRecordEntity.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/records/ServiceDebugRecordEntity.java
new file mode 100644
index 0000000..527236a
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/records/ServiceDebugRecordEntity.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.library.logging.debug.records;
+
+import org.apache.polygene.api.property.Property;
+
+public interface ServiceDebugRecordEntity extends DebugRecord
+{
+    Property<String> source();
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/records/package.html b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/records/package.html
new file mode 100644
index 0000000..ee70e33
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/records/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Debug Logging Records.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/DebugOnConsoleSideEffect.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/DebugOnConsoleSideEffect.java
new file mode 100644
index 0000000..fb2e408
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/DebugOnConsoleSideEffect.java
@@ -0,0 +1,111 @@
+/*
+ *  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.polygene.library.logging.debug.service;
+
+import java.io.PrintStream;
+import java.lang.reflect.Method;
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.injection.scope.Invocation;
+import org.apache.polygene.api.sideeffect.SideEffectOf;
+import org.apache.polygene.library.logging.debug.Debug;
+import org.apache.polygene.library.logging.log.service.LoggingService;
+
+/**
+ * The DebugOnConsoleSideEffect is just a temporary solution for logging output, until a more
+ * robust framework has been designed.
+ */
+public class DebugOnConsoleSideEffect extends SideEffectOf<LoggingService>
+    implements DebuggingService
+{
+    private static PrintStream OUT = System.err;
+
+    private final ResourceBundle bundle;
+
+    public DebugOnConsoleSideEffect( @Invocation Method thisMethod )
+    {
+        bundle = ResourceBundle.getBundle( thisMethod.getDeclaringClass().getName() );
+    }
+
+    @Override
+    public int debugLevel()
+    {
+        return Debug.OFF;
+    }
+
+    @Override
+    public void debug( Composite composite, String message )
+    {
+        String localized = bundle.getString( message );
+        OUT.println( "DEBUG:" + getCompositeName( composite ) + ": " + localized );
+    }
+
+    private String getCompositeName( Composite composite )
+    {
+        return PolygeneAPI.FUNCTION_DESCRIPTOR_FOR.apply( composite ).types().findFirst().get().getName();
+    }
+
+    @Override
+    public void debug( Composite composite, String message, Object param1 )
+    {
+        String localized = bundle.getString( message );
+        String formatted = MessageFormat.format( localized, param1 );
+        OUT.println( "DEBUG:" + getCompositeName( composite ) + ": " + formatted );
+        if( param1 instanceof Throwable )
+        {
+            handleException( (Throwable) param1 );
+        }
+    }
+
+    @Override
+    public void debug( Composite composite, String message, Object param1, Object param2 )
+    {
+        String localized = bundle.getString( message );
+        String formatted = MessageFormat.format( localized, param1, param2 );
+        OUT.println( "DEBUG:" + getCompositeName( composite ) + ": " + formatted );
+        if( param1 instanceof Throwable )
+        {
+            handleException( (Throwable) param1 );
+        }
+    }
+
+    @Override
+    public void debug( Composite composite, String message, Object... params )
+    {
+        String localized = bundle.getString( message );
+        String formatted = MessageFormat.format( localized, (Object) params );
+        OUT.println( "DEBUG:" + getCompositeName( composite ) + ": " + formatted );
+        if( params[ 0 ] instanceof Throwable )
+        {
+            handleException( (Throwable) params[ 0 ] );
+        }
+    }
+
+    private void handleException( Throwable exception )
+    {
+        if( exception != null )
+        {
+            exception.printStackTrace( OUT );
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/DebugServiceConfiguration.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/DebugServiceConfiguration.java
new file mode 100644
index 0000000..b1dc920
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/DebugServiceConfiguration.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.library.logging.debug.service;
+
+import org.apache.polygene.api.property.Property;
+
+public interface DebugServiceConfiguration
+{
+    Property<Integer> debugLevel();
+}
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/DebuggingService.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/DebuggingService.java
new file mode 100644
index 0000000..9828450
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/DebuggingService.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.logging.debug.service;
+
+import org.apache.polygene.api.composite.Composite;
+
+public interface DebuggingService
+{
+    int debugLevel();
+
+    void debug( Composite composite, String message );
+
+    void debug( Composite composite, String message, Object param1 );
+
+    void debug( Composite composite, String message, Object param1, Object param2 );
+
+    void debug( Composite composite, String message, Object... params );
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/DebuggingServiceComposite.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/DebuggingServiceComposite.java
new file mode 100644
index 0000000..2143b06
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/DebuggingServiceComposite.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.logging.debug.service;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.sideeffect.SideEffects;
+import org.apache.polygene.library.logging.log.service.LogOnConsoleSideEffect;
+
+@SideEffects( { LogOnConsoleSideEffect.class } )
+@Mixins( { DebuggingServiceMixin.class } )
+public interface DebuggingServiceComposite extends DebuggingService
+{
+}
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/DebuggingServiceMixin.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/DebuggingServiceMixin.java
new file mode 100644
index 0000000..02aca0f
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/DebuggingServiceMixin.java
@@ -0,0 +1,180 @@
+/*
+ *  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.polygene.library.logging.debug.service;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.time.SystemTime;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.library.logging.debug.records.CompositeDebugRecordEntity;
+import org.apache.polygene.library.logging.debug.records.DebugRecord;
+import org.apache.polygene.library.logging.debug.records.EntityDebugRecordEntity;
+import org.apache.polygene.library.logging.debug.records.ServiceDebugRecordEntity;
+
+public class DebuggingServiceMixin
+    implements DebuggingService
+{
+    @Structure private UnitOfWorkFactory uowf;
+    @This private Configuration<DebugServiceConfiguration> configuration;
+
+    @Override
+    public int debugLevel()
+    {
+        return configuration.get().debugLevel().get();
+    }
+
+    @Override
+    public void debug( Composite composite, String message )
+    {
+        UnitOfWork uow = uowf.newUnitOfWork();
+        try
+        {
+            List<Object> paramsList = new ArrayList<>();
+            createDebugRecord( uow, composite, message, paramsList );
+            uow.complete();
+        }
+        catch( ConcurrentEntityModificationException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+        catch( UnitOfWorkCompletionException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+    }
+
+    @Override
+    public void debug( Composite composite, String message, Object param1 )
+    {
+        UnitOfWork uow = uowf.newUnitOfWork();
+        try
+        {
+            List<Object> paramsList = new ArrayList<>();
+            paramsList.add( param1 );
+            createDebugRecord( uow, composite, message, paramsList );
+            uow.complete();
+        }
+        catch( ConcurrentEntityModificationException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+        catch( UnitOfWorkCompletionException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+    }
+
+    @Override
+    public void debug( Composite composite, String message, Object param1, Object param2 )
+    {
+        UnitOfWork uow = uowf.newUnitOfWork();
+        try
+        {
+            List<Object> paramsList = new ArrayList<>();
+            paramsList.add( param1 );
+            paramsList.add( param2 );
+            createDebugRecord( uow, composite, message, paramsList );
+            uow.complete();
+        }
+        catch( ConcurrentEntityModificationException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+        catch( UnitOfWorkCompletionException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+    }
+
+    @Override
+    public void debug( Composite composite, String message, Object... params )
+    {
+        UnitOfWork uow = uowf.newUnitOfWork();
+        try
+        {
+            List<Object> paramsList = new ArrayList<>( Arrays.asList( params ) );
+            createDebugRecord( uow, composite, message, paramsList );
+            uow.complete();
+        }
+        catch( ConcurrentEntityModificationException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+        catch( UnitOfWorkCompletionException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+    }
+
+    private void createDebugRecord( UnitOfWork uow, Composite composite, String message, List<Object> params )
+    {
+        if( composite instanceof ServiceComposite )
+        {
+            EntityBuilder<ServiceDebugRecordEntity> builder = uow.newEntityBuilder( ServiceDebugRecordEntity.class );
+            ServiceDebugRecordEntity state = builder.instance();
+            setStandardStuff( composite, message, state, params );
+            state.source().set( ( (ServiceComposite) composite ).identity().get().toString() );
+            ServiceDebugRecordEntity slr = builder.newInstance();
+        }
+        else if( composite instanceof EntityComposite )
+        {
+            EntityBuilder<EntityDebugRecordEntity> builder = uow.newEntityBuilder( EntityDebugRecordEntity.class );
+            EntityDebugRecordEntity state = builder.instance();
+            setStandardStuff( composite, message, state, params );
+            state.source().set( (EntityComposite) composite );
+            EntityDebugRecordEntity elr = builder.newInstance();
+        }
+        else
+        {
+            EntityBuilder<CompositeDebugRecordEntity> builder = uow.newEntityBuilder( CompositeDebugRecordEntity.class );
+            CompositeDebugRecordEntity state = builder.instance();
+            setStandardStuff( composite, message, state, params );
+            state.source().set( composite );
+            CompositeDebugRecordEntity clr = builder.newInstance();
+        }
+    }
+
+    private void setStandardStuff( Composite composite, String message, DebugRecord state, List<Object> params )
+    {
+        state.time().set( SystemTime.now() );
+        state.message().set( message );
+        state.compositeTypeName().set( getCompositeName( composite ) );
+        state.threadName().set( Thread.currentThread().getName() );
+        state.parameters().set( params );
+    }
+
+    private String getCompositeName( Composite composite )
+    {
+        return PolygeneAPI.FUNCTION_DESCRIPTOR_FOR.apply( composite ).types().findFirst().get().getName();
+    }
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/package.html b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/package.html
new file mode 100644
index 0000000..c986a18
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/debug/service/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Debug Logging Service.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/CategoryLog.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/CategoryLog.java
new file mode 100644
index 0000000..257dc25
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/CategoryLog.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.library.logging.log;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.mixin.Mixins;
+
+@Concerns( { CategoryLogConcern.class } )
+@Mixins( { CategoryLogMixin.class } )
+public interface CategoryLog
+{
+    void info( String category, String message );
+
+    void info( String category, String message, Object param1 );
+
+    void info( String category, String message, Object param1, Object param2 );
+
+    void info( String category, String message, Object... params );
+
+    void warning( String category, String message );
+
+    void warning( String category, String message, Object param1 );
+
+    void warning( String category, String message, Object param1, Object param2 );
+
+    void warning( String category, String message, Object... params );
+
+    void error( String category, String message );
+
+    void error( String category, String message, Object param1 );
+
+    void error( String category, String message, Object param1, Object param2 );
+
+    void error( String category, String message, Object... params );
+
+
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/CategoryLogConcern.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/CategoryLogConcern.java
new file mode 100644
index 0000000..5fe20d2
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/CategoryLogConcern.java
@@ -0,0 +1,161 @@
+/*
+ *  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.polygene.library.logging.log;
+
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.library.logging.log.service.LoggingService;
+
+public final class CategoryLogConcern
+    implements CategoryLog
+{
+    @Structure private PolygeneAPI api;
+    @Optional @Service private LoggingService loggingService;
+    @This private Composite composite;
+
+    public CategoryLogConcern( @Structure TransientBuilderFactory cbf )
+    {
+    }
+
+    @Override
+    public void info( String category, String message )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.INFO, api.dereference( composite ), category, message );
+    }
+
+    @Override
+    public void info( String category, String message, Object param1 )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, param1 );
+    }
+
+    @Override
+    public void info( String category, String message, Object param1, Object param2 )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, param1, param2 );
+    }
+
+    @Override
+    public void info( String category, String message, Object... params )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, params );
+    }
+
+    @Override
+    public void warning( String category, String message )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.WARNING, api.dereference( composite ), category, message );
+    }
+
+    @Override
+    public void warning( String category, String message, Object param1 )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.WARNING, api.dereference( composite ), category, message, param1 );
+    }
+
+    @Override
+    public void warning( String category, String message, Object param1, Object param2 )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.WARNING, api.dereference( composite ), category, message, param1, param2 );
+    }
+
+    @Override
+    public void warning( String category, String message, Object... params )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.WARNING, api.dereference( composite ), category, message, params );
+    }
+
+    @Override
+    public void error( String category, String message )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.ERROR, api.dereference( composite ), category, message );
+    }
+
+    @Override
+    public void error( String category, String message, Object param1 )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.ERROR, api.dereference( composite ), category, message, param1 );
+    }
+
+    @Override
+    public void error( String category, String message, Object param1, Object param2 )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.ERROR, api.dereference( composite ), category, message, param1, param2 );
+    }
+
+    @Override
+    public void error( String category, String message, Object... params )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.ERROR, api.dereference( composite ), category, message, params );
+    }
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/CategoryLogMixin.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/CategoryLogMixin.java
new file mode 100644
index 0000000..a8a2171
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/CategoryLogMixin.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.library.logging.log;
+
+public class CategoryLogMixin
+    implements CategoryLog
+{
+    @Override
+    public void info( String category, String message )
+    {
+    }
+
+    @Override
+    public void info( String category, String message, Object param1 )
+    {
+    }
+
+    @Override
+    public void info( String category, String message, Object param1, Object param2 )
+    {
+    }
+
+    @Override
+    public void info( String category, String message, Object... params )
+    {
+    }
+
+    @Override
+    public void warning( String category, String message )
+    {
+    }
+
+    @Override
+    public void warning( String category, String message, Object param1 )
+    {
+    }
+
+    @Override
+    public void warning( String category, String message, Object param1, Object param2 )
+    {
+    }
+
+    @Override
+    public void warning( String category, String message, Object... params )
+    {
+    }
+
+    @Override
+    public void error( String category, String message )
+    {
+    }
+
+    @Override
+    public void error( String category, String message, Object param1 )
+    {
+    }
+
+    @Override
+    public void error( String category, String message, Object param1, Object param2 )
+    {
+    }
+
+    @Override
+    public void error( String category, String message, Object... params )
+    {
+    }
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/LogType.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/LogType.java
new file mode 100644
index 0000000..ebc860e
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/LogType.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.library.logging.log;
+
+public enum LogType
+{
+    INFO, WARNING, ERROR
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/SimpleLog.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/SimpleLog.java
new file mode 100644
index 0000000..c3738b8
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/SimpleLog.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.polygene.library.logging.log;
+
+import org.apache.polygene.api.concern.Concerns;
+
+@Concerns( { SimpleLogConcern.class } )
+public interface SimpleLog
+{
+    void info( String message );
+
+    void info( String message, Object param1 );
+
+    void info( String message, Object param1, Object param2 );
+
+    void info( String message, Object... params );
+
+    void warning( String message );
+
+    void warning( String message, Object param1 );
+
+    void warning( String message, Object param1, Object param2 );
+
+    void warning( String message, Object... params );
+
+    void error( String message );
+
+    void error( String message, Object param1 );
+
+    void error( String message, Object param1, Object param2 );
+
+    void error( String message, Object... params );
+
+
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/SimpleLogConcern.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/SimpleLogConcern.java
new file mode 100644
index 0000000..0b6601a
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/SimpleLogConcern.java
@@ -0,0 +1,167 @@
+/*
+ *  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.polygene.library.logging.log;
+
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.library.logging.log.service.LoggingService;
+
+public final class SimpleLogConcern
+    implements SimpleLog
+{
+    @Structure
+    private PolygeneAPI api;
+    @Optional
+    @Service
+    private LoggingService loggingService;
+    private Composite composite;
+    private String category;
+
+    public SimpleLogConcern( @This Composite composite )
+    {
+        this.composite = composite;
+        Class<?> type = PolygeneAPI.FUNCTION_DESCRIPTOR_FOR.apply( composite ).types().findFirst().orElse( null );
+        category = type.getName();
+    }
+
+    @Override
+    public void info( String message )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.INFO, api.dereference( composite ), category, message );
+    }
+
+    @Override
+    public void info( String message, Object param1 )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, param1 );
+    }
+
+    @Override
+    public void info( String message, Object param1, Object param2 )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, param1, param2 );
+    }
+
+    @Override
+    public void info( String message, Object... params )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, params );
+    }
+
+    @Override
+    public void warning( String message )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.INFO, api.dereference( composite ), category, message );
+    }
+
+    @Override
+    public void warning( String message, Object param1 )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, param1 );
+    }
+
+    @Override
+    public void warning( String message, Object param1, Object param2 )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, param1, param2 );
+    }
+
+    @Override
+    public void warning( String message, Object... params )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, params );
+    }
+
+    @Override
+    public void error( String message )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.INFO, api.dereference( composite ), category, message );
+    }
+
+    @Override
+    public void error( String message, Object param1 )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, param1 );
+    }
+
+    @Override
+    public void error( String message, Object param1, Object param2 )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, param1, param2 );
+    }
+
+    @Override
+    public void error( String message, Object... params )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, params );
+    }
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/StandardLog.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/StandardLog.java
new file mode 100644
index 0000000..24654c8
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/StandardLog.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.logging.log;
+
+import org.apache.polygene.api.concern.Concerns;
+
+@Concerns( StandardLogConcern.class )
+public interface StandardLog
+{
+    void log( LogType type, String category, String message );
+
+    void log( LogType type, String category, String message, Object param1 );
+
+    void log( LogType type, String category, String message, Object param1, Object param2 );
+
+    void log( LogType type, String category, String message, Object... params );
+
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/StandardLogConcern.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/StandardLogConcern.java
new file mode 100644
index 0000000..5000216
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/StandardLogConcern.java
@@ -0,0 +1,77 @@
+/*
+ *  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.polygene.library.logging.log;
+
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.library.logging.log.service.LoggingService;
+
+public class StandardLogConcern
+    implements StandardLog
+{
+    @Structure private PolygeneAPI api;
+    @Optional @Service private LoggingService loggingService;
+    @This private Composite composite;
+
+    @Override
+    public void log( LogType type, String category, String message )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( type, api.dereference( composite ), category, message );
+    }
+
+    @Override
+    public void log( LogType type, String category, String message, Object param1 )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( type, api.dereference( composite ), category, message, param1 );
+    }
+
+    @Override
+    public void log( LogType type, String category, String message, Object param1, Object param2 )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( type, api.dereference( composite ), category, message, param1, param2 );
+    }
+
+    @Override
+    public void log( LogType type, String category, String message, Object... params )
+    {
+        if( loggingService == null )
+        {
+            return;
+        }
+        loggingService.log( type, api.dereference( composite ), category, message, params );
+    }
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/assemblies/LoggingAssembler.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/assemblies/LoggingAssembler.java
new file mode 100644
index 0000000..d9aa75f
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/assemblies/LoggingAssembler.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.library.logging.log.assemblies;
+
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.logging.log.service.LoggingServiceComposite;
+
+public class LoggingAssembler
+    implements Assembler
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( LoggingServiceComposite.class );
+    }
+
+}
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/assemblies/package.html b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/assemblies/package.html
new file mode 100644
index 0000000..cce5fba
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/assemblies/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Logging Assembly.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/package.html b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/package.html
new file mode 100644
index 0000000..ab2d91b
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Logging.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/records/CompositeLogRecord.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/records/CompositeLogRecord.java
new file mode 100644
index 0000000..9322960
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/records/CompositeLogRecord.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.library.logging.log.records;
+
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.property.Property;
+
+public interface CompositeLogRecord extends LogRecord
+{
+    Property<Composite> source();
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/records/EntityLogRecord.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/records/EntityLogRecord.java
new file mode 100644
index 0000000..b9a1f68
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/records/EntityLogRecord.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.library.logging.log.records;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.entity.EntityComposite;
+
+public interface EntityLogRecord extends LogRecord
+{
+    Association<EntityComposite> source();
+
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/records/LogRecord.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/records/LogRecord.java
new file mode 100644
index 0000000..0df27ed
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/records/LogRecord.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.library.logging.log.records;
+
+import java.time.Instant;
+import java.util.List;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.logging.log.LogType;
+
+public interface LogRecord
+{
+    Property<String> message();
+
+    Property<String> category();
+
+    Property<String> compositeTypeName();
+
+    Property<String> threadName();
+
+    Property<LogType> logtype();
+
+    Property<Instant> time();
+
+    Property<List<Object>> parameters();
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/records/ServiceLogRecord.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/records/ServiceLogRecord.java
new file mode 100644
index 0000000..3ba4fd3
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/records/ServiceLogRecord.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.library.logging.log.records;
+
+import org.apache.polygene.api.property.Property;
+
+public interface ServiceLogRecord extends LogRecord
+{
+    Property<String> source();
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/records/package.html b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/records/package.html
new file mode 100644
index 0000000..68151ec
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/records/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Logging Records.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/service/LogOnConsoleSideEffect.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/service/LogOnConsoleSideEffect.java
new file mode 100644
index 0000000..c4f45dd
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/service/LogOnConsoleSideEffect.java
@@ -0,0 +1,84 @@
+/*
+ *  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.polygene.library.logging.log.service;
+
+import java.io.PrintStream;
+import java.lang.reflect.Method;
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.injection.scope.Invocation;
+import org.apache.polygene.api.sideeffect.SideEffectOf;
+import org.apache.polygene.library.logging.log.LogType;
+
+/**
+ * The ConsoleViewSideEffect is just a temporary solution for logging output, until a more
+ * robust framework has been designed.
+ */
+public abstract class LogOnConsoleSideEffect extends SideEffectOf<LoggingService>
+    implements LoggingService
+{
+    private static PrintStream OUT = System.err;
+
+    private final ResourceBundle bundle;
+
+    public LogOnConsoleSideEffect( @Invocation Method thisMethod )
+    {
+        bundle = ResourceBundle.getBundle( thisMethod.getDeclaringClass().getName() );
+    }
+
+    public void log( LogType type, Composite composite, String category, String message )
+    {
+        String localized = bundle.getString( message );
+        String logType = type.name();
+        OUT.println( logType + ":" + category + ":" + getCompositeName( composite ) + ": " + localized );
+    }
+
+    private String getCompositeName( Composite composite )
+    {
+        return PolygeneAPI.FUNCTION_DESCRIPTOR_FOR.apply( composite ).types().findFirst().get().getName();
+    }
+
+    public void log( LogType type, Composite composite, String category, String message, Object param1 )
+    {
+        String localized = bundle.getString( message );
+        String formatted = MessageFormat.format( localized, param1 );
+        String logType = type.name();
+        OUT.println( logType + ":" + category + ":" + getCompositeName( composite ) + ": " + formatted );
+    }
+
+    public void log( LogType type, Composite composite, String category, String message, Object param1, Object param2 )
+    {
+        String localized = bundle.getString( message );
+        String formatted = MessageFormat.format( localized, param1, param2 );
+        String logtype = type.name();
+        OUT.println( logtype + ":" + category + ":" + getCompositeName( composite ) + ": " + formatted );
+    }
+
+    public void log( LogType type, Composite composite, String category, String message, Object... params )
+    {
+        String localized = bundle.getString( message );
+        String formatted = MessageFormat.format( localized, params );
+        String logType = type.name();
+        OUT.println( logType + ":" + category + ":" + getCompositeName( composite ) + ": " + formatted );
+    }
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/service/LoggingService.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/service/LoggingService.java
new file mode 100644
index 0000000..5072f55
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/service/LoggingService.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.logging.log.service;
+
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.library.logging.log.LogType;
+
+public interface LoggingService
+{
+    void log( LogType type, Composite composite, String category, String message, Object... params );
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/service/LoggingServiceComposite.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/service/LoggingServiceComposite.java
new file mode 100644
index 0000000..e82c7c8
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/service/LoggingServiceComposite.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.library.logging.log.service;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.sideeffect.SideEffects;
+
+@SideEffects( { LogOnConsoleSideEffect.class } )
+@Mixins( { LoggingServiceMixin.class } )
+public interface LoggingServiceComposite extends LoggingService
+{
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/service/LoggingServiceMixin.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/service/LoggingServiceMixin.java
new file mode 100644
index 0000000..58dc0d4
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/service/LoggingServiceMixin.java
@@ -0,0 +1,173 @@
+/*
+ *  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.polygene.library.logging.log.service;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.time.SystemTime;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.library.logging.log.LogType;
+import org.apache.polygene.library.logging.log.records.CompositeLogRecord;
+import org.apache.polygene.library.logging.log.records.EntityLogRecord;
+import org.apache.polygene.library.logging.log.records.LogRecord;
+import org.apache.polygene.library.logging.log.records.ServiceLogRecord;
+
+
+public abstract class LoggingServiceMixin
+    implements LoggingService
+{
+    @Structure private UnitOfWorkFactory uowf;
+
+    public void log( LogType type, Composite composite, String category, String message )
+    {
+        UnitOfWork uow = uowf.newUnitOfWork();
+        try
+        {
+            List<Object> paramsList = new ArrayList<>();
+            createLogRecord( uow, type, composite, category, message, paramsList );
+            uow.complete();
+        }
+        catch( ConcurrentEntityModificationException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+        catch( UnitOfWorkCompletionException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+    }
+
+    public void log( LogType type, Composite composite, String category, String message, Object param1 )
+    {
+        UnitOfWork uow = uowf.newUnitOfWork();
+        try
+        {
+            List<Object> paramsList = new ArrayList<>();
+            paramsList.add( param1 );
+            createLogRecord( uow, type, composite, category, message, paramsList );
+            uow.complete();
+        }
+        catch( ConcurrentEntityModificationException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+        catch( UnitOfWorkCompletionException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+    }
+
+    public void log( LogType type, Composite composite, String category, String message, Object param1, Object param2 )
+    {
+        UnitOfWork uow = uowf.newUnitOfWork();
+        try
+        {
+            List<Object> paramsList = new ArrayList<>();
+            paramsList.add( param1 );
+            paramsList.add( param2 );
+            createLogRecord( uow, type, composite, category, message, paramsList );
+            uow.complete();
+        }
+        catch( ConcurrentEntityModificationException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+        catch( UnitOfWorkCompletionException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+    }
+
+    @Override
+    public void log( LogType type, Composite composite, String category, String message, Object... params )
+    {
+        UnitOfWork uow = uowf.newUnitOfWork();
+        try
+        {
+            List<Object> paramsList = new ArrayList<>( Arrays.asList( params ) );
+            createLogRecord( uow, type, composite, category, message, paramsList );
+            uow.complete();
+        }
+        catch( ConcurrentEntityModificationException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+        catch( UnitOfWorkCompletionException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+    }
+
+    private void createLogRecord( UnitOfWork uow, LogType type, Composite composite, String category, String message, List<Object> params )
+    {
+        if( composite instanceof ServiceComposite )
+        {
+            EntityBuilder<ServiceLogRecord> builder = uow.newEntityBuilder( ServiceLogRecord.class );
+            ServiceLogRecord state = builder.instance();
+            setStandardStuff( type, composite, category, message, state, params );
+            state.source().set( ( (ServiceComposite) composite ).identity().get().toString() );
+            ServiceLogRecord slr = builder.newInstance();
+        }
+        else if( composite instanceof EntityComposite )
+        {
+            EntityBuilder<EntityLogRecord> builder = uow.newEntityBuilder( EntityLogRecord.class );
+            EntityLogRecord state = builder.instance();
+            setStandardStuff( type, composite, category, message, state, params );
+            state.source().set( (EntityComposite) composite );
+            EntityLogRecord elr = builder.newInstance();
+        }
+        else
+        {
+            EntityBuilder<CompositeLogRecord> builder = uow.newEntityBuilder( CompositeLogRecord.class );
+            CompositeLogRecord state = builder.instance();
+            setStandardStuff( type, composite, category, message, state, params );
+            state.source().set( composite );
+            CompositeLogRecord clr = builder.newInstance();
+        }
+    }
+
+    private void setStandardStuff( LogType type, Composite composite, String category, String message,
+                                   LogRecord state, List<Object> params )
+    {
+        state.logtype().set( type );
+        state.time().set( SystemTime.now() );
+        state.category().set( category );
+        state.message().set( message );
+        state.compositeTypeName().set( getCompositeName( composite ) );
+        state.threadName().set( Thread.currentThread().getName() );
+        state.parameters().set( params );
+    }
+
+    private String getCompositeName( Composite composite )
+    {
+        return PolygeneAPI.FUNCTION_DESCRIPTOR_FOR.apply( composite ).types().findFirst().get().getName();
+    }
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/service/package.html b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/service/package.html
new file mode 100644
index 0000000..b344b28
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/log/service/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Logging Service.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/AbstractTraceConcern.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/AbstractTraceConcern.java
new file mode 100644
index 0000000..36a9e11
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/AbstractTraceConcern.java
@@ -0,0 +1,84 @@
+/*
+ *  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.polygene.library.logging.trace;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.time.Duration;
+import java.time.Instant;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.time.SystemTime;
+import org.apache.polygene.library.logging.trace.service.TraceService;
+
+
+public abstract class AbstractTraceConcern extends ConcernOf<InvocationHandler>
+    implements InvocationHandler
+{
+    @Structure private PolygeneAPI api;
+    @Optional @Service protected TraceService traceService;
+    private Composite thisComposite;
+    private Class compositeType;
+
+    public AbstractTraceConcern( Composite thisComposite )
+    {
+        this.thisComposite = thisComposite;
+        compositeType = thisComposite.getClass().getInterfaces()[ 0 ];
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        boolean doTrace = traceService != null && doTrace();
+        Object result;
+        Instant entryTime = SystemTime.now();;
+        try
+        {
+            result = next.invoke( proxy, method, args );
+            if( doTrace )
+            {
+                Duration duration = Duration.between(entryTime, SystemTime.now() );
+                traceService.traceSuccess( compositeType, api.dereference( thisComposite ), method, args, result, entryTime, duration );
+            }
+        }
+        catch( Throwable t )
+        {
+            if( doTrace )
+            {
+                Duration duration = Duration.between(entryTime, SystemTime.now() );
+                Composite object = api.dereference( thisComposite );
+                traceService.traceException( compositeType, object, method, args, t, entryTime, duration );
+            }
+            throw t;
+        }
+        return result;
+    }
+
+    protected boolean doTrace()
+    {
+        return true;
+    }
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/ExcludeCompositeFilter.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/ExcludeCompositeFilter.java
new file mode 100644
index 0000000..49aaedf
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/ExcludeCompositeFilter.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.logging.trace;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesToFilter;
+import org.apache.polygene.api.composite.Composite;
+
+public class ExcludeCompositeFilter
+    implements AppliesToFilter
+{
+    @Override
+    public boolean appliesTo( Method method, Class mixin, Class compositeType, Class modifierClass )
+    {
+        return method.getDeclaringClass() != Composite.class;
+    }
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/Trace.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/Trace.java
new file mode 100644
index 0000000..59c4628
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/Trace.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.library.logging.trace;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.injection.InjectionScope;
+
+/**
+ * The Trace annotation is to indicate which methods should be traced when tracing is enabled.
+ * <p>
+ * The <i>level</i> of the Trace indicates the <i>threshold level</i> that the <code>Tracer</code> instance must be set
+ * to, to enable tracing. If the <i>threshold level</i> of the <code>Tracer</code> instance is equal to or higher than
+ * the <i>level</i> of the <code>Trace</code> annotation the method will be traced.
+ * </p>
+ * <p>
+ * The <code>Trace</code> annotation will only be used for <code>TraceConcern</code> and not if the
+ * all encompassing <code>TraceAllConcern</code> is used.
+ * </p>
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.METHOD } )
+@Documented
+@InjectionScope
+public @interface Trace
+{
+    int ALL = Integer.MIN_VALUE;
+    int LOWLOW = -100;
+    int LOW = -50;
+    int NORMAL = 0;
+    int HIGH = 50;
+    int HIGHHIGH = 100;
+    int OFF = Integer.MAX_VALUE;
+
+    /**
+     * The value is the threshold level required to enable the tracing.
+     * <p>
+     * If the Trace level is set to 100 (default), it is required that the
+     * Tracer (retrieved from the LogService) used is set to 100 or higher.
+     * </p>
+     *
+     * @return the Trace Level of this Trace annotation.
+     */
+    int level() default NORMAL;
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/TraceAllConcern.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/TraceAllConcern.java
new file mode 100644
index 0000000..add5f44
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/TraceAllConcern.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.library.logging.trace;
+
+import java.lang.reflect.InvocationHandler;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.injection.scope.This;
+
+/**
+ * The TraceAllConcern will call the traceEntry(), traceExit() and traceException() methods in the
+ * Tracer instance associated with the CompositeType that the TraceAllConcern is part of.
+ * <p>
+ * The Trace paradigm is all about tracking the entry and exit (both normal and exceptional ones)
+ * of methods.
+ * </p>
+ * <p>
+ * The main difference to the <code>TraceConcern</code> is that this concern is not associated with
+ * the <code>@Trace</code> annotation, and all methods in the interfaces will be traced, unless
+ * the LogService has turned off tracing.
+ * </p>
+ *
+ * @see TraceConcern
+ */
+@AppliesTo( ExcludeCompositeFilter.class )
+public final class TraceAllConcern extends AbstractTraceConcern
+    implements InvocationHandler
+{
+    public TraceAllConcern( @This Composite composite )
+    {
+        super( composite );
+    }
+
+    @Override
+    protected boolean doTrace()
+    {
+        return true;
+    }
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/TraceConcern.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/TraceConcern.java
new file mode 100644
index 0000000..8db3d0c
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/TraceConcern.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.library.logging.trace;
+
+import java.lang.reflect.InvocationHandler;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.injection.scope.Invocation;
+import org.apache.polygene.api.injection.scope.This;
+
+/**
+ * The TraceConcern will call the traceEntry(), traceExit() and traceException() methods in the
+ * Tracer instance associated with the CompositeType that the TraceConcern is part of.
+ * <p>
+ * The Trace paradigm is all about tracking the entry and exit (both normal and exceptional ones)
+ * of methods. The TraceConcern will be added to all methods that declares the <code>@Trace</code>
+ * annotation, with an optional <i>level</i> argument. The <i>level</i> is the threshold of the
+ * Tracer instance required to trace the method, i.e. the <i>priority</i> of the Tracer instance
+ * must be equal or higher than the <i>level</i> set in the <code>@Trace</code> annotation of the
+ * method.
+ * </p>
+ * <p>
+ * If the <i>priority</i> of the <code>Tracer</code> is set to OFF (Integer.MIN_VALUE) then no
+ * tracing will happen.
+ * </p>
+ */
+@AppliesTo( Trace.class )
+public final class TraceConcern extends AbstractTraceConcern
+    implements InvocationHandler
+{
+    @Invocation private Trace trace;
+
+    public TraceConcern( @This Composite thisComposite )
+    {
+        super( thisComposite );
+    }
+
+    @Override
+    protected boolean doTrace()
+    {
+        return traceService.traceLevel() <= trace.level();
+    }
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/TraceOnConsoleSideEffect.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/TraceOnConsoleSideEffect.java
new file mode 100644
index 0000000..52f500d
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/TraceOnConsoleSideEffect.java
@@ -0,0 +1,97 @@
+/*
+ *  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.polygene.library.logging.trace;
+
+import java.io.PrintStream;
+import java.lang.reflect.Method;
+import java.time.Duration;
+import java.time.Instant;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.sideeffect.SideEffectOf;
+import org.apache.polygene.library.logging.trace.service.TraceService;
+
+/**
+ * The ConsoleViewSideEffect is just a temporary solution for logging output, until a more
+ * robust framework has been designed.
+ */
+public abstract class TraceOnConsoleSideEffect extends SideEffectOf<TraceService>
+    implements TraceService
+{
+    private static PrintStream OUT = System.err;
+
+    @Override
+    public void traceSuccess(Class compositeType, Composite object, Method method, Object[] args, Object result, Instant entryTime, Duration duration )
+    {
+        StringBuffer buf = new StringBuffer();
+        buf.append( duration );
+        buf.append( " : " );
+        formatMethod( buf, object, compositeType, method, args );
+        OUT.println( buf.toString() );
+        OUT.println( result );
+    }
+
+    @Override
+    public void traceException( Class compositeType, Composite object, Method method, Object[] args, Throwable t, Instant entryTime, Duration duration )
+    {
+        String trace = "Exception: " + duration + " : ";
+        OUT.println( trace );
+        t.printStackTrace( OUT );
+    }
+
+    private void formatMethod( StringBuffer buf, Composite object, Class compositeType, Method method, Object[] args )
+    {
+        buf.append( compositeType.getClass().getName() );
+        buf.append( "." );
+        buf.append( method.getName() );
+        buf.append( "( " );
+        if( args != null )
+        {
+            boolean first = true;
+            for( Object arg : args )
+            {
+                if( !first )
+                {
+                    buf.append( ", " );
+                }
+                first = false;
+                if( arg instanceof String )
+                {
+                    buf.append( "\"" );
+                }
+                buf.append( arg );
+                if( arg instanceof String )
+                {
+                    buf.append( "\"" );
+                }
+            }
+        }
+        buf.append( " )  [ " );
+        if( object == null )
+        {
+            buf.append( "<null>" );
+        }
+        else
+        {
+            buf.append( object.toString() );
+        }
+        buf.append( " ]" );
+    }
+}
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/assemblies/TracingAssembler.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/assemblies/TracingAssembler.java
new file mode 100644
index 0000000..fe4542c
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/assemblies/TracingAssembler.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.logging.trace.assemblies;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.logging.trace.service.StandardTraceServiceComposite;
+import org.apache.polygene.library.logging.trace.service.TraceServiceConfiguration;
+
+public class TracingAssembler
+    implements Assembler
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( StandardTraceServiceComposite.class ).visibleIn( Visibility.application );
+        module.entities( TraceServiceConfiguration.class );
+    }
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/assemblies/package.html b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/assemblies/package.html
new file mode 100644
index 0000000..c84fc6b
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/assemblies/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Trace Logging Assembly.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/package.html b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/package.html
new file mode 100644
index 0000000..9c26a1d
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Trace Logging.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/records/CompositeTraceRecordEntity.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/records/CompositeTraceRecordEntity.java
new file mode 100644
index 0000000..773a343
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/records/CompositeTraceRecordEntity.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.library.logging.trace.records;
+
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.property.Property;
+
+public interface CompositeTraceRecordEntity extends TraceRecord
+{
+    Property<Composite> source();
+
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/records/EntityTraceRecordEntity.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/records/EntityTraceRecordEntity.java
new file mode 100644
index 0000000..dcf529f
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/records/EntityTraceRecordEntity.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.logging.trace.records;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.Queryable;
+
+@Queryable( false )
+public interface EntityTraceRecordEntity extends TraceRecord
+{
+    Association<EntityComposite> source();
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/records/ServiceTraceRecordEntity.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/records/ServiceTraceRecordEntity.java
new file mode 100644
index 0000000..9a5135e
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/records/ServiceTraceRecordEntity.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.library.logging.trace.records;
+
+import org.apache.polygene.api.property.Property;
+
+public interface ServiceTraceRecordEntity extends TraceRecord
+{
+    Property<String> source();
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/records/TraceRecord.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/records/TraceRecord.java
new file mode 100644
index 0000000..277ab2f
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/records/TraceRecord.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.library.logging.trace.records;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.List;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.Property;
+
+public interface TraceRecord
+{
+    Property<String> methodName();
+
+    Property<String> compositeTypeName();
+
+    Property<String> threadName();
+
+    Property<Instant> entryTime();
+
+    Property<Duration> duration();
+
+    @Optional Property<Throwable> exception();
+
+    @Queryable( false ) Property<List<String>> arguments();
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/records/package.html b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/records/package.html
new file mode 100644
index 0000000..904e247
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/records/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Trace Logging Records.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/service/StandardTraceServiceComposite.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/service/StandardTraceServiceComposite.java
new file mode 100644
index 0000000..bc20229
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/service/StandardTraceServiceComposite.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.logging.trace.service;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.sideeffect.SideEffects;
+import org.apache.polygene.library.logging.trace.TraceOnConsoleSideEffect;
+
+@SideEffects( TraceOnConsoleSideEffect.class )
+@Mixins( TraceServiceMixin.class )
+public interface StandardTraceServiceComposite extends TraceService
+{
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/service/TraceService.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/service/TraceService.java
new file mode 100644
index 0000000..8467eb5
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/service/TraceService.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.logging.trace.service;
+
+import java.lang.reflect.Method;
+import java.time.Duration;
+import java.time.Instant;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.Composite;
+
+public interface TraceService
+{
+    int traceLevel();
+
+    void traceSuccess(Class compositeType, Composite object, Method method, @Optional Object[] args, Object result, Instant entryTime, Duration duration );
+
+    void traceException( Class compositeType, Composite object, Method method, @Optional Object[] args, Throwable t, Instant entryTime, Duration duration );
+
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/service/TraceServiceConfiguration.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/service/TraceServiceConfiguration.java
new file mode 100644
index 0000000..1987907
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/service/TraceServiceConfiguration.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.logging.trace.service;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+public interface TraceServiceConfiguration
+{
+    @UseDefaults Property<Integer> traceLevel();
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/service/TraceServiceMixin.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/service/TraceServiceMixin.java
new file mode 100644
index 0000000..a088ed0
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/service/TraceServiceMixin.java
@@ -0,0 +1,199 @@
+/*
+ *  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.polygene.library.logging.trace.service;
+
+import java.lang.reflect.Method;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.library.logging.trace.records.CompositeTraceRecordEntity;
+import org.apache.polygene.library.logging.trace.records.EntityTraceRecordEntity;
+import org.apache.polygene.library.logging.trace.records.ServiceTraceRecordEntity;
+import org.apache.polygene.library.logging.trace.records.TraceRecord;
+
+public class TraceServiceMixin
+    implements TraceService
+{
+    @Structure
+    private UnitOfWorkFactory uowf;
+    @This
+    private Configuration<TraceServiceConfiguration> configuration;
+    private int counter;
+    private Integer traceLevel;
+
+    @Override
+    public int traceLevel()
+    {
+        if( counter++ % 100 == 0 )
+        {
+            counter = 0;
+            traceLevel = configuration.get().traceLevel().get();
+        }
+        return traceLevel;
+    }
+
+    @Override
+    public void traceSuccess( Class compositeType,
+                              Composite object,
+                              Method method,
+                              Object[] args,
+                              Object result,
+                              Instant entryTime,
+                              Duration duration
+    )
+    {
+        UnitOfWork uow = uowf.newUnitOfWork();
+        try
+        {
+            createTraceRecord( uow, compositeType, object, method, args, entryTime, duration, null );
+            uow.complete();
+        }
+        catch( ConcurrentEntityModificationException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+        catch( UnitOfWorkCompletionException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+    }
+
+    @Override
+    public void traceException( Class compositeType,
+                                Composite object,
+                                Method method,
+                                Object[] args,
+                                Throwable t,
+                                Instant entryTime,
+                                Duration duration
+    )
+    {
+        UnitOfWork uow = uowf.newUnitOfWork();
+        try
+        {
+            createTraceRecord( uow, compositeType, object, method, args, entryTime, duration, t );
+            uow.complete();
+        }
+        catch( ConcurrentEntityModificationException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+        catch( UnitOfWorkCompletionException e )
+        {
+            // ignore for now. Perhaps discard() and try again.
+        }
+    }
+
+    private void createTraceRecord( UnitOfWork uow,
+                                    Class compositeType,
+                                    Composite object,
+                                    Method method,
+                                    Object[] args,
+                                    Instant entryTime,
+                                    Duration duration,
+                                    Throwable exception
+    )
+    {
+        if( object instanceof EntityComposite )
+        {
+            EntityComposite entity = (EntityComposite) object;
+            EntityComposite source = (EntityComposite) uow.get(
+                PolygeneAPI.FUNCTION_DESCRIPTOR_FOR.apply( entity )
+                    .types()
+                    .findFirst()
+                    .orElse( null ), entity.identity().get() );
+            EntityBuilder<EntityTraceRecordEntity> builder = uow.newEntityBuilder( EntityTraceRecordEntity.class );
+            EntityTraceRecordEntity state = builder.instance();
+            setStandardStuff( compositeType, method, args, entryTime, duration, state, exception );
+            state.source().set( source );
+            EntityTraceRecordEntity etr = builder.newInstance();  // Record is created.
+        }
+        else if( object instanceof ServiceComposite )
+        {
+            ServiceComposite service = (ServiceComposite) object;
+            EntityBuilder<ServiceTraceRecordEntity> builder = uow.newEntityBuilder( ServiceTraceRecordEntity.class );
+            ServiceTraceRecordEntity state = builder.instance();
+            setStandardStuff( compositeType, method, args, entryTime, duration, state, exception );
+            state.source().set( service.toString() );
+            ServiceTraceRecordEntity str = builder.newInstance();  // Record is created.
+        }
+        else
+        {
+            EntityBuilder<CompositeTraceRecordEntity> builder = uow.newEntityBuilder( CompositeTraceRecordEntity.class );
+            CompositeTraceRecordEntity state = builder.instance();
+            state.source().set( object );
+            setStandardStuff( compositeType, method, args, entryTime, duration, state, exception );
+            CompositeTraceRecordEntity ctr = builder.newInstance();  // Record is created.
+        }
+    }
+
+    private void setStandardStuff( Class compositeType,
+                                   Method method,
+                                   Object[] args,
+                                   Instant entryTime,
+                                   Duration duration,
+                                   TraceRecord state,
+                                   Throwable exception
+    )
+    {
+        state.duration().set( duration );
+        state.entryTime().set( entryTime );
+        state.methodName().set( method.getName() );
+        state.compositeTypeName().set( compositeType.getName() );
+        state.arguments().set( convertArguments( args ) );
+        state.threadName().set( Thread.currentThread().getName() );
+        state.exception().set( exception );
+    }
+
+    private List<String> convertArguments( Object[] args )
+    {
+        if( args == null )
+        {
+            return new ArrayList<>( 0 );
+        }
+        List<String> result = new ArrayList<>( args.length );
+        for( Object arg : args )
+        {
+            if( arg == null )
+            {
+                result.add( null );
+            }
+            else
+            {
+                result.add( arg.toString() );
+            }
+        }
+        return result;
+    }
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/service/package.html b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/service/package.html
new file mode 100644
index 0000000..302753f
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/trace/service/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Trace Logging Service.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/view/ConsoleViewerComposite.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/view/ConsoleViewerComposite.java
new file mode 100644
index 0000000..f5ec908
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/view/ConsoleViewerComposite.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.logging.view;
+
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.mixin.Mixins;
+
+@Mixins( { ConsoleViewerMixin.class } )
+public interface ConsoleViewerComposite extends Composite
+{
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/view/ConsoleViewerMixin.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/view/ConsoleViewerMixin.java
new file mode 100644
index 0000000..c1cdd82
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/view/ConsoleViewerMixin.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.library.logging.view;
+
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.library.logging.log.service.LoggingService;
+
+public class ConsoleViewerMixin
+    implements LogServiceListener
+{
+    @Service private LoggingService service;
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/view/LogServiceListener.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/view/LogServiceListener.java
new file mode 100644
index 0000000..c8275f2
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/view/LogServiceListener.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.library.logging.view;
+
+public interface LogServiceListener
+{
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/view/SwingViewer.java b/libraries/logging/src/main/java/org/apache/polygene/library/logging/view/SwingViewer.java
new file mode 100644
index 0000000..8e73e5c
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/view/SwingViewer.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.library.logging.view;
+
+import javax.swing.*;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.library.logging.log.service.LoggingService;
+
+public class SwingViewer extends JFrame
+{
+    @Service private Iterable<LoggingService> services;
+}
diff --git a/libraries/logging/src/main/java/org/apache/polygene/library/logging/view/package.html b/libraries/logging/src/main/java/org/apache/polygene/library/logging/view/package.html
new file mode 100644
index 0000000..595a05e
--- /dev/null
+++ b/libraries/logging/src/main/java/org/apache/polygene/library/logging/view/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Log Viewers.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/debug/Debug.java b/libraries/logging/src/main/java/org/qi4j/logging/debug/Debug.java
deleted file mode 100644
index e7f1d26..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/debug/Debug.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.debug;
-
-import java.io.Serializable;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.mixin.NoopMixin;
-
-@Concerns( DebugConcern.class )
-@Mixins( NoopMixin.class )
-public interface Debug
-{
-    int OFF = Integer.MIN_VALUE;
-    int LOWLOW = -100;
-    int LOW = -50;
-    int NORMAL = 0;
-    int HIGH = 50;
-    int HIGHHIGH = 100;
-
-    Integer debugLevel();
-
-    void debug( int level, String message );
-
-    void debug( int level, String message, Serializable param1 );
-
-    void debug( int level, String message, Serializable param1, Serializable param2 );
-
-    void debug( int level, String message, Serializable... params );
-
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/debug/DebugConcern.java b/libraries/logging/src/main/java/org/qi4j/logging/debug/DebugConcern.java
deleted file mode 100644
index 8158d08..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/debug/DebugConcern.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.debug;
-
-import java.io.Serializable;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.logging.debug.service.DebuggingService;
-
-public class DebugConcern
-    implements Debug
-{
-    @Structure private Qi4j api;
-    @Optional @Service private DebuggingService loggingService;
-    @This private Composite composite;
-
-    @Override
-    public Integer debugLevel()
-    {
-        if( loggingService != null )
-        {
-            return loggingService.debugLevel();
-        }
-        return OFF;
-    }
-
-    @Override
-    public void debug( int priority, String message )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        if( priority >= loggingService.debugLevel() )
-        {
-            Composite derefed = api.dereference( composite );
-            loggingService.debug( derefed, message );
-        }
-    }
-
-    @Override
-    public void debug( int priority, String message, Serializable param1 )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        if( priority >= loggingService.debugLevel() )
-        {
-            loggingService.debug( api.dereference( composite ), message, param1 );
-        }
-    }
-
-    @Override
-    public void debug( int priority, String message, Serializable param1, Serializable param2 )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        if( priority >= loggingService.debugLevel() )
-        {
-            loggingService.debug( api.dereference( composite ), message, param1, param2 );
-        }
-    }
-
-    @Override
-    public void debug( int priority, String message, Serializable... params )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        if( priority >= loggingService.debugLevel() )
-        {
-            loggingService.debug( api.dereference( composite ), message, params );
-        }
-    }
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/debug/package.html b/libraries/logging/src/main/java/org/qi4j/logging/debug/package.html
deleted file mode 100644
index e090255..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/debug/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Debug Logging.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/debug/records/CompositeDebugRecordEntity.java b/libraries/logging/src/main/java/org/qi4j/logging/debug/records/CompositeDebugRecordEntity.java
deleted file mode 100644
index a24817c..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/debug/records/CompositeDebugRecordEntity.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.debug.records;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-
-public interface CompositeDebugRecordEntity extends DebugRecord, EntityComposite
-{
-    Property<Composite> source();
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/debug/records/DebugRecord.java b/libraries/logging/src/main/java/org/qi4j/logging/debug/records/DebugRecord.java
deleted file mode 100644
index cf72cc6..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/debug/records/DebugRecord.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.debug.records;
-
-import java.io.Serializable;
-import java.util.List;
-import org.qi4j.api.property.Property;
-
-public interface DebugRecord
-{
-    Property<String> message();
-
-    Property<String> compositeTypeName();
-
-    Property<String> threadName();
-
-    Property<Long> time();
-
-    Property<List<Serializable>> parameters();
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/debug/records/EntityDebugRecordEntity.java b/libraries/logging/src/main/java/org/qi4j/logging/debug/records/EntityDebugRecordEntity.java
deleted file mode 100644
index a679437..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/debug/records/EntityDebugRecordEntity.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.debug.records;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.entity.EntityComposite;
-
-public interface EntityDebugRecordEntity extends DebugRecord, EntityComposite
-{
-    Association<EntityComposite> source();
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/debug/records/ServiceDebugRecordEntity.java b/libraries/logging/src/main/java/org/qi4j/logging/debug/records/ServiceDebugRecordEntity.java
deleted file mode 100644
index e57e555..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/debug/records/ServiceDebugRecordEntity.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.debug.records;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-
-public interface ServiceDebugRecordEntity extends DebugRecord, EntityComposite
-{
-    Property<String> source();
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/debug/records/package.html b/libraries/logging/src/main/java/org/qi4j/logging/debug/records/package.html
deleted file mode 100644
index 6588b52..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/debug/records/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Debug Logging Records.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/debug/service/DebugOnConsoleSideEffect.java b/libraries/logging/src/main/java/org/qi4j/logging/debug/service/DebugOnConsoleSideEffect.java
deleted file mode 100644
index 8d369aa..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/debug/service/DebugOnConsoleSideEffect.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.debug.service;
-
-import java.io.PrintStream;
-import java.io.Serializable;
-import java.lang.reflect.Method;
-import java.text.MessageFormat;
-import java.util.ResourceBundle;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.injection.scope.Invocation;
-import org.qi4j.api.sideeffect.SideEffectOf;
-import org.qi4j.logging.debug.Debug;
-import org.qi4j.logging.log.service.LoggingService;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * The DebugOnConsoleSideEffect is just a temporary solution for logging output, until a more
- * robust framework has been designed.
- */
-public class DebugOnConsoleSideEffect extends SideEffectOf<LoggingService>
-    implements DebuggingService
-{
-    private static PrintStream OUT = System.err;
-
-    private final ResourceBundle bundle;
-
-    public DebugOnConsoleSideEffect( @Invocation Method thisMethod )
-    {
-        bundle = ResourceBundle.getBundle( thisMethod.getDeclaringClass().getName() );
-    }
-
-    @Override
-    public int debugLevel()
-    {
-        return Debug.OFF;
-    }
-
-    @Override
-    public void debug( Composite composite, String message )
-    {
-        String localized = bundle.getString( message );
-        OUT.println( "DEBUG:" + getCompositeName( composite ) + ": " + localized );
-    }
-
-    private String getCompositeName( Composite composite )
-    {
-        return first( Qi4j.FUNCTION_DESCRIPTOR_FOR.map( composite ).types()).getName();
-    }
-
-    @Override
-    public void debug( Composite composite, String message, Serializable param1 )
-    {
-        String localized = bundle.getString( message );
-        String formatted = MessageFormat.format( localized, param1 );
-        OUT.println( "DEBUG:" + getCompositeName( composite ) + ": " + formatted );
-        if( param1 instanceof Throwable )
-        {
-            handleException( (Throwable) param1 );
-        }
-    }
-
-    @Override
-    public void debug( Composite composite, String message, Serializable param1, Serializable param2 )
-    {
-        String localized = bundle.getString( message );
-        String formatted = MessageFormat.format( localized, param1, param2 );
-        OUT.println( "DEBUG:" + getCompositeName( composite ) + ": " + formatted );
-        if( param1 instanceof Throwable )
-        {
-            handleException( (Throwable) param1 );
-        }
-    }
-
-    @Override
-    public void debug( Composite composite, String message, Serializable... params )
-    {
-        String localized = bundle.getString( message );
-        String formatted = MessageFormat.format( localized, (Serializable) params );
-        OUT.println( "DEBUG:" + getCompositeName( composite ) + ": " + formatted );
-        if( params[ 0 ] instanceof Throwable )
-        {
-            handleException( (Throwable) params[ 0 ] );
-        }
-    }
-
-    private void handleException( Throwable exception )
-    {
-        if( exception != null )
-        {
-            exception.printStackTrace( OUT );
-        }
-    }
-}
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/debug/service/DebugServiceConfiguration.java b/libraries/logging/src/main/java/org/qi4j/logging/debug/service/DebugServiceConfiguration.java
deleted file mode 100644
index 409819e..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/debug/service/DebugServiceConfiguration.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.debug.service;
-
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-public interface DebugServiceConfiguration
-    extends ConfigurationComposite
-{
-    Property<Integer> debugLevel();
-}
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/debug/service/DebuggingService.java b/libraries/logging/src/main/java/org/qi4j/logging/debug/service/DebuggingService.java
deleted file mode 100644
index ae9e0ac..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/debug/service/DebuggingService.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.logging.debug.service;
-
-import java.io.Serializable;
-import org.qi4j.api.composite.Composite;
-
-public interface DebuggingService
-{
-    int debugLevel();
-
-    void debug( Composite composite, String message );
-
-    void debug( Composite composite, String message, Serializable param1 );
-
-    void debug( Composite composite, String message, Serializable param1, Serializable param2 );
-
-    void debug( Composite composite, String message, Serializable... params );
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/debug/service/DebuggingServiceComposite.java b/libraries/logging/src/main/java/org/qi4j/logging/debug/service/DebuggingServiceComposite.java
deleted file mode 100644
index 1d48c22..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/debug/service/DebuggingServiceComposite.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.debug.service;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.sideeffect.SideEffects;
-import org.qi4j.logging.log.service.LogOnConsoleSideEffect;
-
-@SideEffects( { LogOnConsoleSideEffect.class } )
-@Mixins( { DebuggingServiceMixin.class } )
-public interface DebuggingServiceComposite extends DebuggingService, ServiceComposite
-{
-}
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/debug/service/DebuggingServiceMixin.java b/libraries/logging/src/main/java/org/qi4j/logging/debug/service/DebuggingServiceMixin.java
deleted file mode 100644
index b2fd04f..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/debug/service/DebuggingServiceMixin.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.logging.debug.service;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.unitofwork.ConcurrentEntityModificationException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.logging.debug.records.CompositeDebugRecordEntity;
-import org.qi4j.logging.debug.records.DebugRecord;
-import org.qi4j.logging.debug.records.EntityDebugRecordEntity;
-import org.qi4j.logging.debug.records.ServiceDebugRecordEntity;
-
-import static org.qi4j.functional.Iterables.first;
-
-public class DebuggingServiceMixin
-    implements DebuggingService
-{
-    @Structure private UnitOfWorkFactory uowf;
-    @This private Configuration<DebugServiceConfiguration> configuration;
-
-    @Override
-    public int debugLevel()
-    {
-        return configuration.get().debugLevel().get();
-    }
-
-    @Override
-    public void debug( Composite composite, String message )
-    {
-        UnitOfWork uow = uowf.newUnitOfWork();
-        try
-        {
-            List<Serializable> paramsList = new ArrayList<Serializable>();
-            createDebugRecord( uow, composite, message, paramsList );
-            uow.complete();
-        }
-        catch( ConcurrentEntityModificationException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-        catch( UnitOfWorkCompletionException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-    }
-
-    @Override
-    public void debug( Composite composite, String message, Serializable param1 )
-    {
-        UnitOfWork uow = uowf.newUnitOfWork();
-        try
-        {
-            List<Serializable> paramsList = new ArrayList<Serializable>();
-            paramsList.add( param1 );
-            createDebugRecord( uow, composite, message, paramsList );
-            uow.complete();
-        }
-        catch( ConcurrentEntityModificationException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-        catch( UnitOfWorkCompletionException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-    }
-
-    @Override
-    public void debug( Composite composite, String message, Serializable param1, Serializable param2 )
-    {
-        UnitOfWork uow = uowf.newUnitOfWork();
-        try
-        {
-            List<Serializable> paramsList = new ArrayList<Serializable>();
-            paramsList.add( param1 );
-            paramsList.add( param2 );
-            createDebugRecord( uow, composite, message, paramsList );
-            uow.complete();
-        }
-        catch( ConcurrentEntityModificationException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-        catch( UnitOfWorkCompletionException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-    }
-
-    @Override
-    public void debug( Composite composite, String message, Serializable... params )
-    {
-        UnitOfWork uow = uowf.newUnitOfWork();
-        try
-        {
-            List<Serializable> paramsList = new ArrayList<Serializable>( Arrays.asList( params ) );
-            createDebugRecord( uow, composite, message, paramsList );
-            uow.complete();
-        }
-        catch( ConcurrentEntityModificationException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-        catch( UnitOfWorkCompletionException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-    }
-
-    private void createDebugRecord( UnitOfWork uow, Composite composite, String message, List<Serializable> params )
-    {
-        if( composite instanceof ServiceComposite )
-        {
-            EntityBuilder<ServiceDebugRecordEntity> builder = uow.newEntityBuilder( ServiceDebugRecordEntity.class );
-            ServiceDebugRecordEntity state = builder.instance();
-            setStandardStuff( composite, message, state, params );
-            state.source().set( ( (ServiceComposite) composite ).identity().get() );
-            ServiceDebugRecordEntity slr = builder.newInstance();
-        }
-        else if( composite instanceof EntityComposite )
-        {
-            EntityBuilder<EntityDebugRecordEntity> builder = uow.newEntityBuilder( EntityDebugRecordEntity.class );
-            EntityDebugRecordEntity state = builder.instance();
-            setStandardStuff( composite, message, state, params );
-            state.source().set( (EntityComposite) composite );
-            EntityDebugRecordEntity elr = builder.newInstance();
-        }
-        else
-        {
-            EntityBuilder<CompositeDebugRecordEntity> builder = uow.newEntityBuilder( CompositeDebugRecordEntity.class );
-            CompositeDebugRecordEntity state = builder.instance();
-            setStandardStuff( composite, message, state, params );
-            state.source().set( composite );
-            CompositeDebugRecordEntity clr = builder.newInstance();
-        }
-    }
-
-    private void setStandardStuff( Composite composite, String message, DebugRecord state, List<Serializable> params )
-    {
-        state.time().set( System.currentTimeMillis() );
-        state.message().set( message );
-        state.compositeTypeName().set( getCompositeName( composite ) );
-        state.threadName().set( Thread.currentThread().getName() );
-        state.parameters().set( params );
-    }
-
-    private String getCompositeName( Composite composite )
-    {
-        return first( Qi4j.FUNCTION_DESCRIPTOR_FOR.map( composite ).types()).getName();
-    }
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/debug/service/package.html b/libraries/logging/src/main/java/org/qi4j/logging/debug/service/package.html
deleted file mode 100644
index 667c4ca..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/debug/service/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Debug Logging Service.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/CategoryLog.java b/libraries/logging/src/main/java/org/qi4j/logging/log/CategoryLog.java
deleted file mode 100644
index 73f96f7..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/CategoryLog.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.log;
-
-import java.io.Serializable;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-
-@Concerns( { CategoryLogConcern.class } )
-@Mixins( { CategoryLogMixin.class } )
-public interface CategoryLog
-{
-    void info( String category, String message );
-
-    void info( String category, String message, Serializable param1 );
-
-    void info( String category, String message, Serializable param1, Serializable param2 );
-
-    void info( String category, String message, Serializable... params );
-
-    void warning( String category, String message );
-
-    void warning( String category, String message, Serializable param1 );
-
-    void warning( String category, String message, Serializable param1, Serializable param2 );
-
-    void warning( String category, String message, Serializable... params );
-
-    void error( String category, String message );
-
-    void error( String category, String message, Serializable param1 );
-
-    void error( String category, String message, Serializable param1, Serializable param2 );
-
-    void error( String category, String message, Serializable... params );
-
-
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/CategoryLogConcern.java b/libraries/logging/src/main/java/org/qi4j/logging/log/CategoryLogConcern.java
deleted file mode 100644
index 4938e08..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/CategoryLogConcern.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.log;
-
-import java.io.Serializable;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.composite.TransientBuilderFactory;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.logging.log.service.LoggingService;
-
-public final class CategoryLogConcern
-    implements CategoryLog
-{
-    @Structure private Qi4j api;
-    @Optional @Service private LoggingService loggingService;
-    @This private Composite composite;
-
-    public CategoryLogConcern( @Structure TransientBuilderFactory cbf )
-    {
-    }
-
-    @Override
-    public void info( String category, String message )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.INFO, api.dereference( composite ), category, message );
-    }
-
-    @Override
-    public void info( String category, String message, Serializable param1 )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, param1 );
-    }
-
-    @Override
-    public void info( String category, String message, Serializable param1, Serializable param2 )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, param1, param2 );
-    }
-
-    @Override
-    public void info( String category, String message, Serializable... params )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, params );
-    }
-
-    @Override
-    public void warning( String category, String message )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.WARNING, api.dereference( composite ), category, message );
-    }
-
-    @Override
-    public void warning( String category, String message, Serializable param1 )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.WARNING, api.dereference( composite ), category, message, param1 );
-    }
-
-    @Override
-    public void warning( String category, String message, Serializable param1, Serializable param2 )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.WARNING, api.dereference( composite ), category, message, param1, param2 );
-    }
-
-    @Override
-    public void warning( String category, String message, Serializable... params )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.WARNING, api.dereference( composite ), category, message, params );
-    }
-
-    @Override
-    public void error( String category, String message )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.ERROR, api.dereference( composite ), category, message );
-    }
-
-    @Override
-    public void error( String category, String message, Serializable param1 )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.ERROR, api.dereference( composite ), category, message, param1 );
-    }
-
-    @Override
-    public void error( String category, String message, Serializable param1, Serializable param2 )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.ERROR, api.dereference( composite ), category, message, param1, param2 );
-    }
-
-    @Override
-    public void error( String category, String message, Serializable... params )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.ERROR, api.dereference( composite ), category, message, params );
-    }
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/CategoryLogMixin.java b/libraries/logging/src/main/java/org/qi4j/logging/log/CategoryLogMixin.java
deleted file mode 100644
index 2aed7c5..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/CategoryLogMixin.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.log;
-
-import java.io.Serializable;
-
-public class CategoryLogMixin
-    implements CategoryLog
-{
-    @Override
-    public void info( String category, String message )
-    {
-    }
-
-    @Override
-    public void info( String category, String message, Serializable param1 )
-    {
-    }
-
-    @Override
-    public void info( String category, String message, Serializable param1, Serializable param2 )
-    {
-    }
-
-    @Override
-    public void info( String category, String message, Serializable... params )
-    {
-    }
-
-    @Override
-    public void warning( String category, String message )
-    {
-    }
-
-    @Override
-    public void warning( String category, String message, Serializable param1 )
-    {
-    }
-
-    @Override
-    public void warning( String category, String message, Serializable param1, Serializable param2 )
-    {
-    }
-
-    @Override
-    public void warning( String category, String message, Serializable... params )
-    {
-    }
-
-    @Override
-    public void error( String category, String message )
-    {
-    }
-
-    @Override
-    public void error( String category, String message, Serializable param1 )
-    {
-    }
-
-    @Override
-    public void error( String category, String message, Serializable param1, Serializable param2 )
-    {
-    }
-
-    @Override
-    public void error( String category, String message, Serializable... params )
-    {
-    }
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/LogType.java b/libraries/logging/src/main/java/org/qi4j/logging/log/LogType.java
deleted file mode 100644
index dfcb258..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/LogType.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.log;
-
-public enum LogType
-{
-    INFO, WARNING, ERROR
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/SimpleLog.java b/libraries/logging/src/main/java/org/qi4j/logging/log/SimpleLog.java
deleted file mode 100644
index 3265660..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/SimpleLog.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.log;
-
-import java.io.Serializable;
-import org.qi4j.api.concern.Concerns;
-
-@Concerns( { SimpleLogConcern.class } )
-public interface SimpleLog
-{
-    void info( String message );
-
-    void info( String message, Serializable param1 );
-
-    void info( String message, Serializable param1, Serializable param2 );
-
-    void info( String message, Serializable... params );
-
-    void warning( String message );
-
-    void warning( String message, Serializable param1 );
-
-    void warning( String message, Serializable param1, Serializable param2 );
-
-    void warning( String message, Serializable... params );
-
-    void error( String message );
-
-    void error( String message, Serializable param1 );
-
-    void error( String message, Serializable param1, Serializable param2 );
-
-    void error( String message, Serializable... params );
-
-
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/SimpleLogConcern.java b/libraries/logging/src/main/java/org/qi4j/logging/log/SimpleLogConcern.java
deleted file mode 100644
index d096aa5..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/SimpleLogConcern.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.log;
-
-import java.io.Serializable;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.logging.log.service.LoggingService;
-
-import static org.qi4j.functional.Iterables.first;
-
-public final class SimpleLogConcern
-    implements SimpleLog
-{
-    @Structure private Qi4j api;
-    @Optional @Service private LoggingService loggingService;
-    private Composite composite;
-    private String category;
-
-    public SimpleLogConcern( @This Composite composite )
-    {
-        this.composite = composite;
-        Class<?> type = first( Qi4j.FUNCTION_DESCRIPTOR_FOR.map( composite ).types() );
-        category = type.getName();
-    }
-
-    @Override
-    public void info( String message )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.INFO, api.dereference( composite ), category, message );
-    }
-
-    @Override
-    public void info( String message, Serializable param1 )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, param1 );
-    }
-
-    @Override
-    public void info( String message, Serializable param1, Serializable param2 )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, param1, param2 );
-    }
-
-    @Override
-    public void info( String message, Serializable... params )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, params );
-    }
-
-    @Override
-    public void warning( String message )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.INFO, api.dereference( composite ), category, message );
-    }
-
-    @Override
-    public void warning( String message, Serializable param1 )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, param1 );
-    }
-
-    @Override
-    public void warning( String message, Serializable param1, Serializable param2 )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, param1, param2 );
-    }
-
-    @Override
-    public void warning( String message, Serializable... params )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, params );
-    }
-
-    @Override
-    public void error( String message )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.INFO, api.dereference( composite ), category, message );
-    }
-
-    @Override
-    public void error( String message, Serializable param1 )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, param1 );
-    }
-
-    @Override
-    public void error( String message, Serializable param1, Serializable param2 )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, param1, param2 );
-    }
-
-    @Override
-    public void error( String message, Serializable... params )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( LogType.INFO, api.dereference( composite ), category, message, params );
-    }
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/StandardLog.java b/libraries/logging/src/main/java/org/qi4j/logging/log/StandardLog.java
deleted file mode 100644
index 8a0b068..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/StandardLog.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.log;
-
-import java.io.Serializable;
-import org.qi4j.api.concern.Concerns;
-
-@Concerns( StandardLogConcern.class )
-public interface StandardLog
-{
-    void log( LogType type, String category, String message );
-
-    void log( LogType type, String category, String message, Serializable param1 );
-
-    void log( LogType type, String category, String message, Serializable param1, Serializable param2 );
-
-    void log( LogType type, String category, String message, Serializable... params );
-
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/StandardLogConcern.java b/libraries/logging/src/main/java/org/qi4j/logging/log/StandardLogConcern.java
deleted file mode 100644
index ab8cd03..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/StandardLogConcern.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.logging.log;
-
-import java.io.Serializable;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.logging.log.service.LoggingService;
-
-public class StandardLogConcern
-    implements StandardLog
-{
-    @Structure private Qi4j api;
-    @Optional @Service private LoggingService loggingService;
-    @This private Composite composite;
-
-    @Override
-    public void log( LogType type, String category, String message )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( type, api.dereference( composite ), category, message );
-    }
-
-    @Override
-    public void log( LogType type, String category, String message, Serializable param1 )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( type, api.dereference( composite ), category, message, param1 );
-    }
-
-    @Override
-    public void log( LogType type, String category, String message, Serializable param1, Serializable param2 )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( type, api.dereference( composite ), category, message, param1, param2 );
-    }
-
-    @Override
-    public void log( LogType type, String category, String message, Serializable... params )
-    {
-        if( loggingService == null )
-        {
-            return;
-        }
-        loggingService.log( type, api.dereference( composite ), category, message, params );
-    }
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/assemblies/LoggingAssembler.java b/libraries/logging/src/main/java/org/qi4j/logging/log/assemblies/LoggingAssembler.java
deleted file mode 100644
index dd2716d..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/assemblies/LoggingAssembler.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.logging.log.assemblies;
-
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.logging.log.service.LoggingServiceComposite;
-
-public class LoggingAssembler
-    implements Assembler
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( LoggingServiceComposite.class );
-    }
-
-}
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/assemblies/package.html b/libraries/logging/src/main/java/org/qi4j/logging/log/assemblies/package.html
deleted file mode 100644
index b2ed0f1..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/assemblies/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Logging Assembly.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/package.html b/libraries/logging/src/main/java/org/qi4j/logging/log/package.html
deleted file mode 100644
index f6ffb4c..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Logging.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/records/CompositeLogRecord.java b/libraries/logging/src/main/java/org/qi4j/logging/log/records/CompositeLogRecord.java
deleted file mode 100644
index cda672e..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/records/CompositeLogRecord.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.log.records;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-
-public interface CompositeLogRecord extends LogRecord, EntityComposite
-{
-    Property<Composite> source();
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/records/EntityLogRecord.java b/libraries/logging/src/main/java/org/qi4j/logging/log/records/EntityLogRecord.java
deleted file mode 100644
index 7578400..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/records/EntityLogRecord.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.log.records;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.entity.EntityComposite;
-
-public interface EntityLogRecord extends LogRecord
-{
-    Association<EntityComposite> source();
-
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/records/LogRecord.java b/libraries/logging/src/main/java/org/qi4j/logging/log/records/LogRecord.java
deleted file mode 100644
index 657845e..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/records/LogRecord.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.log.records;
-
-import java.io.Serializable;
-import java.util.List;
-import org.qi4j.api.property.Property;
-import org.qi4j.logging.log.LogType;
-
-public interface LogRecord
-{
-    Property<String> message();
-
-    Property<String> category();
-
-    Property<String> compositeTypeName();
-
-    Property<String> threadName();
-
-    Property<LogType> logtype();
-
-    Property<Long> time();
-
-    Property<List<Serializable>> parameters();
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/records/ServiceLogRecord.java b/libraries/logging/src/main/java/org/qi4j/logging/log/records/ServiceLogRecord.java
deleted file mode 100644
index fcb46a3..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/records/ServiceLogRecord.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.log.records;
-
-import org.qi4j.api.property.Property;
-
-public interface ServiceLogRecord extends LogRecord
-{
-    Property<String> source();
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/records/package.html b/libraries/logging/src/main/java/org/qi4j/logging/log/records/package.html
deleted file mode 100644
index 4e5fdc7..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/records/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Logging Records.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/service/LogOnConsoleSideEffect.java b/libraries/logging/src/main/java/org/qi4j/logging/log/service/LogOnConsoleSideEffect.java
deleted file mode 100644
index 72d3626..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/service/LogOnConsoleSideEffect.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.log.service;
-
-import java.io.PrintStream;
-import java.lang.reflect.Method;
-import java.text.MessageFormat;
-import java.util.ResourceBundle;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.injection.scope.Invocation;
-import org.qi4j.api.sideeffect.SideEffectOf;
-import org.qi4j.logging.log.LogType;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * The ConsoleViewSideEffect is just a temporary solution for logging output, until a more
- * robust framework has been designed.
- */
-public abstract class LogOnConsoleSideEffect extends SideEffectOf<LoggingService>
-    implements LoggingService
-{
-    private static PrintStream OUT = System.err;
-
-    private final ResourceBundle bundle;
-
-    public LogOnConsoleSideEffect( @Invocation Method thisMethod )
-    {
-        bundle = ResourceBundle.getBundle( thisMethod.getDeclaringClass().getName() );
-    }
-
-    public void log( LogType type, Composite composite, String category, String message )
-    {
-        String localized = bundle.getString( message );
-        String logType = type.name();
-        OUT.println( logType + ":" + category + ":" + getCompositeName( composite ) + ": " + localized );
-    }
-
-    private String getCompositeName( Composite composite )
-    {
-        return first( Qi4j.FUNCTION_DESCRIPTOR_FOR.map( composite ).types()).getName();
-    }
-
-    public void log( LogType type, Composite composite, String category, String message, Object param1 )
-    {
-        String localized = bundle.getString( message );
-        String formatted = MessageFormat.format( localized, param1 );
-        String logType = type.name();
-        OUT.println( logType + ":" + category + ":" + getCompositeName( composite ) + ": " + formatted );
-    }
-
-    public void log( LogType type, Composite composite, String category, String message, Object param1, Object param2 )
-    {
-        String localized = bundle.getString( message );
-        String formatted = MessageFormat.format( localized, param1, param2 );
-        String logtype = type.name();
-        OUT.println( logtype + ":" + category + ":" + getCompositeName( composite ) + ": " + formatted );
-    }
-
-    public void log( LogType type, Composite composite, String category, String message, Object... params )
-    {
-        String localized = bundle.getString( message );
-        String formatted = MessageFormat.format( localized, params );
-        String logType = type.name();
-        OUT.println( logType + ":" + category + ":" + getCompositeName( composite ) + ": " + formatted );
-    }
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/service/LoggingService.java b/libraries/logging/src/main/java/org/qi4j/logging/log/service/LoggingService.java
deleted file mode 100644
index c7cd09d..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/service/LoggingService.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.log.service;
-
-import java.io.Serializable;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.logging.log.LogType;
-
-public interface LoggingService
-{
-    void log( LogType type, Composite composite, String category, String message, Serializable... params );
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/service/LoggingServiceComposite.java b/libraries/logging/src/main/java/org/qi4j/logging/log/service/LoggingServiceComposite.java
deleted file mode 100644
index cf37e1e..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/service/LoggingServiceComposite.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.log.service;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.sideeffect.SideEffects;
-
-@SideEffects( { LogOnConsoleSideEffect.class } )
-@Mixins( { LoggingServiceMixin.class } )
-public interface LoggingServiceComposite extends LoggingService, ServiceComposite
-{
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/service/LoggingServiceMixin.java b/libraries/logging/src/main/java/org/qi4j/logging/log/service/LoggingServiceMixin.java
deleted file mode 100644
index 4360467..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/service/LoggingServiceMixin.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.log.service;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.unitofwork.ConcurrentEntityModificationException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.logging.log.LogType;
-import org.qi4j.logging.log.records.CompositeLogRecord;
-import org.qi4j.logging.log.records.EntityLogRecord;
-import org.qi4j.logging.log.records.LogRecord;
-import org.qi4j.logging.log.records.ServiceLogRecord;
-
-import static org.qi4j.functional.Iterables.first;
-
-public abstract class LoggingServiceMixin
-    implements LoggingService
-{
-    @Structure private UnitOfWorkFactory uowf;
-
-    public void log( LogType type, Composite composite, String category, String message )
-    {
-        UnitOfWork uow = uowf.newUnitOfWork();
-        try
-        {
-            List<Serializable> paramsList = new ArrayList<Serializable>();
-            createLogRecord( uow, type, composite, category, message, paramsList );
-            uow.complete();
-        }
-        catch( ConcurrentEntityModificationException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-        catch( UnitOfWorkCompletionException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-    }
-
-    public void log( LogType type, Composite composite, String category, String message, Serializable param1 )
-    {
-        UnitOfWork uow = uowf.newUnitOfWork();
-        try
-        {
-            List<Serializable> paramsList = new ArrayList<Serializable>();
-            paramsList.add( param1 );
-            createLogRecord( uow, type, composite, category, message, paramsList );
-            uow.complete();
-        }
-        catch( ConcurrentEntityModificationException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-        catch( UnitOfWorkCompletionException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-    }
-
-    public void log( LogType type, Composite composite, String category, String message, Serializable param1, Serializable param2 )
-    {
-        UnitOfWork uow = uowf.newUnitOfWork();
-        try
-        {
-            List<Serializable> paramsList = new ArrayList<Serializable>();
-            paramsList.add( param1 );
-            paramsList.add( param2 );
-            createLogRecord( uow, type, composite, category, message, paramsList );
-            uow.complete();
-        }
-        catch( ConcurrentEntityModificationException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-        catch( UnitOfWorkCompletionException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-    }
-
-    @Override
-    public void log( LogType type, Composite composite, String category, String message, Serializable... params )
-    {
-        UnitOfWork uow = uowf.newUnitOfWork();
-        try
-        {
-            List<Serializable> paramsList = new ArrayList<Serializable>( Arrays.asList( params ) );
-            createLogRecord( uow, type, composite, category, message, paramsList );
-            uow.complete();
-        }
-        catch( ConcurrentEntityModificationException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-        catch( UnitOfWorkCompletionException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-    }
-
-    private void createLogRecord( UnitOfWork uow, LogType type, Composite composite, String category, String message, List<Serializable> params )
-    {
-        if( composite instanceof ServiceComposite )
-        {
-            EntityBuilder<ServiceLogRecord> builder = uow.newEntityBuilder( ServiceLogRecord.class );
-            ServiceLogRecord state = builder.instance();
-            setStandardStuff( type, composite, category, message, state, params );
-            state.source().set( ( (ServiceComposite) composite ).identity().get() );
-            ServiceLogRecord slr = builder.newInstance();
-        }
-        else if( composite instanceof EntityComposite )
-        {
-            EntityBuilder<EntityLogRecord> builder = uow.newEntityBuilder( EntityLogRecord.class );
-            EntityLogRecord state = builder.instance();
-            setStandardStuff( type, composite, category, message, state, params );
-            state.source().set( (EntityComposite) composite );
-            EntityLogRecord elr = builder.newInstance();
-        }
-        else
-        {
-            EntityBuilder<CompositeLogRecord> builder = uow.newEntityBuilder( CompositeLogRecord.class );
-            CompositeLogRecord state = builder.instance();
-            setStandardStuff( type, composite, category, message, state, params );
-            state.source().set( composite );
-            CompositeLogRecord clr = builder.newInstance();
-        }
-    }
-
-    private void setStandardStuff( LogType type, Composite composite, String category, String message,
-                                   LogRecord state, List<Serializable> params )
-    {
-        state.logtype().set( type );
-        state.time().set( System.currentTimeMillis() );
-        state.category().set( category );
-        state.message().set( message );
-        state.compositeTypeName().set( getCompositeName( composite ) );
-        state.threadName().set( Thread.currentThread().getName() );
-        state.parameters().set( params );
-    }
-
-    private String getCompositeName( Composite composite )
-    {
-        return first( Qi4j.FUNCTION_DESCRIPTOR_FOR.map( composite ).types()).getName();
-    }
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/log/service/package.html b/libraries/logging/src/main/java/org/qi4j/logging/log/service/package.html
deleted file mode 100644
index 2f3d69a..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/log/service/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Logging Service.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/AbstractTraceConcern.java b/libraries/logging/src/main/java/org/qi4j/logging/trace/AbstractTraceConcern.java
deleted file mode 100644
index 6955195..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/AbstractTraceConcern.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.trace;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.logging.trace.service.TraceService;
-
-
-public abstract class AbstractTraceConcern extends ConcernOf<InvocationHandler>
-    implements InvocationHandler
-{
-    @Structure private Qi4j api;
-    @Optional @Service protected TraceService traceService;
-    private Composite thisComposite;
-    private Class compositeType;
-
-    public AbstractTraceConcern( Composite thisComposite )
-    {
-        this.thisComposite = thisComposite;
-        compositeType = thisComposite.getClass().getInterfaces()[ 0 ];
-    }
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        boolean doTrace = traceService != null && doTrace();
-        Object result;
-        long entryTime = 0;
-        long timeStamp = 0;
-        try
-        {
-            if( doTrace )
-            {
-                entryTime = System.currentTimeMillis();
-                timeStamp = System.nanoTime();
-            }
-            result = next.invoke( proxy, method, args );
-            if( doTrace )
-            {
-                long duration = System.nanoTime() - timeStamp;
-                traceService.traceSuccess( compositeType, api.dereference( thisComposite ), method, args, result, entryTime, duration );
-            }
-        }
-        catch( Throwable t )
-        {
-            if( doTrace )
-            {
-                long duration = System.nanoTime() - timeStamp;
-                Composite object = api.dereference( thisComposite );
-                traceService.traceException( compositeType, object, method, args, t, entryTime, duration );
-            }
-            throw t;
-        }
-        return result;
-    }
-
-    protected boolean doTrace()
-    {
-        return true;
-    }
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/ExcludeCompositeFilter.java b/libraries/logging/src/main/java/org/qi4j/logging/trace/ExcludeCompositeFilter.java
deleted file mode 100644
index cf79c1e..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/ExcludeCompositeFilter.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.trace;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesToFilter;
-import org.qi4j.api.composite.Composite;
-
-public class ExcludeCompositeFilter
-    implements AppliesToFilter
-{
-    @Override
-    public boolean appliesTo( Method method, Class mixin, Class compositeType, Class modifierClass )
-    {
-        return method.getDeclaringClass() != Composite.class;
-    }
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/Trace.java b/libraries/logging/src/main/java/org/qi4j/logging/trace/Trace.java
deleted file mode 100644
index c56eeb0..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/Trace.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.trace;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.qi4j.api.injection.InjectionScope;
-
-/**
- * The Trace annotation is to indicate which methods should be traced when tracing is enabled.
- * <p>
- * The <i>level</i> of the Trace indicates the <i>threshold level</i> that the <code>Tracer</code> instance must be set
- * to, to enable tracing. If the <i>threshold level</i> of the <code>Tracer</code> instance is equal to or higher than
- * the <i>level</i> of the <code>Trace</code> annotation the method will be traced.
- * </p>
- * <p>
- * The <code>Trace</code> annotation will only be used for <code>TraceConcern</code> and not if the
- * all encompassing <code>TraceAllConcern</code> is used.
- * </p>
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.METHOD } )
-@Documented
-@InjectionScope
-public @interface Trace
-{
-    int ALL = Integer.MIN_VALUE;
-    int LOWLOW = -100;
-    int LOW = -50;
-    int NORMAL = 0;
-    int HIGH = 50;
-    int HIGHHIGH = 100;
-    int OFF = Integer.MAX_VALUE;
-
-    /**
-     * The value is the threshold level required to enable the tracing.
-     * <p>
-     * If the Trace level is set to 100 (default), it is required that the
-     * Tracer (retrieved from the LogService) used is set to 100 or higher.
-     * </p>
-     *
-     * @return the Trace Level of this Trace annotation.
-     */
-    int level() default NORMAL;
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/TraceAllConcern.java b/libraries/logging/src/main/java/org/qi4j/logging/trace/TraceAllConcern.java
deleted file mode 100644
index f09cb3f..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/TraceAllConcern.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.trace;
-
-import java.lang.reflect.InvocationHandler;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.injection.scope.This;
-
-/**
- * The TraceAllConcern will call the traceEntry(), traceExit() and traceException() methods in the
- * Tracer instance associated with the CompositeType that the TraceAllConcern is part of.
- * <p>
- * The Trace paradigm is all about tracking the entry and exit (both normal and exceptional ones)
- * of methods.
- * </p>
- * <p>
- * The main difference to the <code>TraceConcern</code> is that this concern is not associated with
- * the <code>@Trace</code> annotation, and all methods in the interfaces will be traced, unless
- * the LogService has turned off tracing.
- * </p>
- *
- * @see TraceConcern
- */
-@AppliesTo( ExcludeCompositeFilter.class )
-public final class TraceAllConcern extends AbstractTraceConcern
-    implements InvocationHandler
-{
-    public TraceAllConcern( @This Composite composite )
-    {
-        super( composite );
-    }
-
-    @Override
-    protected boolean doTrace()
-    {
-        return true;
-    }
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/TraceConcern.java b/libraries/logging/src/main/java/org/qi4j/logging/trace/TraceConcern.java
deleted file mode 100644
index 00ac950..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/TraceConcern.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.trace;
-
-import java.lang.reflect.InvocationHandler;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.injection.scope.Invocation;
-import org.qi4j.api.injection.scope.This;
-
-/**
- * The TraceConcern will call the traceEntry(), traceExit() and traceException() methods in the
- * Tracer instance associated with the CompositeType that the TraceConcern is part of.
- * <p>
- * The Trace paradigm is all about tracking the entry and exit (both normal and exceptional ones)
- * of methods. The TraceConcern will be added to all methods that declares the <code>@Trace</code>
- * annotation, with an optional <i>level</i> argument. The <i>level</i> is the threshold of the
- * Tracer instance required to trace the method, i.e. the <i>priority</i> of the Tracer instance
- * must be equal or higher than the <i>level</i> set in the <code>@Trace</code> annotation of the
- * method.
- * </p>
- * <p>
- * If the <i>priority</i> of the <code>Tracer</code> is set to OFF (Integer.MIN_VALUE) then no
- * tracing will happen.
- * </p>
- */
-@AppliesTo( Trace.class )
-public final class TraceConcern extends AbstractTraceConcern
-    implements InvocationHandler
-{
-    @Invocation private Trace trace;
-
-    public TraceConcern( @This Composite thisComposite )
-    {
-        super( thisComposite );
-    }
-
-    @Override
-    protected boolean doTrace()
-    {
-        return traceService.traceLevel() <= trace.level();
-    }
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/TraceOnConsoleSideEffect.java b/libraries/logging/src/main/java/org/qi4j/logging/trace/TraceOnConsoleSideEffect.java
deleted file mode 100644
index 5bc8761..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/TraceOnConsoleSideEffect.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.trace;
-
-import java.io.PrintStream;
-import java.lang.reflect.Method;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.sideeffect.SideEffectOf;
-import org.qi4j.logging.trace.service.TraceService;
-
-/**
- * The ConsoleViewSideEffect is just a temporary solution for logging output, until a more
- * robust framework has been designed.
- */
-public abstract class TraceOnConsoleSideEffect extends SideEffectOf<TraceService>
-    implements TraceService
-{
-    private static PrintStream OUT = System.err;
-
-    @Override
-    public void traceSuccess( Class compositeType, Composite object, Method method, Object[] args, Object result, long entryTime, long durationNano )
-    {
-        StringBuffer buf = new StringBuffer();
-        buf.append( durationNano / 1000000 );
-        buf.append( " ms: " );
-        formatMethod( buf, object, compositeType, method, args );
-        OUT.println( buf.toString() );
-        OUT.println( result );
-    }
-
-    @Override
-    public void traceException( Class compositeType, Composite object, Method method, Object[] args, Throwable t, long entryTime, long durationNano )
-    {
-        StringBuffer buf = new StringBuffer();
-        buf.append( "Exception: " );
-        buf.append( durationNano / 1000000 );
-        buf.append( " ms: " );
-        OUT.println( buf.toString() );
-        t.printStackTrace( OUT );
-    }
-
-    private void formatMethod( StringBuffer buf, Composite object, Class compositeType, Method method, Object[] args )
-    {
-        buf.append( compositeType.getClass().getName() );
-        buf.append( "." );
-        buf.append( method.getName() );
-        buf.append( "( " );
-        if( args != null )
-        {
-            boolean first = true;
-            for( Object arg : args )
-            {
-                if( !first )
-                {
-                    buf.append( ", " );
-                }
-                first = false;
-                if( arg instanceof String )
-                {
-                    buf.append( "\"" );
-                }
-                buf.append( arg );
-                if( arg instanceof String )
-                {
-                    buf.append( "\"" );
-                }
-            }
-        }
-        buf.append( " )  [ " );
-        if( object == null )
-        {
-            buf.append( "<null>" );
-        }
-        else
-        {
-            buf.append( object.toString() );
-        }
-        buf.append( " ]" );
-    }
-}
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/assemblies/TracingAssembler.java b/libraries/logging/src/main/java/org/qi4j/logging/trace/assemblies/TracingAssembler.java
deleted file mode 100644
index c962136..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/assemblies/TracingAssembler.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.logging.trace.assemblies;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.logging.trace.service.StandardTraceServiceComposite;
-import org.qi4j.logging.trace.service.TraceServiceConfiguration;
-
-public class TracingAssembler
-    implements Assembler
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( StandardTraceServiceComposite.class ).visibleIn( Visibility.application );
-        module.entities( TraceServiceConfiguration.class );
-    }
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/assemblies/package.html b/libraries/logging/src/main/java/org/qi4j/logging/trace/assemblies/package.html
deleted file mode 100644
index ba2e6e8..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/assemblies/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Trace Logging Assembly.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/package.html b/libraries/logging/src/main/java/org/qi4j/logging/trace/package.html
deleted file mode 100644
index 06071c6..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Trace Logging.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/records/CompositeTraceRecordEntity.java b/libraries/logging/src/main/java/org/qi4j/logging/trace/records/CompositeTraceRecordEntity.java
deleted file mode 100644
index be99202..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/records/CompositeTraceRecordEntity.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.trace.records;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-
-public interface CompositeTraceRecordEntity extends TraceRecord, EntityComposite
-{
-    Property<Composite> source();
-
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/records/EntityTraceRecordEntity.java b/libraries/logging/src/main/java/org/qi4j/logging/trace/records/EntityTraceRecordEntity.java
deleted file mode 100644
index a028014..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/records/EntityTraceRecordEntity.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.trace.records;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.Queryable;
-
-@Queryable( false )
-public interface EntityTraceRecordEntity extends TraceRecord, EntityComposite
-{
-    Association<EntityComposite> source();
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/records/ServiceTraceRecordEntity.java b/libraries/logging/src/main/java/org/qi4j/logging/trace/records/ServiceTraceRecordEntity.java
deleted file mode 100644
index 8105577..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/records/ServiceTraceRecordEntity.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.trace.records;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-
-public interface ServiceTraceRecordEntity extends TraceRecord, EntityComposite
-{
-    Property<String> source();
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/records/TraceRecord.java b/libraries/logging/src/main/java/org/qi4j/logging/trace/records/TraceRecord.java
deleted file mode 100644
index 89f1fe8..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/records/TraceRecord.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.trace.records;
-
-import java.util.List;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.api.property.Property;
-
-public interface TraceRecord
-{
-    Property<String> methodName();
-
-    Property<String> compositeTypeName();
-
-    Property<String> threadName();
-
-    Property<Long> entryTime();
-
-    Property<Long> duration();
-
-    @Optional Property<Throwable> exception();
-
-    @Queryable( false ) Property<List<String>> arguments();
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/records/package.html b/libraries/logging/src/main/java/org/qi4j/logging/trace/records/package.html
deleted file mode 100644
index 8427d7c..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/records/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Trace Logging Records.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/service/StandardTraceServiceComposite.java b/libraries/logging/src/main/java/org/qi4j/logging/trace/service/StandardTraceServiceComposite.java
deleted file mode 100644
index f6e5773..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/service/StandardTraceServiceComposite.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.logging.trace.service;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.sideeffect.SideEffects;
-import org.qi4j.logging.trace.TraceOnConsoleSideEffect;
-
-@SideEffects( TraceOnConsoleSideEffect.class )
-@Mixins( TraceServiceMixin.class )
-public interface StandardTraceServiceComposite extends TraceService, ServiceComposite
-{
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/service/TraceService.java b/libraries/logging/src/main/java/org/qi4j/logging/trace/service/TraceService.java
deleted file mode 100644
index f820f54..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/service/TraceService.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.logging.trace.service;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.Composite;
-
-public interface TraceService
-{
-    int traceLevel();
-
-    void traceSuccess( Class compositeType, Composite object, Method method, @Optional Object[] args, Object result, long entryTime, long durationNano );
-
-    void traceException( Class compositeType, Composite object, Method method, @Optional Object[] args, Throwable t, long entryTime, long durationNano );
-
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/service/TraceServiceConfiguration.java b/libraries/logging/src/main/java/org/qi4j/logging/trace/service/TraceServiceConfiguration.java
deleted file mode 100644
index 078330c..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/service/TraceServiceConfiguration.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.logging.trace.service;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-public interface TraceServiceConfiguration extends ConfigurationComposite
-{
-    @UseDefaults Property<Integer> traceLevel();
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/service/TraceServiceMixin.java b/libraries/logging/src/main/java/org/qi4j/logging/trace/service/TraceServiceMixin.java
deleted file mode 100644
index 8f20625..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/service/TraceServiceMixin.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.logging.trace.service;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.unitofwork.ConcurrentEntityModificationException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.logging.trace.records.CompositeTraceRecordEntity;
-import org.qi4j.logging.trace.records.EntityTraceRecordEntity;
-import org.qi4j.logging.trace.records.ServiceTraceRecordEntity;
-import org.qi4j.logging.trace.records.TraceRecord;
-
-import static org.qi4j.functional.Iterables.first;
-
-public class TraceServiceMixin
-    implements TraceService
-{
-    @Structure private UnitOfWorkFactory uowf;
-    @This private Configuration<TraceServiceConfiguration> configuration;
-    private int counter;
-    private Integer traceLevel;
-
-    @Override
-    public int traceLevel()
-    {
-        if( counter++ % 100 == 0 )
-        {
-            counter = 0;
-            traceLevel = configuration.get().traceLevel().get();
-        }
-        return traceLevel;
-    }
-
-    @Override
-    public void traceSuccess( Class compositeType, Composite object, Method method, Object[] args, Object result, long entryTime, long durationNano )
-    {
-        UnitOfWork uow = uowf.newUnitOfWork();
-        try
-        {
-            createTraceRecord( uow, compositeType, object, method, args, entryTime, durationNano, null );
-            uow.complete();
-        }
-        catch( ConcurrentEntityModificationException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-        catch( UnitOfWorkCompletionException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-    }
-
-    @Override
-    public void traceException( Class compositeType, Composite object, Method method, Object[] args, Throwable t, long entryTime, long durationNano )
-    {
-        UnitOfWork uow = uowf.newUnitOfWork();
-        try
-        {
-            createTraceRecord( uow, compositeType, object, method, args, entryTime, durationNano, t );
-            uow.complete();
-        }
-        catch( ConcurrentEntityModificationException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-        catch( UnitOfWorkCompletionException e )
-        {
-            // ignore for now. Perhaps discard() and try again.
-        }
-    }
-
-    private void createTraceRecord( UnitOfWork uow, Class compositeType, Composite object, Method method, Object[] args, long entryTime, long durationNano, Throwable exception )
-    {
-        if( object instanceof EntityComposite )
-        {
-            EntityComposite entity = (EntityComposite) object;
-            String identity = entity.identity().get();
-            EntityComposite source = (EntityComposite) uow.get( (Class<?>) first(
-                Qi4j.FUNCTION_DESCRIPTOR_FOR.map( entity ).types() ), identity );
-            EntityBuilder<EntityTraceRecordEntity> builder = uow.newEntityBuilder( EntityTraceRecordEntity.class );
-            EntityTraceRecordEntity state = builder.instance();
-            setStandardStuff( compositeType, method, args, entryTime, durationNano, state, exception );
-            state.source().set( source );
-            EntityTraceRecordEntity etr = builder.newInstance();  // Record is created.
-        }
-        else if( object instanceof ServiceComposite )
-        {
-            ServiceComposite service = (ServiceComposite) object;
-            EntityBuilder<ServiceTraceRecordEntity> builder = uow.newEntityBuilder( ServiceTraceRecordEntity.class );
-            ServiceTraceRecordEntity state = builder.instance();
-            setStandardStuff( compositeType, method, args, entryTime, durationNano, state, exception );
-            state.source().set( service.toString() );
-            ServiceTraceRecordEntity str = builder.newInstance();  // Record is created.
-        }
-        else
-        {
-            EntityBuilder<CompositeTraceRecordEntity> builder = uow.newEntityBuilder( CompositeTraceRecordEntity.class );
-            CompositeTraceRecordEntity state = builder.instance();
-            state.source().set( object );
-            setStandardStuff( compositeType, method, args, entryTime, durationNano, state, exception );
-            CompositeTraceRecordEntity ctr = builder.newInstance();  // Record is created.
-        }
-    }
-
-    private void setStandardStuff( Class compositeType, Method method, Object[] args, long entryTime, long durationNano, TraceRecord state, Throwable exception )
-    {
-        state.duration().set( durationNano );
-        state.entryTime().set( entryTime );
-        state.methodName().set( method.getName() );
-        state.compositeTypeName().set( compositeType.getName() );
-        state.arguments().set( convertArguments( args ) );
-        state.threadName().set( Thread.currentThread().getName() );
-        state.exception().set( exception );
-    }
-
-    private List<String> convertArguments( Object[] args )
-    {
-        if( args == null )
-        {
-            return new ArrayList<String>( 0 );
-        }
-        List<String> result = new ArrayList<String>( args.length );
-        for( Object arg : args )
-        {
-            if( arg == null )
-            {
-                result.add( null );
-            }
-            else
-            {
-                result.add( arg.toString() );
-            }
-        }
-        return result;
-    }
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/trace/service/package.html b/libraries/logging/src/main/java/org/qi4j/logging/trace/service/package.html
deleted file mode 100644
index ef86918..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/trace/service/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Trace Logging Service.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/view/ConsoleViewerComposite.java b/libraries/logging/src/main/java/org/qi4j/logging/view/ConsoleViewerComposite.java
deleted file mode 100644
index 683d202..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/view/ConsoleViewerComposite.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.view;
-
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.mixin.Mixins;
-
-@Mixins( { ConsoleViewerMixin.class } )
-public interface ConsoleViewerComposite extends Composite
-{
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/view/ConsoleViewerMixin.java b/libraries/logging/src/main/java/org/qi4j/logging/view/ConsoleViewerMixin.java
deleted file mode 100644
index a5cf8de..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/view/ConsoleViewerMixin.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.view;
-
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.logging.log.service.LoggingService;
-
-public class ConsoleViewerMixin
-    implements LogServiceListener
-{
-    @Service private LoggingService service;
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/view/LogServiceListener.java b/libraries/logging/src/main/java/org/qi4j/logging/view/LogServiceListener.java
deleted file mode 100644
index 04afb63..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/view/LogServiceListener.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.view;
-
-public interface LogServiceListener
-{
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/view/SwingViewer.java b/libraries/logging/src/main/java/org/qi4j/logging/view/SwingViewer.java
deleted file mode 100644
index 8626c74..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/view/SwingViewer.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging.view;
-
-import javax.swing.*;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.logging.log.service.LoggingService;
-
-public class SwingViewer extends JFrame
-{
-    @Service private Iterable<LoggingService> services;
-}
diff --git a/libraries/logging/src/main/java/org/qi4j/logging/view/package.html b/libraries/logging/src/main/java/org/qi4j/logging/view/package.html
deleted file mode 100644
index ba513ab..0000000
--- a/libraries/logging/src/main/java/org/qi4j/logging/view/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Log Viewers.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/logging/src/test/java/org/apache/polygene/library/logging/DebuggingTest.java b/libraries/logging/src/test/java/org/apache/polygene/library/logging/DebuggingTest.java
new file mode 100644
index 0000000..407d309
--- /dev/null
+++ b/libraries/logging/src/test/java/org/apache/polygene/library/logging/DebuggingTest.java
@@ -0,0 +1,140 @@
+/*
+ *  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.polygene.library.logging;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.logging.debug.Debug;
+import org.apache.polygene.library.logging.debug.DebugConcern;
+import org.apache.polygene.library.logging.debug.records.ServiceDebugRecordEntity;
+import org.apache.polygene.library.logging.debug.service.DebugServiceConfiguration;
+import org.apache.polygene.library.logging.debug.service.DebuggingServiceComposite;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class DebuggingTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( DebuggingServiceComposite.class );
+        new EntityTestAssembler().assemble( module );
+        module.services( SomeService.class ).withMixins( Debug.class ).withConcerns( DebugConcern.class );
+        module.entities( DebugServiceConfiguration.class );
+        module.entities( ServiceDebugRecordEntity.class );
+    }
+
+    @Test
+    public void whenCallingMethodThenExpectDebugEntityCreated()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            // There is no Query capability available for Libraries, since that sits in Extensions.
+            // Obtaining the EntityStore directly is a very ugly hack to get around this problem, and only related
+            // to the test sitting in libraries/ source repository.
+
+//            QueryBuilder<DebugRecord> builder = module.newQueryBuilder( DebugRecord.class );
+//            Query<DebugRecord> query = builder.newQuery( uow );
+//            assertEquals( 0, query.count() );
+            Some service = serviceFinder.findService( Some.class ).get();
+            String message = service.doSomething( "World!", 10 );
+            assertEquals( message, "Hello!" );
+            EntityStore es = serviceFinder.findService( EntityStore.class ).get();
+            final Identity[] result = new Identity[1];
+            try( Stream<EntityState> entityStates = es.entityStates( module ) )
+            {
+                entityStates
+                    .forEach( entityState ->
+                              {
+                                  if( ServiceDebugRecordEntity.class.getName().equals(
+                                      entityState.entityDescriptor().types().findFirst().get().getName() ) )
+                                  {
+                                      result[ 0 ] = entityState.entityReference().identity();
+                                  }
+                              } );
+            }
+
+            ServiceDebugRecordEntity debugEntry = uow.get( ServiceDebugRecordEntity.class, result[ 0 ] );
+            String mess = debugEntry.message().get();
+            System.out.println( mess );
+            assertEquals( "some message.", mess );
+            uow.complete();
+        }
+        catch( ConcurrentEntityModificationException e )
+        {
+            e.printStackTrace();
+            uow.discard();
+        }
+        catch( UnitOfWorkCompletionException e )
+        {
+            e.printStackTrace();
+            uow.discard();
+        }
+        finally
+        {
+            if( uow.isOpen() )
+            {
+                uow.discard();
+            }
+        }
+    }
+
+    public interface Some
+    {
+        String doSomething( String value1, Integer value2 );
+    }
+
+    @Mixins( { SomeMixin.class } )
+    public interface SomeService
+        extends Some, ServiceComposite
+    {
+    }
+
+    public static class SomeMixin
+        implements Some
+    {
+        @This
+        private Debug debug;
+
+        public String doSomething( String value1, Integer value2 )
+        {
+            System.out.println( "DebugLevel: " + debug.debugLevel() );
+            debug.debug( 99, "some lower priority message not being stored." );
+            debug.debug( 100, "some message." );
+            return "Hello!";
+        }
+    }
+}
diff --git a/libraries/logging/src/test/java/org/apache/polygene/library/logging/TracingTest.java b/libraries/logging/src/test/java/org/apache/polygene/library/logging/TracingTest.java
new file mode 100644
index 0000000..852a868
--- /dev/null
+++ b/libraries/logging/src/test/java/org/apache/polygene/library/logging/TracingTest.java
@@ -0,0 +1,257 @@
+/*
+ *  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.polygene.library.logging;
+
+import org.junit.Test;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.rdf.assembly.RdfMemoryStoreAssembler;
+import org.apache.polygene.library.logging.trace.Trace;
+import org.apache.polygene.library.logging.trace.TraceAllConcern;
+import org.apache.polygene.library.logging.trace.TraceConcern;
+import org.apache.polygene.library.logging.trace.assemblies.TracingAssembler;
+import org.apache.polygene.library.logging.trace.records.CompositeTraceRecordEntity;
+import org.apache.polygene.library.logging.trace.records.EntityTraceRecordEntity;
+import org.apache.polygene.library.logging.trace.records.ServiceTraceRecordEntity;
+import org.apache.polygene.library.logging.trace.records.TraceRecord;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import java.util.Iterator;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.*;
+import static org.apache.polygene.api.query.QueryExpressions.orderBy;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+
+public class TracingTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( SomeService.class ).instantiateOnStartup();
+        module.services( SomeService2.class ).instantiateOnStartup();
+        new TracingAssembler().assemble( module );
+        new EntityTestAssembler().assemble( module );
+        new RdfMemoryStoreAssembler().assemble( module );
+        module.entities( CompositeTraceRecordEntity.class );
+        module.entities( EntityTraceRecordEntity.class );
+        module.entities( ServiceTraceRecordEntity.class );
+    }
+
+    @Test
+    public void whenTraceOnMixinTypeMethodExpectOneEntryInEntityStore()
+        throws Exception
+    {
+        SomeService sc = serviceFinder.findService( SomeService.class ).get();
+        assertEquals( 123, sc.doSomethingImportant() );
+        assertEquals( 456, sc.doSomethingLessImportant() );
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        QueryBuilder<TraceRecord> builder = queryBuilderFactory.newQueryBuilder( TraceRecord.class );
+        Query<TraceRecord> query = uow.newQuery( builder );
+        // IS sorting needed??
+//        TraceRecord template = templateFor( TraceRecord.class );
+//        query.orderBy( orderBy( template.methodName() ) );
+        Iterator<TraceRecord> result = query.iterator();
+        assertTrue( result.hasNext() );
+        TraceRecord rec1 = result.next();
+        assertEquals( "doSomethingImportant", rec1.methodName().get() );
+        assertFalse( result.hasNext() );
+        uow.complete();
+    }
+
+    @Test
+    public void whenTraceAllOnCompositeTypeExpectTwoEntryInEntityStore()
+        throws Exception
+    {
+        SomeService2 sc = serviceFinder.findService( SomeService2.class ).get();
+        assertEquals( 123, sc.doSomethingImportant() );
+        assertEquals( 456, sc.doSomethingLessImportant() );
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        QueryBuilder<TraceRecord> builder = queryBuilderFactory.newQueryBuilder( TraceRecord.class );
+        Query<TraceRecord> query = uow.newQuery( builder );
+        // IS sorting needed??
+//        TraceRecord template = templateFor( TraceRecord.class );
+//        query.orderBy( orderBy( template.methodName() ) );
+        Iterator<TraceRecord> result = query.iterator();
+        assertTrue( result.hasNext() );
+        TraceRecord rec1 = result.next();
+        assertEquals( "doSomethingImportant", rec1.methodName().get() );
+        assertTrue( result.hasNext() );
+        TraceRecord rec2 = result.next();
+        assertEquals( "doSomethingLessImportant", rec2.methodName().get() );
+        assertFalse( result.hasNext() );
+        uow.complete();
+    }
+
+    @Test
+    public void whenTraceOnMixinImplExpectTwoEntryInEntityStore()
+        throws Exception
+    {
+        SomeService sc = serviceFinder.findService( SomeService.class ).get();
+        assertEquals( 123, sc.doSomethingImportant() );
+        assertEquals( 789, sc.doSomethingModeratelyImportant() );
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            QueryBuilder<TraceRecord> builder = queryBuilderFactory.newQueryBuilder( TraceRecord.class );
+            Query<TraceRecord> query = uow.newQuery( builder );
+            // IS sorting needed??
+            TraceRecord template = templateFor( TraceRecord.class );
+            query.orderBy( orderBy( template.methodName() ) );
+            Iterator<TraceRecord> result = query.iterator();
+            assertTrue( result.hasNext() );
+            TraceRecord rec1 = result.next();
+            assertEquals( "doSomethingImportant", rec1.methodName().get() );
+            assertTrue( result.hasNext() );
+            TraceRecord rec2 = result.next();
+            assertEquals( "doSomethingModeratelyImportant", rec2.methodName().get() );
+            assertFalse( result.hasNext() );
+            uow.complete();
+        }
+        catch( Exception e )
+        {
+            uow.discard();
+            throw e;
+        }
+        catch( Error e )
+        {
+            uow.discard();
+            throw e;
+        }
+    }
+
+    @Test
+    public void whenTraceOnConcernExpectOneEntryInEntityStore()
+        throws Exception
+    {
+        // It is not possible to put Annotation on Concern Methods, so it should only record one.
+
+        SomeService sc = serviceFinder.findService( SomeService.class ).get();
+        assertEquals( 123, sc.doSomethingImportant() );
+        assertEquals( 753, sc.doSomethingInsanelyImportant() );
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        QueryBuilder<TraceRecord> builder = queryBuilderFactory.newQueryBuilder( TraceRecord.class );
+        Query<TraceRecord> query = uow.newQuery( builder );
+        // IS sorting needed??
+//        TraceRecord template = templateFor( TraceRecord.class );
+//        query.orderBy( orderBy( template.methodName() ) );
+        Iterator<TraceRecord> result = query.iterator();
+        assertTrue( result.hasNext() );
+        TraceRecord rec1 = result.next();
+        assertEquals( "doSomethingImportant", rec1.methodName().get() );
+        assertFalse( result.hasNext() );
+        uow.complete();
+    }
+
+    @Mixins( SomeMixin.class )
+    @Concerns( { SomeConcern.class, TraceConcern.class } )
+    public interface SomeService
+        extends Some, ServiceComposite
+    {
+    }
+
+    @Mixins( SomeMixin.class )
+    @Concerns( { SomeConcern.class, TraceAllConcern.class } )
+    public interface SomeService2
+        extends Some, ServiceComposite
+    {
+    }
+
+    public interface Some
+    {
+        @Trace
+        int doSomethingImportant();
+
+        int doSomethingLessImportant();
+
+        int doSomethingModeratelyImportant();
+
+        int doSomethingInsanelyImportant();
+    }
+
+    public static class SomeConcern
+        extends ConcernOf<Some>
+        implements Some
+    {
+        public int doSomethingImportant()
+        {
+            System.out.println( "-- doSomethingImportant()" );
+            return next.doSomethingImportant();
+        }
+
+        public int doSomethingLessImportant()
+        {
+            System.out.println( "-- doSomethingLessImportant()" );
+            return next.doSomethingLessImportant();
+        }
+
+        public int doSomethingModeratelyImportant()
+        {
+            System.out.println( "-- doSomethingLessImportant()" );
+            return next.doSomethingModeratelyImportant();
+        }
+
+        @Trace
+        public int doSomethingInsanelyImportant()
+        {
+            System.out.println( "-- doSomethingInsanelyImportant()" );
+            return next.doSomethingInsanelyImportant();
+        }
+    }
+
+    public static class SomeMixin
+        implements Some
+    {
+
+        public int doSomethingImportant()
+        {
+            System.out.println( "---- doSomethingImportant()" );
+            return 123;
+        }
+
+        public int doSomethingLessImportant()
+        {
+            System.out.println( "---- doSomethingLessImportant()" );
+            return 456;
+        }
+
+        @Trace
+        public int doSomethingModeratelyImportant()
+        {
+            System.out.println( "---- doSomethingModeratelyImportant()" );
+            return 789;
+        }
+
+        public int doSomethingInsanelyImportant()
+        {
+            System.out.println( "---- doSomethingInsanelyImportant()" );
+            return 753;
+        }
+    }
+}
diff --git a/libraries/logging/src/test/java/org/apache/polygene/library/logging/docsupport/LoggingDocs.java b/libraries/logging/src/test/java/org/apache/polygene/library/logging/docsupport/LoggingDocs.java
new file mode 100644
index 0000000..869fbe5
--- /dev/null
+++ b/libraries/logging/src/test/java/org/apache/polygene/library/logging/docsupport/LoggingDocs.java
@@ -0,0 +1,72 @@
+/*
+ *  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.polygene.library.logging.docsupport;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.logging.debug.Debug;
+import org.apache.polygene.library.logging.trace.Trace;
+import org.apache.polygene.library.logging.trace.TraceAllConcern;
+
+public class LoggingDocs
+{
+
+// START SNIPPET: logging1
+    @Optional @This Debug debug;
+// END SNIPPET: logging1
+
+    public LoggingDocs()
+    {
+// START SNIPPET: logging2
+        if( debug != null )
+        {
+            debug.debug( Debug.NORMAL, "Debugging is made easier." );
+        }
+// END SNIPPET: logging2
+     }
+
+// START SNIPPET: logging3
+    public interface ImportantRepository
+    {
+        @Trace
+        void addImportantStuff( ImportantStuff stuff );
+
+        @Trace
+        void removeImportantStuff( ImportantStuff stuff );
+
+        ImportantStuff findImportantStuff( String searchKey );
+    }
+// END SNIPPET: logging3
+
+// START SNIPPET: logging4
+    public void assemble( ModuleAssembly module )
+            throws AssemblyException
+    {
+        module.addServices(ImportantRepository.class)
+                .withConcerns( TraceAllConcern.class )
+                .withMixins( Debug.class );
+    }
+
+// END SNIPPET: logging4
+
+    class ImportantStuff {}
+}
diff --git a/libraries/logging/src/test/java/org/qi4j/logging/DebuggingTest.java b/libraries/logging/src/test/java/org/qi4j/logging/DebuggingTest.java
deleted file mode 100644
index 108da7a..0000000
--- a/libraries/logging/src/test/java/org/qi4j/logging/DebuggingTest.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging;
-
-import org.junit.Ignore;
-import org.junit.Test;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.unitofwork.ConcurrentEntityModificationException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Function;
-import org.qi4j.io.Outputs;
-import org.qi4j.io.Transforms;
-import org.qi4j.logging.debug.Debug;
-import org.qi4j.logging.debug.DebugConcern;
-import org.qi4j.logging.debug.records.ServiceDebugRecordEntity;
-import org.qi4j.logging.debug.service.DebugServiceConfiguration;
-import org.qi4j.logging.debug.service.DebuggingServiceComposite;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.assertEquals;
-import static org.qi4j.functional.Iterables.first;
-
-public class DebuggingTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( DebuggingServiceComposite.class );
-        new EntityTestAssembler().assemble( module );
-        module.services( SomeService.class ).withMixins( Debug.class ).withConcerns( DebugConcern.class );
-        module.entities( DebugServiceConfiguration.class );
-        module.entities( ServiceDebugRecordEntity.class );
-        module.services( UuidIdentityGeneratorService.class );
-    }
-
-    @Test
-    public void whenCallingMethodThenExpectDebugEntityCreated()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            // There is no Query capability available for Libraries, since that sits in Extensions.
-            // Obtaining the EntityStore directly is a very ugly hack to get around this problem, and only related
-            // to the test sitting in qi4j-libraries source repository.
-
-//            QueryBuilder<DebugRecord> builder = module.newQueryBuilder( DebugRecord.class );
-//            Query<DebugRecord> query = builder.newQuery( uow );
-//            assertEquals( 0, query.count() );
-            Some service = (Some) module.findService( Some.class ).get();
-            String message = service.doSomething( "World!", 10 );
-            assertEquals( message, "Hello!" );
-            EntityStore es = (EntityStore) module.findService( EntityStore.class ).get();
-            final String[] result = new String[1];
-            es.entityStates( module ).transferTo( Transforms.map( new Function<EntityState, EntityState>()
-                    {
-                        public EntityState map( EntityState entityState )
-                        {
-                            if( ServiceDebugRecordEntity.class.getName()
-                                    .equals( first(entityState.entityDescriptor().types()).getName() ) )
-                            {
-                                result[0] = entityState.identity().identity();
-                            }
-
-                            return entityState;
-                        }
-                    }, Outputs.<EntityState>noop() ));
-
-            ServiceDebugRecordEntity debugEntry = uow.get( ServiceDebugRecordEntity.class, result[ 0 ] );
-            String mess = debugEntry.message().get();
-            System.out.println( mess );
-            assertEquals( "some message.", mess );
-            uow.complete();
-        }
-        catch( ConcurrentEntityModificationException e )
-        {
-            e.printStackTrace();
-            uow.discard();
-        }
-        catch( UnitOfWorkCompletionException e )
-        {
-            e.printStackTrace();
-            uow.discard();
-        }
-        finally
-        {
-            if( uow.isOpen() )
-            {
-                uow.discard();
-            }
-        }
-    }
-
-    public interface Some
-    {
-        String doSomething( String value1, Integer value2 );
-    }
-
-    @Mixins( { SomeMixin.class } )
-    public interface SomeService
-        extends Some, ServiceComposite
-    {
-    }
-
-    public static class SomeMixin
-        implements Some
-    {
-        @This
-        private Debug debug;
-
-        public String doSomething( String value1, Integer value2 )
-        {
-            System.out.println( "DebugLevel: " + debug.debugLevel() );
-            debug.debug( 99, "some lower priority message not being stored." );
-            debug.debug( 100, "some message." );
-            return "Hello!";
-        }
-    }
-}
diff --git a/libraries/logging/src/test/java/org/qi4j/logging/TracingTest.java b/libraries/logging/src/test/java/org/qi4j/logging/TracingTest.java
deleted file mode 100644
index 9af63dc..0000000
--- a/libraries/logging/src/test/java/org/qi4j/logging/TracingTest.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright 2006 Niclas Hedhman.
- *
- * Licensed  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.qi4j.logging;
-
-import org.junit.Test;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.rdf.assembly.RdfMemoryStoreAssembler;
-import org.qi4j.logging.trace.Trace;
-import org.qi4j.logging.trace.TraceAllConcern;
-import org.qi4j.logging.trace.TraceConcern;
-import org.qi4j.logging.trace.assemblies.TracingAssembler;
-import org.qi4j.logging.trace.records.CompositeTraceRecordEntity;
-import org.qi4j.logging.trace.records.EntityTraceRecordEntity;
-import org.qi4j.logging.trace.records.ServiceTraceRecordEntity;
-import org.qi4j.logging.trace.records.TraceRecord;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.qi4j.test.AbstractQi4jTest;
-
-import java.util.Iterator;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.*;
-import static org.qi4j.api.query.QueryExpressions.orderBy;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-public class TracingTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( SomeService.class ).instantiateOnStartup();
-        module.services( SomeService2.class ).instantiateOnStartup();
-        new TracingAssembler().assemble( module );
-        new EntityTestAssembler().assemble( module );
-        new RdfMemoryStoreAssembler().assemble( module );
-        module.services( UuidIdentityGeneratorService.class );
-        module.entities( CompositeTraceRecordEntity.class );
-        module.entities( EntityTraceRecordEntity.class );
-        module.entities( ServiceTraceRecordEntity.class );
-    }
-
-    @Test
-    public void whenTraceOnMixinTypeMethodExpectOneEntryInEntityStore()
-        throws Exception
-    {
-        SomeService sc = module.findService( SomeService.class ).get();
-        assertEquals( 123, sc.doSomethingImportant() );
-        assertEquals( 456, sc.doSomethingLessImportant() );
-        UnitOfWork uow = module.newUnitOfWork();
-        QueryBuilder<TraceRecord> builder = module.newQueryBuilder( TraceRecord.class );
-        Query<TraceRecord> query = uow.newQuery( builder );
-        // IS sorting needed??
-//        TraceRecord template = templateFor( TraceRecord.class );
-//        query.orderBy( orderBy( template.methodName() ) );
-        Iterator<TraceRecord> result = query.iterator();
-        assertTrue( result.hasNext() );
-        TraceRecord rec1 = result.next();
-        assertEquals( "doSomethingImportant", rec1.methodName().get() );
-        assertFalse( result.hasNext() );
-        uow.complete();
-    }
-
-    @Test
-    public void whenTraceAllOnCompositeTypeExpectTwoEntryInEntityStore()
-        throws Exception
-    {
-        SomeService2 sc = module.findService( SomeService2.class ).get();
-        assertEquals( 123, sc.doSomethingImportant() );
-        assertEquals( 456, sc.doSomethingLessImportant() );
-        UnitOfWork uow = module.newUnitOfWork();
-        QueryBuilder<TraceRecord> builder = module.newQueryBuilder( TraceRecord.class );
-        Query<TraceRecord> query = uow.newQuery( builder );
-        // IS sorting needed??
-//        TraceRecord template = templateFor( TraceRecord.class );
-//        query.orderBy( orderBy( template.methodName() ) );
-        Iterator<TraceRecord> result = query.iterator();
-        assertTrue( result.hasNext() );
-        TraceRecord rec1 = result.next();
-        assertEquals( "doSomethingImportant", rec1.methodName().get() );
-        assertTrue( result.hasNext() );
-        TraceRecord rec2 = result.next();
-        assertEquals( "doSomethingLessImportant", rec2.methodName().get() );
-        assertFalse( result.hasNext() );
-        uow.complete();
-    }
-
-    @Test
-    public void whenTraceOnMixinImplExpectTwoEntryInEntityStore()
-        throws Exception
-    {
-        SomeService sc = module.findService( SomeService.class ).get();
-        assertEquals( 123, sc.doSomethingImportant() );
-        assertEquals( 789, sc.doSomethingModeratelyImportant() );
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            QueryBuilder<TraceRecord> builder = module.newQueryBuilder( TraceRecord.class );
-            Query<TraceRecord> query = uow.newQuery( builder );
-            // IS sorting needed??
-            TraceRecord template = templateFor( TraceRecord.class );
-            query.orderBy( orderBy( template.methodName() ) );
-            Iterator<TraceRecord> result = query.iterator();
-            assertTrue( result.hasNext() );
-            TraceRecord rec1 = result.next();
-            assertEquals( "doSomethingImportant", rec1.methodName().get() );
-            assertTrue( result.hasNext() );
-            TraceRecord rec2 = result.next();
-            assertEquals( "doSomethingModeratelyImportant", rec2.methodName().get() );
-            assertFalse( result.hasNext() );
-            uow.complete();
-        }
-        catch( Exception e )
-        {
-            uow.discard();
-            throw e;
-        }
-        catch( Error e )
-        {
-            uow.discard();
-            throw e;
-        }
-    }
-
-    @Test
-    public void whenTraceOnConcernExpectOneEntryInEntityStore()
-        throws Exception
-    {
-        // It is not possible to put Annotation on Concern Methods, so it should only record one.
-
-        SomeService sc = module.findService( SomeService.class ).get();
-        assertEquals( 123, sc.doSomethingImportant() );
-        assertEquals( 753, sc.doSomethingInsanelyImportant() );
-        UnitOfWork uow = module.newUnitOfWork();
-        QueryBuilder<TraceRecord> builder = module.newQueryBuilder( TraceRecord.class );
-        Query<TraceRecord> query = uow.newQuery( builder );
-        // IS sorting needed??
-//        TraceRecord template = templateFor( TraceRecord.class );
-//        query.orderBy( orderBy( template.methodName() ) );
-        Iterator<TraceRecord> result = query.iterator();
-        assertTrue( result.hasNext() );
-        TraceRecord rec1 = result.next();
-        assertEquals( "doSomethingImportant", rec1.methodName().get() );
-        assertFalse( result.hasNext() );
-        uow.complete();
-    }
-
-    @Mixins( SomeMixin.class )
-    @Concerns( { SomeConcern.class, TraceConcern.class } )
-    public interface SomeService
-        extends Some, ServiceComposite
-    {
-    }
-
-    @Mixins( SomeMixin.class )
-    @Concerns( { SomeConcern.class, TraceAllConcern.class } )
-    public interface SomeService2
-        extends Some, ServiceComposite
-    {
-    }
-
-    public interface Some
-    {
-        @Trace
-        int doSomethingImportant();
-
-        int doSomethingLessImportant();
-
-        int doSomethingModeratelyImportant();
-
-        int doSomethingInsanelyImportant();
-    }
-
-    public static class SomeConcern
-        extends ConcernOf<Some>
-        implements Some
-    {
-        public int doSomethingImportant()
-        {
-            System.out.println( "-- doSomethingImportant()" );
-            return next.doSomethingImportant();
-        }
-
-        public int doSomethingLessImportant()
-        {
-            System.out.println( "-- doSomethingLessImportant()" );
-            return next.doSomethingLessImportant();
-        }
-
-        public int doSomethingModeratelyImportant()
-        {
-            System.out.println( "-- doSomethingLessImportant()" );
-            return next.doSomethingModeratelyImportant();
-        }
-
-        @Trace
-        public int doSomethingInsanelyImportant()
-        {
-            System.out.println( "-- doSomethingInsanelyImportant()" );
-            return next.doSomethingInsanelyImportant();
-        }
-    }
-
-    public static class SomeMixin
-        implements Some
-    {
-
-        public int doSomethingImportant()
-        {
-            System.out.println( "---- doSomethingImportant()" );
-            return 123;
-        }
-
-        public int doSomethingLessImportant()
-        {
-            System.out.println( "---- doSomethingLessImportant()" );
-            return 456;
-        }
-
-        @Trace
-        public int doSomethingModeratelyImportant()
-        {
-            System.out.println( "---- doSomethingModeratelyImportant()" );
-            return 789;
-        }
-
-        public int doSomethingInsanelyImportant()
-        {
-            System.out.println( "---- doSomethingInsanelyImportant()" );
-            return 753;
-        }
-    }
-}
diff --git a/libraries/logging/src/test/java/org/qi4j/logging/docsupport/LoggingDocs.java b/libraries/logging/src/test/java/org/qi4j/logging/docsupport/LoggingDocs.java
deleted file mode 100644
index a39f1f2..0000000
--- a/libraries/logging/src/test/java/org/qi4j/logging/docsupport/LoggingDocs.java
+++ /dev/null
@@ -1,71 +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.qi4j.logging.docsupport;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.logging.debug.Debug;
-import org.qi4j.logging.trace.Trace;
-import org.qi4j.logging.trace.TraceAllConcern;
-
-public class LoggingDocs
-{
-
-// START SNIPPET: logging1
-    @Optional @This Debug debug;
-// END SNIPPET: logging1
-
-    public LoggingDocs()
-    {
-// START SNIPPET: logging2
-        if( debug != null )
-        {
-            debug.debug( Debug.NORMAL, "Debugging is made easier." );
-        }
-// END SNIPPET: logging2
-     }
-
-// START SNIPPET: logging3
-    public interface ImportantRepository
-    {
-        @Trace
-        void addImportantStuff( ImportantStuff stuff );
-
-        @Trace
-        void removeImportantStuff( ImportantStuff stuff );
-
-        ImportantStuff findImportantStuff( String searchKey );
-    }
-// END SNIPPET: logging3
-
-// START SNIPPET: logging4
-    public void assemble( ModuleAssembly module )
-            throws AssemblyException
-    {
-        module.addServices(ImportantRepository.class)
-                .withConcerns( TraceAllConcern.class )
-                .withMixins( Debug.class );
-    }
-
-// END SNIPPET: logging4
-
-    class ImportantStuff {}
-}
diff --git a/libraries/logging/src/test/resources/org/apache/polygene/library/logging/debug/service/DebuggingServiceComposite.properties b/libraries/logging/src/test/resources/org/apache/polygene/library/logging/debug/service/DebuggingServiceComposite.properties
new file mode 100644
index 0000000..0e829ad
--- /dev/null
+++ b/libraries/logging/src/test/resources/org/apache/polygene/library/logging/debug/service/DebuggingServiceComposite.properties
@@ -0,0 +1,21 @@
+#
+#  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.
+#
+#
+#
+
+debugLevel=100
diff --git a/libraries/logging/src/test/resources/org/qi4j/logging/debug/service/DebuggingServiceComposite.properties b/libraries/logging/src/test/resources/org/qi4j/logging/debug/service/DebuggingServiceComposite.properties
deleted file mode 100644
index 1d8a579..0000000
--- a/libraries/logging/src/test/resources/org/qi4j/logging/debug/service/DebuggingServiceComposite.properties
+++ /dev/null
@@ -1,16 +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.
-
-debugLevel=100
diff --git a/libraries/metrics/build.gradle b/libraries/metrics/build.gradle
deleted file mode 100644
index 7c1ac09..0000000
--- a/libraries/metrics/build.gradle
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.
- */
-
-description = "Apache Zest™ Metrics Library."
-
-jar { manifest { name = "Apache Zest™ Library - Metrics" }}
-
-dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-  testCompile(project(":org.qi4j.extensions:org.qi4j.extension.metrics-yammer"))
-
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
diff --git a/libraries/metrics/dev-status.xml b/libraries/metrics/dev-status.xml
deleted file mode 100644
index 04d78d0..0000000
--- a/libraries/metrics/dev-status.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  ~ Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
-  ~
-  ~ Licensed 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.
-  -->
-
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
-  <status>
-    <!--none,early,beta,stable,mature-->
-    <codebase>beta</codebase>
-
-    <!-- none, brief, good, complete -->
-    <documentation>brief</documentation>
-
-    <!-- none, some, good, complete -->
-    <unittests>some</unittests>
-  </status>
-  <licenses>
-    <license>ALv2</license>
-  </licenses>
-</module>
\ No newline at end of file
diff --git a/libraries/metrics/src/docs/metrics.txt b/libraries/metrics/src/docs/metrics.txt
deleted file mode 100644
index 857c99a..0000000
--- a/libraries/metrics/src/docs/metrics.txt
+++ /dev/null
@@ -1,63 +0,0 @@
-//////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.
-//////////////////////
-
-[[library-metrics,Metrics Library]]
-= Metrics Library =
-
-The Metrics library is available to application code to get production metrics from their applications. It allows
-applications to easily mark critical section for metrics gathering, without handling the details with the Metrics
-Extension.
-
-include::../../build/docs/buildinfo/artifact.txt[]
-
-== Usage ==
-There are currently the following possibilities available;
-
-    * @TimingCapture - capture timing on a single method
-    * TimingCaptureAll - capture timing on all methods of a composite
-
-Before looking at the details of these, we need to point out that there are some pre-conditions for Metrics to be
-working. First of all, you need to install a Metrics Extensions, most likely the
-<<extension-metrics-yammer, Yammer Metrics Extension>>. See your chosen extension for details on how to do that.
-
-Once the Metrics extension is installed, you will also need a suitable backend to gather all the data out of a
-production plant and likewise a good front-end to view this. See your chosen Metrics Extension for this as well.
-
-== TimingCaptureAll ==
-There is a TimingCaptureAllConcern, which when added to a composite will install a _Timer_ for every method call
-in the composite.
-
-== @TimingCapture ==
-The +@TimingCapture+ annotation can be placed on any method of the composite, to indicate that
-a Timer is wanted on that method.
-
-Example;
-
-[snippet,java]
-----
-source=libraries/metrics/src/test/java/org/qi4j/library/metrics/DocumentationSupport.java
-tag=capture
-----
-
-== Which method? ==
-It is valid to annotate either the composite interface methods or the mixin implementation methods.
-Any of the method declarations should work. From the testcases we have the following example;
-
-[snippet,java]
-----
-source=libraries/metrics/src/test/java/org/qi4j/library/metrics/MetricsTest.java
-tag=complex-capture
-----
-
diff --git a/libraries/metrics/src/main/java/org/qi4j/library/metrics/TimingCapture.java b/libraries/metrics/src/main/java/org/qi4j/library/metrics/TimingCapture.java
deleted file mode 100644
index 70e758c..0000000
--- a/libraries/metrics/src/main/java/org/qi4j/library/metrics/TimingCapture.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.metrics;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.qi4j.api.injection.InjectionScope;
-
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.METHOD } )
-@Documented
-@InjectionScope
-public @interface TimingCapture
-{
-}
diff --git a/libraries/metrics/src/main/java/org/qi4j/library/metrics/TimingCaptureAllConcern.java b/libraries/metrics/src/main/java/org/qi4j/library/metrics/TimingCaptureAllConcern.java
deleted file mode 100644
index 3a50181..0000000
--- a/libraries/metrics/src/main/java/org/qi4j/library/metrics/TimingCaptureAllConcern.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.metrics;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.util.concurrent.TimeUnit;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.injection.scope.Invocation;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.metrics.MetricsProvider;
-import org.qi4j.api.metrics.MetricsTimer;
-import org.qi4j.api.metrics.MetricsTimerFactory;
-
-public class TimingCaptureAllConcern extends ConcernOf<InvocationHandler>
-    implements InvocationHandler
-{
-    private MetricsTimer timer;
-
-    public TimingCaptureAllConcern( @Service @Optional MetricsProvider metrics,
-                                    @Invocation Method method
-    )
-    {
-        if( metrics != null )
-        {
-            MetricsTimerFactory factory = metrics.createFactory( MetricsTimerFactory.class );
-            boolean annotated = method.getAnnotation( TimingCapture.class ) != null;
-            String captureNme = getMethodName( method ) + "() ["  +( annotated ? "@" : "" ) + "TimingCapture" + "]";
-            Class<?> declaringClass = method.getDeclaringClass();
-            timer = factory.createTimer( declaringClass, captureNme, TimeUnit.MILLISECONDS, TimeUnit.SECONDS );
-        }
-    }
-
-    private String getMethodName( Method method )
-    {
-        return method.getName();
-    }
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        MetricsTimer.Context timing = null;
-        if( timer != null )
-        {
-            timing = timer.start();
-        }
-        try
-        {
-            return next.invoke( proxy, method, args );
-        }
-        finally
-        {
-            if( timing != null )
-            {
-                timing.stop();
-            }
-        }
-    }
-}
diff --git a/libraries/metrics/src/main/java/org/qi4j/library/metrics/TimingCaptureConcern.java b/libraries/metrics/src/main/java/org/qi4j/library/metrics/TimingCaptureConcern.java
deleted file mode 100644
index df8d141..0000000
--- a/libraries/metrics/src/main/java/org/qi4j/library/metrics/TimingCaptureConcern.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.metrics;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.injection.scope.Invocation;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.metrics.MetricsProvider;
-
-@AppliesTo( TimingCapture.class )
-public class TimingCaptureConcern extends TimingCaptureAllConcern
-{
-
-    public TimingCaptureConcern( @Service @Optional MetricsProvider metrics,
-                                 @Invocation Method method
-    )
-    {
-        super( metrics, method );
-    }
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        return super.invoke( proxy, method, args );
-    }
-}
diff --git a/libraries/metrics/src/main/java/org/qi4j/library/metrics/package.html b/libraries/metrics/src/main/java/org/qi4j/library/metrics/package.html
deleted file mode 100644
index 5f91a38..0000000
--- a/libraries/metrics/src/main/java/org/qi4j/library/metrics/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Metrics Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/metrics/src/test/java/org/qi4j/library/metrics/DocumentationSupport.java b/libraries/metrics/src/test/java/org/qi4j/library/metrics/DocumentationSupport.java
deleted file mode 100644
index bd5dc4e..0000000
--- a/libraries/metrics/src/test/java/org/qi4j/library/metrics/DocumentationSupport.java
+++ /dev/null
@@ -1,79 +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.qi4j.library.metrics;
-
-
-import java.util.List;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-public class DocumentationSupport
-{
-// START SNIPPET: capture
-    public interface Router
-    {
-        @TimingCapture
-        List<Coordinate> route( String source, String destination );
-    }
-
-    public class RouterAlgorithm1
-        implements Router
-    {
-        @Override
-        public List<Coordinate> route( String source, String destination )
-        {
-// END SNIPPET: capture
-            return null;
-// START SNIPPET: capture
-        }
-    }
-
-    public class RouterAlgorithm2
-        implements Router
-    {
-        @Override
-        public List<Coordinate> route( String source, String destination )
-        {
-// END SNIPPET: capture
-            return null;
-// START SNIPPET: capture
-        }
-
-// END SNIPPET: capture
-        public class MyAsembler implements Assembler
-        {
-// START SNIPPET: capture
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.addServices( Router.class ).identifiedBy( "router1" ).withMixins( RouterAlgorithm1.class );
-                module.addServices( Router.class ).identifiedBy( "router2" ).withMixins( RouterAlgorithm2.class );
-// END SNIPPET: capture
-// START SNIPPET: capture
-            }
-        }
-    }
-// END SNIPPET: capture
-
-    public class Coordinate
-    {
-    }
-}
diff --git a/libraries/metrics/src/test/java/org/qi4j/library/metrics/MetricsTest.java b/libraries/metrics/src/test/java/org/qi4j/library/metrics/MetricsTest.java
deleted file mode 100644
index 2ec08be..0000000
--- a/libraries/metrics/src/test/java/org/qi4j/library/metrics/MetricsTest.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.metrics;
-
-import com.yammer.metrics.Metrics;
-import com.yammer.metrics.core.MetricsRegistry;
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.lang.reflect.Field;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import org.junit.Test;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.metrics.yammer.YammerMetricsAssembler;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-
-public class MetricsTest extends AbstractQi4jTest
-{
-    private PrintStream reportOut;
-    private ByteArrayOutputStream result;
-    private YammerMetricsAssembler assembler;
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.layer().application().setName( "SomeApplication" );
-        module.transients( Country1.class );
-        module.transients( Country2.class ).withConcerns( TimingCaptureAllConcern.class );
-        module.transients( Country3.class ).withConcerns( TimingCaptureConcern.class );
-        result = new ByteArrayOutputStream();
-        reportOut = new PrintStream( result );
-        assembler = new YammerMetricsAssembler( reportOut, 100, TimeUnit.MILLISECONDS );
-        assembler.assemble( module );
-    }
-
-    @Override
-    public void tearDown()
-        throws Exception
-    {
-        if( assembler != null )  // Is null if assemble fails...
-        {
-            assembler.shutdown();
-        }
-        Field metrics = MetricsRegistry.class.getDeclaredField( "metrics" );
-        metrics.setAccessible( true );
-        Map m = (Map) metrics.get( Metrics.defaultRegistry() );
-        m.clear();
-        super.tearDown();
-    }
-
-    @Test
-    public void givenNonInstrumentedCompositeWhenCallingUpdateNameExpectNoReport()
-    {
-        Country underTest = module.newTransient( Country1.class );
-        String result = runTest( underTest );
-        result = result.replace( "\r", "" );
-        assertTrue( lastLine( result, 1 ).contains( "=====================" ) );
-        System.out.println( "---END TEST---" );
-    }
-
-    @Test
-    public void givenInstrumentedWithAllCompositeWhenCallingUpdateNameExpectReport()
-    {
-        Country underTest = module.newTransient( Country2.class );
-        String result = runTest( underTest );
-        result = result.replace( "\r", "" );
-        assertThat( lastLine( result, 34 ), equalTo( "org.qi4j.library.metrics.Country.SomeApplication:" ) );
-        assertThat( lastLine( result, 33 ).trim(), equalTo( "name() [TimingCapture]:" ) );
-        assertThat( lastLine( result, 16 ).trim(), equalTo( "updateName() [TimingCapture]:" ) );
-        assertTrue( lastLine( result, 5 ).contains( "75% <=" ) );
-        assertTrue( lastLine( result, 4 ).contains( "95% <=" ) );
-        assertTrue( lastLine( result, 3 ).contains( "98% <=" ) );
-        assertTrue( lastLine( result, 2 ).contains( "99% <=" ) );
-        assertTrue( lastLine( result, 1 ).contains( "99.9% <=" ) );
-        System.out.println( "---END TEST---" );
-    }
-
-    @Test
-    public void givenOneMethodAnnotatedWhenCallingUpdateNameExpectReportForThatMethodOnly()
-    {
-        Country underTest = module.newTransient( Country3.class );
-        String result = runTest( underTest );
-        result = result.replace( "\r", "" );
-        assertThat( lastLine( result, 17 ), equalTo( "org.qi4j.library.metrics.Country.SomeApplication:" ) );
-        assertThat( lastLine( result, 16 ).trim(), equalTo( "updateName() [TimingCapture]:" ) );
-        assertTrue( lastLine( result, 5 ).contains( "75% <=" ) );
-        assertTrue( lastLine( result, 4 ).contains( "95% <=" ) );
-        assertTrue( lastLine( result, 3 ).contains( "98% <=" ) );
-        assertTrue( lastLine( result, 2 ).contains( "99% <=" ) );
-        assertTrue( lastLine( result, 1 ).contains( "99.9% <=" ) );
-        System.out.println( "---END TEST---" );
-    }
-
-    private String lastLine( String text, int index )
-    {
-        String[] lines = text.split( "\n" );
-        return lines[ lines.length - index ];
-    }
-
-    private String runTest( Country underTest )
-    {
-
-        for( int i = 0; i < 1000000; i++ )
-        {
-            underTest.updateName( "Name" + i );
-        }
-        reportOut.close();
-        return result.toString();
-    }
-
-// START SNIPPET: complex-capture
-    public interface Country extends TransientComposite
-    {
-        @Optional
-        Property<String> name();
-
-        void updateName( String newName );
-    }
-
-    @Mixins( Country1Mixin.class )
-    public interface Country1 extends Country
-    {
-
-    }
-
-    public static abstract class Country1Mixin
-        implements Country1
-    {
-
-        @Override
-        public void updateName( String newName )
-        {
-            name().set( newName );
-        }
-    }
-
-    @Mixins( Country2Mixin.class )
-    public interface Country2 extends Country
-    {
-    }
-
-    public static abstract class Country2Mixin
-        implements Country2
-    {
-
-        @Override
-        public void updateName( String newName )
-        {
-            name().set( newName );
-        }
-    }
-
-    @Mixins( Country3Mixin.class )
-    @Concerns( TimingCaptureConcern.class )
-    public interface Country3 extends Country
-    {
-    }
-
-    public static abstract class Country3Mixin
-        implements Country3
-    {
-        @Override
-        @TimingCapture
-        public void updateName( String newName )
-        {
-            name().set( newName );
-        }
-    }
-// END SNIPPET: complex-capture
-}
diff --git a/libraries/osgi/build.gradle b/libraries/osgi/build.gradle
index 887f470..0fc6eb5 100644
--- a/libraries/osgi/build.gradle
+++ b/libraries/osgi/build.gradle
@@ -1,34 +1,38 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ OSGi Library provides integration of OSGi and Apache Zest™, so that services in each system can be shared."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - OSGi Integration" }}
+description = "Apache Polygene™ OSGi Library provides integration of OSGi and Apache Polygene™, so that services in each system can be shared."
+
+jar { manifest { name = "Apache Polygene™ Library - OSGi Integration" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.api"))
-  compile(libraries.osgi_core)
-  compile(libraries.osgi_compendium)
+  api polygene.core.api
+  api libraries.osgi_core
+  api libraries.osgi_compendium
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-  testCompile(libraries.mockito)
+  runtimeOnly polygene.core.runtime
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  testImplementation polygene.core.testsupport
+  testImplementation libraries.mockito
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/libraries/osgi/dev-status.xml b/libraries/osgi/dev-status.xml
index 515291a..e4cf124 100644
--- a/libraries/osgi/dev-status.xml
+++ b/libraries/osgi/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/osgi/src/docs/osgi.txt b/libraries/osgi/src/docs/osgi.txt
index 957bbfc..7ebaaee 100644
--- a/libraries/osgi/src/docs/osgi.txt
+++ b/libraries/osgi/src/docs/osgi.txt
@@ -25,25 +25,25 @@
 source=libraries/osgi/dev-status.xml
 --------------
 
-OSGi Library allows you to import OSGi services as Zest™ Services and to export Zest™ Services as OSGi Services both
-leveraging the Zest™ Availability and OSGi FallbackStrategy mechanisms.
+OSGi Library allows you to import OSGi services as Polygene™ Services and to export Polygene™ Services as OSGi Services both
+leveraging the Polygene™ Availability and OSGi FallbackStrategy mechanisms.
 
 include::../../build/docs/buildinfo/artifact.txt[]
 
-== Export Zest™ services to an OSGi Bundle ==
+== Export Polygene™ services to an OSGi Bundle ==
 
 [snippet,java]
 ----
-source=libraries/osgi/src/test/java/org/qi4j/library/osgi/DocumentationSupport.java
+source=libraries/osgi/src/test/java/org/apache/polygene/library/osgi/DocumentationSupport.java
 tag=export
 ----
 
 
-== Import OSGi services in a Zest™ Module ==
+== Import OSGi services in a Polygene™ Module ==
 
 [snippet,java]
 ----
-source=libraries/osgi/src/test/java/org/qi4j/library/osgi/DocumentationSupport.java
+source=libraries/osgi/src/test/java/org/apache/polygene/library/osgi/DocumentationSupport.java
 tag=import
 ----
 
diff --git a/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/FallbackStrategy.java b/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/FallbackStrategy.java
new file mode 100644
index 0000000..9b2ec3a
--- /dev/null
+++ b/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/FallbackStrategy.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.osgi;
+
+
+import java.lang.reflect.Method;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * The fallback strategy is invoked when the OSGi service is not available and a method call is invoked.
+ * <p>
+ * The FallbackStrategy is declared on the {@link OSGiServiceImporter} service declaration, like;
+ * <pre><code>
+ *     FallbackStrategy strategy = new MyStrategy();
+ *     module.services( OSGiServiceImporter.class )
+ *         .identifiedBy( "osgi" )
+ *         .setMetaInfo( bundleContext )
+ *         .setMetaInfo( strategy );
+ * </code></pre>
+ */
+public interface FallbackStrategy {
+    Object invoke(final ServiceReference reference, Method method, Object... args);
+}
\ No newline at end of file
diff --git a/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/OSGiEnabledService.java b/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/OSGiEnabledService.java
new file mode 100644
index 0000000..faf5787
--- /dev/null
+++ b/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/OSGiEnabledService.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.polygene.library.osgi;
+
+import java.lang.reflect.Type;
+import java.util.Dictionary;
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Module;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import static org.apache.polygene.api.util.Classes.toClassName;
+import static org.apache.polygene.api.util.Classes.typesOf;
+
+/**
+ * Service Fragment providing OSGi support.
+ */
+@Mixins( OSGiEnabledService.OSGiEnabledServiceMixin.class )
+@Activators( OSGiEnabledService.Activator.class )
+public interface OSGiEnabledService extends HasIdentity
+{
+    void registerServices()
+        throws Exception;
+
+    void unregisterServices()
+        throws Exception;
+
+    class Activator
+        extends ActivatorAdapter<ServiceReference<OSGiEnabledService>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<OSGiEnabledService> activated )
+            throws Exception
+        {
+            activated.get().registerServices();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<OSGiEnabledService> passivating )
+            throws Exception
+        {
+            passivating.get().unregisterServices();
+        }
+    }
+
+    abstract class OSGiEnabledServiceMixin
+        implements OSGiEnabledService
+    {
+        @Uses
+        ServiceDescriptor descriptor;
+
+        @Structure
+        private Module module;
+
+        private ServiceRegistration registration;
+
+        @Override
+        public void registerServices()
+            throws Exception
+        {
+            BundleContext context = descriptor.metaInfo( BundleContext.class );
+            if( context == null )
+            {
+                return;
+            }
+            module.findServices( descriptor.types().findFirst().orElse( null ) ).forEach(
+                ref -> {
+                    if( ref.identity().equals( identity().get() ) )
+                    {
+                        Stream<? extends Type> classesSet = descriptor.types();
+                        Dictionary properties = descriptor.metaInfo( Dictionary.class );
+                        String[] clazzes = fetchInterfacesImplemented( classesSet );
+                        registration = context.registerService( clazzes, ref.get(), properties );
+                    }
+                }
+            );
+        }
+
+        private String[] fetchInterfacesImplemented( Stream<? extends Type> classesSet )
+        {
+            return typesOf( classesSet ).map( toClassName() ).toArray( String[]::new );
+        }
+
+        @Override
+        public void unregisterServices()
+            throws Exception
+        {
+            if( registration != null )
+            {
+                registration.unregister();
+                registration = null;
+            }
+        }
+    }
+}
diff --git a/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/OSGiImportInfo.java b/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/OSGiImportInfo.java
new file mode 100644
index 0000000..3e2e8fd
--- /dev/null
+++ b/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/OSGiImportInfo.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.library.osgi;
+
+import org.osgi.framework.BundleContext;
+
+/**
+ * MetaInfo to define imported OSGi services.
+ */
+public class OSGiImportInfo
+{
+    private final BundleContext context;
+    private final Class[] intfaces;
+
+    public OSGiImportInfo( BundleContext context, Class... intfaces )
+    {
+        this.context = context;
+        this.intfaces = intfaces;
+    }
+
+    public BundleContext bundleContext()
+    {
+        return context;
+    }
+
+    public Class[] interfaces()
+    {
+        return intfaces;
+    }
+}
diff --git a/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/OSGiServiceExporter.java b/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/OSGiServiceExporter.java
new file mode 100644
index 0000000..6ba61e0
--- /dev/null
+++ b/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/OSGiServiceExporter.java
@@ -0,0 +1,118 @@
+/*
+ *  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.polygene.library.osgi;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Properties;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.service.qualifier.HasMetaInfo;
+import org.apache.polygene.api.util.Classes;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import static org.apache.polygene.api.util.Classes.interfacesOf;
+
+/**
+ * Export Polygene services to an OSGi Bundle.
+ */
+@Mixins( OSGiServiceExporter.OSGiServiceExporterMixin.class )
+@Activators( OSGiServiceExporter.Activator.class )
+public interface OSGiServiceExporter
+{
+    void registerServices()
+        throws Exception;
+
+    void unregisterServices()
+        throws Exception;
+
+    class Activator
+        extends ActivatorAdapter<ServiceReference<OSGiServiceExporter>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<OSGiServiceExporter> activated )
+            throws Exception
+        {
+            activated.get().registerServices();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<OSGiServiceExporter> passivating )
+            throws Exception
+        {
+            passivating.get().unregisterServices();
+        }
+
+    }
+
+    abstract class OSGiServiceExporterMixin
+        implements OSGiServiceExporter
+    {
+
+        @Service
+        @HasMetaInfo( BundleContext.class )
+        private Iterable<ServiceReference<ServiceComposite>> services;
+        private ArrayList<ServiceRegistration> registrations = new ArrayList<>();
+
+        @Override
+        public void registerServices()
+            throws Exception
+        {
+            for( ServiceReference<ServiceComposite> ref : services )
+            {
+                Class<? extends BundleContext> type = BundleContext.class;
+                BundleContext context = ref.metaInfo( type );
+                ServiceComposite service = ref.get();
+                Dictionary properties = ref.metaInfo( Dictionary.class );
+                if( properties == null )
+                {
+                    properties = new Properties();
+                }
+                properties.put( "org.apache.polygene.api.service.active", ref.isActive() );
+                properties.put( "org.apache.polygene.api.service.available", ref.isAvailable() );
+                properties.put( "org.apache.polygene.api.service.reference", ref.identity() );
+
+
+                String[] interfaceNames = interfacesOf( service.getClass() )
+                    .map( Classes.RAW_CLASS ).toArray( String[]::new );
+
+                registrations.add( context.registerService( interfaceNames, service, properties ) );
+            }
+        }
+
+        @Override
+        public void unregisterServices()
+            throws Exception
+        {
+            for( ServiceRegistration reg : registrations )
+            {
+                reg.unregister();
+            }
+        }
+
+    }
+
+}
diff --git a/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/OSGiServiceImporter.java b/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/OSGiServiceImporter.java
new file mode 100644
index 0000000..b0d4ba1
--- /dev/null
+++ b/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/OSGiServiceImporter.java
@@ -0,0 +1,122 @@
+/*
+ *  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.polygene.library.osgi;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.ServiceImporterException;
+import org.apache.polygene.api.service.ServiceUnavailableException;
+
+/**
+ * Import OSGi services in a Polygene Module.
+ */
+public class OSGiServiceImporter
+    implements ServiceImporter
+{
+
+    @Override
+    public Object importService( ImportedServiceDescriptor serviceDescriptor )
+        throws ServiceImporterException
+    {
+        OSGiImportInfo info = serviceDescriptor.metaInfo( OSGiImportInfo.class );
+        BundleContext context = info.bundleContext();
+        ServiceTrackerHandler handler = new ServiceTrackerHandler( context, serviceDescriptor.type() );
+        handler.open();
+        return Proxy.newProxyInstance( serviceDescriptor.type().getClassLoader(), info.interfaces(), handler );
+    }
+
+    @Override
+    public boolean isAvailable( Object instance )
+    {
+        ServiceTrackerHandler handler = (ServiceTrackerHandler) Proxy.getInvocationHandler( instance );
+        return handler.isAvailable();
+    }
+
+    public static class ServiceTrackerHandler
+        extends ServiceTracker
+        implements InvocationHandler
+    {
+
+        private volatile Object service;
+        private Class typeToImport;
+
+        public ServiceTrackerHandler( BundleContext context, Class typeToImport )
+        {
+            super( context, typeToImport.getName(), null );
+            this.typeToImport = typeToImport;
+        }
+
+        @Override
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            Object temporary;
+            synchronized( this )
+            {
+                if( service == null )
+                {
+                    wait( 5000 );  // Max wait 5 seconds.
+                    if( service == null )
+                    {
+                        throw new ServiceUnavailableException(
+                            "The OSGi service is currently not available: " + typeToImport.getName() );
+                    }
+                }
+                temporary = service;
+            }
+            return method.invoke( temporary, args );
+        }
+
+        @Override
+        public Object addingService( ServiceReference reference )
+        {
+            synchronized( this )
+            {
+                service = super.addingService( reference );
+                notifyAll();
+                return service;
+            }
+        }
+
+        @Override
+        public void removedService( ServiceReference reference, Object service )
+        {
+            synchronized( this )
+            {
+                super.removedService( reference, service );
+                notifyAll();
+                this.service = null;
+            }
+        }
+
+        public boolean isAvailable()
+        {
+            return service != null;
+        }
+
+    }
+
+}
diff --git a/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/package.html b/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/package.html
new file mode 100644
index 0000000..3843103
--- /dev/null
+++ b/libraries/osgi/src/main/java/org/apache/polygene/library/osgi/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>OSGi Library.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/osgi/src/main/java/org/qi4j/library/osgi/FallbackStrategy.java b/libraries/osgi/src/main/java/org/qi4j/library/osgi/FallbackStrategy.java
deleted file mode 100644
index 7cce688..0000000
--- a/libraries/osgi/src/main/java/org/qi4j/library/osgi/FallbackStrategy.java
+++ /dev/null
@@ -1,39 +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.qi4j.library.osgi;
-
-
-import java.lang.reflect.Method;
-import org.osgi.framework.ServiceReference;
-
-/**
- * The fallback strategy is invoked when the OSGi service is not available and a method call is invoked.
- * <p>
- * The FallbackStrategy is declared on the {@link OSGiServiceImporter} service declaration, like;
- * <pre><code>
- *     FallbackStrategy strategy = new MyStrategy();
- *     module.services( OSGiServiceImporter.class )
- *         .identifiedBy( "osgi" )
- *         .setMetaInfo( bundleContext )
- *         .setMetaInfo( strategy );
- * </code></pre>
- */
-public interface FallbackStrategy {
-    Object invoke(final ServiceReference reference, Method method, Object... args);
-}
\ No newline at end of file
diff --git a/libraries/osgi/src/main/java/org/qi4j/library/osgi/OSGiEnabledService.java b/libraries/osgi/src/main/java/org/qi4j/library/osgi/OSGiEnabledService.java
deleted file mode 100644
index efe8e9c..0000000
--- a/libraries/osgi/src/main/java/org/qi4j/library/osgi/OSGiEnabledService.java
+++ /dev/null
@@ -1,125 +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.qi4j.library.osgi;
-
-import java.lang.reflect.Type;
-import java.util.Dictionary;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Module;
-
-import static org.qi4j.api.util.Classes.toClassName;
-import static org.qi4j.api.util.Classes.typesOf;
-import static org.qi4j.functional.Iterables.cast;
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.map;
-import static org.qi4j.functional.Iterables.toArray;
-
-/**
- * Service Fragment providing OSGi support.
- */
-@Mixins( OSGiEnabledService.OSGiEnabledServiceMixin.class )
-@Activators( OSGiEnabledService.Activator.class )
-public interface OSGiEnabledService extends ServiceComposite
-{
-
-    void registerServices()
-            throws Exception;
-
-    void unregisterServices()
-            throws Exception;
-
-    class Activator
-            extends ActivatorAdapter<ServiceReference<OSGiEnabledService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<OSGiEnabledService> activated )
-                throws Exception
-        {
-            activated.get().registerServices();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<OSGiEnabledService> passivating )
-                throws Exception
-        {
-            passivating.get().unregisterServices();
-        }
-
-    }
-
-
-    public abstract class OSGiEnabledServiceMixin
-        implements OSGiEnabledService
-    {
-        @Uses
-        ServiceDescriptor descriptor;
-
-        @Structure
-        private Module module;
-
-        private ServiceRegistration registration;
-
-        @Override
-        public void registerServices()
-            throws Exception
-        {
-            BundleContext context = descriptor.metaInfo( BundleContext.class );
-            if( context == null )
-            {
-                return;
-            }
-            for( ServiceReference ref : module.findServices( first( descriptor.types() ) ) )
-            {
-                if( ref.identity().equals( identity().get() ) )
-                {
-                    Iterable<Type> classesSet = cast(descriptor.types());
-                    Dictionary properties = descriptor.metaInfo( Dictionary.class );
-                    String[] clazzes = fetchInterfacesImplemented( classesSet );
-                    registration = context.registerService( clazzes, ref.get(), properties );
-                }
-            }
-        }
-
-        private String[] fetchInterfacesImplemented( Iterable<Type> classesSet )
-        {
-            return toArray( String.class, map( toClassName(), typesOf( classesSet ) ) );
-        }
-
-        @Override
-        public void unregisterServices()
-            throws Exception
-        {
-            if( registration != null )
-            {
-                registration.unregister();
-                registration = null;
-            }
-        }
-    }
-}
diff --git a/libraries/osgi/src/main/java/org/qi4j/library/osgi/OSGiImportInfo.java b/libraries/osgi/src/main/java/org/qi4j/library/osgi/OSGiImportInfo.java
deleted file mode 100644
index 8f283bd..0000000
--- a/libraries/osgi/src/main/java/org/qi4j/library/osgi/OSGiImportInfo.java
+++ /dev/null
@@ -1,46 +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.qi4j.library.osgi;
-
-import org.osgi.framework.BundleContext;
-
-/**
- * MetaInfo to define imported OSGi services.
- */
-public class OSGiImportInfo
-{
-    private final BundleContext context;
-    private final Class[] intfaces;
-
-    public OSGiImportInfo( BundleContext context, Class... intfaces )
-    {
-        this.context = context;
-        this.intfaces = intfaces;
-    }
-
-    public BundleContext bundleContext()
-    {
-        return context;
-    }
-
-    public Class[] interfaces()
-    {
-        return intfaces;
-    }
-}
diff --git a/libraries/osgi/src/main/java/org/qi4j/library/osgi/OSGiServiceExporter.java b/libraries/osgi/src/main/java/org/qi4j/library/osgi/OSGiServiceExporter.java
deleted file mode 100644
index 0f3ee7d..0000000
--- a/libraries/osgi/src/main/java/org/qi4j/library/osgi/OSGiServiceExporter.java
+++ /dev/null
@@ -1,122 +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.qi4j.library.osgi;
-
-import java.util.ArrayList;
-import java.util.Properties;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.service.qualifier.HasMetaInfo;
-import org.qi4j.api.util.Classes;
-import org.qi4j.functional.Iterables;
-
-import static org.qi4j.api.util.Classes.interfacesOf;
-
-/**
- * Export Zest services to an OSGi Bundle.
- */
-@Mixins( OSGiServiceExporter.OSGiServiceExporterMixin.class )
-@Activators( OSGiServiceExporter.Activator.class )
-public interface OSGiServiceExporter
-    extends ServiceComposite
-{
-
-    void registerServices()
-        throws Exception;
-
-    void unregisterServices()
-        throws Exception;
-
-    class Activator
-        extends ActivatorAdapter<ServiceReference<OSGiServiceExporter>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<OSGiServiceExporter> activated )
-            throws Exception
-        {
-            activated.get().registerServices();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<OSGiServiceExporter> passivating )
-            throws Exception
-        {
-            passivating.get().unregisterServices();
-        }
-
-    }
-
-    public static abstract class OSGiServiceExporterMixin
-        implements OSGiServiceExporter
-    {
-
-        @Service
-        @HasMetaInfo( BundleContext.class )
-        private Iterable<ServiceReference<ServiceComposite>> services;
-        private ArrayList<ServiceRegistration> registrations = new ArrayList<ServiceRegistration>();
-
-        @Override
-        public void registerServices()
-            throws Exception
-        {
-            for( ServiceReference<ServiceComposite> ref : services )
-            {
-                Class<? extends BundleContext> type = BundleContext.class;
-                BundleContext context = ref.metaInfo( type );
-                ServiceComposite service = ref.get();
-                Iterable<Class<?>> interfaces = Iterables.map( Classes.RAW_CLASS, interfacesOf( service.getClass() ) );
-                String[] interfaceNames = new String[ (int) Iterables.count( interfaces ) ];
-                Properties properties = ref.metaInfo( Properties.class );
-                if( properties == null )
-                {
-                    properties = new Properties();
-                }
-                properties.put( "org.qi4j.api.service.active", ref.isActive() );
-                properties.put( "org.qi4j.api.service.available", ref.isAvailable() );
-                properties.put( "org.qi4j.api.service.identity", ref.identity() );
-                int i = 0;
-                for( Class cls : interfaces )
-                {
-                    interfaceNames[ i++] = cls.getName();
-                }
-                registrations.add( context.registerService( interfaceNames, service, properties ) );
-
-            }
-        }
-
-        @Override
-        public void unregisterServices()
-            throws Exception
-        {
-            for( ServiceRegistration reg : registrations )
-            {
-                reg.unregister();
-            }
-        }
-
-    }
-
-}
diff --git a/libraries/osgi/src/main/java/org/qi4j/library/osgi/OSGiServiceImporter.java b/libraries/osgi/src/main/java/org/qi4j/library/osgi/OSGiServiceImporter.java
deleted file mode 100644
index 3f302f6..0000000
--- a/libraries/osgi/src/main/java/org/qi4j/library/osgi/OSGiServiceImporter.java
+++ /dev/null
@@ -1,121 +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.qi4j.library.osgi;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.util.tracker.ServiceTracker;
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.service.ServiceImporterException;
-import org.qi4j.api.service.ServiceUnavailableException;
-
-/**
- * Import OSGi services in a Zest Module.
- */
-public class OSGiServiceImporter
-    implements ServiceImporter
-{
-
-    @Override
-    public Object importService( ImportedServiceDescriptor serviceDescriptor )
-        throws ServiceImporterException
-    {
-        OSGiImportInfo info = serviceDescriptor.metaInfo( OSGiImportInfo.class );
-        BundleContext context = info.bundleContext();
-        ServiceTrackerHandler handler = new ServiceTrackerHandler( context, serviceDescriptor.type() );
-        handler.open();
-        return Proxy.newProxyInstance( serviceDescriptor.type().getClassLoader(), info.interfaces(), handler );
-    }
-
-    @Override
-    public boolean isAvailable( Object instance )
-    {
-        ServiceTrackerHandler handler = (ServiceTrackerHandler) Proxy.getInvocationHandler( instance );
-        return handler.isAvailable();
-    }
-
-    public static class ServiceTrackerHandler
-        extends ServiceTracker
-        implements InvocationHandler
-    {
-
-        private volatile Object service;
-        private Class typeToImport;
-
-        public ServiceTrackerHandler( BundleContext context, Class typeToImport )
-        {
-            super( context, typeToImport.getName(), null );
-            this.typeToImport = typeToImport;
-        }
-
-        @Override
-        public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-        {
-            Object temporary;
-            synchronized( this )
-            {
-                if( service == null )
-                {
-                    wait( 5000 );  // Max wait 5 seconds.
-                    if( service == null )
-                    {
-                        throw new ServiceUnavailableException(
-                            "The OSGi service is currently not available: " + typeToImport.getName() );
-                    }
-                }
-                temporary = service;
-            }
-            return method.invoke( temporary, args );
-        }
-
-        @Override
-        public Object addingService( ServiceReference reference )
-        {
-            synchronized( this )
-            {
-                service = super.addingService( reference );
-                notifyAll();
-                return service;
-            }
-        }
-
-        @Override
-        public void removedService( ServiceReference reference, Object service )
-        {
-            synchronized( this )
-            {
-                super.removedService( reference, service );
-                notifyAll();
-                this.service = null;
-            }
-        }
-
-        public boolean isAvailable()
-        {
-            return service != null;
-        }
-
-    }
-
-}
diff --git a/libraries/osgi/src/main/java/org/qi4j/library/osgi/package.html b/libraries/osgi/src/main/java/org/qi4j/library/osgi/package.html
deleted file mode 100644
index 7d9b47b..0000000
--- a/libraries/osgi/src/main/java/org/qi4j/library/osgi/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>OSGi Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/osgi/src/test/java/org/apache/polygene/library/osgi/DocumentationSupport.java b/libraries/osgi/src/test/java/org/apache/polygene/library/osgi/DocumentationSupport.java
new file mode 100644
index 0000000..4ea5c7e
--- /dev/null
+++ b/libraries/osgi/src/test/java/org/apache/polygene/library/osgi/DocumentationSupport.java
@@ -0,0 +1,93 @@
+/*
+ *  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.polygene.library.osgi;
+
+import org.osgi.framework.BundleContext;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+public class DocumentationSupport
+{
+
+    public static class Export
+        implements Assembler
+    {
+
+        // START SNIPPET: export
+        interface MyPolygeneService
+            extends OSGiEnabledService
+        {
+            // ...
+        }
+        // END SNIPPET: export
+
+        @Override
+        // START SNIPPET: export
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            BundleContext bundleContext = // ...
+                          // END SNIPPET: export
+                          null;
+            // START SNIPPET: export
+            module.services( OSGiServiceExporter.class ).
+                setMetaInfo( bundleContext );
+            module.services( MyPolygeneService.class );
+        }
+        // END SNIPPET: export
+
+    }
+
+    interface MyOSGiService
+    {
+    }
+
+    interface MyOtherOSGiService
+    {
+    }
+
+    static class MyFallbackStrategy
+    {
+    }
+
+    public static class Import
+        implements Assembler
+    {
+
+        @Override
+        // START SNIPPET: import
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            BundleContext bundleContext = // END SNIPPET: import
+                          null;
+            // START SNIPPET: import
+            module.services( OSGiServiceImporter.class ).
+                setMetaInfo( new OSGiImportInfo( bundleContext,
+                                                 MyOSGiService.class,
+                                                 MyOtherOSGiService.class ) ).
+                setMetaInfo( new MyFallbackStrategy() );
+        }
+        // END SNIPPET: import
+
+    }
+
+}
diff --git a/libraries/osgi/src/test/java/org/apache/polygene/library/osgi/OSGiServiceTest.java b/libraries/osgi/src/test/java/org/apache/polygene/library/osgi/OSGiServiceTest.java
new file mode 100644
index 0000000..1514f54
--- /dev/null
+++ b/libraries/osgi/src/test/java/org/apache/polygene/library/osgi/OSGiServiceTest.java
@@ -0,0 +1,80 @@
+/*
+ *  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.polygene.library.osgi;
+
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class OSGiServiceTest
+    extends AbstractPolygeneTest
+{
+
+    private BundleContext bundleContext;
+
+    public OSGiServiceTest()
+    {
+        bundleContext = mock( BundleContext.class );
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( MyService.class ).setMetaInfo( bundleContext ).instantiateOnStartup();
+    }
+
+    @Test
+    public void givenFelixFrameworkWhenStartingPolygeneApplicationExpectServiceToBeRegisteredToOsgiBundleContext()
+    {
+        MyService service = serviceFinder.findService( MyService.class ).get();
+        service.value().set( 15 );
+        assertEquals( (Integer) 15, service.value().get() );
+        String[] expectedClasses = new String[]
+        {
+            "org.apache.polygene.library.osgi.OSGiServiceTest$MyService",
+            "org.apache.polygene.library.osgi.OSGiEnabledService",
+            "org.apache.polygene.api.identity.HasIdentity",
+            "org.apache.polygene.api.service.ServiceComposite",
+            "org.apache.polygene.api.identity.HasIdentity",
+            "org.apache.polygene.api.composite.Composite"
+        };
+        verify( bundleContext ).registerService( expectedClasses, service, null );
+
+    }
+
+    public interface MyService
+        extends OSGiEnabledService
+    {
+
+        @UseDefaults
+        Property<Integer> value();
+
+    }
+
+}
diff --git a/libraries/osgi/src/test/java/org/qi4j/library/osgi/DocumentationSupport.java b/libraries/osgi/src/test/java/org/qi4j/library/osgi/DocumentationSupport.java
deleted file mode 100644
index 9eccaee..0000000
--- a/libraries/osgi/src/test/java/org/qi4j/library/osgi/DocumentationSupport.java
+++ /dev/null
@@ -1,92 +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.qi4j.library.osgi;
-
-import org.osgi.framework.BundleContext;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-public class DocumentationSupport
-{
-
-    public static class Export
-        implements Assembler
-    {
-
-        // START SNIPPET: export
-        interface MyQi4jService
-            extends OSGiEnabledService
-        {
-            // ...
-        }
-        // END SNIPPET: export
-
-        @Override
-        // START SNIPPET: export
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            BundleContext bundleContext = // ...
-                          // END SNIPPET: export
-                          null;
-            // START SNIPPET: export
-            module.services( OSGiServiceExporter.class ).
-                setMetaInfo( bundleContext );
-            module.services( MyQi4jService.class );
-        }
-        // END SNIPPET: export
-
-    }
-
-    interface MyOSGiService
-    {
-    }
-
-    interface MyOtherOSGiService
-    {
-    }
-
-    static class MyFallbackStrategy
-    {
-    }
-
-    public static class Import
-        implements Assembler
-    {
-
-        @Override
-        // START SNIPPET: import
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            BundleContext bundleContext = // END SNIPPET: import
-                          null;
-            // START SNIPPET: import
-            module.services( OSGiServiceImporter.class ).
-                setMetaInfo( new OSGiImportInfo( bundleContext,
-                                                 MyOSGiService.class,
-                                                 MyOtherOSGiService.class ) ).
-                setMetaInfo( new MyFallbackStrategy() );
-        }
-        // END SNIPPET: import
-
-    }
-
-}
diff --git a/libraries/osgi/src/test/java/org/qi4j/library/osgi/OSGiServiceTest.java b/libraries/osgi/src/test/java/org/qi4j/library/osgi/OSGiServiceTest.java
deleted file mode 100644
index bcc5ba6..0000000
--- a/libraries/osgi/src/test/java/org/qi4j/library/osgi/OSGiServiceTest.java
+++ /dev/null
@@ -1,78 +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.qi4j.library.osgi;
-
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-public class OSGiServiceTest
-    extends AbstractQi4jTest
-{
-
-    private BundleContext bundleContext;
-
-    public OSGiServiceTest()
-    {
-        bundleContext = mock( BundleContext.class );
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( MyService.class ).setMetaInfo( bundleContext ).instantiateOnStartup();
-    }
-
-    @Test
-    public void givenFelixFrameworkWhenStartingQi4jApplicationExpectServiceToBeRegisteredToOsgiBundleContext()
-    {
-        MyService service = module.findService( MyService.class ).get();
-        service.value().set( 15 );
-        assertEquals( (Integer) 15, service.value().get() );
-        String[] expectedClasses = new String[]
-        {
-            "org.qi4j.library.osgi.OSGiServiceTest$MyService",
-            "org.qi4j.library.osgi.OSGiEnabledService",
-            "org.qi4j.api.service.ServiceComposite",
-            "org.qi4j.api.entity.Identity",
-            "org.qi4j.api.composite.Composite"
-        };
-        verify( bundleContext ).registerService( expectedClasses, service, null );
-
-    }
-
-    public interface MyService
-        extends OSGiEnabledService
-    {
-
-        @UseDefaults
-        Property<Integer> value();
-
-    }
-
-}
diff --git a/libraries/rdf/build.gradle b/libraries/rdf/build.gradle
index dff55b5..50babbe 100644
--- a/libraries/rdf/build.gradle
+++ b/libraries/rdf/build.gradle
@@ -1,43 +1,39 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ RDF Library provides commonalities of various RDF based services in Apache Zest™, such as RDF Indexing."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - RDF" }}
+description = "Apache Polygene™ RDF Library provides commonalities of various RDF based services in Apache Polygene™, such as RDF Indexing."
+
+jar { manifest { name = "Apache Polygene™ Library - RDF" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.spi"))
-  compile(project(':org.qi4j.libraries:org.qi4j.library.constraints'))
-  compile(project(":org.qi4j.libraries:org.qi4j.library.fileconfig"))
-  compile(libraries.sesame)
-//  compile("org.openrdf.sesame:sesame-model:$rdfVersion")
-//  compile("org.openrdf.sesame:sesame-repository-dataset:$rdfVersion")
-//  compile("org.openrdf.sesame:sesame-repository-http:$rdfVersion")
-//  compile("org.openrdf.sesame:sesame-rio-n3:$rdfVersion")
-//  compile("org.openrdf.sesame:sesame-rio-rdfxml:$rdfVersion")
-//  compile("org.openrdf.sesame:sesame-sail-memory:$rdfVersion")
-//  compile("org.openrdf.sesame:sesame-sail-nativerdf:$rdfVersion")
-//  compile("org.openrdf.sesame:sesame-sail-rdbms:$rdfVersion")
+  api polygene.core.spi
+  api libraries.sesame
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-  testCompile project( ':org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson' )
+  implementation polygene.library( 'constraints' )
+  implementation polygene.library( 'fileconfig' )
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/libraries/rdf/dev-status.xml b/libraries/rdf/dev-status.xml
index f8669b1..33d5d9e 100644
--- a/libraries/rdf/dev-status.xml
+++ b/libraries/rdf/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/DcRdf.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/DcRdf.java
new file mode 100644
index 0000000..cb7b993
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/DcRdf.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.rdf;
+
+import org.openrdf.model.URI;
+import org.openrdf.model.impl.URIImpl;
+
+public interface DcRdf
+{
+    String NAMESPACE = "http://purl.org/dc/elements/1.1/";
+    URI ABOUT = new URIImpl( NAMESPACE + "about" );
+    URI TITLE = new URIImpl( NAMESPACE + "title" );
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/PolygeneEntity.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/PolygeneEntity.java
new file mode 100644
index 0000000..3e97ae8
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/PolygeneEntity.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.rdf;
+
+import org.openrdf.model.URI;
+import org.openrdf.model.impl.URIImpl;
+
+
+/**
+ * This is the RDF vocabulary for Polygene Entity data.
+ */
+public interface PolygeneEntity
+{
+    // Model
+    String NAMESPACE = "http://polygene.apache.org/rdf/entity/1.0/";
+
+    // Types
+    URI ENTITY = new URIImpl( NAMESPACE + "entity" );
+    URI ENTITYTYPEREFERENCE = new URIImpl( NAMESPACE + "entitytypereference" );
+    URI QUALIFIER = new URIImpl( NAMESPACE + "qualifier" );
+}
\ No newline at end of file
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/PolygeneEntityType.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/PolygeneEntityType.java
new file mode 100644
index 0000000..2d63daa
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/PolygeneEntityType.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.rdf;
+
+import org.openrdf.model.URI;
+import org.openrdf.model.impl.URIImpl;
+
+
+/**
+ * This is the RDF vocabulary for Polygene EntityType data.
+ */
+public interface PolygeneEntityType
+{
+    // Namespace
+    String NAMESPACE = "http://polygene.apache.org/rdf/entitytype/1.0/";
+
+    // Predicates
+    URI QUERYABLE = new URIImpl( NAMESPACE + "queryable" );
+    URI VERSION = new URIImpl( NAMESPACE + "version" );
+    URI TYPE = new URIImpl( NAMESPACE + "type" );
+}
\ No newline at end of file
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/PolygeneRdf.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/PolygeneRdf.java
new file mode 100644
index 0000000..8afd4f8
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/PolygeneRdf.java
@@ -0,0 +1,87 @@
+/*
+ *  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.polygene.library.rdf;
+
+import org.openrdf.model.URI;
+import org.openrdf.model.impl.URIImpl;
+
+
+/**
+ * This is the RDF vocabulary for Polygene.
+ */
+public interface PolygeneRdf
+{
+
+    // MODEL
+    // Namespace TODO: Need to figure out what these should really be!
+    String POLYGENE_MODEL = "http://polygene.apache.org/rdf/model/1.0/";
+
+    String POLYGENE_MODEL_TYPES = "http://polygene.apache.org/rdf/model/1.0/type#";
+    String POLYGENE_MODEL_RELATIONSHIPS = "http://polygene.apache.org/rdf/module/1.0/";
+    String POLYGENE_MODEL_PROPERTIES = "http://polygene.apache.org/rdf/model/1.0/property#";
+
+    // Types
+    URI TYPE_APPLICATION = new URIImpl( POLYGENE_MODEL_TYPES + "application" );
+    URI TYPE_LAYER = new URIImpl( POLYGENE_MODEL_TYPES + "layer" );
+    URI TYPE_MODULE = new URIImpl( POLYGENE_MODEL_TYPES + "module" );
+    URI TYPE_ENTITY = new URIImpl( POLYGENE_MODEL_TYPES + "entity" );
+    URI TYPE_QUALIFIER = new URIImpl( POLYGENE_MODEL_TYPES + "qualifier" );
+    URI TYPE_COMPOSITE = new URIImpl( POLYGENE_MODEL_TYPES + "composite" );
+    URI TYPE_SERVICE = new URIImpl( POLYGENE_MODEL_TYPES + "service" );
+    URI TYPE_METHOD = new URIImpl( POLYGENE_MODEL_TYPES + "method" );
+    URI TYPE_CONSTRAINT = new URIImpl( POLYGENE_MODEL_TYPES + "constraint" );
+    URI TYPE_CONCERN = new URIImpl( POLYGENE_MODEL_TYPES + "concern" );
+    URI TYPE_CONSTRUCTOR = new URIImpl( POLYGENE_MODEL_TYPES + "constructor" );
+    URI TYPE_SIDEEFFECT = new URIImpl( POLYGENE_MODEL_TYPES + "sideeffect" );
+    URI TYPE_MIXIN = new URIImpl( POLYGENE_MODEL_TYPES + "mixin" );
+    URI TYPE_FIELD = new URIImpl( POLYGENE_MODEL_TYPES + "field" );
+    URI TYPE_CLASS = new URIImpl( POLYGENE_MODEL_TYPES + "class" );
+    URI TYPE_OBJECT = new URIImpl( POLYGENE_MODEL_TYPES + "object" );
+    URI TYPE_PARAMETER = new URIImpl( POLYGENE_MODEL_TYPES + "parameter" );
+    URI TYPE_INJECTION = new URIImpl( POLYGENE_MODEL_TYPES + "injection" );
+    URI TYPE_INFO = new URIImpl( POLYGENE_MODEL_TYPES + "info" );
+
+    // Properties
+    URI HAS_INJECTIONS = new URIImpl( POLYGENE_MODEL_PROPERTIES + "hasinjections" );
+
+    // Relationship
+    URI RELATIONSHIP_COMPOSITE = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "composite" );
+    URI RELATIONSHIP_ENTITY = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "entity" );
+    URI RELATIONSHIP_SERVICE = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "service" );
+    URI RELATIONSHIP_OBJECT = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "object" );
+    URI RELATIONSHIP_PRIVATE_METHOD = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "private/method" );
+    URI RELATIONSHIP_INJECTION = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "injection" );
+    URI RELATIONSHIP_CONSTRUCTOR = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "constructor" );
+    URI RELATIONSHIP_FIELD = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "field" );
+    URI RELATIONSHIP_APPLIESTO = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "appliesto" );
+    URI RELATIONSHIP_METHOD = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "method" );
+    URI RELATIONSHIP_CONSTRAINT = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "constraint" );
+    URI RELATIONSHIP_CONCERN = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "concern" );
+    URI RELATIONSHIP_SIDEEFFECT = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "sideeffect" );
+    URI RELATIONSHIP_PUBLIC_SERVICE = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "public/service" );
+    URI RELATIONSHIP_PRIVATE_SERVICE = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "private/service" );
+    URI RELATIONSHIP_PROVIDEDBY = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "providedby" );
+    URI RELATIONSHIP_SERVICEINFO = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "info/service" );
+    URI RELATIONSHIP_INFOVALUE = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "info/value" );
+    URI RELATIONSHIP_MIXIN = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "mixin" );
+    URI RELATIONSHIP_LAYER = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "layer" );
+    URI RELATIONSHIP_MODULE = new URIImpl( POLYGENE_MODEL_RELATIONSHIPS + "module" );
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/RdfFormat.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/RdfFormat.java
new file mode 100644
index 0000000..45a15a0
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/RdfFormat.java
@@ -0,0 +1,26 @@
+/*
+ *  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.polygene.library.rdf;
+
+public enum RdfFormat
+{
+    n3, rdfxml, turtle
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/Rdfs.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/Rdfs.java
new file mode 100644
index 0000000..32f1429
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/Rdfs.java
@@ -0,0 +1,67 @@
+/*
+ *  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.polygene.library.rdf;
+
+import org.openrdf.model.URI;
+import org.openrdf.model.impl.URIImpl;
+
+public interface Rdfs
+{
+    String RDFS = "http://www.w3.org/2000/01/rdf-schema#";
+    String RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+
+    URI ID = new URIImpl( RDF + "ID" );
+
+    // Classes
+    URI RESOURCE = new URIImpl( RDF + "resource" );
+    URI LITERAL = new URIImpl( RDFS + "Literal" );
+    URI XML_LITERAL = new URIImpl( RDF + "XMLLiteral" );
+    URI CLASS = new URIImpl( RDFS + "Class" );
+    URI PROPERTY = new URIImpl( RDF + "Property" );
+    URI DATATYPE = new URIImpl( RDFS + "Datatype" );
+    URI STATEMENT = new URIImpl( RDF + "Statement" );
+    URI BAG = new URIImpl( RDF + "Bag" );
+    URI SEQ = new URIImpl( RDF + "Seq" );
+    URI ALT = new URIImpl( RDF + "Alt" );
+    URI CONTAINER = new URIImpl( RDFS + "Container" );
+    URI CONTAINER_MEMBERSHIP_PROPERTY = new URIImpl( RDFS + "ContainerMembershipProperty" );
+    URI LIST = new URIImpl( RDF + "List" );
+    URI LIST_ITEM = new URIImpl( RDF + "li" );
+
+    // Properties
+    URI TYPE = new URIImpl( RDF + "type" );
+    URI SUB_CLASS_OF = new URIImpl( RDFS + "subClassOf" );
+    URI SUB_PROPERTY_OF = new URIImpl( RDFS + "subPropertyOf" );
+    URI DOMAIN = new URIImpl( RDFS + "domain" );
+    URI RANGE = new URIImpl( RDFS + "range" );
+    URI LABEL = new URIImpl( RDFS + "label" );
+    URI COMMENT = new URIImpl( RDFS + "comment" );
+    URI MEMBER = new URIImpl( RDFS + "member" );
+    URI FIRST = new URIImpl( RDF + "first" );
+    URI REST = new URIImpl( RDF + "rest" );
+    URI SEE_ALSO = new URIImpl( RDFS + "seeAlso" );
+    URI IS_DEFINED_BY = new URIImpl( RDFS + "isDefinedBy" );
+    URI VALUE = new URIImpl( RDF + "value" );
+    URI SUBJECT = new URIImpl( RDF + "subject" );
+    URI PREDICATE = new URIImpl( RDF + "predicate" );
+    URI OBJECT = new URIImpl( RDF + "object" );
+
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/entity/EntityStateSerializer.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/entity/EntityStateSerializer.java
new file mode 100644
index 0000000..0bd823b
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/entity/EntityStateSerializer.java
@@ -0,0 +1,285 @@
+/*
+ *  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.polygene.library.rdf.entity;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.api.type.ValueCompositeType;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.library.rdf.Rdfs;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.ManyAssociationState;
+import org.apache.polygene.spi.serialization.JsonSerializer;
+import org.openrdf.model.BNode;
+import org.openrdf.model.Graph;
+import org.openrdf.model.Literal;
+import org.openrdf.model.Resource;
+import org.openrdf.model.Statement;
+import org.openrdf.model.URI;
+import org.openrdf.model.ValueFactory;
+import org.openrdf.model.impl.GraphImpl;
+
+/**
+ * JAVADOC
+ */
+public class EntityStateSerializer
+{
+    @Service
+    private JsonSerializer serializer;
+
+    public URI createEntityURI( ValueFactory valueFactory, EntityReference reference )
+    {
+        return valueFactory.createURI( reference.toURI() );
+    }
+
+    public Iterable<Statement> serialize( final EntityState entityState )
+    {
+        return serialize( entityState, true );
+    }
+
+    public Iterable<Statement> serialize( final EntityState entityState,
+                                          final boolean includeNonQueryable
+    )
+    {
+        Graph graph = new GraphImpl();
+        serialize( entityState, includeNonQueryable, graph );
+        return graph;
+    }
+
+    public void serialize( final EntityState entityState,
+                           final boolean includeNonQueryable,
+                           final Graph graph
+    )
+    {
+        ValueFactory values = graph.getValueFactory();
+        EntityReference reference = entityState.entityReference();
+        URI entityUri = createEntityURI( values, reference );
+
+        graph.add( entityUri,
+                   Rdfs.TYPE,
+                   values.createURI(
+                       Classes.toURI( entityState.entityDescriptor().types().findFirst().orElse( null ) ) ) );
+
+        serializeProperties( entityState,
+                             graph,
+                             entityUri,
+                             entityState.entityDescriptor(),
+                             includeNonQueryable );
+
+        serializeAssociations( entityState,
+                               graph,
+                               entityUri,
+                               entityState.entityDescriptor().state().associations(),
+                               includeNonQueryable );
+
+        serializeManyAssociations( entityState,
+                                   graph,
+                                   entityUri,
+                                   entityState.entityDescriptor().state().manyAssociations(),
+                                   includeNonQueryable );
+    }
+
+    private void serializeProperties( EntityState entityState,
+                                      Graph graph, Resource subject,
+                                      EntityDescriptor entityType,
+                                      boolean includeNonQueryable )
+    {
+        // Properties
+        entityType.state().properties().forEach(
+            persistentProperty ->
+            {
+                Object property = entityState.propertyValueOf( persistentProperty.qualifiedName() );
+                if( property != null )
+                {
+                    serializeProperty( persistentProperty, property, subject, graph, includeNonQueryable );
+                }
+            } );
+    }
+
+    private void serializeProperty( PropertyDescriptor persistentProperty, Object property,
+                                    Resource subject, Graph graph,
+                                    boolean includeNonQueryable )
+    {
+        if( !( includeNonQueryable || persistentProperty.queryable() ) )
+        {
+            return; // Skip non-queryable
+        }
+
+        ValueType valueType = persistentProperty.valueType();
+
+        final ValueFactory valueFactory = graph.getValueFactory();
+
+        String propertyURI = persistentProperty.qualifiedName().toURI();
+        URI predicate = valueFactory.createURI( propertyURI );
+        String baseURI = propertyURI.substring( 0, propertyURI.indexOf( '#' ) ) + "/";
+
+        if( valueType instanceof ValueCompositeType )
+        {
+            serializeValueComposite( subject, predicate, (ValueComposite) property, valueType,
+                                     graph, baseURI, includeNonQueryable );
+        }
+        else
+        {
+            String stringProperty = serializer.serialize( Serializer.Options.NO_TYPE_INFO, property );
+            final Literal object = valueFactory.createLiteral( stringProperty );
+            graph.add( subject, predicate, object );
+        }
+    }
+
+    private void serializeValueComposite( Resource subject, URI predicate,
+                                          ValueComposite value,
+                                          ValueType valueType,
+                                          Graph graph,
+                                          String baseUri,
+                                          boolean includeNonQueryable
+    )
+    {
+        final ValueFactory valueFactory = graph.getValueFactory();
+        BNode collection = valueFactory.createBNode();
+        graph.add( subject, predicate, collection );
+
+        ( (ValueCompositeType) valueType ).properties().forEach(
+            persistentProperty ->
+            {
+                Object propertyValue
+                    = PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF
+                    .apply( value )
+                    .state()
+                    .propertyFor( persistentProperty.accessor() )
+                    .get();
+
+                if( propertyValue != null )
+                {
+                    ValueType type = persistentProperty
+                        .valueType();
+                    if( type instanceof ValueCompositeType )
+                    {
+                        URI pred = valueFactory.createURI( baseUri,
+                                                           persistentProperty
+                                                               .qualifiedName()
+                                                               .name() );
+                        serializeValueComposite( collection, pred,
+                                                 (ValueComposite) propertyValue,
+                                                 type, graph,
+                                                 baseUri
+                                                 + persistentProperty
+                                                     .qualifiedName()
+                                                     .name() + "/",
+                                                 includeNonQueryable );
+                    }
+                    else
+                    {
+                        serializeProperty( persistentProperty,
+                                           propertyValue,
+                                           collection, graph,
+                                           includeNonQueryable );
+                    }
+                }
+            } );
+    }
+
+    private void serializeAssociations( final EntityState entityState,
+                                        final Graph graph, URI entityUri,
+                                        final Stream<? extends AssociationDescriptor> associations,
+                                        final boolean includeNonQueryable
+    )
+    {
+        ValueFactory values = graph.getValueFactory();
+
+        // Associations
+        associations.filter( type -> includeNonQueryable || type.queryable() ).forEach(
+            associationType ->
+            {
+                EntityReference associatedId
+                    = entityState
+                    .associationValueOf(
+                        associationType
+                            .qualifiedName() );
+                if( associatedId != null )
+                {
+                    URI assocURI = values
+                        .createURI(
+                            associationType
+                                .qualifiedName()
+                                .toURI() );
+                    URI assocEntityURI
+                        = values.createURI(
+                        associatedId
+                            .toURI() );
+                    graph.add( entityUri,
+                               assocURI,
+                               assocEntityURI );
+                }
+            } );
+    }
+
+    private void serializeManyAssociations( final EntityState entityState,
+                                            final Graph graph,
+                                            final URI entityUri,
+                                            final Stream<? extends AssociationDescriptor> associations,
+                                            final boolean includeNonQueryable
+    )
+    {
+        ValueFactory values = graph.getValueFactory();
+
+        // Many-Associations
+        associations.filter( type -> includeNonQueryable || type.queryable() ).forEach(
+            associationType ->
+            {
+                BNode collection = values
+                    .createBNode();
+                graph.add( entityUri, values
+                               .createURI(
+                                   associationType
+                                       .qualifiedName()
+                                       .toURI() ),
+                           collection );
+                graph.add( collection,
+                           Rdfs.TYPE,
+                           Rdfs.SEQ );
+
+                ManyAssociationState
+                    associatedIds
+                    = entityState
+                    .manyAssociationValueOf(
+                        associationType
+                            .qualifiedName() );
+                for( EntityReference associatedId : associatedIds )
+                {
+                    URI assocEntityURI
+                        = values.createURI(
+                        associatedId
+                            .toURI() );
+                    graph.add( collection,
+                               Rdfs.LIST_ITEM,
+                               assocEntityURI );
+                }
+            } );
+    }
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/entity/EntityTypeSerializer.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/entity/EntityTypeSerializer.java
new file mode 100644
index 0000000..e16c4e0
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/entity/EntityTypeSerializer.java
@@ -0,0 +1,169 @@
+/*
+ *  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.polygene.library.rdf.entity;
+
+import java.math.BigDecimal;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.Period;
+import java.time.ZonedDateTime;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.library.rdf.Rdfs;
+import org.apache.polygene.library.rdf.PolygeneEntityType;
+import org.openrdf.model.Graph;
+import org.openrdf.model.Statement;
+import org.openrdf.model.URI;
+import org.openrdf.model.ValueFactory;
+import org.openrdf.model.impl.GraphImpl;
+import org.openrdf.model.vocabulary.OWL;
+import org.openrdf.model.vocabulary.XMLSchema;
+
+/**
+ * JAVADOC
+ */
+public class EntityTypeSerializer
+{
+
+    private final Map<String, URI> dataTypes = new HashMap<>( 12 );
+
+    public EntityTypeSerializer()
+    {
+        // TODO A ton more types need to be added here
+        dataTypes.put( String.class.getName(), XMLSchema.STRING );
+        dataTypes.put( Integer.class.getName(), XMLSchema.INT );
+        dataTypes.put( Boolean.class.getName(), XMLSchema.BOOLEAN );
+        dataTypes.put( Byte.class.getName(), XMLSchema.BYTE );
+        dataTypes.put( BigDecimal.class.getName(), XMLSchema.DECIMAL );
+        dataTypes.put( Double.class.getName(), XMLSchema.DOUBLE );
+        dataTypes.put( Long.class.getName(), XMLSchema.LONG );
+        dataTypes.put( Short.class.getName(), XMLSchema.SHORT );
+        dataTypes.put( Instant.class.getName(), XMLSchema.LONG );
+        dataTypes.put( OffsetDateTime.class.getName(), XMLSchema.DATETIME );
+        dataTypes.put( ZonedDateTime.class.getName(), XMLSchema.DATETIME );
+        dataTypes.put( LocalDateTime.class.getName(), XMLSchema.DATETIME );
+        dataTypes.put( LocalDate.class.getName(), XMLSchema.DATE );
+        dataTypes.put( LocalTime.class.getName(), XMLSchema.TIME );
+        dataTypes.put( Duration.class.getName(), XMLSchema.DURATION );
+        dataTypes.put( Period.class.getName(), XMLSchema.DURATION );
+    }
+
+    public Iterable<Statement> serialize( final EntityDescriptor entityDescriptor )
+    {
+        Graph graph = new GraphImpl();
+        ValueFactory values = graph.getValueFactory();
+        URI entityTypeUri = values.createURI( Classes.toURI( entityDescriptor.types().findFirst().orElse( null ) ) );
+
+        graph.add( entityTypeUri, Rdfs.TYPE, Rdfs.CLASS );
+        graph.add( entityTypeUri, Rdfs.TYPE, OWL.CLASS );
+
+        graph.add( entityTypeUri,
+                   PolygeneEntityType.TYPE,
+                   values.createLiteral( entityDescriptor.types().findFirst().get().toString() )
+        );
+        graph.add( entityTypeUri, PolygeneEntityType.QUERYABLE, values.createLiteral( entityDescriptor.queryable() ) );
+
+        serializeMixinTypes( entityDescriptor, graph, entityTypeUri );
+
+        serializePropertyTypes( entityDescriptor, graph, entityTypeUri );
+        serializeAssociationTypes( entityDescriptor, graph, entityTypeUri );
+        serializeManyAssociationTypes( entityDescriptor, graph, entityTypeUri );
+
+        return graph;
+    }
+
+    private void serializeMixinTypes( final EntityDescriptor entityDescriptor,
+                                      final Graph graph,
+                                      final URI entityTypeUri
+    )
+    {
+        ValueFactory values = graph.getValueFactory();
+
+        entityDescriptor.mixinTypes().forEach( mixinType -> {
+            graph.add( entityTypeUri, Rdfs.SUB_CLASS_OF, values.createURI( Classes.toURI( mixinType ) ) );
+        } );
+    }
+
+    private void serializeManyAssociationTypes( final EntityDescriptor entityDescriptor,
+                                                final Graph graph,
+                                                final URI entityTypeUri
+    )
+    {
+        ValueFactory values = graph.getValueFactory();
+        // ManyAssociations
+        entityDescriptor.state().manyAssociations().forEach( manyAssociationType -> {
+            URI associationURI = values.createURI( manyAssociationType.qualifiedName().toURI() );
+            graph.add( associationURI, Rdfs.DOMAIN, entityTypeUri );
+
+            graph.add( associationURI, Rdfs.TYPE, Rdfs.SEQ );
+
+            URI associatedURI = values.createURI( manyAssociationType.qualifiedName().toURI() );
+            graph.add( associationURI, Rdfs.RANGE, associatedURI );
+            graph.add( associationURI, Rdfs.RANGE, XMLSchema.ANYURI );
+        } );
+    }
+
+    private void serializeAssociationTypes( final EntityDescriptor entityDescriptor,
+                                            final Graph graph,
+                                            final URI entityTypeUri
+    )
+    {
+        ValueFactory values = graph.getValueFactory();
+        // Associations
+        entityDescriptor.state().associations().forEach( associationType -> {
+            URI associationURI = values.createURI( associationType.qualifiedName().toURI() );
+            graph.add( associationURI, Rdfs.DOMAIN, entityTypeUri );
+            graph.add( associationURI, Rdfs.TYPE, Rdfs.PROPERTY );
+
+            URI associatedURI = values.createURI( Classes.toURI( Classes.RAW_CLASS.apply( associationType.type() ) ) );
+            graph.add( associationURI, Rdfs.RANGE, associatedURI );
+            graph.add( associationURI, Rdfs.RANGE, XMLSchema.ANYURI );
+        } );
+    }
+
+    private void serializePropertyTypes( final EntityDescriptor entityDescriptor,
+                                         final Graph graph,
+                                         final URI entityTypeUri
+    )
+    {
+        ValueFactory values = graph.getValueFactory();
+
+        // Properties
+        entityDescriptor.state().properties().forEach( persistentProperty -> {
+            URI propertyURI = values.createURI( persistentProperty.qualifiedName().toURI() );
+            graph.add( propertyURI, Rdfs.DOMAIN, entityTypeUri );
+            graph.add( propertyURI, Rdfs.TYPE, Rdfs.PROPERTY );
+
+            // TODO Support more types
+            URI type = dataTypes.get( persistentProperty.valueType().primaryType().getName() );
+            if( type != null )
+            {
+                graph.add( propertyURI, Rdfs.RANGE, type );
+            }
+        } );
+    }
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/entity/package.html b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/entity/package.html
new file mode 100644
index 0000000..8e0d1de
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/entity/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>RDF Entity Serializer.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/model/ApplicationSerializer.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/model/ApplicationSerializer.java
new file mode 100644
index 0000000..7c65ae1
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/model/ApplicationSerializer.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.library.rdf.model;
+
+import java.io.PrintWriter;
+import org.openrdf.model.Graph;
+import org.openrdf.model.impl.GraphImpl;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.library.rdf.serializer.RdfXmlSerializer;
+import org.apache.polygene.library.rdf.serializer.SerializerContext;
+
+public class ApplicationSerializer
+{
+    public Graph serialize( Application app )
+    {
+        Graph graph = new GraphImpl();
+        SerializerContext context = new SerializerContext( graph );
+        ApplicationVisitor applicationVisitor = new ApplicationVisitor( context );
+        app.descriptor().accept( applicationVisitor );
+        return graph;
+    }
+
+    public void outputMetadata( Graph rdf, PrintWriter writer )
+        throws Exception
+    {
+        new RdfXmlSerializer().serialize( rdf, writer );
+    }
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/model/ApplicationVisitor.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/model/ApplicationVisitor.java
new file mode 100644
index 0000000..253eb53
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/model/ApplicationVisitor.java
@@ -0,0 +1,116 @@
+/*
+ *  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.polygene.library.rdf.model;
+
+import org.apache.polygene.api.composite.MethodDescriptor;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitorAdapter;
+import org.apache.polygene.library.rdf.PolygeneRdf;
+import org.apache.polygene.library.rdf.serializer.SerializerContext;
+
+/**
+ * JAVADOC
+ */
+class ApplicationVisitor extends HierarchicalVisitorAdapter<Object, Object, RuntimeException>
+{
+    private SerializerContext context;
+
+    private String appUri;
+
+    private String layerUri;
+
+    private String moduleUri;
+
+    private String compositeUri;
+
+    ApplicationVisitor( SerializerContext context )
+    {
+        this.context = context;
+    }
+
+    @Override
+    public boolean visitEnter( Object visited )
+        throws RuntimeException
+    {
+        if( visited instanceof ApplicationDescriptor )
+        {
+            ApplicationDescriptor applicationDescriptor = (ApplicationDescriptor) visited;
+            appUri = context.createApplicationUri( applicationDescriptor.name() );
+            context.setNameAndType( appUri, applicationDescriptor.name(), PolygeneRdf.TYPE_APPLICATION );
+        }
+
+        if( visited instanceof LayerDescriptor )
+        {
+            LayerDescriptor layerDescriptor = (LayerDescriptor) visited;
+            layerUri = context.createLayerUri( appUri, layerDescriptor.name() );
+            context.setNameAndType( layerUri, layerDescriptor.name(), PolygeneRdf.TYPE_LAYER );
+            context.addRelationship( appUri, PolygeneRdf.RELATIONSHIP_LAYER, layerUri );
+        }
+
+        if( visited instanceof ModuleDescriptor )
+        {
+            ModuleDescriptor moduleDescriptor = (ModuleDescriptor) visited;
+            moduleUri = context.createModuleUri( layerUri, moduleDescriptor.name() );
+            context.setNameAndType( layerUri, moduleDescriptor.name(), PolygeneRdf.TYPE_MODULE );
+
+            context.addRelationship( layerUri, PolygeneRdf.RELATIONSHIP_MODULE, moduleUri );
+        }
+
+        if( visited instanceof TransientDescriptor )
+        {
+            TransientDescriptor transientDescriptor = (TransientDescriptor) visited;
+            compositeUri = context.createCompositeUri( moduleUri, transientDescriptor.types().findFirst().orElse( null ) );
+            context.addType( compositeUri, PolygeneRdf.TYPE_COMPOSITE );
+            context.addRelationship( moduleUri, PolygeneRdf.RELATIONSHIP_COMPOSITE, compositeUri );
+        }
+
+        if( visited instanceof EntityDescriptor )
+        {
+            EntityDescriptor entityDescriptor = (EntityDescriptor) visited;
+            compositeUri = context.createCompositeUri( moduleUri, entityDescriptor.types().findFirst().orElse( null ));
+            context.addType( compositeUri, PolygeneRdf.TYPE_ENTITY );
+            context.addRelationship( moduleUri, PolygeneRdf.RELATIONSHIP_ENTITY, compositeUri );
+        }
+
+        if( visited instanceof ObjectDescriptor )
+        {
+            ObjectDescriptor objectDescriptor = (ObjectDescriptor) visited;
+            compositeUri = context.createCompositeUri( moduleUri, objectDescriptor.types().findFirst().orElse( null ) );
+            context.addType( compositeUri, PolygeneRdf.TYPE_OBJECT );
+            context.addRelationship( moduleUri, PolygeneRdf.RELATIONSHIP_OBJECT, compositeUri );
+        }
+
+        if( visited instanceof MethodDescriptor )
+        {
+            MethodDescriptor compositeMethodDescriptor = (MethodDescriptor) visited;
+            String compositeMethodUri = context.createCompositeMethodUri( compositeUri, compositeMethodDescriptor.method() );
+            context.addType( compositeMethodUri, PolygeneRdf.TYPE_METHOD );
+            context.addRelationship( compositeUri, PolygeneRdf.RELATIONSHIP_METHOD, compositeMethodUri );
+        }
+
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/model/Model2XML.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/model/Model2XML.java
new file mode 100644
index 0000000..f9cb7ec
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/model/Model2XML.java
@@ -0,0 +1,216 @@
+/*
+ *  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.polygene.library.rdf.model;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Stack;
+import java.util.function.Function;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.apache.polygene.api.composite.DependencyDescriptor;
+import org.apache.polygene.api.composite.MethodDescriptor;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.mixin.MixinDescriptor;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * TODO
+ */
+public class Model2XML
+    implements Function<ApplicationDescriptor, Document>
+{
+    private static Map<String, String> simpleMappings = new HashMap<>();
+
+    static
+    {
+        simpleMappings.put( "TransientsModel", "transients" );
+        simpleMappings.put( "EntitiesModel", "entities" );
+        simpleMappings.put( "ServicesModel", "services" );
+        simpleMappings.put( "ImportedServicesModel", "importedservices" );
+        simpleMappings.put( "ObjectsModel", "objects" );
+        simpleMappings.put( "ValuesModel", "values" );
+        simpleMappings.put( "MixinsModel", "mixins" );
+        simpleMappings.put( "CompositeMethodsModel", "methods" );
+        simpleMappings.put( "InjectedFieldsModel", "injectedfields" );
+        simpleMappings.put( "InjectedFieldModel", "injectedfield" );
+    }
+
+    @Override
+    public Document apply( ApplicationDescriptor application )
+    {
+        try
+        {
+            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+            final Document document = builder.newDocument();
+
+            final Stack<Node> current = new Stack<>();
+            current.push( document );
+
+            application.accept( new HierarchicalVisitor<Object, Object, DOMException>()
+            {
+                @Override
+                public boolean visitEnter( Object visited )
+                    throws DOMException
+                {
+                    String mapping = simpleMappings.get( visited.getClass().getSimpleName() );
+                    if( mapping != null )
+                    {
+                        Node node = document.createElement( "mapping" );
+                        current.push( node );
+                    }
+                    else if( visited instanceof ApplicationDescriptor )
+                    {
+                        ApplicationDescriptor applicationDescriptor = (ApplicationDescriptor) visited;
+                        Node application = document.createElement( "application" );
+
+                        addAttribute( "name", applicationDescriptor.name(), application );
+
+                        current.push( application );
+                    }
+                    else if( visited instanceof LayerDescriptor )
+                    {
+                        LayerDescriptor layerDescriptor = (LayerDescriptor) visited;
+                        Node layer = document.createElement( "layer" );
+
+                        addAttribute( "name", layerDescriptor.name(), layer );
+
+                        current.push( layer );
+                    }
+                    else if( visited instanceof ModuleDescriptor )
+                    {
+                        ModuleDescriptor moduleDescriptor = (ModuleDescriptor) visited;
+                        Node module = document.createElement( "module" );
+
+                        addAttribute( "name", moduleDescriptor.name(), module );
+
+                        current.push( module );
+                    }
+                    else if( visited instanceof TransientDescriptor )
+                    {
+                        TransientDescriptor descriptor = (TransientDescriptor) visited;
+                        Node node = document.createElement( "transient" );
+
+                        addAttribute( "type", descriptor.types().findFirst().get().getName(), node );
+                        addAttribute( "visibility", descriptor.visibility().name(), node );
+
+                        current.push( node );
+                    }
+                    else if( visited instanceof MethodDescriptor )
+                    {
+                        MethodDescriptor descriptor = (MethodDescriptor) visited;
+                        Node node = document.createElement( "method" );
+
+                        addAttribute( "name", descriptor.method().getName(), node );
+
+                        current.push( node );
+                    }
+                    else if( visited instanceof MixinDescriptor )
+                    {
+                        MixinDescriptor descriptor = (MixinDescriptor) visited;
+                        Node node = document.createElement( "mixin" );
+
+                        addAttribute( "class", descriptor.mixinClass().getName(), node );
+
+                        current.push( node );
+                    }
+                    else if( visited instanceof DependencyDescriptor )
+                    {
+                        DependencyDescriptor descriptor = (DependencyDescriptor) visited;
+                        Node node = document.createElement( "dependency" );
+
+                        addAttribute( "annotation", descriptor.injectionAnnotation().toString(), node );
+                        addAttribute( "injection", descriptor.injectionType().toString(), node );
+                        addAttribute( "optional", Boolean.toString( descriptor.optional() ), node );
+
+                        current.push( node );
+                    }
+                    else
+                    {
+                        Element element = document.createElement( visited.getClass().getSimpleName() );
+                        current.push( element );
+                    }
+
+                    return true;
+                }
+
+                @Override
+                public boolean visitLeave( Object visited )
+                    throws DOMException
+                {
+                    Node node = current.pop();
+
+                    if( node.getChildNodes().getLength() == 0 && node.getAttributes().getLength() == 0 )
+                    {
+                        return true;
+                    }
+
+                    current.peek().appendChild( node );
+                    return true;
+                }
+
+                @Override
+                public boolean visit( Object visited )
+                    throws DOMException
+                {
+                    Element element;
+                    if( visited instanceof DependencyDescriptor )
+                    {
+                        DependencyDescriptor descriptor = (DependencyDescriptor) visited;
+                        element = document.createElement( "dependency" );
+
+                        addAttribute( "annotation", descriptor.injectionAnnotation().toString(), element );
+                        addAttribute( "injection", descriptor.injectionType().toString(), element );
+                        addAttribute( "optional", Boolean.toString( descriptor.optional() ), element );
+                    }
+                    else
+                    {
+                        element = document.createElement( visited.getClass().getSimpleName() );
+                    }
+
+                    current.peek().appendChild( element );
+
+                    return true;
+                }
+
+                private void addAttribute( String name, String value, Node node )
+                {
+                    Attr attr = document.createAttribute( name );
+                    attr.setValue( value );
+                    ( (Element) node ).setAttributeNode( attr );
+                }
+            } );
+
+            return document;
+        }
+        catch( Exception exception )
+        {
+            throw new IllegalArgumentException( exception );
+        }
+    }
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/model/package.html b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/model/package.html
new file mode 100644
index 0000000..ae55909
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/model/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>RDF Application Model Serializer.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/package.html b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/package.html
new file mode 100644
index 0000000..4e3ffde
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>RDF Library.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/HttpRepositoryConfiguration.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/HttpRepositoryConfiguration.java
new file mode 100644
index 0000000..b1de8af
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/HttpRepositoryConfiguration.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.library.rdf.repository;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+public interface HttpRepositoryConfiguration
+{
+    /**
+     * The URL of the remote Sesame HTTP Repository.
+     *
+     * Default: http://localhost:8183/
+     *
+     * @return The configured URL for the remote Sesame HTTP Repository.
+     */
+    @Optional
+    Property<String> repositoryUrl();
+
+    /**
+     * The ID of the Repository at the remote Sesame HTTP host.
+     *
+     * Default: polygene
+     *
+     * @return The configured ID at the remote Sesame HTTP host.
+     */
+    @Optional
+    Property<String> repositoryId();
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/HttpRepositoryService.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/HttpRepositoryService.java
new file mode 100644
index 0000000..9005066
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/HttpRepositoryService.java
@@ -0,0 +1,98 @@
+/*
+ *  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.polygene.library.rdf.repository;
+
+import org.openrdf.repository.Repository;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.http.HTTPRepository;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceReference;
+
+@Mixins( HttpRepositoryService.HttpRepositoryMixin.class )
+@Activators( HttpRepositoryService.Activator.class )
+public interface HttpRepositoryService
+    extends Repository
+{
+    @Override
+    void initialize()
+            throws RepositoryException;
+
+    @Override
+    void shutDown()
+            throws RepositoryException;
+
+    class Activator
+            extends ActivatorAdapter<ServiceReference<HttpRepositoryService>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<HttpRepositoryService> activated )
+                throws Exception
+        {
+            activated.get().initialize();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<HttpRepositoryService> passivating )
+                throws Exception
+        {
+            passivating.get().shutDown();
+        }
+
+    }
+
+    class HttpRepositoryMixin
+        extends HTTPRepository
+        implements Repository
+    {
+        public HttpRepositoryMixin( @This Configuration<HttpRepositoryConfiguration> configuration )
+        {
+            super( getRepositoryUrl( configuration.get() ), getRepositoryId( configuration.get() ) );
+        }
+
+        private static String getRepositoryUrl( HttpRepositoryConfiguration configuration )
+        {
+            Property<String> repositoryUrl = configuration.repositoryUrl();
+            String url = repositoryUrl.get();
+            if( url == null )
+            {
+                url = "http://localhost:8183/";
+                repositoryUrl.set( url );
+            }
+            return url;
+        }
+
+        private static String getRepositoryId( HttpRepositoryConfiguration configuration )
+        {
+            Property<String> id = configuration.repositoryId();
+            if( id.get() == null )
+            {
+                id.set( "polygene" );
+            }
+            return id.get();
+        }
+    }
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/MemoryRepositoryService.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/MemoryRepositoryService.java
new file mode 100644
index 0000000..c30c39f
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/MemoryRepositoryService.java
@@ -0,0 +1,138 @@
+/*
+ *  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.polygene.library.rdf.repository;
+
+import java.io.File;
+import org.openrdf.model.ValueFactory;
+import org.openrdf.repository.Repository;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.sail.SailRepository;
+import org.openrdf.sail.memory.MemoryStore;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceReference;
+
+@Mixins( MemoryRepositoryService.MemoryRepositoryMixin.class )
+@Activators( MemoryRepositoryService.Activator.class )
+public interface MemoryRepositoryService
+    extends Repository
+{
+
+    @Override
+    void initialize()
+        throws RepositoryException;
+
+    @Override
+    void shutDown()
+        throws RepositoryException;
+
+    class Activator
+        extends ActivatorAdapter<ServiceReference<MemoryRepositoryService>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<MemoryRepositoryService> activated )
+            throws Exception
+        {
+            activated.get().initialize();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<MemoryRepositoryService> passivating )
+            throws Exception
+        {
+            passivating.get().shutDown();
+        }
+    }
+
+    abstract class MemoryRepositoryMixin
+        implements MemoryRepositoryService, ResetableRepository
+    {
+
+        SailRepository repo;
+
+        public MemoryRepositoryMixin()
+        {
+            repo = new SailRepository( new MemoryStore() );
+        }
+
+        @Override
+        public void initialize()
+            throws RepositoryException
+        {
+            repo.initialize();
+        }
+
+        @Override
+        public boolean isInitialized()
+        {
+            return repo.isInitialized();
+        }
+
+        @Override
+        public void shutDown()
+            throws RepositoryException
+        {
+            repo.shutDown();
+        }
+
+        @Override
+        public void setDataDir( File dataDir )
+        {
+            repo.setDataDir( dataDir );
+        }
+
+        @Override
+        public File getDataDir()
+        {
+            return repo.getDataDir();
+        }
+
+        @Override
+        public boolean isWritable()
+            throws RepositoryException
+        {
+            return repo.isWritable();
+        }
+
+        @Override
+        public RepositoryConnection getConnection()
+            throws RepositoryException
+        {
+            return repo.getConnection();
+        }
+
+        @Override
+        public ValueFactory getValueFactory()
+        {
+            return repo.getValueFactory();
+        }
+
+        @Override
+        public void discardEntireRepository()
+            throws RepositoryException
+        {
+            repo = new SailRepository( new MemoryStore() );
+        }
+    }
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/NativeConfiguration.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/NativeConfiguration.java
new file mode 100644
index 0000000..3e40aa1
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/NativeConfiguration.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.rdf.repository;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.configuration.ConfigurationComposite;
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.constraints.annotation.Matches;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+@Queryable( false )
+// START SNIPPET: config
+public interface NativeConfiguration extends ConfigurationComposite
+{
+    @Optional @Matches( "([spoc][spoc][spoc][spoc],?)*" ) Property<String> tripleIndexes();
+
+    @Optional Property<String> dataDirectory();
+
+    @UseDefaults Property<Boolean> forceSync();
+}
+// END SNIPPET: config
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/NativeRepositoryService.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/NativeRepositoryService.java
new file mode 100644
index 0000000..18643bd
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/NativeRepositoryService.java
@@ -0,0 +1,231 @@
+/*
+ *  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.polygene.library.rdf.repository;
+
+import java.io.File;
+import org.openrdf.model.ValueFactory;
+import org.openrdf.repository.Repository;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.sail.SailRepository;
+import org.openrdf.sail.nativerdf.NativeStore;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.Availability;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.library.fileconfig.FileConfiguration;
+
+@Mixins( { NativeRepositoryService.NativeRepositoryMixin.class } )
+@Activators( NativeRepositoryService.Activator.class )
+public interface NativeRepositoryService extends Repository, Availability
+{
+    @Override
+    void initialize()
+        throws RepositoryException;
+
+    @Override
+    void shutDown()
+        throws RepositoryException;
+
+    class Activator
+        extends ActivatorAdapter<ServiceReference<NativeRepositoryService>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<NativeRepositoryService> activated )
+            throws Exception
+        {
+            activated.get().initialize();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<NativeRepositoryService> passivating )
+            throws Exception
+        {
+            passivating.get().shutDown();
+        }
+    }
+
+    abstract class NativeRepositoryMixin
+        implements NativeRepositoryService, ResetableRepository
+    {
+        @Optional
+        @Service
+        FileConfiguration fileConfiguration;
+
+        @This
+        private Configuration<NativeConfiguration> configuration;
+
+        private SailRepository repo;
+        private boolean isNotInitialized;
+
+        public NativeRepositoryMixin()
+        {
+            isNotInitialized = true;
+            repo = new SailRepository( new NativeStore() );
+        }
+
+        @Override
+        public void setDataDir( File dataDir )
+        {
+            repo.setDataDir( dataDir );
+        }
+
+        @Override
+        public File getDataDir()
+        {
+            return repo.getDataDir();
+        }
+
+        @Override
+        public void initialize()
+            throws RepositoryException
+        {
+            String dataDir = configuration.get().dataDirectory().get();
+            File dataDirectory;
+            if( dataDir == null || "".equals( dataDir ) )
+            {
+                String serviceIdentity = configuration.get().identity().get().toString();
+                if( fileConfiguration != null )
+                {
+                    dataDir = new File( fileConfiguration.dataDirectory(), serviceIdentity ).getAbsolutePath();
+                }
+                else
+                {
+                    if( serviceIdentity == null || "".equals( serviceIdentity ) )
+                    {
+                        dataDir = "./rdf/repositories/polygene";
+                    }
+                    else
+                    {
+                        dataDir = "./rdf/repositories/" + serviceIdentity;
+                    }
+                }
+                configuration.get().dataDirectory().set( dataDir );
+                configuration.save();
+                dataDirectory = new File( dataDir );
+            }
+            else
+            {
+                dataDirectory = new File( dataDir ).getAbsoluteFile();
+            }
+            initializeRepository( dataDirectory );
+        }
+
+        @Override
+        public boolean isInitialized()
+        {
+            return !isNotInitialized;
+        }
+
+        @Override
+        public void shutDown()
+            throws RepositoryException
+        {
+            repo.shutDown();
+        }
+
+        @Override
+        public boolean isWritable()
+            throws RepositoryException
+        {
+            return repo.isWritable();
+        }
+
+        @Override
+        public RepositoryConnection getConnection()
+            throws RepositoryException
+        {
+            if( isNotInitialized )
+            {
+                return null;
+            }
+            return repo.getConnection();
+        }
+
+        @Override
+        public ValueFactory getValueFactory()
+        {
+            return repo.getValueFactory();
+        }
+
+        @Override
+        public void discardEntireRepository()
+            throws RepositoryException
+        {
+            File dataDir = repo.getDataDir();
+            repo.shutDown();
+            delete( dataDir );
+            initializeRepository( dataDir );
+        }
+
+        private void delete( File dataDir )
+        {
+            File[] children = dataDir.listFiles();
+            if( children == null )
+            {
+                return;
+            }
+            for( File child : children )
+            {
+                if( child.isDirectory() )
+                {
+                    delete( child );
+                }
+                else
+                {
+                    //noinspection ResultOfMethodCallIgnored
+                    child.delete();
+                }
+            }
+        }
+
+        private void initializeRepository( File dataDir )
+            throws RepositoryException
+        {
+            String tripleIndexes = configuration.get().tripleIndexes().get();
+            if( tripleIndexes == null )
+            {
+                tripleIndexes = "";
+                configuration.get().tripleIndexes().set( tripleIndexes );
+            }
+            boolean forceSync = configuration.get().forceSync().get();
+
+            NativeStore store = (NativeStore) repo.getSail();
+            store.setDataDir( dataDir );
+            store.setTripleIndexes( tripleIndexes );
+            store.setForceSync( forceSync );
+            repo.initialize();
+            isNotInitialized = false;
+        }
+
+        @Override
+        public boolean isAvailable()
+        {
+            return !isNotInitialized;
+        }
+    }
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/RdbmsRepositoryConfiguration.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/RdbmsRepositoryConfiguration.java
new file mode 100644
index 0000000..9c5ad6c
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/RdbmsRepositoryConfiguration.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.rdf.repository;
+
+import org.apache.polygene.api.property.Property;
+
+// START SNIPPET: config
+public interface RdbmsRepositoryConfiguration
+{
+    Property<String> jdbcDriver();
+    Property<String> jdbcUrl();
+    Property<String> user();
+    Property<String> password();
+}
+// END SNIPPET: config
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/RdbmsRepositoryService.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/RdbmsRepositoryService.java
new file mode 100644
index 0000000..61cf547
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/RdbmsRepositoryService.java
@@ -0,0 +1,136 @@
+/*
+ *  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.polygene.library.rdf.repository;
+
+import java.io.File;
+import org.openrdf.model.ValueFactory;
+import org.openrdf.repository.Repository;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.sail.SailRepository;
+import org.openrdf.sail.rdbms.RdbmsStore;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceReference;
+
+@Mixins( RdbmsRepositoryService.RdbmsRepositoryMixin.class )
+@Activators( RdbmsRepositoryService.Activator.class )
+public interface RdbmsRepositoryService extends Repository
+{
+
+    @Override
+    void initialize()
+            throws RepositoryException;
+
+    @Override
+    void shutDown()
+            throws RepositoryException;
+
+    class Activator
+            extends ActivatorAdapter<ServiceReference<RdbmsRepositoryService>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<RdbmsRepositoryService> activated )
+                throws Exception
+        {
+            activated.get().initialize();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<RdbmsRepositoryService> passivating )
+                throws Exception
+        {
+            passivating.get().shutDown();
+        }
+
+    }
+
+    abstract class RdbmsRepositoryMixin
+        implements RdbmsRepositoryService
+    {
+        @This
+        private Configuration<RdbmsRepositoryConfiguration> configuration;
+
+        private SailRepository repo;
+
+        @Override
+        public void setDataDir( File file )
+        {
+            repo.setDataDir( file );
+        }
+
+        @Override
+        public File getDataDir()
+        {
+            return repo.getDataDir();
+        }
+
+        @Override
+        public void initialize()
+            throws RepositoryException
+        {
+            RdbmsRepositoryConfiguration conf = configuration.get();
+            String jdbcDriver = conf.jdbcDriver().get();
+            String jdbcUrl = conf.jdbcUrl().get();
+            String user = conf.user().get();
+            String password = conf.password().get();
+            repo = new SailRepository( new RdbmsStore( jdbcDriver, jdbcUrl, user, password ) );
+            repo.initialize();
+        }
+
+        @Override
+        public boolean isInitialized()
+        {
+            return repo.isInitialized();
+        }
+        
+        @Override
+        public void shutDown()
+            throws RepositoryException
+        {
+            repo.shutDown();
+        }
+
+        @Override
+        public boolean isWritable()
+            throws RepositoryException
+        {
+            return repo.isWritable();
+        }
+
+        @Override
+        public RepositoryConnection getConnection()
+            throws RepositoryException
+        {
+            return repo.getConnection();
+        }
+
+        @Override
+        public ValueFactory getValueFactory()
+        {
+            return repo.getValueFactory();
+        }
+    }
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/ResetableRepository.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/ResetableRepository.java
new file mode 100644
index 0000000..c227e24
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/ResetableRepository.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.rdf.repository;
+
+import org.openrdf.repository.RepositoryException;
+
+public interface ResetableRepository
+{
+    void discardEntireRepository()
+        throws RepositoryException;
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/package.html b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/package.html
new file mode 100644
index 0000000..e2a40ee
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/repository/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>RDF Repositories.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/AbstractSerializer.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/AbstractSerializer.java
new file mode 100644
index 0000000..bca0d6e
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/AbstractSerializer.java
@@ -0,0 +1,81 @@
+/*
+ *  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.polygene.library.rdf.serializer;
+
+import java.io.Writer;
+import org.openrdf.model.Statement;
+import org.openrdf.rio.RDFHandlerException;
+import org.openrdf.rio.RDFWriter;
+import org.openrdf.rio.RDFWriterFactory;
+import org.apache.polygene.library.rdf.PolygeneRdf;
+import org.apache.polygene.library.rdf.Rdfs;
+
+abstract class AbstractSerializer
+    implements Serializer
+{
+    private Class<? extends RDFWriterFactory> writerFactoryClass;
+
+    protected AbstractSerializer( Class<? extends RDFWriterFactory> writerFactoryClass )
+    {
+        this.writerFactoryClass = writerFactoryClass;
+    }
+
+    @Override
+    public void serialize( Iterable<Statement> graph, Writer out ) throws RDFHandlerException
+    {
+        String[] prefixes = { "polygene", "rdf", "rdfs" };
+        String[] namespaces = { PolygeneRdf.POLYGENE_MODEL, Rdfs.RDF, Rdfs.RDFS };
+        serialize( graph, out, prefixes, namespaces );
+    }
+
+    @Override
+    public void serialize( Iterable<Statement> graph, Writer out, String[] namespacePrefixes, String[] namespaces )
+        throws RDFHandlerException
+    {
+        RDFWriterFactory writerFactory;
+        try
+        {
+            writerFactory = writerFactoryClass.newInstance();
+        }
+        catch( InstantiationException e )
+        {
+            throw new InternalError();
+        }
+        catch( IllegalAccessException e )
+        {
+            throw new InternalError();
+        }
+        RDFWriter writer = writerFactory.getWriter( out );
+        writer.startRDF();
+        for( int i = 0; i < namespacePrefixes.length; i++ )
+        {
+            String namespacePrefix = namespacePrefixes[ i ];
+            String namespace = namespaces[ i ];
+            writer.handleNamespace( namespacePrefix, namespace );
+        }
+        for( Statement st : graph )
+        {
+            writer.handleStatement( st );
+        }
+        writer.endRDF();
+    }
+
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/N3Serializer.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/N3Serializer.java
new file mode 100644
index 0000000..b430cc9
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/N3Serializer.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.rdf.serializer;
+
+import org.openrdf.rio.n3.N3WriterFactory;
+
+public final class N3Serializer extends AbstractSerializer
+{
+    public N3Serializer()
+    {
+        super( N3WriterFactory.class );
+    }
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/RdfXmlSerializer.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/RdfXmlSerializer.java
new file mode 100644
index 0000000..4833439
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/RdfXmlSerializer.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.rdf.serializer;
+
+import org.openrdf.rio.rdfxml.util.RDFXMLPrettyWriterFactory;
+
+public final class RdfXmlSerializer extends AbstractSerializer
+{
+    public RdfXmlSerializer()
+    {
+        super( RDFXMLPrettyWriterFactory.class );
+    }
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/Serializer.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/Serializer.java
new file mode 100644
index 0000000..8e71466
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/Serializer.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.rdf.serializer;
+
+import java.io.Writer;
+import org.openrdf.model.Statement;
+import org.openrdf.rio.RDFHandlerException;
+
+public interface Serializer
+{
+    void serialize( Iterable<Statement> graph, Writer out )
+        throws RDFHandlerException;
+
+    void serialize( Iterable<Statement> graph, Writer out, String[] namespacePrefixes, String[] namespaces )
+        throws RDFHandlerException;
+
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/SerializerContext.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/SerializerContext.java
new file mode 100644
index 0000000..45d16fd
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/SerializerContext.java
@@ -0,0 +1,126 @@
+/*
+ *  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.polygene.library.rdf.serializer;
+
+import java.lang.reflect.Method;
+import org.openrdf.model.*;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.library.rdf.Rdfs;
+
+public final class SerializerContext
+{
+    private final Graph graph;
+    private final ValueFactory valueFactory;
+
+    public SerializerContext( Graph graph )
+    {
+        this.valueFactory = graph.getValueFactory();
+        this.graph = graph;
+    }
+
+    public Graph getGraph()
+    {
+        return graph;
+    }
+
+    public ValueFactory getValueFactory()
+    {
+        return valueFactory;
+    }
+
+    public String createServiceUri( String layer, String module, Class type, String identity )
+    {
+        String serviceType = Classes.normalizeClassToURI( type.getName() );
+        String moduleUri = createModuleUri( layer, module );
+        return moduleUri + "/" + serviceType + "/" + identity;
+    }
+
+    public String createCompositeUri( String module, Class composite )
+    {
+        String compositeName = Classes.normalizeClassToURI( composite.getName() );
+        return module + "/" + compositeName;
+    }
+
+    public String createApplicationUri( String app )
+    {
+        return "urn:polygene:model:" + app;
+    }
+
+    public String createLayerUri( String appUri, String layer )
+    {
+        return appUri + "/" + layer;
+    }
+
+    public String createModuleUri( String layerUri, String module )
+    {
+        return layerUri + "/" + module;
+    }
+
+    public void setNameAndType( String node, String name, URI type )
+    {
+        addType( node, type );
+        addName( node, name );
+    }
+
+
+    public void addName( String subject, String name )
+    {
+        Value nameValue = valueFactory.createLiteral( name );
+        URI subjectUri = valueFactory.createURI( subject );
+        graph.add( valueFactory.createStatement( subjectUri, Rdfs.LABEL, nameValue ) );
+    }
+
+    public void addType( String subject, URI type )
+    {
+        URI subjectUri = valueFactory.createURI( subject );
+        Statement statement = valueFactory.createStatement( subjectUri, Rdfs.TYPE, type );
+        graph.add( statement );
+    }
+
+    public void addStatement( String subject, URI predicate, String literal )
+    {
+        Literal object = valueFactory.createLiteral( literal );
+        URI subjectUri = valueFactory.createURI( subject );
+        Statement statement = valueFactory.createStatement( subjectUri, predicate, object );
+        graph.add( statement );
+    }
+
+    public void addRelationship( String subject, URI relationship, String object )
+    {
+        URI subjectUri = valueFactory.createURI( subject );
+        URI objectUri = valueFactory.createURI( object );
+        Statement statement = valueFactory.createStatement( subjectUri, relationship, objectUri );
+        graph.add( statement );
+    }
+
+    public void addStatement( String subject, URI predicate, boolean literal )
+    {
+        URI subjectUri = valueFactory.createURI( subject );
+        Literal object = valueFactory.createLiteral( literal );
+        Statement statement = valueFactory.createStatement( subjectUri, predicate, object );
+        graph.add( statement );
+    }
+
+    public String createCompositeMethodUri( String compositeUri, Method method )
+    {
+        return compositeUri + "/" + method.toGenericString().replace( " ", "_" );
+    }
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/TurtleSerializer.java b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/TurtleSerializer.java
new file mode 100644
index 0000000..a2717ea
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/TurtleSerializer.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.rdf.serializer;
+
+import org.openrdf.rio.turtle.TurtleWriterFactory;
+
+public final class TurtleSerializer extends AbstractSerializer
+{
+    public TurtleSerializer()
+    {
+        super( TurtleWriterFactory.class );
+    }
+}
diff --git a/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/package.html b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/package.html
new file mode 100644
index 0000000..fe83efc
--- /dev/null
+++ b/libraries/rdf/src/main/java/org/apache/polygene/library/rdf/serializer/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>RDF Serializer.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/DcRdf.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/DcRdf.java
deleted file mode 100644
index ad7bef2..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/DcRdf.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf;
-
-import org.openrdf.model.URI;
-import org.openrdf.model.impl.URIImpl;
-
-public interface DcRdf
-{
-    String NAMESPACE = "http://purl.org/dc/elements/1.1/";
-    URI ABOUT = new URIImpl( NAMESPACE + "about" );
-    URI TITLE = new URIImpl( NAMESPACE + "title" );
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/Qi4jEntity.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/Qi4jEntity.java
deleted file mode 100644
index f6d357c..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/Qi4jEntity.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf;
-
-import org.openrdf.model.URI;
-import org.openrdf.model.impl.URIImpl;
-
-
-/**
- * This is the RDF vocabulary for Zest Entity data.
- */
-public interface Qi4jEntity
-{
-    // Model
-    String NAMESPACE = "http://www.qi4j.org/rdf/entity/1.0/";
-
-    // Types
-    URI ENTITY = new URIImpl( NAMESPACE + "entity" );
-    URI ENTITYTYPEREFERENCE = new URIImpl( NAMESPACE + "entitytypereference" );
-    URI QUALIFIER = new URIImpl( NAMESPACE + "qualifier" );
-}
\ No newline at end of file
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/Qi4jEntityType.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/Qi4jEntityType.java
deleted file mode 100644
index 5a16e25..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/Qi4jEntityType.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf;
-
-import org.openrdf.model.URI;
-import org.openrdf.model.impl.URIImpl;
-
-
-/**
- * This is the RDF vocabulary for Zest EntityType data.
- */
-public interface Qi4jEntityType
-{
-    // Namespace
-    String NAMESPACE = "http://www.qi4j.org/rdf/entitytype/1.0/";
-
-    // Predicates
-    URI QUERYABLE = new URIImpl( NAMESPACE + "queryable" );
-    URI VERSION = new URIImpl( NAMESPACE + "version" );
-    URI TYPE = new URIImpl( NAMESPACE + "type" );
-}
\ No newline at end of file
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/Qi4jRdf.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/Qi4jRdf.java
deleted file mode 100644
index 98fd120..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/Qi4jRdf.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf;
-
-import org.openrdf.model.URI;
-import org.openrdf.model.impl.URIImpl;
-
-
-/**
- * This is the RDF vocabulary for Zest.
- */
-public interface Qi4jRdf
-{
-
-    // MODEL
-    // Namespace TODO: Need to figure out what these should really be!
-    String QI4JMODEL = "http://www.qi4j.org/rdf/model/1.0/";
-
-    String QI4JMODEL_TYPES = "http://www.qi4j.org/rdf/model/1.0/type#";
-    String QI4JMODEL_RELATIONSHIPS = "http://www.qi4j.org/rdf/module/1.0/";
-    String QI4JMODEL_PROPERTIES = "http://www.qi4j.org/rdf/model/1.0/property#";
-
-    // Types
-    URI TYPE_APPLICATION = new URIImpl( QI4JMODEL_TYPES + "application" );
-    URI TYPE_LAYER = new URIImpl( QI4JMODEL_TYPES + "layer" );
-    URI TYPE_MODULE = new URIImpl( QI4JMODEL_TYPES + "module" );
-    URI TYPE_ENTITY = new URIImpl( QI4JMODEL_TYPES + "entity" );
-    URI TYPE_QUALIFIER = new URIImpl( QI4JMODEL_TYPES + "qualifier" );
-    URI TYPE_COMPOSITE = new URIImpl( QI4JMODEL_TYPES + "composite" );
-    URI TYPE_SERVICE = new URIImpl( QI4JMODEL_TYPES + "service" );
-    URI TYPE_METHOD = new URIImpl( QI4JMODEL_TYPES + "method" );
-    URI TYPE_CONSTRAINT = new URIImpl( QI4JMODEL_TYPES + "constraint" );
-    URI TYPE_CONCERN = new URIImpl( QI4JMODEL_TYPES + "concern" );
-    URI TYPE_CONSTRUCTOR = new URIImpl( QI4JMODEL_TYPES + "constructor" );
-    URI TYPE_SIDEEFFECT = new URIImpl( QI4JMODEL_TYPES + "sideeffect" );
-    URI TYPE_MIXIN = new URIImpl( QI4JMODEL_TYPES + "mixin" );
-    URI TYPE_FIELD = new URIImpl( QI4JMODEL_TYPES + "field" );
-    URI TYPE_CLASS = new URIImpl( QI4JMODEL_TYPES + "class" );
-    URI TYPE_OBJECT = new URIImpl( QI4JMODEL_TYPES + "object" );
-    URI TYPE_PARAMETER = new URIImpl( QI4JMODEL_TYPES + "parameter" );
-    URI TYPE_INJECTION = new URIImpl( QI4JMODEL_TYPES + "injection" );
-    URI TYPE_INFO = new URIImpl( QI4JMODEL_TYPES + "info" );
-
-    // Properties
-    URI HAS_INJECTIONS = new URIImpl( QI4JMODEL_PROPERTIES + "hasinjections" );
-
-    // Relationship
-    URI RELATIONSHIP_COMPOSITE = new URIImpl( QI4JMODEL_RELATIONSHIPS + "composite" );
-    URI RELATIONSHIP_ENTITY = new URIImpl( QI4JMODEL_RELATIONSHIPS + "entity" );
-    URI RELATIONSHIP_SERVICE = new URIImpl( QI4JMODEL_RELATIONSHIPS + "service" );
-    URI RELATIONSHIP_OBJECT = new URIImpl( QI4JMODEL_RELATIONSHIPS + "object" );
-    URI RELATIONSHIP_PRIVATE_METHOD = new URIImpl( QI4JMODEL_RELATIONSHIPS + "private/method" );
-    URI RELATIONSHIP_INJECTION = new URIImpl( QI4JMODEL_RELATIONSHIPS + "injection" );
-    URI RELATIONSHIP_CONSTRUCTOR = new URIImpl( QI4JMODEL_RELATIONSHIPS + "constructor" );
-    URI RELATIONSHIP_FIELD = new URIImpl( QI4JMODEL_RELATIONSHIPS + "field" );
-    URI RELATIONSHIP_APPLIESTO = new URIImpl( QI4JMODEL_RELATIONSHIPS + "appliesto" );
-    URI RELATIONSHIP_METHOD = new URIImpl( QI4JMODEL_RELATIONSHIPS + "method" );
-    URI RELATIONSHIP_CONSTRAINT = new URIImpl( QI4JMODEL_RELATIONSHIPS + "constraint" );
-    URI RELATIONSHIP_CONCERN = new URIImpl( QI4JMODEL_RELATIONSHIPS + "concern" );
-    URI RELATIONSHIP_SIDEEFFECT = new URIImpl( QI4JMODEL_RELATIONSHIPS + "sideeffect" );
-    URI RELATIONSHIP_PUBLIC_SERVICE = new URIImpl( QI4JMODEL_RELATIONSHIPS + "public/service" );
-    URI RELATIONSHIP_PRIVATE_SERVICE = new URIImpl( QI4JMODEL_RELATIONSHIPS + "private/service" );
-    URI RELATIONSHIP_PROVIDEDBY = new URIImpl( QI4JMODEL_RELATIONSHIPS + "providedby" );
-    URI RELATIONSHIP_SERVICEINFO = new URIImpl( QI4JMODEL_RELATIONSHIPS + "info/service" );
-    URI RELATIONSHIP_INFOVALUE = new URIImpl( QI4JMODEL_RELATIONSHIPS + "info/value" );
-    URI RELATIONSHIP_MIXIN = new URIImpl( QI4JMODEL_RELATIONSHIPS + "mixin" );
-    URI RELATIONSHIP_LAYER = new URIImpl( QI4JMODEL_RELATIONSHIPS + "layer" );
-    URI RELATIONSHIP_MODULE = new URIImpl( QI4JMODEL_RELATIONSHIPS + "module" );
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/RdfFormat.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/RdfFormat.java
deleted file mode 100644
index a3aa83c..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/RdfFormat.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf;
-
-public enum RdfFormat
-{
-    n3, rdfxml, turtle
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/Rdfs.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/Rdfs.java
deleted file mode 100644
index c9aae67..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/Rdfs.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf;
-
-import org.openrdf.model.URI;
-import org.openrdf.model.impl.URIImpl;
-
-public interface Rdfs
-{
-    String RDFS = "http://www.w3.org/2000/01/rdf-schema#";
-    String RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
-
-    URI ID = new URIImpl( RDF + "ID" );
-
-    // Classes
-    URI RESOURCE = new URIImpl( RDF + "resource" );
-    URI LITERAL = new URIImpl( RDFS + "Literal" );
-    URI XML_LITERAL = new URIImpl( RDF + "XMLLiteral" );
-    URI CLASS = new URIImpl( RDFS + "Class" );
-    URI PROPERTY = new URIImpl( RDF + "Property" );
-    URI DATATYPE = new URIImpl( RDFS + "Datatype" );
-    URI STATEMENT = new URIImpl( RDF + "Statement" );
-    URI BAG = new URIImpl( RDF + "Bag" );
-    URI SEQ = new URIImpl( RDF + "Seq" );
-    URI ALT = new URIImpl( RDF + "Alt" );
-    URI CONTAINER = new URIImpl( RDFS + "Container" );
-    URI CONTAINER_MEMBERSHIP_PROPERTY = new URIImpl( RDFS + "ContainerMembershipProperty" );
-    URI LIST = new URIImpl( RDF + "List" );
-    URI LIST_ITEM = new URIImpl( RDF + "li" );
-
-    // Properties
-    URI TYPE = new URIImpl( RDF + "type" );
-    URI SUB_CLASS_OF = new URIImpl( RDFS + "subClassOf" );
-    URI SUB_PROPERTY_OF = new URIImpl( RDFS + "subPropertyOf" );
-    URI DOMAIN = new URIImpl( RDFS + "domain" );
-    URI RANGE = new URIImpl( RDFS + "range" );
-    URI LABEL = new URIImpl( RDFS + "label" );
-    URI COMMENT = new URIImpl( RDFS + "comment" );
-    URI MEMBER = new URIImpl( RDFS + "member" );
-    URI FIRST = new URIImpl( RDF + "first" );
-    URI REST = new URIImpl( RDF + "rest" );
-    URI SEE_ALSO = new URIImpl( RDFS + "seeAlso" );
-    URI IS_DEFINED_BY = new URIImpl( RDFS + "isDefinedBy" );
-    URI VALUE = new URIImpl( RDF + "value" );
-    URI SUBJECT = new URIImpl( RDF + "subject" );
-    URI PREDICATE = new URIImpl( RDF + "predicate" );
-    URI OBJECT = new URIImpl( RDF + "object" );
-
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/entity/EntityStateSerializer.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/entity/EntityStateSerializer.java
deleted file mode 100644
index b26fade..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/entity/EntityStateSerializer.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed  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.qi4j.library.rdf.entity;
-
-import org.openrdf.model.BNode;
-import org.openrdf.model.Graph;
-import org.openrdf.model.Literal;
-import org.openrdf.model.Resource;
-import org.openrdf.model.Statement;
-import org.openrdf.model.URI;
-import org.openrdf.model.ValueFactory;
-import org.openrdf.model.impl.GraphImpl;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.service.qualifier.Tagged;
-import org.qi4j.api.type.ValueCompositeType;
-import org.qi4j.api.type.ValueType;
-import org.qi4j.api.util.Classes;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.api.value.ValueSerializer;
-import org.qi4j.api.value.ValueSerializer.Options;
-import org.qi4j.library.rdf.Rdfs;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.ManyAssociationState;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * JAVADOC
- */
-public class EntityStateSerializer
-{
-
-    @Service
-    @Tagged( ValueSerialization.Formats.JSON )
-    private ValueSerializer valueSerializer;
-
-    public URI createEntityURI( ValueFactory valueFactory, EntityReference identity )
-    {
-        return valueFactory.createURI( identity.toURI() );
-    }
-
-    public Iterable<Statement> serialize( final EntityState entityState )
-    {
-        return serialize( entityState, true );
-    }
-
-    public Iterable<Statement> serialize( final EntityState entityState,
-                                          final boolean includeNonQueryable )
-    {
-        Graph graph = new GraphImpl();
-        serialize( entityState, includeNonQueryable, graph );
-        return graph;
-    }
-
-    public void serialize( final EntityState entityState,
-                           final boolean includeNonQueryable,
-                           final Graph graph )
-    {
-        ValueFactory values = graph.getValueFactory();
-        EntityReference identity = entityState.identity();
-        URI entityUri = createEntityURI( values, identity );
-
-        graph.add( entityUri,
-                   Rdfs.TYPE,
-                   values.createURI( Classes.toURI( first( entityState.entityDescriptor().types() ) ) ) );
-
-        serializeProperties( entityState,
-                             graph,
-                             entityUri,
-                             entityState.entityDescriptor(),
-                             includeNonQueryable );
-
-        serializeAssociations( entityState,
-                               graph,
-                               entityUri,
-                               entityState.entityDescriptor().state().associations(),
-                               includeNonQueryable );
-
-        serializeManyAssociations( entityState,
-                                   graph,
-                                   entityUri,
-                                   entityState.entityDescriptor().state().manyAssociations(),
-                                   includeNonQueryable );
-    }
-
-    private void serializeProperties( final EntityState entityState,
-                                      final Graph graph,
-                                      final Resource subject,
-                                      final EntityDescriptor entityType,
-                                      final boolean includeNonQueryable )
-    {
-        // Properties
-        for( PropertyDescriptor persistentProperty : entityType.state().properties() )
-        {
-            Object property = entityState.propertyValueOf( persistentProperty.qualifiedName() );
-            if( property != null )
-            {
-                serializeProperty( persistentProperty, property, subject, graph, includeNonQueryable );
-            }
-        }
-    }
-
-    private void serializeProperty( PropertyDescriptor persistentProperty,
-                                    Object property,
-                                    Resource subject,
-                                    Graph graph,
-                                    boolean includeNonQueryable )
-    {
-        if( !( includeNonQueryable || persistentProperty.queryable() ) )
-        {
-            return; // Skip non-queryable
-        }
-
-        ValueType valueType = persistentProperty.valueType();
-
-        final ValueFactory valueFactory = graph.getValueFactory();
-
-        String propertyURI = persistentProperty.qualifiedName().toURI();
-        URI predicate = valueFactory.createURI( propertyURI );
-        String baseURI = propertyURI.substring( 0, propertyURI.indexOf( '#' ) ) + "/";
-
-        if( valueType instanceof ValueCompositeType )
-        {
-            serializeValueComposite( subject, predicate, (ValueComposite) property, valueType,
-                                     graph, baseURI, includeNonQueryable );
-        }
-        else
-        {
-            String stringProperty = valueSerializer.serialize( new Options().withoutTypeInfo(), property );
-            final Literal object = valueFactory.createLiteral( stringProperty );
-            graph.add( subject, predicate, object );
-        }
-    }
-
-    private void serializeValueComposite( Resource subject, URI predicate,
-                                          ValueComposite value,
-                                          ValueType valueType,
-                                          Graph graph,
-                                          String baseUri,
-                                          boolean includeNonQueryable )
-    {
-        final ValueFactory valueFactory = graph.getValueFactory();
-        BNode collection = valueFactory.createBNode();
-        graph.add( subject, predicate, collection );
-
-        for( PropertyDescriptor persistentProperty : ( (ValueCompositeType) valueType ).properties() )
-        {
-            Object propertyValue = Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF
-                .map( (Composite) value )
-                .state()
-                .propertyFor( persistentProperty.accessor() )
-                .get();
-
-            if( propertyValue == null )
-            {
-                continue; // Skip null values
-            }
-
-            ValueType type = persistentProperty.valueType();
-            if( type instanceof ValueCompositeType )
-            {
-                URI pred = valueFactory.createURI( baseUri, persistentProperty.qualifiedName().name() );
-                serializeValueComposite( collection, pred, (ValueComposite) propertyValue, type, graph,
-                                         baseUri + persistentProperty.qualifiedName().name() + "/",
-                                         includeNonQueryable );
-            }
-            else
-            {
-                serializeProperty( persistentProperty, propertyValue, collection, graph, includeNonQueryable );
-            }
-        }
-    }
-
-    private void serializeAssociations( final EntityState entityState,
-                                        final Graph graph, URI entityUri,
-                                        final Iterable<? extends AssociationDescriptor> associations,
-                                        final boolean includeNonQueryable )
-    {
-        ValueFactory values = graph.getValueFactory();
-
-        // Associations
-        for( AssociationDescriptor associationType : associations )
-        {
-            if( !( includeNonQueryable || associationType.queryable() ) )
-            {
-                continue; // Skip non-queryable
-            }
-
-            EntityReference associatedId = entityState.associationValueOf( associationType.qualifiedName() );
-            if( associatedId != null )
-            {
-                URI assocURI = values.createURI( associationType.qualifiedName().toURI() );
-                URI assocEntityURI = values.createURI( associatedId.toURI() );
-                graph.add( entityUri, assocURI, assocEntityURI );
-            }
-        }
-    }
-
-    private void serializeManyAssociations( final EntityState entityState,
-                                            final Graph graph,
-                                            final URI entityUri,
-                                            final Iterable<? extends AssociationDescriptor> associations,
-                                            final boolean includeNonQueryable )
-    {
-        ValueFactory values = graph.getValueFactory();
-
-        // Many-Associations
-        for( AssociationDescriptor associationType : associations )
-        {
-            if( !( includeNonQueryable || associationType.queryable() ) )
-            {
-                continue; // Skip non-queryable
-            }
-
-            BNode collection = values.createBNode();
-            graph.add( entityUri, values.createURI( associationType.qualifiedName().toURI() ), collection );
-            graph.add( collection, Rdfs.TYPE, Rdfs.SEQ );
-
-            ManyAssociationState associatedIds = entityState.manyAssociationValueOf( associationType.qualifiedName() );
-            for( EntityReference associatedId : associatedIds )
-            {
-                URI assocEntityURI = values.createURI( associatedId.toURI() );
-                graph.add( collection, Rdfs.LIST_ITEM, assocEntityURI );
-            }
-        }
-    }
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/entity/EntityTypeSerializer.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/entity/EntityTypeSerializer.java
deleted file mode 100644
index 5f7cd97..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/entity/EntityTypeSerializer.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed  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.qi4j.library.rdf.entity;
-
-import java.math.BigDecimal;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import org.joda.time.DateTime;
-import org.joda.time.LocalDate;
-import org.joda.time.LocalDateTime;
-import org.openrdf.model.Graph;
-import org.openrdf.model.Statement;
-import org.openrdf.model.URI;
-import org.openrdf.model.ValueFactory;
-import org.openrdf.model.impl.GraphImpl;
-import org.openrdf.model.vocabulary.OWL;
-import org.openrdf.model.vocabulary.XMLSchema;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.util.Classes;
-import org.qi4j.library.rdf.Qi4jEntityType;
-import org.qi4j.library.rdf.Rdfs;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * JAVADOC
- */
-public class EntityTypeSerializer
-{
-
-    private final Map<String, URI> dataTypes = new HashMap<>( 12 );
-
-    public EntityTypeSerializer()
-    {
-        // TODO A ton more types need to be added here
-        dataTypes.put( String.class.getName(), XMLSchema.STRING );
-        dataTypes.put( Integer.class.getName(), XMLSchema.INT );
-        dataTypes.put( Boolean.class.getName(), XMLSchema.BOOLEAN );
-        dataTypes.put( Byte.class.getName(), XMLSchema.BYTE );
-        dataTypes.put( BigDecimal.class.getName(), XMLSchema.DECIMAL );
-        dataTypes.put( Double.class.getName(), XMLSchema.DOUBLE );
-        dataTypes.put( Long.class.getName(), XMLSchema.LONG );
-        dataTypes.put( Short.class.getName(), XMLSchema.SHORT );
-        dataTypes.put( Date.class.getName(), XMLSchema.DATETIME );
-        dataTypes.put( DateTime.class.getName(), XMLSchema.DATETIME );
-        dataTypes.put( LocalDateTime.class.getName(), XMLSchema.DATETIME );
-        dataTypes.put( LocalDate.class.getName(), XMLSchema.DATE );
-    }
-
-    public Iterable<Statement> serialize( final EntityDescriptor entityDescriptor )
-    {
-        Graph graph = new GraphImpl();
-        ValueFactory values = graph.getValueFactory();
-        URI entityTypeUri = values.createURI( Classes.toURI( first( entityDescriptor.types() ) ) );
-
-        graph.add( entityTypeUri, Rdfs.TYPE, Rdfs.CLASS );
-        graph.add( entityTypeUri, Rdfs.TYPE, OWL.CLASS );
-
-        graph.add( entityTypeUri, Qi4jEntityType.TYPE, values.createLiteral( first( entityDescriptor.types() ).toString() ) );
-        graph.add( entityTypeUri, Qi4jEntityType.QUERYABLE, values.createLiteral( entityDescriptor.queryable() ) );
-
-        serializeMixinTypes( entityDescriptor, graph, entityTypeUri );
-
-        serializePropertyTypes( entityDescriptor, graph, entityTypeUri );
-        serializeAssociationTypes( entityDescriptor, graph, entityTypeUri );
-        serializeManyAssociationTypes( entityDescriptor, graph, entityTypeUri );
-
-        return graph;
-    }
-
-    private void serializeMixinTypes( final EntityDescriptor entityDescriptor,
-                                      final Graph graph,
-                                      final URI entityTypeUri )
-    {
-        ValueFactory values = graph.getValueFactory();
-
-        // Mixin types
-        for( Class<?> mixinType : entityDescriptor.mixinTypes() )
-        {
-            graph.add( entityTypeUri, Rdfs.SUB_CLASS_OF, values.createURI( Classes.toURI( mixinType ) ) );
-        }
-    }
-
-    private void serializeManyAssociationTypes( final EntityDescriptor entityDescriptor,
-                                                final Graph graph,
-                                                final URI entityTypeUri )
-    {
-        ValueFactory values = graph.getValueFactory();
-        // ManyAssociations
-        for( AssociationDescriptor manyAssociationType : entityDescriptor.state().manyAssociations() )
-        {
-            URI associationURI = values.createURI( manyAssociationType.qualifiedName().toURI() );
-            graph.add( associationURI, Rdfs.DOMAIN, entityTypeUri );
-
-            graph.add( associationURI, Rdfs.TYPE, Rdfs.SEQ );
-
-            URI associatedURI = values.createURI( manyAssociationType.qualifiedName().toURI() );
-            graph.add( associationURI, Rdfs.RANGE, associatedURI );
-            graph.add( associationURI, Rdfs.RANGE, XMLSchema.ANYURI );
-        }
-    }
-
-    private void serializeAssociationTypes( final EntityDescriptor entityDescriptor,
-                                            final Graph graph,
-                                            final URI entityTypeUri )
-    {
-        ValueFactory values = graph.getValueFactory();
-        // Associations
-        for( AssociationDescriptor associationType : entityDescriptor.state().associations() )
-        {
-            URI associationURI = values.createURI( associationType.qualifiedName().toURI() );
-            graph.add( associationURI, Rdfs.DOMAIN, entityTypeUri );
-            graph.add( associationURI, Rdfs.TYPE, Rdfs.PROPERTY );
-
-            URI associatedURI = values.createURI( Classes.toURI( Classes.RAW_CLASS.map( associationType.type() ) ) );
-            graph.add( associationURI, Rdfs.RANGE, associatedURI );
-            graph.add( associationURI, Rdfs.RANGE, XMLSchema.ANYURI );
-        }
-    }
-
-    private void serializePropertyTypes( final EntityDescriptor entityDescriptor,
-                                         final Graph graph,
-                                         final URI entityTypeUri )
-    {
-        ValueFactory values = graph.getValueFactory();
-
-        // Properties
-        for( PropertyDescriptor persistentProperty : entityDescriptor.state().properties() )
-        {
-            URI propertyURI = values.createURI( persistentProperty.qualifiedName().toURI() );
-            graph.add( propertyURI, Rdfs.DOMAIN, entityTypeUri );
-            graph.add( propertyURI, Rdfs.TYPE, Rdfs.PROPERTY );
-
-            // TODO Support more types
-            URI type = dataTypes.get( persistentProperty.valueType().mainType().getName() );
-            if( type != null )
-            {
-                graph.add( propertyURI, Rdfs.RANGE, type );
-            }
-        }
-    }
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/entity/package.html b/libraries/rdf/src/main/java/org/qi4j/library/rdf/entity/package.html
deleted file mode 100644
index b638d82..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/entity/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>RDF Entity Serializer.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/model/ApplicationSerializer.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/model/ApplicationSerializer.java
deleted file mode 100644
index 39e19e1..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/model/ApplicationSerializer.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.rdf.model;
-
-import java.io.PrintWriter;
-import org.openrdf.model.Graph;
-import org.openrdf.model.impl.GraphImpl;
-import org.qi4j.api.structure.Application;
-import org.qi4j.library.rdf.serializer.RdfXmlSerializer;
-import org.qi4j.library.rdf.serializer.SerializerContext;
-
-public class ApplicationSerializer
-{
-    public Graph serialize( Application app )
-    {
-        Graph graph = new GraphImpl();
-        SerializerContext context = new SerializerContext( graph );
-        ApplicationVisitor applicationVisitor = new ApplicationVisitor( context );
-        ( (Application) app ).descriptor().accept( applicationVisitor );
-        return graph;
-    }
-
-    public void outputMetadata( Graph rdf, PrintWriter writer )
-        throws Exception
-    {
-        new RdfXmlSerializer().serialize( rdf, writer );
-    }
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/model/ApplicationVisitor.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/model/ApplicationVisitor.java
deleted file mode 100644
index be1b2c4..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/model/ApplicationVisitor.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf.model;
-
-import org.qi4j.api.composite.MethodDescriptor;
-import org.qi4j.api.composite.TransientDescriptor;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.object.ObjectDescriptor;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.api.structure.LayerDescriptor;
-import org.qi4j.api.structure.ModuleDescriptor;
-import org.qi4j.functional.HierarchicalVisitorAdapter;
-import org.qi4j.library.rdf.Qi4jRdf;
-import org.qi4j.library.rdf.serializer.SerializerContext;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * JAVADOC
- */
-class ApplicationVisitor extends HierarchicalVisitorAdapter<Object, Object, RuntimeException>
-{
-    private SerializerContext context;
-
-    private String appUri;
-
-    private String layerUri;
-
-    private String moduleUri;
-
-    private String compositeUri;
-
-    ApplicationVisitor( SerializerContext context )
-    {
-        this.context = context;
-    }
-
-    @Override
-    public boolean visitEnter( Object visited )
-        throws RuntimeException
-    {
-        if( visited instanceof ApplicationDescriptor )
-        {
-            ApplicationDescriptor applicationDescriptor = (ApplicationDescriptor) visited;
-            appUri = context.createApplicationUri( applicationDescriptor.name() );
-            context.setNameAndType( appUri, applicationDescriptor.name(), Qi4jRdf.TYPE_APPLICATION );
-        }
-
-        if( visited instanceof LayerDescriptor )
-        {
-            LayerDescriptor layerDescriptor = (LayerDescriptor) visited;
-            layerUri = context.createLayerUri( appUri, layerDescriptor.name() );
-            context.setNameAndType( layerUri, layerDescriptor.name(), Qi4jRdf.TYPE_LAYER );
-            context.addRelationship( appUri, Qi4jRdf.RELATIONSHIP_LAYER, layerUri );
-        }
-
-        if( visited instanceof ModuleDescriptor )
-        {
-            ModuleDescriptor moduleDescriptor = (ModuleDescriptor) visited;
-            moduleUri = context.createModuleUri( layerUri, moduleDescriptor.name() );
-            context.setNameAndType( layerUri, moduleDescriptor.name(), Qi4jRdf.TYPE_MODULE );
-
-            context.addRelationship( layerUri, Qi4jRdf.RELATIONSHIP_MODULE, moduleUri );
-        }
-
-        if( visited instanceof TransientDescriptor )
-        {
-            TransientDescriptor transientDescriptor = (TransientDescriptor) visited;
-            compositeUri = context.createCompositeUri( moduleUri, first( transientDescriptor.types() ) );
-            context.addType( compositeUri, Qi4jRdf.TYPE_COMPOSITE );
-            context.addRelationship( moduleUri, Qi4jRdf.RELATIONSHIP_COMPOSITE, compositeUri );
-        }
-
-        if( visited instanceof EntityDescriptor )
-        {
-            EntityDescriptor entityDescriptor = (EntityDescriptor) visited;
-            compositeUri = context.createCompositeUri( moduleUri, first( entityDescriptor.types() ) );
-            context.addType( compositeUri, Qi4jRdf.TYPE_ENTITY );
-            context.addRelationship( moduleUri, Qi4jRdf.RELATIONSHIP_ENTITY, compositeUri );
-        }
-
-        if( visited instanceof ObjectDescriptor )
-        {
-            ObjectDescriptor objectDescriptor = (ObjectDescriptor) visited;
-            compositeUri = context.createCompositeUri( moduleUri, first( objectDescriptor.types() ) );
-            context.addType( compositeUri, Qi4jRdf.TYPE_OBJECT );
-            context.addRelationship( moduleUri, Qi4jRdf.RELATIONSHIP_OBJECT, compositeUri );
-        }
-
-        if( visited instanceof MethodDescriptor )
-        {
-            MethodDescriptor compositeMethodDescriptor = (MethodDescriptor) visited;
-            String compositeMethodUri = context.createCompositeMethodUri( compositeUri, compositeMethodDescriptor.method() );
-            context.addType( compositeMethodUri, Qi4jRdf.TYPE_METHOD );
-            context.addRelationship( compositeUri, Qi4jRdf.RELATIONSHIP_METHOD, compositeMethodUri );
-        }
-
-        return true;
-    }
-}
\ No newline at end of file
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/model/Model2XML.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/model/Model2XML.java
deleted file mode 100644
index ae83204..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/model/Model2XML.java
+++ /dev/null
@@ -1,217 +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.qi4j.library.rdf.model;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Stack;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import org.qi4j.api.composite.DependencyDescriptor;
-import org.qi4j.api.composite.MethodDescriptor;
-import org.qi4j.api.composite.TransientDescriptor;
-import org.qi4j.api.mixin.MixinDescriptor;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.api.structure.LayerDescriptor;
-import org.qi4j.api.structure.ModuleDescriptor;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.w3c.dom.Attr;
-import org.w3c.dom.DOMException;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * TODO
- */
-public class Model2XML
-    implements Function<ApplicationDescriptor, Document>
-{
-    private static Map<String, String> simpleMappings = new HashMap<String, String>();
-
-    static
-    {
-        simpleMappings.put( "TransientsModel", "transients" );
-        simpleMappings.put( "EntitiesModel", "entities" );
-        simpleMappings.put( "ServicesModel", "services" );
-        simpleMappings.put( "ImportedServicesModel", "importedservices" );
-        simpleMappings.put( "ObjectsModel", "objects" );
-        simpleMappings.put( "ValuesModel", "values" );
-        simpleMappings.put( "MixinsModel", "mixins" );
-        simpleMappings.put( "CompositeMethodsModel", "methods" );
-        simpleMappings.put( "InjectedFieldsModel", "injectedfields" );
-        simpleMappings.put( "InjectedFieldModel", "injectedfield" );
-    }
-
-    @Override
-    public Document map( ApplicationDescriptor Application )
-    {
-        try
-        {
-            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
-            final Document document = builder.newDocument();
-
-            final Stack<Node> current = new Stack<Node>();
-            current.push( document );
-
-            Application.accept( new HierarchicalVisitor<Object, Object, DOMException>()
-            {
-                @Override
-                public boolean visitEnter( Object visited )
-                    throws DOMException
-                {
-                    String mapping = simpleMappings.get( visited.getClass().getSimpleName() );
-                    if( mapping != null )
-                    {
-                        Node node = document.createElement( "mapping" );
-                        current.push( node );
-                    }
-                    else if( visited instanceof ApplicationDescriptor )
-                    {
-                        ApplicationDescriptor applicationDescriptor = (ApplicationDescriptor) visited;
-                        Node application = document.createElement( "application" );
-
-                        addAttribute( "name", applicationDescriptor.name(), application );
-
-                        current.push( application );
-                    }
-                    else if( visited instanceof LayerDescriptor )
-                    {
-                        LayerDescriptor layerDescriptor = (LayerDescriptor) visited;
-                        Node layer = document.createElement( "layer" );
-
-                        addAttribute( "name", layerDescriptor.name(), layer );
-
-                        current.push( layer );
-                    }
-                    else if( visited instanceof ModuleDescriptor )
-                    {
-                        ModuleDescriptor moduleDescriptor = (ModuleDescriptor) visited;
-                        Node module = document.createElement( "module" );
-
-                        addAttribute( "name", moduleDescriptor.name(), module );
-
-                        current.push( module );
-                    }
-                    else if( visited instanceof TransientDescriptor )
-                    {
-                        TransientDescriptor descriptor = (TransientDescriptor) visited;
-                        Node node = document.createElement( "transient" );
-
-                        addAttribute( "type", first(descriptor.types()).getName(), node );
-                        addAttribute( "visibility", descriptor.visibility().name(), node );
-
-                        current.push( node );
-                    }
-                    else if( visited instanceof MethodDescriptor )
-                    {
-                        MethodDescriptor descriptor = (MethodDescriptor) visited;
-                        Node node = document.createElement( "method" );
-
-                        addAttribute( "name", descriptor.method().getName(), node );
-
-                        current.push( node );
-                    }
-                    else if( visited instanceof MixinDescriptor )
-                    {
-                        MixinDescriptor descriptor = (MixinDescriptor) visited;
-                        Node node = document.createElement( "mixin" );
-
-                        addAttribute( "class", descriptor.mixinClass().getName(), node );
-
-                        current.push( node );
-                    }
-                    else if( visited instanceof DependencyDescriptor )
-                    {
-                        DependencyDescriptor descriptor = (DependencyDescriptor) visited;
-                        Node node = document.createElement( "dependency" );
-
-                        addAttribute( "annotation", descriptor.injectionAnnotation().toString(), node );
-                        addAttribute( "injection", descriptor.injectionType().toString(), node );
-                        addAttribute( "optional", Boolean.toString( descriptor.optional() ), node );
-
-                        current.push( node );
-                    }
-                    else
-                    {
-                        Element element = document.createElement( visited.getClass().getSimpleName() );
-                        current.push( element );
-                    }
-
-                    return true;
-                }
-
-                @Override
-                public boolean visitLeave( Object visited )
-                    throws DOMException
-                {
-                    Node node = current.pop();
-
-                    if( node.getChildNodes().getLength() == 0 && node.getAttributes().getLength() == 0 )
-                    {
-                        return true;
-                    }
-
-                    current.peek().appendChild( node );
-                    return true;
-                }
-
-                @Override
-                public boolean visit( Object visited )
-                    throws DOMException
-                {
-                    Element element;
-                    if( visited instanceof DependencyDescriptor )
-                    {
-                        DependencyDescriptor descriptor = (DependencyDescriptor) visited;
-                        element = document.createElement( "dependency" );
-
-                        addAttribute( "annotation", descriptor.injectionAnnotation().toString(), element );
-                        addAttribute( "injection", descriptor.injectionType().toString(), element );
-                        addAttribute( "optional", Boolean.toString( descriptor.optional() ), element );
-                    }
-                    else
-                    {
-                        element = document.createElement( visited.getClass().getSimpleName() );
-                    }
-
-                    current.peek().appendChild( element );
-
-                    return true;
-                }
-
-                private void addAttribute( String name, String value, Node node )
-                {
-                    Attr attr = document.createAttribute( name );
-                    attr.setValue( value );
-                    ( (Element) node ).setAttributeNode( attr );
-                }
-            } );
-
-            return document;
-        }
-        catch( Exception exception )
-        {
-            throw new IllegalArgumentException( exception );
-        }
-    }
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/model/package.html b/libraries/rdf/src/main/java/org/qi4j/library/rdf/model/package.html
deleted file mode 100644
index 0f17f94..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/model/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>RDF Application Model Serializer.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/package.html b/libraries/rdf/src/main/java/org/qi4j/library/rdf/package.html
deleted file mode 100644
index 9b22669..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>RDF Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/HttpRepositoryConfiguration.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/HttpRepositoryConfiguration.java
deleted file mode 100644
index b8be2d9..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/HttpRepositoryConfiguration.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf.repository;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-/**
- * JAVADOC Add JavaDoc
- */
-public interface HttpRepositoryConfiguration
-    extends ConfigurationComposite
-{
-    /**
-     * The URL of the remote Sesame HTTP Repository.
-     *
-     * Default: http://localhost:8183/
-     *
-     * @return The configured URL for the remote Sesame HTTP Repository.
-     */
-    @Optional
-    Property<String> repositoryUrl();
-
-    /**
-     * The ID of the Repository at the remote Sesame HTTP host.
-     *
-     * Default: qi4j
-     *
-     * @return The configured ID at the remote Sesame HTTP host.
-     */
-    @Optional
-    Property<String> repositoryId();
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/HttpRepositoryService.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/HttpRepositoryService.java
deleted file mode 100644
index a208be9..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/HttpRepositoryService.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf.repository;
-
-import org.openrdf.repository.Repository;
-import org.openrdf.repository.RepositoryException;
-import org.openrdf.repository.http.HTTPRepository;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-
-@Mixins( HttpRepositoryService.HttpRepositoryMixin.class )
-@Activators( HttpRepositoryService.Activator.class )
-public interface HttpRepositoryService
-    extends Repository, ServiceComposite
-{
-    @Override
-    void initialize()
-            throws RepositoryException;
-
-    @Override
-    void shutDown()
-            throws RepositoryException;
-
-    public static class Activator
-            extends ActivatorAdapter<ServiceReference<HttpRepositoryService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<HttpRepositoryService> activated )
-                throws Exception
-        {
-            activated.get().initialize();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<HttpRepositoryService> passivating )
-                throws Exception
-        {
-            passivating.get().shutDown();
-        }
-
-    }
-
-    public static class HttpRepositoryMixin
-        extends HTTPRepository
-        implements Repository
-    {
-        public HttpRepositoryMixin( @This Configuration<HttpRepositoryConfiguration> configuration )
-        {
-            super( getRepositoryUrl( configuration.get() ), getRepositoryId( configuration.get() ) );
-        }
-
-        private static String getRepositoryUrl( HttpRepositoryConfiguration configuration )
-        {
-            Property<String> repositoryUrl = configuration.repositoryUrl();
-            String url = repositoryUrl.get();
-            if( url == null )
-            {
-                url = "http://localhost:8183/";
-                repositoryUrl.set( url );
-            }
-            return url;
-        }
-
-        private static String getRepositoryId( HttpRepositoryConfiguration configuration )
-        {
-            Property<String> id = configuration.repositoryId();
-            if( id.get() == null )
-            {
-                id.set( "qi4j" );
-            }
-            return id.get();
-        }
-    }
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/MemoryRepositoryService.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/MemoryRepositoryService.java
deleted file mode 100644
index 77417be..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/MemoryRepositoryService.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf.repository;
-
-import java.io.File;
-import org.openrdf.model.ValueFactory;
-import org.openrdf.repository.Repository;
-import org.openrdf.repository.RepositoryConnection;
-import org.openrdf.repository.RepositoryException;
-import org.openrdf.repository.sail.SailRepository;
-import org.openrdf.sail.memory.MemoryStore;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-
-@Mixins( MemoryRepositoryService.MemoryRepositoryMixin.class )
-@Activators( MemoryRepositoryService.Activator.class )
-public interface MemoryRepositoryService
-    extends Repository, ServiceComposite
-{
-
-    @Override
-    void initialize()
-        throws RepositoryException;
-
-    @Override
-    void shutDown()
-        throws RepositoryException;
-
-    public static class Activator
-        extends ActivatorAdapter<ServiceReference<MemoryRepositoryService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<MemoryRepositoryService> activated )
-            throws Exception
-        {
-            activated.get().initialize();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<MemoryRepositoryService> passivating )
-            throws Exception
-        {
-            passivating.get().shutDown();
-        }
-    }
-
-    public static abstract class MemoryRepositoryMixin
-        implements MemoryRepositoryService, ResetableRepository
-    {
-
-        SailRepository repo;
-
-        public MemoryRepositoryMixin()
-        {
-            repo = new SailRepository( new MemoryStore() );
-        }
-
-        @Override
-        public void initialize()
-            throws RepositoryException
-        {
-            repo.initialize();
-        }
-
-        @Override
-        public boolean isInitialized()
-        {
-            return repo.isInitialized();
-        }
-
-        @Override
-        public void shutDown()
-            throws RepositoryException
-        {
-            repo.shutDown();
-        }
-
-        @Override
-        public void setDataDir( File dataDir )
-        {
-            repo.setDataDir( dataDir );
-        }
-
-        @Override
-        public File getDataDir()
-        {
-            return repo.getDataDir();
-        }
-
-        @Override
-        public boolean isWritable()
-            throws RepositoryException
-        {
-            return repo.isWritable();
-        }
-
-        @Override
-        public RepositoryConnection getConnection()
-            throws RepositoryException
-        {
-            return repo.getConnection();
-        }
-
-        @Override
-        public ValueFactory getValueFactory()
-        {
-            return repo.getValueFactory();
-        }
-
-        @Override
-        public void discardEntireRepository()
-            throws RepositoryException
-        {
-            repo = new SailRepository( new MemoryStore() );
-        }
-    }
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/NativeConfiguration.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/NativeConfiguration.java
deleted file mode 100644
index 368f4bd..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/NativeConfiguration.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf.repository;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.api.property.Property;
-import org.qi4j.library.constraints.annotation.Matches;
-
-/**
- * JAVADOC Add JavaDoc
- */
-@Queryable( false )
-// START SNIPPET: config
-public interface NativeConfiguration extends ConfigurationComposite
-{
-    @Optional @Matches( "([spoc][spoc][spoc][spoc],?)*" ) Property<String> tripleIndexes();
-
-    @Optional Property<String> dataDirectory();
-
-    @UseDefaults Property<Boolean> forceSync();
-}
-// END SNIPPET: config
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/NativeRepositoryService.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/NativeRepositoryService.java
deleted file mode 100644
index 94e6486..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/NativeRepositoryService.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf.repository;
-
-import java.io.File;
-import org.openrdf.model.ValueFactory;
-import org.openrdf.repository.Repository;
-import org.openrdf.repository.RepositoryConnection;
-import org.openrdf.repository.RepositoryException;
-import org.openrdf.repository.sail.SailRepository;
-import org.openrdf.sail.nativerdf.NativeStore;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.Availability;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.library.fileconfig.FileConfiguration;
-
-@Mixins( { NativeRepositoryService.NativeRepositoryMixin.class } )
-@Activators( NativeRepositoryService.Activator.class )
-public interface NativeRepositoryService extends Repository, ServiceComposite, Availability
-{
-    @Override
-    void initialize()
-        throws RepositoryException;
-
-    @Override
-    void shutDown()
-        throws RepositoryException;
-
-    public static class Activator
-        extends ActivatorAdapter<ServiceReference<NativeRepositoryService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<NativeRepositoryService> activated )
-            throws Exception
-        {
-            activated.get().initialize();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<NativeRepositoryService> passivating )
-            throws Exception
-        {
-            passivating.get().shutDown();
-        }
-    }
-
-    public static abstract class NativeRepositoryMixin
-        implements NativeRepositoryService, ResetableRepository
-    {
-        @Optional
-        @Service
-        FileConfiguration fileConfiguration;
-
-        @This
-        private Configuration<NativeConfiguration> configuration;
-
-        private SailRepository repo;
-        private boolean isNotInitialized;
-
-        public NativeRepositoryMixin()
-        {
-            isNotInitialized = true;
-            repo = new SailRepository( new NativeStore() );
-        }
-
-        @Override
-        public void setDataDir( File dataDir )
-        {
-            repo.setDataDir( dataDir );
-        }
-
-        @Override
-        public File getDataDir()
-        {
-            return repo.getDataDir();
-        }
-
-        @Override
-        public void initialize()
-            throws RepositoryException
-        {
-            String dataDir = configuration.get().dataDirectory().get();
-            File dataDirectory;
-            if( dataDir == null || "".equals( dataDir ) )
-            {
-                String serviceIdentity = configuration.get().identity().get();
-                if( fileConfiguration != null )
-                {
-                    dataDir = new File( fileConfiguration.dataDirectory(), serviceIdentity ).getAbsolutePath();
-                }
-                else
-                {
-                    if( serviceIdentity == null || "".equals( serviceIdentity ) )
-                    {
-                        dataDir = "./rdf/repositories/qi4j";
-                    }
-                    else
-                    {
-                        dataDir = "./rdf/repositories/" + serviceIdentity;
-                    }
-                }
-                configuration.get().dataDirectory().set( dataDir );
-                configuration.save();
-                dataDirectory = new File( dataDir );
-            }
-            else
-            {
-                dataDirectory = new File( dataDir ).getAbsoluteFile();
-            }
-            initializeRepository( dataDirectory );
-        }
-
-        @Override
-        public boolean isInitialized()
-        {
-            return !isNotInitialized;
-        }
-
-        @Override
-        public void shutDown()
-            throws RepositoryException
-        {
-            repo.shutDown();
-        }
-
-        @Override
-        public boolean isWritable()
-            throws RepositoryException
-        {
-            return repo.isWritable();
-        }
-
-        @Override
-        public RepositoryConnection getConnection()
-            throws RepositoryException
-        {
-            if( isNotInitialized )
-            {
-                return null;
-            }
-            return repo.getConnection();
-        }
-
-        @Override
-        public ValueFactory getValueFactory()
-        {
-            return repo.getValueFactory();
-        }
-
-        @Override
-        public void discardEntireRepository()
-            throws RepositoryException
-        {
-            File dataDir = repo.getDataDir();
-            repo.shutDown();
-            delete( dataDir );
-            initializeRepository( dataDir );
-        }
-
-        private void delete( File dataDir )
-        {
-            File[] children = dataDir.listFiles();
-            for( File child : children )
-            {
-                if( child.isDirectory() )
-                {
-                    delete( child );
-                }
-                else
-                {
-                    //noinspection ResultOfMethodCallIgnored
-                    child.delete();
-                }
-            }
-        }
-
-        private void initializeRepository( File dataDir )
-            throws RepositoryException
-        {
-            String tripleIndexes = configuration.get().tripleIndexes().get();
-            if( tripleIndexes == null )
-            {
-                tripleIndexes = "";
-                configuration.get().tripleIndexes().set( tripleIndexes );
-            }
-            boolean forceSync = configuration.get().forceSync().get();
-
-            NativeStore store = (NativeStore) repo.getSail();
-            store.setDataDir( dataDir );
-            store.setTripleIndexes( tripleIndexes );
-            store.setForceSync( forceSync );
-            repo.initialize();
-            isNotInitialized = false;
-        }
-
-        @Override
-        public boolean isAvailable()
-        {
-            return !isNotInitialized;
-        }
-    }
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/RdbmsRepositoryConfiguration.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/RdbmsRepositoryConfiguration.java
deleted file mode 100644
index 8206056..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/RdbmsRepositoryConfiguration.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.rdf.repository;
-
-import org.qi4j.api.property.Property;
-
-// START SNIPPET: config
-public interface RdbmsRepositoryConfiguration
-{
-    Property<String> jdbcDriver();
-    Property<String> jdbcUrl();
-    Property<String> user();
-    Property<String> password();
-}
-// END SNIPPET: config
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/RdbmsRepositoryService.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/RdbmsRepositoryService.java
deleted file mode 100644
index b2485ad..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/RdbmsRepositoryService.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.rdf.repository;
-
-import java.io.File;
-import org.openrdf.model.ValueFactory;
-import org.openrdf.repository.Repository;
-import org.openrdf.repository.RepositoryConnection;
-import org.openrdf.repository.RepositoryException;
-import org.openrdf.repository.sail.SailRepository;
-import org.openrdf.sail.rdbms.RdbmsStore;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-
-@Mixins( RdbmsRepositoryService.RdbmsRepositoryMixin.class )
-@Activators( RdbmsRepositoryService.Activator.class )
-public interface RdbmsRepositoryService extends Repository, ServiceComposite
-{
-
-    @Override
-    public void initialize()
-            throws RepositoryException;
-
-    @Override
-    public void shutDown()
-            throws RepositoryException;
-
-    public static class Activator
-            extends ActivatorAdapter<ServiceReference<RdbmsRepositoryService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<RdbmsRepositoryService> activated )
-                throws Exception
-        {
-            activated.get().initialize();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<RdbmsRepositoryService> passivating )
-                throws Exception
-        {
-            passivating.get().shutDown();
-        }
-
-    }
-
-    public static abstract class RdbmsRepositoryMixin
-        implements RdbmsRepositoryService
-    {
-        @This
-        private Configuration<RdbmsRepositoryConfiguration> configuration;
-
-        private SailRepository repo;
-
-        @Override
-        public void setDataDir( File file )
-        {
-            repo.setDataDir( file );
-        }
-
-        @Override
-        public File getDataDir()
-        {
-            return repo.getDataDir();
-        }
-
-        @Override
-        public void initialize()
-            throws RepositoryException
-        {
-            RdbmsRepositoryConfiguration conf = configuration.get();
-            String jdbcDriver = conf.jdbcDriver().get();
-            String jdbcUrl = conf.jdbcUrl().get();
-            String user = conf.user().get();
-            String password = conf.password().get();
-            repo = new SailRepository( new RdbmsStore( jdbcDriver, jdbcUrl, user, password ) );
-            repo.initialize();
-        }
-
-        @Override
-        public boolean isInitialized()
-        {
-            return repo.isInitialized();
-        }
-        
-        @Override
-        public void shutDown()
-            throws RepositoryException
-        {
-            repo.shutDown();
-        }
-
-        @Override
-        public boolean isWritable()
-            throws RepositoryException
-        {
-            return repo.isWritable();
-        }
-
-        @Override
-        public RepositoryConnection getConnection()
-            throws RepositoryException
-        {
-            return repo.getConnection();
-        }
-
-        @Override
-        public ValueFactory getValueFactory()
-        {
-            return repo.getValueFactory();
-        }
-    }
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/ResetableRepository.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/ResetableRepository.java
deleted file mode 100644
index 18d975b..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/ResetableRepository.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.rdf.repository;
-
-import org.openrdf.repository.RepositoryException;
-
-public interface ResetableRepository
-{
-    void discardEntireRepository()
-        throws RepositoryException;
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/package.html b/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/package.html
deleted file mode 100644
index 129d9a7..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/repository/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>RDF Repositories.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/AbstractSerializer.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/AbstractSerializer.java
deleted file mode 100644
index a2adb58..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/AbstractSerializer.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.rdf.serializer;
-
-import java.io.Writer;
-import org.openrdf.model.Statement;
-import org.openrdf.rio.RDFHandlerException;
-import org.openrdf.rio.RDFWriter;
-import org.openrdf.rio.RDFWriterFactory;
-import org.qi4j.library.rdf.Qi4jRdf;
-import org.qi4j.library.rdf.Rdfs;
-
-abstract class AbstractSerializer
-    implements Serializer
-{
-    private Class<? extends RDFWriterFactory> writerFactoryClass;
-
-    protected AbstractSerializer( Class<? extends RDFWriterFactory> writerFactoryClass )
-    {
-        this.writerFactoryClass = writerFactoryClass;
-    }
-
-    @Override
-    public void serialize( Iterable<Statement> graph, Writer out ) throws RDFHandlerException
-    {
-        String[] prefixes = { "qi4j", "rdf", "rdfs" };
-        String[] namespaces = { Qi4jRdf.QI4JMODEL, Rdfs.RDF, Rdfs.RDFS };
-        serialize( graph, out, prefixes, namespaces );
-    }
-
-    @Override
-    public void serialize( Iterable<Statement> graph, Writer out, String[] namespacePrefixes, String[] namespaces )
-        throws RDFHandlerException
-    {
-        RDFWriterFactory writerFactory;
-        try
-        {
-            writerFactory = writerFactoryClass.newInstance();
-        }
-        catch( InstantiationException e )
-        {
-            throw new InternalError();
-        }
-        catch( IllegalAccessException e )
-        {
-            throw new InternalError();
-        }
-        RDFWriter writer = writerFactory.getWriter( out );
-        writer.startRDF();
-        for( int i = 0; i < namespacePrefixes.length; i++ )
-        {
-            String namespacePrefix = namespacePrefixes[ i ];
-            String namespace = namespaces[ i ];
-            writer.handleNamespace( namespacePrefix, namespace );
-        }
-        for( Statement st : graph )
-        {
-            writer.handleStatement( st );
-        }
-        writer.endRDF();
-    }
-
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/N3Serializer.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/N3Serializer.java
deleted file mode 100644
index 4f4c449..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/N3Serializer.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.rdf.serializer;
-
-import org.openrdf.rio.n3.N3WriterFactory;
-
-public final class N3Serializer extends AbstractSerializer
-{
-    public N3Serializer()
-    {
-        super( N3WriterFactory.class );
-    }
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/RdfXmlSerializer.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/RdfXmlSerializer.java
deleted file mode 100644
index 45a0510..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/RdfXmlSerializer.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.rdf.serializer;
-
-import org.openrdf.rio.rdfxml.util.RDFXMLPrettyWriterFactory;
-
-public final class RdfXmlSerializer extends AbstractSerializer
-{
-    public RdfXmlSerializer()
-    {
-        super( RDFXMLPrettyWriterFactory.class );
-    }
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/Serializer.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/Serializer.java
deleted file mode 100644
index 8e2fc15..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/Serializer.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf.serializer;
-
-import java.io.Writer;
-import org.openrdf.model.Statement;
-import org.openrdf.rio.RDFHandlerException;
-
-public interface Serializer
-{
-    void serialize( Iterable<Statement> graph, Writer out )
-        throws RDFHandlerException;
-
-    void serialize( Iterable<Statement> graph, Writer out, String[] namespacePrefixes, String[] namespaces )
-        throws RDFHandlerException;
-
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/SerializerContext.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/SerializerContext.java
deleted file mode 100644
index 9900a2b..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/SerializerContext.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.rdf.serializer;
-
-import java.lang.reflect.Method;
-import org.openrdf.model.*;
-import org.qi4j.api.util.Classes;
-import org.qi4j.library.rdf.Rdfs;
-
-public final class SerializerContext
-{
-    private final Graph graph;
-    private final ValueFactory valueFactory;
-
-    public SerializerContext( Graph graph )
-    {
-        this.valueFactory = graph.getValueFactory();
-        this.graph = graph;
-    }
-
-    public Graph getGraph()
-    {
-        return graph;
-    }
-
-    public ValueFactory getValueFactory()
-    {
-        return valueFactory;
-    }
-
-    public String createServiceUri( String layer, String module, Class type, String identity )
-    {
-        String serviceType = Classes.normalizeClassToURI( type.getName() );
-        String moduleUri = createModuleUri( layer, module );
-        return moduleUri + "/" + serviceType + "/" + identity;
-    }
-
-    public String createCompositeUri( String module, Class composite )
-    {
-        String compositeName = Classes.normalizeClassToURI( composite.getName() );
-        return module + "/" + compositeName;
-    }
-
-    public String createApplicationUri( String app )
-    {
-        return "urn:qi4j:model:" + app;
-    }
-
-    public String createLayerUri( String appUri, String layer )
-    {
-        return appUri + "/" + layer;
-    }
-
-    public String createModuleUri( String layerUri, String module )
-    {
-        return layerUri + "/" + module;
-    }
-
-    public void setNameAndType( String node, String name, URI type )
-    {
-        addType( node, type );
-        addName( node, name );
-    }
-
-
-    public void addName( String subject, String name )
-    {
-        Value nameValue = valueFactory.createLiteral( name );
-        URI subjectUri = valueFactory.createURI( subject );
-        graph.add( valueFactory.createStatement( subjectUri, Rdfs.LABEL, nameValue ) );
-    }
-
-    public void addType( String subject, URI type )
-    {
-        URI subjectUri = valueFactory.createURI( subject );
-        Statement statement = valueFactory.createStatement( subjectUri, Rdfs.TYPE, type );
-        graph.add( statement );
-    }
-
-    public void addStatement( String subject, URI predicate, String literal )
-    {
-        Literal object = valueFactory.createLiteral( literal );
-        URI subjectUri = valueFactory.createURI( subject );
-        Statement statement = valueFactory.createStatement( subjectUri, predicate, object );
-        graph.add( statement );
-    }
-
-    public void addRelationship( String subject, URI relationship, String object )
-    {
-        URI subjectUri = valueFactory.createURI( subject );
-        URI objectUri = valueFactory.createURI( object );
-        Statement statement = valueFactory.createStatement( subjectUri, relationship, objectUri );
-        graph.add( statement );
-    }
-
-    public void addStatement( String subject, URI predicate, boolean literal )
-    {
-        URI subjectUri = valueFactory.createURI( subject );
-        Literal object = valueFactory.createLiteral( literal );
-        Statement statement = valueFactory.createStatement( subjectUri, predicate, object );
-        graph.add( statement );
-    }
-
-    public String createCompositeMethodUri( String compositeUri, Method method )
-    {
-        return compositeUri + "/" + method.toGenericString().replace( " ", "_" );
-    }
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/TurtleSerializer.java b/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/TurtleSerializer.java
deleted file mode 100644
index 8fc22eb..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/TurtleSerializer.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.rdf.serializer;
-
-import org.openrdf.rio.turtle.TurtleWriterFactory;
-
-public final class TurtleSerializer extends AbstractSerializer
-{
-    public TurtleSerializer()
-    {
-        super( TurtleWriterFactory.class );
-    }
-}
diff --git a/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/package.html b/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/package.html
deleted file mode 100644
index d1fbf42..0000000
--- a/libraries/rdf/src/main/java/org/qi4j/library/rdf/serializer/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>RDF Serializer.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/ApplicationXmlTest.java b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/ApplicationXmlTest.java
new file mode 100644
index 0000000..e953c9b
--- /dev/null
+++ b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/ApplicationXmlTest.java
@@ -0,0 +1,157 @@
+/*
+ *  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.polygene.library.rdf;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.sideeffect.SideEffectOf;
+import org.apache.polygene.api.sideeffect.SideEffects;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.rdf.model.ApplicationSerializer;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.openrdf.model.Statement;
+import org.openrdf.rio.RDFHandlerException;
+import org.openrdf.rio.RDFWriter;
+import org.openrdf.rio.RDFWriterFactory;
+import org.openrdf.rio.n3.N3WriterFactory;
+import org.openrdf.rio.rdfxml.RDFXMLWriterFactory;
+
+/**
+ * JAVADOC
+ */
+public class ApplicationXmlTest extends AbstractPolygeneTest
+{
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        LayerAssembly layerAssembly = module.layer();
+        layerAssembly.application().setName( "testapp" );
+        module.transients( TestComposite.class );
+    }
+
+    @Test
+    public void testApplicationXml()
+        throws Exception
+    {
+        ApplicationSerializer parser = new ApplicationSerializer();
+        Iterable<Statement> graph = parser.serialize( application ); // TODO Fix this
+        writeN3( graph );
+        writeXml( graph );
+    }
+
+    private void writeN3( Iterable<Statement> graph )
+        throws RDFHandlerException, IOException
+    {
+        RDFWriterFactory writerFactory = new N3WriterFactory();
+        RDFWriter writer = writerFactory.getWriter( System.out );
+        writeOutput( writer, graph );
+    }
+
+    private void writeXml( Iterable<Statement> graph )
+        throws RDFHandlerException, IOException
+    {
+        RDFWriterFactory writerFactory = new RDFXMLWriterFactory();
+        RDFWriter writer = writerFactory.getWriter( System.out );
+        writeOutput( writer, graph );
+    }
+
+    private void writeOutput( RDFWriter writer, Iterable<Statement> graph )
+        throws RDFHandlerException
+    {
+        writer.startRDF();
+        writer.handleNamespace( "polygene", PolygeneRdf.POLYGENE_MODEL );
+        writer.handleNamespace( "rdf", Rdfs.RDF );
+        writer.handleNamespace( "rdfs", Rdfs.RDFS );
+        for( Statement st : graph )
+        {
+            writer.handleStatement( st );
+        }
+        writer.endRDF();
+    }
+
+    @Mixins( AMixin.class )
+    public interface A
+    {
+        String doStuff();
+    }
+
+    public static class AMixin
+        implements A
+    {
+        @This B bRef;
+
+        public String doStuff()
+        {
+            return bRef.otherStuff() + "123";
+        }
+    }
+
+    public interface B
+    {
+        String otherStuff();
+    }
+
+    public static class BMixin
+        implements B
+    {
+        public String otherStuff()
+        {
+            return "XYZ";
+        }
+    }
+
+    public static class OtherStuffConcern extends ConcernOf<B>
+        implements B
+    {
+        public String otherStuff()
+        {
+            return next.otherStuff() + "!";
+        }
+    }
+
+    public static class LogSideEffect extends SideEffectOf<InvocationHandler>
+        implements InvocationHandler
+    {
+        public Object invoke( Object object, Method method, Object[] objects ) throws Throwable
+        {
+            System.out.println( "Called " + method.getName() );
+            return null;
+        }
+    }
+
+    @SideEffects( LogSideEffect.class )
+    @Concerns( OtherStuffConcern.class )
+    @Mixins( { BMixin.class } )
+    public interface TestComposite
+        extends A, TransientComposite
+    {
+    }
+}
diff --git a/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/Model2XMLTest.java b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/Model2XMLTest.java
new file mode 100644
index 0000000..4b5b542
--- /dev/null
+++ b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/Model2XMLTest.java
@@ -0,0 +1,83 @@
+/*
+ *  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.polygene.library.rdf;
+
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.bootstrap.*;
+import org.apache.polygene.library.rdf.model.Model2XML;
+import org.w3c.dom.Document;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+/**
+ * TODO
+ */
+public class Model2XMLTest
+{
+    @Test
+    public void testModel2XML() throws AssemblyException, TransformerException
+    {
+        Energy4Java is = new Energy4Java(  );
+        ApplicationDescriptor model = is.newApplicationModel( new ApplicationAssembler()
+        {
+            @Override
+            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory ) throws AssemblyException
+            {
+                ApplicationAssembly assembly = applicationFactory.newApplicationAssembly();
+
+                assembly.setName( "Test application" );
+
+                LayerAssembly webLayer = assembly.layer( "Web" );
+                LayerAssembly domainLayer = assembly.layer( "Domain" );
+                LayerAssembly infrastructureLayer = assembly.layer( "Infrastructure" );
+
+                webLayer.uses( domainLayer, infrastructureLayer );
+                domainLayer.uses( infrastructureLayer );
+
+                ModuleAssembly rest = webLayer.module( "REST" );
+                rest.transients( TestTransient.class ).visibleIn( Visibility.layer );
+                
+                domainLayer.module( "Domain" );
+                infrastructureLayer.module( "Database" );
+
+                return assembly;
+            }
+        } );
+
+        Document document = new Model2XML().apply( model );
+
+        TransformerFactory transformerFactory = TransformerFactory.newInstance();
+        Transformer transformer = transformerFactory.newTransformer();
+        transformer.setOutputProperty( "indent", "yes"  );
+        transformer.setOutputProperty( "{http://xml.apache.org/xslt}indent-amount", "2"  );
+        transformer.transform( new DOMSource( document ), new StreamResult( System.out ) );
+    }
+
+    interface TestTransient
+        extends TransientComposite
+    {}
+}
diff --git a/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/EntitySerializerTest.java b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/EntitySerializerTest.java
new file mode 100644
index 0000000..fb5b0c3
--- /dev/null
+++ b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/EntitySerializerTest.java
@@ -0,0 +1,142 @@
+/*
+ *  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.polygene.library.rdf.entity;
+
+import java.io.PrintWriter;
+import java.time.Instant;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.time.SystemTime;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.rdf.DcRdf;
+import org.apache.polygene.library.rdf.Rdfs;
+import org.apache.polygene.library.rdf.serializer.RdfXmlSerializer;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Before;
+import org.junit.Test;
+import org.openrdf.model.Statement;
+import org.openrdf.rio.RDFHandlerException;
+
+/**
+ * JAVADOC
+ */
+public class EntitySerializerTest
+    extends AbstractPolygeneTest
+{
+    @Service
+    EntityStore entityStore;
+    @Uses
+    EntityStateSerializer serializer;
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+
+        module.entities( TestEntity.class );
+        module.values( TestValue.class, Test2Value.class );
+        module.objects( EntityStateSerializer.class, EntitySerializerTest.class );
+    }
+
+    @Override
+    @Before
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        createDummyData();
+    }
+
+    @Test
+    public void testEntitySerializer()
+        throws RDFHandlerException
+    {
+        EntityReference entityReference = EntityReference.parseEntityReference( "test2" );
+        Usecase usecase = UsecaseBuilder.newUsecase( "Test" );
+        Instant currentTime = SystemTime.now();
+        EntityStoreUnitOfWork unitOfWork = entityStore.newUnitOfWork( module, usecase, currentTime );
+        EntityState entityState = unitOfWork.entityStateOf( module, entityReference );
+
+        Iterable<Statement> graph = serializer.serialize( entityState );
+
+        String[] prefixes = new String[]{ "rdf", "dc", " vc" };
+        String[] namespaces = new String[]{ Rdfs.RDF, DcRdf.NAMESPACE, "http://www.w3.org/2001/vcard-rdf/3.0#" };
+
+        new RdfXmlSerializer().serialize( graph, new PrintWriter( System.out ), prefixes, namespaces );
+    }
+
+    void createDummyData()
+        throws UnitOfWorkCompletionException
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            ValueBuilder<TestValue> valueBuilder = valueBuilderFactory.newValueBuilder( TestValue.class );
+            valueBuilder.prototype().test1().set( 4L );
+            ValueBuilder<Test2Value> valueBuilder2 = valueBuilderFactory.newValueBuilder( Test2Value.class );
+            valueBuilder2.prototype().data().set( "Habba" );
+            valueBuilder.prototype().test3().set( valueBuilder2.newInstance() );
+            TestValue testValue = valueBuilder.newInstance();
+
+            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class, new StringIdentity( "test1" ) );
+            TestEntity rickardTemplate = builder.instance();
+            rickardTemplate.name().set( "Rickard" );
+            rickardTemplate.title().set( "Mr" );
+            rickardTemplate.value().set( testValue );
+            TestEntity testEntity = builder.newInstance();
+
+            EntityBuilder<TestEntity> builder2 = unitOfWork.newEntityBuilder( TestEntity.class, new StringIdentity( "test2" ) );
+            TestEntity niclasTemplate = builder2.instance();
+            niclasTemplate.name().set( "Niclas" );
+            niclasTemplate.title().set( "Mr" );
+            niclasTemplate.association().set( testEntity );
+            niclasTemplate.manyAssoc().add( 0, testEntity );
+            niclasTemplate.group().add( 0, testEntity );
+            niclasTemplate.group().add( 0, testEntity );
+            niclasTemplate.group().add( 0, testEntity );
+            valueBuilder = valueBuilderFactory.newValueBuilderWithPrototype( testValue );
+            valueBuilder.prototype().test1().set( 5L );
+            testValue = valueBuilder.newInstance();
+            niclasTemplate.value().set( testValue );
+            builder2.newInstance();
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+}
+
+
diff --git a/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/EntityTypeSerializerTest.java b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/EntityTypeSerializerTest.java
new file mode 100644
index 0000000..6c1d279
--- /dev/null
+++ b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/EntityTypeSerializerTest.java
@@ -0,0 +1,127 @@
+/*
+ *  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.polygene.library.rdf.entity;
+
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Before;
+import org.junit.Test;
+import org.openrdf.model.Statement;
+import org.openrdf.rio.RDFHandlerException;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.rdf.DcRdf;
+import org.apache.polygene.library.rdf.PolygeneEntityType;
+import org.apache.polygene.library.rdf.Rdfs;
+import org.apache.polygene.library.rdf.serializer.RdfXmlSerializer;
+import org.apache.polygene.spi.entitystore.EntityStore;
+
+import java.io.PrintWriter;
+import org.apache.polygene.test.EntityTestAssembler;
+
+
+/**
+ * JAVADOC
+ */
+public class EntityTypeSerializerTest
+    extends AbstractPolygeneTest
+{
+    @Service EntityStore entityStore;
+    @Uses EntityTypeSerializer serializer;
+
+    public void assemble( ModuleAssembly module ) throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        module.entities( TestEntity.class );
+        module.values( TestValue.class, Test2Value.class );
+        module.objects( EntityTypeSerializer.class, EntityTypeSerializerTest.class );
+    }
+
+    @Override @Before
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        createDummyData();
+    }
+
+    @Test
+    public void testEntityTypeSerializer() throws RDFHandlerException
+    {
+
+        EntityDescriptor entityDescriptor = module.entityDescriptor(TestEntity.class.getName());
+
+        Iterable<Statement> graph = serializer.serialize( entityDescriptor );
+
+        String[] prefixes = new String[]{ "rdf", "dc", " vc", "polygene" };
+        String[] namespaces = new String[]{ Rdfs.RDF, DcRdf.NAMESPACE, "http://www.w3.org/2001/vcard-rdf/3.0#", PolygeneEntityType.NAMESPACE };
+
+        new RdfXmlSerializer().serialize( graph, new PrintWriter( System.out ), prefixes, namespaces );
+    }
+
+    void createDummyData() throws UnitOfWorkCompletionException
+    {
+        UnitOfWork unitOfWork = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            ValueBuilder<Test2Value> vb2 = valueBuilderFactory.newValueBuilder( Test2Value.class );
+            vb2.prototype().data().set( "Zout" );
+
+            ValueBuilder<TestValue> valueBuilder = valueBuilderFactory.newValueBuilder( TestValue.class );
+            valueBuilder.prototype().test1().set( 4L );
+            valueBuilder.prototype().test3().set( vb2.newInstance() );
+            TestValue testValue = valueBuilder.newInstance();
+
+            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder(TestEntity.class, new StringIdentity( "test1") );
+            TestEntity rickardTemplate = builder.instance();
+            rickardTemplate.name().set( "Rickard" );
+            rickardTemplate.title().set( "Mr" );
+            rickardTemplate.value().set( testValue );
+            TestEntity testEntity = builder.newInstance();
+
+            EntityBuilder<TestEntity> builder2 = unitOfWork.newEntityBuilder(TestEntity.class, new StringIdentity( "test2") );
+            TestEntity niclasTemplate = builder2.instance();
+            niclasTemplate.name().set( "Niclas" );
+            niclasTemplate.title().set( "Mr" );
+            niclasTemplate.association().set( testEntity );
+            niclasTemplate.manyAssoc().add( 0, testEntity );
+            niclasTemplate.group().add( 0, testEntity );
+            niclasTemplate.group().add( 0, testEntity );
+            niclasTemplate.group().add( 0, testEntity );
+            valueBuilder = valueBuilderFactory.newValueBuilderWithPrototype( testValue );
+            valueBuilder.prototype().test1().set( 5L );
+            testValue = valueBuilder.newInstance();
+            niclasTemplate.value().set( testValue );
+            TestEntity testEntity2 = builder2.newInstance();
+            unitOfWork.complete();
+        }
+        finally
+        {
+            unitOfWork.discard();
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/Test2Value.java b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/Test2Value.java
new file mode 100644
index 0000000..291bc4b
--- /dev/null
+++ b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/Test2Value.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.rdf.entity;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+public interface Test2Value extends ValueComposite
+{
+    Property<String> data();
+}
diff --git a/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/TestEntity.java b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/TestEntity.java
new file mode 100644
index 0000000..3fac52d
--- /dev/null
+++ b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/TestEntity.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.library.rdf.entity;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.constraints.annotation.NotEmpty;
+
+/**
+ * JAVADOC
+ */
+interface TestEntity
+    extends EntityComposite
+{
+    @NotEmpty Property<String> name();
+
+    @NotEmpty Property<String> title();
+
+    @Optional Association<TestEntity> association();
+
+    Property<TestValue> value();
+
+    ManyAssociation<TestEntity> manyAssoc();
+
+    ManyAssociation<TestEntity> group();
+}
diff --git a/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/TestValue.java b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/TestValue.java
new file mode 100644
index 0000000..0ff7570
--- /dev/null
+++ b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/TestValue.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.rdf.entity;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * JAVADOC
+ */
+public interface TestValue extends ValueComposite
+{
+    Property<Long> test1();
+
+    @Optional Property<String> test2();
+
+    Property<Test2Value> test3();
+}
diff --git a/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/test2.xml b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/test2.xml
new file mode 100644
index 0000000..c8df825
--- /dev/null
+++ b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/entity/test2.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<rdf:RDF
+  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+  xmlns:dc="http://purl.org/dc/elements/1.1/"
+  xmlns:ns1="http://www.w3.org/2001/vcard-rdf/3.0#"
+  xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
+  <org.apache.polygene.library.rdf.entity.TestEntity xmlns="urn:polygene:persistent:Wvgf5vdB2OuC8JfcNmUqJLEPSYM:"
+                                          rdf:about="urn:polygene:entity:test2">
+    <value xmlns="urn:polygene:persistent:org.apache.polygene.library.rdf.entity.TestEntity#">{test1:5,test2:null,test3:{data:"Habba"}}</value>
+    <identity xmlns="urn:polygene:persistent:org.apache.polygene.api.identity.HasIdentity#">test2</identity>
+    <name xmlns="urn:polygene:persistent:org.apache.polygene.library.rdf.entity.TestEntity#">Niclas</name>
+    <title xmlns="urn:polygene:persistent:org.apache.polygene.library.rdf.entity.TestEntity#">Mr</title>
+    <association xmlns="urn:polygene:persistent:org.apache.polygene.library.rdf.entity.TestEntity#" rdf:resource="urn:polygene:entity:test1"/>
+    <group xmlns="urn:polygene:persistent:org.apache.polygene.library.rdf.entity.TestEntity#">
+      <rdf:Seq>
+        <rdf:li rdf:resource="urn:polygene:entity:test1"/>
+      </rdf:Seq>
+    </group>
+    <manyAssoc xmlns="urn:polygene:persistent:org.apache.polygene.library.rdf.entity.TestEntity#">
+      <rdf:Seq>
+        <rdf:li rdf:resource="urn:polygene:entity:test1"/>
+      </rdf:Seq>
+    </manyAssoc>
+  </org.apache.polygene.library.rdf.entity.TestEntity>
+
+</rdf:RDF>
\ No newline at end of file
diff --git a/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/repository/MemoryRepositoryTest.java b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/repository/MemoryRepositoryTest.java
new file mode 100644
index 0000000..bce71ed
--- /dev/null
+++ b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/repository/MemoryRepositoryTest.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.library.rdf.repository;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Test;
+import org.openrdf.repository.Repository;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+/**
+ * JAVADOC
+ */
+public class MemoryRepositoryTest
+    extends AbstractPolygeneTest
+{
+    @Service
+    Repository repository;
+
+    public void assemble( ModuleAssembly module ) throws AssemblyException
+    {
+        module.services( MemoryRepositoryService.class ).instantiateOnStartup();
+        module.objects( getClass() );
+    }
+
+    @Test
+    public void testMemoryRepository() throws RepositoryException
+    {
+        RepositoryConnection conn = repository.getConnection();
+        Assert.assertThat( "repository is open", conn.isOpen(), CoreMatchers.equalTo( true ) );
+        conn.close();
+    }
+}
diff --git a/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/repository/NativeRepositoryTest.java b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/repository/NativeRepositoryTest.java
new file mode 100644
index 0000000..aaa6ce8
--- /dev/null
+++ b/libraries/rdf/src/test/java/org/apache/polygene/library/rdf/repository/NativeRepositoryTest.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.library.rdf.repository;
+
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationOverride;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.openrdf.repository.Repository;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+
+/**
+ * JAVADOC
+ */
+public class NativeRepositoryTest extends AbstractPolygeneTest
+{
+   @Rule
+   public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+   @Service
+   Repository repository;
+
+   public void assemble(ModuleAssembly module) throws AssemblyException
+   {
+      new EntityTestAssembler().assemble( module );
+      new FileConfigurationAssembler()
+          .withOverride( new FileConfigurationOverride().withConventionalRoot( tmpDir.getRoot() ) )
+          .assemble( module );
+      module.services(NativeRepositoryService.class).instantiateOnStartup();
+      module.entities(NativeConfiguration.class);
+      module.objects(getClass());
+   }
+
+   @Test
+   public void testNativeRepository() throws RepositoryException
+   {
+      RepositoryConnection conn = repository.getConnection();
+      Assert.assertThat("repository is open", conn.isOpen(), CoreMatchers.equalTo(true));
+      conn.close();
+   }
+}
\ No newline at end of file
diff --git a/libraries/rdf/src/test/java/org/qi4j/library/rdf/ApplicationXmlTest.java b/libraries/rdf/src/test/java/org/qi4j/library/rdf/ApplicationXmlTest.java
deleted file mode 100644
index 423ef31..0000000
--- a/libraries/rdf/src/test/java/org/qi4j/library/rdf/ApplicationXmlTest.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf;
-
-import org.junit.Test;
-import org.openrdf.model.Statement;
-import org.openrdf.rio.RDFHandlerException;
-import org.openrdf.rio.RDFWriter;
-import org.openrdf.rio.RDFWriterFactory;
-import org.openrdf.rio.n3.N3WriterFactory;
-import org.openrdf.rio.rdfxml.RDFXMLWriterFactory;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.sideeffect.SideEffectOf;
-import org.qi4j.api.sideeffect.SideEffects;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.fileconfig.FileConfiguration;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.library.rdf.model.ApplicationSerializer;
-import org.qi4j.test.AbstractQi4jTest;
-
-import java.io.IOException;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-
-/**
- * JAVADOC
- */
-public class ApplicationXmlTest extends AbstractQi4jTest
-{
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        LayerAssembly layerAssembly = module.layer();
-        layerAssembly.application().setName( "testapp" );
-        module.transients( TestComposite.class );
-        module.services( FileConfigurationService.class );
-    }
-
-    @Test
-    public void testApplicationXml()
-        throws Exception
-    {
-        FileConfiguration fileConfig = (FileConfiguration) module.findService( FileConfiguration.class ).get();
-        ApplicationSerializer parser = new ApplicationSerializer();
-        Iterable<Statement> graph = parser.serialize( application ); // TODO Fix this
-        writeN3( graph );
-        writeXml( graph );
-    }
-
-    private void writeN3( Iterable<Statement> graph )
-        throws RDFHandlerException, IOException
-    {
-        RDFWriterFactory writerFactory = new N3WriterFactory();
-        RDFWriter writer = writerFactory.getWriter( System.out );
-        writeOutput( writer, graph );
-    }
-
-    private void writeXml( Iterable<Statement> graph )
-        throws RDFHandlerException, IOException
-    {
-        RDFWriterFactory writerFactory = new RDFXMLWriterFactory();
-        RDFWriter writer = writerFactory.getWriter( System.out );
-        writeOutput( writer, graph );
-    }
-
-    private void writeOutput( RDFWriter writer, Iterable<Statement> graph )
-        throws RDFHandlerException
-    {
-        writer.startRDF();
-        writer.handleNamespace( "qi4j", Qi4jRdf.QI4JMODEL );
-        writer.handleNamespace( "rdf", Rdfs.RDF );
-        writer.handleNamespace( "rdfs", Rdfs.RDFS );
-        for( Statement st : graph )
-        {
-            writer.handleStatement( st );
-        }
-        writer.endRDF();
-    }
-
-    @Mixins( AMixin.class )
-    public interface A
-    {
-        String doStuff();
-    }
-
-    public static class AMixin
-        implements A
-    {
-        @This B bRef;
-
-        public String doStuff()
-        {
-            return bRef.otherStuff() + "123";
-        }
-    }
-
-    public interface B
-    {
-        String otherStuff();
-    }
-
-    public static class BMixin
-        implements B
-    {
-        public String otherStuff()
-        {
-            return "XYZ";
-        }
-    }
-
-    public static class OtherStuffConcern extends ConcernOf<B>
-        implements B
-    {
-        public String otherStuff()
-        {
-            return next.otherStuff() + "!";
-        }
-    }
-
-    public static class LogSideEffect extends SideEffectOf<InvocationHandler>
-        implements InvocationHandler
-    {
-        public Object invoke( Object object, Method method, Object[] objects ) throws Throwable
-        {
-            System.out.println( "Called " + method.getName() );
-            return null;
-        }
-    }
-
-    @SideEffects( LogSideEffect.class )
-    @Concerns( OtherStuffConcern.class )
-    @Mixins( { BMixin.class } )
-    public interface TestComposite
-        extends A, TransientComposite
-    {
-    }
-}
diff --git a/libraries/rdf/src/test/java/org/qi4j/library/rdf/Model2XMLTest.java b/libraries/rdf/src/test/java/org/qi4j/library/rdf/Model2XMLTest.java
deleted file mode 100644
index bdff5ac..0000000
--- a/libraries/rdf/src/test/java/org/qi4j/library/rdf/Model2XMLTest.java
+++ /dev/null
@@ -1,82 +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.qi4j.library.rdf;
-
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.bootstrap.*;
-import org.qi4j.library.rdf.model.Model2XML;
-import org.w3c.dom.Document;
-
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
-/**
- * TODO
- */
-public class Model2XMLTest
-{
-    @Test
-    public void testModel2XML() throws AssemblyException, TransformerException
-    {
-        Energy4Java is = new Energy4Java(  );
-        ApplicationDescriptor model = is.newApplicationModel( new ApplicationAssembler()
-        {
-            @Override
-            public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory ) throws AssemblyException
-            {
-                ApplicationAssembly assembly = applicationFactory.newApplicationAssembly();
-
-                assembly.setName( "Test application" );
-
-                LayerAssembly webLayer = assembly.layer( "Web" );
-                LayerAssembly domainLayer = assembly.layer( "Domain" );
-                LayerAssembly infrastructureLayer = assembly.layer( "Infrastructure" );
-
-                webLayer.uses( domainLayer, infrastructureLayer );
-                domainLayer.uses( infrastructureLayer );
-
-                ModuleAssembly rest = webLayer.module( "REST" );
-                rest.transients( TestTransient.class ).visibleIn( Visibility.layer );
-                
-                domainLayer.module( "Domain" );
-                infrastructureLayer.module( "Database" );
-
-                return assembly;
-            }
-        } );
-
-        Document document = new Model2XML().map( model );
-
-        TransformerFactory transformerFactory = TransformerFactory.newInstance();
-        Transformer transformer = transformerFactory.newTransformer();
-        transformer.setOutputProperty( "indent", "yes"  );
-        transformer.setOutputProperty( "{http://xml.apache.org/xslt}indent-amount", "2"  );
-        transformer.transform( new DOMSource( document ), new StreamResult( System.out ) );
-    }
-
-    interface TestTransient
-        extends TransientComposite
-    {}
-}
diff --git a/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/EntitySerializerTest.java b/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/EntitySerializerTest.java
deleted file mode 100644
index a89f518..0000000
--- a/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/EntitySerializerTest.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf.entity;
-
-import java.io.PrintWriter;
-import org.junit.Before;
-import org.junit.Test;
-import org.openrdf.model.Statement;
-import org.openrdf.rio.RDFHandlerException;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.rdf.DcRdf;
-import org.qi4j.library.rdf.Rdfs;
-import org.qi4j.library.rdf.serializer.RdfXmlSerializer;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.EntityStoreUnitOfWork;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-/**
- * JAVADOC
- */
-public class EntitySerializerTest
-    extends AbstractQi4jTest
-{
-    @Service
-    EntityStore entityStore;
-    @Uses
-    EntityStateSerializer serializer;
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        new OrgJsonValueSerializationAssembler().assemble( module );
-
-        module.entities( TestEntity.class );
-        module.values( TestValue.class, Test2Value.class );
-        module.objects( EntityStateSerializer.class, EntitySerializerTest.class );
-    }
-
-    @Override
-    @Before
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-
-        createDummyData();
-
-        module.injectTo( this );
-    }
-
-    @Test
-    public void testEntitySerializer()
-        throws RDFHandlerException
-    {
-        EntityReference entityReference = new EntityReference( "test2" );
-        Usecase usecase = UsecaseBuilder.newUsecase( "Test" );
-        long currentTime = System.currentTimeMillis();
-        EntityStoreUnitOfWork unitOfWork = entityStore.newUnitOfWork( usecase, module, currentTime );
-        EntityState entityState = unitOfWork.entityStateOf( module, entityReference );
-
-        Iterable<Statement> graph = serializer.serialize( entityState );
-
-        String[] prefixes = new String[]{ "rdf", "dc", " vc" };
-        String[] namespaces = new String[]{ Rdfs.RDF, DcRdf.NAMESPACE, "http://www.w3.org/2001/vcard-rdf/3.0#" };
-
-        new RdfXmlSerializer().serialize( graph, new PrintWriter( System.out ), prefixes, namespaces );
-    }
-
-    void createDummyData()
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            ValueBuilder<TestValue> valueBuilder = module.newValueBuilder( TestValue.class );
-            valueBuilder.prototype().test1().set( 4L );
-            ValueBuilder<Test2Value> valueBuilder2 = module.newValueBuilder( Test2Value.class );
-            valueBuilder2.prototype().data().set( "Habba" );
-            valueBuilder.prototype().test3().set( valueBuilder2.newInstance() );
-            TestValue testValue = valueBuilder.newInstance();
-
-            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class, "test1" );
-            TestEntity rickardTemplate = builder.instance();
-            rickardTemplate.name().set( "Rickard" );
-            rickardTemplate.title().set( "Mr" );
-            rickardTemplate.value().set( testValue );
-            TestEntity testEntity = builder.newInstance();
-
-            EntityBuilder<TestEntity> builder2 = unitOfWork.newEntityBuilder( TestEntity.class, "test2" );
-            TestEntity niclasTemplate = builder2.instance();
-            niclasTemplate.name().set( "Niclas" );
-            niclasTemplate.title().set( "Mr" );
-            niclasTemplate.association().set( testEntity );
-            niclasTemplate.manyAssoc().add( 0, testEntity );
-            niclasTemplate.group().add( 0, testEntity );
-            niclasTemplate.group().add( 0, testEntity );
-            niclasTemplate.group().add( 0, testEntity );
-            valueBuilder = module.newValueBuilderWithPrototype( testValue );
-            valueBuilder.prototype().test1().set( 5L );
-            testValue = valueBuilder.newInstance();
-            niclasTemplate.value().set( testValue );
-            builder2.newInstance();
-            unitOfWork.complete();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-}
-
-
diff --git a/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/EntityTypeSerializerTest.java b/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/EntityTypeSerializerTest.java
deleted file mode 100644
index 04ac055..0000000
--- a/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/EntityTypeSerializerTest.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf.entity;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.openrdf.model.Statement;
-import org.openrdf.rio.RDFHandlerException;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.rdf.DcRdf;
-import org.qi4j.library.rdf.Qi4jEntityType;
-import org.qi4j.library.rdf.Rdfs;
-import org.qi4j.library.rdf.serializer.RdfXmlSerializer;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.test.AbstractQi4jTest;
-
-import java.io.PrintWriter;
-import org.qi4j.test.EntityTestAssembler;
-
-
-/**
- * JAVADOC
- */
-public class EntityTypeSerializerTest
-    extends AbstractQi4jTest
-{
-    @Service EntityStore entityStore;
-    @Uses EntityTypeSerializer serializer;
-
-    public void assemble( ModuleAssembly module ) throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        module.entities( TestEntity.class );
-        module.values( TestValue.class, Test2Value.class );
-        module.objects( EntityTypeSerializer.class, EntityTypeSerializerTest.class );
-    }
-
-    @Override @Before
-    public void setUp() throws Exception
-    {
-        super.setUp();
-
-        createDummyData();
-
-        module.injectTo( this );
-    }
-
-    @Test
-    public void testEntityTypeSerializer() throws RDFHandlerException
-    {
-
-        EntityDescriptor entityDescriptor = module.entityDescriptor(TestEntity.class.getName());
-
-        Iterable<Statement> graph = serializer.serialize( entityDescriptor );
-
-        String[] prefixes = new String[]{ "rdf", "dc", " vc", "qi4j" };
-        String[] namespaces = new String[]{ Rdfs.RDF, DcRdf.NAMESPACE, "http://www.w3.org/2001/vcard-rdf/3.0#", Qi4jEntityType.NAMESPACE };
-
-        new RdfXmlSerializer().serialize( graph, new PrintWriter( System.out ), prefixes, namespaces );
-    }
-
-    void createDummyData() throws UnitOfWorkCompletionException
-    {
-        UnitOfWork unitOfWork = module.newUnitOfWork();
-        try
-        {
-            ValueBuilder<Test2Value> vb2 = module.newValueBuilder( Test2Value.class );
-            vb2.prototype().data().set( "Zout" );
-
-            ValueBuilder<TestValue> valueBuilder = module.newValueBuilder( TestValue.class );
-            valueBuilder.prototype().test1().set( 4L );
-            valueBuilder.prototype().test3().set( vb2.newInstance() );
-            TestValue testValue = valueBuilder.newInstance();
-
-            EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder(TestEntity.class, "test1");
-            TestEntity rickardTemplate = builder.instance();
-            rickardTemplate.name().set( "Rickard" );
-            rickardTemplate.title().set( "Mr" );
-            rickardTemplate.value().set( testValue );
-            TestEntity testEntity = builder.newInstance();
-
-            EntityBuilder<TestEntity> builder2 = unitOfWork.newEntityBuilder(TestEntity.class, "test2");
-            TestEntity niclasTemplate = builder2.instance();
-            niclasTemplate.name().set( "Niclas" );
-            niclasTemplate.title().set( "Mr" );
-            niclasTemplate.association().set( testEntity );
-            niclasTemplate.manyAssoc().add( 0, testEntity );
-            niclasTemplate.group().add( 0, testEntity );
-            niclasTemplate.group().add( 0, testEntity );
-            niclasTemplate.group().add( 0, testEntity );
-            valueBuilder = module.newValueBuilderWithPrototype( testValue );
-            valueBuilder.prototype().test1().set( 5L );
-            testValue = valueBuilder.newInstance();
-            niclasTemplate.value().set( testValue );
-            TestEntity testEntity2 = builder2.newInstance();
-            unitOfWork.complete();
-        }
-        finally
-        {
-            unitOfWork.discard();
-        }
-    }
-}
\ No newline at end of file
diff --git a/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/Test2Value.java b/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/Test2Value.java
deleted file mode 100644
index 64512e7..0000000
--- a/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/Test2Value.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.rdf.entity;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-public interface Test2Value extends ValueComposite
-{
-    Property<String> data();
-}
diff --git a/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/TestEntity.java b/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/TestEntity.java
deleted file mode 100644
index 44368be..0000000
--- a/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/TestEntity.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf.entity;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.property.Property;
-import org.qi4j.library.constraints.annotation.NotEmpty;
-
-/**
- * JAVADOC
- */
-interface TestEntity
-    extends EntityComposite
-{
-    @NotEmpty Property<String> name();
-
-    @NotEmpty Property<String> title();
-
-    @Optional Association<TestEntity> association();
-
-    Property<TestValue> value();
-
-    ManyAssociation<TestEntity> manyAssoc();
-
-    ManyAssociation<TestEntity> group();
-}
diff --git a/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/TestValue.java b/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/TestValue.java
deleted file mode 100644
index 4447e04..0000000
--- a/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/TestValue.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf.entity;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * JAVADOC
- */
-public interface TestValue extends ValueComposite
-{
-    Property<Long> test1();
-
-    @Optional Property<String> test2();
-
-    Property<Test2Value> test3();
-}
diff --git a/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/test.xml b/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/test.xml
deleted file mode 100644
index b2de33f..0000000
--- a/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/test.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<rdf:RDF
-  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-  xmlns:dc="http://purl.org/dc/elements/1.1/"
-  xmlns:ns1="http://www.w3.org/2001/vcard-rdf/3.0#"
-  xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
-  <org.qi4j.library.rdf.entity.TestEntity xmlns="urn:qi4j:persistent:Wvgf5vdB2OuC8JfcNmUqJLEPSYM:"
-                                          rdf:about="urn:qi4j:entity:test2"/>
-  <rdf:Description>
-    <value.test1 xmlns="urn:qi4j:persistent:org.qi4j.library.rdf.entity.TestEntity#">5</value.test1>
-    <value.,test2 xmlns="urn:qi4j:type:org.qi4j.library.rdf.entity.TestEntity#"/>
-  </rdf:Description>
-  <rdf:Description>
-    <value.data xmlns=".urn:qi4j:persistent:org.qi4j.library.rdf.entity.TestEntity#">Habba</value.data>
-  </rdf:Description>
-  <rdf:Description>
-    <value.test3 xmlns="urn:qi4j:persistent:org.qi4j.library.rdf.entity.TestEntity#"/>
-  </rdf:Description>
-  <rdf:Description rdf:about="urn:qi4j:entity:test2">
-    <value xmlns="urn:qi4j:persistent:org.qi4j.library.rdf.entity.TestEntity#"/>
-    <identity xmlns="urn:qi4j:persistent:org.qi4j.api.entity.Identity#">test2</identity>
-    <name xmlns="urn:qi4j:persistent:org.qi4j.library.rdf.entity.TestEntity#">Niclas</name>
-    <title xmlns="urn:qi4j:persistent:org.qi4j.library.rdf.entity.TestEntity#">Mr</title>
-    <association xmlns="urn:qi4j:persistent:org.qi4j.library.rdf.entity.TestEntity#" rdf:resource="urn:qi4j:entity:test1"/>
-    <group xmlns="urn:qi4j:persistent:org.qi4j.library.rdf.entity.TestEntity#">
-      <rdf:Seq>
-        <rdf:li rdf:resource="urn:qi4j:entity:test1"/>
-      </rdf:Seq>
-    </group>
-    <manyAssoc xmlns="urn:qi4j:persistent:org.qi4j.library.rdf.entity.TestEntity#">
-      <rdf:Seq>
-        <rdf:li rdf:resource="urn:qi4j:entity:test1"/>
-      </rdf:Seq>
-    </manyAssoc>
-  </rdf:Description>
-
-</rdf:RDF>
\ No newline at end of file
diff --git a/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/test2.xml b/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/test2.xml
deleted file mode 100644
index 91ff53b..0000000
--- a/libraries/rdf/src/test/java/org/qi4j/library/rdf/entity/test2.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<rdf:RDF
-  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-  xmlns:dc="http://purl.org/dc/elements/1.1/"
-  xmlns:ns1="http://www.w3.org/2001/vcard-rdf/3.0#"
-  xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
-  <org.qi4j.library.rdf.entity.TestEntity xmlns="urn:qi4j:persistent:Wvgf5vdB2OuC8JfcNmUqJLEPSYM:"
-                                          rdf:about="urn:qi4j:entity:test2">
-    <value xmlns="urn:qi4j:persistent:org.qi4j.library.rdf.entity.TestEntity#">{test1:5,test2:null,test3:{data:"Habba"}}</value>
-    <identity xmlns="urn:qi4j:persistent:org.qi4j.api.entity.Identity#">test2</identity>
-    <name xmlns="urn:qi4j:persistent:org.qi4j.library.rdf.entity.TestEntity#">Niclas</name>
-    <title xmlns="urn:qi4j:persistent:org.qi4j.library.rdf.entity.TestEntity#">Mr</title>
-    <association xmlns="urn:qi4j:persistent:org.qi4j.library.rdf.entity.TestEntity#" rdf:resource="urn:qi4j:entity:test1"/>
-    <group xmlns="urn:qi4j:persistent:org.qi4j.library.rdf.entity.TestEntity#">
-      <rdf:Seq>
-        <rdf:li rdf:resource="urn:qi4j:entity:test1"/>
-      </rdf:Seq>
-    </group>
-    <manyAssoc xmlns="urn:qi4j:persistent:org.qi4j.library.rdf.entity.TestEntity#">
-      <rdf:Seq>
-        <rdf:li rdf:resource="urn:qi4j:entity:test1"/>
-      </rdf:Seq>
-    </manyAssoc>
-  </org.qi4j.library.rdf.entity.TestEntity>
-
-</rdf:RDF>
\ No newline at end of file
diff --git a/libraries/rdf/src/test/java/org/qi4j/library/rdf/repository/MemoryRepositoryTest.java b/libraries/rdf/src/test/java/org/qi4j/library/rdf/repository/MemoryRepositoryTest.java
deleted file mode 100644
index 110f8e1..0000000
--- a/libraries/rdf/src/test/java/org/qi4j/library/rdf/repository/MemoryRepositoryTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf.repository;
-
-import org.hamcrest.CoreMatchers;
-import org.junit.Assert;
-import org.junit.Test;
-import org.openrdf.repository.Repository;
-import org.openrdf.repository.RepositoryConnection;
-import org.openrdf.repository.RepositoryException;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-/**
- * JAVADOC
- */
-public class MemoryRepositoryTest
-    extends AbstractQi4jTest
-{
-    @Service
-    Repository repository;
-
-    public void assemble( ModuleAssembly module ) throws AssemblyException
-    {
-        module.services( MemoryRepositoryService.class ).instantiateOnStartup();
-        module.objects( getClass() );
-    }
-
-    @Test
-    public void testMemoryRepository() throws RepositoryException
-    {
-        module.injectTo( this );
-
-
-        RepositoryConnection conn = repository.getConnection();
-
-        Assert.assertThat( "repository is open", conn.isOpen(), CoreMatchers.equalTo( true ) );
-
-        conn.close();
-    }
-}
diff --git a/libraries/rdf/src/test/java/org/qi4j/library/rdf/repository/NativeRepositoryTest.java b/libraries/rdf/src/test/java/org/qi4j/library/rdf/repository/NativeRepositoryTest.java
deleted file mode 100644
index 7d4a06b..0000000
--- a/libraries/rdf/src/test/java/org/qi4j/library/rdf/repository/NativeRepositoryTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rdf.repository;
-
-import org.hamcrest.CoreMatchers;
-import org.junit.Assert;
-import org.junit.Test;
-import org.openrdf.repository.Repository;
-import org.openrdf.repository.RepositoryConnection;
-import org.openrdf.repository.RepositoryException;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-/**
- * JAVADOC
- */
-public class NativeRepositoryTest
-        extends AbstractQi4jTest
-{
-   @Service
-   Repository repository;
-
-   public void assemble(ModuleAssembly module) throws AssemblyException
-   {
-      new EntityTestAssembler().assemble( module );
-      module.services(FileConfigurationService.class).instantiateOnStartup();
-      module.services(NativeRepositoryService.class).instantiateOnStartup();
-      module.entities(NativeConfiguration.class);
-      module.objects(getClass());
-   }
-
-   @Test
-   public void testNativeRepository() throws RepositoryException
-   {
-      module.injectTo(this);
-
-      RepositoryConnection conn = repository.getConnection();
-
-      Assert.assertThat("repository is open", conn.isOpen(), CoreMatchers.equalTo(true));
-
-      conn.close();
-   }
-}
\ No newline at end of file
diff --git a/libraries/rdf/src/test/resources/org/apache/polygene/library/rdf/repository/NativeRepositoryService.properties b/libraries/rdf/src/test/resources/org/apache/polygene/library/rdf/repository/NativeRepositoryService.properties
new file mode 100644
index 0000000..6715eac
--- /dev/null
+++ b/libraries/rdf/src/test/resources/org/apache/polygene/library/rdf/repository/NativeRepositoryService.properties
@@ -0,0 +1,21 @@
+#
+#  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.
+#
+#
+#
+
+tripleIndexes=spoc
diff --git a/libraries/rdf/src/test/resources/org/qi4j/library/rdf/repository/NativeRepositoryService.properties b/libraries/rdf/src/test/resources/org/qi4j/library/rdf/repository/NativeRepositoryService.properties
deleted file mode 100644
index 5c42def..0000000
--- a/libraries/rdf/src/test/resources/org/qi4j/library/rdf/repository/NativeRepositoryService.properties
+++ /dev/null
@@ -1,16 +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.
-
-tripleIndexes=spoc
diff --git a/libraries/rest-client/build.gradle b/libraries/rest-client/build.gradle
index 04b1ce9..2270e41 100644
--- a/libraries/rest-client/build.gradle
+++ b/libraries/rest-client/build.gradle
@@ -1,38 +1,38 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ REST Client Library provides a client library for the Apache Zest™ REST Server library"
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - REST Client" }}
+description = "Apache Polygene™ REST Client Library provides a client library for the Apache Polygene™ REST Server library"
+
+jar { manifest { name = "Apache Polygene™ Library - REST Client" } }
 
 dependencies {
+  api polygene.library( 'rest-common' )
 
-    compile project( ":org.qi4j.core:org.qi4j.core.api" )
-    compile project( ":org.qi4j.libraries:org.qi4j.library.rest-common" )
-    compile libraries.restlet
-    compile libraries.slf4j_api
+  implementation libraries.restlet
 
-    testCompile project( ":org.qi4j.core:org.qi4j.core.testsupport" )
-    testCompile project( ":org.qi4j.libraries:org.qi4j.library.rest-server" )
-    testCompile project( ':org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson' )
+  runtimeOnly polygene.core.runtime
 
-    testRuntime project( ":org.qi4j.core:org.qi4j.core.runtime" )
-    testRuntime libraries.logback
+  testImplementation polygene.core.testsupport
+  testImplementation polygene.library( 'rest-server' )
 
+  testRuntimeOnly libraries.logback
 }
diff --git a/libraries/rest-client/dev-status.xml b/libraries/rest-client/dev-status.xml
index a294481..8a68435 100644
--- a/libraries/rest-client/dev-status.xml
+++ b/libraries/rest-client/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/rest-client/src/docs/primer.txt b/libraries/rest-client/src/docs/primer.txt
index 62245bd..6497dba 100644
--- a/libraries/rest-client/src/docs/primer.txt
+++ b/libraries/rest-client/src/docs/primer.txt
@@ -20,7 +20,7 @@
 [[library-rest-client-primer, HATEOAS Primer]]
 = ReST - HATEOAS Primer
 
-The Zest™ ReST Client implements HATEOAS (Hypermedia As The Engine Of Application State) to the full extent intended
+The Polygene™ ReST Client implements HATEOAS (Hypermedia As The Engine Of Application State) to the full extent intended
 by Roy Fielding. The ReST Client Library enables the creation of HATEOAS applications that are NOT using the URL space,
 and it is NOT about doing RPC calls over HTTP using a common exchange format (like JSON).
 
@@ -51,7 +51,7 @@
 Example:
 [snippet,java]
 -----------
-source=libraries/rest-client/src/test/java/org/qi4j/library/rest/client/docsupport/RestPrimerDocs.java
+source=libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/docsupport/RestPrimerDocs.java
 tag=1
 -----------
 
@@ -68,7 +68,7 @@
 
 [snippet,java]
 -----------
-source=libraries/rest-client/src/test/java/org/qi4j/library/rest/client/docsupport/RestPrimerDocs.java
+source=libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/docsupport/RestPrimerDocs.java
 tag=2
 -----------
 
@@ -79,7 +79,7 @@
 It becomes possible to blend general application and error handling logic with use case specific handlers.
 
 That's basically it. This is where I want to go with support for REST, as a way to truly leverage the REST ideas and
-make it very easy to do REST applications *and* clients based on Zest, by keeping the application logic on the server.
+make it very easy to do REST applications *and* clients based on Polygene, by keeping the application logic on the server.
 In the long run there would also be a JavaScript version of the client, with the same characteristics, so that you can
-easily build a jQuery UI for Zest™ REST apps.
+easily build a jQuery UI for Polygene™ REST apps.
 
diff --git a/libraries/rest-client/src/docs/rest-client.txt b/libraries/rest-client/src/docs/rest-client.txt
index dafd6db..0e46d53 100644
--- a/libraries/rest-client/src/docs/rest-client.txt
+++ b/libraries/rest-client/src/docs/rest-client.txt
@@ -46,7 +46,7 @@
 
 [snippet,java]
 -------------
-source=libraries/rest-client/src/test/java/org/qi4j/library/rest/client/ContextResourceClientFactoryTest.java
+source=libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/ContextResourceClientFactoryTest.java
 tag=client-create1
 -------------
 
@@ -57,7 +57,7 @@
 
 [snippet,java]
 -------------
-source=libraries/rest-client/src/test/java/org/qi4j/library/rest/client/ContextResourceClientFactoryTest.java
+source=libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/ContextResourceClientFactoryTest.java
 tag=client-create2
 -------------
 
@@ -74,7 +74,7 @@
 
 [snippet,java]
 -------------
-source=libraries/rest-client/src/test/java/org/qi4j/library/rest/client/ContextResourceClientFactoryTest.java
+source=libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/ContextResourceClientFactoryTest.java
 tag=client-create3
 -------------
 
@@ -89,28 +89,28 @@
 === Query without Value ===
 [snippet,java]
 -------------
-source=libraries/rest-client/src/test/java/org/qi4j/library/rest/client/ContextResourceClientFactoryTest.java
+source=libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/ContextResourceClientFactoryTest.java
 tag=query-without-value
 -------------
 
 === Query and Command ===
 [snippet,java]
 -------------
-source=libraries/rest-client/src/test/java/org/qi4j/library/rest/client/ContextResourceClientFactoryTest.java
+source=libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/ContextResourceClientFactoryTest.java
 tag=query-and-command
 -------------
 
 === Query List and Command ===
 [snippet,java]
 -------------
-source=libraries/rest-client/src/test/java/org/qi4j/library/rest/client/ContextResourceClientFactoryTest.java
+source=libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/ContextResourceClientFactoryTest.java
 tag=query-list-and-command
 -------------
 
 === Query List and Command Progressive ===
 [snippet,java]
 -------------
-source=libraries/rest-client/src/test/java/org/qi4j/library/rest/client/ContextResourceClientFactoryTest.java
+source=libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/ContextResourceClientFactoryTest.java
 tag=query-list-and-command-progressive
 -------------
 
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/ClientAssembler.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/ClientAssembler.java
new file mode 100644
index 0000000..91cb279
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/ClientAssembler.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.library.rest.client;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.rest.client.api.ContextResourceClient;
+import org.apache.polygene.library.rest.client.api.ContextResourceClientFactory;
+import org.apache.polygene.library.rest.client.requestwriter.FormRequestWriter;
+import org.apache.polygene.library.rest.client.requestwriter.ValueCompositeRequestWriter;
+import org.apache.polygene.library.rest.client.responsereader.DefaultResponseReader;
+import org.apache.polygene.library.rest.client.responsereader.JSONResponseReader;
+import org.apache.polygene.library.rest.client.responsereader.TableResponseReader;
+
+/**
+ * JAVADOC
+ */
+public class ClientAssembler
+   implements Assembler
+{
+    @Override
+   public void assemble( ModuleAssembly module ) throws AssemblyException
+   {
+      module.objects( ContextResourceClientFactory.class, ContextResourceClient.class ).visibleIn( Visibility.application );
+
+      module.objects( ResponseReaderDelegator.class,
+            DefaultResponseReader.class,
+            JSONResponseReader.class,
+            TableResponseReader.class ).visibleIn( Visibility.application );
+
+      module.objects(RequestWriterDelegator.class,
+            FormRequestWriter.class,
+            ValueCompositeRequestWriter.class).visibleIn(Visibility.application);
+   }
+}
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/ClientCache.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/ClientCache.java
new file mode 100644
index 0000000..8d50a59
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/ClientCache.java
@@ -0,0 +1,149 @@
+/*
+ *  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.polygene.library.rest.client;
+
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.data.Method;
+import org.restlet.data.Reference;
+import org.restlet.data.Tag;
+
+import static java.util.Date.from;
+
+/**
+ * Cache for the ContextResourceClient. This is primarily used to keep track of ETags and lastmodified timestamps for now.
+ */
+public class ClientCache
+{
+    private Map<String, CacheInfo> identityToTimestamp = new HashMap<>();
+    private Map<String, String> pathToIdentity = new HashMap<>();
+
+    public void updateCache( Response response )
+    {
+        if( response.getRequest().getMethod().equals( Method.DELETE ) )
+        {
+            String path = getIdentityPath( response.getRequest().getResourceRef() );
+            String id = pathToIdentity.get( path );
+            if( id != null )
+            {
+                // Clear anything related to this id from cache
+                identityToTimestamp.remove( id );
+                Iterator<Map.Entry<String, String>> paths = pathToIdentity.entrySet().iterator();
+                while( paths.hasNext() )
+                {
+                    Map.Entry<String, String> entry = paths.next();
+                    if( entry.getValue().equals( id ) )
+                    {
+                        paths.remove();
+                    }
+                }
+            }
+        }
+        else if( response.getRequest().getMethod().equals( Method.PUT ) || response.getRequest()
+            .getMethod()
+            .equals( Method.POST ) )
+        {
+            Tag tag = response.getEntity().getTag();
+            if( tag != null )
+            {
+                Reference ref = response.getRequest().getResourceRef().clone();
+
+                CacheInfo value = new CacheInfo( response.getEntity().getModificationDate().toInstant(), tag);
+                identityToTimestamp.put( value.getEntity(), value );
+
+                String path = getIdentityPath( ref );
+
+                pathToIdentity.put( path, value.getEntity() );
+
+//            LoggerFactory.getLogger( ClientCache.class ).info( "Update:"+value.getEntity()+" ("+ref.toString()+") -> "+value.getLastModified() );
+            }
+        }
+        else
+        {
+            // TODO GET caching goes here
+            System.out.println("Caching of GET is not implemented...");
+        }
+    }
+
+    public void updateQueryConditions( Request request )
+    {
+        String identity = pathToIdentity.get( getIdentityPath( request.getResourceRef() ) );
+        if( identity != null )
+        {
+            CacheInfo cacheInfo = identityToTimestamp.get( identity );
+            if( cacheInfo != null )
+            {
+//            LoggerFactory.getLogger( ClientCache.class ).info( "Send:  "+cacheInfo.getEntity()+" ("+request.getMethod().getName()+":"+request.getResourceRef()+") -> "+cacheInfo.getLastModified() );
+                request.getConditions().setModifiedSince( from( cacheInfo.getLastModified() ) );
+            }
+        }
+    }
+
+    public void updateCommandConditions( Request request )
+    {
+        String identity = pathToIdentity.get( getIdentityPath( request.getResourceRef() ) );
+        if( identity != null )
+        {
+            CacheInfo cacheInfo = identityToTimestamp.get( identity );
+            if( cacheInfo != null )
+            {
+//            LoggerFactory.getLogger( ClientCache.class ).info( "Send:  "+cacheInfo.getEntity()+" ("+request.getMethod().getName()+":"+request.getResourceRef()+") -> "+cacheInfo.getLastModified() );
+                request.getConditions().setUnmodifiedSince( from( cacheInfo.getLastModified() ) );
+            }
+        }
+    }
+
+    private String getIdentityPath( Reference ref )
+    {
+        String path = ref.getPath();
+        if( !path.endsWith( "/" ) )
+        {
+            path = path.substring( 0, path.lastIndexOf( '/' ) + 1 );
+        }
+        return path;
+    }
+
+    private static class CacheInfo
+    {
+        private Instant lastModified;
+        private String entity;
+
+        CacheInfo( Instant lastModified, Tag tag )
+        {
+            this.lastModified = lastModified;
+            entity = tag.getName().split( "/" )[ 0 ];
+        }
+
+        Instant getLastModified()
+        {
+            return lastModified;
+        }
+
+        String getEntity()
+        {
+            return entity;
+        }
+    }
+}
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/RequestWriterDelegator.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/RequestWriterDelegator.java
new file mode 100644
index 0000000..f7d1a0a
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/RequestWriterDelegator.java
@@ -0,0 +1,102 @@
+/*
+ *  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.polygene.library.rest.client;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ResourceBundle;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.library.rest.client.spi.RequestWriter;
+import org.restlet.Request;
+import org.restlet.data.Method;
+import org.restlet.representation.EmptyRepresentation;
+import org.restlet.representation.Representation;
+import org.restlet.resource.ResourceException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Delegates to a list of potential writers. Register writers on startup.
+ */
+public class RequestWriterDelegator
+   implements RequestWriter, Initializable
+{
+   List<RequestWriter> requestWriters = new ArrayList<>();
+
+   @Structure
+   private Module module;
+
+    @Override
+   public void initialize()
+   {
+      Logger logger = LoggerFactory.getLogger( getClass() );
+
+      ResourceBundle defaultRequestWriters = ResourceBundle.getBundle( "org.apache.polygene.library.rest.client.rest-client" );
+
+      String requestWriterClasses = defaultRequestWriters.getString( "requestwriters" );
+      logger.info( "Using request writers:"+requestWriterClasses );
+      for (String className : requestWriterClasses.split( "," ))
+      {
+         try
+         {
+            Class writerClass = module.descriptor().classLoader().loadClass( className.trim() );
+            RequestWriter requestWriter = (RequestWriter) module.newObject( writerClass );
+            registerRequestWriter(requestWriter);
+         } catch (ClassNotFoundException e)
+         {
+            logger.warn( "Could not register request writer "+className, e );
+         }
+      }
+   }
+
+   public void registerRequestWriter(RequestWriter writer)
+   {
+      requestWriters.add( writer );
+   }
+
+    @Override
+   public boolean writeRequest(Object requestObject, Request request) throws ResourceException
+   {
+      if (requestObject == null)
+      {
+         if (!Method.GET.equals(request.getMethod()))
+            request.setEntity(new EmptyRepresentation());
+
+         return true;
+      }
+
+      if (requestObject instanceof Representation)
+      {
+         request.setEntity((Representation) requestObject);
+         return true;
+      }
+
+      for (RequestWriter requestWriter : requestWriters)
+      {
+         if (requestWriter.writeRequest(requestObject, request))
+            return true;
+      }
+
+      return false;
+   }
+}
\ No newline at end of file
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/ResponseReaderDelegator.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/ResponseReaderDelegator.java
new file mode 100644
index 0000000..59c0866
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/ResponseReaderDelegator.java
@@ -0,0 +1,89 @@
+/*
+ *  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.polygene.library.rest.client;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ResourceBundle;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.library.rest.client.spi.ResponseReader;
+import org.restlet.Response;
+import org.restlet.representation.Representation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Delegates to a list of potential readers. Register readers on startup.
+ */
+public class ResponseReaderDelegator
+   implements ResponseReader, Initializable
+{
+   List<ResponseReader> responseReaders = new ArrayList<>();
+
+   @Structure
+   private Module module;
+
+   @Override
+   public void initialize()
+   {
+      Logger logger = LoggerFactory.getLogger( getClass() );
+
+      ResourceBundle defaultResponseReaders = ResourceBundle.getBundle( "org.apache.polygene.library.rest.client.rest-client" );
+
+      String responseReaderClasses = defaultResponseReaders.getString( "responsereaders" );
+      logger.info( "Using responsereaders:"+responseReaderClasses );
+      for (String className : responseReaderClasses.split( "," ))
+      {
+         try
+         {
+            Class readerClass = module.descriptor().classLoader().loadClass( className.trim() );
+            ResponseReader reader = (ResponseReader) module.newObject( readerClass );
+            registerResponseReader( reader );
+         } catch (ClassNotFoundException e)
+         {
+            logger.warn( "Could not register response reader "+className, e );
+         }
+      }
+   }
+
+   public void registerResponseReader( ResponseReader reader )
+   {
+      responseReaders.add( reader );
+   }
+
+   @Override
+   public Object readResponse( Response response, Class<?> resultType )
+   {
+      if (resultType.equals(Representation.class))
+         return response.getEntity();
+
+      for (ResponseReader responseReader : responseReaders)
+      {
+         Object result = responseReader.readResponse( response, resultType );
+         if (result != null)
+            return result;
+      }
+
+      return null;
+   }
+}
\ No newline at end of file
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/api/ContextResourceClient.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/api/ContextResourceClient.java
new file mode 100644
index 0000000..ba59930
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/api/ContextResourceClient.java
@@ -0,0 +1,443 @@
+/*
+ *  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.polygene.library.rest.client.api;
+
+import java.lang.reflect.ParameterizedType;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.library.rest.client.spi.NullResponseHandler;
+import org.apache.polygene.library.rest.client.spi.ResponseHandler;
+import org.apache.polygene.library.rest.client.spi.ResultHandler;
+import org.apache.polygene.library.rest.common.Resource;
+import org.apache.polygene.library.rest.common.link.Link;
+import org.apache.polygene.library.rest.common.link.LinksUtil;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.data.ChallengeResponse;
+import org.restlet.data.ChallengeScheme;
+import org.restlet.data.Method;
+import org.restlet.data.Reference;
+import org.restlet.data.Status;
+import org.restlet.representation.EmptyRepresentation;
+import org.restlet.resource.ResourceException;
+import org.restlet.security.User;
+
+/**
+ * Client-side context resources
+ */
+public class ContextResourceClient
+{
+    @Uses
+    private ContextResourceClientFactory contextResourceFactory;
+
+    @Uses
+    private Reference reference;
+
+    private Resource resource;
+
+    // Response handlers
+    private ResponseHandler errorHandler = NullResponseHandler.INSTANCE;
+    private ResponseHandler resourceHandler = NullResponseHandler.INSTANCE;
+    private ResponseHandler deleteHandler = NullResponseHandler.INSTANCE;
+    private Map<String, ResponseHandler> queryHandlers = new HashMap<>();
+    private Map<String, ResponseHandler> commandHandlers = new HashMap<>();
+    private Map<String, ResponseHandler> processingErrorHandlers = new HashMap<>();
+
+    // DSL for registering rules
+    public ContextResourceClient onError(ResponseHandler handler)
+    {
+        errorHandler = handler;
+        return this;
+    }
+
+    public <T> ContextResourceClient onResource( final ResultHandler<T> handler)
+    {
+        resourceHandler = new ResponseHandler()
+        {
+            @Override
+            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+            {
+                final Class<T> resultType = (Class<T>) Classes.RAW_CLASS.apply(( (ParameterizedType) handler.getClass().getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[0]);
+                T result = contextResourceFactory.readResponse( response, resultType );
+
+                if (result instanceof Resource)
+                {
+                    resource = (Resource) result;
+                }
+
+                return handler.handleResult( result, client );
+            }
+        };
+        return this;
+    }
+
+    public ContextResourceClient onQuery( String relation, ResponseHandler handler )
+    {
+        queryHandlers.put( relation, handler );
+        return this;
+    }
+
+    public <T> ContextResourceClient onQuery( String relation, final ResultHandler<T> handler
+    )
+    {
+        final Class<T> resultType = (Class<T>) Classes.RAW_CLASS.apply(( (ParameterizedType) handler.getClass().getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[0]);
+
+        queryHandlers.put( relation,  new ResponseHandler()
+        {
+            @Override
+            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+            {
+                T result = contextResourceFactory.readResponse( response, resultType );
+                return handler.handleResult( result, client );
+            }
+        });
+
+        return this;
+    }
+
+    public ContextResourceClient onCommand( String relation, ResponseHandler handler )
+    {
+        commandHandlers.put( relation, handler);
+        return this;
+    }
+
+    public <T> ContextResourceClient onCommand( String relation, final ResultHandler<T> handler )
+    {
+        final Class<T> resultType = (Class<T>) Classes.RAW_CLASS.apply(( (ParameterizedType) handler.getClass().getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[0]);
+
+        commandHandlers.put( relation,  new ResponseHandler()
+        {
+            @Override
+            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+            {
+                T result = contextResourceFactory.readResponse( response, resultType );
+                return handler.handleResult( result, client );
+            }
+        });
+
+        return this;
+    }
+
+    public ContextResourceClient onProcessingError( String relation, ResponseHandler handler )
+    {
+        processingErrorHandlers.put( relation, handler);
+        return this;
+    }
+
+    public <T> ContextResourceClient onProcessingError( String relation, final ResultHandler<T> handler)
+    {
+        final Class<T> resultType = (Class<T>) Classes.RAW_CLASS.apply(( (ParameterizedType) handler.getClass().getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[0]);
+
+        processingErrorHandlers.put( relation,  new ResponseHandler()
+        {
+            @Override
+            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+            {
+                T result = contextResourceFactory.readResponse( response, resultType );
+                return handler.handleResult( result, client );
+            }
+        });
+
+        return this;
+    }
+
+    public ContextResourceClient onDelete(ResponseHandler handler)
+    {
+        deleteHandler = handler;
+        return this;
+    }
+
+    public ContextResourceClientFactory getContextResourceClientFactory()
+    {
+        return contextResourceFactory;
+    }
+
+    public Reference getReference()
+    {
+        return reference;
+    }
+
+    public Resource getResource()
+    {
+        return resource;
+    }
+
+    public void start()
+    {
+        HandlerCommand command = refresh();
+        while (command != null)
+            command = command.execute( this );
+    }
+
+    // Callable from HandlerCommand
+    HandlerCommand refresh()
+    {
+        if (resourceHandler == null)
+            throw new IllegalStateException( "No handler set for resources" );
+
+        return invokeQuery( reference, null, resourceHandler, null );
+    }
+
+    HandlerCommand query( String relation, Object queryRequest, ResponseHandler handler, ResponseHandler processingErrorHandler )
+    {
+        return query( resource.query( relation ), queryRequest, handler, processingErrorHandler );
+    }
+
+    HandlerCommand query( Link link, Object queryRequest, ResponseHandler handler, ResponseHandler processingErrorHandler )
+    {
+        if (handler == null)
+            handler = queryHandlers.get( link.rel().get() );
+
+        if (handler == null)
+            throw new IllegalArgumentException( "No handler set for relation "+link.rel().get() );
+
+        if (processingErrorHandler == null)
+            processingErrorHandler = processingErrorHandlers.get( link.rel().get() );
+
+        Reference linkRef = new Reference(link.href().get());
+        if (linkRef.isRelative())
+            linkRef = new Reference( reference.toUri().toString() + link.href().get() );
+        return invokeQuery( linkRef, queryRequest, handler, processingErrorHandler );
+    }
+
+    private HandlerCommand invokeQuery( Reference ref, Object queryRequest, ResponseHandler resourceHandler, ResponseHandler processingErrorHandler )
+    {
+        Request request = new Request( Method.GET, ref );
+
+        if( queryRequest != null )
+        {
+            contextResourceFactory.writeRequest( request, queryRequest );
+        }
+
+        contextResourceFactory.updateQueryRequest( request );
+
+        User user = request.getClientInfo().getUser();
+        if ( user != null)
+            request.setChallengeResponse( new ChallengeResponse( ChallengeScheme.HTTP_BASIC, user.getName(), user.getSecret() ) );
+
+        Response response = new Response( request );
+
+        contextResourceFactory.getClient().handle( request, response );
+
+        if( response.getStatus().isSuccess() )
+        {
+            contextResourceFactory.updateCache( response );
+
+            return resourceHandler.handleResponse( response, this );
+        } else if (response.getStatus().isRedirection())
+        {
+            Reference redirectedTo = response.getLocationRef();
+            return invokeQuery( redirectedTo, queryRequest, resourceHandler, processingErrorHandler );
+        } else
+        {
+            if (response.getStatus().equals(Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY) && processingErrorHandler != null)
+            {
+                return processingErrorHandler.handleResponse( response, this );
+            } else
+            {
+                // TODO This needs to be expanded to allow custom handling of all the various cases
+                return errorHandler.handleResponse( response, this );
+            }
+        }
+    }
+
+    // Commands
+    HandlerCommand command( Link link, Object commandRequest, ResponseHandler handler, ResponseHandler processingErrorHandler )
+    {
+        if (handler == null)
+            handler = commandHandlers.get( link.rel().get() );
+
+        if (processingErrorHandler == null)
+            processingErrorHandler = processingErrorHandlers.get( link.rel().get() );
+
+        // Check if we should do POST or PUT
+        Method method;
+        if( LinksUtil.withClass( "idempotent" ).test( link ) )
+        {
+            method = Method.PUT;
+        }
+        else
+        {
+            method = Method.POST;
+        }
+
+        Reference ref = new Reference( reference.toUri().toString() + link.href().get() );
+        return invokeCommand( ref, method, commandRequest, handler, processingErrorHandler );
+    }
+
+    private HandlerCommand invokeCommand( Reference ref, Method method, Object requestObject, ResponseHandler responseHandler, ResponseHandler processingErrorHandler )
+    {
+        Request request = new Request( method, ref );
+
+        if (requestObject == null)
+            requestObject = new EmptyRepresentation();
+
+        contextResourceFactory.writeRequest( request, requestObject );
+
+        contextResourceFactory.updateCommandRequest( request );
+
+        User user = request.getClientInfo().getUser();
+        if ( user != null)
+            request.setChallengeResponse( new ChallengeResponse( ChallengeScheme.HTTP_BASIC, user.getName(), user.getSecret() ) );
+
+        Response response = new Response( request );
+        contextResourceFactory.getClient().handle( request, response );
+
+        try
+        {
+            if( response.getStatus().isSuccess() )
+            {
+                contextResourceFactory.updateCache( response );
+
+                if (responseHandler != null)
+                    return responseHandler.handleResponse( response, this );
+            }
+            else
+            {
+                if (response.getStatus().equals(Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY) && processingErrorHandler != null)
+                {
+                    return processingErrorHandler.handleResponse( response, this );
+                } else
+                {
+                    // TODO This needs to be expanded to allow custom handling of all the various cases
+                    return errorHandler.handleResponse( response, this );
+                }
+            }
+
+            return null; // No handler found
+        }
+        finally
+        {
+            try
+            {
+                response.getEntity().exhaust();
+            }
+            catch( Throwable e )
+            {
+                // Ignore
+            }
+        }
+    }
+
+    // Delete
+    public HandlerCommand delete( ResponseHandler responseHandler, ResponseHandler processingErrorHandler )
+        throws ResourceException
+    {
+        if (responseHandler == null)
+            responseHandler = deleteHandler;
+
+        Request request = new Request( Method.DELETE, new Reference( reference.toUri() ).toString() );
+        contextResourceFactory.updateCommandRequest( request );
+
+        int tries = 3;
+        while( true )
+        {
+            Response response = new Response( request );
+            try
+            {
+                contextResourceFactory.getClient().handle( request, response );
+                if( !response.getStatus().isSuccess() )
+                {
+                    return errorHandler.handleResponse( response, this );
+                }
+                else
+                {
+                    // Reset modification date
+                    contextResourceFactory.updateCache( response );
+
+                    return responseHandler.handleResponse( response, this );
+                }
+            }
+            catch( ResourceException e )
+            {
+                if( e.getStatus().equals( Status.CONNECTOR_ERROR_COMMUNICATION ) ||
+                    e.getStatus().equals( Status.CONNECTOR_ERROR_CONNECTION ) )
+                {
+                    if( tries == 0 )
+                    {
+                        throw e; // Give up
+                    }
+                    else
+                    {
+                        // Try again
+                        tries--;
+                        continue;
+                    }
+                }
+                else
+                {
+                    // Abort
+                    throw e;
+                }
+            }
+            finally
+            {
+                try
+                {
+                    response.getEntity().exhaust();
+                }
+                catch( Throwable e )
+                {
+                    // Ignore
+                }
+            }
+        }
+    }
+
+    // Browse to other resources
+    public synchronized ContextResourceClient newClient( Link link )
+    {
+        if( link == null )
+        {
+            throw new NullPointerException( "No link specified" );
+        }
+
+        return newClient( link.href().get() );
+    }
+
+    public synchronized ContextResourceClient newClient( String relativePath )
+    {
+        if( relativePath.startsWith( "http://" ) )
+        {
+            return contextResourceFactory.newClient( new Reference( relativePath ) );
+        }
+
+        Reference reference = this.reference.clone();
+        if( relativePath.startsWith( "/" ) )
+        {
+            reference.setPath( relativePath );
+        }
+        else
+        {
+            reference.setPath( reference.getPath() + relativePath );
+            reference = reference.normalize();
+        }
+
+        return contextResourceFactory.newClient( reference );
+    }
+
+    @Override
+    public String toString()
+    {
+        return reference.toString();
+    }
+}
\ No newline at end of file
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/api/ContextResourceClientFactory.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/api/ContextResourceClientFactory.java
new file mode 100644
index 0000000..fe6014c
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/api/ContextResourceClientFactory.java
@@ -0,0 +1,189 @@
+/*
+ *  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.polygene.library.rest.client.api;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.library.rest.client.ClientCache;
+import org.apache.polygene.library.rest.client.RequestWriterDelegator;
+import org.apache.polygene.library.rest.client.ResponseReaderDelegator;
+import org.apache.polygene.library.rest.client.spi.RequestWriter;
+import org.apache.polygene.library.rest.client.spi.ResponseHandler;
+import org.apache.polygene.library.rest.client.spi.ResponseReader;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.Uniform;
+import org.restlet.data.ClientInfo;
+import org.restlet.data.Form;
+import org.restlet.data.Language;
+import org.restlet.data.MediaType;
+import org.restlet.data.Preference;
+import org.restlet.data.Reference;
+
+/**
+ * Builder for UsecaseClient
+ */
+public class ContextResourceClientFactory
+{
+    @Structure
+    private Module module;
+
+    @Uses
+    @Optional
+    private ClientCache cache;
+
+    @Uses
+    private ResponseReaderDelegator readerDelegator;
+
+    @Uses
+    private RequestWriterDelegator requestWriterDelegator;
+
+    @Uses
+    private Uniform client;
+
+    private ClientInfo info = new ClientInfo();
+    private Form requestHeaders = new Form();
+
+    private ResponseHandler errorHandler;
+
+    public ContextResourceClient newClient( Reference reference )
+    {
+        ContextResourceClient contextResourceClient = module.newObject( ContextResourceClient.class, this, reference );
+        contextResourceClient.onError( errorHandler );
+        return contextResourceClient;
+    }
+
+    public void setAgent(String agent)
+    {
+        info.setAgent( agent );
+    }
+
+    public Form getCustomRequestHeaders()
+    {
+        return requestHeaders;
+    }
+
+    public void setAcceptedLanguages(Language... acceptedLanguages)
+    {
+        List<Preference<Language>> languages = new ArrayList<>();
+        for( Language acceptedLanguage : acceptedLanguages )
+        {
+            languages.add( new Preference<>());
+        }
+
+        info.setAcceptedLanguages( languages );
+
+    }
+
+    public void setAcceptedMediaTypes(MediaType... acceptedMediaTypes)
+    {
+        List<Preference<MediaType>> mediatypes = new ArrayList<>();
+        for( MediaType mediaType : acceptedMediaTypes )
+        {
+            mediatypes.add( new Preference<>( mediaType ) );
+        }
+
+        info.setAcceptedMediaTypes( mediatypes );
+    }
+
+    public ClientInfo getInfo()
+    {
+        return info;
+    }
+
+    public void setErrorHandler( ResponseHandler errorHandler )
+    {
+        this.errorHandler = errorHandler;
+    }
+
+    public ResponseHandler getErrorHandler()
+    {
+        return errorHandler;
+    }
+
+    // Internal
+    void updateCommandRequest( Request request )
+    {
+        request.setClientInfo( info );
+
+        // Update cache information
+        if( cache != null )
+        {
+            cache.updateCommandConditions( request );
+        }
+
+        // Add all custom headers
+        if (!requestHeaders.isEmpty())
+            request.getAttributes().put( "org.restlet.http.headers", requestHeaders );
+    }
+
+    void updateQueryRequest( Request request )
+    {
+        request.setClientInfo( info );
+
+        // Update cache information
+        if( cache != null )
+        {
+            cache.updateQueryConditions( request );
+        }
+
+    }
+
+    void updateCache( Response response )
+    {
+        if( cache != null )
+        {
+            cache.updateCache( response );
+        }
+    }
+
+    Uniform getClient()
+    {
+        return client;
+    }
+
+    public <T> T readResponse( Response response, Class<T> queryResult )
+    {
+        return (T) readerDelegator.readResponse( response, queryResult );
+    }
+
+    public void writeRequest( Request request, Object queryRequest )
+    {
+        if( !requestWriterDelegator.writeRequest( queryRequest, request ) )
+        {
+            throw new IllegalArgumentException( "Illegal query request type:" + queryRequest.getClass().getName() );
+        }
+    }
+
+    public void registerResponseReader(ResponseReader reader)
+    {
+        readerDelegator.registerResponseReader( reader );
+    }
+
+    public void registerRequestWriter(RequestWriter writer)
+    {
+        requestWriterDelegator.registerRequestWriter( writer );
+    }
+}
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/api/ErrorHandler.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/api/ErrorHandler.java
new file mode 100644
index 0000000..a6489c8
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/api/ErrorHandler.java
@@ -0,0 +1,73 @@
+/*
+ *  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.polygene.library.rest.client.api;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.Predicate;
+import org.apache.polygene.library.rest.client.spi.ResponseHandler;
+import org.restlet.Response;
+import org.restlet.data.Status;
+import org.restlet.resource.ResourceException;
+
+/**
+ * Implements a chained list of specification-&gt;handler. Add the most specific handlers first, and the most generic last.
+ */
+public class ErrorHandler
+    implements ResponseHandler
+{
+    public static Predicate<Response> AUTHENTICATION_REQUIRED = item ->
+        item.getStatus().equals( Status.CLIENT_ERROR_UNAUTHORIZED );
+
+    public static Predicate<Response> RECOVERABLE_ERROR = item -> item.getStatus().isRecoverableError();
+
+    LinkedHashMap<Predicate<Response>, ResponseHandler> handlers = new LinkedHashMap<>();
+
+    public ErrorHandler()
+    {
+    }
+
+    public ErrorHandler onError(Predicate<Response> responseSpecification, ResponseHandler handler)
+    {
+        handlers.put( responseSpecification, handler );
+        return this;
+    }
+
+    public ErrorHandler onError(ResponseHandler handler)
+    {
+        handlers.put( item -> true, handler );
+        return this;
+    }
+
+    @Override
+    public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+    {
+        for( Map.Entry<Predicate<Response>, ResponseHandler> specificationResponseHandlerEntry : handlers.entrySet() )
+        {
+            if (specificationResponseHandlerEntry.getKey().test( response ))
+            {
+                return specificationResponseHandlerEntry.getValue().handleResponse( response, client );
+            }
+        }
+
+        // No handlers, throw exception
+        throw new ResourceException( response.getStatus() );
+    }
+}
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/api/HandlerCommand.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/api/HandlerCommand.java
new file mode 100644
index 0000000..8790fd8
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/api/HandlerCommand.java
@@ -0,0 +1,218 @@
+/*
+ *  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.polygene.library.rest.client.api;
+
+import java.lang.reflect.ParameterizedType;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.library.rest.client.spi.ResponseHandler;
+import org.apache.polygene.library.rest.client.spi.ResultHandler;
+import org.apache.polygene.library.rest.common.link.Link;
+import org.restlet.Response;
+
+/**
+ * TODO
+ */
+public abstract class HandlerCommand
+{
+    public static HandlerCommand refresh()
+    {
+        return new RefreshCommand();
+    }
+
+    public static HandlerCommand query(String relation)
+    {
+        return new QueryCommand( relation, null);
+    }
+
+    public static HandlerCommand query(String relation, Object requestObject)
+    {
+        return new QueryCommand( relation, requestObject);
+    }
+
+    public static HandlerCommand query(Link relation)
+    {
+        return new QueryLinkCommand( relation );
+    }
+
+    public static HandlerCommand command(String relation)
+    {
+        return new CommandRelationCommand( relation, null );
+    }
+
+    public static HandlerCommand command(String relation, Object requestObject)
+    {
+        return new CommandRelationCommand( relation, requestObject );
+    }
+
+    public static HandlerCommand command(Link link)
+    {
+        return new CommandLinkCommand( link, null );
+    }
+
+    public static HandlerCommand command(Link link, Object requestObject)
+    {
+        return new CommandLinkCommand( link, requestObject );
+    }
+
+    public static HandlerCommand delete()
+    {
+        return new DeleteCommand();
+    }
+
+    protected ResponseHandler responseHandler;
+    protected ResponseHandler processingErrorHandler;
+
+    public HandlerCommand onSuccess(ResponseHandler responseHandler)
+    {
+        this.responseHandler = responseHandler;
+        return this;
+    }
+
+    public <T> HandlerCommand onSuccess(final ResultHandler<T> resultHandler)
+    {
+        final Class<T> resultType = (Class<T>) Classes.RAW_CLASS.apply(( (ParameterizedType) resultHandler.getClass().getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[0]);
+        this.responseHandler = new ResponseHandler()
+        {
+            @Override
+            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+            {
+                T result = client.getContextResourceClientFactory().readResponse( response, resultType );
+                return resultHandler.handleResult( result, client );
+            }
+        };
+        return this;
+    }
+
+    public HandlerCommand onProcessingError(ResponseHandler processingErrorHandler)
+    {
+        this.processingErrorHandler = processingErrorHandler;
+        return this;
+    }
+
+    public <T> HandlerCommand onProcessingError(final ResultHandler<T> resultHandler)
+    {
+        final Class<T> resultType = (Class<T>) Classes.RAW_CLASS.apply(( (ParameterizedType) resultHandler.getClass().getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[0]);
+        this.processingErrorHandler = ( response, client ) ->
+        {
+            T result = client.getContextResourceClientFactory().readResponse( response, resultType );
+            return resultHandler.handleResult( result, client );
+        };
+        return this;
+    }
+
+    abstract HandlerCommand execute( ContextResourceClient client);
+
+    private static class RefreshCommand
+        extends HandlerCommand
+    {
+        @Override
+        HandlerCommand execute( ContextResourceClient client )
+        {
+            return client.refresh();
+        }
+    }
+
+    private static class QueryCommand
+        extends HandlerCommand
+    {
+        private String relation;
+        private Object requestObject;
+
+        private QueryCommand( String relation, Object requestObject)
+        {
+            this.relation = relation;
+            this.requestObject = requestObject;
+        }
+
+        @Override
+        HandlerCommand execute( ContextResourceClient client )
+        {
+            Link link = client.getResource().query( relation );
+            return client.query( link, requestObject, responseHandler, processingErrorHandler );
+        }
+    }
+
+    private static class QueryLinkCommand
+        extends HandlerCommand
+    {
+        private Link link;
+
+        private QueryLinkCommand( Link link)
+        {
+            this.link = link;
+        }
+
+        @Override
+        HandlerCommand execute( ContextResourceClient client )
+        {
+            return client.query( link, null, responseHandler, processingErrorHandler );
+        }
+    }
+
+    private static class CommandRelationCommand
+        extends HandlerCommand
+    {
+        private String relation;
+        private Object requestObject;
+
+        private CommandRelationCommand( String relation, Object requestObject )
+        {
+            this.relation = relation;
+            this.requestObject = requestObject;
+        }
+
+        @Override
+        HandlerCommand execute( ContextResourceClient client )
+        {
+            Link link = client.getResource().command( relation );
+            return client.command( link, requestObject, responseHandler, processingErrorHandler );
+        }
+    }
+
+    private static class CommandLinkCommand
+        extends HandlerCommand
+    {
+        private Link link;
+        private Object requestObject;
+
+        private CommandLinkCommand( Link link, Object requestObject )
+        {
+            this.link = link;
+            this.requestObject = requestObject;
+        }
+
+        @Override
+        HandlerCommand execute( ContextResourceClient client )
+        {
+            return client.command( link, requestObject, responseHandler, processingErrorHandler );
+        }
+    }
+
+    private static class DeleteCommand
+        extends HandlerCommand
+    {
+        @Override
+        HandlerCommand execute( ContextResourceClient client )
+        {
+            return client.delete(responseHandler, processingErrorHandler);
+        }
+    }
+
+}
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/api/package.html b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/api/package.html
new file mode 100644
index 0000000..46e6158
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/api/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ReST Client API.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/package.html b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/package.html
new file mode 100644
index 0000000..43852b9
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ReST Client Library.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/requestwriter/FormRequestWriter.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/requestwriter/FormRequestWriter.java
new file mode 100644
index 0000000..518a6f3
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/requestwriter/FormRequestWriter.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.polygene.library.rest.client.requestwriter;
+
+import org.apache.polygene.library.rest.client.spi.RequestWriter;
+import org.restlet.Request;
+import org.restlet.data.CharacterSet;
+import org.restlet.data.Form;
+import org.restlet.data.Method;
+import org.restlet.resource.ResourceException;
+
+/**
+ * Request writer for Form. Transfers form state to request reference as query parameters
+ */
+public class FormRequestWriter
+   implements RequestWriter
+{
+    @Override
+   public boolean writeRequest(Object requestObject, Request request) throws ResourceException
+   {
+      if (requestObject instanceof Form)
+      {
+         // Form as query parameters
+         if (request.getMethod().equals(Method.GET))
+            request.getResourceRef().setQuery(((Form)requestObject).getQueryString());
+         else
+            request.setEntity(((Form)requestObject).getWebRepresentation(CharacterSet.UTF_8));
+
+         return true;
+      }
+
+      return false;
+   }
+}
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/requestwriter/ValueCompositeRequestWriter.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/requestwriter/ValueCompositeRequestWriter.java
new file mode 100644
index 0000000..8eebc7a
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/requestwriter/ValueCompositeRequestWriter.java
@@ -0,0 +1,111 @@
+/*
+ *  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.polygene.library.rest.client.requestwriter;
+
+import java.io.IOException;
+import java.io.Writer;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.service.qualifier.Tagged;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.library.rest.client.spi.RequestWriter;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.restlet.Request;
+import org.restlet.data.CharacterSet;
+import org.restlet.data.MediaType;
+import org.restlet.data.Method;
+import org.restlet.data.Reference;
+import org.restlet.representation.WriterRepresentation;
+import org.restlet.resource.ResourceException;
+
+/**
+ * Request writer for ValueComposites. Transfers value state to request reference as query parameters or JSON entity
+ */
+public class ValueCompositeRequestWriter
+   implements RequestWriter
+{
+   @Structure
+   private PolygeneSPI spi;
+
+   @Service
+   @Tagged( Serialization.Format.JSON )
+   private Serializer serializer;
+
+    @Override
+   public boolean writeRequest(Object requestObject, Request request) throws ResourceException
+   {
+      if (requestObject instanceof ValueComposite)
+      {
+         // Value as parameter
+         final ValueComposite valueObject = (ValueComposite) requestObject;
+         if (request.getMethod().equals(Method.GET))
+         {
+            StateHolder holder = spi.stateOf( valueObject );
+            final ValueDescriptor descriptor = spi.valueDescriptorFor( valueObject );
+
+             final Reference ref = request.getResourceRef();
+             ref.setQuery( null );
+             descriptor.state().properties().forEach( propertyDescriptor -> {
+                 try
+                 {
+                     Object value = holder.propertyFor( propertyDescriptor.accessor() ).get();
+                     String param;
+                     if( value == null )
+                     {
+                         param = null;
+                     }
+                     else
+                     {
+                         param = serializer.serialize( value );
+                     }
+                     ref.addQueryParameter( propertyDescriptor.qualifiedName().name(), param );
+                 }
+                 catch( SerializationException e )
+                 {
+                     throw new ResourceException( e );
+                 }
+             } );
+         }
+         else
+         {
+            request.setEntity(new WriterRepresentation( MediaType.APPLICATION_JSON )
+            {
+                @Override
+                public void write( Writer writer )
+                    throws IOException
+                {
+                   setCharacterSet( CharacterSet.UTF_8 );
+                   serializer.serialize( writer, valueObject );
+                }
+            });
+         }
+
+         return true;
+      }
+
+      return false;
+   }
+}
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/requestwriter/package.html b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/requestwriter/package.html
new file mode 100644
index 0000000..7f1800e
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/requestwriter/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ReST Client Request Writers.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/responsereader/DefaultResponseReader.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/responsereader/DefaultResponseReader.java
new file mode 100644
index 0000000..ff8060b
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/responsereader/DefaultResponseReader.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.library.rest.client.responsereader;
+
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.library.rest.client.spi.ResponseReader;
+import org.apache.polygene.spi.serialization.JsonDeserializer;
+import org.restlet.Response;
+import org.restlet.data.MediaType;
+import org.restlet.resource.ResourceException;
+
+/**
+ * ResponseReader for simple types from JSON
+ */
+public class DefaultResponseReader
+    implements ResponseReader
+{
+    @Structure
+    private ModuleDescriptor module;
+
+    @Service
+    private JsonDeserializer jsonDeserializer;
+
+    @Override
+    public Object readResponse( Response response, Class<?> resultType ) throws ResourceException
+    {
+        if( MediaType.APPLICATION_JSON.equals( response.getEntity().getMediaType() ) )
+        {
+            if( resultType.equals( String.class ) || Number.class.isAssignableFrom( resultType ) )
+            {
+                try
+                {
+                    return jsonDeserializer.deserialize( module, resultType, response.getEntityAsText() );
+                }
+                catch( Exception e )
+                {
+                    throw new ResourceException( e );
+                }
+            }
+        }
+        return null;
+    }
+}
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/responsereader/JSONResponseReader.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/responsereader/JSONResponseReader.java
new file mode 100644
index 0000000..71d2c14
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/responsereader/JSONResponseReader.java
@@ -0,0 +1,93 @@
+/*
+ *  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.polygene.library.rest.client.responsereader;
+
+import java.io.IOException;
+import javax.json.JsonException;
+import javax.json.JsonObject;
+import javax.json.JsonReader;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ValueCompositeType;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.library.rest.client.spi.ResponseReader;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.spi.serialization.JsonDeserializer;
+import org.restlet.Response;
+import org.restlet.data.Form;
+import org.restlet.data.MediaType;
+import org.restlet.resource.ResourceException;
+
+/**
+ * JAVADOC
+ */
+public class JSONResponseReader
+    implements ResponseReader
+{
+    @Structure
+    private ModuleDescriptor module;
+
+    @Service
+    private JsonDeserializer jsonDeserializer;
+
+    @Service
+    private JavaxJsonFactories jsonFactories;
+
+    @Override
+    public Object readResponse( Response response, Class<?> resultType )
+    {
+        if( response.getEntity().getMediaType().equals( MediaType.APPLICATION_JSON ) )
+        {
+            if( ValueComposite.class.isAssignableFrom( resultType ) )
+            {
+                String jsonValue = response.getEntityAsText();
+                ValueCompositeType valueType = module.valueDescriptor( resultType.getName() ).valueType();
+                return jsonDeserializer.deserialize( module, valueType, jsonValue );
+            }
+            else if( resultType.equals( Form.class ) )
+            {
+                try( JsonReader reader = jsonFactories.readerFactory()
+                                                      .createReader( response.getEntity().getReader() ) )
+                {
+                    JsonObject jsonObject = reader.readObject();
+                    Form form = new Form();
+                    jsonObject.forEach(
+                        ( key, value ) ->
+                        {
+                            String valueString = value.getValueType() == JsonValue.ValueType.STRING
+                                                 ? ( (JsonString) value ).getString()
+                                                 : value.toString();
+                            form.set( key, valueString );
+                        } );
+                    return form;
+                }
+                catch( IOException | JsonException e )
+                {
+                    throw new ResourceException( e );
+                }
+            }
+        }
+        return null;
+    }
+}
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/responsereader/TableResponseReader.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/responsereader/TableResponseReader.java
new file mode 100644
index 0000000..7d9cb36
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/responsereader/TableResponseReader.java
@@ -0,0 +1,123 @@
+/*
+ *  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.polygene.library.rest.client.responsereader;
+
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonReader;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.library.rest.client.spi.ResponseReader;
+import org.apache.polygene.library.rest.common.table.Table;
+import org.apache.polygene.library.rest.common.table.TableBuilder;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.spi.serialization.JsonDeserializer;
+import org.restlet.Response;
+import org.restlet.data.MediaType;
+import org.restlet.data.Status;
+import org.restlet.resource.ResourceException;
+
+/**
+ * JAVADOC
+ */
+public class TableResponseReader
+    implements ResponseReader
+{
+    @Structure
+    private Module module;
+
+    @Service
+    private JsonDeserializer jsonDeserializer;
+
+    @Service
+    private JavaxJsonFactories jsonFactories;
+
+    @Override
+    public Object readResponse( Response response, Class<?> resultType ) throws ResourceException
+    {
+        if( response.getEntity().getMediaType().equals( MediaType.APPLICATION_JSON )
+            && Table.class.isAssignableFrom( resultType ) )
+        {
+            try( JsonReader reader = jsonFactories.readerFactory()
+                                                  .createReader( response.getEntity().getReader() ) )
+            {
+                JsonObject jsonObject = reader.readObject();
+                JsonObject table = jsonObject.getJsonObject( "table" );
+
+                TableBuilder builder = new TableBuilder( module );
+
+                JsonArray cols = table.getJsonArray( "cols" );
+                cols.getValuesAs( JsonObject.class ).forEach(
+                    col -> builder.column( col.getString( "id", null ),
+                                           col.getString( "label" ),
+                                           col.getString( "type" ) ) );
+
+                table.getJsonArray( "rows" ).getValuesAs( JsonObject.class ).forEach(
+                    row ->
+                    {
+                        builder.row();
+                        List<JsonObject> cells = row.getJsonArray( "c" ).getValuesAs( JsonObject.class );
+                        for( int idx = 0; idx < cells.size(); idx++ )
+                        {
+                            JsonObject cell = cells.get( idx );
+                            JsonValue jsonValue = cell.get( "v" );
+                            String formatted = cell.getString( "f", null );
+                            String type = cols.getJsonObject( idx ).getString( "type" );
+                            Object value;
+                            switch( type )
+                            {
+                                case "datetime":
+                                    value = ZonedDateTime.parse( ( (JsonString) jsonValue ).getString() );
+                                    break;
+                                case "date":
+                                    value = DateTimeFormatter.ofPattern( "yyyy-MM-dd" )
+                                                             .parse( ( (JsonString) jsonValue ).getString() );
+                                    break;
+                                case "timeofday":
+                                    value = DateTimeFormatter.ofPattern( "HH:mm:ss" )
+                                                             .parse( ( (JsonString) jsonValue ).getString() );
+                                    break;
+                                default:
+                                    value = jsonValue.getValueType() == JsonValue.ValueType.STRING
+                                            ? ( (JsonString) jsonValue ).getString()
+                                            : jsonValue.toString();
+                            }
+                            builder.cell( value, formatted );
+                        }
+                        builder.endRow();
+                    }
+                );
+                return builder.newTable();
+            }
+            catch( Exception e )
+            {
+                throw new ResourceException( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY, e );
+            }
+        }
+        return null;
+    }
+}
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/responsereader/package.html b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/responsereader/package.html
new file mode 100644
index 0000000..2c5419d
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/responsereader/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ReST Client Response Readers.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/NullResponseHandler.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/NullResponseHandler.java
new file mode 100644
index 0000000..1186db6
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/NullResponseHandler.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.rest.client.spi;
+
+import org.apache.polygene.library.rest.client.api.ContextResourceClient;
+import org.apache.polygene.library.rest.client.api.HandlerCommand;
+import org.restlet.Response;
+
+/**
+ */
+public class NullResponseHandler
+   implements ResponseHandler
+{
+    public static NullResponseHandler INSTANCE = new NullResponseHandler();
+
+    @Override
+    public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+    {
+        return null;
+    }
+}
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/RequestWriter.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/RequestWriter.java
new file mode 100644
index 0000000..3433e98
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/RequestWriter.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.rest.client.spi;
+
+import org.restlet.Request;
+import org.restlet.resource.ResourceException;
+
+/**
+ * JAVADOC
+ */
+public interface RequestWriter
+{
+   /**
+    * Write the given request object to the request.
+    *
+    * @param requestObject The object to be written.
+    * @param request The Request destination of the requestObject
+    * @return true if the object was written to the Request instance, false if handler can not write the object.
+    * @throws org.restlet.resource.ResourceException
+    */
+   boolean writeRequest(Object requestObject, Request request)
+      throws ResourceException;
+}
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/ResponseHandler.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/ResponseHandler.java
new file mode 100644
index 0000000..1f8fb8f
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/ResponseHandler.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.library.rest.client.spi;
+
+import org.apache.polygene.library.rest.client.api.ContextResourceClient;
+import org.apache.polygene.library.rest.client.api.HandlerCommand;
+import org.restlet.Response;
+
+/**
+ * Implement this interface and pass an instance to the CommandQueryClient. It will be responsible
+ * for handling the responses of PUT/POST/DELETE calls.
+ */
+public interface ResponseHandler
+{
+   HandlerCommand handleResponse( Response response, ContextResourceClient client);
+}
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/ResponseReader.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/ResponseReader.java
new file mode 100644
index 0000000..abbd777
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/ResponseReader.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.rest.client.spi;
+
+import org.restlet.Response;
+import org.restlet.resource.ResourceException;
+
+/**
+ * JAVADOC
+ */
+public interface ResponseReader
+{
+   Object readResponse(Response response, Class<?> resultType) throws ResourceException;
+}
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/ResultHandler.java b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/ResultHandler.java
new file mode 100644
index 0000000..a799f4f
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/ResultHandler.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.rest.client.spi;
+
+import org.apache.polygene.library.rest.client.api.ContextResourceClient;
+import org.apache.polygene.library.rest.client.api.HandlerCommand;
+
+/**
+ * Implement this interface to handle deserialized results from CRC
+ */
+public interface ResultHandler<T>
+{
+   HandlerCommand handleResult( T result, ContextResourceClient client);
+}
diff --git a/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/package.html b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/package.html
new file mode 100644
index 0000000..dc62395
--- /dev/null
+++ b/libraries/rest-client/src/main/java/org/apache/polygene/library/rest/client/spi/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ReST Client SPI.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/ClientAssembler.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/ClientAssembler.java
deleted file mode 100644
index c1ea6dc..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/ClientAssembler.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.client;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.rest.client.api.ContextResourceClient;
-import org.qi4j.library.rest.client.api.ContextResourceClientFactory;
-import org.qi4j.library.rest.client.requestwriter.FormRequestWriter;
-import org.qi4j.library.rest.client.requestwriter.ValueCompositeRequestWriter;
-import org.qi4j.library.rest.client.responsereader.DefaultResponseReader;
-import org.qi4j.library.rest.client.responsereader.JSONResponseReader;
-import org.qi4j.library.rest.client.responsereader.TableResponseReader;
-
-/**
- * JAVADOC
- */
-public class ClientAssembler
-   implements Assembler
-{
-    @Override
-   public void assemble( ModuleAssembly module ) throws AssemblyException
-   {
-      module.objects( ContextResourceClientFactory.class, ContextResourceClient.class ).visibleIn( Visibility.application );
-
-      module.objects( ResponseReaderDelegator.class,
-            DefaultResponseReader.class,
-            JSONResponseReader.class,
-            TableResponseReader.class ).visibleIn( Visibility.application );
-
-      module.objects(RequestWriterDelegator.class,
-            FormRequestWriter.class,
-            ValueCompositeRequestWriter.class).visibleIn(Visibility.application);
-   }
-}
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/ClientCache.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/ClientCache.java
deleted file mode 100644
index ce3dc89..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/ClientCache.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.client;
-
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import org.restlet.Request;
-import org.restlet.Response;
-import org.restlet.data.Method;
-import org.restlet.data.Reference;
-import org.restlet.data.Tag;
-
-/**
- * Cache for the ContextResourceClient. This is primarily used to keep track of ETags and lastmodified timestamps for now.
- */
-public class ClientCache
-{
-   Map<String, CacheInfo> identityToTimestamp = new HashMap<String, CacheInfo>( );
-   Map<String, String> pathToIdentity = new HashMap<String, String>( );
-
-   public void updateCache( Response response)
-   {
-      if (response.getRequest().getMethod().equals( Method.DELETE ))
-      {
-         String path = getIdentityPath( response.getRequest().getResourceRef() );
-         String id = pathToIdentity.get( path );
-         if (id != null)
-         {
-            // Clear anything related to this id from cache
-            identityToTimestamp.remove( id );
-            Iterator<Map.Entry<String, String>> paths = pathToIdentity.entrySet().iterator();
-            while (paths.hasNext())
-            {
-               Map.Entry<String, String> entry = paths.next();
-               if (entry.getValue().equals( id ))
-                  paths.remove();
-            }
-         }
-      } else if (response.getRequest().getMethod().equals( Method.PUT ) || response.getRequest().getMethod().equals( Method.POST ))
-      {
-         Tag tag = response.getEntity().getTag();
-         if (tag != null)
-         {
-            Reference ref = response.getRequest().getResourceRef().clone();
-
-            CacheInfo value = new CacheInfo( response.getEntity().getModificationDate(), tag, ref );
-            identityToTimestamp.put( value.getEntity(), value );
-
-            String path = getIdentityPath( ref );
-
-            pathToIdentity.put( path, value.getEntity() );
-
-//            LoggerFactory.getLogger( ClientCache.class ).info( "Update:"+value.getEntity()+" ("+ref.toString()+") -> "+value.getLastModified() );
-         }
-      } else
-      {
-          // TODO GET caching goes here
-      }
-   }
-
-   public void updateQueryConditions( Request request)
-   {
-      String identity = pathToIdentity.get( getIdentityPath( request.getResourceRef() ));
-      if (identity != null)
-      {
-         CacheInfo cacheInfo = identityToTimestamp.get( identity );
-         if (cacheInfo != null)
-         {
-//            LoggerFactory.getLogger( ClientCache.class ).info( "Send:  "+cacheInfo.getEntity()+" ("+request.getMethod().getName()+":"+request.getResourceRef()+") -> "+cacheInfo.getLastModified() );
-            request.getConditions().setModifiedSince( cacheInfo.getLastModified() );
-         }
-      }
-   }
-
-   public void updateCommandConditions( Request request)
-   {
-      String identity = pathToIdentity.get( getIdentityPath( request.getResourceRef() ));
-      if (identity != null)
-      {
-         CacheInfo cacheInfo = identityToTimestamp.get( identity );
-         if (cacheInfo != null)
-         {
-//            LoggerFactory.getLogger( ClientCache.class ).info( "Send:  "+cacheInfo.getEntity()+" ("+request.getMethod().getName()+":"+request.getResourceRef()+") -> "+cacheInfo.getLastModified() );
-            request.getConditions().setUnmodifiedSince( cacheInfo.getLastModified() );
-         }
-      }
-   }
-
-   private String getIdentityPath( Reference ref )
-   {
-      String path = ref.getPath();
-      if (!path.endsWith( "/" ))
-         path = path.substring( 0, path.lastIndexOf('/' )+1);
-      return path;
-   }
-
-   static class CacheInfo
-   {
-      private Reference ref;
-      private Date lastModified;
-      private Tag tag;
-      private String entity;
-
-      CacheInfo( Date lastModified, Tag tag, Reference ref )
-      {
-         this.lastModified = lastModified;
-         this.tag = tag;
-         this.ref = ref;
-         entity = tag.getName().split( "/" )[0];
-      }
-
-      public Reference getRef()
-      {
-         return ref;
-      }
-
-      public Date getLastModified()
-      {
-         return lastModified;
-      }
-
-      public Tag getTag()
-      {
-         return tag;
-      }
-
-      public String getEntity()
-      {
-         return entity;
-      }
-   }
-}
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/RequestWriterDelegator.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/RequestWriterDelegator.java
deleted file mode 100644
index 1073b2b..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/RequestWriterDelegator.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.client;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ResourceBundle;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Initializable;
-import org.qi4j.api.mixin.InitializationException;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.client.spi.RequestWriter;
-import org.restlet.Request;
-import org.restlet.data.Method;
-import org.restlet.representation.EmptyRepresentation;
-import org.restlet.representation.Representation;
-import org.restlet.resource.ResourceException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Delegates to a list of potential writers. Register writers on startup.
- */
-public class RequestWriterDelegator
-   implements RequestWriter, Initializable
-{
-   List<RequestWriter> requestWriters = new ArrayList<RequestWriter>( );
-
-   @Structure
-   private Module module;
-
-    @Override
-   public void initialize() throws InitializationException
-   {
-      Logger logger = LoggerFactory.getLogger( getClass() );
-
-      ResourceBundle defaultRequestWriters = ResourceBundle.getBundle( "org.qi4j.library.rest.client.rest-client" );
-
-      String requestWriterClasses = defaultRequestWriters.getString( "requestwriters" );
-      logger.info( "Using request writers:"+requestWriterClasses );
-      for (String className : requestWriterClasses.split( "," ))
-      {
-         try
-         {
-            Class writerClass = module.classLoader().loadClass( className.trim() );
-            RequestWriter requestWriter = (RequestWriter) module.newObject( writerClass );
-            registerRequestWriter(requestWriter);
-         } catch (ClassNotFoundException e)
-         {
-            logger.warn( "Could not register request writer "+className, e );
-         }
-      }
-   }
-
-   public void registerRequestWriter(RequestWriter writer)
-   {
-      requestWriters.add( writer );
-   }
-
-    @Override
-   public boolean writeRequest(Object requestObject, Request request) throws ResourceException
-   {
-      if (requestObject == null)
-      {
-         if (!Method.GET.equals(request.getMethod()))
-            request.setEntity(new EmptyRepresentation());
-
-         return true;
-      }
-
-      if (requestObject instanceof Representation)
-      {
-         request.setEntity((Representation) requestObject);
-         return true;
-      }
-
-      for (RequestWriter requestWriter : requestWriters)
-      {
-         if (requestWriter.writeRequest(requestObject, request))
-            return true;
-      }
-
-      return false;
-   }
-}
\ No newline at end of file
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/ResponseReaderDelegator.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/ResponseReaderDelegator.java
deleted file mode 100644
index ad62990..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/ResponseReaderDelegator.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.client;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ResourceBundle;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Initializable;
-import org.qi4j.api.mixin.InitializationException;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.client.spi.ResponseReader;
-import org.restlet.Response;
-import org.restlet.representation.Representation;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Delegates to a list of potential readers. Register readers on startup.
- */
-public class ResponseReaderDelegator
-   implements ResponseReader, Initializable
-{
-   List<ResponseReader> responseReaders = new ArrayList<ResponseReader>( );
-
-   @Structure
-   private Module module;
-
-   @Override
-   public void initialize() throws InitializationException
-   {
-      Logger logger = LoggerFactory.getLogger( getClass() );
-
-      ResourceBundle defaultResponseReaders = ResourceBundle.getBundle( "org.qi4j.library.rest.client.rest-client" );
-
-      String responseReaderClasses = defaultResponseReaders.getString( "responsereaders" );
-      logger.info( "Using responsereaders:"+responseReaderClasses );
-      for (String className : responseReaderClasses.split( "," ))
-      {
-         try
-         {
-            Class readerClass = module.classLoader().loadClass( className.trim() );
-            ResponseReader reader = (ResponseReader) module.newObject( readerClass );
-            registerResponseReader( reader );
-         } catch (ClassNotFoundException e)
-         {
-            logger.warn( "Could not register response reader "+className, e );
-         }
-      }
-   }
-
-   public void registerResponseReader( ResponseReader reader )
-   {
-      responseReaders.add( reader );
-   }
-
-   @Override
-   public Object readResponse( Response response, Class<?> resultType )
-   {
-      if (resultType.equals(Representation.class))
-         return response.getEntity();
-
-      for (ResponseReader responseReader : responseReaders)
-      {
-         Object result = responseReader.readResponse( response, resultType );
-         if (result != null)
-            return result;
-      }
-
-      return null;
-   }
-}
\ No newline at end of file
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/api/ContextResourceClient.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/api/ContextResourceClient.java
deleted file mode 100644
index 053ce6d..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/api/ContextResourceClient.java
+++ /dev/null
@@ -1,488 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.client.api;
-
-import java.io.IOException;
-import java.lang.reflect.ParameterizedType;
-import java.util.HashMap;
-import java.util.Map;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.util.Classes;
-import org.qi4j.library.rest.client.spi.NullResponseHandler;
-import org.qi4j.library.rest.client.spi.ResponseHandler;
-import org.qi4j.library.rest.client.spi.ResultHandler;
-import org.qi4j.library.rest.common.Resource;
-import org.qi4j.library.rest.common.link.Link;
-import org.qi4j.library.rest.common.link.LinksUtil;
-import org.restlet.Request;
-import org.restlet.Response;
-import org.restlet.data.ChallengeResponse;
-import org.restlet.data.ChallengeScheme;
-import org.restlet.data.MediaType;
-import org.restlet.data.Method;
-import org.restlet.data.Reference;
-import org.restlet.data.Status;
-import org.restlet.representation.EmptyRepresentation;
-import org.restlet.representation.ObjectRepresentation;
-import org.restlet.resource.ResourceException;
-import org.restlet.security.User;
-
-/**
- * Client-side context resources
- */
-public class ContextResourceClient
-{
-    @Uses
-    private ContextResourceClientFactory contextResourceFactory;
-
-    @Uses
-    private Reference reference;
-
-    private Resource resource;
-
-    // Response handlers
-    private ResponseHandler errorHandler = NullResponseHandler.INSTANCE;
-    private ResponseHandler resourceHandler = NullResponseHandler.INSTANCE;
-    private ResponseHandler deleteHandler = NullResponseHandler.INSTANCE;
-    private Map<String, ResponseHandler> queryHandlers = new HashMap<String, ResponseHandler>(  );
-    private Map<String, ResponseHandler> commandHandlers = new HashMap<String, ResponseHandler>(  );
-    private Map<String, ResponseHandler> processingErrorHandlers = new HashMap<String, ResponseHandler>();
-
-    // DSL for registering rules
-    public ContextResourceClient onError(ResponseHandler handler)
-    {
-        errorHandler = handler;
-        return this;
-    }
-
-    public <T> ContextResourceClient onResource( final ResultHandler<T> handler)
-    {
-        resourceHandler = new ResponseHandler()
-        {
-            @Override
-            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-            {
-                final Class<T> resultType = (Class<T>) Classes.RAW_CLASS.map(( (ParameterizedType) handler.getClass().getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[0]);
-                T result = contextResourceFactory.readResponse( response, resultType );
-
-                if (result instanceof Resource)
-                {
-                    resource = (Resource) result;
-                }
-
-                return handler.handleResult( result, client );
-            }
-        };
-        return this;
-    }
-
-    public ContextResourceClient onQuery( String relation, ResponseHandler handler )
-    {
-        queryHandlers.put( relation, handler );
-        return this;
-    }
-
-    public <T> ContextResourceClient onQuery( String relation, final ResultHandler<T> handler
-    )
-    {
-        final Class<T> resultType = (Class<T>) Classes.RAW_CLASS.map(( (ParameterizedType) handler.getClass().getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[0]);
-
-        queryHandlers.put( relation,  new ResponseHandler()
-        {
-            @Override
-            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-            {
-                T result = contextResourceFactory.readResponse( response, resultType );
-                return handler.handleResult( result, client );
-            }
-        });
-
-        return this;
-    }
-
-    public ContextResourceClient onCommand( String relation, ResponseHandler handler )
-    {
-        commandHandlers.put( relation, handler);
-        return this;
-    }
-
-    public <T> ContextResourceClient onCommand( String relation, final ResultHandler<T> handler )
-    {
-        final Class<T> resultType = (Class<T>) Classes.RAW_CLASS.map(( (ParameterizedType) handler.getClass().getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[0]);
-
-        commandHandlers.put( relation,  new ResponseHandler()
-        {
-            @Override
-            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-            {
-                T result = contextResourceFactory.readResponse( response, resultType );
-                return handler.handleResult( result, client );
-            }
-        });
-
-        return this;
-    }
-
-    public ContextResourceClient onProcessingError( String relation, ResponseHandler handler )
-    {
-        processingErrorHandlers.put( relation, handler);
-        return this;
-    }
-
-    public <T> ContextResourceClient onProcessingError( String relation, final ResultHandler<T> handler)
-    {
-        final Class<T> resultType = (Class<T>) Classes.RAW_CLASS.map(( (ParameterizedType) handler.getClass().getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[0]);
-
-        processingErrorHandlers.put( relation,  new ResponseHandler()
-        {
-            @Override
-            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-            {
-                T result = contextResourceFactory.readResponse( response, resultType );
-                return handler.handleResult( result, client );
-            }
-        });
-
-        return this;
-    }
-
-    public ContextResourceClient onDelete(ResponseHandler handler)
-    {
-        deleteHandler = handler;
-        return this;
-    }
-
-    public ContextResourceClientFactory getContextResourceClientFactory()
-    {
-        return contextResourceFactory;
-    }
-
-    public Reference getReference()
-    {
-        return reference;
-    }
-
-    public Resource getResource()
-    {
-        return resource;
-    }
-
-    public void start()
-    {
-        HandlerCommand command = refresh();
-        while (command != null)
-            command = command.execute( this );
-    }
-
-    // Callable from HandlerCommand
-    HandlerCommand refresh()
-    {
-        if (resourceHandler == null)
-            throw new IllegalStateException( "No handler set for resources" );
-
-        return invokeQuery( reference, null, resourceHandler, null );
-    }
-
-    HandlerCommand query( String relation, Object queryRequest, ResponseHandler handler, ResponseHandler processingErrorHandler )
-    {
-        return query( resource.query( relation ), queryRequest, handler, processingErrorHandler );
-    }
-
-    HandlerCommand query( Link link, Object queryRequest, ResponseHandler handler, ResponseHandler processingErrorHandler )
-    {
-        if (handler == null)
-            handler = queryHandlers.get( link.rel().get() );
-
-        if (handler == null)
-            throw new IllegalArgumentException( "No handler set for relation "+link.rel().get() );
-
-        if (processingErrorHandler == null)
-            processingErrorHandler = processingErrorHandlers.get( link.rel().get() );
-
-        Reference linkRef = new Reference(link.href().get());
-        if (linkRef.isRelative())
-            linkRef = new Reference( reference.toUri().toString() + link.href().get() );
-        return invokeQuery( linkRef, queryRequest, handler, processingErrorHandler );
-    }
-
-    private HandlerCommand invokeQuery( Reference ref, Object queryRequest, ResponseHandler resourceHandler, ResponseHandler processingErrorHandler )
-    {
-        Request request = new Request( Method.GET, ref );
-
-        if( queryRequest != null )
-        {
-            contextResourceFactory.writeRequest( request, queryRequest );
-        }
-
-        contextResourceFactory.updateQueryRequest( request );
-
-        User user = request.getClientInfo().getUser();
-        if ( user != null)
-            request.setChallengeResponse( new ChallengeResponse( ChallengeScheme.HTTP_BASIC, user.getName(), user.getSecret() ) );
-
-        Response response = new Response( request );
-
-        contextResourceFactory.getClient().handle( request, response );
-
-        if( response.getStatus().isSuccess() )
-        {
-            contextResourceFactory.updateCache( response );
-
-            return resourceHandler.handleResponse( response, this );
-        } else if (response.getStatus().isRedirection())
-        {
-            Reference redirectedTo = response.getLocationRef();
-            return invokeQuery( redirectedTo, queryRequest, resourceHandler, processingErrorHandler );
-        } else
-        {
-            if (response.getStatus().equals(Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY) && processingErrorHandler != null)
-            {
-                return processingErrorHandler.handleResponse( response, this );
-            } else
-            {
-                // TODO This needs to be expanded to allow custom handling of all the various cases
-                return errorHandler.handleResponse( response, this );
-            }
-        }
-    }
-
-    // Commands
-    HandlerCommand command( Link link, Object commandRequest, ResponseHandler handler, ResponseHandler processingErrorHandler )
-    {
-        if (handler == null)
-            handler = commandHandlers.get( link.rel().get() );
-
-        if (processingErrorHandler == null)
-            processingErrorHandler = processingErrorHandlers.get( link.rel().get() );
-
-        // Check if we should do POST or PUT
-        Method method;
-        if( LinksUtil.withClass( "idempotent" ).satisfiedBy( link ) )
-        {
-            method = Method.PUT;
-        }
-        else
-        {
-            method = Method.POST;
-        }
-
-        Reference ref = new Reference( reference.toUri().toString() + link.href().get() );
-        return invokeCommand( ref, method, commandRequest, handler, processingErrorHandler );
-    }
-
-    private HandlerCommand invokeCommand( Reference ref, Method method, Object requestObject, ResponseHandler responseHandler, ResponseHandler processingErrorHandler )
-    {
-        Request request = new Request( method, ref );
-
-        if (requestObject == null)
-            requestObject = new EmptyRepresentation();
-
-        contextResourceFactory.writeRequest( request, requestObject );
-
-        contextResourceFactory.updateCommandRequest( request );
-
-        User user = request.getClientInfo().getUser();
-        if ( user != null)
-            request.setChallengeResponse( new ChallengeResponse( ChallengeScheme.HTTP_BASIC, user.getName(), user.getSecret() ) );
-
-        Response response = new Response( request );
-        contextResourceFactory.getClient().handle( request, response );
-
-        try
-        {
-            if( response.getStatus().isSuccess() )
-            {
-                contextResourceFactory.updateCache( response );
-
-                if (responseHandler != null)
-                    return responseHandler.handleResponse( response, this );
-            }
-            else
-            {
-                if (response.getStatus().equals(Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY) && processingErrorHandler != null)
-                {
-                    return processingErrorHandler.handleResponse( response, this );
-                } else
-                {
-                    // TODO This needs to be expanded to allow custom handling of all the various cases
-                    return errorHandler.handleResponse( response, this );
-                }
-            }
-
-            return null; // No handler found
-        }
-        finally
-        {
-            try
-            {
-                response.getEntity().exhaust();
-            }
-            catch( Throwable e )
-            {
-                // Ignore
-            }
-        }
-    }
-
-    // Delete
-    public HandlerCommand delete( ResponseHandler responseHandler, ResponseHandler processingErrorHandler )
-        throws ResourceException
-    {
-        if (responseHandler == null)
-            responseHandler = deleteHandler;
-
-        Request request = new Request( Method.DELETE, new Reference( reference.toUri() ).toString() );
-        contextResourceFactory.updateCommandRequest( request );
-
-        int tries = 3;
-        while( true )
-        {
-            Response response = new Response( request );
-            try
-            {
-                contextResourceFactory.getClient().handle( request, response );
-                if( !response.getStatus().isSuccess() )
-                {
-                    return errorHandler.handleResponse( response, this );
-                }
-                else
-                {
-                    // Reset modification date
-                    contextResourceFactory.updateCache( response );
-
-                    return responseHandler.handleResponse( response, this );
-                }
-            }
-            catch( ResourceException e )
-            {
-                if( e.getStatus().equals( Status.CONNECTOR_ERROR_COMMUNICATION ) ||
-                    e.getStatus().equals( Status.CONNECTOR_ERROR_CONNECTION ) )
-                {
-                    if( tries == 0 )
-                    {
-                        throw e; // Give up
-                    }
-                    else
-                    {
-                        // Try again
-                        tries--;
-                        continue;
-                    }
-                }
-                else
-                {
-                    // Abort
-                    throw e;
-                }
-            }
-            finally
-            {
-                try
-                {
-                    response.getEntity().exhaust();
-                }
-                catch( Throwable e )
-                {
-                    // Ignore
-                }
-            }
-        }
-    }
-
-    // Browse to other resources
-    public synchronized ContextResourceClient newClient( Link link )
-    {
-        if( link == null )
-        {
-            throw new NullPointerException( "No link specified" );
-        }
-
-        return newClient( link.href().get() );
-    }
-
-    public synchronized ContextResourceClient newClient( String relativePath )
-    {
-        if( relativePath.startsWith( "http://" ) )
-        {
-            return contextResourceFactory.newClient( new Reference( relativePath ) );
-        }
-
-        Reference reference = this.reference.clone();
-        if( relativePath.startsWith( "/" ) )
-        {
-            reference.setPath( relativePath );
-        }
-        else
-        {
-            reference.setPath( reference.getPath() + relativePath );
-            reference = reference.normalize();
-        }
-
-        return contextResourceFactory.newClient( reference );
-    }
-
-    // Internal
-    private Object handlxeError( Response response )
-        throws ResourceException
-    {
-        if( response.getStatus().equals( Status.SERVER_ERROR_INTERNAL ) )
-        {
-            if( MediaType.APPLICATION_JAVA_OBJECT.equals( response.getEntity().getMediaType() ) )
-            {
-                try
-                {
-                    Object exception = new ObjectRepresentation( response.getEntity() ).getObject();
-                    throw new ResourceException( (Throwable) exception );
-                }
-                catch( IOException e )
-                {
-                    throw new ResourceException( e );
-                }
-                catch( ClassNotFoundException e )
-                {
-                    throw new ResourceException( e );
-                }
-            }
-
-            throw new ResourceException( Status.SERVER_ERROR_INTERNAL, response.getEntityAsText() );
-        }
-        else
-        {
-            if( response.getEntity() != null )
-            {
-                String text = response.getEntityAsText();
-                throw new ResourceException( response.getStatus().getCode(), response.getStatus()
-                    .getName(), text, response.getRequest().getResourceRef().toUri().toString() );
-            }
-            else
-            {
-                throw new ResourceException( response.getStatus().getCode(), response.getStatus()
-                    .getName(), response.getStatus().getDescription(), response.getRequest()
-                    .getResourceRef()
-                    .toUri()
-                    .toString() );
-            }
-        }
-    }
-
-    @Override
-    public String toString()
-    {
-        return reference.toString();
-    }
-}
\ No newline at end of file
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/api/ContextResourceClientFactory.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/api/ContextResourceClientFactory.java
deleted file mode 100644
index f047b26..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/api/ContextResourceClientFactory.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.client.api;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.client.ClientCache;
-import org.qi4j.library.rest.client.RequestWriterDelegator;
-import org.qi4j.library.rest.client.ResponseReaderDelegator;
-import org.qi4j.library.rest.client.spi.RequestWriter;
-import org.qi4j.library.rest.client.spi.ResponseHandler;
-import org.qi4j.library.rest.client.spi.ResponseReader;
-import org.restlet.Request;
-import org.restlet.Response;
-import org.restlet.Uniform;
-import org.restlet.data.ClientInfo;
-import org.restlet.data.Form;
-import org.restlet.data.Language;
-import org.restlet.data.MediaType;
-import org.restlet.data.Preference;
-import org.restlet.data.Reference;
-
-/**
- * Builder for UsecaseClient
- */
-public class ContextResourceClientFactory
-{
-    @Structure
-    private Module module;
-
-    @Uses
-    @Optional
-    private ClientCache cache;
-
-    @Uses
-    private ResponseReaderDelegator readerDelegator;
-
-    @Uses
-    private RequestWriterDelegator requestWriterDelegator;
-
-    @Uses
-    private Uniform client;
-
-    private ClientInfo info = new ClientInfo();
-    private Form requestHeaders = new Form();
-
-    private ResponseHandler errorHandler;
-
-    public ContextResourceClient newClient( Reference reference )
-    {
-        ContextResourceClient contextResourceClient = module.newObject( ContextResourceClient.class, this, reference );
-        contextResourceClient.onError( errorHandler );
-        return contextResourceClient;
-    }
-
-    public void setAgent(String agent)
-    {
-        info.setAgent( agent );
-    }
-
-    public Form getCustomRequestHeaders()
-    {
-        return requestHeaders;
-    }
-
-    public void setAcceptedLanguages(Language... acceptedLanguages)
-    {
-        List<Preference<Language>> languages = new ArrayList<Preference<Language>>();
-        for( Language acceptedLanguage : acceptedLanguages )
-        {
-            languages.add( new Preference<Language>( ));
-        }
-
-        info.setAcceptedLanguages( languages );
-
-    }
-
-    public void setAcceptedMediaTypes(MediaType... acceptedMediaTypes)
-    {
-        List<Preference<MediaType>> mediatypes = new ArrayList<Preference<MediaType>>();
-        for( MediaType mediaType : acceptedMediaTypes )
-        {
-            mediatypes.add( new Preference<MediaType>(mediaType) );
-        }
-
-        info.setAcceptedMediaTypes( mediatypes );
-    }
-
-    public ClientInfo getInfo()
-    {
-        return info;
-    }
-
-    public void setErrorHandler( ResponseHandler errorHandler )
-    {
-        this.errorHandler = errorHandler;
-    }
-
-    public ResponseHandler getErrorHandler()
-    {
-        return errorHandler;
-    }
-
-    // Internal
-    void updateCommandRequest( Request request )
-    {
-        request.setClientInfo( info );
-
-        // Update cache information
-        if( cache != null )
-        {
-            cache.updateCommandConditions( request );
-        }
-
-        // Add all custom headers
-        if (!requestHeaders.isEmpty())
-            request.getAttributes().put( "org.restlet.http.headers", requestHeaders );
-    }
-
-    void updateQueryRequest( Request request )
-    {
-        request.setClientInfo( info );
-
-        // Update cache information
-        if( cache != null )
-        {
-            cache.updateQueryConditions( request );
-        }
-
-    }
-
-    void updateCache( Response response )
-    {
-        if( cache != null )
-        {
-            cache.updateCache( response );
-        }
-    }
-
-    Uniform getClient()
-    {
-        return client;
-    }
-
-    public <T> T readResponse( Response response, Class<T> queryResult )
-    {
-        return (T) readerDelegator.readResponse( response, queryResult );
-    }
-
-    public void writeRequest( Request request, Object queryRequest )
-    {
-        if( !requestWriterDelegator.writeRequest( queryRequest, request ) )
-        {
-            throw new IllegalArgumentException( "Illegal query request type:" + queryRequest.getClass().getName() );
-        }
-    }
-
-    public void registerResponseReader(ResponseReader reader)
-    {
-        readerDelegator.registerResponseReader( reader );
-    }
-
-    public void registerRequestWriter(RequestWriter writer)
-    {
-        requestWriterDelegator.registerRequestWriter( writer );
-    }
-}
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/api/ErrorHandler.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/api/ErrorHandler.java
deleted file mode 100644
index 0afbbf4..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/api/ErrorHandler.java
+++ /dev/null
@@ -1,86 +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.qi4j.library.rest.client.api;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-import org.qi4j.functional.Specification;
-import org.qi4j.functional.Specifications;
-import org.qi4j.library.rest.client.spi.ResponseHandler;
-import org.restlet.Response;
-import org.restlet.data.Status;
-import org.restlet.resource.ResourceException;
-
-/**
- * Implements a chained list of specification-&gt;handler. Add the most specific handlers first, and the most generic last.
- */
-public class ErrorHandler
-    implements ResponseHandler
-{
-    public static Specification<Response> AUTHENTICATION_REQUIRED = new Specification<Response>()
-    {
-        @Override
-        public boolean satisfiedBy( Response item )
-        {
-            return item.getStatus().equals( Status.CLIENT_ERROR_UNAUTHORIZED );
-        }
-    };
-
-    public static Specification<Response> RECOVERABLE_ERROR = new Specification<Response>()
-    {
-        @Override
-        public boolean satisfiedBy( Response item )
-        {
-            return item.getStatus().isRecoverableError();
-        }
-    };
-
-    LinkedHashMap<Specification<Response>, ResponseHandler> handlers = new LinkedHashMap<Specification<Response>, ResponseHandler>(  );
-
-    public ErrorHandler()
-    {
-    }
-
-    public ErrorHandler onError(Specification<Response> responseSpecification, ResponseHandler handler)
-    {
-        handlers.put( responseSpecification, handler );
-        return this;
-    }
-
-    public ErrorHandler onError(ResponseHandler handler)
-    {
-        handlers.put( Specifications.<Response>TRUE(), handler );
-        return this;
-    }
-
-    @Override
-    public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-    {
-        for( Map.Entry<Specification<Response>, ResponseHandler> specificationResponseHandlerEntry : handlers.entrySet() )
-        {
-            if (specificationResponseHandlerEntry.getKey().satisfiedBy( response ))
-            {
-                return specificationResponseHandlerEntry.getValue().handleResponse( response, client );
-            }
-        }
-
-        // No handlers, throw exception
-        throw new ResourceException( response.getStatus() );
-    }
-}
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/api/HandlerCommand.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/api/HandlerCommand.java
deleted file mode 100644
index aed48bb..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/api/HandlerCommand.java
+++ /dev/null
@@ -1,221 +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.qi4j.library.rest.client.api;
-
-import java.lang.reflect.ParameterizedType;
-import org.qi4j.api.util.Classes;
-import org.qi4j.library.rest.client.spi.ResponseHandler;
-import org.qi4j.library.rest.client.spi.ResultHandler;
-import org.qi4j.library.rest.common.link.Link;
-import org.restlet.Response;
-
-/**
- * TODO
- */
-public abstract class HandlerCommand
-{
-    public static HandlerCommand refresh()
-    {
-        return new RefreshCommand();
-    }
-
-    public static HandlerCommand query(String relation)
-    {
-        return new QueryCommand( relation, null);
-    }
-
-    public static HandlerCommand query(String relation, Object requestObject)
-    {
-        return new QueryCommand( relation, requestObject);
-    }
-
-    public static HandlerCommand query(Link relation)
-    {
-        return new QueryLinkCommand( relation );
-    }
-
-    public static HandlerCommand command(String relation)
-    {
-        return new CommandRelationCommand( relation, null );
-    }
-
-    public static HandlerCommand command(String relation, Object requestObject)
-    {
-        return new CommandRelationCommand( relation, requestObject );
-    }
-
-    public static HandlerCommand command(Link link)
-    {
-        return new CommandLinkCommand( link, null );
-    }
-
-    public static HandlerCommand command(Link link, Object requestObject)
-    {
-        return new CommandLinkCommand( link, requestObject );
-    }
-
-    public static HandlerCommand delete()
-    {
-        return new DeleteCommand();
-    }
-
-    protected ResponseHandler responseHandler;
-    protected ResponseHandler processingErrorHandler;
-
-    public HandlerCommand onSuccess(ResponseHandler responseHandler)
-    {
-        this.responseHandler = responseHandler;
-        return this;
-    }
-
-    public <T> HandlerCommand onSuccess(final ResultHandler<T> resultHandler)
-    {
-        final Class<T> resultType = (Class<T>) Classes.RAW_CLASS.map(( (ParameterizedType) resultHandler.getClass().getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[0]);
-        this.responseHandler = new ResponseHandler()
-        {
-            @Override
-            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-            {
-                T result = client.getContextResourceClientFactory().readResponse( response, resultType );
-                return resultHandler.handleResult( result, client );
-            }
-        };
-        return this;
-    }
-
-    public HandlerCommand onProcessingError(ResponseHandler processingErrorHandler)
-    {
-        this.processingErrorHandler = processingErrorHandler;
-        return this;
-    }
-
-    public <T> HandlerCommand onProcessingError(final ResultHandler<T> resultHandler)
-    {
-        final Class<T> resultType = (Class<T>) Classes.RAW_CLASS.map(( (ParameterizedType) resultHandler.getClass().getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[0]);
-        this.processingErrorHandler = new ResponseHandler()
-        {
-            @Override
-            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-            {
-                T result = client.getContextResourceClientFactory().readResponse( response, resultType );
-                return resultHandler.handleResult( result, client );
-            }
-        };
-        return this;
-    }
-
-    abstract HandlerCommand execute( ContextResourceClient client);
-
-    private static class RefreshCommand
-        extends HandlerCommand
-    {
-        @Override
-        HandlerCommand execute( ContextResourceClient client )
-        {
-            return client.refresh();
-        }
-    }
-
-    private static class QueryCommand
-        extends HandlerCommand
-    {
-        private String relation;
-        private Object requestObject;
-
-        private QueryCommand( String relation, Object requestObject)
-        {
-            this.relation = relation;
-            this.requestObject = requestObject;
-        }
-
-        @Override
-        HandlerCommand execute( ContextResourceClient client )
-        {
-            return client.query( client.getResource()
-                                     .query( relation ), requestObject, responseHandler, processingErrorHandler );
-        }
-    }
-
-    private static class QueryLinkCommand
-        extends HandlerCommand
-    {
-        private Link link;
-
-        private QueryLinkCommand( Link link)
-        {
-            this.link = link;
-        }
-
-        @Override
-        HandlerCommand execute( ContextResourceClient client )
-        {
-            return client.query( link, null, responseHandler, processingErrorHandler );
-        }
-    }
-
-    private static class CommandRelationCommand
-        extends HandlerCommand
-    {
-        private String relation;
-        private Object requestObject;
-
-        private CommandRelationCommand( String relation, Object requestObject )
-        {
-            this.relation = relation;
-            this.requestObject = requestObject;
-        }
-
-        @Override
-        HandlerCommand execute( ContextResourceClient client )
-        {
-            return client.command( client.getResource()
-                                       .command( relation ), requestObject, responseHandler, processingErrorHandler );
-        }
-    }
-
-    private static class CommandLinkCommand
-        extends HandlerCommand
-    {
-        private Link link;
-        private Object requestObject;
-
-        private CommandLinkCommand( Link link, Object requestObject )
-        {
-            this.link = link;
-            this.requestObject = requestObject;
-        }
-
-        @Override
-        HandlerCommand execute( ContextResourceClient client )
-        {
-            return client.command( link, requestObject, responseHandler, processingErrorHandler );
-        }
-    }
-
-    private static class DeleteCommand
-        extends HandlerCommand
-    {
-        @Override
-        HandlerCommand execute( ContextResourceClient client )
-        {
-            return client.delete(responseHandler, processingErrorHandler);
-        }
-    }
-
-}
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/api/package.html b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/api/package.html
deleted file mode 100644
index c7ceff6..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/api/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ReST Client API.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/package.html b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/package.html
deleted file mode 100644
index 0e5a93a..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ReST Client Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/requestwriter/FormRequestWriter.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/requestwriter/FormRequestWriter.java
deleted file mode 100644
index db96e81..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/requestwriter/FormRequestWriter.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.client.requestwriter;
-
-import org.qi4j.library.rest.client.spi.RequestWriter;
-import org.restlet.Request;
-import org.restlet.data.CharacterSet;
-import org.restlet.data.Form;
-import org.restlet.data.Method;
-import org.restlet.resource.ResourceException;
-
-/**
- * Request writer for Form. Transfers form state to request reference as query parameters
- */
-public class FormRequestWriter
-   implements RequestWriter
-{
-    @Override
-   public boolean writeRequest(Object requestObject, Request request) throws ResourceException
-   {
-      if (requestObject instanceof Form)
-      {
-         // Form as query parameters
-         if (request.getMethod().equals(Method.GET))
-            request.getResourceRef().setQuery(((Form)requestObject).getQueryString());
-         else
-            request.setEntity(((Form)requestObject).getWebRepresentation(CharacterSet.UTF_8));
-
-         return true;
-      }
-
-      return false;
-   }
-}
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/requestwriter/ValueCompositeRequestWriter.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/requestwriter/ValueCompositeRequestWriter.java
deleted file mode 100644
index baf838d..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/requestwriter/ValueCompositeRequestWriter.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.client.requestwriter;
-
-import java.io.IOException;
-import java.io.Writer;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.property.StateHolder;
-import org.qi4j.api.service.qualifier.Tagged;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.api.value.ValueSerializationException;
-import org.qi4j.api.value.ValueSerializer;
-import org.qi4j.library.rest.client.spi.RequestWriter;
-import org.qi4j.spi.Qi4jSPI;
-import org.restlet.Request;
-import org.restlet.data.CharacterSet;
-import org.restlet.data.MediaType;
-import org.restlet.data.Method;
-import org.restlet.data.Reference;
-import org.restlet.engine.io.WriterOutputStream;
-import org.restlet.representation.WriterRepresentation;
-import org.restlet.resource.ResourceException;
-
-/**
- * Request writer for ValueComposites. Transfers value state to request reference as query parameters or JSON entity
- */
-public class ValueCompositeRequestWriter
-   implements RequestWriter
-{
-   @Structure
-   private Qi4jSPI spi;
-
-   @Service
-   @Tagged( ValueSerialization.Formats.JSON )
-   private ValueSerializer valueSerializer;
-
-    @Override
-   public boolean writeRequest(Object requestObject, Request request) throws ResourceException
-   {
-      if (requestObject instanceof ValueComposite)
-      {
-         // Value as parameter
-         final ValueComposite valueObject = (ValueComposite) requestObject;
-         if (request.getMethod().equals(Method.GET))
-         {
-            StateHolder holder = spi.stateOf( valueObject );
-            final ValueDescriptor descriptor = spi.valueDescriptorFor( valueObject );
-
-            final Reference ref = request.getResourceRef();
-            ref.setQuery( null );
-
-             try
-             {
-                 for( PropertyDescriptor propertyDescriptor : descriptor.state().properties() )
-                 {
-                     Object value = holder.propertyFor( propertyDescriptor.accessor() ).get();
-                     String param;
-                     if( value == null )
-                     {
-                        param = null;
-                     }
-                     else
-                     {
-                        param = valueSerializer.serialize( value );
-                     }
-                     ref.addQueryParameter( propertyDescriptor.qualifiedName().name(), param );
-                 }
-             }
-             catch( ValueSerializationException e )
-             {
-                 throw new ResourceException( e );
-             }
-         } else
-         {
-            request.setEntity(new WriterRepresentation( MediaType.APPLICATION_JSON )
-            {
-                @Override
-                public void write( Writer writer )
-                    throws IOException
-                {
-                   setCharacterSet( CharacterSet.UTF_8 );
-                   valueSerializer.serialize( valueObject, new WriterOutputStream( writer ) );
-                }
-            });
-         }
-
-         return true;
-      }
-
-      return false;
-   }
-}
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/requestwriter/package.html b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/requestwriter/package.html
deleted file mode 100644
index 74b7484..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/requestwriter/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ReST Client Request Writers.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/responsereader/DefaultResponseReader.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/responsereader/DefaultResponseReader.java
deleted file mode 100644
index f529703..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/responsereader/DefaultResponseReader.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.client.responsereader;
-
-import java.io.IOException;
-import org.json.JSONException;
-import org.json.JSONTokener;
-import org.qi4j.library.rest.client.spi.ResponseReader;
-import org.restlet.Response;
-import org.restlet.data.MediaType;
-import org.restlet.resource.ResourceException;
-
-/**
- * ResponseReader for simple types from JSON
- */
-public class DefaultResponseReader
-   implements ResponseReader
-{
-    @Override
-   public Object readResponse(Response response, Class<?> resultType) throws ResourceException
-   {
-      if (MediaType.APPLICATION_JSON.equals(response.getEntity().getMediaType()))
-         if (resultType.equals(String.class))
-         {
-            try
-            {
-               return response.getEntity().getText();
-            } catch (IOException e)
-            {
-               throw new ResourceException(e);
-            }
-         } else if (Number.class.isAssignableFrom(resultType))
-         {
-            try
-            {
-               Number value = (Number) new JSONTokener(response.getEntityAsText()).nextValue();
-               if (resultType.equals(Integer.class))
-                  return Integer.valueOf(value.intValue());
-            } catch (JSONException e)
-            {
-               throw new ResourceException(e);
-            }
-         }
-
-      return null;
-   }
-}
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/responsereader/JSONResponseReader.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/responsereader/JSONResponseReader.java
deleted file mode 100644
index a90c925..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/responsereader/JSONResponseReader.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.client.responsereader;
-
-import java.util.Iterator;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.service.qualifier.Tagged;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.type.ValueCompositeType;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.api.value.ValueDeserializer;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.library.rest.client.spi.ResponseReader;
-import org.restlet.Response;
-import org.restlet.data.Form;
-import org.restlet.data.MediaType;
-import org.restlet.resource.ResourceException;
-
-/**
- * JAVADOC
- */
-public class JSONResponseReader
-   implements ResponseReader
-{
-   @Structure
-   private Module module;
-
-   @Service
-   @Tagged( ValueSerialization.Formats.JSON )
-   private ValueDeserializer valueDeserializer;
-
-    @Override
-   public Object readResponse( Response response, Class<?> resultType )
-   {
-      if (response.getEntity().getMediaType().equals( MediaType.APPLICATION_JSON))
-      {
-         if (ValueComposite.class.isAssignableFrom( resultType ))
-         {
-            String jsonValue = response.getEntityAsText();
-            ValueCompositeType valueType = module.valueDescriptor( resultType.getName() ).valueType();
-            return valueDeserializer.deserialize( valueType, jsonValue );
-         }
-         else if (resultType.equals(Form.class))
-         {
-            try
-            {
-               String jsonValue = response.getEntityAsText();
-               JSONObject jsonObject = new JSONObject(jsonValue);
-               Iterator<?> keys = jsonObject.keys();
-               Form form = new Form();
-               while (keys.hasNext())
-               {
-                  Object key = keys.next();
-                  form.set(key.toString(), jsonObject.get(key.toString()).toString());
-               }
-               return form;
-            } catch (JSONException e)
-            {
-               throw new ResourceException(e);
-            }
-         }
-      }
-
-      return null;
-   }
-}
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/responsereader/TableResponseReader.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/responsereader/TableResponseReader.java
deleted file mode 100644
index 21e13ef..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/responsereader/TableResponseReader.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.client.responsereader;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.util.Dates;
-import org.qi4j.library.rest.client.spi.ResponseReader;
-import org.qi4j.library.rest.common.table.Table;
-import org.qi4j.library.rest.common.table.TableBuilder;
-import org.restlet.Response;
-import org.restlet.data.MediaType;
-import org.restlet.data.Status;
-import org.restlet.resource.ResourceException;
-
-/**
- * JAVADOC
- */
-public class TableResponseReader
-   implements ResponseReader
-{
-   @Structure
-   Module module;
-
-    @Override
-   public Object readResponse( Response response, Class<?> resultType ) throws ResourceException
-   {
-      if (response.getEntity().getMediaType().equals( MediaType.APPLICATION_JSON) && Table.class.isAssignableFrom( resultType ))
-      {
-         String jsonValue = response.getEntityAsText();
-         try
-         {
-            JSONObject jsonObject = new JSONObject(jsonValue);
-
-            JSONObject table = jsonObject.getJSONObject( "table" );
-            TableBuilder builder = new TableBuilder(module);
-
-            JSONArray cols = table.getJSONArray( "cols" );
-            for (int i = 0; i < cols.length(); i++)
-            {
-               JSONObject col = cols.getJSONObject( i );
-               builder.column( col.optString( "id" ),  col.getString( "label" ), col.getString( "type" ));
-            }
-
-            JSONArray rows = table.getJSONArray( "rows" );
-            for (int i = 0; i < rows.length(); i++)
-            {
-               builder.row();
-               JSONObject row = rows.getJSONObject( i );
-               JSONArray cells = row.getJSONArray( "c" );
-               for (int j = 0; j < cells.length(); j++)
-               {
-                  JSONObject cell = cells.getJSONObject( j );
-                  Object value = cell.opt( "v" );
-                  String formatted = cell.optString("f");
-
-                  if (cols.getJSONObject( j ).getString( "type" ).equals("datetime") && value != null)
-                     value = Dates.fromString( value.toString() );
-                  else if (cols.getJSONObject( j ).getString( "type" ).equals("date") && value != null)
-                     try
-                     {
-                        value = new SimpleDateFormat( "yyyy-MM-dd").parse( value.toString() );
-                     } catch (ParseException e)
-                     {
-                        throw new ResourceException(e);
-                     }
-                  else if (cols.getJSONObject( j ).getString( "type" ).equals("timeofday") && value != null)
-                     try
-                     {
-                        value = new SimpleDateFormat( "HH:mm:ss").parse( value.toString() );
-                     } catch (ParseException e)
-                     {
-                        throw new ResourceException(e);
-                     }
-
-                  builder.cell( value, formatted );
-               }
-               builder.endRow();
-            }
-
-            return builder.newTable();
-         } catch (JSONException e)
-         {
-            throw new ResourceException( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY, e);
-         }
-      }
-
-      return null;
-   }
-}
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/responsereader/package.html b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/responsereader/package.html
deleted file mode 100644
index 4e41789..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/responsereader/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ReST Client Response Readers.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/NullResponseHandler.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/NullResponseHandler.java
deleted file mode 100644
index d2c19f0..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/NullResponseHandler.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.client.spi;
-
-import org.qi4j.library.rest.client.api.ContextResourceClient;
-import org.qi4j.library.rest.client.api.HandlerCommand;
-import org.restlet.Response;
-
-/**
- */
-public class NullResponseHandler
-   implements ResponseHandler
-{
-    public static NullResponseHandler INSTANCE = new NullResponseHandler();
-
-    @Override
-    public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-    {
-        return null;
-    }
-}
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/RequestWriter.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/RequestWriter.java
deleted file mode 100644
index a528227..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/RequestWriter.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.client.spi;
-
-import org.restlet.Request;
-import org.restlet.resource.ResourceException;
-
-/**
- * JAVADOC
- */
-public interface RequestWriter
-{
-   /**
-    * Write the given request object to the request.
-    *
-    * @param requestObject The object to be written.
-    * @param request The Request destination of the requestObject
-    * @return true if the object was written to the Request instance, false if handler can not write the object.
-    * @throws org.restlet.resource.ResourceException
-    */
-   public boolean writeRequest(Object requestObject, Request request)
-      throws ResourceException;
-}
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/ResponseHandler.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/ResponseHandler.java
deleted file mode 100644
index 703cd09..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/ResponseHandler.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.client.spi;
-
-import org.qi4j.library.rest.client.api.ContextResourceClient;
-import org.qi4j.library.rest.client.api.HandlerCommand;
-import org.restlet.Response;
-
-/**
- * Implement this interface and pass an instance to the CommandQueryClient. It will be responsible
- * for handling the responses of PUT/POST/DELETE calls.
- */
-public interface ResponseHandler
-{
-   HandlerCommand handleResponse( Response response, ContextResourceClient client);
-}
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/ResponseReader.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/ResponseReader.java
deleted file mode 100644
index e1875aa..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/ResponseReader.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.client.spi;
-
-import org.restlet.Response;
-import org.restlet.resource.ResourceException;
-
-/**
- * JAVADOC
- */
-public interface ResponseReader
-{
-   Object readResponse(Response response, Class<?> resultType) throws ResourceException;
-}
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/ResultHandler.java b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/ResultHandler.java
deleted file mode 100644
index a125f51..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/ResultHandler.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.client.spi;
-
-import org.qi4j.library.rest.client.api.ContextResourceClient;
-import org.qi4j.library.rest.client.api.HandlerCommand;
-
-/**
- * Implement this interface to handle deserialized results from CRC
- */
-public interface ResultHandler<T>
-{
-   HandlerCommand handleResult( T result, ContextResourceClient client);
-}
diff --git a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/package.html b/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/package.html
deleted file mode 100644
index 4525d5f..0000000
--- a/libraries/rest-client/src/main/java/org/qi4j/library/rest/client/spi/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ReST Client SPI.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-client/src/main/resources/org/apache/polygene/library/rest/client/rest-client.properties b/libraries/rest-client/src/main/resources/org/apache/polygene/library/rest/client/rest-client.properties
new file mode 100644
index 0000000..0d4706d
--- /dev/null
+++ b/libraries/rest-client/src/main/resources/org/apache/polygene/library/rest/client/rest-client.properties
@@ -0,0 +1,27 @@
+#
+#  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.
+#
+#
+#
+
+#Client
+requestwriters=org.apache.polygene.library.rest.client.requestwriter.FormRequestWriter,\
+  org.apache.polygene.library.rest.client.requestwriter.ValueCompositeRequestWriter\
+
+responsereaders=org.apache.polygene.library.rest.client.responsereader.DefaultResponseReader,\
+  org.apache.polygene.library.rest.client.responsereader.TableResponseReader,\
+  org.apache.polygene.library.rest.client.responsereader.JSONResponseReader
diff --git a/libraries/rest-client/src/main/resources/org/qi4j/library/rest/client/rest-client.properties b/libraries/rest-client/src/main/resources/org/qi4j/library/rest/client/rest-client.properties
deleted file mode 100644
index 4a0ac1d..0000000
--- a/libraries/rest-client/src/main/resources/org/qi4j/library/rest/client/rest-client.properties
+++ /dev/null
@@ -1,22 +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.
-
-#Client
-requestwriters=org.qi4j.library.rest.client.requestwriter.FormRequestWriter,\
-  org.qi4j.library.rest.client.requestwriter.ValueCompositeRequestWriter\
-
-responsereaders=org.qi4j.library.rest.client.responsereader.DefaultResponseReader,\
-  org.qi4j.library.rest.client.responsereader.TableResponseReader,\
-  org.qi4j.library.rest.client.responsereader.JSONResponseReader
diff --git a/libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/ContextResourceClientFactoryTest.java b/libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/ContextResourceClientFactoryTest.java
new file mode 100644
index 0000000..e979d43
--- /dev/null
+++ b/libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/ContextResourceClientFactoryTest.java
@@ -0,0 +1,763 @@
+/*
+ *  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.polygene.library.rest.client;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.constraint.Name;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCallback;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.rest.client.api.ContextResourceClient;
+import org.apache.polygene.library.rest.client.api.ContextResourceClientFactory;
+import org.apache.polygene.library.rest.client.api.ErrorHandler;
+import org.apache.polygene.library.rest.client.api.HandlerCommand;
+import org.apache.polygene.library.rest.client.spi.ResponseHandler;
+import org.apache.polygene.library.rest.client.spi.ResultHandler;
+import org.apache.polygene.library.rest.common.Resource;
+import org.apache.polygene.library.rest.common.ValueAssembler;
+import org.apache.polygene.library.rest.common.link.Link;
+import org.apache.polygene.library.rest.common.link.Links;
+import org.apache.polygene.library.rest.common.link.LinksBuilder;
+import org.apache.polygene.library.rest.common.link.LinksUtil;
+import org.apache.polygene.library.rest.server.api.ContextResource;
+import org.apache.polygene.library.rest.server.api.ContextRestlet;
+import org.apache.polygene.library.rest.server.api.ObjectSelection;
+import org.apache.polygene.library.rest.server.api.ResourceDelete;
+import org.apache.polygene.library.rest.server.api.ResourceIndex;
+import org.apache.polygene.library.rest.server.api.SubResource;
+import org.apache.polygene.library.rest.server.api.SubResources;
+import org.apache.polygene.library.rest.server.api.constraint.InteractionValidation;
+import org.apache.polygene.library.rest.server.api.constraint.Requires;
+import org.apache.polygene.library.rest.server.api.constraint.RequiresValid;
+import org.apache.polygene.library.rest.server.api.dci.Role;
+import org.apache.polygene.library.rest.server.assembler.RestServerAssembler;
+import org.apache.polygene.library.rest.server.restlet.NullCommandResult;
+import org.apache.polygene.library.rest.server.spi.CommandResult;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.util.FreePortFinder;
+import org.hamcrest.CoreMatchers;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.restlet.Client;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.Server;
+import org.restlet.Uniform;
+import org.restlet.data.ChallengeScheme;
+import org.restlet.data.Form;
+import org.restlet.data.MediaType;
+import org.restlet.data.Protocol;
+import org.restlet.data.Reference;
+import org.restlet.resource.ResourceException;
+import org.restlet.security.ChallengeAuthenticator;
+import org.restlet.security.MapVerifier;
+import org.restlet.security.User;
+import org.restlet.service.MetadataService;
+
+import static org.apache.polygene.bootstrap.ImportedServiceDeclaration.NEW_OBJECT;
+import static org.apache.polygene.library.rest.client.api.HandlerCommand.command;
+import static org.apache.polygene.library.rest.client.api.HandlerCommand.query;
+import static org.apache.polygene.library.rest.client.api.HandlerCommand.refresh;
+
+public class ContextResourceClientFactoryTest
+    extends AbstractPolygeneTest
+{
+    private Server server;
+    private ContextResourceClient crc;
+
+    public static String command = null; // Commands will set this
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // General setup of client and server
+        new ClientAssembler().assemble( module );
+        new ValueAssembler().assemble( module );
+        new RestServerAssembler().assemble( module );
+
+        module.objects( NullCommandResult.class );
+        module.importedServices( CommandResult.class ).importedBy( NEW_OBJECT );
+
+        module.importedServices( MetadataService.class ).importedBy( NEW_OBJECT );
+        module.objects( MetadataService.class );
+
+        // Test specific setup
+        module.values( TestQuery.class, TestResult.class, TestCommand.class );
+        module.forMixin( TestQuery.class ).declareDefaults().abc().set( "def" );
+
+        module.objects( RootRestlet.class, RootResource.class, RootContext.class, SubResource1.class, PagesResource.class );
+
+
+        module.objects( DescribableContext.class );
+        module.transients( TestComposite.class );
+    }
+
+    @Override
+    protected void initApplication( Application app )
+        throws Exception
+    {
+    }
+
+    @Before
+    public void startWebServer()
+        throws Exception
+    {
+        int port = FreePortFinder.findFreePortOnLoopback();
+        server = new Server( Protocol.HTTP, port );
+        ContextRestlet restlet = objectFactory.newObject( ContextRestlet.class, new org.restlet.Context() );
+
+        ChallengeAuthenticator guard = new ChallengeAuthenticator(null, ChallengeScheme.HTTP_BASIC, "testRealm");
+        MapVerifier mapVerifier = new MapVerifier();
+        mapVerifier.getLocalSecrets().put("rickard", "secret".toCharArray());
+        guard.setVerifier(mapVerifier);
+
+        guard.setNext(restlet);
+
+        server.setNext( guard );
+        server.start();
+
+        //START SNIPPET: client-create1
+        Client client =   new Client( Protocol.HTTP );
+
+        ContextResourceClientFactory contextResourceClientFactory = objectFactory.newObject( ContextResourceClientFactory.class, client );
+        contextResourceClientFactory.setAcceptedMediaTypes( MediaType.APPLICATION_JSON );
+        //END SNIPPET: client-create1
+
+        //START SNIPPET: client-create2
+        contextResourceClientFactory.setErrorHandler( new ErrorHandler().onError( ErrorHandler.AUTHENTICATION_REQUIRED, new ResponseHandler()
+        {
+            boolean tried = false;
+
+            @Override
+            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+            {
+                    if (tried)
+                        throw new ResourceException( response.getStatus() );
+
+                    tried = true;
+                    client.getContextResourceClientFactory().getInfo().setUser( new User("rickard", "secret") );
+
+                    // Try again
+                    return refresh();
+            }
+        } ).onError( ErrorHandler.RECOVERABLE_ERROR, new ResponseHandler()
+        {
+            @Override
+            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+            {
+                // Try to restart
+                return refresh();
+            }
+        } ) );
+        //END SNIPPET: client-create2
+
+        //START SNIPPET: client-create3
+        Reference ref = new Reference( "http://localhost:" + port + '/' );
+        crc = contextResourceClientFactory.newClient( ref );
+        //END SNIPPET: client-create3
+    }
+
+    @After
+    public void stopWebServer()
+        throws Exception
+    {
+        server.stop();
+    }
+
+    @Override
+    protected Application newApplicationInstance( ApplicationDescriptor applicationModel )
+    {
+        return applicationModel.newInstance( polygene.api(), new MetadataService() );
+    }
+
+    @Test
+    public void testQueryWithoutValue()
+    {
+        //START SNIPPET: query-without-value
+        crc.onResource( new ResultHandler<Resource>()
+        {
+            @Override
+            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
+            {
+                return query( "querywithoutvalue" );
+            }
+        } ).
+        onQuery( "querywithoutvalue", new ResultHandler<TestResult>()
+        {
+            @Override
+            public HandlerCommand handleResult( TestResult result, ContextResourceClient client )
+            {
+                Assert.assertThat( result.xyz().get(), CoreMatchers.equalTo( "bar" ) );
+                return null;
+            }
+        } );
+
+        crc.start();
+        //END SNIPPET: query-without-value
+    }
+
+    @Test
+    public void testQueryAndCommand()
+    {
+        //START SNIPPET: query-and-command
+        crc.onResource( new ResultHandler<Resource>()
+        {
+            @Override
+            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
+            {
+                return query( "querywithvalue", null );
+            }
+        } ).onProcessingError( "querywithvalue", new ResultHandler<TestQuery>()
+        {
+            @Override
+            public HandlerCommand handleResult( TestQuery result, ContextResourceClient client )
+            {
+                ValueBuilder<TestQuery> builder = valueBuilderFactory.newValueBuilderWithPrototype( result );
+
+                builder.prototype().abc().set( "abc" + builder.prototype().abc().get() );
+
+                return query( "querywithvalue", builder.newInstance() );
+            }
+        } ).onQuery( "querywithvalue", new ResultHandler<TestResult>()
+        {
+            @Override
+            public HandlerCommand handleResult( TestResult result, ContextResourceClient client )
+            {
+                return command( "commandwithvalue", null );
+            }
+        } ).onProcessingError( "commandwithvalue", new ResultHandler<Form>()
+        {
+            @Override
+            public HandlerCommand handleResult( Form result, ContextResourceClient client )
+            {
+                result.set( "abc", "right" );
+
+                return command( "commandwithvalue", result );
+            }
+        } );
+
+        crc.start();
+        //END SNIPPET: query-and-command
+    }
+
+    @Test
+    public void testQueryListAndCommand()
+    {
+        //START SNIPPET: query-list-and-command
+        crc.onResource( new ResultHandler<Resource>()
+        {
+            @Override
+            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
+            {
+                return query( "commandwithvalue" );
+            }
+        } ).onQuery( "commandwithvalue", new ResultHandler<Links>()
+        {
+            @Override
+            public HandlerCommand handleResult( Links result, ContextResourceClient client )
+            {
+                Link link = LinksUtil.withId( "right", result );
+
+                return command( link );
+            }
+        } ).onCommand( "commandwithvalue", new ResponseHandler()
+        {
+            @Override
+            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+            {
+                System.out.println( "Done" );
+                return null;
+            }
+        } );
+
+        crc.start();
+        //END SNIPPET: query-list-and-command
+    }
+
+    @Test
+    public void testQueryListAndCommandProgressive()
+    {
+        //START SNIPPET: query-list-and-command-progressive
+        crc.onResource( new ResultHandler<Resource>()
+        {
+            @Override
+            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
+            {
+                return query( "commandwithvalue" ).onSuccess( new ResultHandler<Links>()
+                {
+                    @Override
+                    public HandlerCommand handleResult( Links result, ContextResourceClient client )
+                    {
+                        Link link = LinksUtil.withId( "right", result );
+
+                        return command( link ).onSuccess( new ResponseHandler()
+                        {
+                            @Override
+                            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+                            {
+                                System.out.println( "Done" );
+                                return null;
+                            }
+                        } );
+                    }
+                } );
+            }
+        } );
+
+        crc.start();
+        //END SNIPPET: query-list-and-command-progressive
+    }
+
+    @Test
+    public void testIndexedResource()
+    {
+        crc.newClient("subcontext/pages/").onResource( new ResultHandler<Resource>()
+        {
+            @Override
+            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
+            {
+                return query( "index" );
+            }
+        } ).onQuery( "index", new ResultHandler<Links>()
+                {
+                    @Override
+                    public HandlerCommand handleResult( Links result, ContextResourceClient client )
+                    {
+                        Assert.assertEquals( result.links().get().size(), 3 );
+                        return null;
+                    }
+                } )
+        .start();
+
+    }
+
+    public interface TestQuery
+        extends ValueComposite
+    {
+        @UseDefaults
+        Property<String> abc();
+    }
+
+    public interface TestCommand
+        extends ValueComposite
+    {
+        Property<String> entity();
+    }
+
+    public interface TestResult
+        extends ValueComposite
+    {
+        Property<String> xyz();
+    }
+
+    public static class RootRestlet
+        extends ContextRestlet
+    {
+        @Override
+        protected Uniform createRoot( Request request, Response response )
+        {
+            return objectFactory.newObject( RootResource.class, this );
+        }
+    }
+
+    public static class RootResource
+        extends ContextResource
+        implements SubResources, ResourceDelete
+    {
+        private static TestComposite instance;
+
+        private RootContext rootContext()
+        {
+            return context( RootContext.class );
+        }
+
+        public RootResource()
+        {
+        }
+
+        public TestResult querywithvalue( TestQuery testQuery )
+            throws Throwable
+        {
+            return rootContext().queryWithValue( testQuery );
+        }
+
+        public TestResult querywithoutvalue()
+            throws Throwable
+        {
+            return rootContext().queryWithoutValue();
+        }
+
+        public String querywithstringresult( TestQuery query )
+            throws Throwable
+        {
+            return rootContext().queryWithStringResult( query );
+        }
+
+        public void commandwithvalue( TestCommand command )
+            throws Throwable
+        {
+            rootContext().commandWithValue( command );
+        }
+
+        public Links commandwithvalue()
+        {
+            return new LinksBuilder(module).
+                command( "commandwithvalue" ).
+                addLink( "Command ABC","right" ).
+                addLink( "Command XYZ", "wrong" ).newLinks();
+        }
+
+        @Override
+        public void delete()
+            throws IOException
+        {
+            rootContext().delete();
+        }
+
+        public void resource( String currentSegment )
+        {
+            ObjectSelection objectSelection = ObjectSelection.current();
+
+            objectSelection.select( new File( "" ) );
+
+            if( instance == null )
+            {
+                objectSelection.select( instance = module.newTransient( TestComposite.class ) );
+            }
+            else
+            {
+                objectSelection.select( instance );
+            }
+
+            subResource( SubResource1.class );
+        }
+    }
+
+    public static class SubResource1
+        extends ContextResource
+        implements InteractionValidation
+    {
+        public SubResource1()
+        {
+        }
+
+        @Requires( File.class )
+        public void commandWithRoleRequirement()
+        {
+            context( SubContext.class ).commandWithRoleRequirement();
+        }
+
+        // Interaction validation
+        private static boolean xyzValid = true;
+
+        @RequiresValid( "xyz" )
+        public void xyz( @Name( "valid" ) boolean valid )
+        {
+            xyzValid = valid;
+        }
+
+        @RequiresValid( "notxyz" )
+        public void notxyz( @Name( "valid" ) boolean valid )
+        {
+            xyzValid = valid;
+        }
+
+        public boolean isValid( String name )
+        {
+            if( name.equals( "xyz" ) )
+            {
+                return xyzValid;
+            }
+            else if( name.equals( "notxyz" ) )
+            {
+                return !xyzValid;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        @Requires( File.class )
+        public TestResult queryWithRoleRequirement(TestQuery query)
+        {
+            return context( SubContext.class ).queryWithRoleRequirement( query );
+        }
+
+        public TestResult genericquery( TestQuery query )
+            throws Throwable
+        {
+            return context( SubContext2.class ).genericQuery( query );
+        }
+
+        public TestResult querywithvalue( TestQuery query )
+            throws Throwable
+        {
+            return context( SubContext.class ).queryWithValue( query );
+        }
+
+        @SubResource
+        public void subresource1()
+        {
+            subResource( SubResource1.class );
+        }
+
+        @SubResource
+        public void subresource2()
+        {
+            subResource( SubResource1.class );
+        }
+
+        @SubResource
+        public void pages() {
+            subResource( PagesResource.class );
+        }
+    }
+
+    public static class RootContext
+    {
+        private static int count = 0;
+
+        @Structure
+        UnitOfWorkFactory uowf;
+
+        @Structure
+        ValueBuilderFactory vbf;
+
+        public TestResult queryWithValue( TestQuery query )
+        {
+            return vbf.newValueFromSerializedState( TestResult.class, "{\"xyz\":\""+query.abc().get()+"\"}" );
+        }
+
+        public TestResult queryWithoutValue()
+        {
+            return vbf.newValueFromSerializedState( TestResult.class, "{\"xyz\":\"bar\"}" );
+        }
+
+        public String queryWithStringResult( TestQuery query )
+        {
+            return "bar";
+        }
+
+        public int queryWithIntegerResult( TestQuery query )
+        {
+            return 7;
+        }
+
+        public void commandWithValue( TestCommand command )
+        {
+            if( !command.entity().get().equals( "right" ) )
+            {
+                throw new IllegalArgumentException( "Wrong argument" );
+            }
+
+            // Done
+        }
+
+        public void idempotentCommandWithValue( TestCommand command )
+            throws ConcurrentEntityModificationException
+        {
+            // On all but every third invocation, throw a concurrency exception
+            // This is to test retries on the server-side
+            count++;
+            if( count % 3 != 0 )
+            {
+                uowf.currentUnitOfWork().addUnitOfWorkCallback( new UnitOfWorkCallback()
+                {
+                    public void beforeCompletion()
+                        throws UnitOfWorkCompletionException
+                    {
+                        throw new ConcurrentEntityModificationException( Collections.emptyMap(),
+                                                                         UsecaseBuilder.newUsecase( "Testing" ) );
+                    }
+
+                    public void afterCompletion( UnitOfWorkStatus status )
+                    {
+                    }
+                } );
+            }
+
+            if( !command.entity().get().equals( "right" ) )
+            {
+                throw new IllegalArgumentException( "Wrong argument" );
+            }
+
+            // Done
+        }
+
+        public void delete()
+        {
+            // Ok!
+            command = "delete";
+        }
+    }
+
+    public static class SubContext
+        implements InteractionValidation
+    {
+        @Structure
+        Module module;
+
+        public TestResult queryWithValue( TestQuery query )
+        {
+            return module.newValueFromSerializedState( TestResult.class, "{\"xyz\":\"bar\"}" );
+        }
+
+        // Test interaction constraints
+
+        @Requires( File.class )
+        public TestResult queryWithRoleRequirement( TestQuery query )
+        {
+            return module.newValueFromSerializedState( TestResult.class, "{\"xyz\":\"bar\"}" );
+        }
+
+        @Requires( File.class )
+        public void commandWithRoleRequirement()
+        {
+        }
+
+        // Interaction validation
+        private static boolean xyzValid = true;
+
+        @RequiresValid( "xyz" )
+        public void xyz( @Name( "valid" ) boolean valid )
+        {
+            xyzValid = valid;
+        }
+
+        @RequiresValid( "notxyz" )
+        public void notxyz( @Name( "valid" ) boolean valid )
+        {
+            xyzValid = valid;
+        }
+
+        public boolean isValid( String name )
+        {
+            if( name.equals( "xyz" ) )
+            {
+                return xyzValid;
+            }
+            else if( name.equals( "notxyz" ) )
+            {
+                return !xyzValid;
+            }
+            else
+            {
+                return false;
+            }
+        }
+    }
+
+    public static class SubContext2
+    {
+        @Structure
+        Module module;
+
+        public TestResult genericQuery( TestQuery query )
+        {
+            return module.newValueFromSerializedState( TestResult.class, "{\"xyz\":\"bar\"}" );
+        }
+    }
+
+    public static class PagesResource extends ContextResource
+        implements ResourceIndex<Links>
+    {
+        @Override
+        public Links index()
+        {
+            return new LinksBuilder(module)
+                    .addLink( "Page1", "page1")
+                    .addLink( "Page2", "page2")
+                    .addLink( "Page3", "page3")
+                    .newLinks();
+        }
+    }
+
+    public static class DescribableContext
+    {
+        @Structure
+        Module module;
+
+        Describable describable = new Describable();
+
+        public void bind( @Uses DescribableData describableData )
+        {
+            describable.bind( describableData );
+        }
+
+        public String description()
+        {
+            return describable.description();
+        }
+
+        public void changeDescription( @Name( "description" ) String newDesc )
+        {
+            describable.changeDescription( newDesc );
+        }
+
+        public static class Describable
+            extends Role<DescribableData>
+        {
+            public void changeDescription( String newDesc )
+            {
+                self.description().set( newDesc );
+            }
+
+            public String description()
+            {
+                return self.description().get();
+            }
+        }
+    }
+
+    public interface DescribableData
+    {
+        @UseDefaults
+        Property<String> description();
+    }
+
+    public interface TestComposite
+        extends TransientComposite, DescribableData
+    {
+        @Optional
+        Property<String> foo();
+    }
+}
diff --git a/libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/ContinuousIntegrationTest.java b/libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/ContinuousIntegrationTest.java
new file mode 100644
index 0000000..9d66d36
--- /dev/null
+++ b/libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/ContinuousIntegrationTest.java
@@ -0,0 +1,453 @@
+/*
+ *  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.polygene.library.rest.client;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.rest.client.api.ContextResourceClient;
+import org.apache.polygene.library.rest.client.api.ContextResourceClientFactory;
+import org.apache.polygene.library.rest.client.api.ErrorHandler;
+import org.apache.polygene.library.rest.client.api.HandlerCommand;
+import org.apache.polygene.library.rest.client.spi.ResponseHandler;
+import org.apache.polygene.library.rest.client.spi.ResultHandler;
+import org.apache.polygene.library.rest.common.Resource;
+import org.apache.polygene.library.rest.common.ValueAssembler;
+import org.apache.polygene.library.rest.common.link.Link;
+import org.apache.polygene.library.rest.common.link.Links;
+import org.apache.polygene.library.rest.common.link.LinksBuilder;
+import org.apache.polygene.library.rest.common.link.LinksUtil;
+import org.apache.polygene.library.rest.server.api.ContextResource;
+import org.apache.polygene.library.rest.server.api.ContextRestlet;
+import org.apache.polygene.library.rest.server.assembler.RestServerAssembler;
+import org.apache.polygene.library.rest.server.restlet.NullCommandResult;
+import org.apache.polygene.library.rest.server.spi.CommandResult;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.util.FreePortFinder;
+import org.hamcrest.CoreMatchers;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.restlet.Client;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.Server;
+import org.restlet.Uniform;
+import org.restlet.data.ChallengeScheme;
+import org.restlet.data.Form;
+import org.restlet.data.MediaType;
+import org.restlet.data.Protocol;
+import org.restlet.data.Reference;
+import org.restlet.resource.ResourceException;
+import org.restlet.security.ChallengeAuthenticator;
+import org.restlet.security.MapVerifier;
+import org.restlet.security.User;
+import org.restlet.service.MetadataService;
+
+import static org.apache.polygene.bootstrap.ImportedServiceDeclaration.NEW_OBJECT;
+import static org.apache.polygene.library.rest.client.api.HandlerCommand.command;
+import static org.apache.polygene.library.rest.client.api.HandlerCommand.query;
+import static org.apache.polygene.library.rest.client.api.HandlerCommand.refresh;
+
+/**
+ * ReST Client libraries documentation source snippets.
+ */
+public class ContinuousIntegrationTest
+    extends AbstractPolygeneTest
+{
+    private Server server;
+    private ContextResourceClient crc;
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // General setup of client and server
+        new ClientAssembler().assemble( module );
+        new ValueAssembler().assemble( module );
+        new RestServerAssembler().assemble( module );
+
+        module.objects( NullCommandResult.class );
+        module.importedServices( CommandResult.class ).importedBy( NEW_OBJECT );
+
+        module.importedServices( MetadataService.class ).importedBy( NEW_OBJECT );
+        module.objects( MetadataService.class );
+
+        // Test specific setup
+        module.values( BuildSpec.class, BuildResult.class, ServerStatus.class, TagBuildCommand.class, RunBuildCommand.class );
+
+        module.objects( RootRestlet.class, RootResource.class, RootContext.class );
+    }
+
+    @Override
+    protected void initApplication( Application app )
+        throws Exception
+    {
+    }
+
+    @Before
+    public void startWebServer()
+        throws Exception
+    {
+        int port = FreePortFinder.findFreePortOnLoopback();
+        server = new Server( Protocol.HTTP, port );
+        ContextRestlet restlet = objectFactory.newObject( ContextRestlet.class, new org.restlet.Context() );
+
+        ChallengeAuthenticator guard = new ChallengeAuthenticator( null, ChallengeScheme.HTTP_BASIC, "testRealm" );
+        MapVerifier mapVerifier = new MapVerifier();
+        mapVerifier.getLocalSecrets().put( "rickard", "secret".toCharArray() );
+        guard.setVerifier( mapVerifier );
+
+        guard.setNext( restlet );
+
+        server.setNext( guard );
+        server.start();
+
+        //START SNIPPET: client-create1
+        Client client = new Client( Protocol.HTTP );
+
+        ContextResourceClientFactory contextResourceClientFactory = objectFactory.newObject( ContextResourceClientFactory.class, client );
+        contextResourceClientFactory.setAcceptedMediaTypes( MediaType.APPLICATION_JSON );
+        //END SNIPPET: client-create1
+
+        //START SNIPPET: client-create2
+        contextResourceClientFactory.setErrorHandler( new ErrorHandler().onError( ErrorHandler.AUTHENTICATION_REQUIRED, new ResponseHandler()
+        {
+            boolean tried = false;
+
+            @Override
+            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+            {
+                if( tried )
+                {
+                    throw new ResourceException( response.getStatus() );
+                }
+
+                tried = true;
+                client.getContextResourceClientFactory().getInfo().setUser( new User( "rickard", "secret" ) );
+
+                // Try again
+                return refresh();
+            }
+        } ).onError( ErrorHandler.RECOVERABLE_ERROR, new ResponseHandler()
+        {
+            @Override
+            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+            {
+                // Try to restart
+                return refresh();
+            }
+        } ) );
+        //END SNIPPET: client-create2
+
+        //START SNIPPET: client-create3
+        Reference ref = new Reference( "http://localhost:" + port + '/' );
+        crc = contextResourceClientFactory.newClient( ref );
+        //END SNIPPET: client-create3
+    }
+
+    @After
+    public void stopWebServer()
+        throws Exception
+    {
+        server.stop();
+    }
+
+    @Override
+    protected Application newApplicationInstance( ApplicationDescriptor applicationModel )
+    {
+        return applicationModel.newInstance( polygene.api(), new MetadataService() );
+    }
+
+    @Test
+    public void testServerStatus()
+    {
+        //START SNIPPET: query-without-value
+        crc.onResource( new ResultHandler<Resource>()
+        {
+            @Override
+            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
+            {
+                return query( "status" );
+            }
+        } ).onQuery( "status", new ResultHandler<ServerStatus>()
+            {
+                @Override
+                public HandlerCommand handleResult( ServerStatus result, ContextResourceClient client )
+                {
+                    Assert.assertThat( result.currentStatus().get(), CoreMatchers.equalTo( "Idle" ) );
+                    return null;
+                }
+            } );
+
+        crc.start();
+        //END SNIPPET: query-without-value
+    }
+
+    @Test
+    public void testBuildStatusAndTag()
+    {
+        //START SNIPPET: query-and-command
+        crc.onResource( new ResultHandler<Resource>()
+        {
+            @Override
+            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
+            {
+                return query( "buildstatus", null );
+            }
+        } ).onProcessingError( "buildstatus", new ResultHandler<BuildSpec>()
+        {
+            @Override
+            public HandlerCommand handleResult( BuildSpec result, ContextResourceClient client )
+            {
+                ValueBuilder<BuildSpec> builder = valueBuilderFactory.newValueBuilderWithPrototype( result );
+
+                builder.prototype().buildNo().set( "#28" );
+
+                return query( "buildstatus", builder.newInstance() );
+            }
+        } ).onQuery( "buildstatus", new ResultHandler<BuildResult>()
+        {
+            @Override
+            public HandlerCommand handleResult( BuildResult result, ContextResourceClient client )
+            {
+                return command( "tagbuild", null );
+            }
+        } ).onProcessingError( "tagbuild", new ResultHandler<Form>()
+        {
+            @Override
+            public HandlerCommand handleResult( Form result, ContextResourceClient client )
+            {
+                result.set( "tag", "RC1" );
+                result.set( "buildNo", "#28" );
+
+                return command( "tagbuild", result );
+            }
+        } );
+
+        crc.start();
+        //END SNIPPET: query-and-command
+    }
+
+    @Test
+    public void testRunBuild()
+    {
+        //START SNIPPET: query-list-and-command
+        crc.onResource( new ResultHandler<Resource>()
+        {
+            @Override
+            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
+            {
+                return query( "runbuild" );
+            }
+        } ).onQuery( "runbuild", new ResultHandler<Links>()
+        {
+            @Override
+            public HandlerCommand handleResult( Links result, ContextResourceClient client )
+            {
+                Link link = LinksUtil.withId( "any", result );
+
+                return command( link );
+            }
+        } ).onCommand( "runbuild", new ResponseHandler()
+        {
+            @Override
+            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+            {
+                System.out.println( "Done" );
+                return null;
+            }
+        } );
+
+        crc.start();
+        //END SNIPPET: query-list-and-command
+    }
+
+    @Test
+    public void testRunBuildProgressive()
+    {
+        //START SNIPPET: query-list-and-command-progressive
+        crc.onResource( new ResultHandler<Resource>()
+        {
+            @Override
+            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
+            {
+                return query( "runbuild" ).onSuccess( new ResultHandler<Links>()
+                {
+                    @Override
+                    public HandlerCommand handleResult( Links result, ContextResourceClient client )
+                    {
+                        Link link = LinksUtil.withId( "any", result );
+
+                        return command( link ).onSuccess( new ResponseHandler()
+                        {
+                            @Override
+                            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+                            {
+                                System.out.println( "Done" );
+                                return null;
+                            }
+                        } );
+                    }
+                } );
+            }
+        } );
+
+        crc.start();
+        //END SNIPPET: query-list-and-command-progressive
+    }
+
+    public interface TagBuildCommand
+        extends ValueComposite
+    {
+        Property<String> buildNo();
+
+        Property<String> tag();
+
+        @Optional
+        Property<String> comment();
+    }
+
+    public interface BuildResult
+        extends ValueComposite
+    {
+        Property<String> buildNo();
+
+        Property<Integer> testsPassed();
+
+        Property<Integer> testsFailed();
+    }
+
+    public interface BuildSpec
+        extends ValueComposite
+    {
+        @Optional
+        Property<String> buildNo();
+
+        @Optional
+        Property<String> tag();
+    }
+
+    public interface ServerStatus
+        extends ValueComposite
+    {
+        Property<String> currentStatus();
+
+        Property<Integer> availableAgents();
+    }
+
+    public interface RunBuildCommand
+        extends ValueComposite
+    {
+        Property<String> entity();
+    }
+
+    public static class RootRestlet
+        extends ContextRestlet
+    {
+        @Override
+        protected Uniform createRoot( Request request, Response response )
+        {
+            return objectFactory.newObject( RootResource.class, this );
+        }
+    }
+
+    public static class RootResource
+        extends ContextResource
+    {
+
+        private RootContext rootContext()
+        {
+            return context( RootContext.class );
+        }
+
+        public RootResource()
+        {
+        }
+
+        public BuildResult buildstatus( BuildSpec build )
+            throws Throwable
+        {
+            return rootContext().buildStatus( build );
+        }
+
+        public ServerStatus status()
+            throws Throwable
+        {
+            return rootContext().serverStatus();
+        }
+
+        public void tagbuild( TagBuildCommand command )
+            throws Throwable
+        {
+            rootContext().tagBuild( command );
+        }
+
+        public void runbuild( RunBuildCommand run )
+        {
+            rootContext().runBuildOn( run.entity().get() );
+        }
+
+        public Links runbuild()
+        {
+            return new LinksBuilder( module ).
+                command( "runbuild" ).
+                addLink( "On available agent", "any" ).
+                addLink( "On LinuxAgent", "LinuxAgent" ).
+                addLink( "On WinAgent", "WinAgent" ).newLinks();
+        }
+    }
+
+    public static class RootContext
+    {
+
+        @Structure
+        Module module;
+
+        public BuildResult buildStatus( BuildSpec build )
+        {
+            String buildNo = build.buildNo().get(); // or lookup by tag
+            return module.newValueFromSerializedState( BuildResult.class, "{ \"buildNo\":\"" + buildNo + "\", \"testsPassed\": 37, \"testsFailed\": 1}" );
+        }
+
+        public ServerStatus serverStatus()
+        {
+            return module.newValueFromSerializedState( ServerStatus.class, "{\"currentStatus\":\"Idle\", \"availableAgents\": 2  }" );
+        }
+
+        public void tagBuild( TagBuildCommand command )
+        {
+            // tagged
+        }
+
+        public void runBuildOn( String agent )
+        {
+            // build started
+        }
+    }
+}
diff --git a/libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/RssReaderTest.java b/libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/RssReaderTest.java
new file mode 100644
index 0000000..bb241df
--- /dev/null
+++ b/libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/RssReaderTest.java
@@ -0,0 +1,176 @@
+/*
+ *  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.polygene.library.rest.client;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.rest.client.api.ContextResourceClient;
+import org.apache.polygene.library.rest.client.api.ContextResourceClientFactory;
+import org.apache.polygene.library.rest.client.api.ErrorHandler;
+import org.apache.polygene.library.rest.client.api.HandlerCommand;
+import org.apache.polygene.library.rest.client.spi.ResponseHandler;
+import org.apache.polygene.library.rest.client.spi.ResponseReader;
+import org.apache.polygene.library.rest.client.spi.ResultHandler;
+import org.apache.polygene.library.rest.common.ValueAssembler;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.restlet.Client;
+import org.restlet.Response;
+import org.restlet.data.Protocol;
+import org.restlet.data.Reference;
+import org.restlet.resource.ResourceException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import static org.apache.polygene.library.rest.client.api.HandlerCommand.refresh;
+import static org.apache.polygene.test.util.Assume.assumeConnectivity;
+
+/**
+ * Reads Qi4j Github commits on develop ATOM feed and prints out all title and detail url for each entry.
+ * This is an example of how to use the RSS client for something more generic that was not produced by Polygene REST server
+ * library.
+ */
+public class RssReaderTest
+    extends AbstractPolygeneTest
+{
+
+    @BeforeClass
+    public static void beforeRssReaderTest()
+    {
+        assumeConnectivity( "github.com", 443 );
+    }
+
+    private ContextResourceClient crc;
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        // General setup of client
+        new ClientAssembler().assemble( module );
+        new ValueAssembler().assemble( module );
+    }
+
+    @Test
+    public void testReadRssFeed()
+    {
+        Client client = new Client( Protocol.HTTPS );
+        Reference ref = new Reference( "https://github.com/Qi4j/qi4j-sdk/commits/develop.atom" );
+        ContextResourceClientFactory contextResourceClientFactory = objectFactory.newObject( ContextResourceClientFactory.class, client );
+
+        contextResourceClientFactory.registerResponseReader( new ResponseReader()
+        {
+            @Override
+            public Object readResponse( Response response, Class<?> resultType )
+                throws ResourceException
+            {
+                if( resultType.equals( Document.class ) )
+                {
+                    try
+                    {
+                        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+                        documentBuilderFactory.setNamespaceAware( false );
+                        return documentBuilderFactory.newDocumentBuilder().parse( response.getEntity().getStream() );
+                    }
+                    catch( Exception e )
+                    {
+                        throw new ResourceException( e );
+                    }
+                }
+
+                return null;
+            }
+        } );
+
+        contextResourceClientFactory.setErrorHandler( new ErrorHandler().onError( ErrorHandler.RECOVERABLE_ERROR, new ResponseHandler()
+        {
+            @Override
+            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+            {
+                System.out.println( ">> REFRESH on recoverable error: " + response.getStatus() );
+                return refresh();
+            }
+        } ) );
+
+        crc = contextResourceClientFactory.newClient( ref );
+
+        crc.onResource( new ResultHandler<Document>()
+        {
+            Iterator<Node> itemNodes;
+
+            @Override
+            public HandlerCommand handleResult( Document result, ContextResourceClient client )
+            {
+                try
+                {
+                    final XPath xPath = XPathFactory.newInstance().newXPath();
+
+                    System.out.println( "== " + xPath.evaluate( "feed/title", result ) + " ==" );
+
+                    final NodeList nodes = (NodeList) xPath.evaluate( "feed/entry", result, XPathConstants.NODESET );
+                    List<Node> items = new ArrayList<>();
+                    for( int i = 0; i < nodes.getLength(); i++ )
+                    {
+                        items.add( nodes.item( i ) );
+                    }
+
+                    itemNodes = items.iterator();
+
+                    return processEntry( xPath );
+                }
+                catch( XPathExpressionException e )
+                {
+                    throw new ResourceException( e );
+                }
+            }
+
+            private HandlerCommand processEntry( final XPath xPath )
+                throws XPathExpressionException
+            {
+                if( !itemNodes.hasNext() )
+                {
+                    return null;
+                }
+
+                Node item = itemNodes.next();
+
+                String title = xPath.evaluate( "title", item );
+                String detailUrl = xPath.evaluate( "link/@href", item );
+
+                System.out.println( "-- " + title + " --" );
+                System.out.println( "-- " + detailUrl + " --" );
+
+                return processEntry( xPath );
+            }
+        } );
+
+        crc.start();
+    }
+}
diff --git a/libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/docsupport/RestPrimerDocs.java b/libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/docsupport/RestPrimerDocs.java
new file mode 100644
index 0000000..d805192
--- /dev/null
+++ b/libraries/rest-client/src/test/java/org/apache/polygene/library/rest/client/docsupport/RestPrimerDocs.java
@@ -0,0 +1,126 @@
+/*
+ *  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.polygene.library.rest.client.docsupport;
+
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.library.rest.client.api.ContextResourceClient;
+import org.apache.polygene.library.rest.client.api.ContextResourceClientFactory;
+import org.apache.polygene.library.rest.client.api.ErrorHandler;
+import org.apache.polygene.library.rest.client.api.HandlerCommand;
+import org.apache.polygene.library.rest.client.spi.NullResponseHandler;
+import org.apache.polygene.library.rest.client.spi.ResponseHandler;
+import org.apache.polygene.library.rest.client.spi.ResultHandler;
+import org.apache.polygene.library.rest.common.Resource;
+import org.restlet.Client;
+import org.restlet.Response;
+import org.restlet.data.MediaType;
+import org.restlet.data.Protocol;
+import org.restlet.data.Reference;
+import org.restlet.resource.ResourceException;
+import org.restlet.security.User;
+
+import static org.apache.polygene.library.rest.client.api.HandlerCommand.query;
+import static org.apache.polygene.library.rest.client.api.HandlerCommand.refresh;
+
+public class RestPrimerDocs
+{
+
+    private Module module;
+
+    private ContextResourceClient crc;
+
+    {
+// START SNIPPET: 1
+    crc.onResource( new ResultHandler<Resource>()
+    {
+        @Override
+        public HandlerCommand handleResult( Resource result, ContextResourceClient client )
+        {
+            // This may throw IAE if no link with relation
+            // "querywithoutvalue" is found in the Resource
+            return query( "querywithoutvalue", null );
+        }
+    } ).
+    onQuery( "querywithoutvalue", new ResultHandler<TestResult>()
+    {
+        @Override
+        public HandlerCommand handleResult( TestResult result, ContextResourceClient client )
+        {
+            Assert.assertThat(result.xyz().get(), CoreMatchers.equalTo("bar"));
+            return null;
+        }
+    } );
+
+    crc.start();
+// END SNIPPET: 1
+    }
+
+    {
+// START SNIPPET: 2
+// Create Restlet client and bookmark Reference
+    Client client = new Client( Protocol.HTTP );
+    Reference ref = new Reference( "http://localhost:8888/" );
+    ContextResourceClientFactory contextResourceClientFactory = module.newObject( ContextResourceClientFactory.class, client, new NullResponseHandler() );
+    contextResourceClientFactory.setAcceptedMediaTypes( MediaType.APPLICATION_JSON );
+
+// Handle logins
+    contextResourceClientFactory.setErrorHandler( new ErrorHandler().onError( ErrorHandler.AUTHENTICATION_REQUIRED, new ResponseHandler()
+    {
+        // Only try to login once
+        boolean tried = false;
+
+        @Override
+        public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+        {
+            // If we have already tried to login, fail!
+            if (tried)
+                throw new ResourceException( response.getStatus() );
+
+            tried = true;
+            client.getContextResourceClientFactory().getInfo().setUser( new User("rickard", "secret") );
+
+            // Try again
+            return refresh();
+        }
+    } ).onError( ErrorHandler.RECOVERABLE_ERROR, new ResponseHandler()
+    {
+        @Override
+        public HandlerCommand handleResponse( Response response, ContextResourceClient client )
+        {
+            // Try to restart this scenario
+            return refresh();
+        }
+    } ) );
+
+    crc = contextResourceClientFactory.newClient( ref );
+    // END SNIPPET: 2
+    }
+
+    public interface TestResult
+            extends ValueComposite
+    {
+        Property<String> xyz();
+    }
+
+}
\ No newline at end of file
diff --git a/libraries/rest-client/src/test/java/org/qi4j/library/rest/client/ContextResourceClientFactoryTest.java b/libraries/rest-client/src/test/java/org/qi4j/library/rest/client/ContextResourceClientFactoryTest.java
deleted file mode 100644
index 7175b9e..0000000
--- a/libraries/rest-client/src/test/java/org/qi4j/library/rest/client/ContextResourceClientFactoryTest.java
+++ /dev/null
@@ -1,754 +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.qi4j.library.rest.client;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Collections;
-import org.hamcrest.CoreMatchers;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.constraint.Name;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.ConcurrentEntityModificationException;
-import org.qi4j.api.unitofwork.UnitOfWorkCallback;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.rest.client.api.ContextResourceClient;
-import org.qi4j.library.rest.client.api.ContextResourceClientFactory;
-import org.qi4j.library.rest.client.api.ErrorHandler;
-import org.qi4j.library.rest.client.api.HandlerCommand;
-import org.qi4j.library.rest.client.spi.ResponseHandler;
-import org.qi4j.library.rest.client.spi.ResultHandler;
-import org.qi4j.library.rest.common.Resource;
-import org.qi4j.library.rest.common.ValueAssembler;
-import org.qi4j.library.rest.common.link.Link;
-import org.qi4j.library.rest.common.link.Links;
-import org.qi4j.library.rest.common.link.LinksBuilder;
-import org.qi4j.library.rest.common.link.LinksUtil;
-import org.qi4j.library.rest.server.api.ContextResource;
-import org.qi4j.library.rest.server.api.ContextRestlet;
-import org.qi4j.library.rest.server.api.ObjectSelection;
-import org.qi4j.library.rest.server.api.ResourceDelete;
-import org.qi4j.library.rest.server.api.ResourceIndex;
-import org.qi4j.library.rest.server.api.SubResource;
-import org.qi4j.library.rest.server.api.SubResources;
-import org.qi4j.library.rest.server.api.constraint.InteractionValidation;
-import org.qi4j.library.rest.server.api.constraint.Requires;
-import org.qi4j.library.rest.server.api.constraint.RequiresValid;
-import org.qi4j.library.rest.server.api.dci.Role;
-import org.qi4j.library.rest.server.assembler.RestServerAssembler;
-import org.qi4j.library.rest.server.restlet.NullCommandResult;
-import org.qi4j.library.rest.server.spi.CommandResult;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-import org.restlet.Client;
-import org.restlet.Request;
-import org.restlet.Response;
-import org.restlet.Server;
-import org.restlet.Uniform;
-import org.restlet.data.ChallengeScheme;
-import org.restlet.data.Form;
-import org.restlet.data.MediaType;
-import org.restlet.data.Protocol;
-import org.restlet.data.Reference;
-import org.restlet.resource.ResourceException;
-import org.restlet.security.ChallengeAuthenticator;
-import org.restlet.security.MapVerifier;
-import org.restlet.security.User;
-import org.restlet.service.MetadataService;
-
-import static org.qi4j.bootstrap.ImportedServiceDeclaration.*;
-import static org.qi4j.library.rest.client.api.HandlerCommand.*;
-
-public class ContextResourceClientFactoryTest
-    extends AbstractQi4jTest
-{
-    private Server server;
-    private ContextResourceClient crc;
-
-    public static String command = null; // Commands will set this
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // General setup of client and server
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        new ClientAssembler().assemble( module );
-        new ValueAssembler().assemble( module );
-        new RestServerAssembler().assemble( module );
-
-        module.objects( NullCommandResult.class );
-        module.importedServices( CommandResult.class ).importedBy( NEW_OBJECT );
-
-        module.importedServices( MetadataService.class ).importedBy( NEW_OBJECT );
-        module.objects( MetadataService.class );
-
-        // Test specific setup
-        module.values( TestQuery.class, TestResult.class, TestCommand.class );
-        module.forMixin( TestQuery.class ).declareDefaults().abc().set( "def" );
-
-        module.objects( RootRestlet.class, RootResource.class, RootContext.class, SubResource1.class, PagesResource.class );
-
-
-        module.objects( DescribableContext.class );
-        module.transients( TestComposite.class );
-    }
-
-    @Override
-    protected void initApplication( Application app )
-        throws Exception
-    {
-    }
-
-    @Before
-    public void startWebServer()
-        throws Exception
-    {
-        server = new Server( Protocol.HTTP, 8888 );
-        ContextRestlet restlet = module.newObject( ContextRestlet.class, new org.restlet.Context() );
-
-        ChallengeAuthenticator guard = new ChallengeAuthenticator(null, ChallengeScheme.HTTP_BASIC, "testRealm");
-        MapVerifier mapVerifier = new MapVerifier();
-        mapVerifier.getLocalSecrets().put("rickard", "secret".toCharArray());
-        guard.setVerifier(mapVerifier);
-
-        guard.setNext(restlet);
-
-        server.setNext( guard );
-        server.start();
-
-        //START SNIPPET: client-create1
-        Client client =   new Client( Protocol.HTTP );
-
-        ContextResourceClientFactory contextResourceClientFactory = module.newObject( ContextResourceClientFactory.class, client );
-        contextResourceClientFactory.setAcceptedMediaTypes( MediaType.APPLICATION_JSON );
-        //END SNIPPET: client-create1
-
-        //START SNIPPET: client-create2
-        contextResourceClientFactory.setErrorHandler( new ErrorHandler().onError( ErrorHandler.AUTHENTICATION_REQUIRED, new ResponseHandler()
-        {
-            boolean tried = false;
-
-            @Override
-            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-            {
-                    if (tried)
-                        throw new ResourceException( response.getStatus() );
-
-                    tried = true;
-                    client.getContextResourceClientFactory().getInfo().setUser( new User("rickard", "secret") );
-
-                    // Try again
-                    return refresh();
-            }
-        } ).onError( ErrorHandler.RECOVERABLE_ERROR, new ResponseHandler()
-        {
-            @Override
-            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-            {
-                // Try to restart
-                return refresh();
-            }
-        } ) );
-        //END SNIPPET: client-create2
-
-        //START SNIPPET: client-create3
-        Reference ref = new Reference( "http://localhost:8888/" );
-        crc = contextResourceClientFactory.newClient( ref );
-        //END SNIPPET: client-create3
-    }
-
-    @After
-    public void stopWebServer()
-        throws Exception
-    {
-        server.stop();
-    }
-
-    @Override
-    protected Application newApplicationInstance( ApplicationDescriptor applicationModel )
-    {
-        return applicationModel.newInstance( qi4j.api(), new MetadataService() );
-    }
-
-    @Test
-    public void testQueryWithoutValue()
-    {
-        //START SNIPPET: query-without-value
-        crc.onResource( new ResultHandler<Resource>()
-        {
-            @Override
-            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
-            {
-                return query( "querywithoutvalue" );
-            }
-        } ).
-        onQuery( "querywithoutvalue", new ResultHandler<TestResult>()
-        {
-            @Override
-            public HandlerCommand handleResult( TestResult result, ContextResourceClient client )
-            {
-                Assert.assertThat( result.xyz().get(), CoreMatchers.equalTo( "bar" ) );
-                return null;
-            }
-        } );
-
-        crc.start();
-        //END SNIPPET: query-without-value
-    }
-
-    @Test
-    public void testQueryAndCommand()
-    {
-        //START SNIPPET: query-and-command
-        crc.onResource( new ResultHandler<Resource>()
-        {
-            @Override
-            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
-            {
-                return query( "querywithvalue", null );
-            }
-        } ).onProcessingError( "querywithvalue", new ResultHandler<TestQuery>()
-        {
-            @Override
-            public HandlerCommand handleResult( TestQuery result, ContextResourceClient client )
-            {
-                ValueBuilder<TestQuery> builder = module.newValueBuilderWithPrototype( result );
-
-                builder.prototype().abc().set( "abc" + builder.prototype().abc().get() );
-
-                return query( "querywithvalue", builder.newInstance() );
-            }
-        } ).onQuery( "querywithvalue", new ResultHandler<TestResult>()
-        {
-            @Override
-            public HandlerCommand handleResult( TestResult result, ContextResourceClient client )
-            {
-                return command( "commandwithvalue", null );
-            }
-        } ).onProcessingError( "commandwithvalue", new ResultHandler<Form>()
-        {
-            @Override
-            public HandlerCommand handleResult( Form result, ContextResourceClient client )
-            {
-                result.set( "abc", "right" );
-
-                return command( "commandwithvalue", result );
-            }
-        } );
-
-        crc.start();
-        //END SNIPPET: query-and-command
-    }
-
-    @Test
-    public void testQueryListAndCommand()
-    {
-        //START SNIPPET: query-list-and-command
-        crc.onResource( new ResultHandler<Resource>()
-        {
-            @Override
-            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
-            {
-                return query( "commandwithvalue" );
-            }
-        } ).onQuery( "commandwithvalue", new ResultHandler<Links>()
-        {
-            @Override
-            public HandlerCommand handleResult( Links result, ContextResourceClient client )
-            {
-                Link link = LinksUtil.withId( "right", result );
-
-                return command( link );
-            }
-        } ).onCommand( "commandwithvalue", new ResponseHandler()
-        {
-            @Override
-            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-            {
-                System.out.println( "Done" );
-                return null;
-            }
-        } );
-
-        crc.start();
-        //END SNIPPET: query-list-and-command
-    }
-
-    @Test
-    public void testQueryListAndCommandProgressive()
-    {
-        //START SNIPPET: query-list-and-command-progressive
-        crc.onResource( new ResultHandler<Resource>()
-        {
-            @Override
-            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
-            {
-                return query( "commandwithvalue" ).onSuccess( new ResultHandler<Links>()
-                {
-                    @Override
-                    public HandlerCommand handleResult( Links result, ContextResourceClient client )
-                    {
-                        Link link = LinksUtil.withId( "right", result );
-
-                        return command( link ).onSuccess( new ResponseHandler()
-                        {
-                            @Override
-                            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-                            {
-                                System.out.println( "Done" );
-                                return null;
-                            }
-                        } );
-                    }
-                } );
-            }
-        } );
-
-        crc.start();
-        //END SNIPPET: query-list-and-command-progressive
-    }
-
-    @Test
-    public void testIndexedResource()
-    {
-        crc.newClient("subcontext/pages/").onResource( new ResultHandler<Resource>()
-        {
-            @Override
-            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
-            {
-                return query( "index" );
-            }
-        } ).onQuery( "index", new ResultHandler<Links>()
-                {
-                    @Override
-                    public HandlerCommand handleResult( Links result, ContextResourceClient client )
-                    {
-                        Assert.assertEquals( result.links().get().size(), 3 );
-                        return null;
-                    }
-                } )
-        .start();
-
-    }
-
-    public interface TestQuery
-        extends ValueComposite
-    {
-        @UseDefaults
-        Property<String> abc();
-    }
-
-    public interface TestCommand
-        extends ValueComposite
-    {
-        Property<String> entity();
-    }
-
-    public interface TestResult
-        extends ValueComposite
-    {
-        Property<String> xyz();
-    }
-
-    public static class RootRestlet
-        extends ContextRestlet
-    {
-        @Override
-        protected Uniform createRoot( Request request, Response response )
-        {
-            return module.newObject( RootResource.class, this );
-        }
-    }
-
-    public static class RootResource
-        extends ContextResource
-        implements SubResources, ResourceDelete
-    {
-        private static TestComposite instance;
-
-        private RootContext rootContext()
-        {
-            return context( RootContext.class );
-        }
-
-        public RootResource()
-        {
-        }
-
-        public TestResult querywithvalue( TestQuery testQuery )
-            throws Throwable
-        {
-            return rootContext().queryWithValue( testQuery );
-        }
-
-        public TestResult querywithoutvalue()
-            throws Throwable
-        {
-            return rootContext().queryWithoutValue();
-        }
-
-        public String querywithstringresult( TestQuery query )
-            throws Throwable
-        {
-            return rootContext().queryWithStringResult( query );
-        }
-
-        public void commandwithvalue( TestCommand command )
-            throws Throwable
-        {
-            rootContext().commandWithValue( command );
-        }
-
-        public Links commandwithvalue()
-        {
-            return new LinksBuilder(module).
-                command( "commandwithvalue" ).
-                addLink( "Command ABC","right" ).
-                addLink( "Command XYZ", "wrong" ).newLinks();
-        }
-
-        @Override
-        public void delete()
-            throws IOException
-        {
-            rootContext().delete();
-        }
-
-        public void resource( String currentSegment )
-        {
-            ObjectSelection objectSelection = ObjectSelection.current();
-
-            objectSelection.select( new File( "" ) );
-
-            if( instance == null )
-            {
-                objectSelection.select( instance = module.newTransient( TestComposite.class ) );
-            }
-            else
-            {
-                objectSelection.select( instance );
-            }
-
-            subResource( SubResource1.class );
-        }
-    }
-
-    public static class SubResource1
-        extends ContextResource
-        implements InteractionValidation
-    {
-        public SubResource1()
-        {
-        }
-
-        @Requires( File.class )
-        public void commandWithRoleRequirement()
-        {
-            context( SubContext.class ).commandWithRoleRequirement();
-        }
-
-        // Interaction validation
-        private static boolean xyzValid = true;
-
-        @RequiresValid( "xyz" )
-        public void xyz( @Name( "valid" ) boolean valid )
-        {
-            xyzValid = valid;
-        }
-
-        @RequiresValid( "notxyz" )
-        public void notxyz( @Name( "valid" ) boolean valid )
-        {
-            xyzValid = valid;
-        }
-
-        public boolean isValid( String name )
-        {
-            if( name.equals( "xyz" ) )
-            {
-                return xyzValid;
-            }
-            else if( name.equals( "notxyz" ) )
-            {
-                return !xyzValid;
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-        @Requires( File.class )
-        public TestResult queryWithRoleRequirement(TestQuery query)
-        {
-            return context( SubContext.class ).queryWithRoleRequirement( query );
-        }
-
-        public TestResult genericquery( TestQuery query )
-            throws Throwable
-        {
-            return context( SubContext2.class ).genericQuery( query );
-        }
-
-        public TestResult querywithvalue( TestQuery query )
-            throws Throwable
-        {
-            return context( SubContext.class ).queryWithValue( query );
-        }
-
-        @SubResource
-        public void subresource1()
-        {
-            subResource( SubResource1.class );
-        }
-
-        @SubResource
-        public void subresource2()
-        {
-            subResource( SubResource1.class );
-        }
-
-        @SubResource
-        public void pages() {
-            subResource( PagesResource.class );
-        }
-    }
-
-    public static class RootContext
-    {
-        private static int count = 0;
-
-        @Structure
-        Module module;
-
-        public TestResult queryWithValue( TestQuery query )
-        {
-            return module.newValueFromSerializedState( TestResult.class, "{'xyz':'"+query.abc().get()+"'}" );
-        }
-
-        public TestResult queryWithoutValue()
-        {
-            return module.newValueFromSerializedState( TestResult.class, "{'xyz':'bar'}" );
-        }
-
-        public String queryWithStringResult( TestQuery query )
-        {
-            return "bar";
-        }
-
-        public int queryWithIntegerResult( TestQuery query )
-        {
-            return 7;
-        }
-
-        public void commandWithValue( TestCommand command )
-        {
-            if( !command.entity().get().equals( "right" ) )
-            {
-                throw new IllegalArgumentException( "Wrong argument" );
-            }
-
-            // Done
-        }
-
-        public void idempotentCommandWithValue( TestCommand command )
-            throws ConcurrentEntityModificationException
-        {
-            // On all but every third invocation, throw a concurrency exception
-            // This is to test retries on the server-side
-            count++;
-            if( count % 3 != 0 )
-            {
-                module.currentUnitOfWork().addUnitOfWorkCallback( new UnitOfWorkCallback()
-                {
-                    public void beforeCompletion()
-                        throws UnitOfWorkCompletionException
-                    {
-                        throw new ConcurrentEntityModificationException( Collections.<EntityComposite>emptyList() );
-                    }
-
-                    public void afterCompletion( UnitOfWorkStatus status )
-                    {
-                    }
-                } );
-            }
-
-            if( !command.entity().get().equals( "right" ) )
-            {
-                throw new IllegalArgumentException( "Wrong argument" );
-            }
-
-            // Done
-        }
-
-        public void delete()
-        {
-            // Ok!
-            command = "delete";
-        }
-    }
-
-    public static class SubContext
-        implements InteractionValidation
-    {
-        @Structure
-        Module module;
-
-        public TestResult queryWithValue( TestQuery query )
-        {
-            return module.newValueFromSerializedState( TestResult.class, "{'xyz':'bar'}" );
-        }
-
-        // Test interaction constraints
-
-        @Requires( File.class )
-        public TestResult queryWithRoleRequirement( TestQuery query )
-        {
-            return module.newValueFromSerializedState( TestResult.class, "{'xyz':'bar'}" );
-        }
-
-        @Requires( File.class )
-        public void commandWithRoleRequirement()
-        {
-        }
-
-        // Interaction validation
-        private static boolean xyzValid = true;
-
-        @RequiresValid( "xyz" )
-        public void xyz( @Name( "valid" ) boolean valid )
-        {
-            xyzValid = valid;
-        }
-
-        @RequiresValid( "notxyz" )
-        public void notxyz( @Name( "valid" ) boolean valid )
-        {
-            xyzValid = valid;
-        }
-
-        public boolean isValid( String name )
-        {
-            if( name.equals( "xyz" ) )
-            {
-                return xyzValid;
-            }
-            else if( name.equals( "notxyz" ) )
-            {
-                return !xyzValid;
-            }
-            else
-            {
-                return false;
-            }
-        }
-    }
-
-    public static class SubContext2
-    {
-        @Structure
-        Module module;
-
-        public TestResult genericQuery( TestQuery query )
-        {
-            return module.newValueFromSerializedState( TestResult.class, "{'xyz':'bar'}" );
-        }
-    }
-
-    public static class PagesResource extends ContextResource
-        implements ResourceIndex<Links>
-    {
-        @Override
-        public Links index()
-        {
-            return new LinksBuilder(module)
-                    .addLink( "Page1", "page1")
-                    .addLink( "Page2", "page2")
-                    .addLink( "Page3", "page3")
-                    .newLinks();
-        }
-    }
-
-    public static class DescribableContext
-    {
-        @Structure
-        Module module;
-
-        Describable describable = new Describable();
-
-        public void bind( @Uses DescribableData describableData )
-        {
-            describable.bind( describableData );
-        }
-
-        public String description()
-        {
-            return describable.description();
-        }
-
-        public void changeDescription( @Name( "description" ) String newDesc )
-        {
-            describable.changeDescription( newDesc );
-        }
-
-        public static class Describable
-            extends Role<DescribableData>
-        {
-            public void changeDescription( String newDesc )
-            {
-                self.description().set( newDesc );
-            }
-
-            public String description()
-            {
-                return self.description().get();
-            }
-        }
-    }
-
-    public interface DescribableData
-    {
-        @UseDefaults
-        Property<String> description();
-    }
-
-    public interface TestComposite
-        extends TransientComposite, DescribableData
-    {
-        @Optional
-        Property<String> foo();
-    }
-}
diff --git a/libraries/rest-client/src/test/java/org/qi4j/library/rest/client/ContinuousIntegrationTest.java b/libraries/rest-client/src/test/java/org/qi4j/library/rest/client/ContinuousIntegrationTest.java
deleted file mode 100644
index 6b75fe7..0000000
--- a/libraries/rest-client/src/test/java/org/qi4j/library/rest/client/ContinuousIntegrationTest.java
+++ /dev/null
@@ -1,452 +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.qi4j.library.rest.client;
-
-import org.hamcrest.CoreMatchers;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.rest.client.api.ContextResourceClient;
-import org.qi4j.library.rest.client.api.ContextResourceClientFactory;
-import org.qi4j.library.rest.client.api.ErrorHandler;
-import org.qi4j.library.rest.client.api.HandlerCommand;
-import org.qi4j.library.rest.client.spi.ResponseHandler;
-import org.qi4j.library.rest.client.spi.ResultHandler;
-import org.qi4j.library.rest.common.Resource;
-import org.qi4j.library.rest.common.ValueAssembler;
-import org.qi4j.library.rest.common.link.Link;
-import org.qi4j.library.rest.common.link.Links;
-import org.qi4j.library.rest.common.link.LinksBuilder;
-import org.qi4j.library.rest.common.link.LinksUtil;
-import org.qi4j.library.rest.server.api.ContextResource;
-import org.qi4j.library.rest.server.api.ContextRestlet;
-import org.qi4j.library.rest.server.assembler.RestServerAssembler;
-import org.qi4j.library.rest.server.restlet.NullCommandResult;
-import org.qi4j.library.rest.server.spi.CommandResult;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-import org.restlet.Client;
-import org.restlet.Request;
-import org.restlet.Response;
-import org.restlet.Server;
-import org.restlet.Uniform;
-import org.restlet.data.ChallengeScheme;
-import org.restlet.data.Form;
-import org.restlet.data.MediaType;
-import org.restlet.data.Protocol;
-import org.restlet.data.Reference;
-import org.restlet.resource.ResourceException;
-import org.restlet.security.ChallengeAuthenticator;
-import org.restlet.security.MapVerifier;
-import org.restlet.security.User;
-import org.restlet.service.MetadataService;
-
-import static org.qi4j.bootstrap.ImportedServiceDeclaration.NEW_OBJECT;
-import static org.qi4j.library.rest.client.api.HandlerCommand.command;
-import static org.qi4j.library.rest.client.api.HandlerCommand.query;
-import static org.qi4j.library.rest.client.api.HandlerCommand.refresh;
-
-/**
- * ReST Client libraries documentation source snippets.
- */
-public class ContinuousIntegrationTest
-    extends AbstractQi4jTest
-{
-    private Server server;
-    private ContextResourceClient crc;
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // General setup of client and server
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        new ClientAssembler().assemble( module );
-        new ValueAssembler().assemble( module );
-        new RestServerAssembler().assemble( module );
-
-        module.objects( NullCommandResult.class );
-        module.importedServices( CommandResult.class ).importedBy( NEW_OBJECT );
-
-        module.importedServices( MetadataService.class ).importedBy( NEW_OBJECT );
-        module.objects( MetadataService.class );
-
-        // Test specific setup
-        module.values( BuildSpec.class, BuildResult.class, ServerStatus.class, TagBuildCommand.class, RunBuildCommand.class );
-
-        module.objects( RootRestlet.class, RootResource.class, RootContext.class );
-    }
-
-    @Override
-    protected void initApplication( Application app )
-        throws Exception
-    {
-    }
-
-    @Before
-    public void startWebServer()
-        throws Exception
-    {
-        server = new Server( Protocol.HTTP, 8888 );
-        ContextRestlet restlet = module.newObject( ContextRestlet.class, new org.restlet.Context() );
-
-        ChallengeAuthenticator guard = new ChallengeAuthenticator( null, ChallengeScheme.HTTP_BASIC, "testRealm" );
-        MapVerifier mapVerifier = new MapVerifier();
-        mapVerifier.getLocalSecrets().put( "rickard", "secret".toCharArray() );
-        guard.setVerifier( mapVerifier );
-
-        guard.setNext( restlet );
-
-        server.setNext( guard );
-        server.start();
-
-        //START SNIPPET: client-create1
-        Client client = new Client( Protocol.HTTP );
-
-        ContextResourceClientFactory contextResourceClientFactory = module.newObject( ContextResourceClientFactory.class, client );
-        contextResourceClientFactory.setAcceptedMediaTypes( MediaType.APPLICATION_JSON );
-        //END SNIPPET: client-create1
-
-        //START SNIPPET: client-create2
-        contextResourceClientFactory.setErrorHandler( new ErrorHandler().onError( ErrorHandler.AUTHENTICATION_REQUIRED, new ResponseHandler()
-        {
-            boolean tried = false;
-
-            @Override
-            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-            {
-                if( tried )
-                {
-                    throw new ResourceException( response.getStatus() );
-                }
-
-                tried = true;
-                client.getContextResourceClientFactory().getInfo().setUser( new User( "rickard", "secret" ) );
-
-                // Try again
-                return refresh();
-            }
-        } ).onError( ErrorHandler.RECOVERABLE_ERROR, new ResponseHandler()
-        {
-            @Override
-            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-            {
-                // Try to restart
-                return refresh();
-            }
-        } ) );
-        //END SNIPPET: client-create2
-
-        //START SNIPPET: client-create3
-        Reference ref = new Reference( "http://localhost:8888/" );
-        crc = contextResourceClientFactory.newClient( ref );
-        //END SNIPPET: client-create3
-    }
-
-    @After
-    public void stopWebServer()
-        throws Exception
-    {
-        server.stop();
-    }
-
-    @Override
-    protected Application newApplicationInstance( ApplicationDescriptor applicationModel )
-    {
-        return applicationModel.newInstance( qi4j.api(), new MetadataService() );
-    }
-
-    @Test
-    public void testServerStatus()
-    {
-        //START SNIPPET: query-without-value
-        crc.onResource( new ResultHandler<Resource>()
-        {
-            @Override
-            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
-            {
-                return query( "status" );
-            }
-        } ).onQuery( "status", new ResultHandler<ServerStatus>()
-            {
-                @Override
-                public HandlerCommand handleResult( ServerStatus result, ContextResourceClient client )
-                {
-                    Assert.assertThat( result.currentStatus().get(), CoreMatchers.equalTo( "Idle" ) );
-                    return null;
-                }
-            } );
-
-        crc.start();
-        //END SNIPPET: query-without-value
-    }
-
-    @Test
-    public void testBuildStatusAndTag()
-    {
-        //START SNIPPET: query-and-command
-        crc.onResource( new ResultHandler<Resource>()
-        {
-            @Override
-            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
-            {
-                return query( "buildstatus", null );
-            }
-        } ).onProcessingError( "buildstatus", new ResultHandler<BuildSpec>()
-        {
-            @Override
-            public HandlerCommand handleResult( BuildSpec result, ContextResourceClient client )
-            {
-                ValueBuilder<BuildSpec> builder = module.newValueBuilderWithPrototype( result );
-
-                builder.prototype().buildNo().set( "#28" );
-
-                return query( "buildstatus", builder.newInstance() );
-            }
-        } ).onQuery( "buildstatus", new ResultHandler<BuildResult>()
-        {
-            @Override
-            public HandlerCommand handleResult( BuildResult result, ContextResourceClient client )
-            {
-                return command( "tagbuild", null );
-            }
-        } ).onProcessingError( "tagbuild", new ResultHandler<Form>()
-        {
-            @Override
-            public HandlerCommand handleResult( Form result, ContextResourceClient client )
-            {
-                result.set( "tag", "RC1" );
-                result.set( "buildNo", "#28" );
-
-                return command( "tagbuild", result );
-            }
-        } );
-
-        crc.start();
-        //END SNIPPET: query-and-command
-    }
-
-    @Test
-    public void testRunBuild()
-    {
-        //START SNIPPET: query-list-and-command
-        crc.onResource( new ResultHandler<Resource>()
-        {
-            @Override
-            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
-            {
-                return query( "runbuild" );
-            }
-        } ).onQuery( "runbuild", new ResultHandler<Links>()
-        {
-            @Override
-            public HandlerCommand handleResult( Links result, ContextResourceClient client )
-            {
-                Link link = LinksUtil.withId( "any", result );
-
-                return command( link );
-            }
-        } ).onCommand( "runbuild", new ResponseHandler()
-        {
-            @Override
-            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-            {
-                System.out.println( "Done" );
-                return null;
-            }
-        } );
-
-        crc.start();
-        //END SNIPPET: query-list-and-command
-    }
-
-    @Test
-    public void testRunBuildProgressive()
-    {
-        //START SNIPPET: query-list-and-command-progressive
-        crc.onResource( new ResultHandler<Resource>()
-        {
-            @Override
-            public HandlerCommand handleResult( Resource result, ContextResourceClient client )
-            {
-                return query( "runbuild" ).onSuccess( new ResultHandler<Links>()
-                {
-                    @Override
-                    public HandlerCommand handleResult( Links result, ContextResourceClient client )
-                    {
-                        Link link = LinksUtil.withId( "any", result );
-
-                        return command( link ).onSuccess( new ResponseHandler()
-                        {
-                            @Override
-                            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-                            {
-                                System.out.println( "Done" );
-                                return null;
-                            }
-                        } );
-                    }
-                } );
-            }
-        } );
-
-        crc.start();
-        //END SNIPPET: query-list-and-command-progressive
-    }
-
-    public interface TagBuildCommand
-        extends ValueComposite
-    {
-        Property<String> buildNo();
-
-        Property<String> tag();
-
-        @Optional
-        Property<String> comment();
-    }
-
-    public interface BuildResult
-        extends ValueComposite
-    {
-        Property<String> buildNo();
-
-        Property<Integer> testsPassed();
-
-        Property<Integer> testsFailed();
-    }
-
-    public interface BuildSpec
-        extends ValueComposite
-    {
-        @Optional
-        Property<String> buildNo();
-
-        @Optional
-        Property<String> tag();
-    }
-
-    public interface ServerStatus
-        extends ValueComposite
-    {
-        Property<String> currentStatus();
-
-        Property<Integer> availableAgents();
-    }
-
-    public interface RunBuildCommand
-        extends ValueComposite
-    {
-        Property<String> entity();
-    }
-
-    public static class RootRestlet
-        extends ContextRestlet
-    {
-        @Override
-        protected Uniform createRoot( Request request, Response response )
-        {
-            return module.newObject( RootResource.class, this );
-        }
-    }
-
-    public static class RootResource
-        extends ContextResource
-    {
-
-        private RootContext rootContext()
-        {
-            return context( RootContext.class );
-        }
-
-        public RootResource()
-        {
-        }
-
-        public BuildResult buildstatus( BuildSpec build )
-            throws Throwable
-        {
-            return rootContext().buildStatus( build );
-        }
-
-        public ServerStatus status()
-            throws Throwable
-        {
-            return rootContext().serverStatus();
-        }
-
-        public void tagbuild( TagBuildCommand command )
-            throws Throwable
-        {
-            rootContext().tagBuild( command );
-        }
-
-        public void runbuild( RunBuildCommand run )
-        {
-            rootContext().runBuildOn( run.entity().get() );
-        }
-
-        public Links runbuild()
-        {
-            return new LinksBuilder( module ).
-                command( "runbuild" ).
-                addLink( "On available agent", "any" ).
-                addLink( "On LinuxAgent", "LinuxAgent" ).
-                addLink( "On WinAgent", "WinAgent" ).newLinks();
-        }
-    }
-
-    public static class RootContext
-    {
-
-        @Structure
-        Module module;
-
-        public BuildResult buildStatus( BuildSpec build )
-        {
-            String buildNo = build.buildNo().get(); // or lookup by tag
-            return module.newValueFromSerializedState( BuildResult.class, "{ 'buildNo':'" + buildNo + "', 'testsPassed': 37, 'testsFailed': 1}" );
-        }
-
-        public ServerStatus serverStatus()
-        {
-            return module.newValueFromSerializedState( ServerStatus.class, "{'currentStatus':'Idle', 'availableAgents': 2  }" );
-        }
-
-        public void tagBuild( TagBuildCommand command )
-        {
-            // tagged
-        }
-
-        public void runBuildOn( String agent )
-        {
-            // build started
-        }
-    }
-}
diff --git a/libraries/rest-client/src/test/java/org/qi4j/library/rest/client/RssReaderTest.java b/libraries/rest-client/src/test/java/org/qi4j/library/rest/client/RssReaderTest.java
deleted file mode 100644
index 961ef5b..0000000
--- a/libraries/rest-client/src/test/java/org/qi4j/library/rest/client/RssReaderTest.java
+++ /dev/null
@@ -1,177 +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.qi4j.library.rest.client;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpressionException;
-import javax.xml.xpath.XPathFactory;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.rest.client.api.ContextResourceClient;
-import org.qi4j.library.rest.client.api.ContextResourceClientFactory;
-import org.qi4j.library.rest.client.api.ErrorHandler;
-import org.qi4j.library.rest.client.api.HandlerCommand;
-import org.qi4j.library.rest.client.spi.ResponseHandler;
-import org.qi4j.library.rest.client.spi.ResponseReader;
-import org.qi4j.library.rest.client.spi.ResultHandler;
-import org.qi4j.library.rest.common.ValueAssembler;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-import org.restlet.Client;
-import org.restlet.Response;
-import org.restlet.data.Protocol;
-import org.restlet.data.Reference;
-import org.restlet.resource.ResourceException;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import static org.qi4j.library.rest.client.api.HandlerCommand.refresh;
-import static org.qi4j.test.util.Assume.assumeConnectivity;
-
-/**
- * Reads Qi4j Github commits on develop ATOM feed and prints out all title and detail url for each entry.
- * This is an example of how to use the RSS client for something more generic that was not produced by Zest REST server
- * library.
- */
-public class RssReaderTest
-    extends AbstractQi4jTest
-{
-
-    @BeforeClass
-    public static void beforeRssReaderTest()
-    {
-        assumeConnectivity( "github.com", 443 );
-    }
-
-    private ContextResourceClient crc;
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        // General setup of client
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        new ClientAssembler().assemble( module );
-        new ValueAssembler().assemble( module );
-    }
-
-    @Test
-    public void testReadRssFeed()
-    {
-        Client client = new Client( Protocol.HTTPS );
-        Reference ref = new Reference( "https://github.com/Qi4j/qi4j-sdk/commits/develop.atom" );
-        ContextResourceClientFactory contextResourceClientFactory = module.newObject( ContextResourceClientFactory.class, client );
-
-        contextResourceClientFactory.registerResponseReader( new ResponseReader()
-        {
-            @Override
-            public Object readResponse( Response response, Class<?> resultType )
-                throws ResourceException
-            {
-                if( resultType.equals( Document.class ) )
-                {
-                    try
-                    {
-                        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
-                        documentBuilderFactory.setNamespaceAware( false );
-                        return documentBuilderFactory.newDocumentBuilder().parse( response.getEntity().getStream() );
-                    }
-                    catch( Exception e )
-                    {
-                        throw new ResourceException( e );
-                    }
-                }
-
-                return null;
-            }
-        } );
-
-        contextResourceClientFactory.setErrorHandler( new ErrorHandler().onError( ErrorHandler.RECOVERABLE_ERROR, new ResponseHandler()
-        {
-            @Override
-            public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-            {
-                System.out.println( ">> REFRESH on recoverable error: " + response.getStatus() );
-                return refresh();
-            }
-        } ) );
-
-        crc = contextResourceClientFactory.newClient( ref );
-
-        crc.onResource( new ResultHandler<Document>()
-        {
-            Iterator<Node> itemNodes;
-
-            @Override
-            public HandlerCommand handleResult( Document result, ContextResourceClient client )
-            {
-                try
-                {
-                    final XPath xPath = XPathFactory.newInstance().newXPath();
-
-                    System.out.println( "== " + xPath.evaluate( "feed/title", result ) + " ==" );
-
-                    final NodeList nodes = (NodeList) xPath.evaluate( "feed/entry", result, XPathConstants.NODESET );
-                    List<Node> items = new ArrayList<>();
-                    for( int i = 0; i < nodes.getLength(); i++ )
-                    {
-                        items.add( nodes.item( i ) );
-                    }
-
-                    itemNodes = items.iterator();
-
-                    return processEntry( xPath );
-                }
-                catch( XPathExpressionException e )
-                {
-                    throw new ResourceException( e );
-                }
-            }
-
-            private HandlerCommand processEntry( final XPath xPath )
-                throws XPathExpressionException
-            {
-                if( !itemNodes.hasNext() )
-                {
-                    return null;
-                }
-
-                Node item = itemNodes.next();
-
-                String title = xPath.evaluate( "title", item );
-                String detailUrl = xPath.evaluate( "link/@href", item );
-
-                System.out.println( "-- " + title + " --" );
-                System.out.println( "-- " + detailUrl + " --" );
-
-                return processEntry( xPath );
-            }
-        } );
-
-        crc.start();
-    }
-}
diff --git a/libraries/rest-client/src/test/java/org/qi4j/library/rest/client/docsupport/RestPrimerDocs.java b/libraries/rest-client/src/test/java/org/qi4j/library/rest/client/docsupport/RestPrimerDocs.java
deleted file mode 100644
index dea72ac..0000000
--- a/libraries/rest-client/src/test/java/org/qi4j/library/rest/client/docsupport/RestPrimerDocs.java
+++ /dev/null
@@ -1,125 +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.qi4j.library.rest.client.docsupport;
-
-import org.hamcrest.CoreMatchers;
-import org.junit.Assert;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.library.rest.client.api.ContextResourceClient;
-import org.qi4j.library.rest.client.api.ContextResourceClientFactory;
-import org.qi4j.library.rest.client.api.ErrorHandler;
-import org.qi4j.library.rest.client.api.HandlerCommand;
-import org.qi4j.library.rest.client.spi.NullResponseHandler;
-import org.qi4j.library.rest.client.spi.ResponseHandler;
-import org.qi4j.library.rest.client.spi.ResultHandler;
-import org.qi4j.library.rest.common.Resource;
-import org.restlet.Client;
-import org.restlet.Response;
-import org.restlet.data.MediaType;
-import org.restlet.data.Protocol;
-import org.restlet.data.Reference;
-import org.restlet.resource.ResourceException;
-import org.restlet.security.User;
-
-import static org.qi4j.library.rest.client.api.HandlerCommand.query;
-import static org.qi4j.library.rest.client.api.HandlerCommand.refresh;
-
-public class RestPrimerDocs
-{
-
-    private Module module;
-
-    private ContextResourceClient crc;
-
-    {
-// START SNIPPET: 1
-    crc.onResource( new ResultHandler<Resource>()
-    {
-        @Override
-        public HandlerCommand handleResult( Resource result, ContextResourceClient client )
-        {
-            // This may throw IAE if no link with relation
-            // "querywithoutvalue" is found in the Resource
-            return query( "querywithoutvalue", null );
-        }
-    } ).
-    onQuery( "querywithoutvalue", new ResultHandler<TestResult>()
-    {
-        @Override
-        public HandlerCommand handleResult( TestResult result, ContextResourceClient client )
-        {
-            Assert.assertThat(result.xyz().get(), CoreMatchers.equalTo("bar"));
-            return null;
-        }
-    } );
-
-    crc.start();
-// END SNIPPET: 1
-    }
-
-    {
-// START SNIPPET: 2
-// Create Restlet client and bookmark Reference
-    Client client = new Client( Protocol.HTTP );
-    Reference ref = new Reference( "http://localhost:8888/" );
-    ContextResourceClientFactory contextResourceClientFactory = module.newObject( ContextResourceClientFactory.class, client, new NullResponseHandler() );
-    contextResourceClientFactory.setAcceptedMediaTypes( MediaType.APPLICATION_JSON );
-
-// Handle logins
-    contextResourceClientFactory.setErrorHandler( new ErrorHandler().onError( ErrorHandler.AUTHENTICATION_REQUIRED, new ResponseHandler()
-    {
-        // Only try to login once
-        boolean tried = false;
-
-        @Override
-        public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-        {
-            // If we have already tried to login, fail!
-            if (tried)
-                throw new ResourceException( response.getStatus() );
-
-            tried = true;
-            client.getContextResourceClientFactory().getInfo().setUser( new User("rickard", "secret") );
-
-            // Try again
-            return refresh();
-        }
-    } ).onError( ErrorHandler.RECOVERABLE_ERROR, new ResponseHandler()
-    {
-        @Override
-        public HandlerCommand handleResponse( Response response, ContextResourceClient client )
-        {
-            // Try to restart this scenario
-            return refresh();
-        }
-    } ) );
-
-    crc = contextResourceClientFactory.newClient( ref );
-    // END SNIPPET: 2
-    }
-
-    public interface TestResult
-            extends ValueComposite
-    {
-        Property<String> xyz();
-    }
-
-}
\ No newline at end of file
diff --git a/libraries/rest-common/build.gradle b/libraries/rest-common/build.gradle
index cfe7410..6f1d281 100644
--- a/libraries/rest-common/build.gradle
+++ b/libraries/rest-common/build.gradle
@@ -1,29 +1,34 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ REST Library provides various Restlet resources that can be used to expose Apache Zest™ entities and indexes. Mostly for debugging."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - REST" }}
+description = "Apache Polygene™ REST Library provides various Restlet resources that can be used to expose Apache Polygene™ entities and indexes. Mostly for debugging."
+
+jar { manifest { name = "Apache Polygene™ Library - REST" } }
 
 dependencies {
-  compile project( ':org.qi4j.core:org.qi4j.core.bootstrap' )
-  compile libraries.restlet
-  compile libraries.velocity
-  compile libraries.servlet_api
+  compileOnly libraries.servlet_api
+
+  api polygene.core.bootstrap
+
+  implementation libraries.restlet
+  implementation libraries.velocity
 }
diff --git a/libraries/rest-common/dev-status.xml b/libraries/rest-common/dev-status.xml
index 37f9020..d3c6f4f 100644
--- a/libraries/rest-common/dev-status.xml
+++ b/libraries/rest-common/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/Form.java b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/Form.java
new file mode 100644
index 0000000..51dd6f6
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/Form.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.rest.common;
+
+import java.util.Map;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * Value that represents a form. This can be used to mimic a HTML form.
+ */
+public interface Form
+      extends ValueComposite
+{
+   @UseDefaults
+   Property<Map<String,String>> form();
+}
\ No newline at end of file
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/Resource.java b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/Resource.java
new file mode 100644
index 0000000..d9d17d7
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/Resource.java
@@ -0,0 +1,81 @@
+/*
+ *  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.polygene.library.rest.common;
+
+import java.util.List;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.library.rest.common.link.Link;
+import org.apache.polygene.library.rest.common.link.LinksUtil;
+
+import static org.apache.polygene.api.util.Collectors.single;
+
+/**
+ * Value representing a whole resource in a URL path. Allows listing of available
+ * queries, commands, sub-resources and an index.
+ */
+@Mixins(Resource.Mixin.class)
+public interface Resource
+    extends ValueComposite
+{
+    @UseDefaults
+    Property<List<Link>> queries();
+
+    Link query(String relation);
+
+    @UseDefaults
+    Property<List<Link>> commands();
+
+    Link command(String relation);
+
+    @UseDefaults
+    Property<List<Link>> resources();
+
+    Link resource(String relation);
+
+    @Optional
+    Property<Object> index();
+
+    abstract class Mixin
+        implements Resource
+    {
+        @Override
+        public Link query( String relation )
+        {
+            return queries().get().stream().filter( LinksUtil.withRel( relation ) ).collect( single() );
+        }
+
+        @Override
+        public Link command( String relation )
+        {
+            return commands().get().stream().filter( LinksUtil.withRel( relation ) ).collect( single() );
+        }
+
+        @Override
+        public Link resource( String relation )
+        {
+            return resources().get().stream().filter( LinksUtil.withRel( relation ) ).collect( single() );
+        }
+    }
+}
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/ValueAssembler.java b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/ValueAssembler.java
new file mode 100644
index 0000000..fa897e2
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/ValueAssembler.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.library.rest.common;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.apache.polygene.api.util.Classes.isAssignableFrom;
+import static org.apache.polygene.bootstrap.ClassScanner.findClasses;
+
+/**
+ * Assembler for all REST values.
+ */
+public class ValueAssembler
+    implements Assembler
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        findClasses( Resource.class ).filter( isAssignableFrom( ValueComposite.class ) )
+                                     .forEach( resourceType -> module.values( resourceType )
+                                                                     .visibleIn( Visibility.application ) );
+    }
+}
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/link/Link.java b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/link/Link.java
new file mode 100644
index 0000000..76ed2c5
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/link/Link.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.library.rest.common.link;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * Link value
+ */
+public interface Link
+      extends ValueComposite
+{
+   /**
+    * This is typically the description of the entity
+    *
+    * @return The text attribute of the Link.
+    */
+   @Optional
+   Property<String> text();
+
+   /**
+    * This is typically the id of the entity
+    *
+    * @return The id attribute of the Link.
+    */
+   Property<String> id();
+
+   /**
+    * This is the href of the entity, relative to the producer of the LinkValue
+    *
+    * @return The href attribute of the Link.
+    */
+   Property<String> href();
+
+   /**
+    * This is the type of the link, typically to help differentiate between
+    * different types of resources.
+    *
+    * @return The rel attribute of the Link.
+    */
+   @Optional
+   Property<String> rel();
+
+   /**
+    * These are the classes of the link, typically to help categorize the link. Space-separated list.
+    *
+    * @return A space-separated list of classes of the Link.
+    */
+   @Optional
+   Property<String> classes();
+}
\ No newline at end of file
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/link/Links.java b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/link/Links.java
new file mode 100644
index 0000000..f4b8ec2
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/link/Links.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.rest.common.link;
+
+import java.util.List;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * A list of links
+ */
+public interface Links
+      extends ValueComposite
+{
+   @UseDefaults
+   Property<List<Link>> links();
+}
\ No newline at end of file
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/link/LinksBuilder.java b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/link/LinksBuilder.java
new file mode 100644
index 0000000..cef6d89
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/link/LinksBuilder.java
@@ -0,0 +1,134 @@
+/*
+ *  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.polygene.library.rest.common.link;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+/**
+ * Builder for making it easier to create LinksValue/LinkValue
+ */
+public class LinksBuilder<T extends LinksBuilder>
+{
+    protected ValueBuilder<? extends Links> linksBuilder;
+    protected ValueBuilder<Link> linkBuilder;
+    protected ValueBuilderFactory vbf;
+
+    private String path;
+    private String rel;
+    private String classes;
+    private String command;
+
+    public LinksBuilder( ValueBuilderFactory vbf )
+    {
+        this.vbf = vbf;
+        linksBuilder = vbf.newValueBuilder( Links.class );
+        linkBuilder = vbf.newValueBuilder( Link.class );
+    }
+
+    public T path( @Optional String subPath )
+    {
+        path = subPath;
+
+        return (T) this;
+    }
+
+    public T rel( String rel )
+    {
+        this.rel = rel;
+
+        return (T) this;
+    }
+
+    public T classes( String classes )
+    {
+        this.classes = classes;
+
+        return (T) this;
+    }
+
+    public T command( String commandName )
+    {
+        this.command = commandName;
+        this.rel = commandName;
+        return (T) this;
+    }
+
+    public T addLink( Link link )
+    {
+        linksBuilder.prototype().links().get().add( link );
+
+        linkBuilder = vbf.newValueBuilderWithPrototype( link );
+
+        return (T) this;
+    }
+
+    public T addLink( String description, String id )
+    {
+        try
+        {
+            linkBuilder.prototype().text().set( description );
+            linkBuilder.prototype().id().set( id );
+            if( command != null )
+            {
+                linkBuilder.prototype().href().set( command + "?entity=" + id );
+            }
+            else
+            {
+                linkBuilder.prototype()
+                    .href()
+                    .set( ( path == null ? "" : path + "/" ) + URLEncoder.encode( id, "UTF-8" ) + "/" );
+            }
+            linkBuilder.prototype().rel().set( rel );
+            linkBuilder.prototype().classes().set( classes );
+
+            addLink( linkBuilder.newInstance() );
+
+            return (T) this;
+        }
+        catch( UnsupportedEncodingException e )
+        {
+            e.printStackTrace();
+            return (T) this;
+        }
+    }
+
+    public T addLink( String description, String id, String rel, String href, String classes )
+    {
+        linkBuilder.prototype().text().set( description );
+        linkBuilder.prototype().id().set( id );
+        linkBuilder.prototype().rel().set( rel );
+        linkBuilder.prototype().href().set( href );
+        linkBuilder.prototype().classes().set( classes );
+
+        addLink( linkBuilder.newInstance() );
+
+        return (T) this;
+    }
+
+    public Links newLinks()
+    {
+        return linksBuilder.newInstance();
+    }
+}
\ No newline at end of file
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/link/LinksUtil.java b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/link/LinksUtil.java
new file mode 100644
index 0000000..44c7fef
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/link/LinksUtil.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.library.rest.common.link;
+
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import static org.apache.polygene.api.util.Collectors.single;
+
+/**
+ * Helper methods for links
+ */
+public final class LinksUtil
+{
+   public static Predicate<Link> withId(final String id)
+   {
+      return link -> link.id().get().equals( id);
+   }
+
+   public static Predicate<Link> withText(final String text)
+   {
+      return link -> link.text().get().equals( text);
+   }
+
+   public static Predicate<Link> withRel(final String rel)
+   {
+      return link -> link.rel().get().equals( rel);
+   }
+
+   public static Predicate<Link> withClass(final String clazz)
+   {
+      return link -> {
+          String classes = link.classes().get();
+          return classes != null && classes.contains( clazz );
+      };
+   }
+
+    public static Link withRel( String rel, Links links )
+    {
+        return links.links().get().stream().filter( withRel( rel ) ).collect( single() );
+    }
+
+    public static Link withId(String id, Links links)
+    {
+        return links.links().get().stream().filter( withId( id ) ).collect( single() );
+    }
+
+   public static Function<Link, String> toRel()
+   {
+      return link -> link.rel().get();
+   }
+}
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/link/package.html b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/link/package.html
new file mode 100644
index 0000000..27b4bc3
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/link/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ReST Link Support.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/package.html b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/package.html
new file mode 100644
index 0000000..e4723e7
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ReST Common Library.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/Cell.java b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/Cell.java
new file mode 100644
index 0000000..ae51953
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/Cell.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.library.rest.common.table;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * JAVADOC
+ */
+public interface Cell
+   extends ValueComposite
+{
+   @Optional
+   Property<Object> v();
+
+   @Optional
+   Property<String> f();
+}
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/Column.java b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/Column.java
new file mode 100644
index 0000000..d4f01eb
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/Column.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.rest.common.table;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * JAVADOC
+ */
+public interface Column
+   extends ValueComposite
+{
+   Property<String> id();
+   Property<String> label();
+   Property<String> columnType();
+}
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/Problem.java b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/Problem.java
new file mode 100644
index 0000000..eaba6c8
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/Problem.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.rest.common.table;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * JAVADOC
+ */
+public interface Problem
+   extends ValueComposite
+{
+   Property<String> reason();
+   Property<String> message();
+   Property<String> detailed_message();
+}
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/QueryBuilder.java b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/QueryBuilder.java
new file mode 100644
index 0000000..bff9066
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/QueryBuilder.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.library.rest.common.table;
+
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+/**
+ * JAVADOC
+ */
+public class QueryBuilder<T extends QueryBuilder>
+{
+   protected ValueBuilder<TableQuery> queryBuilder;
+
+   private StringBuilder select;
+
+   public QueryBuilder( ValueBuilderFactory vbf )
+   {
+      queryBuilder = vbf.newValueBuilder( TableQuery.class );
+   }
+
+   public T select(String... columns)
+   {
+      if (select == null)
+         select = new StringBuilder(  );
+
+      for (String column : columns)
+      {
+         if (select.length() > 0)
+            select.append( ',' );
+         select.append( column );
+      }
+
+      return (T) this;
+   }
+
+   public TableQuery newQuery()
+   {
+      String query = "";
+
+      if (select != null)
+         query+= "select "+select.toString();
+
+      queryBuilder.prototype().tq().set( query );
+
+      return queryBuilder.newInstance();
+   }
+}
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/Row.java b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/Row.java
new file mode 100644
index 0000000..24c0cd2
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/Row.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.rest.common.table;
+
+import java.util.List;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * A single row in a table.
+ */
+public interface Row
+   extends ValueComposite
+{
+   @UseDefaults
+   Property<List<Cell>> c();
+}
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/Table.java b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/Table.java
new file mode 100644
index 0000000..54e6137
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/Table.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.library.rest.common.table;
+
+import java.util.List;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * A table of rows. RowValue needs to be subtyped in order to add columns.
+ */
+@Mixins(Table.Mixin.class)
+public interface Table
+      extends ValueComposite
+{
+   String STRING = "string";
+   String NUMBER = "number";
+   String BOOLEAN = "boolean";
+   String DATE = "date";
+   String DATETIME = "datetime";
+   String TIME_OF_DAY = "timeofday";
+
+   @UseDefaults
+   Property<List<Column>> cols();
+
+   @UseDefaults
+   Property<List<Row>> rows();
+
+   Cell cell(Row row, String name);
+
+   abstract class Mixin
+      implements Table
+   {
+      @State
+      Property<List<Column>> cols;
+
+      @Override
+      public Cell cell(Row row, String columnName)
+      {
+         for (int i = 0; i < cols.get().size(); i++)
+         {
+            Column column = cols.get().get(i);
+            if ( column.id().get().equals(columnName))
+               return row.c().get().get(i);
+         }
+
+         return null;
+      }
+   }
+}
\ No newline at end of file
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/TableBuilder.java b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/TableBuilder.java
new file mode 100644
index 0000000..5594e12
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/TableBuilder.java
@@ -0,0 +1,331 @@
+/*
+ *  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.polygene.library.rest.common.table;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+import static java.util.Collections.reverseOrder;
+
+/**
+ * JAVADOC
+ */
+public class TableBuilder
+{
+    protected ValueBuilderFactory vbf;
+    private Map<String, TableBuilderFactory.Column> columns;
+    private TableQuery tableQuery;
+
+    protected ValueBuilder<Table> tableBuilder;
+
+    protected ValueBuilder<Row> rowBuilder;
+
+    public TableBuilder( ValueBuilderFactory vbf )
+    {
+        this.vbf = vbf;
+
+        tableBuilder = vbf.newValueBuilder( Table.class );
+    }
+
+    public TableBuilder( ValueBuilderFactory vbf,
+                         Map<String, TableBuilderFactory.Column> columns,
+                         TableQuery tableQuery
+    )
+    {
+        this.vbf = vbf;
+        this.columns = columns;
+        this.tableQuery = tableQuery;
+
+        tableBuilder = vbf.newValueBuilder( Table.class );
+
+        if( tableQuery.select().equals( "*" ) )
+        {
+            for( TableBuilderFactory.Column column : columns.values() )
+            {
+                column( column.getId(), column.getLabel(), column.getType() );
+            }
+        }
+        else
+        {
+            for( String columnName : tableQuery.select().split( "[, ]" ) )
+            {
+                TableBuilderFactory.Column column = columns.get( columnName.trim() );
+                if( column != null )
+                {
+                    column( column.getId(), column.getLabel(), column.getType() );
+                }
+            }
+        }
+    }
+
+    public TableBuilder column( String id, String label, String type )
+    {
+        ValueBuilder<Column> builder = vbf.newValueBuilder( Column.class );
+        builder.prototype().id().set( id );
+
+        if( tableQuery != null && tableQuery.label() != null )
+        {
+            // TODO Fix label selection
+        }
+
+        builder.prototype().label().set( label );
+        builder.prototype().columnType().set( type );
+        tableBuilder.prototype().cols().get().add( builder.newInstance() );
+        return this;
+    }
+
+    public TableBuilder rows( Iterable<?> rowObjects )
+    {
+        boolean no_format = false;
+        boolean no_values = false;
+        if( tableQuery != null && tableQuery.options() != null )
+        {
+            if( tableQuery.options().contains( "no_format" ) )
+            {
+                no_format = true;
+            }
+            if( tableQuery != null && tableQuery.options().contains( "no_values" ) )
+            {
+                no_values = true;
+            }
+        }
+
+        for( Object rowObject : rowObjects )
+        {
+            row();
+            for( Column column : tableBuilder.prototype().cols().get() )
+            {
+                Object v = null;
+                String f = null;
+                Function valueFunction = columns.get( column.id().get() ).getValueFunction();
+                if( !no_values && valueFunction != null )
+                {
+                    v = valueFunction.apply( rowObject );
+                }
+                Function formattedFunction = columns.get( column.id().get() ).getFormattedFunction();
+                if( !no_format && formattedFunction != null )
+                {
+                    f = (String) formattedFunction.apply( rowObject );
+                }
+                else if( v != null )
+                {
+                    if( column.columnType().get().equals( Table.DATETIME ) )
+                    {
+                        f = v.toString();
+                    }
+                    else if( column.columnType().get().equals( Table.DATE ) )
+                    {
+                        f = v.toString();
+                    }
+                    else if( column.columnType().get().equals( Table.TIME_OF_DAY ) )
+                    {
+                        f = v.toString();
+                    }
+                    else
+                    {
+                        f = v.toString();
+                    }
+                }
+
+                cell( v, f );
+            }
+            endRow();
+        }
+
+        return this;
+    }
+
+    public TableBuilder row()
+    {
+        if( rowBuilder != null )
+        {
+            endRow();
+        }
+
+        rowBuilder = vbf.newValueBuilder( Row.class );
+        return this;
+    }
+
+    public TableBuilder endRow()
+    {
+        tableBuilder.prototype().rows().get().add( rowBuilder.newInstance() );
+        rowBuilder = null;
+        return this;
+    }
+
+    public TableBuilder cell( Object v, String f )
+    {
+        ValueBuilder<Cell> cellBuilder = vbf.newValueBuilder( Cell.class );
+        cellBuilder.prototype().v().set( v );
+        cellBuilder.prototype().f().set( f );
+        rowBuilder.prototype().c().get().add( cellBuilder.newInstance() );
+        return this;
+    }
+
+    public TableBuilder orderBy()
+    {
+        if( tableQuery.orderBy() != null )
+        {
+            // Sort table
+            // Find sort column index
+
+            String[] orderBy = tableQuery.orderBy().split( " " );
+            boolean descending = orderBy.length == 2 && orderBy[ 1 ].equals( "desc" );
+
+            int sortIndex = -1;
+            List<Column> columns = tableBuilder.prototype().cols().get();
+            for( int i = 0; i < columns.size(); i++ )
+            {
+                Column column = columns.get( i );
+                if( column.id().get().equals( orderBy[ 0 ] ) )
+                {
+                    sortIndex = i;
+                    break;
+                }
+            }
+
+            if( sortIndex != -1 )
+            {
+                final int idx = sortIndex;
+                Comparator<Row> comparator = new Comparator<Row>()
+                {
+                    @Override
+                    public int compare( Row o1, Row o2 )
+                    {
+                        Object o = o1.c().get().get( idx ).v().get();
+
+                        if( o != null && o instanceof Comparable )
+                        {
+                            Comparable c1 = (Comparable) o;
+                            Comparable c2 = (Comparable) o2.c().get().get( idx ).v().get();
+                            return c1.compareTo( c2 );
+                        }
+                        else
+                        {
+                            String f1 = o1.c().get().get( idx ).f().get();
+                            String f2 = o2.c().get().get( idx ).f().get();
+                            return f1.compareTo( f2 );
+                        }
+                    }
+                };
+
+                if( descending )
+                {
+                    // Flip it
+                    comparator = reverseOrder( comparator );
+                }
+
+                tableBuilder.prototype().rows().get().sort( comparator );
+            }
+        }
+
+        return this;
+    }
+
+//   public TableBuilder orderBy()
+//   {
+//      if (tableQuery.orderBy() != null)
+//      {
+//         // Sort table
+//         // Find sort column index
+//         int sortIndex = -1;
+//         List<ColumnValue> columnValues = tableBuilder.prototype().cols().get();
+//         for (int i = 0; i < columnValues.size(); i++)
+//         {
+//            ColumnValue columnValue = columnValues.get(i);
+//            if (columnValue.id().equals(tableQuery.orderBy()))
+//            {
+//               sortIndex = i;
+//               break;
+//            }
+//
+//         }
+//
+//         if (sortIndex != -1)
+//         {
+//            final int idx = sortIndex;
+//            Comparator<RowValue> comparator = new Comparator<RowValue>()
+//            {
+//               public int compare(RowValue o1, RowValue o2)
+//               {
+//                  Object o = o1.c().get().get(idx).v().get();
+//
+//                  if (o != null && o instanceof Comparable)
+//                  {
+//                     Comparable c1 = (Comparable) o;
+//                     Comparable c2 = (Comparable) o2.c().get().get(idx).v().get();
+//                     return c1.compareTo(c2);
+//                  } else
+//                  {
+//                     String f1 = o1.c().get().get(idx).f().get();
+//                     String f2 = o2.c().get().get(idx).f().get();
+//                     return f1.compareTo(f2);
+//                  }
+//               }
+//            };
+//
+//            Collections.sort(tableBuilder.prototype().rows().get(), comparator);
+//         }
+//      }
+//
+//      return this;
+//   }
+
+    public TableBuilder paging()
+    {
+        // Paging
+        int start = 0;
+        int end = tableBuilder.prototype().rows().get().size();
+        if( tableQuery.offset() != null )
+        {
+            start = Integer.parseInt( tableQuery.offset() );
+        }
+        if( tableQuery.limit() != null )
+        {
+            end = Math.min( end, start + Integer.parseInt( tableQuery.limit() ) );
+        }
+
+        if( !( start == 0 && end == tableBuilder.prototype().rows().get().size() ) )
+        {
+            tableBuilder.prototype().rows().set( tableBuilder.prototype().rows().get().subList( start, end ) );
+        }
+
+        return this;
+    }
+
+    public Table newTable()
+    {
+        if( rowBuilder != null )
+        {
+            endRow();
+        }
+
+        return tableBuilder.newInstance();
+    }
+
+    public void abortRow()
+    {
+        rowBuilder = null;
+    }
+}
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/TableBuilderFactory.java b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/TableBuilderFactory.java
new file mode 100644
index 0000000..e77655e
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/TableBuilderFactory.java
@@ -0,0 +1,100 @@
+/*
+ *  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.polygene.library.rest.common.table;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.Function;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+/**
+ * Factory for setting up TableBuilder instances. Defines available columns, and how they are extracted from objects.
+ */
+public class TableBuilderFactory
+{
+   private ValueBuilderFactory vbf;
+
+   public TableBuilderFactory(ValueBuilderFactory vbf)
+   {
+      this.vbf = vbf;
+   }
+
+   private Map<String, Column> columns = new LinkedHashMap<String, Column>();
+
+   public TableBuilderFactory column(String id, String label, String type, Function<?, Object> valueFunction, Function<?, String> formattedFunction)
+   {
+      columns.put(id, new Column(id, label, type, valueFunction, formattedFunction));
+      return this;
+   }
+
+   public TableBuilderFactory column(String id, String label, String type, Function<?, Object> valueFunction)
+   {
+      columns.put(id, new Column(id, label, type, valueFunction, null));
+      return this;
+   }
+
+   public TableBuilder newInstance(TableQuery tableQuery)
+   {
+      return new TableBuilder(vbf, columns, tableQuery);
+   }
+
+   class Column
+   {
+      private String id;
+      private String label;
+      private String type;
+      private Function<?, Object> valueFunction;
+      private Function<?, String> formattedFunction;
+
+      private Column(String id, String label, String type, Function<?, Object> valueFunction, Function<?, String> formattedFunction)
+      {
+         this.id = id;
+         this.label = label;
+         this.type = type;
+         this.valueFunction = valueFunction;
+         this.formattedFunction = formattedFunction;
+      }
+
+      public String getId()
+      {
+         return id;
+      }
+
+      public String getLabel()
+      {
+         return label;
+      }
+
+      public String getType()
+      {
+         return type;
+      }
+
+      public Function<?, Object> getValueFunction()
+      {
+         return valueFunction;
+      }
+
+      public Function<?, String> getFormattedFunction()
+      {
+         return formattedFunction;
+      }
+   }
+}
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/TableQuery.java b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/TableQuery.java
new file mode 100644
index 0000000..fbe829b
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/TableQuery.java
@@ -0,0 +1,240 @@
+/*
+ *  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.polygene.library.rest.common.table;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * Query value for Google Data queries.
+ */
+@Mixins(TableQuery.Mixin.class)
+public interface TableQuery
+        extends ValueComposite
+{
+   Property<String> tq();
+
+   String select();
+
+   String where();
+
+   String groupBy();
+
+   String pivot();
+
+   String orderBy();
+
+   String limit();
+
+   String offset();
+
+   String label();
+
+   String options();
+
+   Table applyTo(Table table);
+
+   abstract class Mixin
+           implements TableQuery
+   {
+      private static Collection<String> keywords = Arrays.asList("select", "where", "group by", "pivot", "order by", "limit", "offset", "label", "options");
+
+      private Map<String, String> parts;
+
+      @Override
+      public String select()
+      {
+         return getParts().get("select");
+      }
+
+      @Override
+      public String where()
+      {
+         return getParts().get("where");
+      }
+
+      @Override
+      public String groupBy()
+      {
+         return getParts().get("group by");
+      }
+
+      @Override
+      public String pivot()
+      {
+         return getParts().get("pivot");
+      }
+
+      @Override
+      public String orderBy()
+      {
+         return getParts().get("order by");
+      }
+
+      @Override
+      public String limit()
+      {
+         return getParts().get("limit");
+      }
+
+      @Override
+      public String offset()
+      {
+         return getParts().get("offset");
+      }
+
+      @Override
+      public String label()
+      {
+         return getParts().get("label");
+      }
+
+      @Override
+      public String options()
+      {
+         return getParts().get("options");
+      }
+
+      private Map<String, String> getParts()
+      {
+         if (parts == null)
+         {
+            parts = new HashMap<>();
+
+            String value = tq().get();
+            List<String> values = Arrays.asList(value.split(" "));
+            Collections.reverse(values);
+            String currentPhrase = "";
+            for (String str : values)
+            {
+               currentPhrase = str + currentPhrase;
+               boolean found = false;
+               for (String keyword : keywords)
+               {
+                  if (currentPhrase.startsWith(keyword + " "))
+                  {
+                     found = true;
+                     parts.put(keyword, currentPhrase.substring(keyword.length() + 1));
+                     currentPhrase = "";
+                     break;
+                  }
+               }
+
+               if (!found)
+                  currentPhrase = " " + currentPhrase;
+            }
+         }
+
+         return parts;
+      }
+
+      @Override
+      public Table applyTo(Table table)
+      {
+         ValueBuilder<Table> tableBuilder = PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF
+             .apply( table ).module().instance().newValueBuilderWithPrototype( table );
+
+/* TODO Finish label setting
+         if (label() != null)
+         {
+            String[] labels = label().split(",");
+            for (String label : labels)
+            {
+               String[] labelDef = label.split(" ",1);
+               labelDef[1] = labelDef[1].trim();
+
+            }
+            for (int i = 0; i < tableBuilder.prototype().cols().get().size(); i++)
+            {
+               ColumnValue cellValue = tableBuilder.prototype().cols().get().get(i);
+            }
+         }
+*/
+
+         if (orderBy() != null)
+         {
+            // Sort table
+            // Find sort column index
+            int sortIndex = -1;
+            List<Column> columns = table.cols().get();
+            for (int i = 0; i < columns.size(); i++)
+            {
+               Column column = columns.get(i);
+               if ( column.id().equals(orderBy()))
+               {
+                  sortIndex = i;
+                  break;
+               }
+
+            }
+
+            if (sortIndex != -1)
+            {
+               final int idx = sortIndex;
+               Comparator<Row> comparator = new Comparator<Row>()
+               {
+                  @Override
+                  public int compare(Row o1, Row o2)
+                  {
+                     Object o = o1.c().get().get(idx).v().get();
+
+                     if (o != null && o instanceof Comparable)
+                     {
+                        Comparable c1 = (Comparable) o;
+                        Comparable c2 = (Comparable) o2.c().get().get(idx).v().get();
+                        return c1.compareTo(c2);
+                     } else
+                     {
+                        String f1 = o1.c().get().get(idx).f().get();
+                        String f2 = o2.c().get().get(idx).f().get();
+                        return f1.compareTo(f2);
+                     }
+                  }
+               };
+
+               tableBuilder.prototype().rows().get().sort( comparator );
+            }
+         }
+
+         // Paging
+         int start = 0;
+         int end = tableBuilder.prototype().rows().get().size();
+         if (offset() != null)
+            start = Integer.parseInt(offset());
+         if (limit() != null)
+            end = Math.min(end, start+ Integer.parseInt(limit()));
+
+         if (!(start == 0 && end == tableBuilder.prototype().rows().get().size()))
+            tableBuilder.prototype().rows().set(tableBuilder.prototype().rows().get().subList(start, end));
+
+         return tableBuilder.newInstance();
+      }
+   }
+}
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/TableResponse.java b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/TableResponse.java
new file mode 100644
index 0000000..70b76e4
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/TableResponse.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.polygene.library.rest.common.table;
+
+import java.util.List;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * JAVADOC
+ */
+public interface TableResponse
+   extends ValueComposite
+{
+   @Optional
+   Property<String> version();
+
+   @Optional
+   Property<String> reqId();
+
+   Property<String> status();
+
+   @Optional
+   Property<List<Problem>> warnings();
+
+   @Optional
+   Property<List<Problem>> errors();
+
+   @Optional
+   Property<String> sig();
+
+   @Optional
+   Property<Table> table();
+}
diff --git a/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/package.html b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/package.html
new file mode 100644
index 0000000..7c257b3
--- /dev/null
+++ b/libraries/rest-common/src/main/java/org/apache/polygene/library/rest/common/table/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ReST Table Support.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/Form.java b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/Form.java
deleted file mode 100644
index 0e155ae..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/Form.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.common;
-
-import java.util.Map;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * Value that represents a form. This can be used to mimic a HTML form.
- */
-public interface Form
-      extends ValueComposite
-{
-   @UseDefaults
-   Property<Map<String,String>> form();
-}
\ No newline at end of file
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/Resource.java b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/Resource.java
deleted file mode 100644
index e0de23d..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/Resource.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.common;
-
-import java.util.List;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.functional.Iterables;
-import org.qi4j.library.rest.common.link.Link;
-import org.qi4j.library.rest.common.link.LinksUtil;
-
-/**
- * Value representing a whole resource in a URL path. Allows listing of available
- * queries, commands, sub-resources and an index.
- */
-@Mixins(Resource.Mixin.class)
-public interface Resource
-    extends ValueComposite
-{
-    @UseDefaults
-    Property<List<Link>> queries();
-
-    Link query(String relation);
-
-    @UseDefaults
-    Property<List<Link>> commands();
-
-    Link command(String relation);
-
-    @UseDefaults
-    Property<List<Link>> resources();
-
-    Link resource(String relation);
-
-    @Optional
-    Property<ValueComposite> index();
-
-    abstract class Mixin
-        implements Resource
-    {
-        @Override
-        public Link query( String relation )
-        {
-            return Iterables.single( Iterables.filter( LinksUtil.withRel( relation ), queries().get() ) );
-        }
-
-        @Override
-        public Link command( String relation )
-        {
-            return Iterables.single(Iterables.filter( LinksUtil.withRel( relation ), commands().get() ));
-        }
-
-        @Override
-        public Link resource( String relation )
-        {
-            return Iterables.single(Iterables.filter( LinksUtil.withRel( relation ), resources().get() ));
-        }
-    }
-}
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/ValueAssembler.java b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/ValueAssembler.java
deleted file mode 100644
index 1c6a066..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/ValueAssembler.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.common;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-import static org.qi4j.api.util.Classes.*;
-import static org.qi4j.bootstrap.ClassScanner.*;
-import static org.qi4j.functional.Iterables.*;
-
-/**
- * Assembler for all REST values.
- */
-public class ValueAssembler
-    implements Assembler
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        for( Class<?> aClass : filter( isAssignableFrom( ValueComposite.class ), findClasses( Resource.class ) ))
-        {
-            module.values( aClass ).visibleIn( Visibility.application );
-        }
-    }
-}
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/link/Link.java b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/link/Link.java
deleted file mode 100644
index fc33fa8..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/link/Link.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.common.link;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * Link value
- */
-public interface Link
-      extends ValueComposite
-{
-   /**
-    * This is typically the description of the entity
-    *
-    * @return The text attribute of the Link.
-    */
-   @Optional
-   Property<String> text();
-
-   /**
-    * This is typically the id of the entity
-    *
-    * @return The id attribute of the Link.
-    */
-   Property<String> id();
-
-   /**
-    * This is the href of the entity, relative to the producer of the LinkValue
-    *
-    * @return The href attribute of the Link.
-    */
-   Property<String> href();
-
-   /**
-    * This is the type of the link, typically to help differentiate between
-    * different types of resources.
-    *
-    * @return The rel attribute of the Link.
-    */
-   @Optional
-   Property<String> rel();
-
-   /**
-    * These are the classes of the link, typically to help categorize the link. Space-separated list.
-    *
-    * @return A space-separated list of classes of the Link.
-    */
-   @Optional
-   Property<String> classes();
-}
\ No newline at end of file
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/link/Links.java b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/link/Links.java
deleted file mode 100644
index 4978c5e..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/link/Links.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.common.link;
-
-import java.util.List;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * A list of links
- */
-public interface Links
-      extends ValueComposite
-{
-   @UseDefaults
-   Property<List<Link>> links();
-}
\ No newline at end of file
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/link/LinksBuilder.java b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/link/LinksBuilder.java
deleted file mode 100644
index 409ae10..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/link/LinksBuilder.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.common.link;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-
-/**
- * Builder for making it easier to create LinksValue/LinkValue
- */
-public class LinksBuilder<T extends LinksBuilder>
-{
-    protected ValueBuilder<? extends Links> linksBuilder;
-    protected ValueBuilder<Link> linkBuilder;
-    protected ValueBuilderFactory vbf;
-
-    private String path;
-    private String rel;
-    private String classes;
-    private String command;
-
-    public LinksBuilder( ValueBuilderFactory vbf )
-    {
-        this.vbf = vbf;
-        linksBuilder = vbf.newValueBuilder( Links.class );
-        linkBuilder = vbf.newValueBuilder( Link.class );
-    }
-
-    public T path( @Optional String subPath )
-    {
-        path = subPath;
-
-        return (T) this;
-    }
-
-    public T rel( String rel )
-    {
-        this.rel = rel;
-
-        return (T) this;
-    }
-
-    public T classes( String classes )
-    {
-        this.classes = classes;
-
-        return (T) this;
-    }
-
-    public T command( String commandName )
-    {
-        this.command = commandName;
-        this.rel = commandName;
-        return (T) this;
-    }
-
-    public T addLink( Link link )
-    {
-        linksBuilder.prototype().links().get().add( link );
-
-        linkBuilder = vbf.newValueBuilderWithPrototype( link );
-
-        return (T) this;
-    }
-
-    public T addLink( String description, String id )
-    {
-        try
-        {
-            linkBuilder.prototype().text().set( description );
-            linkBuilder.prototype().id().set( id );
-            if( command != null )
-            {
-                linkBuilder.prototype().href().set( command + "?entity=" + id );
-            }
-            else
-            {
-                linkBuilder.prototype()
-                    .href()
-                    .set( ( path == null ? "" : path + "/" ) + URLEncoder.encode( id, "UTF-8" ) + "/" );
-            }
-            linkBuilder.prototype().rel().set( rel );
-            linkBuilder.prototype().classes().set( classes );
-
-            addLink( linkBuilder.newInstance() );
-
-            return (T) this;
-        }
-        catch( UnsupportedEncodingException e )
-        {
-            e.printStackTrace();
-            return (T) this;
-        }
-    }
-
-    public T addLink( String description, String id, String rel, String href, String classes )
-    {
-        linkBuilder.prototype().text().set( description );
-        linkBuilder.prototype().id().set( id );
-        linkBuilder.prototype().rel().set( rel );
-        linkBuilder.prototype().href().set( href );
-        linkBuilder.prototype().classes().set( classes );
-
-        addLink( linkBuilder.newInstance() );
-
-        return (T) this;
-    }
-
-    public Links newLinks()
-    {
-        return linksBuilder.newInstance();
-    }
-}
\ No newline at end of file
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/link/LinksUtil.java b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/link/LinksUtil.java
deleted file mode 100644
index 9443956..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/link/LinksUtil.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.common.link;
-
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.functional.Specification;
-
-/**
- * Helper methods for links
- */
-public final class LinksUtil
-{
-   public static Specification<Link> withId(final String id)
-   {
-      return new Specification<Link>()
-      {
-         @Override
-         public boolean satisfiedBy(Link link )
-         {
-            return link.id().get().equals(id);
-         }
-      };
-   }
-
-   public static Specification<Link> withText(final String text)
-   {
-      return new Specification<Link>()
-      {
-         @Override
-         public boolean satisfiedBy(Link link )
-         {
-            return link.text().get().equals(text);
-         }
-      };
-   }
-
-   public static Specification<Link> withRel(final String rel)
-   {
-      return new Specification<Link>()
-      {
-         @Override
-         public boolean satisfiedBy(Link link )
-         {
-            return link.rel().get().equals(rel);
-         }
-      };
-   }
-
-   public static Specification<Link> withClass(final String clazz)
-   {
-      return new Specification<Link>()
-      {
-         @Override
-         public boolean satisfiedBy(Link link )
-         {
-             String classes = link.classes().get();
-             return classes != null && classes.contains( clazz );
-         }
-      };
-   }
-
-    public static Link withRel(String rel, Links links)
-    {
-        return Iterables.single( Iterables.filter( withRel( rel ), links.links().get() ) );
-    }
-
-    public static Link withId(String id, Links links)
-    {
-        return Iterables.single( Iterables.filter( withId( id ), links.links().get() ) );
-    }
-
-   public static Function<Link, String> toRel()
-   {
-      return new Function<Link, String>()
-      {
-         @Override
-         public String map(Link link )
-         {
-            return link.rel().get();
-         }
-      };
-   }
-}
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/link/package.html b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/link/package.html
deleted file mode 100644
index 7fc3cda..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/link/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ReST Link Support.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/package.html b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/package.html
deleted file mode 100644
index 4d4e042..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ReST Common Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/Cell.java b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/Cell.java
deleted file mode 100644
index 96d3d48..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/Cell.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.common.table;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * JAVADOC
- */
-public interface Cell
-   extends ValueComposite
-{
-   @Optional
-   Property<Object> v();
-
-   @Optional
-   Property<String> f();
-}
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/Column.java b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/Column.java
deleted file mode 100644
index 0e3e4d7..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/Column.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.common.table;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * JAVADOC
- */
-public interface Column
-   extends ValueComposite
-{
-   Property<String> id();
-   Property<String> label();
-   Property<String> columnType();
-}
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/Problem.java b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/Problem.java
deleted file mode 100644
index dbc35f3..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/Problem.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.common.table;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * JAVADOC
- */
-public interface Problem
-   extends ValueComposite
-{
-   Property<String> reason();
-   Property<String> message();
-   Property<String> detailed_message();
-}
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/QueryBuilder.java b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/QueryBuilder.java
deleted file mode 100644
index 0347c38..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/QueryBuilder.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.common.table;
-
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-
-/**
- * JAVADOC
- */
-public class QueryBuilder<T extends QueryBuilder>
-{
-   protected ValueBuilder<TableQuery> queryBuilder;
-
-   private StringBuilder select;
-
-   public QueryBuilder( ValueBuilderFactory vbf )
-   {
-      queryBuilder = vbf.newValueBuilder( TableQuery.class );
-   }
-
-   public T select(String... columns)
-   {
-      if (select == null)
-         select = new StringBuilder(  );
-
-      for (String column : columns)
-      {
-         if (select.length() > 0)
-            select.append( ',' );
-         select.append( column );
-      }
-
-      return (T) this;
-   }
-
-   public TableQuery newQuery()
-   {
-      String query = "";
-
-      if (select != null)
-         query+= "select "+select.toString();
-
-      queryBuilder.prototype().tq().set( query );
-
-      return queryBuilder.newInstance();
-   }
-}
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/Row.java b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/Row.java
deleted file mode 100644
index 5102795..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/Row.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.common.table;
-
-import java.util.List;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * A single row in a table.
- */
-public interface Row
-   extends ValueComposite
-{
-   @UseDefaults
-   Property<List<Cell>> c();
-}
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/Table.java b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/Table.java
deleted file mode 100644
index 8ae5baa..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/Table.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.common.table;
-
-import java.util.List;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.injection.scope.State;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * A table of rows. RowValue needs to be subtyped in order to add columns.
- */
-@Mixins(Table.Mixin.class)
-public interface Table
-      extends ValueComposite
-{
-   public static final String STRING = "string";
-   public static final String NUMBER = "number";
-   public static final String BOOLEAN = "boolean";
-   public static final String DATE = "date";
-   public static final String DATETIME = "datetime";
-   public static final String TIME_OF_DAY = "timeofday";
-
-   @UseDefaults
-   Property<List<Column>> cols();
-
-   @UseDefaults
-   Property<List<Row>> rows();
-
-   Cell cell(Row row, String name);
-
-   abstract class Mixin
-      implements Table
-   {
-      @State
-      Property<List<Column>> cols;
-
-      @Override
-      public Cell cell(Row row, String columnName)
-      {
-         for (int i = 0; i < cols.get().size(); i++)
-         {
-            Column column = cols.get().get(i);
-            if ( column.id().get().equals(columnName))
-               return row.c().get().get(i);
-         }
-
-         return null;
-      }
-   }
-}
\ No newline at end of file
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/TableBuilder.java b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/TableBuilder.java
deleted file mode 100644
index 5b2a00f..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/TableBuilder.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.common.table;
-
-import java.text.SimpleDateFormat;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.util.Dates;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.functional.Function;
-
-import static java.util.Collections.reverseOrder;
-
-/**
- * JAVADOC
- */
-public class TableBuilder
-{
-   protected ValueBuilderFactory vbf;
-   private Map<String, TableBuilderFactory.Column> columns;
-   private TableQuery tableQuery;
-
-   protected ValueBuilder<Table> tableBuilder;
-
-   protected ValueBuilder<Row> rowBuilder;
-
-   public TableBuilder(ValueBuilderFactory vbf)
-   {
-      this.vbf = vbf;
-
-      tableBuilder = vbf.newValueBuilder(Table.class);
-   }
-
-   public TableBuilder(ValueBuilderFactory vbf, Map<String, TableBuilderFactory.Column> columns, TableQuery tableQuery)
-   {
-      this.vbf = vbf;
-      this.columns = columns;
-      this.tableQuery = tableQuery;
-
-      tableBuilder = vbf.newValueBuilder(Table.class);
-
-      if (tableQuery.select().equals("*"))
-      {
-         for (TableBuilderFactory.Column column : columns.values())
-         {
-            column(column.getId(), column.getLabel(), column.getType());
-         }
-      } else
-      {
-         for (String columnName : tableQuery.select().split("[, ]"))
-         {
-            TableBuilderFactory.Column column = columns.get(columnName.trim());
-            if (column != null)
-               column(column.getId(), column.getLabel(), column.getType());
-         }
-      }
-   }
-
-   public TableBuilder column(String id, String label, String type)
-   {
-      ValueBuilder<Column> builder = vbf.newValueBuilder(Column.class);
-      builder.prototype().id().set(id);
-
-      if (tableQuery != null && tableQuery.label() != null)
-      {
-         // TODO Fix label selection
-      }
-
-      builder.prototype().label().set(label);
-      builder.prototype().columnType().set(type);
-      tableBuilder.prototype().cols().get().add(builder.newInstance());
-      return this;
-   }
-
-   public TableBuilder rows(Iterable<?> rowObjects)
-   {
-      boolean no_format = false;
-      boolean no_values = false;
-      if (tableQuery != null && tableQuery.options() != null)
-      {
-         if (tableQuery.options().contains("no_format"))
-            no_format = true;
-         if (tableQuery != null && tableQuery.options().contains("no_values"))
-            no_values = true;
-      }
-
-      for (Object rowObject : rowObjects)
-      {
-         row();
-         for (Column column : tableBuilder.prototype().cols().get())
-         {
-            Object v = null;
-            String f = null;
-            Function valueFunction = columns.get( column.id().get()).getValueFunction();
-            if (!no_values && valueFunction != null)
-               v = valueFunction.map(rowObject);
-            Function formattedFunction = columns.get( column.id().get()).getFormattedFunction();
-            if (!no_format && formattedFunction != null)
-               f = (String) formattedFunction.map(rowObject);
-            else if (v != null)
-            {
-               if ( column.columnType().get().equals( Table.DATETIME))
-                  f = Dates.toUtcString( (Date) v );
-               else if ( column.columnType().get().equals( Table.DATE))
-                  f = new SimpleDateFormat( "yyyy-MM-dd").format((Date) v);
-               else if ( column.columnType().get().equals( Table.TIME_OF_DAY))
-                  f = new SimpleDateFormat( "HH:mm:ss").format((Date) v);
-               else
-                  f = v.toString();
-            }
-
-            cell(v, f);
-         }
-         endRow();
-      }
-
-      return this;
-   }
-
-   public TableBuilder row()
-   {
-      if (rowBuilder != null)
-         endRow();
-
-      rowBuilder = vbf.newValueBuilder(Row.class);
-      return this;
-   }
-
-   public TableBuilder endRow()
-   {
-      tableBuilder.prototype().rows().get().add(rowBuilder.newInstance());
-      rowBuilder = null;
-      return this;
-   }
-
-   public TableBuilder cell(Object v, String f)
-   {
-      ValueBuilder<Cell> cellBuilder = vbf.newValueBuilder(Cell.class);
-      cellBuilder.prototype().v().set(v);
-      cellBuilder.prototype().f().set(f);
-      rowBuilder.prototype().c().get().add(cellBuilder.newInstance());
-      return this;
-   }
-
-   public TableBuilder orderBy()
-   {
-      if (tableQuery.orderBy() != null)
-      {
-         // Sort table
-         // Find sort column index
-
-         String[] orderBy = tableQuery.orderBy().split(" ");
-         boolean descending = orderBy.length == 2 && orderBy[1].equals("desc");
-
-         int sortIndex = -1;
-         List<Column> columns = tableBuilder.prototype().cols().get();
-         for (int i = 0; i < columns.size(); i++)
-         {
-            Column column = columns.get(i);
-            if ( column.id().get().equals(orderBy[0]))
-            {
-               sortIndex = i;
-               break;
-            }
-
-         }
-
-         if (sortIndex != -1)
-         {
-            final int idx = sortIndex;
-            Comparator<Row> comparator = new Comparator<Row>()
-            {
-               @Override
-               public int compare(Row o1, Row o2)
-               {
-                  Object o = o1.c().get().get(idx).v().get();
-
-                  if (o != null && o instanceof Comparable)
-                  {
-                     Comparable c1 = (Comparable) o;
-                     Comparable c2 = (Comparable) o2.c().get().get(idx).v().get();
-                     return c1.compareTo(c2);
-                  } else
-                  {
-                     String f1 = o1.c().get().get(idx).f().get();
-                     String f2 = o2.c().get().get(idx).f().get();
-                     return f1.compareTo(f2);
-                  }
-               }
-            };
-
-            if (descending)
-            {
-               // Flip it
-               comparator = reverseOrder(comparator);
-            }
-
-            Collections.sort(tableBuilder.prototype().rows().get(), comparator);
-         }
-      }
-
-      return this;
-   }
-
-//   public TableBuilder orderBy()
-//   {
-//      if (tableQuery.orderBy() != null)
-//      {
-//         // Sort table
-//         // Find sort column index
-//         int sortIndex = -1;
-//         List<ColumnValue> columnValues = tableBuilder.prototype().cols().get();
-//         for (int i = 0; i < columnValues.size(); i++)
-//         {
-//            ColumnValue columnValue = columnValues.get(i);
-//            if (columnValue.id().equals(tableQuery.orderBy()))
-//            {
-//               sortIndex = i;
-//               break;
-//            }
-//
-//         }
-//
-//         if (sortIndex != -1)
-//         {
-//            final int idx = sortIndex;
-//            Comparator<RowValue> comparator = new Comparator<RowValue>()
-//            {
-//               public int compare(RowValue o1, RowValue o2)
-//               {
-//                  Object o = o1.c().get().get(idx).v().get();
-//
-//                  if (o != null && o instanceof Comparable)
-//                  {
-//                     Comparable c1 = (Comparable) o;
-//                     Comparable c2 = (Comparable) o2.c().get().get(idx).v().get();
-//                     return c1.compareTo(c2);
-//                  } else
-//                  {
-//                     String f1 = o1.c().get().get(idx).f().get();
-//                     String f2 = o2.c().get().get(idx).f().get();
-//                     return f1.compareTo(f2);
-//                  }
-//               }
-//            };
-//
-//            Collections.sort(tableBuilder.prototype().rows().get(), comparator);
-//         }
-//      }
-//
-//      return this;
-//   }
-
-   public TableBuilder paging()
-   {
-      // Paging
-      int start = 0;
-      int end = tableBuilder.prototype().rows().get().size();
-      if (tableQuery.offset() != null)
-         start = Integer.parseInt(tableQuery.offset());
-      if (tableQuery.limit() != null)
-         end = Math.min(end, start + Integer.parseInt(tableQuery.limit()));
-
-      if (!(start == 0 && end == tableBuilder.prototype().rows().get().size()))
-         tableBuilder.prototype().rows().set(tableBuilder.prototype().rows().get().subList(start, end));
-
-      return this;
-
-   }
-
-   public Table newTable()
-   {
-      if (rowBuilder != null)
-         endRow();
-
-      return tableBuilder.newInstance();
-   }
-
-   public void abortRow()
-   {
-      rowBuilder = null;
-   }
-}
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/TableBuilderFactory.java b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/TableBuilderFactory.java
deleted file mode 100644
index 987c49f..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/TableBuilderFactory.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.common.table;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.functional.Function;
-
-/**
- * Factory for setting up TableBuilder instances. Defines available columns, and how they are extracted from objects.
- */
-public class TableBuilderFactory
-{
-   private ValueBuilderFactory vbf;
-
-   public TableBuilderFactory(ValueBuilderFactory vbf)
-   {
-      this.vbf = vbf;
-   }
-
-   private Map<String, Column> columns = new LinkedHashMap<String, Column>();
-
-   public TableBuilderFactory column(String id, String label, String type, Function<?, Object> valueFunction, Function<?, String> formattedFunction)
-   {
-      columns.put(id, new Column(id, label, type, valueFunction, formattedFunction));
-      return this;
-   }
-
-   public TableBuilderFactory column(String id, String label, String type, Function<?, Object> valueFunction)
-   {
-      columns.put(id, new Column(id, label, type, valueFunction, null));
-      return this;
-   }
-
-   public TableBuilder newInstance(TableQuery tableQuery)
-   {
-      return new TableBuilder(vbf, columns, tableQuery);
-   }
-
-   class Column
-   {
-      private String id;
-      private String label;
-      private String type;
-      private Function<?, Object> valueFunction;
-      private Function<?, String> formattedFunction;
-
-      private Column(String id, String label, String type, Function<?, Object> valueFunction, Function<?, String> formattedFunction)
-      {
-         this.id = id;
-         this.label = label;
-         this.type = type;
-         this.valueFunction = valueFunction;
-         this.formattedFunction = formattedFunction;
-      }
-
-      public String getId()
-      {
-         return id;
-      }
-
-      public String getLabel()
-      {
-         return label;
-      }
-
-      public String getType()
-      {
-         return type;
-      }
-
-      public Function<?, Object> getValueFunction()
-      {
-         return valueFunction;
-      }
-
-      public Function<?, String> getFormattedFunction()
-      {
-         return formattedFunction;
-      }
-   }
-}
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/TableQuery.java b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/TableQuery.java
deleted file mode 100644
index db70f8b..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/TableQuery.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.common.table;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * Query value for Google Data queries.
- */
-@Mixins(TableQuery.Mixin.class)
-public interface TableQuery
-        extends ValueComposite
-{
-   Property<String> tq();
-
-   public String select();
-
-   public String where();
-
-   public String groupBy();
-
-   public String pivot();
-
-   public String orderBy();
-
-   public String limit();
-
-   public String offset();
-
-   public String label();
-
-   public String options();
-
-   public Table applyTo(Table table);
-
-   abstract class Mixin
-           implements TableQuery
-   {
-      private static Collection<String> keywords = Arrays.asList("select", "where", "group by", "pivot", "order by", "limit", "offset", "label", "options");
-
-      private Map<String, String> parts;
-
-      @Override
-      public String select()
-      {
-         return getParts().get("select");
-      }
-
-      @Override
-      public String where()
-      {
-         return getParts().get("where");
-      }
-
-      @Override
-      public String groupBy()
-      {
-         return getParts().get("group by");
-      }
-
-      @Override
-      public String pivot()
-      {
-         return getParts().get("pivot");
-      }
-
-      @Override
-      public String orderBy()
-      {
-         return getParts().get("order by");
-      }
-
-      @Override
-      public String limit()
-      {
-         return getParts().get("limit");
-      }
-
-      @Override
-      public String offset()
-      {
-         return getParts().get("offset");
-      }
-
-      @Override
-      public String label()
-      {
-         return getParts().get("label");
-      }
-
-      @Override
-      public String options()
-      {
-         return getParts().get("options");
-      }
-
-      private Map<String, String> getParts()
-      {
-         if (parts == null)
-         {
-            parts = new HashMap<String, String>();
-
-            String value = tq().get();
-            List<String> values = Arrays.asList(value.split(" "));
-            Collections.reverse(values);
-            String currentPhrase = "";
-            for (String str : values)
-            {
-               currentPhrase = str + currentPhrase;
-               boolean found = false;
-               for (String keyword : keywords)
-               {
-                  if (currentPhrase.startsWith(keyword + " "))
-                  {
-                     found = true;
-                     parts.put(keyword, currentPhrase.substring(keyword.length() + 1));
-                     currentPhrase = "";
-                     break;
-                  }
-               }
-
-               if (!found)
-                  currentPhrase = " " + currentPhrase;
-            }
-         }
-
-         return parts;
-      }
-
-      @Override
-      public Table applyTo(Table table)
-      {
-         ValueBuilder<Table> tableBuilder = Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF
-             .map( table ).module().newValueBuilderWithPrototype( table );
-
-/* TODO Finish label setting
-         if (label() != null)
-         {
-            String[] labels = label().split(",");
-            for (String label : labels)
-            {
-               String[] labelDef = label.split(" ",1);
-               labelDef[1] = labelDef[1].trim();
-
-            }
-            for (int i = 0; i < tableBuilder.prototype().cols().get().size(); i++)
-            {
-               ColumnValue cellValue = tableBuilder.prototype().cols().get().get(i);
-            }
-         }
-*/
-
-         if (orderBy() != null)
-         {
-            // Sort table
-            // Find sort column index
-            int sortIndex = -1;
-            List<Column> columns = table.cols().get();
-            for (int i = 0; i < columns.size(); i++)
-            {
-               Column column = columns.get(i);
-               if ( column.id().equals(orderBy()))
-               {
-                  sortIndex = i;
-                  break;
-               }
-
-            }
-
-            if (sortIndex != -1)
-            {
-               final int idx = sortIndex;
-               Comparator<Row> comparator = new Comparator<Row>()
-               {
-                  @Override
-                  public int compare(Row o1, Row o2)
-                  {
-                     Object o = o1.c().get().get(idx).v().get();
-
-                     if (o != null && o instanceof Comparable)
-                     {
-                        Comparable c1 = (Comparable) o;
-                        Comparable c2 = (Comparable) o2.c().get().get(idx).v().get();
-                        return c1.compareTo(c2);
-                     } else
-                     {
-                        String f1 = o1.c().get().get(idx).f().get();
-                        String f2 = o2.c().get().get(idx).f().get();
-                        return f1.compareTo(f2);
-                     }
-                  }
-               };
-
-               Collections.sort(tableBuilder.prototype().rows().get(), comparator);
-            }
-         }
-
-         // Paging
-         int start = 0;
-         int end = tableBuilder.prototype().rows().get().size();
-         if (offset() != null)
-            start = Integer.parseInt(offset());
-         if (limit() != null)
-            end = Math.min(end, start+ Integer.parseInt(limit()));
-
-         if (!(start == 0 && end == tableBuilder.prototype().rows().get().size()))
-            tableBuilder.prototype().rows().set(tableBuilder.prototype().rows().get().subList(start, end));
-
-         return tableBuilder.newInstance();
-      }
-   }
-}
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/TableResponse.java b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/TableResponse.java
deleted file mode 100644
index 762376b..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/TableResponse.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.common.table;
-
-import java.util.List;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * JAVADOC
- */
-public interface TableResponse
-   extends ValueComposite
-{
-   @Optional
-   Property<String> version();
-
-   @Optional
-   Property<String> reqId();
-
-   Property<String> status();
-
-   @Optional
-   Property<List<Problem>> warnings();
-
-   @Optional
-   Property<List<Problem>> errors();
-
-   @Optional
-   Property<String> sig();
-
-   @Optional
-   Property<Table> table();
-}
diff --git a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/package.html b/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/package.html
deleted file mode 100644
index 331aab0..0000000
--- a/libraries/rest-common/src/main/java/org/qi4j/library/rest/common/table/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ReST Table Support.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-server/build.gradle b/libraries/rest-server/build.gradle
index b9d14cb..49732c3 100644
--- a/libraries/rest-server/build.gradle
+++ b/libraries/rest-server/build.gradle
@@ -1,37 +1,42 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ REST Server Library provides a server component for building REST API's based on usecases"
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - REST server" }}
+description = "Apache Polygene™ REST Server Library provides a server component for building REST API's based on usecases"
+
+jar { manifest { name = "Apache Polygene™ Library - REST server" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.api"))
-  compile(project(":org.qi4j.libraries:org.qi4j.library.rest-common"))
-  compile(libraries.servlet_api)
-  compile libraries.slf4j_api
-  compile(libraries.velocity)
-  compile(libraries.restlet)
-  compile(libraries.freemarker)
+  compileOnly libraries.servlet_api
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
+  api polygene.library( 'rest-common' )
+  api libraries.restlet
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
+  implementation libraries.slf4j_api
+  implementation libraries.velocity
+  implementation libraries.freemarker
+
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
 }
diff --git a/libraries/rest-server/dev-status.xml b/libraries/rest-server/dev-status.xml
index 37f9020..d3c6f4f 100644
--- a/libraries/rest-server/dev-status.xml
+++ b/libraries/rest-server/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/RestServerException.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/RestServerException.java
new file mode 100644
index 0000000..3a272c4
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/RestServerException.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.library.rest.server;
+
+public class RestServerException extends RuntimeException
+{
+    public RestServerException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+
+    public RestServerException( String message )
+    {
+        super( message );
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ContextResource.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ContextResource.java
new file mode 100644
index 0000000..4b701fb
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ContextResource.java
@@ -0,0 +1,923 @@
+/*
+ *  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.polygene.library.rest.server.api;
+
+import java.io.UnsupportedEncodingException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.constraint.ConstraintViolation;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.constraint.Name;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.library.rest.common.Resource;
+import org.apache.polygene.library.rest.common.link.Link;
+import org.apache.polygene.library.rest.server.restlet.ConstraintViolationMessages;
+import org.apache.polygene.library.rest.server.restlet.InteractionConstraints;
+import org.apache.polygene.library.rest.server.restlet.RequestReaderDelegator;
+import org.apache.polygene.library.rest.server.restlet.ResponseWriterDelegator;
+import org.apache.polygene.library.rest.server.spi.ResultConverter;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.Uniform;
+import org.restlet.data.Form;
+import org.restlet.data.Language;
+import org.restlet.data.Preference;
+import org.restlet.data.Reference;
+import org.restlet.data.Status;
+import org.restlet.representation.EmptyRepresentation;
+import org.restlet.representation.Representation;
+import org.restlet.representation.StringRepresentation;
+import org.restlet.resource.ResourceException;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.polygene.api.util.Annotations.isType;
+import static org.apache.polygene.library.rest.server.api.ObjectSelection.current;
+
+/**
+ * JAVADOC
+ */
+public class ContextResource
+    implements Uniform
+{
+    private static final String ARGUMENTS = "arguments";
+    public static final String RESOURCE_VALIDITY = "validity";
+
+    // API fields
+    @Structure
+    private UnitOfWorkFactory uowf;
+
+    @Structure
+    protected Module module;
+
+    // Private state
+    private final Map<String, Method> resourceMethodQueries = new HashMap<>();
+    private final Map<String, Method> resourceMethodCommands = new HashMap<>();
+    private final Map<String, Method> subResources = new LinkedHashMap<>();
+    private final List<Method> resourceQueries = new ArrayList<>();
+    private final List<Method> resourceCommands = new ArrayList<>();
+
+    @Structure
+    private PolygeneSPI spi;
+
+    @Service
+    private ResponseWriterDelegator responseWriter;
+
+    @Service
+    private RequestReaderDelegator requestReader;
+
+    @Service
+    private InteractionConstraints constraints;
+
+    @Service
+    private Serializer serializer;
+
+    @Optional
+    @Service
+    private ResultConverter converter;
+
+    @Uses
+    private ContextRestlet restlet;
+
+    public ContextResource()
+    {
+        // Resource method mappings
+        for( Method method : getClass().getMethods() )
+        {
+            if( ContextResource.class.isAssignableFrom( method.getDeclaringClass() )
+                && !ContextResource.class.equals( method.getDeclaringClass() )
+                && !method.isSynthetic() )
+            {
+                if( method.getAnnotation( SubResource.class ) == null )
+                {
+                    Method oldMethod;
+
+                    if( isCommand( method ) )
+                    {
+                        oldMethod = resourceMethodCommands.put( method.getName().toLowerCase(), method );
+                        resourceCommands.add( method );
+                    }
+                    else
+                    {
+                        oldMethod = resourceMethodQueries.put( method.getName().toLowerCase(), method );
+                        resourceQueries.add( method );
+                    }
+
+                    if( oldMethod != null )
+                    {
+                        throw new IllegalStateException( "Two methods in resource " + getClass().getName() + " with same name " + oldMethod
+                            .getName() + ", which is not allowed" );
+                    }
+                }
+                else
+                {
+                    Method oldMethod = subResources.put( method.getName().toLowerCase(), method );
+
+                    if( oldMethod != null )
+                    {
+                        throw new IllegalStateException( "Two methods in resource " + getClass().getName() + " with same name " + oldMethod
+                            .getName() + ", which is not allowed" );
+                    }
+                }
+            }
+        }
+    }
+
+    // Uniform implementation
+    @Override
+    public final void handle( Request request, Response response )
+    {
+        ObjectSelection objectSelection = current();
+
+        // Check constraints for this resource
+        if( !constraints.isValid( getClass(), objectSelection, module ) )
+        {
+            throw new ResourceException( Status.CLIENT_ERROR_FORBIDDEN );
+        }
+
+        // Find remaining segments
+        List<String> segments = getSegments();
+
+        if( segments.size() > 0 )
+        {
+            String segment = segments.remove( 0 );
+
+            if( segments.size() > 0 )
+            {
+                handleSubResource( segment );
+            }
+            else
+            {
+                handleResource( segment );
+            }
+        }
+    }
+
+    // API methods
+    protected void setResourceValidity( EntityComposite entity )
+    {
+        Request request = Request.getCurrent();
+        ResourceValidity validity = new ResourceValidity( entity, spi, request );
+        request.getAttributes().put( RESOURCE_VALIDITY, validity );
+    }
+
+    protected void subResource( Class<? extends ContextResource> subResourceClass )
+    {
+        restlet.subResource( subResourceClass );
+    }
+
+    protected <T> T select( Class<T> entityClass, Identity id )
+        throws ResourceException
+    {
+        try
+        {
+            T composite = uowf.currentUnitOfWork().get( entityClass,  id );
+            current().select( composite );
+            return composite;
+        }
+        catch( NoSuchEntityTypeException | NoSuchEntityException e )
+        {
+            throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
+        }
+    }
+
+    protected <T> T selectFromManyAssociation( ManyAssociation<T> manyAssociation, Identity id )
+        throws ResourceException
+    {
+        T entity = (T) uowf.currentUnitOfWork().get( Object.class, id  );
+        if( !manyAssociation.contains( entity ) )
+        {
+            throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
+        }
+
+        current().select( entity );
+        return entity;
+    }
+
+    protected <T> T selectFromNamedAssociation( NamedAssociation<T> namedAssociation, Identity id )
+        throws ResourceException
+    {
+        T entity = (T) uowf.currentUnitOfWork().get( Object.class, id );
+        String name = namedAssociation.nameOf( entity );
+        if( name == null )
+        {
+            throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
+        }
+
+        current().select( entity );
+        return entity;
+    }
+
+    protected void selectFromList( List<?> list, String indexString )
+    {
+        Integer index = Integer.decode( indexString );
+
+        if( index < 0 || index >= list.size() )
+        {
+            throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
+        }
+
+        current().select( index );
+
+        Object value = list.get( index );
+        current().select( value );
+    }
+
+    protected Locale getLocale()
+    {
+        Request request = Request.getCurrent();
+
+        List<Preference<Language>> preferenceList = request.getClientInfo().getAcceptedLanguages();
+
+        if( preferenceList.isEmpty() )
+        {
+            return Locale.getDefault();
+        }
+
+        Language language = preferenceList
+            .get( 0 ).getMetadata();
+        String[] localeStr = language.getName().split( "-" );
+
+        Locale locale;
+        switch( localeStr.length )
+        {
+        case 1:
+            locale = new Locale( localeStr[ 0 ] );
+            break;
+        case 2:
+            locale = new Locale( localeStr[ 0 ], localeStr[ 1 ] );
+            break;
+        case 3:
+            locale = new Locale( localeStr[ 0 ], localeStr[ 1 ], localeStr[ 2 ] );
+            break;
+        default:
+            locale = Locale.getDefault();
+        }
+        return locale;
+    }
+
+    protected <T> T context( Class<T> contextClass )
+    {
+        return module.newObject( contextClass, ObjectSelection.current().toArray() );
+    }
+
+    // Private implementation
+    private void handleSubResource( String segment )
+    {
+        if( this instanceof SubResources )
+        {
+            SubResources subResources = (SubResources) this;
+            try
+            {
+                StringBuilder template = (StringBuilder) Request.getCurrent().getAttributes().get( "template" );
+                template.append( "resource/" );
+                subResources.resource( URLDecoder.decode( segment, "UTF-8" ) );
+            }
+            catch( UnsupportedEncodingException e )
+            {
+                subResources.resource( segment );
+            }
+        }
+        else
+        {
+            // Find @SubResource annotated method
+            try
+            {
+                Method method = getSubResourceMethod( segment );
+
+                StringBuilder template = (StringBuilder) Request.getCurrent().getAttributes().get( "template" );
+                template.append( segment ).append( "/" );
+
+                method.invoke( this );
+            }
+            catch( Throwable e )
+            {
+                handleException( Response.getCurrent(), e );
+            }
+        }
+    }
+
+    private Method getSubResourceMethod( String resourceName )
+        throws ResourceException
+    {
+        Method method = subResources.get( resourceName );
+        if( method != null )
+        {
+            return method;
+        }
+
+        throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
+    }
+
+    private void resource()
+    {
+        Request request = Request.getCurrent();
+        Response response = Response.getCurrent();
+        if( !request.getMethod().equals( org.restlet.data.Method.GET ) )
+        {
+            response.setStatus( Status.CLIENT_ERROR_METHOD_NOT_ALLOWED );
+            return;
+        }
+
+        ObjectSelection objectSelection = current();
+
+        // Check for interaction->method mappings
+        if( ResourceDelete.class.isAssignableFrom( getClass() ) )
+        {
+            response.getAllowedMethods().add( org.restlet.data.Method.DELETE );
+        }
+        if( ResourceUpdate.class.isAssignableFrom( getClass() ) )
+        {
+            response.getAllowedMethods().add( org.restlet.data.Method.PUT );
+        }
+
+        // Construct resource
+        ValueBuilder<Resource> builder = module.newValueBuilder( Resource.class );
+
+        List<Link> queriesProperty = builder.prototype().queries().get();
+        for( Method query : resourceQueries )
+        {
+            if( constraints.isValid( query, objectSelection, module ) )
+            {
+                ValueBuilder<Link> linkBuilder = module.newValueBuilder( Link.class );
+                Link prototype = linkBuilder.prototype();
+                prototype.classes().set( "query" );
+                prototype.text().set( humanReadable( query.getName() ) );
+                prototype.href().set( query.getName().toLowerCase() );
+                prototype.rel().set( query.getName().toLowerCase() );
+                prototype.id().set( query.getName().toLowerCase() );
+                queriesProperty.add( linkBuilder.newInstance() );
+            }
+        }
+
+        List<Link> commandsProperty = builder.prototype().commands().get();
+        for( Method command : resourceCommands )
+        {
+            if( constraints.isValid( command, objectSelection, module ) )
+            {
+                ValueBuilder<Link> linkBuilder = module.newValueBuilder( Link.class );
+                Link prototype = linkBuilder.prototype();
+                prototype.classes().set( "command" );
+                prototype.text().set( humanReadable( command.getName() ) );
+                prototype.href().set( command.getName().toLowerCase() );
+                prototype.rel().set( command.getName().toLowerCase() );
+                prototype.id().set( command.getName().toLowerCase() );
+                commandsProperty.add( linkBuilder.newInstance() );
+            }
+        }
+
+        List<Link> resourcesProperty = builder.prototype().resources().get();
+        for( Method subResource : subResources.values() )
+        {
+            if( constraints.isValid( subResource, objectSelection, module ) )
+            {
+                ValueBuilder<Link> linkBuilder = module.newValueBuilder( Link.class );
+                Link prototype = linkBuilder.prototype();
+                prototype.classes().set( "resource" );
+                prototype.text().set( humanReadable( subResource.getName() ) );
+                prototype.href().set( subResource.getName().toLowerCase() + "/" );
+                prototype.rel().set( subResource.getName().toLowerCase() );
+                prototype.id().set( subResource.getName().toLowerCase() );
+                resourcesProperty.add( linkBuilder.newInstance() );
+            }
+        }
+
+        try
+        {
+            Method indexMethod = resourceMethodQueries.get( "index" );
+            if( indexMethod != null )
+            {
+                Object index = convert( indexMethod.invoke( this ) );
+
+                if( index != null && index instanceof ValueComposite )
+                {
+                    builder.prototype().index().set( index );
+                }
+            }
+        }
+        catch( Throwable e )
+        {
+            // Ignore
+        }
+
+        try
+        {
+            responseWriter.writeResponse( builder.newInstance(), response );
+        }
+        catch( Throwable e )
+        {
+            handleException( response, e );
+        }
+    }
+
+    private boolean isCommand( Method method )
+    {
+        return method.getReturnType().equals( Void.TYPE ) || method.getName().equals( "create" );
+    }
+
+    /**
+     * Transform a Java name to a human readable string by replacing uppercase characters
+     * with space+toLowerCase(char).
+     * <p>
+     * Example:
+     * <pre><code>
+     * changeDescription -> Change description
+     * doStuffNow -> Do stuff now
+     * </code></pre>
+     *
+     * @param name Java name
+     *
+     * @return Human readable name
+     */
+    private String humanReadable( String name )
+    {
+        StringBuilder humanReadableString = new StringBuilder();
+
+        for( int i = 0; i < name.length(); i++ )
+        {
+            char character = name.charAt( i );
+            if( i == 0 )
+            {
+                // Capitalize first character
+                humanReadableString.append( Character.toUpperCase( character ) );
+            }
+            else if( Character.isLowerCase( character ) )
+            {
+                humanReadableString.append( character );
+            }
+            else
+            {
+                humanReadableString.append( ' ' ).append( Character.toLowerCase( character ) );
+            }
+        }
+
+        return humanReadableString.toString();
+    }
+
+    private void result( Object resultValue )
+        throws Exception
+    {
+        if( resultValue != null )
+        {
+            if( !responseWriter.writeResponse( resultValue, Response.getCurrent() ) )
+            {
+                throw new ResourceException( Status.SERVER_ERROR_INTERNAL, "No result writer for type " + resultValue.getClass()
+                    .getName() );
+            }
+        }
+    }
+
+    private List<String> getSegments()
+    {
+        return (List<String>) Request.getCurrent().getAttributes().get( "segments" );
+    }
+
+    private void handleResource( String segment )
+    {
+        Request request = Request.getCurrent();
+        if( segment.isEmpty() || segment.equals( "." ) )
+        {
+            StringBuilder template = (StringBuilder) request.getAttributes().get( "template" );
+            template.append( "resource" );
+
+            // Index for this resource
+            resource();
+        }
+        else
+        {
+            StringBuilder template = (StringBuilder) request.getAttributes().get( "template" );
+            template.append( segment );
+
+            if( resourceMethodCommands.containsKey( segment ) )
+            {
+                handleCommand( segment );
+            }
+            else
+            {
+                handleQuery( segment );
+            }
+        }
+    }
+
+    private void handleCommand( String segment )
+    {
+        Request request = Request.getCurrent();
+        Response response = Response.getCurrent();
+
+        // Check if this is a request to show the form for this command
+        Method interactionMethod = resourceMethodCommands.get( segment );
+        if( shouldShowCommandForm( interactionMethod ) )
+        {
+            // Show form
+
+            // TODO This should check if method is idempotent
+            response.getAllowedMethods().add( org.restlet.data.Method.POST );
+
+            try
+            {
+                // Check if there is a query with this name - if so invoke it
+                Method queryMethod = resourceMethodQueries.get( segment );
+                if( queryMethod != null )
+                {
+                    result( queryMethod.invoke( this ) );
+                }
+                else
+                {
+                    request.setMethod( org.restlet.data.Method.POST );
+                    response.setStatus( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY );
+                    result( formForMethod( interactionMethod ) );
+                }
+            }
+            catch( Exception e )
+            {
+                handleException( response, e );
+            }
+        }
+        else
+        {
+            // Check timestamps
+            ResourceValidity validity = (ResourceValidity) request.getAttributes().get( RESOURCE_VALIDITY );
+            if( validity != null )
+            {
+                validity.checkRequest();
+            }
+
+            // We have input data - do command
+            // Check method constraints
+            if( !constraints.isValid( interactionMethod, current(), module ) )
+            {
+                throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
+            }
+
+            // Create argument
+            Object[] arguments = requestReader.readRequest( Request.getCurrent(), interactionMethod );
+            Request.getCurrent().getAttributes().put( ARGUMENTS, arguments );
+
+            // Invoke method
+            try
+            {
+                Object result = interactionMethod.invoke( this, arguments );
+
+                if( result != null )
+                {
+                    if( result instanceof Representation )
+                    {
+                        response.setEntity( (Representation) result );
+                    }
+                    else
+                    {
+                        result( convert( result ) );
+                    }
+                }
+            }
+            catch( Throwable e )
+            {
+                handleException( response, e );
+            }
+        }
+    }
+
+    private boolean shouldShowCommandForm( Method interactionMethod )
+    {
+        // Show form on GET/HEAD
+        if( Request.getCurrent().getMethod().isSafe() )
+        {
+            return true;
+        }
+
+        if( interactionMethod.getParameterTypes().length > 0 )
+        {
+            return !( interactionMethod.getParameterTypes()[ 0 ].equals( Response.class ) || Request.getCurrent()
+                .getEntity()
+                .isAvailable() || Request.getCurrent().getEntityAsText() != null || Request.getCurrent()
+                                                                                        .getResourceRef()
+                                                                                        .getQuery() != null );
+        }
+
+        return false;
+    }
+
+    private void handleQuery( String segment )
+    {
+        Request request = Request.getCurrent();
+        Response response = Response.getCurrent();
+
+        // Query
+
+        // Try to locate either the query method or command method that should be used
+        Method queryMethod = resourceMethodQueries.get( segment );
+        if( queryMethod == null )
+        {
+            queryMethod = resourceMethodCommands.get( segment );
+        }
+
+        if( queryMethod == null )
+        {
+            // Not found as interaction, try SubResource
+            Method resourceMethod = subResources.get( segment );
+            if( resourceMethod != null && resourceMethod.getAnnotation( SubResource.class ) != null )
+            {
+                // Found it! Redirect to it
+                response.setStatus( Status.REDIRECTION_FOUND );
+                response
+                    .setLocationRef( new Reference( request
+                                                        .getResourceRef()
+                                                        .toString() + "/" ).toString() );
+                return;
+            }
+            else
+            {
+                // 404
+                throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
+            }
+        }
+
+        // Check if this is a request to show the form for this interaction
+        if( ( request
+                  .getMethod()
+                  .isSafe() && queryMethod.getParameterTypes().length != 0 && request
+                                                                                  .getResourceRef()
+                                                                                  .getQuery() == null ) ||
+            ( !request
+                .getMethod()
+                .isSafe() && queryMethod.getParameterTypes().length != 0 && !( request
+                                                                                   .getEntity()
+                                                                                   .isAvailable() || request
+                                                                                                         .getResourceRef()
+                                                                                                         .getQuery() != null || queryMethod
+                                                                                   .getParameterTypes()[ 0 ].equals( Response.class ) ) ) )
+        {
+            // Show form
+            try
+            {
+                // Tell client to try again
+                response.setStatus( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY );
+                response.getAllowedMethods().add( org.restlet.data.Method.GET );
+                response.getAllowedMethods().add( org.restlet.data.Method.POST );
+                result( formForMethod( queryMethod ) );
+            }
+            catch( Exception e )
+            {
+                handleException( response, e );
+            }
+        }
+        else
+        {
+            // Check timestamps
+            ResourceValidity validity = (ResourceValidity) request.getAttributes().get( RESOURCE_VALIDITY );
+            if( validity != null )
+            {
+                validity.checkRequest();
+            }
+
+            // We have input data - do query
+            // Check method constraints
+            if( !constraints.isValid( queryMethod, current(), module ) )
+            {
+                throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
+            }
+
+            try
+            {
+                // Create argument
+                Object[] arguments;
+                if( queryMethod.getParameterTypes().length > 0 )
+                {
+                    try
+                    {
+                        arguments = requestReader.readRequest( Request.getCurrent(), queryMethod );
+
+                        if( arguments == null )
+                        {
+                            // Show form
+                            result( formForMethod( queryMethod ) );
+                            return;
+                        }
+                    }
+                    catch( IllegalArgumentException e )
+                    {
+                        // Still missing some values - show form
+                        result( formForMethod( queryMethod ) );
+                        return;
+                    }
+                }
+                else
+                {
+                    // No arguments to this query
+                    arguments = new Object[ 0 ];
+                }
+
+                // Invoke method
+                Request.getCurrent().getAttributes().put( ARGUMENTS, arguments );
+                Object result = queryMethod.invoke( this, arguments );
+                if( result != null )
+                {
+                    if( result instanceof Representation )
+                    {
+                        response.setEntity( (Representation) result );
+                    }
+                    else
+                    {
+                        result( convert( result ) );
+                    }
+                }
+            }
+            catch( Throwable e )
+            {
+                handleException( response, e );
+            }
+        }
+    }
+
+    private Object convert( Object result )
+    {
+        if( converter != null )
+        {
+            result = converter.convert( result, Request.getCurrent(), (Object[]) Request.getCurrent()
+                .getAttributes()
+                .get( ARGUMENTS ) );
+        }
+
+        return result;
+    }
+
+    private void handleException( Response response, Throwable ex )
+    {
+        while( ex instanceof InvocationTargetException )
+        {
+            ex = ex.getCause();
+        }
+
+        try
+        {
+            throw ex;
+        }
+        catch( ResourceException e )
+        {
+            // IAE (or subclasses) are considered client faults
+            response.setEntity( new StringRepresentation( e.getMessage() ) );
+            response.setStatus( e.getStatus() );
+        }
+        catch( ConstraintViolationException e )
+        {
+            try
+            {
+                ConstraintViolationMessages cvm = new ConstraintViolationMessages();
+
+                // CVE are considered client faults
+                String messages = "";
+                Locale locale = ObjectSelection.type( Locale.class );
+                for( ConstraintViolation constraintViolation : e.constraintViolations() )
+                {
+                    if( !messages.isEmpty() )
+                    {
+                        messages += "\n";
+                    }
+                    messages += cvm.getMessage( constraintViolation, locale );
+                }
+
+                response.setEntity( new StringRepresentation( messages ) );
+                response.setStatus( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY );
+            }
+            catch( Exception e1 )
+            {
+                response.setEntity( new StringRepresentation( e.getMessage() ) );
+                response.setStatus( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY );
+            }
+        }
+        catch( IllegalArgumentException e )
+        {
+            // IAE (or subclasses) are considered client faults
+            response.setEntity( new StringRepresentation( e.getMessage() ) );
+            response.setStatus( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY );
+        }
+        catch( RuntimeException e )
+        {
+            // RuntimeExceptions are considered server faults
+            LoggerFactory.getLogger( getClass() ).warn( "Exception thrown during processing", e );
+            response.setEntity( new StringRepresentation( e.getMessage() ) );
+            response.setStatus( Status.SERVER_ERROR_INTERNAL );
+        }
+        catch( Exception e )
+        {
+            // Checked exceptions are considered client faults
+            String s = e.getMessage();
+            if( s == null )
+            {
+                s = e.getClass().getSimpleName();
+            }
+            response.setEntity( new StringRepresentation( s ) );
+            response.setStatus( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY );
+        }
+        catch( Throwable e )
+        {
+            // Anything else are considered server faults
+            LoggerFactory.getLogger( getClass() ).error( "Exception thrown during processing", e );
+            response.setEntity( new StringRepresentation( e.getMessage() ) );
+            response.setStatus( Status.SERVER_ERROR_INTERNAL );
+        }
+    }
+
+    private Form formForMethod( Method interactionMethod )
+    {
+        Form form = new Form();
+
+        Form queryAsForm = Request.getCurrent().getResourceRef().getQueryAsForm();
+        Form entityAsForm;
+        Representation representation = Request.getCurrent().getEntity();
+        if( representation != null && !EmptyRepresentation.class.isInstance( representation ) )
+        {
+            entityAsForm = new Form( representation );
+        }
+        else
+        {
+            entityAsForm = new Form();
+        }
+
+        Class<?> valueType = interactionMethod.getParameterTypes()[ 0 ];
+        if( ValueComposite.class.isAssignableFrom( valueType ) )
+        {
+            ValueDescriptor valueDescriptor = module.descriptor().valueDescriptor( valueType.getName() );
+
+            valueDescriptor.state().properties().forEach( propertyDescriptor -> {
+                String value = getValue( propertyDescriptor.qualifiedName().name(), queryAsForm, entityAsForm );
+                if( value == null )
+                {
+                    Object initialValue = propertyDescriptor.resolveInitialValue(module.descriptor());
+                    if( initialValue != null )
+                    {
+                        value = serializer.serialize( initialValue );
+                    }
+                }
+                form.add( propertyDescriptor.qualifiedName().name(), value );
+            } );
+        }
+        else if( valueType.isInterface() && interactionMethod.getParameterTypes().length == 1 )
+        {
+            // Single entity as input
+            form.add( "entity", getValue( "entity", queryAsForm, entityAsForm ) );
+        }
+        else
+        {
+            // Construct form out of individual parameters instead
+            for( Annotation[] annotations : interactionMethod.getParameterAnnotations() )
+            {
+                Name name = (Name) Stream.of( annotations ).filter( isType( Name.class ) ).findFirst().orElse( null );
+                form.add( name.value(), getValue( name.value(), queryAsForm, entityAsForm ) );
+            }
+        }
+
+        return form;
+    }
+
+    private String getValue( String name, Form queryAsForm, Form entityAsForm )
+    {
+        String value = queryAsForm.getFirstValue( name );
+        if( value == null )
+        {
+            value = entityAsForm.getFirstValue( name );
+        }
+        return value;
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ContextRestlet.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ContextRestlet.java
new file mode 100644
index 0000000..ac558f7
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ContextRestlet.java
@@ -0,0 +1,315 @@
+/*
+ *  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.polygene.library.rest.server.api;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.polygene.api.cache.CacheOptions;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.library.rest.server.restlet.ResponseWriterDelegator;
+import org.apache.polygene.library.rest.server.spi.CommandResult;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.Restlet;
+import org.restlet.Uniform;
+import org.restlet.data.CharacterSet;
+import org.restlet.data.Language;
+import org.restlet.data.Method;
+import org.restlet.data.Reference;
+import org.restlet.data.Status;
+import org.restlet.representation.Representation;
+import org.restlet.representation.StringRepresentation;
+import org.restlet.resource.ResourceException;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+
+/**
+ * JAVADOC
+ */
+public abstract class ContextRestlet
+    extends Restlet
+{
+    @Structure
+    protected ObjectFactory objectFactory;
+
+    @Structure
+    protected UnitOfWorkFactory uowf;
+
+    @Service
+    private CommandResult commandResult;
+
+    @Service
+    private ResponseWriterDelegator responseWriter;
+
+    private Map<Class, Uniform> subResources = Collections.synchronizedMap( new HashMap<>() );
+
+    @Override
+    public void handle( Request request, Response response )
+    {
+        super.handle( request, response );
+
+        MDC.put( "url", request.getResourceRef().toString() );
+
+        try
+        {
+            int tries = 0;
+
+            // TODO Make this number configurable
+            while( tries < 10 )
+            {
+                tries++;
+
+                // Root of the call
+                Reference ref = request.getResourceRef();
+                List<String> segments = ref.getScheme()
+                                            .equals( "riap" ) ? ref.getRelativeRef( new Reference( "riap://application/" ) )
+                                            .getSegments() : ref.getRelativeRef().getSegments();
+
+                // Handle conversion of verbs into standard interactions
+                if( segments.get( segments.size() - 1 ).equals( "" ) )
+                {
+                    if( request.getMethod().equals( Method.DELETE ) )
+                    {
+                        // Translate DELETE into command "delete"
+                        segments.set( segments.size() - 1, "delete" );
+                    }
+                    else if( request.getMethod().equals( Method.PUT ) )
+                    {
+                        // Translate PUT into command "update"
+                        segments.set( segments.size() - 1, "update" );
+                    }
+                }
+
+                request.getAttributes().put( "segments", segments );
+                request.getAttributes().put( "template", new StringBuilder( "/rest/" ) );
+
+                Usecase usecase = UsecaseBuilder.buildUsecase( getUsecaseName( request ) )
+                    .withMetaInfo( request.getMethod().isSafe() ? CacheOptions.ALWAYS : CacheOptions.NEVER )
+                    .newUsecase();
+                UnitOfWork uow = uowf.newUnitOfWork( usecase );
+
+                ObjectSelection.newSelection();
+
+                try
+                {
+                    // Start handling the build-up for the context
+                    Uniform resource = createRoot( request, response );
+                    resource.handle( request, response );
+
+                    if( response.getEntity() != null )
+                    {
+                        if( response.getEntity().getModificationDate() == null )
+                        {
+
+                            ResourceValidity validity = (ResourceValidity) Request.getCurrent()
+                                .getAttributes()
+                                .get( ContextResource.RESOURCE_VALIDITY );
+                            if( validity != null )
+                            {
+                                validity.updateResponse( response );
+                            }
+                        }
+
+                        // Check if characterset is set
+                        if( response.getEntity().getCharacterSet() == null )
+                        {
+                            response.getEntity().setCharacterSet( CharacterSet.UTF_8 );
+                        }
+
+                        // Check if language is set
+                        if( response.getEntity().getLanguages().isEmpty() )
+                        {
+                            response.getEntity().getLanguages().add( Language.ENGLISH );
+                        }
+
+                        uow.discard();
+                    }
+                    else
+                    {
+                        // Check if last modified and tag is set
+                        ResourceValidity validity = null;
+
+                        try
+                        {
+                            validity = ObjectSelection.type( ResourceValidity.class );
+                        }
+                        catch( IllegalArgumentException e )
+                        {
+                            // Ignore
+                        }
+
+                        uow.complete();
+
+                        Object result = commandResult.getResult();
+                        if( result != null )
+                        {
+                            if( result instanceof Representation )
+                            {
+                                response.setEntity( (Representation) result );
+                            }
+                            else
+                            {
+                                if( !responseWriter.writeResponse( result, response ) )
+                                {
+                                    throw new ResourceException( Status.SERVER_ERROR_INTERNAL, "Could not write result of type " + result
+                                        .getClass()
+                                        .getName() );
+                                }
+                            }
+
+                            if( response.getEntity() != null )
+                            {
+                                // Check if characterset is set
+                                if( response.getEntity().getCharacterSet() == null )
+                                {
+                                    response.getEntity().setCharacterSet( CharacterSet.UTF_8 );
+                                }
+
+                                // Check if language is set
+                                if( response.getEntity().getLanguages().isEmpty() )
+                                {
+                                    response.getEntity().getLanguages().add( Language.ENGLISH );
+                                }
+
+                                // Check if last modified and tag should be set
+                                if( validity != null )
+                                {
+                                    UnitOfWork lastModifiedUoW = uowf.newUnitOfWork();
+
+                                    try
+                                    {
+                                        validity.updateEntity( lastModifiedUoW );
+
+                                        validity.updateResponse( response );
+                                    }
+                                    finally
+                                    {
+                                        lastModifiedUoW.discard();
+                                    }
+                                }
+                            }
+                        }
+                        return;
+                    }
+                    return;
+                }
+                catch( ConcurrentEntityModificationException ex )
+                {
+                    uow.discard();
+
+                    // Try again
+                    ObjectSelection.newSelection();
+                }
+                catch( Throwable e )
+                {
+                    uow.discard();
+                    handleException( response, e );
+                    return;
+                }
+            } // Try again
+        }
+        finally
+        {
+            MDC.clear();
+        }
+    }
+
+    protected abstract Uniform createRoot( Request request, Response response );
+
+    // Callbacks used from resources
+    public void subResource( Class<? extends ContextResource> subResourceClass )
+    {
+        Uniform subResource = subResources.get( subResourceClass );
+
+        if( subResource == null )
+        {
+            // Instantiate and store subresource instance
+            subResource = objectFactory.newObject( subResourceClass, this );
+            subResources.put( subResourceClass, subResource );
+        }
+
+        subResource.handle( Request.getCurrent(), Response.getCurrent() );
+    }
+
+    private String getUsecaseName( Request request )
+    {
+        if( request.getMethod().equals( org.restlet.data.Method.DELETE ) )
+        {
+            return "delete";
+        }
+        else
+        {
+            return request.getResourceRef().getLastSegment();
+        }
+    }
+
+    private void handleException( Response response, Throwable ex )
+    {
+        try
+        {
+            throw ex;
+        }
+        catch( ResourceException e )
+        {
+            // IAE (or subclasses) are considered client faults
+            LoggerFactory.getLogger( getClass() ).debug( "ResourceException thrown during processing", e );
+            response.setEntity( new StringRepresentation( e.getMessage() ) );
+            response.setStatus( e.getStatus() );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // IAE (or subclasses) are considered client faults
+            LoggerFactory.getLogger( getClass() ).debug( "IllegalArgumentsException thrown during processing", e );
+            response.setEntity( new StringRepresentation( e.getMessage() ) );
+            response.setStatus( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY );
+        }
+        catch( RuntimeException e )
+        {
+            // RuntimeExceptions are considered server faults
+            LoggerFactory.getLogger( getClass() ).warn( "Exception thrown during processing", e );
+            response.setEntity( new StringRepresentation( e.getMessage() ) );
+            response.setStatus( Status.SERVER_ERROR_INTERNAL );
+        }
+        catch( Exception e )
+        {
+            // Checked exceptions are considered client faults
+            LoggerFactory.getLogger( getClass() ).debug( "Checked exception thrown during processing", e );
+            response.setEntity( new StringRepresentation( e.getMessage() ) );
+            response.setStatus( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY );
+        }
+        catch( Throwable e )
+        {
+            // Anything else are considered server faults
+            LoggerFactory.getLogger( getClass() ).error( "Exception thrown during processing", e );
+            response.setEntity( new StringRepresentation( e.getMessage() ) );
+            response.setStatus( Status.SERVER_ERROR_INTERNAL );
+        }
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/InteractionConstraintsConcern.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/InteractionConstraintsConcern.java
new file mode 100644
index 0000000..3a197af
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/InteractionConstraintsConcern.java
@@ -0,0 +1,82 @@
+/*
+ *  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.polygene.library.rest.server.api;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.AppliesToFilter;
+import org.apache.polygene.api.concern.GenericConcern;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.library.rest.server.api.constraint.InteractionConstraintDeclaration;
+import org.apache.polygene.library.rest.server.api.constraint.RequiresValid;
+import org.apache.polygene.library.rest.server.restlet.InteractionConstraints;
+
+/**
+ * Add this concern to all interaction methods that use constraints
+ */
+@AppliesTo( InteractionConstraintsConcern.HasInteractionConstraints.class )
+public class InteractionConstraintsConcern
+    extends GenericConcern
+{
+    @Service
+    private InteractionConstraints interactionConstraints;
+
+    @Service
+    private Module module;
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        if( !interactionConstraints.isValid( proxy.getClass(), ObjectSelection.current(), module ) )
+        {
+            throw new IllegalStateException( "Not allowed to invoke interaction " + method.getName() );
+        }
+
+        if( !interactionConstraints.isValid( method, ObjectSelection.current(), module ) )
+        {
+            throw new IllegalStateException( "Not allowed to invoke interaction " + method.getName() );
+        }
+
+        return next.invoke( proxy, method, args );
+    }
+
+    public static class HasInteractionConstraints
+        implements AppliesToFilter
+    {
+        @Override
+        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
+        {
+            for( Annotation annotation : method.getAnnotations() )
+            {
+                if( annotation.annotationType().equals( RequiresValid.class ) ||
+                    annotation.annotationType().getAnnotation( ConstraintDeclaration.class ) != null ||
+                    annotation.annotationType().getAnnotation( InteractionConstraintDeclaration.class ) != null )
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ObjectSelection.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ObjectSelection.java
new file mode 100644
index 0000000..0ea955d
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ObjectSelection.java
@@ -0,0 +1,92 @@
+/*
+ *  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.polygene.library.rest.server.api;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.restlet.Request;
+
+/**
+ * Manage the current object selection. An instance of ObjectSelection
+ * is created for each request, and stored as an attribute.
+ * Whenever an object is identified in the chain, add it to the selection.
+ */
+public class ObjectSelection
+{
+    public static ObjectSelection current()
+    {
+        return (ObjectSelection) Request.getCurrent().getAttributes().get( "selection" );
+    }
+
+    public static <T> T type( Class<T> type )
+    {
+        ObjectSelection selection = current();
+        if( selection == null )
+        {
+            throw new IllegalStateException( "No current selection" );
+        }
+
+        return selection.get( type );
+    }
+
+    public static void newSelection()
+    {
+        Request.getCurrent().getAttributes().put( "selection", new ObjectSelection() );
+    }
+
+    private List<Object> selection = new ArrayList<Object>();
+
+    /**
+     * Create new root roleMap
+     */
+    public ObjectSelection()
+    {
+    }
+
+    public void select( Object object )
+    {
+        selection.add( 0, object );
+    }
+
+    public <T> T get( Class<T> type )
+        throws IllegalArgumentException
+    {
+        for( Object object : selection )
+        {
+            if( type.isInstance( object ) )
+            {
+                return (T) object;
+            }
+        }
+        throw new IllegalArgumentException( "No object in selection for type:" + type.getSimpleName() );
+    }
+
+    public List<Object> selection()
+    {
+        return Collections.unmodifiableList( selection );
+    }
+
+    public Object[] toArray()
+    {
+        return selection.toArray( new Object[ selection.size() ] );
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ResourceCreate.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ResourceCreate.java
new file mode 100644
index 0000000..00b0219
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ResourceCreate.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.rest.server.api;
+
+/**
+ * Standard interface for creation of new resources.
+ */
+public interface ResourceCreate<INPUT, RESULT>
+{
+    RESULT create( INPUT value );
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ResourceDelete.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ResourceDelete.java
new file mode 100644
index 0000000..5d8fdc0
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ResourceDelete.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.rest.server.api;
+
+import java.io.IOException;
+
+/**
+ * Standard interface for deletion of resources
+ */
+public interface ResourceDelete
+{
+    void delete()
+        throws IOException;
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ResourceIndex.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ResourceIndex.java
new file mode 100644
index 0000000..852d780
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ResourceIndex.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.rest.server.api;
+
+/**
+ * Standard interface for index of resources
+ */
+public interface ResourceIndex<T>
+{
+    T index();
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ResourceUpdate.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ResourceUpdate.java
new file mode 100644
index 0000000..3dc9317
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ResourceUpdate.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.rest.server.api;
+
+/**
+ * Standard interface for update of existing resources.
+ */
+public interface ResourceUpdate<T>
+{
+    void update( T value );
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ResourceValidity.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ResourceValidity.java
new file mode 100644
index 0000000..495f067
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/ResourceValidity.java
@@ -0,0 +1,101 @@
+/*
+ *  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.polygene.library.rest.server.api;
+
+import java.time.Instant;
+import java.time.temporal.ChronoField;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.apache.polygene.spi.entity.EntityState;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.data.Status;
+import org.restlet.data.Tag;
+import org.restlet.resource.ResourceException;
+
+/**
+ * JAVADOC
+ */
+class ResourceValidity
+{
+    private EntityComposite entity;
+    private final PolygeneSPI spi;
+    private Request request;
+
+    ResourceValidity( EntityComposite entity, PolygeneSPI spi, Request request )
+    {
+        this.entity = entity;
+        this.spi = spi;
+        this.request = request;
+    }
+
+    void updateEntity( UnitOfWork current )
+    {
+        try
+        {
+            entity = current.get( entity );
+        }
+        catch( NoSuchEntityException e )
+        {
+            // Entity was deleted
+            entity = null;
+        }
+    }
+
+    void updateResponse( Response response )
+    {
+        if( entity != null )
+        {
+            EntityState state = spi.entityStateOf( entity );
+            Tag tag = new Tag( state.entityReference().identity() + "/" + state.version() );
+            response.getEntity().setModificationDate( java.util.Date.from( state.lastModified() ) );
+            response.getEntity().setTag( tag );
+        }
+    }
+
+    void checkRequest()
+        throws ResourceException
+    {
+        // Check command rules
+        Instant unmodifiedSince = request.getConditions().getUnmodifiedSince().toInstant();
+        EntityState state = spi.entityStateOf( entity );
+        Instant lastModifiedSeconds = state.lastModified().with(ChronoField.NANO_OF_SECOND, 0 );
+        if( unmodifiedSince != null )
+        {
+            if( lastModifiedSeconds.isAfter( unmodifiedSince ) )
+            {
+                throw new ResourceException( Status.CLIENT_ERROR_CONFLICT );
+            }
+        }
+
+        // Check query rules
+        Instant modifiedSince = request.getConditions().getModifiedSince().toInstant();
+        if( modifiedSince != null )
+        {
+            if( !lastModifiedSeconds.isAfter( modifiedSince ) )
+            {
+                throw new ResourceException( Status.REDIRECTION_NOT_MODIFIED );
+            }
+        }
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/SubResource.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/SubResource.java
new file mode 100644
index 0000000..8cdf6e0
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/SubResource.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.rest.server.api;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Mark methods that creates new sub-resources with this annotation
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.METHOD } )
+@Documented
+public @interface SubResource
+{
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/SubResources.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/SubResources.java
new file mode 100644
index 0000000..53525ab
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/SubResources.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.rest.server.api;
+
+import org.restlet.resource.ResourceException;
+
+/**
+ * Resources that have a collection of sub-resources should extends this interface.
+ */
+public interface SubResources
+{
+    /**
+     * Instantiate the sub-resource, perform any RoleMap bindings based on
+     * the given segment, and then call handle(Request,Response) on the subresource.
+     *
+     * @param segment the current segment that the sub-resource will correspond to
+     *
+     * @throws org.restlet.resource.ResourceException
+     *          if the subresource could not be lookup up, typically a 404
+     */
+    void resource( String segment )
+        throws ResourceException;
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/InteractionConstraint.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/InteractionConstraint.java
new file mode 100644
index 0000000..b8a3f11
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/InteractionConstraint.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.rest.server.api.constraint;
+
+import org.apache.polygene.library.rest.server.api.ObjectSelection;
+
+/**
+ * JAVADOC
+ */
+
+public interface InteractionConstraint<ANNOTATION extends java.lang.annotation.Annotation>
+{
+    boolean isValid( ANNOTATION annotation, ObjectSelection objectSelection );
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/InteractionConstraintDeclaration.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/InteractionConstraintDeclaration.java
new file mode 100644
index 0000000..5c835a6
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/InteractionConstraintDeclaration.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.rest.server.api.constraint;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * JAVADOC
+ */
+@Retention( RetentionPolicy.RUNTIME )
+public @interface InteractionConstraintDeclaration
+{
+    Class<? extends InteractionConstraint<?>> value();
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/InteractionValidation.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/InteractionValidation.java
new file mode 100644
index 0000000..a89bfa1
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/InteractionValidation.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.library.rest.server.api.constraint;
+
+/**
+ * Interface that resources can implement to achieve custom validation
+ * of whether an interaction is valid or not.
+ * <p>
+ * If the logic only applies for one
+ * method it is usually better to use this instead of creating a new annotation for it.
+ * </p>
+ * <p>
+ * This is triggered by annotating the method that should be validated like so:
+ * </p>
+ * <pre><code>
+ *
+ * &#64;RequiresValid("xyz") public void xyz()
+ * {...}
+ *
+ * </code></pre>
+ * <p>
+ * This causes isValid("xyz") to be called. The isValid()
+ * method can use the name to determine which set of logic is to be applied. Typically the provided
+ * string will correspond to the name of the interaction, but this is not strictly necessary. It is
+ * possible to combine several annotations on one method, if desired:
+ * </p>
+ * <pre><code>
+ *
+ * &#64;RequiresValid("allowed") &#64;RequiresValid("officehours")
+ * public void xyz()
+ * {...}
+ * </code></pre>
+ * <p>
+ * The validation occurs both when a Resource is computed for the resource as a whole, and when an actual
+ * invocation of an interaction is made.
+ * </p>
+ */
+public interface InteractionValidation
+{
+    boolean isValid( String name );
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/Requires.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/Requires.java
new file mode 100644
index 0000000..514f429
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/Requires.java
@@ -0,0 +1,67 @@
+/*
+ *  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.polygene.library.rest.server.api.constraint;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.library.rest.server.api.ObjectSelection;
+
+/**
+ * Annotation on interactions that requires objects of specific types
+ * to be available in the ObjectSelection.
+ *
+ * Example:
+ * <pre>
+ *     &#64;Requires(File.class)
+ *     public Representation content() {...}
+ * </pre>
+ */
+@ConstraintDeclaration
+@Retention( RetentionPolicy.RUNTIME )
+@Constraints( Requires.RequiresRoleConstraint.class )
+public @interface Requires
+{
+    Class<?>[] value();
+
+    class RequiresRoleConstraint
+        implements Constraint<Requires, ObjectSelection>
+    {
+        @Override
+        public boolean isValid( Requires requires, ObjectSelection objectSelection )
+        {
+            for( Class<?> roleClass : requires.value() )
+            {
+                try
+                {
+                    objectSelection.get( roleClass );
+                }
+                catch( IllegalArgumentException ex )
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/RequiresValid.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/RequiresValid.java
new file mode 100644
index 0000000..a6dba90
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/RequiresValid.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.library.rest.server.api.constraint;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+
+/**
+ * JAVADOC
+ */
+@ConstraintDeclaration
+@Retention( RetentionPolicy.RUNTIME )
+@Constraints( RequiresValid.RequiresValidConstraint.class )
+public @interface RequiresValid
+{
+    String value();
+
+    class RequiresValidConstraint
+        implements Constraint<RequiresValid, InteractionValidation>
+    {
+        @Override
+        public boolean isValid( RequiresValid requiresValid, InteractionValidation validation )
+        {
+            return validation.isValid( requiresValid.value() );
+        }
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/ServiceAvailable.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/ServiceAvailable.java
new file mode 100644
index 0000000..1bad104
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/ServiceAvailable.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.library.rest.server.api.constraint;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.library.rest.server.api.ObjectSelection;
+
+/**
+ * Annotate interaction methods with ServiceAvailable. They will only be valid
+ * if a service with the given type is available.
+ */
+@InteractionConstraintDeclaration( ServiceAvailable.ServiceAvailableConstraint.class )
+@Retention( RetentionPolicy.RUNTIME )
+public @interface ServiceAvailable
+{
+    Class value();
+
+    class ServiceAvailableConstraint
+        implements InteractionConstraint<ServiceAvailable>
+    {
+        @Structure
+        Module module;
+
+        @Override
+        public boolean isValid( ServiceAvailable serviceAvailable, ObjectSelection objectSelection )
+        {
+            ServiceReference ref = module.findService( serviceAvailable.value() );
+            return ref != null && ref.isAvailable();
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/package.html b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/package.html
new file mode 100644
index 0000000..e3aa793
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/constraint/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ReST Server Constraints.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/dci/Role.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/dci/Role.java
new file mode 100644
index 0000000..7910e49
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/dci/Role.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.library.rest.server.api.dci;
+
+/**
+ * Base class for methodful roles
+ */
+public class Role<T>
+    implements Comparable<Role<T>>
+{
+    // Self reference to the bound Data object
+    protected T self;
+
+    public Role()
+    {
+    }
+
+    public Role( T self )
+    {
+        this.self = self;
+    }
+
+    public void bind( T newSelf )
+    {
+        self = newSelf;
+    }
+
+    public T self()
+    {
+        return self;
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        return obj != null && obj instanceof Role && self.equals( ( (Role) obj ).self );
+    }
+
+    @Override
+    public int compareTo( Role<T> role )
+    {
+        return ( (Comparable<T>) self ).compareTo( role.self );
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/dci/package.html b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/dci/package.html
new file mode 100644
index 0000000..1cfe820
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/dci/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ReST Server DCI API.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/package.html b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/package.html
new file mode 100644
index 0000000..6482131
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/api/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ReST Server API.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/assembler/RestServerAssembler.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/assembler/RestServerAssembler.java
new file mode 100644
index 0000000..4c12c3c
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/assembler/RestServerAssembler.java
@@ -0,0 +1,117 @@
+/*
+ *  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.polygene.library.rest.server.assembler;
+
+import freemarker.template.Configuration;
+import freemarker.template.Version;
+import java.lang.reflect.Modifier;
+import java.util.List;
+import java.util.Properties;
+import java.util.function.Predicate;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.service.importer.NewObjectImporter;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ClassScanner;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.rest.server.restlet.InteractionConstraintsService;
+import org.apache.polygene.library.rest.server.restlet.RequestReaderDelegator;
+import org.apache.polygene.library.rest.server.restlet.ResponseWriterDelegator;
+import org.apache.polygene.library.rest.server.restlet.freemarker.ValueCompositeObjectWrapper;
+import org.apache.polygene.library.rest.server.restlet.requestreader.DefaultRequestReader;
+import org.apache.polygene.library.rest.server.restlet.responsewriter.AbstractResponseWriter;
+import org.apache.polygene.library.rest.server.restlet.responsewriter.DefaultResponseWriter;
+import org.apache.polygene.library.rest.server.spi.ResponseWriter;
+import org.restlet.service.MetadataService;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.polygene.api.util.Classes.hasModifier;
+import static org.apache.polygene.api.util.Classes.isAssignableFrom;
+import static org.apache.polygene.bootstrap.ImportedServiceDeclaration.INSTANCE;
+import static org.apache.polygene.bootstrap.ImportedServiceDeclaration.NEW_OBJECT;
+
+/**
+ * JAVADOC
+ */
+public class RestServerAssembler
+    implements Assembler
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        Properties props = new Properties();
+        try
+        {
+            props.load( getClass().getResourceAsStream( "/velocity.properties" ) );
+
+            VelocityEngine velocity = new VelocityEngine( props );
+
+            module.importedServices( VelocityEngine.class )
+                  .importedBy( INSTANCE ).setMetaInfo( velocity );
+        }
+        catch( Exception e )
+        {
+            throw new AssemblyException( "Could not load velocity properties", e );
+        }
+
+        Version freemarkerVersion = Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS;
+        Configuration cfg = new Configuration( freemarkerVersion );
+        cfg.setClassForTemplateLoading( AbstractResponseWriter.class, "" );
+        cfg.setObjectWrapper( new ValueCompositeObjectWrapper( freemarkerVersion ) );
+
+        module.importedServices( Configuration.class ).setMetaInfo( cfg );
+
+        module.importedServices( MetadataService.class );
+
+        module.importedServices( ResponseWriterDelegator.class )
+              .identifiedBy( "responsewriterdelegator" )
+              .importedBy( NEW_OBJECT )
+              .visibleIn( Visibility.layer );
+        module.objects( ResponseWriterDelegator.class );
+
+        module.importedServices( RequestReaderDelegator.class )
+              .identifiedBy( "requestreaderdelegator" )
+              .importedBy( NEW_OBJECT )
+              .visibleIn( Visibility.layer );
+        module.objects( RequestReaderDelegator.class );
+
+        module.importedServices( InteractionConstraintsService.class )
+              .importedBy( NewObjectImporter.class )
+              .visibleIn( Visibility.application );
+        module.objects( InteractionConstraintsService.class );
+
+        // Standard response writers
+        Predicate<Class<?>> isResponseWriterClass = isAssignableFrom( ResponseWriter.class );
+        Predicate<Class<?>> isNotAnAbstract = hasModifier( Modifier.ABSTRACT ).negate();
+        List<? extends Class<?>> responseWriters = ClassScanner.findClasses( DefaultResponseWriter.class )
+                                                               .filter( isNotAnAbstract.and( isResponseWriterClass ) )
+                                                               .collect( toList() );
+        for( Class<?> responseWriter : responseWriters )
+        {
+            module.objects( responseWriter );
+        }
+
+        // Standard request readers
+        module.objects( DefaultRequestReader.class );
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/assembler/package.html b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/assembler/package.html
new file mode 100644
index 0000000..8262890
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/assembler/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ReST Server Assembly.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/ConstraintViolationMessages.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/ConstraintViolationMessages.java
new file mode 100644
index 0000000..17b43d5
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/ConstraintViolationMessages.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.library.rest.server.restlet;
+
+import java.lang.annotation.Annotation;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.polygene.api.constraint.ConstraintViolation;
+
+/**
+ * TODO
+ */
+public class ConstraintViolationMessages
+{
+    public String getMessage( ConstraintViolation violation, Locale locale )
+        throws IllegalArgumentException
+    {
+        try
+        {
+            ResourceBundle bundle = ResourceBundle.getBundle( "ValidationMessages", locale );
+
+            Annotation annotation = violation.constraint();
+            String message;
+            try
+            {
+                message = (String) annotation.annotationType().getMethod( "message" ).invoke( annotation );
+            }
+            catch( Exception e1 )
+            {
+                message = "{" + annotation.annotationType().getName() + ".message" + "}";
+            }
+
+            while( message.startsWith( "{" ) )
+            {
+                message = bundle.getString( message.substring( 1, message.length() - 1 ) );
+            }
+
+            Pattern pattern = Pattern.compile( "\\{[^\\}]*\\}" );
+            String result = "";
+            Matcher matcher = pattern.matcher( message );
+            int start = 0;
+            while( matcher.find() )
+            {
+                String match = matcher.group();
+                match = match.substring( 1, match.length() - 1 );
+                result += message.substring( start, matcher.start() );
+
+                if( match.equals( "val" ) )
+                {
+                    result += violation.value() == null ? "null" : violation.value().toString();
+                }
+                else
+                {
+                    result += annotation.annotationType().getMethod( match ).invoke( annotation ).toString();
+                }
+                start = matcher.end();
+            }
+            result += message.substring( start );
+            return result;
+        }
+        catch( Exception e )
+        {
+            throw new IllegalArgumentException( "Could not deduce message", e );
+        }
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/ExtensionMediaTypeFilter.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/ExtensionMediaTypeFilter.java
new file mode 100644
index 0000000..535e06f
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/ExtensionMediaTypeFilter.java
@@ -0,0 +1,88 @@
+/*
+ *  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.polygene.library.rest.server.restlet;
+
+import java.util.Collections;
+import java.util.List;
+import org.restlet.Context;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.Restlet;
+import org.restlet.data.MediaType;
+import org.restlet.data.Metadata;
+import org.restlet.data.Preference;
+import org.restlet.routing.Filter;
+import org.restlet.service.MetadataService;
+
+/**
+ * JAVADOC
+ */
+public class ExtensionMediaTypeFilter
+    extends Filter
+{
+
+    public ExtensionMediaTypeFilter()
+    {
+    }
+
+    public ExtensionMediaTypeFilter( Context context )
+    {
+        super( context );
+    }
+
+    public ExtensionMediaTypeFilter( Context context, Restlet next )
+    {
+        super( context, next );
+    }
+
+    @Override
+    protected int beforeHandle( Request request, Response response )
+    {
+        List<String> segments = request.getResourceRef().getSegments();
+        if( segments.get( segments.size() - 1 ).equals( "" ) )
+        {
+            return Filter.CONTINUE;
+        }
+
+        String extensions = request.getResourceRef().getExtensions();
+        if( extensions != null )
+        {
+            int idx = extensions.lastIndexOf( "." );
+            if( idx != -1 )
+            {
+                extensions = extensions.substring( idx + 1 );
+            }
+
+            MetadataService metadataService = getApplication().getMetadataService();
+            Metadata metadata = metadataService.getMetadata( extensions );
+            if( metadata != null && metadata instanceof MediaType )
+            {
+                request.getClientInfo()
+                    .setAcceptedMediaTypes( Collections.singletonList( new Preference<MediaType>( (MediaType) metadata ) ) );
+                String path = request.getResourceRef().getPath();
+                path = path.substring( 0, path.length() - extensions.length() - 1 );
+                request.getResourceRef().setPath( path );
+            }
+        }
+
+        return Filter.CONTINUE;
+    }
+}
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/InteractionConstraints.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/InteractionConstraints.java
new file mode 100644
index 0000000..7da41ed
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/InteractionConstraints.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.rest.server.restlet;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.library.rest.server.api.ObjectSelection;
+
+/**
+ * Service interface for checking whether a particular method or a whole class is not
+ * valid at this point, for whatever reason (application state or authorization rules usually).
+ */
+public interface InteractionConstraints
+{
+    boolean isValid( Method method, ObjectSelection objectSelection, Module module );
+
+    boolean isValid( Class resourceClass, ObjectSelection objectSelection, Module module );
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/InteractionConstraintsService.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/InteractionConstraintsService.java
new file mode 100644
index 0000000..b04edef
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/InteractionConstraintsService.java
@@ -0,0 +1,362 @@
+/*
+ *  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.polygene.library.rest.server.restlet;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.object.NoSuchObjectException;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.library.rest.server.api.ObjectSelection;
+import org.apache.polygene.library.rest.server.api.constraint.InteractionConstraint;
+import org.apache.polygene.library.rest.server.api.constraint.InteractionConstraintDeclaration;
+import org.apache.polygene.library.rest.server.api.constraint.InteractionValidation;
+import org.apache.polygene.library.rest.server.api.constraint.RequiresValid;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * JAVADOC
+ */
+public class InteractionConstraintsService
+    implements InteractionConstraints
+{
+    @Structure
+    Module module;
+
+    Logger logger = LoggerFactory.getLogger( InteractionConstraintsService.class );
+
+    private Map<Method, InteractionConstraintsBinding> methodsConstraints = new ConcurrentHashMap<>();
+    private Map<Class, InteractionConstraintsBinding> classConstraints = new ConcurrentHashMap<>();
+
+    @Override
+    public boolean isValid( Method method, ObjectSelection objectSelection, Module module )
+    {
+        return getConstraints( method, module ).isValid( objectSelection );
+    }
+
+    @Override
+    public boolean isValid( Class resourceClass, ObjectSelection objectSelection, Module module )
+    {
+        return getConstraints( resourceClass, module ).isValid( objectSelection );
+    }
+
+    private InteractionConstraintsBinding getConstraints( Method method, Module module )
+    {
+        InteractionConstraintsBinding constraintBindings = methodsConstraints.get( method );
+        if( constraintBindings == null )
+        {
+            constraintBindings = findConstraints( method, module );
+            methodsConstraints.put( method, constraintBindings );
+        }
+        return constraintBindings;
+    }
+
+    private InteractionConstraintsBinding getConstraints( Class aClass, Module module )
+    {
+        InteractionConstraintsBinding constraintBindings = classConstraints.get( aClass );
+        if( constraintBindings == null )
+        {
+            constraintBindings = findConstraints( aClass, module );
+            classConstraints.put( aClass, constraintBindings );
+        }
+        return constraintBindings;
+    }
+
+    private InteractionConstraintsBinding findConstraints( Method method, Module module )
+    {
+        List<Binding> methodConstraintBindings = new ArrayList<Binding>();
+
+        for( Annotation annotation : method.getAnnotations() )
+        {
+            if( annotation.annotationType().equals( RequiresValid.class ) )
+            {
+                RequiresValid requiresValid = (RequiresValid) annotation;
+
+                Class contextClass = method.getDeclaringClass();
+                if( InteractionValidation.class.isAssignableFrom( contextClass ) )
+                {
+                    InteractionValidation validation = null;
+                    if( TransientComposite.class.isAssignableFrom( contextClass ) )
+                    {
+                        validation = (InteractionValidation) module.newTransient( contextClass );
+                    }
+                    else
+                    {
+                        validation = (InteractionValidation) module.newObject( contextClass );
+                    }
+                    methodConstraintBindings.add( new RequiresValidBinding( requiresValid, validation ) );
+                }
+            }
+            else if( annotation.annotationType().getAnnotation( ConstraintDeclaration.class ) != null )
+            {
+                Constraints constraints = annotation.annotationType().getAnnotation( Constraints.class );
+
+                for( Class<? extends Constraint<?, ?>> aClass : constraints.value() )
+                {
+                    try
+                    {
+                        Constraint<Annotation, Object> constraint = (Constraint<Annotation, Object>) aClass.newInstance();
+                        Class roleClass = (Class) ( (ParameterizedType) aClass.getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[ 1 ];
+                        ConstraintBinding constraintBinding = new ConstraintBinding( constraint, annotation, roleClass );
+                        methodConstraintBindings.add( constraintBinding );
+                    }
+                    catch( InstantiationException e )
+                    {
+                        e.printStackTrace();
+                    }
+                    catch( IllegalAccessException e )
+                    {
+                        e.printStackTrace();
+                    }
+                }
+            }
+            else if( annotation.annotationType().getAnnotation( InteractionConstraintDeclaration.class ) != null )
+            {
+                Class<? extends InteractionConstraint> constraintClass = annotation.annotationType()
+                    .getAnnotation( InteractionConstraintDeclaration.class )
+                    .value();
+                InteractionConstraint<Annotation> constraint = null;
+                try
+                {
+                    try
+                    {
+                        constraint = module.newObject( constraintClass );
+                    }
+                    catch( NoSuchObjectException e )
+                    {
+                        constraint = constraintClass.newInstance();
+                    }
+                }
+                catch( Exception e )
+                {
+                    continue; // Skip this constraint
+                }
+                InteractionConstraintBinding constraintBinding = new InteractionConstraintBinding( constraint, annotation );
+                methodConstraintBindings.add( constraintBinding );
+            }
+        }
+
+        if( methodConstraintBindings.isEmpty() )
+        {
+            methodConstraintBindings = null;
+        }
+
+        return new InteractionConstraintsBinding( methodConstraintBindings );
+    }
+
+    private InteractionConstraintsBinding findConstraints( Class aClass, Module module )
+    {
+        List<Binding> classConstraintBindings = new ArrayList<Binding>();
+
+        for( Annotation annotation : aClass.getAnnotations() )
+        {
+            if( annotation.annotationType().getAnnotation( ConstraintDeclaration.class ) != null )
+            {
+                Constraints constraints = annotation.annotationType().getAnnotation( Constraints.class );
+
+                for( Class<? extends Constraint<?, ?>> constraintClass : constraints.value() )
+                {
+                    try
+                    {
+                        Constraint<Annotation, Object> constraint = (Constraint<Annotation, Object>) constraintClass.newInstance();
+                        Class roleClass = (Class) ( (ParameterizedType) constraint.getClass()
+                            .getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[ 1 ];
+                        ConstraintBinding constraintBinding = new ConstraintBinding( constraint, annotation, roleClass );
+                        classConstraintBindings.add( constraintBinding );
+                    }
+                    catch( InstantiationException e )
+                    {
+                        e.printStackTrace();
+                    }
+                    catch( IllegalAccessException e )
+                    {
+                        e.printStackTrace();
+                    }
+                }
+            }
+            else if( annotation.annotationType().getAnnotation( InteractionConstraintDeclaration.class ) != null )
+            {
+                Class<? extends InteractionConstraint> constraintClass = annotation.annotationType()
+                    .getAnnotation( InteractionConstraintDeclaration.class )
+                    .value();
+                InteractionConstraint<Annotation> constraint = null;
+                try
+                {
+                    try
+                    {
+                        constraint = module.newObject( constraintClass );
+                    }
+                    catch( NoSuchObjectException e )
+                    {
+                        constraint = constraintClass.newInstance();
+                    }
+                }
+                catch( Exception e )
+                {
+                    continue; // Skip this constraint
+                }
+                InteractionConstraintBinding constraintBinding = new InteractionConstraintBinding( constraint, annotation );
+                classConstraintBindings.add( constraintBinding );
+            }
+        }
+
+        if( classConstraintBindings.isEmpty() )
+        {
+            classConstraintBindings = null;
+        }
+
+        return new InteractionConstraintsBinding( classConstraintBindings );
+    }
+
+    interface Binding
+    {
+        boolean isValid( ObjectSelection objectSelection );
+    }
+
+    public static class InteractionConstraintsBinding
+    {
+        List<Binding> bindings;
+
+        public InteractionConstraintsBinding( List<Binding> bindings )
+        {
+            this.bindings = bindings;
+        }
+
+        public boolean isValid( ObjectSelection objectSelection )
+        {
+            if( bindings != null )
+            {
+                for( Binding constraintBinding : bindings )
+                {
+                    if( !constraintBinding.isValid( objectSelection ) )
+                    {
+                        return false;
+                    }
+                }
+            }
+
+            return true;
+        }
+    }
+
+    public class RequiresValidBinding
+        implements Binding
+    {
+        RequiresValid annotation;
+        private final InteractionValidation validation;
+
+        public RequiresValidBinding( RequiresValid annotation, InteractionValidation validation )
+        {
+            this.validation = validation;
+            this.annotation = annotation;
+        }
+
+        @Override
+        public boolean isValid( ObjectSelection objectSelection )
+        {
+            try
+            {
+                return validation.isValid( annotation.value() );
+            }
+            catch( IllegalArgumentException e )
+            {
+                return false;
+            }
+            catch( Throwable e )
+            {
+                logger.warn( "Could not check validation constraint for '" + annotation.value() + "'", e );
+                return false;
+            }
+        }
+    }
+
+    public class ConstraintBinding
+        implements Binding
+    {
+        Constraint<Annotation, Object> constraint;
+        Annotation annotation;
+        Class roleClass;
+
+        public ConstraintBinding( Constraint<Annotation, Object> constraint, Annotation annotation, Class roleClass )
+        {
+            this.constraint = constraint;
+            this.annotation = annotation;
+            this.roleClass = roleClass;
+        }
+
+        @Override
+        public boolean isValid( ObjectSelection objectSelection )
+        {
+            try
+            {
+                Object checkedObject = roleClass.equals( ObjectSelection.class ) ? objectSelection : objectSelection.get( roleClass );
+
+                return constraint.isValid( annotation, checkedObject );
+            }
+            catch( IllegalArgumentException e )
+            {
+                return false;
+            }
+            catch( Throwable e )
+            {
+                logger.warn( "Could not check constraint " + constraint.getClass().getName(), e );
+                return false;
+            }
+        }
+    }
+
+    public class InteractionConstraintBinding
+        implements Binding
+    {
+        InteractionConstraint<Annotation> constraint;
+        Annotation annotation;
+
+        public InteractionConstraintBinding( InteractionConstraint<Annotation> constraint, Annotation annotation )
+        {
+            this.constraint = constraint;
+            this.annotation = annotation;
+        }
+
+        @Override
+        public boolean isValid( ObjectSelection objectSelection )
+        {
+            try
+            {
+                return constraint.isValid( annotation, objectSelection );
+            }
+            catch( Throwable e )
+            {
+                logger.warn( "Could not check constraint " + constraint.getClass().getName(), e );
+                return false;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/NullCommandResult.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/NullCommandResult.java
new file mode 100644
index 0000000..493aeb4
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/NullCommandResult.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.rest.server.restlet;
+
+import org.apache.polygene.library.rest.server.spi.CommandResult;
+
+/**
+ * The command has no result at all (ignore it).
+ */
+public class NullCommandResult
+    implements CommandResult
+{
+    @Override
+    public Object getResult()
+    {
+        return null;
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/RequestReaderDelegator.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/RequestReaderDelegator.java
new file mode 100644
index 0000000..db767ff
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/RequestReaderDelegator.java
@@ -0,0 +1,111 @@
+/*
+ *  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.polygene.library.rest.server.restlet;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ResourceBundle;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.library.rest.server.spi.RequestReader;
+import org.restlet.Request;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Delegates to a list of potential readers. Register readers on startup.
+ */
+public class RequestReaderDelegator
+    implements RequestReader
+{
+    private static final Object[] NULL_PARAMS = new Object[ 0 ];
+
+    List<RequestReader> requestReaders = new ArrayList<>();
+
+    @Structure
+    Module module;
+
+    public void init( @Service Iterable<ServiceReference<RequestReader>> requestReaderReferences )
+    {
+        Logger logger = LoggerFactory.getLogger( getClass() );
+        Identity requestreaderdelegator = new StringIdentity("requestreaderdelegator");
+
+        // Add custom readers first
+        for( ServiceReference<RequestReader> requestReader : requestReaderReferences )
+        {
+            if( !requestReader.identity().equals(requestreaderdelegator) )
+            {
+                logger.info( "Registered request reader:" + requestReader.identity() );
+                registerRequestReader( requestReader.get() );
+            }
+        }
+
+        // Add defaults
+        ResourceBundle defaultRequestReaders = ResourceBundle.getBundle( "org.apache.polygene.library.rest.server.rest-server" );
+
+        String requestReaderClasses = defaultRequestReaders.getString( "requestreaders" );
+        logger.info( "Using request readers:" + requestReaderClasses );
+        for( String className : requestReaderClasses.split( "," ) )
+        {
+            try
+            {
+                Class readerClass = module.descriptor().classLoader().loadClass( className.trim() );
+                RequestReader writer = (RequestReader) module.newObject( readerClass );
+                registerRequestReader( writer );
+            }
+            catch( ClassNotFoundException e )
+            {
+                logger.warn( "Could not register request reader " + className, e );
+            }
+        }
+    }
+
+    public void registerRequestReader( RequestReader reader )
+    {
+        requestReaders.add( reader );
+    }
+
+    @Override
+    public Object[] readRequest( Request request, Method method )
+    {
+        if( method.getParameterTypes().length == 0 )
+        {
+            return NULL_PARAMS;
+        }
+
+        for( RequestReader requestReader : requestReaders )
+        {
+            Object[] arguments = requestReader.readRequest( request, method );
+
+            if( arguments != null )
+            {
+                return arguments;
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/ResponseWriterDelegator.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/ResponseWriterDelegator.java
new file mode 100644
index 0000000..18fd7fa
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/ResponseWriterDelegator.java
@@ -0,0 +1,100 @@
+/*
+ *  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.polygene.library.rest.server.restlet;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ResourceBundle;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.library.rest.server.spi.ResponseWriter;
+import org.restlet.Response;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Delegates to a list of potential writers. Register writers on startup.
+ */
+public class ResponseWriterDelegator
+    implements ResponseWriter
+{
+    List<ResponseWriter> responseWriters = new ArrayList<>();
+
+    @Structure
+    Module module;
+
+    public void init( @Service Iterable<ServiceReference<ResponseWriter>> resultWriters )
+    {
+        Logger logger = LoggerFactory.getLogger( getClass() );
+        Identity responsewriterdelegator = new StringIdentity( "responsewriterdelegator" );
+
+        // Add custom writers first
+        for( ServiceReference<ResponseWriter> resultWriter : resultWriters )
+        {
+            if( !resultWriter.identity().equals(responsewriterdelegator) )
+            {
+                logger.info( "Registered result writer:" + resultWriter.identity() );
+                registerResultWriter( resultWriter.get() );
+            }
+        }
+
+        // Add defaults
+        ResourceBundle defaultResultWriters = ResourceBundle.getBundle( "org.apache.polygene.library.rest.server.rest-server" );
+
+        String resultWriterClasses = defaultResultWriters.getString( "responsewriters" );
+        logger.info( "Using response writers:" + resultWriterClasses );
+        for( String className : resultWriterClasses.split( "," ) )
+        {
+            try
+            {
+                Class writerClass = module.descriptor().classLoader().loadClass( className.trim() );
+                ResponseWriter writer = (ResponseWriter) module.newObject( writerClass );
+                registerResultWriter( writer );
+            }
+            catch( ClassNotFoundException e )
+            {
+                logger.warn( "Could not register response writer " + className, e );
+            }
+        }
+    }
+
+    public void registerResultWriter( ResponseWriter writer )
+    {
+        responseWriters.add( writer );
+    }
+
+    @Override
+    public boolean writeResponse( Object result, Response response )
+    {
+        for( ResponseWriter responseWriter : responseWriters )
+        {
+            if( responseWriter.writeResponse( result, response ) )
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/freemarker/ValueCompositeObjectWrapper.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/freemarker/ValueCompositeObjectWrapper.java
new file mode 100644
index 0000000..a878e43
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/freemarker/ValueCompositeObjectWrapper.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.polygene.library.rest.server.restlet.freemarker;
+
+import freemarker.template.DefaultObjectWrapper;
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+import freemarker.template.Version;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * ObjectWrapper implementation that adds support for ValueComposites, exposing Property state.
+ */
+public class ValueCompositeObjectWrapper
+    extends DefaultObjectWrapper
+{
+    public ValueCompositeObjectWrapper( Version freemarkerVersion )
+    {
+        super( freemarkerVersion );
+    }
+
+    @Override
+    public TemplateModel wrap( Object obj )
+        throws TemplateModelException
+    {
+        if( obj instanceof ValueComposite )
+        {
+            return new ValueCompositeTemplateModel( (ValueComposite) obj, this );
+        }
+        else
+        {
+            return super.wrap( obj );
+        }
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/freemarker/ValueCompositeTemplateModel.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/freemarker/ValueCompositeTemplateModel.java
new file mode 100644
index 0000000..985fd8a
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/freemarker/ValueCompositeTemplateModel.java
@@ -0,0 +1,122 @@
+/*
+ *  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.polygene.library.rest.server.restlet.freemarker;
+
+import freemarker.template.ObjectWrapper;
+import freemarker.template.TemplateCollectionModel;
+import freemarker.template.TemplateHashModelEx;
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateScalarModel;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.api.value.ValueDescriptor;
+
+/**
+ * TODO
+ */
+public class ValueCompositeTemplateModel
+    implements TemplateHashModelEx, TemplateScalarModel
+{
+    private ValueComposite composite;
+    private ObjectWrapper wrapper;
+    private ValueDescriptor descriptor;
+
+    public ValueCompositeTemplateModel( ValueComposite composite, ObjectWrapper wrapper )
+    {
+        this.composite = composite;
+        this.wrapper = wrapper;
+        descriptor = (ValueDescriptor) PolygeneAPI.FUNCTION_DESCRIPTOR_FOR.apply( composite );
+    }
+
+    @Override
+    public int size()
+        throws TemplateModelException
+    {
+        return (int) descriptor.state().properties().count();
+    }
+
+    @Override
+    public TemplateCollectionModel keys()
+        throws TemplateModelException
+    {
+        List<String> names = descriptor.state().properties()
+            .map( descriptor -> descriptor.qualifiedName().name() )
+            .collect( Collectors.toList() );
+        return (TemplateCollectionModel) wrapper.wrap( names.iterator() );
+    }
+
+    @Override
+    public TemplateCollectionModel values()
+        throws TemplateModelException
+    {
+        List<Object> values = PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF.apply( composite )
+            .state().properties()
+            .map( (Function<Property<?>, Object>) objectProperty -> {
+                try
+                {
+                    return wrapper.wrap( objectProperty.get() );
+                }
+                catch( TemplateModelException e )
+                {
+                    throw new IllegalStateException( e );
+                }
+            } )
+            .collect( Collectors.toList() );
+
+        return (TemplateCollectionModel) wrapper.wrap( values );
+    }
+
+    @Override
+    public TemplateModel get( String key )
+        throws TemplateModelException
+    {
+        try
+        {
+            return wrapper.wrap( PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF
+                                     .apply( composite )
+                                     .state()
+                                     .propertyFor( descriptor.state().findPropertyModelByName( key ).accessor() )
+                                     .get() );
+        }
+        catch( IllegalArgumentException e )
+        {
+            return null;
+        }
+    }
+
+    @Override
+    public boolean isEmpty()
+        throws TemplateModelException
+    {
+        return size() == 0;
+    }
+
+    @Override
+    public String getAsString()
+        throws TemplateModelException
+    {
+        return composite.toString();
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/freemarker/package.html b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/freemarker/package.html
new file mode 100644
index 0000000..534285d
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/freemarker/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Restlet ReST Server FreeMarker Templating.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/package.html b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/package.html
new file mode 100644
index 0000000..e1a1b53
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Restlet ReST Server.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/requestreader/DefaultRequestReader.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/requestreader/DefaultRequestReader.java
new file mode 100644
index 0000000..b968da4
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/requestreader/DefaultRequestReader.java
@@ -0,0 +1,509 @@
+/*
+ *  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.polygene.library.rest.server.restlet.requestreader;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.Period;
+import java.time.ZonedDateTime;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.constraint.Name;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.library.rest.server.spi.RequestReader;
+import org.apache.polygene.spi.serialization.JsonDeserializer;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.data.CharacterSet;
+import org.restlet.data.Form;
+import org.restlet.data.MediaType;
+import org.restlet.data.Parameter;
+import org.restlet.data.Status;
+import org.restlet.representation.EmptyRepresentation;
+import org.restlet.representation.Representation;
+import org.restlet.resource.ResourceException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.polygene.api.util.Annotations.isType;
+
+/**
+ * Convert request into method arguments.
+ *
+ * TODO: This should be split into many classes to handle the different cases.
+ * TODO: This does not support ManyAssociations
+ * TODO: This does not support NamedAssociations
+ */
+public class DefaultRequestReader
+    implements RequestReader
+{
+    private static final Logger LOGGER = LoggerFactory.getLogger( DefaultRequestReader.class );
+    @Structure
+    private UnitOfWorkFactory uowf;
+
+    @Structure
+    private ModuleDescriptor module;
+
+    @Structure
+    private ValueBuilderFactory vbf;
+
+    @Service
+    private JsonDeserializer deserializer;
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public Object[] readRequest( Request request, Method method )
+        throws ResourceException
+    {
+        if( request.getMethod().equals( org.restlet.data.Method.GET ) )
+        {
+            Object[] args = new Object[ method.getParameterTypes().length ];
+
+            Form queryAsForm = Request.getCurrent().getResourceRef().getQueryAsForm();
+            Form entityAsForm;
+            Representation representation = Request.getCurrent().getEntity();
+            if( representation != null && !EmptyRepresentation.class.isInstance( representation ) )
+            {
+                entityAsForm = new Form( representation );
+            }
+            else
+            {
+                entityAsForm = new Form();
+            }
+
+            if( queryAsForm.isEmpty() && entityAsForm.isEmpty() )
+            {
+                // Nothing submitted yet - show form
+                return null;
+            }
+
+            if( args.length == 1 )
+            {
+                if( ValueComposite.class.isAssignableFrom( method.getParameterTypes()[0] ) )
+                {
+                    Class<?> valueType = method.getParameterTypes()[0];
+                    args[0] = getValueFromForm( (Class<ValueComposite>) valueType, queryAsForm, entityAsForm );
+                    return args;
+                }
+                else if( Form.class.equals( method.getParameterTypes()[0] ) )
+                {
+                    args[0] = queryAsForm.isEmpty() ? entityAsForm : queryAsForm;
+                    return args;
+                }
+                else if( Response.class.equals( method.getParameterTypes()[0] ) )
+                {
+                    args[0] = Response.getCurrent();
+                    return args;
+                }
+            }
+            parseMethodArguments( method, args, queryAsForm, entityAsForm );
+
+            return args;
+        }
+        else
+        {
+
+            Object[] args = new Object[ method.getParameterTypes().length ];
+            Class<? extends ValueComposite> commandType = (Class<? extends ValueComposite>) method.getParameterTypes()[0];
+            if( method.getParameterTypes()[0].equals( Response.class ) )
+            {
+                return new Object[]
+                {
+                    Response.getCurrent()
+                };
+            }
+            Representation representation = Request.getCurrent().getEntity();
+            MediaType type = representation.getMediaType();
+            if( type == null )
+            {
+                Form queryAsForm = Request.getCurrent().getResourceRef().getQueryAsForm( CharacterSet.UTF_8 );
+                if( ValueComposite.class.isAssignableFrom( method.getParameterTypes()[0] ) )
+                {
+                    args[0] = getValueFromForm( commandType, queryAsForm, new Form() );
+                }
+                else
+                {
+                    parseMethodArguments( method, args, queryAsForm, new Form() );
+                }
+                return args;
+            }
+            else
+            {
+                if( method.getParameterTypes()[0].equals( Representation.class ) )
+                {
+                    // Command method takes Representation as input
+                    return new Object[]
+                    {
+                        representation
+                    };
+                }
+                else if( method.getParameterTypes()[0].equals( Form.class ) )
+                {
+                    // Command method takes Form as input
+                    return new Object[]
+                    {
+                        new Form( representation )
+                    };
+                }
+                else if( ValueComposite.class.isAssignableFrom( method.getParameterTypes()[0] ) )
+                {
+                    // Need to parse input into ValueComposite
+                    if( type.equals( MediaType.APPLICATION_JSON ) )
+                    {
+                        String json = Request.getCurrent().getEntityAsText();
+                        if( json == null )
+                        {
+                            LOGGER.error( "Restlet bug http://restlet.tigris.org/issues/show_bug.cgi?id=843 detected. "
+                                          + "Notify developers!" );
+                            throw new ResourceException( Status.SERVER_ERROR_INTERNAL,
+                                                         "Bug in Restlet encountered; notify developers!" );
+                        }
+
+                        Object command = vbf.newValueFromSerializedState( commandType, json );
+                        args[0] = command;
+                        return args;
+                    }
+                    else if( type.equals( MediaType.TEXT_PLAIN ) )
+                    {
+                        String text = Request.getCurrent().getEntityAsText();
+                        if( text == null )
+                        {
+                            LOGGER.error( "Restlet bug http://restlet.tigris.org/issues/show_bug.cgi?id=843 detected. "
+                                          + "Notify developers!" );
+                            throw new ResourceException( Status.SERVER_ERROR_INTERNAL,
+                                                         "Bug in Restlet encountered; notify developers!" );
+                        }
+                        args[0] = text;
+                        return args;
+                    }
+                    else if( type.equals( ( MediaType.APPLICATION_WWW_FORM ) ) )
+                    {
+
+                        Form queryAsForm = Request.getCurrent().getResourceRef().getQueryAsForm();
+                        Form entityAsForm;
+                        if( !EmptyRepresentation.class.isInstance( representation )
+                            && representation.isAvailable() )
+                        {
+                            entityAsForm = new Form( representation );
+                        }
+                        else
+                        {
+                            entityAsForm = new Form();
+                        }
+
+                        Class<?> valueType = method.getParameterTypes()[0];
+                        args[0] = getValueFromForm( (Class<ValueComposite>) valueType, queryAsForm, entityAsForm );
+                        return args;
+                    }
+                    else
+                    {
+                        throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST,
+                                                     "Command has to be in JSON format" );
+                    }
+                }
+                else if( method.getParameterTypes()[0].isInterface() && method.getParameterTypes().length == 1 )
+                {
+                    Form queryAsForm = Request.getCurrent().getResourceRef().getQueryAsForm();
+                    Form entityAsForm;
+                    if( !EmptyRepresentation.class.isInstance( representation )
+                        && representation.isAvailable() )
+                    {
+                        entityAsForm = new Form( representation );
+                    }
+                    else
+                    {
+                        entityAsForm = new Form();
+                    }
+
+                    Identity entityIdentity = new StringIdentity( getValue( "entity", queryAsForm, entityAsForm ) );
+                    args[0] = uowf.currentUnitOfWork().get( method.getParameterTypes()[0], entityIdentity );
+
+                    return args;
+                }
+                else
+                {
+                    Form queryAsForm = Request.getCurrent().getResourceRef().getQueryAsForm();
+                    Form entityAsForm;
+                    if( !EmptyRepresentation.class.isInstance( representation )
+                        && representation.isAvailable() )
+                    {
+                        entityAsForm = new Form( representation );
+                    }
+                    else
+                    {
+                        entityAsForm = new Form();
+                    }
+
+                    parseMethodArguments( method, args, queryAsForm, entityAsForm );
+
+                    return args;
+                }
+            }
+        }
+    }
+
+    private ValueComposite getValueFromForm( Class<? extends ValueComposite> valueType,
+                                             final Form queryAsForm,
+                                             final Form entityAsForm
+    )
+    {
+        ValueBuilder<? extends ValueComposite> builder = vbf.newValueBuilderWithState(
+            valueType,
+            (Function<PropertyDescriptor, Object>) propertyDescriptor -> {
+                Parameter param = queryAsForm.getFirst( propertyDescriptor.qualifiedName().name() );
+
+                if( param == null )
+                {
+                    param = entityAsForm.getFirst( propertyDescriptor.qualifiedName().name() );
+                }
+
+                if( param != null )
+                {
+                    String value = param.getValue();
+                    if( value != null )
+                    {
+                        try
+                        {
+                            return deserializer.deserialize( module, propertyDescriptor.valueType(), value );
+                        }
+                        catch( SerializationException e )
+                        {
+                            throw new IllegalArgumentException( "Query parameter has invalid JSON format", e );
+                        }
+                    }
+                }
+
+                return null;
+            },
+            (Function<AssociationDescriptor, EntityReference>) associationDescriptor -> {
+                Parameter param = queryAsForm.getFirst( associationDescriptor.qualifiedName().name() );
+
+                if( param == null )
+                {
+                    param = entityAsForm.getFirst( associationDescriptor.qualifiedName().name() );
+                }
+
+                if( param != null )
+                {
+                    return EntityReference.parseEntityReference( param.getValue() );
+                }
+                else
+                {
+                    return null;
+                }
+            },
+            (Function<AssociationDescriptor, Stream<EntityReference>>) associationDescriptor -> {
+                // TODO
+                return Stream.empty();
+            },
+            (Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>>) associationDescriptor ->
+            {
+                // TODO
+                return Stream.empty();
+            }
+        );
+
+        return builder.newInstance();
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private void parseMethodArguments( Method method, Object[] args, Form queryAsForm, Form entityAsForm )
+    {
+        // Parse each argument separately using the @Name annotation as help
+        int idx = 0;
+        for( Annotation[] annotations : method.getParameterAnnotations() )
+        {
+            Name name = (Name) Stream.of( annotations ).filter( isType( Name.class ) )
+                                     .findFirst().orElse( null );
+            if( name == null )
+            {
+                throw new IllegalStateException( "No @Name annotation found on parameter of method:" + method );
+            }
+
+            String argString = getValue( name.value(), queryAsForm, entityAsForm );
+
+            // Parameter conversion
+            Class<?> parameterType = method.getParameterTypes()[idx];
+            Object arg = null;
+            if( parameterType.equals( String.class ) )
+            {
+                arg = argString;
+            }
+            else if( parameterType.equals( EntityReference.class ) )
+            {
+                arg = EntityReference.parseEntityReference( argString );
+            }
+            else if( parameterType.isEnum() )
+            {
+                arg = Enum.valueOf( (Class<Enum>) parameterType, argString );
+            }
+            else if( Integer.TYPE.isAssignableFrom( parameterType ) )
+            {
+                arg = Integer.valueOf( argString );
+            }
+            else if( Integer.class.isAssignableFrom( parameterType ) )
+            {
+                if( argString != null )
+                {
+                    arg = Integer.valueOf( argString );
+                }
+            }
+            else if( Long.TYPE.isAssignableFrom( parameterType ) )
+            {
+                arg = Long.valueOf( argString );
+            }
+            else if( Long.class.isAssignableFrom( parameterType ) )
+            {
+                if( argString != null )
+                {
+                    arg = Long.valueOf( argString );
+                }
+            }
+            else if( Short.TYPE.isAssignableFrom( parameterType ) )
+            {
+                arg = Short.valueOf( argString );
+            }
+            else if( Short.class.isAssignableFrom( parameterType ) )
+            {
+                if( argString != null )
+                {
+                    arg = Short.valueOf( argString );
+                }
+            }
+            else if( Double.TYPE.isAssignableFrom( parameterType ) )
+            {
+                arg = Double.valueOf( argString );
+            }
+            else if( Double.class.isAssignableFrom( parameterType ) )
+            {
+                if( argString != null )
+                {
+                    arg = Double.valueOf( argString );
+                }
+            }
+            else if( Float.TYPE.isAssignableFrom( parameterType ) )
+            {
+                arg = Float.valueOf( argString );
+            }
+            else if( Float.class.isAssignableFrom( parameterType ) )
+            {
+                if( argString != null )
+                {
+                    arg = Float.valueOf( argString );
+                }
+            }
+            else if( Character.TYPE.isAssignableFrom( parameterType ) )
+            {
+                arg = argString.charAt( 0 );
+            }
+            else if( Character.class.isAssignableFrom( parameterType ) )
+            {
+                if( argString != null )
+                {
+                    arg = argString.charAt( 0 );
+                }
+            }
+            else if( Boolean.TYPE.isAssignableFrom( parameterType ) )
+            {
+                arg = Boolean.valueOf( argString );
+            }
+            else if( Boolean.class.isAssignableFrom( parameterType ) )
+            {
+                if( argString != null )
+                {
+                    arg = Boolean.valueOf( argString );
+                }
+            }
+            else if( LocalDate.class.isAssignableFrom( parameterType ) )
+            {
+                arg = LocalDate.parse( argString );
+            }
+            else if( LocalDateTime.class.isAssignableFrom( parameterType ) )
+            {
+                arg = LocalDateTime.parse( argString );
+            }
+            else if( ZonedDateTime.class.isAssignableFrom( parameterType ) )
+            {
+                arg = ZonedDateTime.parse( argString );
+            }
+            else if( OffsetDateTime.class.isAssignableFrom( parameterType ) )
+            {
+                arg = OffsetDateTime.parse( argString );
+            }
+            else if( Instant.class.isAssignableFrom( parameterType ) )
+            {
+                arg = Instant.parse( argString );
+            }
+            else if( Duration.class.isAssignableFrom( parameterType ) )
+            {
+                arg = Duration.parse( argString );
+            }
+            else if( Period.class.isAssignableFrom( parameterType ) )
+            {
+                arg = Period.parse( argString );
+            }
+            else if( parameterType.isInterface() )
+            {
+                arg = uowf.currentUnitOfWork().get( parameterType, new StringIdentity( argString ) );
+            }
+            else
+            {
+                throw new IllegalArgumentException( "Don't know how to parse parameter " + name.value()
+                                                    + " of type " + parameterType.getName() );
+            }
+
+            if( arg == null && Stream.of( annotations ).noneMatch( isType( Optional.class ) ) )
+            {
+                throw new IllegalArgumentException( "Parameter " + name.value() + " was not set" );
+            }
+
+            args[idx++] = arg;
+        }
+    }
+
+    private String getValue( String name, Form queryAsForm, Form entityAsForm )
+    {
+        String value = queryAsForm.getFirstValue( name );
+        if( value == null )
+        {
+            value = entityAsForm.getFirstValue( name );
+        }
+        return value;
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/requestreader/package.html b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/requestreader/package.html
new file mode 100644
index 0000000..e94f461
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/requestreader/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Restlet ReST Server Request Readers.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/AbstractResponseWriter.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/AbstractResponseWriter.java
new file mode 100644
index 0000000..358d81d
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/AbstractResponseWriter.java
@@ -0,0 +1,65 @@
+/*
+ *  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.polygene.library.rest.server.restlet.responsewriter;
+
+import java.util.Collections;
+import java.util.List;
+import org.apache.polygene.library.rest.server.spi.ResponseWriter;
+import org.restlet.Request;
+import org.restlet.data.CharacterSet;
+import org.restlet.data.Language;
+import org.restlet.data.MediaType;
+import org.restlet.representation.Variant;
+
+/**
+ * Helper methods for ResponseWriters
+ */
+public abstract class AbstractResponseWriter
+    implements ResponseWriter
+{
+    protected static List<Language> ENGLISH = Collections.singletonList( Language.ENGLISH );
+
+    protected Variant getVariant( Request request,
+                                  List<Language> possibleLanguages,
+                                  List<MediaType> possibleMediaTypes
+    )
+    {
+        Language language = request.getClientInfo().getPreferredLanguage( possibleLanguages );
+
+        if( language == null )
+        {
+            language = possibleLanguages.get( 0 );
+        }
+
+        MediaType responseType = request.getClientInfo().getPreferredMediaType( possibleMediaTypes );
+
+        if( responseType == null && request.getClientInfo()
+                                        .getPreferredMediaType( Collections.singletonList( MediaType.ALL ) ) == MediaType.ALL )
+        {
+            responseType = possibleMediaTypes.get( 0 );
+        }
+
+        Variant variant = new Variant( responseType, language );
+        variant.setCharacterSet( CharacterSet.UTF_8 );
+
+        return variant;
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/DefaultResponseWriter.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/DefaultResponseWriter.java
new file mode 100644
index 0000000..1091612
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/DefaultResponseWriter.java
@@ -0,0 +1,58 @@
+/*
+ *  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.polygene.library.rest.server.restlet.responsewriter;
+
+import java.util.Collections;
+import java.util.List;
+import org.restlet.Response;
+import org.restlet.data.MediaType;
+import org.restlet.representation.StringRepresentation;
+import org.restlet.resource.ResourceException;
+
+/**
+ * Handles simple types and serialize to JSON
+ */
+public class DefaultResponseWriter
+    extends AbstractResponseWriter
+{
+    private static final List<MediaType> supportedMediaTypes = Collections.singletonList( MediaType.APPLICATION_JSON );
+
+    @Override
+    public boolean writeResponse( final Object result, final Response response )
+        throws ResourceException
+    {
+        MediaType type = getVariant( response.getRequest(), ENGLISH, supportedMediaTypes ).getMediaType();
+        if( MediaType.APPLICATION_JSON.equals( type ) )
+        {
+            if( result instanceof String || result instanceof Number || result instanceof Boolean )
+            {
+                StringRepresentation representation = new StringRepresentation( result.toString(),
+                                                                                MediaType.APPLICATION_JSON );
+
+                response.setEntity( representation );
+
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/FormResponseWriter.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/FormResponseWriter.java
new file mode 100644
index 0000000..9535e43
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/FormResponseWriter.java
@@ -0,0 +1,127 @@
+/*
+ *  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.polygene.library.rest.server.restlet.responsewriter;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.json.JsonException;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonValue;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.restlet.Response;
+import org.restlet.data.Form;
+import org.restlet.data.MediaType;
+import org.restlet.data.Parameter;
+import org.restlet.representation.Representation;
+import org.restlet.representation.StringRepresentation;
+import org.restlet.representation.WriterRepresentation;
+import org.restlet.resource.ResourceException;
+
+/**
+ * Handles Restlet Form
+ */
+public class FormResponseWriter
+    extends AbstractResponseWriter
+{
+    private static final List<MediaType> supportedMediaTypes = Arrays.asList( MediaType.TEXT_HTML,
+                                                                              MediaType.APPLICATION_JSON );
+
+    @Service
+    private Configuration cfg;
+
+    @Service
+    private JavaxJsonFactories jsonFactories;
+
+    @Override
+    public boolean writeResponse( final Object result, final Response response )
+        throws ResourceException
+    {
+        if( result instanceof Form )
+        {
+            MediaType type = getVariant( response.getRequest(), ENGLISH, supportedMediaTypes ).getMediaType();
+            if( MediaType.APPLICATION_JSON.equals( type ) )
+            {
+                JsonObjectBuilder builder = jsonFactories.builderFactory().createObjectBuilder();
+                Form form = (Form) result;
+                try
+                {
+                    for( Parameter parameter : form )
+                    {
+                        String value = parameter.getValue();
+                        if( value == null )
+                        {
+                            builder.add( parameter.getName(), JsonValue.NULL );
+                        }
+                        else
+                        {
+                            builder.add( parameter.getName(), value );
+                        }
+                    }
+                }
+                catch( JsonException e )
+                {
+                    e.printStackTrace();
+                }
+
+                StringRepresentation representation = new StringRepresentation( builder.build().toString(),
+                                                                                MediaType.APPLICATION_JSON );
+                response.setEntity( representation );
+
+                return true;
+            }
+            else if( MediaType.TEXT_HTML.equals( type ) )
+            {
+                Representation rep = new WriterRepresentation( MediaType.TEXT_HTML )
+                {
+                    @Override
+                    public void write( Writer writer )
+                        throws IOException
+                    {
+                        Map<String, Object> root = new HashMap<>();
+                        root.put( "request", response.getRequest() );
+                        root.put( "response", response );
+                        root.put( "result", result );
+                        try
+                        {
+                            Template formHtmlTemplate = cfg.getTemplate( "form.htm" );
+                            formHtmlTemplate.process( root, writer );
+                        }
+                        catch( TemplateException e )
+                        {
+                            throw new IOException( e );
+                        }
+                    }
+                };
+                response.setEntity( rep );
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/JSONResponseWriter.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/JSONResponseWriter.java
new file mode 100644
index 0000000..6b9af86
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/JSONResponseWriter.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.library.rest.server.restlet.responsewriter;
+
+import java.util.Arrays;
+import java.util.List;
+import javax.json.JsonObject;
+import org.restlet.Response;
+import org.restlet.data.MediaType;
+import org.restlet.representation.StringRepresentation;
+import org.restlet.resource.ResourceException;
+
+/**
+ * Handles JSONObject output
+ */
+public class JSONResponseWriter extends AbstractResponseWriter
+{
+    private static final List<MediaType> supportedMediaTypes = Arrays.asList( MediaType.TEXT_HTML,
+                                                                              MediaType.APPLICATION_JSON );
+
+    @Override
+    public boolean writeResponse( Object result, Response response ) throws ResourceException
+    {
+        if( result instanceof JsonObject )
+        {
+            MediaType type = getVariant( response.getRequest(), ENGLISH, supportedMediaTypes ).getMediaType();
+            if( MediaType.APPLICATION_JSON.equals( type ) )
+            {
+                JsonObject json = (JsonObject) result;
+                StringRepresentation representation = new StringRepresentation( json.toString(),
+                                                                                MediaType.APPLICATION_JSON );
+                response.setEntity( representation );
+                return true;
+            }
+            else if( MediaType.TEXT_HTML.equals( type ) )
+            {
+                JsonObject json = (JsonObject) result;
+                StringRepresentation representation = new StringRepresentation( json.toString(),
+                                                                                MediaType.TEXT_HTML );
+                response.setEntity( representation );
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/LinksResponseWriter.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/LinksResponseWriter.java
new file mode 100644
index 0000000..522eae1
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/LinksResponseWriter.java
@@ -0,0 +1,161 @@
+/*
+ *  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.polygene.library.rest.server.restlet.responsewriter;
+
+import freemarker.template.Configuration;
+import freemarker.template.TemplateException;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.library.rest.common.link.Link;
+import org.apache.polygene.library.rest.common.link.Links;
+import org.apache.polygene.spi.serialization.JsonSerializer;
+import org.restlet.Response;
+import org.restlet.data.MediaType;
+import org.restlet.data.Reference;
+import org.restlet.data.Status;
+import org.restlet.representation.Representation;
+import org.restlet.representation.StringRepresentation;
+import org.restlet.representation.WriterRepresentation;
+import org.restlet.resource.ResourceException;
+
+/**
+ * JAVADOC
+ */
+public class LinksResponseWriter
+    extends AbstractResponseWriter
+{
+    private static final List<MediaType> supportedLinkMediaTypes = Collections.singletonList( MediaType.APPLICATION_JSON );
+    private static final List<MediaType> supportedLinksMediaTypes = Arrays.asList( MediaType.TEXT_HTML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_ATOM );
+
+    @Service
+    Configuration cfg;
+
+    @Service
+    JsonSerializer jsonSerializer;
+
+    @Override
+    public boolean writeResponse( final Object result, final Response response )
+        throws ResourceException
+    {
+        if( result instanceof Link )
+        {
+            MediaType type = getVariant( response.getRequest(), ENGLISH, supportedLinkMediaTypes ).getMediaType();
+            if( MediaType.APPLICATION_JSON.equals( type ) )
+            {
+                String json = jsonSerializer.serialize( result );
+                response.setEntity( new StringRepresentation( json, MediaType.APPLICATION_JSON ) );
+                return true;
+            }
+            else
+            {
+                response.setStatus( Status.REDIRECTION_TEMPORARY );
+                Link link = (Link) result;
+                Reference reference = new Reference( response.getRequest().getResourceRef(), link.href().get() );
+                response.setLocationRef( reference );
+                return true;
+            }
+        }
+        else if( result instanceof Links )
+        {
+            MediaType type = getVariant( response.getRequest(), ENGLISH, supportedLinksMediaTypes ).getMediaType();
+            Representation rep;
+            if( MediaType.APPLICATION_JSON.equals( type ) )
+            {
+                rep = createJsonRepresentation( (Links) result );
+            }
+            else if( MediaType.TEXT_HTML.equals( type ) )
+            {
+                rep = createTextHtmlRepresentation( result, response );
+            }
+            else if( MediaType.APPLICATION_ATOM.equals( type ) )
+            {
+                rep = createAtomRepresentation( result, response );
+            }
+            else
+            {
+                return false;
+            }
+            response.setEntity( rep );
+            return true;
+        }
+        return false;
+    }
+
+    private StringRepresentation createJsonRepresentation( Links result )
+    {
+        String json = jsonSerializer.serialize( result );
+        return new StringRepresentation( json, MediaType.APPLICATION_JSON );
+    }
+
+    private Representation createTextHtmlRepresentation( final Object result, final Response response )
+    {
+        return new WriterRepresentation( MediaType.TEXT_HTML )
+                    {
+                        @Override
+                        public void write( Writer writer )
+                            throws IOException
+                        {
+                            Map<String, Object> context = new HashMap<>();
+                            context.put( "request", response.getRequest() );
+                            context.put( "response", response );
+                            context.put( "result", result );
+                            try
+                            {
+                                cfg.getTemplate( "links.htm" ).process( context, writer );
+                            }
+                            catch( TemplateException e )
+                            {
+                                throw new IOException( e );
+                            }
+                        }
+                    };
+    }
+
+    private Representation createAtomRepresentation( final Object result, final Response response )
+    {
+        return new WriterRepresentation( MediaType.APPLICATION_ATOM )
+        {
+            @Override
+            public void write( Writer writer )
+                throws IOException
+            {
+                Map<String, Object> context = new HashMap<>();
+                context.put( "request", response.getRequest() );
+                context.put( "response", response );
+                context.put( "result", result );
+                try
+                {
+                    cfg.getTemplate( "links.atom" ).process( context, writer );
+                }
+                catch( TemplateException e )
+                {
+                    throw new IOException( e );
+                }
+            }
+        };
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/ResourceResponseWriter.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/ResourceResponseWriter.java
new file mode 100644
index 0000000..4a913cc
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/ResourceResponseWriter.java
@@ -0,0 +1,112 @@
+/*
+ *  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.polygene.library.rest.server.restlet.responsewriter;
+
+import freemarker.template.Configuration;
+import freemarker.template.TemplateException;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.library.rest.common.Resource;
+import org.apache.polygene.library.rest.common.link.LinksUtil;
+import org.apache.polygene.spi.serialization.JsonSerializer;
+import org.restlet.Response;
+import org.restlet.data.MediaType;
+import org.restlet.data.Method;
+import org.restlet.representation.Representation;
+import org.restlet.representation.StringRepresentation;
+import org.restlet.representation.WriterRepresentation;
+import org.restlet.resource.ResourceException;
+
+/**
+ * ResponseWriter for ResourceValues
+ */
+public class ResourceResponseWriter extends AbstractResponseWriter
+{
+    private static final List<MediaType> supportedMediaTypes = Arrays.asList( MediaType.TEXT_HTML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_ATOM );
+
+    @Service
+    private Configuration cfg;
+
+    @Service
+    private JsonSerializer jsonSerializer;
+
+    @Override
+    public boolean writeResponse( final Object result, final Response response )
+        throws ResourceException
+    {
+        if( result instanceof Resource )
+        {
+            Resource resourceValue = (Resource) result;
+
+            // Allowed methods
+            response.getAllowedMethods().add( Method.GET );
+            if( resourceValue.commands().get().stream().anyMatch( LinksUtil.withRel( "delete" ) ) )
+            {
+                response.getAllowedMethods().add( Method.DELETE );
+            }
+            if( resourceValue.commands().get().stream().anyMatch( LinksUtil.withRel( "update" ) ) )
+            {
+                response.getAllowedMethods().add( Method.PUT );
+            }
+
+            // Response according to what client accepts
+            MediaType type = getVariant( response.getRequest(), ENGLISH, supportedMediaTypes ).getMediaType();
+            if( MediaType.APPLICATION_JSON.equals( type ) )
+            {
+                String json = jsonSerializer.serialize( resourceValue );
+                response.setEntity( new StringRepresentation( json, MediaType.APPLICATION_JSON ) );
+                return true;
+            }
+            else if( MediaType.TEXT_HTML.equals( type ) )
+            {
+                Representation rep = new WriterRepresentation( MediaType.TEXT_HTML )
+                {
+                    @Override
+                    public void write( Writer writer )
+                        throws IOException
+                    {
+                        Map<String, Object> context = new HashMap<>();
+                        context.put( "request", response.getRequest() );
+                        context.put( "response", response );
+                        context.put( "result", result );
+                        try
+                        {
+                            cfg.getTemplate( "resource.htm" ).process( context, writer );
+                        }
+                        catch( TemplateException e )
+                        {
+                            throw new IOException( e );
+                        }
+                    }
+                };
+                response.setEntity( rep );
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/ResourceTemplateResponseWriter.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/ResourceTemplateResponseWriter.java
new file mode 100644
index 0000000..eec0715
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/ResourceTemplateResponseWriter.java
@@ -0,0 +1,119 @@
+/*
+ *  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.polygene.library.rest.server.restlet.responsewriter;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.restlet.Response;
+import org.restlet.data.MediaType;
+import org.restlet.representation.Representation;
+import org.restlet.representation.WriterRepresentation;
+import org.restlet.resource.ResourceException;
+import org.restlet.service.MetadataService;
+
+/**
+ * JAVADOC
+ */
+public class ResourceTemplateResponseWriter extends AbstractResponseWriter
+{
+    private static final List<MediaType> supportedMediaTypes = Arrays.asList( MediaType.TEXT_HTML, MediaType.APPLICATION_ATOM );
+
+    @Service
+    private Configuration cfg;
+
+    @Service
+    private MetadataService metadataService;
+
+    Set<String> skip = new HashSet<>();
+
+    @Override
+    public boolean writeResponse( final Object result, final Response response )
+        throws ResourceException
+    {
+        MediaType type = getVariant( response.getRequest(), ENGLISH, supportedMediaTypes ).getMediaType();
+        if( type != null )
+        {
+            // Try to find template for this specific resource
+            StringBuilder templateBuilder = (StringBuilder) response.getRequest().getAttributes().get( "template" );
+            String templateName = templateBuilder.toString();
+
+            if( result instanceof ValueDescriptor )
+            {
+                templateName += "_form";
+            }
+
+            final String extension = metadataService.getExtension( type );
+            templateName += "." + extension;
+
+            // Have we failed on this one before, then don't try again
+            if( skip.contains( templateName ) )
+            {
+                return false;
+            }
+
+            try
+            {
+                final Template template = cfg.getTemplate( templateName );
+                Representation rep = new WriterRepresentation( MediaType.TEXT_HTML )
+                {
+                    @Override
+                    public void write( Writer writer )
+                        throws IOException
+                    {
+                        Map<String, Object> context = new HashMap<>();
+                        context.put( "request", response.getRequest() );
+                        context.put( "response", response );
+
+                        context.put( "result", result );
+
+                        try
+                        {
+                            template.process( context, writer );
+                        }
+                        catch( TemplateException e )
+                        {
+                            throw new IOException( e );
+                        }
+                    }
+                };
+                response.setEntity( rep );
+                return true;
+            }
+            catch( Exception e )
+            {
+                skip.add( templateName );
+                // Ignore
+            }
+        }
+        return false;
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/RestResponseException.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/RestResponseException.java
new file mode 100644
index 0000000..08a875d
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/RestResponseException.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.rest.server.restlet.responsewriter;
+
+import org.apache.polygene.library.rest.server.RestServerException;
+
+public class RestResponseException extends RestServerException
+{
+    public RestResponseException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/TableResponseWriter.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/TableResponseWriter.java
new file mode 100644
index 0000000..55ebe77
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/TableResponseWriter.java
@@ -0,0 +1,210 @@
+/*
+ *  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.polygene.library.rest.server.restlet.responsewriter;
+
+import freemarker.template.Configuration;
+import freemarker.template.TemplateException;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonBuilderFactory;
+import javax.json.JsonException;
+import javax.json.JsonObjectBuilder;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.library.rest.common.table.Cell;
+import org.apache.polygene.library.rest.common.table.Column;
+import org.apache.polygene.library.rest.common.table.Row;
+import org.apache.polygene.library.rest.common.table.Table;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.spi.serialization.JsonSerializer;
+import org.restlet.Response;
+import org.restlet.data.CharacterSet;
+import org.restlet.data.MediaType;
+import org.restlet.representation.Representation;
+import org.restlet.representation.WriterRepresentation;
+import org.restlet.resource.ResourceException;
+
+/**
+ * JAVADOC
+ */
+public class TableResponseWriter extends AbstractResponseWriter
+{
+    private static final List<MediaType> supportedMediaTypes = Arrays.asList( MediaType.TEXT_HTML,
+                                                                              MediaType.APPLICATION_JSON );
+
+    @Service
+    private JsonSerializer jsonSerializer;
+
+    @Service
+    private JavaxJsonFactories json;
+
+    @Service
+    private Configuration cfg;
+
+    @Override
+    public boolean writeResponse( final Object result, final Response response )
+        throws ResourceException
+    {
+        if( result instanceof Table )
+        {
+            MediaType type = getVariant( response.getRequest(), ENGLISH, supportedMediaTypes ).getMediaType();
+            if( MediaType.APPLICATION_JSON.equals( type ) )
+            {
+                response.setEntity( new WriterRepresentation( MediaType.APPLICATION_JSON )
+                {
+                    @Override
+                    public void write( Writer writer )
+                        throws IOException
+                    {
+                        try
+                        {
+                            JsonBuilderFactory jsonBuilderFactory = json.builderFactory();
+                            JsonObjectBuilder builder = jsonBuilderFactory.createObjectBuilder();
+                            Table tableValue = (Table) result;
+
+                            // Parse parameters
+                            String tqx = response.getRequest().getResourceRef().getQueryAsForm()
+                                                 .getFirstValue( "tqx" );
+                            String reqId = null;
+                            if( tqx != null )
+                            {
+                                String[] params = tqx.split( ";" );
+                                for( String param : params )
+                                {
+                                    String[] p = param.split( ":" );
+                                    String key = p[ 0 ];
+                                    String value = p[ 1 ];
+
+                                    if( key.equals( "reqId" ) )
+                                    {
+                                        reqId = value;
+                                    }
+                                }
+                            }
+
+                            builder.add( "version", "0.6" );
+                            if( reqId != null )
+                            {
+                                builder.add( "reqId", reqId );
+                            }
+                            builder.add( "status", "ok" );
+
+                            JsonObjectBuilder tableBuilder = jsonBuilderFactory.createObjectBuilder();
+                            JsonArrayBuilder colsBuilder = jsonBuilderFactory.createArrayBuilder();
+                            List<Column> columnList = tableValue.cols().get();
+                            for( Column columnValue : columnList )
+                            {
+                                colsBuilder.add( jsonBuilderFactory.createObjectBuilder()
+                                                                   .add( "id", columnValue.id().get() )
+                                                                   .add( "label", columnValue.label().get() )
+                                                                   .add( "type", columnValue.columnType().get() )
+                                                                   .build() );
+                            }
+                            tableBuilder.add( "cols", colsBuilder.build() );
+
+                            JsonArrayBuilder rowsBuilder = jsonBuilderFactory.createArrayBuilder();
+                            for( Row rowValue : tableValue.rows().get() )
+                            {
+                                JsonArrayBuilder cellsBuilder = jsonBuilderFactory.createArrayBuilder();
+                                int idx = 0;
+                                for( Cell cellValue : rowValue.c().get() )
+                                {
+                                    Object value = cellValue.v().get();
+                                    if( columnList.get( idx ).columnType().get().equals( Table.DATETIME )
+                                        && value != null )
+                                    {
+                                        value = value.toString();
+                                    }
+                                    else if( columnList.get( idx ).columnType().get().equals( Table.DATE )
+                                             && value != null )
+                                    {
+                                        value = value.toString();
+                                    }
+                                    else if( columnList.get( idx ).columnType().get().equals( Table.TIME_OF_DAY )
+                                             && value != null )
+                                    {
+                                        value = value.toString();
+                                    }
+
+                                    JsonObjectBuilder cellBuilder = jsonBuilderFactory.createObjectBuilder();
+                                    if( value != null )
+                                    {
+                                        cellBuilder.add( "v", jsonSerializer.toJson( Serializer.Options.ALL_TYPE_INFO, value ) );
+                                    }
+                                    if( cellValue.f().get() != null )
+                                    {
+                                        cellBuilder.add( "f", cellValue.f().get() );
+                                    }
+                                    cellsBuilder.add( cellBuilder.build() );
+                                    idx++;
+                                }
+                                JsonObjectBuilder rowBuilder = jsonBuilderFactory.createObjectBuilder();
+                                rowBuilder.add( "c", cellsBuilder.build() );
+                                rowsBuilder.add( rowBuilder.build() );
+                            }
+                            tableBuilder.add( "rows", rowsBuilder.build() );
+                            builder.add( "table", tableBuilder.build() );
+                            writer.write( builder.build().toString() );
+                        }
+                        catch( JsonException e )
+                        {
+                            throw new IOException( e );
+                        }
+                    }
+                } );
+                return true;
+            }
+            else if( MediaType.TEXT_HTML.equals( type ) )
+            {
+                Representation rep = new WriterRepresentation( MediaType.TEXT_HTML )
+                {
+                    @Override
+                    public void write( Writer writer )
+                        throws IOException
+                    {
+                        Map<String, Object> context = new HashMap<>();
+                        context.put( "request", response.getRequest() );
+                        context.put( "response", response );
+
+                        context.put( "result", result );
+                        try
+                        {
+                            cfg.getTemplate( "table.htm" ).process( context, writer );
+                        }
+                        catch( TemplateException e )
+                        {
+                            throw new IOException( e );
+                        }
+                    }
+                };
+                rep.setCharacterSet( CharacterSet.UTF_8 );
+                response.setEntity( rep );
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/ValueCompositeResponseWriter.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/ValueCompositeResponseWriter.java
new file mode 100644
index 0000000..845b256
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/ValueCompositeResponseWriter.java
@@ -0,0 +1,118 @@
+/*
+ *  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.polygene.library.rest.server.restlet.responsewriter;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.serialization.Serializer;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.spi.serialization.JsonSerializer;
+import org.restlet.Response;
+import org.restlet.data.MediaType;
+import org.restlet.representation.Representation;
+import org.restlet.representation.StringRepresentation;
+import org.restlet.representation.WriterRepresentation;
+import org.restlet.resource.ResourceException;
+
+/**
+ * JAVADOC
+ */
+public class ValueCompositeResponseWriter extends AbstractResponseWriter
+{
+    private static final List<MediaType> supportedMediaTypes = Arrays.asList( MediaType.TEXT_HTML, MediaType.APPLICATION_JSON );
+
+    @Service
+    private Configuration cfg;
+
+    @Service
+    private JsonSerializer serializer;
+
+    @Override
+    public boolean writeResponse( final Object result, final Response response )
+        throws ResourceException
+    {
+        if( result instanceof ValueComposite )
+        {
+            MediaType type = getVariant( response.getRequest(), ENGLISH, supportedMediaTypes ).getMediaType();
+            if( MediaType.APPLICATION_JSON.equals( type ) )
+            {
+                StringRepresentation representation = new StringRepresentation( serializer.serialize( Serializer.Options.ALL_TYPE_INFO, result ),
+                                                                                MediaType.APPLICATION_JSON );
+                response.setEntity( representation );
+                return true;
+            }
+            else if( MediaType.TEXT_HTML.equals( type ) )
+            {
+                Representation rep = new WriterRepresentation( MediaType.TEXT_HTML )
+                {
+                    @Override
+                    public void write( Writer writer )
+                        throws IOException
+                    {
+                        // Look for type specific template
+                        Template template;
+                        try
+                        {
+                            template = cfg.getTemplate( "/rest/template/" + result.getClass()
+                                .getInterfaces()[ 0 ].getSimpleName() + ".htm" );
+                        }
+                        catch( Exception e )
+                        {
+                            // Use default
+                            template = cfg.getTemplate( "value.htm" );
+                        }
+
+                        Map<String, Object> context = new HashMap<String, Object>();
+                        context.put( "request", response.getRequest() );
+                        context.put( "response", response );
+                        context.put( "result", result );
+                        context.put( "util", this );
+                        try
+                        {
+                            template.process( context, writer );
+                        }
+                        catch( TemplateException e )
+                        {
+                            throw new IOException( e );
+                        }
+                    }
+
+                    public boolean isSequence( Object obj )
+                    {
+                        return obj instanceof Collection;
+                    }
+                };
+                response.setEntity( rep );
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/ValueDescriptorResponseWriter.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/ValueDescriptorResponseWriter.java
new file mode 100644
index 0000000..cc86a26
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/ValueDescriptorResponseWriter.java
@@ -0,0 +1,133 @@
+/*
+ *  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.polygene.library.rest.server.restlet.responsewriter;
+
+import freemarker.template.Configuration;
+import freemarker.template.TemplateException;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.json.JsonException;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonValue;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
+import org.apache.polygene.spi.serialization.JsonSerializer;
+import org.restlet.Response;
+import org.restlet.data.MediaType;
+import org.restlet.representation.Representation;
+import org.restlet.representation.StringRepresentation;
+import org.restlet.representation.WriterRepresentation;
+import org.restlet.resource.ResourceException;
+
+import static org.restlet.data.MediaType.APPLICATION_JSON;
+import static org.restlet.data.MediaType.TEXT_HTML;
+
+/**
+ * JAVADOC
+ */
+public class ValueDescriptorResponseWriter extends AbstractResponseWriter
+{
+    private static final List<MediaType> supportedMediaTypes = Arrays.asList( TEXT_HTML, APPLICATION_JSON );
+
+    @Structure
+    private ModuleDescriptor module;
+
+    @Service
+    private JsonSerializer jsonSerializer;
+
+    @Service
+    private JavaxJsonFactories json;
+
+    @Service
+    private Configuration cfg;
+
+    @Override
+    public boolean writeResponse( final Object result, final Response response )
+        throws ResourceException
+    {
+        if( result instanceof ValueDescriptor )
+        {
+            MediaType type = getVariant( response.getRequest(), ENGLISH, supportedMediaTypes ).getMediaType();
+            if( APPLICATION_JSON.equals( type ) )
+            {
+                ValueDescriptor vd = (ValueDescriptor) result;
+                JsonObjectBuilder builder = json.builderFactory().createObjectBuilder();
+                vd.state().properties().forEach(
+                    property ->
+                    {
+                        try
+                        {
+                            Object o = property.resolveInitialValue( module );
+                            if( o == null )
+                            {
+                                builder.add( property.qualifiedName().name(), JsonValue.NULL );
+                            }
+                            else
+                            {
+                                builder.add( property.qualifiedName().name(), jsonSerializer.toJson( o ) );
+                            }
+                        }
+                        catch( JsonException ex )
+                        {
+                            throw new RestResponseException( "Unable to serialize " + vd, ex );
+                        }
+                    } );
+                StringRepresentation representation = new StringRepresentation( builder.build().toString(),
+                                                                                APPLICATION_JSON );
+                response.setEntity( representation );
+                return true;
+            }
+            else if( TEXT_HTML.equals( type ) )
+            {
+                Representation rep = new WriterRepresentation( TEXT_HTML )
+                {
+                    @Override
+                    public void write( Writer writer )
+                        throws IOException
+                    {
+                        Map<String, Object> context = new HashMap<>();
+                        context.put( "request", response.getRequest() );
+                        context.put( "response", response );
+                        context.put( "result", result );
+                        try
+                        {
+                            cfg.getTemplate( "form.htm" ).process( context, writer );
+                        }
+                        catch( TemplateException e )
+                        {
+                            throw new IOException( e );
+                        }
+                    }
+                };
+                response.setEntity( rep );
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/package.html b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/package.html
new file mode 100644
index 0000000..91ea832
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/restlet/responsewriter/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Restlet ReST Server Response Writers.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/spi/CommandResult.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/spi/CommandResult.java
new file mode 100644
index 0000000..a5a6b86
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/spi/CommandResult.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.library.rest.server.spi;
+
+/**
+ * TODO
+ */
+public interface CommandResult
+{
+    Object getResult();
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/spi/RequestReader.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/spi/RequestReader.java
new file mode 100644
index 0000000..23a7e55
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/spi/RequestReader.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.rest.server.spi;
+
+import java.lang.reflect.Method;
+import org.restlet.Request;
+import org.restlet.resource.ResourceException;
+
+/**
+ * TODO
+ */
+public interface RequestReader
+{
+    Object[] readRequest( Request request, Method method )
+        throws ResourceException;
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/spi/ResponseWriter.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/spi/ResponseWriter.java
new file mode 100644
index 0000000..fd82124
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/spi/ResponseWriter.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.rest.server.spi;
+
+import org.restlet.Response;
+import org.restlet.resource.ResourceException;
+
+/**
+ * TODO
+ */
+public interface ResponseWriter
+{
+    boolean writeResponse( final Object result, final Response response )
+        throws ResourceException;
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/spi/ResultConverter.java b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/spi/ResultConverter.java
new file mode 100644
index 0000000..23fc066
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/spi/ResultConverter.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.rest.server.spi;
+
+import org.restlet.Request;
+
+/**
+ * JAVADOC
+ */
+public interface ResultConverter
+{
+    Object convert( Object result, Request request, Object[] arguments );
+}
diff --git a/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/spi/package.html b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/spi/package.html
new file mode 100644
index 0000000..ec3367d
--- /dev/null
+++ b/libraries/rest-server/src/main/java/org/apache/polygene/library/rest/server/spi/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ReST Server SPI.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ContextResource.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ContextResource.java
deleted file mode 100644
index b7191d2..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ContextResource.java
+++ /dev/null
@@ -1,917 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.api;
-
-import java.io.UnsupportedEncodingException;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.constraint.ConstraintViolation;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.constraint.Name;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.EntityTypeNotFoundException;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.library.rest.common.Resource;
-import org.qi4j.library.rest.common.link.Link;
-import org.qi4j.library.rest.server.restlet.ConstraintViolationMessages;
-import org.qi4j.library.rest.server.restlet.InteractionConstraints;
-import org.qi4j.library.rest.server.restlet.RequestReaderDelegator;
-import org.qi4j.library.rest.server.restlet.ResponseWriterDelegator;
-import org.qi4j.library.rest.server.spi.ResultConverter;
-import org.qi4j.spi.Qi4jSPI;
-import org.restlet.Request;
-import org.restlet.Response;
-import org.restlet.Uniform;
-import org.restlet.data.Form;
-import org.restlet.data.Language;
-import org.restlet.data.Preference;
-import org.restlet.data.Reference;
-import org.restlet.data.Status;
-import org.restlet.representation.EmptyRepresentation;
-import org.restlet.representation.Representation;
-import org.restlet.representation.StringRepresentation;
-import org.restlet.resource.ResourceException;
-import org.slf4j.LoggerFactory;
-
-import static org.qi4j.api.util.Annotations.isType;
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.iterable;
-import static org.qi4j.library.rest.server.api.ObjectSelection.current;
-
-/**
- * JAVADOC
- */
-public class ContextResource
-    implements Uniform
-{
-    private static final String ARGUMENTS = "arguments";
-    public static final String RESOURCE_VALIDITY = "validity";
-
-    // API fields
-    @Structure
-    protected Module module;
-
-    // Private state
-    private final Map<String, Method> resourceMethodQueries = new HashMap<>();
-    private final Map<String, Method> resourceMethodCommands = new HashMap<>();
-    private final Map<String, Method> subResources = new LinkedHashMap<>();
-    private final List<Method> resourceQueries = new ArrayList<>();
-    private final List<Method> resourceCommands = new ArrayList<>();
-
-    @Structure
-    private Qi4jSPI spi;
-
-    @Service
-    private ResponseWriterDelegator responseWriter;
-
-    @Service
-    private RequestReaderDelegator requestReader;
-
-    @Service
-    private InteractionConstraints constraints;
-
-    @Optional
-    @Service
-    private ResultConverter converter;
-
-    @Uses
-    private ContextRestlet restlet;
-
-    public ContextResource()
-    {
-        // Resource method mappings
-        for( Method method : getClass().getMethods() )
-        {
-            if( ContextResource.class.isAssignableFrom( method.getDeclaringClass() )
-                && !ContextResource.class.equals( method.getDeclaringClass() )
-                && !method.isSynthetic() )
-            {
-                if( method.getAnnotation( SubResource.class ) == null )
-                {
-                    Method oldMethod;
-
-                    if( isCommand( method ) )
-                    {
-                        oldMethod = resourceMethodCommands.put( method.getName().toLowerCase(), method );
-                        resourceCommands.add( method );
-                    }
-                    else
-                    {
-                        oldMethod = resourceMethodQueries.put( method.getName().toLowerCase(), method );
-                        resourceQueries.add( method );
-                    }
-
-                    if( oldMethod != null )
-                    {
-                        throw new IllegalStateException( "Two methods in resource " + getClass().getName() + " with same name " + oldMethod
-                            .getName() + ", which is not allowed" );
-                    }
-                }
-                else
-                {
-                    Method oldMethod = subResources.put( method.getName().toLowerCase(), method );
-
-                    if( oldMethod != null )
-                    {
-                        throw new IllegalStateException( "Two methods in resource " + getClass().getName() + " with same name " + oldMethod
-                            .getName() + ", which is not allowed" );
-                    }
-                }
-            }
-        }
-    }
-
-    // Uniform implementation
-    @Override
-    public final void handle( Request request, Response response )
-    {
-        ObjectSelection objectSelection = current();
-
-        // Check constraints for this resource
-        if( !constraints.isValid( getClass(), objectSelection, module ) )
-        {
-            throw new ResourceException( Status.CLIENT_ERROR_FORBIDDEN );
-        }
-
-        // Find remaining segments
-        List<String> segments = getSegments();
-
-        if( segments.size() > 0 )
-        {
-            String segment = segments.remove( 0 );
-
-            if( segments.size() > 0 )
-            {
-                handleSubResource( segment );
-            }
-            else
-            {
-                handleResource( segment );
-            }
-        }
-    }
-
-    // API methods
-    protected void setResourceValidity( EntityComposite entity )
-    {
-        Request request = Request.getCurrent();
-        ResourceValidity validity = new ResourceValidity( entity, spi, request );
-        request.getAttributes().put( RESOURCE_VALIDITY, validity );
-    }
-
-    protected void subResource( Class<? extends ContextResource> subResourceClass )
-    {
-        restlet.subResource( subResourceClass );
-    }
-
-    protected <T> T select( Class<T> entityClass, String id )
-        throws ResourceException
-    {
-        try
-        {
-            T composite = module.currentUnitOfWork().get( entityClass, id );
-            current().select( composite );
-            return composite;
-        }
-        catch( EntityTypeNotFoundException | NoSuchEntityException e )
-        {
-            throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
-        }
-    }
-
-    protected <T> T selectFromManyAssociation( ManyAssociation<T> manyAssociation, String id )
-        throws ResourceException
-    {
-        T entity = (T) module.currentUnitOfWork().get( Object.class, id );
-        if( !manyAssociation.contains( entity ) )
-        {
-            throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
-        }
-
-        current().select( entity );
-        return entity;
-    }
-    
-    protected <T> T selectFromNamedAssociation( NamedAssociation<T> namedAssociation, String id )
-        throws ResourceException
-    {
-        T entity = (T) module.currentUnitOfWork().get( Object.class, id );
-        String name = namedAssociation.nameOf( entity );
-        if(name == null)
-        {
-            throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
-        }
-
-        current().select( entity );
-        return entity;
-    }
-
-    protected void selectFromList( List<?> list, String indexString )
-    {
-        Integer index = Integer.decode( indexString );
-
-        if( index < 0 || index >= list.size() )
-        {
-            throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
-        }
-
-        current().select( index );
-
-        Object value = list.get( index );
-        current().select( value );
-    }
-
-    protected Locale getLocale()
-    {
-        Request request = Request.getCurrent();
-
-        List<Preference<Language>> preferenceList = request.getClientInfo().getAcceptedLanguages();
-
-        if( preferenceList.isEmpty() )
-        {
-            return Locale.getDefault();
-        }
-
-        Language language = preferenceList
-            .get( 0 ).getMetadata();
-        String[] localeStr = language.getName().split( "-" );
-
-        Locale locale;
-        switch( localeStr.length )
-        {
-        case 1:
-            locale = new Locale( localeStr[ 0 ] );
-            break;
-        case 2:
-            locale = new Locale( localeStr[ 0 ], localeStr[ 1 ] );
-            break;
-        case 3:
-            locale = new Locale( localeStr[ 0 ], localeStr[ 1 ], localeStr[ 2 ] );
-            break;
-        default:
-            locale = Locale.getDefault();
-        }
-        return locale;
-    }
-
-    protected <T> T context( Class<T> contextClass )
-    {
-        return module.newObject( contextClass, ObjectSelection.current().toArray() );
-    }
-
-    // Private implementation
-    private void handleSubResource( String segment )
-    {
-        if( this instanceof SubResources )
-        {
-            SubResources subResources = (SubResources) this;
-            try
-            {
-                StringBuilder template = (StringBuilder) Request.getCurrent().getAttributes().get( "template" );
-                template.append( "resource/" );
-                subResources.resource( URLDecoder.decode( segment, "UTF-8" ) );
-            }
-            catch( UnsupportedEncodingException e )
-            {
-                subResources.resource( segment );
-            }
-        }
-        else
-        {
-            // Find @SubResource annotated method
-            try
-            {
-                Method method = getSubResourceMethod( segment );
-
-                StringBuilder template = (StringBuilder) Request.getCurrent().getAttributes().get( "template" );
-                template.append( segment ).append( "/" );
-
-                method.invoke( this );
-            }
-            catch( Throwable e )
-            {
-                handleException( Response.getCurrent(), e );
-            }
-        }
-    }
-
-    private Method getSubResourceMethod( String resourceName )
-        throws ResourceException
-    {
-        Method method = subResources.get( resourceName );
-        if( method != null )
-        {
-            return method;
-        }
-
-        throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
-    }
-
-    private void resource()
-    {
-        Request request = Request.getCurrent();
-        Response response = Response.getCurrent();
-        if( !request.getMethod().equals( org.restlet.data.Method.GET ) )
-        {
-            response.setStatus( Status.CLIENT_ERROR_METHOD_NOT_ALLOWED );
-            return;
-        }
-
-        ObjectSelection objectSelection = current();
-
-        // Check for interaction->method mappings
-        if( ResourceDelete.class.isAssignableFrom( getClass() ) )
-        {
-            response.getAllowedMethods().add( org.restlet.data.Method.DELETE );
-        }
-        if( ResourceUpdate.class.isAssignableFrom( getClass() ) )
-        {
-            response.getAllowedMethods().add( org.restlet.data.Method.PUT );
-        }
-
-        // Construct resource
-        ValueBuilder<Resource> builder = module.newValueBuilder( Resource.class );
-
-        List<Link> queriesProperty = builder.prototype().queries().get();
-        for( Method query : resourceQueries )
-        {
-            if( constraints.isValid( query, objectSelection, module ) )
-            {
-                ValueBuilder<Link> linkBuilder = module.newValueBuilder( Link.class );
-                Link prototype = linkBuilder.prototype();
-                prototype.classes().set( "query" );
-                prototype.text().set( humanReadable( query.getName() ) );
-                prototype.href().set( query.getName().toLowerCase() );
-                prototype.rel().set( query.getName().toLowerCase() );
-                prototype.id().set( query.getName().toLowerCase() );
-                queriesProperty.add( linkBuilder.newInstance() );
-            }
-        }
-
-        List<Link> commandsProperty = builder.prototype().commands().get();
-        for( Method command : resourceCommands )
-        {
-            if( constraints.isValid( command, objectSelection, module ) )
-            {
-                ValueBuilder<Link> linkBuilder = module.newValueBuilder( Link.class );
-                Link prototype = linkBuilder.prototype();
-                prototype.classes().set( "command" );
-                prototype.text().set( humanReadable( command.getName() ) );
-                prototype.href().set( command.getName().toLowerCase() );
-                prototype.rel().set( command.getName().toLowerCase() );
-                prototype.id().set( command.getName().toLowerCase() );
-                commandsProperty.add( linkBuilder.newInstance() );
-            }
-        }
-
-        List<Link> resourcesProperty = builder.prototype().resources().get();
-        for( Method subResource : subResources.values() )
-        {
-            if( constraints.isValid( subResource, objectSelection, module ) )
-            {
-                ValueBuilder<Link> linkBuilder = module.newValueBuilder( Link.class );
-                Link prototype = linkBuilder.prototype();
-                prototype.classes().set( "resource" );
-                prototype.text().set( humanReadable( subResource.getName() ) );
-                prototype.href().set( subResource.getName().toLowerCase() + "/" );
-                prototype.rel().set( subResource.getName().toLowerCase() );
-                prototype.id().set( subResource.getName().toLowerCase() );
-                resourcesProperty.add( linkBuilder.newInstance() );
-            }
-        }
-
-        try
-        {
-            Method indexMethod = resourceMethodQueries.get( "index" );
-            if( indexMethod != null )
-            {
-                Object index = convert( indexMethod.invoke( this ) );
-
-                if( index != null && index instanceof ValueComposite )
-                {
-                    builder.prototype().index().set( (ValueComposite) index );
-                }
-            }
-        }
-        catch( Throwable e )
-        {
-            // Ignore
-        }
-
-        try
-        {
-            responseWriter.writeResponse( builder.newInstance(), response );
-        }
-        catch( Throwable e )
-        {
-            handleException( response, e );
-        }
-    }
-
-    private boolean isCommand( Method method )
-    {
-        return method.getReturnType().equals( Void.TYPE ) || method.getName().equals( "create" );
-    }
-
-    /**
-     * Transform a Java name to a human readable string by replacing uppercase characters
-     * with space+toLowerCase(char).
-     * <p>
-     * Example:
-     * <pre><code>
-     * changeDescription -> Change description
-     * doStuffNow -> Do stuff now
-     * </code></pre>
-     *
-     * @param name Java name
-     *
-     * @return Human readable name
-     */
-    private String humanReadable( String name )
-    {
-        StringBuilder humanReadableString = new StringBuilder();
-
-        for( int i = 0; i < name.length(); i++ )
-        {
-            char character = name.charAt( i );
-            if( i == 0 )
-            {
-                // Capitalize first character
-                humanReadableString.append( Character.toUpperCase( character ) );
-            }
-            else if( Character.isLowerCase( character ) )
-            {
-                humanReadableString.append( character );
-            }
-            else
-            {
-                humanReadableString.append( ' ' ).append( Character.toLowerCase( character ) );
-            }
-        }
-
-        return humanReadableString.toString();
-    }
-
-    private void result( Object resultValue )
-        throws Exception
-    {
-        if( resultValue != null )
-        {
-            if( !responseWriter.writeResponse( resultValue, Response.getCurrent() ) )
-            {
-                throw new ResourceException( Status.SERVER_ERROR_INTERNAL, "No result writer for type " + resultValue.getClass()
-                    .getName() );
-            }
-        }
-    }
-
-    private List<String> getSegments()
-    {
-        return (List<String>) Request.getCurrent().getAttributes().get( "segments" );
-    }
-
-    private void handleResource( String segment )
-    {
-        Request request = Request.getCurrent();
-        if( segment.isEmpty() || segment.equals( "." ) )
-        {
-            StringBuilder template = (StringBuilder) request.getAttributes().get( "template" );
-            template.append( "resource" );
-
-            // Index for this resource
-            resource();
-        }
-        else
-        {
-            StringBuilder template = (StringBuilder) request.getAttributes().get( "template" );
-            template.append( segment );
-
-            if( resourceMethodCommands.containsKey( segment ) )
-            {
-                handleCommand( segment );
-            }
-            else
-            {
-                handleQuery( segment );
-            }
-        }
-    }
-
-    private void handleCommand( String segment )
-    {
-        Request request = Request.getCurrent();
-        Response response = Response.getCurrent();
-
-        // Check if this is a request to show the form for this command
-        Method interactionMethod = resourceMethodCommands.get( segment );
-        if( shouldShowCommandForm( interactionMethod ) )
-        {
-            // Show form
-
-            // TODO This should check if method is idempotent
-            response.getAllowedMethods().add( org.restlet.data.Method.POST );
-
-            try
-            {
-                // Check if there is a query with this name - if so invoke it
-                Method queryMethod = resourceMethodQueries.get( segment );
-                if( queryMethod != null )
-                {
-                    result( queryMethod.invoke( this ) );
-                }
-                else
-                {
-                    request.setMethod( org.restlet.data.Method.POST );
-                    response.setStatus( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY );
-                    result( formForMethod( interactionMethod ) );
-                }
-            }
-            catch( Exception e )
-            {
-                handleException( response, e );
-            }
-        }
-        else
-        {
-            // Check timestamps
-            ResourceValidity validity = (ResourceValidity) request.getAttributes().get( RESOURCE_VALIDITY );
-            if( validity != null )
-            {
-                validity.checkRequest();
-            }
-
-            // We have input data - do command
-            // Check method constraints
-            if( !constraints.isValid( interactionMethod, current(), module ) )
-            {
-                throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
-            }
-
-            // Create argument
-            Object[] arguments = requestReader.readRequest( Request.getCurrent(), interactionMethod );
-            Request.getCurrent().getAttributes().put( ARGUMENTS, arguments );
-
-            // Invoke method
-            try
-            {
-                Object result = interactionMethod.invoke( this, arguments );
-
-                if( result != null )
-                {
-                    if( result instanceof Representation )
-                    {
-                        response.setEntity( (Representation) result );
-                    }
-                    else
-                    {
-                        result( convert( result ) );
-                    }
-                }
-            }
-            catch( Throwable e )
-            {
-                handleException( response, e );
-            }
-        }
-    }
-
-    private boolean shouldShowCommandForm( Method interactionMethod )
-    {
-        // Show form on GET/HEAD
-        if( Request.getCurrent().getMethod().isSafe() )
-        {
-            return true;
-        }
-
-        if( interactionMethod.getParameterTypes().length > 0 )
-        {
-            return !( interactionMethod.getParameterTypes()[ 0 ].equals( Response.class ) || Request.getCurrent()
-                .getEntity()
-                .isAvailable() || Request.getCurrent().getEntityAsText() != null || Request.getCurrent()
-                                                                                        .getResourceRef()
-                                                                                        .getQuery() != null );
-        }
-
-        return false;
-    }
-
-    private void handleQuery( String segment )
-    {
-        Request request = Request.getCurrent();
-        Response response = Response.getCurrent();
-
-        // Query
-
-        // Try to locate either the query method or command method that should be used
-        Method queryMethod = resourceMethodQueries.get( segment );
-        if( queryMethod == null )
-        {
-            queryMethod = resourceMethodCommands.get( segment );
-        }
-
-        if( queryMethod == null )
-        {
-            // Not found as interaction, try SubResource
-            Method resourceMethod = subResources.get( segment );
-            if( resourceMethod != null && resourceMethod.getAnnotation( SubResource.class ) != null )
-            {
-                // Found it! Redirect to it
-                response.setStatus( Status.REDIRECTION_FOUND );
-                response
-                    .setLocationRef( new Reference( request
-                                                        .getResourceRef()
-                                                        .toString() + "/" ).toString() );
-                return;
-            }
-            else
-            {
-                // 404
-                throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
-            }
-        }
-
-        // Check if this is a request to show the form for this interaction
-        if( ( request
-                  .getMethod()
-                  .isSafe() && queryMethod.getParameterTypes().length != 0 && request
-                                                                                  .getResourceRef()
-                                                                                  .getQuery() == null ) ||
-            ( !request
-                .getMethod()
-                .isSafe() && queryMethod.getParameterTypes().length != 0 && !( request
-                                                                                   .getEntity()
-                                                                                   .isAvailable() || request
-                                                                                                         .getResourceRef()
-                                                                                                         .getQuery() != null || queryMethod
-                .getParameterTypes()[ 0 ].equals( Response.class ) ) ) )
-        {
-            // Show form
-            try
-            {
-                // Tell client to try again
-                response.setStatus( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY );
-                response.getAllowedMethods().add( org.restlet.data.Method.GET );
-                response.getAllowedMethods().add( org.restlet.data.Method.POST );
-                result( formForMethod( queryMethod ) );
-            }
-            catch( Exception e )
-            {
-                handleException( response, e );
-            }
-        }
-        else
-        {
-            // Check timestamps
-            ResourceValidity validity = (ResourceValidity) request.getAttributes().get( RESOURCE_VALIDITY );
-            if( validity != null )
-            {
-                validity.checkRequest();
-            }
-
-            // We have input data - do query
-            // Check method constraints
-            if( !constraints.isValid( queryMethod, current(), module ) )
-            {
-                throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
-            }
-
-            try
-            {
-                // Create argument
-                Object[] arguments;
-                if( queryMethod.getParameterTypes().length > 0 )
-                {
-                    try
-                    {
-                        arguments = requestReader.readRequest( Request.getCurrent(), queryMethod );
-
-                        if( arguments == null )
-                        {
-                            // Show form
-                            result( formForMethod( queryMethod ) );
-                            return;
-                        }
-                    }
-                    catch( IllegalArgumentException e )
-                    {
-                        // Still missing some values - show form
-                        result( formForMethod( queryMethod ) );
-                        return;
-                    }
-                }
-                else
-                {
-                    // No arguments to this query
-                    arguments = new Object[ 0 ];
-                }
-
-                // Invoke method
-                Request.getCurrent().getAttributes().put( ARGUMENTS, arguments );
-                Object result = queryMethod.invoke( this, arguments );
-                if( result != null )
-                {
-                    if( result instanceof Representation )
-                    {
-                        response.setEntity( (Representation) result );
-                    }
-                    else
-                    {
-                        result( convert( result ) );
-                    }
-                }
-            }
-            catch( Throwable e )
-            {
-                handleException( response, e );
-            }
-        }
-    }
-
-    private Object convert( Object result )
-    {
-        if( converter != null )
-        {
-            result = converter.convert( result, Request.getCurrent(), (Object[]) Request.getCurrent()
-                .getAttributes()
-                .get( ARGUMENTS ) );
-        }
-
-        return result;
-    }
-
-    private void handleException( Response response, Throwable ex )
-    {
-        while( ex instanceof InvocationTargetException )
-        {
-            ex = ex.getCause();
-        }
-
-        try
-        {
-            throw ex;
-        }
-        catch( ResourceException e )
-        {
-            // IAE (or subclasses) are considered client faults
-            response.setEntity( new StringRepresentation( e.getMessage() ) );
-            response.setStatus( e.getStatus() );
-        }
-        catch( ConstraintViolationException e )
-        {
-            try
-            {
-                ConstraintViolationMessages cvm = new ConstraintViolationMessages();
-
-                // CVE are considered client faults
-                String messages = "";
-                Locale locale = ObjectSelection.type( Locale.class );
-                for( ConstraintViolation constraintViolation : e.constraintViolations() )
-                {
-                    if( !messages.isEmpty() )
-                    {
-                        messages += "\n";
-                    }
-                    messages += cvm.getMessage( constraintViolation, locale );
-                }
-
-                response.setEntity( new StringRepresentation( messages ) );
-                response.setStatus( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY );
-            }
-            catch( Exception e1 )
-            {
-                response.setEntity( new StringRepresentation( e.getMessage() ) );
-                response.setStatus( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY );
-            }
-        }
-        catch( IllegalArgumentException e )
-        {
-            // IAE (or subclasses) are considered client faults
-            response.setEntity( new StringRepresentation( e.getMessage() ) );
-            response.setStatus( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY );
-        }
-        catch( RuntimeException e )
-        {
-            // RuntimeExceptions are considered server faults
-            LoggerFactory.getLogger( getClass() ).warn( "Exception thrown during processing", e );
-            response.setEntity( new StringRepresentation( e.getMessage() ) );
-            response.setStatus( Status.SERVER_ERROR_INTERNAL );
-        }
-        catch( Exception e )
-        {
-            // Checked exceptions are considered client faults
-            String s = e.getMessage();
-            if( s == null )
-            {
-                s = e.getClass().getSimpleName();
-            }
-            response.setEntity( new StringRepresentation( s ) );
-            response.setStatus( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY );
-        }
-        catch( Throwable e )
-        {
-            // Anything else are considered server faults
-            LoggerFactory.getLogger( getClass() ).error( "Exception thrown during processing", e );
-            response.setEntity( new StringRepresentation( e.getMessage() ) );
-            response.setStatus( Status.SERVER_ERROR_INTERNAL );
-        }
-    }
-
-    private Form formForMethod( Method interactionMethod )
-    {
-        Form form = new Form();
-
-        Form queryAsForm = Request.getCurrent().getResourceRef().getQueryAsForm();
-        Form entityAsForm;
-        Representation representation = Request.getCurrent().getEntity();
-        if( representation != null && !EmptyRepresentation.class.isInstance( representation ) )
-        {
-            entityAsForm = new Form( representation );
-        }
-        else
-        {
-            entityAsForm = new Form();
-        }
-
-        Class<?> valueType = interactionMethod.getParameterTypes()[ 0 ];
-        if( ValueComposite.class.isAssignableFrom( valueType ) )
-        {
-            ValueDescriptor valueDescriptor = module.valueDescriptor( valueType.getName() );
-
-            for( PropertyDescriptor propertyDescriptor : valueDescriptor.state().properties() )
-            {
-                String value = getValue( propertyDescriptor.qualifiedName().name(), queryAsForm, entityAsForm );
-
-                if( value == null )
-                {
-                    Object initialValue = propertyDescriptor.initialValue( module );
-                    if( initialValue != null )
-                    {
-                        value = initialValue.toString();
-                    }
-                }
-
-                form.add( propertyDescriptor.qualifiedName().name(), value );
-            }
-        }
-        else if( valueType.isInterface() && interactionMethod.getParameterTypes().length == 1 )
-        {
-            // Single entity as input
-            form.add( "entity", getValue( "entity", queryAsForm, entityAsForm ) );
-        }
-        else
-        {
-            // Construct form out of individual parameters instead
-            for( Annotation[] annotations : interactionMethod.getParameterAnnotations() )
-            {
-                Name name = (Name) first( filter( isType( Name.class ), iterable( annotations ) ) );
-                form.add( name.value(), getValue( name.value(), queryAsForm, entityAsForm ) );
-            }
-        }
-
-        return form;
-    }
-
-    private String getValue( String name, Form queryAsForm, Form entityAsForm )
-    {
-        String value = queryAsForm.getFirstValue( name );
-        if( value == null )
-        {
-            value = entityAsForm.getFirstValue( name );
-        }
-        return value;
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ContextRestlet.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ContextRestlet.java
deleted file mode 100644
index 764db81..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ContextRestlet.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.api;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.cache.CacheOptions;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.ConcurrentEntityModificationException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.library.rest.server.restlet.ResponseWriterDelegator;
-import org.qi4j.library.rest.server.spi.CommandResult;
-import org.restlet.Request;
-import org.restlet.Response;
-import org.restlet.Restlet;
-import org.restlet.Uniform;
-import org.restlet.data.CharacterSet;
-import org.restlet.data.Language;
-import org.restlet.data.Method;
-import org.restlet.data.Reference;
-import org.restlet.data.Status;
-import org.restlet.representation.Representation;
-import org.restlet.representation.StringRepresentation;
-import org.restlet.resource.ResourceException;
-import org.slf4j.LoggerFactory;
-import org.slf4j.MDC;
-
-/**
- * JAVADOC
- */
-public abstract class ContextRestlet
-    extends Restlet
-{
-    @Structure
-    protected Module module;
-
-    @Service
-    private CommandResult commandResult;
-
-    @Service
-    private ResponseWriterDelegator responseWriter;
-
-    private Map<Class, Uniform> subResources = Collections.synchronizedMap( new HashMap<Class, Uniform>() );
-
-    @Override
-    public void handle( Request request, Response response )
-    {
-        super.handle( request, response );
-
-        MDC.put( "url", request.getResourceRef().toString() );
-
-        try
-        {
-            int tries = 0;
-
-            // TODO Make this number configurable
-            while( tries < 10 )
-            {
-                tries++;
-
-                // Root of the call
-                Reference ref = request.getResourceRef();
-                List<String> segments = ref.getScheme()
-                                            .equals( "riap" ) ? ref.getRelativeRef( new Reference( "riap://application/" ) )
-                    .getSegments() : ref.getRelativeRef().getSegments();
-
-                // Handle conversion of verbs into standard interactions
-                if( segments.get( segments.size() - 1 ).equals( "" ) )
-                {
-                    if( request.getMethod().equals( Method.DELETE ) )
-                    {
-                        // Translate DELETE into command "delete"
-                        segments.set( segments.size() - 1, "delete" );
-                    }
-                    else if( request.getMethod().equals( Method.PUT ) )
-                    {
-                        // Translate PUT into command "update"
-                        segments.set( segments.size() - 1, "update" );
-                    }
-                }
-
-                request.getAttributes().put( "segments", segments );
-                request.getAttributes().put( "template", new StringBuilder( "/rest/" ) );
-
-                Usecase usecase = UsecaseBuilder.buildUsecase( getUsecaseName( request ) )
-                    .withMetaInfo( request.getMethod().isSafe() ? CacheOptions.ALWAYS : CacheOptions.NEVER )
-                    .newUsecase();
-                UnitOfWork uow = module.newUnitOfWork( usecase );
-
-                ObjectSelection.newSelection();
-
-                try
-                {
-                    // Start handling the build-up for the context
-                    Uniform resource = createRoot( request, response );
-                    resource.handle( request, response );
-
-                    if( response.getEntity() != null )
-                    {
-                        if( response.getEntity().getModificationDate() == null )
-                        {
-
-                            ResourceValidity validity = (ResourceValidity) Request.getCurrent()
-                                .getAttributes()
-                                .get( ContextResource.RESOURCE_VALIDITY );
-                            if( validity != null )
-                            {
-                                validity.updateResponse( response );
-                            }
-                        }
-
-                        // Check if characterset is set
-                        if( response.getEntity().getCharacterSet() == null )
-                        {
-                            response.getEntity().setCharacterSet( CharacterSet.UTF_8 );
-                        }
-
-                        // Check if language is set
-                        if( response.getEntity().getLanguages().isEmpty() )
-                        {
-                            response.getEntity().getLanguages().add( Language.ENGLISH );
-                        }
-
-                        uow.discard();
-                    }
-                    else
-                    {
-                        // Check if last modified and tag is set
-                        ResourceValidity validity = null;
-
-                        try
-                        {
-                            validity = ObjectSelection.type( ResourceValidity.class );
-                        }
-                        catch( IllegalArgumentException e )
-                        {
-                            // Ignore
-                        }
-
-                        uow.complete();
-
-                        Object result = commandResult.getResult();
-                        if( result != null )
-                        {
-                            if( result instanceof Representation )
-                            {
-                                response.setEntity( (Representation) result );
-                            }
-                            else
-                            {
-                                if( !responseWriter.writeResponse( result, response ) )
-                                {
-                                    throw new ResourceException( Status.SERVER_ERROR_INTERNAL, "Could not write result of type " + result
-                                        .getClass()
-                                        .getName() );
-                                }
-                            }
-
-                            if( response.getEntity() != null )
-                            {
-                                // Check if characterset is set
-                                if( response.getEntity().getCharacterSet() == null )
-                                {
-                                    response.getEntity().setCharacterSet( CharacterSet.UTF_8 );
-                                }
-
-                                // Check if language is set
-                                if( response.getEntity().getLanguages().isEmpty() )
-                                {
-                                    response.getEntity().getLanguages().add( Language.ENGLISH );
-                                }
-
-                                // Check if last modified and tag should be set
-                                if( validity != null )
-                                {
-                                    UnitOfWork lastModifiedUoW = module.newUnitOfWork();
-
-                                    try
-                                    {
-                                        validity.updateEntity( lastModifiedUoW );
-
-                                        validity.updateResponse( response );
-                                    }
-                                    finally
-                                    {
-                                        lastModifiedUoW.discard();
-                                    }
-                                }
-                            }
-                        }
-                        return;
-                    }
-                    return;
-                }
-                catch( ConcurrentEntityModificationException ex )
-                {
-                    uow.discard();
-
-                    // Try again
-                    ObjectSelection.newSelection();
-                }
-                catch( Throwable e )
-                {
-                    uow.discard();
-                    handleException( response, e );
-                    return;
-                }
-            } // Try again
-        }
-        finally
-        {
-            MDC.clear();
-        }
-    }
-
-    protected abstract Uniform createRoot( Request request, Response response );
-
-    // Callbacks used from resources
-    public void subResource( Class<? extends ContextResource> subResourceClass )
-    {
-        Uniform subResource = subResources.get( subResourceClass );
-
-        if( subResource == null )
-        {
-            // Instantiate and store subresource instance
-            subResource = module.newObject( subResourceClass, this );
-            subResources.put( subResourceClass, subResource );
-        }
-
-        subResource.handle( Request.getCurrent(), Response.getCurrent() );
-    }
-
-    private String getUsecaseName( Request request )
-    {
-        if( request.getMethod().equals( org.restlet.data.Method.DELETE ) )
-        {
-            return "delete";
-        }
-        else
-        {
-            return request.getResourceRef().getLastSegment();
-        }
-    }
-
-    private void handleException( Response response, Throwable ex )
-    {
-        try
-        {
-            throw ex;
-        }
-        catch( ResourceException e )
-        {
-            // IAE (or subclasses) are considered client faults
-            LoggerFactory.getLogger( getClass() ).debug( "ResourceException thrown during processing", e );
-            response.setEntity( new StringRepresentation( e.getMessage() ) );
-            response.setStatus( e.getStatus() );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // IAE (or subclasses) are considered client faults
-            LoggerFactory.getLogger( getClass() ).debug( "IllegalArgumentsException thrown during processing", e );
-            response.setEntity( new StringRepresentation( e.getMessage() ) );
-            response.setStatus( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY );
-        }
-        catch( RuntimeException e )
-        {
-            // RuntimeExceptions are considered server faults
-            LoggerFactory.getLogger( getClass() ).warn( "Exception thrown during processing", e );
-            response.setEntity( new StringRepresentation( e.getMessage() ) );
-            response.setStatus( Status.SERVER_ERROR_INTERNAL );
-        }
-        catch( Exception e )
-        {
-            // Checked exceptions are considered client faults
-            LoggerFactory.getLogger( getClass() ).debug( "Checked exception thrown during processing", e );
-            response.setEntity( new StringRepresentation( e.getMessage() ) );
-            response.setStatus( Status.CLIENT_ERROR_UNPROCESSABLE_ENTITY );
-        }
-        catch( Throwable e )
-        {
-            // Anything else are considered server faults
-            LoggerFactory.getLogger( getClass() ).error( "Exception thrown during processing", e );
-            response.setEntity( new StringRepresentation( e.getMessage() ) );
-            response.setStatus( Status.SERVER_ERROR_INTERNAL );
-        }
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/InteractionConstraintsConcern.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/InteractionConstraintsConcern.java
deleted file mode 100644
index 7507db0..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/InteractionConstraintsConcern.java
+++ /dev/null
@@ -1,81 +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.qi4j.library.rest.server.api;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.AppliesToFilter;
-import org.qi4j.api.concern.GenericConcern;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.server.api.constraint.InteractionConstraintDeclaration;
-import org.qi4j.library.rest.server.api.constraint.RequiresValid;
-import org.qi4j.library.rest.server.restlet.InteractionConstraints;
-
-/**
- * Add this concern to all interaction methods that use constraints
- */
-@AppliesTo( InteractionConstraintsConcern.HasInteractionConstraints.class )
-public class InteractionConstraintsConcern
-    extends GenericConcern
-{
-    @Service
-    private InteractionConstraints interactionConstraints;
-
-    @Service
-    private Module module;
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        if( !interactionConstraints.isValid( proxy.getClass(), ObjectSelection.current(), module ) )
-        {
-            throw new IllegalStateException( "Not allowed to invoke interaction " + method.getName() );
-        }
-
-        if( !interactionConstraints.isValid( method, ObjectSelection.current(), module ) )
-        {
-            throw new IllegalStateException( "Not allowed to invoke interaction " + method.getName() );
-        }
-
-        return next.invoke( proxy, method, args );
-    }
-
-    public static class HasInteractionConstraints
-        implements AppliesToFilter
-    {
-        @Override
-        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
-        {
-            for( Annotation annotation : method.getAnnotations() )
-            {
-                if( annotation.annotationType().equals( RequiresValid.class ) ||
-                    annotation.annotationType().getAnnotation( ConstraintDeclaration.class ) != null ||
-                    annotation.annotationType().getAnnotation( InteractionConstraintDeclaration.class ) != null )
-                {
-                    return true;
-                }
-            }
-            return false;
-        }
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ObjectSelection.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ObjectSelection.java
deleted file mode 100644
index da660a0..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ObjectSelection.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.api;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.functional.Iterables;
-import org.restlet.Request;
-
-/**
- * Manage the current object selection. An instance of ObjectSelection
- * is created for each request, and stored as an attribute.
- * Whenever an object is identified in the chain, add it to the selection.
- */
-public class ObjectSelection
-{
-    public static ObjectSelection current()
-    {
-        return (ObjectSelection) Request.getCurrent().getAttributes().get( "selection" );
-    }
-
-    public static <T> T type( Class<T> type )
-    {
-        ObjectSelection selection = current();
-        if( selection == null )
-        {
-            throw new IllegalStateException( "No current selection" );
-        }
-
-        return selection.get( type );
-    }
-
-    public static void newSelection()
-    {
-        Request.getCurrent().getAttributes().put( "selection", new ObjectSelection() );
-    }
-
-    private List<Object> selection = new ArrayList<Object>();
-
-    /**
-     * Create new root roleMap
-     */
-    public ObjectSelection()
-    {
-    }
-
-    public void select( Object object )
-    {
-        selection.add( 0, object );
-    }
-
-    public <T> T get( Class<T> type )
-        throws IllegalArgumentException
-    {
-        for( Object object : selection )
-        {
-            if( type.isInstance( object ) )
-            {
-                return (T) object;
-            }
-        }
-        throw new IllegalArgumentException( "No object in selection for type:" + type.getSimpleName() );
-    }
-
-    public Iterable<Object> selection()
-    {
-        return selection;
-    }
-
-    public Object[] toArray()
-    {
-        return Iterables.toArray( Object.class, selection );
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ResourceCreate.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ResourceCreate.java
deleted file mode 100644
index 34e6a82..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ResourceCreate.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.api;
-
-/**
- * Standard interface for creation of new resources.
- */
-public interface ResourceCreate<INPUT, RESULT>
-{
-    RESULT create( INPUT value );
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ResourceDelete.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ResourceDelete.java
deleted file mode 100644
index f4eeeb2..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ResourceDelete.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.api;
-
-import java.io.IOException;
-
-/**
- * Standard interface for deletion of resources
- */
-public interface ResourceDelete
-{
-    void delete()
-        throws IOException;
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ResourceIndex.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ResourceIndex.java
deleted file mode 100644
index 63a510e..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ResourceIndex.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.api;
-
-/**
- * Standard interface for index of resources
- */
-public interface ResourceIndex<T>
-{
-    public T index();
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ResourceUpdate.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ResourceUpdate.java
deleted file mode 100644
index 884189d..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ResourceUpdate.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.api;
-
-/**
- * Standard interface for update of existing resources.
- */
-public interface ResourceUpdate<T>
-{
-    void update( T value );
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ResourceValidity.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ResourceValidity.java
deleted file mode 100644
index 2715756..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/ResourceValidity.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.api;
-
-import java.util.Date;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.spi.Qi4jSPI;
-import org.qi4j.spi.entity.EntityState;
-import org.restlet.Request;
-import org.restlet.Response;
-import org.restlet.data.Status;
-import org.restlet.data.Tag;
-import org.restlet.resource.ResourceException;
-
-/**
- * JAVADOC
- */
-public class ResourceValidity
-{
-    EntityComposite entity;
-    private final Qi4jSPI spi;
-    private Request request;
-
-    public ResourceValidity( EntityComposite entity, Qi4jSPI spi, Request request )
-    {
-        this.entity = entity;
-        this.spi = spi;
-        this.request = request;
-    }
-
-    public void updateEntity( UnitOfWork current )
-    {
-        try
-        {
-            entity = current.get( entity );
-        }
-        catch( NoSuchEntityException e )
-        {
-            // Entity was deleted
-            entity = null;
-        }
-    }
-
-    public void updateResponse( Response response )
-    {
-        if( entity != null )
-        {
-            EntityState state = spi.entityStateOf( entity );
-            Date lastModified = new Date( state.lastModified() );
-            Tag tag = new Tag( state.identity().identity() + "/" + state.version() );
-            response.getEntity().setModificationDate( lastModified );
-            response.getEntity().setTag( tag );
-        }
-    }
-
-    public void checkRequest()
-        throws ResourceException
-    {
-        // Check command rules
-        Date modificationDate = request.getConditions().getUnmodifiedSince();
-        if( modificationDate != null )
-        {
-            EntityState state = spi.entityStateOf( entity );
-            Date lastModified = new Date( ( state.lastModified() / 1000 ) * 1000 ); // Cut off milliseconds
-            if( lastModified.after( modificationDate ) )
-            {
-                throw new ResourceException( Status.CLIENT_ERROR_CONFLICT );
-            }
-        }
-
-        // Check query rules
-        modificationDate = request.getConditions().getModifiedSince();
-        if( modificationDate != null )
-        {
-            EntityState state = spi.entityStateOf( entity );
-            Date lastModified = new Date( ( state.lastModified() / 1000 ) * 1000 ); // Cut off milliseconds
-            if( !lastModified.after( modificationDate ) )
-            {
-                throw new ResourceException( Status.REDIRECTION_NOT_MODIFIED );
-            }
-        }
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/SubResource.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/SubResource.java
deleted file mode 100644
index 292dfb5..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/SubResource.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.api;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Mark methods that creates new sub-resources with this annotation
- */
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.METHOD } )
-@Documented
-public @interface SubResource
-{
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/SubResources.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/SubResources.java
deleted file mode 100644
index 5eba578..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/SubResources.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.api;
-
-import org.restlet.resource.ResourceException;
-
-/**
- * Resources that have a collection of sub-resources should extends this interface.
- */
-public interface SubResources
-{
-    /**
-     * Instantiate the sub-resource, perform any RoleMap bindings based on
-     * the given segment, and then call handle(Request,Response) on the subresource.
-     *
-     * @param segment the current segment that the sub-resource will correspond to
-     *
-     * @throws org.restlet.resource.ResourceException
-     *          if the subresource could not be lookup up, typically a 404
-     */
-    void resource( String segment )
-        throws ResourceException;
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/InteractionConstraint.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/InteractionConstraint.java
deleted file mode 100644
index df14d70..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/InteractionConstraint.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.api.constraint;
-
-import org.qi4j.library.rest.server.api.ObjectSelection;
-
-/**
- * JAVADOC
- */
-
-public interface InteractionConstraint<ANNOTATION extends java.lang.annotation.Annotation>
-{
-    boolean isValid( ANNOTATION annotation, ObjectSelection objectSelection );
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/InteractionConstraintDeclaration.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/InteractionConstraintDeclaration.java
deleted file mode 100644
index 96f985e..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/InteractionConstraintDeclaration.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.api.constraint;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * JAVADOC
- */
-@Retention( RetentionPolicy.RUNTIME )
-public @interface InteractionConstraintDeclaration
-{
-    Class<? extends InteractionConstraint<?>> value();
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/InteractionValidation.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/InteractionValidation.java
deleted file mode 100644
index 3739a22..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/InteractionValidation.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.api.constraint;
-
-/**
- * Interface that resources can implement to achieve custom validation
- * of whether an interaction is valid or not.
- * <p>
- * If the logic only applies for one
- * method it is usually better to use this instead of creating a new annotation for it.
- * </p>
- * <p>
- * This is triggered by annotating the method that should be validated like so:
- * </p>
- * <pre><code>
- *
- * &#64;RequiresValid("xyz") public void xyz()
- * {...}
- *
- * </code></pre>
- * <p>
- * This causes isValid("xyz") to be called. The isValid()
- * method can use the name to determine which set of logic is to be applied. Typically the provided
- * string will correspond to the name of the interaction, but this is not strictly necessary. It is
- * possible to combine several annotations on one method, if desired:
- * </p>
- * <pre><code>
- *
- * &#64;RequiresValid("allowed") &#64;RequiresValid("officehours")
- * public void xyz()
- * {...}
- * </code></pre>
- * <p>
- * The validation occurs both when a Resource is computed for the resource as a whole, and when an actual
- * invocation of an interaction is made.
- * </p>
- */
-public interface InteractionValidation
-{
-    boolean isValid( String name );
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/Requires.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/Requires.java
deleted file mode 100644
index 52b7a33..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/Requires.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.api.constraint;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.library.rest.server.api.ObjectSelection;
-
-/**
- * Annotation on interactions that requires objects of specific types
- * to be available in the ObjectSelection.
- *
- * Example:
- * <pre>
- *     &#64;Requires(File.class)
- *     public Representation content() {...}
- * </pre>
- */
-@ConstraintDeclaration
-@Retention( RetentionPolicy.RUNTIME )
-@Constraints( Requires.RequiresRoleConstraint.class )
-public @interface Requires
-{
-    Class<?>[] value();
-
-    class RequiresRoleConstraint
-        implements Constraint<Requires, ObjectSelection>
-    {
-        @Override
-        public boolean isValid( Requires requires, ObjectSelection objectSelection )
-        {
-            for( Class<?> roleClass : requires.value() )
-            {
-                try
-                {
-                    objectSelection.get( roleClass );
-                }
-                catch( IllegalArgumentException ex )
-                {
-                    return false;
-                }
-            }
-            return true;
-        }
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/RequiresValid.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/RequiresValid.java
deleted file mode 100644
index d7bb5bc..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/RequiresValid.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.api.constraint;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-
-/**
- * JAVADOC
- */
-@ConstraintDeclaration
-@Retention( RetentionPolicy.RUNTIME )
-@Constraints( RequiresValid.RequiresValidConstraint.class )
-public @interface RequiresValid
-{
-    String value();
-
-    class RequiresValidConstraint
-        implements Constraint<RequiresValid, InteractionValidation>
-    {
-        @Override
-        public boolean isValid( RequiresValid requiresValid, InteractionValidation validation )
-        {
-            return validation.isValid( requiresValid.value() );
-        }
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/ServiceAvailable.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/ServiceAvailable.java
deleted file mode 100644
index 9789335..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/ServiceAvailable.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.api.constraint;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.server.api.ObjectSelection;
-
-/**
- * Annotate interaction methods with ServiceAvailable. They will only be valid
- * if a service with the given type is available.
- */
-@InteractionConstraintDeclaration( ServiceAvailable.ServiceAvailableConstraint.class )
-@Retention( RetentionPolicy.RUNTIME )
-public @interface ServiceAvailable
-{
-    Class value();
-
-    public class ServiceAvailableConstraint
-        implements InteractionConstraint<ServiceAvailable>
-    {
-        @Structure
-        Module module;
-
-        @Override
-        public boolean isValid( ServiceAvailable serviceAvailable, ObjectSelection objectSelection )
-        {
-            ServiceReference ref = module.findService( serviceAvailable.value() );
-            return ref != null && ref.isAvailable();
-        }
-    }
-}
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/package.html b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/package.html
deleted file mode 100644
index d894adc..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/constraint/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ReST Server Constraints.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/dci/Role.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/dci/Role.java
deleted file mode 100644
index 6ebcb2d..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/dci/Role.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.api.dci;
-
-/**
- * Base class for methodful roles
- */
-public class Role<T>
-    implements Comparable<Role<T>>
-{
-    // Self reference to the bound Data object
-    protected T self;
-
-    public Role()
-    {
-    }
-
-    public Role( T self )
-    {
-        this.self = self;
-    }
-
-    public void bind( T newSelf )
-    {
-        self = newSelf;
-    }
-
-    public T self()
-    {
-        return self;
-    }
-
-    @Override
-    public boolean equals( Object obj )
-    {
-        return obj != null && obj instanceof Role && self.equals( ( (Role) obj ).self );
-    }
-
-    @Override
-    public int compareTo( Role<T> role )
-    {
-        return ( (Comparable<T>) self ).compareTo( role.self );
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/dci/package.html b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/dci/package.html
deleted file mode 100644
index 22b6e5d..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/dci/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ReST Server DCI API.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/package.html b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/package.html
deleted file mode 100644
index d901874..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/api/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ReST Server API.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/assembler/RestServerAssembler.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/assembler/RestServerAssembler.java
deleted file mode 100644
index 2f4a888..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/assembler/RestServerAssembler.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.assembler;
-
-import java.lang.reflect.Modifier;
-import java.util.Properties;
-import org.apache.velocity.app.VelocityEngine;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.service.importer.NewObjectImporter;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ClassScanner;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.Specification;
-import org.qi4j.library.rest.server.restlet.InteractionConstraintsService;
-import org.qi4j.library.rest.server.restlet.RequestReaderDelegator;
-import org.qi4j.library.rest.server.restlet.ResponseWriterDelegator;
-import org.qi4j.library.rest.server.restlet.freemarker.ValueCompositeObjectWrapper;
-import org.qi4j.library.rest.server.restlet.requestreader.DefaultRequestReader;
-import org.qi4j.library.rest.server.restlet.responsewriter.AbstractResponseWriter;
-import org.qi4j.library.rest.server.restlet.responsewriter.DefaultResponseWriter;
-import org.qi4j.library.rest.server.spi.ResponseWriter;
-import org.restlet.service.MetadataService;
-
-import static org.qi4j.api.util.Classes.hasModifier;
-import static org.qi4j.api.util.Classes.isAssignableFrom;
-import static org.qi4j.bootstrap.ImportedServiceDeclaration.INSTANCE;
-import static org.qi4j.bootstrap.ImportedServiceDeclaration.NEW_OBJECT;
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Specifications.and;
-import static org.qi4j.functional.Specifications.not;
-
-/**
- * JAVADOC
- */
-public class RestServerAssembler
-    implements Assembler
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        Properties props = new Properties();
-        try
-        {
-            props.load( getClass().getResourceAsStream( "/velocity.properties" ) );
-
-            VelocityEngine velocity = new VelocityEngine( props );
-
-            module.importedServices( VelocityEngine.class )
-                .importedBy( INSTANCE ).setMetaInfo( velocity );
-        }
-        catch( Exception e )
-        {
-            throw new AssemblyException( "Could not load velocity properties", e );
-        }
-
-        freemarker.template.Configuration cfg = new freemarker.template.Configuration();
-        cfg.setClassForTemplateLoading( AbstractResponseWriter.class, "" );
-        cfg.setObjectWrapper( new ValueCompositeObjectWrapper() );
-
-        module.importedServices( freemarker.template.Configuration.class ).setMetaInfo( cfg );
-
-        module.importedServices( MetadataService.class );
-
-        module.importedServices( ResponseWriterDelegator.class )
-            .identifiedBy( "responsewriterdelegator" )
-            .importedBy( NEW_OBJECT )
-            .visibleIn( Visibility.layer );
-        module.objects( ResponseWriterDelegator.class );
-
-        module.importedServices( RequestReaderDelegator.class )
-            .identifiedBy( "requestreaderdelegator" )
-            .importedBy( NEW_OBJECT )
-            .visibleIn( Visibility.layer );
-        module.objects( RequestReaderDelegator.class );
-
-        module.importedServices( InteractionConstraintsService.class ).
-            importedBy( NewObjectImporter.class ).
-            visibleIn( Visibility.application );
-        module.objects( InteractionConstraintsService.class );
-
-        // Standard response writers
-        Iterable<Class<?>> writers = ClassScanner.findClasses( DefaultResponseWriter.class );
-        Specification<Class<?>> responseWriterClass = isAssignableFrom( ResponseWriter.class );
-        Specification<Class<?>> isNotAnAbstract = not( hasModifier( Modifier.ABSTRACT ) );
-        Iterable<Class<?>> candidates = filter( and( isNotAnAbstract, responseWriterClass ), writers );
-        for( Class<?> responseWriter : candidates )
-        {
-            module.objects( responseWriter );
-        }
-
-        // Standard request readers
-        module.objects( DefaultRequestReader.class );
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/assembler/package.html b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/assembler/package.html
deleted file mode 100644
index c66f3ab..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/assembler/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ReST Server Assembly.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/ConstraintViolationMessages.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/ConstraintViolationMessages.java
deleted file mode 100644
index d016c35..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/ConstraintViolationMessages.java
+++ /dev/null
@@ -1,84 +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.qi4j.library.rest.server.restlet;
-
-import java.lang.annotation.Annotation;
-import java.util.Locale;
-import java.util.ResourceBundle;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.qi4j.api.constraint.ConstraintViolation;
-
-/**
- * TODO
- */
-public class ConstraintViolationMessages
-{
-    public String getMessage( ConstraintViolation violation, Locale locale )
-        throws IllegalArgumentException
-    {
-        try
-        {
-            ResourceBundle bundle = ResourceBundle.getBundle( "ValidationMessages", locale );
-
-            Annotation annotation = violation.constraint();
-            String message;
-            try
-            {
-                message = (String) annotation.annotationType().getMethod( "message" ).invoke( annotation );
-            }
-            catch( Exception e1 )
-            {
-                message = "{" + annotation.annotationType().getName() + ".message" + "}";
-            }
-
-            while( message.startsWith( "{" ) )
-            {
-                message = bundle.getString( message.substring( 1, message.length() - 1 ) );
-            }
-
-            Pattern pattern = Pattern.compile( "\\{[^\\}]*\\}" );
-            String result = "";
-            Matcher matcher = pattern.matcher( message );
-            int start = 0;
-            while( matcher.find() )
-            {
-                String match = matcher.group();
-                match = match.substring( 1, match.length() - 1 );
-                result += message.substring( start, matcher.start() );
-
-                if( match.equals( "val" ) )
-                {
-                    result += violation.value() == null ? "null" : violation.value().toString();
-                }
-                else
-                {
-                    result += annotation.annotationType().getMethod( match ).invoke( annotation ).toString();
-                }
-                start = matcher.end();
-            }
-            result += message.substring( start );
-            return result;
-        }
-        catch( Exception e )
-        {
-            throw new IllegalArgumentException( "Could not deduce message", e );
-        }
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/ExtensionMediaTypeFilter.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/ExtensionMediaTypeFilter.java
deleted file mode 100644
index be31e3c..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/ExtensionMediaTypeFilter.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.restlet;
-
-import java.util.Collections;
-import java.util.List;
-import org.restlet.Context;
-import org.restlet.Request;
-import org.restlet.Response;
-import org.restlet.Restlet;
-import org.restlet.data.MediaType;
-import org.restlet.data.Metadata;
-import org.restlet.data.Preference;
-import org.restlet.routing.Filter;
-import org.restlet.service.MetadataService;
-
-/**
- * JAVADOC
- */
-public class ExtensionMediaTypeFilter
-    extends Filter
-{
-
-    public ExtensionMediaTypeFilter()
-    {
-    }
-
-    public ExtensionMediaTypeFilter( Context context )
-    {
-        super( context );
-    }
-
-    public ExtensionMediaTypeFilter( Context context, Restlet next )
-    {
-        super( context, next );
-    }
-
-    @Override
-    protected int beforeHandle( Request request, Response response )
-    {
-        List<String> segments = request.getResourceRef().getSegments();
-        if( segments.get( segments.size() - 1 ).equals( "" ) )
-        {
-            return Filter.CONTINUE;
-        }
-
-        String extensions = request.getResourceRef().getExtensions();
-        if( extensions != null )
-        {
-            int idx = extensions.lastIndexOf( "." );
-            if( idx != -1 )
-            {
-                extensions = extensions.substring( idx + 1 );
-            }
-
-            MetadataService metadataService = getApplication().getMetadataService();
-            Metadata metadata = metadataService.getMetadata( extensions );
-            if( metadata != null && metadata instanceof MediaType )
-            {
-                request.getClientInfo()
-                    .setAcceptedMediaTypes( Collections.singletonList( new Preference<MediaType>( (MediaType) metadata ) ) );
-                String path = request.getResourceRef().getPath();
-                path = path.substring( 0, path.length() - extensions.length() - 1 );
-                request.getResourceRef().setPath( path );
-            }
-        }
-
-        return Filter.CONTINUE;
-    }
-}
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/InteractionConstraints.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/InteractionConstraints.java
deleted file mode 100644
index fcd60c6..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/InteractionConstraints.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.restlet;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.server.api.ObjectSelection;
-
-/**
- * Service interface for checking whether a particular method or a whole class is not
- * valid at this point, for whatever reason (application state or authorization rules usually).
- */
-public interface InteractionConstraints
-{
-    public boolean isValid( Method method, ObjectSelection objectSelection, Module module );
-
-    public boolean isValid( Class resourceClass, ObjectSelection objectSelection, Module module );
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/InteractionConstraintsService.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/InteractionConstraintsService.java
deleted file mode 100644
index 4f8eedc..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/InteractionConstraintsService.java
+++ /dev/null
@@ -1,359 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.restlet;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.constraint.Constraint;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.object.NoSuchObjectException;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.server.api.ObjectSelection;
-import org.qi4j.library.rest.server.api.constraint.InteractionConstraint;
-import org.qi4j.library.rest.server.api.constraint.InteractionConstraintDeclaration;
-import org.qi4j.library.rest.server.api.constraint.InteractionValidation;
-import org.qi4j.library.rest.server.api.constraint.RequiresValid;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * JAVADOC
- */
-public class InteractionConstraintsService
-    implements InteractionConstraints
-{
-    @Structure
-    Module module;
-
-    Logger logger = LoggerFactory.getLogger( InteractionConstraintsService.class );
-
-    private Map<Method, InteractionConstraintsBinding> methodsConstraints = new ConcurrentHashMap<Method, InteractionConstraintsBinding>();
-    private Map<Class, InteractionConstraintsBinding> classConstraints = new ConcurrentHashMap<Class, InteractionConstraintsBinding>();
-
-    @Override
-    public boolean isValid( Method method, ObjectSelection objectSelection, Module module )
-    {
-        return getConstraints( method, module ).isValid( objectSelection );
-    }
-
-    @Override
-    public boolean isValid( Class resourceClass, ObjectSelection objectSelection, Module module )
-    {
-        return getConstraints( resourceClass, module ).isValid( objectSelection );
-    }
-
-    private InteractionConstraintsBinding getConstraints( Method method, Module module )
-    {
-        InteractionConstraintsBinding constraintBindings = methodsConstraints.get( method );
-        if( constraintBindings == null )
-        {
-            constraintBindings = findConstraints( method, module );
-            methodsConstraints.put( method, constraintBindings );
-        }
-        return constraintBindings;
-    }
-
-    private InteractionConstraintsBinding getConstraints( Class aClass, Module module )
-    {
-        InteractionConstraintsBinding constraintBindings = classConstraints.get( aClass );
-        if( constraintBindings == null )
-        {
-            constraintBindings = findConstraints( aClass, module );
-            classConstraints.put( aClass, constraintBindings );
-        }
-        return constraintBindings;
-    }
-
-    private InteractionConstraintsBinding findConstraints( Method method, Module module )
-    {
-        List<Binding> methodConstraintBindings = new ArrayList<Binding>();
-
-        for( Annotation annotation : method.getAnnotations() )
-        {
-            if( annotation.annotationType().equals( RequiresValid.class ) )
-            {
-                RequiresValid requiresValid = (RequiresValid) annotation;
-
-                Class contextClass = method.getDeclaringClass();
-                if( InteractionValidation.class.isAssignableFrom( contextClass ) )
-                {
-                    InteractionValidation validation = null;
-                    if( TransientComposite.class.isAssignableFrom( contextClass ) )
-                    {
-                        validation = (InteractionValidation) module.newTransient( contextClass );
-                    }
-                    else
-                    {
-                        validation = (InteractionValidation) module.newObject( contextClass );
-                    }
-                    methodConstraintBindings.add( new RequiresValidBinding( requiresValid, validation ) );
-                }
-            }
-            else if( annotation.annotationType().getAnnotation( ConstraintDeclaration.class ) != null )
-            {
-                Constraints constraints = annotation.annotationType().getAnnotation( Constraints.class );
-
-                for( Class<? extends Constraint<?, ?>> aClass : constraints.value() )
-                {
-                    try
-                    {
-                        Constraint<Annotation, Object> constraint = (Constraint<Annotation, Object>) aClass.newInstance();
-                        Class roleClass = (Class) ( (ParameterizedType) aClass.getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[ 1 ];
-                        ConstraintBinding constraintBinding = new ConstraintBinding( constraint, annotation, roleClass );
-                        methodConstraintBindings.add( constraintBinding );
-                    }
-                    catch( InstantiationException e )
-                    {
-                        e.printStackTrace();
-                    }
-                    catch( IllegalAccessException e )
-                    {
-                        e.printStackTrace();
-                    }
-                }
-            }
-            else if( annotation.annotationType().getAnnotation( InteractionConstraintDeclaration.class ) != null )
-            {
-                Class<? extends InteractionConstraint> constraintClass = annotation.annotationType()
-                    .getAnnotation( InteractionConstraintDeclaration.class )
-                    .value();
-                InteractionConstraint<Annotation> constraint = null;
-                try
-                {
-                    try
-                    {
-                        constraint = module.newObject( constraintClass );
-                    }
-                    catch( NoSuchObjectException e )
-                    {
-                        constraint = constraintClass.newInstance();
-                    }
-                }
-                catch( Exception e )
-                {
-                    continue; // Skip this constraint
-                }
-                InteractionConstraintBinding constraintBinding = new InteractionConstraintBinding( constraint, annotation );
-                methodConstraintBindings.add( constraintBinding );
-            }
-        }
-
-        if( methodConstraintBindings.isEmpty() )
-        {
-            methodConstraintBindings = null;
-        }
-
-        return new InteractionConstraintsBinding( methodConstraintBindings );
-    }
-
-    private InteractionConstraintsBinding findConstraints( Class aClass, Module module )
-    {
-        List<Binding> classConstraintBindings = new ArrayList<Binding>();
-
-        for( Annotation annotation : aClass.getAnnotations() )
-        {
-            if( annotation.annotationType().getAnnotation( ConstraintDeclaration.class ) != null )
-            {
-                Constraints constraints = annotation.annotationType().getAnnotation( Constraints.class );
-
-                for( Class<? extends Constraint<?, ?>> constraintClass : constraints.value() )
-                {
-                    try
-                    {
-                        Constraint<Annotation, Object> constraint = (Constraint<Annotation, Object>) constraintClass.newInstance();
-                        Class roleClass = (Class) ( (ParameterizedType) constraint.getClass()
-                            .getGenericInterfaces()[ 0 ] ).getActualTypeArguments()[ 1 ];
-                        ConstraintBinding constraintBinding = new ConstraintBinding( constraint, annotation, roleClass );
-                        classConstraintBindings.add( constraintBinding );
-                    }
-                    catch( InstantiationException e )
-                    {
-                        e.printStackTrace();
-                    }
-                    catch( IllegalAccessException e )
-                    {
-                        e.printStackTrace();
-                    }
-                }
-            }
-            else if( annotation.annotationType().getAnnotation( InteractionConstraintDeclaration.class ) != null )
-            {
-                Class<? extends InteractionConstraint> constraintClass = annotation.annotationType()
-                    .getAnnotation( InteractionConstraintDeclaration.class )
-                    .value();
-                InteractionConstraint<Annotation> constraint = null;
-                try
-                {
-                    try
-                    {
-                        constraint = module.newObject( constraintClass );
-                    }
-                    catch( NoSuchObjectException e )
-                    {
-                        constraint = constraintClass.newInstance();
-                    }
-                }
-                catch( Exception e )
-                {
-                    continue; // Skip this constraint
-                }
-                InteractionConstraintBinding constraintBinding = new InteractionConstraintBinding( constraint, annotation );
-                classConstraintBindings.add( constraintBinding );
-            }
-        }
-
-        if( classConstraintBindings.isEmpty() )
-        {
-            classConstraintBindings = null;
-        }
-
-        return new InteractionConstraintsBinding( classConstraintBindings );
-    }
-
-    interface Binding
-    {
-        boolean isValid( ObjectSelection objectSelection );
-    }
-
-    public static class InteractionConstraintsBinding
-    {
-        List<Binding> bindings;
-
-        public InteractionConstraintsBinding( List<Binding> bindings )
-        {
-            this.bindings = bindings;
-        }
-
-        public boolean isValid( ObjectSelection objectSelection )
-        {
-            if( bindings != null )
-            {
-                for( Binding constraintBinding : bindings )
-                {
-                    if( !constraintBinding.isValid( objectSelection ) )
-                    {
-                        return false;
-                    }
-                }
-            }
-
-            return true;
-        }
-    }
-
-    public class RequiresValidBinding
-        implements Binding
-    {
-        RequiresValid annotation;
-        private final InteractionValidation validation;
-
-        public RequiresValidBinding( RequiresValid annotation, InteractionValidation validation )
-        {
-            this.validation = validation;
-            this.annotation = annotation;
-        }
-
-        @Override
-        public boolean isValid( ObjectSelection objectSelection )
-        {
-            try
-            {
-                return validation.isValid( annotation.value() );
-            }
-            catch( IllegalArgumentException e )
-            {
-                return false;
-            }
-            catch( Throwable e )
-            {
-                logger.warn( "Could not check validation constraint for '" + annotation.value() + "'", e );
-                return false;
-            }
-        }
-    }
-
-    public class ConstraintBinding
-        implements Binding
-    {
-        Constraint<Annotation, Object> constraint;
-        Annotation annotation;
-        Class roleClass;
-
-        public ConstraintBinding( Constraint<Annotation, Object> constraint, Annotation annotation, Class roleClass )
-        {
-            this.constraint = constraint;
-            this.annotation = annotation;
-            this.roleClass = roleClass;
-        }
-
-        @Override
-        public boolean isValid( ObjectSelection objectSelection )
-        {
-            try
-            {
-                Object checkedObject = roleClass.equals( ObjectSelection.class ) ? objectSelection : objectSelection.get( roleClass );
-
-                return constraint.isValid( annotation, checkedObject );
-            }
-            catch( IllegalArgumentException e )
-            {
-                return false;
-            }
-            catch( Throwable e )
-            {
-                logger.warn( "Could not check constraint " + constraint.getClass().getName(), e );
-                return false;
-            }
-        }
-    }
-
-    public class InteractionConstraintBinding
-        implements Binding
-    {
-        InteractionConstraint<Annotation> constraint;
-        Annotation annotation;
-
-        public InteractionConstraintBinding( InteractionConstraint<Annotation> constraint, Annotation annotation )
-        {
-            this.constraint = constraint;
-            this.annotation = annotation;
-        }
-
-        @Override
-        public boolean isValid( ObjectSelection objectSelection )
-        {
-            try
-            {
-                return constraint.isValid( annotation, objectSelection );
-            }
-            catch( Throwable e )
-            {
-                logger.warn( "Could not check constraint " + constraint.getClass().getName(), e );
-                return false;
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/NullCommandResult.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/NullCommandResult.java
deleted file mode 100644
index 0cc78aa..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/NullCommandResult.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.restlet;
-
-import org.qi4j.library.rest.server.spi.CommandResult;
-
-/**
- * The command has no result at all (ignore it).
- */
-public class NullCommandResult
-    implements CommandResult
-{
-    @Override
-    public Object getResult()
-    {
-        return null;
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/RequestReaderDelegator.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/RequestReaderDelegator.java
deleted file mode 100644
index ee36947..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/RequestReaderDelegator.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.restlet;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ResourceBundle;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.InitializationException;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.server.spi.RequestReader;
-import org.restlet.Request;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Delegates to a list of potential readers. Register readers on startup.
- */
-public class RequestReaderDelegator
-    implements RequestReader
-{
-    private static final Object[] NULL_PARAMS = new Object[ 0 ];
-
-    List<RequestReader> requestReaders = new ArrayList<RequestReader>();
-
-    @Structure
-    Module module;
-
-    public void init( @Service Iterable<ServiceReference<RequestReader>> requestReaderReferences )
-        throws InitializationException
-    {
-        Logger logger = LoggerFactory.getLogger( getClass() );
-
-        // Add custom readers first
-        for( ServiceReference<RequestReader> requestReader : requestReaderReferences )
-        {
-            if( !requestReader.identity().equals( "requestreaderdelegator" ) )
-            {
-                logger.info( "Registered request reader:" + requestReader.identity() );
-                registerRequestReader( requestReader.get() );
-            }
-        }
-
-        // Add defaults
-        ResourceBundle defaultRequestReaders = ResourceBundle.getBundle( "org.qi4j.library.rest.server.rest-server" );
-
-        String requestReaderClasses = defaultRequestReaders.getString( "requestreaders" );
-        logger.info( "Using request readers:" + requestReaderClasses );
-        for( String className : requestReaderClasses.split( "," ) )
-        {
-            try
-            {
-                Class readerClass = module.classLoader().loadClass( className.trim() );
-                RequestReader writer = (RequestReader) module.newObject( readerClass );
-                registerRequestReader( writer );
-            }
-            catch( ClassNotFoundException e )
-            {
-                logger.warn( "Could not register request reader " + className, e );
-            }
-        }
-    }
-
-    public void registerRequestReader( RequestReader reader )
-    {
-        requestReaders.add( reader );
-    }
-
-    @Override
-    public Object[] readRequest( Request request, Method method )
-    {
-        if( method.getParameterTypes().length == 0 )
-        {
-            return NULL_PARAMS;
-        }
-
-        for( RequestReader requestReader : requestReaders )
-        {
-            Object[] arguments = requestReader.readRequest( request, method );
-
-            if( arguments != null )
-            {
-                return arguments;
-            }
-        }
-
-        return null;
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/ResponseWriterDelegator.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/ResponseWriterDelegator.java
deleted file mode 100644
index 554b57d..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/ResponseWriterDelegator.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.restlet;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ResourceBundle;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.InitializationException;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.server.spi.ResponseWriter;
-import org.restlet.Response;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Delegates to a list of potential writers. Register writers on startup.
- */
-public class ResponseWriterDelegator
-    implements ResponseWriter
-{
-    List<ResponseWriter> responseWriters = new ArrayList<ResponseWriter>();
-
-    @Structure
-    Module module;
-
-    public void init( @Service Iterable<ServiceReference<ResponseWriter>> resultWriters )
-        throws InitializationException
-    {
-        Logger logger = LoggerFactory.getLogger( getClass() );
-
-        // Add custom writers first
-        for( ServiceReference<ResponseWriter> resultWriter : resultWriters )
-        {
-            if( !resultWriter.identity().equals( "responsewriterdelegator" ) )
-            {
-                logger.info( "Registered result writer:" + resultWriter.identity() );
-                registerResultWriter( resultWriter.get() );
-            }
-        }
-
-        // Add defaults
-        ResourceBundle defaultResultWriters = ResourceBundle.getBundle( "org.qi4j.library.rest.server.rest-server" );
-
-        String resultWriterClasses = defaultResultWriters.getString( "responsewriters" );
-        logger.info( "Using response writers:" + resultWriterClasses );
-        for( String className : resultWriterClasses.split( "," ) )
-        {
-            try
-            {
-                Class writerClass = module.classLoader().loadClass( className.trim() );
-                ResponseWriter writer = (ResponseWriter) module.newObject( writerClass );
-                registerResultWriter( writer );
-            }
-            catch( ClassNotFoundException e )
-            {
-                logger.warn( "Could not register response writer " + className, e );
-            }
-        }
-    }
-
-    public void registerResultWriter( ResponseWriter writer )
-    {
-        responseWriters.add( writer );
-    }
-
-    @Override
-    public boolean writeResponse( Object result, Response response )
-    {
-        for( ResponseWriter responseWriter : responseWriters )
-        {
-            if( responseWriter.writeResponse( result, response ) )
-            {
-                return true;
-            }
-        }
-        return false;
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/freemarker/ValueCompositeObjectWrapper.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/freemarker/ValueCompositeObjectWrapper.java
deleted file mode 100644
index 0be738d..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/freemarker/ValueCompositeObjectWrapper.java
+++ /dev/null
@@ -1,45 +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.qi4j.library.rest.server.restlet.freemarker;
-
-import freemarker.template.DefaultObjectWrapper;
-import freemarker.template.TemplateModel;
-import freemarker.template.TemplateModelException;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * ObjectWrapper implementation that adds support for ValueComposites, exposing Property state.
- */
-public class ValueCompositeObjectWrapper
-    extends DefaultObjectWrapper
-{
-    @Override
-    public TemplateModel wrap( Object obj )
-        throws TemplateModelException
-    {
-        if( obj instanceof ValueComposite )
-        {
-            return new ValueCompositeTemplateModel( (ValueComposite) obj, this );
-        }
-        else
-        {
-            return super.wrap( obj );
-        }
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/freemarker/ValueCompositeTemplateModel.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/freemarker/ValueCompositeTemplateModel.java
deleted file mode 100644
index e6524c2..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/freemarker/ValueCompositeTemplateModel.java
+++ /dev/null
@@ -1,125 +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.qi4j.library.rest.server.restlet.freemarker;
-
-import freemarker.template.ObjectWrapper;
-import freemarker.template.TemplateCollectionModel;
-import freemarker.template.TemplateHashModelEx;
-import freemarker.template.TemplateModel;
-import freemarker.template.TemplateModelException;
-import freemarker.template.TemplateScalarModel;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-
-/**
- * TODO
- */
-public class ValueCompositeTemplateModel
-    implements TemplateHashModelEx, TemplateScalarModel
-{
-    private ValueComposite composite;
-    private ObjectWrapper wrapper;
-    private ValueDescriptor descriptor;
-
-    public ValueCompositeTemplateModel( ValueComposite composite, ObjectWrapper wrapper )
-    {
-        this.composite = composite;
-        this.wrapper = wrapper;
-        descriptor = (ValueDescriptor) Qi4j.FUNCTION_DESCRIPTOR_FOR.map( composite );
-    }
-
-    @Override
-    public int size()
-        throws TemplateModelException
-    {
-        return (int) Iterables.count( descriptor.state().properties() );
-    }
-
-    @Override
-    public TemplateCollectionModel keys()
-        throws TemplateModelException
-    {
-        return (TemplateCollectionModel) wrapper.wrap( Iterables.map( new Function<PropertyDescriptor, String>()
-        {
-            @Override
-            public String map( PropertyDescriptor propertyDescriptor )
-            {
-                return propertyDescriptor.qualifiedName().name();
-            }
-        }, descriptor.state().properties() ).iterator() );
-    }
-
-    @Override
-    public TemplateCollectionModel values()
-        throws TemplateModelException
-    {
-        return (TemplateCollectionModel) wrapper.wrap( Iterables.map( new Function<Property<?>, Object>()
-        {
-            @Override
-            public Object map( Property<?> objectProperty )
-            {
-                try
-                {
-                    return wrapper.wrap( objectProperty.get() );
-                }
-                catch( TemplateModelException e )
-                {
-                    throw new IllegalStateException( e );
-                }
-            }
-        }, Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF.map( composite ).state().properties() ).iterator() );
-    }
-
-    @Override
-    public TemplateModel get( String key )
-        throws TemplateModelException
-    {
-        try
-        {
-            return wrapper.wrap( Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF
-                                     .map( composite )
-                                     .state()
-                                     .propertyFor( descriptor.state().findPropertyModelByName( key ).accessor() )
-                                     .get() );
-        }
-        catch( IllegalArgumentException e )
-        {
-            return null;
-        }
-    }
-
-    @Override
-    public boolean isEmpty()
-        throws TemplateModelException
-    {
-        return size() == 0;
-    }
-
-    @Override
-    public String getAsString()
-        throws TemplateModelException
-    {
-        return composite.toString();
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/freemarker/package.html b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/freemarker/package.html
deleted file mode 100644
index b018992..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/freemarker/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Restlet ReST Server FreeMarker Templating.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/package.html b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/package.html
deleted file mode 100644
index 3856933..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Restlet ReST Server.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/requestreader/DefaultRequestReader.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/requestreader/DefaultRequestReader.java
deleted file mode 100644
index 49d627b..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/requestreader/DefaultRequestReader.java
+++ /dev/null
@@ -1,499 +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.qi4j.library.rest.server.restlet.requestreader;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Map;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.constraint.Name;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.service.qualifier.Tagged;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.util.Dates;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.api.value.ValueDeserializer;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.api.value.ValueSerializationException;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.library.rest.server.spi.RequestReader;
-import org.restlet.Request;
-import org.restlet.Response;
-import org.restlet.data.CharacterSet;
-import org.restlet.data.Form;
-import org.restlet.data.MediaType;
-import org.restlet.data.Parameter;
-import org.restlet.data.Status;
-import org.restlet.representation.EmptyRepresentation;
-import org.restlet.representation.Representation;
-import org.restlet.resource.ResourceException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.qi4j.api.util.Annotations.isType;
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Iterables.first;
-import static org.qi4j.functional.Iterables.iterable;
-import static org.qi4j.functional.Iterables.matchesAny;
-
-/**
- * Convert request into method arguments.
- *
- * TODO: This should be split into many classes to handle the different cases.
- * TODO: This does not support ManyAssociations
- * TODO: This does not support NamedAssociations
- */
-public class DefaultRequestReader
-    implements RequestReader
-{
-    private static final Logger LOGGER = LoggerFactory.getLogger( DefaultRequestReader.class );
-    @Structure
-    private Module module;
-
-    @Service
-    @Tagged( ValueSerialization.Formats.JSON )
-    private ValueDeserializer valueDeserializer;
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    public Object[] readRequest( Request request, Method method )
-        throws ResourceException
-    {
-        if( request.getMethod().equals( org.restlet.data.Method.GET ) )
-        {
-            Object[] args = new Object[ method.getParameterTypes().length ];
-
-            Form queryAsForm = Request.getCurrent().getResourceRef().getQueryAsForm();
-            Form entityAsForm;
-            Representation representation = Request.getCurrent().getEntity();
-            if( representation != null && !EmptyRepresentation.class.isInstance( representation ) )
-            {
-                entityAsForm = new Form( representation );
-            }
-            else
-            {
-                entityAsForm = new Form();
-            }
-
-            if( queryAsForm.isEmpty() && entityAsForm.isEmpty() )
-            {
-                // Nothing submitted yet - show form
-                return null;
-            }
-
-            if( args.length == 1 )
-            {
-                if( ValueComposite.class.isAssignableFrom( method.getParameterTypes()[0] ) )
-                {
-                    Class<?> valueType = method.getParameterTypes()[0];
-                    args[0] = getValueFromForm( (Class<ValueComposite>) valueType, queryAsForm, entityAsForm );
-                    return args;
-                }
-                else if( Form.class.equals( method.getParameterTypes()[0] ) )
-                {
-                    args[0] = queryAsForm.isEmpty() ? entityAsForm : queryAsForm;
-                    return args;
-                }
-                else if( Response.class.equals( method.getParameterTypes()[0] ) )
-                {
-                    args[0] = Response.getCurrent();
-                    return args;
-                }
-            }
-            parseMethodArguments( method, args, queryAsForm, entityAsForm );
-
-            return args;
-        }
-        else
-        {
-
-            Object[] args = new Object[ method.getParameterTypes().length ];
-            Class<? extends ValueComposite> commandType = (Class<? extends ValueComposite>) method.getParameterTypes()[0];
-            if( method.getParameterTypes()[0].equals( Response.class ) )
-            {
-                return new Object[]
-                {
-                    Response.getCurrent()
-                };
-            }
-            Representation representation = Request.getCurrent().getEntity();
-            MediaType type = representation.getMediaType();
-            if( type == null )
-            {
-                Form queryAsForm = Request.getCurrent().getResourceRef().getQueryAsForm( CharacterSet.UTF_8 );
-                if( ValueComposite.class.isAssignableFrom( method.getParameterTypes()[0] ) )
-                {
-                    args[0] = getValueFromForm( commandType, queryAsForm, new Form() );
-                }
-                else
-                {
-                    parseMethodArguments( method, args, queryAsForm, new Form() );
-                }
-                return args;
-            }
-            else
-            {
-                if( method.getParameterTypes()[0].equals( Representation.class ) )
-                {
-                    // Command method takes Representation as input
-                    return new Object[]
-                    {
-                        representation
-                    };
-                }
-                else if( method.getParameterTypes()[0].equals( Form.class ) )
-                {
-                    // Command method takes Form as input
-                    return new Object[]
-                    {
-                        new Form( representation )
-                    };
-                }
-                else if( ValueComposite.class.isAssignableFrom( method.getParameterTypes()[0] ) )
-                {
-                    // Need to parse input into ValueComposite
-                    if( type.equals( MediaType.APPLICATION_JSON ) )
-                    {
-                        String json = Request.getCurrent().getEntityAsText();
-                        if( json == null )
-                        {
-                            LOGGER.error( "Restlet bug http://restlet.tigris.org/issues/show_bug.cgi?id=843 detected. "
-                                          + "Notify developers!" );
-                            throw new ResourceException( Status.SERVER_ERROR_INTERNAL,
-                                                         "Bug in Restlet encountered; notify developers!" );
-                        }
-
-                        Object command = module.newValueFromSerializedState( commandType, json );
-                        args[0] = command;
-                        return args;
-                    }
-                    else if( type.equals( MediaType.TEXT_PLAIN ) )
-                    {
-                        String text = Request.getCurrent().getEntityAsText();
-                        if( text == null )
-                        {
-                            LOGGER.error( "Restlet bug http://restlet.tigris.org/issues/show_bug.cgi?id=843 detected. "
-                                          + "Notify developers!" );
-                            throw new ResourceException( Status.SERVER_ERROR_INTERNAL,
-                                                         "Bug in Restlet encountered; notify developers!" );
-                        }
-                        args[0] = text;
-                        return args;
-                    }
-                    else if( type.equals( ( MediaType.APPLICATION_WWW_FORM ) ) )
-                    {
-
-                        Form queryAsForm = Request.getCurrent().getResourceRef().getQueryAsForm();
-                        Form entityAsForm;
-                        if( representation != null
-                            && !EmptyRepresentation.class.isInstance( representation )
-                            && representation.isAvailable() )
-                        {
-                            entityAsForm = new Form( representation );
-                        }
-                        else
-                        {
-                            entityAsForm = new Form();
-                        }
-
-                        Class<?> valueType = method.getParameterTypes()[0];
-                        args[0] = getValueFromForm( (Class<ValueComposite>) valueType, queryAsForm, entityAsForm );
-                        return args;
-                    }
-                    else
-                    {
-                        throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST,
-                                                     "Command has to be in JSON format" );
-                    }
-                }
-                else if( method.getParameterTypes()[0].isInterface() && method.getParameterTypes().length == 1 )
-                {
-                    Form queryAsForm = Request.getCurrent().getResourceRef().getQueryAsForm();
-                    Form entityAsForm;
-                    if( representation != null
-                        && !EmptyRepresentation.class.isInstance( representation )
-                        && representation.isAvailable() )
-                    {
-                        entityAsForm = new Form( representation );
-                    }
-                    else
-                    {
-                        entityAsForm = new Form();
-                    }
-
-                    args[0] = module.currentUnitOfWork().get( method.getParameterTypes()[0],
-                                                              getValue( "entity", queryAsForm, entityAsForm ) );
-
-                    return args;
-                }
-                else
-                {
-                    Form queryAsForm = Request.getCurrent().getResourceRef().getQueryAsForm();
-                    Form entityAsForm;
-                    if( representation != null
-                        && !EmptyRepresentation.class.isInstance( representation )
-                        && representation.isAvailable() )
-                    {
-                        entityAsForm = new Form( representation );
-                    }
-                    else
-                    {
-                        entityAsForm = new Form();
-                    }
-
-                    parseMethodArguments( method, args, queryAsForm, entityAsForm );
-
-                    return args;
-                }
-            }
-        }
-    }
-
-    private ValueComposite getValueFromForm( Class<? extends ValueComposite> valueType,
-                                             final Form queryAsForm,
-                                             final Form entityAsForm
-    )
-    {
-        ValueBuilder<? extends ValueComposite> builder = module.newValueBuilderWithState(
-            valueType,
-            new Function<PropertyDescriptor, Object>()
-        {
-            @Override
-            public Object map( PropertyDescriptor propertyDescriptor )
-            {
-                Parameter param = queryAsForm.getFirst( propertyDescriptor.qualifiedName().name() );
-
-                if( param == null )
-                {
-                    param = entityAsForm.getFirst( propertyDescriptor.qualifiedName().name() );
-                }
-
-                if( param != null )
-                {
-                    String value = param.getValue();
-                    if( value != null )
-                    {
-                        try
-                        {
-                            return valueDeserializer.deserialize( propertyDescriptor.valueType(), value );
-                        }
-                        catch( ValueSerializationException e )
-                        {
-                            throw new IllegalArgumentException( "Query parameter has invalid JSON format", e );
-                        }
-                    }
-                }
-
-                return null;
-            }
-            },
-            new Function<AssociationDescriptor, EntityReference>()
-            {
-                @Override
-                public EntityReference map( AssociationDescriptor associationDescriptor )
-                {
-                    Parameter param = queryAsForm.getFirst( associationDescriptor.qualifiedName().name() );
-
-                    if( param == null )
-                    {
-                        param = entityAsForm.getFirst( associationDescriptor.qualifiedName().name() );
-                    }
-
-                    if( param != null )
-                    {
-                        return EntityReference.parseEntityReference( param.getValue() );
-                    }
-                    else
-                    {
-                        return null;
-                    }
-                }
-            },
-            new Function<AssociationDescriptor, Iterable<EntityReference>>()
-            {
-                @Override
-                public Iterable<EntityReference> map( AssociationDescriptor associationDescriptor )
-                {
-                    // TODO
-                    return Iterables.empty();
-                }
-            },
-            new Function<AssociationDescriptor, Map<String, EntityReference>>()
-            {
-                @Override
-                public Map<String, EntityReference> map( AssociationDescriptor from )
-                {
-                    // TODO
-                    return Collections.emptyMap();
-                }
-            }
-        );
-
-        return builder.newInstance();
-    }
-
-    @SuppressWarnings( "unchecked" )
-    private void parseMethodArguments( Method method, Object[] args, Form queryAsForm, Form entityAsForm )
-    {
-        // Parse each argument separately using the @Name annotation as help
-        int idx = 0;
-        for( Annotation[] annotations : method.getParameterAnnotations() )
-        {
-            Name name = (Name) first( filter( isType( Name.class ), iterable( annotations ) ) );
-
-            if( name == null )
-            {
-                throw new IllegalStateException( "No @Name annotation found on parameter of method:" + method );
-            }
-
-            String argString = getValue( name.value(), queryAsForm, entityAsForm );
-
-            // Parameter conversion
-            Class<?> parameterType = method.getParameterTypes()[idx];
-            Object arg = null;
-            if( parameterType.equals( String.class ) )
-            {
-                arg = argString;
-            }
-            else if( parameterType.equals( EntityReference.class ) )
-            {
-                arg = EntityReference.parseEntityReference( argString );
-            }
-            else if( parameterType.isEnum() )
-            {
-                arg = Enum.valueOf( (Class<Enum>) parameterType, argString );
-            }
-            else if( Integer.TYPE.isAssignableFrom( parameterType ) )
-            {
-                arg = Integer.valueOf( argString );
-            }
-            else if( Integer.class.isAssignableFrom( parameterType ) )
-            {
-                if( argString != null )
-                {
-                    arg = Integer.valueOf( argString );
-                }
-            }
-            else if( Long.TYPE.isAssignableFrom( parameterType ) )
-            {
-                arg = Long.valueOf( argString );
-            }
-            else if( Long.class.isAssignableFrom( parameterType ) )
-            {
-                if( argString != null )
-                {
-                    arg = Long.valueOf( argString );
-                }
-            }
-            else if( Short.TYPE.isAssignableFrom( parameterType ) )
-            {
-                arg = Short.valueOf( argString );
-            }
-            else if( Short.class.isAssignableFrom( parameterType ) )
-            {
-                if( argString != null )
-                {
-                    arg = Short.valueOf( argString );
-                }
-            }
-            else if( Double.TYPE.isAssignableFrom( parameterType ) )
-            {
-                arg = Double.valueOf( argString );
-            }
-            else if( Double.class.isAssignableFrom( parameterType ) )
-            {
-                if( argString != null )
-                {
-                    arg = Double.valueOf( argString );
-                }
-            }
-            else if( Float.TYPE.isAssignableFrom( parameterType ) )
-            {
-                arg = Float.valueOf( argString );
-            }
-            else if( Float.class.isAssignableFrom( parameterType ) )
-            {
-                if( argString != null )
-                {
-                    arg = Float.valueOf( argString );
-                }
-            }
-            else if( Character.TYPE.isAssignableFrom( parameterType ) )
-            {
-                arg = argString.charAt( 0 );
-            }
-            else if( Character.class.isAssignableFrom( parameterType ) )
-            {
-                if( argString != null )
-                {
-                    arg = argString.charAt( 0 );
-                }
-            }
-            else if( Boolean.TYPE.isAssignableFrom( parameterType ) )
-            {
-                arg = Boolean.valueOf( argString );
-            }
-            else if( Boolean.class.isAssignableFrom( parameterType ) )
-            {
-                if( argString != null )
-                {
-                    arg = Boolean.valueOf( argString );
-                }
-            }
-            else if( Date.class.isAssignableFrom( parameterType ) )
-            {
-                arg = Dates.fromString( argString );
-            }
-            else if( parameterType.isInterface() )
-            {
-                arg = module.currentUnitOfWork().get( parameterType, argString );
-            }
-            else
-            {
-                throw new IllegalArgumentException( "Don't know how to parse parameter " + name.value()
-                                                    + " of type " + parameterType.getName() );
-            }
-
-            if( arg == null && !matchesAny( isType( Optional.class ), iterable( annotations ) ) )
-            {
-                throw new IllegalArgumentException( "Parameter " + name.value() + " was not set" );
-            }
-
-            args[idx++] = arg;
-        }
-    }
-
-    private String getValue( String name, Form queryAsForm, Form entityAsForm )
-    {
-        String value = queryAsForm.getFirstValue( name );
-        if( value == null )
-        {
-            value = entityAsForm.getFirstValue( name );
-        }
-        return value;
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/requestreader/package.html b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/requestreader/package.html
deleted file mode 100644
index 0b92e29..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/requestreader/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Restlet ReST Server Request Readers.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/AbstractResponseWriter.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/AbstractResponseWriter.java
deleted file mode 100644
index 29ee2c9..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/AbstractResponseWriter.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.restlet.responsewriter;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import org.qi4j.library.rest.server.spi.ResponseWriter;
-import org.restlet.Request;
-import org.restlet.data.CharacterSet;
-import org.restlet.data.Language;
-import org.restlet.data.MediaType;
-import org.restlet.representation.Variant;
-
-/**
- * Helper methods for ResponseWriters
- */
-public abstract class AbstractResponseWriter
-    implements ResponseWriter
-{
-    protected static List<Language> ENGLISH = Arrays.asList( Language.ENGLISH );
-
-    protected Variant getVariant( Request request,
-                                  List<Language> possibleLanguages,
-                                  List<MediaType> possibleMediaTypes
-    )
-    {
-        Language language = request.getClientInfo().getPreferredLanguage( possibleLanguages );
-
-        if( language == null )
-        {
-            language = possibleLanguages.get( 0 );
-        }
-
-        MediaType responseType = request.getClientInfo().getPreferredMediaType( possibleMediaTypes );
-
-        if( responseType == null && request.getClientInfo()
-                                        .getPreferredMediaType( Collections.singletonList( MediaType.ALL ) ) == MediaType.ALL )
-        {
-            responseType = possibleMediaTypes.get( 0 );
-        }
-
-        Variant variant = new Variant( responseType, language );
-        variant.setCharacterSet( CharacterSet.UTF_8 );
-
-        return variant;
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/DefaultResponseWriter.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/DefaultResponseWriter.java
deleted file mode 100644
index a994ef3..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/DefaultResponseWriter.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.restlet.responsewriter;
-
-import java.util.Arrays;
-import java.util.List;
-import org.restlet.Response;
-import org.restlet.data.MediaType;
-import org.restlet.representation.StringRepresentation;
-import org.restlet.resource.ResourceException;
-
-/**
- * Handles simple types and serialize to JSON
- */
-public class DefaultResponseWriter
-    extends AbstractResponseWriter
-{
-    private static final List<MediaType> supportedMediaTypes = Arrays.asList( MediaType.APPLICATION_JSON );
-
-    @Override
-    public boolean writeResponse( final Object result, final Response response )
-        throws ResourceException
-    {
-        MediaType type = getVariant( response.getRequest(), ENGLISH, supportedMediaTypes ).getMediaType();
-        if( MediaType.APPLICATION_JSON.equals( type ) )
-        {
-            if( result instanceof String || result instanceof Number || result instanceof Boolean )
-            {
-                StringRepresentation representation = new StringRepresentation( result.toString(),
-                                                                                MediaType.APPLICATION_JSON );
-
-                response.setEntity( representation );
-
-                return true;
-            }
-        }
-
-        return false;
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/FormResponseWriter.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/FormResponseWriter.java
deleted file mode 100644
index 050a64e..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/FormResponseWriter.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.restlet.responsewriter;
-
-import freemarker.template.Configuration;
-import freemarker.template.Template;
-import freemarker.template.TemplateException;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.api.injection.scope.Service;
-import org.restlet.Response;
-import org.restlet.data.Form;
-import org.restlet.data.MediaType;
-import org.restlet.data.Parameter;
-import org.restlet.representation.Representation;
-import org.restlet.representation.StringRepresentation;
-import org.restlet.representation.WriterRepresentation;
-import org.restlet.resource.ResourceException;
-
-/**
- * Handles Restlet Form
- */
-public class FormResponseWriter
-    extends AbstractResponseWriter
-{
-    private static final List<MediaType> supportedMediaTypes = Arrays.asList( MediaType.TEXT_HTML, MediaType.APPLICATION_JSON );
-
-    @Service
-    private Configuration cfg;
-
-    @Override
-    public boolean writeResponse( final Object result, final Response response )
-        throws ResourceException
-    {
-        if( result instanceof Form )
-        {
-            MediaType type = getVariant( response.getRequest(), ENGLISH, supportedMediaTypes ).getMediaType();
-            if( MediaType.APPLICATION_JSON.equals( type ) )
-            {
-                JSONObject json = new JSONObject();
-                Form form = (Form) result;
-                try
-                {
-                    for( Parameter parameter : form )
-                    {
-                        String value = parameter.getValue();
-                        if( value == null )
-                        {
-                            json.put( parameter.getName(), JSONObject.NULL );
-                        }
-                        else
-                        {
-                            json.put( parameter.getName(), value );
-                        }
-                    }
-                }
-                catch( JSONException e )
-                {
-                    e.printStackTrace();
-                }
-
-                StringRepresentation representation
-                    = new StringRepresentation( json.toString(), MediaType.APPLICATION_JSON );
-                response.setEntity( representation );
-
-                return true;
-            }
-            else if( MediaType.TEXT_HTML.equals( type ) )
-            {
-                Representation rep = new WriterRepresentation( MediaType.TEXT_HTML )
-                {
-                    @Override
-                    public void write( Writer writer )
-                        throws IOException
-                    {
-                        Map<String, Object> root = new HashMap<String, Object>();
-                        root.put( "request", response.getRequest() );
-                        root.put( "response", response );
-                        root.put( "result", result );
-                        try
-                        {
-                            Template formHtmlTemplate = cfg.getTemplate( "form.htm" );
-                            formHtmlTemplate.process( root, writer );
-                        }
-                        catch( TemplateException e )
-                        {
-                            throw new IOException( e );
-                        }
-                    }
-                };
-                response.setEntity( rep );
-                return true;
-            }
-        }
-        return false;
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/JSONResponseWriter.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/JSONResponseWriter.java
deleted file mode 100644
index a62754b..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/JSONResponseWriter.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.restlet.responsewriter;
-
-import java.util.Arrays;
-import java.util.List;
-import org.json.JSONObject;
-import org.restlet.Response;
-import org.restlet.data.MediaType;
-import org.restlet.representation.StringRepresentation;
-import org.restlet.resource.ResourceException;
-
-/**
- * Handles JSONObject output
- */
-public class JSONResponseWriter extends AbstractResponseWriter
-{
-    private static final List<MediaType> supportedMediaTypes = Arrays.asList( MediaType.TEXT_HTML, MediaType.APPLICATION_JSON );
-
-    @Override
-    public boolean writeResponse( final Object result, final Response response )
-        throws ResourceException
-    {
-        if( result instanceof JSONObject )
-        {
-            MediaType type = getVariant( response.getRequest(), ENGLISH, supportedMediaTypes ).getMediaType();
-            if( MediaType.APPLICATION_JSON.equals( type ) )
-            {
-                JSONObject json = (JSONObject) result;
-                StringRepresentation representation
-                    = new StringRepresentation( json.toString(), MediaType.APPLICATION_JSON );
-                response.setEntity( representation );
-                return true;
-            }
-            else if( MediaType.TEXT_HTML.equals( type ) )
-            {
-                JSONObject json = (JSONObject) result;
-                StringRepresentation representation
-                    = new StringRepresentation( json.toString(), MediaType.TEXT_HTML );
-                response.setEntity( representation );
-                return true;
-            }
-        }
-        return false;
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/LinksResponseWriter.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/LinksResponseWriter.java
deleted file mode 100644
index 834f5bb..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/LinksResponseWriter.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.restlet.responsewriter;
-
-import freemarker.template.Configuration;
-import freemarker.template.TemplateException;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.library.rest.common.link.Link;
-import org.qi4j.library.rest.common.link.Links;
-import org.restlet.Response;
-import org.restlet.data.MediaType;
-import org.restlet.data.Reference;
-import org.restlet.data.Status;
-import org.restlet.representation.Representation;
-import org.restlet.representation.StringRepresentation;
-import org.restlet.representation.WriterRepresentation;
-import org.restlet.resource.ResourceException;
-
-/**
- * JAVADOC
- */
-public class LinksResponseWriter
-    extends AbstractResponseWriter
-{
-    private static final List<MediaType> supportedLinkMediaTypes = Arrays.asList( MediaType.APPLICATION_JSON );
-    private static final List<MediaType> supportedLinksMediaTypes = Arrays.asList( MediaType.TEXT_HTML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_ATOM );
-
-    @Service
-    Configuration cfg;
-
-    @Override
-    public boolean writeResponse( final Object result, final Response response )
-        throws ResourceException
-    {
-        if( result instanceof Link )
-        {
-            MediaType type = getVariant( response.getRequest(), ENGLISH, supportedLinkMediaTypes ).getMediaType();
-            if( MediaType.APPLICATION_JSON.equals( type ) )
-            {
-                response.setEntity( new StringRepresentation( ( (Link) result ).toString(), MediaType.APPLICATION_JSON ) );
-                return true;
-            }
-            else
-            {
-                response.setStatus( Status.REDIRECTION_TEMPORARY );
-                Link link = (Link) result;
-                Reference reference = new Reference( response.getRequest().getResourceRef(), link.href().get() );
-                response.setLocationRef( reference );
-                return true;
-            }
-        }
-        else if( result instanceof Links )
-        {
-            MediaType type = getVariant( response.getRequest(), ENGLISH, supportedLinksMediaTypes ).getMediaType();
-            Representation rep;
-            if( MediaType.APPLICATION_JSON.equals( type ) )
-            {
-                rep = createJsonRepresentation( (Links) result );
-            }
-            else if( MediaType.TEXT_HTML.equals( type ) )
-            {
-                rep = createTextHtmlRepresentation( result, response );
-            }
-            else if( MediaType.APPLICATION_ATOM.equals( type ) )
-            {
-                rep = createAtomRepresentation( result, response );
-            }
-            else
-            {
-                return false;
-            }
-            response.setEntity( rep );
-            return true;
-        }
-        return false;
-    }
-
-    private StringRepresentation createJsonRepresentation( Links result )
-    {
-        return new StringRepresentation( result.toString(), MediaType.APPLICATION_JSON );
-    }
-
-    private Representation createTextHtmlRepresentation( final Object result, final Response response )
-    {
-        return new WriterRepresentation( MediaType.TEXT_HTML )
-                    {
-                        @Override
-                        public void write( Writer writer )
-                            throws IOException
-                        {
-                            Map<String, Object> context = new HashMap<String, Object>();
-                            context.put( "request", response.getRequest() );
-                            context.put( "response", response );
-                            context.put( "result", result );
-                            try
-                            {
-                                cfg.getTemplate( "links.htm" ).process( context, writer );
-                            }
-                            catch( TemplateException e )
-                            {
-                                throw new IOException( e );
-                            }
-                        }
-                    };
-    }
-
-    private Representation createAtomRepresentation( final Object result, final Response response )
-    {
-        return new WriterRepresentation( MediaType.APPLICATION_ATOM )
-        {
-            @Override
-            public void write( Writer writer )
-                throws IOException
-            {
-                Map<String, Object> context = new HashMap<String, Object>();
-                context.put( "request", response.getRequest() );
-                context.put( "response", response );
-                context.put( "result", result );
-                try
-                {
-                    cfg.getTemplate( "links.atom" ).process( context, writer );
-                }
-                catch( TemplateException e )
-                {
-                    throw new IOException( e );
-                }
-            }
-        };
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/ResourceResponseWriter.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/ResourceResponseWriter.java
deleted file mode 100644
index 640bb13..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/ResourceResponseWriter.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.restlet.responsewriter;
-
-import freemarker.template.Configuration;
-import freemarker.template.TemplateException;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.functional.Iterables;
-import org.qi4j.library.rest.common.Resource;
-import org.qi4j.library.rest.common.link.LinksUtil;
-import org.restlet.Response;
-import org.restlet.data.MediaType;
-import org.restlet.data.Method;
-import org.restlet.representation.Representation;
-import org.restlet.representation.StringRepresentation;
-import org.restlet.representation.WriterRepresentation;
-import org.restlet.resource.ResourceException;
-
-/**
- * ResponseWriter for ResourceValues
- */
-public class ResourceResponseWriter extends AbstractResponseWriter
-{
-    private static final List<MediaType> supportedMediaTypes = Arrays.asList( MediaType.TEXT_HTML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_ATOM );
-
-    @Service
-    private Configuration cfg;
-
-    @Override
-    public boolean writeResponse( final Object result, final Response response )
-        throws ResourceException
-    {
-        if( result instanceof Resource )
-        {
-            Resource resourceValue = (Resource) result;
-
-            // Allowed methods
-            response.getAllowedMethods().add( Method.GET );
-            if( Iterables.matchesAny( LinksUtil.withRel( "delete" ), resourceValue.commands().get() ) )
-            {
-                response.getAllowedMethods().add( Method.DELETE );
-            }
-            if( Iterables.matchesAny( LinksUtil.withRel( "update" ), resourceValue.commands().get() ) )
-            {
-                response.getAllowedMethods().add( Method.PUT );
-            }
-
-            // Response according to what client accepts
-            MediaType type = getVariant( response.getRequest(), ENGLISH, supportedMediaTypes ).getMediaType();
-            if( MediaType.APPLICATION_JSON.equals( type ) )
-            {
-                response.setEntity( new StringRepresentation( resourceValue.toString(), MediaType.APPLICATION_JSON ) );
-                return true;
-            }
-            else if( MediaType.TEXT_HTML.equals( type ) )
-            {
-                Representation rep = new WriterRepresentation( MediaType.TEXT_HTML )
-                {
-                    @Override
-                    public void write( Writer writer )
-                        throws IOException
-                    {
-                        Map<String, Object> context = new HashMap<String, Object>();
-                        context.put( "request", response.getRequest() );
-                        context.put( "response", response );
-                        context.put( "result", result );
-                        try
-                        {
-                            cfg.getTemplate( "resource.htm" ).process( context, writer );
-                        }
-                        catch( TemplateException e )
-                        {
-                            throw new IOException( e );
-                        }
-                    }
-                };
-                response.setEntity( rep );
-                return true;
-            }
-        }
-
-        return false;
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/ResourceTemplateResponseWriter.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/ResourceTemplateResponseWriter.java
deleted file mode 100644
index d117ca1..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/ResourceTemplateResponseWriter.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.restlet.responsewriter;
-
-import freemarker.template.Configuration;
-import freemarker.template.Template;
-import freemarker.template.TemplateException;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.value.ValueDescriptor;
-import org.restlet.Response;
-import org.restlet.data.MediaType;
-import org.restlet.representation.Representation;
-import org.restlet.representation.WriterRepresentation;
-import org.restlet.resource.ResourceException;
-import org.restlet.service.MetadataService;
-
-/**
- * JAVADOC
- */
-public class ResourceTemplateResponseWriter extends AbstractResponseWriter
-{
-    private static final List<MediaType> supportedMediaTypes = Arrays.asList( MediaType.TEXT_HTML, MediaType.APPLICATION_ATOM );
-
-    @Service
-    private Configuration cfg;
-
-    @Service
-    private MetadataService metadataService;
-
-    Set<String> skip = new HashSet<String>();
-
-    @Override
-    public boolean writeResponse( final Object result, final Response response )
-        throws ResourceException
-    {
-        MediaType type = getVariant( response.getRequest(), ENGLISH, supportedMediaTypes ).getMediaType();
-        if( type != null )
-        {
-            // Try to find template for this specific resource
-            StringBuilder templateBuilder = (StringBuilder) response.getRequest().getAttributes().get( "template" );
-            String templateName = templateBuilder.toString();
-
-            if( result instanceof ValueDescriptor )
-            {
-                templateName += "_form";
-            }
-
-            final String extension = metadataService.getExtension( type );
-            templateName += "." + extension;
-
-            // Have we failed on this one before, then don't try again
-            if( skip.contains( templateName ) )
-            {
-                return false;
-            }
-
-            try
-            {
-                final Template template = cfg.getTemplate( templateName );
-                Representation rep = new WriterRepresentation( MediaType.TEXT_HTML )
-                {
-                    @Override
-                    public void write( Writer writer )
-                        throws IOException
-                    {
-                        Map<String, Object> context = new HashMap<String, Object>();
-                        context.put( "request", response.getRequest() );
-                        context.put( "response", response );
-
-                        context.put( "result", result );
-
-                        try
-                        {
-                            template.process( context, writer );
-                        }
-                        catch( TemplateException e )
-                        {
-                            throw new IOException( e );
-                        }
-                    }
-                };
-                response.setEntity( rep );
-                return true;
-            }
-            catch( Exception e )
-            {
-                skip.add( templateName );
-                // Ignore
-            }
-        }
-        return false;
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/TableResponseWriter.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/TableResponseWriter.java
deleted file mode 100644
index 32ca740..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/TableResponseWriter.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.restlet.responsewriter;
-
-import freemarker.template.Configuration;
-import freemarker.template.TemplateException;
-import java.io.IOException;
-import java.io.Writer;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.json.JSONException;
-import org.json.JSONWriter;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.util.Dates;
-import org.qi4j.library.rest.common.table.Cell;
-import org.qi4j.library.rest.common.table.Column;
-import org.qi4j.library.rest.common.table.Row;
-import org.qi4j.library.rest.common.table.Table;
-import org.restlet.Response;
-import org.restlet.data.CharacterSet;
-import org.restlet.data.MediaType;
-import org.restlet.representation.Representation;
-import org.restlet.representation.WriterRepresentation;
-import org.restlet.resource.ResourceException;
-
-/**
- * JAVADOC
- */
-public class TableResponseWriter extends AbstractResponseWriter
-{
-    private static final List<MediaType> supportedMediaTypes = Arrays.asList( MediaType.TEXT_HTML, MediaType.APPLICATION_JSON );
-
-    @Service
-    private Configuration cfg;
-
-    @Override
-    public boolean writeResponse( final Object result, final Response response )
-        throws ResourceException
-    {
-        if( result instanceof Table )
-        {
-            MediaType type = getVariant( response.getRequest(), ENGLISH, supportedMediaTypes ).getMediaType();
-            if( MediaType.APPLICATION_JSON.equals( type ) )
-            {
-
-                response.setEntity( new WriterRepresentation( MediaType.APPLICATION_JSON )
-                {
-                    @Override
-                    public void write( Writer writer )
-                        throws IOException
-                    {
-                        try
-                        {
-                            JSONWriter json = new JSONWriter( writer );
-                            Table tableValue = (Table) result;
-
-                            // Parse parameters
-                            String tqx = response.getRequest().getResourceRef().getQueryAsForm().getFirstValue( "tqx" );
-                            String reqId = null;
-                            if( tqx != null )
-                            {
-                                String[] params = tqx.split( ";" );
-                                for( String param : params )
-                                {
-                                    String[] p = param.split( ":" );
-                                    String key = p[ 0 ];
-                                    String value = p[ 1 ];
-
-                                    if( key.equals( "reqId" ) )
-                                    {
-                                        reqId = value;
-                                    }
-                                }
-                            }
-
-                            json.object().key( "version" ).value( "0.6" );
-                            if( reqId != null )
-                            {
-                                json.key( "reqId" ).value( reqId );
-                            }
-                            json.key( "status" ).value( "ok" );
-                            json.key( "table" ).object();
-                            List<Column> columnList = tableValue.cols().get();
-                            json.key( "cols" ).array();
-                            for( Column columnValue : columnList )
-                            {
-                                json.object().
-                                    key( "id" ).value( columnValue.id().get() ).
-                                    key( "label" ).value( columnValue.label().get() ).
-                                    key( "type" ).value( columnValue.columnType().get() ).
-                                    endObject();
-                            }
-                            json.endArray();
-
-                            json.key( "rows" ).array();
-                            for( Row rowValue : tableValue.rows().get() )
-                            {
-                                json.object();
-                                json.key( "c" ).array();
-                                int idx = 0;
-                                for( Cell cellValue : rowValue.c().get() )
-                                {
-                                    json.object();
-                                    Object value = cellValue.v().get();
-                                    if( columnList.get( idx )
-                                            .columnType()
-                                            .get()
-                                            .equals( Table.DATETIME ) && value != null )
-                                    {
-                                        value = Dates.toUtcString( (Date) value );
-                                    }
-                                    else if( columnList.get( idx )
-                                                 .columnType()
-                                                 .get()
-                                                 .equals( Table.DATE ) && value != null )
-                                    {
-                                        value = new SimpleDateFormat( "yyyy-MM-dd" ).format( (Date) value );
-                                    }
-                                    else if( columnList.get( idx )
-                                                 .columnType()
-                                                 .get()
-                                                 .equals( Table.TIME_OF_DAY ) && value != null )
-                                    {
-                                        value = new SimpleDateFormat( "HH:mm:ss" ).format( (Date) value );
-                                    }
-
-                                    if( value != null )
-                                    {
-                                        json.key( "v" ).value( value );
-                                    }
-                                    if( cellValue.f().get() != null )
-                                    {
-                                        json.key( "f" ).value( cellValue.f().get() );
-                                    }
-                                    json.endObject();
-
-                                    idx++;
-                                }
-                                json.endArray();
-                                json.endObject();
-                            }
-                            json.endArray();
-                            json.endObject();
-                            json.endObject();
-                        }
-                        catch( JSONException e )
-                        {
-                            throw new IOException( e );
-                        }
-                    }
-                } );
-                return true;
-            }
-            else if( MediaType.TEXT_HTML.equals( type ) )
-            {
-                Representation rep = new WriterRepresentation( MediaType.TEXT_HTML )
-                {
-                    @Override
-                    public void write( Writer writer )
-                        throws IOException
-                    {
-                        Map<String, Object> context = new HashMap<String, Object>();
-                        context.put( "request", response.getRequest() );
-                        context.put( "response", response );
-
-                        context.put( "result", result );
-                        try
-                        {
-                            cfg.getTemplate( "table.htm" ).process( context, writer );
-                        }
-                        catch( TemplateException e )
-                        {
-                            throw new IOException( e );
-                        }
-                    }
-                };
-                rep.setCharacterSet( CharacterSet.UTF_8 );
-                response.setEntity( rep );
-                return true;
-            }
-        }
-        return false;
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/ValueCompositeResponseWriter.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/ValueCompositeResponseWriter.java
deleted file mode 100644
index 0394028..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/ValueCompositeResponseWriter.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.restlet.responsewriter;
-
-import freemarker.template.Configuration;
-import freemarker.template.Template;
-import freemarker.template.TemplateException;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.service.qualifier.Tagged;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.api.value.ValueSerializer;
-import org.restlet.Response;
-import org.restlet.data.MediaType;
-import org.restlet.representation.Representation;
-import org.restlet.representation.StringRepresentation;
-import org.restlet.representation.WriterRepresentation;
-import org.restlet.resource.ResourceException;
-
-/**
- * JAVADOC
- */
-public class ValueCompositeResponseWriter extends AbstractResponseWriter
-{
-    private static final List<MediaType> supportedMediaTypes = Arrays.asList( MediaType.TEXT_HTML, MediaType.APPLICATION_JSON );
-
-    @Service
-    private Configuration cfg;
-
-    @Service
-    @Tagged( ValueSerialization.Formats.JSON )
-    private ValueSerializer valueSerializer;
-
-    @Override
-    public boolean writeResponse( final Object result, final Response response )
-        throws ResourceException
-    {
-        if( result instanceof ValueComposite )
-        {
-            MediaType type = getVariant( response.getRequest(), ENGLISH, supportedMediaTypes ).getMediaType();
-            if( MediaType.APPLICATION_JSON.equals( type ) )
-            {
-                StringRepresentation representation = new StringRepresentation( valueSerializer.serialize( result ),
-                                                                                MediaType.APPLICATION_JSON );
-                response.setEntity( representation );
-                return true;
-            }
-            else if( MediaType.TEXT_HTML.equals( type ) )
-            {
-                Representation rep = new WriterRepresentation( MediaType.TEXT_HTML )
-                {
-                    @Override
-                    public void write( Writer writer )
-                        throws IOException
-                    {
-                        // Look for type specific template
-                        Template template;
-                        try
-                        {
-                            template = cfg.getTemplate( "/rest/template/" + result.getClass()
-                                .getInterfaces()[ 0 ].getSimpleName() + ".htm" );
-                        }
-                        catch( Exception e )
-                        {
-                            // Use default
-                            template = cfg.getTemplate( "value.htm" );
-                        }
-
-                        Map<String, Object> context = new HashMap<String, Object>();
-                        context.put( "request", response.getRequest() );
-                        context.put( "response", response );
-                        context.put( "result", result );
-                        context.put( "util", this );
-                        try
-                        {
-                            template.process( context, writer );
-                        }
-                        catch( TemplateException e )
-                        {
-                            throw new IOException( e );
-                        }
-                    }
-
-                    public boolean isSequence( Object obj )
-                    {
-                        return obj instanceof Collection;
-                    }
-                };
-                response.setEntity( rep );
-                return true;
-            }
-        }
-        return false;
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/ValueDescriptorResponseWriter.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/ValueDescriptorResponseWriter.java
deleted file mode 100644
index bcfa0fb..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/ValueDescriptorResponseWriter.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.restlet.responsewriter;
-
-import freemarker.template.Configuration;
-import freemarker.template.TemplateException;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueDescriptor;
-import org.restlet.Response;
-import org.restlet.data.MediaType;
-import org.restlet.representation.Representation;
-import org.restlet.representation.StringRepresentation;
-import org.restlet.representation.WriterRepresentation;
-import org.restlet.resource.ResourceException;
-
-/**
- * JAVADOC
- */
-public class ValueDescriptorResponseWriter extends AbstractResponseWriter
-{
-    private static final List<MediaType> supportedMediaTypes = Arrays.asList( MediaType.TEXT_HTML, MediaType.APPLICATION_JSON );
-
-    @Structure
-    private Module module;
-
-    @Service
-    private Configuration cfg;
-
-    @Override
-    public boolean writeResponse( final Object result, final Response response )
-        throws ResourceException
-    {
-        if( result instanceof ValueDescriptor )
-        {
-            MediaType type = getVariant( response.getRequest(), ENGLISH, supportedMediaTypes ).getMediaType();
-            if( MediaType.APPLICATION_JSON.equals( type ) )
-            {
-                JSONObject json = new JSONObject();
-                ValueDescriptor vd = (ValueDescriptor) result;
-                try
-                {
-                    for( PropertyDescriptor propertyDescriptor : vd.state().properties() )
-                    {
-                        Object o = propertyDescriptor.initialValue( module );
-                        if( o == null )
-                        {
-                            json.put( propertyDescriptor.qualifiedName().name(), JSONObject.NULL );
-                        }
-                        else
-                        {
-                            json.put( propertyDescriptor.qualifiedName().name(), o.toString() );
-                        }
-                    }
-                }
-                catch( JSONException e )
-                {
-                    throw new ResourceException(e);
-                }
-                StringRepresentation representation
-                    = new StringRepresentation( json.toString(), MediaType.APPLICATION_JSON );
-                response.setEntity( representation );
-
-                return true;
-            }
-            else if( MediaType.TEXT_HTML.equals( type ) )
-            {
-                Representation rep = new WriterRepresentation( MediaType.TEXT_HTML )
-                {
-                    @Override
-                    public void write( Writer writer )
-                        throws IOException
-                    {
-                        Map<String, Object> context = new HashMap<String, Object>();
-                        context.put( "request", response.getRequest() );
-                        context.put( "response", response );
-                        context.put( "result", result );
-                        try
-                        {
-                            cfg.getTemplate( "form.htm" ).process( context, writer );
-                        }
-                        catch( TemplateException e )
-                        {
-                            throw new IOException( e );
-                        }
-                    }
-                };
-                response.setEntity( rep );
-                return true;
-            }
-        }
-        return false;
-    }
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/package.html b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/package.html
deleted file mode 100644
index 369b329..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/restlet/responsewriter/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Restlet ReST Server Response Writers.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/spi/CommandResult.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/spi/CommandResult.java
deleted file mode 100644
index 5645566..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/spi/CommandResult.java
+++ /dev/null
@@ -1,27 +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.qi4j.library.rest.server.spi;
-
-/**
- * TODO
- */
-public interface CommandResult
-{
-    public Object getResult();
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/spi/RequestReader.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/spi/RequestReader.java
deleted file mode 100644
index d752238..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/spi/RequestReader.java
+++ /dev/null
@@ -1,32 +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.qi4j.library.rest.server.spi;
-
-import java.lang.reflect.Method;
-import org.restlet.Request;
-import org.restlet.resource.ResourceException;
-
-/**
- * TODO
- */
-public interface RequestReader
-{
-    Object[] readRequest( Request request, Method method )
-        throws ResourceException;
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/spi/ResponseWriter.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/spi/ResponseWriter.java
deleted file mode 100644
index 01efee7..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/spi/ResponseWriter.java
+++ /dev/null
@@ -1,31 +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.qi4j.library.rest.server.spi;
-
-import org.restlet.Response;
-import org.restlet.resource.ResourceException;
-
-/**
- * TODO
- */
-public interface ResponseWriter
-{
-    boolean writeResponse( final Object result, final Response response )
-        throws ResourceException;
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/spi/ResultConverter.java b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/spi/ResultConverter.java
deleted file mode 100644
index 5bf2ab0..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/spi/ResultConverter.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- *
- * Copyright 2009-2011 Rickard Öberg AB
- *
- * Licensed 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.qi4j.library.rest.server.spi;
-
-import org.restlet.Request;
-
-/**
- * JAVADOC
- */
-public interface ResultConverter
-{
-    Object convert( Object result, Request request, Object[] arguments );
-}
diff --git a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/spi/package.html b/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/spi/package.html
deleted file mode 100644
index 61f8776..0000000
--- a/libraries/rest-server/src/main/java/org/qi4j/library/rest/server/spi/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ReST Server SPI.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/rest-server.properties b/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/rest-server.properties
new file mode 100644
index 0000000..beff845
--- /dev/null
+++ b/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/rest-server.properties
@@ -0,0 +1,31 @@
+#
+#  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.
+#
+#
+#
+
+#Server
+responsewriters=org.apache.polygene.library.rest.server.restlet.responsewriter.ResourceTemplateResponseWriter,\
+    org.apache.polygene.library.rest.server.restlet.responsewriter.DefaultResponseWriter,\
+    org.apache.polygene.library.rest.server.restlet.responsewriter.LinksResponseWriter,\
+    org.apache.polygene.library.rest.server.restlet.responsewriter.TableResponseWriter,\
+    org.apache.polygene.library.rest.server.restlet.responsewriter.ResourceResponseWriter,\
+    org.apache.polygene.library.rest.server.restlet.responsewriter.ValueCompositeResponseWriter,\
+    org.apache.polygene.library.rest.server.restlet.responsewriter.FormResponseWriter, \
+    org.apache.polygene.library.rest.server.restlet.responsewriter.JSONResponseWriter
+
+requestreaders=org.apache.polygene.library.rest.server.restlet.requestreader.DefaultRequestReader
diff --git a/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/form.htm b/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/form.htm
new file mode 100644
index 0000000..4236279
--- /dev/null
+++ b/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/form.htm
@@ -0,0 +1,61 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <title>${request.resourceRef.lastSegment}</title>
+    <style type="text/css">
+        form
+        {
+            width: 600px;
+        }
+
+        form label
+        {
+            display: block; /* block float the labels to left column, set a width */
+            float: left;
+            width: 150px;
+            padding: 0;
+            margin: 5px 0 0; /* set top margin same as form input - textarea etc. elements */
+            text-align: right;
+        }
+
+        form br
+        {
+            clear: left;
+        }
+    </style>
+</head>
+
+<body>
+<form action="" method="${request.method.name}">
+    <fieldset>
+        <legend>${request.resourceRef.lastSegment}</legend>
+
+        <#list result as param>
+            <label for="${param.name}">${param.name}:</label>
+            <input type="text" name="${param.name}" value="${param.value!}"><br/>
+        </#list>
+        <input value="Submit" type="submit"/>
+    </fieldset>
+</form>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/links.atom b/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/links.atom
similarity index 100%
rename from libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/links.atom
rename to libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/links.atom
diff --git a/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/links.htm b/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/links.htm
new file mode 100644
index 0000000..63acf2b
--- /dev/null
+++ b/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/links.htm
@@ -0,0 +1,39 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <title>${request.resourceRef.remainingPart}</title>
+    <link media="print" title="Atom feed"
+          type="application/atom+xml"
+          rel="alternate"
+          href="${request.resourceRef.path}.atom?$!{request.resourceRef.query}"/>
+</head>
+
+<body>
+<h3>Result for ${request.resourceRef.remainingPart}</h3>
+<ul>
+    <#list result.links as link>
+        <li><a href="${link.href}">${link.text}</a></li>
+    </#list>
+</ul>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/resource.htm b/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/resource.htm
new file mode 100644
index 0000000..4c00354
--- /dev/null
+++ b/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/resource.htm
@@ -0,0 +1,77 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
+<!-- Default resource template -->
+<html>
+<head>
+    <title>${request.resourceRef.remainingPart}</title>
+</head>
+
+<body>
+
+<h1>${request.resourceRef.remainingPart}</h1>
+
+<div class="block">
+    <h2>Queries</h2>
+    <ul>
+        <#list result.queries as query>
+            <li>
+                <a rel="${query.rel}" href="${query.href}">${query.text}</a></li>
+        </#list>
+    </ul>
+</div>
+
+<div class="block">
+    <h2>Commands</h2>
+    <#list result.commands as command>
+        <form name="${command.id}" action="${command.href}" method="POST"><input type="submit" value="${command.text}"/>
+        </form>
+    </#list>
+</div>
+
+<div class="block">
+    <h2>Resources</h2>
+    <ul>
+        <#list result.resources as resource>
+            <li>
+                <a rel="${resource.rel}" href="${resource.href}">${resource.text}</a>
+            </li>
+        </#list>
+    </ul>
+</div>
+
+<#if result.index??>
+    <h2>Index</h2>
+    <#if result.index.links??>
+        <div class="block">
+            <ul>
+                <#list result.index.links as link>
+                    <li><a href="${link.href}" rel="${link.rel!}" title="${link.title!}">${link.text}</a></li>
+                </#list>
+            </ul>
+        </div>
+        <#else>
+            <h2>Index</h2>
+            <pre>$result.index</pre>
+    </#if>
+</#if>
+
+</body>
+</html>
diff --git a/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/selectresource.htm b/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/selectresource.htm
new file mode 100644
index 0000000..6106c3b
--- /dev/null
+++ b/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/selectresource.htm
@@ -0,0 +1,35 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <title>${name}</title>
+</head>
+
+<body>
+<h1>Select resource</h1>
+
+<form action="resource" method="GET">
+    <input name="resource" value="" type="text"/>
+    <input value="Show" type="submit"/>
+</form>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/table.htm b/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/table.htm
new file mode 100644
index 0000000..e9ce307
--- /dev/null
+++ b/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/table.htm
@@ -0,0 +1,53 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
+<html>
+<body>
+
+<table border="1">
+    <tr>
+        <#list result.cols as column>
+            <th id="${column.id}">${column.label}</th>
+        </#list>
+    </tr>
+    <#list result.rows as row>
+        <tr>
+            <#list row.c as cell>
+                <td>
+                    <#if cell.f??>
+                        <#if cell.v.startsWith("/")>
+                            <a href="$cell.v">$cell.v</a>
+                            <#else>
+                                ${cell.f}
+                        </#if>
+                        <#elseif cell.v??>
+                            ${cell.v}
+                            <#else>
+                                &nbsp;
+                    </#if>
+                </td>
+
+            </#list>
+        </tr>
+    </#list>
+</table>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/value.htm b/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/value.htm
new file mode 100644
index 0000000..971fd24
--- /dev/null
+++ b/libraries/rest-server/src/main/resources/org/apache/polygene/library/rest/server/restlet/responsewriter/value.htm
@@ -0,0 +1,40 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
+<html>
+<body>
+
+<ul>
+    <#list result?keys as name>
+        <#assign val = result[name]>
+            <li>
+                <#attempt>
+                    ${name}: ${val}
+                    <#recover>
+                        ${name}:
+                        <#list val as v>
+                            ${v}
+                        </#list>
+                </#attempt>
+            </li>
+    </#list>
+</ul>
+</body>
+</html>
diff --git a/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/rest-server.properties b/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/rest-server.properties
deleted file mode 100644
index 8bc651c..0000000
--- a/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/rest-server.properties
+++ /dev/null
@@ -1,26 +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.
-
-#Server
-responsewriters=org.qi4j.library.rest.server.restlet.responsewriter.ResourceTemplateResponseWriter,\
-    org.qi4j.library.rest.server.restlet.responsewriter.DefaultResponseWriter,\
-    org.qi4j.library.rest.server.restlet.responsewriter.LinksResponseWriter,\
-    org.qi4j.library.rest.server.restlet.responsewriter.TableResponseWriter,\
-    org.qi4j.library.rest.server.restlet.responsewriter.ResourceResponseWriter,\
-    org.qi4j.library.rest.server.restlet.responsewriter.ValueCompositeResponseWriter,\
-    org.qi4j.library.rest.server.restlet.responsewriter.FormResponseWriter, \
-    org.qi4j.library.rest.server.restlet.responsewriter.JSONResponseWriter
-
-requestreaders=org.qi4j.library.rest.server.restlet.requestreader.DefaultRequestReader
diff --git a/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/form.htm b/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/form.htm
deleted file mode 100644
index deb9a9e..0000000
--- a/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/form.htm
+++ /dev/null
@@ -1,41 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-    <title>${request.resourceRef.lastSegment}</title>
-    <style type="text/css">
-        form
-        {
-            width: 600px;
-        }
-
-        form label
-        {
-            display: block; /* block float the labels to left column, set a width */
-            float: left;
-            width: 150px;
-            padding: 0;
-            margin: 5px 0 0; /* set top margin same as form input - textarea etc. elements */
-            text-align: right;
-        }
-
-        form br
-        {
-            clear: left;
-        }
-    </style>
-</head>
-
-<body>
-<form action="" method="${request.method.name}">
-    <fieldset>
-        <legend>${request.resourceRef.lastSegment}</legend>
-
-        <#list result as param>
-            <label for="${param.name}">${param.name}:</label>
-            <input type="text" name="${param.name}" value="${param.value!}"><br/>
-        </#list>
-        <input value="Submit" type="submit"/>
-    </fieldset>
-</form>
-</body>
-
-</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/links.htm b/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/links.htm
deleted file mode 100644
index 9c0035e..0000000
--- a/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/links.htm
+++ /dev/null
@@ -1,19 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-    <title>${request.resourceRef.remainingPart}</title>
-    <link media="print" title="Atom feed"
-          type="application/atom+xml"
-          rel="alternate"
-          href="${request.resourceRef.path}.atom?$!{request.resourceRef.query}"/>
-</head>
-
-<body>
-<h3>Result for ${request.resourceRef.remainingPart}</h3>
-<ul>
-    <#list result.links as link>
-        <li><a href="${link.href}">${link.text}</a></li>
-    </#list>
-</ul>
-</body>
-
-</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/resource.htm b/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/resource.htm
deleted file mode 100644
index f210c03..0000000
--- a/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/resource.htm
+++ /dev/null
@@ -1,57 +0,0 @@
-<!-- Default resource template -->
-<html>
-<head>
-    <title>${request.resourceRef.remainingPart}</title>
-</head>
-
-<body>
-
-<h1>${request.resourceRef.remainingPart}</h1>
-
-<div class="block">
-    <h2>Queries</h2>
-    <ul>
-        <#list result.queries as query>
-            <li>
-                <a rel="${query.rel}" href="${query.href}">${query.text}</a></li>
-        </#list>
-    </ul>
-</div>
-
-<div class="block">
-    <h2>Commands</h2>
-    <#list result.commands as command>
-        <form name="${command.id}" action="${command.href}" method="POST"><input type="submit" value="${command.text}"/>
-        </form>
-    </#list>
-</div>
-
-<div class="block">
-    <h2>Resources</h2>
-    <ul>
-        <#list result.resources as resource>
-            <li>
-                <a rel="${resource.rel}" href="${resource.href}">${resource.text}</a>
-            </li>
-        </#list>
-    </ul>
-</div>
-
-<#if result.index??>
-    <h2>Index</h2>
-    <#if result.index.links??>
-        <div class="block">
-            <ul>
-                <#list result.index.links as link>
-                    <li><a href="${link.href}" rel="${link.rel!}" title="${link.title!}">${link.text}</a></li>
-                </#list>
-            </ul>
-        </div>
-        <#else>
-            <h2>Index</h2>
-            <pre>$result.index</pre>
-    </#if>
-</#if>
-
-</body>
-</html>
diff --git a/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/selectresource.htm b/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/selectresource.htm
deleted file mode 100644
index b358a30..0000000
--- a/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/selectresource.htm
+++ /dev/null
@@ -1,15 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-    <title>${name}</title>
-</head>
-
-<body>
-<h1>Select resource</h1>
-
-<form action="resource" method="GET">
-    <input name="resource" value="" type="text"/>
-    <input value="Show" type="submit"/>
-</form>
-</body>
-
-</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/table.htm b/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/table.htm
deleted file mode 100644
index 3c5899e..0000000
--- a/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/table.htm
+++ /dev/null
@@ -1,33 +0,0 @@
-<html>
-<body>
-
-<table border="1">
-    <tr>
-        <#list result.cols as column>
-            <th id="${column.id}">${column.label}</th>
-        </#list>
-    </tr>
-    <#list result.rows as row>
-        <tr>
-            <#list row.c as cell>
-                <td>
-                    <#if cell.f??>
-                        <#if cell.v.startsWith("/")>
-                            <a href="$cell.v">$cell.v</a>
-                            <#else>
-                                ${cell.f}
-                        </#if>
-                        <#elseif cell.v??>
-                            ${cell.v}
-                            <#else>
-                                &nbsp;
-                    </#if>
-                </td>
-
-            </#list>
-        </tr>
-    </#list>
-</table>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/value.htm b/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/value.htm
deleted file mode 100644
index 4bdc380..0000000
--- a/libraries/rest-server/src/main/resources/org/qi4j/library/rest/server/restlet/responsewriter/value.htm
+++ /dev/null
@@ -1,20 +0,0 @@
-<html>
-<body>
-
-<ul>
-    <#list result?keys as name>
-        <#assign val = result[name]>
-            <li>
-                <#attempt>
-                    ${name}: ${val}
-                    <#recover>
-                        ${name}:
-                        <#list val as v>
-                            ${v}
-                        </#list>
-                </#attempt>
-            </li>
-    </#list>
-</ul>
-</body>
-</html>
diff --git a/libraries/rest-server/src/main/resources/velocity.properties b/libraries/rest-server/src/main/resources/velocity.properties
index fb4ef10..00b720c 100644
--- a/libraries/rest-server/src/main/resources/velocity.properties
+++ b/libraries/rest-server/src/main/resources/velocity.properties
@@ -1,17 +1,22 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 # ----------------------------------------------------------------------------
 # R U N T I M E  L O G
diff --git a/libraries/rest-server/src/test/java/org/apache/polygene/library/rest/server/DocumentationSupport.java b/libraries/rest-server/src/test/java/org/apache/polygene/library/rest/server/DocumentationSupport.java
new file mode 100644
index 0000000..ef872e8
--- /dev/null
+++ b/libraries/rest-server/src/test/java/org/apache/polygene/library/rest/server/DocumentationSupport.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.rest.server;
+
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.rest.server.assembler.RestServerAssembler;
+
+public class DocumentationSupport
+    implements Assembler
+{
+
+    // START SNIPPET: UsingAssembler
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        RestServerAssembler assembler = new RestServerAssembler();
+        assembler.assemble( module );
+    }
+    // END SNIPPET: UsingAssembler
+}
diff --git a/libraries/rest-server/src/test/java/org/qi4j/library/rest/server/DocumentationSupport.java b/libraries/rest-server/src/test/java/org/qi4j/library/rest/server/DocumentationSupport.java
deleted file mode 100644
index c50ffe1..0000000
--- a/libraries/rest-server/src/test/java/org/qi4j/library/rest/server/DocumentationSupport.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.server;
-
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.rest.server.assembler.RestServerAssembler;
-
-public class DocumentationSupport
-    implements Assembler
-{
-
-    // START SNIPPET: UsingAssembler
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        RestServerAssembler assembler = new RestServerAssembler();
-        assembler.assemble( module );
-    }
-    // END SNIPPET: UsingAssembler
-}
diff --git a/libraries/rest/build.gradle b/libraries/rest/build.gradle
index 2c9ff02..6ca051d 100644
--- a/libraries/rest/build.gradle
+++ b/libraries/rest/build.gradle
@@ -1,40 +1,43 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ REST Library provides various Restlet resources that can be used to expose Apache Zest™ entities and indexes. Mostly for debugging."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - REST" }}
+description = "Apache Polygene™ REST Library provides various Restlet resources that can be used to expose Apache Polygene™ entities and indexes. Mostly for debugging."
+
+jar { manifest { name = "Apache Polygene™ Library - REST" } }
 
 dependencies {
+  compileOnly libraries.servlet_api
 
-    compile project( ':org.qi4j.extensions:org.qi4j.extension.indexing-rdf' )
-    compile libraries.restlet
-    compile libraries.sparql
-    compile libraries.velocity
-    compile libraries.servlet_api
+  api libraries.restlet
 
-    testCompile project( ":org.qi4j.core:org.qi4j.core.testsupport" )
-    testCompile project( ":org.qi4j.libraries:org.qi4j.library.http" )
-    testCompile project( ':org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson' )
-    testCompile libraries.http_client
+  implementation polygene.extension( 'indexing-rdf' )
+  implementation libraries.sparql
+  implementation libraries.velocity
 
-    testRuntime project( ":org.qi4j.core:org.qi4j.core.runtime" )
-    testRuntime libraries.logback
+  runtimeOnly polygene.core.runtime
 
+  testImplementation polygene.core.testsupport
+  testImplementation polygene.library( 'http' )
+  testImplementation libraries.http_client
+
+  testRuntimeOnly libraries.logback
 }
diff --git a/libraries/rest/dev-status.xml b/libraries/rest/dev-status.xml
index 37f9020..d3c6f4f 100644
--- a/libraries/rest/dev-status.xml
+++ b/libraries/rest/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/EntitiesResource.java b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/EntitiesResource.java
new file mode 100644
index 0000000..0b07b3e
--- /dev/null
+++ b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/EntitiesResource.java
@@ -0,0 +1,247 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.spi.query.EntityFinder;
+import org.apache.polygene.spi.query.EntityFinderException;
+import org.restlet.data.CharacterSet;
+import org.restlet.data.MediaType;
+import org.restlet.data.Status;
+import org.restlet.ext.atom.Entry;
+import org.restlet.ext.atom.Feed;
+import org.restlet.ext.atom.Link;
+import org.restlet.ext.atom.Text;
+import org.restlet.representation.EmptyRepresentation;
+import org.restlet.representation.OutputRepresentation;
+import org.restlet.representation.Representation;
+import org.restlet.representation.Variant;
+import org.restlet.representation.WriterRepresentation;
+import org.restlet.resource.ResourceException;
+import org.restlet.resource.ServerResource;
+
+import static java.util.stream.Collectors.toList;
+
+/**
+ * Listing of all Entities.
+ * <p>
+ * Mapped to /entity
+ * </p>
+ */
+public class EntitiesResource
+    extends ServerResource
+{
+
+    @Service
+    private EntityFinder entityFinder;
+    @Service
+    private Serialization stateSerialization;
+
+    public EntitiesResource()
+    {
+        super();
+
+        // Define the supported variants.
+        getVariants().addAll(
+            Arrays.asList( new Variant( MediaType.TEXT_HTML ), new Variant( MediaType.APPLICATION_RDF_XML ),
+                           new Variant( MediaType.APPLICATION_JSON ), new Variant( MediaType.APPLICATION_ATOM ) ) );
+
+        setNegotiated( true );
+    }
+
+    @Override
+    protected Representation get( Variant variant )
+        throws ResourceException
+    {
+        System.out.println( "VARIANT: " + variant.getMediaType() );
+        // Generate the right representation according to its media type.
+        if( MediaType.APPLICATION_JSON.equals( variant.getMediaType() ) )
+        {
+            return representJson();
+        }
+        else if( MediaType.APPLICATION_RDF_XML.equals( variant.getMediaType() ) )
+        {
+            return representRdf();
+        }
+        else if( MediaType.TEXT_HTML.equals( variant.getMediaType() ) )
+        {
+            return representHtml();
+        }
+        else if( MediaType.APPLICATION_ATOM.equals( variant.getMediaType() ) )
+        {
+            return representAtom();
+        }
+
+        throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
+    }
+
+    private Representation representJson()
+        throws ResourceException
+    {
+        try
+        {
+            final Iterable<EntityReference> query = entityFinder.findEntities( EntityComposite.class, null, null, null, null, Collections.emptyMap() )
+                                                                .collect( toList() );
+            return new OutputRepresentation( MediaType.APPLICATION_JSON )
+            {
+                @Override
+                public void write( OutputStream outputStream )
+                    throws IOException
+                {
+                    stateSerialization.serialize( new OutputStreamWriter( outputStream ), query );
+                }
+            };
+        }
+        catch( Exception e )
+        {
+            throw new ResourceException( e );
+        }
+    }
+
+    private Representation representRdf()
+        throws ResourceException
+    {
+        try
+        {
+            final Stream<EntityReference> query = entityFinder.findEntities( EntityComposite.class, null, null, null, null, Collections.emptyMap() );
+
+            WriterRepresentation representation = new WriterRepresentation( MediaType.APPLICATION_RDF_XML )
+            {
+                @Override
+                public void write( Writer writer )
+                    throws IOException
+                {
+                    PrintWriter out = new PrintWriter( writer );
+                    out.println( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<rdf:RDF\n"
+                                 + "\txmlns=\"urn:polygene:\"\n" + "\txmlns:polygene=\"http://polygene.apache.org/rdf/model/1.0/\"\n"
+                                 + "\txmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n"
+                                 + "\txmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">" );
+                    query.forEach( qualifiedIdentity -> out.println( "<polygene:entity rdf:about=\""
+                                                                     + getRequest().getResourceRef().getPath() + "/"
+                                                                     + qualifiedIdentity.identity() + ".rdf\"/>" ) );
+
+                    out.println( "</rdf:RDF>" );
+                }
+            };
+            representation.setCharacterSet( CharacterSet.UTF_8 );
+
+            return representation;
+        }
+        catch( EntityFinderException e )
+        {
+            throw new ResourceException( Status.SERVER_ERROR_INTERNAL, e );
+        }
+    }
+
+    private Representation representHtml()
+        throws ResourceException
+    {
+        try
+        {
+            Stream<EntityReference> query = entityFinder.findEntities( EntityComposite.class, null, null, null, null, Collections.emptyMap() );
+            Representation representation = new WriterRepresentation( MediaType.TEXT_HTML )
+            {
+                @Override
+                public void write( Writer buf )
+                    throws IOException
+                {
+                    PrintWriter out = new PrintWriter( buf );
+                    out.println( "<html><head><title>All entities</title></head><body><h1>All entities</h1><ul>" );
+
+                    query.forEach( entity -> out.println( "<li><a href=\""
+                                                          + getRequest().getResourceRef().clone().addSegment( entity.identity() + ".html" )
+                                                          + "\">" + entity.identity() + "</a></li>" ) );
+                    out.println( "</ul></body></html>" );
+                }
+            };
+            representation.setCharacterSet( CharacterSet.UTF_8 );
+            return representation;
+        }
+        catch( EntityFinderException e )
+        {
+            throw new ResourceException( e );
+        }
+    }
+
+    private Representation representAtom()
+        throws ResourceException
+    {
+        try
+        {
+            Feed feed = new Feed();
+            feed.setTitle( new Text( MediaType.TEXT_PLAIN, "All entities" ) );
+            List<Entry> entries = feed.getEntries();
+            entityFinder.findEntities( EntityComposite.class, null, null, null, null, Collections.emptyMap() )
+                        .forEach(
+                            entityReference ->
+                            {
+                                Entry entry = new Entry();
+                                entry.setTitle( new Text( MediaType.TEXT_PLAIN, entityReference.toString() ) );
+                                Link link = new Link();
+                                link.setHref( getRequest().getResourceRef().clone()
+                                                          .addSegment( entityReference.identity().toString() ) );
+                                entry.getLinks().add( link );
+                                entries.add( entry );
+                            } );
+            return feed;
+        }
+        catch( Exception e )
+        {
+            throw new ResourceException( e );
+        }
+    }
+
+    @Override
+    protected Representation post( Representation entity, Variant variant )
+        throws ResourceException
+    {
+        try
+        {
+            /*
+             * InputStream in = entity.getStream(); ObjectInputStream oin = new ObjectInputStream( in ); String reference
+             * = oin.readUTF(); Usecase usecase = (Usecase) oin.readUnshared(); MetaInfo unitofwork = (MetaInfo)
+             * oin.readUnshared(); Iterable<UnitOfWorkEvent> events = (Iterable<UnitOfWorkEvent>) oin.readUnshared();
+             *
+             * // Store state try { entityStore.apply( reference, events, usecase, unitofwork ).commit(); } catch(
+             * ConcurrentEntityStateModificationException e ) { throw new ResourceException(
+             * Status.CLIENT_ERROR_CONFLICT ); }
+             */
+        }
+        catch( Exception e )
+        {
+            throw new ResourceException( e );
+        }
+
+        return new EmptyRepresentation();
+    }
+}
\ No newline at end of file
diff --git a/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/EntityResource.java b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/EntityResource.java
new file mode 100644
index 0000000..99a538c
--- /dev/null
+++ b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/EntityResource.java
@@ -0,0 +1,523 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.serialization.SerializationException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.time.SystemTime;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.library.rdf.entity.EntityStateSerializer;
+import org.apache.polygene.library.rdf.serializer.RdfXmlSerializer;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.ManyAssociationState;
+import org.apache.polygene.spi.entity.NamedAssociationState;
+import org.apache.polygene.spi.entitystore.ConcurrentEntityStateModificationException;
+import org.apache.polygene.spi.entitystore.EntityNotFoundException;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork;
+import org.apache.polygene.spi.entitystore.helpers.JSONEntityState;
+import org.apache.polygene.spi.serialization.JsonSerialization;
+import org.openrdf.model.Statement;
+import org.openrdf.rio.RDFHandlerException;
+import org.restlet.data.CharacterSet;
+import org.restlet.data.Form;
+import org.restlet.data.Language;
+import org.restlet.data.MediaType;
+import org.restlet.data.Method;
+import org.restlet.data.Status;
+import org.restlet.data.Tag;
+import org.restlet.representation.EmptyRepresentation;
+import org.restlet.representation.Representation;
+import org.restlet.representation.StringRepresentation;
+import org.restlet.representation.Variant;
+import org.restlet.representation.WriterRepresentation;
+import org.restlet.resource.ResourceException;
+import org.restlet.resource.ServerResource;
+
+public class EntityResource
+    extends ServerResource
+{
+
+    @Service
+    private EntityStore entityStore;
+
+    @Service
+    private JsonSerialization serialization;
+
+    @Structure
+    private ModuleDescriptor module;
+
+    @Uses
+    private EntityStateSerializer entitySerializer;
+
+    private Identity identity;
+
+    public EntityResource()
+    {
+        // Define the supported variant.
+        getVariants().addAll( Arrays.asList(
+            new Variant( MediaType.TEXT_HTML ),
+            new Variant( MediaType.APPLICATION_RDF_XML ),
+            new Variant( MediaType.APPLICATION_JSON ) ) );
+        setNegotiated( true );
+        setAllowedMethods( Collections.singleton( Method.ALL ) );
+    }
+
+    @Override
+    protected void doInit()
+        throws ResourceException
+    {
+        // /entity/{reference}
+        Map<String, Object> attributes = getRequest().getAttributes();
+        identity = new StringIdentity( (String) attributes.get( "reference" ) );
+    }
+
+    @Override
+    protected Representation delete( Variant variant )
+        throws ResourceException
+    {
+        Usecase usecase = UsecaseBuilder.newUsecase( "Remove entity" );
+        EntityStoreUnitOfWork uow = entityStore.newUnitOfWork( module, usecase, SystemTime.now() );
+        try
+        {
+            EntityReference reference = EntityReference.create( identity );
+            uow.entityStateOf( module, reference ).remove();
+            uow.applyChanges().commit();
+            getResponse().setStatus( Status.SUCCESS_NO_CONTENT );
+        }
+        catch( EntityNotFoundException e )
+        {
+            uow.discard();
+            getResponse().setStatus( Status.CLIENT_ERROR_NOT_FOUND );
+        }
+
+        return new EmptyRepresentation();
+    }
+
+    @Override
+    protected Representation get( Variant variant )
+        throws ResourceException
+    {
+        EntityStoreUnitOfWork uow = entityStore.newUnitOfWork( module, UsecaseBuilder.newUsecase( "Get entity" ),
+                                                               SystemTime.now() );
+
+        try
+        {
+            EntityState entityState = getEntityState( uow );
+
+            // Check modification date
+            java.util.Date lastModified = getRequest().getConditions().getModifiedSince();
+            if( lastModified != null )
+            {
+                if( lastModified.toInstant().getEpochSecond() == entityState.lastModified().getEpochSecond() )
+                {
+                    throw new ResourceException( Status.REDIRECTION_NOT_MODIFIED );
+                }
+            }
+
+            // Generate the right representation according to its media type.
+            if( MediaType.APPLICATION_RDF_XML.equals( variant.getMediaType() ) )
+            {
+                return entityHeaders( representRdfXml( entityState ), entityState );
+            }
+            else if( MediaType.TEXT_HTML.equals( variant.getMediaType() ) )
+            {
+                return entityHeaders( representHtml( entityState ), entityState );
+            }
+            else if( MediaType.APPLICATION_JSON.equals( variant.getMediaType() ) )
+            {
+                return entityHeaders( representJson( entityState ), entityState );
+            }
+        }
+        catch( ResourceException ex )
+        {
+            uow.discard();
+            throw ex;
+        }
+
+        throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
+    }
+
+    private EntityState getEntityState( EntityStoreUnitOfWork unitOfWork )
+        throws ResourceException
+    {
+        EntityState entityState;
+        try
+        {
+            EntityReference entityReference = EntityReference.create( identity );
+            entityState = unitOfWork.entityStateOf( module, entityReference );
+        }
+        catch( EntityNotFoundException e )
+        {
+            throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
+        }
+        return entityState;
+    }
+
+    private Representation entityHeaders( Representation representation, EntityState entityState )
+    {
+        representation.setModificationDate( java.util.Date.from( entityState.lastModified() ) );
+        representation.setTag( new Tag( "" + entityState.version() ) );
+        representation.setCharacterSet( CharacterSet.UTF_8 );
+        representation.setLanguages( Collections.singletonList( Language.ENGLISH ) );
+
+        return representation;
+    }
+
+    private Representation representHtml( final EntityState entity )
+    {
+        return new WriterRepresentation( MediaType.TEXT_HTML )
+        {
+            @Override
+            public void write( Writer writer )
+                throws IOException
+            {
+                PrintWriter out = new PrintWriter( writer );
+                out.println( "<html><head><title>" + entity.entityReference() + "</title>"
+                             + "<link rel=\"alternate\" type=\"application/rdf+xml\" "
+                             + "href=\"" + entity.entityReference() + ".rdf\"/></head><body>" );
+                out.println( "<h1>" + entity.entityReference() + "</h1>" );
+
+                out.println( "<form method=\"post\" action=\"" + getRequest().getResourceRef().getPath() + "\">\n" );
+                out.println( "<fieldset><legend>Properties</legend>\n<table>" );
+
+                final EntityDescriptor descriptor = entity.entityDescriptor();
+
+                descriptor.state().properties().forEach( persistentProperty -> {
+                    Object value = entity.propertyValueOf( persistentProperty.qualifiedName() );
+                    out.println( "<tr><td>"
+                                 + "<label for=\"" + persistentProperty.qualifiedName() + "\" >"
+                                 + persistentProperty.qualifiedName().name()
+                                 + "</label></td>\n"
+                                 + "<td><input "
+                                 + "size=\"80\" "
+                                 + "type=\"text\" "
+                                 + ( persistentProperty.isImmutable() ? "readonly=\"true\" " : "" )
+                                 + "name=\"" + persistentProperty.qualifiedName() + "\" "
+                                 + "value=\"" + ( value == null ? "" : serialization.serialize( value ) )
+                                 + "\"/></td></tr>" );
+                } );
+                out.println( "</table></fieldset>\n" );
+
+                out.println( "<fieldset><legend>Associations</legend>\n<table>" );
+                descriptor.state().associations().forEach( associationType -> {
+                    Object value = entity.associationValueOf( associationType.qualifiedName() );
+                    if( value == null )
+                    {
+                        value = "";
+                    }
+                    out.println( "<tr><td>"
+                                 + "<label for=\"" + associationType.qualifiedName() + "\" >"
+                                 + associationType.qualifiedName().name()
+                                 + "</label></td>\n"
+                                 + "<td><input "
+                                 + "type=\"text\" "
+                                 + "size=\"80\" "
+                                 + "name=\"" + associationType.qualifiedName() + "\" "
+                                 + "value=\"" + value + "\"/></td></tr>" );
+                } );
+                out.println( "</table></fieldset>\n" );
+
+                out.println( "<fieldset><legend>ManyAssociations</legend>\n<table>" );
+                descriptor.state().manyAssociations().forEach( associationType -> {
+                    ManyAssociationState references = entity.manyAssociationValueOf( associationType.qualifiedName() );
+                    String value = "";
+                    for( EntityReference reference : references )
+                    {
+                        value += reference.identity() + "\n";
+                    }
+
+                    out.println( "<tr><td>"
+                                 + "<label for=\"" + associationType.qualifiedName() + "\" >"
+                                 + associationType.qualifiedName().name()
+                                 + "</label></td>\n"
+                                 + "<td><textarea "
+                                 + "rows=\"10\" "
+                                 + "cols=\"80\" "
+                                 + "name=\"" + associationType.qualifiedName() + "\" >"
+                                 + value
+                                 + "</textarea></td></tr>" );
+                });
+                out.println( "</table></fieldset>\n" );
+
+                out.println( "<fieldset><legend>NamedAssociations</legend>\n<table>" );
+                descriptor.state().namedAssociations().forEach( associationType -> {
+                    NamedAssociationState identities = entity.namedAssociationValueOf( associationType.qualifiedName() );
+                    String value = "";
+                    for( String name : identities )
+                    {
+                        value += name + "\n" + identities.get( name ).identity() + "\n";
+                    }
+
+                    out.println( "<tr><td>"
+                                 + "<label for=\"" + associationType.qualifiedName() + "\" >"
+                                 + associationType.qualifiedName().name()
+                                 + "</label></td>\n"
+                                 + "<td><textarea "
+                                 + "rows=\"10\" "
+                                 + "cols=\"80\" "
+                                 + "name=\"" + associationType.qualifiedName() + "\" >"
+                                 + value
+                                 + "</textarea></td></tr>" );
+                } );
+                out.println( "</table></fieldset>\n" );
+
+                out.println( "<input type=\"submit\" value=\"Update\"/></form>\n" );
+
+                out.println( "</body></html>\n" );
+            }
+        };
+    }
+
+    private Representation representJson( EntityState entityState )
+    {
+        // TODO This guy needs to represent an Entity as JSON
+        if( entityState instanceof JSONEntityState )
+        {
+            JSONEntityState jsonState = (JSONEntityState) entityState;
+            return new StringRepresentation( jsonState.state().toString(), MediaType.APPLICATION_JSON );
+        }
+        else
+        {
+            throw new ResourceException( Status.CLIENT_ERROR_NOT_ACCEPTABLE );
+        }
+    }
+
+    private Representation representRdfXml( final EntityState entity )
+        throws ResourceException
+    {
+        Representation representation = new WriterRepresentation( MediaType.APPLICATION_RDF_XML )
+        {
+            @Override
+            public void write( Writer writer )
+                throws IOException
+            {
+                try
+                {
+                    Iterable<Statement> statements = entitySerializer.serialize( entity );
+                    new RdfXmlSerializer().serialize( statements, writer );
+                }
+                catch( RDFHandlerException e )
+                {
+                    throw new IOException( e );
+                }
+            }
+        };
+        representation.setCharacterSet( CharacterSet.UTF_8 );
+        return representation;
+    }
+
+    @Override
+    protected Representation put( Representation representation, Variant variant )
+        throws ResourceException
+    {
+        return post( representation, variant );
+    }
+
+    @Override
+    public Representation post( Representation entityRepresentation, Variant variant )
+        throws ResourceException
+    {
+        Usecase usecase = UsecaseBuilder.newUsecase( "Update entity" );
+        EntityStoreUnitOfWork unitOfWork = entityStore.newUnitOfWork( module, usecase, SystemTime.now() );
+        EntityState entity = getEntityState( unitOfWork );
+
+        Form form = new Form( entityRepresentation );
+
+        try
+        {
+            final EntityDescriptor descriptor = entity.entityDescriptor();
+
+            // Parse JSON into properties
+            descriptor.state().properties().forEach( persistentProperty -> {
+                if( !persistentProperty.isImmutable() )
+                {
+                    String formValue = form.getFirstValue( persistentProperty.qualifiedName().name(), null );
+                    if( formValue == null )
+                    {
+                        entity.setPropertyValue( persistentProperty.qualifiedName(), null );
+                    }
+                    else
+                    {
+                        entity.setPropertyValue(
+                            persistentProperty.qualifiedName(),
+                            serialization.deserialize( module, persistentProperty.valueType(), formValue ) );
+                    }
+                }
+            } );
+
+            descriptor.state().associations().forEach( associationType -> {
+                String newStringAssociation = form.getFirstValue( associationType.qualifiedName().name() );
+                if( newStringAssociation == null || newStringAssociation.isEmpty() )
+                {
+                    entity.setAssociationValue( associationType.qualifiedName(), null );
+                }
+                else
+                {
+                    entity.setAssociationValue( associationType.qualifiedName(),
+                                                EntityReference.parseEntityReference( newStringAssociation ) );
+                }
+            } );
+            descriptor.state().manyAssociations().forEach( associationType -> {
+                String newStringAssociation = form.getFirstValue( associationType.qualifiedName().name() );
+                ManyAssociationState manyAssociation = entity.manyAssociationValueOf( associationType.qualifiedName() );
+                if( newStringAssociation == null )
+                {
+                    // Remove "left-overs"
+                    manyAssociation.clear();
+                }
+                else
+                {
+                    BufferedReader bufferedReader = new BufferedReader( new StringReader( newStringAssociation ) );
+                    String identity;
+
+                    try
+                    {
+                        // Synchronize old and new association
+                        int index = 0;
+                        while( ( identity = bufferedReader.readLine() ) != null )
+                        {
+                            EntityReference reference = EntityReference.parseEntityReference( identity );
+
+                            if( manyAssociation.count() < index && manyAssociation.get( index ).equals( reference ) )
+                            {
+                                continue;
+                            }
+
+                            try
+                            {
+                                unitOfWork.entityStateOf( module, reference );
+
+                                manyAssociation.remove( reference );
+                                manyAssociation.add( index++, reference );
+                            }
+                            catch( EntityNotFoundException e )
+                            {
+                                // Ignore this entity - doesn't exist
+                            }
+                        }
+
+                        // Remove "left-overs"
+                        while( manyAssociation.count() > index )
+                        {
+                            manyAssociation.remove( manyAssociation.get( index ) );
+                        }
+                    }
+                    catch( IOException e )
+                    {
+                        // Ignore
+                    }
+                }
+            } );
+            descriptor.state().namedAssociations().forEach( associationType -> {
+                String newStringAssociation = form.getFirstValue( associationType.qualifiedName().name() );
+                NamedAssociationState namedAssociation = entity.namedAssociationValueOf( associationType.qualifiedName() );
+                if( newStringAssociation == null )
+                {
+                    // Remove "left-overs"
+                    namedAssociation.clear();
+                }
+                else
+                {
+                    Set<String> names = new HashSet<>();
+                    BufferedReader bufferedReader = new BufferedReader( new StringReader( newStringAssociation ) );
+                    String line;
+                    try
+                    {
+                        while( ( line = bufferedReader.readLine() ) != null )
+                        {
+                            String name = line;
+                            line = bufferedReader.readLine();
+                            if( line == null )
+                            {
+                                break;
+                            }
+                            String identity = line;
+                            EntityReference reference = EntityReference.parseEntityReference( identity );
+                            try
+                            {
+                                unitOfWork.entityStateOf( module, reference );
+
+                                namedAssociation.remove( name );
+                                namedAssociation.put( name, reference );
+
+                                names.add( name );
+                            }
+                            catch( EntityNotFoundException e )
+                            {
+                                // Ignore this entity - doesn't exist
+                            }
+                        }
+
+                        // Remove "left-overs"
+                        StreamSupport.stream( namedAssociation.spliterator(), false )
+                            .filter( assocName -> !names.contains( assocName ) )
+                            .forEach( namedAssociation::remove );
+                    }
+                    catch( IOException e )
+                    {
+                        // Ignore
+                    }
+                }
+            } );
+        }
+        catch( SerializationException | IllegalArgumentException e )
+        {
+            throw new ResourceException( Status.SERVER_ERROR_INTERNAL, e );
+        }
+
+        try
+        {
+            unitOfWork.applyChanges().commit();
+        }
+        catch( ConcurrentEntityStateModificationException e )
+        {
+            throw new ResourceException( Status.CLIENT_ERROR_CONFLICT );
+        }
+        catch( EntityNotFoundException e )
+        {
+            throw new ResourceException( Status.CLIENT_ERROR_GONE );
+        }
+
+        getResponse().setStatus( Status.SUCCESS_RESET_CONTENT );
+
+        return new EmptyRepresentation();
+    }
+}
diff --git a/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/ExceptionRepresentation.java b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/ExceptionRepresentation.java
new file mode 100644
index 0000000..ea9eafe
--- /dev/null
+++ b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/ExceptionRepresentation.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import org.restlet.representation.StringRepresentation;
+
+public class ExceptionRepresentation
+    extends StringRepresentation
+{
+    public ExceptionRepresentation( Throwable e )
+    {
+        super( getStackTraceAsHtml( e ) );
+    }
+
+    private static String getStackTraceAsHtml( Throwable e )
+    {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        PrintStream out = new PrintStream( baos );
+        e.printStackTrace( out );
+        out.close();
+        try
+        {
+            baos.close();
+        }
+        catch( IOException e1 )
+        {
+            // Can not happen.
+        }
+        String text = baos.toString();
+        return "<code>" + text + "</code>";
+    }
+}
diff --git a/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/ExtensionMediaTypeFilter.java b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/ExtensionMediaTypeFilter.java
new file mode 100644
index 0000000..1ceffe0
--- /dev/null
+++ b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/ExtensionMediaTypeFilter.java
@@ -0,0 +1,87 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import java.util.Collections;
+import java.util.List;
+import org.restlet.Context;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.Restlet;
+import org.restlet.data.MediaType;
+import org.restlet.data.Metadata;
+import org.restlet.data.Preference;
+import org.restlet.routing.Filter;
+import org.restlet.service.MetadataService;
+
+/**
+ * Check the extension used and set the corresponding media type
+ * in the request. Then remove the extension from the request resource name.
+ */
+public class ExtensionMediaTypeFilter
+    extends Filter
+{
+
+    public ExtensionMediaTypeFilter()
+    {
+    }
+
+    public ExtensionMediaTypeFilter( Context context )
+    {
+        super( context );
+    }
+
+    public ExtensionMediaTypeFilter( Context context, Restlet next )
+    {
+        super( context, next );
+    }
+
+    @Override
+    protected int beforeHandle( Request request, Response response )
+    {
+        List<String> segments = request.getResourceRef().getSegments();
+        if (segments.get( segments.size()-1 ).equals(""))
+          return Filter.CONTINUE;
+
+        String extensions = request.getResourceRef().getExtensions();
+        if( extensions != null )
+        {
+            int idx = extensions.lastIndexOf( "." );
+            if( idx != -1 )
+            {
+                extensions = extensions.substring( idx + 1 );
+            }
+
+            MetadataService metadataService = getApplication().getMetadataService();
+            Metadata metadata = metadataService.getMetadata( extensions );
+            if( metadata != null && metadata instanceof MediaType )
+            {
+                request.getClientInfo()
+                    .setAcceptedMediaTypes( Collections.singletonList( new Preference<>( (MediaType) metadata ) ) );
+                String path = request.getResourceRef().getPath();
+                path = path.substring( 0, path.length() - extensions.length() - 1 );
+                request.getResourceRef().setPath( path );
+            }
+        }
+
+        return Filter.CONTINUE;
+    }
+}
diff --git a/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/IndexResource.java b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/IndexResource.java
new file mode 100644
index 0000000..971b405
--- /dev/null
+++ b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/IndexResource.java
@@ -0,0 +1,130 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import java.io.*;
+import java.util.Arrays;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.index.rdf.indexing.RdfExporter;
+import org.restlet.data.MediaType;
+import org.restlet.representation.OutputRepresentation;
+import org.restlet.representation.Representation;
+import org.restlet.representation.Variant;
+import org.restlet.resource.ResourceException;
+import org.restlet.resource.ServerResource;
+
+/**
+ * Show RDF index
+ */
+public class IndexResource
+    extends ServerResource
+{
+    @Service
+    private RdfExporter exporter;
+
+    public IndexResource()
+    {
+        getVariants().addAll( Arrays.asList(
+            new Variant( MediaType.TEXT_PLAIN ),
+            new Variant( MediaType.APPLICATION_RDF_TRIG ),
+            new Variant( MediaType.APPLICATION_RDF_XML ) ) );
+
+        setNegotiated( true );
+    }
+
+    @Override
+    public Representation get( Variant variant )
+        throws ResourceException
+    {
+        if( variant.getMediaType().equals( MediaType.APPLICATION_RDF_XML ) )
+        {
+            return new RdfXmlOutputRepresentation();
+        }
+        else if( variant.getMediaType().equals( MediaType.APPLICATION_RDF_TRIG ) )
+        {
+            return new RdfTrigOutputRepresentation( MediaType.APPLICATION_RDF_TRIG );
+        }
+        else if( variant.getMediaType().equals( MediaType.TEXT_PLAIN ) )
+        {
+            return new RdfTrigOutputRepresentation( MediaType.TEXT_PLAIN );
+        }
+
+        return null;
+    }
+
+    private class RdfTrigOutputRepresentation
+        extends OutputRepresentation
+    {
+        public RdfTrigOutputRepresentation( MediaType mediaType )
+        {
+            super( mediaType );
+        }
+
+        @Override
+        public void write( OutputStream outputStream )
+            throws IOException
+        {
+            PrintStream ps = null;
+            try
+            {
+                ps = new PrintStream( outputStream );
+                exporter.exportReadableToStream( ps );
+            }
+            finally
+            {
+                if( ps != null )
+                {
+                    ps.close();
+                }
+            }
+        }
+    }
+
+    private class RdfXmlOutputRepresentation
+        extends OutputRepresentation
+    {
+        public RdfXmlOutputRepresentation()
+        {
+            super( MediaType.APPLICATION_RDF_XML );
+        }
+
+        @Override
+        public void write( OutputStream outputStream )
+            throws IOException
+        {
+            PrintWriter pw = null;
+            try
+            {
+                OutputStreamWriter osw = new OutputStreamWriter( outputStream, "UTF-8" );
+                pw = new PrintWriter( osw );
+                exporter.exportFormalToWriter( pw );
+                pw.flush();
+            }
+            finally
+            {
+                if( pw != null )
+                {
+                    pw.close();
+                }
+            }
+        }
+    }
+}
diff --git a/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/PolygeneFinder.java b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/PolygeneFinder.java
new file mode 100644
index 0000000..b261ed3
--- /dev/null
+++ b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/PolygeneFinder.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.resource.Finder;
+import org.restlet.resource.ServerResource;
+
+public class PolygeneFinder
+    extends Finder
+{
+    @Structure
+    private ObjectFactory factory;
+
+    public PolygeneFinder()
+    {
+    }
+
+    @Override
+    public ServerResource create( Class<? extends ServerResource> targetClass, Request request, Response response )
+    {
+        return factory.newObject( targetClass );
+    }
+}
diff --git a/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/PolygeneServerServlet.java b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/PolygeneServerServlet.java
new file mode 100644
index 0000000..f9e2490
--- /dev/null
+++ b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/PolygeneServerServlet.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.structure.Module;
+import org.restlet.Application;
+import org.restlet.Context;
+import org.restlet.ext.servlet.ServerServlet;
+
+/**
+ * Integration with Polygene. Register an object extending Application to use.
+ */
+public class PolygeneServerServlet
+    extends ServerServlet
+{
+    @Structure
+    Module module;
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    protected Application createApplication( Context context )
+    {
+        return module.newObject( Application.class, context.createChildContext(), getServletConfig(), getServletContext() );
+    }
+}
diff --git a/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/PolygeneServerServletService.java b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/PolygeneServerServletService.java
new file mode 100644
index 0000000..e024c02
--- /dev/null
+++ b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/PolygeneServerServletService.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import javax.servlet.Servlet;
+import org.apache.polygene.api.mixin.Mixins;
+
+/**
+ * JAVADOC
+ */
+@Mixins( PolygeneServerServlet.class )
+public interface PolygeneServerServletService
+    extends Servlet
+{
+}
diff --git a/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestApplication.java b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestApplication.java
new file mode 100644
index 0000000..7dbda57
--- /dev/null
+++ b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestApplication.java
@@ -0,0 +1,117 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.restlet.Application;
+import org.restlet.Context;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.Restlet;
+import org.restlet.data.MediaType;
+import org.restlet.data.Status;
+import org.restlet.resource.Finder;
+import org.restlet.resource.ServerResource;
+import org.restlet.routing.Router;
+
+public class RestApplication
+    extends Application
+{
+    public static final MediaType APPLICATION_SPARQL_JSON = new MediaType( "application/sparql-results+json", "SPARQL JSON" );
+
+    @Structure
+    private ObjectFactory objectFactory;
+
+    @Structure
+    private UnitOfWorkFactory uowf;
+
+    public RestApplication( @Uses Context parentContext )
+    {
+        super( parentContext );
+
+        getMetadataService().addExtension( "srj", APPLICATION_SPARQL_JSON );
+
+        getTunnelService().setExtensionsTunnel( true );
+    }
+
+    @Override
+    public void handle( Request request, Response response )
+    {
+        UnitOfWork uow = uowf.newUnitOfWork();
+        try
+        {
+            super.handle( request, response );
+            uow.complete();
+        }
+        catch( UnitOfWorkException e )
+        {
+            uow.discard();
+            response.setStatus( Status.CLIENT_ERROR_NOT_ACCEPTABLE );
+            response.setEntity( new ExceptionRepresentation( e ) );
+            // More info to send...
+        }
+        catch( ConcurrentEntityModificationException e )
+        {
+            uow.discard();
+            response.setStatus( Status.CLIENT_ERROR_LOCKED );
+            response.setEntity( new ExceptionRepresentation( e ) );
+            // Info to try again...
+        }
+        catch( UnitOfWorkCompletionException e )
+        {
+            uow.discard();
+            response.setStatus( Status.CLIENT_ERROR_NOT_ACCEPTABLE );
+            response.setEntity( new ExceptionRepresentation( e ) );
+        }
+    }
+
+    /**
+     * Creates a root Restlet that will receive all incoming calls.
+     */
+    @Override
+    public synchronized Restlet createInboundRoot()
+    {
+        Router router = new Router( getContext() );
+
+        router.attach( "/entity", newFinder( EntitiesResource.class ) );
+        router.attach( "/entity/{reference}", newFinder( EntityResource.class ) );
+
+        router.attach( "/query", newFinder( SPARQLResource.class ) );
+        router.attach( "/query/sparqlhtml", newFinder( SPARQLResource.class ) );
+        router.attach( "/query/index", newFinder( IndexResource.class ) );
+
+        return router;
+    }
+
+    private Finder newFinder( Class<? extends ServerResource> resource )
+    {
+        Finder finder = objectFactory.newObject( Finder.class );
+        finder.setTargetClass( resource );
+        return finder;
+    }
+}
diff --git a/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestAssembler.java b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestAssembler.java
new file mode 100644
index 0000000..0e28856
--- /dev/null
+++ b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestAssembler.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+public class RestAssembler
+    extends Assemblers.Visibility<RestAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.objects( RestApplication.class ).visibleIn( visibility() );
+        module.objects( PolygeneFinder.class,
+                        EntitiesResource.class,
+                        EntityResource.class,
+                        IndexResource.class,
+                        SPARQLResource.class );
+    }
+}
diff --git a/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestServer.java b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestServer.java
new file mode 100644
index 0000000..49d282f
--- /dev/null
+++ b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestServer.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+public interface RestServer
+{
+}
diff --git a/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestServerComposite.java b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestServerComposite.java
new file mode 100644
index 0000000..9bb5fda
--- /dev/null
+++ b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestServerComposite.java
@@ -0,0 +1,58 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceReference;
+
+@Mixins( { RestServerMixin.class } )
+@Activators( RestServerComposite.Activator.class )
+public interface RestServerComposite
+    extends RestServer
+{
+    
+    void startServer()
+            throws Exception;
+    
+    void stopServer()
+            throws Exception;
+    
+    class Activator extends ActivatorAdapter<ServiceReference<RestServerComposite>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<RestServerComposite> activated )
+                throws Exception
+        {
+            activated.get().startServer();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<RestServerComposite> passivating )
+                throws Exception
+        {
+            passivating.get().stopServer();
+        }
+        
+    }
+}
diff --git a/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestServerConfiguration.java b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestServerConfiguration.java
new file mode 100644
index 0000000..214ff19
--- /dev/null
+++ b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestServerConfiguration.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * RestServer Configuration.
+ */
+public interface RestServerConfiguration
+{
+    @UseDefaults( "8192" )
+    Property<Integer> port();
+}
diff --git a/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestServerMixin.java b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestServerMixin.java
new file mode 100644
index 0000000..9ac1a3c
--- /dev/null
+++ b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/RestServerMixin.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.structure.Module;
+import org.restlet.Component;
+import org.restlet.data.Protocol;
+
+public abstract class RestServerMixin
+    implements RestServerComposite
+{
+    @Structure
+    private Module module;
+
+    @This
+    private Configuration<RestServerConfiguration> configuration;
+
+    private Component component;
+
+    @Override
+    public void startServer()
+        throws Exception
+    {
+        configuration.refresh();
+
+        component = new Component();
+        component.getServers().add( Protocol.HTTP, configuration.get().port().get() );
+        RestApplication application = module.newObject( RestApplication.class, component.getContext() );
+        component.getDefaultHost().attach( application );
+        component.start();
+    }
+
+    @Override
+    public void stopServer()
+        throws Exception
+    {
+        component.stop();
+    }
+}
diff --git a/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/SPARQLResource.java b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/SPARQLResource.java
new file mode 100644
index 0000000..1b76ef1
--- /dev/null
+++ b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/SPARQLResource.java
@@ -0,0 +1,383 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import info.aduna.xml.XMLWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import org.openrdf.http.protocol.Protocol;
+import org.openrdf.model.URI;
+import org.openrdf.model.Value;
+import org.openrdf.query.*;
+import org.openrdf.query.impl.DatasetImpl;
+import org.openrdf.query.resultio.TupleQueryResultWriter;
+import org.openrdf.query.resultio.sparqljson.SPARQLResultsJSONWriterFactory;
+import org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLWriter;
+import org.openrdf.repository.Repository;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+import org.apache.polygene.api.injection.scope.Service;
+import org.restlet.data.Form;
+import org.restlet.data.MediaType;
+import org.restlet.data.Method;
+import org.restlet.data.Status;
+import org.restlet.representation.InputRepresentation;
+import org.restlet.representation.OutputRepresentation;
+import org.restlet.representation.Representation;
+import org.restlet.representation.Variant;
+import org.restlet.resource.ResourceException;
+import org.restlet.resource.ServerResource;
+
+import static org.openrdf.http.protocol.Protocol.*;
+
+/**
+ * JAVADOC
+ */
+public class SPARQLResource
+    extends ServerResource
+{
+    @Service
+    Repository repository;
+
+    public SPARQLResource()
+    {
+        getVariants().addAll( Arrays.asList(
+            new Variant( MediaType.TEXT_HTML ),
+            new Variant( MediaType.APPLICATION_RDF_XML ),
+            new Variant( RestApplication.APPLICATION_SPARQL_JSON ) ) );
+        setNegotiated( true );
+    }
+
+    @Override
+    protected void doInit()
+        throws ResourceException
+    {
+        super.doInit();
+    }
+
+    @Override
+    public Representation get( final Variant variant )
+        throws ResourceException
+    {
+        try
+        {
+            // TODO There's probably a helper somewhere that can do this more nicely
+            if( getRequest().getOriginalRef().getLastSegment().equals( "sparqlhtml.xsl" ) )
+            {
+                InputStream resourceAsStream = getClass().getResourceAsStream( "sparqlhtml.xsl" );
+                return new InputRepresentation( resourceAsStream, MediaType.TEXT_XML );
+            }
+
+            Form form;
+            if( getRequest().getMethod().equals( Method.POST ) )
+            {
+                form = new Form(getRequest().getEntity());
+            }
+            else
+            {
+                form = getRequest().getResourceRef().getQueryAsForm();
+            }
+
+            final RepositoryConnection conn = repository.getConnection();
+
+            String queryStr = form.getFirstValue( "query" );
+
+            if( queryStr == null )
+            {
+                InputStream resourceAsStream = getClass().getResourceAsStream( "sparqlform.html" );
+                return new InputRepresentation( resourceAsStream, MediaType.TEXT_HTML );
+            }
+
+            Query query = getQuery( repository, conn, queryStr );
+
+            if( query instanceof TupleQuery )
+            {
+                TupleQuery tQuery = (TupleQuery) query;
+
+                final TupleQueryResult queryResult = tQuery.evaluate();
+
+                if( variant.getMediaType().equals( MediaType.TEXT_HTML ) )
+                {
+                    return new OutputRepresentation( MediaType.TEXT_XML )
+                    {
+                        @Override
+                        public void write( OutputStream outputStream )
+                            throws IOException
+                        {
+                            try
+                            {
+                                PrintWriter out = new PrintWriter( outputStream );
+                                out.println( "<?xml version='1.0' encoding='UTF-8'?>" );
+                                out.println( "<?xml-stylesheet type=\"text/xsl\" href=\"query/sparqlhtml.xsl\"?>" );
+                                out.flush();
+                                TupleQueryResultWriter qrWriter = new SPARQLResultsXMLWriter( new XMLWriter( outputStream )
+                                {
+                                    @Override
+                                    public void startDocument()
+                                        throws IOException
+                                    {
+                                        // Ignore
+                                    }
+                                } );
+                                QueryResultUtil.report( queryResult, qrWriter );
+                            }
+                            catch( Exception e )
+                            {
+                                throw new IOException( e );
+                            }
+                            finally
+                            {
+                                try
+                                {
+                                    conn.close();
+                                }
+                                catch( RepositoryException e )
+                                {
+                                    // Ignore
+                                }
+                            }
+                        }
+                    };
+                }
+                else if( variant.getMediaType().equals( MediaType.APPLICATION_RDF_XML ) )
+                {
+                    return new OutputRepresentation( MediaType.APPLICATION_XML )
+                    {
+                        @Override
+                        public void write( OutputStream outputStream )
+                            throws IOException
+                        {
+                            try
+                            {
+                                TupleQueryResultWriter qrWriter = new SPARQLResultsXMLWriter( new XMLWriter( outputStream ) );
+                                QueryResultUtil.report( queryResult, qrWriter );
+                            }
+                            catch( Exception e )
+                            {
+                                throw new IOException( e );
+                            }
+                            finally
+                            {
+                                try
+                                {
+                                    conn.close();
+                                }
+                                catch( RepositoryException e )
+                                {
+                                    // Ignore
+                                }
+                            }
+                        }
+                    };
+                }
+                else if( variant.getMediaType().equals( RestApplication.APPLICATION_SPARQL_JSON ) )
+                {
+                    return new OutputRepresentation( RestApplication.APPLICATION_SPARQL_JSON )
+                    {
+                        @Override
+                        public void write( OutputStream outputStream )
+                            throws IOException
+                        {
+                            try
+                            {
+                                TupleQueryResultWriter qrWriter = new SPARQLResultsJSONWriterFactory().getWriter( outputStream );
+                                QueryResultUtil.report( queryResult, qrWriter );
+                            }
+                            catch( Exception e )
+                            {
+                                throw new IOException( e );
+                            }
+                            finally
+                            {
+                                try
+                                {
+                                    conn.close();
+                                }
+                                catch( RepositoryException e )
+                                {
+                                    // Ignore
+                                }
+                            }
+                        }
+                    };
+                }
+            }
+            else if( query instanceof GraphQuery )
+            {
+                GraphQuery gQuery = (GraphQuery) query;
+
+                /*
+                                queryResult = gQuery.evaluate();
+                                registry = RDFWriterRegistry.getInstance();
+                                view = GraphQueryResultView.getInstance();
+                */
+                conn.close();
+            }
+            else if( query instanceof BooleanQuery )
+            {
+                BooleanQuery bQuery = (BooleanQuery) query;
+
+                /*
+                                queryResult = bQuery.evaluate();
+                                registry = BooleanQueryResultWriterRegistry.getInstance();
+                                view = BooleanQueryResultView.getInstance();
+                */
+                conn.close();
+            }
+            else
+            {
+                conn.close();
+                throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, "Unsupported query type: "
+                                                                              + query.getClass().getName() );
+            }
+        }
+        catch( RepositoryException e )
+        {
+            throw new ResourceException( Status.SERVER_ERROR_INTERNAL, e );
+        }
+        catch( QueryEvaluationException e )
+        {
+            throw new ResourceException( Status.SERVER_ERROR_INTERNAL, e );
+        }
+
+        return null;
+    }
+
+    private Query getQuery( Repository repository, RepositoryConnection repositoryCon, String queryStr
+    )
+        throws ResourceException
+    {
+        Form form = getRequest().getResourceRef().getQueryAsForm();
+
+        Query result;
+
+// default query language is SPARQL
+        QueryLanguage queryLn = QueryLanguage.SPARQL;
+
+// determine if inferred triples should be included in query evaluation
+        boolean includeInferred = true;
+
+// build a dataset, if specified
+        String[] defaultGraphURIs = form.getValuesArray( DEFAULT_GRAPH_PARAM_NAME );
+        String[] namedGraphURIs = form.getValuesArray( NAMED_GRAPH_PARAM_NAME );
+
+        DatasetImpl dataset = null;
+        if( defaultGraphURIs.length > 0 || namedGraphURIs.length > 0 )
+        {
+            dataset = new DatasetImpl();
+
+            if( defaultGraphURIs.length > 0 )
+            {
+                for( String defaultGraphURI : defaultGraphURIs )
+                {
+                    try
+                    {
+                        URI uri = repository.getValueFactory().createURI( defaultGraphURI );
+                        dataset.addDefaultGraph( uri );
+                    }
+                    catch( IllegalArgumentException e )
+                    {
+                        throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, "Illegal URI for default graph: "
+                                                                                      + defaultGraphURI );
+                    }
+                }
+            }
+
+            if( namedGraphURIs.length > 0 )
+            {
+                for( String namedGraphURI : namedGraphURIs )
+                {
+                    try
+                    {
+                        URI uri = repository.getValueFactory().createURI( namedGraphURI );
+                        dataset.addNamedGraph( uri );
+                    }
+                    catch( IllegalArgumentException e )
+                    {
+                        throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, "Illegal URI for named graph: "
+                                                                                      + namedGraphURI );
+                    }
+                }
+            }
+        }
+
+        try
+        {
+            result = repositoryCon.prepareQuery( queryLn, queryStr );
+            result.setIncludeInferred( includeInferred );
+
+            if( dataset != null )
+            {
+                result.setDataset( dataset );
+            }
+
+// determine if any variable bindings have been set on this query.
+            @SuppressWarnings( "unchecked" )
+            Enumeration<String> parameterNames = Collections.enumeration( form.getValuesMap().keySet() );
+
+            while( parameterNames.hasMoreElements() )
+            {
+                String parameterName = parameterNames.nextElement();
+
+                if( parameterName.startsWith( BINDING_PREFIX ) && parameterName.length() > BINDING_PREFIX.length() )
+                {
+                    String bindingName = parameterName.substring( BINDING_PREFIX.length() );
+                    Value bindingValue = parseValueParam( repository, form, parameterName );
+                    result.setBinding( bindingName, bindingValue );
+                }
+            }
+        }
+        catch( UnsupportedQueryLanguageException e )
+        {
+            throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, e.getMessage() );
+        }
+        catch( MalformedQueryException e )
+        {
+            throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, e.getMessage() );
+        }
+        catch( RepositoryException e )
+        {
+            throw new ResourceException( Status.SERVER_ERROR_INTERNAL, e.getMessage() );
+        }
+
+        return result;
+    }
+
+    private Value parseValueParam( Repository repository, Form form, String parameterName )
+        throws ResourceException
+    {
+        String paramValue = form.getFirstValue( parameterName );
+        try
+        {
+            return Protocol.decodeValue( paramValue, repository.getValueFactory() );
+        }
+        catch( IllegalArgumentException e )
+        {
+            throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, "Invalid value for parameter '" + parameterName + "': "
+                                                                          + paramValue );
+        }
+    }
+}
diff --git a/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/package.html b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/package.html
new file mode 100644
index 0000000..ad45a8e
--- /dev/null
+++ b/libraries/rest/src/main/java/org/apache/polygene/library/rest/admin/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>ReST EntityStore, Index & Query Library.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/EntitiesResource.java b/libraries/rest/src/main/java/org/qi4j/library/rest/admin/EntitiesResource.java
deleted file mode 100644
index b643178..0000000
--- a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/EntitiesResource.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.io.Writer;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.spi.query.EntityFinder;
-import org.qi4j.spi.query.EntityFinderException;
-import org.restlet.data.CharacterSet;
-import org.restlet.data.MediaType;
-import org.restlet.data.Status;
-import org.restlet.ext.atom.Entry;
-import org.restlet.ext.atom.Feed;
-import org.restlet.ext.atom.Link;
-import org.restlet.ext.atom.Text;
-import org.restlet.representation.EmptyRepresentation;
-import org.restlet.representation.OutputRepresentation;
-import org.restlet.representation.Representation;
-import org.restlet.representation.Variant;
-import org.restlet.representation.WriterRepresentation;
-import org.restlet.resource.ResourceException;
-import org.restlet.resource.ServerResource;
-
-/**
- * Listing of all Entities.
- * <p>
- * Mapped to /entity
- * </p>
- */
-public class EntitiesResource
-    extends ServerResource
-{
-
-    @Service
-    private EntityFinder entityFinder;
-    @Service
-    private ValueSerialization valueSerialization;
-
-    public EntitiesResource()
-    {
-        super();
-
-        // Define the supported variants.
-        getVariants().addAll(
-            Arrays.asList( new Variant( MediaType.TEXT_HTML ), new Variant( MediaType.APPLICATION_RDF_XML ),
-                           new Variant( MediaType.APPLICATION_JSON ), new Variant( MediaType.APPLICATION_ATOM ) ) );
-
-        setNegotiated( true );
-    }
-
-    @Override
-    protected Representation get( Variant variant )
-        throws ResourceException
-    {
-        System.out.println( "VARIANT: " + variant.getMediaType() );
-        // Generate the right representation according to its media type.
-        if( MediaType.APPLICATION_JSON.equals( variant.getMediaType() ) )
-        {
-            return representJson();
-        }
-        else if( MediaType.APPLICATION_RDF_XML.equals( variant.getMediaType() ) )
-        {
-            return representRdf();
-        }
-        else if( MediaType.TEXT_HTML.equals( variant.getMediaType() ) )
-        {
-            return representHtml();
-        }
-        else if( MediaType.APPLICATION_ATOM.equals( variant.getMediaType() ) )
-        {
-            return representAtom();
-        }
-
-        throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
-    }
-
-    private Representation representJson()
-        throws ResourceException
-    {
-        try
-        {
-            final Iterable<EntityReference> query = entityFinder.findEntities( EntityComposite.class, null, null, null, null, Collections.<String, Object>emptyMap() );
-            return new OutputRepresentation( MediaType.APPLICATION_JSON )
-            {
-                @Override
-                public void write( OutputStream outputStream )
-                    throws IOException
-                {
-                    valueSerialization.serialize( query, outputStream );
-                }
-            };
-        }
-        catch( Exception e )
-        {
-            throw new ResourceException( e );
-        }
-    }
-
-    private Representation representRdf()
-        throws ResourceException
-    {
-        try
-        {
-            final Iterable<EntityReference> query = entityFinder.findEntities( EntityComposite.class, null, null, null, null, Collections.<String, Object>emptyMap() );
-
-            WriterRepresentation representation = new WriterRepresentation( MediaType.APPLICATION_RDF_XML )
-            {
-                @Override
-                public void write( Writer writer )
-                    throws IOException
-                {
-                    PrintWriter out = new PrintWriter( writer );
-                    out.println( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<rdf:RDF\n"
-                                 + "\txmlns=\"urn:qi4j:\"\n" + "\txmlns:qi4j=\"http://www.qi4j.org/rdf/model/1.0/\"\n"
-                                 + "\txmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n"
-                                 + "\txmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">" );
-                    for( EntityReference qualifiedIdentity : query )
-                    {
-                        out.println( "<qi4j:entity rdf:about=\"" + getRequest().getResourceRef().getPath() + "/"
-                                     + qualifiedIdentity.identity() + ".rdf\"/>" );
-                    }
-
-                    out.println( "</rdf:RDF>" );
-                }
-            };
-            representation.setCharacterSet( CharacterSet.UTF_8 );
-
-            return representation;
-        }
-        catch( EntityFinderException e )
-        {
-            throw new ResourceException( Status.SERVER_ERROR_INTERNAL, e );
-        }
-    }
-
-    private Representation representHtml()
-        throws ResourceException
-    {
-        try
-        {
-            final Iterable<EntityReference> query = entityFinder.findEntities( EntityComposite.class, null, null, null, null, Collections.<String, Object>emptyMap() );
-            Representation representation = new WriterRepresentation( MediaType.TEXT_HTML )
-            {
-                @Override
-                public void write( Writer buf )
-                    throws IOException
-                {
-                    PrintWriter out = new PrintWriter( buf );
-                    out.println( "<html><head><title>All entities</title></head><body><h1>All entities</h1><ul>" );
-
-                    for( EntityReference entity : query )
-                    {
-                        out.println( "<li><a href=\""
-                                     + getRequest().getResourceRef().clone().addSegment( entity.identity() + ".html" )
-                                     + "\">" + entity.identity() + "</a></li>" );
-                    }
-                    out.println( "</ul></body></html>" );
-                }
-            };
-            representation.setCharacterSet( CharacterSet.UTF_8 );
-            return representation;
-        }
-        catch( EntityFinderException e )
-        {
-            throw new ResourceException( e );
-        }
-    }
-
-    private Representation representAtom()
-        throws ResourceException
-    {
-        try
-        {
-            Feed feed = new Feed();
-            feed.setTitle( new Text( MediaType.TEXT_PLAIN, "All entities" ) );
-            List<Entry> entries = feed.getEntries();
-            final Iterable<EntityReference> query = entityFinder.findEntities( EntityComposite.class, null, null, null, null, Collections.<String, Object>emptyMap() );
-            for( EntityReference entityReference : query )
-            {
-                Entry entry = new Entry();
-                entry.setTitle( new Text( MediaType.TEXT_PLAIN, entityReference.toString() ) );
-                Link link = new Link();
-                link.setHref( getRequest().getResourceRef().clone().addSegment( entityReference.identity() ) );
-                entry.getLinks().add( link );
-                entries.add( entry );
-            }
-
-            return feed;
-        }
-        catch( Exception e )
-        {
-            throw new ResourceException( e );
-        }
-    }
-
-    @Override
-    protected Representation post( Representation entity, Variant variant )
-        throws ResourceException
-    {
-        try
-        {
-            /*
-             * InputStream in = entity.getStream(); ObjectInputStream oin = new ObjectInputStream( in ); String identity
-             * = oin.readUTF(); Usecase usecase = (Usecase) oin.readUnshared(); MetaInfo unitofwork = (MetaInfo)
-             * oin.readUnshared(); Iterable<UnitOfWorkEvent> events = (Iterable<UnitOfWorkEvent>) oin.readUnshared();
-             *
-             * // Store state try { entityStore.apply( identity, events, usecase, unitofwork ).commit(); } catch(
-             * ConcurrentEntityStateModificationException e ) { throw new ResourceException(
-             * Status.CLIENT_ERROR_CONFLICT ); }
-             */
-        }
-        catch( Exception e )
-        {
-            throw new ResourceException( e );
-        }
-
-        return new EmptyRepresentation();
-    }
-}
\ No newline at end of file
diff --git a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/EntityResource.java b/libraries/rest/src/main/java/org/qi4j/library/rest/admin/EntityResource.java
deleted file mode 100644
index 328d2c0..0000000
--- a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/EntityResource.java
+++ /dev/null
@@ -1,534 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.rest.admin;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringReader;
-import java.io.Writer;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import org.openrdf.model.Statement;
-import org.openrdf.rio.RDFHandlerException;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.api.value.ValueSerializationException;
-import org.qi4j.functional.Iterables;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.library.rdf.serializer.RdfXmlSerializer;
-import org.qi4j.spi.entity.EntityState;
-import org.qi4j.spi.entity.ManyAssociationState;
-import org.qi4j.spi.entity.NamedAssociationState;
-import org.qi4j.spi.entitystore.ConcurrentEntityStateModificationException;
-import org.qi4j.spi.entitystore.EntityNotFoundException;
-import org.qi4j.spi.entitystore.EntityStore;
-import org.qi4j.spi.entitystore.EntityStoreUnitOfWork;
-import org.qi4j.spi.entitystore.helpers.JSONEntityState;
-import org.qi4j.spi.module.ModuleSpi;
-import org.restlet.data.CharacterSet;
-import org.restlet.data.Form;
-import org.restlet.data.Language;
-import org.restlet.data.MediaType;
-import org.restlet.data.Method;
-import org.restlet.data.Status;
-import org.restlet.data.Tag;
-import org.restlet.representation.EmptyRepresentation;
-import org.restlet.representation.Representation;
-import org.restlet.representation.StringRepresentation;
-import org.restlet.representation.Variant;
-import org.restlet.representation.WriterRepresentation;
-import org.restlet.resource.ResourceException;
-import org.restlet.resource.ServerResource;
-
-public class EntityResource
-    extends ServerResource
-{
-
-    @Service
-    private EntityStore entityStore;
-
-    @Service
-    private ValueSerialization valueSerialization;
-
-    @Structure
-    private ModuleSpi module;
-
-    @Uses
-    private EntityStateSerializer entitySerializer;
-    private String identity;
-
-    public EntityResource()
-    {
-        // Define the supported variant.
-        getVariants().addAll( Arrays.asList(
-            new Variant( MediaType.TEXT_HTML ),
-            new Variant( MediaType.APPLICATION_RDF_XML ),
-            new Variant( MediaType.APPLICATION_JSON ) ) );
-        setNegotiated( true );
-        setAllowedMethods( Collections.singleton( Method.ALL ) );
-    }
-
-    @Override
-    protected void doInit()
-        throws ResourceException
-    {
-        // /entity/{identity}
-        Map<String, Object> attributes = getRequest().getAttributes();
-        identity = (String) attributes.get( "identity" );
-    }
-
-    @Override
-    protected Representation delete( Variant variant )
-        throws ResourceException
-    {
-        Usecase usecase = UsecaseBuilder.newUsecase( "Remove entity" );
-        EntityStoreUnitOfWork uow = entityStore.newUnitOfWork( usecase, module, System.currentTimeMillis() );
-        try
-        {
-            EntityReference identityRef = EntityReference.parseEntityReference( identity );
-            uow.entityStateOf( module, identityRef ).remove();
-            uow.applyChanges().commit();
-            getResponse().setStatus( Status.SUCCESS_NO_CONTENT );
-        }
-        catch( EntityNotFoundException e )
-        {
-            uow.discard();
-            getResponse().setStatus( Status.CLIENT_ERROR_NOT_FOUND );
-        }
-
-        return new EmptyRepresentation();
-    }
-
-    @Override
-    protected Representation get( Variant variant )
-        throws ResourceException
-    {
-        EntityStoreUnitOfWork uow = entityStore.newUnitOfWork( UsecaseBuilder.newUsecase( "Get entity" ),
-                                                               module,
-                                                               System.currentTimeMillis() );
-
-        try
-        {
-            EntityState entityState = getEntityState( uow );
-
-            // Check modification date
-            Date lastModified = getRequest().getConditions().getModifiedSince();
-            if( lastModified != null )
-            {
-                if( lastModified.getTime() / 1000 == entityState.lastModified() / 1000 )
-                {
-                    throw new ResourceException( Status.REDIRECTION_NOT_MODIFIED );
-                }
-            }
-
-            // Generate the right representation according to its media type.
-            if( MediaType.APPLICATION_RDF_XML.equals( variant.getMediaType() ) )
-            {
-                return entityHeaders( representRdfXml( entityState ), entityState );
-            }
-            else if( MediaType.TEXT_HTML.equals( variant.getMediaType() ) )
-            {
-                return entityHeaders( representHtml( entityState ), entityState );
-            }
-            else if( MediaType.APPLICATION_JSON.equals( variant.getMediaType() ) )
-            {
-                return entityHeaders( representJson( entityState ), entityState );
-            }
-        }
-        catch( ResourceException ex )
-        {
-            uow.discard();
-            throw ex;
-        }
-
-        throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
-    }
-
-    private EntityState getEntityState( EntityStoreUnitOfWork unitOfWork )
-        throws ResourceException
-    {
-        EntityState entityState;
-        try
-        {
-            EntityReference entityReference = EntityReference.parseEntityReference( identity );
-            entityState = unitOfWork.entityStateOf( module, entityReference );
-        }
-        catch( EntityNotFoundException e )
-        {
-            throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
-        }
-        return entityState;
-    }
-
-    private Representation entityHeaders( Representation representation, EntityState entityState )
-    {
-        representation.setModificationDate( new Date( entityState.lastModified() ) );
-        representation.setTag( new Tag( "" + entityState.version() ) );
-        representation.setCharacterSet( CharacterSet.UTF_8 );
-        representation.setLanguages( Collections.singletonList( Language.ENGLISH ) );
-
-        return representation;
-    }
-
-    private Representation representHtml( final EntityState entity )
-    {
-        return new WriterRepresentation( MediaType.TEXT_HTML )
-        {
-            @Override
-            public void write( Writer writer )
-                throws IOException
-            {
-                PrintWriter out = new PrintWriter( writer );
-                out.println( "<html><head><title>" + entity.identity() + "</title>"
-                             + "<link rel=\"alternate\" type=\"application/rdf+xml\" "
-                             + "href=\"" + entity.identity() + ".rdf\"/></head><body>" );
-                out.println( "<h1>" + entity.identity() + "</h1>" );
-
-                out.println( "<form method=\"post\" action=\"" + getRequest().getResourceRef().getPath() + "\">\n" );
-                out.println( "<fieldset><legend>Properties</legend>\n<table>" );
-
-                final EntityDescriptor descriptor = entity.entityDescriptor();
-
-                for( PropertyDescriptor persistentProperty : descriptor.state().properties() )
-                {
-                    Object value = entity.propertyValueOf( persistentProperty.qualifiedName() );
-                    out.println( "<tr><td>"
-                                 + "<label for=\"" + persistentProperty.qualifiedName() + "\" >"
-                                 + persistentProperty.qualifiedName().name()
-                                 + "</label></td>\n"
-                                 + "<td><input "
-                                 + "size=\"80\" "
-                                 + "type=\"text\" "
-                                 + ( persistentProperty.isImmutable() ? "readonly=\"true\" " : "" )
-                                 + "name=\"" + persistentProperty.qualifiedName() + "\" "
-                                 + "value=\"" + ( value == null ? "" : valueSerialization.serialize( value ) )
-                                 + "\"/></td></tr>" );
-                }
-                out.println( "</table></fieldset>\n" );
-
-                out.println( "<fieldset><legend>Associations</legend>\n<table>" );
-                for( AssociationDescriptor associationType : descriptor.state().associations() )
-                {
-                    Object value = entity.associationValueOf( associationType.qualifiedName() );
-                    if( value == null )
-                    {
-                        value = "";
-                    }
-                    out.println( "<tr><td>"
-                                 + "<label for=\"" + associationType.qualifiedName() + "\" >"
-                                 + associationType.qualifiedName().name()
-                                 + "</label></td>\n"
-                                 + "<td><input "
-                                 + "type=\"text\" "
-                                 + "size=\"80\" "
-                                 + "name=\"" + associationType.qualifiedName() + "\" "
-                                 + "value=\"" + value + "\"/></td></tr>" );
-                }
-                out.println( "</table></fieldset>\n" );
-
-                out.println( "<fieldset><legend>ManyAssociations</legend>\n<table>" );
-                for( AssociationDescriptor associationType : descriptor.state().manyAssociations() )
-                {
-                    ManyAssociationState identities = entity.manyAssociationValueOf( associationType.qualifiedName() );
-                    String value = "";
-                    for( EntityReference identity : identities )
-                    {
-                        value += identity.identity() + "\n";
-                    }
-
-                    out.println( "<tr><td>"
-                                 + "<label for=\"" + associationType.qualifiedName() + "\" >"
-                                 + associationType.qualifiedName().name()
-                                 + "</label></td>\n"
-                                 + "<td><textarea "
-                                 + "rows=\"10\" "
-                                 + "cols=\"80\" "
-                                 + "name=\"" + associationType.qualifiedName() + "\" >"
-                                 + value
-                                 + "</textarea></td></tr>" );
-                }
-                out.println( "</table></fieldset>\n" );
-
-                out.println( "<fieldset><legend>NamedAssociations</legend>\n<table>" );
-                for( AssociationDescriptor associationType : descriptor.state().namedAssociations() )
-                {
-                    NamedAssociationState identities = entity.namedAssociationValueOf( associationType.qualifiedName() );
-                    String value = "";
-                    for( String name : identities )
-                    {
-                        value += name + "\n" + identities.get( name ).identity() + "\n";
-                    }
-
-                    out.println( "<tr><td>"
-                                 + "<label for=\"" + associationType.qualifiedName() + "\" >"
-                                 + associationType.qualifiedName().name()
-                                 + "</label></td>\n"
-                                 + "<td><textarea "
-                                 + "rows=\"10\" "
-                                 + "cols=\"80\" "
-                                 + "name=\"" + associationType.qualifiedName() + "\" >"
-                                 + value
-                                 + "</textarea></td></tr>" );
-                }
-                out.println( "</table></fieldset>\n" );
-
-                out.println( "<input type=\"submit\" value=\"Update\"/></form>\n" );
-
-                out.println( "</body></html>\n" );
-            }
-        };
-    }
-
-    private Representation representJson( EntityState entityState )
-    {
-        if( entityState instanceof JSONEntityState )
-        {
-            JSONEntityState jsonState = (JSONEntityState) entityState;
-            return new StringRepresentation( jsonState.state().toString(), MediaType.APPLICATION_JSON );
-        }
-        else
-        {
-            throw new ResourceException( Status.CLIENT_ERROR_NOT_ACCEPTABLE );
-        }
-    }
-
-    private Representation representRdfXml( final EntityState entity )
-        throws ResourceException
-    {
-        Representation representation = new WriterRepresentation( MediaType.APPLICATION_RDF_XML )
-        {
-            @Override
-            public void write( Writer writer )
-                throws IOException
-            {
-                try
-                {
-                    Iterable<Statement> statements = entitySerializer.serialize( entity );
-                    new RdfXmlSerializer().serialize( statements, writer );
-                }
-                catch( RDFHandlerException e )
-                {
-                    throw new IOException( e );
-                }
-            }
-        };
-        representation.setCharacterSet( CharacterSet.UTF_8 );
-        return representation;
-    }
-
-    @Override
-    protected Representation put( Representation representation, Variant variant )
-        throws ResourceException
-    {
-        return post( representation, variant );
-    }
-
-    @Override
-    public Representation post( Representation entityRepresentation, Variant variant )
-        throws ResourceException
-    {
-        Usecase usecase = UsecaseBuilder.newUsecase( "Update entity" );
-        EntityStoreUnitOfWork unitOfWork = entityStore.newUnitOfWork( usecase, module, System.currentTimeMillis() );
-        EntityState entity = getEntityState( unitOfWork );
-
-        Form form = new Form( entityRepresentation );
-
-        try
-        {
-            final EntityDescriptor descriptor = entity.entityDescriptor();
-
-            // Parse JSON into properties
-            for( PropertyDescriptor persistentProperty : descriptor.state().properties() )
-            {
-                if( !persistentProperty.isImmutable() )
-                {
-                    String formValue = form.getFirstValue( persistentProperty.qualifiedName().name(), null );
-                    if( formValue == null )
-                    {
-                        entity.setPropertyValue( persistentProperty.qualifiedName(), null );
-                    }
-                    else
-                    {
-                        entity.setPropertyValue(
-                            persistentProperty.qualifiedName(),
-                            valueSerialization.deserialize( persistentProperty.valueType(), formValue ) );
-                    }
-                }
-            }
-
-            for( AssociationDescriptor associationType : descriptor.state().associations() )
-            {
-                String newStringAssociation = form.getFirstValue( associationType.qualifiedName().name() );
-                if( newStringAssociation == null || newStringAssociation.isEmpty() )
-                {
-                    entity.setAssociationValue( associationType.qualifiedName(), null );
-                }
-                else
-                {
-                    entity.setAssociationValue( associationType.qualifiedName(),
-                                                EntityReference.parseEntityReference( newStringAssociation ) );
-                }
-            }
-            for( AssociationDescriptor associationType : descriptor.state().manyAssociations() )
-            {
-                String newStringAssociation = form.getFirstValue( associationType.qualifiedName().name() );
-                ManyAssociationState manyAssociation = entity.manyAssociationValueOf( associationType.qualifiedName() );
-                if( newStringAssociation == null )
-                {
-                    // Remove "left-overs"
-                    for( EntityReference entityReference : manyAssociation )
-                    {
-                        manyAssociation.remove( entityReference );
-                    }
-                    continue;
-                }
-
-                BufferedReader bufferedReader = new BufferedReader( new StringReader( newStringAssociation ) );
-                String identity;
-
-                try
-                {
-                    // Synchronize old and new association
-                    int index = 0;
-                    while( ( identity = bufferedReader.readLine() ) != null )
-                    {
-                        EntityReference reference = new EntityReference( identity );
-
-                        if( manyAssociation.count() < index && manyAssociation.get( index ).equals( reference ) )
-                        {
-                            continue;
-                        }
-
-                        try
-                        {
-                            unitOfWork.entityStateOf( module, reference );
-
-                            manyAssociation.remove( reference );
-                            manyAssociation.add( index++, reference );
-                        }
-                        catch( EntityNotFoundException e )
-                        {
-                            // Ignore this entity - doesn't exist
-                        }
-                    }
-
-                    // Remove "left-overs"
-                    while( manyAssociation.count() > index )
-                    {
-                        manyAssociation.remove( manyAssociation.get( index ) );
-                    }
-                }
-                catch( IOException e )
-                {
-                    // Ignore
-                }
-            }
-            for( AssociationDescriptor associationType : descriptor.state().namedAssociations() )
-            {
-                String newStringAssociation = form.getFirstValue( associationType.qualifiedName().name() );
-                NamedAssociationState namedAssociation = entity.namedAssociationValueOf( associationType.qualifiedName() );
-                if( newStringAssociation == null )
-                {
-                    // Remove "left-overs"
-                    for( String name : namedAssociation )
-                    {
-                        namedAssociation.remove( name );
-                    }
-                    continue;
-                }
-                Set<String> names = new HashSet<>();
-                BufferedReader bufferedReader = new BufferedReader( new StringReader( newStringAssociation ) );
-                String line;
-                try
-                {
-                    while( ( line = bufferedReader.readLine() ) != null )
-                    {
-                        String name = line;
-                        line = bufferedReader.readLine();
-                        if( line == null )
-                        {
-                            break;
-                        }
-                        String identity = line;
-                        EntityReference reference = new EntityReference( identity );
-                        try
-                        {
-                            unitOfWork.entityStateOf( module, reference );
-
-                            namedAssociation.remove( name );
-                            namedAssociation.put( name, reference );
-
-                            names.add( name );
-                        }
-                        catch( EntityNotFoundException e )
-                        {
-                            // Ignore this entity - doesn't exist
-                        }
-                    }
-
-                    // Remove "left-overs"
-                    for( String assocName : Iterables.toList( namedAssociation ) )
-                    {
-                        if( !names.contains( assocName ) )
-                        {
-                            namedAssociation.remove( assocName );
-                        }
-                    }
-                }
-                catch( IOException e )
-                {
-                    // Ignore
-                }
-            }
-        }
-        catch( ValueSerializationException | IllegalArgumentException e )
-        {
-            throw new ResourceException( Status.SERVER_ERROR_INTERNAL, e );
-        }
-
-        try
-        {
-            unitOfWork.applyChanges().commit();
-        }
-        catch( ConcurrentEntityStateModificationException e )
-        {
-            throw new ResourceException( Status.CLIENT_ERROR_CONFLICT );
-        }
-        catch( EntityNotFoundException e )
-        {
-            throw new ResourceException( Status.CLIENT_ERROR_GONE );
-        }
-
-        getResponse().setStatus( Status.SUCCESS_RESET_CONTENT );
-
-        return new EmptyRepresentation();
-    }
-}
diff --git a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/ExceptionRepresentation.java b/libraries/rest/src/main/java/org/qi4j/library/rest/admin/ExceptionRepresentation.java
deleted file mode 100644
index fca36be..0000000
--- a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/ExceptionRepresentation.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.PrintStream;
-import org.restlet.representation.StringRepresentation;
-
-public class ExceptionRepresentation
-    extends StringRepresentation
-{
-    public ExceptionRepresentation( Throwable e )
-    {
-        super( getStackTraceAsHtml( e ) );
-    }
-
-    private static String getStackTraceAsHtml( Throwable e )
-    {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        PrintStream out = new PrintStream( baos );
-        e.printStackTrace( out );
-        out.close();
-        try
-        {
-            baos.close();
-        }
-        catch( IOException e1 )
-        {
-            // Can not happen.
-        }
-        String text = baos.toString();
-        return "<code>" + text + "</code>";
-    }
-}
diff --git a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/ExtensionMediaTypeFilter.java b/libraries/rest/src/main/java/org/qi4j/library/rest/admin/ExtensionMediaTypeFilter.java
deleted file mode 100644
index eee75f6..0000000
--- a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/ExtensionMediaTypeFilter.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import java.util.Collections;
-import java.util.List;
-import org.restlet.Context;
-import org.restlet.Request;
-import org.restlet.Response;
-import org.restlet.Restlet;
-import org.restlet.data.MediaType;
-import org.restlet.data.Metadata;
-import org.restlet.data.Preference;
-import org.restlet.routing.Filter;
-import org.restlet.service.MetadataService;
-
-/**
- * Check the extension used and set the corresponding media type
- * in the request. Then remove the extension from the request resource name.
- */
-public class ExtensionMediaTypeFilter
-    extends Filter
-{
-
-    public ExtensionMediaTypeFilter()
-    {
-    }
-
-    public ExtensionMediaTypeFilter( Context context )
-    {
-        super( context );
-    }
-
-    public ExtensionMediaTypeFilter( Context context, Restlet next )
-    {
-        super( context, next );
-    }
-
-    @Override
-    protected int beforeHandle( Request request, Response response )
-    {
-        List<String> segments = request.getResourceRef().getSegments();
-        if (segments.get( segments.size()-1 ).equals(""))
-          return Filter.CONTINUE;
-
-        String extensions = request.getResourceRef().getExtensions();
-        if( extensions != null )
-        {
-            int idx = extensions.lastIndexOf( "." );
-            if( idx != -1 )
-            {
-                extensions = extensions.substring( idx + 1 );
-            }
-
-            MetadataService metadataService = getApplication().getMetadataService();
-            Metadata metadata = metadataService.getMetadata( extensions );
-            if( metadata != null && metadata instanceof MediaType )
-            {
-                request.getClientInfo()
-                    .setAcceptedMediaTypes( Collections.singletonList( new Preference<MediaType>( (MediaType) metadata ) ) );
-                String path = request.getResourceRef().getPath();
-                path = path.substring( 0, path.length() - extensions.length() - 1 );
-                request.getResourceRef().setPath( path );
-            }
-        }
-
-        return Filter.CONTINUE;
-    }
-}
diff --git a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/IndexResource.java b/libraries/rest/src/main/java/org/qi4j/library/rest/admin/IndexResource.java
deleted file mode 100644
index 59ff3f3..0000000
--- a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/IndexResource.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import java.io.*;
-import java.util.Arrays;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.index.rdf.indexing.RdfExporter;
-import org.restlet.data.MediaType;
-import org.restlet.representation.OutputRepresentation;
-import org.restlet.representation.Representation;
-import org.restlet.representation.Variant;
-import org.restlet.resource.ResourceException;
-import org.restlet.resource.ServerResource;
-
-/**
- * Show RDF index
- */
-public class IndexResource
-    extends ServerResource
-{
-    @Service
-    private RdfExporter exporter;
-
-    public IndexResource()
-    {
-        getVariants().addAll( Arrays.asList(
-            new Variant( MediaType.TEXT_PLAIN ),
-            new Variant( MediaType.APPLICATION_RDF_TRIG ),
-            new Variant( MediaType.APPLICATION_RDF_XML ) ) );
-
-        setNegotiated( true );
-    }
-
-    @Override
-    public Representation get( Variant variant )
-        throws ResourceException
-    {
-        if( variant.getMediaType().equals( MediaType.APPLICATION_RDF_XML ) )
-        {
-            return new RdfXmlOutputRepresentation();
-        }
-        else if( variant.getMediaType().equals( MediaType.APPLICATION_RDF_TRIG ) )
-        {
-            return new RdfTrigOutputRepresentation( MediaType.APPLICATION_RDF_TRIG );
-        }
-        else if( variant.getMediaType().equals( MediaType.TEXT_PLAIN ) )
-        {
-            return new RdfTrigOutputRepresentation( MediaType.TEXT_PLAIN );
-        }
-
-        return null;
-    }
-
-    private class RdfTrigOutputRepresentation
-        extends OutputRepresentation
-    {
-        public RdfTrigOutputRepresentation( MediaType mediaType )
-        {
-            super( mediaType );
-        }
-
-        @Override
-        public void write( OutputStream outputStream )
-            throws IOException
-        {
-            PrintStream ps = null;
-            try
-            {
-                ps = new PrintStream( outputStream );
-                exporter.exportReadableToStream( ps );
-            }
-            finally
-            {
-                if( ps != null )
-                {
-                    ps.close();
-                }
-            }
-        }
-    }
-
-    private class RdfXmlOutputRepresentation
-        extends OutputRepresentation
-    {
-        public RdfXmlOutputRepresentation()
-        {
-            super( MediaType.APPLICATION_RDF_XML );
-        }
-
-        @Override
-        public void write( OutputStream outputStream )
-            throws IOException
-        {
-            PrintWriter pw = null;
-            try
-            {
-                OutputStreamWriter osw = new OutputStreamWriter( outputStream, "UTF-8" );
-                pw = new PrintWriter( osw );
-                exporter.exportFormalToWriter( pw );
-                pw.flush();
-            }
-            finally
-            {
-                if( pw != null )
-                {
-                    pw.close();
-                }
-            }
-        }
-    }
-}
diff --git a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/Qi4jFinder.java b/libraries/rest/src/main/java/org/qi4j/library/rest/admin/Qi4jFinder.java
deleted file mode 100644
index f76cb01..0000000
--- a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/Qi4jFinder.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.object.ObjectFactory;
-import org.restlet.Request;
-import org.restlet.Response;
-import org.restlet.resource.Finder;
-import org.restlet.resource.ServerResource;
-
-public class Qi4jFinder
-    extends Finder
-{
-    @Structure
-    private ObjectFactory factory;
-
-    public Qi4jFinder()
-    {
-    }
-
-    @Override
-    public ServerResource create( Class<? extends ServerResource> targetClass, Request request, Response response )
-    {
-        return factory.newObject( targetClass );
-    }
-}
diff --git a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/Qi4jServerServlet.java b/libraries/rest/src/main/java/org/qi4j/library/rest/admin/Qi4jServerServlet.java
deleted file mode 100644
index 28682fc..0000000
--- a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/Qi4jServerServlet.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.structure.Module;
-import org.restlet.Application;
-import org.restlet.Context;
-import org.restlet.ext.servlet.ServerServlet;
-
-/**
- * Integration with Zest. Register an object extending Application to use.
- */
-public class Qi4jServerServlet
-    extends ServerServlet
-{
-    @Structure
-    Module module;
-
-    @Override
-    @SuppressWarnings( "unchecked" )
-    protected Application createApplication( Context context )
-    {
-        return module.newObject( Application.class, context.createChildContext(), getServletConfig(), getServletContext() );
-    }
-}
diff --git a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/Qi4jServerServletService.java b/libraries/rest/src/main/java/org/qi4j/library/rest/admin/Qi4jServerServletService.java
deleted file mode 100644
index d661130..0000000
--- a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/Qi4jServerServletService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import javax.servlet.Servlet;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-/**
- * JAVADOC
- */
-@Mixins( Qi4jServerServlet.class )
-public interface Qi4jServerServletService
-    extends Servlet, ServiceComposite
-{
-}
diff --git a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/RestApplication.java b/libraries/rest/src/main/java/org/qi4j/library/rest/admin/RestApplication.java
deleted file mode 100644
index 29b7f75..0000000
--- a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/RestApplication.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.rest.admin;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.*;
-import org.restlet.*;
-import org.restlet.data.MediaType;
-import org.restlet.data.Status;
-import org.restlet.resource.Finder;
-import org.restlet.resource.ServerResource;
-import org.restlet.routing.Router;
-
-public class RestApplication
-    extends Application
-{
-    public static final MediaType APPLICATION_SPARQL_JSON = new MediaType( "application/sparql-results+json", "SPARQL JSON" );
-
-    @Structure
-    private Module module;
-
-    public RestApplication( @Uses Context parentContext )
-    {
-        super( parentContext );
-
-        getMetadataService().addExtension( "srj", APPLICATION_SPARQL_JSON );
-
-        getTunnelService().setExtensionsTunnel( true );
-    }
-
-    @Override
-    public void handle( Request request, Response response )
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            super.handle( request, response );
-            uow.complete();
-        }
-        catch( UnitOfWorkException e )
-        {
-            uow.discard();
-            response.setStatus( Status.CLIENT_ERROR_NOT_ACCEPTABLE );
-            response.setEntity( new ExceptionRepresentation( e ) );
-            // More info to send...
-        }
-        catch( ConcurrentEntityModificationException e )
-        {
-            uow.discard();
-            response.setStatus( Status.CLIENT_ERROR_LOCKED );
-            response.setEntity( new ExceptionRepresentation( e ) );
-            // Info to try again...
-        }
-        catch( UnitOfWorkCompletionException e )
-        {
-            uow.discard();
-            response.setStatus( Status.CLIENT_ERROR_NOT_ACCEPTABLE );
-            response.setEntity( new ExceptionRepresentation( e ) );
-        }
-    }
-
-    /**
-     * Creates a root Restlet that will receive all incoming calls.
-     */
-    @Override
-    public synchronized Restlet createInboundRoot()
-    {
-        Router router = new Router( getContext() );
-
-        router.attach( "/entity", createFinder( EntitiesResource.class ) );
-        router.attach( "/entity/{identity}", createFinder( EntityResource.class ) );
-
-        router.attach( "/query", createFinder( SPARQLResource.class ) );
-        router.attach( "/query/sparqlhtml", createFinder( SPARQLResource.class ) );
-        router.attach( "/query/index", createFinder( IndexResource.class ) );
-
-        return router;
-    }
-
-    private Finder createFinder( Class<? extends ServerResource> resource )
-    {
-        Finder finder = module.newObject( Finder.class );
-        finder.setTargetClass( resource );
-        return finder;
-    }
-}
diff --git a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/RestAssembler.java b/libraries/rest/src/main/java/org/qi4j/library/rest/admin/RestAssembler.java
deleted file mode 100644
index f180e81..0000000
--- a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/RestAssembler.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-public class RestAssembler
-    extends Assemblers.Visibility<RestAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.objects( RestApplication.class ).visibleIn( visibility() );
-        module.objects( Qi4jFinder.class,
-                        EntitiesResource.class,
-                        EntityResource.class,
-                        IndexResource.class,
-                        SPARQLResource.class );
-    }
-}
diff --git a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/RestServer.java b/libraries/rest/src/main/java/org/qi4j/library/rest/admin/RestServer.java
deleted file mode 100644
index df8e6e5..0000000
--- a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/RestServer.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.rest.admin;
-
-public interface RestServer
-{
-}
diff --git a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/RestServerComposite.java b/libraries/rest/src/main/java/org/qi4j/library/rest/admin/RestServerComposite.java
deleted file mode 100644
index 03de262..0000000
--- a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/RestServerComposite.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.rest.admin;
-
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-
-@Mixins( { RestServerMixin.class } )
-@Activators( RestServerComposite.Activator.class )
-public interface RestServerComposite
-    extends ServiceComposite, RestServer
-{
-    
-    void startServer()
-            throws Exception;
-    
-    void stopServer()
-            throws Exception;
-    
-    static class Activator extends ActivatorAdapter<ServiceReference<RestServerComposite>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<RestServerComposite> activated )
-                throws Exception
-        {
-            activated.get().startServer();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<RestServerComposite> passivating )
-                throws Exception
-        {
-            passivating.get().stopServer();
-        }
-        
-    }
-}
diff --git a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/RestServerMixin.java b/libraries/rest/src/main/java/org/qi4j/library/rest/admin/RestServerMixin.java
deleted file mode 100644
index ffb92ff..0000000
--- a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/RestServerMixin.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.rest.admin;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.structure.Module;
-import org.restlet.Component;
-import org.restlet.data.Protocol;
-
-public abstract class RestServerMixin
-    implements RestServerComposite
-{
-    @Structure
-    private Module module;
-
-    private Component component;
-
-    @Override
-    public void startServer()
-        throws Exception
-    {
-        component = new Component();
-        component.getServers().add( Protocol.HTTP, 8182 );
-        RestApplication application = module.newObject( RestApplication.class, component.getContext() );
-        component.getDefaultHost().attach( application );
-        component.start();
-    }
-
-    @Override
-    public void stopServer()
-        throws Exception
-    {
-        component.stop();
-    }
-}
diff --git a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/SPARQLResource.java b/libraries/rest/src/main/java/org/qi4j/library/rest/admin/SPARQLResource.java
deleted file mode 100644
index b2145b2..0000000
--- a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/SPARQLResource.java
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import info.aduna.xml.XMLWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import org.openrdf.http.protocol.Protocol;
-import org.openrdf.model.URI;
-import org.openrdf.model.Value;
-import org.openrdf.query.*;
-import org.openrdf.query.impl.DatasetImpl;
-import org.openrdf.query.resultio.TupleQueryResultWriter;
-import org.openrdf.query.resultio.sparqljson.SPARQLResultsJSONWriterFactory;
-import org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLWriter;
-import org.openrdf.repository.Repository;
-import org.openrdf.repository.RepositoryConnection;
-import org.openrdf.repository.RepositoryException;
-import org.qi4j.api.injection.scope.Service;
-import org.restlet.data.Form;
-import org.restlet.data.MediaType;
-import org.restlet.data.Method;
-import org.restlet.data.Status;
-import org.restlet.representation.InputRepresentation;
-import org.restlet.representation.OutputRepresentation;
-import org.restlet.representation.Representation;
-import org.restlet.representation.Variant;
-import org.restlet.resource.ResourceException;
-import org.restlet.resource.ServerResource;
-
-import static org.openrdf.http.protocol.Protocol.*;
-
-/**
- * JAVADOC
- */
-public class SPARQLResource
-    extends ServerResource
-{
-    @Service
-    Repository repository;
-
-    public SPARQLResource()
-    {
-        getVariants().addAll( Arrays.asList(
-            new Variant( MediaType.TEXT_HTML ),
-            new Variant( MediaType.APPLICATION_RDF_XML ),
-            new Variant( RestApplication.APPLICATION_SPARQL_JSON ) ) );
-        setNegotiated( true );
-    }
-
-    @Override
-    protected void doInit()
-        throws ResourceException
-    {
-        super.doInit();
-    }
-
-    @Override
-    public Representation get( final Variant variant )
-        throws ResourceException
-    {
-        try
-        {
-            // TODO There's probably a helper somewhere that can do this more nicely
-            if( getRequest().getOriginalRef().getLastSegment().equals( "sparqlhtml.xsl" ) )
-            {
-                InputStream resourceAsStream = getClass().getResourceAsStream( "sparqlhtml.xsl" );
-                return new InputRepresentation( resourceAsStream, MediaType.TEXT_XML );
-            }
-
-            Form form;
-            if( getRequest().getMethod().equals( Method.POST ) )
-            {
-                form = new Form(getRequest().getEntity());
-            }
-            else
-            {
-                form = getRequest().getResourceRef().getQueryAsForm();
-            }
-
-            final RepositoryConnection conn = repository.getConnection();
-
-            String queryStr = form.getFirstValue( "query" );
-
-            if( queryStr == null )
-            {
-                InputStream resourceAsStream = getClass().getResourceAsStream( "sparqlform.html" );
-                return new InputRepresentation( resourceAsStream, MediaType.TEXT_HTML );
-            }
-
-            Query query = getQuery( repository, conn, queryStr );
-
-            if( query instanceof TupleQuery )
-            {
-                TupleQuery tQuery = (TupleQuery) query;
-
-                final TupleQueryResult queryResult = tQuery.evaluate();
-
-                if( variant.getMediaType().equals( MediaType.TEXT_HTML ) )
-                {
-                    return new OutputRepresentation( MediaType.TEXT_XML )
-                    {
-                        @Override
-                        public void write( OutputStream outputStream )
-                            throws IOException
-                        {
-                            try
-                            {
-                                PrintWriter out = new PrintWriter( outputStream );
-                                out.println( "<?xml version='1.0' encoding='UTF-8'?>" );
-                                out.println( "<?xml-stylesheet type=\"text/xsl\" href=\"query/sparqlhtml.xsl\"?>" );
-                                out.flush();
-                                TupleQueryResultWriter qrWriter = new SPARQLResultsXMLWriter( new XMLWriter( outputStream )
-                                {
-                                    @Override
-                                    public void startDocument()
-                                        throws IOException
-                                    {
-                                        // Ignore
-                                    }
-                                } );
-                                QueryResultUtil.report( queryResult, qrWriter );
-                            }
-                            catch( Exception e )
-                            {
-                                throw new IOException( e );
-                            }
-                            finally
-                            {
-                                try
-                                {
-                                    conn.close();
-                                }
-                                catch( RepositoryException e )
-                                {
-                                    // Ignore
-                                }
-                            }
-                        }
-                    };
-                }
-                else if( variant.getMediaType().equals( MediaType.APPLICATION_RDF_XML ) )
-                {
-                    return new OutputRepresentation( MediaType.APPLICATION_XML )
-                    {
-                        @Override
-                        public void write( OutputStream outputStream )
-                            throws IOException
-                        {
-                            try
-                            {
-                                TupleQueryResultWriter qrWriter = new SPARQLResultsXMLWriter( new XMLWriter( outputStream ) );
-                                QueryResultUtil.report( queryResult, qrWriter );
-                            }
-                            catch( Exception e )
-                            {
-                                throw new IOException( e );
-                            }
-                            finally
-                            {
-                                try
-                                {
-                                    conn.close();
-                                }
-                                catch( RepositoryException e )
-                                {
-                                    // Ignore
-                                }
-                            }
-                        }
-                    };
-                }
-                else if( variant.getMediaType().equals( RestApplication.APPLICATION_SPARQL_JSON ) )
-                {
-                    return new OutputRepresentation( RestApplication.APPLICATION_SPARQL_JSON )
-                    {
-                        @Override
-                        public void write( OutputStream outputStream )
-                            throws IOException
-                        {
-                            try
-                            {
-                                TupleQueryResultWriter qrWriter = new SPARQLResultsJSONWriterFactory().getWriter( outputStream );
-                                QueryResultUtil.report( queryResult, qrWriter );
-                            }
-                            catch( Exception e )
-                            {
-                                throw new IOException( e );
-                            }
-                            finally
-                            {
-                                try
-                                {
-                                    conn.close();
-                                }
-                                catch( RepositoryException e )
-                                {
-                                    // Ignore
-                                }
-                            }
-                        }
-                    };
-                }
-            }
-            else if( query instanceof GraphQuery )
-            {
-                GraphQuery gQuery = (GraphQuery) query;
-
-                /*
-                                queryResult = gQuery.evaluate();
-                                registry = RDFWriterRegistry.getInstance();
-                                view = GraphQueryResultView.getInstance();
-                */
-                conn.close();
-            }
-            else if( query instanceof BooleanQuery )
-            {
-                BooleanQuery bQuery = (BooleanQuery) query;
-
-                /*
-                                queryResult = bQuery.evaluate();
-                                registry = BooleanQueryResultWriterRegistry.getInstance();
-                                view = BooleanQueryResultView.getInstance();
-                */
-                conn.close();
-            }
-            else
-            {
-                conn.close();
-                throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, "Unsupported query type: "
-                                                                              + query.getClass().getName() );
-            }
-        }
-        catch( RepositoryException e )
-        {
-            throw new ResourceException( Status.SERVER_ERROR_INTERNAL, e );
-        }
-        catch( QueryEvaluationException e )
-        {
-            throw new ResourceException( Status.SERVER_ERROR_INTERNAL, e );
-        }
-
-        return null;
-    }
-
-    private Query getQuery( Repository repository, RepositoryConnection repositoryCon, String queryStr
-    )
-        throws ResourceException
-    {
-        Form form = getRequest().getResourceRef().getQueryAsForm();
-
-        Query result;
-
-// default query language is SPARQL
-        QueryLanguage queryLn = QueryLanguage.SPARQL;
-
-// determine if inferred triples should be included in query evaluation
-        boolean includeInferred = true;
-
-// build a dataset, if specified
-        String[] defaultGraphURIs = form.getValuesArray( DEFAULT_GRAPH_PARAM_NAME );
-        String[] namedGraphURIs = form.getValuesArray( NAMED_GRAPH_PARAM_NAME );
-
-        DatasetImpl dataset = null;
-        if( defaultGraphURIs.length > 0 || namedGraphURIs.length > 0 )
-        {
-            dataset = new DatasetImpl();
-
-            if( defaultGraphURIs.length > 0 )
-            {
-                for( String defaultGraphURI : defaultGraphURIs )
-                {
-                    try
-                    {
-                        URI uri = repository.getValueFactory().createURI( defaultGraphURI );
-                        dataset.addDefaultGraph( uri );
-                    }
-                    catch( IllegalArgumentException e )
-                    {
-                        throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, "Illegal URI for default graph: "
-                                                                                      + defaultGraphURI );
-                    }
-                }
-            }
-
-            if( namedGraphURIs.length > 0 )
-            {
-                for( String namedGraphURI : namedGraphURIs )
-                {
-                    try
-                    {
-                        URI uri = repository.getValueFactory().createURI( namedGraphURI );
-                        dataset.addNamedGraph( uri );
-                    }
-                    catch( IllegalArgumentException e )
-                    {
-                        throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, "Illegal URI for named graph: "
-                                                                                      + namedGraphURI );
-                    }
-                }
-            }
-        }
-
-        try
-        {
-            result = repositoryCon.prepareQuery( queryLn, queryStr );
-            result.setIncludeInferred( includeInferred );
-
-            if( dataset != null )
-            {
-                result.setDataset( dataset );
-            }
-
-// determine if any variable bindings have been set on this query.
-            @SuppressWarnings( "unchecked" )
-            Enumeration<String> parameterNames = Collections.enumeration( form.getValuesMap().keySet() );
-
-            while( parameterNames.hasMoreElements() )
-            {
-                String parameterName = parameterNames.nextElement();
-
-                if( parameterName.startsWith( BINDING_PREFIX ) && parameterName.length() > BINDING_PREFIX.length() )
-                {
-                    String bindingName = parameterName.substring( BINDING_PREFIX.length() );
-                    Value bindingValue = parseValueParam( repository, form, parameterName );
-                    result.setBinding( bindingName, bindingValue );
-                }
-            }
-        }
-        catch( UnsupportedQueryLanguageException e )
-        {
-            throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, e.getMessage() );
-        }
-        catch( MalformedQueryException e )
-        {
-            throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, e.getMessage() );
-        }
-        catch( RepositoryException e )
-        {
-            throw new ResourceException( Status.SERVER_ERROR_INTERNAL, e.getMessage() );
-        }
-
-        return result;
-    }
-
-    private Value parseValueParam( Repository repository, Form form, String parameterName )
-        throws ResourceException
-    {
-        String paramValue = form.getFirstValue( parameterName );
-        try
-        {
-            return Protocol.decodeValue( paramValue, repository.getValueFactory() );
-        }
-        catch( IllegalArgumentException e )
-        {
-            throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, "Invalid value for parameter '" + parameterName + "': "
-                                                                          + paramValue );
-        }
-    }
-}
diff --git a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/package.html b/libraries/rest/src/main/java/org/qi4j/library/rest/admin/package.html
deleted file mode 100644
index 4727fba..0000000
--- a/libraries/rest/src/main/java/org/qi4j/library/rest/admin/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>ReST EntityStore, Index & Query Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest/src/main/resources/org/apache/polygene/library/rest/admin/sparqlform.html b/libraries/rest/src/main/resources/org/apache/polygene/library/rest/admin/sparqlform.html
new file mode 100644
index 0000000..53cf259
--- /dev/null
+++ b/libraries/rest/src/main/resources/org/apache/polygene/library/rest/admin/sparqlform.html
@@ -0,0 +1,99 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
+<html>
+<!--
+  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.
+-->
+<head>
+    <title>
+        SPARQL Query
+    </title>
+</head>
+<body>
+<form method="GET" action="">
+    <label>Query:</label><br/>
+    <textarea rows="20" cols="80" name="query">PREFIX ns0: &lt;urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#&gt;
+        PREFIX rdf: &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#&gt;
+        PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
+        SELECT DISTINCT ?entityType ?identity
+        WHERE {
+        ?entityType rdfs:subClassOf &lt;urn:polygene:type:org.apache.polygene.api.entity.Entity&gt;.
+        ?entity rdf:type ?entityType.
+        ?entity ns0:identity ?identity.
+        }
+    </textarea> <br/>
+    <input type="submit" value="Query"/>
+</form>
+
+<h2>Examples</h2>
+
+<h3>Get all entities</h3>
+<pre>
+PREFIX ns0: &lt;urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#&gt;
+        PREFIX rdf: &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#&gt;
+        PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
+        SELECT DISTINCT ?entityType ?identity
+        WHERE {
+        ?entityType rdfs:subClassOf &lt;urn:polygene:type:org.apache.polygene.api.entity.Entity&gt;.
+        ?entity rdf:type ?entityType.
+        ?entity ns0:identity ?identity.
+        }
+
+</pre>
+<h3>Get entities of a given type</h3>
+<pre>
+PREFIX ns0: &lt;urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#&gt;
+        PREFIX rdf: &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#&gt;
+        PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
+        SELECT DISTINCT ?identity
+        WHERE {
+        ?entity rdf:type &lt;urn:polygene:type:org.apache.polygene.rest.TestEntity&gt;.
+        ?entity ns0:identity ?identity.
+        }
+</pre>
+
+<h3>Get entities with a given property value</h3>
+<pre>
+PREFIX ns0: &lt;urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#&gt;
+        PREFIX rdf: &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#&gt;
+        PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
+        SELECT DISTINCT ?identity
+        WHERE {
+        ?entity rdf:type &lt;urn:polygene:type:org.apache.polygene.rest.TestEntity&gt;.
+        ?entity ns0:identity ?identity.
+        ?entity &lt;urn:polygene:type:org.apache.polygene.rest.Named#name&gt; "Foo bar"
+        }
+</pre>
+</body>
+</html>
\ No newline at end of file
diff --git a/libraries/rest/src/main/resources/org/apache/polygene/library/rest/admin/sparqlhtml.xsl b/libraries/rest/src/main/resources/org/apache/polygene/library/rest/admin/sparqlhtml.xsl
new file mode 100644
index 0000000..784f1cd
--- /dev/null
+++ b/libraries/rest/src/main/resources/org/apache/polygene/library/rest/admin/sparqlhtml.xsl
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:res="http://www.w3.org/2005/sparql-results#"
+                exclude-result-prefixes="res xsl">
+
+  <!--
+  <xsl:output
+    method="html"
+    media-type="text/html"
+    doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
+    indent="yes"
+    encoding="UTF-8"/>
+  -->
+
+  <xsl:output
+    method="xml"
+    indent="yes"
+    encoding="UTF-8"
+    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+    omit-xml-declaration="no"/>
+
+  <xsl:template name="header">
+
+    <div>
+      <h2>Header</h2>
+      <xsl:for-each select="res:head/res:link">
+        <p>Link to
+          <xsl:value-of select="@href"/>
+        </p>
+      </xsl:for-each>
+    </div>
+  </xsl:template>
+
+  <xsl:template name="boolean-result">
+
+    <div>
+      <h2>Boolean Result</h2>
+      <p>Value
+        <xsl:value-of select="res:boolean"/>
+      </p>
+    </div>
+  </xsl:template>
+
+
+  <xsl:template name="vb-result">
+    <table border="1">
+      <xsl:text>
+      </xsl:text>
+      <tr>
+        <xsl:for-each select="res:head/res:variable">
+          <th>
+            <xsl:value-of select="@name"/>
+          </th>
+        </xsl:for-each>
+
+      </tr>
+      <xsl:text>
+      </xsl:text>
+      <xsl:for-each select="res:results/res:result">
+        <tr>
+            <xsl:apply-templates select="."/>
+        </tr>
+      </xsl:for-each>
+    </table>
+
+  </xsl:template>
+
+  <xsl:template match="res:result">
+    <xsl:variable name="current" select="."/>
+    <xsl:for-each select="//res:head/res:variable">
+      <xsl:variable name="name" select="@name"/>
+      <td>
+        <xsl:choose>
+
+          <xsl:when test="$current/res:binding[@name=$name]">
+            <!-- apply template for the correct value type (bnode, uri,
+           literal) -->
+
+              <xsl:choose>
+                  <xsl:when test="$name = 'identity'">
+                    <a href="entity/{$current/res:binding[@name=$name]}"><xsl:apply-templates select="$current/res:binding[@name=$name]"/></a>
+                  </xsl:when>
+                  <xsl:otherwise>
+                      <xsl:apply-templates select="$current/res:binding[@name=$name]"/>
+                  </xsl:otherwise>
+              </xsl:choose>
+          </xsl:when>
+          <xsl:otherwise>
+            <!-- no binding available for this variable in this solution -->
+            [unbound]
+          </xsl:otherwise>
+        </xsl:choose>
+
+      </td>
+    </xsl:for-each>
+  </xsl:template>
+
+  <xsl:template match="res:bnode">
+    <xsl:text>nodeID</xsl:text>
+    <xsl:value-of select="text()"/>
+  </xsl:template>
+
+  <xsl:template match="res:uri">
+    <xsl:variable name="uri" select="text()"/>
+    <xsl:text>URI </xsl:text>
+    <xsl:value-of select="$uri"/>
+  </xsl:template>
+
+  <xsl:template match="res:literal">
+    <xsl:choose>
+      <xsl:when test="@datatype">
+
+        <!-- datatyped literal value -->
+        <xsl:value-of select="text()"/>
+        (datatype
+        <xsl:value-of select="@datatype"/>
+        )
+      </xsl:when>
+      <xsl:when test="@xml:lang">
+        <!-- lang-string -->
+        <xsl:value-of select="text()"/>
+        @
+        <xsl:value-of select="@xml:lang"/>
+      </xsl:when>
+
+      <xsl:when test="string-length(text()) != 0">
+        <!-- present and not empty -->
+        <xsl:value-of select="text()"/>
+      </xsl:when>
+      <xsl:when test="string-length(text()) = 0">
+        <!-- present and empty -->
+        [empty literal]
+      </xsl:when>
+    </xsl:choose>
+
+  </xsl:template>
+
+  <xsl:template match="res:sparql">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
+      <head>
+        <title>SPARQL Query Results</title>
+      </head>
+      <body>
+
+        <xsl:if test="res:head/res:link">
+          <xsl:call-template name="header"/>
+        </xsl:if>
+
+        <xsl:choose>
+          <xsl:when test="res:boolean">
+            <xsl:call-template name="boolean-result"/>
+
+          </xsl:when>
+
+          <xsl:when test="res:results">
+            <xsl:call-template name="vb-result"/>
+          </xsl:when>
+
+        </xsl:choose>
+
+
+      </body>
+    </html>
+
+  </xsl:template>
+</xsl:stylesheet>
diff --git a/libraries/rest/src/main/resources/org/qi4j/library/rest/admin/sparqlform.html b/libraries/rest/src/main/resources/org/qi4j/library/rest/admin/sparqlform.html
deleted file mode 100644
index 83335f6..0000000
--- a/libraries/rest/src/main/resources/org/qi4j/library/rest/admin/sparqlform.html
+++ /dev/null
@@ -1,79 +0,0 @@
-<html>
-<!--
-  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.
--->
-<head>
-    <title>
-        SPARQL Query
-    </title>
-</head>
-<body>
-<form method="GET" action="">
-    <label>Query:</label><br/>
-    <textarea rows="20" cols="80" name="query">PREFIX ns0: &lt;urn:qi4j:type:org.qi4j.api.entity.Identity#&gt;
-        PREFIX rdf: &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#&gt;
-        PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
-        SELECT DISTINCT ?entityType ?identity
-        WHERE {
-        ?entityType rdfs:subClassOf &lt;urn:qi4j:type:org.qi4j.api.entity.Entity&gt;.
-        ?entity rdf:type ?entityType.
-        ?entity ns0:identity ?identity.
-        }
-    </textarea> <br/>
-    <input type="submit" value="Query"/>
-</form>
-
-<h2>Examples</h2>
-
-<h3>Get all entities</h3>
-<pre>
-PREFIX ns0: &lt;urn:qi4j:type:org.qi4j.api.entity.Identity#&gt;
-        PREFIX rdf: &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#&gt;
-        PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
-        SELECT DISTINCT ?entityType ?identity
-        WHERE {
-        ?entityType rdfs:subClassOf &lt;urn:qi4j:type:org.qi4j.api.entity.Entity&gt;.
-        ?entity rdf:type ?entityType.
-        ?entity ns0:identity ?identity.
-        }
-
-</pre>
-<h3>Get entities of a given type</h3>
-<pre>
-PREFIX ns0: &lt;urn:qi4j:type:org.qi4j.api.entity.Identity#&gt;
-        PREFIX rdf: &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#&gt;
-        PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
-        SELECT DISTINCT ?identity
-        WHERE {
-        ?entity rdf:type &lt;urn:qi4j:type:org.qi4j.rest.TestEntity&gt;.
-        ?entity ns0:identity ?identity.
-        }
-</pre>
-
-<h3>Get entities with a given property value</h3>
-<pre>
-PREFIX ns0: &lt;urn:qi4j:type:org.qi4j.api.entity.Identity#&gt;
-        PREFIX rdf: &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#&gt;
-        PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
-        SELECT DISTINCT ?identity
-        WHERE {
-        ?entity rdf:type &lt;urn:qi4j:type:org.qi4j.rest.TestEntity&gt;.
-        ?entity ns0:identity ?identity.
-        ?entity &lt;urn:qi4j:type:org.qi4j.rest.Named#name&gt; "Foo bar"
-        }
-</pre>
-</body>
-</html>
\ No newline at end of file
diff --git a/libraries/rest/src/main/resources/org/qi4j/library/rest/admin/sparqlhtml.xsl b/libraries/rest/src/main/resources/org/qi4j/library/rest/admin/sparqlhtml.xsl
deleted file mode 100644
index 0da6f97..0000000
--- a/libraries/rest/src/main/resources/org/qi4j/library/rest/admin/sparqlhtml.xsl
+++ /dev/null
@@ -1,188 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-
-<!--
-
-XSLT script to format SPARQL Query Results XML Format into xhtml
-
-Copyright © 2004, 2005 World Wide Web Consortium, (Massachusetts
-Institute of Technology, European Research Consortium for
-Informatics and Mathematics, Keio University). All Rights
-Reserved. This work is distributed under the W3C® Software
-License [1] in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.
-
-[1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
-
-$Id: result-to-html.xsl,v 1.1 2008/01/15 02:25:58 eric Exp $
-
--->
-
-<xsl:stylesheet version="1.0"
-                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-                xmlns="http://www.w3.org/1999/xhtml"
-                xmlns:res="http://www.w3.org/2005/sparql-results#"
-                exclude-result-prefixes="res xsl">
-
-  <!--
-  <xsl:output
-    method="html"
-    media-type="text/html"
-    doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
-    indent="yes"
-    encoding="UTF-8"/>
-  -->
-
-  <xsl:output
-    method="xml"
-    indent="yes"
-    encoding="UTF-8"
-    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
-    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
-    omit-xml-declaration="no"/>
-
-  <xsl:template name="header">
-
-    <div>
-      <h2>Header</h2>
-      <xsl:for-each select="res:head/res:link">
-        <p>Link to
-          <xsl:value-of select="@href"/>
-        </p>
-      </xsl:for-each>
-    </div>
-  </xsl:template>
-
-  <xsl:template name="boolean-result">
-
-    <div>
-      <h2>Boolean Result</h2>
-      <p>Value
-        <xsl:value-of select="res:boolean"/>
-      </p>
-    </div>
-  </xsl:template>
-
-
-  <xsl:template name="vb-result">
-    <table border="1">
-      <xsl:text>
-      </xsl:text>
-      <tr>
-        <xsl:for-each select="res:head/res:variable">
-          <th>
-            <xsl:value-of select="@name"/>
-          </th>
-        </xsl:for-each>
-
-      </tr>
-      <xsl:text>
-      </xsl:text>
-      <xsl:for-each select="res:results/res:result">
-        <tr>
-            <xsl:apply-templates select="."/>
-        </tr>
-      </xsl:for-each>
-    </table>
-
-  </xsl:template>
-
-  <xsl:template match="res:result">
-    <xsl:variable name="current" select="."/>
-    <xsl:for-each select="//res:head/res:variable">
-      <xsl:variable name="name" select="@name"/>
-      <td>
-        <xsl:choose>
-
-          <xsl:when test="$current/res:binding[@name=$name]">
-            <!-- apply template for the correct value type (bnode, uri,
-           literal) -->
-
-              <xsl:choose>
-                  <xsl:when test="$name = 'identity'">
-                    <a href="entity/{$current/res:binding[@name=$name]}"><xsl:apply-templates select="$current/res:binding[@name=$name]"/></a>
-                  </xsl:when>
-                  <xsl:otherwise>
-                      <xsl:apply-templates select="$current/res:binding[@name=$name]"/>
-                  </xsl:otherwise>
-              </xsl:choose>
-          </xsl:when>
-          <xsl:otherwise>
-            <!-- no binding available for this variable in this solution -->
-            [unbound]
-          </xsl:otherwise>
-        </xsl:choose>
-
-      </td>
-    </xsl:for-each>
-  </xsl:template>
-
-  <xsl:template match="res:bnode">
-    <xsl:text>nodeID</xsl:text>
-    <xsl:value-of select="text()"/>
-  </xsl:template>
-
-  <xsl:template match="res:uri">
-    <xsl:variable name="uri" select="text()"/>
-    <xsl:text>URI </xsl:text>
-    <xsl:value-of select="$uri"/>
-  </xsl:template>
-
-  <xsl:template match="res:literal">
-    <xsl:choose>
-      <xsl:when test="@datatype">
-
-        <!-- datatyped literal value -->
-        <xsl:value-of select="text()"/>
-        (datatype
-        <xsl:value-of select="@datatype"/>
-        )
-      </xsl:when>
-      <xsl:when test="@xml:lang">
-        <!-- lang-string -->
-        <xsl:value-of select="text()"/>
-        @
-        <xsl:value-of select="@xml:lang"/>
-      </xsl:when>
-
-      <xsl:when test="string-length(text()) != 0">
-        <!-- present and not empty -->
-        <xsl:value-of select="text()"/>
-      </xsl:when>
-      <xsl:when test="string-length(text()) = 0">
-        <!-- present and empty -->
-        [empty literal]
-      </xsl:when>
-    </xsl:choose>
-
-  </xsl:template>
-
-  <xsl:template match="res:sparql">
-    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
-      <head>
-        <title>SPARQL Query Results</title>
-      </head>
-      <body>
-
-        <xsl:if test="res:head/res:link">
-          <xsl:call-template name="header"/>
-        </xsl:if>
-
-        <xsl:choose>
-          <xsl:when test="res:boolean">
-            <xsl:call-template name="boolean-result"/>
-
-          </xsl:when>
-
-          <xsl:when test="res:results">
-            <xsl:call-template name="vb-result"/>
-          </xsl:when>
-
-        </xsl:choose>
-
-
-      </body>
-    </html>
-
-  </xsl:template>
-</xsl:stylesheet>
diff --git a/libraries/rest/src/main/resources/velocity.properties b/libraries/rest/src/main/resources/velocity.properties
index 7c522fd..4cf4997 100644
--- a/libraries/rest/src/main/resources/velocity.properties
+++ b/libraries/rest/src/main/resources/velocity.properties
@@ -1,17 +1,22 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 # ----------------------------------------------------------------------------
 # R U N T I M E  L O G
diff --git a/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/DomainAssembler.java b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/DomainAssembler.java
new file mode 100644
index 0000000..33090b2
--- /dev/null
+++ b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/DomainAssembler.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.polygene.library.rest.admin;
+
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+import org.apache.polygene.index.rdf.RdfIndexingEngineService;
+import org.apache.polygene.library.rdf.repository.MemoryRepositoryService;
+
+import static org.apache.polygene.api.common.Visibility.application;
+import static org.apache.polygene.api.common.Visibility.layer;
+
+/**
+ * JAVADOC
+ */
+public class DomainAssembler
+    implements Assembler
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services(
+            MemoryEntityStoreService.class,
+            RdfIndexingEngineService.class
+        ).visibleIn( application );
+        module.services( MemoryRepositoryService.class ).identifiedBy( "rdf-indexing" ).visibleIn( layer );
+
+        module.entities( TestEntity.class, TestRole.class, TestEntity2.class ).visibleIn( application );
+        module.values( TestValue.class ).visibleIn( application );
+        module.services( DummyDataService.class ).instantiateOnStartup();
+    }
+}
diff --git a/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/DummyDataService.java b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/DummyDataService.java
new file mode 100644
index 0000000..346ebd6
--- /dev/null
+++ b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/DummyDataService.java
@@ -0,0 +1,115 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import java.util.HashMap;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+@Mixins( DummyDataService.DummyDataMixin.class )
+@Activators( DummyDataService.Activator.class )
+public interface DummyDataService
+    extends ServiceComposite
+{
+    
+    void insertInitialData()
+            throws Exception;
+
+    static class Activator
+            extends ActivatorAdapter<ServiceReference<DummyDataService>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<DummyDataService> activated )
+                throws Exception
+        {
+            activated.get().insertInitialData();
+        }
+
+    }
+    
+    abstract class DummyDataMixin
+        implements DummyDataService
+    {
+        @Structure
+        UnitOfWorkFactory uowf;
+
+        @Structure
+        ValueBuilderFactory vbf;
+
+        public void insertInitialData()
+            throws Exception
+        {
+            UnitOfWork unitOfWork = uowf.newUnitOfWork();
+            try
+            {
+                {
+                    ValueBuilder<TestValue> valueBuilder = vbf.newValueBuilder( TestValue.class );
+                    valueBuilder.prototype().longList().get().add( 42L );
+                    valueBuilder.prototype().string().set( "Foo bar value" );
+                    valueBuilder.prototype().map().set( new HashMap() );
+
+                    EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class, new StringIdentity( "test1" ) );
+                    builder.instance().name().set( "Foo bar" );
+                    builder.instance().age().set( 42 );
+                    builder.instance().value().set( valueBuilder.newInstance() );
+                    TestEntity testEntity = builder.newInstance();
+
+                    EntityBuilder<TestEntity> builder2 = unitOfWork.newEntityBuilder( TestEntity.class, new StringIdentity( "test2" ) );
+                    builder2.instance().name().set( "Xyzzy" );
+                    builder2.instance().age().set( 12 );
+                    builder2.instance().association().set( testEntity );
+                    builder2.instance().manyAssociation().add( 0, testEntity );
+                    builder2.instance().manyAssociation().add( 0, testEntity );
+
+                    EntityBuilder<TestRole> builder3 = unitOfWork.newEntityBuilder( TestRole.class );
+                    builder3.instance().name().set( "A role" );
+                    TestRole testRole = builder3.newInstance();
+
+                    builder2.newInstance();
+                }
+
+                {
+                    EntityBuilder<TestEntity2> builder = unitOfWork.newEntityBuilder( TestEntity2.class, new StringIdentity( "test3" ) );
+                    builder.instance().name().set( "Test3" );
+                    builder.newInstance();
+                }
+
+                unitOfWork.complete();
+            }
+            finally
+            {
+                unitOfWork.discard();
+            }
+        }
+
+    }
+}
diff --git a/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/Main.java b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/Main.java
new file mode 100644
index 0000000..1e1f429
--- /dev/null
+++ b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/Main.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.polygene.library.rest.admin;
+
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.Energy4Java;
+
+/**
+ * JAVADOC
+ */
+public class Main
+{
+    private Application application;
+
+    public static void main( String[] args )
+        throws Exception
+    {
+        new Main();
+    }
+
+    public Main()
+        throws Exception
+    {
+        Energy4Java polygene = new Energy4Java();
+        application = polygene.newApplication( new MainAssembler() );
+        application.activate();
+    }
+
+    public Application application()
+    {
+        return application;
+    }
+}
+
diff --git a/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/MainAssembler.java b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/MainAssembler.java
new file mode 100644
index 0000000..510ec34
--- /dev/null
+++ b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/MainAssembler.java
@@ -0,0 +1,76 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import org.apache.polygene.bootstrap.*;
+import org.apache.polygene.library.http.JettyServiceAssembler;
+
+/**
+ * JAVADOC
+ */
+public class MainAssembler
+    implements ApplicationAssembler
+{
+    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+        throws AssemblyException
+    {
+        return applicationFactory.newApplicationAssembly( new Assembler[][][]
+            {
+                // UI
+                {
+                    {
+                        new ModuleName( "Configuration store" ),
+                        new MemoryEntityStoreServiceAssembler(),
+                    },
+                    {
+                        new ModuleName( "Restlet servlet" ),
+                        new RestletServletAssembler(),
+                    },
+                    {
+                        new ModuleName( "Jetty" ),
+                        new JettyServiceAssembler()
+                    }
+                },
+                // Domain
+                {
+                    {
+                        new ModuleName( "Restlet application" ),
+                        new RestAssembler(),
+                    },
+                    {
+                        new ModuleName( "RDF" ),
+                        new RDFAssembler(),
+                    },
+                    {
+                        new ModuleName( "Domain" ),
+                        new DomainAssembler(),
+                    }
+                },
+                // Infrastructure
+                {
+                    {
+                        new ModuleName( "Domain store" ),
+                        new MemoryEntityStoreServiceAssembler()
+                    }
+                }
+            } );
+    }
+}
diff --git a/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/MemoryEntityStoreServiceAssembler.java b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/MemoryEntityStoreServiceAssembler.java
new file mode 100644
index 0000000..88f8759
--- /dev/null
+++ b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/MemoryEntityStoreServiceAssembler.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+
+/**
+ * JAVADOC
+ */
+class MemoryEntityStoreServiceAssembler
+    implements Assembler
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( MemoryEntityStoreService.class ).visibleIn( Visibility.application );
+    }
+}
diff --git a/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/Named.java b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/Named.java
new file mode 100644
index 0000000..454562a
--- /dev/null
+++ b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/Named.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * JAVADOC
+ */
+public interface Named
+{
+    @UseDefaults
+    Property<String> name();
+}
diff --git a/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/RDFAssembler.java b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/RDFAssembler.java
new file mode 100644
index 0000000..654f0d1
--- /dev/null
+++ b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/RDFAssembler.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.rdf.entity.EntityStateSerializer;
+import org.apache.polygene.library.rdf.entity.EntityTypeSerializer;
+
+/**
+ * JAVADOC
+ */
+class RDFAssembler
+    implements Assembler
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.objects( EntityStateSerializer.class ).visibleIn( Visibility.application );
+        module.objects( EntityTypeSerializer.class ).visibleIn( Visibility.application );
+    }
+}
diff --git a/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/RestTest.java b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/RestTest.java
new file mode 100644
index 0000000..f09e785
--- /dev/null
+++ b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/RestTest.java
@@ -0,0 +1,308 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.ApplicationAssemblerAdapter;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.apache.polygene.index.rdf.assembly.RdfMemoryStoreAssembler;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.util.FreePortFinder;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.anyOf;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+
+public class RestTest extends AbstractPolygeneTest
+{
+    private static final int ADMIN_PORT = FreePortFinder.findFreePortOnLoopback();
+
+    @Override
+    protected ApplicationDescriptor newApplicationModel()
+        throws AssemblyException
+    {
+        return polygene.newApplicationModel( new ApplicationAssemblerAdapter(
+            new Assembler[][][]
+                {
+                    {
+                        {
+                            RestTest.this,
+                            new RestAssembler(),
+                            new RdfMemoryStoreAssembler(),
+                            new DefaultUnitOfWorkAssembler()
+                        }
+                    }
+                } )
+        {}  // subclassing ApplicationAssemblerAdapter
+        );
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ModuleAssembly config = module.layer().module( "config" );
+        new EntityTestAssembler().assemble( config );
+        config.configurations( RestServerConfiguration.class ).visibleIn( Visibility.layer );
+        config.forMixin( RestServerConfiguration.class ).declareDefaults().port().set( ADMIN_PORT );
+
+        module.objects( RestTest.class, RestTester.class );
+        module.entities( PersonEntity.class );
+        module.services( RestServerComposite.class ).instantiateOnStartup();
+        new EntityTestAssembler().assemble( module );
+    }
+
+    @Override
+    @Before
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            EntityBuilder<PersonEntity> builder1 = uow.newEntityBuilder( PersonEntity.class, new StringIdentity( "P2" ) );
+            PersonEntity maryDoe = builder1.instance();
+            maryDoe.firstname().set( "Mary" );
+            maryDoe.lastname().set( "Doe" );
+            maryDoe = builder1.newInstance();
+
+            EntityBuilder<PersonEntity> builder2 = uow.newEntityBuilder( PersonEntity.class, new StringIdentity( "P1" ) );
+            PersonEntity joeDoe = builder2.instance();
+            joeDoe.firstname().set( "Joe" );
+            joeDoe.lastname().set( "Doe" );
+            joeDoe.mother().set( maryDoe );
+            builder2.newInstance();
+
+            uow.complete();
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void givenAnIdentityWhenExecutingGetCommandThenExpectTheCorrectRdf()
+        throws Exception
+    {
+        RestTester restTester = objectFactory.newObject( RestTester.class );
+        String rdf = restTester.getEntity( "P1" );
+        // System.out.println( rdf.replaceAll( "\n", "\\\\n" ).replaceAll( "\"", "\\\\\"" ) );
+        assertThat( "Incorrect RDF produced", rdf, anyOf(
+            // Open JDK 8 & Valid
+            equalTo( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rdf:RDF\n\txmlns:polygene=\"http://polygene.apache.org/rdf/model/1.0/\"\n\txmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n\txmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">\n<org.apache.polygene.library.rest.admin.RestTest-PersonEntity xmlns=\"urn:polygene:type:\" rdf:about=\"urn:polygene:entity:P1\">\n\t<lastname xmlns=\"urn:polygene:type:org.apache.polygene.library.rest.admin.RestTest-Person#\">Doe</lastname>\n\t<firstname xmlns=\"urn:polygene:type:org.apache.polygene.library.rest.admin.RestTest-Person#\">Joe</firstname>\n\t<identity xmlns=\"urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#\">P1</identity>\n\t<mother xmlns=\"urn:polygene:type:org.apache.polygene.library.rest.admin.RestTest-Person#\" rdf:resource=\"urn:polygene:entity:P2\"/>\n</org.apache.polygene.library.rest.admin.RestTest-PersonEntity>\n\n</rdf:RDF>" ),
+            equalTo( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rdf:RDF\n\txmlns:polygene=\"http://polygene.apache.org/rdf/model/1.0/\"\n\txmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n\txmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">\n<org.apache.polygene.library.rest.admin.RestTest-PersonEntity xmlns=\"urn:polygene:type:\" rdf:about=\"urn:polygene:entity:P1\">\n\t<identity xmlns=\"urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#\">P1</identity>\n\t<firstname xmlns=\"urn:polygene:type:org.apache.polygene.library.rest.admin.RestTest-Person#\">Joe</firstname>\n\t<lastname xmlns=\"urn:polygene:type:org.apache.polygene.library.rest.admin.RestTest-Person#\">Doe</lastname>\n\t<mother xmlns=\"urn:polygene:type:org.apache.polygene.library.rest.admin.RestTest-Person#\" rdf:resource=\"urn:polygene:entity:P2\"/>\n</org.apache.polygene.library.rest.admin.RestTest-PersonEntity>\n\n</rdf:RDF>" ),
+            // Sun JDK 6 / Oracle JDK 7 & Valid
+            equalTo( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rdf:RDF\n\txmlns:polygene=\"http://polygene.apache.org/rdf/model/1.0/\"\n\txmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n\txmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">\n<org.apache.polygene.library.rest.admin.RestTest-PersonEntity xmlns=\"urn:polygene:type:\" rdf:about=\"urn:polygene:entity:P1\">\n\t<firstname xmlns=\"urn:polygene:type:org.apache.polygene.library.rest.admin.RestTest-Person#\">Joe</firstname>\n\t<lastname xmlns=\"urn:polygene:type:org.apache.polygene.library.rest.admin.RestTest-Person#\">Doe</lastname>\n\t<identity xmlns=\"urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#\">P1</identity>\n\t<mother xmlns=\"urn:polygene:type:org.apache.polygene.library.rest.admin.RestTest-Person#\" rdf:resource=\"urn:polygene:entity:P2\"/>\n</org.apache.polygene.library.rest.admin.RestTest-PersonEntity>\n\n</rdf:RDF>" ),
+            // IBM JDK 6 & Valid
+            equalTo( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rdf:RDF\n\txmlns:polygene=\"http://polygene.apache.org/rdf/model/1.0/\"\n\txmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n\txmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">\n<org.apache.polygene.library.rest.admin.RestTest-PersonEntity xmlns=\"urn:polygene:type:\" rdf:about=\"urn:polygene:entity:P1\">\n\t<identity xmlns=\"urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#\">P1</identity>\n\t<lastname xmlns=\"urn:polygene:type:org.apache.polygene.library.rest.admin.RestTest-Person#\">Doe</lastname>\n\t<firstname xmlns=\"urn:polygene:type:org.apache.polygene.library.rest.admin.RestTest-Person#\">Joe</firstname>\n\t<mother xmlns=\"urn:polygene:type:org.apache.polygene.library.rest.admin.RestTest-Person#\" rdf:resource=\"urn:polygene:entity:P2\"/>\n</org.apache.polygene.library.rest.admin.RestTest-PersonEntity>\n\n</rdf:RDF>" ) ) );
+    }
+
+    @Test
+    public void givenExistingIdentityWhenExecutingPutCommandThenNewValuesInEntity()
+        throws Throwable
+    {
+        RestTester restTester = objectFactory.newObject( RestTester.class );
+        Map<String, String> properties = new HashMap<String, String>();
+        properties.put( "reference", "P1" );
+        properties.put( "firstname", "Jack" );
+        properties.put( "lastname", "Doe" );
+        restTester.putEntity( "P1", properties );
+        UnitOfWork work = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            PersonEntity entity = work.get( PersonEntity.class, new StringIdentity( "P1" ) );
+            assertEquals( "FirstName not changed.", "Jack", entity.firstname().get() );
+            assertEquals( "LastName not changed.", "Doe", entity.lastname().get() );
+            work.complete();
+        }
+        finally
+        {
+            work.discard();
+        }
+    }
+
+    @Test
+    public void givenExistingIdentityWhenExecutingDeleteCommandThenEntityIsRemoved()
+        throws Throwable
+    {
+        RestTester restTester = objectFactory.newObject( RestTester.class );
+        restTester.deleteEntity( "P1" );
+        UnitOfWork work = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            PersonEntity entity = null;
+            try
+            {
+                entity = work.get( PersonEntity.class, new StringIdentity( "P1" ) );
+            }
+            catch( NoSuchEntityException expected )
+            {
+                // expected
+            }
+            assertNull( "Entity not removed.", entity );
+            work.complete();
+        }
+        finally
+        {
+            work.discard();
+        }
+    }
+
+    @Test
+    public void givenExistingEntitiesWhenExecutingGetCommandThenExpectTheCorrectRdf()
+        throws Exception
+    {
+        final RestTester restTester = objectFactory.newObject( RestTester.class );
+        final String result = restTester.getEntities().replace( "\r", "" );
+        assertThat(
+            "Returned RDF", result,
+            anyOf(
+                equalTo( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rdf:RDF\n\txmlns=\"urn:polygene:\"\n\txmlns:polygene=\"http://polygene.apache.org/rdf/model/1.0/\"\n\txmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n\txmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">\n<polygene:entity rdf:about=\"/entity/P2.rdf\"/>\n<polygene:entity rdf:about=\"/entity/P1.rdf\"/>\n</rdf:RDF>\n" ),
+                equalTo( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\\\"no\\\"?>\n<rdf:RDF\n\txmlns=\"urn:polygene:\"\n\txmlns:polygene=\"http://polygene.apache.org/rdf/model/1.0/\"\n\txmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n\txmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">\n<polygene:entity rdf:about=\"/entity/P2.rdf\"/>\n<polygene:entity rdf:about=\"/entity/P1.rdf\"/>\n</rdf:RDF>\n" ),
+                equalTo( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rdf:RDF\n\txmlns=\"urn:polygene:\"\n\txmlns:polygene=\"http://polygene.apache.org/rdf/model/1.0/\"\n\txmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n\txmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">\n<polygene:entity rdf:about=\"/entity/P1.rdf\"/>\n<polygene:entity rdf:about=\"/entity/P2.rdf\"/>\n</rdf:RDF>\n" ),
+                equalTo( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\\\"no\\\"?>\n<rdf:RDF\n\txmlns=\"urn:polygene:\"\n\txmlns:polygene=\"http://polygene.apache.org/rdf/model/1.0/\"\n\txmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n\txmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">\n<polygene:entity rdf:about=\"/entity/P1.rdf\"/>\n<polygene:entity rdf:about=\"/entity/P2.rdf\"/>\n</rdf:RDF>\n" ) ) );
+    }
+
+    public static class RestTester
+    {
+
+        @Service
+        private RestServer server;
+
+        public String getEntity( String identity )
+            throws IOException
+        {
+            CloseableHttpClient client = HttpClients.createDefault();
+            HttpGet method = new HttpGet( "http://localhost:" + ADMIN_PORT + "/entity/" + identity + ".rdf" );
+            method.addHeader( "Accept", "application/rdf+xml" );
+            try( CloseableHttpResponse response = client.execute( method ) )
+            {
+                if( response.getStatusLine().getStatusCode() != 200 )
+                {
+                    throw new RuntimeException( "EntityResource returned status: " + response.getStatusLine() );
+                }
+                return EntityUtils.toString( response.getEntity(), StandardCharsets.UTF_8 );
+            }
+        }
+
+        public void putEntity( String identity, Map<String, String> params )
+            throws IOException
+        {
+            CloseableHttpClient client = HttpClients.createDefault();
+            HttpPost method = new HttpPost( "http://localhost:" + ADMIN_PORT + "/entity/" + identity );
+            List<NameValuePair> parameters = new ArrayList<>();
+            for( Map.Entry<String, String> entry : params.entrySet() )
+            {
+                parameters.add( new BasicNameValuePair( entry.getKey(), entry.getValue() ) );
+            }
+            method.setEntity( new UrlEncodedFormEntity( parameters ) );
+            try( CloseableHttpResponse response = client.execute( method ) )
+            {
+                if( response.getStatusLine().getStatusCode() != 205 )
+                {
+                    throw new RuntimeException( "EntityResource returned status: " + response.getStatusLine() );
+                }
+            }
+        }
+
+        public void deleteEntity( String identity )
+            throws IOException
+        {
+            CloseableHttpClient client = HttpClients.createDefault();
+            HttpDelete method = new HttpDelete( "http://localhost:" + ADMIN_PORT + "/entity/" + identity );
+            try( CloseableHttpResponse response = client.execute( method ) )
+            {
+                if( response.getStatusLine().getStatusCode() != 204 )
+                {
+                    throw new RuntimeException( "EntityResource returned status: " + response.getStatusLine() );
+                }
+            }
+        }
+
+        public String getEntities()
+            throws IOException
+        {
+            CloseableHttpClient client = HttpClients.createDefault();
+            HttpGet method = new HttpGet( "http://localhost:" + ADMIN_PORT + "/entity.rdf" );
+            method.addHeader( "Accept", "application/rdf+xml" );
+            try( CloseableHttpResponse response = client.execute( method ) )
+            {
+                if( response.getStatusLine().getStatusCode() != 200 )
+                {
+                    throw new RuntimeException( "EntityResource returned status: " + response.getStatusLine() );
+                }
+                return EntityUtils.toString( response.getEntity(), StandardCharsets.UTF_8 );
+            }
+        }
+    }
+
+    public interface PersonEntity
+        extends EntityComposite, Person
+    {
+    }
+
+    public interface Person
+    {
+
+        Property<String> firstname();
+
+        Property<String> lastname();
+
+        @Optional
+        Association<Person> mother();
+    }
+}
diff --git a/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/RestletServletAssembler.java b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/RestletServletAssembler.java
new file mode 100644
index 0000000..dc03964
--- /dev/null
+++ b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/RestletServletAssembler.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.apache.polygene.library.http.Servlets.addServlets;
+import static org.apache.polygene.library.http.Servlets.serve;
+
+/**
+ * JAVADOC
+ */
+public class RestletServletAssembler
+    implements Assembler
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        addServlets( serve( "/polygene/*" ).with( PolygeneServerServletService.class ) ).to( module );
+        // addFilters( filter( "/*" ).through( UnitOfWorkFilterService.class ).on( REQUEST ) ).to( module );
+    }
+}
\ No newline at end of file
diff --git a/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/TestEntity.java b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/TestEntity.java
new file mode 100644
index 0000000..ffc8890
--- /dev/null
+++ b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/TestEntity.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * JAVADOC
+ */
+public interface TestEntity
+    extends Named, EntityComposite
+{
+    @UseDefaults
+    Property<Integer> age();
+
+    @Optional
+    Property<TestValue> value();
+
+    @Optional
+    Property<String> unsetName();
+
+    @Optional
+    Association<TestEntity> association();
+
+    @Optional
+    Association<TestEntity> unsetAssociation();
+
+    ManyAssociation<TestEntity> manyAssociation();
+
+    ManyAssociation<TestEntity> rdfAssociation();
+}
+
diff --git a/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/TestEntity2.java b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/TestEntity2.java
new file mode 100644
index 0000000..0716b6c
--- /dev/null
+++ b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/TestEntity2.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import org.apache.polygene.api.entity.EntityComposite;
+
+/**
+ * JAVADOC
+ */
+public interface TestEntity2
+    extends Named, EntityComposite
+{
+}
\ No newline at end of file
diff --git a/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/TestRole.java b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/TestRole.java
new file mode 100644
index 0000000..4d3a91f
--- /dev/null
+++ b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/TestRole.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * JAVADOC
+ */
+public interface TestRole
+    extends EntityComposite
+{
+    Property<String> name();
+}
diff --git a/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/TestValue.java b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/TestValue.java
new file mode 100644
index 0000000..774650c
--- /dev/null
+++ b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/TestValue.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * JAVADOC
+ */
+public interface TestValue
+    extends ValueComposite
+{
+    @UseDefaults
+    Property<String> string();
+
+    @Optional
+    Property<TestValue2> testValue();
+
+    @UseDefaults
+    Property<List<Long>> longList();
+
+    Property<HashMap> map();
+}
diff --git a/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/TestValue2.java b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/TestValue2.java
new file mode 100644
index 0000000..779947a
--- /dev/null
+++ b/libraries/rest/src/test/java/org/apache/polygene/library/rest/admin/TestValue2.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.rest.admin;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * JAVADOC
+ */
+public interface TestValue2
+    extends ValueComposite
+{
+    @UseDefaults
+    Property<String> string();
+}
\ No newline at end of file
diff --git a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/DomainAssembler.java b/libraries/rest/src/test/java/org/qi4j/library/rest/admin/DomainAssembler.java
deleted file mode 100644
index eb5d656..0000000
--- a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/DomainAssembler.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.index.rdf.RdfIndexingEngineService;
-import org.qi4j.library.rdf.repository.MemoryRepositoryService;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-
-import static org.qi4j.api.common.Visibility.application;
-import static org.qi4j.api.common.Visibility.layer;
-
-/**
- * JAVADOC
- */
-public class DomainAssembler
-    implements Assembler
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services(
-            MemoryEntityStoreService.class,
-            UuidIdentityGeneratorService.class,
-            RdfIndexingEngineService.class
-        ).visibleIn( application );
-        module.services( MemoryRepositoryService.class ).identifiedBy( "rdf-indexing" ).visibleIn( layer );
-
-        module.entities( TestEntity.class, TestRole.class, TestEntity2.class ).visibleIn( application );
-        module.values( TestValue.class ).visibleIn( application );
-        module.services( DummyDataService.class ).instantiateOnStartup();
-    }
-}
diff --git a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/DummyDataService.java b/libraries/rest/src/test/java/org/qi4j/library/rest/admin/DummyDataService.java
deleted file mode 100644
index d1461d5..0000000
--- a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/DummyDataService.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import java.util.HashMap;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-
-@Mixins( DummyDataService.DummyDataMixin.class )
-@Activators( DummyDataService.Activator.class )
-public interface DummyDataService
-    extends ServiceComposite
-{
-    
-    void insertInitialData()
-            throws Exception;
-
-    static class Activator
-            extends ActivatorAdapter<ServiceReference<DummyDataService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<DummyDataService> activated )
-                throws Exception
-        {
-            activated.get().insertInitialData();
-        }
-
-    }
-    
-    abstract class DummyDataMixin
-        implements DummyDataService
-    {
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        @Structure
-        ValueBuilderFactory vbf;
-
-        public void insertInitialData()
-            throws Exception
-        {
-            UnitOfWork unitOfWork = uowf.newUnitOfWork();
-            try
-            {
-                {
-                    ValueBuilder<TestValue> valueBuilder = vbf.newValueBuilder( TestValue.class );
-                    valueBuilder.prototype().longList().get().add( 42L );
-                    valueBuilder.prototype().string().set( "Foo bar value" );
-                    valueBuilder.prototype().map().set( new HashMap() );
-
-                    EntityBuilder<TestEntity> builder = unitOfWork.newEntityBuilder( TestEntity.class, "test1" );
-                    builder.instance().name().set( "Foo bar" );
-                    builder.instance().age().set( 42 );
-                    builder.instance().value().set( valueBuilder.newInstance() );
-                    TestEntity testEntity = builder.newInstance();
-
-                    EntityBuilder<TestEntity> builder2 = unitOfWork.newEntityBuilder( TestEntity.class, "test2" );
-                    builder2.instance().name().set( "Xyzzy" );
-                    builder2.instance().age().set( 12 );
-                    builder2.instance().association().set( testEntity );
-                    builder2.instance().manyAssociation().add( 0, testEntity );
-                    builder2.instance().manyAssociation().add( 0, testEntity );
-
-                    EntityBuilder<TestRole> builder3 = unitOfWork.newEntityBuilder( TestRole.class );
-                    builder3.instance().name().set( "A role" );
-                    TestRole testRole = builder3.newInstance();
-
-                    builder2.newInstance();
-                }
-
-                {
-                    EntityBuilder<TestEntity2> builder = unitOfWork.newEntityBuilder( TestEntity2.class, "test3" );
-                    builder.instance().name().set( "Test3" );
-                    builder.newInstance();
-                }
-
-                unitOfWork.complete();
-            }
-            finally
-            {
-                unitOfWork.discard();
-            }
-        }
-
-    }
-}
diff --git a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/Main.java b/libraries/rest/src/test/java/org/qi4j/library/rest/admin/Main.java
deleted file mode 100644
index 25fb3f1..0000000
--- a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/Main.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import org.qi4j.api.structure.Application;
-import org.qi4j.bootstrap.Energy4Java;
-
-/**
- * JAVADOC
- */
-public class Main
-{
-    private Application application;
-
-    public static void main( String[] args )
-        throws Exception
-    {
-        new Main();
-    }
-
-    public Main()
-        throws Exception
-    {
-        Energy4Java qi4j = new Energy4Java();
-        application = qi4j.newApplication( new MainAssembler() );
-        application.activate();
-    }
-
-    public Application application()
-    {
-        return application;
-    }
-}
-
diff --git a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/MainAssembler.java b/libraries/rest/src/test/java/org/qi4j/library/rest/admin/MainAssembler.java
deleted file mode 100644
index 419d88e..0000000
--- a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/MainAssembler.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import org.qi4j.bootstrap.*;
-import org.qi4j.library.http.JettyServiceAssembler;
-
-/**
- * JAVADOC
- */
-public class MainAssembler
-    implements ApplicationAssembler
-{
-    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-        throws AssemblyException
-    {
-        return applicationFactory.newApplicationAssembly( new Assembler[][][]
-            {
-                // UI
-                {
-                    {
-                        new ModuleName( "Configuration store" ),
-                        new MemoryEntityStoreServiceAssembler(),
-                    },
-                    {
-                        new ModuleName( "Restlet servlet" ),
-                        new RestletServletAssembler(),
-                    },
-                    {
-                        new ModuleName( "Jetty" ),
-                        new JettyServiceAssembler()
-                    }
-                },
-                // Domain
-                {
-                    {
-                        new ModuleName( "Restlet application" ),
-                        new RestAssembler(),
-                    },
-                    {
-                        new ModuleName( "RDF" ),
-                        new RDFAssembler(),
-                    },
-                    {
-                        new ModuleName( "Domain" ),
-                        new DomainAssembler(),
-                    }
-                },
-                // Infrastructure
-                {
-                    {
-                        new ModuleName( "Domain store" ),
-                        new MemoryEntityStoreServiceAssembler()
-                    }
-                }
-            } );
-    }
-}
diff --git a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/MemoryEntityStoreServiceAssembler.java b/libraries/rest/src/test/java/org/qi4j/library/rest/admin/MemoryEntityStoreServiceAssembler.java
deleted file mode 100644
index 3a02bc3..0000000
--- a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/MemoryEntityStoreServiceAssembler.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-
-/**
- * JAVADOC
- */
-class MemoryEntityStoreServiceAssembler
-    implements Assembler
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( MemoryEntityStoreService.class ).visibleIn( Visibility.application );
-    }
-}
diff --git a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/Named.java b/libraries/rest/src/test/java/org/qi4j/library/rest/admin/Named.java
deleted file mode 100644
index 4862797..0000000
--- a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/Named.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-
-/**
- * JAVADOC
- */
-public interface Named
-{
-    @UseDefaults
-    Property<String> name();
-}
diff --git a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/RDFAssembler.java b/libraries/rest/src/test/java/org/qi4j/library/rest/admin/RDFAssembler.java
deleted file mode 100644
index 9d3ce77..0000000
--- a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/RDFAssembler.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.library.rdf.entity.EntityTypeSerializer;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-/**
- * JAVADOC
- */
-class RDFAssembler
-    implements Assembler
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new OrgJsonValueSerializationAssembler().assemble( module );
-        module.objects( EntityStateSerializer.class ).visibleIn( Visibility.application );
-        module.objects( EntityTypeSerializer.class ).visibleIn( Visibility.application );
-    }
-}
diff --git a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/RestTest.java b/libraries/rest/src/test/java/org/qi4j/library/rest/admin/RestTest.java
deleted file mode 100644
index 8e6c586..0000000
--- a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/RestTest.java
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.rest.admin;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.HashMap;
-import java.util.Map;
-import org.apache.commons.httpclient.HttpClient;
-import org.apache.commons.httpclient.methods.DeleteMethod;
-import org.apache.commons.httpclient.methods.GetMethod;
-import org.apache.commons.httpclient.methods.PostMethod;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.ApplicationAssemblerAdapter;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.index.rdf.assembly.RdfMemoryStoreAssembler;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.anyOf;
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.*;
-
-public class RestTest
-    extends AbstractQi4jTest
-{
-
-    @Override
-    protected ApplicationDescriptor newApplication()
-        throws AssemblyException
-    {
-        return qi4j.newApplicationModel( new ApplicationAssemblerAdapter( new Assembler[][][]
-            {
-                {
-                    {
-                        RestTest.this,
-                        new RestAssembler(),
-                        new RdfMemoryStoreAssembler()
-                    }
-                }
-            } )
-        {
-        } );
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.objects( RestTest.class, RestTester.class );
-        module.entities( PersonEntity.class );
-        module.services( RestServerComposite.class ).instantiateOnStartup();
-        module.services( MemoryEntityStoreService.class ).identifiedBy( "store" );
-        module.services( UuidIdentityGeneratorService.class );
-    }
-
-    @Override
-    @Before
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            EntityBuilder<PersonEntity> builder1 = uow.newEntityBuilder( PersonEntity.class, "P2" );
-            PersonEntity maryDoe = builder1.instance();
-            maryDoe.firstname().set( "Mary" );
-            maryDoe.lastname().set( "Doe" );
-            maryDoe = builder1.newInstance();
-
-            EntityBuilder<PersonEntity> builder2 = uow.newEntityBuilder( PersonEntity.class, "P1" );
-            PersonEntity joeDoe = builder2.instance();
-            joeDoe.firstname().set( "Joe" );
-            joeDoe.lastname().set( "Doe" );
-            joeDoe.mother().set( maryDoe );
-            builder2.newInstance();
-
-            uow.complete();
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void givenAnIdentityWhenExecutingGetCommandThenExpectTheCorrectRdf()
-        throws Exception
-    {
-        RestTester restTester = module.newObject( RestTester.class );
-        String rdf = restTester.getEntity( "P1" );
-        // System.out.println( rdf.replaceAll( "\n", "\\\\n" ).replaceAll( "\"", "\\\\\"" ) );
-        assertThat( "Incorrect RDF produced", rdf, anyOf(
-            // Open JDK 8 & Valid
-            equalTo( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rdf:RDF\n	xmlns:qi4j=\"http://www.qi4j.org/rdf/model/1.0/\"\n	xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n	xmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">\n<org.qi4j.library.rest.admin.RestTest-PersonEntity xmlns=\"urn:qi4j:type:\" rdf:about=\"urn:qi4j:entity:P1\">\n	<lastname xmlns=\"urn:qi4j:type:org.qi4j.library.rest.admin.RestTest-Person#\">Doe</lastname>\n	<firstname xmlns=\"urn:qi4j:type:org.qi4j.library.rest.admin.RestTest-Person#\">Joe</firstname>\n	<identity xmlns=\"urn:qi4j:type:org.qi4j.api.entity.Identity#\">P1</identity>\n	<mother xmlns=\"urn:qi4j:type:org.qi4j.library.rest.admin.RestTest-Person#\" rdf:resource=\"urn:qi4j:entity:P2\"/>\n</org.qi4j.library.rest.admin.RestTest-PersonEntity>\n\n</rdf:RDF>" ),
-            equalTo( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rdf:RDF\n	xmlns:qi4j=\"http://www.qi4j.org/rdf/model/1.0/\"\n	xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n	xmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">\n<org.qi4j.library.rest.admin.RestTest-PersonEntity xmlns=\"urn:qi4j:type:\" rdf:about=\"urn:qi4j:entity:P1\">\n	<identity xmlns=\"urn:qi4j:type:org.qi4j.api.entity.Identity#\">P1</identity>\n	<firstname xmlns=\"urn:qi4j:type:org.qi4j.library.rest.admin.RestTest-Person#\">Joe</firstname>\n	<lastname xmlns=\"urn:qi4j:type:org.qi4j.library.rest.admin.RestTest-Person#\">Doe</lastname>\n	<mother xmlns=\"urn:qi4j:type:org.qi4j.library.rest.admin.RestTest-Person#\" rdf:resource=\"urn:qi4j:entity:P2\"/>\n</org.qi4j.library.rest.admin.RestTest-PersonEntity>\n\n</rdf:RDF>" ),
-            // Sun JDK 6 / Oracle JDK 7 & Valid
-            equalTo( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rdf:RDF\n	xmlns:qi4j=\"http://www.qi4j.org/rdf/model/1.0/\"\n	xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n	xmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">\n<org.qi4j.library.rest.admin.RestTest-PersonEntity xmlns=\"urn:qi4j:type:\" rdf:about=\"urn:qi4j:entity:P1\">\n	<firstname xmlns=\"urn:qi4j:type:org.qi4j.library.rest.admin.RestTest-Person#\">Joe</firstname>\n	<lastname xmlns=\"urn:qi4j:type:org.qi4j.library.rest.admin.RestTest-Person#\">Doe</lastname>\n	<identity xmlns=\"urn:qi4j:type:org.qi4j.api.entity.Identity#\">P1</identity>\n	<mother xmlns=\"urn:qi4j:type:org.qi4j.library.rest.admin.RestTest-Person#\" rdf:resource=\"urn:qi4j:entity:P2\"/>\n</org.qi4j.library.rest.admin.RestTest-PersonEntity>\n\n</rdf:RDF>" ),
-            // IBM JDK 6 & Valid
-            equalTo( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rdf:RDF\n	xmlns:qi4j=\"http://www.qi4j.org/rdf/model/1.0/\"\n	xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n	xmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">\n<org.qi4j.library.rest.admin.RestTest-PersonEntity xmlns=\"urn:qi4j:type:\" rdf:about=\"urn:qi4j:entity:P1\">\n	<identity xmlns=\"urn:qi4j:type:org.qi4j.api.entity.Identity#\">P1</identity>\n	<lastname xmlns=\"urn:qi4j:type:org.qi4j.library.rest.admin.RestTest-Person#\">Doe</lastname>\n	<firstname xmlns=\"urn:qi4j:type:org.qi4j.library.rest.admin.RestTest-Person#\">Joe</firstname>\n	<mother xmlns=\"urn:qi4j:type:org.qi4j.library.rest.admin.RestTest-Person#\" rdf:resource=\"urn:qi4j:entity:P2\"/>\n</org.qi4j.library.rest.admin.RestTest-PersonEntity>\n\n</rdf:RDF>" ) ) );
-    }
-
-    @Test
-    public void givenExistingIdentityWhenExecutingPutCommandThenNewValuesInEntity()
-        throws Throwable
-    {
-        RestTester restTester = module.newObject( RestTester.class );
-        Map<String, String> properties = new HashMap<String, String>();
-        properties.put( "identity", "P1" );
-        properties.put( "firstname", "Jack" );
-        properties.put( "lastname", "Doe" );
-        restTester.putEntity( "P1", properties );
-        UnitOfWork work = module.newUnitOfWork();
-        try
-        {
-            PersonEntity entity = work.get( PersonEntity.class, "P1" );
-            assertEquals( "FirstName not changed.", "Jack", entity.firstname().get() );
-            assertEquals( "LastName not changed.", "Doe", entity.lastname().get() );
-            work.complete();
-        }
-        finally
-        {
-            work.discard();
-        }
-    }
-
-    @Test
-    public void givenExistingIdentityWhenExecutingDeleteCommandThenEntityIsRemoved()
-        throws Throwable
-    {
-        RestTester restTester = module.newObject( RestTester.class );
-        restTester.deleteEntity( "P1" );
-        UnitOfWork work = module.newUnitOfWork();
-        try
-        {
-            PersonEntity entity = null;
-            try
-            {
-                entity = work.get( PersonEntity.class, "P1" );
-            }
-            catch( NoSuchEntityException expected )
-            {
-                // expected
-            }
-            assertNull( "Entity not removed.", entity );
-            work.complete();
-        }
-        finally
-        {
-            work.discard();
-        }
-    }
-
-    @Test
-    public void givenExistingEntitiesWhenExecutingGetCommandThenExpectTheCorrectRdf()
-        throws Exception
-    {
-        final RestTester restTester = module.newObject( RestTester.class );
-        final String result = restTester.getEntities().replace( "\r", "" );
-        assertThat(
-            "Returned RDF", result,
-            anyOf(
-            equalTo( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rdf:RDF\n\txmlns=\"urn:qi4j:\"\n\txmlns:qi4j=\"http://www.qi4j.org/rdf/model/1.0/\"\n\txmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n\txmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">\n<qi4j:entity rdf:about=\"/entity/P2.rdf\"/>\n<qi4j:entity rdf:about=\"/entity/P1.rdf\"/>\n</rdf:RDF>\n" ),
-            equalTo( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\\\"no\\\"?>\n<rdf:RDF\n\txmlns=\"urn:qi4j:\"\n\txmlns:qi4j=\"http://www.qi4j.org/rdf/model/1.0/\"\n\txmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n\txmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">\n<qi4j:entity rdf:about=\"/entity/P2.rdf\"/>\n<qi4j:entity rdf:about=\"/entity/P1.rdf\"/>\n</rdf:RDF>\n" ),
-            equalTo( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rdf:RDF\n\txmlns=\"urn:qi4j:\"\n\txmlns:qi4j=\"http://www.qi4j.org/rdf/model/1.0/\"\n\txmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n\txmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">\n<qi4j:entity rdf:about=\"/entity/P1.rdf\"/>\n<qi4j:entity rdf:about=\"/entity/P2.rdf\"/>\n</rdf:RDF>\n" ),
-            equalTo( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\\\"no\\\"?>\n<rdf:RDF\n\txmlns=\"urn:qi4j:\"\n\txmlns:qi4j=\"http://www.qi4j.org/rdf/model/1.0/\"\n\txmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n\txmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">\n<qi4j:entity rdf:about=\"/entity/P1.rdf\"/>\n<qi4j:entity rdf:about=\"/entity/P2.rdf\"/>\n</rdf:RDF>\n" ) ) );
-    }
-
-    public static class RestTester
-    {
-
-        @Service
-        private RestServer server;
-
-        public String getEntity( String identity )
-            throws IOException
-        {
-            HttpClient client = new HttpClient();
-            GetMethod method = new GetMethod( "http://localhost:8182/entity/" + identity + ".rdf" );
-            method.addRequestHeader( "Accept", "application/rdf+xml" );
-            try
-            {
-                int status = client.executeMethod( method );
-                if( status != 200 )
-                {
-                    throw new RuntimeException( "EntityResource returned status code: '" + status + "' and message: '" + method.getStatusText() + "'" );
-                }
-                InputStream input = method.getResponseBodyAsStream();
-                ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                copyStream( input, baos );
-                return baos.toString( "UTF-8" );
-            }
-            finally
-            {
-                method.releaseConnection();
-            }
-        }
-
-        public void putEntity( String identity, Map<String, String> params )
-            throws IOException
-        {
-            HttpClient client = new HttpClient();
-            PostMethod method = new PostMethod( "http://localhost:8182/entity/" + identity );
-            for( Map.Entry<String, String> entry : params.entrySet() )
-            {
-                method.addParameter( entry.getKey(), entry.getValue() );
-            }
-            try
-            {
-                int status = client.executeMethod( method );
-                if( status != 205 )
-                {
-                    throw new RuntimeException( "EntityResource returned status code: '" + status + "' and message: '" + method.getStatusText() + "'" );
-                }
-            }
-            finally
-            {
-                method.releaseConnection();
-            }
-        }
-
-        public void deleteEntity( String identity )
-            throws IOException
-        {
-            HttpClient client = new HttpClient();
-            DeleteMethod method = new DeleteMethod( "http://localhost:8182/entity/" + identity );
-            try
-            {
-                int status = client.executeMethod( method );
-                if( status != 204 )
-                {
-                    throw new RuntimeException( "EntityResource returned status code: '" + status + "' and message: '" + method.getStatusText() + "'" );
-                }
-            }
-            finally
-            {
-                method.releaseConnection();
-            }
-        }
-
-        public String getEntities()
-            throws IOException
-        {
-            HttpClient client = new HttpClient();
-            GetMethod method = new GetMethod( "http://localhost:8182/entity.rdf" );
-            method.addRequestHeader( "Accept", "application/rdf+xml" );
-            try
-            {
-                int status = client.executeMethod( method );
-                if( status != 200 )
-                {
-                    throw new RuntimeException( "EntityResource returned status code: '" + status + "' and message: '" + method.getStatusText() + "'" );
-                }
-                InputStream input = method.getResponseBodyAsStream();
-                ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                copyStream( input, baos );
-                return baos.toString( "UTF-8" );
-            }
-            finally
-            {
-                method.releaseConnection();
-            }
-        }
-
-        private void copyStream( InputStream in, OutputStream baos )
-            throws IOException
-        {
-            int data = in.read();
-            while( data != -1 )
-            {
-                baos.write( data );
-                data = in.read();
-            }
-        }
-    }
-
-    public interface PersonEntity
-        extends EntityComposite, Person
-    {
-    }
-
-    public interface Person
-    {
-
-        Property<String> firstname();
-
-        Property<String> lastname();
-
-        @Optional
-        Association<Person> mother();
-    }
-
-}
diff --git a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/RestletServletAssembler.java b/libraries/rest/src/test/java/org/qi4j/library/rest/admin/RestletServletAssembler.java
deleted file mode 100644
index 60e4ec6..0000000
--- a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/RestletServletAssembler.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.rest.admin.Qi4jServerServletService;
-
-import static org.qi4j.library.http.Servlets.addServlets;
-import static org.qi4j.library.http.Servlets.serve;
-
-/**
- * JAVADOC
- */
-public class RestletServletAssembler
-    implements Assembler
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        addServlets( serve( "/qi4j/*" ).with( Qi4jServerServletService.class ) ).to( module );
-        // addFilters( filter( "/*" ).through( UnitOfWorkFilterService.class ).on( REQUEST ) ).to( module );
-    }
-}
\ No newline at end of file
diff --git a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/TestEntity.java b/libraries/rest/src/test/java/org/qi4j/library/rest/admin/TestEntity.java
deleted file mode 100644
index 5a31329..0000000
--- a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/TestEntity.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.property.Property;
-
-/**
- * JAVADOC
- */
-public interface TestEntity
-    extends Named, EntityComposite
-{
-    @UseDefaults
-    Property<Integer> age();
-
-    @Optional
-    Property<TestValue> value();
-
-    @Optional
-    Property<String> unsetName();
-
-    @Optional
-    Association<TestEntity> association();
-
-    @Optional
-    Association<TestEntity> unsetAssociation();
-
-    ManyAssociation<TestEntity> manyAssociation();
-
-    ManyAssociation<TestEntity> rdfAssociation();
-}
-
diff --git a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/TestEntity2.java b/libraries/rest/src/test/java/org/qi4j/library/rest/admin/TestEntity2.java
deleted file mode 100644
index 26212e5..0000000
--- a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/TestEntity2.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import org.qi4j.api.entity.EntityComposite;
-
-/**
- * JAVADOC
- */
-public interface TestEntity2
-    extends Named, EntityComposite
-{
-}
\ No newline at end of file
diff --git a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/TestRole.java b/libraries/rest/src/test/java/org/qi4j/library/rest/admin/TestRole.java
deleted file mode 100644
index 193193d..0000000
--- a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/TestRole.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-
-/**
- * JAVADOC
- */
-public interface TestRole
-    extends EntityComposite
-{
-    Property<String> name();
-}
diff --git a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/TestValue.java b/libraries/rest/src/test/java/org/qi4j/library/rest/admin/TestValue.java
deleted file mode 100644
index 9b97425..0000000
--- a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/TestValue.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * JAVADOC
- */
-public interface TestValue
-    extends ValueComposite
-{
-    @UseDefaults
-    Property<String> string();
-
-    @Optional
-    Property<TestValue2> testValue();
-
-    @UseDefaults
-    Property<List<Long>> longList();
-
-    Property<HashMap> map();
-}
diff --git a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/TestValue2.java b/libraries/rest/src/test/java/org/qi4j/library/rest/admin/TestValue2.java
deleted file mode 100644
index 785d2ea..0000000
--- a/libraries/rest/src/test/java/org/qi4j/library/rest/admin/TestValue2.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.rest.admin;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * JAVADOC
- */
-public interface TestValue2
-    extends ValueComposite
-{
-    @UseDefaults
-    Property<String> string();
-}
\ No newline at end of file
diff --git a/libraries/restlet/build.gradle b/libraries/restlet/build.gradle
new file mode 100644
index 0000000..95ab44b
--- /dev/null
+++ b/libraries/restlet/build.gradle
@@ -0,0 +1,51 @@
+/*
+ *  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.
+ *
+ *
+ */
+import org.apache.polygene.gradle.TaskGroups
+
+apply plugin: 'polygene-library'
+
+description = "Apache Polygene™ Restlet Library provides automatic CRUD resources as well as custom resources integrated to Polygene."
+
+jar { manifest { name = "Apache Polygene™ Library - Restlet" } }
+
+dependencies {
+  compileOnly libraries.servlet_api
+
+  api polygene.core.bootstrap
+
+  implementation polygene.extension( 'entitystore-file' )
+  implementation polygene.extension( 'indexing-rdf' )
+  implementation libraries.restlet
+
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+  testImplementation polygene.library( 'http' )
+  testImplementation libraries.http_client
+
+  testRuntimeOnly libraries.logback
+}
+
+task runRestletSample( type: JavaExec, dependsOn: 'testClasses' ) {
+  group = TaskGroups.SAMPLES
+  description = "Runs $project.name sample."
+  classpath = sourceSets.test.runtimeClasspath
+  main = 'org.apache.polygene.library.restlet.TestApplication'
+}
diff --git a/libraries/restlet/dev-status.xml b/libraries/restlet/dev-status.xml
new file mode 100644
index 0000000..66babc6
--- /dev/null
+++ b/libraries/restlet/dev-status.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
+  <status>
+    <!--none,early,beta,stable,mature-->
+    <codebase>stable</codebase>
+
+    <!-- none, brief, good, complete -->
+    <documentation>brief</documentation>
+
+    <!-- none, some, good, complete -->
+    <unittests>none</unittests>
+  </status>
+  <licenses>
+    <license>ALv2</license>
+  </licenses>
+</module>
\ No newline at end of file
diff --git a/libraries/restlet/src/docs/restlet.txt b/libraries/restlet/src/docs/restlet.txt
new file mode 100644
index 0000000..69cd82a
--- /dev/null
+++ b/libraries/restlet/src/docs/restlet.txt
@@ -0,0 +1,63 @@
+///////////////////////////////////////////////////////////////
+ * 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.
+///////////////////////////////////////////////////////////////
+
+[[library-restlet, Restlet Library]]
+= Restlet Support =
+
+[devstatus]
+--------------
+source=libraries/restlet/dev-status.xml
+--------------
+
+The Restlet Support Library has support to expose CRUD operations directly
+as well as regular Rest resources.
+
+include::../../build/docs/buildinfo/artifact.txt[]
+
+This library leverages +restlet.org+ which has a very neat way to map resources
+to URIs, and flexible ways to be served the requests. This library defines
+all the plumbing needed to set up Restlet, map resources to URIs, convert
+Polygene ValueComposites to resource representations (such as JSON) and
+create a fully HATEOAS environment, with single bookmarkable URI.
+
+To set up the Restlet Connectivity Module, it is recommended to use the provided
++Assembler+ for it;
+
+
+[[library-restlet-resource-binding, Restlet Resource Binding]]
+== Resource Binding ==
+REST defines that all URLs are *resources* and that a known, small set of
+operations can be done on those resources.
+
+
+
+== CRUD Repository ==
+This library provides a +CrudRepository+ which simplifies accessing entities
+directly from the Rest module. This is implemented by using the
+<<library-restlet-resource-binding, Resource Binding>> above.
+
+It also requires that one or more Crud Modules are defined. These are typically
+either in the domain layer directly, or in the layer above (some call that the
+service layer). There is a RestletCrudModuleAssembler that helps set up such
+module. Typical setup is like this;
+
+
+
+
+
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/Command.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/Command.java
new file mode 100644
index 0000000..cd739fe
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/Command.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.restlet;
+
+import org.apache.polygene.api.property.Property;
+
+public interface Command
+{
+    Property<String> name();
+
+    Property<RestForm> form();
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/ConversionException.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/ConversionException.java
new file mode 100644
index 0000000..5e11e3c
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/ConversionException.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.restlet;
+
+public class ConversionException extends RuntimeException
+{
+    public ConversionException( String entityAsText )
+    {
+        super( "Unable to convert REST entity: " + entityAsText );
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/FormField.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/FormField.java
new file mode 100644
index 0000000..5bbe2a5
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/FormField.java
@@ -0,0 +1,105 @@
+/*
+ *  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.polygene.library.restlet;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+
+@Mixins( FormField.Mixin.class )
+public interface FormField extends HasName
+{
+    String TEXT = "TEXT";
+
+    Property<String> type();
+
+    @Optional
+    @UseDefaults
+    Property<String> value();
+
+    Map.Entry<String,String> toMapEntry();
+
+    abstract class Mixin
+        implements FormField
+    {
+        @Override
+        public Map.Entry<String, String> toMapEntry()
+        {
+            return new StringMapEntry( name().get(), value().get() );
+        }
+    }
+
+    class StringMapEntry implements Map.Entry<String, String>
+    {
+        private final String key;
+        private final String value;
+
+        public StringMapEntry( String key, String value )
+        {
+            this.key = key;
+            this.value = value;
+        }
+
+        @Override
+        public String getKey()
+        {
+            return key;
+        }
+
+        @Override
+        public String getValue()
+        {
+            return value;
+        }
+
+        @Override
+        public String setValue( String value )
+        {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean equals( Object o )
+        {
+            if( this == o )
+            {
+                return true;
+            }
+            if( !( o instanceof StringMapEntry ) )
+            {
+                return false;
+            }
+            StringMapEntry miniMap = (StringMapEntry) o;
+            return Objects.equals( key, miniMap.key ) &&
+                   Objects.equals( value, miniMap.value );
+        }
+
+        @Override
+        public int hashCode()
+        {
+            return Objects.hash( key, value );
+        }
+    }
+
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/HasDescription.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/HasDescription.java
new file mode 100644
index 0000000..d4a8f85
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/HasDescription.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.restlet;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+public interface HasDescription
+{
+    @Optional @UseDefaults
+    Property<String> description();
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/HasName.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/HasName.java
new file mode 100644
index 0000000..a8f6517
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/HasName.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.library.restlet;
+
+import org.apache.polygene.api.property.Property;
+
+public interface HasName
+{
+    Property<String> name();
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/PolygeneEntityRestlet.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/PolygeneEntityRestlet.java
new file mode 100644
index 0000000..b76bfd3
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/PolygeneEntityRestlet.java
@@ -0,0 +1,311 @@
+/*
+ *  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.polygene.library.restlet;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.library.restlet.metainfo.UserIdentity;
+import org.apache.polygene.library.restlet.repository.RepositoryLocator;
+import org.apache.polygene.library.restlet.resource.DefaultResourceFactoryImpl;
+import org.apache.polygene.library.restlet.resource.NotPresentException;
+import org.apache.polygene.library.restlet.resource.ResourceFactory;
+import org.apache.polygene.library.restlet.resource.ServerResource;
+import org.apache.polygene.library.restlet.serialization.PolygeneConverter;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.restlet.Context;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.Restlet;
+import org.restlet.data.Form;
+import org.restlet.data.Method;
+import org.restlet.data.Parameter;
+import org.restlet.data.Status;
+import org.restlet.representation.Representation;
+import org.restlet.representation.Variant;
+import org.restlet.routing.Router;
+import org.restlet.security.User;
+
+public class PolygeneEntityRestlet<T extends HasIdentity> extends Restlet
+{
+    /**
+     * Creates a new PolygeneEntityRestlet instance for the given resource and entity classes.
+     * <p>
+     * This utility method should be used in your org.restlet.Application to create routes.
+     *
+     * @param <K>           Parameterized type of the resource
+     * @param <T>           Parameterized type of the entity
+     * @param module        Module to use for object instanciation
+     * @param router        Restlet Router
+     * @param resourceClass Resource class
+     * @param entityClass   Entity class
+     *
+     * @return The PolygeneEntityRestlet instance
+     */
+    public static <K extends HasIdentity, T extends ServerResource<K>> Restlet newInstance(
+        Module module, Router router, Class<T> resourceClass, Class<K> entityClass
+    )
+    {
+        @SuppressWarnings( "unchecked" )
+        ResourceFactory<K, T> factory = module.newObject( DefaultResourceFactoryImpl.class, resourceClass, router );
+        return module.newObject( PolygeneEntityRestlet.class, factory, router, entityClass, new PolygeneConverter( module ) );
+    }
+
+    @Structure
+    private ValueBuilderFactory vbf;
+
+    @Structure
+    private UnitOfWorkFactory uowf;
+
+    @Uses
+    private ResourceFactory resourceFactory;
+
+    @Uses
+    private Router router;
+
+    @Uses
+    @Optional
+    private Class<T> identityType;
+
+    @Structure
+    private PolygeneSPI spi;
+
+    @Uses
+    private PolygeneConverter converter;
+
+    @Service
+    private RepositoryLocator locator;
+
+    @Override
+    public void handle( Request request, Response response )
+    {
+        try
+        {
+            super.handle( request, response );
+            Method method = request.getMethod();
+            if( method.equals( Method.GET ) )
+            {
+                get( request, response );
+            }
+            if( method.equals( Method.DELETE ) )
+            {
+                delete( request, response );
+            }
+            if( method.equals( Method.POST ) )
+            {
+                post( request, response );
+            }
+            if( method.equals( Method.PUT ) )
+            {
+                put( request, response );
+            }
+        }
+        catch( RuntimeException e )
+        {
+            e.printStackTrace();
+            throw e;
+        }
+    }
+
+    private void get( Request request, Response response )
+    {
+        execute( request, response, resource -> {
+                     try
+                     {
+                         T result = resource.get();
+                         if( result != null )
+                         {
+                             if( result instanceof EntityComposite )
+                             {
+                                 result = locator.find( identityType ).toValue( result );
+                             }
+                             Representation representation = converter.toRepresentation( result, new Variant(), null );
+                             response.setEntity( representation );
+                             response.setEntity( representation );
+                             response.setStatus( Status.SUCCESS_OK );
+                         }
+                         else
+                         {
+                             response.setStatus( Status.CLIENT_ERROR_NOT_FOUND );
+                         }
+                     }
+                     catch( NoSuchEntityException e )
+                     {
+                         response.setStatus( Status.CLIENT_ERROR_NOT_FOUND, e, "Entity not found." );
+                     }
+                 }
+        );
+    }
+
+    private void put( Request request, Response response )
+    {
+        execute( request, response, resource -> {
+
+            T value = convertToObject( identityType, request );
+            resource.put( value );
+            response.setStatus( Status.SUCCESS_OK );
+        } );
+    }
+
+    private void delete( Request request, Response response )
+    {
+        execute( request, response, resource -> {
+            resource.delete();
+            response.setStatus( Status.SUCCESS_NO_CONTENT );
+        } );
+    }
+
+    private void post( final Request request, final Response response )
+    {
+        execute( request, response, resource -> {
+            RestForm form = createRestForm( request );
+            RestLink link = resource.post( form );
+            response.setLocationRef( link.path().get() );
+            response.setStatus( Status.REDIRECTION_SEE_OTHER );
+        } );
+    }
+
+    private RestForm createRestForm( final Request request )
+    {
+        //noinspection MismatchedQueryAndUpdateOfCollection
+        Form form = new Form( request.getEntity() );
+        ValueBuilder<RestForm> builder = vbf.newValueBuilderWithState(
+            RestForm.class,
+            descriptor -> {
+                if( descriptor.qualifiedName().name().equals( "fields" ) )
+                {
+                    List<FormField> result = new ArrayList<>();
+                    for( Parameter param : form )
+                    {
+                        String name = param.getName();
+                        String value = param.getValue();
+                        ValueBuilder<FormField> fieldBuilder = vbf.newValueBuilder( FormField.class );
+                        FormField prototype = fieldBuilder.prototype();
+                        prototype.name().set( name );
+                        prototype.value().set( value );
+                        prototype.type().set( FormField.TEXT );
+                        result.add( fieldBuilder.newInstance() );
+                    }
+                    return result;
+                }
+                return null;
+            },
+            descriptor -> null,
+            descriptor -> null,
+            descriptor -> null
+        );
+        return builder.newInstance();
+    }
+
+    private void execute( Request request, Response response, Consumer<ServerResource<T>> closure )
+    {
+        UnitOfWork uow = null;
+        try
+        {
+            uow = createUnitOfWork( request );
+            ServerResource<T> resource = createResource( request, response, getContext() );
+            closure.accept( resource );
+            uow.complete();
+        }
+        catch( UnsupportedOperationException e )
+        {
+            e.printStackTrace();
+            response.setStatus( Status.CLIENT_ERROR_BAD_REQUEST, e, e.getMessage() );
+        }
+        catch( ConversionException e )
+        {
+            e.printStackTrace();
+            response.setStatus( Status.CLIENT_ERROR_BAD_REQUEST, e.getMessage() );
+        }
+        catch( NotPresentException e )
+        {
+            e.printStackTrace();
+            response.setStatus( Status.CLIENT_ERROR_NOT_FOUND, e.getMessage() );
+        }
+        catch( Throwable e )
+        {
+            e.printStackTrace();
+            response.setStatus( Status.CLIENT_ERROR_BAD_REQUEST, e.getMessage() );
+        }
+        finally
+        {
+            if( uow != null && uow.isOpen() )
+            {
+                uow.discard();
+            }
+        }
+    }
+
+    private ServerResource<T> createResource( Request request, Response response, Context context )
+    {
+        @SuppressWarnings( "unchecked" )
+        ServerResource<T> serverResource = resourceFactory.create( identityType, request, response, context );
+        return serverResource;
+    }
+
+    private UnitOfWork createUnitOfWork( Request request )
+    {
+        UsecaseBuilder usecaseBuilder = UsecaseBuilder.buildUsecase( request.getResourceRef().getIdentifier( true ) );
+        User user = request.getClientInfo().getUser();
+        if( user != null )
+        {
+            UserIdentity userIdentity = new UserIdentity( user.getIdentifier(),
+                                                          user.getName(),
+                                                          user.getEmail(),
+                                                          user.getFirstName(),
+                                                          user.getLastName()
+            );
+            usecaseBuilder.withMetaInfo( userIdentity );
+        }
+        return uowf.newUnitOfWork( usecaseBuilder.newUsecase() );
+    }
+
+    private <K> K convertToObject( Class<K> type, Request request )
+    {
+        try
+        {
+            return converter.toObject( request.getEntity(), type, null );
+        }
+        catch( IOException e )
+        {
+            throw new ConversionException( request.getEntityAsText() );
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        return "PolygeneRestlet[" + ( identityType == null ? "<null>" : identityType.getSimpleName() ) + ", " + resourceFactory + "]";
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/PolygeneRestApplication.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/PolygeneRestApplication.java
new file mode 100644
index 0000000..4df326f
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/PolygeneRestApplication.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.polygene.library.restlet;
+
+import java.util.logging.Level;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.layered.LayeredApplicationAssembler;
+import org.apache.polygene.library.restlet.crud.EntityListResource;
+import org.apache.polygene.library.restlet.crud.EntityResource;
+import org.apache.polygene.library.restlet.resource.CreationResource;
+import org.apache.polygene.library.restlet.resource.DefaultResourceFactoryImpl;
+import org.apache.polygene.library.restlet.resource.EntryPoint;
+import org.apache.polygene.library.restlet.resource.EntryPointResource;
+import org.apache.polygene.library.restlet.resource.ResourceFactory;
+import org.apache.polygene.library.restlet.resource.ServerResource;
+import org.apache.polygene.library.restlet.serialization.PolygeneConverter;
+import org.restlet.Context;
+import org.restlet.Restlet;
+import org.restlet.data.ChallengeScheme;
+import org.restlet.data.Parameter;
+import org.restlet.engine.Engine;
+import org.restlet.routing.Filter;
+import org.restlet.routing.Router;
+import org.restlet.routing.TemplateRoute;
+import org.restlet.security.ChallengeAuthenticator;
+import org.restlet.security.Enroler;
+import org.restlet.security.Verifier;
+import org.restlet.util.Series;
+
+/**
+ * This class is generic enough to be promoted to Polygene's Restlet Library
+ */
+public abstract class PolygeneRestApplication extends org.restlet.Application
+{
+    protected org.apache.polygene.api.structure.Application polygeneApplication;
+    protected ServiceFinder serviceFinder;
+    protected ObjectFactory objectFactory;
+    protected TransientBuilderFactory transientBuilderFactory;
+    protected UnitOfWorkFactory unitOfWorkFactory;
+    protected ValueBuilderFactory valueBuilderFactory;
+
+    private Router router;
+
+    public PolygeneRestApplication( Context context )
+        throws AssemblyException
+    {
+        super( context );
+    }
+
+    protected void printRoutes()
+    {
+        router.getRoutes().forEach(
+            route -> System.out.println( route.toString() ) );
+    }
+
+    protected abstract LayeredApplicationAssembler createApplicationAssembler( String mode )
+        throws AssemblyException;
+
+    @Override
+    public synchronized void start()
+        throws Exception
+    {
+        Series<Parameter> parameters = getContext().getParameters();
+        String mode = parameters.getFirstValue( "org.apache.polygene.runtime.mode" );
+        createApplication( mode );
+        polygeneApplication.activate();
+        Module module = polygeneApplication.findModule( getConnectivityLayer(), getConnectivityModule() );
+        serviceFinder = module;
+        objectFactory = module;
+        transientBuilderFactory = module;
+        unitOfWorkFactory = module.unitOfWorkFactory();
+        valueBuilderFactory = module;
+        super.start();
+    }
+
+    private void createApplication( String mode )
+    {
+        try
+        {
+            LayeredApplicationAssembler assembler = createApplicationAssembler(mode);
+            assembler.initialize();
+            polygeneApplication = assembler.application();
+            setName( polygeneApplication.name() );
+        }
+        catch( Throwable e )
+        {
+            e.printStackTrace();
+            getLogger().log( Level.SEVERE, "Unable to start Polygene application.", e );
+            throw new InternalError( "Unable to start Polygene application.", e );
+        }
+        getLogger().info( "RestApplication successfully created." );
+    }
+
+    @Override
+    public synchronized void stop()
+        throws Exception
+    {
+        super.stop();
+        polygeneApplication.passivate();
+    }
+
+    @Override
+    public Restlet createInboundRoot()
+    {
+        Context context = getContext();
+        Engine.getInstance().getRegisteredConverters().add( new PolygeneConverter( objectFactory ) );
+
+        if( polygeneApplication.mode() == Application.Mode.development )
+        {
+            setDebugging( true );
+        }
+        router = new Router( context );
+
+        addRoutes( router );
+        router.attach( "/", newPolygeneRestlet( EntryPointResource.class, EntryPoint.class ) );
+
+        ChallengeAuthenticator guard = new ChallengeAuthenticator( context, ChallengeScheme.HTTP_BASIC, "Storm Clouds" );
+
+        Verifier verifier = createVerifier();
+        if( verifier != null )
+        {
+            guard.setVerifier( verifier );
+        }
+
+        Enroler enroler = createEnroler();
+        if( enroler != null )
+        {
+            guard.setEnroler( enroler );
+        }
+        return createInterceptors( guard );
+    }
+
+    private Restlet createInterceptors( ChallengeAuthenticator guard )
+    {
+        Filter inner = createInnerInterceptor();
+        if( inner != null )
+        {
+            inner.setNext( router );
+            guard.setNext( inner );             // guard -> interceptor -> router
+        }
+        else
+        {
+            guard.setNext( router );            // guard -> router
+        }
+        inner = guard;                      // inner = guard
+
+        Filter outer = createOuterInterceptor();
+        if( outer != null )
+        {
+            outer.setNext( inner );             // outer -> inner
+            return outer;
+        }
+        return inner;
+    }
+
+    protected Filter createOuterInterceptor()
+    {
+        return null;
+    }
+
+    protected Filter createInnerInterceptor()
+    {
+        return null;
+    }
+
+    protected Verifier createVerifier()
+    {
+        return null;
+    }
+
+    protected Enroler createEnroler()
+    {
+        return null;
+    }
+
+    protected abstract String getConnectivityLayer();
+
+    protected abstract String getConnectivityModule();
+
+    protected abstract void addRoutes( Router router );
+
+    protected void addResourcePath( String name,
+                                    Class<? extends HasIdentity> type,
+                                    String basePath
+    )
+    {
+        addResourcePath( name, type, basePath, true, true );
+    }
+
+    protected void addResourcePath( String name,
+                                    Class<? extends HasIdentity> type,
+                                    String basePath,
+                                    boolean createLink,
+                                    boolean rootRoute
+    )
+    {
+        if( createLink )
+        {
+            router.attach( basePath + name + "/create", newPolygeneRestlet( CreationResource.class, type ) );
+        }
+        TemplateRoute route = router.attach( basePath + name + "/", newPolygeneRestlet( EntityListResource.class, type ) );
+        if( rootRoute )
+        {
+            route.setName( name );
+        }
+        router.attach( basePath + name + "/{id}/", newPolygeneRestlet( EntityResource.class, type ) );
+        router.attach( basePath + name + "/{id}/{invoke}", newPolygeneRestlet( EntityResource.class, type ) );
+    }
+
+    private <K extends HasIdentity, T extends ServerResource<K>> Restlet newPolygeneRestlet(Class<T> resourceClass,
+                                                                                        Class<K> entityClass
+    )
+    {
+
+        @SuppressWarnings( "unchecked" )
+        ResourceFactory<K, T> factory = objectFactory.newObject( DefaultResourceFactoryImpl.class,
+                                                                 resourceClass, router
+        );
+        PolygeneConverter converter = new PolygeneConverter( objectFactory );
+        return objectFactory.newObject( PolygeneEntityRestlet.class,
+                                        factory,
+                                        router,
+                                        entityClass,
+                                        converter
+        );
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/PolygeneServerServlet.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/PolygeneServerServlet.java
new file mode 100644
index 0000000..ce5cf03
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/PolygeneServerServlet.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.library.restlet;
+
+import javax.servlet.Servlet;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.structure.Module;
+import org.restlet.Context;
+import org.restlet.ext.servlet.ServerServlet;
+
+/**
+ * Restlet ServerServlet backed by a org.restlet.Application object.
+ */
+@Mixins( PolygeneServerServlet.Mixin.class )
+public interface PolygeneServerServlet extends Servlet
+{
+    class Mixin
+        extends ServerServlet
+    {
+        @Structure
+        private Module module;
+
+        @Override
+        protected org.restlet.Application createApplication( Context parentContext )
+        {
+            return module.newObject( org.restlet.Application.class, parentContext.createChildContext() );
+        }
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/RestForm.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/RestForm.java
new file mode 100644
index 0000000..6f6cdfb
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/RestForm.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.library.restlet;
+
+import java.util.List;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.restlet.filters.NameFilter;
+
+@Mixins( RestForm.Mixin.class )
+public interface RestForm
+{
+    FormField field( String name );
+
+    @Optional
+    Property<RestLink> link();
+
+    Property<List<FormField>> fields();
+
+    abstract class Mixin
+        implements RestForm
+    {
+        @Override
+        public FormField field( String name )
+        {
+            return fields().get().stream().filter( new NameFilter( name ) ).findFirst().orElse( null );
+        }
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/RestLink.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/RestLink.java
new file mode 100644
index 0000000..c2b4371
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/RestLink.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.library.restlet;
+
+import org.apache.polygene.api.property.Property;
+
+public interface RestLink extends HasDescription
+{
+    Property<String> method();
+
+    Property<String> path();
+}
\ No newline at end of file
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/CrudServiceAssembler.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/CrudServiceAssembler.java
new file mode 100644
index 0000000..7eae33f
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/CrudServiceAssembler.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.restlet.assembly;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.restlet.identity.IdentityManager;
+import org.apache.polygene.library.restlet.identity.IdentityMappingConfiguration;
+import org.apache.polygene.library.restlet.repository.RepositoryLocator;
+
+public class CrudServiceAssembler
+    implements Assembler
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( IdentityMappingConfiguration.class );
+        module.services( IdentityManager.class ).visibleIn( Visibility.application ).instantiateOnStartup();
+        module.services( RepositoryLocator.class ).visibleIn( Visibility.application );
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/GenericRestLayer.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/GenericRestLayer.java
new file mode 100644
index 0000000..8b286ab
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/GenericRestLayer.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.restlet.assembly;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.layered.LayeredLayerAssembler;
+
+public class GenericRestLayer extends LayeredLayerAssembler
+{
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        return null;
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/RestApplicationAssembler.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/RestApplicationAssembler.java
new file mode 100644
index 0000000..61f5b08
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/RestApplicationAssembler.java
@@ -0,0 +1,86 @@
+/*
+ *  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.polygene.library.restlet.assembly;
+
+import java.util.LinkedHashMap;
+import java.util.function.BinaryOperator;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.layered.LayerAssembler;
+import org.apache.polygene.bootstrap.layered.LayeredApplicationAssembler;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+
+public class RestApplicationAssembler extends LayeredApplicationAssembler
+{
+    private final LinkedHashMap<Class<? extends LayerAssembler>, LayerAssembly> assemblies = new LinkedHashMap<>();
+    private Class<? extends LayerAssembler>[] layers;
+
+    @SafeVarargs
+    public RestApplicationAssembler( String name, String version, Application.Mode mode, Class<? extends LayerAssembler>... layers )
+        throws AssemblyException
+    {
+        super( name, version, mode );
+        this.layers = layers;
+    }
+
+    @Override
+    protected void assembleLayers( ApplicationAssembly assembly )
+        throws AssemblyException
+    {
+        for( Class<? extends LayerAssembler> layer : layers )
+        {
+            LayerAssembly layerAssembly = createLayer( layer );
+            assemblies.put( layer, layerAssembly );
+        }
+    }
+
+    public void setupUses( BinaryOperator<LayerAssembly> uses )
+    {
+        assemblies.values().stream().reduce( uses );
+    }
+
+    public void setupUses()
+    {
+        assemblies.values().stream().reduce( LayerAssembly::uses );
+    }
+
+    public LayerAssembly layer( Class<? extends LayerAssembler> layerClass, ModuleAssembler... assemblers )
+    {
+        return assemblies.get( layerClass );
+    }
+
+    public void addShutdownHook()
+    {
+        Runtime.getRuntime().addShutdownHook( new Thread( () -> {
+            try
+            {
+                stop();
+            }
+            catch( PassivationException e )
+            {
+                e.printStackTrace();
+            }
+        } ) );
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/RestletCrudConnectivityAssembler.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/RestletCrudConnectivityAssembler.java
new file mode 100644
index 0000000..815691a
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/RestletCrudConnectivityAssembler.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.library.restlet.assembly;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.restlet.Command;
+import org.apache.polygene.library.restlet.FormField;
+import org.apache.polygene.library.restlet.PolygeneEntityRestlet;
+import org.apache.polygene.library.restlet.RestForm;
+import org.apache.polygene.library.restlet.RestLink;
+import org.apache.polygene.library.restlet.crud.EntityList;
+import org.apache.polygene.library.restlet.crud.EntityListResource;
+import org.apache.polygene.library.restlet.crud.EntityRef;
+import org.apache.polygene.library.restlet.crud.EntityResource;
+import org.apache.polygene.library.restlet.resource.CreationResource;
+import org.apache.polygene.library.restlet.resource.DefaultResourceFactoryImpl;
+import org.apache.polygene.library.restlet.resource.EntryPointResource;
+import org.apache.polygene.library.restlet.resource.ResourceBuilder;
+import org.apache.polygene.library.restlet.serialization.FormRepresentation;
+import org.apache.polygene.library.restlet.serialization.JsonRepresentation;
+
+public class RestletCrudConnectivityAssembler
+    implements Assembler
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.values( EntryPointResource.class,
+                       EntityListResource.class,
+                       EntityResource.class,
+                       CreationResource.class )
+            .visibleIn( Visibility.layer );
+        module.values( Command.class,
+                       FormField.class,
+                       RestForm.class,
+                       RestLink.class,
+                       EntityList.class,
+                       EntityRef.class )
+            .visibleIn( Visibility.layer );
+        module.objects( DefaultResourceFactoryImpl.class,
+                        JsonRepresentation.class,
+                        FormRepresentation.class,
+                        PolygeneEntityRestlet.class )
+            .visibleIn( Visibility.layer );
+        module.services( ResourceBuilder.class ).visibleIn( Visibility.layer );
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/RestletCrudModuleAssembler.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/RestletCrudModuleAssembler.java
new file mode 100644
index 0000000..4e859db
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/RestletCrudModuleAssembler.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.library.restlet.assembly;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkConcern;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.restlet.repository.CrudRepository;
+import org.apache.polygene.library.restlet.repository.EntityTypeDescriptor;
+import org.apache.polygene.library.restlet.repository.SmallCrudRepositoryMixin;
+
+public class RestletCrudModuleAssembler
+    implements Assembler
+{
+    private final Class type;
+    private final Class repositoryType;
+
+    public RestletCrudModuleAssembler( Class type, Class repositoryType )
+    {
+        this.type = type;
+        this.repositoryType = repositoryType;
+    }
+
+    public RestletCrudModuleAssembler( Class type )
+    {
+        this.type = type;
+        repositoryType = CrudRepository.class;
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module
+            .addServices( repositoryType )
+            .identifiedBy( "repository_" + type.getSimpleName() )
+            .visibleIn( Visibility.application )
+            .withMixins( SmallCrudRepositoryMixin.class )
+            .withConcerns( UnitOfWorkConcern.class )
+            .taggedWith( type.getSimpleName() )
+            .setMetaInfo( new EntityTypeDescriptor( type ) )
+        ;
+        module.entities( type ).visibleIn( Visibility.layer );
+        module.values( type ).visibleIn( Visibility.layer );
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/configuration/ConfigurationLayer.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/configuration/ConfigurationLayer.java
new file mode 100644
index 0000000..c3ac858
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/configuration/ConfigurationLayer.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.library.restlet.assembly.configuration;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.LayerAssembler;
+import org.apache.polygene.bootstrap.layered.LayeredLayerAssembler;
+
+public class ConfigurationLayer extends LayeredLayerAssembler
+    implements LayerAssembler
+{
+    public static final String NAME = "Configuration Layer";
+    private ModuleAssembly configModule;
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        configModule = createModule( layer, ConfigurationModule.class );
+        return layer;
+    }
+
+    public ModuleAssembly configModule()
+    {
+        return configModule;
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/configuration/ConfigurationModule.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/configuration/ConfigurationModule.java
new file mode 100644
index 0000000..1050e8a
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/configuration/ConfigurationModule.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.restlet.assembly.configuration;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+
+public class ConfigurationModule
+    implements ModuleAssembler
+{
+    public static final String NAME = "Configuration Module";
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( MemoryEntityStoreService.class ).visibleIn( Visibility.layer );
+        return module;
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/connectivity/ConnectivityLayer.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/connectivity/ConnectivityLayer.java
new file mode 100644
index 0000000..6d73d76
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/connectivity/ConnectivityLayer.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.restlet.assembly.connectivity;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.layered.LayerAssembler;
+import org.apache.polygene.bootstrap.layered.LayeredLayerAssembler;
+
+public class ConnectivityLayer extends LayeredLayerAssembler
+    implements LayerAssembler
+{
+    public static final String NAME = "Connectivity Layer";
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        createModule( layer, RestModule.class );
+        createModule( layer, SecurityModule.class );
+        return layer;
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/connectivity/RestModule.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/connectivity/RestModule.java
new file mode 100644
index 0000000..195978a
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/connectivity/RestModule.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.library.restlet.assembly.connectivity;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.library.restlet.assembly.RestletCrudConnectivityAssembler;
+import org.apache.polygene.library.restlet.resource.EntryPoint;
+
+public class RestModule
+    implements ModuleAssembler
+{
+    public static final String NAME = "REST Module";
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        new RestletCrudConnectivityAssembler().assemble( module );
+        module.values( EntryPoint.class );
+        return module;
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/connectivity/SecurityModule.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/connectivity/SecurityModule.java
new file mode 100644
index 0000000..b613b57
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/connectivity/SecurityModule.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.restlet.assembly.connectivity;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+
+public class SecurityModule
+    implements ModuleAssembler
+{
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        return module;
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/domain/CrudModule.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/domain/CrudModule.java
new file mode 100644
index 0000000..16ac2c6
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/domain/CrudModule.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.restlet.assembly.domain;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.library.restlet.assembly.CrudServiceAssembler;
+
+public class CrudModule
+    implements ModuleAssembler
+{
+    public static final String NAME = "CRUD Module";
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        new CrudServiceAssembler().assemble( module );
+        return module;
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/domain/DomainLayer.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/domain/DomainLayer.java
new file mode 100644
index 0000000..80611dc
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/domain/DomainLayer.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.restlet.assembly.domain;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.layered.LayerAssembler;
+import org.apache.polygene.bootstrap.layered.LayeredLayerAssembler;
+
+public class DomainLayer extends LayeredLayerAssembler
+    implements LayerAssembler
+{
+    public static final String NAME = "Domain Layer";
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        createModule( layer, CrudModule.class );
+        return layer;
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/infrastructue/FileStorageModule.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/infrastructue/FileStorageModule.java
new file mode 100644
index 0000000..1146378
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/infrastructue/FileStorageModule.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.polygene.library.restlet.assembly.infrastructue;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.entitystore.file.assembly.FileEntityStoreAssembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+
+public class FileStorageModule
+    implements ModuleAssembler
+{
+    public static final String NAME = "Storage Module";
+
+    private final ModuleAssembly configModule;
+
+    public FileStorageModule( ModuleAssembly configModule )
+    {
+        this.configModule = configModule;
+    }
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        new FileEntityStoreAssembler()
+            .visibleIn( Visibility.application  )
+            .withConfig( configModule, Visibility.application )
+            .assemble( module );
+        return module;
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/infrastructue/IndexingModule.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/infrastructue/IndexingModule.java
new file mode 100644
index 0000000..76a97c8
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/infrastructue/IndexingModule.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.library.restlet.assembly.infrastructue;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.index.rdf.assembly.RdfNativeSesameStoreAssembler;
+import org.apache.polygene.library.rdf.repository.NativeConfiguration;
+
+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
+    {
+//        new FileConfigurationAssembler().assemble( module );
+//        new ESFilesystemIndexQueryAssembler()
+//            .visibleIn( Visibility.application )
+//            .withConfig( configModule, Visibility.application )
+//            .assemble( module );
+
+        configModule.entities( NativeConfiguration.class ).visibleIn( Visibility.application );
+        new RdfNativeSesameStoreAssembler(Visibility.application, Visibility.module).assemble( module );
+        return module;
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/infrastructue/InfrastructureLayer.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/infrastructue/InfrastructureLayer.java
new file mode 100644
index 0000000..ad3e56a
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/infrastructue/InfrastructureLayer.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.library.restlet.assembly.infrastructue;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.LayerAssembler;
+import org.apache.polygene.bootstrap.layered.LayeredLayerAssembler;
+import org.apache.polygene.library.restlet.assembly.configuration.ConfigurationLayer;
+import org.apache.polygene.library.restlet.assembly.configuration.ConfigurationModule;
+
+public class InfrastructureLayer extends LayeredLayerAssembler
+    implements LayerAssembler
+{
+    public static final String NAME = "Infrastructure Layer";
+    private final ModuleAssembly configModule;
+
+    public static InfrastructureLayer create( LayerAssembly layer )
+    {
+        ModuleAssembly config = layer.application().layer( ConfigurationLayer.NAME ).module( ConfigurationModule.NAME );
+        return new InfrastructureLayer( config );
+    }
+
+    public InfrastructureLayer( ModuleAssembly configModule )
+    {
+        this.configModule = configModule;
+    }
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        new IndexingModule( configModule ).assemble( layer, layer.module( IndexingModule.NAME ) );
+        new SerializationModule().assemble( layer, layer.module( SerializationModule.NAME ) );
+        return layer;
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/infrastructue/SerializationModule.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/infrastructue/SerializationModule.java
new file mode 100644
index 0000000..275cb27
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/infrastructue/SerializationModule.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.restlet.assembly.infrastructue;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+
+public class SerializationModule
+    implements ModuleAssembler
+{
+    public static final String NAME = "Serialization Module";
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        return module;
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/resource/ResourceLayer.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/resource/ResourceLayer.java
new file mode 100644
index 0000000..e986d16
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/assembly/resource/ResourceLayer.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.restlet.assembly.resource;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.layered.LayerAssembler;
+import org.apache.polygene.bootstrap.layered.LayeredLayerAssembler;
+
+public class ResourceLayer extends LayeredLayerAssembler
+    implements LayerAssembler
+{
+    public static final String NAME = "Resource Layer";
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        return layer;
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/EntityList.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/EntityList.java
new file mode 100644
index 0000000..7eebdce
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/EntityList.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.restlet.crud;
+
+import java.util.List;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.restlet.Command;
+
+public interface EntityList extends HasIdentity
+{
+    Property<List<EntityRef>> entities();
+
+    Property<List<Command>> commands();
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/EntityListResource.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/EntityListResource.java
new file mode 100644
index 0000000..6085c22
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/EntityListResource.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.polygene.library.restlet.crud;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.library.restlet.FormField;
+import org.apache.polygene.library.restlet.RestForm;
+import org.apache.polygene.library.restlet.RestLink;
+import org.apache.polygene.library.restlet.identity.IdentityManager;
+import org.apache.polygene.library.restlet.repository.CrudRepository;
+import org.apache.polygene.library.restlet.repository.RepositoryLocator;
+import org.apache.polygene.library.restlet.resource.ResourceBuilder;
+import org.apache.polygene.library.restlet.resource.ServerResource;
+import org.restlet.Request;
+import org.restlet.data.Method;
+import org.restlet.data.Reference;
+
+@Mixins( EntityListResource.Mixin.class )
+public interface EntityListResource<T extends HasIdentity> extends ServerResource<EntityList>
+{
+    abstract class Mixin<T extends HasIdentity>
+        implements EntityListResource<T>
+    {
+        @This
+        private Parameters<T> parameters;
+
+        @Structure
+        private ValueBuilderFactory vbf;
+
+        @Service
+        private ResourceBuilder resourceBuilder;
+
+        @Service
+        private RepositoryLocator locator;
+
+        @Service
+        private IdentityManager identityManager;
+
+        @Override
+        public EntityList get()
+        {
+            Property<Request> request = parameters.request();
+            Reference base = request.get().getResourceRef();
+            String name = "list[" + parameters.entityType().get().getSimpleName() + "]";
+            Identity identity = identityManager.generate( EntityListResource.class, name );
+            ValueBuilder<EntityList> builder = vbf.newValueBuilder( EntityList.class );
+            List<EntityRef> result = getEntityRefs( base );
+            EntityList prototype = builder.prototype();
+            prototype.identity().set( identity );
+            prototype.entities().set( Collections.unmodifiableList( result ) );
+            prototype.commands().set( Collections.singletonList( resourceBuilder.createCommand( base ) ) );
+            return builder.newInstance();
+        }
+
+        @Override
+        public RestLink post( RestForm form )
+        {
+            FormField nameField = form.field( "name" );
+            String name = null;
+            if( nameField != null )
+            {
+                name = nameField.value().get();
+            }
+            Reference base = parameters.request().get().getResourceRef();
+
+            //noinspection unchecked
+            Class<T> entityType = parameters.entityType().get();
+
+            Identity identity = identityManager.generate(entityType, name);
+            locator.find( entityType ).create( identity );
+            return resourceBuilder.createRestLink( identity, base, Method.GET );
+        }
+
+        @SuppressWarnings( "unchecked" )
+        private List<EntityRef> getEntityRefs( Reference base )
+        {
+            ArrayList result = new ArrayList<>();
+            Property<Class<T>> property = parameters.entityType();
+            Class<T> entityType = property.get();
+            CrudRepository<T> repository = locator.find( entityType );
+            Iterable<T> all = repository.findAll();
+            Stream<T> stream = StreamSupport.stream( all.spliterator(), false );
+            stream
+                .map( entity -> entity.identity().get() )
+                .map( identity -> resourceBuilder.createEntityRef( identity, base ) )
+                .forEach( result::add );
+            return result;
+        }
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/EntityRef.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/EntityRef.java
new file mode 100644
index 0000000..d077a17
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/EntityRef.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.restlet.crud;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.restlet.RestLink;
+
+public interface EntityRef
+{
+    Property<String> name();
+
+    Property<RestLink> get();
+
+    Property<RestLink> put();
+
+    Property<RestLink> delete();
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/EntityResource.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/EntityResource.java
new file mode 100644
index 0000000..d7ab52c
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/EntityResource.java
@@ -0,0 +1,228 @@
+/*
+ *  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.polygene.library.restlet.crud;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAccessor;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.library.restlet.FormField;
+import org.apache.polygene.library.restlet.RestForm;
+import org.apache.polygene.library.restlet.RestLink;
+import org.apache.polygene.library.restlet.repository.RepositoryLocator;
+import org.apache.polygene.library.restlet.resource.ResourceBuilder;
+import org.apache.polygene.library.restlet.resource.ServerResource;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.restlet.data.Reference;
+
+@Mixins( EntityResource.Mixin.class )
+public interface EntityResource<T extends HasIdentity> extends ServerResource<T>
+{
+    interface EntityParam
+    {
+        @Optional
+        Property<String> invoke();
+    }
+
+    abstract class Mixin<T extends HasIdentity>
+        implements EntityResource<T>
+    {
+
+        @Structure
+        private PolygeneSPI spi;
+
+        @Structure
+        private ValueBuilderFactory vbf;
+
+        @This
+        private HasIdentity me;
+
+        @This
+        private Parameters<T> parameters;
+
+        @This
+        private EntityParam entityParam;
+
+        @Service
+        private RepositoryLocator locator;
+
+        @Service
+        private ResourceBuilder resourceBuilder;
+
+        @Override
+        public T get()
+        {
+            Class entityType = parameters.entityType().get();
+            //noinspection unchecked
+            return (T) locator.find( entityType ).get( identity() );
+        }
+
+        @Override
+        public void put( T value )
+        {
+            Class<T> entityType = parameters.entityType().get();
+            locator.find( entityType ).update( value );
+        }
+
+        @Override
+        public void delete()
+        {
+            Class entityType = parameters.entityType().get();
+            String idOfEntity = parameters.id().get();
+            locator.find( entityType ).delete( new StringIdentity( idOfEntity ) );
+        }
+
+        @Override
+        public RestLink post( RestForm form )
+        {
+            Class<T> type = parameters.entityType().get();
+            String methodName = entityParam.invoke().get();
+            try
+            {
+                Method method = findMethod( type, methodName );
+                if( method == null ) // no arg method doesn't exist, look for single arg method
+                {
+                    throw new IllegalArgumentException( "Method '" + methodName + "' is not present on " + type.getName() );
+                }
+                Class entityType = parameters.entityType().get();
+                //noinspection unchecked
+                T entity = (T) locator.find( entityType ).get( identity() );
+                if( method.getParameterCount() == 1 )
+                {
+                    Class argType = method.getParameterTypes()[ 0 ];
+                    Object parameters = createParametersComposite( form, argType );
+                    method.invoke( entity, parameters );
+                }
+                else
+                {
+                    method.invoke( entity );
+                }
+            }
+            catch( Exception e )
+            {
+                String message = e.getMessage();
+                while( e instanceof InvocationTargetException )
+                {
+                    e = (Exception) ( (InvocationTargetException) e ).getTargetException();
+                    message = e.getMessage();
+                }
+                throw new RuntimeException( message, e );
+            }
+            Reference base = parameters.request().get().getResourceRef();
+            return resourceBuilder.createRestLink( new StringIdentity( "" ), base, org.restlet.data.Method.GET );
+        }
+
+        private Object createParametersComposite( RestForm form, Class argType )
+        {
+            ValueBuilder<?> vb = vbf.newValueBuilderWithState(
+                argType,
+                descriptor -> {
+                    FormField field = form.field( descriptor.qualifiedName().name() );
+                    if( field == null )
+                    {
+                        return null;
+                    }
+                    Class<?> propertyType = descriptor.valueType().primaryType();
+                    Property<String> value = field.value();
+                    if( value == null )
+                    {
+                        return null;
+                    }
+                    return convertPropertyValue( value.get(), propertyType );
+                },
+                descriptor -> null,
+                descriptor -> null,
+                descriptor -> null
+            );
+            return vb.newInstance();
+        }
+
+        private Method findMethod( Class<T> type, String methodName )
+        {
+            Method[] methods = type.getMethods();
+            Method method = null;
+            for( Method m : methods )
+            {
+                if( m.getName().equals( methodName ) )
+                {
+                    method = m;
+                    break;
+                }
+            }
+            return method;
+        }
+
+        private Object convertPropertyValue( String input, Class<?> propertyType )
+        {
+            if( propertyType.equals( String.class ) )
+            {
+                return input;
+            }
+            if( Integer.class.isAssignableFrom( propertyType ) )
+            {
+                return Integer.parseInt( input );
+            }
+            if( Boolean.class.isAssignableFrom( propertyType ) )
+            {
+                return Boolean.valueOf( input );
+            }
+            if( Double.class.isAssignableFrom( propertyType ) )
+            {
+                return Double.parseDouble( input );
+            }
+            if( Long.class.isAssignableFrom( propertyType ) )
+            {
+                return Long.parseLong( input );
+            }
+            if( Byte.class.isAssignableFrom( propertyType ) )
+            {
+                return Byte.parseByte( input );
+            }
+            if( Short.class.isAssignableFrom( propertyType ) )
+            {
+                return Short.parseShort( input );
+            }
+            if( Float.class.isAssignableFrom( propertyType ) )
+            {
+                return Float.parseFloat( input );
+            }
+            if( Character.class.isAssignableFrom( propertyType ) )
+            {
+                return input.charAt( 0 );
+            }
+            if( TemporalAccessor.class.isAssignableFrom( propertyType ) )
+            {
+                return DateTimeFormatter.ISO_DATE_TIME.parse( input );
+            }
+            return null;
+        }
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/HasIdentitySpecification.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/HasIdentitySpecification.java
new file mode 100644
index 0000000..ce359ca
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/HasIdentitySpecification.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.restlet.crud;
+
+import java.util.Objects;
+import java.util.function.Predicate;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+
+public class HasIdentitySpecification
+    implements Predicate<HasIdentity>
+{
+    private final Identity id;
+
+    public HasIdentitySpecification(Identity identity )
+    {
+        Objects.requireNonNull( identity, "reference" );
+        this.id = identity;
+    }
+
+    @Override
+    public boolean test( HasIdentity item )
+    {
+        return id.equals( item.identity().get() );
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/RepositoryNotFoundException.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/RepositoryNotFoundException.java
new file mode 100644
index 0000000..b330aa1
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/crud/RepositoryNotFoundException.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.restlet.crud;
+
+public class RepositoryNotFoundException extends RuntimeException
+{
+    public RepositoryNotFoundException( Class entityType )
+    {
+        super( "No repository found for " + entityType.getName() );
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/filters/NameFilter.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/filters/NameFilter.java
new file mode 100644
index 0000000..d23a3aa
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/filters/NameFilter.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.restlet.filters;
+
+import java.util.function.Predicate;
+import org.apache.polygene.library.restlet.HasName;
+
+public class NameFilter implements Predicate<HasName>
+{
+    private final String name;
+
+    public NameFilter( String name )
+    {
+        this.name = name;
+    }
+
+    @Override
+    public boolean test( HasName hasName )
+    {
+        return hasName.name().get().equals(name);
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/identity/CanonicalName.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/identity/CanonicalName.java
new file mode 100644
index 0000000..3e8ee8b
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/identity/CanonicalName.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.library.restlet.identity;
+
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+
+@Mixins( CanonicalName.Mixin.class )
+public interface CanonicalName
+{
+    String name();
+
+    Class type();
+
+    class Mixin
+        implements CanonicalName
+    {
+        @This
+        private HasIdentity me;
+
+        @Service
+        private IdentityManager manager;
+
+        @Override
+        public String name()
+        {
+            return manager.extractName( me.identity().get() );
+        }
+
+        @Override
+        public Class type()
+        {
+            return manager.extractType( me.identity().get() );
+        }
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/identity/IdentityManager.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/identity/IdentityManager.java
new file mode 100644
index 0000000..b4ebde6
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/identity/IdentityManager.java
@@ -0,0 +1,156 @@
+/*
+ *  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.polygene.library.restlet.identity;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Predicate;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.IdentityGenerator;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkConcern;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation;
+
+@Mixins( IdentityManager.Mixin.class )
+@Concerns( { UnitOfWorkConcern.class } )
+public interface IdentityManager
+{
+    String SEPARATOR = "~";
+    String IDENTITY_SIGNATURE = "[0-9][0-9]*~.*";
+
+    boolean isIdentity( String candidate );
+
+    Identity generate( Class type, @Optional String canonicalName );
+
+    String extractName( Identity identity );
+
+    Class extractType( Identity identity );
+
+    @UnitOfWorkPropagation
+    String findPrefix( Class type );
+
+    class Mixin
+        implements IdentityManager
+    {
+        @Service
+        private IdentityGenerator uuidService;
+
+        @This
+        private Configuration<IdentityMappingConfiguration> config;
+
+        private ConcurrentHashMap<String, Class> actualClasses = new ConcurrentHashMap<>();
+
+        @Override
+        public boolean isIdentity( String candidate )
+        {
+            return candidate.matches( IDENTITY_SIGNATURE );
+        }
+
+        @Override
+        public Identity generate( Class type, String canonicalName )
+        {
+            if( canonicalName == null )
+            {
+                canonicalName = uuidService.generate( type ).toString();
+            }
+            if( isIdentity( canonicalName ) )
+            {
+                // This is already an ID, and we simply return it.
+                return new StringIdentity( canonicalName );
+            }
+            String prefix = findPrefix( type );
+            return new StringIdentity( prefix + SEPARATOR + canonicalName );
+        }
+
+        @Override
+        public String findPrefix( Class type )
+        {
+            Map<String, String> mapping = config.get().mapping().get();
+            String prefix = mapping.get( type.getName() );
+            if( prefix == null )
+            {
+                config.refresh();
+                mapping = config.get().mapping().get();
+                prefix = Integer.toString( mapping.size() + 1 );
+                mapping.put( type.getName(), prefix );
+                config.get().mapping().set( mapping );
+                config.save();
+            }
+            actualClasses.put( type.getName(), type );
+            return prefix;
+        }
+
+        @Override
+        public String extractName( Identity identity )
+        {
+            String idString = identity.toString();
+            int pos = idString.indexOf( SEPARATOR );
+            if( pos < 1 )
+            {
+                throw new InvalidIdentityFormatException( idString );
+            }
+            return idString.substring( pos + 1 );
+        }
+
+        @Override
+        public Class extractType( Identity identity )
+        {
+            String idString = identity.toString();
+            if( !isIdentity( idString ) )
+            {
+                throw new IllegalArgumentException( "Given argument '" + idString + "' is not an Identity" );
+            }
+            int pos = idString.indexOf( SEPARATOR );
+            if( pos < 1 )
+            {
+                throw new InvalidIdentityFormatException( idString );
+            }
+            String prefix = idString.substring( 0, pos );
+            Map.Entry<String, String> found = config.get().mapping().get().entrySet().stream()
+                                                    .filter( new FindClassSpecification( prefix ) )
+                                                    .findFirst().orElse( null );
+            return found == null ? null : actualClasses.get( found.getKey() );
+        }
+
+        private static class FindClassSpecification
+            implements Predicate<Map.Entry<String, String>>
+        {
+            private String prefix;
+
+            private FindClassSpecification( String prefix )
+            {
+                this.prefix = prefix;
+            }
+
+            @Override
+            public boolean test( Map.Entry<String, String> item )
+            {
+                return item.getValue().equals( prefix );
+            }
+        }
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/identity/IdentityMappingConfiguration.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/identity/IdentityMappingConfiguration.java
new file mode 100644
index 0000000..e30d0ed
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/identity/IdentityMappingConfiguration.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.restlet.identity;
+
+import java.util.Map;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+public interface IdentityMappingConfiguration
+{
+    @Optional
+    @UseDefaults
+    Property<Map<String, String>> mapping();
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/identity/InvalidIdentityFormatException.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/identity/InvalidIdentityFormatException.java
new file mode 100644
index 0000000..7514304
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/identity/InvalidIdentityFormatException.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.restlet.identity;
+
+public class InvalidIdentityFormatException extends RuntimeException
+{
+    public InvalidIdentityFormatException( String identity )
+    {
+        super( "The given reference wasn't generated by the UrlIdentityManager: " + identity );
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/metainfo/UserIdentity.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/metainfo/UserIdentity.java
new file mode 100644
index 0000000..58bcdbc
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/metainfo/UserIdentity.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.library.restlet.metainfo;
+
+public class UserIdentity
+{
+    private final String identifier;
+    private final String name;
+    private final String email;
+    private final String firstName;
+    private final String lastName;
+
+    public UserIdentity( String identifier, String name, String email, String firstName, String lastName )
+    {
+        this.identifier = identifier;
+        this.name = name;
+        this.email = email;
+        this.firstName = firstName;
+        this.lastName = lastName;
+    }
+
+    public String identifier()
+    {
+        return identifier;
+    }
+
+    public String name()
+    {
+        return name;
+    }
+
+    public String email()
+    {
+        return email;
+    }
+
+    public String firstName()
+    {
+        return firstName;
+    }
+
+    public String lastName()
+    {
+        return lastName;
+    }
+
+
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/CrudRepository.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/CrudRepository.java
new file mode 100644
index 0000000..0fe23b5
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/CrudRepository.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.library.restlet.repository;
+
+import java.util.function.Predicate;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation;
+
+public interface CrudRepository<T extends HasIdentity>
+{
+    @UnitOfWorkPropagation
+    void create( @EntityName Identity identityOfEntity );
+
+    @UnitOfWorkPropagation
+    T get( @EntityName Identity identityOfEntity );
+
+    @UnitOfWorkPropagation
+    void update( T newStateAsValue );
+
+    @UnitOfWorkPropagation
+    void delete( @EntityName Identity identityOfEntity );
+
+    @UnitOfWorkPropagation
+    Iterable<T> findAll();
+
+    @UnitOfWorkPropagation
+    Iterable<T> find( Predicate<Composite> specification );
+
+    T toValue( T entity );
+
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/EntityName.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/EntityName.java
new file mode 100644
index 0000000..64dd5db
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/EntityName.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.library.restlet.repository;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.library.restlet.identity.IdentityManager;
+
+@ConstraintDeclaration
+@Retention( RetentionPolicy.RUNTIME )
+@Constraints( EntityName.Constraint.class )
+public @interface EntityName
+{
+
+    class Constraint
+        implements org.apache.polygene.api.constraint.Constraint<EntityName, String>
+    {
+
+        @Override
+        public boolean isValid( EntityName annotation, String value )
+        {
+            int pos = value.indexOf( IdentityManager.SEPARATOR );
+            if( pos > 0 )
+            {
+                value = value.substring( pos+1 );
+            }
+            for( int i = 0; i < value.length(); i++ )
+            {
+                char ch = value.charAt( i );
+                if( ( ch < 'A' || ch > 'Z' ) &&
+                    ( ch < 'a' || ch > 'z' ) &&
+                    ( ch < '0' || ch > '9' ) &&
+                    ( ch != '.' ) &&
+                    ( ch != '_' ) &&
+                    ( ch != '-' )
+                    )
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/EntityTypeDescriptor.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/EntityTypeDescriptor.java
new file mode 100644
index 0000000..2779b56
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/EntityTypeDescriptor.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.library.restlet.repository;
+
+public class EntityTypeDescriptor
+{
+    private Class entityType;
+
+    public EntityTypeDescriptor( Class entityType )
+    {
+        this.entityType = entityType;
+    }
+
+    public Class entityType()
+    {
+        return entityType;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "EntityTypeDescriptor{" + entityType + '}';
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/MissingRepositoryException.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/MissingRepositoryException.java
new file mode 100644
index 0000000..3836ec0
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/MissingRepositoryException.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.restlet.repository;
+
+public class MissingRepositoryException extends RuntimeException
+{
+    public MissingRepositoryException( Class typeName )
+    {
+        super( "There is no Entity Repository @Tagged with the name '" + typeName + "'" );
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/RepositoryLocator.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/RepositoryLocator.java
new file mode 100644
index 0000000..452ca4e
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/RepositoryLocator.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.library.restlet.repository;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceReference;
+
+@Mixins( RepositoryLocator.Mixin.class )
+public interface RepositoryLocator
+{
+    <T extends HasIdentity> CrudRepository<T> find(Class<T> entityType );
+
+    class Mixin
+        implements RepositoryLocator
+    {
+
+        private Map<Class, CrudRepository> repositories = new HashMap<>();
+
+        public Mixin( @Service Iterable<ServiceReference<CrudRepository>> repositories )
+        {
+            StreamSupport.stream( repositories.spliterator(), true ).forEach( ref -> {
+                Class type = ref.metaInfo( EntityTypeDescriptor.class ).entityType();
+                this.repositories.put( type, ref.get() );
+            } );
+        }
+
+        @Override
+        public <T extends HasIdentity> CrudRepository<T> find(Class<T> entityType )
+        {
+            //noinspection unchecked
+            return repositories.get( entityType );
+        }
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/SmallCrudRepositoryMixin.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/SmallCrudRepositoryMixin.java
new file mode 100644
index 0000000..a5b921c
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/repository/SmallCrudRepositoryMixin.java
@@ -0,0 +1,122 @@
+/*
+ *  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.polygene.library.restlet.repository;
+
+import java.util.function.Predicate;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.library.restlet.identity.IdentityManager;
+
+public class SmallCrudRepositoryMixin<T extends HasIdentity>
+    implements CrudRepository<T>
+{
+    @Structure
+    private UnitOfWorkFactory uowf;
+
+    @Structure
+    private QueryBuilderFactory qbf;
+
+    @Service
+    private IdentityManager identityManager;
+
+    private final Class<T> entityType;
+
+    @SuppressWarnings( "unchecked" )
+    public SmallCrudRepositoryMixin( @Structure PolygeneAPI api, @This ServiceComposite me )
+    {
+        entityType = api.serviceDescriptorFor( me ).metaInfo( EntityTypeDescriptor.class ).entityType();
+    }
+
+    @Override
+    public void create( Identity identity )
+    {
+        UnitOfWork uow = uowf.currentUnitOfWork();
+        uow.newEntity( entityType, identity );
+    }
+
+    @Override
+    public T get( Identity identity )
+    {
+        UnitOfWork uow = uowf.currentUnitOfWork();
+        return uow.get( entityType, identity );
+    }
+
+    @Override
+    public void update( T newStateAsValue )
+    {
+        UnitOfWork uow = uowf.currentUnitOfWork();
+
+        @SuppressWarnings( "unchecked" )
+        Class<HasIdentity> type = (Class<HasIdentity>) entityType;
+
+        uow.toEntity( type, newStateAsValue );  //updates the identified entity with the value
+    }
+
+    @Override
+    public void delete( Identity identity )
+    {
+        UnitOfWork uow = uowf.currentUnitOfWork();
+        try
+        {
+            T entity = uow.get( entityType, identity );
+            uow.remove( entity );
+        }
+        catch( NoSuchEntityException | NoSuchEntityTypeException e )
+        {
+            throw new IllegalArgumentException( "Entity  '" + identity + "' doesn't exist." );
+        }
+    }
+
+    @Override
+    public Iterable<T> findAll()
+    {
+        return find( item -> true );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public Iterable<T> find( Predicate<Composite> specification )
+    {
+        UnitOfWork uow = uowf.currentUnitOfWork();
+        QueryBuilder<T> qb = qbf.newQueryBuilder( entityType );
+        Query<T> query = uow.newQuery( qb );
+        return qbf.newQueryBuilder( entityType ).where( specification ).newQuery( query );
+    }
+
+    @Override
+    public T toValue( T entity )
+    {
+        return uowf.currentUnitOfWork().toValue( entityType, entity );
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/CreationParameterized.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/CreationParameterized.java
new file mode 100644
index 0000000..c79c62b
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/CreationParameterized.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.restlet.resource;
+
+public interface CreationParameterized<T>
+{
+    /**
+     * Returns the ValueComposite type to be used to parameterize the reosource.
+     *
+     * @return A type to instantiate as a ValueComposite
+     */
+    Class<T> parametersType();
+
+    void parameterize( T parameters );
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/CreationResource.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/CreationResource.java
new file mode 100644
index 0000000..fe86473
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/CreationResource.java
@@ -0,0 +1,118 @@
+/*
+ *  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.polygene.library.restlet.resource;
+
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.library.restlet.FormField;
+import org.apache.polygene.library.restlet.RestForm;
+import org.apache.polygene.library.restlet.RestLink;
+import org.apache.polygene.library.restlet.identity.IdentityManager;
+import org.apache.polygene.library.restlet.repository.RepositoryLocator;
+import org.restlet.data.Method;
+
+@Mixins( CreationResource.Mixin.class )
+public interface CreationResource<T extends HasIdentity> extends ServerResource<T>
+{
+    abstract class Mixin<T extends HasIdentity>
+        implements CreationResource<T>
+    {
+        @Structure
+        private ValueBuilderFactory vbf;
+
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @This
+        private Parameters<T> parameters;
+
+        @Service
+        private ResourceBuilder resourceBuilder;
+
+        @Service
+        private IdentityManager identityManager;
+
+        @Service
+        private RepositoryLocator locator;
+
+        @Override
+        public RestLink post( RestForm form )
+        {
+            String name = form.field( "name" ).value().get();
+            Class entityType = parameters.entityType().get();
+            Identity identity = identityManager.generate( entityType, name );
+            locator.find( entityType ).create( identity );
+            doParameterization( form, entityType, identity );
+            return resourceBuilder.createRestLink( identity, parameters.request().get().getResourceRef(), Method.GET );
+        }
+
+        private <P> void doParameterization( RestForm form, Class entityType, Identity identity )
+        {
+            if( !CreationParameterized.class.isAssignableFrom( entityType ) )
+            {
+                return;
+            }
+            //noinspection unchecked
+            CreationParameterized<P> created = (CreationParameterized<P>) locator.find( entityType ).get( identity );
+            P parameterization = createParameterizationValue( form, created );
+            created.parameterize( parameterization );
+        }
+
+        private <V> V createParameterizationValue( final RestForm form, CreationParameterized<V> created )
+        {
+            Class<V> valueType = created.parametersType();
+            ValueBuilder<V> vb = vbf.newValueBuilderWithState(
+                valueType,
+                propertyName -> mapField( form, propertyName ),
+                association -> null,
+                association -> null,
+                association -> null
+            );
+            return vb.newInstance();
+        }
+
+        private Object mapField( RestForm form, PropertyDescriptor propertyName )
+        {
+            String name = propertyName.qualifiedName().name();
+            FormField field = form.field( name );
+            if( field == null )
+            {
+                UnitOfWork uow = uowf.currentUnitOfWork();
+                String usecase = "";
+                if( uow != null )
+                {
+                    usecase = uow.usecase().name();
+                }
+                throw new IllegalArgumentException( "Field named '" + name + "' is required and not present in usecase " + usecase );
+            }
+            return field.value().get();
+        }
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/DefaultResourceFactoryImpl.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/DefaultResourceFactoryImpl.java
new file mode 100644
index 0000000..d1508d3
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/DefaultResourceFactoryImpl.java
@@ -0,0 +1,101 @@
+/*
+ *  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.polygene.library.restlet.resource;
+
+import java.util.Map;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.restlet.Context;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.routing.Router;
+
+public class DefaultResourceFactoryImpl<K extends HasIdentity, T extends ServerResource<K>>
+    implements ResourceFactory<K, T>
+{
+    @Uses
+    private Class<T> resourceType;
+
+    @Uses
+    private Context context;
+
+    @Uses
+    private Router router;
+
+    @Uses
+    private Request request;
+
+    @Structure
+    private ValueBuilderFactory vbf;
+
+    @Structure
+    private PolygeneSPI spi;
+
+    @Override
+    public T create( Class<T> entityType, Request request, Response response, Context context )
+    {
+        final Map<String, Object> attributes = request.getAttributes();
+        String id = (String) attributes.get( "id" );
+
+        ValueBuilder<T> builder = vbf.newValueBuilderWithState(
+            resourceType,
+            descriptor -> findValue( attributes, descriptor ),
+            descriptor -> null,
+            descriptor -> null,
+            descriptor -> null
+        );
+        //noinspection unchecked
+        ServerResource.Parameters<T> params = builder.prototypeFor( ServerResource.Parameters.class );
+        params.id().set( id );
+        params.entityType().set( entityType );
+        params.context().set( this.context );
+        params.request().set( request );
+        params.router().set( router );
+        params.response().set( response );
+        return builder.newInstance();
+    }
+
+    private Object findValue( Map<String, Object> attributes, PropertyDescriptor descriptor )
+    {
+        String name = descriptor.qualifiedName().name();
+        if( name.equals( "reference" ) )
+        {
+            Object id = attributes.get( "id" );
+            if( id == null )
+            {
+                throw new IllegalArgumentException( resourceType.getName() + " implements Identity and must have an {id} attribute in the path template." );
+            }
+            return id;
+        }
+        return attributes.get( name );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "factory[" + ( resourceType == null ? "<null>" : resourceType.getSimpleName()) + "]";
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/EntryPoint.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/EntryPoint.java
new file mode 100644
index 0000000..3a74b63
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/EntryPoint.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.restlet.resource;
+
+import java.util.Map;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.restlet.RestLink;
+
+public interface EntryPoint extends HasIdentity
+{
+    Property<Map<String,RestLink>> api();
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/EntryPointResource.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/EntryPointResource.java
new file mode 100644
index 0000000..053184b
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/EntryPointResource.java
@@ -0,0 +1,99 @@
+/*
+ *  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.polygene.library.restlet.resource;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.library.restlet.RestLink;
+import org.restlet.data.Method;
+import org.restlet.data.Reference;
+import org.restlet.routing.Route;
+import org.restlet.routing.Template;
+import org.restlet.routing.TemplateRoute;
+
+@Mixins( EntryPointResource.Mixin.class )
+public interface EntryPointResource extends ServerResource<EntryPoint>
+{
+    abstract class Mixin
+        implements EntryPointResource
+    {
+        @This
+        private Parameters<EntryPoint> parameters;
+
+        @Service
+        private ResourceBuilder resourceBuilder;
+
+        @Structure
+        private ValueBuilderFactory vbf;
+
+        private EntryPoint entryPoint;
+
+        @Override
+        public EntryPoint get()
+        {
+            if( entryPoint == null )
+            {
+                entryPoint = createEntryPoint();
+            }
+            return entryPoint;
+        }
+
+        private EntryPoint createEntryPoint()
+        {
+            Map<String, RestLink> entryPoints = new HashMap<>();
+            for( Route r : parameters.router().get().getRoutes() )
+            {
+                if( r instanceof TemplateRoute)
+                {
+                    TemplateRoute route = (TemplateRoute) r;
+                    Template template = route.getTemplate();
+                    // Only include patterns that doesn't have variables, and has a proper name.
+                    if( template.getVariableNames().isEmpty() && route.getName().indexOf( '>' ) == -1 )
+                    {
+                        Reference hostRef = parameters.request().get().getOriginalRef();
+//                        Reference reference = new Reference( hostRef, template.getPattern() );
+                        RestLink link;
+                        if( route.getDescription() == null )
+                        {
+                            link = resourceBuilder.createRestLink( new StringIdentity( template.getPattern() ), hostRef, Method.GET );
+                        }
+                        else
+                        {
+                            link = resourceBuilder.createRestLink( new StringIdentity( template.getPattern() ), hostRef, Method.GET, route.getDescription() );
+                        }
+                        entryPoints.put( route.getName(), link );
+                    }
+                }
+            }
+            ValueBuilder<EntryPoint> builder = vbf.newValueBuilder( EntryPoint.class );
+            builder.prototype().identity().set( new StringIdentity( "/" ) );
+            builder.prototype().api().set( entryPoints );
+            return builder.newInstance();
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/NotPresentException.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/NotPresentException.java
new file mode 100644
index 0000000..627e346
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/NotPresentException.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.library.restlet.resource;
+
+public class NotPresentException extends RuntimeException
+{
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/Parameterizer.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/Parameterizer.java
new file mode 100644
index 0000000..a10ba88
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/Parameterizer.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.library.restlet.resource;
+
+public interface Parameterizer
+{
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/ResourceBuilder.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/ResourceBuilder.java
new file mode 100644
index 0000000..bdf1942
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/ResourceBuilder.java
@@ -0,0 +1,178 @@
+/*
+ *  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.polygene.library.restlet.resource;
+
+import java.io.IOException;
+import java.util.Collections;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.library.restlet.Command;
+import org.apache.polygene.library.restlet.FormField;
+import org.apache.polygene.library.restlet.RestForm;
+import org.apache.polygene.library.restlet.RestLink;
+import org.apache.polygene.library.restlet.crud.EntityRef;
+import org.apache.polygene.library.restlet.identity.IdentityManager;
+import org.apache.polygene.library.restlet.serialization.PolygeneConverter;
+import org.restlet.data.Method;
+import org.restlet.data.Reference;
+import org.restlet.representation.Representation;
+import org.restlet.representation.Variant;
+import org.restlet.routing.Route;
+import org.restlet.routing.Router;
+
+@Mixins( ResourceBuilder.Mixin.class )
+public interface ResourceBuilder
+{
+    EntityRef createEntityRef(Identity name, Reference base );
+
+    EntityRef createEntityRef( Identity name, RestLink get, RestLink put, RestLink delete );
+
+    RestLink createRestLink( Identity name, Reference base, Method method );
+
+    RestLink createRestLink( Identity name, Reference base, Method method, String description );
+
+    Command createCommand( Reference base );
+
+    RestForm createNameForm( Reference base );
+
+    FormField createFormField( String name, String type );
+
+    <T extends HasIdentity> Representation toRepresentation(Class<T> type, T composite );
+
+    <T extends HasIdentity> T toObject(Class<T> type, Representation representation )
+        throws IOException;
+
+    Route findRoute( String name, Router router );
+
+    class Mixin
+        implements ResourceBuilder
+    {
+        @Service
+        private IdentityManager identityManager;
+
+        private final PolygeneConverter converter;
+
+        @Structure
+        private ValueBuilderFactory vbf;
+
+        public Mixin( @Structure ObjectFactory objectFactory )
+        {
+            converter = new PolygeneConverter( objectFactory );
+        }
+
+        @Override
+        public EntityRef createEntityRef( Identity identity, Reference base )
+        {
+            RestLink get = createRestLink( identity, base, Method.GET );
+            RestLink put = createRestLink( identity, base, Method.PUT );
+            RestLink delete = createRestLink( identity, base, Method.DELETE );
+            return createEntityRef( identity, get, put, delete );
+        }
+
+        @Override
+        public EntityRef createEntityRef( Identity identity, RestLink get, RestLink put, RestLink delete )
+        {
+            ValueBuilder<EntityRef> refBuilder = vbf.newValueBuilder( EntityRef.class );
+            EntityRef refPrototype = refBuilder.prototype();
+            refPrototype.name().set( identityManager.extractName( identity ) );
+            refPrototype.get().set( get );
+            refPrototype.put().set( put );
+            refPrototype.delete().set( delete );
+            return refBuilder.newInstance();
+        }
+
+        @Override
+        public RestLink createRestLink( Identity identity, Reference base, Method method )
+        {
+            String name = identityManager.extractName( identity );
+
+            ValueBuilder<RestLink> builder = vbf.newValueBuilder( RestLink.class );
+            RestLink prototype = builder.prototype();
+            String path = base.toUri().resolve( name ).getPath();
+            prototype.path().set( path.endsWith( "/" ) ? path : path + "/" );
+            prototype.method().set( method.getName() );
+            return builder.newInstance();
+        }
+
+        @Override
+        public RestLink createRestLink( Identity identity, Reference base, Method method, String description )
+        {
+            String name = identityManager.extractName( identity );
+            ValueBuilder<RestLink> builder = vbf.newValueBuilder( RestLink.class );
+            RestLink prototype = builder.prototype();
+            prototype.path().set( base.toUri().resolve( name ).getPath() + "/" );
+            prototype.method().set( method.getName() );
+            prototype.description().set( description );
+            return builder.newInstance();
+        }
+
+        public Command createCommand( Reference base )
+        {
+            RestForm form = createNameForm( base );
+            ValueBuilder<Command> builder = vbf.newValueBuilder( Command.class );
+            builder.prototype().name().set( "create" );
+            builder.prototype().form().set( form );
+            return builder.newInstance();
+        }
+
+        public RestForm createNameForm( Reference base )
+        {
+            ValueBuilder<RestForm> builder = vbf.newValueBuilder( RestForm.class );
+            builder.prototype().link().set( createRestLink( new StringIdentity( "form" ), base, Method.POST ) );
+            builder.prototype().fields().set( Collections.singletonList( createFormField( "name", FormField.TEXT ) ) );
+            return builder.newInstance();
+        }
+
+        public FormField createFormField( String name, String type )
+        {
+            ValueBuilder<FormField> builder = vbf.newValueBuilder( FormField.class );
+            builder.prototype().name().set( name );
+            builder.prototype().type().set( type );
+            return builder.newInstance();
+        }
+
+        @Override
+        public <T extends HasIdentity> Representation toRepresentation(Class<T> type, T composite )
+        {
+            return converter.toRepresentation( composite, new Variant(), null );
+        }
+
+        @Override
+        public <T extends HasIdentity> T toObject(Class<T> type, Representation representation )
+            throws IOException
+        {
+            return converter.toObject( representation, type, null );
+        }
+
+        @Override
+        public Route findRoute( String name, Router router )
+        {
+            return router.getRoutes().stream().filter( route -> name.equals( route.getName() ) ).findFirst().orElse( null );
+        }
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/ResourceFactory.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/ResourceFactory.java
new file mode 100644
index 0000000..22c2d24
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/ResourceFactory.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.restlet.resource;
+
+import org.apache.polygene.api.identity.HasIdentity;
+import org.restlet.Context;
+import org.restlet.Request;
+import org.restlet.Response;
+
+public interface ResourceFactory<K extends HasIdentity, T extends ServerResource<K>>
+{
+    T create( Class<T> resourceType, Request request, Response response, Context context );
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/ServerResource.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/ServerResource.java
new file mode 100644
index 0000000..14d0697
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/resource/ServerResource.java
@@ -0,0 +1,109 @@
+/*
+ *  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.polygene.library.restlet.resource;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identifiable;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.restlet.RestForm;
+import org.apache.polygene.library.restlet.RestLink;
+import org.apache.polygene.library.restlet.identity.IdentityManager;
+import org.restlet.Context;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.routing.Router;
+
+@Mixins( { ServerResource.NotPresent.class, ServerResource.IdentityMixin.class } )
+public interface ServerResource<T extends HasIdentity> extends Identifiable
+{
+    T get();
+
+    void put( T value );
+
+    void delete();
+
+    RestLink post( RestForm form );
+
+    interface Parameters<T>
+    {
+        @Optional
+        Property<String> id();
+
+        Property<Class<T>> entityType();
+
+        Property<Request> request();
+
+        Property<Response> response();
+
+        Property<Context> context();
+
+        Property<Router> router();
+    }
+
+    abstract class IdentityMixin<T extends HasIdentity>
+        implements ServerResource<T>
+    {
+        @This
+        private Parameters<T> parameters;
+
+        @Service
+        private IdentityManager identityManager;
+
+        @Override
+        public Identity identity()
+        {
+            return identityManager.generate( parameters.entityType().get(), parameters.id().get() );
+        }
+    }
+
+    abstract class NotPresent
+        implements ServerResource
+    {
+        @Override
+        public HasIdentity get()
+        {
+            throw new NotPresentException();
+        }
+
+        @Override
+        public void put( HasIdentity value )
+        {
+            throw new NotPresentException();
+        }
+
+        @Override
+        public void delete()
+        {
+            throw new NotPresentException();
+        }
+
+        @Override
+        public RestLink post( RestForm form )
+        {
+            throw new NotPresentException();
+        }
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/serialization/FormRepresentation.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/serialization/FormRepresentation.java
new file mode 100644
index 0000000..fbb9a34
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/serialization/FormRepresentation.java
@@ -0,0 +1,150 @@
+/*
+ *  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.polygene.library.restlet.serialization;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.function.Function;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.restlet.data.Form;
+import org.restlet.data.MediaType;
+import org.restlet.representation.OutputRepresentation;
+import org.restlet.representation.Representation;
+
+/**
+ * Representation based of Polygene ValueComposites. It can serialize and deserialize
+ * automatically in JSON only.<br>
+ * <br>
+ */
+public class FormRepresentation<T> extends OutputRepresentation
+{
+    @Structure
+    private PolygeneSPI spi;
+
+    @Structure
+    private ValueBuilderFactory vbf;
+
+    /**
+     * The (parsed) object to format.
+     */
+    @Optional
+    private volatile T object;
+
+    /**
+     * The object class to instantiate.
+     */
+    @Optional
+    @Uses
+    private volatile Class<T> objectClass;
+
+    /**
+     * The representation to parse.
+     */
+    @Optional
+    @Uses
+    private volatile Representation representation;
+
+    public FormRepresentation()
+    {
+        super( MediaType.APPLICATION_WWW_FORM );
+    }
+
+    private T createObject()
+    {
+        //noinspection MismatchedQueryAndUpdateOfCollection
+        final Form form = new Form( representation );
+        ValueBuilder<T> builder = this.vbf.newValueBuilderWithState(
+            objectClass,
+            descriptor -> form.getFirstValue( descriptor.qualifiedName().name() ),
+            descriptor -> null,
+            descriptor -> null,
+            descriptor -> null
+        );
+        return builder.newInstance();
+    }
+
+    /**
+     * Returns the wrapped object, deserializing the representation with Polygene
+     * if necessary.
+     *
+     * @return The wrapped object.
+     *
+     * @throws IOException
+     */
+    public T getObject()
+        throws IOException
+    {
+        if( object == null )
+        {
+            object = createObject();
+        }
+        return object;
+    }
+
+    /**
+     * Returns the object class to instantiate.
+     *
+     * @return The object class to instantiate.
+     */
+    public Class<T> getObjectClass()
+    {
+        return objectClass;
+    }
+
+    @Override
+    public void write( OutputStream outputStream )
+        throws IOException
+    {
+        if( representation != null )
+        {
+            representation.write( outputStream );
+        }
+        else if( object != null )
+        {
+            AssociationStateHolder state = spi.stateOf( (ValueComposite) object );
+            ValueDescriptor descriptor = (ValueDescriptor) spi.modelDescriptorFor( object );
+            descriptor.state().properties().forEach( property -> {
+                String name = property.qualifiedName().name();
+                String value = state.propertyFor( property.accessor() ).get().toString();
+                try
+                {
+                    outputStream.write( name.getBytes( "UTF-8" ) );
+                    outputStream.write( "=".getBytes( "UTF-8" ) );
+                    outputStream.write( value.getBytes( "UTF-8" ) );
+                    outputStream.write( '\n' );
+                }
+                catch( IOException e )
+                {
+                    // TODO; not sure what could happen here.
+                }
+            } );
+        }
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/serialization/JsonRepresentation.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/serialization/JsonRepresentation.java
new file mode 100644
index 0000000..ea0929b
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/serialization/JsonRepresentation.java
@@ -0,0 +1,131 @@
+/*
+ *  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.polygene.library.restlet.serialization;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.restlet.data.MediaType;
+import org.restlet.representation.OutputRepresentation;
+import org.restlet.representation.Representation;
+
+/**
+ * Representation based of Polygene ValueComposites. It can serialize and deserialize
+ * automatically in JSON only.<br>
+ * <br>
+ */
+public class JsonRepresentation<T> extends OutputRepresentation
+{
+
+    @Structure
+    private PolygeneSPI spi;
+
+    @Service
+    private Serialization stateSerialization;
+
+    @Structure
+    private ModuleDescriptor module;
+
+    /**
+     * The (parsed) object to format.
+     */
+    @Optional
+    @Uses
+    private volatile T object;
+
+    /**
+     * The object class to instantiate.
+     */
+    @Optional
+    @Uses
+    private volatile Class<T> objectClass;
+
+    /**
+     * The representation to parse.
+     */
+    @Optional
+    @Uses
+    private volatile Representation representation;
+
+    public JsonRepresentation()
+    {
+        super( MediaType.APPLICATION_JSON );
+    }
+
+    /**
+     * Returns the wrapped object, deserializing the representation with Polygene
+     * if necessary.
+     *
+     * @return The wrapped object.
+     *
+     * @throws IOException
+     */
+    public T getObject()
+        throws IOException
+    {
+        T result = null;
+
+        if( this.object != null )
+        {
+            result = this.object;
+        }
+        else if( this.representation != null )
+        {
+            result = stateSerialization.deserialize( module, objectClass,
+                                                     new InputStreamReader( this.representation.getStream() ) );
+        }
+        return result;
+    }
+
+    /**
+     * Returns the object class to instantiate.
+     *
+     * @return The object class to instantiate.
+     */
+    public Class<T> getObjectClass()
+    {
+        return objectClass;
+    }
+
+    @Override
+    public void write( OutputStream outputStream )
+        throws IOException
+    {
+        if( representation != null )
+        {
+            representation.write( outputStream );
+        }
+        else if( object != null )
+        {
+            // TODO was WITHOUT TYPE INFO
+            stateSerialization.serialize( new OutputStreamWriter( outputStream ), object );
+            outputStream.write( '\n' );
+        }
+    }
+}
diff --git a/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/serialization/PolygeneConverter.java b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/serialization/PolygeneConverter.java
new file mode 100644
index 0000000..17739b6
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/polygene/library/restlet/serialization/PolygeneConverter.java
@@ -0,0 +1,268 @@
+/*
+ *  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.polygene.library.restlet.serialization;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.restlet.data.MediaType;
+import org.restlet.data.Preference;
+import org.restlet.engine.converter.ConverterHelper;
+import org.restlet.engine.resource.VariantInfo;
+import org.restlet.representation.Representation;
+import org.restlet.representation.Variant;
+import org.restlet.resource.Resource;
+
+/**
+ * Converter between Apache Polygene and JSON.
+ */
+public class PolygeneConverter extends ConverterHelper
+{
+    @Structure
+    private PolygeneSPI spi;
+
+    /**
+     * Variant with media type application/json.
+     */
+    private static final VariantInfo VARIANT_JSON = new VariantInfo( MediaType.APPLICATION_JSON );
+    private static final VariantInfo VARIANT_WWW_FORM_URLENCODED = new VariantInfo( MediaType.APPLICATION_WWW_FORM );
+
+    private final ObjectFactory objectFactory;
+
+    public PolygeneConverter( ObjectFactory objectFactory )
+    {
+        this.objectFactory = objectFactory;
+    }
+
+    /**
+     * Creates the marshaling {@link JsonRepresentation}.
+     *
+     * @param mediaType The target media type.
+     * @param source    The source object to marshal.
+     *
+     * @return The marshaling {@link JsonRepresentation}.
+     */
+    protected <T> Representation create( MediaType mediaType, T source )
+    {
+        //noinspection unchecked
+        return objectFactory.newObject( JsonRepresentation.class, source );
+    }
+
+    /**
+     * Creates the unmarshaling {@link JsonRepresentation}.
+     *
+     * @param source      The source representation to unmarshal.
+     * @param objectClass The object class to instantiate.
+     *
+     * @return The unmarshaling {@link JsonRepresentation}.
+     */
+    protected <T> Representation create( Representation source, Class<T> objectClass )
+    {
+        if( VARIANT_WWW_FORM_URLENCODED.isCompatible( source ) )
+        {
+            return objectFactory.newObject( FormRepresentation.class, source, objectClass );
+        }
+        else if( VARIANT_WWW_FORM_URLENCODED.isCompatible( source ) )
+        {
+            //noinspection unchecked
+            return objectFactory.newObject( JsonRepresentation.class, source, objectClass );
+        }
+        return null;
+    }
+
+    public ObjectFactory getObjectFactory()
+    {
+        return objectFactory;
+    }
+
+    @Override
+    public List<Class<?>> getObjectClasses( Variant source )
+    {
+        List<Class<?>> result = new ArrayList<>();
+
+        if( isCompatible( source ) )
+        {
+            result = addObjectClass( result, Object.class );
+            result = addObjectClass( result, JsonRepresentation.class );
+        }
+
+        return result;
+    }
+
+    @Override
+    public List<VariantInfo> getVariants( Class<?> source )
+    {
+        List<VariantInfo> result = new ArrayList<>();
+
+        if( source != null )
+        {
+            result = addVariant( result, VARIANT_JSON );
+            result = addVariant( result, VARIANT_WWW_FORM_URLENCODED );
+        }
+
+        return result;
+    }
+
+    /**
+     * Indicates if the given variant is compatible with the media types
+     * supported by this converter.
+     *
+     * @param variant The variant.
+     *
+     * @return True if the given variant is compatible with the media types
+     * supported by this converter.
+     */
+    protected boolean isCompatible( Variant variant )
+    {
+        //noinspection SimplifiableIfStatement
+        if( variant == null )
+        {
+            return false;
+        }
+
+        return VARIANT_JSON.isCompatible( variant ) ||
+               VARIANT_WWW_FORM_URLENCODED.isCompatible( variant )
+            ;
+    }
+
+    @Override
+    public float score( Object source, Variant target, Resource resource )
+    {
+        float result;
+
+        if( source instanceof JsonRepresentation<?> )
+        {
+            result = 1.0F;
+        }
+        else
+        {
+            if( target == null )
+            {
+                result = 0.5F;
+            }
+            else if( isCompatible( target ) )
+            {
+                result = 0.8F;
+            }
+            else
+            {
+                result = 0.5F;
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T> float score( Representation source, Class<T> target,
+                            Resource resource
+    )
+    {
+        float result = -1.0F;
+
+        if( source instanceof JsonRepresentation<?> )
+        {
+            result = 1.0F;
+        }
+        else if( ( target != null )
+                 && JsonRepresentation.class.isAssignableFrom( target ) )
+        {
+            result = 1.0F;
+        }
+        else if( isCompatible( source ) )
+        {
+            result = 0.8F;
+        }
+
+        return result;
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Override
+    public <T> T toObject( Representation source, Class<T> target, Resource resources )
+        throws IOException
+    {
+        Object result = null;
+
+        Representation representation = null;
+        if( isCompatible( source ) )
+        {
+            representation = create( source, target );
+        }
+
+        if( representation != null )
+        {
+            // Handle the conversion
+            if( ( target != null )
+                && JsonRepresentation.class.isAssignableFrom( target ) )
+            {
+                result = representation;
+            }
+            else
+            {
+                if( representation instanceof JsonRepresentation )
+                {
+                    result = ( (JsonRepresentation) representation ).getObject();
+                }
+                if( representation instanceof FormRepresentation )
+                {
+                    result = ( (FormRepresentation) representation ).getObject();
+                }
+            }
+        }
+
+        return (T) result;
+    }
+
+    @Override
+    public Representation toRepresentation( Object source, Variant target, Resource resource )
+    {
+        Representation result = null;
+
+        if( source instanceof JsonRepresentation )
+        {
+            result = (JsonRepresentation<?>) source;
+        }
+        else
+        {
+            if( target.getMediaType() == null )
+            {
+                target.setMediaType( MediaType.APPLICATION_JSON );
+            }
+            if( isCompatible( target ) )
+            {
+                result = create( target.getMediaType(), source );
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public <T> void updatePreferences( List<Preference<MediaType>> preferences,
+                                       Class<T> entity
+    )
+    {
+        updatePreferences( preferences, MediaType.APPLICATION_JSON, 1.0F );
+    }
+}
diff --git a/libraries/restlet/src/main/resources/META_INF/services/org.restlet.engine.converter.ConverterHelper b/libraries/restlet/src/main/resources/META_INF/services/org.restlet.engine.converter.ConverterHelper
new file mode 100644
index 0000000..3a8c7cf
--- /dev/null
+++ b/libraries/restlet/src/main/resources/META_INF/services/org.restlet.engine.converter.ConverterHelper
@@ -0,0 +1,16 @@
+# 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.
+
+org.apache.polygene.library.restlet.PolygeneConverter
diff --git a/libraries/restlet/src/test/java/org/apache/polygene/library/restlet/Customer.java b/libraries/restlet/src/test/java/org/apache/polygene/library/restlet/Customer.java
new file mode 100644
index 0000000..4245856
--- /dev/null
+++ b/libraries/restlet/src/test/java/org/apache/polygene/library/restlet/Customer.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.library.restlet;
+
+import org.apache.polygene.api.identity.HasIdentity;
+
+public interface Customer extends HasIdentity
+{
+}
diff --git a/libraries/restlet/src/test/java/org/apache/polygene/library/restlet/Order.java b/libraries/restlet/src/test/java/org/apache/polygene/library/restlet/Order.java
new file mode 100644
index 0000000..d37ff5e
--- /dev/null
+++ b/libraries/restlet/src/test/java/org/apache/polygene/library/restlet/Order.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.library.restlet;
+
+import org.apache.polygene.api.identity.HasIdentity;
+
+public interface Order extends HasIdentity
+{
+}
diff --git a/libraries/restlet/src/test/java/org/apache/polygene/library/restlet/OrdersModule.java b/libraries/restlet/src/test/java/org/apache/polygene/library/restlet/OrdersModule.java
new file mode 100644
index 0000000..3b8b42a
--- /dev/null
+++ b/libraries/restlet/src/test/java/org/apache/polygene/library/restlet/OrdersModule.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.restlet;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.library.restlet.assembly.RestletCrudModuleAssembler;
+
+public class OrdersModule
+    implements ModuleAssembler
+{
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        new RestletCrudModuleAssembler( Order.class ).assemble( module );
+        new RestletCrudModuleAssembler( Customer.class ).assemble( module );
+        new RestletCrudModuleAssembler( Product.class ).assemble( module );
+        return module;
+    }
+}
diff --git a/libraries/restlet/src/test/java/org/apache/polygene/library/restlet/Product.java b/libraries/restlet/src/test/java/org/apache/polygene/library/restlet/Product.java
new file mode 100644
index 0000000..91078d0
--- /dev/null
+++ b/libraries/restlet/src/test/java/org/apache/polygene/library/restlet/Product.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.library.restlet;
+
+import org.apache.polygene.api.identity.HasIdentity;
+
+public interface Product extends HasIdentity
+{
+}
diff --git a/libraries/restlet/src/test/java/org/apache/polygene/library/restlet/TestApplication.java b/libraries/restlet/src/test/java/org/apache/polygene/library/restlet/TestApplication.java
new file mode 100644
index 0000000..6d21d05
--- /dev/null
+++ b/libraries/restlet/src/test/java/org/apache/polygene/library/restlet/TestApplication.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.library.restlet;
+
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.restlet.assembly.RestApplicationAssembler;
+import org.apache.polygene.library.restlet.assembly.configuration.ConfigurationModule;
+import org.apache.polygene.library.restlet.assembly.configuration.ConfigurationLayer;
+import org.apache.polygene.library.restlet.assembly.connectivity.ConnectivityLayer;
+import org.apache.polygene.library.restlet.assembly.domain.DomainLayer;
+import org.apache.polygene.library.restlet.assembly.infrastructue.FileStorageModule;
+import org.apache.polygene.library.restlet.assembly.infrastructue.InfrastructureLayer;
+import org.apache.polygene.library.restlet.assembly.resource.ResourceLayer;
+
+// START SNIPPET: app
+public class TestApplication
+{
+    private static final String NAME = "Test Application";
+    private static final String VERSION = "1.0";
+    private static final Application.Mode MODE = Application.Mode.development;
+
+    // END SNIPPET: app
+
+
+    public static void main( String[] args )
+        throws Exception
+    {
+        RestApplicationAssembler assembler = new RestApplicationAssembler( NAME, VERSION, MODE,
+            ConfigurationLayer.class,
+            InfrastructureLayer.class,
+            DomainLayer.class,
+            ResourceLayer.class,
+            ConnectivityLayer.class
+        );
+
+        assembler.initialize();
+
+        ModuleAssembly configModule = assembler.layer( ConfigurationLayer.class ).module( ConfigurationModule.NAME );
+        assembler.layer( InfrastructureLayer.class,
+                         new FileStorageModule( configModule ) );
+
+        assembler.layer( DomainLayer.class,
+                         new OrdersModule()
+        );
+        assembler.start();
+        assembler.addShutdownHook();
+    }
+    // START SNIPPET: app
+}
+// END SNIPPET: app
diff --git a/libraries/scheduler/build.gradle b/libraries/scheduler/build.gradle
deleted file mode 100644
index bc426ce..0000000
--- a/libraries/scheduler/build.gradle
+++ /dev/null
@@ -1,37 +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.
- */
-
-description = "Apache Zest™ Schduler Library for long term timing functionalities."
-
-jar { manifest { name = "Apache Zest™ Library - Scheduler" }}
-
-
-dependencies {
-    compile project( ":org.qi4j.core:org.qi4j.core.bootstrap" )
-    compile project( ':org.qi4j.libraries:org.qi4j.library.constraints' )
-    compile libraries.sked
-    compile libraries.slf4j_api
-
-    testCompile project( ":org.qi4j.core:org.qi4j.core.testsupport" )
-    testCompile project( ":org.qi4j.extensions:org.qi4j.extension.indexing-rdf" )
-    testCompile libraries.awaitility
-
-    testRuntime project( ":org.qi4j.core:org.qi4j.core.runtime" )
-    testRuntime libraries.logback
-}
diff --git a/libraries/scheduler/dev-status.xml b/libraries/scheduler/dev-status.xml
deleted file mode 100644
index fc11ce4..0000000
--- a/libraries/scheduler/dev-status.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
-  <status>
-    <!--none,early,beta,stable,mature-->
-    <codebase>beta</codebase>
-
-    <!-- none, brief, good, complete -->
-    <documentation>good</documentation>
-
-    <!-- none, some, good, complete -->
-    <unittests>good</unittests>
-  </status>
-  <licenses>
-    <license>ALv2</license>
-  </licenses>
-</module>
diff --git a/libraries/scheduler/src/docs/scheduler.txt b/libraries/scheduler/src/docs/scheduler.txt
deleted file mode 100644
index 142907a..0000000
--- a/libraries/scheduler/src/docs/scheduler.txt
+++ /dev/null
@@ -1,168 +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.
-///////////////////////////////////////////////////////////////
-
-[[library-scheduler,Scheduler Library]]
-= Scheduler =
-
-[devstatus]
---------------
-source=libraries/scheduler/dev-status.xml
---------------
-
-The Scheduler library provides an easy way to schedule tasks using cron expressions if needed.
-
-An optional Timeline allows you to browse past and future task runs.
-
-include::../../build/docs/buildinfo/artifact.txt[]
-
-== Logging ==
-
-The SLF4J Logger used by this library is named "org.qi4j.library.scheduler".
-
-== Assembly ==
-
-Use SchedulerAssembler to add the Scheduler service to your Application. This
-Assembler provide a fluent api to programmatically configure configuration defaults and activate the
-Timeline service assembly that allow to browse in past and future Task runs.
-
-Here is a full example:
-
-[snippet,java]
-----
-source=libraries/scheduler/src/test/java/org/qi4j/library/scheduler/SchedulerTest.java
-tag=assembly
-----
-
-== Configuration ==
-
-SchedulerConfiguration defines configuration properties details:
-
-[snippet,java]
-----
-source=libraries/scheduler/src/main/java/org/qi4j/library/scheduler/SchedulerConfiguration.java
-tag=configuration
-----
-
-== Writing Tasks ==
-
-To write a schedulable Task, compose an Entity with the Task type to be able to schedule it.
-
-The Task contract is quite simple:
-
-[snippet,java]
-----
-source=libraries/scheduler/src/main/java/org/qi4j/library/scheduler/Task.java
-tag=task
-----
-
-Tasks have a mandatory name property and an optional tags property. Theses properties get copied in
-each TimelineRecord created when the Timeline feature is activated.
-
-The run() method of Tasks is wrapped in a UnitOfWork when called by the Scheduler.
-Thanks to the UnitOfWork handling in Zest, you can split the work done in your Tasks in
-several UnitOfWorks, the one around the Task#run() invocation will then be paused.
-
-Here is a simple example:
-
-[snippet,java]
------------
-source=libraries/scheduler/src/test/java/org/qi4j/library/scheduler/docsupport/SchedulerDocs.java
-tag=1
------------
-
-== Scheduling Tasks ==
-
-Tasks are scheduled using the Scheduler service. This creates a Schedule associated to
-the Task that allows you to know if it is running, to change it's cron expression and set it's
-durability.
-
-By default, a Schedule is not durable. In other words, it do not survive an Application
-restart. To make a Schedule durable, set it's durable property to true once its scheduled.
-
-There are two ways to schedule a Task using the Scheduler service: once or with a cron
-expression.
-
-=== Scheduling once ===
-
-This is the easiest way to run a background Task once after a given initial delay in seconds.
-
-[snippet,java]
------------
-source=libraries/scheduler/src/test/java/org/qi4j/library/scheduler/docsupport/SchedulerDocs.java
-tag=2
------------
-
-Note that there is no point in making such a Schedule durable because it won't be run repeatedly.
-
-
-=== Scheduling using a cron expression ===
-
-Cron expression parsing is based on the GNU crontab manpage that can be found here:
-http://unixhelp.ed.ac.uk/CGI/man-cgi?crontab+5 .
-
-The following extensions are used:
-
-- a mandatory field is added at the begining: seconds.
-- a special string is added: @minutely
-- a special character is added: ? to choose between dayOfMonth and dayOfWeek
-
-The ? special char has the same behavior as in the Quartz Scheduler expression. The wikipedia page
-http://en.wikipedia.org/wiki/CRON_expression
-explains Quartz Scheduler expression, not simple cron expressions. You'll find there about the ? special
-char and maybe that some other extensions you would like to use are missing in this project.
-
-To sum up, cron expressions used here have a precision of one second. The following special strings can be used:
-
-- @minutely
-- @hourly
-- @midnight or @daily
-- @weekly
-- @monthly
-- @annualy or @yearly
-
-
-== Durability ==
-Schedules can either be ethereal or durable, passed as an argument to the +Scheduler+. If it is a durable
-schedule, then the Task must be an Entity Composite.
-
-When the
-== Observing the Timeline ==
-
-Timeline allow to browse in past and future Task runs. This feature is available only if you activate
-the Timeline assembly in the SchedulerAssembler}, see above.
-
-Once activated, Task success and failures are recorded. Then, the Timeline
-service allow to browse in past (recorded) and in anticipated (future) Task runs.
-
-Use the following in your code to get a Timeline Service injected:
-
-[snippet,java]
------------
-source=libraries/scheduler/src/test/java/org/qi4j/library/scheduler/docsupport/SchedulerDocs.java
-tag=timeline
------------
-
-Here is the actual Timeline contract:
-
-[snippet,java]
-----
-source=libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/Timeline.java
-tag=timeline
-----
-
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/Scheduler.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/Scheduler.java
deleted file mode 100644
index 14df2ee..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/Scheduler.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2010-2012, Paul Merlin.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.scheduler;
-
-import org.joda.time.DateTime;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.unitofwork.concern.UnitOfWorkConcern;
-import org.qi4j.api.unitofwork.concern.UnitOfWorkPropagation;
-import org.qi4j.library.scheduler.bootstrap.SchedulerAssembler;
-import org.qi4j.library.scheduler.schedule.Schedule;
-import org.qi4j.library.scheduler.schedule.cron.CronExpression;
-import org.qi4j.library.scheduler.timeline.Timeline;
-
-import static org.qi4j.api.unitofwork.concern.UnitOfWorkPropagation.Propagation.MANDATORY;
-
-/**
- * Scheduler.
- * <p>
- * This is the only interface you should use in your application for scheduling tasks.
- * </p>
- * <p>
- * See {@link SchedulerConfiguration} for configuration properties.
- * </p>
- * <p>
- * See in {@link SchedulerAssembler} how to assemble a {@link Scheduler} and optional {@link Timeline}.
- * </p>
- * <p>
- * By default, a {@link Schedule} is not durable. In other words, it do not survive an {@link Application} restart.
- * </p>
- * <p>
- * To make a {@link Schedule} durable, set it's durable property to true once its scheduled.
- * </p>
- * <p>
- * Durable {@link Schedule}s that have no future run are removed by {@code SchedulerGarbageCollector} (not implemented?).
- * </p>
- */
-@Concerns( UnitOfWorkConcern.class )
-public interface Scheduler
-{
-    /**
-     * Schedule a Task to be run after a given initial delay in seconds.
-     *
-     * @param task                Task to be scheduled once
-     * @param initialSecondsDelay Initial delay the Task will be run after, in seconds
-     * @param durable             true if this Schedule should survive a restart.
-     *
-     * @return The newly created Schedule
-     */
-    @UnitOfWorkPropagation( MANDATORY )
-    Schedule scheduleOnce( Task task, int initialSecondsDelay, boolean durable );
-
-    /**
-     * Schedule a Task to be run after a given initial delay in seconds.
-     *
-     * @param task    Task to be scheduled once
-     * @param runAt   The future point in time when the Schedule will be run.
-     * @param durable true if this Schedule should survive a restart.
-     *
-     * @return The newly created Schedule
-     */
-    @UnitOfWorkPropagation( MANDATORY )
-    Schedule scheduleOnce( Task task, DateTime runAt, boolean durable );
-
-    /**
-     * Schedule a Task using a CronExpression.
-     *
-     * @param task           Task to be scheduled once
-     * @param cronExpression CronExpression for creating the Schedule for the given Task
-     * @param durable        true if this Schedule should survive a restart.
-     *
-     * @return The newly created Schedule
-     */
-    @UnitOfWorkPropagation( MANDATORY )
-    Schedule scheduleCron( Task task, @CronExpression String cronExpression, boolean durable );
-
-    /**
-     * Schedule a Task using a CronExpression with a given initial delay in milliseconds.
-     *
-     * @param task           Task to be scheduled once
-     * @param cronExpression CronExpression for creating the Schedule for the given Task
-     * @param initialDelay   Initial delay the Schedule will be active after, in milliseconds
-     * @param durable        true if this Schedule should survive a restart.
-     *
-     * @return The newly created Schedule
-     */
-    @UnitOfWorkPropagation( MANDATORY )
-    Schedule scheduleCron( Task task, @CronExpression String cronExpression, long initialDelay, boolean durable );
-
-    /**
-     * Schedule a Task using a CronExpression starting at a given date.
-     *
-     * @param task           Task to be scheduled once
-     * @param cronExpression CronExpression for creating the Schedule for the given Task
-     * @param start          Date from which the Schedule will become active
-     * @param durable        true if this Schedule should survive a restart.
-     *
-     * @return The newly created Schedule
-     */
-    @UnitOfWorkPropagation( MANDATORY )
-    Schedule scheduleCron( Task task, @CronExpression String cronExpression, DateTime start, boolean durable );
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/SchedulerConfiguration.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/SchedulerConfiguration.java
deleted file mode 100644
index 35d3f37..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/SchedulerConfiguration.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2010-2012, Paul Merlin.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.scheduler;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-
-/**
- * Configuration for the {@link Scheduler}.
- *
- * Every property has a default value, you can use a {@link Scheduler} without providing any.
- */
-public interface SchedulerConfiguration
-{
-// START SNIPPET: configuration
-    /**
-     * @return Number of worker threads, optional and defaults to the number of available cores.
-     */
-    @Optional
-    Property<Integer> workersCount();
-
-    /**
-     * @return Size of the queue to use for holding tasks before they are run, optional and defaults to 10.
-     */
-    @Optional
-    Property<Integer> workQueueSize();
-
-    /**
-     * @return If the scheduler must stop without waiting for running tasks, optional and defaults to false.
-     */
-    @UseDefaults
-    Property<Boolean> stopViolently();
-// END SNIPPET: configuration
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/SchedulerMixin.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/SchedulerMixin.java
deleted file mode 100644
index c3f8f61..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/SchedulerMixin.java
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright (c) 2010-2012, Paul Merlin.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.scheduler;
-
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.RejectedExecutionHandler;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import org.joda.time.DateTime;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.library.scheduler.schedule.Schedule;
-import org.qi4j.library.scheduler.schedule.ScheduleFactory;
-import org.qi4j.library.scheduler.schedule.ScheduleTime;
-import org.qi4j.library.scheduler.schedule.Schedules;
-import org.qi4j.library.scheduler.schedule.cron.CronExpression;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class SchedulerMixin
-    implements Scheduler, ServiceActivation
-{
-    private static final Logger LOGGER = LoggerFactory.getLogger( Scheduler.class );
-    private static final int DEFAULT_WORKERS_COUNT = Runtime.getRuntime().availableProcessors() + 1;
-    private static final int DEFAULT_WORKQUEUE_SIZE = 10;
-
-    @Service
-    private ScheduleFactory scheduleFactory;
-
-    private final SortedSet<ScheduleTime> timingQueue = new TreeSet<>();
-
-    private ScheduledExecutorService managementExecutor;
-    private ThreadPoolExecutor taskExecutor;
-
-    @Structure
-    private Module module;
-
-    @This
-    private SchedulerService me;
-
-    @This
-    private ThreadFactory threadFactory;
-
-    @This
-    private RejectedExecutionHandler rejectionHandler;
-
-    @This
-    private Configuration<SchedulerConfiguration> config;
-
-    private ScheduleHandler scheduleHandler;
-
-    @Override
-    public Schedule scheduleOnce( Task task, int initialSecondsDelay, boolean durable )
-    {
-        long now = System.currentTimeMillis();
-        Schedule schedule = scheduleFactory.newOnceSchedule( task, new DateTime( now + initialSecondsDelay * 1000 ), durable );
-        if( durable )
-        {
-            Schedules schedules = module.currentUnitOfWork().get( Schedules.class, getSchedulesIdentity( me ) );
-            schedules.schedules().add( schedule );
-        }
-        dispatchForExecution( schedule );
-        return schedule;
-    }
-
-    @Override
-    public Schedule scheduleOnce( Task task, DateTime runAt, boolean durable )
-    {
-        Schedule schedule = scheduleFactory.newOnceSchedule( task, runAt, durable );
-        dispatchForExecution( schedule );
-        if( durable )
-        {
-            Schedules schedules = module.currentUnitOfWork().get( Schedules.class, getSchedulesIdentity( me ) );
-            schedules.schedules().add( schedule );
-        }
-        return schedule;
-    }
-
-    @Override
-    public Schedule scheduleCron( Task task, String cronExpression, boolean durable )
-    {
-        DateTime now = new DateTime();
-        Schedule schedule = scheduleFactory.newCronSchedule( task, cronExpression, now, durable );
-        if( durable )
-        {
-            Schedules schedules = module.currentUnitOfWork().get( Schedules.class, getSchedulesIdentity( me ) );
-            schedules.schedules().add( schedule );
-        }
-        dispatchForExecution( schedule );
-        return schedule;
-    }
-
-    @Override
-    public Schedule scheduleCron( Task task, @CronExpression String cronExpression, DateTime start, boolean durable )
-    {
-        Schedule schedule = scheduleFactory.newCronSchedule( task, cronExpression, start, durable );
-        if( durable )
-        {
-            Schedules schedules = module.currentUnitOfWork().get( Schedules.class, getSchedulesIdentity( me ) );
-            schedules.schedules().add( schedule );
-        }
-        dispatchForExecution( schedule );
-        return schedule;
-    }
-
-    @Override
-    public Schedule scheduleCron( Task task, String cronExpression, long initialDelay, boolean durable )
-    {
-        DateTime start = new DateTime( System.currentTimeMillis() + initialDelay );
-        Schedule schedule = scheduleFactory.newCronSchedule( task, cronExpression, start, durable );
-        if( durable )
-        {
-            Schedules schedules = module.currentUnitOfWork().get( Schedules.class, getSchedulesIdentity( me ) );
-            schedules.schedules().add( schedule );
-        }
-        dispatchForExecution( schedule );
-        return schedule;
-    }
-
-    private void dispatchForExecution( Schedule schedule )
-    {
-        long now = System.currentTimeMillis();
-        synchronized( timingQueue )
-        {
-            if( timingQueue.size() == 0 )
-            {
-                long nextRun = schedule.nextRun( now );
-                if( nextRun < 0 )
-                {
-                    return;
-                }
-                timingQueue.add( new ScheduleTime( schedule.identity().get(), nextRun ) );
-                if( scheduleHandler == null )
-                {
-                    dispatchHandler();
-                }
-            }
-            else
-            {
-                ScheduleTime first = timingQueue.first();
-                long nextRun = schedule.nextRun( now );
-                if( nextRun < 0 )
-                {
-                    return;
-                }
-                timingQueue.add( new ScheduleTime( schedule.identity().get(), nextRun ) );
-                ScheduleTime newFirst = timingQueue.first();
-                if( !first.equals( newFirst ) )
-                {
-                    // We need to restart the managementThread, which is currently waiting for a 'later' event to
-                    // occur than the one that was just scheduled.
-                    if( scheduleHandler != null && scheduleHandler.future != null )
-                    {
-                        scheduleHandler.future.cancel( true );
-                    }
-                    dispatchHandler();
-                }
-            }
-        }
-    }
-
-    private void dispatchHandler()
-    {
-        scheduleHandler = new ScheduleHandler();
-        managementExecutor.schedule( scheduleHandler, timingQueue.first().nextTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS );
-    }
-
-    @Override
-    public void activateService()
-        throws Exception
-    {
-        // Handle configuration defaults
-        SchedulerConfiguration configuration = config.get();
-        Integer workersCount = configuration.workersCount().get();
-        Integer workQueueSize = configuration.workQueueSize().get();
-
-        if( workersCount == null )
-        {
-            workersCount = DEFAULT_WORKERS_COUNT;
-            LOGGER.debug( "Workers count absent from configuration, falled back to default: {} workers", DEFAULT_WORKERS_COUNT );
-        }
-        if( workQueueSize == null )
-        {
-            workQueueSize = DEFAULT_WORKQUEUE_SIZE;
-            LOGGER.debug( "WorkQueue size absent from configuration, falled back to default: {}", DEFAULT_WORKQUEUE_SIZE );
-        }
-
-        int corePoolSize = 2;
-        if( workersCount > 4 )
-        {
-            corePoolSize = workersCount / 4;
-        }
-        // Throws IllegalArgument if corePoolSize or keepAliveTime less than zero,
-        // or if workersCount less than or equal to zero,
-        // or if corePoolSize greater than workersCount.
-        taskExecutor = new ThreadPoolExecutor( corePoolSize, workersCount,
-            0, TimeUnit.MILLISECONDS,
-            new LinkedBlockingQueue<Runnable>( workQueueSize ),
-            threadFactory, rejectionHandler );
-        taskExecutor.prestartAllCoreThreads();
-        managementExecutor = new ScheduledThreadPoolExecutor( 2, threadFactory, rejectionHandler );
-        loadSchedules();
-        LOGGER.debug( "Activated" );
-    }
-
-    private void loadSchedules()
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            Schedules schedules = uow.get( Schedules.class, getSchedulesIdentity( me ) );
-            for( Schedule schedule : schedules.schedules() )
-            {
-                dispatchForExecution( schedule );
-            }
-        }
-        catch( NoSuchEntityException e )
-        {
-            // Create a new Schedules entity for keeping track of them all.
-            uow.newEntity( Schedules.class, getSchedulesIdentity( me ) );
-            uow.complete();
-        }
-        finally
-        {
-            if( uow.isOpen() )
-            {
-                uow.discard();
-            }
-        }
-    }
-
-    public static String getSchedulesIdentity( SchedulerService service )
-    {
-        return "Schedules:" + service.identity().get();
-    }
-
-    @Override
-    public void passivateService()
-        throws Exception
-    {
-        managementExecutor.shutdown();
-        taskExecutor.shutdown();
-
-        managementExecutor.awaitTermination( 5, TimeUnit.SECONDS );
-        managementExecutor.shutdownNow();
-
-        taskExecutor.awaitTermination( 5, TimeUnit.SECONDS );
-        taskExecutor.shutdownNow();
-
-        LOGGER.debug( "Passivated" );
-    }
-
-    /**
-     * This little bugger wakes up when it is time to dispatch a Task, creates the Runner and dispatches itself
-     * for the next run.
-     */
-    class ScheduleHandler
-        implements Runnable
-    {
-        private ScheduledFuture<?> future;
-
-        @Override
-        public void run()
-        {
-            synchronized( timingQueue )
-            {
-                ScheduleTime scheduleTime = timingQueue.first();
-                timingQueue.remove( scheduleTime );
-                ScheduleRunner scheduleRunner = new ScheduleRunner( scheduleTime, SchedulerMixin.this, module );
-                taskExecutor.submit( scheduleRunner );
-                if( timingQueue.size() == 0 )
-                {
-                    scheduleHandler = null;
-                }
-                else
-                {
-                    ScheduleTime nextTime = timingQueue.first();
-                    future = managementExecutor.schedule( scheduleHandler, nextTime.nextTime, TimeUnit.MILLISECONDS );
-                }
-            }
-        }
-    }
-
-    /**
-     * Handle {@link Task}'s {@link org.qi4j.api.unitofwork.UnitOfWork} and {@link org.qi4j.library.scheduler.timeline.TimelineRecord}s creation.
-     */
-    public static class ScheduleRunner
-        implements Runnable
-    {
-        private final Module module;
-        private final ScheduleTime schedule;
-        private final SchedulerMixin schedulerMixin;
-
-        public ScheduleRunner( ScheduleTime schedule, SchedulerMixin schedulerMixin, Module module )
-        {
-            this.schedule = schedule;
-            this.schedulerMixin = schedulerMixin;
-            this.module = module;
-        }
-
-        // WARN Watch this code, see if we can do better, maybe leverage @UnitOfWorkRetry
-        @Override
-        public void run()
-        {
-            Usecase usecase = UsecaseBuilder.newUsecase( "ScheduleRunner" );
-            UnitOfWork uow = module.newUnitOfWork( usecase );
-            try
-            {
-                Schedule schedule = uow.get( Schedule.class, this.schedule.scheduleIdentity );
-                Task task = schedule.task().get();
-                schedule = uow.get( Schedule.class, this.schedule.scheduleIdentity );
-                try
-                {
-                    schedule.taskStarting();
-                    task.run();
-                    schedule.taskCompletedSuccessfully();
-                }
-                catch( RuntimeException ex )
-                {
-                    schedule.taskCompletedWithException( ex );
-                }
-                schedulerMixin.dispatchForExecution( schedule );
-                uow.complete();
-            }
-            catch( UnitOfWorkCompletionException ex )
-            {
-            }
-            finally
-            {
-                // What should we do if we can't manage the Running flag??
-                if( uow.isOpen() )
-                {
-                    uow.discard();
-                }
-            }
-        }
-    }
-
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/SchedulerService.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/SchedulerService.java
deleted file mode 100644
index 8cb8264..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/SchedulerService.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2010-2014, Paul Merlin.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.scheduler;
-
-import java.util.concurrent.RejectedExecutionHandler;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.atomic.AtomicInteger;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceActivation;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Mixins( { SchedulerMixin.class, SchedulerService.ThreadFactory.class, SchedulerService.RejectionHandler.class } )
-public interface SchedulerService
-    extends Scheduler, ServiceActivation, Identity
-{
-    class RejectionHandler
-        implements RejectedExecutionHandler
-    {
-        private static final Logger LOGGER = LoggerFactory.getLogger( SchedulerService.class );
-
-        @Override
-        public void rejectedExecution( Runnable r, ThreadPoolExecutor executor )
-        {
-            LOGGER.error( "Runnable [" + r + "] was rejected by executor [" + executor + "]" );
-        }
-    }
-
-    class ThreadFactory
-        implements java.util.concurrent.ThreadFactory
-    {
-        private static final AtomicInteger POOL_NUMBER = new AtomicInteger( 1 );
-        private final ThreadGroup group;
-        private final AtomicInteger threadNumber = new AtomicInteger( 1 );
-        private final String namePrefix;
-
-        protected ThreadFactory( @This SchedulerService me )
-        {
-            SecurityManager sm = System.getSecurityManager();
-            group = ( sm != null ) ? sm.getThreadGroup() : Thread.currentThread().getThreadGroup();
-            namePrefix = me.identity().get() + "-P" + POOL_NUMBER.getAndIncrement() + "W";
-        }
-
-        @Override
-        public Thread newThread( Runnable runnable )
-        {
-            Thread thread = new Thread( group, runnable, namePrefix + threadNumber.getAndIncrement(), 0 );
-            if( thread.isDaemon() )
-            {
-                thread.setDaemon( false );
-            }
-            if( thread.getPriority() != Thread.NORM_PRIORITY )
-            {
-                thread.setPriority( Thread.NORM_PRIORITY );
-            }
-            return thread;
-        }
-    }
-
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/Task.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/Task.java
deleted file mode 100644
index 84c034c..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/Task.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2010-2012, Paul Merlin.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.scheduler;
-
-import java.util.List;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-
-/**
- * Compose an Entity using this type to be able to Schedule it.
- *
- * A Task is wrapped in a {@link org.qi4j.library.scheduler.SchedulerMixin.ScheduleRunner} before being run by an executor.
- * {@link org.qi4j.library.scheduler.SchedulerMixin.ScheduleRunner} wrap a {@link UnitOfWork} around the {@link Task#run()} invocation.
- *
- * Here is a simple example:
- * <pre>
- *  interface MyTask
- *      extends Task
- *  {
- *      Property&lt;String customState();
- *      Association&lt;AnotherEntity&gt; anotherEntity();
- *  }
- *
- *  class MyTaskMixin
- *      implements Runnable
- *  {
- *      &#64;This MyTaskEntity me;
- *      public void run()
- *      {
- *          me.customState().set( me.anotherEntity().get().doSomeStuff( me.customState().get() ) );
- *      }
- *  }
- * </pre>
- * Finaly, {@literal MyTask} must be assembled into an {@literal EntityComposite}.
- */
-// START SNIPPET: task
-public interface Task
-    extends Runnable
-{
-    Property<String> name();
-
-    @UseDefaults
-    Property<List<String>> tags();
-}
-// END SNIPPET: task
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/bootstrap/SchedulerAssembler.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/bootstrap/SchedulerAssembler.java
deleted file mode 100644
index 9981c0c..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/bootstrap/SchedulerAssembler.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2010-2012, Paul Merlin.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.scheduler.bootstrap;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.EntityDeclaration;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.bootstrap.ValueDeclaration;
-import org.qi4j.library.scheduler.SchedulerConfiguration;
-import org.qi4j.library.scheduler.SchedulerService;
-import org.qi4j.library.scheduler.schedule.ScheduleFactory;
-import org.qi4j.library.scheduler.schedule.Schedules;
-import org.qi4j.library.scheduler.schedule.cron.CronSchedule;
-import org.qi4j.library.scheduler.schedule.once.OnceSchedule;
-import org.qi4j.library.scheduler.timeline.Timeline;
-import org.qi4j.library.scheduler.timeline.TimelineForScheduleConcern;
-import org.qi4j.library.scheduler.timeline.TimelineRecord;
-import org.qi4j.library.scheduler.timeline.TimelineScheduleMixin;
-import org.qi4j.library.scheduler.timeline.TimelineSchedulerServiceMixin;
-
-/**
- * Assembler for Scheduler.
- *
- * Use this Assembler to add the Scheduler service to your application.
- * This Assembler provide a fluent api to programmatically configure configuration defaults and
- * activate the Timeline service assembly that allow to browse in past and future Task runs.
- *
- * Here is a full example:
- * <pre>
- *      new SchedulerAssembler().
- *              visibleIn( Visibility.layer ).
- *              withConfig( configModuleAssembly, Visibility.application ).
- *              withTimeline().
- *              assemble( module );
- * </pre>
- */
-public class SchedulerAssembler
-    extends Assemblers.VisibilityConfig<SchedulerAssembler>
-{
-    private boolean timeline;
-
-    /**
-     * Activate the assembly of Timeline related services.
-     *
-     * @return SchedulerAssembler
-     */
-    public SchedulerAssembler withTimeline()
-    {
-        timeline = true;
-        return this;
-    }
-
-    @Override
-    public void assemble( ModuleAssembly assembly )
-        throws AssemblyException
-    {
-        assembly.services( ScheduleFactory.class );
-        assembly.entities( Schedules.class );
-        EntityDeclaration scheduleEntities = assembly.entities( CronSchedule.class, OnceSchedule.class );
-
-        ValueDeclaration scheduleValues = assembly.values( CronSchedule.class, OnceSchedule.class );
-
-        ServiceDeclaration schedulerDeclaration = assembly.services( SchedulerService.class )
-            .visibleIn( visibility() )
-            .instantiateOnStartup();
-
-        if( timeline )
-        {
-            scheduleEntities.withTypes( Timeline.class )
-                .withMixins( TimelineScheduleMixin.class )
-                .withConcerns( TimelineForScheduleConcern.class );
-
-            scheduleValues.withTypes( Timeline.class )
-                .withMixins( TimelineScheduleMixin.class )
-                .withConcerns( TimelineForScheduleConcern.class );
-
-            // Internal
-            assembly.values( TimelineRecord.class );
-            schedulerDeclaration.withTypes( Timeline.class ).withMixins( TimelineSchedulerServiceMixin.class );
-        }
-
-        if( hasConfig() )
-        {
-            configModule().entities( SchedulerConfiguration.class ).visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/bootstrap/package.html b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/bootstrap/package.html
deleted file mode 100644
index b9a2ef1..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/bootstrap/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Scheduler Assembly.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/package.html b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/package.html
deleted file mode 100644
index a796ce1..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Scheduler Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/Schedule.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/Schedule.java
deleted file mode 100644
index ef2a214..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/Schedule.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2010-2012, Paul Merlin.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.scheduler.schedule;
-
-import org.joda.time.DateTime;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-import org.qi4j.library.scheduler.Task;
-
-/**
- * Represent the scheduling of a {@link Task}.
- */
-public interface Schedule
-    extends Identity
-{
-    /**
-     * @return The Association to the Task to be executed when it is time.
-     */
-    Association<Task> task();
-
-    /** The first run of this Schedule.
-     *
-     * @return The property containing the first time this Schedule will be run.
-     */
-    @Immutable
-    Property<DateTime> start();
-
-    /**
-     * Called just before the {@link org.qi4j.library.scheduler.Task#run()} method is called.
-     */
-    void taskStarting();
-
-    /**
-     * Called directly after the {@link org.qi4j.library.scheduler.Task#run()} method has been completed and
-     * returned from the method normally.
-     */
-    void taskCompletedSuccessfully();
-
-    /**
-     * Called directly after the {@link org.qi4j.library.scheduler.Task#run()} method has been completed but
-     * threw a RuntimeException.
-     * @param ex
-     */
-    void taskCompletedWithException( RuntimeException ex );
-
-    /**
-     * @return True if the associated {@link org.qi4j.library.scheduler.Task} is currently running, false otherwise
-     */
-    boolean isTaskRunning();
-
-    /**
-     * Compute the next time this schedule is to be run.
-     *
-     * @param from The starting time when to look for the next time it will run.
-     *
-     * @return The exact absolute time when this Schedule is to be run next time, or -1 if never
-     */
-    long nextRun( long from );
-
-    /**
-     * Return a representation of the Schedule in a human understandable format.
-     *
-     * @return A String representing this schedule.
-     */
-    String presentationString();
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/ScheduleFactory.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/ScheduleFactory.java
deleted file mode 100644
index 94b7fd2..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/ScheduleFactory.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.scheduler.schedule;
-
-import org.joda.time.DateTime;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.library.scheduler.SchedulerService;
-import org.qi4j.library.scheduler.Task;
-import org.qi4j.library.scheduler.schedule.cron.CronSchedule;
-import org.qi4j.library.scheduler.schedule.once.OnceSchedule;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Mixins( ScheduleFactory.Mixin.class )
-public interface ScheduleFactory
-{
-    Schedule newCronSchedule( Task task, String cronExpression, DateTime start, boolean durable );
-
-    Schedule newOnceSchedule( Task task, DateTime runAt, boolean durable );
-
-    class Mixin
-        implements ScheduleFactory
-    {
-        private static final Logger logger = LoggerFactory.getLogger( ScheduleFactory.class );
-
-        @Structure
-        private Module module;
-
-        @Service
-        private SchedulerService scheduler;
-
-        @Service
-        private UuidIdentityGeneratorService uuid;
-
-        @Override
-        public CronSchedule newCronSchedule( Task task, String cronExpression, DateTime start, boolean durable )
-        {
-            if( durable )
-            {
-                return newPersistentCronSchedule( task, cronExpression, start );
-            }
-            return newTransientCronSchedule( task, cronExpression, start );
-        }
-
-        @Override
-        public Schedule newOnceSchedule( Task task, DateTime runAt, boolean durable )
-        {
-            if( durable )
-            {
-                return newPersistentOnceSchedule( task, runAt );
-            }
-            return newTransientOnceSchedule( task, runAt );
-        }
-
-        private CronSchedule newTransientCronSchedule( Task task, String cronExpression, DateTime start )
-        {
-            ValueBuilder<CronSchedule> builder = module.newValueBuilder( CronSchedule.class );
-            CronSchedule prototype = builder.prototype();
-            prototype.task().set( task );
-            prototype.start().set( start );
-            prototype.identity().set( uuid.generate( CronSchedule.class ) );
-            prototype.cronExpression().set( cronExpression );
-            CronSchedule schedule = builder.newInstance();
-            logger.info( "Schedule {} created: {}", schedule.presentationString(), schedule.identity().get() );
-            return schedule;
-        }
-
-        private CronSchedule newPersistentCronSchedule( Task task, String cronExpression, DateTime start )
-        {
-            UnitOfWork uow = module.currentUnitOfWork();
-            EntityBuilder<CronSchedule> builder = uow.newEntityBuilder( CronSchedule.class );
-            CronSchedule builderInstance = builder.instance();
-            builderInstance.task().set( task );
-            builderInstance.start().set( start );
-            builderInstance.identity().set( uuid.generate( CronSchedule.class ) );
-            builderInstance.cronExpression().set( cronExpression );
-            CronSchedule schedule = builder.newInstance();
-            logger.info( "Schedule {} created: {}", schedule.presentationString(), schedule.identity().get() );
-            return schedule;
-        }
-
-        private Schedule newTransientOnceSchedule( Task task, DateTime runAt )
-        {
-            ValueBuilder<OnceSchedule> builder = module.newValueBuilder( OnceSchedule.class );
-            OnceSchedule builderInstance = builder.prototype();
-            builderInstance.task().set( task );
-            builderInstance.start().set( runAt );
-            builderInstance.identity().set( uuid.generate( CronSchedule.class ) );
-            OnceSchedule schedule = builder.newInstance();
-            logger.info( "Schedule {} created: {}", schedule.presentationString(), schedule.identity().get() );
-            return schedule;
-        }
-
-        private Schedule newPersistentOnceSchedule( Task task, DateTime runAt )
-        {
-            UnitOfWork uow = module.currentUnitOfWork();
-            EntityBuilder<OnceSchedule> builder = uow.newEntityBuilder( OnceSchedule.class );
-            OnceSchedule builderInstance = builder.instance();
-            builderInstance.task().set( task );
-            builderInstance.start().set( runAt );
-            builderInstance.identity().set( uuid.generate( CronSchedule.class ) );
-            OnceSchedule schedule = builder.newInstance();
-            logger.info( "Schedule {} created: {}", schedule.presentationString(), schedule.identity().get() );
-            return schedule;
-        }
-    }
-
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/ScheduleTime.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/ScheduleTime.java
deleted file mode 100644
index 7bf07d9..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/ScheduleTime.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2010-2012, Paul Merlin. All Rights Reserved.
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.scheduler.schedule;
-
-public final class ScheduleTime
-    implements Comparable<ScheduleTime>
-{
-    public String scheduleIdentity;
-    public long nextTime;
-
-    public ScheduleTime( String scheduleIdentity, long nextTime )
-    {
-        if( scheduleIdentity == null )
-        {
-            throw new IllegalArgumentException( "null not allowed: " + scheduleIdentity );
-        }
-        this.scheduleIdentity = scheduleIdentity;
-        this.nextTime = nextTime;
-    }
-
-    @Override
-    public boolean equals( Object o )
-    {
-        if( this == o )
-        {
-            return true;
-        }
-        if( o == null || getClass() != o.getClass() )
-        {
-            return false;
-        }
-        ScheduleTime that = (ScheduleTime) o;
-        if( nextTime != that.nextTime )
-        {
-            return false;
-        }
-        return scheduleIdentity.equals( that.scheduleIdentity );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        int result = scheduleIdentity.hashCode();
-        result = 31 * result + (int) ( nextTime ^ ( nextTime >>> 32 ) );
-        return result;
-    }
-
-    @Override
-    public int compareTo( ScheduleTime another )
-    {
-        if( this.nextTime < another.nextTime )
-        {
-            return -1;
-        }
-        else
-        {
-            if( this.nextTime == another.nextTime )
-            {
-                return 0;
-            }
-            else
-            {
-                return 1;
-            }
-        }
-    }
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/Schedules.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/Schedules.java
deleted file mode 100644
index 9df8b61..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/Schedules.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2010-2012, Paul Merlin. All Rights Reserved.
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.scheduler.schedule;
-
-import org.qi4j.api.association.ManyAssociation;
-
-public interface Schedules
-{
-    ManyAssociation<Schedule> schedules();
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/cron/CronExpression.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/cron/CronExpression.java
deleted file mode 100644
index fb5160b..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/cron/CronExpression.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2010-2012, Paul Merlin.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.scheduler.schedule.cron;
-
-import java.lang.annotation.Retention;
-import org.qi4j.api.constraint.ConstraintDeclaration;
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.library.constraints.annotation.InstanceOf;
-import org.qi4j.library.constraints.annotation.NotEmpty;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-@ConstraintDeclaration
-@Retention( RUNTIME )
-@NotEmpty
-@InstanceOf( String.class )
-@Constraints( CronExpressionConstraint.class )
-public @interface CronExpression
-{
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/cron/CronExpressionConstraint.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/cron/CronExpressionConstraint.java
deleted file mode 100644
index bf9f480..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/cron/CronExpressionConstraint.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2010-2012, Paul Merlin.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.scheduler.schedule.cron;
-
-import org.codeartisans.sked.cron.CronSchedule;
-import org.qi4j.api.constraint.Constraint;
-
-public class CronExpressionConstraint
-    implements Constraint<CronExpression, String>
-{
-    private static final long serialVersionUID = 1L;
-
-    @Override
-    public boolean isValid( CronExpression annotation, String cronExpression )
-    {
-        return CronSchedule.isExpressionValid( cronExpression );
-    }
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/cron/CronSchedule.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/cron/CronSchedule.java
deleted file mode 100644
index f9b8542..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/cron/CronSchedule.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2010-2012, Paul Merlin. All Rights Reserved.
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.scheduler.schedule.cron;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-import org.qi4j.library.scheduler.schedule.Schedule;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Mixins( CronSchedule.CronScheduleMixin.class )
-public interface CronSchedule
-    extends Schedule
-{
-    /**
-     * The Cron expression indicating when the Schedule is to be run.
-     * The Schedule can NOT be changed once it is set. If this is needed, delete this Schedule and attach the Task
-     * to a new Schedule.
-     *
-     * @return The cron expression that will be used on {@link org.qi4j.api.unitofwork.UnitOfWork} completion to compute next run
-     */
-    @CronExpression
-    @Immutable
-    Property<String> cronExpression();
-
-    abstract class CronScheduleMixin
-        implements CronSchedule
-    {
-        private static final Logger LOGGER = LoggerFactory.getLogger( Schedule.class );
-        private boolean running;
-
-        @Override
-        public void taskStarting()
-        {
-            running = true;
-        }
-
-        @Override
-        public void taskCompletedSuccessfully()
-        {
-            running = false;
-        }
-
-        @Override
-        public void taskCompletedWithException( RuntimeException ex )
-        {
-            running = false;
-        }
-
-        @Override
-        public String presentationString()
-        {
-            return cronExpression().get();
-        }
-
-        @Override
-        public boolean isTaskRunning()
-        {
-            // See SchedulerMixin.ScheduleRunner::run
-            return false;
-        }
-
-        @Override
-        public long nextRun( long from )
-        {
-            long actualFrom = from;
-            long firstRun = start().get().getMillis();
-            if( firstRun > from )
-            {
-                actualFrom = firstRun;
-            }
-            Long nextRun = new org.codeartisans.sked.cron.CronSchedule( cronExpression().get() )
-                .firstRunAfter( actualFrom );
-            LOGGER.info( "CronSchedule::nextRun({}) is {}", from, firstRun );
-            return nextRun;
-        }
-    }
-
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/cron/package.html b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/cron/package.html
deleted file mode 100644
index f3fd2c2..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/cron/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Scheduler CRON Schedules.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/once/OnceSchedule.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/once/OnceSchedule.java
deleted file mode 100644
index 637e3d2..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/once/OnceSchedule.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2010-2012, Paul Merlin. All Rights Reserved.
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.scheduler.schedule.once;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.library.scheduler.schedule.Schedule;
-
-@Mixins( OnceSchedule.OnceScheduleMixin.class )
-public interface OnceSchedule
-    extends Schedule
-{
-    abstract class OnceScheduleMixin
-        implements OnceSchedule
-    {
-        private boolean running;
-
-        @Override
-        public void taskStarting()
-        {
-            running = true;
-        }
-
-        @Override
-        public void taskCompletedSuccessfully()
-        {
-            running = false;
-        }
-
-        @Override
-        public void taskCompletedWithException( RuntimeException ex )
-        {
-            running = false;
-        }
-
-        @Override
-        public boolean isTaskRunning()
-        {
-            return running;
-        }
-
-        @Override
-        public long nextRun( long from )
-        {
-            long runAt = start().get().getMillis();
-            if( runAt >= from )
-            {
-                return runAt;
-            }
-            return -1;
-        }
-
-        @Override
-        public String presentationString()
-        {
-            return start().get().toString();
-        }
-    }
-
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/once/package.html b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/once/package.html
deleted file mode 100644
index c12fd5b..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/once/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Scheduler Once Schedules.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/package.html b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/package.html
deleted file mode 100644
index 7c74250..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/schedule/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Scheduler Schedules.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/Timeline.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/Timeline.java
deleted file mode 100644
index 9c77162..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/Timeline.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2010-2012, Paul Merlin.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.scheduler.timeline;
-
-import org.joda.time.DateTime;
-import org.qi4j.api.unitofwork.concern.UnitOfWorkPropagation;
-
-/**
- * Timeline allow to browse in past and future Task runs.
- */
-// START SNIPPET: timeline
-public interface Timeline
-{
-// END SNIPPET: timeline
-
-    /**
-     * @param maxResults Maximum number of TimelineRecord to compute
-     *
-     * @return Last past records
-     */
-    @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.MANDATORY )
-// START SNIPPET: timeline
-    Iterable<TimelineRecord> getLastRecords( int maxResults );
-// END SNIPPET: timeline
-
-    /**
-     * @param maxResults Maximum number of TimelineRecord to compute
-     *
-     * @return Next running or future records
-     */
-    @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.MANDATORY )
-// START SNIPPET: timeline
-    Iterable<TimelineRecord> getNextRecords( int maxResults );
-// END SNIPPET: timeline
-
-    /**
-     * @param from Lower limit
-     * @param to   Upper limit
-     *
-     * @return Records between the given dates
-     */
-    @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.MANDATORY )
-// START SNIPPET: timeline
-    Iterable<TimelineRecord> getRecords( DateTime from, DateTime to );
-// END SNIPPET: timeline
-
-    /**
-     * @param from Lower limit
-     * @param to   Upper limit
-     *
-     * @return Records between the given dates
-     */
-    @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.MANDATORY )
-// START SNIPPET: timeline
-    Iterable<TimelineRecord> getRecords( long from, long to );
-}
-// END SNIPPET: timeline
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineForScheduleConcern.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineForScheduleConcern.java
deleted file mode 100644
index 60bedba..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineForScheduleConcern.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.scheduler.timeline;
-
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.util.List;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.library.scheduler.schedule.Schedule;
-
-public abstract class TimelineForScheduleConcern
-    extends ConcernOf<Schedule>
-    implements Schedule
-{
-    @This
-    private TimelineScheduleState state;
-
-    @Structure
-    private Module module;
-
-    @Override
-    public void taskStarting()
-    {
-        addRecord( TimelineRecordStep.STARTED, "" );
-        next.taskStarting();
-    }
-
-    @Override
-    public void taskCompletedSuccessfully()
-    {
-        addRecord( TimelineRecordStep.SUCCESS, "" );
-        next.taskCompletedSuccessfully();
-    }
-
-    @Override
-    public void taskCompletedWithException( RuntimeException ex )
-    {
-        TimelineRecordStep step = TimelineRecordStep.FAILURE;
-        String details = "Exception occurred:" + getStackTrace( ex );
-        addRecord( step, details );
-        next.taskCompletedWithException( ex );
-    }
-
-    private void addRecord( TimelineRecordStep step, String details )
-    {
-        ValueBuilder<TimelineRecord> builder = module.newValueBuilder( TimelineRecord.class );
-        TimelineRecord prototype = builder.prototype();
-        prototype.step().set( step );
-        prototype.taskName().set( task().get().name().get() );
-        List<String> tags = task().get().tags().get();
-        prototype.taskTags().set( tags );
-        prototype.timestamp().set( System.currentTimeMillis() );
-        prototype.scheduleIdentity().set( this.identity().get() );
-        prototype.details().set( details );
-        TimelineRecord record = builder.newInstance();
-        List<TimelineRecord> timelineRecords = state.history().get();
-        timelineRecords.add( record );
-        state.history().set( timelineRecords );
-    }
-
-    private String getStackTrace( RuntimeException ex )
-    {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream( 1000 );
-        BufferedOutputStream out = new BufferedOutputStream( baos );
-        PrintStream print = new PrintStream( out );
-        ex.printStackTrace( print );
-        print.flush();
-        return baos.toString();
-    }
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineRecord.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineRecord.java
deleted file mode 100644
index f4ac63f..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineRecord.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2010-2012, Paul Merlin.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.scheduler.timeline;
-
-import java.util.List;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.library.scheduler.Scheduler;
-
-/**
- * Record in {@link Scheduler}'s {@link Timeline}.
- *
- * {@link TimelineRecord}s are {@link Comparable} regarding their {@link TimelineRecord#timestamp()}.
- */
-@Mixins( TimelineRecord.Mixin.class )
-public interface TimelineRecord
-    extends Comparable<TimelineRecord>, ValueComposite
-{
-    /**
-     * @return Identity of the associated {@link Scheduler}
-     */
-    Property<String> scheduleIdentity();
-
-    /**
-     * @return Timestamp of this record
-     */
-    Property<Long> timestamp();
-
-    /**
-     * @return Name of the associated {@link org.qi4j.library.scheduler.Task}
-     */
-    Property<String> taskName();
-
-    /**
-     * @return Tags of the associated {@link org.qi4j.library.scheduler.Task}
-     */
-    @UseDefaults
-    Property<List<String>> taskTags();
-
-    Property<TimelineRecordStep> step();
-
-    /**
-     * @return Details text of this record
-     */
-    @Queryable( false )
-    @UseDefaults
-    Property<String> details();
-
-    abstract class Mixin
-        implements TimelineRecord
-    {
-
-        @Override
-        public int compareTo( TimelineRecord o )
-        {
-            return timestamp().get().compareTo( o.timestamp().get() );
-        }
-    }
-
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineRecordStep.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineRecordStep.java
deleted file mode 100644
index fd329c7..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineRecordStep.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2010-2012, Paul Merlin.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.scheduler.timeline;
-
-public enum TimelineRecordStep
-{
-    STARTED,
-    SUCCESS,
-    FAILURE,
-    FUTURE
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineScheduleMixin.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineScheduleMixin.java
deleted file mode 100644
index eb91f1c..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineScheduleMixin.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.scheduler.timeline;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import org.joda.time.DateTime;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.library.scheduler.schedule.Schedule;
-
-public class TimelineScheduleMixin
-    implements Timeline
-{
-    @Structure
-    private Module module;
-
-    @This
-    private TimelineScheduleState state;
-
-    @This
-    private Schedule me;
-
-    @Override
-    public Iterable<TimelineRecord> getLastRecords( int maxResults )
-    {
-        List<TimelineRecord> timelineRecords = state.history().get();
-        int size = timelineRecords.size();
-        if( size < maxResults )
-        {
-            return Collections.unmodifiableCollection( timelineRecords );
-        }
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-        for( int i = size - maxResults; i < size; i++ )
-        {
-            result.add( timelineRecords.get( i ) );
-        }
-        return result;
-    }
-
-    @Override
-    public Iterable<TimelineRecord> getNextRecords( int maxResults )
-    {
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-        long time = System.currentTimeMillis();
-        for( int i = 0; i < maxResults; i++ )
-        {
-            time = me.nextRun( time );
-            result.add( createFutureRecord( time ) );
-        }
-        return result;
-    }
-
-    @Override
-    public Iterable<TimelineRecord> getRecords( DateTime from, DateTime to )
-    {
-        return getRecords( from.getMillis(), to.getMillis() );
-    }
-
-    @Override
-    public Iterable<TimelineRecord> getRecords( long from, long to )
-    {
-        long now = System.currentTimeMillis();
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-        result.addAll( getPastRecords( from ) );
-        result.addAll( getFutureRecords( now, to ) );
-        return result;
-    }
-
-    private Collection<? extends TimelineRecord> getPastRecords( long from )
-    {
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-        List<TimelineRecord> timelineRecords = state.history().get();
-        for( TimelineRecord record : timelineRecords )
-        {
-            Long timestamp = record.timestamp().get();
-            if( timestamp >= from )
-            {
-                result.add( record );
-            }
-        }
-        return result;
-    }
-
-    private Collection<? extends TimelineRecord> getFutureRecords( long now, long to )
-    {
-        if( now > to )
-        {
-            return Collections.emptyList();
-        }
-
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-        long time = now;
-        while( time <= to )
-        {
-            time = me.nextRun( time );
-            if( time <= to )
-            {
-                result.add( createFutureRecord( time ) );
-            }
-        }
-        return result;
-    }
-
-    private TimelineRecord createFutureRecord( long when )
-    {
-        ValueBuilder<TimelineRecord> builder = module.newValueBuilder( TimelineRecord.class );
-        TimelineRecord prototype = builder.prototype();
-        prototype.step().set( TimelineRecordStep.FUTURE );
-        prototype.taskName().set( me.task().get().name().get() );
-        List<String> tags = me.task().get().tags().get();
-        prototype.taskTags().set( tags );
-        prototype.timestamp().set( when );
-        prototype.scheduleIdentity().set( me.identity().get() );
-        prototype.details().set( "" );
-        return builder.newInstance();
-    }
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineScheduleState.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineScheduleState.java
deleted file mode 100644
index 43790c1..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineScheduleState.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.scheduler.timeline;
-
-import java.util.List;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-
-public interface TimelineScheduleState
-{
-    @UseDefaults
-    Property<List<TimelineRecord>> history();
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineSchedulerServiceMixin.java b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineSchedulerServiceMixin.java
deleted file mode 100644
index 8a55520..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/TimelineSchedulerServiceMixin.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.scheduler.timeline;
-
-import java.util.SortedSet;
-import java.util.TreeSet;
-import org.joda.time.DateTime;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.functional.Iterables;
-import org.qi4j.library.scheduler.SchedulerMixin;
-import org.qi4j.library.scheduler.SchedulerService;
-import org.qi4j.library.scheduler.schedule.Schedule;
-import org.qi4j.library.scheduler.schedule.Schedules;
-
-/**
- * WARN TimelineService Mixin use SortedSets to keep records ordered and repeatedly search for the next run.
- * Could be greedy with large intervals
- */
-public abstract class TimelineSchedulerServiceMixin
-    implements Timeline, ServiceComposite
-{
-    @Structure
-    private Module module;
-
-    @Service
-    private SchedulerService scheduler;
-
-    @Override
-    public Iterable<TimelineRecord> getLastRecords( int maxResults )
-    {
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-
-        UnitOfWork uow = module.currentUnitOfWork();
-        String schedulesName = SchedulerMixin.getSchedulesIdentity( scheduler );
-        Schedules schedules = uow.get( Schedules.class, schedulesName );
-        for( Schedule schedule : schedules.schedules() )
-        {
-            Timeline timeline = (Timeline) schedule;
-            Iterable<TimelineRecord> lastRecords = timeline.getLastRecords( maxResults );
-            Iterables.addAll( result, lastRecords );
-        }
-        return Iterables.limit( maxResults, Iterables.reverse( result ) );
-    }
-
-    @Override
-    public Iterable<TimelineRecord> getNextRecords( int maxResults )
-    {
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-        UnitOfWork uow = module.currentUnitOfWork();
-        String schedulesName = SchedulerMixin.getSchedulesIdentity( scheduler );
-        Schedules schedules = uow.get( Schedules.class, schedulesName );
-        for( Schedule schedule : schedules.schedules() )
-        {
-            Timeline timeline = (Timeline) schedule;
-            Iterable<TimelineRecord> lastRecords = timeline.getNextRecords( maxResults );
-            Iterables.addAll( result, lastRecords );
-        }
-        return Iterables.limit( maxResults, result );
-    }
-
-    @Override
-    public Iterable<TimelineRecord> getRecords( DateTime from, DateTime to )
-    {
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-
-        UnitOfWork uow = module.currentUnitOfWork();
-        String schedulesName = SchedulerMixin.getSchedulesIdentity( scheduler );
-        Schedules schedules = uow.get( Schedules.class, schedulesName );
-        for( Schedule schedule : schedules.schedules() )
-        {
-            Timeline timeline = (Timeline) schedule;
-            Iterable<TimelineRecord> lastRecords = timeline.getRecords( from, to );
-            Iterables.addAll( result, lastRecords );
-        }
-        return result;
-    }
-
-    @Override
-    public Iterable<TimelineRecord> getRecords( long from, long to )
-    {
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-
-        UnitOfWork uow = module.currentUnitOfWork();
-        String schedulesName = SchedulerMixin.getSchedulesIdentity( scheduler );
-        Schedules schedules = uow.get( Schedules.class, schedulesName );
-        for( Schedule schedule : schedules.schedules() )
-        {
-            Timeline timeline = (Timeline) schedule;
-            Iterable<TimelineRecord> lastRecords = timeline.getRecords( from, to );
-            Iterables.addAll( result, lastRecords );
-        }
-        return result;
-    }
-}
diff --git a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/package.html b/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/package.html
deleted file mode 100644
index 1b757d2..0000000
--- a/libraries/scheduler/src/main/java/org/qi4j/library/scheduler/timeline/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Scheduler Timeline.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/scheduler/src/test/java/org/qi4j/library/scheduler/AbstractSchedulerTest.java b/libraries/scheduler/src/test/java/org/qi4j/library/scheduler/AbstractSchedulerTest.java
deleted file mode 100644
index 19ea3f5..0000000
--- a/libraries/scheduler/src/test/java/org/qi4j/library/scheduler/AbstractSchedulerTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2010-2014, Paul Merlin.
- *
- * Licensed  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.qi4j.library.scheduler;
-
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.rdf.assembly.RdfMemoryStoreAssembler;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-public abstract class AbstractSchedulerTest
-    extends AbstractQi4jTest
-{
-    @Override
-    public final void assemble( ModuleAssembly assembly )
-        throws AssemblyException
-    {
-        assembly.entities( FooTask.class );
-
-        new EntityTestAssembler().assemble( assembly );
-        new RdfMemoryStoreAssembler().assemble( assembly );
-
-        onAssembly( assembly );
-    }
-
-    protected abstract void onAssembly( ModuleAssembly module )
-        throws AssemblyException;
-
-    protected final FooTask createFooTask( UnitOfWork uow, String name, String input )
-    {
-        EntityBuilder<FooTask> builder = uow.newEntityBuilder( FooTask.class );
-        FooTask task = builder.instance();
-        task.name().set( name );
-        task.input().set( input );
-        return builder.newInstance();
-    }
-}
diff --git a/libraries/scheduler/src/test/java/org/qi4j/library/scheduler/Constants.java b/libraries/scheduler/src/test/java/org/qi4j/library/scheduler/Constants.java
deleted file mode 100644
index 6f8b13e..0000000
--- a/libraries/scheduler/src/test/java/org/qi4j/library/scheduler/Constants.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2010-2014, Paul Merlin.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.scheduler;
-
-// TODO Rename to TestConstants
-public interface Constants
-{
-    String BAR = "bar";
-    String BAZAR = "bazar";
-}
diff --git a/libraries/scheduler/src/test/java/org/qi4j/library/scheduler/FooTask.java b/libraries/scheduler/src/test/java/org/qi4j/library/scheduler/FooTask.java
deleted file mode 100644
index 6ab61fd..0000000
--- a/libraries/scheduler/src/test/java/org/qi4j/library/scheduler/FooTask.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2010-2014, Paul Merlin.
- *
- * Licensed  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.qi4j.library.scheduler;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Mixins( FooTask.Mixin.class )
-public interface FooTask
-    extends Task, Identity
-{
-    Property<String> input();
-
-    @Optional
-    Property<String> output();
-
-    public static abstract class Mixin
-        implements Runnable
-    {
-
-        private static final Logger LOGGER = LoggerFactory.getLogger( FooTask.class );
-
-        @This
-        private FooTask me;
-
-        @Override
-        public void run()
-        {
-            LOGGER.info( "FooTask.run({})", me.input().get() );
-            if( me.input().get().equals( Constants.BAZAR ) )
-            {
-                if( me.output().get() == null )
-                {
-                    me.output().set( Constants.BAR );
-                }
-                else
-                {
-                    me.output().set( me.output().get() + Constants.BAR );
-                }
-            }
-        }
-    }
-
-}
diff --git a/libraries/scheduler/src/test/java/org/qi4j/library/scheduler/SchedulerTest.java b/libraries/scheduler/src/test/java/org/qi4j/library/scheduler/SchedulerTest.java
deleted file mode 100644
index ac38d8e..0000000
--- a/libraries/scheduler/src/test/java/org/qi4j/library/scheduler/SchedulerTest.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (c) 2010-2014, Paul Merlin. All Rights Reserved.
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.library.scheduler;
-
-import java.util.concurrent.Callable;
-import org.joda.time.DateTime;
-import org.joda.time.Interval;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.scheduler.bootstrap.SchedulerAssembler;
-import org.qi4j.library.scheduler.timeline.Timeline;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static com.jayway.awaitility.Awaitility.await;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.functional.Iterables.count;
-import static org.qi4j.library.scheduler.Constants.BAR;
-import static org.qi4j.library.scheduler.Constants.BAZAR;
-
-public class SchedulerTest
-    extends AbstractSchedulerTest
-{
-    private static final Logger LOGGER = LoggerFactory.getLogger( SchedulerTest.class );
-
-    @Override
-    protected void onAssembly( ModuleAssembly testAssembly )
-        throws AssemblyException
-    {
-        ModuleAssembly moduleAssembly = testAssembly;
-        ModuleAssembly configModuleAssembly = testAssembly;
-        // START SNIPPET: assembly
-        new SchedulerAssembler().visibleIn( Visibility.application )
-            .withConfig( configModuleAssembly, Visibility.layer )
-            .withTimeline()
-            .assemble( moduleAssembly );
-        // END SNIPPET: assembly
-    }
-
-    @Test
-    public void testTaskWithoutScheduling()
-        throws UnitOfWorkCompletionException
-    {
-        Usecase usecase = UsecaseBuilder.newUsecase( "testTask" );
-        String taskId;
-        try( UnitOfWork uow = module.newUnitOfWork( usecase ) )
-        {
-            FooTask task = createFooTask( uow, "TestTask", BAZAR );
-            taskId = task.identity().get();
-            task.run();
-            uow.complete();
-        }
-        try( UnitOfWork uow = module.newUnitOfWork( usecase ) )
-        {
-            FooTask task = uow.get( FooTask.class, taskId );
-            assertThat( task.output().get(), equalTo( BAR ) );
-        }
-    }
-
-    @Test
-    public void testMinutely()
-        throws UnitOfWorkCompletionException
-    {
-        Usecase usecase = UsecaseBuilder.newUsecase( "TestMinutely" );
-        DateTime start = new DateTime();
-        String taskIdentity;
-        long sleepMillis;
-        try( UnitOfWork uow = module.newUnitOfWork( usecase ) )
-        {
-            Scheduler scheduler = module.findService( Scheduler.class ).get();
-
-            FooTask task = createFooTask( uow, usecase.name(), BAZAR );
-            taskIdentity = task.identity().get();
-
-            DateTime expectedRun = start.withMillisOfSecond( 0 ).withSecondOfMinute( 0 ).plusMinutes( 1 );
-            scheduler.scheduleCron( task, "@minutely", true );
-
-            uow.complete();
-
-            sleepMillis = new Interval( start, expectedRun ).toDurationMillis();
-            LOGGER.info( "Task scheduled on {} to be run at {}", start.getMillis(), expectedRun.getMillis() );
-        }
-
-        await( usecase.name() ).
-            atMost( sleepMillis + 5000, MILLISECONDS ).
-            until( taskOutput( taskIdentity ), equalTo( BAR ) );
-
-        try( UnitOfWork uow = module.newUnitOfWork( usecase ) )
-        {
-            Timeline timeline = module.findService( Timeline.class ).get();
-            DateTime now = new DateTime();
-
-            // Queries returning past records
-            assertThat( count( timeline.getLastRecords( 5 ) ),
-                        is( 2L ) );
-            assertThat( count( timeline.getRecords( start.getMillis(), now.getMillis() ) ),
-                        is( 2L ) );
-
-            // Queries returning future records
-            assertThat( count( timeline.getNextRecords( 4 ) ),
-                        is( 4L ) );
-            assertThat( count( timeline.getRecords( now.getMillis() + 100, now.plusMinutes( 5 ).getMillis() ) ),
-                        is( 5L ) );
-
-            // Queries returning mixed past and future records
-            assertThat( count( timeline.getRecords( start.getMillis(), now.plusMinutes( 5 ).getMillis() ) ),
-                        is( 7L ) );
-        }
-    }
-
-    @Test
-    public void testOnce()
-        throws UnitOfWorkCompletionException
-    {
-        final Usecase usecase = UsecaseBuilder.newUsecase( "TestOnce" );
-        final String taskIdentity;
-        try( UnitOfWork uow = module.newUnitOfWork( usecase ) )
-        {
-            Scheduler scheduler = module.findService( Scheduler.class ).get();
-
-            FooTask task = createFooTask( uow, usecase.name(), BAZAR );
-            taskIdentity = task.identity().get();
-
-            scheduler.scheduleOnce( task, 2, true );
-
-            uow.complete();
-        }
-
-        await( usecase.name() ).until( taskOutput( taskIdentity ), equalTo( BAR ) );
-    }
-
-    private Callable<String> taskOutput( final String taskIdentity )
-    {
-        return new Callable<String>()
-        {
-            @Override
-            public String call()
-                throws Exception
-            {
-                try( UnitOfWork uow = module.newUnitOfWork() )
-                {
-                    FooTask task = uow.get( FooTask.class, taskIdentity );
-                    return task == null ? null : task.output().get();
-                }
-            }
-        };
-    }
-}
diff --git a/libraries/scheduler/src/test/java/org/qi4j/library/scheduler/docsupport/SchedulerDocs.java b/libraries/scheduler/src/test/java/org/qi4j/library/scheduler/docsupport/SchedulerDocs.java
deleted file mode 100644
index 25e45e2..0000000
--- a/libraries/scheduler/src/test/java/org/qi4j/library/scheduler/docsupport/SchedulerDocs.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2010-2014, Paul Merlin.
- * Copyright (c) 2012, Niclas Hedhman.
- *
- * Licensed  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.qi4j.library.scheduler.docsupport;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.property.Property;
-import org.qi4j.library.scheduler.Scheduler;
-import org.qi4j.library.scheduler.Task;
-import org.qi4j.library.scheduler.schedule.Schedule;
-import org.qi4j.library.scheduler.timeline.Timeline;
-
-
-public class SchedulerDocs
-{
-
-// START SNIPPET: timeline
-    @Service Timeline timeline;
-// END SNIPPET: timeline
-
-// START SNIPPET: 2
-    @Service Scheduler scheduler;
-
-    public void method()
-    {
-        MyTaskEntity myTask = todo();
-        Schedule schedule = scheduler.scheduleOnce( myTask, 10, false );
-        // myTask will be run in 10 seconds from now
-    }
-
-// END SNIPPET: 2
-    MyTaskEntity todo() {
-        return null;
-    }
-
-// START SNIPPET: 1
-    interface MyTaskEntity extends Task
-    {
-        Property<String> myTaskState();
-
-        Association<AnotherEntity> anotherEntity();
-    }
-
-    class MyTaskMixin implements Runnable
-    {
-        @This MyTaskEntity me;
-
-        @Override
-        public void run()
-        {
-            me.myTaskState().set(me.anotherEntity().get().doSomeStuff(me.myTaskState().get()));
-        }
-    }
-
-// END SNIPPET: 1
-    interface AnotherEntity
-    {
-        String doSomeStuff(String p);
-    }
-
-}
\ No newline at end of file
diff --git a/libraries/scheduler/src/test/resources/logback-test.xml b/libraries/scheduler/src/test/resources/logback-test.xml
deleted file mode 100644
index 76cc7c5..0000000
--- a/libraries/scheduler/src/test/resources/logback-test.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<configuration>
-
-    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
-        <layout class="ch.qos.logback.classic.PatternLayout">
-            <Pattern>@%-10thread %-5level %logger{20} - %msg%n</Pattern>
-        </layout>
-    </appender>
-
-    <root level="info">
-        <appender-ref ref="stdout" />
-    </root>
-
-    <logger name="org.qi4j.library.scheduler" level="trace"/>
-
-</configuration>
\ No newline at end of file
diff --git a/libraries/scheduler/test-repeatedly.sh b/libraries/scheduler/test-repeatedly.sh
deleted file mode 100755
index bb7516b..0000000
--- a/libraries/scheduler/test-repeatedly.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/sh
-
-# 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.
-
-# Run clean test once and test repeatedly
-# Stop on first failure
-# cat build/num-repeats to see how many times it ran
-# Use time run-repeatedly.sh to get a time mesure
-#
-# Written because of milliseconds delays due to multithreading
-
-set -e
-
-../../gradlew clean test -Dversion=2.0-SNAPSHOT
-echo "x "`date` > build/num-repeats
-
-while ( true ) ; do
-	../../gradlew test -Dversion=2.0-SNAPSHOT
-	echo "x "`date` >> build/num-repeats
-done
-
-exit 0
diff --git a/libraries/scripting/build.gradle b/libraries/scripting/build.gradle
index 2d65e32..b885232 100644
--- a/libraries/scripting/build.gradle
+++ b/libraries/scripting/build.gradle
@@ -1,34 +1,39 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Common Scripting Library contains common classes across scripting implementations."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - Scripting - Common" }}
+description = "Apache Polygene™ Common Scripting Library contains common classes across scripting implementations."
+
+jar { manifest { name = "Apache Polygene™ Library - Scripting - Common" } }
+
+apply plugin: 'groovy'
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.api"))
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile(libraries.slf4j_api)
-  testCompile(libraries.junit)
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.asm)
-  testRuntime(libraries.asm_commons)
-  testRuntime(libraries.slf4j_simple)
-}
\ No newline at end of file
+  api polygene.core.api
+  api polygene.core.bootstrap
+
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+  testImplementation libraries.groovy
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/libraries/scripting/dev-status.xml b/libraries/scripting/dev-status.xml
index afa3369..d72e9f9 100644
--- a/libraries/scripting/dev-status.xml
+++ b/libraries/scripting/dev-status.xml
@@ -1,33 +1,36 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
 
     <!-- none, brief, good, complete -->
-    <documentation>none</documentation>
+    <documentation>good</documentation>
 
     <!-- none, some, good, complete -->
-    <unittests>complete</unittests>
+    <unittests>good</unittests>
   </status>
   <licenses>
     <license>ALv2</license>
diff --git a/libraries/scripting/src/docs/groovy.txt b/libraries/scripting/src/docs/groovy.txt
new file mode 100644
index 0000000..a14dfe3
--- /dev/null
+++ b/libraries/scripting/src/docs/groovy.txt
@@ -0,0 +1,77 @@
+///////////////////////////////////////////////////////////////
+ * 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.
+///////////////////////////////////////////////////////////////
+
+[[groovy, Scripting with Groovy]]
+== Groovy ==
+
+The Groovy Scripting Library is a Generic mixin that implements interfaces by delegating to Groovy code from classpath resources.
+
+But before looking at how to use the Scripting library we'll see that *you don't need Scripting library at all if you
+simply need to use Groovy classes as Fragments*. Groovy is a fully Java compatible language and can be used directly,
+similarly to Scala.
+
+Then we'll see how to use Groovy class scripts and method scripts.
+
+All examples below are based on this type:
+
+[snippet,java]
+----
+source=libraries/scripting/src/test/java/org/apache/polygene/library/scripting/HelloSpeaker.java
+tag=speaker
+----
+
+== Using compiled Groovy classes ==
+
+To directly use compiled Groovy classes as Fragments you don't need this library at all.
+
+Having this Groovy class compiled ;
+
+.HelloSpeakerMixin.groovy
+[snippet,groovy]
+----
+source=libraries/scripting/src/test/groovy/org/apache/polygene/library/scripting/HelloSpeakerMixin.groovy
+tag=direct
+----
+
+assemble it directly:
+
+[snippet,java]
+----
+source=libraries/scripting/src/test/groovy/org/apache/polygene/library/scripting/HelloSpeakerTest.java
+tag=direct
+----
+
+== Using Groovy function scripts ==
+
+Declare a Groovy function in a resource file located in the same package as the implemented type with the name +<type>.groovy+:
+
+.HelloSpeaker.groovy
+[snippet,groovy]
+----
+source=libraries/scripting/src/test/resources/org/apache/polygene/library/scripting/HelloSpeaker.groovy
+tag=script
+----
+
+Then assemble it with the normal +ScriptMixin+:
+
+[snippet,java]
+----
+source=libraries/scripting/src/test/groovy/org/apache/polygene/library/scripting/HelloSpeakerTest.java
+tag=script
+----
diff --git a/libraries/scripting/src/docs/javascript.txt b/libraries/scripting/src/docs/javascript.txt
new file mode 100644
index 0000000..493e5a9
--- /dev/null
+++ b/libraries/scripting/src/docs/javascript.txt
@@ -0,0 +1,42 @@
+///////////////////////////////////////////////////////////////
+ * 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.
+///////////////////////////////////////////////////////////////
+
+[[javascript, Scripting with JavaScript]]
+== Javascript ==
+
+In Javascript, we map directly to JS functions with the same name.
+
+For the following Polygene composite type,
+
+[snippet,java]
+----
+source=libraries/scripting/src/test/java/org/apache/polygene/library/scripting/HelloSpeaker.java
+tag=speaker
+----
+
+
+we need a implementation in a resource file (visible on classpath) named +org/apache/polygene/library/scripting/HelloSpeaker.js+
+that looks like this;
+
+[snippet,javascript]
+----
+source=libraries/scripting/src/test/resources/org/apache/polygene/library/scripting/HelloSpeaker.js
+tag=script
+----
+
diff --git a/libraries/scripting/src/docs/scripting.txt b/libraries/scripting/src/docs/scripting.txt
new file mode 100644
index 0000000..90f481a
--- /dev/null
+++ b/libraries/scripting/src/docs/scripting.txt
@@ -0,0 +1,99 @@
+///////////////////////////////////////////////////////////////
+ * 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.
+///////////////////////////////////////////////////////////////
+
+[[scripting, Scripting Library]]
+= Scripting =
+
+[devstatus]
+--------------
+source=libraries/scripting/dev-status.xml
+--------------
+
+The Scripting Library allows Mixin methods to be implemented in any JSR-223 scripting language, loaded dynamically on
+first use and allowing reloading of the script in runtime.
+
+include::../../build/docs/buildinfo/artifact.txt[]
+
+The Scripting Library is a Generic mixin class that implements
+Composite interfaces by delegating to script functions using Java Scripting API. All Java Scripting API (JSR-223)
+implementations that support
+
+[source,java]
+----
+    ((javax.script.Invocable) scriptEngine).invokeFunction( functionName, arguments );
+----
+
+should be supported. On Java.Net there is a https://java.net/projects/scripting/sources/svn/show/trunk/engines[list of Java Scripting API languages].
+
+
+It is important to understand that the ScriptEngines must be present on the classpath, or they will not be available,
+with the exception of JavaScript which uses the built-in Nashorn engine.
+
+We welcome additional information and samples of languages that has been tried and tested.
+
+.Language Support
+[options="header"]
+|=======
+|Language | Supported | Tested | License | Implementation
+|JavaScript | Yes | Yes | ? |Nashorn, built-in Java 8 and later
+|Groovy | Yes | Yes |Apache |Apache Groovy
+|Ruby | Yes | No |(EPL\|GPL\|LGPL) + Ruby |JRuby
+|Python | Yes | No |https://opensource.org/licenses/Python-2.0[Python] |Jython, must use jython-standalone
+|Kotlin | Yes | No |Apache |Jetbrains
+|Lua | Yes | No |MIT |luaj.org,
+|Clojure | Yes | No |CPL |https://github.com/pmf/clojure-jsr223
+|=======
+
+The following languages may or may not be supported, and was found at https://java.net/projects/scripting/sources/svn/show/trunk/engines[Java.Net Scripting project]
+
+.Potential Languages
+[options="header"]
+|=======
+| Language | Location | License
+|beanshell | |
+|ejs | |
+|freemarker |https://freemarker.apache.org | Apache
+|jacl | |
+|jaskell |https://github.com/MarchLiu/jaskell | MIT
+|jawk | |
+|jelly | |Apache
+|jep | |
+|jexl |https://commons.apache.org/jexl/ | Apache
+|jst | |
+|judo | |
+|juel | |
+|ognl |https://commons.apache.org/ognl/ | Apache
+|pnuts | |
+|scheme |http://sisc-scheme.org/ | (MPLv1.1|GPLv2)
+|velocity |https://velocity.apache.org | Apache
+|xpath | |
+|xslt | |
+|=======
+
+.Not Compatible Languages
+[options="header"]
+|=======
+| Language | Comment
+| Java | Implementation exists at https://github.com/nickman/javax-scripting/ which is forked from https://java.net/projects/scripting. It doesn't support Invocable, and additional work on ScriptMixin is required to support this. Alternatively, fork the ScriptEngine implementation and support Invocable in it.
+|=======
+
+include::../../../../libraries/scripting/src/docs/javascript.txt[]
+
+include::../../../../libraries/scripting/src/docs/groovy.txt[]
+
diff --git a/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/ScriptAttributes.java b/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/ScriptAttributes.java
new file mode 100644
index 0000000..c2c0cd4
--- /dev/null
+++ b/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/ScriptAttributes.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.polygene.library.scripting;
+
+/**
+ * ScriptAttributes is the interface into the attributes of the underlying
+ * scripting engine.
+ */
+public interface ScriptAttributes
+{
+    /**
+     * Fetch the value of the named attribute.
+     * <p>
+     *     If the attribute name is found in ENGINE scope, it is returned. If it is not in the ENGINE scope,
+     *     then the value is fetched from GLOBAL scope. If not present in either scope, NULL is returned.
+     * </p>
+     * @param name The name of the attribute to get, or null if not found.
+     * @return The value of the attribute.
+     */
+    Object getAttribute( String name );
+
+    /**
+     * This interface is for accessing both ENGINE and GLOBAL scopes with precision.
+     */
+    interface All
+    {
+        Object getEngineAttribute( String name );
+
+        Object getGlobalAttribute( String name );
+
+        void setEngineAttribute( String name, Object value );
+
+        void setGlobalAttribute( String name, Object value );
+    }
+}
diff --git a/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/ScriptException.java b/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/ScriptException.java
new file mode 100644
index 0000000..80e425a
--- /dev/null
+++ b/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/ScriptException.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.scripting;
+
+public class ScriptException extends RuntimeException
+{
+    public ScriptException( String message )
+    {
+        super( message );
+    }
+
+    public ScriptException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/ScriptMixin.java b/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/ScriptMixin.java
new file mode 100644
index 0000000..651303f
--- /dev/null
+++ b/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/ScriptMixin.java
@@ -0,0 +1,239 @@
+/*
+ *  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.polygene.library.scripting;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.Writer;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import javax.script.Bindings;
+import javax.script.Invocable;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.spi.PolygeneSPI;
+
+public class ScriptMixin
+    implements InvocationHandler, ScriptReloadable, ScriptRedirect, ScriptAttributes, ScriptAttributes.All
+{
+    private final CompositeDescriptor descriptor;
+    private ScriptEngine engine;
+
+    public ScriptMixin( @Structure PolygeneSPI spi,
+                        @This Object thisComposite,
+                        @State StateHolder state,
+                        @Structure Layer layer,
+                        @Structure Module module,
+                        @Structure Application application )
+    {
+        descriptor = spi.compositeDescriptorFor( thisComposite );
+        engine = createNewEngine();
+        Bindings mixinBindings = engine.getBindings( ScriptContext.ENGINE_SCOPE );
+        mixinBindings.put( "Polygene", spi );
+        mixinBindings.put( "application", application );
+        mixinBindings.put( "layer", layer );
+        mixinBindings.put( "module", module );
+        mixinBindings.put( "This", thisComposite );
+        mixinBindings.put( "state", state );
+        mixinBindings.put( "objectFactory", module.objectFactory() );
+        mixinBindings.put( "unitOfWorkFactory", module.unitOfWorkFactory() );
+        mixinBindings.put( "valueBuilderFactory", module.valueBuilderFactory() );
+        mixinBindings.put( "transientBuilderFactory", module.transientBuilderFactory() );
+        mixinBindings.put( "serviceFinder", module.serviceFinder() );
+        mixinBindings.put( "typeLookup", module.typeLookup() );
+    }
+
+    private ScriptEngine createNewEngine()
+    {
+        Scripting scripting = descriptor.metaInfo( Scripting.class );
+        ScriptEngine engine = getScriptEngine( scripting );
+        String scriptName = descriptor.primaryType().getName().replaceAll( "\\.", "/" ) + scripting.extension();
+        try( BufferedReader reader = new BufferedReader( new InputStreamReader( getClass().getClassLoader().getResourceAsStream( scriptName ) ) ) )
+        {
+            engine.eval( reader );
+        }
+        catch( IOException e )
+        {
+            throw new ScriptException( "Unable to load " + scriptName + " for " + descriptor, e );
+        }
+        catch( javax.script.ScriptException e )
+        {
+            throw new ScriptException( "Unable to parse " + scriptName + ".", e );
+        }
+        return engine;
+    }
+
+    private ScriptEngine getScriptEngine( Scripting scripting )
+    {
+        ScriptEngineManager manager = new ScriptEngineManager( getClass().getClassLoader() );
+        String engineName = scripting.engine();
+        ScriptEngine engine;
+        if( engineName != null )
+        {
+            engine = manager.getEngineByName( engineName );
+        }
+        else
+        {
+            engine = manager.getEngineByExtension( scripting.extension() );
+        }
+        if( engine == null )
+        {
+            throw new ScriptException( "Engine " + scripting + " is not available. Perhaps missing implementation on the classpath." );
+        }
+        return engine;
+    }
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] objects )
+        throws Throwable
+    {
+        Object result = ( (Invocable) engine ).invokeFunction( method.getName(), objects );
+        return castInvocationResult( method.getReturnType(), result );
+    }
+
+    @Override
+    public void reloadScript()
+    {
+        engine = createNewEngine();
+    }
+
+    @Override
+    public void setStdOut( Writer writer )
+    {
+        writer = wrap( writer );
+        engine.getContext().setWriter( writer );
+    }
+
+    @Override
+    public void setStdErr( Writer writer )
+    {
+        engine.getContext().setErrorWriter( writer );
+    }
+
+    @Override
+    public void setStdIn( Reader reader )
+    {
+        if( !( reader instanceof BufferedReader ) )
+        {
+            reader = new BufferedReader( reader );
+        }
+        engine.getContext().setReader( reader );
+    }
+
+    private Writer wrap( Writer writer )
+    {
+        if( writer instanceof BufferedWriter )
+        {
+            return writer;
+        }
+        return new BufferedWriter( writer );
+    }
+
+    @Override
+    public Object getAttribute( String name )
+    {
+        return engine.getContext().getAttribute( name );
+    }
+
+    @Override
+    public Object getEngineAttribute( String name )
+    {
+        return engine.getContext().getAttribute( name, ScriptContext.ENGINE_SCOPE );
+    }
+
+    @Override
+    public Object getGlobalAttribute( String name )
+    {
+        return engine.getContext().getAttribute( name, ScriptContext.GLOBAL_SCOPE );
+    }
+
+    @Override
+    public void setEngineAttribute( String name, Object value )
+    {
+        engine.getContext().setAttribute( name, value, ScriptContext.ENGINE_SCOPE );
+    }
+
+    @Override
+    public void setGlobalAttribute( String name, Object value )
+    {
+        engine.getContext().setAttribute( name, value, ScriptContext.GLOBAL_SCOPE );
+    }
+
+    /**
+     * Needed to prevent class cast exception between boxed and unboxed types.
+     * Explicit casting to primitive type, triggers the auto-unboxing compiler trick.
+     */
+    @SuppressWarnings( "RedundantCast" )
+    private static Object castInvocationResult( Class<?> returnType, Object result )
+    {
+        if( void.class.equals( returnType ) || Void.class.equals( returnType ) )
+        {
+            return null;
+        }
+        if( returnType.isPrimitive() )
+        {
+            if( char.class.equals( returnType ) )
+            {
+                return (char) result;
+            }
+            if( boolean.class.equals( returnType ) )
+            {
+                return (boolean) result;
+            }
+            if( short.class.equals( returnType ) )
+            {
+                return result.getClass().isPrimitive() ? result : ( (Number) result ).shortValue();
+            }
+            if( int.class.equals( returnType ) )
+            {
+                return result.getClass().isPrimitive() ? result : ( (Number) result ).intValue();
+            }
+            if( byte.class.equals( returnType ) )
+            {
+                return result.getClass().isPrimitive() ? result : ( (Number) result ).byteValue();
+            }
+            if( long.class.equals( returnType ) )
+            {
+                return result.getClass().isPrimitive() ? result : ( (Number) result ).longValue();
+            }
+            if( float.class.equals( returnType ) )
+            {
+                return result.getClass().isPrimitive() ? result : ( (Number) result ).floatValue();
+            }
+            if( double.class.equals( returnType ) )
+            {
+                return result.getClass().isPrimitive() ? result : ( (Number) result ).doubleValue();
+            }
+        }
+        return returnType.cast( result );
+    }
+}
diff --git a/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/ScriptRedirect.java b/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/ScriptRedirect.java
new file mode 100644
index 0000000..834999f
--- /dev/null
+++ b/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/ScriptRedirect.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.library.scripting;
+
+import java.io.Reader;
+import java.io.Writer;
+
+public interface ScriptRedirect
+{
+    void setStdOut( Writer writer );
+    void setStdErr( Writer writer );
+    void setStdIn( Reader reader );
+}
diff --git a/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/ScriptReloadable.java b/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/ScriptReloadable.java
new file mode 100644
index 0000000..d2753f9
--- /dev/null
+++ b/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/ScriptReloadable.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.library.scripting;
+
+public interface ScriptReloadable
+{
+    void reloadScript();
+}
diff --git a/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/Scripting.java b/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/Scripting.java
new file mode 100644
index 0000000..ad97b42
--- /dev/null
+++ b/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/Scripting.java
@@ -0,0 +1,74 @@
+/*
+ *  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.polygene.library.scripting;
+
+import javax.script.ScriptEngineManager;
+
+// START SNIPPET: supported
+public class Scripting
+{
+    public static final Scripting ECMASCRIPT = new Scripting( "nashorn", ".js" );
+    public static final Scripting GROOVY = new Scripting( "groovy", ".groovy" );
+    public static final Scripting JAVASCRIPT = new Scripting( "nashorn", ".js" );
+    public static final Scripting KOTLIN = new Scripting( "kotlin", ".kts" );
+    public static final Scripting LUA = new Scripting( "lua", ".lua" );
+    public static final Scripting PYTHON = new Scripting( "python", ".py" );
+    public static final Scripting RUBY = new Scripting( "jruby", ".rb" );
+    // END SNIPPET: supported
+
+    private String scriptEngine;
+    private String extension;
+
+    public Scripting( String extension )
+    {
+        this.extension = extension;
+    }
+
+    public Scripting( String scriptEngine, String extension )
+    {
+        this.scriptEngine = scriptEngine;
+        this.extension = extension;
+    }
+
+    public String engine()
+    {
+        return scriptEngine;
+    }
+
+    public String extension()
+    {
+        return extension;
+    }
+
+    @Override
+    public String toString()
+    {
+        if( scriptEngine == null )
+        {
+            return "for script extension '" + extension + "'";
+        }
+        return "'" + scriptEngine + "'";
+    }
+
+    public static void main( String[] args )
+    {
+        new ScriptEngineManager().getEngineFactories().forEach( factory -> System.out.println(factory));
+    }
+}
diff --git a/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/package.html b/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/package.html
new file mode 100644
index 0000000..dd862a0
--- /dev/null
+++ b/libraries/scripting/src/main/java/org/apache/polygene/library/scripting/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Scripting Library.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/scripting/src/main/java/org/qi4j/library/scripting/ScriptException.java b/libraries/scripting/src/main/java/org/qi4j/library/scripting/ScriptException.java
deleted file mode 100644
index 4c4b5fd..0000000
--- a/libraries/scripting/src/main/java/org/qi4j/library/scripting/ScriptException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.scripting;
-
-public class ScriptException extends RuntimeException
-{
-    public ScriptException( String message )
-    {
-        super( message );
-    }
-}
diff --git a/libraries/scripting/src/main/java/org/qi4j/library/scripting/ScriptReloadable.java b/libraries/scripting/src/main/java/org/qi4j/library/scripting/ScriptReloadable.java
deleted file mode 100644
index 79877f2..0000000
--- a/libraries/scripting/src/main/java/org/qi4j/library/scripting/ScriptReloadable.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.scripting;
-
-public interface ScriptReloadable
-{
-    void reloadScripts();
-}
diff --git a/libraries/scripting/src/main/java/org/qi4j/library/scripting/ScriptUtil.java b/libraries/scripting/src/main/java/org/qi4j/library/scripting/ScriptUtil.java
deleted file mode 100644
index 72edf3d..0000000
--- a/libraries/scripting/src/main/java/org/qi4j/library/scripting/ScriptUtil.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg
- * Licensed 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.qi4j.library.scripting;
-
-import java.io.PrintStream;
-import org.qi4j.api.mixin.Mixins;
-
-/**
- * JAVADOC
- */
-@Mixins( ScriptUtilImpl.class )
-public interface ScriptUtil
-{
-    PrintStream getOut();
-}
diff --git a/libraries/scripting/src/main/java/org/qi4j/library/scripting/ScriptUtilImpl.java b/libraries/scripting/src/main/java/org/qi4j/library/scripting/ScriptUtilImpl.java
deleted file mode 100644
index 6cbe7cc..0000000
--- a/libraries/scripting/src/main/java/org/qi4j/library/scripting/ScriptUtilImpl.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2007 Rickard Öberg
- * Licensed 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.qi4j.library.scripting;
-
-import java.io.PrintStream;
-
-/**
- * JAVADOC
- */
-public class ScriptUtilImpl
-    implements ScriptUtil
-{
-    @Override
-    public PrintStream getOut()
-    {
-        return System.out;
-    }
-}
diff --git a/libraries/scripting/src/main/java/org/qi4j/library/scripting/package.html b/libraries/scripting/src/main/java/org/qi4j/library/scripting/package.html
deleted file mode 100644
index fa4c48c..0000000
--- a/libraries/scripting/src/main/java/org/qi4j/library/scripting/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Scripting Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/scripting/src/test/groovy/org/apache/polygene/library/scripting/HelloSpeakerMixin.groovy b/libraries/scripting/src/test/groovy/org/apache/polygene/library/scripting/HelloSpeakerMixin.groovy
new file mode 100644
index 0000000..ad3113b
--- /dev/null
+++ b/libraries/scripting/src/test/groovy/org/apache/polygene/library/scripting/HelloSpeakerMixin.groovy
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.scripting;
+
+// START SNIPPET: direct
+class HelloSpeakerMixin
+    implements HelloSpeaker
+{
+
+    String sayHello() {
+        "Hello there, Groovy"
+    }
+}
+// END SNIPPET: direct
diff --git a/libraries/scripting/src/test/groovy/org/apache/polygene/library/scripting/HelloSpeakerTest.java b/libraries/scripting/src/test/groovy/org/apache/polygene/library/scripting/HelloSpeakerTest.java
new file mode 100644
index 0000000..6ae5436
--- /dev/null
+++ b/libraries/scripting/src/test/groovy/org/apache/polygene/library/scripting/HelloSpeakerTest.java
@@ -0,0 +1,75 @@
+/*
+ *  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.polygene.library.scripting;
+
+import org.junit.Test;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class HelloSpeakerTest extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+    }
+
+    @Test
+    public void testGroovyScriptResourceMixin()
+        throws Exception
+    {
+        // START SNIPPET: script
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.values( HelloSpeaker.class ).setMetaInfo( Scripting.GROOVY ).withMixins( ScriptMixin.class );
+            }
+        };
+        HelloSpeaker speaker = assembler.module().newValue( HelloSpeaker.class );
+        assertThat( speaker.sayHello(), equalTo("Hello, Groovy") );
+        // END SNIPPET: script
+    }
+
+    @Test
+    public void testGroovyClassMixin()
+        throws Exception
+    {
+        // START SNIPPET: direct
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( HelloSpeaker.class ).withMixins( HelloSpeakerMixin.class );
+            }
+        };
+        HelloSpeaker speaker = assembler.module().newTransient( HelloSpeaker.class );
+        assertThat( speaker.sayHello(), equalTo("Hello there, Groovy") );
+        // END SNIPPET: direct
+    }
+}
diff --git a/libraries/scripting/src/test/groovy/org/apache/polygene/library/scripting/SimpleSpeaker.groovy b/libraries/scripting/src/test/groovy/org/apache/polygene/library/scripting/SimpleSpeaker.groovy
new file mode 100644
index 0000000..69e5cfe
--- /dev/null
+++ b/libraries/scripting/src/test/groovy/org/apache/polygene/library/scripting/SimpleSpeaker.groovy
@@ -0,0 +1,26 @@
+/*
+ *  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.polygene.library.scripting
+
+// START SNIPPET: script
+def sayHello() {
+    "Hello, Groovy"
+}
+// END SNIPPET: script
diff --git a/libraries/scripting/src/test/java/org/apache/polygene/library/scripting/DomainType.java b/libraries/scripting/src/test/java/org/apache/polygene/library/scripting/DomainType.java
new file mode 100644
index 0000000..e9fb746
--- /dev/null
+++ b/libraries/scripting/src/test/java/org/apache/polygene/library/scripting/DomainType.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.library.scripting;
+
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.structure.TypeLookup;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+public interface DomainType
+{
+
+    String do1( String message );
+
+    double count();
+
+    void inc();
+
+    Object whatIsThis();
+
+    StateHolder whatIsState();
+
+    Application whatIsApplication();
+
+    Layer whatIsLayer();
+
+    Module whatIsModule();
+
+    ObjectFactory whatIsObjectFactory();
+
+    UnitOfWorkFactory whatIsUnitOfWorkFactory();
+
+    ValueBuilderFactory whatIsValueBuilderFactory();
+
+    TransientBuilderFactory whatIsTransientBuilderFactory();
+
+    ServiceFinder whatIsServiceFinder();
+
+    TypeLookup whatIsTypeLookup();
+}
\ No newline at end of file
diff --git a/libraries/scripting/src/test/java/org/apache/polygene/library/scripting/HelloSpeaker.java b/libraries/scripting/src/test/java/org/apache/polygene/library/scripting/HelloSpeaker.java
new file mode 100644
index 0000000..9e36ea1
--- /dev/null
+++ b/libraries/scripting/src/test/java/org/apache/polygene/library/scripting/HelloSpeaker.java
@@ -0,0 +1,33 @@
+/*
+ *  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.
+ *
+ *
+ */
+// START SNIPPET: speaker
+package org.apache.polygene.library.scripting;
+// END SNIPPET: speaker
+
+import org.apache.polygene.api.mixin.Mixins;
+
+// START SNIPPET: speaker
+
+@Mixins(ScriptMixin.class)
+public interface HelloSpeaker
+{
+    String sayHello();
+}
+// END SNIPPET: speaker
diff --git a/libraries/scripting/src/test/java/org/apache/polygene/library/scripting/ScriptMixinTest.java b/libraries/scripting/src/test/java/org/apache/polygene/library/scripting/ScriptMixinTest.java
new file mode 100644
index 0000000..ba12e68
--- /dev/null
+++ b/libraries/scripting/src/test/java/org/apache/polygene/library/scripting/ScriptMixinTest.java
@@ -0,0 +1,139 @@
+/*
+ *  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.polygene.library.scripting;
+
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.structure.TypeLookup;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+
+public class ScriptMixinTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        LayerAssembly layer = module.layer();
+        layer.application().setName( "Script Test" );
+        module.transients( DomainType.class ).setMetaInfo( Scripting.JAVASCRIPT ).withMixins( ScriptMixin.class );
+        module.transients( HelloSpeaker.class ).setMetaInfo( Scripting.GROOVY ).withMixins( ScriptMixin.class );
+        module.values( HelloSpeaker.class ).setMetaInfo( Scripting.JAVASCRIPT ).withMixins( ScriptMixin.class );
+    }
+
+    @Test
+    public void testInvoke() throws Throwable
+    {
+        DomainType domain1 = transientBuilderFactory.newTransient( DomainType.class );
+        assertThat(domain1.do1("her message"), equalTo("[her message]") );
+    }
+
+    @Test
+    public void testIsolation() throws Throwable
+    {
+        DomainType domain1 = transientBuilderFactory.newTransient( DomainType.class );
+        DomainType domain2 = transientBuilderFactory.newTransient( DomainType.class );
+        DomainType domain3 = transientBuilderFactory.newTransient( DomainType.class );
+        assertThat(domain1.do1("her message"), equalTo("[her message]") );
+        assertThat(domain2.do1("his message"), equalTo("[his message]") );
+        assertThat(domain3.do1("its message"), equalTo("[its message]") );
+        domain1.inc();
+        domain1.inc();
+        domain1.inc();
+        domain1.inc();
+        domain2.inc();
+        domain2.inc();
+        domain2.inc();
+        domain3.inc();
+        assertThat(domain1.count(), equalTo(4.0D) );
+        assertThat(domain2.count(), equalTo(3.0D) );
+        assertThat(domain3.count(), equalTo(1.0D) );
+    }
+
+    @Test
+    public void testBindings() {
+        DomainType domain = transientBuilderFactory.newTransient( DomainType.class );
+
+        Object _this = domain.whatIsThis();
+        assertThat( _this, instanceOf(DomainType.class));
+        assertThat( _this, instanceOf(TransientComposite.class ) );
+
+        StateHolder state = domain.whatIsState( );
+        assertThat( state.properties(), notNullValue());
+
+        Application app  = domain.whatIsApplication( );
+        assertThat( app.name(), equalTo("Script Test"));
+
+        Layer layer = domain.whatIsLayer();
+        assertThat( layer.name(), equalTo("Layer 1"));
+
+        Module module = domain.whatIsModule();
+        assertThat( module.name(), equalTo("Module 1"));
+
+        ObjectFactory of = domain.whatIsObjectFactory( );
+        assertThat( of, notNullValue());
+
+        UnitOfWorkFactory uowf = domain.whatIsUnitOfWorkFactory( );
+        assertThat( uowf, notNullValue());
+
+        ValueBuilderFactory vbf = domain.whatIsValueBuilderFactory( );
+        assertThat( vbf, notNullValue());
+
+        TransientBuilderFactory tbf = domain.whatIsTransientBuilderFactory( );
+        assertThat( tbf, notNullValue());
+
+        ServiceFinder finder = domain.whatIsServiceFinder( );
+        assertThat( finder, notNullValue());
+
+        TypeLookup lookup = domain.whatIsTypeLookup( );
+        assertThat( lookup, notNullValue());
+    }
+
+
+    @Test
+    public void testJavascriptInvoke() throws Exception
+    {
+        HelloSpeaker speaker = valueBuilderFactory.newValue( HelloSpeaker.class );
+        assertThat(speaker.sayHello(), equalTo("Hello, JavaScript"));
+    }
+
+    @Test
+    public void testGroovyInvoke() throws Exception
+    {
+        HelloSpeaker speaker = transientBuilderFactory.newTransient( HelloSpeaker.class );
+        assertThat(speaker.sayHello(), equalTo("Hello, Groovy"));
+    }
+}
\ No newline at end of file
diff --git a/libraries/scripting/src/test/java/org/qi4j/library/scripting/ScriptUtilImplTest.java b/libraries/scripting/src/test/java/org/qi4j/library/scripting/ScriptUtilImplTest.java
deleted file mode 100644
index 4b99809..0000000
--- a/libraries/scripting/src/test/java/org/qi4j/library/scripting/ScriptUtilImplTest.java
+++ /dev/null
@@ -1,40 +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.qi4j.library.scripting;
-
-import org.junit.Test;
-
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
-
-public class ScriptUtilImplTest
-{
-    @Test
-    public void testDefaultStream()
-    {
-        ScriptUtil underTest = new ScriptUtilImpl();
-        assertThat( underTest.getOut(), equalTo(System.out));
-    }
-
-    @Test( expected = ScriptException.class )
-    public void testException()
-    {
-        throw new ScriptException( "This is a test exception." );
-    }
-}
diff --git a/libraries/scripting/src/test/resources/org/apache/polygene/library/scripting/DomainType.js b/libraries/scripting/src/test/resources/org/apache/polygene/library/scripting/DomainType.js
new file mode 100644
index 0000000..7e84d61
--- /dev/null
+++ b/libraries/scripting/src/test/resources/org/apache/polygene/library/scripting/DomainType.js
@@ -0,0 +1,78 @@
+/*
+ *  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.
+ *
+ *
+ */
+
+var counter = 0;
+
+function do1(message) {
+    return "[" + message + "]";
+}
+
+//noinspection JSUnusedGlobalSymbols
+function count() {
+    return counter;
+}
+
+function inc() {
+    return counter++;
+}
+
+function whatIsThis() {
+    return This;
+}
+
+function whatIsState() {
+    return state;
+}
+
+function whatIsApplication() {
+    return application;
+}
+
+function whatIsLayer() {
+    return layer;
+}
+
+function whatIsModule() {
+    return module;
+}
+
+function whatIsObjectFactory() {
+    return objectFactory;
+}
+
+function whatIsUnitOfWorkFactory() {
+    return unitOfWorkFactory;
+}
+
+function whatIsValueBuilderFactory() {
+    return valueBuilderFactory;
+}
+
+function whatIsTransientBuilderFactory() {
+    return transientBuilderFactory;
+}
+
+function whatIsServiceFinder() {
+    return serviceFinder;
+}
+
+function whatIsTypeLookup() {
+    return typeLookup;
+}
\ No newline at end of file
diff --git a/libraries/scripting/src/test/resources/org/apache/polygene/library/scripting/HelloSpeaker.groovy b/libraries/scripting/src/test/resources/org/apache/polygene/library/scripting/HelloSpeaker.groovy
new file mode 100644
index 0000000..69e5cfe
--- /dev/null
+++ b/libraries/scripting/src/test/resources/org/apache/polygene/library/scripting/HelloSpeaker.groovy
@@ -0,0 +1,26 @@
+/*
+ *  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.polygene.library.scripting
+
+// START SNIPPET: script
+def sayHello() {
+    "Hello, Groovy"
+}
+// END SNIPPET: script
diff --git a/libraries/scripting/src/test/resources/org/apache/polygene/library/scripting/HelloSpeaker.js b/libraries/scripting/src/test/resources/org/apache/polygene/library/scripting/HelloSpeaker.js
new file mode 100644
index 0000000..f5e29cf
--- /dev/null
+++ b/libraries/scripting/src/test/resources/org/apache/polygene/library/scripting/HelloSpeaker.js
@@ -0,0 +1,25 @@
+/*
+ *  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.
+ *
+ *
+ */
+
+// START SNIPPET: script
+function sayHello() {
+    return "Hello, JavaScript";
+}
+// END SNIPPET: script
diff --git a/libraries/servlet/build.gradle b/libraries/servlet/build.gradle
index 130afdb..2a128bf 100644
--- a/libraries/servlet/build.gradle
+++ b/libraries/servlet/build.gradle
@@ -1,35 +1,41 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Servlet Library provides integration of Apache Zest™ into web applications."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - Servlet" }}
+description = "Apache Polygene™ Servlet Library provides integration of Apache Polygene™ into web applications."
+
+jar { manifest { name = "Apache Polygene™ Library - Servlet" } }
 
 dependencies {
-  compile( project(":org.qi4j.core:org.qi4j.core.bootstrap") )
-  compile libraries.servlet_api 
-  compile libraries.slf4j_api
+  compileOnly libraries.servlet_api
 
-  testCompile( project(":org.qi4j.core:org.qi4j.core.testsupport") )
-  testCompile( libraries.jetty_webapp )
-  testCompile( libraries.http_client )
+  api polygene.core.bootstrap
 
-  testRuntime( project(":org.qi4j.core:org.qi4j.core.runtime") )
-  testRuntime(libraries.logback )
+  implementation libraries.slf4j_api
+
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+  testImplementation libraries.jetty_webapp
+  testImplementation libraries.http_client
+
+  testRuntimeOnly libraries.logback
 }
diff --git a/libraries/servlet/dev-status.xml b/libraries/servlet/dev-status.xml
index cbcd274..34f74ea 100644
--- a/libraries/servlet/dev-status.xml
+++ b/libraries/servlet/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
     <status>
         <!--none,early,beta,stable,mature-->
         <codebase>stable</codebase>
diff --git a/libraries/servlet/src/docs/servlet.txt b/libraries/servlet/src/docs/servlet.txt
index 4af90c1..1a66235 100644
--- a/libraries/servlet/src/docs/servlet.txt
+++ b/libraries/servlet/src/docs/servlet.txt
@@ -25,45 +25,45 @@
 source=libraries/servlet/dev-status.xml
 --------------
 
-This library provide the necessary boilerplate code to bootstrap a Zest™ Application in a Servlet container plus some
+This library provide the necessary boilerplate code to bootstrap a Polygene™ Application in a Servlet container plus some
 facilities. It aims at a very simple need and is provided as an example integration.
 
-If instead you want to run a servlet container inside a Zest™ Application, see <<library-http>>.
+If instead you want to run a servlet container inside a Polygene™ Application, see <<library-http>>.
 
 include::../../build/docs/buildinfo/artifact.txt[]
 
 == Application Bootstrap ==
 
-Extends `AbstractQi4jServletBootstrap` to easily bind a Zest™ `Application` activation/passivation to your webapp
+Extends `AbstractPolygeneServletBootstrap` to easily bind a Polygene™ `Application` activation/passivation to your webapp
 lifecycle.
 
-Use `Qi4jServletSupport#application(javax.servlet.ServletContext)` to get a handle on the `Application` from the
+Use `PolygeneServletSupport#application(javax.servlet.ServletContext)` to get a handle on the `Application` from the
 `ServletContext`.
 
 Here is an example ServletContextListener:
 
 [snippet,java]
 ----
-source=libraries/servlet/src/test/java/org/qi4j/library/servlet/ServletTest.java
+source=libraries/servlet/src/test/java/org/apache/polygene/library/servlet/ServletTest.java
 tag=bootstrap
 ----
 
 
 == Facilities ==
 
-`Qi4jServlet` and `Qi4jFilter` respectively provide base class for easy access to the `Application` from the
+`PolygeneServlet` and `PolygeneFilter` respectively provide base class for easy access to the `Application` from the
 `ServletContext`.
 
 Here is a sample servlet that simply output the assembled Application name:
 
 [snippet,java]
 ----
-source=libraries/servlet/src/test/java/org/qi4j/library/servlet/ServletTest.java
+source=libraries/servlet/src/test/java/org/apache/polygene/library/servlet/ServletTest.java
 tag=usage
 ----
 
 
 == Logging ==
 
-The SLF4J logger used by this library is named "org.qi4j.library.servlet".
+The SLF4J logger used by this library is named "org.apache.polygene.library.servlet".
 
diff --git a/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/PolygeneFilter.java b/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/PolygeneFilter.java
new file mode 100644
index 0000000..cd76212
--- /dev/null
+++ b/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/PolygeneFilter.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.library.servlet;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.library.servlet.lifecycle.AbstractPolygeneServletBootstrap;
+
+/**
+ * Base Filter providing easy access to the {@link Application} from the {@link ServletContext}.
+ * @see AbstractPolygeneServletBootstrap
+ */
+public abstract class PolygeneFilter
+        implements Filter
+{
+
+    private Application application;
+
+    @Override
+    public void init( FilterConfig filterConfig )
+            throws ServletException
+    {
+        application = PolygeneServletSupport.application( filterConfig.getServletContext() );
+    }
+
+    protected final Application application()
+    {
+        return application;
+    }
+
+}
diff --git a/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/PolygeneServlet.java b/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/PolygeneServlet.java
new file mode 100644
index 0000000..95835a5
--- /dev/null
+++ b/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/PolygeneServlet.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.library.servlet;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.library.servlet.lifecycle.AbstractPolygeneServletBootstrap;
+
+/**
+ * Base HttpServlet providing easy access to the {@link org.apache.polygene.api.structure.Application} from the
+ * {@link javax.servlet.ServletContext}.
+ *
+ * @see AbstractPolygeneServletBootstrap
+ */
+public class PolygeneServlet extends HttpServlet
+{
+
+    private Application application;
+
+    public PolygeneServlet()
+    {
+        super();
+    }
+
+    @Override
+    public void init()
+            throws ServletException
+    {
+        super.init();
+        application = PolygeneServletSupport.application( getServletContext() );
+    }
+
+    protected final Application application()
+    {
+        return application;
+    }
+
+}
diff --git a/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/PolygeneServletSupport.java b/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/PolygeneServletSupport.java
new file mode 100644
index 0000000..0b42323
--- /dev/null
+++ b/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/PolygeneServletSupport.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.servlet;
+
+import javax.servlet.ServletContext;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.library.servlet.lifecycle.AbstractPolygeneServletBootstrap;
+
+public final class PolygeneServletSupport
+{
+
+    public static final String APP_IN_CTX = "polygene-application-servlet-context-attribute";
+
+    /**
+     * @param servletContext    ServletContext
+     * @return                  The Application from the servlet context attribute previously set by {@link AbstractPolygeneServletBootstrap}
+     */
+    public static Application application( ServletContext servletContext )
+    {
+        return ( Application ) servletContext.getAttribute( APP_IN_CTX ); // TODO try/catch and find a suitable Polygene exception
+    }
+
+    private PolygeneServletSupport()
+    {
+    }
+
+}
diff --git a/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/lifecycle/AbstractPolygeneServletBootstrap.java b/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/lifecycle/AbstractPolygeneServletBootstrap.java
new file mode 100644
index 0000000..3a0ee39
--- /dev/null
+++ b/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/lifecycle/AbstractPolygeneServletBootstrap.java
@@ -0,0 +1,143 @@
+/*
+ *  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.polygene.library.servlet.lifecycle;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.common.InvalidApplicationException;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.library.servlet.PolygeneServlet;
+import org.apache.polygene.library.servlet.PolygeneServletSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract ServletContextListener implementing ApplicationAssembler.
+ *
+ * Extends this class to easily bind a Polygene Application activation/passivation to your webapp lifecycle.
+ *
+ * The {@link Application} is set as a {@link ServletContext} attribute named using a constant.
+ * In your servlets, filters, whatever has access to the {@link ServletContext} use the following code to get a
+ * handle on the {@link Application}:
+ *
+ * <pre>
+ *  org.apache.polygene.api.structure.Application application;
+ *
+ *  application = ( Application ) servletContext.getAttribute( PolygeneServletSupport.APP_IN_CTX );
+ *
+ *  // Or, shorter:
+ *
+ *  application = PolygeneServletSupport.application( servletContext );
+ *
+ * </pre>
+ *
+ * Rembember that the servlet specification states:
+ *
+ * In cases where the container is distributed over many virtual machines, a Web application will have an instance of
+ * the ServletContext for each JVM.
+ *
+ * Context attributes are local to the JVM in which they were created. This prevents ServletContext attributes from
+ * being a shared memory store in a distributed container. When information needs to be shared between servlets running
+ * in a distributed environment, the information should be placed into a session, stored in a database, or set in an
+ * Enterprise JavaBeans component.
+ */
+public abstract class AbstractPolygeneServletBootstrap
+        implements ServletContextListener, ApplicationAssembler
+{
+
+    private static final Logger LOGGER = LoggerFactory.getLogger( PolygeneServlet.class.getPackage().getName() );
+    // Polygene Runtime
+    protected PolygeneAPI api;
+    protected Energy4Java polygene;
+    // Polygene Application
+    protected ApplicationDescriptor applicationModel;
+    protected Application application;
+
+    @Override
+    public final void contextInitialized( ServletContextEvent sce )
+    {
+        try {
+
+            ServletContext context = sce.getServletContext();
+
+            LOGGER.trace( "Assembling Application" );
+            polygene = new Energy4Java();
+            applicationModel = polygene.newApplicationModel( this );
+
+            LOGGER.trace( "Instanciating and activating Application" );
+            application = applicationModel.newInstance( polygene.api() );
+            api = polygene.api();
+            beforeApplicationActivation( application );
+            application.activate();
+            afterApplicationActivation( application );
+
+            LOGGER.trace( "Storing Application in ServletContext" );
+            context.setAttribute( PolygeneServletSupport.APP_IN_CTX, application );
+
+        } catch ( Exception ex ) {
+            if ( application != null ) {
+                try {
+                    beforeApplicationPassivation( application );
+                    application.passivate();
+                    afterApplicationPassivation( application );
+                } catch ( Exception ex1 ) {
+                    LOGGER.warn( "Application not null and could not passivate it.", ex1 );
+                }
+            }
+            throw new InvalidApplicationException( "Unexpected error during ServletContext initialization, see previous log for errors.", ex );
+        }
+    }
+
+    protected void beforeApplicationActivation( Application app )
+    {
+    }
+
+    protected void afterApplicationActivation( Application app )
+    {
+    }
+
+    @Override
+    public final void contextDestroyed( ServletContextEvent sce )
+    {
+        try {
+            if ( application != null ) {
+                beforeApplicationPassivation( application );
+                application.passivate();
+                afterApplicationPassivation( application );
+            }
+        } catch ( Exception ex ) {
+            LOGGER.warn( "Unable to passivate Polygene Application.", ex );
+        }
+    }
+
+    protected void beforeApplicationPassivation( Application app )
+    {
+    }
+
+    protected void afterApplicationPassivation( Application app )
+    {
+    }
+
+}
diff --git a/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/lifecycle/package.html b/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/lifecycle/package.html
new file mode 100644
index 0000000..e3ad474
--- /dev/null
+++ b/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/lifecycle/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Servlet Context Lifecycle.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/package.html b/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/package.html
new file mode 100644
index 0000000..74456b5
--- /dev/null
+++ b/libraries/servlet/src/main/java/org/apache/polygene/library/servlet/package.html
@@ -0,0 +1,50 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Servlet Library.</h2>
+        <p>
+            This library provide the necessary mechanism to bootstrap a Polygene™ Application in a Servlet container plus
+            some facilities.
+        </p>
+
+        <h3>Logging</h3>
+        <p>
+            The SLF4J logger used by this library is named "org.apache.polygene.library.servlet".
+        </p>
+
+        <h3>Application Bootstrap</h3>
+        <p>
+            Extends {@link org.apache.polygene.library.servlet.lifecycle.AbstractPolygeneServletBootstrap} to easily bind a Polygene™
+            {@link org.apache.polygene.api.structure.Application} activation/passivation to your webapp lifecycle.
+        </p>
+        <p>
+            Use {@link org.apache.polygene.library.servlet.PolygeneServletSupport#application(javax.servlet.ServletContext)} to get
+            a handle on the {@link org.apache.polygene.api.structure.Application} from the {@link javax.servlet.ServletContext}.
+        </p>
+
+        <h3>Facilities</h3>
+        <p>
+            {@link org.apache.polygene.library.servlet.PolygeneServlet} and {@link org.apache.polygene.library.servlet.PolygeneFilter} respectively
+            provide base class for easy access to the {@link org.apache.polygene.api.structure.Application}} from the
+            {@link javax.servlet.ServletContext}.
+        </p>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/servlet/src/main/java/org/qi4j/library/servlet/Qi4jFilter.java b/libraries/servlet/src/main/java/org/qi4j/library/servlet/Qi4jFilter.java
deleted file mode 100644
index d215926..0000000
--- a/libraries/servlet/src/main/java/org/qi4j/library/servlet/Qi4jFilter.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.servlet;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import org.qi4j.api.structure.Application;
-import org.qi4j.library.servlet.lifecycle.AbstractQi4jServletBootstrap;
-
-/**
- * Base Filter providing easy access to the {@link Application} from the {@link ServletContext}.
- * @see AbstractQi4jServletBootstrap
- */
-public abstract class Qi4jFilter
-        implements Filter
-{
-
-    private Application application;
-
-    @Override
-    public void init( FilterConfig filterConfig )
-            throws ServletException
-    {
-        application = Qi4jServletSupport.application( filterConfig.getServletContext() );
-    }
-
-    protected final Application application()
-    {
-        return application;
-    }
-
-}
diff --git a/libraries/servlet/src/main/java/org/qi4j/library/servlet/Qi4jServlet.java b/libraries/servlet/src/main/java/org/qi4j/library/servlet/Qi4jServlet.java
deleted file mode 100644
index 0d8056b..0000000
--- a/libraries/servlet/src/main/java/org/qi4j/library/servlet/Qi4jServlet.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.servlet;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import org.qi4j.api.structure.Application;
-import org.qi4j.library.servlet.lifecycle.AbstractQi4jServletBootstrap;
-
-/**
- * Base HttpServlet providing easy access to the {@link org.qi4j.api.structure.Application} from the
- * {@link javax.servlet.ServletContext}.
- *
- * @see AbstractQi4jServletBootstrap
- */
-public class Qi4jServlet
-        extends HttpServlet
-{
-
-    private Application application;
-
-    public Qi4jServlet()
-    {
-        super();
-    }
-
-    @Override
-    public void init()
-            throws ServletException
-    {
-        super.init();
-        application = Qi4jServletSupport.application( getServletContext() );
-    }
-
-    protected final Application application()
-    {
-        return application;
-    }
-
-}
diff --git a/libraries/servlet/src/main/java/org/qi4j/library/servlet/Qi4jServletSupport.java b/libraries/servlet/src/main/java/org/qi4j/library/servlet/Qi4jServletSupport.java
deleted file mode 100644
index 3e404e4..0000000
--- a/libraries/servlet/src/main/java/org/qi4j/library/servlet/Qi4jServletSupport.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.servlet;
-
-import javax.servlet.ServletContext;
-import org.qi4j.api.structure.Application;
-import org.qi4j.library.servlet.lifecycle.AbstractQi4jServletBootstrap;
-
-public final class Qi4jServletSupport
-{
-
-    public static final String APP_IN_CTX = "qi4j-application-servlet-context-attribute";
-
-    /**
-     * @param servletContext    ServletContext
-     * @return                  The Application from the servlet context attribute previously set by {@link AbstractQi4jServletBootstrap}
-     */
-    public static Application application( ServletContext servletContext )
-    {
-        return ( Application ) servletContext.getAttribute( APP_IN_CTX ); // TODO try/catch and find a suitable Zest exception
-    }
-
-    private Qi4jServletSupport()
-    {
-    }
-
-}
diff --git a/libraries/servlet/src/main/java/org/qi4j/library/servlet/lifecycle/AbstractQi4jServletBootstrap.java b/libraries/servlet/src/main/java/org/qi4j/library/servlet/lifecycle/AbstractQi4jServletBootstrap.java
deleted file mode 100644
index 2a3607c..0000000
--- a/libraries/servlet/src/main/java/org/qi4j/library/servlet/lifecycle/AbstractQi4jServletBootstrap.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.servlet.lifecycle;
-
-import javax.servlet.ServletContext;
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.common.InvalidApplicationException;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.library.servlet.Qi4jServlet;
-import org.qi4j.library.servlet.Qi4jServletSupport;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Abstract ServletContextListener implementing ApplicationAssembler.
- *
- * Extends this class to easily bind a Zest Application activation/passivation to your webapp lifecycle.
- *
- * The {@link Application} is set as a {@link ServletContext} attribute named using a constant.
- * In your servlets, filters, whatever has access to the {@link ServletContext} use the following code to get a
- * handle on the {@link Application}:
- *
- * <pre>
- *  org.qi4j.api.structure.Application application;
- *
- *  application = ( Application ) servletContext.getAttribute( Qi4jServletSupport.APP_IN_CTX );
- *
- *  // Or, shorter:
- *
- *  application = Qi4jServletSupport.application( servletContext );
- *
- * </pre>
- *
- * Rembember that the servlet specification states:
- *
- * In cases where the container is distributed over many virtual machines, a Web application will have an instance of
- * the ServletContext for each JVM.
- *
- * Context attributes are local to the JVM in which they were created. This prevents ServletContext attributes from
- * being a shared memory store in a distributed container. When information needs to be shared between servlets running
- * in a distributed environment, the information should be placed into a session, stored in a database, or set in an
- * Enterprise JavaBeans component.
- */
-public abstract class AbstractQi4jServletBootstrap
-        implements ServletContextListener, ApplicationAssembler
-{
-
-    private static final Logger LOGGER = LoggerFactory.getLogger( Qi4jServlet.class.getPackage().getName() );
-    // Zest Runtime
-    protected Qi4j api;
-    protected Energy4Java qi4j;
-    // Zest Application
-    protected ApplicationDescriptor applicationModel;
-    protected Application application;
-
-    @Override
-    public final void contextInitialized( ServletContextEvent sce )
-    {
-        try {
-
-            ServletContext context = sce.getServletContext();
-
-            LOGGER.trace( "Assembling Application" );
-            qi4j = new Energy4Java();
-            applicationModel = qi4j.newApplicationModel( this );
-
-            LOGGER.trace( "Instanciating and activating Application" );
-            application = applicationModel.newInstance( qi4j.api() );
-            api = qi4j.api();
-            beforeApplicationActivation( application );
-            application.activate();
-            afterApplicationActivation( application );
-
-            LOGGER.trace( "Storing Application in ServletContext" );
-            context.setAttribute( Qi4jServletSupport.APP_IN_CTX, application );
-
-        } catch ( Exception ex ) {
-            if ( application != null ) {
-                try {
-                    beforeApplicationPassivation( application );
-                    application.passivate();
-                    afterApplicationPassivation( application );
-                } catch ( Exception ex1 ) {
-                    LOGGER.warn( "Application not null and could not passivate it.", ex1 );
-                }
-            }
-            throw new InvalidApplicationException( "Unexpected error during ServletContext initialization, see previous log for errors.", ex );
-        }
-    }
-
-    protected void beforeApplicationActivation( Application app )
-    {
-    }
-
-    protected void afterApplicationActivation( Application app )
-    {
-    }
-
-    @Override
-    public final void contextDestroyed( ServletContextEvent sce )
-    {
-        try {
-            if ( application != null ) {
-                beforeApplicationPassivation( application );
-                application.passivate();
-                afterApplicationPassivation( application );
-            }
-        } catch ( Exception ex ) {
-            LOGGER.warn( "Unable to passivate Zest Application.", ex );
-        }
-    }
-
-    protected void beforeApplicationPassivation( Application app )
-    {
-    }
-
-    protected void afterApplicationPassivation( Application app )
-    {
-    }
-
-}
diff --git a/libraries/servlet/src/main/java/org/qi4j/library/servlet/lifecycle/package.html b/libraries/servlet/src/main/java/org/qi4j/library/servlet/lifecycle/package.html
deleted file mode 100644
index b692009..0000000
--- a/libraries/servlet/src/main/java/org/qi4j/library/servlet/lifecycle/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Servlet Context Lifecycle.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/servlet/src/main/java/org/qi4j/library/servlet/package.html b/libraries/servlet/src/main/java/org/qi4j/library/servlet/package.html
deleted file mode 100644
index edc745e..0000000
--- a/libraries/servlet/src/main/java/org/qi4j/library/servlet/package.html
+++ /dev/null
@@ -1,47 +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.
--->
-<html>
-    <body>
-        <h2>Servlet Library.</h2>
-        <p>
-            This library provide the necessary mechanism to bootstrap a Zest™ Application in a Servlet container plus
-            some facilities.
-        </p>
-
-        <h3>Logging</h3>
-        <p>
-            The SLF4J logger used by this library is named "org.qi4j.library.servlet".
-        </p>
-
-        <h3>Application Bootstrap</h3>
-        <p>
-            Extends {@link org.qi4j.library.servlet.lifecycle.AbstractQi4jServletBootstrap} to easily bind a Zest™
-            {@link org.qi4j.api.structure.Application} activation/passivation to your webapp lifecycle.
-        </p>
-        <p>
-            Use {@link org.qi4j.library.servlet.Qi4jServletSupport#application(javax.servlet.ServletContext)} to get
-            a handle on the {@link org.qi4j.api.structure.Application} from the {@link javax.servlet.ServletContext}.
-        </p>
-
-        <h3>Facilities</h3>
-        <p>
-            {@link org.qi4j.library.servlet.Qi4jServlet} and {@link org.qi4j.library.servlet.Qi4jFilter} respectively
-            provide base class for easy access to the {@link org.qi4j.api.structure.Application}} from the
-            {@link javax.servlet.ServletContext}.
-        </p>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/servlet/src/test/java/org/apache/polygene/library/servlet/ServletTest.java b/libraries/servlet/src/test/java/org/apache/polygene/library/servlet/ServletTest.java
new file mode 100644
index 0000000..e16e24f
--- /dev/null
+++ b/libraries/servlet/src/test/java/org/apache/polygene/library/servlet/ServletTest.java
@@ -0,0 +1,115 @@
+/*
+ *  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.polygene.library.servlet;
+
+import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.BasicResponseHandler;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.servlet.lifecycle.AbstractPolygeneServletBootstrap;
+import org.apache.polygene.test.util.FreePortFinder;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ServletTest
+{
+
+    private static final String APP_NAME = "FooApplication";
+
+    // START SNIPPET: bootstrap
+    public static class FooServletContextListener
+            extends AbstractPolygeneServletBootstrap
+    {
+
+        public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+                throws AssemblyException
+        {
+            ApplicationAssembly appass = applicationFactory.newApplicationAssembly();
+            // END SNIPPET: bootstrap
+            // Assemble your application here
+            appass.setName( APP_NAME );
+            ModuleAssembly module = appass.layer( "Layer 1" ).module( "Module 1" );
+            module.transients( UselessComposite.class );
+            // START SNIPPET: bootstrap
+            return appass;
+        }
+
+    }
+    // END SNIPPET: bootstrap
+
+    public interface UselessComposite
+    {
+    }
+
+    // START SNIPPET: usage
+    public static class FooServlet
+            extends PolygeneServlet
+    {
+
+        @Override
+        protected void doGet( HttpServletRequest req, HttpServletResponse resp )
+                throws ServletException, IOException
+        {
+            // Output the assembled Application's name as an example
+            resp.getWriter().println( application().name() );
+        }
+
+    }
+    // END SNIPPET: usage
+
+    @Test
+    public void test()
+            throws Exception
+    {
+        int port = FreePortFinder.findFreePortOnLoopback();
+        Server server = new Server( port );
+        try {
+
+            ServletContextHandler context = new ServletContextHandler();
+            context.setContextPath( "/" );
+            context.addEventListener( new FooServletContextListener() );
+            context.addServlet( FooServlet.class, "/*" );
+
+            server.setHandler( context );
+            server.start();
+
+            try( CloseableHttpClient client = HttpClientBuilder.create().build() )
+            {
+                String result = client.execute( new HttpGet( "http://127.0.0.1:" + port + "/" ),
+                                                new BasicResponseHandler() );
+                Assert.assertEquals( APP_NAME, result.trim() );
+            }
+
+        } finally {
+            server.stop();
+        }
+    }
+
+}
diff --git a/libraries/servlet/src/test/java/org/qi4j/library/servlet/ServletTest.java b/libraries/servlet/src/test/java/org/qi4j/library/servlet/ServletTest.java
deleted file mode 100644
index 0fc635d..0000000
--- a/libraries/servlet/src/test/java/org/qi4j/library/servlet/ServletTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin.
- *
- * Licensed 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.qi4j.library.servlet;
-
-import java.io.IOException;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.BasicResponseHandler;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.ApplicationAssemblyFactory;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.servlet.lifecycle.AbstractQi4jServletBootstrap;
-import org.qi4j.test.util.FreePortFinder;
-
-public class ServletTest
-{
-
-    private static final String APP_NAME = "FooApplication";
-
-    // START SNIPPET: bootstrap
-    public static class FooServletContextListener
-            extends AbstractQi4jServletBootstrap
-    {
-
-        public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-                throws AssemblyException
-        {
-            ApplicationAssembly appass = applicationFactory.newApplicationAssembly();
-            // END SNIPPET: bootstrap
-            // Assemble your application here
-            appass.setName( APP_NAME );
-            ModuleAssembly module = appass.layer( "Layer 1" ).module( "Module 1" );
-            module.transients( UselessComposite.class );
-            // START SNIPPET: bootstrap
-            return appass;
-        }
-
-    }
-    // END SNIPPET: bootstrap
-
-    public interface UselessComposite
-    {
-    }
-
-    // START SNIPPET: usage
-    public static class FooServlet
-            extends Qi4jServlet
-    {
-
-        @Override
-        protected void doGet( HttpServletRequest req, HttpServletResponse resp )
-                throws ServletException, IOException
-        {
-            // Output the assembled Application's name as an example
-            resp.getWriter().println( application().name() );
-        }
-
-    }
-    // END SNIPPET: usage
-
-    @Test
-    public void test()
-            throws Exception
-    {
-        int port = FreePortFinder.findFreePortOnLoopback( 9001 );
-        Server server = new Server( port );
-        try {
-
-            ServletContextHandler context = new ServletContextHandler();
-            context.setContextPath( "/" );
-            context.addEventListener( new FooServletContextListener() );
-            context.addServlet( FooServlet.class, "/*" );
-
-            server.setHandler( context );
-            server.start();
-
-            HttpClient client = new DefaultHttpClient();
-            String result = client.execute( new HttpGet( "http://127.0.0.1:" + port + "/" ), new BasicResponseHandler() );
-            Assert.assertEquals( APP_NAME, result.trim() );
-
-        } finally {
-            server.stop();
-        }
-    }
-
-}
diff --git a/libraries/shiro-core/build.gradle b/libraries/shiro-core/build.gradle
index d57ac77..6bbf3ac 100644
--- a/libraries/shiro-core/build.gradle
+++ b/libraries/shiro-core/build.gradle
@@ -1,41 +1,43 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Shiro Library integrates Apache Shiro security framework into Apache Zest™."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - Shiro Core" }}
+description = "Apache Polygene™ Shiro Library integrates Apache Shiro security framework into Apache Polygene™."
+
+jar { manifest { name = "Apache Polygene™ Library - Shiro Core" } }
 
 dependencies {
+  api polygene.core.bootstrap
+  api libraries.shiro
 
-  compile project( ":org.qi4j.core:org.qi4j.core.bootstrap" )
-  compile libraries.shiro
-  compile libraries.bouncy_castle
-  compile libraries.slf4j_api
+  implementation libraries.bouncy_castle
 
-  testCompile project( ":org.qi4j.core:org.qi4j.core.testsupport" )
-  testCompile project( ":org.qi4j.libraries:org.qi4j.library.shiro-web" )
-  testCompile project( ":org.qi4j.libraries:org.qi4j.library.servlet" )
-  testCompile project( ":org.qi4j.extensions:org.qi4j.extension.indexing-rdf" )
-  testCompile libraries.jetty_webapp
-  testCompile libraries.http_client
+  runtimeOnly polygene.core.runtime
 
-  testRuntime project( ":org.qi4j.core:org.qi4j.core.runtime" )
-  testRuntime libraries.logback
+  testImplementation polygene.core.testsupport
+  testImplementation polygene.library( 'shiro-web' )
+  testImplementation polygene.library( 'servlet' )
+  testImplementation polygene.extension( 'indexing-rdf' )
+  testImplementation libraries.jetty_webapp
+  testImplementation libraries.http_client
 
+  testRuntimeOnly libraries.logback
 }
diff --git a/libraries/shiro-core/dev-status.xml b/libraries/shiro-core/dev-status.xml
index cbcd274..34f74ea 100644
--- a/libraries/shiro-core/dev-status.xml
+++ b/libraries/shiro-core/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
     <status>
         <!--none,early,beta,stable,mature-->
         <codebase>stable</codebase>
diff --git a/libraries/shiro-core/src/docs/shiro.txt b/libraries/shiro-core/src/docs/shiro.txt
index a12a3e7..fd35a05 100644
--- a/libraries/shiro-core/src/docs/shiro.txt
+++ b/libraries/shiro-core/src/docs/shiro.txt
@@ -35,25 +35,25 @@
 application – from the smallest mobile applications to the largest web and enterprise applications.'' says the Apache
 Shiro website.
 
-Altough Apache Shiro can be used as-is with Zest™ Applications, this library provides integrations that can come in
+Altough Apache Shiro can be used as-is with Polygene™ Applications, this library provides integrations that can come in
 handy. If your use case do not fit any of theses integrations, look at their respective code. You should find out
 pretty easily how to compose the provided code to write your integration. Don't hesitate to contribute interesting
 integrations to this very library.
 
 We invite you to read the comprehensive http://shiro.apache.org/documentation.html[Apache Shiro documentation], we will
-mostly discuss Zest™ related matters here.
+mostly discuss Polygene™ related matters here.
 
 include::../../build/docs/buildinfo/artifact.txt[]
 
 == Basic usage ==
 
 For standalone applications, you can use plain Shiro easily. The only thing to do is to register a configured
-SecurityManager when activating your Zest™ Application. It can be done outside the application, before its activation,
+SecurityManager when activating your Polygene™ Application. It can be done outside the application, before its activation,
 "à là" by-hand ;
 
 [snippet,java]
 ----
-source=libraries/shiro-core/src/test/java/org/qi4j/library/shiro/StandaloneShiroTest.java
+source=libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/StandaloneShiroTest.java
 tag=before
 ----
 
@@ -64,7 +64,7 @@
 
 [snippet,java]
 ----
-source=libraries/shiro-core/src/test/java/org/qi4j/library/shiro/StandaloneShiroTest.java
+source=libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/StandaloneShiroTest.java
 tag=assembly
 ----
 
@@ -72,20 +72,20 @@
 
 [snippet,java]
 ----
-source=libraries/shiro-core/src/main/java/org/qi4j/library/shiro/ini/ShiroIniConfiguration.java
+source=libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/ini/ShiroIniConfiguration.java
 tag=config
 ----
 
 Remember that this setup use a ThreadLocal SecurityManager singleton. Among other things it means that, althoug the
 IniSecurityManagerService is activated on Application activation, if you need to use Shiro in other Services that are
-activated on Application activation you should tell Zest™ about this dependency by injecting the SecurityManagerService
+activated on Application activation you should tell Polygene™ about this dependency by injecting the SecurityManagerService
 in the laters.
 
 Once started you must remember to register the SecurityManager in Shiro's ThreadContext ;
 
 [snippet,java]
 ----
-source=libraries/shiro-core/src/test/java/org/qi4j/library/shiro/StandaloneShiroTest.java
+source=libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/StandaloneShiroTest.java
 tag=thread-context
 ----
 
@@ -116,17 +116,17 @@
 
 All the above is sufficient as long as you use the ini file to store user credentials and permissions or a Realm that
 has no dependency on your application code and can be specified in the ini file to be instanciated by Shiro outside the
-Zest™ scope.
+Polygene™ scope.
 
 One usecase where it's not sufficient comes quickly as you would like to provide user credentials and permissions
-from Entities stored in an EntityStore or perform any custom logic involving your Zest™ Application.
+from Entities stored in an EntityStore or perform any custom logic involving your Polygene™ Application.
 
 Let's look at a complete example using a Realm Service that extends one of the Shiro provided Realm which use in-memory
 credientials and configuring it ;
 
 [snippet,java]
 ----
-source=libraries/shiro-core/src/test/java/org/qi4j/library/shiro/RealmServiceTest.java
+source=libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/RealmServiceTest.java
 tag=realm-service
 ----
 
@@ -164,7 +164,7 @@
 
 [snippet,java]
 ----
-source=libraries/shiro-core/src/test/java/org/qi4j/library/shiro/PasswordDomainTest.java
+source=libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/PasswordDomainTest.java
 tag=domain
 ----
 
@@ -173,7 +173,7 @@
 
 [snippet,java]
 ----
-source=libraries/shiro-core/src/test/java/org/qi4j/library/shiro/PasswordDomainTest.java
+source=libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/PasswordDomainTest.java
 tag=assembly
 ----
 
@@ -181,7 +181,7 @@
 
 [snippet,java]
 ----
-source=libraries/shiro-core/src/test/java/org/qi4j/library/shiro/PasswordDomainTest.java
+source=libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/PasswordDomainTest.java
 tag=usage
 ----
 
@@ -190,7 +190,7 @@
 
 [snippet,java]
 ----
-source=libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/passwords/PasswordRealmConfiguration.java
+source=libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/passwords/PasswordRealmConfiguration.java
 tag=config
 ----
 
@@ -206,7 +206,7 @@
 
 [snippet,java]
 ----
-source=libraries/shiro-core/src/test/java/org/qi4j/library/shiro/PermissionsDomainTest.java
+source=libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/PermissionsDomainTest.java
 tag=domain
 ----
 
@@ -214,7 +214,7 @@
 
 [snippet,java]
 ----
-source=libraries/shiro-core/src/test/java/org/qi4j/library/shiro/PermissionsDomainTest.java
+source=libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/PermissionsDomainTest.java
 tag=assembly
 ----
 
@@ -222,7 +222,7 @@
 
 [snippet,java]
 ----
-source=libraries/shiro-core/src/test/java/org/qi4j/library/shiro/PermissionsDomainTest.java
+source=libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/PermissionsDomainTest.java
 tag=usage
 ----
 
@@ -235,10 +235,14 @@
 
 Take the PasswordRealmService as a start and extend/rewrite it to suit your needs.
 
-If you happen to come with a Zest™ integration that could be valuable in this very library, don't hesitate to
+If you happen to come with a Polygene™ integration that could be valuable in this very library, don't hesitate to
 contribute.
 
 
 == Logging ==
 
-All code from this library use the `org.qi4j.library.shiro` logger.
+All code from this library use the `org.apache.polygene.library.shiro` logger.
+
+
+
+
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/Shiro.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/Shiro.java
new file mode 100644
index 0000000..8646637
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/Shiro.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.shiro;
+
+public interface Shiro
+{
+
+    String LOGGER_NAME = Shiro.class.getPackage().getName();
+
+    String DEFAULT_INI_RESOURCE_PATH = "classpath:shiro.ini";
+
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/assembly/PasswordDomainAssembler.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/assembly/PasswordDomainAssembler.java
new file mode 100644
index 0000000..67be79e
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/assembly/PasswordDomainAssembler.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.library.shiro.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.library.shiro.domain.passwords.PasswordRealmConfiguration;
+import org.apache.polygene.library.shiro.domain.passwords.PasswordRealmService;
+import org.apache.polygene.library.shiro.domain.passwords.PasswordSecurable;
+
+public class PasswordDomainAssembler
+    extends Assemblers.VisibilityIdentityConfig<PasswordDomainAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( PasswordSecurable.class ).visibleIn( visibility() );
+        ServiceDeclaration service = module.services( PasswordRealmService.class ).
+            instantiateOnStartup().
+            visibleIn( visibility() );
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+        if( hasConfig() )
+        {
+            configModule().entities( PasswordRealmConfiguration.class ).
+                visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/assembly/PermissionsDomainAssembler.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/assembly/PermissionsDomainAssembler.java
new file mode 100644
index 0000000..086749c
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/assembly/PermissionsDomainAssembler.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.library.shiro.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.shiro.domain.permissions.Role;
+import org.apache.polygene.library.shiro.domain.permissions.RoleAssignee;
+import org.apache.polygene.library.shiro.domain.permissions.RoleAssignment;
+import org.apache.polygene.library.shiro.domain.permissions.RoleFactory;
+
+public class PermissionsDomainAssembler
+    extends Assemblers.Visibility<PermissionsDomainAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( Role.class, RoleAssignment.class, RoleAssignee.class ).
+            visibleIn( visibility() );
+        module.services( RoleFactory.class ).
+            visibleIn( visibility() );
+    }
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/assembly/StandaloneShiroAssembler.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/assembly/StandaloneShiroAssembler.java
new file mode 100644
index 0000000..2f35ea0
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/assembly/StandaloneShiroAssembler.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.library.shiro.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.library.shiro.ini.IniSecurityManagerService;
+import org.apache.polygene.library.shiro.ini.ShiroIniConfiguration;
+
+public class StandaloneShiroAssembler
+    extends Assemblers.VisibilityIdentityConfig<StandaloneShiroAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( IniSecurityManagerService.class ).
+            visibleIn( visibility() ).
+            instantiateOnStartup();
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+        if( hasConfig() )
+        {
+            configModule().entities( ShiroIniConfiguration.class ).
+                visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/assembly/package.html b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/assembly/package.html
new file mode 100644
index 0000000..0025078
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Shiro Security Assembly.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/RequiresAuthentication.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/RequiresAuthentication.java
new file mode 100644
index 0000000..71c4344
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/RequiresAuthentication.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.shiro.concerns;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.injection.InjectionScope;
+
+@Target( ElementType.METHOD )
+@Retention( RetentionPolicy.RUNTIME )
+@Documented
+@InjectionScope
+public @interface RequiresAuthentication
+{
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/RequiresGuest.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/RequiresGuest.java
new file mode 100644
index 0000000..aa407bc
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/RequiresGuest.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.shiro.concerns;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.injection.InjectionScope;
+
+@Target( ElementType.METHOD )
+@Retention( RetentionPolicy.RUNTIME )
+@Documented
+@InjectionScope
+public @interface RequiresGuest
+{
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/RequiresPermissions.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/RequiresPermissions.java
new file mode 100644
index 0000000..72805ec
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/RequiresPermissions.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.library.shiro.concerns;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.injection.InjectionScope;
+
+@Target( ElementType.METHOD )
+@Retention( RetentionPolicy.RUNTIME )
+@Documented
+@InjectionScope
+public @interface RequiresPermissions
+{
+
+    /**
+     * The permission string which will be passed to {@link org.apache.shiro.subject.Subject#isPermitted(String)}
+     * to determine if the user is allowed to invoke the code protected by this annotation.
+     */
+    String value();
+
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/RequiresRoles.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/RequiresRoles.java
new file mode 100644
index 0000000..e5220d8
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/RequiresRoles.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.library.shiro.concerns;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.injection.InjectionScope;
+
+@Target( ElementType.METHOD )
+@Retention( RetentionPolicy.RUNTIME )
+@Documented
+@InjectionScope
+public @interface RequiresRoles
+{
+
+    /**
+     * A single String role name or multiple comma-delimitted role names required in order for the method
+     * invocation to be allowed.
+     */
+    String value();
+
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/RequiresUser.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/RequiresUser.java
new file mode 100644
index 0000000..b787b21
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/RequiresUser.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.shiro.concerns;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.injection.InjectionScope;
+
+@Target( ElementType.METHOD )
+@Retention( RetentionPolicy.RUNTIME )
+@Documented
+@InjectionScope
+public @interface RequiresUser
+{
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/SecurityConcern.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/SecurityConcern.java
new file mode 100644
index 0000000..cd50f5e
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/SecurityConcern.java
@@ -0,0 +1,184 @@
+/*
+ *  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.polygene.library.shiro.concerns;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authz.UnauthenticatedException;
+import org.apache.shiro.authz.UnauthorizedException;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.util.PermissionUtils;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.injection.scope.Invocation;
+import org.apache.polygene.library.shiro.Shiro;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@AppliesTo( { RequiresAuthentication.class,
+              RequiresGuest.class,
+              RequiresPermissions.class,
+              RequiresRoles.class,
+              RequiresUser.class } )
+public class SecurityConcern
+        extends ConcernOf<InvocationHandler>
+        implements InvocationHandler
+{
+
+    private static final Logger LOGGER = LoggerFactory.getLogger( Shiro.LOGGER_NAME );
+
+    @Optional
+    @Invocation
+    private RequiresAuthentication requiresAuthentication;
+
+    @Optional
+    @Invocation
+    private RequiresGuest requiresGuest;
+
+    @Optional
+    @Invocation
+    private RequiresPermissions requiresPermissions;
+
+    @Optional
+    @Invocation
+    private RequiresRoles requiresRoles;
+
+    @Optional
+    @Invocation
+    private RequiresUser requiresUser;
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+    {
+        Subject subject = SecurityUtils.getSubject();
+
+        handleRequiresGuest( subject );
+        handleRequiresUser( subject );
+        handleRequiresAuthentication( subject );
+        handleRequiresRoles( subject );
+        handleRequiresPermissions( subject );
+
+        return next.invoke( proxy, method, args );
+    }
+
+    private void handleRequiresGuest( Subject subject )
+    {
+        if ( requiresGuest != null ) {
+            LOGGER.debug( "SecurityConcern::RequiresGuest" );
+            if ( subject.getPrincipal() != null ) {
+                throw new UnauthenticatedException(
+                        "Attempting to perform a guest-only operation. The current Subject is "
+                        + "not a guest (they have been authenticated or remembered from a previous login).  Access "
+                        + "denied." );
+
+            }
+        } else {
+            LOGGER.debug( "SecurityConcern::RequiresGuest: not concerned" );
+        }
+    }
+
+    private void handleRequiresUser( Subject subject )
+    {
+        if ( requiresUser != null ) {
+            LOGGER.debug( "SecurityConcern::RequiresUser" );
+            if ( subject.getPrincipal() == null ) {
+                throw new UnauthenticatedException(
+                        "Attempting to perform a user-only operation. The current Subject is "
+                        + "not a user (they haven't been authenticated or remembered from a previous login).  "
+                        + "Access denied." );
+            }
+        } else {
+            LOGGER.debug( "SecurityConcern::RequiresUser: not concerned" );
+        }
+    }
+
+    private void handleRequiresAuthentication( Subject subject )
+    {
+        if ( requiresAuthentication != null ) {
+            LOGGER.debug( "SecurityConcern::RequiresAuthentication" );
+            if ( !subject.isAuthenticated() ) {
+                throw new UnauthenticatedException( "The current Subject is not authenticated.  Access denied." );
+            }
+        } else {
+            LOGGER.debug( "SecurityConcern::RequiresAuthentication: not concerned" );
+        }
+    }
+
+    private void handleRequiresRoles( Subject subject )
+    {
+        if ( requiresRoles != null ) {
+            LOGGER.debug( "SecurityConcern::RequiresRoles" );
+            String roleId = requiresRoles.value();
+            String[] roles = roleId.split( "," );
+            if ( roles.length == 1 ) {
+                if ( !subject.hasRole( roles[ 0] ) ) {
+                    String msg = "Calling Subject does not have required role [" + roleId + "].  "
+                                 + "MethodInvocation denied.";
+                    throw new UnauthorizedException( msg );
+                }
+            } else {
+                Set<String> rolesSet = new LinkedHashSet<String>( Arrays.asList( roles ) );
+                if ( !subject.hasAllRoles( rolesSet ) ) {
+                    String msg = "Calling Subject does not have required roles [" + roleId + "].  "
+                                 + "MethodInvocation denied.";
+                    throw new UnauthorizedException( msg );
+                }
+            }
+        } else {
+            LOGGER.debug( "SecurityConcern::RequiresRoles: not concerned" );
+        }
+
+    }
+
+    private void handleRequiresPermissions( Subject subject )
+    {
+        if ( requiresPermissions != null ) {
+            LOGGER.debug( "SecurityConcern::RequiresPermissions" );
+            String permsString = requiresPermissions.value();
+            Set<String> permissions = PermissionUtils.toPermissionStrings( permsString );
+            if ( permissions.size() == 1 ) {
+                if ( !subject.isPermitted( permissions.iterator().next() ) ) {
+                    String msg = "Calling Subject does not have required permission [" + permsString + "].  "
+                                 + "Method invocation denied.";
+                    throw new UnauthorizedException( msg );
+                }
+            } else {
+                String[] permStrings = new String[ permissions.size() ];
+                permStrings = permissions.toArray( permStrings );
+                if ( !subject.isPermittedAll( permStrings ) ) {
+                    String msg = "Calling Subject does not have required permissions [" + permsString + "].  "
+                                 + "Method invocation denied.";
+                    throw new UnauthorizedException( msg );
+                }
+
+            }
+        } else {
+            LOGGER.debug( "SecurityConcern::RequiresPermissions: not concerned" );
+        }
+
+    }
+
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/package.html b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/package.html
new file mode 100644
index 0000000..00ebac0
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/concerns/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Shiro Security Concerns.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/common/IdentifiableSubject.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/common/IdentifiableSubject.java
new file mode 100644
index 0000000..39f27a1
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/common/IdentifiableSubject.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.library.shiro.domain.common;
+
+import org.apache.polygene.api.property.Property;
+
+public interface IdentifiableSubject
+{
+    Property<String> subjectIdentifier();
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/common/package.html b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/common/package.html
new file mode 100644
index 0000000..3f350c8
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/common/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Shiro Security Common Domain.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/passwords/PasswordRealmConfiguration.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/passwords/PasswordRealmConfiguration.java
new file mode 100644
index 0000000..8ddeb5a
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/passwords/PasswordRealmConfiguration.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.shiro.domain.passwords;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+
+public interface PasswordRealmConfiguration
+{
+    // START SNIPPET: config
+    /**
+     * Sets the name of the MessageDigest algorithm that will be used to compute hashes.
+     */
+    @Optional
+    Property<String> hashAlgorithmName();
+
+    /**
+     * Sets the number of hash iterations that will be performed during hash computation.
+     */
+    @Optional
+    Property<Integer> hashIterationsCount();
+    // END SNIPPET: config
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/passwords/PasswordRealmMixin.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/passwords/PasswordRealmMixin.java
new file mode 100644
index 0000000..80e2196
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/passwords/PasswordRealmMixin.java
@@ -0,0 +1,189 @@
+/*
+ *  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.polygene.library.shiro.domain.passwords;
+
+import java.util.Set;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.SimpleAuthenticationInfo;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.authc.credential.DefaultPasswordService;
+import org.apache.shiro.authc.credential.PasswordMatcher;
+import org.apache.shiro.authc.credential.PasswordService;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.Authorizer;
+import org.apache.shiro.authz.SimpleAuthorizationInfo;
+import org.apache.shiro.crypto.hash.DefaultHashService;
+import org.apache.shiro.realm.AuthorizingRealm;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.library.shiro.Shiro;
+import org.apache.polygene.library.shiro.domain.permissions.RoleAssignee;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.polygene.api.query.QueryExpressions.eq;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+
+public class PasswordRealmMixin
+    extends AuthorizingRealm
+    implements Realm, Authorizer, PasswordService, ServiceActivation
+{
+
+    private static final Logger LOG = LoggerFactory.getLogger( Shiro.LOGGER_NAME );
+
+    @Structure
+    private UnitOfWorkFactory uowf;
+
+    @Structure
+    private QueryBuilderFactory qbf;
+
+    @This
+    private Configuration<PasswordRealmConfiguration> configuration;
+
+    private final DefaultPasswordService passwordService;
+
+    public PasswordRealmMixin()
+    {
+        super();
+        passwordService = new DefaultPasswordService();
+        PasswordMatcher matcher = new PasswordMatcher();
+        matcher.setPasswordService( passwordService );
+        setCredentialsMatcher( matcher );
+    }
+
+    @Override
+    public void activateService()
+        throws Exception
+    {
+        configuration.refresh();
+        PasswordRealmConfiguration config = configuration.get();
+        String algorithm = config.hashAlgorithmName().get();
+        Integer iterations = config.hashIterationsCount().get();
+        if( algorithm != null || iterations != null )
+        {
+            DefaultHashService hashService = (DefaultHashService) passwordService.getHashService();
+            if( algorithm != null )
+            {
+                hashService.setHashAlgorithmName( algorithm );
+            }
+            if( iterations != null )
+            {
+                hashService.setHashIterations( iterations );
+            }
+        }
+    }
+
+    @Override
+    public void passivateService()
+        throws Exception
+    {
+    }
+
+    @Override
+    public String encryptPassword( Object plaintextPassword )
+        throws IllegalArgumentException
+    {
+        return passwordService.encryptPassword( plaintextPassword );
+    }
+
+    @Override
+    public boolean passwordsMatch( Object submittedPlaintext, String encrypted )
+    {
+        return passwordService.passwordsMatch( submittedPlaintext, encrypted );
+    }
+
+    @Override
+    protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token )
+        throws AuthenticationException
+    {
+        UnitOfWork uow = uowf.newUnitOfWork();
+        try
+        {
+
+            String username = ( (UsernamePasswordToken) token ).getUsername();
+            PasswordSecurable account = findPasswordSecurable( uow, username );
+            if( account == null )
+            {
+                LOG.debug( "Unknown subject identifier: {}" + username );
+                return null;
+            }
+            LOG.debug( "Found account for {}: {}", username, account );
+            return new SimpleAuthenticationInfo( account.subjectIdentifier().get(), account.password()
+                .get(), getName() );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Override
+    protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals )
+    {
+        UnitOfWork uow = uowf.newUnitOfWork();
+        try
+        {
+
+            String username = getAvailablePrincipal( principals ).toString();
+            RoleAssignee roleAssignee = findRoleAssignee( uow, username );
+            if( roleAssignee == null )
+            {
+                LOG.debug( "No authorization info for {}", username );
+                return null;
+            }
+            LOG.debug( "Found role assignee for {}: {}", username, roleAssignee );
+            Set<String> roleNames = roleAssignee.roleNames();
+            Set<String> permissionStrings = roleAssignee.permissionStrings();
+            LOG.debug( "Found role assignee has the following roles: {}", roleNames );
+            LOG.debug( "Found role assignee has the following permissions: {}", permissionStrings );
+            SimpleAuthorizationInfo atzInfo = new SimpleAuthorizationInfo( roleNames );
+            atzInfo.setStringPermissions( permissionStrings );
+            return atzInfo;
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    private PasswordSecurable findPasswordSecurable( UnitOfWork uow, String username )
+    {
+        QueryBuilder<PasswordSecurable> builder = qbf.newQueryBuilder( PasswordSecurable.class );
+        builder = builder.where( eq( templateFor( PasswordSecurable.class ).subjectIdentifier(), username ) );
+        return uow.newQuery( builder ).find();
+    }
+
+    private RoleAssignee findRoleAssignee( UnitOfWork uow, String username )
+    {
+        QueryBuilder<RoleAssignee> builder = qbf.newQueryBuilder( RoleAssignee.class );
+        builder = builder.where( eq( templateFor( RoleAssignee.class ).subjectIdentifier(), username ) );
+        return uow.newQuery( builder ).find();
+    }
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/passwords/PasswordRealmService.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/passwords/PasswordRealmService.java
new file mode 100644
index 0000000..45c8e64
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/passwords/PasswordRealmService.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.shiro.domain.passwords;
+
+import org.apache.shiro.authc.credential.PasswordService;
+import org.apache.shiro.authz.Authorizer;
+import org.apache.shiro.realm.Realm;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+
+@Mixins( PasswordRealmMixin.class )
+public interface PasswordRealmService
+    extends Realm, Authorizer, PasswordService, ServiceActivation
+{
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/passwords/PasswordSecurable.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/passwords/PasswordSecurable.java
new file mode 100644
index 0000000..827d94e
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/passwords/PasswordSecurable.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.shiro.domain.passwords;
+
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.shiro.domain.common.IdentifiableSubject;
+
+public interface PasswordSecurable
+    extends IdentifiableSubject
+{
+    @Queryable( false )
+    Property<String> password();
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/passwords/package.html b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/passwords/package.html
new file mode 100644
index 0000000..90e8743
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/passwords/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Shiro Security Passwords Domain.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/permissions/Role.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/permissions/Role.java
new file mode 100644
index 0000000..fed39ec
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/permissions/Role.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.library.shiro.domain.permissions;
+
+import java.util.List;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+
+@Mixins( Role.Mixin.class )
+public interface Role
+    extends HasIdentity
+{
+    Property<String> name();
+
+    @UseDefaults
+    Property<List<String>> permissions();
+
+    RoleAssignment assignTo( RoleAssignee assignee );
+
+    abstract class Mixin
+        implements Role
+    {
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @This
+        private Role role;
+
+        @Override
+        public RoleAssignment assignTo( RoleAssignee assignee )
+        {
+            UnitOfWork uow = uowf.currentUnitOfWork();
+            EntityBuilder<RoleAssignment> builder = uow.newEntityBuilder( RoleAssignment.class );
+            RoleAssignment assignment = builder.instance();
+            assignment.assignee().set( assignee );
+            assignment.role().set( role );
+            assignment = builder.newInstance();
+            assignee.roleAssignments().add( assignment );
+            return assignment;
+        }
+    }
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/permissions/RoleAssignee.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/permissions/RoleAssignee.java
new file mode 100644
index 0000000..78b8f00
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/permissions/RoleAssignee.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.library.shiro.domain.permissions;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.Aggregated;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.library.shiro.domain.common.IdentifiableSubject;
+
+@Mixins( RoleAssignee.Mixin.class )
+public interface RoleAssignee
+    extends IdentifiableSubject, HasIdentity
+{
+    @Aggregated
+    @UseDefaults
+    ManyAssociation<RoleAssignment> roleAssignments();
+
+    Set<String> roleNames();
+
+    Set<String> permissionStrings();
+
+    abstract class Mixin
+            implements RoleAssignee
+    {
+        @This
+        private RoleAssignee roleAssignee;
+
+        @Override
+        public Set<String> roleNames()
+        {
+            Set<String> roleNames = new HashSet<>();
+            for ( RoleAssignment assignment : roleAssignee.roleAssignments() ) {
+                roleNames.add( assignment.role().get().name().get() );
+            }
+            return Collections.unmodifiableSet( roleNames );
+        }
+
+        @Override
+        public Set<String> permissionStrings()
+        {
+            Set<String> permissionStrings = new HashSet<>();
+            for ( RoleAssignment assignment : roleAssignee.roleAssignments() ) {
+                permissionStrings.addAll( assignment.role().get().permissions().get() );
+            }
+            return Collections.unmodifiableSet( permissionStrings );
+        }
+    }
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/permissions/RoleAssignment.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/permissions/RoleAssignment.java
new file mode 100644
index 0000000..3c5ccb8
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/permissions/RoleAssignment.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.shiro.domain.permissions;
+
+import org.apache.polygene.api.association.Association;
+
+public interface RoleAssignment
+{
+    Association<Role> role();
+
+    Association<RoleAssignee> assignee();
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/permissions/RoleFactory.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/permissions/RoleFactory.java
new file mode 100644
index 0000000..67f81a5
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/permissions/RoleFactory.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.library.shiro.domain.permissions;
+
+import java.util.Arrays;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+
+@Mixins( RoleFactory.Mixin.class )
+public interface RoleFactory
+{
+
+    Role create( String name, String... permissions );
+
+    Role create( String name, Iterable<String> permissions );
+
+    abstract class Mixin
+            implements RoleFactory
+    {
+
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @Override
+        public Role create( String name, String... permissions )
+        {
+            return create( name, Arrays.asList( permissions ) );
+        }
+
+        @Override
+        public Role create( String name, Iterable<String> permissions )
+        {
+            UnitOfWork uow = uowf.currentUnitOfWork();
+            EntityBuilder<Role> roleBuilder = uow.newEntityBuilder( Role.class );
+            Role role = roleBuilder.instance();
+            role.name().set( name );
+            permissions.forEach( p -> role.permissions().get().add( p ) );
+            return roleBuilder.newInstance();
+        }
+
+    }
+
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/permissions/package.html b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/permissions/package.html
new file mode 100644
index 0000000..d0258ea
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/domain/permissions/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Shiro Security Permissions Domain.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/ini/IniSecurityManagerService.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/ini/IniSecurityManagerService.java
new file mode 100644
index 0000000..ea24a8b
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/ini/IniSecurityManagerService.java
@@ -0,0 +1,110 @@
+/*
+ *  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.polygene.library.shiro.ini;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import org.apache.shiro.config.Ini;
+import org.apache.shiro.config.IniSecurityManagerFactory;
+import org.apache.shiro.mgt.RealmSecurityManager;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.util.ThreadContext;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.library.shiro.Shiro;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Mixins( IniSecurityManagerService.Mixin.class )
+public interface IniSecurityManagerService
+        extends ServiceActivation
+{
+
+    SecurityManager getSecurityManager();
+
+    class Mixin
+            extends IniSecurityManagerFactory
+            implements IniSecurityManagerService
+    {
+
+        private static final Logger LOG = LoggerFactory.getLogger( Shiro.LOGGER_NAME );
+
+        @This
+        private Configuration<ShiroIniConfiguration> configuration;
+
+        @Optional
+        @Service
+        private Iterable<ServiceReference<Realm>> realmsRefs;
+
+        private SecurityManager securityManager;
+
+        @Override
+        public void activateService()
+                throws Exception
+        {
+            configuration.refresh();
+            ShiroIniConfiguration config = configuration.get();
+
+            String iniResourcePath = config.iniResourcePath().get() == null
+                                     ? Shiro.DEFAULT_INI_RESOURCE_PATH
+                                     : config.iniResourcePath().get();
+
+            setIni( Ini.fromResourcePath( iniResourcePath ) );
+            securityManager = getInstance();
+
+            if ( realmsRefs != null && realmsRefs.iterator().hasNext() ) {
+
+                // Register Realms Services
+                RealmSecurityManager realmSecurityManager = ( RealmSecurityManager ) securityManager;
+                Collection<Realm> iniRealms = new ArrayList<>( realmSecurityManager.getRealms() );
+                for ( ServiceReference<Realm> realmRef : realmsRefs ) {
+                    iniRealms.add( realmRef.get() );
+                    LOG.debug( "Realm Service '{}' registered!", realmRef.identity() );
+                }
+                realmSecurityManager.setRealms( iniRealms );
+
+            }
+
+            ThreadContext.bind( securityManager );
+        }
+
+        @Override
+        public void passivateService()
+                throws Exception
+        {
+            ThreadContext.unbindSubject();
+            ThreadContext.unbindSecurityManager();
+        }
+
+        @Override
+        public SecurityManager getSecurityManager()
+        {
+            return securityManager;
+        }
+
+    }
+
+}
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/ini/ShiroIniConfiguration.java b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/ini/ShiroIniConfiguration.java
new file mode 100644
index 0000000..cec7e60
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/ini/ShiroIniConfiguration.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.shiro.ini;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+
+// START SNIPPET: config
+public interface ShiroIniConfiguration
+{
+    /**
+     * Resource path of the ini configuration file.
+     * "classpath:", "file": and "url:" prefixes are supported.
+     * Defaulted to "classpath:shiro.ini".
+     */
+    @Optional
+    Property<String> iniResourcePath();
+}
+// END SNIPPET: config
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/ini/package.html b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/ini/package.html
new file mode 100644
index 0000000..6ce108b
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/ini/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Shiro Security INI Configuration Support.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/package.html b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/package.html
new file mode 100644
index 0000000..680b8e3
--- /dev/null
+++ b/libraries/shiro-core/src/main/java/org/apache/polygene/library/shiro/package.html
@@ -0,0 +1,34 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Shiro Security Library.</h2>
+        <p>
+            This library provide integration with the
+            <a href="http://shiro.apache.org/" target="_blank">Apache Shiro</a> Java Security Framework.
+        </p>
+        <blockquote>
+            Apache Shiro is a powerful and easy-to-use Java security framework that performs authentication,
+            authorization, cryptography, and session management. With Shiro's easy-to-understand API, you can quickly
+            and easily secure any application – from the smallest mobile applications to the largest web and enterprise
+            applications.
+        </blockquote>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/Shiro.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/Shiro.java
deleted file mode 100644
index feefb85..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/Shiro.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro;
-
-public interface Shiro
-{
-
-    String LOGGER_NAME = Shiro.class.getPackage().getName();
-
-    String DEFAULT_INI_RESOURCE_PATH = "classpath:shiro.ini";
-
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/assembly/PasswordDomainAssembler.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/assembly/PasswordDomainAssembler.java
deleted file mode 100644
index 00ba4ab..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/assembly/PasswordDomainAssembler.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.assembly;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.library.shiro.domain.passwords.PasswordRealmConfiguration;
-import org.qi4j.library.shiro.domain.passwords.PasswordRealmService;
-import org.qi4j.library.shiro.domain.passwords.PasswordSecurable;
-
-public class PasswordDomainAssembler
-    extends Assemblers.VisibilityIdentityConfig<PasswordDomainAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( PasswordSecurable.class ).visibleIn( visibility() );
-        ServiceDeclaration service = module.services( PasswordRealmService.class ).
-            instantiateOnStartup().
-            visibleIn( visibility() );
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        if( hasConfig() )
-        {
-            configModule().entities( PasswordRealmConfiguration.class ).
-                visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/assembly/PermissionsDomainAssembler.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/assembly/PermissionsDomainAssembler.java
deleted file mode 100644
index c54c562..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/assembly/PermissionsDomainAssembler.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.assembly;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.shiro.domain.permissions.Role;
-import org.qi4j.library.shiro.domain.permissions.RoleAssignee;
-import org.qi4j.library.shiro.domain.permissions.RoleAssignment;
-import org.qi4j.library.shiro.domain.permissions.RoleFactory;
-
-public class PermissionsDomainAssembler
-    extends Assemblers.Visibility<PermissionsDomainAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( Role.class, RoleAssignment.class, RoleAssignee.class ).
-            visibleIn( visibility() );
-        module.services( RoleFactory.class ).
-            visibleIn( visibility() );
-    }
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/assembly/StandaloneShiroAssembler.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/assembly/StandaloneShiroAssembler.java
deleted file mode 100644
index 54fd7bb..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/assembly/StandaloneShiroAssembler.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2011, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.assembly;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.library.shiro.ini.IniSecurityManagerService;
-import org.qi4j.library.shiro.ini.ShiroIniConfiguration;
-
-public class StandaloneShiroAssembler
-    extends Assemblers.VisibilityIdentityConfig<StandaloneShiroAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ServiceDeclaration service = module.services( IniSecurityManagerService.class ).
-            visibleIn( visibility() ).
-            instantiateOnStartup();
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        if( hasConfig() )
-        {
-            configModule().entities( ShiroIniConfiguration.class ).
-                visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/assembly/package.html b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/assembly/package.html
deleted file mode 100644
index bd0dad6..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/assembly/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Shiro Security Assembly.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/RequiresAuthentication.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/RequiresAuthentication.java
deleted file mode 100644
index b3cd03f..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/RequiresAuthentication.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.concerns;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.qi4j.api.injection.InjectionScope;
-
-@Target( ElementType.METHOD )
-@Retention( RetentionPolicy.RUNTIME )
-@Documented
-@InjectionScope
-public @interface RequiresAuthentication
-{
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/RequiresGuest.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/RequiresGuest.java
deleted file mode 100644
index 316219a..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/RequiresGuest.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.concerns;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.qi4j.api.injection.InjectionScope;
-
-@Target( ElementType.METHOD )
-@Retention( RetentionPolicy.RUNTIME )
-@Documented
-@InjectionScope
-public @interface RequiresGuest
-{
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/RequiresPermissions.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/RequiresPermissions.java
deleted file mode 100644
index 5dd4e45..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/RequiresPermissions.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.concerns;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.qi4j.api.injection.InjectionScope;
-
-@Target( ElementType.METHOD )
-@Retention( RetentionPolicy.RUNTIME )
-@Documented
-@InjectionScope
-public @interface RequiresPermissions
-{
-
-    /**
-     * The permission string which will be passed to {@link org.apache.shiro.subject.Subject#isPermitted(String)}
-     * to determine if the user is allowed to invoke the code protected by this annotation.
-     */
-    String value();
-
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/RequiresRoles.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/RequiresRoles.java
deleted file mode 100644
index a7a379c..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/RequiresRoles.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.concerns;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.qi4j.api.injection.InjectionScope;
-
-@Target( ElementType.METHOD )
-@Retention( RetentionPolicy.RUNTIME )
-@Documented
-@InjectionScope
-public @interface RequiresRoles
-{
-
-    /**
-     * A single String role name or multiple comma-delimitted role names required in order for the method
-     * invocation to be allowed.
-     */
-    String value();
-
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/RequiresUser.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/RequiresUser.java
deleted file mode 100644
index 08df117..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/RequiresUser.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.concerns;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.qi4j.api.injection.InjectionScope;
-
-@Target( ElementType.METHOD )
-@Retention( RetentionPolicy.RUNTIME )
-@Documented
-@InjectionScope
-public @interface RequiresUser
-{
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/SecurityConcern.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/SecurityConcern.java
deleted file mode 100644
index e3bccf0..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/SecurityConcern.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.concerns;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.LinkedHashSet;
-import java.util.Set;
-import org.apache.shiro.SecurityUtils;
-import org.apache.shiro.authz.UnauthenticatedException;
-import org.apache.shiro.authz.UnauthorizedException;
-import org.apache.shiro.subject.Subject;
-import org.apache.shiro.util.PermissionUtils;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.injection.scope.Invocation;
-import org.qi4j.library.shiro.Shiro;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@AppliesTo( { RequiresAuthentication.class,
-              RequiresGuest.class,
-              RequiresPermissions.class,
-              RequiresRoles.class,
-              RequiresUser.class } )
-public class SecurityConcern
-        extends ConcernOf<InvocationHandler>
-        implements InvocationHandler
-{
-
-    private static final Logger LOGGER = LoggerFactory.getLogger( Shiro.LOGGER_NAME );
-
-    @Optional
-    @Invocation
-    private RequiresAuthentication requiresAuthentication;
-
-    @Optional
-    @Invocation
-    private RequiresGuest requiresGuest;
-
-    @Optional
-    @Invocation
-    private RequiresPermissions requiresPermissions;
-
-    @Optional
-    @Invocation
-    private RequiresRoles requiresRoles;
-
-    @Optional
-    @Invocation
-    private RequiresUser requiresUser;
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-    {
-        Subject subject = SecurityUtils.getSubject();
-
-        handleRequiresGuest( subject );
-        handleRequiresUser( subject );
-        handleRequiresAuthentication( subject );
-        handleRequiresRoles( subject );
-        handleRequiresPermissions( subject );
-
-        return next.invoke( proxy, method, args );
-    }
-
-    private void handleRequiresGuest( Subject subject )
-    {
-        if ( requiresGuest != null ) {
-            LOGGER.debug( "SecurityConcern::RequiresGuest" );
-            if ( subject.getPrincipal() != null ) {
-                throw new UnauthenticatedException(
-                        "Attempting to perform a guest-only operation. The current Subject is "
-                        + "not a guest (they have been authenticated or remembered from a previous login).  Access "
-                        + "denied." );
-
-            }
-        } else {
-            LOGGER.debug( "SecurityConcern::RequiresGuest: not concerned" );
-        }
-    }
-
-    private void handleRequiresUser( Subject subject )
-    {
-        if ( requiresUser != null ) {
-            LOGGER.debug( "SecurityConcern::RequiresUser" );
-            if ( subject.getPrincipal() == null ) {
-                throw new UnauthenticatedException(
-                        "Attempting to perform a user-only operation. The current Subject is "
-                        + "not a user (they haven't been authenticated or remembered from a previous login).  "
-                        + "Access denied." );
-            }
-        } else {
-            LOGGER.debug( "SecurityConcern::RequiresUser: not concerned" );
-        }
-    }
-
-    private void handleRequiresAuthentication( Subject subject )
-    {
-        if ( requiresAuthentication != null ) {
-            LOGGER.debug( "SecurityConcern::RequiresAuthentication" );
-            if ( !subject.isAuthenticated() ) {
-                throw new UnauthenticatedException( "The current Subject is not authenticated.  Access denied." );
-            }
-        } else {
-            LOGGER.debug( "SecurityConcern::RequiresAuthentication: not concerned" );
-        }
-    }
-
-    private void handleRequiresRoles( Subject subject )
-    {
-        if ( requiresRoles != null ) {
-            LOGGER.debug( "SecurityConcern::RequiresRoles" );
-            String roleId = requiresRoles.value();
-            String[] roles = roleId.split( "," );
-            if ( roles.length == 1 ) {
-                if ( !subject.hasRole( roles[ 0] ) ) {
-                    String msg = "Calling Subject does not have required role [" + roleId + "].  "
-                                 + "MethodInvocation denied.";
-                    throw new UnauthorizedException( msg );
-                }
-            } else {
-                Set<String> rolesSet = new LinkedHashSet<String>( Arrays.asList( roles ) );
-                if ( !subject.hasAllRoles( rolesSet ) ) {
-                    String msg = "Calling Subject does not have required roles [" + roleId + "].  "
-                                 + "MethodInvocation denied.";
-                    throw new UnauthorizedException( msg );
-                }
-            }
-        } else {
-            LOGGER.debug( "SecurityConcern::RequiresRoles: not concerned" );
-        }
-
-    }
-
-    private void handleRequiresPermissions( Subject subject )
-    {
-        if ( requiresPermissions != null ) {
-            LOGGER.debug( "SecurityConcern::RequiresPermissions" );
-            String permsString = requiresPermissions.value();
-            Set<String> permissions = PermissionUtils.toPermissionStrings( permsString );
-            if ( permissions.size() == 1 ) {
-                if ( !subject.isPermitted( permissions.iterator().next() ) ) {
-                    String msg = "Calling Subject does not have required permission [" + permsString + "].  "
-                                 + "Method invocation denied.";
-                    throw new UnauthorizedException( msg );
-                }
-            } else {
-                String[] permStrings = new String[ permissions.size() ];
-                permStrings = permissions.toArray( permStrings );
-                if ( !subject.isPermittedAll( permStrings ) ) {
-                    String msg = "Calling Subject does not have required permissions [" + permsString + "].  "
-                                 + "Method invocation denied.";
-                    throw new UnauthorizedException( msg );
-                }
-
-            }
-        } else {
-            LOGGER.debug( "SecurityConcern::RequiresPermissions: not concerned" );
-        }
-
-    }
-
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/package.html b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/package.html
deleted file mode 100644
index 2c1faf9..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/concerns/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Shiro Security Concerns.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/common/IdentifiableSubject.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/common/IdentifiableSubject.java
deleted file mode 100644
index 4f24cdb..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/common/IdentifiableSubject.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.domain.common;
-
-import org.qi4j.api.property.Property;
-
-public interface IdentifiableSubject
-{
-
-    Property<String> subjectIdentifier();
-
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/common/package.html b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/common/package.html
deleted file mode 100644
index 0b6ffb8..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/common/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Shiro Security Common Domain.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/passwords/PasswordRealmConfiguration.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/passwords/PasswordRealmConfiguration.java
deleted file mode 100644
index 544b558..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/passwords/PasswordRealmConfiguration.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.domain.passwords;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-public interface PasswordRealmConfiguration
-        extends ConfigurationComposite
-{
-
-    // START SNIPPET: config
-    /**
-     * Sets the name of the MessageDigest algorithm that will be used to compute hashes.
-     */
-    @Optional
-    Property<String> hashAlgorithmName();
-
-    /**
-     * Sets the number of hash iterations that will be performed during hash computation.
-     */
-    @Optional
-    Property<Integer> hashIterationsCount();
-    // END SNIPPET: config
-
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/passwords/PasswordRealmMixin.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/passwords/PasswordRealmMixin.java
deleted file mode 100644
index 3b43000..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/passwords/PasswordRealmMixin.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.domain.passwords;
-
-import java.util.Set;
-import org.apache.shiro.authc.AuthenticationException;
-import org.apache.shiro.authc.AuthenticationInfo;
-import org.apache.shiro.authc.AuthenticationToken;
-import org.apache.shiro.authc.SimpleAuthenticationInfo;
-import org.apache.shiro.authc.UsernamePasswordToken;
-import org.apache.shiro.authc.credential.DefaultPasswordService;
-import org.apache.shiro.authc.credential.PasswordMatcher;
-import org.apache.shiro.authc.credential.PasswordService;
-import org.apache.shiro.authz.AuthorizationInfo;
-import org.apache.shiro.authz.Authorizer;
-import org.apache.shiro.authz.SimpleAuthorizationInfo;
-import org.apache.shiro.crypto.hash.DefaultHashService;
-import org.apache.shiro.realm.AuthorizingRealm;
-import org.apache.shiro.realm.Realm;
-import org.apache.shiro.subject.PrincipalCollection;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.library.shiro.Shiro;
-import org.qi4j.library.shiro.domain.permissions.RoleAssignee;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.qi4j.api.query.QueryExpressions.eq;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-public class PasswordRealmMixin
-        extends AuthorizingRealm
-        implements Realm, Authorizer, PasswordService, ServiceActivation
-{
-
-    private static final Logger LOG = LoggerFactory.getLogger( Shiro.LOGGER_NAME );
-
-    @Structure
-    private Module module;
-
-    @This
-    private Configuration<PasswordRealmConfiguration> configuration;
-
-    private final DefaultPasswordService passwordService;
-
-    public PasswordRealmMixin()
-    {
-        super();
-        passwordService = new DefaultPasswordService();
-        PasswordMatcher matcher = new PasswordMatcher();
-        matcher.setPasswordService( passwordService );
-        setCredentialsMatcher( matcher );
-    }
-
-    @Override
-    public void activateService()
-            throws Exception
-    {
-        configuration.refresh();
-        PasswordRealmConfiguration config = configuration.get();
-        String algorithm = config.hashAlgorithmName().get();
-        Integer iterations = config.hashIterationsCount().get();
-        if ( algorithm != null || iterations != null ) {
-            DefaultHashService hashService = ( DefaultHashService ) passwordService.getHashService();
-            if ( algorithm != null ) {
-                hashService.setHashAlgorithmName( algorithm );
-            }
-            if ( iterations != null ) {
-                hashService.setHashIterations( iterations );
-            }
-        }
-    }
-
-    @Override
-    public void passivateService()
-            throws Exception
-    {
-    }
-
-    @Override
-    public String encryptPassword( Object plaintextPassword )
-            throws IllegalArgumentException
-    {
-        return passwordService.encryptPassword( plaintextPassword );
-    }
-
-    @Override
-    public boolean passwordsMatch( Object submittedPlaintext, String encrypted )
-    {
-        return passwordService.passwordsMatch( submittedPlaintext, encrypted );
-    }
-
-    @Override
-    protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token )
-            throws AuthenticationException
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try {
-
-            String username = ( ( UsernamePasswordToken ) token ).getUsername();
-            PasswordSecurable account = findPasswordSecurable( uow, username );
-            if ( account == null ) {
-                LOG.debug( "Unknown subject identifier: {}" + username );
-                return null;
-            }
-            LOG.debug( "Found account for {}: {}", username, account );
-            return new SimpleAuthenticationInfo( account.subjectIdentifier().get(), account.password().get(), getName() );
-
-        } finally {
-            uow.discard();
-        }
-    }
-
-    @Override
-    protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals )
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try {
-
-            String username = getAvailablePrincipal( principals ).toString();
-            RoleAssignee roleAssignee = findRoleAssignee( uow, username );
-            if ( roleAssignee == null ) {
-                LOG.debug( "No authorization info for {}", username );
-                return null;
-            }
-            LOG.debug( "Found role assignee for {}: {}", username, roleAssignee );
-            Set<String> roleNames = roleAssignee.roleNames();
-            Set<String> permissionStrings = roleAssignee.permissionStrings();
-            LOG.debug( "Found role assignee has the following roles: {}", roleNames );
-            LOG.debug( "Found role assignee has the following permissions: {}", permissionStrings );
-            SimpleAuthorizationInfo atzInfo = new SimpleAuthorizationInfo( roleNames );
-            atzInfo.setStringPermissions( permissionStrings );
-            return atzInfo;
-
-        } finally {
-            uow.discard();
-        }
-    }
-
-    private PasswordSecurable findPasswordSecurable( UnitOfWork uow, String username )
-    {
-        QueryBuilder<PasswordSecurable> builder = module.newQueryBuilder( PasswordSecurable.class );
-        builder = builder.where( eq( templateFor( PasswordSecurable.class ).subjectIdentifier(), username ) );
-        return uow.newQuery( builder ).find();
-    }
-
-    private RoleAssignee findRoleAssignee( UnitOfWork uow, String username )
-    {
-        QueryBuilder<RoleAssignee> builder = module.newQueryBuilder( RoleAssignee.class );
-        builder = builder.where( eq( templateFor( RoleAssignee.class ).subjectIdentifier(), username ) );
-        return uow.newQuery( builder ).find();
-    }
-
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/passwords/PasswordRealmService.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/passwords/PasswordRealmService.java
deleted file mode 100644
index 2a6dcf7..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/passwords/PasswordRealmService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.domain.passwords;
-
-import org.apache.shiro.authc.credential.PasswordService;
-import org.apache.shiro.authz.Authorizer;
-import org.apache.shiro.realm.Realm;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.service.ServiceComposite;
-
-@Mixins( PasswordRealmMixin.class )
-public interface PasswordRealmService
-        extends Realm, Authorizer, PasswordService,
-                ServiceComposite, ServiceActivation
-{
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/passwords/PasswordSecurable.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/passwords/PasswordSecurable.java
deleted file mode 100644
index 987782d..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/passwords/PasswordSecurable.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.domain.passwords;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.api.property.Property;
-import org.qi4j.library.shiro.domain.common.IdentifiableSubject;
-
-public interface PasswordSecurable
-        extends IdentifiableSubject, EntityComposite
-{
-
-    @Queryable( false )
-    Property<String> password();
-
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/passwords/package.html b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/passwords/package.html
deleted file mode 100644
index df9ff36..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/passwords/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Shiro Security Passwords Domain.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/permissions/Role.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/permissions/Role.java
deleted file mode 100644
index f2c9b8f..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/permissions/Role.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.domain.permissions;
-
-import java.util.List;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-
-@Mixins( Role.Mixin.class )
-public interface Role
-        extends EntityComposite
-{
-
-    Property<String> name();
-
-    @UseDefaults
-    Property<List<String>> permissions();
-
-    RoleAssignment assignTo( RoleAssignee assignee );
-
-    public abstract class Mixin
-            implements Role
-    {
-
-        @Structure
-        private Module module;
-
-        @This
-        private Role role;
-
-        @Override
-        public RoleAssignment assignTo( RoleAssignee assignee )
-        {
-            UnitOfWork uow = module.currentUnitOfWork();
-            EntityBuilder<RoleAssignment> builder = uow.newEntityBuilder( RoleAssignment.class );
-            RoleAssignment assignment = builder.instance();
-            assignment.assignee().set( assignee );
-            assignment.role().set( role );
-            assignment = builder.newInstance();
-            assignee.roleAssignments().add( assignment );
-            return assignment;
-        }
-
-    }
-
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/permissions/RoleAssignee.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/permissions/RoleAssignee.java
deleted file mode 100644
index c90a9b2..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/permissions/RoleAssignee.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.domain.permissions;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.Aggregated;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.library.shiro.domain.common.IdentifiableSubject;
-
-@Mixins( RoleAssignee.Mixin.class )
-public interface RoleAssignee
-        extends IdentifiableSubject, EntityComposite
-{
-
-    @Aggregated
-    @UseDefaults
-    ManyAssociation<RoleAssignment> roleAssignments();
-
-    Set<String> roleNames();
-
-    Set<String> permissionStrings();
-
-    public abstract class Mixin
-            implements RoleAssignee
-    {
-
-        @This
-        private RoleAssignee roleAssignee;
-
-        @Override
-        public Set<String> roleNames()
-        {
-            Set<String> roleNames = new HashSet<String>();
-            for ( RoleAssignment assignment : roleAssignee.roleAssignments() ) {
-                roleNames.add( assignment.role().get().name().get() );
-            }
-            return Collections.unmodifiableSet( roleNames );
-        }
-
-        @Override
-        public Set<String> permissionStrings()
-        {
-            Set<String> permissionStrings = new HashSet<String>();
-            for ( RoleAssignment assignment : roleAssignee.roleAssignments() ) {
-                permissionStrings.addAll( assignment.role().get().permissions().get() );
-            }
-            return Collections.unmodifiableSet( permissionStrings );
-        }
-
-    }
-
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/permissions/RoleAssignment.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/permissions/RoleAssignment.java
deleted file mode 100644
index bfd1a9f..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/permissions/RoleAssignment.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.domain.permissions;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.entity.EntityComposite;
-
-public interface RoleAssignment
-        extends EntityComposite
-{
-
-    Association<Role> role();
-
-    Association<RoleAssignee> assignee();
-
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/permissions/RoleFactory.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/permissions/RoleFactory.java
deleted file mode 100644
index 900289e..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/permissions/RoleFactory.java
+++ /dev/null
@@ -1,65 +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.qi4j.library.shiro.domain.permissions;
-
-import java.util.Arrays;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.functional.Iterables;
-
-@Mixins( RoleFactory.Mixin.class )
-public interface RoleFactory
-        extends ServiceComposite
-{
-
-    Role create( String name, String... permissions );
-
-    Role create( String name, Iterable<String> permissions );
-
-    abstract class Mixin
-            implements RoleFactory
-    {
-
-        @Structure
-        private Module module;
-
-        @Override
-        public Role create( String name, String... permissions )
-        {
-            return create( name, Arrays.asList( permissions ) );
-        }
-
-        @Override
-        public Role create( String name, Iterable<String> permissions )
-        {
-            UnitOfWork uow = module.currentUnitOfWork();
-            EntityBuilder<Role> roleBuilder = uow.newEntityBuilder( Role.class );
-            Role role = roleBuilder.instance();
-            role.name().set( name );
-            role.permissions().set( Iterables.toList( permissions ) );
-            return roleBuilder.newInstance();
-        }
-
-    }
-
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/permissions/package.html b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/permissions/package.html
deleted file mode 100644
index 3d0b2dd..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/domain/permissions/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Shiro Security Permissions Domain.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/ini/IniSecurityManagerService.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/ini/IniSecurityManagerService.java
deleted file mode 100644
index 440a7e0..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/ini/IniSecurityManagerService.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.ini;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import org.apache.shiro.config.Ini;
-import org.apache.shiro.config.IniSecurityManagerFactory;
-import org.apache.shiro.mgt.RealmSecurityManager;
-import org.apache.shiro.mgt.SecurityManager;
-import org.apache.shiro.realm.Realm;
-import org.apache.shiro.util.ThreadContext;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.functional.Iterables;
-import org.qi4j.library.shiro.Shiro;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Mixins( IniSecurityManagerService.Mixin.class )
-public interface IniSecurityManagerService
-        extends ServiceActivation
-{
-
-    SecurityManager getSecurityManager();
-
-    public class Mixin
-            extends IniSecurityManagerFactory
-            implements IniSecurityManagerService
-    {
-
-        private static final Logger LOG = LoggerFactory.getLogger( Shiro.LOGGER_NAME );
-
-        @This
-        private Configuration<ShiroIniConfiguration> configuration;
-
-        @Optional
-        @Service
-        private Iterable<ServiceReference<Realm>> realmsRefs;
-
-        private SecurityManager securityManager;
-
-        @Override
-        public void activateService()
-                throws Exception
-        {
-            configuration.refresh();
-            ShiroIniConfiguration config = configuration.get();
-
-            String iniResourcePath = config.iniResourcePath().get() == null
-                                     ? Shiro.DEFAULT_INI_RESOURCE_PATH
-                                     : config.iniResourcePath().get();
-
-            setIni( Ini.fromResourcePath( iniResourcePath ) );
-            securityManager = getInstance();
-
-            if ( realmsRefs != null && Iterables.count( realmsRefs ) > 0 ) {
-
-                // Register Realms Services
-                RealmSecurityManager realmSecurityManager = ( RealmSecurityManager ) securityManager;
-                Collection<Realm> iniRealms = new ArrayList<Realm>( realmSecurityManager.getRealms() );
-                for ( ServiceReference<Realm> realmRef : realmsRefs ) {
-                    iniRealms.add( realmRef.get() );
-                    LOG.debug( "Realm Service '{}' registered!", realmRef.identity() );
-                }
-                realmSecurityManager.setRealms( iniRealms );
-
-            }
-
-            ThreadContext.bind( securityManager );
-        }
-
-        @Override
-        public void passivateService()
-                throws Exception
-        {
-            ThreadContext.unbindSubject();
-            ThreadContext.unbindSecurityManager();
-        }
-
-        @Override
-        public SecurityManager getSecurityManager()
-        {
-            return securityManager;
-        }
-
-    }
-
-}
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/ini/ShiroIniConfiguration.java b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/ini/ShiroIniConfiguration.java
deleted file mode 100644
index 5e3ea51..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/ini/ShiroIniConfiguration.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.ini;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-// START SNIPPET: config
-public interface ShiroIniConfiguration
-        extends ConfigurationComposite
-{
-
-    /**
-     * Resource path of the ini configuration file.
-     * "classpath:", "file": and "url:" prefixes are supported.
-     * Defaulted to "classpath:shiro.ini".
-     */
-    @Optional
-    Property<String> iniResourcePath();
-
-}
-// END SNIPPET: config
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/ini/package.html b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/ini/package.html
deleted file mode 100644
index cd04c13..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/ini/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Shiro Security INI Configuration Support.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/package.html b/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/package.html
deleted file mode 100644
index 1b648ea..0000000
--- a/libraries/shiro-core/src/main/java/org/qi4j/library/shiro/package.html
+++ /dev/null
@@ -1,31 +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.
--->
-<html>
-    <body>
-        <h2>Shiro Security Library.</h2>
-        <p>
-            This library provide integration with the
-            <a href="http://shiro.apache.org/" target="_blank">Apache Shiro</a> Java Security Framework.
-        </p>
-        <blockquote>
-            Apache Shiro is a powerful and easy-to-use Java security framework that performs authentication,
-            authorization, cryptography, and session management. With Shiro's easy-to-understand API, you can quickly
-            and easily secure any application – from the smallest mobile applications to the largest web and enterprise
-            applications.
-        </blockquote>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/PasswordDomainTest.java b/libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/PasswordDomainTest.java
new file mode 100644
index 0000000..c2b3fb8
--- /dev/null
+++ b/libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/PasswordDomainTest.java
@@ -0,0 +1,148 @@
+/*
+ *  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.polygene.library.shiro;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.authc.credential.PasswordService;
+import org.apache.shiro.subject.Subject;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.rdf.assembly.RdfMemoryStoreAssembler;
+import org.apache.polygene.library.shiro.assembly.PasswordDomainAssembler;
+import org.apache.polygene.library.shiro.assembly.StandaloneShiroAssembler;
+import org.apache.polygene.library.shiro.domain.passwords.PasswordSecurable;
+import org.apache.polygene.library.shiro.ini.ShiroIniConfiguration;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.*;
+
+public class PasswordDomainTest
+    extends AbstractPolygeneTest
+{
+
+    // START SNIPPET: domain
+    public interface User
+            extends PasswordSecurable
+    {
+    }
+
+    // END SNIPPET: domain
+    // START SNIPPET: domain
+    @Mixins( UserFactoryMixin.class )
+    public interface UserFactory
+    {
+
+        User createNewUser( String username, String password );
+
+    }
+
+    // END SNIPPET: domain
+    // START SNIPPET: domain
+    public static class UserFactoryMixin
+            implements UserFactory
+    {
+
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @Service
+        private PasswordService passwordService;
+
+        @Override
+        public User createNewUser( String username, String password )
+        {
+            EntityBuilder<User> userBuilder = uowf.currentUnitOfWork().newEntityBuilder( User.class );
+            User user = userBuilder.instance();
+            user.subjectIdentifier().set( username );
+            user.password().set( passwordService.encryptPassword( password ) );
+            return userBuilder.newInstance();
+        }
+
+    }
+
+    // END SNIPPET: domain
+    // START SNIPPET: assembly
+    @Override
+    public void assemble( ModuleAssembly module )
+            throws AssemblyException
+    {
+        // END SNIPPET: assembly
+        new EntityTestAssembler().assemble( module );
+        new RdfMemoryStoreAssembler().assemble( module );
+        ModuleAssembly configModule = module;
+        // START SNIPPET: assembly
+        new StandaloneShiroAssembler().
+            withConfig( configModule, Visibility.layer ).
+            assemble( module );
+        new PasswordDomainAssembler().
+            withConfig( configModule, Visibility.layer ).
+            assemble( module );
+
+        module.entities( User.class );
+        module.services( UserFactory.class );
+
+        // END SNIPPET: assembly
+        configModule.forMixin( ShiroIniConfiguration.class ).
+                declareDefaults().
+                iniResourcePath().set( "classpath:standalone-shiro.ini" );
+        // START SNIPPET: assembly
+    }
+
+    // END SNIPPET: assembly
+    @Test
+    public void test()
+            throws UnitOfWorkCompletionException
+    {
+
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+
+        UserFactory userFactory = serviceFinder.findService( UserFactory.class ).get();
+        // START SNIPPET: usage
+        User user = userFactory.createNewUser( "foo", "bar" );
+
+        // END SNIPPET: usage
+        uow.complete();
+
+        uow = unitOfWorkFactory.newUnitOfWork();
+
+        // START SNIPPET: usage
+        Subject currentUser = SecurityUtils.getSubject();
+        currentUser.login( new UsernamePasswordToken( "foo", "bar" ) );
+
+        // END SNIPPET: usage
+        assertNotNull( "Unable to authenticate against PasswordRealmService", currentUser.getPrincipal() );
+
+        assertFalse( currentUser.hasRole( "role-one" ) );
+
+        uow.discard();
+    }
+
+}
\ No newline at end of file
diff --git a/libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/PermissionsDomainTest.java b/libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/PermissionsDomainTest.java
new file mode 100644
index 0000000..604b0bb
--- /dev/null
+++ b/libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/PermissionsDomainTest.java
@@ -0,0 +1,174 @@
+/*
+ *  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.polygene.library.shiro;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.authc.credential.PasswordService;
+import org.apache.shiro.subject.Subject;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.index.rdf.assembly.RdfMemoryStoreAssembler;
+import org.apache.polygene.library.shiro.assembly.PasswordDomainAssembler;
+import org.apache.polygene.library.shiro.assembly.PermissionsDomainAssembler;
+import org.apache.polygene.library.shiro.assembly.StandaloneShiroAssembler;
+import org.apache.polygene.library.shiro.domain.passwords.PasswordSecurable;
+import org.apache.polygene.library.shiro.domain.permissions.Role;
+import org.apache.polygene.library.shiro.domain.permissions.RoleAssignee;
+import org.apache.polygene.library.shiro.domain.permissions.RoleFactory;
+import org.apache.polygene.library.shiro.ini.ShiroIniConfiguration;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class PermissionsDomainTest
+    extends AbstractPolygeneTest
+{
+
+    // START SNIPPET: domain
+    public interface User
+            extends PasswordSecurable, RoleAssignee
+    {
+    }
+
+    // END SNIPPET: domain
+    @Mixins( UserFactoryMixin.class )
+    public interface UserFactory
+    {
+
+        User createNewUser( String username, String password );
+
+    }
+
+    public static class UserFactoryMixin
+            implements UserFactory
+    {
+
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @Service
+        private PasswordService passwordService;
+
+        @Override
+        public User createNewUser( String username, String password )
+        {
+            EntityBuilder<User> userBuilder = uowf.currentUnitOfWork().newEntityBuilder( User.class );
+            User user = userBuilder.instance();
+            user.subjectIdentifier().set( username );
+            user.password().set( passwordService.encryptPassword( password ) );
+            return userBuilder.newInstance();
+        }
+
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+            throws AssemblyException
+    {
+
+        new EntityTestAssembler().assemble( module );
+        new RdfMemoryStoreAssembler().assemble( module );
+        ModuleAssembly configModule = module;
+        // START SNIPPET: assembly
+        new StandaloneShiroAssembler().
+            withConfig( configModule, Visibility.layer ).
+            assemble( module );
+        new PasswordDomainAssembler().
+            withConfig( configModule, Visibility.layer ).
+            assemble( module );
+        new PermissionsDomainAssembler().
+            assemble( module );
+
+        module.entities( User.class );
+        module.services( UserFactory.class );
+
+        // END SNIPPET: assembly
+        configModule.forMixin( ShiroIniConfiguration.class ).
+                declareDefaults().
+                iniResourcePath().set( "classpath:standalone-shiro.ini" );
+    }
+
+    private UserFactory userFactory;
+
+    private RoleFactory roleFactory;
+
+    @Before
+    public void before_PermissionsDomainTest()
+    {
+        userFactory = serviceFinder.findService( UserFactory.class ).get();
+        roleFactory = serviceFinder.findService( RoleFactory.class ).get();
+    }
+
+    @Test
+    public void test()
+            throws UnitOfWorkCompletionException
+    {
+        // START SNIPPET: usage
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+
+        User user = userFactory.createNewUser( "foo", "bar" );
+        Role role = roleFactory.create( "role-one", "permission-one", "permission-two" );
+        role.assignTo( user );
+
+        uow.complete();
+
+        // END SNIPPET: usage
+        // START SNIPPET: usage
+        uow = unitOfWorkFactory.newUnitOfWork();
+
+        Subject currentUser = SecurityUtils.getSubject();
+        currentUser.login( new UsernamePasswordToken( "foo", "bar" ) );
+
+        if ( !currentUser.hasRole( "role-one" ) ) {
+            fail( "User 'foo' must have 'role-one' role." );
+        }
+
+        if ( !currentUser.isPermitted( "permission-one" ) ) {
+            fail( "User 'foo' must have 'permission-one' permission." );
+        }
+
+        // END SNIPPET: usage
+        assertThat( currentUser.hasRole( "role-one" ), is( true ) );
+        assertThat( currentUser.hasRole( "role-two" ), is( false ) );
+
+        assertThat( currentUser.isPermitted( "permission-one" ), is( true ) );
+        assertThat( currentUser.isPermitted( "permission-two" ), is( true ) );
+        assertThat( currentUser.isPermitted( "permission-three" ), is( false ) );
+
+        // START SNIPPET: usage
+        uow.discard();
+        // END SNIPPET: usage
+    }
+
+}
diff --git a/libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/RealmServiceTest.java b/libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/RealmServiceTest.java
new file mode 100644
index 0000000..3a774a2
--- /dev/null
+++ b/libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/RealmServiceTest.java
@@ -0,0 +1,119 @@
+/*
+ *  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.polygene.library.shiro;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.authc.credential.DefaultPasswordService;
+import org.apache.shiro.authc.credential.PasswordMatcher;
+import org.apache.shiro.authc.credential.PasswordService;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.realm.SimpleAccountRealm;
+import org.apache.shiro.subject.Subject;
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.shiro.assembly.StandaloneShiroAssembler;
+import org.apache.polygene.library.shiro.ini.ShiroIniConfiguration;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.assertNotNull;
+
+public class RealmServiceTest
+    extends AbstractPolygeneTest
+{
+
+    // START SNIPPET: realm-service
+    @Mixins( MyRealmMixin.class )
+    public interface MyRealmService
+            extends Realm, ServiceComposite, ServiceActivation
+    {
+    }
+
+    // END SNIPPET: realm-service
+    // START SNIPPET: realm-service
+    public class MyRealmMixin
+            extends SimpleAccountRealm
+            implements ServiceActivation
+    {
+
+        private final PasswordService passwordService;
+
+        public MyRealmMixin()
+        {
+            super();
+            passwordService = new DefaultPasswordService();
+            PasswordMatcher matcher = new PasswordMatcher();
+            matcher.setPasswordService( passwordService );
+            setCredentialsMatcher( matcher );
+        }
+
+        public void activateService()
+                throws Exception
+        {
+            // Create a test account
+            addAccount( "foo", passwordService.encryptPassword( "bar" ) );
+        }
+
+        // END SNIPPET: realm-service
+        public void passivateService()
+                throws Exception
+        {
+        }
+        // START SNIPPET: realm-service
+
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+            throws AssemblyException
+    {
+        // END SNIPPET: realm-service
+        new EntityTestAssembler().assemble( module );
+        ModuleAssembly configModule = module;
+        // START SNIPPET: realm-service
+        new StandaloneShiroAssembler().
+            withConfig( configModule, Visibility.layer ).
+            assemble( module );
+        module.services( MyRealmService.class );
+
+        // END SNIPPET: realm-service
+        configModule.forMixin( ShiroIniConfiguration.class ).
+                declareDefaults().
+                iniResourcePath().set( "classpath:standalone-shiro.ini" );
+        // START SNIPPET: realm-service
+    }
+
+    // END SNIPPET: realm-service
+    @Test
+    public void test()
+    {
+        Subject currentUser = SecurityUtils.getSubject();
+        UsernamePasswordToken token = new UsernamePasswordToken( "foo", "bar" );
+        currentUser.login( token );
+        assertNotNull( "Unable to authenticate against MyRealmService", currentUser.getPrincipal() );
+    }
+
+}
diff --git a/libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/StandaloneShiroTest.java b/libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/StandaloneShiroTest.java
new file mode 100644
index 0000000..062077a
--- /dev/null
+++ b/libraries/shiro-core/src/test/java/org/apache/polygene/library/shiro/StandaloneShiroTest.java
@@ -0,0 +1,171 @@
+/*
+ *  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.polygene.library.shiro;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.IncorrectCredentialsException;
+import org.apache.shiro.authc.LockedAccountException;
+import org.apache.shiro.authc.UnknownAccountException;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.config.IniSecurityManagerFactory;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.util.ThreadContext;
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.shiro.assembly.StandaloneShiroAssembler;
+import org.apache.polygene.library.shiro.ini.IniSecurityManagerService;
+import org.apache.polygene.library.shiro.ini.ShiroIniConfiguration;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+public class StandaloneShiroTest
+    extends AbstractPolygeneTest
+{
+
+    public void documentationSupport_before()
+    {
+        // START SNIPPET: before
+        IniSecurityManagerFactory factory = new IniSecurityManagerFactory( "classpath:standalone-shiro.ini" );
+        SecurityManager securityManager = factory.getInstance();
+        SecurityUtils.setSecurityManager( securityManager );
+        // END SNIPPET: before
+    }
+
+    public static class documentationSupport_ThreadContext
+    {
+        // START SNIPPET: thread-context
+
+        @Service
+        private IniSecurityManagerService securityManagerService;
+
+        // END SNIPPET: thread-context
+        // START SNIPPET: thread-context
+        public void interactionBegins()
+        {
+            ThreadContext.bind( securityManagerService.getSecurityManager() );
+        }
+
+        // END SNIPPET: thread-context
+        // START SNIPPET: thread-context
+        public void interactionEnds()
+        {
+            ThreadContext.unbindSubject();
+            ThreadContext.unbindSecurityManager();
+        }
+        // END SNIPPET: thread-context
+
+    }
+
+    private static final Logger LOG = LoggerFactory.getLogger( Shiro.LOGGER_NAME );
+
+    @Override
+    public void assemble( ModuleAssembly module )
+            throws AssemblyException
+    {
+        new EntityTestAssembler().assemble( module );
+        ModuleAssembly configModule = module;
+        // START SNIPPET: assembly
+        new StandaloneShiroAssembler().
+            withConfig( configModule, Visibility.layer ).
+            assemble( module );
+
+        // END SNIPPET: assembly
+        configModule.forMixin( ShiroIniConfiguration.class ).
+                declareDefaults().
+                iniResourcePath().set( "classpath:standalone-shiro.ini" );
+    }
+
+    @Test
+    public void test()
+    {
+        // get the currently executing user:
+        Subject currentUser = SecurityUtils.getSubject();
+
+        // Do some stuff with a Session (no need for a web or EJB container!!!)
+        Session session = currentUser.getSession();
+        session.setAttribute( "someKey", "aValue" );
+        String value = ( String ) session.getAttribute( "someKey" );
+        assertEquals( "aValue", value );
+        LOG.info( "Retrieved the correct value! [" + value + "]" );
+
+        // let's login the current user so we can check against roles and permissions:
+        if ( !currentUser.isAuthenticated() ) {
+            UsernamePasswordToken token = new UsernamePasswordToken( "lonestarr", "vespa" );
+            token.setRememberMe( true );
+            try {
+                currentUser.login( token );
+            } catch ( UnknownAccountException uae ) {
+                fail( "There is no user with username of " + token.getPrincipal() );
+            } catch ( IncorrectCredentialsException ice ) {
+                fail( "Password for account " + token.getPrincipal() + " was incorrect!" );
+            } catch ( LockedAccountException lae ) {
+                fail( "The account for username " + token.getPrincipal() + " is locked.  "
+                      + "Please contact your administrator to unlock it." );
+            } // ... catch more exceptions here (maybe custom ones specific to your application?
+            catch ( AuthenticationException ae ) {
+                //unexpected condition?  error?
+                throw ae;
+            }
+        }
+
+        //say who they are:
+        //print their identifying principal (in this case, a username):
+        assertNotNull( currentUser.getPrincipal() );
+        LOG.info( "User [" + currentUser.getPrincipal() + "] logged in successfully." );
+
+        //test a role:
+        if ( currentUser.hasRole( "schwartz" ) ) {
+            LOG.info( "May the Schwartz be with you!" );
+        } else {
+            fail( "Hello, mere mortal." );
+        }
+
+        //test a typed permission (not instance-level)
+        if ( currentUser.isPermitted( "lightsaber:weild" ) ) {
+            LOG.info( "You may use a lightsaber ring.  Use it wisely." );
+        } else {
+            fail( "Sorry, lightsaber rings are for schwartz masters only." );
+        }
+
+        //a (very powerful) Instance Level permission:
+        if ( currentUser.isPermitted( "winnebago:drive:eagle5" ) ) {
+            LOG.info( "You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  "
+                      + "Here are the keys - have fun!" );
+        } else {
+            fail( "Sorry, you aren't allowed to drive the 'eagle5' winnebago!" );
+        }
+
+        //all done - log out!
+        currentUser.logout();
+    }
+
+}
diff --git a/libraries/shiro-core/src/test/java/org/qi4j/library/shiro/PasswordDomainTest.java b/libraries/shiro-core/src/test/java/org/qi4j/library/shiro/PasswordDomainTest.java
deleted file mode 100644
index 12a4450..0000000
--- a/libraries/shiro-core/src/test/java/org/qi4j/library/shiro/PasswordDomainTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro;
-
-import org.apache.shiro.SecurityUtils;
-import org.apache.shiro.authc.UsernamePasswordToken;
-import org.apache.shiro.authc.credential.PasswordService;
-import org.apache.shiro.subject.Subject;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.rdf.assembly.RdfMemoryStoreAssembler;
-import org.qi4j.library.shiro.assembly.PasswordDomainAssembler;
-import org.qi4j.library.shiro.assembly.StandaloneShiroAssembler;
-import org.qi4j.library.shiro.domain.passwords.PasswordSecurable;
-import org.qi4j.library.shiro.ini.ShiroIniConfiguration;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.*;
-
-public class PasswordDomainTest
-        extends AbstractQi4jTest
-{
-
-    // START SNIPPET: domain
-    public interface User
-            extends PasswordSecurable
-    {
-    }
-
-    // END SNIPPET: domain
-    // START SNIPPET: domain
-    @Mixins( UserFactoryMixin.class )
-    public interface UserFactory
-    {
-
-        User createNewUser( String username, String password );
-
-    }
-
-    // END SNIPPET: domain
-    // START SNIPPET: domain
-    public static class UserFactoryMixin
-            implements UserFactory
-    {
-
-        @Structure
-        private Module module;
-
-        @Service
-        private PasswordService passwordService;
-
-        @Override
-        public User createNewUser( String username, String password )
-        {
-            EntityBuilder<User> userBuilder = module.currentUnitOfWork().newEntityBuilder( User.class );
-            User user = userBuilder.instance();
-            user.subjectIdentifier().set( username );
-            user.password().set( passwordService.encryptPassword( password ) );
-            return userBuilder.newInstance();
-        }
-
-    }
-
-    // END SNIPPET: domain
-    // START SNIPPET: assembly
-    @Override
-    public void assemble( ModuleAssembly module )
-            throws AssemblyException
-    {
-        // END SNIPPET: assembly
-        new EntityTestAssembler().assemble( module );
-        new RdfMemoryStoreAssembler().assemble( module );
-        ModuleAssembly configModule = module;
-        // START SNIPPET: assembly
-        new StandaloneShiroAssembler().
-            withConfig( configModule, Visibility.layer ).
-            assemble( module );
-        new PasswordDomainAssembler().
-            withConfig( configModule, Visibility.layer ).
-            assemble( module );
-
-        module.entities( User.class );
-        module.services( UserFactory.class );
-
-        // END SNIPPET: assembly
-        configModule.forMixin( ShiroIniConfiguration.class ).
-                declareDefaults().
-                iniResourcePath().set( "classpath:standalone-shiro.ini" );
-        // START SNIPPET: assembly
-    }
-
-    // END SNIPPET: assembly
-    @Test
-    public void test()
-            throws UnitOfWorkCompletionException
-    {
-
-        UnitOfWork uow = module.newUnitOfWork();
-
-        UserFactory userFactory = module.findService( UserFactory.class ).get();
-        // START SNIPPET: usage
-        User user = userFactory.createNewUser( "foo", "bar" );
-
-        // END SNIPPET: usage
-        uow.complete();
-
-        uow = module.newUnitOfWork();
-
-        // START SNIPPET: usage
-        Subject currentUser = SecurityUtils.getSubject();
-        currentUser.login( new UsernamePasswordToken( "foo", "bar" ) );
-
-        // END SNIPPET: usage
-        assertNotNull( "Unable to authenticate against PasswordRealmService", currentUser.getPrincipal() );
-
-        assertFalse( currentUser.hasRole( "role-one" ) );
-
-        uow.discard();
-    }
-
-}
\ No newline at end of file
diff --git a/libraries/shiro-core/src/test/java/org/qi4j/library/shiro/PermissionsDomainTest.java b/libraries/shiro-core/src/test/java/org/qi4j/library/shiro/PermissionsDomainTest.java
deleted file mode 100644
index b616f4f..0000000
--- a/libraries/shiro-core/src/test/java/org/qi4j/library/shiro/PermissionsDomainTest.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro;
-
-import org.apache.shiro.SecurityUtils;
-import org.apache.shiro.authc.UsernamePasswordToken;
-import org.apache.shiro.authc.credential.PasswordService;
-import org.apache.shiro.subject.Subject;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.index.rdf.assembly.RdfMemoryStoreAssembler;
-import org.qi4j.library.shiro.assembly.PasswordDomainAssembler;
-import org.qi4j.library.shiro.assembly.PermissionsDomainAssembler;
-import org.qi4j.library.shiro.assembly.StandaloneShiroAssembler;
-import org.qi4j.library.shiro.domain.passwords.PasswordSecurable;
-import org.qi4j.library.shiro.domain.permissions.Role;
-import org.qi4j.library.shiro.domain.permissions.RoleAssignee;
-import org.qi4j.library.shiro.domain.permissions.RoleFactory;
-import org.qi4j.library.shiro.ini.ShiroIniConfiguration;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-public class PermissionsDomainTest
-        extends AbstractQi4jTest
-{
-
-    // START SNIPPET: domain
-    public interface User
-            extends PasswordSecurable, RoleAssignee
-    {
-    }
-
-    // END SNIPPET: domain
-    @Mixins( UserFactoryMixin.class )
-    public interface UserFactory
-    {
-
-        User createNewUser( String username, String password );
-
-    }
-
-    public static class UserFactoryMixin
-            implements UserFactory
-    {
-
-        @Structure
-        private Module module;
-
-        @Service
-        private PasswordService passwordService;
-
-        @Override
-        public User createNewUser( String username, String password )
-        {
-            EntityBuilder<User> userBuilder = module.currentUnitOfWork().newEntityBuilder( User.class );
-            User user = userBuilder.instance();
-            user.subjectIdentifier().set( username );
-            user.password().set( passwordService.encryptPassword( password ) );
-            return userBuilder.newInstance();
-        }
-
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-            throws AssemblyException
-    {
-
-        new EntityTestAssembler().assemble( module );
-        new RdfMemoryStoreAssembler().assemble( module );
-        ModuleAssembly configModule = module;
-        // START SNIPPET: assembly
-        new StandaloneShiroAssembler().
-            withConfig( configModule, Visibility.layer ).
-            assemble( module );
-        new PasswordDomainAssembler().
-            withConfig( configModule, Visibility.layer ).
-            assemble( module );
-        new PermissionsDomainAssembler().
-            assemble( module );
-
-        module.entities( User.class );
-        module.services( UserFactory.class );
-
-        // END SNIPPET: assembly
-        configModule.forMixin( ShiroIniConfiguration.class ).
-                declareDefaults().
-                iniResourcePath().set( "classpath:standalone-shiro.ini" );
-    }
-
-    private UserFactory userFactory;
-
-    private RoleFactory roleFactory;
-
-    @Before
-    public void before_PermissionsDomainTest()
-    {
-        userFactory = module.findService( UserFactory.class ).get();
-        roleFactory = module.findService( RoleFactory.class ).get();
-    }
-
-    @Test
-    public void test()
-            throws UnitOfWorkCompletionException
-    {
-        // START SNIPPET: usage
-        UnitOfWork uow = module.newUnitOfWork();
-
-        User user = userFactory.createNewUser( "foo", "bar" );
-        Role role = roleFactory.create( "role-one", "permission-one", "permission-two" );
-        role.assignTo( user );
-
-        uow.complete();
-
-        // END SNIPPET: usage
-        // START SNIPPET: usage
-        uow = module.newUnitOfWork();
-
-        Subject currentUser = SecurityUtils.getSubject();
-        currentUser.login( new UsernamePasswordToken( "foo", "bar" ) );
-
-        if ( !currentUser.hasRole( "role-one" ) ) {
-            fail( "User 'foo' must have 'role-one' role." );
-        }
-
-        if ( !currentUser.isPermitted( "permission-one" ) ) {
-            fail( "User 'foo' must have 'permission-one' permission." );
-        }
-
-        // END SNIPPET: usage
-        assertThat( currentUser.hasRole( "role-one" ), is( true ) );
-        assertThat( currentUser.hasRole( "role-two" ), is( false ) );
-
-        assertThat( currentUser.isPermitted( "permission-one" ), is( true ) );
-        assertThat( currentUser.isPermitted( "permission-two" ), is( true ) );
-        assertThat( currentUser.isPermitted( "permission-three" ), is( false ) );
-
-        // START SNIPPET: usage
-        uow.discard();
-        // END SNIPPET: usage
-    }
-
-}
diff --git a/libraries/shiro-core/src/test/java/org/qi4j/library/shiro/RealmServiceTest.java b/libraries/shiro-core/src/test/java/org/qi4j/library/shiro/RealmServiceTest.java
deleted file mode 100644
index 2145de1..0000000
--- a/libraries/shiro-core/src/test/java/org/qi4j/library/shiro/RealmServiceTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro;
-
-import org.apache.shiro.SecurityUtils;
-import org.apache.shiro.authc.UsernamePasswordToken;
-import org.apache.shiro.authc.credential.DefaultPasswordService;
-import org.apache.shiro.authc.credential.PasswordMatcher;
-import org.apache.shiro.authc.credential.PasswordService;
-import org.apache.shiro.realm.Realm;
-import org.apache.shiro.realm.SimpleAccountRealm;
-import org.apache.shiro.subject.Subject;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.shiro.assembly.StandaloneShiroAssembler;
-import org.qi4j.library.shiro.ini.ShiroIniConfiguration;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.assertNotNull;
-
-public class RealmServiceTest
-        extends AbstractQi4jTest
-{
-
-    // START SNIPPET: realm-service
-    @Mixins( MyRealmMixin.class )
-    public interface MyRealmService
-            extends Realm, ServiceComposite, ServiceActivation
-    {
-    }
-
-    // END SNIPPET: realm-service
-    // START SNIPPET: realm-service
-    public class MyRealmMixin
-            extends SimpleAccountRealm
-            implements ServiceActivation
-    {
-
-        private final PasswordService passwordService;
-
-        public MyRealmMixin()
-        {
-            super();
-            passwordService = new DefaultPasswordService();
-            PasswordMatcher matcher = new PasswordMatcher();
-            matcher.setPasswordService( passwordService );
-            setCredentialsMatcher( matcher );
-        }
-
-        public void activateService()
-                throws Exception
-        {
-            // Create a test account
-            addAccount( "foo", passwordService.encryptPassword( "bar" ) );
-        }
-
-        // END SNIPPET: realm-service
-        public void passivateService()
-                throws Exception
-        {
-        }
-        // START SNIPPET: realm-service
-
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-            throws AssemblyException
-    {
-        // END SNIPPET: realm-service
-        new EntityTestAssembler().assemble( module );
-        ModuleAssembly configModule = module;
-        // START SNIPPET: realm-service
-        new StandaloneShiroAssembler().
-            withConfig( configModule, Visibility.layer ).
-            assemble( module );
-        module.services( MyRealmService.class );
-
-        // END SNIPPET: realm-service
-        configModule.forMixin( ShiroIniConfiguration.class ).
-                declareDefaults().
-                iniResourcePath().set( "classpath:standalone-shiro.ini" );
-        // START SNIPPET: realm-service
-    }
-
-    // END SNIPPET: realm-service
-    @Test
-    public void test()
-    {
-        Subject currentUser = SecurityUtils.getSubject();
-        UsernamePasswordToken token = new UsernamePasswordToken( "foo", "bar" );
-        currentUser.login( token );
-        assertNotNull( "Unable to authenticate against MyRealmService", currentUser.getPrincipal() );
-    }
-
-}
diff --git a/libraries/shiro-core/src/test/java/org/qi4j/library/shiro/StandaloneShiroTest.java b/libraries/shiro-core/src/test/java/org/qi4j/library/shiro/StandaloneShiroTest.java
deleted file mode 100644
index 7ab1d91..0000000
--- a/libraries/shiro-core/src/test/java/org/qi4j/library/shiro/StandaloneShiroTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro;
-
-import org.apache.shiro.SecurityUtils;
-import org.apache.shiro.authc.AuthenticationException;
-import org.apache.shiro.authc.IncorrectCredentialsException;
-import org.apache.shiro.authc.LockedAccountException;
-import org.apache.shiro.authc.UnknownAccountException;
-import org.apache.shiro.authc.UsernamePasswordToken;
-import org.apache.shiro.config.IniSecurityManagerFactory;
-import org.apache.shiro.mgt.SecurityManager;
-import org.apache.shiro.session.Session;
-import org.apache.shiro.subject.Subject;
-import org.apache.shiro.util.ThreadContext;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.shiro.assembly.StandaloneShiroAssembler;
-import org.qi4j.library.shiro.ini.IniSecurityManagerService;
-import org.qi4j.library.shiro.ini.ShiroIniConfiguration;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-public class StandaloneShiroTest
-        extends AbstractQi4jTest
-{
-
-    public void documentationSupport_before()
-    {
-        // START SNIPPET: before
-        IniSecurityManagerFactory factory = new IniSecurityManagerFactory( "classpath:standalone-shiro.ini" );
-        SecurityManager securityManager = factory.getInstance();
-        SecurityUtils.setSecurityManager( securityManager );
-        // END SNIPPET: before
-    }
-
-    public static class documentationSupport_ThreadContext
-    {
-        // START SNIPPET: thread-context
-
-        @Service
-        private IniSecurityManagerService securityManagerService;
-
-        // END SNIPPET: thread-context
-        // START SNIPPET: thread-context
-        public void interactionBegins()
-        {
-            ThreadContext.bind( securityManagerService.getSecurityManager() );
-        }
-
-        // END SNIPPET: thread-context
-        // START SNIPPET: thread-context
-        public void interactionEnds()
-        {
-            ThreadContext.unbindSubject();
-            ThreadContext.unbindSecurityManager();
-        }
-        // END SNIPPET: thread-context
-
-    }
-
-    private static final Logger LOG = LoggerFactory.getLogger( Shiro.LOGGER_NAME );
-
-    @Override
-    public void assemble( ModuleAssembly module )
-            throws AssemblyException
-    {
-        new EntityTestAssembler().assemble( module );
-        ModuleAssembly configModule = module;
-        // START SNIPPET: assembly
-        new StandaloneShiroAssembler().
-            withConfig( configModule, Visibility.layer ).
-            assemble( module );
-
-        // END SNIPPET: assembly
-        configModule.forMixin( ShiroIniConfiguration.class ).
-                declareDefaults().
-                iniResourcePath().set( "classpath:standalone-shiro.ini" );
-    }
-
-    @Test
-    public void test()
-    {
-        // get the currently executing user:
-        Subject currentUser = SecurityUtils.getSubject();
-
-        // Do some stuff with a Session (no need for a web or EJB container!!!)
-        Session session = currentUser.getSession();
-        session.setAttribute( "someKey", "aValue" );
-        String value = ( String ) session.getAttribute( "someKey" );
-        assertEquals( "aValue", value );
-        LOG.info( "Retrieved the correct value! [" + value + "]" );
-
-        // let's login the current user so we can check against roles and permissions:
-        if ( !currentUser.isAuthenticated() ) {
-            UsernamePasswordToken token = new UsernamePasswordToken( "lonestarr", "vespa" );
-            token.setRememberMe( true );
-            try {
-                currentUser.login( token );
-            } catch ( UnknownAccountException uae ) {
-                fail( "There is no user with username of " + token.getPrincipal() );
-            } catch ( IncorrectCredentialsException ice ) {
-                fail( "Password for account " + token.getPrincipal() + " was incorrect!" );
-            } catch ( LockedAccountException lae ) {
-                fail( "The account for username " + token.getPrincipal() + " is locked.  "
-                      + "Please contact your administrator to unlock it." );
-            } // ... catch more exceptions here (maybe custom ones specific to your application?
-            catch ( AuthenticationException ae ) {
-                //unexpected condition?  error?
-                throw ae;
-            }
-        }
-
-        //say who they are:
-        //print their identifying principal (in this case, a username):
-        assertNotNull( currentUser.getPrincipal() );
-        LOG.info( "User [" + currentUser.getPrincipal() + "] logged in successfully." );
-
-        //test a role:
-        if ( currentUser.hasRole( "schwartz" ) ) {
-            LOG.info( "May the Schwartz be with you!" );
-        } else {
-            fail( "Hello, mere mortal." );
-        }
-
-        //test a typed permission (not instance-level)
-        if ( currentUser.isPermitted( "lightsaber:weild" ) ) {
-            LOG.info( "You may use a lightsaber ring.  Use it wisely." );
-        } else {
-            fail( "Sorry, lightsaber rings are for schwartz masters only." );
-        }
-
-        //a (very powerful) Instance Level permission:
-        if ( currentUser.isPermitted( "winnebago:drive:eagle5" ) ) {
-            LOG.info( "You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  "
-                      + "Here are the keys - have fun!" );
-        } else {
-            fail( "Sorry, you aren't allowed to drive the 'eagle5' winnebago!" );
-        }
-
-        //all done - log out!
-        currentUser.logout();
-    }
-
-}
diff --git a/libraries/shiro-core/src/test/resources/logback-test.xml b/libraries/shiro-core/src/test/resources/logback-test.xml
index 8c9b50a..3f88299 100644
--- a/libraries/shiro-core/src/test/resources/logback-test.xml
+++ b/libraries/shiro-core/src/test/resources/logback-test.xml
@@ -1,20 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <configuration>
 
     <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
@@ -27,7 +30,7 @@
         <appender-ref ref="stdout" />
     </root>
 
-    <logger name="org.qi4j.library.shiro" level="trace"/>
+    <logger name="org.apache.polygene.library.shiro" level="trace"/>
     <logger name="org.apache.shiro" level="trace"/>
     <logger name="org.apache.shiro.util.ThreadContext" level="info"/>
 
diff --git a/libraries/shiro-web/build.gradle b/libraries/shiro-web/build.gradle
index ebf7da3..79cea7e 100644
--- a/libraries/shiro-web/build.gradle
+++ b/libraries/shiro-web/build.gradle
@@ -1,43 +1,48 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Shiro Library integrates Apache Shiro security framework into Apache Zest™. This bundle provides Servlet support."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - Shiro Web" }}
+description = "Apache Polygene™ Shiro Library integrates Apache Shiro security framework into Apache Polygene™. This bundle provides Servlet support."
+
+jar { manifest { name = "Apache Polygene™ Library - Shiro Web" } }
 
 dependencies {
 
-  compile project( ":org.qi4j.core:org.qi4j.core.bootstrap" )
-  compile project( ':org.qi4j.libraries:org.qi4j.library.shiro-core' )
-  compile project( ':org.qi4j.libraries:org.qi4j.library.servlet' )
-  compile project( ':org.qi4j.libraries:org.qi4j.library.http' )
-  compile libraries.shiro_web
-  compile libraries.servlet_api
-  compile libraries.slf4j_api
+  compileOnly libraries.servlet_api
 
-  testCompile project( ":org.qi4j.core:org.qi4j.core.testsupport" )
-  testCompile project( ":org.qi4j.libraries:org.qi4j.library.shiro-web" )
-  testCompile project( ":org.qi4j.libraries:org.qi4j.library.servlet" )
-  testCompile project( ":org.qi4j.extensions:org.qi4j.extension.indexing-rdf" )
-  testCompile libraries.jetty_webapp
-  testCompile libraries.http_client
+  api polygene.core.bootstrap
+  api polygene.library( 'shiro-core' )
+  api polygene.library( 'servlet' )
+  api polygene.library( 'http' )
 
-  testRuntime project( ":org.qi4j.core:org.qi4j.core.runtime" )
-  testRuntime libraries.logback
+  implementation libraries.shiro_web
+  implementation libraries.slf4j_api
+
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+  testImplementation polygene.library( 'shiro-web' )
+  testImplementation polygene.extension( 'indexing-rdf' )
+  testImplementation libraries.jetty_webapp
+  testImplementation libraries.http_client
+
+  testRuntimeOnly libraries.logback
 }
diff --git a/libraries/shiro-web/dev-status.xml b/libraries/shiro-web/dev-status.xml
index cbcd274..34f74ea 100644
--- a/libraries/shiro-web/dev-status.xml
+++ b/libraries/shiro-web/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
     <status>
         <!--none,early,beta,stable,mature-->
         <codebase>stable</codebase>
diff --git a/libraries/shiro-web/src/docs/shiro-web.txt b/libraries/shiro-web/src/docs/shiro-web.txt
index c92d9b8..c54bf29 100644
--- a/libraries/shiro-web/src/docs/shiro-web.txt
+++ b/libraries/shiro-web/src/docs/shiro-web.txt
@@ -37,23 +37,23 @@
 Shiro website.
 
 We invite you to read the comprehensive http://shiro.apache.org/documentation.html[Apache Shiro documentation], we will
-mostly discuss Zest™ related matters here.
+mostly discuss Polygene™ related matters here.
 
 include::../../build/docs/buildinfo/artifact.txt[]
 
 == Servlet Context ==
 
-In a servlet context, being through the <<library-servlet>>, the <<library-http>> or your custom Zest™ application
+In a servlet context, being through the <<library-servlet>>, the <<library-http>> or your custom Polygene™ application
 bootstrap, plain Shiro is usable. A WebEnvironment must be globally available and ShiroFilter must be registered.
 
-If you use a custom Zest™ application boostrap or the <<library-servlet>> you can directly use Shiro's provided
+If you use a custom Polygene™ application boostrap or the <<library-servlet>> you can directly use Shiro's provided
 EnvironmentLoaderListener and ShiroFilter.
 
 If you use the <<library-http>> you can either directly use Shiro classes or use the assembly API as follows:
 
 [snippet,java]
 ----
-source=libraries/shiro-web/src/test/java/org/qi4j/library/shiro/web/WebHttpShiroTest.java
+source=libraries/shiro-web/src/test/java/org/apache/polygene/library/shiro/web/WebHttpShiroTest.java
 tag=assembly
 ----
 
diff --git a/libraries/shiro-web/src/main/java/org/apache/polygene/library/shiro/web/EnvironmentLoaderService.java b/libraries/shiro-web/src/main/java/org/apache/polygene/library/shiro/web/EnvironmentLoaderService.java
new file mode 100644
index 0000000..ca26d48
--- /dev/null
+++ b/libraries/shiro-web/src/main/java/org/apache/polygene/library/shiro/web/EnvironmentLoaderService.java
@@ -0,0 +1,93 @@
+/*
+ *  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.polygene.library.shiro.web;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import org.apache.shiro.mgt.RealmSecurityManager;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.web.env.EnvironmentLoader;
+import org.apache.shiro.web.env.WebEnvironment;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.library.shiro.Shiro;
+import org.apache.polygene.library.shiro.ini.ShiroIniConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Mixins( EnvironmentLoaderService.Mixin.class )
+public interface EnvironmentLoaderService
+        extends ServletContextListener, ServiceComposite
+{
+
+    public class Mixin
+            extends EnvironmentLoader
+            implements ServletContextListener
+    {
+
+        private static final Logger LOG = LoggerFactory.getLogger( Shiro.LOGGER_NAME );
+
+        @This
+        private Configuration<ShiroIniConfiguration> configuration;
+
+        @Optional
+        @Service
+        private Iterable<ServiceReference<Realm>> realmsRefs;
+
+        @Override
+        public void contextInitialized( ServletContextEvent sce )
+        {
+            configuration.refresh();
+            ShiroIniConfiguration config = configuration.get();
+            String iniResourcePath = config.iniResourcePath().get() == null ? "classpath:shiro.ini" : config.iniResourcePath().get();
+            sce.getServletContext().setInitParameter( "shiroConfigLocations", iniResourcePath );
+            WebEnvironment env = initEnvironment( sce.getServletContext() );
+
+            if ( realmsRefs != null && realmsRefs.iterator().hasNext() ) {
+
+                // Register Realms Services
+                RealmSecurityManager realmSecurityManager = ( RealmSecurityManager ) env.getSecurityManager();
+                Collection<Realm> iniRealms = new ArrayList<Realm>( realmSecurityManager.getRealms() );
+                for ( ServiceReference<Realm> realmRef : realmsRefs ) {
+                    iniRealms.add( realmRef.get() );
+                    LOG.debug( "Realm Service '{}' registered!", realmRef.identity() );
+                }
+                realmSecurityManager.setRealms( iniRealms );
+
+            }
+
+        }
+
+        @Override
+        public void contextDestroyed( ServletContextEvent sce )
+        {
+            destroyEnvironment( sce.getServletContext() );
+        }
+
+    }
+
+}
diff --git a/libraries/shiro-web/src/main/java/org/apache/polygene/library/shiro/web/ShiroFilterService.java b/libraries/shiro-web/src/main/java/org/apache/polygene/library/shiro/web/ShiroFilterService.java
new file mode 100644
index 0000000..698bcaa
--- /dev/null
+++ b/libraries/shiro-web/src/main/java/org/apache/polygene/library/shiro/web/ShiroFilterService.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.library.shiro.web;
+
+import javax.servlet.Filter;
+import org.apache.shiro.web.servlet.ShiroFilter;
+import org.apache.polygene.api.mixin.Mixins;
+
+@Mixins( ShiroFilter.class )
+public interface ShiroFilterService
+        extends Filter
+{
+}
diff --git a/libraries/shiro-web/src/main/java/org/apache/polygene/library/shiro/web/assembly/HttpShiroAssembler.java b/libraries/shiro-web/src/main/java/org/apache/polygene/library/shiro/web/assembly/HttpShiroAssembler.java
new file mode 100644
index 0000000..0c0a5e0
--- /dev/null
+++ b/libraries/shiro-web/src/main/java/org/apache/polygene/library/shiro/web/assembly/HttpShiroAssembler.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.library.shiro.web.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.shiro.ini.ShiroIniConfiguration;
+import org.apache.polygene.library.shiro.web.EnvironmentLoaderService;
+import org.apache.polygene.library.shiro.web.ShiroFilterService;
+
+import static javax.servlet.DispatcherType.ASYNC;
+import static javax.servlet.DispatcherType.ERROR;
+import static javax.servlet.DispatcherType.FORWARD;
+import static javax.servlet.DispatcherType.INCLUDE;
+import static javax.servlet.DispatcherType.REQUEST;
+import static org.apache.polygene.library.http.Servlets.addContextListeners;
+import static org.apache.polygene.library.http.Servlets.addFilters;
+import static org.apache.polygene.library.http.Servlets.filter;
+import static org.apache.polygene.library.http.Servlets.listen;
+
+public class HttpShiroAssembler
+    extends Assemblers.Config<HttpShiroAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        addContextListeners( listen().
+            with( EnvironmentLoaderService.class ) ).
+            to( module );
+
+        addFilters( filter( "/*" ).
+            through( ShiroFilterService.class ).
+            on( REQUEST, FORWARD, INCLUDE, ERROR, ASYNC ) ).
+            to( module );
+
+        if( hasConfig() )
+        {
+            configModule().entities( ShiroIniConfiguration.class ).
+                visibleIn( configVisibility() );
+        }
+    }
+}
diff --git a/libraries/shiro-web/src/main/java/org/apache/polygene/library/shiro/web/assembly/package.html b/libraries/shiro-web/src/main/java/org/apache/polygene/library/shiro/web/assembly/package.html
new file mode 100644
index 0000000..d1e8dc2
--- /dev/null
+++ b/libraries/shiro-web/src/main/java/org/apache/polygene/library/shiro/web/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Shiro Web Security Assembly.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/shiro-web/src/main/java/org/apache/polygene/library/shiro/web/package.html b/libraries/shiro-web/src/main/java/org/apache/polygene/library/shiro/web/package.html
new file mode 100644
index 0000000..4e7cc98
--- /dev/null
+++ b/libraries/shiro-web/src/main/java/org/apache/polygene/library/shiro/web/package.html
@@ -0,0 +1,34 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Shiro Web Security Library.</h2>
+        <p>
+            This library provide integration with the
+            <a href="http://shiro.apache.org/" target="_blank">Apache Shiro</a> Java Security Framework for webapps.
+        </p>
+        <blockquote>
+            Apache Shiro is a powerful and easy-to-use Java security framework that performs authentication,
+            authorization, cryptography, and session management. With Shiro's easy-to-understand API, you can quickly
+            and easily secure any application – from the smallest mobile applications to the largest web and enterprise
+            applications.
+        </blockquote>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/shiro-web/src/main/java/org/qi4j/library/shiro/web/EnvironmentLoaderService.java b/libraries/shiro-web/src/main/java/org/qi4j/library/shiro/web/EnvironmentLoaderService.java
deleted file mode 100644
index 251eb4e..0000000
--- a/libraries/shiro-web/src/main/java/org/qi4j/library/shiro/web/EnvironmentLoaderService.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.web;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-import org.apache.shiro.mgt.RealmSecurityManager;
-import org.apache.shiro.realm.Realm;
-import org.apache.shiro.web.env.EnvironmentLoader;
-import org.apache.shiro.web.env.WebEnvironment;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.functional.Iterables;
-import org.qi4j.library.shiro.Shiro;
-import org.qi4j.library.shiro.ini.ShiroIniConfiguration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Mixins( EnvironmentLoaderService.Mixin.class )
-public interface EnvironmentLoaderService
-        extends ServletContextListener, ServiceComposite
-{
-
-    public class Mixin
-            extends EnvironmentLoader
-            implements ServletContextListener
-    {
-
-        private static final Logger LOG = LoggerFactory.getLogger( Shiro.LOGGER_NAME );
-
-        @This
-        private Configuration<ShiroIniConfiguration> configuration;
-
-        @Optional
-        @Service
-        private Iterable<ServiceReference<Realm>> realmsRefs;
-
-        @Override
-        public void contextInitialized( ServletContextEvent sce )
-        {
-            configuration.refresh();
-            ShiroIniConfiguration config = configuration.get();
-            String iniResourcePath = config.iniResourcePath().get() == null ? "classpath:shiro.ini" : config.iniResourcePath().get();
-            sce.getServletContext().setInitParameter( "shiroConfigLocations", iniResourcePath );
-            WebEnvironment env = initEnvironment( sce.getServletContext() );
-
-            if ( realmsRefs != null && Iterables.count( realmsRefs ) > 0 ) {
-
-                // Register Realms Services
-                RealmSecurityManager realmSecurityManager = ( RealmSecurityManager ) env.getSecurityManager();
-                Collection<Realm> iniRealms = new ArrayList<Realm>( realmSecurityManager.getRealms() );
-                for ( ServiceReference<Realm> realmRef : realmsRefs ) {
-                    iniRealms.add( realmRef.get() );
-                    LOG.debug( "Realm Service '{}' registered!", realmRef.identity() );
-                }
-                realmSecurityManager.setRealms( iniRealms );
-
-            }
-
-        }
-
-        @Override
-        public void contextDestroyed( ServletContextEvent sce )
-        {
-            destroyEnvironment( sce.getServletContext() );
-        }
-
-    }
-
-}
diff --git a/libraries/shiro-web/src/main/java/org/qi4j/library/shiro/web/ShiroFilterService.java b/libraries/shiro-web/src/main/java/org/qi4j/library/shiro/web/ShiroFilterService.java
deleted file mode 100644
index b65faa0..0000000
--- a/libraries/shiro-web/src/main/java/org/qi4j/library/shiro/web/ShiroFilterService.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.web;
-
-import javax.servlet.Filter;
-import org.apache.shiro.web.servlet.ShiroFilter;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-@Mixins( ShiroFilter.class )
-public interface ShiroFilterService
-        extends Filter, ServiceComposite
-{
-}
diff --git a/libraries/shiro-web/src/main/java/org/qi4j/library/shiro/web/assembly/HttpShiroAssembler.java b/libraries/shiro-web/src/main/java/org/qi4j/library/shiro/web/assembly/HttpShiroAssembler.java
deleted file mode 100644
index 494fc19..0000000
--- a/libraries/shiro-web/src/main/java/org/qi4j/library/shiro/web/assembly/HttpShiroAssembler.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.web.assembly;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.shiro.ini.ShiroIniConfiguration;
-import org.qi4j.library.shiro.web.EnvironmentLoaderService;
-import org.qi4j.library.shiro.web.ShiroFilterService;
-
-import static javax.servlet.DispatcherType.ASYNC;
-import static javax.servlet.DispatcherType.ERROR;
-import static javax.servlet.DispatcherType.FORWARD;
-import static javax.servlet.DispatcherType.INCLUDE;
-import static javax.servlet.DispatcherType.REQUEST;
-import static org.qi4j.library.http.Servlets.addContextListeners;
-import static org.qi4j.library.http.Servlets.addFilters;
-import static org.qi4j.library.http.Servlets.filter;
-import static org.qi4j.library.http.Servlets.listen;
-
-public class HttpShiroAssembler
-    extends Assemblers.Config<HttpShiroAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        addContextListeners( listen().
-            with( EnvironmentLoaderService.class ) ).
-            to( module );
-
-        addFilters( filter( "/*" ).
-            through( ShiroFilterService.class ).
-            on( REQUEST, FORWARD, INCLUDE, ERROR, ASYNC ) ).
-            to( module );
-
-        if( hasConfig() )
-        {
-            configModule().entities( ShiroIniConfiguration.class ).
-                visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/libraries/shiro-web/src/main/java/org/qi4j/library/shiro/web/assembly/package.html b/libraries/shiro-web/src/main/java/org/qi4j/library/shiro/web/assembly/package.html
deleted file mode 100644
index 14673b5..0000000
--- a/libraries/shiro-web/src/main/java/org/qi4j/library/shiro/web/assembly/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Shiro Web Security Assembly.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/shiro-web/src/main/java/org/qi4j/library/shiro/web/package.html b/libraries/shiro-web/src/main/java/org/qi4j/library/shiro/web/package.html
deleted file mode 100644
index af1d4b8..0000000
--- a/libraries/shiro-web/src/main/java/org/qi4j/library/shiro/web/package.html
+++ /dev/null
@@ -1,31 +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.
--->
-<html>
-    <body>
-        <h2>Shiro Web Security Library.</h2>
-        <p>
-            This library provide integration with the
-            <a href="http://shiro.apache.org/" target="_blank">Apache Shiro</a> Java Security Framework for webapps.
-        </p>
-        <blockquote>
-            Apache Shiro is a powerful and easy-to-use Java security framework that performs authentication,
-            authorization, cryptography, and session management. With Shiro's easy-to-understand API, you can quickly
-            and easily secure any application – from the smallest mobile applications to the largest web and enterprise
-            applications.
-        </blockquote>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/shiro-web/src/test/java/org/apache/polygene/library/shiro/web/WebHttpShiroTest.java b/libraries/shiro-web/src/test/java/org/apache/polygene/library/shiro/web/WebHttpShiroTest.java
new file mode 100644
index 0000000..e34edd0
--- /dev/null
+++ b/libraries/shiro-web/src/test/java/org/apache/polygene/library/shiro/web/WebHttpShiroTest.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.library.shiro.web;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.http.JettyConfiguration;
+import org.apache.polygene.library.http.JettyServiceAssembler;
+import org.apache.polygene.library.shiro.ini.ShiroIniConfiguration;
+import org.apache.polygene.library.shiro.web.assembly.HttpShiroAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.util.FreePortFinder;
+
+public class WebHttpShiroTest
+    extends AbstractPolygeneTest
+{
+    private int port;
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ModuleAssembly configModule = module;
+        new EntityTestAssembler().assemble( configModule );
+        // START SNIPPET: assembly
+        new JettyServiceAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
+        // END SNIPPET: assembly
+
+        port = FreePortFinder.findFreePortOnLoopback();
+        JettyConfiguration config = module.forMixin( JettyConfiguration.class ).declareDefaults();
+        config.hostName().set( "127.0.0.1" );
+        config.port().set( port );
+
+        // START SNIPPET: assembly
+        new HttpShiroAssembler()
+            .withConfig( configModule, Visibility.layer )
+            .assemble( module );
+        // END SNIPPET: assembly
+
+        configModule.forMixin( ShiroIniConfiguration.class )
+                    .declareDefaults().iniResourcePath().set( "classpath:web-shiro.ini" );
+    }
+
+    @Test
+    public void test()
+    {
+    }
+}
diff --git a/libraries/shiro-web/src/test/java/org/apache/polygene/library/shiro/web/WebRealmServiceTest.java b/libraries/shiro-web/src/test/java/org/apache/polygene/library/shiro/web/WebRealmServiceTest.java
new file mode 100644
index 0000000..cebe368
--- /dev/null
+++ b/libraries/shiro-web/src/test/java/org/apache/polygene/library/shiro/web/WebRealmServiceTest.java
@@ -0,0 +1,221 @@
+/*
+ *  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.polygene.library.shiro.web;
+
+import java.io.IOException;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.http.HttpException;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpRequestInterceptor;
+import org.apache.http.HttpResponse;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.AuthState;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.protocol.ClientContext;
+import org.apache.http.impl.auth.BasicScheme;
+import org.apache.http.impl.client.BasicResponseHandler;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.protocol.ExecutionContext;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.util.EntityUtils;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.shiro.authc.credential.DefaultPasswordService;
+import org.apache.shiro.authc.credential.PasswordMatcher;
+import org.apache.shiro.authc.credential.PasswordService;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.realm.SimpleAccountRealm;
+import org.junit.Test;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.http.JettyConfiguration;
+import org.apache.polygene.library.http.JettyServiceAssembler;
+import org.apache.polygene.library.shiro.ini.ShiroIniConfiguration;
+import org.apache.polygene.library.shiro.web.assembly.HttpShiroAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.util.FreePortFinder;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.apache.polygene.library.http.Servlets.addServlets;
+import static org.apache.polygene.library.http.Servlets.serve;
+
+public class WebRealmServiceTest
+    extends AbstractPolygeneTest
+{
+    private final int port = FreePortFinder.findFreePortOnLoopback();
+
+    @Mixins( MyRealmMixin.class )
+    public interface MyRealmService
+        extends Realm, ServiceComposite, ServiceActivation
+    {
+    }
+
+    public class MyRealmMixin
+        extends SimpleAccountRealm
+        implements ServiceActivation
+    {
+        private final PasswordService passwordService;
+
+        public MyRealmMixin()
+        {
+            super();
+            passwordService = new DefaultPasswordService();
+            PasswordMatcher matcher = new PasswordMatcher();
+            matcher.setPasswordService( passwordService );
+            setCredentialsMatcher( matcher );
+        }
+
+        @Override
+        public void activateService()
+            throws Exception
+        {
+            // Create a test account
+            addAccount( "foo", passwordService.encryptPassword( "bar" ) );
+        }
+
+        @Override
+        public void passivateService()
+            throws Exception
+        {
+        }
+    }
+
+    @Mixins( MyServlet.class )
+    public interface MyServletService
+        extends Servlet, ServiceComposite
+    {
+    }
+
+    public static class MyServlet
+        extends HttpServlet
+    {
+        @Override
+        protected void doGet( HttpServletRequest req, HttpServletResponse resp )
+            throws ServletException, IOException
+        {
+            resp.getWriter().println( "FOO" );
+        }
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ModuleAssembly configModule = module;
+        new EntityTestAssembler().assemble( configModule );
+        // START SNIPPET: assembly
+        new JettyServiceAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
+        // END SNIPPET: assembly
+
+        JettyConfiguration config = module.forMixin( JettyConfiguration.class ).declareDefaults();
+        config.hostName().set( "127.0.0.1" );
+        config.port().set( port );
+
+        // START SNIPPET: assembly
+        new HttpShiroAssembler()
+            .withConfig( configModule, Visibility.layer )
+            .assemble( module );
+        module.services( MyRealmService.class );
+        // END SNIPPET: assembly
+
+        configModule.forMixin( ShiroIniConfiguration.class )
+                    .declareDefaults().iniResourcePath().set( "classpath:web-shiro.ini" );
+
+        addServlets( serve( "/*" ).with( MyServletService.class ) ).to( module );
+    }
+
+    @Test
+    public void test()
+        throws IOException
+    {
+        DefaultHttpClient client = new DefaultHttpClient();
+
+        // Our request method
+        HttpGet get = new HttpGet( "http://127.0.0.1:" + port + "/" );
+
+        HttpResponse response = client.execute( get );
+        int status = response.getStatusLine().getStatusCode();
+
+        assertThat( String.valueOf( status ).substring( 0, 1 ) + "xx", is( "4xx" ) );
+
+        EntityUtils.consume( response.getEntity() );
+
+        // Simple interceptor set as first interceptor in the protocol chain
+        HttpRequestInterceptor preemptiveAuth = new BasicAuthRequestInterceptor();
+        client.addRequestInterceptor( preemptiveAuth, 0 );
+
+        // Set credentials
+        UsernamePasswordCredentials creds = new UsernamePasswordCredentials( "foo", "bar" );
+        client.getCredentialsProvider().setCredentials( AuthScope.ANY, creds );
+
+        response = client.execute( get );
+        status = response.getStatusLine().getStatusCode();
+
+        assertThat( status, is( 200 ) );
+
+        String result = new BasicResponseHandler().handleResponse( response ).trim();
+        assertThat( result, is( "FOO" ) );
+    }
+
+    /**
+     * HttpClient Basic Auth Request Interceptor.
+     * Needed for HTTP Basic Authentication.
+     */
+    public class BasicAuthRequestInterceptor
+        implements HttpRequestInterceptor
+    {
+        @Override
+        public void process( final HttpRequest request, final HttpContext context )
+            throws HttpException, IOException
+        {
+            AuthState authState = (AuthState) context.getAttribute( ClientContext.TARGET_AUTH_STATE );
+            CredentialsProvider credsProvider = (CredentialsProvider) context
+                .getAttribute( ClientContext.CREDS_PROVIDER );
+            HttpHost targetHost = (HttpHost) context.getAttribute( ExecutionContext.HTTP_TARGET_HOST );
+
+            // If not auth scheme has been initialized yet
+            if( authState.getAuthScheme() == null )
+            {
+                AuthScope authScope = new AuthScope( targetHost.getHostName(),
+                                                     targetHost.getPort() );
+                // Obtain credentials matching the target host
+                Credentials creds = credsProvider.getCredentials( authScope );
+                // If found, generate BasicScheme preemptively
+                if( creds != null )
+                {
+                    authState.setAuthScheme( new BasicScheme() );
+                    authState.setCredentials( creds );
+                }
+            }
+        }
+    }
+}
diff --git a/libraries/shiro-web/src/test/java/org/apache/polygene/library/shiro/web/WebServletShiroTest.java b/libraries/shiro-web/src/test/java/org/apache/polygene/library/shiro/web/WebServletShiroTest.java
new file mode 100644
index 0000000..4d7dfe4
--- /dev/null
+++ b/libraries/shiro-web/src/test/java/org/apache/polygene/library/shiro/web/WebServletShiroTest.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.library.shiro.web;
+
+import java.util.EnumSet;
+import org.apache.shiro.web.env.EnvironmentLoaderListener;
+import org.apache.shiro.web.servlet.ShiroFilter;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.junit.Test;
+import org.apache.polygene.test.util.FreePortFinder;
+
+import static javax.servlet.DispatcherType.*;
+
+public class WebServletShiroTest
+{
+
+    @Test
+    public void test()
+            throws Exception
+    {
+        int port = FreePortFinder.findFreePortOnLoopback();
+        Server server = new Server( port );
+        try {
+
+            ServletContextHandler context = new ServletContextHandler();
+            context.setContextPath( "/" );
+
+            context.setInitParameter( "shiroConfigLocations", "classpath:web-shiro.ini" );
+            context.addEventListener( new EnvironmentLoaderListener() );
+
+            context.addFilter( ShiroFilter.class, "/*", EnumSet.of( REQUEST, FORWARD, INCLUDE, ERROR ) );
+
+            server.setHandler( context );
+            server.start();
+
+            // HttpClient client = new DefaultHttpClient();
+            // String result = client.execute( new HttpGet( "http://127.0.0.1:" + port + "/" ), new BasicResponseHandler() );
+
+        } finally {
+            server.stop();
+        }
+
+    }
+
+}
diff --git a/libraries/shiro-web/src/test/java/org/qi4j/library/shiro/web/WebHttpShiroTest.java b/libraries/shiro-web/src/test/java/org/qi4j/library/shiro/web/WebHttpShiroTest.java
deleted file mode 100644
index 071c71a..0000000
--- a/libraries/shiro-web/src/test/java/org/qi4j/library/shiro/web/WebHttpShiroTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.web;
-
-import java.io.IOException;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.http.JettyConfiguration;
-import org.qi4j.library.http.JettyServiceAssembler;
-import org.qi4j.library.shiro.ini.ShiroIniConfiguration;
-import org.qi4j.library.shiro.web.assembly.HttpShiroAssembler;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.util.FreePortFinder;
-
-public class WebHttpShiroTest
-    extends AbstractQi4jTest
-{
-    private int port;
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        try
-        {
-            ModuleAssembly configModule = module;
-            new EntityTestAssembler().assemble( configModule );
-            // START SNIPPET: assembly
-            new JettyServiceAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
-            // END SNIPPET: assembly
-
-            port = FreePortFinder.findFreePortOnLoopback();
-            JettyConfiguration config = module.forMixin( JettyConfiguration.class ).declareDefaults();
-            config.hostName().set( "127.0.0.1" );
-            config.port().set( port );
-
-            // START SNIPPET: assembly
-            new HttpShiroAssembler().
-                withConfig( configModule, Visibility.layer ).
-                assemble( module );
-            // END SNIPPET: assembly
-
-            configModule.forMixin( ShiroIniConfiguration.class ).
-                declareDefaults().
-                iniResourcePath().set( "classpath:web-shiro.ini" );
-        }
-        catch( IOException ex )
-        {
-            throw new AssemblyException( "Unable to find free port to bind to", ex );
-        }
-    }
-
-    @Test
-    public void test()
-    {
-    }
-}
diff --git a/libraries/shiro-web/src/test/java/org/qi4j/library/shiro/web/WebRealmServiceTest.java b/libraries/shiro-web/src/test/java/org/qi4j/library/shiro/web/WebRealmServiceTest.java
deleted file mode 100644
index 48c198e..0000000
--- a/libraries/shiro-web/src/test/java/org/qi4j/library/shiro/web/WebRealmServiceTest.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.web;
-
-import java.io.IOException;
-import javax.servlet.Servlet;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.apache.http.HttpException;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpRequestInterceptor;
-import org.apache.http.HttpResponse;
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.AuthState;
-import org.apache.http.auth.Credentials;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.CredentialsProvider;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.protocol.ClientContext;
-import org.apache.http.impl.auth.BasicScheme;
-import org.apache.http.impl.client.BasicResponseHandler;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.protocol.ExecutionContext;
-import org.apache.http.protocol.HttpContext;
-import org.apache.http.util.EntityUtils;
-import org.apache.shiro.authc.credential.DefaultPasswordService;
-import org.apache.shiro.authc.credential.PasswordMatcher;
-import org.apache.shiro.authc.credential.PasswordService;
-import org.apache.shiro.realm.Realm;
-import org.apache.shiro.realm.SimpleAccountRealm;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.http.JettyConfiguration;
-import org.qi4j.library.http.JettyServiceAssembler;
-import org.qi4j.library.shiro.ini.ShiroIniConfiguration;
-import org.qi4j.library.shiro.web.assembly.HttpShiroAssembler;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.util.FreePortFinder;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.library.http.Servlets.addServlets;
-import static org.qi4j.library.http.Servlets.serve;
-
-public class WebRealmServiceTest
-    extends AbstractQi4jTest
-{
-
-    private int port;
-
-    @Mixins( MyRealmMixin.class )
-    public interface MyRealmService
-        extends Realm, ServiceComposite, ServiceActivation
-    {
-    }
-
-    public class MyRealmMixin
-        extends SimpleAccountRealm
-        implements ServiceActivation
-    {
-
-        private final PasswordService passwordService;
-
-        public MyRealmMixin()
-        {
-            super();
-            passwordService = new DefaultPasswordService();
-            PasswordMatcher matcher = new PasswordMatcher();
-            matcher.setPasswordService( passwordService );
-            setCredentialsMatcher( matcher );
-        }
-
-        @Override
-        public void activateService()
-            throws Exception
-        {
-            // Create a test account
-            addAccount( "foo", passwordService.encryptPassword( "bar" ) );
-        }
-
-        @Override
-        public void passivateService()
-            throws Exception
-        {
-        }
-
-    }
-
-    @Mixins( MyServlet.class )
-    public interface MyServletService
-        extends Servlet, ServiceComposite
-    {
-    }
-
-    public static class MyServlet
-        extends HttpServlet
-    {
-
-        @Override
-        protected void doGet( HttpServletRequest req, HttpServletResponse resp )
-            throws ServletException, IOException
-        {
-            resp.getWriter().println( "FOO" );
-        }
-
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        try
-        {
-            ModuleAssembly configModule = module;
-            new EntityTestAssembler().assemble( configModule );
-            // START SNIPPET: assembly
-            new JettyServiceAssembler().withConfig( configModule, Visibility.layer ).assemble( module );
-            // END SNIPPET: assembly
-
-            port = FreePortFinder.findFreePortOnLoopback();
-            JettyConfiguration config = module.forMixin( JettyConfiguration.class ).declareDefaults();
-            config.hostName().set( "127.0.0.1" );
-            config.port().set( port );
-
-            // START SNIPPET: assembly
-            new HttpShiroAssembler().
-                withConfig( configModule, Visibility.layer ).
-                assemble( module );
-            module.services( MyRealmService.class );
-            // END SNIPPET: assembly
-
-            configModule.forMixin( ShiroIniConfiguration.class ).
-                declareDefaults().
-                iniResourcePath().set( "classpath:web-shiro.ini" );
-
-            addServlets( serve( "/*" ).with( MyServletService.class ) ).to( module );
-        }
-        catch( IOException ex )
-        {
-            throw new AssemblyException( "Unable to find free port to bind to", ex );
-        }
-    }
-
-    @Test
-    public void test()
-        throws IOException
-    {
-        DefaultHttpClient client = new DefaultHttpClient();
-
-        // Our request method
-        HttpGet get = new HttpGet( "http://127.0.0.1:" + port + "/" );
-
-        HttpResponse response = client.execute( get );
-        int status = response.getStatusLine().getStatusCode();
-
-        assertThat( String.valueOf( status ).substring( 0, 1 ) + "xx", is( "4xx" ) );
-
-        EntityUtils.consume( response.getEntity() );
-
-        // Simple interceptor set as first interceptor in the protocol chain
-        HttpRequestInterceptor preemptiveAuth = new BasicAuthRequestInterceptor();
-        client.addRequestInterceptor( preemptiveAuth, 0 );
-
-        // Set credentials
-        UsernamePasswordCredentials creds = new UsernamePasswordCredentials( "foo", "bar" );
-        client.getCredentialsProvider().setCredentials( AuthScope.ANY, creds );
-
-        response = client.execute( get );
-        status = response.getStatusLine().getStatusCode();
-
-        assertThat( status, is( 200 ) );
-
-        String result = new BasicResponseHandler().handleResponse( response ).trim();
-        assertThat( result, is( "FOO" ) );
-    }
-
-    /**
-     * HttpClient Basic Auth Request Interceptor.
-     * Needed for HTTP Basic Authentication.
-     */
-    public class BasicAuthRequestInterceptor
-        implements HttpRequestInterceptor
-    {
-        @Override
-        public void process( final HttpRequest request, final HttpContext context )
-            throws HttpException, IOException
-        {
-            AuthState authState = (AuthState) context.getAttribute( ClientContext.TARGET_AUTH_STATE );
-            CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute( ClientContext.CREDS_PROVIDER );
-            HttpHost targetHost = (HttpHost) context.getAttribute( ExecutionContext.HTTP_TARGET_HOST );
-
-            // If not auth scheme has been initialized yet
-            if( authState.getAuthScheme() == null )
-            {
-                AuthScope authScope = new AuthScope( targetHost.getHostName(),
-                                                     targetHost.getPort() );
-                // Obtain credentials matching the target host
-                Credentials creds = credsProvider.getCredentials( authScope );
-                // If found, generate BasicScheme preemptively
-                if( creds != null )
-                {
-                    authState.setAuthScheme( new BasicScheme() );
-                    authState.setCredentials( creds );
-                }
-            }
-        }
-    }
-
-}
diff --git a/libraries/shiro-web/src/test/java/org/qi4j/library/shiro/web/WebServletShiroTest.java b/libraries/shiro-web/src/test/java/org/qi4j/library/shiro/web/WebServletShiroTest.java
deleted file mode 100644
index 62e950e..0000000
--- a/libraries/shiro-web/src/test/java/org/qi4j/library/shiro/web/WebServletShiroTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.shiro.web;
-
-import java.util.EnumSet;
-import org.apache.shiro.web.env.EnvironmentLoaderListener;
-import org.apache.shiro.web.servlet.ShiroFilter;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.junit.Test;
-import org.qi4j.test.util.FreePortFinder;
-
-import static javax.servlet.DispatcherType.*;
-
-public class WebServletShiroTest
-{
-
-    @Test
-    public void test()
-            throws Exception
-    {
-        int port = FreePortFinder.findFreePortOnLoopback( 9001 );
-        Server server = new Server( port );
-        try {
-
-            ServletContextHandler context = new ServletContextHandler();
-            context.setContextPath( "/" );
-
-            context.setInitParameter( "shiroConfigLocations", "classpath:web-shiro.ini" );
-            context.addEventListener( new EnvironmentLoaderListener() );
-
-            context.addFilter( ShiroFilter.class, "/*", EnumSet.of( REQUEST, FORWARD, INCLUDE, ERROR ) );
-
-            server.setHandler( context );
-            server.start();
-
-            // HttpClient client = new DefaultHttpClient();
-            // String result = client.execute( new HttpGet( "http://127.0.0.1:" + port + "/" ), new BasicResponseHandler() );
-
-        } finally {
-            server.stop();
-        }
-
-    }
-
-}
diff --git a/libraries/shiro-web/src/test/resources/logback-test.xml b/libraries/shiro-web/src/test/resources/logback-test.xml
index 8c9b50a..3f88299 100644
--- a/libraries/shiro-web/src/test/resources/logback-test.xml
+++ b/libraries/shiro-web/src/test/resources/logback-test.xml
@@ -1,20 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <configuration>
 
     <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
@@ -27,7 +30,7 @@
         <appender-ref ref="stdout" />
     </root>
 
-    <logger name="org.qi4j.library.shiro" level="trace"/>
+    <logger name="org.apache.polygene.library.shiro" level="trace"/>
     <logger name="org.apache.shiro" level="trace"/>
     <logger name="org.apache.shiro.util.ThreadContext" level="info"/>
 
diff --git a/libraries/spring/build.gradle b/libraries/spring/build.gradle
index f5b1613..26a9dde 100644
--- a/libraries/spring/build.gradle
+++ b/libraries/spring/build.gradle
@@ -1,33 +1,37 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Spring Library allows for tight integration of Spring Framework and Apache Zest™ applications."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - Spring" }}
+description = "Apache Polygene™ Spring Library allows for tight integration of Spring Framework and Apache Polygene™ applications."
+
+jar { manifest { name = "Apache Polygene™ Library - Spring" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile(libraries.spring_core)
+  api polygene.core.bootstrap
+  api libraries.spring_core
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-  testCompile(libraries.spring_testsupport)
+  runtimeOnly polygene.core.runtime
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  testImplementation polygene.core.testsupport
+  testImplementation libraries.spring_testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/libraries/spring/dev-status.xml b/libraries/spring/dev-status.xml
index 58fda09..7a96a31 100644
--- a/libraries/spring/dev-status.xml
+++ b/libraries/spring/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>beta</codebase>
diff --git a/libraries/spring/src/docs/spring.txt b/libraries/spring/src/docs/spring.txt
index 12ec47e..ccd050c 100644
--- a/libraries/spring/src/docs/spring.txt
+++ b/libraries/spring/src/docs/spring.txt
@@ -27,38 +27,38 @@
 
 include::../../build/docs/buildinfo/artifact.txt[]
 
-== Using Spring Framework in Apache Zest™ ==
-Zest™ supports that Spring Application Context is imported into the Zest™ runtime, and the declared Spring
-beans will be available as Zest™ services. The most important things to remember are;
+== Using Spring Framework in Apache Polygene™ ==
+Polygene™ supports that Spring Application Context is imported into the Polygene™ runtime, and the declared Spring
+beans will be available as Polygene™ services. The most important things to remember are;
 
     1. Only Spring Singletons are currently supported.
-    2. One ApplicationContext per Zest™ Module.
-    3. The Zest™ service will be given the same name as the Spring Bean name.
-    4. Zest™ Configuration is not reacbable from the Spring bean (kind of obvious).
+    2. One ApplicationContext per Polygene™ Module.
+    3. The Polygene™ service will be given the same name as the Spring Bean name.
+    4. Polygene™ Configuration is not reacbable from the Spring bean (kind of obvious).
 
 [snippet,java]
 ----
-source=libraries/spring/src/test/java/org/qi4j/library/spring/importer/Qi4jImportServiceTest.java
+source=libraries/spring/src/test/java/org/apache/polygene/library/spring/importer/PolygeneImportServiceTest.java
 tag=import
 ----
 
-== Using Apache Zest™ in Spring Framework ==
-It is also possible to run a Zest™ Application as a Spring Bean and export its Services to Spring.
+== Using Apache Polygene™ in Spring Framework ==
+It is also possible to run a Polygene™ Application as a Spring Bean and export its Services to Spring.
 
-Steps to export Zest™ service:
+Steps to export Polygene™ service:
 
-    1. Create spring BeanFactory service of qi4j services to export.
-    2. Create a class that extends Qi4jApplicationBootstrap.
+    1. Create spring BeanFactory service of Polygene services to export.
+    2. Create a class that extends PolygeneApplicationBootstrap.
     3. Sets the layer and module that register BeanFactory service.
-    4. Assemble qi4j application by implementing #assemble method.
+    4. Assemble Polygene application by implementing #assemble method.
     5. Sets the identity of bean factory service. This identity is the spring bean name.
-    6. Declare qi4j bootstrap in spring xml application context.
+    6. Declare Polygene bootstrap in spring xml application context.
 
-To bootstrap the Zest™ runtime in Spring, you should have a bootstrap bean that extends the
-+org.qi4j.library.spring.bootstrap.Qi4jApplicationBootstrap+ and implement the
+To bootstrap the Polygene™ runtime in Spring, you should have a bootstrap bean that extends the
++org.apache.polygene.library.spring.bootstrap.PolygeneApplicationBootstrap+ and implement the
 +org.springframework.context.ApplicationContextAware+.
 
-A new bean will appear in the application context, called +"qi4jApplication"+ which is only
+A new bean will appear in the application context, called +"polygeneApplication"+ which is only
 intended for internal use of this library.
 
 Example application context;
@@ -68,24 +68,24 @@
 
  <beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xmlns:qi4j="http://www.qi4j.org/schema/qi4j/spring"
+  xmlns:polygene="http://polygene.apache.org/schema/polygene/spring"
   xsi:schemaLocation="
   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
-  http://www.qi4j.org/schema/qi4j/spring http://www.qi4j.org/schema/qi4j/spring/spring-0.5.xsd">
+  http://polygene.apache.org/schema/polygene/spring http://polygene.apache.org/schema/polygene/spring/spring-0.5.xsd">
 
-  <!-- class that implements Qi4jApplicationBootstrap -->
+  <!-- class that implements PolygeneApplicationBootstrap -->
 
-  <qi4j:bootstrap class="org.hedhman.niclas.MyZestBootstrapper"/>
+  <polygene:bootstrap class="org.hedhman.niclas.MyPolygeneBootstrapper"/>
 
   <bean id="someService" class="org.hedhman.niclas.SomeService">
 
-  <constructor-arg ref="someService"/> <!-- Reference qi4j comment service -->
+  <constructor-arg ref="someService"/> <!-- Reference polygene comment service -->
 
  </bean>
 ----
 
 [snippet,java]
 ----
-source=libraries/spring/src/test/java/org/qi4j/library/spring/MyZestBootstrapper.java
+source=libraries/spring/src/test/java/org/apache/polygene/library/spring/MyPolygeneBootstrapper.java
 tag=code
 ----
diff --git a/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/Constants.java b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/Constants.java
new file mode 100644
index 0000000..5b99275
--- /dev/null
+++ b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/Constants.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.spring.bootstrap;
+
+public final class Constants
+{
+    public static final String BEAN_ID_POLYGENE_APPLICATION = "polygeneApplication";
+
+    private Constants()
+    {
+    }
+}
diff --git a/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/PolygeneApplicationBootstrap.java b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/PolygeneApplicationBootstrap.java
new file mode 100644
index 0000000..2b33e22
--- /dev/null
+++ b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/PolygeneApplicationBootstrap.java
@@ -0,0 +1,88 @@
+/*
+ *  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.polygene.library.spring.bootstrap;
+
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.springframework.context.ApplicationContextAware;
+
+/**
+ * Run a Polygene Application as a Spring Bean and export its Services to Spring.
+ * <p>
+ * Steps to export Polygene service:
+ * </p>
+ * <ul>
+ * <li>Create spring BeanFactory service of Apache Polygene services to export.</li>
+ * <li>Create a class that extends {@link PolygeneApplicationBootstrap}.</li>
+ * <li>Sets the layer and module that register BeanFactory service.</li>
+ * <li>Assemble Polygene application by implementing #assemble method.</li>
+ * <li>Sets the reference of bean factory service. This reference is the spring
+ * bean name.</li>
+ * <li>Declare Polygene bootstrap in spring xml application context.
+ * <pre><code>
+ * &lt;?xml version="1.0" encoding="UTF-8"?&gt;
+ *
+ * &lt;beans xmlns="http://www.springframework.org/schema/beans"
+ * xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ * xmlns:polygene="http://polygene.apache.org/schema/polygene/spring"
+ * xsi:schemaLocation="
+ * http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ * http://polygene.apache.org/schema/polygene/spring http://polygene.apache.org/schema/polygene/spring/spring-0.5.xsd"&gt;
+ *
+ * &lt;!-- class that implements PolygeneApplicationBootstrap --&gt;
+ *
+ * &lt;polygene:bootstrap class="org.apache.polygene.library.spring.bootstrap.PolygeneTestBootstrap"/&gt;
+ *
+ * &lt;bean id="commentServiceHolder" class="org.apache.polygene.library.spring.bootstrap.CommentServiceHolder"&gt;
+ *
+ * &lt;constructor-arg ref="commentService"/&gt; &lt;!-- Reference Polygene comment service --&gt;
+ *
+ * &lt;/bean&gt;
+ * </code></pre>
+ * </li>
+ * </ul>
+ * <p>
+ * <b>Importing Spring beans as services</b><br>
+ * </p>
+ * <ol>
+ * <li>Application bootstrap class must implement interface
+ * {@link ApplicationContextAware}.</li>
+ * <li>In the application bootstrap import service to the module using method
+ * {@link ModuleAssembly#importedServices(Class...)}.</li>
+ * <li>Set concrete Spring bean as meta-data of the imported service.</li>
+ * </ol>
+ * <p>
+ * Look at org.apache.polygene.library.spring.bootstrap.PolygeneExportServiceTest for sample
+ * implementation.
+ * </p>
+ */
+public abstract class PolygeneApplicationBootstrap
+{
+    /**
+     * Assembles Polygene application.
+     * 
+     * @param applicationAssembly
+     *            Polygene application assembly. Must not be {@code null}.
+     * @throws AssemblyException
+     *             Thrown if assemblies fails.
+     */
+    public abstract void assemble( ApplicationAssembly applicationAssembly ) throws AssemblyException;
+}
diff --git a/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/PolygeneNamespaceHandler.java b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/PolygeneNamespaceHandler.java
new file mode 100644
index 0000000..6cbf7b4
--- /dev/null
+++ b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/PolygeneNamespaceHandler.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.library.spring.bootstrap.internal;
+
+import org.apache.polygene.library.spring.bootstrap.internal.application.PolygeneBootstrapBeanDefinitionParser;
+import org.apache.polygene.library.spring.bootstrap.internal.service.PolygeneServiceBeanDefinitionParser;
+import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
+
+public final class PolygeneNamespaceHandler extends NamespaceHandlerSupport
+{
+    @Override
+    public final void init()
+    {
+        registerBeanDefinitionParser( "bootstrap", new PolygeneBootstrapBeanDefinitionParser() );
+        registerBeanDefinitionParser( "service", new PolygeneServiceBeanDefinitionParser() );
+    }
+}
diff --git a/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/application/PolygeneApplicationFactoryBean.java b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/application/PolygeneApplicationFactoryBean.java
new file mode 100644
index 0000000..cbca71e
--- /dev/null
+++ b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/application/PolygeneApplicationFactoryBean.java
@@ -0,0 +1,114 @@
+/*
+ *  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.polygene.library.spring.bootstrap.internal.application;
+
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.*;
+import org.apache.polygene.library.spring.bootstrap.PolygeneApplicationBootstrap;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanInitializationException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.util.Assert;
+
+/**
+ * This class responsible to handle the lifecycle of Polygene application.
+ */
+public final class PolygeneApplicationFactoryBean
+        implements FactoryBean, DisposableBean, InitializingBean, ApplicationContextAware
+{
+
+    private final PolygeneApplicationBootstrap applicationBootstrap;
+
+    private Application application;
+
+    public PolygeneApplicationFactoryBean( final PolygeneApplicationBootstrap applicationBootstrap )
+    {
+        Assert.notNull( applicationBootstrap, "'applicationBootstrap' must not be null" );
+        this.applicationBootstrap = applicationBootstrap;
+    }
+
+    @Override
+    public final Application getObject() throws Exception
+    {
+        if ( this.application == null )
+        {
+            this.application = this.createApplication();
+        }
+        return this.application;
+    }
+
+    @Override
+    public final Class<Application> getObjectType()
+    {
+        return Application.class;
+    }
+
+    @Override
+    public final boolean isSingleton()
+    {
+        return true;
+    }
+
+    @Override
+    public final void destroy() throws Exception
+    {
+        this.getObject().passivate();
+    }
+
+    @Override
+    public final void afterPropertiesSet() throws Exception
+    {
+        this.getObject().activate();
+    }
+
+    private Application createApplication()
+    {
+        Energy4Java energy4Java = new Energy4Java();
+        try
+        {
+            return energy4Java.newApplication(
+                factory ->
+                {
+                    ApplicationAssembly applicationAssembly = factory.newApplicationAssembly();
+                    applicationBootstrap.assemble( applicationAssembly );
+                    return applicationAssembly;
+                } );
+        } catch ( AssemblyException e )
+        {
+            throw new BeanInitializationException( "Fail to bootstrap Polygene application.", e );
+        }
+
+    }
+
+    @Override
+    public void setApplicationContext( final ApplicationContext applicationContext ) throws BeansException
+    {
+        if ( this.applicationBootstrap instanceof ApplicationContextAware )
+        {
+            // propagate application context to the application bootstrap
+            ApplicationContextAware aware = (ApplicationContextAware) this.applicationBootstrap;
+            aware.setApplicationContext( applicationContext );
+        }
+    }
+}
diff --git a/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/application/PolygeneBootstrapBeanDefinitionParser.java b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/application/PolygeneBootstrapBeanDefinitionParser.java
new file mode 100644
index 0000000..694a1a7
--- /dev/null
+++ b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/application/PolygeneBootstrapBeanDefinitionParser.java
@@ -0,0 +1,103 @@
+/*
+ *  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.polygene.library.spring.bootstrap.internal.application;
+
+import org.apache.polygene.library.spring.bootstrap.PolygeneApplicationBootstrap;
+import org.springframework.beans.BeanInstantiationException;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.xml.BeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.beans.factory.xml.XmlReaderContext;
+import org.w3c.dom.Element;
+
+import static org.apache.polygene.library.spring.bootstrap.Constants.BEAN_ID_POLYGENE_APPLICATION;
+import static org.springframework.beans.BeanUtils.instantiateClass;
+import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
+import static org.springframework.util.Assert.hasText;
+import static org.springframework.util.ClassUtils.forName;
+
+public final class PolygeneBootstrapBeanDefinitionParser
+        implements BeanDefinitionParser
+{
+
+    private static final String CLASS = "class";
+
+    @Override
+    public final BeanDefinition parse( Element anElement, ParserContext aParserContext )
+    {
+        PolygeneApplicationBootstrap bootstrap = createPolygeneApplicationBootstrap( anElement, aParserContext );
+        AbstractBeanDefinition factoryBeanDefinition = createPolygeneApplicationFactoryBeanDefinition( bootstrap );
+        registerBean( aParserContext, factoryBeanDefinition );
+        return factoryBeanDefinition;
+    }
+
+    private PolygeneApplicationBootstrap createPolygeneApplicationBootstrap( Element anElement, ParserContext aParserContext )
+    {
+        String bootstrapClassString = anElement.getAttribute( CLASS );
+        hasText( bootstrapClassString, "No " + CLASS + " attribute found" );
+        XmlReaderContext readerContext = aParserContext.getReaderContext();
+
+        Class<?> bootstrapClass;
+        try
+        {
+            bootstrapClass = forName( bootstrapClassString, getClass().getClassLoader() );
+        } catch ( ClassNotFoundException e )
+        {
+            readerContext.error( "Polygene bootstrap class [" + bootstrapClassString + "] is not found.", anElement );
+            return null;
+        }
+
+        if ( !PolygeneApplicationBootstrap.class.isAssignableFrom( bootstrapClass ) )
+        {
+            readerContext.error( CLASS + "attribute is not an instance of [" + PolygeneApplicationBootstrap.class.getName()
+                    + "] class", anElement );
+            return null;
+        }
+
+        PolygeneApplicationBootstrap bootstrap = null;
+        try
+        {
+            bootstrap = (PolygeneApplicationBootstrap) instantiateClass( bootstrapClass );
+        } catch ( BeanInstantiationException e )
+        {
+            readerContext.error( "Fail to instantiate Polygene bootstrap class [" + bootstrapClassString + "]", anElement,
+                    e );
+        }
+        return bootstrap;
+    }
+
+    private AbstractBeanDefinition createPolygeneApplicationFactoryBeanDefinition(
+        final PolygeneApplicationBootstrap applicationBootstrap
+    )
+    {
+        BeanDefinitionBuilder builder = rootBeanDefinition( PolygeneApplicationFactoryBean.class );
+        builder.addConstructorArgValue( applicationBootstrap );
+        return builder.getBeanDefinition();
+    }
+
+    private void registerBean( ParserContext aParserContext, BeanDefinition aBeanDefinition )
+    {
+        BeanDefinitionRegistry registry = aParserContext.getRegistry();
+        registry.registerBeanDefinition( BEAN_ID_POLYGENE_APPLICATION, aBeanDefinition );
+    }
+}
\ No newline at end of file
diff --git a/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/application/package.html b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/application/package.html
new file mode 100644
index 0000000..055a20c
--- /dev/null
+++ b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/application/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Spring Integration internal package.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/package.html b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/package.html
new file mode 100644
index 0000000..055a20c
--- /dev/null
+++ b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Spring Integration internal package.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/service/PolygeneServiceBeanDefinitionParser.java b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/service/PolygeneServiceBeanDefinitionParser.java
new file mode 100644
index 0000000..401fd39
--- /dev/null
+++ b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/service/PolygeneServiceBeanDefinitionParser.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.library.spring.bootstrap.internal.service;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.xml.BeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.w3c.dom.Element;
+
+import static org.apache.polygene.library.spring.bootstrap.Constants.BEAN_ID_POLYGENE_APPLICATION;
+import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
+
+public final class PolygeneServiceBeanDefinitionParser
+    implements BeanDefinitionParser
+{
+    private static final String SERVICE_ID = "id";
+
+    @Override
+    public final BeanDefinition parse( Element anElement, ParserContext aParserContext )
+    {
+        String serviceId = anElement.getAttribute( SERVICE_ID );
+
+        // Service factory bean
+        BeanDefinitionBuilder builder = rootBeanDefinition( ServiceFactoryBean.class );
+        builder.addConstructorArgReference( BEAN_ID_POLYGENE_APPLICATION );
+        builder.addConstructorArgValue( serviceId );
+        AbstractBeanDefinition definition = builder.getBeanDefinition();
+
+        // Register service factory bean
+        BeanDefinitionRegistry definitionRegistry = aParserContext.getRegistry();
+        definitionRegistry.registerBeanDefinition( serviceId, definition );
+
+        return definition;
+    }
+}
diff --git a/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/service/ServiceFactoryBean.java b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/service/ServiceFactoryBean.java
new file mode 100644
index 0000000..6f9f1bb
--- /dev/null
+++ b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/service/ServiceFactoryBean.java
@@ -0,0 +1,67 @@
+/*
+ *  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.polygene.library.spring.bootstrap.internal.service;
+
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Application;
+import org.springframework.beans.factory.FactoryBean;
+
+import static org.springframework.util.Assert.notNull;
+
+public final class ServiceFactoryBean
+    implements FactoryBean
+{
+    private ServiceReference serviceReference;
+
+    public ServiceFactoryBean( Application anApplication, String aServiceId )
+        throws IllegalArgumentException
+    {
+        notNull( anApplication, "Argument [anApplication] must not be [null]." );
+        notNull( aServiceId, "Argument [aServiceId] must not be [null]." );
+
+        ServiceLocator serviceLocator = new ServiceLocator( aServiceId );
+        anApplication.descriptor().accept( serviceLocator );
+        serviceReference = serviceLocator.locateService( anApplication );
+
+        if( serviceReference == null )
+        {
+            throw new IllegalArgumentException( "Polygene service with id [" + aServiceId + "] is not found." );
+        }
+    }
+
+    @Override
+    public final Object getObject()
+        throws Exception
+    {
+        return serviceReference.get();
+    }
+
+    @Override
+    public final Class getObjectType()
+    {
+        return serviceReference.types().findFirst().orElse( null );
+    }
+
+    @Override
+    public final boolean isSingleton()
+    {
+        return false;
+    }
+}
diff --git a/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/service/ServiceLocator.java b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/service/ServiceLocator.java
new file mode 100644
index 0000000..a72408e
--- /dev/null
+++ b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/service/ServiceLocator.java
@@ -0,0 +1,124 @@
+/*
+ *  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.polygene.library.spring.bootstrap.internal.service;
+
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+
+final class ServiceLocator
+    implements HierarchicalVisitor<Object, Object, RuntimeException>
+{
+    private final String serviceId;
+    private Class<?> serviceType;
+    private String moduleName;
+    private String layerName;
+
+    private String tempLayerName;
+    private String tempModuleName;
+
+    ServiceLocator( String serviceId )
+    {
+        this.serviceId = serviceId;
+    }
+
+    @Override
+    public boolean visitEnter( Object visited )
+        throws RuntimeException
+    {
+        if( visited instanceof ApplicationDescriptor )
+        {
+            return true;
+        }
+        else if( visited instanceof LayerDescriptor )
+        {
+            tempLayerName = ( (LayerDescriptor) visited ).name();
+            return true;
+        }
+        else if( visited instanceof ModuleDescriptor )
+        {
+            tempModuleName = ( (ModuleDescriptor) visited ).name();
+            return true;
+        }
+        else if( visited instanceof ServiceDescriptor )
+        {
+            ServiceDescriptor aDescriptor = (ServiceDescriptor) visited;
+            String identity = aDescriptor.identity().toString();
+            if( serviceId.equals( identity ) )
+            {
+                layerName = tempLayerName;
+                moduleName = tempModuleName;
+                serviceType = aDescriptor.types().findFirst().orElse( null );
+            }
+        }
+        else if( visited instanceof ObjectDescriptor )
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean visitLeave( Object visited )
+        throws RuntimeException
+    {
+        return true;
+    }
+
+    @Override
+    public boolean visit( Object visited )
+        throws RuntimeException
+    {
+        if( visited instanceof ImportedServiceDescriptor )
+        {
+            ImportedServiceDescriptor aDescriptor = (ImportedServiceDescriptor) visited;
+            String identity = aDescriptor.identity().toString();
+            if( serviceId.equals( identity ) )
+            {
+                layerName = tempLayerName;
+                moduleName = tempModuleName;
+                serviceType = aDescriptor.type();
+            }
+        }
+
+        return true;
+    }
+
+    @SuppressWarnings( "unchecked" )
+    ServiceReference locateService( Application anApplication )
+    {
+        if( layerName != null )
+        {
+            Module module = anApplication.findModule( layerName, moduleName );
+            return module.findServices( serviceType )
+                         .filter( ref -> ref.identity().toString().equals( serviceId ) )
+                         .findFirst().orElse( null );
+        }
+        return null;
+    }
+}
diff --git a/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/service/package.html b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/service/package.html
new file mode 100644
index 0000000..055a20c
--- /dev/null
+++ b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/internal/service/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Spring Integration internal package.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/package.html b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/package.html
new file mode 100644
index 0000000..c94d900
--- /dev/null
+++ b/libraries/spring/src/main/java/org/apache/polygene/library/spring/bootstrap/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Run a Polygene™ Application as a Spring Bean and export its Services to Spring.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/spring/src/main/java/org/apache/polygene/library/spring/importer/SpringImporter.java b/libraries/spring/src/main/java/org/apache/polygene/library/spring/importer/SpringImporter.java
new file mode 100644
index 0000000..8f5839f
--- /dev/null
+++ b/libraries/spring/src/main/java/org/apache/polygene/library/spring/importer/SpringImporter.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.library.spring.importer;
+
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.ServiceImporterException;
+import org.springframework.context.ApplicationContext;
+
+/**
+ * Import a service from Spring. This assumes that the service has been imported
+ * into the assembly using the SpringImporterAssembler, so that the ApplicationContext
+ * is available as service meta-info.
+ */
+public class SpringImporter
+    implements ServiceImporter
+{
+    /**
+     * Import a service from Spring by looking it up in the ApplicationContext.
+     *
+     * @param serviceDescriptor The service descriptor.
+     * @return a service instance
+     * @throws ServiceImporterException if unable to import the service
+     */
+    @Override
+    public Object importService( ImportedServiceDescriptor serviceDescriptor ) throws ServiceImporterException
+    {
+        try
+        {
+            return serviceDescriptor.
+                metaInfo( ApplicationContext.class ).
+                getBean( serviceDescriptor.identity().toString(), serviceDescriptor.type() );
+        }
+        catch( Throwable e )
+        {
+            throw new ServiceImporterException( "Could not import Spring service with id " + serviceDescriptor.identity(), e );
+        }
+    }
+
+    @Override
+    public boolean isAvailable( Object instance )
+    {
+        return true;
+    }
+}
diff --git a/libraries/spring/src/main/java/org/apache/polygene/library/spring/importer/SpringImporterAssembler.java b/libraries/spring/src/main/java/org/apache/polygene/library/spring/importer/SpringImporterAssembler.java
new file mode 100644
index 0000000..ecafc5a
--- /dev/null
+++ b/libraries/spring/src/main/java/org/apache/polygene/library/spring/importer/SpringImporterAssembler.java
@@ -0,0 +1,79 @@
+/*
+ *  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.polygene.library.spring.importer;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.springframework.context.ApplicationContext;
+
+/**
+ * Imports all services in the given Spring ApplicationContext into a module.
+ */
+public class SpringImporterAssembler
+    implements Assembler
+{
+    private ApplicationContext context;
+    private Visibility defaultVisibility;
+
+    /**
+     * Import all beans from the given ApplicationContext as services in Polygene,
+     * using Module as Visibility.
+     *
+     * @param context the Spring ApplicationContext
+     */
+    public SpringImporterAssembler( ApplicationContext context )
+    {
+        this( context, Visibility.module );
+    }
+
+
+    /**
+     * Import all beans from the given ApplicationContext as services in Polygene,
+     * using the specified Visibility level.
+     *
+     * @param context           the Spring ApplicationContext
+     * @param defaultVisibility the visibility level for the imported services
+     */
+    public SpringImporterAssembler( ApplicationContext context, Visibility defaultVisibility )
+    {
+        this.context = context;
+        this.defaultVisibility = defaultVisibility;
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module ) throws AssemblyException
+    {
+        // Register all Spring beans as services
+        String[] names = context.getBeanDefinitionNames();
+        for( String name : names )
+        {
+            Class serviceType = context.getType( name );
+            module.
+                importedServices( serviceType ).
+                importedBy( SpringImporter.class ).
+                identifiedBy( name ).
+                setMetaInfo( context ).
+                visibleIn( defaultVisibility );
+        }
+    }
+}
diff --git a/libraries/spring/src/main/java/org/apache/polygene/library/spring/importer/package.html b/libraries/spring/src/main/java/org/apache/polygene/library/spring/importer/package.html
new file mode 100644
index 0000000..8e9bbe1
--- /dev/null
+++ b/libraries/spring/src/main/java/org/apache/polygene/library/spring/importer/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Import Spring Services inside a Polygene™ Application.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/spring/src/main/java/org/apache/polygene/library/spring/package.html b/libraries/spring/src/main/java/org/apache/polygene/library/spring/package.html
new file mode 100644
index 0000000..67fc472
--- /dev/null
+++ b/libraries/spring/src/main/java/org/apache/polygene/library/spring/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Spring Integration.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/Constants.java b/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/Constants.java
deleted file mode 100644
index b51d7dd..0000000
--- a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/Constants.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.library.spring.bootstrap;
-
-public final class Constants
-{
-    public static final String BEAN_ID_QI4J_APPLICATION = "qi4jApplication";
-
-    private Constants()
-    {
-    }
-}
diff --git a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/Qi4jApplicationBootstrap.java b/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/Qi4jApplicationBootstrap.java
deleted file mode 100644
index a60661b..0000000
--- a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/Qi4jApplicationBootstrap.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.library.spring.bootstrap;
-
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.springframework.context.ApplicationContextAware;
-
-/**
- * Run a Zest Application as a Spring Bean and export its Services to Spring.
- * <p>
- * Steps to export Zest service:
- * </p>
- * <ul>
- * <li>Create spring BeanFactory service of qi4j services to export.</li>
- * <li>Create a class that extends {@link Qi4jApplicationBootstrap}.</li>
- * <li>Sets the layer and module that register BeanFactory service.</li>
- * <li>Assemble qi4j application by implementing #assemble method.</li>
- * <li>Sets the identity of bean factory service. This identity is the spring
- * bean name.</li>
- * <li>Declare qi4j bootstrap in spring xml application context.
- * <pre><code>
- * &lt;?xml version="1.0" encoding="UTF-8"?&gt;
- *
- * &lt;beans xmlns="http://www.springframework.org/schema/beans"
- * xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- * xmlns:qi4j="http://www.qi4j.org/schema/qi4j/spring"
- * xsi:schemaLocation="
- * http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- * http://www.qi4j.org/schema/qi4j/spring http://www.qi4j.org/schema/qi4j/spring/spring-0.5.xsd"&gt;
- *
- * &lt;!-- class that implements Qi4jApplicationBootstrap --&gt;
- *
- * &lt;qi4j:bootstrap class="org.qi4j.library.spring.bootstrap.Qi4jTestBootstrap"/&gt;
- *
- * &lt;bean id="commentServiceHolder" class="org.qi4j.library.spring.bootstrap.CommentServiceHolder"&gt;
- *
- * &lt;constructor-arg ref="commentService"/&gt; &lt;!-- Reference qi4j comment service --&gt;
- *
- * &lt;/bean&gt;
- * </code></pre>
- * </li>
- * </ul>
- * <p>
- * <b>Importing Spring beans as services</b><br>
- * </p>
- * <ol>
- * <li>Application bootstrap class must implement interface
- * {@link ApplicationContextAware}.</li>
- * <li>In the application bootstrap import service to the module using method
- * {@link ModuleAssembly#importedServices(Class...)}.</li>
- * <li>Set concrete Spring bean as meta-data of the imported service.</li>
- * </ol>
- * <p>
- * Look at org.qi4j.library.spring.bootstrap.Qi4jExportServiceTest for sample
- * implementation.
- * </p>
- */
-public abstract class Qi4jApplicationBootstrap
-{
-    /**
-     * Assembles qi4j application.
-     * 
-     * @param applicationAssembly
-     *            qi4j application assembly. Must not be {@code null}.
-     * @throws AssemblyException
-     *             Thrown if assemblies fails.
-     */
-    public abstract void assemble( ApplicationAssembly applicationAssembly ) throws AssemblyException;
-}
diff --git a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/Qi4jNamespaceHandler.java b/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/Qi4jNamespaceHandler.java
deleted file mode 100644
index 2f50ee3..0000000
--- a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/Qi4jNamespaceHandler.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.library.spring.bootstrap.internal;
-
-import org.qi4j.library.spring.bootstrap.internal.application.Qi4jBootstrapBeanDefinitionParser;
-import org.qi4j.library.spring.bootstrap.internal.service.Qi4jServiceBeanDefinitionParser;
-import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
-
-public final class Qi4jNamespaceHandler extends NamespaceHandlerSupport
-{
-    @Override
-    public final void init()
-    {
-        registerBeanDefinitionParser( "bootstrap", new Qi4jBootstrapBeanDefinitionParser() );
-        registerBeanDefinitionParser( "service", new Qi4jServiceBeanDefinitionParser() );
-    }
-}
diff --git a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/application/Qi4jApplicationFactoryBean.java b/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/application/Qi4jApplicationFactoryBean.java
deleted file mode 100644
index adbccb8..0000000
--- a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/application/Qi4jApplicationFactoryBean.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.library.spring.bootstrap.internal.application;
-
-import org.qi4j.api.structure.Application;
-import org.qi4j.bootstrap.*;
-import org.qi4j.library.spring.bootstrap.Qi4jApplicationBootstrap;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.BeanInitializationException;
-import org.springframework.beans.factory.DisposableBean;
-import org.springframework.beans.factory.FactoryBean;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.util.Assert;
-
-/**
- * This class responsible to handle the lifecycle of qi4j application.
- */
-public final class Qi4jApplicationFactoryBean
-        implements FactoryBean, DisposableBean, InitializingBean, ApplicationContextAware
-{
-
-    private final Qi4jApplicationBootstrap applicationBootstrap;
-
-    private Application application;
-
-    public Qi4jApplicationFactoryBean( final Qi4jApplicationBootstrap applicationBootstrap )
-    {
-        Assert.notNull( applicationBootstrap, "'applicationBootstrap' must not be null" );
-        this.applicationBootstrap = applicationBootstrap;
-    }
-
-    @Override
-    public final Application getObject() throws Exception
-    {
-        if ( this.application == null )
-        {
-            this.application = this.createApplication();
-        }
-        return this.application;
-    }
-
-    @Override
-    public final Class<Application> getObjectType()
-    {
-        return Application.class;
-    }
-
-    @Override
-    public final boolean isSingleton()
-    {
-        return true;
-    }
-
-    @Override
-    public final void destroy() throws Exception
-    {
-        this.getObject().passivate();
-    }
-
-    @Override
-    public final void afterPropertiesSet() throws Exception
-    {
-        this.getObject().activate();
-    }
-
-    private Application createApplication()
-    {
-        Energy4Java energy4Java = new Energy4Java();
-        try
-        {
-            return energy4Java.newApplication( new ApplicationAssembler()
-            {
-
-                @Override
-                public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-                        throws AssemblyException
-                {
-                    final ApplicationAssembly applicationAssembly = applicationFactory.newApplicationAssembly();
-                    Qi4jApplicationFactoryBean.this.applicationBootstrap.assemble( applicationAssembly );
-                    return applicationAssembly;
-                }
-            } );
-        } catch ( AssemblyException e )
-        {
-            throw new BeanInitializationException( "Fail to bootstrap qi4j application.", e );
-        }
-
-    }
-
-    @Override
-    public void setApplicationContext( final ApplicationContext applicationContext ) throws BeansException
-    {
-        if ( this.applicationBootstrap instanceof ApplicationContextAware )
-        {
-            // propagate application context to the application bootstrap
-            ApplicationContextAware aware = (ApplicationContextAware) this.applicationBootstrap;
-            aware.setApplicationContext( applicationContext );
-        }
-    }
-}
diff --git a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/application/Qi4jBootstrapBeanDefinitionParser.java b/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/application/Qi4jBootstrapBeanDefinitionParser.java
deleted file mode 100644
index fb875b3..0000000
--- a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/application/Qi4jBootstrapBeanDefinitionParser.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.library.spring.bootstrap.internal.application;
-
-import org.qi4j.library.spring.bootstrap.Qi4jApplicationBootstrap;
-import org.springframework.beans.BeanInstantiationException;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.xml.BeanDefinitionParser;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.beans.factory.xml.XmlReaderContext;
-import org.w3c.dom.Element;
-
-import static org.qi4j.library.spring.bootstrap.Constants.BEAN_ID_QI4J_APPLICATION;
-import static org.springframework.beans.BeanUtils.instantiateClass;
-import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
-import static org.springframework.util.Assert.hasText;
-import static org.springframework.util.ClassUtils.forName;
-
-public final class Qi4jBootstrapBeanDefinitionParser
-        implements BeanDefinitionParser
-{
-
-    private static final String CLASS = "class";
-
-    @Override
-    public final BeanDefinition parse( Element anElement, ParserContext aParserContext )
-    {
-        Qi4jApplicationBootstrap bootstrap = createQi4jApplicationBootstrap( anElement, aParserContext );
-        AbstractBeanDefinition factoryBeanDefinition = createQi4jApplicationFactoryBeanDefinition( bootstrap );
-        registerBean( aParserContext, factoryBeanDefinition );
-        return factoryBeanDefinition;
-    }
-
-    private Qi4jApplicationBootstrap createQi4jApplicationBootstrap( Element anElement, ParserContext aParserContext )
-    {
-        String bootstrapClassString = anElement.getAttribute( CLASS );
-        hasText( bootstrapClassString );
-        XmlReaderContext readerContext = aParserContext.getReaderContext();
-
-        Class<?> bootstrapClass;
-        try
-        {
-            bootstrapClass = forName( bootstrapClassString, getClass().getClassLoader() );
-        } catch ( ClassNotFoundException e )
-        {
-            readerContext.error( "Zest bootstrap class [" + bootstrapClassString + "] is not found.", anElement );
-            return null;
-        }
-
-        if ( !Qi4jApplicationBootstrap.class.isAssignableFrom( bootstrapClass ) )
-        {
-            readerContext.error( CLASS + "attribute is not an instance of [" + Qi4jApplicationBootstrap.class.getName()
-                    + "] class", anElement );
-            return null;
-        }
-
-        Qi4jApplicationBootstrap bootstrap = null;
-        try
-        {
-            bootstrap = (Qi4jApplicationBootstrap) instantiateClass( bootstrapClass );
-        } catch ( BeanInstantiationException e )
-        {
-            readerContext.error( "Fail to instantiate qi4j bootstrap class [" + bootstrapClassString + "]", anElement,
-                    e );
-        }
-        return bootstrap;
-    }
-
-    private AbstractBeanDefinition createQi4jApplicationFactoryBeanDefinition(
-            final Qi4jApplicationBootstrap applicationBootstrap )
-    {
-        BeanDefinitionBuilder builder = rootBeanDefinition( Qi4jApplicationFactoryBean.class );
-        builder.addConstructorArgValue( applicationBootstrap );
-        return builder.getBeanDefinition();
-    }
-
-    private void registerBean( ParserContext aParserContext, BeanDefinition aBeanDefinition )
-    {
-        BeanDefinitionRegistry registry = aParserContext.getRegistry();
-        registry.registerBeanDefinition( BEAN_ID_QI4J_APPLICATION, aBeanDefinition );
-    }
-}
\ No newline at end of file
diff --git a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/application/package.html b/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/application/package.html
deleted file mode 100644
index e1c2093..0000000
--- a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/application/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Spring Integration internal package.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/package.html b/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/package.html
deleted file mode 100644
index e1c2093..0000000
--- a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Spring Integration internal package.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/service/Qi4jServiceBeanDefinitionParser.java b/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/service/Qi4jServiceBeanDefinitionParser.java
deleted file mode 100644
index 002936e..0000000
--- a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/service/Qi4jServiceBeanDefinitionParser.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.library.spring.bootstrap.internal.service;
-
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.xml.BeanDefinitionParser;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.w3c.dom.Element;
-
-import static org.qi4j.library.spring.bootstrap.Constants.BEAN_ID_QI4J_APPLICATION;
-import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
-
-public final class Qi4jServiceBeanDefinitionParser
-    implements BeanDefinitionParser
-{
-    private static final String SERVICE_ID = "id";
-
-    @Override
-    public final BeanDefinition parse( Element anElement, ParserContext aParserContext )
-    {
-        String serviceId = anElement.getAttribute( SERVICE_ID );
-
-        // Service factory bean
-        BeanDefinitionBuilder builder = rootBeanDefinition( ServiceFactoryBean.class );
-        builder.addConstructorArgReference( BEAN_ID_QI4J_APPLICATION );
-        builder.addConstructorArgValue( serviceId );
-        AbstractBeanDefinition definition = builder.getBeanDefinition();
-
-        // Register service factory bean
-        BeanDefinitionRegistry definitionRegistry = aParserContext.getRegistry();
-        definitionRegistry.registerBeanDefinition( serviceId, definition );
-
-        return definition;
-    }
-}
diff --git a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/service/ServiceFactoryBean.java b/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/service/ServiceFactoryBean.java
deleted file mode 100644
index 76c5bff..0000000
--- a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/service/ServiceFactoryBean.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.library.spring.bootstrap.internal.service;
-
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.springframework.beans.factory.FactoryBean;
-
-import static org.qi4j.functional.Iterables.first;
-import static org.springframework.util.Assert.notNull;
-
-public final class ServiceFactoryBean
-    implements FactoryBean
-{
-    private ServiceReference serviceReference;
-
-    public ServiceFactoryBean( Application anApplication, String aServiceId )
-        throws IllegalArgumentException
-    {
-        notNull( anApplication, "Argument [anApplication] must not be [null]." );
-        notNull( aServiceId, "Argument [aServiceId] must not be [null]." );
-
-        ServiceLocator serviceLocator = new ServiceLocator( aServiceId );
-        anApplication.descriptor().accept( serviceLocator );
-        serviceReference = serviceLocator.locateService( anApplication );
-
-        if( serviceReference == null )
-        {
-            throw new IllegalArgumentException( "Zest service with id [" + aServiceId + "] is not found." );
-        }
-    }
-
-    @Override
-    public final Object getObject()
-        throws Exception
-    {
-        return serviceReference.get();
-    }
-
-    @Override
-    public final Class getObjectType()
-    {
-        return first( serviceReference.types() );
-    }
-
-    @Override
-    public final boolean isSingleton()
-    {
-        return false;
-    }
-}
diff --git a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/service/ServiceLocator.java b/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/service/ServiceLocator.java
deleted file mode 100644
index 937e8e4..0000000
--- a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/service/ServiceLocator.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.library.spring.bootstrap.internal.service;
-
-import org.qi4j.api.object.ObjectDescriptor;
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.api.structure.LayerDescriptor;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.structure.ModuleDescriptor;
-import org.qi4j.functional.HierarchicalVisitor;
-
-import static org.qi4j.functional.Iterables.first;
-
-final class ServiceLocator
-    implements HierarchicalVisitor<Object, Object, RuntimeException>
-{
-    private final String serviceId;
-    private Class serviceType;
-    private String moduleName;
-    private String layerName;
-
-    private String tempLayerName;
-    private String tempModuleName;
-
-    ServiceLocator( String serviceId )
-    {
-        this.serviceId = serviceId;
-    }
-
-    @Override
-    public boolean visitEnter( Object visited )
-        throws RuntimeException
-    {
-        if( visited instanceof ApplicationDescriptor )
-        {
-            return true;
-        }
-        else if( visited instanceof LayerDescriptor )
-        {
-            tempLayerName = ( (LayerDescriptor) visited ).name();
-            return true;
-        }
-        else if( visited instanceof ModuleDescriptor )
-        {
-            tempModuleName = ( (ModuleDescriptor) visited ).name();
-            return true;
-        }
-        else if( visited instanceof ServiceDescriptor )
-        {
-            ServiceDescriptor aDescriptor = (ServiceDescriptor) visited;
-            String identity = aDescriptor.identity();
-            if( serviceId.equals( identity ) )
-            {
-                layerName = tempLayerName;
-                moduleName = tempModuleName;
-                serviceType = first( aDescriptor.types() );
-            }
-        }
-        else if( visited instanceof ObjectDescriptor )
-        {
-            return false;
-        }
-
-        return true;
-    }
-
-    @Override
-    public boolean visitLeave( Object visited )
-        throws RuntimeException
-    {
-        return true;
-    }
-
-    @Override
-    public boolean visit( Object visited )
-        throws RuntimeException
-    {
-        if( visited instanceof ImportedServiceDescriptor )
-        {
-            ImportedServiceDescriptor aDescriptor = (ImportedServiceDescriptor) visited;
-            String identity = aDescriptor.identity();
-            if( serviceId.equals( identity ) )
-            {
-                layerName = tempLayerName;
-                moduleName = tempModuleName;
-                serviceType = aDescriptor.type();
-            }
-        }
-
-        return true;
-    }
-
-    @SuppressWarnings( "unchecked" )
-    ServiceReference locateService( Application anApplication )
-    {
-        if( layerName != null )
-        {
-            Module module = anApplication.findModule( layerName, moduleName );
-            Iterable<ServiceReference<Object>> serviceRefs = module.findServices( serviceType );
-            for( ServiceReference<Object> serviceRef : serviceRefs )
-            {
-                if( serviceId.equals( serviceRef.identity() ) )
-                {
-                    return serviceRef;
-                }
-            }
-        }
-
-        return null;
-    }
-}
diff --git a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/service/package.html b/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/service/package.html
deleted file mode 100644
index e1c2093..0000000
--- a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/internal/service/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Spring Integration internal package.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/package.html b/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/package.html
deleted file mode 100644
index 664565f..0000000
--- a/libraries/spring/src/main/java/org/qi4j/library/spring/bootstrap/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Run a Zest™ Application as a Spring Bean and export its Services to Spring.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/spring/src/main/java/org/qi4j/library/spring/importer/SpringImporter.java b/libraries/spring/src/main/java/org/qi4j/library/spring/importer/SpringImporter.java
deleted file mode 100644
index 46e9161..0000000
--- a/libraries/spring/src/main/java/org/qi4j/library/spring/importer/SpringImporter.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.spring.importer;
-
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.service.ServiceImporterException;
-import org.springframework.context.ApplicationContext;
-
-/**
- * Import a service from Spring. This assumes that the service has been imported
- * into the assembly using the SpringImporterAssembler, so that the ApplicationContext
- * is available as service meta-info.
- */
-public class SpringImporter
-    implements ServiceImporter
-{
-    /**
-     * Import a service from Spring by looking it up in the ApplicationContext.
-     *
-     * @param serviceDescriptor The service descriptor.
-     * @return a service instance
-     * @throws ServiceImporterException if unable to import the service
-     */
-    @Override
-    public Object importService( ImportedServiceDescriptor serviceDescriptor ) throws ServiceImporterException
-    {
-        try
-        {
-            return serviceDescriptor.
-                metaInfo( ApplicationContext.class ).
-                getBean( serviceDescriptor.identity(), serviceDescriptor.type() );
-        }
-        catch( Throwable e )
-        {
-            throw new ServiceImporterException( "Could not import Spring service with id " + serviceDescriptor.identity(), e );
-        }
-    }
-
-    @Override
-    public boolean isAvailable( Object instance )
-    {
-        return true;
-    }
-}
diff --git a/libraries/spring/src/main/java/org/qi4j/library/spring/importer/SpringImporterAssembler.java b/libraries/spring/src/main/java/org/qi4j/library/spring/importer/SpringImporterAssembler.java
deleted file mode 100644
index f7f06f9..0000000
--- a/libraries/spring/src/main/java/org/qi4j/library/spring/importer/SpringImporterAssembler.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.spring.importer;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.springframework.context.ApplicationContext;
-
-/**
- * Imports all services in the given Spring ApplicationContext into a module.
- */
-public class SpringImporterAssembler
-    implements Assembler
-{
-    private ApplicationContext context;
-    private Visibility defaultVisibility;
-
-    /**
-     * Import all beans from the given ApplicationContext as services in Zest,
-     * using Module as Visibility.
-     *
-     * @param context the Spring ApplicationContext
-     */
-    public SpringImporterAssembler( ApplicationContext context )
-    {
-        this( context, Visibility.module );
-    }
-
-
-    /**
-     * Import all beans from the given ApplicationContext as services in Zest,
-     * using the specified Visibility level.
-     *
-     * @param context           the Spring ApplicationContext
-     * @param defaultVisibility the visibility level for the imported services
-     */
-    public SpringImporterAssembler( ApplicationContext context, Visibility defaultVisibility )
-    {
-        this.context = context;
-        this.defaultVisibility = defaultVisibility;
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module ) throws AssemblyException
-    {
-        // Register all Spring beans as services
-        String[] names = context.getBeanDefinitionNames();
-        for( String name : names )
-        {
-            Class serviceType = context.getType( name );
-            module.
-                importedServices( serviceType ).
-                importedBy( SpringImporter.class ).
-                identifiedBy( name ).
-                setMetaInfo( context ).
-                visibleIn( defaultVisibility );
-        }
-    }
-}
diff --git a/libraries/spring/src/main/java/org/qi4j/library/spring/importer/package.html b/libraries/spring/src/main/java/org/qi4j/library/spring/importer/package.html
deleted file mode 100644
index 5a9a6cc..0000000
--- a/libraries/spring/src/main/java/org/qi4j/library/spring/importer/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Import Spring Services inside a Zest™ Application.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/spring/src/main/java/org/qi4j/library/spring/package.html b/libraries/spring/src/main/java/org/qi4j/library/spring/package.html
deleted file mode 100644
index 516d035..0000000
--- a/libraries/spring/src/main/java/org/qi4j/library/spring/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Spring Integration.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/spring/src/main/resources/META-INF/spring.handlers b/libraries/spring/src/main/resources/META-INF/spring.handlers
index 67b4ee4..c948664 100644
--- a/libraries/spring/src/main/resources/META-INF/spring.handlers
+++ b/libraries/spring/src/main/resources/META-INF/spring.handlers
@@ -1,16 +1,21 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
-http\://www.qi4j.org/schema/qi4j/spring=org.qi4j.library.spring.bootstrap.internal.Qi4jNamespaceHandler
\ No newline at end of file
+http\://polygene.apache.org/schema/polygene/spring=org.apache.polygene.library.spring.bootstrap.internal.PolygeneNamespaceHandler
\ No newline at end of file
diff --git a/libraries/spring/src/main/resources/META-INF/spring.schemas b/libraries/spring/src/main/resources/META-INF/spring.schemas
index 6695877..d04fe55 100644
--- a/libraries/spring/src/main/resources/META-INF/spring.schemas
+++ b/libraries/spring/src/main/resources/META-INF/spring.schemas
@@ -1,16 +1,21 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
-http\://www.qi4j.org/schema/qi4j/spring/spring-0.5.xsd=org/qi4j/library/spring/spring-0.5.xsd
\ No newline at end of file
+http\://polygene.apache.org/schema/polygene/spring/spring-0.5.xsd=org/apache/polygene/library/spring/spring-0.5.xsd
\ No newline at end of file
diff --git a/libraries/spring/src/main/resources/org/apache/polygene/library/spring/spring-0.5.xsd b/libraries/spring/src/main/resources/org/apache/polygene/library/spring/spring-0.5.xsd
new file mode 100644
index 0000000..e6cfcae
--- /dev/null
+++ b/libraries/spring/src/main/resources/org/apache/polygene/library/spring/spring-0.5.xsd
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<xsd:schema xmlns="http://polygene.apache.org/schema/polygene/spring"
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:beans="http://www.springframework.org/schema/beans"
+            targetNamespace="http://polygene.apache.org/schema/polygene/spring"
+            elementFormDefault="qualified"
+            attributeFormDefault="unqualified">
+
+  <xsd:import namespace="http://www.springframework.org/schema/beans"/>
+
+  <xsd:element name="bootstrap">
+    <xsd:annotation>
+      <xsd:documentation><![CDATA[
+Defines Apache Polygene application bootstrap.
+			]]></xsd:documentation>
+    </xsd:annotation>
+    <xsd:complexType>
+      <xsd:attributeGroup ref="bootstrapAttributes"/>
+    </xsd:complexType>
+  </xsd:element>
+
+  <!-- Polygene application attributes -->
+  <xsd:attributeGroup name="bootstrapAttributes">
+    <xsd:attribute name="class" type="xsd:string" use="required">
+      <xsd:annotation>
+        <xsd:documentation source="java:java.lang.Class"><![CDATA[
+Full class name of bootstrap class.
+        ]]></xsd:documentation>
+      </xsd:annotation>
+    </xsd:attribute>
+  </xsd:attributeGroup>
+
+  <xsd:element name="service">
+    <xsd:annotation>
+      <xsd:documentation><![CDATA[
+Defines Apache Polygene service to be exposed as spring bean.
+			]]></xsd:documentation>
+    </xsd:annotation>
+    <xsd:complexType>
+      <xsd:complexContent>
+        <xsd:extension base="beans:identifiedType"/>
+      </xsd:complexContent>
+    </xsd:complexType>
+  </xsd:element>
+</xsd:schema>
\ No newline at end of file
diff --git a/libraries/spring/src/main/resources/org/qi4j/library/spring/spring-0.5.xsd b/libraries/spring/src/main/resources/org/qi4j/library/spring/spring-0.5.xsd
deleted file mode 100644
index af62ecc..0000000
--- a/libraries/spring/src/main/resources/org/qi4j/library/spring/spring-0.5.xsd
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<xsd:schema xmlns="http://www.qi4j.org/schema/qi4j/spring"
-            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
-            xmlns:beans="http://www.springframework.org/schema/beans"
-            targetNamespace="http://www.qi4j.org/schema/qi4j/spring"
-            elementFormDefault="qualified"
-            attributeFormDefault="unqualified">
-
-  <xsd:import namespace="http://www.springframework.org/schema/beans"/>
-
-  <xsd:element name="bootstrap">
-    <xsd:annotation>
-      <xsd:documentation><![CDATA[
-Defines qi4j application bootstrap.
-			]]></xsd:documentation>
-    </xsd:annotation>
-    <xsd:complexType>
-      <xsd:attributeGroup ref="bootstrapAttributes"/>
-    </xsd:complexType>
-  </xsd:element>
-
-  <!-- Qi4j application attributes -->
-  <xsd:attributeGroup name="bootstrapAttributes">
-    <xsd:attribute name="class" type="xsd:string" use="required">
-      <xsd:annotation>
-        <xsd:documentation source="java:java.lang.Class"><![CDATA[
-Full class name of bootstrap class.
-        ]]></xsd:documentation>
-      </xsd:annotation>
-    </xsd:attribute>
-  </xsd:attributeGroup>
-
-  <xsd:element name="service">
-    <xsd:annotation>
-      <xsd:documentation><![CDATA[
-Defines qi4j service to be exposed as spring bean.
-			]]></xsd:documentation>
-    </xsd:annotation>
-    <xsd:complexType>
-      <xsd:complexContent>
-        <xsd:extension base="beans:identifiedType"/>
-      </xsd:complexContent>
-    </xsd:complexType>
-  </xsd:element>
-</xsd:schema>
\ No newline at end of file
diff --git a/libraries/spring/src/test/java/org/apache/polygene/library/spring/MyPolygeneBootstrapper.java b/libraries/spring/src/test/java/org/apache/polygene/library/spring/MyPolygeneBootstrapper.java
new file mode 100644
index 0000000..1aa3c8b
--- /dev/null
+++ b/libraries/spring/src/test/java/org/apache/polygene/library/spring/MyPolygeneBootstrapper.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.library.spring;
+
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.library.spring.bootstrap.PolygeneApplicationBootstrap;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+// START SNIPPET: code
+public class MyPolygeneBootstrapper extends PolygeneApplicationBootstrap
+        implements ApplicationContextAware
+{
+    private ApplicationContext applicationContext;
+
+    @Override
+    public void assemble(ApplicationAssembly assembly) throws AssemblyException
+    {
+        // Normal assembly of an application.
+// END SNIPPET: code
+// START SNIPPET: code
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
+    {
+        this.applicationContext = applicationContext;
+    }
+
+}
+// END SNIPPET: code
diff --git a/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/CommentService.java b/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/CommentService.java
new file mode 100644
index 0000000..901deae
--- /dev/null
+++ b/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/CommentService.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.library.spring.bootstrap;
+
+public interface CommentService
+{
+    String comment( String sentence );
+}
diff --git a/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/CommentServiceComposite.java b/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/CommentServiceComposite.java
new file mode 100644
index 0000000..249e92c
--- /dev/null
+++ b/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/CommentServiceComposite.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.library.spring.bootstrap;
+
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+
+@Mixins(CommentServiceComposite.CommentServiceMixin.class)
+public interface CommentServiceComposite
+        extends CommentService, ServiceComposite
+{
+
+    class CommentServiceMixin
+            implements CommentService
+    {
+        @Service
+        private TextProcessingService textProcessingService;
+
+        public String comment( String item )
+        {
+            String comment = "";
+            if ( "beer".equals( item ) || "cola".equals( item ) )
+            {
+                comment = item + " is good.";
+            } else
+            {
+                comment = item + " is baaad.";
+            }
+
+            comment = textProcessingService.process( comment );
+
+            return comment;
+        }
+    }
+}
diff --git a/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/CommentServiceHolder.java b/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/CommentServiceHolder.java
new file mode 100644
index 0000000..98fffea
--- /dev/null
+++ b/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/CommentServiceHolder.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.spring.bootstrap;
+
+public class CommentServiceHolder
+{
+    private final CommentService service;
+
+    public CommentServiceHolder( CommentService aService )
+    {
+        service = aService;
+    }
+
+    final CommentService service()
+    {
+        return service;
+    }
+}
diff --git a/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/PolygeneExportServiceTest.java b/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/PolygeneExportServiceTest.java
new file mode 100644
index 0000000..7c5f447
--- /dev/null
+++ b/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/PolygeneExportServiceTest.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.library.spring.bootstrap;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import static org.junit.Assert.*;
+import static org.apache.polygene.library.spring.bootstrap.PolygeneTestBootstrap.COMMENT_SERVICE_ID;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration
+public final class PolygeneExportServiceTest
+{
+    @Autowired
+    private ApplicationContext appContext;
+
+    @Test
+    public final void testCommentService()
+    {
+        assertTrue( appContext.containsBean( COMMENT_SERVICE_ID ) );
+
+        CommentService commentService = (CommentService) appContext.getBean( COMMENT_SERVICE_ID );
+        assertNotNull( commentService );
+
+        String beerComment = commentService.comment( "beer" );
+        assertEquals( "BEER IS GOOD.", beerComment );
+
+        String colaComment = commentService.comment( "cola" );
+        assertEquals( "COLA IS GOOD.", colaComment );
+
+        String colaBeerComment = commentService.comment( "cola+beer" );
+        assertEquals( "COLA+BEER IS BAAAD.", colaBeerComment );
+
+        CommentServiceHolder holder = (CommentServiceHolder) appContext.getBean( "commentServiceHolder" );
+        assertTrue( commentService == holder.service() );
+    }
+}
diff --git a/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/PolygeneTestBootstrap.java b/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/PolygeneTestBootstrap.java
new file mode 100644
index 0000000..6cb12e0
--- /dev/null
+++ b/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/PolygeneTestBootstrap.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.library.spring.bootstrap;
+
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+public final class PolygeneTestBootstrap extends PolygeneApplicationBootstrap
+        implements ApplicationContextAware
+{
+    private static final String LAYER = "layer";
+
+    private static final String MODULE = "module";
+
+    static final String COMMENT_SERVICE_ID = "commentService";
+
+    private static final String TO_UPPERCASE_SERVICE_ID = "toUppercaseService";
+
+    private ApplicationContext applicationContext;
+
+    public final void assemble( ApplicationAssembly applicationAssembly ) throws AssemblyException
+    {
+        LayerAssembly layerAssembly = applicationAssembly.layer( LAYER );
+        ModuleAssembly moduleAssembly = layerAssembly.module( MODULE );
+        moduleAssembly.services( CommentServiceComposite.class ).identifiedBy( COMMENT_SERVICE_ID );
+        // inject Spring bean as a service
+        moduleAssembly.importedServices( TextProcessingService.class )
+                .setMetaInfo( this.applicationContext.getBean( TO_UPPERCASE_SERVICE_ID ) );
+    }
+
+    public void setApplicationContext( ApplicationContext applicationContext ) throws BeansException
+    {
+        this.applicationContext = applicationContext;
+    }
+}
diff --git a/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/TextProcessingService.java b/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/TextProcessingService.java
new file mode 100644
index 0000000..3c2612c
--- /dev/null
+++ b/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/TextProcessingService.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.library.spring.bootstrap;
+
+public interface TextProcessingService
+{
+    String process(String text);
+}
diff --git a/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/ToUppercaseService.java b/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/ToUppercaseService.java
new file mode 100644
index 0000000..6b12d65
--- /dev/null
+++ b/libraries/spring/src/test/java/org/apache/polygene/library/spring/bootstrap/ToUppercaseService.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.spring.bootstrap;
+
+public class ToUppercaseService
+        implements TextProcessingService
+{
+
+    public String process( final String text )
+    {
+        return text.toUpperCase();
+    }
+
+}
diff --git a/libraries/spring/src/test/java/org/apache/polygene/library/spring/importer/CommentService.java b/libraries/spring/src/test/java/org/apache/polygene/library/spring/importer/CommentService.java
new file mode 100644
index 0000000..589e0ac
--- /dev/null
+++ b/libraries/spring/src/test/java/org/apache/polygene/library/spring/importer/CommentService.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.library.spring.importer;
+
+interface CommentService
+{
+    String comment( String sentence );
+}
\ No newline at end of file
diff --git a/libraries/spring/src/test/java/org/apache/polygene/library/spring/importer/CommentServiceBean.java b/libraries/spring/src/test/java/org/apache/polygene/library/spring/importer/CommentServiceBean.java
new file mode 100644
index 0000000..c3b580a
--- /dev/null
+++ b/libraries/spring/src/test/java/org/apache/polygene/library/spring/importer/CommentServiceBean.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.spring.importer;
+
+public class CommentServiceBean
+    implements CommentService
+{
+    public final String comment( String item )
+    {
+        if( "beer".equals( item ) || "cola".equals( item ) )
+        {
+            return item + " is good.";
+        }
+        else
+        {
+            return item + " is baaad.";
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries/spring/src/test/java/org/apache/polygene/library/spring/importer/CommentServiceBean2.java b/libraries/spring/src/test/java/org/apache/polygene/library/spring/importer/CommentServiceBean2.java
new file mode 100644
index 0000000..de959e3
--- /dev/null
+++ b/libraries/spring/src/test/java/org/apache/polygene/library/spring/importer/CommentServiceBean2.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.spring.importer;
+
+public class CommentServiceBean2
+    implements CommentService
+{
+    public final String comment( String item )
+    {
+        if( "beer".equals( item ) || "cola".equals( item ) )
+        {
+            return item + " is baaad.";
+        }
+        else
+        {
+            return item + " is good.";
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries/spring/src/test/java/org/apache/polygene/library/spring/importer/PolygeneImportServiceTest.java b/libraries/spring/src/test/java/org/apache/polygene/library/spring/importer/PolygeneImportServiceTest.java
new file mode 100644
index 0000000..74bbec4
--- /dev/null
+++ b/libraries/spring/src/test/java/org/apache/polygene/library/spring/importer/PolygeneImportServiceTest.java
@@ -0,0 +1,118 @@
+/*
+ *  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.polygene.library.spring.importer;
+
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import static org.apache.polygene.api.service.qualifier.ServiceQualifier.withId;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+@RunWith( SpringJUnit4ClassRunner.class )
+@ContextConfiguration
+public final class PolygeneImportServiceTest
+{
+    @Autowired ApplicationContext appContext;
+
+    @Service CommentService service;
+
+    @Test
+    public final void givenImportedSpringServicesWhenServiceIsInjectedThenUseSpringService()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module ) throws AssemblyException
+            {
+                module.objects( PolygeneImportServiceTest.class );
+                // START SNIPPET: import
+                new SpringImporterAssembler( appContext ).assemble( module );
+                // END SNIPPET: import
+            }
+        };
+
+        assembler.module().injectTo( this );
+
+        assertThat( "service can be called", service.comment( "beer" ), equalTo( "beer is good." ) );
+    }
+
+    @Service Iterable<ServiceReference<CommentService>> services;
+
+    @Test
+    public final void givenImportedSpringServicesWhenServicesAreInjectedThenCanIdentifyByName()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module ) throws AssemblyException
+            {
+                module.objects( PolygeneImportServiceTest.class );
+
+                new SpringImporterAssembler( appContext ).assemble( module );
+            }
+        };
+
+        assembler.module().injectTo(this);
+
+        CommentService service = StreamSupport.stream( services.spliterator(), false )
+                                              .filter( withId( "commentService2" ) )
+                                              .findFirst().map( ServiceReference::get ).orElse( null );
+        assertThat( "service with correct id has been selected", service.comment( "pizza" ), equalTo( "pizza is good." ) );
+    }
+
+    @Structure ServiceFinder finder;
+
+    @Test
+    public final void givenImportedSpringServicesWhenServicesAreFoundThenCanIdentifyByName()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module ) throws AssemblyException
+            {
+                module.objects( PolygeneImportServiceTest.class );
+
+                new SpringImporterAssembler( appContext ).assemble( module );
+            }
+        };
+
+        assembler.module().injectTo( this );
+
+        CommentService foundService = finder.findServices( CommentService.class )
+                                            .filter( withId( "commentService2" ) )
+                                            .findFirst().map( ServiceReference::get )
+                                            .orElse( null );
+        assertThat( "service with correct id has been selected", foundService.comment( "pizza" ), equalTo( "pizza is good." ) );
+    }
+}
\ No newline at end of file
diff --git a/libraries/spring/src/test/java/org/qi4j/library/spring/MyZestBootstrapper.java b/libraries/spring/src/test/java/org/qi4j/library/spring/MyZestBootstrapper.java
deleted file mode 100644
index afcf0a2..0000000
--- a/libraries/spring/src/test/java/org/qi4j/library/spring/MyZestBootstrapper.java
+++ /dev/null
@@ -1,49 +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.qi4j.library.spring;
-
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.library.spring.bootstrap.Qi4jApplicationBootstrap;
-import org.springframework.beans.BeansException;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-
-// START SNIPPET: code
-public class MyZestBootstrapper extends Qi4jApplicationBootstrap
-        implements ApplicationContextAware
-{
-    private ApplicationContext applicationContext;
-
-    @Override
-    public void assemble(ApplicationAssembly assembly) throws AssemblyException
-    {
-        // Normal assembly of an application.
-// END SNIPPET: code
-// START SNIPPET: code
-    }
-
-    @Override
-    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
-    {
-        this.applicationContext = applicationContext;
-    }
-
-}
-// END SNIPPET: code
diff --git a/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/CommentService.java b/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/CommentService.java
deleted file mode 100644
index 9c056de..0000000
--- a/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/CommentService.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.library.spring.bootstrap;
-
-public interface CommentService
-{
-    String comment( String sentence );
-}
diff --git a/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/CommentServiceComposite.java b/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/CommentServiceComposite.java
deleted file mode 100644
index 99d5136..0000000
--- a/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/CommentServiceComposite.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.library.spring.bootstrap;
-
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-@Mixins(CommentServiceComposite.CommentServiceMixin.class)
-public interface CommentServiceComposite
-        extends CommentService, ServiceComposite
-{
-
-    class CommentServiceMixin
-            implements CommentService
-    {
-        @Service
-        private TextProcessingService textProcessingService;
-
-        public String comment( String item )
-        {
-            String comment = "";
-            if ( "beer".equals( item ) || "cola".equals( item ) )
-            {
-                comment = item + " is good.";
-            } else
-            {
-                comment = item + " is baaad.";
-            }
-
-            comment = textProcessingService.process( comment );
-
-            return comment;
-        }
-    }
-}
diff --git a/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/CommentServiceHolder.java b/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/CommentServiceHolder.java
deleted file mode 100644
index 208efcf..0000000
--- a/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/CommentServiceHolder.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.library.spring.bootstrap;
-
-public class CommentServiceHolder
-{
-    private final CommentService service;
-
-    public CommentServiceHolder( CommentService aService )
-    {
-        service = aService;
-    }
-
-    final CommentService service()
-    {
-        return service;
-    }
-}
diff --git a/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/Qi4jExportServiceTest.java b/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/Qi4jExportServiceTest.java
deleted file mode 100644
index b0f5964..0000000
--- a/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/Qi4jExportServiceTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.library.spring.bootstrap;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-
-import static org.junit.Assert.*;
-import static org.qi4j.library.spring.bootstrap.Qi4jTestBootstrap.COMMENT_SERVICE_ID;
-
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration
-public final class Qi4jExportServiceTest
-{
-    @Autowired
-    private ApplicationContext appContext;
-
-    @Test
-    public final void testCommentService()
-    {
-        assertTrue( appContext.containsBean( COMMENT_SERVICE_ID ) );
-
-        CommentService commentService = (CommentService) appContext.getBean( COMMENT_SERVICE_ID );
-        assertNotNull( commentService );
-
-        String beerComment = commentService.comment( "beer" );
-        assertEquals( "BEER IS GOOD.", beerComment );
-
-        String colaComment = commentService.comment( "cola" );
-        assertEquals( "COLA IS GOOD.", colaComment );
-
-        String colaBeerComment = commentService.comment( "cola+beer" );
-        assertEquals( "COLA+BEER IS BAAAD.", colaBeerComment );
-
-        CommentServiceHolder holder = (CommentServiceHolder) appContext.getBean( "commentServiceHolder" );
-        assertTrue( commentService == holder.service() );
-    }
-}
diff --git a/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/Qi4jTestBootstrap.java b/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/Qi4jTestBootstrap.java
deleted file mode 100644
index 6cbbe5c..0000000
--- a/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/Qi4jTestBootstrap.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.library.spring.bootstrap;
-
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.springframework.beans.BeansException;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-
-public final class Qi4jTestBootstrap
-        extends Qi4jApplicationBootstrap
-        implements ApplicationContextAware
-{
-    private static final String LAYER = "layer";
-
-    private static final String MODULE = "module";
-
-    static final String COMMENT_SERVICE_ID = "commentService";
-
-    private static final String TO_UPPERCASE_SERVICE_ID = "toUppercaseService";
-
-    private ApplicationContext applicationContext;
-
-    public final void assemble( ApplicationAssembly applicationAssembly ) throws AssemblyException
-    {
-        LayerAssembly layerAssembly = applicationAssembly.layer( LAYER );
-        ModuleAssembly moduleAssembly = layerAssembly.module( MODULE );
-        moduleAssembly.services( CommentServiceComposite.class ).identifiedBy( COMMENT_SERVICE_ID );
-        // inject Spring bean as a service
-        moduleAssembly.importedServices( TextProcessingService.class ).setMetaInfo(
-                this.applicationContext.getBean( TO_UPPERCASE_SERVICE_ID ) );
-    }
-
-    public void setApplicationContext( ApplicationContext applicationContext ) throws BeansException
-    {
-        this.applicationContext = applicationContext;
-    }
-}
diff --git a/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/TextProcessingService.java b/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/TextProcessingService.java
deleted file mode 100644
index e219568..0000000
--- a/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/TextProcessingService.java
+++ /dev/null
@@ -1,24 +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.qi4j.library.spring.bootstrap;
-
-public interface TextProcessingService
-{
-    String process(String text);
-}
diff --git a/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/ToUppercaseService.java b/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/ToUppercaseService.java
deleted file mode 100644
index 1e6c259..0000000
--- a/libraries/spring/src/test/java/org/qi4j/library/spring/bootstrap/ToUppercaseService.java
+++ /dev/null
@@ -1,30 +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.qi4j.library.spring.bootstrap;
-
-public class ToUppercaseService
-        implements TextProcessingService
-{
-
-    public String process( final String text )
-    {
-        return text.toUpperCase();
-    }
-
-}
diff --git a/libraries/spring/src/test/java/org/qi4j/library/spring/importer/CommentService.java b/libraries/spring/src/test/java/org/qi4j/library/spring/importer/CommentService.java
deleted file mode 100644
index d9d507a..0000000
--- a/libraries/spring/src/test/java/org/qi4j/library/spring/importer/CommentService.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*  Copyright 2008 Rickard Öberg.
-*
-* Licensed 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.qi4j.library.spring.importer;
-
-interface CommentService
-{
-    String comment( String sentence );
-}
\ No newline at end of file
diff --git a/libraries/spring/src/test/java/org/qi4j/library/spring/importer/CommentServiceBean.java b/libraries/spring/src/test/java/org/qi4j/library/spring/importer/CommentServiceBean.java
deleted file mode 100644
index de6c8ad..0000000
--- a/libraries/spring/src/test/java/org/qi4j/library/spring/importer/CommentServiceBean.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*  Copyright 2008 Rickard Öberg.
-*
-* Licensed 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.qi4j.library.spring.importer;
-
-public class CommentServiceBean
-    implements CommentService
-{
-    public final String comment( String item )
-    {
-        if( "beer".equals( item ) || "cola".equals( item ) )
-        {
-            return item + " is good.";
-        }
-        else
-        {
-            return item + " is baaad.";
-        }
-    }
-}
\ No newline at end of file
diff --git a/libraries/spring/src/test/java/org/qi4j/library/spring/importer/CommentServiceBean2.java b/libraries/spring/src/test/java/org/qi4j/library/spring/importer/CommentServiceBean2.java
deleted file mode 100644
index 43aeb36..0000000
--- a/libraries/spring/src/test/java/org/qi4j/library/spring/importer/CommentServiceBean2.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*  Copyright 2008 Rickard Öberg.
-*
-* Licensed 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.qi4j.library.spring.importer;
-
-public class CommentServiceBean2
-    implements CommentService
-{
-    public final String comment( String item )
-    {
-        if( "beer".equals( item ) || "cola".equals( item ) )
-        {
-            return item + " is baaad.";
-        }
-        else
-        {
-            return item + " is good.";
-        }
-    }
-}
\ No newline at end of file
diff --git a/libraries/spring/src/test/java/org/qi4j/library/spring/importer/Qi4jImportServiceTest.java b/libraries/spring/src/test/java/org/qi4j/library/spring/importer/Qi4jImportServiceTest.java
deleted file mode 100644
index fc76bea..0000000
--- a/libraries/spring/src/test/java/org/qi4j/library/spring/importer/Qi4jImportServiceTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*  Copyright 2008 Rickard Öberg.
-*
-* Licensed 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.qi4j.library.spring.importer;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.service.ServiceFinder;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.service.qualifier.ServiceQualifier;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.api.service.qualifier.ServiceQualifier.firstService;
-import static org.qi4j.api.service.qualifier.ServiceQualifier.withId;
-
-@RunWith( SpringJUnit4ClassRunner.class )
-@ContextConfiguration
-public final class Qi4jImportServiceTest
-{
-    @Autowired ApplicationContext appContext;
-
-    @Service CommentService service;
-
-    @Test
-    public final void givenImportedSpringServicesWhenServiceIsInjectedThenUseSpringService()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module ) throws AssemblyException
-            {
-                module.objects( Qi4jImportServiceTest.class );
-                // START SNIPPET: import
-                new SpringImporterAssembler( appContext ).assemble( module );
-                // END SNIPPET: import
-            }
-        };
-
-        assembler.module().injectTo( this );
-
-        assertThat( "service can be called", service.comment( "beer" ), equalTo( "beer is good." ) );
-    }
-
-    @Service Iterable<ServiceReference<CommentService>> services;
-
-    @Test
-    public final void givenImportedSpringServicesWhenServicesAreInjectedThenCanIdentifyByName()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module ) throws AssemblyException
-            {
-                module.objects( Qi4jImportServiceTest.class );
-
-                new SpringImporterAssembler( appContext ).assemble( module );
-            }
-        };
-
-        assembler.module().injectTo(this);
-
-        CommentService service = firstService( withId( "commentService2" ), services );
-        assertThat( "service with correct id has been selected", service.comment( "pizza" ), equalTo( "pizza is good." ) );
-    }
-
-    @Structure ServiceFinder finder;
-
-    @Test
-    public final void givenImportedSpringServicesWhenServicesAreFoundThenCanIdentifyByName()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module ) throws AssemblyException
-            {
-                module.objects( Qi4jImportServiceTest.class );
-
-                new SpringImporterAssembler( appContext ).assemble( module );
-            }
-        };
-
-        assembler.module().injectTo( this );
-
-        CommentService foundService = ServiceQualifier.firstService( withId( "commentService2" ), finder.<CommentService>findServices( CommentService.class ));
-        assertThat( "service with correct id has been selected", foundService.comment( "pizza" ), equalTo( "pizza is good." ) );
-    }
-}
\ No newline at end of file
diff --git a/libraries/spring/src/test/resources/org/apache/polygene/library/spring/bootstrap/PolygeneExportServiceTest-context.xml b/libraries/spring/src/test/resources/org/apache/polygene/library/spring/bootstrap/PolygeneExportServiceTest-context.xml
new file mode 100644
index 0000000..1e29446
--- /dev/null
+++ b/libraries/spring/src/test/resources/org/apache/polygene/library/spring/bootstrap/PolygeneExportServiceTest-context.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:polygene="http://polygene.apache.org/schema/polygene/spring"
+    xsi:schemaLocation="
+       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+       http://polygene.apache.org/schema/polygene/spring http://polygene.apache.org/schema/polygene/spring/spring-0.5.xsd">
+
+    <polygene:bootstrap class="org.apache.polygene.library.spring.bootstrap.PolygeneTestBootstrap" />
+    <polygene:service id="commentService" />
+
+    <bean id="commentServiceHolder" class="org.apache.polygene.library.spring.bootstrap.CommentServiceHolder">
+        <constructor-arg ref="commentService" />
+    </bean>
+
+    <!-- This Spring bean is injected as a service to the Apache Polygene application -->
+    <bean id="toUppercaseService" class="org.apache.polygene.library.spring.bootstrap.ToUppercaseService" />
+
+</beans>
diff --git a/libraries/spring/src/test/resources/org/apache/polygene/library/spring/importer/PolygeneImportServiceTest-context.xml b/libraries/spring/src/test/resources/org/apache/polygene/library/spring/importer/PolygeneImportServiceTest-context.xml
new file mode 100644
index 0000000..24bc63f
--- /dev/null
+++ b/libraries/spring/src/test/resources/org/apache/polygene/library/spring/importer/PolygeneImportServiceTest-context.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+  <bean id="commentService" class="org.apache.polygene.library.spring.importer.CommentServiceBean"/>
+  <bean id="commentService2" class="org.apache.polygene.library.spring.importer.CommentServiceBean2"/>
+</beans>
diff --git a/libraries/spring/src/test/resources/org/qi4j/library/spring/bootstrap/Qi4jExportServiceTest-context.xml b/libraries/spring/src/test/resources/org/qi4j/library/spring/bootstrap/Qi4jExportServiceTest-context.xml
deleted file mode 100644
index a96ec1c..0000000
--- a/libraries/spring/src/test/resources/org/qi4j/library/spring/bootstrap/Qi4jExportServiceTest-context.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:qi4j="http://www.qi4j.org/schema/qi4j/spring"
-    xsi:schemaLocation="
-       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
-       http://www.qi4j.org/schema/qi4j/spring http://www.qi4j.org/schema/qi4j/spring/spring-0.5.xsd">
-
-    <qi4j:bootstrap class="org.qi4j.library.spring.bootstrap.Qi4jTestBootstrap" />
-    <qi4j:service id="commentService" />
-
-    <bean id="commentServiceHolder" class="org.qi4j.library.spring.bootstrap.CommentServiceHolder">
-        <constructor-arg ref="commentService" />
-    </bean>
-
-    <!-- This Spring bean is injected as a service to the qi4j application -->
-    <bean id="toUppercaseService" class="org.qi4j.library.spring.bootstrap.ToUppercaseService" />
-
-</beans>
diff --git a/libraries/spring/src/test/resources/org/qi4j/library/spring/importer/Qi4jImportServiceTest-context.xml b/libraries/spring/src/test/resources/org/qi4j/library/spring/importer/Qi4jImportServiceTest-context.xml
deleted file mode 100644
index 19c9af7..0000000
--- a/libraries/spring/src/test/resources/org/qi4j/library/spring/importer/Qi4jImportServiceTest-context.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<beans xmlns="http://www.springframework.org/schema/beans"
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:schemaLocation="
-       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
-
-  <bean id="commentService" class="org.qi4j.library.spring.importer.CommentServiceBean"/>
-  <bean id="commentService2" class="org.qi4j.library.spring.importer.CommentServiceBean2"/>
-</beans>
diff --git a/libraries/sql-bonecp/build.gradle b/libraries/sql-bonecp/build.gradle
index a503338..ff7b098 100644
--- a/libraries/sql-bonecp/build.gradle
+++ b/libraries/sql-bonecp/build.gradle
@@ -1,28 +1,31 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ SQL BoneCP Library provides BoneCP support."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - SQL BoneCP" }}
+description = "Apache Polygene™ SQL BoneCP Library provides BoneCP support."
+
+jar { manifest { name = "Apache Polygene™ Library - SQL BoneCP" } }
 
 dependencies {
-  compile(project(":org.qi4j.libraries:org.qi4j.library.sql"))
-  compile(libraries.bonecp)
-}
+  api polygene.library( 'sql' )
 
+  implementation libraries.bonecp
+}
diff --git a/libraries/sql-bonecp/dev-status.xml b/libraries/sql-bonecp/dev-status.xml
index bdf00e7..0914c52 100644
--- a/libraries/sql-bonecp/dev-status.xml
+++ b/libraries/sql-bonecp/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/sql-bonecp/src/main/java/org/apache/polygene/library/sql/bonecp/BoneCPDataSourceServiceAssembler.java b/libraries/sql-bonecp/src/main/java/org/apache/polygene/library/sql/bonecp/BoneCPDataSourceServiceAssembler.java
new file mode 100644
index 0000000..0201575
--- /dev/null
+++ b/libraries/sql-bonecp/src/main/java/org/apache/polygene/library/sql/bonecp/BoneCPDataSourceServiceAssembler.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.sql.bonecp;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.sql.assembly.AbstractPooledDataSourceServiceAssembler;
+
+/**
+ * Use this Assembler to register a DataSourceService based on BoneCP and its Configuration entity.
+ */
+public class BoneCPDataSourceServiceAssembler
+        extends AbstractPooledDataSourceServiceAssembler<BoneCPDataSourceServiceAssembler>
+{
+
+    @Override
+    protected void onAssemble( ModuleAssembly module, String identity, Visibility visibility )
+    {
+        module.services( BoneCPDataSourceServiceImporter.class ).identifiedBy( identity ).visibleIn( visibility );
+    }
+
+}
diff --git a/libraries/sql-bonecp/src/main/java/org/apache/polygene/library/sql/bonecp/BoneCPDataSourceServiceImporter.java b/libraries/sql-bonecp/src/main/java/org/apache/polygene/library/sql/bonecp/BoneCPDataSourceServiceImporter.java
new file mode 100644
index 0000000..57238e8
--- /dev/null
+++ b/libraries/sql-bonecp/src/main/java/org/apache/polygene/library/sql/bonecp/BoneCPDataSourceServiceImporter.java
@@ -0,0 +1,99 @@
+/*
+ *  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.polygene.library.sql.bonecp;
+
+import com.jolbox.bonecp.BoneCPDataSource;
+import java.util.Properties;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.library.sql.datasource.AbstractDataSourceServiceImporterMixin;
+import org.apache.polygene.library.sql.datasource.DataSourceConfiguration;
+import org.apache.polygene.library.sql.datasource.DataSourceServiceImporterActivation;
+
+/**
+ * DataSource service implemented as a ServiceImporter.
+ *
+ * Import visible DataSources as Services. The default Mixin use the BoneCP
+ * pooling system optionaly wrapped with CircuitBreaker using a proxy.
+ */
+@Mixins( BoneCPDataSourceServiceImporter.Mixin.class )
+@Activators( DataSourceServiceImporterActivation.Activator.class )
+public class BoneCPDataSourceServiceImporter
+{
+
+    public static class Mixin
+            extends AbstractDataSourceServiceImporterMixin<BoneCPDataSource>
+    {
+
+        @Override
+        protected BoneCPDataSource setupDataSourcePool( DataSourceConfiguration config )
+                throws Exception
+        {
+            BoneCPDataSource pool = new BoneCPDataSource();
+
+            Class.forName( config.driver().get() );
+            pool.setDriverClass( config.driver().get() );
+            pool.setJdbcUrl( config.url().get() );
+
+            if ( !config.username().get().equals( "" ) ) {
+                pool.setUsername( config.username().get() );
+                pool.setPassword( config.password().get() );
+            }
+            
+            if ( config.minPoolSize().get() != null ) {
+                pool.setMinConnectionsPerPartition( config.minPoolSize().get() );
+            }
+            if ( config.maxPoolSize().get() != null ) {
+                pool.setMaxConnectionsPerPartition( config.maxPoolSize().get() );
+            }
+            if ( config.loginTimeoutSeconds().get() != null ) {
+                pool.setLoginTimeout( config.loginTimeoutSeconds().get() );
+            }
+            if ( config.maxConnectionAgeSeconds().get() != null ) {
+                pool.setMaxConnectionAgeInSeconds( config.maxConnectionAgeSeconds().get() );
+            }
+            if ( config.validationQuery().get() != null ) {
+                pool.setConnectionTestStatement( config.validationQuery().get() );
+            }
+
+            String props = config.properties().get();
+            String[] properties = props.split( "," );
+            Properties poolProperties = new Properties();
+            for ( String property : properties ) {
+                if ( property.trim().length() > 0 ) {
+                    String[] keyvalue = property.trim().split( "=" );
+                    poolProperties.setProperty( keyvalue[0], keyvalue[1] );
+                }
+            }
+            pool.setProperties( poolProperties );
+
+            return pool;
+        }
+
+        @Override
+        protected void passivateDataSourcePool( BoneCPDataSource dataSourcePool )
+                throws Exception
+        {
+            dataSourcePool.close();
+        }
+
+    }
+
+}
diff --git a/libraries/sql-bonecp/src/main/java/org/apache/polygene/library/sql/bonecp/package.html b/libraries/sql-bonecp/src/main/java/org/apache/polygene/library/sql/bonecp/package.html
new file mode 100644
index 0000000..6e7e4c0
--- /dev/null
+++ b/libraries/sql-bonecp/src/main/java/org/apache/polygene/library/sql/bonecp/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL BoneCP Support.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/sql-bonecp/src/main/java/org/qi4j/library/sql/bonecp/BoneCPDataSourceServiceAssembler.java b/libraries/sql-bonecp/src/main/java/org/qi4j/library/sql/bonecp/BoneCPDataSourceServiceAssembler.java
deleted file mode 100644
index f061736..0000000
--- a/libraries/sql-bonecp/src/main/java/org/qi4j/library/sql/bonecp/BoneCPDataSourceServiceAssembler.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.bonecp;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.sql.assembly.AbstractPooledDataSourceServiceAssembler;
-
-/**
- * Use this Assembler to register a DataSourceService based on BoneCP and its Configuration entity.
- */
-public class BoneCPDataSourceServiceAssembler
-        extends AbstractPooledDataSourceServiceAssembler<BoneCPDataSourceServiceAssembler>
-{
-
-    @Override
-    protected void onAssemble( ModuleAssembly module, String identity, Visibility visibility )
-    {
-        module.services( BoneCPDataSourceServiceImporter.class ).identifiedBy( identity ).visibleIn( visibility );
-    }
-
-}
diff --git a/libraries/sql-bonecp/src/main/java/org/qi4j/library/sql/bonecp/BoneCPDataSourceServiceImporter.java b/libraries/sql-bonecp/src/main/java/org/qi4j/library/sql/bonecp/BoneCPDataSourceServiceImporter.java
deleted file mode 100644
index d6ca094..0000000
--- a/libraries/sql-bonecp/src/main/java/org/qi4j/library/sql/bonecp/BoneCPDataSourceServiceImporter.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.bonecp;
-
-import com.jolbox.bonecp.BoneCPDataSource;
-import java.util.Properties;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.library.sql.datasource.AbstractDataSourceServiceImporterMixin;
-import org.qi4j.library.sql.datasource.DataSourceConfigurationValue;
-import org.qi4j.library.sql.datasource.DataSourceServiceImporterActivation;
-
-/**
- * DataSource service implemented as a ServiceImporter.
- *
- * Import visible DataSources as Services. The default Mixin use the BoneCP
- * pooling system optionaly wrapped with CircuitBreaker using a proxy.
- */
-@Mixins( BoneCPDataSourceServiceImporter.Mixin.class )
-@Activators( DataSourceServiceImporterActivation.Activator.class )
-public class BoneCPDataSourceServiceImporter
-{
-
-    public static class Mixin
-            extends AbstractDataSourceServiceImporterMixin<BoneCPDataSource>
-    {
-
-        @Override
-        protected BoneCPDataSource setupDataSourcePool( DataSourceConfigurationValue config )
-                throws Exception
-        {
-            BoneCPDataSource pool = new BoneCPDataSource();
-
-            Class.forName( config.driver().get() );
-            pool.setDriverClass( config.driver().get() );
-            pool.setJdbcUrl( config.url().get() );
-
-            if ( !config.username().get().equals( "" ) ) {
-                pool.setUsername( config.username().get() );
-                pool.setPassword( config.password().get() );
-            }
-            
-            if ( config.minPoolSize().get() != null ) {
-                pool.setMinConnectionsPerPartition( config.minPoolSize().get() );
-            }
-            if ( config.maxPoolSize().get() != null ) {
-                pool.setMaxConnectionsPerPartition( config.maxPoolSize().get() );
-            }
-            if ( config.loginTimeoutSeconds().get() != null ) {
-                pool.setLoginTimeout( config.loginTimeoutSeconds().get() );
-            }
-            if ( config.maxConnectionAgeSeconds().get() != null ) {
-                pool.setMaxConnectionAgeInSeconds( config.maxConnectionAgeSeconds().get() );
-            }
-            if ( config.validationQuery().get() != null ) {
-                pool.setConnectionTestStatement( config.validationQuery().get() );
-            }
-
-            String props = config.properties().get();
-            String[] properties = props.split( "," );
-            Properties poolProperties = new Properties();
-            for ( String property : properties ) {
-                if ( property.trim().length() > 0 ) {
-                    String[] keyvalue = property.trim().split( "=" );
-                    poolProperties.setProperty( keyvalue[0], keyvalue[1] );
-                }
-            }
-            pool.setProperties( poolProperties );
-
-            return pool;
-        }
-
-        @Override
-        protected void passivateDataSourcePool( BoneCPDataSource dataSourcePool )
-                throws Exception
-        {
-            dataSourcePool.close();
-        }
-
-    }
-
-}
diff --git a/libraries/sql-bonecp/src/main/java/org/qi4j/library/sql/bonecp/package.html b/libraries/sql-bonecp/src/main/java/org/qi4j/library/sql/bonecp/package.html
deleted file mode 100644
index 4060d7f..0000000
--- a/libraries/sql-bonecp/src/main/java/org/qi4j/library/sql/bonecp/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL BoneCP Support.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/sql-dbcp/build.gradle b/libraries/sql-dbcp/build.gradle
index 51abe7c..0e804ea 100644
--- a/libraries/sql-dbcp/build.gradle
+++ b/libraries/sql-dbcp/build.gradle
@@ -1,28 +1,31 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ SQL DBCP Library provides DBCP support."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - SQL DBCP" }}
+description = "Apache Polygene™ SQL DBCP Library provides DBCP support."
+
+jar { manifest { name = "Apache Polygene™ Library - SQL DBCP" } }
 
 dependencies {
-  compile(project(":org.qi4j.libraries:org.qi4j.library.sql"))
-  compile(libraries.commons_dbcp)
-}
+  api polygene.library( 'sql' )
 
+  implementation libraries.commons_dbcp
+}
diff --git a/libraries/sql-dbcp/dev-status.xml b/libraries/sql-dbcp/dev-status.xml
index bdf00e7..0914c52 100644
--- a/libraries/sql-dbcp/dev-status.xml
+++ b/libraries/sql-dbcp/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/sql-dbcp/src/main/java/org/apache/polygene/library/sql/dbcp/DBCPDataSourceServiceAssembler.java b/libraries/sql-dbcp/src/main/java/org/apache/polygene/library/sql/dbcp/DBCPDataSourceServiceAssembler.java
new file mode 100644
index 0000000..e1226e2
--- /dev/null
+++ b/libraries/sql-dbcp/src/main/java/org/apache/polygene/library/sql/dbcp/DBCPDataSourceServiceAssembler.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.sql.dbcp;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.sql.assembly.AbstractPooledDataSourceServiceAssembler;
+
+/**
+ * Use this Assembler to register a DataSourceService based on DBCP and its Configuration entity.
+ */
+public class DBCPDataSourceServiceAssembler
+        extends AbstractPooledDataSourceServiceAssembler<DBCPDataSourceServiceAssembler>
+{
+
+    @Override
+    protected void onAssemble( ModuleAssembly module, String identity, Visibility visibility )
+    {
+        module.services( DBCPDataSourceServiceImporter.class ).identifiedBy( identity ).visibleIn( visibility );
+    }
+
+}
diff --git a/libraries/sql-dbcp/src/main/java/org/apache/polygene/library/sql/dbcp/DBCPDataSourceServiceImporter.java b/libraries/sql-dbcp/src/main/java/org/apache/polygene/library/sql/dbcp/DBCPDataSourceServiceImporter.java
new file mode 100644
index 0000000..38b6c5a
--- /dev/null
+++ b/libraries/sql-dbcp/src/main/java/org/apache/polygene/library/sql/dbcp/DBCPDataSourceServiceImporter.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.library.sql.dbcp;
+
+import javax.sql.DataSource;
+import org.apache.commons.dbcp2.BasicDataSource;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.library.sql.datasource.AbstractDataSourceServiceImporterMixin;
+import org.apache.polygene.library.sql.datasource.DataSourceConfiguration;
+import org.apache.polygene.library.sql.datasource.DataSourceServiceImporterActivation;
+
+@Mixins( DBCPDataSourceServiceImporter.Mixin.class )
+@Activators( DataSourceServiceImporterActivation.Activator.class )
+public interface DBCPDataSourceServiceImporter
+        extends ServiceImporter<DataSource>, DataSourceServiceImporterActivation, ServiceComposite
+{
+
+    class Mixin
+            extends AbstractDataSourceServiceImporterMixin<BasicDataSource>
+    {
+
+        @Override
+        protected BasicDataSource setupDataSourcePool( DataSourceConfiguration config )
+                throws Exception
+        {
+            BasicDataSource pool = new BasicDataSource();
+
+            Class.forName( config.driver().get() );
+            pool.setDriverClassName( config.driver().get() );
+            pool.setUrl( config.url().get() );
+
+            if ( !config.username().get().equals( "" ) ) {
+                pool.setUsername( config.username().get() );
+                pool.setPassword( config.password().get() );
+            }
+
+            if ( config.minPoolSize().get() != null ) {
+                pool.setMinIdle( config.minPoolSize().get() );
+            }
+            if ( config.maxPoolSize().get() != null ) {
+                pool.setMaxTotal( config.maxPoolSize().get() );
+            }
+            if ( config.loginTimeoutSeconds().get() != null ) {
+                pool.setLoginTimeout( config.loginTimeoutSeconds().get() );
+            }
+            if ( config.maxConnectionAgeSeconds().get() != null ) {
+                pool.setMinEvictableIdleTimeMillis( config.maxConnectionAgeSeconds().get() * 1000 );
+            }
+            if ( config.validationQuery().get() != null ) {
+                pool.setValidationQuery( config.validationQuery().get() );
+            }
+
+            return pool;
+        }
+
+        @Override
+        protected void passivateDataSourcePool( BasicDataSource dataSourcePool )
+                throws Exception
+        {
+            dataSourcePool.close();
+        }
+
+    }
+
+}
diff --git a/libraries/sql-dbcp/src/main/java/org/apache/polygene/library/sql/dbcp/package.html b/libraries/sql-dbcp/src/main/java/org/apache/polygene/library/sql/dbcp/package.html
new file mode 100644
index 0000000..e9b54bc
--- /dev/null
+++ b/libraries/sql-dbcp/src/main/java/org/apache/polygene/library/sql/dbcp/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL Apache DBCP Support.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/sql-dbcp/src/main/java/org/qi4j/library/sql/dbcp/DBCPDataSourceServiceAssembler.java b/libraries/sql-dbcp/src/main/java/org/qi4j/library/sql/dbcp/DBCPDataSourceServiceAssembler.java
deleted file mode 100644
index 71ad339..0000000
--- a/libraries/sql-dbcp/src/main/java/org/qi4j/library/sql/dbcp/DBCPDataSourceServiceAssembler.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.dbcp;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.sql.assembly.AbstractPooledDataSourceServiceAssembler;
-
-/**
- * Use this Assembler to register a DataSourceService based on DBCP and its Configuration entity.
- */
-public class DBCPDataSourceServiceAssembler
-        extends AbstractPooledDataSourceServiceAssembler<DBCPDataSourceServiceAssembler>
-{
-
-    @Override
-    protected void onAssemble( ModuleAssembly module, String identity, Visibility visibility )
-    {
-        module.services( DBCPDataSourceServiceImporter.class ).identifiedBy( identity ).visibleIn( visibility );
-    }
-
-}
diff --git a/libraries/sql-dbcp/src/main/java/org/qi4j/library/sql/dbcp/DBCPDataSourceServiceImporter.java b/libraries/sql-dbcp/src/main/java/org/qi4j/library/sql/dbcp/DBCPDataSourceServiceImporter.java
deleted file mode 100644
index 3e333cc..0000000
--- a/libraries/sql-dbcp/src/main/java/org/qi4j/library/sql/dbcp/DBCPDataSourceServiceImporter.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.dbcp;
-
-import javax.sql.DataSource;
-import org.apache.commons.dbcp.BasicDataSource;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.library.sql.datasource.AbstractDataSourceServiceImporterMixin;
-import org.qi4j.library.sql.datasource.DataSourceConfigurationValue;
-import org.qi4j.library.sql.datasource.DataSourceServiceImporterActivation;
-
-@Mixins( DBCPDataSourceServiceImporter.Mixin.class )
-@Activators( DataSourceServiceImporterActivation.Activator.class )
-public interface DBCPDataSourceServiceImporter
-        extends ServiceImporter<DataSource>, DataSourceServiceImporterActivation, ServiceComposite
-{
-
-    public static class Mixin
-            extends AbstractDataSourceServiceImporterMixin<BasicDataSource>
-    {
-
-        @Override
-        protected BasicDataSource setupDataSourcePool( DataSourceConfigurationValue config )
-                throws Exception
-        {
-            BasicDataSource pool = new BasicDataSource();
-
-            Class.forName( config.driver().get() );
-            pool.setDriverClassName( config.driver().get() );
-            pool.setUrl( config.url().get() );
-
-            if ( !config.username().get().equals( "" ) ) {
-                pool.setUsername( config.username().get() );
-                pool.setPassword( config.password().get() );
-            }
-
-            if ( config.minPoolSize().get() != null ) {
-                pool.setMinIdle( config.minPoolSize().get() );
-            }
-            if ( config.maxPoolSize().get() != null ) {
-                pool.setMaxActive( config.maxPoolSize().get() );
-            }
-            if ( config.loginTimeoutSeconds().get() != null ) {
-                pool.setLoginTimeout( config.loginTimeoutSeconds().get() );
-            }
-            if ( config.maxConnectionAgeSeconds().get() != null ) {
-                pool.setMinEvictableIdleTimeMillis( config.maxConnectionAgeSeconds().get() * 1000 );
-            }
-            if ( config.validationQuery().get() != null ) {
-                pool.setValidationQuery( config.validationQuery().get() );
-            }
-
-            return pool;
-        }
-
-        @Override
-        protected void passivateDataSourcePool( BasicDataSource dataSourcePool )
-                throws Exception
-        {
-            dataSourcePool.close();
-        }
-
-    }
-
-}
diff --git a/libraries/sql-dbcp/src/main/java/org/qi4j/library/sql/dbcp/package.html b/libraries/sql-dbcp/src/main/java/org/qi4j/library/sql/dbcp/package.html
deleted file mode 100644
index 493bf47..0000000
--- a/libraries/sql-dbcp/src/main/java/org/qi4j/library/sql/dbcp/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL Apache DBCP Support.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/sql-generator/build.gradle b/libraries/sql-generator/build.gradle
new file mode 100644
index 0000000..31d0d88
--- /dev/null
+++ b/libraries/sql-generator/build.gradle
@@ -0,0 +1,34 @@
+/*
+ *  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.
+ *
+ *
+ */
+
+apply plugin: 'polygene-library'
+
+description = "Apache Polygene™ SQL Library provides SQL support."
+
+jar { manifest { name = "Apache Polygene™ Library - SQL" } }
+
+dependencies {
+  api libraries.slf4j_api
+
+  testRuntimeOnly libraries.logback
+  testRuntimeOnly libraries.derby
+  testRuntimeOnly libraries.mysql_connector
+  testRuntimeOnly libraries.postgres
+}
diff --git a/libraries/sql-generator/dev-status.xml b/libraries/sql-generator/dev-status.xml
new file mode 100644
index 0000000..f279e24
--- /dev/null
+++ b/libraries/sql-generator/dev-status.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
+  <status>
+    <!--none,early,beta,stable,mature-->
+    <codebase>stable</codebase>
+
+    <!-- none, brief, good, complete -->
+    <documentation>brief</documentation>
+
+    <!-- none, some, good, complete -->
+    <unittests>good</unittests>
+  </status>
+  <licenses>
+    <license>ALv2</license>
+  </licenses>
+</module>
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/Typeable.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/Typeable.java
new file mode 100644
index 0000000..40988a5
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/Typeable.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.library.sql.generator;
+
+import java.util.Map;
+
+/**
+ * <p>
+ * The {@link Object#getClass()} method returns the actual class of the object. Sometimes, that is not what is wanted;
+ * instead it would be good to know which API interface the object implements. Let's say we have a API interface
+ * hierarchy, and we know that each object implements only one specific interface (it may implement more, but all others
+ * must be then super-interface of the actual implemented one). Then we have a mapping from types of interfaces to some
+ * other things, like algorithms or some other functionality. We can not use {@link Map#get(Object)} or
+ * {@link Map#containsKey(Object)} methods for the result of {@link Object#getClass()}, since we would much rather use
+ * API interfaces than actual implementing classes as keys. And because of that, each time, we need to iterate through
+ * whole map, and check for each key that whether the specified object is instance of this key. In other words, quite
+ * inefficient.
+ * </p>
+ * <p>
+ * <p>
+ * This is when this interface comes to aid. It provides a method returning an API interface/class, which is implemented
+ * by the implementation. Then one can use the {@link Map#get(Object)} and {@link Map#containsKey(Object)} methods in
+ * order to retrieve the object associated with specific API interface, without the need to iterate through whole map.
+ * </p>
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface Typeable<BaseType>
+{
+
+    /**
+     * Returns the API interface/class, which is implemented by this object.
+     *
+     * @return The API interface/class, which is implemented by this object.
+     */
+    Class<? extends BaseType> getImplementedType();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/BetweenPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/BetweenPredicate.java
new file mode 100644
index 0000000..15ca4be
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/BetweenPredicate.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+
+/**
+ * The interface for syntax element representing SQL expression {@code BETWEEN }x {@code AND} y.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface BetweenPredicate
+    extends MultiPredicate
+{
+
+    /**
+     * Returns the minimum value (the expression on the left side of {@code AND}).
+     *
+     * @return The minimum value.
+     */
+    NonBooleanExpression getMinimum();
+
+    /**
+     * Returns the maxmimum value (the expression on the right side of {@code AND}).
+     *
+     * @return The maximum value.
+     */
+    NonBooleanExpression getMaximum();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/BinaryPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/BinaryPredicate.java
new file mode 100644
index 0000000..64a8edc
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/BinaryPredicate.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+
+/**
+ * A common interface for all boolean expressions taking two value expressions and having some operator between them.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface BinaryPredicate
+    extends Predicate
+{
+
+    /**
+     * Returns the expression on the left side of the operator.
+     *
+     * @return The expression on the left side of the operator.
+     */
+    NonBooleanExpression getLeft();
+
+    /**
+     * Returns the expression on the right side of the operator.
+     *
+     * @return The expression on the right side of the operator.
+     */
+    NonBooleanExpression getRight();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/BooleanExpression.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/BooleanExpression.java
new file mode 100644
index 0000000..79cd276
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/BooleanExpression.java
@@ -0,0 +1,86 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+
+/**
+ * A common interface for all boolean expressions in SQL language.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface BooleanExpression
+    extends ValueExpression
+{
+
+    /**
+     * This class represents a boolean expression which always evaluates to true ({@code TRUE}).
+     *
+     * @author Stanislav Muhametsin
+     */
+    final class True
+        implements BooleanExpression
+    {
+        private True()
+        {
+
+        }
+
+        /**
+         * Returns {@link True}.
+         */
+        public Class<? extends ValueExpression> getImplementedType()
+        {
+            return True.class;
+        }
+
+        /**
+         * Returns the singleton instance representing {@code TRUE}.
+         */
+        public static final True INSTANCE = new True();
+    }
+
+    /**
+     * This class represents a boolean expression which always evaluates to false ({@code FALSE}.
+     *
+     * @author Stanislav Muhametsin
+     */
+    final class False
+        implements BooleanExpression
+    {
+        private False()
+        {
+
+        }
+
+        /**
+         * Returns {@link False}.
+         */
+        public Class<? extends ValueExpression> getImplementedType()
+        {
+            return False.class;
+        }
+
+        /**
+         * Returns the singleton instance representing {@code FALSE}.
+         */
+        public static final False INSTANCE = new False();
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/BooleanTest.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/BooleanTest.java
new file mode 100644
index 0000000..9d0a05b
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/BooleanTest.java
@@ -0,0 +1,94 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * The interface for syntax element representing {@code <X> IS [NOT] (TRUE | FALSE | UNKNOWN)} expression (boolean
+ * test), where {@code <X>} is some boolean expression.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface BooleanTest
+    extends ComposedBooleanExpression
+{
+    /**
+     * The type of the test.
+     *
+     * @author Stanislav Muhametsin
+     */
+    final class TestType
+    {
+
+        /**
+         * The test which tests the expression against the truth value.
+         */
+        public static final TestType IS = new TestType();
+
+        /**
+         * The test which tests the expression against the negation of the truth value.
+         */
+        public static final TestType IS_NOT = new TestType();
+    }
+
+    /**
+     * The tested truth value.
+     *
+     * @author Stanislav Muhametsin
+     */
+    final class TruthValue
+    {
+
+        /**
+         * The {@code TRUE} truth value.
+         */
+        public static final TruthValue TRUE = new TruthValue();
+
+        /**
+         * The {@code FALSE} truth value.
+         */
+        public static final TruthValue FALSE = new TruthValue();
+
+        /**
+         * The {@code UNKNOWN} truth value.
+         */
+        public static final TruthValue UNKNOWN = new TruthValue();
+    }
+
+    /**
+     * Returns the boolean expression to be tested.
+     *
+     * @return The boolean expression to be tested.
+     */
+    BooleanExpression getBooleanExpression();
+
+    /**
+     * Returns the test type - whether it should, or should not, be something.
+     *
+     * @return The test type.
+     */
+    TestType getTestType();
+
+    /**
+     * The truth value which must evaluate from the expression.
+     *
+     * @return The truth value which must evaluate from the expression.
+     */
+    TruthValue getTruthValue();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/ComposedBooleanExpression.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/ComposedBooleanExpression.java
new file mode 100644
index 0000000..1dbeb76
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/ComposedBooleanExpression.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * A common interface for all boolean expressions composing of other boolean expressions.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface ComposedBooleanExpression
+    extends BooleanExpression, Iterable<BooleanExpression>
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/Conjunction.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/Conjunction.java
new file mode 100644
index 0000000..33b6e29
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/Conjunction.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * A conjunction ({@code AND}) of two boolean expressions.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface Conjunction
+    extends ComposedBooleanExpression
+{
+
+    /**
+     * Returns the boolean expression on the left side of {@code AND}.
+     *
+     * @return The boolean expression on the left side of {@code AND}.
+     */
+    BooleanExpression getLeft();
+
+    /**
+     * Returns the boolean expression on the right side of {@code AND}.
+     *
+     * @return The boolean expression on the right side of {@code AND}.
+     */
+    BooleanExpression getRight();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/Disjunction.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/Disjunction.java
new file mode 100644
index 0000000..b9725ff
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/Disjunction.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * A disjunction ({@code OR} of two boolean expressions.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface Disjunction
+    extends ComposedBooleanExpression
+{
+    /**
+     * Returns the boolean expression on the left side of {@code OR}.
+     *
+     * @return The boolean expression on the left side of {@code OR}.
+     */
+    BooleanExpression getLeft();
+
+    /**
+     * Returns the boolean expression on the right side of {@code OR}.
+     *
+     * @return The boolean expression on the right side of {@code OR}.
+     */
+    BooleanExpression getRight();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/EqualsPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/EqualsPredicate.java
new file mode 100644
index 0000000..9aad53b
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/EqualsPredicate.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * The interface for syntax element representing equality test (x {@code =} y).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface EqualsPredicate
+    extends BinaryPredicate
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/ExistsPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/ExistsPredicate.java
new file mode 100644
index 0000000..bb203d5
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/ExistsPredicate.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+
+/**
+ * The interface for syntax element representing existence test ({@code EXISTS}).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface ExistsPredicate
+    extends UnaryPredicate
+{
+    /**
+     * Returns the query on which {@code EXISTS} operates on.
+     */
+    QueryExpression getValueExpression();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/GreaterOrEqualPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/GreaterOrEqualPredicate.java
new file mode 100644
index 0000000..ac5d684
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/GreaterOrEqualPredicate.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * The interface for syntax element representing the test of left value being greater than, or equal to right value (x
+ * {@code >=} y).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface GreaterOrEqualPredicate
+    extends BinaryPredicate
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/GreaterThanPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/GreaterThanPredicate.java
new file mode 100644
index 0000000..9132336
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/GreaterThanPredicate.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * The interface for syntax element representing the test of left value being greater than right value (x {@code >} y).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface GreaterThanPredicate
+    extends BinaryPredicate
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/InPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/InPredicate.java
new file mode 100644
index 0000000..2326f5f
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/InPredicate.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * The interface for syntax element representing the test of something being one of the specified set of values (x
+ * {@code IN (}y, z, {@code ...)}).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface InPredicate
+    extends MultiPredicate
+{
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/IsNotNullPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/IsNotNullPredicate.java
new file mode 100644
index 0000000..956cfb7
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/IsNotNullPredicate.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * The interface for syntax element representing test for something being not {@code NULL} (x {@code IS NOT NULL}).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface IsNotNullPredicate
+    extends UnaryPredicate
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/IsNullPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/IsNullPredicate.java
new file mode 100644
index 0000000..7612fbe
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/IsNullPredicate.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * The interface for syntax element representing test for something being {@code NULL} (x {@code IS NULL}).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface IsNullPredicate
+    extends UnaryPredicate
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/LessOrEqualPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/LessOrEqualPredicate.java
new file mode 100644
index 0000000..61f78dc
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/LessOrEqualPredicate.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * The interface for syntax element representing the test of left value being lesser than, or equal to right value (x
+ * {@code <=} y).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface LessOrEqualPredicate
+    extends BinaryPredicate
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/LessThanPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/LessThanPredicate.java
new file mode 100644
index 0000000..fc89053
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/LessThanPredicate.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * The interface for syntax element representing the test of left value being less than right value (x {@code <} y).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface LessThanPredicate
+    extends BinaryPredicate
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/LikePredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/LikePredicate.java
new file mode 100644
index 0000000..3c213d4
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/LikePredicate.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * The interface for syntax element representing the test of left expression matching the supplied pattern using basic
+ * SQL match (x {@code LIKE} y).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface LikePredicate
+    extends BinaryPredicate
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/MultiPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/MultiPredicate.java
new file mode 100644
index 0000000..955c103
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/MultiPredicate.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+
+/**
+ * A common interface for all predicates accepting more than two expressions.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface MultiPredicate
+    extends Predicate
+{
+
+    /**
+     * Returns the expression on the left side (the first expression).
+     *
+     * @return The first expression.
+     */
+    NonBooleanExpression getLeft();
+
+    /**
+     * Returns the remaining expressions after the first one.
+     *
+     * @return The remaining expressions after the first one.
+     */
+    List<NonBooleanExpression> getRights();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/Negation.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/Negation.java
new file mode 100644
index 0000000..2a34115
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/Negation.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * A negation ({@code NOT} x) of a boolean expression.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface Negation
+    extends ComposedBooleanExpression
+{
+
+    /**
+     * Returns the boolean expression being negated.
+     *
+     * @return The boolean expression being negated.
+     */
+    BooleanExpression getNegated();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/NotBetweenPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/NotBetweenPredicate.java
new file mode 100644
index 0000000..c1f7c1f
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/NotBetweenPredicate.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+
+/**
+ * The interface for syntax element representing SQL expression {@code NOT BETWEEN} x {@code AND} y.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface NotBetweenPredicate
+    extends MultiPredicate
+{
+    /**
+     * Returns the minimum value (the expression on the left side of {@code AND}).
+     *
+     * @return The minimum value.
+     */
+    NonBooleanExpression getMinimum();
+
+    /**
+     * Returns the maxmimum value (the expression on the right side of {@code AND}).
+     *
+     * @return The maximum value.
+     */
+    NonBooleanExpression getMaximum();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/NotEqualsPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/NotEqualsPredicate.java
new file mode 100644
index 0000000..c6e69fc
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/NotEqualsPredicate.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * The interface for syntax element representing inequality test (x {@code <>} y).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface NotEqualsPredicate
+    extends BinaryPredicate
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/NotInPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/NotInPredicate.java
new file mode 100644
index 0000000..cb9addd
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/NotInPredicate.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * The interface for syntax element representing the test of something not being one of the specified set of values (x
+ * {@code NOT IN (}y, z, {@code ...)}).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface NotInPredicate
+    extends MultiPredicate
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/NotLikePredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/NotLikePredicate.java
new file mode 100644
index 0000000..efc3a4d
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/NotLikePredicate.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * The interface for syntax element representing the test of left expression not matching the supplied pattern using
+ * basic SQL match (x {@code NOT LIKE} y).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface NotLikePredicate
+    extends BinaryPredicate
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/NotRegexpPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/NotRegexpPredicate.java
new file mode 100644
index 0000000..7f83dcc
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/NotRegexpPredicate.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * The interface for syntax element representing the test of left expression not matching the supplied pattern using
+ * advanced regular expression match (operator varies). By default this kind of matching is not supported.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface NotRegexpPredicate
+    extends BinaryPredicate
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/Predicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/Predicate.java
new file mode 100644
index 0000000..c58cf58
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/Predicate.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * A common interfaces for predicates (boolean expressions not containing other boolean expressions).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface Predicate
+    extends BooleanExpression
+{
+    /**
+     * A class representing empty predicate. The result of empty predicate is empty string. If empty predicate is
+     * encountered inside {@link Conjunction} or {@link Disjunction}, their operator is omitted. So, <i>empty
+     * predicate</i> {@code AND} <i>something</i> becomes just <i>something</i>.
+     *
+     * @author Stanislav Muhametsin
+     */
+    final class EmptyPredicate
+        implements Predicate
+    {
+        private EmptyPredicate()
+        {
+        }
+
+        /**
+         * Returns {@link EmptyPredicate}.
+         */
+        public Class<? extends BooleanExpression> getImplementedType()
+        {
+            return EmptyPredicate.class;
+        }
+
+        /**
+         * Singleton instance of {@link EmptyPredicate}.
+         */
+        public static final EmptyPredicate INSTANCE = new EmptyPredicate();
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/RegexpPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/RegexpPredicate.java
new file mode 100644
index 0000000..f44732b
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/RegexpPredicate.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+/**
+ * The interface for syntax element representing the test of left expression matching the supplied pattern using
+ * advanced regular expression match (operator varies). By default this kind of matching is not supported.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface RegexpPredicate
+    extends BinaryPredicate
+{
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/UnaryPredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/UnaryPredicate.java
new file mode 100644
index 0000000..37aed37
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/UnaryPredicate.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+
+/**
+ * A common interface for all boolean expressions requiring exactly one value expression.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface UnaryPredicate
+    extends Predicate
+{
+
+    /**
+     * Returns the value expression for this predicate.
+     *
+     * @return The value expression for this predicate.
+     */
+    NonBooleanExpression getValueExpression();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/UniquePredicate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/UniquePredicate.java
new file mode 100644
index 0000000..f91eeab
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/UniquePredicate.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+
+/**
+ * The interface for syntax element representing the test for uniqueness ({@code UNIQUE} sub-query).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface UniquePredicate
+    extends UnaryPredicate
+{
+
+    /**
+     * Gets the query on which {@code UNIQUE} operates on.
+     */
+    QueryExpression getValueExpression();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/package-info.java
new file mode 100644
index 0000000..5d5fd7f
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/booleans/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This package provides interfaces for syntax elements of boolean expressions in SQL language. As all syntax elements, they provide a read-only API to their contents.
+ */
+package org.apache.polygene.library.sql.generator.grammar.booleans;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/AbstractBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/AbstractBuilder.java
new file mode 100644
index 0000000..a938b1b
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/AbstractBuilder.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders;
+
+/**
+ * A common interface for all builders.
+ *
+ * @param <ExpressionType> The type of the expression being built.
+ * @author Stanislav Muhametsin
+ */
+public interface AbstractBuilder<ExpressionType>
+{
+    /**
+     * Returns the expression which was being built by this builder.
+     *
+     * @return The expression built by this builder.
+     */
+    ExpressionType createExpression();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/booleans/BooleanBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/booleans/BooleanBuilder.java
new file mode 100644
index 0000000..7788daa
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/booleans/BooleanBuilder.java
@@ -0,0 +1,65 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+
+/**
+ * A builder-pattern interface to build boolean expressions. It holds the current expression, modifying it as per user's
+ * instructions, and returns it once the {@link #createExpression()} method is called.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface BooleanBuilder
+    extends AbstractBuilder<BooleanExpression>
+{
+
+    /**
+     * Sets current expression as current expression {@code AND next}.
+     *
+     * @param next The expression on a right hand of {@code AND}.
+     * @return This builder.
+     */
+    BooleanBuilder and( BooleanExpression next );
+
+    /**
+     * Sets current expression as current expression {@code OR next}
+     *
+     * @param next The expression on a right hand of {@code OR}
+     * @return This builder.
+     */
+    BooleanBuilder or( BooleanExpression next );
+
+    /**
+     * Sets current expression as {@code NOT} current expression.
+     *
+     * @return This builder.
+     */
+    BooleanBuilder not();
+
+    /**
+     * Sets current expression as given parameter.
+     *
+     * @param newExpression The new expression.
+     * @return This builder.
+     */
+    BooleanBuilder reset( BooleanExpression newExpression );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/booleans/InBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/booleans/InBuilder.java
new file mode 100644
index 0000000..23295ed
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/booleans/InBuilder.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.InPredicate;
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+
+/**
+ * The builder to build {@code IN} expressions
+ *
+ * @author Stanislav Muhametsin
+ * @see InPredicate
+ */
+public interface InBuilder
+    extends AbstractBuilder<InPredicate>
+{
+
+    InBuilder addValues( NonBooleanExpression... expressions );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/booleans/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/booleans/package-info.java
new file mode 100644
index 0000000..2f741fb
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/booleans/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This package contains builders for various boolean expressions.
+ */
+package org.apache.polygene.library.sql.generator.grammar.builders.booleans;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/ForeignKeyConstraintBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/ForeignKeyConstraintBuilder.java
new file mode 100644
index 0000000..50cbeeb
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/ForeignKeyConstraintBuilder.java
@@ -0,0 +1,133 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.definition;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ForeignKeyConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.MatchType;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ReferentialAction;
+
+/**
+ * The builder for table constraint {@code FOREIGN KEY(source columns) REFERENCES table_name(target columns) etc....}).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface ForeignKeyConstraintBuilder
+    extends AbstractBuilder<ForeignKeyConstraint>
+{
+
+    /**
+     * Adds source column names to this foreign key constraint.
+     *
+     * @param columnNames The source column names to be added to this foreign key constraint.
+     * @return This builder.
+     */
+    ForeignKeyConstraintBuilder addSourceColumns( String... columnNames );
+
+    /**
+     * Adds target column names to this foreign key constraint.
+     *
+     * @param columnNames The target column names to be added to this foreign key constraint.
+     * @return This builder.
+     */
+    ForeignKeyConstraintBuilder addTargetColumns( String... columnNames );
+
+    /**
+     * Sets the target table name for this foreign key constraint.
+     *
+     * @param tableName The target table name for this foreign key constraint.
+     * @return This builder.
+     */
+    ForeignKeyConstraintBuilder setTargetTableName( TableNameDirect tableName );
+
+    /**
+     * Sets the match type for this foreign key constraint.
+     *
+     * @param matchType The match type for this foreign key constraint.
+     * @return This builder.
+     * @see MatchType
+     */
+    ForeignKeyConstraintBuilder setMatchType( MatchType matchType );
+
+    /**
+     * Sets the {@code ON UPDATE} action.
+     *
+     * @param action The action to perform {@code ON UPDATE}.
+     * @return This builder.
+     * @see ReferentialAction
+     */
+    ForeignKeyConstraintBuilder setOnUpdate( ReferentialAction action );
+
+    /**
+     * Sets the {@code ON DELETE} action.
+     *
+     * @param action The action to perform {@code ON DELETE}.
+     * @return This builder.
+     * @see ReferentialAction
+     */
+    ForeignKeyConstraintBuilder setOnDelete( ReferentialAction action );
+
+    /**
+     * Returns the source column names for this foreign key constraint.
+     *
+     * @return The source column names for this foreign key constraint.
+     */
+    List<String> getSourceColumns();
+
+    /**
+     * Returns the target column names for this foreign key constraint.
+     *
+     * @return The target column names for this foreign key constraint.
+     */
+    List<String> getTargetColumns();
+
+    /**
+     * Returns the target table name for this foreign key constraint.
+     *
+     * @return The target table name for this foreign key constraint.
+     */
+    TableNameDirect getTableName();
+
+    /**
+     * Returns the match type for this foreign key constraint.
+     *
+     * @return The match type for this foreign key constraint.
+     * @see MatchType
+     */
+    MatchType getMatchType();
+
+    /**
+     * Returns the {@code ON UPDATE} action for this foreign key constraint.
+     *
+     * @return The {@code ON UPDATE} action for this foreign key constraint.
+     * @see ReferentialAction
+     */
+    ReferentialAction getOnUpdate();
+
+    /**
+     * Returns the {@code ON DELETE} action for this foreign key constraint.
+     *
+     * @return The {@code ON DELETE} action for this foreign key constraint.
+     * @see ReferentialAction
+     */
+    ReferentialAction getOnDelete();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/SchemaDefinitionBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/SchemaDefinitionBuilder.java
new file mode 100644
index 0000000..6f1080a
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/SchemaDefinitionBuilder.java
@@ -0,0 +1,81 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.definition;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.definition.schema.SchemaDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.schema.SchemaElement;
+
+/**
+ * This is builder interface for creating schema definition statements ({@code CREATE SCHEMA} ...).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SchemaDefinitionBuilder
+    extends AbstractBuilder<SchemaDefinition>
+{
+
+    /**
+     * Sets the name for the schema to be created.
+     *
+     * @param schemaName The name for the schema to be created.
+     * @return This builder.
+     */
+    SchemaDefinitionBuilder setSchemaName( String schemaName );
+
+    /**
+     * Sets the character set for the schema to be created.
+     *
+     * @param charset The charset for the schema to be created.
+     * @return This builder.
+     */
+    SchemaDefinitionBuilder setSchemaCharset( String charset );
+
+    /**
+     * Adds schema elements for the schema to be created.
+     *
+     * @param elements The schema elements for the schema to be created.
+     * @return This builder.
+     * @see SchemaElement
+     */
+    SchemaDefinitionBuilder addSchemaElements( SchemaElement... elements );
+
+    /**
+     * Returns the name of the schema to be created.
+     *
+     * @return The name of the schema to be created.
+     */
+    String getSchemaName();
+
+    /**
+     * Returns the name of the character set for the schema to be created.
+     *
+     * @return The name of the character set for the schema to be created.
+     */
+    String getSchemaCharset();
+
+    /**
+     * Returns all the schema elements for the schema to be created.
+     *
+     * @return All the schema elements for the schema to be created.
+     */
+    List<SchemaElement> getSchemaElements();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/TableDefinitionBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/TableDefinitionBuilder.java
new file mode 100644
index 0000000..ed65f94
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/TableDefinitionBuilder.java
@@ -0,0 +1,104 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.definition;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.TableName;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableCommitAction;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableContentsSource;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableElementList;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableScope;
+
+/**
+ * This is the builder for table definition statements ({@code CREATE TABLE} ...).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface TableDefinitionBuilder
+    extends AbstractBuilder<TableDefinition>
+{
+
+    /**
+     * Sets the scope for this table.
+     *
+     * @param scope The scope for this table.
+     * @return This builder.
+     * @see TableScope
+     */
+    TableDefinitionBuilder setTableScope( TableScope scope );
+
+    /**
+     * Sets the name for this table.
+     *
+     * @param tableName The name for this table.
+     * @return This builder.
+     * @see TableName
+     */
+    TableDefinitionBuilder setTableName( TableNameDirect tableName );
+
+    /**
+     * Sets the commit action for this table.
+     *
+     * @param commitAction The commit action for this table.
+     * @return This builder.
+     * @see TableCommitAction
+     */
+    TableDefinitionBuilder setCommitAction( TableCommitAction commitAction );
+
+    /**
+     * Sets the contents source for this table.
+     *
+     * @param contents The contents source for this table.
+     * @return This builder.
+     * @see TableContentsSource
+     * @see TableElementList
+     */
+    TableDefinitionBuilder setTableContentsSource( TableContentsSource contents );
+
+    /**
+     * Returns the scope for this table.
+     *
+     * @return The scope for this table.
+     */
+    TableScope getTableScope();
+
+    /**
+     * Returns the name for this table.
+     *
+     * @return The name for this table.
+     */
+    TableNameDirect getTableName();
+
+    /**
+     * Returns the commit action for this table.
+     *
+     * @return The commit action for this table.
+     */
+    TableCommitAction getCommitAction();
+
+    /**
+     * Returns the table contents source for this table.
+     *
+     * @return The table contents source for this table.
+     */
+    TableContentsSource getTableContentsSource();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/TableElementListBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/TableElementListBuilder.java
new file mode 100644
index 0000000..50defa2
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/TableElementListBuilder.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.definition;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableElement;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableElementList;
+
+/**
+ * This is the builder for table element list used in {@code CREATE TABLE} statements.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface TableElementListBuilder
+    extends AbstractBuilder<TableElementList>
+{
+
+    /**
+     * Adds the table element to this list.
+     *
+     * @param element The table element to add to this list.
+     * @return This builder.
+     */
+    TableElementListBuilder addTableElement( TableElement element );
+
+    /**
+     * Returns all the elements that this builder has.
+     *
+     * @return All the elements that this builder has.
+     */
+    List<TableElement> getTableElements();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/UniqueConstraintBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/UniqueConstraintBuilder.java
new file mode 100644
index 0000000..4dfc67c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/UniqueConstraintBuilder.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.definition;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.UniqueConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.UniqueSpecification;
+
+/**
+ * This is builder for {@code UNIQUE(...)} and {@code PRIMARY KEY(...)} table constraints in table definition.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface UniqueConstraintBuilder
+    extends AbstractBuilder<UniqueConstraint>
+{
+
+    /**
+     * Sets the uniqueness kind for this uniqueness constraint.
+     *
+     * @param uniqueness The uniqueness kind for this uniqueness constraint.
+     * @return This builder.
+     * @see UniqueSpecification
+     */
+    UniqueConstraintBuilder setUniqueness( UniqueSpecification uniqueness );
+
+    /**
+     * Adds the columns that have to be unique.
+     *
+     * @param columnNames The column names that have to be unique.
+     * @return This builder.
+     */
+    UniqueConstraintBuilder addColumns( String... columnNames );
+
+    /**
+     * Returns the uniqueness type for this uniqueness constraint.
+     *
+     * @return The uniqueness type for this uniqueness constraint.
+     */
+    UniqueSpecification getUniqueness();
+
+    /**
+     * Returns the column names that have to be unique.
+     *
+     * @return The column names that have to be unique.
+     */
+    List<String> getColumns();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/ViewDefinitionBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/ViewDefinitionBuilder.java
new file mode 100644
index 0000000..ae61aa2
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/ViewDefinitionBuilder.java
@@ -0,0 +1,117 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.definition;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.RegularViewSpecification;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.ViewCheckOption;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.ViewDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.ViewSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+
+/**
+ * This is a builder for {@code CREATE VIEW} statements.
+ *
+ * @author Stanislav Muhametsin
+ * @see ViewDefinition
+ */
+public interface ViewDefinitionBuilder
+    extends AbstractBuilder<ViewDefinition>
+{
+
+    /**
+     * Sets whether this view is {@code RECURSIVE}.
+     *
+     * @param isRecursive True if view is to be {@code RECURSIVE}; false otherwise.
+     * @return This builder.
+     */
+    ViewDefinitionBuilder setRecursive( Boolean isRecursive );
+
+    /**
+     * Sets the name for this view.
+     *
+     * @param viewName The name for this view.
+     * @return This builder.
+     */
+    ViewDefinitionBuilder setViewName( TableNameDirect viewName );
+
+    /**
+     * Sets the query for this view.
+     *
+     * @param query The query for this view.
+     * @return This builder.
+     */
+    ViewDefinitionBuilder setQuery( QueryExpression query );
+
+    /**
+     * Sets the view check option for this view.
+     *
+     * @param viewCheck The view check option for this view.
+     * @return This builder.
+     * @see ViewCheckOption
+     */
+    ViewDefinitionBuilder setViewCheckOption( ViewCheckOption viewCheck );
+
+    /**
+     * Sets the view specification for this view. Typically is a list of columns (via {@link RegularViewSpecification}).
+     *
+     * @param spec The view specification.
+     * @return This builder.
+     * @see ViewSpecification
+     */
+    ViewDefinitionBuilder setViewSpecification( ViewSpecification spec );
+
+    /**
+     * Returns whether this view is to be {@code RECURSIVE}.
+     *
+     * @return True if this view is to be {@code RECURSIVE}; false otherwise.
+     */
+    Boolean isRecursive();
+
+    /**
+     * Returns the name of the view.
+     *
+     * @return The name of the view.
+     */
+    TableNameDirect getViewName();
+
+    /**
+     * Returns the query for the view.
+     *
+     * @return The query for the view.
+     */
+    QueryExpression getQueryExpression();
+
+    /**
+     * Returns the view check option.
+     *
+     * @return The view check option.
+     * @see ViewCheckOption
+     */
+    ViewCheckOption getViewCheckOption();
+
+    /**
+     * Returns the view specification. Typically is a list of columns (via {@link RegularViewSpecification}).
+     *
+     * @return The view specification.
+     */
+    ViewSpecification getViewSpecification();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/package-info.java
new file mode 100644
index 0000000..d438ea9
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/definition/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This is package containing builders for syntax elements used in SQL Data Definition statements (typically {@code CREATE} statements).
+ */
+package org.apache.polygene.library.sql.generator.grammar.builders.definition;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/ColumnSourceByValuesBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/ColumnSourceByValuesBuilder.java
new file mode 100644
index 0000000..dc3a709
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/ColumnSourceByValuesBuilder.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.modification;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSourceByValues;
+
+/**
+ * This builder builds the {@link ColumnSourceByValues} syntax element.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface ColumnSourceByValuesBuilder
+    extends AbstractBuilder<ColumnSourceByValues>
+{
+    /**
+     * Adds the expressions as values to columns.
+     *
+     * @param values The value expressions to add.
+     * @return This builder.
+     */
+    ColumnSourceByValuesBuilder addValues( ValueExpression... values );
+
+    /**
+     * Returns the value expressions for the columns.
+     *
+     * @return The value expressions for the columns.
+     */
+    List<ValueExpression> getValues();
+
+    /**
+     * Adds the names for the columns.
+     *
+     * @param columnNames The names for columns.
+     * @return This builder.
+     */
+    ColumnSourceByValuesBuilder addColumnNames( String... columnNames );
+
+    /**
+     * Returns the names for the columns.
+     *
+     * @return The names for the columns.
+     */
+    List<String> getColumnNames();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/DeleteBySearchBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/DeleteBySearchBuilder.java
new file mode 100644
index 0000000..4d1ca4a
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/DeleteBySearchBuilder.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.modification;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.booleans.BooleanBuilder;
+import org.apache.polygene.library.sql.generator.grammar.modification.DeleteBySearch;
+import org.apache.polygene.library.sql.generator.grammar.modification.TargetTable;
+
+/**
+ * This builder builds statements deleting rows matching search condition ({@code DELETE FROM} table {@code [WHERE}
+ * searchCondition {@code ]}).
+ *
+ * @author Stanislav Muhametsin
+ * @see TargetTable
+ * @see BooleanBuilder
+ */
+public interface DeleteBySearchBuilder
+    extends AbstractBuilder<DeleteBySearch>
+{
+    /**
+     * Sets the target table for this {@code DELETE} statement.
+     *
+     * @param table The target table for this {@code DELETE} statement.
+     * @return This builder.
+     */
+    DeleteBySearchBuilder setTargetTable( TargetTable table );
+
+    /**
+     * Retrieves the target table for this {@code DELETE} statement.
+     *
+     * @return The target table for this {@code DELETE} statement.
+     */
+    TargetTable getTargetTable();
+
+    /**
+     * Returns the builder for search condition for this {@code DELETE} statement (boolean expression after
+     * {@code WHERE}). The search condition is optional.
+     *
+     * @return The builder for search condition for this {@code DELETE} statement.
+     */
+    BooleanBuilder getWhere();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/InsertStatementBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/InsertStatementBuilder.java
new file mode 100644
index 0000000..c404bc5
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/InsertStatementBuilder.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.modification;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.TableName;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSource;
+import org.apache.polygene.library.sql.generator.grammar.modification.InsertStatement;
+
+/**
+ * This builder builds statements inserting rows to tables ({@code INSERT INTO } tableName {@code [(} column names
+ * {@code )]} expression).
+ *
+ * @author Stanislav Muhametsin
+ * @see TableName
+ * @see ColumnSource
+ */
+public interface InsertStatementBuilder
+    extends AbstractBuilder<InsertStatement>
+{
+
+    /**
+     * Sets the table name for this {@code INSERT} statement.
+     *
+     * @param tableName The table name for this {@code INSERT} statement.
+     * @return This builder.
+     */
+    InsertStatementBuilder setTableName( TableNameDirect tableName );
+
+    /**
+     * Returns the table name for this {@code INSERT} statement.
+     *
+     * @return The table name for this {@code INSERT} statement.
+     */
+    TableNameDirect getTableName();
+
+    /**
+     * Sets the source for the columns for this {@code INSERT} statement.
+     *
+     * @param source The source for columns for this {@code INSERT} statement.
+     * @return This builder.
+     */
+    InsertStatementBuilder setColumnSource( ColumnSource source );
+
+    /**
+     * Returns the source for the columns for this {@code INSERT} statement.
+     *
+     * @return The source for the columns for this {@code INSERT} statement.
+     */
+    ColumnSource getColumnSource();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/UpdateBySearchBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/UpdateBySearchBuilder.java
new file mode 100644
index 0000000..c82087c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/UpdateBySearchBuilder.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.modification;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.booleans.BooleanBuilder;
+import org.apache.polygene.library.sql.generator.grammar.modification.SetClause;
+import org.apache.polygene.library.sql.generator.grammar.modification.TargetTable;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateBySearch;
+
+/**
+ * This builder builds statements updating rows matching search condition ({@code UPDATE} table {@code SET} set-clauses
+ * {@code [WHERE} searchCondition {@code ]}).
+ *
+ * @author Stanislav Muhametsin
+ * @see SetClause
+ * @see BooleanBuilder
+ */
+public interface UpdateBySearchBuilder
+    extends AbstractBuilder<UpdateBySearch>
+{
+    /**
+     * Sets the target table for this {@code UPDATE} statement.
+     *
+     * @param table The target table for this {@code UPDATE} statement.
+     * @return This builder.
+     */
+    UpdateBySearchBuilder setTargetTable( TargetTable table );
+
+    /**
+     * Returns the builder for search condition for this {@code UPDATE} statement (boolean expression after
+     * {@code WHERE}). The search condition is optional.
+     *
+     * @return The builder for search condition for this {@code UPDATE} statement.
+     */
+    BooleanBuilder getWhereBuilder();
+
+    /**
+     * Adds the clause to the set-clause list of this {@code UPDATE} statement.
+     *
+     * @param clauses The set-clauses for this {@code UPDATE} statement.
+     * @return This builder.
+     */
+    UpdateBySearchBuilder addSetClauses( SetClause... clauses );
+
+    /**
+     * Returns the list of set clauses which has been added to this builder.
+     *
+     * @return The list of set clauses which has been added to this builder.
+     */
+    List<SetClause> getSetClauses();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/package-info.java
new file mode 100644
index 0000000..181488c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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 to hold builders common for SQL modification clauses ({@code INSERT}, {@code UPDATE}, and {@code DELETE}).
+ */
+package org.apache.polygene.library.sql.generator.grammar.builders.modification;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/pgsql/PgSQLInsertStatementBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/pgsql/PgSQLInsertStatementBuilder.java
new file mode 100644
index 0000000..38cbca3
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/pgsql/PgSQLInsertStatementBuilder.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.modification.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.InsertStatementBuilder;
+import org.apache.polygene.library.sql.generator.grammar.query.SelectColumnClause;
+
+/**
+ * This build is used for creating {@code INSERT} statements specific for PostgreSQL databases.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface PgSQLInsertStatementBuilder extends InsertStatementBuilder
+{
+
+    /**
+     * Sets the {@code RETURNING} clause for this {@code INSERT} statement.
+     *
+     * @param clause The {@code RETURNING} clause. May be {@code null} if no {@code RETURNING}
+     *               clause is desired.
+     * @return This builder.
+     */
+    PgSQLInsertStatementBuilder setReturningClause( SelectColumnClause clause );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/pgsql/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/pgsql/package-info.java
new file mode 100644
index 0000000..359bfff
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/modification/pgsql/package-info.java
@@ -0,0 +1,24 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This package contains modification statement ( {@code UPDATE}, {@code INSERT} or {@code DELETE})
+ * builders specific for PostgreSQL database.
+ */
+package org.apache.polygene.library.sql.generator.grammar.builders.modification.pgsql;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/package-info.java
new file mode 100644
index 0000000..dc3e00c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * A package containing builders for common elements of SQL syntax.
+ */
+package org.apache.polygene.library.sql.generator.grammar.builders;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/AbstractQueryBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/AbstractQueryBuilder.java
new file mode 100644
index 0000000..86a1b2e
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/AbstractQueryBuilder.java
@@ -0,0 +1,82 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.query;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.literals.NumericLiteral;
+import org.apache.polygene.library.sql.generator.grammar.query.LimitSpecification;
+
+/**
+ * @author 2011 Stanislav Muhametsin
+ */
+public interface AbstractQueryBuilder<ExpressionType>
+    extends AbstractBuilder<ExpressionType>
+{
+    /**
+     * Adds the {@code FETCH FIRST ROW ONLY} expression for this query. The resulting {@link LimitSpecification} will
+     * have its count as {@code null}.
+     *
+     * @return This builder.
+     */
+    AbstractQueryBuilder<ExpressionType> limit();
+
+    /**
+     * Adds the {@code FETCH FIRST <number> ROWS ONLY} expression for this query. Calling this method is equivalent of
+     * calling {@link #limit(NonBooleanExpression)} and passing the {@link NumericLiteral} representing the given number
+     * as the parameter.
+     *
+     * @param max The maximum amount of rows for this query to return. Use {@code null} to remove the
+     *            {@code FETCH FIRST <number> ROWS ONLY} expression.
+     * @return This builder.
+     */
+    AbstractQueryBuilder<ExpressionType> limit( Integer max );
+
+    /**
+     * Adds the {@code FETCH FIRST <number> ROWS ONLY} expression for this query.
+     *
+     * @param max The maximum amount of rows for this query to return. May be subquery or something else that evaluates
+     *            to number or {@code NULL}. Use {@code null} to remove the {@code FETCH FIRST <number> ROWS ONLY}
+     *            expression.
+     * @return This builder.
+     */
+    AbstractQueryBuilder<ExpressionType> limit( NonBooleanExpression max );
+
+    /**
+     * Adds the {@code OFFSET <number> ROWS} expression for this query. Calling this method is equivalen of calling
+     * {@link #offset(NonBooleanExpression)} and passing the {@link NumericLiteral} representing the given number as the
+     * parameter.
+     *
+     * @param skip The amount of rows to skip before starting to include them into this query. Use {@code null} to
+     *             remove the {@code OFFSET <number> ROWS} expression.
+     * @return This builder.
+     */
+    AbstractQueryBuilder<ExpressionType> offset( Integer skip );
+
+    /**
+     * Adds the {@code OFFSET <number> ROWS} expression for this query.
+     *
+     * @param skip The amount of rows to skip before starting to include them into this query. May be subquery or
+     *             something else that evaluates to number or {@code NULL}. Use {@code null} to remove the
+     *             {@code OFFSET <number> ROWS} expression.
+     * @return This builder.
+     */
+    AbstractQueryBuilder<ExpressionType> offset( NonBooleanExpression skip );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/ColumnsBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/ColumnsBuilder.java
new file mode 100644
index 0000000..20b7144
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/ColumnsBuilder.java
@@ -0,0 +1,86 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.query;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReference;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferences.ColumnReferenceInfo;
+import org.apache.polygene.library.sql.generator.grammar.query.QuerySpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.SelectColumnClause;
+
+/**
+ * This builder builds the columns for {@code SELECT} statement.
+ *
+ * @author Stanislav Muhametsin
+ * @see SelectColumnClause
+ * @see QuerySpecification
+ * @see ColumnReference
+ */
+public interface ColumnsBuilder
+    extends AbstractBuilder<SelectColumnClause>
+{
+    /**
+     * Adds columns without aliases to this {@code SELECT} statement.
+     *
+     * @param columns Columns without aliases to add to this {@code SELECT} statement.
+     * @return This builder.
+     */
+    ColumnsBuilder addUnnamedColumns( ColumnReference... columns );
+
+    /**
+     * Add columns with aliases to this {@code SELECT} statement.
+     *
+     * @param namedColumns Columns with aliases to add to this {@code SELECT} statement.
+     */
+    ColumnsBuilder addNamedColumns( ColumnReferenceInfo... namedColumns );
+
+    /**
+     * Sets the set quantifier ({@code ALL} or {@code DISTINCT}) for this {@code SELECT} statement.
+     *
+     * @param newSetQuantifier The new set quantifier.
+     * @return This builder.
+     * @see SetQuantifier
+     */
+    ColumnsBuilder setSetQuantifier( SetQuantifier newSetQuantifier );
+
+    /**
+     * Marks that all columns should be selected ({@literal SELECT} *). This will empty a list of columns to select.
+     *
+     * @return This builder.
+     */
+    ColumnsBuilder selectAll();
+
+    /**
+     * Returns the columns of this {@code SELECT} statement. It returns empty by default, or after calling
+     * {@link #selectAll()} method.
+     *
+     * @return A list of columns of this {@code SELECT} statement. Might be empty.
+     */
+    List<ColumnReferenceInfo> getColumns();
+
+    /**
+     * Returns the set quantifier ({@code ALL} or {@code DISTINCT}) of this {@code SELECT} statement.
+     *
+     * @return The set quantifier of this {@code SELECT} statement.
+     */
+    SetQuantifier getSetQuantifier();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/FromBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/FromBuilder.java
new file mode 100644
index 0000000..cbed912
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/FromBuilder.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.query;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.query.FromClause;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReference;
+
+/**
+ * The builder that builds the {@code FROM} clause in SQL {@code SELECT} query. It treats {@code FROM} clause as a list
+ * of {@link TableReference}s, and acts as aggregator for {@link TableReferenceBuilder}s.
+ *
+ * @author Stanislav Muhametsin
+ * @see TableReference
+ * @see TableReferenceBuilder
+ */
+public interface FromBuilder
+    extends AbstractBuilder<FromClause>
+{
+
+    /**
+     * Adds table reference builders to this {@code FROM} clause. When {@link #createExpression()} method will be called
+     * on this builder, it will build all table references from builders that were added through this method.
+     *
+     * @param tableRefs Table reference builders to add to this {@code FROM} clause.
+     * @return This builder.
+     */
+    FromBuilder addTableReferences( TableReferenceBuilder... tableRefs );
+
+    /**
+     * Returns a list of table reference builders in this builder.
+     *
+     * @return A list of table reference builders in this builder. Might be empty.
+     */
+    List<TableReferenceBuilder> getTableReferences();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/GroupByBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/GroupByBuilder.java
new file mode 100644
index 0000000..102d379
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/GroupByBuilder.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.polygene.library.sql.generator.grammar.builders.query;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.query.GroupByClause;
+import org.apache.polygene.library.sql.generator.grammar.query.GroupingElement;
+
+/**
+ * The builder that builds the {@code GROUP BY} clause in SQL {@code SELECT} query.
+ *
+ * @author Stanislav Muhametsin
+ * @see GroupByClause
+ * @see GroupingElement
+ */
+public interface GroupByBuilder
+    extends AbstractBuilder<GroupByClause>
+{
+
+    /**
+     * Adds grouping elements to this {@code GROUP BY} clause.
+     *
+     * @param elements The grouping elements for this {@code GROUP BY} clause.
+     * @return This builder.
+     */
+    GroupByBuilder addGroupingElements( GroupingElement... elements );
+
+    /**
+     * Returns the list of added grouping elements.
+     *
+     * @return The list of added grouping elements.
+     */
+    List<GroupingElement> getGroupingElements();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/OrderByBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/OrderByBuilder.java
new file mode 100644
index 0000000..49cbaa3
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/OrderByBuilder.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.polygene.library.sql.generator.grammar.builders.query;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.query.OrderByClause;
+import org.apache.polygene.library.sql.generator.grammar.query.SortSpecification;
+
+/**
+ * The builder that builds the {@code ORDER BY} clause in SQL {@code SELECT} query.
+ *
+ * @author Stanislav Muhametsin
+ * @see OrderByClause
+ * @see SortSpecification
+ */
+public interface OrderByBuilder
+    extends AbstractBuilder<OrderByClause>
+{
+
+    /**
+     * Adds sort specifications to this {@code ORDER BY} clause.
+     *
+     * @param specs The sort specifications for this {@code ORDER BY} clause.
+     * @return This builder.
+     */
+    OrderByBuilder addSortSpecs( SortSpecification... specs );
+
+    /**
+     * Returns the list of added sort specifications.
+     *
+     * @return The added sort specifications.
+     */
+    List<SortSpecification> getSortSpecs();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/QueryBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/QueryBuilder.java
new file mode 100644
index 0000000..15dde25
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/QueryBuilder.java
@@ -0,0 +1,212 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.query;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+import org.apache.polygene.library.sql.generator.grammar.query.CorrespondingSpec;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBody;
+import org.apache.polygene.library.sql.generator.grammar.query.QuerySpecification;
+
+/**
+ * The builder that builds the SQL queries having {@code UNION}, {@code INTERSECT}, or {@code EXCEPT} between the
+ * {@code SELECT} statements.
+ *
+ * @author Stanislav Muhametsin
+ * @see QueryExpressionBody
+ * @see QuerySpecification
+ * @see QuerySpecificationBuilder
+ * @see CorrespondingSpec
+ */
+public interface QueryBuilder
+    extends AbstractBuilder<QueryExpressionBody>
+{
+    /**
+     * <p>
+     * Adds {@code UNION} between current query and the given query. Then makes resulting query the current query.
+     * </p>
+     * <p>
+     * This is equivalent on calling {@link #union(SetQuantifier, QueryExpressionBody)} and giving
+     * {@link SetQuantifier#DISTINCT} as first parameter.
+     * </p>
+     *
+     * @param another The query to perform {@code UNION} with.
+     * @return This builder.
+     */
+    QueryBuilder union( QueryExpressionBody another );
+
+    /**
+     * <p>
+     * Adds {@code UNION <setQuantifier>} between current query and the given query. Then makes resulting query the
+     * current query.
+     * </p>
+     * <p>
+     * This is equivalent on calling {@link #union(SetQuantifier, CorrespondingSpec, QueryExpressionBody)} and giving
+     * {@code null} as second parameter.
+     * </p>
+     *
+     * @param setQuantifier The set quantifier for this union.
+     * @param another       The query to perform {@code UNION} with.
+     * @return This builder.
+     */
+    QueryBuilder union( SetQuantifier setQuantifier, QueryExpressionBody another );
+
+    /**
+     * <p>
+     * Adds {@code UNION <correspondingSpec>} between current query and the given query. Then makes resulting query the
+     * current query.
+     * </p>
+     * <p>
+     * This is equivalent on calling {@link #union(SetQuantifier, CorrespondingSpec, QueryExpressionBody)} and giving
+     * {@link SetQuantifier#DISTINCT} as first parameter.
+     * </p>
+     *
+     * @param correspondingSpec The column correspondence specification.
+     * @param another           The query to perform {@code UNION} with.
+     * @return This builder.
+     */
+    QueryBuilder union( CorrespondingSpec correspondingSpec, QueryExpressionBody another );
+
+    /**
+     * Adds {@code UNION <setQuantifier> <correspondingSpec>} between current query and the given query. Then makes
+     * resulting query the current query.
+     *
+     * @param setQuantifier     The set quantifier for this union.
+     * @param correspondingSpec The column correspondence specification. May be {@code null}.
+     * @param another           The query to perform {@code UNION} with.
+     * @return This builder.
+     */
+    QueryBuilder union( SetQuantifier setQuantifier, CorrespondingSpec correspondingSpec,
+                        QueryExpressionBody another );
+
+    /**
+     * <p>
+     * Adds {@code INTERSECT} between current query and the given query. Then makes resulting query the current query.
+     * </p>
+     * <p>
+     * This is equivalent on calling {@link #intersect(SetQuantifier, QueryExpressionBody)} and giving
+     * {@link SetQuantifier#DISTINCT} as first parameter.
+     * </p>
+     *
+     * @param another The query to perform {@code INTERSECT} with.
+     * @return This builder.
+     */
+    QueryBuilder intersect( QueryExpressionBody another );
+
+    /**
+     * <p>
+     * Adds {@code INTERSECT <setQuantifier>} between current query and the given query. Then makes resulting query the
+     * current query.
+     * </p>
+     * <p>
+     * This is equivalent on calling {@link #intersect(SetQuantifier, CorrespondingSpec, QueryExpressionBody)} and
+     * giving {@code null} as second parameter.
+     * </p>
+     *
+     * @param setQuantifier The set quantifier for this union.
+     * @param another       The query to perform {@code INTERSECT} with.
+     * @return This builder.
+     */
+    QueryBuilder intersect( SetQuantifier setQuantifier, QueryExpressionBody another );
+
+    /**
+     * <p>
+     * Adds {@code INTERSECT <correspondingSpec>} between current query and the given query. Then makes resulting query
+     * the current query.
+     * </p>
+     * <p>
+     * This is equivalent on calling {@link #intersect(SetQuantifier, CorrespondingSpec, QueryExpressionBody)} and
+     * giving {@link SetQuantifier#DISTINCT} as first parameter.
+     * </p>
+     *
+     * @param correspondingSpec The column correspondence specification.
+     * @param another           The query to perform {@code INTERSECT} with.
+     * @return This builder.
+     */
+    QueryBuilder intersect( CorrespondingSpec correspondingSpec, QueryExpressionBody another );
+
+    /**
+     * Adds {@code INTERSECT <setQuantifier> <correspondingSpec>} between current query and the given query. Then makes
+     * resulting query the current query.
+     *
+     * @param setQuantifier     The set quantifier for this union.
+     * @param correspondingSpec The column correspondence specification. May be {@code null}.
+     * @param another           The query to perform {@code INTERSECT} with.
+     * @return This builder.
+     */
+    QueryBuilder intersect( SetQuantifier setQuantifier, CorrespondingSpec correspondingSpec,
+                            QueryExpressionBody another );
+
+    /**
+     * <p>
+     * Adds {@code EXCEPT} between current query and the given query. Then makes resulting query the current query.
+     * </p>
+     * <p>
+     * This is equivalent on calling {@link #except(SetQuantifier, QueryExpressionBody)} and giving
+     * {@link SetQuantifier#DISTINCT} as first parameter.
+     * </p>
+     *
+     * @param another The query to perform {@code EXCEPT} with.
+     * @return This builder.
+     */
+    QueryBuilder except( SetQuantifier setQuantifier, CorrespondingSpec correspondingSpec,
+                         QueryExpressionBody another );
+
+    /**
+     * <p>
+     * Adds {@code EXCEPT <setQuantifier>} between current query and the given query. Then makes resulting query the
+     * current query.
+     * </p>
+     * <p>
+     * This is equivalent on calling {@link #except(SetQuantifier, CorrespondingSpec, QueryExpressionBody)} and giving
+     * {@code null} as second parameter.
+     * </p>
+     *
+     * @param another       The query to perform {@code EXCEPT} with.
+     * @return This builder.
+     */
+    QueryBuilder except( QueryExpressionBody another );
+
+    /**
+     * <p>
+     * Adds {@code EXCEPT <correspondingSpec>} between current query and the given query. Then makes resulting query the
+     * current query.
+     * </p>
+     * <p>
+     * This is equivalent on calling {@link #except(SetQuantifier, CorrespondingSpec, QueryExpressionBody)} and giving
+     * {@link SetQuantifier#DISTINCT} as first parameter.
+     * </p>
+     *
+     * @param setQuantifier The set quantifier for this union.
+     * @param another           The query to perform {@code EXCEPT} with.
+     * @return This builder.
+     */
+    QueryBuilder except( SetQuantifier setQuantifier, QueryExpressionBody another );
+
+    /**
+     * Adds {@code EXCEPT <setQuantifier> <correspondingSpec>} between current query and the given query. Then makes
+     * resulting query the current query.
+     *
+     * @param correspondingSpec The column correspondence specification. May be {@code null}.
+     * @param another           The query to perform {@code EXCEPT} with.
+     * @return This builder.
+     */
+    QueryBuilder except( CorrespondingSpec correspondingSpec, QueryExpressionBody another );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/QuerySpecificationBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/QuerySpecificationBuilder.java
new file mode 100644
index 0000000..3be9d71
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/QuerySpecificationBuilder.java
@@ -0,0 +1,140 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.query;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.booleans.BooleanBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.QuerySpecification;
+
+/**
+ * This builder builds a single {@code SELECT} query. It acts as an aggregator for {@link ColumnsBuilder} for columns in
+ * {@code SELECT}, {@link FromBuilder} for tables in {@code FROM} clause, {@link BooleanBuilder} for search condition in
+ * {@code WHERE} clause, {@link GroupByBuilder} for {@code GROUP BY} clause, another {@link BooleanBuilder} for grouping
+ * conditions in {@code HAVING} clause, and finally {@link OrderByBuilder} for {@code ORDER BY} clause.
+ *
+ * @author Stanislav Muhametsin
+ * @see QuerySpecification
+ */
+public interface QuerySpecificationBuilder
+    extends AbstractQueryBuilder<QuerySpecification>
+{
+
+    /**
+     * Gets the builder for columns in this {@code SELECT} statement.
+     *
+     * @return The builder for columns in this {@code SELECT} statement.
+     */
+    ColumnsBuilder getSelect();
+
+    /**
+     * Gets the builder for {@code FROM} clause of this {@code SELECT} statement.
+     *
+     * @return The builder for {@code FROM} clause of this {@code SELECT} statement.
+     */
+    FromBuilder getFrom();
+
+    /**
+     * Gets the builder for search condition in {@code WHERE} clause of this {@code SELECT} statement.
+     *
+     * @return The builder for search condition in {@code WHERE} clause of this {@code SELECT} statement.
+     */
+    BooleanBuilder getWhere();
+
+    /**
+     * Gets the builder for {@code GROUP BY} clause of this {@code SELECT} statement.
+     *
+     * @return The builder for {@code GROUP BY} clause of this {@code SELECT} statement.
+     */
+    GroupByBuilder getGroupBy();
+
+    /**
+     * Gets the builder for grouping condition in {@code HAVING} clause of this {@code SELECT} statement.
+     *
+     * @return The builder for grouping condition in {@code HAVING} clause of this {@code SELECT} statement.
+     */
+    BooleanBuilder getHaving();
+
+    /**
+     * Gets the builder for {@code ORDER BY} clause of this {@code SELECT} statement.
+     *
+     * @return The builder for {@code ORDER BY} clause of this {@code SELECT} statement.
+     */
+    OrderByBuilder getOrderBy();
+
+    /**
+     * Checks that all selected columns are in {@code GROUP BY} clause. If they are not, it adds them as last columns of
+     * {@code GROUP BY} clause.
+     *
+     * @return This builder.
+     */
+    QuerySpecificationBuilder trimGroupBy();
+
+    /**
+     * Sets the builder for columns in {@code SELECT} statement.
+     *
+     * @return This builder.
+     */
+    QuerySpecificationBuilder setSelect( ColumnsBuilder builder );
+
+    /**
+     * Sets the builder for {@code FROM} clause of this {@code SELECT} statement.
+     *
+     * @return This builder.
+     */
+    QuerySpecificationBuilder setFrom( FromBuilder builder );
+
+    /**
+     * Sets the builder for search condition in {@code WHERE} clause of this {@code SELECT} statement.
+     *
+     * @return This builder.
+     */
+    QuerySpecificationBuilder setWhere( BooleanBuilder builder );
+
+    /**
+     * Sets the builder for {@code GROUP BY} clause of this {@code SELECT} statement.
+     *
+     * @return This builder.
+     */
+    QuerySpecificationBuilder setGroupBy( GroupByBuilder builder );
+
+    /**
+     * Sets the builder for grouping condition in {@code HAVING} clause of this {@code SELECT} statement.
+     *
+     * @return This builder.
+     */
+    QuerySpecificationBuilder setHaving( BooleanBuilder builder );
+
+    /**
+     * Sets the builder for {@code ORDER BY} clause of this {@code SELECT} statement.
+     *
+     * @return This builder.
+     */
+    QuerySpecificationBuilder setOrderBy( OrderByBuilder builder );
+
+    QuerySpecificationBuilder limit();
+
+    QuerySpecificationBuilder limit( Integer max );
+
+    QuerySpecificationBuilder limit( NonBooleanExpression max );
+
+    QuerySpecificationBuilder offset( Integer skip );
+
+    QuerySpecificationBuilder offset( NonBooleanExpression skip );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/SimpleQueryBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/SimpleQueryBuilder.java
new file mode 100644
index 0000000..e3907dd
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/SimpleQueryBuilder.java
@@ -0,0 +1,127 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.query;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.common.TableName;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.factories.QueryFactory;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+
+/**
+ * This is builder to quickly create simple queries, without the generic and not-so-easy-to-use methods of traditional
+ * {@link QuerySpecificationBuilder} + {@link QueryFactory} style. Using this builder is generally not thread-safe.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SimpleQueryBuilder
+    extends AbstractQueryBuilder<QueryExpression>
+{
+
+    /**
+     * Adds the specified columns to the {@code SELECT} list.
+     *
+     * @param columnNames The names of the columns.
+     * @return This builder.
+     */
+    SimpleQueryBuilder select( String... columnNames );
+
+    /**
+     * Adds the specified column expressions to the {@code SELECT} list.
+     *
+     * @param expressions The value expressions for columns.
+     * @return This builder.
+     */
+    SimpleQueryBuilder select( ValueExpression... expressions );
+
+    /**
+     * Selects all columns ({@code SELECT *}).
+     *
+     * @return This builder.
+     */
+    SimpleQueryBuilder selectAllColumns();
+
+    /**
+     * Adds alias to the most recently added column.
+     *
+     * @param columnAlias The alias for most recently added column;
+     * @return This builder.
+     */
+    SimpleQueryBuilder as( String columnAlias );
+
+    /**
+     * Adds table names for {@code FROM} clause of this query.
+     *
+     * @param tableNames The table names to add.
+     * @return This builder.
+     */
+    SimpleQueryBuilder from( TableName... tableNames );
+
+    /**
+     * Sets the search condition ({@code WHERE} clause) for this query.
+     *
+     * @param searchCondition The search condition for this query.
+     * @return This builder.
+     */
+    SimpleQueryBuilder where( BooleanExpression searchCondition );
+
+    /**
+     * Adds {@code GROUP BY} columns for this query.
+     *
+     * @param columns The column names for {@code GROUP BY} clause.
+     * @return This builder.
+     */
+    SimpleQueryBuilder groupBy( String... columns );
+
+    /**
+     * Adds {@code HAVING} grouping condition for this query.
+     *
+     * @param groupingCondition The grouping condition for this query.
+     * @return This builder.
+     */
+    SimpleQueryBuilder having( BooleanExpression groupingCondition );
+
+    /**
+     * Adds {@code ORDER BY} columns for this query, with {@code ASC} as ordering specification.
+     *
+     * @param columns The column names for {@code ORDER BY}.
+     * @return This builder.
+     */
+    SimpleQueryBuilder orderByAsc( String... columns );
+
+    /**
+     * Adds {@code ORDER BY} columns for this query, with {@code DESC} as ordering specification.
+     *
+     * @param columns The column names for {@code ORDER BY}.
+     * @return This builder.
+     */
+    SimpleQueryBuilder orderByDesc( String... columns );
+
+    SimpleQueryBuilder limit();
+
+    SimpleQueryBuilder limit( Integer max );
+
+    SimpleQueryBuilder limit( NonBooleanExpression max );
+
+    SimpleQueryBuilder offset( Integer skip );
+
+    SimpleQueryBuilder offset( NonBooleanExpression skip );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/TableReferenceBuilder.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/TableReferenceBuilder.java
new file mode 100644
index 0000000..1365809
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/TableReferenceBuilder.java
@@ -0,0 +1,76 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.builders.query;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.AbstractBuilder;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReference;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinType;
+
+/**
+ * The builder to build joined tables. A joined table contains 0 or more joins.
+ *
+ * @author Stanislav Muhametsin
+ * @see TableReference
+ */
+public interface TableReferenceBuilder
+    extends AbstractBuilder<TableReference>
+{
+    /**
+     * Adds a qualified join ({@code JOIN}) to whatever current table of builder, and overwrites the current table with
+     * the result.
+     *
+     * @param joinType The join type.
+     * @param right    The table on the right side of the join.
+     * @param joinSpec The join specification.
+     * @return This builder
+     * @see JoinType
+     * @see JoinSpecification
+     */
+    TableReferenceBuilder addQualifiedJoin( JoinType joinType, TableReference right, JoinSpecification joinSpec );
+
+    /**
+     * Adds a cross join ({@code CROSS JOIN}) to whatever current table of builder, and overwrites the current table
+     * with the result.
+     *
+     * @param right The table on the right side of the join.
+     * @return This builder.
+     */
+    TableReferenceBuilder addCrossJoin( TableReference right );
+
+    /**
+     * Adds a natural join ({@code NATURAL JOIN}) to whatever current table of builder, and overwrites the current table
+     * with the result.
+     *
+     * @param joinType The join type.
+     * @param right    The table on the right side of the join.
+     * @return This builder.
+     */
+    TableReferenceBuilder addNaturalJoin( JoinType joinType, TableReference right );
+
+    /**
+     * Adds an union join ({@code UNION JOIN}) to whatever current table of builder, and overwrites the current table
+     * with the result.
+     *
+     * @param right The table on the right side of the join.
+     * @return This builder
+     */
+    TableReferenceBuilder addUnionJoin( TableReference right );
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/package-info.java
new file mode 100644
index 0000000..a3d21fe
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/builders/query/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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 to hold builders for SQL queries ({@code SELECT} -statements).
+ */
+package org.apache.polygene.library.sql.generator.grammar.builders.query;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/ColumnNameList.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/ColumnNameList.java
new file mode 100644
index 0000000..53b0b12
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/ColumnNameList.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This interface presents a non-empty list of plain-text column names.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface ColumnNameList extends Typeable<ColumnNameList>
+{
+    /**
+     * Returns the list of column names. This list will be always non-empty.
+     *
+     * @return The non-empty list of column names.
+     */
+    List<String> getColumnNames();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/NonBooleanExpression.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/NonBooleanExpression.java
new file mode 100644
index 0000000..4ecc86b
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/NonBooleanExpression.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common;
+
+/**
+ * A common interface for all expressions, which return non-boolean value.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface NonBooleanExpression
+    extends ValueExpression
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SQLConstants.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SQLConstants.java
new file mode 100644
index 0000000..57f1402
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SQLConstants.java
@@ -0,0 +1,82 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common;
+
+/**
+ * A container for common textual constants of SQL language.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SQLConstants
+{
+    String SELECT = "SELECT";
+
+    String FROM = "FROM";
+
+    String WHERE = "WHERE";
+
+    String GROUP_BY = "GROUP BY";
+
+    String HAVING = "HAVING";
+
+    String ORDER_BY = "ORDER BY";
+
+    String TABLE_COLUMN_SEPARATOR = ".";
+
+    String SCHEMA_TABLE_SEPARATOR = ".";
+
+    String TOKEN_SEPARATOR = " ";
+
+    String AND = "AND";
+
+    String OR = "OR";
+
+    String NOT = "NOT";
+
+    String ASTERISK = "*";
+
+    String COMMA = ",";
+
+    String PERIOD = ".";
+
+    String QUESTION_MARK = "?";
+
+    String OPEN_PARENTHESIS = "(";
+
+    String CLOSE_PARENTHESIS = ")";
+
+    String ALIAS_DEFINER = "AS";
+
+    String NEWLINE = "\n";
+
+    String NULL = "NULL";
+
+    String IS = "IS";
+
+    String CREATE = "CREATE";
+
+    String OFFSET_PREFIX = "OFFSET";
+
+    String OFFSET_POSTFIX = "ROWS";
+
+    String LIMIT_PREFIX = "FETCH FIRST";
+
+    String LIMIT_POSTFIX = "ROWS ONLY";
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SQLFunctions.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SQLFunctions.java
new file mode 100644
index 0000000..06a644f
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SQLFunctions.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common;
+
+/**
+ * A container for textual names of default SQL functions.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SQLFunctions
+{
+
+    String AVG = "AVG";
+
+    String MAX = "MAX";
+
+    String MIN = "MIN";
+
+    String SUM = "SUM";
+
+    String EVERY = "EVERY";
+
+    String ANY = "ANY";
+
+    String COUNT = "COUNT";
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SQLStatement.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SQLStatement.java
new file mode 100644
index 0000000..d9120c9
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SQLStatement.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common;
+
+import org.apache.polygene.library.sql.generator.grammar.modification.DeleteStatement;
+import org.apache.polygene.library.sql.generator.grammar.modification.InsertStatement;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateStatement;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+
+/**
+ * A single SQL statement, which is to be sent to database.
+ *
+ * @author Stanislav Muhametsin
+ * @see QueryExpression
+ * @see DeleteStatement
+ * @see UpdateStatement
+ * @see InsertStatement
+ */
+public interface SQLStatement
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SchemaDefinitionStatement.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SchemaDefinitionStatement.java
new file mode 100644
index 0000000..23ecde5
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SchemaDefinitionStatement.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common;
+
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableDefinition;
+
+/**
+ * This is a common interface for all definition ({@code CREATE}) clauses.
+ *
+ * @author Stanislav Muhametsin
+ * @see TableDefinition
+ */
+public interface SchemaDefinitionStatement
+    extends SchemaStatement
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SchemaManipulationStatement.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SchemaManipulationStatement.java
new file mode 100644
index 0000000..d27c4c3
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SchemaManipulationStatement.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public interface SchemaManipulationStatement
+    extends SchemaStatement
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SchemaStatement.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SchemaStatement.java
new file mode 100644
index 0000000..10560b8
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SchemaStatement.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public interface SchemaStatement
+    extends Typeable<SchemaStatement>, SQLStatement
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SetQuantifier.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SetQuantifier.java
new file mode 100644
index 0000000..524bc61
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/SetQuantifier.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common;
+
+/**
+ * Set quantifer, can be either {@link #ALL} or {@link #DISTINCT}.
+ *
+ * @author Stanislav Muhametsin
+ */
+public final class SetQuantifier
+{
+
+    /**
+     * Set quantifier for {@code DISTINCT} element.
+     */
+    public static final SetQuantifier DISTINCT = new SetQuantifier();
+
+    /**
+     * Set quantifier for {@code ALL} element.
+     */
+    public static final SetQuantifier ALL = new SetQuantifier();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/TableName.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/TableName.java
new file mode 100644
index 0000000..8cbd2cb
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/TableName.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This is common interface for table names. Table name may be either {@link TableNameDirect} or
+ * {@link TableNameFunction}.
+ *
+ * @author 2011 Stanislav Muhametsin
+ */
+public interface TableName
+    extends Typeable<TableName>
+{
+    /**
+     * Gets the schema name. Returns {@code null} if this is not schema-qualified table name.
+     *
+     * @return Schema name of the schema-qualified table name, or {@code null} if this is not a schema-qualified table
+     * name.
+     */
+    String getSchemaName();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/TableNameDirect.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/TableNameDirect.java
new file mode 100644
index 0000000..7936c7a
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/TableNameDirect.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common;
+
+/**
+ * A direct table name may be just table name, or schema-qualified table name.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface TableNameDirect
+    extends TableName
+{
+
+    /**
+     * Gets name of the table. Returns always non-{@code null}.
+     *
+     * @return The name of the table. Always non-{@code null}.
+     */
+    String getTableName();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/TableNameFunction.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/TableNameFunction.java
new file mode 100644
index 0000000..2e38392
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/TableNameFunction.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common;
+
+import org.apache.polygene.library.sql.generator.grammar.literals.SQLFunctionLiteral;
+
+/**
+ * A table name function serves as a function call when selecting data.
+ *
+ * @author 2011 Stanislav Muhametsin
+ */
+public interface TableNameFunction
+    extends TableName
+{
+    /**
+     * Returns the function to call.
+     *
+     * @return The function to call.
+     */
+    SQLFunctionLiteral getFunction();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/ValueExpression.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/ValueExpression.java
new file mode 100644
index 0000000..de07261
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/ValueExpression.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+
+/**
+ * A common interface for {@link BooleanExpression} and {@link NonBooleanExpression}.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface ValueExpression
+    extends Typeable<ValueExpression>
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/BigInt.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/BigInt.java
new file mode 100644
index 0000000..a82b1f4
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/BigInt.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common.datatypes;
+
+/**
+ * This class represents the {@code BIGINT} type (typically 64-bit integer).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface BigInt
+    extends SQLDataType
+{
+
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/Decimal.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/Decimal.java
new file mode 100644
index 0000000..d4b441e
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/Decimal.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.polygene.library.sql.generator.grammar.common.datatypes;
+
+/**
+ * <p>
+ * This class represents the {@code DECIMAL} data type, sometimes abbreviated as {@code DEC}. The site
+ * http://intelligent-enterprise.informationweek.com/000626/celko.jhtml explains difference between {@code NUMERIC} and
+ * {@code DECIMAL}:
+ * </p>
+ * <p>
+ * The difference between DECIMAL(s,p) and NUMERIC(s,p) is subtle in the SQL-92 Standard -- DECIMAL(s,p) must be exactly
+ * as precise as declared, while NUMERIC(s,p) must be at least as precise as declared.
+ * </p>
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface Decimal
+    extends SQLDataType, ParametrizableDataType
+{
+
+    /**
+     * Returns the precision (first integer) for this {@code DECIMAL}.
+     *
+     * @return The precision for this {@code DECIMAL}.
+     */
+    Integer getPrecision();
+
+    /**
+     * Returns the scale (second integer) for this {@code DECIMAL}.
+     *
+     * @return The precision for this {@code DECIMAL}.
+     */
+    Integer getScale();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/DoublePrecision.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/DoublePrecision.java
new file mode 100644
index 0000000..431b75c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/DoublePrecision.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common.datatypes;
+
+/**
+ * This class represents {@code DOUBLE PRECISION} data type.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface DoublePrecision
+    extends SQLDataType
+{
+
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/IntervalDataType.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/IntervalDataType.java
new file mode 100644
index 0000000..fb9b93e
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/IntervalDataType.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common.datatypes;
+
+/**
+ * This class contains all the types for fields in {@code INTERVAL} data type.
+ *
+ * @author Stanislav Muhametsin
+ */
+public final class IntervalDataType
+{
+    public static final IntervalDataType YEAR = new IntervalDataType();
+
+    public static final IntervalDataType MONTH = new IntervalDataType();
+
+    public static final IntervalDataType DAY = new IntervalDataType();
+
+    public static final IntervalDataType HOUR = new IntervalDataType();
+
+    public static final IntervalDataType MINUTE = new IntervalDataType();
+
+    public static final IntervalDataType SECOND = new IntervalDataType();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/Numeric.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/Numeric.java
new file mode 100644
index 0000000..842e1be
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/Numeric.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.polygene.library.sql.generator.grammar.common.datatypes;
+
+/**
+ * <p>
+ * This class represents the {@code NUMERIC} type. The site
+ * http://intelligent-enterprise.informationweek.com/000626/celko.jhtml explains difference between {@code NUMERIC} and
+ * {@code DECIMAL}:
+ * </p>
+ * <p>
+ * The difference between DECIMAL(s,p) and NUMERIC(s,p) is subtle in the SQL-92 Standard -- DECIMAL(s,p) must be exactly
+ * as precise as declared, while NUMERIC(s,p) must be at least as precise as declared.
+ * </p>
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface Numeric
+    extends SQLDataType, ParametrizableDataType
+{
+
+    /**
+     * Returns the precision (first integer) for this {@code NUMERIC}.
+     *
+     * @return The precision for this {@code NUMERIC}.
+     */
+    Integer getPrecision();
+
+    /**
+     * Returns the scale (second integer) for this {@code NUMERIC}.
+     *
+     * @return The precision for this {@code NUMERIC}.
+     */
+    Integer getScale();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/ParametrizableDataType.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/ParametrizableDataType.java
new file mode 100644
index 0000000..b056181
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/ParametrizableDataType.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common.datatypes;
+
+/**
+ * This is marker interface for SQL data types which may be parametrized (like, {@code DECIMAL} or {@code VARCHAR}).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface ParametrizableDataType
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/Real.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/Real.java
new file mode 100644
index 0000000..3a73cae
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/Real.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common.datatypes;
+
+/**
+ * This class represents the {@code REAL} data type.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface Real
+    extends SQLDataType
+{
+
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLBoolean.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLBoolean.java
new file mode 100644
index 0000000..870aff6
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLBoolean.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common.datatypes;
+
+/**
+ * This class represents the {@code BOOLEAN} type.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SQLBoolean
+    extends SQLDataType
+{
+
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLChar.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLChar.java
new file mode 100644
index 0000000..82ec6db
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLChar.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common.datatypes;
+
+/**
+ * This class represents {@code CHARACTER} and {@code CHARACTER VARYING} data types, typically abbreviated as
+ * {@code CHAR} and {@code VARCHAR}, respectively.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SQLChar
+    extends SQLDataType, ParametrizableDataType
+{
+
+    /**
+     * Returns {@code true} if this is {@code CHARACTER VARYING}; {@code false otherwise}.
+     *
+     * @return {@code true} if this is {@code CHARACTER VARYING}; {@code false otherwise}.
+     */
+    Boolean isVarying();
+
+    /**
+     * Returns the length specification for this {@code CHARACTER} or {@code CHARACTER VARYING}. Returns {@code null} if
+     * none specified.
+     *
+     * @return The length for this {@code CHARACTER} or {@code CHARACTER VARYING}.
+     */
+    Integer getLength();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLDataType.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLDataType.java
new file mode 100644
index 0000000..9df446a
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLDataType.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common.datatypes;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This is common interface for all SQL data types. The data types provided in this project cover most of of SQL
+ * predefined types, however each vendor may extend these with their own custom types.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SQLDataType
+    extends Typeable<SQLDataType>
+{
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLDate.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLDate.java
new file mode 100644
index 0000000..eae5f4d
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLDate.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common.datatypes;
+
+/**
+ * This class represents the {@code DATE} data type.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SQLDate
+    extends SQLDataType
+{
+
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLFloat.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLFloat.java
new file mode 100644
index 0000000..2b89cc1
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLFloat.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common.datatypes;
+
+/**
+ * This class represents the {@code FLOAT} type.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SQLFloat
+    extends SQLDataType, ParametrizableDataType
+{
+
+    /**
+     * Returns the precision for this {@code FLOAT}.
+     *
+     * @return The precision for this {@code FLOAT}.
+     */
+    Integer getPrecision();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLInteger.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLInteger.java
new file mode 100644
index 0000000..951f5c0
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLInteger.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common.datatypes;
+
+/**
+ * This class represents the {@code INTEGER} type, sometimes abbreviated as {@code INT} (typically 32-bit integer).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SQLInteger
+    extends SQLDataType
+{
+
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLInterval.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLInterval.java
new file mode 100644
index 0000000..5f35b90
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLInterval.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common.datatypes;
+
+/**
+ * This class represents the {@code INTEGER} type, sometimes abbreviated as {@code INT} (typically 32-bit integer).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SQLInterval
+    extends SQLDataType, ParametrizableDataType
+{
+
+    /**
+     * Returns the start field type for this {@code INTERVAL}.
+     *
+     * @return The start field type for this {@code INTERVAL}.
+     */
+    IntervalDataType getStartField();
+
+    /**
+     * Return the start field precision for this {@code INTERVAL}. May be {@code null} if none specified.
+     *
+     * @return The start field precision for this {@code INTERVAL}.
+     */
+    Integer getStartFieldPrecision();
+
+    /**
+     * Returns the end field precision for this {@code INTERVAL}. Will always be {@code null} for single datetime field
+     * intervals.
+     *
+     * @return The end field precision for this {@code INTERVAL}.
+     */
+    IntervalDataType getEndField();
+
+    /**
+     * Returns the fraction seconds precision for this {@code INTERVAL}. Will always be {@code null} if the end field
+     * type is not {@link IntervalDataType#SECOND}, or if this is single datetime field interval, and its start type is
+     * not {@link IntervalDataType#SECOND}.
+     *
+     * @return The fraction seconds precision for this {@code INTERVAL}.
+     */
+    Integer getSecondFracs();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLTime.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLTime.java
new file mode 100644
index 0000000..713f211
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLTime.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common.datatypes;
+
+/**
+ * This class represents {@code TIME} data type.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SQLTime
+    extends SQLDataType, ParametrizableDataType
+{
+
+    /**
+     * Returns the precision for this {@code TIME}. May be {@code null}.
+     *
+     * @return The precision for this {@code TIME}.
+     */
+    Integer getPrecision();
+
+    /**
+     * Returns whether the {@code TIME} should be with time zone. May be {@code null} if no choice specified.
+     */
+    Boolean isWithTimeZone();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLTimeStamp.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLTimeStamp.java
new file mode 100644
index 0000000..fc0bc3d
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SQLTimeStamp.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common.datatypes;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public interface SQLTimeStamp
+    extends SQLDataType, ParametrizableDataType
+{
+
+    /**
+     * Returns the precision for this {@code TIMESTAMP}. May be {@code null}.
+     *
+     * @return The precision for this {@code TIMESTAMP}.
+     */
+    Integer getPrecision();
+
+    /**
+     * Returns whether the {@code TIMESTAMP} should be with time zone. May be {@code null} if no choice specified.
+     */
+    Boolean isWithTimeZone();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SmallInt.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SmallInt.java
new file mode 100644
index 0000000..2fd83e5
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/SmallInt.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common.datatypes;
+
+/**
+ * This class represents the {@code SMALLINT} type (typically 16-bit integer).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SmallInt
+    extends SQLDataType
+{
+
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/UserDefinedType.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/UserDefinedType.java
new file mode 100644
index 0000000..cded18a
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/UserDefinedType.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common.datatypes;
+
+import org.apache.polygene.library.sql.generator.grammar.factories.DataTypeFactory;
+
+/**
+ * This is a general way of handling any user-created or otherwise custom type. It is advisable to always use the
+ * methods provided by your vendor's data type factory (most likely sub-interface of {@link DataTypeFactory}) instead of
+ * using this interface. However, when data type is dynamically created, it is quite a must to use this type.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface UserDefinedType
+    extends SQLDataType
+{
+
+    String getTextualRepresentation();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/package-info.java
new file mode 100644
index 0000000..08e9d95
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This is the package containing support for (most)pre-defined SQL data types.
+ */
+package org.apache.polygene.library.sql.generator.grammar.common.datatypes;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/pgsql/Text.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/pgsql/Text.java
new file mode 100644
index 0000000..01ef739
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/datatypes/pgsql/Text.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.common.datatypes.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDataType;
+
+/**
+ * This data type represents the {@code TEXT} data type in PostgreSQL.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface Text
+    extends SQLDataType
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/package-info.java
new file mode 100644
index 0000000..1581cb0
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/common/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This package contains interfaces and classes common for most parts of SQL generator.
+ */
+package org.apache.polygene.library.sql.generator.grammar.common;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/schema/SchemaDefinition.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/schema/SchemaDefinition.java
new file mode 100644
index 0000000..ede7a43
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/schema/SchemaDefinition.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.schema;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.common.SchemaDefinitionStatement;
+
+/**
+ * This syntax element represents the {@code CREATE SCHEMA} statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SchemaDefinition
+    extends SchemaDefinitionStatement
+{
+
+    /**
+     * Returns the name of the schema to be created.
+     *
+     * @return The name of the schema to be created.
+     */
+    String getSchemaName();
+
+    /**
+     * Returns the character set for this schema. May be {@code null} if none specified.
+     *
+     * @return The character set for this schema. May be {@code null} if none specified.
+     */
+    String getSchemaCharset();
+
+    /**
+     * Returns any additional elements for this schema. May be empty if none are present.
+     *
+     * @return Any additional elements for this schema. May be empty if none are present.
+     */
+    List<SchemaElement> getSchemaElements();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/schema/SchemaElement.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/schema/SchemaElement.java
new file mode 100644
index 0000000..24a895e
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/schema/SchemaElement.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.schema;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This is a common interface for all definitions that may be present in schema definition.
+ *
+ * @author Stanislav Muhametsin
+ * @see SchemaDefinition
+ */
+public interface SchemaElement
+{
+
+    Typeable<?> asTypeable();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/schema/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/schema/package-info.java
new file mode 100644
index 0000000..6fe4d50
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/schema/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This package contains syntax interfaces for {@code CREATE SCHEMA} statement.
+ */
+package org.apache.polygene.library.sql.generator.grammar.definition.schema;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/AutoGenerationPolicy.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/AutoGenerationPolicy.java
new file mode 100644
index 0000000..44576e7
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/AutoGenerationPolicy.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.polygene.library.sql.generator.grammar.definition.table;
+
+/**
+ * This class defines the policy for auto-generated columns ({@code GENERATED <strategy> AS IDENTITY}.
+ *
+ * @author Stanislav Muhametsin
+ * @see ColumnDefinition
+ */
+public final class AutoGenerationPolicy
+{
+    private final String _policyName;
+
+    public AutoGenerationPolicy( String policyName )
+    {
+        this._policyName = policyName;
+    }
+
+    /**
+     * Represents the {@code GENERATED ALWAYS AS IDENTITY} auto generation policy.
+     */
+    public static final AutoGenerationPolicy ALWAYS = new AutoGenerationPolicy( "ALWAYS" );
+
+    /**
+     * Represents the {@code GENERATED BY DEFAULT AS IDENTITY} auto generation policy.
+     */
+    public static final AutoGenerationPolicy BY_DEFAULT = new AutoGenerationPolicy( "BY DEFAULT" );
+
+    @Override
+    public String toString()
+    {
+        return this._policyName;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/CheckConstraint.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/CheckConstraint.java
new file mode 100644
index 0000000..febef93
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/CheckConstraint.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+
+/**
+ * This syntax element represents the {@code CHECK( ... )} constraint in table definition.
+ *
+ * @author Stanislav Muhametsin
+ * @see TableDefinition
+ */
+public interface CheckConstraint
+    extends TableConstraint
+{
+    BooleanExpression getCheckCondition();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/ColumnDefinition.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/ColumnDefinition.java
new file mode 100644
index 0000000..c13fe32
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/ColumnDefinition.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDataType;
+
+/**
+ * This syntax element represents the column definition of the table definition statement.
+ *
+ * @author Stanislav Muhametsin
+ * @see TableDefinition
+ */
+public interface ColumnDefinition
+    extends TableElement
+{
+
+    /**
+     * Returns the name of this column.
+     *
+     * @return The name of this column.
+     */
+    String getColumnName();
+
+    /**
+     * Returns the data type of this column.
+     *
+     * @return The data type of this column.
+     */
+    SQLDataType getDataType();
+
+    /**
+     * Returns the default clause for this column. May be {@code null} if no default value is defined.
+     *
+     * @return The default clause for this column. May be {@code null} if no default value is defined.
+     */
+    String getDefault();
+
+    /**
+     * Returns {@code true} if this column may have {@code NULL} values, otherwise (when {@code NOT NULL} constraints is
+     * present) returns {@code false}.
+     *
+     * @return {@code true} if this column may have {@code NULL} values; {@code false} otherwise.
+     */
+    Boolean mayBeNull();
+
+    /**
+     * Returns the auto generation policy for this column. May be {@code null} if no auto generation policy exists for
+     * this column.
+     *
+     * @return Auto generation policy for this column, or {@code null} if the column is not auto-generated.
+     */
+    AutoGenerationPolicy getAutoGenerationPolicy();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/ConstraintCharacteristics.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/ConstraintCharacteristics.java
new file mode 100644
index 0000000..90d7638
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/ConstraintCharacteristics.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table;
+
+/**
+ * This enum represents three different policies for checking constraints time. These policies are
+ * {@link #INITIALLY_IMMEDIATE_DEFERRABLE}, {@link #INITIALLY_DEFERRED_DEFERRABLE}, and {@link #NOT_DEFERRABLE}.
+ *
+ * @author Stanislav Muhametsin
+ */
+public final class ConstraintCharacteristics
+{
+    /**
+     * Represents the {@code INITIALLY IMMEDIATE DEFERRABLE} constraint time check.
+     */
+    public static final ConstraintCharacteristics INITIALLY_IMMEDIATE_DEFERRABLE = new ConstraintCharacteristics();
+
+    /**
+     * Represents the {@code INITIALLY DEFERRED DEFERRABLE} constraint time check.
+     */
+    public static final ConstraintCharacteristics INITIALLY_DEFERRED_DEFERRABLE = new ConstraintCharacteristics();
+
+    /**
+     * Represents the {@code [INITIALLY IMMEDIATE] NOT DEFERRABLE} constraint time check.
+     */
+    public static final ConstraintCharacteristics NOT_DEFERRABLE = new ConstraintCharacteristics();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/ForeignKeyConstraint.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/ForeignKeyConstraint.java
new file mode 100644
index 0000000..55acc2c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/ForeignKeyConstraint.java
@@ -0,0 +1,79 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table;
+
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+
+/**
+ * This syntax element represents the {@code FOREIGN KEY(col1, col2, ...) ...} table constraint in table definition.
+ *
+ * @author Stanislav Muhametsin
+ * @see TableConstraint
+ * @see TableDefinition
+ */
+public interface ForeignKeyConstraint
+    extends TableConstraint
+{
+
+    /**
+     * Returns the list of column names in this table.
+     *
+     * @return The list of column names in this table.
+     */
+    ColumnNameList getSourceColumns();
+
+    /**
+     * Returns the name of the table where the columns in this table are referencing to.
+     *
+     * @return The name of the table where the columns in this table are referencing to.
+     */
+    TableNameDirect getTargetTableName();
+
+    /**
+     * Returns the list of column names in target table. Will be {@code null} if none specified.
+     *
+     * @return The list of column names in target table. Will be {@code null} if none specified.
+     */
+    ColumnNameList getTargetColumns();
+
+    /**
+     * Returns the match type for this foreign key. May be {@code null} if no match type is specified.
+     *
+     * @return The match type for this foreign key. May be {@code null} if no match type is specified.
+     */
+    MatchType getMatchType();
+
+    /**
+     * Returns the referential action of updating the rows. May be {@code null} if none specified.
+     *
+     * @return The referential action of updating the rows. May be {@code null} if none specified.
+     * @see ReferentialAction
+     */
+    ReferentialAction getOnUpdate();
+
+    /**
+     * Returns the referential action of deleting the rows. May be {@code null} if none specified.
+     *
+     * @return The referential action of deleting the rows. May be {@code null} if none specified.
+     * @see ReferentialAction
+     */
+    ReferentialAction getOnDelete();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/LikeClause.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/LikeClause.java
new file mode 100644
index 0000000..2ef51e9
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/LikeClause.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table;
+
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+
+/**
+ * This syntax element represents the {@code LIKE
+ * <table name>} clause in table definition.
+ *
+ * @author Stanislav Muhametsin
+ * @see TableDefinition
+ */
+public interface LikeClause
+    extends TableElement
+{
+
+    /**
+     * Returns the name of the table for this {@code LIKE} clause.
+     *
+     * @return The name of the table for this {@code LIKE} clause.
+     */
+    TableNameDirect getTableName();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/MatchType.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/MatchType.java
new file mode 100644
index 0000000..00c8183
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/MatchType.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table;
+
+/**
+ * This enum represents the three different ways of matching foreign keys. May be {@link #FULL}, {@link #PARTIAL}, or
+ * {@link #SIMPLE}.
+ *
+ * @author Stanislav Muhametsin
+ */
+public final class MatchType
+{
+
+    /**
+     * Represents the full match ({@code MATCH FULL}).
+     */
+    public static final MatchType FULL = new MatchType();
+
+    /**
+     * Represents the partial match ({@code MATCH PARTIAL}).
+     */
+    public static final MatchType PARTIAL = new MatchType();
+
+    /**
+     * Represents the simple match ({@code MATCH SIMPLE}).
+     */
+    public static final MatchType SIMPLE = new MatchType();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/ReferentialAction.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/ReferentialAction.java
new file mode 100644
index 0000000..f1f056d
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/ReferentialAction.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table;
+
+/**
+ * This enum represents the five referential actions of SQL. These are {@link #CASCADE}, {@link #SET_NULL},
+ * {@link #SET_DEFAULT}, {@link #RESTRICT}, and {@link #NO_ACTION}.
+ *
+ * @author Stanislav Muhametsin
+ */
+public final class ReferentialAction
+{
+
+    /**
+     * Represents the cascading policy ({@code CASCADE}.
+     */
+    public static final ReferentialAction CASCADE = new ReferentialAction();
+
+    /**
+     * Represents the policy, which sets the value as {@code NULL} ({@code SET NULL}.
+     */
+    public static final ReferentialAction SET_NULL = new ReferentialAction();
+
+    /**
+     * Represents the policy, which sets the value as default ({@code SET DEFAULT}.
+     */
+    public static final ReferentialAction SET_DEFAULT = new ReferentialAction();
+
+    /**
+     * Represents the policy, which checks the integrity <b>before</b> {@code UPDATE} or {@code DELETE} statement, and
+     * the statement will not be executed if it violates integrity.
+     */
+    public static final ReferentialAction RESTRICT = new ReferentialAction();
+
+    /**
+     * Represents the policy, which checks the integrity <b>after</b> {@code UPDATE} or {@code DELETE} statement, and
+     * the statement will not be executed if it violates integrity.
+     */
+    public static final ReferentialAction NO_ACTION = new ReferentialAction();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableCommitAction.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableCommitAction.java
new file mode 100644
index 0000000..c232fa5
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableCommitAction.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table;
+
+/**
+ * This enum is for table commit action ({@code ON COMMIT} ...) in table definition. The commit action may be either
+ * {@link #ON_COMMIT_PRESERVE_ROWS} or {@link #ON_COMMIT_DELETE_ROWS}.
+ *
+ * @author Stanislav Muhametsin
+ * @see TableDefinition
+ */
+public final class TableCommitAction
+{
+
+    /**
+     * The commit action for {@code ON COMMIT PRESERVE ROWS}.
+     */
+    public static final TableCommitAction ON_COMMIT_PRESERVE_ROWS = new TableCommitAction();
+
+    /**
+     * The commit action for {@code ON COMMIT DELETE ROWS}.
+     */
+    public static final TableCommitAction ON_COMMIT_DELETE_ROWS = new TableCommitAction();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableConstraint.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableConstraint.java
new file mode 100644
index 0000000..1f0c30e
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableConstraint.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This is a common interface for all table constraints.
+ *
+ * @author Stanislav Muhametsin
+ * @see TableConstraintDefinition
+ * @see TableDefinition
+ */
+public interface TableConstraint
+    extends Typeable<TableConstraint>
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableConstraintDefinition.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableConstraintDefinition.java
new file mode 100644
index 0000000..b7e6232
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableConstraintDefinition.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table;
+
+/**
+ * This syntax element represents the constraint definition for a table.
+ *
+ * @author Stanislav Muhametsin
+ * @see TableElement
+ * @see TableDefinition
+ * @see TableConstraint
+ */
+public interface TableConstraintDefinition
+    extends TableElement
+{
+
+    /**
+     * Returns the optional name for this constraint. Will be {@code null} if no name defined for this constraint.
+     *
+     * @return The optional name for this constraint. Will be {@code null} if no name defined for this constraint.
+     */
+    String getConstraintName();
+
+    /**
+     * Returns the constraint characteristics for this constraint. Will be {@code null} if no characteristics defined.
+     *
+     * @return The constraint characteristics for this constraint. Will be {@code null} if no characteristics defined.
+     * @see ConstraintCharacteristics
+     */
+    ConstraintCharacteristics getCharacteristics();
+
+    /**
+     * Returns the actual table constraint.
+     *
+     * @return The actual table constraint.
+     */
+    TableConstraint getConstraint();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableContentsSource.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableContentsSource.java
new file mode 100644
index 0000000..d129fc9
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableContentsSource.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This is a common interface for table source in table definition (in most cases, it is a comma-separated list of
+ * column definitions).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface TableContentsSource
+    extends Typeable<TableContentsSource>
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableDefinition.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableDefinition.java
new file mode 100644
index 0000000..37e90e5
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableDefinition.java
@@ -0,0 +1,65 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table;
+
+import org.apache.polygene.library.sql.generator.grammar.common.SchemaDefinitionStatement;
+import org.apache.polygene.library.sql.generator.grammar.common.TableName;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.definition.schema.SchemaElement;
+
+/**
+ * This syntax element represents the table definition ({@code CREATE TABLE }) statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface TableDefinition
+    extends SchemaDefinitionStatement, SchemaElement
+{
+    /**
+     * Returns the table scope for this table. May be {@code null} if no scope defined.
+     *
+     * @return The table scope for this table. May be {@code null} if no scope defined.
+     * @see TableScope
+     */
+    TableScope getTableScope();
+
+    /**
+     * Returns the name for this table.
+     *
+     * @return The name for this table.
+     * @see TableName
+     */
+    TableNameDirect getTableName();
+
+    /**
+     * Returns the commit action for this table. May be {@code null} if no commit action defined.
+     *
+     * @return The commit action for this table. May be {@code null} if no commit action defined.
+     * @see TableCommitAction
+     */
+    TableCommitAction getCommitAction();
+
+    /**
+     * Returns the actual body of this table definition. Usually is a list of column definitions and constraints.
+     *
+     * @return The actual body of this table definition.
+     */
+    TableContentsSource getContents();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableElement.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableElement.java
new file mode 100644
index 0000000..2b54f3e
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableElement.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This is a common interface for table elements in the table element list of table definition. It is usually column
+ * definition.
+ *
+ * @author Stanislav Muhametsin
+ * @see TableDefinition
+ * @see ColumnDefinition
+ */
+public interface TableElement
+    extends Typeable<TableElement>
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableElementList.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableElementList.java
new file mode 100644
index 0000000..5de5dbd
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableElementList.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table;
+
+import java.util.List;
+
+/**
+ * This syntax element represents the table element list in table definition.
+ *
+ * @author Stanislav Muhametsin
+ * @see TableDefinition
+ * @see TableElement
+ */
+public interface TableElementList
+    extends TableContentsSource
+{
+    /**
+     * Returns a list of table elements. Will be non-empty.
+     *
+     * @return A list of table elements. Will be non-empty.
+     */
+    List<TableElement> getElementList();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableScope.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableScope.java
new file mode 100644
index 0000000..518af9e
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/TableScope.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table;
+
+/**
+ * This enum is for table scope in table definition. The scope may be either {@link #GLOBAL_TEMPORARY} or
+ * {@link #LOCAL_TEMPORARY}.
+ *
+ * @author Stanislav Muhametsin
+ * @see TableDefinition
+ */
+public final class TableScope
+{
+
+    /**
+     * This value represents the {@code GLOBAL TEMPORARY} table.
+     */
+    public static final TableScope GLOBAL_TEMPORARY = new TableScope();
+
+    /**
+     * This value represents the {@code LOCAL TEMPORARY} table.
+     */
+    public static final TableScope LOCAL_TEMPORARY = new TableScope();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/UniqueConstraint.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/UniqueConstraint.java
new file mode 100644
index 0000000..1315f27
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/UniqueConstraint.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table;
+
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+
+/**
+ * This constraint defines the columns to be unique ({@code UNIQUE(col1, col2, ...)}).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface UniqueConstraint
+    extends TableConstraint
+{
+
+    /**
+     * Returns the kind of uniqueness: either primary key constraint ({@code PRIMARY KEY}), or normal uniqueness
+     * constraint ({@code UNIQUE}).
+     *
+     * @return The kind of uniqueness.
+     * @see UniqueSpecification
+     */
+    UniqueSpecification getUniquenessKind();
+
+    /**
+     * Returns the names of columns that are unique.
+     *
+     * @return The names of columns that are unique.
+     */
+    ColumnNameList getColumnNameList();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/UniqueSpecification.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/UniqueSpecification.java
new file mode 100644
index 0000000..8aea72b
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/UniqueSpecification.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table;
+
+/**
+ * This syntax element represents the two kind of uniqueness of a column(s): either that the column(s) are
+ * {@code PRIMARY KEY} ({@link #PRIMARY_KEY}), or {@code UNIQUE} ({@link #UNIQUE}).
+ *
+ * @author Stanislav Muhametsin
+ */
+public final class UniqueSpecification
+{
+
+    /**
+     * Represents the primary key uniqueness ({@code PRIMARY KEY(col1, col2, ...)}).
+     */
+    public static final UniqueSpecification PRIMARY_KEY = new UniqueSpecification();
+
+    /**
+     * Represents the normal uniqueness ({@code UNIQUE(col1, col2, ...)}).
+     */
+    public static final UniqueSpecification UNIQUE = new UniqueSpecification();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/package-info.java
new file mode 100644
index 0000000..12745a6
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This package contains syntax interfaces for {@code CREATE TABLE} statement.
+ */
+package org.apache.polygene.library.sql.generator.grammar.definition.table;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/pgsql/PgSQLTableCommitAction.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/pgsql/PgSQLTableCommitAction.java
new file mode 100644
index 0000000..04ca291
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/table/pgsql/PgSQLTableCommitAction.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.table.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableCommitAction;
+
+/**
+ * This class extends the default table commit actions ({@code PRESERVE/DELETE ROWS}) to include third option,
+ * {@code DROP}, supported in PostgreSQL.
+ *
+ * @author Stanislav Muhametsin
+ */
+public class PgSQLTableCommitAction
+{
+    /**
+     * The table commit action to {@code DROP} table when transaction ends.
+     */
+    public static TableCommitAction DROP = new TableCommitAction();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/view/RegularViewSpecification.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/view/RegularViewSpecification.java
new file mode 100644
index 0000000..0c31fb5
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/view/RegularViewSpecification.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.view;
+
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+
+/**
+ * This syntax element represents the column name list in view definition.
+ *
+ * @author Stanislav Muhametsin
+ * @see ViewDefinition
+ */
+public interface RegularViewSpecification
+    extends ViewSpecification
+{
+
+    /**
+     * Returns the column names of this view. Will be {@code null} if none are specified.
+     *
+     * @return The column names of this view. Will be {@code null} if none are specified.
+     */
+    ColumnNameList getColumns();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/view/ViewCheckOption.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/view/ViewCheckOption.java
new file mode 100644
index 0000000..4579615
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/view/ViewCheckOption.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.view;
+
+/**
+ * View check option is typically either {@link #CASCADED} or {@link #LOCAL}.
+ *
+ * @author Stanislav Muhametsin
+ */
+public final class ViewCheckOption
+{
+
+    /**
+     * This is the cascaded view check option.
+     */
+    public static final ViewCheckOption CASCADED = new ViewCheckOption();
+
+    /**
+     * This is the local view check option.
+     */
+    public static final ViewCheckOption LOCAL = new ViewCheckOption();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/view/ViewDefinition.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/view/ViewDefinition.java
new file mode 100644
index 0000000..769dfd1
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/view/ViewDefinition.java
@@ -0,0 +1,72 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.view;
+
+import org.apache.polygene.library.sql.generator.grammar.common.SchemaDefinitionStatement;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.definition.schema.SchemaElement;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+
+/**
+ * This syntax element represents the {@code CREATE VIEW} statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface ViewDefinition
+    extends SchemaDefinitionStatement, SchemaElement
+{
+
+    /**
+     * Returns {@code true} if the view is defined to be {@code RECURSIVE}, {@code false} otherwise.
+     *
+     * @return {@code true} if the view is defined to be {@code RECURSIVE}, {@code false} otherwise.
+     */
+    Boolean isRecursive();
+
+    /**
+     * Returns the name of this view.
+     *
+     * @return The name of this view.
+     */
+    TableNameDirect getViewName();
+
+    /**
+     * Returns the view specification.
+     *
+     * @return The view specification.
+     * @see ViewSpecification
+     */
+    ViewSpecification getViewSpecification();
+
+    /**
+     * Returns the query defining the contents for this view.
+     *
+     * @return The query defining the contents for this view.
+     */
+    QueryExpression getViewQuery();
+
+    /**
+     * Returns the view check option. Will be {@code null} if none defined.
+     *
+     * @return The view check option. Will be {@code null} if none defined.
+     * @see ViewCheckOption
+     */
+    ViewCheckOption getViewCheckOption();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/view/ViewSpecification.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/view/ViewSpecification.java
new file mode 100644
index 0000000..71dc8a3
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/view/ViewSpecification.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.definition.view;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This a common interface for view specification (typically column name list).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface ViewSpecification
+    extends Typeable<ViewSpecification>
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/view/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/view/package-info.java
new file mode 100644
index 0000000..18143ce
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/definition/view/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This package contains syntax interfaces required for {@code CREATE VIEW} statement.
+ */
+package org.apache.polygene.library.sql.generator.grammar.definition.view;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/BooleanFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/BooleanFactory.java
new file mode 100644
index 0000000..7cac4a7
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/BooleanFactory.java
@@ -0,0 +1,283 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.BetweenPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanTest;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanTest.TestType;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanTest.TruthValue;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Conjunction;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Disjunction;
+import org.apache.polygene.library.sql.generator.grammar.booleans.EqualsPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.ExistsPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.GreaterOrEqualPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.GreaterThanPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.InPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.IsNotNullPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.IsNullPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.LessOrEqualPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.LessThanPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.LikePredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Negation;
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotBetweenPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotEqualsPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotInPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotLikePredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotRegexpPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.RegexpPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.UniquePredicate;
+import org.apache.polygene.library.sql.generator.grammar.builders.booleans.BooleanBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.booleans.InBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * A factory for creating various {@link BooleanExpression}s. This factory is obtainable from {@link SQLVendor}.
+ *
+ * @author Stanislav Muhametsin
+ * @see SQLVendor
+ */
+public interface BooleanFactory
+{
+
+    /**
+     * Creates new {@link EqualsPredicate}.
+     *
+     * @param left  The left-side expression.
+     * @param right The right-side expression.
+     * @return The new {@link EqualsPredicate}.
+     */
+    EqualsPredicate eq( NonBooleanExpression left, NonBooleanExpression right );
+
+    /**
+     * Creates new {@link NotEqualsPredicate}.
+     *
+     * @param left  The left-side expression.
+     * @param right The right-side expression.
+     * @return The new {@link NotEqualsPredicate}.
+     */
+    NotEqualsPredicate neq( NonBooleanExpression left, NonBooleanExpression right );
+
+    /**
+     * Creates new {@link LessThanPredicate}.
+     *
+     * @param left  The left-side expression.
+     * @param right The right-side expression.
+     * @return The new {@link LessThanPredicate}.
+     */
+    LessThanPredicate lt( NonBooleanExpression left, NonBooleanExpression right );
+
+    /**
+     * Creates new {@link LessOrEqualPredicate}.
+     *
+     * @param left  The left-side expression.
+     * @param right The right-side expression.
+     * @return The new {@link LessOrEqualPredicate}.
+     */
+    LessOrEqualPredicate leq( NonBooleanExpression left, NonBooleanExpression right );
+
+    /**
+     * Creates new {@link GreaterThanPredicate}.
+     *
+     * @param left  The left-side expression.
+     * @param right The right-side expression.
+     * @return The new {@link GreaterThanPredicate}.
+     */
+    GreaterThanPredicate gt( NonBooleanExpression left, NonBooleanExpression right );
+
+    /**
+     * Creates new {@link GreaterOrEqualPredicate}.
+     *
+     * @param left  The left-side expression.
+     * @param right The right-side expression.
+     * @return The new {@link GreaterOrEqualPredicate}.
+     */
+    GreaterOrEqualPredicate geq( NonBooleanExpression left, NonBooleanExpression right );
+
+    /**
+     * Creates new {@link IsNullPredicate}.
+     *
+     * @param what The expression for the predicate.
+     * @return The new {@link IsNullPredicate}.
+     */
+    IsNullPredicate isNull( NonBooleanExpression what );
+
+    /**
+     * Creates new {@link IsNotNullPredicate}.
+     *
+     * @param what The expression for the predicate.
+     * @return The new {@link IsNotNullPredicate}.
+     */
+    IsNotNullPredicate isNotNull( NonBooleanExpression what );
+
+    /**
+     * Creates new {@link Negation}.
+     *
+     * @param what The expression to be negated.
+     * @return The new {@link Negation}.
+     */
+    Negation not( BooleanExpression what );
+
+    /**
+     * Creates new {@link Conjunction}.
+     *
+     * @param left  The left-side expression.
+     * @param right The right-side expression.
+     * @return The new {@link Conjunction}.
+     */
+    Conjunction and( BooleanExpression left, BooleanExpression right );
+
+    /**
+     * Creates new {@link Disjunction}.
+     *
+     * @param left  The left-side expression.
+     * @param right The right-side expression.
+     * @return The new {@link Disjunction}.
+     */
+    Disjunction or( BooleanExpression left, BooleanExpression right );
+
+    /**
+     * Creates new {@link BetweenPredicate}.
+     *
+     * @param left    What to be between.
+     * @param minimum The minimum value.
+     * @param maximum The maximum value.
+     * @return The new {@link BetweenPredicate}.
+     */
+    BetweenPredicate between( NonBooleanExpression left, NonBooleanExpression minimum,
+                              NonBooleanExpression maximum );
+
+    /**
+     * Creates new {@link NotBetweenPredicate}.
+     *
+     * @param left    What not to be between.
+     * @param minimum The minimum value
+     * @param maximum The maximum value.
+     * @return The new {@link NotBetweenPredicate}.
+     */
+    NotBetweenPredicate notBetween( NonBooleanExpression left, NonBooleanExpression minimum,
+                                    NonBooleanExpression maximum );
+
+    /**
+     * Creates new {@link InPredicate}.
+     *
+     * @param what   What to be in accepted values.
+     * @param values The accepted values.
+     * @return The new {@link InPredicate}.
+     */
+    InPredicate in( NonBooleanExpression what, NonBooleanExpression... values );
+
+    /**
+     * Returns a builder for {@link InPredicate}.
+     *
+     * @param what What to be in accepted values.
+     * @return The builder for {@link InPredicate}.
+     */
+    InBuilder inBuilder( NonBooleanExpression what );
+
+    /**
+     * Creates new {@link NotInPredicate}.
+     *
+     * @param what   What not to be in values.
+     * @param values The values.
+     * @return The new {@link NotInPredicate}.
+     */
+    NotInPredicate notIn( NonBooleanExpression what, NonBooleanExpression... values );
+
+    /**
+     * Creates new {@link LikePredicate}.
+     *
+     * @param what    What to be like something.
+     * @param pattern The pattern to match.
+     * @return The new {@link LikePredicate}
+     */
+    LikePredicate like( NonBooleanExpression what, NonBooleanExpression pattern );
+
+    /**
+     * Creates new {@link NotLikePredicate}.
+     *
+     * @param what    What not to be like something.
+     * @param pattern The pattern.
+     * @return The new {@link NotLikePredicate}.
+     */
+    NotLikePredicate notLike( NonBooleanExpression what, NonBooleanExpression pattern );
+
+    /**
+     * Creates new {@link RegexpPredicate}.
+     *
+     * @param what    What to match.
+     * @param pattern The pattern to match.
+     * @return The new {@link NotRegexpPredicate}.
+     */
+    RegexpPredicate regexp( NonBooleanExpression what, NonBooleanExpression pattern );
+
+    /**
+     * Creates new {@link NotRegexpPredicate}.
+     *
+     * @param what    What would be not matching the pattern.
+     * @param pattern The pattern to use.
+     * @return The new {@link NotRegexpPredicate}.
+     */
+    NotRegexpPredicate notRegexp( NonBooleanExpression what, NonBooleanExpression pattern );
+
+    /**
+     * Creates new {@link ExistsPredicate}.
+     *
+     * @param query A query to use.
+     * @return The new {@link ExistsPredicate}.
+     */
+    ExistsPredicate exists( QueryExpression query );
+
+    /**
+     * Creates new {@link UniquePredicate}.
+     *
+     * @param query A query to use.
+     * @return The new {@link UniquePredicate}.
+     */
+    UniquePredicate unique( QueryExpression query );
+
+    /**
+     * Creates new {@link BooleanTest}.
+     *
+     * @param expression The expresssion to test.
+     * @param testType   The test type to use.
+     * @param truthValue The truth value to use.
+     * @return The new {@link BooleanTest}.
+     */
+    BooleanTest test( BooleanExpression expression, TestType testType, TruthValue truthValue );
+
+    /**
+     * Returns new {@link BooleanBuilder} with {@link org.apache.polygene.library.sql.generator.grammar.booleans.Predicate.EmptyPredicate}
+     * as initial value.
+     *
+     * @return The new {@link BooleanBuilder}.
+     */
+    BooleanBuilder booleanBuilder();
+
+    /**
+     * Returns new {@link BooleanBuilder} with given boolean expression as initial value.
+     *
+     * @param first The initial value for boolean expression.
+     * @return The new {@link BooleanBuilder}.
+     */
+    BooleanBuilder booleanBuilder( BooleanExpression first );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/ColumnsFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/ColumnsFactory.java
new file mode 100644
index 0000000..7fd5299
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/ColumnsFactory.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.factories;
+
+import java.util.Collection;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferenceByExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferenceByName;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * A factory to create various expressions related to columns. This factory is obtainable from {@link SQLVendor}.
+ *
+ * @author Stanislav Muhametsin
+ * @see SQLVendor
+ */
+public interface ColumnsFactory
+{
+
+    /**
+     * Creates column reference, which has value of some expression.
+     *
+     * @param expression The expression for the column.
+     * @return The new {@link ColumnReferenceByExpression}.
+     */
+    ColumnReferenceByExpression colExp( ValueExpression expression );
+
+    /**
+     * <p>
+     * Creates column reference, which references column by name, without table name.
+     * </p>
+     * <p>
+     * Calling this method is equivalent in calling {@link #colName(String, String)} and passing {@code null} as first
+     * argument.
+     * </p>
+     *
+     * @param colName The name of the column.
+     * @return The new {@link ColumnReferenceByName}.
+     */
+    ColumnReferenceByName colName( String colName );
+
+    /**
+     * Creates column reference, which reference column by its name and by name of table, to which it belongs.
+     *
+     * @param tableName The name of the table. May be {@code null}.
+     * @param colName   The name of the column.
+     * @return The new {@link ColumnReferenceByName}.
+     */
+    ColumnReferenceByName colName( String tableName, String colName );
+
+    /**
+     * Constructs new {@link ColumnNameList}.
+     *
+     * @param names The column names. At least one element must be present.
+     * @return The new {@link ColumnNameList}.
+     */
+    ColumnNameList colNames( String... names );
+
+    /**
+     * Constructs new {@link ColumnNameList} using specified column names. A new copy of List will be allocated for the
+     * {@link ColumnNameList}.
+     *
+     * @param names The column names. Must contain at least one name.
+     * @return The new {@link ColumnNameList}.
+     */
+    ColumnNameList colNames( Collection<String> names );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/DataTypeFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/DataTypeFactory.java
new file mode 100644
index 0000000..5511a55
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/DataTypeFactory.java
@@ -0,0 +1,375 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.BigInt;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.Decimal;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.DoublePrecision;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.IntervalDataType;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.Numeric;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.Real;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLBoolean;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLChar;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDate;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLFloat;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLInteger;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLInterval;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLTime;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLTimeStamp;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SmallInt;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.UserDefinedType;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableDefinition;
+
+/**
+ * This is factory for creating SQL data types. Typically required when defining tables.
+ *
+ * @author Stanislav Muhametsin
+ * @see TableDefinition
+ */
+public interface DataTypeFactory
+{
+
+    /**
+     * Creates data type representing {@code BIGINT}.
+     *
+     * @return Data type representing {@code BIGINT}.
+     */
+    BigInt bigInt();
+
+    /**
+     * <p>
+     * Creates plain {@code DECIMAL} type. Calling this method is equivalent to calling
+     * {@link #decimal(Integer, Integer)} and passing {@code null} as both parameters.
+     * </p>
+     * <p>
+     * The site http://intelligent-enterprise.informationweek.com/000626/celko.jhtml explains difference between
+     * {@code NUMERIC} and {@code DECIMAL}:
+     * </p>
+     * <p>
+     * The difference between DECIMAL(s,p) and NUMERIC(s,p) is subtle in the SQL-92 Standard -- DECIMAL(s,p) must be
+     * exactly as precise as declared, while NUMERIC(s,p) must be at least as precise as declared.
+     * </p>
+     *
+     * @return The new {@code DECIMAL} type.
+     */
+    Decimal decimal();
+
+    /**
+     * <p>
+     * Creates {@code DECIMAL(p)} type, where {@code p} is given precision. Calling this method is equivalent to calling
+     * {@link #decimal(Integer, Integer)} and passing {@code null} as second parameter.
+     * </p>
+     * <p>
+     * The site http://intelligent-enterprise.informationweek.com/000626/celko.jhtml explains difference between
+     * {@code NUMERIC} and {@code DECIMAL}:
+     * </p>
+     * <p>
+     * The difference between DECIMAL(s,p) and NUMERIC(s,p) is subtle in the SQL-92 Standard -- DECIMAL(s,p) must be
+     * exactly as precise as declared, while NUMERIC(s,p) must be at least as precise as declared.
+     * </p>
+     *
+     * @param precision The precision for this {@code DECIMAL}. May be {@code null} to create plain {@code DECIMAL}
+     *                  type.
+     * @return The new {@code DECIMAL} type.
+     */
+    Decimal decimal( Integer precision );
+
+    /**
+     * <p>
+     * Creates {@code DECIMAL(p,s)} type, where {@code p} is given precision, and {@code s} is given scale.
+     * </p>
+     * <p>
+     * The site http://intelligent-enterprise.informationweek.com/000626/celko.jhtml explains difference between
+     * {@code NUMERIC} and {@code DECIMAL}:
+     * </p>
+     * <p>
+     * The difference between DECIMAL(s,p) and NUMERIC(s,p) is subtle in the SQL-92 Standard -- DECIMAL(s,p) must be
+     * exactly as precise as declared, while NUMERIC(s,p) must be at least as precise as declared.
+     * </p>
+     *
+     * @param precision The precision for this {@code DECIMAL}. May be {@code null} to create plain {@code DECIMAL}.
+     * @param scale     The scale for this {@code DECIMAL}. Is ignored if {@code precision} is {@code null}.
+     * @return The new {@code DECIMAL} type.
+     */
+    Decimal decimal( Integer precision, Integer scale );
+
+    /**
+     * Creates data type representing {@code DOUBLE PRECISION}.
+     *
+     * @return Data type representing {@code DOUBLE PRECISION}.
+     */
+    DoublePrecision doublePrecision();
+
+    /**
+     * <p>
+     * Creates plain {@code NUMERIC} type. Calling this method is equivalent to calling
+     * {@link #numeric(Integer, Integer)} and passing {@code null} as both parameters.
+     * </p>
+     * <p>
+     * The site http://intelligent-enterprise.informationweek.com/000626/celko.jhtml explains difference between
+     * {@code NUMERIC} and {@code DECIMAL}:
+     * </p>
+     * <p>
+     * The difference between DECIMAL(s,p) and NUMERIC(s,p) is subtle in the SQL-92 Standard -- DECIMAL(s,p) must be
+     * exactly as precise as declared, while NUMERIC(s,p) must be at least as precise as declared.
+     * </p>
+     *
+     * @return The new {@code NUMERIC} type.
+     */
+    Numeric numeric();
+
+    /**
+     * <p>
+     * Creates {@code NUMERIC(p)} type, where {@code p} is given precision. Calling this method is equivalent to calling
+     * {@link #numeric(Integer, Integer)} and passing {@code null} as second parameter.
+     * </p>
+     * <p>
+     * The site http://intelligent-enterprise.informationweek.com/000626/celko.jhtml explains difference between
+     * {@code NUMERIC} and {@code DECIMAL}:
+     * </p>
+     * <p>
+     * The difference between DECIMAL(s,p) and NUMERIC(s,p) is subtle in the SQL-92 Standard -- DECIMAL(s,p) must be
+     * exactly as precise as declared, while NUMERIC(s,p) must be at least as precise as declared.
+     * </p>
+     *
+     * @param precision The precision for this {@code NUMERIC}. May be {@code null} to create plain {@code NUMERIC}
+     *                  type.
+     * @return The new {@code NUMERIC} type.
+     */
+    Numeric numeric( Integer precision );
+
+    /**
+     * <p>
+     * Creates {@code NUMERIC(p,s)} type, where {@code p} is given precision, and {@code s} is given scale.
+     * </p>
+     * <p>
+     * The site http://intelligent-enterprise.informationweek.com/000626/celko.jhtml explains difference between
+     * {@code NUMERIC} and {@code DECIMAL}:
+     * </p>
+     * <p>
+     * The difference between DECIMAL(s,p) and NUMERIC(s,p) is subtle in the SQL-92 Standard -- DECIMAL(s,p) must be
+     * exactly as precise as declared, while NUMERIC(s,p) must be at least as precise as declared.
+     * </p>
+     *
+     * @param precision The precision for this {@code NUMERIC}. May be {@code null} to create plain {@code NUMERIC}.
+     * @param scale     The scale for this {@code NUMERIC}. Is ignored if {@code precision} is {@code null}.
+     * @return The new {@code NUMERIC} type.
+     */
+    Numeric numeric( Integer precision, Integer scale );
+
+    /**
+     * Creates data type representing {@code REAL}.
+     *
+     * @return Data type representing {@code REAL}.
+     */
+    Real real();
+
+    /**
+     * Creates data type representing {@code SMALLINT}.
+     *
+     * @return Data type representing {@code SMALLINT}.
+     */
+    SmallInt smallInt();
+
+    /**
+     * Creates data type representing {@code BOOLEAN}.
+     *
+     * @return Data type representing {@code BOOLEAN}.
+     */
+    SQLBoolean sqlBoolean();
+
+    /**
+     * Creates a new {@code CHARACTER} type. Calling this method is equivalent to calling {@link #sqlChar(Integer)} and
+     * passing {@code null} as parameter.
+     *
+     * @return New {@code CHARACTER} type.
+     */
+    SQLChar sqlChar();
+
+    /**
+     * Creates a new {@code CHARACTER} type.
+     *
+     * @param length The length for this {@code CHARACTER}. May be {@code null}.
+     * @return New {@code CHARACTER} type.
+     */
+    SQLChar sqlChar( Integer length );
+
+    /**
+     * Creates a new {@code CHARACTER VARYING} type. Calling this method is equivalent to calling
+     * {@link #sqlVarChar(Integer)} and passing {@code null} as parameter.
+     *
+     * @return New {@code CHARACTER VARYING} type.
+     */
+    SQLChar sqlVarChar();
+
+    /**
+     * Creates a new {@code CHARACTER VARYING} type.
+     *
+     * @param length The length for this {@code CHARACTER VARYING}. May be {@code null}.
+     * @return New {@code CHARACTER VARYING} type.
+     */
+    SQLChar sqlVarChar( Integer length );
+
+    /**
+     * Creates a {@code DATE} type.
+     *
+     * @return New {@code DATE} type.
+     */
+    SQLDate date();
+
+    /**
+     * Creates new instance of {@code FLOAT} type. Calling this method is equivalent to calling
+     * {@link #sqlFloat(Integer)} and passing {@code null} as argument.
+     *
+     * @return New {@code FLOAt} type.
+     */
+    SQLFloat sqlFloat();
+
+    /**
+     * Creates new instance of {@code FLOAT} type.
+     *
+     * @param precision The precision for this {@code FLOAT} type. May be {@code null}.
+     * @return New {@code FLOAT} type.
+     */
+    SQLFloat sqlFloat( Integer precision );
+
+    /**
+     * Creates new instance of {@code INTEGER} type.
+     *
+     * @return New {@code INTEGER} type.
+     */
+    SQLInteger integer();
+
+    /**
+     * Creates a new <b>year-month</b> {@code INTERVAL}.
+     *
+     * @param startField          The type of start field for this {@code INTERVAL}. Must be either {@link IntervalDataType#YEAR}
+     *                            or {@link IntervalDataType#MONTH}.
+     * @param startFieldPrecision The precision for the start field. May be {@code null} if none specified.
+     * @param endField            The type of end field for this {@code INTERVAL}. May be {@code null} for single date interval. If
+     *                            it is not {@code null}, must be either {@link IntervalDataType#YEAR} or {@link IntervalDataType#MONTH}
+     *                            .
+     * @return The new {@code INTERVAL} with specified values.
+     * @throws NullPointerException     If {@code startField} is {@code null}.
+     * @throws IllegalArgumentException If requirements for {@code startField} or {@code endField} fail.
+     */
+    SQLInterval yearMonthInterval( IntervalDataType startField, Integer startFieldPrecision,
+                                   IntervalDataType endField );
+
+    /**
+     * Creates a new <b>day-time</b> {@code INTERVAL}.
+     *
+     * @param startField          The type of start field for this {@code INTERVAL}. Must not be {@link IntervalDataType#YEAR}
+     *                            nor {@link IntervalDataType#MONTH}.
+     * @param startFieldPrecision The precision for the start field. May {@code null} if none specified.
+     * @param endField            The type of end field for this {@code INTERVAL}. May be {@code null} for single day-time
+     *                            interval. If it is not {@code null}, it must not be {@link IntervalDataType#YEAR} nor
+     *                            {@link IntervalDataType#MONTH}.
+     * @param secondFracs         The fractional precision for when end field is {@link IntervalDataType#SECOND} or when this is
+     *                            single day-time interval and start field is {@link IntervalDataType#SECOND}. Otherwise this value is
+     *                            ignored.
+     * @return The new {@code INTERVAL}.
+     * @throws NullPointerException     If {@code startField} is {@code null}.
+     * @throws IllegalArgumentException If requirements for {@code startField} or {@code endField} fail, or if when
+     *                                  using single day-time interval with type {@link IntervalDataType#SECOND}, and {@code secondFracs}
+     *                                  is specified, but {@code startFieldPrecision} is not specified.
+     */
+    SQLInterval dayTimeInterval( IntervalDataType startField, Integer startFieldPrecision,
+                                 IntervalDataType endField, Integer secondFracs );
+
+    /**
+     * Creates {@code TIME} type with unspecified precision and unspecified value for including time zone. Calling this
+     * method is equivalent to calling {@link #time(Integer, Boolean)} and pass {@code null} as both parameters.
+     *
+     * @return {@code TIME} type without precision and unspecified value for including time zone.
+     */
+    SQLTime time();
+
+    /**
+     * Creates {@code TIME} type with given precision and unspecified value for including time zone. Calling this method
+     * is equivalent to calling {@link #time(Integer, Boolean)} and pass {@code null} as second parameter.
+     *
+     * @param precision The precision for {@code TIME}. May be {@code null}.
+     * @return {@code TIME} type with given precision and unspecified value for including time zone.
+     */
+    SQLTime time( Integer precision );
+
+    /**
+     * Creates {@code TIME} type with unspecified precision and given value for including time zone. Calling this method
+     * is equivalent to calling {@link #time(Integer, Boolean)} and pass {@code null} as first parameter.
+     *
+     * @param withTimeZone Whether to include time zone. May be {@code null} if no decision is wanted.
+     * @return {@code TIME} type with unspecified precision and given value for including time zone.
+     */
+    SQLTime time( Boolean withTimeZone );
+
+    /**
+     * Creates {@code TIME} type with given precision and whether to include time zone.
+     *
+     * @param precision    The precision for {@code TIME}. May be {@code null}.
+     * @param withTimeZone Whether to include time zone. May be {@code null} if no decision is wanted.
+     * @return {@code TIME} type with given precision and whether to include time zone.
+     */
+    SQLTime time( Integer precision, Boolean withTimeZone );
+
+    /**
+     * Creates {@code TIMESTAMP} type with unspecified precision and unspecified value for including time zone. Calling
+     * this method is equivalent to calling {@link #timeStamp(Integer, Boolean)} and pass {@code null} as both
+     * parameters.
+     *
+     * @return {@code TIMESTAMP} type without precision and unspecified value for including time zone.
+     */
+    SQLTimeStamp timeStamp();
+
+    /**
+     * Creates {@code TIMESTAMP} type with given precision and unspecified value for including time zone. Calling this
+     * method is equivalent to calling {@link #timeStamp(Integer, Boolean)} and pass {@code null} as second parameter.
+     *
+     * @param precision The precision for {@code TIME}. May be {@code null}.
+     * @return {@code TIMESTAMP} type with given precision and unspecified value for including time zone.
+     */
+    SQLTimeStamp timeStamp( Integer precision );
+
+    /**
+     * Creates {@code TIMESTAMP} type with unspecified precision and given value for including time zone. Calling this
+     * method is equivalent to calling {@link #timeStamp(Integer, Boolean)} and pass {@code null} as first parameter.
+     *
+     * @param withTimeZone Whether to include time zone. May be {@code null} if no decision is wanted.
+     * @return {@code TIMESTAMP} type with unspecified precision and given value for including time zone.
+     */
+    SQLTimeStamp timeStamp( Boolean withTimeZone );
+
+    /**
+     * Creates {@code TIMESTAMP} type with given precision and whether to include time zone.
+     *
+     * @param precision    The precision for {@code TIMESTAMP}. May be {@code null}.
+     * @param withTimeZone Whether to include time zone. May be {@code null} if no decision is wanted.
+     * @return {@code TIMESTAMP} type with given precision and whether to include time zone.
+     */
+    SQLTimeStamp timeStamp( Integer precision, Boolean withTimeZone );
+
+    /**
+     * Creates a user-defined type which will be inserted into SQL statement as-such.
+     *
+     * @param textualContent The textual contents for user-defined type.
+     * @return Syntax element for user defined type.
+     */
+    UserDefinedType userDefined( String textualContent );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/DefinitionFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/DefinitionFactory.java
new file mode 100644
index 0000000..edf5672
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/DefinitionFactory.java
@@ -0,0 +1,253 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.ForeignKeyConstraintBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.SchemaDefinitionBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.TableDefinitionBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.TableElementListBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.UniqueConstraintBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.ViewDefinitionBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDataType;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.AutoGenerationPolicy;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.CheckConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ConstraintCharacteristics;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ForeignKeyConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.LikeClause;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.RegularViewSpecification;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.ViewDefinition;
+
+/**
+ * This is factory for creating builders and syntax elements related to SQL Data Definition (typically {@code CREATE}
+ * statements).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface DefinitionFactory
+{
+
+    /**
+     * Creates an empty builder for {@code CREATE SCHEMA} statement.
+     *
+     * @return An empty builder for {@code CREATE SCHEMA} statement.
+     */
+    SchemaDefinitionBuilder createSchemaDefinitionBuilder();
+
+    /**
+     * Creates an empty builder for {@code CREATE TABLE} statement.
+     *
+     * @return An empty builder for {@code CREATE TABLE} statement.
+     */
+    TableDefinitionBuilder createTableDefinitionBuilder();
+
+    /**
+     * Creates an empty builder for defining columns and constraints for {@code CREATE TABLE} statement.
+     *
+     * @return An empty builder for defining columns and constraints for {@code CREATE TABLE} statement.
+     * @see TableDefinition
+     */
+    TableElementListBuilder createTableElementListBuilder();
+
+    /**
+     * Creates a new definition of column with specified name and data type. Invoking this method is equivalent to
+     * invoking {@link #createColumnDefinition(String, SQLDataType, String, Boolean)} and pass {@code null} and {@code true}
+     * as last two parameters (meaning that there is no default value for column, and it may have {@code NULL} values).
+     *
+     * @param columnName     The name of the column.
+     * @param columnDataType The data type of the column.
+     * @return The syntax element for definition of column with specified name and data type.
+     * @see #createColumnDefinition(String, SQLDataType, String, Boolean)
+     */
+    ColumnDefinition createColumnDefinition( String columnName, SQLDataType columnDataType );
+
+    /**
+     * Creates a new definition of column with specified name, data type, and {@code NULL} value policy. Invoking this
+     * method is equivalent to invoking {@link #createColumnDefinition(String, SQLDataType, String, Boolean)} and pass
+     * {@code null} and {@code mayBeNull} as last two parameters (meaning that there is no default value for column).
+     *
+     * @param columnName     The name of the column.
+     * @param columnDataType The data type of the column.
+     * @param mayBeNull      The {@code NULL} value policy. Setting this to {@code false} is same as specifying
+     *                       {@code NOT NULL} in column definition in SQL.
+     * @return The syntax element for definition of column with specified name, data type, and {@code NULL} value
+     * policy.
+     * @see #createColumnDefinition(String, SQLDataType, String, Boolean)
+     */
+    ColumnDefinition createColumnDefinition( String columnName, SQLDataType columnDataType, Boolean mayBeNull );
+
+    /**
+     * Creates a new definition of column with specified name, data type, default value. Invoking this method is
+     * equivalent to invoking {@link #createColumnDefinition(String, SQLDataType, String, Boolean)} and pass
+     * {@code columnDefault} and {@code true} as last two parameters (meaning that column may have {@code NULL} values).
+     *
+     * @param columnName     The name of the column.
+     * @param columnDataType The data type of the column.
+     * @param columnDefault  The default value of the column.
+     * @return The syntax element for definition of column with specified name, data type, default value.
+     * @see #createColumnDefinition(String, SQLDataType, String, Boolean)
+     */
+    ColumnDefinition createColumnDefinition( String columnName, SQLDataType columnDataType, String columnDefault );
+
+    /**
+     * Creates a new definition of column with specified name, data type, default value, and {@code NULL} value policy.
+     * Invoking this method is equivalent to invoking
+     * {@link #createColumnDefinition(String, SQLDataType, Boolean, AutoGenerationPolicy)} and pass {@code null}
+     * as last parameter.
+     *
+     * @param columnName     The name of the column.
+     * @param columnDataType The data type of the column.
+     * @param columnDefault  The default value of the column.
+     * @param mayBeNull      The {@code NULL} value policy for the column. Setting this to {@code false} is same as
+     *                       specifying {@code NOT NULL} in column definition in SQL.
+     * @return The syntax element for definition of column with specified name, data type, default value, and
+     * {@code NULL} value policy.
+     */
+    ColumnDefinition createColumnDefinition( String columnName, SQLDataType columnDataType,
+                                             String columnDefault, Boolean mayBeNull );
+
+    /**
+     * Creates a new definition of column with specified name, data type, {@code NULL} value policy, and auto generation
+     * policy.
+     *
+     * @param columnName           The name of the column.
+     * @param columnDataType       The data type of the column.
+     * @param mayBeNull            The {@code NULL} value policy for the column. Setting this to {@code false} is same as
+     *                             specifying {@code NOT NULL} in column definition in SQL.
+     * @param autoGenerationPolicy The policy for auto generation for this column. Should be {@code null} if the column
+     *                             should not be marked as automatically generated.
+     * @return The syntax element for definition of column with specified name, data type, default value, {@code NULL}
+     * value policy, and auto generation policy.
+     */
+
+    ColumnDefinition createColumnDefinition( String columnName, SQLDataType columnDataType, Boolean mayBeNull,
+                                             AutoGenerationPolicy autoGenerationPolicy );
+
+    /**
+     * Creates a new {@code LIKE
+     * <table name>} clause for {@code CREATE TABLE} statement.
+     *
+     * @param tableName The name of the target table.
+     * @return The syntax element for {@code LIKE
+     * <table name>} clause for {@code CREATE TABLE} statement.
+     */
+    LikeClause createLikeClause( TableNameDirect tableName );
+
+    /**
+     * Creates a new unnamed table constraint without any {@link ConstraintCharacteristics}. Invoking this method is
+     * equivalent to invoking
+     * {@link #createTableConstraintDefinition(String, TableConstraint, ConstraintCharacteristics)} and passing
+     * {@code null}s as first and last parameters.
+     *
+     * @param constraint The constraint for the table.
+     * @return The syntax element for unnamed table constraint without any {@link ConstraintCharacteristics}.
+     * @see #createColumnDefinition(String, SQLDataType, String, Boolean)
+     */
+    TableConstraintDefinition createTableConstraintDefinition( TableConstraint constraint );
+
+    /**
+     * Creates a new, named table constraint without any {@link ConstraintCharacteristics}. Invoking this method is
+     * equivalent to invoking
+     * {@link #createTableConstraintDefinition(String, TableConstraint, ConstraintCharacteristics)} and passing
+     * {@code null} as last parameter.
+     *
+     * @param name       The name for the constraint.
+     * @param constraint The constraint for the table.
+     * @return The syntax element for named table constraint without any {@link ConstraintCharacteristics}.
+     * @see #createColumnDefinition(String, SQLDataType, String, Boolean)
+     */
+    TableConstraintDefinition createTableConstraintDefinition( String name, TableConstraint constraint );
+
+    /**
+     * Creates a new unnamed table constraint with specified {@link ConstraintCharacteristics}. Invoking this method is
+     * equivalent to invoking
+     * {@link #createTableConstraintDefinition(String, TableConstraint, ConstraintCharacteristics)} and passing
+     * {@code null} as first parameter.
+     *
+     * @param constraint      The constraint for the table.
+     * @param characteristics The constraint characteristics for the constraint.
+     * @return The syntax element for unnamed table constraint with specified {@link ConstraintCharacteristics}.
+     * @see #createColumnDefinition(String, SQLDataType, String, Boolean)
+     * @see ConstraintCharacteristics
+     */
+    TableConstraintDefinition createTableConstraintDefinition( TableConstraint constraint,
+                                                               ConstraintCharacteristics characteristics );
+
+    /**
+     * Creates a new named table constraint with specified {@link ConstraintCharacteristics}.
+     *
+     * @param name            The name for the constraint.
+     * @param constraint      The constraint for the table.
+     * @param characteristics The characteristics for the constraint.
+     * @return The syntax element for named table constraint with specified {@link ConstraintCharacteristics}.
+     * @see ConstraintCharacteristics
+     */
+    TableConstraintDefinition createTableConstraintDefinition( String name, TableConstraint constraint,
+                                                               ConstraintCharacteristics characteristics );
+
+    /**
+     * Creates a {@code CHECK} clause, typically used in {@code CREATE TABLE} statements.
+     *
+     * @param check The boolean expression for check.
+     * @return The syntax element for {@code CHECK} clause, typically used in {@code CREATE TABLE} statements.
+     */
+    CheckConstraint createCheckConstraint( BooleanExpression check );
+
+    /**
+     * Creates an empty builder for unique constraint (either {@code UNIQUE(columns...)} or
+     * {@code PRIMARY KEY(columns...)}), typically used in {@code CREATE TABLE} statements.
+     *
+     * @return An empty builder for unique constraints (either {@code UNIQUE(columns...)} or
+     * {@code PRIMARY KEY(columns...)}).
+     */
+    UniqueConstraintBuilder createUniqueConstraintBuilder();
+
+    /**
+     * Creates an empty builder for {@code FOREIGN KEY} constraint, typically used in {@code CREATE TABLE} statements.
+     *
+     * @return An empty builder for {@code FOREIGN KEY} constraint.
+     * @see ForeignKeyConstraintBuilder
+     * @see ForeignKeyConstraint
+     */
+    ForeignKeyConstraintBuilder createForeignKeyConstraintBuilder();
+
+    /**
+     * Creates an empty builder for {@code CREATE VIEW} statement.
+     *
+     * @return An empty builder for {@code CREATE VIEW} statement.
+     * @see ViewDefinitionBuilder
+     * @see ViewDefinition
+     */
+    ViewDefinitionBuilder createViewDefinitionBuilder();
+
+    /**
+     * Creates a new view specification with given columns. Must have at least one column.
+     *
+     * @param columnNames The names of the columns.
+     * @return A new {@link RegularViewSpecification}.
+     * @see RegularViewSpecification
+     */
+    RegularViewSpecification createRegularViewSpecification( String... columnNames );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/LiteralFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/LiteralFactory.java
new file mode 100644
index 0000000..50feb61
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/LiteralFactory.java
@@ -0,0 +1,88 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.factories;
+
+import java.sql.Timestamp;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.literals.DirectLiteral;
+import org.apache.polygene.library.sql.generator.grammar.literals.NumericLiteral;
+import org.apache.polygene.library.sql.generator.grammar.literals.SQLFunctionLiteral;
+import org.apache.polygene.library.sql.generator.grammar.literals.StringLiteral;
+import org.apache.polygene.library.sql.generator.grammar.literals.TimestampTimeLiteral;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * A factory to create various literal expressions. This factory is obtainable from {@link SQLVendor}.
+ *
+ * @author Stanislav Muhametsin
+ * @see SQLVendor
+ */
+public interface LiteralFactory
+{
+
+    /**
+     * Creates new string literal, that is, a string to be enclosed in {@code '} -characters.
+     *
+     * @param stringContents The contents of string literal.
+     * @return The new {@link StringLiteral}
+     */
+    StringLiteral s( String stringContents );
+
+    /**
+     * Returns literal, representing a parameter ({@code ?}) in parameterized SQL statement.
+     *
+     * @return The expression representing parameter ({@code ?}) in parameterized SQL statement.
+     */
+    DirectLiteral param();
+
+    /**
+     * Creates a literal, which has some textual content. This content will be used <b>directly</b> when processing SQL
+     * statement.
+     *
+     * @param literalContents The contents to be used.
+     * @return The new {@link DirectLiteral}.
+     */
+    DirectLiteral l( String literalContents );
+
+    /**
+     * Creates a literal, which has some date as content.
+     *
+     * @param date The date to use.
+     * @return The new {@link TimestampTimeLiteral}.
+     */
+    TimestampTimeLiteral dt( Timestamp date );
+
+    /**
+     * Creates a literal, which has some number as contents.
+     *
+     * @param number The number to use.
+     * @return The new {@link NumericLiteral}.
+     */
+    NumericLiteral n( Number number );
+
+    /**
+     * Creates a literal, which represents a use of SQL function.
+     *
+     * @param name       The name of function.
+     * @param parameters The parameters for function.
+     * @return The new {@link SQLFunctionLiteral}.
+     */
+    SQLFunctionLiteral func( String name, ValueExpression... parameters );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/ManipulationFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/ManipulationFactory.java
new file mode 100644
index 0000000..96149b5
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/ManipulationFactory.java
@@ -0,0 +1,157 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AddColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AddTableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterColumnAction;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterColumnAction.DropDefault;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterTableAction;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterTableStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropBehaviour;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropSchemaStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropTableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropTableOrViewStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.ObjectType;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.SetColumnDefault;
+
+/**
+ * This is factory for creating builders and syntax elements related to SQL Data Manipulation (typically {@code ALTER}
+ * and {@code DROP} statements).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface ManipulationFactory
+{
+
+    /**
+     * Creates the {@code ALTER TABLE} statement with specified parameter.
+     *
+     * @param tableName The name of the table.
+     * @param action    The action to be done to the table.
+     * @return The {@code ALTER TABLE} statement syntax element.
+     * @see AlterTableStatement
+     * @see #createAddColumnDefinition(ColumnDefinition)
+     * @see #createAddTableConstraintDefinition(TableConstraintDefinition)
+     * @see #createAlterColumnDefinition(String, AlterColumnAction)
+     * @see #createDropColumnDefinition(String, DropBehaviour)
+     * @see #createDropTableConstraintDefinition(String, DropBehaviour)
+     */
+    AlterTableStatement createAlterTableStatement( TableNameDirect tableName, AlterTableAction action );
+
+    /**
+     * Creates the syntax element for adding column ({@code ADD COLUMN ...}) in {@code ALTER TABLE} statement.
+     *
+     * @param definition The column to add to table.
+     * @return The syntax element for adding column ({@code ADD COLUMN ...}) in {@code ALTER TABLE} statement.
+     * @see AlterTableStatement
+     */
+    AddColumnDefinition createAddColumnDefinition( ColumnDefinition definition );
+
+    /**
+     * Creates the syntax element for adding table constraint({@code ADD ...}) in {@code ALTER TABLE} statement.
+     *
+     * @param constraintDefinition The table constraint to add to table.
+     * @return The syntax element for adding table constraint ({@code ADD ...}) in {@code ALTER TABLE} statement.
+     * @see AlterTableStatement
+     */
+    AddTableConstraintDefinition createAddTableConstraintDefinition(
+        TableConstraintDefinition constraintDefinition );
+
+    /**
+     * Creates the syntax element for altering column definition ({@code ALTER COLUMN}) in {@code ALTER TABLE}
+     * statement.
+     *
+     * @param columnName The name of the column to alter.
+     * @param action     The way how column should be altered.
+     * @return The syntax element for altering column definition ({@code ALTER COLUMN}) in {@code ALTER TABLE}
+     * statement.
+     * @see AlterColumnAction
+     * @see DropDefault
+     * @see #createSetColumnDefault(String)
+     */
+    AlterColumnDefinition createAlterColumnDefinition( String columnName, AlterColumnAction action );
+
+    /**
+     * Creates the syntax element for setting a new default for column ({@code SET DEFAULT ...}) in {@code ALTER TABLE}
+     * statement.
+     *
+     * @param newDefault The new default value for column.
+     * @return The syntax element for setting a new default for column ({@code SET DEFAULT ...}) in {@code ALTER TABLE}
+     * statement.
+     * @see AlterColumnAction
+     */
+    SetColumnDefault createSetColumnDefault( String newDefault );
+
+    /**
+     * Creates the syntax element for dropping a column definition ({@code DROP COLUMN}) in {@code ALTER TABLE}
+     * statement.
+     *
+     * @param columnName    The name of the column to drop.
+     * @param dropBehaviour The drop behaviour.
+     * @return The syntax element for dropping a column definition ({@code DROP COLUMN}) in {@code ALTER TABLE}
+     * statement.
+     * @see DropBehaviour
+     * @see AlterTableStatement
+     */
+    DropColumnDefinition createDropColumnDefinition( String columnName, DropBehaviour dropBehaviour );
+
+    /**
+     * Creates the syntax element for dropping a table constraint ({@code DROP CONSTRAINT ...}) in {@code ALTER TABLE}
+     * statement.
+     *
+     * @param constraintName The name of the constraint to drop.
+     * @param dropBehaviour  The drop behaviour.
+     * @return The syntax element for dropping a table constraint ({@code DROP CONSTRAINT ...}) in {@code ALTER TABLE}
+     * statement.
+     * @see DropBehaviour
+     * @see AlterTableStatement
+     */
+    DropTableConstraintDefinition createDropTableConstraintDefinition( String constraintName,
+                                                                       DropBehaviour dropBehaviour );
+
+    /**
+     * Creates the statement to drop schema ({@code DROP SCHEMA ...}).
+     *
+     * @param schemaName    The name of the schema to drop.
+     * @param dropBehaviour The drop behaviour.
+     * @return The statement to drop schema ({@code DROP SCHEMA ...}).
+     */
+    DropSchemaStatement createDropSchemaStatement( String schemaName, DropBehaviour dropBehaviour );
+
+    /**
+     * Creates the statement to drop table ({@code DROP TABLE ...}) or view ({@code DROP VIEW ...}).
+     *
+     * @param tableName     The name of the table or view to drop.
+     * @param theType       What to drop. Must be either {@link ObjectType#TABLE} for tables or {@link ObjectType#VIEW} for
+     *                      views.
+     * @param dropBehaviour The drop behaviour.
+     * @return The statement to drop table ({@code DROP TABLE ...}) or view ({@code DROP VIEW ...}).
+     * @see DropBehaviour
+     * @see ObjectType
+     */
+    DropTableOrViewStatement createDropTableOrViewStatement( TableNameDirect tableName, ObjectType theType,
+                                                             DropBehaviour dropBehaviour );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/ModificationFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/ModificationFactory.java
new file mode 100644
index 0000000..72160af
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/ModificationFactory.java
@@ -0,0 +1,147 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.ColumnSourceByValuesBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.DeleteBySearchBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.InsertStatementBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.UpdateBySearchBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSourceByQuery;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSourceByValues;
+import org.apache.polygene.library.sql.generator.grammar.modification.DeleteBySearch;
+import org.apache.polygene.library.sql.generator.grammar.modification.InsertStatement;
+import org.apache.polygene.library.sql.generator.grammar.modification.SetClause;
+import org.apache.polygene.library.sql.generator.grammar.modification.TargetTable;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateBySearch;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateSource;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateSourceByExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * A factory, which creates SQL syntax elements related to modification statements ({@code INSERT INTO},
+ * {@code DELETE FROM}, and {@code UPDATE}). This factory is obtainable from {@link SQLVendor}.
+ *
+ * @author Stanislav Muhametsin
+ * @see SQLVendor
+ */
+public interface ModificationFactory
+{
+
+    /**
+     * Creates a builder to add values as column sources in {@code INSERT INTO} statement.
+     *
+     * @return The new {@link ColumnSourceByValuesBuilder} for {@link ColumnSourceByValues}.
+     */
+    ColumnSourceByValuesBuilder columnSourceByValues();
+
+    /**
+     * <p>
+     * Creates a column source, which uses a query as a source for columns in {@code INSERT INTO} statement.
+     * </p>
+     * <p>
+     * Calling this method is equivalent in calling {@link #columnSourceByQuery(ColumnNameList, QueryExpression)} and
+     * passing {@code null} as first argument.
+     * </p>
+     *
+     * @param query The query to use as source for columns in {@code INSERT INTO} statement.
+     * @return The new {@link ColumnSourceByQuery}.
+     */
+    ColumnSourceByQuery columnSourceByQuery( QueryExpression query );
+
+    /**
+     * Creates a column source, which uses specified target table column names and query as source columns in
+     * {@code INSERT INTO} statement.
+     *
+     * @param columnNames The column names to use in target table.
+     * @param query       The query to use to populate target table.
+     * @return The new {@link ColumnSourceByQuery}.
+     */
+    ColumnSourceByQuery columnSourceByQuery( ColumnNameList columnNames, QueryExpression query );
+
+    /**
+     * Creates builder to create {@link DeleteBySearch} statements.
+     *
+     * @return The new builder for {@link DeleteBySearch}.
+     * @see DeleteBySearchBuilder
+     */
+    DeleteBySearchBuilder deleteBySearch();
+
+    /**
+     * Creates builder to create {@link InsertStatement}s.
+     *
+     * @return The new builder for {@link InsertStatement}.
+     * @see InsertStatementBuilder
+     */
+    InsertStatementBuilder insert();
+
+    /**
+     * Creates builder to create {@link UpdateBySearch} statements.
+     *
+     * @return The new builder for {@link UpdateBySearch} statements.
+     * @see UpdateBySearchBuilder
+     */
+    UpdateBySearchBuilder updateBySearch();
+
+    /**
+     * <p>
+     * Creates new target table to use in modification statements.
+     * </p>
+     * <p>
+     * Calling this method is equivalent for calling {@link #createTargetTable(TableNameDirect, Boolean)} and passing
+     * {@code false} as second parameter.
+     *
+     * @param tableName The name of the table.
+     * @return The new {@link TargetTable}.
+     */
+    TargetTable createTargetTable( TableNameDirect tableName );
+
+    /**
+     * Creates new target table to use in modification statements.
+     *
+     * @param tableName The name of the table.
+     * @param isOnly    Whether modification should affect child-tables too.
+     * @return The new {@link TargetTable}.
+     */
+    TargetTable createTargetTable( TableNameDirect tableName, Boolean isOnly );
+
+    /**
+     * Creates a new source for {@code UPDATE} statement. This source will use specified expression as a source for
+     * values.
+     *
+     * @param expression The expression to use.
+     * @return The new {@link UpdateSourceByExpression}.
+     * @see UpdateBySearch
+     */
+    UpdateSourceByExpression updateSourceByExp( ValueExpression expression );
+
+    /**
+     * Creates a new set clause for {@code UPDATE} statement.
+     *
+     * @param updateTarget The target of the update, typically name of the column.
+     * @param updateSource The source for data to be put into that column.
+     * @return The new {@link SetClause}.
+     * @see UpdateBySearch
+     */
+    SetClause setClause( String updateTarget, UpdateSource updateSource );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/QueryFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/QueryFactory.java
new file mode 100644
index 0000000..8872251
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/QueryFactory.java
@@ -0,0 +1,227 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.query.ColumnsBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.FromBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.GroupByBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.OrderByBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.QueryBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.QuerySpecificationBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.SimpleQueryBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.literals.SQLFunctionLiteral;
+import org.apache.polygene.library.sql.generator.grammar.query.GroupByClause;
+import org.apache.polygene.library.sql.generator.grammar.query.LimitSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.OffsetSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.Ordering;
+import org.apache.polygene.library.sql.generator.grammar.query.OrdinaryGroupingSet;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBody;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBody.EmptyQueryExpressionBody;
+import org.apache.polygene.library.sql.generator.grammar.query.QuerySpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.RowDefinition;
+import org.apache.polygene.library.sql.generator.grammar.query.RowSubQuery;
+import org.apache.polygene.library.sql.generator.grammar.query.RowValueConstructor;
+import org.apache.polygene.library.sql.generator.grammar.query.SortSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.TableValueConstructor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * A factory, which creates builders and syntax elements for SQL queries ({@code SELECT} statements). This factory may
+ * be obtained from {@link SQLVendor}.
+ *
+ * @author Stanislav Muhametsin
+ * @see SQLVendor
+ * @see QueryExpression
+ * @see QuerySpecification
+ */
+public interface QueryFactory
+{
+
+    /**
+     * Creates new query, which has the specified body as an actual query.
+     *
+     * @param body The actual query to use.
+     * @return The new {@link QueryExpression}
+     */
+    QueryExpression createQuery( QueryExpressionBody body );
+
+    /**
+     * Creates a builder to build query specifications ({@code SELECT} expressions).
+     *
+     * @return The new {@link QuerySpecificationBuilder}.
+     */
+    QuerySpecificationBuilder querySpecificationBuilder();
+
+    /**
+     * <p>
+     * Creates a builder for the columns in {@code SELECT} expressions.
+     * </p>
+     * <p>
+     * Calling this method is equivalent to calling {@link #columnsBuilder(SetQuantifier)} and passing
+     * {@link SetQuantifier#ALL} as argument.
+     * </p>
+     *
+     * @return The new {@link ColumnsBuilder}.
+     */
+    ColumnsBuilder columnsBuilder();
+
+    /**
+     * Creates a builder for columns in {@code SELECT} expressions, which has specified set quantifier initially.
+     *
+     * @param setQuantifier The set quantifier to use.
+     * @return The new {@link ColumnsBuilder}.
+     */
+    ColumnsBuilder columnsBuilder( SetQuantifier setQuantifier );
+
+    /**
+     * <p>
+     * Creates a builder to build queries with capability for {@code UNION}, {@code INTERSECT}, and {@code EXCEPT} set
+     * operations.
+     * </p>
+     * <p>
+     * Calling this method is equivalent in calling {@link #queryBuilder(QueryExpressionBody)} and passing
+     * {@link EmptyQueryExpressionBody} as argument.
+     *
+     * @return The new {@link QueryBuilder}.
+     */
+    QueryBuilder queryBuilder();
+
+    /**
+     * Creates a builder to build queries with capability for {@code UNION}, {@code INTERSECT}, and {@code EXCEPT} set
+     * operations.
+     *
+     * @param query The initial query for builder.
+     * @return The new {@link QueryBuilder}.
+     */
+    QueryBuilder queryBuilder( QueryExpressionBody query );
+
+    /**
+     * Creates a builder for {@code GROUP BY} clause.
+     *
+     * @return The new {@link GroupByBuilder}.
+     */
+    GroupByBuilder groupByBuilder();
+
+    /**
+     * Creates a builder for {@code FROM} clause.
+     *
+     * @return The new {@link FromBuilder}.
+     */
+    FromBuilder fromBuilder();
+
+    /**
+     * Creates a new grouping element, which has some expressions as grouping columns.
+     *
+     * @param expressions The expressions to use.
+     * @return The new {@link OrdinaryGroupingSet}.
+     * @see GroupByClause
+     */
+    OrdinaryGroupingSet groupingElement( NonBooleanExpression... expressions );
+
+    /**
+     * Creates a new sort specification for {@code ORDER BY} clause.
+     *
+     * @param expression The expression for column.
+     * @param ordering   The ordering to use.
+     * @return The new {@link SortSpecification}.
+     */
+    SortSpecification sortSpec( ValueExpression expression, Ordering ordering );
+
+    /**
+     * Creates a builder for {@code ORDER BY} clause.
+     *
+     * @return The new {@link OrderByBuilder}.
+     */
+    OrderByBuilder orderByBuilder();
+
+    /**
+     * Creates a builder for simple queries.
+     *
+     * @return The new {@link SimpleQueryBuilder}.
+     */
+    SimpleQueryBuilder simpleQueryBuilder();
+
+    /**
+     * Creates a new {@code VALUES} expression in query.
+     *
+     * @param rows The rows for {@code VALUES} expression.
+     * @return The new {@link TableValueConstructor}.
+     * @see RowValueConstructor
+     * @see RowSubQuery
+     * @see RowDefinition
+     */
+    TableValueConstructor values( RowValueConstructor... rows );
+
+    /**
+     * Creates a new subquery for a row for {@code VALUES} expression in query.
+     *
+     * @param subQuery The query to return the row.
+     * @return The new {@link RowSubQuery}.
+     */
+    RowSubQuery rowSubQuery( QueryExpression subQuery );
+
+    /**
+     * Creates a new row for {@code VALUES} expression in query.
+     *
+     * @param elements The elements for the row.
+     * @return The new {@link RowDefinition}.
+     */
+    RowDefinition row( ValueExpression... elements );
+
+    /**
+     * Returns a query for calling a SQL function with schema. The query is
+     * {@code SELECT * FROM schemaName.functionName(params...)}.
+     *
+     * @param schemaName The name of the schema where SQL function resides.
+     * @param function   The SQL function to call.
+     * @return A query returning the results of calling SQL function.
+     */
+    QueryExpression callFunction( String schemaName, SQLFunctionLiteral function );
+
+    /**
+     * Returns a query for calling a SQL function without a schema. The query is
+     * {@code SELECT * FROM functionName(params...)}. Calling this method is equivalent to calling
+     * {@link #callFunction(String, SQLFunctionLiteral)} and passing {@code null} as first argument.
+     *
+     * @param function The function to call.
+     * @return A query returning the results of calling SQL function.
+     */
+    QueryExpression callFunction( SQLFunctionLiteral function );
+
+    /**
+     * Creates a new {@code OFFSET <n> ROWS} syntax element for query.
+     *
+     * @param offset The offset amount.
+     * @return A new {@code OFFSET <n> ROWS} syntax element.
+     */
+    OffsetSpecification offset( NonBooleanExpression offset );
+
+    /**
+     * Creates a new {@code FETCH FIRST <n> ROWS ONLY} syntax element for query.
+     *
+     * @param count The limit amount.
+     * @return A new {@code FETCH FIRST <n> ROWS ONLY} syntax element.
+     */
+    LimitSpecification limit( NonBooleanExpression count );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/TableReferenceFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/TableReferenceFactory.java
new file mode 100644
index 0000000..252f807
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/TableReferenceFactory.java
@@ -0,0 +1,182 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.TableReferenceBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.common.TableName;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameFunction;
+import org.apache.polygene.library.sql.generator.grammar.literals.SQLFunctionLiteral;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.TableAlias;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferenceByExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferenceByName;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferencePrimary;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinCondition;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.NamedColumnsJoin;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * A factory for creating builders and syntax elements related to tables. This factory is obtainable from
+ * {@link SQLVendor}.
+ *
+ * @author Stanislav Muhametsin
+ * @see SQLVendor
+ */
+public interface TableReferenceFactory
+{
+    /**
+     * <p>
+     * Creates a new table reference, which uses given table name, without table alias.
+     * </p>
+     * <p>
+     * Calling this method is equivalent to calling {@link #table(TableName, TableAlias)} and passing {@code null} as
+     * second parameter.
+     * </p>
+     *
+     * @param tableName The table name to use.
+     * @return The new {@link TableReferenceByName}.
+     */
+    TableReferenceByName table( TableName tableName );
+
+    /**
+     * Creates a new table references, which uses given table name along with given table alias.
+     *
+     * @param tableName The table name to use.
+     * @param alias     The table alias to use. May be {@code null}.
+     * @return The new {@link TableReferenceByName}.
+     */
+    TableReferenceByName table( TableName tableName, TableAlias alias );
+
+    /**
+     * <p>
+     * Creates a new table name, which isn't schema-qualified.
+     * </p>
+     * <p>
+     * Calling this method is equivalent to calling {@link #tableName(String, String)} and passing {@code null} as first
+     * parameter.
+     * </p>
+     *
+     * @param tableName The name of the table.
+     * @return The new {@link TableName}.
+     */
+    TableNameDirect tableName( String tableName );
+
+    /**
+     * Creates a new table name. If the given schema-name is non-{@code null}, the table name is said to be
+     * schema-qualified.
+     *
+     * @param schemaName The schema name to use. May be {@code null}.
+     * @param tableName  The table name to use.
+     * @return The new {@link TableName}.
+     */
+    TableNameDirect tableName( String schemaName, String tableName );
+
+    /**
+     * Creates a new table name representing a call to SQL function without a schema. This is equivalent to calling
+     * {@link #tableName(String, SQLFunctionLiteral)} and passing {@code null} as first argument.
+     *
+     * @param function The function to call.
+     * @return Table name representing a call to SQL function without a schema.
+     */
+    TableNameFunction tableName( SQLFunctionLiteral function );
+
+    /**
+     * Creates a new table name representing a call to SQL function with schema.
+     *
+     * @param schemaName The schema where function resides.
+     * @param function   The function to call.
+     * @return Table name representing a call to SQL function with schema.
+     */
+    TableNameFunction tableName( String schemaName, SQLFunctionLiteral function );
+
+    /**
+     * <p>
+     * Creates a new alias for table.
+     * </p>
+     * <p>
+     * Calling this method is equivalent to calling {@link #tableAliasWithCols(String, String...)} and not pass anything
+     * to varargs parameter.
+     * </p>
+     *
+     * @param tableNameAlias The alias for table name.
+     * @return The new {@link TableAlias}.
+     */
+    TableAlias tableAlias( String tableNameAlias );
+
+    /**
+     * Creates a new table alias for table, with renamed columns.
+     *
+     * @param tableNameAlias The alias for table name.
+     * @param colNames       The new column names for table.
+     * @return The new {@link TableAlias}.
+     */
+    TableAlias tableAliasWithCols( String tableNameAlias, String... colNames );
+
+    /**
+     * <p>
+     * Creates a new table reference, which will use the values returned by query as if they were values of the table.
+     * </p>
+     * <p>
+     * Calling this method is equivalent to calling {@link #table(QueryExpression, TableAlias)} and passing {@code null}
+     * as second parameter.
+     * </p>
+     *
+     * @param query The query to use.
+     * @return The new {@link TableReferenceByExpression}.
+     */
+    TableReferenceByExpression table( QueryExpression query );
+
+    /**
+     * Creates a new table reference, which will use the values returned by query as if they were values of the table.
+     * Optionally, the table will has a given alias.
+     *
+     * @param query The query to use.
+     * @param alias The table alias to use. May be {@code null} if no alias is needed.
+     * @return The new {@link TableReferenceByExpression}.
+     */
+    TableReferenceByExpression table( QueryExpression query, TableAlias alias );
+
+    /**
+     * Creates a new {@link TableReferenceBuilder} typically used to build joined tables.
+     *
+     * @param firstTable The starting table.
+     * @return The new {@link TableReferenceBuilder}.
+     */
+    TableReferenceBuilder tableBuilder( TableReferencePrimary firstTable );
+
+    /**
+     * Creates a join-condition using specified boolean expression to join tables.
+     *
+     * @param condition The condition to join tables.
+     * @return The new {@link JoinCondition}.
+     */
+    JoinCondition jc( BooleanExpression condition );
+
+    /**
+     * Creates a new named columns join specification, which will use column names to join tables.
+     *
+     * @param columnNames The column names to use to join tables.
+     * @return The new {@link NamedColumnsJoin}.
+     */
+    NamedColumnsJoin nc( ColumnNameList columnNames );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/package-info.java
new file mode 100644
index 0000000..81a4977
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This package provides factories to create various builders and SQL syntax elements.
+ */
+package org.apache.polygene.library.sql.generator.grammar.factories;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/pgsql/PgSQLDataTypeFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/pgsql/PgSQLDataTypeFactory.java
new file mode 100644
index 0000000..729173c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/pgsql/PgSQLDataTypeFactory.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.factories.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.pgsql.Text;
+import org.apache.polygene.library.sql.generator.grammar.factories.DataTypeFactory;
+
+/**
+ * This is factory for creating SQL pre-defined types, as well as types specific for PostgreSQL.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface PgSQLDataTypeFactory
+    extends DataTypeFactory
+{
+
+    /**
+     * Creates the data type representing {@code TEXT} data type.
+     *
+     * @return The data type representing {@code TEXT} data type.
+     */
+    Text text();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/pgsql/PgSQLManipulationFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/pgsql/PgSQLManipulationFactory.java
new file mode 100644
index 0000000..64acf71
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/pgsql/PgSQLManipulationFactory.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.factories.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.factories.ManipulationFactory;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropBehaviour;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.ObjectType;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.pgsql.PgSQLDropTableOrViewStatement;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public interface PgSQLManipulationFactory
+    extends ManipulationFactory
+{
+
+    PgSQLDropTableOrViewStatement createDropTableOrViewStatement( TableNameDirect tableName, ObjectType theType,
+                                                                  DropBehaviour dropBehaviour );
+
+    /**
+     * Creates {@code DROP TABLE/VIEW} statement, which may use {@code IF EXISTS} clause before the table name.
+     *
+     * @param tableName     The name of the table/view to drop.
+     * @param theType       What to drop - {@link ObjectType#TABLE} or {@link ObjectType#VIEW}.
+     * @param dropBehaviour Drop behaviour - {@link DropBehaviour#CASCADE} or {@link DropBehaviour#RESTRICT}.
+     * @param useIfExists   {@code true} to append {@code IF EXISTS} before table/view name, {@code false} otherwise.
+     * @return New {@code DROP TABLE/VIEW} statement.
+     */
+    PgSQLDropTableOrViewStatement createDropTableOrViewStatement( TableNameDirect tableName, ObjectType theType,
+                                                                  DropBehaviour dropBehaviour, Boolean useIfExists );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/pgsql/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/pgsql/package-info.java
new file mode 100644
index 0000000..63949b2
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/factories/pgsql/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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 to contain PostgreSQL-specific factories enabling creating of PostgreSQL-specific syntax elements.
+ */
+package org.apache.polygene.library.sql.generator.grammar.factories.pgsql;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/DirectLiteral.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/DirectLiteral.java
new file mode 100644
index 0000000..9e52571
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/DirectLiteral.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.literals;
+
+/**
+ * This syntax element encapsulates text to be inserted directly into SQL statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface DirectLiteral
+    extends LiteralExpression
+{
+
+    /**
+     * Returns the text to be inserted directly into SQL statement.
+     *
+     * @return The text to be inserted directly into SQL statement.
+     */
+    String getDirectLiteral();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/LiteralExpression.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/LiteralExpression.java
new file mode 100644
index 0000000..2e6d15d
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/LiteralExpression.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.literals;
+
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+
+/**
+ * This is common interface for all literal expressions.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface LiteralExpression
+    extends NonBooleanExpression
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/NumericLiteral.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/NumericLiteral.java
new file mode 100644
index 0000000..e61e29d
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/NumericLiteral.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.literals;
+
+/**
+ * This syntax element encapsulates reference to some number to be inserted into SQL statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface NumericLiteral
+    extends LiteralExpression
+{
+    /**
+     * Returns the number to be inserted into SQL statement.
+     *
+     * @return The number to be inserted into SQL statement.
+     */
+    Number getNumber();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/SQLFunctionLiteral.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/SQLFunctionLiteral.java
new file mode 100644
index 0000000..1db873d
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/SQLFunctionLiteral.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.literals;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+
+/**
+ * This syntax element encapsulates reference to some SQL function to be inserted into SQL statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SQLFunctionLiteral
+    extends LiteralExpression
+{
+
+    /**
+     * Returns the name of the SQL function.
+     *
+     * @return The name of the SQL function.
+     */
+    String getFunctionName();
+
+    /**
+     * The parameters for SQL function.
+     *
+     * @return The parameters for SQL function.
+     */
+    List<ValueExpression> getParameters();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/StringLiteral.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/StringLiteral.java
new file mode 100644
index 0000000..9006e81
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/StringLiteral.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.literals;
+
+/**
+ * This syntax element encapsulates reference to SQL string, that is, some element between {@code '} and {@code '}
+ * characters.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface StringLiteral
+    extends LiteralExpression
+{
+
+    /**
+     * Returns the contents of the string literal, that is, the string to be put between {@code '} and {@code '}.
+     *
+     * @return The contents of the string literal.
+     */
+    String getString();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/TemporalLiteral.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/TemporalLiteral.java
new file mode 100644
index 0000000..8293a4e
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/TemporalLiteral.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.literals;
+
+/**
+ * This syntax element represents any literal that represents some kind of time.
+ *
+ * @author 2011 Stanislav Muhametsin
+ * @see TimestampTimeLiteral
+ */
+public interface TemporalLiteral
+    extends LiteralExpression
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/TimestampTimeLiteral.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/TimestampTimeLiteral.java
new file mode 100644
index 0000000..423594f
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/TimestampTimeLiteral.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.literals;
+
+import java.sql.Timestamp;
+
+/**
+ * This syntax element encapsulates reference to some time stamp to be inserted into SQL statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface TimestampTimeLiteral
+    extends TemporalLiteral
+{
+
+    /**
+     * Returns the time stamp to be inserted into SQL statement.
+     *
+     * @return The time stamp to be inserted into SQL statement.
+     */
+    Timestamp getTimestamp();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/package-info.java
new file mode 100644
index 0000000..23fb2e3
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/literals/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * The package for syntax elements representing various literals.
+ */
+package org.apache.polygene.library.sql.generator.grammar.literals;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AddColumnDefinition.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AddColumnDefinition.java
new file mode 100644
index 0000000..48f6b19
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AddColumnDefinition.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.manipulation;
+
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+
+/**
+ * This syntax element represents adding a new column to table.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface AddColumnDefinition
+    extends AlterTableAction
+{
+
+    /**
+     * Returns the definition for column to be added.
+     *
+     * @return The definition for column to be added.
+     * @see ColumnDefinition
+     */
+    ColumnDefinition getColumnDefinition();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AddTableConstraintDefinition.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AddTableConstraintDefinition.java
new file mode 100644
index 0000000..24b1eab
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AddTableConstraintDefinition.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.manipulation;
+
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraintDefinition;
+
+/**
+ * This syntax element represents the new table constraint to be added in table alteration statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface AddTableConstraintDefinition
+    extends AlterTableAction
+{
+    /**
+     * Returns the table constraint to be added.
+     *
+     * @return The table constraint to be added.
+     */
+    TableConstraintDefinition getConstraint();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AlterColumnAction.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AlterColumnAction.java
new file mode 100644
index 0000000..1f2b2a5
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AlterColumnAction.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.manipulation;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This is common interface for column alteration actions.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface AlterColumnAction
+    extends Typeable<AlterColumnAction>
+{
+
+    /**
+     * This syntax element represents dropping column default in table alteration statement.
+     *
+     * @author Stanislav Muhametsin
+     */
+    final class DropDefault
+        implements AlterColumnAction
+    {
+        private DropDefault()
+        {
+
+        }
+
+        public Class<? extends AlterColumnAction> getImplementedType()
+        {
+            return DropDefault.class;
+        }
+
+        public static final DropDefault INSTANCE = new DropDefault();
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AlterColumnDefinition.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AlterColumnDefinition.java
new file mode 100644
index 0000000..26616fa
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AlterColumnDefinition.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.manipulation;
+
+/**
+ * This syntax element represents the alteration of column.
+ *
+ * @author Stanislav Muhametsin
+ * @see AlterTableAction
+ */
+public interface AlterColumnDefinition
+    extends AlterTableAction
+{
+
+    /**
+     * Returns the name of the column to be altered.
+     *
+     * @return The name of the column to be altered.
+     */
+    String getColumnName();
+
+    /**
+     * Returns the action to be done on column.
+     *
+     * @return The action to be done on column.
+     * @see AlterColumnAction
+     */
+    AlterColumnAction getAction();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AlterStatement.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AlterStatement.java
new file mode 100644
index 0000000..d807954
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AlterStatement.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.manipulation;
+
+import org.apache.polygene.library.sql.generator.grammar.common.SchemaManipulationStatement;
+
+/**
+ * This is a common interface for all {@code ALTER} statements.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface AlterStatement
+    extends SchemaManipulationStatement
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AlterTableAction.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AlterTableAction.java
new file mode 100644
index 0000000..0ee5866
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AlterTableAction.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.manipulation;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This is common interface for actions altering table.
+ *
+ * @author Stanislav Muhametsin
+ * @see AlterTableStatement
+ */
+public interface AlterTableAction
+    extends Typeable<AlterTableAction>
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AlterTableStatement.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AlterTableStatement.java
new file mode 100644
index 0000000..ad5158d
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/AlterTableStatement.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.manipulation;
+
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public interface AlterTableStatement
+    extends AlterStatement
+{
+
+    /**
+     * Returns the name of the table to be altered.
+     *
+     * @return The name of the table to be altered.
+     */
+    TableNameDirect getTableName();
+
+    /**
+     * Returns the action to perform in order to alter table.
+     *
+     * @return The action to perform in order to alter table.
+     * @see AlterTableAction
+     */
+    AlterTableAction getAction();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropBehaviour.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropBehaviour.java
new file mode 100644
index 0000000..bb57cdf
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropBehaviour.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.manipulation;
+
+/**
+ * The drop behaviour for generalized {@code DROP} statement. Typically one of {@link #CASCADE} or {@link #RESTRICT}.
+ *
+ * @author Stanislav Muhametsin
+ * @see DropStatement
+ */
+public final class DropBehaviour
+{
+
+    /**
+     * The drop behaviour which means to {@code CASCADE} the {@code DROP} through all depending elements.
+     */
+    public static final DropBehaviour CASCADE = new DropBehaviour();
+
+    /**
+     * The drop behaviour which means to {@code RESTRICT} the {@code DROP} if any elements depend on the object to be
+     * dropped.
+     */
+    public static final DropBehaviour RESTRICT = new DropBehaviour();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropBehaviourContainer.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropBehaviourContainer.java
new file mode 100644
index 0000000..9f61bed
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropBehaviourContainer.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.manipulation;
+
+/**
+ * A generic drop behaviour container (for any {@code DROP} clause and statement).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface DropBehaviourContainer
+{
+
+    /**
+     * Returns the drop behaviour for this clause or statement.
+     *
+     * @return The drop behaviour for this clause or statement.
+     */
+    DropBehaviour getDropBehaviour();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropColumnDefinition.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropColumnDefinition.java
new file mode 100644
index 0000000..59cd0e2
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropColumnDefinition.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.manipulation;
+
+/**
+ * This syntax element represents dropping a column from a table in table alteration statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface DropColumnDefinition
+    extends AlterTableAction, DropBehaviourContainer
+{
+
+    /**
+     * Returns the name of the column to be dropped.
+     *
+     * @return The name of the column to be dropped.
+     */
+    String getColumnName();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropSchemaStatement.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropSchemaStatement.java
new file mode 100644
index 0000000..5b57453
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropSchemaStatement.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.manipulation;
+
+/**
+ * This syntax element represents the {@code DROP SCHEMA} statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface DropSchemaStatement
+    extends DropStatement
+{
+
+    /**
+     * Returns the name of the schema to be dropped.
+     *
+     * @return The name of the schema to be dropped.
+     */
+    String getSchemaName();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropStatement.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropStatement.java
new file mode 100644
index 0000000..0ca5010
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropStatement.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.manipulation;
+
+import org.apache.polygene.library.sql.generator.grammar.common.SchemaManipulationStatement;
+
+/**
+ * This is a common interface for {@code DROP} statements.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface DropStatement
+    extends SchemaManipulationStatement, DropBehaviourContainer
+{
+
+    /**
+     * Returns the object type to drop. Typically either {@link ObjectType#SCHEMA}, {@link ObjectType#TABLE}, or
+     * {@link ObjectType#VIEW}.
+     *
+     * @return The object type to drop.
+     * @see ObjectType
+     */
+    ObjectType whatToDrop();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropTableConstraintDefinition.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropTableConstraintDefinition.java
new file mode 100644
index 0000000..a6a1cc1
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropTableConstraintDefinition.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.manipulation;
+
+/**
+ * This syntax element represents dropping a table constraint in table alteration statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface DropTableConstraintDefinition
+    extends AlterTableAction, DropBehaviourContainer
+{
+
+    /**
+     * Returns the constraint name to be dropped.
+     *
+     * @return The constraint name to be dropped.
+     */
+    String getConstraintName();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropTableOrViewStatement.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropTableOrViewStatement.java
new file mode 100644
index 0000000..1872743
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/DropTableOrViewStatement.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.manipulation;
+
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+
+/**
+ * This is generalized statement to drop tables and views.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface DropTableOrViewStatement
+    extends DropStatement
+{
+
+    /**
+     * Returns the name of the table or view to be deleted.
+     *
+     * @return The name of the table or view to be deleted.
+     */
+    TableNameDirect getTableName();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/ObjectType.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/ObjectType.java
new file mode 100644
index 0000000..33275c8
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/ObjectType.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.manipulation;
+
+/**
+ * Object type is used in generalized {@code DROP} statement to define what to drop. It is usually one of
+ * {@link #SCHEMA}, {@link #TABLE}, or {@link #VIEW}.
+ *
+ * @author Stanislav Muhametsin
+ * @see DropStatement
+ */
+public final class ObjectType
+{
+
+    /**
+     * The object type which means to {@code DROP SCHEMA}.
+     */
+    public static final ObjectType SCHEMA = new ObjectType();
+
+    /**
+     * The object type which means to {@code DROP TABLE}.
+     */
+    public static final ObjectType TABLE = new ObjectType();
+
+    /**
+     * The object type which means to {@code DROP VIEW}.
+     */
+    public static final ObjectType VIEW = new ObjectType();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/SetColumnDefault.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/SetColumnDefault.java
new file mode 100644
index 0000000..4998f80
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/SetColumnDefault.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.manipulation;
+
+/**
+ * This syntax element represents setting a new default for a column in table alteration statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SetColumnDefault
+    extends AlterColumnAction
+{
+
+    /**
+     * Returns the new default value for this column.
+     *
+     * @return The new default value for this column.
+     */
+    String getDefault();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/package-info.java
new file mode 100644
index 0000000..6ff9718
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This package provides syntax elements for {@code DROP} and {@code ALTER} statements.
+ */
+package org.apache.polygene.library.sql.generator.grammar.manipulation;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/pgsql/PgSQLDropTableOrViewStatement.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/pgsql/PgSQLDropTableOrViewStatement.java
new file mode 100644
index 0000000..2b916b9
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/pgsql/PgSQLDropTableOrViewStatement.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.manipulation.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropTableOrViewStatement;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public interface PgSQLDropTableOrViewStatement extends DropTableOrViewStatement
+{
+
+    Boolean useIfExists();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/pgsql/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/pgsql/package-info.java
new file mode 100644
index 0000000..f136488
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/manipulation/pgsql/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This is package for syntax elements specific for data manipulation for PostgreSQL databases.
+ */
+package org.apache.polygene.library.sql.generator.grammar.manipulation.pgsql;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/ColumnSource.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/ColumnSource.java
new file mode 100644
index 0000000..7e14967
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/ColumnSource.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.modification;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This is common interface for syntax elements representing the data source for columns in {@code INSERT INTO}
+ * statement.
+ *
+ * @author Stanislav Muhametsin
+ * @see InsertStatement
+ */
+public interface ColumnSource
+    extends Typeable<ColumnSource>
+{
+    /**
+     * This syntax element represents when default values of columns are wanted to be inserted into table.
+     *
+     * @author Stanislav Muhametsin
+     */
+    final class Defaults
+        implements ColumnSource
+    {
+        private Defaults()
+        {
+
+        }
+
+        /**
+         * Returns {@link Defaults}.
+         */
+        public Class<? extends ColumnSource> getImplementedType()
+        {
+            return Defaults.class;
+        }
+
+        /**
+         * The singleton reference to object of this class.
+         */
+        public static final Defaults INSTANCE = new Defaults();
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/ColumnSourceByQuery.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/ColumnSourceByQuery.java
new file mode 100644
index 0000000..c503fcb
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/ColumnSourceByQuery.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.modification;
+
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+
+/**
+ * This syntax element represents column source acquired by some query, for {@code INSERT INTO} statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface ColumnSourceByQuery
+    extends DynamicColumnSource
+{
+
+    /**
+     * Returns the query to use as column source.
+     *
+     * @return The query to use as column source.
+     */
+    QueryExpression getQuery();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/ColumnSourceByValues.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/ColumnSourceByValues.java
new file mode 100644
index 0000000..0bf1bb3
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/ColumnSourceByValues.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.modification;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+
+/**
+ * <p>
+ * This syntax element represents explicitly defined values for column source in {@code INSERT INTO}
+ * statement.
+ * </p>
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface ColumnSourceByValues
+    extends DynamicColumnSource
+{
+    /**
+     * Returns the values to use as column source.
+     *
+     * @return The values to use as column source.
+     */
+    List<ValueExpression> getValues();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/DeleteBySearch.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/DeleteBySearch.java
new file mode 100644
index 0000000..4e0f1ab
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/DeleteBySearch.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.modification;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+
+/**
+ * This syntax element represents a {@code DELETE FROM} statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface DeleteBySearch
+    extends DeleteStatement
+{
+    /**
+     * Returns the target table for this {@code DELETE FROM} statement.
+     *
+     * @return The target table for this {@code DELETE FROM} statement.
+     */
+    TargetTable getTargetTable();
+
+    /**
+     * Returns the search condition for rows to delete.
+     *
+     * @return The search condition for rows to delete.
+     */
+    BooleanExpression getWhere();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/DeleteStatement.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/DeleteStatement.java
new file mode 100644
index 0000000..17dc635
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/DeleteStatement.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.modification;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLStatement;
+
+/**
+ * A common interface for all statements deleting data from tables.
+ *
+ * @author Stanislav Muhametsin
+ * @see DeleteBySearch
+ */
+public interface DeleteStatement
+    extends SQLStatement, Typeable<DeleteStatement>
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/DynamicColumnSource.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/DynamicColumnSource.java
new file mode 100644
index 0000000..9fdcea6
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/DynamicColumnSource.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.modification;
+
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+
+/**
+ * A common interface for column sources with named columns for {@code INSERT INTO} statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface DynamicColumnSource
+    extends ColumnSource
+{
+
+    /**
+     * Returns the named columns of this column source. May be null if no column names are
+     * specified.
+     *
+     * @return The named columns of this column source.
+     */
+    ColumnNameList getColumnNames();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/InsertStatement.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/InsertStatement.java
new file mode 100644
index 0000000..830cbff
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/InsertStatement.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.modification;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLStatement;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+
+/**
+ * This syntax element represents a {@code INSERT INTO} statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface InsertStatement
+    extends SQLStatement, Typeable<InsertStatement>
+{
+
+    /**
+     * Returns the table name where to insert.
+     *
+     * @return The table name where to insert.
+     */
+    TableNameDirect getTableName();
+
+    /**
+     * Returns the data source for columns.
+     *
+     * @return The data source for columns.
+     */
+    ColumnSource getColumnSource();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/SetClause.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/SetClause.java
new file mode 100644
index 0000000..56f955b
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/SetClause.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.modification;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This syntax element represents a single {@code SET} element of {@code UPDATE} statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SetClause
+    extends Typeable<SetClause>
+{
+
+    /**
+     * Returns the update target, typically a name of the column.
+     *
+     * @return The update target, typically a name of the column.
+     */
+    String getUpdateTarget();
+
+    /**
+     * Returns the update source, that is, data, for the columns.
+     *
+     * @return The data for the columns.
+     */
+    UpdateSource getUpdateSource();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/TargetTable.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/TargetTable.java
new file mode 100644
index 0000000..5591608
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/TargetTable.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.modification;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.TableName;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+
+/**
+ * This syntax element represents the target table of {@code DELETE FROM} and {@code UPDATE} statements.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface TargetTable
+    extends Typeable<TargetTable>
+{
+
+    /**
+     * Returns whether only this table should be updated (and not, for example, inheriting tables).
+     *
+     * @return {@code true} if only this table should be updated; {@code false} otherwise.
+     */
+    Boolean isOnly();
+
+    /**
+     * Returns the table name of the target table.
+     *
+     * @return The table name of the target table.
+     * @see TableName
+     */
+    TableNameDirect getTableName();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/UpdateBySearch.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/UpdateBySearch.java
new file mode 100644
index 0000000..82398ad
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/UpdateBySearch.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.modification;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+
+/**
+ * This syntax element represents {@code UPDATE} statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface UpdateBySearch
+    extends UpdateStatement
+{
+
+    /**
+     * Returns the target table of this {@code UPDATE} statement.
+     *
+     * @return The target table of this {@code UPDATE} statement.
+     * @see TargetTable
+     */
+    TargetTable getTargetTable();
+
+    /**
+     * Returns the search condition for the rows to be updated.
+     *
+     * @return The search condition for the rows to be updated.
+     */
+    BooleanExpression getWhere();
+
+    /**
+     * Returns the {@code SET} clauses for columns of the target table.
+     *
+     * @return The {@code SET} clauses for columns of the target table.
+     * @see SetClause
+     */
+    List<SetClause> getSetClauses();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/UpdateSource.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/UpdateSource.java
new file mode 100644
index 0000000..e6982db
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/UpdateSource.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.modification;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This syntax element represents the data source for column in {@code SET} clause of {@code UPDATE}
+ * statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface UpdateSource
+    extends Typeable<UpdateSource>
+{
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/UpdateSourceByExpression.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/UpdateSourceByExpression.java
new file mode 100644
index 0000000..bd6a4e8
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/UpdateSourceByExpression.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.modification;
+
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+
+/**
+ * This syntax element represents the update source having value of whatever expression it holds.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface UpdateSourceByExpression
+    extends UpdateSource
+{
+
+    /**
+     * Returns the value expression to use as value for update source.
+     *
+     * @return The value expression to use as value for update source.
+     */
+    ValueExpression getValueExpression();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/UpdateStatement.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/UpdateStatement.java
new file mode 100644
index 0000000..bab5554
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/UpdateStatement.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.modification;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLStatement;
+
+/**
+ * This is common interface for all statements doing updates.
+ *
+ * @author Stanislav Muhametsin
+ * @see UpdateBySearch
+ */
+public interface UpdateStatement
+    extends SQLStatement, Typeable<UpdateStatement>
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/ValueSource.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/ValueSource.java
new file mode 100644
index 0000000..93c1c06
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/ValueSource.java
@@ -0,0 +1,82 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.modification;
+
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+
+public class ValueSource
+{
+
+    /**
+     * This syntax element represents the {@code DEFAULT} keyword as data source for column, meaning
+     * to use the default value for the column.
+     *
+     * @author Stanislav Muhametsin
+     */
+    public static final class Default
+        implements ValueExpression
+    {
+        private Default()
+        {
+
+        }
+
+        /**
+         * Returns {@link Default}.
+         */
+        public Class<? extends ValueExpression> getImplementedType()
+        {
+            return Default.class;
+        }
+
+        /**
+         * Singleton instance of {@link Default}.
+         */
+        public static final Default INSTANCE = new Default();
+    }
+
+    /**
+     * This syntax element represents the {@code NULL} keyword as data source for column, meaning to
+     * use the {@code NULL} value for the column.
+     *
+     * @author Stanislav Muhametsin
+     */
+    public static final class Null
+        implements ValueExpression
+    {
+        private Null()
+        {
+
+        }
+
+        /**
+         * Returns {@link Null}.
+         */
+        public Class<? extends ValueExpression> getImplementedType()
+        {
+            return Null.class;
+        }
+
+        /**
+         * The singleton instance of {@link Null}.
+         */
+        public static final Null INSTANCE = new Null();
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/package-info.java
new file mode 100644
index 0000000..302ab4e
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This package contains syntax elements relevant to SQL modification clauses ({@code INSERT INTO}, {@code DELETE FROM}, and {@code UPDATE}).
+ */
+package org.apache.polygene.library.sql.generator.grammar.modification;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/pgsql/PgSQLInsertStatement.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/pgsql/PgSQLInsertStatement.java
new file mode 100644
index 0000000..1f88f99
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/pgsql/PgSQLInsertStatement.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.modification.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.modification.InsertStatement;
+import org.apache.polygene.library.sql.generator.grammar.query.SelectColumnClause;
+
+/**
+ * <p>
+ * This interface represents {@code INSERT} statement with PostgreSQL-specific elements.
+ * </p>
+ * <p>
+ * <p>
+ * TODO: {@code WITH RECURSIVE} query
+ * </p>
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface PgSQLInsertStatement extends InsertStatement
+{
+    /**
+     * Gets the columns for the {@code RETURNING} clause. Returns {@code null} if this
+     * {@code INSERT} statement has no {@code RETURNING} clause.
+     *
+     * @return The {@code RETURNING} clause for this statement, or {@code null} if none.
+     */
+    SelectColumnClause getReturningClause();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/pgsql/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/pgsql/package-info.java
new file mode 100644
index 0000000..86ee8d8
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/modification/pgsql/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This is package for syntax elements specific for data modification in PostgreSQL databases.
+ */
+package org.apache.polygene.library.sql.generator.grammar.modification.pgsql;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/AsteriskSelect.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/AsteriskSelect.java
new file mode 100644
index 0000000..ae995cb
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/AsteriskSelect.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+/**
+ * This syntax element represents the asterisk in expression {@code SELECT} *.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface AsteriskSelect
+    extends SelectColumnClause
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/ColumnReference.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/ColumnReference.java
new file mode 100644
index 0000000..31472c4
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/ColumnReference.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+
+/**
+ * Common interface for columns in expression {@code SELECT <column1>, <column2>, ...}.
+ *
+ * @author Stanislav Muhametsin
+ * @see ColumnReferenceByName
+ * @see ColumnReferenceByExpression
+ */
+public interface ColumnReference
+    extends NonBooleanExpression
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/ColumnReferenceByExpression.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/ColumnReferenceByExpression.java
new file mode 100644
index 0000000..78a72ab
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/ColumnReferenceByExpression.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+
+/**
+ * This syntax element represents the column reference in {@code SELECT <column reference>} clause, where the column
+ * reference is some kind of expression (for example, a constant, or a query).
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface ColumnReferenceByExpression
+    extends ColumnReference
+{
+
+    /**
+     * Gets the expression for this column reference.
+     *
+     * @return The expression for this column reference.
+     */
+    ValueExpression getExpression();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/ColumnReferenceByName.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/ColumnReferenceByName.java
new file mode 100644
index 0000000..14ae9f2
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/ColumnReferenceByName.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+/**
+ * This syntax element represents the column reference in {@code SELECT <column reference>} clause, where the column
+ * reference is column name, either with table name or without.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface ColumnReferenceByName
+    extends ColumnReference
+{
+    /**
+     * Gets the table name of this column. Might be {@code null}.
+     *
+     * @return The table name of this column. Might be {@code null}.
+     */
+    String getTableName();
+
+    /**
+     * Gets the column name of this column.
+     *
+     * @return The column name of this column.
+     */
+    String getColumnName();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/ColumnReferences.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/ColumnReferences.java
new file mode 100644
index 0000000..915c4b1
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/ColumnReferences.java
@@ -0,0 +1,79 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * This syntax element represents the whole {@code SELECT <column1>, <column2>, ...} clause, up until {@code FROM}. Each
+ * column might have an alias.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface ColumnReferences
+    extends SelectColumnClause
+{
+    /**
+     * A helper class to encapsulate column reference along with its alias.
+     *
+     * @author Stanislav Muhametsin
+     */
+    class ColumnReferenceInfo
+    {
+        private final String _alias;
+        private final ColumnReference _reference;
+
+        public ColumnReferenceInfo( String alias, ColumnReference reference )
+        {
+            Objects.requireNonNull( reference );
+
+            this._alias = alias;
+            this._reference = reference;
+        }
+
+        /**
+         * Returns the alias of this column reference. May be {@code null.}
+         *
+         * @return The alias of this column reference. May be {@code null.}
+         */
+        public String getAlias()
+        {
+            return this._alias;
+        }
+
+        /**
+         * Returns the column reference.
+         *
+         * @return The column reference.
+         */
+        public ColumnReference getReference()
+        {
+            return this._reference;
+        }
+    }
+
+    /**
+     * Returns the list of column references, along with their aliases.
+     *
+     * @return The list of column references, along with their aliases.
+     */
+    List<ColumnReferenceInfo> getColumns();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/CorrespondingSpec.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/CorrespondingSpec.java
new file mode 100644
index 0000000..67d4ee6
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/CorrespondingSpec.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+
+/**
+ * This syntax element represents the {@code CORRESPONDING BY} clause in {@code UNION}, {@code INTERSECT}, and
+ * {@code EXCEPT} operations on queries.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface CorrespondingSpec
+    extends Typeable<CorrespondingSpec>
+{
+    /**
+     * Gets the column name correspondence list.
+     *
+     * @return The column name correspondence list.
+     */
+    ColumnNameList getColumnList();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/FromClause.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/FromClause.java
new file mode 100644
index 0000000..9ab567d
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/FromClause.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinedTable;
+
+/**
+ * This syntax element represents the {@code FROM} clause in {@code SELECT} statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface FromClause
+    extends Typeable<FromClause>
+{
+    /**
+     * Gets all the table references. Each table reference may be a simple reference to table name, sub-query, or a
+     * joined table.
+     *
+     * @return The table references for this {@code FROM} clause.
+     * @see TableReference
+     * @see JoinedTable
+     */
+    List<TableReference> getTableReferences();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/GroupByClause.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/GroupByClause.java
new file mode 100644
index 0000000..90264f2
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/GroupByClause.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This syntax element represents the {@code GROUP BY} clause in {@code SELECT} statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface GroupByClause
+    extends Typeable<GroupByClause>
+{
+    /**
+     * Returns the grouping elements of this {@code GROUP BY} clause.
+     *
+     * @return The grouping elements of this {@code GROUP BY} clause.
+     * @see GroupingElement
+     */
+    List<GroupingElement> getGroupingElements();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/GroupingElement.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/GroupingElement.java
new file mode 100644
index 0000000..c5b4f55
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/GroupingElement.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This is a common interface for a grouping element of the {@code GROUP BY} clause.
+ *
+ * @author Stanislav Muhametsin
+ * @see GroupByClause
+ */
+public interface GroupingElement
+    extends Typeable<GroupingElement>
+{
+    /**
+     * This syntax element represents the grand total grouping element. It is open parenthesis followed by close
+     * parenthesis.
+     *
+     * @author Stanislav Muhametsin
+     */
+    final class GrandTotal
+        implements GroupingElement
+    {
+        private GrandTotal()
+        {
+        }
+
+        /**
+         * Returns {@link GrandTotal}
+         */
+        public Class<? extends GroupingElement> getImplementedType()
+        {
+            return GrandTotal.class;
+        }
+
+        /**
+         * The singleton instance of {@link GrandTotal}.
+         */
+        public static final GrandTotal INSTANCE = new GrandTotal();
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/LimitSpecification.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/LimitSpecification.java
new file mode 100644
index 0000000..fb8cbe4
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/LimitSpecification.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+
+/**
+ * This syntax element represents the {@code FETCH FIRST <number> ROWS ONLY} element of the query. This addition has
+ * been defined in SQL 2008 standard.
+ *
+ * @author 2011 Stanislav Muhametsin
+ */
+public interface LimitSpecification
+    extends Typeable<LimitSpecification>
+{
+    /**
+     * Returns the {@code <number>} element in the {@code FETCH FIRST <number> ROWS ONLY} expression. Means the maximum
+     * amounts of rows to be selected.
+     *
+     * @return The maximum amount of rows to be selected. May be {@code null}, in which case the behaviour is
+     * vendor-specific.
+     */
+    NonBooleanExpression getCount();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/OffsetSpecification.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/OffsetSpecification.java
new file mode 100644
index 0000000..88b3ecf
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/OffsetSpecification.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+
+/**
+ * This syntax element represents the {@code OFFSET <number> ROWS} element of the query. This addition has been defined
+ * in SQL 2008 standard.
+ *
+ * @author 2011 Stanislav Muhametsin
+ */
+public interface OffsetSpecification
+    extends Typeable<OffsetSpecification>
+{
+    /**
+     * Returns the {@code <number>} element in the {@code OFFSET <number> ROWS} expression. Means the amount of rows to
+     * skip before including them into select.
+     *
+     * @return The amount of rows to be skipped before starting selecting.
+     */
+    NonBooleanExpression getSkip();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/OrderByClause.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/OrderByClause.java
new file mode 100644
index 0000000..b1afbb3
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/OrderByClause.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This syntax element represents the {@code ORDER BY} clause of {@code SELECT} statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface OrderByClause
+    extends Typeable<OrderByClause>
+{
+
+    /**
+     * Returns the ordering columns of this {@code ORDER BY} clause.
+     *
+     * @return The ordering columns of this {@code ORDER BY} clause.
+     */
+    List<SortSpecification> getOrderingColumns();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/Ordering.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/Ordering.java
new file mode 100644
index 0000000..14af2ea
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/Ordering.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+/**
+ * This is enum for what kind of order will be applied to each ordering column. Can be either {@link #ASCENDING} or
+ * {@link #DESCENDING}.
+ *
+ * @author Stanislav Muhametsin
+ * @see SortSpecification
+ */
+public final class Ordering
+{
+    /**
+     * The ordering will be ascending ({@code ASC}).
+     */
+    public static final Ordering ASCENDING = new Ordering();
+
+    /**
+     * The ordering will be descending ({@code DESC}).
+     */
+    public static final Ordering DESCENDING = new Ordering();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/OrdinaryGroupingSet.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/OrdinaryGroupingSet.java
new file mode 100644
index 0000000..17c9b71
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/OrdinaryGroupingSet.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+
+/**
+ * This syntax element represents the ordinary grouping set specification. In future there might be {@code CUBE} or
+ * {@code ROLLUP} grouping sets.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface OrdinaryGroupingSet
+    extends GroupingElement
+{
+    /**
+     * Returns the grouping column reference expressions.
+     *
+     * @return The grouping column reference expressions.
+     */
+    List<NonBooleanExpression> getColumns();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QueryExpression.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QueryExpression.java
new file mode 100644
index 0000000..b3807e5
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QueryExpression.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLStatement;
+
+/**
+ * This syntax element represents the {@link QueryExpressionBody} and, in future, the WithClause ({@code WITH}) to be
+ * used with query.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface QueryExpression
+    extends NonBooleanExpression, SQLStatement
+{
+    /**
+     * Returns the body of this query.
+     *
+     * @return The body of this query.
+     */
+    QueryExpressionBody getQueryExpressionBody();
+
+    // public WithClause getWithClause();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QueryExpressionBody.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QueryExpressionBody.java
new file mode 100644
index 0000000..1df2130
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QueryExpressionBody.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinedTable;
+
+/**
+ * This is common interface for a queries and joined tables.
+ *
+ * @author Stanislav Muhametsin
+ * @see QueryExpressionBodyActual
+ * @see JoinedTable
+ */
+public interface QueryExpressionBody
+    extends NonBooleanExpression
+{
+    /**
+     * This syntax element represents the empty query expression body. It is defined for convenience. For example, an
+     * {@code UNION} (or any other set operation) between empty query and another query is always just another query.
+     *
+     * @author Stanislav Muhametsin
+     */
+    final class EmptyQueryExpressionBody
+        implements QueryExpressionBody
+    {
+        private EmptyQueryExpressionBody()
+        {
+        }
+
+        /**
+         * Returns {@link EmptyQueryExpressionBody}.
+         */
+        public Class<? extends QueryExpressionBody> getImplementedType()
+        {
+            return EmptyQueryExpressionBody.class;
+        }
+
+        /**
+         * The singleton instance of {@link EmptyQueryExpressionBody}.
+         */
+        public static final EmptyQueryExpressionBody INSTANCE = new EmptyQueryExpressionBody();
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QueryExpressionBodyActual.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QueryExpressionBodyActual.java
new file mode 100644
index 0000000..857aa16
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QueryExpressionBodyActual.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+/**
+ * This is common interface for a query, which is either one {@code SELECT} statement, or many {@code SELECT} statements
+ * joined together with {@link SetOperation}s.
+ *
+ * @author Stanislav Muhametsin
+ * @see QuerySpecification
+ */
+public interface QueryExpressionBodyActual
+    extends QueryExpressionBody
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QueryExpressionBodyBinary.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QueryExpressionBodyBinary.java
new file mode 100644
index 0000000..cc1e211
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QueryExpressionBodyBinary.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+
+/**
+ * This syntax element represents two queries which have a set operation ({@code UNION}, {@code INTERSECT}, or
+ * {@code EXCEPT}) between them.
+ *
+ * @author Stanislav Muhametsin
+ * @see SetOperation
+ */
+public interface QueryExpressionBodyBinary
+    extends QueryExpressionBodyActual
+{
+    /**
+     * Returns the set operation to put between queries.
+     *
+     * @return The set operation to put between queries.
+     * @see SetOperation
+     */
+    SetOperation getSetOperation();
+
+    /**
+     * Returns the correspondence columns.
+     *
+     * @return The correspondence columns.
+     * @see CorrespondingSpec
+     */
+    CorrespondingSpec getCorrespondingColumns();
+
+    /**
+     * Returns the query on the left side of the set operation.
+     *
+     * @return The query on the left side of the set operation.
+     */
+    QueryExpressionBody getLeft();
+
+    /**
+     * Returns the query on the right side of the set operation.
+     *
+     * @return The query on the right side of the set operation.
+     */
+    QueryExpressionBody getRight();
+
+    /**
+     * Returns the set quantifier for the set operation.
+     *
+     * @return The set quantifier for the set operation.
+     * @see SetQuantifier
+     */
+    SetQuantifier getSetQuantifier();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QueryExpressionBodyQuery.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QueryExpressionBodyQuery.java
new file mode 100644
index 0000000..f25637a
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QueryExpressionBodyQuery.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+/**
+ * This syntax element represents the single query (currently only {@code SELECT} statement, represented by
+ * {@link QuerySpecification}.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface QueryExpressionBodyQuery
+    extends QueryExpressionBodyActual
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QuerySpecification.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QuerySpecification.java
new file mode 100644
index 0000000..b35be17
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/QuerySpecification.java
@@ -0,0 +1,95 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.QuerySpecificationBuilder;
+
+/**
+ * This syntax element represents the single {@code SELECT} statement.
+ *
+ * @author Stanislav Muhametsin
+ * @see QuerySpecificationBuilder
+ * @see SelectColumnClause
+ * @see FromClause
+ * @see BooleanExpression
+ * @see GroupByClause
+ * @see OrderByClause
+ */
+public interface QuerySpecification
+    extends QueryExpressionBodyQuery
+{
+
+    /**
+     * Returns the columns in this {@code SELECT} statement.
+     *
+     * @return The columns in this {@code SELECT} statement.
+     */
+    SelectColumnClause getColumns();
+
+    /**
+     * Returns the {@code FROM} clause of this {@code SELECT} statement.
+     *
+     * @return The {@code FROM} clause of this {@code SELECT} statement.
+     */
+    FromClause getFrom();
+
+    /**
+     * Returns the search condition for resulting rows of this {@code SELECT} statement.
+     *
+     * @return The search condition for resulting rows of this {@code SELECT} statement.
+     */
+    BooleanExpression getWhere();
+
+    /**
+     * Returns the {@code GROUP BY} clause of this {@code SELECT} statement.
+     *
+     * @return The {@code GROUP BY} clause of this {@code SELECT} statement.
+     */
+    GroupByClause getGroupBy();
+
+    /**
+     * Returns the grouping condition for {@code GROUP BY} clause of this {@code SELECT} statement.
+     *
+     * @return The grouping condition for {@code GROUP BY} clause of this {@code SELECT} statement.
+     */
+    BooleanExpression getHaving();
+
+    /**
+     * Returns the {@code ORDER BY} clause of this {@code SELECT} statement.
+     *
+     * @return The {@code ORDER BY} clause of this {@code SELECT} statement.
+     */
+    OrderByClause getOrderBy();
+
+    /**
+     * Returns the {@code FETCH FIRST <number> ROWS ONLY} expression for this {@code SELECT} statement.
+     *
+     * @return The {@code FETCH FIRST <number> ROWS ONLY} expression for this {@code SELECT} statement.
+     */
+    LimitSpecification getLimitSpecification();
+
+    /**
+     * Returns the {@code OFFSET <number> ROWS} expression for this {@code SELECT} statement.
+     *
+     * @return The {@code OFFSET <number> ROWS} expression for this {@code SELECT} statement.
+     */
+    OffsetSpecification getOffsetSpecification();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/RowDefinition.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/RowDefinition.java
new file mode 100644
index 0000000..dcdf6bb
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/RowDefinition.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+
+/**
+ * This syntax element represents a comma-separated row value definition of {@code VALUES} expression in query.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface RowDefinition
+    extends RowValueConstructor
+{
+
+    List<ValueExpression> getRowElements();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/RowSubQuery.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/RowSubQuery.java
new file mode 100644
index 0000000..7b1628f
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/RowSubQuery.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+/**
+ * This syntax element represents subquery in {@code VALUES} expression in query.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface RowSubQuery
+    extends RowValueConstructor
+{
+
+    QueryExpression getQueryExpression();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/RowValueConstructor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/RowValueConstructor.java
new file mode 100644
index 0000000..89827b9
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/RowValueConstructor.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This syntax elements represents either subquery or parenthesized row definition of {@code VALUES} expression in
+ * query.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface RowValueConstructor
+    extends Typeable<RowValueConstructor>
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/SelectColumnClause.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/SelectColumnClause.java
new file mode 100644
index 0000000..1b111e3
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/SelectColumnClause.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+
+/**
+ * This is common interface for columns of {@code SELECT} statement.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SelectColumnClause
+    extends Typeable<SelectColumnClause>
+{
+    /**
+     * Returns the set quantifier for the columns of {@code SELECT} statement.
+     *
+     * @return The set quantifier for the columns of {@code SELECT} statement.
+     * @see SetQuantifier
+     */
+    SetQuantifier getSetQuantifier();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/SetOperation.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/SetOperation.java
new file mode 100644
index 0000000..259eec2
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/SetOperation.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+/**
+ * This enum represents the possible set operations to combine queries with. These set operations are {@link #UNION},
+ * {@link #INTERSECT}, and {@link #EXCEPT}.
+ *
+ * @author Stanislav Muhametsin
+ */
+public final class SetOperation
+{
+    /**
+     * The {@code UNION} between two queries.
+     */
+    public static final SetOperation UNION = new SetOperation();
+
+    /**
+     * The {@code INTERSECT} between two queries.
+     */
+    public static final SetOperation INTERSECT = new SetOperation();
+
+    /**
+     * The set difference ({@code EXCEPT}) between two queries.
+     */
+    public static final SetOperation EXCEPT = new SetOperation();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/SortSpecification.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/SortSpecification.java
new file mode 100644
index 0000000..2a59780
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/SortSpecification.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+
+/**
+ * This syntax element represents the sort specification used in {@code ORDER BY} clause.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface SortSpecification
+    extends Typeable<SortSpecification>
+{
+    /**
+     * Returns the {@link Ordering} of this sort specification.
+     *
+     * @return The {@link Ordering} of this sort specification.
+     */
+    Ordering getOrderingSpecification();
+
+    /**
+     * The value expression, which may be a column reference, for example.
+     *
+     * @return The value expression of this sort specification.
+     */
+    ValueExpression getValueExpression();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableAlias.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableAlias.java
new file mode 100644
index 0000000..3d85359
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableAlias.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+
+/**
+ * This syntax element represents the alias for a table. Table alias may have additional list of column aliases.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface TableAlias
+    extends Typeable<TableAlias>
+{
+
+    /**
+     * Returns an alias for a table name.
+     *
+     * @return The alias for the table name.
+     */
+    String getTableAlias();
+
+    /**
+     * Returns aliases for columns in the original table.
+     *
+     * @return Aliases for columns in the original table. May be {@code null}.
+     */
+    ColumnNameList getColumnAliases();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableReference.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableReference.java
new file mode 100644
index 0000000..90998a6
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableReference.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinedTable;
+
+/**
+ * This is common interface for all table references in {@code FROM} clause.
+ *
+ * @author Stanislav Muhametsin
+ * @see FromClause
+ * @see TableReferencePrimary
+ * @see JoinedTable
+ */
+public interface TableReference
+{
+    /**
+     * Helper method to cast this object into {@link Typeable}.
+     *
+     * @return This object.
+     */
+    Typeable<?> asTypeable();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableReferenceByExpression.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableReferenceByExpression.java
new file mode 100644
index 0000000..403c7a6
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableReferenceByExpression.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+/**
+ * This syntax element represents the sub-query which acts as a table in {@code FROM} clause.
+ *
+ * @author Stanislav Muhametsin
+ * @see FromClause
+ * @see QueryExpression
+ */
+public interface TableReferenceByExpression
+    extends TableReferencePrimary
+{
+
+    /**
+     * Returns the query to use.
+     *
+     * @return The query to use.
+     */
+    QueryExpression getQuery();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableReferenceByName.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableReferenceByName.java
new file mode 100644
index 0000000..432e982
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableReferenceByName.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import org.apache.polygene.library.sql.generator.grammar.common.TableName;
+
+/**
+ * This syntax element represents the reference to a table in {@code FROM} clause.
+ *
+ * @author Stanislav Muhametsin
+ * @see TableName
+ */
+public interface TableReferenceByName
+    extends TableReferencePrimary
+{
+    /**
+     * Returns the table name.
+     *
+     * @return The table name.
+     * @see TableName
+     */
+    TableName getTableName();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableReferencePrimary.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableReferencePrimary.java
new file mode 100644
index 0000000..aa71ad8
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableReferencePrimary.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This is common interface for non-joined table references.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface TableReferencePrimary
+    extends TableReference, Typeable<TableReferencePrimary>
+{
+
+    /**
+     * Returns the alias for this table.
+     *
+     * @return The alias for this table.
+     * @see TableAlias
+     */
+    TableAlias getTableAlias();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableValueConstructor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableValueConstructor.java
new file mode 100644
index 0000000..5f5a967
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/TableValueConstructor.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query;
+
+import java.util.List;
+
+/**
+ * This syntax element represents the {@code VALUES} expression in query.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface TableValueConstructor
+    extends QueryExpressionBodyActual
+{
+    List<RowValueConstructor> getRows();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/CrossJoinedTable.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/CrossJoinedTable.java
new file mode 100644
index 0000000..2be150a
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/CrossJoinedTable.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query.joins;
+
+/**
+ * This syntax element represents the cross join ({@code CROSS JOIN} between two tables.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface CrossJoinedTable
+    extends JoinedTable
+{
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/JoinCondition.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/JoinCondition.java
new file mode 100644
index 0000000..caab8cb
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/JoinCondition.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query.joins;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+
+/**
+ * This syntax element represents the join condition, used in {@link QualifiedJoinedTable}.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface JoinCondition
+    extends JoinSpecification
+{
+
+    /**
+     * Returns the join condition for the {@link QualifiedJoinedTable}.
+     *
+     * @return The join condition for the {@link QualifiedJoinedTable}.
+     */
+    BooleanExpression getSearchConidition();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/JoinSpecification.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/JoinSpecification.java
new file mode 100644
index 0000000..b13dcc4
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/JoinSpecification.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query.joins;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This is common interface for join specification used in {@link QualifiedJoinedTable}.
+ *
+ * @author Stanislav Muhametsin
+ * @see JoinCondition
+ * @see NamedColumnsJoin
+ */
+public interface JoinSpecification
+    extends Typeable<JoinSpecification>
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/JoinType.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/JoinType.java
new file mode 100644
index 0000000..cfbd3ac
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/JoinType.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query.joins;
+
+/**
+ * This enum represents the join type, used in {@link QualifiedJoinedTable} and {@link NaturalJoinedTable}. Is one of
+ * {@link #INNER}, {@link #LEFT_OUTER}, {@link #RIGHT_OUTER}, or {@link #FULL_OUTER}.
+ *
+ * @author Stanislav Muhametsin
+ */
+public final class JoinType
+{
+    /**
+     * The {@code INNER} join, typically default.
+     */
+    public static final JoinType INNER = new JoinType();
+
+    /**
+     * The {@code LEFT OUTER} join.
+     */
+    public static final JoinType LEFT_OUTER = new JoinType();
+
+    /**
+     * The {@code RIGHT OUTER} join.
+     */
+    public static final JoinType RIGHT_OUTER = new JoinType();
+
+    /**
+     * The {@code FULL OUTER} join.
+     */
+    public static final JoinType FULL_OUTER = new JoinType();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/JoinedTable.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/JoinedTable.java
new file mode 100644
index 0000000..ddc1300
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/JoinedTable.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query.joins;
+
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBody;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReference;
+
+/**
+ * This is common interface for joined tables.
+ *
+ * @author Stanislav Muhametsin
+ * @see CrossJoinedTable
+ * @see NaturalJoinedTable
+ * @see QualifiedJoinedTable
+ * @see UnionJoinedTable
+ */
+public interface JoinedTable
+    extends QueryExpressionBody, TableReference
+{
+    /**
+     * Returns the table on the left side of the join.
+     *
+     * @return The table on the left side of the join.
+     */
+    TableReference getLeft();
+
+    /**
+     * Gets the table on the right side of the join.
+     *
+     * @return The table on the right side of the join.
+     */
+    TableReference getRight();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/NamedColumnsJoin.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/NamedColumnsJoin.java
new file mode 100644
index 0000000..a018ce1
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/NamedColumnsJoin.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query.joins;
+
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+
+/**
+ * This syntax element represents the join based on same-named columns in two tables having same value. Used in
+ * {@link QualifiedJoinedTable}.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface NamedColumnsJoin
+    extends JoinSpecification
+{
+
+    /**
+     * Returns the column names. Might be {@code null}.
+     *
+     * @return The column names. Might be {@code null}.
+     */
+    ColumnNameList getColumnNames();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/NaturalJoinedTable.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/NaturalJoinedTable.java
new file mode 100644
index 0000000..064aba1
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/NaturalJoinedTable.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query.joins;
+
+/**
+ * This syntax element represents the {@code NATURAL JOIN} between two tables.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface NaturalJoinedTable
+    extends JoinedTable
+{
+
+    /**
+     * Returns the join type for this {@code NATURAL JOIN}.
+     *
+     * @return The join type for this {@code NATURAL JOIN}.
+     */
+    JoinType getJoinType();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/QualifiedJoinedTable.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/QualifiedJoinedTable.java
new file mode 100644
index 0000000..6525b4c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/QualifiedJoinedTable.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query.joins;
+
+/**
+ * This syntax element represents the qualified join ({@code JOIN} between two tables.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface QualifiedJoinedTable
+    extends JoinedTable
+{
+    /**
+     * Returns the join type for this {@code JOIN}.
+     *
+     * @return The join type for this {@code JOIN}.
+     * @see JoinType
+     */
+    JoinType getJoinType();
+
+    /**
+     * Returns the join specification for this {@code JOIN}.
+     *
+     * @return The join specification for this {@code JOIN}.
+     * @see JoinSpecification
+     */
+    JoinSpecification getJoinSpecification();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/UnionJoinedTable.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/UnionJoinedTable.java
new file mode 100644
index 0000000..c04263e
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/UnionJoinedTable.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.library.sql.generator.grammar.query.joins;
+
+/**
+ * This syntax element represents the {@code UNION JOIN} between two tables.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface UnionJoinedTable
+    extends JoinedTable
+{
+
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/package-info.java
new file mode 100644
index 0000000..4ca3d8b
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/joins/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This package provides syntax interfaces for joined tables, mostly used in {@code FROM} clause.
+ */
+package org.apache.polygene.library.sql.generator.grammar.query.joins;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/package-info.java
new file mode 100644
index 0000000..2f30389
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/grammar/query/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This package and its sub-package contain elements related to SQL queries ({@code SELECT} statements).
+ */
+package org.apache.polygene.library.sql.generator.grammar.query;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/TypeableImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/TypeableImpl.java
new file mode 100644
index 0000000..8b36b64
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/TypeableImpl.java
@@ -0,0 +1,104 @@
+/*
+ *  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.polygene.library.sql.generator.implementation;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * This is base class for all classes implementing sub-types of {@link Typeable}. It is meant to be extended by actual
+ * domain-specific classes implementing the API interfaces/classes inherited from {@link Typeable}. For simple usecases,
+ * typically {@code <ImplementedType>} and {@code <RealImplementedType>} are both the same.
+ *
+ * @param <ImplementedType>     The base type for API interface or class.
+ * @param <RealImplementedType> The actual, possibly extended in other project, type of API interface or class. This is
+ *                              useful when one has a complex and extendable type hierarchy and wants the implementation class to be
+ *                              extendable as well.
+ * @author Stanislav Muhametsin
+ */
+public abstract class TypeableImpl<ImplementedType extends Typeable<?>, RealImplementedType extends ImplementedType>
+    implements Typeable<ImplementedType>
+{
+
+    /**
+     * The implemented API type of this object.
+     */
+    private final Class<? extends RealImplementedType> _expressionClass;
+
+    /**
+     * Constructs new base implementation for {@link Typeable}.
+     *
+     * @param realImplementingType The API type, which this specific instance implements. Must not be null.
+     * @throws IllegalArgumentException If the {@code realImplementingType} is {@code null}.
+     */
+    protected TypeableImpl( Class<? extends RealImplementedType> realImplementingType )
+    {
+        if( realImplementingType == null )
+        {
+            throw new IllegalArgumentException( "The implemented type can not be null." );
+        }
+
+        this._expressionClass = realImplementingType;
+    }
+
+    /**
+     */
+    public Class<? extends RealImplementedType> getImplementedType()
+    {
+        return this._expressionClass;
+    }
+
+    /**
+     * This {@link Typeable} equals to {@code obj}, when {@code this} == {@code obj}, OR when {@code obj} is not null,
+     * and {@code obj} is instance of {@link Typeable}, and this.{@link #getImplementedType()} returns SAME type as
+     * {@code obj}. {@link #getImplementedType()}, and {@code this}.{@link #doesEqual(Typeable)} returns {@code true}
+     * when given {@code obj}.
+     */
+    @Override
+    public boolean equals( Object obj )
+    {
+        return this == obj
+               || ( obj != null && obj instanceof Typeable<?>
+                    && this.getImplementedType().equals( ( (Typeable<?>) obj ).getImplementedType() ) && this
+                        .doesEqual( this._expressionClass.cast( obj ) ) );
+    }
+
+    /**
+     * Override this method to test equaling to other objects implementing same API type as this.
+     *
+     * @param another Another object implementing same API type as {@code this}. Is guaranteed to be non-null and
+     *                different reference than {@code this}, when called by {@code Typeable#equals(Object)}.
+     * @return {@code true} if this object equals to {@code another}; false otherwise.
+     */
+    protected abstract boolean doesEqual( RealImplementedType another );
+
+    /**
+     * Helper method to check that either both arguments are {@code null}s, or one is non-null and equals to another.
+     * Note that this method fails if {@code one.equals(another)} fails when {@code another} is null.
+     *
+     * @param <T>     The type of objects.
+     * @param one     First object to check.
+     * @param another Second object to check.
+     * @return {@code (one == null && another == null) || (one != null && one.equals( another ))}.
+     */
+    public static final <T> boolean bothNullOrEquals( T one, T another )
+    {
+        return ( one == null && another == null ) || ( one != null && one.equals( another ) );
+    }
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/AbstractBooleanExpression.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/AbstractBooleanExpression.java
new file mode 100644
index 0000000..d2485f6
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/AbstractBooleanExpression.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class AbstractBooleanExpression<ExpressionType extends BooleanExpression> extends
+                                                                                          SQLSyntaxElementBase<ValueExpression, ExpressionType>
+    implements BooleanExpression
+{
+
+    protected AbstractBooleanExpression( SQLProcessorAggregator processor,
+                                         Class<? extends ExpressionType> expressionClass )
+    {
+        super( processor, expressionClass );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/BetweenPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/BetweenPredicateImpl.java
new file mode 100644
index 0000000..e5bdb8e
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/BetweenPredicateImpl.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.BetweenPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class BetweenPredicateImpl extends MultiPredicateImpl<BetweenPredicate>
+    implements BetweenPredicate
+{
+    public BetweenPredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression left,
+                                 NonBooleanExpression minimum, NonBooleanExpression maximum )
+    {
+        this( processor, BetweenPredicate.class, left, minimum, maximum );
+    }
+
+    protected BetweenPredicateImpl( SQLProcessorAggregator processor, Class<? extends BetweenPredicate> predicateClass,
+                                    NonBooleanExpression left, NonBooleanExpression minimum, NonBooleanExpression maximum )
+    {
+        super( processor, predicateClass, left, minimum, maximum );
+    }
+
+    public NonBooleanExpression getMaximum()
+    {
+        return this.getRights().get( 1 );
+    }
+
+    public NonBooleanExpression getMinimum()
+    {
+        return this.getRights().get( 0 );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/BinaryPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/BinaryPredicateImpl.java
new file mode 100644
index 0000000..af0d1f1
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/BinaryPredicateImpl.java
@@ -0,0 +1,65 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BinaryPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class BinaryPredicateImpl<ExpressionType extends BinaryPredicate> extends
+                                                                                  AbstractBooleanExpression<ExpressionType>
+    implements BinaryPredicate
+{
+
+    private final NonBooleanExpression _left;
+
+    private final NonBooleanExpression _right;
+
+    protected BinaryPredicateImpl( SQLProcessorAggregator processor, Class<? extends ExpressionType> expressionClass,
+                                   NonBooleanExpression left, NonBooleanExpression right )
+    {
+        super( processor, expressionClass );
+        Objects.requireNonNull( left, "left" );
+        Objects.requireNonNull( right, "right" );
+
+        this._left = left;
+        this._right = right;
+    }
+
+    public NonBooleanExpression getLeft()
+    {
+        return this._left;
+    }
+
+    public NonBooleanExpression getRight()
+    {
+        return this._right;
+    }
+
+    @Override
+    protected boolean doesEqual( ExpressionType another )
+    {
+        return this._left.equals( another.getLeft() ) && this._right.equals( another.getRight() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/BooleanTestImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/BooleanTestImpl.java
new file mode 100644
index 0000000..61cc960
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/BooleanTestImpl.java
@@ -0,0 +1,82 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanTest;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class BooleanTestImpl extends ComposedBooleanExpressionImpl<BooleanTest>
+    implements BooleanTest
+{
+
+    private final BooleanExpression _booleanExpression;
+    private final TestType _testType;
+    private final TruthValue _truthValue;
+
+    public BooleanTestImpl( SQLProcessorAggregator processor, BooleanExpression expression, TestType testType,
+                            TruthValue truthValue )
+    {
+        this( processor, BooleanTest.class, expression, testType, truthValue );
+    }
+
+    protected BooleanTestImpl( SQLProcessorAggregator processor, Class<? extends BooleanTest> expressionClass,
+                               BooleanExpression expression, TestType testType, TruthValue truthValue )
+    {
+        super( processor, expressionClass );
+
+        Objects.requireNonNull( expression, "expression" );
+
+        if( BooleanUtils.isEmpty( expression ) )
+        {
+            throw new IllegalArgumentException( "Boolean test must be on something." );
+        }
+
+        this._booleanExpression = expression;
+        this._testType = testType;
+        this._truthValue = truthValue;
+    }
+
+    public BooleanExpression getBooleanExpression()
+    {
+        return this._booleanExpression;
+    }
+
+    public TestType getTestType()
+    {
+        return this._testType;
+    }
+
+    public TruthValue getTruthValue()
+    {
+        return this._truthValue;
+    }
+
+    public Iterator<BooleanExpression> iterator()
+    {
+        return Arrays.asList( this._booleanExpression ).iterator();
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/BooleanUtils.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/BooleanUtils.java
new file mode 100644
index 0000000..a5d797a
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/BooleanUtils.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.booleans.ComposedBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Predicate.EmptyPredicate;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class BooleanUtils
+{
+
+    public static Boolean isEmpty( BooleanExpression expression )
+    {
+        Boolean result = expression == EmptyPredicate.INSTANCE;
+        if( !result && expression instanceof ComposedBooleanExpression )
+        {
+            for( BooleanExpression exp : (ComposedBooleanExpression) expression )
+            {
+                result = isEmpty( exp );
+                if( !result )
+                {
+                    break;
+                }
+            }
+        }
+
+        return result;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/ComposedBooleanExpressionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/ComposedBooleanExpressionImpl.java
new file mode 100644
index 0000000..bb00466
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/ComposedBooleanExpressionImpl.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import java.util.Iterator;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.booleans.ComposedBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class ComposedBooleanExpressionImpl<ExpressionType extends ComposedBooleanExpression> extends
+                                                                                                      AbstractBooleanExpression<ExpressionType>
+    implements ComposedBooleanExpression
+{
+
+    protected ComposedBooleanExpressionImpl( SQLProcessorAggregator processor,
+                                             Class<? extends ExpressionType> expressionClass )
+    {
+        super( processor, expressionClass );
+    }
+
+    @Override
+    protected boolean doesEqual( ExpressionType another )
+    {
+        Iterator<BooleanExpression> thisIter = this.iterator();
+        Iterator<BooleanExpression> anotherIter = another.iterator();
+        Boolean prevResult = true;
+        while( thisIter.hasNext() && anotherIter.hasNext() && prevResult )
+        {
+            prevResult = thisIter.next().equals( anotherIter.next() );
+        }
+
+        return !thisIter.hasNext() && !anotherIter.hasNext() && prevResult;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/ConjunctionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/ConjunctionImpl.java
new file mode 100644
index 0000000..d96f6d1
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/ConjunctionImpl.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Conjunction;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ConjunctionImpl extends ComposedBooleanExpressionImpl<Conjunction>
+    implements Conjunction
+{
+
+    private final BooleanExpression _left;
+
+    private final BooleanExpression _right;
+
+    public ConjunctionImpl( SQLProcessorAggregator processor, BooleanExpression left, BooleanExpression right )
+    {
+        this( processor, Conjunction.class, left, right );
+    }
+
+    protected ConjunctionImpl( SQLProcessorAggregator processor, Class<? extends Conjunction> expressionClass,
+                               BooleanExpression left, BooleanExpression right )
+    {
+        super( processor, expressionClass );
+        Objects.requireNonNull( left, "left" );
+        Objects.requireNonNull( right, "right" );
+
+        this._left = left;
+        this._right = right;
+    }
+
+    public BooleanExpression getLeft()
+    {
+        return this._left;
+    }
+
+    public BooleanExpression getRight()
+    {
+        return this._right;
+    }
+
+    public Iterator<BooleanExpression> iterator()
+    {
+        return Arrays.asList( this._left, this._right ).iterator();
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/DisjunctionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/DisjunctionImpl.java
new file mode 100644
index 0000000..c8e507f
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/DisjunctionImpl.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Disjunction;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DisjunctionImpl extends ComposedBooleanExpressionImpl<Disjunction>
+    implements Disjunction
+{
+
+    private final BooleanExpression _left;
+
+    private final BooleanExpression _right;
+
+    public DisjunctionImpl( SQLProcessorAggregator processor, BooleanExpression left, BooleanExpression right )
+    {
+        this( processor, Disjunction.class, left, right );
+    }
+
+    protected DisjunctionImpl( SQLProcessorAggregator processor, Class<? extends Disjunction> expressionClass,
+                               BooleanExpression left, BooleanExpression right )
+    {
+        super( processor, expressionClass );
+        Objects.requireNonNull( left, "left" );
+        Objects.requireNonNull( right, "right" );
+
+        this._left = left;
+        this._right = right;
+    }
+
+    public BooleanExpression getLeft()
+    {
+        return this._left;
+    }
+
+    public BooleanExpression getRight()
+    {
+        return this._right;
+    }
+
+    public Iterator<BooleanExpression> iterator()
+    {
+        return Arrays.asList( this._left, this._right ).iterator();
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/EqualsPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/EqualsPredicateImpl.java
new file mode 100644
index 0000000..7668478
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/EqualsPredicateImpl.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.EqualsPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class EqualsPredicateImpl extends BinaryPredicateImpl<EqualsPredicate>
+    implements EqualsPredicate
+{
+
+    public EqualsPredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression left, NonBooleanExpression right )
+    {
+        this( processor, EqualsPredicate.class, left, right );
+    }
+
+    protected EqualsPredicateImpl( SQLProcessorAggregator processor, Class<? extends EqualsPredicate> predicateClass,
+                                   NonBooleanExpression left, NonBooleanExpression right )
+    {
+        super( processor, predicateClass, left, right );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/ExistsPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/ExistsPredicateImpl.java
new file mode 100644
index 0000000..44c1623
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/ExistsPredicateImpl.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.ExistsPredicate;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ExistsPredicateImpl extends UnaryPredicateImpl<ExistsPredicate>
+    implements ExistsPredicate
+{
+
+    public ExistsPredicateImpl( SQLProcessorAggregator processor, QueryExpression query )
+    {
+        this( processor, ExistsPredicate.class, query );
+    }
+
+    protected ExistsPredicateImpl( SQLProcessorAggregator processor, Class<? extends ExistsPredicate> predicateClass,
+                                   QueryExpression query )
+    {
+        super( processor, predicateClass, query );
+    }
+
+    @Override
+    public QueryExpression getValueExpression()
+    {
+        return (QueryExpression) super.getValueExpression();
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/GreaterOrEqualPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/GreaterOrEqualPredicateImpl.java
new file mode 100644
index 0000000..8b8f582
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/GreaterOrEqualPredicateImpl.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.GreaterOrEqualPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class GreaterOrEqualPredicateImpl extends BinaryPredicateImpl<GreaterOrEqualPredicate>
+    implements GreaterOrEqualPredicate
+{
+
+    public GreaterOrEqualPredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression left,
+                                        NonBooleanExpression right )
+    {
+        this( processor, GreaterOrEqualPredicate.class, left, right );
+    }
+
+    protected GreaterOrEqualPredicateImpl( SQLProcessorAggregator processor,
+                                           Class<? extends GreaterOrEqualPredicate> predicateClass, NonBooleanExpression left, NonBooleanExpression right )
+    {
+        super( processor, predicateClass, left, right );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/GreaterThanPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/GreaterThanPredicateImpl.java
new file mode 100644
index 0000000..3fa3b62
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/GreaterThanPredicateImpl.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.GreaterThanPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class GreaterThanPredicateImpl extends BinaryPredicateImpl<GreaterThanPredicate>
+    implements GreaterThanPredicate
+{
+
+    public GreaterThanPredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression left,
+                                     NonBooleanExpression right )
+    {
+        this( processor, GreaterThanPredicate.class, left, right );
+    }
+
+    protected GreaterThanPredicateImpl( SQLProcessorAggregator processor,
+                                        Class<? extends GreaterThanPredicate> predicateClass, NonBooleanExpression left, NonBooleanExpression right )
+    {
+        super( processor, predicateClass, left, right );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/InPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/InPredicateImpl.java
new file mode 100644
index 0000000..159c1a2
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/InPredicateImpl.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.booleans.InPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class InPredicateImpl extends MultiPredicateImpl<InPredicate>
+    implements InPredicate
+{
+
+    public InPredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression left,
+                            List<NonBooleanExpression> rights )
+    {
+        this( processor, InPredicate.class, left, rights );
+    }
+
+    protected InPredicateImpl( SQLProcessorAggregator processor, Class<? extends InPredicate> predicateClass,
+                               NonBooleanExpression left, List<NonBooleanExpression> rights )
+    {
+        super( processor, predicateClass, left, rights );
+    }
+
+    public InPredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression left, NonBooleanExpression... rights )
+    {
+        this( processor, InPredicate.class, left, rights );
+    }
+
+    protected InPredicateImpl( SQLProcessorAggregator processor, Class<? extends InPredicate> predicateClass,
+                               NonBooleanExpression left, NonBooleanExpression... rights )
+    {
+        super( processor, predicateClass, left, rights );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/IsNotNullPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/IsNotNullPredicateImpl.java
new file mode 100644
index 0000000..eff8be0
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/IsNotNullPredicateImpl.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.IsNotNullPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class IsNotNullPredicateImpl extends UnaryPredicateImpl<IsNotNullPredicate>
+    implements IsNotNullPredicate
+{
+
+    public IsNotNullPredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression expression )
+    {
+        this( processor, IsNotNullPredicate.class, expression );
+    }
+
+    protected IsNotNullPredicateImpl( SQLProcessorAggregator processor,
+                                      Class<? extends IsNotNullPredicate> predicateClass, NonBooleanExpression expression )
+    {
+        super( processor, predicateClass, expression );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/IsNullPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/IsNullPredicateImpl.java
new file mode 100644
index 0000000..4dec363
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/IsNullPredicateImpl.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.IsNullPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class IsNullPredicateImpl extends UnaryPredicateImpl<IsNullPredicate>
+    implements IsNullPredicate
+{
+
+    public IsNullPredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression expression )
+    {
+        this( processor, IsNullPredicate.class, expression );
+    }
+
+    protected IsNullPredicateImpl( SQLProcessorAggregator processor, Class<? extends IsNullPredicate> predicateClass,
+                                   NonBooleanExpression expression )
+    {
+        super( processor, predicateClass, expression );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/LessOrEqualPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/LessOrEqualPredicateImpl.java
new file mode 100644
index 0000000..31b8f91
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/LessOrEqualPredicateImpl.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.LessOrEqualPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class LessOrEqualPredicateImpl extends BinaryPredicateImpl<LessOrEqualPredicate>
+    implements LessOrEqualPredicate
+{
+
+    public LessOrEqualPredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression left,
+                                     NonBooleanExpression right )
+    {
+        this( processor, LessOrEqualPredicate.class, left, right );
+    }
+
+    protected LessOrEqualPredicateImpl( SQLProcessorAggregator processor,
+                                        Class<? extends LessOrEqualPredicate> predicateClass, NonBooleanExpression left, NonBooleanExpression right )
+    {
+        super( processor, predicateClass, left, right );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/LessThanPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/LessThanPredicateImpl.java
new file mode 100644
index 0000000..feb1460
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/LessThanPredicateImpl.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.LessThanPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class LessThanPredicateImpl extends BinaryPredicateImpl<LessThanPredicate>
+    implements LessThanPredicate
+{
+
+    public LessThanPredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression left,
+                                  NonBooleanExpression right )
+    {
+        this( processor, LessThanPredicate.class, left, right );
+    }
+
+    protected LessThanPredicateImpl( SQLProcessorAggregator processor,
+                                     Class<? extends LessThanPredicate> predicateClass, NonBooleanExpression left, NonBooleanExpression right )
+    {
+        super( processor, predicateClass, left, right );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/LikePredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/LikePredicateImpl.java
new file mode 100644
index 0000000..a394ea0
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/LikePredicateImpl.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.LikePredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class LikePredicateImpl extends BinaryPredicateImpl<LikePredicate>
+    implements LikePredicate
+{
+
+    public LikePredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression left, NonBooleanExpression right )
+    {
+        this( processor, LikePredicate.class, left, right );
+    }
+
+    protected LikePredicateImpl( SQLProcessorAggregator processor, Class<? extends LikePredicate> predicateClass,
+                                 NonBooleanExpression left, NonBooleanExpression right )
+    {
+        super( processor, predicateClass, left, right );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/MultiPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/MultiPredicateImpl.java
new file mode 100644
index 0000000..ffdb5fc
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/MultiPredicateImpl.java
@@ -0,0 +1,79 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.booleans.MultiPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class MultiPredicateImpl<ExpressionType extends MultiPredicate> extends
+                                                                                AbstractBooleanExpression<ExpressionType>
+    implements MultiPredicate
+{
+
+    private final NonBooleanExpression _left;
+
+    private final List<NonBooleanExpression> _rights;
+
+    protected MultiPredicateImpl( SQLProcessorAggregator processor, Class<? extends ExpressionType> expressionClass,
+                                  NonBooleanExpression left, NonBooleanExpression... rights )
+    {
+        this( processor, expressionClass, left, Arrays.asList( rights ) );
+    }
+
+    protected MultiPredicateImpl( SQLProcessorAggregator processor, Class<? extends ExpressionType> expressionClass,
+                                  NonBooleanExpression left, List<NonBooleanExpression> rights )
+    {
+        super( processor, expressionClass );
+        Objects.requireNonNull( left, "left" );
+        Objects.requireNonNull( rights, "rights" );
+
+        for( NonBooleanExpression exp : rights )
+        {
+            Objects.requireNonNull( exp, "right" );
+        }
+
+        this._left = left;
+        this._rights = Collections.unmodifiableList( rights );
+    }
+
+    public NonBooleanExpression getLeft()
+    {
+        return this._left;
+    }
+
+    public List<NonBooleanExpression> getRights()
+    {
+        return this._rights;
+    }
+
+    @Override
+    protected boolean doesEqual( ExpressionType another )
+    {
+        return this._left.equals( another.getLeft() ) && this._rights.equals( another.getRights() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NegationImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NegationImpl.java
new file mode 100644
index 0000000..8e294ec
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NegationImpl.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Negation;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class NegationImpl extends ComposedBooleanExpressionImpl<Negation>
+    implements Negation
+{
+
+    private final BooleanExpression _negated;
+
+    public NegationImpl( SQLProcessorAggregator processor, BooleanExpression negated )
+    {
+        this( processor, Negation.class, negated );
+    }
+
+    protected NegationImpl( SQLProcessorAggregator processor, Class<? extends Negation> negationClass,
+                            BooleanExpression negated )
+    {
+        super( processor, negationClass );
+        Objects.requireNonNull( negated, "negated" );
+
+        this._negated = negated;
+    }
+
+    public BooleanExpression getNegated()
+    {
+        return this._negated;
+    }
+
+    public Iterator<BooleanExpression> iterator()
+    {
+        return Arrays.asList( this._negated ).iterator();
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NotBetweenPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NotBetweenPredicateImpl.java
new file mode 100644
index 0000000..d7b68ae
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NotBetweenPredicateImpl.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotBetweenPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class NotBetweenPredicateImpl extends MultiPredicateImpl<NotBetweenPredicate>
+    implements NotBetweenPredicate
+{
+
+    public NotBetweenPredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression left,
+                                    NonBooleanExpression minimum, NonBooleanExpression maximum )
+    {
+        this( processor, NotBetweenPredicate.class, left, minimum, maximum );
+    }
+
+    protected NotBetweenPredicateImpl( SQLProcessorAggregator processor,
+                                       Class<? extends NotBetweenPredicate> predicateClass, NonBooleanExpression left, NonBooleanExpression minimum,
+                                       NonBooleanExpression maximum )
+    {
+        super( processor, predicateClass, left, minimum, maximum );
+    }
+
+    public NonBooleanExpression getMaximum()
+    {
+        return this.getRights().get( 1 );
+    }
+
+    public NonBooleanExpression getMinimum()
+    {
+        return this.getRights().get( 0 );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NotEqualsPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NotEqualsPredicateImpl.java
new file mode 100644
index 0000000..5a7e858
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NotEqualsPredicateImpl.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotEqualsPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class NotEqualsPredicateImpl extends BinaryPredicateImpl<NotEqualsPredicate>
+    implements NotEqualsPredicate
+{
+
+    public NotEqualsPredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression left,
+                                   NonBooleanExpression right )
+    {
+        this( processor, NotEqualsPredicate.class, left, right );
+    }
+
+    protected NotEqualsPredicateImpl( SQLProcessorAggregator processor,
+                                      Class<? extends NotEqualsPredicate> predicateClass, NonBooleanExpression left, NonBooleanExpression right )
+    {
+        super( processor, predicateClass, left, right );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NotInPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NotInPredicateImpl.java
new file mode 100644
index 0000000..fe3a3af
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NotInPredicateImpl.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotInPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class NotInPredicateImpl extends MultiPredicateImpl<NotInPredicate>
+    implements NotInPredicate
+{
+
+    public NotInPredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression left,
+                               List<NonBooleanExpression> rights )
+    {
+        this( processor, NotInPredicate.class, left, rights );
+    }
+
+    protected NotInPredicateImpl( SQLProcessorAggregator processor, Class<? extends NotInPredicate> predicateClass,
+                                  NonBooleanExpression left, List<NonBooleanExpression> rights )
+    {
+        super( processor, predicateClass, left, rights );
+    }
+
+    public NotInPredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression left,
+                               NonBooleanExpression... rights )
+    {
+        this( processor, NotInPredicate.class, left, rights );
+    }
+
+    protected NotInPredicateImpl( SQLProcessorAggregator processor, Class<? extends NotInPredicate> predicateClass,
+                                  NonBooleanExpression left, NonBooleanExpression... rights )
+    {
+        super( processor, predicateClass, left, rights );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NotLikePredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NotLikePredicateImpl.java
new file mode 100644
index 0000000..0b18a78
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NotLikePredicateImpl.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotLikePredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class NotLikePredicateImpl extends BinaryPredicateImpl<NotLikePredicate>
+    implements NotLikePredicate
+{
+
+    public NotLikePredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression left, NonBooleanExpression right )
+    {
+        this( processor, NotLikePredicate.class, left, right );
+    }
+
+    protected NotLikePredicateImpl( SQLProcessorAggregator processor, Class<? extends NotLikePredicate> predicateClass,
+                                    NonBooleanExpression left, NonBooleanExpression right )
+    {
+        super( processor, predicateClass, left, right );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NotRegexpPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NotRegexpPredicateImpl.java
new file mode 100644
index 0000000..3f86c30
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/NotRegexpPredicateImpl.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotRegexpPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class NotRegexpPredicateImpl extends BinaryPredicateImpl<NotRegexpPredicate>
+    implements NotRegexpPredicate
+{
+
+    public NotRegexpPredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression left,
+                                   NonBooleanExpression right )
+    {
+        this( processor, NotRegexpPredicate.class, left, right );
+    }
+
+    protected NotRegexpPredicateImpl( SQLProcessorAggregator processor,
+                                      Class<? extends NotRegexpPredicate> predicateClass, NonBooleanExpression left, NonBooleanExpression right )
+    {
+        super( processor, predicateClass, left, right );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/RegexpPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/RegexpPredicateImpl.java
new file mode 100644
index 0000000..f725100
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/RegexpPredicateImpl.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.RegexpPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class RegexpPredicateImpl extends BinaryPredicateImpl<RegexpPredicate>
+    implements RegexpPredicate
+{
+
+    public RegexpPredicateImpl( SQLProcessorAggregator processor, NonBooleanExpression left, NonBooleanExpression right )
+    {
+        this( processor, RegexpPredicate.class, left, right );
+    }
+
+    protected RegexpPredicateImpl( SQLProcessorAggregator processor, Class<? extends RegexpPredicate> predicateClass,
+                                   NonBooleanExpression left, NonBooleanExpression right )
+    {
+        super( processor, predicateClass, left, right );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/UnaryPredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/UnaryPredicateImpl.java
new file mode 100644
index 0000000..3c26361
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/UnaryPredicateImpl.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.booleans.UnaryPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class UnaryPredicateImpl<ExpressionType extends UnaryPredicate> extends
+                                                                                AbstractBooleanExpression<ExpressionType>
+    implements UnaryPredicate
+{
+
+    private final NonBooleanExpression _expression;
+
+    public UnaryPredicateImpl( SQLProcessorAggregator processor, Class<? extends ExpressionType> expressionClass,
+                               NonBooleanExpression expression )
+    {
+        super( processor, expressionClass );
+        Objects.requireNonNull( expression, "expression" );
+
+        this._expression = expression;
+    }
+
+    public NonBooleanExpression getValueExpression()
+    {
+        return this._expression;
+    }
+
+    @Override
+    protected boolean doesEqual( ExpressionType another )
+    {
+        return this._expression.equals( another.getValueExpression() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/UniquePredicateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/UniquePredicateImpl.java
new file mode 100644
index 0000000..19f96fe
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/booleans/UniquePredicateImpl.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.booleans;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.UniquePredicate;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class UniquePredicateImpl extends UnaryPredicateImpl<UniquePredicate>
+    implements UniquePredicate
+{
+
+    public UniquePredicateImpl( SQLProcessorAggregator processor, QueryExpression query )
+    {
+        this( processor, UniquePredicate.class, query );
+    }
+
+    protected UniquePredicateImpl( SQLProcessorAggregator processor, Class<? extends UniquePredicate> predicateClass,
+                                   QueryExpression query )
+    {
+        super( processor, predicateClass, query );
+    }
+
+    @Override
+    public QueryExpression getValueExpression()
+    {
+        return (QueryExpression) super.getValueExpression();
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/booleans/BooleanBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/booleans/BooleanBuilderImpl.java
new file mode 100644
index 0000000..450e263
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/booleans/BooleanBuilderImpl.java
@@ -0,0 +1,83 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.booleans;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Predicate;
+import org.apache.polygene.library.sql.generator.grammar.builders.booleans.BooleanBuilder;
+import org.apache.polygene.library.sql.generator.grammar.factories.BooleanFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class BooleanBuilderImpl extends SQLBuilderBase
+    implements BooleanBuilder
+{
+
+    private BooleanExpression _topLevelExpression;
+
+    private final BooleanFactory _factory;
+
+    public BooleanBuilderImpl( SQLProcessorAggregator processor, BooleanFactory factory )
+    {
+        this( processor, factory, Predicate.EmptyPredicate.INSTANCE );
+    }
+
+    public BooleanBuilderImpl( SQLProcessorAggregator processor, BooleanFactory factory, BooleanExpression expression )
+    {
+        super( processor );
+        Objects.requireNonNull( factory, "boolean expression factory" );
+
+        this._factory = factory;
+        this._topLevelExpression = expression;
+    }
+
+    public BooleanBuilder and( BooleanExpression next )
+    {
+        this._topLevelExpression = this._factory.and( this._topLevelExpression, next );
+        return this;
+    }
+
+    public BooleanBuilder or( BooleanExpression next )
+    {
+        this._topLevelExpression = this._factory.or( this._topLevelExpression, next );
+        return this;
+    }
+
+    public BooleanBuilder not()
+    {
+        this._topLevelExpression = this._factory.not( this._topLevelExpression );
+        return this;
+    }
+
+    public BooleanBuilder reset( BooleanExpression newExpression )
+    {
+        this._topLevelExpression = newExpression;
+        return this;
+    }
+
+    public BooleanExpression createExpression()
+    {
+        return this._topLevelExpression == null ? Predicate.EmptyPredicate.INSTANCE : this._topLevelExpression;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/booleans/InBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/booleans/InBuilderImpl.java
new file mode 100644
index 0000000..9c6b290
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/booleans/InBuilderImpl.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.booleans;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.booleans.InPredicate;
+import org.apache.polygene.library.sql.generator.grammar.builders.booleans.InBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.InPredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class InBuilderImpl extends SQLBuilderBase
+    implements InBuilder
+{
+
+    private final NonBooleanExpression _left;
+
+    private final List<NonBooleanExpression> _expressions;
+
+    public InBuilderImpl( SQLProcessorAggregator processor, NonBooleanExpression left )
+    {
+        super( processor );
+        Objects.requireNonNull( left, "left" );
+
+        this._left = left;
+        this._expressions = new ArrayList<NonBooleanExpression>();
+    }
+
+    public InBuilder addValues( NonBooleanExpression... expressions )
+    {
+        Objects.requireNonNull( expressions, "expressions" );
+        for( NonBooleanExpression exp : expressions )
+        {
+            Objects.requireNonNull( exp, "expression" );
+        }
+
+        this._expressions.addAll( Arrays.asList( expressions ) );
+        return this;
+    }
+
+    public InPredicate createExpression()
+    {
+        return new InPredicateImpl( this.getProcessor(), this._left, this._expressions );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/ForeignKeyConstraintBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/ForeignKeyConstraintBuilderImpl.java
new file mode 100644
index 0000000..5d4051e
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/ForeignKeyConstraintBuilderImpl.java
@@ -0,0 +1,140 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.definition;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.ForeignKeyConstraintBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ForeignKeyConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.MatchType;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ReferentialAction;
+import org.apache.polygene.library.sql.generator.grammar.factories.ColumnsFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.definition.table.ForeignKeyConstraintImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ForeignKeyConstraintBuilderImpl extends SQLBuilderBase
+    implements ForeignKeyConstraintBuilder
+{
+
+    private final List<String> _sourceColumns;
+    private final List<String> _targetColumns;
+    private TableNameDirect _targetTable;
+    private MatchType _matchType;
+    private ReferentialAction _onUpdate;
+    private ReferentialAction _onDelete;
+
+    private final ColumnsFactory _c;
+
+    public ForeignKeyConstraintBuilderImpl( SQLProcessorAggregator processor, ColumnsFactory c )
+    {
+        super( processor );
+        Objects.requireNonNull( c, "Columns factory" );
+
+        this._c = c;
+
+        this._sourceColumns = new ArrayList<String>();
+        this._targetColumns = new ArrayList<String>();
+    }
+
+    public ForeignKeyConstraint createExpression()
+    {
+        return new ForeignKeyConstraintImpl( this.getProcessor(), this._c.colNames( this._sourceColumns ),
+                                             this._targetTable, this._targetColumns.size() == 0 ? null : this._c.colNames( this._targetColumns ),
+                                             this._matchType, this._onDelete, this._onUpdate );
+    }
+
+    public ForeignKeyConstraintBuilder addSourceColumns( String... columnNames )
+    {
+        for( String name : columnNames )
+        {
+            this._sourceColumns.add( name );
+        }
+        return this;
+    }
+
+    public ForeignKeyConstraintBuilder addTargetColumns( String... columnNames )
+    {
+        for( String name : columnNames )
+        {
+            this._targetColumns.add( name );
+        }
+        return this;
+    }
+
+    public ForeignKeyConstraintBuilder setTargetTableName( TableNameDirect tableName )
+    {
+        this._targetTable = tableName;
+        return this;
+    }
+
+    public ForeignKeyConstraintBuilder setMatchType( MatchType matchType )
+    {
+        this._matchType = matchType;
+        return this;
+    }
+
+    public ForeignKeyConstraintBuilder setOnUpdate( ReferentialAction action )
+    {
+        this._onUpdate = action;
+        return this;
+    }
+
+    public ForeignKeyConstraintBuilder setOnDelete( ReferentialAction action )
+    {
+        this._onDelete = action;
+        return this;
+    }
+
+    public List<String> getSourceColumns()
+    {
+        return this._sourceColumns;
+    }
+
+    public List<String> getTargetColumns()
+    {
+        return this._targetColumns;
+    }
+
+    public TableNameDirect getTableName()
+    {
+        return this._targetTable;
+    }
+
+    public MatchType getMatchType()
+    {
+        return this._matchType;
+    }
+
+    public ReferentialAction getOnUpdate()
+    {
+        return this._onUpdate;
+    }
+
+    public ReferentialAction getOnDelete()
+    {
+        return this._onDelete;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/SchemaDefinitionBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/SchemaDefinitionBuilderImpl.java
new file mode 100644
index 0000000..f8aa750
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/SchemaDefinitionBuilderImpl.java
@@ -0,0 +1,88 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.definition;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.SchemaDefinitionBuilder;
+import org.apache.polygene.library.sql.generator.grammar.definition.schema.SchemaDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.schema.SchemaElement;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.definition.schema.SchemaDefinitionImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class SchemaDefinitionBuilderImpl extends SQLBuilderBase
+    implements SchemaDefinitionBuilder
+{
+
+    private String _schemaName;
+    private String _schemaCharset;
+    private final List<SchemaElement> _elements;
+
+    public SchemaDefinitionBuilderImpl( SQLProcessorAggregator processor )
+    {
+        super( processor );
+        this._elements = new ArrayList<SchemaElement>();
+    }
+
+    public SchemaDefinition createExpression()
+    {
+        return new SchemaDefinitionImpl( this.getProcessor(), this._schemaName, this._schemaCharset, this._elements );
+    }
+
+    public SchemaDefinitionBuilder setSchemaName( String schemaName )
+    {
+        this._schemaName = schemaName;
+        return this;
+    }
+
+    public SchemaDefinitionBuilder setSchemaCharset( String charset )
+    {
+        this._schemaCharset = charset;
+        return this;
+    }
+
+    public SchemaDefinitionBuilder addSchemaElements( SchemaElement... elements )
+    {
+        for( SchemaElement el : elements )
+        {
+            this._elements.add( el );
+        }
+        return this;
+    }
+
+    public String getSchemaName()
+    {
+        return this._schemaName;
+    }
+
+    public String getSchemaCharset()
+    {
+        return this._schemaCharset;
+    }
+
+    public List<SchemaElement> getSchemaElements()
+    {
+        return this._elements;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/TableDefinitionBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/TableDefinitionBuilderImpl.java
new file mode 100644
index 0000000..d4f5241
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/TableDefinitionBuilderImpl.java
@@ -0,0 +1,98 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.definition;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.TableDefinitionBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableCommitAction;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableContentsSource;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableScope;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.definition.table.TableDefinitionImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TableDefinitionBuilderImpl extends SQLBuilderBase
+    implements TableDefinitionBuilder
+{
+
+    private TableScope _scope;
+    private TableNameDirect _name;
+    private TableCommitAction _commitAction;
+    private TableContentsSource _contents;
+
+    public TableDefinitionBuilderImpl( SQLProcessorAggregator processor )
+    {
+        super( processor );
+    }
+
+    public TableDefinition createExpression()
+    {
+        return new TableDefinitionImpl( this.getProcessor(), this._commitAction, this._contents, this._name,
+                                        this._scope );
+    }
+
+    public TableDefinitionBuilder setTableScope( TableScope scope )
+    {
+        this._scope = scope;
+        return this;
+    }
+
+    public TableDefinitionBuilder setTableName( TableNameDirect tableName )
+    {
+        this._name = tableName;
+        return this;
+    }
+
+    public TableDefinitionBuilder setCommitAction( TableCommitAction commitAction )
+    {
+        this._commitAction = commitAction;
+        return this;
+    }
+
+    public TableDefinitionBuilder setTableContentsSource( TableContentsSource contents )
+    {
+        this._contents = contents;
+        return this;
+    }
+
+    public TableScope getTableScope()
+    {
+        return this._scope;
+    }
+
+    public TableNameDirect getTableName()
+    {
+        return this._name;
+    }
+
+    public TableCommitAction getCommitAction()
+    {
+        return this._commitAction;
+    }
+
+    public TableContentsSource getTableContentsSource()
+    {
+        return this._contents;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/TableElementListBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/TableElementListBuilderImpl.java
new file mode 100644
index 0000000..0798a66
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/TableElementListBuilderImpl.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.definition;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.TableElementListBuilder;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableElement;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableElementList;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.definition.table.TableElementListImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TableElementListBuilderImpl extends SQLBuilderBase
+    implements TableElementListBuilder
+{
+
+    private final List<TableElement> _elements;
+
+    public TableElementListBuilderImpl( SQLProcessorAggregator processor )
+    {
+        super( processor );
+        this._elements = new ArrayList<TableElement>();
+    }
+
+    public TableElementList createExpression()
+    {
+        return new TableElementListImpl( this.getProcessor(), this._elements );
+    }
+
+    public TableElementListBuilder addTableElement( TableElement element )
+    {
+        this._elements.add( element );
+        return this;
+    }
+
+    public List<TableElement> getTableElements()
+    {
+        return this._elements;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/UniqueConstraintBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/UniqueConstraintBuilderImpl.java
new file mode 100644
index 0000000..9668a2c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/UniqueConstraintBuilderImpl.java
@@ -0,0 +1,83 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.definition;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.UniqueConstraintBuilder;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.UniqueConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.UniqueSpecification;
+import org.apache.polygene.library.sql.generator.grammar.factories.ColumnsFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.definition.table.UniqueConstraintImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class UniqueConstraintBuilderImpl extends SQLBuilderBase
+    implements UniqueConstraintBuilder
+{
+
+    private UniqueSpecification _uniqueness;
+    private final List<String> _columns;
+
+    private final ColumnsFactory _c;
+
+    public UniqueConstraintBuilderImpl( SQLProcessorAggregator processor, ColumnsFactory c )
+    {
+        super( processor );
+        Objects.requireNonNull( c, "Columns factory" );
+
+        this._c = c;
+        this._columns = new ArrayList<String>();
+    }
+
+    public UniqueConstraint createExpression()
+    {
+        return new UniqueConstraintImpl( this.getProcessor(), this._c.colNames( this._columns ), this._uniqueness );
+    }
+
+    public UniqueConstraintBuilder setUniqueness( UniqueSpecification uniqueness )
+    {
+        this._uniqueness = uniqueness;
+        return this;
+    }
+
+    public UniqueConstraintBuilder addColumns( String... columnNames )
+    {
+        for( String col : columnNames )
+        {
+            this._columns.add( col );
+        }
+        return this;
+    }
+
+    public UniqueSpecification getUniqueness()
+    {
+        return this._uniqueness;
+    }
+
+    public List<String> getColumns()
+    {
+        return this._columns;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/ViewDefinitionBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/ViewDefinitionBuilderImpl.java
new file mode 100644
index 0000000..f3dd53e
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/definition/ViewDefinitionBuilderImpl.java
@@ -0,0 +1,110 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.definition;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.ViewDefinitionBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.ViewCheckOption;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.ViewDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.ViewSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.definition.view.ViewDefinitionImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ViewDefinitionBuilderImpl extends SQLBuilderBase
+    implements ViewDefinitionBuilder
+{
+
+    private Boolean _isRecursive;
+    private TableNameDirect _name;
+    private QueryExpression _query;
+    private ViewCheckOption _viewCheck;
+    private ViewSpecification _viewSpec;
+
+    public ViewDefinitionBuilderImpl( SQLProcessorAggregator processor )
+    {
+        super( processor );
+    }
+
+    public ViewDefinition createExpression()
+    {
+        return new ViewDefinitionImpl( this.getProcessor(), this._name, this._query, this._viewSpec, this._viewCheck,
+                                       this._isRecursive );
+    }
+
+    public ViewDefinitionBuilder setRecursive( Boolean isRecursive )
+    {
+        this._isRecursive = isRecursive;
+        return this;
+    }
+
+    public ViewDefinitionBuilder setViewName( TableNameDirect viewName )
+    {
+        this._name = viewName;
+        return this;
+    }
+
+    public ViewDefinitionBuilder setQuery( QueryExpression query )
+    {
+        this._query = query;
+        return this;
+    }
+
+    public ViewDefinitionBuilder setViewCheckOption( ViewCheckOption viewCheck )
+    {
+        this._viewCheck = viewCheck;
+        return this;
+    }
+
+    public ViewDefinitionBuilder setViewSpecification( ViewSpecification spec )
+    {
+        this._viewSpec = spec;
+        return this;
+    }
+
+    public Boolean isRecursive()
+    {
+        return this._isRecursive;
+    }
+
+    public TableNameDirect getViewName()
+    {
+        return this._name;
+    }
+
+    public QueryExpression getQueryExpression()
+    {
+        return this._query;
+    }
+
+    public ViewCheckOption getViewCheckOption()
+    {
+        return this._viewCheck;
+    }
+
+    public ViewSpecification getViewSpecification()
+    {
+        return this._viewSpec;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/modification/ColumnSourceByValuesBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/modification/ColumnSourceByValuesBuilderImpl.java
new file mode 100644
index 0000000..f106dbf
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/modification/ColumnSourceByValuesBuilderImpl.java
@@ -0,0 +1,93 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.modification;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.ColumnSourceByValuesBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSourceByValues;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.ColumnNameListImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.modification.ColumnSourceByValuesImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ColumnSourceByValuesBuilderImpl extends SQLBuilderBase
+    implements ColumnSourceByValuesBuilder
+{
+
+    private final List<ValueExpression> _values;
+
+    private final List<String> _columnNames;
+
+    public ColumnSourceByValuesBuilderImpl( SQLProcessorAggregator processor )
+    {
+        super( processor );
+        this._values = new ArrayList<ValueExpression>();
+        this._columnNames = new ArrayList<String>();
+    }
+
+    public ColumnSourceByValues createExpression()
+    {
+        ColumnNameList list = null;
+        if( !this._columnNames.isEmpty() )
+        {
+            list = new ColumnNameListImpl( this.getProcessor(), this._columnNames );
+        }
+        return new ColumnSourceByValuesImpl( this.getProcessor(), list, this._values );
+    }
+
+    public ColumnSourceByValuesBuilder addValues( ValueExpression... values )
+    {
+        for( ValueExpression exp : values )
+        {
+            Objects.requireNonNull( exp, "value" );
+            this._values.add( exp );
+        }
+        return this;
+    }
+
+    public List<ValueExpression> getValues()
+    {
+        return Collections.unmodifiableList( this._values );
+    }
+
+    public ColumnSourceByValuesBuilder addColumnNames( String... columnNames )
+    {
+        for( String str : columnNames )
+        {
+            Objects.requireNonNull( str, "column name" );
+            this._columnNames.add( str );
+        }
+
+        return this;
+    }
+
+    public List<String> getColumnNames()
+    {
+        return Collections.unmodifiableList( this._columnNames );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/modification/DeleteBySearchBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/modification/DeleteBySearchBuilderImpl.java
new file mode 100644
index 0000000..b5dade8
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/modification/DeleteBySearchBuilderImpl.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.modification;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.builders.booleans.BooleanBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.DeleteBySearchBuilder;
+import org.apache.polygene.library.sql.generator.grammar.modification.DeleteBySearch;
+import org.apache.polygene.library.sql.generator.grammar.modification.TargetTable;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.modification.DeleteBySearchImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DeleteBySearchBuilderImpl extends SQLBuilderBase
+    implements DeleteBySearchBuilder
+{
+
+    private final BooleanBuilder _whereBuilder;
+
+    private TargetTable _targetTable;
+
+    public DeleteBySearchBuilderImpl( SQLProcessorAggregator processor, BooleanBuilder whereBuilder )
+    {
+        super( processor );
+        Objects.requireNonNull( whereBuilder, "where builder" );
+        this._whereBuilder = whereBuilder;
+    }
+
+    public DeleteBySearch createExpression()
+    {
+
+        return new DeleteBySearchImpl( this.getProcessor(), this._targetTable, this._whereBuilder.createExpression() );
+    }
+
+    public DeleteBySearchBuilder setTargetTable( TargetTable table )
+    {
+        Objects.requireNonNull( table, "table" );
+        this._targetTable = table;
+        return this;
+    }
+
+    public TargetTable getTargetTable()
+    {
+        return this._targetTable;
+    }
+
+    public BooleanBuilder getWhere()
+    {
+        return this._whereBuilder;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/modification/InsertStatementBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/modification/InsertStatementBuilderImpl.java
new file mode 100644
index 0000000..31b0373
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/modification/InsertStatementBuilderImpl.java
@@ -0,0 +1,72 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.modification;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.InsertStatementBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSource;
+import org.apache.polygene.library.sql.generator.grammar.modification.InsertStatement;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.modification.InsertStatementImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class InsertStatementBuilderImpl extends SQLBuilderBase
+    implements InsertStatementBuilder
+{
+
+    private TableNameDirect _tableName;
+
+    private ColumnSource _columnSource;
+
+    public InsertStatementBuilderImpl( SQLProcessorAggregator processor )
+    {
+        super( processor );
+    }
+
+    public InsertStatement createExpression()
+    {
+        return new InsertStatementImpl( this.getProcessor(), this._tableName, this._columnSource );
+    }
+
+    public InsertStatementBuilder setTableName( TableNameDirect tableName )
+    {
+        this._tableName = tableName;
+        return this;
+    }
+
+    public TableNameDirect getTableName()
+    {
+        return this._tableName;
+    }
+
+    public InsertStatementBuilder setColumnSource( ColumnSource source )
+    {
+        this._columnSource = source;
+        return this;
+    }
+
+    public ColumnSource getColumnSource()
+    {
+        return this._columnSource;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/modification/UpdateBySearchBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/modification/UpdateBySearchBuilderImpl.java
new file mode 100644
index 0000000..93b9271
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/modification/UpdateBySearchBuilderImpl.java
@@ -0,0 +1,87 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.modification;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.builders.booleans.BooleanBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.UpdateBySearchBuilder;
+import org.apache.polygene.library.sql.generator.grammar.modification.SetClause;
+import org.apache.polygene.library.sql.generator.grammar.modification.TargetTable;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateBySearch;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.modification.UpdateBySearchImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class UpdateBySearchBuilderImpl extends SQLBuilderBase
+    implements UpdateBySearchBuilder
+{
+
+    private TargetTable _targetTable;
+
+    private final List<SetClause> _setClauses;
+
+    private final BooleanBuilder _whereBuilder;
+
+    public UpdateBySearchBuilderImpl( SQLProcessorAggregator processor, BooleanBuilder whereBuilder )
+    {
+        super( processor );
+        Objects.requireNonNull( whereBuilder, "where builder" );
+
+        this._setClauses = new ArrayList<SetClause>();
+        this._whereBuilder = whereBuilder;
+    }
+
+    public UpdateBySearch createExpression()
+    {
+        return new UpdateBySearchImpl( this.getProcessor(), this._targetTable, this._setClauses,
+                                       this._whereBuilder.createExpression() );
+    }
+
+    public UpdateBySearchBuilder setTargetTable( TargetTable table )
+    {
+        this._targetTable = table;
+        return this;
+    }
+
+    public BooleanBuilder getWhereBuilder()
+    {
+        return this._whereBuilder;
+    }
+
+    public UpdateBySearchBuilder addSetClauses( SetClause... clauses )
+    {
+        for( SetClause clause : clauses )
+        {
+            this._setClauses.add( clause );
+        }
+        return this;
+    }
+
+    public List<SetClause> getSetClauses()
+    {
+        return Collections.unmodifiableList( this._setClauses );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/modification/pgsql/PgSQLInsertStatementBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/modification/pgsql/PgSQLInsertStatementBuilderImpl.java
new file mode 100644
index 0000000..7aa4861
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/modification/pgsql/PgSQLInsertStatementBuilderImpl.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.polygene.library.sql.generator.implementation.grammar.builders.modification.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.pgsql.PgSQLInsertStatementBuilder;
+import org.apache.polygene.library.sql.generator.grammar.modification.InsertStatement;
+import org.apache.polygene.library.sql.generator.grammar.query.SelectColumnClause;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.modification.InsertStatementBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.modification.pgsql.PgSQLInsertStatementImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+public class PgSQLInsertStatementBuilderImpl extends InsertStatementBuilderImpl implements
+                                                                                PgSQLInsertStatementBuilder
+{
+
+    private SelectColumnClause _returning;
+
+    public PgSQLInsertStatementBuilderImpl( SQLProcessorAggregator processor )
+    {
+        super( processor );
+    }
+
+    public PgSQLInsertStatementBuilder setReturningClause( SelectColumnClause clause )
+    {
+        this._returning = clause;
+        return this;
+    }
+
+    @Override
+    public InsertStatement createExpression()
+    {
+        return new PgSQLInsertStatementImpl( this.getProcessor(), this.getTableName(),
+                                             this.getColumnSource(), this._returning );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/AbstractQueryFactoryImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/AbstractQueryFactoryImpl.java
new file mode 100644
index 0000000..a4e76a5
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/AbstractQueryFactoryImpl.java
@@ -0,0 +1,84 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.query;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.query.AbstractQueryBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.LimitSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.OffsetSpecification;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.LimitSpecificationImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author 2011 Stanislav Muhametsin
+ */
+public abstract class AbstractQueryFactoryImpl<ExpressionType> extends SQLBuilderBase
+    implements AbstractQueryBuilder<ExpressionType>
+{
+
+    private LimitSpecification _limit;
+    private OffsetSpecification _offset;
+
+    protected AbstractQueryFactoryImpl( SQLProcessorAggregator processor )
+    {
+        super( processor );
+    }
+
+    public AbstractQueryBuilder<ExpressionType> limit()
+    {
+        this._limit = new LimitSpecificationImpl( this.getProcessor(), null );
+        return this;
+    }
+
+    public AbstractQueryBuilder<ExpressionType> limit( Integer max )
+    {
+        return this.limit( this.getProcessor().getVendor().getLiteralFactory().n( max ) );
+    }
+
+    public AbstractQueryBuilder<ExpressionType> limit( NonBooleanExpression max )
+    {
+        this._limit =
+            ( max == null ? null : this.getProcessor().getVendor().getQueryFactory().limit( max ) );
+        return this;
+    }
+
+    public AbstractQueryBuilder<ExpressionType> offset( Integer skip )
+    {
+        return this.offset( this.getProcessor().getVendor().getLiteralFactory().n( skip ) );
+    }
+
+    public AbstractQueryBuilder<ExpressionType> offset( NonBooleanExpression skip )
+    {
+        this._offset =
+            ( skip == null ? null : this.getProcessor().getVendor().getQueryFactory().offset( skip ) );
+        return this;
+    }
+
+    protected LimitSpecification getLimit()
+    {
+        return this._limit;
+    }
+
+    protected OffsetSpecification getOffset()
+    {
+        return this._offset;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/ColumnsBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/ColumnsBuilderImpl.java
new file mode 100644
index 0000000..2df5f54
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/ColumnsBuilderImpl.java
@@ -0,0 +1,113 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.query;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.ColumnsBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReference;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferences.ColumnReferenceInfo;
+import org.apache.polygene.library.sql.generator.grammar.query.SelectColumnClause;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.AsteriskSelectImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.ColumnReferencesImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ColumnsBuilderImpl extends SQLBuilderBase
+    implements ColumnsBuilder
+{
+    private final List<ColumnReferenceInfo> _columns;
+    private SetQuantifier _quantifier;
+
+    public ColumnsBuilderImpl( SQLProcessorAggregator processor, SetQuantifier setQuantifier )
+    {
+        super( processor );
+        Objects.requireNonNull( setQuantifier, "set quantifier" );
+
+        this._quantifier = setQuantifier;
+        this._columns = new ArrayList<ColumnReferenceInfo>();
+    }
+
+    public ColumnsBuilder addUnnamedColumns( ColumnReference... columns )
+    {
+        for( ColumnReference col : columns )
+        {
+            this.addNamedColumns( new ColumnReferenceInfo( null, col ) );
+        }
+
+        return this;
+    }
+
+    public ColumnsBuilder addNamedColumns( ColumnReferenceInfo... namedColumns )
+    {
+        for( ColumnReferenceInfo info : namedColumns )
+        {
+            Objects.requireNonNull( info, "named column" );
+            this._columns.add( info );
+        }
+
+        return this;
+    }
+
+    public ColumnsBuilder setSetQuantifier( SetQuantifier newSetQuantifier )
+    {
+        Objects.requireNonNull( newSetQuantifier, "new set quantifier" );
+        this._quantifier = newSetQuantifier;
+
+        return this;
+    }
+
+    public ColumnsBuilder selectAll()
+    {
+        this._columns.clear();
+        return this;
+    }
+
+    public List<ColumnReferenceInfo> getColumns()
+    {
+        return Collections.unmodifiableList( this._columns );
+    }
+
+    public SetQuantifier getSetQuantifier()
+    {
+        return this._quantifier;
+    }
+
+    public SelectColumnClause createExpression()
+    {
+        SelectColumnClause result = null;
+        if( this._columns.isEmpty() )
+        {
+            result = new AsteriskSelectImpl( this.getProcessor(), this._quantifier );
+        }
+        else
+        {
+            result = new ColumnReferencesImpl( this.getProcessor(), this._quantifier, this._columns );
+        }
+
+        return result;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/FromBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/FromBuilderImpl.java
new file mode 100644
index 0000000..50d2d2b
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/FromBuilderImpl.java
@@ -0,0 +1,75 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.query;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.FromBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.TableReferenceBuilder;
+import org.apache.polygene.library.sql.generator.grammar.query.FromClause;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReference;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.FromClauseImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class FromBuilderImpl extends SQLBuilderBase
+    implements FromBuilder
+{
+
+    private final List<TableReferenceBuilder> _tableRefs;
+
+    public FromBuilderImpl( SQLProcessorAggregator processor )
+    {
+        super( processor );
+        this._tableRefs = new ArrayList<TableReferenceBuilder>();
+    }
+
+    public FromBuilder addTableReferences( TableReferenceBuilder... tableRefs )
+    {
+        for( TableReferenceBuilder ref : tableRefs )
+        {
+            Objects.requireNonNull( ref, "table reference" );
+            this._tableRefs.add( ref );
+        }
+
+        return this;
+    }
+
+    public List<TableReferenceBuilder> getTableReferences()
+    {
+        return Collections.unmodifiableList( this._tableRefs );
+    }
+
+    public FromClause createExpression()
+    {
+        List<TableReference> refs = new ArrayList<TableReference>( this._tableRefs.size() );
+        for( TableReferenceBuilder builder : this._tableRefs )
+        {
+            refs.add( builder.createExpression() );
+        }
+
+        return new FromClauseImpl( this.getProcessor(), refs );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/GroupByBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/GroupByBuilderImpl.java
new file mode 100644
index 0000000..84c9b12
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/GroupByBuilderImpl.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.query;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.GroupByBuilder;
+import org.apache.polygene.library.sql.generator.grammar.query.GroupByClause;
+import org.apache.polygene.library.sql.generator.grammar.query.GroupingElement;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.GroupByClauseImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class GroupByBuilderImpl extends SQLBuilderBase
+    implements GroupByBuilder
+{
+
+    private final List<GroupingElement> _elements;
+
+    public GroupByBuilderImpl( SQLProcessorAggregator processor )
+    {
+        super( processor );
+        this._elements = new ArrayList<GroupingElement>();
+    }
+
+    public GroupByBuilder addGroupingElements( GroupingElement... elements )
+    {
+        Objects.requireNonNull( elements, "elements" );
+        for( GroupingElement element : elements )
+        {
+            Objects.requireNonNull( element, "element" );
+        }
+
+        this._elements.addAll( Arrays.asList( elements ) );
+        return this;
+    }
+
+    public List<GroupingElement> getGroupingElements()
+    {
+        return Collections.unmodifiableList( this._elements );
+    }
+
+    public GroupByClause createExpression()
+    {
+        return new GroupByClauseImpl( this.getProcessor(), this._elements );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/OrderByBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/OrderByBuilderImpl.java
new file mode 100644
index 0000000..128851f
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/OrderByBuilderImpl.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.query;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.OrderByBuilder;
+import org.apache.polygene.library.sql.generator.grammar.query.OrderByClause;
+import org.apache.polygene.library.sql.generator.grammar.query.SortSpecification;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.OrderByClauseImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class OrderByBuilderImpl extends SQLBuilderBase
+    implements OrderByBuilder
+{
+
+    private final List<SortSpecification> _sortSpecs;
+
+    public OrderByBuilderImpl( SQLProcessorAggregator processor )
+    {
+        super( processor );
+        this._sortSpecs = new ArrayList<SortSpecification>();
+    }
+
+    public OrderByBuilder addSortSpecs( SortSpecification... specs )
+    {
+        for( SortSpecification spec : specs )
+        {
+            Objects.requireNonNull( spec, "specification" );
+        }
+
+        this._sortSpecs.addAll( Arrays.asList( specs ) );
+        return this;
+    }
+
+    public List<SortSpecification> getSortSpecs()
+    {
+        return Collections.unmodifiableList( this._sortSpecs );
+    }
+
+    public OrderByClause createExpression()
+    {
+        return new OrderByClauseImpl( this.getProcessor(), this._sortSpecs );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/QueryBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/QueryBuilderImpl.java
new file mode 100644
index 0000000..ca93068
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/QueryBuilderImpl.java
@@ -0,0 +1,148 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.query;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.QueryBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+import org.apache.polygene.library.sql.generator.grammar.query.CorrespondingSpec;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBody;
+import org.apache.polygene.library.sql.generator.grammar.query.SetOperation;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.QueryExpressionBodyBinaryImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class QueryBuilderImpl extends SQLBuilderBase
+    implements QueryBuilder
+{
+
+    public static final SetQuantifier DEFAULT_SET_QUANTIFIER_FOR_UNIONS = SetQuantifier.DISTINCT;
+
+    public static final SetQuantifier DEFAULT_SET_QUANTIFIER_FOR_INTERSECTIONS = SetQuantifier.DISTINCT;
+
+    public static final SetQuantifier DEFAULT_SET_QUANTIFIER_FOR_EXCEPTS = SetQuantifier.DISTINCT;
+
+    private final SetQuantifier _defaultSetQuantifierForUnions;
+
+    private final SetQuantifier _defaultSetQuantifierForIntersections;
+
+    private final SetQuantifier _defaultSetQuantifierForExcepts;
+
+    private QueryExpressionBody _topLevelExpression;
+
+    public QueryBuilderImpl( SQLProcessorAggregator processor, QueryExpressionBody topLevelExpression )
+    {
+        this( processor, topLevelExpression, DEFAULT_SET_QUANTIFIER_FOR_UNIONS,
+              DEFAULT_SET_QUANTIFIER_FOR_INTERSECTIONS, DEFAULT_SET_QUANTIFIER_FOR_EXCEPTS );
+    }
+
+    protected QueryBuilderImpl( SQLProcessorAggregator processor, QueryExpressionBody topLevelExpression,
+                                SetQuantifier defaultSetQuantifierForUnions, SetQuantifier defaultSetQuantifierForIntersections,
+                                SetQuantifier defaultSetQuantifierForExcepts )
+    {
+        super( processor );
+        Objects.requireNonNull( defaultSetQuantifierForUnions, "default quantifier for unions" );
+        Objects.requireNonNull( defaultSetQuantifierForIntersections, "default quantifier for intersections" );
+        Objects.requireNonNull( defaultSetQuantifierForExcepts, "default quantifier for excepts" );
+        Objects.requireNonNull( topLevelExpression, "top level expression" );
+
+        this._defaultSetQuantifierForExcepts = defaultSetQuantifierForExcepts;
+        this._defaultSetQuantifierForIntersections = defaultSetQuantifierForIntersections;
+        this._defaultSetQuantifierForUnions = defaultSetQuantifierForUnions;
+        this._topLevelExpression = topLevelExpression;
+    }
+
+    public QueryBuilder union( QueryExpressionBody another )
+    {
+        return this.union( this._defaultSetQuantifierForUnions, another );
+    }
+
+    public QueryBuilder union( CorrespondingSpec correspondingSpec, QueryExpressionBody another )
+    {
+        return this.union( this._defaultSetQuantifierForUnions, correspondingSpec, another );
+    }
+
+    public QueryBuilder union( SetQuantifier setQuantifier, QueryExpressionBody another )
+    {
+        return this.union( setQuantifier, null, another );
+    }
+
+    public QueryBuilder union( SetQuantifier setQuantifier, CorrespondingSpec correspondingSpec,
+                               QueryExpressionBody another )
+    {
+        this._topLevelExpression = new QueryExpressionBodyBinaryImpl( this.getProcessor(), SetOperation.UNION,
+                                                                      this._topLevelExpression, another, setQuantifier, correspondingSpec );
+        return this;
+    }
+
+    public QueryBuilder intersect( QueryExpressionBody another )
+    {
+        return this.intersect( this._defaultSetQuantifierForIntersections, another );
+    }
+
+    public QueryBuilder intersect( CorrespondingSpec correspondingSpec, QueryExpressionBody another )
+    {
+        return this.intersect( this._defaultSetQuantifierForIntersections, correspondingSpec, another );
+    }
+
+    public QueryBuilder intersect( SetQuantifier setQuantifier, QueryExpressionBody another )
+    {
+        return this.intersect( setQuantifier, null, another );
+    }
+
+    public QueryBuilder intersect( SetQuantifier setQuantifier, CorrespondingSpec correspondingSpec,
+                                   QueryExpressionBody another )
+    {
+        this._topLevelExpression = new QueryExpressionBodyBinaryImpl( this.getProcessor(), SetOperation.INTERSECT,
+                                                                      this._topLevelExpression, another, setQuantifier, correspondingSpec );
+        return this;
+    }
+
+    public QueryBuilder except( QueryExpressionBody another )
+    {
+        return this.except( this._defaultSetQuantifierForExcepts, another );
+    }
+
+    public QueryBuilder except( CorrespondingSpec correspondingSpec, QueryExpressionBody another )
+    {
+        return this.except( this._defaultSetQuantifierForExcepts, correspondingSpec, another );
+    }
+
+    public QueryBuilder except( SetQuantifier setQuantifier, QueryExpressionBody another )
+    {
+        return this.except( setQuantifier, null, another );
+    }
+
+    public QueryBuilder except( SetQuantifier setQuantifier, CorrespondingSpec correspondingSpec,
+                                QueryExpressionBody another )
+    {
+        this._topLevelExpression = new QueryExpressionBodyBinaryImpl( this.getProcessor(), SetOperation.EXCEPT,
+                                                                      this._topLevelExpression, another, setQuantifier, correspondingSpec );
+        return this;
+    }
+
+    public QueryExpressionBody createExpression()
+    {
+        return this._topLevelExpression;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/QuerySpecificationBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/QuerySpecificationBuilderImpl.java
new file mode 100644
index 0000000..c7e83aa
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/QuerySpecificationBuilderImpl.java
@@ -0,0 +1,238 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.query;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Predicate;
+import org.apache.polygene.library.sql.generator.grammar.builders.booleans.BooleanBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.ColumnsBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.FromBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.GroupByBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.OrderByBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.QuerySpecificationBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.factories.QueryFactory;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReference;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferences.ColumnReferenceInfo;
+import org.apache.polygene.library.sql.generator.grammar.query.GroupingElement;
+import org.apache.polygene.library.sql.generator.grammar.query.OrdinaryGroupingSet;
+import org.apache.polygene.library.sql.generator.grammar.query.QuerySpecification;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.QuerySpecificationImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class QuerySpecificationBuilderImpl extends AbstractQueryFactoryImpl<QuerySpecification>
+    implements QuerySpecificationBuilder
+{
+
+    private ColumnsBuilder _select;
+
+    private FromBuilder _from;
+
+    private BooleanBuilder _where;
+
+    private GroupByBuilder _groupBy;
+
+    private BooleanBuilder _having;
+
+    private OrderByBuilder _orderBy;
+
+    private final QueryFactory _queryFactory;
+
+    public QuerySpecificationBuilderImpl( SQLProcessorAggregator processor, QueryFactory q, ColumnsBuilder select,
+                                          FromBuilder from, BooleanBuilder where, GroupByBuilder groupBy, BooleanBuilder having, OrderByBuilder orderBy )
+    {
+        super( processor );
+
+        Objects.requireNonNull( q, "Query factory" );
+        Objects.requireNonNull( select, "select" );
+        Objects.requireNonNull( from, "from" );
+        Objects.requireNonNull( where, "where" );
+        Objects.requireNonNull( groupBy, "group by" );
+        Objects.requireNonNull( having, "having" );
+        Objects.requireNonNull( orderBy, "order by" );
+
+        this._queryFactory = q;
+        this._select = select;
+        this._from = from;
+        this._where = where;
+        this._groupBy = groupBy;
+        this._having = having;
+        this._orderBy = orderBy;
+    }
+
+    public FromBuilder getFrom()
+    {
+        return this._from;
+    }
+
+    public ColumnsBuilder getSelect()
+    {
+        return this._select;
+    }
+
+    public BooleanBuilder getWhere()
+    {
+        return this._where;
+    }
+
+    public GroupByBuilder getGroupBy()
+    {
+        return this._groupBy;
+    }
+
+    public BooleanBuilder getHaving()
+    {
+        return this._having;
+    }
+
+    public OrderByBuilder getOrderBy()
+    {
+        return this._orderBy;
+    }
+
+    public QuerySpecificationBuilder trimGroupBy()
+    {
+        if( this._having.createExpression() != Predicate.EmptyPredicate.INSTANCE )
+        {
+            List<ColumnReference> groupByColumns = new ArrayList<ColumnReference>();
+            for( GroupingElement element : this._groupBy.getGroupingElements() )
+            {
+                if( element instanceof OrdinaryGroupingSet )
+                {
+                    for( NonBooleanExpression exp : ( (OrdinaryGroupingSet) element ).getColumns() )
+                    {
+                        if( exp instanceof ColumnReference )
+                        {
+                            groupByColumns.add( (ColumnReference) exp );
+                        }
+                    }
+                }
+            }
+            for( ColumnReferenceInfo column : this._select.getColumns() )
+            {
+                Boolean noColumn = true;
+                for( ColumnReference groupByColumn : groupByColumns )
+                {
+                    if( column.getReference().equals( groupByColumn ) )
+                    {
+                        noColumn = false;
+                        break;
+                    }
+                }
+
+                if( noColumn )
+                {
+                    this._groupBy.addGroupingElements( this._queryFactory.groupingElement( column.getReference() ) );
+                }
+            }
+        }
+
+        return this;
+    }
+
+    public QuerySpecification createExpression()
+    {
+        return new QuerySpecificationImpl( this.getProcessor(), this._select.createExpression(),
+                                           this._from.createExpression(), this._where.createExpression(), this._groupBy.createExpression(),
+                                           this._having.createExpression(), this._orderBy.createExpression(), this.getOffset(), this.getLimit() );
+    }
+
+    public QuerySpecificationBuilder setSelect( ColumnsBuilder builder )
+    {
+        Objects.requireNonNull( builder, "builder" );
+        this._select = builder;
+        return this;
+    }
+
+    public QuerySpecificationBuilder setFrom( FromBuilder builder )
+    {
+        Objects.requireNonNull( builder, "builder" );
+        this._from = builder;
+        return this;
+    }
+
+    public QuerySpecificationBuilder setWhere( BooleanBuilder builder )
+    {
+        Objects.requireNonNull( builder, "builder" );
+        this._where = builder;
+        return this;
+    }
+
+    public QuerySpecificationBuilder setGroupBy( GroupByBuilder builder )
+    {
+        Objects.requireNonNull( builder, "builder" );
+        this._groupBy = builder;
+        return this;
+    }
+
+    public QuerySpecificationBuilder setHaving( BooleanBuilder builder )
+    {
+        Objects.requireNonNull( builder, "builder" );
+        this._having = builder;
+        return this;
+    }
+
+    public QuerySpecificationBuilder setOrderBy( OrderByBuilder builder )
+    {
+        Objects.requireNonNull( builder, "builder" );
+        this._orderBy = builder;
+        return this;
+    }
+
+    protected QueryFactory getQueryFactory()
+    {
+        return this._queryFactory;
+    }
+
+    @Override
+    public QuerySpecificationBuilder limit()
+    {
+        return (QuerySpecificationBuilder) super.limit();
+    }
+
+    @Override
+    public QuerySpecificationBuilder limit( Integer max )
+    {
+        return (QuerySpecificationBuilder) super.limit( max );
+    }
+
+    @Override
+    public QuerySpecificationBuilder limit( NonBooleanExpression max )
+    {
+        return (QuerySpecificationBuilder) super.limit( max );
+    }
+
+    @Override
+    public QuerySpecificationBuilder offset( Integer skip )
+    {
+        return (QuerySpecificationBuilder) super.offset( skip );
+    }
+
+    @Override
+    public QuerySpecificationBuilder offset( NonBooleanExpression skip )
+    {
+        return (QuerySpecificationBuilder) super.offset( skip );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/SimpleQueryBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/SimpleQueryBuilderImpl.java
new file mode 100644
index 0000000..0da15e0
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/SimpleQueryBuilderImpl.java
@@ -0,0 +1,262 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.query;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.QuerySpecificationBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.SimpleQueryBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.common.TableName;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.factories.ColumnsFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.QueryFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.TableReferenceFactory;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReference;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferences.ColumnReferenceInfo;
+import org.apache.polygene.library.sql.generator.grammar.query.Ordering;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class SimpleQueryBuilderImpl extends AbstractQueryFactoryImpl<QueryExpression>
+    implements SimpleQueryBuilder
+{
+
+    private final List<ColumnReference> _columns;
+
+    private final Map<Integer, String> _columnAliases;
+
+    private final List<TableName> _from;
+
+    private BooleanExpression _where;
+
+    private final List<String> _groupBy;
+
+    private BooleanExpression _having;
+
+    private final List<String> _orderBy;
+
+    private final List<Ordering> _orderings;
+
+    private final SQLVendor _vendor;
+
+    private boolean _selectAll;
+
+    public SimpleQueryBuilderImpl( SQLProcessorAggregator processor, SQLVendor vendor )
+    {
+        super( processor );
+        Objects.requireNonNull( vendor, "Vendor" );
+
+        this._vendor = vendor;
+        this._columns = new ArrayList<ColumnReference>();
+        this._columnAliases = new HashMap<Integer, String>();
+        this._from = new ArrayList<TableName>();
+        this._groupBy = new ArrayList<String>();
+        this._orderBy = new ArrayList<String>();
+        this._orderings = new ArrayList<Ordering>();
+        this._selectAll = false;
+    }
+
+    public QueryExpression createExpression()
+    {
+        QueryFactory q = this._vendor.getQueryFactory();
+
+        QuerySpecificationBuilder builda = q.querySpecificationBuilder();
+
+        this.processQuerySpecBuilder( builda );
+
+        return q.createQuery( builda.createExpression() );
+    }
+
+    protected void processQuerySpecBuilder( QuerySpecificationBuilder builda )
+    {
+        QueryFactory q = this._vendor.getQueryFactory();
+        ColumnsFactory c = this._vendor.getColumnsFactory();
+        TableReferenceFactory t = this._vendor.getTableReferenceFactory();
+
+        if( this._selectAll )
+        {
+            builda.getSelect().selectAll();
+        }
+        else
+        {
+            for( Integer colIndex = 0; colIndex < this._columns.size(); ++colIndex )
+            {
+                ColumnReference ref = this._columns.get( colIndex );
+                String alias = this._columnAliases.get( colIndex );
+                builda.getSelect().addNamedColumns( new ColumnReferenceInfo( alias, ref ) );
+            }
+        }
+        for( TableName tableName : this._from )
+        {
+            builda.getFrom().addTableReferences( t.tableBuilder( t.table( tableName ) ) );
+        }
+
+        builda.getWhere().reset( this._where );
+
+        for( String groupBy : this._groupBy )
+        {
+            builda.getGroupBy().addGroupingElements( q.groupingElement( c.colName( groupBy ) ) );
+        }
+
+        builda.getHaving().reset( this._having );
+
+        for( Integer orderByIndex = 0; orderByIndex < this._orderBy.size(); ++orderByIndex )
+        {
+            builda.getOrderBy().addSortSpecs(
+                q.sortSpec( c.colName( this._orderBy.get( orderByIndex ) ), this._orderings.get( orderByIndex ) ) );
+        }
+
+        if( this.getOffset() != null )
+        {
+            builda.offset( this.getOffset().getSkip() );
+        }
+
+        if( this.getLimit() != null )
+        {
+            builda.limit( this.getLimit().getCount() );
+        }
+    }
+
+    protected SQLVendor getVendor()
+    {
+        return this._vendor;
+    }
+
+    public SimpleQueryBuilder select( String... columnNames )
+    {
+        this._selectAll = false;
+        for( String col : columnNames )
+        {
+            this._columns.add( this._vendor.getColumnsFactory().colName( col ) );
+        }
+        return this;
+    }
+
+    public SimpleQueryBuilder select( ValueExpression... expressions )
+    {
+        this._selectAll = false;
+        for( ValueExpression exp : expressions )
+        {
+            this._columns.add( this._vendor.getColumnsFactory().colExp( exp ) );
+        }
+        return this;
+    }
+
+    public SimpleQueryBuilder selectAllColumns()
+    {
+        this._selectAll = true;
+        return this;
+    }
+
+    public SimpleQueryBuilder as( String columnAlias )
+    {
+        this._columnAliases.put( this._columns.size() - 1, columnAlias );
+        return this;
+    }
+
+    public SimpleQueryBuilder from( TableName... tableNames )
+    {
+        for( TableName table : tableNames )
+        {
+            this._from.add( table );
+        }
+        return this;
+    }
+
+    public SimpleQueryBuilder where( BooleanExpression searchCondition )
+    {
+        this._where = searchCondition;
+        return this;
+    }
+
+    public SimpleQueryBuilder groupBy( String... columns )
+    {
+        for( String col : columns )
+        {
+            this._groupBy.add( col );
+        }
+        return this;
+    }
+
+    public SimpleQueryBuilder having( BooleanExpression groupingCondition )
+    {
+        this._having = groupingCondition;
+        return this;
+    }
+
+    public SimpleQueryBuilder orderByAsc( String... columns )
+    {
+        for( String col : columns )
+        {
+            this._orderBy.add( col );
+            this._orderings.add( Ordering.ASCENDING );
+        }
+        return this;
+    }
+
+    public SimpleQueryBuilder orderByDesc( String... columns )
+    {
+        for( String col : columns )
+        {
+            this._orderBy.add( col );
+            this._orderings.add( Ordering.DESCENDING );
+        }
+        return this;
+    }
+
+    @Override
+    public SimpleQueryBuilder limit()
+    {
+        return (SimpleQueryBuilder) super.limit();
+    }
+
+    @Override
+    public SimpleQueryBuilder limit( Integer max )
+    {
+        return (SimpleQueryBuilder) super.limit( max );
+    }
+
+    @Override
+    public SimpleQueryBuilder limit( NonBooleanExpression max )
+    {
+        return (SimpleQueryBuilder) super.limit( max );
+    }
+
+    @Override
+    public SimpleQueryBuilder offset( Integer skip )
+    {
+        return (SimpleQueryBuilder) super.offset( skip );
+    }
+
+    @Override
+    public SimpleQueryBuilder offset( NonBooleanExpression skip )
+    {
+        return (SimpleQueryBuilder) super.offset( skip );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/TableReferenceBuilderImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/TableReferenceBuilderImpl.java
new file mode 100644
index 0000000..a98dd35
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/builders/query/TableReferenceBuilderImpl.java
@@ -0,0 +1,78 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.builders.query;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.TableReferenceBuilder;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReference;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferencePrimary;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinType;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLBuilderBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.joins.CrossJoinedTableImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.joins.NaturalJoinedTableImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.joins.QualifiedJoinedTableImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.joins.UnionJoinedTableImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+public class TableReferenceBuilderImpl extends SQLBuilderBase
+    implements TableReferenceBuilder
+{
+
+    private TableReference _currentTable;
+
+    public TableReferenceBuilderImpl( SQLProcessorAggregator processor, TableReferencePrimary startingTable )
+    {
+        super( processor );
+        Objects.requireNonNull( startingTable, "starting table" );
+
+        this._currentTable = startingTable;
+    }
+
+    public TableReferenceBuilder addQualifiedJoin( JoinType joinType, TableReference right, JoinSpecification joinSpec )
+    {
+        this._currentTable = new QualifiedJoinedTableImpl( this.getProcessor(), this._currentTable, right, joinType,
+                                                           joinSpec );
+        return this;
+    }
+
+    public TableReferenceBuilder addCrossJoin( TableReference right )
+    {
+        this._currentTable = new CrossJoinedTableImpl( this.getProcessor(), this._currentTable, right );
+        return this;
+    }
+
+    public TableReferenceBuilder addNaturalJoin( JoinType joinType, TableReference right )
+    {
+        this._currentTable = new NaturalJoinedTableImpl( this.getProcessor(), this._currentTable, right, joinType );
+        return this;
+    }
+
+    public TableReferenceBuilder addUnionJoin( TableReference right )
+    {
+        this._currentTable = new UnionJoinedTableImpl( this.getProcessor(), this._currentTable, right );
+        return this;
+    }
+
+    public TableReference createExpression()
+    {
+        return this._currentTable;
+    }
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/ColumnNameListImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/ColumnNameListImpl.java
new file mode 100644
index 0000000..a04ba7c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/ColumnNameListImpl.java
@@ -0,0 +1,80 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ColumnNameListImpl extends SQLSyntaxElementBase<ColumnNameList, ColumnNameList>
+    implements ColumnNameList
+{
+
+    private final List<String> _columnNames;
+
+    public ColumnNameListImpl( SQLProcessorAggregator processor, Collection<String> columnNames )
+    {
+        this( processor, ColumnNameList.class, columnNames );
+    }
+
+    protected ColumnNameListImpl( SQLProcessorAggregator processor,
+                                  Class<? extends ColumnNameList> implClass,
+                                  Collection<String> columnNames )
+    {
+        super( processor, implClass );
+        Objects.requireNonNull( columnNames, "column names" );
+
+        if( columnNames.isEmpty() )
+        {
+            throw new IllegalArgumentException( "Column name list must have at least one column." );
+        }
+
+        for( String columnName : columnNames )
+        {
+            Objects.requireNonNull( columnName, "column name" );
+        }
+
+        this._columnNames = Collections.unmodifiableList( new ArrayList<String>( columnNames ) );
+    }
+
+    public ColumnNameListImpl( SQLProcessorAggregator processor, String... columnNames )
+    {
+        this( processor, Arrays.asList( columnNames ) );
+    }
+
+    public List<String> getColumnNames()
+    {
+        return this._columnNames;
+    }
+
+    @Override
+    protected boolean doesEqual( ColumnNameList another )
+    {
+        return this._columnNames.equals( another.getColumnNames() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/NonBooleanExpressionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/NonBooleanExpressionImpl.java
new file mode 100644
index 0000000..7e92690
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/NonBooleanExpressionImpl.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common;
+
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class NonBooleanExpressionImpl<ExpressionType extends NonBooleanExpression> extends
+                                                                                            SQLSyntaxElementBase<ValueExpression, ExpressionType>
+{
+
+    protected NonBooleanExpressionImpl( SQLProcessorAggregator aggregator,
+                                        Class<? extends ExpressionType> expressionClass )
+    {
+        super( aggregator, expressionClass );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/SQLBuilderBase.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/SQLBuilderBase.java
new file mode 100644
index 0000000..099a07b
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/SQLBuilderBase.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author 2011 Stanislav Muhametsin
+ */
+public abstract class SQLBuilderBase
+{
+    private final SQLProcessorAggregator _processor;
+
+    protected SQLBuilderBase( SQLProcessorAggregator processor )
+    {
+        Objects.requireNonNull( processor, "Processor" );
+
+        this._processor = processor;
+    }
+
+    protected SQLProcessorAggregator getProcessor()
+    {
+        return this._processor;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/SQLFactoryBase.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/SQLFactoryBase.java
new file mode 100644
index 0000000..5f0ecc8
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/SQLFactoryBase.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author 2011 Stanislav Muhametsin
+ */
+public abstract class SQLFactoryBase
+{
+
+    private final SQLVendor _vendor;
+    private final SQLProcessorAggregator _processor;
+
+    protected SQLFactoryBase( SQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        Objects.requireNonNull( vendor, "vendor" );
+        Objects.requireNonNull( processor, "SQL processor" );
+
+        this._vendor = vendor;
+        this._processor = processor;
+    }
+
+    protected SQLVendor getVendor()
+    {
+        return this._vendor;
+    }
+
+    protected SQLProcessorAggregator getProcessor()
+    {
+        return this._processor;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/SQLSyntaxElementBase.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/SQLSyntaxElementBase.java
new file mode 100644
index 0000000..1dc548b
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/SQLSyntaxElementBase.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.polygene.library.sql.generator.implementation.grammar.common;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author 2011 Stanislav Muhametsin
+ */
+public abstract class SQLSyntaxElementBase<BaseInterfaceType extends Typeable<?>, ActualInterfaceType extends BaseInterfaceType>
+    extends TypeableImpl<BaseInterfaceType, ActualInterfaceType>
+{
+    private final SQLProcessorAggregator _processor;
+
+    protected SQLSyntaxElementBase( SQLProcessorAggregator processor,
+                                    Class<? extends ActualInterfaceType> realImplementingType )
+    {
+        super( realImplementingType );
+
+        Objects.requireNonNull( processor, "SQL Processor" );
+
+        this._processor = processor;
+    }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder builder = new StringBuilder();
+        this._processor.process( this, builder );
+        return builder.toString();
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/TableNameDirectImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/TableNameDirectImpl.java
new file mode 100644
index 0000000..2e98080
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/TableNameDirectImpl.java
@@ -0,0 +1,58 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TableNameDirectImpl extends TableNameImpl<TableNameDirect>
+    implements TableNameDirect
+{
+    private final String _tableName;
+
+    public TableNameDirectImpl( SQLProcessorAggregator processor, String schemaName, String tableName )
+    {
+        this( processor, TableNameDirect.class, schemaName, tableName );
+    }
+
+    protected TableNameDirectImpl( SQLProcessorAggregator processor, Class<? extends TableNameDirect> implClass,
+                                   String schemaName, String tableName )
+    {
+        super( processor, implClass, schemaName );
+        Objects.requireNonNull( tableName, "table name" );
+
+        this._tableName = tableName;
+    }
+
+    public String getTableName()
+    {
+        return this._tableName;
+    }
+
+    @Override
+    protected boolean doesEqual( TableNameDirect another )
+    {
+        return super.doesEqual( another ) && this._tableName.equals( another.getTableName() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/TableNameFunctionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/TableNameFunctionImpl.java
new file mode 100644
index 0000000..d758473
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/TableNameFunctionImpl.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameFunction;
+import org.apache.polygene.library.sql.generator.grammar.literals.SQLFunctionLiteral;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author 2011 Stanislav Muhametsin
+ */
+public class TableNameFunctionImpl extends TableNameImpl<TableNameFunction>
+    implements TableNameFunction
+{
+
+    private final SQLFunctionLiteral _function;
+
+    public TableNameFunctionImpl( SQLProcessorAggregator processor, String schemaName, SQLFunctionLiteral function )
+    {
+        this( processor, TableNameFunction.class, schemaName, function );
+    }
+
+    protected TableNameFunctionImpl( SQLProcessorAggregator processor, Class<? extends TableNameFunction> implClass,
+                                     String schemaName, SQLFunctionLiteral function )
+    {
+        super( processor, implClass, schemaName );
+        Objects.requireNonNull( function, "SQL function" );
+
+        this._function = function;
+    }
+
+    public SQLFunctionLiteral getFunction()
+    {
+        return this._function;
+    }
+
+    @Override
+    protected boolean doesEqual( TableNameFunction another )
+    {
+        return super.doesEqual( another ) && this._function.equals( another.getFunction() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/TableNameImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/TableNameImpl.java
new file mode 100644
index 0000000..d6f63f0
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/TableNameImpl.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.polygene.library.sql.generator.implementation.grammar.common;
+
+import org.apache.polygene.library.sql.generator.grammar.common.TableName;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author 2011 Stanislav Muhametsin
+ */
+public class TableNameImpl<TableNameType extends TableName> extends SQLSyntaxElementBase<TableName, TableNameType>
+    implements TableName
+{
+    private final String _schemaName;
+
+    protected TableNameImpl( SQLProcessorAggregator processor, Class<? extends TableNameType> implClass,
+                             String schemaName )
+    {
+        super( processor, implClass );
+
+        this._schemaName = schemaName;
+    }
+
+    public String getSchemaName()
+    {
+        return this._schemaName;
+    }
+
+    @Override
+    protected boolean doesEqual( TableNameType another )
+    {
+        return TypeableImpl.bothNullOrEquals( this._schemaName, another.getSchemaName() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/BigIntImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/BigIntImpl.java
new file mode 100644
index 0000000..6a8aa73
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/BigIntImpl.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common.datatypes;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.BigInt;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public final class BigIntImpl
+    implements BigInt
+{
+    public BigIntImpl()
+    {
+    }
+
+    /**
+     * Returns {@link BigInt}.
+     */
+    public Class<BigInt> getImplementedType()
+    {
+        return BigInt.class;
+    }
+
+    /**
+     * The singleton instance of {@code BIGINT}.
+     */
+    public static final BigInt INSTANCE = new BigIntImpl();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/DecimalImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/DecimalImpl.java
new file mode 100644
index 0000000..2015562
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/DecimalImpl.java
@@ -0,0 +1,74 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common.datatypes;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.Decimal;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDataType;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public final class DecimalImpl extends TypeableImpl<SQLDataType, Decimal>
+    implements Decimal
+{
+    private final Integer _precision;
+    private final Integer _scale;
+
+    public DecimalImpl( Integer precision, Integer scale )
+    {
+        super( Decimal.class );
+
+        this._precision = precision;
+        this._scale = scale;
+    }
+
+    @Override
+    protected boolean doesEqual( Decimal another )
+    {
+        return bothNullOrEquals( this._precision, another.getPrecision() )
+               && bothNullOrEquals( this._scale, another.getScale() );
+    }
+
+    /**
+     * Returns the precision (first integer) for this {@code DECIMAL}.
+     *
+     * @return The precision for this {@code DECIMAL}.
+     */
+    public Integer getPrecision()
+    {
+        return this._precision;
+    }
+
+    /**
+     * Returns the scale (second integer) for this {@code DECIMAL}.
+     *
+     * @return The precision for this {@code DECIMAL}.
+     */
+    public Integer getScale()
+    {
+        return this._scale;
+    }
+
+    /**
+     * This instance represents {@code DECIMAL} without precision and scale.
+     */
+    public static final Decimal PLAIN_DECIMAL = new DecimalImpl( null, null );
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/DoublePrecisionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/DoublePrecisionImpl.java
new file mode 100644
index 0000000..8c68de3
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/DoublePrecisionImpl.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common.datatypes;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.DoublePrecision;
+
+public final class DoublePrecisionImpl
+    implements DoublePrecision
+{
+    public DoublePrecisionImpl()
+    {
+    }
+
+    /**
+     * Returns {@link DoublePrecision}.
+     */
+    public Class<DoublePrecision> getImplementedType()
+    {
+        return DoublePrecision.class;
+    }
+
+    /**
+     * A singleton instance of {@code DOUBLE PRECISION} data type.
+     */
+    public static final DoublePrecision INSTANCE = new DoublePrecisionImpl();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/NumericImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/NumericImpl.java
new file mode 100644
index 0000000..c426231
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/NumericImpl.java
@@ -0,0 +1,73 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common.datatypes;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.Numeric;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDataType;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public final class NumericImpl extends TypeableImpl<SQLDataType, Numeric>
+    implements Numeric
+{
+    private final Integer _precision;
+    private final Integer _scale;
+
+    public NumericImpl( Integer precision, Integer scale )
+    {
+        super( Numeric.class );
+        this._precision = precision;
+        this._scale = scale;
+    }
+
+    @Override
+    protected boolean doesEqual( Numeric another )
+    {
+        return bothNullOrEquals( this._precision, another.getPrecision() )
+               && bothNullOrEquals( this._scale, another.getScale() );
+    }
+
+    /**
+     * Returns the precision (first integer) for this {@code NUMERIC}.
+     *
+     * @return The precision for this {@code NUMERIC}.
+     */
+    public Integer getPrecision()
+    {
+        return this._precision;
+    }
+
+    /**
+     * Returns the scale (second integer) for this {@code NUMERIC}.
+     *
+     * @return The precision for this {@code NUMERIC}.
+     */
+    public Integer getScale()
+    {
+        return this._scale;
+    }
+
+    /**
+     * This instance represents {@code NUMERIC} without precision and scale.
+     */
+    public static final Numeric PLAIN_NUMERIC = new NumericImpl( null, null );
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/RealImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/RealImpl.java
new file mode 100644
index 0000000..19a3bb4
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/RealImpl.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common.datatypes;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.Real;
+
+public final class RealImpl
+    implements Real
+{
+    public RealImpl()
+    {
+    }
+
+    /**
+     * Returns {@link Real}.
+     */
+    public Class<Real> getImplementedType()
+    {
+        return Real.class;
+    }
+
+    /**
+     * A singleton instance of {@code REAL}.
+     */
+    public static final Real INSTANCE = new RealImpl();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLBooleanImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLBooleanImpl.java
new file mode 100644
index 0000000..081172e
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLBooleanImpl.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common.datatypes;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLBoolean;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public final class SQLBooleanImpl
+    implements SQLBoolean
+{
+    public SQLBooleanImpl()
+    {
+
+    }
+
+    /**
+     * Returns {@link SQLBoolean}.
+     */
+    public Class<SQLBoolean> getImplementedType()
+    {
+        return SQLBoolean.class;
+    }
+
+    /**
+     * The singleton instance of {@code BOOLEAN}.
+     */
+    public static final SQLBoolean INSTANCE = new SQLBooleanImpl();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLCharImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLCharImpl.java
new file mode 100644
index 0000000..e5d3fb0
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLCharImpl.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common.datatypes;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLChar;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDataType;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+
+public final class SQLCharImpl extends TypeableImpl<SQLDataType, SQLChar>
+    implements SQLChar
+{
+    private final Boolean _isVarying;
+    private final Integer _length;
+
+    public SQLCharImpl( Boolean isVarying, Integer length )
+    {
+        super( SQLChar.class );
+        this._isVarying = isVarying;
+        this._length = length;
+    }
+
+    @Override
+    protected boolean doesEqual( SQLChar another )
+    {
+        return this._isVarying.equals( another.isVarying() ) && bothNullOrEquals( this._length, another.getLength() );
+    }
+
+    /**
+     * Returns {@code true} if this is {@code CHARACTER VARYING}; {@code false otherwise}.
+     *
+     * @return {@code true} if this is {@code CHARACTER VARYING}; {@code false otherwise}.
+     */
+    public Boolean isVarying()
+    {
+        return this._isVarying;
+    }
+
+    /**
+     * Returns the length specification for this {@code CHARACTER} or {@code CHARACTER VARYING}. Returns {@code null} if
+     * none specified.
+     *
+     * @return The length for this {@code CHARACTER} or {@code CHARACTER VARYING}.
+     */
+    public Integer getLength()
+    {
+        return this._length;
+    }
+
+    public static final SQLChar PLAIN_FIXED = new SQLCharImpl( false, null );
+
+    public static final SQLChar PLAIN_VARYING = new SQLCharImpl( true, null );
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLDateImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLDateImpl.java
new file mode 100644
index 0000000..f2a1f8c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLDateImpl.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common.datatypes;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDate;
+
+public final class SQLDateImpl
+    implements SQLDate
+{
+    public SQLDateImpl()
+    {
+    }
+
+    /**
+     * Returns {@link SQLDate}.
+     */
+    public Class<SQLDate> getImplementedType()
+    {
+        return SQLDate.class;
+    }
+
+    /**
+     * A singleton instance of {@code DATE} data type.
+     */
+    public static final SQLDate INSTANCE = new SQLDateImpl();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLFloatImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLFloatImpl.java
new file mode 100644
index 0000000..2a1bc47
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLFloatImpl.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common.datatypes;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDataType;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLFloat;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public final class SQLFloatImpl extends TypeableImpl<SQLDataType, SQLFloat>
+    implements SQLFloat
+{
+    private final Integer _precision;
+
+    public SQLFloatImpl( Integer precision )
+    {
+        super( SQLFloat.class );
+        this._precision = precision;
+    }
+
+    @Override
+    protected boolean doesEqual( SQLFloat another )
+    {
+        return bothNullOrEquals( this._precision, another.getPrecision() );
+    }
+
+    /**
+     * Returns the precision for this {@code FLOAT}.
+     *
+     * @return The precision for this {@code FLOAT}.
+     */
+    public Integer getPrecision()
+    {
+        return this._precision;
+    }
+
+    /**
+     * This instance represents {@code FLOAT} without precision.
+     */
+    public static final SQLFloat PLAIN_FLOAT = new SQLFloatImpl( null );
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLIntegerImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLIntegerImpl.java
new file mode 100644
index 0000000..e80ed6c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLIntegerImpl.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common.datatypes;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLInteger;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public final class SQLIntegerImpl
+    implements SQLInteger
+{
+    public SQLIntegerImpl()
+    {
+    }
+
+    /**
+     * Returns {@link SQLInteger}.
+     */
+    public Class<SQLInteger> getImplementedType()
+    {
+        return SQLInteger.class;
+    }
+
+    /**
+     * The singleton instance of {@code INTEGER}.
+     */
+    public static final SQLInteger INSTANCE = new SQLIntegerImpl();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLIntervalImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLIntervalImpl.java
new file mode 100644
index 0000000..9b9e239
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLIntervalImpl.java
@@ -0,0 +1,103 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common.datatypes;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.IntervalDataType;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDataType;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLInterval;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class SQLIntervalImpl extends TypeableImpl<SQLDataType, SQLInterval>
+    implements SQLInterval
+{
+
+    private final IntervalDataType _startField;
+
+    private final Integer _startFieldPrecision;
+
+    private final IntervalDataType _endField;
+
+    private final Integer _secondFracs;
+
+    public SQLIntervalImpl( IntervalDataType startField, Integer startFieldPrecision, IntervalDataType endField,
+                            Integer secondFracs )
+    {
+        super( SQLInterval.class );
+        this._startField = startField;
+        this._startFieldPrecision = startFieldPrecision;
+        this._endField = endField;
+        this._secondFracs = secondFracs;
+    }
+
+    @Override
+    protected boolean doesEqual( SQLInterval another )
+    {
+        return this._startField.equals( another.getStartField() )
+               && bothNullOrEquals( this._startFieldPrecision, another.getStartFieldPrecision() )
+               && bothNullOrEquals( this._endField, another.getEndField() )
+               && bothNullOrEquals( this._secondFracs, another.getSecondFracs() );
+    }
+
+    /**
+     * Returns the start field type for this {@code INTERVAL}.
+     *
+     * @return The start field type for this {@code INTERVAL}.
+     */
+    public IntervalDataType getStartField()
+    {
+        return this._startField;
+    }
+
+    /**
+     * Return the start field precision for this {@code INTERVAL}. May be {@code null} if none specified.
+     *
+     * @return The start field precision for this {@code INTERVAL}.
+     */
+    public Integer getStartFieldPrecision()
+    {
+        return this._startFieldPrecision;
+    }
+
+    /**
+     * Returns the end field precision for this {@code INTERVAL}. Will always be {@code null} for single datetime field
+     * intervals.
+     *
+     * @return The end field precision for this {@code INTERVAL}.
+     */
+    public IntervalDataType getEndField()
+    {
+        return this._endField;
+    }
+
+    /**
+     * Returns the fraction seconds precision for this {@code INTERVAL}. Will always be {@code null} if the end field
+     * type is not {@link IntervalDataType#SECOND}, or if this is single datetime field interval, and its start type is
+     * not {@link IntervalDataType#SECOND}.
+     *
+     * @return The fraction seconds precision for this {@code INTERVAL}.
+     */
+    public Integer getSecondFracs()
+    {
+        return this._secondFracs;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLTimeImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLTimeImpl.java
new file mode 100644
index 0000000..bb271ed
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLTimeImpl.java
@@ -0,0 +1,72 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common.datatypes;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDataType;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLTime;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public final class SQLTimeImpl extends TypeableImpl<SQLDataType, SQLTime>
+    implements SQLTime
+{
+    private final Integer _precision;
+    private final Boolean _withTimeZone;
+
+    public SQLTimeImpl( Integer precision, Boolean withTimeZone )
+    {
+        super( SQLTime.class );
+        this._precision = precision;
+        this._withTimeZone = withTimeZone;
+    }
+
+    @Override
+    protected boolean doesEqual( SQLTime another )
+    {
+        return bothNullOrEquals( this._precision, another.getPrecision() )
+               && bothNullOrEquals( this._withTimeZone, another.isWithTimeZone() );
+    }
+
+    /**
+     * Returns the precision for this {@code TIME}. May be {@code null}.
+     *
+     * @return The precision for this {@code TIME}.
+     */
+    public Integer getPrecision()
+    {
+        return this._precision;
+    }
+
+    /**
+     * Returns whether the {@code TIME} should be with time zone. May be {@code null} if no choice specified.
+     */
+    public Boolean isWithTimeZone()
+    {
+        return this._withTimeZone;
+    }
+
+    public static final SQLTime PLAIN_TIME = new SQLTimeImpl( null, null );
+
+    public static final SQLTime PLAIN_TIME_WITHOUT_TZ = new SQLTimeImpl( null, false );
+
+    public static final SQLTime PLAIN_TIME_WITH_TZ = new SQLTimeImpl( null, true );
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLTimeStampImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLTimeStampImpl.java
new file mode 100644
index 0000000..f707a9c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SQLTimeStampImpl.java
@@ -0,0 +1,74 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common.datatypes;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDataType;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLTimeStamp;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+
+/**
+ * This class represents {@code TIMESTAMP} data type.
+ *
+ * @author Stanislav Muhametsin
+ */
+public final class SQLTimeStampImpl extends TypeableImpl<SQLDataType, SQLTimeStamp>
+    implements SQLTimeStamp
+{
+    private final Integer _precision;
+    private final Boolean _withTimeZone;
+
+    public SQLTimeStampImpl( Integer precision, Boolean withTimeZone )
+    {
+        super( SQLTimeStamp.class );
+        this._precision = precision;
+        this._withTimeZone = withTimeZone;
+    }
+
+    @Override
+    protected boolean doesEqual( SQLTimeStamp another )
+    {
+        return bothNullOrEquals( this._precision, another.getPrecision() )
+               && bothNullOrEquals( this._withTimeZone, another.isWithTimeZone() );
+    }
+
+    /**
+     * Returns the precision for this {@code TIMESTAMP}. May be {@code null}.
+     *
+     * @return The precision for this {@code TIMESTAMP}.
+     */
+    public Integer getPrecision()
+    {
+        return this._precision;
+    }
+
+    /**
+     * Returns whether the {@code TIMESTAMP} should be with time zone. May be {@code null} if no choice specified.
+     */
+    public Boolean isWithTimeZone()
+    {
+        return this._withTimeZone;
+    }
+
+    public static final SQLTimeStamp PLAIN_TIMESTAMP = new SQLTimeStampImpl( null, null );
+
+    public static final SQLTimeStamp PLAIN_TIMESTAMP_WITHOUT_TZ = new SQLTimeStampImpl( null, false );
+
+    public static final SQLTimeStamp PLAIN_TIMESTAMP_WITH_TZ = new SQLTimeStampImpl( null, true );
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SmallIntImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SmallIntImpl.java
new file mode 100644
index 0000000..e931873
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/SmallIntImpl.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common.datatypes;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SmallInt;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public final class SmallIntImpl
+    implements SmallInt
+{
+    public SmallIntImpl()
+    {
+    }
+
+    /**
+     * Returns {@link SmallInt}.
+     */
+    public Class<SmallInt> getImplementedType()
+    {
+        return SmallInt.class;
+    }
+
+    /**
+     * The singleton instance of {@code SMALLINT}.
+     */
+    public static final SmallInt INSTANCE = new SmallIntImpl();
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/UserDefinedTypeImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/UserDefinedTypeImpl.java
new file mode 100644
index 0000000..8a7e119
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/UserDefinedTypeImpl.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common.datatypes;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDataType;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.UserDefinedType;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class UserDefinedTypeImpl extends TypeableImpl<SQLDataType, UserDefinedType>
+    implements UserDefinedType
+{
+
+    private final String _text;
+
+    public UserDefinedTypeImpl( String textContent )
+    {
+        this( UserDefinedType.class, textContent );
+    }
+
+    protected UserDefinedTypeImpl( Class<? extends UserDefinedType> realImplementingType, String textContent )
+    {
+        super( realImplementingType );
+
+        this._text = textContent;
+    }
+
+    @Override
+    protected boolean doesEqual( UserDefinedType another )
+    {
+        return bothNullOrEquals( this._text, another.getTextualRepresentation() );
+    }
+
+    public String getTextualRepresentation()
+    {
+        return this._text;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/pgsql/TextImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/pgsql/TextImpl.java
new file mode 100644
index 0000000..0667f16
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/common/datatypes/pgsql/TextImpl.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.common.datatypes.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.pgsql.Text;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TextImpl
+    implements Text
+{
+
+    public TextImpl()
+    {
+    }
+
+    /**
+     * Returns {@link Text}.
+     */
+    public Class<Text> getImplementedType()
+    {
+        return Text.class;
+    }
+
+    /**
+     * A singleton instance of {@code TEXT} data type.
+     */
+    public static Text INSTANCE = new TextImpl();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/schema/SchemaDefinitionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/schema/SchemaDefinitionImpl.java
new file mode 100644
index 0000000..6a376f3
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/schema/SchemaDefinitionImpl.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.definition.schema;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.SchemaStatement;
+import org.apache.polygene.library.sql.generator.grammar.definition.schema.SchemaDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.schema.SchemaElement;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class SchemaDefinitionImpl extends SQLSyntaxElementBase<SchemaStatement, SchemaDefinition>
+    implements SchemaDefinition
+{
+
+    private final String _charset;
+    private final String _name;
+    private final List<SchemaElement> _elements;
+
+    public SchemaDefinitionImpl( SQLProcessorAggregator processor, String name, String charset,
+                                 List<SchemaElement> elements )
+    {
+        this( processor, SchemaDefinition.class, name, charset, elements );
+    }
+
+    protected SchemaDefinitionImpl( SQLProcessorAggregator processor,
+                                    Class<? extends SchemaDefinition> realImplementingType, String name, String charset,
+                                    List<SchemaElement> elements )
+    {
+        super( processor, realImplementingType );
+
+        Objects.requireNonNull( name, "Schema name" );
+        Objects.requireNonNull( elements, "Elements" );
+
+        this._name = name;
+        this._charset = charset;
+        this._elements = Collections.unmodifiableList( new ArrayList<SchemaElement>( elements ) );
+    }
+
+    @Override
+    protected boolean doesEqual( SchemaDefinition another )
+    {
+        return this._name.equals( another.getSchemaName() ) && this._elements.equals( another.getSchemaElements() )
+               && TypeableImpl.bothNullOrEquals( this._charset, another.getSchemaCharset() );
+    }
+
+    public String getSchemaCharset()
+    {
+        return this._charset;
+    }
+
+    public List<SchemaElement> getSchemaElements()
+    {
+        return this._elements;
+    }
+
+    public String getSchemaName()
+    {
+        return this._name;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/CheckConstraintImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/CheckConstraintImpl.java
new file mode 100644
index 0000000..175744f
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/CheckConstraintImpl.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.definition.table;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.CheckConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraint;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class CheckConstraintImpl extends SQLSyntaxElementBase<TableConstraint, CheckConstraint>
+    implements CheckConstraint
+{
+
+    private final BooleanExpression _searchCondition;
+
+    public CheckConstraintImpl( SQLProcessorAggregator processor, BooleanExpression searchCondition )
+    {
+        this( processor, CheckConstraint.class, searchCondition );
+    }
+
+    protected CheckConstraintImpl( SQLProcessorAggregator processor,
+                                   Class<? extends CheckConstraint> realImplementingType, BooleanExpression searchCondition )
+    {
+        super( processor, realImplementingType );
+
+        this._searchCondition = searchCondition;
+    }
+
+    @Override
+    protected boolean doesEqual( CheckConstraint another )
+    {
+        return TypeableImpl.bothNullOrEquals( this._searchCondition, another.getCheckCondition() );
+    }
+
+    public BooleanExpression getCheckCondition()
+    {
+        return this._searchCondition;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/ColumnDefinitionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/ColumnDefinitionImpl.java
new file mode 100644
index 0000000..9a19e4f
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/ColumnDefinitionImpl.java
@@ -0,0 +1,99 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.definition.table;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDataType;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.AutoGenerationPolicy;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableElement;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ColumnDefinitionImpl extends SQLSyntaxElementBase<TableElement, ColumnDefinition>
+    implements ColumnDefinition
+{
+
+    private final String _name;
+    private final SQLDataType _dataType;
+    private final String _default;
+    private final Boolean _mayBeNull;
+    private final AutoGenerationPolicy _autoGenerationPolicy;
+
+    public ColumnDefinitionImpl( SQLProcessorAggregator processor, String name, SQLDataType dataType,
+                                 String defaultStr, Boolean mayBeNull, AutoGenerationPolicy autoGenerationPolicy )
+    {
+        this( processor, ColumnDefinition.class, name, dataType, defaultStr, mayBeNull, autoGenerationPolicy );
+    }
+
+    protected ColumnDefinitionImpl( SQLProcessorAggregator processor,
+                                    Class<? extends ColumnDefinition> realImplementingType, String name, SQLDataType dataType, String defaultStr,
+                                    Boolean mayBeNull, AutoGenerationPolicy autoGenerationPolicy )
+    {
+        super( processor, realImplementingType );
+
+        Objects.requireNonNull( name, "Column name" );
+        Objects.requireNonNull( dataType, "Column data type" );
+        Objects.requireNonNull( mayBeNull, "Null policy" );
+
+        this._name = name;
+        this._dataType = dataType;
+        this._default = defaultStr;
+        this._mayBeNull = mayBeNull;
+        this._autoGenerationPolicy = autoGenerationPolicy;
+    }
+
+    @Override
+    protected boolean doesEqual( ColumnDefinition another )
+    {
+        return this._name.equals( another.getColumnName() ) && this._dataType.equals( another.getDataType() )
+               && TypeableImpl.bothNullOrEquals( this._default, another.getDefault() )
+               && this._mayBeNull.equals( another.mayBeNull() );
+    }
+
+    public String getColumnName()
+    {
+        return this._name;
+    }
+
+    public SQLDataType getDataType()
+    {
+        return this._dataType;
+    }
+
+    public String getDefault()
+    {
+        return this._default;
+    }
+
+    public Boolean mayBeNull()
+    {
+        return this._mayBeNull;
+    }
+
+    public AutoGenerationPolicy getAutoGenerationPolicy()
+    {
+        return this._autoGenerationPolicy;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/ForeignKeyConstraintImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/ForeignKeyConstraintImpl.java
new file mode 100644
index 0000000..e856424
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/ForeignKeyConstraintImpl.java
@@ -0,0 +1,113 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.definition.table;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ForeignKeyConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.MatchType;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ReferentialAction;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraint;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ForeignKeyConstraintImpl extends SQLSyntaxElementBase<TableConstraint, ForeignKeyConstraint>
+    implements ForeignKeyConstraint
+{
+
+    private final ColumnNameList _sourceColumns;
+    private final TableNameDirect _targetTableName;
+    private final ColumnNameList _targetColumns;
+    private final MatchType _matchType;
+    private final ReferentialAction _onDelete;
+    private final ReferentialAction _onUpdate;
+
+    public ForeignKeyConstraintImpl( SQLProcessorAggregator processor, ColumnNameList sourceColumns,
+                                     TableNameDirect targetTableName, ColumnNameList targetColumns, MatchType matchType, ReferentialAction onDelete,
+                                     ReferentialAction onUpdate )
+    {
+        this( processor, ForeignKeyConstraint.class, sourceColumns, targetTableName, targetColumns, matchType,
+              onDelete, onUpdate );
+    }
+
+    protected ForeignKeyConstraintImpl( SQLProcessorAggregator processor,
+                                        Class<? extends ForeignKeyConstraint> realImplementingType, ColumnNameList sourceColumns,
+                                        TableNameDirect targetTableName, ColumnNameList targetColumns, MatchType matchType, ReferentialAction onDelete,
+                                        ReferentialAction onUpdate )
+    {
+        super( processor, realImplementingType );
+
+        Objects.requireNonNull( sourceColumns, "Source columns" );
+        Objects.requireNonNull( targetTableName, "Target table name" );
+
+        this._sourceColumns = sourceColumns;
+        this._targetTableName = targetTableName;
+        this._targetColumns = targetColumns;
+        this._matchType = matchType;
+        this._onDelete = onDelete;
+        this._onUpdate = onUpdate;
+    }
+
+    @Override
+    protected boolean doesEqual( ForeignKeyConstraint another )
+    {
+        return this._targetTableName.equals( another.getTargetTableName() )
+               && this._sourceColumns.equals( another.getSourceColumns() )
+               && TypeableImpl.bothNullOrEquals( this._targetColumns, another.getTargetColumns() )
+               && TypeableImpl.bothNullOrEquals( this._matchType, another.getMatchType() )
+               && TypeableImpl.bothNullOrEquals( this._onDelete, another.getOnDelete() )
+               && TypeableImpl.bothNullOrEquals( this._onUpdate, another.getOnUpdate() );
+    }
+
+    public MatchType getMatchType()
+    {
+        return this._matchType;
+    }
+
+    public ReferentialAction getOnDelete()
+    {
+        return this._onDelete;
+    }
+
+    public ReferentialAction getOnUpdate()
+    {
+        return this._onUpdate;
+    }
+
+    public ColumnNameList getSourceColumns()
+    {
+        return this._sourceColumns;
+    }
+
+    public ColumnNameList getTargetColumns()
+    {
+        return this._targetColumns;
+    }
+
+    public TableNameDirect getTargetTableName()
+    {
+        return this._targetTableName;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/LikeClauseImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/LikeClauseImpl.java
new file mode 100644
index 0000000..d763b7a
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/LikeClauseImpl.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.definition.table;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.LikeClause;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableElement;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class LikeClauseImpl extends SQLSyntaxElementBase<TableElement, LikeClause>
+    implements LikeClause
+{
+
+    private final TableNameDirect _tableName;
+
+    public LikeClauseImpl( SQLProcessorAggregator processor, TableNameDirect tableName )
+    {
+        this( processor, LikeClause.class, tableName );
+    }
+
+    protected LikeClauseImpl( SQLProcessorAggregator processor, Class<? extends LikeClause> realImplementingType,
+                              TableNameDirect tableName )
+    {
+        super( processor, realImplementingType );
+
+        Objects.requireNonNull( tableName, "Table name" );
+
+        this._tableName = tableName;
+    }
+
+    @Override
+    protected boolean doesEqual( LikeClause another )
+    {
+        return this._tableName.equals( another.getTableName() );
+    }
+
+    public TableNameDirect getTableName()
+    {
+        return this._tableName;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/TableConstraintDefinitionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/TableConstraintDefinitionImpl.java
new file mode 100644
index 0000000..0998576
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/TableConstraintDefinitionImpl.java
@@ -0,0 +1,83 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.definition.table;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ConstraintCharacteristics;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableElement;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TableConstraintDefinitionImpl extends SQLSyntaxElementBase<TableElement, TableConstraintDefinition>
+    implements TableConstraintDefinition
+{
+
+    private final String _name;
+    private final TableConstraint _constraint;
+    private final ConstraintCharacteristics _characteristics;
+
+    public TableConstraintDefinitionImpl( SQLProcessorAggregator processor, String name, TableConstraint constraint,
+                                          ConstraintCharacteristics characteristics )
+    {
+        this( processor, TableConstraintDefinition.class, name, constraint, characteristics );
+    }
+
+    protected TableConstraintDefinitionImpl( SQLProcessorAggregator processor,
+                                             Class<? extends TableConstraintDefinition> realImplementingType, String name, TableConstraint constraint,
+                                             ConstraintCharacteristics characteristics )
+    {
+        super( processor, realImplementingType );
+
+        Objects.requireNonNull( constraint, "Constraint" );
+
+        this._constraint = constraint;
+        this._name = name;
+        this._characteristics = characteristics;
+    }
+
+    @Override
+    protected boolean doesEqual( TableConstraintDefinition another )
+    {
+        return this._constraint.equals( another.getConstraint() )
+               && TypeableImpl.bothNullOrEquals( this._name, another.getConstraintName() )
+               && TypeableImpl.bothNullOrEquals( this._characteristics, another.getCharacteristics() );
+    }
+
+    public ConstraintCharacteristics getCharacteristics()
+    {
+        return this._characteristics;
+    }
+
+    public TableConstraint getConstraint()
+    {
+        return this._constraint;
+    }
+
+    public String getConstraintName()
+    {
+        return this._name;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/TableDefinitionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/TableDefinitionImpl.java
new file mode 100644
index 0000000..6abed15
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/TableDefinitionImpl.java
@@ -0,0 +1,99 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.definition.table;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.SchemaStatement;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableCommitAction;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableContentsSource;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableScope;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TableDefinitionImpl extends SQLSyntaxElementBase<SchemaStatement, TableDefinition>
+    implements TableDefinition
+{
+
+    private final TableCommitAction _commitAction;
+    private final TableContentsSource _contents;
+    private final TableNameDirect _name;
+    private final TableScope _scope;
+
+    public TableDefinitionImpl( SQLProcessorAggregator processor, TableCommitAction commitAction,
+                                TableContentsSource contents, TableNameDirect name, TableScope scope )
+    {
+        this( processor, TableDefinition.class, commitAction, contents, name, scope );
+    }
+
+    protected TableDefinitionImpl( SQLProcessorAggregator processor,
+                                   Class<? extends TableDefinition> realImplementingType, TableCommitAction commitAction,
+                                   TableContentsSource contents, TableNameDirect name, TableScope scope )
+    {
+        super( processor, realImplementingType );
+
+        Objects.requireNonNull( name, "Table name" );
+        Objects.requireNonNull( contents, "Table contents" );
+
+        this._name = name;
+        this._contents = contents;
+        this._scope = scope;
+        this._commitAction = commitAction;
+    }
+
+    @Override
+    protected boolean doesEqual( TableDefinition another )
+    {
+        return this._name.equals( another.getTableName() ) && this._contents.equals( another.getContents() )
+               && TypeableImpl.bothNullOrEquals( this._scope, another.getTableScope() )
+               && TypeableImpl.bothNullOrEquals( this._commitAction, another.getCommitAction() );
+    }
+
+    public Typeable<?> asTypeable()
+    {
+        return this;
+    }
+
+    public TableCommitAction getCommitAction()
+    {
+        return this._commitAction;
+    }
+
+    public TableContentsSource getContents()
+    {
+        return this._contents;
+    }
+
+    public TableNameDirect getTableName()
+    {
+        return this._name;
+    }
+
+    public TableScope getTableScope()
+    {
+        return this._scope;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/TableElementListImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/TableElementListImpl.java
new file mode 100644
index 0000000..7114482
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/TableElementListImpl.java
@@ -0,0 +1,65 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.definition.table;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableContentsSource;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableElement;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableElementList;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TableElementListImpl extends SQLSyntaxElementBase<TableContentsSource, TableElementList>
+    implements TableElementList
+{
+
+    private final List<TableElement> _elements;
+
+    public TableElementListImpl( SQLProcessorAggregator processor, List<TableElement> elements )
+    {
+        this( processor, TableElementList.class, elements );
+    }
+
+    protected TableElementListImpl( SQLProcessorAggregator processor,
+                                    Class<? extends TableElementList> realImplementingType, List<TableElement> elements )
+    {
+        super( processor, realImplementingType );
+
+        Objects.requireNonNull( elements, "Table elements" );
+
+        this._elements = Collections.unmodifiableList( elements );
+    }
+
+    @Override
+    protected boolean doesEqual( TableElementList another )
+    {
+        return this._elements.equals( another.getElementList() );
+    }
+
+    public List<TableElement> getElementList()
+    {
+        return this._elements;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/UniqueConstraintImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/UniqueConstraintImpl.java
new file mode 100644
index 0000000..8a115ba
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/table/UniqueConstraintImpl.java
@@ -0,0 +1,74 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.definition.table;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.UniqueConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.UniqueSpecification;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class UniqueConstraintImpl extends SQLSyntaxElementBase<TableConstraint, UniqueConstraint>
+    implements UniqueConstraint
+{
+
+    private final ColumnNameList _columns;
+    private final UniqueSpecification _uniqueness;
+
+    public UniqueConstraintImpl( SQLProcessorAggregator processor, ColumnNameList columns,
+                                 UniqueSpecification uniqueness )
+    {
+        this( processor, UniqueConstraint.class, columns, uniqueness );
+    }
+
+    protected UniqueConstraintImpl( SQLProcessorAggregator processor,
+                                    Class<? extends UniqueConstraint> realImplementingType, ColumnNameList columns, UniqueSpecification uniqueness )
+    {
+        super( processor, realImplementingType );
+
+        Objects.requireNonNull( columns, "Columns" );
+        Objects.requireNonNull( uniqueness, "Uniqueness" );
+
+        this._columns = columns;
+        this._uniqueness = uniqueness;
+    }
+
+    @Override
+    protected boolean doesEqual( UniqueConstraint another )
+    {
+        return this._uniqueness.equals( another.getUniquenessKind() )
+               && this._columns.equals( another.getColumnNameList() );
+    }
+
+    public ColumnNameList getColumnNameList()
+    {
+        return this._columns;
+    }
+
+    public UniqueSpecification getUniquenessKind()
+    {
+        return this._uniqueness;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/view/RegularViewSpecificationImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/view/RegularViewSpecificationImpl.java
new file mode 100644
index 0000000..79aa362
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/view/RegularViewSpecificationImpl.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.definition.view;
+
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.RegularViewSpecification;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.ViewSpecification;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class RegularViewSpecificationImpl extends SQLSyntaxElementBase<ViewSpecification, RegularViewSpecification>
+    implements RegularViewSpecification
+{
+
+    private final ColumnNameList _columns;
+
+    public RegularViewSpecificationImpl( SQLProcessorAggregator processor, ColumnNameList columns )
+    {
+        this( processor, RegularViewSpecification.class, columns );
+    }
+
+    protected RegularViewSpecificationImpl( SQLProcessorAggregator processor,
+                                            Class<? extends RegularViewSpecification> realImplementingType, ColumnNameList columns )
+    {
+        super( processor, realImplementingType );
+
+        this._columns = columns;
+    }
+
+    @Override
+    protected boolean doesEqual( RegularViewSpecification another )
+    {
+        return this._columns.equals( another.getColumns() );
+    }
+
+    public ColumnNameList getColumns()
+    {
+        return this._columns;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/view/ViewDefinitionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/view/ViewDefinitionImpl.java
new file mode 100644
index 0000000..202ae9c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/definition/view/ViewDefinitionImpl.java
@@ -0,0 +1,108 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.definition.view;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.SchemaStatement;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.ViewCheckOption;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.ViewDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.ViewSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ViewDefinitionImpl extends SQLSyntaxElementBase<SchemaStatement, ViewDefinition>
+    implements ViewDefinition
+{
+
+    private final TableNameDirect _name;
+    private final QueryExpression _query;
+    private final ViewSpecification _spec;
+    private final ViewCheckOption _viewCheck;
+    private final Boolean _isRecursive;
+
+    public ViewDefinitionImpl( SQLProcessorAggregator processor, TableNameDirect name, QueryExpression query,
+                               ViewSpecification spec, ViewCheckOption viewCheck, Boolean isRecursive )
+    {
+        this( processor, ViewDefinition.class, name, query, spec, viewCheck, isRecursive );
+    }
+
+    protected ViewDefinitionImpl( SQLProcessorAggregator processor,
+                                  Class<? extends ViewDefinition> realImplementingType, TableNameDirect name, QueryExpression query,
+                                  ViewSpecification spec, ViewCheckOption viewCheck, Boolean isRecursive )
+    {
+        super( processor, realImplementingType );
+
+        Objects.requireNonNull( name, "View name" );
+        Objects.requireNonNull( query, "View query" );
+        Objects.requireNonNull( isRecursive, "Is recursive" );
+        Objects.requireNonNull( spec, "View specification" );
+
+        this._name = name;
+        this._query = query;
+        this._spec = spec;
+        this._isRecursive = isRecursive;
+        this._viewCheck = viewCheck;
+    }
+
+    @Override
+    protected boolean doesEqual( ViewDefinition another )
+    {
+        return this._name.equals( another.getViewName() ) && this._isRecursive.equals( another.isRecursive() )
+               && this._spec.equals( another.getViewSpecification() ) && this._query.equals( another.getViewQuery() )
+               && TypeableImpl.bothNullOrEquals( this._viewCheck, another.getViewCheckOption() );
+    }
+
+    public Typeable<?> asTypeable()
+    {
+        return this;
+    }
+
+    public ViewCheckOption getViewCheckOption()
+    {
+        return this._viewCheck;
+    }
+
+    public TableNameDirect getViewName()
+    {
+        return this._name;
+    }
+
+    public QueryExpression getViewQuery()
+    {
+        return this._query;
+    }
+
+    public ViewSpecification getViewSpecification()
+    {
+        return this._spec;
+    }
+
+    public Boolean isRecursive()
+    {
+        return this._isRecursive;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractBooleanFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractBooleanFactory.java
new file mode 100644
index 0000000..e0ec1a7
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractBooleanFactory.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.InPredicate;
+import org.apache.polygene.library.sql.generator.grammar.builders.booleans.BooleanBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.factories.BooleanFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLFactoryBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class AbstractBooleanFactory extends SQLFactoryBase
+    implements BooleanFactory
+{
+
+    protected AbstractBooleanFactory( SQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    public BooleanBuilder booleanBuilder()
+    {
+        return this.booleanBuilder( null );
+    }
+
+    public InPredicate in( NonBooleanExpression what, NonBooleanExpression... values )
+    {
+        return this.inBuilder( what ).addValues( values ).createExpression();
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractColumnsFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractColumnsFactory.java
new file mode 100644
index 0000000..c67e8a8
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractColumnsFactory.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.factories.ColumnsFactory;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferenceByName;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLFactoryBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class AbstractColumnsFactory extends SQLFactoryBase
+    implements ColumnsFactory
+{
+
+    protected AbstractColumnsFactory( SQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    public ColumnReferenceByName colName( String colName )
+    {
+        return this.colName( null, colName );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractDataTypeFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractDataTypeFactory.java
new file mode 100644
index 0000000..f4944dd
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractDataTypeFactory.java
@@ -0,0 +1,109 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.Decimal;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.Numeric;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLChar;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLFloat;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLTime;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLTimeStamp;
+import org.apache.polygene.library.sql.generator.grammar.factories.DataTypeFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLFactoryBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class AbstractDataTypeFactory extends SQLFactoryBase
+    implements DataTypeFactory
+{
+
+    protected AbstractDataTypeFactory( SQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    public Decimal decimal()
+    {
+        return this.decimal( null, null );
+    }
+
+    public Decimal decimal( Integer precision )
+    {
+        return this.decimal( precision, null );
+    }
+
+    public Numeric numeric()
+    {
+        return this.numeric( null, null );
+    }
+
+    public Numeric numeric( Integer precision )
+    {
+        return this.numeric( precision, null );
+    }
+
+    public SQLChar sqlChar()
+    {
+        return this.sqlChar( null );
+    }
+
+    public SQLFloat sqlFloat()
+    {
+        return this.sqlFloat( null );
+    }
+
+    public SQLChar sqlVarChar()
+    {
+        return this.sqlVarChar( null );
+    }
+
+    public SQLTime time()
+    {
+        return this.time( null, null );
+    }
+
+    public SQLTime time( Boolean withTimeZone )
+    {
+        return this.time( null, withTimeZone );
+    }
+
+    public SQLTime time( Integer precision )
+    {
+        return this.time( precision, null );
+    }
+
+    public SQLTimeStamp timeStamp()
+    {
+        return this.timeStamp( null, null );
+    }
+
+    public SQLTimeStamp timeStamp( Boolean withTimeZone )
+    {
+        return this.timeStamp( null, withTimeZone );
+    }
+
+    public SQLTimeStamp timeStamp( Integer precision )
+    {
+        return this.timeStamp( precision, null );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractDefinitionFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractDefinitionFactory.java
new file mode 100644
index 0000000..dcccb79
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractDefinitionFactory.java
@@ -0,0 +1,90 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDataType;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.AutoGenerationPolicy;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ConstraintCharacteristics;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.factories.DefinitionFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLFactoryBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class AbstractDefinitionFactory extends SQLFactoryBase
+    implements DefinitionFactory
+{
+
+    protected AbstractDefinitionFactory( SQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    public ColumnDefinition createColumnDefinition( String columnName, SQLDataType columnDataType )
+    {
+        return this.createColumnDefinition( columnName, columnDataType, null, true );
+    }
+
+    public ColumnDefinition createColumnDefinition( String columnName, SQLDataType columnDataType, Boolean mayBeNull )
+    {
+        return this.createColumnDefinition( columnName, columnDataType, null, mayBeNull );
+    }
+
+    public ColumnDefinition createColumnDefinition( String columnName, SQLDataType columnDataType, String columnDefault )
+    {
+        return this.createColumnDefinition( columnName, columnDataType, columnDefault, true );
+    }
+
+    public ColumnDefinition createColumnDefinition( String columnName, SQLDataType columnDataType,
+                                                    String columnDefault, Boolean mayBeNull )
+    {
+        return this.createColumnDefinition( columnName, columnDataType, columnDefault, mayBeNull, null );
+    }
+
+    public ColumnDefinition createColumnDefinition( String columnName, SQLDataType columnDataType, Boolean mayBeNull,
+                                                    AutoGenerationPolicy autoGenerationPolicy )
+    {
+        return this.createColumnDefinition( columnName, columnDataType, null, mayBeNull, autoGenerationPolicy );
+    }
+
+    public TableConstraintDefinition createTableConstraintDefinition( String name, TableConstraint constraint )
+    {
+        return this.createTableConstraintDefinition( name, constraint, null );
+    }
+
+    public TableConstraintDefinition createTableConstraintDefinition( TableConstraint constraint )
+    {
+        return this.createTableConstraintDefinition( null, constraint, null );
+    }
+
+    public TableConstraintDefinition createTableConstraintDefinition( TableConstraint constraint,
+                                                                      ConstraintCharacteristics characteristics )
+    {
+        return this.createTableConstraintDefinition( null, constraint, characteristics );
+    }
+
+    protected abstract ColumnDefinition createColumnDefinition( String columnName, SQLDataType columnDataType,
+                                                                String columnDefault, Boolean mayBeNull, AutoGenerationPolicy autoGenerationPolicy );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractModificationFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractModificationFactory.java
new file mode 100644
index 0000000..cc7dc33
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractModificationFactory.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.polygene.library.sql.generator.implementation.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.factories.ModificationFactory;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSourceByQuery;
+import org.apache.polygene.library.sql.generator.grammar.modification.TargetTable;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLFactoryBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class AbstractModificationFactory extends SQLFactoryBase
+    implements ModificationFactory
+{
+
+    protected AbstractModificationFactory( SQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    public TargetTable createTargetTable( TableNameDirect tableName )
+    {
+        return this.createTargetTable( tableName, false );
+    }
+
+    public ColumnSourceByQuery columnSourceByQuery( QueryExpression query )
+    {
+        return this.columnSourceByQuery( null, query );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractQueryFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractQueryFactory.java
new file mode 100644
index 0000000..af2df2a
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractQueryFactory.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.query.ColumnsBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.QueryBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+import org.apache.polygene.library.sql.generator.grammar.factories.QueryFactory;
+import org.apache.polygene.library.sql.generator.grammar.literals.SQLFunctionLiteral;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBody;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.query.ColumnsBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLFactoryBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class AbstractQueryFactory extends SQLFactoryBase
+    implements QueryFactory
+{
+
+    protected AbstractQueryFactory( SQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    public QueryBuilder queryBuilder()
+    {
+        return this.queryBuilder( QueryExpressionBody.EmptyQueryExpressionBody.INSTANCE );
+    }
+
+    public ColumnsBuilder columnsBuilder()
+    {
+        return new ColumnsBuilderImpl( this.getProcessor(), SetQuantifier.ALL );
+    }
+
+    public QueryExpression callFunction( SQLFunctionLiteral function )
+    {
+        return this.callFunction( null, function );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractTableRefFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractTableRefFactory.java
new file mode 100644
index 0000000..3865fef
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/AbstractTableRefFactory.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.common.TableName;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameFunction;
+import org.apache.polygene.library.sql.generator.grammar.factories.TableReferenceFactory;
+import org.apache.polygene.library.sql.generator.grammar.literals.SQLFunctionLiteral;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.TableAlias;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferenceByExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferenceByName;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLFactoryBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class AbstractTableRefFactory extends SQLFactoryBase
+    implements TableReferenceFactory
+{
+
+    protected AbstractTableRefFactory( SQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    public TableReferenceByName table( TableName tableName )
+    {
+        return this.table( tableName, null );
+    }
+
+    public TableNameDirect tableName( String tableName )
+    {
+        return this.tableName( null, tableName );
+    }
+
+    public TableAlias tableAlias( String tableNameAlias )
+    {
+        return this.tableAliasWithCols( tableNameAlias );
+    }
+
+    public TableReferenceByExpression table( QueryExpression query )
+    {
+        return this.table( query, null );
+    }
+
+    public TableNameFunction tableName( SQLFunctionLiteral function )
+    {
+        return this.tableName( null, function );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultBooleanFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultBooleanFactory.java
new file mode 100644
index 0000000..bd5e159
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultBooleanFactory.java
@@ -0,0 +1,209 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.BetweenPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanTest;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanTest.TestType;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanTest.TruthValue;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Conjunction;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Disjunction;
+import org.apache.polygene.library.sql.generator.grammar.booleans.EqualsPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.ExistsPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.GreaterOrEqualPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.GreaterThanPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.IsNotNullPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.IsNullPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.LessOrEqualPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.LessThanPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.LikePredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Negation;
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotBetweenPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotEqualsPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotInPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotLikePredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotRegexpPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Predicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.RegexpPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.UniquePredicate;
+import org.apache.polygene.library.sql.generator.grammar.builders.booleans.BooleanBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.booleans.InBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.BetweenPredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.BooleanTestImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.ConjunctionImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.DisjunctionImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.EqualsPredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.ExistsPredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.GreaterOrEqualPredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.GreaterThanPredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.IsNotNullPredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.IsNullPredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.LessOrEqualPredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.LessThanPredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.LikePredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.NegationImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.NotBetweenPredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.NotEqualsPredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.NotInPredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.NotLikePredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.NotRegexpPredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.RegexpPredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.UniquePredicateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.booleans.BooleanBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.booleans.InBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DefaultBooleanFactory extends AbstractBooleanFactory
+{
+
+    public DefaultBooleanFactory( SQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    public EqualsPredicate eq( NonBooleanExpression left, NonBooleanExpression right )
+    {
+        return new EqualsPredicateImpl( this.getProcessor(), left, right );
+    }
+
+    public NotEqualsPredicate neq( NonBooleanExpression left, NonBooleanExpression right )
+    {
+        return new NotEqualsPredicateImpl( this.getProcessor(), left, right );
+    }
+
+    public LessThanPredicate lt( NonBooleanExpression left, NonBooleanExpression right )
+    {
+        return new LessThanPredicateImpl( this.getProcessor(), left, right );
+    }
+
+    public LessOrEqualPredicate leq( NonBooleanExpression left, NonBooleanExpression right )
+    {
+        return new LessOrEqualPredicateImpl( this.getProcessor(), left, right );
+    }
+
+    public GreaterThanPredicate gt( NonBooleanExpression left, NonBooleanExpression right )
+    {
+        return new GreaterThanPredicateImpl( this.getProcessor(), left, right );
+    }
+
+    public GreaterOrEqualPredicate geq( NonBooleanExpression left, NonBooleanExpression right )
+    {
+        return new GreaterOrEqualPredicateImpl( this.getProcessor(), left, right );
+    }
+
+    public IsNullPredicate isNull( NonBooleanExpression what )
+    {
+        return new IsNullPredicateImpl( this.getProcessor(), what );
+    }
+
+    public IsNotNullPredicate isNotNull( NonBooleanExpression what )
+    {
+        return new IsNotNullPredicateImpl( this.getProcessor(), what );
+    }
+
+    public Negation not( BooleanExpression what )
+    {
+        return new NegationImpl( this.getProcessor(), what );
+    }
+
+    public Conjunction and( BooleanExpression left, BooleanExpression right )
+    {
+        return new ConjunctionImpl( this.getProcessor(), left, right );
+    }
+
+    public Disjunction or( BooleanExpression left, BooleanExpression right )
+    {
+        return new DisjunctionImpl( this.getProcessor(), left, right );
+    }
+
+    public BetweenPredicate between( NonBooleanExpression left, NonBooleanExpression minimum,
+                                     NonBooleanExpression maximum )
+    {
+        return new BetweenPredicateImpl( this.getProcessor(), left, minimum, maximum );
+    }
+
+    public NotBetweenPredicate notBetween( NonBooleanExpression left, NonBooleanExpression minimum,
+                                           NonBooleanExpression maximum )
+    {
+        return new NotBetweenPredicateImpl( this.getProcessor(), left, minimum, maximum );
+    }
+
+    public InBuilder inBuilder( NonBooleanExpression what )
+    {
+        return new InBuilderImpl( this.getProcessor(), what );
+    }
+
+    public NotInPredicate notIn( NonBooleanExpression what, NonBooleanExpression... values )
+    {
+        return new NotInPredicateImpl( this.getProcessor(), what, values );
+    }
+
+    public LikePredicate like( NonBooleanExpression what, NonBooleanExpression pattern )
+    {
+        return new LikePredicateImpl( this.getProcessor(), what, pattern );
+    }
+
+    public NotLikePredicate notLike( NonBooleanExpression what, NonBooleanExpression pattern )
+    {
+        return new NotLikePredicateImpl( this.getProcessor(), what, pattern );
+    }
+
+    public RegexpPredicate regexp( NonBooleanExpression what, NonBooleanExpression pattern )
+    {
+        return new RegexpPredicateImpl( this.getProcessor(), what, pattern );
+    }
+
+    public NotRegexpPredicate notRegexp( NonBooleanExpression what, NonBooleanExpression pattern )
+    {
+        return new NotRegexpPredicateImpl( this.getProcessor(), what, pattern );
+    }
+
+    public ExistsPredicate exists( QueryExpression query )
+    {
+        return new ExistsPredicateImpl( this.getProcessor(), query );
+    }
+
+    public UniquePredicate unique( QueryExpression query )
+    {
+        return new UniquePredicateImpl( this.getProcessor(), query );
+    }
+
+    public BooleanTest test( BooleanExpression expression, TestType testType, TruthValue truthValue )
+    {
+        return new BooleanTestImpl( this.getProcessor(), expression, testType, truthValue );
+    }
+
+    public BooleanBuilder booleanBuilder( BooleanExpression first )
+    {
+        return new BooleanBuilderImpl( this.getProcessor(), this, this.transformNullToEmpty( first ) );
+    }
+
+    private final BooleanExpression transformNullToEmpty( BooleanExpression expression )
+    {
+        return expression == null ? Predicate.EmptyPredicate.INSTANCE : expression;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultColumnsFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultColumnsFactory.java
new file mode 100644
index 0000000..2e1258b
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultColumnsFactory.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories;
+
+import java.util.Collection;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.ColumnsBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferenceByExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferenceByName;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.query.ColumnsBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.ColumnNameListImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.ColumnReferenceByExpressionImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.ColumnReferenceByNameImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DefaultColumnsFactory extends AbstractColumnsFactory
+{
+
+    public DefaultColumnsFactory( SQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    public ColumnsBuilder columnsBuilder( SetQuantifier setQuantifier )
+    {
+        return new ColumnsBuilderImpl( this.getProcessor(), setQuantifier );
+    }
+
+    public ColumnReferenceByName colName( String tableName, String colName )
+    {
+        return new ColumnReferenceByNameImpl( this.getProcessor(), tableName, colName );
+    }
+
+    public ColumnReferenceByExpression colExp( ValueExpression expression )
+    {
+        return new ColumnReferenceByExpressionImpl( this.getProcessor(), expression );
+    }
+
+    public ColumnNameList colNames( String... names )
+    {
+        return new ColumnNameListImpl( this.getProcessor(), names );
+    }
+
+    public ColumnNameList colNames( Collection<String> names )
+    {
+        return new ColumnNameListImpl( this.getProcessor(), names );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultDataTypeFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultDataTypeFactory.java
new file mode 100644
index 0000000..a934d18
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultDataTypeFactory.java
@@ -0,0 +1,235 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.BigInt;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.Decimal;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.DoublePrecision;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.IntervalDataType;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.Numeric;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.Real;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLBoolean;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLChar;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDate;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLFloat;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLInteger;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLInterval;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLTime;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLTimeStamp;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SmallInt;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.UserDefinedType;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.datatypes.BigIntImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.datatypes.DecimalImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.datatypes.DoublePrecisionImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.datatypes.NumericImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.datatypes.RealImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.datatypes.SQLBooleanImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.datatypes.SQLCharImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.datatypes.SQLDateImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.datatypes.SQLFloatImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.datatypes.SQLIntegerImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.datatypes.SQLIntervalImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.datatypes.SQLTimeImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.datatypes.SQLTimeStampImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.datatypes.SmallIntImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.datatypes.UserDefinedTypeImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DefaultDataTypeFactory extends AbstractDataTypeFactory
+{
+
+    public DefaultDataTypeFactory( SQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    public BigInt bigInt()
+    {
+        return BigIntImpl.INSTANCE;
+    }
+
+    public Decimal decimal( Integer precision, Integer scale )
+    {
+        return precision == null ? DecimalImpl.PLAIN_DECIMAL : new DecimalImpl( precision, scale );
+    }
+
+    public DoublePrecision doublePrecision()
+    {
+        return DoublePrecisionImpl.INSTANCE;
+    }
+
+    public Numeric numeric( Integer precision, Integer scale )
+    {
+        return precision == null ? NumericImpl.PLAIN_NUMERIC : new NumericImpl( precision, scale );
+    }
+
+    public Real real()
+    {
+        return RealImpl.INSTANCE;
+    }
+
+    public SmallInt smallInt()
+    {
+        return SmallIntImpl.INSTANCE;
+    }
+
+    public SQLBoolean sqlBoolean()
+    {
+        return SQLBooleanImpl.INSTANCE;
+    }
+
+    public SQLChar sqlChar( Integer length )
+    {
+        return length == null ? SQLCharImpl.PLAIN_FIXED : new SQLCharImpl( false, length );
+    }
+
+    public SQLChar sqlVarChar( Integer length )
+    {
+        return length == null ? SQLCharImpl.PLAIN_VARYING : new SQLCharImpl( true, length );
+    }
+
+    public SQLDate date()
+    {
+        return SQLDateImpl.INSTANCE;
+    }
+
+    public SQLFloat sqlFloat( Integer precision )
+    {
+        return precision == null ? SQLFloatImpl.PLAIN_FLOAT : new SQLFloatImpl( precision );
+    }
+
+    public SQLInteger integer()
+    {
+        return SQLIntegerImpl.INSTANCE;
+    }
+
+    public SQLInterval yearMonthInterval( IntervalDataType startField, Integer startFieldPrecision,
+                                          IntervalDataType endField )
+    {
+        Objects.requireNonNull( startField, "Start field" );
+
+        SQLInterval result = null;
+        if( ( startField == IntervalDataType.YEAR || startField == IntervalDataType.MONTH )
+            && ( endField == null || endField == IntervalDataType.YEAR || endField == IntervalDataType.MONTH ) )
+        {
+            result = new SQLIntervalImpl( startField, startFieldPrecision, endField, null );
+        }
+        else
+        {
+            throw new IllegalArgumentException( "The interval data types must be either YEAR or MONTH." );
+        }
+
+        return result;
+    }
+
+    public SQLInterval dayTimeInterval( IntervalDataType startField, Integer startFieldPrecision,
+                                        IntervalDataType endField, Integer secondFracs )
+    {
+        Objects.requireNonNull( startField, "Start field" );
+        SQLInterval result = null;
+        if( startField != IntervalDataType.YEAR
+            && startField != IntervalDataType.MONTH
+            && ( endField == null || ( endField != IntervalDataType.YEAR && endField != IntervalDataType.MONTH && startField != IntervalDataType.SECOND ) ) )
+        {
+            if( secondFracs != null
+                && ( startField != IntervalDataType.SECOND || ( endField != null && endField != IntervalDataType.SECOND ) ) )
+            {
+                // Trying to set second fractionals, even when not needed
+                secondFracs = null;
+            }
+
+            if( endField == null && secondFracs != null && startFieldPrecision == null )
+            {
+                throw new IllegalArgumentException(
+                    "When specifying second fracs for single day-time intervals, the start field precision must be specified also." );
+            }
+
+            result = new SQLIntervalImpl( startField, startFieldPrecision, endField, secondFracs );
+        }
+        else
+        {
+            throw new IllegalArgumentException(
+                "The interval data types must be either DAY, HOUR, MINUTE, or SECOND. For single day-time intervals, the start field must not be SECOND if end field is non-null." );
+        }
+        return result;
+    }
+
+    public SQLTime time( Integer precision, Boolean withTimeZone )
+    {
+        SQLTime result = null;
+        if( precision == null )
+        {
+            if( withTimeZone == null )
+            {
+                result = SQLTimeImpl.PLAIN_TIME;
+            }
+            else if( withTimeZone )
+            {
+                result = SQLTimeImpl.PLAIN_TIME_WITH_TZ;
+            }
+            else
+            {
+                result = SQLTimeImpl.PLAIN_TIME_WITHOUT_TZ;
+            }
+        }
+        else
+        {
+            result = new SQLTimeImpl( precision, withTimeZone );
+        }
+
+        return result;
+    }
+
+    public SQLTimeStamp timeStamp( Integer precision, Boolean withTimeZone )
+    {
+        SQLTimeStamp result = null;
+        if( precision == null )
+        {
+            if( withTimeZone == null )
+            {
+                result = SQLTimeStampImpl.PLAIN_TIMESTAMP;
+            }
+            else if( withTimeZone )
+            {
+                result = SQLTimeStampImpl.PLAIN_TIMESTAMP_WITH_TZ;
+            }
+            else
+            {
+                result = SQLTimeStampImpl.PLAIN_TIMESTAMP_WITHOUT_TZ;
+            }
+        }
+        else
+        {
+            result = new SQLTimeStampImpl( precision, withTimeZone );
+        }
+
+        return result;
+    }
+
+    public UserDefinedType userDefined( String textualContent )
+    {
+        return new UserDefinedTypeImpl( textualContent );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultDefinitionFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultDefinitionFactory.java
new file mode 100644
index 0000000..9c5805b
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultDefinitionFactory.java
@@ -0,0 +1,122 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.ForeignKeyConstraintBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.SchemaDefinitionBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.TableDefinitionBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.TableElementListBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.UniqueConstraintBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.ViewDefinitionBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDataType;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.AutoGenerationPolicy;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.CheckConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ConstraintCharacteristics;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.LikeClause;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.RegularViewSpecification;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.definition.ForeignKeyConstraintBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.definition.SchemaDefinitionBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.definition.TableDefinitionBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.definition.TableElementListBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.definition.UniqueConstraintBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.definition.ViewDefinitionBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.definition.table.CheckConstraintImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.definition.table.ColumnDefinitionImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.definition.table.LikeClauseImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.definition.table.TableConstraintDefinitionImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.definition.view.RegularViewSpecificationImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DefaultDefinitionFactory extends AbstractDefinitionFactory
+{
+    public DefaultDefinitionFactory( SQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    public SchemaDefinitionBuilder createSchemaDefinitionBuilder()
+    {
+        return new SchemaDefinitionBuilderImpl( this.getProcessor() );
+    }
+
+    public TableDefinitionBuilder createTableDefinitionBuilder()
+    {
+        return new TableDefinitionBuilderImpl( this.getProcessor() );
+    }
+
+    public TableElementListBuilder createTableElementListBuilder()
+    {
+        return new TableElementListBuilderImpl( this.getProcessor() );
+    }
+
+    @Override
+    protected ColumnDefinition createColumnDefinition( String columnName, SQLDataType columnDataType,
+                                                       String columnDefault, Boolean mayBeNull, AutoGenerationPolicy autoGenerationPolicy )
+    {
+        return new ColumnDefinitionImpl( this.getProcessor(), columnName, columnDataType, columnDefault, mayBeNull,
+                                         autoGenerationPolicy );
+    }
+
+    public LikeClause createLikeClause( TableNameDirect tableName )
+    {
+        return new LikeClauseImpl( this.getProcessor(), tableName );
+    }
+
+    public TableConstraintDefinition createTableConstraintDefinition( String name, TableConstraint constraint,
+                                                                      ConstraintCharacteristics characteristics )
+    {
+        return new TableConstraintDefinitionImpl( this.getProcessor(), name, constraint, characteristics );
+    }
+
+    public CheckConstraint createCheckConstraint( BooleanExpression check )
+    {
+        return new CheckConstraintImpl( this.getProcessor(), check );
+    }
+
+    public UniqueConstraintBuilder createUniqueConstraintBuilder()
+    {
+        return new UniqueConstraintBuilderImpl( this.getProcessor(), this.getVendor().getColumnsFactory() );
+    }
+
+    public ForeignKeyConstraintBuilder createForeignKeyConstraintBuilder()
+    {
+        return new ForeignKeyConstraintBuilderImpl( this.getProcessor(), this.getVendor().getColumnsFactory() );
+    }
+
+    public ViewDefinitionBuilder createViewDefinitionBuilder()
+    {
+        return new ViewDefinitionBuilderImpl( this.getProcessor() );
+    }
+
+    public RegularViewSpecification createRegularViewSpecification( String... columnNames )
+    {
+        return new RegularViewSpecificationImpl( this.getProcessor(), this.getVendor().getColumnsFactory()
+                                                                          .colNames( columnNames ) );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultLiteralFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultLiteralFactory.java
new file mode 100644
index 0000000..eb096e4
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultLiteralFactory.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories;
+
+import java.sql.Timestamp;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.factories.LiteralFactory;
+import org.apache.polygene.library.sql.generator.grammar.literals.DirectLiteral;
+import org.apache.polygene.library.sql.generator.grammar.literals.NumericLiteral;
+import org.apache.polygene.library.sql.generator.grammar.literals.SQLFunctionLiteral;
+import org.apache.polygene.library.sql.generator.grammar.literals.StringLiteral;
+import org.apache.polygene.library.sql.generator.grammar.literals.TimestampTimeLiteral;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLFactoryBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.literals.DirectLiteralImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.literals.NumericLiteralImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.literals.SQLFunctionLiteralImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.literals.StringLiteralImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.literals.TimestampLiteralImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DefaultLiteralFactory extends SQLFactoryBase
+    implements LiteralFactory
+{
+
+    private final DirectLiteral _param;
+
+    public DefaultLiteralFactory( SQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+
+        this._param = new DirectLiteralImpl( this.getProcessor(), SQLConstants.QUESTION_MARK );
+    }
+
+    public DirectLiteral l( String literalContents )
+    {
+        return new DirectLiteralImpl( this.getProcessor(), literalContents );
+    }
+
+    public DirectLiteral param()
+    {
+        return _param;
+    }
+
+    public StringLiteral s( String literal )
+    {
+        return new StringLiteralImpl( this.getProcessor(), literal );
+    }
+
+    public TimestampTimeLiteral dt( Timestamp date )
+    {
+        return new TimestampLiteralImpl( this.getProcessor(), date );
+    }
+
+    public NumericLiteral n( Number number )
+    {
+        return new NumericLiteralImpl( this.getProcessor(), number );
+    }
+
+    public SQLFunctionLiteral func( String name, ValueExpression... parameters )
+    {
+        return new SQLFunctionLiteralImpl( this.getProcessor(), name, parameters );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultManipulationFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultManipulationFactory.java
new file mode 100644
index 0000000..66596e6
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultManipulationFactory.java
@@ -0,0 +1,122 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.factories.ManipulationFactory;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AddColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AddTableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterColumnAction;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterTableAction;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterTableStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropBehaviour;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropSchemaStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropTableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropTableOrViewStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.ObjectType;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.SetColumnDefault;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLFactoryBase;
+import org.apache.polygene.library.sql.generator.implementation.grammar.manipulation.AddColumnDefinitionImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.manipulation.AddTableConstraintDefinitionImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.manipulation.AlterColumnDefinitionImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.manipulation.AlterTableStatementImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.manipulation.DropColumnDefinitionImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.manipulation.DropSchemaStatementImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.manipulation.DropTableConstraintDefinitionImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.manipulation.DropTableOrViewStatementImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.manipulation.SetColumnDefaultImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DefaultManipulationFactory extends SQLFactoryBase
+    implements ManipulationFactory
+{
+
+    public DefaultManipulationFactory( SQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    public AlterTableStatement createAlterTableStatement( TableNameDirect tableName, AlterTableAction action )
+    {
+        return new AlterTableStatementImpl( this.getProcessor(), tableName, action );
+    }
+
+    public AddColumnDefinition createAddColumnDefinition( ColumnDefinition definition )
+    {
+        return new AddColumnDefinitionImpl( this.getProcessor(), definition );
+    }
+
+    public AddTableConstraintDefinition createAddTableConstraintDefinition(
+        TableConstraintDefinition constraintDefinition )
+    {
+        return new AddTableConstraintDefinitionImpl( this.getProcessor(), constraintDefinition );
+    }
+
+    public AlterColumnDefinition createAlterColumnDefinition( String columnName, AlterColumnAction action )
+    {
+        return new AlterColumnDefinitionImpl( this.getProcessor(), columnName, action );
+    }
+
+    public SetColumnDefault createSetColumnDefault( String newDefault )
+    {
+        return new SetColumnDefaultImpl( this.getProcessor(), newDefault );
+    }
+
+    public DropColumnDefinition createDropColumnDefinition( String columnName, DropBehaviour dropBehaviour )
+    {
+        return new DropColumnDefinitionImpl( this.getProcessor(), columnName, dropBehaviour );
+    }
+
+    public DropTableConstraintDefinition createDropTableConstraintDefinition( String constraintName,
+                                                                              DropBehaviour dropBehaviour )
+    {
+        return new DropTableConstraintDefinitionImpl( this.getProcessor(), constraintName, dropBehaviour );
+    }
+
+    public DropSchemaStatement createDropSchemaStatement( String schemaName, DropBehaviour dropBehaviour )
+    {
+        return new DropSchemaStatementImpl( this.getProcessor(), dropBehaviour, schemaName );
+    }
+
+    public DropTableOrViewStatement createDropTableOrViewStatement( TableNameDirect tableName, ObjectType theType,
+                                                                    DropBehaviour dropBehaviour )
+    {
+        DropTableOrViewStatement result = null;
+        if( theType == ObjectType.TABLE || theType == ObjectType.VIEW )
+        {
+            result = new DropTableOrViewStatementImpl( this.getProcessor(), theType, dropBehaviour, tableName );
+        }
+        else
+        {
+            throw new IllegalArgumentException( "Object type " + theType
+                                                + " is not a valid type for DROP TABLE or DROP VIEW statement." );
+        }
+
+        return result;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultModificationFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultModificationFactory.java
new file mode 100644
index 0000000..e519918
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultModificationFactory.java
@@ -0,0 +1,98 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.ColumnSourceByValuesBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.DeleteBySearchBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.InsertStatementBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.UpdateBySearchBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSourceByQuery;
+import org.apache.polygene.library.sql.generator.grammar.modification.SetClause;
+import org.apache.polygene.library.sql.generator.grammar.modification.TargetTable;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateSource;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateSourceByExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.modification.ColumnSourceByValuesBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.modification.DeleteBySearchBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.modification.InsertStatementBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.modification.UpdateBySearchBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.modification.ColumnSourceByQueryImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.modification.SetClauseImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.modification.TargetTableImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.modification.UpdateSourceByExpressionImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DefaultModificationFactory extends AbstractModificationFactory
+{
+
+    public DefaultModificationFactory( SQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    public ColumnSourceByValuesBuilder columnSourceByValues()
+    {
+        return new ColumnSourceByValuesBuilderImpl( this.getProcessor() );
+    }
+
+    public ColumnSourceByQuery columnSourceByQuery( ColumnNameList columnNames, QueryExpression query )
+    {
+        return new ColumnSourceByQueryImpl( this.getProcessor(), columnNames, query );
+    }
+
+    public DeleteBySearchBuilder deleteBySearch()
+    {
+        return new DeleteBySearchBuilderImpl( this.getProcessor(), this.getVendor().getBooleanFactory()
+                                                                       .booleanBuilder() );
+    }
+
+    public InsertStatementBuilder insert()
+    {
+        return new InsertStatementBuilderImpl( this.getProcessor() );
+    }
+
+    public UpdateBySearchBuilder updateBySearch()
+    {
+        return new UpdateBySearchBuilderImpl( this.getProcessor(), this.getVendor().getBooleanFactory()
+                                                                       .booleanBuilder() );
+    }
+
+    public TargetTable createTargetTable( TableNameDirect tableName, Boolean isOnly )
+    {
+        return new TargetTableImpl( this.getProcessor(), isOnly, tableName );
+    }
+
+    public UpdateSourceByExpression updateSourceByExp( ValueExpression expression )
+    {
+        return new UpdateSourceByExpressionImpl( this.getProcessor(), expression );
+    }
+
+    public SetClause setClause( String updateTarget, UpdateSource updateSource )
+    {
+        return new SetClauseImpl( this.getProcessor(), updateTarget, updateSource );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultQueryFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultQueryFactory.java
new file mode 100644
index 0000000..fe5f64e
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultQueryFactory.java
@@ -0,0 +1,156 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories;
+
+import java.util.Arrays;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.ColumnsBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.FromBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.GroupByBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.OrderByBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.QueryBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.QuerySpecificationBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.SimpleQueryBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.literals.SQLFunctionLiteral;
+import org.apache.polygene.library.sql.generator.grammar.query.LimitSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.OffsetSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.Ordering;
+import org.apache.polygene.library.sql.generator.grammar.query.OrdinaryGroupingSet;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBody;
+import org.apache.polygene.library.sql.generator.grammar.query.RowDefinition;
+import org.apache.polygene.library.sql.generator.grammar.query.RowSubQuery;
+import org.apache.polygene.library.sql.generator.grammar.query.RowValueConstructor;
+import org.apache.polygene.library.sql.generator.grammar.query.SortSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.TableValueConstructor;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.query.ColumnsBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.query.FromBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.query.GroupByBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.query.OrderByBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.query.QueryBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.query.QuerySpecificationBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.query.SimpleQueryBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.LimitSpecificationImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.OffsetSpecificationImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.OrdinaryGroupingSetImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.QueryExpressionImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.RowDefinitionImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.RowSubQueryImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.SortSpecificationImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.TableValueConstructorImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DefaultQueryFactory extends AbstractQueryFactory
+{
+
+    public DefaultQueryFactory( SQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    public QueryExpression createQuery( QueryExpressionBody body )
+    {
+        return new QueryExpressionImpl( this.getProcessor(), body );
+    }
+
+    public QuerySpecificationBuilder querySpecificationBuilder()
+    {
+        return new QuerySpecificationBuilderImpl( this.getProcessor(), this, this.columnsBuilder(), this.fromBuilder(),
+                                                  this.getVendor().getBooleanFactory().booleanBuilder(), this.groupByBuilder(), this.getVendor()
+                                                                                                                                    .getBooleanFactory().booleanBuilder(), this.orderByBuilder() );
+    }
+
+    public ColumnsBuilder columnsBuilder( SetQuantifier setQuantifier )
+    {
+        return new ColumnsBuilderImpl( this.getProcessor(), setQuantifier );
+    }
+
+    public QueryBuilder queryBuilder( QueryExpressionBody query )
+    {
+        return new QueryBuilderImpl( this.getProcessor(), query );
+    }
+
+    public GroupByBuilder groupByBuilder()
+    {
+        return new GroupByBuilderImpl( this.getProcessor() );
+    }
+
+    public OrdinaryGroupingSet groupingElement( NonBooleanExpression... expressions )
+    {
+        return new OrdinaryGroupingSetImpl( this.getProcessor(), expressions );
+    }
+
+    public FromBuilder fromBuilder()
+    {
+        return new FromBuilderImpl( this.getProcessor() );
+    }
+
+    public OrderByBuilder orderByBuilder()
+    {
+        return new OrderByBuilderImpl( this.getProcessor() );
+    }
+
+    public SortSpecification sortSpec( ValueExpression expression, Ordering ordering )
+    {
+        return new SortSpecificationImpl( this.getProcessor(), expression, ordering );
+    }
+
+    public SimpleQueryBuilder simpleQueryBuilder()
+    {
+        return new SimpleQueryBuilderImpl( this.getProcessor(), this.getVendor() );
+    }
+
+    public TableValueConstructor values( RowValueConstructor... rows )
+    {
+        return new TableValueConstructorImpl( this.getProcessor(), Arrays.asList( rows ) );
+    }
+
+    public RowSubQuery rowSubQuery( QueryExpression subQuery )
+    {
+        return new RowSubQueryImpl( this.getProcessor(), subQuery );
+    }
+
+    public RowDefinition row( ValueExpression... elements )
+    {
+        return new RowDefinitionImpl( this.getProcessor(), Arrays.asList( elements ) );
+    }
+
+    public QueryExpression callFunction( String schemaName, SQLFunctionLiteral function )
+    {
+        return this.simpleQueryBuilder().selectAllColumns()
+                   .from( this.getVendor().getTableReferenceFactory().tableName( schemaName, function ) ).createExpression();
+    }
+
+    public LimitSpecification limit( NonBooleanExpression count )
+    {
+        return new LimitSpecificationImpl( this.getProcessor(), count );
+    }
+
+    public OffsetSpecification offset( NonBooleanExpression offset )
+    {
+        return new OffsetSpecificationImpl( this.getProcessor(), offset );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultTableRefFactory.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultTableRefFactory.java
new file mode 100644
index 0000000..612c9f4
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/DefaultTableRefFactory.java
@@ -0,0 +1,103 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.TableReferenceBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.common.TableName;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameFunction;
+import org.apache.polygene.library.sql.generator.grammar.literals.SQLFunctionLiteral;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.TableAlias;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferenceByExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferenceByName;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferencePrimary;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinCondition;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.NamedColumnsJoin;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.query.TableReferenceBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.TableNameDirectImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.TableNameFunctionImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.TableAliasImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.TableReferenceByExpressionImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.TableReferenceByNameImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.joins.JoinConditionImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.joins.NamedColumnsJoinImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DefaultTableRefFactory extends AbstractTableRefFactory
+{
+
+    public DefaultTableRefFactory( SQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    public JoinCondition jc( BooleanExpression condition )
+    {
+        return new JoinConditionImpl( this.getProcessor(), condition );
+    }
+
+    public NamedColumnsJoin nc( ColumnNameList columnNames )
+    {
+        return new NamedColumnsJoinImpl( this.getProcessor(), columnNames );
+    }
+
+    public TableReferenceByName table( TableName tableName, TableAlias alias )
+    {
+        return new TableReferenceByNameImpl( this.getProcessor(), tableName, alias );
+    }
+
+    public TableNameDirect tableName( String schemaName, String tableName )
+    {
+        return new TableNameDirectImpl( this.getProcessor(), schemaName, tableName );
+    }
+
+    public TableNameFunction tableName( String schemaName, SQLFunctionLiteral function )
+    {
+        return new TableNameFunctionImpl( this.getProcessor(), schemaName, function );
+    }
+
+    public TableAlias tableAliasWithCols( String tableNameAlias, String... colNames )
+    {
+        ColumnNameList colNameList = null;
+        if( colNames.length > 0 )
+        {
+            colNameList = this.getVendor().getColumnsFactory().colNames( colNames );
+        }
+
+        return new TableAliasImpl( this.getProcessor(), tableNameAlias, colNameList );
+    }
+
+    public TableReferenceByExpression table( QueryExpression query, TableAlias alias )
+    {
+        return new TableReferenceByExpressionImpl( this.getProcessor(), query, alias );
+    }
+
+    public TableReferenceBuilder tableBuilder( TableReferencePrimary firstTable )
+    {
+        return new TableReferenceBuilderImpl( this.getProcessor(), firstTable );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/pgsql/PgSQLDataTypeFactoryImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/pgsql/PgSQLDataTypeFactoryImpl.java
new file mode 100644
index 0000000..2cbc4ae
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/pgsql/PgSQLDataTypeFactoryImpl.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.pgsql.Text;
+import org.apache.polygene.library.sql.generator.grammar.factories.pgsql.PgSQLDataTypeFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.datatypes.pgsql.TextImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.factories.DefaultDataTypeFactory;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.PostgreSQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class PgSQLDataTypeFactoryImpl extends DefaultDataTypeFactory
+    implements PgSQLDataTypeFactory
+{
+
+    public PgSQLDataTypeFactoryImpl( PostgreSQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    public Text text()
+    {
+        return TextImpl.INSTANCE;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/pgsql/PgSQLManipulationFactoryImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/pgsql/PgSQLManipulationFactoryImpl.java
new file mode 100644
index 0000000..52c43ce
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/pgsql/PgSQLManipulationFactoryImpl.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.factories.pgsql.PgSQLManipulationFactory;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropBehaviour;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.ObjectType;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.pgsql.PgSQLDropTableOrViewStatement;
+import org.apache.polygene.library.sql.generator.implementation.grammar.factories.DefaultManipulationFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.manipulation.pgsql.PgSQLDropTableOrViewStatementImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.PostgreSQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class PgSQLManipulationFactoryImpl extends DefaultManipulationFactory
+    implements PgSQLManipulationFactory
+{
+    public PgSQLManipulationFactoryImpl( PostgreSQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    @Override
+    public PgSQLDropTableOrViewStatement createDropTableOrViewStatement( TableNameDirect tableName, ObjectType theType,
+                                                                         DropBehaviour dropBehaviour )
+    {
+        return this.createDropTableOrViewStatement( tableName, theType, dropBehaviour, false );
+    }
+
+    public PgSQLDropTableOrViewStatement createDropTableOrViewStatement( TableNameDirect tableName, ObjectType theType,
+                                                                         DropBehaviour dropBehaviour, Boolean useIfExists )
+    {
+        return new PgSQLDropTableOrViewStatementImpl( this.getProcessor(), theType, dropBehaviour, tableName,
+                                                      useIfExists );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/pgsql/PgSQLModificationFactoryImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/pgsql/PgSQLModificationFactoryImpl.java
new file mode 100644
index 0000000..18905ec
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/factories/pgsql/PgSQLModificationFactoryImpl.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.factories.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.InsertStatementBuilder;
+import org.apache.polygene.library.sql.generator.implementation.grammar.builders.modification.pgsql.PgSQLInsertStatementBuilderImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.factories.DefaultModificationFactory;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.PostgreSQLVendor;
+
+public class PgSQLModificationFactoryImpl extends DefaultModificationFactory
+{
+
+    public PgSQLModificationFactoryImpl( PostgreSQLVendor vendor, SQLProcessorAggregator processor )
+    {
+        super( vendor, processor );
+    }
+
+    @Override
+    public InsertStatementBuilder insert()
+    {
+        return new PgSQLInsertStatementBuilderImpl( this.getProcessor() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/literals/DirectLiteralImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/literals/DirectLiteralImpl.java
new file mode 100644
index 0000000..f2fc875
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/literals/DirectLiteralImpl.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.literals;
+
+import org.apache.polygene.library.sql.generator.grammar.literals.DirectLiteral;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.NonBooleanExpressionImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DirectLiteralImpl extends NonBooleanExpressionImpl<DirectLiteral>
+    implements DirectLiteral
+{
+
+    private final String _literal;
+
+    public DirectLiteralImpl( SQLProcessorAggregator processor, String literal )
+    {
+        this( processor, DirectLiteral.class, literal );
+    }
+
+    protected DirectLiteralImpl( SQLProcessorAggregator processor, Class<? extends DirectLiteral> implClass,
+                                 String literal )
+    {
+        super( processor, implClass );
+
+        this._literal = literal;
+    }
+
+    public String getDirectLiteral()
+    {
+        return this._literal;
+    }
+
+    @Override
+    protected boolean doesEqual( DirectLiteral another )
+    {
+        return TypeableImpl.bothNullOrEquals( this._literal, another.getDirectLiteral() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/literals/NumericLiteralImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/literals/NumericLiteralImpl.java
new file mode 100644
index 0000000..bc714c2
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/literals/NumericLiteralImpl.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.literals;
+
+import org.apache.polygene.library.sql.generator.grammar.literals.NumericLiteral;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.NonBooleanExpressionImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class NumericLiteralImpl extends NonBooleanExpressionImpl<NumericLiteral>
+    implements NumericLiteral
+{
+
+    private final Number _number;
+
+    public NumericLiteralImpl( SQLProcessorAggregator processor, Number number )
+    {
+        this( processor, NumericLiteral.class, number );
+    }
+
+    protected NumericLiteralImpl( SQLProcessorAggregator processor, Class<? extends NumericLiteral> implClass,
+                                  Number number )
+    {
+        super( processor, implClass );
+
+        this._number = number;
+    }
+
+    public Number getNumber()
+    {
+        return this._number;
+    }
+
+    @Override
+    protected boolean doesEqual( NumericLiteral another )
+    {
+        return TypeableImpl.bothNullOrEquals( this._number, another.getNumber() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/literals/SQLFunctionLiteralImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/literals/SQLFunctionLiteralImpl.java
new file mode 100644
index 0000000..e397e2f
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/literals/SQLFunctionLiteralImpl.java
@@ -0,0 +1,83 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.literals;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.literals.SQLFunctionLiteral;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.NonBooleanExpressionImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class SQLFunctionLiteralImpl extends NonBooleanExpressionImpl<SQLFunctionLiteral>
+    implements SQLFunctionLiteral
+{
+
+    private final String _name;
+
+    private final List<ValueExpression> _parameters;
+
+    public SQLFunctionLiteralImpl( SQLProcessorAggregator processor, String name, ValueExpression... parameters )
+    {
+        this( processor, name, Arrays.asList( parameters ) );
+    }
+
+    public SQLFunctionLiteralImpl( SQLProcessorAggregator processor, String name, List<ValueExpression> parameters )
+    {
+        this( processor, SQLFunctionLiteral.class, name, parameters );
+    }
+
+    protected SQLFunctionLiteralImpl( SQLProcessorAggregator processor, Class<? extends SQLFunctionLiteral> implClass,
+                                      String name, List<ValueExpression> parameters )
+    {
+        super( processor, implClass );
+        Objects.requireNonNull( name, "name" );
+        Objects.requireNonNull( parameters, "parameters" );
+        for( ValueExpression exp : parameters )
+        {
+            Objects.requireNonNull( exp, "parameter" );
+        }
+
+        this._name = name;
+        this._parameters = Collections.unmodifiableList( new ArrayList<ValueExpression>( parameters ) );
+    }
+
+    public String getFunctionName()
+    {
+        return this._name;
+    }
+
+    public List<ValueExpression> getParameters()
+    {
+        return this._parameters;
+    }
+
+    @Override
+    protected boolean doesEqual( SQLFunctionLiteral another )
+    {
+        return this._name.equals( another.getFunctionName() ) && this._parameters.equals( another.getParameters() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/literals/StringLiteralImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/literals/StringLiteralImpl.java
new file mode 100644
index 0000000..fa3b075
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/literals/StringLiteralImpl.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.literals;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.literals.StringLiteral;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.NonBooleanExpressionImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class StringLiteralImpl extends NonBooleanExpressionImpl<StringLiteral>
+    implements StringLiteral
+{
+
+    private final String _literal;
+
+    public StringLiteralImpl( SQLProcessorAggregator processor, String literal )
+    {
+        this( processor, StringLiteral.class, literal );
+    }
+
+    protected StringLiteralImpl( SQLProcessorAggregator processor, Class<? extends StringLiteral> implClass,
+                                 String literal )
+    {
+        super( processor, implClass );
+        Objects.requireNonNull( literal, "literal" );
+
+        this._literal = literal;
+    }
+
+    public String getString()
+    {
+        return this._literal;
+    }
+
+    @Override
+    protected boolean doesEqual( StringLiteral another )
+    {
+        return this._literal.equals( another.getString() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/literals/TimestampLiteralImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/literals/TimestampLiteralImpl.java
new file mode 100644
index 0000000..8245bd1
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/literals/TimestampLiteralImpl.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.literals;
+
+import java.sql.Timestamp;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.literals.TimestampTimeLiteral;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.NonBooleanExpressionImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TimestampLiteralImpl extends NonBooleanExpressionImpl<TimestampTimeLiteral>
+    implements TimestampTimeLiteral
+{
+
+    private final Timestamp _date;
+
+    public TimestampLiteralImpl( SQLProcessorAggregator processor, Timestamp date )
+    {
+        this( processor, TimestampTimeLiteral.class, date );
+    }
+
+    protected TimestampLiteralImpl( SQLProcessorAggregator processor, Class<? extends TimestampTimeLiteral> implClass,
+                                    Timestamp date )
+    {
+        super( processor, implClass );
+
+        Objects.requireNonNull( date, "Timestamp" );
+        this._date = date;
+    }
+
+    public Timestamp getTimestamp()
+    {
+        return this._date;
+    }
+
+    @Override
+    protected boolean doesEqual( TimestampTimeLiteral another )
+    {
+        return this._date.equals( another.getTimestamp() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/AddColumnDefinitionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/AddColumnDefinitionImpl.java
new file mode 100644
index 0000000..4400ebc
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/AddColumnDefinitionImpl.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.manipulation;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AddColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterTableAction;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class AddColumnDefinitionImpl extends SQLSyntaxElementBase<AlterTableAction, AddColumnDefinition>
+    implements AddColumnDefinition
+{
+
+    private final ColumnDefinition _columnDefinition;
+
+    public AddColumnDefinitionImpl( SQLProcessorAggregator processor, ColumnDefinition columnDefinition )
+    {
+        this( processor, AddColumnDefinition.class, columnDefinition );
+    }
+
+    protected AddColumnDefinitionImpl( SQLProcessorAggregator processor,
+                                       Class<? extends AddColumnDefinition> realImplementingType, ColumnDefinition columnDefinition )
+    {
+        super( processor, realImplementingType );
+
+        Objects.requireNonNull( columnDefinition, "Column definition" );
+
+        this._columnDefinition = columnDefinition;
+    }
+
+    @Override
+    protected boolean doesEqual( AddColumnDefinition another )
+    {
+        return this._columnDefinition.equals( another.getColumnDefinition() );
+    }
+
+    public ColumnDefinition getColumnDefinition()
+    {
+        return this._columnDefinition;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/AddTableConstraintDefinitionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/AddTableConstraintDefinitionImpl.java
new file mode 100644
index 0000000..d23ddf3
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/AddTableConstraintDefinitionImpl.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.manipulation;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AddTableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterTableAction;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class AddTableConstraintDefinitionImpl extends
+                                              SQLSyntaxElementBase<AlterTableAction, AddTableConstraintDefinition>
+    implements AddTableConstraintDefinition
+{
+
+    private final TableConstraintDefinition _constraint;
+
+    public AddTableConstraintDefinitionImpl( SQLProcessorAggregator processor, TableConstraintDefinition constraint )
+    {
+        this( processor, AddTableConstraintDefinition.class, constraint );
+    }
+
+    protected AddTableConstraintDefinitionImpl( SQLProcessorAggregator processor,
+                                                Class<? extends AddTableConstraintDefinition> realImplementingType, TableConstraintDefinition constraint )
+    {
+        super( processor, realImplementingType );
+        Objects.requireNonNull( constraint, "Constraint" );
+        this._constraint = constraint;
+    }
+
+    @Override
+    protected boolean doesEqual( AddTableConstraintDefinition another )
+    {
+        return this._constraint.equals( another.getConstraint() );
+    }
+
+    public TableConstraintDefinition getConstraint()
+    {
+        return this._constraint;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/AlterColumnDefinitionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/AlterColumnDefinitionImpl.java
new file mode 100644
index 0000000..5689e9c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/AlterColumnDefinitionImpl.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.manipulation;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterColumnAction;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterTableAction;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class AlterColumnDefinitionImpl extends SQLSyntaxElementBase<AlterTableAction, AlterColumnDefinition>
+    implements AlterColumnDefinition
+{
+
+    private final String _columnName;
+    private final AlterColumnAction _action;
+
+    public AlterColumnDefinitionImpl( SQLProcessorAggregator processor, String columnName, AlterColumnAction action )
+    {
+        this( processor, AlterColumnDefinition.class, columnName, action );
+    }
+
+    protected AlterColumnDefinitionImpl( SQLProcessorAggregator processor,
+                                         Class<? extends AlterColumnDefinition> realImplementingType, String columnName, AlterColumnAction action )
+    {
+        super( processor, realImplementingType );
+        Objects.requireNonNull( columnName, "Column name" );
+        Objects.requireNonNull( action, "Alter column action" );
+        this._columnName = columnName;
+        this._action = action;
+    }
+
+    @Override
+    protected boolean doesEqual( AlterColumnDefinition another )
+    {
+        return this._columnName.equals( another.getColumnName() ) && this._action.equals( another.getAction() );
+    }
+
+    public AlterColumnAction getAction()
+    {
+        return this._action;
+    }
+
+    public String getColumnName()
+    {
+        return this._columnName;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/AlterTableStatementImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/AlterTableStatementImpl.java
new file mode 100644
index 0000000..284ac6d
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/AlterTableStatementImpl.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.manipulation;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.SchemaStatement;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterTableAction;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterTableStatement;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class AlterTableStatementImpl extends SQLSyntaxElementBase<SchemaStatement, AlterTableStatement>
+    implements AlterTableStatement
+{
+
+    private final TableNameDirect _tableName;
+    private final AlterTableAction _action;
+
+    public AlterTableStatementImpl( SQLProcessorAggregator processor, TableNameDirect tableName, AlterTableAction action )
+    {
+        this( processor, AlterTableStatement.class, tableName, action );
+    }
+
+    protected AlterTableStatementImpl( SQLProcessorAggregator processor,
+                                       Class<? extends AlterTableStatement> realImplementingType, TableNameDirect tableName, AlterTableAction action )
+    {
+        super( processor, realImplementingType );
+        Objects.requireNonNull( tableName, "Table name" );
+        Objects.requireNonNull( action, "Alter table taction" );
+        this._tableName = tableName;
+        this._action = action;
+    }
+
+    @Override
+    protected boolean doesEqual( AlterTableStatement another )
+    {
+        return this._tableName.equals( another.getTableName() ) && this._action.equals( another.getAction() );
+    }
+
+    public AlterTableAction getAction()
+    {
+        return this._action;
+    }
+
+    public TableNameDirect getTableName()
+    {
+        return this._tableName;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/DropColumnDefinitionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/DropColumnDefinitionImpl.java
new file mode 100644
index 0000000..3db7753
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/DropColumnDefinitionImpl.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.manipulation;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterTableAction;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropBehaviour;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropColumnDefinition;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DropColumnDefinitionImpl extends SQLSyntaxElementBase<AlterTableAction, DropColumnDefinition>
+    implements DropColumnDefinition
+{
+
+    private final String _columnName;
+    private final DropBehaviour _dropBehaviour;
+
+    public DropColumnDefinitionImpl( SQLProcessorAggregator processor, String columnName, DropBehaviour dropBehaviour )
+    {
+        this( processor, DropColumnDefinition.class, columnName, dropBehaviour );
+    }
+
+    protected DropColumnDefinitionImpl( SQLProcessorAggregator processor,
+                                        Class<? extends DropColumnDefinition> realImplementingType, String columnName, DropBehaviour dropBehaviour )
+    {
+        super( processor, realImplementingType );
+        Objects.requireNonNull( columnName, "Column name" );
+        Objects.requireNonNull( dropBehaviour, "Drop behaviour" );
+        this._columnName = columnName;
+        this._dropBehaviour = dropBehaviour;
+    }
+
+    @Override
+    protected boolean doesEqual( DropColumnDefinition another )
+    {
+        return this._dropBehaviour.equals( another.getDropBehaviour() )
+               && this._columnName.equals( another.getColumnName() );
+    }
+
+    public String getColumnName()
+    {
+        return this._columnName;
+    }
+
+    public DropBehaviour getDropBehaviour()
+    {
+        return this._dropBehaviour;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/DropSchemaStatementImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/DropSchemaStatementImpl.java
new file mode 100644
index 0000000..3aaef7b
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/DropSchemaStatementImpl.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.manipulation;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropBehaviour;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropSchemaStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.ObjectType;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DropSchemaStatementImpl extends DropStatementImpl<DropSchemaStatement>
+    implements DropSchemaStatement
+{
+
+    private final String _schemaName;
+
+    public DropSchemaStatementImpl( SQLProcessorAggregator processor, DropBehaviour dropBehaviour, String schemaName )
+    {
+        this( processor, DropSchemaStatement.class, ObjectType.SCHEMA, dropBehaviour, schemaName );
+    }
+
+    protected DropSchemaStatementImpl( SQLProcessorAggregator processor,
+                                       Class<? extends DropSchemaStatement> realImplementingType, ObjectType whatToDrop, DropBehaviour dropBehaviour,
+                                       String schemaName )
+    {
+        super( processor, realImplementingType, whatToDrop, dropBehaviour );
+        Objects.requireNonNull( schemaName, "Schema name" );
+        this._schemaName = schemaName;
+    }
+
+    @Override
+    protected boolean doesEqual( DropSchemaStatement another )
+    {
+        return this._schemaName.equals( another.getSchemaName() ) && super.doesEqual( another );
+    }
+
+    public String getSchemaName()
+    {
+        return this._schemaName;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/DropStatementImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/DropStatementImpl.java
new file mode 100644
index 0000000..e09f573
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/DropStatementImpl.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.manipulation;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.SchemaStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropBehaviour;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.ObjectType;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DropStatementImpl<DropStatementType extends DropStatement> extends
+                                                                        SQLSyntaxElementBase<SchemaStatement, DropStatementType>
+    implements DropStatement
+{
+
+    private final DropBehaviour _dropBehaviour;
+    private final ObjectType _whatToDrop;
+
+    protected DropStatementImpl( SQLProcessorAggregator processor,
+                                 Class<? extends DropStatementType> realImplementingType, ObjectType whatToDrop, DropBehaviour dropBehaviour )
+    {
+        super( processor, realImplementingType );
+        Objects.requireNonNull( whatToDrop, "What to drop" );
+        Objects.requireNonNull( dropBehaviour, "Drop behaviour" );
+        this._whatToDrop = whatToDrop;
+        this._dropBehaviour = dropBehaviour;
+    }
+
+    protected boolean doesEqual( DropStatementType another )
+    {
+        return this._dropBehaviour.equals( another.getDropBehaviour() )
+               && this._whatToDrop.equals( another.whatToDrop() );
+    }
+
+    public DropBehaviour getDropBehaviour()
+    {
+        return this._dropBehaviour;
+    }
+
+    public ObjectType whatToDrop()
+    {
+        return this._whatToDrop;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/DropTableConstraintDefinitionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/DropTableConstraintDefinitionImpl.java
new file mode 100644
index 0000000..3e85d7c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/DropTableConstraintDefinitionImpl.java
@@ -0,0 +1,73 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.manipulation;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterTableAction;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropBehaviour;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropTableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DropTableConstraintDefinitionImpl extends
+                                               SQLSyntaxElementBase<AlterTableAction, DropTableConstraintDefinition>
+    implements DropTableConstraintDefinition
+{
+
+    private final String _constraintName;
+    private final DropBehaviour _dropBehaviour;
+
+    public DropTableConstraintDefinitionImpl( SQLProcessorAggregator processor, String constraintName,
+                                              DropBehaviour dropBehaviour )
+    {
+        this( processor, DropTableConstraintDefinition.class, constraintName, dropBehaviour );
+    }
+
+    protected DropTableConstraintDefinitionImpl( SQLProcessorAggregator processor,
+                                                 Class<? extends DropTableConstraintDefinition> realImplementingType, String constraintName,
+                                                 DropBehaviour dropBehaviour )
+    {
+        super( processor, realImplementingType );
+        Objects.requireNonNull( constraintName, "Constraint name" );
+        Objects.requireNonNull( dropBehaviour, "Drop behaviour" );
+        this._constraintName = constraintName;
+        this._dropBehaviour = dropBehaviour;
+    }
+
+    @Override
+    protected boolean doesEqual( DropTableConstraintDefinition another )
+    {
+        return this._constraintName.equals( another.getConstraintName() )
+               && this._dropBehaviour.equals( another.getDropBehaviour() );
+    }
+
+    public String getConstraintName()
+    {
+        return this._constraintName;
+    }
+
+    public DropBehaviour getDropBehaviour()
+    {
+        return this._dropBehaviour;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/DropTableOrViewStatementImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/DropTableOrViewStatementImpl.java
new file mode 100644
index 0000000..f0c0df0
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/DropTableOrViewStatementImpl.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.manipulation;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropBehaviour;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropTableOrViewStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.ObjectType;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DropTableOrViewStatementImpl extends DropStatementImpl<DropTableOrViewStatement>
+    implements DropTableOrViewStatement
+{
+
+    private final TableNameDirect _name;
+
+    public DropTableOrViewStatementImpl( SQLProcessorAggregator processor, ObjectType whatToDrop,
+                                         DropBehaviour dropBehaviour, TableNameDirect name )
+    {
+        this( processor, DropTableOrViewStatement.class, whatToDrop, dropBehaviour, name );
+    }
+
+    protected DropTableOrViewStatementImpl( SQLProcessorAggregator processor,
+                                            Class<? extends DropTableOrViewStatement> realImplementingType, ObjectType whatToDrop,
+                                            DropBehaviour dropBehaviour, TableNameDirect name )
+    {
+        super( processor, realImplementingType, whatToDrop, dropBehaviour );
+        Objects.requireNonNull( name, "Table name" );
+        this._name = name;
+    }
+
+    @Override
+    protected boolean doesEqual( DropTableOrViewStatement another )
+    {
+        return this._name.equals( another.getTableName() ) && super.doesEqual( another );
+    }
+
+    public TableNameDirect getTableName()
+    {
+        return this._name;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/SetColumnDefaultImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/SetColumnDefaultImpl.java
new file mode 100644
index 0000000..278f166
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/SetColumnDefaultImpl.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.manipulation;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterColumnAction;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.SetColumnDefault;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class SetColumnDefaultImpl extends SQLSyntaxElementBase<AlterColumnAction, SetColumnDefault>
+    implements SetColumnDefault
+{
+
+    private final String _default;
+
+    public SetColumnDefaultImpl( SQLProcessorAggregator processor, String colDefault )
+    {
+        this( processor, SetColumnDefault.class, colDefault );
+    }
+
+    protected SetColumnDefaultImpl( SQLProcessorAggregator processor,
+                                    Class<? extends SetColumnDefault> realImplementingType, String colDefault )
+    {
+        super( processor, realImplementingType );
+        Objects.requireNonNull( colDefault, "Column default" );
+        this._default = colDefault;
+    }
+
+    @Override
+    protected boolean doesEqual( SetColumnDefault another )
+    {
+        return this._default.equals( another.getDefault() );
+    }
+
+    public String getDefault()
+    {
+        return this._default;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/pgsql/PgSQLDropTableOrViewStatementImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/pgsql/PgSQLDropTableOrViewStatementImpl.java
new file mode 100644
index 0000000..f9e5e77
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/manipulation/pgsql/PgSQLDropTableOrViewStatementImpl.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.manipulation.pgsql;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropBehaviour;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropTableOrViewStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.ObjectType;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.pgsql.PgSQLDropTableOrViewStatement;
+import org.apache.polygene.library.sql.generator.implementation.grammar.manipulation.DropTableOrViewStatementImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class PgSQLDropTableOrViewStatementImpl extends DropTableOrViewStatementImpl
+    implements PgSQLDropTableOrViewStatement
+{
+
+    private final Boolean _useIfExists;
+
+    public PgSQLDropTableOrViewStatementImpl( SQLProcessorAggregator processor, ObjectType whatToDrop,
+                                              DropBehaviour dropBehaviour, TableNameDirect name, Boolean useIfExists )
+    {
+        this( processor, PgSQLDropTableOrViewStatement.class, whatToDrop, dropBehaviour, name, useIfExists );
+    }
+
+    protected PgSQLDropTableOrViewStatementImpl( SQLProcessorAggregator processor,
+                                                 Class<? extends PgSQLDropTableOrViewStatement> realImplementingType, ObjectType whatToDrop,
+                                                 DropBehaviour dropBehaviour, TableNameDirect name, Boolean useIfExists )
+    {
+        super( processor, realImplementingType, whatToDrop, dropBehaviour, name );
+        Objects.requireNonNull( useIfExists, "Use IF EXISTS" );
+        this._useIfExists = useIfExists;
+    }
+
+    @Override
+    protected boolean doesEqual( DropTableOrViewStatement another )
+    {
+        return super.doesEqual( another )
+               && this._useIfExists.equals( ( (PgSQLDropTableOrViewStatement) another ).useIfExists() );
+    }
+
+    public Boolean useIfExists()
+    {
+        return this._useIfExists;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/ColumnSourceByQueryImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/ColumnSourceByQueryImpl.java
new file mode 100644
index 0000000..fdd9479
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/ColumnSourceByQueryImpl.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.modification;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSourceByQuery;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ColumnSourceByQueryImpl extends DynamicColumnSourceImpl<ColumnSourceByQuery>
+    implements ColumnSourceByQuery
+{
+
+    private final QueryExpression _query;
+
+    public ColumnSourceByQueryImpl( SQLProcessorAggregator processor, ColumnNameList columnNames, QueryExpression query )
+    {
+        this( processor, ColumnSourceByQuery.class, columnNames, query );
+    }
+
+    protected ColumnSourceByQueryImpl( SQLProcessorAggregator processor,
+                                       Class<? extends ColumnSourceByQuery> expressionClass, ColumnNameList columnNames, QueryExpression query )
+    {
+        super( processor, expressionClass, columnNames );
+        Objects.requireNonNull( query, "query" );
+        this._query = query;
+    }
+
+    public QueryExpression getQuery()
+    {
+        return this._query;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/ColumnSourceByValuesImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/ColumnSourceByValuesImpl.java
new file mode 100644
index 0000000..f999371
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/ColumnSourceByValuesImpl.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.modification;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSourceByValues;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ColumnSourceByValuesImpl extends DynamicColumnSourceImpl<ColumnSourceByValues>
+    implements ColumnSourceByValues
+{
+
+    private final List<ValueExpression> _expressions;
+
+    public ColumnSourceByValuesImpl( SQLProcessorAggregator processor, ColumnNameList columnNames,
+                                     List<ValueExpression> expressions )
+    {
+        this( processor, ColumnSourceByValues.class, columnNames, expressions );
+    }
+
+    protected ColumnSourceByValuesImpl( SQLProcessorAggregator processor,
+                                        Class<? extends ColumnSourceByValues> expressionClass, ColumnNameList columnNames,
+                                        List<ValueExpression> expressions )
+    {
+        super( processor, expressionClass, columnNames );
+        Objects.requireNonNull( expressions, "expressions" );
+        if( expressions.isEmpty() )
+        {
+            throw new IllegalArgumentException( "Empty column source list not allowed." );
+        }
+
+        this._expressions = Collections.unmodifiableList( new ArrayList<ValueExpression>( expressions ) );
+    }
+
+    public List<ValueExpression> getValues()
+    {
+        return this._expressions;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/DeleteBySearchImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/DeleteBySearchImpl.java
new file mode 100644
index 0000000..21efdf7
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/DeleteBySearchImpl.java
@@ -0,0 +1,72 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.modification;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.modification.DeleteBySearch;
+import org.apache.polygene.library.sql.generator.grammar.modification.DeleteStatement;
+import org.apache.polygene.library.sql.generator.grammar.modification.TargetTable;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DeleteBySearchImpl extends SQLSyntaxElementBase<DeleteStatement, DeleteBySearch>
+    implements DeleteBySearch
+{
+
+    private final TargetTable _targetTable;
+
+    private final BooleanExpression _where;
+
+    public DeleteBySearchImpl( SQLProcessorAggregator processor, TargetTable targetTable, BooleanExpression where )
+    {
+        this( processor, DeleteBySearch.class, targetTable, where );
+    }
+
+    protected DeleteBySearchImpl( SQLProcessorAggregator processor, Class<? extends DeleteBySearch> expressionClass,
+                                  TargetTable targetTable, BooleanExpression where )
+    {
+        super( processor, expressionClass );
+        Objects.requireNonNull( targetTable, "target table" );
+        this._targetTable = targetTable;
+        this._where = where;
+    }
+
+    public TargetTable getTargetTable()
+    {
+        return this._targetTable;
+    }
+
+    public BooleanExpression getWhere()
+    {
+        return this._where;
+    }
+
+    @Override
+    protected boolean doesEqual( DeleteBySearch another )
+    {
+        return this._targetTable.equals( another.getTargetTable() )
+               && TypeableImpl.bothNullOrEquals( this._where, another.getWhere() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/DynamicColumnSourceImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/DynamicColumnSourceImpl.java
new file mode 100644
index 0000000..2467b35
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/DynamicColumnSourceImpl.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.modification;
+
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSource;
+import org.apache.polygene.library.sql.generator.grammar.modification.DynamicColumnSource;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class DynamicColumnSourceImpl<ColumnSourceType extends DynamicColumnSource> extends
+                                                                                            SQLSyntaxElementBase<ColumnSource, ColumnSourceType>
+    implements DynamicColumnSource
+{
+
+    private final ColumnNameList _columnNames;
+
+    protected DynamicColumnSourceImpl( SQLProcessorAggregator processor,
+                                       Class<? extends ColumnSourceType> expressionClass, ColumnNameList columnNames )
+    {
+        super( processor, expressionClass );
+
+        this._columnNames = columnNames;
+    }
+
+    public ColumnNameList getColumnNames()
+    {
+        return this._columnNames;
+    }
+
+    @Override
+    protected boolean doesEqual( ColumnSourceType another )
+    {
+        return ( this._columnNames != null && this._columnNames.equals( another.getColumnNames() ) )
+               || ( this._columnNames == null && another.getColumnNames() == null );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/InsertStatementImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/InsertStatementImpl.java
new file mode 100644
index 0000000..f7c92f1
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/InsertStatementImpl.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.modification;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSource;
+import org.apache.polygene.library.sql.generator.grammar.modification.InsertStatement;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class InsertStatementImpl extends SQLSyntaxElementBase<InsertStatement, InsertStatement>
+    implements InsertStatement
+{
+
+    private final TableNameDirect _tableName;
+    private final ColumnSource _columnSource;
+
+    public InsertStatementImpl( SQLProcessorAggregator processor, TableNameDirect tableName, ColumnSource columnSource )
+    {
+        this( processor, InsertStatement.class, tableName, columnSource );
+    }
+
+    protected InsertStatementImpl( SQLProcessorAggregator processor, Class<? extends InsertStatement> expressionClass,
+                                   TableNameDirect tableName, ColumnSource columnSource )
+    {
+        super( processor, expressionClass );
+        Objects.requireNonNull( tableName, "tableName" );
+        Objects.requireNonNull( columnSource, "column source" );
+        this._tableName = tableName;
+        this._columnSource = columnSource;
+    }
+
+    public TableNameDirect getTableName()
+    {
+        return this._tableName;
+    }
+
+    public ColumnSource getColumnSource()
+    {
+        return this._columnSource;
+    }
+
+    @Override
+    protected boolean doesEqual( InsertStatement another )
+    {
+        return this._tableName.equals( another.getTableName() )
+               && this._columnSource.equals( another.getColumnSource() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/SetClauseImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/SetClauseImpl.java
new file mode 100644
index 0000000..25716fe
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/SetClauseImpl.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.modification;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.modification.SetClause;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateSource;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class SetClauseImpl extends SQLSyntaxElementBase<SetClause, SetClause>
+    implements SetClause
+{
+
+    private final String _target;
+
+    private final UpdateSource _source;
+
+    public SetClauseImpl( SQLProcessorAggregator processor, String updateTarget, UpdateSource updateSource )
+    {
+        this( processor, SetClause.class, updateTarget, updateSource );
+    }
+
+    protected SetClauseImpl( SQLProcessorAggregator processor, Class<? extends SetClause> expressionClass,
+                             String updateTarget, UpdateSource updateSource )
+    {
+        super( processor, expressionClass );
+        Objects.requireNonNull( updateTarget, "update target" );
+        Objects.requireNonNull( updateSource, "source" );
+
+        this._target = updateTarget;
+        this._source = updateSource;
+    }
+
+    public UpdateSource getUpdateSource()
+    {
+        return this._source;
+    }
+
+    public String getUpdateTarget()
+    {
+        return this._target;
+    }
+
+    @Override
+    protected boolean doesEqual( SetClause another )
+    {
+        return this._target.equals( another.getUpdateTarget() ) && this._source.equals( another.getUpdateSource() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/TargetTableImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/TargetTableImpl.java
new file mode 100644
index 0000000..af8a119
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/TargetTableImpl.java
@@ -0,0 +1,72 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.modification;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.modification.TargetTable;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TargetTableImpl extends SQLSyntaxElementBase<TargetTable, TargetTable>
+    implements TargetTable
+{
+
+    private Boolean _isOnly;
+
+    private TableNameDirect _tableName;
+
+    public TargetTableImpl( SQLProcessorAggregator processor, Boolean isOnly, TableNameDirect tableName )
+    {
+        this( processor, TargetTable.class, isOnly, tableName );
+    }
+
+    protected TargetTableImpl( SQLProcessorAggregator processor, Class<? extends TargetTable> expressionClass,
+                               Boolean isOnly, TableNameDirect tableName )
+    {
+        super( processor, expressionClass );
+        Objects.requireNonNull( tableName, "table name" );
+        if( isOnly == null )
+        {
+            isOnly = false;
+        }
+        this._tableName = tableName;
+        this._isOnly = isOnly;
+    }
+
+    public Boolean isOnly()
+    {
+        return this._isOnly;
+    }
+
+    public TableNameDirect getTableName()
+    {
+        return this._tableName;
+    }
+
+    @Override
+    protected boolean doesEqual( TargetTable another )
+    {
+        return this._tableName.equals( another.getTableName() ) && this._isOnly.equals( another.isOnly() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/UpdateBySearchImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/UpdateBySearchImpl.java
new file mode 100644
index 0000000..de8ae0a
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/UpdateBySearchImpl.java
@@ -0,0 +1,98 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.modification;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.modification.SetClause;
+import org.apache.polygene.library.sql.generator.grammar.modification.TargetTable;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateBySearch;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateStatement;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class UpdateBySearchImpl extends SQLSyntaxElementBase<UpdateStatement, UpdateBySearch>
+    implements UpdateBySearch
+{
+
+    private final TargetTable _targetTable;
+
+    private final List<SetClause> _setClauses;
+
+    private final BooleanExpression _where;
+
+    public UpdateBySearchImpl( SQLProcessorAggregator processor, TargetTable targetTable,
+                               List<SetClause> setClauses,
+                               BooleanExpression where )
+    {
+        this( processor, UpdateBySearch.class, targetTable, setClauses, where );
+    }
+
+    protected UpdateBySearchImpl( SQLProcessorAggregator processor,
+                                  Class<? extends UpdateBySearch> expressionClass,
+                                  TargetTable targetTable, List<SetClause> setClauses, BooleanExpression where )
+    {
+        super( processor, expressionClass );
+        Objects.requireNonNull( targetTable, "target table" );
+        Objects.requireNonNull( setClauses, "set clauses" );
+        if( setClauses.isEmpty() )
+        {
+            throw new IllegalArgumentException( "At least one set clause must be present." );
+        }
+        for( SetClause clause : setClauses )
+        {
+            Objects.requireNonNull( clause, "set clause" );
+        }
+
+        this._targetTable = targetTable;
+        this._setClauses = Collections.unmodifiableList( new ArrayList<SetClause>( setClauses ) );
+        this._where = where;
+    }
+
+    public TargetTable getTargetTable()
+    {
+        return this._targetTable;
+    }
+
+    public BooleanExpression getWhere()
+    {
+        return this._where;
+    }
+
+    public List<SetClause> getSetClauses()
+    {
+        return this._setClauses;
+    }
+
+    @Override
+    protected boolean doesEqual( UpdateBySearch another )
+    {
+        return this._targetTable.equals( another.getTargetTable() )
+               && this._setClauses.equals( another.getSetClauses() )
+               && TypeableImpl.bothNullOrEquals( this._where, another.getWhere() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/UpdateSourceByExpressionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/UpdateSourceByExpressionImpl.java
new file mode 100644
index 0000000..70d3664
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/UpdateSourceByExpressionImpl.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.modification;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateSource;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateSourceByExpression;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class UpdateSourceByExpressionImpl extends SQLSyntaxElementBase<UpdateSource, UpdateSourceByExpression>
+    implements UpdateSourceByExpression
+{
+
+    private final ValueExpression _valueExpression;
+
+    public UpdateSourceByExpressionImpl( SQLProcessorAggregator processor, ValueExpression valueExpression )
+    {
+        this( processor, UpdateSourceByExpression.class, valueExpression );
+    }
+
+    protected UpdateSourceByExpressionImpl( SQLProcessorAggregator processor,
+                                            Class<? extends UpdateSourceByExpression> expressionClass, ValueExpression valueExpression )
+    {
+        super( processor, expressionClass );
+        Objects.requireNonNull( valueExpression, "expression" );
+        this._valueExpression = valueExpression;
+    }
+
+    public ValueExpression getValueExpression()
+    {
+        return this._valueExpression;
+    }
+
+    @Override
+    protected boolean doesEqual( UpdateSourceByExpression another )
+    {
+        return this._valueExpression.equals( another.getValueExpression() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/pgsql/PgSQLInsertStatementImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/pgsql/PgSQLInsertStatementImpl.java
new file mode 100644
index 0000000..4c96727
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/modification/pgsql/PgSQLInsertStatementImpl.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.modification.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSource;
+import org.apache.polygene.library.sql.generator.grammar.modification.pgsql.PgSQLInsertStatement;
+import org.apache.polygene.library.sql.generator.grammar.query.SelectColumnClause;
+import org.apache.polygene.library.sql.generator.implementation.grammar.modification.InsertStatementImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+public class PgSQLInsertStatementImpl extends InsertStatementImpl implements PgSQLInsertStatement
+{
+
+    private final SelectColumnClause _returning;
+
+    public PgSQLInsertStatementImpl( SQLProcessorAggregator processor,
+                                     TableNameDirect tableName, ColumnSource columnSource, SelectColumnClause returning )
+    {
+        super( processor, PgSQLInsertStatement.class, tableName, columnSource );
+
+        this._returning = returning;
+    }
+
+    public SelectColumnClause getReturningClause()
+    {
+        return this._returning;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/AsteriskSelectImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/AsteriskSelectImpl.java
new file mode 100644
index 0000000..53c6e1f
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/AsteriskSelectImpl.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+import org.apache.polygene.library.sql.generator.grammar.query.AsteriskSelect;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class AsteriskSelectImpl extends SelectColumnClauseImpl<AsteriskSelect>
+    implements AsteriskSelect
+{
+    public AsteriskSelectImpl( SQLProcessorAggregator processor, SetQuantifier quantifier )
+    {
+        this( processor, AsteriskSelect.class, quantifier );
+    }
+
+    public AsteriskSelectImpl( SQLProcessorAggregator processor, Class<? extends AsteriskSelect> type,
+                               SetQuantifier quantifier )
+    {
+        super( processor, type, quantifier );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/ColumnReferenceByExpressionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/ColumnReferenceByExpressionImpl.java
new file mode 100644
index 0000000..afaf230
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/ColumnReferenceByExpressionImpl.java
@@ -0,0 +1,58 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferenceByExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ColumnReferenceByExpressionImpl extends ColumnReferenceImpl<ColumnReferenceByExpression>
+    implements ColumnReferenceByExpression
+{
+    private final ValueExpression _expression;
+
+    public ColumnReferenceByExpressionImpl( SQLProcessorAggregator processor, ValueExpression expression )
+    {
+        this( processor, ColumnReferenceByExpression.class, expression );
+    }
+
+    protected ColumnReferenceByExpressionImpl( SQLProcessorAggregator processor,
+                                               Class<? extends ColumnReferenceByExpression> implClass, ValueExpression expression )
+    {
+        super( processor, implClass );
+        Objects.requireNonNull( expression, "expression" );
+        this._expression = expression;
+    }
+
+    public ValueExpression getExpression()
+    {
+        return this._expression;
+    }
+
+    @Override
+    protected boolean doesEqual( ColumnReferenceByExpression another )
+    {
+        return this._expression.equals( another.getExpression() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/ColumnReferenceByNameImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/ColumnReferenceByNameImpl.java
new file mode 100644
index 0000000..689c635
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/ColumnReferenceByNameImpl.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferenceByName;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ColumnReferenceByNameImpl extends ColumnReferenceImpl<ColumnReferenceByName>
+    implements ColumnReferenceByName
+{
+
+    private final String _tableName;
+
+    private final String _columnName;
+
+    public ColumnReferenceByNameImpl( SQLProcessorAggregator processor, String tableName, String columnName )
+    {
+        this( processor, ColumnReferenceByName.class, tableName, columnName );
+    }
+
+    protected ColumnReferenceByNameImpl( SQLProcessorAggregator processor,
+                                         Class<? extends ColumnReferenceByName> implClass, String tableName, String columnName )
+    {
+        super( processor, implClass );
+        Objects.requireNonNull( columnName, "column name" );
+        this._tableName = tableName;
+        this._columnName = columnName;
+    }
+
+    public String getColumnName()
+    {
+        return this._columnName;
+    }
+
+    public String getTableName()
+    {
+        return this._tableName;
+    }
+
+    @Override
+    protected boolean doesEqual( ColumnReferenceByName another )
+    {
+        return this._columnName.equals( another.getColumnName() )
+               && TypeableImpl.bothNullOrEquals( this._tableName, another.getTableName() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/ColumnReferenceImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/ColumnReferenceImpl.java
new file mode 100644
index 0000000..22812e4
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/ColumnReferenceImpl.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReference;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.NonBooleanExpressionImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class ColumnReferenceImpl<ColumnReferenceType extends ColumnReference> extends
+                                                                                       NonBooleanExpressionImpl<ColumnReferenceType>
+    implements ColumnReference
+{
+    public ColumnReferenceImpl( SQLProcessorAggregator processor,
+                                Class<? extends ColumnReferenceType> columnReferenceClass )
+    {
+        super( processor, columnReferenceClass );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/ColumnReferencesImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/ColumnReferencesImpl.java
new file mode 100644
index 0000000..7213ad1
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/ColumnReferencesImpl.java
@@ -0,0 +1,79 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferences;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ColumnReferencesImpl extends SelectColumnClauseImpl<ColumnReferences>
+    implements ColumnReferences
+{
+
+    private final List<ColumnReferenceInfo> _columns;
+
+    public ColumnReferencesImpl( SQLProcessorAggregator processor, SetQuantifier quantifier,
+                                 ColumnReferenceInfo... columns )
+    {
+        this( processor, quantifier, Arrays.asList( columns ) );
+    }
+
+    public ColumnReferencesImpl( SQLProcessorAggregator processor, SetQuantifier quantifier,
+                                 List<ColumnReferenceInfo> columns )
+    {
+        this( processor, ColumnReferences.class, quantifier, columns );
+    }
+
+    public ColumnReferencesImpl( SQLProcessorAggregator processor, Class<? extends ColumnReferences> type,
+                                 SetQuantifier quantifier, List<ColumnReferenceInfo> columns )
+    {
+        super( processor, type, quantifier );
+        Objects.requireNonNull( columns, "columns" );
+        if( columns.isEmpty() )
+        {
+            throw new IllegalArgumentException( "Must have at least one column in column list." );
+        }
+
+        for( ColumnReferenceInfo column : columns )
+        {
+            Objects.requireNonNull( column, "column" );
+        }
+
+        this._columns = Collections.unmodifiableList( columns );
+    }
+
+    public List<ColumnReferenceInfo> getColumns()
+    {
+        return this._columns;
+    }
+
+    @Override
+    protected boolean doesEqual( ColumnReferences another )
+    {
+        return super.doesEqual( another ) && this._columns.equals( another.getColumns() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/CorrespondingSpecImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/CorrespondingSpecImpl.java
new file mode 100644
index 0000000..81780f3
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/CorrespondingSpecImpl.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.query.CorrespondingSpec;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class CorrespondingSpecImpl extends SQLSyntaxElementBase<CorrespondingSpec, CorrespondingSpec>
+    implements CorrespondingSpec
+{
+
+    private final ColumnNameList _columnList;
+
+    public CorrespondingSpecImpl( SQLProcessorAggregator processor, ColumnNameList columnNames )
+    {
+        this( processor, CorrespondingSpec.class, columnNames );
+    }
+
+    protected CorrespondingSpecImpl( SQLProcessorAggregator processor, Class<? extends CorrespondingSpec> implClass,
+                                     ColumnNameList columnNames )
+    {
+        super( processor, implClass );
+
+        this._columnList = columnNames;
+    }
+
+    public ColumnNameList getColumnList()
+    {
+        return this._columnList;
+    }
+
+    @Override
+    protected boolean doesEqual( CorrespondingSpec another )
+    {
+        return TypeableImpl.bothNullOrEquals( this._columnList, another.getColumnList() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/FromClauseImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/FromClauseImpl.java
new file mode 100644
index 0000000..44f8010
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/FromClauseImpl.java
@@ -0,0 +1,72 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.query.FromClause;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReference;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class FromClauseImpl extends SQLSyntaxElementBase<FromClause, FromClause>
+    implements FromClause
+{
+
+    private List<TableReference> _tableReferences;
+
+    public FromClauseImpl( SQLProcessorAggregator processor, TableReference... tableReferences )
+    {
+        this( processor, Arrays.asList( tableReferences ) );
+    }
+
+    public FromClauseImpl( SQLProcessorAggregator processor, List<TableReference> tableReferences )
+    {
+        this( processor, FromClause.class, tableReferences );
+    }
+
+    protected FromClauseImpl( SQLProcessorAggregator processor, Class<? extends FromClause> type,
+                              List<TableReference> tableReferences )
+    {
+        super( processor, type );
+        Objects.requireNonNull( tableReferences, "table references" );
+        for( TableReference ref : tableReferences )
+        {
+            Objects.requireNonNull( ref, "table reference" );
+        }
+        this._tableReferences = Collections.unmodifiableList( tableReferences );
+    }
+
+    public List<TableReference> getTableReferences()
+    {
+        return this._tableReferences;
+    }
+
+    @Override
+    protected boolean doesEqual( FromClause another )
+    {
+        return this._tableReferences.equals( another.getTableReferences() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/GroupByClauseImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/GroupByClauseImpl.java
new file mode 100644
index 0000000..838b1a2
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/GroupByClauseImpl.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.query.GroupByClause;
+import org.apache.polygene.library.sql.generator.grammar.query.GroupingElement;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class GroupByClauseImpl extends SQLSyntaxElementBase<GroupByClause, GroupByClause>
+    implements GroupByClause
+{
+
+    private final List<GroupingElement> _groupingElements;
+
+    public GroupByClauseImpl( SQLProcessorAggregator processor, List<GroupingElement> groupingElements )
+    {
+        super( processor, GroupByClause.class );
+        Objects.requireNonNull( groupingElements, "grouping elements" );
+        for( GroupingElement element : groupingElements )
+        {
+            Objects.requireNonNull( element, "grouping element" );
+        }
+        this._groupingElements = Collections.unmodifiableList( new ArrayList<GroupingElement>( groupingElements ) );
+    }
+
+    public List<GroupingElement> getGroupingElements()
+    {
+        return this._groupingElements;
+    }
+
+    @Override
+    protected boolean doesEqual( GroupByClause another )
+    {
+        return this._groupingElements.equals( another.getGroupingElements() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/LimitSpecificationImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/LimitSpecificationImpl.java
new file mode 100644
index 0000000..5c074a9
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/LimitSpecificationImpl.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.LimitSpecification;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author 2011 Stanislav Muhametsin
+ */
+public class LimitSpecificationImpl extends SQLSyntaxElementBase<LimitSpecification, LimitSpecification>
+    implements LimitSpecification
+{
+
+    private final NonBooleanExpression _count;
+
+    public LimitSpecificationImpl( SQLProcessorAggregator processor, NonBooleanExpression count )
+    {
+        this( processor, LimitSpecification.class, count );
+    }
+
+    protected LimitSpecificationImpl( SQLProcessorAggregator processor,
+                                      Class<? extends LimitSpecification> realImplementingType, NonBooleanExpression count )
+    {
+        super( processor, realImplementingType );
+
+        this._count = count;
+    }
+
+    public NonBooleanExpression getCount()
+    {
+        return this._count;
+    }
+
+    @Override
+    protected boolean doesEqual( LimitSpecification another )
+    {
+        return bothNullOrEquals( this._count, another.getCount() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/OffsetSpecificationImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/OffsetSpecificationImpl.java
new file mode 100644
index 0000000..0f3e798
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/OffsetSpecificationImpl.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.OffsetSpecification;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author 2011 Stanislav Muhametsin
+ */
+public class OffsetSpecificationImpl extends SQLSyntaxElementBase<OffsetSpecification, OffsetSpecification>
+    implements OffsetSpecification
+{
+
+    private final NonBooleanExpression _skip;
+
+    public OffsetSpecificationImpl( SQLProcessorAggregator processor, NonBooleanExpression skip )
+    {
+        this( processor, OffsetSpecification.class, skip );
+    }
+
+    protected OffsetSpecificationImpl( SQLProcessorAggregator processor,
+                                       Class<? extends OffsetSpecification> realImplementingType, NonBooleanExpression skip )
+    {
+        super( processor, realImplementingType );
+        Objects.requireNonNull( skip, "Skip" );
+        this._skip = skip;
+    }
+
+    public NonBooleanExpression getSkip()
+    {
+        return this._skip;
+    }
+
+    @Override
+    protected boolean doesEqual( OffsetSpecification another )
+    {
+        return this._skip.equals( another.getSkip() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/OrderByClauseImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/OrderByClauseImpl.java
new file mode 100644
index 0000000..ef56170
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/OrderByClauseImpl.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.query.OrderByClause;
+import org.apache.polygene.library.sql.generator.grammar.query.SortSpecification;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class OrderByClauseImpl extends SQLSyntaxElementBase<OrderByClause, OrderByClause>
+    implements OrderByClause
+{
+
+    private List<SortSpecification> _sortSpecs;
+
+    public OrderByClauseImpl( SQLProcessorAggregator processor, List<SortSpecification> sortSpecs )
+    {
+        super( processor, OrderByClause.class );
+        Objects.requireNonNull( sortSpecs, "sort specifications" );
+        for( SortSpecification sortSpec : sortSpecs )
+        {
+            Objects.requireNonNull( sortSpec, "sort specification" );
+        }
+
+        this._sortSpecs = Collections.unmodifiableList( new ArrayList<SortSpecification>( sortSpecs ) );
+    }
+
+    public List<SortSpecification> getOrderingColumns()
+    {
+        return this._sortSpecs;
+    }
+
+    @Override
+    protected boolean doesEqual( OrderByClause another )
+    {
+        return this._sortSpecs.equals( another.getOrderingColumns() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/OrdinaryGroupingSetImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/OrdinaryGroupingSetImpl.java
new file mode 100644
index 0000000..3ebd307
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/OrdinaryGroupingSetImpl.java
@@ -0,0 +1,73 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.GroupingElement;
+import org.apache.polygene.library.sql.generator.grammar.query.OrdinaryGroupingSet;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class OrdinaryGroupingSetImpl extends SQLSyntaxElementBase<GroupingElement, OrdinaryGroupingSet>
+    implements OrdinaryGroupingSet
+{
+    private final List<NonBooleanExpression> _columns;
+
+    public OrdinaryGroupingSetImpl( SQLProcessorAggregator processor, NonBooleanExpression... columns )
+    {
+        this( processor, Arrays.asList( columns ) );
+    }
+
+    public OrdinaryGroupingSetImpl( SQLProcessorAggregator processor, List<NonBooleanExpression> columns )
+    {
+        this( processor, OrdinaryGroupingSet.class, columns );
+    }
+
+    protected OrdinaryGroupingSetImpl( SQLProcessorAggregator processor,
+                                       Class<? extends OrdinaryGroupingSet> implClass, List<NonBooleanExpression> columns )
+    {
+        super( processor, implClass );
+        Objects.requireNonNull( columns, "columns" );
+        for( NonBooleanExpression expr : columns )
+        {
+            Objects.requireNonNull( expr, "column" );
+        }
+        this._columns = Collections.unmodifiableList( new ArrayList<NonBooleanExpression>( columns ) );
+    }
+
+    public List<NonBooleanExpression> getColumns()
+    {
+        return this._columns;
+    }
+
+    @Override
+    protected boolean doesEqual( OrdinaryGroupingSet another )
+    {
+        return this._columns.equals( another.getColumns() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/QueryExpressionBodyBinaryImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/QueryExpressionBodyBinaryImpl.java
new file mode 100644
index 0000000..eabbf92
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/QueryExpressionBodyBinaryImpl.java
@@ -0,0 +1,105 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+import org.apache.polygene.library.sql.generator.grammar.query.CorrespondingSpec;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBody;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBodyBinary;
+import org.apache.polygene.library.sql.generator.grammar.query.SetOperation;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class QueryExpressionBodyBinaryImpl extends QueryExpressionBodyImpl<QueryExpressionBodyBinary>
+    implements QueryExpressionBodyBinary
+{
+
+    private final SetOperation _setOperation;
+
+    private final QueryExpressionBody _left;
+
+    private final QueryExpressionBody _right;
+
+    private final SetQuantifier _setQuantifier;
+
+    private final CorrespondingSpec _correspondingColumns;
+
+    public QueryExpressionBodyBinaryImpl( SQLProcessorAggregator processor, SetOperation setOperation,
+                                          QueryExpressionBody left, QueryExpressionBody right, SetQuantifier setQuantifier,
+                                          CorrespondingSpec correspondingColumns )
+    {
+        this( processor, QueryExpressionBodyBinary.class, setOperation, left, right, setQuantifier,
+              correspondingColumns );
+    }
+
+    protected QueryExpressionBodyBinaryImpl( SQLProcessorAggregator processor,
+                                             Class<? extends QueryExpressionBodyBinary> implClass, SetOperation setOperation, QueryExpressionBody left,
+                                             QueryExpressionBody right, SetQuantifier setQuantifier, CorrespondingSpec correspondingColumns )
+    {
+        super( processor, implClass );
+        Objects.requireNonNull( setOperation, "set operation" );
+        Objects.requireNonNull( left, "left" );
+        Objects.requireNonNull( right, "right" );
+        Objects.requireNonNull( setQuantifier, "set quantifier" );
+        this._setOperation = setOperation;
+        this._left = left;
+        this._right = right;
+        this._correspondingColumns = correspondingColumns;
+        this._setQuantifier = setQuantifier;
+    }
+
+    public QueryExpressionBody getLeft()
+    {
+        return this._left;
+    }
+
+    public QueryExpressionBody getRight()
+    {
+        return this._right;
+    }
+
+    public SetOperation getSetOperation()
+    {
+        return this._setOperation;
+    }
+
+    public CorrespondingSpec getCorrespondingColumns()
+    {
+        return this._correspondingColumns;
+    }
+
+    public SetQuantifier getSetQuantifier()
+    {
+        return this._setQuantifier;
+    }
+
+    @Override
+    protected boolean doesEqual( QueryExpressionBodyBinary another )
+    {
+        return this._setOperation.equals( another.getSetOperation() )
+               && this._setQuantifier.equals( another.getSetQuantifier() )
+               && TypeableImpl.bothNullOrEquals( this._correspondingColumns, another.getCorrespondingColumns() )
+               && this._left.equals( another.getLeft() ) && this._right.equals( another.getRight() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/QueryExpressionBodyImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/QueryExpressionBodyImpl.java
new file mode 100644
index 0000000..700dcac
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/QueryExpressionBodyImpl.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBody;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.NonBooleanExpressionImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class QueryExpressionBodyImpl<ExpressionType extends QueryExpressionBody> extends
+                                                                                          NonBooleanExpressionImpl<ExpressionType>
+{
+
+    public QueryExpressionBodyImpl( SQLProcessorAggregator processor, Class<? extends ExpressionType> expressionClass )
+    {
+        super( processor, expressionClass );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/QueryExpressionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/QueryExpressionImpl.java
new file mode 100644
index 0000000..f2cb8f0
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/QueryExpressionImpl.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBody;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.NonBooleanExpressionImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class QueryExpressionImpl extends NonBooleanExpressionImpl<QueryExpression>
+    implements QueryExpression
+{
+
+    private final QueryExpressionBody _body;
+
+    public QueryExpressionImpl( SQLProcessorAggregator processor, QueryExpressionBody body )
+    {
+        this( processor, QueryExpression.class, body );
+    }
+
+    protected QueryExpressionImpl( SQLProcessorAggregator processor, Class<? extends QueryExpression> implClass,
+                                   QueryExpressionBody body )
+    {
+        super( processor, implClass );
+        Objects.requireNonNull( body, "query expression body" );
+        this._body = body;
+    }
+
+    public QueryExpressionBody getQueryExpressionBody()
+    {
+        return this._body;
+    }
+
+    @Override
+    protected boolean doesEqual( QueryExpression another )
+    {
+        return this._body.equals( another.getQueryExpressionBody() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/QuerySpecificationImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/QuerySpecificationImpl.java
new file mode 100644
index 0000000..812a341
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/QuerySpecificationImpl.java
@@ -0,0 +1,130 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.FromClause;
+import org.apache.polygene.library.sql.generator.grammar.query.GroupByClause;
+import org.apache.polygene.library.sql.generator.grammar.query.LimitSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.OffsetSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.OrderByClause;
+import org.apache.polygene.library.sql.generator.grammar.query.QuerySpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.SelectColumnClause;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class QuerySpecificationImpl extends QueryExpressionBodyImpl<QuerySpecification>
+    implements QuerySpecification
+{
+
+    private final SelectColumnClause _select;
+
+    private final FromClause _from;
+
+    private final BooleanExpression _where;
+
+    private final GroupByClause _groupBy;
+
+    private final BooleanExpression _having;
+
+    private final OrderByClause _orderBy;
+
+    private final OffsetSpecification _offset;
+
+    private final LimitSpecification _limit;
+
+    public QuerySpecificationImpl( SQLProcessorAggregator processor, SelectColumnClause select, FromClause from,
+                                   BooleanExpression where, GroupByClause groupBy, BooleanExpression having, OrderByClause orderBy,
+                                   OffsetSpecification offset, LimitSpecification limit )
+    {
+        this( processor, QuerySpecification.class, select, from, where, groupBy, having, orderBy, offset, limit );
+    }
+
+    protected QuerySpecificationImpl( SQLProcessorAggregator processor, Class<? extends QuerySpecification> queryClass,
+                                      SelectColumnClause select, FromClause from, BooleanExpression where, GroupByClause groupBy,
+                                      BooleanExpression having, OrderByClause orderBy, OffsetSpecification offset, LimitSpecification limit )
+    {
+        super( processor, queryClass );
+        Objects.requireNonNull( select, "select" );
+        this._select = select;
+        this._from = from;
+        this._where = where;
+        this._groupBy = groupBy;
+        this._having = having;
+        this._orderBy = orderBy;
+        this._offset = offset;
+        this._limit = limit;
+    }
+
+    public SelectColumnClause getColumns()
+    {
+        return this._select;
+    }
+
+    public FromClause getFrom()
+    {
+        return this._from;
+    }
+
+    public BooleanExpression getWhere()
+    {
+        return this._where;
+    }
+
+    public GroupByClause getGroupBy()
+    {
+        return this._groupBy;
+    }
+
+    public BooleanExpression getHaving()
+    {
+        return this._having;
+    }
+
+    public OrderByClause getOrderBy()
+    {
+        return this._orderBy;
+    }
+
+    public LimitSpecification getLimitSpecification()
+    {
+        return this._limit;
+    }
+
+    public OffsetSpecification getOffsetSpecification()
+    {
+        return this._offset;
+    }
+
+    @Override
+    protected boolean doesEqual( QuerySpecification another )
+    {
+        return this._select.equals( another.getColumns() )
+               && TypeableImpl.bothNullOrEquals( this._from, another.getFrom() )
+               && TypeableImpl.bothNullOrEquals( this._where, another.getWhere() )
+               && TypeableImpl.bothNullOrEquals( this._groupBy, another.getGroupBy() )
+               && TypeableImpl.bothNullOrEquals( this._having, another.getHaving() )
+               && TypeableImpl.bothNullOrEquals( this._orderBy, another.getOrderBy() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/RowDefinitionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/RowDefinitionImpl.java
new file mode 100644
index 0000000..51cf107
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/RowDefinitionImpl.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.RowDefinition;
+import org.apache.polygene.library.sql.generator.grammar.query.RowValueConstructor;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class RowDefinitionImpl extends SQLSyntaxElementBase<RowValueConstructor, RowDefinition>
+    implements RowDefinition
+{
+
+    private List<ValueExpression> _rowElements;
+
+    public RowDefinitionImpl( SQLProcessorAggregator processor, List<ValueExpression> rowElements )
+    {
+        this( processor, RowDefinition.class, rowElements );
+    }
+
+    protected RowDefinitionImpl( SQLProcessorAggregator processor, Class<? extends RowDefinition> realImplementingType,
+                                 List<ValueExpression> rowElements )
+    {
+        super( processor, realImplementingType );
+        Objects.requireNonNull( rowElements, "row elements" );
+        this._rowElements = Collections.unmodifiableList( rowElements );
+    }
+
+    public List<ValueExpression> getRowElements()
+    {
+        return this._rowElements;
+    }
+
+    @Override
+    protected boolean doesEqual( RowDefinition another )
+    {
+        return this._rowElements.equals( another.getRowElements() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/RowSubQueryImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/RowSubQueryImpl.java
new file mode 100644
index 0000000..ca50e05
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/RowSubQueryImpl.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.RowSubQuery;
+import org.apache.polygene.library.sql.generator.grammar.query.RowValueConstructor;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class RowSubQueryImpl extends SQLSyntaxElementBase<RowValueConstructor, RowSubQuery>
+    implements RowSubQuery
+{
+    private final QueryExpression _queryExpression;
+
+    public RowSubQueryImpl( SQLProcessorAggregator processor, QueryExpression queryExpression )
+    {
+        this( processor, RowSubQuery.class, queryExpression );
+    }
+
+    protected RowSubQueryImpl( SQLProcessorAggregator processor, Class<? extends RowSubQuery> realImplementingType,
+                               QueryExpression queryExpression )
+    {
+        super( processor, realImplementingType );
+        Objects.requireNonNull( queryExpression, "query expression" );
+        this._queryExpression = queryExpression;
+    }
+
+    public QueryExpression getQueryExpression()
+    {
+        return this._queryExpression;
+    }
+
+    @Override
+    protected boolean doesEqual( RowSubQuery another )
+    {
+        return this._queryExpression.equals( another.getQueryExpression() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/SelectColumnClauseImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/SelectColumnClauseImpl.java
new file mode 100644
index 0000000..8be59aa
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/SelectColumnClauseImpl.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+import org.apache.polygene.library.sql.generator.grammar.query.SelectColumnClause;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class SelectColumnClauseImpl<SelectType extends SelectColumnClause> extends
+                                                                                    SQLSyntaxElementBase<SelectColumnClause, SelectType>
+    implements SelectColumnClause
+{
+
+    private final SetQuantifier _setQuantifier;
+
+    protected SelectColumnClauseImpl( SQLProcessorAggregator processor, Class<? extends SelectType> type,
+                                      SetQuantifier quantifier )
+    {
+        super( processor, type );
+        Objects.requireNonNull( quantifier, "set quantifier" );
+        this._setQuantifier = quantifier;
+    }
+
+    public SetQuantifier getSetQuantifier()
+    {
+        return this._setQuantifier;
+    }
+
+    @Override
+    protected boolean doesEqual( SelectType another )
+    {
+        return this._setQuantifier.equals( another.getSetQuantifier() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/SortSpecificationImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/SortSpecificationImpl.java
new file mode 100644
index 0000000..9fbec3a
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/SortSpecificationImpl.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.Ordering;
+import org.apache.polygene.library.sql.generator.grammar.query.SortSpecification;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class SortSpecificationImpl extends SQLSyntaxElementBase<SortSpecification, SortSpecification>
+    implements SortSpecification
+{
+    private final Ordering _ordering;
+
+    private final ValueExpression _expression;
+
+    public SortSpecificationImpl( SQLProcessorAggregator processor, ValueExpression expression, Ordering ordering )
+    {
+        this( processor, SortSpecification.class, expression, ordering );
+    }
+
+    protected SortSpecificationImpl( SQLProcessorAggregator processor, Class<? extends SortSpecification> implClass,
+                                     ValueExpression expression, Ordering ordering )
+    {
+        super( processor, implClass );
+        Objects.requireNonNull( expression, "expression" );
+        Objects.requireNonNull( ordering, "ordering" );
+
+        this._expression = expression;
+        this._ordering = ordering;
+    }
+
+    public Ordering getOrderingSpecification()
+    {
+        return this._ordering;
+    }
+
+    public ValueExpression getValueExpression()
+    {
+        return this._expression;
+    }
+
+    @Override
+    protected boolean doesEqual( SortSpecification another )
+    {
+        return this._ordering.equals( another.getOrderingSpecification() )
+               && this._expression.equals( another.getOrderingSpecification() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableAliasImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableAliasImpl.java
new file mode 100644
index 0000000..04b5b57
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableAliasImpl.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.query.TableAlias;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TableAliasImpl extends SQLSyntaxElementBase<TableAlias, TableAlias>
+    implements TableAlias
+{
+    private final String _tableAlias;
+
+    private final ColumnNameList _columnAliases;
+
+    public TableAliasImpl( SQLProcessorAggregator processor, String tableAlias, ColumnNameList columnNames )
+    {
+        this( processor, TableAlias.class, tableAlias, columnNames );
+    }
+
+    protected TableAliasImpl( SQLProcessorAggregator processor, Class<? extends TableAlias> implementingClass,
+                              String tableAlias, ColumnNameList columnNames )
+    {
+        super( processor, implementingClass );
+        Objects.requireNonNull( tableAlias, "table alias table name" );
+        this._tableAlias = tableAlias;
+        this._columnAliases = columnNames;
+    }
+
+    public ColumnNameList getColumnAliases()
+    {
+        return this._columnAliases;
+    }
+
+    public String getTableAlias()
+    {
+        return this._tableAlias;
+    }
+
+    @Override
+    protected boolean doesEqual( TableAlias another )
+    {
+        return this._tableAlias.equals( another.getTableAlias() )
+               && bothNullOrEquals( this._columnAliases, another.getColumnAliases() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableReferenceByExpressionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableReferenceByExpressionImpl.java
new file mode 100644
index 0000000..9278dad
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableReferenceByExpressionImpl.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.TableAlias;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferenceByExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TableReferenceByExpressionImpl extends TableReferencePrimaryImpl<TableReferenceByExpression>
+    implements TableReferenceByExpression
+{
+    private final QueryExpression _expression;
+
+    public TableReferenceByExpressionImpl( SQLProcessorAggregator processor, QueryExpression expression,
+                                           TableAlias alias )
+    {
+        this( processor, TableReferenceByExpression.class, expression, alias );
+    }
+
+    protected TableReferenceByExpressionImpl( SQLProcessorAggregator processor,
+                                              Class<? extends TableReferenceByExpression> implClass, QueryExpression expression, TableAlias alias )
+    {
+        super( processor, implClass, alias );
+        Objects.requireNonNull( expression, "collection expression" );
+        this._expression = expression;
+    }
+
+    public QueryExpression getQuery()
+    {
+        return this._expression;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableReferenceByNameImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableReferenceByNameImpl.java
new file mode 100644
index 0000000..2f54001
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableReferenceByNameImpl.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.TableName;
+import org.apache.polygene.library.sql.generator.grammar.query.TableAlias;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferenceByName;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TableReferenceByNameImpl extends TableReferencePrimaryImpl<TableReferenceByName>
+    implements TableReferenceByName
+{
+    private final TableName _tableName;
+
+    public TableReferenceByNameImpl( SQLProcessorAggregator processor, TableName tableName, TableAlias alias )
+    {
+        this( processor, TableReferenceByName.class, tableName, alias );
+    }
+
+    protected TableReferenceByNameImpl( SQLProcessorAggregator processor,
+                                        Class<? extends TableReferenceByName> implClass, TableName tableName, TableAlias alias )
+    {
+        super( processor, implClass, alias );
+        Objects.requireNonNull( tableName, "table name" );
+        this._tableName = tableName;
+    }
+
+    public TableName getTableName()
+    {
+        return this._tableName;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableReferenceImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableReferenceImpl.java
new file mode 100644
index 0000000..762c002
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableReferenceImpl.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReference;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class TableReferenceImpl<TypeableType extends Typeable<? super TypeableType>, RealType extends TypeableType>
+    extends SQLSyntaxElementBase<TypeableType, RealType>
+    implements TableReference
+{
+
+    public TableReferenceImpl( SQLProcessorAggregator processor, Class<? extends RealType> expressionClass )
+    {
+        super( processor, expressionClass );
+    }
+
+    public Typeable<?> asTypeable()
+    {
+        return this;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableReferencePrimaryImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableReferencePrimaryImpl.java
new file mode 100644
index 0000000..9423618
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableReferencePrimaryImpl.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import org.apache.polygene.library.sql.generator.grammar.query.TableAlias;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferencePrimary;
+import org.apache.polygene.library.sql.generator.implementation.TypeableImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TableReferencePrimaryImpl<TableReferenceType extends TableReferencePrimary> extends
+                                                                                         TableReferenceImpl<TableReferencePrimary, TableReferenceType>
+    implements TableReferencePrimary
+{
+
+    private final TableAlias _tableAlias;
+
+    public TableReferencePrimaryImpl( SQLProcessorAggregator processor,
+                                      Class<? extends TableReferenceType> tableReferenceClass, TableAlias alias )
+    {
+        super( processor, tableReferenceClass );
+        this._tableAlias = alias;
+    }
+
+    public TableAlias getTableAlias()
+    {
+        return this._tableAlias;
+    }
+
+    @Override
+    protected boolean doesEqual( TableReferenceType another )
+    {
+        return TypeableImpl.bothNullOrEquals( this._tableAlias, another.getTableAlias() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableValueConstructorImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableValueConstructorImpl.java
new file mode 100644
index 0000000..84dc5c9
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/TableValueConstructorImpl.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.query.RowValueConstructor;
+import org.apache.polygene.library.sql.generator.grammar.query.TableValueConstructor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TableValueConstructorImpl extends QueryExpressionBodyImpl<TableValueConstructor>
+    implements TableValueConstructor
+{
+
+    private final List<RowValueConstructor> _rows;
+
+    public TableValueConstructorImpl( SQLProcessorAggregator processor, List<RowValueConstructor> rows )
+    {
+        this( processor, TableValueConstructor.class, rows );
+    }
+
+    protected TableValueConstructorImpl( SQLProcessorAggregator processor,
+                                         Class<? extends TableValueConstructor> expressionClass, List<RowValueConstructor> rows )
+    {
+        super( processor, expressionClass );
+        Objects.requireNonNull( rows, "rows" );
+        this._rows = Collections.unmodifiableList( rows );
+    }
+
+    public List<RowValueConstructor> getRows()
+    {
+        return this._rows;
+    }
+
+    @Override
+    protected boolean doesEqual( TableValueConstructor other )
+    {
+        return this._rows.equals( other.getRows() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/CrossJoinedTableImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/CrossJoinedTableImpl.java
new file mode 100644
index 0000000..a60d038
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/CrossJoinedTableImpl.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query.joins;
+
+import org.apache.polygene.library.sql.generator.grammar.query.TableReference;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.CrossJoinedTable;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class CrossJoinedTableImpl extends JoinedTableImpl<CrossJoinedTable>
+    implements CrossJoinedTable
+{
+
+    public CrossJoinedTableImpl( SQLProcessorAggregator processor, TableReference left, TableReference right )
+    {
+        this( processor, CrossJoinedTable.class, left, right );
+    }
+
+    protected CrossJoinedTableImpl( SQLProcessorAggregator processor, Class<? extends CrossJoinedTable> implClass,
+                                    TableReference left, TableReference right )
+    {
+        super( processor, implClass, left, right );
+    }
+
+    @Override
+    protected boolean doesEqual( CrossJoinedTable another )
+    {
+        boolean result = this.getRight().equals( another.getRight() );
+        if( result )
+        {
+            result = super.doesEqual( another );
+        }
+
+        return result;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/JoinConditionImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/JoinConditionImpl.java
new file mode 100644
index 0000000..7859695
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/JoinConditionImpl.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query.joins;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinCondition;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class JoinConditionImpl extends JoinSpecificationImpl<JoinCondition>
+    implements JoinCondition
+{
+
+    private final BooleanExpression _searchCondition;
+
+    public JoinConditionImpl( SQLProcessorAggregator processor, BooleanExpression searchCondition )
+    {
+        this( processor, JoinCondition.class, searchCondition );
+    }
+
+    protected JoinConditionImpl( SQLProcessorAggregator processor, Class<? extends JoinCondition> implClass,
+                                 BooleanExpression searchCondition )
+    {
+        super( processor, implClass );
+        Objects.requireNonNull( searchCondition, "search condition" );
+        this._searchCondition = searchCondition;
+    }
+
+    public BooleanExpression getSearchConidition()
+    {
+        return this._searchCondition;
+    }
+
+    @Override
+    protected boolean doesEqual( JoinCondition another )
+    {
+        return this._searchCondition.equals( another.getSearchConidition() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/JoinSpecificationImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/JoinSpecificationImpl.java
new file mode 100644
index 0000000..ef7c914
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/JoinSpecificationImpl.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query.joins;
+
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinSpecification;
+import org.apache.polygene.library.sql.generator.implementation.grammar.common.SQLSyntaxElementBase;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class JoinSpecificationImpl<JoinSpecificationType extends JoinSpecification> extends
+                                                                                             SQLSyntaxElementBase<JoinSpecification, JoinSpecificationType>
+    implements JoinSpecification
+{
+
+    public JoinSpecificationImpl( SQLProcessorAggregator processor,
+                                  Class<? extends JoinSpecificationType> expressionClass )
+    {
+        super( processor, expressionClass );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/JoinedTableImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/JoinedTableImpl.java
new file mode 100644
index 0000000..07a9b04
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/JoinedTableImpl.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query.joins;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReference;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinedTable;
+import org.apache.polygene.library.sql.generator.implementation.grammar.query.QueryExpressionBodyImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class JoinedTableImpl<TableReferenceType extends JoinedTable> extends
+                                                                              QueryExpressionBodyImpl<TableReferenceType>
+    implements JoinedTable
+{
+
+    private final TableReference _left;
+    private final TableReference _right;
+
+    protected JoinedTableImpl( SQLProcessorAggregator processor,
+                               Class<? extends TableReferenceType> tableReferenceClass, TableReference left, TableReference right )
+    {
+        super( processor, tableReferenceClass );
+        Objects.requireNonNull( left, "left" );
+        Objects.requireNonNull( right, "right" );
+        this._left = left;
+        this._right = right;
+    }
+
+    public TableReference getLeft()
+    {
+        return this._left;
+    }
+
+    public TableReference getRight()
+    {
+        return this._right;
+    }
+
+    public Typeable<?> asTypeable()
+    {
+        return this;
+    }
+
+    @Override
+    protected boolean doesEqual( TableReferenceType another )
+    {
+        return this._left.equals( another.getLeft() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/NamedColumnsJoinImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/NamedColumnsJoinImpl.java
new file mode 100644
index 0000000..7bc45d9
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/NamedColumnsJoinImpl.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query.joins;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.NamedColumnsJoin;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class NamedColumnsJoinImpl extends JoinSpecificationImpl<NamedColumnsJoin>
+    implements NamedColumnsJoin
+{
+
+    private final ColumnNameList _columnNames;
+
+    public NamedColumnsJoinImpl( SQLProcessorAggregator processor, ColumnNameList columnNames )
+    {
+        this( processor, NamedColumnsJoin.class, columnNames );
+    }
+
+    protected NamedColumnsJoinImpl( SQLProcessorAggregator processor, Class<? extends NamedColumnsJoin> implClass,
+                                    ColumnNameList columnNames )
+    {
+        super( processor, implClass );
+        Objects.requireNonNull( columnNames, "column names" );
+        this._columnNames = columnNames;
+    }
+
+    public ColumnNameList getColumnNames()
+    {
+        return this._columnNames;
+    }
+
+    @Override
+    protected boolean doesEqual( NamedColumnsJoin another )
+    {
+        return this._columnNames.equals( another.getColumnNames() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/NaturalJoinedTableImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/NaturalJoinedTableImpl.java
new file mode 100644
index 0000000..b1663f7
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/NaturalJoinedTableImpl.java
@@ -0,0 +1,67 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query.joins;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReference;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinType;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.NaturalJoinedTable;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class NaturalJoinedTableImpl extends JoinedTableImpl<NaturalJoinedTable>
+    implements NaturalJoinedTable
+{
+
+    private final JoinType _joinType;
+
+    public NaturalJoinedTableImpl( SQLProcessorAggregator processor, TableReference left, TableReference right,
+                                   JoinType joinType )
+    {
+        this( processor, NaturalJoinedTable.class, left, right, joinType );
+    }
+
+    protected NaturalJoinedTableImpl( SQLProcessorAggregator processor, Class<? extends NaturalJoinedTable> implClass,
+                                      TableReference left, TableReference right, JoinType joinType )
+    {
+        super( processor, implClass, left, right );
+        Objects.requireNonNull( joinType, "join type" );
+        this._joinType = joinType;
+    }
+
+    public JoinType getJoinType()
+    {
+        return this._joinType;
+    }
+
+    @Override
+    protected boolean doesEqual( NaturalJoinedTable another )
+    {
+        boolean result = this._joinType.equals( another.getJoinType() ) && this.getRight().equals( another.getRight() );
+        if( result )
+        {
+            result = super.doesEqual( another );
+        }
+
+        return result;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/QualifiedJoinedTableImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/QualifiedJoinedTableImpl.java
new file mode 100644
index 0000000..864c82b
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/QualifiedJoinedTableImpl.java
@@ -0,0 +1,78 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query.joins;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReference;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinType;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.QualifiedJoinedTable;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class QualifiedJoinedTableImpl extends JoinedTableImpl<QualifiedJoinedTable>
+    implements QualifiedJoinedTable
+{
+
+    private final JoinType _joinType;
+
+    private final JoinSpecification _joinSpec;
+
+    public QualifiedJoinedTableImpl( SQLProcessorAggregator processor, TableReference left, TableReference right,
+                                     JoinType joinType, JoinSpecification joinSpec )
+    {
+        this( processor, QualifiedJoinedTable.class, left, right, joinType, joinSpec );
+    }
+
+    protected QualifiedJoinedTableImpl( SQLProcessorAggregator processor,
+                                        Class<? extends QualifiedJoinedTable> implClass, TableReference left, TableReference right, JoinType joinType,
+                                        JoinSpecification joinSpec )
+    {
+        super( processor, implClass, left, right );
+        Objects.requireNonNull( joinType, "join type" );
+        Objects.requireNonNull( joinSpec, "join specification" );
+        this._joinType = joinType;
+        this._joinSpec = joinSpec;
+    }
+
+    public JoinType getJoinType()
+    {
+        return this._joinType;
+    }
+
+    public JoinSpecification getJoinSpecification()
+    {
+        return this._joinSpec;
+    }
+
+    @Override
+    protected boolean doesEqual( QualifiedJoinedTable another )
+    {
+        boolean result = this._joinType.equals( another.getJoinType() )
+                         && this._joinSpec.equals( another.getJoinSpecification() ) && this.getRight().equals( another.getRight() );
+        if( result )
+        {
+            result = super.doesEqual( another );
+        }
+        return result;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/UnionJoinedTableImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/UnionJoinedTableImpl.java
new file mode 100644
index 0000000..9d7496b
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/grammar/query/joins/UnionJoinedTableImpl.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.grammar.query.joins;
+
+import org.apache.polygene.library.sql.generator.grammar.query.TableReference;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.UnionJoinedTable;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class UnionJoinedTableImpl extends JoinedTableImpl<UnionJoinedTable>
+    implements UnionJoinedTable
+{
+
+    public UnionJoinedTableImpl( SQLProcessorAggregator processor, TableReference left, TableReference right )
+    {
+        this( processor, UnionJoinedTable.class, left, right );
+    }
+
+    protected UnionJoinedTableImpl( SQLProcessorAggregator processor, Class<? extends UnionJoinedTable> implClass,
+                                    TableReference left, TableReference right )
+    {
+        super( processor, implClass, left, right );
+    }
+
+    @Override
+    protected boolean doesEqual( UnionJoinedTable another )
+    {
+        boolean result = this.getRight().equals( another.getRight() );
+        if( result )
+        {
+            result = super.doesEqual( another );
+        }
+
+        return result;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/AbstractProcessor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/AbstractProcessor.java
new file mode 100644
index 0000000..661014d
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/AbstractProcessor.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class AbstractProcessor<ProcessableType extends Typeable<?>>
+    implements SQLProcessor
+{
+
+    private final Class<? extends ProcessableType> _type;
+
+    public AbstractProcessor( Class<? extends ProcessableType> realType )
+    {
+        Objects.requireNonNull( realType, "Processable type" );
+        this._type = realType;
+    }
+
+    public void process( SQLProcessorAggregator aggregator, Typeable<?> object, StringBuilder builder )
+    {
+        if( object != null )
+        {
+            this.doProcess( aggregator, this._type.cast( object ), builder );
+        }
+    }
+
+    protected abstract void doProcess( SQLProcessorAggregator aggregator, ProcessableType object, StringBuilder builder );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/BooleanExpressionProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/BooleanExpressionProcessing.java
new file mode 100644
index 0000000..8b42d9b
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/BooleanExpressionProcessing.java
@@ -0,0 +1,289 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation;
+
+import java.util.Iterator;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BinaryPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanTest;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanTest.TestType;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Conjunction;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Disjunction;
+import org.apache.polygene.library.sql.generator.grammar.booleans.MultiPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Negation;
+import org.apache.polygene.library.sql.generator.grammar.booleans.UnaryPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.BooleanUtils;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * Currently not thread-safe.
+ *
+ * @author Stanislav Muhametsin
+ */
+public class BooleanExpressionProcessing
+{
+    public static class UnaryPredicateProcessor extends AbstractProcessor<UnaryPredicate>
+    {
+        public enum UnaryOperatorOrientation
+        {
+            BEFORE_EXPRESSION, // After expression
+            AFTER_EXPRESSION
+            // Before expression
+        }
+
+        public static final UnaryOperatorOrientation DEFAULT_ORIENTATION = UnaryOperatorOrientation.AFTER_EXPRESSION;
+
+        private final UnaryOperatorOrientation _orientation;
+        private final String _operator;
+
+        public UnaryPredicateProcessor( String operator )
+        {
+            this( DEFAULT_ORIENTATION, operator );
+        }
+
+        public UnaryPredicateProcessor( UnaryOperatorOrientation unaryOrientation, String unaryOperator )
+        {
+            super( UnaryPredicate.class );
+            Objects.requireNonNull( unaryOrientation, "unary operator orientation" );
+            Objects.requireNonNull( unaryOperator, "unary operator" );
+            this._orientation = unaryOrientation;
+            this._operator = unaryOperator;
+        }
+
+        protected void doProcess( SQLProcessorAggregator processor, UnaryPredicate predicate, StringBuilder builder )
+        {
+            UnaryOperatorOrientation orientation = this._orientation;
+            if( orientation == UnaryOperatorOrientation.BEFORE_EXPRESSION )
+            {
+                builder.append( this._operator ).append( SQLConstants.TOKEN_SEPARATOR );
+            }
+
+            NonBooleanExpression exp = predicate.getValueExpression();
+            Boolean isQuery = exp instanceof QueryExpression;
+            if( isQuery )
+            {
+                builder.append( SQLConstants.OPEN_PARENTHESIS );
+            }
+            processor.process( exp, builder );
+            if( isQuery )
+            {
+                builder.append( SQLConstants.CLOSE_PARENTHESIS );
+            }
+
+            if( orientation == UnaryOperatorOrientation.AFTER_EXPRESSION )
+            {
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append( this._operator );
+            }
+        }
+    }
+
+    public static class BinaryPredicateProcessor extends AbstractProcessor<BinaryPredicate>
+    {
+        private final String _operator;
+
+        public BinaryPredicateProcessor( String binaryOperator )
+        {
+            super( BinaryPredicate.class );
+            Objects.requireNonNull( binaryOperator, "binary operator" );
+
+            this._operator = binaryOperator;
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, BinaryPredicate predicate, StringBuilder builder )
+        {
+            processor.process( predicate.getLeft(), builder );
+            builder.append( SQLConstants.TOKEN_SEPARATOR ).append( this._operator )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( predicate.getRight(), builder );
+        }
+    }
+
+    public static class MultiPredicateProcessor extends AbstractProcessor<MultiPredicate>
+    {
+        private final String _operator;
+        private final String _separator;
+        private final Boolean _needParenthesis;
+
+        public MultiPredicateProcessor( String multiOperator, String multiSeparator, Boolean needParenthesis )
+        {
+            super( MultiPredicate.class );
+            Objects.requireNonNull( multiOperator, "multi-operator" );
+            Objects.requireNonNull( multiSeparator, "multi separator" );
+            Objects.requireNonNull( needParenthesis, "need parenthesis" );
+
+            this._operator = multiOperator;
+            this._separator = multiSeparator;
+            this._needParenthesis = needParenthesis;
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, MultiPredicate predicate, StringBuilder builder )
+        {
+            processor.process( predicate.getLeft(), builder );
+            builder.append( SQLConstants.TOKEN_SEPARATOR ).append( this._operator )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+            if( this._needParenthesis )
+            {
+                builder.append( SQLConstants.OPEN_PARENTHESIS );
+            }
+
+            Iterator<NonBooleanExpression> iter = predicate.getRights().iterator();
+            while( iter.hasNext() )
+            {
+                NonBooleanExpression next = iter.next();
+                Boolean isQuery = next instanceof QueryExpression;
+
+                if( isQuery )
+                {
+                    builder.append( SQLConstants.OPEN_PARENTHESIS );
+                }
+
+                processor.process( next, builder );
+
+                if( isQuery )
+                {
+                    builder.append( SQLConstants.CLOSE_PARENTHESIS );
+                }
+
+                if( iter.hasNext() )
+                {
+                    builder.append( this._separator );
+                }
+            }
+
+            if( this._needParenthesis )
+            {
+                builder.append( SQLConstants.CLOSE_PARENTHESIS );
+            }
+        }
+    }
+
+    public static class NegationProcessor extends AbstractProcessor<Negation>
+    {
+        public NegationProcessor()
+        {
+            super( Negation.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, Negation object, StringBuilder builder )
+        {
+            BooleanExpression negated = object.getNegated();
+            if( !BooleanUtils.isEmpty( negated ) )
+            {
+                builder.append( SQLConstants.NOT ).append( SQLConstants.TOKEN_SEPARATOR );
+                aggregator.process( negated, builder );
+            }
+        }
+    }
+
+    public static void processBinaryComposedObject( SQLProcessorAggregator aggregator, BooleanExpression left,
+                                                    BooleanExpression right, StringBuilder builder, String operator )
+    {
+        Boolean leftEmpty = BooleanUtils.isEmpty( left );
+        Boolean rightEmpty = BooleanUtils.isEmpty( right );
+        if( !leftEmpty || !rightEmpty )
+        {
+            Boolean oneEmpty = leftEmpty || rightEmpty;
+            if( !oneEmpty )
+            {
+                builder.append( SQLConstants.OPEN_PARENTHESIS );
+            }
+            aggregator.process( left, builder );
+
+            if( !oneEmpty )
+            {
+                if( !leftEmpty )
+                {
+                    builder.append( SQLConstants.TOKEN_SEPARATOR );
+                }
+                builder.append( operator );
+                if( !rightEmpty )
+                {
+                    builder.append( SQLConstants.TOKEN_SEPARATOR );
+                }
+            }
+
+            aggregator.process( right, builder );
+            if( !oneEmpty )
+            {
+                builder.append( SQLConstants.CLOSE_PARENTHESIS );
+            }
+        }
+    }
+
+    public static class ConjunctionProcessor extends AbstractProcessor<Conjunction>
+    {
+
+        public ConjunctionProcessor()
+        {
+            super( Conjunction.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, Conjunction object, StringBuilder builder )
+        {
+            processBinaryComposedObject( aggregator, object.getLeft(), object.getRight(), builder, SQLConstants.AND );
+        }
+    }
+
+    public static class DisjunctionProcessor extends AbstractProcessor<Disjunction>
+    {
+        public DisjunctionProcessor()
+        {
+            super( Disjunction.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, Disjunction object, StringBuilder builder )
+        {
+            processBinaryComposedObject( aggregator, object.getLeft(), object.getRight(), builder, SQLConstants.OR );
+        }
+    }
+
+    public static class BooleanTestProcessor extends AbstractProcessor<BooleanTest>
+    {
+        public BooleanTestProcessor()
+        {
+            super( BooleanTest.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, BooleanTest object, StringBuilder builder )
+        {
+            BooleanExpression testable = object.getBooleanExpression();
+            builder.append( SQLConstants.OPEN_PARENTHESIS );
+            aggregator.process( testable, builder );
+            builder.append( SQLConstants.CLOSE_PARENTHESIS ).append( SQLConstants.IS )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+            if( object.getTestType() == TestType.IS_NOT )
+            {
+                builder.append( SQLConstants.NOT ).append( SQLConstants.TOKEN_SEPARATOR );
+            }
+
+            builder.append( object.getTruthValue().toString() );
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ColumnProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ColumnProcessing.java
new file mode 100644
index 0000000..2c2dbf8
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ColumnProcessing.java
@@ -0,0 +1,95 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation;
+
+import java.util.Iterator;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferenceByExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferenceByName;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ColumnProcessing
+{
+
+    public static class ColumnReferenceByNameProcessor extends AbstractProcessor<ColumnReferenceByName>
+    {
+        public ColumnReferenceByNameProcessor()
+        {
+            super( ColumnReferenceByName.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, ColumnReferenceByName columnRef,
+                                  StringBuilder builder )
+        {
+            String tableName = columnRef.getTableName();
+            if( ProcessorUtils.notNullAndNotEmpty( tableName ) )
+            {
+                builder.append( tableName ).append( SQLConstants.TABLE_COLUMN_SEPARATOR );
+            }
+
+            builder.append( columnRef.getColumnName() );
+        }
+    }
+
+    public static class ColumnReferenceByExpressionProcessor extends AbstractProcessor<ColumnReferenceByExpression>
+    {
+
+        public ColumnReferenceByExpressionProcessor()
+        {
+            super( ColumnReferenceByExpression.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, ColumnReferenceByExpression columnRef,
+                                  StringBuilder builder )
+        {
+            processor.process( columnRef.getExpression(), builder );
+        }
+    }
+
+    public static class ColumnNamesProcessor extends AbstractProcessor<ColumnNameList>
+    {
+        public ColumnNamesProcessor()
+        {
+            super( ColumnNameList.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, ColumnNameList object, StringBuilder builder )
+        {
+            builder.append( SQLConstants.OPEN_PARENTHESIS );
+            Iterator<String> iter = object.getColumnNames().iterator();
+            while( iter.hasNext() )
+            {
+                builder.append( iter.next() );
+                if( iter.hasNext() )
+                {
+                    builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                }
+            }
+            builder.append( SQLConstants.CLOSE_PARENTHESIS );
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ConstantProcessor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ConstantProcessor.java
new file mode 100644
index 0000000..a27c5f5
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ConstantProcessor.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ConstantProcessor
+    implements SQLProcessor
+{
+
+    private final String _constant;
+
+    public ConstantProcessor( String constant )
+    {
+        if( constant == null )
+        {
+            constant = "";
+        }
+
+        this._constant = constant;
+    }
+
+    public void process( SQLProcessorAggregator aggregator, Typeable<?> object, StringBuilder builder )
+    {
+        builder.append( this._constant );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/DataTypeProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/DataTypeProcessing.java
new file mode 100644
index 0000000..abb1b2d
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/DataTypeProcessing.java
@@ -0,0 +1,275 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.Decimal;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.IntervalDataType;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.Numeric;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLChar;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLFloat;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLInterval;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLTime;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLTimeStamp;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.UserDefinedType;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DataTypeProcessing
+{
+
+    public static class UserDefinedDataTypeProcessor extends AbstractProcessor<UserDefinedType>
+    {
+
+        public UserDefinedDataTypeProcessor()
+        {
+            super( UserDefinedType.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, UserDefinedType object, StringBuilder builder )
+        {
+            builder.append( object.getTextualRepresentation() );
+        }
+    }
+
+    public static class DecimalProcessor extends AbstractProcessor<Decimal>
+    {
+
+        public DecimalProcessor()
+        {
+            super( Decimal.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, Decimal object, StringBuilder builder )
+        {
+            builder.append( "DECIMAL" );
+            if( object.getPrecision() != null )
+            {
+                builder.append( SQLConstants.OPEN_PARENTHESIS ).append( object.getPrecision() );
+                if( object.getScale() != null )
+                {
+                    builder.append( object.getScale() );
+                }
+                builder.append( SQLConstants.CLOSE_PARENTHESIS );
+            }
+        }
+    }
+
+    public static class NumericProcessor extends AbstractProcessor<Numeric>
+    {
+
+        public NumericProcessor()
+        {
+            super( Numeric.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, Numeric object, StringBuilder builder )
+        {
+            builder.append( "NUMERIC" );
+            if( object.getPrecision() != null )
+            {
+                builder.append( SQLConstants.OPEN_PARENTHESIS ).append( object.getPrecision() );
+                if( object.getScale() != null )
+                {
+                    builder.append( object.getScale() );
+                }
+                builder.append( SQLConstants.CLOSE_PARENTHESIS );
+            }
+        }
+    }
+
+    public static class SQLCharProcessor extends AbstractProcessor<SQLChar>
+    {
+        public SQLCharProcessor()
+        {
+            super( SQLChar.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, SQLChar object, StringBuilder builder )
+        {
+            builder.append( "CHARACTER" );
+            if( object.isVarying() )
+            {
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "VARYING" );
+            }
+
+            if( object.getLength() != null )
+            {
+                builder.append( SQLConstants.OPEN_PARENTHESIS ).append( object.getLength() )
+                       .append( SQLConstants.CLOSE_PARENTHESIS );
+            }
+        }
+    }
+
+    public static class SQLFloatProcessor extends AbstractProcessor<SQLFloat>
+    {
+
+        public SQLFloatProcessor()
+        {
+            super( SQLFloat.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, SQLFloat object, StringBuilder builder )
+        {
+            builder.append( "FLOAT" );
+            if( object.getPrecision() != null )
+            {
+                builder.append( SQLConstants.OPEN_PARENTHESIS ).append( object.getPrecision() )
+                       .append( SQLConstants.CLOSE_PARENTHESIS );
+            }
+        }
+    }
+
+    public static class SQLIntervalProcessor extends AbstractProcessor<SQLInterval>
+    {
+
+        private final static Map<IntervalDataType, String> _defaultIntervalDataTypes;
+
+        static
+        {
+            Map<IntervalDataType, String> map = new HashMap<IntervalDataType, String>();
+            map.put( IntervalDataType.YEAR, "YEAR" );
+            map.put( IntervalDataType.MONTH, "MONTH" );
+            map.put( IntervalDataType.DAY, "DAY" );
+            map.put( IntervalDataType.HOUR, "HOUR" );
+            map.put( IntervalDataType.MINUTE, "MINUTE" );
+            map.put( IntervalDataType.SECOND, "SECOND" );
+
+            _defaultIntervalDataTypes = map;
+        }
+
+        private final Map<IntervalDataType, String> _intervalDataTypes;
+
+        public SQLIntervalProcessor()
+        {
+            this( _defaultIntervalDataTypes );
+        }
+
+        public SQLIntervalProcessor( Map<IntervalDataType, String> intervalDataTypes )
+        {
+            super( SQLInterval.class );
+
+            this._intervalDataTypes = intervalDataTypes;
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, SQLInterval object, StringBuilder builder )
+        {
+            builder.append( "INTERVAL" ).append( SQLConstants.TOKEN_SEPARATOR )
+                   .append( this._intervalDataTypes.get( object.getStartField() ) );
+
+            if( object.getStartFieldPrecision() != null )
+            {
+                builder.append( SQLConstants.OPEN_PARENTHESIS ).append( object.getStartFieldPrecision() );
+
+                if( object.getEndField() == null && object.getSecondFracs() != null )
+                {
+                    builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR )
+                           .append( object.getSecondFracs() );
+                }
+
+                builder.append( SQLConstants.CLOSE_PARENTHESIS );
+            }
+
+            if( object.getEndField() != null )
+            {
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "TO" ).append( SQLConstants.TOKEN_SEPARATOR )
+                       .append( this._intervalDataTypes.get( object.getEndField() ) );
+
+                if( object.getSecondFracs() != null )
+                {
+                    builder.append( SQLConstants.OPEN_PARENTHESIS ).append( object.getSecondFracs() )
+                           .append( SQLConstants.CLOSE_PARENTHESIS );
+                }
+            }
+        }
+    }
+
+    public static class SQLTimeProcessor extends AbstractProcessor<SQLTime>
+    {
+
+        public SQLTimeProcessor()
+        {
+            super( SQLTime.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, SQLTime object, StringBuilder builder )
+        {
+            builder.append( "TIME" );
+            if( object.getPrecision() != null )
+            {
+                builder.append( SQLConstants.OPEN_PARENTHESIS ).append( object.getPrecision() )
+                       .append( SQLConstants.CLOSE_PARENTHESIS );
+            }
+
+            if( object.isWithTimeZone() != null )
+            {
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "WITH" );
+                if( !object.isWithTimeZone() )
+                {
+                    builder.append( "OUT" );
+                }
+
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "TIME ZONE" );
+            }
+        }
+    }
+
+    public static class SQLTimeStampProcessor extends AbstractProcessor<SQLTimeStamp>
+    {
+
+        public SQLTimeStampProcessor()
+        {
+            super( SQLTimeStamp.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, SQLTimeStamp object, StringBuilder builder )
+        {
+            builder.append( "TIMESTAMP" );
+            if( object.getPrecision() != null )
+            {
+                builder.append( SQLConstants.OPEN_PARENTHESIS ).append( object.getPrecision() )
+                       .append( SQLConstants.CLOSE_PARENTHESIS );
+            }
+
+            if( object.isWithTimeZone() != null )
+            {
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "WITH" );
+                if( !object.isWithTimeZone() )
+                {
+                    builder.append( "OUT" );
+                }
+
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "TIME ZONE" );
+            }
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/DefaultSQLProcessor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/DefaultSQLProcessor.java
new file mode 100644
index 0000000..2a54858
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/DefaultSQLProcessor.java
@@ -0,0 +1,571 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BetweenPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BinaryPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression.False;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression.True;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanTest;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Conjunction;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Disjunction;
+import org.apache.polygene.library.sql.generator.grammar.booleans.EqualsPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.ExistsPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.GreaterOrEqualPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.GreaterThanPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.InPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.IsNotNullPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.IsNullPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.LessOrEqualPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.LessThanPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.LikePredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.MultiPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Negation;
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotBetweenPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotEqualsPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotInPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotLikePredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.Predicate.EmptyPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.UnaryPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.UniquePredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.ColumnNameList;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameFunction;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.BigInt;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.Decimal;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.DoublePrecision;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.Numeric;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.Real;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLBoolean;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLChar;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLDate;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLFloat;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLInteger;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLInterval;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLTime;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLTimeStamp;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SmallInt;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.UserDefinedType;
+import org.apache.polygene.library.sql.generator.grammar.definition.schema.SchemaDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.CheckConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ForeignKeyConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.LikeClause;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableElementList;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.UniqueConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.RegularViewSpecification;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.ViewDefinition;
+import org.apache.polygene.library.sql.generator.grammar.literals.DirectLiteral;
+import org.apache.polygene.library.sql.generator.grammar.literals.NumericLiteral;
+import org.apache.polygene.library.sql.generator.grammar.literals.SQLFunctionLiteral;
+import org.apache.polygene.library.sql.generator.grammar.literals.StringLiteral;
+import org.apache.polygene.library.sql.generator.grammar.literals.TimestampTimeLiteral;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AddColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AddTableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterColumnAction.DropDefault;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterTableStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropSchemaStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropTableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropTableOrViewStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.SetColumnDefault;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSource.Defaults;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSourceByQuery;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSourceByValues;
+import org.apache.polygene.library.sql.generator.grammar.modification.DeleteBySearch;
+import org.apache.polygene.library.sql.generator.grammar.modification.InsertStatement;
+import org.apache.polygene.library.sql.generator.grammar.modification.SetClause;
+import org.apache.polygene.library.sql.generator.grammar.modification.TargetTable;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateBySearch;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateSourceByExpression;
+import org.apache.polygene.library.sql.generator.grammar.modification.ValueSource;
+import org.apache.polygene.library.sql.generator.grammar.query.AsteriskSelect;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferenceByExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferenceByName;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferences;
+import org.apache.polygene.library.sql.generator.grammar.query.CorrespondingSpec;
+import org.apache.polygene.library.sql.generator.grammar.query.FromClause;
+import org.apache.polygene.library.sql.generator.grammar.query.GroupByClause;
+import org.apache.polygene.library.sql.generator.grammar.query.GroupingElement.GrandTotal;
+import org.apache.polygene.library.sql.generator.grammar.query.LimitSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.OffsetSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.OrderByClause;
+import org.apache.polygene.library.sql.generator.grammar.query.OrdinaryGroupingSet;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBody.EmptyQueryExpressionBody;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBodyBinary;
+import org.apache.polygene.library.sql.generator.grammar.query.QuerySpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.RowDefinition;
+import org.apache.polygene.library.sql.generator.grammar.query.RowSubQuery;
+import org.apache.polygene.library.sql.generator.grammar.query.SortSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferenceByExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferenceByName;
+import org.apache.polygene.library.sql.generator.grammar.query.TableValueConstructor;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.CrossJoinedTable;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinCondition;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.NamedColumnsJoin;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.NaturalJoinedTable;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.QualifiedJoinedTable;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.UnionJoinedTable;
+import org.apache.polygene.library.sql.generator.implementation.transformation.BooleanExpressionProcessing.BinaryPredicateProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.BooleanExpressionProcessing.BooleanTestProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.BooleanExpressionProcessing.ConjunctionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.BooleanExpressionProcessing.DisjunctionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.BooleanExpressionProcessing.MultiPredicateProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.BooleanExpressionProcessing.NegationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.BooleanExpressionProcessing.UnaryPredicateProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.BooleanExpressionProcessing.UnaryPredicateProcessor.UnaryOperatorOrientation;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ColumnProcessing.ColumnNamesProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ColumnProcessing.ColumnReferenceByExpressionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ColumnProcessing.ColumnReferenceByNameProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DataTypeProcessing.DecimalProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DataTypeProcessing.NumericProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DataTypeProcessing.SQLCharProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DataTypeProcessing.SQLFloatProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DataTypeProcessing.SQLIntervalProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DataTypeProcessing.SQLTimeProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DataTypeProcessing.SQLTimeStampProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DataTypeProcessing.UserDefinedDataTypeProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.CheckConstraintProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.ColumnDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.ForeignKeyConstraintProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.LikeClauseProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.RegularViewSpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.SchemaDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.TableConstraintDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.TableDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.TableElementListProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.UniqueConstraintProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.ViewDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.LiteralExpressionProcessing.DateTimeLiteralProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.LiteralExpressionProcessing.DirectLiteralProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.LiteralExpressionProcessing.NumericLiteralProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.LiteralExpressionProcessing.SQLFunctionLiteralProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.LiteralExpressionProcessing.StringLiteralExpressionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ManipulationProcessing.AddColumnDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ManipulationProcessing.AddTableConstraintDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ManipulationProcessing.AlterColumnDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ManipulationProcessing.AlterTableStatementProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ManipulationProcessing.DropColumnDefaultProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ManipulationProcessing.DropColumnDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ManipulationProcessing.DropSchemaStatementProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ManipulationProcessing.DropTableConstraintDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ManipulationProcessing.DropTableOrViewStatementProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ManipulationProcessing.SetColumnDefaultProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ModificationProcessing.ColumnSourceByQueryProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ModificationProcessing.ColumnSourceByValuesProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ModificationProcessing.DeleteBySearchProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ModificationProcessing.InsertStatementProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ModificationProcessing.SetClauseProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ModificationProcessing.TargetTableProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ModificationProcessing.UpdateBySearchProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ModificationProcessing.UpdateSourceByExpressionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.CorrespondingSpecProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.FromProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.GroupByProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.LimitSpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.OffsetSpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.OrderByProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.OrdinaryGroupingSetProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.QueryExpressionBinaryProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.QueryExpressionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.QuerySpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.RowDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.RowSubQueryProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.SelectColumnsProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.SortSpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.TableValueConstructorProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.TableReferenceProcessing.CrossJoinedTableProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.TableReferenceProcessing.JoinConditionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.TableReferenceProcessing.NamedColumnsJoinProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.TableReferenceProcessing.NaturalJoinedTableProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.TableReferenceProcessing.QualifiedJoinedTableProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.TableReferenceProcessing.TableNameDirectProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.TableReferenceProcessing.TableNameFunctionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.TableReferenceProcessing.TableReferenceByExpressionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.TableReferenceProcessing.TableReferenceByNameProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.TableReferenceProcessing.UnionJoinedTableProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.UnsupportedElementException;
+
+/**
+ * This is base class for processing the SQL syntax elements defined in API. It contains the default
+ * processors for nearly all default syntax elements, and a way to easily extend this class in order
+ * to add custom processors, or replace default processors with custom ones.
+ *
+ * @author Stanislav Muhametsin
+ */
+public class DefaultSQLProcessor
+    implements SQLProcessorAggregator
+{
+
+    private static final Map<Class<? extends Typeable<?>>, SQLProcessor> _defaultProcessors;
+
+    private static final Map<Class<? extends UnaryPredicate>, UnaryOperatorOrientation> _defaultUnaryOrientations;
+
+    private static final Map<Class<? extends UnaryPredicate>, String> _defaultUnaryOperators;
+
+    private static final Map<Class<? extends BinaryPredicate>, String> _defaultBinaryOperators;
+
+    private static final Map<Class<? extends MultiPredicate>, String> _defaultMultiOperators;
+
+    private static final Map<Class<? extends MultiPredicate>, String> _defaultMultiSeparators;
+
+    private static final Map<Class<? extends MultiPredicate>, Boolean> _defaultParenthesisPolicies;
+
+    static
+    {
+        Map<Class<? extends UnaryPredicate>, UnaryOperatorOrientation> unaryOrientations =
+            new HashMap<Class<? extends UnaryPredicate>, UnaryOperatorOrientation>();
+        unaryOrientations.put( IsNullPredicate.class, UnaryOperatorOrientation.AFTER_EXPRESSION );
+        unaryOrientations.put( IsNotNullPredicate.class, UnaryOperatorOrientation.AFTER_EXPRESSION );
+        unaryOrientations.put( ExistsPredicate.class, UnaryOperatorOrientation.BEFORE_EXPRESSION );
+        unaryOrientations.put( UniquePredicate.class, UnaryOperatorOrientation.BEFORE_EXPRESSION );
+        _defaultUnaryOrientations = Collections.unmodifiableMap( unaryOrientations );
+
+        Map<Class<? extends UnaryPredicate>, String> unaryOperators =
+            new HashMap<Class<? extends UnaryPredicate>, String>();
+        unaryOperators.put( IsNullPredicate.class, "IS NULL" );
+        unaryOperators.put( IsNotNullPredicate.class, "IS NOT NULL" );
+        unaryOperators.put( ExistsPredicate.class, "EXISTS" );
+        unaryOperators.put( UniquePredicate.class, "UNIQUE" );
+        _defaultUnaryOperators = Collections.unmodifiableMap( unaryOperators );
+
+        Map<Class<? extends BinaryPredicate>, String> binaryOperators =
+            new HashMap<Class<? extends BinaryPredicate>, String>();
+        binaryOperators.put( EqualsPredicate.class, "=" );
+        binaryOperators.put( NotEqualsPredicate.class, "<>" );
+        binaryOperators.put( GreaterOrEqualPredicate.class, ">=" );
+        binaryOperators.put( GreaterThanPredicate.class, ">" );
+        binaryOperators.put( LessOrEqualPredicate.class, "<=" );
+        binaryOperators.put( LessThanPredicate.class, "<" );
+        binaryOperators.put( LikePredicate.class, "LIKE" );
+        binaryOperators.put( NotLikePredicate.class, "NOT LIKE" );
+        _defaultBinaryOperators = Collections.unmodifiableMap( binaryOperators );
+
+        Map<Class<? extends MultiPredicate>, String> multiOperators =
+            new HashMap<Class<? extends MultiPredicate>, String>();
+        multiOperators.put( BetweenPredicate.class, "BETWEEN" );
+        multiOperators.put( InPredicate.class, "IN" );
+        multiOperators.put( NotBetweenPredicate.class, "NOT BETWEEN" );
+        multiOperators.put( NotInPredicate.class, "NOT IN" );
+        _defaultMultiOperators = Collections.unmodifiableMap( multiOperators );
+
+        Map<Class<? extends MultiPredicate>, String> multiSeparators =
+            new HashMap<Class<? extends MultiPredicate>, String>();
+        multiSeparators.put( BetweenPredicate.class, " AND " );
+        multiSeparators.put( InPredicate.class, ", " );
+        multiSeparators.put( NotBetweenPredicate.class, " AND " );
+        multiSeparators.put( NotInPredicate.class, ", " );
+        _defaultMultiSeparators = Collections.unmodifiableMap( multiSeparators );
+
+        Map<Class<? extends MultiPredicate>, Boolean> parenthesisPolicies =
+            new HashMap<Class<? extends MultiPredicate>, Boolean>();
+        parenthesisPolicies.put( BetweenPredicate.class, false );
+        parenthesisPolicies.put( InPredicate.class, true );
+        parenthesisPolicies.put( NotBetweenPredicate.class, false );
+        parenthesisPolicies.put( NotInPredicate.class, true );
+        _defaultParenthesisPolicies = parenthesisPolicies;
+
+        Map<Class<? extends Typeable<?>>, SQLProcessor> processors =
+            new HashMap<Class<? extends Typeable<?>>, SQLProcessor>();
+
+        // Boolean expressions
+        // Constants
+        processors.put( True.class, new ConstantProcessor( "TRUE" ) );
+        processors.put( False.class, new ConstantProcessor( "FALSE" ) );
+        // Unary
+        processors.put(
+            IsNullPredicate.class,
+            new UnaryPredicateProcessor( _defaultUnaryOrientations.get( IsNullPredicate.class ),
+                                         _defaultUnaryOperators
+                                             .get( IsNullPredicate.class ) ) );
+        processors.put( IsNotNullPredicate.class,
+                        new UnaryPredicateProcessor( _defaultUnaryOrientations.get( IsNotNullPredicate.class ),
+                                                     _defaultUnaryOperators.get( IsNotNullPredicate.class ) ) );
+        processors.put(
+            ExistsPredicate.class,
+            new UnaryPredicateProcessor( _defaultUnaryOrientations.get( ExistsPredicate.class ),
+                                         _defaultUnaryOperators
+                                             .get( ExistsPredicate.class ) ) );
+        processors.put(
+            UniquePredicate.class,
+            new UnaryPredicateProcessor( _defaultUnaryOrientations.get( UniquePredicate.class ),
+                                         _defaultUnaryOperators
+                                             .get( UniquePredicate.class ) ) );
+        // Binary
+        processors.put( EqualsPredicate.class,
+                        new BinaryPredicateProcessor( _defaultBinaryOperators.get( EqualsPredicate.class ) ) );
+        processors
+            .put(
+                NotEqualsPredicate.class,
+                new BinaryPredicateProcessor( _defaultBinaryOperators
+                                                  .get( NotEqualsPredicate.class ) ) );
+        processors.put(
+            GreaterOrEqualPredicate.class,
+            new BinaryPredicateProcessor( _defaultBinaryOperators
+                                              .get( GreaterOrEqualPredicate.class ) ) );
+        processors
+            .put(
+                GreaterThanPredicate.class,
+                new BinaryPredicateProcessor( _defaultBinaryOperators
+                                                  .get( GreaterThanPredicate.class ) ) );
+        processors
+            .put(
+                LessOrEqualPredicate.class,
+                new BinaryPredicateProcessor( _defaultBinaryOperators
+                                                  .get( LessOrEqualPredicate.class ) ) );
+        processors.put( LessThanPredicate.class,
+                        new BinaryPredicateProcessor( _defaultBinaryOperators.get( LessThanPredicate.class ) ) );
+        processors.put( LikePredicate.class,
+                        new BinaryPredicateProcessor( _defaultBinaryOperators.get( LikePredicate.class ) ) );
+        processors.put( NotLikePredicate.class,
+                        new BinaryPredicateProcessor( _defaultBinaryOperators.get( NotLikePredicate.class ) ) );
+        // Multi
+        processors.put(
+            BetweenPredicate.class,
+            new MultiPredicateProcessor( _defaultMultiOperators.get( BetweenPredicate.class ),
+                                         _defaultMultiSeparators
+                                             .get( BetweenPredicate.class ), _defaultParenthesisPolicies
+                                             .get( BetweenPredicate.class ) ) );
+        processors.put(
+            InPredicate.class,
+            new MultiPredicateProcessor(
+                _defaultMultiOperators.get( InPredicate.class ), _defaultMultiSeparators
+                .get( InPredicate.class ),
+                _defaultParenthesisPolicies.get( InPredicate.class ) ) );
+        processors.put(
+            NotBetweenPredicate.class,
+            new MultiPredicateProcessor( _defaultMultiOperators.get( NotBetweenPredicate.class ),
+                                         _defaultMultiSeparators.get( NotBetweenPredicate.class ),
+                                         _defaultParenthesisPolicies
+                                             .get( NotBetweenPredicate.class ) ) );
+        processors.put(
+            NotInPredicate.class,
+            new MultiPredicateProcessor( _defaultMultiOperators.get( NotInPredicate.class ),
+                                         _defaultMultiSeparators
+                                             .get( NotInPredicate.class ), _defaultParenthesisPolicies
+                                             .get( NotInPredicate.class ) ) );
+        // Composed
+        processors.put( Conjunction.class, new ConjunctionProcessor() );
+        processors.put( Disjunction.class, new DisjunctionProcessor() );
+        processors.put( Negation.class, new NegationProcessor() );
+        processors.put( BooleanTest.class, new BooleanTestProcessor() );
+        // Empty
+        processors.put( EmptyPredicate.class, new NoOpProcessor() );
+
+        // Column references
+        processors.put( ColumnReferenceByName.class, new ColumnReferenceByNameProcessor() );
+        processors.put( ColumnReferenceByExpression.class,
+                        new ColumnReferenceByExpressionProcessor() );
+        processors.put( ColumnNameList.class, new ColumnNamesProcessor() );
+
+        // Literals
+        processors.put( StringLiteral.class, new StringLiteralExpressionProcessor() );
+        processors.put( TimestampTimeLiteral.class, new DateTimeLiteralProcessor() );
+        processors.put( SQLFunctionLiteral.class, new SQLFunctionLiteralProcessor() );
+        processors.put( NumericLiteral.class, new NumericLiteralProcessor() );
+        processors.put( DirectLiteral.class, new DirectLiteralProcessor() );
+
+        // Queries
+        processors.put( QueryExpressionBodyBinary.class, new QueryExpressionBinaryProcessor() );
+        processors.put( QuerySpecification.class, new QuerySpecificationProcessor() );
+        processors.put( QueryExpression.class, new QueryExpressionProcessor() );
+        processors.put( EmptyQueryExpressionBody.class, new NoOpProcessor() );
+        processors.put( CorrespondingSpec.class, new CorrespondingSpecProcessor() );
+        processors.put( GrandTotal.class, new ConstantProcessor( SQLConstants.OPEN_PARENTHESIS
+                                                                 + SQLConstants.CLOSE_PARENTHESIS ) );
+        processors.put( OrdinaryGroupingSet.class, new OrdinaryGroupingSetProcessor() );
+        processors.put( SortSpecification.class, new SortSpecificationProcessor() );
+        processors.put( GroupByClause.class, new GroupByProcessor() );
+        processors.put( OrderByClause.class, new OrderByProcessor() );
+        processors.put( FromClause.class, new FromProcessor() );
+        SelectColumnsProcessor selectProcessor = new SelectColumnsProcessor();
+        processors.put( AsteriskSelect.class, selectProcessor );
+        processors.put( ColumnReferences.class, selectProcessor );
+        processors.put( TableValueConstructor.class, new TableValueConstructorProcessor() );
+        processors.put( RowDefinition.class, new RowDefinitionProcessor() );
+        processors.put( RowSubQuery.class, new RowSubQueryProcessor() );
+        processors.put( OffsetSpecification.class, new OffsetSpecificationProcessor() );
+        processors.put( LimitSpecification.class, new LimitSpecificationProcessor() );
+
+        // Table references
+        processors.put( TableNameDirect.class, new TableNameDirectProcessor() );
+        processors.put( TableNameFunction.class, new TableNameFunctionProcessor() );
+        processors.put( TableReferenceByName.class, new TableReferenceByNameProcessor() );
+        processors
+            .put( TableReferenceByExpression.class, new TableReferenceByExpressionProcessor() );
+        processors.put( CrossJoinedTable.class, new CrossJoinedTableProcessor() );
+        processors.put( NaturalJoinedTable.class, new NaturalJoinedTableProcessor() );
+        processors.put( QualifiedJoinedTable.class, new QualifiedJoinedTableProcessor() );
+        processors.put( UnionJoinedTable.class, new UnionJoinedTableProcessor() );
+        processors.put( JoinCondition.class, new JoinConditionProcessor() );
+        processors.put( NamedColumnsJoin.class, new NamedColumnsJoinProcessor() );
+
+        // Modification clauses
+        processors.put( ColumnSourceByQuery.class, new ColumnSourceByQueryProcessor() );
+        processors.put( ColumnSourceByValues.class, new ColumnSourceByValuesProcessor() );
+        processors.put( DeleteBySearch.class, new DeleteBySearchProcessor() );
+        processors.put( InsertStatement.class, new InsertStatementProcessor() );
+        processors.put( SetClause.class, new SetClauseProcessor() );
+        processors.put( TargetTable.class, new TargetTableProcessor() );
+        processors.put( UpdateBySearch.class, new UpdateBySearchProcessor() );
+        processors.put( UpdateSourceByExpression.class, new UpdateSourceByExpressionProcessor() );
+        processors.put( ValueSource.Null.class, new ConstantProcessor( "NULL" ) );
+        processors.put( ValueSource.Default.class, new ConstantProcessor( "DEFAULT" ) );
+        processors.put( Defaults.class, new ConstantProcessor( SQLConstants.TOKEN_SEPARATOR
+                                                               + "DEFAULT VALUES" ) );
+
+        // Data definition
+        // First data types
+        processors.put( BigInt.class, new ConstantProcessor( "BIGINT" ) );
+        processors.put( DoublePrecision.class, new ConstantProcessor( "DOUBLE PRECISION" ) );
+        processors.put( Real.class, new ConstantProcessor( "REAL" ) );
+        processors.put( SmallInt.class, new ConstantProcessor( "SMALLINT" ) );
+        processors.put( SQLBoolean.class, new ConstantProcessor( "BOOLEAN" ) );
+        processors.put( SQLDate.class, new ConstantProcessor( "DATE" ) );
+        processors.put( SQLInteger.class, new ConstantProcessor( "INTEGER" ) );
+        processors.put( UserDefinedType.class, new UserDefinedDataTypeProcessor() );
+        processors.put( Decimal.class, new DecimalProcessor() );
+        processors.put( Numeric.class, new NumericProcessor() );
+        processors.put( SQLChar.class, new SQLCharProcessor() );
+        processors.put( SQLFloat.class, new SQLFloatProcessor() );
+        processors.put( SQLInterval.class, new SQLIntervalProcessor() );
+        processors.put( SQLTime.class, new SQLTimeProcessor() );
+        processors.put( SQLTimeStamp.class, new SQLTimeStampProcessor() );
+        // Then statements and clauses
+        processors.put( SchemaDefinition.class, new SchemaDefinitionProcessor() );
+        processors.put( TableDefinition.class, new TableDefinitionProcessor() );
+        processors.put( TableElementList.class, new TableElementListProcessor() );
+        processors.put( ColumnDefinition.class, new ColumnDefinitionProcessor() );
+        processors.put( LikeClause.class, new LikeClauseProcessor() );
+        processors.put( TableConstraintDefinition.class, new TableConstraintDefinitionProcessor() );
+        processors.put( CheckConstraint.class, new CheckConstraintProcessor() );
+        processors.put( UniqueConstraint.class, new UniqueConstraintProcessor() );
+        processors.put( ForeignKeyConstraint.class, new ForeignKeyConstraintProcessor() );
+        processors.put( ViewDefinition.class, new ViewDefinitionProcessor() );
+        processors.put( RegularViewSpecification.class, new RegularViewSpecificationProcessor() );
+
+        // Data manipulation
+        processors.put( AlterTableStatement.class, new AlterTableStatementProcessor() );
+        processors.put( AddColumnDefinition.class, new AddColumnDefinitionProcessor() );
+        processors.put( AddTableConstraintDefinition.class,
+                        new AddTableConstraintDefinitionProcessor() );
+        processors.put( AlterColumnDefinition.class, new AlterColumnDefinitionProcessor() );
+        processors.put( DropDefault.class, new DropColumnDefaultProcessor() );
+        processors.put( SetColumnDefault.class, new SetColumnDefaultProcessor() );
+        processors.put( DropColumnDefinition.class, new DropColumnDefinitionProcessor() );
+        processors.put( DropTableConstraintDefinition.class,
+                        new DropTableConstraintDefinitionProcessor() );
+        processors.put( DropSchemaStatement.class, new DropSchemaStatementProcessor() );
+        processors.put( DropTableOrViewStatement.class, new DropTableOrViewStatementProcessor() );
+
+        _defaultProcessors = Collections.unmodifiableMap( processors );
+    }
+
+    private final Map<Class<? extends Typeable<?>>, SQLProcessor> _processors;
+    private final SQLVendor _vendor;
+
+    public DefaultSQLProcessor( SQLVendor vendor )
+    {
+        this( vendor, _defaultProcessors );
+    }
+
+    public DefaultSQLProcessor( SQLVendor vendor,
+                                Map<Class<? extends Typeable<?>>, SQLProcessor> processors )
+    {
+        Objects.requireNonNull( vendor, "Vendor" );
+        Objects.requireNonNull( processors, "Processors" );
+        this._vendor = vendor;
+        this._processors = new HashMap<>( processors );
+    }
+
+    public void process( Typeable<?> object, StringBuilder builder )
+    {
+        SQLProcessor processor = this._processors.get( object.getImplementedType() );
+        if( processor != null )
+        {
+            processor.process( this, object, builder );
+        }
+        else
+        {
+            throw new UnsupportedElementException( "The vendor " + this.getClass()
+                                                   + " does not know how to handle element of type " + object.getImplementedType()
+                                                   + ".", object );
+        }
+    }
+
+    public SQLVendor getVendor()
+    {
+        return this._vendor;
+    }
+
+    protected Map<Class<? extends Typeable<?>>, SQLProcessor> getProcessors()
+    {
+        return this._processors;
+    }
+
+    public static Map<Class<? extends Typeable<?>>, SQLProcessor> getDefaultProcessors()
+    {
+        return _defaultProcessors;
+    }
+
+    public static Map<Class<? extends BinaryPredicate>, String> getDefaultBinaryOperators()
+    {
+        return _defaultBinaryOperators;
+    }
+
+    public static Map<Class<? extends MultiPredicate>, String> getDefaultMultiOperators()
+    {
+        return _defaultMultiOperators;
+    }
+
+    public static Map<Class<? extends MultiPredicate>, String> getDefaultMultiSeparators()
+    {
+        return _defaultMultiSeparators;
+    }
+
+    public static Map<Class<? extends MultiPredicate>, Boolean> getDefaultParenthesisPolicies()
+    {
+        return _defaultParenthesisPolicies;
+    }
+
+    public static Map<Class<? extends UnaryPredicate>, String> getDefaultUnaryOperators()
+    {
+        return _defaultUnaryOperators;
+    }
+
+    public static Map<Class<? extends UnaryPredicate>, UnaryOperatorOrientation>
+    getDefaultUnaryOrientations()
+    {
+        return _defaultUnaryOrientations;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/DefinitionProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/DefinitionProcessing.java
new file mode 100644
index 0000000..f2a2f90
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/DefinitionProcessing.java
@@ -0,0 +1,516 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.definition.schema.SchemaDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.schema.SchemaElement;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.AutoGenerationPolicy;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.CheckConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ConstraintCharacteristics;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ForeignKeyConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.LikeClause;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.MatchType;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ReferentialAction;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableCommitAction;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableElement;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableElementList;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableScope;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.UniqueConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.UniqueSpecification;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.RegularViewSpecification;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.ViewCheckOption;
+import org.apache.polygene.library.sql.generator.grammar.definition.view.ViewDefinition;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DefinitionProcessing
+{
+
+    public static class SchemaDefinitionProcessor extends AbstractProcessor<SchemaDefinition>
+    {
+        public SchemaDefinitionProcessor()
+        {
+            super( SchemaDefinition.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, SchemaDefinition object, StringBuilder builder )
+        {
+            builder.append( SQLConstants.CREATE ).append( SQLConstants.TOKEN_SEPARATOR ).append( "SCHEMA " )
+                   .append( object.getSchemaName() );
+            String charset = object.getSchemaCharset();
+            if( charset != null )
+            {
+                builder.append( " DEFAULT CHARSET " ).append( object.getSchemaCharset() );
+            }
+
+            builder.append( SQLConstants.NEWLINE );
+        }
+
+        protected void processSchemaElements( SQLProcessorAggregator aggregator, SchemaDefinition object,
+                                              StringBuilder builder )
+        {
+            for( SchemaElement el : object.getSchemaElements() )
+            {
+                aggregator.process( el.asTypeable(), builder );
+                builder.append( SQLConstants.NEWLINE );
+            }
+        }
+    }
+
+    public static class TableDefinitionProcessor extends AbstractProcessor<TableDefinition>
+    {
+        private static final Map<TableScope, String> _defaultTableScopes;
+        private static final Map<TableCommitAction, String> _defaultCommitActions;
+
+        static
+        {
+            Map<TableScope, String> operations = new HashMap<TableScope, String>();
+            operations.put( TableScope.GLOBAL_TEMPORARY, "GLOBAL TEMPORARY" );
+            operations.put( TableScope.LOCAL_TEMPORARY, "LOCAL TEMPORARY" );
+            _defaultTableScopes = operations;
+
+            Map<TableCommitAction, String> commitActions = new HashMap<TableCommitAction, String>();
+            commitActions.put( TableCommitAction.ON_COMMIT_DELETE_ROWS, "DELETE ROWS" );
+            commitActions.put( TableCommitAction.ON_COMMIT_PRESERVE_ROWS, "PRESERVE ROWS" );
+            _defaultCommitActions = commitActions;
+        }
+
+        public static Map<TableCommitAction, String> getDefaultCommitActions()
+        {
+            return Collections.unmodifiableMap( _defaultCommitActions );
+        }
+
+        public static Map<TableScope, String> getDefaultTableScopes()
+        {
+            return Collections.unmodifiableMap( _defaultTableScopes );
+        }
+
+        private final Map<TableScope, String> _tableScopes;
+        private final Map<TableCommitAction, String> _commitActions;
+
+        public TableDefinitionProcessor()
+        {
+            this( _defaultTableScopes, _defaultCommitActions );
+        }
+
+        public TableDefinitionProcessor( Map<TableScope, String> tableScopes,
+                                         Map<TableCommitAction, String> commitActions )
+        {
+            super( TableDefinition.class );
+
+            this._tableScopes = tableScopes;
+            this._commitActions = commitActions;
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, TableDefinition object, StringBuilder builder )
+        {
+            builder.append( SQLConstants.CREATE );
+            if( object.getTableScope() != null )
+            {
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append( this._tableScopes.get( object.getTableScope() ) );
+            }
+
+            builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "TABLE" ).append( SQLConstants.TOKEN_SEPARATOR );
+            aggregator.process( object.getTableName(), builder );
+
+            builder.append( SQLConstants.NEWLINE );
+            aggregator.process( object.getContents(), builder );
+
+            builder.append( SQLConstants.NEWLINE );
+            if( object.getCommitAction() != null )
+            {
+                builder.append( "ON COMMIT" ).append( SQLConstants.TOKEN_SEPARATOR )
+                       .append( this._commitActions.get( object.getCommitAction() ) );
+            }
+        }
+    }
+
+    public static class TableElementListProcessor extends AbstractProcessor<TableElementList>
+    {
+
+        public TableElementListProcessor()
+        {
+            super( TableElementList.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, TableElementList object, StringBuilder builder )
+        {
+            Iterator<TableElement> iter = object.getElementList().iterator();
+            builder.append( SQLConstants.OPEN_PARENTHESIS ).append( SQLConstants.NEWLINE );
+            while( iter.hasNext() )
+            {
+                this.processTableElement( aggregator, iter.next(), builder, iter.hasNext() );
+                builder.append( SQLConstants.NEWLINE );
+            }
+            builder.append( SQLConstants.CLOSE_PARENTHESIS );
+        }
+
+        protected void processTableElement( SQLProcessorAggregator aggregator, TableElement object, StringBuilder builder, boolean hasNext )
+        {
+            aggregator.process( object, builder );
+            if( hasNext )
+            {
+                builder.append( SQLConstants.COMMA );
+            }
+        }
+    }
+
+    public static class ColumnDefinitionProcessor extends AbstractProcessor<ColumnDefinition>
+    {
+
+        public ColumnDefinitionProcessor()
+        {
+            super( ColumnDefinition.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, ColumnDefinition object, StringBuilder builder )
+        {
+            builder.append( object.getColumnName() ).append( SQLConstants.TOKEN_SEPARATOR );
+
+            this.processDataType( aggregator, object, builder );
+
+            if( object.getDefault() != null )
+            {
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "DEFAULT" )
+                       .append( SQLConstants.TOKEN_SEPARATOR ).append( object.getDefault() );
+            }
+
+            this.processMayBeNull( object, builder );
+
+            if( object.getAutoGenerationPolicy() != null )
+            {
+                this.processAutoGenerationPolicy( object, builder );
+            }
+        }
+
+        protected void processMayBeNull( ColumnDefinition object, StringBuilder builder )
+        {
+            if( !object.mayBeNull() )
+            {
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "NOT NULL" );
+            }
+        }
+
+        protected void processDataType( SQLProcessorAggregator aggregator, ColumnDefinition object,
+                                        StringBuilder builder )
+        {
+            aggregator.process( object.getDataType(), builder );
+        }
+
+        protected void processAutoGenerationPolicy( ColumnDefinition object, StringBuilder builder )
+        {
+            builder.append( " GENERATED " );
+            if( AutoGenerationPolicy.ALWAYS.equals( object.getAutoGenerationPolicy() ) )
+            {
+                builder.append( "ALWAYS " );
+            }
+            else if( AutoGenerationPolicy.BY_DEFAULT.equals( object.getAutoGenerationPolicy() ) )
+            {
+                builder.append( "BY DEFAULT " );
+            }
+            else
+            {
+                throw new UnsupportedOperationException( "Unknown auto generation policy: "
+                                                         + object.getAutoGenerationPolicy() + "." );
+            }
+            builder.append( "AS IDENTITY" );
+        }
+    }
+
+    public static class LikeClauseProcessor extends AbstractProcessor<LikeClause>
+    {
+
+        public LikeClauseProcessor()
+        {
+            super( LikeClause.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, LikeClause object, StringBuilder builder )
+        {
+            builder.append( "LIKE" ).append( SQLConstants.TOKEN_SEPARATOR );
+            aggregator.process( object.getTableName(), builder );
+        }
+    }
+
+    public static class TableConstraintDefinitionProcessor extends AbstractProcessor<TableConstraintDefinition>
+    {
+
+        private static final Map<ConstraintCharacteristics, String> _defaultCharacteristics;
+
+        static
+        {
+            Map<ConstraintCharacteristics, String> operations = new HashMap<ConstraintCharacteristics, String>();
+            operations.put( ConstraintCharacteristics.INITIALLY_DEFERRED_DEFERRABLE, "INITIALLY DEFERRED DEFERRABLE" );
+            operations.put( ConstraintCharacteristics.INITIALLY_IMMEDIATE_DEFERRABLE, "INITIALLY IMMEDIATE DEFERRABLE" );
+            operations.put( ConstraintCharacteristics.NOT_DEFERRABLE, "NOT DEFERRABLE" );
+            _defaultCharacteristics = operations;
+        }
+
+        private final Map<ConstraintCharacteristics, String> _characteristics;
+
+        public TableConstraintDefinitionProcessor()
+        {
+            this( _defaultCharacteristics );
+        }
+
+        public TableConstraintDefinitionProcessor( Map<ConstraintCharacteristics, String> characteristics )
+        {
+            super( TableConstraintDefinition.class );
+
+            this._characteristics = characteristics;
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, TableConstraintDefinition object,
+                                  StringBuilder builder )
+        {
+            if( object.getConstraintName() != null )
+            {
+                builder.append( "CONSTRAINT" ).append( SQLConstants.TOKEN_SEPARATOR )
+                       .append( object.getConstraintName() ).append( SQLConstants.TOKEN_SEPARATOR );
+            }
+
+            aggregator.process( object.getConstraint(), builder );
+
+            if( object.getCharacteristics() != null )
+            {
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append(
+                    this._characteristics.get( object.getCharacteristics() ) );
+            }
+        }
+    }
+
+    public static class CheckConstraintProcessor extends AbstractProcessor<CheckConstraint>
+    {
+
+        public CheckConstraintProcessor()
+        {
+            super( CheckConstraint.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, CheckConstraint object, StringBuilder builder )
+        {
+            builder.append( "CHECK" ).append( SQLConstants.TOKEN_SEPARATOR ).append( SQLConstants.OPEN_PARENTHESIS );
+            aggregator.process( object.getCheckCondition(), builder );
+            builder.append( SQLConstants.CLOSE_PARENTHESIS );
+        }
+    }
+
+    public static class UniqueConstraintProcessor extends AbstractProcessor<UniqueConstraint>
+    {
+
+        private static final Map<UniqueSpecification, String> _defaultUniqueSpecs;
+
+        static
+        {
+            Map<UniqueSpecification, String> map = new HashMap<UniqueSpecification, String>();
+            map.put( UniqueSpecification.PRIMARY_KEY, "PRIMARY KEY" );
+            map.put( UniqueSpecification.UNIQUE, "UNIQUE" );
+            _defaultUniqueSpecs = map;
+        }
+
+        private final Map<UniqueSpecification, String> _uniqueSpecs;
+
+        public UniqueConstraintProcessor()
+        {
+            this( _defaultUniqueSpecs );
+        }
+
+        public UniqueConstraintProcessor( Map<UniqueSpecification, String> uniqueSpecs )
+        {
+            super( UniqueConstraint.class );
+
+            this._uniqueSpecs = uniqueSpecs;
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, UniqueConstraint object, StringBuilder builder )
+        {
+            this.processUniqueness( aggregator, object, builder );
+        }
+
+        protected void processUniqueness( SQLProcessorAggregator aggregator, UniqueConstraint object, StringBuilder builder )
+        {
+            builder.append( this._uniqueSpecs.get( object.getUniquenessKind() ) );
+            aggregator.process( object.getColumnNameList(), builder );
+        }
+    }
+
+    public static class ForeignKeyConstraintProcessor extends AbstractProcessor<ForeignKeyConstraint>
+    {
+        private static final Map<ReferentialAction, String> _defaultReferentialActions;
+
+        private static final Map<MatchType, String> _defaultMatchTypes;
+
+        static
+        {
+            Map<ReferentialAction, String> map = new HashMap<ReferentialAction, String>();
+            map.put( ReferentialAction.CASCADE, "CASCADE" );
+            map.put( ReferentialAction.NO_ACTION, "NO ACTION" );
+            map.put( ReferentialAction.RESTRICT, "RESTRICT" );
+            map.put( ReferentialAction.SET_DEFAULT, "SET DEFAULT" );
+            map.put( ReferentialAction.SET_NULL, "SET NULL" );
+            _defaultReferentialActions = map;
+
+            Map<MatchType, String> mt = new HashMap<MatchType, String>();
+            mt.put( MatchType.FULL, "FULL" );
+            mt.put( MatchType.PARTIAL, "PARTIAL" );
+            mt.put( MatchType.SIMPLE, "SIMPLE" );
+            _defaultMatchTypes = mt;
+        }
+
+        private final Map<ReferentialAction, String> _referentialActions;
+
+        private final Map<MatchType, String> _matchTypes;
+
+        public ForeignKeyConstraintProcessor()
+        {
+            this( _defaultReferentialActions, _defaultMatchTypes );
+        }
+
+        public ForeignKeyConstraintProcessor( Map<ReferentialAction, String> uniqueSpecs,
+                                              Map<MatchType, String> matchTypes )
+        {
+            super( ForeignKeyConstraint.class );
+
+            this._referentialActions = uniqueSpecs;
+            this._matchTypes = matchTypes;
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, ForeignKeyConstraint object, StringBuilder builder )
+        {
+            builder.append( "FOREIGN KEY" );
+            aggregator.process( object.getSourceColumns(), builder );
+            builder.append( SQLConstants.NEWLINE ).append( "REFERENCES" ).append( SQLConstants.TOKEN_SEPARATOR );
+            aggregator.process( object.getTargetTableName(), builder );
+            if( object.getTargetColumns() != null )
+            {
+                aggregator.process( object.getTargetColumns(), builder );
+            }
+
+            if( object.getMatchType() != null )
+            {
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "MATCH" ).append( SQLConstants.TOKEN_SEPARATOR )
+                       .append( this._matchTypes.get( object.getMatchType() ) );
+            }
+            builder.append( SQLConstants.NEWLINE );
+
+            this.handleReferentialAction( "ON UPDATE", object.getOnUpdate(), builder );
+            builder.append( SQLConstants.TOKEN_SEPARATOR );
+            this.handleReferentialAction( "ON DELETE", object.getOnDelete(), builder );
+        }
+
+        protected void handleReferentialAction( String prefix, ReferentialAction action, StringBuilder builder )
+        {
+            if( action != null )
+            {
+                builder.append( prefix ).append( SQLConstants.TOKEN_SEPARATOR )
+                       .append( this._referentialActions.get( action ) );
+            }
+        }
+    }
+
+    public static class ViewDefinitionProcessor extends AbstractProcessor<ViewDefinition>
+    {
+
+        private static final Map<ViewCheckOption, String> _defaultViewCheckOptions;
+
+        static
+        {
+            Map<ViewCheckOption, String> map = new HashMap<ViewCheckOption, String>();
+            map.put( ViewCheckOption.CASCADED, "CASCADED" );
+            map.put( ViewCheckOption.LOCAL, "LOCAL" );
+            _defaultViewCheckOptions = map;
+        }
+
+        private final Map<ViewCheckOption, String> _viewCheckOptions;
+
+        public ViewDefinitionProcessor()
+        {
+            this( _defaultViewCheckOptions );
+        }
+
+        public ViewDefinitionProcessor( Map<ViewCheckOption, String> viewCheckOptions )
+        {
+            super( ViewDefinition.class );
+
+            this._viewCheckOptions = viewCheckOptions;
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, ViewDefinition object, StringBuilder builder )
+        {
+            builder.append( SQLConstants.CREATE ).append( SQLConstants.TOKEN_SEPARATOR );
+            if( object.isRecursive() )
+            {
+                builder.append( "RECURSIVE" ).append( SQLConstants.TOKEN_SEPARATOR );
+            }
+            builder.append( "VIEW" ).append( SQLConstants.TOKEN_SEPARATOR );
+
+            aggregator.process( object.getViewName(), builder );
+            aggregator.process( object.getViewSpecification(), builder );
+            builder.append( "AS" ).append( SQLConstants.NEWLINE );
+            aggregator.process( object.getViewQuery(), builder );
+
+            if( object.getViewCheckOption() != null )
+            {
+                builder.append( SQLConstants.NEWLINE ).append( "WITH" ).append( SQLConstants.TOKEN_SEPARATOR )
+                       .append( this._viewCheckOptions.get( object.getViewCheckOption() ) )
+                       .append( SQLConstants.TOKEN_SEPARATOR ).append( "CHECK OPTION" );
+            }
+        }
+    }
+
+    public static class RegularViewSpecificationProcessor extends AbstractProcessor<RegularViewSpecification>
+    {
+
+        public RegularViewSpecificationProcessor()
+        {
+            super( RegularViewSpecification.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, RegularViewSpecification object,
+                                  StringBuilder builder )
+        {
+            if( object.getColumns() != null )
+            {
+                aggregator.process( object.getColumns(), builder );
+            }
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/LiteralExpressionProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/LiteralExpressionProcessing.java
new file mode 100644
index 0000000..4dbc52d
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/LiteralExpressionProcessing.java
@@ -0,0 +1,128 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Iterator;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.literals.DirectLiteral;
+import org.apache.polygene.library.sql.generator.grammar.literals.NumericLiteral;
+import org.apache.polygene.library.sql.generator.grammar.literals.SQLFunctionLiteral;
+import org.apache.polygene.library.sql.generator.grammar.literals.StringLiteral;
+import org.apache.polygene.library.sql.generator.grammar.literals.TimestampTimeLiteral;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * Currently not thread-safe.
+ *
+ * @author Stanislav Muhametsin
+ */
+public class LiteralExpressionProcessing
+{
+
+    public static class StringLiteralExpressionProcessor extends AbstractProcessor<StringLiteral>
+    {
+        public StringLiteralExpressionProcessor()
+        {
+            super( StringLiteral.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, StringLiteral literal, StringBuilder builder )
+        {
+            String string = literal.getString();
+            builder.append( string == null ? SQLConstants.NULL : "'" + string + "'" );
+        }
+    }
+
+    public static class DirectLiteralProcessor extends AbstractProcessor<DirectLiteral>
+    {
+        public DirectLiteralProcessor()
+        {
+            super( DirectLiteral.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, DirectLiteral literal, StringBuilder builder )
+        {
+            String string = literal.getDirectLiteral();
+            builder.append( string == null ? SQLConstants.NULL : string );
+        }
+    }
+
+    public static class DateTimeLiteralProcessor extends AbstractProcessor<TimestampTimeLiteral>
+    {
+        private final DateFormat _format;
+
+        public DateTimeLiteralProcessor()
+        {
+            super( TimestampTimeLiteral.class );
+            this._format = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss.SSS" );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, TimestampTimeLiteral object, StringBuilder builder )
+        {
+            builder.append( "'" + this._format.format( object.getTimestamp() ) + "'" );
+        }
+    }
+
+    public static class SQLFunctionLiteralProcessor extends AbstractProcessor<SQLFunctionLiteral>
+    {
+        public SQLFunctionLiteralProcessor()
+        {
+            super( SQLFunctionLiteral.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, SQLFunctionLiteral object, StringBuilder builder )
+        {
+            builder.append( object.getFunctionName() ).append( SQLConstants.OPEN_PARENTHESIS );
+            Iterator<ValueExpression> iter = object.getParameters().iterator();
+            while( iter.hasNext() )
+            {
+                processor.process( iter.next(), builder );
+                if( iter.hasNext() )
+                {
+                    builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                }
+            }
+            builder.append( SQLConstants.CLOSE_PARENTHESIS );
+        }
+    }
+
+    public static class NumericLiteralProcessor extends AbstractProcessor<NumericLiteral>
+    {
+
+        public NumericLiteralProcessor()
+        {
+            super( NumericLiteral.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, NumericLiteral object, StringBuilder builder )
+        {
+            Number numba = object.getNumber();
+            builder.append( numba == null ? SQLConstants.NULL : numba.toString() );
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ManipulationProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ManipulationProcessing.java
new file mode 100644
index 0000000..853ba67
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ManipulationProcessing.java
@@ -0,0 +1,230 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AddColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AddTableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterColumnAction.DropDefault;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.AlterTableStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropSchemaStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropTableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropTableOrViewStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.ObjectType;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.SetColumnDefault;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ManipulationProcessing
+{
+
+    public static class AlterTableStatementProcessor extends AbstractProcessor<AlterTableStatement>
+    {
+        public AlterTableStatementProcessor()
+        {
+            super( AlterTableStatement.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, AlterTableStatement object, StringBuilder builder )
+        {
+            builder.append( "ALTER TABLE" ).append( SQLConstants.TOKEN_SEPARATOR );
+            aggregator.process( object.getTableName(), builder );
+            builder.append( SQLConstants.NEWLINE );
+            aggregator.process( object.getAction(), builder );
+        }
+    }
+
+    public static class AddColumnDefinitionProcessor extends AbstractProcessor<AddColumnDefinition>
+    {
+
+        public AddColumnDefinitionProcessor()
+        {
+            super( AddColumnDefinition.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, AddColumnDefinition object, StringBuilder builder )
+        {
+            builder.append( "ADD COLUMN" ).append( SQLConstants.TOKEN_SEPARATOR );
+            aggregator.process( object.getColumnDefinition(), builder );
+        }
+    }
+
+    public static class AddTableConstraintDefinitionProcessor extends AbstractProcessor<AddTableConstraintDefinition>
+    {
+
+        public AddTableConstraintDefinitionProcessor()
+        {
+            super( AddTableConstraintDefinition.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, AddTableConstraintDefinition object,
+                                  StringBuilder builder )
+        {
+            builder.append( "ADD" ).append( SQLConstants.TOKEN_SEPARATOR );
+            aggregator.process( object.getConstraint(), builder );
+        }
+    }
+
+    public static class AlterColumnDefinitionProcessor extends AbstractProcessor<AlterColumnDefinition>
+    {
+        public AlterColumnDefinitionProcessor()
+        {
+            super( AlterColumnDefinition.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, AlterColumnDefinition object, StringBuilder builder )
+        {
+            builder.append( "ALTER COLUMN" ).append( SQLConstants.TOKEN_SEPARATOR ).append( object.getColumnName() )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+            aggregator.process( object.getAction(), builder );
+        }
+    }
+
+    public static class DropColumnDefaultProcessor extends AbstractProcessor<DropDefault>
+    {
+        public DropColumnDefaultProcessor()
+        {
+            super( DropDefault.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, DropDefault object, StringBuilder builder )
+        {
+            builder.append( "DROP DEFAULT" );
+        }
+    }
+
+    public static class SetColumnDefaultProcessor extends AbstractProcessor<SetColumnDefault>
+    {
+        public SetColumnDefaultProcessor()
+        {
+            super( SetColumnDefault.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, SetColumnDefault object, StringBuilder builder )
+        {
+            builder.append( "SET" ).append( SQLConstants.TOKEN_SEPARATOR );
+            builder.append( object.getDefault() );
+        }
+    }
+
+    public static class DropColumnDefinitionProcessor extends AbstractProcessor<DropColumnDefinition>
+    {
+        public DropColumnDefinitionProcessor()
+        {
+            super( DropColumnDefinition.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, DropColumnDefinition object, StringBuilder builder )
+        {
+            builder.append( "DROP COLUMN" ).append( SQLConstants.TOKEN_SEPARATOR ).append( object.getColumnName() );
+            ProcessorUtils.processDropBehaviour( object.getDropBehaviour(), builder );
+        }
+    }
+
+    public static class DropTableConstraintDefinitionProcessor extends AbstractProcessor<DropTableConstraintDefinition>
+    {
+        public DropTableConstraintDefinitionProcessor()
+        {
+            super( DropTableConstraintDefinition.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, DropTableConstraintDefinition object,
+                                  StringBuilder builder )
+        {
+            builder.append( "DROP CONSTRAINT" ).append( SQLConstants.TOKEN_SEPARATOR )
+                   .append( object.getConstraintName() );
+            ProcessorUtils.processDropBehaviour( object.getDropBehaviour(), builder );
+        }
+    }
+
+    public static class DropSchemaStatementProcessor extends AbstractProcessor<DropSchemaStatement>
+    {
+        public DropSchemaStatementProcessor()
+        {
+            super( DropSchemaStatement.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, DropSchemaStatement object, StringBuilder builder )
+        {
+            builder.append( "DROP SCHEMA" ).append( SQLConstants.TOKEN_SEPARATOR ).append( object.getSchemaName() );
+            ProcessorUtils.processDropBehaviour( object.getDropBehaviour(), builder );
+        }
+    }
+
+    public static class DropTableOrViewStatementProcessor extends AbstractProcessor<DropTableOrViewStatement>
+    {
+        private static final Map<ObjectType, String> _defaultObjectTypes;
+
+        static
+        {
+            Map<ObjectType, String> map = new HashMap<ObjectType, String>();
+            map.put( ObjectType.TABLE, "TABLE" );
+            map.put( ObjectType.VIEW, "VIEW" );
+
+            _defaultObjectTypes = map;
+        }
+
+        private final Map<ObjectType, String> _objectTypes;
+
+        public DropTableOrViewStatementProcessor()
+        {
+            this( _defaultObjectTypes );
+        }
+
+        public DropTableOrViewStatementProcessor( Map<ObjectType, String> objectTypes )
+        {
+            super( DropTableOrViewStatement.class );
+
+            this._objectTypes = objectTypes;
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, DropTableOrViewStatement object,
+                                  StringBuilder builder )
+        {
+            builder.append( "DROP" ).append( SQLConstants.TOKEN_SEPARATOR )
+                   .append( this._objectTypes.get( object.whatToDrop() ) ).append( SQLConstants.TOKEN_SEPARATOR );
+
+            aggregator.process( object.getTableName(), builder );
+
+            ProcessorUtils.processDropBehaviour( object.getDropBehaviour(), builder );
+        }
+
+        protected Map<ObjectType, String> getObjectTypes()
+        {
+            return this._objectTypes;
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ModificationProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ModificationProcessing.java
new file mode 100644
index 0000000..835ada1
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ModificationProcessing.java
@@ -0,0 +1,291 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation;
+
+import java.util.Iterator;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSourceByQuery;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSourceByValues;
+import org.apache.polygene.library.sql.generator.grammar.modification.DeleteBySearch;
+import org.apache.polygene.library.sql.generator.grammar.modification.DynamicColumnSource;
+import org.apache.polygene.library.sql.generator.grammar.modification.InsertStatement;
+import org.apache.polygene.library.sql.generator.grammar.modification.SetClause;
+import org.apache.polygene.library.sql.generator.grammar.modification.TargetTable;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateBySearch;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateSourceByExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ModificationProcessing
+{
+
+    public static abstract class DynamicColumnSourceProcessor<SourceType extends DynamicColumnSource>
+        extends
+        AbstractProcessor<SourceType>
+    {
+        public DynamicColumnSourceProcessor( Class<? extends SourceType> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, SourceType object,
+                                  StringBuilder builder )
+        {
+            if( object.getColumnNames() != null )
+            {
+                processor.process( object.getColumnNames(), builder );
+            }
+            this.doProcessColumnSource( processor, object, builder );
+        }
+
+        protected abstract void doProcessColumnSource( SQLProcessorAggregator processor,
+                                                       SourceType object,
+                                                       StringBuilder builder );
+    }
+
+    public static class ColumnSourceByQueryProcessor extends
+                                                     DynamicColumnSourceProcessor<ColumnSourceByQuery>
+    {
+
+        public ColumnSourceByQueryProcessor()
+        {
+            this( ColumnSourceByQuery.class );
+        }
+
+        protected ColumnSourceByQueryProcessor( Class<? extends ColumnSourceByQuery> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcessColumnSource( SQLProcessorAggregator processor,
+                                              ColumnSourceByQuery object,
+                                              StringBuilder builder )
+        {
+            builder.append( SQLConstants.NEWLINE );
+            processor.process( object.getQuery(), builder );
+        }
+    }
+
+    public static class ColumnSourceByValuesProcessor extends
+                                                      DynamicColumnSourceProcessor<ColumnSourceByValues>
+    {
+
+        public ColumnSourceByValuesProcessor()
+        {
+            this( ColumnSourceByValues.class );
+        }
+
+        public ColumnSourceByValuesProcessor( Class<? extends ColumnSourceByValues> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcessColumnSource( SQLProcessorAggregator processor,
+                                              ColumnSourceByValues object,
+                                              StringBuilder builder )
+        {
+            builder.append( SQLConstants.NEWLINE ).append( "VALUES" )
+                   .append( SQLConstants.OPEN_PARENTHESIS );
+            Iterator<ValueExpression> iter = object.getValues().iterator();
+            while( iter.hasNext() )
+            {
+                ValueExpression next = iter.next();
+                boolean needParenthesis = next instanceof QueryExpression;
+                if( needParenthesis )
+                {
+                    builder.append( SQLConstants.OPEN_PARENTHESIS );
+                }
+                processor.process( next, builder );
+                if( needParenthesis )
+                {
+                    builder.append( SQLConstants.CLOSE_PARENTHESIS );
+                }
+                if( iter.hasNext() )
+                {
+                    builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                }
+            }
+            builder.append( SQLConstants.CLOSE_PARENTHESIS );
+        }
+    }
+
+    public static class DeleteBySearchProcessor extends AbstractProcessor<DeleteBySearch>
+    {
+        public DeleteBySearchProcessor()
+        {
+            this( DeleteBySearch.class );
+        }
+
+        public DeleteBySearchProcessor( Class<? extends DeleteBySearch> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, DeleteBySearch object,
+                                  StringBuilder builder )
+        {
+            builder.append( "DELETE FROM" ).append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( object.getTargetTable(), builder );
+            QueryProcessing.processOptionalBooleanExpression( processor, builder,
+                                                              object.getWhere(),
+                                                              SQLConstants.NEWLINE, SQLConstants.WHERE );
+        }
+    }
+
+    public static class InsertStatementProcessor extends AbstractProcessor<InsertStatement>
+    {
+        public InsertStatementProcessor()
+        {
+            this( InsertStatement.class );
+        }
+
+        public InsertStatementProcessor( Class<? extends InsertStatement> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, InsertStatement object,
+                                  StringBuilder builder )
+        {
+            builder.append( "INSERT INTO" ).append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( object.getTableName(), builder );
+            builder.append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( object.getColumnSource(), builder );
+        }
+    }
+
+    public static class SetClauseProcessor extends AbstractProcessor<SetClause>
+    {
+        public SetClauseProcessor()
+        {
+            this( SetClause.class );
+        }
+
+        public SetClauseProcessor( Class<? extends SetClause> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, SetClause object,
+                                  StringBuilder builder )
+        {
+            builder.append( object.getUpdateTarget() ).append( SQLConstants.TOKEN_SEPARATOR )
+                   .append( "=" )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( object.getUpdateSource(), builder );
+        }
+    }
+
+    public static class TargetTableProcessor extends AbstractProcessor<TargetTable>
+    {
+        public TargetTableProcessor()
+        {
+            this( TargetTable.class );
+        }
+
+        protected TargetTableProcessor( Class<? extends TargetTable> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, TargetTable object,
+                                  StringBuilder builder )
+        {
+            Boolean isOnly = object.isOnly();
+            if( isOnly )
+            {
+                builder.append( "ONLY" ).append( SQLConstants.OPEN_PARENTHESIS );
+            }
+            processor.process( object.getTableName(), builder );
+            if( isOnly )
+            {
+                builder.append( SQLConstants.CLOSE_PARENTHESIS );
+            }
+        }
+    }
+
+    public static class UpdateBySearchProcessor extends AbstractProcessor<UpdateBySearch>
+    {
+        public UpdateBySearchProcessor()
+        {
+            this( UpdateBySearch.class );
+        }
+
+        protected UpdateBySearchProcessor( Class<? extends UpdateBySearch> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, UpdateBySearch object,
+                                  StringBuilder builder )
+        {
+            builder.append( "UPDATE" ).append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( object.getTargetTable(), builder );
+            builder.append( SQLConstants.NEWLINE ).append( "SET" )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+            Iterator<SetClause> iter = object.getSetClauses().iterator();
+            while( iter.hasNext() )
+            {
+                processor.process( iter.next(), builder );
+                if( iter.hasNext() )
+                {
+                    builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                }
+            }
+            QueryProcessing.processOptionalBooleanExpression( processor, builder,
+                                                              object.getWhere(),
+                                                              SQLConstants.NEWLINE, SQLConstants.WHERE );
+        }
+    }
+
+    public static class UpdateSourceByExpressionProcessor extends
+                                                          AbstractProcessor<UpdateSourceByExpression>
+    {
+        public UpdateSourceByExpressionProcessor()
+        {
+            this( UpdateSourceByExpression.class );
+        }
+
+        public UpdateSourceByExpressionProcessor( Class<? extends UpdateSourceByExpression> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor,
+                                  UpdateSourceByExpression object,
+                                  StringBuilder builder )
+        {
+            processor.process( object.getValueExpression(), builder );
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/NoOpProcessor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/NoOpProcessor.java
new file mode 100644
index 0000000..e6bc330
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/NoOpProcessor.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+public class NoOpProcessor
+    implements SQLProcessor
+{
+
+    public void process( SQLProcessorAggregator processor, Typeable<?> object, StringBuilder builder )
+    {
+        // No-op
+    }
+}
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ProcessorUtils.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ProcessorUtils.java
new file mode 100644
index 0000000..15bb6b3
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ProcessorUtils.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation;
+
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropBehaviour;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ProcessorUtils
+{
+    public static Boolean notNullAndNotEmpty( String str )
+    {
+        return str != null && str.trim().length() > 0;
+    }
+
+    public static void processSetQuantifier( SetQuantifier quantifier, StringBuilder builder )
+    {
+        if( quantifier == SetQuantifier.ALL )
+        {
+            builder.append( "ALL" );
+        }
+        else
+        {
+            builder.append( "DISTINCT" );
+        }
+    }
+
+    public static void processDropBehaviour( DropBehaviour behaviour, StringBuilder builder )
+    {
+        builder.append( SQLConstants.TOKEN_SEPARATOR );
+        if( behaviour == DropBehaviour.CASCADE )
+        {
+            builder.append( "CASCADE" );
+        }
+        else
+        {
+            builder.append( "RESTRICT" );
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/QueryProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/QueryProcessing.java
new file mode 100644
index 0000000..e49bf15
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/QueryProcessing.java
@@ -0,0 +1,615 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.literals.LiteralExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferences;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferences.ColumnReferenceInfo;
+import org.apache.polygene.library.sql.generator.grammar.query.CorrespondingSpec;
+import org.apache.polygene.library.sql.generator.grammar.query.FromClause;
+import org.apache.polygene.library.sql.generator.grammar.query.GroupByClause;
+import org.apache.polygene.library.sql.generator.grammar.query.GroupingElement;
+import org.apache.polygene.library.sql.generator.grammar.query.LimitSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.OffsetSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.OrderByClause;
+import org.apache.polygene.library.sql.generator.grammar.query.Ordering;
+import org.apache.polygene.library.sql.generator.grammar.query.OrdinaryGroupingSet;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBody;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBodyBinary;
+import org.apache.polygene.library.sql.generator.grammar.query.QuerySpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.RowDefinition;
+import org.apache.polygene.library.sql.generator.grammar.query.RowSubQuery;
+import org.apache.polygene.library.sql.generator.grammar.query.RowValueConstructor;
+import org.apache.polygene.library.sql.generator.grammar.query.SelectColumnClause;
+import org.apache.polygene.library.sql.generator.grammar.query.SetOperation;
+import org.apache.polygene.library.sql.generator.grammar.query.SortSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReference;
+import org.apache.polygene.library.sql.generator.grammar.query.TableValueConstructor;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.BooleanUtils;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class QueryProcessing
+{
+
+    public static void processOptionalBooleanExpression( SQLProcessorAggregator processor,
+                                                         StringBuilder builder,
+                                                         BooleanExpression expression, String prefix, String name )
+    {
+        if( expression != null && !BooleanUtils.isEmpty( expression ) )
+        {
+            processOptional( processor, builder, expression, prefix, name );
+        }
+    }
+
+    public static void processOptional( SQLProcessorAggregator processor, StringBuilder builder,
+                                        Typeable<?> element,
+                                        String prefix, String name )
+    {
+        if( element != null )
+        {
+            builder.append( prefix );
+            if( name != null )
+            {
+                builder.append( name ).append( SQLConstants.TOKEN_SEPARATOR );
+            }
+            processor.process( element, builder );
+        }
+    }
+
+    public static class QueryExpressionBinaryProcessor extends
+                                                       AbstractProcessor<QueryExpressionBodyBinary>
+    {
+        private static final Map<SetOperation, String> _defaultSetOperations;
+
+        static
+        {
+            Map<SetOperation, String> operations = new HashMap<SetOperation, String>();
+            operations.put( SetOperation.EXCEPT, "EXCEPT" );
+            operations.put( SetOperation.INTERSECT, "INTERSECT" );
+            operations.put( SetOperation.UNION, "UNION" );
+            _defaultSetOperations = operations;
+        }
+
+        private final Map<SetOperation, String> _setOperations;
+
+        public QueryExpressionBinaryProcessor()
+        {
+            this( _defaultSetOperations );
+        }
+
+        public QueryExpressionBinaryProcessor( Map<SetOperation, String> setOperations )
+        {
+            super( QueryExpressionBodyBinary.class );
+            Objects.requireNonNull( setOperations, "set operations" );
+            this._setOperations = setOperations;
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, QueryExpressionBodyBinary body,
+                                  StringBuilder builder )
+        {
+            Boolean leftIsNotEmpty =
+                body.getLeft() != QueryExpressionBody.EmptyQueryExpressionBody.INSTANCE;
+            if( leftIsNotEmpty )
+            {
+                builder.append( SQLConstants.OPEN_PARENTHESIS );
+                processor.process( body.getLeft(), builder );
+                builder.append( SQLConstants.CLOSE_PARENTHESIS ).append( SQLConstants.NEWLINE );
+                this.processSetOperation( body.getSetOperation(), builder );
+
+                builder.append( SQLConstants.TOKEN_SEPARATOR );
+                ProcessorUtils.processSetQuantifier( body.getSetQuantifier(), builder );
+
+                CorrespondingSpec correspondingCols = body.getCorrespondingColumns();
+                if( correspondingCols != null )
+                {
+                    builder.append( SQLConstants.TOKEN_SEPARATOR );
+                    processor.process( correspondingCols, builder );
+                }
+
+                builder.append( SQLConstants.NEWLINE ).append( SQLConstants.OPEN_PARENTHESIS );
+            }
+            processor.process( body.getRight(), builder );
+            if( leftIsNotEmpty )
+            {
+                builder.append( SQLConstants.CLOSE_PARENTHESIS );
+            }
+        }
+
+        protected void processSetOperation( SetOperation operation, StringBuilder builder )
+        {
+            builder.append( this._setOperations.get( operation ) );
+        }
+    }
+
+    public static class QuerySpecificationProcessor extends AbstractProcessor<QuerySpecification>
+    {
+
+        public QuerySpecificationProcessor()
+        {
+            this( QuerySpecification.class );
+        }
+
+        public QuerySpecificationProcessor( Class<? extends QuerySpecification> queryClass )
+        {
+            super( queryClass );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, QuerySpecification query,
+                                  StringBuilder builder )
+        {
+            builder.append( SQLConstants.SELECT ).append( SQLConstants.TOKEN_SEPARATOR );
+            ProcessorUtils.processSetQuantifier( query.getColumns().getSetQuantifier(), builder );
+            builder.append( SQLConstants.TOKEN_SEPARATOR );
+
+            processor.process( query.getColumns(), builder );
+            processor.process( query.getFrom(), builder );
+            QueryProcessing.processOptionalBooleanExpression( processor, builder, query.getWhere(),
+                                                              SQLConstants.NEWLINE, SQLConstants.WHERE );
+            processor.process( query.getGroupBy(), builder );
+            QueryProcessing.processOptionalBooleanExpression( processor, builder,
+                                                              query.getHaving(),
+                                                              SQLConstants.NEWLINE, SQLConstants.HAVING );
+            processor.process( query.getOrderBy(), builder );
+            Typeable<?> first = null;
+            Typeable<?> second = null;
+            if( this.isOffsetBeforeLimit( processor ) )
+            {
+                first = query.getOffsetSpecification();
+                second = query.getLimitSpecification();
+            }
+            else
+            {
+                first = query.getLimitSpecification();
+                second = query.getOffsetSpecification();
+            }
+
+            if( first != null || second != null )
+            {
+                this.processLimitAndOffset( processor, builder, first, second );
+            }
+
+            if( query.getOrderBy() == null
+                && ( query.getOffsetSpecification() != null || query.getLimitSpecification() != null ) )
+            {
+                LoggerFactory.getLogger( this.getClass().getName() ).warn(
+                    "Spotted query with " + SQLConstants.OFFSET_PREFIX + " and/or "
+                    + SQLConstants.LIMIT_PREFIX
+                    + " clause, but without ORDER BY. The result will be unpredictable!"
+                    + "\n" + "Query: "
+                    + builder.toString() );
+            }
+        }
+
+        protected boolean isOffsetBeforeLimit( SQLProcessorAggregator processor )
+        {
+            return true;
+        }
+
+        protected void processLimitAndOffset( SQLProcessorAggregator processor,
+                                              StringBuilder builder,
+                                              Typeable<?> first, Typeable<?> second )
+        {
+            QueryProcessing.processOptional( processor, builder, first, SQLConstants.NEWLINE, null );
+            QueryProcessing
+                .processOptional( processor, builder, second, SQLConstants.NEWLINE, null );
+        }
+    }
+
+    public static class SelectColumnsProcessor extends AbstractProcessor<SelectColumnClause>
+    {
+        public SelectColumnsProcessor()
+        {
+            super( SelectColumnClause.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, SelectColumnClause select,
+                                  StringBuilder builder )
+        {
+            if( select instanceof ColumnReferences )
+            {
+                Iterator<ColumnReferenceInfo> iter =
+                    ( (ColumnReferences) select ).getColumns().iterator();
+                while( iter.hasNext() )
+                {
+                    ColumnReferenceInfo info = iter.next();
+                    aggregator.process( info.getReference(), builder );
+                    String alias = info.getAlias();
+                    if( ProcessorUtils.notNullAndNotEmpty( alias ) )
+                    {
+                        builder.append( SQLConstants.TOKEN_SEPARATOR )
+                               .append( SQLConstants.ALIAS_DEFINER )
+                               .append( SQLConstants.TOKEN_SEPARATOR ).append( alias );
+                    }
+
+                    if( iter.hasNext() )
+                    {
+                        builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                    }
+                }
+            }
+            else
+            {
+                builder.append( SQLConstants.ASTERISK );
+            }
+        }
+    }
+
+    public static class FromProcessor extends AbstractProcessor<FromClause>
+    {
+        public FromProcessor()
+        {
+            super( FromClause.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, FromClause from,
+                                  StringBuilder builder )
+        {
+            if( !from.getTableReferences().isEmpty() )
+            {
+                builder.append( SQLConstants.NEWLINE ).append( SQLConstants.FROM )
+                       .append( SQLConstants.TOKEN_SEPARATOR );
+                Iterator<TableReference> iter = from.getTableReferences().iterator();
+                while( iter.hasNext() )
+                {
+                    aggregator.process( iter.next().asTypeable(), builder );
+                    if( iter.hasNext() )
+                    {
+                        builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                    }
+                }
+            }
+        }
+    }
+
+    public static class QueryExpressionProcessor extends AbstractProcessor<QueryExpression>
+    {
+        public QueryExpressionProcessor()
+        {
+            super( QueryExpression.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, QueryExpression object,
+                                  StringBuilder builder )
+        {
+            processor.process( object.getQueryExpressionBody(), builder );
+        }
+    }
+
+    public static class CorrespondingSpecProcessor extends AbstractProcessor<CorrespondingSpec>
+    {
+        public CorrespondingSpecProcessor()
+        {
+            super( CorrespondingSpec.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, CorrespondingSpec object,
+                                  StringBuilder builder )
+        {
+            builder.append( "CORRESPONDING" );
+            if( object.getColumnList() != null )
+            {
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "BY" )
+                       .append( SQLConstants.TOKEN_SEPARATOR );
+                processor.process( object.getColumnList(), builder );
+            }
+        }
+    }
+
+    public static class SortSpecificationProcessor extends AbstractProcessor<SortSpecification>
+    {
+        private static final Map<Ordering, String> _defaultOrderingStrings;
+
+        static
+        {
+            Map<Ordering, String> map = new HashMap<Ordering, String>();
+            map.put( Ordering.ASCENDING, "ASC" );
+            map.put( Ordering.DESCENDING, "DESC" );
+            _defaultOrderingStrings = map;
+        }
+
+        private final Map<Ordering, String> _orderingStrings;
+
+        public SortSpecificationProcessor()
+        {
+            this( _defaultOrderingStrings );
+        }
+
+        public SortSpecificationProcessor( Map<Ordering, String> orderingStrings )
+        {
+            super( SortSpecification.class );
+            Objects.requireNonNull( orderingStrings, "ordering strings" );
+            this._orderingStrings = orderingStrings;
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, SortSpecification object,
+                                  StringBuilder builder )
+        {
+            processor.process( object.getValueExpression(), builder );
+            builder.append( SQLConstants.TOKEN_SEPARATOR ).append(
+                this._orderingStrings.get( object.getOrderingSpecification() ) );
+        }
+    }
+
+    public static class OrdinaryGroupingSetProcessor extends AbstractProcessor<OrdinaryGroupingSet>
+    {
+        public OrdinaryGroupingSetProcessor()
+        {
+            super( OrdinaryGroupingSet.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, OrdinaryGroupingSet object,
+                                  StringBuilder builder )
+        {
+            Iterator<NonBooleanExpression> iter = object.getColumns().iterator();
+            while( iter.hasNext() )
+            {
+                processor.process( iter.next(), builder );
+                if( iter.hasNext() )
+                {
+                    builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                }
+            }
+        }
+    }
+
+    public static class GroupByProcessor extends AbstractProcessor<GroupByClause>
+    {
+        public GroupByProcessor()
+        {
+            super( GroupByClause.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, GroupByClause groupBy,
+                                  StringBuilder builder )
+        {
+            if( !groupBy.getGroupingElements().isEmpty() )
+            {
+                builder.append( SQLConstants.NEWLINE ).append( SQLConstants.GROUP_BY )
+                       .append( SQLConstants.TOKEN_SEPARATOR );
+                Iterator<GroupingElement> iter = groupBy.getGroupingElements().iterator();
+                while( iter.hasNext() )
+                {
+                    aggregator.process( iter.next(), builder );
+                    if( iter.hasNext() )
+                    {
+                        builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                    }
+                }
+            }
+        }
+    }
+
+    public static class OrderByProcessor extends AbstractProcessor<OrderByClause>
+    {
+        public OrderByProcessor()
+        {
+            super( OrderByClause.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, OrderByClause orderBy,
+                                  StringBuilder builder )
+        {
+            if( !orderBy.getOrderingColumns().isEmpty() )
+            {
+                builder.append( SQLConstants.NEWLINE ).append( SQLConstants.ORDER_BY )
+                       .append( SQLConstants.TOKEN_SEPARATOR );
+                Iterator<SortSpecification> iter = orderBy.getOrderingColumns().iterator();
+                while( iter.hasNext() )
+                {
+                    aggregator.process( iter.next(), builder );
+                    if( iter.hasNext() )
+                    {
+                        builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                    }
+                }
+            }
+        }
+    }
+
+    public static class TableValueConstructorProcessor extends
+                                                       AbstractProcessor<TableValueConstructor>
+    {
+        public TableValueConstructorProcessor()
+        {
+            super( TableValueConstructor.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, TableValueConstructor object,
+                                  StringBuilder builder )
+        {
+            builder.append( "VALUES" ).append( SQLConstants.TOKEN_SEPARATOR );
+            Iterator<RowValueConstructor> iter = object.getRows().iterator();
+            while( iter.hasNext() )
+            {
+                aggregator.process( iter.next(), builder );
+                if( iter.hasNext() )
+                {
+                    builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                }
+            }
+        }
+    }
+
+    public static class RowSubQueryProcessor extends AbstractProcessor<RowSubQuery>
+    {
+        public RowSubQueryProcessor()
+        {
+            super( RowSubQuery.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, RowSubQuery object,
+                                  StringBuilder builder )
+        {
+            builder.append( SQLConstants.OPEN_PARENTHESIS );
+            aggregator.process( object.getQueryExpression(), builder );
+            builder.append( SQLConstants.CLOSE_PARENTHESIS );
+        }
+    }
+
+    public static class RowDefinitionProcessor extends AbstractProcessor<RowDefinition>
+    {
+        public RowDefinitionProcessor()
+        {
+            super( RowDefinition.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, RowDefinition object,
+                                  StringBuilder builder )
+        {
+            builder.append( SQLConstants.OPEN_PARENTHESIS );
+            Iterator<ValueExpression> vals = object.getRowElements().iterator();
+            while( vals.hasNext() )
+            {
+                aggregator.process( vals.next(), builder );
+                if( vals.hasNext() )
+                {
+                    builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                }
+            }
+            builder.append( SQLConstants.CLOSE_PARENTHESIS );
+        }
+    }
+
+    public static class OffsetSpecificationProcessor extends AbstractProcessor<OffsetSpecification>
+    {
+
+        public OffsetSpecificationProcessor()
+        {
+            super( OffsetSpecification.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, OffsetSpecification object,
+                                  StringBuilder builder )
+        {
+            String prefix = this.getPrefix( aggregator );
+            if( prefix != null )
+            {
+                builder.append( prefix ).append( SQLConstants.TOKEN_SEPARATOR );
+            }
+            NonBooleanExpression skip = object.getSkip();
+            boolean isComplex = !( skip instanceof LiteralExpression );
+            if( isComplex )
+            {
+                builder.append( SQLConstants.OPEN_PARENTHESIS ).append( SQLConstants.NEWLINE );
+            }
+            aggregator.process( skip, builder );
+            if( isComplex )
+            {
+                builder.append( SQLConstants.CLOSE_PARENTHESIS );
+            }
+            String postfix = this.getPostfix( aggregator );
+            if( postfix != null )
+            {
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append( postfix );
+            }
+        }
+
+        protected String getPrefix( SQLProcessorAggregator processor )
+        {
+            return SQLConstants.OFFSET_PREFIX;
+        }
+
+        protected String getPostfix( SQLProcessorAggregator processor )
+        {
+            return SQLConstants.OFFSET_POSTFIX;
+        }
+    }
+
+    public static class LimitSpecificationProcessor extends AbstractProcessor<LimitSpecification>
+    {
+        public LimitSpecificationProcessor()
+        {
+            super( LimitSpecification.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, LimitSpecification object,
+                                  StringBuilder builder )
+        {
+            NonBooleanExpression count = this.getRealCount( object.getCount() );
+            if( count != null )
+            {
+                String prefix = this.getPrefix( aggregator );
+                if( prefix != null )
+                {
+                    builder.append( prefix ).append( SQLConstants.TOKEN_SEPARATOR );
+                }
+                boolean isComplex = !( count instanceof LiteralExpression );
+                if( isComplex )
+                {
+                    builder.append( SQLConstants.OPEN_PARENTHESIS ).append( SQLConstants.NEWLINE );
+                }
+                aggregator.process( count, builder );
+                if( isComplex )
+                {
+                    builder.append( SQLConstants.CLOSE_PARENTHESIS );
+                }
+                String postfix = this.getPostfix( aggregator );
+                if( postfix != null )
+                {
+                    builder.append( SQLConstants.TOKEN_SEPARATOR ).append( postfix );
+                }
+            }
+        }
+
+        protected NonBooleanExpression getRealCount( NonBooleanExpression limitCount )
+        {
+            return limitCount;
+        }
+
+        protected String getPrefix( SQLProcessorAggregator processor )
+        {
+            return SQLConstants.LIMIT_PREFIX;
+        }
+
+        protected String getPostfix( SQLProcessorAggregator processor )
+        {
+            return SQLConstants.LIMIT_POSTFIX;
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/TableReferenceProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/TableReferenceProcessing.java
new file mode 100644
index 0000000..151b4f7
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/TableReferenceProcessing.java
@@ -0,0 +1,354 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation;
+
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.common.TableName;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameFunction;
+import org.apache.polygene.library.sql.generator.grammar.query.TableAlias;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferenceByExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferenceByName;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferencePrimary;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.CrossJoinedTable;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinCondition;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinType;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinedTable;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.NamedColumnsJoin;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.NaturalJoinedTable;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.QualifiedJoinedTable;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.UnionJoinedTable;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TableReferenceProcessing
+{
+
+    public static abstract class AbstractTableNameProcessor<TableNameType extends TableName>
+        extends
+        AbstractProcessor<TableNameType>
+    {
+
+        protected AbstractTableNameProcessor( Class<? extends TableNameType> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, TableNameType object,
+                                  StringBuilder builder )
+        {
+            String schemaName = object.getSchemaName();
+            if( ProcessorUtils.notNullAndNotEmpty( schemaName ) )
+            {
+                builder.append( schemaName ).append( SQLConstants.SCHEMA_TABLE_SEPARATOR );
+            }
+            this.doProcessTableName( processor, object, builder );
+        }
+
+        protected abstract void doProcessTableName( SQLProcessorAggregator processor,
+                                                    TableNameType object,
+                                                    StringBuilder builder );
+    }
+
+    public static class TableNameFunctionProcessor extends
+                                                   AbstractTableNameProcessor<TableNameFunction>
+    {
+
+        public TableNameFunctionProcessor()
+        {
+            this( TableNameFunction.class );
+        }
+
+        protected TableNameFunctionProcessor( Class<? extends TableNameFunction> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcessTableName( SQLProcessorAggregator processor,
+                                           TableNameFunction object,
+                                           StringBuilder builder )
+        {
+            processor.process( object.getFunction(), builder );
+        }
+    }
+
+    public static class TableNameDirectProcessor extends
+                                                 AbstractTableNameProcessor<TableNameDirect>
+    {
+
+        public TableNameDirectProcessor()
+        {
+            this( TableNameDirect.class );
+        }
+
+        protected TableNameDirectProcessor( Class<? extends TableNameDirect> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcessTableName( SQLProcessorAggregator processor,
+                                           TableNameDirect object,
+                                           StringBuilder builder )
+        {
+            builder.append( object.getTableName() );
+        }
+    }
+
+    public static abstract class TableReferencePrimaryProcessor<TableReferenceType extends TableReferencePrimary>
+        extends AbstractProcessor<TableReferenceType>
+    {
+        public TableReferencePrimaryProcessor( Class<TableReferenceType> realType )
+        {
+            super( realType );
+        }
+
+        protected void doProcess( SQLProcessorAggregator processor, TableReferenceType object,
+                                  StringBuilder builder )
+        {
+            this.doProcessTablePrimary( processor, object, builder );
+            if( object.getTableAlias() != null )
+            {
+                this.processTableAlias( processor, object.getTableAlias(), builder );
+            }
+        }
+
+        protected abstract void doProcessTablePrimary( SQLProcessorAggregator processor,
+                                                       TableReferenceType object,
+                                                       StringBuilder builder );
+
+        protected void processTableAlias( SQLProcessorAggregator processor, TableAlias tableAlias,
+                                          StringBuilder builder )
+        {
+            String alias = tableAlias.getTableAlias();
+            if( ProcessorUtils.notNullAndNotEmpty( alias ) )
+            {
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append( SQLConstants.ALIAS_DEFINER )
+                       .append( SQLConstants.TOKEN_SEPARATOR ).append( alias );
+
+                if( tableAlias.getColumnAliases() != null )
+                {
+                    processor.process( tableAlias.getColumnAliases(), builder );
+                }
+            }
+        }
+    }
+
+    public static class TableReferenceByNameProcessor extends
+                                                      TableReferencePrimaryProcessor<TableReferenceByName>
+    {
+        public TableReferenceByNameProcessor()
+        {
+            super( TableReferenceByName.class );
+        }
+
+        @Override
+        protected void doProcessTablePrimary( SQLProcessorAggregator processor,
+                                              TableReferenceByName object,
+                                              StringBuilder builder )
+        {
+            processor.process( object.getTableName(), builder );
+        }
+    }
+
+    public static class TableReferenceByExpressionProcessor extends
+                                                            TableReferencePrimaryProcessor<TableReferenceByExpression>
+    {
+        public TableReferenceByExpressionProcessor()
+        {
+            super( TableReferenceByExpression.class );
+        }
+
+        @Override
+        protected void doProcessTablePrimary( SQLProcessorAggregator processor,
+                                              TableReferenceByExpression tableRef,
+                                              StringBuilder builder )
+        {
+            builder.append( SQLConstants.OPEN_PARENTHESIS );
+            processor.process( tableRef.getQuery(), builder );
+            builder.append( SQLConstants.CLOSE_PARENTHESIS );
+        }
+    }
+
+    public static abstract class JoinedTableProcessor<JoinedTableType extends JoinedTable> extends
+                                                                                           AbstractProcessor<JoinedTableType>
+    {
+
+        public JoinedTableProcessor( Class<JoinedTableType> realType )
+        {
+            super( realType );
+        }
+
+        protected void doProcess( SQLProcessorAggregator processor, JoinedTableType table,
+                                  StringBuilder builder )
+        {
+            processor.process( table.getLeft().asTypeable(), builder );
+            builder.append( SQLConstants.NEWLINE );
+            this.doProcessJoinedTable( processor, table, builder );
+        }
+
+        protected abstract void doProcessJoinedTable( SQLProcessorAggregator processor,
+                                                      JoinedTableType table,
+                                                      StringBuilder builder );
+
+        protected void processJoinType( JoinType joinType, StringBuilder builder )
+        {
+            if( joinType != null )
+            {
+                if( joinType == JoinType.INNER )
+                {
+                    builder.append( "INNER " );
+                }
+                else
+                {
+                    if( joinType == JoinType.FULL_OUTER )
+                    {
+                        builder.append( "FULL " );
+                    }
+                    else if( joinType == JoinType.LEFT_OUTER )
+                    {
+                        builder.append( "LEFT " );
+                    }
+                    else
+                    // if (joinType == JoinType.RIGHT_OUTER)
+                    {
+                        builder.append( "RIGHT " );
+                    }
+                }
+                builder.append( "JOIN" ).append( SQLConstants.TOKEN_SEPARATOR );
+            }
+        }
+    }
+
+    public static class CrossJoinedTableProcessor extends JoinedTableProcessor<CrossJoinedTable>
+    {
+        public CrossJoinedTableProcessor()
+        {
+            super( CrossJoinedTable.class );
+        }
+
+        @Override
+        protected void doProcessJoinedTable( SQLProcessorAggregator processor,
+                                             CrossJoinedTable table,
+                                             StringBuilder builder )
+        {
+            builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "CROSS JOIN" )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( table.getRight().asTypeable(), builder );
+        }
+    }
+
+    public static class NaturalJoinedTableProcessor extends
+                                                    JoinedTableProcessor<NaturalJoinedTable>
+    {
+        public NaturalJoinedTableProcessor()
+        {
+            super( NaturalJoinedTable.class );
+        }
+
+        @Override
+        protected void doProcessJoinedTable( SQLProcessorAggregator processor,
+                                             NaturalJoinedTable table,
+                                             StringBuilder builder )
+        {
+            builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "NATURAL" )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+            this.processJoinType( table.getJoinType(), builder );
+            builder.append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( table.getRight().asTypeable(), builder );
+        }
+    }
+
+    public static class QualifiedJoinedTableProcessor extends
+                                                      JoinedTableProcessor<QualifiedJoinedTable>
+    {
+        public QualifiedJoinedTableProcessor()
+        {
+            super( QualifiedJoinedTable.class );
+        }
+
+        @Override
+        protected void doProcessJoinedTable( SQLProcessorAggregator processor,
+                                             QualifiedJoinedTable table,
+                                             StringBuilder builder )
+        {
+            this.processJoinType( table.getJoinType(), builder );
+            processor.process( table.getRight().asTypeable(), builder );
+            processor.process( table.getJoinSpecification(), builder );
+        }
+    }
+
+    public static class UnionJoinedTableProcessor extends JoinedTableProcessor<UnionJoinedTable>
+    {
+        public UnionJoinedTableProcessor()
+        {
+            super( UnionJoinedTable.class );
+        }
+
+        @Override
+        protected void doProcessJoinedTable( SQLProcessorAggregator processor,
+                                             UnionJoinedTable table,
+                                             StringBuilder builder )
+        {
+            builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "UNION JOIN" )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( table.getRight().asTypeable(), builder );
+        }
+    }
+
+    public static class JoinConditionProcessor extends AbstractProcessor<JoinCondition>
+    {
+        public JoinConditionProcessor()
+        {
+            super( JoinCondition.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, JoinCondition condition,
+                                  StringBuilder builder )
+        {
+            builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "ON" )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( condition.getSearchConidition(), builder );
+        }
+    }
+
+    public static class NamedColumnsJoinProcessor extends AbstractProcessor<NamedColumnsJoin>
+    {
+        public NamedColumnsJoinProcessor()
+        {
+            super( NamedColumnsJoin.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, NamedColumnsJoin join,
+                                  StringBuilder builder )
+        {
+            builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "USING" )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+
+            processor.process( join.getColumnNames(), builder );
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/derby/DerbyProcessor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/derby/DerbyProcessor.java
new file mode 100644
index 0000000..afc7d35
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/derby/DerbyProcessor.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation.derby;
+
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefaultSQLProcessor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+public class DerbyProcessor extends DefaultSQLProcessor
+{
+
+    public DerbyProcessor( SQLVendor vendor )
+    {
+        super( vendor, DefaultSQLProcessor.getDefaultProcessors() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/h2/H2Processor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/h2/H2Processor.java
new file mode 100644
index 0000000..8176980
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/h2/H2Processor.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation.h2;
+
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefaultSQLProcessor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+public class H2Processor
+    extends DefaultSQLProcessor
+{
+
+    public H2Processor( SQLVendor vendor )
+    {
+        super( vendor, DefaultSQLProcessor.getDefaultProcessors() );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/DefinitionProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/DefinitionProcessing.java
new file mode 100644
index 0000000..3ccc96f
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/DefinitionProcessing.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation.mysql;
+
+import org.apache.polygene.library.sql.generator.grammar.definition.schema.SchemaDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.ColumnDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.SchemaDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DefinitionProcessing
+{
+
+    public static class MySQLSchemaDefinitionProcessor extends SchemaDefinitionProcessor
+    {
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, SchemaDefinition object, StringBuilder builder )
+        {
+            // Just process schema elements
+            this.processSchemaElements( aggregator, object, builder );
+        }
+    }
+
+    public static class MySQLColumnDefinitionProcessor extends ColumnDefinitionProcessor
+    {
+        @Override
+        protected void processAutoGenerationPolicy( ColumnDefinition object, StringBuilder builder )
+        {
+            // MySQL combines both ALWAYS and BY DEFAULT policies.
+            builder.append( " AUTO_INCREMENT" );
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/MySQLProcessor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/MySQLProcessor.java
new file mode 100644
index 0000000..dc036f6
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/MySQLProcessor.java
@@ -0,0 +1,81 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation.mysql;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameFunction;
+import org.apache.polygene.library.sql.generator.grammar.definition.schema.SchemaDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropSchemaStatement;
+import org.apache.polygene.library.sql.generator.grammar.query.LimitSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.OffsetSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.QuerySpecification;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefaultSQLProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.NoOpProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.mysql.DefinitionProcessing.MySQLColumnDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.mysql.DefinitionProcessing.MySQLSchemaDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.mysql.QueryProcessing.MySQLLimitSpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.mysql.QueryProcessing.MySQLOffsetSpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.mysql.QueryProcessing.MySQLQuerySpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.mysql.TableProcessing.MySQLTableNameDirectProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.mysql.TableProcessing.MySQLTableNameFunctionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class MySQLProcessor extends DefaultSQLProcessor
+{
+
+    private static final Map<Class<? extends Typeable<?>>, SQLProcessor> _defaultProcessors;
+
+    static
+    {
+        Map<Class<? extends Typeable<?>>, SQLProcessor> processors = new HashMap<Class<? extends Typeable<?>>, SQLProcessor>(
+            DefaultSQLProcessor.getDefaultProcessors() );
+
+        // MySQL does not understand schema-qualified table names (or anything related to schemas)
+        processors.put( TableNameDirect.class, new MySQLTableNameDirectProcessor() );
+        processors.put( TableNameFunction.class, new MySQLTableNameFunctionProcessor() );
+
+        // Only process schema elements from schema definition, and ignore drop schema statements
+        processors.put( SchemaDefinition.class, new MySQLSchemaDefinitionProcessor() );
+        processors.put( DropSchemaStatement.class, new NoOpProcessor() );
+
+        // Override default column definition support
+        processors.put( ColumnDefinition.class, new MySQLColumnDefinitionProcessor() );
+
+        // Different syntax for OFFSET/FETCH
+        processors.put( QuerySpecification.class, new MySQLQuerySpecificationProcessor() );
+        processors.put( OffsetSpecification.class, new MySQLOffsetSpecificationProcessor() );
+        processors.put( LimitSpecification.class, new MySQLLimitSpecificationProcessor() );
+
+        _defaultProcessors = processors;
+    }
+
+    public MySQLProcessor( SQLVendor vendor )
+    {
+        super( vendor, _defaultProcessors );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/QueryProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/QueryProcessing.java
new file mode 100644
index 0000000..7324418
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/QueryProcessing.java
@@ -0,0 +1,114 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation.mysql;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.query.LimitSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.OffsetSpecification;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.LimitSpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.OffsetSpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.QuerySpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.MySQLVendor;
+
+/**
+ * @author 2011 Stanislav Muhametsin
+ */
+public class QueryProcessing
+{
+    private static final String MYSQL_LIMIT_PREFIX = "LIMIT";
+    private static final String MYSQL_LIMIT_POSTFIX = null;
+    private static final String MYSQL_OFFSET_PREFIX = "OFFSET";
+    private static final String MYSQL_OFFSET_POSTFIX = null;
+
+    public static class MySQLQuerySpecificationProcessor extends QuerySpecificationProcessor
+    {
+        @Override
+        protected boolean isOffsetBeforeLimit( SQLProcessorAggregator processor )
+        {
+            return false;
+        }
+
+        @Override
+        protected void processLimitAndOffset( SQLProcessorAggregator processor, StringBuilder builder,
+                                              Typeable<?> first, Typeable<?> second )
+        {
+            MySQLVendor vendor = (MySQLVendor) processor.getVendor();
+            if( vendor.legacyLimit() )
+            {
+                // Just do the processing right away, because of the difference of syntax
+                builder.append( SQLConstants.NEWLINE ).append( MYSQL_LIMIT_PREFIX )
+                       .append( SQLConstants.TOKEN_SEPARATOR );
+                if( second != null )
+                {
+                    processor.process( ( (OffsetSpecification) second ).getSkip(), builder );
+                    builder.append( SQLConstants.COMMA );
+                }
+                if( first != null && ( (LimitSpecification) first ).getCount() != null )
+                {
+                    processor.process( ( (LimitSpecification) first ).getCount(), builder );
+                }
+                else if( second != null )
+                {
+                    builder.append( Long.MAX_VALUE );
+                }
+            }
+            else
+            {
+                if( first == null && second != null )
+                {
+                    first = vendor.getQueryFactory().limit( vendor.getLiteralFactory().n( Long.MAX_VALUE ) );
+                }
+                super.processLimitAndOffset( processor, builder, first, second );
+            }
+        }
+    }
+
+    public static class MySQLOffsetSpecificationProcessor extends OffsetSpecificationProcessor
+    {
+        @Override
+        protected String getPrefix( SQLProcessorAggregator processor )
+        {
+            return MYSQL_OFFSET_PREFIX;
+        }
+
+        @Override
+        protected String getPostfix( SQLProcessorAggregator processor )
+        {
+            return MYSQL_OFFSET_POSTFIX;
+        }
+    }
+
+    public static class MySQLLimitSpecificationProcessor extends LimitSpecificationProcessor
+    {
+        @Override
+        protected String getPrefix( SQLProcessorAggregator processor )
+        {
+            return MYSQL_LIMIT_PREFIX;
+        }
+
+        @Override
+        protected String getPostfix( SQLProcessorAggregator processor )
+        {
+            return MYSQL_LIMIT_POSTFIX;
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/TableProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/TableProcessing.java
new file mode 100644
index 0000000..e209b07
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/TableProcessing.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.polygene.library.sql.generator.implementation.transformation.mysql;
+
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameFunction;
+import org.apache.polygene.library.sql.generator.implementation.transformation.TableReferenceProcessing.TableNameDirectProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.TableReferenceProcessing.TableNameFunctionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TableProcessing
+{
+    public static class MySQLTableNameDirectProcessor extends TableNameDirectProcessor
+    {
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, TableNameDirect object, StringBuilder builder )
+        {
+            // MySQL does not understand schema-qualified table names
+            builder.append( object.getTableName() );
+        }
+    }
+
+    public static class MySQLTableNameFunctionProcessor extends TableNameFunctionProcessor
+    {
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, TableNameFunction object, StringBuilder builder )
+        {
+            // MySQL does not understand schema-qualified table names
+            processor.process( object.getFunction(), builder );
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/package-info.java
new file mode 100644
index 0000000..1560a29
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This package contains the default processors for syntax elements defined in API. The vendor uses these processors (or custom processors) to create textual SQL statement out of API syntax elements.
+ */
+package org.apache.polygene.library.sql.generator.implementation.transformation;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/DefinitionProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/DefinitionProcessing.java
new file mode 100644
index 0000000..2eb78fa
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/DefinitionProcessing.java
@@ -0,0 +1,90 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation.pgsql;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.AutoGenerationPolicy;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.ColumnDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DefinitionProcessing
+{
+    public static class PGColumnDefinitionProcessor extends ColumnDefinitionProcessor
+    {
+        private final Map<Class<?>, String> _dataTypeSerialNames;
+
+        public PGColumnDefinitionProcessor( Map<Class<?>, String> dataTypeSerialNames )
+        {
+            Objects.requireNonNull( dataTypeSerialNames, "Data type serial names" );
+            this._dataTypeSerialNames = dataTypeSerialNames;
+        }
+
+        @Override
+        protected void processDataType( SQLProcessorAggregator aggregator, ColumnDefinition object,
+                                        StringBuilder builder )
+        {
+            AutoGenerationPolicy autoGenPolicy = object.getAutoGenerationPolicy();
+            if( autoGenPolicy == null )
+            {
+                super.processDataType( aggregator, object, builder );
+            }
+            else
+            {
+                // PostgreSQL can't handle the ALWAYS strategy
+                if( AutoGenerationPolicy.BY_DEFAULT.equals( autoGenPolicy ) )
+                {
+                    // Don't produce default data type if auto generated
+                    Class<?> dtClass = object.getDataType().getClass();
+                    Boolean success = false;
+                    for( Map.Entry<Class<?>, String> entry : this._dataTypeSerialNames.entrySet() )
+                    {
+                        success = entry.getKey().isAssignableFrom( dtClass );
+                        if( success )
+                        {
+                            builder.append( entry.getValue() );
+                            break;
+                        }
+                    }
+                    if( !success )
+                    {
+                        throw new UnsupportedOperationException( "Unsupported column data type " + object.getDataType()
+                                                                 + " for auto-generated column." );
+                    }
+                }
+                else
+                {
+                    throw new UnsupportedOperationException( "Unsupported auto generation policy: " + autoGenPolicy
+                                                             + "." );
+                }
+            }
+        }
+
+        @Override
+        protected void processAutoGenerationPolicy( ColumnDefinition object, StringBuilder builder )
+        {
+            // Nothing to do - auto generation policy handled in data type orc
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/LiteralExpressionProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/LiteralExpressionProcessing.java
new file mode 100644
index 0000000..de1dae7
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/LiteralExpressionProcessing.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.literals.TimestampTimeLiteral;
+import org.apache.polygene.library.sql.generator.implementation.transformation.LiteralExpressionProcessing.DateTimeLiteralProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class LiteralExpressionProcessing
+{
+    public static class PGDateTimeLiteralProcessor extends DateTimeLiteralProcessor
+    {
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, TimestampTimeLiteral object, StringBuilder builder )
+        {
+            builder.append( "timestamp " );
+            super.doProcess( processor, object, builder );
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/ManipulationProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/ManipulationProcessing.java
new file mode 100644
index 0000000..9aa0c6a
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/ManipulationProcessing.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropTableOrViewStatement;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.pgsql.PgSQLDropTableOrViewStatement;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ManipulationProcessing.DropTableOrViewStatementProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ProcessorUtils;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ManipulationProcessing
+{
+
+    public static class PgSQLDropTableOrViewStatementProcessor extends DropTableOrViewStatementProcessor
+    {
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, DropTableOrViewStatement object,
+                                  StringBuilder builder )
+        {
+            builder.append( "DROP" ).append( SQLConstants.TOKEN_SEPARATOR )
+                   .append( this.getObjectTypes().get( object.whatToDrop() ) ).append( SQLConstants.TOKEN_SEPARATOR );
+
+            Boolean useIfExists = ( (PgSQLDropTableOrViewStatement) object ).useIfExists();
+            if( useIfExists )
+            {
+                builder.append( "IF EXISTS" ).append( SQLConstants.TOKEN_SEPARATOR );
+            }
+
+            aggregator.process( object.getTableName(), builder );
+
+            ProcessorUtils.processDropBehaviour( object.getDropBehaviour(), builder );
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/ModificationProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/ModificationProcessing.java
new file mode 100644
index 0000000..100e311
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/ModificationProcessing.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.modification.InsertStatement;
+import org.apache.polygene.library.sql.generator.grammar.modification.pgsql.PgSQLInsertStatement;
+import org.apache.polygene.library.sql.generator.grammar.query.SelectColumnClause;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ModificationProcessing.InsertStatementProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+public class ModificationProcessing
+{
+
+    public static class PgSQLInsertStatementProcessor extends InsertStatementProcessor
+    {
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, InsertStatement object,
+                                  StringBuilder builder )
+        {
+            super.doProcess( processor, object, builder );
+
+            SelectColumnClause returning = ( (PgSQLInsertStatement) object ).getReturningClause();
+            if( returning != null )
+            {
+                builder.append( SQLConstants.NEWLINE ).append( "RETURNING " );
+                processor.process( returning, builder );
+            }
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/PostgreSQLProcessor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/PostgreSQLProcessor.java
new file mode 100644
index 0000000..3dbc059
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/PostgreSQLProcessor.java
@@ -0,0 +1,132 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation.pgsql;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BinaryPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.NotRegexpPredicate;
+import org.apache.polygene.library.sql.generator.grammar.booleans.RegexpPredicate;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.BigInt;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLInteger;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SmallInt;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.pgsql.Text;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableCommitAction;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.pgsql.PgSQLTableCommitAction;
+import org.apache.polygene.library.sql.generator.grammar.literals.TimestampTimeLiteral;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.pgsql.PgSQLDropTableOrViewStatement;
+import org.apache.polygene.library.sql.generator.grammar.modification.pgsql.PgSQLInsertStatement;
+import org.apache.polygene.library.sql.generator.grammar.query.LimitSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.OffsetSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.QuerySpecification;
+import org.apache.polygene.library.sql.generator.implementation.transformation.BooleanExpressionProcessing.BinaryPredicateProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.ConstantProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefaultSQLProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.TableDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.pgsql.DefinitionProcessing.PGColumnDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.pgsql.LiteralExpressionProcessing.PGDateTimeLiteralProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.pgsql.ManipulationProcessing.PgSQLDropTableOrViewStatementProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.pgsql.ModificationProcessing.PgSQLInsertStatementProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.pgsql.QueryProcessing.PgSQLLimitSpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.pgsql.QueryProcessing.PgSQLOffsetSpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.pgsql.QueryProcessing.PgSQLQuerySpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class PostgreSQLProcessor extends DefaultSQLProcessor
+{
+
+    private static final Map<Class<? extends Typeable<?>>, SQLProcessor> _defaultProcessors;
+
+    private static final Map<Class<? extends BinaryPredicate>, String> _defaultPgSQLBinaryOperators;
+
+    static
+    {
+        Map<Class<? extends BinaryPredicate>, String> binaryOperators =
+            new HashMap<Class<? extends BinaryPredicate>, String>(
+                DefaultSQLProcessor.getDefaultBinaryOperators() );
+        binaryOperators.put( RegexpPredicate.class, "~" );
+        binaryOperators.put( NotRegexpPredicate.class, "!~" );
+        _defaultPgSQLBinaryOperators = binaryOperators;
+
+        Map<Class<? extends Typeable<?>>, SQLProcessor> processors =
+            new HashMap<Class<? extends Typeable<?>>, SQLProcessor>(
+                DefaultSQLProcessor.getDefaultProcessors() );
+
+        // Override default processor for date-time
+        processors.put( TimestampTimeLiteral.class, new PGDateTimeLiteralProcessor() );
+
+        // Override default processor for column definition
+        Map<Class<?>, String> dataTypeSerials = new HashMap<Class<?>, String>();
+        dataTypeSerials.put( BigInt.class, "BIGSERIAL" );
+        dataTypeSerials.put( SQLInteger.class, "SERIAL" );
+        dataTypeSerials.put( SmallInt.class, "SMALLSERIAL" );
+        processors.put( ColumnDefinition.class,
+                        new PGColumnDefinitionProcessor( Collections.unmodifiableMap( dataTypeSerials ) ) );
+
+        // Add support for regexp comparing
+        processors
+            .put(
+                RegexpPredicate.class,
+                new BinaryPredicateProcessor( _defaultPgSQLBinaryOperators
+                                                  .get( RegexpPredicate.class ) ) );
+        processors.put(
+            NotRegexpPredicate.class,
+            new BinaryPredicateProcessor( _defaultPgSQLBinaryOperators
+                                              .get( NotRegexpPredicate.class ) ) );
+
+        // Add support for PostgreSQL legacy LIMIT/OFFSET
+        processors.put( QuerySpecification.class, new PgSQLQuerySpecificationProcessor() );
+        processors.put( OffsetSpecification.class, new PgSQLOffsetSpecificationProcessor() );
+        processors.put( LimitSpecification.class, new PgSQLLimitSpecificationProcessor() );
+
+        // Add support for "TEXT" data type
+        processors.put( Text.class, new ConstantProcessor( "TEXT" ) );
+
+        // Add "DROP" table commit action
+        Map<TableCommitAction, String> commitActions = new HashMap<TableCommitAction, String>(
+            TableDefinitionProcessor.getDefaultCommitActions() );
+        commitActions.put( PgSQLTableCommitAction.DROP, "DROP" );
+        processors.put( TableDefinition.class,
+                        new TableDefinitionProcessor( TableDefinitionProcessor.getDefaultTableScopes(),
+                                                      commitActions ) );
+
+        // Add "IF EXISTS" functionality to DROP TABLE/VIEW statements
+        processors.put( PgSQLDropTableOrViewStatement.class,
+                        new PgSQLDropTableOrViewStatementProcessor() );
+
+        // Add support for PostgreSQL-specific INSTERT statement RETURNING clause
+        processors.put( PgSQLInsertStatement.class, new PgSQLInsertStatementProcessor() );
+
+        _defaultProcessors = processors;
+    }
+
+    public PostgreSQLProcessor( SQLVendor vendor )
+    {
+        super( vendor, _defaultProcessors );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/QueryProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/QueryProcessing.java
new file mode 100644
index 0000000..a5bb806
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/QueryProcessing.java
@@ -0,0 +1,81 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation.pgsql;
+
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.LimitSpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.OffsetSpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.QuerySpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.PostgreSQLVendor;
+
+/**
+ * @author 2011 Stanislav Muhametsin
+ */
+public class QueryProcessing
+{
+
+    private static final String LEGACY_LIMIT_PREFIX = "LIMIT";
+    private static final String LEGACY_LIMIT_POSTFIX = null;
+    private static final String LEGACY_OFFSET_PREFIX = "OFFSET";
+    private static final String LEGACY_OFFSET_POSTFIX = null;
+
+    public static class PgSQLQuerySpecificationProcessor extends QuerySpecificationProcessor
+    {
+        @Override
+        protected boolean isOffsetBeforeLimit( SQLProcessorAggregator processor )
+        {
+            return !( (PostgreSQLVendor) processor.getVendor() ).legacyOffsetAndLimit();
+        }
+    }
+
+    public static class PgSQLOffsetSpecificationProcessor extends OffsetSpecificationProcessor
+    {
+        @Override
+        protected String getPrefix( SQLProcessorAggregator processor )
+        {
+            return ( (PostgreSQLVendor) processor.getVendor() ).legacyOffsetAndLimit() ? LEGACY_OFFSET_PREFIX : super
+                .getPrefix( processor );
+        }
+
+        @Override
+        protected String getPostfix( SQLProcessorAggregator processor )
+        {
+            return ( (PostgreSQLVendor) processor.getVendor() ).legacyOffsetAndLimit() ? LEGACY_OFFSET_POSTFIX : super
+                .getPostfix( processor );
+        }
+    }
+
+    public static class PgSQLLimitSpecificationProcessor extends LimitSpecificationProcessor
+    {
+        @Override
+        protected String getPrefix( SQLProcessorAggregator processor )
+        {
+            return ( (PostgreSQLVendor) processor.getVendor() ).legacyOffsetAndLimit() ? LEGACY_LIMIT_PREFIX : super
+                .getPrefix( processor );
+        }
+
+        @Override
+        protected String getPostfix( SQLProcessorAggregator processor )
+        {
+            return ( (PostgreSQLVendor) processor.getVendor() ).legacyOffsetAndLimit() ? LEGACY_LIMIT_POSTFIX : super
+                .getPostfix( processor );
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/spi/SQLProcessor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/spi/SQLProcessor.java
new file mode 100644
index 0000000..f0e6f37
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/spi/SQLProcessor.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation.spi;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public interface SQLProcessor
+{
+    void process( SQLProcessorAggregator aggregator, Typeable<?> object, StringBuilder builder );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/spi/SQLProcessorAggregator.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/spi/SQLProcessorAggregator.java
new file mode 100644
index 0000000..cbbe6de
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/spi/SQLProcessorAggregator.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation.spi;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public interface SQLProcessorAggregator
+{
+    void process( Typeable<?> object, StringBuilder builder );
+
+    SQLVendor getVendor();
+
+    /**
+     * <p>
+     * This provides a way to access current path in a SQL syntax tree. The first element is the root one, then the next
+     * one is its child, etc. This stack is read-only.
+     * </p>
+     * <p>
+     * Currently I'm not sure if there is an efficient way to acquire read-only stacks rather than creating a new one
+     * from contents of another.
+     * </p>
+     *
+     * @return A current path in SQL syntax tree.
+     */
+    // public Stack<Typeable<?>> getCurrentSyntaxTree();
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/sqlite/DefinitionProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/sqlite/DefinitionProcessing.java
new file mode 100644
index 0000000..9bd835e
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/sqlite/DefinitionProcessing.java
@@ -0,0 +1,141 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation.sqlite;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.definition.schema.SchemaDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.AutoGenerationPolicy;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableConstraintDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableElement;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.UniqueConstraint;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.UniqueSpecification;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.ColumnDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.SchemaDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.TableElementListProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+public class DefinitionProcessing
+{
+    public static class SQLListeTableElementListProcessor
+        extends TableElementListProcessor
+    {
+        @Override
+        protected void processTableElement( SQLProcessorAggregator aggregator, TableElement object,
+                                            StringBuilder builder, boolean hasNext )
+        {
+            if( object.getImplementedType().isAssignableFrom( TableConstraintDefinition.class ) )
+            {
+                TableConstraint constraint =
+                    TableConstraintDefinition.class.cast( object ).getConstraint();
+                if( constraint.getImplementedType().isAssignableFrom( UniqueConstraint.class ) )
+                {
+                    UniqueConstraint unique = UniqueConstraint.class.cast( constraint );
+                    if( UniqueSpecification.PRIMARY_KEY.equals( unique.getUniquenessKind() ) )
+                    {
+                        return; // Skip the whole TableElement for SQL autogen support, see below
+                    }
+                }
+            }
+            super.processTableElement( aggregator, object, builder, hasNext );
+        }
+    }
+
+    public static class SQLiteSchemaDefinitionProcessor
+        extends SchemaDefinitionProcessor
+    {
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, SchemaDefinition object,
+                                  StringBuilder builder )
+        {
+            // Just process schema elements
+            this.processSchemaElements( aggregator, object, builder );
+        }
+    }
+
+    public static class SQLiteColumnDefinitionProcessor
+        extends ColumnDefinitionProcessor
+    {
+        private final Map<Class<?>, String> _autoGenDataTypes;
+
+        public SQLiteColumnDefinitionProcessor( Map<Class<?>, String> autoGenDataTypes )
+        {
+            Objects.requireNonNull( autoGenDataTypes, "Data type serial names" );
+            this._autoGenDataTypes = autoGenDataTypes;
+        }
+
+        @Override
+        protected void processDataType( SQLProcessorAggregator aggregator, ColumnDefinition object,
+                                        StringBuilder builder )
+        {
+            AutoGenerationPolicy autoGenPolicy = object.getAutoGenerationPolicy();
+            if( autoGenPolicy == null )
+            {
+                super.processDataType( aggregator, object, builder );
+            }
+            else
+            {
+                // SQLite can't handle the ALWAYS strategy
+                if( AutoGenerationPolicy.BY_DEFAULT.equals( autoGenPolicy ) )
+                {
+                    // SQLite MUST use INTEGER type when autogenerated
+                    Class<?> dtClass = object.getDataType().getClass();
+                    Boolean success = false;
+                    for( Map.Entry<Class<?>, String> entry : this._autoGenDataTypes.entrySet() )
+                    {
+                        success = entry.getKey().isAssignableFrom( dtClass );
+                        if( success )
+                        {
+                            builder.append( entry.getValue() );
+                            break;
+                        }
+                    }
+                    if( !success )
+                    {
+                        throw new UnsupportedOperationException( "Unsupported column data type "
+                                                                 + object.getDataType()
+                                                                 + " for auto-generated column." );
+                    }
+                }
+                else
+                {
+                    throw new UnsupportedOperationException( "Unsupported auto generation policy: "
+                                                             + autoGenPolicy
+                                                             + "." );
+                }
+            }
+        }
+
+        @Override
+        protected void processMayBeNull( ColumnDefinition object, StringBuilder builder )
+        {
+            // Nothing to do - auto generation policy handled in data type orc
+        }
+
+        @Override
+        protected void processAutoGenerationPolicy( ColumnDefinition object, StringBuilder builder )
+        {
+            // Nothing to do - auto generation policy handled in data type orc
+        }
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/sqlite/SQLiteProcessor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/sqlite/SQLiteProcessor.java
new file mode 100644
index 0000000..d013c2c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/sqlite/SQLiteProcessor.java
@@ -0,0 +1,82 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.transformation.sqlite;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameFunction;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.BigInt;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SQLInteger;
+import org.apache.polygene.library.sql.generator.grammar.common.datatypes.SmallInt;
+import org.apache.polygene.library.sql.generator.grammar.definition.schema.SchemaDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableElementList;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropSchemaStatement;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefaultSQLProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.NoOpProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.mysql.TableProcessing;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.sqlite.DefinitionProcessing.SQLListeTableElementListProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.sqlite.DefinitionProcessing.SQLiteColumnDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.sqlite.DefinitionProcessing.SQLiteSchemaDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+public class SQLiteProcessor
+    extends DefaultSQLProcessor
+{
+
+    private static final Map<Class<? extends Typeable<?>>, SQLProcessor> _defaultProcessors;
+
+    static
+    {
+        Map<Class<? extends Typeable<?>>, SQLProcessor> processors = new HashMap<Class<? extends Typeable<?>>, SQLProcessor>(
+            DefaultSQLProcessor.getDefaultProcessors() );
+
+        // SQLite does not understand schema-qualified table names (or anything related to schemas)
+        processors.put( TableNameDirect.class, new TableProcessing.MySQLTableNameDirectProcessor() );
+        processors.put( TableNameFunction.class, new TableProcessing.MySQLTableNameFunctionProcessor() );
+
+        // Only process schema elements from schema definition, and ignore drop schema statements
+        processors.put( SchemaDefinition.class, new SQLiteSchemaDefinitionProcessor() );
+        processors.put( DropSchemaStatement.class, new NoOpProcessor() );
+
+        // SQLite MUST use INTEGER PRIMARY KEY AUTOINCREMENT type when autogenerated
+        // see http://www.sqlite.org/autoinc.html
+
+        // Override default table element list support
+        processors.put( TableElementList.class, new SQLListeTableElementListProcessor() );
+
+        // Override default column definition support
+        Map<Class<?>, String> autoGenDataTypes = new HashMap<Class<?>, String>();
+        autoGenDataTypes.put( BigInt.class, "INTEGER PRIMARY KEY AUTOINCREMENT" );
+        autoGenDataTypes.put( SQLInteger.class, "INTEGER PRIMARY KEY AUTOINCREMENT" );
+        autoGenDataTypes.put( SmallInt.class, "INTEGER PRIMARY KEY AUTOINCREMENT" );
+        processors.put( ColumnDefinition.class, new SQLiteColumnDefinitionProcessor( autoGenDataTypes ) );
+
+        _defaultProcessors = processors;
+    }
+
+    public SQLiteProcessor( SQLVendor vendor )
+    {
+        super( vendor, _defaultProcessors );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/DefaultVendor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/DefaultVendor.java
new file mode 100644
index 0000000..c5f96dd
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/DefaultVendor.java
@@ -0,0 +1,254 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.vendor;
+
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLStatement;
+import org.apache.polygene.library.sql.generator.grammar.factories.BooleanFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.ColumnsFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.DataTypeFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.DefinitionFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.LiteralFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.ManipulationFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.ModificationFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.QueryFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.TableReferenceFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.factories.DefaultBooleanFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.factories.DefaultColumnsFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.factories.DefaultDataTypeFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.factories.DefaultDefinitionFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.factories.DefaultLiteralFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.factories.DefaultManipulationFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.factories.DefaultModificationFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.factories.DefaultQueryFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.factories.DefaultTableRefFactory;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefaultSQLProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DefaultVendor
+    implements SQLVendor
+{
+
+    protected interface ProcessorCallback
+    {
+        SQLProcessorAggregator get( SQLVendor vendor );
+    }
+
+    protected interface Callback<T>
+    {
+        T get( SQLVendor vendor, SQLProcessorAggregator processor );
+    }
+
+    protected static final Callback<BooleanFactory> BOOLEAN_FACTORY = new Callback<BooleanFactory>()
+    {
+        public BooleanFactory get( SQLVendor vendor, SQLProcessorAggregator processor )
+        {
+            return new DefaultBooleanFactory( vendor, processor );
+        }
+    };
+
+    protected static final Callback<ColumnsFactory> COLUMNS_FACTORY = new Callback<ColumnsFactory>()
+    {
+        public ColumnsFactory get( SQLVendor vendor, SQLProcessorAggregator processor )
+        {
+            return new DefaultColumnsFactory( vendor, processor );
+        }
+    };
+    protected static final Callback<LiteralFactory> LITERAL_FACTORY = new Callback<LiteralFactory>()
+    {
+        public LiteralFactory get( SQLVendor vendor, SQLProcessorAggregator processor )
+        {
+            return new DefaultLiteralFactory( vendor, processor );
+        }
+    };
+
+    protected static final Callback<ModificationFactory> MODIFICATION_FACTORY = new Callback<ModificationFactory>()
+    {
+        public ModificationFactory get( SQLVendor vendor, SQLProcessorAggregator processor )
+        {
+            return new DefaultModificationFactory( vendor, processor );
+        }
+    };
+
+    protected static final Callback<QueryFactory> QUERY_FACTORY = new Callback<QueryFactory>()
+    {
+        public QueryFactory get( SQLVendor vendor, SQLProcessorAggregator processor )
+        {
+            return new DefaultQueryFactory( vendor, processor );
+        }
+    };
+
+    protected static final Callback<TableReferenceFactory> TABLE_REFERENCE_FACTORY = new Callback<TableReferenceFactory>()
+    {
+        public TableReferenceFactory get( SQLVendor vendor, SQLProcessorAggregator processor )
+        {
+            return new DefaultTableRefFactory( vendor, processor );
+        }
+    };
+
+    protected static final Callback<DefinitionFactory> DEFINITION_FACTORY = new Callback<DefinitionFactory>()
+    {
+        public DefinitionFactory get( SQLVendor vendor, SQLProcessorAggregator processor )
+        {
+            return new DefaultDefinitionFactory( vendor, processor );
+        }
+    };
+
+    protected static final Callback<ManipulationFactory> MANIPULATION_FACTORY = new Callback<ManipulationFactory>()
+    {
+        public ManipulationFactory get( SQLVendor vendor, SQLProcessorAggregator processor )
+        {
+            return new DefaultManipulationFactory( vendor, processor );
+        }
+    };
+
+    protected static final Callback<DataTypeFactory> DATA_TYPE_FACTORY = new Callback<DataTypeFactory>()
+    {
+        public DataTypeFactory get( SQLVendor vendor, SQLProcessorAggregator processor )
+        {
+            return new DefaultDataTypeFactory( vendor, processor );
+        }
+    };
+
+    protected static final ProcessorCallback DEFAULT_PROCESSOR = new ProcessorCallback()
+    {
+        public SQLProcessorAggregator get( SQLVendor vendor )
+        {
+            return new DefaultSQLProcessor( vendor );
+        }
+    };
+
+    private final QueryFactory _queryFactory;
+
+    private final BooleanFactory _booleanFactory;
+
+    private final TableReferenceFactory _fromFactory;
+
+    private final LiteralFactory _literalFactory;
+
+    private final ColumnsFactory _columnsFactory;
+
+    private final ModificationFactory _modificationFactory;
+
+    private final DefinitionFactory _definitionFactory;
+
+    private final ManipulationFactory _manipulationFactory;
+
+    private final DataTypeFactory _dataTypeFactory;
+
+    private final SQLProcessorAggregator _processor;
+
+    public DefaultVendor()
+    {
+        this( DEFAULT_PROCESSOR );
+    }
+
+    protected DefaultVendor( ProcessorCallback processor )
+    {
+        this( processor, BOOLEAN_FACTORY, COLUMNS_FACTORY, LITERAL_FACTORY, MODIFICATION_FACTORY, QUERY_FACTORY,
+              TABLE_REFERENCE_FACTORY, DEFINITION_FACTORY, MANIPULATION_FACTORY, DATA_TYPE_FACTORY );
+    }
+
+    protected DefaultVendor( ProcessorCallback processor, Callback<? extends BooleanFactory> booleanFactory,
+                             Callback<? extends ColumnsFactory> columnsFactory, Callback<? extends LiteralFactory> literalFactory,
+                             Callback<? extends ModificationFactory> modificationFactory, Callback<? extends QueryFactory> queryFactory,
+                             Callback<? extends TableReferenceFactory> tableReferenceFactory,
+                             Callback<? extends DefinitionFactory> definitionFactory,
+                             Callback<? extends ManipulationFactory> manipulationFactory, Callback<? extends DataTypeFactory> dataTypeFactory )
+    {
+        Objects.requireNonNull( processor, "processor" );
+
+        this._processor = processor.get( this );
+        this._booleanFactory = booleanFactory.get( this, this._processor );
+        this._columnsFactory = columnsFactory.get( this, this._processor );
+        this._literalFactory = literalFactory.get( this, this._processor );
+        this._queryFactory = queryFactory.get( this, this._processor );
+        this._modificationFactory = modificationFactory.get( this, this._processor );
+        this._fromFactory = tableReferenceFactory.get( this, this._processor );
+        this._definitionFactory = definitionFactory.get( this, this._processor );
+        this._manipulationFactory = manipulationFactory.get( this, this._processor );
+        this._dataTypeFactory = dataTypeFactory.get( this, this._processor );
+    }
+
+    /**
+     * Note that exactly one string builder is allocated for each statement.
+     */
+    public String toString( SQLStatement statement )
+    {
+        StringBuilder builder = new StringBuilder();
+        this._processor.process( (Typeable<?>) statement, builder );
+        return builder.toString();
+    }
+
+    public QueryFactory getQueryFactory()
+    {
+        return this._queryFactory;
+    }
+
+    public BooleanFactory getBooleanFactory()
+    {
+        return this._booleanFactory;
+    }
+
+    public TableReferenceFactory getTableReferenceFactory()
+    {
+        return this._fromFactory;
+    }
+
+    public LiteralFactory getLiteralFactory()
+    {
+        return this._literalFactory;
+    }
+
+    public ColumnsFactory getColumnsFactory()
+    {
+        return this._columnsFactory;
+    }
+
+    public ModificationFactory getModificationFactory()
+    {
+        return this._modificationFactory;
+    }
+
+    public DefinitionFactory getDefinitionFactory()
+    {
+        return this._definitionFactory;
+    }
+
+    public ManipulationFactory getManipulationFactory()
+    {
+        return this._manipulationFactory;
+    }
+
+    public DataTypeFactory getDataTypeFactory()
+    {
+        return this._dataTypeFactory;
+    }
+
+    protected SQLProcessorAggregator getProcessor()
+    {
+        return this._processor;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/derby/DerbyVendorImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/derby/DerbyVendorImpl.java
new file mode 100644
index 0000000..d7f47a5
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/derby/DerbyVendorImpl.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.vendor.derby;
+
+import org.apache.polygene.library.sql.generator.implementation.transformation.derby.DerbyProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.implementation.vendor.DefaultVendor;
+import org.apache.polygene.library.sql.generator.vendor.DerbyVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+public class DerbyVendorImpl extends DefaultVendor
+    implements DerbyVendor
+{
+
+    protected static final ProcessorCallback DERBY_PROCESSOR = new ProcessorCallback()
+    {
+        public SQLProcessorAggregator get( SQLVendor vendor )
+        {
+            return new DerbyProcessor( vendor );
+        }
+    };
+
+    public DerbyVendorImpl()
+    {
+        super( DERBY_PROCESSOR );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/h2/H2VendorImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/h2/H2VendorImpl.java
new file mode 100644
index 0000000..c9f1d4a
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/h2/H2VendorImpl.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.vendor.h2;
+
+import org.apache.polygene.library.sql.generator.implementation.transformation.h2.H2Processor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.implementation.vendor.DefaultVendor;
+import org.apache.polygene.library.sql.generator.vendor.H2Vendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+public class H2VendorImpl extends DefaultVendor
+    implements H2Vendor
+{
+
+    protected static final ProcessorCallback H2_PROCESSOR = new ProcessorCallback()
+    {
+
+        public SQLProcessorAggregator get( SQLVendor vendor )
+        {
+            return new H2Processor( vendor );
+        }
+    };
+
+    public H2VendorImpl()
+    {
+        super( H2_PROCESSOR );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/mysql/MySQLVendorImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/mysql/MySQLVendorImpl.java
new file mode 100644
index 0000000..a497e59
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/mysql/MySQLVendorImpl.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.vendor.mysql;
+
+import org.apache.polygene.library.sql.generator.implementation.transformation.mysql.MySQLProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.implementation.vendor.DefaultVendor;
+import org.apache.polygene.library.sql.generator.vendor.MySQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class MySQLVendorImpl extends DefaultVendor
+    implements MySQLVendor
+{
+
+    protected static final ProcessorCallback MYSQL_PROCESSOR = new ProcessorCallback()
+    {
+        public SQLProcessorAggregator get( SQLVendor vendor )
+        {
+            return new MySQLProcessor( vendor );
+        }
+    };
+
+    private boolean _legacyLimit;
+
+    public MySQLVendorImpl()
+    {
+        super( MYSQL_PROCESSOR );
+
+        this._legacyLimit = false;
+    }
+
+    public boolean legacyLimit()
+    {
+        return this._legacyLimit;
+    }
+
+    public void setLegacyLimit( boolean useLegacyLimit )
+    {
+        this._legacyLimit = useLegacyLimit;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/pgsql/PostgreSQLVendorImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/pgsql/PostgreSQLVendorImpl.java
new file mode 100644
index 0000000..e663ed9
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/pgsql/PostgreSQLVendorImpl.java
@@ -0,0 +1,108 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.vendor.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.factories.ModificationFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.pgsql.PgSQLDataTypeFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.pgsql.PgSQLManipulationFactory;
+import org.apache.polygene.library.sql.generator.implementation.grammar.factories.pgsql.PgSQLDataTypeFactoryImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.factories.pgsql.PgSQLManipulationFactoryImpl;
+import org.apache.polygene.library.sql.generator.implementation.grammar.factories.pgsql.PgSQLModificationFactoryImpl;
+import org.apache.polygene.library.sql.generator.implementation.transformation.pgsql.PostgreSQLProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.implementation.vendor.DefaultVendor;
+import org.apache.polygene.library.sql.generator.vendor.PostgreSQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class PostgreSQLVendorImpl extends DefaultVendor
+    implements PostgreSQLVendor
+{
+    protected static final Callback<PgSQLDataTypeFactory> PG_DATA_TYPE_FACTORY =
+        new Callback<PgSQLDataTypeFactory>()
+        {
+            public PgSQLDataTypeFactory get( SQLVendor vendor, SQLProcessorAggregator processor )
+            {
+                return new PgSQLDataTypeFactoryImpl( (PostgreSQLVendor) vendor, processor );
+            }
+        };
+
+    protected static final Callback<PgSQLManipulationFactory> PG_MANIPULATION_FACTORY =
+        new Callback<PgSQLManipulationFactory>()
+        {
+            public PgSQLManipulationFactory
+            get( SQLVendor vendor, SQLProcessorAggregator processor )
+            {
+                return new PgSQLManipulationFactoryImpl( (PostgreSQLVendor) vendor, processor );
+            }
+        };
+
+    protected static final Callback<ModificationFactory> PG_MODIFICATION_FACTORY =
+        new Callback<ModificationFactory>()
+        {
+            public ModificationFactory get( SQLVendor vendor, SQLProcessorAggregator processor )
+            {
+                return new PgSQLModificationFactoryImpl( (PostgreSQLVendor) vendor, processor );
+            }
+        };
+
+    protected static final ProcessorCallback PG_PROCESSOR = new ProcessorCallback()
+    {
+        public SQLProcessorAggregator get( SQLVendor vendor )
+        {
+            return new PostgreSQLProcessor( vendor );
+        }
+    };
+
+    private boolean _legacyOffsetAndLimit;
+
+    public PostgreSQLVendorImpl()
+    {
+        super( PG_PROCESSOR, BOOLEAN_FACTORY, COLUMNS_FACTORY, LITERAL_FACTORY,
+               PG_MODIFICATION_FACTORY, QUERY_FACTORY,
+               TABLE_REFERENCE_FACTORY, DEFINITION_FACTORY, PG_MANIPULATION_FACTORY,
+               PG_DATA_TYPE_FACTORY );
+        this._legacyOffsetAndLimit = false;
+    }
+
+    @Override
+    public PgSQLDataTypeFactory getDataTypeFactory()
+    {
+        return (PgSQLDataTypeFactory) super.getDataTypeFactory();
+    }
+
+    @Override
+    public PgSQLManipulationFactory getManipulationFactory()
+    {
+        return (PgSQLManipulationFactory) super.getManipulationFactory();
+    }
+
+    public boolean legacyOffsetAndLimit()
+    {
+        return this._legacyOffsetAndLimit;
+    }
+
+    public void setLegacyOffsetAndLimit( boolean useLegacyOffsetAndLimit )
+    {
+        this._legacyOffsetAndLimit = useLegacyOffsetAndLimit;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/sqlite/SQLiteVendorImpl.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/sqlite/SQLiteVendorImpl.java
new file mode 100644
index 0000000..e5f5116
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/vendor/sqlite/SQLiteVendorImpl.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.library.sql.generator.implementation.vendor.sqlite;
+
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.implementation.transformation.sqlite.SQLiteProcessor;
+import org.apache.polygene.library.sql.generator.implementation.vendor.DefaultVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLiteVendor;
+
+public class SQLiteVendorImpl extends DefaultVendor
+    implements SQLiteVendor
+{
+
+    protected static final ProcessorCallback SQLITE_PROCESSOR = new ProcessorCallback()
+    {
+
+        public SQLProcessorAggregator get( SQLVendor vendor )
+        {
+            return new SQLiteProcessor( vendor );
+        }
+    };
+
+    public SQLiteVendorImpl()
+    {
+        super( SQLITE_PROCESSOR );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/DerbyVendor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/DerbyVendor.java
new file mode 100644
index 0000000..04c3303
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/DerbyVendor.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.library.sql.generator.vendor;
+
+public interface DerbyVendor
+    extends SQLVendor
+{
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/H2Vendor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/H2Vendor.java
new file mode 100644
index 0000000..59e8f5a
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/H2Vendor.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.library.sql.generator.vendor;
+
+public interface H2Vendor
+    extends SQLVendor
+{
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/MySQLVendor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/MySQLVendor.java
new file mode 100644
index 0000000..0cb638c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/MySQLVendor.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.library.sql.generator.vendor;
+
+/**
+ * This is vendor for MySQL database. MySQL typically does not understand schema-qualified names, so this vendor doesn't
+ * process any schema name it encounters when creating a SQL string.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface MySQLVendor
+    extends SQLVendor
+{
+
+    /**
+     * <p>
+     * Returns whether the legacy LIMIT expression is used instead of the of the newer LIMIT/OFFSET. In a legacy syntax,
+     * the {@code LIMIT <n> OFFSET <skip>} is written as {@code LIMIT <skip>, <n> } instead. This method is not
+     * thread-safe.
+     * </p>
+     *
+     * @return {@code true} if the legacy LIMIT expressions are used; {@code false} otherwise.
+     */
+    boolean legacyLimit();
+
+    /**
+     * <p>
+     * Sets the switch to use legacy LIMIT expression instead of the newer LIMIT/OFFSET expressions. In a legacy syntax,
+     * the {@code LIMIT <n> OFFSET <skip>} is written as {@code LIMIT <skip>, <n> } instead. Set this to true only if
+     * you really require it. This method is not thread-safe.
+     * </p>
+     *
+     * @param useLegacyLimit Whether to use legacy LIMIT expression instead of the newer LIMIT/OFFSET expressions.
+     */
+    void setLegacyLimit( boolean useLegacyLimit );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/PostgreSQLVendor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/PostgreSQLVendor.java
new file mode 100644
index 0000000..13b1eaa
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/PostgreSQLVendor.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.library.sql.generator.vendor;
+
+import org.apache.polygene.library.sql.generator.grammar.factories.pgsql.PgSQLDataTypeFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.pgsql.PgSQLManipulationFactory;
+
+/**
+ * This is vendor for PostgreSQL database. PostgreSQL provides some extra SQL syntax elements for queries (notably
+ * {@code LIMIT} and {@code OFFSET} clauses), and this vendor gives access to factory, which enables the creation of
+ * these elements.
+ *
+ * @author Stanislav Muhametsin
+ */
+public interface PostgreSQLVendor
+    extends SQLVendor
+{
+    /**
+     * Returns the data type factory, which knows to create PostgreSQL-specific data types as well as pre-defined
+     * standard ones.
+     */
+    PgSQLDataTypeFactory getDataTypeFactory();
+
+    /**
+     * Returns the manipulation factory, which knows to create PostgreSQL-specific data manipulation statements.
+     */
+    PgSQLManipulationFactory getManipulationFactory();
+
+    /**
+     * Returns whether the legacy (pre-8.4) OFFSET/LIMIT expressions are used instead of the OFFSET/FETCH defined in the
+     * SQL 2008 standard. For more information, see http://www.postgresql.org/docs/8.3/static/sql-select.html#SQL-LIMIT
+     * . This method is not thread-safe.
+     *
+     * @return {@code true} if the legacy OFFSET/LIMIT expressions are used; {@code false} otherwise.
+     */
+    boolean legacyOffsetAndLimit();
+
+    /**
+     * Sets the switch to use legacy LIMIT/OFFSET expressions instead of the OFFSET/FETCH expressions of the SQL 2008
+     * standard. This is necessary only for pre-8.4 PgSQL databases. For more information, see
+     * http://www.postgresql.org/docs/8.3/static/sql-select.html#SQL-LIMIT . This method is not thread-safe.
+     *
+     * @param useLegacyOffsetAndLimit Whether to use legacy LIMIT/OFFSET expressions instead of the OFFSET/FETCH
+     *                                expressions defined in the SQL 2008 standard.
+     */
+    void setLegacyOffsetAndLimit( boolean useLegacyOffsetAndLimit );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/SQLVendor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/SQLVendor.java
new file mode 100644
index 0000000..e11da0c
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/SQLVendor.java
@@ -0,0 +1,137 @@
+/*
+ *  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.polygene.library.sql.generator.vendor;
+
+import org.apache.polygene.library.sql.generator.grammar.common.SQLStatement;
+import org.apache.polygene.library.sql.generator.grammar.factories.BooleanFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.ColumnsFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.DataTypeFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.DefinitionFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.LiteralFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.ManipulationFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.ModificationFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.QueryFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.TableReferenceFactory;
+import org.apache.polygene.library.sql.generator.grammar.query.QuerySpecification;
+
+/**
+ * This is the base API interface for all SQLVendors to implement. It gives the means to acquire factories to create SQL
+ * syntax elements. Additionally, the vendor creates the textual representation of these syntax elements so that the
+ * query may be passed directly to database, for example, through JDBC.
+ *
+ * @author Stanislav Muhametsin
+ * @see MySQLVendor
+ * @see PostgreSQLVendor
+ * @see QueryFactory
+ * @see BooleanFactory
+ * @see TableReferenceFactory
+ * @see LiteralFactory
+ * @see ColumnsFactory
+ * @see ModificationFactory
+ * @see #toString(SQLStatement)
+ */
+public interface SQLVendor
+{
+
+    /**
+     * Returns the query factory of this vendor.
+     *
+     * @return The query factory of this vendor.
+     * @see QueryFactory
+     * @see QuerySpecification
+     */
+    QueryFactory getQueryFactory();
+
+    /**
+     * Returns the boolean factory for this vendor.
+     *
+     * @return The boolean factory for this vendor.
+     * @see BooleanFactory
+     */
+    BooleanFactory getBooleanFactory();
+
+    /**
+     * Returns the table reference factory for this vendor.
+     *
+     * @return The table reference factory for this vendor.
+     * @see TableReferenceFactory
+     */
+    TableReferenceFactory getTableReferenceFactory();
+
+    /**
+     * Returns the literal factory for this vendor.
+     *
+     * @return The literal factory for this vendor.
+     * @see LiteralFactory
+     */
+    LiteralFactory getLiteralFactory();
+
+    /**
+     * Returns the columns factory for this vendor.
+     *
+     * @return The columns factory for this vendor.
+     * @see ColumnsFactory
+     */
+    ColumnsFactory getColumnsFactory();
+
+    /**
+     * Returns the factory to create modification statements for this vendor.
+     *
+     * @return The factory to create modification statements for this vendor.
+     * @see ModificationFactory
+     */
+    ModificationFactory getModificationFactory();
+
+    /**
+     * Returns the factory to create definition statements ({@code CREATE SCHEMA/TABLE/VIEW/etc}) for this vendor.
+     *
+     * @return The factory to create definition statements for this vendor.
+     * @see DefinitionFactory
+     */
+    DefinitionFactory getDefinitionFactory();
+
+    /**
+     * Returns the factory to create manipulation statements ({@code DROP/ALTER SCHEMA/TABLE/etc}) for this vendor.
+     *
+     * @return The factory to create manipulation statements.
+     * @see ManipulationFactory
+     */
+    ManipulationFactory getManipulationFactory();
+
+    /**
+     * Returns the factory to create syntax elements for SQL data types compatible with this vendor.
+     *
+     * @return The factory to create syntax elements for SQL data types.
+     * @see DataTypeFactory
+     */
+    DataTypeFactory getDataTypeFactory();
+
+    /**
+     * Takes the {@link SQLStatement} (typically either a query, or a modification statement) and produces a textual SQL
+     * statement out of it.
+     *
+     * @param statement The {@link SQLStatement} to process.
+     * @return The textual SQL statement to be used directly with database.
+     * @throws UnsupportedElementException If during parsing this vendor encounters some SQL syntax element not
+     *                                     understood by this vendor.
+     * @see SQLStatement
+     */
+    String toString( SQLStatement statement );
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/SQLVendorProvider.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/SQLVendorProvider.java
new file mode 100644
index 0000000..d3332a5
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/SQLVendorProvider.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.library.sql.generator.vendor;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.ServiceLoader;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class provides easy way of acquiring vendors for specific databases.
+ *
+ * @author Stanislav Muhametsin
+ */
+public class SQLVendorProvider
+{
+    /**
+     * <p>
+     * Creates a new vendor. If one passes {@link SQLVendor} as a parameter, it will return the default vendor-neutral
+     * implementation.
+     * </p>
+     * <p>
+     * Invoking this statement is equivalent to calling {@code new ServiceLoader().firstProvider( vendorClass); }.
+     *
+     * @param <VendorType> The type of the vendor.
+     * @param vendorClass  The class of the vendor.
+     * @return The vendor of a given class.
+     * @throws IOException If {@link ServiceLoader} throws {@link IOException}.
+     * @see ServiceLoader
+     */
+    public static <VendorType extends SQLVendor> VendorType createVendor( Class<VendorType> vendorClass )
+        throws IOException
+    {
+        LoggerFactory.getLogger( SQLVendorProvider.class ).info( "Trying to load implementation for " + vendorClass.getName() );
+        ServiceLoader<VendorType> load = ServiceLoader.load( vendorClass );
+        Iterator<VendorType> vendorTypeIterator = load.iterator();
+        if( vendorTypeIterator.hasNext() )
+        {
+            return vendorTypeIterator.next();
+        }
+        throw new InternalError( "ServiceLoader of SQLVendor implementations is not finding the META-INF/services" );
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/SQLiteVendor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/SQLiteVendor.java
new file mode 100644
index 0000000..ba7c961
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/SQLiteVendor.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.library.sql.generator.vendor;
+
+public interface SQLiteVendor
+    extends SQLVendor
+{
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/UnsupportedElementException.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/UnsupportedElementException.java
new file mode 100644
index 0000000..f07b7a8
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/UnsupportedElementException.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.library.sql.generator.vendor;
+
+import org.apache.polygene.library.sql.generator.grammar.common.SQLStatement;
+
+/**
+ * This exception will typically be thrown by
+ * {@link SQLVendor#toString(SQLStatement)} method when the vendor encounters a
+ * SQL syntax element that the vendor doesn't understand.
+ *
+ * @author Stanislav Muhametsin
+ */
+public class UnsupportedElementException extends RuntimeException
+{
+
+    private static final long serialVersionUID = -5331011803322815958L;
+
+    private final Object _element;
+
+    public UnsupportedElementException( String msg )
+    {
+        this( msg, null );
+    }
+
+    public UnsupportedElementException( String msg, Object element )
+    {
+        super( msg );
+        this._element = element;
+    }
+
+    public Object getElement()
+    {
+        return this._element;
+    }
+}
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/package-info.java
new file mode 100644
index 0000000..1719927
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/vendor/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ *
+ *
+ */
+/**
+ * This package provides an API for SQLVendors to implement, and a way to load different vendors dynamically. The vendor will give access to factories in package org.sql.generation.api.grammar.factories , which will enable users to create SQL syntax elements. Vendor is also responsible for creating a textual representation (String) of a SQL syntax structure generated with these factories.
+ */
+package org.apache.polygene.library.sql.generator.vendor;
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.DerbyVendor b/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.DerbyVendor
new file mode 100644
index 0000000..551f610
--- /dev/null
+++ b/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.DerbyVendor
@@ -0,0 +1,17 @@
+#  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.
+
+org.apache.polygene.library.sql.generator.implementation.vendor.derby.DerbyVendorImpl
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.H2Vendor b/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.H2Vendor
new file mode 100644
index 0000000..f337ac1
--- /dev/null
+++ b/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.H2Vendor
@@ -0,0 +1,17 @@
+#  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.
+
+org.apache.polygene.library.sql.generator.implementation.vendor.h2.H2VendorImpl
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.MySQLVendor b/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.MySQLVendor
new file mode 100644
index 0000000..55e13de
--- /dev/null
+++ b/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.MySQLVendor
@@ -0,0 +1,17 @@
+#  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.
+
+org.apache.polygene.library.sql.generator.implementation.vendor.mysql.MySQLVendorImpl
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.PostgreSQLVendor b/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.PostgreSQLVendor
new file mode 100644
index 0000000..8917bb7
--- /dev/null
+++ b/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.PostgreSQLVendor
@@ -0,0 +1,17 @@
+#  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.
+
+org.apache.polygene.library.sql.generator.implementation.vendor.pgsql.PostgreSQLVendorImpl
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.SQLVendor b/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.SQLVendor
new file mode 100644
index 0000000..8fabefb
--- /dev/null
+++ b/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.SQLVendor
@@ -0,0 +1,17 @@
+#  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.
+
+org.apache.polygene.library.sql.generator.implementation.vendor.DefaultVendor
\ No newline at end of file
diff --git a/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.SQLiteVendor b/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.SQLiteVendor
new file mode 100644
index 0000000..a5cd9ac
--- /dev/null
+++ b/libraries/sql-generator/src/main/resources/META-INF/services/org.apache.polygene.library.sql.generator.vendor.SQLiteVendor
@@ -0,0 +1,17 @@
+#  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.
+
+org.apache.polygene.library.sql.generator.implementation.vendor.sqlite.SQLiteVendorImpl
\ No newline at end of file
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/AbstractDataDefinitionTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/AbstractDataDefinitionTest.java
new file mode 100644
index 0000000..279c799
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/AbstractDataDefinitionTest.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.TableDefinitionBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.definition.TableElementListBuilder;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.AutoGenerationPolicy;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ConstraintCharacteristics;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.MatchType;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ReferentialAction;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.TableDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.UniqueSpecification;
+import org.apache.polygene.library.sql.generator.grammar.factories.DataTypeFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.DefinitionFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.TableReferenceFactory;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.junit.Test;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class AbstractDataDefinitionTest extends AbstractSQLSyntaxTest
+{
+
+    @Test
+    public void definition1()
+        throws Exception
+    {
+        // @formatter:off
+        /*
+         * CREATE TABLE qi4j_schema.qname_9
+         * (
+         * qname_id integer NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+         * entity_pk bigint NOT NULL,
+         * parent_qname integer,
+         * collection_path ltree NOT NULL,
+         * qname_value integer,
+         * PRIMARY KEY (qname_id, entity_pk),
+         * CONSTRAINT qname_9_parent_qname_fkey FOREIGN KEY (parent_qname, entity_pk)
+         * REFERENCES qi4j_schema.all_qnames (qname_id, entity_pk) MATCH SIMPLE
+         * ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+         * CONSTRAINT qname_9_qname_id_fkey FOREIGN KEY (qname_id, entity_pk)
+         * REFERENCES qi4j_schema.all_qnames (qname_id, entity_pk) MATCH SIMPLE
+         * ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+         * CONSTRAINT qname_9_qname_value_fkey FOREIGN KEY (qname_value)
+         * REFERENCES qi4j_schema.used_classes (used_class_id)
+         * ON UPDATE CASCADE ON DELETE RESTRICT
+         * )
+         */
+
+        SQLVendor vendor = this.getVendor();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+        DefinitionFactory d = vendor.getDefinitionFactory();
+        DataTypeFactory dt = vendor.getDataTypeFactory();
+        String schemaName = "qi4j_schema";
+
+        TableDefinitionBuilder builder = d.createTableDefinitionBuilder();
+        builder
+            .setTableName( t.tableName( schemaName, "qname_9" ) );
+
+        TableElementListBuilder cBuilder = d.createTableElementListBuilder();
+        cBuilder
+            .addTableElement( d.createColumnDefinition( "qname_id", dt.integer(), false, AutoGenerationPolicy.BY_DEFAULT ) )
+            .addTableElement( d.createColumnDefinition( "entity_pk", dt.bigInt(), false ) )
+            .addTableElement( d.createColumnDefinition( "parent_qname", dt.integer() ) )
+            .addTableElement( d.createColumnDefinition( "collection_path", dt.userDefined( "ltree" ), false ) )
+            .addTableElement( d.createColumnDefinition( "qname_value", dt.integer() ) )
+            .addTableElement( d.createTableConstraintDefinition(
+                d.createUniqueConstraintBuilder()
+                 .setUniqueness( UniqueSpecification.PRIMARY_KEY )
+                 .addColumns( "qname_id", "entity_pk" )
+                 .createExpression() )
+                            )
+            .addTableElement(
+                d.createTableConstraintDefinition(
+                    "qname_9_parent_qname_fkey",
+                    d.createForeignKeyConstraintBuilder()
+                     .addSourceColumns( "parent_qname", "entity_pk" )
+                     .setTargetTableName( t.tableName( schemaName, "all_qnames" ) )
+                     .addTargetColumns( "qname_id", "entity_pk" )
+                     .setMatchType( MatchType.SIMPLE )
+                     .setOnUpdate( ReferentialAction.CASCADE )
+                     .setOnDelete( ReferentialAction.CASCADE )
+                     .createExpression(),
+                    ConstraintCharacteristics.INITIALLY_DEFERRED_DEFERRABLE
+                                                 )
+                            )
+            .addTableElement(
+                d.createTableConstraintDefinition(
+                    "qname_9_qname_id_fkey",
+                    d.createForeignKeyConstraintBuilder()
+                     .addSourceColumns( "qname_id", "entity_pk" )
+                     .setTargetTableName( t.tableName( schemaName, "all_qnames" ) )
+                     .addTargetColumns( "qname_id", "entity_pk" )
+                     .setMatchType( MatchType.SIMPLE )
+                     .setOnUpdate( ReferentialAction.CASCADE )
+                     .setOnDelete( ReferentialAction.CASCADE )
+                     .createExpression(),
+                    ConstraintCharacteristics.INITIALLY_DEFERRED_DEFERRABLE
+                                                 )
+                            )
+            .addTableElement(
+                d.createTableConstraintDefinition(
+                    "qname_9_qname_value_fkey",
+                    d.createForeignKeyConstraintBuilder()
+                     .addSourceColumns( "qname_value" )
+                     .setTargetTableName( t.tableName( schemaName, "used_classes" ) )
+                     .addTargetColumns( "used_class_id" )
+                     .setOnUpdate( ReferentialAction.CASCADE )
+                     .setOnDelete( ReferentialAction.RESTRICT )
+                     .createExpression()
+                                                 )
+                            );
+
+        builder.setTableContentsSource( cBuilder.createExpression() );
+
+        this.logStatement( "Table definition", vendor, builder.createExpression() );
+
+        // @formatter:on
+    }
+
+    @Test
+    public void definition2()
+        throws Exception
+    {
+        SQLVendor vendor = this.getVendor();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+        DefinitionFactory d = vendor.getDefinitionFactory();
+        DataTypeFactory dt = vendor.getDataTypeFactory();
+
+        String schemaName = "the_schema";
+        String tableName = "the_table";
+        String colPKName = "pk_column";
+        String colValueName = "value_column";
+
+        TableDefinition def = d
+            .createTableDefinitionBuilder()
+            .setTableName( t.tableName( schemaName, tableName ) )
+            .setTableContentsSource(
+                d.createTableElementListBuilder()
+                 .addTableElement( d.createColumnDefinition( colPKName, dt.integer(), false ) )
+                 .addTableElement( d.createColumnDefinition( colValueName, dt.sqlVarChar(), false ) )
+                 .addTableElement(
+                     d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
+                                                         .setUniqueness( UniqueSpecification.PRIMARY_KEY ).addColumns( colPKName )
+                                                         .createExpression() ) )
+                 .addTableElement(
+                     d.createTableConstraintDefinition( d.createUniqueConstraintBuilder()
+                                                         .setUniqueness( UniqueSpecification.UNIQUE ).addColumns( colValueName ).createExpression() ) )
+                 .createExpression() ).createExpression();
+
+        this.logStatement( "Table definition", vendor, def );
+    }
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/AbstractModificationTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/AbstractModificationTest.java
new file mode 100644
index 0000000..379da70
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/AbstractModificationTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012, Stanislav Muhametsin. All Rights Reserved.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.grammar.factories.LiteralFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.ModificationFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.QueryFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.TableReferenceFactory;
+import org.apache.polygene.library.sql.generator.grammar.modification.InsertStatement;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.junit.Test;
+
+public abstract class AbstractModificationTest extends AbstractSQLSyntaxTest
+{
+
+    @Test
+    public void modification1()
+    {
+        // INSERT INTO schema.table
+        // VALUES (5, 'String', SELECT column FROM schema.other_table);
+
+        SQLVendor vendor = this.getVendor();
+
+        QueryFactory q = vendor.getQueryFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+        ModificationFactory m = vendor.getModificationFactory();
+        LiteralFactory l = vendor.getLiteralFactory();
+
+        InsertStatement insert = this.getVendor().getModificationFactory().insert()
+                                     .setTableName( t.tableName( "schema", "table" ) )
+                                     .setColumnSource(
+                                         m.columnSourceByValues().addValues(
+                                             l.n( 5 ),
+                                             l.s( "String" ),
+                                             q.simpleQueryBuilder()
+                                              .select( "column" )
+                                              .from( t.tableName( "schema", "other_table" ) )
+                                              .createExpression()
+                                                                           ).createExpression()
+                                                     )
+                                     .createExpression();
+
+        this.logStatement( "Table modification", vendor, insert );
+    }
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/AbstractQueryTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/AbstractQueryTest.java
new file mode 100644
index 0000000..06c92e9
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/AbstractQueryTest.java
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.ColumnsBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.QuerySpecificationBuilder;
+import org.apache.polygene.library.sql.generator.grammar.builders.query.TableReferenceBuilder;
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+import org.apache.polygene.library.sql.generator.grammar.factories.BooleanFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.ColumnsFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.LiteralFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.QueryFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.TableReferenceFactory;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferenceByName;
+import org.apache.polygene.library.sql.generator.grammar.query.Ordering;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBody;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinType;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.junit.Test;
+
+/**
+ * Contains the tests for various queries to test functionality of parser.
+ * <p>
+ * TODO how to actually verify queries? Currently this only outputs them.
+ *
+ * @author Stanislav Muhametsin
+ */
+public abstract class AbstractQueryTest extends AbstractSQLSyntaxTest
+{
+    protected void logQuery( SQLVendor vendor, QueryExpression query )
+    {
+        this.logStatement( "Query", vendor, query );
+    }
+
+    @Test
+    public void query1()
+        throws Exception
+    {
+        // @formatter:off
+        /*
+        
+          SELECT t0.entity_identity
+          FROM (
+          SELECT DISTINCT t0.entity_pk, t0.entity_identity
+            FROM qi4j.entities t0
+            JOIN qi4j.qname_6 t1 ON (t0.entity_pk = t1.entity_pk AND t1.parent_qname IS NULL)
+            JOIN qi4j.qname_14 t2 ON (t1.qname_id = t2.parent_qname AND t1.entity_pk = t2.entity_pk)
+            JOIN qi4j.qname_15 t3 ON (t2.qname_id = t3.parent_qname AND t2.entity_pk = t3.entity_pk)
+            WHERE t0.entity_type_id IN (3, 4) AND
+            ((t3.qname_value IS NOT NULL AND t3.qname_value = ?) )
+            ) AS t0
+         
+         */
+
+        SQLVendor vendor = this.getVendor();
+
+        QueryFactory q = vendor.getQueryFactory();
+        BooleanFactory b = vendor.getBooleanFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+        LiteralFactory l = vendor.getLiteralFactory();
+        ColumnsFactory c = vendor.getColumnsFactory();
+
+        ColumnsBuilder innerSelectCols = q.columnsBuilder( SetQuantifier.DISTINCT ).addUnnamedColumns(
+            c.colName( "t0", "entity_pk" ), c.colName( "t0", "entity_identity" ) );
+
+        TableReferenceBuilder join = t.tableBuilder(
+            t.table( t.tableName( "qi4j", "entities" ), t.tableAlias( "t0" ) )
+                                                   ).addQualifiedJoin(
+            JoinType.INNER,
+            t.table( t.tableName( "qi4j", "qname_6" ), t.tableAlias( "t1" ) ),
+            t.jc(
+                b.booleanBuilder(
+                    b.eq( c.colName( "t0", "entity_pk" ), c.colName( "t1", "entity_pk" ) )
+                                ).and(
+                    b.isNull( c.colName( "t1", "parent_qname" ) )
+                                     ).createExpression()
+                )
+                                                                     ).addQualifiedJoin(
+            JoinType.INNER,
+            t.table( t.tableName( "qi4j", "qname_14" ), t.tableAlias( "t2" ) ),
+            t.jc(
+                b.booleanBuilder(
+                    b.eq( c.colName( "t1", "qname_id" ), c.colName( "t2", "parent_qname" ) )
+                                ).and(
+                    b.eq( c.colName( "t1", "entity_pk" ), c.colName( "t2", "entity_pk" ) )
+                                     ).createExpression()
+                )
+                                                                                       ).addQualifiedJoin(
+            JoinType.INNER,
+            t.table( t.tableName( "qi4j", "qname_15" ), t.tableAlias( "t3" ) ),
+            t.jc(
+                b.booleanBuilder(
+                    b.eq( c.colName( "t2", "qname_id" ), c.colName( "t3", "parent_qname" ) )
+                                ).and(
+                    b.eq( c.colName( "t2", "entity_pk" ), c.colName( "t3", "entity_pk" ) )
+                                     ).createExpression()
+                )
+                                                                                                         );
+
+        BooleanExpression innerWhere = b.booleanBuilder(
+            b.in( c.colName( "t0", "entity_type_id" ), l.n( 3 ), l.n( 4 ) )
+                                                       ).and( b.isNotNull( c.colName( "t3", "qname_value" ) )
+                                                            ).and( b.eq( c.colName( "t3", "qname_value" ), l.param() )
+                                                                 ).createExpression();
+
+        QuerySpecificationBuilder builder = q.querySpecificationBuilder();
+        builder.setSelect( innerSelectCols );
+        builder.getFrom().addTableReferences( join );
+        builder.getWhere().reset( innerWhere );
+
+        QuerySpecificationBuilder select =
+            q.querySpecificationBuilder();
+        select.getSelect().addUnnamedColumns( c.colName( "t0", "entity_identity" ) );
+        select.getFrom().addTableReferences( t.tableBuilder( t.table( q.createQuery( builder.createExpression() ), t.tableAlias( "t0" ) ) ) );
+
+        QueryExpression query = q.createQuery( q.queryBuilder( select.createExpression() ).createExpression() );
+
+        this.logQuery( vendor, query );
+
+        // @formatter:on
+
+    }
+
+    @Test
+    public void query2()
+        throws Exception
+    {
+        // @formatter:off
+        /*
+          SELECT t0.entity_identity
+          FROM (SELECT DISTINCT t0.entity_pk, t0.entity_identity
+            FROM qi4j.entities t0
+            WHERE t0.entity_type_id IN (3, 4)
+            EXCEPT
+            SELECT DISTINCT t0.entity_pk, t0.entity_identity
+            FROM qi4j.entities t0
+            JOIN qi4j.qname_6 t1 ON (t0.entity_pk = t1.entity_pk AND t1.parent_qname IS NULL)
+            JOIN qi4j.qname_11 t2 ON (t1.qname_id = t2.parent_qname AND t1.entity_pk = t2.entity_pk)
+            LEFT JOIN qi4j.qname_12 t3 ON (t2.qname_id = t3.parent_qname AND t2.entity_pk = t3.entity_pk)
+            LEFT JOIN qi4j.qname_13 t4 ON (t2.qname_id = t4.parent_qname AND t2.entity_pk = t4.entity_pk)
+            WHERE t0.entity_type_id IN (3, 4)
+            GROUP BY t0.entity_pk, t0.entity_identity
+            HAVING COUNT(t2.qname_value) >= 2
+            ORDER BY t0.entity_pk ASC
+          ) AS t0
+        */
+        // @formatter:on
+
+        SQLVendor vendor = this.getVendor();
+
+        QueryFactory q = vendor.getQueryFactory();
+        BooleanFactory b = vendor.getBooleanFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+        LiteralFactory l = vendor.getLiteralFactory();
+        ColumnsFactory c = vendor.getColumnsFactory();
+
+        ColumnReferenceByName innerFirstCol = c.colName( "t0", "entity_pk" );
+        ColumnReferenceByName innerSecondCol = c.colName( "t0", "entity_identity" );
+        ColumnsBuilder innerSelectCols = q.columnsBuilder( SetQuantifier.DISTINCT ).addUnnamedColumns( innerFirstCol,
+                                                                                                       innerSecondCol );
+
+        BooleanExpression where = b.in( c.colName( "t0", "entity_type_id" ), l.n( 3 ), l.n( 4 ) );
+        QuerySpecificationBuilder firstInnerQuery = q.querySpecificationBuilder();
+        firstInnerQuery.setSelect( innerSelectCols );
+
+        firstInnerQuery.getFrom().addTableReferences(
+            t.tableBuilder( t.table( t.tableName( "qi4j", "entities" ), t.tableAlias( "t0" ) ) ) );
+
+        firstInnerQuery.getWhere().reset( where );
+
+        TableReferenceBuilder join = t
+            .tableBuilder( t.table( t.tableName( "qi4j", "entities" ), t.tableAlias( "t0" ) ) )
+            .addQualifiedJoin(
+                JoinType.INNER,
+                t.table( t.tableName( "qi4j", "qname_6" ), t.tableAlias( "t1" ) ),
+                t.jc( b.booleanBuilder( b.eq( c.colName( "t0", "entity_pk" ), c.colName( "t1", "entity_pk" ) ) )
+                       .and( b.isNull( c.colName( "t1", "parent_qname" ) ) ).createExpression() ) )
+            .addQualifiedJoin(
+                JoinType.INNER,
+                t.table( t.tableName( "qi4j", "qname_11" ), t.tableAlias( "t2" ) ),
+                t.jc( b.booleanBuilder( b.eq( c.colName( "t1", "qname_id" ), c.colName( "t2", "parent_qname" ) ) )
+                       .and( b.eq( c.colName( "t1", "entity_pk" ), c.colName( "t2", "entity_pk" ) ) ).createExpression() ) )
+            .addQualifiedJoin(
+                JoinType.LEFT_OUTER,
+                t.table( t.tableName( "qi4j", "qname_12" ), t.tableAlias( "t3" ) ),
+                t.jc( b.booleanBuilder( b.eq( c.colName( "t2", "qname_id" ), c.colName( "t3", "parent_qname" ) ) )
+                       .and( b.eq( c.colName( "t2", "entity_pk" ), c.colName( "t3", "entity_pk" ) ) ).createExpression() ) )
+            .addQualifiedJoin(
+                JoinType.LEFT_OUTER,
+                t.table( t.tableName( "qi4j", "qname_13" ), t.tableAlias( "t4" ) ),
+                t.jc( b.booleanBuilder( b.eq( c.colName( "t3", "qname_id" ), c.colName( "t4", "parent_qname" ) ) )
+                       .and( b.eq( c.colName( "t2", "entity_pk" ), c.colName( "t4", "entity_pk" ) ) ).createExpression() ) );
+
+        QuerySpecificationBuilder secondBuilder = q.querySpecificationBuilder();
+        secondBuilder.setSelect( innerSelectCols );
+        secondBuilder.getFrom().addTableReferences( join );
+        secondBuilder.getWhere().reset( where );
+        secondBuilder.getGroupBy().addGroupingElements( q.groupingElement( innerFirstCol ),
+                                                        q.groupingElement( innerSecondCol ) );
+        secondBuilder.getHaving().reset( b.geq( l.func( "COUNT", c.colName( "t2", "qname_value" ) ), l.n( 2 ) ) );
+        secondBuilder.getOrderBy().addSortSpecs( q.sortSpec( c.colName( "t0", "entity_pk" ), Ordering.ASCENDING ) );
+
+        QueryExpressionBody innerQuery = q.queryBuilder( firstInnerQuery.createExpression() )
+                                          .except( secondBuilder.createExpression() ).createExpression();
+
+        QuerySpecificationBuilder select = q.querySpecificationBuilder().setSelect(
+            q.columnsBuilder().addUnnamedColumns( c.colName( "t0", "entity_identity" ) ) );
+        select.getFrom().addTableReferences(
+            t.tableBuilder( t.table( q.createQuery( innerQuery ), t.tableAlias( "t0" ) ) ) );
+
+        QueryExpression query = q.createQuery( q.queryBuilder( select.createExpression() ).createExpression() );
+
+        this.logQuery( vendor, query );
+    }
+
+    @Test
+    public void query3()
+        throws Exception
+    {
+        // @formatter:off
+        // SELECT COUNT(firstCol), MAX(secondCol)
+        // FROM schema.table;
+        // @formatter:on
+
+        // This test is related to bug reported by Paul Merlin
+        // The simple query builder was iterating the columns in erroneus way,
+        // thus skipping all non-aliased columns
+        SQLVendor vendor = this.getVendor();
+
+        QueryFactory q = vendor.getQueryFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+
+        String firstCol = "firstCol";
+        String secondCol = "secondCol";
+        String schemaName = "schema";
+        String tableName = "table";
+
+        QueryExpression query = q.simpleQueryBuilder().select( "COUNT(" + firstCol + ")", "MAX(" + secondCol + ")" )
+                                 .from( t.tableName( schemaName, tableName ) ).createExpression();
+
+        this.logQuery( vendor, query );
+    }
+
+    @Test
+    public void query4()
+        throws Exception
+    {
+        // @formatter:off
+        // SELECT * FROM schema.function_name(6, 'param2');
+        // @formatter:on
+
+        SQLVendor vendor = this.getVendor();
+        QueryFactory q = vendor.getQueryFactory();
+        LiteralFactory l = vendor.getLiteralFactory();
+
+        this.logQuery( vendor, q.callFunction( "schema", l.func( "function_name", l.n( 6 ), l.s( "param2" ) ) ) );
+    }
+
+    @Test
+    public void query5()
+        throws Exception
+    {
+        // @formatter:off
+        /*
+          SELECT *
+          FROM table
+          WHERE table.value = ?
+          ORDER BY 1 ASC
+          OFFSET 3 ROWS
+          FETCH FIRST 6 ROWS ONLY
+        */
+
+        SQLVendor vendor = this.getVendor();
+
+        BooleanFactory b = vendor.getBooleanFactory();
+        ColumnsFactory c = vendor.getColumnsFactory();
+
+        QueryExpression query = vendor.getQueryFactory().simpleQueryBuilder()
+                                      .selectAllColumns()
+                                      .from( vendor.getTableReferenceFactory().tableName( "table" ) )
+                                      .where( b.eq( c.colName( "table", "value" ), vendor.getLiteralFactory().param() ) )
+                                      .orderByAsc( "1" )
+                                      .limit( 6 )
+                                      .offset( 3 )
+                                      .createExpression();
+        // @formatter:on
+
+        this.logQuery( vendor, query );
+    }
+
+    @Test
+    public void query6()
+        throws Exception
+    {
+        // @formatter:off
+        /*
+          SELECT *
+          FROM table
+          WHERE table.value = ?
+          ORDER BY 1 ASC
+          OFFSET 3 ROWS
+        */
+
+        SQLVendor vendor = this.getVendor();
+
+        BooleanFactory b = vendor.getBooleanFactory();
+        ColumnsFactory c = vendor.getColumnsFactory();
+
+        QueryExpression query = vendor.getQueryFactory().simpleQueryBuilder()
+                                      .selectAllColumns()
+                                      .from( vendor.getTableReferenceFactory().tableName( "table" ) )
+                                      .where( b.eq( c.colName( "table", "value" ), vendor.getLiteralFactory().param() ) )
+                                      .orderByAsc( "1" )
+                                      .offset( 3 )
+                                      .createExpression();
+        // @formatter:on
+
+        this.logQuery( vendor, query );
+    }
+
+    @Test
+    public void query7()
+        throws Exception
+    {
+        // @formatter:off
+        /*
+          SELECT *
+          FROM table
+          WHERE table.value = ?
+          ORDER BY 1 ASC
+          FETCH FIRST 6 ROWS ONLY
+        */
+
+        SQLVendor vendor = this.getVendor();
+
+        BooleanFactory b = vendor.getBooleanFactory();
+        ColumnsFactory c = vendor.getColumnsFactory();
+
+        QueryExpression query = vendor.getQueryFactory().simpleQueryBuilder()
+                                      .selectAllColumns()
+                                      .from( vendor.getTableReferenceFactory().tableName( "table" ) )
+                                      .where( b.eq( c.colName( "table", "value" ), vendor.getLiteralFactory().param() ) )
+                                      .orderByAsc( "1" )
+                                      .limit( 6 )
+                                      .createExpression();
+        // @formatter:on
+
+        this.logQuery( vendor, query );
+    }
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/AbstractSQLSyntaxTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/AbstractSQLSyntaxTest.java
new file mode 100644
index 0000000..9bb8ab9
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/AbstractSQLSyntaxTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.grammar.common.SQLStatement;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public abstract class AbstractSQLSyntaxTest
+{
+
+    private SQLVendor _vendor;
+
+    protected void logStatement( String statementType, SQLVendor vendor, SQLStatement statement )
+    {
+        String stringStmt = vendor.toString( statement );
+        LoggerFactory.getLogger( this.getClass().getName() ).info( statementType + ":" + "\n" + stringStmt + "\n" );
+
+        Assert.assertEquals(
+            "Strings must be same from both SQLVendor.toString(...) and statement.toString() methods.", stringStmt,
+            statement.toString() );
+    }
+
+    @Before
+    public final void setUp()
+        throws Exception
+    {
+        this._vendor = this.loadVendor();
+    }
+
+    @After
+    public final void tearDown()
+    {
+        this._vendor = null;
+    }
+
+    protected final SQLVendor getVendor()
+    {
+        return this._vendor;
+    }
+
+    protected abstract SQLVendor loadVendor()
+        throws Exception;
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/DefaultDataDefinitionTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/DefaultDataDefinitionTest.java
new file mode 100644
index 0000000..2ff1329
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/DefaultDataDefinitionTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DefaultDataDefinitionTest extends AbstractDataDefinitionTest
+{
+
+    @Override
+    protected SQLVendor loadVendor()
+        throws Exception
+    {
+        return SQLVendorProvider.createVendor( SQLVendor.class );
+    }
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/DefaultModificationTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/DefaultModificationTest.java
new file mode 100644
index 0000000..2a040f5
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/DefaultModificationTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, Stanislav Muhametsin. All Rights Reserved.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+
+public class DefaultModificationTest extends AbstractModificationTest
+{
+
+    @Override
+    protected SQLVendor loadVendor()
+        throws Exception
+    {
+        return SQLVendorProvider.createVendor( SQLVendor.class );
+    }
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/DefaultSQLQueryTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/DefaultSQLQueryTest.java
new file mode 100644
index 0000000..c8a0eba
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/DefaultSQLQueryTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DefaultSQLQueryTest extends AbstractQueryTest
+{
+
+    @Override
+    protected SQLVendor loadVendor()
+        throws Exception
+    {
+        return SQLVendorProvider.createVendor( SQLVendor.class );
+    }
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/H2DataDefinitionTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/H2DataDefinitionTest.java
new file mode 100644
index 0000000..a034907
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/H2DataDefinitionTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2012 Paul Merlin.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.vendor.H2Vendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+
+public class H2DataDefinitionTest
+    extends AbstractDataDefinitionTest
+{
+
+    @Override
+    protected SQLVendor loadVendor()
+        throws Exception
+    {
+        return SQLVendorProvider.createVendor( H2Vendor.class );
+    }
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/H2ModificationTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/H2ModificationTest.java
new file mode 100644
index 0000000..752e827
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/H2ModificationTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2012, Stanislav Muhametsin. All Rights Reserved.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.vendor.H2Vendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+
+public class H2ModificationTest extends AbstractModificationTest
+{
+
+    @Override
+    protected SQLVendor loadVendor()
+        throws Exception
+    {
+        return SQLVendorProvider.createVendor( H2Vendor.class );
+    }
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/H2QueryTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/H2QueryTest.java
new file mode 100644
index 0000000..056b750
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/H2QueryTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2012 Paul Merlin.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.vendor.H2Vendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+
+public class H2QueryTest
+    extends AbstractQueryTest
+{
+
+    @Override
+    protected SQLVendor loadVendor()
+        throws Exception
+    {
+        return SQLVendorProvider.createVendor( H2Vendor.class );
+    }
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/MySQLDataDefinitionTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/MySQLDataDefinitionTest.java
new file mode 100644
index 0000000..25daacb
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/MySQLDataDefinitionTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.vendor.MySQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class MySQLDataDefinitionTest extends AbstractDataDefinitionTest
+{
+
+    @Override
+    protected SQLVendor loadVendor()
+        throws Exception
+    {
+        return SQLVendorProvider.createVendor( MySQLVendor.class );
+    }
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/MySQLModificationTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/MySQLModificationTest.java
new file mode 100644
index 0000000..54c6f04
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/MySQLModificationTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2012, Stanislav Muhametsin. All Rights Reserved.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.vendor.MySQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+
+public class MySQLModificationTest extends AbstractModificationTest
+{
+
+    @Override
+    protected SQLVendor loadVendor()
+        throws Exception
+    {
+        return SQLVendorProvider.createVendor( MySQLVendor.class );
+    }
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/MySQLQueryTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/MySQLQueryTest.java
new file mode 100644
index 0000000..953137e
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/MySQLQueryTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.vendor.MySQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+import org.junit.Test;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class MySQLQueryTest extends AbstractQueryTest
+{
+
+    @Override
+    protected SQLVendor loadVendor()
+        throws Exception
+    {
+        return SQLVendorProvider.createVendor( MySQLVendor.class );
+    }
+
+    @Test
+    public void mySQLQuery5()
+        throws Exception
+    {
+        ( (MySQLVendor) this.getVendor() ).setLegacyLimit( true );
+        super.query5();
+    }
+
+    @Test
+    public void mySQLQuery6()
+        throws Exception
+    {
+        ( (MySQLVendor) this.getVendor() ).setLegacyLimit( true );
+        super.query6();
+    }
+
+    @Test
+    public void mySQLQuery7()
+        throws Exception
+    {
+        ( (MySQLVendor) this.getVendor() ).setLegacyLimit( true );
+        super.query7();
+    }
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/PostgreSQLDataDefinitionTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/PostgreSQLDataDefinitionTest.java
new file mode 100644
index 0000000..0a4a0f8
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/PostgreSQLDataDefinitionTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, Stanislav Muhametsin. All Rights Reserved.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.vendor.PostgreSQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class PostgreSQLDataDefinitionTest extends AbstractDataDefinitionTest
+{
+    @Override
+    protected SQLVendor loadVendor()
+        throws Exception
+    {
+        return SQLVendorProvider.createVendor( PostgreSQLVendor.class );
+    }
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/PostgreSQLModificationTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/PostgreSQLModificationTest.java
new file mode 100644
index 0000000..7d605b8
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/PostgreSQLModificationTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2012, Stanislav Muhametsin. All Rights Reserved.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.grammar.builders.modification.pgsql.PgSQLInsertStatementBuilder;
+import org.apache.polygene.library.sql.generator.grammar.factories.ColumnsFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.LiteralFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.ModificationFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.QueryFactory;
+import org.apache.polygene.library.sql.generator.grammar.factories.TableReferenceFactory;
+import org.apache.polygene.library.sql.generator.grammar.modification.InsertStatement;
+import org.apache.polygene.library.sql.generator.grammar.modification.ValueSource;
+import org.apache.polygene.library.sql.generator.vendor.PostgreSQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+import org.junit.Test;
+
+public class PostgreSQLModificationTest extends AbstractModificationTest
+{
+
+    @Override
+    protected SQLVendor loadVendor()
+        throws Exception
+    {
+        return SQLVendorProvider.createVendor( PostgreSQLVendor.class );
+    }
+
+    @Test
+    public void pgInsert1()
+    {
+        // INSERT INTO some_schema.some_table
+        // VALUES (DEFAULT, "SomeString")
+        // RETURNING id_column;
+        SQLVendor vendor = this.getVendor();
+
+        QueryFactory q = vendor.getQueryFactory();
+        TableReferenceFactory t = vendor.getTableReferenceFactory();
+        ModificationFactory m = vendor.getModificationFactory();
+        LiteralFactory l = vendor.getLiteralFactory();
+        ColumnsFactory c = vendor.getColumnsFactory();
+
+        InsertStatement insert =
+            ( (PgSQLInsertStatementBuilder) m.insert() )
+                .setReturningClause(
+                    q.columnsBuilder().addUnnamedColumns( c.colName( "id_column" ) )
+                     .createExpression() )
+                .setTableName( t.tableName( "some_schema", "some_table" ) )
+                .setColumnSource(
+                    m.columnSourceByValues()
+                     .addValues( ValueSource.Default.INSTANCE, l.s( "SomeString" ) )
+                     .createExpression()
+                                ).createExpression();
+
+        logStatement( "PGSQL table modification", vendor, insert );
+    }
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/PostgreSQLQueryTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/PostgreSQLQueryTest.java
new file mode 100644
index 0000000..ca4dc37
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/PostgreSQLQueryTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.vendor.PostgreSQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+import org.junit.Test;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class PostgreSQLQueryTest extends AbstractQueryTest
+{
+
+    @Override
+    protected PostgreSQLVendor loadVendor()
+        throws Exception
+    {
+        return SQLVendorProvider.createVendor( PostgreSQLVendor.class );
+    }
+
+    @Test
+    public void pgQuery5()
+        throws Exception
+    {
+        ( (PostgreSQLVendor) this.getVendor() ).setLegacyOffsetAndLimit( true );
+        super.query5();
+    }
+
+    @Test
+    public void pgQuery6()
+        throws Exception
+    {
+        ( (PostgreSQLVendor) this.getVendor() ).setLegacyOffsetAndLimit( true );
+        super.query6();
+    }
+
+    @Test
+    public void pgQuery7()
+        throws Exception
+    {
+        ( (PostgreSQLVendor) this.getVendor() ).setLegacyOffsetAndLimit( true );
+        super.query7();
+    }
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/SQLiteDataDefinitionTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/SQLiteDataDefinitionTest.java
new file mode 100644
index 0000000..5e76755
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/SQLiteDataDefinitionTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2012, Paul Merlin.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+import org.apache.polygene.library.sql.generator.vendor.SQLiteVendor;
+
+public class SQLiteDataDefinitionTest
+    extends AbstractDataDefinitionTest
+{
+
+    @Override
+    protected SQLVendor loadVendor()
+        throws Exception
+    {
+        return SQLVendorProvider.createVendor( SQLiteVendor.class );
+    }
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/SQLiteModificationTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/SQLiteModificationTest.java
new file mode 100644
index 0000000..35db800
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/SQLiteModificationTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2012, Stanislav Muhametsin. All Rights Reserved.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+import org.apache.polygene.library.sql.generator.vendor.SQLiteVendor;
+
+public class SQLiteModificationTest extends AbstractModificationTest
+{
+
+    @Override
+    protected SQLVendor loadVendor()
+        throws Exception
+    {
+        return SQLVendorProvider.createVendor( SQLiteVendor.class );
+    }
+}
diff --git a/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/SQLiteQueryTest.java b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/SQLiteQueryTest.java
new file mode 100644
index 0000000..4ab7ebb
--- /dev/null
+++ b/libraries/sql-generator/src/test/java/org/apache/polygene/library/sql/generator/SQLiteQueryTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2012, Paul Merlin.
+ *
+ * Licensed 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.polygene.library.sql.generator;
+
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendorProvider;
+import org.apache.polygene.library.sql.generator.vendor.SQLiteVendor;
+
+public class SQLiteQueryTest
+    extends AbstractQueryTest
+{
+
+    @Override
+    protected SQLVendor loadVendor()
+        throws Exception
+    {
+        return SQLVendorProvider.createVendor( SQLiteVendor.class );
+    }
+}
diff --git a/libraries/sql-liquibase/build.gradle b/libraries/sql-liquibase/build.gradle
index 910552e..e6a43ef 100644
--- a/libraries/sql-liquibase/build.gradle
+++ b/libraries/sql-liquibase/build.gradle
@@ -1,36 +1,39 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ SQL Liquibase Library provides Liquibase support."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - SQL Liquibase" }}
+description = "Apache Polygene™ SQL Liquibase Library provides Liquibase support."
+
+jar { manifest { name = "Apache Polygene™ Library - SQL Liquibase" } }
 
 dependencies {
-  compile(project(":org.qi4j.libraries:org.qi4j.library.sql"))
-  compile(libraries.liquibase)
-  compile libraries.slf4j_api
+  api polygene.library( 'sql' )
+  api libraries.liquibase
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-  testCompile(project(":org.qi4j.libraries:org.qi4j.library.sql-dbcp"))
+  runtimeOnly polygene.core.runtime
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.derby)
-  testRuntime(libraries.logback)
+  testImplementation polygene.core.testsupport
+  testImplementation polygene.library( 'sql-dbcp' )
+  testImplementation libraries.jooq
+
+  testRuntimeOnly libraries.derby
+  testRuntimeOnly libraries.logback
 }
-
diff --git a/libraries/sql-liquibase/dev-status.xml b/libraries/sql-liquibase/dev-status.xml
index bdf00e7..0914c52 100644
--- a/libraries/sql-liquibase/dev-status.xml
+++ b/libraries/sql-liquibase/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/sql-liquibase/src/main/java/org/apache/polygene/library/sql/liquibase/LiquibaseAssembler.java b/libraries/sql-liquibase/src/main/java/org/apache/polygene/library/sql/liquibase/LiquibaseAssembler.java
new file mode 100644
index 0000000..e462c0b
--- /dev/null
+++ b/libraries/sql-liquibase/src/main/java/org/apache/polygene/library/sql/liquibase/LiquibaseAssembler.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.library.sql.liquibase;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+
+public class LiquibaseAssembler
+    extends Assemblers.VisibilityIdentityConfig<LiquibaseAssembler>
+{
+    private boolean applyChangelogOnStartup;
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        ServiceDeclaration service = module.services( LiquibaseService.class ).visibleIn( visibility() );
+        if( applyChangelogOnStartup )
+        {
+            service.withActivators( LiquibaseService.ApplyChangelogActivator.class ).instantiateOnStartup();
+        }
+        if( hasIdentity() )
+        {
+            service.identifiedBy( identity() );
+        }
+        if( hasConfig() )
+        {
+            configModule().entities( LiquibaseConfiguration.class ).visibleIn( configVisibility() );
+        }
+    }
+
+    public LiquibaseAssembler applyChangelogOnStartup()
+    {
+        applyChangelogOnStartup = true;
+        return this;
+    }
+}
diff --git a/libraries/sql-liquibase/src/main/java/org/apache/polygene/library/sql/liquibase/LiquibaseConfiguration.java b/libraries/sql-liquibase/src/main/java/org/apache/polygene/library/sql/liquibase/LiquibaseConfiguration.java
new file mode 100644
index 0000000..99ffa3a
--- /dev/null
+++ b/libraries/sql-liquibase/src/main/java/org/apache/polygene/library/sql/liquibase/LiquibaseConfiguration.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.sql.liquibase;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Configuration for Liquibase.
+ */
+// START SNIPPET: config
+public interface LiquibaseConfiguration
+{
+    @UseDefaults
+    Property<String> changeLog();
+
+    @UseDefaults
+    Property<String> contexts();
+}
+// END SNIPPET: config
diff --git a/libraries/sql-liquibase/src/main/java/org/apache/polygene/library/sql/liquibase/LiquibaseService.java b/libraries/sql-liquibase/src/main/java/org/apache/polygene/library/sql/liquibase/LiquibaseService.java
new file mode 100644
index 0000000..4be23a5
--- /dev/null
+++ b/libraries/sql-liquibase/src/main/java/org/apache/polygene/library/sql/liquibase/LiquibaseService.java
@@ -0,0 +1,137 @@
+/*
+ *  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.polygene.library.sql.liquibase;
+
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.Map;
+import javax.sql.DataSource;
+import liquibase.Liquibase;
+import liquibase.database.DatabaseConnection;
+import liquibase.database.jvm.JdbcConnection;
+import liquibase.exception.LiquibaseException;
+import liquibase.resource.ClassLoaderResourceAccessor;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceReference;
+
+/**
+ * Wrapper service for Liquibase.
+ */
+@Mixins( LiquibaseService.Mixin.class )
+public interface LiquibaseService
+{
+    /**
+     * Creates a new Liquibase instance connected to a visible DataSource.
+     *
+     * <strong>WARNING</strong> remember to {@literal liquibase.getDatabase().close()}
+     *
+     * @return a new Liquibase instance connected to a visible DataSource.
+     * @throws SQLException if something goes wrong
+     * @throws LiquibaseException  if something goes wrong
+     */
+    Liquibase newConnectedLiquibase() throws SQLException, LiquibaseException;
+
+    /**
+     * Apply the configured database changelog.
+     *
+     * @throws SQLException if something goes wrong
+     * @throws LiquibaseException  if something goes wrong
+     */
+    void applyChangelog() throws SQLException, LiquibaseException;
+
+    /**
+     * Apply the configured database changelog.
+     *
+     * @param parameters changelog parameters, see {@link Liquibase#getChangeLogParameters()}
+     * @throws SQLException if something goes wrong
+     * @throws LiquibaseException  if something goes wrong
+     */
+    void applyChangelog( Map<String, Object> parameters )
+        throws SQLException, LiquibaseException;
+
+    /**
+     * Apply database changelog on application startup.
+     *
+     * Assembled by {@link LiquibaseAssembler#applyChangelogOnStartup()}.
+     *
+     * @see LiquibaseService#applyChangelog()
+     */
+    class ApplyChangelogActivator extends ActivatorAdapter<ServiceReference<LiquibaseService>>
+    {
+        @Override
+        public void afterActivation( ServiceReference<LiquibaseService> activated )
+            throws Exception
+        {
+            activated.get().applyChangelog();
+        }
+    }
+
+    class Mixin implements LiquibaseService
+    {
+        @This
+        Configuration<LiquibaseConfiguration> config;
+
+        @Service
+        ServiceReference<DataSource> dataSource;
+
+        @Override
+        public Liquibase newConnectedLiquibase() throws SQLException, LiquibaseException
+        {
+            config.refresh();
+            DatabaseConnection dbConnection = new JdbcConnection( dataSource.get().getConnection() );
+            return new Liquibase( config.get().changeLog().get(),
+                                  new ClassLoaderResourceAccessor(),
+                                  dbConnection );
+        }
+
+        @Override
+        public void applyChangelog() throws SQLException, LiquibaseException
+        {
+            applyChangelog( Collections.emptyMap() );
+        }
+
+        @Override
+        public void applyChangelog( Map<String, Object> parameters )
+            throws SQLException, LiquibaseException
+        {
+            Liquibase liquibase = null;
+            try
+            {
+                liquibase = newConnectedLiquibase();
+                for( Map.Entry<String, Object> entry : parameters.entrySet() )
+                {
+                    liquibase.getChangeLogParameters().set( entry.getKey(), entry.getValue() );
+                }
+                liquibase.update( config.get().contexts().get() );
+            }
+            finally
+            {
+                if( liquibase != null )
+                {
+                    liquibase.getDatabase().close();
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries/sql-liquibase/src/main/java/org/apache/polygene/library/sql/liquibase/package.html b/libraries/sql-liquibase/src/main/java/org/apache/polygene/library/sql/liquibase/package.html
new file mode 100644
index 0000000..fee0bf4
--- /dev/null
+++ b/libraries/sql-liquibase/src/main/java/org/apache/polygene/library/sql/liquibase/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL Liquibase Support.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/sql-liquibase/src/main/java/org/qi4j/library/sql/liquibase/LiquibaseAssembler.java b/libraries/sql-liquibase/src/main/java/org/qi4j/library/sql/liquibase/LiquibaseAssembler.java
deleted file mode 100644
index 535993a..0000000
--- a/libraries/sql-liquibase/src/main/java/org/qi4j/library/sql/liquibase/LiquibaseAssembler.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011 Rickard Öberg.
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.library.sql.liquibase;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-
-public class LiquibaseAssembler
-    extends Assemblers.VisibilityIdentityConfig<LiquibaseAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        ServiceDeclaration service = module.services( LiquibaseService.class ).
-            visibleIn( visibility() ).
-            instantiateOnStartup();
-        if( hasIdentity() )
-        {
-            service.identifiedBy( identity() );
-        }
-        if( hasConfig() )
-        {
-            configModule().entities( LiquibaseConfiguration.class ).visibleIn( configVisibility() );
-        }
-    }
-}
diff --git a/libraries/sql-liquibase/src/main/java/org/qi4j/library/sql/liquibase/LiquibaseConfiguration.java b/libraries/sql-liquibase/src/main/java/org/qi4j/library/sql/liquibase/LiquibaseConfiguration.java
deleted file mode 100644
index 70cdedb..0000000
--- a/libraries/sql-liquibase/src/main/java/org/qi4j/library/sql/liquibase/LiquibaseConfiguration.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.liquibase;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.configuration.Enabled;
-import org.qi4j.api.property.Property;
-
-/**
- * Configuration for Liquibase
- */
-// START SNIPPET: config
-public interface LiquibaseConfiguration
-        extends ConfigurationComposite, Enabled
-{
-    @UseDefaults Property<String> contexts();
-    @UseDefaults Property<String> changeLog();
-}
-// END SNIPPET: config
diff --git a/libraries/sql-liquibase/src/main/java/org/qi4j/library/sql/liquibase/LiquibaseService.java b/libraries/sql-liquibase/src/main/java/org/qi4j/library/sql/liquibase/LiquibaseService.java
deleted file mode 100644
index 92ff9b7..0000000
--- a/libraries/sql-liquibase/src/main/java/org/qi4j/library/sql/liquibase/LiquibaseService.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.liquibase;
-
-import java.net.ConnectException;
-import java.sql.Connection;
-import java.sql.SQLException;
-import javax.sql.DataSource;
-import liquibase.Liquibase;
-import liquibase.database.DatabaseConnection;
-import liquibase.database.jvm.JdbcConnection;
-import liquibase.resource.ClassLoaderResourceAccessor;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceImporterException;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Wrapper service for Liquibase.
- */
-@Mixins( LiquibaseService.Mixin.class )
-@Activators( LiquibaseService.Activator.class )
-public interface LiquibaseService
-        extends ServiceComposite
-{
-
-    void activateLiquibase()
-            throws Exception;
-
-    public static class Activator
-            extends ActivatorAdapter<ServiceReference<LiquibaseService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<LiquibaseService> activated )
-                throws Exception
-        {
-            activated.get().activateLiquibase();
-        }
-
-    }
-
-    public static abstract class Mixin
-            implements LiquibaseService
-    {
-
-        private static final Logger LOGGER = LoggerFactory.getLogger( "org.qi4j.library.sql" );
-
-        @This
-        Configuration<LiquibaseConfiguration> config;
-
-        @Service
-        ServiceReference<DataSource> dataSource;
-
-        @Override
-        public void activateLiquibase()
-                throws Exception
-        {
-            config.refresh();
-            boolean enabled = config.get().enabled().get();
-            if ( !enabled ) {
-                return;
-            }
-
-            Connection connection = null;
-            try {
-
-                connection = dataSource.get().getConnection();
-                DatabaseConnection dc = new JdbcConnection( connection );
-                Liquibase liquibase = new Liquibase( config.get().changeLog().get(), new ClassLoaderResourceAccessor(), dc );
-                liquibase.update( config.get().contexts().get() );
-
-            } catch ( SQLException e ) {
-
-                Throwable ex = e;
-                while ( ex.getCause() != null ) {
-                    ex = ex.getCause();
-                }
-
-                if ( ex instanceof ConnectException ) {
-                    LOGGER.warn( "Could not connect to database; Liquibase should be disabled" );
-                    return;
-                }
-
-                LOGGER.error( "Liquibase could not perform database migration", e );
-
-            } catch ( ServiceImporterException ex ) {
-
-                LOGGER.warn( "DataSource is not available - database refactoring skipped" );
-
-            } finally {
-
-                SQLUtil.rollbackQuietly( connection );
-                SQLUtil.closeQuietly( connection );
-
-            }
-        }
-
-    }
-
-}
\ No newline at end of file
diff --git a/libraries/sql-liquibase/src/main/java/org/qi4j/library/sql/liquibase/package.html b/libraries/sql-liquibase/src/main/java/org/qi4j/library/sql/liquibase/package.html
deleted file mode 100644
index 95ddcf2..0000000
--- a/libraries/sql-liquibase/src/main/java/org/qi4j/library/sql/liquibase/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL Liquibase Support.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/sql-liquibase/src/test/java/org/apache/polygene/library/sql/liquibase/LiquibaseServiceTest.java b/libraries/sql-liquibase/src/test/java/org/apache/polygene/library/sql/liquibase/LiquibaseServiceTest.java
new file mode 100644
index 0000000..fd39fb3
--- /dev/null
+++ b/libraries/sql-liquibase/src/test/java/org/apache/polygene/library/sql/liquibase/LiquibaseServiceTest.java
@@ -0,0 +1,149 @@
+/*
+ *  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.polygene.library.sql.liquibase;
+
+import java.util.List;
+import java.util.function.Function;
+import javax.sql.DataSource;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.library.sql.assembly.DataSourceAssembler;
+import org.apache.polygene.library.sql.dbcp.DBCPDataSourceServiceAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.jooq.DSLContext;
+import org.jooq.Field;
+import org.jooq.InsertValuesStep2;
+import org.jooq.Record;
+import org.jooq.SQLDialect;
+import org.jooq.Table;
+import org.jooq.impl.DSL;
+import org.junit.Test;
+
+import static java.util.stream.Collectors.toList;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.jooq.impl.DSL.field;
+import static org.jooq.impl.DSL.table;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test DataSource and Liquibase services
+ */
+public class LiquibaseServiceTest
+{
+    @Test
+    public void testLiquibase() throws ActivationException
+    {
+        final SingletonAssembler assembler = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                ModuleAssembly configModule = module;
+                // Create in-memory store for configurations
+                new EntityTestAssembler().assemble( configModule );
+
+                new DBCPDataSourceServiceAssembler()
+                    .identifiedBy( "datasource-service" )
+                    .withConfig( configModule, Visibility.layer )
+                    .assemble( module );
+                new DataSourceAssembler()
+                    .withDataSourceServiceIdentity( "datasource-service" )
+                    .identifiedBy( "testds-liquibase" )
+                    .withCircuitBreaker()
+                    .assemble( module );
+
+                module.values( SomeValue.class );
+
+                // Set up Liquibase service that will create the tables
+                // START SNIPPET: assembly
+                new LiquibaseAssembler()
+                    .withConfig( configModule, Visibility.layer )
+                    .applyChangelogOnStartup()
+                    .assemble( module );
+                // END SNIPPET: assembly
+                module.forMixin( LiquibaseConfiguration.class ).declareDefaults().changeLog().set( "changelog.xml" );
+            }
+
+            @Override
+            public void beforeActivation( Application application )
+            {
+                application.registerActivationEventListener( System.out::println );
+            }
+        };
+
+        Module module = assembler.module();
+
+        // Look up the DataSource
+        DataSource ds = module.findService( DataSource.class ).get();
+
+        // Prepare jOOQ and the schema model
+        DSLContext jooq = DSL.using( ds, SQLDialect.DERBY );
+        Table<Record> testTable = table( "TEST" );
+        Field<String> idColumn = field( "ID", String.class );
+        Field<String> fooColumn = field( "FOO", String.class );
+
+        // Assert that insertion works
+        InsertValuesStep2 insert = jooq.insertInto( testTable )
+                                       .columns( idColumn, fooColumn )
+                                       .values( "someid", "bar" );
+        assertTrue( insert.execute() == 1 );
+
+        List<Record> records = jooq.selectFrom( testTable ).stream().collect( toList() );
+        assertThat( records.size(), is( 1 ) );
+        assertThat( records.get( 0 ).get( idColumn ), equalTo( "someid" ) );
+        assertThat( records.get( 0 ).get( fooColumn ), equalTo( "bar" ) );
+
+        Function<Record, SomeValue> toValue = record ->
+        {
+            ValueBuilder<SomeValue> builder = assembler.module().newValueBuilder( SomeValue.class );
+            builder.prototype().id().set( record.get( idColumn ) );
+            builder.prototype().foo().set( record.get( fooColumn ) );
+            return builder.newInstance();
+        };
+
+        List<SomeValue> values = jooq.selectFrom( testTable ).stream()
+                                     .map( toValue )
+                                     .peek( System.out::println )
+                                     .collect( toList() );
+
+        assertThat( values.size(), is( 1 ) );
+        assertThat( values.get( 0 ).id().get(), equalTo( "someid" ) );
+        assertThat( values.get( 0 ).foo().get(), equalTo( "bar" ) );
+    }
+
+    interface SomeValue
+        extends ValueComposite
+    {
+        Property<String> id();
+
+        Property<String> foo();
+    }
+}
diff --git a/libraries/sql-liquibase/src/test/java/org/qi4j/library/sql/liquibase/LiquibaseServiceTest.java b/libraries/sql-liquibase/src/test/java/org/qi4j/library/sql/liquibase/LiquibaseServiceTest.java
deleted file mode 100644
index 82e56e8..0000000
--- a/libraries/sql-liquibase/src/test/java/org/qi4j/library/sql/liquibase/LiquibaseServiceTest.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.liquibase;
-
-import java.io.IOException;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.List;
-import javax.sql.DataSource;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationEvent;
-import org.qi4j.api.activation.ActivationEventListener;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.functional.Function;
-import org.qi4j.io.Inputs;
-import org.qi4j.io.Outputs;
-import org.qi4j.library.sql.assembly.DataSourceAssembler;
-import org.qi4j.library.sql.common.Databases;
-import org.qi4j.library.sql.dbcp.DBCPDataSourceServiceAssembler;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.qi4j.io.Outputs.collection;
-import static org.qi4j.io.Transforms.map;
-
-/**
- * Test DataSource and Liquibase services
- */
-public class LiquibaseServiceTest
-{
-    @Test
-    public void testLiquibase()
-        throws SQLException, IOException, ActivationException, AssemblyException
-    {
-        final SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                ModuleAssembly configModule = module;
-                // Create in-memory store for configurations
-                new EntityTestAssembler().assemble( configModule );
-
-                new DBCPDataSourceServiceAssembler().
-                    identifiedBy( "datasource-service" ).
-                    withConfig( configModule, Visibility.layer ).
-                    assemble( module );
-                new DataSourceAssembler().
-                    withDataSourceServiceIdentity( "datasource-service" ).
-                    identifiedBy( "testds-liquibase" ).
-                    withCircuitBreaker().
-                    assemble( module );
-
-                module.values( SomeValue.class );
-
-                // Set up Liquibase service that will create the tables
-                // START SNIPPET: assembly
-                new LiquibaseAssembler().
-                    withConfig( configModule, Visibility.layer ).
-                    assemble( module );
-                // END SNIPPET: assembly
-                module.forMixin( LiquibaseConfiguration.class ).declareDefaults().enabled().set( true );
-                module.forMixin( LiquibaseConfiguration.class ).declareDefaults().changeLog().set( "changelog.xml" );
-            }
-
-            @Override
-            public void beforeActivation( Application application )
-            {
-                application.registerActivationEventListener( new ActivationEventListener()
-                {
-
-                    @Override
-                    public void onEvent( ActivationEvent event )
-                    {
-                        System.out.println( event );
-                    }
-
-                } );
-            }
-
-        };
-
-        Module module = assembler.module();
-
-        // START SNIPPET: io
-        // Look up the DataSource
-        DataSource ds = module.findService( DataSource.class ).get();
-
-        // Instanciate Databases helper
-        Databases database = new Databases( ds );
-
-        // Assert that insertion works
-        assertTrue( database.update( "insert into test values ('someid', 'bar')" ) == 1 );
-        // END SNIPPET: io
-
-        database.query( "select * from test", new Databases.ResultSetVisitor()
-        {
-            @Override
-            public boolean visit( ResultSet visited )
-                throws SQLException
-            {
-                assertThat( visited.getString( "id" ), equalTo( "someid" ) );
-                assertThat( visited.getString( "foo" ), equalTo( "bar" ) );
-
-                return true;
-            }
-        } );
-
-        Function<ResultSet, SomeValue> toValue = new Function<ResultSet, SomeValue>()
-        {
-            @Override
-            public SomeValue map( ResultSet resultSet )
-            {
-                ValueBuilder<SomeValue> builder = assembler.module().newValueBuilder( SomeValue.class );
-                try
-                {
-                    builder.prototype().id().set( resultSet.getString( "id" ) );
-                    builder.prototype().foo().set( resultSet.getString( "foo" ) );
-                }
-                catch( SQLException e )
-                {
-                    throw new IllegalArgumentException( "Could not convert to SomeValue", e );
-                }
-
-                return builder.newInstance();
-            }
-        };
-
-        // START SNIPPET: io
-        // Select rows and load them in a List
-        List<SomeValue> rows = new ArrayList<SomeValue>();
-        database.query( "select * from test" ).transferTo( map( toValue, collection( rows ) ) );
-
-        // Transfer all rows to System.out
-        Inputs.iterable( rows ).transferTo( Outputs.systemOut() );
-        // END SNIPPET: io
-    }
-
-    interface SomeValue
-        extends ValueComposite
-    {
-        Property<String> id();
-
-        Property<String> foo();
-    }
-
-}
diff --git a/libraries/sql-liquibase/src/test/resources/changelog.xml b/libraries/sql-liquibase/src/test/resources/changelog.xml
index 9ae0236..7a33052 100644
--- a/libraries/sql-liquibase/src/test/resources/changelog.xml
+++ b/libraries/sql-liquibase/src/test/resources/changelog.xml
@@ -1,20 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <databaseChangeLog
      xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
diff --git a/libraries/sql-liquibase/src/test/resources/testds-liquibase.properties b/libraries/sql-liquibase/src/test/resources/testds-liquibase.properties
index 93b1eeb..ac9b114 100644
--- a/libraries/sql-liquibase/src/test/resources/testds-liquibase.properties
+++ b/libraries/sql-liquibase/src/test/resources/testds-liquibase.properties
@@ -1,17 +1,22 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 enabled=true
 url=jdbc:derby:memory:testdb3;create=true
diff --git a/libraries/sql/build.gradle b/libraries/sql/build.gradle
index d4789c3..9249981 100644
--- a/libraries/sql/build.gradle
+++ b/libraries/sql/build.gradle
@@ -1,42 +1,47 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ SQL Library provides SQL support."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - SQL" }}
+description = "Apache Polygene™ SQL Library provides SQL support."
+
+jar { manifest { name = "Apache Polygene™ Library - SQL" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile(project(":org.qi4j.libraries:org.qi4j.library.circuitbreaker"))
-  compile(project(":org.qi4j.libraries:org.qi4j.library.conversion"))
-  compile(project(":org.qi4j.libraries:org.qi4j.library.jmx"))
-  compile libraries.slf4j_api
+  api polygene.core.bootstrap
+  api polygene.library( 'circuitbreaker' )
+  api libraries.slf4j_api
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-  testCompile(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testCompile(project(":org.qi4j.libraries:org.qi4j.library.sql-bonecp"))
-  testCompile(project(":org.qi4j.libraries:org.qi4j.library.sql-dbcp"))
-  testCompile(project(":org.qi4j.libraries:org.qi4j.library.sql-liquibase"))
-  testCompile(project(":org.qi4j.extensions:org.qi4j.extension.entitystore-preferences"))
-  
-  testRuntime(libraries.derby)
-  testRuntime(libraries.mysql_connector)
-  testRuntime(libraries.postgres)
-  testRuntime(libraries.logback)
+  implementation polygene.library( 'jmx' )
+
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+  testImplementation polygene.library( 'sql-bonecp' )
+  testImplementation polygene.library( 'sql-dbcp' )
+  testImplementation polygene.library( 'sql-liquibase' )
+  testImplementation polygene.extension( 'entitystore-preferences' )
+  testImplementation libraries.commons_dbcp
+
+  testRuntimeOnly libraries.logback
+  testRuntimeOnly libraries.derby
+  testRuntimeOnly libraries.mysql_connector
+  testRuntimeOnly libraries.postgres
 }
diff --git a/libraries/sql/dev-status.xml b/libraries/sql/dev-status.xml
index bdf00e7..0914c52 100644
--- a/libraries/sql/dev-status.xml
+++ b/libraries/sql/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/sql/src/docs/sql.txt b/libraries/sql/src/docs/sql.txt
index ffad172..1021c6a 100644
--- a/libraries/sql/src/docs/sql.txt
+++ b/libraries/sql/src/docs/sql.txt
@@ -29,7 +29,7 @@
 The SQL Library provides facilities for working with SQL databases.
 
 The center piece is the DataSource support that comes with
-<<library-circuitbreaker>> and <<library-jmx>> support. Facilities for doing SQL I/O with the <<core-io>> are provided.
+<<library-circuitbreaker>> and <<library-jmx>> support.
 
 TIP: See the <<sample-sql-support>> that demonstrate combined use of <<library-sql>>, <<extension-es-sql>> and
 <<extension-indexing-sql>>.
@@ -69,7 +69,7 @@
 
 [snippet,java]
 ----
-source=libraries/sql/src/test/java/org/qi4j/library/sql/DocumentationSupport.java
+source=libraries/sql/src/test/java/org/apache/polygene/library/sql/DocumentationSupport.java
 tag=bonecp
 ----
 
@@ -84,7 +84,7 @@
 
 [snippet,java]
 ----
-source=libraries/sql/src/test/java/org/qi4j/library/sql/DocumentationSupport.java
+source=libraries/sql/src/test/java/org/apache/polygene/library/sql/DocumentationSupport.java
 tag=dbcp
 ----
 
@@ -98,7 +98,7 @@
 
 [snippet,java]
 ----
-source=libraries/sql/src/test/java/org/qi4j/library/sql/DocumentationSupport.java
+source=libraries/sql/src/test/java/org/apache/polygene/library/sql/DocumentationSupport.java
 tag=datasource
 ----
 
@@ -111,7 +111,7 @@
 
 [snippet,java]
 ----
-source=libraries/sql/src/main/java/org/qi4j/library/sql/datasource/DataSourceConfigurationState.java
+source=libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/DataSourceConfigurationState.java
 tag=config
 ----
 
@@ -126,12 +126,12 @@
 
 === Importing an existing DataSource ===
 
-Importing an existing DataSource at assembly time is usefull when your Zest
+Importing an existing DataSource at assembly time is usefull when your Polygene
 Application runs in an environment where DataSource are already provided.
 
 [snippet,java]
 ----
-source=libraries/sql/src/test/java/org/qi4j/library/sql/datasource/ExternalDataSourceTest.java
+source=libraries/sql/src/test/java/org/apache/polygene/library/sql/datasource/ExternalDataSourceTest.java
 tag=assembly
 ----
 
@@ -149,7 +149,7 @@
 
 [snippet,java]
 ----
-source=libraries/sql/src/test/java/org/qi4j/library/sql/DocumentationSupport.java
+source=libraries/sql/src/test/java/org/apache/polygene/library/sql/DocumentationSupport.java
 tag=cb-assembly
 ----
 
@@ -158,25 +158,12 @@
 
 [snippet,java]
 ----
-source=libraries/sql/src/test/java/org/qi4j/library/sql/DocumentationSupport.java
+source=libraries/sql/src/test/java/org/apache/polygene/library/sql/DocumentationSupport.java
 tag=cb-datasource
 ----
 
 
 
-
-== I/O ==
-
-Here is a simple example:
-
-[snippet,java]
-----
-source=libraries/sql-liquibase/src/test/java/org/qi4j/library/sql/liquibase/LiquibaseServiceTest.java
-tag=io
-----
-
-
-
 == JMX ==
 
 Thanks to the <<library-jmx>> the Configuration of DataSources is exposed
@@ -184,7 +171,7 @@
 
 [snippet,java]
 ----
-source=libraries/sql/src/test/java/org/qi4j/library/sql/jmx/DataSourceConfigurationManagerServiceTest.java
+source=libraries/sql/src/test/java/org/apache/polygene/library/sql/jmx/DataSourceConfigurationManagerServiceTest.java
 tag=jmx
 ----
 
@@ -212,7 +199,7 @@
 
 [snippet,java]
 ----
-source=libraries/sql-liquibase/src/test/java/org/qi4j/library/sql/liquibase/LiquibaseServiceTest.java
+source=libraries/sql-liquibase/src/test/java/org/apache/polygene/library/sql/liquibase/LiquibaseServiceTest.java
 tag=assembly
 ----
 
@@ -223,7 +210,7 @@
 
 [snippet,java]
 ----
-source=libraries/sql-liquibase/src/main/java/org/qi4j/library/sql/liquibase/LiquibaseConfiguration.java
+source=libraries/sql-liquibase/src/main/java/org/apache/polygene/library/sql/liquibase/LiquibaseConfiguration.java
 tag=config
 ----
 
diff --git a/libraries/sql/src/main/java/org/apache/polygene/library/sql/assembly/AbstractPooledDataSourceServiceAssembler.java b/libraries/sql/src/main/java/org/apache/polygene/library/sql/assembly/AbstractPooledDataSourceServiceAssembler.java
new file mode 100644
index 0000000..8a6e777
--- /dev/null
+++ b/libraries/sql/src/main/java/org/apache/polygene/library/sql/assembly/AbstractPooledDataSourceServiceAssembler.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.library.sql.assembly;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.sql.datasource.DataSourceConfiguration;
+
+public abstract class AbstractPooledDataSourceServiceAssembler<AssemblerType>
+    extends Assemblers.VisibilityIdentityConfig<AssemblerType>
+{
+    public static String DEFAULT_DATASOURCE_SERVICE_IDENTITY = "datasource-service";
+
+    @Override
+    public final void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.values( DataSourceConfiguration.class ).visibleIn( Visibility.module );
+        if( hasConfig() )
+        {
+            configModule().entities( DataSourceConfiguration.class ).visibleIn( configVisibility() );
+        }
+        onAssemble( module, identity() == null ? DEFAULT_DATASOURCE_SERVICE_IDENTITY : identity(), visibility() );
+    }
+
+    protected abstract void onAssemble( ModuleAssembly module, String identity, Visibility visibility );
+}
diff --git a/libraries/sql/src/main/java/org/apache/polygene/library/sql/assembly/DataSourceAssembler.java b/libraries/sql/src/main/java/org/apache/polygene/library/sql/assembly/DataSourceAssembler.java
new file mode 100644
index 0000000..e6a3d78
--- /dev/null
+++ b/libraries/sql/src/main/java/org/apache/polygene/library/sql/assembly/DataSourceAssembler.java
@@ -0,0 +1,83 @@
+/*
+ *  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.polygene.library.sql.assembly;
+
+import java.util.Objects;
+import javax.sql.DataSource;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.service.importer.ServiceInstanceImporter;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.circuitbreaker.CircuitBreaker;
+import org.apache.polygene.library.sql.datasource.DataSources;
+
+/**
+ * Use this Assembler to register a javax.sql.DataSource.
+ */
+public class DataSourceAssembler
+    extends Assemblers.VisibilityIdentity<DataSourceAssembler>
+{
+    public static String DEFAULT_DATASOURCE_IDENTITY = "datasource";
+
+    private String dataSourceServiceId = AbstractPooledDataSourceServiceAssembler.DEFAULT_DATASOURCE_SERVICE_IDENTITY;
+
+    private CircuitBreaker circuitBreaker;
+
+    public DataSourceAssembler()
+    {
+        identifiedBy( DEFAULT_DATASOURCE_IDENTITY );
+    }
+
+    public DataSourceAssembler withDataSourceServiceIdentity( String dataSourceServiceId )
+    {
+        Objects.requireNonNull( dataSourceServiceId, "DataSourceService reference" );
+        this.dataSourceServiceId = dataSourceServiceId;
+        return this;
+    }
+
+    public DataSourceAssembler withCircuitBreaker()
+    {
+        this.circuitBreaker = DataSources.newDataSourceCircuitBreaker();
+        return this;
+    }
+
+    public DataSourceAssembler withCircuitBreaker( CircuitBreaker circuitBreaker )
+    {
+        Objects.requireNonNull( circuitBreaker, "CircuitBreaker" );
+        this.circuitBreaker = circuitBreaker;
+        return this;
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.importedServices( DataSource.class ).
+            importedBy( ServiceInstanceImporter.class ).
+            setMetaInfo( new StringIdentity( dataSourceServiceId ) ).
+            identifiedBy( identity() ).
+            visibleIn( visibility() );
+        if( circuitBreaker != null )
+        {
+            module.importedServices( DataSource.class ).identifiedBy( identity() ).setMetaInfo( circuitBreaker );
+        }
+    }
+}
diff --git a/libraries/sql/src/main/java/org/apache/polygene/library/sql/assembly/DataSourceJMXAssembler.java b/libraries/sql/src/main/java/org/apache/polygene/library/sql/assembly/DataSourceJMXAssembler.java
new file mode 100644
index 0000000..6cf0d51
--- /dev/null
+++ b/libraries/sql/src/main/java/org/apache/polygene/library/sql/assembly/DataSourceJMXAssembler.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.sql.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.sql.jmx.DataSourceConfigurationManagerService;
+
+public class DataSourceJMXAssembler
+    extends Assemblers.Visibility<DataSourceJMXAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( DataSourceConfigurationManagerService.class ).visibleIn( visibility() ).instantiateOnStartup();
+    }
+}
diff --git a/libraries/sql/src/main/java/org/apache/polygene/library/sql/assembly/ExternalDataSourceAssembler.java b/libraries/sql/src/main/java/org/apache/polygene/library/sql/assembly/ExternalDataSourceAssembler.java
new file mode 100644
index 0000000..4af36cf
--- /dev/null
+++ b/libraries/sql/src/main/java/org/apache/polygene/library/sql/assembly/ExternalDataSourceAssembler.java
@@ -0,0 +1,77 @@
+/*
+ *  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.polygene.library.sql.assembly;
+
+import java.util.Objects;
+import javax.sql.DataSource;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.circuitbreaker.CircuitBreaker;
+import org.apache.polygene.library.sql.datasource.DataSources;
+
+public class ExternalDataSourceAssembler
+    extends Assemblers.VisibilityIdentity<ExternalDataSourceAssembler>
+{
+    public static String DEFAULT_DATASOURCE_IDENTITY = "external-datasource";
+
+    private DataSource externalDataSource;
+
+    private CircuitBreaker circuitBreaker;
+
+    public ExternalDataSourceAssembler()
+    {
+        identifiedBy( DEFAULT_DATASOURCE_IDENTITY );
+    }
+
+    public ExternalDataSourceAssembler( DataSource externalDataSource )
+    {
+        Objects.requireNonNull( externalDataSource, "DataSource" );
+        this.externalDataSource = externalDataSource;
+    }
+
+    public ExternalDataSourceAssembler withCircuitBreaker()
+    {
+        this.circuitBreaker = DataSources.newDataSourceCircuitBreaker();
+        return this;
+    }
+
+    public ExternalDataSourceAssembler withCircuitBreaker( CircuitBreaker circuitBreaker )
+    {
+        Objects.requireNonNull( circuitBreaker, "CircuitBreaker" );
+        this.circuitBreaker = circuitBreaker;
+        return this;
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        if( circuitBreaker != null )
+        {
+            externalDataSource = DataSources.wrapWithCircuitBreaker( new StringIdentity(identity()), externalDataSource, circuitBreaker );
+        }
+        module.importedServices( DataSource.class ).
+            identifiedBy( identity() ).
+            visibleIn( visibility() ).
+            setMetaInfo( externalDataSource );
+    }
+}
diff --git a/libraries/sql/src/main/java/org/apache/polygene/library/sql/assembly/package.html b/libraries/sql/src/main/java/org/apache/polygene/library/sql/assembly/package.html
new file mode 100644
index 0000000..f946201
--- /dev/null
+++ b/libraries/sql/src/main/java/org/apache/polygene/library/sql/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL Library Assembly.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/sql/src/main/java/org/apache/polygene/library/sql/common/SQLConfiguration.java b/libraries/sql/src/main/java/org/apache/polygene/library/sql/common/SQLConfiguration.java
new file mode 100644
index 0000000..2a62a7e
--- /dev/null
+++ b/libraries/sql/src/main/java/org/apache/polygene/library/sql/common/SQLConfiguration.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.sql.common;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Typical configuration for service, which uses a {@link javax.sql.DataSource} as connection to SQL
+ * database, and given schema name as schema to create tables in.
+ */
+public interface SQLConfiguration
+{
+    /**
+     * The schema name to use to create/find tables.
+     */
+    @Optional
+    Property<String> schemaName();
+}
diff --git a/libraries/sql/src/main/java/org/apache/polygene/library/sql/common/SQLUtil.java b/libraries/sql/src/main/java/org/apache/polygene/library/sql/common/SQLUtil.java
new file mode 100644
index 0000000..db388ee
--- /dev/null
+++ b/libraries/sql/src/main/java/org/apache/polygene/library/sql/common/SQLUtil.java
@@ -0,0 +1,135 @@
+/*
+ *  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.polygene.library.sql.common;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+public class SQLUtil
+{
+    public static SQLException withAllSQLExceptions( SQLException sqlEx )
+    {
+        SQLException next = sqlEx.getNextException();
+        while( next != null )
+        {
+            sqlEx.addSuppressed( next );
+            next = next.getNextException();
+        }
+        return sqlEx;
+    }
+
+    public static void closeQuietly( ResultSet resultSet )
+    {
+        closeQuietly( resultSet, null );
+    }
+
+    public static void closeQuietly( ResultSet resultSet, Throwable originalException )
+    {
+        if( resultSet != null )
+        {
+            try
+            {
+                resultSet.close();
+            }
+            catch( SQLException ignored )
+            {
+                if( originalException != null )
+                {
+                    originalException.addSuppressed( ignored );
+                }
+            }
+        }
+    }
+
+    public static void closeQuietly( Statement select )
+    {
+        closeQuietly( select, null );
+    }
+
+    public static void closeQuietly( Statement select, Throwable originalException )
+    {
+        if( select != null )
+        {
+            try
+            {
+                select.close();
+            }
+            catch( SQLException ignored )
+            {
+                if( originalException != null )
+                {
+                    originalException.addSuppressed( ignored );
+                }
+            }
+        }
+    }
+
+    public static void closeQuietly( Connection connection )
+    {
+        closeQuietly( connection, null );
+    }
+
+    public static void closeQuietly( Connection connection, Throwable originalException )
+    {
+        if( connection != null )
+        {
+            try
+            {
+                connection.close();
+            }
+            catch( SQLException ignored )
+            {
+                if( originalException != null )
+                {
+                    originalException.addSuppressed( ignored );
+                }
+            }
+        }
+    }
+
+    public static void rollbackQuietly( Connection connection )
+    {
+        rollbackQuietly( connection, null );
+    }
+
+    public static void rollbackQuietly( Connection connection, Throwable originalException )
+    {
+        if( connection != null )
+        {
+            try
+            {
+                connection.rollback();
+            }
+            catch( SQLException ignored )
+            {
+                if( originalException != null )
+                {
+                    originalException.addSuppressed( ignored );
+                }
+            }
+        }
+    }
+
+    private SQLUtil()
+    {
+    }
+}
diff --git a/libraries/sql/src/main/java/org/apache/polygene/library/sql/common/package.html b/libraries/sql/src/main/java/org/apache/polygene/library/sql/common/package.html
new file mode 100644
index 0000000..33e2cee
--- /dev/null
+++ b/libraries/sql/src/main/java/org/apache/polygene/library/sql/common/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL Library Utilities.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/AbstractDataSourceServiceImporterMixin.java b/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/AbstractDataSourceServiceImporterMixin.java
new file mode 100644
index 0000000..37e740e
--- /dev/null
+++ b/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/AbstractDataSourceServiceImporterMixin.java
@@ -0,0 +1,193 @@
+/*
+ *  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.polygene.library.sql.datasource;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+import javax.sql.DataSource;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.PropertyMapper;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.ServiceImporterException;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.library.circuitbreaker.CircuitBreaker;
+import org.apache.polygene.library.sql.common.SQLUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractDataSourceServiceImporterMixin<PooledDataSourceType extends DataSource>
+        implements ServiceImporter<DataSource>, DataSourceServiceImporterActivation
+{
+
+    protected static final Logger LOGGER = LoggerFactory.getLogger( AbstractDataSourceServiceImporterMixin.class );
+
+    private final Map<Identity, DataSourceConfiguration> configs = new HashMap<>();
+
+    private final Map<Identity, PooledDataSourceType> pools = new HashMap<>();
+
+    private final Map<DataSource, CircuitBreaker> circuitBreakers = new HashMap<>();
+
+    @Structure
+    protected UnitOfWorkFactory uowf;
+
+    @Override
+    public final void passivateDataSourceService()
+            throws Exception
+    {
+        for ( PooledDataSourceType pool : pools.values() ) {
+            passivateDataSourcePool( pool );
+        }
+        pools.clear();
+        configs.clear();
+        circuitBreakers.clear();
+    }
+
+    @Override
+    public final synchronized DataSource importService( final ImportedServiceDescriptor importedServiceDescriptor )
+            throws ServiceImporterException
+    {
+        PooledDataSourceType pool = pools.get( importedServiceDescriptor.identity() );
+        if ( pool == null ) {
+
+            try {
+
+                DataSourceConfiguration config = getConfiguration( importedServiceDescriptor.identity() );
+                if ( !config.enabled().get() ) {
+                    // Not started
+                    throw new ServiceImporterException( "DataSource not enabled" );
+                }
+
+                // Instantiate pool
+                pool = setupDataSourcePool( config );
+                pools.put( importedServiceDescriptor.identity(), pool );
+
+                LOGGER.info( "Starting up DataSource '" + importedServiceDescriptor.identity() + "' for: {}@{}", config.username().get(), config.url().get() );
+
+            } catch ( Exception e ) {
+                throw new ServiceImporterException( e );
+            }
+
+            // Test the pool
+            ClassLoader cl = Thread.currentThread().getContextClassLoader();
+            Thread.currentThread().setContextClassLoader( null );
+            try {
+                pool.getConnection().close();
+                LOGGER.info( "Database for DataSource is up!" );
+            } catch ( SQLException e ) {
+                LOGGER.warn( "Database for DataSource " + importedServiceDescriptor.identity() + " is not currently available" );
+                throw new ServiceImporterException( "Database for DataSource " + importedServiceDescriptor.identity() + " is not currently available",
+                                                    SQLUtil.withAllSQLExceptions( e ) );
+            } finally {
+                Thread.currentThread().setContextClassLoader( cl );
+            }
+        }
+
+        // Check if circuitbreaker is used
+        final CircuitBreaker circuitBreaker = importedServiceDescriptor.metaInfo( CircuitBreaker.class );
+        if ( circuitBreaker != null ) {
+
+            DataSource wrappedDataSource = DataSources.wrapWithCircuitBreaker( importedServiceDescriptor.identity(), pool, circuitBreaker );
+            circuitBreakers.put( pool, circuitBreaker );
+            return wrappedDataSource;
+
+        } else {
+
+            return pool;
+
+        }
+    }
+
+    private DataSourceConfiguration getConfiguration( Identity identity )
+            throws InstantiationException
+    {
+        DataSourceConfiguration config = configs.get( identity );
+        if ( config == null ) {
+            UnitOfWork uow = uowf.newUnitOfWork( UsecaseBuilder.newUsecase( "Create DataSource pool configuration" ) );
+
+            try {
+                DataSourceConfiguration configEntity = uow.get( DataSourceConfiguration.class, identity );
+                config = uow.toValue( DataSourceConfiguration.class, configEntity );
+            } catch ( NoSuchEntityException e ) {
+                EntityBuilder<DataSourceConfiguration> configBuilder = uow.newEntityBuilder( DataSourceConfiguration.class, identity );
+
+                // Check for defaults
+                String s = identity + ".properties";
+                InputStream asStream = DataSourceConfiguration.class.getClassLoader().getResourceAsStream( s );
+                if ( asStream != null ) {
+                    try {
+                        PropertyMapper.map( asStream, (Composite) configBuilder.instance() );
+                    } catch ( IOException e1 ) {
+                        uow.discard();
+                        InstantiationException exception = new InstantiationException( "Could not read underlying Properties file." );
+                        exception.initCause( e1 );
+                        throw exception;
+                    }
+                }
+
+                DataSourceConfiguration configEntity = configBuilder.newInstance();
+                config = uow.toValue( DataSourceConfiguration.class, configEntity );
+
+                // save
+                try {
+                    uow.complete();
+                } catch ( UnitOfWorkCompletionException e2 ) {
+                    InstantiationException exception = new InstantiationException( "Could not save configuration in JavaPreferences." );
+                    exception.initCause( e2 );
+                    throw exception;
+                }
+
+            }
+
+            configs.put( identity, config );
+        }
+
+        return config;
+    }
+
+    @Override
+    public final boolean isAvailable( DataSource instance )
+    {
+        if ( pools.containsValue( instance ) )
+        {
+            CircuitBreaker circuitBreaker = circuitBreakers.get( instance );
+            return circuitBreaker == null || circuitBreaker.isOn();
+        } else {
+            return false;
+        }
+    }
+
+    protected abstract PooledDataSourceType setupDataSourcePool( DataSourceConfiguration configuration )
+            throws Exception;
+
+    protected abstract void passivateDataSourcePool( PooledDataSourceType dataSourcePool )
+            throws Exception;
+
+}
diff --git a/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/DataSourceConfiguration.java b/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/DataSourceConfiguration.java
new file mode 100644
index 0000000..93a27df
--- /dev/null
+++ b/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/DataSourceConfiguration.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.library.sql.datasource;
+
+import org.apache.polygene.api.identity.HasIdentity;
+
+/**
+ * Configuration Entity for a DataSource.
+ */
+public interface DataSourceConfiguration
+        extends HasIdentity, DataSourceConfigurationState
+{
+}
diff --git a/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/DataSourceConfigurationState.java b/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/DataSourceConfigurationState.java
new file mode 100644
index 0000000..20274c4
--- /dev/null
+++ b/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/DataSourceConfigurationState.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.library.sql.datasource;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.configuration.Enabled;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Describe DataSourceConfiguration properties.
+ */
+// START SNIPPET: config
+public interface DataSourceConfigurationState
+        extends Enabled
+{
+    Property<String> driver();
+    Property<String> url();
+    @UseDefaults Property<String> username();
+    @UseDefaults Property<String> password();
+    @Optional Property<Integer> minPoolSize();
+    @Optional Property<Integer> maxPoolSize();
+    @Optional Property<Integer> loginTimeoutSeconds();
+    @Optional Property<Integer> maxConnectionAgeSeconds();
+    @Optional Property<String> validationQuery();
+    @UseDefaults Property<String> properties();
+}
+// END SNIPPET: config
diff --git a/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/DataSourceServiceImporterActivation.java b/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/DataSourceServiceImporterActivation.java
new file mode 100644
index 0000000..c28c357
--- /dev/null
+++ b/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/DataSourceServiceImporterActivation.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.library.sql.datasource;
+
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.service.ServiceReference;
+
+public interface DataSourceServiceImporterActivation
+{
+
+    void passivateDataSourceService()
+            throws Exception;
+
+    class Activator
+            extends ActivatorAdapter<ServiceReference<DataSourceServiceImporterActivation>>
+    {
+
+        @Override
+        public void beforePassivation( ServiceReference<DataSourceServiceImporterActivation> passivating )
+                throws Exception
+        {
+            passivating.get().passivateDataSourceService();
+        }
+
+    }
+
+}
diff --git a/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/DataSources.java b/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/DataSources.java
new file mode 100644
index 0000000..88aa37d
--- /dev/null
+++ b/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/DataSources.java
@@ -0,0 +1,95 @@
+/*
+ *  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.polygene.library.sql.datasource;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.net.ConnectException;
+import java.util.function.Predicate;
+import javax.sql.DataSource;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.service.ServiceImporterException;
+import org.apache.polygene.library.circuitbreaker.CircuitBreaker;
+
+import static org.apache.polygene.library.circuitbreaker.CircuitBreakers.in;
+import static org.apache.polygene.library.circuitbreaker.CircuitBreakers.rootCause;
+
+public class DataSources
+{
+
+    public static CircuitBreaker newDataSourceCircuitBreaker()
+    {
+        return newDataSourceCircuitBreaker( 5, 1000 * 60 * 5 );
+    }
+
+    public static CircuitBreaker newDataSourceCircuitBreaker( int threshold, long timeout )
+    {
+        @SuppressWarnings( "unchecked" )
+        Predicate<Throwable> in = in( ConnectException.class );
+        return new CircuitBreaker( threshold, timeout, rootCause( in ).negate() );
+    }
+
+    public static DataSource wrapWithCircuitBreaker(final Identity dataSourceIdentity, final DataSource pool, final CircuitBreaker circuitBreaker )
+    {
+        // Create wrapper
+        InvocationHandler handler = new InvocationHandler()
+        {
+            @Override
+            public Object invoke( Object proxy, Method method, Object[] args )
+                    throws Throwable
+            {
+                if ( !circuitBreaker.isOn() ) {
+                    Throwable throwable = circuitBreaker.lastThrowable();
+                    if ( throwable != null ) {
+                        throw throwable;
+                    } else {
+                        throw new ServiceImporterException( "Circuit breaker for DataSource " + dataSourceIdentity + " is not on" );
+                    }
+                }
+
+                try {
+                    Object result = method.invoke( pool, args );
+                    circuitBreaker.success();
+                    return result;
+                } catch ( IllegalAccessException e ) {
+                    circuitBreaker.throwable( e );
+                    throw e;
+                } catch ( IllegalArgumentException e ) {
+                    circuitBreaker.throwable( e );
+                    throw e;
+                } catch ( InvocationTargetException e ) {
+                    circuitBreaker.throwable( e.getCause() );
+                    throw e.getCause();
+                }
+            }
+
+        };
+
+        // Create proxy with circuit breaker
+        return ( DataSource ) Proxy.newProxyInstance( DataSource.class.getClassLoader(), new Class[]{ DataSource.class }, handler );
+    }
+
+    private DataSources()
+    {
+    }
+
+}
diff --git a/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/package.html b/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/package.html
new file mode 100644
index 0000000..2a7bc45
--- /dev/null
+++ b/libraries/sql/src/main/java/org/apache/polygene/library/sql/datasource/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL Library DataSource Support.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/sql/src/main/java/org/apache/polygene/library/sql/jmx/DataSourceConfigurationManagerService.java b/libraries/sql/src/main/java/org/apache/polygene/library/sql/jmx/DataSourceConfigurationManagerService.java
new file mode 100644
index 0000000..777d419
--- /dev/null
+++ b/libraries/sql/src/main/java/org/apache/polygene/library/sql/jmx/DataSourceConfigurationManagerService.java
@@ -0,0 +1,300 @@
+/*
+ *  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.polygene.library.sql.jmx;
+
+import java.lang.reflect.AccessibleObject;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import javax.sql.DataSource;
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.library.sql.datasource.DataSourceConfiguration;
+import org.apache.polygene.spi.PolygeneSPI;
+
+/**
+ * Expose DataSourceConfiguration through JMX.
+ * Allow configurations to be edited, and the services to be restarted.
+ */
+@Mixins( DataSourceConfigurationManagerService.Mixin.class )
+@Activators( DataSourceConfigurationManagerService.Activator.class )
+public interface DataSourceConfigurationManagerService
+{
+
+    void exportDataSources()
+            throws Exception;
+
+    void unexportDataSources()
+            throws Exception;
+
+    class Activator
+            extends ActivatorAdapter<ServiceReference<DataSourceConfigurationManagerService>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<DataSourceConfigurationManagerService> activated )
+                throws Exception
+        {
+            activated.get().exportDataSources();
+        }
+
+        @Override
+        public void beforePassivation( ServiceReference<DataSourceConfigurationManagerService> passivating )
+                throws Exception
+        {
+            passivating.get().unexportDataSources();
+        }
+
+    }
+
+    abstract class Mixin
+            implements DataSourceConfigurationManagerService
+    {
+
+        @Structure
+        UnitOfWorkFactory uowf;
+
+        @Service
+        MBeanServer server;
+
+        @Structure
+        PolygeneSPI spi;
+
+        @Structure
+        Application application;
+
+        @Service
+        Iterable<ServiceReference<DataSource>> dataSources;
+
+        @Service
+        ServiceReference<ServiceImporter<DataSource>> dataSourceService;
+
+        private List<ObjectName> configurationNames = new ArrayList<>();
+
+        @Override
+        public void exportDataSources()
+                throws MalformedObjectNameException, MBeanRegistrationException, InstanceAlreadyExistsException, NotCompliantMBeanException
+        {
+            for ( ServiceReference<DataSource> dataSource : dataSources ) {
+                ModuleDescriptor module = spi.moduleOf( dataSource );
+                EntityDescriptor descriptor = module.entityDescriptor( DataSourceConfiguration.class.getName() );
+                List<MBeanAttributeInfo> attributes = new ArrayList<>();
+                Map<String, AccessibleObject> properties = new LinkedHashMap<>();
+                descriptor.state().properties().forEach(persistentProperty -> {
+                    if ( !persistentProperty.isImmutable() ) {
+                        String propertyName = persistentProperty.qualifiedName().name();
+                        String type = persistentProperty.valueType().primaryType().getName();
+                        attributes.add( new MBeanAttributeInfo( propertyName, type, propertyName, true, true, type.equals( "java.lang.Boolean" ) ) );
+                        properties.put( propertyName, persistentProperty.accessor() );
+                    }
+                } );
+
+                List<MBeanOperationInfo> operations = new ArrayList<>();
+                operations.add( new MBeanOperationInfo( "restart", "Restart DataSource", new MBeanParameterInfo[ 0 ], "void", MBeanOperationInfo.ACTION_INFO ) );
+
+                String mbeanName = dataSource.identity().toString();
+                MBeanInfo mbeanInfo = new MBeanInfo( DataSourceConfiguration.class.getName(), mbeanName, attributes.toArray( new MBeanAttributeInfo[ attributes.size() ] ), null, operations.toArray( new MBeanOperationInfo[ operations.size() ] ), null );
+                Object mbean = new ConfigurableDataSource( dataSourceService, mbeanInfo, mbeanName, properties );
+                ObjectName configurableDataSourceName = new ObjectName( "Polygene:application=" + application.name() + ",class=Datasource,name=" + mbeanName );
+                server.registerMBean( mbean, configurableDataSourceName );
+                configurationNames.add( configurableDataSourceName );
+            }
+        }
+
+        @Override
+        public void unexportDataSources()
+                throws Exception
+        {
+            for ( ObjectName configurableServiceName : configurationNames ) {
+                server.unregisterMBean( configurableServiceName );
+            }
+        }
+
+        abstract class EditableConfiguration
+                implements DynamicMBean
+        {
+
+            MBeanInfo info;
+
+            Identity identity;
+
+            Map<String, AccessibleObject> propertyNames;
+
+            EditableConfiguration( MBeanInfo info, String identity, Map<String, AccessibleObject> propertyNames )
+            {
+                this.info = info;
+                this.identity = new StringIdentity( identity );
+                this.propertyNames = propertyNames;
+            }
+
+            @Override
+            public Object getAttribute( String name )
+                    throws AttributeNotFoundException, MBeanException, ReflectionException
+            {
+                UnitOfWork uow = uowf.newUnitOfWork();
+                try {
+                    EntityComposite configuration = uow.get( EntityComposite.class, identity );
+                    AssociationStateHolder state = spi.stateOf( configuration );
+                    AccessibleObject accessor = propertyNames.get( name );
+                    Property<Object> property = state.propertyFor( accessor );
+                    return property.get();
+                } catch ( Exception ex ) {
+                    throw new ReflectionException( ex, "Could not get attribute " + name );
+                } finally {
+                    uow.discard();
+                }
+            }
+
+            @Override
+            public void setAttribute( Attribute attribute )
+                    throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException
+            {
+                UnitOfWork uow = uowf.newUnitOfWork();
+                try {
+                    EntityComposite configuration = uow.get( EntityComposite.class, identity );
+                    AssociationStateHolder state = spi.stateOf( configuration );
+                    AccessibleObject accessor = propertyNames.get( attribute.getName() );
+                    Property<Object> property = state.propertyFor( accessor );
+                    property.set( attribute.getValue() );
+                    try {
+                        uow.complete();
+                    } catch ( UnitOfWorkCompletionException e ) {
+                        throw new ReflectionException( e );
+                    }
+                } finally {
+                    uow.discard();
+                }
+            }
+
+            @Override
+            public AttributeList getAttributes( String[] names )
+            {
+                AttributeList list = new AttributeList();
+                for ( String name : names ) {
+                    try {
+                        Object value = getAttribute( name );
+                        list.add( new Attribute( name, value ) );
+                    } catch ( AttributeNotFoundException | MBeanException | ReflectionException e ) {
+                        e.printStackTrace();
+                    }
+                }
+
+                return list;
+            }
+
+            @Override
+            public AttributeList setAttributes( AttributeList attributeList )
+            {
+                AttributeList list = new AttributeList();
+                for ( int i = 0; i < list.size(); i++ ) {
+                    Attribute attribute = ( Attribute ) list.get( i );
+
+                    try {
+                        setAttribute( attribute );
+                        list.add( attribute );
+                    } catch ( AttributeNotFoundException | InvalidAttributeValueException | ReflectionException | MBeanException e ) {
+                        e.printStackTrace();
+                    }
+                }
+
+                return list;
+            }
+
+            @Override
+            public MBeanInfo getMBeanInfo()
+            {
+                return info;
+            }
+
+        }
+
+        class ConfigurableDataSource
+                extends EditableConfiguration
+        {
+
+            private ServiceReference<ServiceImporter<DataSource>> service;
+
+            ConfigurableDataSource( ServiceReference<ServiceImporter<DataSource>> service, MBeanInfo info, String identity, Map<String, AccessibleObject> propertyNames )
+            {
+                super( info, identity, propertyNames );
+                this.service = service;
+            }
+
+            @Override
+            public Object invoke( String s, Object[] objects, String[] strings )
+                    throws MBeanException, ReflectionException
+            {
+                if ( s.equals( "restart" ) ) {
+                    try {
+                        // Refresh and restart
+                        if ( service.isActive() ) {
+                            ( ( Activation ) service ).passivate();
+                            ( ( Activation ) service ).activate();
+                        }
+
+                        return "Restarted DataSource";
+                    } catch ( Exception e ) {
+                        return "Could not restart DataSource:" + e.getMessage();
+                    }
+                }
+
+                return "Unknown operation";
+            }
+
+        }
+
+    }
+
+}
diff --git a/libraries/sql/src/main/java/org/apache/polygene/library/sql/jmx/package.html b/libraries/sql/src/main/java/org/apache/polygene/library/sql/jmx/package.html
new file mode 100644
index 0000000..3e2410f
--- /dev/null
+++ b/libraries/sql/src/main/java/org/apache/polygene/library/sql/jmx/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>SQL Library JMX Support.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/assembly/AbstractPooledDataSourceServiceAssembler.java b/libraries/sql/src/main/java/org/qi4j/library/sql/assembly/AbstractPooledDataSourceServiceAssembler.java
deleted file mode 100644
index b1d2c05..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/assembly/AbstractPooledDataSourceServiceAssembler.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.library.sql.assembly;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.conversion.values.EntityToValueService;
-import org.qi4j.library.sql.datasource.DataSourceConfiguration;
-import org.qi4j.library.sql.datasource.DataSourceConfigurationValue;
-
-public abstract class AbstractPooledDataSourceServiceAssembler<AssemblerType>
-    extends Assemblers.VisibilityIdentityConfig<AssemblerType>
-{
-    public static String DEFAULT_DATASOURCE_SERVICE_IDENTITY = "datasource-service";
-
-    @Override
-    public final void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.values( DataSourceConfigurationValue.class ).visibleIn( Visibility.module );
-        module.services( EntityToValueService.class ).visibleIn( Visibility.module );
-        if( hasConfig() )
-        {
-            configModule().entities( DataSourceConfiguration.class ).visibleIn( configVisibility() );
-        }
-        onAssemble( module, identity() == null ? DEFAULT_DATASOURCE_SERVICE_IDENTITY : identity(), visibility() );
-    }
-
-    protected abstract void onAssemble( ModuleAssembly module, String identity, Visibility visibility );
-}
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/assembly/DataSourceAssembler.java b/libraries/sql/src/main/java/org/qi4j/library/sql/assembly/DataSourceAssembler.java
deleted file mode 100644
index d7993e2..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/assembly/DataSourceAssembler.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2011 Rickard Öberg.
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.library.sql.assembly;
-
-import javax.sql.DataSource;
-import org.qi4j.api.service.importer.ServiceInstanceImporter;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.circuitbreaker.CircuitBreaker;
-import org.qi4j.library.sql.datasource.DataSources;
-
-/**
- * Use this Assembler to register a javax.sql.DataSource.
- */
-public class DataSourceAssembler
-    extends Assemblers.VisibilityIdentity<DataSourceAssembler>
-{
-    public static String DEFAULT_DATASOURCE_IDENTITY = "datasource";
-
-    private String dataSourceServiceId = AbstractPooledDataSourceServiceAssembler.DEFAULT_DATASOURCE_SERVICE_IDENTITY;
-
-    private CircuitBreaker circuitBreaker;
-
-    public DataSourceAssembler()
-    {
-        identifiedBy( DEFAULT_DATASOURCE_IDENTITY );
-    }
-
-    public DataSourceAssembler withDataSourceServiceIdentity( String dataSourceServiceId )
-    {
-        NullArgumentException.validateNotNull( "DataSourceService identity", dataSourceServiceId );
-        this.dataSourceServiceId = dataSourceServiceId;
-        return this;
-    }
-
-    public DataSourceAssembler withCircuitBreaker()
-    {
-        this.circuitBreaker = DataSources.newDataSourceCircuitBreaker();
-        return this;
-    }
-
-    public DataSourceAssembler withCircuitBreaker( CircuitBreaker circuitBreaker )
-    {
-        NullArgumentException.validateNotNull( "CircuitBreaker", circuitBreaker );
-        this.circuitBreaker = circuitBreaker;
-        return this;
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.importedServices( DataSource.class ).
-            importedBy( ServiceInstanceImporter.class ).
-            setMetaInfo( dataSourceServiceId ).
-            identifiedBy( identity() ).
-            visibleIn( visibility() );
-        if( circuitBreaker != null )
-        {
-            module.importedServices( DataSource.class ).identifiedBy( identity() ).setMetaInfo( circuitBreaker );
-        }
-    }
-}
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/assembly/DataSourceJMXAssembler.java b/libraries/sql/src/main/java/org/qi4j/library/sql/assembly/DataSourceJMXAssembler.java
deleted file mode 100644
index cd637bc..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/assembly/DataSourceJMXAssembler.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.library.sql.assembly;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.sql.jmx.DataSourceConfigurationManagerService;
-
-public class DataSourceJMXAssembler
-    extends Assemblers.Visibility<DataSourceJMXAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( DataSourceConfigurationManagerService.class ).visibleIn( visibility() ).instantiateOnStartup();
-    }
-}
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/assembly/ExternalDataSourceAssembler.java b/libraries/sql/src/main/java/org/qi4j/library/sql/assembly/ExternalDataSourceAssembler.java
deleted file mode 100644
index 4be91b3..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/assembly/ExternalDataSourceAssembler.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2010 Paul Merlin.
- *
- * Licensed  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.qi4j.library.sql.assembly;
-
-import javax.sql.DataSource;
-import org.qi4j.api.util.NullArgumentException;
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.circuitbreaker.CircuitBreaker;
-import org.qi4j.library.sql.datasource.DataSources;
-
-public class ExternalDataSourceAssembler
-    extends Assemblers.VisibilityIdentity<ExternalDataSourceAssembler>
-{
-    public static String DEFAULT_DATASOURCE_IDENTITY = "external-datasource";
-
-    private DataSource externalDataSource;
-
-    private CircuitBreaker circuitBreaker;
-
-    public ExternalDataSourceAssembler()
-    {
-        identifiedBy( DEFAULT_DATASOURCE_IDENTITY );
-    }
-
-    public ExternalDataSourceAssembler( DataSource externalDataSource )
-    {
-        NullArgumentException.validateNotNull( "DataSource", externalDataSource );
-        this.externalDataSource = externalDataSource;
-    }
-
-    public ExternalDataSourceAssembler withCircuitBreaker()
-    {
-        this.circuitBreaker = DataSources.newDataSourceCircuitBreaker();
-        return this;
-    }
-
-    public ExternalDataSourceAssembler withCircuitBreaker( CircuitBreaker circuitBreaker )
-    {
-        NullArgumentException.validateNotNull( "CircuitBreaker", circuitBreaker );
-        this.circuitBreaker = circuitBreaker;
-        return this;
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        if( circuitBreaker != null )
-        {
-            externalDataSource = DataSources.wrapWithCircuitBreaker( identity(), externalDataSource, circuitBreaker );
-        }
-        module.importedServices( DataSource.class ).
-            identifiedBy( identity() ).
-            visibleIn( visibility() ).
-            setMetaInfo( externalDataSource );
-    }
-}
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/assembly/package.html b/libraries/sql/src/main/java/org/qi4j/library/sql/assembly/package.html
deleted file mode 100644
index b3b62a7..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/assembly/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL Library Assembly.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/common/Databases.java b/libraries/sql/src/main/java/org/qi4j/library/sql/common/Databases.java
deleted file mode 100644
index 989a0a9..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/common/Databases.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.common;
-
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import javax.sql.DataSource;
-import org.qi4j.functional.Visitor;
-import org.qi4j.io.Input;
-import org.qi4j.io.Output;
-import org.qi4j.io.Receiver;
-import org.qi4j.io.Sender;
-
-/**
- * Utility methods for performing SQL calls wrapping a given DataSource.
- */
-public class Databases
-{
-
-    DataSource source;
-
-    /**
-     * Create a new Databases wrapper for a given DataSource.
-     */
-    public Databases( DataSource source )
-    {
-        this.source = source;
-    }
-
-    /**
-     * Perform SQL update statement.
-     */
-    public int update( String sql )
-            throws SQLException
-    {
-        Connection connection = null;
-        PreparedStatement stmt = null;
-        try {
-            connection = source.getConnection();
-            stmt = connection.prepareStatement( sql );
-            return stmt.executeUpdate();
-        } finally {
-            SQLUtil.closeQuietly( stmt );
-            SQLUtil.closeQuietly( connection );
-        }
-    }
-
-    /**
-     * Perform SQL update statement.
-     *
-     * If the SQL string contains ? placeholders, use the StatementVisitor to
-     * update the PreparedStatement with actual values.
-     */
-    public int update( String sql, StatementVisitor visitor )
-            throws SQLException
-    {
-        Connection connection = null;
-        PreparedStatement stmt = null;
-        try {
-            connection = source.getConnection();
-            stmt = connection.prepareStatement( sql );
-            visitor.visit( stmt );
-            return stmt.executeUpdate();
-        } finally {
-            SQLUtil.closeQuietly( stmt );
-            SQLUtil.closeQuietly( connection );
-        }
-    }
-
-    /**
-     * Perform SQL query and let visitor handle results.
-     */
-    public void query( String sql, ResultSetVisitor visitor )
-            throws SQLException
-    {
-        query( sql, null, visitor );
-    }
-
-    /**
-     * Perform SQL query and let visitor handle results.
-     *
-     * If the SQL string contains ? placeholders, use the StatementVisitor to
-     * update the PreparedStatement with actual values.
-     */
-    public void query( String sql, StatementVisitor statement, ResultSetVisitor resultsetVisitor )
-            throws SQLException
-    {
-        Connection connection = null;
-        PreparedStatement stmt = null;
-        ResultSet resultSet = null;
-        try {
-            connection = source.getConnection();
-            stmt = connection.prepareStatement( sql );
-            if ( statement != null ) {
-                statement.visit( stmt );
-            }
-            resultSet = stmt.executeQuery();
-            while ( resultSet.next() ) {
-                if ( !resultsetVisitor.visit( resultSet ) ) {
-                    return;
-                }
-            }
-            resultSet.close();
-        } finally {
-            SQLUtil.closeQuietly( resultSet );
-            SQLUtil.closeQuietly( stmt );
-            SQLUtil.closeQuietly( connection );
-        }
-    }
-
-    /**
-     * Perform SQL query and provide results as an Input.
-     *
-     * This makes it possible to combine SQL data with the I/O API.
-     */
-    public Input<ResultSet, SQLException> query( final String sql )
-    {
-        return new Input<ResultSet, SQLException>()
-        {
-
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super ResultSet, ReceiverThrowableType> output )
-                    throws SQLException, ReceiverThrowableType
-            {
-                output.receiveFrom( new Sender<ResultSet, SQLException>()
-                {
-
-                    @Override
-                    public <ReceiverThrowableType extends Throwable> void sendTo( final Receiver<? super ResultSet, ReceiverThrowableType> receiver )
-                            throws ReceiverThrowableType, SQLException
-                    {
-                        query( sql, new ResultSetVisitor()
-                        {
-
-                            @Override
-                            public boolean visit( ResultSet visited )
-                                    throws SQLException
-                            {
-                                try {
-                                    receiver.receive( visited );
-                                } catch ( Throwable receiverThrowableType ) {
-                                    throw new SQLException( receiverThrowableType );
-                                }
-
-                                return true;
-                            }
-
-                        } );
-                    }
-
-                } );
-            }
-
-        };
-    }
-
-    /**
-     * Perform SQL query and provide results as an Input.
-     *
-     * This makes it possible to combine SQL data with the I/O API. If the SQL
-     * string contains ? placeholders, use the StatementVisitor to update the
-     * PreparedStatement with actual values.
-     */
-    public Input<ResultSet, SQLException> query( final String sql, final StatementVisitor visitor )
-    {
-        return new Input<ResultSet, SQLException>()
-        {
-
-            @Override
-            public <ReceiverThrowableType extends Throwable> void transferTo( Output<? super ResultSet, ReceiverThrowableType> output )
-                    throws SQLException, ReceiverThrowableType
-            {
-                output.receiveFrom( new Sender<ResultSet, SQLException>()
-                {
-
-                    @Override
-                    public <ReceiverThrowableType extends Throwable> void sendTo( final Receiver<? super ResultSet, ReceiverThrowableType> receiver )
-                            throws ReceiverThrowableType, SQLException
-                    {
-                        query( sql, visitor, new ResultSetVisitor()
-                        {
-
-                            @Override
-                            public boolean visit( ResultSet visited )
-                                    throws SQLException
-                            {
-                                try {
-                                    receiver.receive( visited );
-                                } catch ( Throwable receiverThrowableType ) {
-                                    throw new SQLException( receiverThrowableType );
-                                }
-
-                                return true;
-                            }
-
-                        } );
-                    }
-
-                } );
-            }
-
-        };
-    }
-
-    /**
-     * Visitor for PreparedStatements.
-     *
-     * These are created when the SQL statements contain ? placeholders.
-     */
-    public interface StatementVisitor
-    {
-
-        void visit( PreparedStatement preparedStatement )
-                throws SQLException;
-
-    }
-
-    /**
-     * Visitor for the ResultSet.
-     *
-     * Only access data from the given ResultSet, as the iteration will be done
-     * by this API.
-     */
-    public interface ResultSetVisitor
-            extends Visitor<ResultSet, SQLException>
-    {
-    }
-
-}
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/common/SQLConfiguration.java b/libraries/sql/src/main/java/org/qi4j/library/sql/common/SQLConfiguration.java
deleted file mode 100644
index e03fc7d..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/common/SQLConfiguration.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.common;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-/**
- * Typical configuration for service, which uses a {@link javax.sql.DataSource} as connection to SQL
- * database, and given schema name as schema to create tables in.
- */
-public interface SQLConfiguration
-        extends ConfigurationComposite
-{
-
-    /**
-     * The schema name to use to create/find tables.
-     */
-    @Optional
-    Property<String> schemaName();
-
-}
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/common/SQLUtil.java b/libraries/sql/src/main/java/org/qi4j/library/sql/common/SQLUtil.java
deleted file mode 100644
index 98f1396..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/common/SQLUtil.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2010, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.common;
-
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-
-public class SQLUtil
-{
-
-    public static void closeQuietly( ResultSet resultSet )
-    {
-        if ( resultSet != null ) {
-            try {
-                resultSet.close();
-            } catch ( SQLException ignored ) {
-            }
-        }
-    }
-
-    public static void closeQuietly( Statement select )
-    {
-        if ( select != null ) {
-            try {
-                select.close();
-            } catch ( SQLException ignored ) {
-            }
-        }
-    }
-
-    public static void closeQuietly( Connection connection )
-    {
-        if ( connection != null ) {
-            try {
-                connection.close();
-            } catch ( SQLException ignored ) {
-            }
-        }
-    }
-
-    public static void rollbackQuietly( Connection connection )
-    {
-        if ( connection != null ) {
-            try {
-                connection.rollback();
-            } catch ( SQLException ignored ) {
-            }
-        }
-    }
-
-    private SQLUtil()
-    {
-    }
-
-}
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/common/package.html b/libraries/sql/src/main/java/org/qi4j/library/sql/common/package.html
deleted file mode 100644
index e8cb99d..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/common/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL Library Utilities.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/AbstractDataSourceServiceImporterMixin.java b/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/AbstractDataSourceServiceImporterMixin.java
deleted file mode 100644
index b5d959b..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/AbstractDataSourceServiceImporterMixin.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.datasource;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.sql.SQLException;
-import java.util.HashMap;
-import java.util.Map;
-import javax.sql.DataSource;
-import org.qi4j.api.composite.PropertyMapper;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.service.ServiceImporterException;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.library.circuitbreaker.CircuitBreaker;
-import org.qi4j.library.conversion.values.EntityToValue;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public abstract class AbstractDataSourceServiceImporterMixin<PooledDataSourceType extends DataSource>
-        implements ServiceImporter<DataSource>, DataSourceServiceImporterActivation
-{
-
-    protected static final Logger LOGGER = LoggerFactory.getLogger( AbstractDataSourceServiceImporterMixin.class );
-
-    private final Map<String, DataSourceConfigurationValue> configs = new HashMap<String, DataSourceConfigurationValue>();
-
-    private final Map<String, PooledDataSourceType> pools = new HashMap<String, PooledDataSourceType>();
-
-    private final Map<DataSource, CircuitBreaker> circuitBreakers = new HashMap<DataSource, CircuitBreaker>();
-
-    @Structure
-    protected Module module;
-
-    @Service
-    private EntityToValue entityToValue;
-
-    @Override
-    public final void passivateDataSourceService()
-            throws Exception
-    {
-        for ( PooledDataSourceType pool : pools.values() ) {
-            passivateDataSourcePool( pool );
-        }
-        pools.clear();
-        configs.clear();
-        circuitBreakers.clear();
-    }
-
-    @Override
-    public final synchronized DataSource importService( final ImportedServiceDescriptor importedServiceDescriptor )
-            throws ServiceImporterException
-    {
-        PooledDataSourceType pool = pools.get( importedServiceDescriptor.identity() );
-        if ( pool == null ) {
-
-            try {
-
-                DataSourceConfigurationValue config = getConfiguration( importedServiceDescriptor.identity() );
-                if ( !config.enabled().get() ) {
-                    // Not started
-                    throw new ServiceImporterException( "DataSource not enabled" );
-                }
-
-                // Instantiate pool
-                pool = setupDataSourcePool( config );
-                pools.put( importedServiceDescriptor.identity(), pool );
-
-                LOGGER.info( "Starting up DataSource '" + importedServiceDescriptor.identity() + "' for: {}@{}", config.username().get(), config.url().get() );
-
-            } catch ( Exception e ) {
-                throw new ServiceImporterException( e );
-            }
-
-            // Test the pool
-            ClassLoader cl = Thread.currentThread().getContextClassLoader();
-            Thread.currentThread().setContextClassLoader( null );
-            try {
-                pool.getConnection().close();
-                LOGGER.info( "Database for DataSource is up!" );
-            } catch ( SQLException e ) {
-                LOGGER.warn( "Database for DataSource " + importedServiceDescriptor.identity() + " is not currently available" );
-                throw new ServiceImporterException( "Database for DataSource " + importedServiceDescriptor.identity() + " is not currently available", e );
-            } finally {
-                Thread.currentThread().setContextClassLoader( cl );
-            }
-        }
-
-        // Check if circuitbreaker is used
-        final CircuitBreaker circuitBreaker = importedServiceDescriptor.metaInfo( CircuitBreaker.class );
-        if ( circuitBreaker != null ) {
-
-            DataSource wrappedDataSource = DataSources.wrapWithCircuitBreaker( importedServiceDescriptor.identity(), pool, circuitBreaker );
-            circuitBreakers.put( pool, circuitBreaker );
-            return wrappedDataSource;
-
-        } else {
-
-            return pool;
-
-        }
-    }
-
-    private DataSourceConfigurationValue getConfiguration( String identity )
-            throws InstantiationException
-    {
-        DataSourceConfigurationValue config = configs.get( identity );
-        if ( config == null ) {
-            UnitOfWork uow = module.newUnitOfWork( UsecaseBuilder.newUsecase( "Create DataSource pool configuration" ) );
-
-            try {
-                DataSourceConfiguration configEntity = uow.get( DataSourceConfiguration.class, identity );
-                config = entityToValue.convert( DataSourceConfigurationValue.class, configEntity );
-            } catch ( NoSuchEntityException e ) {
-                EntityBuilder<DataSourceConfiguration> configBuilder = uow.newEntityBuilder( DataSourceConfiguration.class, identity );
-
-                // Check for defaults
-                String s = identity + ".properties";
-                InputStream asStream = DataSourceConfiguration.class.getClassLoader().getResourceAsStream( s );
-                if ( asStream != null ) {
-                    try {
-                        PropertyMapper.map( asStream, configBuilder.instance() );
-                    } catch ( IOException e1 ) {
-                        uow.discard();
-                        InstantiationException exception = new InstantiationException( "Could not read underlying Properties file." );
-                        exception.initCause( e1 );
-                        throw exception;
-                    }
-                }
-
-                DataSourceConfiguration configEntity = configBuilder.newInstance();
-                config = entityToValue.convert( DataSourceConfigurationValue.class, configEntity );
-
-                // save
-                try {
-                    uow.complete();
-                } catch ( UnitOfWorkCompletionException e2 ) {
-                    InstantiationException exception = new InstantiationException( "Could not save configuration in JavaPreferences." );
-                    exception.initCause( e2 );
-                    throw exception;
-                }
-
-            }
-
-            configs.put( identity, config );
-        }
-
-        return config;
-    }
-
-    @Override
-    public final boolean isAvailable( DataSource instance )
-    {
-        if ( pools.containsValue( instance ) ) {
-            CircuitBreaker circuitBreaker = circuitBreakers.get( instance );
-            if ( circuitBreaker != null ) {
-                return circuitBreaker.isOn();
-            } else {
-                return true;
-            }
-        } else {
-            return false;
-        }
-    }
-
-    protected abstract PooledDataSourceType setupDataSourcePool( DataSourceConfigurationValue configuration )
-            throws Exception;
-
-    protected abstract void passivateDataSourcePool( PooledDataSourceType dataSourcePool )
-            throws Exception;
-
-}
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/DataSourceConfiguration.java b/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/DataSourceConfiguration.java
deleted file mode 100644
index c679bda..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/DataSourceConfiguration.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.datasource;
-
-import org.qi4j.api.configuration.ConfigurationComposite;
-
-/**
- * Configuration Entity for a DataSource.
- */
-public interface DataSourceConfiguration
-        extends ConfigurationComposite, DataSourceConfigurationState
-{
-}
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/DataSourceConfigurationState.java b/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/DataSourceConfigurationState.java
deleted file mode 100644
index f27b93c..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/DataSourceConfigurationState.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.datasource;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.Enabled;
-import org.qi4j.api.property.Property;
-
-/**
- * Describe DataSourceConfiguration properties.
- */
-// START SNIPPET: config
-public interface DataSourceConfigurationState
-        extends Enabled
-{
-    Property<String> driver();
-    Property<String> url();
-    @UseDefaults Property<String> username();
-    @UseDefaults Property<String> password();
-    @Optional Property<Integer> minPoolSize();
-    @Optional Property<Integer> maxPoolSize();
-    @Optional Property<Integer> loginTimeoutSeconds();
-    @Optional Property<Integer> maxConnectionAgeSeconds();
-    @Optional Property<String> validationQuery();
-    @UseDefaults Property<String> properties();
-}
-// END SNIPPET: config
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/DataSourceConfigurationValue.java b/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/DataSourceConfigurationValue.java
deleted file mode 100644
index b5a40e8..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/DataSourceConfigurationValue.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.datasource;
-
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * DataSource configuration as a Value to be used outside of UoWs.
- */
-public interface DataSourceConfigurationValue
-        extends ValueComposite, DataSourceConfigurationState
-{
-}
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/DataSourceServiceImporterActivation.java b/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/DataSourceServiceImporterActivation.java
deleted file mode 100644
index b039f7a..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/DataSourceServiceImporterActivation.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.datasource;
-
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.service.ServiceReference;
-
-public interface DataSourceServiceImporterActivation
-{
-
-    void passivateDataSourceService()
-            throws Exception;
-
-    class Activator
-            extends ActivatorAdapter<ServiceReference<DataSourceServiceImporterActivation>>
-    {
-
-        @Override
-        public void beforePassivation( ServiceReference<DataSourceServiceImporterActivation> passivating )
-                throws Exception
-        {
-            passivating.get().passivateDataSourceService();
-        }
-
-    }
-
-}
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/DataSources.java b/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/DataSources.java
deleted file mode 100644
index 8a52c41..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/DataSources.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.datasource;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.net.ConnectException;
-import javax.sql.DataSource;
-import org.qi4j.api.service.ServiceImporterException;
-import org.qi4j.functional.Specification;
-import org.qi4j.library.circuitbreaker.CircuitBreaker;
-
-import static org.qi4j.functional.Specifications.not;
-import static org.qi4j.library.circuitbreaker.CircuitBreakers.in;
-import static org.qi4j.library.circuitbreaker.CircuitBreakers.rootCause;
-
-public class DataSources
-{
-
-    public static CircuitBreaker newDataSourceCircuitBreaker()
-    {
-        return newDataSourceCircuitBreaker( 5, 1000 * 60 * 5 );
-    }
-
-    public static CircuitBreaker newDataSourceCircuitBreaker( int threshold, long timeout )
-    {
-        @SuppressWarnings( "unchecked" )
-        Specification<Throwable> in = in( ConnectException.class );
-        return new CircuitBreaker( threshold, timeout, not( rootCause( in ) ) );
-    }
-
-    public static DataSource wrapWithCircuitBreaker( final String dataSourceIdentity, final DataSource pool, final CircuitBreaker circuitBreaker )
-    {
-        // Create wrapper
-        InvocationHandler handler = new InvocationHandler()
-        {
-            @Override
-            public Object invoke( Object proxy, Method method, Object[] args )
-                    throws Throwable
-            {
-                if ( !circuitBreaker.isOn() ) {
-                    Throwable throwable = circuitBreaker.lastThrowable();
-                    if ( throwable != null ) {
-                        throw throwable;
-                    } else {
-                        throw new ServiceImporterException( "Circuit breaker for DataSource " + dataSourceIdentity + " is not on" );
-                    }
-                }
-
-                try {
-                    Object result = method.invoke( pool, args );
-                    circuitBreaker.success();
-                    return result;
-                } catch ( IllegalAccessException e ) {
-                    circuitBreaker.throwable( e );
-                    throw e;
-                } catch ( IllegalArgumentException e ) {
-                    circuitBreaker.throwable( e );
-                    throw e;
-                } catch ( InvocationTargetException e ) {
-                    circuitBreaker.throwable( e.getCause() );
-                    throw e.getCause();
-                }
-            }
-
-        };
-
-        // Create proxy with circuit breaker
-        return ( DataSource ) Proxy.newProxyInstance( DataSource.class.getClassLoader(), new Class[]{ DataSource.class }, handler );
-    }
-
-    private DataSources()
-    {
-    }
-
-}
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/package.html b/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/package.html
deleted file mode 100644
index 3d3502d..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/datasource/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL Library DataSource Support.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/jmx/DataSourceConfigurationManagerService.java b/libraries/sql/src/main/java/org/qi4j/library/sql/jmx/DataSourceConfigurationManagerService.java
deleted file mode 100644
index 5833f53..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/jmx/DataSourceConfigurationManagerService.java
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.jmx;
-
-import java.lang.reflect.AccessibleObject;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import javax.management.Attribute;
-import javax.management.AttributeList;
-import javax.management.AttributeNotFoundException;
-import javax.management.DynamicMBean;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InvalidAttributeValueException;
-import javax.management.MBeanAttributeInfo;
-import javax.management.MBeanException;
-import javax.management.MBeanInfo;
-import javax.management.MBeanOperationInfo;
-import javax.management.MBeanParameterInfo;
-import javax.management.MBeanRegistrationException;
-import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.ObjectName;
-import javax.management.ReflectionException;
-import javax.sql.DataSource;
-import org.qi4j.api.activation.Activation;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.library.sql.datasource.DataSourceConfiguration;
-import org.qi4j.spi.Qi4jSPI;
-
-/**
- * Expose DataSourceConfiguration through JMX.
- * Allow configurations to be edited, and the services to be restarted.
- */
-@Mixins( DataSourceConfigurationManagerService.Mixin.class )
-@Activators( DataSourceConfigurationManagerService.Activator.class )
-public interface DataSourceConfigurationManagerService
-        extends ServiceComposite
-{
-
-    void exportDataSources()
-            throws Exception;
-
-    void unexportDataSources()
-            throws Exception;
-
-    class Activator
-            extends ActivatorAdapter<ServiceReference<DataSourceConfigurationManagerService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<DataSourceConfigurationManagerService> activated )
-                throws Exception
-        {
-            activated.get().exportDataSources();
-        }
-
-        @Override
-        public void beforePassivation( ServiceReference<DataSourceConfigurationManagerService> passivating )
-                throws Exception
-        {
-            passivating.get().unexportDataSources();
-        }
-
-    }
-
-    abstract class Mixin
-            implements DataSourceConfigurationManagerService
-    {
-
-        @Structure
-        Module module;
-
-        @Service
-        MBeanServer server;
-
-        @Structure
-        Qi4jSPI spi;
-
-        @Structure
-        Application application;
-
-        @Service
-        Iterable<ServiceReference<DataSource>> dataSources;
-
-        @Service
-        ServiceReference<ServiceImporter<DataSource>> dataSourceService;
-
-        private List<ObjectName> configurationNames = new ArrayList<ObjectName>();
-
-        @Override
-        public void exportDataSources()
-                throws MalformedObjectNameException, MBeanRegistrationException, InstanceAlreadyExistsException, NotCompliantMBeanException
-        {
-            for ( ServiceReference<DataSource> dataSource : dataSources ) {
-                String name = dataSource.identity();
-                Module module = ( Module ) spi.moduleOf( dataSource );
-                EntityDescriptor descriptor = module.entityDescriptor( DataSourceConfiguration.class.getName() );
-                List<MBeanAttributeInfo> attributes = new ArrayList<MBeanAttributeInfo>();
-                Map<String, AccessibleObject> properties = new LinkedHashMap<String, AccessibleObject>();
-                for ( PropertyDescriptor persistentProperty : descriptor.state().properties() ) {
-                    if ( !persistentProperty.isImmutable() ) {
-                        String propertyName = persistentProperty.qualifiedName().name();
-                        String type = persistentProperty.valueType().mainType().getName();
-                        attributes.add( new MBeanAttributeInfo( propertyName, type, propertyName, true, true, type.equals( "java.lang.Boolean" ) ) );
-                        properties.put( propertyName, persistentProperty.accessor() );
-                    }
-                }
-
-                List<MBeanOperationInfo> operations = new ArrayList<MBeanOperationInfo>();
-                operations.add( new MBeanOperationInfo( "restart", "Restart DataSource", new MBeanParameterInfo[ 0 ], "void", MBeanOperationInfo.ACTION_INFO ) );
-
-                MBeanInfo mbeanInfo = new MBeanInfo( DataSourceConfiguration.class.getName(), name, attributes.toArray( new MBeanAttributeInfo[ attributes.size() ] ), null, operations.toArray( new MBeanOperationInfo[ operations.size() ] ), null );
-                Object mbean = new ConfigurableDataSource( dataSourceService, mbeanInfo, name, properties );
-                ObjectName configurableDataSourceName = new ObjectName( "Zest:application=" + application.name() + ",class=Datasource,name=" + name );
-                server.registerMBean( mbean, configurableDataSourceName );
-                configurationNames.add( configurableDataSourceName );
-            }
-        }
-
-        @Override
-        public void unexportDataSources()
-                throws Exception
-        {
-            for ( ObjectName configurableServiceName : configurationNames ) {
-                server.unregisterMBean( configurableServiceName );
-            }
-        }
-
-        abstract class EditableConfiguration
-                implements DynamicMBean
-        {
-
-            MBeanInfo info;
-
-            String identity;
-
-            Map<String, AccessibleObject> propertyNames;
-
-            EditableConfiguration( MBeanInfo info, String identity, Map<String, AccessibleObject> propertyNames )
-            {
-                this.info = info;
-                this.identity = identity;
-                this.propertyNames = propertyNames;
-            }
-
-            @Override
-            public Object getAttribute( String name )
-                    throws AttributeNotFoundException, MBeanException, ReflectionException
-            {
-                UnitOfWork uow = module.newUnitOfWork();
-                try {
-                    EntityComposite configuration = uow.get( EntityComposite.class, identity );
-                    AssociationStateHolder state = spi.stateOf( configuration );
-                    AccessibleObject accessor = propertyNames.get( name );
-                    Property<Object> property = state.propertyFor( accessor );
-                    return property.get();
-                } catch ( Exception ex ) {
-                    throw new ReflectionException( ex, "Could not get attribute " + name );
-                } finally {
-                    uow.discard();
-                }
-            }
-
-            @Override
-            public void setAttribute( Attribute attribute )
-                    throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException
-            {
-                UnitOfWork uow = module.newUnitOfWork();
-                try {
-                    EntityComposite configuration = uow.get( EntityComposite.class, identity );
-                    AssociationStateHolder state = spi.stateOf( configuration );
-                    AccessibleObject accessor = propertyNames.get( attribute.getName() );
-                    Property<Object> property = state.propertyFor( accessor );
-                    property.set( attribute.getValue() );
-                    try {
-                        uow.complete();
-                    } catch ( UnitOfWorkCompletionException e ) {
-                        throw new ReflectionException( e );
-                    }
-                } finally {
-                    uow.discard();
-                }
-            }
-
-            @Override
-            public AttributeList getAttributes( String[] names )
-            {
-                AttributeList list = new AttributeList();
-                for ( String name : names ) {
-                    try {
-                        Object value = getAttribute( name );
-                        list.add( new Attribute( name, value ) );
-                    } catch ( AttributeNotFoundException e ) {
-                        e.printStackTrace();
-                    } catch ( MBeanException e ) {
-                        e.printStackTrace();
-                    } catch ( ReflectionException e ) {
-                        e.printStackTrace();
-                    }
-                }
-
-                return list;
-            }
-
-            @Override
-            public AttributeList setAttributes( AttributeList attributeList )
-            {
-                AttributeList list = new AttributeList();
-                for ( int i = 0; i < list.size(); i++ ) {
-                    Attribute attribute = ( Attribute ) list.get( i );
-
-                    try {
-                        setAttribute( attribute );
-                        list.add( attribute );
-                    } catch ( AttributeNotFoundException e ) {
-                        e.printStackTrace();
-                    } catch ( InvalidAttributeValueException e ) {
-                        e.printStackTrace();
-                    } catch ( MBeanException e ) {
-                        e.printStackTrace();
-                    } catch ( ReflectionException e ) {
-                        e.printStackTrace();
-                    }
-                }
-
-                return list;
-            }
-
-            @Override
-            public MBeanInfo getMBeanInfo()
-            {
-                return info;
-            }
-
-        }
-
-        class ConfigurableDataSource
-                extends EditableConfiguration
-        {
-
-            private ServiceReference<ServiceImporter<DataSource>> service;
-
-            ConfigurableDataSource( ServiceReference<ServiceImporter<DataSource>> service, MBeanInfo info, String identity, Map<String, AccessibleObject> propertyNames )
-            {
-                super( info, identity, propertyNames );
-                this.service = service;
-            }
-
-            @Override
-            public Object invoke( String s, Object[] objects, String[] strings )
-                    throws MBeanException, ReflectionException
-            {
-                if ( s.equals( "restart" ) ) {
-                    try {
-                        // Refresh and restart
-                        if ( service.isActive() ) {
-                            ( ( Activation ) service ).passivate();
-                            ( ( Activation ) service ).activate();
-                        }
-
-                        return "Restarted DataSource";
-                    } catch ( Exception e ) {
-                        return "Could not restart DataSource:" + e.getMessage();
-                    }
-                }
-
-                return "Unknown operation";
-            }
-
-        }
-
-    }
-
-}
diff --git a/libraries/sql/src/main/java/org/qi4j/library/sql/jmx/package.html b/libraries/sql/src/main/java/org/qi4j/library/sql/jmx/package.html
deleted file mode 100644
index ee7f93f..0000000
--- a/libraries/sql/src/main/java/org/qi4j/library/sql/jmx/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>SQL Library JMX Support.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/sql/src/test/java/org/apache/polygene/library/sql/DocumentationSupport.java b/libraries/sql/src/test/java/org/apache/polygene/library/sql/DocumentationSupport.java
new file mode 100644
index 0000000..70f856f
--- /dev/null
+++ b/libraries/sql/src/test/java/org/apache/polygene/library/sql/DocumentationSupport.java
@@ -0,0 +1,118 @@
+/*
+ *  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.polygene.library.sql;
+
+import javax.sql.DataSource;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.circuitbreaker.CircuitBreaker;
+import org.apache.polygene.library.sql.assembly.DataSourceAssembler;
+import org.apache.polygene.library.sql.bonecp.BoneCPDataSourceServiceAssembler;
+import org.apache.polygene.library.sql.dbcp.DBCPDataSourceServiceAssembler;
+
+import static org.apache.polygene.library.sql.DocumentationSupport.Constants.DS_ID;
+import static org.apache.polygene.library.sql.DocumentationSupport.Constants.DS_SERVICE_ID;
+import static org.apache.polygene.library.sql.DocumentationSupport.Constants.OTHER_DS_ID;
+import static org.apache.polygene.library.sql.datasource.DataSources.newDataSourceCircuitBreaker;
+
+class DocumentationSupport
+{
+    interface Constants
+    {
+        String DS_ID = "datasource";
+
+        String OTHER_DS_ID = "datasource2";
+
+        String DS_SERVICE_ID = "datasource-service";
+    }
+
+    class CircuitBreakerDoc
+        implements Assembler
+    {
+        // START SNIPPET: cb-datasource
+        @Service
+        DataSource dataSource; // Wrapped with a CircuitBreaker proxy
+        // END SNIPPET: cb-datasource
+
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            // START SNIPPET: cb-assembly
+            CircuitBreaker circuitBreaker = newDataSourceCircuitBreaker( 5 /* threshold */,
+                                                                         1000 * 60 * 5 /* 5min timeout */ );
+            new DataSourceAssembler().
+                withDataSourceServiceIdentity( DS_SERVICE_ID ).
+                identifiedBy( DS_ID ).
+                visibleIn( Visibility.layer ).
+                withCircuitBreaker( circuitBreaker ).
+                assemble( module );
+            // END SNIPPET: cb-assembly
+        }
+    }
+
+    class PoolsDoc
+        implements Assembler
+    {
+        @Override
+        public void assemble( ModuleAssembly module )
+            throws AssemblyException
+        {
+            ModuleAssembly config = module;
+
+            // START SNIPPET: bonecp
+            // Assemble the BoneCP based Service Importer
+            new BoneCPDataSourceServiceAssembler().
+                identifiedBy( DS_SERVICE_ID ).
+                visibleIn( Visibility.module ).
+                withConfig( config, Visibility.layer ).
+                assemble( module );
+            // END SNIPPET: bonecp
+
+            // START SNIPPET: dbcp
+            // Assemble the Apache DBCP based Service Importer
+            new DBCPDataSourceServiceAssembler().
+                identifiedBy( DS_SERVICE_ID ).
+                visibleIn( Visibility.module ).
+                withConfig( config, Visibility.layer ).
+                assemble( module );
+            // END SNIPPET: dbcp
+
+            // START SNIPPET: datasource
+            // Assemble a DataSource
+            new DataSourceAssembler().
+                withDataSourceServiceIdentity( DS_SERVICE_ID ).
+                identifiedBy( DS_ID ).
+                visibleIn( Visibility.module ).
+                assemble( module );
+            // Another DataSource managed by the same C3P0 connection pool
+            new DataSourceAssembler().
+                withDataSourceServiceIdentity( DS_SERVICE_ID ).
+                identifiedBy( OTHER_DS_ID ).
+                visibleIn( Visibility.module ).
+                assemble( module );
+            // END SNIPPET: datasource
+        }
+    }
+
+}
diff --git a/libraries/sql/src/test/java/org/apache/polygene/library/sql/datasource/ExternalDataSourceTest.java b/libraries/sql/src/test/java/org/apache/polygene/library/sql/datasource/ExternalDataSourceTest.java
new file mode 100644
index 0000000..3d2e9a2
--- /dev/null
+++ b/libraries/sql/src/test/java/org/apache/polygene/library/sql/datasource/ExternalDataSourceTest.java
@@ -0,0 +1,67 @@
+/*
+ *  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.polygene.library.sql.datasource;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import javax.sql.DataSource;
+import org.apache.commons.dbcp2.BasicDataSource;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.sql.assembly.ExternalDataSourceAssembler;
+import org.apache.polygene.library.sql.common.SQLUtil;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+
+public class ExternalDataSourceTest
+    extends AbstractPolygeneTest
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+            throws AssemblyException
+    {
+        BasicDataSource externalDataSource = new BasicDataSource();
+        externalDataSource.setDriverClassName( "org.apache.derby.jdbc.EmbeddedDriver" );
+        externalDataSource.setUrl( "jdbc:derby:memory:testdbexternal;create=true" );
+        // START SNIPPET: assembly
+        new ExternalDataSourceAssembler( externalDataSource ).
+                visibleIn( Visibility.module ).
+                identifiedBy( "datasource-external-id" ).
+                withCircuitBreaker( DataSources.newDataSourceCircuitBreaker() ).
+                assemble( module );
+        // END SNIPPET: assembly
+    }
+
+    @Test
+    public void test()
+            throws SQLException
+    {
+        DataSource dataSource = serviceFinder.findService( DataSource.class ).get();
+        Connection connection = dataSource.getConnection();
+        try {
+            connection.getMetaData();
+        } finally {
+            SQLUtil.closeQuietly( connection );
+        }
+    }
+
+}
diff --git a/libraries/sql/src/test/java/org/apache/polygene/library/sql/jmx/DataSourceConfigurationManagerServiceTest.java b/libraries/sql/src/test/java/org/apache/polygene/library/sql/jmx/DataSourceConfigurationManagerServiceTest.java
new file mode 100644
index 0000000..882df7a
--- /dev/null
+++ b/libraries/sql/src/test/java/org/apache/polygene/library/sql/jmx/DataSourceConfigurationManagerServiceTest.java
@@ -0,0 +1,133 @@
+/*
+ *  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.polygene.library.sql.jmx;
+
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
+import org.apache.polygene.library.jmx.JMXAssembler;
+import org.apache.polygene.library.sql.assembly.DataSourceAssembler;
+import org.apache.polygene.library.sql.assembly.DataSourceJMXAssembler;
+import org.apache.polygene.library.sql.datasource.DataSources;
+import org.apache.polygene.library.sql.dbcp.DBCPDataSourceServiceAssembler;
+import org.apache.polygene.library.sql.liquibase.LiquibaseAssembler;
+import org.apache.polygene.library.sql.liquibase.LiquibaseConfiguration;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Test;
+
+/**
+ * Test of export of DataSources to JMX, and some other stuff
+ */
+public class DataSourceConfigurationManagerServiceTest
+{
+
+    public static void main( String[] args )
+        throws ActivationException, AssemblyException
+    {
+
+        DataSourceConfigurationManagerServiceTest instance = new DataSourceConfigurationManagerServiceTest();
+        instance.testDataSources();
+
+        // Hang so it becomes possible to connect through VisualVM and check the JMX beans
+        synchronized( instance )
+        {
+            try
+            {
+                instance.wait();
+            }
+            catch( InterruptedException e )
+            {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    @Test
+    public void testDataSources()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                new JMXAssembler().assemble( module );
+
+                // Create in-memory store for configurations
+                new EntityTestAssembler().visibleIn( Visibility.layer ).assemble( module );
+
+                new DefaultUnitOfWorkAssembler().assemble( module );
+
+                // Set up DataSource service that will manage the connection pools
+                new DBCPDataSourceServiceAssembler().identifiedBy( "datasource-service" )
+                                                    .visibleIn( Visibility.layer )
+                                                    .withConfig( module, Visibility.layer )
+                                                    .assemble( module );
+
+                {
+                    ModuleAssembly testModule = module.layer().module( "TestDS" );
+
+                    // Create a specific DataSource that uses the "datasource" service to do the main work
+                    new DataSourceAssembler().withDataSourceServiceIdentity( "datasource-service" )
+                                             .identifiedBy( "testds" )
+                                             .visibleIn( Visibility.module )
+                                             .withCircuitBreaker( DataSources.newDataSourceCircuitBreaker() )
+                                             .assemble( testModule );
+
+                    // Set up Liquibase service that will create the tables
+                    new LiquibaseAssembler().identifiedBy( "liquibase1" )
+                                            .withConfig( testModule, Visibility.module )
+                                            .applyChangelogOnStartup()
+                                            .assemble( testModule );
+                    testModule.forMixin( LiquibaseConfiguration.class ).declareDefaults()
+                              .changeLog().set( "changelog.xml" );
+                }
+
+                {
+                    ModuleAssembly testModule2 = module.layer().module( "TestDS2" );
+
+                    // Create another specific DataSource that uses the "datasource" service to do the main work
+                    // Use DataSourceAssembler to assemble the DataSource.
+                    new DataSourceAssembler().withDataSourceServiceIdentity( "datasource-service" )
+                                             .identifiedBy( "testds2" )
+                                             .visibleIn( Visibility.module )
+                                             .withCircuitBreaker( DataSources.newDataSourceCircuitBreaker() )
+                                             .assemble( testModule2 );
+
+                    // Set up Liquibase service that will create the tables
+                    new LiquibaseAssembler().identifiedBy( "liquibase2" )
+                                            .withConfig( testModule2, Visibility.module )
+                                            .applyChangelogOnStartup()
+                                            .assemble( testModule2 );
+                    testModule2.forMixin( LiquibaseConfiguration.class ).declareDefaults()
+                              .changeLog().set( "changelog.xml" );
+                }
+
+                // START SNIPPET: jmx
+                new DataSourceJMXAssembler().visibleIn( Visibility.module ).assemble( module );
+                // END SNIPPET: jmx
+            }
+        };
+    }
+}
diff --git a/libraries/sql/src/test/java/org/qi4j/library/sql/DocumentationSupport.java b/libraries/sql/src/test/java/org/qi4j/library/sql/DocumentationSupport.java
deleted file mode 100644
index b9ea940..0000000
--- a/libraries/sql/src/test/java/org/qi4j/library/sql/DocumentationSupport.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.library.sql;
-
-import javax.sql.DataSource;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.circuitbreaker.CircuitBreaker;
-import org.qi4j.library.sql.assembly.DataSourceAssembler;
-import org.qi4j.library.sql.bonecp.BoneCPDataSourceServiceAssembler;
-import org.qi4j.library.sql.dbcp.DBCPDataSourceServiceAssembler;
-
-import static org.qi4j.library.sql.DocumentationSupport.Constants.DS_ID;
-import static org.qi4j.library.sql.DocumentationSupport.Constants.DS_SERVICE_ID;
-import static org.qi4j.library.sql.DocumentationSupport.Constants.OTHER_DS_ID;
-import static org.qi4j.library.sql.datasource.DataSources.newDataSourceCircuitBreaker;
-
-class DocumentationSupport
-{
-    interface Constants
-    {
-        String DS_ID = "datasource";
-
-        String OTHER_DS_ID = "datasource2";
-
-        String DS_SERVICE_ID = "datasource-service";
-    }
-
-    class CircuitBreakerDoc
-        implements Assembler
-    {
-        // START SNIPPET: cb-datasource
-        @Service
-        DataSource dataSource; // Wrapped with a CircuitBreaker proxy
-        // END SNIPPET: cb-datasource
-
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            // START SNIPPET: cb-assembly
-            CircuitBreaker circuitBreaker = newDataSourceCircuitBreaker( 5 /* threshold */,
-                                                                         1000 * 60 * 5 /* 5min timeout */ );
-            new DataSourceAssembler().
-                withDataSourceServiceIdentity( DS_SERVICE_ID ).
-                identifiedBy( DS_ID ).
-                visibleIn( Visibility.layer ).
-                withCircuitBreaker( circuitBreaker ).
-                assemble( module );
-            // END SNIPPET: cb-assembly
-        }
-    }
-
-    class PoolsDoc
-        implements Assembler
-    {
-        @Override
-        public void assemble( ModuleAssembly module )
-            throws AssemblyException
-        {
-            ModuleAssembly config = module;
-
-            // START SNIPPET: bonecp
-            // Assemble the BoneCP based Service Importer
-            new BoneCPDataSourceServiceAssembler().
-                identifiedBy( DS_SERVICE_ID ).
-                visibleIn( Visibility.module ).
-                withConfig( config, Visibility.layer ).
-                assemble( module );
-            // END SNIPPET: bonecp
-
-            // START SNIPPET: dbcp
-            // Assemble the Apache DBCP based Service Importer
-            new DBCPDataSourceServiceAssembler().
-                identifiedBy( DS_SERVICE_ID ).
-                visibleIn( Visibility.module ).
-                withConfig( config, Visibility.layer ).
-                assemble( module );
-            // END SNIPPET: dbcp
-
-            // START SNIPPET: datasource
-            // Assemble a DataSource
-            new DataSourceAssembler().
-                withDataSourceServiceIdentity( DS_SERVICE_ID ).
-                identifiedBy( DS_ID ).
-                visibleIn( Visibility.module ).
-                assemble( module );
-            // Another DataSource managed by the same C3P0 connection pool
-            new DataSourceAssembler().
-                withDataSourceServiceIdentity( DS_SERVICE_ID ).
-                identifiedBy( OTHER_DS_ID ).
-                visibleIn( Visibility.module ).
-                assemble( module );
-            // END SNIPPET: datasource
-        }
-    }
-
-}
diff --git a/libraries/sql/src/test/java/org/qi4j/library/sql/datasource/ExternalDataSourceTest.java b/libraries/sql/src/test/java/org/qi4j/library/sql/datasource/ExternalDataSourceTest.java
deleted file mode 100644
index c8e3f4b..0000000
--- a/libraries/sql/src/test/java/org/qi4j/library/sql/datasource/ExternalDataSourceTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.datasource;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-import javax.sql.DataSource;
-import org.apache.commons.dbcp.BasicDataSource;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.sql.assembly.ExternalDataSourceAssembler;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.qi4j.test.AbstractQi4jTest;
-
-public class ExternalDataSourceTest
-        extends AbstractQi4jTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-            throws AssemblyException
-    {
-        BasicDataSource externalDataSource = new BasicDataSource();
-        externalDataSource.setDriverClassName( "org.apache.derby.jdbc.EmbeddedDriver" );
-        externalDataSource.setUrl( "jdbc:derby:memory:testdbexternal;create=true" );
-        // START SNIPPET: assembly
-        new ExternalDataSourceAssembler( externalDataSource ).
-                visibleIn( Visibility.module ).
-                identifiedBy( "datasource-external-id" ).
-                withCircuitBreaker( DataSources.newDataSourceCircuitBreaker() ).
-                assemble( module );
-        // END SNIPPET: assembly
-    }
-
-    @Test
-    public void test()
-            throws SQLException
-    {
-        DataSource dataSource = module.findService( DataSource.class ).get();
-        Connection connection = dataSource.getConnection();
-        try {
-            connection.getMetaData();
-        } finally {
-            SQLUtil.closeQuietly( connection );
-        }
-    }
-
-}
diff --git a/libraries/sql/src/test/java/org/qi4j/library/sql/jmx/DataSourceConfigurationManagerServiceTest.java b/libraries/sql/src/test/java/org/qi4j/library/sql/jmx/DataSourceConfigurationManagerServiceTest.java
deleted file mode 100644
index a428c05..0000000
--- a/libraries/sql/src/test/java/org/qi4j/library/sql/jmx/DataSourceConfigurationManagerServiceTest.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.library.sql.jmx;
-
-import java.beans.PropertyVetoException;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import javax.sql.DataSource;
-import org.junit.Assert;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.service.qualifier.IdentifiedBy;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.io.Outputs;
-import org.qi4j.io.Receiver;
-import org.qi4j.library.circuitbreaker.CircuitBreaker;
-import org.qi4j.library.jmx.JMXAssembler;
-import org.qi4j.library.sql.assembly.DataSourceAssembler;
-import org.qi4j.library.sql.assembly.DataSourceJMXAssembler;
-import org.qi4j.library.sql.common.Databases;
-import org.qi4j.library.sql.datasource.DataSources;
-import org.qi4j.library.sql.dbcp.DBCPDataSourceServiceAssembler;
-import org.qi4j.library.sql.liquibase.LiquibaseConfiguration;
-import org.qi4j.library.sql.liquibase.LiquibaseService;
-import org.qi4j.test.EntityTestAssembler;
-
-/**
- * Test of export of DataSources to JMX, and some other stuff
- */
-public class DataSourceConfigurationManagerServiceTest
-{
-
-    public static void main( String[] args )
-        throws ActivationException, AssemblyException
-    {
-
-        DataSourceConfigurationManagerServiceTest instance = new DataSourceConfigurationManagerServiceTest();
-        instance.testDataSources();
-
-        // Hang so it becomes possible to connect through VisualVM and check the JMX beans
-        synchronized( instance ) {
-            try {
-                instance.wait();
-            } catch ( InterruptedException e ) {
-                e.printStackTrace();
-            }
-        }
-    }
-
-    @Test
-    public void testDataSources()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-            {
-                new JMXAssembler().assemble( module );
-
-                // Create in-memory store for configurations
-                new EntityTestAssembler().visibleIn( Visibility.layer ).assemble( module );
-
-                // Set up DataSource service that will manage the connection pools
-                new DBCPDataSourceServiceAssembler().identifiedBy( "datasource-service" ).visibleIn( Visibility.layer ).assemble( module );
-
-                {
-                    ModuleAssembly testModule = module.layer().module( "TestDS" );
-
-                    // Create a specific DataSource that uses the "datasource" service to do the main work
-                    new DataSourceAssembler().
-                            withDataSourceServiceIdentity( "datasource-service" ).
-                            identifiedBy( "testds" ).
-                            visibleIn( Visibility.module ).
-                            withCircuitBreaker( DataSources.newDataSourceCircuitBreaker() ).
-                            assemble( testModule );
-
-                    // Set up Liquibase service that will create the tables
-                    testModule.services( LiquibaseService.class ).identifiedBy( "liquibase1" ).instantiateOnStartup();
-                    testModule.entities( LiquibaseConfiguration.class );
-                    testModule.forMixin( LiquibaseConfiguration.class ).declareDefaults().enabled().set( true );
-                    testModule.forMixin( LiquibaseConfiguration.class ).declareDefaults().changeLog().set( "changelog.xml" );
-                }
-
-                {
-                    ModuleAssembly testModule2 = module.layer().module( "TestDS2" );
-
-                    // Create another specific DataSource that uses the "datasource" service to do the main work
-                    // Use DataSourceAssembler to assemble the DataSource.
-                    new DataSourceAssembler().
-                            withDataSourceServiceIdentity( "datasource-service" ).
-                            identifiedBy( "testds2" ).
-                            visibleIn( Visibility.module ).
-                            withCircuitBreaker( DataSources.newDataSourceCircuitBreaker() ).
-                            assemble( testModule2 );
-
-                    // Set up Liquibase service that will create the tables
-                    testModule2.services( LiquibaseService.class ).identifiedBy( "liquibase2" ).instantiateOnStartup();
-                    testModule2.entities( LiquibaseConfiguration.class );
-                    testModule2.forMixin( LiquibaseConfiguration.class ).declareDefaults().enabled().set( true );
-                    testModule2.forMixin( LiquibaseConfiguration.class ).declareDefaults().changeLog().set( "changelog.xml" );
-                }
-
-                // START SNIPPET: jmx
-                new DataSourceJMXAssembler().visibleIn( Visibility.module ).assemble( module );
-                // END SNIPPET: jmx
-
-            }
-
-        };
-
-//        assembler.application().findModule( "Layer 1","Test" ).objectBuilderFactory().newObjectBuilder( DataSourceConfigurationManagerServiceTest.class ).injectTo( this );
-    }
-
-    public void init( @Service @IdentifiedBy( "testds" ) DataSource dataSource, @Service @IdentifiedBy( "testds2" ) ServiceReference<DataSource> dataSource2 )
-            throws SQLException, PropertyVetoException
-    {
-        Databases databases = new Databases( dataSource );
-
-        // Insert some data and print it out
-        databases.update( "insert into test values ('id1','foo')" );
-        databases.query( "select * from test" ).transferTo( Outputs.withReceiver( new Receiver<ResultSet, SQLException>()
-        {
-            @Override
-            public void receive( ResultSet item )
-                    throws SQLException
-            {
-                System.out.println( item.getString( "id" ) );
-            }
-
-        } ) );
-
-        Databases databases2 = new Databases( dataSource2.get() );
-
-        // Insert some data and print it out
-        databases2.update( "insert into test values ('id2','bar')" );
-        databases2.query( "select * from test" ).transferTo( Outputs.withReceiver( new Receiver<ResultSet, SQLException>()
-        {
-            @Override
-            public void receive( ResultSet item )
-                    throws SQLException
-            {
-                System.out.println( item.getString( "id" ) );
-            }
-
-        } ) );
-
-        // Trip the CB
-        dataSource2.metaInfo( CircuitBreaker.class ).trip();
-
-        // This should now fail
-        try {
-            databases2.query( "select * from test" ).transferTo( Outputs.withReceiver( new Receiver<ResultSet, SQLException>()
-            {
-                @Override
-                public void receive( ResultSet item )
-                        throws SQLException
-                {
-                    System.out.println( item.getString( "id" ) );
-                }
-
-            } ) );
-
-            Assert.fail();
-
-        } catch ( Throwable e ) {
-            // Correct
-        }
-
-        // Turn the CB back on
-        dataSource2.metaInfo( CircuitBreaker.class ).turnOn();
-
-        // This should now work
-        databases2.query( "select * from test" ).transferTo( Outputs.withReceiver( new Receiver<ResultSet, SQLException>()
-        {
-            @Override
-            public void receive( ResultSet item )
-                    throws SQLException
-            {
-                System.out.println( item.getString( "id" ) );
-            }
-
-        } ) );
-
-    }
-
-}
diff --git a/libraries/sql/src/test/resources/changelog.xml b/libraries/sql/src/test/resources/changelog.xml
index 9ae0236..7a33052 100644
--- a/libraries/sql/src/test/resources/changelog.xml
+++ b/libraries/sql/src/test/resources/changelog.xml
@@ -1,20 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <databaseChangeLog
      xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
diff --git a/libraries/sql/src/test/resources/testds.properties b/libraries/sql/src/test/resources/testds.properties
index 8fc9229..35261ab 100644
--- a/libraries/sql/src/test/resources/testds.properties
+++ b/libraries/sql/src/test/resources/testds.properties
@@ -1,17 +1,22 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 enabled=true
 url=jdbc:derby:memory:testdb;create=true
diff --git a/libraries/sql/src/test/resources/testds2.properties b/libraries/sql/src/test/resources/testds2.properties
index e62e9fe..12a15ff 100644
--- a/libraries/sql/src/test/resources/testds2.properties
+++ b/libraries/sql/src/test/resources/testds2.properties
@@ -1,17 +1,22 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 enabled=true
 url=jdbc:derby:memory:testdb2;create=true
diff --git a/libraries/uid/build.gradle b/libraries/uid/build.gradle
index eb6dcfd..2ccabfd 100644
--- a/libraries/uid/build.gradle
+++ b/libraries/uid/build.gradle
@@ -1,31 +1,35 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ UID Library contains various Identity generation services."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - UID" }}
+description = "Apache Polygene™ UID Library contains various Identity generation services."
+
+jar { manifest { name = "Apache Polygene™ Library - UID" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
+  api polygene.core.bootstrap
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
+  runtimeOnly polygene.core.runtime
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/libraries/uid/dev-status.xml b/libraries/uid/dev-status.xml
index bdf00e7..0914c52 100644
--- a/libraries/uid/dev-status.xml
+++ b/libraries/uid/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/uid/src/docs/uid.txt b/libraries/uid/src/docs/uid.txt
index 710b606..6ebf216 100644
--- a/libraries/uid/src/docs/uid.txt
+++ b/libraries/uid/src/docs/uid.txt
@@ -35,7 +35,7 @@
 
 [snippet,java]
 ----
-source=libraries/uid/src/test/java/org/qi4j/library/uid/DocumentationSupport.java
+source=libraries/uid/src/test/java/org/apache/polygene/library/uid/DocumentationSupport.java
 tag=uuid-assembly
 ----
 
@@ -43,7 +43,7 @@
 
 [snippet,java]
 ----
-source=libraries/uid/src/test/java/org/qi4j/library/uid/DocumentationSupport.java
+source=libraries/uid/src/test/java/org/apache/polygene/library/uid/DocumentationSupport.java
 tag=uuid-usage
 ----
 
@@ -64,7 +64,7 @@
 
 [snippet,java]
 ----
-source=libraries/uid/src/test/java/org/qi4j/library/uid/DocumentationSupport.java
+source=libraries/uid/src/test/java/org/apache/polygene/library/uid/DocumentationSupport.java
 tag=seq-assembly
 ----
 
@@ -72,7 +72,7 @@
 
 [snippet,java]
 ----
-source=libraries/uid/src/test/java/org/qi4j/library/uid/DocumentationSupport.java
+source=libraries/uid/src/test/java/org/apache/polygene/library/uid/DocumentationSupport.java
 tag=seq-usage
 ----
 
@@ -82,7 +82,7 @@
 
 [snippet,java]
 ----
-source=libraries/uid/src/test/java/org/qi4j/library/uid/DocumentationSupport.java
+source=libraries/uid/src/test/java/org/apache/polygene/library/uid/DocumentationSupport.java
 tag=perseq-assembly
 ----
 
@@ -90,7 +90,7 @@
 
 [snippet,java]
 ----
-source=libraries/uid/src/test/java/org/qi4j/library/uid/DocumentationSupport.java
+source=libraries/uid/src/test/java/org/apache/polygene/library/uid/DocumentationSupport.java
 tag=seq-usage
 ----
 
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/PersistedSequencingMixin.java b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/PersistedSequencingMixin.java
new file mode 100644
index 0000000..6e5ca3f
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/PersistedSequencingMixin.java
@@ -0,0 +1,81 @@
+/*
+ *  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.polygene.library.uid.sequence;
+
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+
+public class PersistedSequencingMixin
+    implements Sequencing
+{
+    @Structure private UnitOfWorkFactory uowf;
+    @This private Configuration<Sequence> sequence;
+
+    @Override
+    public Long newSequenceValue()
+        throws SequencingException
+    {
+        synchronized( this )
+        {
+            ConcurrentEntityModificationException exc = null;
+            UnitOfWork uow = uowf.newUnitOfWork();
+            try
+            {
+                for( int i = 0; i < 3; i++ )
+                {
+                    try
+                    {
+                        Property<Long> property = sequence.get().currentValue();
+                        long value = property.get();
+                        value = value + 1;
+                        property.set( value );
+                        uow.complete();
+                        return value;
+                    }
+                    catch( ConcurrentEntityModificationException e )
+                    {
+                        // Ignore;
+                        exc = e;
+                    }
+                }
+                throw new SequencingException( "Unable to update sequence value.", exc );
+            }
+            catch( UnitOfWorkCompletionException e )
+            {
+                throw new SequencingException( "Unable to update sequence value.", exc );
+            }
+        }
+    }
+
+    @Override
+    public Long currentSequenceValue()
+    {
+        synchronized( this )
+        {
+            return sequence.get().currentValue().get();
+        }
+    }
+}
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/PersistingSequencingService.java b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/PersistingSequencingService.java
new file mode 100644
index 0000000..75aad9a
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/PersistingSequencingService.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.library.uid.sequence;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+
+@Mixins( PersistedSequencingMixin.class )
+public interface PersistingSequencingService extends Sequencing, ServiceComposite
+{
+}
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/Sequence.java b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/Sequence.java
new file mode 100644
index 0000000..ad98165
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/Sequence.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.library.uid.sequence;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * JAVADOC Add JavaDoc
+ */
+@Queryable( false )
+public interface Sequence
+{
+    @UseDefaults Property<Long> currentValue();
+}
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/SequenceEntity.java b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/SequenceEntity.java
new file mode 100644
index 0000000..798f5c2
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/SequenceEntity.java
@@ -0,0 +1,26 @@
+/*
+ *  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.polygene.library.uid.sequence;
+
+import org.apache.polygene.api.entity.EntityComposite;
+
+public interface SequenceEntity extends Sequence, EntityComposite
+{
+}
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/Sequencing.java b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/Sequencing.java
new file mode 100644
index 0000000..81aeda1
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/Sequencing.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.library.uid.sequence;
+
+/**
+ * Sequencing is used to automatically generate a sequence of numbers.
+ * The algorithm is that <code>currentSequenceValue</code> is the number that was last returned
+ * in a <code>newSequenceValue</code> call, and will initially be zero. Persisting Sequencing
+ * services defines "initially" as the first run ever, as subsequent starts may retrieve the
+ * <code>currentSequenceValue</code> from an <code>EntityStore</code>
+ */
+public interface Sequencing
+{
+    Long newSequenceValue()
+        throws SequencingException;
+
+    Long currentSequenceValue();
+}
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/SequencingException.java b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/SequencingException.java
new file mode 100644
index 0000000..e7bad83
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/SequencingException.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.library.uid.sequence;
+
+/**
+ * SequencingException happens when the sequence number can not be reliably
+ * updated.
+ */
+public class SequencingException extends RuntimeException
+{
+    public SequencingException( String message )
+    {
+        super( message );
+    }
+
+    public SequencingException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/TransientSequencingMixin.java b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/TransientSequencingMixin.java
new file mode 100644
index 0000000..dff3ca4
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/TransientSequencingMixin.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.library.uid.sequence;
+
+public class TransientSequencingMixin
+    implements Sequencing
+{
+    private long counter;
+
+    @Override
+    public Long newSequenceValue()
+        throws SequencingException
+    {
+        synchronized( this )
+        {
+            return ++counter;
+        }
+    }
+
+    @Override
+    public Long currentSequenceValue()
+    {
+        synchronized( this )
+        {
+            return counter;
+        }
+    }
+}
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/TransientSequencingService.java b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/TransientSequencingService.java
new file mode 100644
index 0000000..f37b3a0
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/TransientSequencingService.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.library.uid.sequence;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+
+@Mixins( TransientSequencingMixin.class )
+public interface TransientSequencingService extends Sequencing, ServiceComposite
+{
+}
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/assembly/PersistingSequencingAssembler.java b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/assembly/PersistingSequencingAssembler.java
new file mode 100644
index 0000000..2409973
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/assembly/PersistingSequencingAssembler.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.library.uid.sequence.assembly;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.uid.sequence.PersistingSequencingService;
+import org.apache.polygene.library.uid.sequence.SequenceEntity;
+
+public class PersistingSequencingAssembler
+    extends Assemblers.Visibility<PersistingSequencingAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( PersistingSequencingService.class ).visibleIn( visibility() );
+        module.entities( SequenceEntity.class ).visibleIn( Visibility.module );
+    }
+}
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/assembly/TransientSequencingAssembler.java b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/assembly/TransientSequencingAssembler.java
new file mode 100644
index 0000000..24f0571
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/assembly/TransientSequencingAssembler.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.uid.sequence.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.uid.sequence.TransientSequencingService;
+
+public class TransientSequencingAssembler
+    extends Assemblers.Visibility<TransientSequencingAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( TransientSequencingService.class ).visibleIn( visibility() );
+    }
+}
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/assembly/package.html b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/assembly/package.html
new file mode 100644
index 0000000..64acf00
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Sequence Services Assembly.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/package.html b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/package.html
new file mode 100644
index 0000000..77cc167
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/sequence/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Sequence Services.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/UuidGenerationMixin.java b/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/UuidGenerationMixin.java
new file mode 100644
index 0000000..239cdaa
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/UuidGenerationMixin.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.library.uid.uuid;
+
+import java.util.UUID;
+
+public class UuidGenerationMixin
+    implements UuidService
+{
+    private String uuid;
+    private int count;
+
+    public UuidGenerationMixin()
+    {
+        uuid = UUID.randomUUID().toString() + "-";
+    }
+
+    @Override
+    public String generateUuid( int hashLength )
+    {
+        synchronized( this )
+        {
+            String uid = this.uuid + Integer.toHexString( count++ );
+            if( hashLength > 0 )
+            {
+                byte[] result = new byte[hashLength];
+                byte[] bytes = uid.getBytes();
+                for( int i = 0; i < bytes.length; i++ )
+                {
+                    int pos = i % hashLength;
+                    result[ pos ] = (byte) ( result[ pos ] * 31 + 19 + bytes[ i ] );
+                }
+                StringBuffer buf = new StringBuffer();
+                for( int data : result )
+                {
+                    if( data < 0 )
+                    {
+                        data = 256 + data;
+                    }
+                    String hex = Integer.toHexString( data );
+                    if( hex.length() == 1 )
+                    {
+                        hex = "0" + hex;
+                    }
+                    buf = buf.append( hex );
+                }
+                uid = buf.toString();
+            }
+            return uid.toUpperCase();
+        }
+    }
+}
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/UuidService.java b/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/UuidService.java
new file mode 100644
index 0000000..553f935
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/UuidService.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.library.uid.uuid;
+
+public interface UuidService
+{
+    String generateUuid( int hashLength );
+}
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/UuidServiceComposite.java b/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/UuidServiceComposite.java
new file mode 100644
index 0000000..df4fe49
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/UuidServiceComposite.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.library.uid.uuid;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+
+@Mixins( UuidGenerationMixin.class )
+public interface UuidServiceComposite extends UuidService, ServiceComposite
+{
+}
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/assembly/UuidServiceAssembler.java b/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/assembly/UuidServiceAssembler.java
new file mode 100644
index 0000000..a24a555
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/assembly/UuidServiceAssembler.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.uid.uuid.assembly;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.uid.uuid.UuidServiceComposite;
+
+public class UuidServiceAssembler
+    extends Assemblers.Visibility<UuidServiceAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( UuidServiceComposite.class ).visibleIn( visibility() );
+    }
+}
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/assembly/package.html b/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/assembly/package.html
new file mode 100644
index 0000000..e970092
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/assembly/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>UUID Service Assembly.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/package.html b/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/package.html
new file mode 100644
index 0000000..24f0277
--- /dev/null
+++ b/libraries/uid/src/main/java/org/apache/polygene/library/uid/uuid/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>UUID Service.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/PersistedSequencingMixin.java b/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/PersistedSequencingMixin.java
deleted file mode 100644
index ae7151d..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/PersistedSequencingMixin.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.uid.sequence;
-
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.ConcurrentEntityModificationException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-
-public class PersistedSequencingMixin
-    implements Sequencing
-{
-    @Structure private UnitOfWorkFactory uowf;
-    @This private Configuration<Sequence> sequence;
-
-    @Override
-    public Long newSequenceValue()
-        throws SequencingException
-    {
-        synchronized( this )
-        {
-            ConcurrentEntityModificationException exc = null;
-            UnitOfWork uow = uowf.newUnitOfWork();
-            try
-            {
-                for( int i = 0; i < 3; i++ )
-                {
-                    try
-                    {
-                        Property<Long> property = sequence.get().currentValue();
-                        long value = property.get();
-                        value = value + 1;
-                        property.set( value );
-                        uow.complete();
-                        return value;
-                    }
-                    catch( ConcurrentEntityModificationException e )
-                    {
-                        // Ignore;
-                        exc = e;
-                    }
-                }
-                throw new SequencingException( "Unable to update sequence value.", exc );
-            }
-            catch( UnitOfWorkCompletionException e )
-            {
-                throw new SequencingException( "Unable to update sequence value.", exc );
-            }
-        }
-    }
-
-    @Override
-    public Long currentSequenceValue()
-    {
-        synchronized( this )
-        {
-            return sequence.get().currentValue().get();
-        }
-    }
-}
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/PersistingSequencingService.java b/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/PersistingSequencingService.java
deleted file mode 100644
index 38634fe..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/PersistingSequencingService.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.uid.sequence;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-@Mixins( PersistedSequencingMixin.class )
-public interface PersistingSequencingService extends Sequencing, ServiceComposite
-{
-}
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/Sequence.java b/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/Sequence.java
deleted file mode 100644
index 8aa4a15..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/Sequence.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.uid.sequence;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.Queryable;
-import org.qi4j.api.property.Property;
-
-/**
- * JAVADOC Add JavaDoc
- */
-@Queryable( false )
-public interface Sequence
-{
-    @UseDefaults Property<Long> currentValue();
-}
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/SequenceEntity.java b/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/SequenceEntity.java
deleted file mode 100644
index 58f2d1a..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/SequenceEntity.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.uid.sequence;
-
-import org.qi4j.api.entity.EntityComposite;
-
-public interface SequenceEntity extends Sequence, EntityComposite
-{
-}
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/Sequencing.java b/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/Sequencing.java
deleted file mode 100644
index 0e59102..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/Sequencing.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.uid.sequence;
-
-/**
- * Sequencing is used to automatically generate a sequence of numbers.
- * The algorithm is that <code>currentSequenceValue</code> is the number that was last returned
- * in a <code>newSequenceValue</code> call, and will initially be zero. Persisting Sequencing
- * services defines "initially" as the first run ever, as subsequent starts may retrieve the
- * <code>currentSequenceValue</code> from an <code>EntityStore</code>
- */
-public interface Sequencing
-{
-    Long newSequenceValue()
-        throws SequencingException;
-
-    Long currentSequenceValue();
-}
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/SequencingException.java b/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/SequencingException.java
deleted file mode 100644
index b155ad3..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/SequencingException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.uid.sequence;
-
-/**
- * SequencingException happens when the sequence number can not be reliably
- * updated.
- */
-public class SequencingException extends RuntimeException
-{
-    public SequencingException( String message )
-    {
-        super( message );
-    }
-
-    public SequencingException( String message, Throwable cause )
-    {
-        super( message, cause );
-    }
-}
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/TransientSequencingMixin.java b/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/TransientSequencingMixin.java
deleted file mode 100644
index 45c38eb..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/TransientSequencingMixin.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.uid.sequence;
-
-public class TransientSequencingMixin
-    implements Sequencing
-{
-    private long counter;
-
-    @Override
-    public Long newSequenceValue()
-        throws SequencingException
-    {
-        synchronized( this )
-        {
-            return ++counter;
-        }
-    }
-
-    @Override
-    public Long currentSequenceValue()
-    {
-        synchronized( this )
-        {
-            return counter;
-        }
-    }
-}
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/TransientSequencingService.java b/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/TransientSequencingService.java
deleted file mode 100644
index b238881..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/TransientSequencingService.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.uid.sequence;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-@Mixins( TransientSequencingMixin.class )
-public interface TransientSequencingService extends Sequencing, ServiceComposite
-{
-}
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/assembly/PersistingSequencingAssembler.java b/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/assembly/PersistingSequencingAssembler.java
deleted file mode 100644
index 4854bbc..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/assembly/PersistingSequencingAssembler.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.uid.sequence.assembly;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.uid.sequence.PersistingSequencingService;
-import org.qi4j.library.uid.sequence.SequenceEntity;
-
-public class PersistingSequencingAssembler
-    extends Assemblers.Visibility<PersistingSequencingAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( PersistingSequencingService.class ).visibleIn( visibility() );
-        module.entities( SequenceEntity.class ).visibleIn( Visibility.module );
-    }
-}
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/assembly/TransientSequencingAssembler.java b/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/assembly/TransientSequencingAssembler.java
deleted file mode 100644
index 50548d4..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/assembly/TransientSequencingAssembler.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.uid.sequence.assembly;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.uid.sequence.TransientSequencingService;
-
-public class TransientSequencingAssembler
-    extends Assemblers.Visibility<TransientSequencingAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( TransientSequencingService.class ).visibleIn( visibility() );
-    }
-}
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/assembly/package.html b/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/assembly/package.html
deleted file mode 100644
index d4bb2f2..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/assembly/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Sequence Services Assembly.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/package.html b/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/package.html
deleted file mode 100644
index 0a7ead9..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/sequence/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Sequence Services.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/UuidGenerationMixin.java b/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/UuidGenerationMixin.java
deleted file mode 100644
index 331a1cb..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/UuidGenerationMixin.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.uid.uuid;
-
-import java.util.UUID;
-
-public class UuidGenerationMixin
-    implements UuidService
-{
-    private String uuid;
-    private int count;
-
-    public UuidGenerationMixin()
-    {
-        uuid = UUID.randomUUID().toString() + "-";
-    }
-
-    @Override
-    public String generateUuid( int hashLength )
-    {
-        synchronized( this )
-        {
-            String uid = this.uuid + Integer.toHexString( count++ );
-            if( hashLength > 0 )
-            {
-                byte[] result = new byte[hashLength];
-                byte[] bytes = uid.getBytes();
-                for( int i = 0; i < bytes.length; i++ )
-                {
-                    int pos = i % hashLength;
-                    result[ pos ] = (byte) ( result[ pos ] * 31 + 19 + bytes[ i ] );
-                }
-                StringBuffer buf = new StringBuffer();
-                for( int data : result )
-                {
-                    if( data < 0 )
-                    {
-                        data = 256 + data;
-                    }
-                    String hex = Integer.toHexString( data );
-                    if( hex.length() == 1 )
-                    {
-                        hex = "0" + hex;
-                    }
-                    buf = buf.append( hex );
-                }
-                uid = buf.toString();
-            }
-            return uid.toUpperCase();
-        }
-    }
-}
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/UuidService.java b/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/UuidService.java
deleted file mode 100644
index 8e73cd1..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/UuidService.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.uid.uuid;
-
-public interface UuidService
-{
-    String generateUuid( int hashLength );
-}
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/UuidServiceComposite.java b/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/UuidServiceComposite.java
deleted file mode 100644
index 5b1f23c..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/UuidServiceComposite.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.uid.uuid;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-@Mixins( UuidGenerationMixin.class )
-public interface UuidServiceComposite extends UuidService, ServiceComposite
-{
-}
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/assembly/UuidServiceAssembler.java b/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/assembly/UuidServiceAssembler.java
deleted file mode 100644
index ac1785f..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/assembly/UuidServiceAssembler.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.uid.uuid.assembly;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.uid.uuid.UuidServiceComposite;
-
-public class UuidServiceAssembler
-    extends Assemblers.Visibility<UuidServiceAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( UuidServiceComposite.class ).visibleIn( visibility() );
-    }
-}
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/assembly/package.html b/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/assembly/package.html
deleted file mode 100644
index 6202f3e..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/assembly/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>UUID Service Assembly.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/package.html b/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/package.html
deleted file mode 100644
index 6925b32..0000000
--- a/libraries/uid/src/main/java/org/qi4j/library/uid/uuid/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>UUID Service.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/uid/src/test/java/org/apache/polygene/library/uid/DocumentationSupport.java b/libraries/uid/src/test/java/org/apache/polygene/library/uid/DocumentationSupport.java
new file mode 100644
index 0000000..a1274f1
--- /dev/null
+++ b/libraries/uid/src/test/java/org/apache/polygene/library/uid/DocumentationSupport.java
@@ -0,0 +1,104 @@
+/*
+ *  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.polygene.library.uid;
+
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.uid.sequence.Sequencing;
+import org.apache.polygene.library.uid.sequence.assembly.PersistingSequencingAssembler;
+import org.apache.polygene.library.uid.sequence.assembly.TransientSequencingAssembler;
+import org.apache.polygene.library.uid.uuid.UuidService;
+import org.apache.polygene.library.uid.uuid.assembly.UuidServiceAssembler;
+
+import static org.apache.polygene.api.common.Visibility.layer;
+
+public class DocumentationSupport
+{
+
+    class Uuid
+            implements Assembler
+    {
+
+        public void assemble( ModuleAssembly moduleAssembly )
+                throws AssemblyException
+        {
+            // START SNIPPET: uuid-assembly
+            new UuidServiceAssembler().visibleIn( layer ).assemble( moduleAssembly );
+            // END SNIPPET: uuid-assembly
+        }
+
+        // START SNIPPET: uuid-usage
+        @Service UuidService uuidService;
+
+        public void doSomething()
+        {
+            String id1 = uuidService.generateUuid( 0 );
+            // eg. 1020ECBB-098C-46E0-94DC-F78E2265EAA1-36
+
+            String id2 = uuidService.generateUuid( 12 );
+            // eg. 84E06578EAE3
+        }
+        // END SNIPPET: uuid-usage
+
+    }
+
+    class Seq
+            implements Assembler
+    {
+
+        public void assemble( ModuleAssembly moduleAssembly )
+                throws AssemblyException
+        {
+            // START SNIPPET: seq-assembly
+            new TransientSequencingAssembler().visibleIn( layer ).assemble( moduleAssembly );
+            // END SNIPPET: seq-assembly
+        }
+
+        // START SNIPPET: seq-usage
+        @Service Sequencing sequencing;
+
+        public void doSomething()
+        {
+            sequencing.currentSequenceValue(); // return 0
+
+            sequencing.newSequenceValue(); // return 1
+            sequencing.currentSequenceValue(); // return 1
+        }
+        // END SNIPPET: seq-usage
+
+    }
+
+    class Perseq
+            implements Assembler
+    {
+
+        public void assemble( ModuleAssembly moduleAssembly )
+                throws AssemblyException
+        {
+            // START SNIPPET: perseq-assembly
+            new PersistingSequencingAssembler().visibleIn( layer ).assemble( moduleAssembly );
+            // END SNIPPET: perseq-assembly
+        }
+
+    }
+
+}
diff --git a/libraries/uid/src/test/java/org/apache/polygene/library/uid/sequence/PersistingSequencingTest.java b/libraries/uid/src/test/java/org/apache/polygene/library/uid/sequence/PersistingSequencingTest.java
new file mode 100644
index 0000000..25be0f6
--- /dev/null
+++ b/libraries/uid/src/test/java/org/apache/polygene/library/uid/sequence/PersistingSequencingTest.java
@@ -0,0 +1,102 @@
+/*
+ *  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.polygene.library.uid.sequence;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.uid.sequence.assembly.PersistingSequencingAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.junit.Assert.*;
+    
+public class PersistingSequencingTest extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module ) throws AssemblyException
+    {
+        new PersistingSequencingAssembler().assemble( module );
+        new EntityTestAssembler().assemble( module );
+        module.transients( UnderTestComposite.class );
+    }
+
+    @Test
+    public void whenTransientSequencingThenNumbersStartAtZero()
+        throws Exception
+    {
+        UnderTest underTest = transientBuilderFactory.newTransient( UnderTest.class );
+        assertEquals( 0, underTest.currentValue() );
+    }
+
+    @Test
+    public void whenTransientSequencingThenFirstNextValueIsOne()
+        throws Exception
+    {
+        UnderTest underTest = transientBuilderFactory.newTransient( UnderTest.class );
+        assertEquals( 1, underTest.nextValue() );
+        assertEquals( 1, underTest.currentValue() );
+    }
+
+    @Test
+    public void whenTransientSequencingThenFirst100ValuesAreInSequence()
+        throws Exception
+    {
+        UnderTest underTest = transientBuilderFactory.newTransient( UnderTest.class );
+        for( int i = 1; i <= 100; i++ )
+        {
+            assertEquals( i, underTest.nextValue() );
+            assertEquals( i, underTest.currentValue() );
+            assertEquals( i, underTest.currentValue() );
+            assertEquals( i, underTest.currentValue() );
+        }
+    }
+
+    public interface UnderTest
+    {
+        long nextValue();
+
+        long currentValue();
+    }
+
+    @Mixins( UnderTestMixin.class )
+    public interface UnderTestComposite extends UnderTest, TransientComposite
+    {
+    }
+
+    public static class UnderTestMixin
+        implements UnderTest
+    {
+        @Service private Sequencing service;
+
+        public long nextValue()
+        {
+            return service.newSequenceValue();
+        }
+
+        public long currentValue()
+        {
+            return service.currentSequenceValue();
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries/uid/src/test/java/org/apache/polygene/library/uid/sequence/TransientSequencingTest.java b/libraries/uid/src/test/java/org/apache/polygene/library/uid/sequence/TransientSequencingTest.java
new file mode 100644
index 0000000..e8f8f40
--- /dev/null
+++ b/libraries/uid/src/test/java/org/apache/polygene/library/uid/sequence/TransientSequencingTest.java
@@ -0,0 +1,100 @@
+/*
+ *  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.polygene.library.uid.sequence;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.uid.sequence.assembly.TransientSequencingAssembler;
+
+import static org.junit.Assert.assertEquals;
+
+public class TransientSequencingTest extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module ) throws AssemblyException
+    {
+        new TransientSequencingAssembler().assemble( module );
+        module.transients( UnderTestComposite.class );
+    }
+
+    @Test
+    public void whenTransientSequencingThenNumbersStartAtZero()
+        throws Exception
+    {
+        UnderTest underTest = transientBuilderFactory.newTransient( UnderTest.class );
+        assertEquals( 0, underTest.currentValue() );
+    }
+
+    @Test
+    public void whenTransientSequencingThenFirstNextValueIsOne()
+        throws Exception
+    {
+        UnderTest underTest = transientBuilderFactory.newTransient( UnderTest.class );
+        assertEquals( 1, underTest.nextValue() );
+        assertEquals( 1, underTest.currentValue() );
+    }
+
+    @Test
+    public void whenTransientSequencingThenFirst100ValuesAreInSequence()
+        throws Exception
+    {
+        UnderTest underTest = transientBuilderFactory.newTransient( UnderTest.class );
+        for( int i = 1; i <= 100; i++ )
+        {
+            assertEquals( i, underTest.nextValue() );
+            assertEquals( i, underTest.currentValue() );
+            assertEquals( i, underTest.currentValue() );
+            assertEquals( i, underTest.currentValue() );
+        }
+    }
+
+    public interface UnderTest
+    {
+        long nextValue();
+
+        long currentValue();
+    }
+
+    @Mixins( UnderTestMixin.class )
+    public interface UnderTestComposite extends UnderTest, TransientComposite
+    {
+    }
+
+    public static class UnderTestMixin
+        implements UnderTest
+    {
+        @Service private Sequencing service;
+
+        public long nextValue()
+        {
+            return service.newSequenceValue();
+        }
+
+        public long currentValue()
+        {
+            return service.currentSequenceValue();
+        }
+    }
+}
diff --git a/libraries/uid/src/test/java/org/apache/polygene/library/uid/uuid/UuidServiceTest.java b/libraries/uid/src/test/java/org/apache/polygene/library/uid/uuid/UuidServiceTest.java
new file mode 100644
index 0000000..af5a490
--- /dev/null
+++ b/libraries/uid/src/test/java/org/apache/polygene/library/uid/uuid/UuidServiceTest.java
@@ -0,0 +1,101 @@
+/*
+ *  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.polygene.library.uid.uuid;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.uid.uuid.assembly.UuidServiceAssembler;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class UuidServiceTest extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module ) throws AssemblyException
+    {
+        new UuidServiceAssembler().assemble(module);
+        module.transients( UnderTestComposite.class );
+    }
+
+    @Test
+    public void whenGeneratingUuidGivenHashLengthLargerThanZeroThenValidateTheSizeAndContent()
+        throws Exception
+    {
+        UnderTest ut = transientBuilderFactory.newTransient( UnderTest.class );
+        for( int hashLength = 1; hashLength < 50; hashLength++ )
+        {
+            String uid = ut.generateUuid( hashLength );
+            assertEquals( hashLength * 2, uid.length() );
+            for( int i = 0; i < uid.length(); i++ )
+            {
+                char ch = uid.charAt( i );
+                assertTrue( ( ch >= '0' && ch <= '9' ) || ( ch >= 'A' && ch <= 'F' ) );
+            }
+        }
+    }
+
+    @Test
+    public void whenGeneratingUuidGivenZeroHashLengthThenValidateFormat()
+        throws Exception
+    {
+        UnderTest ut = transientBuilderFactory.newTransient( UnderTest.class );
+        String uid = ut.generateUuid( 0 );
+        int dashCounter = 0;
+        for( int i = 0; i < uid.length(); i++ )
+        {
+            char ch = uid.charAt( i );
+            if( ch == '-' )
+            {
+                dashCounter++;
+            }
+            else
+            {
+                assertTrue( ( ch >= '0' && ch <= '9' ) || ( ch >= 'A' && ch <= 'F' ) );
+            }
+        }
+        assertEquals( 5, dashCounter );
+    }
+
+    @Mixins( UnderTestMixin.class )
+    public interface UnderTestComposite extends UnderTest, TransientComposite
+    {
+    }
+
+    public interface UnderTest
+    {
+        String generateUuid( int len );
+    }
+
+    public static class UnderTestMixin
+        implements UnderTest
+    {
+        @Service private UuidService service;
+
+        public String generateUuid( int len )
+        {
+            return service.generateUuid( len );
+        }
+    }
+}
diff --git a/libraries/uid/src/test/java/org/qi4j/library/uid/DocumentationSupport.java b/libraries/uid/src/test/java/org/qi4j/library/uid/DocumentationSupport.java
deleted file mode 100644
index 28c24be..0000000
--- a/libraries/uid/src/test/java/org/qi4j/library/uid/DocumentationSupport.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.library.uid;
-
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.uid.sequence.Sequencing;
-import org.qi4j.library.uid.sequence.assembly.PersistingSequencingAssembler;
-import org.qi4j.library.uid.sequence.assembly.TransientSequencingAssembler;
-import org.qi4j.library.uid.uuid.UuidService;
-import org.qi4j.library.uid.uuid.assembly.UuidServiceAssembler;
-
-import static org.qi4j.api.common.Visibility.layer;
-
-public class DocumentationSupport
-{
-
-    class Uuid
-            implements Assembler
-    {
-
-        public void assemble( ModuleAssembly moduleAssembly )
-                throws AssemblyException
-        {
-            // START SNIPPET: uuid-assembly
-            new UuidServiceAssembler().visibleIn( layer ).assemble( moduleAssembly );
-            // END SNIPPET: uuid-assembly
-        }
-
-        // START SNIPPET: uuid-usage
-        @Service UuidService uuidService;
-
-        public void doSomething()
-        {
-            String id1 = uuidService.generateUuid( 0 );
-            // eg. 1020ECBB-098C-46E0-94DC-F78E2265EAA1-36
-
-            String id2 = uuidService.generateUuid( 12 );
-            // eg. 84E06578EAE3
-        }
-        // END SNIPPET: uuid-usage
-
-    }
-
-    class Seq
-            implements Assembler
-    {
-
-        public void assemble( ModuleAssembly moduleAssembly )
-                throws AssemblyException
-        {
-            // START SNIPPET: seq-assembly
-            new TransientSequencingAssembler().visibleIn( layer ).assemble( moduleAssembly );
-            // END SNIPPET: seq-assembly
-        }
-
-        // START SNIPPET: seq-usage
-        @Service Sequencing sequencing;
-
-        public void doSomething()
-        {
-            sequencing.currentSequenceValue(); // return 0
-
-            sequencing.newSequenceValue(); // return 1
-            sequencing.currentSequenceValue(); // return 1
-        }
-        // END SNIPPET: seq-usage
-
-    }
-
-    class Perseq
-            implements Assembler
-    {
-
-        public void assemble( ModuleAssembly moduleAssembly )
-                throws AssemblyException
-        {
-            // START SNIPPET: perseq-assembly
-            new PersistingSequencingAssembler().visibleIn( layer ).assemble( moduleAssembly );
-            // END SNIPPET: perseq-assembly
-        }
-
-    }
-
-}
diff --git a/libraries/uid/src/test/java/org/qi4j/library/uid/sequence/PersistingSequencingTest.java b/libraries/uid/src/test/java/org/qi4j/library/uid/sequence/PersistingSequencingTest.java
deleted file mode 100644
index 3a33c9e..0000000
--- a/libraries/uid/src/test/java/org/qi4j/library/uid/sequence/PersistingSequencingTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.uid.sequence;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.uid.sequence.assembly.PersistingSequencingAssembler;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.junit.Assert.*;
-    
-public class PersistingSequencingTest extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module ) throws AssemblyException
-    {
-        new PersistingSequencingAssembler().assemble( module );
-        new EntityTestAssembler().assemble( module );
-        module.transients( UnderTestComposite.class );
-    }
-
-    @Test
-    public void whenTransientSequencingThenNumbersStartAtZero()
-        throws Exception
-    {
-        UnderTest underTest = module.newTransient( UnderTest.class );
-        assertEquals( 0, underTest.currentValue() );
-    }
-
-    @Test
-    public void whenTransientSequencingThenFirstNextValueIsOne()
-        throws Exception
-    {
-        UnderTest underTest = module.newTransient( UnderTest.class );
-        assertEquals( 1, underTest.nextValue() );
-        assertEquals( 1, underTest.currentValue() );
-    }
-
-    @Test
-    public void whenTransientSequencingThenFirst100ValuesAreInSequence()
-        throws Exception
-    {
-        UnderTest underTest = module.newTransient( UnderTest.class );
-        for( int i = 1; i <= 100; i++ )
-        {
-            assertEquals( i, underTest.nextValue() );
-            assertEquals( i, underTest.currentValue() );
-            assertEquals( i, underTest.currentValue() );
-            assertEquals( i, underTest.currentValue() );
-        }
-    }
-
-    public interface UnderTest
-    {
-        long nextValue();
-
-        long currentValue();
-    }
-
-    @Mixins( UnderTestMixin.class )
-    public interface UnderTestComposite extends UnderTest, TransientComposite
-    {
-    }
-
-    public static class UnderTestMixin
-        implements UnderTest
-    {
-        @Service private Sequencing service;
-
-        public long nextValue()
-        {
-            return service.newSequenceValue();
-        }
-
-        public long currentValue()
-        {
-            return service.currentSequenceValue();
-        }
-    }
-}
\ No newline at end of file
diff --git a/libraries/uid/src/test/java/org/qi4j/library/uid/sequence/TransientSequencingTest.java b/libraries/uid/src/test/java/org/qi4j/library/uid/sequence/TransientSequencingTest.java
deleted file mode 100644
index 5ad7e5b..0000000
--- a/libraries/uid/src/test/java/org/qi4j/library/uid/sequence/TransientSequencingTest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.uid.sequence;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.uid.sequence.assembly.TransientSequencingAssembler;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-
-public class TransientSequencingTest extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module ) throws AssemblyException
-    {
-        new TransientSequencingAssembler().assemble( module );
-        module.transients( UnderTestComposite.class );
-    }
-
-    @Test
-    public void whenTransientSequencingThenNumbersStartAtZero()
-        throws Exception
-    {
-        UnderTest underTest = module.newTransient( UnderTest.class );
-        assertEquals( 0, underTest.currentValue() );
-    }
-
-    @Test
-    public void whenTransientSequencingThenFirstNextValueIsOne()
-        throws Exception
-    {
-        UnderTest underTest = module.newTransient( UnderTest.class );
-        assertEquals( 1, underTest.nextValue() );
-        assertEquals( 1, underTest.currentValue() );
-    }
-
-    @Test
-    public void whenTransientSequencingThenFirst100ValuesAreInSequence()
-        throws Exception
-    {
-        UnderTest underTest = module.newTransient( UnderTest.class );
-        for( int i = 1; i <= 100; i++ )
-        {
-            assertEquals( i, underTest.nextValue() );
-            assertEquals( i, underTest.currentValue() );
-            assertEquals( i, underTest.currentValue() );
-            assertEquals( i, underTest.currentValue() );
-        }
-    }
-
-    public interface UnderTest
-    {
-        long nextValue();
-
-        long currentValue();
-    }
-
-    @Mixins( UnderTestMixin.class )
-    public interface UnderTestComposite extends UnderTest, TransientComposite
-    {
-    }
-
-    public static class UnderTestMixin
-        implements UnderTest
-    {
-        @Service private Sequencing service;
-
-        public long nextValue()
-        {
-            return service.newSequenceValue();
-        }
-
-        public long currentValue()
-        {
-            return service.currentSequenceValue();
-        }
-    }
-}
diff --git a/libraries/uid/src/test/java/org/qi4j/library/uid/uuid/UuidServiceTest.java b/libraries/uid/src/test/java/org/qi4j/library/uid/uuid/UuidServiceTest.java
deleted file mode 100644
index f4449a9..0000000
--- a/libraries/uid/src/test/java/org/qi4j/library/uid/uuid/UuidServiceTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.library.uid.uuid;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.uid.uuid.assembly.UuidServiceAssembler;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-public class UuidServiceTest extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module ) throws AssemblyException
-    {
-        new UuidServiceAssembler().assemble(module);
-        module.transients( UnderTestComposite.class );
-    }
-
-    @Test
-    public void whenGeneratingUuidGivenHashLengthLargerThanZeroThenValidateTheSizeAndContent()
-        throws Exception
-    {
-        UnderTest ut = module.newTransient( UnderTest.class );
-        for( int hashLength = 1; hashLength < 50; hashLength++ )
-        {
-            String uid = ut.generateUuid( hashLength );
-            assertEquals( hashLength * 2, uid.length() );
-            for( int i = 0; i < uid.length(); i++ )
-            {
-                char ch = uid.charAt( i );
-                assertTrue( ( ch >= '0' && ch <= '9' ) || ( ch >= 'A' && ch <= 'F' ) );
-            }
-        }
-    }
-
-    @Test
-    public void whenGeneratingUuidGivenZeroHashLengthThenValidateFormat()
-        throws Exception
-    {
-        UnderTest ut = module.newTransient( UnderTest.class );
-        String uid = ut.generateUuid( 0 );
-        int dashCounter = 0;
-        for( int i = 0; i < uid.length(); i++ )
-        {
-            char ch = uid.charAt( i );
-            if( ch == '-' )
-            {
-                dashCounter++;
-            }
-            else
-            {
-                assertTrue( ( ch >= '0' && ch <= '9' ) || ( ch >= 'A' && ch <= 'F' ) );
-            }
-        }
-        assertEquals( 5, dashCounter );
-    }
-
-    @Mixins( UnderTestMixin.class )
-    public interface UnderTestComposite extends UnderTest, TransientComposite
-    {
-    }
-
-    public interface UnderTest
-    {
-        String generateUuid( int len );
-    }
-
-    public static class UnderTestMixin
-        implements UnderTest
-    {
-        @Service private UuidService service;
-
-        public String generateUuid( int len )
-        {
-            return service.generateUuid( len );
-        }
-    }
-}
diff --git a/libraries/uowfile/build.gradle b/libraries/uowfile/build.gradle
index e0f3116..75dbb9e 100644
--- a/libraries/uowfile/build.gradle
+++ b/libraries/uowfile/build.gradle
@@ -1,32 +1,38 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ UoWFile Library provides file operations binding to UoWs."
+apply plugin: 'polygene-library'
 
-jar { manifest { name = "Apache Zest™ Library - UoWFile" }}
+description = "Apache Polygene™ UoWFile Library provides file operations binding to UoWs."
+
+jar { manifest { name = "Apache Polygene™ Library - UoWFile" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile(project(":org.qi4j.libraries:org.qi4j.library.fileconfig"))
+  api polygene.core.bootstrap
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
+  implementation polygene.library( 'fileconfig' )
+  implementation libraries.slf4j_api
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
 }
diff --git a/libraries/uowfile/dev-status.xml b/libraries/uowfile/dev-status.xml
index 43df615..476db6d 100644
--- a/libraries/uowfile/dev-status.xml
+++ b/libraries/uowfile/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/libraries/uowfile/src/docs/uowfile.txt b/libraries/uowfile/src/docs/uowfile.txt
index b3a1c00..9ad65c3 100644
--- a/libraries/uowfile/src/docs/uowfile.txt
+++ b/libraries/uowfile/src/docs/uowfile.txt
@@ -43,7 +43,7 @@
 
 == Logging ==
 
-The SLF4J Logger used by this library is named "org.qi4j.library.uowfile".
+The SLF4J Logger used by this library is named "org.apache.polygene.library.uowfile".
 
 
 == Add an attached file to an Entity ==
@@ -52,7 +52,7 @@
 
 [snippet,java]
 ----
-source=libraries/uowfile/src/test/java/org/qi4j/library/uowfile/HasUoWFileTest.java
+source=libraries/uowfile/src/test/java/org/apache/polygene/library/uowfile/HasUoWFileTest.java
 tag=entity
 ----
 
@@ -60,7 +60,7 @@
 
 [snippet,java]
 ----
-source=libraries/uowfile/src/test/java/org/qi4j/library/uowfile/HasUoWFileTest.java
+source=libraries/uowfile/src/test/java/org/apache/polygene/library/uowfile/HasUoWFileTest.java
 tag=uowfile
 ----
 
@@ -68,7 +68,7 @@
 
 [snippet,java]
 ----
-source=libraries/uowfile/src/main/java/org/qi4j/library/uowfile/singular/HasUoWFile.java
+source=libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/singular/HasUoWFile.java
 tag=contract
 ----
 
@@ -76,7 +76,7 @@
 
 [snippet,java]
 ----
-source=libraries/uowfile/src/test/java/org/qi4j/library/uowfile/HasUoWFileTest.java
+source=libraries/uowfile/src/test/java/org/apache/polygene/library/uowfile/HasUoWFileTest.java
 tag=locator
 ----
 
@@ -84,7 +84,7 @@
 
 [snippet,java]
 ----
-source=libraries/uowfile/src/test/java/org/qi4j/library/uowfile/HasUoWFileTest.java
+source=libraries/uowfile/src/test/java/org/apache/polygene/library/uowfile/HasUoWFileTest.java
 tag=assembly
 ----
 
@@ -92,7 +92,7 @@
 
 [snippet,java]
 ----
-source=libraries/uowfile/src/test/java/org/qi4j/library/uowfile/HasUoWFileTest.java
+source=libraries/uowfile/src/test/java/org/apache/polygene/library/uowfile/HasUoWFileTest.java
 tag=api
 ----
 
@@ -106,7 +106,7 @@
 
 [snippet,java]
 ----
-source=libraries/uowfile/src/test/java/org/qi4j/library/uowfile/HasUoWFilesTest.java
+source=libraries/uowfile/src/test/java/org/apache/polygene/library/uowfile/HasUoWFilesTest.java
 tag=entity
 ----
 
@@ -118,7 +118,7 @@
 
 [snippet,java]
 ----
-source=libraries/uowfile/src/test/java/org/qi4j/library/uowfile/HasUoWFilesTest.java
+source=libraries/uowfile/src/test/java/org/apache/polygene/library/uowfile/HasUoWFilesTest.java
 tag=uowfile
 ----
 
@@ -126,7 +126,7 @@
 
 [snippet,java]
 ----
-source=libraries/uowfile/src/main/java/org/qi4j/library/uowfile/plural/HasUoWFiles.java
+source=libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/plural/HasUoWFiles.java
 tag=contract
 ----
 
@@ -134,7 +134,7 @@
 
 [snippet,java]
 ----
-source=libraries/uowfile/src/test/java/org/qi4j/library/uowfile/HasUoWFilesTest.java
+source=libraries/uowfile/src/test/java/org/apache/polygene/library/uowfile/HasUoWFilesTest.java
 tag=locator
 ----
 
@@ -142,7 +142,7 @@
 
 [snippet,java]
 ----
-source=libraries/uowfile/src/test/java/org/qi4j/library/uowfile/HasUoWFilesTest.java
+source=libraries/uowfile/src/test/java/org/apache/polygene/library/uowfile/HasUoWFilesTest.java
 tag=assembly
 ----
 
@@ -150,7 +150,7 @@
 
 [snippet,java]
 ----
-source=libraries/uowfile/src/test/java/org/qi4j/library/uowfile/HasUoWFilesTest.java
+source=libraries/uowfile/src/test/java/org/apache/polygene/library/uowfile/HasUoWFilesTest.java
 tag=api
 ----
 
diff --git a/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/bootstrap/UoWFileAssembler.java b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/bootstrap/UoWFileAssembler.java
new file mode 100644
index 0000000..ae96cb0
--- /dev/null
+++ b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/bootstrap/UoWFileAssembler.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.library.uowfile.bootstrap;
+
+import org.apache.polygene.bootstrap.Assemblers;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.uowfile.internal.UoWFileFactory;
+import org.apache.polygene.library.uowfile.plural.HasUoWFiles;
+import org.apache.polygene.library.uowfile.plural.UoWFilesLocator;
+import org.apache.polygene.library.uowfile.singular.HasUoWFile;
+import org.apache.polygene.library.uowfile.singular.UoWFileLocator;
+
+/**
+ * Add services needed for {@link HasUoWFile} and {@link HasUoWFiles}.
+ * 
+ * You usually want to use this assembler on the module where your entities belong.
+ * 
+ * Your entity types must extends either {@link HasUoWFile} or {@link HasUoWFiles}.
+ * Their mixins must respectively implements {@link UoWFileLocator} and {@link UoWFilesLocator}
+ */
+public class UoWFileAssembler
+    extends Assemblers.Visibility<UoWFileAssembler>
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( UoWFileFactory.class ).visibleIn( visibility() );
+    }
+}
diff --git a/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/bootstrap/package.html b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/bootstrap/package.html
new file mode 100644
index 0000000..52c4c3e
--- /dev/null
+++ b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/bootstrap/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>UnitOfWork File Assembly.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/ConcurrentUoWFileModificationException.java b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/ConcurrentUoWFileModificationException.java
new file mode 100644
index 0000000..36892e7
--- /dev/null
+++ b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/ConcurrentUoWFileModificationException.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.library.uowfile.internal;
+
+import java.util.Collections;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+import org.apache.polygene.api.usecase.Usecase;
+
+public class ConcurrentUoWFileModificationException
+    extends ConcurrentEntityModificationException
+{
+    private final Iterable<UoWFile> concurrentlyModifiedFiles;
+
+    ConcurrentUoWFileModificationException( Iterable<UoWFile> concurrentlyModifiedFiles, Usecase usecase )
+    {
+        super( Collections.emptyMap(), usecase );
+        this.concurrentlyModifiedFiles = concurrentlyModifiedFiles;
+    }
+
+    public Iterable<UoWFile> concurrentlyModifiedUoWFiles()
+    {
+        return concurrentlyModifiedFiles;
+    }
+
+    @Override
+    public String getMessage()
+    {
+        return "Files changed concurently: " + concurrentlyModifiedFiles;
+    }
+}
diff --git a/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/ConcurrentUoWFileStateModificationException.java b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/ConcurrentUoWFileStateModificationException.java
new file mode 100644
index 0000000..b67d560
--- /dev/null
+++ b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/ConcurrentUoWFileStateModificationException.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.library.uowfile.internal;
+
+class ConcurrentUoWFileStateModificationException
+    extends Exception
+{
+    private final UoWFile file;
+
+    ConcurrentUoWFileStateModificationException( UoWFile file )
+    {
+        this.file = file;
+    }
+
+    UoWFile getUoWFile()
+    {
+        return file;
+    }
+
+    @Override
+    public String getMessage()
+    {
+        return "UoWFile modified concurently: " + file.toString();
+    }
+}
diff --git a/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/UoWFile.java b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/UoWFile.java
new file mode 100644
index 0000000..2a9553e
--- /dev/null
+++ b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/UoWFile.java
@@ -0,0 +1,168 @@
+/*
+ *  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.polygene.library.uowfile.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.concurrent.atomic.AtomicLong;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UoWFile
+{
+    private static final Logger LOGGER = LoggerFactory.getLogger( "org.apache.polygene.library.uowfile" );
+    private static final AtomicLong COUNT = new AtomicLong( 0L );
+    private final long originalIdentity;
+    private final File original;
+    private final File current;
+    private final File backup;
+
+    UoWFile( File original, File workDir )
+    {
+        this.originalIdentity = original.length() + original.lastModified();
+        this.original = original;
+        long count = COUNT.incrementAndGet();
+        this.current = new File( workDir, original.getName() + ".current." + count );
+        this.backup = new File( workDir, original.getName() + ".backup." + count );
+    }
+
+    public File asFile()
+    {
+        return current;
+    }
+
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder().append( UoWFile.class.getSimpleName() );
+        // UoWFile{parent/( original(oid->id) | current(id) | backup(id) )}
+        sb.append( "{" ).append( original.getParentFile().getName() ).append( "/( " )
+          .append( original.getName() ).append( "(" ).append( originalIdentity ).append( "->" )
+          .append( fileTag( original ) ).append( ") | " ).append( current.getName() )
+          .append( "(" ).append( fileTag( current ) ).append( ") | " ).append( backup.getName() )
+          .append( "(" ).append( fileTag( backup ) ).append( ") )}" );
+        return sb.toString();
+    }
+
+    void copyOriginalToCurrent()
+    {
+        if( original.exists() )
+        {
+            copy( original, current );
+        }
+    }
+
+    void apply()
+        throws ConcurrentUoWFileStateModificationException
+    {
+        LOGGER.trace( "Will apply changes to {}", this );
+        if( fileTag( current ) != originalIdentity )
+        {
+            if( fileTag( original ) != originalIdentity )
+            {
+                LOGGER.info(
+                    "Concurrent modification, original creation reference is {} and original apply reference is {}",
+                    originalIdentity, fileTag( original ) );
+                throw new ConcurrentUoWFileStateModificationException( this );
+            }
+            if( original.exists() )
+            {
+                move( original, backup );
+            }
+            if( current.exists() )
+            {
+                move( current, original );
+            }
+            LOGGER.debug( "Applied changes to {}", original );
+        }
+    }
+
+    void rollback()
+    {
+        if( backup.exists() )
+        {
+            if( fileTag( original ) != originalIdentity )
+            {
+                delete( original );
+                move( backup, original );
+            }
+            LOGGER.debug( "Restored backup to {}", original );
+        }
+    }
+
+    void cleanup()
+    {
+        if( current.exists() )
+        {
+            delete( current );
+        }
+        if( backup.exists() )
+        {
+            delete( backup );
+        }
+    }
+
+    /**
+     * @return OL if the file does not exist
+     */
+    private long fileTag( File file )
+    {
+        return file.length() + file.lastModified();
+    }
+
+    private void copy( File source, File dest )
+    {
+        try
+        {
+            Files.copy( source.toPath(), dest.toPath() );
+        }
+        catch( IOException ex )
+        {
+            throw new UoWFileException( ex );
+        }
+    }
+
+    private void delete( File file )
+    {
+        if( !file.delete() )
+        {
+            throw new UoWFileException( new IOException( "Unable to delete file " + file ) );
+        }
+    }
+
+    private void move( File source, File dest )
+    {
+        // Atomic move attempt
+        if( !source.renameTo( dest ) )
+        {
+            // source and dest are probably on different filesystem, fallback to a non atomic copy/move operation
+            copy( source, dest );
+            if( !source.delete() )
+            {
+                throw new UoWFileException( new IOException( "Unable to delete source file " + source
+                                                             + " after copy(move) to " + dest
+                                                             + " (rename failed before that)." ) );
+            }
+            LOGGER.warn( "Moved {} to {} using a copy/delete operation instead of an atomic move. "
+                         + "Are they on different filesystems?", source, dest );
+        }
+    }
+}
diff --git a/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/UoWFileException.java b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/UoWFileException.java
new file mode 100644
index 0000000..f288855
--- /dev/null
+++ b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/UoWFileException.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.library.uowfile.internal;
+
+import java.io.IOException;
+
+class UoWFileException
+    extends RuntimeException
+{
+    UoWFileException( IOException cause )
+    {
+        super( cause.getMessage(), cause );
+    }
+
+    UoWFileException( String message, IOException cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/UoWFileFactory.java b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/UoWFileFactory.java
new file mode 100644
index 0000000..1666415
--- /dev/null
+++ b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/UoWFileFactory.java
@@ -0,0 +1,186 @@
+/*
+ *  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.polygene.library.uowfile.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCallback;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.library.fileconfig.FileConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Mixins( UoWFileFactory.Mixin.class )
+public interface UoWFileFactory
+    extends ServiceActivation
+{
+
+    UoWFile createCurrentUoWFile( File file );
+
+    class Mixin
+        implements UoWFileFactory
+    {
+
+        private static class UoWFilesMetaInfo
+            extends HashMap<String, UoWFile>
+        {
+        }
+
+        private static final Logger LOGGER = LoggerFactory.getLogger( "org.apache.polygene.library.uowfile" );
+
+        @Structure
+        private Application app;
+
+        @Structure
+        private UnitOfWorkFactory module;
+
+        @This
+        private ServiceComposite me;
+
+        @Optional
+        @Service
+        private FileConfiguration fileConfig;
+
+        private File workDir;
+
+        @Override
+        public void activateService()
+            throws IOException
+        {
+            File tmp;
+            if( fileConfig == null )
+            {
+                tmp = new File( "polygene", app.name() + "-" + app.version() );
+            }
+            else
+            {
+                tmp = fileConfig.temporaryDirectory();
+            }
+            workDir = new File( tmp, "uowfile-" + me.identity().get() );
+            if( !workDir.exists() && !workDir.mkdirs() )
+            {
+                throw new IOException( "Unable to create temporary directory: " + workDir );
+            }
+        }
+
+        @Override
+        public void passivateService()
+            throws Exception
+        {
+        }
+
+        @Override
+        public UoWFile createCurrentUoWFile( File file )
+        {
+            return createUoWFile( module.currentUnitOfWork(), file, workDir );
+        }
+
+        private static synchronized UoWFile createUoWFile( UnitOfWork uow, File file, File workDir )
+        {
+            UoWFilesMetaInfo uowMeta = ensureUoWMeta( uow );
+            String absolutePath = file.getAbsolutePath();
+            UoWFile uowFile = uowMeta.get( absolutePath );
+            if( uowFile == null )
+            {
+                uowFile = new UoWFile( file, workDir );
+                uowFile.copyOriginalToCurrent();
+                uowMeta.put( absolutePath, uowFile );
+                LOGGER.trace( "Registered {} in UoW", uowFile );
+            }
+            return uowFile;
+        }
+
+        /**
+         * Ensure UoW meta info tracking UoWFiles is present and UoW callback is registered.
+         */
+        private static UoWFilesMetaInfo ensureUoWMeta( final UnitOfWork uow )
+        {
+            UoWFilesMetaInfo uowMeta = uow.metaInfo( UoWFilesMetaInfo.class );
+            if( uowMeta != null )
+            {
+                return uowMeta;
+            }
+
+            uowMeta = new UoWFilesMetaInfo();
+            uow.setMetaInfo( uowMeta );
+
+            uow.addUnitOfWorkCallback( new UnitOfWorkCallback()
+            {
+                @Override
+                public void beforeCompletion()
+                    throws UnitOfWorkCompletionException
+                {
+                    UoWFilesMetaInfo uowMeta = uow.metaInfo( UoWFilesMetaInfo.class );
+                    if( uowMeta != null && !uowMeta.isEmpty() )
+                    {
+                        List<UoWFile> concurrentlyModified = new ArrayList<>();
+                        for( UoWFile eachUoWFile : uowMeta.values() )
+                        {
+                            try
+                            {
+                                eachUoWFile.apply();
+                            }
+                            catch( ConcurrentUoWFileStateModificationException ex )
+                            {
+                                concurrentlyModified.add( ex.getUoWFile() );
+                            }
+                        }
+                        if( !concurrentlyModified.isEmpty() )
+                        {
+                            throw new ConcurrentUoWFileModificationException( concurrentlyModified, uow.usecase() );
+                        }
+                    }
+                }
+
+                @Override
+                public void afterCompletion( UnitOfWorkStatus status )
+                {
+                    UoWFilesMetaInfo uowMeta = uow.metaInfo( UoWFilesMetaInfo.class );
+                    if( uowMeta != null && !uowMeta.isEmpty() )
+                    {
+                        for( UoWFile eachUoWFile : uowMeta.values() )
+                        {
+                            if( status == UnitOfWorkStatus.DISCARDED )
+                            {
+                                eachUoWFile.rollback();
+                            }
+                            eachUoWFile.cleanup();
+                        }
+                        uow.metaInfo( UoWFilesMetaInfo.class ).clear();
+                    }
+                }
+            } );
+            return uowMeta;
+        }
+    }
+}
diff --git a/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/package.html b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/package.html
new file mode 100644
index 0000000..4ad79fa
--- /dev/null
+++ b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/internal/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>UnitOfWork File Library Internal Package.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/plural/HasUoWFiles.java b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/plural/HasUoWFiles.java
new file mode 100644
index 0000000..315582a
--- /dev/null
+++ b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/plural/HasUoWFiles.java
@@ -0,0 +1,90 @@
+/*
+ *  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.polygene.library.uowfile.plural;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.library.uowfile.internal.UoWFileFactory;
+
+@Mixins( HasUoWFiles.Mixin.class )
+// START SNIPPET: contract
+public interface HasUoWFiles<T extends Enum<T>>
+{
+    /**
+     * IMPORTANT Use this {@link File} only inside read-only {@link UnitOfWork}s
+     */
+    File attachedFile( T key );
+
+    /**
+     * IMPORTANT Use these {@link File}s only inside read-only {@link UnitOfWork}s
+     */
+    Iterable<File> attachedFiles();
+
+    File managedFile( T key );
+
+    Iterable<File> managedFiles();
+    // END SNIPPET: contract
+
+    abstract class Mixin<R extends Enum<R>>
+        implements HasUoWFiles<R>
+    {
+        @Service
+        private UoWFileFactory uowFileFactory;
+        @This
+        private UoWFilesLocator<R> locator;
+
+        @Override
+        public File attachedFile( R key )
+        {
+            return locator.locateAttachedFile( key );
+        }
+
+        @Override
+        public Iterable<File> attachedFiles()
+        {
+            return locator.locateAttachedFiles();
+        }
+
+        @Override
+        public File managedFile( R key )
+        {
+            return uowFileFactory.createCurrentUoWFile( locator.locateAttachedFile( key ) ).asFile();
+        }
+
+        @Override
+        public Iterable<File> managedFiles()
+        {
+            List<File> managedFiles = new ArrayList<>();
+            for( File eachAttachedFile : locator.locateAttachedFiles() )
+            {
+                managedFiles.add( uowFileFactory.createCurrentUoWFile( eachAttachedFile ).asFile() );
+            }
+            return managedFiles;
+        }
+    }
+
+    // START SNIPPET: contract
+}
+// END SNIPPET: contract
diff --git a/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/plural/HasUoWFilesLifecycle.java b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/plural/HasUoWFilesLifecycle.java
new file mode 100644
index 0000000..476acd5
--- /dev/null
+++ b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/plural/HasUoWFilesLifecycle.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.library.uowfile.plural;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.entity.Lifecycle;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+
+@Mixins( HasUoWFilesLifecycle.Mixin.class )
+public interface HasUoWFilesLifecycle<T extends Enum<T>>
+    extends HasUoWFiles<T>, Lifecycle
+{
+    class Mixin
+        implements Lifecycle
+    {
+        @This
+        private HasUoWFiles<?> hasUoWFiles;
+
+        @Override
+        public void create()
+        {
+            // NOOP
+        }
+
+        @Override
+        public void remove()
+            throws IOException
+        {
+            // We use the managed files so that if the UoW gets discarded the files will be restored
+            List<File> errors = new ArrayList<>();
+            for( File eachFile : hasUoWFiles.managedFiles() )
+            {
+                if( eachFile.exists() )
+                {
+                    if( !eachFile.delete() )
+                    {
+                        errors.add( eachFile );
+                    }
+                }
+            }
+            if( !errors.isEmpty() )
+            {
+                throw new IOException( "Unable to delete existing files: " + errors );
+            }
+        }
+    }
+
+}
diff --git a/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/plural/UoWFilesLocator.java b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/plural/UoWFilesLocator.java
new file mode 100644
index 0000000..3afed71
--- /dev/null
+++ b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/plural/UoWFilesLocator.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.library.uowfile.plural;
+
+import java.io.File;
+
+public interface UoWFilesLocator<T extends Enum<T>>
+{
+    File locateAttachedFile( T key );
+
+    Iterable<File> locateAttachedFiles();
+}
diff --git a/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/plural/package.html b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/plural/package.html
new file mode 100644
index 0000000..61ec024
--- /dev/null
+++ b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/plural/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>UnitOfWork File Plural Support.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/singular/HasUoWFile.java b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/singular/HasUoWFile.java
new file mode 100644
index 0000000..01a2f36
--- /dev/null
+++ b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/singular/HasUoWFile.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.library.uowfile.singular;
+
+import java.io.File;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.library.uowfile.internal.UoWFileFactory;
+
+@Mixins( HasUoWFile.Mixin.class )
+// START SNIPPET: contract
+public interface HasUoWFile
+{
+    /**
+     * IMPORTANT Use this {@link File} inside read-only {@link UnitOfWork}s only
+     * @return The file that is attached.
+     */
+    File attachedFile();
+
+    File managedFile();
+    // END SNIPPET: contract
+
+    class Mixin
+        implements HasUoWFile
+    {
+        @Service
+        private UoWFileFactory uowFileFactory;
+
+        @This
+        private UoWFileLocator locator;
+
+        @Override
+        public File attachedFile()
+        {
+            return locator.locateAttachedFile();
+        }
+
+        @Override
+        public File managedFile()
+        {
+            return uowFileFactory.createCurrentUoWFile( locator.locateAttachedFile() ).asFile();
+        }
+    }
+    // START SNIPPET: contract
+
+}
+// END SNIPPET: contract
diff --git a/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/singular/HasUoWFileLifecycle.java b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/singular/HasUoWFileLifecycle.java
new file mode 100644
index 0000000..598baf5
--- /dev/null
+++ b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/singular/HasUoWFileLifecycle.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.library.uowfile.singular;
+
+import java.io.File;
+import java.io.IOException;
+import org.apache.polygene.api.entity.Lifecycle;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+
+@Mixins( HasUoWFileLifecycle.Mixin.class )
+public interface HasUoWFileLifecycle
+    extends HasUoWFile, Lifecycle
+{
+    class Mixin
+        implements Lifecycle
+    {
+        @This
+        private HasUoWFile hasUoWFile;
+
+        @Override
+        public void create()
+        {
+            // NOOP
+        }
+
+        @Override
+        public void remove()
+            throws IOException
+        {
+            // We use the managed file so that if the UoW gets discarded the file will be restored
+            File file = hasUoWFile.managedFile();
+            if( file.exists() && !file.delete() )
+            {
+                throw new IOException( "Unable to delete existing file: " + file );
+            }
+        }
+    }
+
+}
diff --git a/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/singular/UoWFileLocator.java b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/singular/UoWFileLocator.java
new file mode 100644
index 0000000..7e25e39
--- /dev/null
+++ b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/singular/UoWFileLocator.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.library.uowfile.singular;
+
+import java.io.File;
+
+public interface UoWFileLocator
+{
+    File locateAttachedFile();
+}
diff --git a/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/singular/package.html b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/singular/package.html
new file mode 100644
index 0000000..3b15a30
--- /dev/null
+++ b/libraries/uowfile/src/main/java/org/apache/polygene/library/uowfile/singular/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>UnitOfWork File Singular Support.</h2>
+    </body>
+</html>
\ No newline at end of file
diff --git a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/bootstrap/UoWFileAssembler.java b/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/bootstrap/UoWFileAssembler.java
deleted file mode 100644
index c6feabc..0000000
--- a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/bootstrap/UoWFileAssembler.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2011 Paul Merlin.
- *
- * Licensed  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.qi4j.library.uowfile.bootstrap;
-
-import org.qi4j.bootstrap.Assemblers;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.library.uowfile.internal.UoWFileFactory;
-import org.qi4j.library.uowfile.plural.HasUoWFiles;
-import org.qi4j.library.uowfile.plural.UoWFilesLocator;
-import org.qi4j.library.uowfile.singular.HasUoWFile;
-import org.qi4j.library.uowfile.singular.UoWFileLocator;
-
-/**
- * Add services needed for {@link HasUoWFile} and {@link HasUoWFiles}.
- * 
- * You usually want to use this assembler on the module where your entities belong.
- * 
- * Your entity types must extends either {@link HasUoWFile} or {@link HasUoWFiles}.
- * Their mixins must respectively implements {@link UoWFileLocator} and {@link UoWFilesLocator}
- */
-public class UoWFileAssembler
-    extends Assemblers.Visibility<UoWFileAssembler>
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( UoWFileFactory.class ).visibleIn( visibility() );
-    }
-}
diff --git a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/bootstrap/package.html b/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/bootstrap/package.html
deleted file mode 100644
index c887e26..0000000
--- a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/bootstrap/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>UnitOfWork File Assembly.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/ConcurrentUoWFileModificationException.java b/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/ConcurrentUoWFileModificationException.java
deleted file mode 100644
index 1350011..0000000
--- a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/ConcurrentUoWFileModificationException.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011 Paul Merlin.
- *
- * Licensed  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.qi4j.library.uowfile.internal;
-
-import java.util.Collections;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.unitofwork.ConcurrentEntityModificationException;
-
-public class ConcurrentUoWFileModificationException
-    extends ConcurrentEntityModificationException
-{
-    private final Iterable<UoWFile> concurrentlyModifiedFiles;
-
-    ConcurrentUoWFileModificationException( Iterable<UoWFile> concurrentlyModifiedFiles )
-    {
-        super( Collections.<EntityComposite>emptyList() );
-        this.concurrentlyModifiedFiles = concurrentlyModifiedFiles;
-    }
-
-    public Iterable<UoWFile> concurrentlyModifiedUoWFiles()
-    {
-        return concurrentlyModifiedFiles;
-    }
-
-    @Override
-    public String getMessage()
-    {
-        return "Files changed concurently: " + concurrentlyModifiedFiles;
-    }
-}
diff --git a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/ConcurrentUoWFileStateModificationException.java b/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/ConcurrentUoWFileStateModificationException.java
deleted file mode 100644
index 7c09144..0000000
--- a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/ConcurrentUoWFileStateModificationException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2011 Paul Merlin.
- *
- * Licensed  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.qi4j.library.uowfile.internal;
-
-class ConcurrentUoWFileStateModificationException
-    extends Exception
-{
-    private final UoWFile file;
-
-    ConcurrentUoWFileStateModificationException( UoWFile file )
-    {
-        this.file = file;
-    }
-
-    UoWFile getUoWFile()
-    {
-        return file;
-    }
-
-    @Override
-    public String getMessage()
-    {
-        return "UoWFile modified concurently: " + file.toString();
-    }
-}
diff --git a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/UoWFile.java b/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/UoWFile.java
deleted file mode 100644
index f8b0bb8..0000000
--- a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/UoWFile.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright 2011 Paul Merlin.
- *
- * Licensed  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.qi4j.library.uowfile.internal;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.concurrent.atomic.AtomicLong;
-import org.qi4j.io.Inputs;
-import org.qi4j.io.Outputs;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class UoWFile
-{
-    /* package */ static final Logger LOGGER = LoggerFactory.getLogger( "org.qi4j.library.uowfile" );
-    private static final int FILE_BUFFER_SIZE = 4096;
-    private static final AtomicLong COUNT = new AtomicLong( 0L );
-    private final long originalIdentity;
-    private final File original;
-    private final File current;
-    private final File backup;
-
-    UoWFile( File original, File workDir )
-    {
-        this.originalIdentity = original.length() + original.lastModified();
-        this.original = original;
-        long count = COUNT.incrementAndGet();
-        this.current = new File( workDir, original.getName() + ".current." + count );
-        this.backup = new File( workDir, original.getName() + ".backup." + count );
-    }
-
-    public File asFile()
-    {
-        return current;
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder().append( UoWFile.class.getSimpleName() );
-        // UoWFile{parent/( original(oid->id) | current(id) | backup(id) )}
-        sb.append( "{" ).append( original.getParentFile().getName() ).append( "/( " ).
-            append( original.getName() ).append( "(" ).append( originalIdentity ).append( "->" ).append( fileTag( original ) ).append( ") | " ).
-            append( current.getName() ).append( "(" ).append( fileTag( current ) ).append( ") | " ).
-            append( backup.getName() ).append( "(" ).append( fileTag( backup ) ).
-            append( ") )}" );
-        return sb.toString();
-    }
-
-    void copyOriginalToCurrent()
-    {
-        if( original.exists() )
-        {
-            copy( original, current );
-        }
-    }
-
-    void apply()
-        throws ConcurrentUoWFileStateModificationException
-    {
-        LOGGER.trace( "Will apply changes to {}", this );
-        if( fileTag( current ) != originalIdentity )
-        {
-            if( fileTag( original ) != originalIdentity )
-            {
-                LOGGER.info( "Concurrent modification, original creation identity is {} and original apply identity is {}", originalIdentity, fileTag( original ) );
-                throw new ConcurrentUoWFileStateModificationException( this );
-            }
-            if( original.exists() )
-            {
-                move( original, backup );
-            }
-            if( current.exists() )
-            {
-                move( current, original );
-            }
-            LOGGER.debug( "Applied changes to {}", original );
-        }
-    }
-
-    void rollback()
-    {
-        if( backup.exists() )
-        {
-            if( fileTag( original ) != originalIdentity )
-            {
-                delete( original );
-                move( backup, original );
-            }
-            LOGGER.debug( "Restored backup to {}", original );
-        }
-    }
-
-    void cleanup()
-    {
-        if( current.exists() )
-        {
-            delete( current );
-        }
-        if( backup.exists() )
-        {
-            delete( backup );
-        }
-    }
-
-    /**
-     * @return OL if the file does not exist
-     */
-    private long fileTag( File file )
-    {
-        return file.length() + file.lastModified();
-    }
-
-    private void copy( File source, File dest )
-    {
-        try
-        {
-            Inputs.byteBuffer( source, FILE_BUFFER_SIZE ).transferTo( Outputs.byteBuffer( dest ) );
-        }
-        catch( IOException ex )
-        {
-            throw new UoWFileException( ex );
-        }
-    }
-
-    private void delete( File file )
-    {
-        if( !file.delete() )
-        {
-            throw new UoWFileException( new IOException( "Unable to delete file " + file ) );
-        }
-    }
-
-    private void move( File source, File dest )
-    {
-        // Atomic move attempt
-        if( !source.renameTo( dest ) )
-        {
-            // source and dest are probably on different filesystem, fallback to a non atomic copy/move operation
-            copy( source, dest );
-            if( !source.delete() )
-            {
-                throw new UoWFileException( new IOException( "Unable to delete source file " + source
-                                                             + " after copy(move) to " + dest
-                                                             + " (rename failed before that)." ) );
-            }
-            LOGGER.warn( "Moved {} to {} using a copy/delete operation instead of an atomic move. "
-                         + "Are they on different filesystems?", source, dest );
-        }
-    }
-
-}
diff --git a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/UoWFileException.java b/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/UoWFileException.java
deleted file mode 100644
index ee48c49..0000000
--- a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/UoWFileException.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2011 Paul Merlin.
- *
- * Licensed  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.qi4j.library.uowfile.internal;
-
-import java.io.IOException;
-
-class UoWFileException
-    extends RuntimeException
-{
-    UoWFileException( IOException cause )
-    {
-        super( cause.getMessage(), cause );
-    }
-
-    UoWFileException( String message, IOException cause )
-    {
-        super( message, cause );
-    }
-}
diff --git a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/UoWFileFactory.java b/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/UoWFileFactory.java
deleted file mode 100644
index 863a102..0000000
--- a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/UoWFileFactory.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright 2011 Paul Merlin.
- *
- * Licensed  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.qi4j.library.uowfile.internal;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceActivation;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCallback;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.library.fileconfig.FileConfiguration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Mixins( UoWFileFactory.Mixin.class )
-public interface UoWFileFactory
-    extends ServiceActivation
-{
-
-    UoWFile createCurrentUoWFile( File file );
-
-    class Mixin
-        implements UoWFileFactory
-    {
-
-        private static class UoWFilesMetaInfo
-            extends HashMap<String, UoWFile>
-        {
-        }
-
-        private static final Logger LOGGER = LoggerFactory.getLogger( "org.qi4j.library.uowfile" );
-
-        @Structure
-        private Application app;
-
-        @Structure
-        private Module module;
-
-        @This
-        private ServiceComposite me;
-
-        @Optional
-        @Service
-        private FileConfiguration fileConfig;
-
-        private File workDir;
-
-        @Override
-        public void activateService()
-            throws IOException
-        {
-            File tmp;
-            if( fileConfig == null )
-            {
-                tmp = new File( "qi4j", app.name() + "-" + app.version() );
-            }
-            else
-            {
-                tmp = fileConfig.temporaryDirectory();
-            }
-            workDir = new File( tmp, "uowfile-" + me.identity().get() );
-            if( !workDir.exists() && !workDir.mkdirs() )
-            {
-                throw new IOException( "Unable to create temporary directory: " + workDir );
-            }
-        }
-
-        @Override
-        public void passivateService()
-            throws Exception
-        {
-        }
-
-        @Override
-        public UoWFile createCurrentUoWFile( File file )
-        {
-            return createUoWFile( module.currentUnitOfWork(), file, workDir );
-        }
-
-        private static synchronized UoWFile createUoWFile( UnitOfWork uow, File file, File workDir )
-        {
-            UoWFilesMetaInfo uowMeta = ensureUoWMeta( uow );
-            String absolutePath = file.getAbsolutePath();
-            UoWFile uowFile = uowMeta.get( absolutePath );
-            if( uowFile == null )
-            {
-                uowFile = new UoWFile( file, workDir );
-                uowFile.copyOriginalToCurrent();
-                uowMeta.put( absolutePath, uowFile );
-                LOGGER.trace( "Registered {} in UoW", uowFile );
-            }
-            return uowFile;
-        }
-
-        /**
-         * Ensure UoW meta info tracking UoWFiles is present and UoW callback is registered.
-         */
-        private static UoWFilesMetaInfo ensureUoWMeta( final UnitOfWork uow )
-        {
-            UoWFilesMetaInfo uowMeta = uow.metaInfo( UoWFilesMetaInfo.class );
-            if( uowMeta != null )
-            {
-                return uowMeta;
-            }
-
-            uowMeta = new UoWFilesMetaInfo();
-            uow.setMetaInfo( uowMeta );
-
-            uow.addUnitOfWorkCallback( new UnitOfWorkCallback()
-            {
-                @Override
-                public void beforeCompletion()
-                    throws UnitOfWorkCompletionException
-                {
-                    UoWFilesMetaInfo uowMeta = uow.metaInfo( UoWFilesMetaInfo.class );
-                    if( uowMeta != null && !uowMeta.isEmpty() )
-                    {
-                        List<UoWFile> concurrentlyModified = new ArrayList<>();
-                        for( UoWFile eachUoWFile : uowMeta.values() )
-                        {
-                            try
-                            {
-                                eachUoWFile.apply();
-                            }
-                            catch( ConcurrentUoWFileStateModificationException ex )
-                            {
-                                concurrentlyModified.add( ex.getUoWFile() );
-                            }
-                        }
-                        if( !concurrentlyModified.isEmpty() )
-                        {
-                            throw new ConcurrentUoWFileModificationException( concurrentlyModified );
-                        }
-                    }
-                }
-
-                @Override
-                public void afterCompletion( UnitOfWorkStatus status )
-                {
-                    UoWFilesMetaInfo uowMeta = uow.metaInfo( UoWFilesMetaInfo.class );
-                    if( uowMeta != null && !uowMeta.isEmpty() )
-                    {
-                        for( UoWFile eachUoWFile : uowMeta.values() )
-                        {
-                            if( status == UnitOfWorkStatus.DISCARDED )
-                            {
-                                eachUoWFile.rollback();
-                            }
-                            eachUoWFile.cleanup();
-                        }
-                        uow.metaInfo( UoWFilesMetaInfo.class ).clear();
-                    }
-                }
-            } );
-            return uowMeta;
-        }
-    }
-
-}
diff --git a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/package.html b/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/package.html
deleted file mode 100644
index bdb34b1..0000000
--- a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/internal/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>UnitOfWork File Library Internal Package.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/plural/HasUoWFiles.java b/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/plural/HasUoWFiles.java
deleted file mode 100644
index f1d2ac1..0000000
--- a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/plural/HasUoWFiles.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2011 Paul Merlin.
- *
- * Licensed  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.qi4j.library.uowfile.plural;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.library.uowfile.internal.UoWFileFactory;
-
-@Mixins( HasUoWFiles.Mixin.class )
-// START SNIPPET: contract
-public interface HasUoWFiles<T extends Enum<T>>
-{
-    /**
-     * IMPORTANT Use this {@link File} only inside read-only {@link UnitOfWork}s
-     */
-    File attachedFile( T key );
-
-    /**
-     * IMPORTANT Use these {@link File}s only inside read-only {@link UnitOfWork}s
-     */
-    Iterable<File> attachedFiles();
-
-    File managedFile( T key );
-
-    Iterable<File> managedFiles();
-    // END SNIPPET: contract
-
-    abstract class Mixin<R extends Enum<R>>
-        implements HasUoWFiles<R>
-    {
-        @Service
-        private UoWFileFactory uowFileFactory;
-        @This
-        private UoWFilesLocator<R> locator;
-
-        @Override
-        public File attachedFile( R key )
-        {
-            return locator.locateAttachedFile( key );
-        }
-
-        @Override
-        public Iterable<File> attachedFiles()
-        {
-            return locator.locateAttachedFiles();
-        }
-
-        @Override
-        public File managedFile( R key )
-        {
-            return uowFileFactory.createCurrentUoWFile( locator.locateAttachedFile( key ) ).asFile();
-        }
-
-        @Override
-        public Iterable<File> managedFiles()
-        {
-            List<File> managedFiles = new ArrayList<>();
-            for( File eachAttachedFile : locator.locateAttachedFiles() )
-            {
-                managedFiles.add( uowFileFactory.createCurrentUoWFile( eachAttachedFile ).asFile() );
-            }
-            return managedFiles;
-        }
-    }
-
-    // START SNIPPET: contract
-}
-// END SNIPPET: contract
diff --git a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/plural/HasUoWFilesLifecycle.java b/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/plural/HasUoWFilesLifecycle.java
deleted file mode 100644
index 5a634f6..0000000
--- a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/plural/HasUoWFilesLifecycle.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2011 Paul Merlin.
- *
- * Licensed  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.qi4j.library.uowfile.plural;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.entity.Lifecycle;
-import org.qi4j.api.entity.LifecycleException;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-
-@Mixins( HasUoWFilesLifecycle.Mixin.class )
-public interface HasUoWFilesLifecycle<T extends Enum<T>>
-    extends HasUoWFiles<T>, Lifecycle
-{
-    public class Mixin
-        implements Lifecycle
-    {
-        @This
-        private HasUoWFiles<?> hasUoWFiles;
-
-        @Override
-        public void create()
-            throws LifecycleException
-        {
-            // NOOP
-        }
-
-        @Override
-        public void remove()
-            throws LifecycleException
-        {
-            // We use the managed files so that if the UoW gets discarded the files will be restored
-            List<File> errors = new ArrayList<>();
-            for( File eachFile : hasUoWFiles.managedFiles() )
-            {
-                if( eachFile.exists() )
-                {
-                    if( !eachFile.delete() )
-                    {
-                        errors.add( eachFile );
-                    }
-                }
-            }
-            if( !errors.isEmpty() )
-            {
-                throw new LifecycleException( "Unable to delete existing files: " + errors );
-            }
-        }
-    }
-
-}
diff --git a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/plural/UoWFilesLocator.java b/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/plural/UoWFilesLocator.java
deleted file mode 100644
index 11e9263..0000000
--- a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/plural/UoWFilesLocator.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2011 Paul Merlin.
- *
- * Licensed  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.qi4j.library.uowfile.plural;
-
-import java.io.File;
-
-public interface UoWFilesLocator<T extends Enum<T>>
-{
-    File locateAttachedFile( T key );
-
-    Iterable<File> locateAttachedFiles();
-}
diff --git a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/plural/package.html b/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/plural/package.html
deleted file mode 100644
index d0b791e..0000000
--- a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/plural/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>UnitOfWork File Plural Support.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/singular/HasUoWFile.java b/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/singular/HasUoWFile.java
deleted file mode 100644
index e0df50e..0000000
--- a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/singular/HasUoWFile.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2011 Paul Merlin.
- *
- * Licensed  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.qi4j.library.uowfile.singular;
-
-import java.io.File;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.library.uowfile.internal.UoWFileFactory;
-
-@Mixins( HasUoWFile.Mixin.class )
-// START SNIPPET: contract
-public interface HasUoWFile
-{
-    /**
-     * IMPORTANT Use this {@link File} inside read-only {@link UnitOfWork}s only
-     * @return The file that is attached.
-     */
-    File attachedFile();
-
-    File managedFile();
-    // END SNIPPET: contract
-
-    class Mixin
-        implements HasUoWFile
-    {
-        @Service
-        private UoWFileFactory uowFileFactory;
-
-        @This
-        private UoWFileLocator locator;
-
-        @Override
-        public File attachedFile()
-        {
-            return locator.locateAttachedFile();
-        }
-
-        @Override
-        public File managedFile()
-        {
-            return uowFileFactory.createCurrentUoWFile( locator.locateAttachedFile() ).asFile();
-        }
-    }
-    // START SNIPPET: contract
-
-}
-// END SNIPPET: contract
diff --git a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/singular/HasUoWFileLifecycle.java b/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/singular/HasUoWFileLifecycle.java
deleted file mode 100644
index 83364de..0000000
--- a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/singular/HasUoWFileLifecycle.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2011 Paul Merlin.
- *
- * Licensed  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.qi4j.library.uowfile.singular;
-
-import java.io.File;
-import org.qi4j.api.entity.Lifecycle;
-import org.qi4j.api.entity.LifecycleException;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-
-@Mixins( HasUoWFileLifecycle.Mixin.class )
-public interface HasUoWFileLifecycle
-    extends HasUoWFile, Lifecycle
-{
-    class Mixin
-        implements Lifecycle
-    {
-        @This
-        private HasUoWFile hasUoWFile;
-
-        @Override
-        public void create()
-            throws LifecycleException
-        {
-            // NOOP
-        }
-
-        @Override
-        public void remove()
-            throws LifecycleException
-        {
-            // We use the managed file so that if the UoW gets discarded the file will be restored
-            File file = hasUoWFile.managedFile();
-            if( file.exists() && !file.delete() )
-            {
-                throw new LifecycleException( "Unable to delete existing file: " + file );
-            }
-        }
-    }
-
-}
diff --git a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/singular/UoWFileLocator.java b/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/singular/UoWFileLocator.java
deleted file mode 100644
index 7555c04..0000000
--- a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/singular/UoWFileLocator.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2011 Paul Merlin.
- *
- * Licensed  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.qi4j.library.uowfile.singular;
-
-import java.io.File;
-
-public interface UoWFileLocator
-{
-    File locateAttachedFile();
-}
diff --git a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/singular/package.html b/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/singular/package.html
deleted file mode 100644
index 378e2a8..0000000
--- a/libraries/uowfile/src/main/java/org/qi4j/library/uowfile/singular/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>UnitOfWork File Singular Support.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/uowfile/src/test/java/org/apache/polygene/library/uowfile/HasUoWFileTest.java b/libraries/uowfile/src/test/java/org/apache/polygene/library/uowfile/HasUoWFileTest.java
new file mode 100644
index 0000000..ea92556
--- /dev/null
+++ b/libraries/uowfile/src/test/java/org/apache/polygene/library/uowfile/HasUoWFileTest.java
@@ -0,0 +1,433 @@
+/*
+ *  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.polygene.library.uowfile;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkConcern;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkRetry;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.uowfile.bootstrap.UoWFileAssembler;
+import org.apache.polygene.library.uowfile.internal.ConcurrentUoWFileModificationException;
+import org.apache.polygene.library.uowfile.singular.HasUoWFileLifecycle;
+import org.apache.polygene.library.uowfile.singular.UoWFileLocator;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class HasUoWFileTest
+    extends AbstractPolygeneTest
+{
+    private static final Logger LOGGER = LoggerFactory.getLogger( HasUoWFileTest.class );
+    private static final URL CREATION_CONTENT_URL = HasUoWFileTest.class.getResource( "creation.txt" );
+    private static final URL MODIFICATION_CONTENT_URL = HasUoWFileTest.class.getResource( "modification.txt" );
+
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    // START SNIPPET: entity
+    // START SNIPPET: uowfile
+    public interface TestedEntity
+        extends HasUoWFileLifecycle // END SNIPPET: entity
+        , HasIdentity
+    // START SNIPPET: entity
+    {
+        Property<String> name();
+    }
+    // END SNIPPET: entity
+    // END SNIPPET: uowfile
+
+    // START SNIPPET: locator
+    public static class TestedFileLocatorMixin
+        implements UoWFileLocator
+    {
+        @This
+        private HasIdentity meAsIdentity;
+
+        @Structure
+        private PolygeneSPI spi;
+
+        @Override
+        public File locateAttachedFile()
+        {
+            File baseDir = spi.entityDescriptorFor( meAsIdentity ).metaInfo( File.class );
+            return new File( baseDir, meAsIdentity.identity().get().toString() );
+        }
+    }
+    // END SNIPPET: locator
+
+    @Mixins( HasUoWFileTest.TestServiceMixin.class )
+    @Concerns( UnitOfWorkConcern.class )
+    public interface TestService
+    {
+        void modifyFile( Identity entityId )
+            throws IOException;
+
+        @UnitOfWorkPropagation
+        @UnitOfWorkRetry
+        void modifyFileWithRetry( Identity entityId, long sleepBefore, long sleepAfter )
+            throws IOException;
+    }
+
+    public static abstract class TestServiceMixin
+        implements TestService
+    {
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @Override
+        public void modifyFile( Identity entityId )
+            throws IOException
+        {
+            modifyFileImmediatly( entityId );
+        }
+
+        @Override
+        public void modifyFileWithRetry( Identity entityId, long sleepBefore, long sleepAfter )
+            throws IOException
+        {
+            LOGGER.info( "Waiting " + sleepBefore + "ms before file modification" );
+            if( sleepBefore > 0 )
+            {
+                try
+                {
+                    Thread.sleep( sleepBefore );
+                }
+                catch( InterruptedException ex )
+                {
+                    throw new RuntimeException( ex );
+                }
+            }
+            modifyFileImmediatly( entityId );
+            LOGGER.info( "Waiting " + sleepAfter + "ms after file modification" );
+            if( sleepAfter > 0 )
+            {
+                try
+                {
+                    Thread.sleep( sleepAfter );
+                }
+                catch( InterruptedException ex )
+                {
+                    throw new RuntimeException( ex );
+                }
+            }
+        }
+
+        private void modifyFileImmediatly( Identity entityId )
+            throws IOException
+        {
+            TestedEntity entity = uowf.currentUnitOfWork().get( TestedEntity.class, entityId );
+            // START SNIPPET: api
+            File attachedFile = entity.attachedFile();
+            File managedFile = entity.managedFile();
+            // END SNIPPET: api
+            try( InputStream input = MODIFICATION_CONTENT_URL.openStream() )
+            {
+                Files.copy( input, managedFile.toPath(), REPLACE_EXISTING );
+            }
+        }
+    }
+
+    @Override
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new UoWFileAssembler().assemble( module );
+
+        module.entities( TestedEntity.class ).withMixins( TestedFileLocatorMixin.class );
+        // END SNIPPET: assembly
+        module.entities( TestedEntity.class ).setMetaInfo( tmpDir.getRoot() );
+        module.services( TestService.class );
+        new EntityTestAssembler().assemble( module );
+        new FileConfigurationAssembler().assemble( module );
+        // START SNIPPET: assembly
+    }
+    // END SNIPPET: assembly
+
+    private TestService testService;
+
+    @Before
+    public void beforeTest()
+    {
+        testService = serviceFinder.findService( TestService.class ).get();
+    }
+
+    @Test
+    public void testCreation()
+        throws UnitOfWorkCompletionException, IOException
+    {
+        LOGGER.info( "# Test Creation ##############################################################################" );
+        File attachedFile;
+
+        // Test discarded creation
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            TestedEntity entity = createTestedEntity( uow, "Testing Creation Rollback" );
+            attachedFile = entity.attachedFile();
+        }
+        assertFalse( "File still exists after discarded creation UoW", attachedFile.exists() );
+
+        // Test completed creation
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            TestedEntity entity = createTestedEntity( uow, "Testing Creation" );
+            attachedFile = entity.attachedFile();
+            uow.complete();
+        }
+        try( Stream<String> lines = Files.lines( attachedFile.toPath() ) )
+        {
+            assertThat( "File content was not the good one",
+                        lines.limit( 1 ).findFirst().get(),
+                        equalTo( "Creation" ) );
+        }
+    }
+
+    @Test
+    public void testModification()
+        throws UnitOfWorkCompletionException, IOException
+    {
+        LOGGER.info( "# Test Modification ##########################################################################" );
+        final Identity entityId;
+        File attachedFile;
+
+        // Create new
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            TestedEntity entity = createTestedEntity( uow, "Testing Modification" );
+            entityId = entity.identity().get();
+            attachedFile = entity.attachedFile();
+            uow.complete();
+        }
+
+        // Testing discarded modification
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            testService.modifyFile( entityId );
+        }
+        try( Stream<String> lines = Files.lines( attachedFile.toPath() ) )
+        {
+            assertThat( "File content after discarded modification was not the good one",
+                        lines.limit( 1 ).findFirst().get(),
+                        equalTo( "Creation" ) );
+        }
+
+        // Testing completed modification
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            testService.modifyFile( entityId );
+            uow.complete();
+        }
+        try( Stream<String> lines = Files.lines( attachedFile.toPath() ) )
+        {
+            assertThat( "Modified file content was not the good one",
+                        lines.limit( 1 ).findFirst().get(),
+                        equalTo( "Modification" ) );
+        }
+    }
+
+    @Test
+    public void testDeletion()
+        throws UnitOfWorkCompletionException, IOException
+    {
+        LOGGER.info( "# Test Deletion ##############################################################################" );
+        final Identity entityId;
+        File attachedFile;
+
+        // Create new
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            TestedEntity entity = createTestedEntity( uow, "Testing Deletion" );
+            entityId = entity.identity().get();
+            attachedFile = entity.attachedFile();
+            uow.complete();
+        }
+
+        // Testing discarded deletion
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            TestedEntity entity = uow.get( TestedEntity.class, entityId );
+            uow.remove( entity );
+        }
+        assertTrue( "File do not exists after discarded deletion", attachedFile.exists() );
+
+        // Testing completed deletion
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            TestedEntity entity = uow.get( TestedEntity.class, entityId );
+            uow.remove( entity );
+            uow.complete();
+        }
+        assertFalse( "File still exists after deletion", attachedFile.exists() );
+    }
+
+    @Test
+    public void testConcurrentModification()
+        throws IOException, UnitOfWorkCompletionException
+    {
+        LOGGER.info( "# Test Concurrent Modification ###############################################################" );
+        final Identity entityId;
+
+        // Create new
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            TestedEntity entity = createTestedEntity( uow, "Testing Concurrent Modification" );
+            entityId = entity.identity().get();
+            uow.complete();
+        }
+
+        // Testing concurrent modification
+        UnitOfWork uow, uow2;
+        TestedEntity entity;
+
+        uow = unitOfWorkFactory.newUnitOfWork();
+        entity = uow.get( TestedEntity.class, entityId );
+        try( InputStream input = MODIFICATION_CONTENT_URL.openStream() )
+        {
+            Files.copy( input, entity.managedFile().toPath(), REPLACE_EXISTING );
+        }
+
+        uow2 = unitOfWorkFactory.newUnitOfWork();
+        entity = uow2.get( TestedEntity.class, entityId );
+        try( InputStream input = MODIFICATION_CONTENT_URL.openStream() )
+        {
+            Files.copy( input, entity.managedFile().toPath(), REPLACE_EXISTING );
+        }
+
+        uow.complete();
+        try
+        {
+            uow2.complete();
+            fail( "A ConcurrentUoWFileModificationException should have been raised" );
+        }
+        catch( ConcurrentUoWFileModificationException expected )
+        {
+            uow2.discard();
+        }
+    }
+
+    @Test
+    public void testRetry()
+        throws IOException, UnitOfWorkCompletionException, InterruptedException
+    {
+        LOGGER.info( "# Test Retry #################################################################################" );
+        final Identity entityId;
+        File attachedFile;
+
+        // Create new
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            TestedEntity entity = createTestedEntity( uow, "Testing Concurrent Modification" );
+            entityId = entity.identity().get();
+            attachedFile = entity.attachedFile();
+            uow.complete();
+        }
+
+        final List<Exception> ex = new ArrayList<>();
+        Thread t1 = new Thread(() ->
+        {
+            try
+            {
+                testService.modifyFileWithRetry( entityId, 0, 3000 );
+            }
+            catch( Exception ex1 )
+            {
+                ex.add( ex1 );
+            }
+        }, "job1" );
+        Thread t2 = new Thread(() ->
+        {
+            try
+            {
+                testService.modifyFileWithRetry( entityId, 1000, 0 );
+            }
+            catch( Exception ex1 )
+            {
+                ex.add( ex1 );
+            }
+        }, "job2" );
+
+        t1.start();
+        t2.start();
+
+        t1.join();
+        t2.join();
+
+        for( Exception eachEx : ex )
+        {
+            eachEx.printStackTrace();
+        }
+
+        assertTrue( "There were errors during TestRetry", ex.isEmpty() );
+        try( Stream<String> lines = Files.lines( attachedFile.toPath() ) )
+        {
+            assertThat( "Modified file content was not the good one",
+                        lines.limit( 1 ).findFirst().get(),
+                        equalTo( "Modification" ) );
+        }
+    }
+
+    private TestedEntity createTestedEntity( UnitOfWork uow, String name )
+        throws IOException
+    {
+        EntityBuilder<TestedEntity> builder = uow.newEntityBuilder( TestedEntity.class );
+        TestedEntity entity = builder.instance();
+        entity.name().set( name );
+        entity = builder.newInstance();
+        try( InputStream input = CREATION_CONTENT_URL.openStream() )
+        {
+            Files.copy( input, entity.managedFile().toPath() );
+        }
+        return entity;
+    }
+}
diff --git a/libraries/uowfile/src/test/java/org/apache/polygene/library/uowfile/HasUoWFilesTest.java b/libraries/uowfile/src/test/java/org/apache/polygene/library/uowfile/HasUoWFilesTest.java
new file mode 100644
index 0000000..6fcdce9
--- /dev/null
+++ b/libraries/uowfile/src/test/java/org/apache/polygene/library/uowfile/HasUoWFilesTest.java
@@ -0,0 +1,451 @@
+/*
+ *  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.polygene.library.uowfile;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkConcern;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkRetry;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.uowfile.bootstrap.UoWFileAssembler;
+import org.apache.polygene.library.uowfile.internal.ConcurrentUoWFileModificationException;
+import org.apache.polygene.library.uowfile.plural.HasUoWFilesLifecycle;
+import org.apache.polygene.library.uowfile.plural.UoWFilesLocator;
+import org.apache.polygene.spi.PolygeneSPI;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class HasUoWFilesTest
+    extends AbstractPolygeneTest
+{
+    private static final Logger LOGGER = LoggerFactory.getLogger( HasUoWFilesTest.class );
+    private static final URL CREATION_CONTENT_URL = HasUoWFilesTest.class.getResource( "creation.txt" );
+    private static final URL MODIFICATION_CONTENT_URL = HasUoWFilesTest.class.getResource( "modification.txt" );
+
+    @Rule
+    public final TemporaryFolder tmpDir = new TemporaryFolder();
+
+    // START SNIPPET: uowfile
+    public enum MyEnum
+    {
+        fileOne, fileTwo
+    }
+
+    // START SNIPPET: entity
+    public interface TestedEntity
+        extends HasUoWFilesLifecycle<MyEnum> // END SNIPPET: entity
+        , HasIdentity
+    // START SNIPPET: entity
+    {
+        Property<String> name();
+    }
+    // END SNIPPET: entity
+    // END SNIPPET: uowfile
+
+    // START SNIPPET: locator
+    public static abstract class TestedFilesLocatorMixin
+        implements UoWFilesLocator<MyEnum>
+    {
+        @This
+        private HasIdentity meAsIdentity;
+
+        @Structure
+        private PolygeneSPI spi;
+
+        @Override
+        public Iterable<File> locateAttachedFiles()
+        {
+            File baseDir = spi.entityDescriptorFor( meAsIdentity ).metaInfo( File.class );
+            List<File> list = new ArrayList<>();
+            for( MyEnum eachValue : MyEnum.values() )
+            {
+                list.add( new File( baseDir, meAsIdentity.identity().get() + "." + eachValue.name() ) );
+            }
+            return list;
+        }
+
+        @Override
+        public File locateAttachedFile( MyEnum key )
+        {
+            File baseDir = spi.entityDescriptorFor( meAsIdentity ).metaInfo( File.class );
+            return new File( baseDir, meAsIdentity.identity().get() + "." + key.name() );
+        }
+    }
+    // END SNIPPET: locator
+
+    @Mixins( TestServiceMixin.class )
+    @Concerns( UnitOfWorkConcern.class )
+    public interface TestService
+    {
+        void modifyFile( Identity entityId )
+            throws IOException;
+
+        @UnitOfWorkPropagation
+        @UnitOfWorkRetry
+        void modifyFileWithRetry( Identity entityId, long sleepBefore, long sleepAfter )
+            throws IOException;
+    }
+
+    public static class TestServiceMixin
+        implements TestService
+    {
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @Override
+        public void modifyFile( Identity entityId )
+            throws IOException
+        {
+            modifyFileImmediatly( entityId );
+        }
+
+        @Override
+        public void modifyFileWithRetry( Identity entityId, long sleepBefore, long sleepAfter )
+            throws IOException
+        {
+            LOGGER.info( "Waiting " + sleepBefore + "ms before file modification" );
+            if( sleepBefore > 0 )
+            {
+                try
+                {
+                    Thread.sleep( sleepBefore );
+                }
+                catch( InterruptedException ex )
+                {
+                    throw new RuntimeException( ex );
+                }
+            }
+            modifyFileImmediatly( entityId );
+            LOGGER.info( "Waiting " + sleepAfter + "ms after file modification" );
+            if( sleepAfter > 0 )
+            {
+                try
+                {
+                    Thread.sleep( sleepAfter );
+                }
+                catch( InterruptedException ex )
+                {
+                    throw new RuntimeException( ex );
+                }
+            }
+        }
+
+        private void modifyFileImmediatly( Identity entityId )
+            throws IOException
+        {
+            TestedEntity entity = uowf.currentUnitOfWork().get( TestedEntity.class, entityId );
+            // START SNIPPET: api
+            File attachedFileTwo = entity.attachedFile( MyEnum.fileTwo );
+            File managedFileOne = entity.managedFile( MyEnum.fileOne );
+            // END SNIPPET: api
+            try( InputStream input = MODIFICATION_CONTENT_URL.openStream() )
+            {
+                Files.copy( input, managedFileOne.toPath(), REPLACE_EXISTING );
+            }
+        }
+    }
+
+    @Override
+    // START SNIPPET: assembly
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new UoWFileAssembler().assemble( module );
+
+        module.entities( TestedEntity.class ).withMixins( TestedFilesLocatorMixin.class );
+        // END SNIPPET: assembly
+        module.entities( TestedEntity.class ).setMetaInfo( tmpDir.getRoot() );
+        module.services( TestService.class );
+        new EntityTestAssembler().assemble( module );
+        new FileConfigurationAssembler().assemble( module );
+        // START SNIPPET: assembly
+    }
+    // END SNIPPET: assembly
+
+    private TestService testService;
+
+    @Before
+    public void beforeTest()
+    {
+        testService = serviceFinder.findService( TestService.class ).get();
+    }
+
+    @Test
+    public void testCreation()
+        throws UnitOfWorkCompletionException, IOException
+    {
+        LOGGER.info( "# Test Creation ##############################################################################" );
+        File attachedFile;
+
+        // Test discarded creation
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            TestedEntity entity = createTestedOneEntityTwoFilesEntity( uow, "Testing Creation Rollback" );
+            attachedFile = entity.attachedFile( MyEnum.fileOne );
+        }
+        assertFalse( "File still exists after discarded creation UoW", attachedFile.exists() );
+
+        // Test completed creation
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            TestedEntity entity = createTestedOneEntityTwoFilesEntity( uow, "Testing Creation" );
+            attachedFile = entity.attachedFile( MyEnum.fileOne );
+            uow.complete();
+        }
+        try( Stream<String> lines = Files.lines( attachedFile.toPath() ) )
+        {
+            assertThat("File content was not the good one",
+                       lines.limit( 1 ).findFirst().get(),
+                       equalTo( "Creation" ) );
+        }
+    }
+
+    @Test
+    public void testModification()
+        throws UnitOfWorkCompletionException, IOException
+    {
+        LOGGER.info( "# Test Modification ##########################################################################" );
+        final Identity entityId;
+        File attachedFile;
+
+        // Create new
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            TestedEntity entity = createTestedOneEntityTwoFilesEntity( uow, "Testing Modification" );
+            entityId = entity.identity().get();
+            attachedFile = entity.attachedFile( MyEnum.fileOne );
+            uow.complete();
+        }
+
+        // Testing discarded modification
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            testService.modifyFile( entityId );
+        }
+        try( Stream<String> lines = Files.lines( attachedFile.toPath() ) )
+        {
+            assertThat("File content after discarded modification was not the good one",
+                       lines.limit( 1 ).findFirst().get(),
+                       equalTo( "Creation" ) );
+        }
+
+        // Testing completed modification
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            testService.modifyFile( entityId );
+            uow.complete();
+        }
+        try( Stream<String> lines = Files.lines( attachedFile.toPath() ) )
+        {
+            assertThat("Modified file content was not the good one",
+                       lines.limit( 1 ).findFirst().get(),
+                       equalTo( "Modification" ) );
+        }
+    }
+
+    @Test
+    public void testDeletion()
+        throws UnitOfWorkCompletionException, IOException
+    {
+        LOGGER.info( "# Test Deletion ##############################################################################" );
+        final Identity entityId;
+        File attachedFile;
+
+        // Create new
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            TestedEntity entity = createTestedOneEntityTwoFilesEntity( uow, "Testing Deletion" );
+            entityId = entity.identity().get();
+            attachedFile = entity.attachedFile( MyEnum.fileOne );
+            uow.complete();
+        }
+
+        // Testing discarded deletion
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            TestedEntity entity = uow.get( TestedEntity.class, entityId );
+            uow.remove( entity );
+        }
+        assertTrue( "File do not exists after discarded deletion", attachedFile.exists() );
+
+        // Testing completed deletion
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            TestedEntity entity = uow.get( TestedEntity.class, entityId );
+            uow.remove( entity );
+            uow.complete();
+        }
+        assertFalse( "File still exists after deletion", attachedFile.exists() );
+    }
+
+    @Test
+    public void testConcurrentModification()
+        throws IOException, UnitOfWorkCompletionException
+    {
+        LOGGER.info( "# Test Concurrent Modification ###############################################################" );
+        final Identity entityId;
+
+        // Create new
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            TestedEntity entity = createTestedOneEntityTwoFilesEntity( uow, "Testing Concurrent Modification" );
+            entityId = entity.identity().get();
+            uow.complete();
+        }
+
+        // Testing concurrent modification
+        UnitOfWork uow, uow2;
+        TestedEntity entity;
+
+        uow = unitOfWorkFactory.newUnitOfWork();
+        entity = uow.get( TestedEntity.class, entityId );
+        try( InputStream input = MODIFICATION_CONTENT_URL.openStream() )
+        {
+            Files.copy( input, entity.managedFile( MyEnum.fileOne ).toPath(), REPLACE_EXISTING );
+        }
+
+        uow2 = unitOfWorkFactory.newUnitOfWork();
+        entity = uow2.get( TestedEntity.class, entityId );
+        try( InputStream input = MODIFICATION_CONTENT_URL.openStream() )
+        {
+            Files.copy( input, entity.managedFile( MyEnum.fileOne ).toPath(), REPLACE_EXISTING );
+        }
+
+        uow.complete();
+        try
+        {
+            uow2.complete();
+            fail( "A ConcurrentUoWFileModificationException should have been raised" );
+        }
+        catch( ConcurrentUoWFileModificationException expected )
+        {
+            uow2.discard();
+        }
+    }
+
+    @Test
+    public void testRetry()
+        throws IOException, UnitOfWorkCompletionException, InterruptedException
+    {
+        LOGGER.info( "# Test Retry #################################################################################" );
+        final Identity entityId;
+        File attachedFile;
+
+        // Create new
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            TestedEntity entity = createTestedOneEntityTwoFilesEntity( uow, "Testing Concurrent Modification" );
+            entityId = entity.identity().get();
+            attachedFile = entity.attachedFile( MyEnum.fileOne );
+            uow.complete();
+        }
+
+        final List<Exception> ex = new ArrayList<>();
+        Thread t1 = new Thread(() ->
+        {
+            try
+            {
+                testService.modifyFileWithRetry( entityId, 0, 10000 );
+            }
+            catch( Exception ex1 )
+            {
+                ex.add( ex1 );
+            }
+        }, "job1" );
+        Thread t2 = new Thread(() ->
+        {
+            try
+            {
+                testService.modifyFileWithRetry( entityId, 5000, 0 );
+            }
+            catch( Exception ex1 )
+            {
+                ex.add( ex1 );
+            }
+        }, "job2" );
+
+        t1.start();
+        t2.start();
+
+        t1.join();
+        t2.join();
+
+        for( Exception eachEx : ex )
+        {
+            eachEx.printStackTrace();
+        }
+
+        assertTrue( "There were errors during TestRetry", ex.isEmpty() );
+        try( Stream<String> lines = Files.lines( attachedFile.toPath() ) )
+        {
+            assertThat("Modified file content was not the good one",
+                       lines.limit( 1 ).findFirst().get(),
+                       equalTo( "Modification" ) );
+        }
+    }
+
+    private TestedEntity createTestedOneEntityTwoFilesEntity( UnitOfWork uow, String name )
+        throws IOException
+    {
+        EntityBuilder<TestedEntity> builder = uow.newEntityBuilder( TestedEntity.class );
+        TestedEntity entity = builder.instance();
+        entity.name().set( name );
+        entity = builder.newInstance();
+        try( InputStream input = CREATION_CONTENT_URL.openStream() )
+        {
+            Files.copy( input, entity.managedFile( MyEnum.fileOne ).toPath() );
+        }
+        return entity;
+    }
+
+}
diff --git a/libraries/uowfile/src/test/java/org/qi4j/library/uowfile/AbstractUoWFileTest.java b/libraries/uowfile/src/test/java/org/qi4j/library/uowfile/AbstractUoWFileTest.java
deleted file mode 100644
index 8250658..0000000
--- a/libraries/uowfile/src/test/java/org/qi4j/library/uowfile/AbstractUoWFileTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2011-2014 Paul Merlin.
- *
- * Licensed  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.qi4j.library.uowfile;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Stack;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.qi4j.io.Inputs;
-import org.qi4j.io.Outputs;
-import org.qi4j.test.AbstractQi4jTest;
-
-public abstract class AbstractUoWFileTest
-    extends AbstractQi4jTest
-{
-    protected static File baseTestDir;
-
-    @BeforeClass
-    public static void beforeClass()
-        throws IOException
-    {
-        File testDir = new File( "build/uowfiletest" );
-        if( !testDir.exists() )
-        {
-            if( !testDir.mkdirs() )
-            {
-                throw new IOException( "Unable to create directory: " + testDir );
-            }
-        }
-        baseTestDir = testDir;
-    }
-
-    @AfterClass
-    public static void afterClass()
-    {
-        // Delete test data
-        Stack<File> stack = new Stack<>();
-        stack.push( baseTestDir );
-        while( !stack.empty() )
-        {
-            File each = stack.peek();
-            if( each.isDirectory() )
-            {
-                File[] children = each.listFiles();
-                if( children.length > 0 )
-                {
-                    for( File child : children )
-                    {
-                        stack.push( child );
-                    }
-                }
-                else
-                {
-                    stack.pop().delete();
-                }
-            }
-            else
-            {
-                stack.pop().delete();
-            }
-        }
-    }
-
-    protected final boolean isFileFirstLineEqualsTo( File file, String start )
-        throws IOException
-    {
-        List<String> lines = new ArrayList<>();
-        // This load the full file but used test resources are single line files
-        Inputs.text( file ).transferTo( Outputs.collection( lines ) );
-        return lines.get( 0 ).trim().startsWith( start );
-    }
-}
diff --git a/libraries/uowfile/src/test/java/org/qi4j/library/uowfile/HasUoWFileTest.java b/libraries/uowfile/src/test/java/org/qi4j/library/uowfile/HasUoWFileTest.java
deleted file mode 100644
index a9e0864..0000000
--- a/libraries/uowfile/src/test/java/org/qi4j/library/uowfile/HasUoWFileTest.java
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Copyright 2011-2014 Paul Merlin.
- *
- * Licensed  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.qi4j.library.uowfile;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.unitofwork.concern.UnitOfWorkConcern;
-import org.qi4j.api.unitofwork.concern.UnitOfWorkPropagation;
-import org.qi4j.api.unitofwork.concern.UnitOfWorkRetry;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.io.Inputs;
-import org.qi4j.io.Outputs;
-import org.qi4j.library.fileconfig.FileConfigurationAssembler;
-import org.qi4j.library.uowfile.bootstrap.UoWFileAssembler;
-import org.qi4j.library.uowfile.internal.ConcurrentUoWFileModificationException;
-import org.qi4j.library.uowfile.singular.HasUoWFileLifecycle;
-import org.qi4j.library.uowfile.singular.UoWFileLocator;
-import org.qi4j.test.EntityTestAssembler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-public class HasUoWFileTest
-    extends AbstractUoWFileTest
-{
-    private static final Logger LOGGER = LoggerFactory.getLogger( HasUoWFileTest.class );
-    private static final URL CREATION_CONTENT_URL = HasUoWFileTest.class.getResource( "creation.txt" );
-    private static final URL MODIFICATION_CONTENT_URL = HasUoWFileTest.class.getResource( "modification.txt" );
-
-    // START SNIPPET: entity
-    // START SNIPPET: uowfile
-    public interface TestedEntity
-        extends HasUoWFileLifecycle // END SNIPPET: entity
-        , Identity
-    // START SNIPPET: entity
-    {
-        Property<String> name();
-    }
-    // END SNIPPET: entity
-    // END SNIPPET: uowfile
-
-    // START SNIPPET: locator
-    public static class TestedFileLocatorMixin
-        implements UoWFileLocator
-    {
-        @This
-        private Identity meAsIdentity;
-
-        @Override
-        public File locateAttachedFile()
-        {
-            return new File( baseTestDir, meAsIdentity.identity().get() );
-        }
-    }
-    // END SNIPPET: locator
-
-    @Mixins( HasUoWFileTest.TestServiceMixin.class )
-    @Concerns( UnitOfWorkConcern.class )
-    public interface TestService
-    {
-        void modifyFile( String entityId )
-            throws IOException;
-
-        @UnitOfWorkPropagation
-        @UnitOfWorkRetry
-        void modifyFileWithRetry( String entityId, long sleepBefore, long sleepAfter )
-            throws IOException;
-    }
-
-    public static abstract class TestServiceMixin
-        implements TestService
-    {
-        @Structure
-        private Module module;
-
-        @Override
-        public void modifyFile( String entityId )
-            throws IOException
-        {
-            modifyFileImmediatly( entityId );
-        }
-
-        @Override
-        public void modifyFileWithRetry( String entityId, long sleepBefore, long sleepAfter )
-            throws IOException
-        {
-            LOGGER.info( "Waiting " + sleepBefore + "ms before file modification" );
-            if( sleepBefore > 0 )
-            {
-                try
-                {
-                    Thread.sleep( sleepBefore );
-                }
-                catch( InterruptedException ex )
-                {
-                    throw new RuntimeException( ex );
-                }
-            }
-            modifyFileImmediatly( entityId );
-            LOGGER.info( "Waiting " + sleepAfter + "ms after file modification" );
-            if( sleepAfter > 0 )
-            {
-                try
-                {
-                    Thread.sleep( sleepAfter );
-                }
-                catch( InterruptedException ex )
-                {
-                    throw new RuntimeException( ex );
-                }
-            }
-        }
-
-        private void modifyFileImmediatly( String entityId )
-            throws IOException
-        {
-            TestedEntity entity = module.currentUnitOfWork().get( TestedEntity.class, entityId );
-            // START SNIPPET: api
-            File attachedFile = entity.attachedFile();
-            File managedFile = entity.managedFile();
-            // END SNIPPET: api
-            Inputs.text( MODIFICATION_CONTENT_URL ).transferTo( Outputs.text( managedFile ) );
-        }
-
-    }
-
-    @Override
-    // START SNIPPET: assembly
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new UoWFileAssembler().assemble( module );
-
-        module.entities( TestedEntity.class ).withMixins( TestedFileLocatorMixin.class );
-        // END SNIPPET: assembly
-        module.services( TestService.class );
-        new EntityTestAssembler().assemble( module );
-        new FileConfigurationAssembler().assemble( module );
-        // START SNIPPET: assembly
-    }
-    // END SNIPPET: assembly
-
-    private TestService testService;
-
-    @Before
-    public void beforeTest()
-    {
-        testService = module.<TestService>findService( TestService.class ).get();
-    }
-
-    @Test
-    public void testCreation()
-        throws UnitOfWorkCompletionException, IOException
-    {
-        LOGGER.info( "# Test Creation ##############################################################################" );
-        File attachedFile;
-
-        // Test discarded creation
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            TestedEntity entity = createTestedEntity( uow, "Testing Creation Rollback" );
-            attachedFile = entity.attachedFile();
-        }
-        assertFalse( "File still exists after discarded creation UoW", attachedFile.exists() );
-
-        // Test completed creation
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            TestedEntity entity = createTestedEntity( uow, "Testing Creation" );
-            attachedFile = entity.attachedFile();
-            uow.complete();
-        }
-        assertTrue( "File content was not the good one", isFileFirstLineEqualsTo( attachedFile, "Creation" ) );
-    }
-
-    @Test
-    public void testModification()
-        throws UnitOfWorkCompletionException, IOException
-    {
-        LOGGER.info( "# Test Modification ##########################################################################" );
-        final String entityId;
-        File attachedFile;
-
-        // Create new
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            TestedEntity entity = createTestedEntity( uow, "Testing Modification" );
-            entityId = entity.identity().get();
-            attachedFile = entity.attachedFile();
-            uow.complete();
-        }
-
-        // Testing discarded modification
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            testService.modifyFile( entityId );
-        }
-        assertTrue( "File content after discarded modification was not the good one", isFileFirstLineEqualsTo( attachedFile, "Creation" ) );
-
-        // Testing completed modification
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            testService.modifyFile( entityId );
-            uow.complete();
-        }
-        assertTrue( "Modified file content was not the good one", isFileFirstLineEqualsTo( attachedFile, "Modification" ) );
-    }
-
-    @Test
-    public void testDeletion()
-        throws UnitOfWorkCompletionException, IOException
-    {
-        LOGGER.info( "# Test Deletion ##############################################################################" );
-        final String entityId;
-        File attachedFile;
-
-        // Create new
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            TestedEntity entity = createTestedEntity( uow, "Testing Deletion" );
-            entityId = entity.identity().get();
-            attachedFile = entity.attachedFile();
-            uow.complete();
-        }
-
-        // Testing discarded deletion
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            TestedEntity entity = uow.get( TestedEntity.class, entityId );
-            uow.remove( entity );
-        }
-        assertTrue( "File do not exists after discarded deletion", attachedFile.exists() );
-
-        // Testing completed deletion
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            TestedEntity entity = uow.get( TestedEntity.class, entityId );
-            uow.remove( entity );
-            uow.complete();
-        }
-        assertFalse( "File still exists after deletion", attachedFile.exists() );
-    }
-
-    @Test
-    public void testConcurrentModification()
-        throws IOException, UnitOfWorkCompletionException
-    {
-        LOGGER.info( "# Test Concurrent Modification ###############################################################" );
-        final String entityId;
-
-        // Create new
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            TestedEntity entity = createTestedEntity( uow, "Testing Concurrent Modification" );
-            entityId = entity.identity().get();
-            uow.complete();
-        }
-
-        // Testing concurrent modification
-        UnitOfWork uow, uow2;
-        TestedEntity entity;
-
-        uow = module.newUnitOfWork();
-        entity = uow.get( TestedEntity.class, entityId );
-        Inputs.text( MODIFICATION_CONTENT_URL ).transferTo( Outputs.text( entity.managedFile() ) );
-
-        uow2 = module.newUnitOfWork();
-        entity = uow2.get( TestedEntity.class, entityId );
-        Inputs.text( MODIFICATION_CONTENT_URL ).transferTo( Outputs.text( entity.managedFile() ) );
-
-        uow.complete();
-        try
-        {
-            uow2.complete();
-            fail( "A ConcurrentUoWFileModificationException should have been raised" );
-        }
-        catch( ConcurrentUoWFileModificationException expected )
-        {
-            uow2.discard();
-        }
-    }
-
-    @Test
-    public void testRetry()
-        throws IOException, UnitOfWorkCompletionException, InterruptedException
-    {
-        LOGGER.info( "# Test Retry #################################################################################" );
-        final String entityId;
-        File attachedFile;
-
-        // Create new
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            TestedEntity entity = createTestedEntity( uow, "Testing Concurrent Modification" );
-            entityId = entity.identity().get();
-            attachedFile = entity.attachedFile();
-            uow.complete();
-        }
-
-        final List<Exception> ex = new ArrayList<>();
-        Thread t1 = new Thread( new Runnable()
-        {
-            @Override
-            public void run()
-            {
-                try
-                {
-                    testService.modifyFileWithRetry( entityId, 0, 3000 );
-                }
-                catch( Exception ex1 )
-                {
-                    ex.add( ex1 );
-                }
-            }
-        }, "job1" );
-        Thread t2 = new Thread( new Runnable()
-        {
-            @Override
-            public void run()
-            {
-                try
-                {
-                    testService.modifyFileWithRetry( entityId, 1000, 0 );
-                }
-                catch( Exception ex1 )
-                {
-                    ex.add( ex1 );
-                }
-            }
-        }, "job2" );
-
-        t1.start();
-        t2.start();
-
-        t1.join();
-        t2.join();
-
-        for( Exception eachEx : ex )
-        {
-            eachEx.printStackTrace();
-        }
-
-        assertTrue( "There were errors during TestRetry", ex.isEmpty() );
-        assertTrue( "Modified file content was not the good one", isFileFirstLineEqualsTo( attachedFile, "Modification" ) );
-    }
-
-    private TestedEntity createTestedEntity( UnitOfWork uow, String name )
-        throws IOException
-    {
-        EntityBuilder<TestedEntity> builder = uow.newEntityBuilder( TestedEntity.class );
-        TestedEntity entity = builder.instance();
-        entity.name().set( name );
-        entity = builder.newInstance();
-        Inputs.text( CREATION_CONTENT_URL ).transferTo( Outputs.text( entity.managedFile() ) );
-        return entity;
-    }
-
-}
diff --git a/libraries/uowfile/src/test/java/org/qi4j/library/uowfile/HasUoWFilesTest.java b/libraries/uowfile/src/test/java/org/qi4j/library/uowfile/HasUoWFilesTest.java
deleted file mode 100644
index c330676..0000000
--- a/libraries/uowfile/src/test/java/org/qi4j/library/uowfile/HasUoWFilesTest.java
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * Copyright 2011-2014 Paul Merlin.
- *
- * Licensed  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.qi4j.library.uowfile;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.unitofwork.concern.UnitOfWorkConcern;
-import org.qi4j.api.unitofwork.concern.UnitOfWorkPropagation;
-import org.qi4j.api.unitofwork.concern.UnitOfWorkRetry;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.io.Inputs;
-import org.qi4j.io.Outputs;
-import org.qi4j.library.fileconfig.FileConfigurationAssembler;
-import org.qi4j.library.uowfile.bootstrap.UoWFileAssembler;
-import org.qi4j.library.uowfile.internal.ConcurrentUoWFileModificationException;
-import org.qi4j.library.uowfile.plural.HasUoWFilesLifecycle;
-import org.qi4j.library.uowfile.plural.UoWFilesLocator;
-import org.qi4j.test.EntityTestAssembler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-public class HasUoWFilesTest
-    extends AbstractUoWFileTest
-{
-    private static final Logger LOGGER = LoggerFactory.getLogger( HasUoWFilesTest.class );
-    private static final URL CREATION_CONTENT_URL = HasUoWFilesTest.class.getResource( "creation.txt" );
-    private static final URL MODIFICATION_CONTENT_URL = HasUoWFilesTest.class.getResource( "modification.txt" );
-
-    // START SNIPPET: uowfile
-    public enum MyEnum
-    {
-        fileOne, fileTwo
-    }
-
-    // START SNIPPET: entity
-    public interface TestedEntity
-        extends HasUoWFilesLifecycle<MyEnum> // END SNIPPET: entity
-        , Identity
-    // START SNIPPET: entity
-    {
-        Property<String> name();
-    }
-    // END SNIPPET: entity
-    // END SNIPPET: uowfile
-
-    // START SNIPPET: locator
-    public static abstract class TestedFilesLocatorMixin
-        implements UoWFilesLocator<MyEnum>
-    {
-        @This
-        private Identity meAsIdentity;
-
-        @Override
-        public Iterable<File> locateAttachedFiles()
-        {
-            List<File> list = new ArrayList<>();
-            for( MyEnum eachValue : MyEnum.values() )
-            {
-                list.add( new File( baseTestDir, meAsIdentity.identity().get() + "." + eachValue.name() ) );
-            }
-            return list;
-        }
-
-        @Override
-        public File locateAttachedFile( MyEnum key )
-        {
-            return new File( baseTestDir, meAsIdentity.identity().get() + "." + key.name() );
-        }
-    }
-    // END SNIPPET: locator
-
-    @Mixins( TestServiceMixin.class )
-    @Concerns( UnitOfWorkConcern.class )
-    public interface TestService
-    {
-        void modifyFile( String entityId )
-            throws IOException;
-
-        @UnitOfWorkPropagation
-        @UnitOfWorkRetry
-        void modifyFileWithRetry( String entityId, long sleepBefore, long sleepAfter )
-            throws IOException;
-    }
-
-    public static class TestServiceMixin
-        implements TestService
-    {
-        @Structure
-        private Module module;
-
-        @Override
-        public void modifyFile( String entityId )
-            throws IOException
-        {
-            modifyFileImmediatly( entityId );
-        }
-
-        @Override
-        public void modifyFileWithRetry( String entityId, long sleepBefore, long sleepAfter )
-            throws IOException
-        {
-            LOGGER.info( "Waiting " + sleepBefore + "ms before file modification" );
-            if( sleepBefore > 0 )
-            {
-                try
-                {
-                    Thread.sleep( sleepBefore );
-                }
-                catch( InterruptedException ex )
-                {
-                    throw new RuntimeException( ex );
-                }
-            }
-            modifyFileImmediatly( entityId );
-            LOGGER.info( "Waiting " + sleepAfter + "ms after file modification" );
-            if( sleepAfter > 0 )
-            {
-                try
-                {
-                    Thread.sleep( sleepAfter );
-                }
-                catch( InterruptedException ex )
-                {
-                    throw new RuntimeException( ex );
-                }
-            }
-        }
-
-        private void modifyFileImmediatly( String entityId )
-            throws IOException
-        {
-            TestedEntity entity = module.currentUnitOfWork().get( TestedEntity.class, entityId );
-            // START SNIPPET: api
-            File attachedFileTwo = entity.attachedFile( MyEnum.fileTwo );
-            File managedFileOne = entity.managedFile( MyEnum.fileOne );
-            // END SNIPPET: api
-            Inputs.text( MODIFICATION_CONTENT_URL ).transferTo( Outputs.text( managedFileOne ) );
-        }
-    }
-
-    @Override
-    // START SNIPPET: assembly
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        new UoWFileAssembler().assemble( module );
-
-        module.entities( TestedEntity.class ).withMixins( TestedFilesLocatorMixin.class );
-        // END SNIPPET: assembly
-        module.services( TestService.class );
-        new EntityTestAssembler().assemble( module );
-        new FileConfigurationAssembler().assemble( module );
-        // START SNIPPET: assembly
-    }
-    // END SNIPPET: assembly
-
-    private TestService testService;
-
-    @Before
-    public void beforeTest()
-    {
-        testService = module.<TestService>findService( TestService.class ).get();
-    }
-
-    @Test
-    public void testCreation()
-        throws UnitOfWorkCompletionException, IOException
-    {
-        LOGGER.info( "# Test Creation ##############################################################################" );
-        File attachedFile;
-
-        // Test discarded creation
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            TestedEntity entity = createTestedOneEntityTwoFilesEntity( uow, "Testing Creation Rollback" );
-            attachedFile = entity.attachedFile( MyEnum.fileOne );
-        }
-        assertFalse( "File still exists after discarded creation UoW", attachedFile.exists() );
-
-        // Test completed creation
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            TestedEntity entity = createTestedOneEntityTwoFilesEntity( uow, "Testing Creation" );
-            attachedFile = entity.attachedFile( MyEnum.fileOne );
-            uow.complete();
-        }
-        assertTrue( "File content was not the good one", isFileFirstLineEqualsTo( attachedFile, "Creation" ) );
-    }
-
-    @Test
-    public void testModification()
-        throws UnitOfWorkCompletionException, IOException
-    {
-        LOGGER.info( "# Test Modification ##########################################################################" );
-        final String entityId;
-        File attachedFile;
-
-        // Create new
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            TestedEntity entity = createTestedOneEntityTwoFilesEntity( uow, "Testing Modification" );
-            entityId = entity.identity().get();
-            attachedFile = entity.attachedFile( MyEnum.fileOne );
-            uow.complete();
-        }
-
-        // Testing discarded modification
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            testService.modifyFile( entityId );
-        }
-        assertTrue( "File content after discarded modification was not the good one", isFileFirstLineEqualsTo( attachedFile, "Creation" ) );
-
-        // Testing completed modification
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            testService.modifyFile( entityId );
-            uow.complete();
-        }
-        assertTrue( "Modified file content was not the good one", isFileFirstLineEqualsTo( attachedFile, "Modification" ) );
-    }
-
-    @Test
-    public void testDeletion()
-        throws UnitOfWorkCompletionException, IOException
-    {
-        LOGGER.info( "# Test Deletion ##############################################################################" );
-        final String entityId;
-        File attachedFile;
-
-        // Create new
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            TestedEntity entity = createTestedOneEntityTwoFilesEntity( uow, "Testing Deletion" );
-            entityId = entity.identity().get();
-            attachedFile = entity.attachedFile( MyEnum.fileOne );
-            uow.complete();
-        }
-
-        // Testing discarded deletion
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            TestedEntity entity = uow.get( TestedEntity.class, entityId );
-            uow.remove( entity );
-        }
-        assertTrue( "File do not exists after discarded deletion", attachedFile.exists() );
-
-        // Testing completed deletion
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            TestedEntity entity = uow.get( TestedEntity.class, entityId );
-            uow.remove( entity );
-            uow.complete();
-        }
-        assertFalse( "File still exists after deletion", attachedFile.exists() );
-    }
-
-    @Test
-    public void testConcurrentModification()
-        throws IOException, UnitOfWorkCompletionException
-    {
-        LOGGER.info( "# Test Concurrent Modification ###############################################################" );
-        final String entityId;
-
-        // Create new
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            TestedEntity entity = createTestedOneEntityTwoFilesEntity( uow, "Testing Concurrent Modification" );
-            entityId = entity.identity().get();
-            uow.complete();
-        }
-
-        // Testing concurrent modification
-        UnitOfWork uow, uow2;
-        TestedEntity entity;
-
-        uow = module.newUnitOfWork();
-        entity = uow.get( TestedEntity.class, entityId );
-        Inputs.text( MODIFICATION_CONTENT_URL ).transferTo( Outputs.text( entity.managedFile( MyEnum.fileOne ) ) );
-
-        uow2 = module.newUnitOfWork();
-        entity = uow2.get( TestedEntity.class, entityId );
-        Inputs.text( MODIFICATION_CONTENT_URL ).transferTo( Outputs.text( entity.managedFile( MyEnum.fileOne ) ) );
-
-        uow.complete();
-        try
-        {
-            uow2.complete();
-            fail( "A ConcurrentUoWFileModificationException should have been raised" );
-        }
-        catch( ConcurrentUoWFileModificationException expected )
-        {
-            uow2.discard();
-        }
-    }
-
-    @Test
-    public void testRetry()
-        throws IOException, UnitOfWorkCompletionException, InterruptedException
-    {
-        LOGGER.info( "# Test Retry #################################################################################" );
-        final String entityId;
-        File attachedFile;
-
-        // Create new
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            TestedEntity entity = createTestedOneEntityTwoFilesEntity( uow, "Testing Concurrent Modification" );
-            entityId = entity.identity().get();
-            attachedFile = entity.attachedFile( MyEnum.fileOne );
-            uow.complete();
-        }
-
-        final List<Exception> ex = new ArrayList<>();
-        Thread t1 = new Thread( new Runnable()
-        {
-            @Override
-            public void run()
-            {
-                try
-                {
-                    testService.modifyFileWithRetry( entityId, 0, 10000 );
-                }
-                catch( Exception ex1 )
-                {
-                    ex.add( ex1 );
-                }
-            }
-        }, "job1" );
-        Thread t2 = new Thread( new Runnable()
-        {
-            @Override
-            public void run()
-            {
-                try
-                {
-                    testService.modifyFileWithRetry( entityId, 5000, 0 );
-                }
-                catch( Exception ex1 )
-                {
-                    ex.add( ex1 );
-                }
-            }
-        }, "job2" );
-
-        t1.start();
-        t2.start();
-
-        t1.join();
-        t2.join();
-
-        for( Exception eachEx : ex )
-        {
-            eachEx.printStackTrace();
-        }
-
-        assertTrue( "There were errors during TestRetry", ex.isEmpty() );
-        assertTrue( "Modified file content was not the good one", isFileFirstLineEqualsTo( attachedFile, "Modification" ) );
-    }
-
-    private TestedEntity createTestedOneEntityTwoFilesEntity( UnitOfWork uow, String name )
-        throws IOException
-    {
-        EntityBuilder<TestedEntity> builder = uow.newEntityBuilder( TestedEntity.class );
-        TestedEntity entity = builder.instance();
-        entity.name().set( name );
-        entity = builder.newInstance();
-        Inputs.text( CREATION_CONTENT_URL ).transferTo( Outputs.text( entity.managedFile( MyEnum.fileOne ) ) );
-        return entity;
-    }
-
-}
diff --git a/libraries/uowfile/src/test/resources/org/qi4j/library/uowfile/creation.txt b/libraries/uowfile/src/test/resources/org/apache/polygene/library/uowfile/creation.txt
similarity index 100%
rename from libraries/uowfile/src/test/resources/org/qi4j/library/uowfile/creation.txt
rename to libraries/uowfile/src/test/resources/org/apache/polygene/library/uowfile/creation.txt
diff --git a/libraries/uowfile/src/test/resources/org/qi4j/library/uowfile/modification.txt b/libraries/uowfile/src/test/resources/org/apache/polygene/library/uowfile/modification.txt
similarity index 100%
rename from libraries/uowfile/src/test/resources/org/qi4j/library/uowfile/modification.txt
rename to libraries/uowfile/src/test/resources/org/apache/polygene/library/uowfile/modification.txt
diff --git a/manual/build.gradle b/manual/build.gradle
index c754880..2511096 100644
--- a/manual/build.gradle
+++ b/manual/build.gradle
@@ -1,96 +1,30 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
  */
 
-description = "Apache Zest™ Manuals and Website."
+apply plugin: 'polygene-manual'
+
+description = "Apache Polygene™ Manuals and Website."
 
 dependencies {
-  compile( project( ":org.qi4j.core:org.qi4j.core.bootstrap" ) )
-  compile( project( ":org.qi4j.libraries:org.qi4j.library.constraints" ) )
-  compile( project( ":org.qi4j.libraries:org.qi4j.library.logging" ) )
-  runtime( project( ":org.qi4j.core:org.qi4j.core.runtime" ) )
-  runtime( libraries.slf4j_simple )
-}
+  implementation polygene.core.bootstrap
+  implementation polygene.library( 'constraints' )
+  implementation polygene.library( 'logging' )
 
-
-//task userguide( type: org.qi4j.gradle.plugin.documentation.Documentation ) {
-//  docName = 'userguide'
-//  docType = 'book'
-//}
-//
-//task recipes( type: org.qi4j.gradle.plugin.documentation.Documentation ) {
-//  docName = 'recipes'
-//  docType = 'article'
-//}
-//
-//task referenceManual( type: org.qi4j.gradle.plugin.documentation.Documentation ) {
-//  docName = 'reference'
-//  docType = 'book'
-//}
-
-
-task website( type: org.qi4j.gradle.plugin.Documentation,
-              dependsOn: rootProject.allprojects.tasks.flatten().findAll { it.name == AsciidocBuildInfo.TASK_NAME } ) {
-  docName 'website'
-  docType 'article'
-}
-
-task archiveWebsite( type: Copy ) {
-  dependsOn website
-  if( rootProject.version == '0' || rootProject.version.contains( "SNAPSHOT" ) )
-  {
-    into( "$rootProject.projectDir/../zest-web/site/content/java/develop" )
-  }
-  else
-  {
-    into( "$rootProject.projectDir/../zest-web/site/content/java/$version" )
-  }
-  from( 'build/docs/website/' )
-}
-
-task copyWebsite( type: Copy ) {
-  dependsOn archiveWebsite
-  if( rootProject.version != '0' && !rootProject.version.contains( "SNAPSHOT" ) )
-  {
-    from( "$rootProject.projectDir/../zest-web/site/content/java/$version/" )
-    into( "$rootProject.projectDir/../zest-web/site/content/java/latest/" )
-  }
-}
-
-task manuals() {
-  dependsOn copyWebsite
-//  dependsOn userguide
-//  dependsOn referenceManual
-//  dependsOn recipes
-}
-
-// Skip if asciidoc is not found in PATH when building a 0 or SNAPSHOT version,
-// or if skipAsciidocIfAbsent property is set and asciidoc is not found in PATH
-[ website, archiveWebsite, copyWebsite, manuals ]*.onlyIf {
-  def skipAsciidocIfAbsent = rootProject.hasProperty( 'skipAsciidocIfAbsent' ) ? rootProject.skipAsciidocIfAbsent : false
-  def pathDirs = System.getenv( 'PATH' ).split( File.pathSeparator )
-  def present = pathDirs.collect( { new File( it, 'asciidoc') } ).flatten().findAll( { it.isFile() } )
-  if( !skipAsciidocIfAbsent && version != '0' && !version.contains( 'SNAPSHOT' ) ) {
-    project.logger.debug 'Asciidoc tasks forced because version is no-0 and no-SNAPSHOT, hope you have Asciidoc installed'
-    return true
-  }
-  if( !present ) {
-    project.logger.warn 'Asciidoc not found in PATH, manual tasks will skip, please install http://www.methods.co.nz/asciidoc/'
-  }
-  present
+  runtimeOnly polygene.core.runtime
+  runtimeOnly libraries.logback
 }
diff --git a/manual/src/docs/reference/docinfo.xml b/manual/src/docs/reference/docinfo.xml
index 28df1f5..90a79ae 100644
--- a/manual/src/docs/reference/docinfo.xml
+++ b/manual/src/docs/reference/docinfo.xml
@@ -1,27 +1,30 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <authorgroup>
-  <corpauthor>The Zest™ Community
+  <corpauthor>The Polygene™ Community
   </corpauthor>
 </authorgroup>
 
 <copyright>
 <year>2011</year>
-<holder>Zest™ Community</holder>
+<holder>Polygene™ Community</holder>
 </copyright>
 
 <legalnotice>
diff --git a/manual/src/docs/reference/index.txt b/manual/src/docs/reference/index.txt
index 0b2d397..04963d8 100644
--- a/manual/src/docs/reference/index.txt
+++ b/manual/src/docs/reference/index.txt
@@ -18,11 +18,11 @@
 ///////////////////////////////////////////////////////////////
 
 [[reference-documentation,Reference Manual]]
-= Apache Zest™ v{revnumber} Reference Manual =
+= Apache Polygene™ v{revnumber} Reference Manual =
 
-:qi4j-version: {revnumber}
-:qi4j-buildnumber: {revnumber}
-:qi4j-git-tag: {gitversion}
+:polygene-version: {revnumber}
+:polygene-buildnumber: {revnumber}
+:polygene-git-tag: {gitversion}
 
 
 :leveloffset: 2
diff --git a/manual/src/docs/tutorials/docinfo.xml b/manual/src/docs/tutorials/docinfo.xml
index 7c3ae97..6467343 100644
--- a/manual/src/docs/tutorials/docinfo.xml
+++ b/manual/src/docs/tutorials/docinfo.xml
@@ -1,27 +1,30 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <authorgroup>
-  <corpauthor>The Zest™ Community
+  <corpauthor>The Polygene™ Community
   </corpauthor>
 </authorgroup>
 
 <copyright>
   <year>2011</year>
-  <holder>Zest™ Community</holder>
+  <holder>Polygene™ Community</holder>
 </copyright>
 
 <legalnotice>
diff --git a/manual/src/docs/tutorials/howto-assembly-application.txt b/manual/src/docs/tutorials/howto-assembly-application.txt
index 05e2ad7..200f662 100644
--- a/manual/src/docs/tutorials/howto-assembly-application.txt
+++ b/manual/src/docs/tutorials/howto-assembly-application.txt
@@ -1,16 +1,19 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
+ * 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
  *
- * Licensed 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.
+ *     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.
 //////////////////////
 
 [[howto-assemble-application,Assemble an Application]]
@@ -23,13 +26,13 @@
 
 include::../../../../core/bootstrap/build/docs/buildinfo/artifact.txt[]
 
-At runtime you will need the Core Runtime artifact too. See the <<howto-depend-on-zest>> tutorial for details.
+At runtime you will need the Core Runtime artifact too. See the <<howto-depend-on-polygene>> tutorial for details.
 
 == Basics ==
 
-First let's recap the structural requirements of Zest;
+First let's recap the structural requirements of Polygene;
 
-    * There is one and only one Application instance per Zest™ Runtime.
+    * There is one and only one Application instance per Polygene™ Runtime.
     * Every Application must contain one or more Layers.
     * All Composites must be declared in one or more Modules.
     * Each Module belong to a Layer.
@@ -40,7 +43,7 @@
 
 == Application ==
 
-The first one means that for each Zest™ Runtime you start, there will be exactly one application. As far as we know, Zest
+The first one means that for each Polygene™ Runtime you start, there will be exactly one application. As far as we know, Polygene
 is fully isolated, meaning there are no static members being populated and such.
 
 == Layers ==
@@ -49,7 +52,7 @@
 whiteboards (or even black boards for those old enough), and sometimes organized the codebases along such boundaries.
 But, there has been little effort to enforce the Layer mechanism in code, although it is an extremely powerful
 construct. First of all it implies directional dependency and a high degree of order, spagetti code is reduced if
-successfully implemented. For Zest, it means that we can restrict access to Composite and Object declarations, so that
+successfully implemented. For Polygene, it means that we can restrict access to Composite and Object declarations, so that
 higher layers can not reach them incidentally. You can enforce architecture to a high degree. You can require all
 creation of composites to go through an exposed Factory, which doesn't require the Composite to be public. And so on.
 Layers have hierarchy, i.e. one layer is top of one or more layers, and is below one or more layers, except for the
@@ -58,7 +61,7 @@
 
 == Modules ==
 
-The Module concept has also been around forever. And in Zest™ we also makes the Modules explicit. Each Module belong to a
+The Module concept has also been around forever. And in Polygene™ we also makes the Modules explicit. Each Module belong to a
 Layer, and for each Module you declare the Composite and Object types for that Module, together with a Visibility rule,
 one of; application, layer, module.
 
@@ -70,7 +73,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/assemble/Docs.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/assemble/Docs.java
 tag=direct
 -----------
 
@@ -78,7 +81,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/assemble/Docs.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/assemble/Docs.java
 tag=indirect
 -----------
 
@@ -109,7 +112,7 @@
 How to structure your code is beyond the scope of this section. If you are an experienced designer, you will have done
 that before, and you may have started out with good intentions at times only to find yourself in a spaghetti swamp
 later, or perhaps in the also famous "Clear as Clay" or "Ball (bowl?) of Mud". Either way, you need to draw on your
-experience and come up with good structure that Zest™ lets you enforce.
+experience and come up with good structure that Polygene™ lets you enforce.
 
 So, for the sake of education, we are going to look at an application that consists of many layers, each with a few
 modules. See picture below.
@@ -122,12 +125,12 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/assemble/Main.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/assemble/Main.java
 tag=main
 -----------
 
 The above is the basic setup on how to structure a real-world applicaton, unless you intend to mess with the
-implementations of various Zest™ systems (yes there are hooks for that too), but that is definitely beyond the scope of
+implementations of various Polygene™ systems (yes there are hooks for that too), but that is definitely beyond the scope of
 this tutorial.
 
 Now, the createXyzLayer() methods were excluded to keep the sample crisp and easy to follow. Let's take a look at what
@@ -135,7 +138,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/assemble/Main.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/assemble/Main.java
 tag=domainLayer
 -----------
 
@@ -145,7 +148,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/assemble/Main.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/assemble/Main.java
 tag=accountModule
 -----------
 
@@ -154,9 +157,9 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/assemble/Main.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/assemble/Main.java
 tag=shutdown
 -----------
 
-This concludes this tutorial. We have looked how to get the initial Zest™ runtime going, how to declare the assembly
+This concludes this tutorial. We have looked how to get the initial Polygene™ runtime going, how to declare the assembly
 for application model creation and finally the activation of the model itself.
diff --git a/manual/src/docs/tutorials/howto-build-system.txt b/manual/src/docs/tutorials/howto-build-system.txt
index ab2d3fa..45c8b10 100644
--- a/manual/src/docs/tutorials/howto-build-system.txt
+++ b/manual/src/docs/tutorials/howto-build-system.txt
@@ -18,98 +18,120 @@
 ///////////////////////////////////////////////////////////////
 
 [[build-system,Build System]]
-= Zest™ Build System =
+= Polygene™ Build System =
 
-This tutorial is intended for developpers who want to build the Zest™ SDK themselves.
-It describe the Zest™ SDK Build System from compilation to publication of artifacts for consumption by other
+This tutorial is intended for developers who want to build the Polygene™ SDK themselves.
+It describe the Polygene™ SDK Build System from compilation to publication of artifacts for consumption by other
 applications.
 
-If instead you want to setup your project build system to depend on modules of the Zest™ SDK see the
-<<howto-depend-on-zest,dedicated tutorial>>.
+If instead you want to setup your project build system to depend on modules of the Polygene™ SDK see the
+<<howto-depend-on-polygene,dedicated tutorial>>.
 
 
 == Gradle ==
 
 NOTE: All major Java IDEs have great Gradle support.
-Visit the http://www.gradle.org/tooling[Gradle Tooling] page to learn how to import the Zest™ SDK build into your
+Visit the https://www.gradle.org/resources[Gradle] website to learn how to import the Polygene™ SDK build into your
 favorite IDE.
 
-Zest™ community migrated away from Maven after several years of frustration, especially around release management,
+Polygene™ community migrated away from Maven after several years of frustration, especially around release management,
 versioning and cross-module dependency resolution issues, in Feb 2011.
 The tool of choice is now Gradle, and it doesn't require any installation, there are +gradlew+ and +gradlew.bat+ in
-the root folder of the Zest™ SDK that will bootstrap Gradle if not done so already.
+the root folder of the Polygene™ SDK that will bootstrap Gradle if not done so already.
 
-If you are new to Gradle, you should keep the http://www.gradle.org/documentation[documentation] at hands.
+If you are new to Gradle, you should keep the https://gradle.org/docs[documentation] at hands.
 
 Build System configuration is done through Gradle properties.
 This can be done in many ways, see
-http://gradle.org/docs/current/userguide/tutorial_this_and_that.html#sec:gradle_properties_and_system_properties[Gradle properties and system properties].
+https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_properties_and_system_properties[Gradle properties and system properties].
 
+== The Wrapper ==
 
-== Root project tasks ==
+`gradlew` and `gradlew.bat` scripts that can be found at the root of the Polygene sources is *The Wrapper*.
+Any build invocation starts from this script.
+It will download the Gradle distribution version required by the build.
+See the https://docs.gradle.org/current/userguide/gradle_wrapper.html[Gradle Wrapper] documentation for more details.
 
-The Zest™ SDK root project has tasks that work with the whole SDK.
-The default build, triggered when running gradle without any command line arguments, compiles the code and run the
-tests, but nothing else.
-A quick way to check that nothing broke.
+== Main tasks ==
 
-Here are some of theses global tasks we defined:
+The Polygene™ SDK project has tasks that work with the whole SDK.
 
-goOffline::
-+
+`./gradlew downloadDependencies`::
 --
 Resolve, download and cache all needed dependencies.
 Useful to go offline.
 --
 
-clean::
-+
+`./gradlew`::
+--
+The default build, triggered when running gradle without any command line arguments, compiles the code and run the
+tests, but nothing else. A quick way to check that nothing broke.
+--
+
+`./gradlew clean`::
 --
 Clean up of all build output and restore the code base to a fresh state.
 --
 
-check::
-+
+`./gradlew assemble`::
 --
-Run the tests and other checks like checkstyle.
-Reports are generated in +build/reports+.
+Produces all the archives, javadocs, manuals and website content.
+Global output is generated into +distributions/build+.
 --
 
-install::
-+
+`./gradlew check`::
+--
+Run the tests and other checks like checkstyle.
+Global reports are generated in +reports/build/reports+.
+--
+
+`./gradlew build`::
+--
+Equivalent to `./gradlew assemble check`
+--
+
+`./gradlew checkDistributions`::
+--
+Run global checks against the assembled distributions.
+Can take a while.
+--
+
+`./gradlew install`::
 --
 Is roughly the same as Maven's install goal.
 It produces the test reports, javadocs and installs all the Jars into the local disk repository, for consumption
 by other applications.
 --
 
-buildAll::
-+
---
-Produces all the archives, javadocs, manuals and website content.
-The output is generated to +build+.
---
 
-release::
-+
---
-Uploads the release artifacts to the distribution servers and creates the release output into the
-+build/distributions+ directory.
---
-
-
-== Submodules tasks ==
+== Other tasks ==
 
 In addition to that, some submodules have specific tasks.
-To see all available tasks on a submodule issue the following command:
+To see all available tasks, issue the following command:
 
 [source,bash]
 ----
-./gradlew -p tests/performance tasks
+./gradlew tasks
 ----
 
-This example will output all gradle tasks available in the +tests/performance+ module where you should find
-the +testPerf+ task that run the Zest™ performance test suite.
+All available tasks from all modules of the SDK are shown.
+If you want to narrow your exploration to submodules use the following:
+
+[source,bash]
+----
+./gradlew :test:performance:tasks
+./gradlew :release:tasks
+----
+
+These examples will respectively output all gradle tasks available in the +:tests:performance+ module where you should find
+the +performanceTest+ task that runs the Polygene™ performance test suite and the +:release+ module tasks.
+
++tasks+ itself is a task, in the same way we can target module(s) with tasks, e.g.:
+
+[source,bash]
+----
+./gradlew :core:check :libraries:alarm:check
+----
 
 
 == Versions ==
@@ -127,11 +149,12 @@
 -----------
 
 If a +version+ property is not defined, the build system will refuse to make a release and upload.
+It will also try hard to do less and not get in your way.
 
 
 == Tests ==
 
-NOTE: See the https://builds.apache.org/view/S-Z/view/Zest/[Zest™ Continuous Integration] for current tests results
+NOTE: See the https://builds.apache.org/view/P/view/Polygene/[Polygene™ Continuous Integration] for current tests results
 
 Unit and integration tests are located near the code under test.
 You'll find theses tests across the whole SDK.
@@ -139,33 +162,44 @@
 === Unit tests requiring external services ===
 
 Among unit tests, some require an external service to be run.
-For example, the MongoDB EntityStore extension requires an actual MongoDB server to run its tests.
+For example, the Redis EntityStore extension requires an actual Redis server to run its tests.
 
-NOTE: The HTML test reports generated by Gradle show skipped tests.
+NOTE: The HTML test reports generated by Gradle shows skipped tests.
 
-All thoses tests should be part of the default build and check if the service is available at its default location
-on +localhost+ and skip if not.
-This is easily achieved using http://junit.sourceforge.net/javadoc/org/junit/Assume.html[JUnit assumptions].
+Testing against external services is automated using Docker and is enabled automatically if a running Docker service
+is reachable.
+The build creates the necessary Docker images and start/stop containers around the tests.
 
-We'll list here services that the unit tests will use if available.
+On Linux it should work out of the box.
 
-- Memcached, ASCII protocol, no authentication on +localhost:4444+ for +extensions/cache-memcache+
-- MongoDB without authentication on +localhost:27017+ for +extensions/entitystore-mongodb+
-- Riak without authentication on +localhost:4444+ for +extensions/entitystore-riak+
-- Redis without authentication on +localhost:4444+ for +extensions/entitystore-redis+
-- PostgreSQL for +extensions/entitystore-sql+ and +extensions/indexing-sql+ (need setup, see test source)
-- MySQL for +extensions/entitystore-sql+ (need setup, see test source)
+The simplest way to get this running on other systems (macOS and Windows) is to use `docker-machine` to create a
+development Docker virtual machine where all images will be built and containers started:
+
+[source,bash]
+----
+docker-machine create dev
+docker-machine start dev
+eval $(docker-machine env dev)
+----
+
+The last stanza set environment variables for Docker to use the newly created Docker virtual machine.
+
+If you want to run the Docker containers in a remote machine, simply set the `DOCKER_HOST` and `DOCKER_CERT_PATH`
+environment variables to something sensible for your setup.
+
+If you want to forcibly skip all Docker related work, set the `skipDocker` Gradle property by e.g. appending
+`-PskipDocker` to your Gradle command line.
 
 === Performance tests ===
 
-Performance tests provide performance mesurements for typical Zest™ use cases.
+Performance tests provide performance measurements for typical Polygene™ use cases.
 They are not part of the default build and are located in the `tests/performance` directory of the SDK.
 
 They can be run with the following Gradle command:
 
 [source,bash]
 -----------
-./gradlew :org.qi4j.tests:org.qi4j.test.performance:testPerf
+./gradlew :tests:performance:performanceTest
 -----------
 
 Results will then be available in the test reports.
@@ -177,7 +211,7 @@
 
 [source,bash]
 -----------
-./gradlew -p manual website
+./gradlew :manual:assemble
 -----------
 
 Output is in `~/manual/build/docs/website`.
@@ -190,8 +224,8 @@
 
 IMPORTANT: Remember that if a +version+ property is not defined, the build system will refuse to make a release and upload.
 
-The Zest™ SDK build system is setup for an easy release process.
-This is very useful to the Zest™ Core Team but can also be useful to third parties that want to cut a in-house release.
+The Polygene™ SDK build system is setup for an easy release process.
+This is very useful to the Polygene™ Core Team but can also be useful to third parties that want to cut a in-house release.
 In this regard, we try to make every aspect of the release process usable for such cases.
 
 The following sections describe various aspects of the release process.
@@ -200,12 +234,12 @@
 
 === Release Criteria ===
 
-The Zest™ SDK modules are of varying maturity level and we try to maintain a STATUS (+dev-status.xml+) file indicating
+The Polygene™ SDK modules are of varying maturity level and we try to maintain a STATUS (+dev-status.xml+) file indicating
 how good the codebase, documentation and unit tests are for each of the modules. This is highly subjective and
 potentially different individuals will judge this differently, but at least it gives a ballpark idea of the situation
 for our users.
 
-The Zest™ SDK build system use the values from the +dev-status.xml+ files to filter out non-releasable modules out for
+The Polygene™ SDK build system use the values from the +dev-status.xml+ files to filter out non-releasable modules out for
 the +javadocs+ and +uploadArchives+ root project tasks.
 Moreover, the +release+ task ensure that no releasable module depends on module(s) that don't fit the release criteria
 and throw a detailed exception if need be.
@@ -260,7 +294,5 @@
 ./gradlew uploadArchives -Dversion=3.2.1 -PuploadRepository=file:///path/to/local/repository
 -----------
 
-See the http://www.gradle.org/docs/current/userguide/maven_plugin.html#wagonLibs[Gradle documentation] about
+See the https://docs.gradle.org/current/userguide/maven_plugin.html#wagonLibs[Gradle documentation] about
 supported protocols.
-
-
diff --git a/manual/src/docs/tutorials/howto-configure-service.txt b/manual/src/docs/tutorials/howto-configure-service.txt
index 86751b5..02dc0a6 100644
--- a/manual/src/docs/tutorials/howto-configure-service.txt
+++ b/manual/src/docs/tutorials/howto-configure-service.txt
@@ -1,31 +1,34 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
+ * 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
  *
- * Licensed 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.
+ *     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.
 //////////////////////
 
 [[howto-configure-service,Configure a Service]]
 = Configure a Service =
-Zest™ supports a Configuration system for services. The configuration instance itself is an Entity and is therefor
+Polygene™ supports a Configuration system for services. The configuration instance itself is an Entity and is therefor
 readable, writeable and queryable, just like other Entities. This should make Configuration management much simpler,
 since you can easily build GUI tools to allow editing of these in runtime. However, to simplify the initial values of
-the Configuration instance, Zest™ also does the initial bootstrapping of the Configuration entity for you. This HowTo is
+the Configuration instance, Polygene™ also does the initial bootstrapping of the Configuration entity for you. This HowTo is
 going to show how.
 
 If you want to reproduce what's explained in this tutorial, remember to depend on the Core Bootstrap artifact:
 
 include::../../../../core/bootstrap/build/docs/buildinfo/artifact.txt[]
 
-At runtime you will need the Core Runtime artifact too. See the <<howto-depend-on-zest>> tutorial for details.
+At runtime you will need the Core Runtime artifact too. See the <<howto-depend-on-polygene>> tutorial for details.
 
 == We need a Service ==
 
@@ -34,7 +37,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/travel/TravelPlan.java
+source=manual/src/main/java/org/apache/polygene/manual/travel/TravelPlan.java
 tag=service
 -----------
 
@@ -42,7 +45,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/travel/TravelPlanService.java
+source=manual/src/main/java/org/apache/polygene/manual/travel/TravelPlanService.java
 tag=serviceComposite
 -----------
 
@@ -52,7 +55,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/travel/TravelPlanConfiguration.java
+source=manual/src/main/java/org/apache/polygene/manual/travel/TravelPlanConfiguration.java
 tag=configuration
 -----------
 
@@ -63,7 +66,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/travel/TravelPlanMixin.java
+source=manual/src/main/java/org/apache/polygene/manual/travel/TravelPlanMixin.java
 tag=mixin
 -----------
 
@@ -74,7 +77,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/travel/TravelPlanMixin.java
+source=manual/src/main/java/org/apache/polygene/manual/travel/TravelPlanMixin.java
 tag=refresh
 -----------
 
@@ -95,7 +98,7 @@
 
 [snippet,bash]
 -----------
-source=manual/src/main/java/org/qi4j/manual/travel/TravelPlanService.properties
+source=manual/src/main/java/org/apache/polygene/manual/travel/TravelPlanService.properties
 tag=params
 -----------
 File: org/hedhman/niclas/travel/TravelPlanService.properties
@@ -106,7 +109,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/travel/Main.java
+source=manual/src/main/java/org/apache/polygene/manual/travel/Main.java
 tag=simple
 -----------
 
@@ -117,7 +120,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/travel/Main.java
+source=manual/src/main/java/org/apache/polygene/manual/travel/Main.java
 tag=assemble
 -----------
 
@@ -125,21 +128,21 @@
 
 [snippet,bash]
 -----------
-source=manual/src/main/java/org/qi4j/manual/travel/ExpediaService.properties
+source=manual/src/main/java/org/apache/polygene/manual/travel/ExpediaService.properties
 tag=params
 -----------
-File: org/qi4j/manual/travel/ExpediaService.properties
+File: org/apache/polygene/manual/travel/ExpediaService.properties
 
 
 [snippet,bash]
 -----------
-source=manual/src/main/java/org/qi4j/manual/travel/OrbitzService.properties
+source=manual/src/main/java/org/apache/polygene/manual/travel/OrbitzService.properties
 tag=params
 -----------
-File: org/qi4j/manual/travel/OrbitzService.properties
+File: org/apache/polygene/manual/travel/OrbitzService.properties
 
 == Changing Configuration in runtime ==
-Unlike most frameworks, the Configuration in Zest™ is an active Entity, and once the properties file has been read once
+Unlike most frameworks, the Configuration in Polygene™ is an active Entity, and once the properties file has been read once
 at the first(!) startup, it no longer serves any purpose. The Configuration will always be retrieved from the
 EntityStore. Changes to the properties file are not taken into consideration if the Configuration entity is found in the
 entity store.
diff --git a/manual/src/docs/tutorials/howto-contextual-fragments.txt b/manual/src/docs/tutorials/howto-contextual-fragments.txt
index 1dc423c..d42152a 100644
--- a/manual/src/docs/tutorials/howto-contextual-fragments.txt
+++ b/manual/src/docs/tutorials/howto-contextual-fragments.txt
@@ -1,16 +1,19 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
+ * 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
  *
- * Licensed 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.
+ *     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.
 //////////////////////
 
 [[howto-contextual-fragments,Use Contextual Fragments]]
@@ -29,13 +32,13 @@
 
 include::../../../../core/bootstrap/build/docs/buildinfo/artifact.txt[]
 
-At runtime you will need the Core Runtime artifact too. See the <<howto-depend-on-zest>> tutorial for details.
+At runtime you will need the Core Runtime artifact too. See the <<howto-depend-on-polygene>> tutorial for details.
 
 The mixins, sideeffects and concerns are added during the bootstrap phase. It is very straight-forward;
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/contextualFragments/TraceAll.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/contextualFragments/TraceAll.java
 tag=assemble
 -----------
 
diff --git a/manual/src/docs/tutorials/howto-create-concern.txt b/manual/src/docs/tutorials/howto-create-concern.txt
index a36ea99..d76ae1f 100644
--- a/manual/src/docs/tutorials/howto-create-concern.txt
+++ b/manual/src/docs/tutorials/howto-create-concern.txt
@@ -26,7 +26,7 @@
 
 include::../../../../core/bootstrap/build/docs/buildinfo/artifact.txt[]
 
-At runtime you will need the Core Runtime artifact too. See the <<howto-depend-on-zest>> tutorial for details.
+At runtime you will need the Core Runtime artifact too. See the <<howto-depend-on-polygene>> tutorial for details.
 
 == Typed Concern ==
 
@@ -34,22 +34,22 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/InventoryConcern.java
+source=tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/InventoryConcern.java
 tag=allClass
 -----------
 
 Note that we could have implemented the InventoryConcern as an abstract class if we were not interested in __all__ the methods in the Order interface.
 Extending the ConcernOf is a convenience mechanism, instead of an explicit @ConcernFor annotation on
 a private field, which can be used in rare occasions when you are not able to extend. This base class defines the next
-field, which is set up by the Zest™ runtime and points to the next fragment in the call stack. We can also see that the
-InventoryService is provided to the concern, which is done with dependency injection. Zest™ also supports dependency
+field, which is set up by the Polygene™ runtime and points to the next fragment in the call stack. We can also see that the
+InventoryService is provided to the concern, which is done with dependency injection. Polygene™ also supports dependency
 injection via constructors and methods.
 
 It can be used as follows;
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/concern/Order.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/concern/Order.java
 tag=class
 -----------
 
@@ -63,7 +63,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/concern/MyGenericConcern.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/concern/MyGenericConcern.java
 tag=class
 -----------
 
@@ -71,7 +71,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/concern/AnyMixinType.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/concern/AnyMixinType.java
 tag=class
 -----------
 
@@ -90,7 +90,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/concern/MyGenericConcern.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/concern/MyGenericConcern.java
 tag=appliesTo
 -----------
 
@@ -98,7 +98,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/concern/AnyMixinType.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/concern/AnyMixinType.java
 tag=annotationUse
 -----------
 
@@ -108,6 +108,6 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/concern/MyAppliesToFilter.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/concern/MyAppliesToFilter.java
 tag=filter
 -----------
diff --git a/manual/src/docs/tutorials/howto-create-constraint.txt b/manual/src/docs/tutorials/howto-create-constraint.txt
index 23dfab7..9efd38e 100644
--- a/manual/src/docs/tutorials/howto-create-constraint.txt
+++ b/manual/src/docs/tutorials/howto-create-constraint.txt
@@ -26,7 +26,7 @@
 
 include::../../../../core/bootstrap/build/docs/buildinfo/artifact.txt[]
 
-At runtime you will need the Core Runtime artifact too. See the <<howto-depend-on-zest>> tutorial for details.
+At runtime you will need the Core Runtime artifact too. See the <<howto-depend-on-polygene>> tutorial for details.
 
 == Method Constraint ==
 
@@ -34,7 +34,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createConstraint/Dialer.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/Dialer.java
 tag=dialer
 -----------
 
@@ -42,7 +42,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createConstraint/PhoneNumber.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/PhoneNumber.java
 tag=annotation
 -----------
 
@@ -50,7 +50,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createConstraint/PhoneNumberConstraint.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/PhoneNumberConstraint.java
 tag=constraint
 -----------
 
@@ -58,7 +58,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createConstraint/DialerComposite.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/DialerComposite.java
 tag=composite
 -----------
 
@@ -67,7 +67,7 @@
 
 [snippet,java]
 ----
-source=manual/src/main/java/org/qi4j/manual/recipes/createConstraint/ParameterViolationConcern.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/ParameterViolationConcern.java
 tag=report
 ----
 
@@ -77,7 +77,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createConstraint/HasPhoneNumber.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/HasPhoneNumber.java
 tag=property
 -----------
 
@@ -89,6 +89,6 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createConstraint/PhoneNumberParameterViolationConcern.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/PhoneNumberParameterViolationConcern.java
 tag=property
 -----------
diff --git a/manual/src/docs/tutorials/howto-create-entity.txt b/manual/src/docs/tutorials/howto-create-entity.txt
index 41ffe94..2a20ce6 100644
--- a/manual/src/docs/tutorials/howto-create-entity.txt
+++ b/manual/src/docs/tutorials/howto-create-entity.txt
@@ -1,23 +1,26 @@
 //////////////////////
- * Copyright (c) 2007-2012, Niclas Hedhman. All Rights Reserved.
+ * 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
  *
- * Licensed 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.
+ *     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.
 //////////////////////
 
 [[howto-create-entity,Create an Entity]]
 = Create an Entity =
-One of the most common tasks in Zest™ is the management of the life cycle of Entities. Since Zest™ is capable of
+One of the most common tasks in Polygene™ is the management of the life cycle of Entities. Since Polygene™ is capable of
 delivering much higher performance than traditional Object-Relational Mapping technologies, we also expect that people
-use Entities more frequently in Zest™ applications, so it is a very important topic to cover.
+use Entities more frequently in Polygene™ applications, so it is a very important topic to cover.
 
 If you want to reproduce what's explained in this tutorial, remember to depend on the Core Bootstrap artifact:
 
@@ -26,7 +29,7 @@
 Moreover, you'll need an EntityStore for persistence and an Indexing engine for querying. Choose among the available
 implementations listed in the <<extensions>> section.
 
-At runtime you will need the Core Runtime artifact too. See the <<howto-depend-on-zest>> tutorial for details.
+At runtime you will need the Core Runtime artifact too. See the <<howto-depend-on-polygene>> tutorial for details.
 
 == Basics First ==
 
@@ -39,7 +42,7 @@
 interface. The Visibility rules will be applied to associate the right EntityComposite when a domain type is requested.
 Ambiguities are not accepted and will result in runtime exceptions.
 
-Zest™ supports that each entity instance can have more than one entity type, and it is managed per instance. This feature
+Polygene™ supports that each entity instance can have more than one entity type, and it is managed per instance. This feature
 is beyond the scope of this HowTO and will be covered subsequently.
 
 == Good Practice ==
@@ -65,17 +68,17 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createEntity/Car.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/Car.java
 tag=entity
 -----------
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createEntity/Manufacturer.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/Manufacturer.java
 tag=entity
 -----------
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createEntity/Accident.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/Accident.java
 tag=entity
 -----------
 
@@ -90,17 +93,17 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntity.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntity.java
 tag=composite
 -----------
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createEntity/ManufacturerEntity.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/ManufacturerEntity.java
 tag=composite
 -----------
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createEntity/AccidentValue.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/AccidentValue.java
 tag=composite
 -----------
 
@@ -114,7 +117,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createEntity/MyAssembler.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/MyAssembler.java
 tag=assembler1
 -----------
 
@@ -125,21 +128,21 @@
 
 == The Entity Factory ==
 
-The entity factory is something you need to write yourself, but as with most things in Zest™ it will end up being a
+The entity factory is something you need to write yourself, but as with most things in Polygene™ it will end up being a
 fairly small implementation. So how is that done?
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntityFactory.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntityFactory.java
 tag=carFactory
 -----------
 
-That is just the domain interface. We now need to make the service interface, which Zest™ needs to identify services and
+That is just the domain interface. We now need to make the service interface, which Polygene™ needs to identify services and
 make it possible for the service injection later.
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntityFactoryService.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntityFactoryService.java
 tag=carFactoryService
 -----------
 
@@ -147,11 +150,11 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntityFactoryMixin.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntityFactoryMixin.java
 tag=carFactoryMixin1
 -----------
 
-And doing that, first of all we need to request Zest™ runtime to give us the Module
+And doing that, first of all we need to request Polygene™ runtime to give us the Module
 that our code belongs to, and the UnitOfWork current context the execution is happening in.
 
 Injections that are related to the Visibility rules are handled by the @Structure annotation. And the easiest way for us
@@ -159,16 +162,16 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntityFactoryMixin.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntityFactoryMixin.java
 tag=carFactoryMixin2
 -----------
 
-Here Zest™ will inject the member module with the correct Module. In case we only need the Module
+Here Polygene™ will inject the member module with the correct Module. In case we only need the Module
 during the construction, we can also request it in the same manner as constructor argument.
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntityFactoryMixin.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntityFactoryMixin.java
 tag=carFactoryMixin3
 -----------
 
@@ -179,7 +182,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntityFactoryMixin.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntityFactoryMixin.java
 tag=create
 -----------
 
@@ -191,7 +194,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createEntity/ManufacturerRepository.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/ManufacturerRepository.java
 tag=repo
 -----------
 
@@ -199,7 +202,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createEntity/ManufacturerRepositoryService.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/ManufacturerRepositoryService.java
 tag=manufacturerRepositoryService
 -----------
 
@@ -207,7 +210,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createEntity/ManufacturerRepositoryMixin.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/ManufacturerRepositoryMixin.java
 tag=repo
 -----------
 
@@ -216,7 +219,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/createEntity/MyAssembler.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/MyAssembler.java
 tag=assembler2
 -----------
 
diff --git a/manual/src/docs/tutorials/howto-create-sideeffect.txt b/manual/src/docs/tutorials/howto-create-sideeffect.txt
index 2675168..d9b5680 100644
--- a/manual/src/docs/tutorials/howto-create-sideeffect.txt
+++ b/manual/src/docs/tutorials/howto-create-sideeffect.txt
@@ -26,7 +26,7 @@
 
 include::../../../../core/bootstrap/build/docs/buildinfo/artifact.txt[]
 
-At runtime you will need the Core Runtime artifact too. See the <<howto-depend-on-zest>> tutorial for details.
+At runtime you will need the Core Runtime artifact too. See the <<howto-depend-on-polygene>> tutorial for details.
 
 == Typed SideEffect ==
 
@@ -34,22 +34,22 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/MailNotifySideEffect.java
+source=tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/MailNotifySideEffect.java
 tag=allClass
 -----------
 
 The MailNotifySideEffect is implemented as an abstract class, since we are not interested in the many other methods in
 the Confirmable interface. Extending the SideEffectOf is a convenience mechanism, instead of an explicit @SideEffectFor
 annotation on a private field, which can be used in rare occasions when you are not able to extend. This base class
-defines the next field, which is set up by the Zest™ runtime and points to the next fragment in the call stack. We can
+defines the next field, which is set up by the Polygene™ runtime and points to the next fragment in the call stack. We can
 also see that the MailService, HasLineItems and HasCustomer are provided to the side-effect, which is done with
-dependency injection. Zest™ also supports dependency injection via constructors and methods.
+dependency injection. Polygene™ also supports dependency injection via constructors and methods.
 
 It can be used as follows;
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/sideeffects/OrderEntity.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/OrderEntity.java
 tag=body
 -----------
 
@@ -62,7 +62,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/sideeffects/MyGenericSideEffect.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/MyGenericSideEffect.java
 tag=body
 -----------
 
@@ -70,7 +70,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/sideeffects/AnyMixinType.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/AnyMixinType.java
 tag=body
 -----------
 
@@ -90,7 +90,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/sideeffects/MyGenericSideEffect.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/MyGenericSideEffect.java
 tag=appliesTo
 -----------
 
@@ -98,7 +98,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/sideeffects/AnyMixinType.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/AnyMixinType.java
 tag=annotation
 -----------
 
@@ -108,7 +108,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/sideeffects/MyAppliesToFilter.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/MyAppliesToFilter.java
 tag=filter
 -----------
 
diff --git a/manual/src/docs/tutorials/howto-depend-on-polygene.txt b/manual/src/docs/tutorials/howto-depend-on-polygene.txt
new file mode 100644
index 0000000..90ae1d6
--- /dev/null
+++ b/manual/src/docs/tutorials/howto-depend-on-polygene.txt
@@ -0,0 +1,193 @@
+///////////////////////////////////////////////////////////////
+ * 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.
+///////////////////////////////////////////////////////////////
+
+[[howto-depend-on-polygene,Depend on Polygene™]]
+= Depend on Polygene™ =
+
+NOTE: Some of the <<libraries>> and <<extensions>> depend on artifacts that are not deployed in central, you'll need to
+add other repositories to your build scripts accordingly.
+
+Release artifacts, including sources and javadoc, are deployed to Maven Central:
+
+http://repo1.maven.org/maven2/ (US)
+
+http://uk.maven.org/maven2/ (Europe)
+
+Snapshot artifacts, including sources and javadoc, are built against the `develop` branch and deployed weekly to the Apache SNAPSHOTS repository:
+
+http://repository.apache.org/snapshots/
+
+
+== Manually ==
+
+If you don't rely on your build scripts dependency resolution mechanism you should
+https://polygene.apache.org/download.html[download] the SDK distribution.
+
+
+== Using Maven ==
+
+You simply declare dependencies on Polygene™ artifacts:
+
+[source,xml]
+----
+<dependencies>
+    <dependency>
+        <groupId>org.apache.polygene.core</groupId>
+        <artifactId>org.apache.polygene.core.bootstrap</artifactId>
+        <version>POLYGENE_VERSION</version>
+    </dependency>
+    <dependency>
+        <groupId>org.apache.polygene.core</groupId>
+        <artifactId>org.apache.polygene.core.runtime</artifactId>
+        <version>POLYGENE_VERSION</version>
+        <scope>runtime</scope>
+    </dependency>
+    <dependency>
+        <groupId>org.apache.polygene.core</groupId>
+        <artifactId>org.apache.polygene.core.testsupport</artifactId>
+        <version>POLYGENE_VERSION</version>
+        <scope>test</scope>
+    </dependency>
+</dependencies>
+----
+
+Where `POLYGENE_VERSION` is the Polygene™ version you want to use.
+
+If you want to use +-SNAPSHOT+ versions, you need to register the Apache Snapshots repository:
+
+[source,xml]
+----
+<repositories>
+    <repository>
+        <id>apache-snapshots</id>
+        <url>https://repository.apache.org/snapshots/</url>
+        <releases><enabled>false</enabled></releases>
+        <snapshots><enabled>true</enabled></snapshots>
+    </repository>
+</repositories>
+----
+
+
+== Using Gradle ==
+
+You simply declare dependencies on Polygene™ artifacts:
+
+[source,groovy]
+----
+dependencies {
+    compile     "org.apache.polygene.core:org.apache.polygene.core.bootstrap:POLYGENE_VERSION"
+    runtime     "org.apache.polygene.core:org.apache.polygene.core.runtime:POLYGENE_VERSION"
+    testCompile "org.apache.polygene.core:org.apache.polygene.core.testsupport:POLYGENE_VERSION"
+}
+----
+
+Where `POLYGENE_VERSION` is the Polygene™ version you want to use.
+
+If you want to use +-SNAPSHOT+ versions, you need to register the Apache Snapshots repository:
+
+[source,groovy]
+----
+repositories {
+    maven { name 'apache-snapshots'; url "https://repository.apache.org/snapshots/" }
+}
+----
+
+
+== Using Buildr ==
+
+You simply declare dependencies on Polygene™ artifacts:
+
+[source,ruby]
+----
+compile.with 'org.apache.polygene.core:org.apache.polygene.core.bootstrap:POLYGENE_VERSION'
+package(:war).with :libs => 'org.apache.polygene.core:org.apache.polygene.core.runtime:POLYGENE_VERSION'
+test.with 'org.apache.polygene.core:org.apache.polygene.core.testsupport:POLYGENE_VERSION'
+----
+
+Where `POLYGENE_VERSION` is the Polygene™ version you want to use.
+
+If you want to use +-SNAPSHOT+ versions, you need to register the Apache Snapshots repository:
+
+[source,ruby]
+----
+repositories.remote << 'https://repository.apache.org/snapshots/'
+----
+
+
+== Using SBT ==
+
+You simply declare dependencies on Polygene™ artifacts:
+
+[source,scala]
+----
+libraryDependencies += \
+    "org.apache.polygene.core" % "org.apache.polygene.core.bootstrap" % "POLYGENE_VERSION" \
+    withSources() withJavadoc()
+libraryDependencies += \
+    "org.apache.polygene.core" % "org.apache.polygene.core.runtime" % "POLYGENE_VERSION" % "runtime" \
+    withSources() withJavadoc()
+libraryDependencies += \
+    "org.apache.polygene.core" % "org.apache.polygene.core.testsupport" % "POLYGENE_VERSION" % "test" \
+    withSources() withJavadoc()
+----
+
+Where `POLYGENE_VERSION` is the Polygene™ version you want to use.
+
+If you want to use +-SNAPSHOT+ versions, you need to register the Apache Snapshots repository:
+
+[source,scala]
+----
+resolvers += "apache-snapshots" at "https://repository.apache.org/snapshots/"
+----
+
+
+== Using Ivy ==
+
+You simply declare dependencies on Polygene™ artifacts:
+
+[source,xml]
+----
+<ivy-module>
+    <dependencies>
+        <dependency org="org.apache.polygene.core" name="org.apache.polygene.core.bootstrap"
+                    rev="POLYGENE_VERSION"  conf="default" />
+        <dependency org="org.apache.polygene.core" name="org.apache.polygene.core.runtime"
+                    rev="POLYGENE_VERSION"  conf="runtime" />
+        <dependency org="org.apache.polygene.core" name="org.apache.polygene.core.testsupport"
+                    rev="POLYGENE_VERSION"  conf="test" />
+    </dependencies>
+</ivy-module>
+----
+
+Where `POLYGENE_VERSION` is the Polygene™ version you want to use.
+
+If you want to use +-SNAPSHOT+ versions, you need to register the Apache Snapshots repository in a `ivysettings.xml` file:
+
+[source,xml]
+----
+<ivysettings>
+    <settings defaultResolver="chain"/>
+    <resolvers>
+        <chain name="chain">
+            <ibiblio name="apache-snapshots" m2compatible="true"
+                     root="https://repository.apache.org/snapshots/"/>
+        </chain>
+    </resolvers>
+</ivysettings>
+----
diff --git a/manual/src/docs/tutorials/howto-depend-on-zest.txt b/manual/src/docs/tutorials/howto-depend-on-zest.txt
deleted file mode 100644
index 1d0b629..0000000
--- a/manual/src/docs/tutorials/howto-depend-on-zest.txt
+++ /dev/null
@@ -1,193 +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.
-///////////////////////////////////////////////////////////////
-
-[[howto-depend-on-zest,Depend on Zest™ in your build]]
-= Depend on Zest™ in your build =
-
-NOTE: Some of the <<libraries>> and <<extensions>> depend on artifacts that are not deployed in central, you'll need to
-add other repositories to your build scripts accordingly.
-
-Release artifacts, including sources and javadoc, are deployed to Maven Central:
-
-http://repo1.maven.org/maven2/ (US)
-
-http://uk.maven.org/maven2/ (Europe)
-
-Snapshot artifacts, including sources and javadoc, are built against the `develop` branch and deployed weekly to the Apache SNAPSHOTS repository:
-
-http://repository.apache.org/snapshots/
-
-
-== Manually ==
-
-If you don't rely on your build scripts dependency resolution mechanism you should
-https://zest.apache.org/download.html[download] the SDK distribution.
-
-
-== Using Maven ==
-
-You simply declare dependencies on Zest™ artifacts:
-
-[source,xml]
-----
-<dependencies>
-    <dependency>
-        <groupId>org.qi4j.core</groupId>
-        <artifactId>org.qi4j.core.bootstrap</artifactId>
-        <version>ZEST_VERSION</version>
-    </dependency>
-    <dependency>
-        <groupId>org.qi4j.core</groupId>
-        <artifactId>org.qi4j.core.runtime</artifactId>
-        <version>ZEST_VERSION</version>
-        <scope>runtime</scope>
-    </dependency>
-    <dependency>
-        <groupId>org.qi4j.core</groupId>
-        <artifactId>org.qi4j.core.testsupport</artifactId>
-        <version>ZEST_VERSION</version>
-        <scope>test</scope>
-    </dependency>
-</dependencies>
-----
-
-Where `ZEST_VERSION` is the Zest™ version you want to use.
-
-If you want to use +-SNAPSHOT+ versions, you need to register the Apache Snapshots repository:
-
-[source,xml]
-----
-<repositories>
-    <repository>
-        <id>apache-snapshots</id>
-        <url>https://repository.apache.org/snapshots/</url>
-        <releases><enabled>false</enabled></releases>
-        <snapshots><enabled>true</enabled></snapshots>
-    </repository>
-</repositories>
-----
-
-
-== Using Gradle ==
-
-You simply declare dependencies on Zest™ artifacts:
-
-[source,groovy]
-----
-dependencies {
-    compile     "org.qi4j.core:org.qi4j.core.bootstrap:ZEST_VERSION"
-    runtime     "org.qi4j.core:org.qi4j.core.runtime:ZEST_VERSION"
-    testCompile "org.qi4j.core:org.qi4j.core.testsupport:ZEST_VERSION"
-}
-----
-
-Where `ZEST_VERSION` is the Zest™ version you want to use.
-
-If you want to use +-SNAPSHOT+ versions, you need to register the Apache Snapshots repository:
-
-[source,groovy]
-----
-repositories {
-    maven { name 'apache-snapshots'; url "https://repository.apache.org/snapshots/" }
-}
-----
-
-
-== Using Buildr ==
-
-You simply declare dependencies on Zest™ artifacts:
-
-[source,ruby]
-----
-compile.with 'org.qi4j.core:org.qi4j.core.bootstrap:ZEST_VERSION'
-package(:war).with :libs => 'org.qi4j.core:org.qi4j.core.runtime:ZEST_VERSION'
-test.with 'org.qi4j.core:org.qi4j.core.testsupport:ZEST_VERSION'
-----
-
-Where `ZEST_VERSION` is the Zest™ version you want to use.
-
-If you want to use +-SNAPSHOT+ versions, you need to register the Apache Snapshots repository:
-
-[source,ruby]
-----
-repositories.remote << 'https://repository.apache.org/snapshots/'
-----
-
-
-== Using SBT ==
-
-You simply declare dependencies on Zest™ artifacts:
-
-[source,scala]
-----
-libraryDependencies += \
-    "org.qi4j.core" % "org.qi4j.core.bootstrap" % "ZEST_VERSION" \
-    withSources() withJavadoc()
-libraryDependencies += \
-    "org.qi4j.core" % "org.qi4j.core.runtime" % "ZEST_VERSION" % "runtime" \
-    withSources() withJavadoc()
-libraryDependencies += \
-    "org.qi4j.core" % "org.qi4j.core.testsupport" % "ZEST_VERSION" % "test" \
-    withSources() withJavadoc()
-----
-
-Where `ZEST_VERSION` is the Zest™ version you want to use.
-
-If you want to use +-SNAPSHOT+ versions, you need to register the Apache Snapshots repository:
-
-[source,scala]
-----
-resolvers += "apache-snapshots" at "https://repository.apache.org/snapshots/"
-----
-
-
-== Using Ivy ==
-
-You simply declare dependencies on Zest™ artifacts:
-
-[source,xml]
-----
-<ivy-module>
-    <dependencies>
-        <dependency org="org.qi4j.core" name="org.qi4j.core.bootstrap"
-                    rev="ZEST_VERSION"  conf="default" />
-        <dependency org="org.qi4j.core" name="org.qi4j.core.runtime"
-                    rev="ZEST_VERSION"  conf="runtime" />
-        <dependency org="org.qi4j.core" name="org.qi4j.core.testsupport"
-                    rev="ZEST_VERSION"  conf="test" />
-    </dependencies>
-</ivy-module>
-----
-
-Where `ZEST_VERSION` is the Zest™ version you want to use.
-
-If you want to use +-SNAPSHOT+ versions, you need to register the Apache Snapshots repository in a `ivysettings.xml` file:
-
-[source,xml]
-----
-<ivysettings>
-    <settings defaultResolver="chain"/>
-    <resolvers>
-        <chain name="chain">
-            <ibiblio name="apache-snapshots" m2compatible="true"
-                     root="https://repository.apache.org/snapshots/"/>
-        </chain>
-    </resolvers>
-</ivysettings>
-----
diff --git a/manual/src/docs/tutorials/howto-invocation-annotation.txt b/manual/src/docs/tutorials/howto-invocation-annotation.txt
index 200ed44..8c87fe3 100644
--- a/manual/src/docs/tutorials/howto-invocation-annotation.txt
+++ b/manual/src/docs/tutorials/howto-invocation-annotation.txt
@@ -22,7 +22,7 @@
 The @Invocation annotation is relatively unknown but can be rather powerful to use, especially when creating
 libraries that needs to be flexible of what the user needs to do.
 
-@Invocation is a different +InjectionScope+, which is a concept to tell Zest runtime where to look for the
+@Invocation is a different +InjectionScope+, which is a concept to tell Polygene runtime where to look for the
 instances to be injected. Other, more well-known, +InjectionScope+ annotations are +@This+, +@Structure+ and
 +@Service+.
 
@@ -40,20 +40,20 @@
 it is useful to obtain this for typed fragment as well, to reduce names in Strings.
 
 == java.lang.reflect.AnnotatedElement ==
-This Reflection API class encapsulates the annotation aspect of any element that can be annotated. Zest implements
+This Reflection API class encapsulates the annotation aspect of any element that can be annotated. Polygene implements
 this interface for the Composite. That means that annotations for both the method as well as the composite is provided
 through this injection.
 
 == Custom Annotations ==
 It is often useful to introduce one's own annotations, especially for libraries, and use these annotations to direct
-the runtime to do different things. Many of the "built-in" features in Zest is actually done by this mechanism and
+the runtime to do different things. Many of the "built-in" features in Polygene is actually done by this mechanism and
 not directly implemented in the Core Runtime.
 
 First create an annotation of your own liking, it must have +java.lang.annotation.Retention+ set to +RUNTIME+
 
 [snippet,java]
 -----------
-source=core/runtime/src/test/java/org/qi4j/runtime/injection/InvocationInjectionTest.java
+source=core/runtime/src/test/java/org/apache/polygene/runtime/injection/InvocationInjectionTest.java
 tag=annotation
 -----------
 
@@ -61,7 +61,7 @@
 
 [snippet,java]
 -----------
-source=core/runtime/src/test/java/org/qi4j/runtime/injection/InvocationInjectionTest.java
+source=core/runtime/src/test/java/org/apache/polygene/runtime/injection/InvocationInjectionTest.java
 tag=declaration
 -----------
 
@@ -69,7 +69,7 @@
 
 [snippet,java]
 -----------
-source=core/runtime/src/test/java/org/qi4j/runtime/injection/InvocationInjectionTest.java
+source=core/runtime/src/test/java/org/apache/polygene/runtime/injection/InvocationInjectionTest.java
 tag=use1
 -----------
 
diff --git a/manual/src/docs/tutorials/howto-leverage-properties.txt b/manual/src/docs/tutorials/howto-leverage-properties.txt
index 1934f8c..c3fda1e 100644
--- a/manual/src/docs/tutorials/howto-leverage-properties.txt
+++ b/manual/src/docs/tutorials/howto-leverage-properties.txt
@@ -1,22 +1,25 @@
 //////////////////////
- * Copyright (c) 2007-2013, Niclas Hedhman. All Rights Reserved.
+ * 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
  *
- * Licensed 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.
+ *     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.
 //////////////////////
 
 [[howto-leverage-properties,Leverage Properties]]
 = Leverage Properties =
 
-Zest™ does not follow the JavaBeans standard for property support. Instead, a much more explicit concept is in place. The
+Polygene™ does not follow the JavaBeans standard for property support. Instead, a much more explicit concept is in place. The
 advantages are enormous, and the only real downside is that people are already destroyed, thinking in so called POJO
 terms.
 
@@ -24,19 +27,19 @@
 
 include::../../../../core/api/build/docs/buildinfo/artifact.txt[]
 
-At runtime you will need the Core Runtime artifact too. See the <<howto-depend-on-zest>> tutorial for details.
+At runtime you will need the Core Runtime artifact too. See the <<howto-depend-on-polygene>> tutorial for details.
 
-So in Zest, instead of writing;
+So in Polygene, instead of writing;
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/properties/pojo/Book.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/properties/pojo/Book.java
 tag=book
 -----------
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/properties/pojo/MutableBook.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/properties/pojo/MutableBook.java
 tag=mutableBook
 -----------
 
@@ -51,7 +54,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/properties/Book.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/properties/Book.java
 tag=book
 -----------
 
@@ -64,13 +67,13 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/properties/BookFactory.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/properties/BookFactory.java
 tag=create
 -----------
 
 == Persistence ==
 
-The Property concept also allows a much better defined persistence model. In Zest, only Property and Association
+The Property concept also allows a much better defined persistence model. In Polygene, only Property and Association
 instances are persisted, and that makes the semantics around the persistence system very clear.
 
 Properties reference values only, and these values must be Serializable, which means that Properties can not contain
@@ -87,7 +90,7 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/properties/SwingInfo.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/properties/SwingInfo.java
 tag=info
 -----------
 
@@ -95,6 +98,6 @@
 
 [snippet,java]
 -----------
-source=manual/src/main/java/org/qi4j/manual/recipes/properties/SwingPanel.java
+source=manual/src/main/java/org/apache/polygene/manual/recipes/properties/SwingPanel.java
 tag=info-use
 -----------
diff --git a/manual/src/docs/tutorials/howto-releasing-apache.txt b/manual/src/docs/tutorials/howto-releasing-apache.txt
index f529318..8421dfc 100644
--- a/manual/src/docs/tutorials/howto-releasing-apache.txt
+++ b/manual/src/docs/tutorials/howto-releasing-apache.txt
@@ -17,8 +17,8 @@
  * under the License.
 ///////////////////////////////////////////////////////////////
 
-[[releasing-apache,Releasing Zest]]
-= Releasing Zest™
+[[releasing-apache,Releasing Polygene]]
+= Releasing Polygene™
 
 [WARNING]
 ====
@@ -26,10 +26,10 @@
 This tutorial is known to work on Linux and Mac.
 ====
 
-This tutorial is intended for Apache Zest™ commiters who want to release a new version of Apache Zest™ (Java Edition) at The Apache Software Foundation.
+This tutorial is intended for Apache Polygene™ commiters who want to release a new version of Apache Polygene™ (Java Edition) at The Apache Software Foundation.
 It describes the tools and processes of a typical release.
 
-It is intended to be a recommendation of best practices for the Apache Zest™ project.
+It is intended to be a recommendation of best practices for the Apache Polygene™ project.
 The instructions provided here are consistent with, but not a replacement for the https://www.apache.org/dev/release.html[ASF Release Guidelines].
 
 
@@ -39,7 +39,7 @@
 
 === Select a Release Manager
 
-A Zest committer (normally one of the development team) should post an email to the development list proposing that a release be made and nominating a release manager.
+A Polygene committer (normally one of the development team) should post an email to the development list proposing that a release be made and nominating a release manager.
 Typically, the proposer volunteers as the release manager and it passes by https://www.apache.org/foundation/glossary.html#LazyConsensus[lazy consensus].
 
 
@@ -49,16 +49,21 @@
 
 [source,shell]
 ----
-mkdir zest-repos
-cd zest-repos
-git clone https://git-wip-us.apache.org/repos/asf/zest-java.git zest-java
-svn checkout https://svn.apache.org/repos/asf/zest/ zest-web
-svn checkout --depth empty https://dist.apache.org/repos/dist/ zest-dist
-cd zest-dist
+mkdir polygene-repos
+cd polygene-repos
+git clone https://git-wip-us.apache.org/repos/asf/polygene-java.git polygene-java
+git clone https://git-wip-us.apache.org/repos/asf/polygene-website.git polygene-website
+cd polygene-website
+git checkout asf-site
+cd ..
+svn checkout --depth empty https://dist.apache.org/repos/dist/ polygene-dist
+cd polygene-dist
 svn update --set-depth immediates dev
 svn update --set-depth immediates release
-svn update --set-depth infinity dev/zest
-svn update --set-depth infinity release/zest
+svn update --set-depth infinity dev/polygene
+svn update --set-depth infinity release/polygene
+cd ..
+
 ----
 
 You should then get the following directory tree:
@@ -66,46 +71,51 @@
 [source,text]
 ----
 .
-└── zest-repos
-    ├── zest-java           # Apache Zest™ (Java Edition) source
-    ├── zest-web            # https://zest.apache.org/ website
-    └── zest-dist
+└── polygene-repos
+    ├── polygene-java           # Apache Polygene™ (Java Edition) source
+    ├── polygene-website        # https://polygene.apache.org/ website
+    └── polygene-dist
         ├── dev
-        |   └── zest        # Releases candidate distributions
+        |   └── polygene        # Releases candidate distributions
         └── release
-            └── zest        # Releases distributions
+            └── polygene        # Releases distributions
 ----
 
 
 [TIP]
 ====
-From now on, all command line snippets start from the `zest-repos` directory.
+From now on, all command line snippets start from the `polygene-repos` directory.
 ====
 
 
-=== Build Apache Zest™ (Java Edition)
+=== Build Apache Polygene™ (Java Edition)
 
-Ensure you can test, build Apache Zest™ (Java Edition), including the documentation minisite generation using Asciidoc and artifact signing.
+Ensure you can test, build Apache Polygene™ (Java Edition), including the documentation minisite generation using Asciidoc and artifact signing.
 
 Here is what should pass before going further:
 
 [source,shell]
 ----
-cd zest-java
-./gradlew -Dversion="<RELEASE-VERSION>" website signArchives
+cd polygene-java
+git checkout develop
+./gradlew -Dversion="<RELEASE-VERSION>" checkDistributions
 ----
 
 See the <<build-system, Build System>> tutorial for details.
 
+[IMPORTANT]
+====
+Also ensure that the link:https://builds.apache.org/view/P/view/Polygene/job/Polygene(JavaEdition)-develop-java8-checkDists/[`checkDists`] CI build is passing.
+====
 
 === Install Jekyll
 
-Moreover, you will need to have a valid http://jekyllrb.com/[Jekyll] installation as the Apache Zest™ https://zest.apache.org/[website] is generated using it.
+Moreover, you will need to have a valid http://jekyllrb.com/[Jekyll] installation as the Apache Polygene™ https://polygene.apache.org/[website] is generated using it.
 
 
 === Setup git flow
 
-`git-flow` is a git extension that add git commands to easily use the git flow branching model the Apache Zest™ project follows.
+`git-flow` is a git extension that add git commands to easily use the git flow branching model the Apache Polygene™ project follows.
 See the https://github.com/nvie/gitflow/wiki/Installation[installation instructions].
 
 
@@ -123,31 +133,47 @@
 
 === Setup Apache Nexus credentials
 
-See the Apache https://www.apache.org/dev/publishing-maven-artifacts.html[Publishing Maven Artifacts] guide and the Apache Zest™ (Java Edition) <<build-system,Build System>> tutorial.
+See the Apache https://www.apache.org/dev/publishing-maven-artifacts.html[Publishing Maven Artifacts] guide and the Apache Polygene™ (Java Edition) <<build-system,Build System>> tutorial.
+
+
+=== Setup nodejs and NPM registry credentials
+
+First, https://nodejs.org/en/download/[install NodeJS].
+
+If you don't have a `npmjs.org` user yet, create one now:
+
+[source,shell]
+----
+npm adduser
+----
+
+If your `npmjs.org` user is not registered as a maintainer for the
+https://www.npmjs.com/package/generator-polygene[generator-polygene] package, ask for the privilege on
+`dev@polygene.apache.org`.
 
 
 === Update the `KEYS` files if needed.
 
-The reference `KEYS` file can be found at the `zest-java` repository's root, that is `zest-java/KEYS`.
+The reference `KEYS` file can be found at the `polygene-java` repository's root, that is `polygene-java/KEYS`.
 Ensure that it contains your public key.
 
 Next, diff it against the ones present in the `dev` and `release` distribution areas:
 
 [source,shell]
 ----
-diff zest-java/KEYS zest-dist/dev/zest/KEYS
-diff zest-java/KEYS zest-dist/release/zest/KEYS
+diff polygene-java/KEYS polygene-dist/dev/polygene/KEYS
+diff polygene-java/KEYS polygene-dist/release/polygene/KEYS
 ----
 
 And update them if needed:
 
 [source,shell]
 ----
-cp zest-java/KEYS zest-dist/dev/zest/KEYS
-cp zest-java/KEYS zest-dist/release/zest/KEYS
-cd zest-dist/dev/zest
-svn add dev/zest/KEYS release/zest/KEYS
-svn commit -m "zest: updating Zest KEYS"
+cp polygene-java/KEYS polygene-dist/dev/polygene/KEYS
+cp polygene-java/KEYS polygene-dist/release/polygene/KEYS
+cd polygene-dist/dev/polygene
+svn add dev/polygene/KEYS release/polygene/KEYS
+svn commit -m "polygene: updating Polygene KEYS"
 ----
 
 
@@ -164,14 +190,14 @@
 - marking them as `INVALID` or `WONTFIX`
 - changing their fix version to another unreleased version
 
-See the https://issues.apache.org/jira/browse/ZEST[ZEST] project on JIRA.
+See the https://issues.apache.org/jira/browse/POLYGENE[POLYGENE] project on JIRA.
 
 
 === Prepare Release-Notes
 
-Apache Zest™ release-notes are generated from JIRA issues.
+Apache Polygene™ release-notes are generated from JIRA issues.
 
-Open the target Zest™ version's release-notes in https://issues.apache.org/jira/browse/ZEST/?selectedTab=com.atlassian.jira.jira-projects-plugin:roadmap-panel[JIRA] and review them.
+Open the target Polygene™ version's release-notes in https://issues.apache.org/jira/browse/POLYGENE/?selectedTab=com.atlassian.jira.jira-projects-plugin:roadmap-panel[JIRA] and review them.
 
 JIRA can produces release-notes as HTML or plain-text.
 Set it up to generate plain-text release-notes.
@@ -179,25 +205,27 @@
 We will need these in several formats.
 Starting from the plain-text one we will generate the others.
 
-First save the text-plain release-notes in a file named `apache-zest-java-<RELEASE-VERSION>-release-notes.txt`.
-A good place for this file would be in the `zest-repos` directory created earlier, alongside all repositories.
+First save the text-plain release-notes in a file named `apache-polygene-java-<RELEASE-VERSION>-release-notes.txt`.
+A good place for this file would be in the `polygene-repos` directory created earlier, alongside all repositories.
 
 Convert to Asciidoc:
 
 [source,shell]
 ----
-cat "apache-zest-java-<RELEASE-VERSION>-release-notes.txt" | \
-  sed -e "s/* \[ZEST-\([0-9]\)*\]/- https:\/\/issues.apache.org\/jira\/browse\/ZEST-\1[ZEST-\1]/" | \
-  sed -e "s/^\*\*/===/" > "apache-zest-java-<RELEASE-VERSION>-release-notes.adoc"
+cat "apache-polygene-java-<RELEASE-VERSION>-release-notes.txt" | \
+  sed -e "s/\[POLYGENE-\([0-9]\)*\]/https:\/\/issues.apache.org\/jira\/browse\/POLYGENE-\1[POLYGENE-\1]/" | \
+  sed -e "s/    \* /- /" | sed -e "s/^\*\*/====/" \
+  > "apache-polygene-java-<RELEASE-VERSION>-release-notes.adoc"
 ----
 
 Convert to Markdown:
 
 [source,shell]
 ----
-cat "apache-zest-java-<RELEASE-VERSION>-release-notes.txt" | \
-  sed -e "s/* \[ZEST-\([0-9]\)*\]/- [ZEST-\1](https:\/\/issues.apache.org\/jira\/browse\/ZEST-\1)/" | \
-  sed -e "s/^\*\*/###/" > "apache-zest-java-<RELEASE-VERSION>-release-notes.md"
+cat "apache-polygene-java-<RELEASE-VERSION>-release-notes.txt" | \
+  sed -e "s/\[POLYGENE-\([0-9]*\)\]/[POLYGENE-\1](https:\/\/issues.apache.org\/jira\/browse\/POLYGENE-\1)/" | \
+  sed -e "s/    \* /- /" | sed -e "s/^\*\*/####/" \
+  > "apache-polygene-java-<RELEASE-VERSION>-release-notes.md"
 ----
 
 You should then have the following files:
@@ -205,9 +233,9 @@
 [source,shell]
 ----
 .
-├── apache-zest-java-<RELEASE-VERSION>-release-notes.txt
-├── apache-zest-java-<RELEASE-VERSION>-release-notes.adoc
-└── apache-zest-java-<RELEASE-VERSION>-release-notes.md
+├── apache-polygene-java-<RELEASE-VERSION>-release-notes.txt
+├── apache-polygene-java-<RELEASE-VERSION>-release-notes.adoc
+└── apache-polygene-java-<RELEASE-VERSION>-release-notes.md
 ----
 
 We will use them later.
@@ -219,7 +247,7 @@
 
 [source,shell]
 ----
-cd zest-java
+cd polygene-java
 git flow release start "<RELEASE-VERSION>-RC#"
 ----
 
@@ -232,34 +260,33 @@
 
 [source,shell]
 ----
-cd zest-java
-./gradlew -Dversion="<RELEASE-VERSION>" -PuploadRepository="file://$(pwd)/build/repositories/zest-java" \
-    clean assemble checkDists uploadArchives
+cd polygene-java
+./gradlew -Dversion="<RELEASE-VERSION>" assemble
 ----
 
-Review maven artifacts in `build/repositories/zest-java`.
+Review maven artifacts in `distributions/build/stage/maven-binaries`.
 
-Also review the release distributions in `build/distributions` where you should find the following files:
+Also review the release distributions in `distributions/build/distributions` where you should find the following files:
 
 [source,shell]
 ----
 .
-├── apache-zest-java-<RELEASE-VERSION>-bin.tgz
-├── apache-zest-java-<RELEASE-VERSION>-bin.tgz.MD5
-├── apache-zest-java-<RELEASE-VERSION>-bin.tgz.SHA-512
-├── apache-zest-java-<RELEASE-VERSION>-bin.tgz.asc
-├── apache-zest-java-<RELEASE-VERSION>-bin.zip
-├── apache-zest-java-<RELEASE-VERSION>-bin.zip.MD5
-├── apache-zest-java-<RELEASE-VERSION>-bin.zip.SHA-512
-├── apache-zest-java-<RELEASE-VERSION>-bin.zip.asc
-├── apache-zest-java-<RELEASE-VERSION>-src.tgz
-├── apache-zest-java-<RELEASE-VERSION>-src.tgz.MD5
-├── apache-zest-java-<RELEASE-VERSION>-src.tgz.SHA-512
-├── apache-zest-java-<RELEASE-VERSION>-src.tgz.asc
-├── apache-zest-java-<RELEASE-VERSION>-src.zip
-├── apache-zest-java-<RELEASE-VERSION>-src.zip.MD5
-├── apache-zest-java-<RELEASE-VERSION>-src.zip.SHA-512
-└── apache-zest-java-<RELEASE-VERSION>-src.zip.asc
+├── apache-polygene-java-<RELEASE-VERSION>-bin.tgz
+├── apache-polygene-java-<RELEASE-VERSION>-bin.tgz.MD5
+├── apache-polygene-java-<RELEASE-VERSION>-bin.tgz.SHA-512
+├── apache-polygene-java-<RELEASE-VERSION>-bin.tgz.asc
+├── apache-polygene-java-<RELEASE-VERSION>-bin.zip
+├── apache-polygene-java-<RELEASE-VERSION>-bin.zip.MD5
+├── apache-polygene-java-<RELEASE-VERSION>-bin.zip.SHA-512
+├── apache-polygene-java-<RELEASE-VERSION>-bin.zip.asc
+├── apache-polygene-java-<RELEASE-VERSION>-src.tgz
+├── apache-polygene-java-<RELEASE-VERSION>-src.tgz.MD5
+├── apache-polygene-java-<RELEASE-VERSION>-src.tgz.SHA-512
+├── apache-polygene-java-<RELEASE-VERSION>-src.tgz.asc
+├── apache-polygene-java-<RELEASE-VERSION>-src.zip
+├── apache-polygene-java-<RELEASE-VERSION>-src.zip.MD5
+├── apache-polygene-java-<RELEASE-VERSION>-src.zip.SHA-512
+└── apache-polygene-java-<RELEASE-VERSION>-src.zip.asc
 ----
 
 If any, make the required changes, commit them and iterate.
@@ -271,18 +298,18 @@
 
 [source,shell]
 ----
-cd zest-java
+cd polygene-java
 git flow release finish "<RELEASE-VERSION>-RC#"
 ----
 
 
 === Checkout the RC tag
 
-To build the release candidate bits, we need to checkout the release candidate tag, that will eventually be promoted as a signed release tag, because the Apache Zest™ build system generates versionning information based on git metadata.
+To build the release candidate bits, we need to checkout the release candidate tag, that will eventually be promoted as a signed release tag, because the Apache Polygene™ build system generates versionning information based on git metadata.
 
 [source,shell]
 ----
-cd zest-java
+cd polygene-java
 git checkout "<RELEASE-VERSION>-RC#"
 ----
 
@@ -291,7 +318,7 @@
 
 [source,shell]
 ----
-cd zest-java
+cd polygene-java
 ./gradlew -Dversion="<RELEASE-VERSION>" clean assemble
 ----
 
@@ -302,60 +329,92 @@
 
 [source,shell]
 ----
-cd zest-java
-./gradlew -Dversion="<RELEASE-VERSION>" uploadArchives
+cd polygene-java
+./gradlew -Dversion="<RELEASE-VERSION>" publishAsfMavenArtifacts
 ----
 
 Close the staging Nexus repository by following the https://www.apache.org/dev/publishing-maven-artifacts.html#close-stage[Closing the staged repository] guide.
 
 
+=== Stage NPM registry packages
+
+Publish the new version of the `generator-polygene` NPM package tagged as `beta`:
+
+[source,shell]
+----
+cd polygene-java/tools/generator-polygene
+npm publish --tag beta
+----
+
+If the release VOTE passes, we'll remove the `beta` tag, making the new version available.
+
+Then open https://www.npmjs.com/package/generator-polygene[https://www.npmjs.com/package/generator-polygene] to check
+that the new version was published and is tagged as `beta`.
+
+
 === Upload RC distributions
 
-Source and binary distributions, checksums and signatures must be uploaded to https://dist.apache.org/repos/dist/dev/zest/[dist.apache.org/repos/dist/dev/zest].
-This build created these in the `buid/distributions` directory, named `apache-zest-java-<RELEASE-VERSION>-[src|bin]*.*`.
+Source and binary distributions, checksums and signatures must be uploaded to https://dist.apache.org/repos/dist/dev/polygene/[dist.apache.org/repos/dist/dev/polygene].
+This build created these in the `buid/distributions` directory, named `apache-polygene-java-<RELEASE-VERSION>-[src|bin]*.*`.
 As this release still is a simple candidate, we'll rename them before upload to advertise this in their names.
 
 [source,shell]
 ----
 # Source ZIP
-cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-src.zip" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.zip"
-cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-src.zip.MD5" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.zip.MD5"
-cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-src.zip.SHA-512" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.zip.SHA-512"
-cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-src.zip.asc" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.zip.asc"
+cp "polygene-java/distributions/build/distributions/apache-polygene-java-<RELEASE-VERSION>-src.zip" \
+   "polygene-dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip"
+cp "polygene-java/distributions/build/distributions/apache-polygene-java-<RELEASE-VERSION>-src.zip.MD5" \
+   "polygene-dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip.MD5"
+cp "polygene-java/distributions/build/distributions/apache-polygene-java-<RELEASE-VERSION>-src.zip.SHA-512" \
+   "polygene-dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip.SHA-512"
+cp "polygene-java/distributions/build/distributions/apache-polygene-java-<RELEASE-VERSION>-src.zip.asc" \
+   "polygene-dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip.asc"
 # Source TAR.GZ
-cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-src.tgz" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.tgz"
-cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-src.tgz.MD5" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.tgz.MD5"
-cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-src.tgz.SHA-512" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.tgz.SHA-512"
-cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-src.tgz.asc" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.tgz.asc"
+cp "polygene-java/distributions/build/distributions/apache-polygene-java-<RELEASE-VERSION>-src.tgz" \
+   "polygene-dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-src.tgz"
+cp "polygene-java/distributions/build/distributions/apache-polygene-java-<RELEASE-VERSION>-src.tgz.MD5" \
+   "polygene-dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-src.tgz.MD5"
+cp "polygene-java/distributions/build/distributions/apache-polygene-java-<RELEASE-VERSION>-src.tgz.SHA-512" \
+   "polygene-dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-src.tgz.SHA-512"
+cp "polygene-java/distributions/build/distributions/apache-polygene-java-<RELEASE-VERSION>-src.tgz.asc" \
+   "polygene-dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-src.tgz.asc"
 # Binary ZIP
-cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-bin.zip" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.zip"
-cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-bin.zip.MD5" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.zip.MD5"
-cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-bin.zip.SHA-512" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.zip.SHA-512"
-cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-bin.zip.asc" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.zip.asc"
+cp "polygene-java/distributions/build/distributions/apache-polygene-java-<RELEASE-VERSION>-bin.zip" \
+   "polygene-dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.zip"
+cp "polygene-java/distributions/build/distributions/apache-polygene-java-<RELEASE-VERSION>-bin.zip.MD5" \
+   "polygene-dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.zip.MD5"
+cp "polygene-java/distributions/build/distributions/apache-polygene-java-<RELEASE-VERSION>-bin.zip.SHA-512" \
+   "polygene-dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.zip.SHA-512"
+cp "polygene-java/distributions/build/distributions/apache-polygene-java-<RELEASE-VERSION>-bin.zip.asc" \
+   "polygene-dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.zip.asc"
 # Binary TAR.GZ
-cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-bin.tgz" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.tgz"
-cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-bin.tgz.MD5" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.tgz.MD5"
-cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-bin.tgz.SHA-512" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.tgz.SHA-512"
-cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-bin.tgz.asc" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.tgz.asc"
+cp "polygene-java/distributions/build/distributions/apache-polygene-java-<RELEASE-VERSION>-bin.tgz" \
+   "polygene-dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.tgz"
+cp "polygene-java/distributions/build/distributions/apache-polygene-java-<RELEASE-VERSION>-bin.tgz.MD5" \
+   "polygene-dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.tgz.MD5"
+cp "polygene-java/distributions/build/distributions/apache-polygene-java-<RELEASE-VERSION>-bin.tgz.SHA-512" \
+   "polygene-dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.tgz.SHA-512"
+cp "polygene-java/distributions/build/distributions/apache-polygene-java-<RELEASE-VERSION>-bin.tgz.asc" \
+   "polygene-dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.tgz.asc"
 ----
 
 And then upload them:
 
 [source,shell]
 ----
-cd zest-dist/dev/zest
+cd polygene-dist/dev/polygene
 svn add * --force
-svn commit -m "zest: upload <RELEASE-VERSION> to dist/dev/zest"
+svn commit -m "polygene: upload <RELEASE-VERSION> to dist/dev/polygene"
 ----
 
 
 == Run the vote
 
-Send a "VOTE" to the mailto:dev@zest.apache.org[developer mailing list] including links to release artifacts. A VOTE always contains two parts. Send an email to the developer mailing list with the subject line:
+Send a "VOTE" to the mailto:dev@polygene.apache.org[developer mailing list] including links to release artifacts. A VOTE always contains two parts. Send an email to the developer mailing list with the subject line:
 
 [source,text]
 ----
-[VOTE] Release Zest (Java Edition) version <RELEASE-VERSION>
+[VOTE] Release Polygene (Java Edition) version <RELEASE-VERSION>
 ----
 
 Here is a sample template:
@@ -364,25 +423,27 @@
 ----
 Dear community,
 
-I am happy to start the VOTE thread for Apache Zest (Java Edition) <RELEASE-VERSION>!
+I am happy to start the VOTE thread for Apache Polygene (Java Edition) <RELEASE-VERSION>!
 
 The changelog for this release can be found here: https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12316820&version=12332997
 
-Tag: https://git-wip-us.apache.org/repos/asf?p=zest-java.git;a=tag;h=cc0f8211bf47b2df72a6239c9fdcd1d6906ea246
+Tag: https://git-wip-us.apache.org/repos/asf?p=polygene-java.git;a=tag;h=refs/tags/<RELEASE-VERSION>-RC#
 
-The distributions to be voted on are located here: https://dist.apache.org/repos/dist/dev/zest/
+The distributions to be voted on are located here: https://dist.apache.org/repos/dist/dev/polygene/
 
-Convenience artifacts in a maven repository are staged here: https://repository.apache.org/content/groups/staging/org/qi4j/
+Convenience artifacts in a maven repository are staged here: https://repository.apache.org/content/groups/staging/org/apache/polygene/
 
-Release distributions and convenience artifacts are signed with the following key: https://dist.apache.org/repos/dist/dev/zest/KEYS
+Release distributions and convenience artifacts are signed with the following key: https://dist.apache.org/repos/dist/dev/polygene/KEYS
 
-Please vote on releasing this package as Apache Zest (Java Edition) <RELEASE-VERSION>.
+Some guidance on how to validate distributions and artifacts can be found here: https://polygene.apache.org/java/develop/releasing-apache.html#_verifying_a_release_candidate
+
+Please vote on releasing this package as Apache Polygene (Java Edition) <RELEASE-VERSION>.
 
 The vote is open for the next 72 hours and passes if a majority of at least three +1 PMC votes are cast and there must be more positive than negative votes.
 
-[ ] +1 Release Apache Zest (Java Edition) <RELEASE-VERSION>
+[ ] +1 Release Apache Polygene (Java Edition) <RELEASE-VERSION>
 [ ]  0 I don't have a strong opinion about this, but I assume it's ok
-[ ] -1 Do not release Apache Zest (Java Edition) <RELEASE-VERSION> because...
+[ ] -1 Do not release Apache Polygene (Java Edition) <RELEASE-VERSION> because...
 
 Here is my vote:
 
@@ -395,16 +456,16 @@
 
 [source,text]
 ----
-[RESULT][VOTE] Release Zest (Java Edition) version <RELEASE-VERSION>
+[RESULT][VOTE] Release Polygene (Java Edition) version <RELEASE-VERSION>
 ----
 
 Here is a sample template:
 
 [source,text]
 ----
-To: "Zest Developers List" <dev@zest.apache.org>
-CC: "Zest Project Management Committee List" <private@zest.apache.org>
-Subject: [RESULT][VOTE] Release Zest (Java Edition) version <RELEASE-VERSION>
+To: "Polygene Developers List" <dev@polygene.apache.org>
+CC: "Polygene Project Management Committee List" <private@polygene.apache.org>
+Subject: [RESULT][VOTE] Release Polygene (Java Edition) version <RELEASE-VERSION>
 
 Hi,
 
@@ -419,6 +480,117 @@
 Votes on whether a package is ready to be released use majority approval -- i.e., at least three PMC members must vote affirmatively for release, and there must be more positive than negative votes.
 
 
+
+== Verifying a Release Candidate
+
+In order to verify a Apache Polygene™ (Java Edition) release candidate you'll need valid `wget`, `md5sum`, `shasum` with support for SHA-5.12, GnuPG and Java JDK >= 7 installations.
+
+If the setup feels like a chore, keep reading, you probably already have what's needed for some of the checks.
+A single check is better than none.
+
+
+=== Download RC
+
+First go downloading the release candidate distributions from https://dist.apache.org/repos/dist/dev/polygene/[dist.a.o/repos/dist/dev/polygene].
+Including `*.MD5`, `*.SHA-512` and `*.asc` files.
+Put them in a directory:
+
+[source,shell]
+----
+cd polygene-check-rc
+wget https://dist.apache.org/repos/dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.tgz
+wget https://dist.apache.org/repos/dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.tgz.MD5
+wget https://dist.apache.org/repos/dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.tgz.SHA-512
+wget https://dist.apache.org/repos/dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.tgz.asc
+wget https://dist.apache.org/repos/dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.zip
+wget https://dist.apache.org/repos/dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.zip.MD5
+wget https://dist.apache.org/repos/dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.zip.SHA-512
+wget https://dist.apache.org/repos/dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.zip.asc
+wget https://dist.apache.org/repos/dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-src.tgz
+wget https://dist.apache.org/repos/dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-src.tgz.MD5
+wget https://dist.apache.org/repos/dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-src.tgz.SHA-512
+wget https://dist.apache.org/repos/dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-src.tgz.asc
+wget https://dist.apache.org/repos/dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip
+wget https://dist.apache.org/repos/dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip.MD5
+wget https://dist.apache.org/repos/dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip.SHA-512
+wget https://dist.apache.org/repos/dist/dev/polygene/apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip.asc
+----
+
+
+=== Verify RC signatures
+
+Verify PGP signatures:
+
+[source,shell]
+----
+cd polygene-check-rc
+gpg apache-polygene-java-<RELEASE-VERSION>-RC#-bin.tgz.asc
+gpg apache-polygene-java-<RELEASE-VERSION>-RC#-bin.zip.asc
+gpg apache-polygene-java-<RELEASE-VERSION>-RC#-src.tgz.asc
+gpg apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip.asc
+----
+
+This must output `gpg: Good signature from "Signer Name <signer@ema.il>"` for each distribution.
+
+
+Verify MD5 checksum:
+
+[source,shell]
+----
+cd polygene-check-rc
+echo "$(cat apache-polygene-java-<RELEASE-VERSION>-RC#-bin.tgz.MD5) apache-polygene-java-<RELEASE-VERSION>-RC#-bin.tgz" | md5sum -c -
+echo "$(cat apache-polygene-java-<RELEASE-VERSION>-RC#-bin.zip.MD5) apache-polygene-java-<RELEASE-VERSION>-RC#-bin.zip" | md5sum -c -
+echo "$(cat apache-polygene-java-<RELEASE-VERSION>-RC#-src.tgz.MD5) apache-polygene-java-<RELEASE-VERSION>-RC#-src.tgz" | md5sum -c -
+echo "$(cat apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip.MD5) apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip" | md5sum -c -
+----
+
+This must output `some-filename: OK` for each distribution.
+
+
+Verify SHA-512 checksum:
+
+[source,shell]
+----
+cd polygene-check-rc
+echo "$(cat apache-polygene-java-<RELEASE-VERSION>-RC#-bin.tgz.MD5)  apache-polygene-java-<RELEASE-VERSION>-RC#-bin.tgz" | shasum -a 512 -c -
+echo "$(cat apache-polygene-java-<RELEASE-VERSION>-RC#-bin.zip.MD5)  apache-polygene-java-<RELEASE-VERSION>-RC#-bin.zip" | shasum -a 512 -c -
+echo "$(cat apache-polygene-java-<RELEASE-VERSION>-RC#-src.tgz.MD5)  apache-polygene-java-<RELEASE-VERSION>-RC#-src.tgz" | shasum -a 512 -c -
+echo "$(cat apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip.MD5)  apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip" | shasum -a 512 -c -
+----
+
+This also must output `some-filename: OK` for each distribution.
+
+
+=== Verify source distribution
+
+Unpack the source distributions, we will use the `zip` distribution here, both should be checked.
+
+[source,shell]
+----
+cd polygene-check-rc
+unzip apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip
+cd apache-polygene-java-<RELEASE-VERSION>-RC#-src
+----
+
+
+*LICENSE & NOTICE*
+
+Review `LICENSE` and `NOTICE` file(s) ;
+see the Apache's https://www.apache.org/dev/licensing-howto.html[Licensing Howto].
+
+Tools like https://creadur.apache.org/rat/[Apache Rat™] and other projects from https://creadur.apache.org/[Apache Creadur™] can come in handy.
+You can also `grep` the whole source tree.
+
+
+*Build RC from sources*
+
+[source,shell]
+----
+cd polygene-check-rc/apache-polygene-java-<RELEASE-VERSION>-RC#-src
+./gradlew assemble check
+----
+
+
 == VOTE passes
 
 
@@ -428,7 +600,7 @@
 
 [source,shell]
 ----
-cd zest-java
+cd polygene-java
 git tag -s "<RELEASE-VERSION>" "<RELEASE-VERSION>-RC#"
 ----
 
@@ -436,7 +608,7 @@
 
 [source,shell]
 ----
-cd zest-java
+cd polygene-java
 git checkout master
 git push origin master
 git checkout develop
@@ -449,40 +621,68 @@
 
 Promote the staged Nexus repository so it gets synched to Maven Central by following the https://www.apache.org/dev/publishing-maven-artifacts.html#promote[Promoting a repo] guide.
 
-Move the release distributions, checksums and signatures from https://dist.apache.org/repos/dist/dev/zest/[zest-dist/dev/zest] to https://dist.apache.org/repos/dist/release/zest/[zest-dist/release/zest]:
+Move the release distributions, checksums and signatures from https://dist.apache.org/repos/dist/dev/polygene/[polygene-dist/dev/polygene] to https://dist.apache.org/repos/dist/release/polygene/[polygene-dist/release/polygene]:
 
 [source,shell]
 ----
-cd zest-dist
-# Source ZIP
-svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.zip" "release/zest/apache-zest-java-<RELEASE-VERSION>-src.zip"
-svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.zip.MD5" "release/zest/apache-zest-java-<RELEASE-VERSION>-src.zip.MD5"
-svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.zip.SHA-512" "release/zest/apache-zest-java-<RELEASE-VERSION>-src.zip.SHA-512"
-svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.zip.asc" "release/zest/apache-zest-java-<RELEASE-VERSION>-src.zip.asc"
+cd polygene-dist
+# Source ZIP TODO
+export DIST_DEV_URL="https://dist.apache.org/repos/dist/dev/polygene"
+export DIST_RELEASE_URL="https://dist.apache.org/repos/dist/release/polygene"
+svn move "$DIST_DEV_URL/apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip" \
+     "$DIST_RELEASE_URL/apache-polygene-java-<RELEASE-VERSION>-src.zip" \
+     -m "polygene: promoting release <RELEASE-VERSION> distributions"
+svn move "$DIST_DEV_URL/apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip.MD5" \
+     "$DIST_RELEASE_URL/apache-polygene-java-<RELEASE-VERSION>-src.zip.MD5" \
+     -m "polygene: promoting release <RELEASE-VERSION> distributions"
+svn move "$DIST_DEV_URL/apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip.SHA-512" \
+     "$DIST_RELEASE_URL/apache-polygene-java-<RELEASE-VERSION>-src.zip.SHA-512" \
+     -m "polygene: promoting release <RELEASE-VERSION> distributions"
+svn move "$DIST_DEV_URL/apache-polygene-java-<RELEASE-VERSION>-RC#-src.zip.asc" \
+     "$DIST_RELEASE_URL/apache-polygene-java-<RELEASE-VERSION>-src.zip.asc" \
+     -m "polygene: promoting release <RELEASE-VERSION> distributions"
 # Source TAR.GZ
-svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.tgz" "release/zest/apache-zest-java-<RELEASE-VERSION>-src.tgz"
-svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.tgz.MD5" "release/zest/apache-zest-java-<RELEASE-VERSION>-src.tgz.MD5"
-svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.tgz.SHA-512" "release/zest/apache-zest-java-<RELEASE-VERSION>-src.tgz.SHA-512"
-svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.tgz.asc" "release/zest/apache-zest-java-<RELEASE-VERSION>-src.tgz.asc"
+svn move "$DIST_DEV_URL/apache-polygene-java-<RELEASE-VERSION>-RC#-src.tgz" \
+     "$DIST_RELEASE_URL/apache-polygene-java-<RELEASE-VERSION>-src.tgz" \
+     -m "polygene: promoting release <RELEASE-VERSION> distributions"
+svn move "$DIST_DEV_URL/apache-polygene-java-<RELEASE-VERSION>-RC#-src.tgz.MD5" \
+     "$DIST_RELEASE_URL/apache-polygene-java-<RELEASE-VERSION>-src.tgz.MD5" \
+     -m "polygene: promoting release <RELEASE-VERSION> distributions"
+svn move "$DIST_DEV_URL/apache-polygene-java-<RELEASE-VERSION>-RC#-src.tgz.SHA-512" \
+     "$DIST_RELEASE_URL/apache-polygene-java-<RELEASE-VERSION>-src.tgz.SHA-512" \
+     -m "polygene: promoting release <RELEASE-VERSION> distributions"
+svn move "$DIST_DEV_URL/apache-polygene-java-<RELEASE-VERSION>-RC#-src.tgz.asc" \
+     "$DIST_RELEASE_URL/apache-polygene-java-<RELEASE-VERSION>-src.tgz.asc" \
+     -m "polygene: promoting release <RELEASE-VERSION> distributions"
 # Binary ZIP
-svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.zip" "release/zest/apache-zest-java-<RELEASE-VERSION>-bin.zip"
-svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.zip.MD5" "release/zest/apache-zest-java-<RELEASE-VERSION>-bin.zip.MD5"
-svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.zip.SHA-512" "release/zest/apache-zest-java-<RELEASE-VERSION>-bin.zip.SHA-512"
-svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.zip.asc" "release/zest/apache-zest-java-<RELEASE-VERSION>-bin.zip.asc"
+svn move "$DIST_DEV_URL/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.zip" \
+     "$DIST_RELEASE_URL/apache-polygene-java-<RELEASE-VERSION>-bin.zip" \
+     -m "polygene: promoting release <RELEASE-VERSION> distributions"
+svn move "$DIST_DEV_URL/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.zip.MD5" \
+     "$DIST_RELEASE_URL/apache-polygene-java-<RELEASE-VERSION>-bin.zip.MD5" \
+     -m "polygene: promoting release <RELEASE-VERSION> distributions"
+svn move "$DIST_DEV_URL/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.zip.SHA-512" \
+     "$DIST_RELEASE_URL/apache-polygene-java-<RELEASE-VERSION>-bin.zip.SHA-512" \
+     -m "polygene: promoting release <RELEASE-VERSION> distributions"
+svn move "$DIST_DEV_URL/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.zip.asc" \
+     "$DIST_RELEASE_URL/apache-polygene-java-<RELEASE-VERSION>-bin.zip.asc" \
+     -m "polygene: promoting release <RELEASE-VERSION> distributions"
 # Binary TAR.GZ
-svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.tgz" "release/zest/apache-zest-java-<RELEASE-VERSION>-bin.tgz"
-svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.tgz.MD5" "release/zest/apache-zest-java-<RELEASE-VERSION>-bin.tgz.MD5"
-svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.tgz.SHA-512" "release/zest/apache-zest-java-<RELEASE-VERSION>-bin.tgz.SHA-512"
-svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.tgz.asc" "release/zest/apache-zest-java-<RELEASE-VERSION>-bin.tgz.asc"
+svn move "$DIST_DEV_URL/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.tgz" \
+     "$DIST_RELEASE_URL/apache-polygene-java-<RELEASE-VERSION>-bin.tgz" \
+     -m "polygene: promoting release <RELEASE-VERSION> distributions"
+svn move "$DIST_DEV_URL/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.tgz.MD5" \
+     "$DIST_RELEASE_URL/apache-polygene-java-<RELEASE-VERSION>-bin.tgz.MD5" \
+     -m "polygene: promoting release <RELEASE-VERSION> distributions"
+svn move "$DIST_DEV_URL/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.tgz.SHA-512" \
+     "$DIST_RELEASE_URL/apache-polygene-java-<RELEASE-VERSION>-bin.tgz.SHA-512" \
+     -m "polygene: promoting release <RELEASE-VERSION> distributions"
+svn move "$DIST_DEV_URL/apache-polygene-java-<RELEASE-VERSION>-RC#-bin.tgz.asc" \
+     "$DIST_RELEASE_URL/apache-polygene-java-<RELEASE-VERSION>-bin.tgz.asc" \
+     -m "polygene: promoting release <RELEASE-VERSION> distributions"
 ----
 
-And upload them:
-
-[source,shell]
-----
-cd zest-dist
-svn commit -m "zest: <RELEASE-VERSION>-RC# vote passed, promoted as <RELEASE-VERSION> release"
-----
+This produces one commit per file but keep svn history and runs fast, without re-uploading the distributions.
 
 
 === Wait 24 hours
@@ -502,30 +702,41 @@
 Start with a text version and once satisfied create at least a Markdown version for the website, see below.
 
 
-=== Update the Zest™ website
+=== Publish `generator-polygene` to the NPM registry
+
+[source,shell]
+----
+npm dist-tag rm generator-polygene beta
+----
+
+Then open https://www.npmjs.com/package/generator-polygene[https://www.npmjs.com/package/generator-polygene] to check
+that the package is not tagged as `beta` anymore.
+
+
+=== Update the Polygene™ website
 
 Generate the documentation and javadoc minisite:
 
 [source,shell]
 ----
-cd zest-java
-./gradlew -Dversion="<RELEASE-VERSION>" archiveJavadocs manuals
+cd polygene-java
+./gradlew -Dversion="<RELEASE-VERSION>" copyAsfDocumentation
 ----
 
-This will automatically put all files into the `zest-web` website repository.
+This will automatically put all files into the `polygene-website` website repository.
 
-Create a new post on the Zest™ website by creating a new Markdown file:
+Create a new post on the Polygene™ website by creating a new Markdown file:
 
 [source,shell]
 ----
-cd zest-web
-touch "site/src/_posts/YYYY-MM-DD-apache-zest-java-<RELEASE-VERSION>.md"
+cd polygene-website
+touch "src/_posts/YYYY-MM-DD-apache-polygene-java-<RELEASE-VERSION>.md"
 open !$
 ----
 
 You can reuse the Markdown formatted announcement content.
 
-Add the new released version in `zest-web/site/content/java/versions.json` below the `latest` entry:
+Add the new released version in `polygene-website/site/content/java/versions.json` below the `latest` entry:
 
 [source,js]
 ----
@@ -538,22 +749,22 @@
 }
 ----
 
-Finally, edit `zest-web/site/src/_data/releases.yml` with the new release data.
+Finally, edit `polygene-website/site/src/_data/releases.yml` with the new release data.
 Upmost is the latest:
 
 [source,text]
 ----
 - version: <RELEASE-VERSION>
-  announcement: YYYY/MM/DD/apache-zest-java-<RELEASE-VERSION>
+  announcement: YYYY/MM/DD/apache-polygene-java-<RELEASE-VERSION>
   signer: John Doe
   pgpId: FB751943
 ----
 
-You can run the Zest™ website locally:
+You can run the Polygene™ website locally:
 
 [source,shell]
 ----
-cd zest-web
+cd polygene-website
 jekyll serve
 ----
 
@@ -563,16 +774,26 @@
 
 [source,shell]
 ----
-cd zest-web
+cd polygene-website
 jekyll build
 ----
 
+Link `/latest` to the latest release:
+
+[source,shell]
+----
+cd polygene-website/content/java
+ln -s <RELEASE_VERSION> latest
+----
+
 And publish it:
 
 [source,shell]
 ----
-svn add * --force
-svn commit -m "zest: update website"
+cd polygene-website
+git add .
+git commit -m "update website"
+git push
 ----
 
 
@@ -583,14 +804,14 @@
 
 === Announce
 
-Finally, send an announcement to mailto:dev@zest.apache.org[dev@] and mailto:users@zest.apache.org[users@] mailing lists. Email announcements should have the subject line:
+Finally, send an announcement to mailto:dev@polygene.apache.org[dev@] and mailto:users@polygene.apache.org[users@] mailing lists. Email announcements should have the subject line:
 
 [source,text]
 ----
-[ANNOUNCE] Released Zest (Java Edition) version <RELEASE-VERSION>
+[ANNOUNCE] Released Polygene (Java Edition) version <RELEASE-VERSION>
 ----
 
-The announcement email should contains the release-notes as text, remember they are in the `apache-zest-java-<RELEASE-VERSION>-release-notes.txt` file you created earlier.
+The announcement email should contains the release-notes as text, remember they are in the `apache-polygene-java-<RELEASE-VERSION>-release-notes.txt` file you created earlier.
 
 
 
@@ -605,7 +826,7 @@
 
 [source,shell]
 ----
-cd zest-java
+cd polygene-java
 git checkout master
 git push origin master
 git checkout develop
@@ -618,18 +839,17 @@
 
 Drop the Nexus staging repository by following the https://www.apache.org/dev/publishing-maven-artifacts.html#drop[Dropping a repo] guide.
 
-Drop distributions, checksums and signatures from https://dist.apache.org/repos/dist/dev/zest/[zest-dist/dev/zest]
+Drop distributions, checksums and signatures from https://dist.apache.org/repos/dist/dev/polygene/[polygene-dist/dev/polygene]
 
 [source,shell]
 ----
-cd zest-dist/dev/zest/
+cd polygene-dist/dev/polygene/
 rm "*<RELEASE-VERSION>-RC#*.*"
 svn add * --force
-svn commit -m "zest: dropping <RELEASE-VERSION>-RC# from dist/dev/zest as the vote failed"
+svn commit -m "polygene: dropping <RELEASE-VERSION>-RC# from dist/dev/polygene as the vote failed"
 ----
 
 
 === Start over
 
 If a new RC is to be created, restart the process as described above.
-
diff --git a/manual/src/docs/tutorials/howto-use-io.txt b/manual/src/docs/tutorials/howto-use-io.txt
deleted file mode 100644
index 7eaecf6..0000000
--- a/manual/src/docs/tutorials/howto-use-io.txt
+++ /dev/null
@@ -1,326 +0,0 @@
-//////////////////////
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.
-//////////////////////
-
-[[howto-use-io,Use I/O API]]
-= Use I/O API =
-
-NOTE: This article was written on Rickard Öberg's blog, 6 Nov 2010
-
-
-The past week I've had to deal with a lot of data shuffling, both in raw form as bytes and strings, and as SPI and
-domain level objects. What struck me is that it is notoriously hard to shuffle things from one place to another in a
-way that is scalable, performant and handles errors correctly. And I had to do some things over and over again, like
-reading strings from files.
-
-So the thought occurred: there must be a general pattern to how this thing works, which can be extracted and put into a
-library. "Reading lines from a text file" should only have to be done once, and then used in whatever scenario requires
-it. Let's take a look at a typical example of reading from one file and writing to another to see if we can find out
-what the possible pieces could be:
-
-[source,java]
--------------
-1: File source = new File( getClass().getResource( "/iotest.txt" ).getFile() );
-1: File destination = File.createTempFile( "test", ".txt" );
-1: destination.deleteOnExit();
-2: BufferedReader reader = new BufferedReader(new FileReader(source));
-3: long count = 0;
-2: try
-2: {
-4:    BufferedWriter writer = new BufferedWriter(new FileWriter(destination));
-4:    try
-4:    {
-2:        String line = null;
-2:        while ((line = reader.readLine()) != null)
-2:        {
-3:            count++;
-4:            writer.append( line ).append( '\n' );
-2:        }
-4:        writer.close();
-4:    } catch (IOException e)
-4:    {
-4:        writer.close();
-4:        destination.delete();
-4:    }
-2: } finally
-2: {
-2:     reader.close();
-2: }
-1: System.out.println(count)
--------------
-
-As the numbers to the left indicates, I've identified four parts in this type of code that could be separated from
-each other.
-
-1) is the client code that initiates a transfer, and which have to know the input and output source.
-
-2) is the code that reads lines from an input.
-
-3) is helper code that I use to keep track of what's going on, and which I'd like to reuse no matter what kind of
-transfer is being done.
-
-4) receives the data and writes it down. In this code, if I wanted to implement batching on the read and write side I
-could do so by changing the 2 and 4 parts to read/write multiple lines at a time.
-
-== The API ==
-
-If you want to reproduce what's explained in this tutorial, remember to depend on the Core Runtime artifact that depends
-on Core API, Core SPI, Core Bootstrap and Core Functional & I/O APIs:
-
-include::../../../../core/runtime/build/docs/buildinfo/artifact.txt[]
-
-See the <<howto-depend-on-zest>> tutorial for details.
-
-Once theses parts were identified it was mostly just a matter of putting interfaces on these pieces, and making sure
-they can be easily used in many different situations. The result is as follows.
-
-To start with we have Input:
-
-[snippet,java]
---------------
-source=core/io/src/main/java/org/qi4j/io/Input.java
-tag=input
--------------
-
-Inputs, like Iterables, can be used over and over again to initiate transfers of data from one place to another, in
-this case an Output. Since I want this to be generic the type of things that is sent is T, so can be anything
-(byte[], String, EntityState, MyDomainObject). I also want the sender and receiver of data to be able to throw their
-own exceptions, and this is marked by declaring these as generic exception types. For example, the input may want to
-throw SQLException and the output IOException, if anything goes wrong. This should be strongly typed, and both sender
-and receiver must know when either side screws up, so that they can recover properly and close any resources they have
-opened.
-
-On the receiving side we then have Output:
-
-[snippet,java]
---------------
-source=core/io/src/main/java/org/qi4j/io/Output.java
-tag=output
--------------
-
-When receiveFrom is invoked by an Input, as a result of invoking transferTo on the Input, the Output should open
-whatever resources it needs to write to, and then expect data to come from a Sender. Both the Input and Output must
-have the same type T, so that they agree on what is being sent. We will see later how this can be handled if this is
-not the case.
-
-Next we have Sender:
-
-[snippet,java]
---------------
-source=core/io/src/main/java/org/qi4j/io/Sender.java
-tag=sender
--------------
-
-The Output invokes sendTo and passes in a Receiver that the Sender will use to send individual items. The sender at
-this point can start transferring data of type T to the receiver, one at a time. The Receiver looks like this:
-
-[snippet,java]
---------------
-source=core/io/src/main/java/org/qi4j/io/Receiver.java
-tag=receiver
--------------
-
-When the receiver gets the individual items from the sender it can either immediately write them to its underlying
-resource, or batch them up. Since the receiver will know when the transfer is done (sendTo returns) it can write the
-remaining batches properly and close any resource it holds.
-
-This simple pattern, with two interfaces on the sending side and two on the receiving side, gives us the potential to
-do scalable, performant and fault-tolerant transfers of data.
-
-== Standard Inputs and Outputs ==
-
-So now that the above API defines the contract of sending and receiving data, I can then create a couple of standard
-inputs and outputs. Let's say, reading lines of text from a file, and writing lines of text to a file. These
-implementations I can then put in static methods so they are easy to use. In the end, to make a copy of a text file
-looks like this:
-
-[snippet,java]
---------------
-source=manual/src/main/java/org/qi4j/manual/recipes/io/Docs.java
-tag=filter
---------------
-
-One line of code that handles the reading, the writing, the cleaning up, buffering, and whatnot. Pretty nifty! The
-transferTo method will throw IOException, which I can catch if I want to present any errors to the user. But actually
-dealing with those errors, i.e. closing the files and potentially deleting the destination if the transfer failed, is
-already handled by the Input and Output. I will never have to deal with the details of reading text from a file ever
-again!
-
-== Intercepting the transfer ==
-
-While the above handles the basic input/output of a transfer, there are usually other things that I want to do as well.
-I may want to count how many items were transferred, do some filtering, or log every 1000 items or so to see what's
-going on. Since input and output are now separated this becomes simply a matter of inserting something in the middle
-that mediates the input and output. Since many of these mediations have a similar character I can put these into
-standard utility methods to make them easier to use.
-
-The first standard decorator is a filter. I will implement this by means of supplying a Specification:
-
-[source,java]
---------------
-public static <T,ReceiverThrowableType extends Throwable> Output<T, ReceiverThrowableType> filter( final Specification<T> specification, final Output<T, ReceiverThrowableType> output)
-{
-   ... create an Output that filters items based on the Specification<T> ...
-}
---------------
-
-Where Specification is:
-
-[source,java]
---------------
-interface Specification<T>
-{
-     boolean test(T item);
-}
---------------
-
-With this simple construct I can now perform transfers and easily filter out items I don't want on the receiving side.
-This example removes empty lines from a text file.
-
-[source,java]
---------------
-File source = ...
-File destination = ...
-Inputs.text( source ).transferTo( Transforms.filter(new Specification<String>()
-{
-   public boolean test(String string)
-   {
-      return string.length() != 0;
-   }
-}, Outputs.text(destination) );
---------------
-
-
-The second common operation is mapping from one type to the other. This deals with the case that one Input you have may
-not match the Output you want to send to, but there's a way to map from the input type to the output type. An example
-would be to map from String to JSONObject, for example. The operation itself looks like this:
-
-[source,java]
---------------
-public static <From,To,ReceiverThrowableType extends Throwable> Output<From, ReceiverThrowableType> map( Function<From,To> function, Output<To, ReceiverThrowableType> output)
---------------
-
-Where Function is defined as:
-
-[source,java]
---------------
-interface Function<From, To>
-{
-    To map(From from);
-}
---------------
-
-With this I can then connect an Input of Strings to an Output of JSONObject like so:
-
-[source,java]
---------------
-Input<String,IOException> input = ...;
-Output<JSONObject,RuntimeException> output = ...;
-input.transferTo(Transforms.map(new String2JSON(), output);
---------------
-
-Where String2JSON implements Function and it's map method converts the String into a JSONObject.
-
-At this point we can now deal with the last part of the initial example, the counting of items. This can be implemented
-as a generic Map that has the same input and output type, and just maintains a count internally that updates on every
-call to map(). The example can then be written as:
-
-[source,java]
---------------
-File source = ...
-File destination = ...
-Counter<String> counter = new Counter<String>();
-Inputs.text( source ).transferTo( Transforms.map(counter, Outputs.text(destination) ));
-System.out.println("Nr of lines:"+counter.getCount())
---------------
-
-== Usage in the Zest™ SPI ==
-
-Now I can finally get back to my initial problem that led me to look into this: how to implement a good way to access
-EntityStates in a Zest™ EntityStore, and perform restores of backups. The current version of accessing EntityStates look
-like this:
-
-[source,java]
---------------
-<ThrowableType extends Throwable> void visitEntityStates( EntityStateVisitor<ThrowableType> visitor, ModuleSPI module )
-     throws ThrowableType;
-
-interface EntityStateVisitor<ThrowableType extends Throwable>
-{
-  void visitEntityState( EntityState entityState )
-     throws ThrowableType;
-}
---------------
-
-This can now be replaced with:
-
-[source,java]
---------------
-Input<EntityState, EntityStoreException> entityStates(ModuleSPI module);
---------------
-
-Because of the pattern outlined above, users of this will get more information about what's happening in the traversal,
-such as if the EntityStore raised an EntityStoreException during the traversal, which they can then handle gracefully.
-It also becomes easy to add decorators such as maps and filters to users of this. Let's say you only are interested in
-EntityState's of a given type. Then add a filter for this, without changing the consumer.
-
-For importing backup data into an EntityStore, the interface used to look like this:
-
-[source,java]
---------------
-interface ImportSupport
-{
-    ImportResult importFrom( Reader in )
-            throws IOException;
-}
---------------
-
-This ties the EntityStore to only being able to read JSON lines from Reader's, the client will not know if the
-IOException raised is due to errors in the Reader or writing in the store, and the ImportResult, which contains a list
-of exceptions and count of stuff, is quite ugly to create and use. With the I/O API at hand this can now be replaced
-with:
-
-[source,java]
---------------
-interface ImportSupport
-{
-   Output<String,EntityStoreException> importJSON();
-}
---------------
-
-
-To use this, given the helpers outlined above, is as simple as:
-
-[source,java]
---------------
-File backup = ...
-ImportSupport entityStore = ...
-Inputs.text(backup).transferTo(entityStore.importJSON());
---------------
-
-If the client wants any "extras", such as counting how many objects were imported, this can be done by adding filters
-as previously shown. If you only want to, say, import entities modified before a particular date (let's say you know
-some junk was introduced after a given time), then add a specification filter that performs this check. And so on.
-
-== Conclusion ==
-
-It is quite common while developing software that you have to shuffle data or objects from one input to another output,
-possible with some transformations in the middle. Usually these things have to be done from scratch, which opens up for
-errors and badly applied patterns. By introducing a generic Input/Output API that encapsulates and separates these
-things properly it becomes easier to perform these tasks in a scalable, performant and error-free way, and while still
-allowing these tasks to be decorated with extra features when needed.
-
-This article has outlined one way to do this, and the API and helpers that I've described are available in the current
-Zest™ Core 1.3-SNAPSHOT in Git (see Zest™ homepage for access details). The idea is to start using it throughout Zest
-wherever we need to do I/O of the type described here.
\ No newline at end of file
diff --git a/manual/src/docs/tutorials/howto-writing-docs.txt b/manual/src/docs/tutorials/howto-writing-docs.txt
index d5eb13e..92f7e3d 100644
--- a/manual/src/docs/tutorials/howto-writing-docs.txt
+++ b/manual/src/docs/tutorials/howto-writing-docs.txt
@@ -18,7 +18,7 @@
 ///////////////////////////////////////////////////////////////
 
 [[community-docs,Writing Documentation]]
-= Writing Zest™ Documentation =
+= Polygene™ Documentation =
 
 The documents use the asciidoc format, see:
 
@@ -33,7 +33,7 @@
 [[community-docs-overall-flow,Documentation Flow]]
 == Overall Flow ==
 
-TIP: To generate the website locally use `./gradlew -p manual website`. Output is in `~/manual/build/docs/website`.
+TIP: To generate the website locally use `./gradlew website`. Output is in `~/manual/build/docs/website`.
 
 Each (sub)project has its own documentation, in 'src/docs/' and all the Asciidoc documents have the +.txt+ file extension.
 
@@ -127,28 +127,28 @@
 
 [source]
 ----
-https://zest.apache.org/[Link text here]
+https://polygene.apache.org/[Link text here]
 ----
 
-Which renders like: https://zest.apache.org/[Link text here]
+Which renders like: https://polygene.apache.org/[Link text here]
 
 For short links it may be better not to add a link text, just do:
 
 [source]
 ----
-https://zest.apache.org/
+https://polygene.apache.org/
 ----
 
-Which renders like: https://zest.apache.org/
+Which renders like: https://polygene.apache.org/
 
 It's ok to have a dot right after the URL, it won't be part of the link.
 
 [source]
 ----
-https://zest.apache.org/.
+https://polygene.apache.org/.
 ----
 
-Which renders like: https://zest.apache.org/.
+Which renders like: https://polygene.apache.org/.
 
 == Text Formatting ==
 
@@ -226,7 +226,7 @@
 ----
  [snippet,java]
  -----------
- source=tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/OrderEntity.java
+ source=tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/OrderEntity.java
  tag=mainClass
  -----------
 ----
@@ -236,11 +236,11 @@
 
 [source]
 ----
-package org.qi4j.demo.tenminute;
+package org.apache.polygene.demo.tenminute;
 
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.sideeffect.SideEffects;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.sideeffect.SideEffects;
 
 // START SNIPPET: sideEffect
 @SideEffects( MailNotifySideEffect.class )
@@ -259,7 +259,7 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/OrderEntity.java
+source=tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/OrderEntity.java
 tag=mainClass
 -----------
 
@@ -322,8 +322,8 @@
 
 Common attributes you can use in documents:
 
-* \{qi4j-revnumber} - rendered as "{qi4j-revnumber}"
-* \{qi4j-importdir} - rendered as "{qi4j-importdir}"
+* \{polygene-revnumber} - rendered as "{polygene-revnumber}"
+* \{polygene-importdir} - rendered as "{polygene-importdir}"
 
 These can substitute part of URLs that point to for example APIdocs or source code.
 
@@ -339,5 +339,3 @@
 * http://www.sagehill.net/docbookxsl/index.html
 * http://docbook.sourceforge.net/release/xsl/1.76.1/doc/html/index.html
 * http://docbook.sourceforge.net/release/xsl/1.76.1/doc/fo/index.html
-
-
diff --git a/manual/src/docs/userguide/core.txt b/manual/src/docs/userguide/core.txt
index b6d77de..4c3da23 100644
--- a/manual/src/docs/userguide/core.txt
+++ b/manual/src/docs/userguide/core.txt
@@ -24,20 +24,20 @@
 
 == Overview ==
 
-The Zest™ Core is composed of several artifacts described in this section.
+The Polygene™ Core is composed of several artifacts described in this section.
 
 The following figure show the Core artifacts alongside <<libraries,libraries>> and <<extensions,extensions>>, and, in green,
 typical applications artifacts. This is not a full code dependency graph but should give you a good overview of how the
-pieces fit together. Find out more about each of the Zest™ Core artifacts below.
+pieces fit together. Find out more about each of the Polygene™ Core artifacts below.
 
-.Zest™ Core Overview
+.Polygene™ Core Overview
 image::core-overview.png[]
 
 //*<<core-api,Core API>>*
 === Core API ===
 
 //____
-The Zest™ Core API is the primary interface for client application code during the main execution phase, i.e. after the
+The Polygene™ Core API is the primary interface for client application code during the main execution phase, i.e. after the
 application has been activated.
 
 <<core-api,Learn more>>
@@ -46,9 +46,9 @@
 //*<<core-bootstrap-assembly,Core Bootstrap>>*
 === Core Bootstrap ===
 //____
-Zest™ has a distinct bootstrap phase, also known as the _Assembly_ of an application, where the applications structure
+Polygene™ has a distinct bootstrap phase, also known as the _Assembly_ of an application, where the applications structure
 is defined programmatically. Once all the layers, modules and all the composite types in each module have been defined
-the model is instantiated into an application. This enables the entire _structure_ system in Zest, where types "belongs"
+the model is instantiated into an application. This enables the entire _structure_ system in Polygene, where types "belongs"
 to a module and visibility rules define default behaviors, enforcement of architectural integrity and much more.
 
 <<core-bootstrap-assembly,Learn more>>
@@ -57,37 +57,17 @@
 //*<<core-testsupport,Core Test Support>>*
 === Core Test Support ===
 //____
-Zest™ comes with classes to help with testing. There is also some mocking support, to allow some of Zest’s unique
-aspects to be mocked, but since Zest™ is so flexible at a fine-granular level, we have found that mocking is seldom,
+Polygene™ comes with classes to help with testing. There is also some mocking support, to allow some of Polygene’s unique
+aspects to be mocked, but since Polygene™ is so flexible at a fine-granular level, we have found that mocking is seldom,
 if ever, needed.
 
 <<core-testsupport,Learn more>>
 //____
 
-//*<<core-functional,Core Functional API>>*
-=== Core Functional API ===
-//____
-The Zest™ Core Functional API is a generic package to work with Iterables in a "functional programming language" style.
-
-This package is completely independent of everything else in Zest™ and may be used on its own in any kind of environment
-such as Spring or Java EE applications.
-
-<<core-functional,Learn more>>
-//____
-
-//*<<core-io,Core I/O API>>*
-=== Core I/O API ===
-//____
-The Zest™ Core I/O API tries to address the problem around shuffling data around from various I/O inputs and outputs,
-possibly with transformations and filtering along the way.
-
-<<core-io,Learn more>>
-//____
-
 //*<<core-spi,Core Extension SPI>>*
 === Core Extension SPI ===
 //____
-The Zest™ Core Runtime has a number of extension points, which we call the _Zest™ Core Extension SPI_. These are defined
+The Polygene™ Core Runtime has a number of extension points, which we call the _Polygene™ Core Extension SPI_. These are defined
 interfaces used *only* by the Core Runtime and *never* directly by application code. <<extensions>> are assembled in
 applications during the bootstrap phase.
 
@@ -97,8 +77,8 @@
 //*<<core-spi,Core Runtime>>*
 === Core Runtime ===
 //____
-Your code should *never*, *ever*, have a dependency on Zest™ Core Runtime. If you think you need this, you should
-probably contact dev@zest.apache.org and see if your usecase can either be solved in a existing way or
+Your code should *never*, *ever*, have a dependency on Polygene™ Core Runtime. If you think you need this, you should
+probably contact dev@polygene.apache.org and see if your usecase can either be solved in a existing way or
 perhaps that a new Core Extension SPI is needed.
 
 <<core-runtime,Learn more>>
@@ -119,14 +99,6 @@
 
 :leveloffset: 2
 
-include::../../../../core/functional/src/docs/functional.txt[]
-
-:leveloffset: 2
-
-include::../../../../core/io/src/docs/io.txt[]
-
-:leveloffset: 2
-
 include::../../../../core/spi/src/docs/spi.txt[]
 
 :leveloffset: 2
diff --git a/manual/src/docs/userguide/docinfo.xml b/manual/src/docs/userguide/docinfo.xml
index c970145..c8d3023 100644
--- a/manual/src/docs/userguide/docinfo.xml
+++ b/manual/src/docs/userguide/docinfo.xml
@@ -1,27 +1,30 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <authorgroup>
-  <corpauthor>The Qi4j Community
+  <corpauthor>The Apache Polygene Community
   </corpauthor>
 </authorgroup>
 
 <copyright>
 <year>2011</year>
-<holder>Qi4j Community</holder>
+<holder>The Apache Polygene Community</holder>
 </copyright>
 
 <legalnotice>
diff --git a/manual/src/docs/userguide/extensions.txt b/manual/src/docs/userguide/extensions.txt
index 511578f..433bd47 100644
--- a/manual/src/docs/userguide/extensions.txt
+++ b/manual/src/docs/userguide/extensions.txt
@@ -24,11 +24,11 @@
 
 == Overview ==
 
-We try to keep the Zest™ Core Runtime as lean as possible, and a lot of the power to the Zest™ Platform comes via its
+We try to keep the Polygene™ Core Runtime as lean as possible, and a lot of the power to the Polygene™ Platform comes via its
 Extension SPI, which defines clear ways to extend the platform. There are currently the following Extensions types,
 each with possibly more than one implementation;
 
-   * Value Serialization
+   * Serialization
    * Entity Stores
    * Index / Query Engines
    * Entity Caches
@@ -37,7 +37,7 @@
    * Migration
 
 This section will go through each of the available extensions.
-The Zest™ Extensions are of varying maturity level and we try to maintain a STATUS (dev-status.xml) file indicating
+The Polygene™ Extensions are of varying maturity level and we try to maintain a STATUS (dev-status.xml) file indicating
 how good the codebase, documentation and unit tests are for each of the libraries. This is highly subjective and
 potentially different individuals will judge this differently, but at least it gives a ballpark idea of the situation
 for our users.
@@ -45,23 +45,15 @@
 
 :leveloffset: 2
 
-include::../../../../extensions/valueserialization-orgjson/src/docs/vs-orgjson.txt[]
+include::../../../../extensions/serialization-javaxjson/src/docs/serialization-javaxjson.txt[]
 
 :leveloffset: 2
 
-include::../../../../extensions/valueserialization-jackson/src/docs/vs-jackson.txt[]
+include::../../../../extensions/serialization-javaxxml/src/docs/serialization-javaxxml.txt[]
 
 :leveloffset: 2
 
-include::../../../../extensions/valueserialization-stax/src/docs/vs-stax.txt[]
-
-:leveloffset: 2
-
-include::../../../../extensions/cache-ehcache/src/docs/cache-ehcache.txt[]
-
-:leveloffset: 2
-
-include::../../../../extensions/cache-memcache/src/docs/cache-memcache.txt[]
+include::../../../../extensions/serialization-messagepack/src/docs/serialization-messagepack.txt[]
 
 :leveloffset: 2
 
@@ -73,6 +65,10 @@
 
 :leveloffset: 2
 
+include::../../../../extensions/entitystore-geode/src/docs/es-geode.txt[]
+
+:leveloffset: 2
+
 include::../../../../extensions/entitystore-hazelcast/src/docs/es-hazelcast.txt[]
 
 :leveloffset: 2
@@ -109,6 +105,14 @@
 
 :leveloffset: 2
 
+include::../../../../extensions/cache-ehcache/src/docs/cache-ehcache.txt[]
+
+:leveloffset: 2
+
+include::../../../../extensions/cache-memcache/src/docs/cache-memcache.txt[]
+
+:leveloffset: 2
+
 include::../../../../extensions/indexing-elasticsearch/src/docs/index-elasticsearch.txt[]
 
 :leveloffset: 2
@@ -125,7 +129,7 @@
 
 :leveloffset: 2
 
-include::../../../../extensions/metrics-yammer/src/docs/metrics-yammer.txt[]
+include::../../../../extensions/metrics-codahale/src/docs/metrics-codahale.txt[]
 
 :leveloffset: 2
 
@@ -136,4 +140,3 @@
 include::../../../../extensions/reindexer/src/docs/reindexer.txt[]
 
 :leveloffset: 2
-
diff --git a/manual/src/docs/userguide/faq.txt b/manual/src/docs/userguide/faq.txt
index bd93829..ad38602 100644
--- a/manual/src/docs/userguide/faq.txt
+++ b/manual/src/docs/userguide/faq.txt
@@ -20,7 +20,7 @@
 [[faq,FAQ]]
 = Frequently Asked Questions =
 
-Is it possible to use Scala with Zest?::
-        Short Answer: Yes. Scala traits can be used as Zest™ fragments, and Zest™ composites can be used in Scala.
+Is it possible to use Scala with Polygene?::
+        Short Answer: Yes. Scala traits can be used as Polygene™ fragments, and Polygene™ composites can be used in Scala.
 
 
diff --git a/manual/src/docs/userguide/glossary.txt b/manual/src/docs/userguide/glossary.txt
index 38a1205..ffef798 100644
--- a/manual/src/docs/userguide/glossary.txt
+++ b/manual/src/docs/userguide/glossary.txt
@@ -24,7 +24,7 @@
 
 == Glossary ==
 
-There are a lot of concepts in Zest™ which may have different meanings in other contexts. So in true DDD-style
+There are a lot of concepts in Polygene™ which may have different meanings in other contexts. So in true DDD-style
 ubiquitous language, we are here listing the definitions of the terms and concepts that are being used.
 
 [glossary]
@@ -34,7 +34,7 @@
 An Abstract Mixin is an implementation of the <<def-mixin-type>> interface, but is an abstract class and has not
 implemented all the methods.
 
-The Zest™ runtime can use multiple <<def-mixin,Mixins>> for each <<def-mixin-type>> interface. It is also possible to let
+The Polygene™ runtime can use multiple <<def-mixin,Mixins>> for each <<def-mixin-type>> interface. It is also possible to let
 a <<def-generic-mixin>> handle the remaining missing methods.
 --
 
@@ -53,10 +53,10 @@
 [[def-application,Application]]Application::
 +
 --
-Application is the top level concept handled by the Zest™ runtime instance. It holds the information about the
+Application is the top level concept handled by the Polygene™ runtime instance. It holds the information about the
 <<def-layer,Layers>> in the application architecture. See <<def-structure>> for more information.
 
-There is one and only one Application instance per Zest™ Runtime instance.
+There is one and only one Application instance per Polygene™ Runtime instance.
 --
 
 
@@ -102,7 +102,7 @@
 [[def-composite-metatype,Composite Meta Type]]Composite Meta Type::
 +
 --
-There are 5 Composite Meta Types defined in Zest, which each share the composition features but have distinct
+There are 5 Composite Meta Types defined in Polygene, which each share the composition features but have distinct
 semantic differences.
 
 * <<def-entitycomposite>>
@@ -120,7 +120,7 @@
 created.
 
 Composite Type interfaces must be a sub-type of one of the 5 <<def-composite-metatype,Composite Meta Types>> defined in
-Zest™ otherwise it can not be instantiated.
+Polygene™ otherwise it can not be instantiated.
 --
 
 
@@ -140,7 +140,7 @@
 
 Concerns are established by the use of the @Concerns annotation on composites.
 
-Concern is one of the 3 kinds of <<def-modifier,Modifiers>> defined in Zest.
+Concern is one of the 3 kinds of <<def-modifier,Modifiers>> defined in Polygene.
 --
 
 
@@ -153,7 +153,7 @@
 properties files first time. Note that on consequent start-ups the properties file is not read, as the configuration is
 read from the EntityStore.
 
-ConfigurationComposite is one of the 5 <<def-composite-metatype,Composite Meta Types>> defined in Zest.
+ConfigurationComposite is one of the 5 <<def-composite-metatype,Composite Meta Types>> defined in Polygene.
 
 See <<howto-configure-service>> to learn how to use Configuration Composites.
 --
@@ -162,7 +162,7 @@
 [[def-constraint,Constraint]]Constraint::
 +
 --
-Constraints are a kind of validators, which are consulted prior to invoking the method call. Zest™ currently only
+Constraints are a kind of validators, which are consulted prior to invoking the method call. Polygene™ currently only
 supports ParameterConstraints on methods and value constraints on <<def-property,Properties>>, but future versions will
 include Constraint types for checking complete method calls and return values.
 
@@ -172,7 +172,7 @@
 
 See <<howto-create-constraint>> to learn how to write your own Constraints.
 
-Constraint is one of the 3 kinds of <<def-modifier,Modifiers>> defined in Zest.
+Constraint is one of the 3 kinds of <<def-modifier,Modifiers>> defined in Polygene.
 --
 
 
@@ -182,7 +182,7 @@
 An Entity Composite, or just Entity for short, is a persisted composite with an <<def-identity>>. An entity only has
 scope within an <<def-unitofwork>> and is therefor inherently thread-safe.
 
-EntityComposite is one of the 5 <<def-composite-metatype,Composite Meta Types>> defined in Zest.
+EntityComposite is one of the 5 <<def-composite-metatype,Composite Meta Types>> defined in Polygene.
 --
 
 
@@ -231,15 +231,15 @@
 [[def-invocation-stack,Invocation Stack]]Invocation Stack::
 +
 --
-For each method, Qi4J will create and re-use an Invocation Stack. It will be built with the sequence of
+For each method, Polygene™ will create and re-use an Invocation Stack. It will be built with the sequence of
 <<def-modifier,Modifiers>> and an end-point that will link into the stateful <<def-mixin>>.
 
 It is important to recognize that, for memory footprint reasons, Invocation Stacks are shared across
-<<def-composite,Composites>> of the same <<def-composite-type>>. They are however thread-safe, in that Zest™ will never
+<<def-composite,Composites>> of the same <<def-composite-type>>. They are however thread-safe, in that Polygene™ will never
 bind the same Invocation Stack to more than one <<def-composite>> instance during a method call, but that between method
 invocations the <<def-modifier,Modifiers>> in the Invocation Stack can not assume that it is bound to the same
 <<def-composite>> instance. Therefor, <<def-modifier,Modifiers>> are not expected to keep state between method
-invocations, and when it needs to do that, then it should reference a <<def-mixin>> via the @This annotation. Zest™ will
+invocations, and when it needs to do that, then it should reference a <<def-mixin>> via the @This annotation. Polygene™ will
 during the binding of the Invocation Stack to the <<def-composite>>, also ensure that all referenced
 <<def-mixin,Mixins>> are correctly injected in the Invocation Stack.
 --
@@ -248,7 +248,7 @@
 [[def-layer,Layer]]Layer::
 +
 --
-Zest™ promotes a Layered application design, where Layers can only access lower Layers and not higher Layers or Layers at
+Polygene™ promotes a Layered application design, where Layers can only access lower Layers and not higher Layers or Layers at
 the same level.
 --
 
@@ -345,7 +345,7 @@
 --
 Service Composite is a subtype of <<def-composite>>, and has a range of features built into it.
 
-ServiceComposite is one of the 5 <<def-composite-metatype,Composite Meta Types>> defined in Zest.
+ServiceComposite is one of the 5 <<def-composite-metatype,Composite Meta Types>> defined in Polygene.
 
 See the <<core-api-service,Service Composite chapter>>.
 --
@@ -370,24 +370,24 @@
 
 SideEffects are established by the use of the @SideEffects annotation on composites.
 
-SideEffect is one of the 3 kinds of <<def-modifier,Modifiers>> defined in Zest.
+SideEffect is one of the 3 kinds of <<def-modifier,Modifiers>> defined in Polygene.
 --
 
 
 [[def-structure,Structure]]Structure::
 +
 --
-Zest™ promotes a conventional view of application structure, that computer science has been using for decades.
+Polygene™ promotes a conventional view of application structure, that computer science has been using for decades.
 
 The definition is as follows;
 
-* One <<def-application>> per Zest™ runtime instance.
+* One <<def-application>> per Polygene™ runtime instance.
 * One or more <<def-layer,Layers>> per <<def-application>>.
 * Zero, one or more <<def-module,Modules>> per <<def-layer>>.
 * Zero, one or more Assemblies per <<def-module>>.
 
 The principle of this Structure is to assist the programmer to create well modularized applications, that are easily
-extended and maintained. Zest™ will restrict access between <<def-module,Modules>>, so that code can only reach
+extended and maintained. Polygene™ will restrict access between <<def-module,Modules>>, so that code can only reach
 <<def-composite,Composites>> and Objects in <<def-module,Modules>> (including itself) of the same or lower
 <<def-layer,Layers>>.
 
@@ -424,7 +424,7 @@
 the value exists or it doesn't, no need for synchronization. Values are typically very easy to test and very robust to
 refactoring.
 
-Zest™ defines values as a primary meta type through the ValueComposite, as we think the benefits of values are great.
+Polygene™ defines values as a primary meta type through the ValueComposite, as we think the benefits of values are great.
 The ValueComposite is very light-weight compared to the <<def-entitycomposite>>, and its value can still be persisted as
 part of an <<def-entitycomposite>> via a <<def-property>>.
 
diff --git a/manual/src/docs/userguide/index.txt b/manual/src/docs/userguide/index.txt
index 683dee0..a2fda6a 100644
--- a/manual/src/docs/userguide/index.txt
+++ b/manual/src/docs/userguide/index.txt
@@ -17,11 +17,11 @@
  * under the License.
 ///////////////////////////////////////////////////////////////
 
-= Zest™ v{revnumber} User Guide =
+= Polygene™ v{revnumber} User Guide =
 
-:qi4j-version: {revnumber}
-:qi4j-buildnumber: {revnumber}
-:qi4j-git-tag: {gitversion}
+:polygene-version: {revnumber}
+:polygene-buildnumber: {revnumber}
+:polygene-git-tag: {gitversion}
 
 
 :leveloffset: {level2}
diff --git a/manual/src/docs/userguide/libraries.txt b/manual/src/docs/userguide/libraries.txt
index b13ac39..b4bcce6 100644
--- a/manual/src/docs/userguide/libraries.txt
+++ b/manual/src/docs/userguide/libraries.txt
@@ -24,22 +24,14 @@
 
 == Overview ==
 
-The Zest™ Libraries are of varying maturity level and we try to maintain a STATUS (dev-status.xml) file indicating
+The Polygene™ Libraries are of varying maturity level and we try to maintain a STATUS (dev-status.xml) file indicating
 how good the codebase, documentation and unit tests are for each of the libraries. This is highly subjective and
 potentially different individuals will judge this differently, but at least it gives a ballpark idea of the situation
 for our users.
 
 :leveloffset: 2
 
-include::../../../../libraries/lang-groovy/src/docs/lang-groovy.txt[]
-
-:leveloffset: 2
-
-include::../../../../libraries/lang-javascript/src/docs/lang-javascript.txt[]
-
-:leveloffset: 2
-
-include::../../../../libraries/lang-scala/src/docs/lang-scala.txt[]
+include::../../../../libraries/scripting/src/docs/scripting.txt[]
 
 :leveloffset: 2
 
@@ -55,14 +47,6 @@
 
 :leveloffset: 2
 
-include::../../../../libraries/conversion/src/docs/conversion.txt[]
-
-:leveloffset: 2
-
-include::../../../../libraries/eventsourcing/src/docs/eventsourcing.txt[]
-
-:leveloffset: 2
-
 include::../../../../libraries/fileconfig/src/docs/fileconfig.txt[]
 
 :leveloffset: 2
@@ -87,10 +71,6 @@
 
 :leveloffset: 2
 
-include::../../../../libraries/metrics/src/docs/metrics.txt[]
-
-:leveloffset: 2
-
 include::../../../../libraries/osgi/src/docs/osgi.txt[]
 
 :leveloffset: 2
@@ -115,7 +95,7 @@
 
 :leveloffset: 2
 
-include::../../../../libraries/scheduler/src/docs/scheduler.txt[]
+include::../../../../libraries/restlet/src/docs/restlet.txt[]
 
 :leveloffset: 2
 
diff --git a/manual/src/docs/userguide/preface.txt b/manual/src/docs/userguide/preface.txt
index 668d5b1..5831837 100644
--- a/manual/src/docs/userguide/preface.txt
+++ b/manual/src/docs/userguide/preface.txt
@@ -20,19 +20,19 @@
 [[preface, Preface]]
 = Preface =
 
-This is the reference manual for Zest™ version {qi4j-version}, written by members of the Zest™ Community.
+This is the reference manual for Polygene™ version {polygene-version}, written by members of the Polygene™ Community.
 
 The main parts of the manual are:
 
-* <<introduction>> -- introducing Composite Oriented Programming concepts and Zest.
-* <<tutorials>> -- learn how to use Zest.
-* <<core-api>> -- detailed information on how to use Zest.
-* <<libraries>> -- detailed information on the many libraries available for Zest.
-* <<extensions>> -- detailed information each of the Zest™ extensions, such as entity stores,
+* <<introduction>> -- introducing Composite Oriented Programming concepts and Polygene.
+* <<tutorials>> -- learn how to use Polygene.
+* <<core-api>> -- detailed information on how to use Polygene.
+* <<libraries>> -- detailed information on the many libraries available for Polygene.
+* <<extensions>> -- detailed information each of the Polygene™ extensions, such as entity stores,
 indexing, caching and runtime metrics.
 
 The material is practical, technical, and focused on answering specific questions. 
-It addresses how things work, what to do and what to avoid to successfully use Zest™ in domain rich applications.
+It addresses how things work, what to do and what to avoid to successfully use Polygene™ in domain rich applications.
  
 The goal is to be thumb-through and rule-of-thumb friendly.
 
@@ -40,7 +40,7 @@
 When possible, the sections distill "rules of thumb" which you can keep in mind whenever you wander out of the house
 without this manual in your back pocket.
 
-The included code examples are executed when Zest™ is built and tested.
+The included code examples are executed when Polygene™ is built and tested.
 
 _Who should read this?_
 
diff --git a/manual/src/docs/userguide/tools.txt b/manual/src/docs/userguide/tools.txt
index 2a4b1e0..b621669 100644
--- a/manual/src/docs/userguide/tools.txt
+++ b/manual/src/docs/userguide/tools.txt
@@ -24,14 +24,19 @@
 
 == Overview ==
 
-The Zest™ SDK comes with usefull development tools. Theses tools can come in
+The Polygene™ SDK comes with usefull development tools. Theses tools can come in
 handy when assembled into your <<def-application>> in development
 <<def-application-mode>>.
 
-The tools are available in the +tools/+ directory of the Zest™ SDK.
+The tools are available in the +tools/+ directory of the Polygene™ SDK.
 
 :leveloffset: 2
 
-include::../../../../tools/envisage/src/docs/envisage.txt[]
+include:: ../../../tools/src/docs/yeoman_polygene.txt[]
+
+:leveloffset: 2
+
+include:: ../../../tools/src/docs/envisage.txt[]
+// include:: ../../../tools/envisage/src/docs/envisage.txt[]
 
 :leveloffset: 2
diff --git a/manual/src/docs/website/docinfo.xml b/manual/src/docs/website/docinfo.xml
index a8f6a82..4594096 100644
--- a/manual/src/docs/website/docinfo.xml
+++ b/manual/src/docs/website/docinfo.xml
@@ -1,16 +1,19 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
diff --git a/manual/src/docs/website/home.txt b/manual/src/docs/website/home.txt
index 6b82cff..b280abb 100644
--- a/manual/src/docs/website/home.txt
+++ b/manual/src/docs/website/home.txt
@@ -19,33 +19,33 @@
 
 :leveloffset: 1
 
-[[home,Zest™ Home Page]]
-= Zest™ =
+[[home,Polygene™ Home Page]]
+= Polygene™ =
 
 [IMPORTANT]
-.Zest™ {revnumber}
+.{revnumber}
 ====
-This is the documentation for *Zest™ {revnumber}*. Use the version switcher on the left to browse other
+This is the documentation for *Polygene™ {revnumber}*. Use the version switcher on the left to browse other
 versions documentation.
 ====
 
-== What is Apache Zest™ ? ==
-The short answer is that Apache Zest™ is a framework for domain centric application development, including evolved
+== What is Apache Polygene™ ? ==
+The short answer is that Apache Polygene™ is a framework for domain centric application development, including evolved
 concepts from http://en.wikipedia.org/wiki/Aspect-oriented_programming[AOP],
 http://en.wikipedia.org/wiki/Dependency_injection[DI] and http://en.wikipedia.org/wiki/Domain-driven_design[DDD].
 
-Zest™ is an implementation of Composite Oriented Programming, using the standard Java platform, without the use of
+Polygene™ is an implementation of Composite Oriented Programming, using the standard Java platform, without the use of
 any pre-processors or new language elements. Everything you know from Java still applies and you can leverage both
 your experience and toolkits to become more productive with Composite Oriented Programming today.
 
-Moreover, Zest™ enables Composite Oriented Programming on the Java platform, including both Java and Scala as primary
+Moreover, Polygene™ enables Composite Oriented Programming on the Java platform, including both Java and Scala as primary
 languages as well as many of the plethora of languages running on the JVM as bridged languages.
 
 We strongly recommend the <<intro, introduction>> section.
 
 == Brief History ==
-Apache Zest™ started its life in 2007 as Qi4j™, initially at OPS4J's infrastructure and later on GitHub.
-In March 2015, Apache Zest™ was created with the Qi4j™ codebase as the base, existing Apache Members as the
+Apache Polygene™ started its life in 2007 as Qi4j™, initially at OPS4J's infrastructure and later on GitHub.
+In March 2015, Apache Polygene™ was created with the Qi4j™ codebase as the base, existing Apache Members as the
 bootstrap Project Management Committee (PMC).
 
 image:intro-qi.png["Qi",align="center"]
@@ -54,4 +54,3 @@
 facets and history of Qi, so we refer the interested to read the http://en.wikipedia.org/wiki/Qi[lengthy article] at
 Wikipedia. For us, Qi is the force/energy within the body, in this case the Java platform. Something that makes Java
 so much better, if it is found and channeled into a greater good.
-
diff --git a/manual/src/docs/website/intro.txt b/manual/src/docs/website/intro.txt
index 8b86d4a..fe240f1 100644
--- a/manual/src/docs/website/intro.txt
+++ b/manual/src/docs/website/intro.txt
@@ -28,6 +28,10 @@
 
 :leveloffset: 2
 
+include::../../../../tools/src/docs/yeoman_polygene.txt[]
+
+:leveloffset: 2
+
 include::../../../../tutorials/introduction/src/docs/background.txt[]
 
 :leveloffset: 2
@@ -36,7 +40,7 @@
 
 :leveloffset: 2
 
-// include::../../../../tutorials/introduction/src/docs/qi4j-cop.txt[]
+// include::../../../../tutorials/introduction/src/docs/polygene-cop.txt[]
 //
 // :leveloffset: 2
 
diff --git a/manual/src/docs/website/javadocs.txt b/manual/src/docs/website/javadocs.txt
index 690ee09..f6d406f 100644
--- a/manual/src/docs/website/javadocs.txt
+++ b/manual/src/docs/website/javadocs.txt
@@ -24,11 +24,11 @@
 
 == JavaDocs ==
 
-In this section you will find links to JavaDocs corresponding to this Apache Zest™ (Java Edition) version ({revnumber}), to some alias versions, and finally, to previous releases.
+In this section you will find links to JavaDocs corresponding to this Apache Polygene™ (Java Edition) version ({revnumber}), to some alias versions, and finally, to previous releases.
 
-=== Apache Zest™ (Java Edition) {revnumber} ===
+=== Apache Polygene™ (Java Edition) {revnumber} ===
 
-// JavaDocs for Apache Zest™ (Java Edition) {revnumber}:
+// JavaDocs for Apache Polygene™ (Java Edition) {revnumber}:
 
 * link:javadocs/index.html[Release {revnumber}]
 
@@ -37,24 +37,25 @@
 
 Links to _"alias versions"_ JavaDocs:
 
-* https://zest.apache.org/java/latest/javadocs/[Latest Release (`master` branch)]
-* https://zest.apache.org/java/develop/javadocs/[Development (`develop` branch)]
+* https://polygene.apache.org/java/latest/javadocs/[Latest Release (`master` branch)]
+* https://polygene.apache.org/java/develop/javadocs/[Development (`develop` branch)]
 
 
 === Previous Releases ===
 
 Archived JavaDocs of previous releases:
 
-* https://zest.apache.org/java/2.0/javadocs/[Release 2.0]
-* https://zest.apache.org/java/1.4.1/javadocs/[Release 1.4.1]
-* https://zest.apache.org/java/1.4/javadocs/[Release 1.4]
-* https://zest.apache.org/java/1.3/javadocs/[Release 1.3]
+* https://polygene.apache.org/java/2.1/javadocs/[Release 2.1]
+* https://polygene.apache.org/java/2.0/javadocs/[Release 2.0]
+* https://polygene.apache.org/java/1.4.1/javadocs/[Release 1.4.1]
+* https://polygene.apache.org/java/1.4/javadocs/[Release 1.4]
+* https://polygene.apache.org/java/1.3/javadocs/[Release 1.3]
 * Release 1.2
-** https://zest.apache.org/java/1.2/javadocs/api[Core API]
-** https://zest.apache.org/java/1.2/javadocs/bootstrap[Core Bootstrap]
-** https://zest.apache.org/java/1.2/javadocs/spi[Core SPI]
+** https://polygene.apache.org/java/1.2/javadocs/api[Core API]
+** https://polygene.apache.org/java/1.2/javadocs/bootstrap[Core Bootstrap]
+** https://polygene.apache.org/java/1.2/javadocs/spi[Core SPI]
 * Release 1.0
-** https://zest.apache.org/java/1.0/javadocs/api[Core API]
-** https://zest.apache.org/java/1.0/javadocs/bootstrap[Core Bootstrap]
-** https://zest.apache.org/java/1.0/javadocs/spi[Core SPI]
+** https://polygene.apache.org/java/1.0/javadocs/api[Core API]
+** https://polygene.apache.org/java/1.0/javadocs/bootstrap[Core Bootstrap]
+** https://polygene.apache.org/java/1.0/javadocs/spi[Core SPI]
 
diff --git a/manual/src/docs/website/related.txt b/manual/src/docs/website/related.txt
index 453d078..fdc12d3 100644
--- a/manual/src/docs/website/related.txt
+++ b/manual/src/docs/website/related.txt
@@ -20,9 +20,9 @@
 [[related,Related publications and projects]]
 = Related publications & projects =
 
-Zest™ addresses a wide range of concepts, the related publications and projects you'll find in this section span accross
+Polygene™ addresses a wide range of concepts, the related publications and projects you'll find in this section span accross
 all theses concepts. Please note that this is not an exhaustive list but only some pointers to help you understand which
-principles Zest™ is based on.
+principles Polygene™ is based on.
 
 
 == Publications ==
diff --git a/manual/src/docs/website/resources/css/polygene.css b/manual/src/docs/website/resources/css/polygene.css
new file mode 100644
index 0000000..d512429
--- /dev/null
+++ b/manual/src/docs/website/resources/css/polygene.css
@@ -0,0 +1,825 @@
+/*
+ *  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.
+ *
+ *
+ */
+
+span.remark
+{
+    background: yellow;
+}
+
+td p
+{
+    margin: 0.125em 0;
+}
+
+#disqus_thread
+{
+    max-width: 40em;
+}
+
+body #toolbar_item command_help
+{
+    /* display: none !important; */
+}
+
+pre {
+    max-width: 55em;
+    overflow: scroll;
+}
+
+.syntaxhighlighter a,
+.syntaxhighlighter div,
+.syntaxhighlighter code,
+.syntaxhighlighter table,
+.syntaxhighlighter table td,
+.syntaxhighlighter table tr,
+.syntaxhighlighter table tbody,
+.syntaxhighlighter table thead,
+.syntaxhighlighter table caption,
+.syntaxhighlighter textarea
+{
+    font-size: 12px !important;
+    font-family: Consolas, Monaco, "Bitstream Vera Sans Mono", monospace !important;
+    line-height: 14px !important;
+}
+
+.syntaxhighlighter {
+    background-color: rgba(11,117,188,0.1) !important;
+    /*
+    overflow: visible !important;
+    */
+    border: 1px solid #0b75bc;
+    padding: 8px;
+    -moz-border-radius: 5px;
+    -webkit-border-radius: 5px;
+    border-radius: 5px;
+}
+
+.syntaxhighlighter .line.alt1 {
+    background-color: rgba(11,117,188,0.05) !important;
+}
+.syntaxhighlighter .line.alt2 {
+    background-color:  rgba(11,117,188,0.1)  !important;
+}
+
+html
+{
+    text-align: center;
+}
+
+html body
+{
+    background: url("bg.png");
+    margin: 0 auto;
+    text-align: left;
+}
+
+div.navheader, div.navfooter {
+    padding: 0 5%;
+}
+
+body, div.navheader th, div.navheader td, div.navfooter td
+{
+    font-family: Georgia, "Times New Roman", Times, serif;
+    color: #4c4c4c;
+}
+
+a {
+    color: #0b75bc;
+}
+
+a:hover {
+    text-decoration: none;
+}
+
+a:visited {
+    color: #0b75bc;
+    /* color: #08568a; */
+}
+
+hr {
+    border-color: #0b75bc;
+    border-style: solid;
+}
+
+.navheader a {
+    color: #acacac;
+    text-decoration: none;
+    font-family: Helvetica, Arial, sans-serif;
+}
+
+.navheader a:hover, .navfooter a:hover {
+    text-decoration: underline;
+}
+
+h1, h2, h3, h4, h5, h6,
+div.toc p b,
+div.important th, div.info th, div.tip th,
+div.warning th, div.note th, div.caution th,
+p.legalnotice-title,
+div.refnamediv p,
+div.sidebar p.title,
+th,
+div.table-contents td p span.strong strong,
+tr.question td b p
+{
+    color: #0b75bc;
+    font-family: Helvetica, Arial, sans-serif;
+    text-shadow: 0 1px 0 #fff;
+}
+
+
+.book, .chapter, .part {
+    width:90%;
+    margin: 0 auto;
+}
+
+td p strong
+{
+    font-size: 1.067em;
+}
+
+tr.question td b p
+{
+    font-size: 1em;
+    margin: 0.5em 0 0 0;
+}
+
+tr.question td
+{
+    padding: 0;
+}
+
+tr.answer td, tr.answer td p
+{
+    padding-top: 0;
+}
+
+tr.answer td
+{
+    padding-left: 1em;
+}
+
+div.navheader
+{
+    height: 50px;
+    background: url(../../../../resources/css/navHead_bg.png) repeat-x;
+}
+
+div.navheader hr
+{
+    display: none;
+}
+
+div.refentry body h2.title, div.refentry body h1.title, div.refentry div.refnamediv p,
+body > div.section h1, body > div.section h2,
+body > div.part h1, body > div.part h2,
+body > div.chapter h1, body > div.chapter h2,
+body > div.book h1,
+body > div.preface h2,
+body > div.appendix h2
+{
+    border-bottom: none;
+    margin-top: 2.2em;
+    margin-bottom: .7em;
+}
+
+div.legalnotice
+{
+    padding-top: 3em;
+}
+
+p.legalnotice-title b
+{
+    font-size: 1.5em;
+    font-style: normal;
+    font-weight: bold;
+}
+
+p.legalnotice-title
+{
+    margin-bottom: 2em;
+}
+
+body > div.book h1.title
+{
+    margin-top: 0.5em;
+    padding-top: 0;
+    margin-bottom: 0;
+}
+
+div.part h1.title
+{
+    margin-top: 1.5em;
+}
+
+.book div.titlepage {
+    position: absolute;
+    top: 40px;
+    background: url(logo.png) no-repeat left top;
+    min-height: 250px;
+    padding-left: 150px;
+}
+
+.book div.titlepage .authorgroup {
+    font-size: 150%;
+}
+
+.book div.titlepage hr {
+    display: none;
+}
+
+div.titlepage h3.corpauthor
+{
+}
+
+div.refnamediv
+{
+    padding-top: 24px;
+    margin-bottom: 24px;
+}
+
+div.refsynopsisdiv h2, div.refsect1 h2
+{
+    border-bottom: none;
+}
+
+div.titlepage h3.corpauthor a.ulink, div.titlepage h3.corpauthor a.ulink:link,
+div.titlepage h3.corpauthor a.ulink:visited, div.titlepage h3.corpauthor a.ulink:hover
+div.titlepage h3.corpauthor a.ulink:focus, div.titlepage h3.corpauthor a.ulink:active
+{
+    color: #dddddd;
+    text-decoration: none;
+    font-style: normal;
+    padding-left: 0.6em;
+}
+
+div.refnamediv h2
+{
+    display: none;
+}
+
+div.refnamediv p
+{
+    font-size: 1em;
+    font-weight: bold;
+    margin-top: 3em;
+    margin-bottom: 2em;
+    width: 60%;
+    line-height: 1.2;
+}
+
+p, li, dt, div.navheader th, div.navheader td, div.navfooter td
+{
+    font-family: Georgia, "Times New Roman", Times, serif;
+    font-size: .9375em;
+    text-shadow: 0 1px 0 #fff;
+}
+
+p, ul, ol
+{
+    margin-top: 0;
+    margin-bottom: 1em;
+}
+
+li p
+{
+    margin-bottom: 0.5em;
+}
+
+div.list-of-figures p, div.list-of-tables p
+{
+    margin-top: 1.5em;
+}
+
+div.list-of-figures p b, div.list-of-tables p b, div.sidebar p b
+{
+    font-style: normal;
+    font-weight: bold;
+}
+
+div.toc
+{
+    margin-bottom: 1em;
+}
+
+.book .toc {
+    margin-top: 220px;
+}
+
+div.toc p {
+    width: 100%;
+    font-family: Helvetica, Arial, sans-serif;
+    color: #0b75bc;
+    font-size: 120%;
+    border-bottom: 1px solid #0b75bc;
+}
+
+div.toc a, div.toc a:visited {
+    color: #0b75bc;
+}
+
+div.toc dt {
+    margin-bottom: 8px;
+}
+
+div.toc dl dl {
+    margin: 5px 0;
+}
+
+p.copyright
+{
+    margin: 0;
+    padding: 10px 0 5px 0;
+    text-align: center;
+    max-width: 100%;
+    background: #0b75bc url(../../../../resources/css/copyright_bg.png) repeat-x top;
+    color: #fff;
+    text-shadow: none;
+    border-bottom: 1px solid #095e96;
+}
+
+.titlepage p.copyright {
+    background: none;
+    border: none;
+    text-align: left;
+    color: #0b75bc;
+}
+
+code.literal
+{
+    font-family: Consolas, Monaco, monospace;
+    font-size: .9375em;
+}
+
+td code.literal
+{
+    font-size: .8em;
+}
+
+li
+{
+    line-height: 1.3em;
+}
+
+p
+{
+    line-height: 1.6em;
+}
+
+.toc p {
+    max-width: 100%;
+}
+
+ul, ol
+{
+    max-width: 38em;
+}
+
+div.sidebar
+{
+    max-width: 30em;
+    padding: 0.67em 1em;
+    background: #c1d5d9 url("../../../../resources/css/content-bg.png") repeat-x;
+}
+
+div.sidebar p.title
+{
+    margin: 0;
+}
+
+div.sidebar ul
+{
+    margin-top: 0.3em;
+    margin-bottom: 0.3em;
+}
+
+p b, div.figure p.title b, div.table p.title b
+{
+    font-style: italic;
+    font-weight: normal;
+}
+
+/* BEGIN SIDE NOTES */
+div.important, div.info, div.tip, div.note,
+div.warning, div.caution
+{
+    float: right;
+    max-width: 20em;
+    margin: 1em 0 1em 1em !important;
+    padding: 1em !important;
+    font-size: 0.9em;
+    -moz-border-radius: 5px;
+    -webkit-border-radius: 5px;
+    border-radius: 5px;
+}
+div.important, div.info, div.tip, div.note
+{
+    background-color:  rgba(11, 117, 188, 0.1) !important;
+    border: 1px solid #0b75bc;
+}
+div.warning
+{
+    background-color:  rgba(188, 117, 11, 0.1) !important;
+    border: 1px solid #bc750b;
+}
+div.caution
+{
+    background-color:  rgba(188, 11, 11, 0.1) !important;
+    border: 1px solid #bc0b0b;
+}
+div.important h3, div.info h3, div.tip h3, div.note h3,
+div.warning h3, div.caution h3
+{
+    margin: 0 0 0.5em 0 !important;
+    line-height: 50px;
+    padding-right: 55px;
+    background-position: top right !important;
+    background-repeat: no-repeat !important;
+}
+div.important h3
+{
+    background-image: url("important.png");
+}
+div.info h3, div.tip h3
+{
+    background-image: url("tip.png");
+}
+div.note h3
+{
+    background-image: url("note.png");
+}
+div.warning h3
+{
+    background-image: url("warning.png");
+    color: #bc750b;
+}
+div.caution h3
+{
+    background-image: url("caution.png");
+    color: #bc0b0b;
+}
+div.important p, div.info p, div.tip p, div.note p,
+div.warning p, div.caution p
+{
+    margin: 0 0 0.5em 0 !important;
+}
+/* END SIDE NOTES */
+
+
+div.table, div.informaltable
+{
+    width: 100%;
+    clear: both;
+}
+div.table div.table-contents, div.informaltable div.table-contents
+{
+    background-color: rgba(11,117,188,0.1) !important;
+    border: 1px solid #0b75bc;
+    padding: 8px;
+    -moz-border-radius: 5px;
+    -webkit-border-radius: 5px;
+    border-radius: 5px;
+}
+
+div.table table, div.informaltable table
+{
+    width: 100%;
+    border: none;
+    border-collapse: collapse;
+}
+
+td, th
+{
+    padding: 2px 4px;
+}
+
+div.table table, div.informaltable table,
+div.table table th, div.informaltable table th,
+div.table table td, div.informaltable table td,
+div.table table tr, div.informaltable table tr,
+div.table table tbody, div.informaltable table tbody,
+div.table table thead, div.informaltable table thead,
+div.table table tfoot, div.informaltable table tfoot
+{
+    font-size: 15px;
+    text-align: center;
+}
+div.table table td,
+div.informaltable table td,
+div.table table th,
+div.informaltable table th
+{
+    border: 1px solid #3D8AC9;
+}
+div.table table tr:first-child th,
+div.informaltable table tr:first-child th
+{
+  border-top: 0;
+}
+div.table table tr:last-child td,
+div.informaltable table tr:last-child td
+{
+  border-bottom: 0;
+}
+div.table table tr td:first-child,
+div.informaltable table tr td:first-child,
+div.table table tr th:first-child,
+div.informaltable table tr th:first-child
+{
+  border-left: 0;
+}
+div.table table tr td:last-child,
+div.informaltable table tr td:last-child,
+div.table table tr th:last-child,
+div.informaltable table tr th:last-child
+{
+  border-right: 0;
+}
+
+div.queryresult table tbody td p code.literal
+{
+    color: #000000;
+}
+
+div.queryresult table thead tr,
+div.queryresult table tfoot tr
+{
+    background: #cad9dc;
+}
+
+div.queryresult table tbody
+{
+    background: #d1dee1;
+}
+
+div.queryresult table tbody tr.evenresult
+{
+    background: #dfe8eb;
+}
+
+div.queryresult table thead th
+{
+    font-size: 0.9375em;
+}
+
+div.queryresult table tfoot th
+{
+    font-size: 0.8125em;
+    font-weight: normal;
+}
+
+div.table table th, div.informaltable table th
+{
+    color: #3D8AC9;
+}
+div.table-contents td p span.strong strong
+{
+    color: #333333;
+}
+
+div.informaltable span.strong strong
+{
+    font-weight: normal;
+    font-style: italic;
+}
+
+div.informalfigure a img, div.figure a img
+{
+    border: none;
+}
+
+/* additional styles for slides */
+
+div.slide h1
+{
+    margin-top: 40px;
+    margin-bottom: 1em;
+    color: white;
+    border-bottom: none;
+}
+
+div.slide p, div.slide li
+{
+    font-size: 1.25em;
+}
+
+.navfooter{
+    background: #0b75bc;
+    border: 1px solid #0b75bc;
+    border-top: 1px solid #3c91c9;
+}
+
+.navfooter a {
+    color: #fff;
+    color: rgba(255,255,255,0.8);
+    text-decoration: none;
+    text-shadow: none;
+    font-family: Helvetica, Arial, sans-serif;
+}
+
+h1 { font-size: 1.8em; margin-bottom: 1em; }
+h2 { font-size: 1.6em; margin-bottom: 1em; }
+h3 { font-size: 1.4em; margin-bottom: 1em; }
+h4 { font-size: 1.2em; margin-bottom: 0.5em; }
+h5 { font-size: 1em; margin-bottom: 0.5em; }
+
+.devstatus-code-none {
+    border: solid black 2px;
+    margin-right: 5px !important;
+    display: block;
+    float: right;
+    width: 4em;
+    font-size: 10pt !important;
+    font-weight: bolder;
+    font-family: "Courier New", "Courier", monospace !important;
+    background-color: #f08080;
+    text-align: center;
+    text-shadow: none  !important;
+}
+
+.devstatus-code-early {
+    border: solid black 2px;
+    margin-right: 5px !important;
+    display: block;
+    float: right;
+    width: 4em;
+    font-size: 10pt !important;
+    font-weight: bolder;
+    font-family: "Courier New", "Courier", monospace !important;
+    background-color: orange;
+    text-align: center;
+    text-shadow: none  !important;
+}
+.devstatus-code-beta {
+    border: solid black 2px;
+    margin-right: 5px !important;
+    display: block;
+    float: right;
+    width: 4em;
+    font-size: 10pt !important;
+    font-weight: bold;
+    font-family: "Courier New", "Courier", monospace !important;
+    background-color: yellow;
+    text-align: center;
+    text-shadow: none  !important;
+}
+.devstatus-code-stable {
+    border: solid black 2px;
+    margin-right: 5px !important;
+    display: block;
+    float: right;
+    width: 4em;
+    font-size: 10pt !important;
+    font-weight: bolder;
+    font-family: "Courier New", "Courier", monospace !important;
+    background-color: #adff2f;
+    text-align: center;
+    text-shadow: none  !important;
+}
+.devstatus-code-mature {
+    border: solid black 2px;
+    margin-right: 5px !important;
+    display: block;
+    float: right;
+    width: 4em;
+    font-size: 10pt !important;
+    font-weight: bolder;
+    font-family: "Courier New", "Courier", monospace !important;
+    background-color: #7cfc00;
+    text-align: center;
+    text-shadow: none  !important;
+}
+
+.devstatus-docs-none {
+    border: solid black 2px;
+    margin-right: 5px !important;
+    display: block;
+    float: right;
+    width: 4em;
+    font-size: 10pt !important;
+    font-weight: bolder;
+    font-family: "Courier New", "Courier", monospace !important;
+    background-color: #f08080;
+    text-align: center;
+    text-shadow: none  !important;
+}
+
+.devstatus-docs-brief {
+    border: solid black 2px;
+    margin-right: 5px !important;
+    display: block;
+    float: right;
+    width: 4em;
+    font-size: 10pt !important;
+    font-weight: bolder;
+    font-family: "Courier New", "Courier", monospace !important;
+    background-color: yellow;
+    text-align: center;
+    text-shadow: none  !important;
+}
+.devstatus-docs-good {
+    border: solid black 2px;
+    margin-right: 5px !important;
+    display: block;
+    float: right;
+    width: 4em;
+    font-size: 10pt !important;
+    font-weight: bolder;
+    font-family: "Courier New", "Courier", monospace !important;
+    background-color: #adff2f;
+    text-align: center;
+    text-shadow: none  !important;
+}
+.devstatus-docs-complete {
+    border: solid black 2px;
+    margin-right: 5px !important;
+    display: block;
+    float: right;
+    width: 4em;
+    font-size: 10pt !important;
+    font-weight: bolder;
+    font-family: "Courier New", "Courier", monospace !important;
+    background-color: #7cfc00;
+    text-align: center;
+    text-shadow: none  !important;
+}
+
+.devstatus-tests-none {
+    border: solid black 2px;
+    margin-right: 5px !important;
+    display: block;
+    float: right;
+    width: 4em;
+    font-size: 10pt !important;
+    font-weight: bolder;
+    font-family: "Courier New", "Courier", monospace !important;
+    background-color: #f08080;
+    text-align: center;
+    text-shadow: none  !important;
+}
+
+.devstatus-tests-some {
+    border: solid black 2px;
+    margin-right: 5px !important;
+    display: block;
+    float: right;
+    width: 4em;
+
+    font-size: 10pt !important;
+    font-weight: bolder;
+    font-family: "Courier New", "Courier", monospace !important;
+    background-color: yellow;
+    text-align: center;
+    text-shadow: none  !important;
+}
+.devstatus-tests-good {
+    border: solid black 2px;
+    margin-right: 5px !important;
+    display: block;
+    float: right;
+    width: 4em;
+    font-size: 10pt !important;
+    font-weight: bolder;
+    font-family: "Courier New", "Courier", monospace !important;
+    background-color: #adff2f;
+    text-align: center;
+    text-shadow: none  !important;
+}
+
+.devstatus-tests-complete {
+    border: solid black 2px;
+    margin-right: 5px !important;
+    display: block;
+    float: right;
+    width: 4em;
+    font-size: 10pt !important;
+    font-weight: bolder;
+    font-family: "Courier New", "Courier", monospace !important;
+    background-color: #7cfc00;
+    text-align: center;
+    text-shadow: none  !important;
+}
+
+
+.section .variablelist dt .term {
+    font-weight: bolder;
+    font-family: Consolas, Monaco, monospace;
+    background: #DEDEDE;
+}
diff --git a/manual/src/docs/website/resources/css/qi4j.css b/manual/src/docs/website/resources/css/qi4j.css
deleted file mode 100644
index d302aae..0000000
--- a/manual/src/docs/website/resources/css/qi4j.css
+++ /dev/null
@@ -1,824 +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.
- */
-
-span.remark
-{
-    background: yellow;
-}
-
-td p
-{
-    margin: 0.125em 0;
-}
-
-#disqus_thread
-{
-    max-width: 40em;
-}
-
-body #toolbar_item command_help
-{
-    /* display: none !important; */
-}
-
-pre {
-    max-width: 55em;
-    overflow: scroll;
-}
-
-.syntaxhighlighter a,
-.syntaxhighlighter div,
-.syntaxhighlighter code,
-.syntaxhighlighter table,
-.syntaxhighlighter table td,
-.syntaxhighlighter table tr,
-.syntaxhighlighter table tbody,
-.syntaxhighlighter table thead,
-.syntaxhighlighter table caption,
-.syntaxhighlighter textarea
-{
-    font-size: 12px !important;
-    font-family: Consolas, Monaco, "Bitstream Vera Sans Mono", monospace !important;
-    line-height: 14px !important;
-}
-
-.syntaxhighlighter {
-    background-color: rgba(11,117,188,0.1) !important;
-    /*
-    overflow: visible !important;
-    */
-    border: 1px solid #0b75bc;
-    padding: 8px;
-    -moz-border-radius: 5px;
-    -webkit-border-radius: 5px;
-    border-radius: 5px;
-}
-
-.syntaxhighlighter .line.alt1 {
-    background-color: rgba(11,117,188,0.05) !important;
-}
-.syntaxhighlighter .line.alt2 {
-    background-color:  rgba(11,117,188,0.1)  !important;
-}
-
-html
-{
-    text-align: center;
-}
-
-html body
-{
-    background: url("bg.png");
-    margin: 0 auto;
-    text-align: left;
-}
-
-div.navheader, div.navfooter {
-    padding: 0 5%;
-}
-
-body, div.navheader th, div.navheader td, div.navfooter td
-{
-    font-family: Georgia, "Times New Roman", Times, serif;
-    color: #4c4c4c;
-}
-
-a {
-    color: #0b75bc;
-}
-
-a:hover {
-    text-decoration: none;
-}
-
-a:visited {
-    color: #0b75bc;
-    /* color: #08568a; */
-}
-
-hr {
-    border-color: #0b75bc;
-    border-style: solid;
-}
-
-.navheader a {
-    color: #acacac;
-    text-decoration: none;
-    font-family: Helvetica, Arial, sans-serif;
-}
-
-.navheader a:hover, .navfooter a:hover {
-    text-decoration: underline;
-}
-
-h1, h2, h3, h4, h5, h6,
-div.toc p b,
-div.important th, div.info th, div.tip th,
-div.warning th, div.note th, div.caution th,
-p.legalnotice-title,
-div.refnamediv p,
-div.sidebar p.title,
-th,
-div.table-contents td p span.strong strong,
-tr.question td b p
-{
-    color: #0b75bc;
-    font-family: Helvetica, Arial, sans-serif;
-    text-shadow: 0 1px 0 #fff;
-}
-
-
-.book, .chapter, .part {
-    width:90%;
-    margin: 0 auto;
-}
-
-td p strong
-{
-    font-size: 1.067em;
-}
-
-tr.question td b p
-{
-    font-size: 1em;
-    margin: 0.5em 0 0 0;
-}
-
-tr.question td
-{
-    padding: 0;
-}
-
-tr.answer td, tr.answer td p
-{
-    padding-top: 0;
-}
-
-tr.answer td
-{
-    padding-left: 1em;
-}
-
-div.navheader
-{
-    height: 50px;
-    background: url(../../../../resources/css/navHead_bg.png) repeat-x;
-}
-
-div.navheader hr
-{
-    display: none;
-}
-
-div.refentry body h2.title, div.refentry body h1.title, div.refentry div.refnamediv p,
-body > div.section h1, body > div.section h2,
-body > div.part h1, body > div.part h2,
-body > div.chapter h1, body > div.chapter h2,
-body > div.book h1,
-body > div.preface h2,
-body > div.appendix h2
-{
-    border-bottom: none;
-    margin-top: 2.2em;
-    margin-bottom: .7em;
-}
-
-div.legalnotice
-{
-    padding-top: 3em;
-}
-
-p.legalnotice-title b
-{
-    font-size: 1.5em;
-    font-style: normal;
-    font-weight: bold;
-}
-
-p.legalnotice-title
-{
-    margin-bottom: 2em;
-}
-
-body > div.book h1.title
-{
-    margin-top: 0.5em;
-    padding-top: 0;
-    margin-bottom: 0;
-}
-
-div.part h1.title
-{
-    margin-top: 1.5em;
-}
-
-.book div.titlepage {
-    position: absolute;
-    top: 40px;
-    background: url(logo.png) no-repeat left top;
-    min-height: 250px;
-    padding-left: 150px;
-}
-
-.book div.titlepage .authorgroup {
-    font-size: 150%;
-}
-
-.book div.titlepage hr {
-    display: none;
-}
-
-div.titlepage h3.corpauthor
-{
-}
-
-div.refnamediv
-{
-    padding-top: 24px;
-    margin-bottom: 24px;
-}
-
-div.refsynopsisdiv h2, div.refsect1 h2
-{
-    border-bottom: none;
-}
-
-div.titlepage h3.corpauthor a.ulink, div.titlepage h3.corpauthor a.ulink:link,
-div.titlepage h3.corpauthor a.ulink:visited, div.titlepage h3.corpauthor a.ulink:hover
-div.titlepage h3.corpauthor a.ulink:focus, div.titlepage h3.corpauthor a.ulink:active
-{
-    color: #dddddd;
-    text-decoration: none;
-    font-style: normal;
-    padding-left: 0.6em;
-}
-
-div.refnamediv h2
-{
-    display: none;
-}
-
-div.refnamediv p
-{
-    font-size: 1em;
-    font-weight: bold;
-    margin-top: 3em;
-    margin-bottom: 2em;
-    width: 60%;
-    line-height: 1.2;
-}
-
-p, li, dt, div.navheader th, div.navheader td, div.navfooter td
-{
-    font-family: Georgia, "Times New Roman", Times, serif;
-    font-size: .9375em;
-    text-shadow: 0 1px 0 #fff;
-}
-
-p, ul, ol
-{
-    margin-top: 0;
-    margin-bottom: 1em;
-}
-
-li p
-{
-    margin-bottom: 0.5em;
-}
-
-div.list-of-figures p, div.list-of-tables p
-{
-    margin-top: 1.5em;
-}
-
-div.list-of-figures p b, div.list-of-tables p b, div.sidebar p b
-{
-    font-style: normal;
-    font-weight: bold;
-}
-
-div.toc
-{
-    margin-bottom: 1em;
-}
-
-.book .toc {
-    margin-top: 220px;
-}
-
-div.toc p {
-    width: 100%;
-    font-family: Helvetica, Arial, sans-serif;
-    color: #0b75bc;
-    font-size: 120%;
-    border-bottom: 1px solid #0b75bc;
-}
-
-div.toc a, div.toc a:visited {
-    color: #0b75bc;
-}
-
-div.toc dt {
-    margin-bottom: 8px;
-}
-
-div.toc dl dl {
-    margin: 5px 0;
-}
-
-p.copyright
-{
-    margin: 0;
-    padding: 10px 0 5px 0;
-    text-align: center;
-    max-width: 100%;
-    background: #0b75bc url(../../../../resources/css/copyright_bg.png) repeat-x top;
-    color: #fff;
-    text-shadow: none;
-    border-bottom: 1px solid #095e96;
-}
-
-.titlepage p.copyright {
-    background: none;
-    border: none;
-    text-align: left;
-    color: #0b75bc;
-}
-
-code.literal
-{
-    font-family: Consolas, Monaco, monospace;
-    font-size: .9375em;
-}
-
-td code.literal
-{
-    font-size: .8em;
-}
-
-li
-{
-    line-height: 1.3em;
-}
-
-p
-{
-    line-height: 1.6em;
-}
-
-.toc p {
-    max-width: 100%;
-}
-
-ul, ol
-{
-    max-width: 38em;
-}
-
-div.sidebar
-{
-    max-width: 30em;
-    padding: 0.67em 1em;
-    background: #c1d5d9 url("../../../../resources/css/content-bg.png") repeat-x;
-}
-
-div.sidebar p.title
-{
-    margin: 0;
-}
-
-div.sidebar ul
-{
-    margin-top: 0.3em;
-    margin-bottom: 0.3em;
-}
-
-p b, div.figure p.title b, div.table p.title b
-{
-    font-style: italic;
-    font-weight: normal;
-}
-
-/* BEGIN SIDE NOTES */
-div.important, div.info, div.tip, div.note,
-div.warning, div.caution
-{
-    float: right;
-    max-width: 20em;
-    margin: 1em 0 1em 1em !important;
-    padding: 1em !important;
-    font-size: 0.9em;
-    -moz-border-radius: 5px;
-    -webkit-border-radius: 5px;
-    border-radius: 5px;
-}
-div.important, div.info, div.tip, div.note
-{
-    background-color:  rgba(11, 117, 188, 0.1) !important;
-    border: 1px solid #0b75bc;
-}
-div.warning
-{
-    background-color:  rgba(188, 117, 11, 0.1) !important;
-    border: 1px solid #bc750b;
-}
-div.caution
-{
-    background-color:  rgba(188, 11, 11, 0.1) !important;
-    border: 1px solid #bc0b0b;
-}
-div.important h3, div.info h3, div.tip h3, div.note h3,
-div.warning h3, div.caution h3
-{
-    margin: 0 0 0.5em 0 !important;
-    line-height: 50px;
-    padding-right: 55px;
-    background-position: top right !important;
-    background-repeat: no-repeat !important;
-}
-div.important h3
-{
-    background-image: url("important.png");
-}
-div.info h3, div.tip h3
-{
-    background-image: url("tip.png");
-}
-div.note h3
-{
-    background-image: url("note.png");
-}
-div.warning h3
-{
-    background-image: url("warning.png");
-    color: #bc750b;
-}
-div.caution h3
-{
-    background-image: url("caution.png");
-    color: #bc0b0b;
-}
-div.important p, div.info p, div.tip p, div.note p,
-div.warning p, div.caution p
-{
-    margin: 0 0 0.5em 0 !important;
-}
-/* END SIDE NOTES */
-
-
-div.table, div.informaltable
-{
-    width: 100%;
-    clear: both;
-}
-div.table div.table-contents, div.informaltable div.table-contents
-{
-    background-color: rgba(11,117,188,0.1) !important;
-    border: 1px solid #0b75bc;
-    padding: 8px;
-    -moz-border-radius: 5px;
-    -webkit-border-radius: 5px;
-    border-radius: 5px;
-}
-
-div.table table, div.informaltable table
-{
-    width: 100%;
-    border: none;
-    border-collapse: collapse;
-}
-
-td, th
-{
-    padding: 2px 4px;
-}
-
-div.table table, div.informaltable table,
-div.table table th, div.informaltable table th,
-div.table table td, div.informaltable table td,
-div.table table tr, div.informaltable table tr,
-div.table table tbody, div.informaltable table tbody,
-div.table table thead, div.informaltable table thead,
-div.table table tfoot, div.informaltable table tfoot
-{
-    font-size: 15px;
-    text-align: center;
-}
-div.table table td,
-div.informaltable table td,
-div.table table th,
-div.informaltable table th
-{
-    border: 1px solid #3D8AC9;
-}
-div.table table tr:first-child th,
-div.informaltable table tr:first-child th
-{
-  border-top: 0;
-}
-div.table table tr:last-child td,
-div.informaltable table tr:last-child td
-{
-  border-bottom: 0;
-}
-div.table table tr td:first-child,
-div.informaltable table tr td:first-child,
-div.table table tr th:first-child,
-div.informaltable table tr th:first-child
-{
-  border-left: 0;
-}
-div.table table tr td:last-child,
-div.informaltable table tr td:last-child,
-div.table table tr th:last-child,
-div.informaltable table tr th:last-child
-{
-  border-right: 0;
-}
-
-div.queryresult table tbody td p code.literal
-{
-    color: #000000;
-}
-
-div.queryresult table thead tr,
-div.queryresult table tfoot tr
-{
-    background: #cad9dc;
-}
-
-div.queryresult table tbody
-{
-    background: #d1dee1;
-}
-
-div.queryresult table tbody tr.evenresult
-{
-    background: #dfe8eb;
-}
-
-div.queryresult table thead th
-{
-    font-size: 0.9375em;
-}
-
-div.queryresult table tfoot th
-{
-    font-size: 0.8125em;
-    font-weight: normal;
-}
-
-div.table table th, div.informaltable table th
-{
-    color: #3D8AC9;
-}
-div.table-contents td p span.strong strong
-{
-    color: #333333;
-}
-
-div.informaltable span.strong strong
-{
-    font-weight: normal;
-    font-style: italic;
-}
-
-div.informalfigure a img, div.figure a img
-{
-    border: none;
-}
-
-/* additional styles for slides */
-
-div.slide h1
-{
-    margin-top: 40px;
-    margin-bottom: 1em;
-    color: white;
-    border-bottom: none;
-}
-
-div.slide p, div.slide li
-{
-    font-size: 1.25em;
-}
-
-.navfooter{
-    background: #0b75bc;
-    border: 1px solid #0b75bc;
-    border-top: 1px solid #3c91c9;
-}
-
-.navfooter a {
-    color: #fff;
-    color: rgba(255,255,255,0.8);
-    text-decoration: none;
-    text-shadow: none;
-    font-family: Helvetica, Arial, sans-serif;
-}
-
-h1 { font-size: 1.8em; margin-bottom: 1em; }
-h2 { font-size: 1.6em; margin-bottom: 1em; }
-h3 { font-size: 1.4em; margin-bottom: 1em; }
-h4 { font-size: 1.2em; margin-bottom: 0.5em; }
-h5 { font-size: 1em; margin-bottom: 0.5em; }
-
-.devstatus-code-none {
-    border: solid black 2px;
-    margin-right: 5px !important;
-    display: block;
-    float: right;
-    width: 4em;
-    font-size: 10pt !important;
-    font-weight: bolder;
-    font-family: "Courier New", "Courier", monospace !important;
-    background-color: #f08080;
-    text-align: center;
-    text-shadow: none  !important;
-}
-
-.devstatus-code-early {
-    border: solid black 2px;
-    margin-right: 5px !important;
-    display: block;
-    float: right;
-    width: 4em;
-    font-size: 10pt !important;
-    font-weight: bolder;
-    font-family: "Courier New", "Courier", monospace !important;
-    background-color: orange;
-    text-align: center;
-    text-shadow: none  !important;
-}
-.devstatus-code-beta {
-    border: solid black 2px;
-    margin-right: 5px !important;
-    display: block;
-    float: right;
-    width: 4em;
-    font-size: 10pt !important;
-    font-weight: bold;
-    font-family: "Courier New", "Courier", monospace !important;
-    background-color: yellow;
-    text-align: center;
-    text-shadow: none  !important;
-}
-.devstatus-code-stable {
-    border: solid black 2px;
-    margin-right: 5px !important;
-    display: block;
-    float: right;
-    width: 4em;
-    font-size: 10pt !important;
-    font-weight: bolder;
-    font-family: "Courier New", "Courier", monospace !important;
-    background-color: #adff2f;
-    text-align: center;
-    text-shadow: none  !important;
-}
-.devstatus-code-mature {
-    border: solid black 2px;
-    margin-right: 5px !important;
-    display: block;
-    float: right;
-    width: 4em;
-    font-size: 10pt !important;
-    font-weight: bolder;
-    font-family: "Courier New", "Courier", monospace !important;
-    background-color: #7cfc00;
-    text-align: center;
-    text-shadow: none  !important;
-}
-
-.devstatus-docs-none {
-    border: solid black 2px;
-    margin-right: 5px !important;
-    display: block;
-    float: right;
-    width: 4em;
-    font-size: 10pt !important;
-    font-weight: bolder;
-    font-family: "Courier New", "Courier", monospace !important;
-    background-color: #f08080;
-    text-align: center;
-    text-shadow: none  !important;
-}
-
-.devstatus-docs-brief {
-    border: solid black 2px;
-    margin-right: 5px !important;
-    display: block;
-    float: right;
-    width: 4em;
-    font-size: 10pt !important;
-    font-weight: bolder;
-    font-family: "Courier New", "Courier", monospace !important;
-    background-color: yellow;
-    text-align: center;
-    text-shadow: none  !important;
-}
-.devstatus-docs-good {
-    border: solid black 2px;
-    margin-right: 5px !important;
-    display: block;
-    float: right;
-    width: 4em;
-    font-size: 10pt !important;
-    font-weight: bolder;
-    font-family: "Courier New", "Courier", monospace !important;
-    background-color: #adff2f;
-    text-align: center;
-    text-shadow: none  !important;
-}
-.devstatus-docs-complete {
-    border: solid black 2px;
-    margin-right: 5px !important;
-    display: block;
-    float: right;
-    width: 4em;
-    font-size: 10pt !important;
-    font-weight: bolder;
-    font-family: "Courier New", "Courier", monospace !important;
-    background-color: #7cfc00;
-    text-align: center;
-    text-shadow: none  !important;
-}
-
-.devstatus-tests-none {
-    border: solid black 2px;
-    margin-right: 5px !important;
-    display: block;
-    float: right;
-    width: 4em;
-    font-size: 10pt !important;
-    font-weight: bolder;
-    font-family: "Courier New", "Courier", monospace !important;
-    background-color: #f08080;
-    text-align: center;
-    text-shadow: none  !important;
-}
-
-.devstatus-tests-some {
-    border: solid black 2px;
-    margin-right: 5px !important;
-    display: block;
-    float: right;
-    width: 4em;
-
-    font-size: 10pt !important;
-    font-weight: bolder;
-    font-family: "Courier New", "Courier", monospace !important;
-    background-color: yellow;
-    text-align: center;
-    text-shadow: none  !important;
-}
-.devstatus-tests-good {
-    border: solid black 2px;
-    margin-right: 5px !important;
-    display: block;
-    float: right;
-    width: 4em;
-    font-size: 10pt !important;
-    font-weight: bolder;
-    font-family: "Courier New", "Courier", monospace !important;
-    background-color: #adff2f;
-    text-align: center;
-    text-shadow: none  !important;
-}
-
-.devstatus-tests-complete {
-    border: solid black 2px;
-    margin-right: 5px !important;
-    display: block;
-    float: right;
-    width: 4em;
-    font-size: 10pt !important;
-    font-weight: bolder;
-    font-family: "Courier New", "Courier", monospace !important;
-    background-color: #7cfc00;
-    text-align: center;
-    text-shadow: none  !important;
-}
-
-
-.section .variablelist dt .term {
-    font-weight: bolder;
-    font-family: Consolas, Monaco, monospace;
-    background: #DEDEDE;
-}
diff --git a/manual/src/docs/website/resources/css/shCore.css b/manual/src/docs/website/resources/css/shCore.css
index 34f6864..737b6c5 100644
--- a/manual/src/docs/website/resources/css/shCore.css
+++ b/manual/src/docs/website/resources/css/shCore.css
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
+ *       http://www.apache.org/licenses/LICENSE-2.0
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
+ *  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.
  *
- * @license
- * Dual licensed under the MIT and GPL licenses.
+ *
  */
 .syntaxhighlighter a,
 .syntaxhighlighter div,
diff --git a/manual/src/docs/website/resources/css/shCoreEclipse.css b/manual/src/docs/website/resources/css/shCoreEclipse.css
index a45de9f..6adfd6c 100644
--- a/manual/src/docs/website/resources/css/shCoreEclipse.css
+++ b/manual/src/docs/website/resources/css/shCoreEclipse.css
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
+ *       http://www.apache.org/licenses/LICENSE-2.0
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
+ *  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.
  *
- * @license
- * Dual licensed under the MIT and GPL licenses.
+ *
  */
 .syntaxhighlighter a,
 .syntaxhighlighter div,
diff --git a/manual/src/docs/website/resources/css/shThemeEclipse.css b/manual/src/docs/website/resources/css/shThemeEclipse.css
index 77377d9..f175025 100644
--- a/manual/src/docs/website/resources/css/shThemeEclipse.css
+++ b/manual/src/docs/website/resources/css/shThemeEclipse.css
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
+ *       http://www.apache.org/licenses/LICENSE-2.0
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
+ *  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.
  *
- * @license
- * Dual licensed under the MIT and GPL licenses.
+ *
  */
 .syntaxhighlighter {
   background-color: white !important;
diff --git a/manual/src/docs/website/resources/css/style.css b/manual/src/docs/website/resources/css/style.css
index 86374f1..8516dbd 100644
--- a/manual/src/docs/website/resources/css/style.css
+++ b/manual/src/docs/website/resources/css/style.css
@@ -1,17 +1,21 @@
 /*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
+ *  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
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
+ *       http://www.apache.org/licenses/LICENSE-2.0
  *
- *     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.
  *
- * 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.
+ *
  */
 
 body
@@ -75,7 +79,6 @@
     margin: 0;
     margin-top: -7px;
     padding: 0;
-    height: 40px;
 }
 
 .top-nav .toc dl
@@ -158,7 +161,7 @@
 {
 }
 
-.sub-nav .toc
+.sub-nav div.toc
 {
     position: absolute;
     top: 65px;
diff --git a/manual/src/docs/website/samples.txt b/manual/src/docs/website/samples.txt
index b4de2ff..191b00f 100644
--- a/manual/src/docs/website/samples.txt
+++ b/manual/src/docs/website/samples.txt
@@ -24,29 +24,18 @@
 
 == Overview ==
 
-The Zest™ SDK comes with several sample applications. This is a very good place
+The Polygene™ SDK comes with several sample applications. This is a very good place
 to look for code examples and recipes.
 
-The samples are available in the +samples/+ directory of the Zest™ SDK.
+The samples are available in the +samples/+ directory of the Polygene™ SDK.
 
 [[sample-dci, DCI Sample]]
 == DCI Sample ==
 
 Sample of how DCI (Data, Context & Interaction) pattern is implemented using
-Zest™ core only.
+Polygene™ core only.
 
-https://github.com/apache/zest-java/tree/develop/samples/dci[Browse Source]
-
-[[sample-dci-cargo,DCI Cargo Sample]]
-== DCI Cargo Sample ==
-
-Sample of how DCI (Data, Context & Interaction) pattern is implemented with
-Zest™, for Eric Evans DDD sample.
-
-This sample, contributed by Marc Grue, is described in details on his
-website: http://marcgrue.com/
-
-https://github.com/apache/zest-java/tree/develop/samples/dci-cargo[Browse Source]
+https://github.com/apache/polygene-java/tree/develop/samples/dci[Browse Source]
 
 [[sample-forum,Forum Sample]]
 == Forum Sample ==
@@ -54,7 +43,7 @@
 Sample of how to build a web forum using <<library-rest-server>>,
 <<extension-es-file>> and <<library-fileconfig>>.
 
-https://github.com/apache/zest-java/tree/develop/samples/forum[Browse Source]
+https://github.com/apache/polygene-java/tree/develop/samples/forum[Browse Source]
 
 [[sample-car-rental,Car Rental Sample]]
 == Car Rental Sample ==
@@ -62,23 +51,23 @@
 Sample of implementation of a Car Rental application implemented as a Servlet
 based Webapp packaged as a WAR.
 
-https://github.com/apache/zest-java/tree/develop/samples/rental[Browse Source]
+https://github.com/apache/polygene-java/tree/develop/samples/rental[Browse Source]
 
 // [[sample-scala,Scala Sample]]
 // == Scala Sample ==
 //
-// Sample of how to use Scala with Zest™.
+// Sample of how to use Scala with Polygene™.
 //
-// https://github.com/apache/zest-java/tree/develop/samples/scala[Browse Source]
+// https://github.com/apache/polygene-java/tree/develop/samples/scala[Browse Source]
 
 [[sample-sql-support,SQL Support Sample]]
 == SQL Support Sample ==
 
 NOTE: This sample use PostgreSQL and drop all of its data once run in order to be runnable multiple times.
 
-Sample of how to fully use Zest™ SQL support : <<library-sql>>, <<extension-es-sql>> and <<extension-indexing-sql>>.
+Sample of how to fully use Polygene™ SQL support : <<library-sql>>, <<extension-es-sql>> and <<extension-indexing-sql>>.
 
-https://github.com/apache/zest-java/tree/develop/samples/sql-support[Browse Source]
+https://github.com/apache/polygene-java/tree/develop/samples/sql-support[Browse Source]
 
 Here are the steps needed to setup the database using the `psql` utility command:
 
@@ -99,11 +88,12 @@
 user@host $
 ----
 
-A gradle task `runSample` is defined in this module as a shortcut to run the example. See <<build-system>>.
+From the sources you can run the `runSqlSupportSample` Gradle task to run the example.
+See <<build-system>> if you need some guidance.
 
 [[sample-swing,Swing Bindings Sample]]
 == Swing Bindings Sample ==
 
 Sample of how to write custom binders.
 
-https://github.com/apache/zest-java/tree/develop/samples/swing[Browse Source]
+https://github.com/apache/polygene-java/tree/develop/samples/swing[Browse Source]
diff --git a/manual/src/docs/website/tutorials.txt b/manual/src/docs/website/tutorials.txt
index 256d8e8..677dd09 100644
--- a/manual/src/docs/website/tutorials.txt
+++ b/manual/src/docs/website/tutorials.txt
@@ -25,30 +25,30 @@
 == Overview ==
 
 TIP: Theses tutorials are based on actual code found in the `tutorials/` directory of the
-https://zest.apache.org/download.html[Zest™ SDK sources]. You should start your favorite editor and find the code related to
+https://polygene.apache.org/download.html[Polygene™ SDK sources]. You should start your favorite editor and find the code related to
 this tutorial, run it and play with it.
 
-In this section you will find a comprehensive set of tutorials about Composite Oriented Programming using Zest™.
+In this section you will find a comprehensive set of tutorials about Composite Oriented Programming using Polygene™.
 
-[[tutorials-intro,Zest™ in 2 hours 42 minutes]]
-=== Zest™ in 2 hours 42 minutes ===
+[[tutorials-intro,Polygene™ in 42 minutes]]
+=== Polygene™ in 42 minutes ===
 
-This quite long introduction to Zest™ will start by brushing up an overview of the problems Zest™ solve, teach you what
+This quite long introduction to Polygene™ will start by brushing up an overview of the problems Polygene™ solve, teach you what
 Composite Oriented Programming is and guide you through the process of writing a complete Application around an adapted
 Hello World example.
 
 - <<two-minutes-intro>>
 - <<ten-minutes-intro>>
 - <<thirty-minutes-intro>>
-- <<two-hours-intro>>
+// - <<two-hours-intro>>
 
-=== Getting real with Zest™ ===
+=== Getting real with Polygene™ ===
 
-Throughout this set of tutorials it will be shown how to depend on Zest™ in your build, how to assemble a complete
+Throughout this set of tutorials it will be shown how to depend on Polygene™ in your build, how to assemble a complete
 application, how to create and work with Composites and Services, how to use contextual fragments and leverage
 properties.
 
-- <<howto-depend-on-zest>>
+- <<howto-depend-on-polygene>>
 - <<howto-assemble-application>>
 - <<tut-composites>>
 - <<tut-services>>
@@ -65,12 +65,11 @@
 - <<howto-create-sideeffect>>
 - <<howto-create-entity>>
 - <<howto-configure-service>>
-- <<howto-use-io>>
 
-=== Zest™ Development ===
+=== Polygene™ Development ===
 
-This last set of tutorials you'll learn how to build the Zest™ SDK from sources including this very documentation website
-, the Zest™ manual, binaries and sources distributions.
+This last set of tutorials you'll learn how to build the Polygene™ SDK from sources including this very documentation website
+, the Polygene™ manual, binaries and sources distributions.
 
 - <<build-system>>
 - <<community-docs>>
@@ -89,13 +88,13 @@
 
 include::../../../../tutorials/introduction/thirtyminutes/src/docs/thirty-minutes.txt[]
 
-:leveloffset: 2
-
-include::../../../../tutorials/introduction/twohours/src/docs/two-hours.txt[]
+//:leveloffset: 2
+//
+//include::../../../../tutorials/introduction/twohours/src/docs/two-hours.txt[]
 
 :leveloffset: 2
 
-include::../tutorials/howto-depend-on-zest.txt[]
+include::../tutorials/howto-depend-on-polygene.txt[]
 
 :leveloffset: 2
 
@@ -143,10 +142,6 @@
 
 :leveloffset: 2
 
-include::../tutorials/howto-use-io.txt[]
-
-:leveloffset: 2
-
 include::../tutorials/howto-build-system.txt[]
 
 :leveloffset: 2
diff --git a/manual/src/docs/website/xsl/chunked.xsl b/manual/src/docs/website/xsl/chunked.xsl
index 8848a8e..4f76ff3 100644
--- a/manual/src/docs/website/xsl/chunked.xsl
+++ b/manual/src/docs/website/xsl/chunked.xsl
@@ -1,17 +1,21 @@
 <!--
-  ~ Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
+  ~  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
   ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
+  ~       http://www.apache.org/licenses/LICENSE-2.0
   ~
-  ~     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.
   ~
-  ~ 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.
+  ~
   -->
 
 <!--
@@ -58,7 +62,7 @@
         Copyright © 2015 The Apache Software Foundation, Licensed under the <a href="http://www.apache.org/licenses/" target="_blank">Apache License, Version 2.0</a>.
         <br/>
         <small>
-            Apache Zest, Zest, Apache, the Apache feather logo, and the Apache Zest project logo are trademarks of The Apache Software Foundation.<br/>
+            Apache Polygene, Polygene, Apache, the Apache feather logo, and the Apache Polygene project logo are trademarks of The Apache Software Foundation.<br/>
             All other marks mentioned may be trademarks or registered trademarks of their respective owners.
         </small>
       </p>
diff --git a/manual/src/docs/website/xsl/head.xsl b/manual/src/docs/website/xsl/head.xsl
index 297d67e..85780d1 100644
--- a/manual/src/docs/website/xsl/head.xsl
+++ b/manual/src/docs/website/xsl/head.xsl
@@ -1,19 +1,22 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 
   <xsl:template name="user.head.content">
@@ -22,15 +25,15 @@
 
 <!-- favicon -->
 
-<link rel="shortcut icon" href="http://qi4j.org/favicon.ico" type="image/vnd.microsoft.icon" />
-<link rel="icon" href="http://qi4j.org/favicon.ico" type="image/x-icon" />
+<link rel="shortcut icon" href="http://polygene.apache.org/favicon.ico" type="image/vnd.microsoft.icon" />
+<link rel="icon" href="http://polygene.apache.org/favicon.ico" type="image/x-icon" />
 
 <!-- style -->
 
 <link href="css/shCore.css" rel="stylesheet" type="text/css" />
 <link href="css/shCoreEclipse.css" rel="stylesheet" type="text/css" />
 <link href="css/shThemeEclipse.css" rel="stylesheet" type="text/css" />
-<link href="css/qi4j.css" rel="stylesheet" type="text/css" />
+<link href="css/polygene.css" rel="stylesheet" type="text/css" />
 
 <!-- Syntax Highlighter -->
 
@@ -65,7 +68,7 @@
 
 <script type="text/javascript" src="js/tablestyler.js"></script>
 
-<!-- Qi4j WebSite Progressive Enhancement -->
+<!-- Apache Polygene WebSite Progressive Enhancement -->
 
 <link href="css/progressive-enhancement.css" rel="stylesheet" type="text/css" />
 <script type="text/javascript" src="js/jquery.scrollTo-1.4.2.js"></script>
diff --git a/manual/src/docs/website/xsl/singlepage.xsl b/manual/src/docs/website/xsl/singlepage.xsl
index 8c653d5..ef1b5b4 100644
--- a/manual/src/docs/website/xsl/singlepage.xsl
+++ b/manual/src/docs/website/xsl/singlepage.xsl
@@ -1,17 +1,21 @@
 <!--
-  ~ Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
+  ~  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
   ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
+  ~       http://www.apache.org/licenses/LICENSE-2.0
   ~
-  ~     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.
   ~
-  ~ 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.
+  ~
   -->
 
 <!--
diff --git a/manual/src/docs/website/xsl/syntaxhighlight.xsl b/manual/src/docs/website/xsl/syntaxhighlight.xsl
index 1db9578..7c7b978 100644
--- a/manual/src/docs/website/xsl/syntaxhighlight.xsl
+++ b/manual/src/docs/website/xsl/syntaxhighlight.xsl
@@ -1,17 +1,21 @@
 <!--
-  ~ Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
+  ~  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
   ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
+  ~       http://www.apache.org/licenses/LICENSE-2.0
   ~
-  ~     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.
   ~
-  ~ 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.
+  ~
   -->
 
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/assemble/Docs.java b/manual/src/main/java/org/apache/polygene/manual/recipes/assemble/Docs.java
new file mode 100644
index 0000000..7c27654
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/assemble/Docs.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.manual.recipes.assemble;
+
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+
+public class Docs
+{
+    @This
+    UnitOfWorkFactory module;
+
+    public void showUsage()
+    {
+        {
+// START SNIPPET: indirect
+            UnitOfWork unitOfWork = module.currentUnitOfWork();
+            Person person = unitOfWork.newEntity( Person.class );
+// END SNIPPET: indirect
+        }
+        {
+// START SNIPPET: direct
+            UnitOfWork unitOfWork = module.currentUnitOfWork();
+            PersonEntity person = unitOfWork.newEntity( PersonEntity.class );
+// END SNIPPET: direct
+        }
+    }
+
+    public interface Person
+    {
+    }
+
+    public interface PersonEntity
+    {
+    }
+}
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/assemble/Main.java b/manual/src/main/java/org/apache/polygene/manual/recipes/assemble/Main.java
new file mode 100644
index 0000000..abdf123
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/assemble/Main.java
@@ -0,0 +1,163 @@
+/*
+ *  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.polygene.manual.recipes.assemble;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.*;
+
+// START SNIPPET: main
+public class Main
+{
+    private static Energy4Java polygene;
+    private static Application application;
+
+    public static void main( String[] args )
+            throws Exception
+    {
+        // Bootstrap Polygene Runtime
+        // Create a Polygene Runtime
+        polygene = new Energy4Java();
+
+        // Instantiate the Application Model.
+        application = polygene.newApplication(
+            factory ->
+            {
+                ApplicationAssembly assembly = factory.newApplicationAssembly();
+                LayerAssembly runtime = createRuntimeLayer( assembly );
+                LayerAssembly designer = createDesignerLayer( assembly );
+                LayerAssembly domain = createDomainLayer( assembly );
+                LayerAssembly messaging = createMessagingLayer( assembly );
+                LayerAssembly persistence = createPersistenceLayer( assembly );
+
+                // declare structure between layers
+                domain.uses( messaging );
+                domain.uses( persistence );
+                designer.uses( persistence );
+                designer.uses( domain );
+                runtime.uses( domain );
+
+                return assembly;
+            } );
+
+        // We need to handle shutdown.
+        installShutdownHook();
+
+        // Activate the Application Runtime.
+        application.activate();
+    }
+
+// END SNIPPET: main
+    private static LayerAssembly createRuntimeLayer( ApplicationAssembly app )
+    {
+        return app.layer( "runtime-layer" );
+    }
+
+    private static LayerAssembly createDesignerLayer( ApplicationAssembly app )
+    {
+        return app.layer( "designer-layer" );
+    }
+
+    private static LayerAssembly createMessagingLayer( ApplicationAssembly app )
+    {
+        return app.layer( "messaging-layer" );
+    }
+
+    private static LayerAssembly createPersistenceLayer( ApplicationAssembly app )
+    {
+        return app.layer( "persistence-layer" );
+    }
+
+// START SNIPPET: domainLayer
+    private static LayerAssembly createDomainLayer( ApplicationAssembly app )
+    {
+        LayerAssembly layer = app.layer("domain-layer");
+        createAccountModule( layer );
+        createInventoryModule( layer );
+        createReceivablesModule( layer );
+        createPayablesModule( layer );
+        return layer;
+    }
+
+// END SNIPPET: domainLayer
+// START SNIPPET: accountModule
+    private static void createAccountModule( LayerAssembly layer )
+    {
+        ModuleAssembly module = layer.module("account-module");
+
+        module.entities(AccountEntity.class, EntryEntity.class);
+
+        module.addServices(
+                AccountRepositoryService.class,
+                AccountFactoryService.class,
+                EntryFactoryService.class,
+                EntryRepositoryService.class
+        ).visibleIn( Visibility.layer );
+    }
+
+// END SNIPPET: accountModule
+    private static void createPayablesModule( LayerAssembly layer )
+    {
+        layer.module("payables-module");
+    }
+
+    private static void createInventoryModule( LayerAssembly layer )
+    {
+        layer.module("inventory-module");
+    }
+
+    private static void createReceivablesModule( LayerAssembly layer )
+    {
+        layer.module("receivables-module");
+    }
+
+// START SNIPPET: shutdown
+    private static void installShutdownHook()
+    {
+        Runtime.getRuntime().addShutdownHook( new Thread( new Runnable()
+        {
+            public void run()
+            {
+                if( application != null )
+                {
+                    try
+                    {
+                        application.passivate();
+                    }
+                    catch( Exception e )
+                    {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }) );
+    }
+// END SNIPPET: shutdown
+// START SNIPPET: main
+}
+
+// END SNIPPET: main
+interface AccountEntity {}
+interface EntryEntity {}
+
+interface AccountFactoryService {}
+interface EntryFactoryService {}
+interface EntryRepositoryService {}
+interface AccountRepositoryService {}
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/concern/AnyMixinType.java b/manual/src/main/java/org/apache/polygene/manual/recipes/concern/AnyMixinType.java
new file mode 100644
index 0000000..daa681d
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/concern/AnyMixinType.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.manual.recipes.concern;
+
+import org.apache.polygene.api.concern.Concerns;
+
+// START SNIPPET: annotationUse
+// START SNIPPET: class
+@Concerns( MyGenericConcern.class )
+public interface AnyMixinType
+{
+
+// START SNIPPET: class
+    @MyAnnotation
+    void doSomething();
+
+    void doSomethingElse();
+
+// END SNIPPET: class
+}
+// END SNIPPET: class
+// END SNIPPET: annotationUse
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/concern/InventoryConcern.java b/manual/src/main/java/org/apache/polygene/manual/recipes/concern/InventoryConcern.java
new file mode 100644
index 0000000..27d0879
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/concern/InventoryConcern.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.manual.recipes.concern;
+
+public class InventoryConcern
+    implements Order
+{
+    @Override
+    public void addLineItem( LineItem item )
+    {
+    }
+
+    @Override
+    public void removeLineItem( LineItem item )
+    {
+    }
+}
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/concern/LineItem.java b/manual/src/main/java/org/apache/polygene/manual/recipes/concern/LineItem.java
new file mode 100644
index 0000000..e027d3a
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/concern/LineItem.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.manual.recipes.concern;
+
+
+public interface LineItem
+{
+}
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/concern/MyAnnotation.java b/manual/src/main/java/org/apache/polygene/manual/recipes/concern/MyAnnotation.java
new file mode 100644
index 0000000..35d9050
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/concern/MyAnnotation.java
@@ -0,0 +1,24 @@
+/*
+ *  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.polygene.manual.recipes.concern;
+
+public @interface MyAnnotation
+{
+}
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/concern/MyAppliesToFilter.java b/manual/src/main/java/org/apache/polygene/manual/recipes/concern/MyAppliesToFilter.java
new file mode 100644
index 0000000..e276505
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/concern/MyAppliesToFilter.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.manual.recipes.concern;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesToFilter;
+
+// START SNIPPET: filter
+public class MyAppliesToFilter implements AppliesToFilter
+{
+    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> modifierClass )
+    {
+        boolean appliesTo = evaluate(method); // Do whatever you want
+        return appliesTo;
+    }
+
+// START SNIPPET: filter
+    private boolean evaluate( Method method )
+    {
+        return true;
+    }
+// END SNIPPET: filter
+}
+// END SNIPPET: filter
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/concern/MyGenericConcern.java b/manual/src/main/java/org/apache/polygene/manual/recipes/concern/MyGenericConcern.java
new file mode 100644
index 0000000..9527709
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/concern/MyGenericConcern.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.manual.recipes.concern;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.concern.GenericConcern;
+
+// START SNIPPET: appliesTo
+@AppliesTo( { MyAnnotation.class, MyAppliesToFilter.class } )
+// START SNIPPET: class
+public class MyGenericConcern extends GenericConcern
+{
+// END SNIPPET: appliesTo
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        // Do whatever you want
+
+// START SNIPPET: class
+// END SNIPPET: class
+        return next.invoke( proxy, method, args );
+    }
+}
+// END SNIPPET: class
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/concern/Order.java b/manual/src/main/java/org/apache/polygene/manual/recipes/concern/Order.java
new file mode 100644
index 0000000..fc0a671
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/concern/Order.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.manual.recipes.concern;
+
+import org.apache.polygene.api.concern.Concerns;
+
+// START SNIPPET: class
+@Concerns( InventoryConcern.class )
+public interface Order
+{
+    void addLineItem( LineItem item );
+    void removeLineItem( LineItem item );
+
+// START SNIPPET: class
+// END SNIPPET: class
+}
+// END SNIPPET: class
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/contextualFragments/TraceAll.java b/manual/src/main/java/org/apache/polygene/manual/recipes/contextualFragments/TraceAll.java
new file mode 100644
index 0000000..aab3e17
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/contextualFragments/TraceAll.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.manual.recipes.contextualFragments;
+
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.library.logging.trace.TraceAllConcern;
+
+// START SNIPPET: assemble
+public class TraceAll
+{
+    public void assemble( ModuleAssembly module )
+    {
+        ServiceDeclaration decl = module.addServices( PinSearchService.class );
+        if( Boolean.getBoolean( "trace.all"  ) )
+        {
+            decl.withConcerns( TraceAllConcern.class );
+        }
+    }
+}
+
+// END SNIPPET: assemble
+class PinSearchService {}
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/Dialer.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/Dialer.java
new file mode 100644
index 0000000..e05662b
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/Dialer.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.manual.recipes.createConstraint;
+
+// START SNIPPET: dialer
+public interface Dialer
+{
+    void callPhoneNumber(@PhoneNumber String phoneNo);
+
+}
+// END SNIPPET: dialer
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/DialerComposite.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/DialerComposite.java
new file mode 100644
index 0000000..cbd35e6
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/DialerComposite.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.manual.recipes.createConstraint;
+
+import org.apache.polygene.api.constraint.Constraints;
+
+// START SNIPPET: composite
+@Constraints( PhoneNumberConstraint.class )
+public interface DialerComposite extends Dialer
+{
+}
+// END SNIPPET: composite
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/HasPhoneNumber.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/HasPhoneNumber.java
new file mode 100644
index 0000000..5e2f5ab
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/HasPhoneNumber.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.manual.recipes.createConstraint;
+
+import org.apache.polygene.api.property.Property;
+
+// START SNIPPET: property
+public interface HasPhoneNumber
+{
+    @PhoneNumber
+    Property<String> phoneNumber();
+}
+// END SNIPPET: property
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/ParameterViolationConcern.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/ParameterViolationConcern.java
new file mode 100644
index 0000000..a7dd18d
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/ParameterViolationConcern.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.manual.recipes.createConstraint;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.constraint.ConstraintViolation;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+
+// START SNIPPET: report
+public class ParameterViolationConcern extends ConcernOf<InvocationHandler>
+    implements InvocationHandler
+{
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        try
+        {
+            return next.invoke( proxy, method, args );
+        }
+        catch( ConstraintViolationException e )
+        {
+            for( ConstraintViolation violation : e.constraintViolations() )
+            {
+                String name = violation.name();
+                Object value = violation.value();
+                Annotation constraint = violation.constraint();
+                report( name, value, constraint );
+            }
+            throw new IllegalArgumentException("Invalid argument(s)", e);
+        }
+    }
+
+// END SNIPPET: report
+// START SNIPPET: report
+    private void report( String name, Object value, Annotation constraint )
+    {
+    }
+}
+// END SNIPPET: report
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/PhoneNumber.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/PhoneNumber.java
new file mode 100644
index 0000000..0f40e95
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/PhoneNumber.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.manual.recipes.createConstraint;
+
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// START SNIPPET: annotation
+@ConstraintDeclaration
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.PARAMETER, ElementType.ANNOTATION_TYPE, ElementType.METHOD } )
+public @interface PhoneNumber
+{
+}
+// END SNIPPET: annotation
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/PhoneNumberConstraint.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/PhoneNumberConstraint.java
new file mode 100644
index 0000000..20a86c3
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/PhoneNumberConstraint.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.manual.recipes.createConstraint;
+
+import org.apache.polygene.api.constraint.Constraint;
+
+// START SNIPPET: constraint
+public class PhoneNumberConstraint
+        implements Constraint<PhoneNumber, String>
+{
+    public boolean isValid( PhoneNumber annotation, String number )
+    {
+        boolean validPhoneNumber = true; // check phone number format...
+        return validPhoneNumber;  // return true if valid phone number.
+    }
+}
+// END SNIPPET: constraint
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/PhoneNumberParameterViolationConcern.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/PhoneNumberParameterViolationConcern.java
new file mode 100644
index 0000000..92db8a2
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createConstraint/PhoneNumberParameterViolationConcern.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.manual.recipes.createConstraint;
+
+import java.util.Collection;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.constraint.ConstraintViolation;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.property.Property;
+
+// START SNIPPET: property
+public abstract class PhoneNumberParameterViolationConcern extends ConcernOf<HasPhoneNumber>
+    implements HasPhoneNumber
+{
+    @Concerns( CheckViolation.class )
+    public abstract Property<String> phoneNumber();
+
+    private abstract class CheckViolation extends ConcernOf<Property<String>>
+        implements Property<String>
+    {
+        public void set( String number )
+        {
+            try
+            {
+                next.set( number );
+            }
+            catch( ConstraintViolationException e )
+            {
+                Collection<ConstraintViolation> violations = e.constraintViolations();
+                report( violations );
+            }
+        }
+
+// END SNIPPET: property
+
+// START SNIPPET: property
+        private void report( Collection<ConstraintViolation> violations )
+        {
+        }
+    }
+}
+// END SNIPPET: property
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/Accident.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/Accident.java
new file mode 100644
index 0000000..ca793fc
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/Accident.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.manual.recipes.createEntity;
+
+import java.time.LocalDate;
+import org.apache.polygene.api.property.Property;
+
+// START SNIPPET: entity
+public interface Accident
+{
+    Property<String> description();
+    Property<LocalDate> occured();
+    Property<LocalDate> repaired();
+}
+
+// END SNIPPET: entity
\ No newline at end of file
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/AccidentValue.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/AccidentValue.java
new file mode 100644
index 0000000..abc320a
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/AccidentValue.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.manual.recipes.createEntity;
+
+import org.apache.polygene.api.value.ValueComposite;
+
+// START SNIPPET: composite
+public interface AccidentValue extends Accident
+{}
+
+// END SNIPPET: composite
\ No newline at end of file
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/Car.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/Car.java
new file mode 100644
index 0000000..c48a0df
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/Car.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.manual.recipes.createEntity;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.property.Immutable;
+import org.apache.polygene.api.property.Property;
+
+// START SNIPPET: entity
+public interface Car
+{
+    @Immutable
+    Association<Manufacturer> manufacturer();
+
+    @Immutable
+    Property<String> model();
+
+    ManyAssociation<Accident> accidents();
+}
+
+// END SNIPPET: entity
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntity.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntity.java
new file mode 100644
index 0000000..e93fcc6
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntity.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.manual.recipes.createEntity;
+
+import org.apache.polygene.api.identity.HasIdentity;
+
+// START SNIPPET: composite
+public interface CarEntity extends HasIdentity, Car
+{}
+
+// END SNIPPET: composite
\ No newline at end of file
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntityFactory.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntityFactory.java
new file mode 100644
index 0000000..53ec400
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntityFactory.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.manual.recipes.createEntity;
+
+// START SNIPPET: carFactory
+public interface CarEntityFactory
+{
+    Car create(Manufacturer manufacturer, String model);
+}
+
+// END SNIPPET: carFactory
\ No newline at end of file
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntityFactoryMixin.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntityFactoryMixin.java
new file mode 100644
index 0000000..3750314
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntityFactoryMixin.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.manual.recipes.createEntity;
+
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+
+// START SNIPPET: carFactoryMixin2
+// START SNIPPET: carFactoryMixin1
+public class CarEntityFactoryMixin
+    implements CarEntityFactory
+{
+
+    // END SNIPPET: carFactoryMixin1
+    @Structure
+    UnitOfWorkFactory unitOfWorkFactory;
+
+    // END SNIPPET: carFactoryMixin2
+// START SNIPPET: carFactoryMixin3
+    public CarEntityFactoryMixin( @Structure UnitOfWorkFactory unitOfWorkFactory )
+    {
+    }
+
+    // END SNIPPET: carFactoryMixin3
+// START SNIPPET: create
+    public Car create( Manufacturer manufacturer, String model )
+    {
+        UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+        EntityBuilder<Car> builder = uow.newEntityBuilder( Car.class );
+
+        Car prototype = builder.instance();
+        prototype.manufacturer().set( manufacturer );
+        prototype.model().set( model );
+
+        return builder.newInstance();
+    }
+// END SNIPPET: create
+}
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntityFactoryService.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntityFactoryService.java
new file mode 100644
index 0000000..18a535a
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/CarEntityFactoryService.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.manual.recipes.createEntity;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+// START SNIPPET: carFactoryService
+@Mixins( { CarEntityFactoryMixin.class } )
+public interface CarEntityFactoryService
+        extends CarEntityFactory
+{}
+// END SNIPPET: carFactoryService
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/Main.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/Main.java
new file mode 100644
index 0000000..69a3cff
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/Main.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.manual.recipes.createEntity;
+
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.*;
+
+public class Main
+{
+    public static void main(String[] args) throws Exception
+    {
+
+        Energy4Java polygene = new Energy4Java();
+
+        // Instantiate the Application Model.
+        Application application = polygene.newApplication(
+            factory -> factory.newApplicationAssembly( new MyAssembler()) );
+
+        application.activate();
+
+    }
+}
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/Manufacturer.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/Manufacturer.java
new file mode 100644
index 0000000..3b58345
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/Manufacturer.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.manual.recipes.createEntity;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+// START SNIPPET: entity
+public interface Manufacturer
+{
+    Property<String> name();
+    Property<String> country();
+
+    @UseDefaults
+    Property<Long> carsProduced();
+}
+
+// END SNIPPET: entity
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/ManufacturerEntity.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/ManufacturerEntity.java
new file mode 100644
index 0000000..19bfe0c
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/ManufacturerEntity.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.manual.recipes.createEntity;
+
+import org.apache.polygene.api.identity.HasIdentity;
+
+// START SNIPPET: composite
+public interface ManufacturerEntity extends HasIdentity, Manufacturer
+{}
+
+// END SNIPPET: composite
\ No newline at end of file
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/ManufacturerRepository.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/ManufacturerRepository.java
new file mode 100644
index 0000000..a368f59
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/ManufacturerRepository.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.manual.recipes.createEntity;
+
+import org.apache.polygene.api.identity.Identity;
+
+// START SNIPPET: repo
+public interface ManufacturerRepository
+{
+    Manufacturer findByIdentity(Identity identity);
+
+    Manufacturer findByName(String name);
+}
+// END SNIPPET: repo
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/ManufacturerRepositoryMixin.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/ManufacturerRepositoryMixin.java
new file mode 100644
index 0000000..c70af1f
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/ManufacturerRepositoryMixin.java
@@ -0,0 +1,63 @@
+/*
+ *  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.polygene.manual.recipes.createEntity;
+
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+
+import static org.apache.polygene.api.query.QueryExpressions.eq;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+
+// START SNIPPET: repo
+public class ManufacturerRepositoryMixin
+    implements ManufacturerRepository
+{
+    @Structure
+    private UnitOfWorkFactory uowf;
+
+    @Structure
+    private Module module;
+
+    public Manufacturer findByIdentity( Identity identity )
+    {
+        UnitOfWork uow = uowf.currentUnitOfWork();
+        return uow.get(Manufacturer.class, identity );
+    }
+
+    public Manufacturer findByName( String name )
+    {
+        UnitOfWork uow = uowf.currentUnitOfWork();
+        QueryBuilder<Manufacturer> builder =
+                module.newQueryBuilder( Manufacturer.class );
+
+        Manufacturer template = templateFor( Manufacturer.class );
+        builder.where( eq( template.name(), name ) );
+
+        Query<Manufacturer> query = uow.newQuery( builder);
+        return query.find();
+    }
+}
+
+// END SNIPPET: repo
\ No newline at end of file
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/ManufacturerRepositoryService.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/ManufacturerRepositoryService.java
new file mode 100644
index 0000000..83943a8
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/ManufacturerRepositoryService.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.manual.recipes.createEntity;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+// START SNIPPET: manufacturerRepositoryService
+@Mixins( ManufacturerRepositoryMixin.class  )
+public interface ManufacturerRepositoryService
+    extends ManufacturerRepository
+{}
+// END SNIPPET: manufacturerRepositoryService
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/MyAssembler.java b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/MyAssembler.java
new file mode 100644
index 0000000..ed5b1b1
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/createEntity/MyAssembler.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.manual.recipes.createEntity;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+// START SNIPPET: assembler2
+// START SNIPPET: assembler1
+public class MyAssembler
+    implements Assembler
+{
+    public void assemble( ModuleAssembly module )
+    {
+        module.entities( CarEntity.class,
+                ManufacturerEntity.class );
+
+        module.values( AccidentValue.class );
+// END SNIPPET: assembler1
+        module.addServices(
+                ManufacturerRepositoryService.class,
+                CarEntityFactoryService.class
+        ).visibleIn( Visibility.application );
+// START SNIPPET: assembler1
+    }
+}
+// END SNIPPET: assembler1
+// END SNIPPET: assembler2
\ No newline at end of file
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/properties/Book.java b/manual/src/main/java/org/apache/polygene/manual/recipes/properties/Book.java
new file mode 100644
index 0000000..4068e7d
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/properties/Book.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.manual.recipes.properties;
+
+import org.apache.polygene.api.property.Immutable;
+import org.apache.polygene.api.property.Property;
+
+// START SNIPPET: book
+public interface Book
+{
+    @Immutable
+    Property<String> title();
+
+    @Immutable
+    Property<String> author();
+}
+// END SNIPPET: book
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/properties/BookFactory.java b/manual/src/main/java/org/apache/polygene/manual/recipes/properties/BookFactory.java
new file mode 100644
index 0000000..a9d5743
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/properties/BookFactory.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.manual.recipes.properties;
+
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.structure.Module;
+
+public class BookFactory
+{
+// START SNIPPET: create
+    @Structure
+    Module module;
+// END SNIPPET: create
+
+    public Book create()
+    {
+// START SNIPPET: create
+        TransientBuilder<Book> builder = module.newTransientBuilder( Book.class );
+        Book prototype = builder.prototype();
+        prototype.title().set( "The Death of POJOs" );
+        prototype.author().set( "Niclas Hedhman" );
+        Book book = builder.newInstance();
+        String title = book.title().get();     // Retrieves the title.
+        book.title().set( "Long Live POJOs" ); // throws an IllegalStateException
+// END SNIPPET: create
+        return book;
+    }
+}
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/properties/SwingInfo.java b/manual/src/main/java/org/apache/polygene/manual/recipes/properties/SwingInfo.java
new file mode 100644
index 0000000..5b9e961
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/properties/SwingInfo.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.manual.recipes.properties;
+
+import java.awt.Rectangle;
+import java.util.Locale;
+import javax.swing.Icon;
+
+// START SNIPPET: info
+public interface SwingInfo
+{
+    Icon icon( Rectangle size );
+
+    String displayName( Locale locale );
+}
+// END SNIPPET: info
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/properties/SwingPanel.java b/manual/src/main/java/org/apache/polygene/manual/recipes/properties/SwingPanel.java
new file mode 100644
index 0000000..7945a15
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/properties/SwingPanel.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.manual.recipes.properties;
+
+import java.awt.Rectangle;
+import java.util.Locale;
+import javax.swing.Icon;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.property.Property;
+
+public class SwingPanel
+{
+    private static final Rectangle SIZE_32_32 = new Rectangle( 32, 32 );
+    private Locale locale;
+
+// START SNIPPET: info-use
+    @Structure
+    private PolygeneAPI api;
+// END SNIPPET: info-use
+
+// START SNIPPET: info-use
+    private void addProperty( JPanel panel, Property<?> property )
+    {
+        SwingInfo info = api.propertyDescriptorFor( property ).metaInfo( SwingInfo.class );
+        Icon icon = info.icon( SIZE_32_32 );
+        panel.add(  new JLabel(info.displayName( this.locale ), icon, JLabel.CENTER) );
+    }
+// START SNIPPET: info-use
+}
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/properties/pojo/Book.java b/manual/src/main/java/org/apache/polygene/manual/recipes/properties/pojo/Book.java
new file mode 100644
index 0000000..40620a9
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/properties/pojo/Book.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.manual.recipes.properties.pojo;
+
+// START SNIPPET: book
+public interface Book
+{
+    String getTitle();
+    String getAuthor();
+}
+// END SNIPPET: book
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/properties/pojo/MutableBook.java b/manual/src/main/java/org/apache/polygene/manual/recipes/properties/pojo/MutableBook.java
new file mode 100644
index 0000000..00049f2
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/properties/pojo/MutableBook.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.manual.recipes.properties.pojo;
+
+
+// START SNIPPET: mutableBook
+public interface MutableBook extends Book
+{
+    void setTitle( String title );
+    void setAuthor( String author );
+}
+// END SNIPPET: mutableBook
\ No newline at end of file
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/AnyMixinType.java b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/AnyMixinType.java
new file mode 100644
index 0000000..d6115d0
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/AnyMixinType.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.manual.recipes.sideeffects;
+
+import org.apache.polygene.api.concern.Concerns;
+
+// START SNIPPET: body
+// START SNIPPET: annotation
+@Concerns( MyGenericSideEffect.class )
+public interface AnyMixinType
+{
+// END SNIPPET: body
+
+    @MyAnnotation
+    void doSomething();
+
+    void doSomethingElse();
+
+// START SNIPPET: body
+}
+// START SNIPPET: annotation
+// END SNIPPET: body
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/Confirmable.java b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/Confirmable.java
new file mode 100644
index 0000000..9181f6e
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/Confirmable.java
@@ -0,0 +1,24 @@
+/*
+ *  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.polygene.manual.recipes.sideeffects;
+
+public interface Confirmable
+{
+}
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/HasCustomer.java b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/HasCustomer.java
new file mode 100644
index 0000000..e38d98e
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/HasCustomer.java
@@ -0,0 +1,24 @@
+/*
+ *  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.polygene.manual.recipes.sideeffects;
+
+public interface HasCustomer
+{
+}
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/HasLineItems.java b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/HasLineItems.java
new file mode 100644
index 0000000..62a1c40
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/HasLineItems.java
@@ -0,0 +1,24 @@
+/*
+ *  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.polygene.manual.recipes.sideeffects;
+
+public interface HasLineItems
+{
+}
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/HasSequenceNumber.java b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/HasSequenceNumber.java
new file mode 100644
index 0000000..358fea8
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/HasSequenceNumber.java
@@ -0,0 +1,24 @@
+/*
+ *  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.polygene.manual.recipes.sideeffects;
+
+public interface HasSequenceNumber
+{
+}
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/MailNotifySideEffect.java b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/MailNotifySideEffect.java
new file mode 100644
index 0000000..c7f2ed0
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/MailNotifySideEffect.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.manual.recipes.sideeffects;
+
+import org.apache.polygene.api.sideeffect.SideEffectOf;
+
+public class MailNotifySideEffect extends SideEffectOf<Order>
+    implements Order
+{
+}
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/MyAnnotation.java b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/MyAnnotation.java
new file mode 100644
index 0000000..3c85096
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/MyAnnotation.java
@@ -0,0 +1,24 @@
+/*
+ *  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.polygene.manual.recipes.sideeffects;
+
+public @interface MyAnnotation
+{
+}
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/MyAppliesToFilter.java b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/MyAppliesToFilter.java
new file mode 100644
index 0000000..582e17c
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/MyAppliesToFilter.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.manual.recipes.sideeffects;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesToFilter;
+
+// START SNIPPET: filter
+public class MyAppliesToFilter implements AppliesToFilter
+{
+    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> modifierClass )
+    {
+        boolean appliesTo = evaluate(method); // Do whatever you want
+        return appliesTo;
+    }
+
+// START SNIPPET: filter
+    private boolean evaluate( Method method )
+    {
+        return true;
+    }
+// END SNIPPET: filter
+}
+// END SNIPPET: filter
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/MyGenericSideEffect.java b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/MyGenericSideEffect.java
new file mode 100644
index 0000000..0f396a5
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/MyGenericSideEffect.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.polygene.manual.recipes.sideeffects;
+
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.sideeffect.GenericSideEffect;
+
+// START SNIPPET: appliesTo
+@AppliesTo( { MyAnnotation.class, MyAppliesToFilter.class } )
+// START SNIPPET: body
+public class MyGenericSideEffect extends GenericSideEffect
+{
+// END SNIPPET: appliesTo
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        // Do whatever you need...
+
+        try
+        {
+            // It is possible to obtain the returned values by using 'result' member;
+            Object returnedValue = result.invoke( proxy, method, args );
+        } catch( NumberFormatException e )
+        {
+            // And Exception will be thrown accordingly, in case you need to know.
+            throw new IllegalArgumentException(); // But any thrown exceptions are ignored.
+        }
+        return 23; // Return values will also be ignored.
+    }
+// START SNIPPET: appliesTo
+}
+// END SNIPPET: appliesTo
+// END SNIPPET: body
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/Order.java b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/Order.java
new file mode 100644
index 0000000..daecbf3
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/Order.java
@@ -0,0 +1,24 @@
+/*
+ *  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.polygene.manual.recipes.sideeffects;
+
+public interface Order
+{
+}
diff --git a/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/OrderEntity.java b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/OrderEntity.java
new file mode 100644
index 0000000..cfd32ab
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/recipes/sideeffects/OrderEntity.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.manual.recipes.sideeffects;
+
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.sideeffect.SideEffects;
+
+// START SNIPPET: body
+@SideEffects( MailNotifySideEffect.class )
+public interface OrderEntity
+    extends Order, HasSequenceNumber, HasCustomer,
+            HasLineItems, Confirmable, HasIdentity
+{
+}
+// END SNIPPET: body
diff --git a/manual/src/main/java/org/apache/polygene/manual/travel/ExpediaService.properties b/manual/src/main/java/org/apache/polygene/manual/travel/ExpediaService.properties
new file mode 100644
index 0000000..af50397
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/travel/ExpediaService.properties
@@ -0,0 +1,30 @@
+#
+#  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.
+#
+#
+#
+
+#// START SNIPPET: params
+# Hostname to the TravelPlan service
+hostName=expedia.hedhman.org
+
+# Port number to use for the connection
+portNumber=9251
+
+# Protocol to use; Valid options "ssh", "rlogin", "telnet"
+protocol=ssh
+#// END SNIPPET: params
\ No newline at end of file
diff --git a/manual/src/main/java/org/apache/polygene/manual/travel/Main.java b/manual/src/main/java/org/apache/polygene/manual/travel/Main.java
new file mode 100644
index 0000000..244e0ac
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/travel/Main.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.manual.travel;
+
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+public class Main
+{
+
+    public static void main(String[] args) throws Exception
+    {
+        SingletonAssembler singleton = new SingletonAssembler()
+        {
+            // START SNIPPET: assemble
+            @Override
+            public void assemble(ModuleAssembly module)
+            {
+                module.addServices(TravelPlanService.class)
+                        .instantiateOnStartup()
+                        .identifiedBy("ExpediaService");
+
+                module.addServices(TravelPlanService.class)
+                        .instantiateOnStartup()
+                        .identifiedBy("OrbitzService");
+            }
+            // END SNIPPET: assemble
+        };
+    }
+
+    public static void simple(String[] args) throws Exception
+    {
+        SingletonAssembler singleton = new SingletonAssembler()
+        {
+            // START SNIPPET: simple
+            @Override
+            public void assemble(ModuleAssembly module)
+            {
+                module.addServices(TravelPlanService.class).instantiateOnStartup();
+            }
+            // END SNIPPET: simple
+        };
+    }
+
+}
\ No newline at end of file
diff --git a/manual/src/main/java/org/apache/polygene/manual/travel/OrbitzService.properties b/manual/src/main/java/org/apache/polygene/manual/travel/OrbitzService.properties
new file mode 100644
index 0000000..b042b21
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/travel/OrbitzService.properties
@@ -0,0 +1,30 @@
+#
+#  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.
+#
+#
+#
+
+#// START SNIPPET: params
+# Hostname to the TravelPlan service
+hostName=orbitz.hedhman.org
+
+# Port number to use for the connection
+portNumber=7412
+
+# Protocol to use; Valid options "ssh", "rlogin", "telnet"
+protocol=rlogin
+#// END SNIPPET: params
\ No newline at end of file
diff --git a/manual/src/main/java/org/apache/polygene/manual/travel/TravelPlan.java b/manual/src/main/java/org/apache/polygene/manual/travel/TravelPlan.java
new file mode 100644
index 0000000..82c2ff6
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/travel/TravelPlan.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.manual.travel;
+
+// START SNIPPET: service
+public interface TravelPlan
+{
+    // Domain methods, which are beyond the discussion at hand.
+}
+// END SNIPPET: service
\ No newline at end of file
diff --git a/manual/src/main/java/org/apache/polygene/manual/travel/TravelPlanConfiguration.java b/manual/src/main/java/org/apache/polygene/manual/travel/TravelPlanConfiguration.java
new file mode 100644
index 0000000..5fe02ea
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/travel/TravelPlanConfiguration.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.manual.travel;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.constraints.annotation.Matches;
+import org.apache.polygene.library.constraints.annotation.Range;
+
+// START SNIPPET: configuration
+public interface TravelPlanConfiguration
+{
+    Property<String> hostName();
+
+    @Range( min=0, max=65535 )
+    Property<Integer> portNumber();
+
+    @Matches( "(ssh|rlogin|telnet)" )
+    Property<String> protocol();
+}
+// END SNIPPET: configuration
\ No newline at end of file
diff --git a/manual/src/main/java/org/apache/polygene/manual/travel/TravelPlanMixin.java b/manual/src/main/java/org/apache/polygene/manual/travel/TravelPlanMixin.java
new file mode 100644
index 0000000..ebad79c
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/travel/TravelPlanMixin.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.polygene.manual.travel;
+
+import org.apache.polygene.api.injection.scope.This;
+// START SNIPPET: mixin
+import org.apache.polygene.api.configuration.Configuration;
+
+public class TravelPlanMixin implements TravelPlan
+{
+    @This
+    Configuration<TravelPlanConfiguration> config;
+
+    private void foo()
+    {
+        TravelPlanConfiguration tpConf = config.get();
+        String hostName = tpConf.hostName().get();
+        // ...
+    }
+// END SNIPPET: mixin
+
+    // START SNIPPET: refresh
+    public void doSomething()
+    {
+        // Refresh Configuration before reading it.
+        config.refresh();
+
+        TravelPlanConfiguration tpConf = config.get();
+        // ...
+    }
+    // END SNIPPET: refresh
+
+// START SNIPPET: mixin
+}
+// END SNIPPET: mixin
\ No newline at end of file
diff --git a/manual/src/main/java/org/apache/polygene/manual/travel/TravelPlanService.java b/manual/src/main/java/org/apache/polygene/manual/travel/TravelPlanService.java
new file mode 100644
index 0000000..9398fe5
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/travel/TravelPlanService.java
@@ -0,0 +1,31 @@
+/*
+ *  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.
+ *
+ *
+ */
+// START SNIPPET: serviceComposite
+// The package is relevant to the Initial Values discussed later.
+package org.apache.polygene.manual.travel;
+// END SNIPPET: serviceComposite
+
+import org.apache.polygene.api.mixin.Mixins;
+
+// START SNIPPET: serviceComposite
+@Mixins( { TravelPlanMixin.class } )
+public interface TravelPlanService extends TravelPlan
+{}
+// END SNIPPET: serviceComposite
\ No newline at end of file
diff --git a/manual/src/main/java/org/apache/polygene/manual/travel/TravelPlanService.properties b/manual/src/main/java/org/apache/polygene/manual/travel/TravelPlanService.properties
new file mode 100644
index 0000000..0c63858
--- /dev/null
+++ b/manual/src/main/java/org/apache/polygene/manual/travel/TravelPlanService.properties
@@ -0,0 +1,31 @@
+#
+#  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.
+#
+#
+#
+
+#// START SNIPPET: params
+# Hostname to the TravelPlan service
+hostName=niclas.hedhman.org
+
+# Port number to use for the connection
+portNumber=5439
+
+# Protocol to use; Valid options "ssh", "rlogin", "telnet"
+protocol=ssh
+
+#// END SNIPPET: params
\ No newline at end of file
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/assemble/Docs.java b/manual/src/main/java/org/qi4j/manual/recipes/assemble/Docs.java
deleted file mode 100644
index bc9a5bd..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/assemble/Docs.java
+++ /dev/null
@@ -1,54 +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.qi4j.manual.recipes.assemble;
-
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueComposite;
-
-public class Docs
-{
-    @This
-    Module module;
-
-    public void showUsage()
-    {
-        {
-// START SNIPPET: indirect
-            UnitOfWork unitOfWork = module.currentUnitOfWork();
-            Person person = unitOfWork.newEntity( Person.class );
-// END SNIPPET: indirect
-        }
-        {
-// START SNIPPET: direct
-            UnitOfWork unitOfWork = module.currentUnitOfWork();
-            PersonEntity person = unitOfWork.newEntity( PersonEntity.class );
-// END SNIPPET: direct
-        }
-    }
-
-    public interface Person
-    {
-    }
-
-    public interface PersonEntity extends ValueComposite
-    {
-    }
-}
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/assemble/Main.java b/manual/src/main/java/org/qi4j/manual/recipes/assemble/Main.java
deleted file mode 100644
index 87c37c7..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/assemble/Main.java
+++ /dev/null
@@ -1,173 +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.qi4j.manual.recipes.assemble;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Application;
-import org.qi4j.bootstrap.*;
-
-// START SNIPPET: main
-public class Main
-{
-    private static Energy4Java qi4j;
-    private static Application application;
-
-    public static void main( String[] args )
-            throws Exception
-    {
-        // Bootstrap Zest Runtime
-        // Create a Zest Runtime
-        qi4j = new Energy4Java();
-
-        // Instantiate the Application Model.
-        application = qi4j.newApplication( new ApplicationAssembler()
-        {
-            public ApplicationAssembly assemble(
-                    ApplicationAssemblyFactory factory )
-                    throws AssemblyException
-            {
-                ApplicationAssembly assembly =
-                        factory.newApplicationAssembly();
-                LayerAssembly runtime = createRuntimeLayer( assembly );
-                LayerAssembly designer = createDesignerLayer( assembly );
-                LayerAssembly domain = createDomainLayer( assembly );
-                LayerAssembly messaging= createMessagingLayer( assembly );
-                LayerAssembly persistence = createPersistenceLayer( assembly );
-
-                // declare structure between layers
-                domain.uses( messaging );
-                domain.uses( persistence );
-                designer.uses( persistence );
-                designer.uses( domain );
-                runtime.uses( domain );
-
-                return assembly;
-            }
-        } );
-
-        // We need to handle shutdown.
-        installShutdownHook();
-
-        // Activate the Application Runtime.
-        application.activate();
-    }
-
-// END SNIPPET: main
-    private static LayerAssembly createRuntimeLayer( ApplicationAssembly app )
-    {
-        LayerAssembly layer = app.layer( "runtime-layer" );
-        return layer;
-    }
-
-    private static LayerAssembly createDesignerLayer( ApplicationAssembly app )
-    {
-        LayerAssembly layer = app.layer( "designer-layer" );
-        return layer;
-    }
-
-    private static LayerAssembly createMessagingLayer( ApplicationAssembly app )
-    {
-        LayerAssembly layer = app.layer( "messaging-layer" );
-        return layer;
-    }
-
-    private static LayerAssembly createPersistenceLayer( ApplicationAssembly app )
-    {
-        LayerAssembly layer = app.layer( "persistence-layer" );
-        return layer;
-    }
-
-// START SNIPPET: domainLayer
-    private static LayerAssembly createDomainLayer( ApplicationAssembly app )
-    {
-        LayerAssembly layer = app.layer("domain-layer");
-        createAccountModule( layer );
-        createInventoryModule( layer );
-        createReceivablesModule( layer );
-        createPayablesModule( layer );
-        return layer;
-    }
-
-// END SNIPPET: domainLayer
-// START SNIPPET: accountModule
-    private static void createAccountModule( LayerAssembly layer )
-    {
-        ModuleAssembly module = layer.module("account-module");
-
-        module.entities(AccountEntity.class, EntryEntity.class);
-
-        module.addServices(
-                AccountRepositoryService.class,
-                AccountFactoryService.class,
-                EntryFactoryService.class,
-                EntryRepositoryService.class
-        ).visibleIn( Visibility.layer );
-    }
-
-// END SNIPPET: accountModule
-    private static void createPayablesModule( LayerAssembly layer )
-    {
-        layer.module("payables-module");
-    }
-
-    private static void createInventoryModule( LayerAssembly layer )
-    {
-        layer.module("inventory-module");
-    }
-
-    private static void createReceivablesModule( LayerAssembly layer )
-    {
-        layer.module("receivables-module");
-    }
-
-// START SNIPPET: shutdown
-    private static void installShutdownHook()
-    {
-        Runtime.getRuntime().addShutdownHook( new Thread( new Runnable()
-        {
-            public void run()
-            {
-                if( application != null )
-                {
-                    try
-                    {
-                        application.passivate();
-                    }
-                    catch( Exception e )
-                    {
-                        e.printStackTrace();
-                    }
-                }
-            }
-        }) );
-    }
-// END SNIPPET: shutdown
-// START SNIPPET: main
-}
-
-// END SNIPPET: main
-interface AccountEntity extends EntityComposite {};
-interface EntryEntity extends EntityComposite {};
-
-interface AccountFactoryService extends ServiceComposite{};
-interface EntryFactoryService extends ServiceComposite{};
-interface EntryRepositoryService extends ServiceComposite{};
-interface AccountRepositoryService extends ServiceComposite{};
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/concern/AnyMixinType.java b/manual/src/main/java/org/qi4j/manual/recipes/concern/AnyMixinType.java
deleted file mode 100644
index f11b76f..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/concern/AnyMixinType.java
+++ /dev/null
@@ -1,38 +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.qi4j.manual.recipes.concern;
-
-import org.qi4j.api.concern.Concerns;
-
-// START SNIPPET: annotationUse
-// START SNIPPET: class
-@Concerns( MyGenericConcern.class )
-public interface AnyMixinType
-{
-
-// START SNIPPET: class
-    @MyAnnotation
-    void doSomething();
-
-    void doSomethingElse();
-
-// END SNIPPET: class
-}
-// END SNIPPET: class
-// END SNIPPET: annotationUse
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/concern/InventoryConcern.java b/manual/src/main/java/org/qi4j/manual/recipes/concern/InventoryConcern.java
deleted file mode 100644
index 7d41006..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/concern/InventoryConcern.java
+++ /dev/null
@@ -1,33 +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.qi4j.manual.recipes.concern;
-
-public class InventoryConcern
-    implements Order
-{
-    @Override
-    public void addLineItem( LineItem item )
-    {
-    }
-
-    @Override
-    public void removeLineItem( LineItem item )
-    {
-    }
-}
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/concern/LineItem.java b/manual/src/main/java/org/qi4j/manual/recipes/concern/LineItem.java
deleted file mode 100644
index 39ae306..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/concern/LineItem.java
+++ /dev/null
@@ -1,24 +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.qi4j.manual.recipes.concern;
-
-
-public interface LineItem
-{
-}
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/concern/MyAnnotation.java b/manual/src/main/java/org/qi4j/manual/recipes/concern/MyAnnotation.java
deleted file mode 100644
index 1a95c5f..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/concern/MyAnnotation.java
+++ /dev/null
@@ -1,23 +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.qi4j.manual.recipes.concern;
-
-public @interface MyAnnotation
-{
-}
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/concern/MyAppliesToFilter.java b/manual/src/main/java/org/qi4j/manual/recipes/concern/MyAppliesToFilter.java
deleted file mode 100644
index 47a72d3..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/concern/MyAppliesToFilter.java
+++ /dev/null
@@ -1,40 +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.qi4j.manual.recipes.concern;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesToFilter;
-
-// START SNIPPET: filter
-public class MyAppliesToFilter implements AppliesToFilter
-{
-    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> modifierClass )
-    {
-        boolean appliesTo = evaluate(method); // Do whatever you want
-        return appliesTo;
-    }
-
-// START SNIPPET: filter
-    private boolean evaluate( Method method )
-    {
-        return true;
-    }
-// END SNIPPET: filter
-}
-// END SNIPPET: filter
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/concern/MyGenericConcern.java b/manual/src/main/java/org/qi4j/manual/recipes/concern/MyGenericConcern.java
deleted file mode 100644
index 58ea48e..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/concern/MyGenericConcern.java
+++ /dev/null
@@ -1,42 +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.qi4j.manual.recipes.concern;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.concern.GenericConcern;
-
-// START SNIPPET: appliesTo
-@AppliesTo( { MyAnnotation.class, MyAppliesToFilter.class } )
-// START SNIPPET: class
-public class MyGenericConcern extends GenericConcern
-{
-// END SNIPPET: appliesTo
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        // Do whatever you want
-
-// START SNIPPET: class
-// END SNIPPET: class
-        return next.invoke( proxy, method, args );
-    }
-}
-// END SNIPPET: class
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/concern/Order.java b/manual/src/main/java/org/qi4j/manual/recipes/concern/Order.java
deleted file mode 100644
index 670b2a6..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/concern/Order.java
+++ /dev/null
@@ -1,33 +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.qi4j.manual.recipes.concern;
-
-import org.qi4j.api.concern.Concerns;
-
-// START SNIPPET: class
-@Concerns( InventoryConcern.class )
-public interface Order
-{
-    void addLineItem( LineItem item );
-    void removeLineItem( LineItem item );
-
-// START SNIPPET: class
-// END SNIPPET: class
-}
-// END SNIPPET: class
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/contextualFragments/TraceAll.java b/manual/src/main/java/org/qi4j/manual/recipes/contextualFragments/TraceAll.java
deleted file mode 100644
index 273f95d..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/contextualFragments/TraceAll.java
+++ /dev/null
@@ -1,41 +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.qi4j.manual.recipes.contextualFragments;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.ServiceDeclaration;
-import org.qi4j.logging.trace.TraceAllConcern;
-
-// START SNIPPET: assemble
-public class TraceAll
-{
-    public void assemble( ModuleAssembly module )
-            throws AssemblyException
-    {
-        ServiceDeclaration decl = module.addServices( PinSearchService.class );
-        if( Boolean.getBoolean( "trace.all"  ) )
-        {
-            decl.withConcerns( TraceAllConcern.class );
-        }
-    }
-}
-
-// END SNIPPET: assemble
-class PinSearchService {}
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/Dialer.java b/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/Dialer.java
deleted file mode 100644
index 9cb8aed..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/Dialer.java
+++ /dev/null
@@ -1,27 +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.qi4j.manual.recipes.createConstraint;
-
-// START SNIPPET: dialer
-public interface Dialer
-{
-    void callPhoneNumber(@PhoneNumber String phoneNo);
-
-}
-// END SNIPPET: dialer
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/DialerComposite.java b/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/DialerComposite.java
deleted file mode 100644
index ed569e2..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/DialerComposite.java
+++ /dev/null
@@ -1,29 +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.qi4j.manual.recipes.createConstraint;
-
-import org.qi4j.api.constraint.Constraints;
-import org.qi4j.api.service.ServiceComposite;
-
-// START SNIPPET: composite
-@Constraints( PhoneNumberConstraint.class )
-public interface DialerComposite extends ServiceComposite, Dialer
-{
-}
-// END SNIPPET: composite
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/HasPhoneNumber.java b/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/HasPhoneNumber.java
deleted file mode 100644
index 810154d..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/HasPhoneNumber.java
+++ /dev/null
@@ -1,29 +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.qi4j.manual.recipes.createConstraint;
-
-import org.qi4j.api.property.Property;
-
-// START SNIPPET: property
-public interface HasPhoneNumber
-{
-    @PhoneNumber
-    Property<String> phoneNumber();
-}
-// END SNIPPET: property
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/ParameterViolationConcern.java b/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/ParameterViolationConcern.java
deleted file mode 100644
index e5ef82d..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/ParameterViolationConcern.java
+++ /dev/null
@@ -1,58 +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.qi4j.manual.recipes.createConstraint;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.constraint.ConstraintViolation;
-import org.qi4j.api.constraint.ConstraintViolationException;
-
-// START SNIPPET: report
-public class ParameterViolationConcern extends ConcernOf<InvocationHandler>
-    implements InvocationHandler
-{
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        try
-        {
-            return next.invoke( proxy, method, args );
-        }
-        catch( ConstraintViolationException e )
-        {
-            for( ConstraintViolation violation : e.constraintViolations() )
-            {
-                String name = violation.name();
-                Object value = violation.value();
-                Annotation constraint = violation.constraint();
-                report( name, value, constraint );
-            }
-            throw new IllegalArgumentException("Invalid argument(s)", e);
-        }
-    }
-
-// END SNIPPET: report
-// START SNIPPET: report
-    private void report( String name, Object value, Annotation constraint )
-    {
-    }
-}
-// END SNIPPET: report
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/PhoneNumber.java b/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/PhoneNumber.java
deleted file mode 100644
index 0540d62..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/PhoneNumber.java
+++ /dev/null
@@ -1,35 +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.qi4j.manual.recipes.createConstraint;
-
-import org.qi4j.api.constraint.ConstraintDeclaration;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-// START SNIPPET: annotation
-@ConstraintDeclaration
-@Retention( RetentionPolicy.RUNTIME )
-@Target( { ElementType.PARAMETER, ElementType.ANNOTATION_TYPE, ElementType.METHOD } )
-public @interface PhoneNumber
-{
-}
-// END SNIPPET: annotation
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/PhoneNumberConstraint.java b/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/PhoneNumberConstraint.java
deleted file mode 100644
index 7ed3fde..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/PhoneNumberConstraint.java
+++ /dev/null
@@ -1,33 +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.qi4j.manual.recipes.createConstraint;
-
-import org.qi4j.api.constraint.Constraint;
-
-// START SNIPPET: constraint
-public class PhoneNumberConstraint
-        implements Constraint<PhoneNumber, String>
-{
-    public boolean isValid( PhoneNumber annotation, String number )
-    {
-        boolean validPhoneNumber = true; // check phone number format...
-        return validPhoneNumber;  // return true if valid phone number.
-    }
-}
-// END SNIPPET: constraint
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/PhoneNumberParameterViolationConcern.java b/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/PhoneNumberParameterViolationConcern.java
deleted file mode 100644
index 1303b08..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createConstraint/PhoneNumberParameterViolationConcern.java
+++ /dev/null
@@ -1,59 +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.qi4j.manual.recipes.createConstraint;
-
-import java.util.Collection;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.constraint.ConstraintViolation;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.property.Property;
-
-// START SNIPPET: property
-public abstract class PhoneNumberParameterViolationConcern extends ConcernOf<HasPhoneNumber>
-    implements HasPhoneNumber
-{
-    @Concerns( CheckViolation.class )
-    public abstract Property<String> phoneNumber();
-
-    private abstract class CheckViolation extends ConcernOf<Property<String>>
-        implements Property<String>
-    {
-        public void set( String number )
-        {
-            try
-            {
-                next.set( number );
-            }
-            catch( ConstraintViolationException e )
-            {
-                Collection<ConstraintViolation> violations = e.constraintViolations();
-                report( violations );
-            }
-        }
-
-// END SNIPPET: property
-
-// START SNIPPET: property
-        private void report( Collection<ConstraintViolation> violations )
-        {
-        }
-    }
-}
-// END SNIPPET: property
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/Accident.java b/manual/src/main/java/org/qi4j/manual/recipes/createEntity/Accident.java
deleted file mode 100644
index 606e396..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/Accident.java
+++ /dev/null
@@ -1,32 +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.qi4j.manual.recipes.createEntity;
-
-import org.qi4j.api.property.Property;
-import java.util.Date;
-
-// START SNIPPET: entity
-public interface Accident
-{
-    Property<String> description();
-    Property<Date> occured();
-    Property<Date> repaired();
-}
-
-// END SNIPPET: entity
\ No newline at end of file
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/AccidentValue.java b/manual/src/main/java/org/qi4j/manual/recipes/createEntity/AccidentValue.java
deleted file mode 100644
index 5928630..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/AccidentValue.java
+++ /dev/null
@@ -1,27 +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.qi4j.manual.recipes.createEntity;
-
-import org.qi4j.api.value.ValueComposite;
-
-// START SNIPPET: composite
-public interface AccidentValue extends Accident, ValueComposite
-{}
-
-// END SNIPPET: composite
\ No newline at end of file
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/Car.java b/manual/src/main/java/org/qi4j/manual/recipes/createEntity/Car.java
deleted file mode 100644
index 72cc30d..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/Car.java
+++ /dev/null
@@ -1,38 +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.qi4j.manual.recipes.createEntity;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-
-// START SNIPPET: entity
-public interface Car
-{
-    @Immutable
-    Association<Manufacturer> manufacturer();
-
-    @Immutable
-    Property<String> model();
-
-    ManyAssociation<Accident> accidents();
-}
-
-// END SNIPPET: entity
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntity.java b/manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntity.java
deleted file mode 100644
index fb12239..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntity.java
+++ /dev/null
@@ -1,27 +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.qi4j.manual.recipes.createEntity;
-
-import org.qi4j.api.entity.EntityComposite;
-
-// START SNIPPET: composite
-public interface CarEntity extends Car, EntityComposite
-{}
-
-// END SNIPPET: composite
\ No newline at end of file
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntityFactory.java b/manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntityFactory.java
deleted file mode 100644
index 780e9ff..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntityFactory.java
+++ /dev/null
@@ -1,27 +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.qi4j.manual.recipes.createEntity;
-
-// START SNIPPET: carFactory
-public interface CarEntityFactory
-{
-    Car create(Manufacturer manufacturer, String model);
-}
-
-// END SNIPPET: carFactory
\ No newline at end of file
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntityFactoryMixin.java b/manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntityFactoryMixin.java
deleted file mode 100644
index 20542b8..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntityFactoryMixin.java
+++ /dev/null
@@ -1,56 +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.qi4j.manual.recipes.createEntity;
-
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-
-// START SNIPPET: carFactoryMixin2
-// START SNIPPET: carFactoryMixin1
-public class CarEntityFactoryMixin
-        implements CarEntityFactory
-{
-
-// END SNIPPET: carFactoryMixin1
-    @Structure
-    Module module;
-// END SNIPPET: carFactoryMixin2
-// START SNIPPET: carFactoryMixin3
-    public CarEntityFactoryMixin( @Structure Module module )
-    {
-    }
-
-// END SNIPPET: carFactoryMixin3
-// START SNIPPET: createCar
-    public Car create(Manufacturer manufacturer, String model)
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        EntityBuilder<Car> builder = uow.newEntityBuilder( Car.class );
-
-        Car prototype = builder.instance();
-        prototype.manufacturer().set( manufacturer );
-        prototype.model().set( model );
-
-        return builder.newInstance();
-    }
-// END SNIPPET: createCar
-}
-
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntityFactoryService.java b/manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntityFactoryService.java
deleted file mode 100644
index 68347ed..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/CarEntityFactoryService.java
+++ /dev/null
@@ -1,29 +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.qi4j.manual.recipes.createEntity;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-// START SNIPPET: carFactoryService
-@Mixins( { CarEntityFactoryMixin.class } )
-public interface CarEntityFactoryService
-        extends CarEntityFactory, ServiceComposite
-{}
-// END SNIPPET: carFactoryService
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/Main.java b/manual/src/main/java/org/qi4j/manual/recipes/createEntity/Main.java
deleted file mode 100644
index d65efb2..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/Main.java
+++ /dev/null
@@ -1,44 +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.qi4j.manual.recipes.createEntity;
-
-import org.qi4j.api.structure.Application;
-import org.qi4j.bootstrap.*;
-
-public class Main
-{
-    public static void main(String[] args) throws Exception
-    {
-
-        Energy4Java qi4j = new Energy4Java();
-
-        // Instantiate the Application Model.
-        Application application = qi4j.newApplication( new ApplicationAssembler()
-        {
-            @Override
-            public ApplicationAssembly assemble(ApplicationAssemblyFactory applicationFactory) throws AssemblyException
-            {
-                return applicationFactory.newApplicationAssembly( new MyAssembler()) ;
-            }
-        });
-
-        application.activate();
-
-    }
-}
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/Manufacturer.java b/manual/src/main/java/org/qi4j/manual/recipes/createEntity/Manufacturer.java
deleted file mode 100644
index c2087ca..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/Manufacturer.java
+++ /dev/null
@@ -1,34 +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.qi4j.manual.recipes.createEntity;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-
-// START SNIPPET: entity
-public interface Manufacturer
-{
-    Property<String> name();
-    Property<String> country();
-
-    @UseDefaults
-    Property<Long> carsProduced();
-}
-
-// END SNIPPET: entity
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/ManufacturerEntity.java b/manual/src/main/java/org/qi4j/manual/recipes/createEntity/ManufacturerEntity.java
deleted file mode 100644
index 94b2e1a..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/ManufacturerEntity.java
+++ /dev/null
@@ -1,27 +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.qi4j.manual.recipes.createEntity;
-
-import org.qi4j.api.entity.EntityComposite;
-
-// START SNIPPET: composite
-public interface ManufacturerEntity extends Manufacturer, EntityComposite
-{}
-
-// END SNIPPET: composite
\ No newline at end of file
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/ManufacturerRepository.java b/manual/src/main/java/org/qi4j/manual/recipes/createEntity/ManufacturerRepository.java
deleted file mode 100644
index 2a080f1..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/ManufacturerRepository.java
+++ /dev/null
@@ -1,28 +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.qi4j.manual.recipes.createEntity;
-
-// START SNIPPET: repo
-public interface ManufacturerRepository
-{
-    Manufacturer findByIdentity(String identity);
-
-    Manufacturer findByName(String name);
-}
-// END SNIPPET: repo
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/ManufacturerRepositoryMixin.java b/manual/src/main/java/org/qi4j/manual/recipes/createEntity/ManufacturerRepositoryMixin.java
deleted file mode 100644
index 9389e0f..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/ManufacturerRepositoryMixin.java
+++ /dev/null
@@ -1,63 +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.qi4j.manual.recipes.createEntity;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-
-import java.util.Iterator;
-
-import static org.qi4j.api.query.QueryExpressions.eq;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-// START SNIPPET: repo
-public class ManufacturerRepositoryMixin
-        implements ManufacturerRepository
-{
-    @Structure
-    private UnitOfWorkFactory uowf;
-
-    @Structure
-    private Module module;
-
-    public Manufacturer findByIdentity( String identity )
-    {
-        UnitOfWork uow = uowf.currentUnitOfWork();
-        return uow.get(Manufacturer.class, identity);
-    }
-
-    public Manufacturer findByName( String name )
-    {
-        UnitOfWork uow = uowf.currentUnitOfWork();
-        QueryBuilder<Manufacturer> builder =
-                module.newQueryBuilder( Manufacturer.class );
-
-        Manufacturer template = templateFor( Manufacturer.class );
-        builder.where( eq( template.name(), name ) );
-
-        Query<Manufacturer> query = uow.newQuery( builder);
-        return query.find();
-    }
-}
-
-// END SNIPPET: repo
\ No newline at end of file
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/ManufacturerRepositoryService.java b/manual/src/main/java/org/qi4j/manual/recipes/createEntity/ManufacturerRepositoryService.java
deleted file mode 100644
index 31c8d6b..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/ManufacturerRepositoryService.java
+++ /dev/null
@@ -1,29 +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.qi4j.manual.recipes.createEntity;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-// START SNIPPET: manufacturerRepositoryService
-@Mixins( ManufacturerRepositoryMixin.class  )
-public interface ManufacturerRepositoryService
-        extends ManufacturerRepository, ServiceComposite
-{}
-// END SNIPPET: manufacturerRepositoryService
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/MyAssembler.java b/manual/src/main/java/org/qi4j/manual/recipes/createEntity/MyAssembler.java
deleted file mode 100644
index fe9a0bd..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/createEntity/MyAssembler.java
+++ /dev/null
@@ -1,45 +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.qi4j.manual.recipes.createEntity;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-// START SNIPPET: assembler2
-// START SNIPPET: assembler1
-public class MyAssembler
-        implements Assembler
-{
-    public void assemble( ModuleAssembly module )
-    {
-        module.entities( CarEntity.class,
-                ManufacturerEntity.class );
-
-        module.values( AccidentValue.class );
-// END SNIPPET: assembler1
-        module.addServices(
-                ManufacturerRepositoryService.class,
-                CarEntityFactoryService.class
-        ).visibleIn( Visibility.application );
-// START SNIPPET: assembler1
-    }
-}
-// END SNIPPET: assembler1
-// END SNIPPET: assembler2
\ No newline at end of file
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/io/Docs.java b/manual/src/main/java/org/qi4j/manual/recipes/io/Docs.java
deleted file mode 100644
index 71a21aa..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/io/Docs.java
+++ /dev/null
@@ -1,38 +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.qi4j.manual.recipes.io;
-
-import java.io.File;
-import java.io.IOException;
-import org.qi4j.io.Inputs;
-import org.qi4j.io.Outputs;
-
-public class Docs
-{
-
-    public void filter()
-        throws IOException
-    {
-// START SNIPPET: filter
-        File source = new File("source.txt");
-        File destination = new File("destination.txt");
-        Inputs.text( source ).transferTo( Outputs.text( destination ) );
-// END SNIPPET: filter
-    }
-}
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/properties/Book.java b/manual/src/main/java/org/qi4j/manual/recipes/properties/Book.java
deleted file mode 100644
index 81fba20..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/properties/Book.java
+++ /dev/null
@@ -1,33 +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.qi4j.manual.recipes.properties;
-
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-
-// START SNIPPET: book
-public interface Book
-{
-    @Immutable
-    Property<String> title();
-
-    @Immutable
-    Property<String> author();
-}
-// END SNIPPET: book
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/properties/BookFactory.java b/manual/src/main/java/org/qi4j/manual/recipes/properties/BookFactory.java
deleted file mode 100644
index 527ab8a..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/properties/BookFactory.java
+++ /dev/null
@@ -1,45 +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.qi4j.manual.recipes.properties;
-
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.structure.Module;
-
-public class BookFactory
-{
-// START SNIPPET: create
-    @Structure
-    Module module;
-// END SNIPPET: create
-
-    public Book create()
-    {
-// START SNIPPET: create
-        TransientBuilder<Book> builder = module.newTransientBuilder( Book.class );
-        Book prototype = builder.prototype();
-        prototype.title().set( "The Death of POJOs" );
-        prototype.author().set( "Niclas Hedhman" );
-        Book book = builder.newInstance();
-        String title = book.title().get();     // Retrieves the title.
-        book.title().set( "Long Live POJOs" ); // throws an IllegalStateException
-// END SNIPPET: create
-        return book;
-    }
-}
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/properties/SwingInfo.java b/manual/src/main/java/org/qi4j/manual/recipes/properties/SwingInfo.java
deleted file mode 100644
index 0782adf..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/properties/SwingInfo.java
+++ /dev/null
@@ -1,32 +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.qi4j.manual.recipes.properties;
-
-import java.awt.Rectangle;
-import java.util.Locale;
-import javax.swing.Icon;
-
-// START SNIPPET: info
-public interface SwingInfo
-{
-    Icon icon( Rectangle size );
-
-    String displayName( Locale locale );
-}
-// END SNIPPET: info
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/properties/SwingPanel.java b/manual/src/main/java/org/qi4j/manual/recipes/properties/SwingPanel.java
deleted file mode 100644
index 9736d11..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/properties/SwingPanel.java
+++ /dev/null
@@ -1,48 +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.qi4j.manual.recipes.properties;
-
-import java.awt.Rectangle;
-import java.util.Locale;
-import javax.swing.Icon;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.property.Property;
-
-public class SwingPanel
-{
-    private static final Rectangle SIZE_32_32 = new Rectangle( 32, 32 );
-    private Locale locale;
-
-// START SNIPPET: info-use
-    @Structure
-    private Qi4j api;
-// END SNIPPET: info-use
-
-// START SNIPPET: info-use
-    private void addProperty( JPanel panel, Property<?> property )
-    {
-        SwingInfo info = api.propertyDescriptorFor( property ).metaInfo( SwingInfo.class );
-        Icon icon = info.icon( SIZE_32_32 );
-        panel.add(  new JLabel(info.displayName( this.locale ), icon, JLabel.CENTER) );
-    }
-// START SNIPPET: info-use
-}
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/properties/pojo/Book.java b/manual/src/main/java/org/qi4j/manual/recipes/properties/pojo/Book.java
deleted file mode 100644
index a394657..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/properties/pojo/Book.java
+++ /dev/null
@@ -1,27 +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.qi4j.manual.recipes.properties.pojo;
-
-// START SNIPPET: book
-public interface Book
-{
-    String getTitle();
-    String getAuthor();
-}
-// END SNIPPET: book
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/properties/pojo/MutableBook.java b/manual/src/main/java/org/qi4j/manual/recipes/properties/pojo/MutableBook.java
deleted file mode 100644
index 23a8fa9..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/properties/pojo/MutableBook.java
+++ /dev/null
@@ -1,28 +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.qi4j.manual.recipes.properties.pojo;
-
-
-// START SNIPPET: mutableBook
-public interface MutableBook extends Book
-{
-    void setTitle( String title );
-    void setAuthor( String author );
-}
-// END SNIPPET: mutableBook
\ No newline at end of file
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/AnyMixinType.java b/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/AnyMixinType.java
deleted file mode 100644
index 1c7e841..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/AnyMixinType.java
+++ /dev/null
@@ -1,38 +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.qi4j.manual.recipes.sideeffects;
-
-import org.qi4j.api.concern.Concerns;
-
-// START SNIPPET: body
-// START SNIPPET: annotation
-@Concerns( MyGenericSideEffect.class )
-public interface AnyMixinType
-{
-// END SNIPPET: body
-
-    @MyAnnotation
-    void doSomething();
-
-    void doSomethingElse();
-
-// START SNIPPET: body
-}
-// START SNIPPET: annotation
-// END SNIPPET: body
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/Confirmable.java b/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/Confirmable.java
deleted file mode 100644
index 2723472..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/Confirmable.java
+++ /dev/null
@@ -1,23 +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.qi4j.manual.recipes.sideeffects;
-
-public interface Confirmable
-{
-}
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/HasCustomer.java b/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/HasCustomer.java
deleted file mode 100644
index ecfc9b3..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/HasCustomer.java
+++ /dev/null
@@ -1,23 +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.qi4j.manual.recipes.sideeffects;
-
-public interface HasCustomer
-{
-}
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/HasLineItems.java b/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/HasLineItems.java
deleted file mode 100644
index 9bd2de1..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/HasLineItems.java
+++ /dev/null
@@ -1,23 +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.qi4j.manual.recipes.sideeffects;
-
-public interface HasLineItems
-{
-}
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/HasSequenceNumber.java b/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/HasSequenceNumber.java
deleted file mode 100644
index cbb53ee..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/HasSequenceNumber.java
+++ /dev/null
@@ -1,23 +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.qi4j.manual.recipes.sideeffects;
-
-public interface HasSequenceNumber
-{
-}
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/MailNotifySideEffect.java b/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/MailNotifySideEffect.java
deleted file mode 100644
index 05b6ddd..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/MailNotifySideEffect.java
+++ /dev/null
@@ -1,26 +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.qi4j.manual.recipes.sideeffects;
-
-import org.qi4j.api.sideeffect.SideEffectOf;
-
-public class MailNotifySideEffect extends SideEffectOf<Order>
-    implements Order
-{
-}
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/MyAnnotation.java b/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/MyAnnotation.java
deleted file mode 100644
index c2664bd..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/MyAnnotation.java
+++ /dev/null
@@ -1,23 +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.qi4j.manual.recipes.sideeffects;
-
-public @interface MyAnnotation
-{
-}
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/MyAppliesToFilter.java b/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/MyAppliesToFilter.java
deleted file mode 100644
index f09e4e5..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/MyAppliesToFilter.java
+++ /dev/null
@@ -1,40 +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.qi4j.manual.recipes.sideeffects;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesToFilter;
-
-// START SNIPPET: filter
-public class MyAppliesToFilter implements AppliesToFilter
-{
-    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> modifierClass )
-    {
-        boolean appliesTo = evaluate(method); // Do whatever you want
-        return appliesTo;
-    }
-
-// START SNIPPET: filter
-    private boolean evaluate( Method method )
-    {
-        return true;
-    }
-// END SNIPPET: filter
-}
-// END SNIPPET: filter
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/MyGenericSideEffect.java b/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/MyGenericSideEffect.java
deleted file mode 100644
index 89432d5..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/MyGenericSideEffect.java
+++ /dev/null
@@ -1,51 +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.qi4j.manual.recipes.sideeffects;
-
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.sideeffect.GenericSideEffect;
-
-// START SNIPPET: appliesTo
-@AppliesTo( { MyAnnotation.class, MyAppliesToFilter.class } )
-// START SNIPPET: body
-public class MyGenericSideEffect extends GenericSideEffect
-{
-// END SNIPPET: appliesTo
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        // Do whatever you need...
-
-        try
-        {
-            // It is possible to obtain the returned values by using 'result' member;
-            Object returnedValue = result.invoke( proxy, method, args );
-        } catch( NumberFormatException e )
-        {
-            // And Exception will be thrown accordingly, in case you need to know.
-            throw new IllegalArgumentException(); // But any thrown exceptions are ignored.
-        }
-        return 23; // Return values will also be ignored.
-    }
-// START SNIPPET: appliesTo
-}
-// END SNIPPET: appliesTo
-// END SNIPPET: body
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/Order.java b/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/Order.java
deleted file mode 100644
index 3624835..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/Order.java
+++ /dev/null
@@ -1,23 +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.qi4j.manual.recipes.sideeffects;
-
-public interface Order
-{
-}
diff --git a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/OrderEntity.java b/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/OrderEntity.java
deleted file mode 100644
index 8875ff0..0000000
--- a/manual/src/main/java/org/qi4j/manual/recipes/sideeffects/OrderEntity.java
+++ /dev/null
@@ -1,31 +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.qi4j.manual.recipes.sideeffects;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.sideeffect.SideEffects;
-
-// START SNIPPET: body
-@SideEffects( MailNotifySideEffect.class )
-public interface OrderEntity
-    extends Order, HasSequenceNumber, HasCustomer,
-            HasLineItems, Confirmable, EntityComposite
-{
-}
-// END SNIPPET: body
diff --git a/manual/src/main/java/org/qi4j/manual/travel/ExpediaService.properties b/manual/src/main/java/org/qi4j/manual/travel/ExpediaService.properties
deleted file mode 100644
index 5e00430..0000000
--- a/manual/src/main/java/org/qi4j/manual/travel/ExpediaService.properties
+++ /dev/null
@@ -1,25 +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.
-
-#// START SNIPPET: params
-# Hostname to the TravelPlan service
-hostName=expedia.hedhman.org
-
-# Port number to use for the connection
-portNumber=9251
-
-# Protocol to use; Valid options "ssh", "rlogin", "telnet"
-protocol=ssh
-#// END SNIPPET: params
\ No newline at end of file
diff --git a/manual/src/main/java/org/qi4j/manual/travel/Main.java b/manual/src/main/java/org/qi4j/manual/travel/Main.java
deleted file mode 100644
index 167b286..0000000
--- a/manual/src/main/java/org/qi4j/manual/travel/Main.java
+++ /dev/null
@@ -1,62 +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.qi4j.manual.travel;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-public class Main
-{
-
-    public static void main(String[] args) throws Exception
-    {
-        SingletonAssembler singleton = new SingletonAssembler()
-        {
-            @Override
-// START SNIPPET: assemble
-            public void assemble(ModuleAssembly module) throws AssemblyException
-            {
-                module.addServices(TravelPlanService.class)
-                        .instantiateOnStartup()
-                        .identifiedBy("ExpediaService");
-
-                module.addServices(TravelPlanService.class)
-                        .instantiateOnStartup()
-                        .identifiedBy("OrbitzService");
-            }
-// END SNIPPET: assemble
-        };
-    }
-
-    public static void simple(String[] args) throws Exception
-    {
-        SingletonAssembler singleton = new SingletonAssembler()
-        {
-            @Override
-// START SNIPPET: simple
-            public void assemble(ModuleAssembly module) throws AssemblyException
-            {
-                module.addServices(TravelPlanService.class).instantiateOnStartup();
-            }
-// END SNIPPET: simple
-        };
-    }
-
-}
\ No newline at end of file
diff --git a/manual/src/main/java/org/qi4j/manual/travel/OrbitzService.properties b/manual/src/main/java/org/qi4j/manual/travel/OrbitzService.properties
deleted file mode 100644
index 5f410f8..0000000
--- a/manual/src/main/java/org/qi4j/manual/travel/OrbitzService.properties
+++ /dev/null
@@ -1,25 +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.
-
-#// START SNIPPET: params
-# Hostname to the TravelPlan service
-hostName=orbitz.hedhman.org
-
-# Port number to use for the connection
-portNumber=7412
-
-# Protocol to use; Valid options "ssh", "rlogin", "telnet"
-protocol=rlogin
-#// END SNIPPET: params
\ No newline at end of file
diff --git a/manual/src/main/java/org/qi4j/manual/travel/TravelPlan.java b/manual/src/main/java/org/qi4j/manual/travel/TravelPlan.java
deleted file mode 100644
index 6067b82..0000000
--- a/manual/src/main/java/org/qi4j/manual/travel/TravelPlan.java
+++ /dev/null
@@ -1,26 +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.qi4j.manual.travel;
-
-// START SNIPPET: service
-public interface TravelPlan
-{
-    // Domain methods, which are beyond the discussion at hand.
-}
-// END SNIPPET: service
\ No newline at end of file
diff --git a/manual/src/main/java/org/qi4j/manual/travel/TravelPlanConfiguration.java b/manual/src/main/java/org/qi4j/manual/travel/TravelPlanConfiguration.java
deleted file mode 100644
index 55a7cc9..0000000
--- a/manual/src/main/java/org/qi4j/manual/travel/TravelPlanConfiguration.java
+++ /dev/null
@@ -1,36 +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.qi4j.manual.travel;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.library.constraints.annotation.Matches;
-import org.qi4j.library.constraints.annotation.Range;
-
-// START SNIPPET: configuration
-public interface TravelPlanConfiguration
-{
-    Property<String> hostName();
-
-    @Range( min=0, max=65535 )
-    Property<Integer> portNumber();
-
-    @Matches( "(ssh|rlogin|telnet)" )
-    Property<String> protocol();
-}
-// END SNIPPET: configuration
\ No newline at end of file
diff --git a/manual/src/main/java/org/qi4j/manual/travel/TravelPlanMixin.java b/manual/src/main/java/org/qi4j/manual/travel/TravelPlanMixin.java
deleted file mode 100644
index f5bba98..0000000
--- a/manual/src/main/java/org/qi4j/manual/travel/TravelPlanMixin.java
+++ /dev/null
@@ -1,51 +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.qi4j.manual.travel;
-
-import org.qi4j.api.injection.scope.This;
-// START SNIPPET: mixin
-import org.qi4j.api.configuration.Configuration;
-
-public class TravelPlanMixin implements TravelPlan
-{
-    @This
-    Configuration<TravelPlanConfiguration> config;
-
-    private void foo()
-    {
-        TravelPlanConfiguration tpConf = config.get();
-        String hostName = tpConf.hostName().get();
-        // ...
-    }
-// END SNIPPET: mixin
-
-    // START SNIPPET: refresh
-    public void doSomething()
-    {
-        // Refresh Configuration before reading it.
-        config.refresh();
-
-        TravelPlanConfiguration tpConf = config.get();
-        // ...
-    }
-    // END SNIPPET: refresh
-
-// START SNIPPET: mixin
-}
-// END SNIPPET: mixin
\ No newline at end of file
diff --git a/manual/src/main/java/org/qi4j/manual/travel/TravelPlanService.java b/manual/src/main/java/org/qi4j/manual/travel/TravelPlanService.java
deleted file mode 100644
index be772ae..0000000
--- a/manual/src/main/java/org/qi4j/manual/travel/TravelPlanService.java
+++ /dev/null
@@ -1,31 +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.
- */
-// START SNIPPET: serviceComposite
-// The package is relevant to the Initial Values discussed later.
-package org.qi4j.manual.travel;
-// END SNIPPET: serviceComposite
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-// START SNIPPET: serviceComposite
-@Mixins( { TravelPlanMixin.class } )
-public interface TravelPlanService extends TravelPlan, ServiceComposite
-{}
-// END SNIPPET: serviceComposite
\ No newline at end of file
diff --git a/manual/src/main/java/org/qi4j/manual/travel/TravelPlanService.properties b/manual/src/main/java/org/qi4j/manual/travel/TravelPlanService.properties
deleted file mode 100644
index 0a2b9d0..0000000
--- a/manual/src/main/java/org/qi4j/manual/travel/TravelPlanService.properties
+++ /dev/null
@@ -1,26 +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.
-
-#// START SNIPPET: params
-# Hostname to the TravelPlan service
-hostName=niclas.hedhman.org
-
-# Port number to use for the connection
-portNumber=5439
-
-# Protocol to use; Valid options "ssh", "rlogin", "telnet"
-protocol=ssh
-
-#// END SNIPPET: params
\ No newline at end of file
diff --git a/manual/src/resources/css/progressive-enhancement.css b/manual/src/resources/css/progressive-enhancement.css
index 590ec6d..a6a551b 100644
--- a/manual/src/resources/css/progressive-enhancement.css
+++ b/manual/src/resources/css/progressive-enhancement.css
@@ -1,20 +1,21 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
 /**
@@ -117,7 +118,7 @@
 /**
  * Google Groups forum
 */
-#qi4j-dev-iframe {
+#polygene-dev-iframe {
     -moz-transform: scale(0.85, 0.85); 
     -webkit-transform: scale(0.85, 0.85); 
     -o-transform: scale(0.85, 0.85);
diff --git a/manual/src/resources/images/icons/admon/caution.svg b/manual/src/resources/images/icons/admon/caution.svg
index e09ecca..3832910 100644
--- a/manual/src/resources/images/icons/admon/caution.svg
+++ b/manual/src/resources/images/icons/admon/caution.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Created with Inkscape (http://www.inkscape.org/) -->
 <svg
    xmlns:dc="http://purl.org/dc/elements/1.1/"
diff --git a/manual/src/resources/images/icons/admon/important.svg b/manual/src/resources/images/icons/admon/important.svg
index 75bec8c..a7384f7 100644
--- a/manual/src/resources/images/icons/admon/important.svg
+++ b/manual/src/resources/images/icons/admon/important.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Created with Inkscape (http://www.inkscape.org/) -->
 <svg
    xmlns:dc="http://purl.org/dc/elements/1.1/"
diff --git a/manual/src/resources/images/icons/admon/note.svg b/manual/src/resources/images/icons/admon/note.svg
index 9710292..05d3592 100644
--- a/manual/src/resources/images/icons/admon/note.svg
+++ b/manual/src/resources/images/icons/admon/note.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Created with Inkscape (http://www.inkscape.org/) -->
 <svg
    xmlns:dc="http://purl.org/dc/elements/1.1/"
diff --git a/manual/src/resources/images/icons/admon/tip.svg b/manual/src/resources/images/icons/admon/tip.svg
index 922b316..6e618ec 100644
--- a/manual/src/resources/images/icons/admon/tip.svg
+++ b/manual/src/resources/images/icons/admon/tip.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Created with Inkscape (http://www.inkscape.org/) -->
 <svg
    xmlns:dc="http://purl.org/dc/elements/1.1/"
diff --git a/manual/src/resources/images/icons/admon/warning.svg b/manual/src/resources/images/icons/admon/warning.svg
index 04ce3a7..1039f57 100644
--- a/manual/src/resources/images/icons/admon/warning.svg
+++ b/manual/src/resources/images/icons/admon/warning.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Created with Inkscape (http://www.inkscape.org/) -->
 <svg
    xmlns:dc="http://purl.org/dc/elements/1.1/"
diff --git a/manual/src/resources/images/icons/callouts/1.svg b/manual/src/resources/images/icons/callouts/1.svg
index e2e87dc..0949e57 100644
--- a/manual/src/resources/images/icons/callouts/1.svg
+++ b/manual/src/resources/images/icons/callouts/1.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/10.svg b/manual/src/resources/images/icons/callouts/10.svg
index 4740f58..2936e25 100644
--- a/manual/src/resources/images/icons/callouts/10.svg
+++ b/manual/src/resources/images/icons/callouts/10.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/11.svg b/manual/src/resources/images/icons/callouts/11.svg
index 09a0b2c..d65789a 100644
--- a/manual/src/resources/images/icons/callouts/11.svg
+++ b/manual/src/resources/images/icons/callouts/11.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/12.svg b/manual/src/resources/images/icons/callouts/12.svg
index 9794044..f8eaf8c 100644
--- a/manual/src/resources/images/icons/callouts/12.svg
+++ b/manual/src/resources/images/icons/callouts/12.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/13.svg b/manual/src/resources/images/icons/callouts/13.svg
index 64268bb..693e8d5 100644
--- a/manual/src/resources/images/icons/callouts/13.svg
+++ b/manual/src/resources/images/icons/callouts/13.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/14.svg b/manual/src/resources/images/icons/callouts/14.svg
index 469aa97..b0dbcdc 100644
--- a/manual/src/resources/images/icons/callouts/14.svg
+++ b/manual/src/resources/images/icons/callouts/14.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/15.svg b/manual/src/resources/images/icons/callouts/15.svg
index 8202233..697c58b 100644
--- a/manual/src/resources/images/icons/callouts/15.svg
+++ b/manual/src/resources/images/icons/callouts/15.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/16.svg b/manual/src/resources/images/icons/callouts/16.svg
index 01d6bf8..656fe12 100644
--- a/manual/src/resources/images/icons/callouts/16.svg
+++ b/manual/src/resources/images/icons/callouts/16.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/17.svg b/manual/src/resources/images/icons/callouts/17.svg
index 0a04c55..8879bf7 100644
--- a/manual/src/resources/images/icons/callouts/17.svg
+++ b/manual/src/resources/images/icons/callouts/17.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/18.svg b/manual/src/resources/images/icons/callouts/18.svg
index 1cb891b..ae64e5b 100644
--- a/manual/src/resources/images/icons/callouts/18.svg
+++ b/manual/src/resources/images/icons/callouts/18.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/19.svg b/manual/src/resources/images/icons/callouts/19.svg
index e6fbb17..5d25807 100644
--- a/manual/src/resources/images/icons/callouts/19.svg
+++ b/manual/src/resources/images/icons/callouts/19.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/2.svg b/manual/src/resources/images/icons/callouts/2.svg
index 07d0339..e0f836c 100644
--- a/manual/src/resources/images/icons/callouts/2.svg
+++ b/manual/src/resources/images/icons/callouts/2.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/20.svg b/manual/src/resources/images/icons/callouts/20.svg
index ccbfd40..b08acba 100644
--- a/manual/src/resources/images/icons/callouts/20.svg
+++ b/manual/src/resources/images/icons/callouts/20.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/21.svg b/manual/src/resources/images/icons/callouts/21.svg
index 93ec53f..0d900fa 100644
--- a/manual/src/resources/images/icons/callouts/21.svg
+++ b/manual/src/resources/images/icons/callouts/21.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/22.svg b/manual/src/resources/images/icons/callouts/22.svg
index f48c5f3..400475a 100644
--- a/manual/src/resources/images/icons/callouts/22.svg
+++ b/manual/src/resources/images/icons/callouts/22.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/23.svg b/manual/src/resources/images/icons/callouts/23.svg
index 6624212..7eef0d8 100644
--- a/manual/src/resources/images/icons/callouts/23.svg
+++ b/manual/src/resources/images/icons/callouts/23.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/24.svg b/manual/src/resources/images/icons/callouts/24.svg
index a3d5525..6be76be 100644
--- a/manual/src/resources/images/icons/callouts/24.svg
+++ b/manual/src/resources/images/icons/callouts/24.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/25.svg b/manual/src/resources/images/icons/callouts/25.svg
index 56614a9..88f7b09 100644
--- a/manual/src/resources/images/icons/callouts/25.svg
+++ b/manual/src/resources/images/icons/callouts/25.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/26.svg b/manual/src/resources/images/icons/callouts/26.svg
index 56faeac..e2b7bc1 100644
--- a/manual/src/resources/images/icons/callouts/26.svg
+++ b/manual/src/resources/images/icons/callouts/26.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/27.svg b/manual/src/resources/images/icons/callouts/27.svg
index a75c812..6ef2f3b 100644
--- a/manual/src/resources/images/icons/callouts/27.svg
+++ b/manual/src/resources/images/icons/callouts/27.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/28.svg b/manual/src/resources/images/icons/callouts/28.svg
index 7f8cf1a..b018583 100644
--- a/manual/src/resources/images/icons/callouts/28.svg
+++ b/manual/src/resources/images/icons/callouts/28.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/29.svg b/manual/src/resources/images/icons/callouts/29.svg
index cb63adf..7ed795c 100644
--- a/manual/src/resources/images/icons/callouts/29.svg
+++ b/manual/src/resources/images/icons/callouts/29.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/3.svg b/manual/src/resources/images/icons/callouts/3.svg
index 918be80..225df6f 100644
--- a/manual/src/resources/images/icons/callouts/3.svg
+++ b/manual/src/resources/images/icons/callouts/3.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/30.svg b/manual/src/resources/images/icons/callouts/30.svg
index dc43ba1..1b09d60 100644
--- a/manual/src/resources/images/icons/callouts/30.svg
+++ b/manual/src/resources/images/icons/callouts/30.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/4.svg b/manual/src/resources/images/icons/callouts/4.svg
index 8eb6a53..6c108fd 100644
--- a/manual/src/resources/images/icons/callouts/4.svg
+++ b/manual/src/resources/images/icons/callouts/4.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/5.svg b/manual/src/resources/images/icons/callouts/5.svg
index ca7a9f2..164f440 100644
--- a/manual/src/resources/images/icons/callouts/5.svg
+++ b/manual/src/resources/images/icons/callouts/5.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/6.svg b/manual/src/resources/images/icons/callouts/6.svg
index 783a0b9..c4d831e 100644
--- a/manual/src/resources/images/icons/callouts/6.svg
+++ b/manual/src/resources/images/icons/callouts/6.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/7.svg b/manual/src/resources/images/icons/callouts/7.svg
index 59b3714..e28a65c 100644
--- a/manual/src/resources/images/icons/callouts/7.svg
+++ b/manual/src/resources/images/icons/callouts/7.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/8.svg b/manual/src/resources/images/icons/callouts/8.svg
index c1803a3..3d6935c 100644
--- a/manual/src/resources/images/icons/callouts/8.svg
+++ b/manual/src/resources/images/icons/callouts/8.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/icons/callouts/9.svg b/manual/src/resources/images/icons/callouts/9.svg
index bc149d3..f5d70eb 100644
--- a/manual/src/resources/images/icons/callouts/9.svg
+++ b/manual/src/resources/images/icons/callouts/9.svg
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448)  -->
 <!DOCTYPE svg [
 	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
diff --git a/manual/src/resources/images/logo-box.jpg b/manual/src/resources/images/logo-box-qi4j.jpg
similarity index 100%
rename from manual/src/resources/images/logo-box.jpg
rename to manual/src/resources/images/logo-box-qi4j.jpg
Binary files differ
diff --git a/manual/src/resources/images/logo-standard-zest.png b/manual/src/resources/images/logo-standard-zest.png
new file mode 100644
index 0000000..c8b255f
--- /dev/null
+++ b/manual/src/resources/images/logo-standard-zest.png
Binary files differ
diff --git a/manual/src/resources/images/logo-standard.png b/manual/src/resources/images/logo-standard.png
index c8b255f..2d22919 100644
--- a/manual/src/resources/images/logo-standard.png
+++ b/manual/src/resources/images/logo-standard.png
Binary files differ
diff --git a/manual/src/resources/images/qi4j-blue.png b/manual/src/resources/images/polygene-blue.png
similarity index 100%
rename from manual/src/resources/images/qi4j-blue.png
rename to manual/src/resources/images/polygene-blue.png
Binary files differ
diff --git a/manual/src/resources/js/imagescaler.js b/manual/src/resources/js/imagescaler.js
index 0cb425c..eea583e 100644
--- a/manual/src/resources/js/imagescaler.js
+++ b/manual/src/resources/js/imagescaler.js
@@ -1,20 +1,21 @@
-/**
- * Licensed to Neo Technology under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Neo Technology 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
+/*
+ *  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.
  *
- * 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.
  */
 
 /* Smart Image Scaling
diff --git a/manual/src/resources/js/jquery.scrollTo-1.4.2.js b/manual/src/resources/js/jquery.scrollTo-1.4.2.js
index eec31e1..53b86f4 100644
--- a/manual/src/resources/js/jquery.scrollTo-1.4.2.js
+++ b/manual/src/resources/js/jquery.scrollTo-1.4.2.js
@@ -1,57 +1,21 @@
-/**

- * jQuery.ScrollTo

- * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com

- * Dual licensed under MIT and GPL.

- * Date: 5/25/2009

+/*

+ *  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.

  *

- * @projectDescription Easy element scrolling using jQuery.

- * http://flesler.blogspot.com/2007/10/jqueryscrollto.html

- * Works with jQuery +1.2.6. Tested on FF 2/3, IE 6/7/8, Opera 9.5/6, Safari 3, Chrome 1 on WinXP.

  *

- * @author Ariel Flesler

- * @version 1.4.2

- *

- * @id jQuery.scrollTo

- * @id jQuery.fn.scrollTo

- * @param {String, Number, DOMElement, jQuery, Object} target Where to scroll the matched elements.

- *	  The different options for target are:

- *		- A number position (will be applied to all axes).

- *		- A string position ('44', '100px', '+=90', etc ) will be applied to all axes

- *		- A jQuery/DOM element ( logically, child of the element to scroll )

- *		- A string selector, that will be relative to the element to scroll ( 'li:eq(2)', etc )

- *		- A hash { top:x, left:y }, x and y can be any kind of number/string like above.

-*		- A percentage of the container's dimension/s, for example: 50% to go to the middle.

- *		- The string 'max' for go-to-end. 

- * @param {Number} duration The OVERALL length of the animation, this argument can be the settings object instead.

- * @param {Object,Function} settings Optional set of settings or the onAfter callback.

- *	 @option {String} axis Which axis must be scrolled, use 'x', 'y', 'xy' or 'yx'.

- *	 @option {Number} duration The OVERALL length of the animation.

- *	 @option {String} easing The easing method for the animation.

- *	 @option {Boolean} margin If true, the margin of the target element will be deducted from the final position.

- *	 @option {Object, Number} offset Add/deduct from the end position. One number for both axes or { top:x, left:y }.

- *	 @option {Object, Number} over Add/deduct the height/width multiplied by 'over', can be { top:x, left:y } when using both axes.

- *	 @option {Boolean} queue If true, and both axis are given, the 2nd axis will only be animated after the first one ends.

- *	 @option {Function} onAfter Function to be called after the scrolling ends. 

- *	 @option {Function} onAfterFirst If queuing is activated, this function will be called after the first scrolling ends.

- * @return {jQuery} Returns the same jQuery object, for chaining.

- *

- * @desc Scroll to a fixed position

- * @example $('div').scrollTo( 340 );

- *

- * @desc Scroll relatively to the actual position

- * @example $('div').scrollTo( '+=340px', { axis:'y' } );

- *

- * @dec Scroll using a selector (relative to the scrolled element)

- * @example $('div').scrollTo( 'p.paragraph:eq(2)', 500, { easing:'swing', queue:true, axis:'xy' } );

- *

- * @ Scroll to a DOM element (same for jQuery object)

- * @example var second_child = document.getElementById('container').firstChild.nextSibling;

- *			$('#container').scrollTo( second_child, { duration:500, axis:'x', onAfter:function(){

- *				alert('scrolled!!');																   

- *			}});

- *

- * @desc Scroll on both axes, to different values

- * @example $('div').scrollTo( { top: 300, left:'+=200' }, { axis:'xy', offset:-20 } );

  */

 ;(function( $ ){

 	

diff --git a/manual/src/resources/js/progressive-enhancement.js b/manual/src/resources/js/progressive-enhancement.js
index bbf6f86..0aaecc0 100644
--- a/manual/src/resources/js/progressive-enhancement.js
+++ b/manual/src/resources/js/progressive-enhancement.js
@@ -1,29 +1,30 @@
 /*
- * 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
+ *  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.
  *
- *   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.
  */
 
 
 /**
- * Qi4j Documentation WebSite Progressive Enhancement.
+ * Apache Polygene Documentation WebSite Progressive Enhancement.
  */
 $( document ).ready( function($){
 
-    var atHome = window.location.hostname == "zest.apache.org"
+    var atHome = window.location.hostname == "polygene.apache.org"
 
     /**
      * Glossary.
@@ -94,7 +95,7 @@
                 }
                 else
                 {
-                    return "https://zest.apache.org/java/" + versions[ displayName ];
+                    return "https://polygene.apache.org/java/" + versions[ displayName ];
                 }
             }
             $( "div.logo select" ).change( function()
@@ -143,9 +144,9 @@
             case "Overview":
                 $dt.attr( "style", "margin-bottom: 24px" );
             // Tutorials
-            case "Zest\u2122 in 2 hours":
+            case "Polygene\u2122 in 30 minutes":
             case "Leverage Properties":
-            case "Use I/O API":
+            case "Use @Invocation":
                 $dt.attr( "style", "margin-bottom: 24px" );
                 break;
             // JavaDocs
@@ -160,7 +161,7 @@
             case "Ehcache Cache":
             case "Memory EntityStore":
             case "ElasticSearch Index/Query":
-            case "Yammer Metrics":
+            case "Codahale Metrics":
             case "Migration":
                 $dt.attr( "style", "margin-top: 24px" );
                 break;            
diff --git a/manual/src/resources/js/shBrushAS3.js b/manual/src/resources/js/shBrushAS3.js
index 8aa3ed2..417a227 100644
--- a/manual/src/resources/js/shBrushAS3.js
+++ b/manual/src/resources/js/shBrushAS3.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushAppleScript.js b/manual/src/resources/js/shBrushAppleScript.js
index d40bbd7..f34eb48 100644
--- a/manual/src/resources/js/shBrushAppleScript.js
+++ b/manual/src/resources/js/shBrushAppleScript.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushBash.js b/manual/src/resources/js/shBrushBash.js
index 8c29696..e274c15 100644
--- a/manual/src/resources/js/shBrushBash.js
+++ b/manual/src/resources/js/shBrushBash.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushCSharp.js b/manual/src/resources/js/shBrushCSharp.js
index 079214e..8523cb8 100644
--- a/manual/src/resources/js/shBrushCSharp.js
+++ b/manual/src/resources/js/shBrushCSharp.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushColdFusion.js b/manual/src/resources/js/shBrushColdFusion.js
index 627dbb9..75b45f4 100644
--- a/manual/src/resources/js/shBrushColdFusion.js
+++ b/manual/src/resources/js/shBrushColdFusion.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushCpp.js b/manual/src/resources/js/shBrushCpp.js
index 9f70d3a..9b1bfda 100644
--- a/manual/src/resources/js/shBrushCpp.js
+++ b/manual/src/resources/js/shBrushCpp.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushCss.js b/manual/src/resources/js/shBrushCss.js
index 4297a9a..44fd7f1 100644
--- a/manual/src/resources/js/shBrushCss.js
+++ b/manual/src/resources/js/shBrushCss.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushDelphi.js b/manual/src/resources/js/shBrushDelphi.js
index e1060d4..b5b999b 100644
--- a/manual/src/resources/js/shBrushDelphi.js
+++ b/manual/src/resources/js/shBrushDelphi.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushDiff.js b/manual/src/resources/js/shBrushDiff.js
index e9b14fc..70bcaa5 100644
--- a/manual/src/resources/js/shBrushDiff.js
+++ b/manual/src/resources/js/shBrushDiff.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushErlang.js b/manual/src/resources/js/shBrushErlang.js
index 6ba7d9d..fcf4477 100644
--- a/manual/src/resources/js/shBrushErlang.js
+++ b/manual/src/resources/js/shBrushErlang.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushGroovy.js b/manual/src/resources/js/shBrushGroovy.js
index 6ec5c18..5740817 100644
--- a/manual/src/resources/js/shBrushGroovy.js
+++ b/manual/src/resources/js/shBrushGroovy.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushJScript.js b/manual/src/resources/js/shBrushJScript.js
index ff98dab..9451bc5 100644
--- a/manual/src/resources/js/shBrushJScript.js
+++ b/manual/src/resources/js/shBrushJScript.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushJava.js b/manual/src/resources/js/shBrushJava.js
index d692fd6..c0e35d1 100644
--- a/manual/src/resources/js/shBrushJava.js
+++ b/manual/src/resources/js/shBrushJava.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushJavaFX.js b/manual/src/resources/js/shBrushJavaFX.js
index 1a150a6..882f4e5 100644
--- a/manual/src/resources/js/shBrushJavaFX.js
+++ b/manual/src/resources/js/shBrushJavaFX.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushPerl.js b/manual/src/resources/js/shBrushPerl.js
index d94a2e0..e5d4143 100644
--- a/manual/src/resources/js/shBrushPerl.js
+++ b/manual/src/resources/js/shBrushPerl.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushPhp.js b/manual/src/resources/js/shBrushPhp.js
index 95e6e43..32bfd45 100644
--- a/manual/src/resources/js/shBrushPhp.js
+++ b/manual/src/resources/js/shBrushPhp.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushPlain.js b/manual/src/resources/js/shBrushPlain.js
index 9f7d9e9..894a706 100644
--- a/manual/src/resources/js/shBrushPlain.js
+++ b/manual/src/resources/js/shBrushPlain.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushPowerShell.js b/manual/src/resources/js/shBrushPowerShell.js
index 0be1752..e9cb72f 100644
--- a/manual/src/resources/js/shBrushPowerShell.js
+++ b/manual/src/resources/js/shBrushPowerShell.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushPython.js b/manual/src/resources/js/shBrushPython.js
index ce77462..4019aa1 100644
--- a/manual/src/resources/js/shBrushPython.js
+++ b/manual/src/resources/js/shBrushPython.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushRuby.js b/manual/src/resources/js/shBrushRuby.js
index ff82130..e9de541 100644
--- a/manual/src/resources/js/shBrushRuby.js
+++ b/manual/src/resources/js/shBrushRuby.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushSass.js b/manual/src/resources/js/shBrushSass.js
index aa04da0..e48094c 100644
--- a/manual/src/resources/js/shBrushSass.js
+++ b/manual/src/resources/js/shBrushSass.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushScala.js b/manual/src/resources/js/shBrushScala.js
index 4b0b6f0..d6f39db 100644
--- a/manual/src/resources/js/shBrushScala.js
+++ b/manual/src/resources/js/shBrushScala.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushSql.js b/manual/src/resources/js/shBrushSql.js
index 5c2cd88..1b97d38 100644
--- a/manual/src/resources/js/shBrushSql.js
+++ b/manual/src/resources/js/shBrushSql.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushVb.js b/manual/src/resources/js/shBrushVb.js
index be845dc..fbfc400 100644
--- a/manual/src/resources/js/shBrushVb.js
+++ b/manual/src/resources/js/shBrushVb.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/shBrushXml.js b/manual/src/resources/js/shBrushXml.js
index 69d9fd0..2e8e7be 100644
--- a/manual/src/resources/js/shBrushXml.js
+++ b/manual/src/resources/js/shBrushXml.js
@@ -1,18 +1,21 @@
-/**
- * SyntaxHighlighter
- * http://alexgorbatchev.com/SyntaxHighlighter
+/*
+ *  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.
  *
- * SyntaxHighlighter is donationware. If you are using it, please donate.
- * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  *
- * @version
- * 3.0.83 (July 02 2010)
- * 
- * @copyright
- * Copyright (C) 2004-2010 Alex Gorbatchev.
- *
- * @license
- * Dual licensed under the MIT and GPL licenses.
  */
 ;(function()
 {
diff --git a/manual/src/resources/js/tablestyler.js b/manual/src/resources/js/tablestyler.js
index 680254d..ccb6432 100644
--- a/manual/src/resources/js/tablestyler.js
+++ b/manual/src/resources/js/tablestyler.js
@@ -1,20 +1,21 @@
-/**
- * Licensed to Neo Technology under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Neo Technology 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
+/*
+ *  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.
  *
- * 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.
  */
 
 /* Smart Image Scaling
diff --git a/manual/src/resources/schemas/2008/dev-status/1/dev-status.xsd b/manual/src/resources/schemas/2008/dev-status/1/dev-status.xsd
index 1174fdf..47831aa 100644
--- a/manual/src/resources/schemas/2008/dev-status/1/dev-status.xsd
+++ b/manual/src/resources/schemas/2008/dev-status/1/dev-status.xsd
@@ -1,31 +1,34 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <xs:schema attributeFormDefault="unqualified"
            elementFormDefault="qualified"
-           targetNamespace="http://www.qi4j.org/schemas/2008/dev-status/1"
+           targetNamespace="http://polygene.apache.org/schemas/2008/dev-status/1"
            xmlns:xs="http://www.w3.org/2001/XMLSchema">
-  <xs:element name="module" type="ns:moduleType" xmlns:ns="http://www.qi4j.org/schemas/2008/dev-status/1"/>
+  <xs:element name="module" type="ns:moduleType" xmlns:ns="http://polygene.apache.org/schemas/2008/dev-status/1"/>
   <xs:complexType name="licensesType">
     <xs:sequence>
       <xs:element type="xs:string" name="license">
         <xs:annotation>
           <xs:documentation>
-            Qi4j itself only uses Apache License ver 2.0 for all its own developed code. We also try to list
+            Apache Polygene itself only uses Apache License ver 2.0 for all its own developed code. We also try to list
             all dependencies' licenses here, so automated tools can bring that into the documentation.
             If the license is OTHER, the documentation will highlight this as a warning, and instruct users
             to carefully examine NOTICE file as well as the dependencies themselves.
@@ -45,8 +48,8 @@
   </xs:complexType>
   <xs:complexType name="moduleType">
     <xs:sequence>
-      <xs:element type="ns:statusType" name="status" xmlns:ns="http://www.qi4j.org/schemas/2008/dev-status/1"/>
-      <xs:element type="ns:licensesType" name="licenses" xmlns:ns="http://www.qi4j.org/schemas/2008/dev-status/1"/>
+      <xs:element type="ns:statusType" name="status" xmlns:ns="http://polygene.apache.org/schemas/2008/dev-status/1"/>
+      <xs:element type="ns:licensesType" name="licenses" xmlns:ns="http://polygene.apache.org/schemas/2008/dev-status/1"/>
     </xs:sequence>
   </xs:complexType>
   <xs:complexType name="statusType">
diff --git a/manual/src/xsl/chunked-basic.xsl b/manual/src/xsl/chunked-basic.xsl
index 0b60821..01bdc56 100644
--- a/manual/src/xsl/chunked-basic.xsl
+++ b/manual/src/xsl/chunked-basic.xsl
@@ -1,19 +1,22 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <!--
   Generates chunked XHTML documents from DocBook XML source using DocBook XSL
   stylesheets.
@@ -53,7 +56,7 @@
     <xsl:param name="generate.toc" select="''"/>
 
     <xsl:template name="footer.navigation">
-      <div class="footer"> (c) 2012 The Qi4j Community</div>
+      <div class="footer"> (c) 2012 The Apache Polygene Community</div>
     </xsl:template>
 
     <xsl:template name="header.navigation">
diff --git a/manual/src/xsl/chunked-offline.xsl b/manual/src/xsl/chunked-offline.xsl
index 4459ba2..b0ae0e3 100644
--- a/manual/src/xsl/chunked-offline.xsl
+++ b/manual/src/xsl/chunked-offline.xsl
@@ -1,19 +1,22 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <!--
   Generates chunked XHTML documents from DocBook XML source using DocBook XSL
   stylesheets.
diff --git a/manual/src/xsl/common.xsl b/manual/src/xsl/common.xsl
index bce356d..b1818a4 100644
--- a/manual/src/xsl/common.xsl
+++ b/manual/src/xsl/common.xsl
@@ -1,19 +1,22 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <!--
   Inlcuded in xhtml.xsl, xhtml.chunked.xsl, htmlhelp.xsl.
   Contains common XSL stylesheets parameters.
diff --git a/manual/src/xsl/disqus-footer.xsl b/manual/src/xsl/disqus-footer.xsl
index c5695db..e4707e1 100644
--- a/manual/src/xsl/disqus-footer.xsl
+++ b/manual/src/xsl/disqus-footer.xsl
@@ -1,19 +1,22 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 
   <xsl:template name="user.footer.content">
@@ -23,7 +26,7 @@
 <script type="text/javascript">
 // DISQUS
   var disqus_identifier = "manual";
-  var disqus_title = "The Qi4j Manual";
+  var disqus_title = "The Apache Polygene Manual";
   function getIdFromHeading ( headingElement )
   {
     var id = disqus_identifier;
@@ -98,7 +101,7 @@
   var disqus_url = window.location;
   if ( disqus_url.protocol === "http:" || disqus_url.protocol === "https:" )
   {
-    var docsLocation = "http://www.qi4j.org/chunked/snapshot/";
+    var docsLocation = "http://polygene.apache.org/chunked/snapshot/";
     var path = disqus_url.pathname;
     var position = path.lastIndexOf('/');
     if ( position === -1 )
@@ -111,7 +114,7 @@
       disqus_url = docsLocation + page;
     }
   }
-  var disqus_shortname = "qi4j";
+  var disqus_shortname = "polygene";
   var disqus_developer = 0;
 
 (function() {
diff --git a/manual/src/xsl/fo.xsl b/manual/src/xsl/fo.xsl
index d125c94..50d18af 100644
--- a/manual/src/xsl/fo.xsl
+++ b/manual/src/xsl/fo.xsl
@@ -1,19 +1,22 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <!--
   Generates single FO document from DocBook XML source using DocBook XSL
   stylesheets.
@@ -343,7 +346,7 @@
       <xsl:with-param name="master-reference">titlepage</xsl:with-param>
       <xsl:with-param name="content">
         <fo:block text-align="center" margin-top="5.0cm">
-          <fo:external-graphic src="url(images/qi4j-blue.png)"
+          <fo:external-graphic src="url(images/polygene-blue.png)"
                                content-width="12cm"
                                content-height="2.94cm"
                                scaling="uniform"/>
diff --git a/manual/src/xsl/footer.xsl b/manual/src/xsl/footer.xsl
index 2e6d6e0..684128e 100644
--- a/manual/src/xsl/footer.xsl
+++ b/manual/src/xsl/footer.xsl
@@ -1,19 +1,22 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 
   <xsl:template name="user.footer.content">
diff --git a/manual/src/xsl/head-offline.xsl b/manual/src/xsl/head-offline.xsl
index 4e8a120..57fa60a 100644
--- a/manual/src/xsl/head-offline.xsl
+++ b/manual/src/xsl/head-offline.xsl
@@ -1,19 +1,22 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 
   <xsl:template name="user.head.content">
@@ -22,15 +25,15 @@
 
 <!-- favicon -->
 
-<link rel="shortcut icon" href="http://qi4j.org/favicon.ico" type="image/vnd.microsoft.icon" />
-<link rel="icon" href="http://qi4j.org/favicon.ico" type="image/x-icon" />
+<link rel="shortcut icon" href="http://polygene.apache.org/favicon.ico" type="image/vnd.microsoft.icon" />
+<link rel="icon" href="http://polygene.apache.org/favicon.ico" type="image/x-icon" />
 
 <!-- style -->
 
 <link href="css/shCore.css" rel="stylesheet" type="text/css" />
 <link href="css/shCoreEclipse.css" rel="stylesheet" type="text/css" />
 <link href="css/shThemeEclipse.css" rel="stylesheet" type="text/css" />
-<link href="css/qi4j.css" rel="stylesheet" type="text/css" />
+<link href="css/polygene.css" rel="stylesheet" type="text/css" />
 
 <!-- Syntax Highlighter -->
 
diff --git a/manual/src/xsl/html-params.xsl b/manual/src/xsl/html-params.xsl
index 970df0a..bcd53a2 100644
--- a/manual/src/xsl/html-params.xsl
+++ b/manual/src/xsl/html-params.xsl
@@ -1,19 +1,22 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 version="1.0">
 
diff --git a/manual/src/xsl/offline-footer.xsl b/manual/src/xsl/offline-footer.xsl
index d810632..9148b47 100644
--- a/manual/src/xsl/offline-footer.xsl
+++ b/manual/src/xsl/offline-footer.xsl
@@ -1,19 +1,22 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 
   <xsl:template name="user.footer.content">
diff --git a/manual/src/xsl/syntaxhighlight.xsl b/manual/src/xsl/syntaxhighlight.xsl
index c62013f..d00d7f7 100644
--- a/manual/src/xsl/syntaxhighlight.xsl
+++ b/manual/src/xsl/syntaxhighlight.xsl
@@ -1,19 +1,22 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 
   <xsl:template match="*/programlisting" mode="class.value">
diff --git a/manual/src/xsl/text.xsl b/manual/src/xsl/text.xsl
index 52e0266..bb634d3 100644
--- a/manual/src/xsl/text.xsl
+++ b/manual/src/xsl/text.xsl
@@ -1,19 +1,22 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <?xml version="1.0"?>
 <!--
   Used by AsciiDoc a2x(1) for w3m(1) based text generation.
diff --git a/manual/src/xsl/xhtml.xsl b/manual/src/xsl/xhtml.xsl
index 294564d..69cda2b 100644
--- a/manual/src/xsl/xhtml.xsl
+++ b/manual/src/xsl/xhtml.xsl
@@ -1,19 +1,22 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <!--
   Generates single XHTML document from DocBook XML source using DocBook XSL
   stylesheets.
diff --git a/maven-compat.gradle b/maven-compat.gradle
deleted file mode 100644
index 0387818..0000000
--- a/maven-compat.gradle
+++ /dev/null
@@ -1,282 +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.
- */
-
-// See http://maven.apache.org/pom/asf/
-
-uploadArchives {
-  repositories.mavenDeployer {
-
-    pom {
-
-      project {
-        url 'https://zest.apache.org/'
-        organization {
-          name 'The Apache Software Foundation'
-          url 'https://apache.org/'
-        }
-        inceptionYear '2007'
-        issueManagement {
-          system 'jira'
-          url 'https://issues.apache.org/jira/browse/ZEST'
-        }
-        scm {
-          url "https://github.com/apache/zest-java"
-          connection "scm:git:https://git-wip-us.apache.org/repos/asf/zest-java.git"
-          developerConnection "scm:git:https://git-wip-us.apache.org/repos/asf/zest-java.git"
-        }
-        licenses {
-          license {
-            name 'Apache License, version 2.0.'
-            url 'http://www.apache.org/licenses/LICENSE-2.0'
-          }
-        }
-        mailingLists {
-          mailingList {
-            name 'Users List'
-            subscribe 'users-subscribe@zest.apache.org'
-            unsubscribe 'users-unsubscribe@zest.apache.org'
-            post 'users@zest.apache.org'
-            archive 'https://mail-archives.apache.org/mod_mbox/zest-users/'
-            otherArchives {
-              otherArchive 'https://www.apache.org/foundation/mailinglists.html#archives'
-            }
-          }
-          mailingList {
-            name 'Development List'
-            subscribe 'dev-subscribe@zest.apache.org'
-            unsubscribe 'dev-unsubscribe@zest.apache.org'
-            post 'dev@zest.apache.org'
-            archive 'https://mail-archives.apache.org/mod_mbox/zest-dev/'
-            otherArchives {
-              otherArchive 'https://www.apache.org/foundation/mailinglists.html#archives'
-            }
-          }
-          mailingList {
-            name 'Commits List'
-            subscribe 'commits-subscribe@zest.apache.org'
-            unsubscribe 'commits-unsubscribe@zest.apache.org'
-            post 'commits@zest.apache.org'
-            archive 'https://mail-archives.apache.org/mod_mbox/zest-commits/'
-            otherArchives {
-              otherArchive 'https://www.apache.org/foundation/mailinglists.html#archives'
-            }
-          }
-        }
-        developers {
-          developer {
-            id 'niclas@hedhman.org'
-            name 'Niclas Hedhman'
-            email 'niclas@hedhman.org'
-            roles {
-              role 'Core Team'
-            }
-            organizationUrl 'http://www.qi4j.org'
-            timezone 'UTC+8'
-          }
-          developer {
-            id 'rickardoberg'
-            name 'Rickard \u00F6berg'
-            email 'rickard.oberg@jayway.se'
-            roles {
-              role 'Core Team'
-            }
-            url 'http://www.neotechnology.com'
-            organization 'Neo Technology AB'
-            organizationUrl 'http://www.neotechnology.com'
-            timezone 'UTC+8'
-          }
-          developer {
-            id 'edward.yakop@gmail.com'
-            name 'Edward Yakop'
-            email 'efy@codedragons.com'
-            roles {
-              role 'Core Team'
-            }
-            organizationUrl 'http://www.qi4j.org'
-            timezone 'UTC+8'
-          }
-          developer {
-            id 'adreghiciu@gmail.com'
-            name 'Alin Dreghiciu'
-            email 'adreghiciu@codedragons.com'
-            roles {
-              role 'Core Team'
-            }
-            organizationUrl 'http://www.qi4j.org'
-            timezone 'UTC+2'
-          }
-          developer {
-            id 'mesirii'
-            name 'Michael Hunger'
-            email 'qi4j@jexp.de'
-            roles {
-              role 'Core Team'
-            }
-            timezone 'CET'
-          }
-
-          developer {
-            id "muhdkamil"
-            name "Muhd Kamil bin Mohd Baki"
-            roles {
-              role 'Platform Team'
-            }
-            timezone "UTC+8"
-          }
-
-          developer {
-            id "ops4j@leangen.net"
-            name "David Leangen"
-            organization "Bioscene"
-            email "ops4j@leangen.net"
-            roles {
-              role 'Platform Team'
-            }
-            timezone "UTC+9"
-          }
-
-          developer {
-            id "sonny.gill@jayway.net"
-            name "Sonny Gill"
-            email "sonny.public@gmail.com"
-            roles {
-              role 'Community Team'
-            }
-            timezone "UTC+8"
-          }
-
-          developer {
-            id "taowen"
-            name "Tao Wen"
-            organization ""
-            email "taowen@gmail.com"
-            roles {
-              role 'Community Team'
-            }
-            timezone "UTC+8"
-          }
-
-          developer {
-            id "thobe"
-            name "Tobias Ivarsson"
-            email "tobias@neotechnology.com"
-            url "http://www.neotechnology.com"
-            organization "NeoTechnology"
-            organizationUrl "http://www.neotechnology.com"
-            roles {
-              role "Platform Team"
-            }
-            timezone "CET"
-          }
-
-          developer {
-            id "boon"
-            name "Lan Boon Ping"
-            email "boonping81@gmail.com"
-            roles {
-              role 'Platform Team'
-            }
-            timezone "UTC+8"
-          }
-
-          developer {
-            id "jan.kronquist@gmail.com"
-            name "Jan Kronquist"
-            email "jan.kronquist@gmail.com"
-            organization "Jayway"
-            roles {
-              role 'Platform Team'
-            }
-            timezone "CET"
-          }
-
-          developer {
-            id "nmwael"
-            name "Nino Saturnino Martinez Vazquez Wael"
-            roles {
-              role 'Platform Team'
-            }
-            timezone "CET"
-          }
-
-          developer {
-            id "peter@neubauer.se"
-            name "Peter Neubauer"
-            email "peter@neubauer.se"
-            roles {
-              role 'Platform Team'
-            }
-            timezone "CET"
-          }
-
-          developer {
-            id "rwallace"
-            name "Richard Wallace"
-            email "rwallace@thewallacepack.net"
-            roles {
-              role 'Platform Team'
-            }
-            timezone "UTC-7"
-          }
-
-          developer {
-            id "siannyhalim@gmail.com"
-            name "Sianny Halim"
-            email "siannyhalim@gmail.com"
-            roles {
-              role 'Platform Team'
-            }
-            timezone "UTC+8"
-          }
-
-          developer {
-            id "paul@nosphere.org"
-            name "Paul Merlin"
-            email "paul@nosphere.org"
-            roles {
-              role 'Core Team'
-            }
-            timezone "CET"
-          }
-
-          developer {
-            id "stas.dev+qi4j@gmail.com"
-            name "Stanislav Muhametsin"
-            email "stas.dev+qi4j@gmail.com"
-            roles {
-              role 'Platform Team'
-            }
-            timezone "UTC+2"
-          }
-
-          developer {
-            id "tonny"
-            name "Tonny Kohar"
-            roles {
-              role "Community Team"
-            }
-            email "tonny.kohar@gmail.com"
-            timezone "UTC+7"
-          }
-        }
-      }
-    }
-
-  }  
-}
diff --git a/release/build.gradle b/release/build.gradle
new file mode 100644
index 0000000..5979fee
--- /dev/null
+++ b/release/build.gradle
@@ -0,0 +1,19 @@
+/*
+ *  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.
+ */
+
+apply plugin: 'polygene-release'
diff --git a/reports/build.gradle b/reports/build.gradle
new file mode 100644
index 0000000..a26565e
--- /dev/null
+++ b/reports/build.gradle
@@ -0,0 +1,19 @@
+/*
+ *  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.
+ */
+
+apply plugin: 'polygene-reports'
diff --git a/reports/src/javadoc/overview.html b/reports/src/javadoc/overview.html
new file mode 100644
index 0000000..9530721
--- /dev/null
+++ b/reports/src/javadoc/overview.html
@@ -0,0 +1,26 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h3>Welcome to the Apache Polygene™ (Java Edition) SDK Javadoc.</h3>
+        <p>Apache Polygene™ is a framework for domain centric application development, including evolved concepts from AOP, DI and DDD.</p>
+        <p><a href="https://polygene.apache.org" target="_blank">polygene.apache.org</a></p>
+    </body>
+</html>
diff --git a/samples/dci-cargo/README.txt b/samples/dci-cargo/README.txt
deleted file mode 100644
index b588156..0000000
--- a/samples/dci-cargo/README.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-DCI Sample
-==========
-
-This is a port of the DDD Sample application to the DCI paradigm using Java, Zest™ and Wicket.
-
-The code is licensed under the Apache Software License 2.0 and lastest revisions are
-available from https://github.com/dci.
-
-See more information at http://marcgrue.com/dci/dci-sample
-
-Version A:
-- Run com.marcgrue.dcisample_a.bootstrap.Start8081 (in test folder)
-- Point browser to http://localhost:8081
-
-Version B:
-- Run com.marcgrue.dcisample_b.bootstrap.Start8082 (in test folder)
-- Point browser to http://localhost:8082
-
-
-Marc Grue
-marcgrue.com
-October 2011
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/build.gradle b/samples/dci-cargo/dcisample_a/build.gradle
deleted file mode 100644
index 63927b4..0000000
--- a/samples/dci-cargo/dcisample_a/build.gradle
+++ /dev/null
@@ -1,50 +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.
- */
-
-description = "Sample of how DCI (Data, Context & Interaction) pattern is implemented with Apache Zest™, for Eric Evans DDD sample."
-
-jar { manifest { name = "Apache Zest™ Sample DCI Cargo - Sample A" }}
-
-dependencies {
-
-  compile project( ':org.qi4j.core:org.qi4j.core.bootstrap' )
-  compile project( ':org.qi4j.libraries:org.qi4j.library.constraints' )
-  compile project( ':org.qi4j.libraries:org.qi4j.library.conversion' )
-  compile project( ':org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson' )
-  compile project( ':org.qi4j.extensions:org.qi4j.extension.indexing-rdf' )
-  compile project( ':org.qi4j.tools:org.qi4j.tool.envisage' )
-  compile libraries.jetty_webapp
-  compile libraries.wicket
-  compile libraries.wicket_devutils
-  compile libraries.wicket_stateless
-  compile libraries.slf4j_api
-
-  runtime project( ':org.qi4j.core:org.qi4j.core.runtime' )
-
-  testCompile project( ':org.qi4j.core:org.qi4j.core.testsupport' )
-  testCompile libraries.easymock
-
-  testRuntime libraries.logback
-
-}
-
-task(runSample, dependsOn: 'testClasses', type: JavaExec) {
-    main = 'org.qi4j.sample.dcicargo.sample_a.bootstrap.Start8081'
-    classpath = sourceSets.test.runtimeClasspath
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/api/GraphTraversalService.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/api/GraphTraversalService.java
deleted file mode 100644
index b0cb496..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/api/GraphTraversalService.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.pathfinder_a.api;
-
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.util.List;
-
-/**
- * Part of the external graph traversal API exposed by the routing team
- * and used by us (booking and tracking team).
- */
-public interface GraphTraversalService extends Remote
-{
-
-    /**
-     * @param originUnLocode      origin UN Locode
-     * @param destinationUnLocode destination UN Locode
-     *
-     * @return A list of transit paths
-     *
-     * @throws RemoteException RMI problem
-     */
-    List<TransitPath> findShortestPath( String originUnLocode, String destinationUnLocode )
-        throws RemoteException;
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/api/TransitEdge.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/api/TransitEdge.java
deleted file mode 100644
index 51315de..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/api/TransitEdge.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.pathfinder_a.api;
-
-import java.io.Serializable;
-import java.util.Date;
-
-/**
- * Represents an edge in a path through a graph,
- * describing the route of a cargo.
- */
-public final class TransitEdge implements Serializable
-{
-
-    private final String voyageNumber;
-    private final String fromUnLocode;
-    private final String toUnLocode;
-    private final Date fromDate;
-    private final Date toDate;
-
-    /**
-     * Constructor.
-     *
-     * @param voyageNumber
-     * @param fromUnLocode
-     * @param toUnLocode
-     * @param fromDate
-     * @param toDate
-     */
-    public TransitEdge( final String voyageNumber,
-                        final String fromUnLocode,
-                        final String toUnLocode,
-                        final Date fromDate,
-                        final Date toDate
-    )
-    {
-        this.voyageNumber = voyageNumber;
-        this.fromUnLocode = fromUnLocode;
-        this.toUnLocode = toUnLocode;
-        this.fromDate = fromDate;
-        this.toDate = toDate;
-    }
-
-    public String getVoyageNumber()
-    {
-        return voyageNumber;
-    }
-
-    public String getFromUnLocode()
-    {
-        return fromUnLocode;
-    }
-
-    public String getToUnLocode()
-    {
-        return toUnLocode;
-    }
-
-    public Date getFromDate()
-    {
-        return fromDate;
-    }
-
-    public Date getToDate()
-    {
-        return toDate;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/api/TransitPath.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/api/TransitPath.java
deleted file mode 100644
index 0f65f0a..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/api/TransitPath.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.pathfinder_a.api;
-
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.List;
-
-/**
- *
- */
-public final class TransitPath implements Serializable
-{
-
-    private final List<TransitEdge> transitEdges;
-
-    /**
-     * Constructor.
-     *
-     * @param transitEdges The legs for this itinerary.
-     */
-    public TransitPath( final List<TransitEdge> transitEdges )
-    {
-        this.transitEdges = transitEdges;
-    }
-
-    /**
-     * @return An unmodifiable list DTOs.
-     */
-    public List<TransitEdge> getTransitEdges()
-    {
-        return Collections.unmodifiableList( transitEdges );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/api/package.html b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/api/package.html
deleted file mode 100644
index 01921e5..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/api/package.html
+++ /dev/null
@@ -1,23 +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.
--->
-<html>
-<body>
-<p>
-    Public API for the pathfinder application.
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/internal/GraphDAO.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/internal/GraphDAO.java
deleted file mode 100644
index 1e1225d..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/internal/GraphDAO.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.pathfinder_a.internal;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Random;
-
-public class GraphDAO
-{
-
-    private static final Random random = new Random();
-
-    public List<String> listLocations()
-    {
-        return new ArrayList<String>( Arrays.asList(
-            "CNHKG", "AUMEL", "SESTO", "FIHEL", "USCHI", "JNTKO", "DEHAM", "CNSHA", "NLRTM", "SEGOT", "CNHGH", "USNYC", "USDAL"
-        ) );
-    }
-
-    public String getVoyageNumber( String from, String to )
-    {
-        final int i = random.nextInt( 5 );
-        if( i == 0 )
-        {
-            return "V100S";
-        }
-        if( i == 1 )
-        {
-            return "V200T";
-        }
-        if( i == 2 )
-        {
-            return "V300A";
-        }
-        if( i == 3 )
-        {
-            return "V400S";
-        }
-        return "V500S";
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/internal/GraphTraversalServiceImpl.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/internal/GraphTraversalServiceImpl.java
deleted file mode 100644
index 41237c6..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/internal/GraphTraversalServiceImpl.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.pathfinder_a.internal;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Random;
-import org.qi4j.sample.dcicargo.pathfinder_a.api.GraphTraversalService;
-import org.qi4j.sample.dcicargo.pathfinder_a.api.TransitEdge;
-import org.qi4j.sample.dcicargo.pathfinder_a.api.TransitPath;
-
-public class GraphTraversalServiceImpl
-    implements GraphTraversalService
-{
-    private GraphDAO dao;
-    private Random random;
-    private static final long ONE_MIN_MS = 1000 * 60;
-    private static final long ONE_DAY_MS = ONE_MIN_MS * 60 * 24;
-
-    public GraphTraversalServiceImpl( GraphDAO dao )
-    {
-        this.dao = dao;
-        this.random = new Random();
-    }
-
-    public List<TransitPath> findShortestPath( String originUnLocode, String destinationUnLocode )
-    {
-        Date date = nextDate( new Date() );
-
-        List<String> allVertices = dao.listLocations();
-        allVertices.remove( originUnLocode );
-        allVertices.remove( destinationUnLocode );
-
-        final int candidateCount = getRandomNumberOfCandidates();
-        final List<TransitPath> candidates = new ArrayList<TransitPath>( candidateCount );
-
-        for( int i = 0; i < candidateCount; i++ )
-        {
-            allVertices = getRandomChunkOfLocations( allVertices );
-            final List<TransitEdge> transitEdges = new ArrayList<TransitEdge>( allVertices.size() - 1 );
-            final String firstLegTo = allVertices.get( 0 );
-
-            Date fromDate = nextDate( date );
-            Date toDate = nextDate( fromDate );
-            date = nextDate( toDate );
-
-            transitEdges.add( new TransitEdge(
-                dao.getVoyageNumber( originUnLocode, firstLegTo ),
-                originUnLocode, firstLegTo, fromDate, toDate ) );
-
-            for( int j = 0; j < allVertices.size() - 1; j++ )
-            {
-                final String curr = allVertices.get( j );
-                final String next = allVertices.get( j + 1 );
-                fromDate = nextDate( date );
-                toDate = nextDate( fromDate );
-                date = nextDate( toDate );
-                transitEdges.add( new TransitEdge( dao.getVoyageNumber( curr, next ), curr, next, fromDate, toDate ) );
-            }
-
-            final String lastLegFrom = allVertices.get( allVertices.size() - 1 );
-            fromDate = nextDate( date );
-            toDate = nextDate( fromDate );
-            transitEdges.add( new TransitEdge(
-                dao.getVoyageNumber( lastLegFrom, destinationUnLocode ),
-                lastLegFrom, destinationUnLocode, fromDate, toDate ) );
-
-            candidates.add( new TransitPath( transitEdges ) );
-        }
-
-        return candidates;
-    }
-
-    private Date nextDate( Date date )
-    {
-        return new Date( date.getTime() + ONE_DAY_MS + ( random.nextInt( 1000 ) - 500 ) * ONE_MIN_MS );
-    }
-
-    private int getRandomNumberOfCandidates()
-    {
-        return 3 + random.nextInt( 3 );
-    }
-
-    private List<String> getRandomChunkOfLocations( List<String> allLocations )
-    {
-        Collections.shuffle( allLocations );
-        final int total = allLocations.size();
-        final int chunk = total > 4 ? 1 + new Random().nextInt( 5 ) : total;
-        return allLocations.subList( 0, chunk );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/internal/package.html b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/internal/package.html
deleted file mode 100644
index 3c4f049..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/internal/package.html
+++ /dev/null
@@ -1,23 +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.
--->
-<html>
-<body>
-<p>
-    Internal parts of the pathfinder application.
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/package.html b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/package.html
deleted file mode 100644
index af1b144..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/pathfinder_a/package.html
+++ /dev/null
@@ -1,31 +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.
--->
-<html>
-<body>
-<p>
-    This is the pathfinder application context, which is separate from "our" application and context.
-    Our domain model with cargo, itinerary, handling event etc does not exist here.
-    The routing domain service implementation works against the API exposed by
-    this context.
-</p>
-
-<p>
-    It is not related to the core application at all, and is only part of this source tree for
-    developer convenience.
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/DCISampleApplication_a.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/DCISampleApplication_a.java
deleted file mode 100644
index 292684a..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/DCISampleApplication_a.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.bootstrap;
-
-import java.util.Date;
-import org.apache.wicket.ConverterLocator;
-import org.apache.wicket.Page;
-import org.apache.wicket.datetime.PatternDateConverter;
-import org.apache.wicket.devutils.stateless.StatelessChecker;
-import org.qi4j.sample.dcicargo.sample_a.communication.web.booking.BookNewCargoPage;
-import org.qi4j.sample.dcicargo.sample_a.communication.web.booking.CargoDetailsPage;
-import org.qi4j.sample.dcicargo.sample_a.communication.web.booking.CargoListPage;
-import org.qi4j.sample.dcicargo.sample_a.communication.web.booking.ChangeDestinationPage;
-import org.qi4j.sample.dcicargo.sample_a.communication.web.booking.RouteCargoPage;
-import org.qi4j.sample.dcicargo.sample_a.communication.web.handling.RegisterHandlingEventPage;
-import org.qi4j.sample.dcicargo.sample_a.communication.web.tracking.TrackCargoPage;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.WicketQi4jApplication;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.tabs.TabsPanel;
-
-/**
- * DCI Sample application instance
- *
- * A Wicket application backed by Zest.
- */
-public class DCISampleApplication_a
-    extends WicketQi4jApplication
-{
-    public void wicketInit()
-    {
-        // Tabs and SEO urls
-        mountPages();
-
-        // Show/hide Ajax debugging
-        getDebugSettings().setDevelopmentUtilitiesEnabled( true );
-
-        // Check that components are stateless when required
-        getComponentPostOnBeforeRenderListeners().add( new StatelessChecker() );
-
-        // Show/hide wicket tags in html code
-        getMarkupSettings().setStripWicketTags( true );
-
-        // Default date format (we don't care for now about the hour of the day)
-        ( (ConverterLocator) getConverterLocator() ).set( Date.class, new PatternDateConverter( "yyyy-MM-dd", true ) );
-    }
-
-    private void mountPages()
-    {
-        TabsPanel.registerTab( this, CargoListPage.class, "booking", "Booking and Routing" );
-        TabsPanel.registerTab( this, TrackCargoPage.class, "tracking", "Tracking" );
-        TabsPanel.registerTab( this, RegisterHandlingEventPage.class, "handling", "Handling" );
-
-        mountPage( "/booking", CargoListPage.class );
-        mountPage( "/booking/book-new-cargo", BookNewCargoPage.class );
-        mountPage( "/booking/cargo", CargoDetailsPage.class );
-        mountPage( "/booking/change-destination", ChangeDestinationPage.class );
-        mountPage( "/booking/route-cargo", RouteCargoPage.class );
-
-        mountPage( "/handling", RegisterHandlingEventPage.class );
-        mountPage( "/tracking", TrackCargoPage.class );
-    }
-
-    public Class<? extends Page> getHomePage()
-    {
-        return CargoListPage.class;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/VisualizeApplicationStructure.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/VisualizeApplicationStructure.java
deleted file mode 100644
index 90cd6b4..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/VisualizeApplicationStructure.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.bootstrap;
-
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.envisage.Envisage;
-import org.qi4j.sample.dcicargo.sample_a.bootstrap.assembly.Assembler;
-
-/**
- * Visualize the application assemblage structure.
- */
-public class VisualizeApplicationStructure
-{
-    public static void main( String[] args )
-        throws Exception
-    {
-        Energy4Java qi4j = new Energy4Java();
-        Assembler assembler = new Assembler();
-        ApplicationDescriptor applicationModel = qi4j.newApplicationModel( assembler );
-        applicationModel.newInstance( qi4j.spi() );
-
-        /*
-       * The Envisage Swing app visualizes the application assemblage structure.
-       *
-       * Tree view:
-       * - Click on elements to expand sub-elements.
-       * - Scroll to change font size.
-       * - Right click on viewer to re-size to fit window.
-       *
-       * Stacked view:
-       * - Scroll to zoom in/out of structure levels - might freeze though :-(
-       *
-       * Click on any element and see details of that element in the upper right pane.
-       *
-       * Pretty cool, eh?
-       * */
-        new Envisage().run( applicationModel );
-        int randomTimeoutMs = 18374140;
-        Thread.sleep( randomTimeoutMs );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/assembly/Assembler.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/assembly/Assembler.java
deleted file mode 100644
index 6191377..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/assembly/Assembler.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.bootstrap.assembly;
-
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.ApplicationAssemblyFactory;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.functional.Function;
-import org.qi4j.index.rdf.RdfIndexingEngineService;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.library.rdf.entity.EntityTypeSerializer;
-import org.qi4j.library.rdf.repository.MemoryRepositoryService;
-import org.qi4j.sample.dcicargo.pathfinder_a.api.GraphTraversalService;
-import org.qi4j.sample.dcicargo.pathfinder_a.internal.GraphDAO;
-import org.qi4j.sample.dcicargo.pathfinder_a.internal.GraphTraversalServiceImpl;
-import org.qi4j.sample.dcicargo.sample_a.bootstrap.DCISampleApplication_a;
-import org.qi4j.sample.dcicargo.sample_a.bootstrap.sampledata.BaseDataService;
-import org.qi4j.sample.dcicargo.sample_a.bootstrap.sampledata.SampleDataService;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.BookingQueries;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.dto.CargoDTO;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.dto.HandlingEventDTO;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.dto.LocationDTO;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.dto.VoyageDTO;
-import org.qi4j.sample.dcicargo.sample_a.context.rolemap.CargoRoleMap;
-import org.qi4j.sample.dcicargo.sample_a.context.rolemap.CargosRoleMap;
-import org.qi4j.sample.dcicargo.sample_a.context.rolemap.HandlingEventRoleMap;
-import org.qi4j.sample.dcicargo.sample_a.context.rolemap.HandlingEventsRoleMap;
-import org.qi4j.sample.dcicargo.sample_a.context.rolemap.ItineraryRoleMap;
-import org.qi4j.sample.dcicargo.sample_a.context.rolemap.RouteSpecificationRoleMap;
-import org.qi4j.sample.dcicargo.sample_a.context.support.ApplicationEvents;
-import org.qi4j.sample.dcicargo.sample_a.context.support.RegisterHandlingEventAttemptDTO;
-import org.qi4j.sample.dcicargo.sample_a.context.support.RoutingService;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.LocationEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.VoyageEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.TrackingId;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.ExpectedHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Leg;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.UnLocode;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.CarrierMovement;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Schedule;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.VoyageNumber;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.conversion.EntityToDTOService;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-import static org.qi4j.api.common.Visibility.application;
-import static org.qi4j.api.structure.Application.Mode.development;
-
-/**
- * Zest assembly of the DCI Sample application (version A)
- *
- * A Zest application structure is declared by an assembly that defines which layers and modules
- * the application has and how they are allowed to depend on each other. Each layer could have it's
- * own assembly file in larger applications (read more at http://qi4j.org/latest/core-bootstrap-assembly.html).
- *
- * The Zest assembly doesn't follow a strict 1-1 correlation between the directory hierarchy and
- * the assembly structures. An example is the Entities:
- *
- * Entities can be promoted to Role Players when they are needed to play a Role in a Context.
- * One Role Map is created for each Entity and it lists Roles in different Contexts that the Entity
- * can play. It hence has knowledge about the Context layer. If an Entity is in a Role Map it doesn't
- * get assembled as an Entity down in the Data layer but rather up in the CONTEXT-EntityRole module.
- * The Entities left behind without Roles could still have been assembled in a DATA-Entity module but
- * to avoid swapping Entities up and down between the Data and Context layers we have them all in the
- * Context layer. Note that there are still no "physical" upward dependencies from the Entities to
- * layers above.
- *
- * So dependency structure layers (ie. as shown by Structure101) are not the same as Zest layers.
- * See more at http://qi4j.org/latest/core-bootstrap-assembly.html
- *
- * TRY THIS: Run VisualizeApplicationStructure to see a cool visualization of the assembly below!
- */
-@SuppressWarnings( "unchecked" )
-public class Assembler
-    implements ApplicationAssembler
-{
-    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-        throws AssemblyException
-    {
-        // Application assembly
-        ApplicationAssembly assembly = applicationFactory.newApplicationAssembly();
-        assembly.setName( "DCI Sample (version A)" );
-        assembly.setVersion( "A.1.0" );
-        assembly.setMode( development );
-
-        // Layers (adding bottom-up - will be assembled in this order)
-        LayerAssembly infrastructureLayer = assembly.layer( "INFRASTRUCTURE" );
-        LayerAssembly dataLayer = assembly.layer( "DATA" );
-        LayerAssembly contextLayer = assembly.layer( "CONTEXT" );
-        LayerAssembly communicationLayer = assembly.layer( "COMMUNICATION" );
-        LayerAssembly bootstrapLayer = assembly.layer( "BOOTSTRAP" );
-
-        // Layer dependencies
-        bootstrapLayer.uses(
-            communicationLayer,
-            contextLayer,
-            dataLayer,
-            infrastructureLayer );
-
-        communicationLayer.uses(
-            contextLayer,
-            dataLayer,
-            infrastructureLayer );
-
-        contextLayer.uses(
-            dataLayer,
-            infrastructureLayer );
-
-        dataLayer.uses(
-            infrastructureLayer
-        );
-
-        // Assemble
-        assembleBootstrapLayer( bootstrapLayer );
-        assembleCommunicationLayer( communicationLayer );
-        assembleContextLayer( contextLayer );
-        assembleDataLayer( dataLayer );
-        assembleInfrastructureLayer( infrastructureLayer );
-
-        return assembly;
-    }
-
-    private void assembleBootstrapLayer( LayerAssembly bootstrapLayer )
-        throws AssemblyException
-    {
-        ModuleAssembly bootstrapModule = bootstrapLayer.module( "BOOTSTRAP-Bootstrap" );
-        bootstrapModule
-            .objects(
-                DCISampleApplication_a.class );
-
-        // Load sample data on startup
-        bootstrapModule
-            .addServices(
-                BaseDataService.class )
-            .instantiateOnStartup();
-        bootstrapModule
-            .addServices(
-                SampleDataService.class )
-            .instantiateOnStartup();
-    }
-
-    private void assembleCommunicationLayer( LayerAssembly communicationLayer )
-        throws AssemblyException
-    {
-        ModuleAssembly queryModule = communicationLayer.module( "COMMUNICATION-Query" );
-        queryModule
-            .transients(
-                BookingQueries.class )
-            .visibleIn( application );
-
-        queryModule
-            .values(
-                CargoDTO.class,
-                LocationDTO.class,
-                HandlingEventDTO.class,
-                VoyageDTO.class );
-
-        queryModule
-            .addServices(
-                EntityToDTOService.class,
-                OrgJsonValueSerializationService.class )
-            .visibleIn( application );
-    }
-
-    private void assembleContextLayer( LayerAssembly contextLayer )
-        throws AssemblyException
-    {
-        // Role-playing entities
-        ModuleAssembly entityRoleModule = contextLayer.module( "CONTEXT-EntityRole" );
-        entityRoleModule
-            .entities(
-                CargoRoleMap.class,
-                CargosRoleMap.class,
-                HandlingEventRoleMap.class,
-                HandlingEventsRoleMap.class )
-            .visibleIn( application );
-
-        // Non-role-playing entities
-        ModuleAssembly entityNonRoleModule = contextLayer.module( "CONTEXT-EntityNonRole" );
-        entityNonRoleModule
-            .entities(
-                LocationEntity.class,
-                VoyageEntity.class )
-            .visibleIn( application );
-
-        // Role-playing values
-        ModuleAssembly valueRoleModule = contextLayer.module( "CONTEXT-ValueRole" );
-        valueRoleModule
-            .values(
-                ItineraryRoleMap.class,
-                RouteSpecificationRoleMap.class )
-            .visibleIn( application );
-
-        ModuleAssembly contextSupportModule = contextLayer.module( "CONTEXT-ContextSupport" );
-        contextSupportModule
-            .addServices(
-                RoutingService.class,
-                ApplicationEvents.class )
-            .visibleIn( application );
-
-        contextSupportModule
-            .values(
-                RegisterHandlingEventAttemptDTO.class )
-            .visibleIn( application );
-    }
-
-    private void assembleDataLayer( LayerAssembly dataLayer )
-        throws AssemblyException
-    {
-        // Non-role-playing values
-        ModuleAssembly dataModule = dataLayer.module( "DATA-Data" );
-        dataModule
-            .values(
-                TrackingId.class,
-                Delivery.class,
-                ExpectedHandlingEvent.class,
-                UnLocode.class,
-                Leg.class,
-                CarrierMovement.class,
-                Schedule.class,
-                VoyageNumber.class )
-            .visibleIn( application );
-    }
-
-    private void assembleInfrastructureLayer( LayerAssembly infrastructureLayer )
-        throws AssemblyException
-    {
-        ModuleAssembly serializationModule = infrastructureLayer.module( "INFRASTRUCTURE-Serialization" );
-        serializationModule
-            .services( OrgJsonValueSerializationService.class )
-            .taggedWith( ValueSerialization.Formats.JSON )
-            .setMetaInfo( new Function<Application, Module>()
-        {
-            @Override
-            public Module map( Application application )
-            {
-                return application.findModule( "CONTEXT", "CONTEXT-ContextSupport" );
-            }
-        } )
-        .visibleIn( application );
-
-        ModuleAssembly indexingModule = infrastructureLayer.module( "INFRASTRUCTURE-Indexing" );
-        indexingModule
-            .objects(
-                EntityStateSerializer.class,
-                EntityTypeSerializer.class );
-
-        indexingModule
-            .addServices(
-                MemoryRepositoryService.class,
-                RdfIndexingEngineService.class )
-            .instantiateOnStartup()
-            .visibleIn( application );
-
-        ModuleAssembly entityStoreModule = infrastructureLayer.module( "INFRASTRUCTURE-EntityStore" );
-        entityStoreModule
-            .addServices(
-                MemoryEntityStoreService.class,
-                UuidIdentityGeneratorService.class )
-            .instantiateOnStartup()
-            .visibleIn( application );
-
-        ModuleAssembly externalServiceModule = infrastructureLayer.module( "INFRASTRUCTURE-ExternalService" );
-        externalServiceModule
-            .importedServices(
-                GraphTraversalService.class )
-            .setMetaInfo( new GraphTraversalServiceImpl( new GraphDAO() ) )
-            .visibleIn( application );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/sampledata/BaseData.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/sampledata/BaseData.java
deleted file mode 100644
index ac474a6..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/sampledata/BaseData.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.bootstrap.sampledata;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import org.joda.time.DateTime;
-import org.joda.time.LocalDate;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Leg;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.UnLocode;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.CarrierMovement;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Schedule;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
-
-/**
- * Test base class with shared Locations, Voyages etc.
- */
-public abstract class BaseData
-{
-    protected Module module;
-
-    protected static UnLocode AUMEL;
-    protected static UnLocode CNHGH;
-    protected static UnLocode CNHKG;
-    protected static UnLocode CNSHA;
-    protected static UnLocode DEHAM;
-    protected static UnLocode FIHEL;
-    protected static UnLocode JNTKO;
-    protected static UnLocode NLRTM;
-    protected static UnLocode SEGOT;
-    protected static UnLocode SESTO;
-    protected static UnLocode USCHI;
-    protected static UnLocode USDAL;
-    protected static UnLocode USNYC;
-
-    public BaseData( Module module )
-    {
-        this.module = module;
-    }
-
-    protected UnLocode unlocode( String unlocodeString )
-    {
-        ValueBuilder<UnLocode> unlocode = module.newValueBuilder( UnLocode.class );
-        unlocode.prototype().code().set( unlocodeString );
-        return unlocode.newInstance();
-    }
-
-    protected CarrierMovement carrierMovement( Location depLoc, Location arrLoc, Date depTime, Date arrTime )
-    {
-        ValueBuilder<CarrierMovement> carrierMovement = module.newValueBuilder( CarrierMovement.class );
-        carrierMovement.prototype().departureLocation().set( depLoc );
-        carrierMovement.prototype().arrivalLocation().set( arrLoc );
-        carrierMovement.prototype().departureTime().set( depTime );
-        carrierMovement.prototype().arrivalTime().set( arrTime );
-        return carrierMovement.newInstance();
-    }
-
-    protected Schedule schedule( CarrierMovement... carrierMovements )
-    {
-        ValueBuilder<Schedule> schedule = module.newValueBuilder( Schedule.class );
-        List<CarrierMovement> cm = new ArrayList<CarrierMovement>();
-        cm.addAll( Arrays.asList( carrierMovements ) );
-        schedule.prototype().carrierMovements().set( cm );
-        return schedule.newInstance();
-    }
-
-    protected Leg leg( Voyage voyage, Location load, Location unload, Date loadTime, Date unloadTime )
-    {
-        ValueBuilder<Leg> leg = module.newValueBuilder( Leg.class );
-        leg.prototype().voyage().set( voyage );
-        leg.prototype().loadLocation().set( load );
-        leg.prototype().unloadLocation().set( unload );
-        leg.prototype().loadTime().set( loadTime );
-        leg.prototype().unloadTime().set( unloadTime );
-        return leg.newInstance();
-    }
-
-    protected Itinerary itinerary( Leg... legArray )
-    {
-        ValueBuilder<Itinerary> itinerary = module.newValueBuilder( Itinerary.class );
-        List<Leg> legs = new ArrayList<Leg>();
-        legs.addAll( Arrays.asList( legArray ) );
-        itinerary.prototype().legs().set( legs );
-        return itinerary.newInstance();
-    }
-
-    protected RouteSpecification routeSpecification( Location origin, Location destination, Date deadline )
-    {
-        ValueBuilder<RouteSpecification> routeSpec = module.newValueBuilder( RouteSpecification.class );
-        routeSpec.prototype().origin().set( origin );
-        routeSpec.prototype().destination().set( destination );
-        routeSpec.prototype().arrivalDeadline().set( deadline );
-        return routeSpec.newInstance();
-    }
-
-    protected static Date day( int days )
-    {
-        return LocalDate.now().plusDays( days ).toDate();
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/sampledata/BaseDataService.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/sampledata/BaseDataService.java
deleted file mode 100644
index 116b733..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/sampledata/BaseDataService.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.bootstrap.sampledata;
-
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.CargosEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.HandlingEventsEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.UnLocode;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Schedule;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.VoyageNumber;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.qi4j.api.usecase.UsecaseBuilder.newUsecase;
-
-/**
- * Create basic sample data
- */
-@Mixins( BaseDataService.Mixin.class )
-@Activators( BaseDataService.Activator.class )
-public interface BaseDataService
-    extends ServiceComposite
-{
-
-    void createBaseData() 
-    		throws Exception;
-
-    class Activator
-            extends ActivatorAdapter<ServiceReference<BaseDataService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<BaseDataService> activated )
-                throws Exception
-        {
-            activated.get().createBaseData();
-        }
-
-    }
-
-    public abstract class Mixin extends BaseData
-        implements BaseDataService
-    {
-        private static final Logger logger = LoggerFactory.getLogger( BaseDataService.class );
-
-        public Mixin( @Structure Module module )
-        {
-            super( module );
-        }
-
-        @Override
-        public void createBaseData()
-        	throws Exception
-        {
-            logger.debug( "CREATING BASIC DATA..." );
-            UnitOfWork uow = module.newUnitOfWork( newUsecase( "Open uow for " ) );
-            try
-            {
-	            // UnLocode value objects
-	            AUMEL = unlocode( "AUMEL" ); // Melbourne
-	            CNHGH = unlocode( "CNHGH" ); // Hangzou
-	            CNHKG = unlocode( "CNHKG" ); // Hong Kong
-	            CNSHA = unlocode( "CNSHA" ); // Shanghai
-	            DEHAM = unlocode( "DEHAM" ); // Hamburg
-	            FIHEL = unlocode( "FIHEL" ); // Helsinki
-	            JNTKO = unlocode( "JNTKO" ); // Tokyo
-	            NLRTM = unlocode( "NLRTM" ); // Rotterdam
-	            SEGOT = unlocode( "SEGOT" ); // Gothenburg
-	            SESTO = unlocode( "SESTO" ); // Stockholm
-	            USCHI = unlocode( "USCHI" ); // Chicago
-	            USDAL = unlocode( "USDAL" ); // Dallas
-	            USNYC = unlocode( "USNYC" ); // New York
-	
-	            // Location entity objects
-                Location MELBOURNE = location( AUMEL, "Melbourne" );
-                Location HANGZHOU = location( CNHGH, "Hangzhou" );
-                Location HONGKONG = location( CNHKG, "Hongkong" );
-                Location SHANGHAI = location( CNSHA, "Shanghai" );
-                Location HAMBURG = location( DEHAM, "Hamburg" );
-                Location HELSINKI = location( FIHEL, "Helsinki" );
-                Location TOKYO = location( JNTKO, "Tokyo" );
-                Location ROTTERDAM = location( NLRTM, "Rotterdam" );
-                Location GOTHENBURG = location( SEGOT, "Gothenburg" );
-                Location STOCKHOLM = location( SESTO, "Stockholm" );
-                Location CHICAGO = location( USCHI, "Chicago" );
-                Location DALLAS = location( USDAL, "Dallas" );
-                Location NEWYORK = location( USNYC, "New York" );
-
-	            // Voyage entity objects
-                Voyage V100S = voyage( "V100S", schedule(
-	                carrierMovement( NEWYORK, CHICAGO, day( 1 ), day( 2 ) ),
-	                carrierMovement( CHICAGO, DALLAS, day( 8 ), day( 9 ) )
-	            ) );
-                Voyage V200T = voyage( "V200T", schedule(
-	                carrierMovement( NEWYORK, CHICAGO, day( 7 ), day( 8 ) ),
-	                carrierMovement( CHICAGO, DALLAS, day( 8 ), day( 9 ) )
-	            ) );
-                Voyage V300A = voyage( "V300A", schedule(
-	                carrierMovement( DALLAS, HAMBURG, day( 10 ), day( 14 ) ),
-	                carrierMovement( HAMBURG, STOCKHOLM, day( 15 ), day( 16 ) ),
-	                carrierMovement( STOCKHOLM, HELSINKI, day( 17 ), day( 18 ) )
-	            ) );
-                Voyage V400S = voyage( "V400S", schedule(
-	                carrierMovement( TOKYO, ROTTERDAM, day( 9 ), day( 15 ) ),
-	                carrierMovement( ROTTERDAM, HAMBURG, day( 15 ), day( 16 ) ),
-	                carrierMovement( HAMBURG, MELBOURNE, day( 17 ), day( 26 ) ),
-	                carrierMovement( MELBOURNE, TOKYO, day( 27 ), day( 33 ) )
-	            ) );
-                Voyage V500S = voyage( "V500S", schedule(
-	                carrierMovement( HAMBURG, STOCKHOLM, day( 17 ), day( 19 ) ),
-	                carrierMovement( STOCKHOLM, HELSINKI, day( 20 ), day( 21 ) )
-	            ) );
-
-	            // Cargo and HandlingEvent factories
-                CargosEntity CARGOS = uow.newEntity( CargosEntity.class, CargosEntity.CARGOS_ID );
-                uow.newEntity( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
-	
-	            logger.debug( "BASIC DATA CREATED" );
-	            uow.complete();
-            }
-            catch(Exception e)
-            {
-            	uow.discard();
-            	logger.error("CANNOT CREATE BASIC DATA");
-            	throw e;
-            }
-        }
-
-        private Location location( UnLocode unlocode, String locationStr )
-        {
-            UnitOfWork uow = module.currentUnitOfWork();
-            EntityBuilder<Location> location = uow.newEntityBuilder( Location.class, unlocode.code().get() );
-            location.instance().unLocode().set( unlocode );
-            location.instance().name().set( locationStr );
-            return location.newInstance();
-        }
-
-        private Voyage voyage( String voyageNumberStr, Schedule schedule )
-        {
-            UnitOfWork uow = module.currentUnitOfWork();
-            EntityBuilder<Voyage> voyage = uow.newEntityBuilder( Voyage.class, voyageNumberStr );
-
-            // VoyageNumber
-            ValueBuilder<VoyageNumber> voyageNumber = module.newValueBuilder( VoyageNumber.class );
-            voyageNumber.prototype().number().set( voyageNumberStr );
-            voyage.instance().voyageNumber().set( voyageNumber.newInstance() );
-
-            // Schedule
-            voyage.instance().schedule().set( schedule );
-            return voyage.newInstance();
-        }
-
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/sampledata/SampleDataService.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/sampledata/SampleDataService.java
deleted file mode 100644
index c991893..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/sampledata/SampleDataService.java
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.bootstrap.sampledata;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Random;
-import java.util.UUID;
-import org.joda.time.LocalDate;
-import org.joda.time.LocalTime;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.QueryBuilderFactory;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.sample.dcicargo.sample_a.context.shipping.booking.BookNewCargo;
-import org.qi4j.sample.dcicargo.sample_a.context.shipping.handling.RegisterHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.CargosEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.ExpectedHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.qi4j.api.usecase.UsecaseBuilder.newUsecase;
-import static org.qi4j.sample.dcicargo.sample_a.infrastructure.dci.Context.prepareContextBaseClass;
-
-/**
- * Create sample Cargos in different delivery stages
- */
-@Mixins( SampleDataService.Mixin.class )
-@Activators( SampleDataService.Activator.class )
-public interface SampleDataService
-    extends ServiceComposite
-{
-
-    void insertSampleData()
-            throws Exception;
-
-    class Activator
-            extends ActivatorAdapter<ServiceReference<SampleDataService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<SampleDataService> activated )
-                throws Exception
-        {
-            activated.get().insertSampleData();
-        }
-
-    }
-
-    public abstract class Mixin
-        implements SampleDataService
-    {
-        @Structure
-        QueryBuilderFactory qbf;
-
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        @Service // We depend on BaseData to be inserted
-        BaseDataService baseDataService;
-
-        private static final Logger logger = LoggerFactory.getLogger( SampleDataService.class );
-
-        @Override
-        public void insertSampleData()
-            throws Exception
-        {
-            prepareContextBaseClass( uowf );
-
-            logger.info( "######  CREATING SAMPLE DATA...  ##########################################" );
-
-            // Create cargos
-            populateRandomCargos( 15 );
-
-            // Handle cargos
-            UnitOfWork uow = uowf.newUnitOfWork( newUsecase( "### Create sample data" ) );
-            try
-            {
-                int i = 11; // starting at 11 for sortable tracking id prefix in lists
-                QueryBuilder<Cargo> qb = qbf.newQueryBuilder( Cargo.class );
-                for( Cargo cargo : uow.newQuery( qb ) )
-                {
-                    String trackingId = cargo.trackingId().get().id().get();
-                    ExpectedHandlingEvent nextEvent;
-                    Date time;
-                    String port;
-                    String voyage;
-                    HandlingEventType type;
-
-                    // BOOK cargo with no handling (i == 11)
-
-                    // ROUTE
-                    if( i > 11 )
-                    {
-                        Itinerary itinerary = new BookNewCargo( cargo ).routeCandidates().get( 0 );
-                        new BookNewCargo( cargo, itinerary ).assignCargoToRoute();
-                    }
-
-                    // RECEIVE
-                    if( i > 12 )
-                    {
-                        nextEvent = cargo.delivery().get().nextExpectedHandlingEvent().get();
-                        port = nextEvent.location().get().getCode();
-                        Date mockTime = new Date();
-                        new RegisterHandlingEvent( mockTime, mockTime, trackingId, "RECEIVE", port, null ).register();
-                    }
-
-                    // LOAD
-                    if( i > 13 )
-                    {
-                        nextEvent = cargo.delivery().get().nextExpectedHandlingEvent().get();
-                        time = nextEvent.time().get();
-                        port = nextEvent.location().get().getCode();
-                        voyage = nextEvent.voyage().get().voyageNumber().get().number().get();
-                        new RegisterHandlingEvent( time, time, trackingId, "LOAD", port, voyage ).register();
-                    }
-
-                    // UNLOAD
-                    if( i > 14 )
-                    {
-                        nextEvent = cargo.delivery().get().nextExpectedHandlingEvent().get();
-                        time = nextEvent.time().get();
-                        port = nextEvent.location().get().getCode();
-                        voyage = nextEvent.voyage().get().voyageNumber().get().number().get();
-                        new RegisterHandlingEvent( time, time, trackingId, "UNLOAD", port, voyage ).register();
-                    }
-
-                    // Cargo is now in port
-                    nextEvent = cargo.delivery().get().nextExpectedHandlingEvent().get();
-                    time = nextEvent.time().get();
-                    port = nextEvent.location().get().getCode();
-                    type = nextEvent.handlingEventType().get();
-
-                    // MISDIRECTED: Unexpected customs handling before reaching destination
-                    if( i == 16 )
-                    {
-                        new RegisterHandlingEvent( time, time, trackingId, "CUSTOMS", port, null ).register();
-                    }
-
-                    // MISDIRECTED: Unexpected claim before reaching destination
-                    if( i == 17 )
-                    {
-                        new RegisterHandlingEvent( time, time, trackingId, "CLAIM", port, null ).register();
-                    }
-
-                    // MISDIRECTED: LOAD in wrong port
-                    if( i == 18 )
-                    {
-                        String wrongPort = port.equals( "USDAL" ) ? "USCHI" : "USDAL";
-                        voyage = nextEvent.voyage().get().voyageNumber().get().number().get();
-                        new RegisterHandlingEvent( time, time, trackingId, "LOAD", wrongPort, voyage ).register();
-                    }
-
-                    // MISDIRECTED: LOAD onto wrong carrier
-                    if( i == 19 )
-                    {
-                        voyage = nextEvent.voyage().get().voyageNumber().get().number().get();
-                        String wrongVoyage = voyage.equals( "V100S" ) ? "V200T" : "V100S";
-                        new RegisterHandlingEvent( time, time, trackingId, "LOAD", port, wrongVoyage ).register();
-                    }
-
-                    // MISDIRECTED: LOAD onto wrong carrier in wrong port
-                    if( i == 20 )
-                    {
-                        String wrongPort = port.equals( "USDAL" ) ? "USCHI" : "USDAL";
-                        voyage = nextEvent.voyage().get().voyageNumber().get().number().get();
-                        String wrongVoyage = voyage.equals( "V100S" ) ? "V200T" : "V100S";
-                        new RegisterHandlingEvent( time, time, trackingId, "LOAD", wrongPort, wrongVoyage ).register();
-                    }
-
-                    // MISDIRECTED: UNLOAD in wrong port
-                    if( i == 21 )
-                    {
-                        String wrongPort = port.equals( "USDAL" ) ? "USCHI" : "USDAL";
-                        voyage = nextEvent.voyage().get().voyageNumber().get().number().get();
-                        new RegisterHandlingEvent( time, time, trackingId, "UNLOAD", wrongPort, voyage ).register();
-                    }
-
-                    // MISDIRECTED: UNLOAD from wrong carrier
-                    if( i == 22 )
-                    {
-                        voyage = nextEvent.voyage().get().voyageNumber().get().number().get();
-                        String wrongVoyage = voyage.equals( "V100S" ) ? "V200T" : "V100S";
-                        new RegisterHandlingEvent( time, time, trackingId, "UNLOAD", port, wrongVoyage ).register();
-                    }
-
-                    // MISDIRECTED: UNLOAD from wrong carrier in wrong port
-                    if( i == 23 )
-                    {
-                        String wrongPort = port.equals( "USDAL" ) ? "USCHI" : "USDAL";
-                        voyage = nextEvent.voyage().get().voyageNumber().get().number().get();
-                        String wrongVoyage = voyage.equals( "V100S" ) ? "V200T" : "V100S";
-                        new RegisterHandlingEvent( time, time, trackingId, "UNLOAD", wrongPort, wrongVoyage ).register();
-                    }
-
-                    // Complete all LOAD/UNLOADS
-                    if( i > 23 )
-                    {
-                        do
-                        {
-                            voyage = nextEvent.voyage().get().voyageNumber().get().number().get();
-                            new RegisterHandlingEvent( time, time, trackingId, type.name(), port, voyage ).register();
-
-                            nextEvent = cargo.delivery().get().nextExpectedHandlingEvent().get();
-                            time = nextEvent.time().get();
-                            port = nextEvent.location().get().getCode();
-                            type = nextEvent.handlingEventType().get();
-                        }
-                        while( type != HandlingEventType.CLAIM );
-                    }
-
-                    // CLAIM at destination - this ends the life cycle of the cargo delivery
-                    if( i == 25 )
-                    {
-                        new RegisterHandlingEvent( time, time, trackingId, "CLAIM", port, null ).register();
-                    }
-
-                    // Add more cases if needed...
-
-                    i++;
-                }
-
-                uow.complete();
-            }
-            catch( Exception e )
-            {
-                uow.discard();
-                logger.error( "Problem handling cargos: " + e.getMessage() );
-                throw e;
-            }
-
-            logger.info( "######  SAMPLE DATA CREATED  ##############################################" );
-        }
-
-        private void populateRandomCargos( int numberOfCargos )
-        {
-            Usecase usecase = UsecaseBuilder.newUsecase( "### Populate Random Cargos ###" );
-            UnitOfWork uow = uowf.newUnitOfWork( usecase );
-
-            CargosEntity cargos = uow.get( CargosEntity.class, CargosEntity.CARGOS_ID );
-
-            QueryBuilder<Location> qb = qbf.newQueryBuilder( Location.class );
-            Query<Location> allLocations = uow.newQuery( qb );
-            int locationSize = (int) allLocations.count();
-
-            // Make array for selection of location with random index
-            final List<Location> locationList = new ArrayList<Location>();
-            for( Location location : allLocations )
-            {
-                locationList.add( location );
-            }
-
-            Location origin;
-            Location destination;
-            Random random = new Random();
-            Date deadline;
-            String uuid;
-            String id;
-            try
-            {
-                for( int i = 0; i < numberOfCargos; i++ )
-                {
-                    origin = locationList.get( random.nextInt( locationSize ) );
-
-                    // Find destination different from origin
-                    do
-                    {
-                        destination = locationList.get( random.nextInt( locationSize ) );
-                    }
-                    while( destination.equals( origin ) );
-
-                    deadline = new LocalDate().plusDays( 15 + random.nextInt( 10 ) )
-                        .toDateTime( new LocalTime() )
-                        .toDate();
-
-                    // Build sortable random tracking ids
-                    uuid = UUID.randomUUID().toString().toUpperCase();
-                    id = ( i + 11 ) + "-" + uuid.substring( 0, uuid.indexOf( "-" ) );
-
-                    new BookNewCargo( cargos, origin, destination, deadline ).createCargo( id );
-                }
-                uow.complete();
-            }
-            catch( Exception e )
-            {
-                uow.discard();
-                logger.error( "Problem booking a new cargo: " + e.getMessage() );
-            }
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/BookingQueries.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/BookingQueries.java
deleted file mode 100644
index 6a047f3..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/BookingQueries.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.query;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.wicket.model.IModel;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.sample.dcicargo.sample_a.context.support.FoundNoRoutesException;
-import org.qi4j.sample.dcicargo.sample_a.context.support.RoutingService;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.model.JSONModel;
-
-/**
- * Booking queries
- *
- * This is in a Zest composite since we can then conveniently get the routing service injected.
- * We could choose to implement all query classes like this too.
- *
- * Used by the communication layer only. Can change according to ui needs.
- */
-@Mixins( BookingQueries.Mixin.class )
-public interface BookingQueries
-    extends TransientComposite
-{
-    List<IModel<Itinerary>> routeCandidates( String trackingIdString )
-        throws FoundNoRoutesException;
-
-    abstract class Mixin
-        implements BookingQueries
-    {
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        @Service
-        RoutingService routingService;
-
-        public List<IModel<Itinerary>> routeCandidates( final String trackingIdString )
-            throws FoundNoRoutesException
-        {
-            Cargo cargo = uowf.currentUnitOfWork().get( Cargo.class, trackingIdString );
-            List<Itinerary> routes = routingService.fetchRoutesForSpecification( cargo.routeSpecification().get() );
-
-            List<IModel<Itinerary>> modelList = new ArrayList<IModel<Itinerary>>();
-            for( Itinerary itinerary : routes )
-            {
-                modelList.add( JSONModel.of( itinerary ) );
-            }
-
-            return modelList;
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/CommonQueries.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/CommonQueries.java
deleted file mode 100644
index 4c7182f..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/CommonQueries.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.query;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.wicket.model.IModel;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.dto.CargoDTO;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.CargoEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.model.EntityModel;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.model.Queries;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.model.QueryModel;
-
-import static org.qi4j.api.query.QueryExpressions.orderBy;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-/**
- * Common queries
- *
- * Queries shared across packages.
- *
- * Used by the communication layer only. Can change according to ui needs.
- */
-public class CommonQueries extends Queries
-{
-    public IModel<CargoDTO> cargo( String trackingId )
-    {
-        return EntityModel.of( CargoEntity.class, trackingId, CargoDTO.class );
-    }
-
-    public IModel<List<CargoDTO>> cargoList()
-    {
-        return new QueryModel<CargoDTO, CargoEntity>( CargoDTO.class )
-        {
-            public Query<CargoEntity> getQuery()
-            {
-                QueryBuilder<CargoEntity> qb = qbf.newQueryBuilder( CargoEntity.class );
-                return uowf.currentUnitOfWork().newQuery( qb )
-                    .orderBy( orderBy( templateFor( CargoEntity.class ).trackingId().get().id() ) );
-            }
-        };
-    }
-
-    public List<String> unLocodes()
-    {
-        QueryBuilder<Location> qb = qbf.newQueryBuilder( Location.class );
-        Query<Location> locations = uowf.currentUnitOfWork().newQuery( qb )
-            .orderBy( orderBy( templateFor( Location.class ).unLocode().get().code() ) );
-        List<String> unLocodeList = new ArrayList<String>();
-        for( Location location : locations )
-        {
-            unLocodeList.add( location.getCode() );
-        }
-
-        return unLocodeList;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/HandlingQueries.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/HandlingQueries.java
deleted file mode 100644
index 1289822..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/HandlingQueries.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.query;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.CargoEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.model.Queries;
-
-import static org.qi4j.api.query.QueryExpressions.orderBy;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-/**
- * Handling queries
- *
- * Used by the communication layer only. Can change according to ui needs.
- */
-public class HandlingQueries extends Queries
-{
-    public List<String> voyages()
-    {
-        QueryBuilder<Voyage> qb = qbf.newQueryBuilder( Voyage.class );
-        Query<Voyage> voyages = uowf.currentUnitOfWork().newQuery( qb )
-            .orderBy( orderBy( templateFor( Voyage.class ).voyageNumber() ) );
-
-        List<String> voyageList = new ArrayList<String>();
-        for( Voyage voyage : voyages )
-        {
-            voyageList.add( voyage.voyageNumber().get().number().get() );
-        }
-        return voyageList;
-    }
-
-    public List<String> cargoIds()
-    {
-        QueryBuilder<CargoEntity> qb = qbf.newQueryBuilder( CargoEntity.class );
-        Query<CargoEntity> cargos = uowf.currentUnitOfWork().newQuery( qb )
-            .orderBy( orderBy( templateFor( CargoEntity.class ).trackingId().get().id() ) );
-        List<String> cargoList = new ArrayList<String>();
-        for( CargoEntity cargo : cargos )
-        {
-            cargoList.add( cargo.trackingId().get().id().get() );
-        }
-        return cargoList;
-    }
-
-    public List<String> eventTypes()
-    {
-        List<String> eventTypes = new ArrayList<String>();
-        for( HandlingEventType eventType : HandlingEventType.values() )
-        {
-            eventTypes.add( eventType.name() );
-        }
-        return eventTypes;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/TrackingQueries.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/TrackingQueries.java
deleted file mode 100644
index a849460..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/TrackingQueries.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.query;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.wicket.model.IModel;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.QueryExpressions;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.dto.HandlingEventDTO;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.CargoEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.HandlingEventEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.model.Queries;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.model.QueryModel;
-
-import static org.qi4j.api.query.QueryExpressions.*;
-
-/**
- * Tracking queries
- *
- * Used by the communication layer only. Can change according to ui needs.
- */
-public class TrackingQueries extends Queries
-{
-    public List<String> routedCargos()
-    {
-        Cargo cargoEntity = templateFor( CargoEntity.class );
-
-        QueryBuilder<CargoEntity> qb = qbf.newQueryBuilder( CargoEntity.class )
-            .where( isNotNull( cargoEntity.itinerary() ) );
-        Query<CargoEntity> cargos = uowf.currentUnitOfWork().newQuery( qb )
-            .orderBy( orderBy( cargoEntity.trackingId().get().id() ) );
-
-        List<String> cargoList = new ArrayList<String>();
-        for( CargoEntity cargo : cargos )
-        {
-            cargoList.add( cargo.trackingId().get().id().get() );
-        }
-
-        return cargoList;
-    }
-
-    public IModel<List<HandlingEventDTO>> events( final String trackingIdString )
-    {
-        return new QueryModel<HandlingEventDTO, HandlingEventEntity>( HandlingEventDTO.class )
-        {
-            public Query<HandlingEventEntity> getQuery()
-            {
-                HandlingEvent eventTemplate = templateFor( HandlingEvent.class );
-
-                QueryBuilder<HandlingEventEntity> qb = qbf.newQueryBuilder( HandlingEventEntity.class )
-                    .where( QueryExpressions.eq( eventTemplate.trackingId().get().id(), trackingIdString ) );
-                return uowf.currentUnitOfWork().newQuery( qb )
-                    .orderBy( orderBy( eventTemplate.completionTime() ) );
-            }
-        };
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/dto/CargoDTO.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/dto/CargoDTO.java
deleted file mode 100644
index 3105853..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/dto/CargoDTO.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.query.dto;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-import org.qi4j.library.conversion.values.Unqualified;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.TrackingId;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.conversion.DTO;
-
-/**
- * Cargo DTO
- *
- * We need the @Unqualified annotation since the CargoDTO interface has other properties than {@link Cargo}
- * so that properties can not be directly mapped when we convert from entity to immutable value DTO.
- * With the annotation, property access methods are compared by name instead.
- */
-@Unqualified
-public interface CargoDTO extends DTO
-{
-    Property<TrackingId> trackingId();
-
-    // Associated Location entity in Cargo is converted to an immutable LocationDTO value object
-    Property<LocationDTO> origin();
-
-    Property<RouteSpecification> routeSpecification();
-
-    Property<Delivery> delivery();
-
-    @Optional
-    Property<Itinerary> itinerary();
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/dto/HandlingEventDTO.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/dto/HandlingEventDTO.java
deleted file mode 100644
index b8e3a76..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/dto/HandlingEventDTO.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.query.dto;
-
-import java.util.Date;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-import org.qi4j.library.conversion.values.Unqualified;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.TrackingId;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.conversion.DTO;
-
-/**
- * HandlingEvent DTO
- *
- * We need the @Unqualified annotation since the HandlingEventDTO interface has other properties than
- * {@link HandlingEvent} so that properties can not be directly mapped when we convert from entity to
- * immutable value DTO. With the annotation, property access methods are compared by name instead.
- */
-@Unqualified
-public interface HandlingEventDTO extends DTO
-{
-    Property<Date> completionTime();
-
-    Property<TrackingId> trackingId();
-
-    Property<HandlingEventType> handlingEventType();
-
-    Property<LocationDTO> location();
-
-    @Optional
-    Property<VoyageDTO> voyage();
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/dto/LocationDTO.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/dto/LocationDTO.java
deleted file mode 100644
index 7b7011d..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/dto/LocationDTO.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.query.dto;
-
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.conversion.DTO;
-
-/**
- * Location DTO
- *
- * Since all properties of Location are immutable, we can simply re-use the same interface.
- * We need the Location as a DTO when we do entity to value conversions.
- */
-public interface LocationDTO extends Location, DTO
-{
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/dto/VoyageDTO.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/dto/VoyageDTO.java
deleted file mode 100644
index fba3857..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/query/dto/VoyageDTO.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.query.dto;
-
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.conversion.DTO;
-
-/**
- * Voyage DTO
- *
- * Since all properties of Voyage are immutable, we can simply re-use the same interface.
- * We need the Voyage as a DTO when we do entity to value conversions.
- */
-public interface VoyageDTO extends Voyage, DTO
-{
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/BasePage.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/BasePage.java
deleted file mode 100644
index e43e450..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/BasePage.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.web;
-
-import com.google.code.joliratools.StatelessAjaxFallbackLink;
-import org.apache.wicket.AttributeModifier;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.link.Link;
-import org.apache.wicket.markup.html.panel.Fragment;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.WicketQi4jApplication;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.page.BaseWebPage;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.tabs.TabsPanel;
-
-/**
- * Base Wicket page of the DCI Sample application
- */
-public class BasePage extends BaseWebPage
-{
-    private final Link toggleLinks;
-    private static boolean showLInks = false;
-    private Fragment links = new Fragment( "links", "linksFragment", this );
-
-    public BasePage( String activeTab )
-    {
-        this( activeTab, null );
-    }
-
-    public BasePage( String activeTab, PageParameters pageParameters )
-    {
-        super( pageParameters );
-
-        toggleLinks = new StatelessAjaxFallbackLink<Void>( "toggleLinks" )
-        {
-            @Override
-            public void onClick( AjaxRequestTarget target )
-            {
-                // Open/close triangle of this toggle link
-                add( new AttributeModifier( "class", Model.of( showLInks ? "closed" : "open" ) ) );
-
-                // Show/hide links
-                links.setVisible( showLInks = !showLInks );
-
-                // Update with ajax if browser allows
-                if( target != null )
-                {
-                    target.add( links, toggleLinks );
-                }
-            }
-        };
-        add( toggleLinks );
-        add( links.setOutputMarkupPlaceholderTag( true ).setVisible( false ) );
-
-        add( new Label( "version", ( (WicketQi4jApplication) getApplication() ).appVersion() ) );
-
-        add( new TabsPanel( activeTab ) );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/BookNewCargoPage.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/BookNewCargoPage.java
deleted file mode 100644
index ccb6946..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/BookNewCargoPage.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.web.booking;
-
-import java.util.Date;
-import java.util.List;
-import org.apache.wicket.Session;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
-import org.apache.wicket.ajax.markup.html.form.AjaxFallbackButton;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.markup.html.panel.ComponentFeedbackPanel;
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.joda.time.LocalDate;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.CommonQueries;
-import org.qi4j.sample.dcicargo.sample_a.context.shipping.booking.BookNewCargo;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.TrackingId;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.form.AbstractForm;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.form.DateTextFieldWithPicker;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.form.SelectorInForm;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.prevnext.PrevNext;
-
-/**
- * Book new cargo
- *
- * An example of UI validation:
- * - you can't choose equal locations
- * - earliest deadline you can choose from the date picker is tomorrow (we could set any date that the domain wants).
- *
- * More elaborate validation rules could be enforced in a real domain to avoid even touching
- * the backend with invalid data (of course we would still need backend validation).
- */
-public class BookNewCargoPage extends BookingBasePage
-{
-    public BookNewCargoPage()
-    {
-        add( new BookNewCargoForm() );
-        setVersioned( false );
-    }
-
-    private final class BookNewCargoForm extends AbstractForm<Void>
-    {
-        // Set by Wicket property resolvers:
-        private String origin, destination;
-        private Date deadline;
-
-        public BookNewCargoForm()
-        {
-            List<String> locations = new CommonQueries().unLocodes();
-
-            final FeedbackPanel feedback = new FeedbackPanel( "feedback" );
-            add( feedback.setOutputMarkupId( true ) );
-
-            final SelectorInForm originSelector = new SelectorInForm(
-                "origin", "Origin", locations, this, "destination" );
-            originSelector.setRequired( true );
-
-            final ComponentFeedbackPanel originFeedback = new ComponentFeedbackPanel(
-                "originFeedback", originSelector );
-            add( originFeedback.setOutputMarkupId( true ) );
-
-            final SelectorInForm destinationSelector = new SelectorInForm(
-                "destination", "Destinatin", locations, this, "origin" );
-            destinationSelector.setRequired( true );
-
-            final ComponentFeedbackPanel destinationFeedback = new ComponentFeedbackPanel(
-                "destinationFeedback", destinationSelector );
-            add( destinationFeedback.setOutputMarkupId( true ) );
-
-            // Disable equal locations
-            originSelector.add( new AjaxFormComponentUpdatingBehavior( "onchange" )
-            {
-                @Override
-                protected void onUpdate( AjaxRequestTarget target )
-                {
-                    // Exclude origin in destination drop down
-                    target.add( originSelector, originFeedback, destinationSelector );
-                    focusFirstError( target );
-                }
-            } );
-
-            destinationSelector.add( new AjaxFormComponentUpdatingBehavior( "onchange" )
-            {
-                @Override
-                protected void onUpdate( AjaxRequestTarget target )
-                {
-                    // Exclude destination in origin drop down
-                    target.add( destinationSelector, destinationFeedback, originSelector );
-                    focusFirstError( target );
-                }
-            } );
-
-            // Deadline
-            final DateTextFieldWithPicker deadlineField = new DateTextFieldWithPicker( "deadline", "Arrival deadline", this );
-            deadlineField.earliestDate( new LocalDate().plusDays( 1 ) );
-
-            final ComponentFeedbackPanel deadlineFeedback = new ComponentFeedbackPanel(
-                "deadlineFeedback", deadlineField );
-            add( deadlineFeedback.setOutputMarkupId( true ) );
-
-            add( originSelector, destinationSelector, deadlineField );
-
-            add( new AjaxFallbackButton( "book", this )
-            {
-                @Override
-                protected void onSubmit( AjaxRequestTarget target, Form<?> form )
-                {
-                    try
-                    {
-                        // Perform use case
-                        TrackingId trackingId = new BookNewCargo( origin, destination, deadline ).book();
-
-                        // Add new tracking id to list in session
-                        PrevNext.addId( Session.get(), trackingId.id().get() );
-
-                        // Show created cargo
-                        setResponsePage( CargoDetailsPage.class, new PageParameters().set( 0, trackingId.id().get() ) );
-                    }
-                    catch( Exception e )
-                    {
-                        logger.warn( "Problem booking a new cargo: " + e.getMessage() );
-                        feedback.error( e.getMessage() );
-                        target.add( feedback );
-                    }
-                }
-
-                @Override
-                protected void onError( final AjaxRequestTarget target, Form<?> form )
-                {
-                    target.add( originFeedback, destinationFeedback, deadlineFeedback );
-                    focusFirstError( target );
-                }
-            } );
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/BookingBasePage.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/BookingBasePage.java
deleted file mode 100644
index c577154..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/BookingBasePage.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.web.booking;
-
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.qi4j.sample.dcicargo.sample_a.communication.web.BasePage;
-
-/**
- * Booking base page - to control the selected tab
- */
-public class BookingBasePage extends BasePage
-{
-    public BookingBasePage()
-    {
-        super( "booking" );
-    }
-
-    public BookingBasePage( PageParameters pageParameters )
-    {
-        super( "booking", pageParameters );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/CargoDetailsPage.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/CargoDetailsPage.java
deleted file mode 100644
index 2b44087..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/CargoDetailsPage.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.web.booking;
-
-import java.util.Date;
-import java.util.List;
-import org.apache.wicket.AttributeModifier;
-import org.apache.wicket.devutils.stateless.StatelessComponent;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.basic.MultiLineLabel;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.wicket.markup.html.panel.Fragment;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.LoadableDetachableModel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.CommonQueries;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.dto.CargoDTO;
-import org.qi4j.sample.dcicargo.sample_a.communication.web.tracking.HandlingHistoryPanel;
-import org.qi4j.sample.dcicargo.sample_a.communication.web.tracking.NextHandlingEventPanel;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.RoutingStatus;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Leg;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.color.CorrectColor;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.color.ErrorColor;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.link.LinkPanel;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.prevnext.PrevNext;
-
-/**
- * Cargo details - an overview of all data available about a cargo.
- */
-@StatelessComponent
-public class CargoDetailsPage extends BookingBasePage
-{
-    public CargoDetailsPage( PageParameters parameters )
-    {
-        this( parameters.get( 0 ).toString() );
-    }
-
-    public CargoDetailsPage( String trackingId )
-    {
-        super( new PageParameters().set( 0, trackingId ) );
-
-        IModel<CargoDTO> cargoModel = new CommonQueries().cargo( trackingId );
-        CargoDTO cargo = cargoModel.getObject();
-        Delivery delivery = cargo.delivery().get();
-        RouteSpecification routeSpecification = cargo.routeSpecification().get();
-        final RoutingStatus routingStatus = delivery.routingStatus().get();
-        Boolean isMisrouted = routingStatus == RoutingStatus.MISROUTED;
-
-        add( new PrevNext( "prevNext", CargoDetailsPage.class, trackingId ) );
-
-        add( new Label( "trackingId", trackingId ) );
-        add( new Label( "origin", cargo.origin().get().getString() ) );
-        add( new Label( "destination", routeSpecification.destination()
-            .get()
-            .getString() ).add( new CorrectColor( isMisrouted ) ) );
-        add( new Label( "deadline", Model.of( routeSpecification.arrivalDeadline().get() ) ) );
-        add( new Label( "routingStatus", routingStatus.toString() ).add( new ErrorColor( isMisrouted ) ) );
-        add( new LinkPanel( "changeDestination", ChangeDestinationPage.class, trackingId, "Change destination" ) );
-
-        if( routingStatus == RoutingStatus.NOT_ROUTED )
-        {
-            add( new LinkPanel( "routingAction", RouteCargoPage.class, trackingId, "Route" ) );
-            add( new Label( "delivery" ) );
-            add( new Label( "itinerary" ) );
-        }
-        else if( routingStatus == RoutingStatus.ROUTED )
-        {
-            add( new LinkPanel( "routingAction", RouteCargoPage.class, trackingId, "Re-route" ) );
-            add( new DeliveryFragment( delivery ) );
-            add( new ItineraryFragment( cargoModel, routingStatus ) );
-        }
-        else if( routingStatus == RoutingStatus.MISROUTED )
-        {
-            add( new LinkPanel( "routingAction", RouteCargoPage.class, trackingId, "Re-route" ) );
-            add( new DeliveryFragment( delivery ) );
-            add( new ItineraryFragment( cargoModel, routingStatus ) );
-        }
-        else
-        {
-            throw new RuntimeException( "Unknown routing status." );
-        }
-
-        if( delivery.lastHandlingEvent().get() == null )
-        {
-            add( new Label( "handlingHistoryPanel" ) );
-        }
-        else
-        {
-            add( new HandlingHistoryPanel( "handlingHistoryPanel", cargoModel, trackingId ) );
-        }
-
-        add( new NextHandlingEventPanel( "nextHandlingEventPanel", cargoModel ) );
-    }
-//
-//    @Override
-//    public boolean isVersioned()
-//    {
-//        return false;
-//    }
-
-    private class ItineraryFragment extends Fragment
-    {
-        public ItineraryFragment( final IModel<CargoDTO> cargoModel, final RoutingStatus routingStatus )
-        {
-            super( "itinerary", "itineraryFragment", CargoDetailsPage.this );
-
-            IModel<List<Leg>> legListModel = new LoadableDetachableModel<List<Leg>>()
-            {
-                @Override
-                protected List<Leg> load()
-                {
-                    return cargoModel.getObject().itinerary().get().legs().get();
-                }
-            };
-
-            add( new ListView<Leg>( "legs", legListModel )
-            {
-                @Override
-                protected void populateItem( ListItem<Leg> item )
-                {
-                    Leg leg = item.getModelObject();
-
-                    item.add( new Label( "loadLocation", leg.loadLocation().get().getCode() ) );
-                    item.add( new Label( "loadTime", new Model<Date>( leg.loadTime().get() ) ) );
-                    item.add( new Label( "voyage", leg.voyage().get().voyageNumber().get().number().get() ) );
-
-                    Boolean isMisrouted = routingStatus == RoutingStatus.MISROUTED && item.getIndex() == ( getList().size() - 1 );
-                    item.add( new Label( "unloadLocation", leg.unloadLocation().get().getCode() )
-                                  .add( new ErrorColor( isMisrouted ) ) );
-
-                    item.add( new Label( "unloadTime", new Model<Date>( leg.unloadTime().get() ) ) );
-                }
-            } );
-        }
-    }
-
-    private class DeliveryFragment extends Fragment
-    {
-        public DeliveryFragment( Delivery delivery )
-        {
-            super( "delivery", "deliveryFragment", CargoDetailsPage.this );
-
-            add( new Label( "transportStatus", delivery.transportStatus().get().toString() ) );
-
-            if( delivery.isMisdirected().get() )
-            {
-                String msg = "Cargo is misdirected. \nPlease reroute cargo.";
-                add( new MultiLineLabel( "deliveryStatus", msg ).add( new AttributeModifier( "class", "errorColor" ) ) );
-            }
-            else
-            {
-                add( new Label( "deliveryStatus", "On track" ) );
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/CargoListPage.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/CargoListPage.java
deleted file mode 100644
index 4962a0f..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/CargoListPage.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.web.booking;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import org.apache.wicket.Session;
-import org.apache.wicket.devutils.stateless.StatelessComponent;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.CommonQueries;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.dto.CargoDTO;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.RoutingStatus;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.color.ErrorColor;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.link.LinkPanel;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.prevnext.PrevNext;
-
-/**
- * List of Cargos
- */
-@StatelessComponent
-public class CargoListPage extends BookingBasePage
-{
-    public CargoListPage()
-    {
-        IModel<List<CargoDTO>> cargoList = new CommonQueries().cargoList();
-
-        // Save current trackingIds in session (for prev/next buttons on details page)
-        ArrayList<String> ids = new ArrayList<String>();
-        for( CargoDTO cargo : cargoList.getObject() )
-        {
-            ids.add( cargo.trackingId().get().id().get() );
-        }
-        PrevNext.registerIds( Session.get(), ids );
-
-        add( new ListView<CargoDTO>( "list", cargoList )
-        {
-            @Override
-            protected void populateItem( ListItem<CargoDTO> item )
-            {
-                CargoDTO cargo = item.getModelObject();
-                String trackingId = cargo.trackingId().get().id().get();
-                Delivery delivery = cargo.delivery().get();
-                RoutingStatus routingStatus = cargo.delivery().get().routingStatus().get();
-
-                item.add( new LinkPanel( "trackingId", CargoDetailsPage.class, trackingId ) );
-
-                item.add( new Label( "origin", cargo.origin().get().getCode() ) );
-
-                item.add( new Label( "destination", cargo.routeSpecification().get().destination().get().getCode() ) );
-
-                item.add( new Label( "deadline", new Model<Date>( cargo.routeSpecification()
-                                                                      .get()
-                                                                      .arrivalDeadline()
-                                                                      .get() ) ) );
-
-                item.add( new Label( "routingStatus", routingStatus.toString() ).add( new ErrorColor( routingStatus == RoutingStatus.MISROUTED ) ) );
-
-                Boolean inCustoms = delivery.lastHandlingEvent().get() != null
-                                    && delivery.lastHandlingEvent()
-                                           .get()
-                                           .handlingEventType()
-                                           .get() == HandlingEventType.CUSTOMS;
-                String customsLabel = delivery.transportStatus().get().name() + ( inCustoms ? " (CUSTOMS)" : "" );
-                item.add( new Label( "transportStatus", customsLabel ) );
-
-                IModel directed = new Model<String>( delivery.isMisdirected().get() ? "Misdirected" : "On track" );
-                item.add( new Label( "deliveryStatus", directed ).add( new ErrorColor( delivery.isMisdirected()
-                                                                                           .get() ) ) );
-            }
-        } );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/ChangeDestinationPage.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/ChangeDestinationPage.java
deleted file mode 100644
index 95b34ce..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/ChangeDestinationPage.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.web.booking;
-
-import java.util.List;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.markup.html.form.AjaxFallbackButton;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.markup.html.panel.ComponentFeedbackPanel;
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.CommonQueries;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.dto.CargoDTO;
-import org.qi4j.sample.dcicargo.sample_a.context.shipping.booking.BookNewCargo;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.form.AbstractForm;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.form.SelectorInForm;
-
-/**
- * Change destination of Cargo
- */
-public class ChangeDestinationPage extends BookingBasePage
-{
-    public ChangeDestinationPage( PageParameters parameters )
-    {
-        String trackingId = parameters.get( 0 ).toString();
-        add( new Label( "trackingId", trackingId ) );
-        add( new CargoEditForm( trackingId ) );
-    }
-
-    private class CargoEditForm extends AbstractForm<Void>
-    {
-        private String trackingId; // Set by Wicket property resolver
-        private String origin, destination, oldDestination;
-
-        public CargoEditForm( final String trackingId )
-        {
-            CommonQueries fetch = new CommonQueries();
-            CargoDTO cargo = fetch.cargo( trackingId ).getObject();
-            List<String> locations = fetch.unLocodes();
-
-            origin = cargo.origin().get().getCode();
-            oldDestination = destination = cargo.routeSpecification().get().destination().get().getCode();
-
-            final FeedbackPanel feedback = new FeedbackPanel( "usecaseFeedback" );
-            final SelectorInForm destinationSelector = new SelectorInForm(
-                "destination", "Destination", locations, this, "origin" );
-            final ComponentFeedbackPanel destinationFeedback = new ComponentFeedbackPanel(
-                "destinationFeedback", destinationSelector.setRequired( true ) );
-
-            add( feedback.setOutputMarkupId( true ) );
-            add( new Label( "origin", origin ) );
-            add( new Label( "destination", destination ) );
-            add( destinationFeedback.setOutputMarkupId( true ) );
-            add( destinationSelector );
-            add( new AjaxFallbackButton( "submit", this )
-            {
-                @Override
-                protected void onSubmit( AjaxRequestTarget target, Form<?> form )
-                {
-                    try
-                    {
-                        if( oldDestination.equals( destination ) )
-                        {
-                            throw new IllegalArgumentException( "Please select a new destination." );
-                        }
-
-                        // Perform use case
-                        new BookNewCargo( trackingId ).changeDestination( destination );
-
-                        // Show updated cargo
-                        setResponsePage( CargoDetailsPage.class, new PageParameters().set( 0, trackingId ) );
-                    }
-                    catch( Exception e )
-                    {
-                        logger.warn( "Problem changing destination of cargo " + trackingId + ": " + e.getMessage() );
-                        feedback.error( e.getMessage() );
-                        target.add( feedback );
-                    }
-                }
-
-                @Override
-                protected void onError( final AjaxRequestTarget target, Form<?> form )
-                {
-                    target.add( destinationFeedback );
-                    target.focusComponent( destinationSelector );
-                }
-            } );
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/RouteCargoPage.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/RouteCargoPage.java
deleted file mode 100644
index 3df6099..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/RouteCargoPage.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.web.booking;
-
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.BookingQueries;
-import org.qi4j.sample.dcicargo.sample_a.context.support.FoundNoRoutesException;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
-
-/**
- * Re-route page - presents a list of possible routes a cargo can take that the user can choose from.
- *
- * Each route candidate is presented by a {@link RoutePanel}.
- */
-public class RouteCargoPage extends BookingBasePage
-{
-    private FeedbackPanel feedback = new FeedbackPanel( "feedback" );
-
-    public RouteCargoPage( PageParameters parameters )
-    {
-        final String trackingId = parameters.get( 0 ).toString();
-
-        add( new Label( "trackingId", trackingId ) );
-
-        add( new FeedbackPanel( "feedback" ) );
-
-//        List<IModel<Itinerary>> routes = null;
-        try
-        {
-            add( new ListView<IModel<Itinerary>>( "routes", query( BookingQueries.class ).routeCandidates( trackingId ) )
-            {
-                @Override
-                protected void populateItem( ListItem<IModel<Itinerary>> item )
-                {
-                    item.add( new RoutePanel( "route", trackingId, item.getModelObject(), item.getIndex() + 1 ) );
-                }
-            } );
-        }
-        catch( FoundNoRoutesException e )
-        {
-            error( e.getMessage() );
-
-            add( new WebMarkupContainer( "routes" ).add( new Label( "route" ) ) );
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/RoutePanel.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/RoutePanel.java
deleted file mode 100644
index 83fd9bd..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/RoutePanel.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.web.booking;
-
-import java.util.Date;
-import java.util.List;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.markup.html.form.AjaxFallbackButton;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.LoadableDetachableModel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.qi4j.sample.dcicargo.sample_a.context.shipping.booking.BookNewCargo;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Leg;
-
-/**
- * Route Panel - shows a suggested route a Cargo can take.
- *
- * If the user chooses this candidate route, all route data (a value object) is attached by the BookNewCargo context
- * as an Itinerary to the Cargo. To see the result, the user is then redirected to the details page of the cargo.
- */
-public class RoutePanel extends Panel
-{
-    public RoutePanel( String id,
-                       final String trackingIdString,
-                       final IModel<Itinerary> candidateRouteModel,
-                       int index
-    )
-    {
-        super( id, candidateRouteModel );
-        Itinerary itinerary = candidateRouteModel.getObject();
-
-        IModel<String> header = Model.of( "Route candidate " + index + " - duration: " + itinerary.days() + " days." );
-        add( new Label( "routeHeader", header ) );
-
-        final FeedbackPanel routeFeedback = new FeedbackPanel( "routeFeedback" );
-        add( routeFeedback.setOutputMarkupId( true ) );
-
-        IModel<List<Leg>> legListModel = new LoadableDetachableModel<List<Leg>>()
-        {
-            @Override
-            protected List<Leg> load()
-            {
-                return candidateRouteModel.getObject().legs().get();
-            }
-        };
-
-        add( new ListView<Leg>( "legs", legListModel )
-        {
-            @Override
-            protected void populateItem( ListItem<Leg> item )
-            {
-                Leg leg = item.getModelObject();
-                item.add( new Label( "voyage", leg.voyage().get().toString() ),
-                          new Label( "loadLocation", leg.loadLocation().get().getCode() ),
-                          new Label( "loadTime", new Model<Date>( leg.loadTime().get() ) ),
-                          new Label( "unloadLocation", leg.unloadLocation().get().getCode() ),
-                          new Label( "unloadTime", new Model<Date>( leg.unloadTime().get() ) )
-                );
-            }
-        } );
-
-        Form form = new Form<Void>( "form" );
-        form.add( new AjaxFallbackButton( "assign", form )
-        {
-            @Override
-            protected void onSubmit( AjaxRequestTarget target, Form<?> form )
-            {
-                try
-                {
-                    // The candidate route is sent as the chosen Itinerary
-                    new BookNewCargo( trackingIdString, candidateRouteModel.getObject() ).assignCargoToRoute();
-                    setResponsePage( CargoDetailsPage.class, new PageParameters().set( 0, trackingIdString ) );
-                }
-                catch( Exception e )
-                {
-                    String msg = "Problem assigning this route to cargo: " + e.getMessage();
-                    routeFeedback.error( msg );
-                    target.add( routeFeedback );
-                }
-            }
-
-            @Override
-            protected void onError( final AjaxRequestTarget target, Form<?> form )
-            {
-                routeFeedback.error( "Unexpected error - all routes are expected to be valid." );
-                target.add( routeFeedback );
-            }
-        } );
-        add( form );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/handling/RegisterHandlingEventPage.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/handling/RegisterHandlingEventPage.java
deleted file mode 100644
index cd0a242..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/handling/RegisterHandlingEventPage.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.web.handling;
-
-import java.util.Date;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.markup.html.form.AjaxFallbackButton;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.model.StringResourceModel;
-import org.apache.wicket.util.value.ValueMap;
-import org.joda.time.LocalDate;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.CommonQueries;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.HandlingQueries;
-import org.qi4j.sample.dcicargo.sample_a.communication.web.BasePage;
-import org.qi4j.sample.dcicargo.sample_a.context.shipping.handling.RegisterHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.form.AbstractForm;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.form.DateTextFieldWithPicker;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.form.SelectorInForm;
-
-/**
- * Register Handling Events
- *
- * Interface used by various authorities to register handling events for cargos. This would be a
- * separate interface not coupled to the booking system, but for testing convenience it is integrated
- * with Booking and Tracking.
- *
- * Tip: try open the Event Registration window side-by-side to a Cargo details window for a specific cargo.
- * Then register events for that cargo and here and update the details window to see the progress. You can
- * also then in the details window see what event is expected next...
- */
-public class RegisterHandlingEventPage extends BasePage
-{
-    public RegisterHandlingEventPage()
-    {
-        super( "handling" ); // Selects the Event Registration tab
-        add( new RegisterHandlingEventForm() );
-    }
-
-    private final class RegisterHandlingEventForm extends AbstractForm<Void>
-    {
-        // Set by Wicket property resolvers:
-        private Date completion;
-        private String trackingId, unLocode, voyageNumber, eventType;
-
-        private String lastSubmittedData;
-
-        public RegisterHandlingEventForm()
-        {
-            final FeedbackPanel feedback = new FeedbackPanel( "feedback" );
-            add( feedback.setOutputMarkupId( true ) );
-
-            final DateTextFieldWithPicker completionDateInput = new DateTextFieldWithPicker( "completion", "Completion", this );
-            completionDateInput.earliestDate( new LocalDate() );
-
-            HandlingQueries fetch = new HandlingQueries();
-            add( completionDateInput.setLabel( Model.of( "Completion" ) ) );
-            add( new SelectorInForm( "trackingId", "Tracking Id", fetch.cargoIds(), this ).setRequired( true ) );
-            add( new SelectorInForm( "eventType", "Event Type", fetch.eventTypes(), this ).setRequired( true ) );
-            add( new SelectorInForm( "unLocode", "Location", new CommonQueries().unLocodes(), this ).setRequired( true ) );
-            add( new SelectorInForm( "voyageNumber", "Voyage number", fetch.voyages(), this ) );
-
-            add( new AjaxFallbackButton( "register", this )
-            {
-                @Override
-                protected void onSubmit( AjaxRequestTarget target, Form<?> form )
-                {
-                    try
-                    {
-                        // We want to allow making multiple _unique_ handling event registrations
-                        if( sameDataIsSubmitted() )
-                        {
-                            throw new Exception( "Can't re-submit the same data." );
-                        }
-
-                        // Perform use case
-                        new RegisterHandlingEvent(
-                            new Date(), completion, trackingId, eventType, unLocode, voyageNumber ).register();
-
-                        // We could redirect to Details, but it's more fun to update details in a separate
-                        // window to follow the successive handling event registrations you make...
-//                        setResponsePage( CargoDetails.class, new PageParameters().set( 0, trackingId ) );
-
-                        ValueMap map = new ValueMap();
-                        map.put( "type", eventType );
-                        map.put( "location", unLocode );
-                        if( voyageNumber != null )
-                        {
-                            map.put( "voyage", voyageNumber );
-                        }
-                        String msg = new StringResourceModel( "handlingEvent.${type}", this, new Model<ValueMap>( map ) )
-                            .getObject();
-
-                        feedback.info( "Registered handling event for cargo '" + trackingId + "': " + msg );
-                        target.add( feedback );
-                    }
-                    catch( Exception e )
-                    {
-                        logger.warn( "Problem registering handling event: " + e.getMessage() );
-                        feedback.error( e.getMessage() );
-                        target.add( feedback );
-                    }
-                }
-
-                @Override
-                protected void onError( final AjaxRequestTarget target, Form<?> form )
-                {
-                    target.add( feedback );
-                    focusFirstError( target );
-                }
-            } );
-        }
-
-        private boolean sameDataIsSubmitted()
-        {
-            String submittedData = completion.toString() + trackingId + unLocode + voyageNumber + eventType;
-
-            if( submittedData.equals( lastSubmittedData ) )
-            {
-                return true;
-            }
-
-            // Valid new data submitted
-            lastSubmittedData = submittedData;
-
-            return false;
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/HandlingHistoryPanel.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/HandlingHistoryPanel.java
deleted file mode 100644
index 85e01f7..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/HandlingHistoryPanel.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.web.tracking;
-
-import java.util.Date;
-import java.util.List;
-import org.apache.wicket.behavior.AttributeAppender;
-import org.apache.wicket.devutils.stateless.StatelessComponent;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.model.StringResourceModel;
-import org.apache.wicket.util.value.ValueMap;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.TrackingQueries;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.dto.CargoDTO;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.dto.HandlingEventDTO;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.color.ErrorColor;
-
-/**
- * Handling history - a table list of handling events
- *
- * A tracking id string is passed in to retrieve all events matching that cargo.
- */
-@StatelessComponent
-public class HandlingHistoryPanel extends Panel
-{
-    public HandlingHistoryPanel( String id, final IModel<CargoDTO> cargoModel, String trackingId )
-    {
-        super( id );
-
-        IModel<List<HandlingEventDTO>> handlingEventsModel = new TrackingQueries().events( trackingId );
-
-        add( new ListView<HandlingEventDTO>( "handlingEvents", handlingEventsModel )
-        {
-            @Override
-            protected void populateItem( ListItem<HandlingEventDTO> item )
-            {
-                HandlingEventDTO event = item.getModelObject();
-                Boolean isLast = item.getIndex() == getList().size() - 1;
-                Boolean isMisdirected = cargoModel.getObject().delivery().get().isMisdirected().get();
-
-                // Status icon
-                IModel iconName = Model.of( isLast && isMisdirected ? "cross.png" : "tick.png" );
-                item.add( new WebMarkupContainer( "onTrackIcon" ).add( new AttributeAppender( "src", iconName, "" ) ) );
-
-                // Date
-                item.add( new Label( "completion", new Model<Date>( event.completionTime().get() ) ) );
-
-                // Event description (data substitution in strings from HandlingHistoryPanel.properties)
-                ValueMap map = new ValueMap();
-                map.put( "type", event.handlingEventType().get().name() );
-                map.put( "location", event.location().get().getString() );
-                if( event.voyage().get() != null )
-                {
-                    map.put( "voyage", event.voyage().get().voyageNumber().get().number().get() );
-                }
-                IModel text = new StringResourceModel( "handlingEvent.${type}", this, new Model<ValueMap>( map ) );
-                item.add( new Label( "event", text )
-                              .add( new ErrorColor( isLast && isMisdirected ) )
-                              .setEscapeModelStrings( false ) );
-            }
-        } );
-    }
-}
-
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/NextHandlingEventPanel.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/NextHandlingEventPanel.java
deleted file mode 100644
index 2f0d887..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/NextHandlingEventPanel.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.web.tracking;
-
-import java.text.SimpleDateFormat;
-import org.apache.wicket.AttributeModifier;
-import org.apache.wicket.devutils.stateless.StatelessComponent;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.model.StringResourceModel;
-import org.apache.wicket.util.value.ValueMap;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.dto.CargoDTO;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.ExpectedHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-
-/**
- * Next expected handling event
- *
- * Quite some logic to render 1 line of information!
- */
-@StatelessComponent
-public class NextHandlingEventPanel extends Panel
-{
-    public NextHandlingEventPanel( String id, IModel<CargoDTO> cargoModel )
-    {
-        super( id );
-
-        ValueMap map = new ValueMap();
-        Label label = new Label( "text", new StringResourceModel(
-            "expectedEvent.${expectedEvent}", this, new Model<ValueMap>( map ) ) );
-        add( label );
-
-        CargoDTO cargo = cargoModel.getObject();
-        Location destination = cargo.routeSpecification().get().destination().get();
-
-        if( cargo.itinerary().get() == null )
-        {
-            map.put( "expectedEvent", "ROUTE" );
-            return;
-        }
-
-        HandlingEvent previousEvent = cargo.delivery().get().lastHandlingEvent().get();
-        if( previousEvent == null )
-        {
-            map.put( "expectedEvent", "RECEIVE" );
-            map.put( "location", cargo.routeSpecification().get().origin().get().getString() );
-            return;
-        }
-
-        Location lastLocation = previousEvent.location().get();
-        if( previousEvent.handlingEventType().get() == HandlingEventType.CLAIM && lastLocation == destination )
-        {
-            map.put( "expectedEvent", "END_OF_CYCLE" );
-            map.put( "location", destination.getString() );
-            label.add( new AttributeModifier( "class", "correctColor" ) );
-            return;
-        }
-
-        ExpectedHandlingEvent nextEvent = cargo.delivery().get().nextExpectedHandlingEvent().get();
-        if( nextEvent == null )
-        {
-            map.put( "expectedEvent", "UNKNOWN" );
-            label.add( new AttributeModifier( "class", "errorColor" ) );
-            return;
-        }
-
-        map.put( "expectedEvent", nextEvent.handlingEventType().get().name() );
-        map.put( "location", nextEvent.location().get().getString() );
-
-        if( nextEvent.time() != null )
-        {
-            map.put( "time", new SimpleDateFormat( "yyyy-MM-dd" ).format( nextEvent.time().get() ) );
-        }
-
-        if( nextEvent.voyage().get() != null )
-        {
-            map.put( "voyage", nextEvent.voyage().get().voyageNumber().get().number().get() );
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/TrackCargoPage.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/TrackCargoPage.java
deleted file mode 100644
index a8b4bcc..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/TrackCargoPage.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.communication.web.tracking;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.List;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
-import org.apache.wicket.ajax.markup.html.form.AjaxFallbackButton;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.markup.html.form.TextField;
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
-import org.apache.wicket.markup.html.panel.Fragment;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.model.StringResourceModel;
-import org.apache.wicket.util.value.ValueMap;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.CommonQueries;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.TrackingQueries;
-import org.qi4j.sample.dcicargo.sample_a.communication.query.dto.CargoDTO;
-import org.qi4j.sample.dcicargo.sample_a.communication.web.BasePage;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.form.AbstractForm;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.form.SelectorInForm;
-
-/**
- * Track a cargo
- *
- * For convenience during testing, routed (non-received) cargos can be chosen from the dropdown list.
- */
-public class TrackCargoPage extends BasePage
-{
-    public TrackCargoPage()
-    {
-        super( "tracking" ); // Selects the Tracking tab
-        add( new TrackingForm() );
-    }
-
-    private final class TrackingForm extends AbstractForm<Void>
-    {
-        private String trackingId;
-        private String selectedTrackingId; // Set by Wicket property resolver
-
-        private TextField<String> trackingIdInput;
-        private SelectorInForm selectedTrackingIdSelector;
-
-        private FeedbackPanel feedback = new FeedbackPanel( "feedback" );
-        private Fragment statusFragment = new Fragment( "status", "statusFragment", new WebMarkupContainer( "mock" ) );
-
-        private TrackingForm()
-        {
-            // Manual input
-            trackingIdInput = new TextField<String>( "trackingId", new PropertyModel<String>( this, "trackingId" ) );
-            add( trackingIdInput.setRequired( true ).setOutputMarkupId( true ) );
-
-            // Submit button
-            add( new AjaxFallbackButton( "track", this )
-            {
-                @Override
-                protected void onSubmit( AjaxRequestTarget target, Form<?> form )
-                {
-                    updateStatusFragment( target );
-                }
-
-                @Override
-                protected void onError( final AjaxRequestTarget target, Form<?> form )
-                {
-                    target.add( feedback, trackingIdInput, selectedTrackingIdSelector, statusFragment.setVisible( false ) );
-                }
-            } );
-
-            // Drop down selector (for convenience when testing)
-            List<String> cargoIds = new TrackingQueries().routedCargos();
-            add( selectedTrackingIdSelector = new SelectorInForm(
-                "selectedTrackingId", "Selected Tracking id", cargoIds, this ) );
-            selectedTrackingIdSelector.add( new AjaxFormComponentUpdatingBehavior( "onchange" )
-            {
-                @Override
-                protected void onUpdate( AjaxRequestTarget target )
-                {
-                    trackingId = selectedTrackingId;
-                    updateStatusFragment( target );
-                }
-            } );
-
-            add( feedback.setOutputMarkupId( true ) );
-            add( statusFragment.setOutputMarkupId( true ).setOutputMarkupPlaceholderTag( true ).setVisible( false ) );
-        }
-
-        private void updateStatusFragment( final AjaxRequestTarget target )
-        {
-            try
-            {
-                IModel<CargoDTO> cargoModel = new CommonQueries().cargo( trackingId );
-                statusFragment = (Fragment) statusFragment.replaceWith( new StatusFragment( cargoModel, false ) );
-                target.add( feedback, trackingIdInput, selectedTrackingIdSelector, statusFragment.setVisible( true ) );
-            }
-            catch( NoSuchEntityException e )
-            {
-                e.printStackTrace();
-                error( "Cargo '" + trackingId + "' wasn't found in the system. Please check the tracking number." );
-                target.add( feedback, trackingIdInput, selectedTrackingIdSelector, statusFragment.setVisible( false ) );
-            }
-            catch( Exception e )
-            {
-                e.printStackTrace();
-                error( "Problem retrieving status for cargo '" + trackingId + "': " + e.getMessage() );
-                target.add( feedback, trackingIdInput, selectedTrackingIdSelector, statusFragment.setVisible( false ) );
-            }
-        }
-
-        private class StatusFragment extends Fragment
-        {
-            public StatusFragment( IModel<CargoDTO> cargoModel, Boolean visible )
-            {
-                super( "status", "statusFragment", TrackingForm.this );
-                setVisible( visible );
-
-                CargoDTO cargo = cargoModel.getObject();
-
-                // Status ----------------------------------------------------------------------
-                ValueMap map = new ValueMap();
-                map.put( "status", cargo.delivery().get().transportStatus().get().name() );
-                map.put( "trackingId", trackingId );
-                HandlingEvent lastEvent = cargo.delivery().get().lastHandlingEvent().get();
-                if( lastEvent != null )
-                {
-                    String voyageString = lastEvent.voyage().get() != null ?
-                                          lastEvent.voyage()
-                                              .get()
-                                              .voyageNumber()
-                                              .get()
-                                              .number()
-                                              .get() : "UNKNOWN_VOYAGE";
-                    map.put( "voyage", voyageString );
-                    map.put( "location", lastEvent.location().get().getString() );
-                }
-                else
-                {
-                    map.put( "voyage", "UNKNOWN_VOYAGE" );
-                    map.put( "location", cargo.origin().get().getString() );
-                }
-                add( new Label( "transportStatus", new StringResourceModel(
-                    "transportStatus.${status}", this, new Model<ValueMap>( map ) ) ) );
-
-                // ETA ----------------------------------------------------------------------
-                String destination = cargo.routeSpecification().get().destination().get().getString();
-                Date eta = cargo.delivery().get().eta().get();
-                String etaString = eta == null ? "?" : new SimpleDateFormat( "yyyy-MM-dd" ).format( eta );
-                add( new Label( "eta", new StringResourceModel(
-                    "eta", this, null, Model.of( destination ), Model.of( etaString ) ) ) );
-
-                // Warning/Notifier ----------------------------------------------------------------------
-                add( new WebMarkupContainer( "isMisdirected" ).setVisible( cargo.delivery()
-                                                                               .get()
-                                                                               .isMisdirected()
-                                                                               .get() ) );
-                add( new WebMarkupContainer( "isClaimed" ).setVisible(
-                    !cargo.delivery().get().isMisdirected().get()
-                    && cargo.delivery().get().isUnloadedAtDestination().get()
-                    && lastEvent != null
-                    && lastEvent.handlingEventType().get() == HandlingEventType.CLAIM
-                ) );
-
-                // Handling history ----------------------------------------------------------------------
-                if( cargo.delivery().get().lastHandlingEvent().get() == null )
-                {
-                    add( new Label( "handlingHistoryPanel" ) );
-                }
-                else
-                {
-                    add( new HandlingHistoryPanel( "handlingHistoryPanel", cargoModel, trackingId ) );
-                }
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/CargoRoleMap.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/CargoRoleMap.java
deleted file mode 100644
index 3bb7359..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/CargoRoleMap.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.rolemap;
-
-import org.qi4j.sample.dcicargo.sample_a.context.shipping.booking.BookNewCargo;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.CargoEntity;
-
-/**
- * Cargo Role Map
- */
-public interface CargoRoleMap
-    extends CargoEntity,
-            BookNewCargo.RoutingFacadeRole
-{
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/CargosRoleMap.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/CargosRoleMap.java
deleted file mode 100644
index 5fa9bfa..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/CargosRoleMap.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.rolemap;
-
-import org.qi4j.sample.dcicargo.sample_a.context.shipping.booking.BookNewCargo;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.CargosEntity;
-
-/**
- * Cargos Role Map
- */
-public interface CargosRoleMap
-    extends CargosEntity,
-            BookNewCargo.CargoFactoryRole
-{
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/HandlingEventRoleMap.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/HandlingEventRoleMap.java
deleted file mode 100644
index f736f96..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/HandlingEventRoleMap.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.rolemap;
-
-import org.qi4j.sample.dcicargo.sample_a.context.shipping.booking.BuildDeliverySnapshot;
-import org.qi4j.sample.dcicargo.sample_a.context.shipping.handling.InspectCargo;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.HandlingEventEntity;
-
-/**
- * Handling Event Role Map
- */
-public interface HandlingEventRoleMap
-    extends HandlingEventEntity,
-            BuildDeliverySnapshot.HandlingEventRole,
-            InspectCargo.CargoInspectorRole
-{
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/HandlingEventsRoleMap.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/HandlingEventsRoleMap.java
deleted file mode 100644
index a713641..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/HandlingEventsRoleMap.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.rolemap;
-
-import org.qi4j.sample.dcicargo.sample_a.context.shipping.handling.RegisterHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.HandlingEventsEntity;
-
-/**
- * Handling Events Role Map
- */
-public interface HandlingEventsRoleMap
-    extends HandlingEventsEntity,
-            RegisterHandlingEvent.HandlingEventFactoryRole
-{
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/ItineraryRoleMap.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/ItineraryRoleMap.java
deleted file mode 100644
index cd9b8ef..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/ItineraryRoleMap.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.rolemap;
-
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.sample.dcicargo.sample_a.context.shipping.booking.BuildDeliverySnapshot;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
-
-/**
- * Itinerary Role Map
- *
- * Note that this is a Value Composite (and not an entity) capable of playing different Roles.
- */
-public interface ItineraryRoleMap
-    extends ValueComposite,
-            Itinerary,
-            BuildDeliverySnapshot.ItineraryRole
-{
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/RouteSpecificationRoleMap.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/RouteSpecificationRoleMap.java
deleted file mode 100644
index 5444730..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/rolemap/RouteSpecificationRoleMap.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.rolemap;
-
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.sample.dcicargo.sample_a.context.shipping.booking.BuildDeliverySnapshot;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.RouteSpecification;
-
-/**
- * Route Specification Role Map
- *
- * Note that this is a Value Composite (and not an entity) capable of playing different Roles.
- */
-public interface RouteSpecificationRoleMap
-    extends ValueComposite,
-            RouteSpecification,
-            BuildDeliverySnapshot.FactoryRole
-{
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BookNewCargo.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BookNewCargo.java
deleted file mode 100644
index bf86b64..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BookNewCargo.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.shipping.booking;
-
-import java.util.Date;
-import java.util.List;
-import org.joda.time.DateMidnight;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.sample.dcicargo.sample_a.context.support.FoundNoRoutesException;
-import org.qi4j.sample.dcicargo.sample_a.context.support.RoutingService;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.CargoEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.CargosEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.LocationEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargos;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.TrackingId;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.dci.RoleMixin;
-
-/**
- * Book New Cargo use case
- */
-public class BookNewCargo extends Context
-{
-    // ROLES ---------------------------------------------------------------------
-
-    // Methodful Roles
-    private CargoFactoryRole cargoFactory;
-    private RoutingFacadeRole routingFacade;
-
-    // Methodless Roles
-    private Location origin;
-    private Location destination;
-    private Date arrivalDeadline;
-    private Itinerary itinerary;
-
-    // CONTEXT CONSTRUCTORS ------------------------------------------------------
-
-    public BookNewCargo( Cargos cargos,
-                         Location origin,
-                         Location destination,
-                         Date arrivalDeadline
-    )
-        throws Exception
-    {
-        cargoFactory = rolePlayer( CargoFactoryRole.class, cargos );
-        this.origin = origin;
-        this.destination = destination;
-        this.arrivalDeadline = arrivalDeadline;
-    }
-
-    public BookNewCargo( Cargo cargo )
-    {
-        routingFacade = rolePlayer( RoutingFacadeRole.class, cargo );
-    }
-
-    public BookNewCargo( Cargo cargo, Itinerary itinerary )
-    {
-        routingFacade = rolePlayer( RoutingFacadeRole.class, cargo );
-        this.itinerary = itinerary;
-    }
-
-    // Constructor proxies for communication layer
-
-    public BookNewCargo( String originId, String destinationId, Date deadline )
-        throws Exception
-    {
-        this( loadEntity( CargosEntity.class, CargosEntity.CARGOS_ID ),
-              loadEntity( Location.class, originId ),
-              loadEntity( Location.class, destinationId ),
-              deadline );
-    }
-
-    public BookNewCargo( String trackingIdString )
-    {
-        this( loadEntity( CargoEntity.class, trackingIdString ) );
-    }
-
-    public BookNewCargo( String trackingIdString, Itinerary itinerary )
-    {
-        this( loadEntity( Cargo.class, trackingIdString ), itinerary );
-    }
-
-    // INTERACTIONS --------------------------------------------------------------
-
-    public TrackingId book()
-    {
-        return cargoFactory.createCargo( null );
-    }
-
-    public TrackingId createCargo( String trackingIdString )
-    {
-        return cargoFactory.createCargo( trackingIdString );
-    }
-
-    public void changeDestination( String destination )
-    {
-        routingFacade.changeDestination( loadEntity( LocationEntity.class, destination ) );
-    }
-
-    public List<Itinerary> routeCandidates()
-        throws FoundNoRoutesException
-    {
-        return routingFacade.routeCandidates();
-    }
-
-    public void assignCargoToRoute()
-    {
-        routingFacade.assignCargoToRoute();
-    }
-
-    // METHODFUL ROLE IMPLEMENTATIONS --------------------------------------------
-
-    @Mixins( CargoFactoryRole.Mixin.class )
-    public interface CargoFactoryRole
-    {
-        void setContext( BookNewCargo context );
-
-        TrackingId createCargo( @Optional String trackingIdString );
-
-        class Mixin
-            extends RoleMixin<BookNewCargo>
-            implements CargoFactoryRole
-        {
-            @This
-            Cargos cargos;
-
-            public TrackingId createCargo( String trackingIdString )
-            {
-                // New route specification
-                RouteSpecification routeSpec = context.buildRouteSpecification(
-                    vbf, context.origin, context.destination, context.arrivalDeadline );
-
-                // Build delivery snapshot from route specification
-                Delivery delivery = new BuildDeliverySnapshot( routeSpec ).get();
-
-                // Create cargo
-                Cargo cargo = cargos.createCargo( routeSpec, delivery, trackingIdString );
-
-                return cargo.trackingId().get();
-            }
-        }
-    }
-
-    @Mixins( RoutingFacadeRole.Mixin.class )
-    public interface RoutingFacadeRole
-    {
-        void setContext( BookNewCargo context );
-
-        List<Itinerary> routeCandidates()
-            throws FoundNoRoutesException;
-
-        void assignCargoToRoute();
-
-        void changeDestination( Location destination );
-
-        class Mixin
-            extends RoleMixin<BookNewCargo>
-            implements RoutingFacadeRole
-        {
-            @This
-            Cargo cargo;
-
-            @Service
-            RoutingService routingService;
-
-            // Use case step 3 - system calculates possible routes
-            public List<Itinerary> routeCandidates()
-                throws FoundNoRoutesException  // Deviation 3a
-            {
-                return routingService.fetchRoutesForSpecification( cargo.routeSpecification().get() );
-            }
-
-            public void assignCargoToRoute()
-            {
-                cargo.itinerary().set( context.itinerary );
-
-                if( cargo.delivery().get().lastHandlingEvent().get() != null )
-                {
-                    // We treat subsequent route assignments as reroutes of misdirected cargo
-                    cargo.delivery().get().lastHandlingEvent().get().wasUnexpected().set( true );
-                }
-
-                // Build delivery snapshot with updated itinerary
-                cargo.delivery().set( new BuildDeliverySnapshot( cargo ).get() );
-            }
-
-            public void changeDestination( Location newDestination )
-            {
-                Location currentOrigin = cargo.routeSpecification().get().origin().get();
-                Date currentDeadline = cargo.routeSpecification().get().arrivalDeadline().get();
-
-                RouteSpecification newRouteSpecification =
-                    context.buildRouteSpecification( vbf, currentOrigin, newDestination, currentDeadline );
-
-                cargo.routeSpecification().set( newRouteSpecification );
-
-                // Build new delivery snapshot with updated route specification
-                cargo.delivery().set( new BuildDeliverySnapshot( cargo ).get() );
-            }
-        }
-    }
-
-    public RouteSpecification buildRouteSpecification(
-        ValueBuilderFactory vbf, Location origin, Location destination, Date deadline
-    )
-    {
-        if( origin == destination )
-        {
-            throw new RouteException( "Origin location can't be same as destination location." );
-        }
-
-        if( deadline == null )
-        {
-            throw new RouteException( "Arrival deadline cannot be null." );
-        }
-
-        Date endOfToday = new DateMidnight().plusDays( 1 ).toDate();
-        if( deadline.before( endOfToday ) )
-        {
-            throw new RouteException( "Arrival deadline is in the past or Today." +
-                                        "\nDeadline           " + deadline +
-                                        "\nToday (midnight)   " + endOfToday );
-        }
-
-        ValueBuilder<RouteSpecification> routeSpec = vbf.newValueBuilder( RouteSpecification.class );
-        routeSpec.prototype().origin().set( origin );
-        routeSpec.prototype().destination().set( destination );
-        routeSpec.prototype().arrivalDeadline().set( deadline );
-        return routeSpec.newInstance();
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BuildDeliverySnapshot.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BuildDeliverySnapshot.java
deleted file mode 100644
index 54741b6..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BuildDeliverySnapshot.java
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.shipping.booking;
-
-import java.util.Date;
-import java.util.Iterator;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.ExpectedHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.RoutingStatus;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.TransportStatus;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Leg;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.dci.RoleMixin;
-
-/**
- * Build Delivery Snapshot use case.
- *
- * This is a subfunction level use case (see Cockurn 2001) supporting user-goal level use cases
- * like {@link BookNewCargo} by returning a Delivery snapshot Value object.
- *
- * A Delivery snapshot describes all we know about the current shipping status of a Cargo. It's the
- * heart of the application domain knowledge.
- *
- * The Delivery snapshot is derived from one of the 3 overall stages a Cargo shipping can be in:
- * 1) Cargo is being created  (Route Specification is known)
- * 2) Cargo has been routed   (Route Specification + Itinerary is known)
- * 3) Cargo is in transit     (Route Specification + Itinerary + last Handling Event is known)
- *
- * Code is organized along the contours of the process flow of cargo shipping instead of the data
- * structures. This makes it easier to reason about a certain step in the shipping process (use case)
- * according to the intuitive understanding of the shipping domain.
- *
- * @see RouteSpecification  plays a (methodful) Role of a factory that coordinates the Delivery build.
- * @see HandlingEvent       plays a (methodful) Role that coordinates deriving data from the last Handling Event.
- * @see Itinerary           plays a (methodful) Role supporting the other two roles with Itinerary calculations.
- */
-public class BuildDeliverySnapshot extends Context
-{
-    // ROLES ---------------------------------------------------------------------
-
-    private FactoryRole factory;
-    private ItineraryRole itinerary;
-    private HandlingEventRole handlingEvent;
-
-    private Delivery newDeliverySnapshot;
-
-    // CONTEXT CONSTRUCTORS ------------------------------------------------------
-
-    public BuildDeliverySnapshot( RouteSpecification routeSpecification )
-    {
-        // Deviation 2a
-        if( routeSpecification.origin().get() == routeSpecification.destination().get() )
-        {
-            throw new RouteException( "Route specification is invalid. Origin equals destination." );
-        }
-
-        // Deviation 2b
-        if( routeSpecification.arrivalDeadline().get().before( new Date() ) )
-        {
-            throw new RouteException( "Arrival deadline is in the past or Today." +
-                                        "\nDeadline " + routeSpecification.arrivalDeadline().get() +
-                                        "\nToday    " + new Date() );
-        }
-
-        factory = rolePlayer( FactoryRole.class, routeSpecification );
-        itinerary = null;
-        handlingEvent = null;
-    }
-
-    public BuildDeliverySnapshot( Cargo cargo )
-    {
-        factory = rolePlayer( FactoryRole.class, cargo.routeSpecification().get() );
-        itinerary = rolePlayer( ItineraryRole.class, cargo.itinerary().get() );
-        handlingEvent = rolePlayer( HandlingEventRole.class, cargo.delivery().get().lastHandlingEvent().get() );
-    }
-
-    public BuildDeliverySnapshot( Cargo cargo, HandlingEvent registeredHandlingEvent )
-    {
-        factory = rolePlayer( FactoryRole.class, cargo.routeSpecification().get() );
-        itinerary = rolePlayer( ItineraryRole.class, cargo.itinerary().get() );
-        handlingEvent = rolePlayer( HandlingEventRole.class, registeredHandlingEvent );
-    }
-
-    // INTERACTIONS --------------------------------------------------------------
-
-    public Delivery get()
-    {
-        return factory.deriveDeliverySnapshot();
-    }
-
-    // METHODFUL ROLE IMPLEMENTATIONS --------------------------------------------
-
-    /**
-     * The FactoryRole coordinates the overall Delivery snapshot build.
-     *
-     * When the Cargo has a delivery history the FactoryRole delegates to the LastHandlingEventRole
-     * to derive data from the last HandlingEvent.
-     */
-    @Mixins( FactoryRole.Mixin.class )
-    public interface FactoryRole
-    {
-        void setContext( BuildDeliverySnapshot context );
-
-        Delivery deriveDeliverySnapshot();
-
-        class Mixin
-            extends RoleMixin<BuildDeliverySnapshot>
-            implements FactoryRole
-        {
-            @This
-            RouteSpecification routeSpecification;
-
-            ValueBuilder<Delivery> deliveryBuilder;
-
-            public Delivery deriveDeliverySnapshot()
-            {
-                /*
-               * Default values:
-               *
-               * isMisdirected = false
-               * nextExpectedHandlingEvent = null
-               * lastHandlingEvent = null
-               * lastKnownLocation = null
-               * currentVoyage = null
-               * eta = null
-               * isUnloadedAtDestination = false
-               *
-               * */
-
-                // Build delivery snapshot object
-                deliveryBuilder = vbf.newValueBuilder( Delivery.class );
-                context.newDeliverySnapshot = deliveryBuilder.prototype();
-                context.newDeliverySnapshot.timestamp().set( new Date() );
-
-                // Deviation 2c: Cargo is not routed yet
-                if( context.itinerary == null )
-                {
-                    return deriveWithRouteSpecification();
-                }
-
-                if( !routeSpecification.isSatisfiedBy( (Itinerary) context.itinerary ) )
-                {
-                    // Deviation 2d: Itinerary not satisfying
-                    context.newDeliverySnapshot.routingStatus().set( RoutingStatus.MISROUTED );
-                }
-                else
-                {
-                    // Step 2
-                    context.newDeliverySnapshot.routingStatus().set( RoutingStatus.ROUTED );
-                    context.newDeliverySnapshot.eta().set( context.itinerary.eta() );
-                }
-
-                // Deviation 3a: Cargo has no handling history yet
-                if( context.handlingEvent == null )
-                {
-                    return deriveWithItinerary();
-                }
-
-                // Step 4: Cargo has a handling history
-                context.handlingEvent.deriveWithHandlingEvent();
-
-                // Step 5: Return Delivery object
-                return deliveryBuilder.newInstance();
-            }
-
-            private Delivery deriveWithRouteSpecification()
-            {
-                // Deviation 2c
-                context.newDeliverySnapshot.routingStatus().set( RoutingStatus.NOT_ROUTED );
-                context.newDeliverySnapshot.transportStatus().set( TransportStatus.NOT_RECEIVED );
-                context.newDeliverySnapshot.nextExpectedHandlingEvent().set( buildExpectedReceiveEvent() );
-                return deliveryBuilder.newInstance();
-            }
-
-            private Delivery deriveWithItinerary()
-            {
-                context.newDeliverySnapshot.transportStatus().set( TransportStatus.NOT_RECEIVED );
-
-                // Deviation 3a.1.a
-                if( context.newDeliverySnapshot.routingStatus().get() == RoutingStatus.ROUTED )
-                {
-                    context.newDeliverySnapshot.nextExpectedHandlingEvent().set( buildExpectedReceiveEvent() );
-                }
-
-                return deliveryBuilder.newInstance();
-            }
-
-            private ExpectedHandlingEvent buildExpectedReceiveEvent()
-            {
-                ValueBuilder<ExpectedHandlingEvent> builder = vbf.newValueBuilder( ExpectedHandlingEvent.class );
-                builder.prototype().handlingEventType().set( HandlingEventType.RECEIVE );
-                builder.prototype().location().set( routeSpecification.origin().get() );
-                return builder.newInstance();
-            }
-        }
-    }
-
-    /**
-     * The HandlingEventRole derives data from the last Handling Event.
-     *
-     * This is where the core domain knowledge about the shipping flow is. Code is organized by the
-     * 6 different handling event types of a cargo:
-     * RECEIVE - LOAD - UNLOAD - CLAIM - CUSTOMS - (UNKNOWN)
-     *
-     * For each HandlingEventType we can reason about the status and what is expected next. This
-     * follows the real world shipping flow rather than data structures of the domain.
-     *
-     * The HandlingEventRole uses the ItineraryRole heavily to calculate values based on Itinerary data.
-     */
-    @Mixins( HandlingEventRole.Mixin.class )
-    public interface HandlingEventRole
-    {
-        void setContext( BuildDeliverySnapshot context );
-
-        void deriveWithHandlingEvent();
-
-        class Mixin
-            extends RoleMixin<BuildDeliverySnapshot>
-            implements HandlingEventRole
-        {
-            /*
-           * HandlingEvent can be from last Delivery snapshot (last expected HandlingEvent) or
-           * a new registered HandlingEvent.
-           * */
-            @This
-            HandlingEvent handlingEvent;
-
-            // Local convenience fields
-            Location lastKnownLocation;
-            Voyage currentVoyage;
-            Boolean cargoIsNotMisrouted;
-
-            // Flag for determining if we should wasUnexpected a former misdirected Handling Event after a reroute
-            Boolean cargoIsRerouted;
-
-            public void deriveWithHandlingEvent()
-            {
-                lastKnownLocation = handlingEvent.location().get();
-                currentVoyage = handlingEvent.voyage().get();
-                cargoIsNotMisrouted = context.newDeliverySnapshot.routingStatus().get() == RoutingStatus.ROUTED;
-
-                // Cargo has been rerouted when the last handling event is declared unexpected.
-                cargoIsRerouted = handlingEvent.wasUnexpected().get();
-
-                // Step 3
-                context.newDeliverySnapshot.lastHandlingEvent().set( handlingEvent );
-                context.newDeliverySnapshot.lastKnownLocation().set( lastKnownLocation );
-
-                // Step 4
-                switch( handlingEvent.handlingEventType().get() )
-                {
-                case RECEIVE:
-                    cargoReceived();        // Deviation 4a
-                    return;
-
-                case LOAD:
-                    cargoLoaded();          // Deviation 4b
-                    return;
-
-                case UNLOAD:
-                    cargoUnloaded();        // Deviation 4c
-                    return;
-
-                case CUSTOMS:
-                    cargoInCustoms();       // Deviation 4d
-                    return;
-
-                case CLAIM:
-                    cargoClaimed();         // Deviation 4e
-                    return;
-
-                default:
-                    unknownHandlingEvent(); // Deviation 4f
-                }
-            }
-
-            // Deviation 4a
-            private void cargoReceived()
-            {
-                context.newDeliverySnapshot.transportStatus().set( TransportStatus.IN_PORT );
-
-                if( !cargoIsRerouted && !context.itinerary.expectsOrigin( lastKnownLocation ) )
-                {
-                    context.newDeliverySnapshot.eta().set( null );
-                    context.newDeliverySnapshot.isMisdirected().set( true );
-                }
-                else if( cargoIsNotMisrouted )
-                {
-                    ExpectedHandlingEvent expectedEvent = context.itinerary.expectedEventAfterReceive();
-                    context.newDeliverySnapshot.nextExpectedHandlingEvent().set( expectedEvent );
-                }
-            }
-
-            // Deviation 4b
-            private void cargoLoaded()
-            {
-                context.newDeliverySnapshot.transportStatus().set( TransportStatus.ONBOARD_CARRIER );
-                context.newDeliverySnapshot.currentVoyage().set( currentVoyage );
-
-                if( cargoIsRerouted )
-                {
-                    // After a reroute following a load in an unexpected location, we expected the cargo to be
-                    // unloaded at the unload location of the first leg of the new itinerary.
-                    ExpectedHandlingEvent expectedEvent = context.itinerary
-                        .expectedEventAfterLoadAt( lastKnownLocation );
-                    context.newDeliverySnapshot.nextExpectedHandlingEvent().set( expectedEvent );
-                }
-                else if( !context.itinerary.expectsLoad( lastKnownLocation, currentVoyage ) )
-                {
-                    context.newDeliverySnapshot.eta().set( null );
-                    context.newDeliverySnapshot.isMisdirected().set( true );
-                }
-                else if( cargoIsNotMisrouted )
-                {
-                    ExpectedHandlingEvent expectedEvent = context.itinerary
-                        .expectedEventAfterLoadAt( lastKnownLocation );
-                    context.newDeliverySnapshot.nextExpectedHandlingEvent().set( expectedEvent );
-                }
-            }
-
-            // Deviation 4c
-            private void cargoUnloaded()
-            {
-                context.newDeliverySnapshot.transportStatus().set( TransportStatus.IN_PORT );
-
-                if( cargoIsRerouted )
-                {
-                    // After a reroute following an unload in an unexpected location, we expected the cargo
-                    // to be loaded onto a carrier at the first location of the new route specification.
-                    ExpectedHandlingEvent expectedEvent = context.itinerary.expectedEventAfterReceive();
-                    context.newDeliverySnapshot.nextExpectedHandlingEvent().set( expectedEvent );
-                }
-                else if( !context.itinerary.expectsUnload( lastKnownLocation, currentVoyage ) )
-                {
-                    context.newDeliverySnapshot.eta().set( null );
-                    context.newDeliverySnapshot.isMisdirected().set( true );
-                }
-                else if( cargoIsNotMisrouted )
-                {
-                    ExpectedHandlingEvent expectedEvent = context.itinerary
-                        .expectedEventAfterUnloadAt( lastKnownLocation );
-                    context.newDeliverySnapshot.nextExpectedHandlingEvent().set( expectedEvent );
-
-                    Location expectedDestination = ( (RouteSpecification) context.factory ).destination().get();
-                    context.newDeliverySnapshot
-                        .isUnloadedAtDestination()
-                        .set( lastKnownLocation.equals( expectedDestination ) );
-                }
-            }
-
-            // Deviation 4d
-            private void cargoInCustoms()
-            {
-                context.newDeliverySnapshot.transportStatus().set( TransportStatus.IN_PORT );
-
-                Location expectedDestination = ( (RouteSpecification) context.factory ).destination().get();
-                context.newDeliverySnapshot
-                    .isUnloadedAtDestination()
-                    .set( lastKnownLocation.equals( expectedDestination ) );
-            }
-
-            // Deviation 4e
-            private void cargoClaimed()
-            {
-                context.newDeliverySnapshot.transportStatus().set( TransportStatus.CLAIMED );
-
-                Location expectedDestination = ( (RouteSpecification) context.factory ).destination().get();
-                context.newDeliverySnapshot
-                    .isUnloadedAtDestination()
-                    .set( lastKnownLocation.equals( expectedDestination ) );
-
-                if( !context.itinerary.expectsDestination( lastKnownLocation ) )
-                {
-                    context.newDeliverySnapshot.eta().set( null );
-                    context.newDeliverySnapshot.isMisdirected().set( true );
-                }
-            }
-
-            // Deviation 4f
-            private void unknownHandlingEvent()
-            {
-                context.newDeliverySnapshot.transportStatus().set( TransportStatus.UNKNOWN );
-            }
-        }
-    }
-
-    /**
-     * The ItineraryRole supports the HandlingEventRole with calculated results derived from Itinerary Legs.
-     */
-    @Mixins( ItineraryRole.Mixin.class )
-    public interface ItineraryRole
-    {
-        void setContext( BuildDeliverySnapshot context );
-
-        Date eta();
-
-        boolean expectsOrigin( Location location );
-
-        boolean expectsLoad( Location location, Voyage voyage );
-
-        boolean expectsUnload( Location location, Voyage voyage );
-
-        boolean expectsDestination( Location location );
-
-        ExpectedHandlingEvent expectedEventAfterReceive();
-
-        ExpectedHandlingEvent expectedEventAfterLoadAt( Location lastLoadLocation );
-
-        ExpectedHandlingEvent expectedEventAfterUnloadAt( Location lastUnloadLocation );
-
-        class Mixin
-            extends RoleMixin<BuildDeliverySnapshot>
-            implements ItineraryRole
-        {
-            @This
-            Itinerary itinerary;
-
-            public Date eta()
-            {
-                return itinerary.lastLeg().unloadTime().get();
-            }
-
-            // Route expectations ----------------------------------------------------
-
-            public boolean expectsOrigin( Location location )
-            {
-                return itinerary.firstLeg().loadLocation().get().equals( location );
-            }
-
-            public boolean expectsLoad( Location location, Voyage voyage )
-            {
-                // One leg with same load location and voyage
-                for( Leg leg : itinerary.legs().get() )
-                {
-                    if( leg.loadLocation().get().equals( location ) && leg.voyage().get().equals( voyage ) )
-                    {
-                        return true;
-                    }
-                }
-                return false;
-            }
-
-            public boolean expectsUnload( Location location, Voyage voyage )
-            {
-                // One leg with same unload location and voyage
-                for( Leg leg : itinerary.legs().get() )
-                {
-                    if( leg.unloadLocation().get().equals( location ) && leg.voyage().get().equals( voyage ) )
-                    {
-                        return true;
-                    }
-                }
-                return false;
-            }
-
-            public boolean expectsDestination( Location location )
-            {
-                // Last leg destination matches
-                return ( itinerary.lastLeg().unloadLocation().get().equals( location ) );
-            }
-
-            // Next expected handling event ----------------------------------------------
-
-            public ExpectedHandlingEvent expectedEventAfterReceive()
-            {
-                // After RECEIVE, expect LOAD location and voyage of first itinerary leg
-                final Leg firstLeg = itinerary.legs().get().iterator().next();
-                return buildEvent( HandlingEventType.LOAD, firstLeg.loadLocation().get(), firstLeg.loadTime()
-                    .get(), firstLeg.voyage().get() );
-            }
-
-            public ExpectedHandlingEvent expectedEventAfterLoadAt( Location lastLoadLocation )
-            {
-                // After LOAD, expect UNLOAD location and voyage of same itinerary leg as LOAD
-                for( Leg leg : itinerary.legs().get() )
-                {
-                    if( leg.loadLocation().get().equals( lastLoadLocation ) )
-                    {
-                        return buildEvent( HandlingEventType.UNLOAD, leg.unloadLocation().get(), leg.unloadTime()
-                            .get(), leg.voyage().get() );
-                    }
-                }
-                return null;
-            }
-
-            public ExpectedHandlingEvent expectedEventAfterUnloadAt( Location lastUnloadLocation )
-            {
-                // After UNLOAD, expect LOAD location and voyage of following itinerary leg, or CLAIM if no more legs
-                for( Iterator<Leg> it = itinerary.legs().get().iterator(); it.hasNext(); )
-                {
-                    final Leg leg = it.next();
-                    if( leg.unloadLocation().get().equals( lastUnloadLocation ) )
-                    {
-                        // Cargo has a matching unload location in itinerary
-
-                        if( it.hasNext() )
-                        {
-                            // Cargo has not arrived yet (uncompleted legs in itinerary)
-                            // We expect it to be loaded onto some Carrier
-                            final Leg nextLeg = it.next();
-                            return buildEvent( HandlingEventType.LOAD, nextLeg.loadLocation().get(), nextLeg.loadTime()
-                                .get(), nextLeg.voyage().get() );
-                        }
-                        else
-                        {
-                            // Cargo has arrived (no more legs in itinerary)
-                            // We expect it to be claimed by the customer
-                            return buildEvent( HandlingEventType.CLAIM, leg.unloadLocation().get(), leg.unloadTime()
-                                .get(), null );
-                        }
-                    }
-                }
-
-                // Itinerary doesn't recognize last unload location
-                return null;
-            }
-
-            private ExpectedHandlingEvent buildEvent( HandlingEventType eventType,
-                                                      Location location,
-                                                      Date time,
-                                                      Voyage voyage
-            )
-            {
-                ValueBuilder<ExpectedHandlingEvent> builder = vbf.newValueBuilder( ExpectedHandlingEvent.class );
-                builder.prototype().handlingEventType().set( eventType );
-                builder.prototype().location().set( location );
-                builder.prototype().time().set( time );
-                builder.prototype().voyage().set( voyage );
-                return builder.newInstance();
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/RouteException.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/RouteException.java
deleted file mode 100644
index 3955794..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/RouteException.java
+++ /dev/null
@@ -1,27 +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.qi4j.sample.dcicargo.sample_a.context.shipping.booking;
-
-public class RouteException extends RuntimeException
-{
-    public RouteException( String message )
-    {
-        super(message);
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/InspectCargo.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/InspectCargo.java
deleted file mode 100644
index dfcd5e7..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/InspectCargo.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.shipping.handling;
-
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.sample.dcicargo.sample_a.context.shipping.booking.BuildDeliverySnapshot;
-import org.qi4j.sample.dcicargo.sample_a.context.support.ApplicationEvents;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.dci.RoleMixin;
-
-/**
- * The Inspect Cargo use case updates the delivery history of the cargo and
- * determines if the registered handling event was expected.
- */
-public class InspectCargo extends Context
-{
-    // ROLES ---------------------------------------------------------------------
-
-    private CargoInspectorRole cargoInspector;
-
-    private Cargo cargo;
-    private Delivery delivery;
-
-    // CONTEXT CONSTRUCTORS ------------------------------------------------------
-
-    public InspectCargo( HandlingEvent registeredHandlingEvent )
-    {
-        cargoInspector = rolePlayer( CargoInspectorRole.class, registeredHandlingEvent );
-        cargo = loadEntity( Cargo.class, registeredHandlingEvent.trackingId().get().id().get() );
-        delivery = cargo.delivery().get();
-    }
-
-    // INTERACTIONS --------------------------------------------------------------
-
-    public void inspect()
-    {
-        cargoInspector.inspect();
-    }
-
-    // METHODFUL ROLE IMPLEMENTATIONS --------------------------------------------
-
-    /**
-     * Cargo handling role.
-     */
-    @Mixins( CargoInspectorRole.Mixin.class )
-    public interface CargoInspectorRole
-    {
-        void setContext( InspectCargo context );
-
-        void inspect();
-
-        class Mixin
-            extends RoleMixin<InspectCargo>
-            implements CargoInspectorRole
-        {
-            @This
-            HandlingEvent registeredHandlingEvent;
-
-            @Service
-            ApplicationEvents applicationEvents;
-
-            public void inspect()
-            {
-                // Step 1: Update delivery history of cargo.
-                context.delivery = new BuildDeliverySnapshot( context.cargo, registeredHandlingEvent ).get();
-
-                // Step 2: Replace updated delivery snapshot of cargo
-                context.cargo.delivery().set( context.delivery );
-
-                // Deviation 3a: Publish that cargo was misdirected
-                if( context.delivery.isMisdirected().get() )
-                {
-                    applicationEvents.cargoWasMisdirected( context.cargo );
-                }
-
-                // Deviation 3b: Publish that cargo has arrived
-                if( context.delivery.isUnloadedAtDestination().get() )
-                {
-                    applicationEvents.cargoHasArrived( context.cargo );
-                }
-
-                // Step 4: Updated cargo is saved when UnitOfWork completes.
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/RegisterHandlingEvent.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/RegisterHandlingEvent.java
deleted file mode 100644
index 64665d7..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/RegisterHandlingEvent.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.shipping.handling;
-
-import java.util.Arrays;
-import java.util.Date;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.sample.dcicargo.sample_a.context.support.ApplicationEvents;
-import org.qi4j.sample.dcicargo.sample_a.context.support.RegisterHandlingEventAttemptDTO;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.HandlingEventsEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.TrackingId;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvents;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.dci.RoleMixin;
-
-import static org.qi4j.sample.dcicargo.sample_a.data.entity.HandlingEventsEntity.HANDLING_EVENTS_ID;
-
-/**
- * Register new handling event use case.
- *
- * The Cargo is updated synchronously in this implementation.
- */
-public class RegisterHandlingEvent extends Context
-{
-    // ROLES ---------------------------------------------------------------------
-
-    private HandlingEventFactoryRole handlingEventFactory;
-
-    private Date registrationTime;
-    private Date completionTime;
-    private String trackingIdString;
-    private String eventTypeString;
-    private String unLocodeString;
-    private String voyageNumberString;
-
-    // CONTEXT CONSTRUCTORS ------------------------------------------------------
-
-    public RegisterHandlingEvent( Date registrationTime,
-                                  Date completionTime,
-                                  String trackingIdString,
-                                  String eventTypeString,
-                                  String unLocodeString,
-                                  String voyageNumberString
-    )
-    {
-        handlingEventFactory = rolePlayer( HandlingEventFactoryRole.class, HandlingEventsEntity.class, HANDLING_EVENTS_ID );
-
-        this.registrationTime = registrationTime;
-        this.completionTime = completionTime;
-        this.trackingIdString = trackingIdString;
-        this.eventTypeString = eventTypeString;
-        this.unLocodeString = unLocodeString;
-        this.voyageNumberString = voyageNumberString;
-    }
-
-    // INTERACTIONS --------------------------------------------------------------
-
-    public void register()
-    {
-        handlingEventFactory.registerHandlingEvent();
-    }
-
-    // METHODFUL ROLE IMPLEMENTATIONS --------------------------------------------
-
-    @Mixins( HandlingEventFactoryRole.Mixin.class )
-    public interface HandlingEventFactoryRole
-    {
-        void setContext( RegisterHandlingEvent context );
-
-        void registerHandlingEvent();
-
-        class Mixin
-            extends RoleMixin<RegisterHandlingEvent>
-            implements HandlingEventFactoryRole
-        {
-            @Service
-            ApplicationEvents applicationEvents;
-
-            @This
-            HandlingEvents handlingEvents;
-
-            // Handling event properties
-            TrackingId trackingId;
-            HandlingEventType handlingEventType;
-            Location location;
-            Voyage voyage;
-
-            public void registerHandlingEvent()
-            {
-                RegisterHandlingEventAttemptDTO registrationAttempt = buildRegistrationAttempt();
-
-                // Step 1: Publish event stating that registration attempt has been received.
-                applicationEvents.receivedHandlingEventRegistrationAttempt( registrationAttempt );
-
-                HandlingEvent handlingEvent = null;
-                try
-                {
-                    // Step 2: Verify existing data
-                    verifyExistingData();
-
-                    // Step 3: Verify that received data can represent a valid handling event
-                    verifyValidData();
-
-                    // Step 4: Create and save handling event
-                    handlingEvent = handlingEvents.createHandlingEvent(
-                        context.registrationTime, context.completionTime, trackingId, handlingEventType, location, voyage );
-                }
-                catch( IllegalArgumentException e )
-                {
-                    // Deviation 2-5a: Publish event if registration is unsuccessful
-                    applicationEvents.unsuccessfulHandlingEventRegistration( registrationAttempt );
-                    throw e;
-                }
-
-                // Step 5: Inspect cargo
-                new InspectCargo( handlingEvent ).inspect();
-
-                // Step 6: Publish notification that cargo was successfully handled
-                applicationEvents.cargoWasHandled( handlingEvent );
-            }
-
-            private RegisterHandlingEventAttemptDTO buildRegistrationAttempt()
-            {
-                ValueBuilder<RegisterHandlingEventAttemptDTO> builder =
-                    vbf.newValueBuilder( RegisterHandlingEventAttemptDTO.class );
-                builder.prototype().registrationTime().set( context.registrationTime );
-                builder.prototype().completionTime().set( context.completionTime );
-                builder.prototype().trackingIdString().set( context.trackingIdString );
-                builder.prototype().eventTypeString().set( context.eventTypeString );
-                builder.prototype().unLocodeString().set( context.unLocodeString );
-                builder.prototype().voyageNumberString().set( context.voyageNumberString );
-                return builder.newInstance();
-            }
-
-            private void verifyExistingData()
-            {
-                if( context.registrationTime == null )
-                {
-                    throw new IllegalArgumentException( "Registration time was null. All parameters have to be passed." );
-                }
-                if( context.completionTime == null )
-                {
-                    throw new IllegalArgumentException( "Completion time was null. All parameters have to be passed." );
-                }
-
-                context.trackingIdString = getClean( "Tracking id", context.trackingIdString );
-                context.eventTypeString = getClean( "Event type", context.eventTypeString );
-                context.unLocodeString = getClean( "UnLocode", context.unLocodeString );
-
-                // Voyage is optional
-            }
-
-            private String getClean( String parameter, String value )
-            {
-                if( value == null )
-                {
-                    throw new IllegalArgumentException( parameter + " was null. All parameters have to be passed." );
-                }
-
-                if( value.trim().length() == 0 )
-                {
-                    throw new IllegalArgumentException( parameter + " cannot be empty." );
-                }
-
-                return value.trim();
-            }
-
-            private void verifyValidData()
-            {
-                // Deviation 3a
-                try
-                {
-                    handlingEventType = HandlingEventType.valueOf( context.eventTypeString );
-                }
-                catch( Exception e )
-                {
-                    throw new IllegalArgumentException(
-                        "'" + context.eventTypeString + "' is not a valid handling event type. Valid types are: "
-                        + Arrays.toString( HandlingEventType.values() ) );
-                }
-
-                // Verifications against data store
-                UnitOfWork uow = uowf.currentUnitOfWork();
-
-                // Deviation 3b
-                try
-                {
-                    // Will throw NoSuchEntityException if not found in store
-                    Cargo cargo = uow.get( Cargo.class, context.trackingIdString );
-                    trackingId = cargo.trackingId().get();
-
-                    // Deviation 3c
-                    if( cargo.itinerary().get() == null )
-                    {
-                        throw new IllegalArgumentException( "Can't create handling event for non-routed cargo '"
-                                                            + context.trackingIdString + "'." );
-                    }
-                }
-                catch( NoSuchEntityException e )
-                {
-                    throw new IllegalArgumentException( "Found no cargo with tracking id '" + context.trackingIdString + "'." );
-                }
-
-                // Deviation 3d
-                try
-                {
-                    location = uow.get( Location.class, context.unLocodeString );
-                }
-                catch( NoSuchEntityException e )
-                {
-                    throw new IllegalArgumentException( "Unknown location: " + context.unLocodeString );
-                }
-
-                // Deviation 3e
-                if( handlingEventType.requiresVoyage() )
-                {
-                    // Deviation 3e1a
-                    if( context.voyageNumberString == null )
-                    {
-                        throw new IllegalArgumentException( "Handling event " + handlingEventType.toString() +
-                                                            " requires a voyage. No voyage number submitted." );
-                    }
-
-                    // Deviation 3e1b
-                    try
-                    {
-                        voyage = uow.get( Voyage.class, context.voyageNumberString );
-                    }
-                    catch( NoSuchEntityException e )
-                    {
-                        throw new IllegalArgumentException(
-                            "Found no voyage with voyage number '" + context.voyageNumberString + "'." );
-                    }
-                }
-                else
-                {
-                    // Deviation 3f
-                    voyage = null;
-                }
-            }
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/support/ApplicationEvents.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/support/ApplicationEvents.java
deleted file mode 100644
index eb951fa..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/support/ApplicationEvents.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.support;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * "Messaging"
- *
- * This interface provides a way to let other parts of the system know about events that have occurred.
- * For now, no notifications are passed on but could be implemented here using for example JMS.
- */
-@Mixins( ApplicationEvents.SynchronousApplicationEventsStub.class )
-public interface ApplicationEvents
-    extends ServiceComposite
-{
-    /**
-     * A cargo has been handled.
-     *
-     * @param registeredHandlingEvent handling event
-     */
-    void cargoWasHandled( HandlingEvent registeredHandlingEvent );
-
-    /**
-     * A cargo has been misdirected.
-     *
-     * @param cargo cargo
-     */
-    void cargoWasMisdirected( Cargo cargo );
-
-    /**
-     * A cargo has arrived at its final destination.
-     *
-     * @param cargo cargo
-     */
-    void cargoHasArrived( Cargo cargo );
-
-    /**
-     * A handling event registration attempt is received.
-     *
-     * @param attempt Handling event registration attempt
-     */
-    void receivedHandlingEventRegistrationAttempt( RegisterHandlingEventAttemptDTO attempt );
-
-    void unsuccessfulHandlingEventRegistration( RegisterHandlingEventAttemptDTO attempt );
-
-    // Default implementation (could be substituted in assembly)
-    abstract class SynchronousApplicationEventsStub
-        implements ApplicationEvents
-    {
-        String id;
-        String time;
-        String type;
-        String unloc;
-        String loc;
-        String voyage;
-
-        Logger logger = LoggerFactory.getLogger( ApplicationEvents.class );
-
-        public void cargoWasHandled( HandlingEvent registeredHandlingEvent )
-        {
-            id = registeredHandlingEvent.trackingId().get().id().get();
-            time = parseDate( registeredHandlingEvent.completionTime().get() );
-            type = registeredHandlingEvent.handlingEventType().get().name();
-            unloc = registeredHandlingEvent.location().get().getCode();
-            loc = registeredHandlingEvent.location().get().name().get();
-            Voyage voy = registeredHandlingEvent.voyage().get();
-            voyage = voy != null ? ", voyage " + voy.voyageNumber().get().number().get() : "";
-
-            logger.info( "  Cargo '" + id + "' was handled " + time
-                         + " (" + type + " in " + loc + "/" + unloc + voyage + ")." );
-        }
-
-        public void cargoWasMisdirected( Cargo cargo )
-        {
-            id = cargo.trackingId().get().id().get();
-            loc = cargo.delivery().get().lastKnownLocation().get().name().get();
-            unloc = cargo.delivery().get().lastKnownLocation().get().toString();
-            type = cargo.delivery().get().lastHandlingEvent().get().handlingEventType().get().name();
-
-            logger.info( "  Unexpected " + type + " of cargo '" + id
-                         + "' in " + loc + "/" + unloc + "." );
-            logger.info( "  NOTIFICATION TO CUSTOMER: Please re-route misdirected cargo '"
-                         + id + "' (now in " + loc + ")." );
-        }
-
-        public void cargoHasArrived( Cargo cargo )
-        {
-            id = cargo.trackingId().get().id().get();
-            loc = cargo.delivery().get().lastKnownLocation().get().name().get();
-            unloc = cargo.delivery().get().lastKnownLocation().get().toString();
-
-            logger.info( "  Cargo '" + id + "' has arrived in " + loc + "/" + unloc + "." );
-            logger.info( "  NOTIFICATION TO CUSTOMER: Please claim cargo '" + id + "' in " + loc + "." );
-        }
-
-        public void receivedHandlingEventRegistrationAttempt( RegisterHandlingEventAttemptDTO attempt )
-        {
-            time = parseDate( attempt.completionTime().get() );
-            id = parse( attempt.trackingIdString().get() );
-            type = parse( attempt.eventTypeString().get() );
-            unloc = parse( attempt.unLocodeString().get() );
-            voyage = parse( attempt.voyageNumberString().get() );
-
-            logger.info( "  Handling registration attempt received ("
-                         + time + ", " + id + ", " + type + ", " + unloc + ", " + voyage + ")." );
-        }
-
-        public void unsuccessfulHandlingEventRegistration( RegisterHandlingEventAttemptDTO attempt )
-        {
-            id = attempt.trackingIdString().get();
-            type = attempt.eventTypeString().get();
-            unloc = attempt.unLocodeString().get();
-
-            logger.info( "  Unsuccessful handling event registration for cargo '"
-                         + id + "' (handling event '" + type + "' in '" + unloc + "')." );
-        }
-
-        private String parse( String str )
-        {
-            return str == null ? "null" : str;
-        }
-
-        private String parseDate( Date date )
-        {
-            return date == null ? "null" : new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ).format( date );
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/support/FoundNoRoutesException.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/support/FoundNoRoutesException.java
deleted file mode 100644
index fde107a..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/support/FoundNoRoutesException.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.support;
-
-import org.joda.time.LocalDate;
-
-/**
- * Custom messages when the deadline is too close and we can't find a route.
- */
-public class FoundNoRoutesException extends Exception
-{
-    private final String city;
-    private final LocalDate deadline;
-
-    public FoundNoRoutesException( String city, LocalDate deadline )
-    {
-        this.city = city;
-        this.deadline = deadline;
-    }
-
-    @Override
-    public String getMessage()
-    {
-        if( deadline.isBefore( new LocalDate().plusDays( 2 ) ) )
-        {
-            return "Impossible to get the cargo to " + city + " before " + deadline
-                   + "! Make a new booking with a deadline 2-3 weeks ahead in time.";
-        }
-        else if( deadline.isBefore( new LocalDate().plusDays( 4 ) ) )
-        {
-            return "Couldn't find any routes arriving in " + city + " before " + deadline
-                   + ". Please try again or make a new booking with a deadline 2-3 weeks ahead in time.";
-        }
-        else if( deadline.isBefore( new LocalDate().plusDays( 6 ) ) )
-        {
-            return "Sorry, our system couldn't immediately find a route arriving in " + city + " before " + deadline
-                   + ". Please try again, and we should hopefully be able to find a new route for you.";
-        }
-
-        return "Couldn't find any route to " + city + " arriving before " + deadline
-               + ". We don't know why. Have a nice day.";
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/support/RegisterHandlingEventAttemptDTO.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/support/RegisterHandlingEventAttemptDTO.java
deleted file mode 100644
index c37930b..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/support/RegisterHandlingEventAttemptDTO.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.support;
-
-import java.util.Date;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.conversion.DTO;
-
-/**
- * The RegisterHandlingEventAttemptDTO simply helps move event registration data around.
- */
-@Immutable
-public interface RegisterHandlingEventAttemptDTO extends DTO
-{
-    @Optional
-    Property<Date> registrationTime();
-
-    @Optional
-    Property<Date> completionTime();
-
-    @Optional
-    Property<String> trackingIdString();
-
-    @Optional
-    Property<String> eventTypeString();
-
-    @Optional
-    Property<String> unLocodeString();
-
-    @Optional
-    Property<String> voyageNumberString();
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/support/RoutingService.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/support/RoutingService.java
deleted file mode 100644
index 694322c..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/context/support/RoutingService.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.support;
-
-import java.rmi.RemoteException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import org.joda.time.LocalDate;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.sample.dcicargo.pathfinder_a.api.GraphTraversalService;
-import org.qi4j.sample.dcicargo.pathfinder_a.api.TransitEdge;
-import org.qi4j.sample.dcicargo.pathfinder_a.api.TransitPath;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Leg;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Routing service.
- *
- * Our end of the routing service. This is basically a data model
- * translation layer between our domain model and the API put forward
- * by the path finder team, which operates in a different context from us.
- */
-@Mixins( RoutingService.Mixin.class )
-public interface RoutingService
-    extends ServiceComposite
-{
-    /**
-     * @param routeSpecification route specification
-     *
-     * @return A list of itineraries that satisfy the specification. May be an empty list if no route is found.
-     */
-    List<Itinerary> fetchRoutesForSpecification( RouteSpecification routeSpecification )
-        throws FoundNoRoutesException;
-
-    abstract class Mixin
-        implements RoutingService
-    {
-        private static final Logger logger = LoggerFactory.getLogger( RoutingService.class );
-
-        @Structure
-        ValueBuilderFactory vbf;
-
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        @Service
-        GraphTraversalService graphTraversalService;
-
-        final static int MAX_TRIES = 10;
-
-        public List<Itinerary> fetchRoutesForSpecification( RouteSpecification routeSpecification )
-            throws FoundNoRoutesException
-        {
-            final Location origin = routeSpecification.origin().get();
-            final Location destination = routeSpecification.destination().get();
-
-            List<TransitPath> transitPaths;
-            List<Itinerary> itineraries = new ArrayList<Itinerary>();
-
-            // Try a MAX_TRIES times to avoid empty results too often
-            int tries = 0;
-            do
-            {
-                try
-                {
-                    transitPaths = graphTraversalService.findShortestPath( origin.getCode(), destination.getCode() );
-                }
-                catch( RemoteException e )
-                {
-                    logger.error( e.getMessage(), e );
-                    return Collections.emptyList();
-                }
-
-                // The returned result is then translated back into our domain model.
-                for( TransitPath transitPath : transitPaths )
-                {
-                    final Itinerary itinerary = toItinerary( transitPath );
-
-                    // Use the specification to safe-guard against invalid itineraries
-                    // We can use the side-effects free method of the RouteSpecification data object
-                    if( routeSpecification.isSatisfiedBy( itinerary ) )
-                    {
-                        itineraries.add( itinerary );
-                    }
-                }
-            }
-            while( tries++ < MAX_TRIES && itineraries.size() == 0 );
-
-            if( itineraries.size() == 0 )
-            {
-                throw new FoundNoRoutesException( destination.name().get(),
-                                                  new LocalDate( routeSpecification.arrivalDeadline().get() ) );
-            }
-
-            return itineraries;
-        }
-
-        private Itinerary toItinerary( TransitPath transitPath )
-        {
-            ValueBuilder<Itinerary> itinerary = vbf.newValueBuilder( Itinerary.class );
-            List<Leg> legs = new ArrayList<Leg>();
-            for( TransitEdge edge : transitPath.getTransitEdges() )
-            {
-                legs.add( toLeg( edge ) );
-            }
-            itinerary.prototype().legs().set( legs );
-
-            return itinerary.newInstance();
-        }
-
-        private Leg toLeg( TransitEdge edge )
-        {
-            UnitOfWork uow = uowf.currentUnitOfWork();
-
-            // Build Leg value object
-            ValueBuilder<Leg> leg = vbf.newValueBuilder( Leg.class );
-            leg.prototype().voyage().set( uow.get( Voyage.class, edge.getVoyageNumber() ) );
-            leg.prototype().loadLocation().set( uow.get( Location.class, edge.getFromUnLocode() ) );
-            leg.prototype().unloadLocation().set( uow.get( Location.class, edge.getToUnLocode() ) );
-            leg.prototype().loadTime().set( edge.getFromDate() );
-            leg.prototype().unloadTime().set( edge.getToDate() );
-
-            return leg.newInstance();
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/CargoEntity.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/CargoEntity.java
deleted file mode 100644
index ad2dc59..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/CargoEntity.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.entity;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargo;
-
-/**
- * Cargo entity
- */
-public interface CargoEntity
-    extends EntityComposite,
-
-            Cargo
-{
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/CargosEntity.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/CargosEntity.java
deleted file mode 100644
index 35c5055..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/CargosEntity.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.entity;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargos;
-
-/**
- * Cargo aggregate root?
- */
-public interface CargosEntity
-    extends EntityComposite, Cargos
-{
-    public static final String CARGOS_ID = "Cargos_id";
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/HandlingEventEntity.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/HandlingEventEntity.java
deleted file mode 100644
index f9fc52b..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/HandlingEventEntity.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.entity;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvent;
-
-/**
- * Handling Event entity
- */
-public interface HandlingEventEntity
-    extends EntityComposite,
-
-            HandlingEvent
-{
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/HandlingEventsEntity.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/HandlingEventsEntity.java
deleted file mode 100644
index e30cd9e..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/HandlingEventsEntity.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.entity;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvents;
-
-/**
- * HandlingEvent aggregate root?
- */
-public interface HandlingEventsEntity
-    extends EntityComposite,
-
-            HandlingEvents
-{
-    public static final String HANDLING_EVENTS_ID = "Handling_events_id";
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/LocationEntity.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/LocationEntity.java
deleted file mode 100644
index 8aa06ae..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/LocationEntity.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.entity;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-
-/**
- * Location entity
- *
- * Locations have been created outside the shipping application context so we don't have any
- * separate aggregate root to create those from.
- */
-public interface LocationEntity
-    extends EntityComposite,
-
-            Location
-{
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/VoyageEntity.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/VoyageEntity.java
deleted file mode 100644
index e289add..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/entity/VoyageEntity.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.entity;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
-
-/**
- * Voyage entity
- *
- * Voyages have been created outside the shipping application context so we don't have any
- * separate aggregate root to create those from.
- */
-public interface VoyageEntity
-    extends EntityComposite,
-
-            Voyage
-{
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/cargo/Cargo.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/cargo/Cargo.java
deleted file mode 100644
index b424c91..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/cargo/Cargo.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.cargo;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-
-/**
- * Cargo data
- *
- * {@link TrackingId}           created automatically
- * {@link Location} origin      Specified upon creation (mandatory)
- * {@link RouteSpecification}   Specified upon creation (mandatory)
- * {@link Delivery}             A calculated snapshot of the current delivery status (created by system)
- * {@link Itinerary}            Description of chosen route (optional)
- */
-public interface Cargo
-{
-    @Immutable
-    Property<TrackingId> trackingId();
-
-    @Immutable
-    Association<Location> origin();
-
-    Property<RouteSpecification> routeSpecification();
-
-    Property<Delivery> delivery();
-
-    @Optional
-    Property<Itinerary> itinerary();
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/cargo/Cargos.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/cargo/Cargos.java
deleted file mode 100644
index 40e71f4..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/cargo/Cargos.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.cargo;
-
-import java.util.UUID;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.Delivery;
-
-/**
- * Cargo "collection" - could have had a many-association to cargos if it was part of the domain model.
- */
-@Mixins( Cargos.Mixin.class )
-public interface Cargos
-{
-    Cargo createCargo( RouteSpecification routeSpecification, Delivery delivery, @Optional String id );
-
-    class Mixin
-        implements Cargos
-    {
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        @Structure
-        ValueBuilderFactory vbf;
-
-        public Cargo createCargo( RouteSpecification routeSpecification, Delivery delivery, String id )
-        {
-            TrackingId trackingId = buildTrackingId( id );
-
-            UnitOfWork uow = uowf.currentUnitOfWork();
-            EntityBuilder<Cargo> cargoBuilder = uow.newEntityBuilder( Cargo.class, trackingId.id().get() );
-            cargoBuilder.instance().trackingId().set( trackingId );
-            cargoBuilder.instance().origin().set( routeSpecification.origin().get() );
-            cargoBuilder.instance().routeSpecification().set( routeSpecification );
-            cargoBuilder.instance().delivery().set( delivery );
-
-            return cargoBuilder.newInstance();
-        }
-
-        private TrackingId buildTrackingId( String id )
-        {
-            if( id == null || id.trim().equals( "" ) )
-            {
-                // Build random tracking id
-                final String uuid = UUID.randomUUID().toString().toUpperCase();
-                id = uuid.substring( 0, uuid.indexOf( "-" ) );
-            }
-
-            ValueBuilder<TrackingId> trackingIdBuilder = vbf.newValueBuilder( TrackingId.class );
-            trackingIdBuilder.prototype().id().set( id );
-            return trackingIdBuilder.newInstance();
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/cargo/RouteSpecification.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/cargo/RouteSpecification.java
deleted file mode 100644
index 582d633..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/cargo/RouteSpecification.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.cargo;
-
-import java.util.Date;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-
-/**
- * A route specification describes:
- * - where a cargo is going from (origin)
- * - where a cargo is going to (destination)
- * - when a cargo is expected to arrive at the latest (deadline)
- *
- * If the route specification needs to change because of unexpected
- * handling events, it's replaced with a new one.
- *
- * A route specification "is satisfied" when an itinerary meets the requirements:
- * - First leg of itinerary has same location as origin in route specification
- * - Last leg of itinerary has same location as destination in route specification
- * - Arrival deadline is before deadline of route specification
- *
- * DCI Data is supposed to be dumb. Can we accept to have the specification
- * logic here?
- *
- * All properties are mandatory and immutable.
- * If the destination needs to change, a new RouteSpecification value object is created.
- */
-@Mixins( RouteSpecification.Mixin.class )
-public interface RouteSpecification
-{
-    Association<Location> origin();
-
-    Association<Location> destination();
-
-    Property<Date> arrivalDeadline();
-
-    // Can we accept to have this "intelligent" logic here?
-    // DCI Data is supposed to be dumb, but it's really convenient to have this logic here,
-    // and there's no dependencies involved...
-    boolean isSatisfiedBy( Itinerary itinerary );
-
-    abstract class Mixin
-        implements RouteSpecification
-    {
-        public boolean isSatisfiedBy( Itinerary itinerary )
-        {
-            return itinerary != null &&
-                   !itinerary.legs().get().isEmpty() &&
-                   origin().get().equals( itinerary.firstLeg().loadLocation().get() ) &&
-                   destination().get().equals( itinerary.lastLeg().unloadLocation().get() ) &&
-                   arrivalDeadline().get().after( itinerary.finalArrivalDate() );
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/cargo/TrackingId.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/cargo/TrackingId.java
deleted file mode 100644
index 09ece56..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/cargo/TrackingId.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.cargo;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.library.constraints.annotation.NotEmpty;
-
-/**
- * A TrackingId uniquely identifies a particular cargo.
- * Automatically generated by the application.
- */
-public interface TrackingId
-    extends ValueComposite
-{
-    @NotEmpty
-    Property<String> id();
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/delivery/Delivery.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/delivery/Delivery.java
deleted file mode 100644
index 4d46fbe..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/delivery/Delivery.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.delivery;
-
-import java.util.Date;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.sample.dcicargo.sample_a.context.support.ApplicationEvents;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
-
-/**
- * The Delivery describes the actual transportation of the cargo, as opposed to
- * the customer requirement {@link RouteSpecification} and the plan {@link Itinerary}.
- *
- * Complex data of the shipping domain is captured here in a value object that is
- * re-created each time some delivery status changes.
- *
- * Booking
- * The life cycle of a cargo begins with the booking procedure. During a (short) period
- * of time, between booking and initial routing, the cargo has no itinerary and is therefore
- * not_routed.
- *
- * Routing
- * The booking clerk requests a list of possible routes, matching the route specification,
- * and assigns the cargo to one route. The route to which a cargo is assigned is described
- * by an itinerary. The cargo is now routed.
- *
- * Handling
- * Receipt of the cargo in the origin location marks the beginning of a series of handling
- * events that will eventually deliver the cargo at the destination. Handling events are
- * supposed to be registered by local authorities and sent asynchronously to the cargo system
- * which then re-calculate and replaces the delivery value object of the cargo.
- * (In this implementation the trigger is synchronous in {@link ApplicationEvents}
- * and the registration-ui is close to the booking and tracking interfaces for simplicity).
- *
- * Change of destination
- * It may also happen that a cargo is accidentally misrouted when a new destination is
- * selected in the middle of the voyage of the cargo. The cargo then becomes misrouted,
- * which should notify the proper personnel and also trigger a re-routing procedure.
- * In this implementation a synchronous message is sent to system output.
- *
- * Re-routing
- * A cargo can be re-routed during transport, on demand of the customer, in which case
- * a new route is specified for the cargo and a new route is requested. The old itinerary,
- * being a value object, is discarded and a new one is attached to the cargo.
- *
- * Customs
- * The cargo can be checked by the custom authorities anytime during the delivery. In that
- * case it's unknown what happens next so the cargo is then considered misdirected.
- *
- * Claim
- * The life cycle of a cargo ends when the cargo is claimed by the customer.
- */
-public interface Delivery
-    extends ValueComposite
-{
-    Property<Date> timestamp();
-
-    /*
-   * NOT_ROUTED
-   * ROUTED
-   * MISROUTED
-   * */
-    Property<RoutingStatus> routingStatus();
-
-    /*
-   * NOT_RECEIVED
-   * IN_PORT
-   * ONBOARD_CARRIER
-   * CLAIMED
-   * UNKNOWN
-   * */
-    Property<TransportStatus> transportStatus();
-
-    // Unexpected location of cargo according to itinerary
-    @UseDefaults
-    Property<Boolean> isMisdirected();
-
-    /**
-     * RECEIVE
-     * LOAD
-     * UNLOAD
-     * CUSTOMS
-     * CLAIM
-     *
-     * ("HandlingActivity" in DDD sample)
-     */
-    @Optional
-    Property<ExpectedHandlingEvent> nextExpectedHandlingEvent();
-
-    @Optional
-    Association<HandlingEvent> lastHandlingEvent();
-
-    @Optional
-    Association<Location> lastKnownLocation();
-
-    @Optional
-    Association<Voyage> currentVoyage();
-
-    @Optional
-    Property<Date> eta();
-
-    @UseDefaults
-    Property<Boolean> isUnloadedAtDestination();
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/delivery/ExpectedHandlingEvent.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/delivery/ExpectedHandlingEvent.java
deleted file mode 100644
index 194ea24..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/delivery/ExpectedHandlingEvent.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.delivery;
-
-import java.util.Date;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
-
-/**
- * An expected handling event (former "HandlingActivity") represents how and where a cargo
- * is expected to be handled next.
- */
-public interface ExpectedHandlingEvent
-    extends ValueComposite
-{
-    Property<HandlingEventType> handlingEventType();
-
-    Association<Location> location();
-
-    // Added expected time for the event to happen (compared to the original DDD sample)
-    @Optional
-    Property<Date> time();
-
-    @Optional
-    Association<Voyage> voyage();
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/delivery/RoutingStatus.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/delivery/RoutingStatus.java
deleted file mode 100644
index 369bdfc..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/delivery/RoutingStatus.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.delivery;
-
-/**
- * A routing status indicates whether an itinerary is assigned to
- * a cargo and satisfying the route specification.
- */
-public enum RoutingStatus
-{
-    NOT_ROUTED,    // Itinerary has not been assigned to cargo yet
-    ROUTED,        // Itinerary is assigned to cargo
-    MISROUTED;     // RouteSpecification is not satisfied by Itinerary
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/delivery/TransportStatus.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/delivery/TransportStatus.java
deleted file mode 100644
index 7240870..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/delivery/TransportStatus.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.delivery;
-
-/**
- * A transport status represents what transportation state a cargo is in.
- */
-public enum TransportStatus
-{
-    NOT_RECEIVED,
-    IN_PORT,
-    ONBOARD_CARRIER,
-    CLAIMED,
-    UNKNOWN
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/handling/HandlingEvent.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/handling/HandlingEvent.java
deleted file mode 100644
index c256201..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/handling/HandlingEvent.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.handling;
-
-import java.util.Date;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.TrackingId;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
-
-/**
- * A HandlingEvent is used to register the event when, for instance,
- * a cargo is unloaded from a carrier at some location at a given time.
- *
- * The HandlingEvent's are sent from different Incident Logging Applications
- * some time after the event occurred and contain information about the
- * {@link TrackingId}, {@link Location}, timestamp of the completion of the event,
- * and possibly, if applicable a {@link Voyage}.
- *
- * HandlingEvent's could contain information about a {@link Voyage} and if so,
- * the event type must be either {@link HandlingEventType#LOAD} or
- * {@link HandlingEventType#UNLOAD}.
- *
- * All other events must be of {@link HandlingEventType#RECEIVE},
- * {@link HandlingEventType#CLAIM} or {@link HandlingEventType#CUSTOMS}.
- * (Handling event type is mandatory).
- */
-public interface HandlingEvent
-{
-    @Immutable
-    Property<Date> registrationTime();
-
-    @Immutable
-    Property<Date> completionTime();
-
-    @Immutable
-    Property<TrackingId> trackingId();
-
-    @Immutable
-    Property<HandlingEventType> handlingEventType();
-
-    @Immutable
-    Association<Location> location();
-
-    @Optional
-    @Immutable
-    Association<Voyage> voyage();
-
-    @Optional
-    @UseDefaults
-    Property<Boolean> wasUnexpected();
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/handling/HandlingEventType.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/handling/HandlingEventType.java
deleted file mode 100644
index 2fc0144..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/handling/HandlingEventType.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.handling;
-
-/**
- * A handling event type either requires or prohibits a voyage association.
- */
-public enum HandlingEventType
-{
-    RECEIVE( false ),
-    LOAD( true ),
-    UNLOAD( true ),
-    CUSTOMS( false ),
-    CLAIM( false );
-
-    private final boolean voyageRequired;
-
-    /**
-     * Private enum constructor.
-     *
-     * @param voyageRequired whether or not a voyage is associated with this event type
-     */
-    private HandlingEventType( final boolean voyageRequired )
-    {
-        this.voyageRequired = voyageRequired;
-    }
-
-    /**
-     * @return True if a voyage association is required for this event type.
-     */
-    public boolean requiresVoyage()
-    {
-        return voyageRequired;
-    }
-
-    /**
-     * @return True if a voyage association is prohibited for this event type.
-     */
-    public boolean prohibitsVoyage()
-    {
-        return !requiresVoyage();
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/handling/HandlingEvents.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/handling/HandlingEvents.java
deleted file mode 100644
index d267b3f..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/handling/HandlingEvents.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.handling;
-
-import java.util.Date;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.TrackingId;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
-
-/**
- * HandlingEvent "collection" - could have had a many-association to
- * Handling Events if it was part of the domain model.
- */
-@Mixins( HandlingEvents.Mixin.class )
-public interface HandlingEvents
-{
-    HandlingEvent createHandlingEvent( Date registrationTime,
-                                       Date completionTime,
-                                       TrackingId trackingId,
-                                       HandlingEventType handlingEventType,
-                                       Location location,
-                                       @Optional Voyage voyage
-    )
-        throws IllegalArgumentException;
-
-    public abstract class Mixin
-        implements HandlingEvents
-    {
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        public HandlingEvent createHandlingEvent( Date registrationTime,
-                                                  Date completionTime,
-                                                  TrackingId trackingId,
-                                                  HandlingEventType handlingEventType,
-                                                  Location location,
-                                                  Voyage voyage
-        )
-            throws IllegalArgumentException
-        {
-            if( voyage == null && handlingEventType.requiresVoyage() )
-            {
-                throw new IllegalArgumentException( "Voyage is required for handling event type " + handlingEventType );
-            }
-
-            else if( voyage != null && handlingEventType.prohibitsVoyage() )
-            {
-                throw new IllegalArgumentException( "Voyage is not allowed with handling event type " + handlingEventType );
-            }
-
-            UnitOfWork uow = uowf.currentUnitOfWork();
-            EntityBuilder<HandlingEvent> handlingEventBuilder = uow.newEntityBuilder( HandlingEvent.class );
-            handlingEventBuilder.instance().registrationTime().set( registrationTime );
-            handlingEventBuilder.instance().completionTime().set( completionTime );
-            handlingEventBuilder.instance().trackingId().set( trackingId );
-            handlingEventBuilder.instance().handlingEventType().set( handlingEventType );
-            handlingEventBuilder.instance().location().set( location );
-            handlingEventBuilder.instance().voyage().set( voyage );  // could be null
-
-            // Save and return
-            return handlingEventBuilder.newInstance();
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/itinerary/Itinerary.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/itinerary/Itinerary.java
deleted file mode 100644
index 329cc7a..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/itinerary/Itinerary.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary;
-
-import java.util.Date;
-import java.util.List;
-import org.joda.time.Days;
-import org.joda.time.LocalDate;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.library.constraints.annotation.NotEmpty;
-
-/**
- * An itinerary is a description of a planned route for a cargo.
- *
- * The itinerary has a list of Legs each describing expected
- * loading onto/ unloading from voyages at different locations.
- *
- * List of legs is mandatory and immutable.
- */
-@Mixins( Itinerary.Mixin.class )
-public interface Itinerary
-{
-    @NotEmpty
-    Property<List<Leg>> legs();
-
-    // Side-effects free and UI agnostic convenience methods
-    Leg firstLeg();
-
-    Leg lastLeg();
-
-    Date finalArrivalDate();
-
-    int days();
-
-    public abstract class Mixin
-        implements Itinerary
-    {
-        public Leg firstLeg()
-        {
-            if( legs().get().isEmpty() )
-            {
-                return null;
-            }
-
-            return legs().get().get( 0 );
-        }
-
-        public Leg lastLeg()
-        {
-            if( legs().get().isEmpty() )
-            {
-                return null;
-            }
-
-            return legs().get().get( legs().get().size() - 1 );
-        }
-
-        public Date finalArrivalDate()
-        {
-            if( lastLeg() == null )
-            {
-                return new Date( new Date( Long.MAX_VALUE ).getTime() );
-            }
-
-            return new Date( lastLeg().unloadTime().get().getTime() );
-        }
-
-        public int days()
-        {
-            Date dep = firstLeg().loadTime().get();
-            Date arr = lastLeg().unloadTime().get();
-            return Days.daysBetween( new LocalDate( dep ), new LocalDate( arr ) ).getDays();
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/itinerary/Leg.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/itinerary/Leg.java
deleted file mode 100644
index 8978a05..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/itinerary/Leg.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary;
-
-import java.util.Date;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
-
-/**
- * A leg describes an expected segment of a route:
- * - loading onto a voyage at a load location
- * - unloading from the voyage at a unload location
- *
- * All properties are mandatory and immutable.
- */
-public interface Leg
-    extends ValueComposite
-{
-    Association<Location> loadLocation();
-
-    Property<Date> loadTime();
-
-    Association<Voyage> voyage();
-
-    Property<Date> unloadTime();
-
-    Association<Location> unloadLocation();
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/location/Location.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/location/Location.java
deleted file mode 100644
index f504ee4..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/location/Location.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.location;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-
-/**
- * A location is stops on a journey, such as cargo
- * origin or destination, or carrier movement endpoints.
- *
- * It is uniquely identified by a {@link UnLocode}.
- *
- * All properties are mandatory and immutable.
- */
-@Immutable
-@Mixins( Location.Mixin.class )
-public interface Location
-{
-    Property<UnLocode> unLocode();
-
-    Property<String> name();
-
-    // Side-effects free and UI agnostic convenience methods
-    String getCode();
-
-    String getString();
-
-    abstract class Mixin
-        implements Location
-    {
-        public String getCode()
-        {
-            return unLocode().get().code().get();
-        }
-
-        public String getString()
-        {
-            return name().get() + " (" + getCode() + ")";
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/location/UnLocode.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/location/UnLocode.java
deleted file mode 100644
index 2d40d4d..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/location/UnLocode.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.location;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.library.constraints.annotation.Matches;
-
-/**
- * United Nations location code.
- *
- * http://www.unece.org/cefact/locode/
- * http://www.unece.org/cefact/locode/DocColumnDescription.htm#LOCODE
- *
- * UnLocode is mandatory and immutable.
- */
-public interface UnLocode
-    extends ValueComposite
-{
-    // Country code is exactly two letters.
-    // Location code is usually three letters, but may contain the numbers 2-9 as well
-    @Matches( "[a-zA-Z]{2}[a-zA-Z2-9]{3}" )
-    Property<String> code();
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/voyage/CarrierMovement.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/voyage/CarrierMovement.java
deleted file mode 100644
index 41c1b2a..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/voyage/CarrierMovement.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.voyage;
-
-import java.util.Date;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-
-/**
- * A carrier movement is a vessel voyage from one location to another.
- *
- * All properties are mandatory and immutable.
- */
-public interface CarrierMovement
-    extends ValueComposite
-{
-    Association<Location> departureLocation();
-
-    Association<Location> arrivalLocation();
-
-    Property<Date> departureTime();
-
-    Property<Date> arrivalTime();
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/voyage/Schedule.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/voyage/Schedule.java
deleted file mode 100644
index b3cb935..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/voyage/Schedule.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.voyage;
-
-import java.util.List;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * A schedule is a series of {@link CarrierMovement}s.
- *
- * List of carrier movements is mandatory and immutable.
- */
-public interface Schedule
-    extends ValueComposite
-{
-    Property<List<CarrierMovement>> carrierMovements();
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/voyage/Voyage.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/voyage/Voyage.java
deleted file mode 100644
index 4454bc8..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/voyage/Voyage.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.voyage;
-
-import org.qi4j.api.property.Property;
-
-/**
- * A voyage is a ship, train, flight etc carrying a cargo from one location
- * to another. A {@link Schedule} describes the route it takes.
- *
- * A cargo can be loaded onto part of, or the whole voyage.
- *
- * All properties are mandatory and immutable.
- */
-public interface Voyage
-{
-    Property<VoyageNumber> voyageNumber();
-
-    Property<Schedule> schedule();
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/voyage/VoyageNumber.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/voyage/VoyageNumber.java
deleted file mode 100644
index 1f8623a..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/data/shipping/voyage/VoyageNumber.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.data.shipping.voyage;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * Identifies a {@link Voyage}.
- *
- * Voyage number is mandatory and immutable.
- */
-public interface VoyageNumber
-    extends ValueComposite
-{
-    Property<String> number();
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/WicketQi4jApplication.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/WicketQi4jApplication.java
deleted file mode 100644
index 20e3700..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/WicketQi4jApplication.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure;
-
-import javax.servlet.http.HttpServletRequest;
-import org.apache.wicket.Page;
-import org.apache.wicket.protocol.http.WebApplication;
-import org.apache.wicket.request.cycle.AbstractRequestCycleListener;
-import org.apache.wicket.request.cycle.RequestCycle;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.composite.TransientBuilderFactory;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.query.QueryBuilderFactory;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.ConcurrentEntityModificationException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.conversion.EntityToDTOService;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.model.Queries;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.model.ReadOnlyModel;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.page.BaseWebPage;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Base Wicket Web Application containing the Zest application.
- */
-public class WicketQi4jApplication
-    extends WebApplication
-{
-    public Logger logger = LoggerFactory.getLogger( WicketQi4jApplication.class );
-
-    protected Application qi4jApp;
-    protected Module qi4jModule;
-
-    @Structure
-    protected UnitOfWorkFactory uowf;
-
-    @Structure
-    protected ValueBuilderFactory vbf;
-
-    @Structure
-    protected QueryBuilderFactory qbf;
-
-    @Structure
-    protected TransientBuilderFactory tbf;
-
-    @Structure
-    protected Qi4j qi4j;
-
-    @Service
-    protected EntityToDTOService valueConverter;
-
-    /**
-     * Zest Assembler
-     *
-     * To let the custom application class (DCISampleApplication_x) focus on starting up the
-     * Wicket environment, I made a convention of having Zest Assembler files in an 'assembly'
-     * folder beside the custom application class.
-     *
-     * There's always only one application file, but we could split the assemblage into several
-     * files ie. one for each layer. In that case, the Assembler file would be distributing to
-     * the individual LayerXAssembler classes.
-     *
-     * If you like, you can also override this method in the custom application class and simply
-     * return an instance of YourAssembler:
-     *
-     * &#64;Override protected ApplicationAssembler getAssembler() {
-     * return new YourAssemblerInAnyPath();
-     * }
-     */
-    protected ApplicationAssembler getAssembler()
-        throws Exception
-    {
-        String appPath = getClass().getCanonicalName();
-        String expectedPathFromApplication = ".assembly.Assembler";
-        String assemblerPath = appPath.substring( 0, appPath.lastIndexOf( "." ) ) + expectedPathFromApplication;
-        try
-        {
-            return (ApplicationAssembler) Class.forName( assemblerPath ).newInstance();
-        }
-        catch( ClassNotFoundException e )
-        {
-            throw new Exception( "Couldn't find Zest assembler in path '" + assemblerPath + "'" );
-        }
-    }
-
-    protected String defaultLayerName()
-    {
-        return "BOOTSTRAP";
-    }
-
-    protected String defaultModuleName()
-    {
-        return "BOOTSTRAP-Bootstrap";
-    }
-
-    // Override this to bootstrap the wicket application
-    protected void wicketInit()
-    {
-    }
-
-    @Override
-    protected void init()
-    {
-        startQi4j();
-        handleUnitOfWork();
-
-        Context.prepareContextBaseClass( uowf );
-        BaseWebPage.prepareBaseWebPageClass( tbf );
-        ReadOnlyModel.prepareModelBaseClass( qi4jModule, qi4j, valueConverter );
-        Queries.prepareQueriesBaseClass( uowf, qbf );
-
-        wicketInit();
-    }
-
-    private void startQi4j()
-    {
-        try
-        {
-            logger.info( "Starting Zest application" );
-            Energy4Java qi4j = new Energy4Java();
-            qi4jApp = qi4j.newApplication( getAssembler() );
-            qi4jApp.activate();
-            qi4jModule = qi4jApp.findModule( defaultLayerName(), defaultModuleName() );
-
-            // Zest injects @Structure and @Service elements into this application instance
-            //qi4jModule.newObject( WicketQi4jApplication.class );
-            qi4jModule.injectTo( this );
-
-            logger.info( "Started Zest application" );
-        }
-        catch( Exception e )
-        {
-            logger.error( "Could not start Zest application." );
-            e.printStackTrace();
-            System.exit( 100 );
-        }
-    }
-
-    private void handleUnitOfWork()
-    {
-        getRequestCycleListeners().add( new AbstractRequestCycleListener()
-        {
-            @Override
-            public void onBeginRequest( final RequestCycle requestCycle )
-            {
-                super.onBeginRequest( requestCycle );
-
-                logger.debug( "================================" );
-                logger.debug( "REQUEST start" );
-                logger.debug( requestCycle.getRequest().toString() );
-                logger.debug( requestCycle.getRequest().getRequestParameters().toString() );
-
-                UnitOfWork uow = uowf.newUnitOfWork( UsecaseBuilder.newUsecase( "REQUEST" ) );
-                logger.debug( "  ### NEW " + uow + "   ### MODULE: " + qi4jModule );
-            }
-
-            @Override
-            public void onEndRequest( final RequestCycle requestCycle )
-            {
-                UnitOfWork uow = uowf.currentUnitOfWork();
-                if( uow != null )
-                {
-                    try
-                    {
-                        if( "POST".equals( ( (HttpServletRequest) requestCycle.getRequest()
-                            .getContainerRequest() ).getMethod() ) )
-                        {
-                            // "Save"
-                            logger.debug( "  ### COMPLETE " + uow + "   ### MODULE: " + qi4jModule );
-                            uow.complete();
-                        }
-                        else
-                        {
-                            // GET requests
-                            logger.debug( "  ### DISCARD " + uow + "   ### MODULE: " + qi4jModule );
-                            uow.discard();
-                        }
-                    }
-                    catch( ConcurrentEntityModificationException e )
-                    {
-                        logger.error( "  ### DISCARD " + uow + "   ### MODULE: " + qi4jModule );
-                        uow.discard();
-                        e.printStackTrace();
-                    }
-                    catch( UnitOfWorkCompletionException e )
-                    {
-                        logger.error( "  ### DISCARD " + uow + "   ### MODULE: " + qi4jModule );
-                        uow.discard();
-                        e.printStackTrace();
-                    }
-                }
-                logger.debug( "REQUEST end" );
-                logger.debug( "------------------------------------" );
-            }
-        } );
-    }
-
-    // Since Zest can only add concrete classes in the assembly, we need to implement a (dummy) getHomePage()
-    // method here. Override in wicket application class with a real returned page class.
-    @Override
-    public Class<? extends Page> getHomePage()
-    {
-        return null;
-    }
-
-    @Override
-    protected void onDestroy()
-    {
-        if( qi4jApp == null )
-        {
-            return;
-        }
-
-        try
-        {
-            logger.info( "Passivating Zest application" );
-            qi4jApp.passivate();
-        }
-        catch( Exception e )
-        {
-            e.printStackTrace();
-        }
-    }
-
-    public String appVersion()
-    {
-        return qi4jApp.version();
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/conversion/DTO.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/conversion/DTO.java
deleted file mode 100644
index cc87155..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/conversion/DTO.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.conversion;
-
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * ValueComposites that extend DTO are candidates to have association types converted and assigned
- */
-@Immutable
-public interface DTO extends ValueComposite
-{
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/conversion/EntityToDTOService.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/conversion/EntityToDTOService.java
deleted file mode 100644
index 64ec55d..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/conversion/EntityToDTOService.java
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.conversion;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.type.CollectionType;
-import org.qi4j.api.value.NoSuchValueException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.library.conversion.values.Unqualified;
-import org.qi4j.spi.Qi4jSPI;
-
-/**
- * Conversion of Entity objects to DTO's
- *
- * Value composites that extend {@link DTO} will have association properties converted recursively.
- *
- * Modification of {org.qi4j.library.conversion.values.EntityToValue}
- * WARN No support of NamedAssociations
- */
-@SuppressWarnings( "unchecked" )
-@Mixins( EntityToDTOService.Mixin.class )
-public interface EntityToDTOService
-    extends ServiceComposite
-{
-    <T> T convert( Class<T> valueType, Object entity );
-
-    static abstract class Mixin
-        implements EntityToDTOService
-    {
-        @Structure
-        private ValueBuilderFactory vbf;
-
-        @Structure
-        private Qi4jSPI spi;
-
-        @Structure
-        private Module module;
-
-        @Override
-        public <T> T convert( final Class<T> valueType, Object entity )
-        {
-            ValueDescriptor valueDescriptor = module.valueDescriptor( valueType.getName() );
-            if( valueDescriptor == null )
-            {
-                throw new NoSuchValueException( valueType.getName(), module.name() );
-            }
-            Unqualified unqualified = valueDescriptor.metaInfo( Unqualified.class );
-            final EntityComposite composite = (EntityComposite) entity;
-            final EntityDescriptor entityDescriptor = spi.entityDescriptorFor( composite );
-            final AssociationStateHolder associationState = spi.stateOf( composite );
-            ValueBuilder<?> builder;
-
-            if( unqualified == null || !unqualified.value() )
-            {
-                // Copy state using qualified names
-                builder = vbf.newValueBuilderWithState( valueType, new Function<PropertyDescriptor, Object>()
-                {
-                    @Override
-                    public Object map( PropertyDescriptor descriptor )
-                    {
-                        try
-                        {
-                            return associationState.propertyFor( descriptor.accessor() ).get();
-                        }
-                        catch( IllegalArgumentException e )
-                        {
-                            if( descriptor.valueType().mainType().equals( String.class ) )
-                            {
-                                // Find Association and convert to string
-                                AssociationDescriptor associationDescriptor;
-                                try
-                                {
-                                    associationDescriptor = entityDescriptor.state()
-                                        .getAssociationByName( descriptor.qualifiedName().name() );
-                                }
-                                catch( IllegalArgumentException e1 )
-                                {
-                                    return null;
-                                }
-                                Object entity = associationState.associationFor( associationDescriptor.accessor() ).get();
-                                if( entity != null )
-                                {
-                                    return ( (Identity) entity ).identity().get();
-                                }
-                                return null;
-                            }
-                            else if( descriptor.valueType() instanceof CollectionType
-                                     && ( (CollectionType) descriptor.valueType() ).collectedType().mainType().equals( String.class ) )
-                            {
-                                AssociationDescriptor associationDescriptor;
-                                try
-                                {
-                                    associationDescriptor = entityDescriptor.state()
-                                        .getManyAssociationByName( descriptor.qualifiedName().name() );
-                                }
-                                catch( IllegalArgumentException e1 )
-                                {
-                                    return Collections.emptyList();
-                                }
-
-                                ManyAssociation<?> state = associationState.manyAssociationFor( associationDescriptor.accessor() );
-                                List<String> entities = new ArrayList<>( state.count() );
-                                for( Object entity : state )
-                                {
-                                    entities.add( ( (Identity) entity ).identity().get() );
-                                }
-                                return entities;
-                            }
-
-                            // No NamedAssociation support
-
-                            return null;
-                        }
-                    }
-                }, new Function<AssociationDescriptor, EntityReference>()
-                {
-                    @Override
-                    public EntityReference map( AssociationDescriptor associationDescriptor )
-                    {
-                        return EntityReference.entityReferenceFor(
-                            associationState.associationFor( associationDescriptor.accessor() ).get() );
-                    }
-                }, new Function<AssociationDescriptor, Iterable<EntityReference>>()
-                {
-                    @Override
-                    public Iterable<EntityReference> map( AssociationDescriptor associationDescriptor )
-                    {
-                        ManyAssociation<?> state = associationState.manyAssociationFor( associationDescriptor.accessor() );
-                        List<EntityReference> refs = new ArrayList<>( state.count() );
-                        for( Object entity : state )
-                        {
-                            refs.add( EntityReference.entityReferenceFor( entity ) );
-                        }
-                        return refs;
-                    }
-                }, new Function<AssociationDescriptor, Map<String, EntityReference>>()
-                {
-                    @Override
-                    public Map<String, EntityReference> map( AssociationDescriptor from )
-                    {
-                        // No NamedAssociation support
-                        return Collections.emptyMap();
-                    }
-                } );
-            }
-            else
-            {
-                builder = vbf.newValueBuilderWithState( valueType, new Function<PropertyDescriptor, Object>()
-                {
-                    @Override
-                    public Object map( PropertyDescriptor descriptor )
-                    {
-                        try
-                        {
-                            PropertyDescriptor propertyDescriptor = entityDescriptor.state()
-                                .findPropertyModelByName( descriptor.qualifiedName().name() );
-                            return associationState.propertyFor( propertyDescriptor.accessor() ).get();
-                        }
-                        catch( IllegalArgumentException e )
-                        {
-                            if( descriptor.valueType().mainType().equals( String.class ) )
-                            {
-                                // Find Association and convert to string
-                                AssociationDescriptor associationDescriptor;
-                                try
-                                {
-                                    associationDescriptor = entityDescriptor.state()
-                                        .getAssociationByName( descriptor.qualifiedName().name() );
-                                }
-                                catch( IllegalArgumentException e1 )
-                                {
-                                    return null;
-                                }
-
-                                Object entity = associationState.associationFor( associationDescriptor.accessor() ).get();
-                                if( entity != null )
-                                {
-                                    return ( (Identity) entity ).identity().get();
-                                }
-                                return null;
-                            }
-                            else if( descriptor.valueType() instanceof CollectionType
-                                     && ( (CollectionType) descriptor.valueType() ).collectedType().mainType().equals( String.class ) )
-                            {
-                                AssociationDescriptor associationDescriptor;
-                                try
-                                {
-                                    associationDescriptor = entityDescriptor.state()
-                                        .getManyAssociationByName( descriptor.qualifiedName().name() );
-                                }
-                                catch( IllegalArgumentException e1 )
-                                {
-                                    return null;
-                                }
-
-                                ManyAssociation<?> state = associationState.manyAssociationFor( associationDescriptor.accessor() );
-                                List<String> entities = new ArrayList<>( state.count() );
-                                for( Object entity : state )
-                                {
-                                    entities.add( ( (Identity) entity ).identity().get() );
-                                }
-                                return entities;
-                            }
-
-                            // No NamedAssociation support
-
-                            // DTO
-                            Class<?> type = descriptor.valueType().mainType();
-                            if( DTO.class.isAssignableFrom( type ) )
-                            {
-                                AssociationDescriptor associationDescriptor;
-                                try
-                                {
-                                    associationDescriptor = entityDescriptor.state()
-                                        .getAssociationByName( descriptor.qualifiedName().name() );
-                                }
-                                catch( IllegalArgumentException e1 )
-                                {
-                                    return null;
-                                }
-
-                                Object entity = associationState.associationFor( associationDescriptor.accessor() ).get();
-                                if( entity != null )
-                                {
-                                    return convert( type, entity );
-                                }
-                            }
-
-                            return null;
-                        }
-                    }
-                }, new Function<AssociationDescriptor, EntityReference>()
-                {
-                    @Override
-                    public EntityReference map( AssociationDescriptor descriptor )
-                    {
-                        AssociationDescriptor associationDescriptor;
-                        try
-                        {
-                            associationDescriptor = entityDescriptor.state()
-                                .getAssociationByName( descriptor.qualifiedName().name() );
-                        }
-                        catch( IllegalArgumentException e )
-                        {
-                            return null;
-                        }
-
-                        return EntityReference.entityReferenceFor( associationState
-                            .associationFor( associationDescriptor.accessor() ).get() );
-                    }
-                }, new Function<AssociationDescriptor, Iterable<EntityReference>>()
-                {
-                    @Override
-                    public Iterable<EntityReference> map( AssociationDescriptor descriptor )
-                    {
-                        AssociationDescriptor associationDescriptor;
-                        try
-                        {
-                            associationDescriptor = entityDescriptor.state()
-                                .getManyAssociationByName( descriptor.qualifiedName().name() );
-                        }
-                        catch( IllegalArgumentException e )
-                        {
-                            return Iterables.empty();
-                        }
-
-                        ManyAssociation<?> state = associationState.manyAssociationFor( associationDescriptor.accessor() );
-                        List<EntityReference> refs = new ArrayList<>( state.count() );
-                        for( Object entity : state )
-                        {
-                            refs.add( EntityReference.entityReferenceFor( entity ) );
-                        }
-                        return refs;
-                    }
-                }, new Function<AssociationDescriptor, Map<String, EntityReference>>()
-                {
-                    @Override
-                    public Map<String, EntityReference> map( AssociationDescriptor from )
-                    {
-                        // No NamedAssociations support
-                        return Collections.emptyMap();
-                    }
-                } );
-            }
-
-            return (T) builder.newInstance();
-        }
-    }
-
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/dci/Context.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/dci/Context.java
deleted file mode 100644
index 936b985..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/dci/Context.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.dci;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Context
- *
- * Base class for DCI contexts.
- *
- * Helps assigning Entity objects to Roles and to "inject" the Context object into Methodful Roles.
- */
-public abstract class Context
-{
-    protected Logger logger = LoggerFactory.getLogger( getClass() );
-
-    protected static UnitOfWorkFactory uowf;
-
-    /*
-    * Role assignment + Context "injection"
-    *
-    * Cast a Data object to a Role, set the Context object in the Role and return the RolePlayer.
-    *
-    * Requirements:
-    * 1) SomeRole interface declares a 'void setContext(YourContext context);' method
-    * 2) SomeRole.Mixin class extends RoleMixin<YourContext>
-    *
-    * The RolePlayer can then use the context pointer to lookup other Roles in the current Context.
-    */
-    protected <T> T rolePlayer( Class<T> roleClass, Object dataObject )
-    {
-        if( dataObject == null )
-        {
-            return null;
-        }
-
-        objectCanPlayRole( roleClass, dataObject );
-        T rolePlayer = roleClass.cast( dataObject );
-        setContext( rolePlayer, this );
-        return rolePlayer;
-    }
-
-    private <T> void objectCanPlayRole( Class<T> roleClass, Object dataObject )
-    {
-        if( roleClass.isAssignableFrom( dataObject.getClass() ) )
-        {
-            return;
-        }
-
-        String className;
-        if( dataObject instanceof Proxy )
-        {
-            className = Proxy.getInvocationHandler( dataObject ).getClass().getSimpleName();
-        }
-        else
-        {
-            className = dataObject.getClass().getSimpleName();
-        }
-
-        throw new IllegalArgumentException(
-            "Object '" + className + "' can't play Role of '" + roleClass.getSimpleName() + "'" );
-    }
-
-    /*
-    * Poor mans Context injection
-    * */
-    private <T> void setContext( T rolePlayer, Context context )
-    {
-        try
-        {
-            Method setContextMethod = rolePlayer.getClass().getDeclaredMethod( "setContext", context.getClass() );
-
-            // Set Context in Role
-            setContextMethod.invoke( rolePlayer, context );
-        }
-        catch( Exception e )
-        {
-            String c = context.getClass().getSimpleName();
-            String r = rolePlayer.getClass().getSimpleName();
-            String msg = "Couldn't invoke 'void setContext( " + c + " context);' on " + r + "." +
-                         "\nPlease check the following requirements: " +
-                         "\n1) 'void setContext( " + c + " context);' is declared in " + r + " interface." +
-                         "\n2) " + r + " extends RoleMixin<" + c + ">";
-            logger.error( msg, e.getMessage() );
-            e.printStackTrace();
-            throw new RuntimeException( msg );
-        }
-    }
-
-    // Entity object instantiation
-
-    protected <T, U> T rolePlayer( Class<T> roleClass, Class<U> dataClass, String entityId )
-    {
-        U dataObject = uowf.currentUnitOfWork().get( dataClass, entityId );
-        return rolePlayer( roleClass, dataObject );
-    }
-
-    protected static <T> T loadEntity( Class<T> roleClass, String entityId )
-    {
-        return uowf.currentUnitOfWork().get( roleClass, entityId );
-    }
-
-    public static void prepareContextBaseClass( UnitOfWorkFactory unitOfWorkFactory )
-    {
-        uowf = unitOfWorkFactory;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/dci/RoleMixin.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/dci/RoleMixin.java
deleted file mode 100644
index d693a87..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/dci/RoleMixin.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.dci;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.query.QueryBuilderFactory;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilderFactory;
-
-/**
- * Methodful Role implementation base class
- *
- * Helps "inject" the Context object into the Role Player.
- */
-public abstract class RoleMixin<T extends Context>
-{
-    public T context;
-
-    // Other common role services/methods could be added here...
-
-    @Structure
-    public UnitOfWorkFactory uowf;
-
-    @Structure
-    public QueryBuilderFactory qbf;
-
-    @Structure
-    public ValueBuilderFactory vbf;
-
-    /**
-     * setContext is called with method invocation in {@link Context#setContext(Object, Context)}
-     * (therefore "never used" according to IDE)
-     */
-    public void setContext( T context )
-    {
-        this.context = context;
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/model/EntityModel.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/model/EntityModel.java
deleted file mode 100644
index 0a9f138..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/model/EntityModel.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- * Copyright (c) 2013, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.model;
-
-import org.apache.wicket.model.IModel;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.conversion.DTO;
-
-/**
- * Javadoc
- */
-public class EntityModel<T extends DTO, U extends EntityComposite>
-    extends ReadOnlyModel<T>
-{
-    private Class<U> entityClass;
-    private String identity;
-    private Class<T> dtoClass;
-
-    private transient T dtoComposite;
-
-    public EntityModel( Class<U> entityClass, String identity, Class<T> dtoClass )
-    {
-        this.entityClass = entityClass;
-        this.identity = identity;
-        this.dtoClass = dtoClass;
-    }
-
-    public static <T extends DTO, U extends EntityComposite> IModel<T> of(
-        Class<U> entityClass, String identity, Class<T> dtoClass
-    )
-    {
-        return new EntityModel<T, U>( entityClass, identity, dtoClass );
-    }
-
-    public T getObject()
-    {
-        if( dtoComposite == null && identity != null )
-        {
-            dtoComposite = valueConverter.convert( dtoClass, loadEntity() );
-        }
-        return dtoComposite;
-    }
-
-    public void detach()
-    {
-        dtoComposite = null;
-    }
-
-    private U loadEntity()
-    {
-        U entity = module.currentUnitOfWork().get( entityClass, identity );
-        if( entity == null )
-        {
-            Usecase usecase = module.currentUnitOfWork().usecase();
-            throw new NoSuchEntityException( EntityReference.parseEntityReference( identity ), entityClass, usecase );
-        }
-        return entity;
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/model/JSONModel.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/model/JSONModel.java
deleted file mode 100644
index 2abc2b8..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/model/JSONModel.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.model;
-
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.api.value.ValueSerializer;
-
-/**
- * Model that can serialize/de-serialize an object to/from a JSON string.
- */
-public class JSONModel<T, U extends ValueComposite>
-    extends ReadOnlyModel<T>
-{
-    private Class<U> valueCompositeClass;
-    private String json;
-    private transient T valueComposite;
-
-    @SuppressWarnings( "unchecked" )
-    public JSONModel( T valueComposite, Class<U> valueCompositeClass )
-    {
-        json = module.findService( ValueSerializer.class ).get().serialize( (U) valueComposite );;
-        this.valueCompositeClass = valueCompositeClass;
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public static <T, U extends ValueComposite> JSONModel<T, U> of( T value )
-    {
-        if( !( value instanceof ValueComposite ) )
-        {
-            throw new RuntimeException( value + " has to be an instance of a ValueComposite." );
-        }
-
-        // Get ValueComposite interface
-        Class<U> valueCompositeClass = (Class<U>) qi4j.valueDescriptorFor( value ).valueType().mainType();
-
-        return new JSONModel<T, U>( value, valueCompositeClass );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public T getObject()
-    {
-        if( valueComposite == null && json != null )
-        {
-            // De-serialize
-            valueComposite = (T) module.newValueFromSerializedState( valueCompositeClass, json ); // Unchecked cast
-        }
-        return valueComposite;
-    }
-
-    public void detach()
-    {
-        valueComposite = null;
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/model/Queries.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/model/Queries.java
deleted file mode 100644
index a2ce47b..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/model/Queries.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.model;
-
-import java.io.Serializable;
-import org.qi4j.api.query.QueryBuilderFactory;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-
-/**
- * Queries base class
- */
-public class Queries
-    implements Serializable // For Wicket (don't remove)
-{
-    static protected UnitOfWorkFactory uowf;
-    static protected QueryBuilderFactory qbf;
-
-    public static void prepareQueriesBaseClass( UnitOfWorkFactory unitOfWorkFactory,
-                                                QueryBuilderFactory queryBuilderFactory
-    )
-    {
-        uowf = unitOfWorkFactory;
-        qbf = queryBuilderFactory;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/model/QueryModel.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/model/QueryModel.java
deleted file mode 100644
index 9f374ac..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/model/QueryModel.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.model;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.query.Query;
-
-/**
- * Callback Wicket model that holds a Zest Query object that can be called when needed to
- * retrieve fresh data.
- */
-public abstract class QueryModel<T, U extends EntityComposite>
-    extends ReadOnlyModel<List<T>>
-{
-    private Class<T> dtoClass;
-    private transient List<T> dtoList;
-
-    public QueryModel( Class<T> dtoClass )
-    {
-        this.dtoClass = dtoClass;
-    }
-
-    public List<T> getObject()
-    {
-        if( dtoList != null )
-        {
-            return dtoList;
-        }
-
-        dtoList = new ArrayList<T>();
-        for( U entity : getQuery() )
-        {
-            dtoList.add( getValue( entity ) );
-        }
-
-        return dtoList;
-    }
-
-    // Callback to retrieve the (unserializable) Zest Query object
-    public abstract Query<U> getQuery();
-
-    public T getValue( U entity )
-    {
-        return valueConverter.convert( dtoClass, entity );
-    }
-
-    public void detach()
-    {
-        dtoList = null;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/model/ReadOnlyModel.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/model/ReadOnlyModel.java
deleted file mode 100644
index f357356..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/model/ReadOnlyModel.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.model;
-
-import org.apache.wicket.model.IModel;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.structure.Module;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.conversion.EntityToDTOService;
-
-/**
- * Abstract base model for Wicket model objects taking Zest objects.
- */
-public abstract class ReadOnlyModel<T>
-    implements IModel<T>
-{
-    private static final long serialVersionUID = 1L;
-
-    static protected EntityToDTOService valueConverter;
-    static protected Qi4j qi4j;
-    static protected Module module;
-
-    /**
-     * This default implementation of setObject unconditionally throws an
-     * UnsupportedOperationException. Since the method is final, any subclass is effectively a
-     * read-only model.
-     *
-     * @param object The object to set into the model
-     *
-     * @throws UnsupportedOperationException
-     */
-    public final void setObject( final T object )
-    {
-        throw new UnsupportedOperationException( "Model " + getClass() +
-                                                 " does not support setObject(Object)" );
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder( "Model:classname=[" );
-        sb.append( getClass().getName() ).append( "]" );
-        return sb.toString();
-    }
-
-    public static void prepareModelBaseClass( Module m,
-                                              Qi4j api,
-                                              EntityToDTOService entityToDTO
-    )
-    {
-        module = m;
-        qi4j = api;
-        valueConverter = entityToDTO;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/color/CorrectColor.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/color/CorrectColor.java
deleted file mode 100644
index d363202..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/color/CorrectColor.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.color;
-
-import org.apache.wicket.AttributeModifier;
-
-/**
- * Javadoc
- */
-public class CorrectColor extends AttributeModifier
-{
-    public CorrectColor( Boolean condition )
-    {
-        super( "class", condition ? "correctColor" : "VA_REMOVE" );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/color/ErrorColor.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/color/ErrorColor.java
deleted file mode 100644
index 6a2938e..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/color/ErrorColor.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.color;
-
-import org.apache.wicket.AttributeModifier;
-
-/**
- * Javadoc
- */
-public class ErrorColor
-        extends AttributeModifier
-{
-
-    public ErrorColor( Boolean condition )
-    {
-        super( "class", condition ? "errorColor" : "VA_REMOVE" );
-    }
-
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/form/AbstractForm.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/form/AbstractForm.java
deleted file mode 100644
index a5d6e87..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/form/AbstractForm.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.form;
-
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.markup.html.form.Button;
-import org.apache.wicket.markup.html.form.CheckBox;
-import org.apache.wicket.markup.html.form.FormComponent;
-import org.apache.wicket.markup.html.form.RadioChoice;
-import org.apache.wicket.markup.html.form.StatelessForm;
-import org.apache.wicket.util.visit.IVisit;
-import org.apache.wicket.util.visit.IVisitor;
-
-/**
- *
- */
-//public abstract class AbstractForm<T> extends Form<T>
-public abstract class AbstractForm<T> extends StatelessForm<T>
-{
-    public AbstractForm( String id )
-    {
-        super( id );
-    }
-
-    public AbstractForm()
-    {
-        super( "form" );
-    }
-
-    public void focusFirstError( final AjaxRequestTarget target )
-    {
-        visitFormComponents( new IVisitor<FormComponent<?>, Void>()
-        {
-            public void component( FormComponent<?> fc, IVisit<Void> visit )
-            {
-                if( isOtherComponent( fc ) || fc.isValid() )
-                {
-                    return;
-                }
-
-                target.focusComponent( fc );
-                visit.stop();
-            }
-        } );
-    }
-
-    private boolean isOtherComponent( FormComponent<?> fc )
-    {
-        return fc instanceof Button || fc instanceof CheckBox || fc instanceof RadioChoice;
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/form/DateTextFieldWithPicker.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/form/DateTextFieldWithPicker.java
deleted file mode 100644
index 6617619..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/form/DateTextFieldWithPicker.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.form;
-
-import com.google.code.joliratools.StatelessAjaxEventBehavior;
-import java.util.Date;
-import java.util.Map;
-import org.apache.wicket.Component;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.datetime.DateConverter;
-import org.apache.wicket.datetime.PatternDateConverter;
-import org.apache.wicket.datetime.markup.html.form.DateTextField;
-import org.apache.wicket.devutils.stateless.StatelessComponent;
-import org.apache.wicket.extensions.yui.calendar.DatePicker;
-import org.apache.wicket.markup.html.IHeaderResponse;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.apache.wicket.validation.validator.DateValidator;
-import org.joda.time.DateTime;
-import org.joda.time.LocalDate;
-import org.joda.time.LocalTime;
-
-//import org.wicketstuff.stateless.StatelessAjaxEventBehavior;
-
-/**
- * {@link DateTextField} with a {@link DatePicker}.
- */
-@StatelessComponent
-public class DateTextFieldWithPicker extends DateTextField
-{
-    DatePicker datePicker;
-
-    // Configurable widget options
-    LocalDate earliestDate;
-    LocalDate selectedDate;
-
-    final static String YUI_DATE_FORMAT = "MM/dd/yyyy";
-
-    public DateTextFieldWithPicker( String id, String label, Component model )
-    {
-//      this( id, new PropertyModel<Date>( model, id ), new StyleDateConverter( "S-", true ) );
-        this( id, label, new PropertyModel<Date>( model, id ), new PatternDateConverter( "yyyy-MM-dd", true ) );
-    }
-
-    public DateTextFieldWithPicker( String id, String label, IModel<Date> model, DateConverter converter )
-    {
-        super( id, model, converter );
-
-        // Make the text field reachable by Ajax requests
-        setOutputMarkupId( true );
-
-        // Set required as default
-        setRequired( true );
-
-        // Add Date Picker with callback configuration
-        add( newDatePicker().setShowOnFieldClick( true ) );
-
-        setNonEmptyLabel( label );
-
-        // Show calendar if tabbing into the text field (weird it isn't default)
-        add( new StatelessAjaxEventBehavior( "onfocus" )
-        {
-            @Override
-            protected void onEvent( AjaxRequestTarget target )
-            {
-                String componentId = getComponent().getMarkupId();
-                String widgetId = componentId + "DpJs";
-                target.appendJavaScript(
-                    "Wicket.DateTime.showCalendar(" +
-                    "YAHOO.wicket['" + widgetId + "'], " +
-                    "document.getElementById('" + componentId + "').value, " +
-                    "'yyyy-MM-dd');"
-                );
-            }
-
-            @Override
-            protected PageParameters getPageParameters()
-            {
-                return null;
-            }
-        } );
-
-//        add( new StatelessAjaxEventBehavior( "onBlur" )
-//        {
-//            @Override
-//            protected void onEvent( AjaxRequestTarget target )
-//            {
-//                String componentId = getComponent().getMarkupId();
-//                String widgetId = componentId + "DpJs";
-//                target.appendJavaScript(
-//                      "Wicket.DateTime.showCalendar(" +
-//                            "YAHOO.wicket['" + widgetId + "'], " +
-//                            "document.getElementById('" + componentId + "').value, " +
-//                            "'yyyy-MM-dd');" +
-//                      "YAHOO.wicket['" + widgetId + "'].hide();" );
-//            }
-//
-//            @Override
-//            protected PageParameters getPageParameters()
-//            {
-//                return null;
-//            }
-//        } );
-    }
-
-    private void setNonEmptyLabel( String label )
-    {
-        if( label == null )
-        {
-            return;
-        }
-
-        if( label.isEmpty() )
-        {
-            throw new IllegalArgumentException( "Can't set an empty label on the drop down selector." );
-        }
-
-        setLabel( Model.of( label ) );
-    }
-
-    /**
-     * The DatePicker that gets added to the DateTextField component. Users may override this method
-     * with a DatePicker of their choice.
-     *
-     * @return a new {@link DatePicker} instance
-     */
-    protected DatePicker newDatePicker()
-    {
-        return new DatePicker()
-        {
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            protected void configure( final Map<String, Object> widgetProperties,
-                                      final IHeaderResponse response, final Map<String, Object> initVariables
-            )
-            {
-                super.configure( widgetProperties, response, initVariables );
-
-                DateTextFieldWithPicker.this.configure( widgetProperties );
-            }
-        };
-    }
-
-    /**
-     * Gives overriding classes the option of adding (or even changing/ removing) configuration
-     * properties for the javascript widget. See <a
-     * href="http://developer.yahoo.com/yui/calendar/">the widget's documentation</a> for the
-     * available options. If you want to override/ remove properties, you should call
-     * super.configure(properties) first. If you don't call that, be aware that you will have to
-     * call {@literal #localize(Map)} manually if you like localized strings to be added.
-     *
-     * @param widgetProperties the current widget properties
-     */
-    protected void configure( Map<String, Object> widgetProperties )
-    {
-        // Set various YUI calendar options - add more if necessary
-        widgetProperties.put( "mindate", getEarliestDateStr() );
-        widgetProperties.put( "selected", getSelectedDateStr() );
-    }
-
-    public DateTextFieldWithPicker earliestDate( LocalDate newEarliestDate )
-    {
-        if( selectedDate != null && newEarliestDate.isAfter( selectedDate ) )
-        {
-            throw new IllegalArgumentException( "Earliest date can't be before selected day." );
-        }
-
-        earliestDate = newEarliestDate;
-
-        // Input field validation - date should be _after_ minimumDate (not the same)
-        LocalDate minimumDate = newEarliestDate.minusDays( 1 );
-        Date convertedMinimumDate = new DateTime( minimumDate.toDateTime( new LocalTime() ) ).toDate();
-        add( DateValidator.minimum( convertedMinimumDate ) );
-
-        return this;
-    }
-
-    // Add latestDate(..) + other configuration options if needed..
-
-    public DateTextFieldWithPicker selectedDate( LocalDate newSelectedDate )
-    {
-        if( earliestDate != null && newSelectedDate.isBefore( earliestDate ) )
-        {
-            throw new IllegalArgumentException( "Selected date can't be before earliest day." );
-        }
-
-        selectedDate = newSelectedDate;
-
-        return this;
-    }
-
-    private String getSelectedDateStr()
-    {
-        if( selectedDate != null )
-        {
-            return selectedDate.toString( YUI_DATE_FORMAT );
-        }
-
-        // Select today or earliest date (if later) as default
-        return earliestDate == null ?
-               new LocalDate().toString( YUI_DATE_FORMAT ) :
-               earliestDate.toString( YUI_DATE_FORMAT );
-    }
-
-    private String getEarliestDateStr()
-    {
-        return earliestDate == null ? "" : earliestDate.toString( YUI_DATE_FORMAT );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/form/SelectorInForm.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/form/SelectorInForm.java
deleted file mode 100644
index 226e994..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/form/SelectorInForm.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.form;
-
-import java.util.List;
-import org.apache.wicket.markup.html.form.DropDownChoice;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.model.util.ListModel;
-
-/**
- * Drop down list that resolves properties against a form
- */
-public class SelectorInForm extends DropDownChoice<String>
-{
-    PropertyModel<String> disablingPropertyModel;
-    String disablingValue = "";
-
-    public SelectorInForm( String property, String label, List<String> choices, Form form )
-    {
-        super( property + "Selector", new PropertyModel<String>( form, property ), new ListModel<String>( choices ) );
-        setNonEmptyLabel( label );
-        setOutputMarkupId( true );
-    }
-
-    public SelectorInForm( String property, String label, List<String> choices, Form form, String disablingProperty )
-    {
-        super( property + "Selector", new PropertyModel<String>( form, property ), new ListModel<String>( choices ) );
-        disablingPropertyModel = new PropertyModel<String>( form, disablingProperty );
-        setNonEmptyLabel( label );
-        setOutputMarkupId( true );
-    }
-
-    private void setNonEmptyLabel( String label )
-    {
-        if( label == null )
-        {
-            return;
-        }
-
-        setLabel( Model.of( label ) );
-    }
-
-    @Override
-    protected boolean isDisabled( final String currentValue, int index, String selected )
-    {
-        if( disablingPropertyModel != null )
-        {
-            disablingValue = disablingPropertyModel.getObject();
-        }
-
-        return currentValue.equals( disablingValue );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/link/LinkPanel.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/link/LinkPanel.java
deleted file mode 100644
index ca9fb67..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/link/LinkPanel.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.link;
-
-import org.apache.wicket.Page;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.link.BookmarkablePageLink;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-
-/**
- * Link panel for displaying a bookmarkable link
- */
-public class LinkPanel extends Panel
-{
-    public <T extends Page> LinkPanel( String id, Class<T> pageClass, String rowId )
-    {
-        this( id, pageClass, rowId, rowId );
-    }
-
-    public <T extends Page> LinkPanel( String id, Class<T> pageClass, String rowId, String label )
-    {
-        super( id );
-
-        PageParameters pageParameters = new PageParameters().set( 0, rowId );
-        BookmarkablePageLink<Void> link = new BookmarkablePageLink<Void>( "link", pageClass, pageParameters );
-        link.add( new Label( "label", label ) );
-        add( link );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/page/BaseWebPage.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/page/BaseWebPage.java
deleted file mode 100644
index 8b81bc5..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/page/BaseWebPage.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.page;
-
-import org.apache.wicket.markup.html.WebPage;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.qi4j.api.composite.TransientBuilderFactory;
-import org.qi4j.api.composite.TransientComposite;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Generic Wicket base page
- *
- * Convenience access to common resources
- */
-public class BaseWebPage extends WebPage
-{
-    public Logger logger = LoggerFactory.getLogger( getClass() );
-
-    static protected TransientBuilderFactory tbf;
-
-    public BaseWebPage( PageParameters pageParameters )
-    {
-        super( pageParameters );
-    }
-
-    public BaseWebPage()
-    {
-    }
-
-    public static <T extends TransientComposite> T query( Class<T> queryClass )
-    {
-        return tbf.newTransient( queryClass );
-    }
-
-    public static void prepareBaseWebPageClass( TransientBuilderFactory transientBuilderFactory )
-    {
-        tbf = transientBuilderFactory;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/prevnext/PrevNext.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/prevnext/PrevNext.java
deleted file mode 100644
index d1fcafa..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/prevnext/PrevNext.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.prevnext;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import org.apache.wicket.AttributeModifier;
-import org.apache.wicket.MetaDataKey;
-import org.apache.wicket.Page;
-import org.apache.wicket.Session;
-import org.apache.wicket.devutils.stateless.StatelessComponent;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.link.BookmarkablePageLink;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-
-/**
- * Previous/Next arrows navigation panel with list of ids in session.
- *
- * Takes care of showing disabled icons at beginning/end.
- */
-@StatelessComponent
-public class PrevNext extends Panel
-{
-    private static final MetaDataKey<ArrayList<String>> PREV_NEXT_PANEL_KEY = new MetaDataKey<ArrayList<String>>()
-    {
-        private static final long serialVersionUID = 1L;
-    };
-
-    public static void registerIds( Session session, ArrayList<String> ids )
-    {
-        if( ids == null || ids.isEmpty() )
-        {
-            throw new RuntimeException( "Please register a list of ids." );
-        }
-
-        session.setMetaData( PREV_NEXT_PANEL_KEY, ids );
-        session.bind();
-    }
-
-    public static void addId( Session session, String id )
-    {
-        if( id == null || id.isEmpty() )
-        {
-            throw new RuntimeException( "Can't register empty id." );
-        }
-
-        ArrayList<String> ids = session.getMetaData( PREV_NEXT_PANEL_KEY );
-        if( ids == null || ids.isEmpty() )
-        {
-            ids = new ArrayList<String>();
-        }
-
-        ids.add( id );
-        session.setMetaData( PREV_NEXT_PANEL_KEY, ids );
-        session.bind();
-    }
-
-    public PrevNext( String id, Class<? extends Page> pageClass, String actualId )
-    {
-        super( id );
-
-        List<String> ids = getSession().getMetaData( PREV_NEXT_PANEL_KEY );
-
-        if( ids == null || ids.size() == 0 )
-        {
-            setEnabled( false );
-            setVisible( false );
-            return;
-        }
-
-        String prev = null;
-        String current;
-        for( Iterator<String> it = ids.iterator(); it.hasNext(); )
-        {
-            current = it.next();
-            if( current.equals( actualId ) )
-            {
-                if( prev == null )
-                {
-                    add( new WebMarkupContainer( "prev" ).add( new AttributeModifier( "class", "prevDisabled" ) ) );
-                }
-                else
-                {
-                    add( new BookmarkablePageLink<Void>( "prev", pageClass, new PageParameters().set( 0, prev ) ) );
-                }
-
-                if( !it.hasNext() )
-                {
-                    add( new WebMarkupContainer( "next" ).add( new AttributeModifier( "class", "nextDisabled" ) ) );
-                }
-                else
-                {
-                    add( new BookmarkablePageLink<Void>( "next", pageClass, new PageParameters().set( 0, it.next() ) ) );
-                }
-
-                return;
-            }
-            prev = current;
-        }
-
-        throw new RuntimeException( "Passed tracking id was not found in the PrevNextSession." );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/tabs/TabsPanel.java b/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/tabs/TabsPanel.java
deleted file mode 100644
index c35f15f..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/java/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/tabs/TabsPanel.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.infrastructure.wicket.tabs;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-import org.apache.wicket.Application;
-import org.apache.wicket.AttributeModifier;
-import org.apache.wicket.MetaDataKey;
-import org.apache.wicket.Page;
-import org.apache.wicket.devutils.stateless.StatelessComponent;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.link.BookmarkablePageLink;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.markup.repeater.RepeatingView;
-
-/**
- * Tabs panel that stores tab data as application meta data.
- */
-@StatelessComponent
-public class TabsPanel extends Panel
-{
-    public static final MetaDataKey<LinkedHashMap<Class, String[]>> TABS_PANEL_KEY = new MetaDataKey<LinkedHashMap<Class, String[]>>()
-    {
-        public static final long serialVersionUID = 1L;
-    };
-
-    public static <T extends Page> void registerTab( Application app, Class<T> clazz, String ref, String label )
-    {
-        Map<Class, String[]> tabsInfo = app.getMetaData( TABS_PANEL_KEY );
-
-        if( tabsInfo == null || tabsInfo.isEmpty() )
-        {
-            tabsInfo = new LinkedHashMap<Class, String[]>();
-        }
-
-        tabsInfo.put( clazz, new String[]{ ref, label } );
-        app.setMetaData( TABS_PANEL_KEY, tabsInfo );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public TabsPanel( String activeTab )
-    {
-        super( "tabsPanel" );
-
-        Map<Class, String[]> tabs = getApplication().getMetaData( TABS_PANEL_KEY );
-        if( tabs == null || tabs.isEmpty() )
-        {
-            throw new RuntimeException( "Please register one or more tabs." );
-        }
-
-        RepeatingView tabsView = new RepeatingView( "tabsView" );
-
-        // Loop "mounted" tabs
-        for( Map.Entry<Class, String[]> tab : tabs.entrySet() )
-        {
-            Class pageClass = tab.getKey();
-            String tabReference = tab.getValue()[ 0 ];
-            String tabLabel = tab.getValue()[ 1 ];
-
-            WebMarkupContainer tabView = new WebMarkupContainer( tabsView.newChildId() );
-            if( tabReference.equals( activeTab ) )
-            {
-                tabView.add( new AttributeModifier( "id", "current" ) );
-            }
-
-            BookmarkablePageLink link = new BookmarkablePageLink( "link", pageClass );  // unchecked
-
-            Label label = new Label( "label", tabLabel );
-
-            tabsView.add( tabView.add( link.add( label ) ) );
-        }
-        add( tabsView );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/log4j.properties b/samples/dci-cargo/dcisample_a/src/main/resources/log4j.properties
deleted file mode 100644
index 02c5759..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/log4j.properties
+++ /dev/null
@@ -1,29 +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.
-
-log4j.appender.Stdout=org.apache.log4j.ConsoleAppender
-log4j.appender.Stdout.layout=org.apache.log4j.PatternLayout
-log4j.appender.Stdout.layout.conversionPattern=%-5p - %-26.26c{1} - %m\n
-
-log4j.rootLogger=INFO,Stdout
-#log4j.rootLogger=DEBUG,Stdout
-
-#log4j.logger.org.apache.wicket=DEBUG
-#log4j.logger.org.apache.wicket.protocol.http.HttpSessionStore=DEBUG
-#log4j.logger.org.apache.wicket.version=DEBUG
-#log4j.logger.org.apache.wicket.RequestCycle=DEBUG
-#log4j.logger.org.apache.wicket.util.resource=DEBUG
-
-#log4j.logger.org.qi4j.index.rdf.query.internal.RdfQueryParserImpl=DEBUG, Stdout
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/BasePage.html b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/BasePage.html
deleted file mode 100644
index 87ec4f6..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/BasePage.html
+++ /dev/null
@@ -1,108 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<head>
-    <title>DCI sample (version A)</title>
-    <link href="css/style.css" rel="stylesheet" type="text/css"/>
-</head>
-<body>
-
-<div class="left">
-    <div class="headline"><a href="/">DCI sample</a></div>
-    <div id="toggle">
-        <a href="#" class="closed" wicket:id="toggleLinks">Qi4j/Wicket port of the DDD sample application to the DCI
-            paradigm.</a>
-    </div>
-
-    <div id="links" wicket:id="links"></div>
-    <wicket:fragment wicket:id="linksFragment">
-        <br>
-        <table>
-            <thead>
-            <tr>
-                <td>DCI</td>
-                <td>DDD</td>
-                <td>Qi4j</td>
-                <td>Wicket</td>
-                <td>Marc Grue</td>
-            </tr>
-            </thead>
-            <tbody>
-            <tr>
-                <td valign="top">
-                    <a href="http://groups.google.com/group/object-composition/topics?hl=en"
-                       target="_blank">Forum</a><br>
-                    <a href="https://github.com/DCI/dci-sample" target="_blank">Github</a><br>
-                    <a href="http://en.wikipedia.org/wiki/Data,_Context,_and_Interaction" target="_blank">Wiki</a><br>
-                    <a href="http://folk.uio.no/trygver/2010/DCIExecutionModel.pdf" target="_blank">Execution Model</a>
-                </td>
-                <td valign="top">
-                    <a href="http://dddsample.sourceforge.net/" target="_blank">Sample</a><br>
-                    <a href="http://tech.groups.yahoo.com/group/domaindrivendesign/" target="_blank">Forum</a>
-                </td>
-                <td valign="top">
-                    <a href="https://zest.apache.org/" target="_blank">Website</a><br>
-                    <a href="https://zest.apache.org/community/get_help.html" target="_blank">Forum</a><br>
-                    <a href="https://zest.apache.org/download.html" target="_blank">Download</a><br>
-                    <a href="https://zest.apache.org/java/latest/howto-depend-on-zest.html" target="_blank">Maven</a><br>
-                    <a href="https://github.com/apache/zest-java" target="_blank">Github</a>
-                </td>
-                <td valign="top">
-                    <a href="http://wicket.apache.org/" target="_blank">Website</a><br>
-                    <a href="http://apache-wicket.1842946.n4.nabble.com/Users-forum-f1842947.html"
-                       target="_blank">Forum</a><br>
-                    <a href="http://wicketstuff.org/wicket/index.html" target="_blank">Examples</a><br>
-                    <a href="https://cwiki.apache.org/WICKET/" target="_blank">Wiki</a><br>
-                    <a href="http://apache.dataphone.se/wicket/1.5.1/" target="_blank">Download</a>
-                </td>
-                <td valign="top">
-                    <a href="http://marcgrue.com/" target="_blank">Overview</a><br>
-                    <a href="http://marcgrue.com/dci/dci-sample/what-the-system-is" target="_blank">What-the-system-is</a><br>
-                    <a href="http://marcgrue.com/dci/process-thinking" target="_blank">Process Thinking</a><br>
-                </td>
-                <td valign="top">
-                    <a href="http://www.amazon.co.uk/gp/product/0470684208/ref=as_li_ss_tl?ie=UTF8&tag=doubtrol-21&linkCode=as2&camp=1634&creative=19450&creativeASIN=0470684208"
-                       target="_blank">Lean Architecture</a><img
-                        src="http://www.assoc-amazon.co.uk/e/ir?t=&l=as2&o=2&a=0470684208" width="1" height="1"
-                        border="0" alt="" style="border:none !important; margin:0px !important;"/><br>
-                    <a href="http://www.amazon.co.uk/gp/product/0201702258/ref=as_li_ss_tl?ie=UTF8&tag=doubtrol-21&linkCode=as2&camp=1634&creative=19450&creativeASIN=0201702258"
-                       target="_blank">Writing Effective Use Cases</a><img
-                        src="http://www.assoc-amazon.co.uk/e/ir?t=doubtrol-21&l=as2&o=2&a=0201702258" width="1"
-                        height="1" border="0" alt="" style="border:none !important; margin:0px !important;"/>
-
-                </td>
-            </tr>
-            </tbody>
-        </table>
-    </wicket:fragment>
-</div>
-
-<div class="right">
-    <b>Java-Qi4j-Wicket<br>
-        Version <span wicket:id="version">[X.Y.Z]</span></b><br>
-    Created 2011-10-04<br>
-    Modified 2011-10-04<br>
-    by Marc Grue
-</div>
-
-<div wicket:id="tabsPanel">[tabs]</div>
-
-<!--Inherited pages go here-->
-<wicket:child/>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/BookNewCargoPage.html b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/BookNewCargoPage.html
deleted file mode 100644
index 80f9dc3..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/BookNewCargoPage.html
+++ /dev/null
@@ -1,71 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:extend>
-    <div class="headerMenu">
-        Book new cargo
-        <wicket:link><a href="CargoListPage.html">List of Cargos</a></wicket:link>
-    </div>
-
-    <form wicket:id="form">
-        <div wicket:id="feedback"></div>
-        <table>
-            <tbody>
-            <tr>
-                <td>Origin</td>
-                <td>
-                    <select wicket:id="originSelector">
-                        <option>Markup1</option>
-                        <option>Markup2</option>
-                    </select>
-                </td>
-                <td>
-                    <div wicket:id="originFeedback">&nbsp;</div>
-                </td>
-            </tr>
-            <tr>
-                <td>Destination</td>
-                <td>
-                    <select wicket:id="destinationSelector"></select>
-                </td>
-                <td>
-                    <div wicket:id="destinationFeedback">&nbsp;</div>
-                </td>
-            </tr>
-            <tr>
-                <td>Arrival deadline</td>
-                <td>
-                    <input type="text" wicket:id="deadline"/>
-                </td>
-                <td>
-                    <div wicket:id="deadlineFeedback">&nbsp;</div>
-                </td>
-            </tr>
-            </tbody>
-            <tfoot>
-            <tr>
-                <td></td>
-                <td>
-                    <input type="submit" value="Book" wicket:id="book"/>
-                </td>
-            </tr>
-            </tfoot>
-        </table>
-    </form>
-
-</wicket:extend>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/BookingBasePage.html b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/BookingBasePage.html
deleted file mode 100644
index 0af9860..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/BookingBasePage.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:extend>
-    <div id="box">
-        <wicket:child/>
-    </div>
-</wicket:extend>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/CargoDetailsPage.html b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/CargoDetailsPage.html
deleted file mode 100644
index 8b3b1b2..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/CargoDetailsPage.html
+++ /dev/null
@@ -1,89 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:extend>
-
-    <div wicket:id="prevNext"></div>
-    <div class="headerMenu">
-        Details for cargo <span wicket:id="trackingId">[trackingId]</span>
-        <wicket:link>
-            <a href="CargoListPage.html">List of Cargos</a>
-            <a href="BookNewCargoPage.html">Book new cargo</a>
-        </wicket:link>
-    </div>
-
-    <table class="styleLeftColumn">
-        <tr>
-            <td>Origin</td>
-            <td wicket:id="origin"></td>
-        </tr>
-        <tr>
-            <td>Destination</td>
-            <td wicket:id="destination"></td>
-            <td wicket:id="changeDestination"></td>
-        </tr>
-        <tr>
-            <td>Arrival deadline</td>
-            <td wicket:id="deadline"></td>
-        </tr>
-        <tr>
-            <td>Routing status</td>
-            <td wicket:id="routingStatus"></td>
-            <td wicket:id="routingAction"></td>
-        </tr>
-        <wicket:container wicket:id="delivery"></wicket:container>
-        <wicket:fragment wicket:id="deliveryFragment">
-            <tr>
-                <td>Transport status</td>
-                <td wicket:id="transportStatus"></td>
-            </tr>
-            <tr>
-                <td valign="top">Delivery status</td>
-                <td wicket:id="deliveryStatus"></td>
-            </tr>
-        </wicket:fragment>
-    </table>
-
-    <wicket:container wicket:id="itinerary"></wicket:container>
-    <wicket:fragment wicket:id="itineraryFragment">
-        <h4>Itinerary</h4>
-        <table>
-            <thead>
-            <tr>
-                <td>Voyage</td>
-                <td colspan="2">Load</td>
-                <td colspan="2">Unload</td>
-            </tr>
-            </thead>
-            <tbody>
-            <tr wicket:id="legs">
-                <td wicket:id="voyage"></td>
-                <td wicket:id="loadLocation"></td>
-                <td wicket:id="loadTime"></td>
-                <td wicket:id="unloadLocation"></td>
-                <td wicket:id="unloadTime"></td>
-            </tr>
-            </tbody>
-        </table>
-    </wicket:fragment>
-
-    <div wicket:id="handlingHistoryPanel"></div>
-
-    <div wicket:id="nextHandlingEventPanel"></div>
-
-</wicket:extend>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/CargoListPage.html b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/CargoListPage.html
deleted file mode 100644
index 850773a..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/CargoListPage.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:extend>
-    <div class="headerMenu">
-        List of Cargos
-        <wicket:link><a href="BookNewCargoPage.html">Book new cargo</a></wicket:link>
-    </div>
-
-    <table>
-        <thead>
-        <tr>
-            <td>Tracking Id</td>
-            <td>Origin</td>
-            <td>Destination</td>
-            <td>Arrival deadline</td>
-            <td>Routing status</td>
-            <td>Transport status</td>
-            <td>Delivery status</td>
-        </tr>
-        </thead>
-        <tbody>
-        <tr wicket:id="list">
-            <td wicket:id="trackingId"></td>
-            <td wicket:id="origin"></td>
-            <td align="center" wicket:id="destination"></td>
-            <td align="center" wicket:id="deadline"></td>
-            <td wicket:id="routingStatus"></td>
-            <td wicket:id="transportStatus"></td>
-            <td wicket:id="deliveryStatus"></td>
-        </tr>
-        </tbody>
-    </table>
-</wicket:extend>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/ChangeDestinationPage.html b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/ChangeDestinationPage.html
deleted file mode 100644
index 892722a..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/ChangeDestinationPage.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:extend>
-
-    <div class="headerMenu">
-        Change destination for cargo <span wicket:id="trackingId">[trackingId]</span>
-        <wicket:link>
-            <a href="CargoListPage.html">List of Cargos</a>
-            <a href="BookNewCargoPage.html">Book new cargo</a>
-        </wicket:link>
-    </div>
-
-    <form wicket:id="form">
-        <div wicket:id="usecaseFeedback"></div>
-        <table>
-            <tbody>
-            <tr>
-                <td>Origin</td>
-                <td wicket:id="origin"></td>
-            </tr>
-            <tr>
-                <td>Old destination</td>
-                <td wicket:id="destination"></td>
-            </tr>
-            <tr>
-                <td>New destination</td>
-                <td>
-                    <select wicket:id="destinationSelector"></select>
-                </td>
-                <td wicket:id="destinationFeedback"></td>
-            </tr>
-            </tbody>
-            <tfoot>
-            <tr>
-                <td></td>
-                <td>
-                    <input type="submit" value="Change destination" wicket:id="submit"/>
-                </td>
-            </tr>
-            </tfoot>
-        </table>
-    </form>
-
-</wicket:extend>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/RouteCargoPage.html b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/RouteCargoPage.html
deleted file mode 100644
index 7561f1f..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/RouteCargoPage.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:extend>
-
-    <div class="headerMenu">
-        Assign route for cargo <span wicket:id="trackingId">[trackingId]</span>
-        <wicket:link>
-            <a href="CargoListPage.html">List of Cargos</a>
-            <a href="BookNewCargoPage.html">Book new cargo</a>
-        </wicket:link>
-    </div>
-
-    <span wicket:id="feedback"></span>
-
-    <span wicket:id="routes">
-        <span wicket:id="route"></span><br/>
-    </span>
-
-</wicket:extend>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/RoutePanel.html b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/RoutePanel.html
deleted file mode 100644
index f7b8d82..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/booking/RoutePanel.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:panel>
-    <h4 wicket:id="routeHeader"></h4>
-    <span wicket:id="routeFeedback"></span>
-
-    <table>
-        <thead>
-        <tr>
-            <td>Voyage</td>
-            <td colspan="2">From</td>
-            <td colspan="2">To</td>
-        </tr>
-        </thead>
-        <tbody>
-        <tr wicket:id="legs">
-            <td wicket:id="voyage"></td>
-            <td wicket:id="loadLocation"></td>
-            <td wicket:id="loadTime"></td>
-            <td wicket:id="unloadLocation"></td>
-            <td wicket:id="unloadTime"></td>
-        </tr>
-        </tbody>
-    </table>
-    <form wicket:id="form">
-        <input type="submit" value="Assign cargo to this route" wicket:id="assign"/>
-    </form>
-</wicket:panel>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/handling/RegisterHandlingEventPage.html b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/handling/RegisterHandlingEventPage.html
deleted file mode 100644
index 537b3b0..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/handling/RegisterHandlingEventPage.html
+++ /dev/null
@@ -1,70 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:extend>
-    <div id="box">
-
-        <div class="headerMenu">Register handling event</div>
-
-        <form wicket:id="form">
-            <div wicket:id="feedback"></div>
-            <table>
-                <tbody>
-                <tr>
-                    <td>Completion</td>
-                    <td>
-                        <input type="text" wicket:id="completion"/>
-                    </td>
-                </tr>
-                <tr>
-                    <td>Cargo</td>
-                    <td>
-                        <select wicket:id="trackingIdSelector"></select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>Event type</td>
-                    <td>
-                        <select wicket:id="eventTypeSelector"></select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>Voyage</td>
-                    <td>
-                        <select wicket:id="voyageNumberSelector"></select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>Location</td>
-                    <td>
-                        <select wicket:id="unLocodeSelector"></select>
-                    </td>
-                </tr>
-                </tbody>
-                <tfoot>
-                <tr>
-                    <td></td>
-                    <td>
-                        <input type="submit" value="Register" wicket:id="register"/>
-                    </td>
-                </tr>
-                </tfoot>
-            </table>
-        </form>
-    </div>
-</wicket:extend>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/handling/RegisterHandlingEventPage.properties b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/handling/RegisterHandlingEventPage.properties
deleted file mode 100644
index d8a7552..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/handling/RegisterHandlingEventPage.properties
+++ /dev/null
@@ -1,21 +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.
-
-handlingEvent.UNKNOWN=ERROR: *** UNKNOWN EVENT TYPE ***
-handlingEvent.RECEIVE=Received in ${location}.
-handlingEvent.LOAD=Loaded onto voyage ${voyage} in port ${location}.
-handlingEvent.UNLOAD=Unloaded from voyage ${voyage} in port ${location}.
-handlingEvent.CLAIM=Claimed in port ${location} by customer.
-handlingEvent.CUSTOMS=In customs.
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/HandlingHistoryPanel.html b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/HandlingHistoryPanel.html
deleted file mode 100644
index f89e3ae..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/HandlingHistoryPanel.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:panel>
-    <h4>Handling history</h4>
-    <table>
-        <tbody>
-        <tr wicket:id="handlingEvents">
-            <td><img src="/graphics/icon/" wicket:id="onTrackIcon"/></td>
-            <td wicket:id="completion"></td>
-            <td wicket:id="event"></td>
-        </tr>
-        </tbody>
-    </table>
-</wicket:panel>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/HandlingHistoryPanel.properties b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/HandlingHistoryPanel.properties
deleted file mode 100644
index a92c7cd..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/HandlingHistoryPanel.properties
+++ /dev/null
@@ -1,21 +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.
-
-handlingEvent.UNKNOWN=ERROR: *** UNKNOWN EVENT TYPE ***
-handlingEvent.RECEIVE=Received in ${location}
-handlingEvent.LOAD=Loaded onto voyage ${voyage} in ${location}
-handlingEvent.UNLOAD=Unloaded from voyage ${voyage} in ${location}
-handlingEvent.CLAIM=Claimed in ${location} by customer
-handlingEvent.CUSTOMS=In customs
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/NextHandlingEventPanel.html b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/NextHandlingEventPanel.html
deleted file mode 100644
index e37b8ce..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/NextHandlingEventPanel.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:panel>
-    <p wicket:id="text" style="font-style:italic;font-weight: bold;"></p>
-</wicket:panel>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/NextHandlingEventPanel.properties b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/NextHandlingEventPanel.properties
deleted file mode 100644
index eefa396..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/NextHandlingEventPanel.properties
+++ /dev/null
@@ -1,23 +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.
-
-expectedEvent.UNKNOWN=Next expected activity: Unknown...
-expectedEvent.ROUTE=Next expected activity: Routing of cargo
-expectedEvent.RECEIVE=Next expected activity: Receipt of cargo in ${location}
-expectedEvent.LOAD=Next expected activity: Load onto voyage ${voyage} in ${location} ${time}
-expectedEvent.UNLOAD=Next expected activity: Unload off voyage ${voyage} in ${location} ${time}
-expectedEvent.CLAIM=Next expected activity: Claim by customer in destination port ${location} ${time}
-expectedEvent.CUSTOMS=ERROR: CUSTOMS IS NOT AN EXPECTED EVENT
-expectedEvent.END_OF_CYCLE=Cargo has successfully been claimed in ${location} by customer
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/TrackCargoPage.html b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/TrackCargoPage.html
deleted file mode 100644
index 26de6b8..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/TrackCargoPage.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:extend>
-    <div id="box">
-
-        <div class="headerMenu">Tracking</div>
-
-        <form wicket:id="form">
-            Tracking number
-            <input type="text" wicket:id="trackingId"/>
-            <input type="submit" value="Track" wicket:id="track"/>
-            &nbsp;&nbsp;&nbsp;&nbsp;Pre-selection: <select wicket:id="selectedTrackingIdSelector"></select>
-
-            <div wicket:id="feedback"></div>
-
-            <div wicket:id="status"></div>
-            <wicket:fragment wicket:id="statusFragment">
-                <br/>
-                <span wicket:id="transportStatus" style="font-weight:bold">[Text]</span>
-
-                <p wicket:id="eta">eta </p>
-
-                <p wicket:id="isMisdirected" class="notifyError"><img src="../../graphics/icon/error.png"/>&nbsp;
-                    Cargo is misdirected. </p>
-
-                <p wicket:id="isClaimed" class="notifySuccess"><img src="../../graphics/icon/tick.png"/>&nbsp;
-                    Cargo succesfully delivered. </p>
-
-                <div wicket:id="handlingHistoryPanel"></div>
-            </wicket:fragment>
-        </form>
-
-    </div>
-</wicket:extend>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/TrackCargoPage.properties b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/TrackCargoPage.properties
deleted file mode 100644
index 1f6a51f..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/communication/web/tracking/TrackCargoPage.properties
+++ /dev/null
@@ -1,24 +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.
-
-cargoDropDown.null=Track known cargo
-
-eta=Estimated time of arrival in {0}: {1}
-
-transportStatus.NOT_RECEIVED=Cargo ${trackingId} has not been received yet
-transportStatus.IN_PORT=Cargo ${trackingId} is now in ${location}
-transportStatus.ONBOARD_CARRIER=Cargo ${trackingId} is now onboard voyage ${voyage}
-transportStatus.CLAIMED=Cargo ${trackingId} is now claimed by customer in ${location}
-transportStatus.UNKNOWN=Cargo ${trackingId} has an unknown transport status
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BookNewCargo.txt b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BookNewCargo.txt
deleted file mode 100644
index 7412c32..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BookNewCargo.txt
+++ /dev/null
@@ -1,75 +0,0 @@
-
-USE CASE	    Book New Cargo
-===========================================================================
-Customer books shipping of Cargo from one destination to another with an arrival deadline.
-
-Scope.......... Booking application ("system")
-Level.......... User-goal
-Primary actor.. Customer (can be Sales Rep/Manager or Booking clerk on behalf of Customer).
-Preconditions.. Customer is logged in.
-Trigger........ Customer wants to book cargo shipping.
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Customer provides origin/destination location and arrival deadline of cargo to system.
-2. System creates cargo with unique tracking id from route specification.
-3. System calculates one or more routes for cargo and presents itineraries for those routes to customer.
-4. Customer chooses preferred route.
-5. System assigns cargo to selected route.
-6. System confirms booking completion to customer.
-7. System notifies booking clerk to <initiate cargo transport>#3.
-
-Deviations
----------------------------------------------------------------------------
-Can happen anytime in the booking process:
-*a. Customer logs out or cancels booking:
-    1. System asks customer if he/she wants to save booking for later completion:
-        a. System saves/deletes cargo.
-*b. Customer session times out.
-    1. System offers customer to logger in again and continue with same booking.
-*c. Customer closes browser:
-    1. System deletes cargo.
-
-Deviations of main success scenario steps:
-1a. Customer has unfinished booking from earlier session:
-    1. System asks customer if he/she wants to continue with this booking or to delete it.
-        a. System presents next step in booking process to customer.
-        b. System deletes cargo and starts new booking.
-2a. Origin location equals destination location:
-    1. Ask customer to choose different locations (or better: prevent in UI)
-2b. Arrival deadline is in the past or Today:
-    1. Ask customer to correct (or better: prevent in UI).
-3a. No routes satisfy route specification:
-    1. System logs unsatisfied route specification.
-    2. system shows failure message to customer.
-
----------------------------------------------------------------------------
-Success guarantees:
-    Booking is saved and awaits handling by Booking clerk
-
-Minimal guarantees:
-    Data entered is logged.
-
-Stakeholders/Interests:
-    Customer - wants cargo delivered within chosen deadline.
-    Handling dep - wants correct data to handle shipping.
-    Sales dep - wants customer satisfaction and overbooking of vessels to maximize profit.
-    Financial dep - wants payment settlement with customer.
-
-
-Tests
----------------------------------------------------------------------------
-*a: UI
-*b: UI
-*c: UI
-
-1a: UI
-2a: BookNewCargoTest
-2b: BookNewCargoTest
-2:  BookNewCargoTest
-3a: BookNewCargoTest
-3b: UI
-4:  UI
-5:  BookNewCargoTest
-6:  UI
-7:  UI
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BuildDeliverySnapshot.txt b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BuildDeliverySnapshot.txt
deleted file mode 100644
index c2cbdef..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BuildDeliverySnapshot.txt
+++ /dev/null
@@ -1,157 +0,0 @@
-
-USE CASE        Build Delivery Snapshot [subfunction]
-===========================================================================
-Building of a delivery snapshot for a cargo is based on the handling
-history of a cargo, as well as its route specification and itinerary.
-
-A cargo is routed when an itinerary that satisfy the route specification has
-been assigned to the cargo (a route is chosen).
-
-A cargo has a handling history when one or more handling events have been registered for the cargo.
-
-Scope.......... Booking application ("system")
-Level.......... Subfunction
-Primary actor.. System as a "factory".
-Preconditions.. Route specification is known.
-Trigger........ System asks for a Delivery snapshot value object.
-
-A Delivery snapshot captures the relationships between
-Routing status, Transport status and Handling events:
-
-Routing status
-    Some action, leading to next routing status
----------------------------------------------------------------------------
-NOT_ROUTED
-    Customer routes cargo (Itinerary gets assigned to cargo) ->
-ROUTED
-    Route specification changes so that Itinerary is no longer satisfying ->
-MISROUTED
-    Awaits re-routing or new handling event (??) -> ROUTED
-
-Furthermore a cargo can become "misdirected" if the last handling event says
-that the cargo is now in a location not expected by the itinerary. The customer
-then has to reroute the cargo.
-
-Transport status
-    Handling event type, leading to next transport status
----------------------------------------------------------------------------
-NOT_RECEIVED (in first port)
-    RECEIVE
-IN_PORT (origin)
-    LOAD
-ONBOARD_CARRIER
-    UNLOAD
-IN_PORT (1 or more midpoints)
-    LOAD
-ONBOARD_CARRIER
-    UNLOAD (to destination)
-IN_PORT (destination)
-    CUSTOMS (cargo awaits customs clearance - doesn't affect locations)
-    CLAIM (customer claims cargo)
-CLAIMED (cargo is finally delivered)
-
-    [Unknown or empty handling event type received] leads to
-UNKNOWN handling status [not used in citerus version]
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Factory initiates build of new delivery snapshot object with a time stamp.
-2. Factory sets routingStatus to ROUTED and calculates eta from itinerary.
-3. Factory sets lastHandlingEvent and lastKnownLocation from last handling event.
-4. Factory derives handling event type dependent data, namely:
-    - transportStatus
-    - isMisdirected
-    - nextExpectedHandlingEvent
-    - currentVoyage
-    - isUnloadedAtDestination
-5. Factory returns delivery snapshot object containing derived data.
-
-
-Deviations
----------------------------------------------------------------------------
-2a. Route specification has same origin and destination location:
-    1. Failure.
-
-2b. Route specification has a deadline Today or in the past:
-    1. Failure.
-
-2c. Itinerary is unknown (cargo hasn't been routed yet):
-    1. Factory sets routingStatus = NOT_ROUTED and transportStatus = NOT_RECEIVED.
-    2. Factory sets nextExpectedHandlingEvent to RECEIVE in origin of route specification.
-    3. Go to step 5.
-
-2d. Route specification is not satisfied by itinerary:
-    1. Factory sets routingStatus = MISROUTED.
-
-3a. Cargo has no handling history yet:
-    1. Factory sets transportStatus to NOT_RECEIVED.
-        a. Cargo is correctly routed:
-            1. Factory sets nextExpectedHandlingEvent to RECEIVE in origin location of route specification.
-    2. Go to step 5.
-
-4a. Cargo was received in port:
-    1. Factory sets transportStatus to IN_PORT.
-        a. Cargo was received in wrong port:
-            1. Factory sets isMisdirected to true.
-            2. Factory sets eta to null.
-        b. Cargo is correctly routed:
-            1. Factory sets nextExpectedHandlingEvent to LOAD/voyage/location of first itinerary leg.
-
-4b. Cargo was loaded onto carrier:
-    1. Factory sets transportStatus = ONBOARD_CARRIER.
-        a. Cargo was rerouted:
-            1. Factory sets nextExpectedHandlingEvent to UNLOAD/voyage/location of first leg of new itinerary.
-        a. Cargo was loaded in unexpected port:
-            1. Factory sets isMisdirected to true.
-            2. Factory sets eta to null.
-            3. Factory sets currentVoyage to voyage of last handling event.
-        b. Cargo was correctly routed:
-            1. Factory sets nextExpectedHandlingEvent to UNLOAD location of current itinerary leg.
-            2. Factory sets currentVoyage to voyage of last handling event.
-        c. Cargo was loaded onto wrong carrier [not in original version]
-            1. Factory should set isMisdirected to true...
-            2. Factory sets eta to null.
-
-4c. Cargo was unloaded from carrier:
-    1. Factory sets transportStatus to IN_PORT.
-        a. Cargo is rerouted:
-            1. Factory sets nextExpectedHandlingEvent to LOAD/voyage/location of first leg of new itinerary.
-        a. Cargo was unloaded in unexpected port:
-            1. Factory sets isMisdirected to true.
-            2. Factory sets eta to null.
-        b. Cargo was unloaded at midpoint location:
-            1. Factory sets nextExpectedHandlingEvent to LOAD/voyage/location of following itinerary leg.
-        c. Cargo was unloaded at destination location:
-            1. Factory sets nextExpectedHandlingEvent to CLAIM at destination location.
-            2. Factory sets isUnloadedAtDestination to true.
-
-4d. Cargo was registered by customs authorities:
-    1. Factory sets transportStatus to IN_PORT.
-        a. Cargo is in destination port:
-            1. Factory sets isUnloadedAtDestination to true.
-
-4e. Cargo was claimed by customer:
-    1. Factory sets transportStatus = CLAIMED
-        a. Cargo is not in destination port:
-            1. Factory sets isMisdirected to true.
-            2. Factory sets eta to null.
-        b. Cargo is in destination port:
-            1. Factory sets isUnloadedAtDestination to true.
-
-4f. An unknown handling event was registered:
-    1. Factory sets transportStatus to UNKNOWN.
-
----------------------------------------------------------------------------
-Success guarantees:
-    A Delivery object containing a complete transportation data snapshot for the cargo is returned.
-
-Minimal guarantees:
-    No guarantee that a Delivery object can be created from supplied data.
-
-Stakeholders/Interests:
-    System - can get a valid Delivery object.
-
-
-
-
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/InspectCargo.txt b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/InspectCargo.txt
deleted file mode 100644
index a6e0aaf..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/InspectCargo.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-
-USE CASE        Inspect Cargo [subfunction]
-===========================================================================
-System updates delivery snapshot of cargo based on registered handling event and saves cargo.
-
-Scope.......... Booking application ("system")
-Level.......... Subfunction
-Primary actor.. System
-Preconditions.. Cargo delivery snapshot is not up do date with registered handling event.
-Trigger........ Handling event has been registered.
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. System <builds delivery snapshot> for cargo with registered handling event.
-2. System assigns new delivery snapshot to cargo.
-3. System checks that cargo is correctly in transit.
-4. System saves cargo.
-
-Deviations
----------------------------------------------------------------------------
-3a. Cargo is misdirected:
-    1. System notifies customer to reroute cargo.
-3b. Cargo has arrived:
-    1. System notifies customer to claim cargo (?)
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/RegisterHandlingEvent.txt b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/RegisterHandlingEvent.txt
deleted file mode 100644
index c3ab921..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/RegisterHandlingEvent.txt
+++ /dev/null
@@ -1,79 +0,0 @@
-
-USE CASE	    Register Handling Event [subfunction]
-===========================================================================
-System registers cargo handling event data received from handling authority (port, shipper etc).
-
-Scope.......... Booking application ("system")
-Level.......... subfunction
-Primary actor.. System
-Preconditions.. Cargo trackingId is know by system and handler.
-Trigger........ Handling authority ("handler") submits handling event data for one or more cargos to system.
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. System publishes event stating that handling event registration attempt has been received.
-2. System verifies that submitted data is complete.
-3. System verifies that submitted data can represent a valid handling event.
-4. System creates and saves handling event from submitted data.
-5. System <inspects cargo> to verify that handling event was expected
-6. System publishes event stating that handling event has been registered.
-
-
-Deviations
----------------------------------------------------------------------------
-2-5a. System couldn't create handling event:
-    1. System publishes event stating unsuccessful registration.
-
-2a. Submitted completion time, tracking id, event type or unLocode is null or empty:
-    1. Failure.
-
-3a. Handling event type string is not recognized:
-    1. Failure.
-3b. Tracking id doesn't represent a cargo in system:
-    1. Failure.
-3c. Tracking id doesn't represent a routed cargo in system:
-    1. Failure.
-3d. Location is not recognized in system:
-    1. Failure.
-3e. Handling event type requires voyage:
-    1. System finds voyage in store with voyage number.
-        a. Voyage number is null:
-            1. Failure.
-        b. Voyage number doesn't represent a voyage in system:
-            1. Failure.
-3f. Handling event type prohibits voyage:
-    1. System sets voyage to null.
-
-We could also check that a new event is not older than the last registered one...
-
-
----------------------------------------------------------------------------
-Success guarantees:
-    Handling event is registered in system.
-    Cargo is successfully updated.
-    Handler is notified of successful handling event registration.
-    Customer is notified if cargo is misdirected or has arrived.
-
-Minimal guarantees:
-    System data is in a valid state.
-    Registration attempt data is logged.
-
-Stakeholders/Interests:
-    Customer - wants notification when cargo has arrived or is misdirected.
-    Handler - wants confirmation that handling event registration was successful.
-    Booking - wants all data to be in a valid and updated state and have a logger of all events.
-
-
-Comments
----------------------------------------------------------------------------
-I think the execution flow in RegisterHandlingEvent is easier to follow compared to that of DDDSample:
-
-1. HandlingReportServiceImpl -> JmsApplicationEventsImpl -> HandlingEventRegistrationAttemptConsumer
-2. HandlingReportServiceImpl -> HandlingReportParser
-3. HandlingReportServiceImpl -> JmsApplicationEventsImpl -> HandlingEventRegistrationAttemptConsumer
-4. HandlingEventRegistrationAttemptConsumer -> HandlingEventServiceImpl -> HandlingEventFactory
-5. HandlingEventServiceImpl -> HandlingEventRepositoryHibernate
-6. HandlingEventServiceImpl -> JmsApplicationEventsImpl -> CargoHandledConsumer
-7. CargoHandledConsumer -> CargoInspectionServiceImpl
-8. CargoInspectionServiceImpl -> CargoRepositoryHibernate
-
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/link/LinkPanel.html b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/link/LinkPanel.html
deleted file mode 100644
index a628cfb..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/link/LinkPanel.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:panel>
-	<a wicket:id="link"><span wicket:id="label"></span></a>
-</wicket:panel>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/prevnext/PrevNext.html b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/prevnext/PrevNext.html
deleted file mode 100644
index ca46915..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/prevnext/PrevNext.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:head>
-    <link href="css/prev-next.css" rel="stylesheet" type="text/css"/>
-</wicket:head>
-<wicket:panel>
-    <div class="prevNextIcons">
-        <a class="prev" href="#" wicket:id="prev"></a>
-        <a class="next" href="#" wicket:id="next" ></a>
-    </div>
-</wicket:panel>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/tabs/TabsPanel.html b/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/tabs/TabsPanel.html
deleted file mode 100644
index 7fc034a..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/resources/org/qi4j/sample/dcicargo/sample_a/infrastructure/wicket/tabs/TabsPanel.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:head>
-    <link href="css/tabs.css" rel="stylesheet" type="text/css"/>
-</wicket:head>
-<wicket:panel>
-    <div id="tabs">
-        <ul>
-            <li wicket:id="tabsView"><a href="#" wicket:id="link"><span wicket:id="label"></span></a></li>
-        </ul>
-    </div>
-
-    <!-- Clear floating to force subsequent containers to draw beneath the tabs -->
-    <div style="clear:both"></div>
-</wicket:panel>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/WEB-INF/web.xml b/samples/dci-cargo/dcisample_a/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index 720a8bf..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<web-app xmlns="http://java.sun.com/xml/ns/javaee"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
-         version="2.5">
-
-    <display-name>DCI Sample (version A)</display-name>
-
-    <filter>
-        <filter-name>DCISample_basic_redirect</filter-name>
-        <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
-        <init-param>
-            <param-name>applicationClassName</param-name>
-            <param-value>org.qi4j.sample.dcicargo.sample_a.bootstrap.DCISampleApplication_a</param-value>
-        </init-param>
-    </filter>
-
-    <filter-mapping>
-        <filter-name>DCISample_basic_redirect</filter-name>
-        <url-pattern>/*</url-pattern>
-    </filter-mapping>
-
-</web-app>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/css/prev-next.css b/samples/dci-cargo/dcisample_a/src/main/webapp/css/prev-next.css
deleted file mode 100644
index d6e85ce..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/css/prev-next.css
+++ /dev/null
@@ -1,50 +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.
- */
-
-.prevNextIcons {
-  /* Modify custom positioning here */
-  float:left;
-  margin-top: 17px;
-  margin-right: 10px;
-}
-
-.prevNextIcons a {
-  padding:8px;
-  background-repeat:no-repeat;
-}
-
-.prevNextIcons .prev  {
-  background-image: url("../../graphics/icon/prev.png");
-}
-.prevNextIcons .prevDisabled {
-  background-image: url("../../graphics/icon/prev_disabled.png");
-  pointer-events: none;
-  cursor: default;
-}
-
-.prevNextIcons .next  {
-  margin-left:8px;
-  background-image: url("../../graphics/icon/next.png");
-}
-.prevNextIcons .nextDisabled {
-  margin-left:8px;
-  background-image: url("../../graphics/icon/next_disabled.png");
-  pointer-events: none;
-  cursor: default;
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/css/style.css b/samples/dci-cargo/dcisample_a/src/main/webapp/css/style.css
deleted file mode 100644
index ec9a49e..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/css/style.css
+++ /dev/null
@@ -1,178 +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.
- */
-
-body {
-    margin: 2em;
-    font-family: 'Lucida Sans', 'Helvetica', 'Sans-serif', 'sans', sans-serif;
-    font-size: 9pt;
-    line-height: 1.2em;
-    background-color: #f5f5f5;
-}
-
-h1, h2, h3, h4, h6 {
-    color: #E9601A;
-}
-h4 {
-    margin-bottom: 5px;
-}
-a{
-    text-decoration:none;
-}
-a:hover{
-    text-decoration:underline;
-}
-a:visited{
-    color:blue;
-}
-
-.left {
-	float: left;
-	width: 75%;
-}
-.right {
-    font-family: 'Verdana', Arial, Helvetica, serif;
-    text-align:right;
-    color: #666;
-    font-size: 8pt;
-    font-style: italic;
-    font-weight: normal;
-    line-height: 1.5em;
-    margin-bottom: -50px;
-}
-.headline {
-    margin-bottom:17px;
-}
-.headline a {
-  text-decoration:none;
-    color: #E9601A;
-    font-size: 2em;
-    font-weight: bold;
-}
-
-#box {
-    border-width: 0px 1px 1px;
-    border-style: solid;
-    border-color: 484a4a;
-    padding: 1em;
-    overflow: hidden;
-    background-color: white;
-}
-
-.headerMenu {
-    margin-top:10px;
-    margin-bottom:20px;
-    color: #E9601A;
-    font-size: 1.5em;
-    font-weight: bold;
-}
-.headerMenu a {
-    margin-left:15px;
-    font-size: 9pt;
-    font-weight: normal;
-}
-
-pre, table, td {
-    font-family: 'Verdana', Arial, Helvetica, serif;
-    font-size: 9pt;
-    line-height: 1.1em;
-}
-
-table td, th {
-    padding: 4 18 4 0;
-    align: left;
-    vertical-align: top;
-}
-
-table thead {
-    font-weight: bold;
-}
-
-.styleLeftColumn td:first-child {
-    font-weight: bold;
-}
-
-.errorColor {
-    color: red;
-    font-weight: bold;
-}
-.correctColor {
-    color: green;
-    font-weight: bold;
-}
-
-.notifyError {
-    border: 2px solid red;
-    padding: 5px;
-    font-weight: bold;
-}
-.notifySuccess {
-    border: 2px solid green;
-    padding: 5px;
-    font-weight: bold;
-}
-.notifySuccess {
-    border: 2px solid green;
-    padding: 5px;
-    font-weight: bold;
-}
-
-
-
-#toggle a {
-        padding-left: 17px;
-        text-decoration:none;
-        color:black;
-}
-
-#toggle a:hover {
-        color:blue;
-}
-
-#toggle .closed  {
-        background: url(/graphics/icon/triangle-closed.png)  no-repeat;
-        background-position: 4 2px;
-}
-#toggle .open  {
-        background: url(/graphics/icon/triangle-open.png)  no-repeat;
-        background-position: 2 4px;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/css/tabs.css b/samples/dci-cargo/dcisample_a/src/main/webapp/css/tabs.css
deleted file mode 100644
index 184b9c7..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/css/tabs.css
+++ /dev/null
@@ -1,76 +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.
- */
-
-#tabs {
-  margin-top:12px;
-  float:left;
-  width:100%;
-  background: #f5f5f5  url("../graphics/tabs/bg.png") repeat-x bottom;
-  font-size:0.9em;
-  line-height:1.6;
-  }
-#tabs ul {
-  margin:0;
-  padding:10px 0;
-  list-style:none;
-  }
-#tabs li {
-  float:left;
-  background: #f5f5f5 url("../graphics/tabs/left.png") no-repeat left top;
-  margin:0;
-  padding:0 0 0 11px;
-  }
-#tabs a {
-  float:left;
-  display:block;
-  background: #f5f5f5 url("../graphics/tabs/right.png") no-repeat right top;
-  padding:6px 15px 4px 4px;
-  text-decoration:none;
-  font-weight:bold;
- color:#444;
-  }
-
-#tabs a:hover {
-  color:blue;
-  }
-
-#tabs a:visited {
-   color:#444;
-}
-
-#tabs a:visited:hover {
-   color:blue;
-   /*color:#E9601A;*/
-}
-
-/* Commented Backslash Hack
-   hides rule from IE5-Mac  \*/
-#tabs a {float:none;}
-/* End IE5-Mac hack */
-
-
-
-#tabs #current {
-  background-image: url("../graphics/tabs/left_on.png");
-  }
-#tabs #current a {
-  background-image:url("../graphics/tabs/right_on.png");
-  color:#333;
-  padding-bottom:5px;
-  }
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/cross.png b/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/cross.png
deleted file mode 100644
index 1514d51..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/cross.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/error.png b/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/error.png
deleted file mode 100644
index 628cf2d..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/error.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/next.png b/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/next.png
deleted file mode 100644
index 823db76..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/next.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/next_disabled.png b/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/next_disabled.png
deleted file mode 100644
index 61b8738..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/next_disabled.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/prev-next.psd b/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/prev-next.psd
deleted file mode 100644
index 14869ef..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/prev-next.psd
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/prev.png b/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/prev.png
deleted file mode 100644
index f1ccf7a..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/prev.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/prev_disabled.png b/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/prev_disabled.png
deleted file mode 100644
index bc0a07b..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/prev_disabled.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/tick.png b/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/tick.png
deleted file mode 100644
index a9925a0..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/tick.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/triangle-closed.png b/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/triangle-closed.png
deleted file mode 100644
index dac3b3e..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/triangle-closed.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/triangle-open.png b/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/triangle-open.png
deleted file mode 100644
index d9ff340..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/icon/triangle-open.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/bg.png b/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/bg.png
deleted file mode 100644
index a682768..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/bg.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/left.png b/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/left.png
deleted file mode 100644
index 92b5eeb..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/left.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/left_on.png b/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/left_on.png
deleted file mode 100644
index b0fcc59..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/left_on.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/original.psd b/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/original.psd
deleted file mode 100644
index fc71fea..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/original.psd
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/right.png b/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/right.png
deleted file mode 100644
index 97efb03..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/right.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/right_on.png b/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/right_on.png
deleted file mode 100644
index 6d9783b..0000000
--- a/samples/dci-cargo/dcisample_a/src/main/webapp/graphics/tabs/right_on.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/Start8081.java b/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/Start8081.java
deleted file mode 100644
index 432e3b3..0000000
--- a/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/Start8081.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.bootstrap;
-
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.webapp.WebAppContext;
-
-/**
- * Javadoc
- */
-public class Start8081
-{
-    private Server jetty;
-
-    public static void main( String[] args ) throws Exception
-    {
-        new Start8081().start();
-    }
-
-    public void start() throws Exception
-    {
-        jetty = new Server();
-        ServerConnector connector = new ServerConnector(jetty );
-        connector.setIdleTimeout( 1000 * 60 * 60 );
-        connector.setSoLingerTime( -1 );
-        connector.setPort( 8081 );
-        jetty.setConnectors( new Connector[]{connector} );
-
-        WebAppContext webAppContext = new WebAppContext();
-        webAppContext.setContextPath( "/" );
-        webAppContext.setWar( "src/main/webapp" );
-        jetty.setHandler( webAppContext );
-
-        try
-        {
-            jetty.start();
-            jetty.join();
-        }
-        catch (Exception e)
-        {
-            e.printStackTrace();
-            System.exit( 100 );
-        }
-    }
-
-    public void stop() throws Exception
-    {
-        jetty.stop();
-        jetty.join();
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/test/TestApplication.java b/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/test/TestApplication.java
deleted file mode 100644
index 059ab4a..0000000
--- a/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/test/TestApplication.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.bootstrap.test;
-
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.rules.TestName;
-import org.qi4j.api.activation.PassivationException;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.sample.dcicargo.sample_a.bootstrap.sampledata.BaseData;
-import org.qi4j.sample.dcicargo.sample_a.infrastructure.dci.Context;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Base class for testing Context Interactions
- */
-public class TestApplication extends BaseData
-{
-    // Logger for sub classes
-    protected Logger logger = LoggerFactory.getLogger( getClass() );
-
-    protected static Application app;
-
-    @BeforeClass
-    public static void setup() throws Exception
-    {
-        System.out.println( "\n@@@@@@@@@@@@@@@  TEST  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" );
-        app = new Energy4Java().newApplication( new TestAssembler() );
-        app.activate();
-
-        // Separate test suites in console output
-        System.out.println();
-    }
-
-    public TestApplication()
-    {
-        super(app.findModule( "BOOTSTRAP", "BOOTSTRAP-Bootstrap" ));
-        Context.prepareContextBaseClass( module );
-    }
-
-    // Printing current test method name to console
-    @Rule
-    public TestName name = new TestName();
-
-    @Before
-    public void prepareTest()
-        throws Exception
-    {
-        logger.info( name.getMethodName() );
-        Usecase usecase = UsecaseBuilder.newUsecase( "Usecase: " + name );
-        module.newUnitOfWork(usecase);
-    }
-
-    @After
-    public void concludeTest()
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        if( uow != null && uow.isOpen() )
-            uow.discard();
-        if( module != null && module.isUnitOfWorkActive() )
-        {
-            while( module.isUnitOfWorkActive() )
-            {
-                uow = module.currentUnitOfWork();
-                if( uow.isOpen() )
-                {
-                    System.err.println( "UnitOfWork not cleaned up:" + uow.usecase().name() );
-                    uow.discard();
-                }
-                else
-                {
-                    throw new InternalError( "I have seen a case where a UoW is on the stack, but not opened. First is: " + uow.usecase().name() );
-                }
-            }
-            new Exception( "UnitOfWork not properly cleaned up" ).printStackTrace();
-        }
-
-    }
-
-    @AfterClass
-    public static void terminateApplication()
-        throws PassivationException
-    {
-        if( app != null )
-        {
-            app.passivate();
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/test/TestAssembler.java b/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/test/TestAssembler.java
deleted file mode 100644
index f2ac4a1..0000000
--- a/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/bootstrap/test/TestAssembler.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.bootstrap.test;
-
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.ApplicationAssemblyFactory;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.functional.Function;
-import org.qi4j.index.rdf.RdfIndexingEngineService;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.library.rdf.entity.EntityTypeSerializer;
-import org.qi4j.library.rdf.repository.MemoryRepositoryService;
-import org.qi4j.sample.dcicargo.pathfinder_a.api.GraphTraversalService;
-import org.qi4j.sample.dcicargo.pathfinder_a.internal.GraphDAO;
-import org.qi4j.sample.dcicargo.pathfinder_a.internal.GraphTraversalServiceImpl;
-import org.qi4j.sample.dcicargo.sample_a.bootstrap.sampledata.BaseDataService;
-import org.qi4j.sample.dcicargo.sample_a.context.rolemap.CargoRoleMap;
-import org.qi4j.sample.dcicargo.sample_a.context.rolemap.CargosRoleMap;
-import org.qi4j.sample.dcicargo.sample_a.context.rolemap.HandlingEventRoleMap;
-import org.qi4j.sample.dcicargo.sample_a.context.rolemap.HandlingEventsRoleMap;
-import org.qi4j.sample.dcicargo.sample_a.context.rolemap.ItineraryRoleMap;
-import org.qi4j.sample.dcicargo.sample_a.context.rolemap.RouteSpecificationRoleMap;
-import org.qi4j.sample.dcicargo.sample_a.context.support.ApplicationEvents;
-import org.qi4j.sample.dcicargo.sample_a.context.support.RegisterHandlingEventAttemptDTO;
-import org.qi4j.sample.dcicargo.sample_a.context.support.RoutingService;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.LocationEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.VoyageEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.TrackingId;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.ExpectedHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Leg;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.UnLocode;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.CarrierMovement;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Schedule;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.VoyageNumber;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-import static org.qi4j.api.common.Visibility.application;
-import static org.qi4j.api.structure.Application.Mode.test;
-
-/**
- * Test application assembler
- */
-@SuppressWarnings( "unchecked" )
-public class TestAssembler
-      implements ApplicationAssembler
-{
-    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-          throws AssemblyException
-    {
-        // Application assembly
-        ApplicationAssembly assembly = applicationFactory.newApplicationAssembly();
-        assembly.setName( "DCI Sample (version A) - TEST" );
-        assembly.setVersion( "A.1.0" );
-        assembly.setMode( test );
-
-        // Layers
-        LayerAssembly infrastructureLayer = assembly.layer( "INFRASTRUCTURE" );
-        LayerAssembly domainLayer = assembly.layer( "DOMAIN" );
-        LayerAssembly contextLayer = assembly.layer( "CONTEXT" );
-        LayerAssembly bootstrapLayer = assembly.layer( "BOOTSTRAP" );
-
-        // Layer dependencies
-        bootstrapLayer.uses(
-              contextLayer,
-              domainLayer,
-              infrastructureLayer );
-
-        contextLayer.uses(
-              domainLayer,
-              infrastructureLayer );
-
-        domainLayer.uses(
-              contextLayer,
-              infrastructureLayer
-        );
-
-        // Assemble
-        assembleDomainLayer( domainLayer );
-        assembleContextLayer( contextLayer );
-        assembleBootstrapLayer( bootstrapLayer );
-        assembleInfrastructureLayer( infrastructureLayer );
-
-        return assembly;
-    }
-
-    private void assembleBootstrapLayer( LayerAssembly bootstrapLayer ) throws AssemblyException
-    {
-        ModuleAssembly bootstrapModule = bootstrapLayer.module( "BOOTSTRAP-Bootstrap" );
-
-        // Load base data on startup
-        bootstrapModule
-              .addServices(
-                    BaseDataService.class )
-              .visibleIn( application )
-              .instantiateOnStartup();
-    }
-
-    private void assembleContextLayer( LayerAssembly contextLayer ) throws AssemblyException
-    {
-        // Role-playing entities
-        ModuleAssembly entityRoleModule = contextLayer.module( "CONTEXT-EntityRole" );
-        entityRoleModule
-              .entities(
-                    CargoRoleMap.class,
-                    CargosRoleMap.class,
-                    HandlingEventRoleMap.class,
-                    HandlingEventsRoleMap.class )
-              .visibleIn( application );
-
-
-        // Role-playing values
-        ModuleAssembly valueRoleModule = contextLayer.module( "CONTEXT-ValueRole" );
-        valueRoleModule
-              .values(
-                    ItineraryRoleMap.class,
-                    RouteSpecificationRoleMap.class )
-              .visibleIn( application );
-
-
-        ModuleAssembly contextSupportModule = contextLayer.module( "CONTEXT-ContextSupport" );
-        contextSupportModule
-              .addServices(
-                    RoutingService.class,
-                    ApplicationEvents.class )
-              .visibleIn( application );
-
-        contextSupportModule
-              .values(
-                    RegisterHandlingEventAttemptDTO.class )
-              .visibleIn( application );
-    }
-
-    private void assembleDomainLayer( LayerAssembly domainLayer ) throws AssemblyException
-    {
-        // Non-role-playing entities
-        ModuleAssembly entityModule = domainLayer.module( "DOMAIN-Entity" );
-        entityModule
-              .entities(
-                    LocationEntity.class,
-                    VoyageEntity.class )
-              .visibleIn( application );
-
-
-        // Non-role-playing values
-        ModuleAssembly dataModule = domainLayer.module( "DOMAIN-Data" );
-        dataModule
-              .values(
-                    TrackingId.class,
-                    Delivery.class,
-                    ExpectedHandlingEvent.class,
-                    UnLocode.class,
-                    Leg.class,
-                    CarrierMovement.class,
-                    Schedule.class,
-                    VoyageNumber.class )
-              .visibleIn( application );
-    }
-
-    private void assembleInfrastructureLayer( LayerAssembly infrastructureLayer ) throws AssemblyException
-    {
-        ModuleAssembly serializationModule = infrastructureLayer.module( "INFRASTRUCTURE-Serialization" );
-        serializationModule
-            .services( OrgJsonValueSerializationService.class )
-            .taggedWith( ValueSerialization.Formats.JSON )
-            .setMetaInfo( new Function<Application, Module>()
-        {
-            @Override
-            public Module map( Application application )
-            {
-                return application.findModule( "CONTEXT", "CONTEXT-ContextSupport" );
-            }
-        } )
-        .visibleIn( application );
-
-        ModuleAssembly indexingModule = infrastructureLayer.module( "INFRASTRUCTURE-Indexing" );
-        indexingModule
-              .objects(
-                    EntityStateSerializer.class,
-                    EntityTypeSerializer.class );
-
-        indexingModule
-              .addServices(
-                    MemoryRepositoryService.class,
-                    RdfIndexingEngineService.class )
-              .visibleIn( application );
-
-
-        ModuleAssembly entityStoreModule = infrastructureLayer.module( "INFRASTRUCTURE-EntityStore" );
-        entityStoreModule
-              .addServices(
-                    MemoryEntityStoreService.class,
-                    UuidIdentityGeneratorService.class )
-              .visibleIn( application );
-
-        ModuleAssembly externalServiceModule = infrastructureLayer.module( "INFRASTRUCTURE-ExternalService" );
-        externalServiceModule
-              .importedServices(
-                    GraphTraversalService.class )
-              .setMetaInfo( new GraphTraversalServiceImpl( new GraphDAO() ) )
-              .visibleIn( application );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BookNewCargoTest.java b/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BookNewCargoTest.java
deleted file mode 100644
index dbb3ea3..0000000
--- a/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BookNewCargoTest.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.shipping.booking;
-
-import java.util.Date;
-import java.util.List;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_a.bootstrap.test.TestApplication;
-import org.qi4j.sample.dcicargo.sample_a.context.support.FoundNoRoutesException;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.CargosEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargos;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.TrackingId;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.RoutingStatus;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.TransportStatus;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.*;
-
-/**
- * Test of Book New Cargo use case.
- *
- * This is a test suite where all steps and deviations in the use case are tested.
- * Some data will carry over from one test to another (all tests run within the same UnitOfWork).
- *
- * Test method names describe the test purpose. The prefix refers to the step in the use case.
- */
-public class BookNewCargoTest
-      extends TestApplication
-{
-
-    private static final Date TODAY = new Date();
-
-    @Before
-    public void prepareTest()
-        throws Exception
-    {
-        super.prepareTest();
-
-    }
-
-    @Test( expected = RouteException.class )
-    public void deviation2a_OriginAndDestinationSame() throws Exception
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        Location HONGKONG = uow.get( Location.class, CNHKG.code().get() );
-        Cargos CARGOS = uow.get( Cargos.class, CargosEntity.CARGOS_ID );
-        new BookNewCargo( CARGOS, HONGKONG, HONGKONG, day( 17 ) ).book();
-    }
-
-    @Test( expected = RouteException.class )
-    public void deviation_2b_1_DeadlineInThePastNotAccepted() throws Exception
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        Location HONGKONG = uow.get( Location.class, CNHKG.code().get() );
-        Location STOCKHOLM = uow.get( Location.class, SESTO.code().get() );
-        Cargos CARGOS = uow.get( Cargos.class, CargosEntity.CARGOS_ID );
-        new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, day( -1 ) ).book();
-    }
-
-    @Test( expected = RouteException.class )
-    public void deviation_2b_2_DeadlineTodayIsTooEarly() throws Exception
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        Location HONGKONG = uow.get( Location.class, CNHKG.code().get() );
-        Location STOCKHOLM = uow.get( Location.class, SESTO.code().get() );
-        Cargos CARGOS = uow.get( Cargos.class, CargosEntity.CARGOS_ID );
-        new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, day( 0 ) ).book();
-    }
-
-    @Test
-    public void deviation_2b_3_DeadlineTomorrowIsOkay() throws Exception
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        Location HONGKONG = uow.get( Location.class, CNHKG.code().get() );
-        Location STOCKHOLM = uow.get( Location.class, SESTO.code().get() );
-        Cargos CARGOS = uow.get( Cargos.class, CargosEntity.CARGOS_ID );
-        new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, day( 1 ) ).book();
-    }
-
-    @Test
-    public void step_2_CreateNewCargo() throws Exception
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        Location HONGKONG = uow.get( Location.class, CNHKG.code().get() );
-        Location STOCKHOLM = uow.get( Location.class, SESTO.code().get() );
-        Cargos CARGOS = uow.get( Cargos.class, CargosEntity.CARGOS_ID );
-        // Create cargo with valid input from customer
-        TrackingId trackingId = new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, day( 17 ) ).book();
-
-        // Retrieve created cargo from store
-        Cargo cargo = uow.get( Cargo.class, trackingId.id().get() );
-
-        // Test cargo data
-        assertThat( cargo.trackingId().get(), is( equalTo( trackingId ) ) );
-        assertThat( cargo.origin().get(), is( equalTo( HONGKONG ) ) );
-
-        // Test route specification
-        assertThat( cargo.routeSpecification().get().destination().get(), is( equalTo( STOCKHOLM ) ) );
-        // day(17) here is calculated a few milliseconds after initial day(17), so it will be later...
-        assertThat( cargo.routeSpecification().get().arrivalDeadline().get(),  equalTo( day( 17 )  ));
-
-        // (Itinerary is not assigned yet)
-
-        // Test derived delivery snapshot
-        Delivery delivery = cargo.delivery().get();
-        assertThat( delivery.timestamp().get().after( TODAY ), is( equalTo( true ) ) ); // TODAY is set first
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.NOT_ROUTED ) ) );
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.NOT_RECEIVED ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( HandlingEventType.RECEIVE ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( HONGKONG ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( null ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( null ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( null ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
-        assertThat( delivery.eta().get(), is( equalTo( null ) ) ); // Is set when itinerary is assigned
-        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
-        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
-    }
-
-    @Test( expected = FoundNoRoutesException.class )
-    public void deviation_3a_NoRoutesCanBeThatFast() throws Exception
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        Location HONGKONG = uow.get( Location.class, CNHKG.code().get() );
-        Location STOCKHOLM = uow.get( Location.class, SESTO.code().get() );
-        Cargos CARGOS = uow.get( Cargos.class, CargosEntity.CARGOS_ID );
-        TrackingId trackingId = new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, day( 1 ) ).book();
-        Cargo cargo = uow.get( Cargo.class, trackingId.id().get() );
-
-        // No routes will be found
-        new BookNewCargo( cargo ).routeCandidates();
-    }
-
-    @Test
-    public void step_3_CalculatePossibleRoutes() throws Exception
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        Location HONGKONG = uow.get( Location.class, CNHKG.code().get() );
-        Location STOCKHOLM = uow.get( Location.class, SESTO.code().get() );
-        Cargos CARGOS = uow.get( Cargos.class, CargosEntity.CARGOS_ID );
-
-        // Create valid cargo
-        TrackingId trackingId = new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, day( 30 ) ).book();
-        Cargo cargo = uow.get( Cargo.class, trackingId.id().get() );
-
-        // Step 3 - Find possible routes
-        List<Itinerary> routeCandidates = new BookNewCargo( cargo ).routeCandidates();
-
-        // Check possible routes
-        for (Itinerary itinerary : routeCandidates)
-        {
-            assertThat( "First load location equals origin location.",
-                        itinerary.firstLeg().loadLocation().get(),
-                        is( equalTo( cargo.routeSpecification().get().origin().get() ) ) );
-            assertThat( "Last unload location equals destination location.",
-                        itinerary.lastLeg().unloadLocation().get(),
-                        is( equalTo( cargo.routeSpecification().get().destination().get() ) ) );
-            assertThat( "Cargo will be delivered in time.",
-                        itinerary.finalArrivalDate().before( cargo.routeSpecification().get().arrivalDeadline().get() ),
-                        is( equalTo( true ) ) );
-        }
-    }
-
-    @Test
-    public void step_5_AssignCargoToRoute() throws Exception
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        Location HONGKONG = uow.get( Location.class, CNHKG.code().get() );
-        Location STOCKHOLM = uow.get( Location.class, SESTO.code().get() );
-        Cargos CARGOS = uow.get( Cargos.class, CargosEntity.CARGOS_ID );
-
-        // Create valid cargo
-        Date deadline = day( 30 );
-        TrackingId trackingId = new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, deadline ).book();
-        Cargo cargo = uow.get( Cargo.class, trackingId.id().get() );
-
-        List<Itinerary> routeCandidates = new BookNewCargo( cargo ).routeCandidates();
-
-        // Get first route found
-        // Would normally be found with an Itinerary id from customer selection
-        Itinerary itinerary = routeCandidates.get( 0 );
-
-        // Use case step 5 - System assigns cargo to route
-        new BookNewCargo( cargo, itinerary ).assignCargoToRoute();
-
-        assertThat( "Itinerary has been assigned to cargo.", itinerary, is( equalTo( cargo.itinerary().get() ) ) );
-
-        // BuildDeliverySnapshot will check if itinerary is valid. No need to check it here.
-
-        // Check values set in new delivery snapshot
-        Delivery delivery = cargo.delivery().get();
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
-
-        // ETA (= Unload time of last Leg) is before Deadline (set in previous test)
-        assertTrue( delivery.eta().get().before( deadline ) );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BuildDeliverySnapshotTest.java b/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BuildDeliverySnapshotTest.java
deleted file mode 100644
index bb5c1e2..0000000
--- a/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/booking/BuildDeliverySnapshotTest.java
+++ /dev/null
@@ -1,639 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.shipping.booking;
-
-import java.util.Date;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_a.bootstrap.test.TestApplication;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.CargosEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.HandlingEventsEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargos;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.TrackingId;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.RoutingStatus;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.TransportStatus;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
-
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.*;
-import static org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType.*;
-
-/**
- * Tests of the Build Delivery Snapshot subfunction use case.
- *
- * All deviations of the use case are tested one by one. The business rules are therefore enforcing the
- * structure for the test suite and not arbitrary ideas of the programmer what to test. If the business
- * analyst haven't foreseen a deviation in the use case, it's his responsibility that it's not tested.
- *
- * Test method names describe the test purpose. The prefix refers to the step in the use case.
- *
- * FIXME: Test methods call each other to allow ordered execution, ie. tests are not indepedants !
- */
-public class BuildDeliverySnapshotTest
-      extends TestApplication
-{
-    final Date TODAY = new Date();
-
-    private Location HONGKONG;
-    private Location STOCKHOLM;
-    private Location NEWYORK;
-    private Location DALLAS;
-    private Location HANGZHOU;
-    private Location HELSINKI;
-    private Location TOKYO;
-    private Location HAMBURG;
-    private Voyage V100S;
-    private Voyage V200T;
-    private Voyage V300A;
-    private Voyage V400S;
-    private Voyage V500S;
-    private Location SHANGHAI;
-    private TrackingId trackingId;
-    private Cargo cargo;
-    private Itinerary itinerary;
-
-    @Before
-    public void prepareTest()
-        throws Exception
-    {
-        super.prepareTest();
-        UnitOfWork uow = module.currentUnitOfWork();
-        HONGKONG = uow.get( Location.class, CNHKG.code().get() );
-        STOCKHOLM = uow.get( Location.class, SESTO.code().get() );
-        SHANGHAI = uow.get( Location.class, CNSHA.code().get() );
-        TOKYO = uow.get( Location.class, JNTKO.code().get() );
-        NEWYORK = uow.get( Location.class, USNYC.code().get() );
-        DALLAS = uow.get( Location.class, USDAL.code().get() );
-        HANGZHOU = uow.get( Location.class, CNHGH.code().get() );
-        HELSINKI = uow.get( Location.class, FIHEL.code().get() );
-        HAMBURG = uow.get( Location.class, DEHAM.code().get() );
-        V100S = uow.get( Voyage.class, "V100S" );
-        V200T = uow.get( Voyage.class, "V200T" );
-        V300A = uow.get( Voyage.class, "V300A" );
-        V400S = uow.get( Voyage.class, "V400S" );
-        V500S = uow.get( Voyage.class, "V500S" );
-
-        Cargos CARGOS = uow.get( Cargos.class, CargosEntity.CARGOS_ID );
-        trackingId = new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, day( 17 ) ).createCargo( "ABC" );
-        cargo = uow.get( Cargo.class, trackingId.id().get() );
-
-        itinerary = itinerary(
-            leg( V100S, HONGKONG, NEWYORK, day( 1 ), day( 8 ) ),
-            leg( V200T, NEWYORK, DALLAS, day( 9 ), day( 12 ) ),
-            leg( V300A, DALLAS, STOCKHOLM, day( 13 ), day( 16 ) )
-        );
-
-
-    }
-
-    // DERIVE WITH ROUTE SPECIFICATION ==============================================================================
-
-    @Test( expected = RouteException.class )
-    public void deviation_2a_InvalidRouteSpecification_sameLocations() throws Exception
-    {
-        RouteSpecification routeSpec = routeSpecification( HONGKONG, HONGKONG, day( 20 ) );
-        new BuildDeliverySnapshot( routeSpec ).get();
-    }
-
-    @Test( expected = RouteException.class )
-    public void deviation_2b_InvalidRouteSpecification_tooEarlyDeadline() throws Exception
-    {
-        RouteSpecification routeSpec = routeSpecification( HONGKONG, STOCKHOLM, TODAY );
-        new BuildDeliverySnapshot( routeSpec ).get();
-    }
-
-    @Test
-    public void deviation_2c_ItineraryIsUnknown_buildFromRouteSpecification() throws Exception
-    {
-        RouteSpecification routeSpec = routeSpecification( HONGKONG, STOCKHOLM, day( 20 ) );
-        Delivery delivery = new BuildDeliverySnapshot( routeSpec ).get();
-
-        assertThat( delivery.timestamp().get().after( TODAY ), is( equalTo( true ) ) ); // TODAY is set first
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.NOT_ROUTED ) ) );
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.NOT_RECEIVED ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( HandlingEventType.RECEIVE ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( HONGKONG ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( null ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( null ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( null ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
-        assertThat( delivery.eta().get(), is( equalTo( null ) ) );
-        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
-        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
-    }
-
-
-    // DERIVE WITH NON-ROUTED CARGO ==============================================================================
-
-    @Test
-    public void deviation_2c_ItineraryIsUnknown_buildFromNonRoutedCargo() throws Exception
-    {
-        deviation_2c_ItineraryIsUnknown_buildFromRouteSpecification();
-
-        UnitOfWork uow = module.currentUnitOfWork();
-        RouteSpecification routeSpec = routeSpecification( HONGKONG, STOCKHOLM, day( 20 ) );
-        Cargos CARGOS = uow.get( Cargos.class, CargosEntity.CARGOS_ID );
-        Delivery delivery = new BuildDeliverySnapshot( routeSpec ).get();
-        Cargo cargo = CARGOS.createCargo( routeSpec, delivery, "ABCD" );
-
-        // Same as previous test (just build from cargo instead)
-        assertThat( delivery.timestamp().get().after( TODAY ), is( equalTo( true ) ) ); // TODAY is set first
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.NOT_ROUTED ) ) );
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.NOT_RECEIVED ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( HandlingEventType.RECEIVE ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( HONGKONG ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( null ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( null ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( null ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
-        assertThat( delivery.eta().get(), is( equalTo( null ) ) );
-        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
-        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
-    }
-
-
-    // DERIVE WITH ROUTE SPECIFICATION + ITINERARY (Routed cargo) ==============================================
-
-    @Test
-    public void deviation_2d_UnsatisfyingItinerary_wrongOrigin() throws Exception
-    {
-        deviation_2c_ItineraryIsUnknown_buildFromNonRoutedCargo();
-
-        Itinerary itinerary = itinerary(
-            leg( V100S, HONGKONG, NEWYORK, day( 1 ), day( 8 ) ),
-            leg( V200T, NEWYORK, DALLAS, day( 9 ), day( 12 ) ),
-            leg( V300A, DALLAS, STOCKHOLM, day( 13 ), day( 16 ) )
-        );
-
-        // Hangzhou not in itinerary first leg
-        RouteSpecification routeSpec = routeSpecification( HANGZHOU, STOCKHOLM, day( 20 ) );
-        cargo.itinerary().set( itinerary );
-        cargo.routeSpecification().set( routeSpec );
-        Delivery delivery = new BuildDeliverySnapshot( cargo ).get();
-
-        // Route specification not satisfied by itinerary
-        assertThat( itinerary.firstLeg().loadLocation().get(), is( not( equalTo( routeSpec.origin().get() ) ) ) );
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.MISROUTED ) ) );
-    }
-
-    @Test
-    public void deviation_2d_UnsatisfyingItinerary_wrongDestination() throws Exception
-    {
-        deviation_2d_UnsatisfyingItinerary_wrongOrigin();
-
-        // Helsinki not in itinerary last leg
-        RouteSpecification routeSpec = routeSpecification( HONGKONG, HELSINKI, day( 20 ) );
-        cargo.routeSpecification().set( routeSpec );
-        Delivery delivery = new BuildDeliverySnapshot( cargo ).get();
-
-        // Route specification not satisfied by itinerary
-        assertThat( itinerary.lastLeg().unloadLocation().get(), is( not( equalTo( routeSpec.destination().get() ) ) ) );
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.MISROUTED ) ) );
-    }
-
-    @Test
-    public void deviation_2d_UnsatisfyingItinerary_missedDeadline() throws Exception
-    {
-        deviation_2d_UnsatisfyingItinerary_wrongDestination();
-
-        // Arrival on day 12 according to itinerary is not meeting deadline
-        RouteSpecification routeSpec = routeSpecification( HONGKONG, STOCKHOLM, day( 14 ) );
-        cargo.routeSpecification().set( routeSpec );
-        Delivery delivery = new BuildDeliverySnapshot( cargo ).get();
-
-        // Route specification not satisfied by itinerary
-        assertFalse( routeSpec.arrivalDeadline().get().after( itinerary.finalArrivalDate() ) );
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.MISROUTED ) ) );
-    }
-
-    @Test
-    public void deviation_3a_CargoHasNoHandlingHistory() throws Exception
-    {
-        deviation_2d_UnsatisfyingItinerary_missedDeadline();
-
-        Date arrival = day( 16 );
-        Date deadline = day( 20 );
-        // Itinerary will satisfy route specification
-        RouteSpecification routeSpec = routeSpecification( HONGKONG, STOCKHOLM, deadline );
-        cargo.routeSpecification().set( routeSpec );
-        Delivery delivery = new BuildDeliverySnapshot( cargo ).get();
-
-        // Route specification satisfied by itinerary
-        assertThat( itinerary.firstLeg().loadLocation().get(), is( equalTo( routeSpec.origin().get() ) ) );
-        assertThat( itinerary.lastLeg().unloadLocation().get(), is( equalTo( routeSpec.destination().get() ) ) );
-        assertTrue( routeSpec.arrivalDeadline().get().after( itinerary.finalArrivalDate() ) );
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
-
-        assertThat( delivery.timestamp().get().after( TODAY ), is( equalTo( true ) ) ); // TODAY is set first
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.NOT_RECEIVED ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( HandlingEventType.RECEIVE ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( HONGKONG ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( null ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( null ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( null ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
-        assertThat( delivery.eta().get(), is( equalTo( arrival ) ) );
-        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
-        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
-    }
-
-
-    // DERIVE WITH ROUTE SPECIFICATION + ITINERARY + LAST HANDLING EVENT ============================================
-
-    @Test
-    public void deviation_4a_RECEIVE_1a_UnexpectedPort() throws Exception
-    {
-        deviation_3a_CargoHasNoHandlingHistory();
-
-        UnitOfWork uow = module.currentUnitOfWork();
-        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
-        // Unexpected receipt in Shanghai
-        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 1 ), trackingId, HandlingEventType.RECEIVE, SHANGHAI, null );
-        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
-
-        // We don't know what's next for a misdirected cargo
-        assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
-        assertThat( delivery.eta().get(), is( equalTo( null ) ) );
-
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( SHANGHAI ) ) );
-
-        // Cargo is still routed - but it should be re-routed according to new (unexpected) location.
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
-        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
-    }
-
-    @Test
-    public void deviation_4a_RECEIVE_1b_ExpectedPort() throws Exception
-    {
-        deviation_4a_RECEIVE_1a_UnexpectedPort();
-
-        UnitOfWork uow = module.currentUnitOfWork();
-        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
-        // Expected receipt in Hong Kong
-        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 1 ), trackingId, HandlingEventType.RECEIVE, HONGKONG, null );
-        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
-
-        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( HONGKONG ) ) );
-
-        // We expect the cargo to be loaded on voyage V100S in Hong Kong
-        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( LOAD ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( HONGKONG ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( V100S ) ) );
-    }
-
-
-    @Test
-    public void deviation_4b_LOAD_2a_UnexpectedPort() throws Exception
-    {
-        deviation_4a_RECEIVE_1b_ExpectedPort();
-
-        UnitOfWork uow = module.currentUnitOfWork();
-        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
-        // Unexpected load in Tokyo
-        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 1 ), trackingId, LOAD, TOKYO, V100S );
-        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
-
-        assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
-        assertThat( delivery.eta().get(), is( equalTo( null ) ) );
-
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.ONBOARD_CARRIER ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( TOKYO ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( V100S ) ) );
-    }
-
-    @Test
-    public void deviation_4b_LOAD_2b_ExpectedPort() throws Exception
-    {
-        deviation_4b_LOAD_2a_UnexpectedPort();
-
-        UnitOfWork uow = module.currentUnitOfWork();
-        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
-        // Expected load in Hong Kong
-        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 1 ), trackingId, LOAD, HONGKONG, V100S );
-        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
-
-        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.ONBOARD_CARRIER ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( HONGKONG ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( V100S ) ) );
-
-        // We expect the cargo to be unloaded from voyage V100S in New York
-        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( UNLOAD ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( NEWYORK ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( V100S ) ) );
-    }
-
-    @Test
-    public void deviation_4b_LOAD_2c_UnexpectedVoyageNotFromItinerary() throws Exception
-    {
-        deviation_4b_LOAD_2b_ExpectedPort();
-
-        UnitOfWork uow = module.currentUnitOfWork();
-        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
-        // Load onto unexpected voyage
-        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 1 ), trackingId, LOAD, HONGKONG, V400S );
-        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
-
-        assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
-        assertThat( delivery.eta().get(), is( equalTo( null ) ) );
-
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.ONBOARD_CARRIER ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( HONGKONG ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( V400S ) ) );
-    }
-
-    @Test
-    public void deviation_4b_LOAD_2c_ExpectedButLaterVoyageInItinerary() throws Exception
-    {
-        deviation_4b_LOAD_2c_UnexpectedVoyageNotFromItinerary();
-
-        UnitOfWork uow = module.currentUnitOfWork();
-        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
-
-        // The system doesn't currently check if handling events happen in the right order, so
-        // a cargo can now suddenly load in New York, even though it hasn't got there yet.
-        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 5 ), day( 5 ), trackingId, LOAD, NEWYORK, V200T );
-        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
-
-        // Should have been true, but we accept it for now...
-        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
-
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.ONBOARD_CARRIER ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( NEWYORK ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( V200T ) ) );
-
-        // We expect the cargo to be unloaded from voyage V200T in Dallas
-        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( UNLOAD ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( DALLAS ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( V200T ) ) );
-    }
-
-
-    @Test
-    public void deviation_4c_UNLOAD_1a_UnexpectedPort() throws Exception
-    {
-        deviation_4b_LOAD_2c_ExpectedButLaterVoyageInItinerary();
-
-        UnitOfWork uow = module.currentUnitOfWork();
-        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
-
-        // Unexpected unload in Tokyo
-        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 5 ), day( 5 ), trackingId, UNLOAD, TOKYO, V100S );
-        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
-        cargo.delivery().set( delivery );
-
-        assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
-        assertThat( delivery.eta().get(), is( equalTo( null ) ) );
-
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
-        assertThat( delivery.lastHandlingEvent().get().handlingEventType().get(), is( equalTo( UNLOAD ) ) );
-        assertThat( delivery.lastHandlingEvent().get().voyage().get(), is( equalTo( V100S ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( TOKYO ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
-        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
-
-        // Cargo needs to be rerouted
-
-        // Customer specifies a new route
-        RouteSpecification routeSpec = routeSpecification( TOKYO, STOCKHOLM, day( 20 ) );
-        cargo.routeSpecification().set( routeSpec );
-        delivery = new BuildDeliverySnapshot( cargo ).get();
-        cargo.delivery().set( delivery );
-
-        // Old itinerary will not satisfy new route specification
-        assertThat( itinerary.firstLeg().loadLocation().get(), is( not( equalTo( routeSpec.origin().get() ) ) ) );
-        assertThat( itinerary.lastLeg().unloadLocation().get(), is( equalTo( routeSpec.destination().get() ) ) );
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.MISROUTED ) ) );
-
-        // Old planned arrival time is still satisfying new deadline
-        assertTrue( routeSpec.arrivalDeadline().get().after( itinerary.finalArrivalDate() ) );
-
-        // We don't know what's next before a new itinerary has been chosen
-        assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
-        assertThat( delivery.eta().get(), is( equalTo( null ) ) );
-
-        // Cargo is still misdirected (in unexpected location) according to old itinerary
-        assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );
-
-        // Last known data
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
-        assertThat( delivery.lastHandlingEvent().get().handlingEventType().get(), is( equalTo( UNLOAD ) ) );
-        assertThat( delivery.lastHandlingEvent().get().voyage().get(), is( equalTo( V100S ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( TOKYO ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
-        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
-
-        // New itinerary that satisfy the new route specification. New origin departure from Tokyo.
-        Date arrival= day( 19 );
-        itinerary = itinerary(
-              leg( V400S, TOKYO, HAMBURG, day( 9 ), day( 16 ) ),
-              leg( V500S, HAMBURG, STOCKHOLM, day( 17 ), arrival  )
-        );
-
-        // Customer reroutes cargo. This is a possible step in the cargo booking process.
-        new BookNewCargo( cargo, itinerary ).assignCargoToRoute();
-        delivery = cargo.delivery().get();
-
-        // Cargo is on track again
-        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
-        assertThat( delivery.lastHandlingEvent().get().handlingEventType().get(), is( equalTo( UNLOAD ) ) );
-        assertThat( delivery.lastHandlingEvent().get().voyage().get(), is( equalTo( V100S ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( TOKYO ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
-        assertThat( delivery.eta().get(), is( equalTo( arrival ) ) );
-        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
-
-        // When a cargo is rerouted the (often misdirected) last handling event is flagged as disregarded
-        // since it doesn't have to be part of the new itinerary (this isn't in the Citerus version).
-
-        // We now expect the cargo to be loaded onto voyage V400S in Tokyo heading to Hamburg
-        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( LOAD ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( TOKYO ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( V400S ) ) );
-
-        // Cargo is not misdirected anymore according to new itinerary. Cargo location is now expected to be in Tokyo.
-    }
-
-    @Test
-    public void deviation_4c_UNLOAD_1b_ExpectedMidpointLocation() throws Exception
-    {
-        deviation_4c_UNLOAD_1a_UnexpectedPort();
-
-        UnitOfWork uow = module.currentUnitOfWork();
-        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
-
-        // Unload at midpoint location of itinerary
-        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 8 ), day( 8 ), trackingId, UNLOAD, HAMBURG, V400S );
-        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
-
-        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( HAMBURG ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
-        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
-
-        // We expect the cargo to be loaded onto voyage V200T in New York heading for Dallas
-        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( LOAD ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( HAMBURG ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( V500S ) ) );
-    }
-
-    @Test
-    public void deviation_4c_UNLOAD_1c_Destination() throws Exception
-    {
-        deviation_4c_UNLOAD_1b_ExpectedMidpointLocation();
-
-        UnitOfWork uow = module.currentUnitOfWork();
-        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
-
-        // Unload at destination
-        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 16 ), day( 16 ), trackingId, UNLOAD, STOCKHOLM, V500S );
-        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
-
-        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( STOCKHOLM ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
-
-        // Cargo has arrived at destination location
-        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( true ) ) );
-
-        // We expect the cargo to be claimed by customer
-        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( CLAIM ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( STOCKHOLM ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( null ) ) );
-    }
-
-
-    @Test
-    public void deviation_4d_CUSTOMS_1a_CargoIsInDestinationPort() throws Exception
-    {
-        deviation_4c_UNLOAD_1c_Destination();
-
-        UnitOfWork uow = module.currentUnitOfWork();
-        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
-
-        // Cargo was handled by the customs authorities
-        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 16 ), day( 16 ), trackingId, CUSTOMS, STOCKHOLM, null );
-        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
-
-        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( STOCKHOLM ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
-
-        // Cargo might be at destination, but the last handling event wasn't unloading
-        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( true ) ) );
-
-        // Shouldn't we expect the cargo to be claimed by the customer now ?
-        assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
-    }
-
-
-    @Test
-    public void deviation_4e_CLAIM_1a_CargoIsNotInDestinationPort() throws Exception
-    {
-        deviation_4d_CUSTOMS_1a_CargoIsInDestinationPort();
-
-        UnitOfWork uow = module.currentUnitOfWork();
-        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
-
-        // Cargo was claimed but not at destination location
-        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 16 ), trackingId, CLAIM, HELSINKI, null );
-        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
-
-        assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
-        assertThat( delivery.eta().get(), is( equalTo( null ) ) );
-
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.CLAIMED ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( HELSINKI ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
-
-        // Cargo is claimed but has not arrived yet in destination port
-        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
-    }
-
-    @Test
-    public void deviation_4e_CLAIM_1b_CargoIsInDestinationPort() throws Exception
-    {
-        deviation_4e_CLAIM_1a_CargoIsNotInDestinationPort();
-
-        UnitOfWork uow = module.currentUnitOfWork();
-        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
-
-        // Cargo was claimed by customer at destination location
-        HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 16 ), day( 16 ), trackingId, CLAIM, STOCKHOLM, null );
-        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
-
-        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.CLAIMED ) ) );
-        assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( STOCKHOLM ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
-
-        // Cargo is claimed in destination port
-        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( true ) ) );
-
-        // No more expected handling events
-        assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/InspectCargoTest.java b/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/InspectCargoTest.java
deleted file mode 100644
index 9203204..0000000
--- a/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/InspectCargoTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.shipping.handling;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_a.bootstrap.test.TestApplication;
-import org.qi4j.sample.dcicargo.sample_a.context.shipping.booking.BookNewCargo;
-import org.qi4j.sample.dcicargo.sample_a.context.shipping.booking.BuildDeliverySnapshot;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.CargosEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.HandlingEventsEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargos;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.TrackingId;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-/**
- * Javadoc
- *
- * Test method names describe the test purpose. The prefix refers to the step in the use case.
- */
-public class InspectCargoTest
-    extends TestApplication
-{
-    private Cargo cargo;
-    private TrackingId trackingId;
-    private Location STOCKHOLM;
-    private Location DALLAS;
-    private Location SHANGHAI;
-    private Voyage V200T;
-    private Voyage V300A;
-    private HandlingEvent handlingEvent;
-
-    @Before
-    public void beforeEachTest()
-        throws Exception
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        Cargos CARGOS = uow.get( Cargos.class, CargosEntity.CARGOS_ID );
-        Location HONGKONG = uow.get( Location.class, CNHKG.code().get() );
-        SHANGHAI = uow.get( Location.class, CNSHA.code().get() );
-        STOCKHOLM = uow.get( Location.class, SESTO.code().get() );
-        Location NEWYORK = uow.get( Location.class, USNYC.code().get() );
-        DALLAS = uow.get( Location.class, USDAL.code().get() );
-        Voyage V100S = uow.get( Voyage.class, "V100S" );
-        V200T = uow.get( Voyage.class, "V200T" );
-        V300A = uow.get( Voyage.class, "V300A" );
-
-        // Create cargo
-        trackingId = new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, day( 17 ) ).createCargo( "ABC" );
-        cargo = uow.get( Cargo.class, trackingId.id().get() );
-        Itinerary itinerary = itinerary(
-            leg( V100S, HONGKONG, NEWYORK, day( 1 ), day( 8 ) ),
-            leg( V200T, NEWYORK, DALLAS, day( 9 ), day( 12 ) ),
-            leg( V300A, DALLAS, STOCKHOLM, day( 13 ), day( 16 ) )
-        );
-
-        // Route cargo
-        new BookNewCargo( cargo, itinerary ).assignCargoToRoute();
-    }
-
-    @Test
-    public void deviation_3a_CargoIsMisdirected()
-        throws Exception
-    {
-        // Create misdirected handling event for cargo (receipt in Shanghai is unexpected)
-        UnitOfWork uow = module.currentUnitOfWork();
-        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 0 ), day( 0 ), trackingId, HandlingEventType.RECEIVE, SHANGHAI, null );
-        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
-        cargo.delivery().set( delivery );
-        assertThat( cargo.delivery().get().isMisdirected().get(), is( equalTo( true ) ) );
-
-        logger.info( "  Handling cargo 'ABC' (misdirected):" );
-        new InspectCargo( handlingEvent ).inspect();
-
-        // Assert that notification of misdirection has been sent (see console output).
-    }
-
-    @Test
-    public void deviation_3b_CargoHasArrived()
-        throws Exception
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 15 ), day( 15 ), trackingId, HandlingEventType.UNLOAD, STOCKHOLM, V300A );
-        Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
-        cargo.delivery().set( delivery );
-        assertThat( cargo.delivery().get().isUnloadedAtDestination().get(), is( equalTo( true ) ) );
-
-        logger.info( "  Handling cargo 'ABC' (arrived):" );
-        new InspectCargo( handlingEvent ).inspect();
-
-        // Assert that notification of  arrival has been sent (see console output).
-    }
-
-    @Test
-    public void step_3_CargoIsCorrectlyInTransit()
-        throws Exception
-    {
-        logger.info( "  Handling cargo 'ABC' (unloaded in Dallas):" );
-        UnitOfWork uow = module.currentUnitOfWork();
-        HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 12 ), day( 12 ), trackingId, HandlingEventType.UNLOAD, DALLAS, V200T );
-        cargo.delivery().set( new BuildDeliverySnapshot( cargo, handlingEvent ).get() );
-        assertThat( cargo.delivery().get().isMisdirected().get(), is( equalTo( false ) ) );
-        new InspectCargo( handlingEvent ).inspect();
-
-        logger.info( "  Cargo was correctly directed." );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/RegisterHandlingEventTest.java b/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/RegisterHandlingEventTest.java
deleted file mode 100644
index fba4edc..0000000
--- a/samples/dci-cargo/dcisample_a/src/test/java/org/qi4j/sample/dcicargo/sample_a/context/shipping/handling/RegisterHandlingEventTest.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_a.context.shipping.handling;
-
-import java.util.Date;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_a.bootstrap.test.TestApplication;
-import org.qi4j.sample.dcicargo.sample_a.context.shipping.booking.BookNewCargo;
-import org.qi4j.sample.dcicargo.sample_a.data.entity.CargosEntity;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.Cargos;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.cargo.TrackingId;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.RoutingStatus;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.delivery.TransportStatus;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.location.Location;
-import org.qi4j.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType.UNLOAD;
-
-/**
- * Testing the Register Handling Event use case.
- *
- * Test method names describe the test purpose. The prefix refers to the step in the use case.
- */
-public class RegisterHandlingEventTest
-      extends TestApplication
-{
-    Date time;
-    String trackId;
-    String msg;
-    private Date arrival;
-    private Cargo cargo;
-    private TrackingId trackingId;
-    private Cargos CARGOS;
-    private Location HONGKONG;
-    private Location STOCKHOLM;
-    private Location NEWYORK;
-    private Location DALLAS;
-    private Voyage V100S;
-    private Voyage V200T;
-    private Voyage V300A;
-
-    @Before
-    public void beforeEachTest() throws Exception {
-        UnitOfWork uow = module.currentUnitOfWork();
-        CARGOS = uow.get(Cargos.class,  CargosEntity.CARGOS_ID );
-        HONGKONG = uow.get( Location.class, CNHKG.code().get() );
-        STOCKHOLM = uow.get( Location.class, SESTO.code().get() );
-        NEWYORK = uow.get( Location.class, USNYC.code().get() );
-        DALLAS = uow.get( Location.class, USDAL.code().get() );
-        V100S = uow.get( Voyage.class, "V100S" );
-        V200T = uow.get( Voyage.class, "V200T" );
-        V300A = uow.get( Voyage.class, "V300A" );
-        trackingId = new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, day( 17 ) ).createCargo( "ABC" );
-        cargo = uow.get( Cargo.class, trackingId.id().get() );
-        Itinerary itinerary = itinerary(
-              leg( V100S, HONGKONG, NEWYORK, day( 1 ), day( 8 ) ),
-              leg( V200T, NEWYORK, DALLAS, day( 9 ), day( 12 ) ),
-              leg( V300A, DALLAS, STOCKHOLM, day( 13 ),
-                   arrival = day( 16 ) )
-        );
-        new BookNewCargo( cargo, itinerary ).assignCargoToRoute();
-        time = day( 1 );
-        trackId = trackingId.id().get();
-    }
-
-    // INPUT EXISTENCE VALIDATION ==================================================================
-
-    @Test
-    public void deviation_2a_MissingRegistrationTime() throws Exception
-    {
-        msg = register( null, time, trackId, "RECEIVE", "CNHKG", null );
-        assertThat( msg, is( equalTo( "Registration time was null. All parameters have to be passed." ) ) );
-    }
-    @Test
-    public void deviation_2a_MissingCompletionTime() throws Exception
-    {
-        msg = register( time, null, trackId, "RECEIVE", "CNHKG", null );
-        assertThat( msg, is( equalTo( "Completion time was null. All parameters have to be passed." ) ) );
-    }
-
-    @Test
-    public void deviation_2a_MissingTrackingId() throws Exception
-    {
-        msg = register( time, time, null, "RECEIVE", "CNHKG", null );
-        assertThat( msg, is( equalTo( "Tracking id was null. All parameters have to be passed." ) ) );
-    }
-
-    @Test
-    public void deviation_2a_EmptyTrackingId() throws Exception
-    {
-        msg = register( time, time, "", "RECEIVE", "CNHKG", null );
-        assertThat( msg, is( equalTo( "Tracking id cannot be empty." ) ) );
-    }
-
-    @Test
-    public void deviation_2a_MissingEventType() throws Exception
-    {
-        msg = register( time, time, trackId, null, "CNHKG", null );
-        assertThat( msg, is( equalTo( "Event type was null. All parameters have to be passed." ) ) );
-    }
-
-    @Test
-    public void deviation_2a_EmptyEventType() throws Exception
-    {
-        msg = register( time, time, trackId, "", "CNHKG", null );
-        assertThat( msg, is( equalTo( "Event type cannot be empty." ) ) );
-    }
-
-    @Test
-    public void deviation_2a_MissingUnlocode() throws Exception
-    {
-        msg = register( time, time, trackId, "RECEIVE", null, null );
-        assertThat( msg, is( equalTo( "UnLocode was null. All parameters have to be passed." ) ) );
-    }
-
-    @Test
-    public void deviation_2a_EmptyUnlocode() throws Exception
-    {
-        msg = register( time, time, trackId, "RECEIVE", "", null );
-        assertThat( msg, is( equalTo( "UnLocode cannot be empty." ) ) );
-    }
-
-    @Test
-    public void step_2_CompleteData__Receive_in_Hong_Kong() throws Exception
-    {
-        new RegisterHandlingEvent( time, time, trackId, "RECEIVE", "CNHKG", null ).register();
-    }
-
-
-    // INPUT VALIDATION ==================================================================
-
-    @Test
-    public void deviation_3a_HandlingTypeNotRecognized() throws Exception
-    {
-        msg = register( time, time, trackId, "RECEIPT", "CNHKG", null );
-        assertThat( msg, is( equalTo(
-              "'RECEIPT' is not a valid handling event type. Valid types are: [RECEIVE, LOAD, UNLOAD, CUSTOMS, CLAIM]" ) ) );
-    }
-
-    @Test
-    public void deviation_3b_NoCargoWithTrackingId() throws Exception
-    {
-        msg = register( time, time, "XXX", "RECEIVE", "CNHKG", null );
-        assertThat( msg, is( equalTo( "Found no cargo with tracking id 'XXX'." ) ) );
-    }
-
-    @Test
-    public void deviation_3c_CargoNotRoutedYet() throws Exception
-    {
-        TrackingId nonRoutedTrackingId = new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, day( 17 ) ).createCargo( "NonRoutedCargo" );
-        String nonRouted = nonRoutedTrackingId.id().get();
-
-        msg = register( time, time, nonRouted, "RECEIVE", "CNHKG", null );
-        assertThat( msg, is( equalTo( "Can't create handling event for non-routed cargo '" + nonRouted + "'." ) ) );
-    }
-
-    @Test
-    public void deviation_3d_NoLocationWithUnlocode() throws Exception
-    {
-        msg = register( time, time, trackId, "RECEIVE", "ZZZZZ", null );
-        assertThat( msg, is( equalTo( "Unknown location: ZZZZZ" ) ) );
-    }
-
-    @Test
-    public void deviation_3e_1a_MissingVoyageNumber() throws Exception
-    {
-        msg = register( time, time, trackId, "LOAD", "CNHKG", null );
-        assertThat( msg, is( equalTo( "Handling event LOAD requires a voyage. No voyage number submitted." ) ) );
-    }
-
-    @Test
-    public void deviation_3e_1b_MissingVoyage() throws Exception
-    {
-        msg = register( time, time, trackId, "LOAD", "CNHKG", "V600S" );
-        assertThat( msg, is( equalTo( "Found no voyage with voyage number 'V600S'." ) ) );
-    }
-
-    @Test
-    public void deviation_3f_SkipVoyageNumberSilentlyWhenProhibited() throws Exception
-    {
-        new RegisterHandlingEvent( time, time, trackId, "RECEIVE", "CNHKG", "V100S" ).register();
-        assertThat( cargo.delivery().get().currentVoyage().get(), is( equalTo( null ) ) );
-    }
-
-    @Test
-    public void step_3_to_5_ValidRegistration__Load_in_Hong_Kong() throws Exception
-    {
-        new RegisterHandlingEvent( time, time, trackId, "LOAD", "CNHKG", "V100S" ).register();
-
-        Delivery delivery = cargo.delivery().get();
-        assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
-        assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.ONBOARD_CARRIER ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( UNLOAD ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( NEWYORK ) ) );
-        assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( V100S ) ) );
-        assertThat( delivery.lastKnownLocation().get(), is( equalTo( HONGKONG ) ) );
-        assertThat( delivery.currentVoyage().get(), is( equalTo( V100S ) ) );
-        assertThat( delivery.eta().get(), is( equalTo( arrival ) ) );
-        assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
-        assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
-    }
-
-
-    private String register( Date registrationTime,
-                             Date completionTime,
-                             String trackingIdString,
-                             String eventTypeString,
-                             String unLocodeString,
-                             String voyageNumberString ) throws Exception
-    {
-        try
-        {
-            new RegisterHandlingEvent( registrationTime,
-                                       completionTime,
-                                       trackingIdString,
-                                       eventTypeString,
-                                       unLocodeString,
-                                       voyageNumberString ).register();
-        }
-        catch (IllegalArgumentException e)
-        {
-            return e.getMessage();
-        }
-        throw new Exception( "Unexpected exception." );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/build.gradle b/samples/dci-cargo/dcisample_b/build.gradle
deleted file mode 100644
index ca9961a..0000000
--- a/samples/dci-cargo/dcisample_b/build.gradle
+++ /dev/null
@@ -1,50 +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.
- */
-
-description = "Sample of how DCI (Data, Context & Interaction) pattern is implemented with Apache Zest™, for Eric Evans DDD sample."
-
-jar { manifest { name = "Apache Zest™ Sample DCI Cargo - Sample B" }}
-
-dependencies {
-
-  compile project( ':org.qi4j.core:org.qi4j.core.bootstrap' )
-  compile project( ':org.qi4j.libraries:org.qi4j.library.constraints' )
-  compile project( ':org.qi4j.libraries:org.qi4j.library.conversion' )
-  compile project( ':org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson' )
-  compile project( ':org.qi4j.extensions:org.qi4j.extension.indexing-rdf' )
-  compile project( ':org.qi4j.tools:org.qi4j.tool.envisage' )
-  compile libraries.jetty_webapp
-  compile libraries.wicket
-  compile libraries.wicket_devutils
-  compile libraries.wicket_stateless
-  compile libraries.slf4j_api
-
-  runtime project( ':org.qi4j.core:org.qi4j.core.runtime' )
-
-  testCompile project( ':org.qi4j.core:org.qi4j.core.testsupport' )
-  testCompile libraries.easymock
-
-  testRuntime libraries.logback
-
-}
-
-task(runSample, dependsOn: 'testClasses', type: JavaExec) {
-    main = 'org.qi4j.sample.dcicargo.sample_b.bootstrap.Start8082'
-    classpath = sourceSets.test.runtimeClasspath
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/api/GraphTraversalService.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/api/GraphTraversalService.java
deleted file mode 100644
index 7fc9dbf..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/api/GraphTraversalService.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.pathfinder_b.api;
-
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.util.Date;
-import java.util.List;
-
-/**
- * Part of the external graph traversal API exposed by the routing team
- * and used by us (booking and tracking team).
- */
-public interface GraphTraversalService extends Remote
-{
-
-    /**
-     * @param departureDate
-     * @param originUnLocode      origin UN Locode
-     * @param destinationUnLocode destination UN Locode
-     *
-     * @return A list of transit paths
-     *
-     * @throws RemoteException RMI problem
-     */
-    List<TransitPath> findShortestPath( Date departureDate, String originUnLocode, String destinationUnLocode )
-        throws RemoteException;
-
-    List<TransitPath> getVoyages()
-        throws RemoteException;
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/api/TransitEdge.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/api/TransitEdge.java
deleted file mode 100644
index 111c941..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/api/TransitEdge.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.pathfinder_b.api;
-
-import java.io.Serializable;
-import java.util.Date;
-
-/**
- * Represents an edge in a path through a graph,
- * describing the route of a cargo.
- */
-public final class TransitEdge implements Serializable
-{
-
-    private final String voyageNumber;
-    private final String fromUnLocode;
-    private final String toUnLocode;
-    private final Date fromDate;
-    private final Date toDate;
-
-    /**
-     * Constructor.
-     *
-     * @param voyageNumber
-     * @param fromUnLocode
-     * @param toUnLocode
-     * @param fromDate
-     * @param toDate
-     */
-    public TransitEdge( final String voyageNumber,
-                        final String fromUnLocode,
-                        final String toUnLocode,
-                        final Date fromDate,
-                        final Date toDate
-    )
-    {
-        this.voyageNumber = voyageNumber;
-        this.fromUnLocode = fromUnLocode;
-        this.toUnLocode = toUnLocode;
-        this.fromDate = fromDate;
-        this.toDate = toDate;
-    }
-
-    public String getVoyageNumber()
-    {
-        return voyageNumber;
-    }
-
-    public String getFromUnLocode()
-    {
-        return fromUnLocode;
-    }
-
-    public String getToUnLocode()
-    {
-        return toUnLocode;
-    }
-
-    public Date getFromDate()
-    {
-        return fromDate;
-    }
-
-    public Date getToDate()
-    {
-        return toDate;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/api/TransitPath.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/api/TransitPath.java
deleted file mode 100644
index cf91921..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/api/TransitPath.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.pathfinder_b.api;
-
-import java.io.Serializable;
-import java.text.SimpleDateFormat;
-import java.util.Collections;
-import java.util.List;
-
-/**
- *
- */
-public final class TransitPath implements Serializable
-{
-
-    private final List<TransitEdge> transitEdges;
-
-    /**
-     * Constructor.
-     *
-     * @param transitEdges The legs for this itinerary.
-     */
-    public TransitPath( final List<TransitEdge> transitEdges )
-    {
-        this.transitEdges = transitEdges;
-    }
-
-    /**
-     * @return An unmodifiable list DTOs.
-     */
-    public List<TransitEdge> getTransitEdges()
-    {
-        return Collections.unmodifiableList( transitEdges );
-    }
-
-    public String print()
-    {
-        StringBuilder sb = new StringBuilder( "\nTRANSIT PATH -----------------------------------------------------" );
-        for( int i = 0; i < transitEdges.size(); i++ )
-        {
-            printLeg( i, sb, transitEdges.get( i ) );
-        }
-        return sb.append( "\n---------------------------------------------------------------\n" ).toString();
-    }
-
-    private void printLeg( int i, StringBuilder sb, TransitEdge edge )
-    {
-        sb.append( "\n  Leg " ).append( i );
-        sb.append( "  Load " );
-        sb.append( new SimpleDateFormat( "yyyy-MM-dd" ).format( edge.getFromDate() ) );
-        sb.append( " " ).append( edge.getFromUnLocode() );
-        sb.append( "   " ).append( edge.getVoyageNumber() );
-        sb.append( "   Unload " );
-        sb.append( new SimpleDateFormat( "yyyy-MM-dd" ).format( edge.getToDate() ) );
-        sb.append( " " ).append( edge.getToUnLocode() );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/api/package.html b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/api/package.html
deleted file mode 100644
index 01921e5..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/api/package.html
+++ /dev/null
@@ -1,23 +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.
--->
-<html>
-<body>
-<p>
-    Public API for the pathfinder application.
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/internal/GraphDAO.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/internal/GraphDAO.java
deleted file mode 100644
index f1929d4..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/internal/GraphDAO.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.pathfinder_b.internal;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Random;
-import org.qi4j.sample.dcicargo.pathfinder_b.api.TransitEdge;
-import org.qi4j.sample.dcicargo.pathfinder_b.api.TransitPath;
-
-public class GraphDAO
-{
-
-    private static final Random random = new Random();
-    private static final long ONE_MIN_MS = 1000 * 60;
-    private static final long ONE_HOUR_MS = ONE_MIN_MS * 60;
-    private static final long ONE_DAY_MS = ONE_HOUR_MS * 24;
-
-    private List<TransitPath> voyages = new ArrayList<TransitPath>();
-
-    public List<String> listLocations()
-    {
-        return new ArrayList<String>( Arrays.asList(
-            "CNHKG", "AUMEL", "SESTO", "FIHEL", "USCHI", "JNTKO", "DEHAM", "CNSHA", "NLRTM", "SEGOT", "CNHGH", "SOMGQ", "USNYC", "USDAL"
-        ) );
-    }
-
-    public List<TransitPath> voyages()
-    {
-        if( voyages.size() > 0 )
-        {
-            return voyages;
-        }
-
-        Date departureDate = new Date();
-        for( int i = 0; i < 50; i++ )
-        {
-            List<String> locations = getRandomChunkOfLocations( listLocations() );
-            final List<TransitEdge> transitEdges = new ArrayList<TransitEdge>( locations.size() - 1 );
-            final String voyageNumber = "V" + ( 101 + i );
-
-            // Origin and destination of voyage schedule
-            String from = locations.remove( 0 );
-            String destination = locations.remove( 0 );
-
-            Date date = nextDate( departureDate );
-            Date fromDate;
-            Date toDate;
-
-            // Carrier movements
-            for( final String to : locations )
-            {
-                fromDate = nextDate( date );
-                toDate = nextDate( fromDate );
-                date = nextDate( toDate );
-                transitEdges.add( new TransitEdge( voyageNumber, from, to, fromDate, toDate ) );
-
-                // Arrival location of last carrier movement becomes departure location of next
-                from = to;
-            }
-
-            // Final carrier movement
-            fromDate = nextDate( date );
-            toDate = nextDate( fromDate );
-            transitEdges.add( new TransitEdge( voyageNumber, from, destination, fromDate, toDate ) );
-
-            voyages.add( new TransitPath( transitEdges ) );
-        }
-
-        return voyages;
-    }
-
-    private Date nextDate( Date date )
-    {
-        return new Date( date.getTime() + ONE_DAY_MS + ( random.nextInt( 1000 ) - 500 ) * ONE_MIN_MS );
-    }
-
-    private List<String> getRandomChunkOfLocations( List<String> allLocations )
-    {
-        Collections.shuffle( allLocations );
-        final int total = allLocations.size();
-        // Including origin and destination
-        final int chunk = total > 6 ? 3 + new Random().nextInt( 5 ) : total;
-        return allLocations.subList( 0, chunk );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/internal/GraphTraversalServiceImpl.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/internal/GraphTraversalServiceImpl.java
deleted file mode 100644
index 9db0e44..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/internal/GraphTraversalServiceImpl.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.pathfinder_b.internal;
-
-import java.rmi.RemoteException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Random;
-import org.qi4j.sample.dcicargo.pathfinder_b.api.GraphTraversalService;
-import org.qi4j.sample.dcicargo.pathfinder_b.api.TransitEdge;
-import org.qi4j.sample.dcicargo.pathfinder_b.api.TransitPath;
-
-public class GraphTraversalServiceImpl
-    implements GraphTraversalService
-{
-    private GraphDAO dao;
-    private Random random;
-
-    public GraphTraversalServiceImpl( GraphDAO dao )
-    {
-        this.dao = dao;
-        this.random = new Random();
-    }
-
-    // Combine existing voyages to create a route.
-    public List<TransitPath> findShortestPath( final Date departureDate,
-                                               final String originUnLocode,
-                                               final String destinationUnLocode
-    )
-    {
-        // Transit paths (itineraries)
-        final int candidateCount = getRandomNumberOfCandidates();
-        final List<TransitPath> routeCandidates = new ArrayList<TransitPath>( candidateCount );
-
-        int maxTries = 50;
-        int tries = 0;
-        do
-        {
-            String expectedDeparture = originUnLocode;
-            Date lastArrivalTime = departureDate;
-
-            // Transit edges (itinerary legs)
-            final List<TransitEdge> routeEdges = new ArrayList<TransitEdge>();
-
-            // Avoid duplicate locations
-            final List<String> oldDepartures = new ArrayList<String>();
-
-            // Loop by depth - enabling chronological order
-            int depth = 0;
-            do
-            {
-                final List<TransitPath> voyages = getShuffledVoyages( dao.voyages() );
-
-                for( TransitPath voyage : voyages )
-                {
-                    if( depth >= voyage.getTransitEdges().size() )
-                    {
-                        continue;
-                    }
-
-                    final TransitEdge voyageEdge = voyage.getTransitEdges().get( depth );
-
-                    final String departure = voyageEdge.getFromUnLocode();
-                    final String arrival = voyageEdge.getToUnLocode();
-                    final Date departureTime = voyageEdge.getFromDate();
-                    final Date arrivalTime = voyageEdge.getToDate();
-
-                    boolean expectsDeparture = departure.equals( expectedDeparture );
-                    boolean uniqueDeparture = !oldDepartures.contains( departure );
-                    boolean uniqueArrival = !oldDepartures.contains( arrival );
-                    boolean afterLastArrivalTime = departureTime.after( lastArrivalTime );
-
-                    if( expectsDeparture && uniqueDeparture && uniqueArrival && afterLastArrivalTime )
-                    {
-                        // Visited departure locations
-                        oldDepartures.add( departure );
-
-                        // Go with this carrier movement
-                        routeEdges.add( voyageEdge );
-
-                        // Current carrier movement destination will be origin of next movement
-                        expectedDeparture = arrival;
-                        lastArrivalTime = arrivalTime;
-
-                        // Go deeper to next edge in transit path (later dates)
-                        break;
-                    }
-                }
-            }
-            while( !expectedDeparture.equals( destinationUnLocode ) && depth++ < 10 );
-
-            // Satisfying routes with at least 2 legs (nextDeparture is the last arrival location)
-            if( expectedDeparture.equals( destinationUnLocode ) && routeEdges.size() > 1 )
-            {
-                routeCandidates.add( new TransitPath( routeEdges ) );
-            }
-        }
-        while( routeCandidates.size() < candidateCount && tries++ < maxTries );
-
-        return routeCandidates;
-    }
-
-    private List<TransitPath> getShuffledVoyages( List<TransitPath> voyages )
-    {
-        Collections.shuffle( voyages );
-        return voyages;
-    }
-
-    public List<TransitPath> getVoyages()
-        throws RemoteException
-    {
-        return dao.voyages();
-    }
-
-    private int getRandomNumberOfCandidates()
-    {
-        return 3 + random.nextInt( 3 );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/internal/package.html b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/internal/package.html
deleted file mode 100644
index 3c4f049..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/internal/package.html
+++ /dev/null
@@ -1,23 +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.
--->
-<html>
-<body>
-<p>
-    Internal parts of the pathfinder application.
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/package.html b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/package.html
deleted file mode 100644
index af1b144..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/pathfinder_b/package.html
+++ /dev/null
@@ -1,31 +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.
--->
-<html>
-<body>
-<p>
-    This is the pathfinder application context, which is separate from "our" application and context.
-    Our domain model with cargo, itinerary, handling event etc does not exist here.
-    The routing domain service implementation works against the API exposed by
-    this context.
-</p>
-
-<p>
-    It is not related to the core application at all, and is only part of this source tree for
-    developer convenience.
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/DCISampleApplication_b.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/DCISampleApplication_b.java
deleted file mode 100644
index 3225e5b..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/DCISampleApplication_b.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.bootstrap;
-
-import java.util.Date;
-import org.apache.wicket.ConverterLocator;
-import org.apache.wicket.Page;
-import org.apache.wicket.datetime.PatternDateConverter;
-import org.apache.wicket.devutils.stateless.StatelessChecker;
-import org.qi4j.sample.dcicargo.sample_b.communication.web.booking.BookNewCargoPage;
-import org.qi4j.sample.dcicargo.sample_b.communication.web.booking.CargoDetailsPage;
-import org.qi4j.sample.dcicargo.sample_b.communication.web.booking.CargoListPage;
-import org.qi4j.sample.dcicargo.sample_b.communication.web.booking.ChangeDestinationPage;
-import org.qi4j.sample.dcicargo.sample_b.communication.web.booking.ReRouteCargoPage;
-import org.qi4j.sample.dcicargo.sample_b.communication.web.booking.RouteCargoPage;
-import org.qi4j.sample.dcicargo.sample_b.communication.web.handling.IncidentLoggingApplicationMockupPage;
-import org.qi4j.sample.dcicargo.sample_b.communication.web.tracking.TrackCargoPage;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.WicketQi4jApplication;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.tabs.TabsPanel;
-
-/**
- * DCI Sample application instance
- *
- * A Wicket application backed by Zest.
- */
-public class DCISampleApplication_b
-    extends WicketQi4jApplication
-{
-    public void wicketInit()
-    {
-        // Tabs and SEO urls
-        mountPages();
-
-        // Show/hide Ajax debugging
-        getDebugSettings().setDevelopmentUtilitiesEnabled( true );
-
-        // Check that components are stateless when required
-        getComponentPostOnBeforeRenderListeners().add( new StatelessChecker() );
-
-        // Show/hide wicket tags in html code
-        getMarkupSettings().setStripWicketTags( true );
-
-        // Default date format (we don't care for now about the hour of the day)
-        ( (ConverterLocator) getConverterLocator() ).set( Date.class, new PatternDateConverter( "yyyy-MM-dd", true ) );
-    }
-
-    private void mountPages()
-    {
-        TabsPanel.registerTab( this, CargoListPage.class, "booking", "Booking and Routing" );
-        TabsPanel.registerTab( this, TrackCargoPage.class, "tracking", "Tracking" );
-        TabsPanel.registerTab( this, IncidentLoggingApplicationMockupPage.class, "handling", "Handling" );
-
-        mountPage( "/booking", CargoListPage.class );
-        mountPage( "/booking/book-new-cargo", BookNewCargoPage.class );
-        mountPage( "/booking/cargo", CargoDetailsPage.class );
-        mountPage( "/booking/change-destination", ChangeDestinationPage.class );
-        mountPage( "/booking/route-cargo", RouteCargoPage.class );
-        mountPage( "/booking/re-route-cargo", ReRouteCargoPage.class );
-
-        mountPage( "/tracking", TrackCargoPage.class );
-
-        mountPage( "/register-handling-event", IncidentLoggingApplicationMockupPage.class );
-    }
-
-    public Class<? extends Page> getHomePage()
-    {
-        return CargoListPage.class;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/VisualizeApplicationStructure.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/VisualizeApplicationStructure.java
deleted file mode 100644
index f17ceb7..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/VisualizeApplicationStructure.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.bootstrap;
-
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.envisage.Envisage;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.assembly.Assembler;
-
-/**
- * Visualize the application assemblage structure.
- */
-public class VisualizeApplicationStructure
-{
-    public static void main( String[] args )
-        throws Exception
-    {
-        Energy4Java qi4j = new Energy4Java();
-        Assembler assembler = new Assembler();
-        ApplicationDescriptor applicationModel = qi4j.newApplicationModel( assembler );
-        applicationModel.newInstance( qi4j.spi() );
-
-        /*
-       * The Envisage Swing app visualizes the application assemblage structure.
-       *
-       * Tree view:
-       * - Click on elements to expand sub-elements.
-       * - Scroll to change font size.
-       * - Right click on viewer to re-size to fit window.
-       *
-       * Stacked view:
-       * - Scroll to zoom in/out of structure levels - might freeze though :-(
-       *
-       * Click on any element and see details of that element in the upper right pane.
-       *
-       * Pretty cool, eh?
-       * */
-        new Envisage().run( applicationModel );
-        int randomTimeoutMs = 18374140;
-        Thread.sleep( randomTimeoutMs );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/assembly/Assembler.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/assembly/Assembler.java
deleted file mode 100644
index f1d0776..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/assembly/Assembler.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.bootstrap.assembly;
-
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.ApplicationAssemblyFactory;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.functional.Function;
-import org.qi4j.index.rdf.RdfIndexingEngineService;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.library.rdf.entity.EntityTypeSerializer;
-import org.qi4j.library.rdf.repository.MemoryRepositoryService;
-import org.qi4j.sample.dcicargo.pathfinder_b.api.GraphTraversalService;
-import org.qi4j.sample.dcicargo.pathfinder_b.internal.GraphDAO;
-import org.qi4j.sample.dcicargo.pathfinder_b.internal.GraphTraversalServiceImpl;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.DCISampleApplication_b;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.sampledata.BaseDataService;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.sampledata.SampleDataService;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.BookingQueries;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.dto.CargoDTO;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.dto.HandlingEventDTO;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.dto.LocationDTO;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.dto.VoyageDTO;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.ProcessHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.ParseHandlingEventData;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-import org.qi4j.sample.dcicargo.sample_b.context.rolemap.CargoRoleMap;
-import org.qi4j.sample.dcicargo.sample_b.context.rolemap.CargosRoleMap;
-import org.qi4j.sample.dcicargo.sample_b.context.rolemap.HandlingEventsRoleMap;
-import org.qi4j.sample.dcicargo.sample_b.context.service.routing.RoutingService;
-import org.qi4j.sample.dcicargo.sample_b.data.entity.HandlingEventEntity;
-import org.qi4j.sample.dcicargo.sample_b.data.entity.LocationEntity;
-import org.qi4j.sample.dcicargo.sample_b.data.entity.VoyageEntity;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.RouteSpecificationFactoryService;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.NextHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Leg;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.UnLocode;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.tracking.TrackingId;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.CarrierMovement;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Schedule;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.VoyageNumber;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.conversion.EntityToDTOService;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-import static org.qi4j.api.common.Visibility.application;
-import static org.qi4j.api.structure.Application.Mode.development;
-
-/**
- * Zest assembly of the DCI Sample application (version B)
- *
- * A Zest application structure is declared by an assembly that defines which layers and modules
- * the application has and how they are allowed to depend on each other. Each layer could have it's
- * own assembly file in larger applications.
- *
- * The Zest assembly doesn't strictly map 1-1 to the directory hierarchy and the assembly
- * structures. An example is the Entities:
- *
- * Data objects (Entities and ValuesComposites) can be promoted to Role Players when they are
- * needed to play a Role in a Context. One Role Map is created for each Data object and it lists
- * Roles in different Contexts that the object can play. It then has knowledge about the Context
- * layer and therefore goes into the CONTEXT-RoleMap module.
- *
- * All other Date objects are candidates to play a role if needed by some context and they "stand by"
- * in the CONTEXT-RoleMapCandidates module. Note that there are still no "physical" upward dependencies
- * from the data package (containing entities and values) to layers above.
- *
- * See more at http://www.qi4j.org/qi4j/70.html
- *
- * TRY THIS:
- * Run VisualizeApplicationStructure to see a cool visualization of the assembly!
- */
-@SuppressWarnings( "unchecked" )
-public class Assembler
-    implements ApplicationAssembler
-{
-    @Override
-    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-        throws AssemblyException
-    {
-        // Application assembly
-        ApplicationAssembly assembly = applicationFactory.newApplicationAssembly();
-        assembly.setName( "DCI Sample (version B)" );
-        assembly.setVersion( "B.1.0" );
-        assembly.setMode( development );
-
-        // Layers (adding bottom-up - will be assembled in this order)
-        LayerAssembly infrastructureLayer = assembly.layer( "INFRASTRUCTURE" );
-        LayerAssembly dataLayer = assembly.layer( "DATA" );
-        LayerAssembly contextLayer = assembly.layer( "CONTEXT" );
-        LayerAssembly communicationLayer = assembly.layer( "COMMUNICATION" );
-        LayerAssembly bootstrapLayer = assembly.layer( "BOOTSTRAP" );
-
-        // Layer dependencies
-        bootstrapLayer.uses(
-            communicationLayer,
-            contextLayer,
-            dataLayer,
-            infrastructureLayer );
-
-        communicationLayer.uses(
-            contextLayer,
-            dataLayer,
-            infrastructureLayer );
-
-        contextLayer.uses(
-            dataLayer,
-            infrastructureLayer );
-
-        dataLayer.uses(
-            infrastructureLayer
-        );
-
-        // Assemble
-        assembleBootstrapLayer( bootstrapLayer );
-        assembleCommunicationLayer( communicationLayer );
-        assembleContextLayer( contextLayer );
-        assembleDataLayer( dataLayer );
-        assembleInfrastructureLayer( infrastructureLayer );
-
-        return assembly;
-    }
-
-    private void assembleBootstrapLayer( LayerAssembly bootstrapLayer )
-        throws AssemblyException
-    {
-        ModuleAssembly bootstrapModule = bootstrapLayer.module( "BOOTSTRAP-Bootstrap" );
-        bootstrapModule
-            .objects(
-                DCISampleApplication_b.class );
-
-        bootstrapModule
-            .addServices(
-                BaseDataService.class )
-            .instantiateOnStartup();
-
-        bootstrapModule
-            .addServices(
-                SampleDataService.class )
-            .instantiateOnStartup();
-    }
-
-    private void assembleCommunicationLayer( LayerAssembly communicationLayer )
-        throws AssemblyException
-    {
-        ModuleAssembly queryModule = communicationLayer.module( "COMMUNICATION-Query" );
-        queryModule
-            .values(
-                CargoDTO.class,
-                LocationDTO.class,
-                HandlingEventDTO.class,
-                VoyageDTO.class );
-
-        queryModule
-            .transients(
-                BookingQueries.class )
-            .visibleIn( application );
-
-        queryModule
-            .addServices(
-                EntityToDTOService.class,
-                OrgJsonValueSerializationService.class )
-            .visibleIn( application );
-    }
-
-    private void assembleContextLayer( LayerAssembly contextLayer )
-        throws AssemblyException
-    {
-        ModuleAssembly roleMapModule = contextLayer.module( "CONTEXT-RoleMap" );
-        roleMapModule
-            .entities(
-                CargoRoleMap.class,
-                CargosRoleMap.class,
-                HandlingEventsRoleMap.class )
-            .visibleIn( application );
-
-        ModuleAssembly roleMapCandidatesModule = contextLayer.module( "CONTEXT-RoleMapCandidates" );
-        roleMapCandidatesModule
-            .entities(
-                HandlingEventEntity.class,
-                LocationEntity.class,
-                VoyageEntity.class )
-            .visibleIn( application );
-
-        roleMapCandidatesModule
-            .values(
-                Itinerary.class )
-            .visibleIn( application );
-
-        ModuleAssembly interactionModule = contextLayer.module( "CONTEXT-Interaction" );
-        interactionModule
-            .transients(
-                ProcessHandlingEvent.class )
-            .visibleIn( application );
-
-        ModuleAssembly contextServiceModule = contextLayer.module( "CONTEXT-Service" );
-        contextServiceModule
-            .addServices(
-                ParseHandlingEventData.class,
-                RoutingService.class,
-                RouteSpecificationFactoryService.class )
-            .visibleIn( application );
-
-        contextServiceModule
-            .values(
-                ParsedHandlingEventData.class )
-            .visibleIn( application );
-    }
-
-    private void assembleDataLayer( LayerAssembly dataLayer )
-        throws AssemblyException
-    {
-        ModuleAssembly dataModule = dataLayer.module( "DATA-Structure" );
-        dataModule
-            .values(
-                TrackingId.class,
-                RouteSpecification.class,
-                Delivery.class,
-                NextHandlingEvent.class,
-                UnLocode.class,
-                Leg.class,
-                CarrierMovement.class,
-                Schedule.class,
-                VoyageNumber.class )
-            .visibleIn( application );
-    }
-
-    private void assembleInfrastructureLayer( LayerAssembly infrastructureLayer )
-        throws AssemblyException
-    {
-        ModuleAssembly serializationModule = infrastructureLayer.module( "INFRASTRUCTURE-Serialization" );
-        serializationModule
-            .services( OrgJsonValueSerializationService.class )
-            .taggedWith( ValueSerialization.Formats.JSON )
-            .setMetaInfo( new Function<Application, Module>()
-        {
-            @Override
-            public Module map( Application application )
-            {
-                return application.findModule( "CONTEXT", "CONTEXT-RoleMap" );
-            }
-        } )
-        .visibleIn( application );
-
-        ModuleAssembly indexingModule = infrastructureLayer.module( "INFRASTRUCTURE-Indexing" );
-        indexingModule
-            .objects(
-                EntityStateSerializer.class,
-                EntityTypeSerializer.class );
-
-        indexingModule
-            .services(
-                MemoryRepositoryService.class,
-                RdfIndexingEngineService.class )
-            .instantiateOnStartup()
-            .visibleIn( application );
-
-        ModuleAssembly entityStoreModule = infrastructureLayer.module( "INFRASTRUCTURE-EntityStore" );
-        entityStoreModule
-            .services(
-                MemoryEntityStoreService.class,
-                UuidIdentityGeneratorService.class )
-            .instantiateOnStartup()
-            .visibleIn( application );
-
-        ModuleAssembly externalServiceModule = infrastructureLayer.module( "INFRASTRUCTURE-ExternalService" );
-        externalServiceModule
-            .importedServices(
-                GraphTraversalService.class )
-            .setMetaInfo( new GraphTraversalServiceImpl( new GraphDAO() ) )
-            .visibleIn( application );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/sampledata/BaseData.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/sampledata/BaseData.java
deleted file mode 100644
index dc2c669..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/sampledata/BaseData.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.bootstrap.sampledata;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.NextHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Leg;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.UnLocode;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.CarrierMovement;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Schedule;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-
-/**
- * Test base class with shared data and factory methods.
- */
-public abstract class BaseData
-{
-    protected UnLocode AUMEL;
-    protected UnLocode CNHGH;
-    protected UnLocode CNHKG;
-    protected UnLocode CNSHA;
-    protected UnLocode DEHAM;
-    protected UnLocode FIHEL;
-    protected UnLocode JNTKO;
-    protected UnLocode NLRTM;
-    protected UnLocode SEGOT;
-    protected UnLocode SESTO;
-    protected UnLocode SOMGQ;
-    protected UnLocode USCHI;
-    protected UnLocode USDAL;
-    protected UnLocode USNYC;
-    protected final Module module;
-
-    protected BaseData( Module module )
-    {
-        this.module = module;
-    }
-
-    protected UnLocode unlocode( String unlocodeString )
-    {
-        ValueBuilder<UnLocode> unlocode = module.newValueBuilder( UnLocode.class );
-        unlocode.prototype().code().set( unlocodeString );
-        return unlocode.newInstance();
-    }
-
-    protected CarrierMovement carrierMovement( Location depLoc, Location arrLoc, Date depTime, Date arrTime )
-    {
-        ValueBuilder<CarrierMovement> carrierMovement = module.newValueBuilder( CarrierMovement.class );
-        carrierMovement.prototype().departureLocation().set( depLoc );
-        carrierMovement.prototype().arrivalLocation().set( arrLoc );
-        carrierMovement.prototype().departureTime().set( depTime );
-        carrierMovement.prototype().arrivalTime().set( arrTime );
-        return carrierMovement.newInstance();
-    }
-
-    protected Schedule schedule( CarrierMovement... carrierMovements )
-    {
-        ValueBuilder<Schedule> schedule = module.newValueBuilder( Schedule.class );
-        List<CarrierMovement> cm = new ArrayList<>();
-        cm.addAll( Arrays.asList( carrierMovements ) );
-        schedule.prototype().carrierMovements().set( cm );
-        return schedule.newInstance();
-    }
-
-    protected Leg leg( Voyage voyage, Location load, Location unload, Date loadTime, Date unloadTime )
-    {
-        ValueBuilder<Leg> leg = module.newValueBuilder( Leg.class );
-        leg.prototype().voyage().set( voyage );
-        leg.prototype().loadLocation().set( load );
-        leg.prototype().unloadLocation().set( unload );
-        leg.prototype().loadTime().set( loadTime );
-        leg.prototype().unloadTime().set( unloadTime );
-        return leg.newInstance();
-    }
-
-    protected Itinerary itinerary( Leg... legArray )
-    {
-        ValueBuilder<Itinerary> itinerary = module.newValueBuilder( Itinerary.class );
-        List<Leg> legs = new ArrayList<>();
-        legs.addAll( Arrays.asList( legArray ) );
-        itinerary.prototype().legs().set( legs );
-        return itinerary.newInstance();
-    }
-
-    protected Delivery delivery(
-        HandlingEvent lastHandlingEvent,
-        TransportStatus transportStatus,
-        Boolean isUnloadedAtDestination,
-        RoutingStatus routingStatus,
-        Boolean isMisdirected,
-        Date eta,
-        Integer itineraryProgressIndex,
-        NextHandlingEvent nextHandlingEvent
-    )
-    {
-        ValueBuilder<Delivery> delivery = module.newValueBuilder( Delivery.class );
-        delivery.prototype().timestamp().set( new Date() );
-        delivery.prototype().lastHandlingEvent().set( lastHandlingEvent );
-        delivery.prototype().transportStatus().set( transportStatus );
-        delivery.prototype().isUnloadedAtDestination().set( isUnloadedAtDestination );
-        delivery.prototype().routingStatus().set( routingStatus );
-        delivery.prototype().isMisdirected().set( isMisdirected );
-        delivery.prototype().eta().set( eta );
-        delivery.prototype().itineraryProgressIndex().set( itineraryProgressIndex );
-        delivery.prototype().nextHandlingEvent().set( nextHandlingEvent );
-        return delivery.newInstance();
-    }
-
-    // Delivery with only mandatory values
-    protected Delivery delivery( Date date,
-                                 TransportStatus transportStatus,
-                                 RoutingStatus routingStatus,
-                                 Integer itineraryProgressIndex
-    )
-    {
-        ValueBuilder<Delivery> delivery = module.newValueBuilder( Delivery.class );
-        delivery.prototype().timestamp().set( date );
-        delivery.prototype().transportStatus().set( transportStatus );
-        delivery.prototype().routingStatus().set( routingStatus );
-        delivery.prototype().itineraryProgressIndex().set( itineraryProgressIndex );
-        return delivery.newInstance();
-    }
-
-    protected NextHandlingEvent nextHandlingEvent( HandlingEventType handlingEventType,
-                                                   Location location,
-                                                   Date time,
-                                                   Voyage voyage
-    )
-    {
-        ValueBuilder<NextHandlingEvent> nextHandlingEvent = module.newValueBuilder( NextHandlingEvent.class );
-        nextHandlingEvent.prototype().handlingEventType().set( handlingEventType );
-        nextHandlingEvent.prototype().location().set( location );
-        nextHandlingEvent.prototype().time().set( time );
-        nextHandlingEvent.prototype().voyage().set( voyage );
-        return nextHandlingEvent.newInstance();
-    }
-
-    protected ParsedHandlingEventData parsedHandlingEventData( Date registrationTime,
-                                                               Date completionTime,
-                                                               String trackingIdString,
-                                                               HandlingEventType handlingEventType,
-                                                               String unLocodeString,
-                                                               String voyageNumberString
-    )
-        throws Exception
-    {
-        ValueBuilder<ParsedHandlingEventData> attempt = module.newValueBuilder( ParsedHandlingEventData.class );
-        attempt.prototype().registrationTime().set( registrationTime );
-        attempt.prototype().completionTime().set( completionTime );
-        attempt.prototype().trackingIdString().set( trackingIdString );
-        attempt.prototype().handlingEventType().set( handlingEventType );
-        attempt.prototype().unLocodeString().set( unLocodeString );
-        attempt.prototype().voyageNumberString().set( voyageNumberString );
-
-        return attempt.newInstance();
-    }
-
-    protected static Date day( int days )
-    {
-        Date today = new Date();
-        long aDay = 24 * 60 * 60 * 1000;
-        return new Date( today.getTime() + days * aDay );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/sampledata/BaseDataService.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/sampledata/BaseDataService.java
deleted file mode 100644
index 8b2830a..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/sampledata/BaseDataService.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.bootstrap.sampledata;
-
-import java.rmi.RemoteException;
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.sample.dcicargo.pathfinder_b.api.GraphTraversalService;
-import org.qi4j.sample.dcicargo.pathfinder_b.api.TransitEdge;
-import org.qi4j.sample.dcicargo.pathfinder_b.api.TransitPath;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.CargoAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.HandlingEventAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.UnLocode;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.CarrierMovement;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Schedule;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.VoyageNumber;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.qi4j.api.usecase.UsecaseBuilder.newUsecase;
-
-/**
- * Create basic sample data on startup of application.
- */
-@Mixins(BaseDataService.Mixin.class)
-@Activators(BaseDataService.Activator.class)
-public interface BaseDataService
-    extends ServiceComposite
-{
-
-    void createBaseData()
-        throws Exception;
-
-    class Activator
-        extends ActivatorAdapter<ServiceReference<BaseDataService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<BaseDataService> activated )
-            throws Exception
-        {
-            activated.get().createBaseData();
-        }
-    }
-
-    public abstract class Mixin
-        extends BaseData
-        implements BaseDataService
-    {
-        @Service
-        GraphTraversalService graphTraversalService;
-
-        private static final Logger logger = LoggerFactory.getLogger( BaseDataService.class );
-
-        protected Mixin( @Structure Module module )
-        {
-            super( module );
-        }
-
-        @Override
-        public void createBaseData()
-            throws Exception
-        {
-            logger.debug( "CREATING BASIC DATA..." );
-
-            UnitOfWork uow = module.newUnitOfWork( newUsecase( "Create base data" ) );
-
-            // Create locations
-            location( unlocode( "AUMEL" ), "Melbourne" );
-            location( unlocode( "CNHGH" ), "Hangzhou" );
-            location( unlocode( "CNHKG" ), "Hongkong" );
-            location( unlocode( "CNSHA" ), "Shanghai" );
-            location( unlocode( "DEHAM" ), "Hamburg" );
-            location( unlocode( "FIHEL" ), "Helsinki" );
-            location( unlocode( "JNTKO" ), "Tokyo" );
-            location( unlocode( "NLRTM" ), "Rotterdam" );
-            location( unlocode( "SEGOT" ), "Gothenburg" );
-            location( unlocode( "SESTO" ), "Stockholm" );
-            location( unlocode( "SOMGQ" ), "Mogadishu" );
-            location( unlocode( "USCHI" ), "Chicago" );
-            location( unlocode( "USDAL" ), "Dallas" );
-            location( unlocode( "USNYC" ), "New York" );
-
-            // Create voyages
-            try
-            {
-                for( TransitPath voyagePath : graphTraversalService.getVoyages() )
-                {
-                    String voyageNumber = null;
-                    List<CarrierMovement> carrierMovements = new ArrayList<>();
-                    for( TransitEdge voyageEdge : voyagePath.getTransitEdges() )
-                    {
-                        voyageNumber = voyageEdge.getVoyageNumber();
-                        Location from = uow.get( Location.class, voyageEdge.getFromUnLocode() );
-                        Location to = uow.get( Location.class, voyageEdge.getToUnLocode() );
-                        carrierMovements.add( carrierMovement( from, to, voyageEdge.getFromDate(), voyageEdge.getToDate() ) );
-                    }
-
-                    ValueBuilder<Schedule> schedule = module.newValueBuilder( Schedule.class );
-                    schedule.prototype().carrierMovements().set( carrierMovements );
-                    voyage( voyageNumber, schedule.newInstance() );
-                }
-            }
-            catch( RemoteException e )
-            {
-                e.printStackTrace();
-            }
-
-            // Cargo and HandlingEvent aggregate roots
-            uow.newEntity( CargoAggregateRoot.class, CargoAggregateRoot.CARGOS_ID );
-            uow.newEntity( HandlingEventAggregateRoot.class, HandlingEventAggregateRoot.HANDLING_EVENTS_ID );
-
-            try
-            {
-                uow.complete();
-                logger.debug( "BASIC DATA CREATED" );
-            }
-            catch( UnitOfWorkCompletionException ex )
-            {
-                uow.discard();
-                logger.error( "UNABLE TO CREATE BASIC DATA" );
-                throw ex;
-            }
-        }
-
-        protected UnLocode unlocode( String unlocodeString )
-        {
-            ValueBuilder<UnLocode> unlocode = module.newValueBuilder( UnLocode.class );
-            unlocode.prototype().code().set( unlocodeString );
-            return unlocode.newInstance();
-        }
-
-        protected Location location( UnLocode unlocode, String locationStr )
-        {
-            UnitOfWork uow = module.currentUnitOfWork();
-            EntityBuilder<Location> location = uow.newEntityBuilder( Location.class, unlocode.code().get() );
-            location.instance().unLocode().set( unlocode );
-            location.instance().name().set( locationStr );
-            return location.newInstance();
-        }
-
-        protected Voyage voyage( String voyageNumberStr, Schedule schedule )
-        {
-            UnitOfWork uow = module.currentUnitOfWork();
-            EntityBuilder<Voyage> voyage = uow.newEntityBuilder( Voyage.class, voyageNumberStr );
-
-            // VoyageNumber
-            ValueBuilder<VoyageNumber> voyageNumber = module.newValueBuilder( VoyageNumber.class );
-            voyageNumber.prototype().number().set( voyageNumberStr );
-            voyage.instance().voyageNumber().set( voyageNumber.newInstance() );
-
-            // Schedule
-            voyage.instance().schedule().set( schedule );
-            return voyage.newInstance();
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/sampledata/SampleDataService.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/sampledata/SampleDataService.java
deleted file mode 100644
index 753e232..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/sampledata/SampleDataService.java
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.bootstrap.sampledata;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Random;
-import java.util.UUID;
-import org.joda.time.DateTime;
-import org.joda.time.LocalDate;
-import org.joda.time.LocalTime;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.BookNewCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.routing.AssignCargoToRoute;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.ProcessHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectUnhandledCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-import org.qi4j.sample.dcicargo.sample_b.context.service.routing.RoutingService;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.CargoAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.RouteSpecificationFactoryService;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.NextHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.CarrierMovement;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.qi4j.api.usecase.UsecaseBuilder.newUsecase;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.CLAIM;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.CUSTOMS;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.LOAD;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.RECEIVE;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.UNLOAD;
-import static org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.Context.prepareContextBaseClass;
-
-/**
- * Create sample cargos in different delivery stages.
- *
- * Add more cases if needed in the loop below.
- */
-@Mixins(SampleDataService.Mixin.class)
-@Activators(SampleDataService.Activator.class)
-public interface SampleDataService
-    extends ServiceComposite
-{
-    void insertSampleData()
-        throws Exception;
-
-    class Activator
-        extends ActivatorAdapter<ServiceReference<SampleDataService>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<SampleDataService> activated )
-            throws Exception
-        {
-            activated.get().insertSampleData();
-        }
-    }
-
-    public abstract class Mixin
-        implements SampleDataService
-    {
-        @Structure
-        Module module;
-
-        @Service
-        RoutingService routingService;
-
-        @Service
-        BaseDataService baseDataService;
-
-        @Service
-        RouteSpecificationFactoryService routeSpecFactory;
-
-        private static final Logger logger = LoggerFactory.getLogger( SampleDataService.class );
-
-        @Override
-        public void insertSampleData()
-            throws Exception
-        {
-            prepareContextBaseClass( module );
-
-            logger.info( "######  CREATING SAMPLE DATA...  ##########################################" );
-
-            // Create cargos
-            populateRandomCargos( 12 );
-
-            // Handle cargos
-            UnitOfWork uow = module.newUnitOfWork( newUsecase( "Create sample data" ) );
-            try
-            {
-                int i = 11; // starting at 11 for sortable tracking id prefix in lists
-                QueryBuilder<Cargo> qb = module.newQueryBuilder( Cargo.class );
-                for( Cargo cargo : uow.newQuery( qb ) )
-
-                {
-                    final String trackingId = cargo.trackingId().get().id().get();
-                    final RouteSpecification routeSpec = cargo.routeSpecification().get();
-                    routeSpec.print();
-
-                    NextHandlingEvent nextEvent = null;
-                    Date time = null;
-                    String port = null;
-                    String voyageNumber = null;
-                    Voyage voyage;
-                    HandlingEventType type = null;
-                    String wrongPort = null;
-                    String wrongVoyage = null;
-
-                    // First cargo with id 11 is not routed
-
-                    // ROUTE
-                    if( i > 11 )
-                    {
-                        final List<Itinerary> routes = routingService.fetchRoutesForSpecification( routeSpec );
-                        final Itinerary itinerary = routes.get( 0 );
-                        new AssignCargoToRoute( cargo, itinerary ).assign();
-                    }
-
-                    // MISROUTE: Route specification not satisfied with itinerary
-                    if( i == 12 )
-                    {
-                        Location origin = routeSpec.origin().get();
-                        Location dest = routeSpec.destination().get();
-                        Location badDest = null;
-                        Query<Location> locations = uow.newQuery( module.newQueryBuilder( Location.class ) );
-                        for( Location loc : locations )
-                        {
-                            if( !origin.equals( loc ) && !dest.equals( loc ) )
-                            {
-                                badDest = loc;
-                                break;
-                            }
-                        }
-
-                        final RouteSpecification unsatisfiedRouteSpec =
-                            routeSpecFactory.build( origin, badDest, new Date(), new DateTime().plusDays( 25 )
-                                .toDate() );
-                        cargo.routeSpecification().set( unsatisfiedRouteSpec );
-
-                        new InspectUnhandledCargo( cargo ).inspect();
-                    }
-
-                    // RECEIVE
-                    if( i > 13 )
-                    {
-                        nextEvent = cargo.delivery().get().nextHandlingEvent().get();
-                        port = nextEvent.location().get().getCode();
-                        final Date mockTime = new Date();
-                        registerEvent( mockTime, mockTime, trackingId, RECEIVE, port, null );
-                    }
-
-                    // MISDIRECT: LOAD onto wrong carrier
-                    if( i == 15 )
-                    {
-                        nextEvent = cargo.delivery().get().nextHandlingEvent().get();
-                        time = nextEvent.time().get();
-                        port = nextEvent.location().get().getCode();
-                        voyageNumber = nextEvent.voyage().get().voyageNumber().get().number().get();
-
-                        // Find earliest wrong carrier movement (voyage) with same departure location
-                        final Query<Voyage> voyages = module.currentUnitOfWork()
-                            .newQuery( module.newQueryBuilder( Voyage.class ) );
-                        int depth = 0;
-                        do
-                        {
-                            for( Voyage voy : voyages )
-                            {
-                                if( voy.voyageNumber().get().number().get().equals( voyageNumber ) )
-                                {
-                                    continue;
-                                }
-
-                                if( depth >= voy.schedule().get().carrierMovements().get().size() )
-                                {
-                                    continue;
-                                }
-
-                                // Carrier movement at current depth
-                                final CarrierMovement movement = voy.schedule()
-                                    .get()
-                                    .carrierMovements()
-                                    .get()
-                                    .get( depth );
-                                final boolean goingFromSamePort = movement.departureLocation()
-                                    .get()
-                                    .getCode()
-                                    .equals( port );
-                                final boolean notGoingToDestination = !movement.arrivalLocation()
-                                    .get()
-                                    .equals( routeSpec.destination().get() );
-
-                                if( goingFromSamePort && notGoingToDestination )
-                                {
-                                    wrongVoyage = voy.voyageNumber().get().number().get();
-                                    break;
-                                }
-                            }
-                        }
-                        while( wrongVoyage == null && depth++ < 10 );
-
-                        registerEvent( time, time, trackingId, LOAD, port, wrongVoyage );
-                    }
-
-                    // LOAD
-                    if( i > 15 )
-                    {
-                        nextEvent = cargo.delivery().get().nextHandlingEvent().get();
-                        time = nextEvent.time().get();
-                        port = nextEvent.location().get().getCode();
-                        voyageNumber = nextEvent.voyage().get().voyageNumber().get().number().get();
-                        registerEvent( time, time, trackingId, LOAD, port, voyageNumber );
-
-                        // Cargo is now on board carrier
-                        nextEvent = cargo.delivery().get().nextHandlingEvent().get();
-                        time = nextEvent.time().get();
-                        type = nextEvent.handlingEventType().get();
-                        port = nextEvent.location().get().getCode();
-                        voyageNumber = nextEvent.voyage().get().voyageNumber().get().number().get();
-                    }
-
-                    // MISDIRECT: UNLOAD from carrier in wrong location
-                    if( i == 17 )
-                    {
-                        voyage = uow.get( Voyage.class, voyageNumber );
-                        for( CarrierMovement movement : voyage.schedule().get().carrierMovements().get() )
-                        {
-                            final String arrivalPort = movement.arrivalLocation().get().getCode();
-
-                            // Take first voyage with different arrival location
-                            if( !arrivalPort.equals( port ) )
-                            {
-                                wrongPort = movement.arrivalLocation().get().unLocode().get().code().get();
-                                break;
-                            }
-                        }
-                        registerEvent( time, time, trackingId, UNLOAD, wrongPort, voyageNumber );
-                    }
-
-                    // UNLOAD
-                    if( i > 17 )
-                    {
-                        nextEvent = cargo.delivery().get().nextHandlingEvent().get();
-                        time = nextEvent.time().get();
-                        port = nextEvent.location().get().getCode();
-                        voyageNumber = nextEvent.voyage().get().voyageNumber().get().number().get();
-                        registerEvent( time, time, trackingId, UNLOAD, port, voyageNumber );
-
-                        // Cargo is now in midpoint location
-                        nextEvent = cargo.delivery().get().nextHandlingEvent().get();
-                        time = nextEvent.time().get();
-                        type = nextEvent.handlingEventType().get();
-                        port = nextEvent.location().get().getCode();
-                    }
-
-                    // CUSTOMS: Customs handling in midpoint location (doesn't affect misdirection status)
-                    if( i == 19 )
-                    {
-                        registerEvent( time, time, trackingId, CUSTOMS, port, null );
-                    }
-
-                    // MISDIRECT: Unexpected claim before reaching destination
-                    if( i == 20 )
-                    {
-                        registerEvent( time, time, trackingId, CLAIM, port, null );
-                    }
-
-                    // Complete all LOAD/UNLOADS
-                    if( i > 20 )
-                    {
-                        do
-                        {
-                            //noinspection ConstantConditions
-                            voyageNumber = nextEvent.voyage().get().voyageNumber().get().number().get();
-                            registerEvent( time, time, trackingId, type, port, voyageNumber );
-
-                            nextEvent = cargo.delivery().get().nextHandlingEvent().get();
-                            time = nextEvent.time().get();
-                            port = nextEvent.location().get().getCode();
-                            type = nextEvent.handlingEventType().get();
-                        }
-                        while( type != HandlingEventType.CLAIM );
-                    }
-
-                    // CLAIM at destination - this ends the life cycle of the cargo delivery
-                    if( i == 22 )
-                    {
-                        registerEvent( time, time, trackingId, CLAIM, port, null );
-                    }
-
-                    // Add more cases if needed...
-                    i++;
-                }
-
-                uow.complete();
-            }
-            catch( Exception e )
-            {
-                uow.discard();
-                logger.error( "Problem handling cargos: " + e.getMessage() );
-                throw e;
-            }
-
-            logger.info( "######  SAMPLE DATA CREATED  ##############################################" );
-        }
-
-        private void populateRandomCargos( int numberOfCargos )
-        {
-            Usecase usecase = UsecaseBuilder.newUsecase( "Populate Random Cargos" );
-            UnitOfWork uow = module.newUnitOfWork( usecase );
-
-            CargoAggregateRoot cargos = uow.get( CargoAggregateRoot.class, CargoAggregateRoot.CARGOS_ID );
-
-            Query<Location> allLocations = uow.newQuery( module.newQueryBuilder( Location.class ) );
-            int locationSize = (int) allLocations.count();
-
-            // Make array for selection of location with random index
-            final List<Location> locationList = new ArrayList<>();
-            for( Location location : allLocations )
-            {
-                locationList.add( location );
-            }
-
-            Location origin;
-            Location destination;
-            Random random = new Random();
-            Date deadline;
-            String uuid;
-            String id;
-            try
-            {
-                for( int i = 0; i < numberOfCargos; i++ )
-                {
-                    origin = locationList.get( random.nextInt( locationSize ) );
-
-                    // Find destination different from origin
-                    do
-                    {
-                        destination = locationList.get( random.nextInt( locationSize ) );
-                    }
-                    while( destination.equals( origin ) );
-
-                    deadline = new LocalDate().plusDays( 35 + random.nextInt( 10 ) )
-                        .toDateTime( new LocalTime() )
-                        .toDate();
-
-                    // Build sortable random tracking ids
-                    uuid = UUID.randomUUID().toString().toUpperCase();
-                    id = ( i + 11 ) + "-" + uuid.substring( 0, uuid.indexOf( "-" ) );
-
-                    new BookNewCargo( cargos, origin, destination, deadline ).withTrackingId( id );
-                }
-                uow.complete();
-            }
-            catch( Exception e )
-            {
-                uow.discard();
-                logger.error( "Problem booking a new cargo: " + e.getMessage() );
-            }
-        }
-
-        private void registerEvent( Date registrationTime,
-                                    Date completionTime,
-                                    String trackingIdString,
-                                    HandlingEventType handlingEventType,
-                                    String unLocodeString,
-                                    String voyageNumberString
-        )
-            throws Exception
-        {
-            ValueBuilder<ParsedHandlingEventData> event = module.newValueBuilder( ParsedHandlingEventData.class );
-            event.prototype().registrationTime().set( registrationTime );
-            event.prototype().completionTime().set( completionTime );
-            event.prototype().trackingIdString().set( trackingIdString );
-            event.prototype().handlingEventType().set( handlingEventType );
-            event.prototype().unLocodeString().set( unLocodeString );
-            event.prototype().voyageNumberString().set( voyageNumberString );
-
-            module.newTransient( ProcessHandlingEvent.class ).register( event.newInstance() );
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/BookingQueries.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/BookingQueries.java
deleted file mode 100644
index a224f17..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/BookingQueries.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.query;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.wicket.model.IModel;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.sample.dcicargo.sample_b.context.service.routing.RoutingService;
-import org.qi4j.sample.dcicargo.sample_b.context.service.routing.exception.FoundNoRoutesException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.model.JSONModel;
-
-/**
- * Booking queries
- *
- * Implemented as a Zest composite since we can then conveniently get the routing service injected.
- * We could choose to implement all query classes like this too.
- *
- * Used by the communication layer only. Can change according to ui needs.
- */
-@Mixins( BookingQueries.Mixin.class )
-public interface BookingQueries
-    extends TransientComposite
-{
-    List<IModel<Itinerary>> routeCandidates( String trackingIdString )
-        throws FoundNoRoutesException;
-
-    List<IModel<Itinerary>> routeCandidates( RouteSpecification routeSpec )
-        throws FoundNoRoutesException;
-
-    abstract class Mixin
-        implements BookingQueries
-    {
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        @Service
-        RoutingService routingService;
-
-        public List<IModel<Itinerary>> routeCandidates( final String trackingIdString )
-            throws FoundNoRoutesException
-        {
-            Cargo cargo = uowf.currentUnitOfWork().get( Cargo.class, trackingIdString );
-            RouteSpecification routeSpec = cargo.routeSpecification().get();
-
-            return routeCandidates( routeSpec );
-        }
-
-        public List<IModel<Itinerary>> routeCandidates( final RouteSpecification routeSpec )
-            throws FoundNoRoutesException
-        {
-            List<Itinerary> routes = routingService.fetchRoutesForSpecification( routeSpec );
-
-            List<IModel<Itinerary>> modelList = new ArrayList<IModel<Itinerary>>();
-            for( Itinerary itinerary : routes )
-            {
-                modelList.add( JSONModel.of( itinerary ) );
-            }
-
-            return modelList;
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/CommonQueries.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/CommonQueries.java
deleted file mode 100644
index 811f35a..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/CommonQueries.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.query;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.wicket.model.IModel;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.dto.CargoDTO;
-import org.qi4j.sample.dcicargo.sample_b.data.entity.CargoEntity;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.model.EntityModel;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.model.Queries;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.model.QueryModel;
-
-import static org.qi4j.api.query.QueryExpressions.orderBy;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-/**
- * Common queries
- *
- * Queries shared by Contexts in different packages.
- *
- * Used by the communication layer only. Can change freely according to presentation needs.
- */
-public class CommonQueries extends Queries
-{
-    public IModel<CargoDTO> cargo( String trackingId )
-    {
-        return EntityModel.of( CargoEntity.class, trackingId, CargoDTO.class );
-    }
-
-    public IModel<List<CargoDTO>> cargoList()
-    {
-        return new QueryModel<CargoDTO, CargoEntity>( CargoDTO.class )
-        {
-            public Query<CargoEntity> getQuery()
-            {
-                QueryBuilder<CargoEntity> qb = qbf.newQueryBuilder( CargoEntity.class );
-                return uowf.currentUnitOfWork().newQuery( qb )
-                    .orderBy( orderBy( templateFor( CargoEntity.class ).trackingId().get().id() ) );
-            }
-        };
-    }
-
-    public List<String> unLocodes()
-    {
-        QueryBuilder<Location> qb = qbf.newQueryBuilder( Location.class );
-        Query<Location> locations = uowf.currentUnitOfWork().newQuery( qb )
-            .orderBy( orderBy( templateFor( Location.class ).unLocode().get().code() ) );
-        List<String> unLocodeList = new ArrayList<String>();
-        for( Location location : locations )
-        {
-            unLocodeList.add( location.getCode() );
-        }
-
-        return unLocodeList;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/HandlingQueries.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/HandlingQueries.java
deleted file mode 100644
index c3158cf..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/HandlingQueries.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.query;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.sample.dcicargo.sample_b.data.entity.CargoEntity;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.model.Queries;
-
-import static org.qi4j.api.query.QueryExpressions.orderBy;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-/**
- * Handling queries
- *
- * Used by the communication layer only. Can change freely according to presentation needs.
- */
-public class HandlingQueries extends Queries
-{
-    public List<String> voyages()
-    {
-        QueryBuilder<Voyage> qb = qbf.newQueryBuilder( Voyage.class );
-        Query<Voyage> voyages = uowf.currentUnitOfWork().newQuery( qb )
-            .orderBy( orderBy( templateFor( Voyage.class ).voyageNumber() ) );
-
-        List<String> voyageList = new ArrayList<String>();
-        for( Voyage voyage : voyages )
-        {
-            voyageList.add( voyage.voyageNumber().get().number().get() );
-        }
-        return voyageList;
-    }
-
-    public List<String> cargoIds()
-    {
-        QueryBuilder<CargoEntity> qb = qbf.newQueryBuilder( CargoEntity.class );
-        Query<CargoEntity> cargos = uowf.currentUnitOfWork().newQuery( qb )
-            .orderBy( orderBy( templateFor( CargoEntity.class ).trackingId().get().id() ) );
-        List<String> cargoList = new ArrayList<String>();
-        for( CargoEntity cargo : cargos )
-        {
-            cargoList.add( cargo.trackingId().get().id().get() );
-        }
-        return cargoList;
-    }
-
-    public List<String> eventTypes()
-    {
-        List<String> eventTypes = new ArrayList<String>();
-        for( HandlingEventType eventType : HandlingEventType.values() )
-        {
-            eventTypes.add( eventType.name() );
-        }
-        return eventTypes;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/TrackingQueries.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/TrackingQueries.java
deleted file mode 100644
index 2a77a9f..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/TrackingQueries.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.query;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.wicket.model.IModel;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.QueryExpressions;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.dto.HandlingEventDTO;
-import org.qi4j.sample.dcicargo.sample_b.data.entity.CargoEntity;
-import org.qi4j.sample.dcicargo.sample_b.data.entity.HandlingEventEntity;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.model.Queries;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.model.QueryModel;
-
-import static org.qi4j.api.query.QueryExpressions.*;
-
-/**
- * Tracking queries
- *
- * Used by the communication layer only. Can change freely according to presentation needs.
- */
-public class TrackingQueries extends Queries
-{
-    public List<String> routedCargos()
-    {
-        Cargo cargoEntity = templateFor( CargoEntity.class );
-
-        QueryBuilder<CargoEntity> qb = qbf.newQueryBuilder( CargoEntity.class )
-            .where( isNotNull( cargoEntity.itinerary() ) );
-        Query<CargoEntity> cargos = uowf.currentUnitOfWork().newQuery( qb )
-            .orderBy( orderBy( cargoEntity.trackingId().get().id() ) );
-
-        List<String> cargoList = new ArrayList<String>();
-        for( CargoEntity cargo : cargos )
-        {
-            cargoList.add( cargo.trackingId().get().id().get() );
-        }
-
-        return cargoList;
-    }
-
-    public IModel<List<HandlingEventDTO>> events( final String trackingIdString )
-    {
-        return new QueryModel<HandlingEventDTO, HandlingEventEntity>( HandlingEventDTO.class )
-        {
-            public Query<HandlingEventEntity> getQuery()
-            {
-                HandlingEvent eventTemplate = templateFor( HandlingEvent.class );
-
-                QueryBuilder<HandlingEventEntity> qb = qbf.newQueryBuilder( HandlingEventEntity.class )
-                    .where( QueryExpressions.eq( eventTemplate.trackingId().get().id(), trackingIdString ) );
-                return uowf.currentUnitOfWork().newQuery( qb )
-                    .orderBy( orderBy( eventTemplate.completionTime() ) );
-            }
-        };
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/dto/CargoDTO.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/dto/CargoDTO.java
deleted file mode 100644
index d9ca4ef..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/dto/CargoDTO.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.query.dto;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-import org.qi4j.library.conversion.values.Unqualified;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.tracking.TrackingId;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.conversion.DTO;
-
-/**
- * Cargo DTO
- *
- * Zest-comment:
- * We need the @Unqualified annotation since the CargoDTO interface has other properties than {@link Cargo}
- * so that properties can not be directly mapped when we convert from entity to immutable value DTO.
- * With the annotation, property access methods are compared by name instead.
- *
- * @see Cargo
- */
-@Unqualified
-public interface CargoDTO extends DTO
-{
-    Property<TrackingId> trackingId();
-
-    // Associated Location entity in Cargo is converted to an immutable LocationDTO value object
-    Property<LocationDTO> origin();
-
-    Property<RouteSpecification> routeSpecification();
-
-    Property<Delivery> delivery();
-
-    @Optional
-    Property<Itinerary> itinerary();
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/dto/HandlingEventDTO.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/dto/HandlingEventDTO.java
deleted file mode 100644
index c0a21b2..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/dto/HandlingEventDTO.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.query.dto;
-
-import java.util.Date;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-import org.qi4j.library.conversion.values.Unqualified;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.tracking.TrackingId;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.conversion.DTO;
-
-/**
- * HandlingEvent DTO
- *
- * Zest-comment:
- * We need the @Unqualified annotation since the HandlingEventDTO interface has other properties than
- * {@link HandlingEvent} so that properties can not be directly mapped when we convert from entity to
- * immutable value DTO. With the annotation, property access methods are compared by name instead.
- */
-@Unqualified
-public interface HandlingEventDTO extends DTO
-{
-    Property<Date> completionTime();
-
-    Property<TrackingId> trackingId();
-
-    Property<HandlingEventType> handlingEventType();
-
-    Property<LocationDTO> location();
-
-    @Optional
-    Property<VoyageDTO> voyage();
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/dto/LocationDTO.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/dto/LocationDTO.java
deleted file mode 100644
index a52b79d..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/dto/LocationDTO.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.query.dto;
-
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.conversion.DTO;
-
-/**
- * Location DTO
- *
- * Since all properties of Location are immutable, we can simply re-use the same interface.
- * We need the Location as a DTO when we do entity to value conversions.
- */
-public interface LocationDTO extends Location, DTO
-{
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/dto/VoyageDTO.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/dto/VoyageDTO.java
deleted file mode 100644
index e27bc91..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/query/dto/VoyageDTO.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.query.dto;
-
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.conversion.DTO;
-
-/**
- * Voyage DTO
- *
- * Since all properties of Voyage are immutable, we can simply re-use the same interface.
- * We need the Voyage as a DTO when we do entity to value conversions.
- */
-public interface VoyageDTO extends Voyage, DTO
-{
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/BasePage.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/BasePage.java
deleted file mode 100644
index f7df26e..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/BasePage.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.web;
-
-import com.google.code.joliratools.StatelessAjaxFallbackLink;
-import org.apache.wicket.AttributeModifier;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.link.Link;
-import org.apache.wicket.markup.html.panel.Fragment;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.WicketQi4jApplication;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.page.BaseWebPage;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.tabs.TabsPanel;
-//import org.wicketstuff.stateless.StatelessAjaxFallbackLink;
-
-/**
- * Base Wicket page of the DCI Sample application
- */
-public class BasePage extends BaseWebPage
-{
-    private final Link toggleLinks;
-    private static boolean showLInks = false;
-    private Fragment links = new Fragment( "links", "linksFragment", this );
-
-    public BasePage( String activeTab )
-    {
-        this( activeTab, null );
-    }
-
-    public BasePage( String activeTab, PageParameters pageParameters )
-    {
-        super( pageParameters );
-
-        toggleLinks = new StatelessAjaxFallbackLink<Void>( "toggleLinks" )
-        {
-            @Override
-            public void onClick( AjaxRequestTarget target )
-            {
-                // Open/close triangle of this toggle link
-                add( new AttributeModifier( "class", Model.of( showLInks ? "closed" : "open" ) ) );
-
-                // Show/hide links
-                links.setVisible( showLInks = !showLInks );
-
-                // Update with ajax if browser allows
-                if( target != null )
-                {
-                    target.add( links, toggleLinks );
-                }
-            }
-        };
-        add( toggleLinks );
-        add( links.setOutputMarkupPlaceholderTag( true ).setVisible( false ) );
-
-        add( new Label( "version", ( (WicketQi4jApplication) getApplication() ).appVersion() ) );
-
-        add( new TabsPanel( activeTab ) );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/BookNewCargoPage.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/BookNewCargoPage.java
deleted file mode 100644
index 8c71905..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/BookNewCargoPage.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.web.booking;
-
-import java.util.Date;
-import java.util.List;
-import org.apache.wicket.Session;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
-import org.apache.wicket.ajax.markup.html.form.AjaxFallbackButton;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.markup.html.panel.ComponentFeedbackPanel;
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.joda.time.LocalDate;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.CommonQueries;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.BookNewCargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.tracking.TrackingId;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.form.AbstractForm;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.form.DateTextFieldWithPicker;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.form.SelectorInForm;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.prevnext.PrevNext;
-
-/**
- * Book new cargo
- *
- * An example of UI validation:
- * - you can't choose equal locations
- * - earliest deadline you can choose from the date picker is tomorrow (we could set any date that the domain wants).
- *
- * More elaborate validation rules could be enforced in a real domain to avoid even touching
- * the backend with invalid data (of course we would still need backend validation).
- */
-public class BookNewCargoPage extends BookingBasePage
-{
-    public BookNewCargoPage()
-    {
-        add( new BookNewCargoForm() );
-    }
-
-    private final class BookNewCargoForm extends AbstractForm<Void>
-    {
-        // Set by Wicket property resolvers:
-        private String origin, destination;
-        private Date deadline;
-
-        public BookNewCargoForm()
-        {
-            List<String> locations = new CommonQueries().unLocodes();
-
-            final FeedbackPanel feedback = new FeedbackPanel( "feedback" );
-            add( feedback.setOutputMarkupId( true ) );
-
-            final SelectorInForm originSelector = new SelectorInForm(
-                "origin", "Origin", locations, this, "destination" );
-            originSelector.setRequired( true );
-
-            final ComponentFeedbackPanel originFeedback = new ComponentFeedbackPanel(
-                "originFeedback", originSelector );
-            add( originFeedback.setOutputMarkupId( true ) );
-
-            final SelectorInForm destinationSelector = new SelectorInForm(
-                "destination", "Destinatin", locations, this, "origin" );
-            destinationSelector.setRequired( true );
-
-            final ComponentFeedbackPanel destinationFeedback = new ComponentFeedbackPanel(
-                "destinationFeedback", destinationSelector );
-            add( destinationFeedback.setOutputMarkupId( true ) );
-
-            // Disable equal locations
-            originSelector.add( new AjaxFormComponentUpdatingBehavior( "onchange" )
-            {
-                @Override
-                protected void onUpdate( AjaxRequestTarget target )
-                {
-                    // Exclude origin in destination drop down
-                    target.add( originSelector, originFeedback, destinationSelector );
-                    focusFirstError( target );
-                }
-            } );
-
-            destinationSelector.add( new AjaxFormComponentUpdatingBehavior( "onchange" )
-            {
-                @Override
-                protected void onUpdate( AjaxRequestTarget target )
-                {
-                    // Exclude destination in origin drop down
-                    target.add( destinationSelector, destinationFeedback, originSelector );
-                    focusFirstError( target );
-                }
-            } );
-
-            // Deadline
-            final DateTextFieldWithPicker deadlineField = new DateTextFieldWithPicker( "deadline", "Arrival deadline", this );
-            deadlineField.earliestDate( new LocalDate().plusDays( 1 ) );
-
-            final ComponentFeedbackPanel deadlineFeedback = new ComponentFeedbackPanel(
-                "deadlineFeedback", deadlineField );
-            add( deadlineFeedback.setOutputMarkupId( true ) );
-
-            add( originSelector, destinationSelector, deadlineField );
-
-            add( new AjaxFallbackButton( "book", this )
-            {
-                @Override
-                protected void onSubmit( AjaxRequestTarget target, Form<?> form )
-                {
-                    try
-                    {
-                        // Perform use case
-                        TrackingId trackingId = new BookNewCargo( origin, destination, deadline ).getTrackingId();
-
-                        // Add new tracking id to list in session
-                        PrevNext.addId( Session.get(), trackingId.id().get() );
-
-                        // Show created cargo
-                        setResponsePage( CargoDetailsPage.class, new PageParameters().set( 0, trackingId.id().get() ) );
-                    }
-                    catch( Exception e )
-                    {
-                        logger.warn( "Problem booking a new cargo: " + e.getMessage() );
-                        feedback.error( e.getMessage() );
-                        target.add( feedback );
-                    }
-                }
-
-                @Override
-                protected void onError( final AjaxRequestTarget target, Form<?> form )
-                {
-                    target.add( originFeedback, destinationFeedback, deadlineFeedback );
-                    focusFirstError( target );
-                }
-            } );
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/BookingBasePage.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/BookingBasePage.java
deleted file mode 100644
index d1effe5..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/BookingBasePage.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.web.booking;
-
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.qi4j.sample.dcicargo.sample_b.communication.web.BasePage;
-
-/**
- * Booking base page - to control the selected tab
- */
-public class BookingBasePage extends BasePage
-{
-    public BookingBasePage()
-    {
-        super( "booking" );
-    }
-
-    public BookingBasePage( PageParameters pageParameters )
-    {
-        super( "booking", pageParameters );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/CargoDetailsPage.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/CargoDetailsPage.java
deleted file mode 100644
index eafd5fe..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/CargoDetailsPage.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.web.booking;
-
-import java.util.Date;
-import java.util.List;
-import org.apache.wicket.AttributeModifier;
-import org.apache.wicket.devutils.stateless.StatelessComponent;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.basic.MultiLineLabel;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.wicket.markup.html.panel.Fragment;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.LoadableDetachableModel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.CommonQueries;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.dto.CargoDTO;
-import org.qi4j.sample.dcicargo.sample_b.communication.web.tracking.HandlingHistoryPanel;
-import org.qi4j.sample.dcicargo.sample_b.communication.web.tracking.NextHandlingEventPanel;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Leg;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.color.CorrectColor;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.color.ErrorColor;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.link.LinkPanel;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.prevnext.PrevNext;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.MISROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.NOT_ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.CLAIMED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.UNKNOWN;
-
-/**
- * Cargo details - an overview of all data available about a cargo.
- *
- * Wicket-comment:
- * The StatelessComponent annotation verifies that this component is not saved in session (remains stateless).
- */
-@StatelessComponent
-public class CargoDetailsPage extends BookingBasePage
-{
-    // Standard constructor for Prev/Next links...
-    public CargoDetailsPage( PageParameters parameters )
-    {
-        this( parameters.get( 0 ).toString() );
-    }
-
-    public CargoDetailsPage( String trackingId )
-    {
-        super( new PageParameters().set( 0, trackingId ) );
-
-        IModel<CargoDTO> cargoModel = new CommonQueries().cargo( trackingId );
-        CargoDTO cargo = cargoModel.getObject();
-        Delivery delivery = cargo.delivery().get();
-        TransportStatus transportStatus = delivery.transportStatus().get();
-        RouteSpecification routeSpecification = cargo.routeSpecification().get();
-        final RoutingStatus routingStatus = delivery.routingStatus().get();
-        boolean isMisrouted = routingStatus == MISROUTED;
-        boolean isReRouted = !cargo.origin().get().getCode().equals( routeSpecification.origin().get().getCode() );
-
-        add( new PrevNext( "prevNext", CargoDetailsPage.class, trackingId ) );
-
-        add( new Label( "trackingId", trackingId ) );
-
-        // Show both cargo origin and new route spec origin when re-routed during transport
-        if( isReRouted )
-        {
-            Fragment originFragment = new Fragment( "origin", "re-routed-originFragment", this );
-            originFragment.add( new Label( "cargoOrigin", cargo.origin().get().getString() ) );
-            originFragment.add( new Label( "routeOrigin", routeSpecification.origin()
-                .get()
-                .getString() ).add( new CorrectColor( isMisrouted ) ) );
-            add( originFragment );
-        }
-        else
-        {
-            Fragment originFragment = new Fragment( "origin", "originFragment", this );
-            originFragment.add( new Label( "cargoOrigin", cargo.origin().get().getString() ) );
-            add( originFragment );
-        }
-
-        add( new Label( "departure", Model.of( routeSpecification.earliestDeparture().get() ) ) );
-        add( new Label( "destination", routeSpecification.destination()
-            .get()
-            .getString() ).add( new CorrectColor( isMisrouted ) ) );
-        add( new Label( "deadline", Model.of( routeSpecification.arrivalDeadline().get() ) ) );
-        add( new Label( "routingStatus", routingStatus.toString() ).add( new ErrorColor( isMisrouted ) ) );
-        add( new LinkPanel( "changeDestination", ChangeDestinationPage.class, trackingId, "Change destination" ) );
-
-        if( transportStatus.equals( CLAIMED ) )
-        {
-            // Can't re-route claimed cargo
-            add( new Label( "routingAction" ) );
-            add( new DeliveryFragment( delivery ) );
-            add( new ItineraryFragment( cargoModel, routingStatus ) );
-        }
-        else if( routingStatus.equals( NOT_ROUTED ) )
-        {
-            add( new LinkPanel( "routingAction", RouteCargoPage.class, trackingId, "Route" ) );
-            add( new Label( "delivery" ) );
-            add( new Label( "itinerary" ) );
-        }
-        else
-        {
-            add( new LinkPanel( "routingAction", ReRouteCargoPage.class, trackingId, "Re-route" ) );
-            add( new DeliveryFragment( delivery ) );
-            add( new ItineraryFragment( cargoModel, routingStatus ) );
-        }
-
-        if( delivery.lastHandlingEvent().get() == null )
-        {
-            add( new Label( "handlingHistoryPanel" ) );
-        }
-        else
-        {
-            add( new HandlingHistoryPanel( "handlingHistoryPanel", cargoModel, trackingId ) );
-        }
-
-        add( new NextHandlingEventPanel( "nextHandlingEventPanel", cargoModel ) );
-    }
-
-    private class ItineraryFragment extends Fragment
-    {
-        public ItineraryFragment( final IModel<CargoDTO> cargoModel, final RoutingStatus routingStatus )
-        {
-            super( "itinerary", "itineraryFragment", CargoDetailsPage.this );
-
-            IModel<List<Leg>> legListModel = new LoadableDetachableModel<List<Leg>>()
-            {
-                @Override
-                protected List<Leg> load()
-                {
-                    return cargoModel.getObject().itinerary().get().legs().get();
-                }
-            };
-
-            add( new ListView<Leg>( "legs", legListModel )
-            {
-                @Override
-                protected void populateItem( ListItem<Leg> item )
-                {
-                    Leg leg = item.getModelObject();
-
-                    item.add( new Label( "loadLocation", leg.loadLocation().get().getCode() ) );
-                    item.add( new Label( "loadTime", new Model<Date>( leg.loadTime().get() ) ) );
-                    item.add( new Label( "voyage", leg.voyage().get().voyageNumber().get().number().get() ) );
-
-                    Boolean isMisrouted = routingStatus == MISROUTED && item.getIndex() == ( getList().size() - 1 );
-                    item.add( new Label( "unloadLocation", leg.unloadLocation().get().getCode() )
-                                  .add( new ErrorColor( isMisrouted ) ) );
-
-                    item.add( new Label( "unloadTime", new Model<Date>( leg.unloadTime().get() ) ) );
-                }
-            } );
-        }
-    }
-
-    private class DeliveryFragment extends Fragment
-    {
-        public DeliveryFragment( Delivery delivery )
-        {
-            super( "delivery", "deliveryFragment", CargoDetailsPage.this );
-
-            if( delivery.transportStatus().get().equals( UNKNOWN ) )
-            {
-                String msg = "UNKNOWN \n(Could be hi-jacked)";
-                add( new MultiLineLabel( "transportStatus", msg ).add( new AttributeModifier( "class", "errorColor" ) ) );
-            }
-            else
-            {
-                add( new Label( "transportStatus", delivery.transportStatus().get().toString() ) );
-            }
-
-            if( delivery.isMisdirected().get() )
-            {
-                String msg = "Cargo is misdirected \nPlease reroute cargo";
-                if( delivery.transportStatus().get().equals( CLAIMED ) )
-                {
-                    msg = "Cargo is misdirected \n(Can't re-route claimed cargo)";
-                }
-
-                add( new MultiLineLabel( "deliveryStatus", msg ).add( new AttributeModifier( "class", "errorColor" ) ) );
-            }
-            else
-            {
-                add( new Label( "deliveryStatus", "On track" ) );
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/CargoListPage.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/CargoListPage.java
deleted file mode 100644
index dc569bb..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/CargoListPage.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.web.booking;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import org.apache.wicket.Session;
-import org.apache.wicket.devutils.stateless.StatelessComponent;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.CommonQueries;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.dto.CargoDTO;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.color.ErrorColor;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.link.LinkPanel;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.prevnext.PrevNext;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.UNKNOWN;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.CUSTOMS;
-
-/**
- * List of Cargos
- */
-@StatelessComponent
-public class CargoListPage extends BookingBasePage
-{
-    public CargoListPage()
-    {
-        IModel<List<CargoDTO>> cargoList = new CommonQueries().cargoList();
-
-        // Save current trackingIds in session (for prev/next buttons on details page)
-        ArrayList<String> ids = new ArrayList<String>();
-        for( CargoDTO cargo : cargoList.getObject() )
-        {
-            ids.add( cargo.trackingId().get().id().get() );
-        }
-        PrevNext.registerIds( Session.get(), ids );
-
-        add( new ListView<CargoDTO>( "list", cargoList )
-        {
-            @Override
-            protected void populateItem( ListItem<CargoDTO> item )
-            {
-                // Cargo
-                CargoDTO cargo = item.getModelObject();
-                String trackingId = cargo.trackingId().get().id().get();
-                String origin = cargo.origin().get().getCode();
-
-                // Route specification
-                RouteSpecification routeSpec = cargo.routeSpecification().get();
-                String destination = routeSpec.destination().get().getCode();
-                Date deadline = routeSpec.arrivalDeadline().get();
-
-                // Routing status
-                Delivery delivery = cargo.delivery().get();
-                RoutingStatus routingStatus = cargo.delivery().get().routingStatus().get();
-                boolean isMisrouted = routingStatus == RoutingStatus.MISROUTED;
-
-                // Transport status
-                TransportStatus transportStatus = delivery.transportStatus().get();
-                boolean isHiJacked = transportStatus.equals( UNKNOWN );
-
-                // Delivery status
-                boolean isMisdirected = delivery.isMisdirected().get();
-                HandlingEvent event = delivery.lastHandlingEvent().get();
-                boolean inCustoms = event != null && event.handlingEventType().get() == CUSTOMS;
-
-                // Output
-
-                item.add( new LinkPanel( "trackingId", CargoDetailsPage.class, trackingId ) );
-
-                item.add( new Label( "origin", origin ) );
-
-                item.add( new Label( "destination", destination ) );
-
-                item.add( new Label( "deadline", new Model<Date>( deadline ) ) );
-
-                item.add( new Label( "routingStatus", routingStatus.toString() ).add( new ErrorColor( isMisrouted ) ) );
-
-                String customsLabel = transportStatus.name() + ( inCustoms ? " (CUSTOMS)" : "" );
-                item.add( new Label( "transportStatus", customsLabel ).add( new ErrorColor( isHiJacked ) ) );
-
-                String directed = isMisdirected ? "Misdirected" : "On track";
-                item.add( new Label( "deliveryStatus", directed ).add( new ErrorColor( isMisdirected ) ) );
-            }
-        } );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/ChangeDestinationPage.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/ChangeDestinationPage.java
deleted file mode 100644
index 53b431c..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/ChangeDestinationPage.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.web.booking;
-
-import java.util.List;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.markup.html.form.AjaxFallbackButton;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.markup.html.panel.ComponentFeedbackPanel;
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.CommonQueries;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.dto.CargoDTO;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.routing.RegisterNewDestination;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoMisroutedException;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.form.AbstractForm;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.form.SelectorInForm;
-
-/**
- * Change destination of Cargo
- */
-public class ChangeDestinationPage extends BookingBasePage
-{
-    public ChangeDestinationPage( PageParameters parameters )
-    {
-        String trackingId = parameters.get( 0 ).toString();
-        add( new Label( "trackingId", trackingId ) );
-        add( new CargoEditForm( trackingId ) );
-    }
-
-    private class CargoEditForm extends AbstractForm<Void>
-    {
-        private String trackingId; // Set by Wicket property resolver
-        private String origin, destination, oldDestination;
-
-        public CargoEditForm( final String trackingId )
-        {
-            CommonQueries fetch = new CommonQueries();
-            CargoDTO cargo = fetch.cargo( trackingId ).getObject();
-            List<String> locations = fetch.unLocodes();
-
-            origin = cargo.routeSpecification().get().origin().get().getCode();
-            oldDestination = destination = cargo.routeSpecification().get().destination().get().getCode();
-
-            final FeedbackPanel feedback = new FeedbackPanel( "usecaseFeedback" );
-            final SelectorInForm destinationSelector = new SelectorInForm(
-                "destination", "Destination", locations, this, "origin" );
-            final ComponentFeedbackPanel destinationFeedback = new ComponentFeedbackPanel(
-                "destinationFeedback", destinationSelector.setRequired( true ) );
-
-            add( feedback.setOutputMarkupId( true ) );
-            add( new Label( "origin", origin ) );
-            add( new Label( "destination", destination ) );
-            add( destinationFeedback.setOutputMarkupId( true ) );
-            add( destinationSelector );
-            add( new AjaxFallbackButton( "submit", this )
-            {
-                @Override
-                protected void onSubmit( AjaxRequestTarget target, Form<?> form )
-                {
-                    try
-                    {
-                        if( oldDestination.equals( destination ) )
-                        {
-                            throw new IllegalArgumentException( "Please select a new destination." );
-                        }
-
-                        new RegisterNewDestination( trackingId ).to( destination );
-
-                        // Show updated cargo
-                        setResponsePage( CargoDetailsPage.class, new PageParameters().set( 0, trackingId ) );
-                    }
-                    catch( CargoMisroutedException e )
-                    {
-                        // If re-routed, we expect it to be misrouted - show updated cargo
-                        setResponsePage( CargoDetailsPage.class, new PageParameters().set( 0, trackingId ) );
-                    }
-                    catch( Exception e )
-                    {
-                        logger.warn( "Problem changing destination of cargo " + trackingId + ": " + e.getMessage() );
-                        feedback.error( e.getMessage() );
-                        target.add( feedback );
-                    }
-                }
-
-                @Override
-                protected void onError( final AjaxRequestTarget target, Form<?> form )
-                {
-                    target.add( destinationFeedback );
-                    target.focusComponent( destinationSelector );
-                }
-            } );
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/ReRouteCargoPage.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/ReRouteCargoPage.java
deleted file mode 100644
index 569fb75..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/ReRouteCargoPage.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.web.booking;
-
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.BookingQueries;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.specification.DeriveUpdatedRouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-
-/**
- * Re-route page
- *
- * Presents a list of possible routes a cargo can take that the user can choose from.
- *
- * Each route candidate is presented by a {@link RoutePanel}.
- */
-public class ReRouteCargoPage extends BookingBasePage
-{
-    private FeedbackPanel feedback = new FeedbackPanel( "feedback" );
-
-    public ReRouteCargoPage( PageParameters parameters )
-    {
-        final String trackingIdString = parameters.get( 0 ).toString();
-
-        add( new Label( "trackingId", trackingIdString ) );
-
-        add( new FeedbackPanel( "feedback" ) );
-
-        try
-        {
-            // Temporary routeSpec to get correct route candidates
-            RouteSpecification tempRouteSpec = new DeriveUpdatedRouteSpecification( trackingIdString ).getRouteSpec();
-
-            add( new ListView<IModel<Itinerary>>( "routes", query( BookingQueries.class ).routeCandidates( tempRouteSpec ) )
-            {
-                @Override
-                protected void populateItem( ListItem<IModel<Itinerary>> item )
-                {
-                    item.add( new RoutePanel( "route", trackingIdString, item.getModelObject(), item.getIndex() + 1 ) );
-                }
-            } );
-        }
-        catch( Exception e )
-        {
-            logger.info( e.getMessage() );
-            error( e.getMessage() );
-            add( new WebMarkupContainer( "routes" ).add( new Label( "route" ) ) );
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/RouteCargoPage.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/RouteCargoPage.java
deleted file mode 100644
index 1b54078..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/RouteCargoPage.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.web.booking;
-
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.BookingQueries;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-
-/**
- * Re-route page - presents a list of possible routes a cargo can take that the user can choose from.
- *
- * Each route candidate is presented by a {@link RoutePanel}.
- */
-public class RouteCargoPage extends BookingBasePage
-{
-    private FeedbackPanel feedback = new FeedbackPanel( "feedback" );
-
-    public RouteCargoPage( PageParameters parameters )
-    {
-        final String trackingIdString = parameters.get( 0 ).toString();
-
-        add( new Label( "trackingId", trackingIdString ) );
-
-        add( new FeedbackPanel( "feedback" ) );
-
-        try
-        {
-            add( new ListView<IModel<Itinerary>>( "routes", query( BookingQueries.class ).routeCandidates( trackingIdString ) )
-            {
-                @Override
-                protected void populateItem( ListItem<IModel<Itinerary>> item )
-                {
-                    item.add( new RoutePanel( "route", trackingIdString, item.getModelObject(), item.getIndex() + 1 ) );
-                }
-            } );
-        }
-        catch( Exception e )
-        {
-            logger.info( e.getMessage() );
-            error( "Unexpected error happened." );
-            add( new WebMarkupContainer( "routes" ).add( new Label( "route" ) ) );
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/RoutePanel.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/RoutePanel.java
deleted file mode 100644
index 5094ed7..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/RoutePanel.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.web.booking;
-
-import java.util.Date;
-import java.util.List;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.markup.html.form.AjaxFallbackButton;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.markup.html.form.StatelessForm;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.LoadableDetachableModel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.routing.AssignCargoToRoute;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Leg;
-
-/**
- * Route Panel
- *
- * Shows a suggested route that a Cargo can take.
- *
- * If the user chooses this candidate route, all route data (a value object) is attached by the
- * RegisterNewDestination context as an Itinerary to the Cargo. To see the result, the user is
- * then redirected to the details page of the cargo.
- */
-public class RoutePanel extends Panel
-{
-    public RoutePanel( String id,
-                       final String trackingIdString,
-                       final IModel<Itinerary> candidateRouteModel,
-                       int index
-    )
-    {
-        super( id, candidateRouteModel );
-        Itinerary itinerary = candidateRouteModel.getObject();
-
-        IModel<String> header = Model.of( "Route candidate " + index + " - duration: " + itinerary.days() + " days." );
-        add( new Label( "routeHeader", header ) );
-
-        final FeedbackPanel routeFeedback = new FeedbackPanel( "routeFeedback" );
-        add( routeFeedback.setOutputMarkupId( true ).setEscapeModelStrings( true ) );
-
-        IModel<List<Leg>> legListModel = new LoadableDetachableModel<List<Leg>>()
-        {
-            @Override
-            protected List<Leg> load()
-            {
-                return candidateRouteModel.getObject().legs().get();
-            }
-        };
-
-        add( new ListView<Leg>( "legs", legListModel )
-        {
-            @Override
-            protected void populateItem( ListItem<Leg> item )
-            {
-                Leg leg = item.getModelObject();
-                item.add( new Label( "voyage", leg.voyage().get().toString() ),
-                          new Label( "loadLocation", leg.loadLocation().get().getCode() ),
-                          new Label( "loadTime", new Model<Date>( leg.loadTime().get() ) ),
-                          new Label( "unloadLocation", leg.unloadLocation().get().getCode() ),
-                          new Label( "unloadTime", new Model<Date>( leg.unloadTime().get() ) )
-                );
-            }
-        } );
-
-        StatelessForm form = new StatelessForm<Void>( "form" );
-        form.add( new AjaxFallbackButton( "assign", form )
-        {
-            @Override
-            protected void onSubmit( AjaxRequestTarget target, Form<?> form )
-            {
-                try
-                {
-                    Itinerary itinerary = candidateRouteModel.getObject();
-                    new AssignCargoToRoute( trackingIdString, itinerary ).assign();
-                    setResponsePage( CargoDetailsPage.class, new PageParameters().set( 0, trackingIdString ) );
-                }
-                catch( Exception e )
-                {
-                    String msg = "Problem assigning this route to cargo: " + e.getMessage();
-                    routeFeedback.error( msg );
-                    target.add( routeFeedback );
-                }
-            }
-
-            @Override
-            protected void onError( final AjaxRequestTarget target, Form<?> form )
-            {
-                routeFeedback.error( "Unexpected error - all routes are expected to be valid." );
-                target.add( routeFeedback );
-            }
-        } );
-        add( form );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/handling/IncidentLoggingApplicationMockupPage.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/handling/IncidentLoggingApplicationMockupPage.java
deleted file mode 100644
index 57d1683..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/handling/IncidentLoggingApplicationMockupPage.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.web.handling;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
-import org.apache.wicket.ajax.markup.html.form.AjaxFallbackButton;
-import org.apache.wicket.markup.html.form.DropDownChoice;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.markup.html.form.TextField;
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.model.StringResourceModel;
-import org.apache.wicket.util.value.ValueMap;
-import org.joda.time.DateTime;
-import org.joda.time.LocalDate;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.CommonQueries;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.HandlingQueries;
-import org.qi4j.sample.dcicargo.sample_b.communication.web.BasePage;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.ProcessHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.form.AbstractForm;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.form.DateTextFieldWithPicker;
-
-/**
- * Incident Logging Application mockup page
- *
- * This is a mockup of an Incident Logging Application interface that external handling
- * authorities would use to send us handling event data for cargos that they have handled.
- *
- * For simplicity we don't create a separate Incident Logging Application for now but instead
- * let it reside inside our booking application. We act as a handling authority entering handling
- * event data, and in the lower half of the page we mock the receipt of the data and show the
- * validation results from our own validation of the incoming data.
- *
- * We could also instead (in future versions?) implement a web service endpoint receiving
- * asynchronous messages from a separate incident logging application. We have prepared for
- * this by separating the processing in three steps, with ProcessHandlingEvent coordinating
- * the following steps:
- *
- * {@link ProcessHandlingEvent}
- * 1. parsedHandlingEventData = parse( completion, trackingId, eventType, unLocode, voyage )
- * 2. handlingEvent = register( parsedHandlingEventData )
- * 3. inspect( handlingEvent )
- *
- * The last step updates the delivery status of the cargo.
- *
- * On this page we act as a handling authority sending handling event data to our booking
- * application. We perform basic validation and parsing of incoming data, and in case of a
- * valid registration attempt, synchronously send the data to the booking application for
- * processing there.
- */
-public class IncidentLoggingApplicationMockupPage extends BasePage
-{
-    public IncidentLoggingApplicationMockupPage()
-    {
-        super( "handling" ); // Selects the Handling tab
-        add( new ReportHandlingEventForm() );
-    }
-
-    private final class ReportHandlingEventForm extends AbstractForm<Void>
-    {
-        FeedbackPanel feedback;
-
-        // Form values
-        Date completion;
-        String trackingId, unLocode, voyageNumber, eventType;
-
-        // Input
-        TextField<String> trackingIdInput, eventTypeInput, voyageInput, locationInput;
-        String trackingIdSelected, eventTypeSelected, voyageSelected, locationSelected;
-        DropDownChoice<String> trackingIdSelector, eventTypeSelector, voyageSelector, locationSelector;
-
-        // To avoid re-submitting same data
-        String lastSubmittedData;
-
-        public ReportHandlingEventForm()
-        {
-            final FeedbackPanel feedback = new FeedbackPanel( "feedback" );
-            add( feedback.setOutputMarkupId( true ) );
-
-            // Completion time
-
-            final DateTextFieldWithPicker completionDateInput = new DateTextFieldWithPicker( "completion", "Completion", this );
-            completionDateInput.earliestDate( new LocalDate() );
-            add( completionDateInput.setLabel( Model.of( "Completion" ) ) );
-
-            HandlingQueries fetch = new HandlingQueries();
-
-            // Tracking id
-
-            trackingIdInput = new TextField<String>( "trackingIdInput", new PropertyModel<String>( this, "trackingId" ) );
-            add( trackingIdInput.setRequired( true ).setLabel( Model.of( "Cargo" ) ).setOutputMarkupId( true ) );
-
-            trackingIdSelector = new DropDownChoice<String>( "trackingIdSelector",
-                                                             new PropertyModel<String>( this, "trackingIdSelected" ),
-                                                             fetch.cargoIds() );
-            trackingIdSelector.add( new AjaxFormComponentUpdatingBehavior( "onchange" )
-            {
-                @Override
-                protected void onUpdate( AjaxRequestTarget target )
-                {
-                    trackingId = trackingIdSelected;
-                    target.add( feedback, trackingIdInput, trackingIdSelector );
-                }
-            } );
-            add( trackingIdSelector.setOutputMarkupId( true ) );
-
-            // Event Type
-
-            eventTypeInput = new TextField<String>( "eventTypeInput", new PropertyModel<String>( this, "eventType" ) );
-            add( eventTypeInput.setRequired( true ).setLabel( Model.of( "Event Type" ) ).setOutputMarkupId( true ) );
-
-            eventTypeSelector = new DropDownChoice<String>( "eventTypeSelector",
-                                                            new PropertyModel<String>( this, "eventTypeSelected" ),
-                                                            fetch.eventTypes() );
-            eventTypeSelector.add( new AjaxFormComponentUpdatingBehavior( "onchange" )
-            {
-                @Override
-                protected void onUpdate( AjaxRequestTarget target )
-                {
-                    eventType = eventTypeSelected;
-                    target.add( feedback, eventTypeInput, eventTypeSelector );
-                }
-            } );
-            add( eventTypeSelector.setOutputMarkupId( true ) );
-
-            // Voyage (optional in some cases)
-
-            voyageInput = new TextField<String>( "voyageInput", new PropertyModel<String>( this, "voyageNumber" ) );
-            add( voyageInput.setLabel( Model.of( "Voyage" ) ).setOutputMarkupId( true ) );
-
-            voyageSelector = new DropDownChoice<String>( "voyageSelector",
-                                                         new PropertyModel<String>( this, "voyageSelected" ),
-                                                         fetch.voyages() );
-            voyageSelector.add( new AjaxFormComponentUpdatingBehavior( "onchange" )
-            {
-                @Override
-                protected void onUpdate( AjaxRequestTarget target )
-                {
-                    voyageNumber = voyageSelected;
-                    target.add( feedback, voyageInput, voyageSelector );
-                }
-            } );
-            add( voyageSelector.setOutputMarkupId( true ) );
-
-            // Location
-
-            locationInput = new TextField<String>( "locationInput", new PropertyModel<String>( this, "unLocode" ) );
-            add( locationInput.setRequired( true ).setLabel( Model.of( "Location" ) ).setOutputMarkupId( true ) );
-
-            locationSelector = new DropDownChoice<String>( "locationSelector",
-                                                           new PropertyModel<String>( this, "locationSelected" ),
-                                                           new CommonQueries().unLocodes() );
-            locationSelector.add( new AjaxFormComponentUpdatingBehavior( "onchange" )
-            {
-                @Override
-                protected void onUpdate( AjaxRequestTarget target )
-                {
-                    unLocode = locationSelected;
-                    target.add( feedback, locationInput, locationSelector );
-                }
-            } );
-            add( locationSelector.setOutputMarkupId( true ) );
-
-            // Submit and process
-
-            add( new AjaxFallbackButton( "register", this )
-            {
-                @Override
-                protected void onSubmit( AjaxRequestTarget target, Form<?> form )
-                {
-                    try
-                    {
-                        // We want to allow making multiple _unique_ handling event registrations
-                        if( sameDataIsSubmitted() )
-                        {
-                            throw new Exception( "Can't re-submit the same data." );
-                        }
-
-                        // We simulate receiving raw text data from incident logging applications
-                        // Add current time to date to have same-dates in processing order (would register full time in real app)
-                        Date adjustedCompletion = new Date( completion.getTime() + new DateTime().getMillisOfDay() );
-                        String completionTimeString = new SimpleDateFormat( "yyyy-MM-dd HH:mm" ).format( adjustedCompletion );
-
-                        // Parse "incoming" data (step 1 of ProcessHandlingEvent use case)
-                        tbf.newTransient( ProcessHandlingEvent.class ).parse(
-                            completionTimeString, trackingId, eventType, unLocode, voyageNumber );
-
-                        /**
-                         * We could redirect to Details, but it's more fun to update details in a separate
-                         * window to follow the successive handling event registrations you make...
-                         * */
-//                        setResponsePage( CargoDetailsPage.class, new PageParameters().set( 0, trackingId ) );
-
-                        try
-                        {
-                            HandlingEventType.valueOf( eventType );
-                        }
-                        catch( Exception e )
-                        {
-                            throw new Exception( "'" + eventType + "' is not a valid handling event type" );
-                        }
-
-                        ValueMap map = new ValueMap();
-                        map.put( "type", eventType );
-                        map.put( "location", unLocode );
-                        if( voyageNumber != null )
-                        {
-                            map.put( "voyage", voyageNumber );
-                        }
-                        String msg = new StringResourceModel( "handlingEvent.${type}", this, new Model<ValueMap>( map ) )
-                            .getObject();
-
-                        feedback.info( "Registered handling event for cargo '" + trackingId + "': " + msg );
-                        target.add( feedback );
-                    }
-                    catch( Exception e )
-                    {
-                        logger.warn( "Problem registering handling event: " + e.getMessage() );
-                        feedback.error( e.getMessage() );
-                        target.add( feedback );
-                    }
-                }
-
-                @Override
-                protected void onError( final AjaxRequestTarget target, Form<?> form )
-                {
-                    target.add( feedback );
-                    focusFirstError( target );
-                }
-            } );
-        }
-
-        private boolean sameDataIsSubmitted()
-        {
-            String submittedData = completion.toString() + trackingId + unLocode + voyageNumber + eventType;
-
-            if( submittedData.equals( lastSubmittedData ) )
-            {
-                return true;
-            }
-
-            // Valid new data submitted
-            lastSubmittedData = submittedData;
-
-            return false;
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/HandlingHistoryPanel.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/HandlingHistoryPanel.java
deleted file mode 100644
index c07442b..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/HandlingHistoryPanel.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.web.tracking;
-
-import java.util.Date;
-import java.util.List;
-import org.apache.wicket.behavior.AttributeAppender;
-import org.apache.wicket.devutils.stateless.StatelessComponent;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.model.StringResourceModel;
-import org.apache.wicket.util.value.ValueMap;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.TrackingQueries;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.dto.CargoDTO;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.dto.HandlingEventDTO;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.color.ErrorColor;
-
-/**
- * Handling history
- *
- * Shows a list of handling events for a cargo.
- *
- * A tracking id string is passed in to retrieve all events matching that cargo.
- */
-@StatelessComponent
-public class HandlingHistoryPanel extends Panel
-{
-    public HandlingHistoryPanel( String id, final IModel<CargoDTO> cargoModel, String trackingId )
-    {
-        super( id );
-
-        IModel<List<HandlingEventDTO>> handlingEventsModel = new TrackingQueries().events( trackingId );
-
-        add( new ListView<HandlingEventDTO>( "handlingEvents", handlingEventsModel )
-        {
-            @Override
-            protected void populateItem( ListItem<HandlingEventDTO> item )
-            {
-                HandlingEventDTO event = item.getModelObject();
-                Boolean isLast = item.getIndex() == getList().size() - 1;
-                Boolean isMisdirected = cargoModel.getObject().delivery().get().isMisdirected().get();
-
-                // Status icon
-                IModel iconName = Model.of( isLast && isMisdirected ? "cross.png" : "tick.png" );
-                item.add( new WebMarkupContainer( "onTrackIcon" ).add( new AttributeAppender( "src", iconName, "" ) ) );
-
-                // Date
-                item.add( new Label( "completion", new Model<Date>( event.completionTime().get() ) ) );
-
-                // Event description (data substitution in strings from HandlingHistoryPanel.properties)
-                ValueMap map = new ValueMap();
-                map.put( "type", event.handlingEventType().get().name() );
-                map.put( "location", event.location().get().getString() );
-                if( event.voyage().get() != null )
-                {
-                    map.put( "voyage", event.voyage().get().voyageNumber().get().number().get() );
-                }
-                IModel text = new StringResourceModel( "handlingEvent.${type}", this, new Model<ValueMap>( map ) );
-                item.add( new Label( "event", text )
-                              .add( new ErrorColor( isLast && isMisdirected ) )
-                              .setEscapeModelStrings( false ) );
-            }
-        } );
-    }
-}
-
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/NextHandlingEventPanel.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/NextHandlingEventPanel.java
deleted file mode 100644
index 68010a7..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/NextHandlingEventPanel.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.web.tracking;
-
-import java.text.SimpleDateFormat;
-import org.apache.wicket.AttributeModifier;
-import org.apache.wicket.devutils.stateless.StatelessComponent;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.model.StringResourceModel;
-import org.apache.wicket.util.value.ValueMap;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.dto.CargoDTO;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.NextHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-
-/**
- * Next handling event
- *
- * Quite some presentation logic to render 1 line of information!
- */
-@StatelessComponent
-public class NextHandlingEventPanel extends Panel
-{
-    public NextHandlingEventPanel( String id, IModel<CargoDTO> cargoModel )
-    {
-        super( id );
-
-        ValueMap map = new ValueMap();
-        Label label = new Label( "text", new StringResourceModel(
-            "nextEvent.${nextEvent}", this, new Model<ValueMap>( map ) ) );
-        add( label );
-
-        CargoDTO cargo = cargoModel.getObject();
-        Location destination = cargo.routeSpecification().get().destination().get();
-
-        if( cargo.itinerary().get() == null )
-        {
-            map.put( "nextEvent", "ROUTE" );
-            return;
-        }
-
-        HandlingEvent previousEvent = cargo.delivery().get().lastHandlingEvent().get();
-        if( previousEvent == null )
-        {
-            map.put( "nextEvent", "RECEIVE" );
-            map.put( "location", cargo.routeSpecification().get().origin().get().getString() );
-            return;
-        }
-
-        Location lastLocation = previousEvent.location().get();
-        if( previousEvent.handlingEventType().get() == HandlingEventType.CLAIM && lastLocation == destination )
-        {
-            map.put( "nextEvent", "END_OF_CYCLE" );
-            map.put( "location", destination.getString() );
-            label.add( new AttributeModifier( "class", "correctColor" ) );
-            return;
-        }
-
-        NextHandlingEvent nextEvent = cargo.delivery().get().nextHandlingEvent().get();
-        if( nextEvent == null )
-        {
-            map.put( "nextEvent", "UNKNOWN" );
-            label.add( new AttributeModifier( "class", "errorColor" ) );
-            return;
-        }
-
-        map.put( "nextEvent", nextEvent.handlingEventType().get().name() );
-        map.put( "location", nextEvent.location().get().getString() );
-
-        if( nextEvent.time() != null )
-        {
-            map.put( "time", new SimpleDateFormat( "yyyy-MM-dd" ).format( nextEvent.time().get() ) );
-        }
-
-        if( nextEvent.voyage().get() != null )
-        {
-            map.put( "voyage", nextEvent.voyage().get().voyageNumber().get().number().get() );
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/TrackCargoPage.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/TrackCargoPage.java
deleted file mode 100644
index 2161a9a..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/TrackCargoPage.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.communication.web.tracking;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.List;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
-import org.apache.wicket.ajax.markup.html.form.AjaxFallbackButton;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.markup.html.form.TextField;
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
-import org.apache.wicket.markup.html.panel.Fragment;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.model.StringResourceModel;
-import org.apache.wicket.util.value.ValueMap;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.CommonQueries;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.TrackingQueries;
-import org.qi4j.sample.dcicargo.sample_b.communication.query.dto.CargoDTO;
-import org.qi4j.sample.dcicargo.sample_b.communication.web.BasePage;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.form.AbstractForm;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.form.SelectorInForm;
-
-/**
- * Track a cargo
- *
- * For convenience during testing, routed (non-received) cargos can be chosen from the dropdown list.
- */
-public class TrackCargoPage extends BasePage
-{
-    public TrackCargoPage()
-    {
-        super( "tracking" ); // Selects the Tracking tab
-        add( new TrackingForm() );
-    }
-
-    private final class TrackingForm extends AbstractForm<Void>
-    {
-        private String trackingId;
-        private String selectedTrackingId; // Set by Wicket property resolver
-
-        private TextField<String> trackingIdInput;
-        private SelectorInForm selectedTrackingIdSelector;
-
-        private FeedbackPanel feedback = new FeedbackPanel( "feedback" );
-        private Fragment statusFragment = new Fragment( "status", "statusFragment", new WebMarkupContainer( "mock" ) );
-
-        private TrackingForm()
-        {
-            // Manual input
-            trackingIdInput = new TextField<String>( "trackingId", new PropertyModel<String>( this, "trackingId" ) );
-            add( trackingIdInput.setRequired( true ).setOutputMarkupId( true ) );
-
-            // Submit button
-            add( new AjaxFallbackButton( "track", this )
-            {
-                @Override
-                protected void onSubmit( AjaxRequestTarget target, Form<?> form )
-                {
-                    updateStatusFragment( target );
-                }
-
-                @Override
-                protected void onError( final AjaxRequestTarget target, Form<?> form )
-                {
-                    updateStatusFragment( target );
-                    target.add( feedback, trackingIdInput, selectedTrackingIdSelector, statusFragment.setVisible( false ) );
-                }
-            } );
-
-            // Drop down selector (for convenience)
-            List<String> cargoIds = new TrackingQueries().routedCargos();
-            add( selectedTrackingIdSelector = new SelectorInForm(
-                "selectedTrackingId", "Selected Tracking id", cargoIds, this ) );
-            selectedTrackingIdSelector.add( new AjaxFormComponentUpdatingBehavior( "onchange" )
-            {
-                @Override
-                protected void onUpdate( AjaxRequestTarget target )
-                {
-                    trackingId = selectedTrackingId;
-                    updateStatusFragment( target );
-                }
-            } );
-
-            add( feedback.setOutputMarkupId( true ) );
-            add( statusFragment.setOutputMarkupId( true ).setOutputMarkupPlaceholderTag( true ).setVisible( false ) );
-        }
-
-        private void updateStatusFragment( final AjaxRequestTarget target )
-        {
-            try
-            {
-                IModel<CargoDTO> cargoModel = new CommonQueries().cargo( trackingId );
-                statusFragment = (Fragment) statusFragment.replaceWith( new StatusFragment( cargoModel, false ) );
-                target.add( feedback, trackingIdInput, selectedTrackingIdSelector, statusFragment.setVisible( true ) );
-            }
-            catch( NoSuchEntityException e )
-            {
-                e.printStackTrace();
-                error( "Cargo '" + trackingId + "' wasn't found in the system. Please check the tracking number." );
-
-                target.add( feedback, trackingIdInput, selectedTrackingIdSelector, statusFragment.setVisible( false ) );
-            }
-            catch( Exception e )
-            {
-                e.printStackTrace();
-                error( "Problem retrieving status for cargo '" + trackingId + "': " + e.getMessage() );
-                target.add( feedback, trackingIdInput, selectedTrackingIdSelector, statusFragment.setVisible( false ) );
-            }
-        }
-
-        private class StatusFragment extends Fragment
-        {
-            public StatusFragment( IModel<CargoDTO> cargoModel, Boolean visible )
-            {
-                super( "status", "statusFragment", TrackingForm.this );
-                setVisible( visible );
-
-                CargoDTO cargo = cargoModel.getObject();
-
-                // Status ----------------------------------------------------------------------
-                ValueMap map = new ValueMap();
-                map.put( "status", cargo.delivery().get().transportStatus().get().name() );
-                map.put( "trackingId", trackingId );
-                HandlingEvent lastEvent = cargo.delivery().get().lastHandlingEvent().get();
-                if( lastEvent != null )
-                {
-                    String voyageString = lastEvent.voyage().get() != null ?
-                                          lastEvent.voyage()
-                                              .get()
-                                              .voyageNumber()
-                                              .get()
-                                              .number()
-                                              .get() : "UNKNOWN_VOYAGE";
-                    map.put( "voyage", voyageString );
-                    map.put( "location", lastEvent.location().get().getString() );
-                }
-                else
-                {
-                    map.put( "voyage", "UNKNOWN_VOYAGE" );
-                    map.put( "location", cargo.origin().get().getString() );
-                }
-                add( new Label( "transportStatus", new StringResourceModel(
-                    "transportStatus.${status}", this, new Model<ValueMap>( map ) ) ) );
-
-                // ETA ----------------------------------------------------------------------
-                String destination = cargo.routeSpecification().get().destination().get().getString();
-                Date eta = cargo.delivery().get().eta().get();
-                String etaString = eta == null ? "?" : new SimpleDateFormat( "yyyy-MM-dd" ).format( eta );
-                add( new Label( "eta", new StringResourceModel(
-                    "eta", this, null, Model.of( destination ), Model.of( etaString ) ) ) );
-
-                // Warning/Notifier ----------------------------------------------------------------------
-                add( new WebMarkupContainer( "isMisdirected" ).setVisible( cargo.delivery()
-                                                                               .get()
-                                                                               .isMisdirected()
-                                                                               .get() ) );
-                add( new WebMarkupContainer( "isClaimed" ).setVisible(
-                    !cargo.delivery().get().isMisdirected().get()
-                    && cargo.delivery().get().isUnloadedAtDestination().get()
-                    && lastEvent != null
-                    && lastEvent.handlingEventType().get() == HandlingEventType.CLAIM
-                ) );
-
-                // Handling history ----------------------------------------------------------------------
-                if( cargo.delivery().get().lastHandlingEvent().get() == null )
-                {
-                    add( new Label( "handlingHistoryPanel" ) );
-                }
-                else
-                {
-                    add( new HandlingHistoryPanel( "handlingHistoryPanel", cargoModel, trackingId ) );
-                }
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/BookNewCargo.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/BookNewCargo.java
deleted file mode 100644
index deed463..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/BookNewCargo.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.booking;
-
-import java.util.Date;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.CargoAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.CargoFactory;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.RouteSpecificationFactoryService;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.NextHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.tracking.TrackingId;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.RoleMixin;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.RECEIVE;
-
-/**
- * Book New Cargo (use case)
- *
- * Cargo Owner starts with the 1st step in the overall Ship Cargo use case by booking a cargo shipment
- * in our shipping application.
- *
- * The Cargo Owner provides an origin and destination location and a arrival deadline to the booking
- * application. A route specification is created from the input and attached to a new cargo with
- * a unique tracking id.
- */
-public class BookNewCargo extends Context
-{
-    private BookingSystemRole bookingSystem;
-
-    private Location origin;
-    private Location destination;
-    private Date arrivalDeadline;
-
-    public BookNewCargo( CargoFactory cargoFactory, Location origin, Location destination, Date arrivalDeadline )
-        throws Exception
-    {
-        bookingSystem = rolePlayer( BookingSystemRole.class, cargoFactory );
-        this.origin = origin;
-        this.destination = destination;
-        this.arrivalDeadline = arrivalDeadline;
-    }
-
-    public BookNewCargo( String originId, String destinationId, Date deadline )
-        throws Exception
-    {
-        this( loadEntity( CargoAggregateRoot.class, CargoAggregateRoot.CARGOS_ID ),
-              loadEntity( Location.class, originId ),
-              loadEntity( Location.class, destinationId ),
-              deadline );
-    }
-
-    public TrackingId getTrackingId()
-        throws Exception
-    {
-        return bookingSystem.createCargo( null );
-    }
-
-    public TrackingId withTrackingId( String trackingIdString )
-        throws Exception
-    {
-        return bookingSystem.createCargo( trackingIdString );
-    }
-
-    @Mixins( BookingSystemRole.Mixin.class )
-    public interface BookingSystemRole
-    {
-        void setContext( BookNewCargo context );
-
-        TrackingId createCargo( @Optional String trackingIdString )
-            throws Exception;
-
-        class Mixin
-            extends RoleMixin<BookNewCargo>
-            implements BookingSystemRole
-        {
-            @This
-            CargoFactory cargoFactory;
-
-            @Service
-            RouteSpecificationFactoryService routeSpecFactory;
-
-            public TrackingId createCargo( String trackingIdString )
-                throws Exception
-            {
-                Date earliestDeparture = new Date();
-                RouteSpecification routeSpec = routeSpecFactory.build( c.origin,
-                                                                       c.destination,
-                                                                       earliestDeparture,
-                                                                       c.arrivalDeadline );
-
-                ValueBuilder<Delivery> delivery = vbf.newValueBuilder( Delivery.class );
-                delivery.prototype().timestamp().set( new Date() );
-                delivery.prototype().transportStatus().set( TransportStatus.NOT_RECEIVED );
-                delivery.prototype().routingStatus().set( RoutingStatus.NOT_ROUTED );
-
-                // Expect receipt in origin (time unknown / no voyage yet)
-                ValueBuilder<NextHandlingEvent> nextEvent = vbf.newValueBuilder( NextHandlingEvent.class );
-                nextEvent.prototype().handlingEventType().set( RECEIVE );
-                nextEvent.prototype().location().set( routeSpec.origin().get() );
-                delivery.prototype().nextHandlingEvent().set( nextEvent.newInstance() );
-
-                Cargo cargo = cargoFactory.createCargo( routeSpec, delivery.newInstance(), trackingIdString );
-
-                return cargo.trackingId().get();
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/exception/ChangeDestinationException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/exception/ChangeDestinationException.java
deleted file mode 100644
index db32fdb..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/exception/ChangeDestinationException.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.booking.exception;
-
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-
-/**
- * Javadoc
- */
-public class ChangeDestinationException extends Exception
-{
-
-    //    private RouteSpecification routeSpec;
-//    private Itinerary itinerary;
-    protected String msg = "";
-
-    public ChangeDestinationException( String s, RouteSpecification routeSpec, Itinerary itinerary )
-    {
-        msg = s;
-//        this.routeSpec = routeSpec;
-//        this.itinerary = itinerary;
-    }
-
-    @Override
-    public String getMessage()
-    {
-        return msg;
-//        return "Couldn't change destination of cargo: " + msg;
-    }
-
-    public ChangeDestinationException( Throwable e )
-    {
-        super( e );
-    }
-
-    public ChangeDestinationException()
-    {
-        super();
-    }
-
-    public ChangeDestinationException( String s )
-    {
-        msg = s;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/exception/RoutingException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/exception/RoutingException.java
deleted file mode 100644
index b934cc6..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/exception/RoutingException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.booking.exception;
-
-/**
- * Javadoc
- */
-public class RoutingException extends Exception
-{
-    public RoutingException( String s )
-    {
-        super( s );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/exception/UnsatisfyingRouteException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/exception/UnsatisfyingRouteException.java
deleted file mode 100644
index 0dbcd8f..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/exception/UnsatisfyingRouteException.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.booking.exception;
-
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-
-/**
- * Javadoc
- */
-public class UnsatisfyingRouteException extends Exception
-{
-    private RouteSpecification routeSpec;
-    private Itinerary itinerary;
-
-    public UnsatisfyingRouteException( RouteSpecification routeSpec, Itinerary itinerary )
-    {
-        this.routeSpec = routeSpec;
-        this.itinerary = itinerary;
-    }
-
-    @Override
-    public String getMessage()
-    {
-//        return "Route specification was not satisfied with itinerary.";
-
-        // When testing:
-        return "Route specification was not satisfied with itinerary:\n" + routeSpec.print() + "\n" + itinerary.print();
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/routing/AssignCargoToRoute.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/routing/AssignCargoToRoute.java
deleted file mode 100644
index b656771..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/routing/AssignCargoToRoute.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.booking.routing;
-
-import java.util.Date;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.exception.RoutingException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.exception.UnsatisfyingRouteException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.specification.DeriveUpdatedRouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionException;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.exception.CannotCreateRouteSpecificationException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.NextHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.CarrierMovement;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.RoleMixin;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.*;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.*;
-
-/**
- * Assign Cargo to Route (subfunction use case)
- *
- * The booking application presents some routes that the cargo can take and the Cargo Owner chooses
- * a preferred route that we then assign to the cargo here.
- *
- * This is step 4 in the Route Cargo use case.
- */
-public class AssignCargoToRoute extends Context
-{
-    CargoInspectorRole cargoInspector;
-
-    RouteSpecification routeSpecification;
-    TransportStatus transportStatus;
-    HandlingEvent lastHandlingEvent;
-
-    Itinerary itinerary;
-
-    public AssignCargoToRoute( Cargo cargo, Itinerary itinerary )
-    {
-        cargoInspector = rolePlayer( CargoInspectorRole.class, cargo );
-
-        routeSpecification = cargo.routeSpecification().get();
-        transportStatus = cargo.delivery().get().transportStatus().get();
-        lastHandlingEvent = cargo.delivery().get().lastHandlingEvent().get();
-
-        this.itinerary = itinerary;
-    }
-
-    public AssignCargoToRoute( String trackingIdString, Itinerary itinerary )
-    {
-        this( loadEntity( Cargo.class, trackingIdString ), itinerary );
-    }
-
-    public void assign()
-        throws CannotCreateRouteSpecificationException, UnsatisfyingRouteException, InspectionException, RoutingException
-    {
-        // Pre-conditions
-        if( transportStatus.equals( CLAIMED ) )
-        {
-            throw new RoutingException( "Can't re-route claimed cargo" );
-        }
-
-        cargoInspector.assignCargoToRoute();
-    }
-
-    @Mixins( CargoInspectorRole.Mixin.class )
-    public interface CargoInspectorRole
-    {
-        void setContext( AssignCargoToRoute context );
-
-        void assignCargoToRoute()
-            throws CannotCreateRouteSpecificationException, UnsatisfyingRouteException, InspectionException;
-
-        class Mixin
-            extends RoleMixin<AssignCargoToRoute>
-            implements CargoInspectorRole
-        {
-            @This
-            Cargo cargo;
-
-            RouteSpecification newRouteSpec;
-            NextHandlingEvent nextHandlingEvent;
-            Delivery newDelivery;
-
-            public void assignCargoToRoute()
-                throws CannotCreateRouteSpecificationException, UnsatisfyingRouteException, InspectionException
-            {
-                // Step 1 - Derive updated route specification
-
-                newRouteSpec = new DeriveUpdatedRouteSpecification( cargo ).getRouteSpec();
-
-                // Step 2 - Verify that route satisfies route specification
-
-                if( !newRouteSpec.isSatisfiedBy( c.itinerary ) )
-                {
-                    throw new UnsatisfyingRouteException( newRouteSpec, c.itinerary );
-                }
-
-                // Step 3 - Assign new route specification to cargo
-
-                cargo.routeSpecification().set( newRouteSpec );
-
-                // Step 4 - Assign cargo to route
-
-                cargo.itinerary().set( c.itinerary );
-
-                // Step 5 - Determine next handling event
-
-                ValueBuilder<NextHandlingEvent> nextHandlingEventBuilder = vbf.newValueBuilder( NextHandlingEvent.class );
-                nextHandlingEvent = nextHandlingEventBuilder.prototype();
-
-                if( c.transportStatus.equals( NOT_RECEIVED ) )
-                {
-                    // Routed unhandled cargo is expected to be received in origin.
-                    nextHandlingEvent.handlingEventType().set( RECEIVE );
-                    nextHandlingEvent.location().set( c.itinerary.firstLeg().loadLocation().get() );
-                }
-                else if( c.transportStatus.equals( ONBOARD_CARRIER ) )
-                {
-                    // Re-routed cargo onboard carrier is expected to be unloaded in next port (regardless of new itinerary).
-                    Voyage voyage = c.lastHandlingEvent.voyage().get();
-                    CarrierMovement carrierMovement = voyage.carrierMovementDepartingFrom( c.lastHandlingEvent
-                                                                                               .location()
-                                                                                               .get() );
-
-                    // Estimate carrier arrival time
-                    Date estimatedArrivalDate = carrierMovement.arrivalTime().get();
-                    if( c.lastHandlingEvent.completionTime().get().after( carrierMovement.departureTime().get() ) )
-                    {
-                        long start = carrierMovement.departureTime().get().getTime();
-                        long end = carrierMovement.arrivalTime().get().getTime();
-                        long duration = end - start;
-                        estimatedArrivalDate = new Date( c.lastHandlingEvent
-                                                             .completionTime()
-                                                             .get()
-                                                             .getTime() + duration );
-                    }
-
-                    nextHandlingEvent.handlingEventType().set( UNLOAD );
-                    nextHandlingEvent.location().set( carrierMovement.arrivalLocation().get() );
-                    nextHandlingEvent.time().set( estimatedArrivalDate );
-                    nextHandlingEvent.voyage().set( c.lastHandlingEvent.voyage().get() );
-                }
-                else // IN_PORT
-                {
-                    // Re-routed cargo in port is expected to be loaded onto first carrier of new itinerary.
-                    nextHandlingEvent.handlingEventType().set( LOAD );
-                    nextHandlingEvent.location().set( c.itinerary.firstLeg().loadLocation().get() );
-                    nextHandlingEvent.time().set( c.itinerary.firstLeg().loadTime().get() );
-                    nextHandlingEvent.voyage().set( c.itinerary.firstLeg().voyage().get() );
-                }
-
-                // Step 6 - Update cargo delivery status
-
-                ValueBuilder<Delivery> deliveryBuilder = vbf.newValueBuilder( Delivery.class );
-                newDelivery = deliveryBuilder.prototype();
-                newDelivery.timestamp().set( new Date() );
-                newDelivery.lastHandlingEvent().set( c.lastHandlingEvent );
-                newDelivery.transportStatus().set( c.transportStatus );
-                newDelivery.isUnloadedAtDestination().set( false );
-                newDelivery.routingStatus().set( ROUTED );
-                newDelivery.isMisdirected().set( false );
-                newDelivery.eta().set( c.itinerary.eta() );
-                newDelivery.itineraryProgressIndex().set( 0 );
-                newDelivery.nextHandlingEvent().set( nextHandlingEventBuilder.newInstance() );
-
-                cargo.delivery().set( deliveryBuilder.newInstance() );
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/routing/RegisterNewDestination.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/routing/RegisterNewDestination.java
deleted file mode 100644
index fa99f2e..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/routing/RegisterNewDestination.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.booking.routing;
-
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.exception.ChangeDestinationException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.specification.DeriveUpdatedRouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.InspectCargoDeliveryStatus;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionException;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.exception.CannotCreateRouteSpecificationException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.RoleMixin;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.CLAIMED;
-
-/**
- * Register New Destination (subfunction use case)
- *
- * Booking system has asked Cargo Inspector to register a new destination for a cargo.
- */
-public class RegisterNewDestination extends Context
-{
-    CargoInspectorRole cargoInspector;
-
-    TransportStatus transportStatus;
-//    HandlingEvent lastHandlingEvent;
-
-    public RegisterNewDestination( Cargo cargo )
-    {
-        this.cargoInspector = rolePlayer( CargoInspectorRole.class, cargo );
-
-        transportStatus = cargo.delivery().get().transportStatus().get();
-//        lastHandlingEvent = cargo.delivery().get().lastHandlingEvent().get();
-    }
-
-    public RegisterNewDestination( String trackingIdString )
-    {
-        this( loadEntity( Cargo.class, trackingIdString ) );
-    }
-
-    public void to( String destinationUnLocodeString )
-        throws Exception
-    {
-        // Pre-conditions
-        if( transportStatus.equals( CLAIMED ) )
-        {
-            throw new ChangeDestinationException( "Can't change destination of claimed cargo." );
-        }
-
-        cargoInspector.registerNewDestination( destinationUnLocodeString );
-    }
-
-    @Mixins( CargoInspectorRole.Mixin.class )
-    public interface CargoInspectorRole
-    {
-        void setContext( RegisterNewDestination context );
-
-        void registerNewDestination( String destination )
-            throws Exception;
-
-        class Mixin
-            extends RoleMixin<RegisterNewDestination>
-            implements CargoInspectorRole
-        {
-            @This
-            Cargo cargo;
-
-            Location newDestination;
-            RouteSpecification newRouteSpec;
-
-            public void registerNewDestination( String newDestinationString )
-                throws ChangeDestinationException, CannotCreateRouteSpecificationException, InspectionException
-            {
-                // Step 1 - Verify new destination
-
-                try
-                {
-                    newDestination = uowf.currentUnitOfWork().get( Location.class, newDestinationString );
-                }
-                catch( NoSuchEntityException e )
-                {
-                    throw new ChangeDestinationException( "Didn't recognize location '" + newDestinationString + "'" );
-                }
-                if( newDestination.equals( cargo.routeSpecification().get().destination().get() ) )
-                {
-                    throw new ChangeDestinationException( "New destination is same as old destination." );
-                }
-
-                // Step 2 - Derive new route specification
-
-                newRouteSpec = new DeriveUpdatedRouteSpecification( cargo, newDestination ).getRouteSpec();
-
-                // Step 3 - Assign new route specification to cargo
-
-                cargo.routeSpecification().set( newRouteSpec );
-
-                // Step 4 - Update cargo delivery status
-
-                new InspectCargoDeliveryStatus( cargo ).update();
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/specification/DeriveUpdatedRouteSpecification.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/specification/DeriveUpdatedRouteSpecification.java
deleted file mode 100644
index 106ea51..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/booking/specification/DeriveUpdatedRouteSpecification.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.booking.specification;
-
-import java.util.Date;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.UnexpectedCarrierException;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.RouteSpecificationFactoryService;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.exception.CannotCreateRouteSpecificationException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.CarrierMovement;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.RoleMixin;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.*;
-
-/**
- * Derive Updated Route Specification (subfunction use case)
- *
- * A Cargo Owner requests to change the route for a Cargo.
- *
- * If the request happens during transport we have to consider the current location of the cargo.
- * If currently on board a carrier we use the arrival port as the new origin for a new route specification
- * otherwise simply the lastKnownLocation. Original origin location of Cargo remains the same.
- */
-public class DeriveUpdatedRouteSpecification extends Context
-{
-    CargoInspectorRole cargoInspector;
-
-    RouteSpecification routeSpecification;
-    TransportStatus transportStatus;
-    HandlingEvent lastHandlingEvent;
-    Location newDestination;
-
-    public DeriveUpdatedRouteSpecification( Cargo cargo )
-    {
-        this.cargoInspector = rolePlayer( CargoInspectorRole.class, cargo );
-
-        routeSpecification = cargo.routeSpecification().get();
-        transportStatus = cargo.delivery().get().transportStatus().get();
-        lastHandlingEvent = cargo.delivery().get().lastHandlingEvent().get();
-    }
-
-    public DeriveUpdatedRouteSpecification( String trackingIdString )
-    {
-        this( loadEntity( Cargo.class, trackingIdString ) );
-    }
-
-    public DeriveUpdatedRouteSpecification( Cargo cargo, Location newDestination )
-    {
-        this( cargo );
-        this.newDestination = newDestination;
-    }
-
-    public RouteSpecification getRouteSpec()
-        throws CannotCreateRouteSpecificationException, UnexpectedCarrierException
-    {
-        // Pre-conditions
-        if( transportStatus.equals( CLAIMED ) )
-        {
-            throw new CannotCreateRouteSpecificationException( "Can't derive new route specification for a claimed cargo." );
-        }
-
-        return cargoInspector.getUpdatedRouteSpecification();
-    }
-
-    @Mixins( CargoInspectorRole.Mixin.class )
-    public interface CargoInspectorRole
-    {
-        void setContext( DeriveUpdatedRouteSpecification context );
-
-        RouteSpecification getUpdatedRouteSpecification()
-            throws CannotCreateRouteSpecificationException, UnexpectedCarrierException;
-
-        class Mixin
-            extends RoleMixin<DeriveUpdatedRouteSpecification>
-            implements CargoInspectorRole
-        {
-            @This
-            Cargo cargo;
-
-            @Service
-            RouteSpecificationFactoryService routeSpecFactory;
-
-            Location newOrigin;
-            Location newDestination;
-            Date newEarliestDeparture;
-            Date newArrivalDeadline;
-
-            public RouteSpecification getUpdatedRouteSpecification()
-                throws CannotCreateRouteSpecificationException, UnexpectedCarrierException
-            {
-                // Step 1 - Collect destination and deadline
-
-                newDestination = c.newDestination == null ? c.routeSpecification.destination().get() : c.newDestination;
-                newArrivalDeadline = c.routeSpecification.arrivalDeadline().get();
-
-                // Step 2 - Derive origin and earliest departure date
-
-                if( c.transportStatus.equals( NOT_RECEIVED ) )
-                {
-                    newOrigin = cargo.origin().get();
-                    newEarliestDeparture = c.routeSpecification.earliestDeparture().get();
-                }
-                else if( c.transportStatus.equals( ONBOARD_CARRIER ) )
-                {
-                    Voyage voyage = c.lastHandlingEvent.voyage().get();
-                    Location departureLocation = c.lastHandlingEvent.location().get();
-                    CarrierMovement carrierMovement = voyage.carrierMovementDepartingFrom( departureLocation );
-                    if( carrierMovement == null )
-                    {
-                        throw new UnexpectedCarrierException( c.lastHandlingEvent );
-                    }
-
-                    newOrigin = carrierMovement.arrivalLocation().get();
-                    newEarliestDeparture = carrierMovement.arrivalTime().get();
-                }
-                else
-                {
-                    newOrigin = c.lastHandlingEvent.location().get();
-                    newEarliestDeparture = c.lastHandlingEvent.completionTime().get();
-                }
-
-                // Step 3 - Build and return new route specification
-
-                return routeSpecFactory.build( newOrigin, newDestination, newEarliestDeparture, newArrivalDeadline );
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/ProcessHandlingEvent.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/ProcessHandlingEvent.java
deleted file mode 100644
index 5348568..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/ProcessHandlingEvent.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.InspectCargoDeliveryStatus;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoArrivedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionFailedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.ParseHandlingEventData;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.exception.InvalidHandlingEventDataException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.RegisterHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception.CannotRegisterHandlingEventException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Process Handling Event (subfunction use case)
- *
- * This is the main subfunction use case for processing incoming handling event registration attempts
- * from incident logging applications.
- *
- * The main responsibility here is to delegate the event processing to (sub)subfunction use cases
- * and to notify relevant parties when certain conditions are met (exceptions thrown). Notifi-
- * cations to the cargo owner are simply presented as red-color key words like "Misrouted" in
- * the booking application UI.
- *
- * A "Handling Manager" in this use case delegates to to following Roles in Contexts
- * (Subfunction Use Cases):
- *
- * 1. Data Parser in {@link ParseHandlingEventData}
- * 2. Event Registrar in {@link RegisterHandlingEvent}
- * 3. Delivery Inspector in {@link org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.InspectCargoDeliveryStatus}
- *
- * For now we simply (synchronously) invoke each subfunction use case with a method call. But
- * we could also implement this asynchronously with JMS or other similar solutions and have
- * message consumers initiate the subfunction use cases instead (as in JmsApplicationEventsImpl
- * in the DDD sample).
- */
-@Mixins( ProcessHandlingEvent.SynchronousProcessingStub.class )
-public interface ProcessHandlingEvent
-    extends TransientComposite
-{
-
-    void parse( String completion, String trackingId, String eventType, String unLocode, @Optional String voyage )
-        throws ProcessHandlingEventException;
-
-    void register( ParsedHandlingEventData parsedHandlingEventData )
-        throws ProcessHandlingEventException;
-
-    void inspect( HandlingEvent handlingEvent );
-
-    abstract class SynchronousProcessingStub
-        implements ProcessHandlingEvent
-    {
-        Logger logger = LoggerFactory.getLogger( ProcessHandlingEvent.class );
-
-        @Service
-        ParseHandlingEventData parser;
-
-        // Step 1 - Parse handling event data
-
-        public void parse( String completion, String trackingId, String eventType, String unLocode, String voyage )
-            throws ProcessHandlingEventException
-        {
-            logger.debug( "Received handling event registration attempt " );
-            try
-            {
-                ParsedHandlingEventData parsedData = parser.parse( completion, trackingId, eventType, unLocode, voyage );
-                logger.debug( "Parsed handling event data" );
-
-                register( parsedData );
-            }
-            catch( InvalidHandlingEventDataException e )
-            {
-                logger.info( e.getMessage() ); // Notify handling authority...
-                throw new ProcessHandlingEventException( e.getMessage() );
-            }
-        }
-
-        // Step 2 - Register handling event
-
-        public void register( ParsedHandlingEventData parsedHandlingEventData )
-            throws ProcessHandlingEventException
-        {
-            try
-            {
-                HandlingEvent handlingEvent = new RegisterHandlingEvent( parsedHandlingEventData ).getEvent();
-                logger.debug( "Registered handling event" );
-
-                inspect( handlingEvent );
-            }
-            catch( CannotRegisterHandlingEventException e )
-            {
-                logger.info( e.getMessage() ); // Notify handling authority...
-                throw new ProcessHandlingEventException( e.getMessage() );
-            }
-        }
-
-        // Step 3 - Update cargo delivery status
-
-        public void inspect( HandlingEvent handlingEvent )
-        {
-            try
-            {
-                new InspectCargoDeliveryStatus( handlingEvent ).update();
-                logger.info( "Inspected handled cargo '" + handlingEvent.trackingId().get().id().get() + "'." );
-            }
-            catch( InspectionFailedException e )
-            {
-                logger.error( e.getMessage() ); // Unexpected error
-            }
-            catch( CargoArrivedException e )
-            {
-                logger.info( e.getMessage() );  // Request Cargo Owner to claim cargo at destination...
-            }
-            catch( InspectionException e )
-            {
-                logger.info( e.getMessage() );  // Request Cargo Owner to re-route cargo...
-            }
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/ProcessHandlingEventException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/ProcessHandlingEventException.java
deleted file mode 100644
index 477299f..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/ProcessHandlingEventException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling;
-
-public class ProcessHandlingEventException extends Exception
-{
-    public ProcessHandlingEventException( String s )
-    {
-        super( s );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/InspectCargoDeliveryStatus.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/InspectCargoDeliveryStatus.java
deleted file mode 100644
index f52e589..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/InspectCargoDeliveryStatus.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection;
-
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectArrivedCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectCargoInCustoms;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectClaimedCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectLoadedCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectReceivedCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectUnhandledCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectUnloadedCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.RoleMixin;
-
-/**
- * Inspect Cargo Delivery Status (subfunction use case)
- *
- * Third and last step in the ProcessHandlingEvent use case.
- *
- * Updates our knowledge about a cargo delivery. All we know about the delivery is saved in
- * a Delivery value object that is replaced each time it's updated.
- *
- * Cargo is playing the Role of a Delivery Inspector that inspects a specific handling event
- * in order to update the Delivery status for the cargo.
- *
- * If the Delivery Inspector realizes that the cargo is not on track, proper notifications are
- * sent out so that the cargo owner can re-route the cargo or the system take some action.
- *
- * Handling cargo in customs is a completely different process and context than loading it onto
- * a ship, so each handling event has its own use case and thus its own Context. Each of those
- * (sub-)subfunction use cases/Contexts reflects our understanding of a real world process and
- * can be easily reviewed, maintained, specialized, tested etc. It's now easy to understand
- * what our program does and what we can expect from it - basically in one place in the code.
- */
-public class InspectCargoDeliveryStatus extends Context
-{
-    DeliveryInspectorRole deliveryInspector;
-
-    Location destination;
-    HandlingEvent handlingEvent;
-    Location handlingLocation;
-
-    public InspectCargoDeliveryStatus( HandlingEvent handlingEvent )
-    {
-        this.handlingEvent = handlingEvent;
-
-        Cargo cargo = loadEntity( Cargo.class, handlingEvent.trackingId().get().id().get() );
-        deliveryInspector = rolePlayer( DeliveryInspectorRole.class, cargo );
-
-        handlingLocation = handlingEvent.location().get();
-        destination = cargo.routeSpecification().get().destination().get();
-    }
-
-    public InspectCargoDeliveryStatus( Cargo cargo )
-    {
-        deliveryInspector = rolePlayer( DeliveryInspectorRole.class, cargo );
-        destination = cargo.routeSpecification().get().destination().get();
-
-        handlingEvent = cargo.delivery().get().lastHandlingEvent().get();
-        if( handlingEvent != null )
-        {
-            handlingLocation = handlingEvent.location().get();
-        }
-    }
-
-    public void update()
-        throws InspectionException
-    {
-        deliveryInspector.delegateInspection();
-    }
-
-    @Mixins( DeliveryInspectorRole.Mixin.class )
-    public interface DeliveryInspectorRole
-    {
-        void setContext( InspectCargoDeliveryStatus context );
-
-        void delegateInspection()
-            throws InspectionException;
-
-        class Mixin
-            extends RoleMixin<InspectCargoDeliveryStatus>
-            implements DeliveryInspectorRole
-        {
-            @This
-            Cargo cargo;
-
-            public void delegateInspection()
-                throws InspectionException
-            {
-
-                // Step 1 - Determine handling event type
-
-                if( c.handlingEvent == null )
-                {
-                    new InspectUnhandledCargo( cargo ).inspect();
-                    return;
-                }
-                HandlingEventType handlingEventType = c.handlingEvent.handlingEventType().get();
-
-                // Step 2 - Delegate inspection
-
-                switch( handlingEventType )
-                {
-                case RECEIVE:
-                    new InspectReceivedCargo( cargo, c.handlingEvent ).inspect();
-                    break;
-
-                case LOAD:
-                    new InspectLoadedCargo( cargo, c.handlingEvent ).inspect();
-                    break;
-
-                case UNLOAD:
-                    if( c.handlingLocation.equals( c.destination ) )
-                    {
-                        new InspectArrivedCargo( cargo, c.handlingEvent ).inspect();
-                    }
-                    else
-                    {
-                        new InspectUnloadedCargo( cargo, c.handlingEvent ).inspect();
-                    }
-                    break;
-
-                case CUSTOMS:
-                    new InspectCargoInCustoms( cargo, c.handlingEvent ).inspect();
-                    break;
-
-                case CLAIM:
-                    new InspectClaimedCargo( cargo, c.handlingEvent ).inspect();
-                    break;
-
-                default:
-                    // No other handling event types
-                }
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectArrivedCargo.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectArrivedCargo.java
deleted file mode 100644
index ba90b17..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectArrivedCargo.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event;
-
-import java.util.Date;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoArrivedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionFailedException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.NextHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.RoleMixin;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.*;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.IN_PORT;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.CLAIM;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.UNLOAD;
-
-/**
- * Inspect Arrived Cargo (subfunction use case)
- *
- * This is one the variations of the {@link org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.InspectCargoDeliveryStatus} use case.
- */
-public class InspectArrivedCargo extends Context
-{
-    DeliveryInspectorRole deliveryInspector;
-
-    HandlingEvent arrivalEvent;
-    Location arrivalLocation;
-
-    RouteSpecification routeSpecification;
-    Location destination;
-
-    Itinerary itinerary;
-    Integer itineraryProgressIndex;
-
-    public InspectArrivedCargo( Cargo cargo, HandlingEvent handlingEvent )
-    {
-        deliveryInspector = rolePlayer( DeliveryInspectorRole.class, cargo );
-
-        arrivalEvent = handlingEvent;
-        arrivalLocation = arrivalEvent.location().get();
-
-        routeSpecification = cargo.routeSpecification().get();
-        destination = routeSpecification.destination().get();
-        itinerary = cargo.itinerary().get();
-
-        // Before handling
-        itineraryProgressIndex = cargo.delivery().get().itineraryProgressIndex().get();
-    }
-
-    public void inspect()
-        throws InspectionException
-    {
-        // Pre-conditions
-        if( arrivalEvent == null ||
-            !arrivalEvent.handlingEventType().get().equals( UNLOAD ) ||
-            !arrivalLocation.equals( destination ) )
-        {
-            throw new InspectionFailedException( "Can only inspect arrived cargo." );
-        }
-
-        deliveryInspector.inspectArrivedCargo();
-    }
-
-    @Mixins( DeliveryInspectorRole.Mixin.class )
-    public interface DeliveryInspectorRole
-    {
-        void setContext( InspectArrivedCargo context );
-
-        void inspectArrivedCargo()
-            throws InspectionException;
-
-        class Mixin
-            extends RoleMixin<InspectArrivedCargo>
-            implements DeliveryInspectorRole
-        {
-            @This
-            Cargo cargo;
-
-            Delivery newDelivery;
-
-            public void inspectArrivedCargo()
-                throws InspectionException
-            {
-                // Step 1 - Collect known delivery data
-
-                ValueBuilder<Delivery> newDeliveryBuilder = vbf.newValueBuilder( Delivery.class );
-                newDelivery = newDeliveryBuilder.prototype();
-                newDelivery.timestamp().set( new Date() );
-                newDelivery.lastHandlingEvent().set( c.arrivalEvent );
-                newDelivery.transportStatus().set( IN_PORT );
-
-                // Always on track if arrived at final destination
-                newDelivery.isUnloadedAtDestination().set( true );
-                newDelivery.isMisdirected().set( false );
-
-                // Step 2 - Determine that cargo is routed (for internal reference)
-
-                if( c.itinerary == null )
-                {
-                    newDelivery.routingStatus().set( NOT_ROUTED );
-                    newDelivery.eta().set( null );
-                    newDelivery.itineraryProgressIndex().set( 0 );
-                }
-                else if( !c.routeSpecification.isSatisfiedBy( c.itinerary ) )
-                {
-                    newDelivery.routingStatus().set( MISROUTED );
-                    newDelivery.eta().set( null );
-                    newDelivery.itineraryProgressIndex().set( 0 );
-                }
-                else
-                {
-                    newDelivery.routingStatus().set( ROUTED );
-                    newDelivery.eta().set( c.itinerary.eta() );
-                    newDelivery.itineraryProgressIndex().set( c.itineraryProgressIndex );
-                }
-
-                // Step 3 - Set next expected handling event to claim
-
-                ValueBuilder<NextHandlingEvent> nextHandlingEvent = vbf.newValueBuilder( NextHandlingEvent.class );
-                nextHandlingEvent.prototype().handlingEventType().set( CLAIM );
-                nextHandlingEvent.prototype().location().set( c.arrivalLocation );
-                nextHandlingEvent.prototype().time().set( c.arrivalEvent.completionTime().get() );
-                nextHandlingEvent.prototype().voyage().set( null );
-                newDelivery.nextHandlingEvent().set( nextHandlingEvent.newInstance() );
-
-                // Step 4 - Save cargo delivery snapshot
-
-                cargo.delivery().set( newDeliveryBuilder.newInstance() );
-
-                // Step 5 - Notify cargo owner of arrival at final destination
-
-                // (Mockup for notification to cargo owner)
-                throw new CargoArrivedException( c.arrivalEvent );
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectCargoInCustoms.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectCargoInCustoms.java
deleted file mode 100644
index 1bbfb78..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectCargoInCustoms.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event;
-
-import java.util.Date;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionFailedException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.RoleMixin;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.NOT_ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.IN_PORT;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.ONBOARD_CARRIER;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.CUSTOMS;
-
-/**
- * Inspect Cargo In Customs (subfunction use case)
- *
- * This is one the variations of the {@link org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.InspectCargoDeliveryStatus} use case.
- *
- * Can the cargo get handled by customs only in the current port location?! Nothing now prevents
- * an unexpected cargo in customs in some random location. A domain expert is needed to explain
- * how this goes.
- *
- * For now the location doesn't affect the misdirection status, and we presume (hope) that the
- * cargo will only get handled by customs in the port it's currently in. Should we safeguard
- * against unexpected in-customs-locations?
- */
-public class InspectCargoInCustoms extends Context
-{
-    DeliveryInspectorRole deliveryInspector;
-
-    HandlingEvent customsEvent;
-
-    RouteSpecification routeSpecification;
-    Itinerary itinerary;
-    Integer itineraryProgressIndex;
-    TransportStatus transportStatus;
-
-    public InspectCargoInCustoms( Cargo cargo, HandlingEvent handlingEvent )
-    {
-        deliveryInspector = rolePlayer( DeliveryInspectorRole.class, cargo );
-
-        customsEvent = handlingEvent;
-
-        routeSpecification = cargo.routeSpecification().get();
-        itinerary = cargo.itinerary().get();
-        itineraryProgressIndex = cargo.delivery().get().itineraryProgressIndex().get();
-
-        // Transport status before customs handling
-        transportStatus = cargo.delivery().get().transportStatus().get();
-    }
-
-    public void inspect()
-        throws InspectionException
-    {
-        // Pre-conditions
-        if( customsEvent == null || !customsEvent.handlingEventType().get().equals( CUSTOMS ) )
-        {
-            throw new InspectionFailedException( "Can only inspect cargo in customs." );
-        }
-
-        if( transportStatus.equals( ONBOARD_CARRIER ) )
-        {
-            throw new InspectionFailedException( "Cannot handle cargo in customs on board a carrier." );
-        }
-
-        deliveryInspector.inspectCargoInCustoms();
-    }
-
-    @Mixins( DeliveryInspectorRole.Mixin.class )
-    public interface DeliveryInspectorRole
-    {
-        void setContext( InspectCargoInCustoms context );
-
-        void inspectCargoInCustoms()
-            throws InspectionException;
-
-        class Mixin
-            extends RoleMixin<InspectCargoInCustoms>
-            implements DeliveryInspectorRole
-        {
-            @This
-            Cargo cargo;
-
-            Delivery newDelivery;
-
-            public void inspectCargoInCustoms()
-                throws InspectionException
-            {
-                // Step 1 - Collect known delivery data
-
-                ValueBuilder<Delivery> newDeliveryBuilder = vbf.newValueBuilder( Delivery.class );
-                newDelivery = newDeliveryBuilder.prototype();
-                newDelivery.timestamp().set( new Date() );
-                newDelivery.lastHandlingEvent().set( c.customsEvent );
-                newDelivery.transportStatus().set( IN_PORT );
-                newDelivery.isUnloadedAtDestination().set( false );
-
-                // Customs handling location doesn't affect direction
-                newDelivery.isMisdirected().set( false );
-
-                // We can't predict the next handling event from the customs event
-                newDelivery.nextHandlingEvent().set( null );
-
-                // Step 2 - Verify cargo is routed
-
-                if( c.itinerary == null )
-                {
-                    newDelivery.routingStatus().set( NOT_ROUTED );
-                    newDelivery.itineraryProgressIndex().set( 0 );
-                    newDelivery.eta().set( null );
-                }
-                else if( !c.routeSpecification.isSatisfiedBy( c.itinerary ) )
-                {
-                    newDelivery.routingStatus().set( RoutingStatus.MISROUTED );
-                    newDelivery.itineraryProgressIndex().set( 0 );
-                    newDelivery.eta().set( null );
-                }
-                else
-                {
-                    newDelivery.routingStatus().set( RoutingStatus.ROUTED );
-                    newDelivery.itineraryProgressIndex().set( c.itineraryProgressIndex );
-                    newDelivery.eta().set( c.itinerary.eta() );
-                }
-
-                // Step 3 - Save cargo delivery snapshot
-
-                cargo.delivery().set( newDeliveryBuilder.newInstance() );
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectClaimedCargo.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectClaimedCargo.java
deleted file mode 100644
index f009140..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectClaimedCargo.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event;
-
-import java.util.Date;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionFailedException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.RoleMixin;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.*;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.CLAIMED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.CLAIM;
-
-/**
- * Inspect Claimed Cargo (subfunction use case)
- *
- * This is one the variations of the {@link org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.InspectCargoDeliveryStatus} use case.
- *
- * NOTE: We don't throw any misrouted/misdirected exceptions even though the cargo might not have
- * followed the original itinerary. The cargo has been delivered at destination and claimed by
- * Cargo Owner, so we're happy no matter how it got there.
- */
-public class InspectClaimedCargo extends Context
-{
-    DeliveryInspectorRole deliveryInspector;
-
-    HandlingEvent claimEvent;
-    Location claimLocation;
-
-    RouteSpecification routeSpecification;
-    Itinerary itinerary;
-    Integer itineraryProgressIndex;
-
-    public InspectClaimedCargo( Cargo cargo, HandlingEvent handlingEvent )
-    {
-        deliveryInspector = rolePlayer( DeliveryInspectorRole.class, cargo );
-
-        claimEvent = handlingEvent;
-        claimLocation = claimEvent.location().get();
-
-        routeSpecification = cargo.routeSpecification().get();
-        itinerary = cargo.itinerary().get();
-
-        // Before handling
-        itineraryProgressIndex = cargo.delivery().get().itineraryProgressIndex().get();
-    }
-
-    public void inspect()
-        throws InspectionException
-    {
-        // Pre-conditions
-        if( claimEvent == null || !claimEvent.handlingEventType().get().equals( CLAIM ) )
-        {
-            throw new InspectionFailedException( "Can only inspect claimed cargo." );
-        }
-
-        deliveryInspector.inspectClaimedCargo();
-    }
-
-    @Mixins( DeliveryInspectorRole.Mixin.class )
-    public interface DeliveryInspectorRole
-    {
-        void setContext( InspectClaimedCargo context );
-
-        void inspectClaimedCargo()
-            throws InspectionException;
-
-        class Mixin
-            extends RoleMixin<InspectClaimedCargo>
-            implements DeliveryInspectorRole
-        {
-            @This
-            Cargo cargo;
-
-            Delivery newDelivery;
-
-            public void inspectClaimedCargo()
-                throws InspectionException
-            {
-                // Step 1 - Collect known delivery data
-
-                ValueBuilder<Delivery> newDeliveryBuilder = vbf.newValueBuilder( Delivery.class );
-                newDelivery = newDeliveryBuilder.prototype();
-                newDelivery.timestamp().set( new Date() );
-                newDelivery.lastHandlingEvent().set( c.claimEvent );
-                newDelivery.transportStatus().set( CLAIMED );
-                newDelivery.isUnloadedAtDestination().set( false ); // Why not true if claimed in final destination?
-
-                // Claim is end of delivery cycle
-                newDelivery.nextHandlingEvent().set( null );
-
-                // Step 2 - Determine that cargo was routed (for internal reference)
-
-                if( c.itinerary == null )
-                {
-                    newDelivery.routingStatus().set( NOT_ROUTED );
-                    newDelivery.eta().set( null );
-                    newDelivery.itineraryProgressIndex().set( 0 );
-                }
-                else if( !c.routeSpecification.isSatisfiedBy( c.itinerary ) )
-                {
-                    newDelivery.routingStatus().set( MISROUTED );
-                    newDelivery.eta().set( null );
-                    newDelivery.itineraryProgressIndex().set( 0 );
-                }
-                else
-                {
-                    newDelivery.routingStatus().set( ROUTED );
-                    newDelivery.eta().set( c.itinerary.eta() );
-                    newDelivery.itineraryProgressIndex().set( c.itineraryProgressIndex );
-                }
-
-                // Step 3 - Determine that cargo was on track according to itinerary (for internal reference)
-
-                if( newDelivery.routingStatus().get().equals( ROUTED ) )
-                {
-                    newDelivery.isMisdirected()
-                        .set( !c.claimLocation.equals( c.itinerary.lastLeg().unloadLocation().get() ) );
-                }
-                else
-                {
-                    newDelivery.isMisdirected().set( false );
-                }
-
-                // Step 4 - Save cargo delivery snapshot
-
-                cargo.delivery().set( newDeliveryBuilder.newInstance() );
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectLoadedCargo.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectLoadedCargo.java
deleted file mode 100644
index 0625040..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectLoadedCargo.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event;
-
-import java.util.Date;
-import java.util.Random;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoHijackedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoMisdirectedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoMisroutedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoNotRoutedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionFailedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.UnexpectedCarrierException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.NextHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Leg;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.CarrierMovement;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.RoleMixin;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.MISROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.NOT_ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.ONBOARD_CARRIER;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.UNKNOWN;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.LOAD;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.UNLOAD;
-
-/**
- * Inspect Loaded Cargo (subfunction use case)
- *
- * This is one the variations of the
- * {@link org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.InspectCargoDeliveryStatus} use
- * case.
- *
- * When the cargo is loaded onto some unexpected carrier we need to find out where that carrier
- * is going so that we can make a new route specification starting from that location. The Cargo Owner
- * is then requested to re-route the cargo in order to get the cargo back on track.
- */
-public class InspectLoadedCargo extends Context
-{
-    DeliveryInspectorRole deliveryInspector;
-
-    HandlingEvent loadEvent;
-    Location loadLocation;
-    Voyage voyage;
-
-    RouteSpecification routeSpecification;
-    Itinerary itinerary;
-    Integer itineraryProgressIndex;
-    RoutingStatus oldRoutingStatus;
-
-    public InspectLoadedCargo( Cargo cargo, HandlingEvent handlingEvent )
-    {
-        deliveryInspector = rolePlayer( DeliveryInspectorRole.class, cargo );
-
-        loadEvent = handlingEvent;
-        loadLocation = loadEvent.location().get();
-        voyage = loadEvent.voyage().get();
-
-        routeSpecification = cargo.routeSpecification().get();
-        itinerary = cargo.itinerary().get();
-
-        // Before handling
-        itineraryProgressIndex = cargo.delivery().get().itineraryProgressIndex().get();
-        oldRoutingStatus = cargo.delivery().get().routingStatus().get();
-    }
-
-    public void inspect()
-        throws InspectionException
-    {
-        // Pre-conditions
-        if( loadEvent == null || !loadEvent.handlingEventType().get().equals( LOAD ) )
-        {
-            throw new InspectionFailedException( "Can only inspect loaded cargo." );
-        }
-
-        deliveryInspector.inspectLoadedCargo();
-    }
-
-    @Mixins( DeliveryInspectorRole.Mixin.class )
-    public interface DeliveryInspectorRole
-    {
-        void setContext( InspectLoadedCargo context );
-
-        void inspectLoadedCargo()
-            throws InspectionException;
-
-        abstract class Mixin extends RoleMixin<InspectLoadedCargo> implements DeliveryInspectorRole
-        {
-            @This
-            Cargo cargo;
-
-            Delivery newDelivery;
-
-            public void inspectLoadedCargo()
-                throws InspectionException
-            {
-                // Step 1 - Collect known delivery data
-
-                ValueBuilder<Delivery> newDeliveryBuilder = vbf.newValueBuilder( Delivery.class );
-                newDelivery = newDeliveryBuilder.prototype();
-                newDelivery.timestamp().set( new Date() );
-                newDelivery.lastHandlingEvent().set( c.loadEvent );
-                newDelivery.transportStatus().set( ONBOARD_CARRIER );
-                newDelivery.isUnloadedAtDestination().set( false );
-
-                // Step 2 - Determine next unload from carrier
-
-                CarrierMovement carrierMovement = c.voyage.carrierMovementDepartingFrom( c.loadLocation );
-                if( carrierMovement == null )
-                {
-                    // Unexpected carrier movement
-                    newDelivery.routingStatus().set( c.oldRoutingStatus );
-                    newDelivery.eta().set( null );
-                    newDelivery.itineraryProgressIndex().set( 0 );
-                    newDelivery.isMisdirected().set( true );
-                    cargo.delivery().set( newDeliveryBuilder.newInstance() );
-                    throw new UnexpectedCarrierException( c.loadEvent );
-                }
-
-                // Estimate carrier arrival time
-                Date estimatedArrivalDate = carrierMovement.arrivalTime().get();
-                if( c.loadEvent.completionTime().get().after( carrierMovement.departureTime().get() ) )
-                {
-                    long start = carrierMovement.departureTime().get().getTime();
-                    long end = carrierMovement.arrivalTime().get().getTime();
-                    long duration = end - start;
-                    estimatedArrivalDate = new Date( c.loadEvent.completionTime().get().getTime() + duration );
-                    // ... We could notify cargo owner if we already now know that we will miss the next ship
-                }
-
-                ValueBuilder<NextHandlingEvent> nextHandlingEvent = vbf.newValueBuilder( NextHandlingEvent.class );
-                nextHandlingEvent.prototype().handlingEventType().set( UNLOAD );
-                nextHandlingEvent.prototype().location().set( carrierMovement.arrivalLocation().get() );
-                nextHandlingEvent.prototype().time().set( estimatedArrivalDate );
-                nextHandlingEvent.prototype().voyage().set( c.voyage );
-                newDelivery.nextHandlingEvent().set( nextHandlingEvent.newInstance() );
-
-                // Step 3 - Verify cargo is routed
-
-                if( c.itinerary == null )
-                {
-                    newDelivery.routingStatus().set( NOT_ROUTED );
-                    newDelivery.eta().set( null );
-                    newDelivery.itineraryProgressIndex().set( 0 );
-                    cargo.delivery().set( newDeliveryBuilder.newInstance() );
-                    throw new CargoNotRoutedException( c.loadEvent );
-                }
-                if( !c.routeSpecification.isSatisfiedBy( c.itinerary ) )
-                {
-                    newDelivery.routingStatus().set( MISROUTED );
-                    newDelivery.eta().set( null );
-                    newDelivery.itineraryProgressIndex().set( 0 );
-                    cargo.delivery().set( newDeliveryBuilder.newInstance() );
-                    throw new CargoMisroutedException( c.loadEvent, c.routeSpecification, c.itinerary );
-                }
-                newDelivery.routingStatus().set( RoutingStatus.ROUTED );
-                newDelivery.eta().set( c.itinerary.eta() );
-                newDelivery.itineraryProgressIndex().set( c.itineraryProgressIndex );
-
-                // Step 4 - Verify cargo is on track
-
-                Leg plannedCarrierMovement = c.itinerary.leg( c.itineraryProgressIndex );
-
-                // Unexpected internal state
-                if( plannedCarrierMovement == null )
-                {
-                    // We should always know the current itinerary leg
-                    throw new InspectionFailedException( "Itinerary progress index '" + c.itineraryProgressIndex + "' is invalid!" );
-                }
-
-                // Unexpected load location - Cargo can't travel in time!
-                // Either previous or current location is wrong - only investigation can clarify...
-                if( !plannedCarrierMovement.loadLocation().get().equals( c.loadLocation ) )
-                {
-                    newDelivery.isMisdirected().set( true );
-                    newDelivery.nextHandlingEvent().set( null );
-                    cargo.delivery().set( newDeliveryBuilder.newInstance() );
-                    throw new CargoMisdirectedException( c.loadEvent, "Itinerary expected load in "
-                                                                      + plannedCarrierMovement.loadLocation()
-                        .get()
-                        .getString() );
-                }
-
-                // Unexpected carrier
-                if( !plannedCarrierMovement.voyage().get().equals( c.voyage ) )
-                {
-                    newDelivery.isMisdirected().set( true );
-                    cargo.delivery().set( newDeliveryBuilder.newInstance() );
-
-                    // ...Expected arrival location - should we accept this?
-                    if( plannedCarrierMovement.unloadLocation()
-                        .get()
-                        .equals( carrierMovement.arrivalLocation().get() ) )
-                    {
-                        throw new CargoMisdirectedException( c.loadEvent, c.itinerary, "Cargo is heading to expected arrival location "
-                                                                                       + plannedCarrierMovement.unloadLocation()
-                            .get() + " but on unexpected voyage "
-                                                                                       + c.voyage
-                            .toString() + ". Notify shipper to unload unexpected cargo in next port." );
-                    }
-
-                    throw new CargoMisdirectedException( c.loadEvent, c.itinerary, "Itinerary expected load onto voyage "
-                                                                                   + plannedCarrierMovement.voyage()
-                        .get() );
-                }
-
-                // Unexpected carrier destination
-                if( !plannedCarrierMovement.unloadLocation().get().equals( carrierMovement.arrivalLocation().get() ) )
-                {
-                    newDelivery.isMisdirected().set( true );
-                    cargo.delivery().set( newDeliveryBuilder.newInstance() );
-                    throw new CargoMisdirectedException( c.loadEvent, "Itinerary expects voyage " + c.voyage.toString()
-                                                                      + " to arrive in " + plannedCarrierMovement.unloadLocation()
-                        .get() + " but carrier is now going to "
-                                                                      + carrierMovement.arrivalLocation().get() );
-                }
-
-                // True exception
-                if( ( c.loadLocation.getCode().equals( "SOMGQ" ) && new Random().nextInt( 100 ) < 20 ) ||
-                    ( carrierMovement.arrivalLocation()
-                          .get()
-                          .getCode()
-                          .equals( "SOMGQ" ) && new Random().nextInt( 100 ) < 15 ) )
-                {
-                    newDelivery.transportStatus().set( UNKNOWN );
-                    newDelivery.isMisdirected().set( false );
-                    cargo.delivery().set( newDeliveryBuilder.newInstance() );
-                    throw new CargoHijackedException( c.loadEvent );
-                }
-
-                // Cargo is on track
-                newDelivery.isMisdirected().set( false );
-
-                // Step 5 - Save cargo delivery snapshot
-
-                cargo.delivery().set( newDeliveryBuilder.newInstance() );
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectReceivedCargo.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectReceivedCargo.java
deleted file mode 100644
index 1914636..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectReceivedCargo.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event;
-
-import java.util.Date;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoMisdirectedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionFailedException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.NextHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Leg;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.RoleMixin;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.*;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.IN_PORT;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.LOAD;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.RECEIVE;
-
-/**
- * Inspect Received Cargo (subfunction use case)
- *
- * This is one the variations of the {@link org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.InspectCargoDeliveryStatus} use case.
- *
- * Note that we consider the cargo still on track if it's received in cargo origin regardless of routing status!
- */
-public class InspectReceivedCargo extends Context
-{
-    DeliveryInspectorRole deliveryInspector;
-
-    HandlingEvent previousEvent;
-
-    HandlingEvent receiveEvent;
-    Location receiveLocation;
-    Voyage voyage;
-
-    RouteSpecification routeSpecification;
-    Itinerary itinerary;
-    Integer itineraryProgressIndex;
-
-    public InspectReceivedCargo( Cargo cargo, HandlingEvent handlingEvent )
-    {
-        deliveryInspector = rolePlayer( DeliveryInspectorRole.class, cargo );
-        previousEvent = cargo.delivery().get().lastHandlingEvent().get();
-
-        receiveEvent = handlingEvent;
-        receiveLocation = receiveEvent.location().get();
-        voyage = receiveEvent.voyage().get();
-
-        routeSpecification = cargo.routeSpecification().get();
-        itinerary = cargo.itinerary().get();
-
-        // Before handling
-        itineraryProgressIndex = cargo.delivery().get().itineraryProgressIndex().get();
-    }
-
-    public void inspect()
-        throws InspectionException
-    {
-        // Pre-conditions
-
-        // Cargo has already been received before
-        if( previousEvent != null && !previousEvent.equals( receiveEvent ) )
-        {
-            throw new InspectionFailedException( "Can't receive cargo again." );
-        }
-
-        if( receiveEvent == null || !receiveEvent.handlingEventType().get().equals( RECEIVE ) )
-        {
-            throw new InspectionFailedException( "Can only inspect received cargo." );
-        }
-
-        deliveryInspector.inspectReceivedCargo();
-    }
-
-    @Mixins( DeliveryInspectorRole.Mixin.class )
-    public interface DeliveryInspectorRole
-    {
-        void setContext( InspectReceivedCargo context );
-
-        void inspectReceivedCargo()
-            throws InspectionException;
-
-        class Mixin
-            extends RoleMixin<InspectReceivedCargo>
-            implements DeliveryInspectorRole
-        {
-            @This
-            Cargo cargo;
-
-            Delivery newDelivery;
-
-            public void inspectReceivedCargo()
-                throws InspectionException
-            {
-                // Step 1 - Collect known delivery data
-
-                ValueBuilder<Delivery> newDeliveryBuilder = vbf.newValueBuilder( Delivery.class );
-                newDelivery = newDeliveryBuilder.prototype();
-                newDelivery.timestamp().set( new Date() );
-                newDelivery.lastHandlingEvent().set( c.receiveEvent );
-                newDelivery.transportStatus().set( IN_PORT );
-                newDelivery.isUnloadedAtDestination().set( false );
-                newDelivery.itineraryProgressIndex().set( 0 );
-
-                // Step 2 - Verify cargo is routed
-
-                if( c.itinerary == null )
-                {
-                    newDelivery.routingStatus().set( NOT_ROUTED );
-                }
-                else if( !c.routeSpecification.isSatisfiedBy( c.itinerary ) )
-                {
-                    newDelivery.routingStatus().set( MISROUTED );
-                }
-                else
-                {
-                    newDelivery.routingStatus().set( ROUTED );
-                }
-
-                if( newDelivery.routingStatus().get().equals( ROUTED ) )
-                {
-                    // Step 3 - Verify cargo is received in origin
-
-                    Leg firstLeg = c.itinerary.firstLeg();
-                    if( !firstLeg.loadLocation().get().equals( c.receiveEvent.location().get() ) )
-                    {
-                        newDelivery.isMisdirected().set( true );
-                        cargo.delivery().set( newDeliveryBuilder.newInstance() );
-                        throw new CargoMisdirectedException( c.receiveEvent, "Itinerary expected receipt in "
-                                                                             + firstLeg.loadLocation()
-                            .get()
-                            .getString() );
-                    }
-
-                    newDelivery.isMisdirected().set( false );
-                    newDelivery.eta().set( c.itinerary.eta() );
-
-                    // Step 4 - Determine next expected handling event
-
-                    ValueBuilder<NextHandlingEvent> nextHandlingEvent = vbf.newValueBuilder( NextHandlingEvent.class );
-                    nextHandlingEvent.prototype().handlingEventType().set( LOAD );
-                    nextHandlingEvent.prototype().location().set( firstLeg.loadLocation().get() );
-                    nextHandlingEvent.prototype().time().set( firstLeg.loadTime().get() );
-                    nextHandlingEvent.prototype().voyage().set( firstLeg.voyage().get() );
-                    newDelivery.nextHandlingEvent().set( nextHandlingEvent.newInstance() );
-                }
-
-                // Step 5 - Save cargo delivery snapshot
-
-                cargo.delivery().set( newDeliveryBuilder.newInstance() );
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectUnhandledCargo.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectUnhandledCargo.java
deleted file mode 100644
index ff667c1..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectUnhandledCargo.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event;
-
-import java.util.Date;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionFailedException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.NextHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.RoleMixin;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.*;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.NOT_RECEIVED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.RECEIVE;
-
-/**
- * Inspect Unhandled Cargo (subfunction use case)
- *
- * This is one the variations of the {@link org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.InspectCargoDeliveryStatus} use case.
- *
- * Here we can check a cargo that hasn't been received in origin yet.
- */
-public class InspectUnhandledCargo extends Context
-{
-    DeliveryInspectorRole deliveryInspector;
-
-    HandlingEvent noEvent;
-
-    RouteSpecification routeSpecification;
-    Itinerary itinerary;
-
-    public InspectUnhandledCargo( Cargo cargo )
-    {
-        deliveryInspector = rolePlayer( DeliveryInspectorRole.class, cargo );
-
-        noEvent = cargo.delivery().get().lastHandlingEvent().get();
-
-        routeSpecification = cargo.routeSpecification().get();
-        itinerary = cargo.itinerary().get();
-    }
-
-    public void inspect()
-        throws InspectionException
-    {
-        // Pre-conditions
-        if( noEvent != null )
-        {
-            throw new InspectionFailedException( "Can only inspect unhandled cargo." );
-        }
-
-        deliveryInspector.inspectUnhandledCargo();
-    }
-
-    @Mixins( DeliveryInspectorRole.Mixin.class )
-    public interface DeliveryInspectorRole
-    {
-        void setContext( InspectUnhandledCargo context );
-
-        void inspectUnhandledCargo()
-            throws InspectionException;
-
-        class Mixin
-            extends RoleMixin<InspectUnhandledCargo>
-            implements DeliveryInspectorRole
-        {
-            @This
-            Cargo cargo;
-
-            Delivery newDelivery;
-
-            public void inspectUnhandledCargo()
-                throws InspectionException
-            {
-                // Step 1 - Collect known delivery data
-
-                ValueBuilder<Delivery> newDeliveryBuilder = vbf.newValueBuilder( Delivery.class );
-                newDelivery = newDeliveryBuilder.prototype();
-                newDelivery.timestamp().set( new Date() );
-                newDelivery.lastHandlingEvent().set( null );
-                newDelivery.transportStatus().set( NOT_RECEIVED );
-                newDelivery.isUnloadedAtDestination().set( false );
-                newDelivery.itineraryProgressIndex().set( 0 );
-
-                // Can't be misdirected before being handled
-                newDelivery.isMisdirected().set( false );
-
-                // Step 2 - Determine if cargo is routed
-
-                if( c.itinerary == null )
-                {
-                    newDelivery.routingStatus().set( NOT_ROUTED );
-                    newDelivery.eta().set( null );
-                }
-                else if( !c.routeSpecification.isSatisfiedBy( c.itinerary ) )
-                {
-                    newDelivery.routingStatus().set( MISROUTED );
-                    newDelivery.eta().set( null );
-                }
-                else
-                {
-                    newDelivery.routingStatus().set( ROUTED );
-                    newDelivery.eta().set( c.itinerary.eta() );
-                }
-
-                // Step 3 - Expect receipt in origin location
-
-                ValueBuilder<NextHandlingEvent> nextHandlingEvent = vbf.newValueBuilder( NextHandlingEvent.class );
-                nextHandlingEvent.prototype().handlingEventType().set( RECEIVE );
-                nextHandlingEvent.prototype().location().set( cargo.origin().get() );
-                nextHandlingEvent.prototype().time().set( null );
-                nextHandlingEvent.prototype().voyage().set( null );
-                newDelivery.nextHandlingEvent().set( nextHandlingEvent.newInstance() );
-
-                // Step 4 - Save cargo delivery snapshot
-
-                cargo.delivery().set( newDeliveryBuilder.newInstance() );
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectUnloadedCargo.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectUnloadedCargo.java
deleted file mode 100644
index 6893c59..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/event/InspectUnloadedCargo.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event;
-
-import java.util.Date;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoMisdirectedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoMisroutedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoNotRoutedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionFailedException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.NextHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Leg;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.RoleMixin;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.*;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.IN_PORT;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.LOAD;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.UNLOAD;
-
-/**
- * Inspect Unloaded Cargo (subfunction use case)
- *
- * This is one the variations of the {@link org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.InspectCargoDeliveryStatus} use case.
- */
-public class InspectUnloadedCargo extends Context
-{
-    DeliveryInspectorRole deliveryInspector;
-
-    HandlingEvent unloadEvent;
-    Location unloadLocation;
-    Voyage voyage;
-
-    RouteSpecification routeSpecification;
-    Location destination;
-    Itinerary itinerary;
-    Integer itineraryProgressIndex;
-    boolean wasMisdirected;
-
-    public InspectUnloadedCargo( Cargo cargo, HandlingEvent handlingEvent )
-    {
-        deliveryInspector = rolePlayer( DeliveryInspectorRole.class, cargo );
-
-        unloadEvent = handlingEvent;
-        unloadLocation = unloadEvent.location().get();
-        voyage = unloadEvent.voyage().get();
-
-        routeSpecification = cargo.routeSpecification().get();
-        destination = routeSpecification.destination().get();
-        itinerary = cargo.itinerary().get();
-        wasMisdirected = cargo.delivery().get().isMisdirected().get();
-
-        // Before inspection
-        itineraryProgressIndex = cargo.delivery().get().itineraryProgressIndex().get();
-    }
-
-    public void inspect()
-        throws InspectionException
-    {
-        // Pre-conditions
-        if( unloadEvent == null || !unloadEvent.handlingEventType()
-            .get()
-            .equals( UNLOAD ) || unloadLocation.equals( destination ) )
-        {
-            throw new InspectionFailedException( "Can only inspect unloaded cargo that hasn't arrived at destination." );
-        }
-
-        deliveryInspector.inspectUnloadedCargo();
-    }
-
-    @Mixins( DeliveryInspectorRole.Mixin.class )
-    public interface DeliveryInspectorRole
-    {
-        void setContext( InspectUnloadedCargo context );
-
-        void inspectUnloadedCargo()
-            throws InspectionException;
-
-        class Mixin
-            extends RoleMixin<InspectUnloadedCargo>
-            implements DeliveryInspectorRole
-        {
-            @This
-            Cargo cargo;
-
-            Delivery newDelivery;
-
-            public void inspectUnloadedCargo()
-                throws InspectionException
-            {
-                // Step 1 - Collect known delivery data
-
-                ValueBuilder<Delivery> newDeliveryBuilder = vbf.newValueBuilder( Delivery.class );
-                newDelivery = newDeliveryBuilder.prototype();
-                newDelivery.timestamp().set( new Date() );
-                newDelivery.lastHandlingEvent().set( c.unloadEvent );
-                newDelivery.transportStatus().set( IN_PORT );
-                newDelivery.isUnloadedAtDestination().set( false );
-
-                // Step 2 - Verify cargo is routed
-
-                if( c.itinerary == null )
-                {
-                    newDelivery.routingStatus().set( NOT_ROUTED );
-                    newDelivery.itineraryProgressIndex().set( 0 );
-                    cargo.delivery().set( newDeliveryBuilder.newInstance() );
-                    throw new CargoNotRoutedException( c.unloadEvent );
-                }
-                if( !c.routeSpecification.isSatisfiedBy( c.itinerary ) )
-                {
-                    newDelivery.routingStatus().set( MISROUTED );
-                    newDelivery.itineraryProgressIndex().set( 0 );
-                    cargo.delivery().set( newDeliveryBuilder.newInstance() );
-                    throw new CargoMisroutedException( c.unloadEvent, c.routeSpecification, c.itinerary );
-                }
-                newDelivery.routingStatus().set( ROUTED );
-                newDelivery.eta().set( c.itinerary.eta() );
-
-                // Current itinerary progress
-                newDelivery.itineraryProgressIndex().set( c.itineraryProgressIndex );
-
-                // Step 3 - Verify cargo is on track
-
-                Leg plannedCarrierMovement = c.itinerary.leg( c.itineraryProgressIndex );
-                if( plannedCarrierMovement == null )
-                {
-                    throw new InspectionFailedException( "Itinerary progress index '" + c.itineraryProgressIndex + "' is invalid!" );
-                }
-
-                Integer itineraryProgressIndex;
-//                if (c.wasMisdirected && c.unloadLocation.equals( c.routeSpecification.origin().get() ))
-                if( c.unloadLocation.equals( c.routeSpecification.origin().get() ) )
-//                if (c.itineraryProgressIndex == -1)
-                {
-                    /**
-                     * Unloading in the origin of a route specification of a misdirected cargo
-                     * tells us that the cargo has been re-routed (re-routing while on board a
-                     * carrier sets new origin of route specification to arrival location of
-                     * current carrier movement).
-                     *
-                     * Since the current unload was related to the old itinerary, we don't verify
-                     * the misdirection status against the new itinerary.
-                     *
-                     * The itinerary index starts over from the first leg of the new itinerary
-                     * */
-                    itineraryProgressIndex = 0;
-                }
-                else if( !plannedCarrierMovement.unloadLocation().get().equals( c.unloadLocation ) )
-                {
-                    newDelivery.isMisdirected().set( true );
-                    cargo.delivery().set( newDeliveryBuilder.newInstance() );
-                    throw new CargoMisdirectedException( c.unloadEvent, "Itinerary expected unload in "
-                                                                        + plannedCarrierMovement.unloadLocation()
-                        .get() );
-                }
-                else if( !plannedCarrierMovement.voyage().get().equals( c.voyage ) )
-                {
-                    // Do we care if cargo unloads from an unexpected carrier?
-                    itineraryProgressIndex = c.itineraryProgressIndex + 1;
-                }
-                else
-                {
-                    // Cargo delivery has progressed and we expect a load in next itinerary leg load location
-                    itineraryProgressIndex = c.itineraryProgressIndex + 1;
-                }
-
-                newDelivery.isMisdirected().set( false );
-
-                // Modify itinerary progress index according to misdirection status
-                newDelivery.itineraryProgressIndex().set( itineraryProgressIndex );
-
-                // Step 4 - Determine next expected handling event
-
-                Leg nextCarrierMovement = c.itinerary.leg( itineraryProgressIndex );
-
-                ValueBuilder<NextHandlingEvent> nextHandlingEvent = vbf.newValueBuilder( NextHandlingEvent.class );
-                nextHandlingEvent.prototype().handlingEventType().set( LOAD );
-                nextHandlingEvent.prototype().location().set( nextCarrierMovement.loadLocation().get() );
-                nextHandlingEvent.prototype().time().set( nextCarrierMovement.loadTime().get() );
-                nextHandlingEvent.prototype().voyage().set( nextCarrierMovement.voyage().get() );
-                newDelivery.nextHandlingEvent().set( nextHandlingEvent.newInstance() );
-
-                // Step 5 - Save cargo delivery snapshot
-
-                cargo.delivery().set( newDeliveryBuilder.newInstance() );
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/CargoArrivedException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/CargoArrivedException.java
deleted file mode 100644
index e0945bf..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/CargoArrivedException.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception;
-
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-
-public class CargoArrivedException extends InspectionException
-{
-    public CargoArrivedException( HandlingEvent handlingEvent )
-    {
-        super( createMessage( handlingEvent) );
-    }
-
-    public static String createMessage(HandlingEvent handlingEvent )
-    {
-        String id = handlingEvent.trackingId().get().id().get();
-        String city = handlingEvent.location().get().name().get();
-        String location = handlingEvent.location().get().getString();
-        String msg = "Cargo '" + id + "' has arrived in destination " + location + ".";
-        msg += "\nMOCKUP REQUEST TO CARGO OWNER: Please claim cargo '" + id + "' in " + city + ".";
-        return msg;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/CargoHijackedException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/CargoHijackedException.java
deleted file mode 100644
index bc51b6e..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/CargoHijackedException.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception;
-
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-
-/**
- * The easter egg.
- */
-public class CargoHijackedException extends InspectionException
-{
-    public CargoHijackedException( HandlingEvent handlingEvent )
-    {
-        super( createMessage( handlingEvent ) );
-    }
-
-    public static String createMessage( HandlingEvent handlingEvent )
-    {
-        String id = handlingEvent.trackingId().get().id().get();
-        StringBuilder msg = new StringBuilder().append( "Cargo '" ).append( id ).append( "' was hijacked." );
-        msg.append( msg );
-        msg.append( "\nMOCKUP MESSAGE TO CARGO OWNER: We're sorry to inform you that your cargo '" );
-        msg.append( id );
-        msg.append( "' was hijacked. Please contact your insurance company." );
-        return msg.toString();
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/CargoMisdirectedException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/CargoMisdirectedException.java
deleted file mode 100644
index e83eec5..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/CargoMisdirectedException.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception;
-
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-
-/**
- * CargoMisdirectedException
- *
- * This would have to set off notifying the cargo owner and request a re-route.
- */
-public class CargoMisdirectedException extends InspectionException
-{
-    private Itinerary itinerary;
-
-    public CargoMisdirectedException( HandlingEvent handlingEvent, String msg )
-    {
-        super( createMessage(msg, handlingEvent, null) );
-    }
-
-    public CargoMisdirectedException( HandlingEvent handlingEvent, Itinerary itinerary, String msg )
-    {
-        super( msg );
-        this.itinerary = itinerary;
-    }
-
-    private static String createMessage( String msg, HandlingEvent handlingEvent, Itinerary itinerary )
-    {
-        String id = handlingEvent.trackingId().get().id().get();
-        String city = handlingEvent.location().get().name().get();
-
-        String itineraryString = "";
-        if( itinerary != null )
-        {
-            itineraryString = itinerary.print();
-        }
-
-        return "\nCargo is MISDIRECTED! " + msg + "\n" + handlingEvent.print() + itineraryString
-               + "MOCKUP REQUEST TO CARGO OWNER: Please re-route misdirected cargo '" + id + "' (now in " + city + ").";
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/CargoMisroutedException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/CargoMisroutedException.java
deleted file mode 100644
index cc13efc..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/CargoMisroutedException.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception;
-
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-
-/**
- * CargoMisroutedException
- *
- * This would have to set off notifying the cargo owner and request a re-route.
- */
-public class CargoMisroutedException extends InspectionException
-{
-    public CargoMisroutedException( HandlingEvent handlingEvent,
-                                    RouteSpecification routeSpecification,
-                                    Itinerary itinerary
-    )
-    {
-        super( createMessage( handlingEvent, routeSpecification, itinerary ) );
-    }
-
-    private static String createMessage( HandlingEvent handlingEvent,
-                                         RouteSpecification routeSpecification,
-                                         Itinerary itinerary )
-    {
-        String id = handlingEvent.trackingId().get().id().get();
-        String city = handlingEvent.location().get().name().get();
-        return "\nCargo is MISROUTED! Route specification is not satisfied with itinerary:\n"
-               + routeSpecification.print() + itinerary.print()
-               + "MOCKUP REQUEST TO CARGO OWNER: Please re-route misrouted cargo '" + id + "' (now in " + city + ")."
-            ;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/CargoNotRoutedException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/CargoNotRoutedException.java
deleted file mode 100644
index 479c2f9..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/CargoNotRoutedException.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception;
-
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-
-public class CargoNotRoutedException extends InspectionException
-{
-    public CargoNotRoutedException( HandlingEvent handlingEvent )
-    {
-        super( createMessage(handlingEvent) );
-    }
-
-    private static String createMessage( HandlingEvent handlingEvent )
-    {
-        String id = handlingEvent.trackingId().get().id().get();
-        String city = handlingEvent.location().get().name().get();
-        return "\nCargo is NOT ROUTED while being handled!" + handlingEvent.print()
-               + "MOCKUP REQUEST TO CARGO OWNER: Please re-route cargo '" + id + "' (now in " + city + ").";
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/InspectionException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/InspectionException.java
deleted file mode 100644
index 4c3c371..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/InspectionException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception;
-
-/**
- * Base exception for all variations of inspection.
- */
-public class InspectionException extends Exception
-{
-    public InspectionException( String message )
-    {
-        super( message );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/InspectionFailedException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/InspectionFailedException.java
deleted file mode 100644
index e97baf0..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/InspectionFailedException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception;
-
-/**
- * Truly unexpected errors.
- */
-public class InspectionFailedException extends InspectionException
-{
-    public InspectionFailedException( String s )
-    {
-        super( s );
-    }
-
-    @Override
-    public String getMessage()
-    {
-        return "INTERNAL ERROR: " + super.getMessage();
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/UnexpectedCarrierException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/UnexpectedCarrierException.java
deleted file mode 100644
index 6294f51..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/inspection/exception/UnexpectedCarrierException.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception;
-
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-
-public class UnexpectedCarrierException extends InspectionException
-{
-    public UnexpectedCarrierException( HandlingEvent handlingEvent )
-    {
-        super( createMessage(handlingEvent) );
-    }
-
-    private static String createMessage( HandlingEvent handlingEvent )
-    {
-        String voyage = handlingEvent.voyage().get().voyageNumber().get().number().get();
-        String city = handlingEvent.location().get().name().get();
-        String location = handlingEvent.location().get().getString();
-        return "\nCarrier of voyage " + voyage + " didn't expect a load in " + location;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/parsing/ParseHandlingEventData.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/parsing/ParseHandlingEventData.java
deleted file mode 100644
index 21d6fef..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/parsing/ParseHandlingEventData.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.library.constraints.annotation.NotEmpty;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.exception.InvalidHandlingEventDataException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType;
-
-/**
- * Parse Handling Event Data  (subfunction use case)
- *
- * First step in the ProcessHandlingEvent use case.
- *
- * Since no Data objects are playing a Role in a Context, it's implemented as a Service
- * instead of a Context. In that respect it doesn't have much to do with DCI, but it shares
- * the intend to implement a use case and we therefore have it in the context package that
- * is then given the broader semantics of the English word "context".
- *
- * Could be implemented as a web service endpoint like HandlingReportServiceImpl,
- * a file upload solution like UploadDirectoryScanner in the DDD sample - or some other
- * technical solution.
- */
-@Mixins( ParseHandlingEventData.Mixin.class )
-public interface ParseHandlingEventData
-    extends ServiceComposite
-{
-    // Step 1 - Receive handling event data for a handled cargo
-    // Step 2 - Verify that data is complete (with annotated constraints)
-
-    public ParsedHandlingEventData parse( @NotEmpty String completionStr,
-                                          @NotEmpty String trackingIdStr,
-                                          @NotEmpty String handlingEventTypeStr,
-                                          @NotEmpty String unLocodeStr,
-                                          @Optional String voyageNumberStr
-    )
-        throws InvalidHandlingEventDataException;
-
-    abstract class Mixin
-        implements ParseHandlingEventData
-    {
-        @Structure
-        ValueBuilderFactory vbf;
-
-        static final String ISO_8601_FORMAT = "yyyy-MM-dd HH:mm";
-
-        Date completionTime;
-        HandlingEventType handlingEventType;
-
-        public ParsedHandlingEventData parse( String completionStr,
-                                              String trackingIdStr,
-                                              String handlingEventTypeStr,
-                                              String unLocodeStr,
-                                              String voyageNumberStr
-        )
-            throws InvalidHandlingEventDataException
-        {
-            // Step 3 - Perform basic type conversion
-
-            try
-            {
-                completionTime = new SimpleDateFormat( ISO_8601_FORMAT ).parse( completionStr.trim() );
-            }
-            catch( ParseException e )
-            {
-                throw new InvalidHandlingEventDataException(
-                    "Invalid date format: '" + completionStr + "' must be on ISO 8601 format " + ISO_8601_FORMAT );
-            }
-
-            try
-            {
-                handlingEventType = HandlingEventType.valueOf( handlingEventTypeStr.trim() );
-            }
-            catch( Exception e )
-            {
-                throw new InvalidHandlingEventDataException( e.getMessage() );
-            }
-
-            // Step 4 - Collect parsed handling event data
-
-            ValueBuilder<ParsedHandlingEventData> parsedData = vbf.newValueBuilder( ParsedHandlingEventData.class );
-            parsedData.prototype().registrationTime().set( new Date() );
-            parsedData.prototype().completionTime().set( completionTime );
-            parsedData.prototype().trackingIdString().set( trackingIdStr );
-            parsedData.prototype().handlingEventType().set( handlingEventType );
-            parsedData.prototype().unLocodeString().set( unLocodeStr );
-            parsedData.prototype().voyageNumberString().set( voyageNumberStr );
-
-            // Step 5 - Return parsed handling event data
-
-            return parsedData.newInstance();
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/parsing/dto/ParsedHandlingEventData.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/parsing/dto/ParsedHandlingEventData.java
deleted file mode 100644
index 19a8410..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/parsing/dto/ParsedHandlingEventData.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.conversion.DTO;
-
-/**
- * The ParsedHandlingEventData simply helps move submitted event registration data around.
- */
-@Immutable
-@Mixins( ParsedHandlingEventData.Mixin.class )
-public interface ParsedHandlingEventData extends DTO
-{
-    Property<Date> registrationTime();
-
-    Property<Date> completionTime();
-
-    Property<String> trackingIdString();
-
-    Property<HandlingEventType> handlingEventType();
-
-    Property<String> unLocodeString();
-
-    @Optional
-    Property<String> voyageNumberString();
-
-    public String print();
-
-    abstract class Mixin
-        implements ParsedHandlingEventData
-    {
-        public String print()
-        {
-            String voyage = "";
-            if( voyageNumberString().get() != null )
-            {
-                voyage = voyageNumberString().get();
-            }
-
-            SimpleDateFormat date = new SimpleDateFormat( "yyyy-MM-dd" );
-
-            StringBuilder builder = new StringBuilder( "\nPARSED HANDLING EVENT DATA -----------------" ).
-                append( "\n  Tracking id string           " ).append( trackingIdString().get() ).
-                append( "\n  Handling Event Type string   " ).append( handlingEventType().get().name() ).
-                append( "\n  UnLocode string              " ).append( unLocodeString().get() ).
-                append( "\n  Completed string             " ).append( date.format( completionTime().get() ) ).
-                append( "\n  Registered string            " ).append( date.format( registrationTime().get() ) ).
-                append( "\n  Voyage string                " ).append( voyage ).
-                append( "\n--------------------------------------------\n" );
-
-            return builder.toString();
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/parsing/exception/InvalidHandlingEventDataException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/parsing/exception/InvalidHandlingEventDataException.java
deleted file mode 100644
index 28496f3..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/parsing/exception/InvalidHandlingEventDataException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.exception;
-
-public class InvalidHandlingEventDataException extends Exception
-{
-    public InvalidHandlingEventDataException( String msg )
-    {
-        super( msg );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/RegisterHandlingEvent.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/RegisterHandlingEvent.java
deleted file mode 100644
index 6738cb7..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/RegisterHandlingEvent.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration;
-
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.ProcessHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception.AlreadyClaimedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception.CannotRegisterHandlingEventException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception.DuplicateEventException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception.MissingVoyageNumberException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception.UnknownCargoException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception.UnknownLocationException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception.UnknownVoyageException;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.HandlingEventAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.entity.HandlingEventEntity;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.HandlingEventFactory;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.exception.CannotCreateHandlingEventException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.tracking.TrackingId;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.RoleMixin;
-
-import static org.qi4j.api.query.QueryExpressions.*;
-import static org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.HandlingEventAggregateRoot.HANDLING_EVENTS_ID;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.*;
-
-/**
- * Register Handling Event (subfunction use case)
- *
- * Second step in the ProcessHandlingEvent use case.
- *
- * Verifies handling event data received from ParseHandlingEventData against the database in
- * order to create a valid HandlingEvent.
- *
- * If only the enclosing {@link ProcessHandlingEvent} summary use case is allowed to call this
- * subfunction use case, we could draw an interesting parallel to the responsibilities of the
- * DDD aggregate of enforcing invariants between its member objects. Whereas here it would be
- * {@link ProcessHandlingEvent} enforcing its subfunction use cases to process correctly and
- * ultimately abort the interactions chain when any of the subfunction interactions fail...
- *
- * As an example of "process integrity enforcement" we here validate that a cargo with the
- * given TrackingId exists in our system. When we then inspect the cargo in the third and last
- * step of the ProcessHandlingEvent summary use case, we presume having a valid cargo.
- *
- * How can we ensure that RegisterHandlingEvent is not mistakenly called directly out of the
- * larger context of ProcessHandlingEvent?
- *
- * IMPORTANT:
- * Compared to the DDD sample, we don't save a Cargo object with the HandlingEvent, but only
- * the TrackingId! HandlingEvent never needs the full Cargo graph (not in the DDD sample either),
- * so by saving only the TrackingId we get a much slimmer HandlingEvent object.
- */
-public class RegisterHandlingEvent extends Context
-{
-    EventRegistrarRole eventRegistrar;
-
-    ParsedHandlingEventData eventData;
-    HandlingEventType eventType;
-    String trackingIdString;
-    String unLocodeString;
-    String voyageNumberString;
-
-    public RegisterHandlingEvent( ParsedHandlingEventData parsedEventData )
-    {
-        eventRegistrar = rolePlayer( EventRegistrarRole.class, HandlingEventAggregateRoot.class, HANDLING_EVENTS_ID );
-
-        this.eventData = parsedEventData;
-        eventType = parsedEventData.handlingEventType().get();
-        trackingIdString = parsedEventData.trackingIdString().get();
-        unLocodeString = parsedEventData.unLocodeString().get();
-        voyageNumberString = parsedEventData.voyageNumberString().get();
-    }
-
-    public HandlingEvent getEvent()
-        throws CannotRegisterHandlingEventException
-    {
-        return eventRegistrar.registerAndGetHandlingEvent();
-    }
-
-    @Mixins( EventRegistrarRole.Mixin.class )
-    public interface EventRegistrarRole
-    {
-        void setContext( RegisterHandlingEvent context );
-
-        HandlingEvent registerAndGetHandlingEvent()
-            throws CannotRegisterHandlingEventException;
-
-        class Mixin
-            extends RoleMixin<RegisterHandlingEvent>
-            implements EventRegistrarRole
-        {
-            @This
-            HandlingEventFactory eventFactory;
-
-            public HandlingEvent registerAndGetHandlingEvent()
-                throws CannotRegisterHandlingEventException
-            {
-                UnitOfWork uow = uowf.currentUnitOfWork();
-                TrackingId trackingId;
-                Location location;
-                Voyage voyage = null;
-
-                // Step 1 - Find Cargo from tracking id string
-                try
-                {
-                    trackingId = uow.get( Cargo.class, c.trackingIdString ).trackingId().get();
-                }
-                catch( NoSuchEntityException e )
-                {
-                    throw new UnknownCargoException( c.eventData );
-                }
-
-                // Step 2 - Find Location from UnLocode string
-
-                try
-                {
-                    location = uow.get( Location.class, c.unLocodeString );
-                }
-                catch( NoSuchEntityException e )
-                {
-                    throw new UnknownLocationException( c.eventData );
-                }
-
-                // Step 3 - Find Voyage from voyage number string
-
-                if( c.eventType.requiresVoyage() )
-                {
-                    if( c.voyageNumberString == null )
-                    {
-                        throw new MissingVoyageNumberException( c.eventData );
-                    }
-
-                    try
-                    {
-                        voyage = uow.get( Voyage.class, c.voyageNumberString );
-                    }
-                    catch( NoSuchEntityException e )
-                    {
-                        throw new UnknownVoyageException( c.eventData );
-                    }
-                }
-
-                // Step 4 - Verify that cargo is not received, in customs or claimed more than once
-
-                if( c.eventType.equals( RECEIVE ) || c.eventType.equals( CUSTOMS ) || c.eventType.equals( CLAIM ) )
-                {
-                    QueryBuilder<HandlingEventEntity> qb = qbf.newQueryBuilder( HandlingEventEntity.class )
-                        .where(
-                            and(
-                                eq( templateFor( HandlingEvent.class ).trackingId().get().id(), c.trackingIdString ),
-                                eq( templateFor( HandlingEvent.class ).handlingEventType(), c.eventType )
-                            )
-                        );
-                    Query<HandlingEventEntity> duplicates = uowf.currentUnitOfWork().newQuery( qb );
-                    if( duplicates.count() > 0 )
-                    {
-                        throw new DuplicateEventException( c.eventData );
-                    }
-                }
-
-                // Step 5 - Verify that cargo is not handled after being claimed
-
-                if( !c.eventType.equals( CLAIM ) )
-                {
-                    HandlingEvent eventTemplate = templateFor( HandlingEvent.class );
-                    QueryBuilder<HandlingEventEntity> qb = qbf.newQueryBuilder( HandlingEventEntity.class )
-                        .where(
-                            and(
-                                eq( eventTemplate.trackingId().get().id(), c.trackingIdString ),
-                                eq( eventTemplate.handlingEventType(), CLAIM )
-                            )
-                        );
-                    Query<HandlingEventEntity> alreadyClaimed = uowf.currentUnitOfWork().newQuery( qb );
-                    if( alreadyClaimed.count() > 0 )
-                    {
-                        throw new AlreadyClaimedException( c.eventData );
-                    }
-                }
-
-                // Step 6 - Create Handling Event in the system
-
-                try
-                {
-                    return eventFactory.createHandlingEvent( c.eventData.registrationTime().get(),
-                                                             c.eventData.completionTime().get(),
-                                                             trackingId,
-                                                             c.eventData.handlingEventType().get(),
-                                                             location,
-                                                             voyage );
-                }
-                catch( CannotCreateHandlingEventException e )
-                {
-                    throw new CannotRegisterHandlingEventException( c.eventData );
-                }
-            }
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/AlreadyClaimedException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/AlreadyClaimedException.java
deleted file mode 100644
index 07a9712..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/AlreadyClaimedException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception;
-
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-
-/**
- * Thrown when trying to register a handling event after cargo has been claimed.
- */
-public final class AlreadyClaimedException extends CannotRegisterHandlingEventException
-{
-    public AlreadyClaimedException( ParsedHandlingEventData parsedHandlingEventData )
-    {
-        super( parsedHandlingEventData );
-    }
-
-    @Override
-    public String getMessage()
-    {
-        return type + " handling event can't be registered after cargo has been claimed.";
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/CannotRegisterHandlingEventException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/CannotRegisterHandlingEventException.java
deleted file mode 100644
index ea3692a..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/CannotRegisterHandlingEventException.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-
-/**
- * If a {@link HandlingEvent} can't be created from a given set of parameters.
- *
- * It is a checked exception because it's not a programming error, but rather a
- * special case that the application is built to handle. It can occur during normal
- * program execution.
- */
-public class CannotRegisterHandlingEventException extends Exception
-{
-    private ParsedHandlingEventData parsedHandlingEventData;
-
-    protected String msg, id, time, type, unloc;
-    protected String voy = "";
-
-    public CannotRegisterHandlingEventException( ParsedHandlingEventData parsedHandlingEventData )
-    {
-        super();
-        this.parsedHandlingEventData = parsedHandlingEventData;
-
-        time = parseDate( parsedHandlingEventData.completionTime().get() );
-        id = parse( parsedHandlingEventData.trackingIdString().get() );
-        type = parse( parsedHandlingEventData.handlingEventType().get().name() );
-        unloc = parse( parsedHandlingEventData.unLocodeString().get() );
-        voy = parse( parsedHandlingEventData.voyageNumberString().get() );
-    }
-
-    public ParsedHandlingEventData getParsedHandlingEventData()
-    {
-        return parsedHandlingEventData;
-    }
-
-    private String parse( String str )
-    {
-        return str == null ? "null" : str;
-    }
-
-    private String parseDate( Date date )
-    {
-        return date == null ? "null" : new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ).format( date );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/ChronologicalException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/ChronologicalException.java
deleted file mode 100644
index 94a0371..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/ChronologicalException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception;
-
-import java.util.Date;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-
-/**
- * Thrown when trying to register a handling event with an unknown tracking id.
- */
-public final class ChronologicalException extends CannotRegisterHandlingEventException
-{
-    Date lastCompletionTime;
-
-    public ChronologicalException( ParsedHandlingEventData parsedHandlingEventData, Date lastCompletionTime )
-    {
-        super( parsedHandlingEventData );
-        this.lastCompletionTime = lastCompletionTime;
-    }
-
-    @Override
-    public String getMessage()
-    {
-        return "Completion time " + time + " is unexpectedly before last handling event completion.";
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/DuplicateEventException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/DuplicateEventException.java
deleted file mode 100644
index b8add5e..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/DuplicateEventException.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception;
-
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-
-/**
- * Thrown when trying to register a receive/in customs/claim handling event twice.
- */
-public final class DuplicateEventException extends CannotRegisterHandlingEventException
-{
-    public DuplicateEventException( ParsedHandlingEventData parsedHandlingEventData )
-    {
-        super( parsedHandlingEventData );
-    }
-
-    @Override
-    public String getMessage()
-    {
-        if( type.equals( "RECEIVE" ) )
-        {
-            return "Cargo can't be received more than once.";
-        }
-        else if( type.equals( "CUSTOMS" ) )
-        {
-            return "Cargo can't be in customs more than once.";
-        }
-        else if( type.equals( "CLAIM" ) )
-        {
-            return "Cargo can't be claimed more than once.";
-        }
-        else
-        {
-            return "INTERNAL ERROR: Unexpected handling event type for this exception";
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/MissingVoyageNumberException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/MissingVoyageNumberException.java
deleted file mode 100644
index e288f9d..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/MissingVoyageNumberException.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception;
-
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-
-/**
- * Thrown when trying to register a handling event without a required voyage
- */
-public final class MissingVoyageNumberException extends CannotRegisterHandlingEventException
-{
-    public MissingVoyageNumberException( ParsedHandlingEventData parsedHandlingEventData )
-    {
-        super( parsedHandlingEventData );
-    }
-
-    @Override
-    public String getMessage()
-    {
-        msg = "Unsuccessful handling event registration for cargo '" + id + "' (handling event '" + type + "' in '" + unloc + "')." +
-              "\nMissing voyage number. Handling event " + type + " requires a voyage.";
-
-        msg += "\nMOCKUP NOTIFICATION TO HANDLING AUTHORITY: Please check submitted invalid handling event data:";
-        msg += getParsedHandlingEventData();
-
-        return msg;
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/NonRoutedCargoException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/NonRoutedCargoException.java
deleted file mode 100644
index 7893ca1..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/NonRoutedCargoException.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception;
-
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-
-/**
- * Thrown when trying to register a handling event for an nonRouted cargo.
- */
-public class NonRoutedCargoException extends CannotRegisterHandlingEventException
-{
-    public NonRoutedCargoException( ParsedHandlingEventData parsedHandlingEventData )
-    {
-        super( parsedHandlingEventData );
-    }
-
-    @Override
-    public String getMessage()
-    {
-        msg = "\nUnsuccessful handling event registration for cargo '" + id +
-              "' (handling event '" + type + "' in '" + unloc + "'). Cargo is not routed!";
-
-        msg += "\nMOCKUP NOTIFICATION TO HANDLING AUTHORITY: Please check submitted invalid handling event data:";
-        msg += getParsedHandlingEventData();
-
-        return msg;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/UnknownCargoException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/UnknownCargoException.java
deleted file mode 100644
index 7c0a834..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/UnknownCargoException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception;
-
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-
-/**
- * Thrown when trying to register a handling event with an unknown tracking id.
- */
-public final class UnknownCargoException extends CannotRegisterHandlingEventException
-{
-    public UnknownCargoException( ParsedHandlingEventData parsedHandlingEventData )
-    {
-        super( parsedHandlingEventData );
-    }
-
-    @Override
-    public String getMessage()
-    {
-        return "Found no cargo with tracking id '" + id + "'.";
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/UnknownEventTypeException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/UnknownEventTypeException.java
deleted file mode 100644
index 8da03b1..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/UnknownEventTypeException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception;
-
-import java.util.Arrays;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType;
-
-/**
- * Thrown when trying to register a handling event with an unknown handling event type.
- */
-public final class UnknownEventTypeException extends CannotRegisterHandlingEventException
-{
-    public UnknownEventTypeException( ParsedHandlingEventData parsedHandlingEventData )
-    {
-        super( parsedHandlingEventData );
-    }
-
-    @Override
-    public String getMessage()
-    {
-        return "'" + type + "' is not a valid handling event type. Valid types are: "
-               + Arrays.toString( HandlingEventType.values() );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/UnknownLocationException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/UnknownLocationException.java
deleted file mode 100644
index be3efae..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/UnknownLocationException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception;
-
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-
-/**
- * Thrown when trying to register a handling event with an unknown location.
- */
-public final class UnknownLocationException extends CannotRegisterHandlingEventException
-{
-    public UnknownLocationException( ParsedHandlingEventData parsedHandlingEventData )
-    {
-        super( parsedHandlingEventData );
-    }
-
-    @Override
-    public String getMessage()
-    {
-        return "Found no location with UN locode '" + unloc + "'.";
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/UnknownVoyageException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/UnknownVoyageException.java
deleted file mode 100644
index 8e13df8..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/interaction/handling/registration/exception/UnknownVoyageException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception;
-
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-
-/**
- * Thrown when trying to register an event with an unknown voyage number.
- */
-public final class UnknownVoyageException extends CannotRegisterHandlingEventException
-{
-    public UnknownVoyageException( ParsedHandlingEventData parsedHandlingEventData )
-    {
-        super( parsedHandlingEventData );
-    }
-
-    @Override
-    public String getMessage()
-    {
-        return "Found no voyage with voyage number '" + voy + "'.";
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/rolemap/CargoRoleMap.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/rolemap/CargoRoleMap.java
deleted file mode 100644
index 61d8c87..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/rolemap/CargoRoleMap.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.rolemap;
-
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.routing.AssignCargoToRoute;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.routing.RegisterNewDestination;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.specification.DeriveUpdatedRouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.InspectCargoDeliveryStatus;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectArrivedCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectCargoInCustoms;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectClaimedCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectLoadedCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectReceivedCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectUnhandledCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectUnloadedCargo;
-import org.qi4j.sample.dcicargo.sample_b.data.entity.CargoEntity;
-
-/**
- * Cargo Role Map
- *
- * Shows all the Roles that a CargoEntity can play.
- *
- * Note that the CargoEntity knows nothing about this map (and that Cargo (Data) knows nothing about CargoEntity).
- */
-public interface CargoRoleMap
-    extends CargoEntity,
-
-            RegisterNewDestination.CargoInspectorRole,
-            AssignCargoToRoute.CargoInspectorRole,
-            DeriveUpdatedRouteSpecification.CargoInspectorRole,
-
-            InspectCargoDeliveryStatus.DeliveryInspectorRole,
-
-            InspectUnhandledCargo.DeliveryInspectorRole,
-            InspectReceivedCargo.DeliveryInspectorRole,
-            InspectLoadedCargo.DeliveryInspectorRole,
-            InspectUnloadedCargo.DeliveryInspectorRole,
-            InspectArrivedCargo.DeliveryInspectorRole,
-            InspectCargoInCustoms.DeliveryInspectorRole,
-            InspectClaimedCargo.DeliveryInspectorRole
-{
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/rolemap/CargosRoleMap.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/rolemap/CargosRoleMap.java
deleted file mode 100644
index c0a586e..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/rolemap/CargosRoleMap.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.rolemap;
-
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.BookNewCargo;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.CargoAggregateRoot;
-
-/**
- * Cargos Role Map
- *
- * Shows what Roles the CargoAggregateRoot can play.
- */
-public interface CargosRoleMap
-    extends CargoAggregateRoot,
-
-            BookNewCargo.BookingSystemRole
-{
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/rolemap/HandlingEventsRoleMap.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/rolemap/HandlingEventsRoleMap.java
deleted file mode 100644
index 181aca4..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/rolemap/HandlingEventsRoleMap.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.rolemap;
-
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.RegisterHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.HandlingEventAggregateRoot;
-
-/**
- * Handling Events Role Map
- *
- * shows what Roles the HandlingEventAggregateRoot can play.
- */
-public interface HandlingEventsRoleMap
-    extends HandlingEventAggregateRoot,
-
-            RegisterHandlingEvent.EventRegistrarRole
-{
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/service/routing/RoutingService.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/service/routing/RoutingService.java
deleted file mode 100644
index 9296df2..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/service/routing/RoutingService.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.service.routing;
-
-import java.rmi.RemoteException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import org.joda.time.LocalDate;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.sample.dcicargo.pathfinder_b.api.GraphTraversalService;
-import org.qi4j.sample.dcicargo.pathfinder_b.api.TransitEdge;
-import org.qi4j.sample.dcicargo.pathfinder_b.api.TransitPath;
-import org.qi4j.sample.dcicargo.sample_b.context.service.routing.exception.FoundNoRoutesException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Leg;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Routing service.
- *
- * This is basically a data model translation layer between our domain model and the
- * API put forward by the path finder team, which operates in a different context from us.
- */
-@Mixins( RoutingService.Mixin.class )
-public interface RoutingService
-    extends ServiceComposite
-{
-    /**
-     * @param routeSpecification route specification
-     *
-     * @return A list of itineraries that satisfy the specification. May be an empty list if no route is found.
-     */
-    List<Itinerary> fetchRoutesForSpecification( RouteSpecification routeSpecification )
-        throws FoundNoRoutesException;
-
-    abstract class Mixin
-        implements RoutingService
-    {
-        private static final Logger logger = LoggerFactory.getLogger( RoutingService.class );
-
-        @Structure
-        ValueBuilderFactory vbf;
-
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        @Service
-        GraphTraversalService graphTraversalService;
-
-        public List<Itinerary> fetchRoutesForSpecification( RouteSpecification routeSpecification )
-            throws FoundNoRoutesException
-        {
-            final Date departureDate = routeSpecification.earliestDeparture().get();
-            final Location origin = routeSpecification.origin().get();
-            final Location destination = routeSpecification.destination().get();
-
-            List<TransitPath> transitPaths;
-            List<Itinerary> itineraries = new ArrayList<Itinerary>();
-
-            try
-            {
-                transitPaths = graphTraversalService.findShortestPath( departureDate, origin.getCode(), destination.getCode() );
-            }
-            catch( RemoteException e )
-            {
-                logger.error( e.getMessage(), e );
-                return Collections.emptyList();
-            }
-
-            // The returned result is then translated back into our domain model.
-            for( TransitPath transitPath : transitPaths )
-            {
-                final Itinerary itinerary = toItinerary( transitPath );
-
-                // Use the specification to safe-guard against invalid itineraries
-                // We can use the side-effects free method of the RouteSpecification data object
-                if( routeSpecification.isSatisfiedBy( itinerary ) )
-                {
-                    itineraries.add( itinerary );
-                }
-            }
-
-            if( itineraries.size() == 0 )
-            {
-                throw new FoundNoRoutesException( destination.name().get(),
-                                                  new LocalDate( routeSpecification.arrivalDeadline().get() ) );
-            }
-
-            return itineraries;
-        }
-
-        private Itinerary toItinerary( TransitPath transitPath )
-        {
-            ValueBuilder<Itinerary> itinerary = vbf.newValueBuilder( Itinerary.class );
-            List<Leg> legs = new ArrayList<Leg>();
-            for( TransitEdge edge : transitPath.getTransitEdges() )
-            {
-                legs.add( toLeg( edge ) );
-            }
-            itinerary.prototype().legs().set( legs );
-
-            return itinerary.newInstance();
-        }
-
-        private Leg toLeg( TransitEdge edge )
-        {
-            UnitOfWork uow = uowf.currentUnitOfWork();
-
-            // Build Leg value object
-            ValueBuilder<Leg> leg = vbf.newValueBuilder( Leg.class );
-            leg.prototype().voyage().set( uow.get( Voyage.class, edge.getVoyageNumber() ) );
-            leg.prototype().loadLocation().set( uow.get( Location.class, edge.getFromUnLocode() ) );
-            leg.prototype().unloadLocation().set( uow.get( Location.class, edge.getToUnLocode() ) );
-            leg.prototype().loadTime().set( edge.getFromDate() );
-            leg.prototype().unloadTime().set( edge.getToDate() );
-
-            return leg.newInstance();
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/service/routing/exception/FoundNoRoutesException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/service/routing/exception/FoundNoRoutesException.java
deleted file mode 100644
index 1808a7d..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/context/service/routing/exception/FoundNoRoutesException.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.service.routing.exception;
-
-import org.joda.time.LocalDate;
-
-/**
- * Custom messages when the arrival deadline is too close and we can't find a route.
- */
-public class FoundNoRoutesException extends Exception
-{
-    private final String city;
-    private final LocalDate deadline;
-
-    public FoundNoRoutesException( String city, LocalDate deadline )
-    {
-        this.city = city;
-        this.deadline = deadline;
-    }
-
-    @Override
-    public String getMessage()
-    {
-        if( deadline.isBefore( new LocalDate().plusDays( 2 ) ) )
-        {
-            return "Impossible to get the cargo to " + city + " before " + deadline
-                   + "! Make a new booking with a deadline 2-3 weeks ahead in time.";
-        }
-        else if( deadline.isBefore( new LocalDate().plusDays( 4 ) ) )
-        {
-            return "Couldn't find any routes arriving in " + city + " before " + deadline
-                   + ". Please try again or make a new booking with a deadline 2-3 weeks ahead in time.";
-        }
-        else if( deadline.isBefore( new LocalDate().plusDays( 6 ) ) )
-        {
-            return "Sorry, our system couldn't immediately find a route arriving in " + city + " before " + deadline
-                   + ". Please try again, and we should hopefully be able to find a new route for you.";
-        }
-
-        return "Couldn't find any route to " + city + " arriving before " + deadline
-               + ". There might be a shortage of voyages going there. Please try again.";
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/aggregateroot/CargoAggregateRoot.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/aggregateroot/CargoAggregateRoot.java
deleted file mode 100644
index 2da9945..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/aggregateroot/CargoAggregateRoot.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.aggregateroot;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.CargoFactory;
-
-/**
- * Cargo aggregate root
- *
- * An identified unique starting point to create Cargos.
- *
- * Cargos are only allowed to be created through this aggregate root. Can we enforce this?
- */
-public interface CargoAggregateRoot
-    extends EntityComposite,
-
-            CargoFactory
-{
-    public static final String CARGOS_ID = "Cargos_id";
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/aggregateroot/HandlingEventAggregateRoot.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/aggregateroot/HandlingEventAggregateRoot.java
deleted file mode 100644
index 2bd6190..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/aggregateroot/HandlingEventAggregateRoot.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.aggregateroot;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.HandlingEventFactory;
-
-/**
- * HandlingEvent aggregate root
- *
- * An identified unique starting point to create HandlingEvents.
- *
- * HandlingEvents are only allowed to be created through this aggregate root. Can we enforce this?
- */
-public interface HandlingEventAggregateRoot
-    extends EntityComposite,
-
-            HandlingEventFactory
-{
-    public static final String HANDLING_EVENTS_ID = "Handling_events_id";
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/entity/CargoEntity.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/entity/CargoEntity.java
deleted file mode 100644
index e3a0cd0..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/entity/CargoEntity.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.entity;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-
-/**
- * Cargo entity
- */
-public interface CargoEntity
-    extends EntityComposite,
-
-            Cargo
-{
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/entity/HandlingEventEntity.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/entity/HandlingEventEntity.java
deleted file mode 100644
index e3f15b2..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/entity/HandlingEventEntity.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.entity;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-
-/**
- * Handling Event entity
- */
-public interface HandlingEventEntity
-    extends EntityComposite,
-
-            HandlingEvent
-{
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/entity/LocationEntity.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/entity/LocationEntity.java
deleted file mode 100644
index e563ebb..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/entity/LocationEntity.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.entity;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-
-/**
- * Location entity
- *
- * Locations have been created outside the shipping application context so we don't have any
- * separate aggregate root to create those from.
- */
-public interface LocationEntity
-    extends EntityComposite,
-
-            Location
-{
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/entity/VoyageEntity.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/entity/VoyageEntity.java
deleted file mode 100644
index 96a8852..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/entity/VoyageEntity.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.entity;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-
-/**
- * Voyage entity
- *
- * Voyages have been created outside the shipping application context so we don't have any
- * separate aggregate root to create those from.
- */
-public interface VoyageEntity
-    extends EntityComposite,
-
-            Voyage
-{
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/CargoFactory.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/CargoFactory.java
deleted file mode 100644
index 8d58d55..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/CargoFactory.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.factory;
-
-import java.util.UUID;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.exception.CannotCreateCargoException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.tracking.TrackingId;
-
-/**
- * Cargo factory
- *
- * If an empty tracking id string is received the factory will create an automated tracking id.
- *
- * Validations of RouteSpecification and Delivery are considered out of this scope.
- */
-@Mixins( CargoFactory.Mixin.class )
-public interface CargoFactory
-{
-    Cargo createCargo( RouteSpecification routeSpecification, Delivery delivery, @Optional String id )
-        throws CannotCreateCargoException;
-
-    class Mixin
-        implements CargoFactory
-    {
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        @Structure
-        ValueBuilderFactory vbf;
-
-        public Cargo createCargo( RouteSpecification routeSpecification, Delivery delivery, String id )
-            throws ConstraintViolationException, CannotCreateCargoException
-        {
-            TrackingId trackingId = buildTrackingId( id );
-
-            UnitOfWork uow = uowf.currentUnitOfWork();
-            EntityBuilder<Cargo> cargoBuilder = uow.newEntityBuilder( Cargo.class, trackingId.id().get() );
-            cargoBuilder.instance().trackingId().set( trackingId );
-            cargoBuilder.instance().origin().set( routeSpecification.origin().get() );
-            cargoBuilder.instance().routeSpecification().set( routeSpecification );
-            cargoBuilder.instance().delivery().set( delivery );
-
-            return cargoBuilder.newInstance();
-        }
-
-        private TrackingId buildTrackingId( String id )
-            throws CannotCreateCargoException
-        {
-            if( id == null || id.trim().equals( "" ) )
-            {
-                // Build random tracking id
-                final String uuid = UUID.randomUUID().toString().toUpperCase();
-                id = uuid.substring( 0, uuid.indexOf( "-" ) );
-            }
-            else
-            {
-                try
-                {
-                    // Verify that tracking id doesn't exist in store
-                    uowf.currentUnitOfWork().get( Cargo.class, id );
-                    throw new CannotCreateCargoException( "Tracking id '" + id + "' is not unique." );
-                }
-                catch( NoSuchEntityException e )
-                {
-                    // Ok: tracking id is unique
-                }
-            }
-
-            ValueBuilder<TrackingId> trackingIdBuilder = vbf.newValueBuilder( TrackingId.class );
-            trackingIdBuilder.prototype().id().set( id );
-            return trackingIdBuilder.newInstance();
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/HandlingEventFactory.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/HandlingEventFactory.java
deleted file mode 100644
index 297ea00..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/HandlingEventFactory.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.factory;
-
-import java.util.Date;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.exception.CannotCreateHandlingEventException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.tracking.TrackingId;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-
-/**
- * HandlingEventFactory
- *
- * Creates a valid handling event
- *
- * - Verifies if a voyage is mandatory or prohibited for the handling event type
- * - Verifies if a load/unload location is expected by the voyage
- *
- * Validations of TrackingId, Location and Voyage are considered out of this scope.
- */
-@Mixins( HandlingEventFactory.Mixin.class )
-public interface HandlingEventFactory
-{
-    HandlingEvent createHandlingEvent( Date registrationTime,
-                                       Date completionTime,
-                                       TrackingId trackingId,
-                                       HandlingEventType handlingEventType,
-                                       Location location,
-                                       @Optional Voyage voyage
-    )
-        throws CannotCreateHandlingEventException;
-
-    public abstract class Mixin
-        implements HandlingEventFactory
-    {
-        @Structure
-        UnitOfWorkFactory uowf;
-
-        public HandlingEvent createHandlingEvent( Date registrationTime,
-                                                  Date completionTime,
-                                                  TrackingId trackingId,
-                                                  HandlingEventType handlingEventType,
-                                                  Location location,
-                                                  Voyage voyage
-        )
-            throws CannotCreateHandlingEventException
-        {
-            if( voyage == null && handlingEventType.requiresVoyage() )
-            {
-                throw new CannotCreateHandlingEventException( "Voyage is required for handling event type " + handlingEventType );
-            }
-
-            else if( voyage != null && handlingEventType.prohibitsVoyage() )
-            {
-                throw new CannotCreateHandlingEventException( "Voyage is not allowed with handling event type " + handlingEventType );
-            }
-
-            UnitOfWork uow = uowf.currentUnitOfWork();
-            EntityBuilder<HandlingEvent> handlingEventBuilder = uow.newEntityBuilder( HandlingEvent.class );
-            handlingEventBuilder.instance().registrationTime().set( registrationTime );
-            handlingEventBuilder.instance().completionTime().set( completionTime );
-            handlingEventBuilder.instance().trackingId().set( trackingId );
-            handlingEventBuilder.instance().handlingEventType().set( handlingEventType );
-            handlingEventBuilder.instance().location().set( location );
-            handlingEventBuilder.instance().voyage().set( voyage );
-
-            // Save and return
-            return handlingEventBuilder.newInstance();
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/RouteSpecificationFactoryService.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/RouteSpecificationFactoryService.java
deleted file mode 100644
index 0fe9143..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/RouteSpecificationFactoryService.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.factory;
-
-import java.util.Date;
-import org.joda.time.DateMidnight;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.exception.CannotCreateRouteSpecificationException;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-
-/**
- * Route Specification factory
- *
- * Enforces 3 invariants:
- * - no identical origin and destination
- * - deadline in the future
- * - earliest departure before deadline
- *
- * Validation of Locations is considered out of this scope.
- */
-@Mixins( RouteSpecificationFactoryService.Mixin.class )
-public interface RouteSpecificationFactoryService
-    extends ServiceComposite
-{
-    RouteSpecification build( Location origin, Location destination, Date earliestDeparture, Date deadline )
-        throws CannotCreateRouteSpecificationException;
-
-    abstract class Mixin
-        implements RouteSpecificationFactoryService
-    {
-        @Structure
-        ValueBuilderFactory vbf;
-
-        public RouteSpecification build( Location origin, Location destination, Date earliestDeparture, Date deadline )
-            throws CannotCreateRouteSpecificationException
-        {
-            if( origin == destination )
-            {
-                throw new CannotCreateRouteSpecificationException( "Origin location can't be same as destination location." );
-            }
-
-            Date endOfToday = new DateMidnight().plusDays( 1 ).toDate();
-            if( deadline.before( endOfToday ) )
-            {
-                throw new CannotCreateRouteSpecificationException( "Arrival deadline is in the past or Today." +
-                                                                   "\nDeadline           " + deadline +
-                                                                   "\nToday (midnight)   " + endOfToday );
-            }
-
-            if( deadline.before( earliestDeparture ) )
-            {
-                throw new CannotCreateRouteSpecificationException( "Deadline can't be before departure:" +
-                                                                   "\nDeparture   " + earliestDeparture +
-                                                                   "\nDeadline    " + deadline );
-            }
-
-            ValueBuilder<RouteSpecification> routeSpec = vbf.newValueBuilder( RouteSpecification.class );
-            routeSpec.prototype().origin().set( origin );
-            routeSpec.prototype().destination().set( destination );
-            routeSpec.prototype().earliestDeparture().set( earliestDeparture );
-            routeSpec.prototype().arrivalDeadline().set( deadline );
-            return routeSpec.newInstance();
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/exception/CannotCreateCargoException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/exception/CannotCreateCargoException.java
deleted file mode 100644
index a7abf00..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/exception/CannotCreateCargoException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.factory.exception;
-
-import org.qi4j.sample.dcicargo.sample_b.data.structure.tracking.TrackingId;
-
-/**
- * If a Cargo can't be created.
- *
- * Usually because a supplied tracking id string
- * - doesn't match the pattern in {@link TrackingId}
- * - is not unique
- */
-public class CannotCreateCargoException extends Exception
-{
-    public CannotCreateCargoException( String s )
-    {
-        super( s );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/exception/CannotCreateHandlingEventException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/exception/CannotCreateHandlingEventException.java
deleted file mode 100644
index 7412877..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/exception/CannotCreateHandlingEventException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.factory.exception;
-
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-
-/**
- * If a {@link HandlingEvent} can't be created from a given set of parameters.
- *
- * It is a checked exception because it's not a programming error, but rather a
- * special case that the application is built to handle. It can occur during normal
- * program execution.
- */
-public class CannotCreateHandlingEventException extends Exception
-{
-    public CannotCreateHandlingEventException( String s )
-    {
-        super( s );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/exception/CannotCreateRouteSpecificationException.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/exception/CannotCreateRouteSpecificationException.java
deleted file mode 100644
index 086c597..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/factory/exception/CannotCreateRouteSpecificationException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.factory.exception;
-
-/**
- * Thrown when trying to create an invalid Route Specification.
- */
-public class CannotCreateRouteSpecificationException extends Exception
-{
-    private final String msg;
-
-    public CannotCreateRouteSpecificationException( String msg )
-    {
-        this.msg = msg;
-    }
-
-    @Override
-    public String getMessage()
-    {
-        return "Couldn't create a valid Route Specification: " + msg;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/cargo/Cargo.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/cargo/Cargo.java
deleted file mode 100644
index 4f0b628..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/cargo/Cargo.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.structure.cargo;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.tracking.TrackingId;
-
-/**
- * Cargo
- *
- * Data describing a cargo, it's planned route and current delivery status.
- *
- * {@link TrackingId}           created automatically
- * {@link Location} origin      Specified upon creation (mandatory)
- * {@link RouteSpecification}   Specified upon creation (mandatory)
- * {@link Itinerary}            Description of chosen route (optional)
- * {@link Delivery}             Snapshot of the current delivery status (automatically created by the system)
- */
-public interface Cargo
-{
-    @Immutable
-    Property<TrackingId> trackingId();
-
-    @Immutable
-    Association<Location> origin();
-
-    Property<RouteSpecification> routeSpecification();
-
-    @Optional
-    Property<Itinerary> itinerary();
-
-    Property<Delivery> delivery();
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/cargo/RouteSpecification.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/cargo/RouteSpecification.java
deleted file mode 100644
index cc72b5d..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/cargo/RouteSpecification.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.structure.cargo;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-
-/**
- * RouteSpecification
- *
- * Describes:
- * - where a cargo is going from (origin)
- * - the earliest departure date from origin (earliestDeparture)
- * - where a cargo is going to (destination)
- * - when a cargo is expected to arrive (arrivalDeadline)
- *
- * If the route specification needs to change because of unexpected
- * handling events, it's replaced with a new one in {@link Cargo}.
- *
- * An itinerary describes the route a cargo can take, and it satisfies the route
- * specification when the route
- * - starts in the origin location of the route specification origin
- * - starts after the earliest departure of the route specification
- * - ends in the destination location of the route specification
- * - ends before the arrival deadline of the route specification
- *
- * DCI Data is supposed to be dumb. Can we accept to have the specification
- * logic here?
- *
- * All properties are mandatory and immutable.
- */
-@Mixins( RouteSpecification.Mixin.class )
-public interface RouteSpecification
-    extends ValueComposite
-{
-    Association<Location> origin();
-
-    Association<Location> destination();
-
-    Property<Date> earliestDeparture();
-
-    Property<Date> arrivalDeadline();
-
-    // Side-effects free and UI agnostic convenience methods
-    boolean isSatisfiedBy( Itinerary itinerary );
-
-    String print();
-
-    abstract class Mixin
-        implements RouteSpecification
-    {
-        public boolean isSatisfiedBy( Itinerary itinerary )
-        {
-            return itinerary != null &&
-                   !itinerary.legs().get().isEmpty() &&
-                   origin().get().equals( itinerary.firstLeg().loadLocation().get() ) &&
-                   earliestDeparture().get().before( itinerary.firstLeg().loadTime().get() ) &&
-                   destination().get().equals( itinerary.lastLeg().unloadLocation().get() ) &&
-                   arrivalDeadline().get().after( itinerary.eta() );
-        }
-
-        public String print()
-        {
-            StringBuilder sb = new StringBuilder(
-                "\nROUTE SPECIFICATION ------------" ).
-                append( "\n  Origin               " ).append( origin().get() ).
-                append( "\n  Destination          " ).append( destination().get() ).
-                append( "\n  Earliest departure   " )
-                .append( new SimpleDateFormat( "yyyy-MM-dd" ).format( earliestDeparture().get() ) )
-                .
-                    append( "\n  Arrival deadline     " )
-                .append( new SimpleDateFormat( "yyyy-MM-dd" ).format( arrivalDeadline().get() ) )
-                .
-                    append( "\n--------------------------------" );
-            return sb.toString();
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/delivery/Delivery.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/delivery/Delivery.java
deleted file mode 100644
index 5c13f48..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/delivery/Delivery.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.structure.delivery;
-
-import java.util.Date;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-
-/**
- * Delivery
- *
- * The Delivery describes the actual transportation of the cargo, as opposed to
- * the Cargo Owner requirement {@link RouteSpecification} and the plan {@link Itinerary}.
- *
- * Complex data of the shipping domain is captured here in a value object that is
- * re-created each time some delivery status changes.
- *
- * Booking
- * The life cycle of a cargo begins with the booking procedure. During a (short) period
- * of time, between booking and initial routing, the cargo has no itinerary and is therefore
- * not routed.
- *
- * Routing
- * The Cargo Owner or booking clerk requests a list of possible routes, matching the route
- * specification, and assigns the cargo to a preferred route. The route to which a cargo is
- * assigned is described by an itinerary. The cargo is now routed.
- *
- * Cargo handling
- * Receipt of the cargo in the origin location marks the beginning of a series of handling
- * events that will eventually deliver the cargo at the destination. Handling events are
- * supposed to be reported by local handling authorities through incident logging applications
- * that then notify us of those events.
- *
- * Processing of handling events
- * When we receive handling event data from an incident logging application we validate
- * and register the event to determine what action to take. A new Delivery snapshot value
- * object is saved with the Cargo.
- *
- * Change of destination
- * It may happen that the Cargo Owner changes the destination of a cargo in the middle of a
- * voyage. The cargo route specification then no longer matches the itinerary and we say
- * that the cargo is misrouted. This will cause the system to notify the proper personel
- * and request the Cargo Owner to re-route the cargo.
- *
- * Re-routing
- * A cargo can be re-routed during transport, on demand of the Cargo Owner, in which case
- * a new itinerary is requested. The old itinerary, being a value object, is discarded and
- * a new one is attached to the cargo.
- *
- * Customs
- * The cargo can be checked by custom authorities anytime during the delivery. This doesn't
- * affect the delivery status of the cargo.
- *
- * Claim
- * The life cycle of a cargo ends when the cargo is claimed by the Cargo Owner.
- *
- * ItineraryProgressIndex
- * We have added an index that tells us how far we have come on our route. An Itinerary
- * describes a route by a list of "legs" that each describes a load time/location, a voyage
- * and an unload time/location. The itineraryProgressIndex indicates what leg is the current
- * leg. In the DDD sample the location was used to determine the current leg, but if the
- * cargo was suddenly in an unexpected location (not in the itinerary) then we wouldn't be
- * able to find out what to expect next. With the itineraryProgressIndex we can and that
- * allow us to derive a more precise delivery snapshot taking the chronological perspective
- * into account too.
- *
- * LastKnowLocation and currentVoyage didn't add much value since we can extract those from
- * the lastHandlingEvent, so we removed those.
- */
-public interface Delivery
-    extends ValueComposite
-{
-    Property<Date> timestamp();
-
-    /* (types:)
-     * RECEIVE
-     * LOAD
-     * UNLOAD
-     * CUSTOMS
-     * CLAIM
-     */
-    @Optional
-    Association<HandlingEvent> lastHandlingEvent();
-
-    /*
-     * NOT_RECEIVED
-     * IN_PORT
-     * ONBOARD_CARRIER
-     * CLAIMED
-     * UNKNOWN
-     */
-    Property<TransportStatus> transportStatus();
-
-    @UseDefaults
-    Property<Boolean> isUnloadedAtDestination();
-
-    /*
-     * NOT_ROUTED
-     * ROUTED
-     * MISROUTED
-     */
-    Property<RoutingStatus> routingStatus();
-
-    @UseDefaults
-    Property<Boolean> isMisdirected();
-
-    @Optional
-    Property<Date> eta();
-
-    // Index of earliest uncompleted Itinerary Leg - bumped up after each unload (except at destination)
-    @UseDefaults
-    Property<Integer> itineraryProgressIndex();
-
-    @Optional
-    Property<NextHandlingEvent> nextHandlingEvent();
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/delivery/NextHandlingEvent.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/delivery/NextHandlingEvent.java
deleted file mode 100644
index 72da122..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/delivery/NextHandlingEvent.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.structure.delivery;
-
-import java.util.Date;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-
-/**
- * NextHandlingEvent
- *
- * (former "HandlingActivity" / "ExpectedHandlingEvent")
- *
- * This represents our assumptions about the next handling event for a cargo.
- *
- * Since a cargo could have been loaded onto an unexpected carrier it seems better
- * not to call the next unload an _expected_ handling event. It's expected to
- * the carrier voyage schedule, but unexpected to the itinerary.
- *
- * A time for the expected event was added.
- */
-public interface NextHandlingEvent
-    extends ValueComposite
-{
-    Property<HandlingEventType> handlingEventType();
-
-    Association<Location> location();
-
-    @Optional
-    Property<Date> time();
-
-    @Optional
-    Association<Voyage> voyage();
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/delivery/RoutingStatus.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/delivery/RoutingStatus.java
deleted file mode 100644
index a09d3c3..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/delivery/RoutingStatus.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.structure.delivery;
-
-/**
- * RoutingStatus
- *
- * A routing status indicates whether an itinerary is assigned to
- * a cargo and satisfying the route specification.
- */
-public enum RoutingStatus
-{
-    NOT_ROUTED,    // Itinerary has not been assigned to cargo yet
-    ROUTED,        // Itinerary is assigned to cargo
-    MISROUTED;     // RouteSpecification is not satisfied by Itinerary
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/delivery/TransportStatus.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/delivery/TransportStatus.java
deleted file mode 100644
index f60edcc..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/delivery/TransportStatus.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.structure.delivery;
-
-/**
- * TransportStatus
- *
- * A transport status represents what transportation state a cargo is in.
- */
-public enum TransportStatus
-{
-    NOT_RECEIVED,
-    IN_PORT,
-    ONBOARD_CARRIER,
-    CLAIMED,
-    UNKNOWN
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/handling/HandlingEvent.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/handling/HandlingEvent.java
deleted file mode 100644
index b4b33c8..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/handling/HandlingEvent.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.structure.handling;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.tracking.TrackingId;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-
-/**
- * HandlingEvent
- *
- * A HandlingEvent is used to register the event when, for instance,
- * a cargo is unloaded from a carrier at some location at a given time.
- *
- * The HandlingEvents are sent from different Incident Logging Applications
- * some time after the event occurred and contain information about the
- * {@link TrackingId}, {@link Location}, timestamp of the completion of the event,
- * and possibly, if applicable a {@link Voyage}.
- *
- * Note that we don't save the whole cargo graph here as in the DDD sample! With
- * the tracking id saved only, our HandlingEvent objects become much lighter and
- * faster to save as we register incoming handling event data in high volumes from
- * incident logging applications.
- *
- * HandlingEvents could contain information about a {@link Voyage} and if so,
- * the event type must be either {@link HandlingEventType#LOAD} or
- * {@link HandlingEventType#UNLOAD}.
- *
- * All other events must be of type {@link HandlingEventType#RECEIVE},
- * {@link HandlingEventType#CLAIM} or {@link HandlingEventType#CUSTOMS}.
- */
-@Immutable
-@Mixins( HandlingEvent.Mixin.class )
-public interface HandlingEvent
-{
-    Property<Date> registrationTime();
-
-    Property<Date> completionTime();
-
-    Property<TrackingId> trackingId();
-
-    Property<HandlingEventType> handlingEventType();
-
-    Association<Location> location();
-
-    @Optional
-    Association<Voyage> voyage();
-
-    String print();
-
-    abstract class Mixin
-        implements HandlingEvent
-    {
-        public String print()
-        {
-            String voyage = "";
-            if( voyage().get() != null )
-            {
-                voyage = voyage().get().voyageNumber().get().number().get();
-            }
-
-            SimpleDateFormat date = new SimpleDateFormat( "yyyy-MM-dd" );
-
-            StringBuilder builder = new StringBuilder( "\nHANDLING EVENT -----------------" ).
-                append( "\n  Cargo       " ).append( trackingId().get().id().get() ).
-                append( "\n  Type        " ).append( handlingEventType().get().name() ).
-                append( "\n  Location    " ).append( location().get().getString() ).
-                append( "\n  Completed   " ).append( date.format( completionTime().get() ) ).
-                append( "\n  Registered  " ).append( date.format( registrationTime().get() ) ).
-                append( "\n  Voyage      " ).append( voyage ).
-                append( "\n--------------------------------\n" );
-
-            return builder.toString();
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/handling/HandlingEventType.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/handling/HandlingEventType.java
deleted file mode 100644
index 44f7f20..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/handling/HandlingEventType.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.structure.handling;
-
-/**
- * HandlingEventType
- *
- * A handling event type either requires or prohibits a voyage association.
- */
-public enum HandlingEventType
-{
-    RECEIVE( false ),
-    LOAD( true ),
-    UNLOAD( true ),
-    CUSTOMS( false ),
-    CLAIM( false );
-
-    private final boolean voyageRequired;
-
-    /**
-     * Private enum constructor.
-     *
-     * @param voyageRequired whether or not a voyage is associated with this event type
-     */
-    private HandlingEventType( final boolean voyageRequired )
-    {
-        this.voyageRequired = voyageRequired;
-    }
-
-    /**
-     * @return True if a voyage association is required for this event type.
-     */
-    public boolean requiresVoyage()
-    {
-        return voyageRequired;
-    }
-
-    /**
-     * @return True if a voyage association is prohibited for this event type.
-     */
-    public boolean prohibitsVoyage()
-    {
-        return !requiresVoyage();
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/itinerary/Itinerary.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/itinerary/Itinerary.java
deleted file mode 100644
index 41d2d4f..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/itinerary/Itinerary.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.structure.itinerary;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.List;
-import org.joda.time.Days;
-import org.joda.time.LocalDate;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.library.constraints.annotation.NotEmpty;
-
-/**
- * Itinerary
- *
- * Describes a planned route for a Cargo.
- *
- * The Itinerary has a list of Legs each describing expected loading onto/ unloading from
- * voyages at different locations. The list of legs is mandatory, immutable and can't be empty.
- */
-@Mixins( Itinerary.Mixin.class )
-public interface Itinerary
-    extends ValueComposite
-{
-    @NotEmpty
-    Property<List<Leg>> legs();
-
-    // Side-effects free and UI agnostic convenience methods
-    Leg firstLeg();
-
-    Leg leg( Integer current );
-
-    Leg lastLeg();
-
-    Date eta();
-
-    int days();
-
-    String print();
-
-    public abstract class Mixin
-        implements Itinerary
-    {
-        public Leg firstLeg()
-        {
-            return legs().get().get( 0 );
-        }
-
-        public Leg leg( Integer index )
-        {
-            if( index < 0 || index + 1 > legs().get().size() )
-            {
-                return null;
-            }
-
-            return legs().get().get( index );
-        }
-
-        public Leg lastLeg()
-        {
-            return legs().get().get( legs().get().size() - 1 );
-        }
-
-        public Date eta()
-        {
-            return lastLeg().unloadTime().get();
-        }
-
-        public int days()
-        {
-            Date dep = firstLeg().loadTime().get();
-            Date arr = lastLeg().unloadTime().get();
-            return Days.daysBetween( new LocalDate( dep ), new LocalDate( arr ) ).getDays();
-        }
-
-        public String print()
-        {
-            StringBuilder sb = new StringBuilder( "\nITINERARY -----------------------------------------------------" );
-            for( int i = 0; i < legs().get().size(); i++ )
-            {
-                printLeg( i, sb, legs().get().get( i ) );
-            }
-            return sb.append( "\n---------------------------------------------------------------\n" ).toString();
-        }
-
-        private void printLeg( int i, StringBuilder sb, Leg leg )
-        {
-            sb.append( "\n  Leg " ).append( i );
-            sb.append( "  Load " );
-            sb.append( new SimpleDateFormat( "yyyy-MM-dd" ).format( leg.loadTime().get() ) );
-            sb.append( " " ).append( leg.loadLocation().get() );
-            sb.append( "   " ).append( leg.voyage().get() );
-            sb.append( "   Unload " );
-            sb.append( new SimpleDateFormat( "yyyy-MM-dd" ).format( leg.unloadTime().get() ) );
-            sb.append( " " ).append( leg.unloadLocation().get() );
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/itinerary/Leg.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/itinerary/Leg.java
deleted file mode 100644
index bbcc286..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/itinerary/Leg.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.structure.itinerary;
-
-import java.util.Date;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-
-/**
- * A leg describes an expected segment of a route:
- * - loading onto a voyage at a load location
- * - unloading from the voyage at a unload location
- *
- * All properties are mandatory and immutable.
- */
-public interface Leg
-    extends ValueComposite
-{
-    Association<Location> loadLocation();
-
-    Property<Date> loadTime();
-
-    Association<Voyage> voyage();
-
-    Property<Date> unloadTime();
-
-    Association<Location> unloadLocation();
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/location/Location.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/location/Location.java
deleted file mode 100644
index 03cd585..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/location/Location.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.structure.location;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-
-/**
- * Location
- *
- * A location is a stop on a journey, such as cargo origin or destination, or
- * carrier movement endpoints.
- *
- * It is uniquely identified by a {@link UnLocode}.
- *
- * All properties are mandatory and immutable.
- */
-@Immutable
-@Mixins( Location.Mixin.class )
-public interface Location
-{
-    Property<UnLocode> unLocode();
-
-    Property<String> name();
-
-    // Side-effects free and UI agnostic convenience methods
-    String getCode();
-
-    String getString();
-
-    abstract class Mixin
-        implements Location
-    {
-        public String getCode()
-        {
-            return unLocode().get().code().get();
-        }
-
-        public String getString()
-        {
-            return name().get() + " (" + getCode() + ")";
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/location/UnLocode.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/location/UnLocode.java
deleted file mode 100644
index bb731cf..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/location/UnLocode.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.structure.location;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.library.constraints.annotation.Matches;
-
-/**
- * UnLocode
- *
- * A United Nations location code.
- *
- * http://www.unece.org/cefact/locode/
- * http://www.unece.org/cefact/locode/DocColumnDescription.htm#LOCODE
- *
- * UnLocode is mandatory and immutable.
- */
-public interface UnLocode
-    extends ValueComposite
-{
-    // Country code is exactly two letters.
-    // Location code is usually three letters, but may contain the numbers 2-9 as well
-    @Matches( "[a-zA-Z]{2}[a-zA-Z2-9]{3}" )
-    Property<String> code();
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/tracking/TrackingId.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/tracking/TrackingId.java
deleted file mode 100644
index dc6bd6e..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/tracking/TrackingId.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.structure.tracking;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.library.constraints.annotation.Matches;
-
-/**
- * TrackingId
- *
- * A TrackingId uniquely identifies a particular cargo.
- *
- * Suggested constraints:
- * - starts with a letter [a-zA-Z] or digit
- * - then allows underscore/dash
- * - is minimum 3 characters long
- * - is maximum 30 characters long.
- */
-public interface TrackingId
-    extends ValueComposite
-{
-    @Matches( "[a-zA-Z0-9]{1}[a-zA-Z0-9_-]{2,29}" )
-    Property<String> id();
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/voyage/CarrierMovement.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/voyage/CarrierMovement.java
deleted file mode 100644
index 20a2442..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/voyage/CarrierMovement.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.structure.voyage;
-
-import java.util.Date;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-
-/**
- * CarrierMovement
- *
- * A carrier movement is a vessel voyage from one location to another.
- *
- * All properties are mandatory and immutable.
- */
-public interface CarrierMovement
-    extends ValueComposite
-{
-    Association<Location> departureLocation();
-
-    Association<Location> arrivalLocation();
-
-    Property<Date> departureTime();
-
-    Property<Date> arrivalTime();
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/voyage/Schedule.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/voyage/Schedule.java
deleted file mode 100644
index 0bdec78..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/voyage/Schedule.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.structure.voyage;
-
-import java.util.List;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * Schedule
- *
- * A schedule is a series of {@link CarrierMovement}s.
- *
- * List of carrier movements is mandatory and immutable.
- */
-public interface Schedule
-    extends ValueComposite
-{
-    Property<List<CarrierMovement>> carrierMovements();
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/voyage/Voyage.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/voyage/Voyage.java
deleted file mode 100644
index aecae21..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/voyage/Voyage.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.structure.voyage;
-
-import java.text.SimpleDateFormat;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-
-/**
- * Voyage
- *
- * A voyage is a ship, train, flight etc carrying a cargo from one location
- * to another. A {@link Schedule} describes the route it takes.
- *
- * A cargo can be loaded onto part of, or the whole voyage.
- *
- * All properties are mandatory and immutable.
- */
-@Mixins( Voyage.Mixin.class )
-public interface Voyage
-{
-    Property<VoyageNumber> voyageNumber();
-
-    Property<Schedule> schedule();
-
-    // Side-effects free and UI agnostic convenience methods
-    CarrierMovement carrierMovementDepartingFrom( Location departure );
-
-    String print();
-
-    public abstract class Mixin
-        implements Voyage
-    {
-        public CarrierMovement carrierMovementDepartingFrom( Location departure )
-        {
-            for( CarrierMovement carrierMovement : schedule().get().carrierMovements().get() )
-            {
-                if( carrierMovement.departureLocation().get().equals( departure ) )
-                {
-                    return carrierMovement;
-                }
-            }
-
-            return null;
-        }
-
-        public String print()
-        {
-            StringBuilder sb = new StringBuilder( "\nVOYAGE " )
-                .append( voyageNumber().get().number().get() )
-                .append( " -----------------------------------------------------" );
-
-            for( int i = 0; i < schedule().get().carrierMovements().get().size(); i++ )
-            {
-                printLeg( i, sb, schedule().get().carrierMovements().get().get( i ) );
-            }
-
-            return sb.append( "\n---------------------------------------------------------------\n" ).toString();
-        }
-
-        private void printLeg( int i, StringBuilder sb, CarrierMovement carrierMovement )
-        {
-            sb.append( "\n  (Leg " ).append( i ).append( ")" );
-            sb.append( "  Departure " );
-            sb.append( new SimpleDateFormat( "yyyy-MM-dd" ).format( carrierMovement.departureTime().get() ) );
-            sb.append( " " ).append( carrierMovement.departureLocation().get() );
-            sb.append( "   Arrival  " );
-            sb.append( new SimpleDateFormat( "yyyy-MM-dd" ).format( carrierMovement.arrivalTime().get() ) );
-            sb.append( " " ).append( carrierMovement.arrivalLocation().get() );
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/voyage/VoyageNumber.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/voyage/VoyageNumber.java
deleted file mode 100644
index 895f2db..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/data/structure/voyage/VoyageNumber.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.data.structure.voyage;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * VoyageNumber
- *
- * Identifies a {@link Voyage}.
- *
- * Voyage number is mandatory and immutable.
- */
-public interface VoyageNumber
-    extends ValueComposite
-{
-    Property<String> number();
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/WicketQi4jApplication.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/WicketQi4jApplication.java
deleted file mode 100644
index 63dcf0d..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/WicketQi4jApplication.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure;
-
-import javax.servlet.http.HttpServletRequest;
-import org.apache.wicket.Page;
-import org.apache.wicket.protocol.http.WebApplication;
-import org.apache.wicket.request.cycle.AbstractRequestCycleListener;
-import org.apache.wicket.request.cycle.RequestCycle;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.conversion.EntityToDTOService;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.model.Queries;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.model.ReadOnlyModel;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.page.BaseWebPage;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * WicketQi4jApplication
- *
- * Base Wicket Web Application containing the Zest application.
- */
-public class WicketQi4jApplication
-    extends WebApplication
-{
-    public Logger logger = LoggerFactory.getLogger( WicketQi4jApplication.class );
-
-    protected Application qi4jApp;
-    protected Module qi4jModule;
-
-    @Structure
-    protected Module module;
-
-    @Structure
-    protected Qi4j qi4j;
-
-    @Service
-    protected EntityToDTOService valueConverter;
-
-    /**
-     * Zest Assembler
-     *
-     * To let the custom application class (DCISampleApplication_x) focus on starting up the
-     * Wicket environment, I made a convention of having Zest Assembler files in an 'assembly'
-     * folder beside the custom application class.
-     *
-     * There's always only one application file, but we could split the assemblage into several
-     * files ie. one for each layer. In that case, the Assembler file would be distributing to
-     * the individual LayerXAssembler classes.
-     *
-     * If you like, you can also override this method in the custom application class and simply
-     * return an instance of YourAssembler:
-     * <pre><code>
-     * &#64;Override protected ApplicationAssembler getAssembler() {
-     *     return new YourAssemblerInAnyPath();
-     * }
-     * </code></pre>
-     */
-    protected ApplicationAssembler getAssembler()
-        throws Exception
-    {
-        String appPath = getClass().getCanonicalName();
-        String expectedPathFromApplication = ".assembly.Assembler";
-        String assemblerPath = appPath.substring( 0, appPath.lastIndexOf( "." ) ) + expectedPathFromApplication;
-        try
-        {
-            return (ApplicationAssembler) Class.forName( assemblerPath ).newInstance();
-        }
-        catch( ClassNotFoundException e )
-        {
-            throw new Exception( "Couldn't find Zest assembler in path '" + assemblerPath + "'" );
-        }
-    }
-
-    protected String defaultLayerName()
-    {
-        return "BOOTSTRAP";
-    }
-
-    protected String defaultModuleName()
-    {
-        return "BOOTSTRAP-Bootstrap";
-    }
-
-    // Override this to bootstrap the wicket application
-    protected void wicketInit()
-    {
-    }
-
-    @Override
-    protected void init()
-    {
-        startQi4j();
-        handleUnitOfWork();
-
-        Context.prepareContextBaseClass( module );
-        BaseWebPage.prepareBaseWebPageClass( module );
-        ReadOnlyModel.prepareModelBaseClass( qi4jModule, qi4j, valueConverter );
-        Queries.prepareQueriesBaseClass( module, module );
-
-        wicketInit();
-    }
-
-    private void startQi4j()
-    {
-        try
-        {
-            logger.info( "Starting Zest application" );
-            Energy4Java qi4j = new Energy4Java();
-            qi4jApp = qi4j.newApplication( getAssembler() );
-            qi4jApp.activate();
-            qi4jModule = qi4jApp.findModule( defaultLayerName(), defaultModuleName() );
-
-            // Zest injects @Structure and @Service elements into this application instance
-            qi4jModule.injectTo( this );
-
-            logger.info( "Started Zest application" );
-        }
-        catch( Exception e )
-        {
-            logger.error( "Could not start Zest application." );
-            e.printStackTrace();
-            System.exit( 100 );
-        }
-    }
-
-    private void handleUnitOfWork()
-    {
-        getRequestCycleListeners().add( new AbstractRequestCycleListener()
-        {
-            @Override
-            public void onBeginRequest( final RequestCycle requestCycle )
-            {
-                super.onBeginRequest( requestCycle );
-
-                logger.debug( "================================" );
-                logger.debug( "REQUEST start" );
-                logger.debug( requestCycle.getRequest().toString() );
-                logger.debug( requestCycle.getRequest().getRequestParameters().toString() );
-
-                UnitOfWork uow = module.newUnitOfWork( UsecaseBuilder.newUsecase( "REQUEST" ) );
-                logger.debug( "  ### NEW " + uow + "   ### MODULE: " + qi4jModule );
-            }
-
-            @Override
-            public void onEndRequest( final RequestCycle requestCycle )
-            {
-                UnitOfWork uow = module.currentUnitOfWork();
-                if( uow != null )
-                {
-                    try
-                    {
-                        if( "POST".equals( ( (HttpServletRequest) requestCycle.getRequest()
-                            .getContainerRequest() ).getMethod() ) )
-                        {
-                            // "Save"
-                            logger.debug( "  ### COMPLETE " + uow + "   ### MODULE: " + qi4jModule );
-                            uow.complete();
-                        }
-                        else
-                        {
-                            // GET requests
-                            logger.debug( "  ### DISCARD " + uow + "   ### MODULE: " + qi4jModule );
-                            uow.discard();
-                        }
-                    }
-                    catch( UnitOfWorkCompletionException e )
-                    {
-                        logger.error( "  ### DISCARD " + uow + "   ### MODULE: " + qi4jModule );
-                        uow.discard();
-                        e.printStackTrace();
-                    }
-                }
-                logger.debug( "REQUEST end" );
-                logger.debug( "------------------------------------" );
-            }
-        } );
-    }
-
-    // Since Zest can only add concrete classes in the assembly, we need to implement a (dummy) getHomePage()
-    // method here. Override in wicket application class with a real returned page class.
-    @Override
-    public Class<? extends Page> getHomePage()
-    {
-        return null;
-    }
-
-    @Override
-    protected void onDestroy()
-    {
-        if( qi4jApp == null )
-        {
-            return;
-        }
-
-        try
-        {
-            logger.info( "Passivating Zest application" );
-            qi4jApp.passivate();
-        }
-        catch( Exception e )
-        {
-            e.printStackTrace();
-        }
-    }
-
-    public String appVersion()
-    {
-        return qi4jApp.version();
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/conversion/DTO.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/conversion/DTO.java
deleted file mode 100644
index 1ee78b3..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/conversion/DTO.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.conversion;
-
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * DTO
- *
- * Base class for DTOs
- *
- * Zest-comment:
- * ValueComposites that extend DTO are candidates to have association types converted and
- * assigned in the EntityToDTOService.
- */
-@Immutable
-public interface DTO extends ValueComposite
-{
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/conversion/EntityToDTOService.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/conversion/EntityToDTOService.java
deleted file mode 100644
index 50adef3..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/conversion/EntityToDTOService.java
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.conversion;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import org.qi4j.api.association.AssociationDescriptor;
-import org.qi4j.api.association.AssociationStateHolder;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.PropertyDescriptor;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.type.CollectionType;
-import org.qi4j.api.value.NoSuchValueException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.library.conversion.values.Unqualified;
-import org.qi4j.spi.Qi4jSPI;
-
-/**
- * Conversion of Entity objects to DTO's
- *
- * Value composites that extend {@link DTO} will have association properties converted recursively.
- *
- * Modification of {org.qi4j.library.conversion.values.EntityToValue}
- * WARN No support of NamedAssociations
- */
-@SuppressWarnings( "unchecked" )
-@Mixins( EntityToDTOService.Mixin.class )
-public interface EntityToDTOService
-    extends ServiceComposite
-{
-    <T> T convert( Class<T> valueType, Object entity );
-
-    static abstract class Mixin
-        implements EntityToDTOService
-    {
-        @Structure
-        private ValueBuilderFactory vbf;
-
-        @Structure
-        private Qi4jSPI spi;
-
-        @Structure
-        private Module module;
-
-        @Override
-        public <T> T convert( final Class<T> valueType, Object entity )
-        {
-            ValueDescriptor valueDescriptor = module.valueDescriptor( valueType.getName() );
-            if( valueDescriptor == null )
-            {
-                throw new NoSuchValueException( valueType.getName(), module.name() );
-            }
-            Unqualified unqualified = valueDescriptor.metaInfo( Unqualified.class );
-            final EntityComposite composite = (EntityComposite) entity;
-            final EntityDescriptor entityDescriptor = spi.entityDescriptorFor( composite );
-            final AssociationStateHolder associationState = spi.stateOf( composite );
-            ValueBuilder<?> builder;
-
-            if( unqualified == null || !unqualified.value() )
-            {
-                // Copy state using qualified names
-                builder = vbf.newValueBuilderWithState( valueType, new Function<PropertyDescriptor, Object>()
-                {
-                    @Override
-                    public Object map( PropertyDescriptor descriptor )
-                    {
-                        try
-                        {
-                            return associationState.propertyFor( descriptor.accessor() ).get();
-                        }
-                        catch( IllegalArgumentException e )
-                        {
-                            if( descriptor.valueType().mainType().equals( String.class ) )
-                            {
-                                // Find Association and convert to string
-                                AssociationDescriptor associationDescriptor;
-                                try
-                                {
-                                    associationDescriptor = entityDescriptor.state()
-                                        .getAssociationByName( descriptor.qualifiedName().name() );
-                                }
-                                catch( IllegalArgumentException e1 )
-                                {
-                                    return null;
-                                }
-                                Object entity = associationState.associationFor( associationDescriptor.accessor() ).get();
-                                if( entity != null )
-                                {
-                                    return ( (Identity) entity ).identity().get();
-                                }
-                                else
-                                {
-                                    return null;
-                                }
-                            }
-                            else if( descriptor.valueType() instanceof CollectionType
-                                     && ( (CollectionType) descriptor.valueType() ).collectedType().mainType().equals( String.class ) )
-                            {
-                                AssociationDescriptor associationDescriptor;
-                                try
-                                {
-                                    associationDescriptor = entityDescriptor.state()
-                                        .getManyAssociationByName( descriptor.qualifiedName().name() );
-                                }
-                                catch( IllegalArgumentException e1 )
-                                {
-                                    return Collections.emptyList();
-                                }
-
-                                ManyAssociation<?> state = associationState.manyAssociationFor( associationDescriptor.accessor() );
-                                List<String> entities = new ArrayList<>( state.count() );
-                                for( Object entity : state )
-                                {
-                                    entities.add( ( (Identity) entity ).identity().get() );
-                                }
-                                return entities;
-                            }
-
-                            // No NamedAssociation support
-
-                            return null;
-                        }
-                    }
-                }, new Function<AssociationDescriptor, EntityReference>()
-                {
-                    @Override
-                    public EntityReference map( AssociationDescriptor associationDescriptor )
-                    {
-                        return EntityReference.entityReferenceFor(
-                            associationState.associationFor( associationDescriptor.accessor() ).get() );
-                    }
-                }, new Function<AssociationDescriptor, Iterable<EntityReference>>()
-                {
-                    @Override
-                    public Iterable<EntityReference> map( AssociationDescriptor associationDescriptor )
-                    {
-                        ManyAssociation<?> state = associationState.manyAssociationFor( associationDescriptor.accessor() );
-                        List<EntityReference> refs = new ArrayList<>( state.count() );
-                        for( Object entity : state )
-                        {
-                            refs.add( EntityReference.entityReferenceFor( entity ) );
-                        }
-                        return refs;
-                    }
-                }, new Function<AssociationDescriptor, Map<String, EntityReference>>()
-                {
-                    @Override
-                    public Map<String, EntityReference> map( AssociationDescriptor from )
-                    {
-                        throw new UnsupportedOperationException( "NamedAssociations are not supported." );
-                    }
-                } );
-            }
-            else
-            {
-                builder = vbf.newValueBuilderWithState( valueType, new Function<PropertyDescriptor, Object>()
-                {
-                    @Override
-                    public Object map( PropertyDescriptor descriptor )
-                    {
-                        try
-                        {
-                            PropertyDescriptor propertyDescriptor = entityDescriptor.state()
-                                .findPropertyModelByName( descriptor.qualifiedName().name() );
-                            return associationState.propertyFor( propertyDescriptor.accessor() ).get();
-                        }
-                        catch( IllegalArgumentException e )
-                        {
-                            if( descriptor.valueType().mainType().equals( String.class ) )
-                            {
-                                // Find Association and convert to string
-                                AssociationDescriptor associationDescriptor;
-                                try
-                                {
-                                    associationDescriptor = entityDescriptor.state()
-                                        .getAssociationByName( descriptor.qualifiedName().name() );
-                                }
-                                catch( IllegalArgumentException e1 )
-                                {
-                                    return null;
-                                }
-
-                                Object entity = associationState.associationFor( associationDescriptor.accessor() ).get();
-                                if( entity != null )
-                                {
-                                    return ( (Identity) entity ).identity().get();
-                                }
-                                return null;
-                            }
-                            else if( descriptor.valueType() instanceof CollectionType
-                                     && ( (CollectionType) descriptor.valueType() ).collectedType().mainType().equals( String.class ) )
-                            {
-                                AssociationDescriptor associationDescriptor;
-                                try
-                                {
-                                    associationDescriptor = entityDescriptor.state()
-                                        .getManyAssociationByName( descriptor.qualifiedName().name() );
-                                }
-                                catch( IllegalArgumentException e1 )
-                                {
-                                    return null;
-                                }
-
-                                ManyAssociation<?> state = associationState.manyAssociationFor( associationDescriptor.accessor() );
-                                List<String> entities = new ArrayList<>( state.count() );
-                                for( Object entity : state )
-                                {
-                                    entities.add( ( (Identity) entity ).identity().get() );
-                                }
-                                return entities;
-                            }
-
-                            // No NamedAssociation support
-
-                            // DTO
-                            Class<?> type = descriptor.valueType().mainType();
-                            if( DTO.class.isAssignableFrom( type ) )
-                            {
-                                AssociationDescriptor associationDescriptor;
-                                try
-                                {
-                                    associationDescriptor = entityDescriptor.state()
-                                        .getAssociationByName( descriptor.qualifiedName().name() );
-                                }
-                                catch( IllegalArgumentException e1 )
-                                {
-                                    return null;
-                                }
-
-                                Object entity = associationState.associationFor( associationDescriptor.accessor() ).get();
-                                if( entity != null )
-                                {
-                                    return convert( type, entity );
-                                }
-                            }
-
-                            return null;
-                        }
-                    }
-                }, new Function<AssociationDescriptor, EntityReference>()
-                {
-                    @Override
-                    public EntityReference map( AssociationDescriptor descriptor )
-                    {
-                        AssociationDescriptor associationDescriptor;
-                        try
-                        {
-                            associationDescriptor = entityDescriptor.state()
-                                .getAssociationByName( descriptor.qualifiedName().name() );
-                        }
-                        catch( IllegalArgumentException e )
-                        {
-                            return null;
-                        }
-
-                        return EntityReference.entityReferenceFor( associationState
-                            .associationFor( associationDescriptor.accessor() ).get() );
-                    }
-                }, new Function<AssociationDescriptor, Iterable<EntityReference>>()
-                {
-                    @Override
-                    public Iterable<EntityReference> map( AssociationDescriptor descriptor )
-                    {
-                        AssociationDescriptor associationDescriptor;
-                        try
-                        {
-                            associationDescriptor = entityDescriptor.state()
-                                .getManyAssociationByName( descriptor.qualifiedName().name() );
-                        }
-                        catch( IllegalArgumentException e )
-                        {
-                            return Iterables.empty();
-                        }
-
-                        ManyAssociation<?> state = associationState.manyAssociationFor( associationDescriptor.accessor() );
-                        List<EntityReference> refs = new ArrayList<>( state.count() );
-                        for( Object entity : state )
-                        {
-                            refs.add( EntityReference.entityReferenceFor( entity ) );
-                        }
-                        return refs;
-                    }
-                }, new Function<AssociationDescriptor, Map<String, EntityReference>>()
-                {
-                    @Override
-                    public Map<String, EntityReference> map( AssociationDescriptor from )
-                    {
-                        throw new UnsupportedOperationException( "NamedAssociations are not supported." );
-                    }
-                } );
-            }
-
-            return (T) builder.newInstance();
-        }
-    }
-
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/dci/Context.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/dci/Context.java
deleted file mode 100644
index 06340d7..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/dci/Context.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.dci;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.api.value.ValueComposite;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Context
- *
- * Base class for DCI Contexts
- *
- * Helps assigning Entity objects to Roles and to "inject" the Context object into Methodful Roles.
- */
-public abstract class Context
-{
-    protected Logger logger = LoggerFactory.getLogger( getClass() );
-
-    /**
-     * We don't allow SubContexts to access the store directly
-     *
-     * All entities should be created through aggregate r
-     */
-    private static Module module;
-
-    protected Context()
-    {
-    }
-
-    /*
-        * Role assignment + Context "injection"
-        *
-        * Cast a Data object to a Role, set the Context object in the Role and return the RolePlayer.
-        *
-        * Requirements:
-        * 1) SomeRole interface declares a 'void setContext(YourContext context);' method
-        * 2) SomeRole.Mixin class extends RoleMixin<YourContext>
-        *
-        * The RolePlayer can then use the context pointer to lookup other Roles in the current Context.
-        */
-    protected <T> T rolePlayer( Class<T> roleClass, Object dataObject )
-    {
-        if( dataObject == null )
-        {
-            return null;
-        }
-
-        objectCanPlayRole( roleClass, dataObject );
-        T rolePlayer = roleClass.cast( dataObject );
-        setContext( rolePlayer, this );
-        return rolePlayer;
-    }
-
-    private <T> void objectCanPlayRole( Class<T> roleClass, Object dataObject )
-    {
-        if( roleClass.isAssignableFrom( dataObject.getClass() ) )
-        {
-            return;
-        }
-
-        String className;
-        if( dataObject instanceof Proxy )
-        {
-            className = Proxy.getInvocationHandler( dataObject ).getClass().getSimpleName();
-        }
-        else
-        {
-            className = dataObject.getClass().getSimpleName();
-        }
-
-        throw new IllegalArgumentException(
-            "Object '" + className + "' can't play Role of '" + roleClass.getSimpleName() + "'" );
-    }
-
-    /*
-    * Poor mans Context injection
-    * */
-    private <T> void setContext( T rolePlayer, Context context )
-    {
-        try
-        {
-            Method setContextMethod = rolePlayer.getClass().getDeclaredMethod( "setContext", context.getClass() );
-
-            // Set Context in Role
-            setContextMethod.invoke( rolePlayer, context );
-        }
-        catch( Exception e )
-        {
-            String c = context.getClass().getSimpleName();
-            String r = rolePlayer.getClass().getSimpleName();
-            String msg = "Couldn't invoke 'void setContext( " + c + " context);' on " + r + "." +
-                         "\nPlease check the following requirements: " +
-                         "\n1) 'void setContext( " + c + " context);' is declared in " + r + " interface." +
-                         "\n2) " + r + " extends RoleMixin<" + c + ">";
-            logger.error( msg, e.getMessage() );
-            e.printStackTrace();
-            throw new RuntimeException( msg );
-        }
-    }
-
-    // Entity object instantiation
-
-    protected <T, U> T rolePlayer( Class<T> roleClass, Class<U> dataClass, String entityId )
-    {
-        U dataObject = module.currentUnitOfWork().get( dataClass, entityId );
-        return rolePlayer( roleClass, dataObject );
-    }
-
-    protected static <T> T loadEntity( Class<T> entityRoleClass, String entityId )
-    {
-        return module.currentUnitOfWork().get( entityRoleClass, entityId );
-    }
-
-    protected static <T extends ValueComposite> ValueBuilder<T> valueBuilder( Class<T> valueClass )
-    {
-        return module.newValueBuilder( valueClass );
-    }
-
-    public static void prepareContextBaseClass( Module module )
-    {
-        Context.module = module;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/dci/RoleMixin.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/dci/RoleMixin.java
deleted file mode 100644
index 7571439..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/dci/RoleMixin.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.dci;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.query.QueryBuilderFactory;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilderFactory;
-
-/**
- * RoleMixin
- *
- * Base class for Methodful Roles in Contexts
- *
- * Helps "inject" the Context object into the Role Player.
- *
- * The context field name is now "c" since we don't want the word "context" interfere
- * with domain semantics. We could for instance in one domain have some "material context"
- * where "context" is not a DCI Context but the context of some material. In that case a
- * DCI keyword "context" would confuse the semantics. We could also use "ctx", but why not
- * the shortest option? Less typing, and we know what it is. Furthermore a single letter is
- * easier to spot in the code masses than "ctx" (good to be able to quickly spot all uses
- * of the Context).
- */
-public abstract class RoleMixin<T extends Context>
-{
-    // Context object reference
-    public T c;
-
-    // Other common role services/methods could be added here...
-
-    @Structure
-    public UnitOfWorkFactory uowf;
-
-    @Structure
-    public QueryBuilderFactory qbf;
-
-    @Structure
-    public ValueBuilderFactory vbf;
-
-    /**
-     * setContext is called with method invocation in {@link Context#setContext(Object, Context)}
-     * (therefore "never used" according to IDE)
-     */
-    public void setContext( T context )
-    {
-        c = context;
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/model/EntityModel.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/model/EntityModel.java
deleted file mode 100644
index fc303e0..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/model/EntityModel.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- * Copyright (c) 2013, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.model;
-
-import org.apache.wicket.model.IModel;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.conversion.DTO;
-
-/**
- * EntityModel
- *
- * A Wicket Model that bridges to our Zest data store.
- *
- * In Wicket we need to be able to pass around serializable data that can be "detachable".
- * Zest entities are therefore lazy loaded with a class and identity through our UnitOfWork
- * and then converted to a DTO ValueComposite.
- */
-public class EntityModel<T extends DTO, U extends EntityComposite>
-    extends ReadOnlyModel<T>
-{
-    private Class<U> entityClass;
-    private String identity;
-    private Class<T> dtoClass;
-
-    private transient T dtoComposite;
-
-    public EntityModel( Class<U> entityClass, String identity, Class<T> dtoClass )
-    {
-        this.entityClass = entityClass;
-        this.identity = identity;
-        this.dtoClass = dtoClass;
-    }
-
-    public static <T extends DTO, U extends EntityComposite> IModel<T> of(
-        Class<U> entityClass, String identity, Class<T> dtoClass
-    )
-    {
-        return new EntityModel<T, U>( entityClass, identity, dtoClass );
-    }
-
-    public T getObject()
-    {
-        if( dtoComposite == null && identity != null )
-        {
-            dtoComposite = valueConverter.convert( dtoClass, loadEntity() );
-        }
-        return dtoComposite;
-    }
-
-    public void detach()
-    {
-        dtoComposite = null;
-    }
-
-    private U loadEntity()
-    {
-        U entity = module.currentUnitOfWork().get( entityClass, identity );
-        if( entity == null )
-        {
-            Usecase usecase = module.currentUnitOfWork().usecase();
-            throw new NoSuchEntityException( EntityReference.parseEntityReference( identity ), entityClass, usecase );
-        }
-        return entity;
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/model/JSONModel.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/model/JSONModel.java
deleted file mode 100644
index a61a8a8..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/model/JSONModel.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.model;
-
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.api.value.ValueSerializer;
-
-/**
- * JSONModel
- *
- * Model that can serialize/de-serialize an object to/from a JSON string.
- */
-public class JSONModel<T, U extends ValueComposite>
-    extends ReadOnlyModel<T>
-{
-    private Class<U> valueCompositeClass;
-    private String json;
-    private transient T valueComposite;
-
-    @SuppressWarnings( "unchecked" )
-    public JSONModel( T valueComposite, Class<U> valueCompositeClass )
-    {
-        json = module.findService( ValueSerializer.class ).get().serialize( (U) valueComposite );;
-        this.valueCompositeClass = valueCompositeClass;
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public static <T, U extends ValueComposite> JSONModel<T, U> of( T value )
-    {
-        if( !( value instanceof ValueComposite ) )
-        {
-            throw new RuntimeException( value + " has to be an instance of a ValueComposite." );
-        }
-
-        // Get ValueComposite interface
-        Class<U> valueCompositeClass = (Class<U>) qi4j.valueDescriptorFor( value ).valueType().mainType();
-
-        return new JSONModel<T, U>( value, valueCompositeClass );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public T getObject()
-    {
-        if( valueComposite == null && json != null )
-        {
-            // De-serialize
-            valueComposite = (T) module.newValueFromSerializedState( valueCompositeClass, json ); // Unchecked cast
-        }
-        return valueComposite;
-    }
-
-    public void detach()
-    {
-        valueComposite = null;
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/model/Queries.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/model/Queries.java
deleted file mode 100644
index 4658516..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/model/Queries.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.model;
-
-import java.io.Serializable;
-import org.qi4j.api.query.QueryBuilderFactory;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-
-/**
- * Queries
- *
- * Base class for Queries objects in our query package in the communication layer.
- */
-public class Queries
-    implements Serializable // For Wicket (don't remove)
-{
-    static protected UnitOfWorkFactory uowf;
-    static protected QueryBuilderFactory qbf;
-
-    public static void prepareQueriesBaseClass( UnitOfWorkFactory unitOfWorkFactory,
-                                                QueryBuilderFactory queryBuilderFactory
-    )
-    {
-        uowf = unitOfWorkFactory;
-        qbf = queryBuilderFactory;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/model/QueryModel.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/model/QueryModel.java
deleted file mode 100644
index eabf703..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/model/QueryModel.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.model;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.query.Query;
-
-/**
- * QueryModel
- *
- * Callback Wicket model that holds a Zest Query object that can be called when needed to
- * retrieve fresh data.
- */
-public abstract class QueryModel<T, U extends EntityComposite>
-    extends ReadOnlyModel<List<T>>
-{
-    private Class<T> dtoClass;
-    private transient List<T> dtoList;
-
-    public QueryModel( Class<T> dtoClass )
-    {
-        this.dtoClass = dtoClass;
-    }
-
-    public List<T> getObject()
-    {
-        if( dtoList != null )
-        {
-            return dtoList;
-        }
-
-        dtoList = new ArrayList<T>();
-        for( U entity : getQuery() )
-        {
-            dtoList.add( getValue( entity ) );
-        }
-
-        return dtoList;
-    }
-
-    // Callback to retrieve the (unserializable) Zest Query object
-    public abstract Query<U> getQuery();
-
-    public T getValue( U entity )
-    {
-        return valueConverter.convert( dtoClass, entity );
-    }
-
-    public void detach()
-    {
-        dtoList = null;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/model/ReadOnlyModel.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/model/ReadOnlyModel.java
deleted file mode 100644
index 8eadb4f..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/model/ReadOnlyModel.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.model;
-
-import org.apache.wicket.model.IModel;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.structure.Module;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.conversion.EntityToDTOService;
-
-/**
- * ReadOnlyModel
- *
- * Abstract base model for Wicket model objects taking Zest objects.
- */
-public abstract class ReadOnlyModel<T>
-    implements IModel<T>
-{
-    private static final long serialVersionUID = 1L;
-
-    static protected EntityToDTOService valueConverter;
-    static protected Qi4j qi4j;
-    static protected Module module;
-
-    /**
-     * This default implementation of setObject unconditionally throws an
-     * UnsupportedOperationException. Since the method is final, any subclass is effectively a
-     * read-only model.
-     *
-     * @param object The object to set into the model
-     *
-     * @throws UnsupportedOperationException
-     */
-    public final void setObject( final T object )
-    {
-        throw new UnsupportedOperationException( "Model " + getClass() +
-                                                 " does not support setObject(Object)" );
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder( "Model:classname=[" );
-        sb.append( getClass().getName() ).append( "]" );
-        return sb.toString();
-    }
-
-    public static void prepareModelBaseClass( Module m,
-                                              Qi4j api,
-                                              EntityToDTOService entityToDTO
-    )
-    {
-        module = m;
-        qi4j = api;
-        valueConverter = entityToDTO;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/color/CorrectColor.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/color/CorrectColor.java
deleted file mode 100644
index bf829cf..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/color/CorrectColor.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.color;
-
-import org.apache.wicket.AttributeModifier;
-
-/**
- * CorrectColor
- *
- * Convenience method for adding an AttributeModifier based on a boolean value.
- */
-public class CorrectColor extends AttributeModifier
-{
-    public CorrectColor( Boolean condition )
-    {
-        super( "class", condition ? "correctColor" : "VA_REMOVE" );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/color/ErrorColor.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/color/ErrorColor.java
deleted file mode 100644
index 0c339f5..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/color/ErrorColor.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.color;
-
-import org.apache.wicket.AttributeModifier;
-
-/**
- * ErrorColor
- *
- * Convenience method for adding an AttributeModifier based on a boolean value.
- */
-public class ErrorColor extends AttributeModifier
-{
-    public ErrorColor( Boolean condition )
-    {
-        super( "class", condition ? "errorColor" : "VA_REMOVE" );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/form/AbstractForm.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/form/AbstractForm.java
deleted file mode 100644
index 2cbf34d..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/form/AbstractForm.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.form;
-
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.markup.html.form.Button;
-import org.apache.wicket.markup.html.form.CheckBox;
-import org.apache.wicket.markup.html.form.FormComponent;
-import org.apache.wicket.markup.html.form.RadioChoice;
-import org.apache.wicket.markup.html.form.StatelessForm;
-import org.apache.wicket.util.visit.IVisit;
-import org.apache.wicket.util.visit.IVisitor;
-
-/**
- * AbstractForm
- *
- * Base class for forms.
- */
-public abstract class AbstractForm<T> extends StatelessForm<T>
-{
-    public AbstractForm( String id )
-    {
-        super( id );
-    }
-
-    public AbstractForm()
-    {
-        super( "form" );
-    }
-
-    public void focusFirstError( final AjaxRequestTarget target )
-    {
-        visitFormComponents( new IVisitor<FormComponent<?>, Void>()
-        {
-            public void component( FormComponent<?> fc, IVisit<Void> visit )
-            {
-                if( isOtherComponent( fc ) || fc.isValid() )
-                {
-                    return;
-                }
-
-                target.focusComponent( fc );
-                visit.stop();
-            }
-        } );
-    }
-
-    private boolean isOtherComponent( FormComponent<?> fc )
-    {
-        return fc instanceof Button || fc instanceof CheckBox || fc instanceof RadioChoice;
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/form/DateTextFieldWithPicker.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/form/DateTextFieldWithPicker.java
deleted file mode 100644
index ff6d131..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/form/DateTextFieldWithPicker.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.form;
-
-import com.google.code.joliratools.StatelessAjaxEventBehavior;
-import java.util.Date;
-import java.util.Map;
-import org.apache.wicket.Component;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.datetime.DateConverter;
-import org.apache.wicket.datetime.PatternDateConverter;
-import org.apache.wicket.datetime.markup.html.form.DateTextField;
-import org.apache.wicket.devutils.stateless.StatelessComponent;
-import org.apache.wicket.extensions.yui.calendar.DatePicker;
-import org.apache.wicket.markup.html.IHeaderResponse;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.apache.wicket.validation.validator.DateValidator;
-import org.joda.time.DateTime;
-import org.joda.time.LocalDate;
-import org.joda.time.LocalTime;
-
-/**
- * DateTextFieldWithPicker
- *
- * Customized {@link DateTextField} with a {@link DatePicker}.
- */
-@StatelessComponent
-public class DateTextFieldWithPicker extends DateTextField
-{
-    DatePicker datePicker;
-
-    // Configurable widget options
-    LocalDate earliestDate;
-    LocalDate selectedDate;
-
-    final static String YUI_DATE_FORMAT = "MM/dd/yyyy";
-
-    public DateTextFieldWithPicker( String id, String label, Component model )
-    {
-//      this( id, new PropertyModel<Date>( model, id ), new StyleDateConverter( "S-", true ) );
-        this( id, label, new PropertyModel<Date>( model, id ), new PatternDateConverter( "yyyy-MM-dd", true ) );
-    }
-
-    public DateTextFieldWithPicker( String id, String label, IModel<Date> model, DateConverter converter )
-    {
-        super( id, model, converter );
-
-        // Make the text field reachable by Ajax requests
-        setOutputMarkupId( true );
-
-        // Set required as default
-        setRequired( true );
-
-        // Add Date Picker with callback configuration
-        add( newDatePicker().setShowOnFieldClick( true ) );
-
-        setNonEmptyLabel( label );
-
-        // Show calendar if tabbing into the text field (weird it isn't default)
-        add( new StatelessAjaxEventBehavior( "onfocus" )
-        {
-            @Override
-            protected void onEvent( AjaxRequestTarget target )
-            {
-                String componentId = getComponent().getMarkupId();
-                String widgetId = componentId + "DpJs";
-                target.appendJavaScript(
-                    "Wicket.DateTime.showCalendar(" +
-                    "YAHOO.wicket['" + widgetId + "'], " +
-                    "document.getElementById('" + componentId + "').value, " +
-                    "'yyyy-MM-dd');"
-                );
-            }
-
-            @Override
-            protected PageParameters getPageParameters()
-            {
-                return null;
-            }
-        } );
-
-//        add( new StatelessAjaxEventBehavior( "onBlur" )
-//        {
-//            @Override
-//            protected void onEvent( AjaxRequestTarget target )
-//            {
-//                String componentId = getComponent().getMarkupId();
-//                String widgetId = componentId + "DpJs";
-//                target.appendJavaScript(
-//                      "Wicket.DateTime.showCalendar(" +
-//                            "YAHOO.wicket['" + widgetId + "'], " +
-//                            "document.getElementById('" + componentId + "').value, " +
-//                            "'yyyy-MM-dd');" +
-//                      "YAHOO.wicket['" + widgetId + "'].hide();" );
-//            }
-//
-//            @Override
-//            protected PageParameters getPageParameters()
-//            {
-//                return null;
-//            }
-//        } );
-    }
-
-    private void setNonEmptyLabel( String label )
-    {
-        if( label == null )
-        {
-            return;
-        }
-
-        if( label.isEmpty() )
-        {
-            throw new IllegalArgumentException( "Can't set an empty label on the drop down selector." );
-        }
-
-        setLabel( Model.of( label ) );
-    }
-
-    /**
-     * The DatePicker that gets added to the DateTextField component. Users may override this method
-     * with a DatePicker of their choice.
-     *
-     * @return a new {@link DatePicker} instance
-     */
-    protected DatePicker newDatePicker()
-    {
-        return new DatePicker()
-        {
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            protected void configure( final Map<String, Object> widgetProperties,
-                                      final IHeaderResponse response, final Map<String, Object> initVariables
-            )
-            {
-                super.configure( widgetProperties, response, initVariables );
-
-                DateTextFieldWithPicker.this.configure( widgetProperties );
-            }
-        };
-    }
-
-    /**
-     * Gives overriding classes the option of adding (or even changing/ removing) configuration
-     * properties for the javascript widget. See <a
-     * href="http://developer.yahoo.com/yui/calendar/">the widget's documentation</a> for the
-     * available options. If you want to override/ remove properties, you should call
-     * super.configure(properties) first. If you don't call that, be aware that you will have to
-     * call {@literal #localize(Map)} manually if you like localized strings to be added.
-     *
-     * @param widgetProperties the current widget properties
-     */
-    protected void configure( Map<String, Object> widgetProperties )
-    {
-        // Set various YUI calendar options - add more if necessary
-        widgetProperties.put( "mindate", getEarliestDateStr() );
-        widgetProperties.put( "selected", getSelectedDateStr() );
-    }
-
-    public DateTextFieldWithPicker earliestDate( LocalDate newEarliestDate )
-    {
-        if( selectedDate != null && newEarliestDate.isAfter( selectedDate ) )
-        {
-            throw new IllegalArgumentException( "Earliest date can't be before selected day." );
-        }
-
-        earliestDate = newEarliestDate;
-
-        // Input field validation - date should be _after_ minimumDate (not the same)
-        LocalDate minimumDate = newEarliestDate.minusDays( 1 );
-        Date convertedMinimumDate = new DateTime( minimumDate.toDateTime( new LocalTime() ) ).toDate();
-        add( DateValidator.minimum( convertedMinimumDate ) );
-
-        return this;
-    }
-
-    // Add latestDate(..) + other configuration options if needed..
-
-    public DateTextFieldWithPicker selectedDate( LocalDate newSelectedDate )
-    {
-        if( earliestDate != null && newSelectedDate.isBefore( earliestDate ) )
-        {
-            throw new IllegalArgumentException( "Selected date can't be before earliest day." );
-        }
-
-        selectedDate = newSelectedDate;
-
-        return this;
-    }
-
-    private String getSelectedDateStr()
-    {
-        if( selectedDate != null )
-        {
-            return selectedDate.toString( YUI_DATE_FORMAT );
-        }
-
-        // Select today or earliest date (if later) as default
-        return earliestDate == null ?
-               new LocalDate().toString( YUI_DATE_FORMAT ) :
-               earliestDate.toString( YUI_DATE_FORMAT );
-    }
-
-    private String getEarliestDateStr()
-    {
-        return earliestDate == null ? "" : earliestDate.toString( YUI_DATE_FORMAT );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/form/SelectorInForm.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/form/SelectorInForm.java
deleted file mode 100644
index 40b0536..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/form/SelectorInForm.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.form;
-
-import java.util.List;
-import org.apache.wicket.markup.html.form.DropDownChoice;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.model.util.ListModel;
-
-/**
- * SelectorInForm
- *
- * Convenience drop down list that resolves properties against a form.
- */
-public class SelectorInForm extends DropDownChoice<String>
-{
-    PropertyModel<String> disablingPropertyModel;
-    String disablingValue = "";
-
-    public SelectorInForm( String property, String label, List<String> choices, Form form )
-    {
-        super( property + "Selector", new PropertyModel<String>( form, property ), new ListModel<String>( choices ) );
-        setNonEmptyLabel( label );
-        setOutputMarkupId( true );
-    }
-
-    public SelectorInForm( String property, String label, List<String> choices, Form form, String disablingProperty )
-    {
-        super( property + "Selector", new PropertyModel<String>( form, property ), new ListModel<String>( choices ) );
-        disablingPropertyModel = new PropertyModel<String>( form, disablingProperty );
-        setNonEmptyLabel( label );
-        setOutputMarkupId( true );
-    }
-
-    private void setNonEmptyLabel( String label )
-    {
-        if( label == null )
-        {
-            return;
-        }
-
-        if( label.isEmpty() )
-        {
-            throw new IllegalArgumentException( "Can't set an empty label on the drop down selector." );
-        }
-
-        setLabel( Model.of( label ) );
-    }
-
-    @Override
-    protected boolean isDisabled( final String currentValue, int index, String selected )
-    {
-        if( disablingPropertyModel != null )
-        {
-            disablingValue = disablingPropertyModel.getObject();
-        }
-
-        return currentValue.equals( disablingValue );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/link/LinkPanel.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/link/LinkPanel.java
deleted file mode 100644
index 96d182d..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/link/LinkPanel.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.link;
-
-import org.apache.wicket.Page;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.link.BookmarkablePageLink;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-
-/**
- * LinkPanel
- *
- * Convenience panel for displaying a bookmarkable link
- */
-public class LinkPanel extends Panel
-{
-    public <T extends Page> LinkPanel( String id, Class<T> pageClass, String rowId )
-    {
-        this( id, pageClass, rowId, rowId );
-    }
-
-    public <T extends Page> LinkPanel( String id, Class<T> pageClass, String rowId, String label )
-    {
-        super( id );
-
-        PageParameters pageParameters = new PageParameters().set( 0, rowId );
-        BookmarkablePageLink<Void> link = new BookmarkablePageLink<Void>( "link", pageClass, pageParameters );
-        link.add( new Label( "label", label ) );
-        add( link );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/page/BaseWebPage.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/page/BaseWebPage.java
deleted file mode 100644
index b96f3ad..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/page/BaseWebPage.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.page;
-
-import org.apache.wicket.markup.html.WebPage;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.qi4j.api.composite.TransientBuilderFactory;
-import org.qi4j.api.composite.TransientComposite;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * BaseWebPage
- *
- * Convenience base page to provide access to common resources
- */
-public class BaseWebPage extends WebPage
-{
-    public Logger logger = LoggerFactory.getLogger( getClass() );
-
-    static protected TransientBuilderFactory tbf;
-
-    public BaseWebPage( PageParameters pageParameters )
-    {
-        super( pageParameters );
-    }
-
-    public BaseWebPage()
-    {
-    }
-
-    public static <T extends TransientComposite> T query( Class<T> queryClass )
-    {
-        return tbf.newTransient( queryClass );
-    }
-
-    public static void prepareBaseWebPageClass( TransientBuilderFactory transientBuilderFactory )
-    {
-        tbf = transientBuilderFactory;
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/prevnext/PrevNext.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/prevnext/PrevNext.java
deleted file mode 100644
index b78ecde..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/prevnext/PrevNext.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.prevnext;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import org.apache.wicket.AttributeModifier;
-import org.apache.wicket.MetaDataKey;
-import org.apache.wicket.Page;
-import org.apache.wicket.Session;
-import org.apache.wicket.devutils.stateless.StatelessComponent;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.link.BookmarkablePageLink;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
-
-/**
- * PrevNext
- *
- * Panel for displaying and administrating pre/next arrows to browse detail pages
- * of records from a list. Record ids are kept in the session. Also takes care of
- * showing disabled icons at beginning/end.
- */
-@StatelessComponent
-public class PrevNext extends Panel
-{
-    private static final MetaDataKey<ArrayList<String>> PREV_NEXT_PANEL_KEY = new MetaDataKey<ArrayList<String>>()
-    {
-        private static final long serialVersionUID = 1L;
-    };
-
-    public static void registerIds( Session session, ArrayList<String> ids )
-    {
-        if( ids == null || ids.isEmpty() )
-        {
-            throw new RuntimeException( "Please register a list of ids." );
-        }
-
-        session.setMetaData( PREV_NEXT_PANEL_KEY, ids );
-        session.bind();
-    }
-
-    public static void addId( Session session, String id )
-    {
-        if( id == null || id.isEmpty() )
-        {
-            throw new RuntimeException( "Can't register empty id." );
-        }
-
-        ArrayList<String> ids = session.getMetaData( PREV_NEXT_PANEL_KEY );
-        if( ids == null || ids.isEmpty() )
-        {
-            ids = new ArrayList<String>();
-        }
-
-        ids.add( id );
-        session.setMetaData( PREV_NEXT_PANEL_KEY, ids );
-        session.bind();
-    }
-
-    public PrevNext( String id, Class<? extends Page> pageClass, String actualId )
-    {
-        super( id );
-
-        List<String> ids = getSession().getMetaData( PREV_NEXT_PANEL_KEY );
-
-        if( ids == null || ids.size() == 0 )
-        {
-            setEnabled( false );
-            setVisible( false );
-            return;
-        }
-
-        String prev = null;
-        String current;
-        for( Iterator<String> it = ids.iterator(); it.hasNext(); )
-        {
-            current = it.next();
-            if( current.equals( actualId ) )
-            {
-                if( prev == null )
-                {
-                    add( new WebMarkupContainer( "prev" ).add( new AttributeModifier( "class", "prevDisabled" ) ) );
-                }
-                else
-                {
-                    add( new BookmarkablePageLink<Void>( "prev", pageClass, new PageParameters().set( 0, prev ) ) );
-                }
-
-                if( !it.hasNext() )
-                {
-                    add( new WebMarkupContainer( "next" ).add( new AttributeModifier( "class", "nextDisabled" ) ) );
-                }
-                else
-                {
-                    add( new BookmarkablePageLink<Void>( "next", pageClass, new PageParameters().set( 0, it.next() ) ) );
-                }
-
-                return;
-            }
-            prev = current;
-        }
-
-        throw new RuntimeException( "Passed tracking id was not found in the PrevNextSession." );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/tabs/TabsPanel.java b/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/tabs/TabsPanel.java
deleted file mode 100644
index 67ea90e..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/tabs/TabsPanel.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.wicket.tabs;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-import org.apache.wicket.Application;
-import org.apache.wicket.AttributeModifier;
-import org.apache.wicket.MetaDataKey;
-import org.apache.wicket.Page;
-import org.apache.wicket.devutils.stateless.StatelessComponent;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.link.BookmarkablePageLink;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.markup.repeater.RepeatingView;
-
-/**
- * TabsPanel
- *
- * Convenience panel that stores tab data as application meta data.
- */
-@StatelessComponent
-public class TabsPanel extends Panel
-{
-    public static final MetaDataKey<LinkedHashMap<Class, String[]>> TABS_PANEL_KEY = new MetaDataKey<LinkedHashMap<Class, String[]>>()
-    {
-        public static final long serialVersionUID = 1L;
-    };
-
-    public static <T extends Page> void registerTab( Application app, Class<T> clazz, String ref, String label )
-    {
-        registerTab( app, clazz, ref, label, null );
-    }
-
-    public static <T extends Page> void registerTab( Application app,
-                                                     Class<T> clazz,
-                                                     String ref,
-                                                     String label,
-                                                     String cssClass
-    )
-    {
-        Map<Class, String[]> tabsInfo = app.getMetaData( TABS_PANEL_KEY );
-
-        if( tabsInfo == null || tabsInfo.isEmpty() )
-        {
-            tabsInfo = new LinkedHashMap<Class, String[]>();
-        }
-
-        tabsInfo.put( clazz, new String[]{ ref, label } );
-        app.setMetaData( TABS_PANEL_KEY, tabsInfo );
-    }
-
-    @SuppressWarnings( "unchecked" )
-    public TabsPanel( String activeTab )
-    {
-        super( "tabsPanel" );
-
-        Map<Class, String[]> tabs = getApplication().getMetaData( TABS_PANEL_KEY );
-        if( tabs == null || tabs.isEmpty() )
-        {
-            throw new RuntimeException( "Please register one or more tabs." );
-        }
-
-        RepeatingView tabsView = new RepeatingView( "tabsView" );
-
-        // Loop "mounted" tabs
-        for( Map.Entry<Class, String[]> tab : tabs.entrySet() )
-        {
-            Class pageClass = tab.getKey();
-            String tabReference = tab.getValue()[ 0 ];
-            String tabLabel = tab.getValue()[ 1 ];
-
-            WebMarkupContainer tabView = new WebMarkupContainer( tabsView.newChildId() );
-            if( tabReference.equals( activeTab ) )
-            {
-                tabView.add( new AttributeModifier( "id", "current" ) );
-            }
-
-            BookmarkablePageLink link = new BookmarkablePageLink( "link", pageClass );  // unchecked
-
-            Label label = new Label( "label", tabLabel );
-
-            tabsView.add( tabView.add( link.add( label ) ) );
-        }
-        add( tabsView );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/log4j.properties b/samples/dci-cargo/dcisample_b/src/main/resources/log4j.properties
deleted file mode 100644
index f212fe5..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/log4j.properties
+++ /dev/null
@@ -1,29 +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.
-
-log4j.appender.Stdout=org.apache.log4j.ConsoleAppender
-log4j.appender.Stdout.layout=org.apache.log4j.PatternLayout
-log4j.appender.Stdout.layout.conversionPattern=%-5p - %-36.36c{1} - %m\n
-
-log4j.rootLogger=INFO,Stdout
-#log4j.rootLogger=DEBUG,Stdout
-
-#log4j.logger.org.apache.wicket=DEBUG
-#log4j.logger.org.apache.wicket.protocol.http.HttpSessionStore=DEBUG
-#log4j.logger.org.apache.wicket.version=DEBUG
-#log4j.logger.org.apache.wicket.RequestCycle=DEBUG
-#log4j.logger.org.apache.wicket.util.resource=DEBUG
-
-#log4j.logger.org.qi4j.index.rdf.query.internal.RdfQueryParserImpl=DEBUG, Stdout
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/BasePage.html b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/BasePage.html
deleted file mode 100644
index 010b6f8..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/BasePage.html
+++ /dev/null
@@ -1,108 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<head>
-    <title>DCI sample (version B)</title>
-    <link href="css/style.css" rel="stylesheet" type="text/css"/>
-</head>
-<body>
-
-<div class="left">
-    <div class="headline"><a href="/">DCI sample</a></div>
-    <div id="toggle">
-        <a href="#" class="closed" wicket:id="toggleLinks">Qi4j/Wicket port of the DDD sample application to the DCI
-            paradigm.</a>
-    </div>
-
-    <div id="links" wicket:id="links"></div>
-    <wicket:fragment wicket:id="linksFragment">
-        <br>
-        <table>
-            <thead>
-            <tr>
-                <td>DCI</td>
-                <td>DDD</td>
-                <td>Qi4j</td>
-                <td>Wicket</td>
-                <td>Marc Grue blog</td>
-                <td>Books</td>
-            </tr>
-            </thead>
-            <tbody>
-            <tr>
-                <td valign="top">
-                    <a href="http://groups.google.com/group/object-composition/topics?hl=en"
-                       target="_blank">Forum</a><br>
-                    <a href="https://github.com/DCI/dci-sample" target="_blank">Github</a><br>
-                    <a href="http://en.wikipedia.org/wiki/Data,_Context,_and_Interaction" target="_blank">Wiki</a><br>
-                    <a href="http://folk.uio.no/trygver/2010/DCIExecutionModel.pdf" target="_blank">Execution Model</a>
-                </td>
-                <td valign="top">
-                    <a href="http://dddsample.sourceforge.net/" target="_blank">Sample</a><br>
-                    <a href="http://tech.groups.yahoo.com/group/domaindrivendesign/" target="_blank">Forum</a>
-                </td>
-                <td valign="top">
-                    <a href="https://zest.apache.org/" target="_blank">Website</a><br>
-                    <a href="https://zest.apache.org/community/get_help.html" target="_blank">Forum</a><br>
-                    <a href="https://zest.apache.org/download.html" target="_blank">Download</a><br>
-                    <a href="https://zest.apache.org/java/latest/howto-depend-on-zest.html" target="_blank">Maven</a><br>
-                    <a href="https://github.com/apache/zest-java" target="_blank">Github</a>
-                </td>
-                <td valign="top">
-                    <a href="http://wicket.apache.org/" target="_blank">Website</a><br>
-                    <a href="http://apache-wicket.1842946.n4.nabble.com/Users-forum-f1842947.html"
-                       target="_blank">Forum</a><br>
-                    <a href="http://wicketstuff.org/wicket/index.html" target="_blank">Examples</a><br>
-                    <a href="https://cwiki.apache.org/WICKET/" target="_blank">Wiki</a><br>
-                    <a href="http://apache.dataphone.se/wicket/1.5.1/" target="_blank">Download</a>
-                </td>
-                <td valign="top">
-                    <a href="http://marcgrue.com/" target="_blank">Overview</a><br>
-                    <a href="http://marcgrue.com/dci/dci-sample/what-the-system-is" target="_blank">What-the-system-is</a><br>
-                    <a href="http://marcgrue.com/dci/process-thinking" target="_blank">Process Thinking</a><br>
-                </td>
-                <td valign="top">
-                    <a href="http://www.amazon.co.uk/gp/product/0470684208/ref=as_li_ss_tl?ie=UTF8&tag=doubtrol-21&linkCode=as2&camp=1634&creative=19450&creativeASIN=0470684208"
-                       target="_blank">Lean Architecture</a><img
-                        src="http://www.assoc-amazon.co.uk/e/ir?t=&l=as2&o=2&a=0470684208" width="1" height="1"
-                        border="0" alt="" style="border:none !important; margin:0px !important;"/><br>
-                    <a href="http://www.amazon.co.uk/gp/product/0201702258/ref=as_li_ss_tl?ie=UTF8&tag=doubtrol-21&linkCode=as2&camp=1634&creative=19450&creativeASIN=0201702258"
-                       target="_blank">Writing Effective Use Cases</a><img
-                        src="http://www.assoc-amazon.co.uk/e/ir?t=doubtrol-21&l=as2&o=2&a=0201702258" width="1"
-                        height="1" border="0" alt="" style="border:none !important; margin:0px !important;"/>
-                </td>
-            </tr>
-            </tbody>
-        </table>
-    </wicket:fragment>
-</div>
-
-<div class="right">
-    <b>Java-Qi4j-Wicket<br>
-        Version <span wicket:id="version">[X.Y.Z]</span></b><br>
-    Created 2011-10-04<br>
-    Modified 2011-10-04<br>
-    by Marc Grue
-</div>
-
-<div wicket:id="tabsPanel">[tabs]</div>
-
-<!--Inherited pages go here-->
-<wicket:child/>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/BookNewCargoPage.html b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/BookNewCargoPage.html
deleted file mode 100644
index 80f9dc3..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/BookNewCargoPage.html
+++ /dev/null
@@ -1,71 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:extend>
-    <div class="headerMenu">
-        Book new cargo
-        <wicket:link><a href="CargoListPage.html">List of Cargos</a></wicket:link>
-    </div>
-
-    <form wicket:id="form">
-        <div wicket:id="feedback"></div>
-        <table>
-            <tbody>
-            <tr>
-                <td>Origin</td>
-                <td>
-                    <select wicket:id="originSelector">
-                        <option>Markup1</option>
-                        <option>Markup2</option>
-                    </select>
-                </td>
-                <td>
-                    <div wicket:id="originFeedback">&nbsp;</div>
-                </td>
-            </tr>
-            <tr>
-                <td>Destination</td>
-                <td>
-                    <select wicket:id="destinationSelector"></select>
-                </td>
-                <td>
-                    <div wicket:id="destinationFeedback">&nbsp;</div>
-                </td>
-            </tr>
-            <tr>
-                <td>Arrival deadline</td>
-                <td>
-                    <input type="text" wicket:id="deadline"/>
-                </td>
-                <td>
-                    <div wicket:id="deadlineFeedback">&nbsp;</div>
-                </td>
-            </tr>
-            </tbody>
-            <tfoot>
-            <tr>
-                <td></td>
-                <td>
-                    <input type="submit" value="Book" wicket:id="book"/>
-                </td>
-            </tr>
-            </tfoot>
-        </table>
-    </form>
-
-</wicket:extend>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/BookingBasePage.html b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/BookingBasePage.html
deleted file mode 100644
index 0af9860..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/BookingBasePage.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:extend>
-    <div id="box">
-        <wicket:child/>
-    </div>
-</wicket:extend>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/CargoDetailsPage.html b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/CargoDetailsPage.html
deleted file mode 100644
index c78f1c5..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/CargoDetailsPage.html
+++ /dev/null
@@ -1,110 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:extend>
-
-    <div wicket:id="prevNext"></div>
-    <div class="headerMenu">
-        Details for cargo <span wicket:id="trackingId">[trackingId]</span>
-        <wicket:link>
-            <a href="CargoListPage.html">List of Cargos</a>
-            <a href="BookNewCargoPage.html">Book new cargo</a>
-        </wicket:link>
-    </div>
-
-    <table class="styleLeftColumn">
-
-        <wicket:container wicket:id="origin"></wicket:container>
-        <wicket:fragment wicket:id="originFragment">
-            <tr>
-                <td>Origin</td>
-                <td wicket:id="cargoOrigin"></td>
-            </tr>
-        </wicket:fragment>
-        <wicket:fragment wicket:id="re-routed-originFragment">
-            <tr>
-                <td>Origin (Cargo)</td>
-                <td wicket:id="cargoOrigin"></td>
-            </tr>
-            <tr>
-                <td>Origin (Route Spec)</td>
-                <td wicket:id="routeOrigin"></td>
-            </tr>
-        </wicket:fragment>
-
-        <tr>
-            <td>Destination</td>
-            <td wicket:id="destination"></td>
-            <td wicket:id="changeDestination"></td>
-        </tr>
-        <tr>
-            <td>Earliest departure</td>
-            <td wicket:id="departure"></td>
-        </tr>
-        <tr>
-            <td>Arrival deadline</td>
-            <td wicket:id="deadline"></td>
-        </tr>
-        <tr>
-            <td>Routing status</td>
-            <td wicket:id="routingStatus"></td>
-            <td wicket:id="routingAction"></td>
-        </tr>
-
-        <wicket:container wicket:id="delivery"></wicket:container>
-        <wicket:fragment wicket:id="deliveryFragment">
-            <tr>
-                <td>Transport status</td>
-                <td wicket:id="transportStatus"></td>
-            </tr>
-            <tr>
-                <td valign="top">Delivery status</td>
-                <td wicket:id="deliveryStatus"></td>
-            </tr>
-        </wicket:fragment>
-
-    </table>
-
-    <wicket:container wicket:id="itinerary"></wicket:container>
-    <wicket:fragment wicket:id="itineraryFragment">
-        <h4>Itinerary</h4>
-        <table>
-            <thead>
-            <tr>
-                <td>Voyage</td>
-                <td colspan="2">Load</td>
-                <td colspan="2">Unload</td>
-            </tr>
-            </thead>
-            <tbody>
-            <tr wicket:id="legs">
-                <td wicket:id="voyage"></td>
-                <td wicket:id="loadLocation"></td>
-                <td wicket:id="loadTime"></td>
-                <td wicket:id="unloadLocation"></td>
-                <td wicket:id="unloadTime"></td>
-            </tr>
-            </tbody>
-        </table>
-    </wicket:fragment>
-
-    <div wicket:id="handlingHistoryPanel"></div>
-
-    <div wicket:id="nextHandlingEventPanel"></div>
-
-</wicket:extend>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/CargoListPage.html b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/CargoListPage.html
deleted file mode 100644
index 850773a..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/CargoListPage.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:extend>
-    <div class="headerMenu">
-        List of Cargos
-        <wicket:link><a href="BookNewCargoPage.html">Book new cargo</a></wicket:link>
-    </div>
-
-    <table>
-        <thead>
-        <tr>
-            <td>Tracking Id</td>
-            <td>Origin</td>
-            <td>Destination</td>
-            <td>Arrival deadline</td>
-            <td>Routing status</td>
-            <td>Transport status</td>
-            <td>Delivery status</td>
-        </tr>
-        </thead>
-        <tbody>
-        <tr wicket:id="list">
-            <td wicket:id="trackingId"></td>
-            <td wicket:id="origin"></td>
-            <td align="center" wicket:id="destination"></td>
-            <td align="center" wicket:id="deadline"></td>
-            <td wicket:id="routingStatus"></td>
-            <td wicket:id="transportStatus"></td>
-            <td wicket:id="deliveryStatus"></td>
-        </tr>
-        </tbody>
-    </table>
-</wicket:extend>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/ChangeDestinationPage.html b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/ChangeDestinationPage.html
deleted file mode 100644
index 892722a..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/ChangeDestinationPage.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:extend>
-
-    <div class="headerMenu">
-        Change destination for cargo <span wicket:id="trackingId">[trackingId]</span>
-        <wicket:link>
-            <a href="CargoListPage.html">List of Cargos</a>
-            <a href="BookNewCargoPage.html">Book new cargo</a>
-        </wicket:link>
-    </div>
-
-    <form wicket:id="form">
-        <div wicket:id="usecaseFeedback"></div>
-        <table>
-            <tbody>
-            <tr>
-                <td>Origin</td>
-                <td wicket:id="origin"></td>
-            </tr>
-            <tr>
-                <td>Old destination</td>
-                <td wicket:id="destination"></td>
-            </tr>
-            <tr>
-                <td>New destination</td>
-                <td>
-                    <select wicket:id="destinationSelector"></select>
-                </td>
-                <td wicket:id="destinationFeedback"></td>
-            </tr>
-            </tbody>
-            <tfoot>
-            <tr>
-                <td></td>
-                <td>
-                    <input type="submit" value="Change destination" wicket:id="submit"/>
-                </td>
-            </tr>
-            </tfoot>
-        </table>
-    </form>
-
-</wicket:extend>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/ReRouteCargoPage.html b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/ReRouteCargoPage.html
deleted file mode 100644
index 7d1a4b2..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/ReRouteCargoPage.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:extend>
-
-    <div class="headerMenu">
-        Re-route cargo <span wicket:id="trackingId">[trackingId]</span>
-        <wicket:link>
-            <a href="CargoListPage.html">List of Cargos</a>
-            <a href="BookNewCargoPage.html">Book new cargo</a>
-        </wicket:link>
-    </div>
-
-    <span wicket:id="feedback"></span>
-
-    <span wicket:id="routes">
-        <span wicket:id="route"></span><br/>
-    </span>
-
-</wicket:extend>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/RouteCargoPage.html b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/RouteCargoPage.html
deleted file mode 100644
index 069004e..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/RouteCargoPage.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:extend>
-
-    <div class="headerMenu">
-        Assign cargo <span wicket:id="trackingId">[trackingId]</span> to a route
-        <wicket:link>
-            <a href="CargoListPage.html">List of Cargos</a>
-            <a href="BookNewCargoPage.html">Book new cargo</a>
-        </wicket:link>
-    </div>
-
-    <span wicket:id="feedback"></span>
-
-    <span wicket:id="routes">
-        <span wicket:id="route"></span><br/>
-    </span>
-
-</wicket:extend>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/RoutePanel.html b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/RoutePanel.html
deleted file mode 100644
index f7b8d82..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/booking/RoutePanel.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:panel>
-    <h4 wicket:id="routeHeader"></h4>
-    <span wicket:id="routeFeedback"></span>
-
-    <table>
-        <thead>
-        <tr>
-            <td>Voyage</td>
-            <td colspan="2">From</td>
-            <td colspan="2">To</td>
-        </tr>
-        </thead>
-        <tbody>
-        <tr wicket:id="legs">
-            <td wicket:id="voyage"></td>
-            <td wicket:id="loadLocation"></td>
-            <td wicket:id="loadTime"></td>
-            <td wicket:id="unloadLocation"></td>
-            <td wicket:id="unloadTime"></td>
-        </tr>
-        </tbody>
-    </table>
-    <form wicket:id="form">
-        <input type="submit" value="Assign cargo to this route" wicket:id="assign"/>
-    </form>
-</wicket:panel>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/handling/IncidentLoggingApplicationMockupPage.html b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/handling/IncidentLoggingApplicationMockupPage.html
deleted file mode 100644
index 3827ced..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/handling/IncidentLoggingApplicationMockupPage.html
+++ /dev/null
@@ -1,91 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:extend>
-    <div id="box">
-
-        <div class="headerMenu" style="color:purple">Incident Logging Application mockup</div>
-        <h3 style="color:purple">Report Handling Event</h3>
-
-        <form wicket:id="form">
-            <table>
-                <tbody>
-                <tr>
-                    <td>Completion</td>
-                    <td nowrap><input type="text" wicket:id="completion"/></td>
-                    <!--<td rowspan="7" style="padding-left:30px">-->
-                          <!--<span style="font-style:italic;font-family: 'Lucida Sans', 'Helvetica'"> External cargo handling authorities (ports, shippers,-->
-                              <!--customs etc) continuously send handling event messages through incident logging-->
-                              <!--applications as they handle cargos in order to inform shippers (like us) of what-->
-                              <!--has happened to a certain cargo.<br>-->
-                              <!--<br>-->
-                              <!--It's outside the scope of our incident logging application mockup to validate the-->
-                              <!--data since our perspective is the booking application receiving raw data that we-->
-                              <!--have no control over.<br>-->
-                              <!--<br>-->
-                              <!--It's first when the data hit our booking application (below) that we can validate-->
-                              <!--and process it...-->
-                        <!--</span>-->
-                    <!--</td>-->
-                </tr>
-                <tr>
-                    <td nowrap>Cargo Tracking Id</td>
-                    <td nowrap>
-                        <input type="text" wicket:id="trackingIdInput"/> <select
-                            wicket:id="trackingIdSelector"></select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>Event type</td>
-                    <td nowrap>
-                        <input type="text" wicket:id="eventTypeInput"/> <select wicket:id="eventTypeSelector"></select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>Voyage</td>
-                    <td nowrap>
-                        <input type="text" wicket:id="voyageInput"/> <select wicket:id="voyageSelector"></select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>Location</td>
-                    <td nowrap>
-                        <input type="text" wicket:id="locationInput"/> <select wicket:id="locationSelector"></select>
-                    </td>
-                </tr>
-                <tr>
-                    <td></td>
-                    <td>
-                        <input type="submit" value="Send" wicket:id="register"/>
-                    </td>
-                </tr>
-                </tbody>
-            </table>
-
-            <hr>
-
-            <div class="headerMenu">Booking Application</div>
-            <h3>Process Handling Event</h3>
-            <span style="font-style:italic">Result of our processing:
-            </span>
-
-            <div wicket:id="feedback"></div>
-        </form>
-
-    </div>
-</wicket:extend>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/handling/IncidentLoggingApplicationMockupPage.properties b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/handling/IncidentLoggingApplicationMockupPage.properties
deleted file mode 100644
index 8c05b4d..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/handling/IncidentLoggingApplicationMockupPage.properties
+++ /dev/null
@@ -1,21 +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.
-
-handlingEvent.UNKNOWN=ERROR: *** UNKNOWN EVENT TYPE ***
-handlingEvent.RECEIVE=Received in ${location}.
-handlingEvent.LOAD=Loaded onto voyage ${voyage} in port ${location}.
-handlingEvent.UNLOAD=Unloaded from voyage ${voyage} in port ${location}.
-handlingEvent.CLAIM=Claimed in port ${location} by cargo owner.
-handlingEvent.CUSTOMS=In customs.
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/HandlingHistoryPanel.html b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/HandlingHistoryPanel.html
deleted file mode 100644
index f89e3ae..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/HandlingHistoryPanel.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:panel>
-    <h4>Handling history</h4>
-    <table>
-        <tbody>
-        <tr wicket:id="handlingEvents">
-            <td><img src="/graphics/icon/" wicket:id="onTrackIcon"/></td>
-            <td wicket:id="completion"></td>
-            <td wicket:id="event"></td>
-        </tr>
-        </tbody>
-    </table>
-</wicket:panel>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/HandlingHistoryPanel.properties b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/HandlingHistoryPanel.properties
deleted file mode 100644
index 089ebb1..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/HandlingHistoryPanel.properties
+++ /dev/null
@@ -1,21 +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.
-
-handlingEvent.UNKNOWN=ERROR: *** UNKNOWN EVENT TYPE ***
-handlingEvent.RECEIVE=Received in ${location}
-handlingEvent.LOAD=Loaded onto voyage ${voyage} in ${location}
-handlingEvent.UNLOAD=Unloaded from voyage ${voyage} in ${location}
-handlingEvent.CLAIM=Claimed in ${location} by cargo owner
-handlingEvent.CUSTOMS=In customs
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/NextHandlingEventPanel.html b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/NextHandlingEventPanel.html
deleted file mode 100644
index e37b8ce..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/NextHandlingEventPanel.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:panel>
-    <p wicket:id="text" style="font-style:italic;font-weight: bold;"></p>
-</wicket:panel>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/NextHandlingEventPanel.properties b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/NextHandlingEventPanel.properties
deleted file mode 100644
index 506cd20..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/NextHandlingEventPanel.properties
+++ /dev/null
@@ -1,23 +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.
-
-nextEvent.UNKNOWN=Next expected activity: Unknown...
-nextEvent.ROUTE=Next expected activity: Routing of cargo
-nextEvent.RECEIVE=Next expected activity: Receipt of cargo in ${location}
-nextEvent.LOAD=Next expected activity: Load onto voyage ${voyage} in ${location} ${time}
-nextEvent.UNLOAD=Next expected activity: Unload off voyage ${voyage} in ${location} ${time}
-nextEvent.CLAIM=Next expected activity: Claim by cargo owner in destination port ${location} ${time}
-nextEvent.CUSTOMS=ERROR: CUSTOMS IS NOT AN EXPECTED EVENT
-nextEvent.END_OF_CYCLE=Cargo has successfully been claimed in ${location} by cargo owner
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/TrackCargoPage.html b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/TrackCargoPage.html
deleted file mode 100644
index 26de6b8..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/TrackCargoPage.html
+++ /dev/null
@@ -1,50 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:extend>
-    <div id="box">
-
-        <div class="headerMenu">Tracking</div>
-
-        <form wicket:id="form">
-            Tracking number
-            <input type="text" wicket:id="trackingId"/>
-            <input type="submit" value="Track" wicket:id="track"/>
-            &nbsp;&nbsp;&nbsp;&nbsp;Pre-selection: <select wicket:id="selectedTrackingIdSelector"></select>
-
-            <div wicket:id="feedback"></div>
-
-            <div wicket:id="status"></div>
-            <wicket:fragment wicket:id="statusFragment">
-                <br/>
-                <span wicket:id="transportStatus" style="font-weight:bold">[Text]</span>
-
-                <p wicket:id="eta">eta </p>
-
-                <p wicket:id="isMisdirected" class="notifyError"><img src="../../graphics/icon/error.png"/>&nbsp;
-                    Cargo is misdirected. </p>
-
-                <p wicket:id="isClaimed" class="notifySuccess"><img src="../../graphics/icon/tick.png"/>&nbsp;
-                    Cargo succesfully delivered. </p>
-
-                <div wicket:id="handlingHistoryPanel"></div>
-            </wicket:fragment>
-        </form>
-
-    </div>
-</wicket:extend>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/TrackCargoPage.properties b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/TrackCargoPage.properties
deleted file mode 100644
index 3e99229..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/communication/web/tracking/TrackCargoPage.properties
+++ /dev/null
@@ -1,24 +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.
-
-cargoDropDown.null=Track known cargo
-
-eta=Estimated time of arrival in {0}: {1}
-
-transportStatus.NOT_RECEIVED=Cargo ${trackingId} has not been received yet
-transportStatus.IN_PORT=Cargo ${trackingId} is now in ${location}
-transportStatus.ONBOARD_CARRIER=Cargo ${trackingId} is now onboard voyage ${voyage}
-transportStatus.CLAIMED=Cargo ${trackingId} is now claimed by cargo owner in ${location}
-transportStatus.UNKNOWN=Cargo ${trackingId} has an unknown transport status
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/_ShipCargo.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/_ShipCargo.txt
deleted file mode 100644
index ffd8a3d..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/_ShipCargo.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-
-USE CASE	    Ship Cargo [summary]
-===========================================================================
-A Cargo Owner asks a shipping company to ship a cargo.
-
-This is the overall view of our shipping domain.
-
-
-Primary actor.. Cargo Owner
-Scope.......... Shipping company
-Preconditions.. None
-Trigger........ Cargo Owner <books new cargo> shipment.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Cargo Owner <books new cargo> shipment
-2. Cargo Owner <routes cargo>
-3. Shipper receives cargo at origin location
-4. Shipper sends cargo
-5. Cargo Owner can <change destination of cargo>
-6. Cargo Owner can <re-route cargo>
-7. Cargo Owner can track cargo
-8. Shipper delivers cargo at destination
-9. Cargo Owner claims cargo
-
-
-Deviations
----------------------------------------------------------------------------
-3-8a. Cargo is in an unexpected location (misdirected):
-    1. Shipper requests Cargo Owner to <re-route cargo>.
-
-5a. Cargo Owner changes destination:
-    1. Shipper requests Cargo Owner to <re-route cargo>.
-
-
----------------------------------------------------------------------------
-Success guarantees:
-    Shipper delivers cargo according to route specification.
-
-Minimal guarantees:
-    None (?).
-
-Stakeholders/Interests:
-    Cargo Owner - wants cargo shipped safely, fast and cheap.
-
-    Shipper:
-    Handling dep - wants overbooking of vessels to maximize profit.
-    Sales dep - wants Cargo Owner satisfaction.
-    Financial dep - wants payment settlement with Cargo Owner.
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/BookNewCargo.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/BookNewCargo.txt
deleted file mode 100644
index 308defd..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/BookNewCargo.txt
+++ /dev/null
@@ -1,51 +0,0 @@
-
-USE CASE	    Book New Cargo [user-goal]
-===========================================================================
-Cargo Owner wants to book a cargo shipment from A to B with an arrival deadline.
-
-
-Primary actor.. Cargo Owner (or Booking Clerk on behalf of Cargo Owner)
-Scope.......... Booking System in shipping application
-Preconditions.. None
-Trigger........ Cargo Owner wants to book a new cargo shipment.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Cargo Owner provides origin/destination, arrival deadline and optionally a tracking id.
-2. Booking System creates route specification.
-3. Booking System derives initial delivery data.
-4. Booking System creates cargo.
-5. Booking System requests Cargo Owner to <route cargo>.
-
-
-Deviations
----------------------------------------------------------------------------
-2a. Origin location equals destination location:
-    1. Exit.
-
-2b. Arrival deadline is in the past or Today:
-    1. Exit.
-
-4a. Supplied tracking id doesn't match pattern:
-    1. Exit.
-
-4b. Supplied tracking id is not unique:
-    1. Exit.
-
-
----------------------------------------------------------------------------
-Success guarantees:
-    Booking is saved and awaits routing by Cargo Owner
-
-Minimal guarantees:
-    Data entered is logged.
-
-Stakeholders/Interests:
-    Cargo Owner - wants successful booking of shipment.
-
-    Shipper:
-    Handling dep - wants correct data and overbooking of vessels to maximize profit.
-    Sales dep - wants Cargo Owner satisfaction.
-    Financial dep - wants payment settlement with Cargo Owner.
-
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/ChangeDestinationOfCargo.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/ChangeDestinationOfCargo.txt
deleted file mode 100644
index 39680bd..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/ChangeDestinationOfCargo.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-
-USE CASE	    Change Destination of Cargo [user-goal]
-===========================================================================
-Cargo Owner wants to change destination of cargo.
-
-
-Primary actor.. Cargo Owner
-Scope.......... Booking System in shipping application
-Preconditions.. Cargo is not claimed yet.
-Trigger........ Cargo Owner requests to change destination of cargo.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Booking System presents possible new destinations of cargo to cargo owner.
-2. Cargo Owner chooses a new destination.
-3. Booking System asks Cargo Inspector to <register new destination> for cargo.
-4. Booking System requests Cargo Owner to <re-route cargo>.
-
-
-Deviations
----------------------------------------------------------------------------
-1a. Cargo has been claimed:
-    1. Failure (no reason to change destination of a claimed cargo).
-
-3a. Shipping application can't change destination:
-    1. Failure.
-
-
----------------------------------------------------------------------------
-Success guarantees:
-    Cargo has changed destination and Cargo Owner is notified to re-route cargo.
-
-Minimal guarantees:
-    Cargo remains on track (?)
-
-Stakeholders/Interests:
-    Cargo Owner - wants cargo delivered to the new destination.
-    Shipping company - wants fast re-routing of cargo (to avoid delaying the cargo).
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/ReRouteCargo.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/ReRouteCargo.txt
deleted file mode 100644
index d9b647d..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/ReRouteCargo.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-
-USE CASE	    Re-route Cargo [user-goal]
-===========================================================================
-Cargo Owner wants to assign cargo to another route.
-
-If a cargo was handled in an unexpected location (is misdirected), the booking
-system will request the Cargo Owner to re-route the cargo to get it back on track.
-
-The Cargo Owner can also anytime re-route a cargo that is on track.
-
-
-Primary actor.. Cargo Owner (can be a Booking clerk on behalf of Cargo Owner)
-Scope.......... Booking System in shipping application
-Preconditions.. Cargo has a route specification.
-Trigger........ Cargo Owner requests to re-route cargo.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Cargo Owner requests to re-route cargo.
-2. Booking System asks Delivery Inspector to <derive updated route specification> for cargo.
-3. Booking System asks Path Finder for route candidates matching route specification.
-4. Booking System presents route candidates to Cargo Owner.
-5. Cargo Owner chooses preferred route.
-6. Booking System <assigns cargo to route>.
-
-
-Deviations
----------------------------------------------------------------------------
-3a. No routes satisfy new route specification:
-    1. Failure.
-
-
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/RouteCargo.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/RouteCargo.txt
deleted file mode 100644
index 6254403..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/RouteCargo.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-
-USE CASE	    Route Cargo [user-goal]
-===========================================================================
-Cargo Owner wants to choose a route for a cargo.
-
-
-Primary actor.. Cargo Owner (can be a Booking clerk on behalf of Cargo Owner)
-Scope.......... Booking System in shipping application
-Preconditions.. Cargo is not routed.
-Trigger........ Cargo Owner requests to route cargo.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Cargo Owner requests to route cargo.
-2. Booking System asks Path Finder for route candidates matching route specification.
-3. Booking System presents route candidates to Cargo Owner.
-4. Cargo Owner chooses preferred route.
-5. Booking System <assigns cargo to new route>.
-
-
-Deviations
----------------------------------------------------------------------------
-2a. No routes satisfy route specification:
-    1. Failure.
-
-
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/routing/AssignCargoToRoute.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/routing/AssignCargoToRoute.txt
deleted file mode 100644
index 59b3a72..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/routing/AssignCargoToRoute.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-
-USE CASE	    Assign Cargo to Route [subfunction]
-===========================================================================
-Cargo Inspector assigns cargo to a route. A route is described by an itinerary.
-
-
-Primary actor.. Cargo Inspector
-Scope.......... Shipping application
-Preconditions.. Cargo has not been claimed yet.
-Trigger........ Cargo Inspector receives new itinerary to be assigned to cargo.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Cargo Inspector <derives updated route specification>.
-2. Cargo Inspector verifies that route satisfies route specification.
-3. Cargo Inspector assigns cargo to route.
-4. Cargo Inspector assigns route specification to cargo.
-5. Cargo Inspector determines next expected handling event.
-6. Cargo Inspector updates cargo delivery status.
-
-
-Deviations
----------------------------------------------------------------------------
-*1. Cargo has been claimed:
-    1. Failure. Can't re-route claimed cargo.
-
-1a. Route doesn't satisfy route specification:
-    1. Failure.
-
-3a. Route doesn't satisfy new route specification:
-    1. Failure.
-
-5a. Cargo has not been handled (initial routing):
-    1. Cargo Inspector expects receipt in route origin.
-
-5b. Cargo is on board carrier (re-routing):
-    1. Cargo Inspector expects unload in arrival location of current carrier movement.
-
-5c. Cargo is in port (re-routing):
-    1. Cargo Inspector expects load in route origin.
-
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/routing/RegisterNewDestination.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/routing/RegisterNewDestination.txt
deleted file mode 100644
index 6c1e7aa..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/routing/RegisterNewDestination.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-
-USE CASE	    Register New Destination  [subfunction]
-===========================================================================
-A Cargo Inspector registers a new destination for a cargo.
-
-
-Primary actor.. Cargo Inspector
-Scope.......... Booking system
-Preconditions.. Cargo has a route specification.
-Trigger........ Cargo Inspector receives request to register new destination of cargo.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Cargo Inspector verifies new destination.
-2. Cargo Inspector <derives updated route specification>.
-3. Cargo Inspector assigns new route specification to cargo.
-4. Cargo Inspector asks Delivery Inspector to <inspect cargo delivery status>.
-
-
-Deviations
----------------------------------------------------------------------------
-x1. Cargo has been claimed:
-    1. Failure (can't change destination after cargo has been handed over to cargo owner).
-
-1a. Cargo Inspector doesn't recognize new location:
-    1. Failure.
-
-1b. New destination is same as old destination:
-    1. Exit.
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/specification/DeriveUpdatedRouteSpecification.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/specification/DeriveUpdatedRouteSpecification.txt
deleted file mode 100644
index b825367..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/booking/specification/DeriveUpdatedRouteSpecification.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-
-USE CASE	    Derive Updated Route Specification [subfunction]
-===========================================================================
-A Cargo Inspector is asked for an updated route specification for a cargo
-according to the current delivery status.
-
-
-Primary actor.. Cargo Inspector
-Scope.......... Booking System
-Preconditions.. Cargo is routed.
-Trigger........ Booking System wants an updated route specification for a cargo.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Cargo Inspector collects destination and arrival deadline from old route specification.
-2. Cargo Inspector sets new origin to current location and new earliest departure date to last completion time.
-3. Cargo Inspector builds and returns new route specification.
-
-
-Deviations
----------------------------------------------------------------------------
-1a. Cargo is going to a new destination:
-    1. Cargo Inspector uses new given destination.
-
-2a. Cargo is not received yet:
-    1. Cargo Inspector sets new origin to cargo origin.
-    2. Cargo Inspector leaves earliest departure time unchanged.
-
-2b. Cargo is on board carrier:
-    1. Cargo Inspector sets new origin to arrival location of current carrier movement.
-    2. Cargo Inspector sets new earliest departure date to arrival time of current carrier movement.
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/_ProcessHandlingEvent.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/_ProcessHandlingEvent.txt
deleted file mode 100644
index 5935846..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/_ProcessHandlingEvent.txt
+++ /dev/null
@@ -1,67 +0,0 @@
-
-USE CASE	    Process Handling Event [summary - Nuts and Bolts use case]
-===========================================================================
-System automatically receives and validates incoming handling event data
-for a cargo. The cargo is then inspected to see if it's still on track and
-to initiate actions if necessary.
-
-Certain conditions can cause relevant parties to be notified.
-
-
-Primary actor.. Handling Manager
-Scope.......... Handling System in shipping application
-Preconditions.. None
-Trigger........ Delivery Inspector receives handling event data from handling authority.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Handling Manager asks Data Parser to <parse handling event data>.
-2. Handling Manager asks Event Registrar to <register handling event>.
-3. Handling Manager asks Delivery Inspector to <inspect cargo delivery status>.
-
-
-Deviations
----------------------------------------------------------------------------
-1a. Handling event data is invalid:
-    1. Handling Manager notifies handling authority of invalid data and exits.
-
-2a. Handling event data is not recognized in Delivery Inspector:
-    1. Handling Manager notifies handling authority of unrecognized data and exits.
-
-3a. Cargo has arrived:
-    1. Handling Manager requests cargo owner to claim cargo.
-
-3b. Cargo is misdirected or misrouted:
-    1. Handling Manager requests cargo owner to re-route cargo.
-
-
----------------------------------------------------------------------------
-Success guarantees:
-    Handling event is registered.
-    Cargo delivery status is inspected.
-    Relevant notifications are sent.
-
-Minimal guarantees:
-    Delivery Inspector data is in a valid state.
-    Registration attempt data is logged.
-    Relevant notifications are sent.
-
-Stakeholders/Interests:
-    Cargo Owner wants
-        - access to accurate last-minute tracking information
-        - notification of misdirection or arrival of cargo
-    Shipper wants
-        - cargo handled efficiently (financial department)
-        - data consistency (IT department)
-        - handling process traceability (legal/support department)
-    Handling authority wants
-        - notification of rejected handling registration attempts.
-
-
-Comments
----------------------------------------------------------------------------
-Handling events are supposed to come in automatically from various incident
-logging applications. We have no users processing handled cargos and therefore
-no user-goal level use cases either! We only have subfunction use cases like
-"RegisterHandlingEvent" describing a technical process with no human involvement.
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/InspectCargoDeliveryStatus.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/InspectCargoDeliveryStatus.txt
deleted file mode 100644
index 23c9533..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/InspectCargoDeliveryStatus.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-
-USE CASE        Inspect Cargo Delivery Status [subfunction]
-===========================================================================
-A Delivery Inspector inspects and updates the delivery status of a cargo.
-
-If the cargo has been handled, the handling event data is used to derive the
-delivery status.
-
-(This can hardly be called a use case...)
-
-
-Primary actor.. Delivery Inspector
-Scope.......... Handling Monitoring System in shipping application
-Preconditions.. Cargo has a route specification.
-Trigger........ Delivery Inspector receives request to inspect the cargo delivery status.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Delivery Inspector determines the handling event type.
-2. Delivery Inspector delegates inspection according to handling event type.
-
-
-Deviations
----------------------------------------------------------------------------
-1a. Cargo hasn't been handled yet:
-    1. Delivery Inspector <inspects unhandled cargo>.
-
-2a. Cargo was received:
-    1. Delivery Inspector <inspects received cargo>.
-
-2b. Cargo was loaded:
-    1. Delivery Inspector <inspects loaded cargo>.
-
-2c. Cargo was unloaded in final destination:
-    1. Delivery Inspector <inspects arrived cargo>.
-
-2d. Cargo was unloaded:
-    1. Delivery Inspector <inspects unloaded cargo>.
-
-2e. Cargo is being handled by customs authorities:
-    1. Delivery Inspector <inspects cargo in customs>.
-
-2f. Cargo was claimed by cargo owner:
-    1. Delivery Inspector <inspects claimed cargo>.
-
-
----------------------------------------------------------------------------
-Success guarantees:
-    All information we know about a Cargo delivery is derived.
-
-Minimal guarantees:
-    Persisted data is consistent (?)...
-
-Stakeholders/Interests:
-    Cargo owner - wants reliable tracking information
-    Shipping company - wants precise handling monitoring to prevent further (expensive) misdirection
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectArrivedCargo.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectArrivedCargo.txt
deleted file mode 100644
index 245cc8d..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectArrivedCargo.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-
-USE CASE        Inspect Arrived Cargo [subfunction]
-===========================================================================
-A Delivery Inspector inspects and updates the delivery status of a cargo that
-has been unloaded at its final destination according to the route specification.
-
-Since the route specification is the single authority to determine the final
-destination of the cargo - regardless of any itinerary - we should be able to
-only save the routing/misdirection status for internal reference without
-notifying the cargo owner. Could be interesting to hear what a domain expert
-thinks of this...
-
-Our _transportation_ obligations have ended here and our last responsibility is to
-notify the cargo owner that the cargo has arrived and is ready to be claimed.
-
-
-Primary actor.. Delivery Inspector
-Scope.......... Handling Monitoring System in shipping application
-Preconditions.. Cargo has been unloaded from a carrier in final destination.
-Trigger........ Delivery Inspector receives request to inspect the delivery status of arrived cargo.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Delivery Inspector collects known delivery data.
-2. Delivery Inspector determines that cargo is routed (for internal reference).
-3. Delivery Inspector sets next expected handling event to claim.
-4. Delivery Inspector saves cargo delivery snapshot.
-5. Delivery Inspector notifies cargo owner of cargo arrival at final destination.
-
-
-Deviations
----------------------------------------------------------------------------
-2a. Cargo has no itinerary:
-    1. Delivery Inspector marks cargo as non-routed.
-
-2b. RouteSpecification is not satisfied by Itinerary:
-    1. Delivery Inspector marks cargo as misrouted.
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectCargoInCustoms.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectCargoInCustoms.txt
deleted file mode 100644
index 8079a47..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectCargoInCustoms.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-
-USE CASE        Inspect Cargo In Customs [subfunction]
-===========================================================================
-A Delivery Inspector inspects and updates the delivery status of a cargo being
-handled in customs.
-
-It seems from the DDD sample code that a cargo can be handled by customs authorities
-in any location. So even if this is different from the last known location - or even
-not in the itinerary - the cargo will still be on track.
-
-In the DDD sample we can have additional transportation after a customs handling event,
-but isn't a claim a more logical expected next step? Can a cargo be handled by customs
-authorities and then continue its travel to other locations?!
-
-For now we don't predict any next handling event - a domain expert opinion on this
-would be interesting.
-
-
-Primary actor.. Delivery Inspector
-Scope.......... Handling Monitoring System in shipping application
-Preconditions.. Cargo is in port (??) and handled by customs authorities.
-Trigger........ Delivery Inspector receives request to inspect the delivery status of cargo in customs.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Delivery Inspector collects known delivery data.
-2. Delivery Inspector determines that cargo is routed (for internal reference).
-3. Delivery Inspector saves cargo delivery snapshot.
-
-
-Deviations
----------------------------------------------------------------------------
-2a. Cargo has no itinerary:
-    1. Delivery Inspector marks cargo as non-routed.
-
-2b. RouteSpecification is not satisfied by Itinerary:
-    1. Delivery Inspector marks cargo as misrouted.
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectClaimedCargo.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectClaimedCargo.txt
deleted file mode 100644
index 8737eee..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectClaimedCargo.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-
-USE CASE        Inspect Claimed Cargo [subfunction]
-===========================================================================
-A Delivery Inspector inspects and updates the delivery status of a claimed cargo.
-
-The cargo owner can claim the cargo in any location along the route or even in an
-unexpected location if it was misdirected! Whenever it gets picked up it marks the
-end of the cargo delivery cycle.
-
-From this point our job is done and we have no reason to determine a next handling
-event or notify the cargo owner of the cargo eventually being misdirected or
-misrouted (we though calculate it for internal reference).
-
-
-Primary actor.. Delivery Inspector
-Scope.......... Handling Monitoring System in shipping application
-Preconditions.. Cargo has been claimed by cargo owner.
-Trigger........ Delivery Inspector receives request to inspect the delivery status of claimed cargo.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Delivery Inspector collects known delivery data.
-2. Delivery Inspector determines that cargo was routed (for internal reference).
-3. Delivery Inspector determines that cargo was on track according to itinerary (for internal reference).
-4. Delivery Inspector saves cargo delivery snapshot.
-
-
-Deviations
----------------------------------------------------------------------------
-2a. Cargo has no itinerary:
-    1. Delivery Inspector marks cargo as non-routed.
-
-2b. RouteSpecification was not satisfied by Itinerary:
-    1. Delivery Inspector marks cargo as misrouted.
-
-3a. Claim location was not the same as itinerary destination:
-    1. Delivery Inspector marks cargo as misdirected.
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectLoadedCargo.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectLoadedCargo.txt
deleted file mode 100644
index 54c29a9..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectLoadedCargo.txt
+++ /dev/null
@@ -1,60 +0,0 @@
-
-USE CASE        Inspect Loaded Cargo [subfunction]
-===========================================================================
-A Delivery Inspector inspects and updates the delivery status of a loaded cargo.
-
-
-Primary actor.. Delivery Inspector
-Scope.......... Handling Monitoring System in shipping application
-Preconditions.. Cargo has been loaded onto a carrier.
-Trigger........ Delivery Inspector receives request to inspect the delivery status of loaded cargo.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Delivery Inspector collects known delivery data.
-2. Delivery Inspector determines next expected unload from carrier.
-3. Delivery Inspector verifies that cargo is routed.
-4. Delivery Inspector verifies that cargo is on track.
-5. Delivery Inspector saves cargo delivery snapshot.
-
-
-Deviations
----------------------------------------------------------------------------
-2a. Cargo loaded onto carrier without being routed:
-    1. Delivery Inspector marks cargo as non-routed and misdirected (??).
-    2. Delivery Inspector saves delivery snapshot (step 5).
-    3. Delivery Inspector sends notification of non-routed cargo and exits.
-
-2b. Voyage schedule has changed:
-    1. Delivery Inspector marks cargo as non-routed and misdirected (??).
-    2. Delivery Inspector saves delivery snapshot (step 5).
-    3. Delivery Inspector sends notification of non-routed cargo and exits.
-
-3a. Cargo has no itinerary:
-    1. Delivery Inspector marks cargo as non-routed and saves delivery snapshot.
-    2. Delivery Inspector sends notification of non-routed cargo and exits.
-
-3b. RouteSpecification is not satisfied by Itinerary:
-    1. Delivery Inspector marks cargo as misrouted and saves delivery snapshot.
-    2. Delivery Inspector sends notification of misrouted cargo and exits.
-
-4a. Voyage schedule didn't expect load location:
-    1. Delivery Inspector marks cargo as misdirected and saves delivery snapshot.
-    2. Delivery Inspector sends notification of misdirected cargo and exits.
-
-4b. Itinerary didn't expect load location:
-    1. Delivery Inspector marks cargo as misdirected and saves delivery snapshot.
-    2. Delivery Inspector sends notification of misdirected cargo and exits.
-
-4c. Itinerary didn't expect voyage:
-    1. Delivery Inspector marks cargo as misdirected and saves delivery snapshot.
-    2. Delivery Inspector sends notification of misdirected cargo and exits.
-
-4d. Itinerary didn't expect voyage but arrival location of carrier is expected:
-    1. Delivery Inspector marks cargo as misdirected and saves delivery snapshot.
-    2. Delivery Inspector notifies shipper of (for them unexpected) cargo to be unloaded in next port.
-
-4e. Itinerary didn't expect voyage arrival location:
-    1. Delivery Inspector marks cargo as misdirected and saves delivery snapshot.
-    2. Delivery Inspector sends notification of misdirected cargo and exits.
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectReceivedCargo.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectReceivedCargo.txt
deleted file mode 100644
index c7b5474..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectReceivedCargo.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-
-USE CASE        Inspect Received Cargo [subfunction]
-===========================================================================
-A Delivery Inspector inspects and updates the delivery status of a cargo that has
-been received from the cargo owner in the origin location.
-
-
-Primary actor.. Delivery Inspector
-Scope.......... Handling Monitoring System in shipping application
-Preconditions.. Cargo hasn't been received but not transported yet.
-Trigger........ Delivery Inspector receives request to inspect the delivery status of received cargo.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Delivery Inspector collects known delivery data.
-2. Delivery Inspector verifies that cargo is routed.
-3. Delivery Inspector verifies that cargo is received in cargo origin location.
-4. Delivery Inspector determines next expected load onto carrier.
-5. Delivery Inspector saves cargo delivery snapshot.
-
-
-Deviations
----------------------------------------------------------------------------
-3a. Cargo has no itinerary:
-    1. Delivery Inspector marks cargo as non-routed and updates delivery status.
-    2. Delivery Inspector sends notification of non-routed cargo and exits.
-
-3b. RouteSpecification is not satisfied by Itinerary:
-    1. Delivery Inspector marks cargo as misrouted and updates delivery status.
-    2. Delivery Inspector sends notification of misrouted cargo and exits.
-
-4a. Cargo wasn't received in origin location:
-    1. Delivery Inspector marks cargo as misdirected and updates delivery status.
-    2. Delivery Inspector sends notification of misdirected cargo and exits.
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectUnhandledCargo.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectUnhandledCargo.txt
deleted file mode 100644
index 8744ffe..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectUnhandledCargo.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-
-USE CASE        Inspect Unhandled Cargo [subfunction]
-===========================================================================
-A Delivery Inspector inspects and updates the delivery status of a cargo that has
-not been received in the origin location yet.
-
-Since the route specification is the single authority to determine the origin
-of the cargo - regardless of any itinerary - we expect the cargo to be received
-in the origin location as the first handling event.
-
-
-Primary actor.. Delivery Inspector
-Scope.......... Handling Monitoring System in shipping application
-Preconditions.. Cargo has not been received yet.
-Trigger........ Delivery Inspector receives request to inspect the delivery status of unhandled cargo.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Delivery Inspector collects known delivery data.
-2. Delivery Inspector verifies that cargo is routed.
-3. Delivery Inspector sets expected receipt in origin location.
-4. Delivery Inspector saves cargo delivery snapshot.
-
-
-Deviations
----------------------------------------------------------------------------
-2a. Cargo has no itinerary:
-    1. Delivery Inspector marks cargo as non-routed.
-
-2b. RouteSpecification is not satisfied by Itinerary:
-    1. Delivery Inspector marks cargo as misrouted.
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectUnloadedCargo.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectUnloadedCargo.txt
deleted file mode 100644
index c250bb1..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/inspection/event/InspectUnloadedCargo.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-
-USE CASE        Inspect Unloaded Cargo [subfunction]
-===========================================================================
-A Delivery Inspector inspects and updates the delivery status of a cargo that has
-been unloaded in a midpoint of the itinerary (not in final destination).
-
-If cargo has been re-routed while the cargo was on board a carrier, the unload
-location will be unexpected to the new itinerary. But we don't consider this as
-misdirected since the unload is related to the old itinerary.
-
-
-Primary actor.. Delivery Inspector
-Scope.......... Handling Monitoring System in shipping application
-Preconditions.. Cargo has been unloaded from a carrier in midpoint (not destination).
-Trigger........ Delivery Inspector receives request to inspect the delivery status of unloaded cargo.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Delivery Inspector collects known delivery data.
-2. Delivery Inspector verifies that cargo is routed.
-3. Delivery Inspector verifies that cargo is on track.
-4. Delivery Inspector determines next expected load onto carrier.
-5. Delivery Inspector saves cargo delivery snapshot.
-
-
-Deviations
----------------------------------------------------------------------------
-2a. Cargo has no itinerary:
-    1. Delivery Inspector marks cargo as non-routed and updates delivery status.
-    2. Delivery Inspector sends notification of non-routed cargo and exits.
-
-2b. Route specification is not satisfied by itinerary:
-    1. Delivery Inspector marks cargo as misrouted and updates delivery status.
-    2. Delivery Inspector sends notification of misrouted cargo and exits.
-
-3a. Cargo is misdirected and unloaded in route specification origin (cargo was re-routed):
-    1. Delivery Inspector marks cargo as not misdirected.
-
-3b. Itinerary didn't expect unload location:
-    1. Delivery Inspector marks cargo as misdirected and saves delivery snapshot.
-    2. Delivery Inspector sends notification of misdirected cargo and exits.
-
-3c. Itinerary didn't expect unload voyage but unload location was expected:
-    1. Surprising, but do we care?
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/parsing/ParseHandlingEventData.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/parsing/ParseHandlingEventData.txt
deleted file mode 100644
index 074b847..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/parsing/ParseHandlingEventData.txt
+++ /dev/null
@@ -1,62 +0,0 @@
-
-USE CASE	    Parse Handling Event Data [subfunction]
-===========================================================================
-System receives and parses handling event data coming in from a handling authority
-(port, shipper, customs etc).
-
-Primary actor.. Data Parser
-Scope.......... Handling Monitoring System in shipping application
-Preconditions.. None
-Trigger........ Incident logging application sends handling event registration attempt.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. External incident logging application provides handling event data for a handled cargo.
-2. Data Parser verifies that data is complete.
-3. Data Parser performs basic type conversion.
-4. Data Parser collects parsed handling event data.
-5. Data Parser returns parsed handling event data to handling system.
-
-
-Deviations
----------------------------------------------------------------------------
-2a. Completion time, tracking id, event type or unLocode is null or empty:
-    1. Failure.
-
-3a. Completion time string is not in ISO 8601 format:
-    1. Failure.
-
-3b. Handling event type string is not recognized:
-    1. Failure.
-
-
-Technology & Data variations *)
----------------------------------------------------------------------------
-The same business scenario can be implemented with various combinations of
-technologies:
-
-1a. Receive handling event data
-    1. manually (form input)
-    2. automatically (web service, file upload, etc.)
-
-4a. Return handling event DTO
-    1. synchronously (return value)
-    2. asynchronously (JMS, event sourcing, etc.)
-
-
----------------------------------------------------------------------------
-Success guarantees:
-    Valid handling event DTO is returned.
-
-Minimal guarantees:
-    Data consistency: Invalid data is rejected.
-    Handling authorities are notified of invalid handling event data.
-
-Stakeholders/Interests:
-    Handling System - wants data consistency
-    Handling authority - wants notification of rejected handling event data submission.
-
-
-
-*) See A. Cockburn: "Writing Effective Use Cases", pp 111
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/registration/RegisterHandlingEvent.txt b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/registration/RegisterHandlingEvent.txt
deleted file mode 100644
index 6d9bb76..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/context/usecase/handling/registration/RegisterHandlingEvent.txt
+++ /dev/null
@@ -1,76 +0,0 @@
-
-USE CASE	    Register Handling Event [subfunction]
-===========================================================================
-Event Registrar registers handling event in system.
-
-Primary actor.. Event Registrar
-Scope.......... Handling Monitoring System in booking application
-Preconditions.. None
-Trigger........ Event Registrar receives parsed handling event data.
-
-
-Main Success Scenario
----------------------------------------------------------------------------
-1. Event Registrar finds cargo from tracking id string.
-2. Event Registrar finds location from UnLocode string.
-3. Event Registrar finds voyage from voyage number string.
-4. Event Registrar verifies that cargo is not received, in customs or claimed more than once.
-5. Event Registrar verifies that cargo is not handled after being claimed.
-6. Event Registrar creates a handling event in the system.
-
-
-Deviations
----------------------------------------------------------------------------
-1a. Tracking id string doesn't represent a Cargo in Handling System:
-    1. Failure.
-
-2a. UnLocode string doesn't represent a Location in Handling System:
-    1. Failure.
-
-3a. Handling event type doesn't require a Voyage:
-    1. Continue.
-
-3b. Voyage number string is missing:
-    1. Failure.
-
-3c. Voyage number string doesn't represent a Voyage in Handling System:
-    1. Failure.
-
-4a. Cargo is received, in customs or claimed more than once:
-    1. Failure.
-
-5a. Cargo is handled after being claimed by cargo owner:
-    1. Failure (can't continue handling after claim).
-
-
-Technology & Data variations *)
----------------------------------------------------------------------------
-The same business scenario can be implemented with various combinations of
-technologies:
-
-5a. Return handling event object
-    1. synchronously (return value)
-    2. asynchronously (JMS, event sourcing, other?)
-
-
----------------------------------------------------------------------------
-Success guarantees:
-    Verified handling event object is returned.
-
-    Handling event is registered in Handling System.
-    Cargo delivery status is successfully inspected.
-    Handler is notified of successful handling event registration.
-    Cargo Owner is notified if cargo is misdirected or has arrived.
-
-Minimal guarantees:
-    Data consistency: invalid handling events are not created.
-    Handling authorities are notified of unrecognized handling event data.
-
-Stakeholders/Interests:
-    Handling System - wants data consistency
-    Handling authority - wants notification of rejected handling event data submission.
-
-
-
-
-*) See A. Cockburn: "Writing Effective Use Cases", pp 111
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/link/LinkPanel.html b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/link/LinkPanel.html
deleted file mode 100644
index a628cfb..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/link/LinkPanel.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:panel>
-	<a wicket:id="link"><span wicket:id="label"></span></a>
-</wicket:panel>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/prevnext/PrevNext.html b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/prevnext/PrevNext.html
deleted file mode 100644
index ca46915..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/prevnext/PrevNext.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:head>
-    <link href="css/prev-next.css" rel="stylesheet" type="text/css"/>
-</wicket:head>
-<wicket:panel>
-    <div class="prevNextIcons">
-        <a class="prev" href="#" wicket:id="prev"></a>
-        <a class="next" href="#" wicket:id="next" ></a>
-    </div>
-</wicket:panel>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/tabs/TabsPanel.html b/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/tabs/TabsPanel.html
deleted file mode 100644
index 7fc034a..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/resources/org/qi4j/sample/dcicargo/sample_b/infrastructure/wicket/tabs/TabsPanel.html
+++ /dev/null
@@ -1,31 +0,0 @@
-<html xmlns:wicket>
-<!--
-  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.
--->
-<wicket:head>
-    <link href="css/tabs.css" rel="stylesheet" type="text/css"/>
-</wicket:head>
-<wicket:panel>
-    <div id="tabs">
-        <ul>
-            <li wicket:id="tabsView"><a href="#" wicket:id="link"><span wicket:id="label"></span></a></li>
-        </ul>
-    </div>
-
-    <!-- Clear floating to force subsequent containers to draw beneath the tabs -->
-    <div style="clear:both"></div>
-</wicket:panel>
-</html>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/WEB-INF/web.xml b/samples/dci-cargo/dcisample_b/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index 93b47d5..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<web-app xmlns="http://java.sun.com/xml/ns/javaee"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
-         version="2.5">
-
-    <display-name>DCI Sample (version B)</display-name>
-
-    <filter>
-        <filter-name>DCISample_basic_redirect</filter-name>
-        <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
-        <init-param>
-            <param-name>applicationClassName</param-name>
-            <param-value>org.qi4j.sample.dcicargo.sample_b.bootstrap.DCISampleApplication_b</param-value>
-        </init-param>
-    </filter>
-
-    <filter-mapping>
-        <filter-name>DCISample_basic_redirect</filter-name>
-        <url-pattern>/*</url-pattern>
-    </filter-mapping>
-
-</web-app>
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/css/prev-next.css b/samples/dci-cargo/dcisample_b/src/main/webapp/css/prev-next.css
deleted file mode 100644
index d6e85ce..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/css/prev-next.css
+++ /dev/null
@@ -1,50 +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.
- */
-
-.prevNextIcons {
-  /* Modify custom positioning here */
-  float:left;
-  margin-top: 17px;
-  margin-right: 10px;
-}
-
-.prevNextIcons a {
-  padding:8px;
-  background-repeat:no-repeat;
-}
-
-.prevNextIcons .prev  {
-  background-image: url("../../graphics/icon/prev.png");
-}
-.prevNextIcons .prevDisabled {
-  background-image: url("../../graphics/icon/prev_disabled.png");
-  pointer-events: none;
-  cursor: default;
-}
-
-.prevNextIcons .next  {
-  margin-left:8px;
-  background-image: url("../../graphics/icon/next.png");
-}
-.prevNextIcons .nextDisabled {
-  margin-left:8px;
-  background-image: url("../../graphics/icon/next_disabled.png");
-  pointer-events: none;
-  cursor: default;
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/css/style.css b/samples/dci-cargo/dcisample_b/src/main/webapp/css/style.css
deleted file mode 100644
index 1bd59aa..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/css/style.css
+++ /dev/null
@@ -1,177 +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.
- */
-
-body {
-    margin: 2em;
-    font-family: 'Lucida Sans', 'Helvetica', 'Sans-serif', 'sans', sans-serif;
-    font-size: 9pt;
-    line-height: 1.2em;
-    background-color: #f5f5f5;
-}
-
-h1, h2, h3, h4, h6 {
-    color: #E9601A;
-}
-h4 {
-    margin-bottom: 5px;
-}
-a{
-    text-decoration:none;
-}
-a:hover{
-    text-decoration:underline;
-}
-a:visited{
-    color:blue;
-}
-
-.left {
-	float: left;
-	width: 75%;
-}
-.right {
-    font-family: 'Verdana', Arial, Helvetica, serif;
-    text-align:right;
-    color: #666;
-    font-size: 8pt;
-    font-style: italic;
-    font-weight: normal;
-    line-height: 1.5em;
-    margin-bottom: -50px;
-}
-.headline {
-    margin-bottom:17px;
-}
-.headline a {
-  text-decoration:none;
-    color: #E9601A;
-    font-size: 2em;
-    font-weight: bold;
-}
-
-#box {
-    border-width: 0px 1px 1px;
-    border-style: solid;
-    border-color: 484a4a;
-    padding: 1em;
-    overflow: hidden;
-    background-color: white;
-}
-
-.headerMenu {
-    margin-top:10px;
-    margin-bottom:20px;
-    color: #E9601A;
-    font-size: 1.5em;
-    font-weight: bold;
-}
-.headerMenu a {
-    margin-left:15px;
-    font-size: 9pt;
-    font-weight: normal;
-}
-
-pre, table, td {
-    font-family: 'Verdana', Arial, Helvetica, serif;
-    font-size: 9pt;
-    line-height: 1.1em;
-}
-
-table td, th {
-    padding: 4 18 4 0;
-    align: left;
-}
-
-table thead {
-    font-weight: bold;
-}
-
-.styleLeftColumn td:first-child {
-    font-weight: bold;
-}
-
-.errorColor {
-    color: red;
-    font-weight: bold;
-}
-.correctColor {
-    color: green;
-    font-weight: bold;
-}
-
-.notifyError {
-    border: 2px solid red;
-    padding: 5px;
-    font-weight: bold;
-}
-.notifySuccess {
-    border: 2px solid green;
-    padding: 5px;
-    font-weight: bold;
-}
-.notifySuccess {
-    border: 2px solid green;
-    padding: 5px;
-    font-weight: bold;
-}
-
-
-
-#toggle a {
-        padding-left: 17px;
-        text-decoration:none;
-        color:black;
-}
-
-#toggle a:hover {
-        color:blue;
-}
-
-#toggle .closed  {
-        background: url(/graphics/icon/triangle-closed.png)  no-repeat;
-        background-position: 4 2px;
-}
-#toggle .open  {
-        background: url(/graphics/icon/triangle-open.png)  no-repeat;
-        background-position: 2 4px;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/css/tabs.css b/samples/dci-cargo/dcisample_b/src/main/webapp/css/tabs.css
deleted file mode 100644
index 184b9c7..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/css/tabs.css
+++ /dev/null
@@ -1,76 +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.
- */
-
-#tabs {
-  margin-top:12px;
-  float:left;
-  width:100%;
-  background: #f5f5f5  url("../graphics/tabs/bg.png") repeat-x bottom;
-  font-size:0.9em;
-  line-height:1.6;
-  }
-#tabs ul {
-  margin:0;
-  padding:10px 0;
-  list-style:none;
-  }
-#tabs li {
-  float:left;
-  background: #f5f5f5 url("../graphics/tabs/left.png") no-repeat left top;
-  margin:0;
-  padding:0 0 0 11px;
-  }
-#tabs a {
-  float:left;
-  display:block;
-  background: #f5f5f5 url("../graphics/tabs/right.png") no-repeat right top;
-  padding:6px 15px 4px 4px;
-  text-decoration:none;
-  font-weight:bold;
- color:#444;
-  }
-
-#tabs a:hover {
-  color:blue;
-  }
-
-#tabs a:visited {
-   color:#444;
-}
-
-#tabs a:visited:hover {
-   color:blue;
-   /*color:#E9601A;*/
-}
-
-/* Commented Backslash Hack
-   hides rule from IE5-Mac  \*/
-#tabs a {float:none;}
-/* End IE5-Mac hack */
-
-
-
-#tabs #current {
-  background-image: url("../graphics/tabs/left_on.png");
-  }
-#tabs #current a {
-  background-image:url("../graphics/tabs/right_on.png");
-  color:#333;
-  padding-bottom:5px;
-  }
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/cross.png b/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/cross.png
deleted file mode 100644
index 1514d51..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/cross.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/error.png b/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/error.png
deleted file mode 100644
index 628cf2d..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/error.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/next.png b/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/next.png
deleted file mode 100644
index 823db76..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/next.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/next_disabled.png b/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/next_disabled.png
deleted file mode 100644
index 61b8738..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/next_disabled.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/prev-next.psd b/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/prev-next.psd
deleted file mode 100644
index 14869ef..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/prev-next.psd
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/prev.png b/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/prev.png
deleted file mode 100644
index f1ccf7a..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/prev.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/prev_disabled.png b/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/prev_disabled.png
deleted file mode 100644
index bc0a07b..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/prev_disabled.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/tick.png b/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/tick.png
deleted file mode 100644
index a9925a0..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/tick.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/triangle-closed.png b/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/triangle-closed.png
deleted file mode 100644
index dac3b3e..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/triangle-closed.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/triangle-open.png b/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/triangle-open.png
deleted file mode 100644
index d9ff340..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/icon/triangle-open.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/bg.png b/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/bg.png
deleted file mode 100644
index a682768..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/bg.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/left.png b/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/left.png
deleted file mode 100644
index 92b5eeb..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/left.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/left_on.png b/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/left_on.png
deleted file mode 100644
index b0fcc59..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/left_on.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/original.psd b/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/original.psd
deleted file mode 100644
index fc71fea..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/original.psd
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/right.png b/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/right.png
deleted file mode 100644
index 97efb03..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/right.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/right_on.png b/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/right_on.png
deleted file mode 100644
index 6d9783b..0000000
--- a/samples/dci-cargo/dcisample_b/src/main/webapp/graphics/tabs/right_on.png
+++ /dev/null
Binary files differ
diff --git a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/Start8082.java b/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/Start8082.java
deleted file mode 100644
index a943c61..0000000
--- a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/Start8082.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.bootstrap;
-
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.webapp.WebAppContext;
-
-/**
- * Run this to start DCI Sample, version B
- */
-public class Start8082
-{
-    private Server jetty;
-
-    public static void main( String[] args ) throws Exception
-    {
-        new Start8082().start();
-    }
-
-    public void start() throws Exception
-    {
-        jetty = new Server();
-        ServerConnector connector = new ServerConnector(jetty );
-        connector.setIdleTimeout( 1000 * 60 * 60 );
-        connector.setSoLingerTime( -1 );
-        connector.setPort( 8082 );
-        jetty.setConnectors( new Connector[]{connector} );
-
-        WebAppContext webAppContext = new WebAppContext();
-        webAppContext.setContextPath( "/" );
-        webAppContext.setWar( "src/main/webapp" );
-        jetty.setHandler( webAppContext );
-
-        try
-        {
-            jetty.start();
-            jetty.join();
-        }
-        catch (Exception e)
-        {
-            e.printStackTrace();
-            System.exit( 100 );
-        }
-    }
-
-    public void stop() throws Exception
-    {
-        jetty.stop();
-        jetty.join();
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/test/TestApplication.java b/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/test/TestApplication.java
deleted file mode 100644
index 7adc9af..0000000
--- a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/test/TestApplication.java
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.bootstrap.test;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.rules.TestName;
-import org.qi4j.api.composite.TransientBuilderFactory;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.query.QueryBuilderFactory;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.usecase.Usecase;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.sampledata.BaseData;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.RouteSpecificationFactoryService;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.Cargo;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.NextHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.Location;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.tracking.TrackingId;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Schedule;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Voyage;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.VoyageNumber;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.dci.Context;
-import org.qi4j.sample.dcicargo.sample_b.infrastructure.testing.ExpectedException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.*;
-
-/**
- * Base class for testing Context Interactions
- */
-public class TestApplication
-      extends BaseData
-{
-    // Logger for sub classes
-    protected Logger logger = LoggerFactory.getLogger( getClass() );
-
-    protected static Application app;
-
-    protected static RouteSpecificationFactoryService routeSpecFactory;
-
-    final protected static Date TODAY = new Date();
-    final protected static Date DAY1 = day( 1 );
-    final protected static Date DAY2 = day( 2 );
-    final protected static Date DAY3 = day( 3 );
-    final protected static Date DAY4 = day( 4 );
-    final protected static Date DAY5 = day( 5 );
-    final protected static Date DAY6 = day( 6 );
-    final protected static Date DAY7 = day( 7 );
-    final protected static Date DAY8 = day( 8 );
-    final protected static Date DAY9 = day( 9 );
-    final protected static Date DAY10 = day( 10 );
-    final protected static Date DAY11 = day( 11 );
-    final protected static Date DAY12 = day( 12 );
-    final protected static Date DAY13 = day( 13 );
-    final protected static Date DAY14 = day( 14 );
-    final protected static Date DAY15 = day( 15 );
-    final protected static Date DAY16 = day( 16 );
-    final protected static Date DAY17 = day( 17 );
-    final protected static Date DAY18 = day( 18 );
-    final protected static Date DAY19 = day( 19 );
-    final protected static Date DAY20 = day( 20 );
-    final protected static Date DAY21 = day( 21 );
-    final protected static Date DAY22 = day( 22 );
-    final protected static Date DAY23 = day( 23 );
-    final protected static Date DAY24 = day( 24 );
-    final protected static Date DAY25 = day( 25 );
-
-    protected static Voyage V201;
-    protected static Voyage V202;
-    protected static Voyage V203;
-    protected static Voyage V204;
-    protected static Voyage V205;
-
-    final protected static Voyage noVoyage = null;
-    final protected static boolean notArrived = false;
-    final protected static boolean arrived = true;
-    final protected static boolean directed = false;
-    final protected static boolean misdirected = true;
-    final protected static Date unknownETA = null;
-    final protected static Date noSpecificDate = null;
-    final protected static Integer leg1 = 0;
-    final protected static Integer leg2 = 1;
-    final protected static Integer leg3 = 2;
-    final protected static Integer leg4 = 3;
-    final protected static Integer leg5 = 4;
-    final protected static Integer unknownLeg = 0;
-    final protected static NextHandlingEvent unknownNextHandlingEvent = null;
-
-    protected Date deadline;
-    protected Date arrival;
-    protected RouteSpecification routeSpec;
-    protected RouteSpecification newRouteSpec;
-    protected Delivery delivery;
-    protected Cargo cargo;
-    protected TrackingId trackingId;
-    protected String trackingIdString;
-    protected Itinerary itinerary;
-    protected Itinerary wrongItinerary;
-    protected HandlingEvent handlingEvent;
-    protected Location MELBOURNE;
-    protected Location HANGZHOU;
-    protected Location HONGKONG;
-    protected Location SHANGHAI;
-    protected Location HAMBURG;
-    protected Location STOCKHOLM;
-    protected Location DALLAS;
-    protected Location NEWYORK;
-    protected Location MOGADISHU;
-    protected Location ROTTERDAM;
-    protected Location HELSINKI;
-    protected Location GOTHENBURG;
-    protected Location TOKYO;
-    protected Location CHICAGO;
-
-    protected TestApplication()
-    {
-        super( findHostingModule() );
-    }
-
-    @BeforeClass
-    public static void setup() throws Exception
-    {
-        System.out.println( "\n@@@@@@@@@@@  TEST SUITE  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" );
-        app = new Energy4Java().newApplication( new TestAssembler() );
-        app.activate();
-        Context.prepareContextBaseClass( findHostingModule() );
-
-    }
-
-    // Allow to test message output from exceptions after they have been thrown
-    @Rule
-    public ExpectedException thrown = ExpectedException.none();
-
-    // Print current test method name to console
-    @Rule
-    public TestName name = new TestName();
-
-    @Before
-    public void prepareTest()
-        throws Exception
-    {
-        logger.info( name.getMethodName() );
-        Usecase usecase = UsecaseBuilder.newUsecase( "Usecase:" + name );
-        UnitOfWork uow = module.newUnitOfWork(usecase);
-        populateTestData();
-
-        ServiceReference<RouteSpecificationFactoryService> routeSpecFactoryServiceRef =
-            module.findService( RouteSpecificationFactoryService.class );
-        routeSpecFactory = routeSpecFactoryServiceRef.get();
-
-        // Separate test suites in console output
-        System.out.println();
-    }
-
-    @After
-    public void concludeTests()
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        if (uow != null)
-        {
-            uow.discard();
-        }
-        if( module.isUnitOfWorkActive() )
-        {
-            while( module.isUnitOfWorkActive() )
-            {
-                uow = module.currentUnitOfWork();
-                if( uow.isOpen() )
-                {
-                    System.err.println( "UnitOfWork not cleaned up:" + uow.usecase().name() );
-                    uow.discard();
-                }
-                else
-                {
-                    throw new InternalError( "I have seen a case where a UoW is on the stack, but not opened. First is: " + uow.usecase().name() );
-                }
-            }
-            new Exception( "UnitOfWork not properly cleaned up" ).printStackTrace();
-        }
-    }
-
-    @AfterClass
-    public static void terminateApplication() throws Exception
-    {
-        if( app != null )
-        {
-            app.passivate();
-        }
-    }
-
-    public void assertMessage( Exception e, String msg )
-    {
-        String message = "\nEXPECTED: " + msg + "\nGOT: " + e.getMessage();
-        assertTrue( message, e.getMessage().contains( msg ) );
-    }
-
-
-    private void populateTestData() throws Exception
-    {
-        // UnLocode value objects
-        AUMEL = unlocode( "AUMEL" ); // Melbourne
-        CNHGH = unlocode( "CNHGH" ); // Hangzou
-        CNHKG = unlocode( "CNHKG" ); // Hong Kong
-        CNSHA = unlocode( "CNSHA" ); // Shanghai
-        DEHAM = unlocode( "DEHAM" ); // Hamburg
-        FIHEL = unlocode( "FIHEL" ); // Helsinki
-        JNTKO = unlocode( "JNTKO" ); // Tokyo
-        NLRTM = unlocode( "NLRTM" ); // Rotterdam
-        SEGOT = unlocode( "SEGOT" ); // Gothenburg
-        SESTO = unlocode( "SESTO" ); // Stockholm
-        SOMGQ = unlocode( "SOMGQ" ); // Mogadishu
-        USCHI = unlocode( "USCHI" ); // Chicago
-        USDAL = unlocode( "USDAL" ); // Dallas
-        USNYC = unlocode( "USNYC" ); // New York
-
-        UnitOfWork uow = module.currentUnitOfWork();
-
-        // Get locations created in BaseDataService on startup
-        MELBOURNE = uow.get( Location.class, "AUMEL" );
-        HANGZHOU = uow.get( Location.class, "CNHGH" );
-        HONGKONG = uow.get( Location.class, "CNHKG" );
-        SHANGHAI = uow.get( Location.class, "CNSHA" );
-        HAMBURG = uow.get( Location.class, "DEHAM" );
-        HELSINKI = uow.get( Location.class, "FIHEL" );
-        TOKYO = uow.get( Location.class, "JNTKO" );
-        ROTTERDAM = uow.get( Location.class, "NLRTM" );
-        GOTHENBURG = uow.get( Location.class, "SEGOT" );
-        STOCKHOLM = uow.get( Location.class, "SESTO" );
-        MOGADISHU = uow.get( Location.class, "SOMGQ" );
-        CHICAGO = uow.get( Location.class, "USCHI" );
-        DALLAS = uow.get( Location.class, "USDAL" );
-        NEWYORK = uow.get( Location.class, "USNYC" );
-
-        // Voyage entity objects for testing
-        V201 = voyage( "V201", schedule(
-              carrierMovement( HONGKONG, CHICAGO, DAY1, DAY5 ),
-              carrierMovement( CHICAGO, NEWYORK, DAY5, DAY6 ),
-              carrierMovement( NEWYORK, GOTHENBURG, DAY6, DAY12 )
-        ) );
-        V202 = voyage( "V202", schedule(
-              carrierMovement( CHICAGO, NEWYORK, DAY3, DAY5 ),
-              carrierMovement( NEWYORK, DALLAS, DAY7, DAY8 ),
-              carrierMovement( DALLAS, ROTTERDAM, DAY10, DAY17 ),
-              carrierMovement( ROTTERDAM, HAMBURG, DAY17, DAY19 ),
-              carrierMovement( HAMBURG, GOTHENBURG, DAY20, DAY24 )
-        ) );
-        V203 = voyage( "V203", schedule(
-              carrierMovement( NEWYORK, HAMBURG, DAY3, DAY12 ),
-              carrierMovement( HAMBURG, ROTTERDAM, DAY13, DAY18 ),
-              carrierMovement( ROTTERDAM, STOCKHOLM, DAY20, DAY23 ),
-              carrierMovement( STOCKHOLM, HELSINKI, DAY24, DAY25 )
-        ) );
-        V204 = voyage( "V204", schedule(
-              carrierMovement( TOKYO, HANGZHOU, DAY3, DAY6 ),
-              carrierMovement( HANGZHOU, HONGKONG, DAY7, DAY8 ),
-              carrierMovement( HONGKONG, NEWYORK, DAY9, DAY12 ),
-              carrierMovement( NEWYORK, MELBOURNE, DAY13, DAY19 )
-        ) );
-        V205 = voyage( "V205", schedule(
-              carrierMovement( HANGZHOU, MOGADISHU, DAY1, DAY2 ),
-              carrierMovement( MOGADISHU, ROTTERDAM, DAY2, DAY4 ),
-              carrierMovement( ROTTERDAM, NEWYORK, DAY4, DAY7 ),
-              carrierMovement( NEWYORK, DALLAS, DAY9, DAY10 )
-        ) );
-
-        itinerary = itinerary(
-              leg( V201, HONGKONG, CHICAGO, DAY1, DAY5 ),
-              leg( V201, CHICAGO, NEWYORK, DAY5, DAY6 ),
-              leg( V202, NEWYORK, DALLAS, DAY7, DAY8 ),
-              leg( V202, DALLAS, ROTTERDAM, DAY10, DAY17 ),
-              leg( V203, ROTTERDAM, STOCKHOLM, DAY20, DAY23 )
-        );
-
-        wrongItinerary = itinerary(
-              leg( V201, HONGKONG, CHICAGO, DAY1, DAY5 ),
-              leg( V201, CHICAGO, NEWYORK, DAY5, DAY6 ),
-              leg( V204, NEWYORK, MELBOURNE, DAY13, DAY19 )
-        );
-    }
-
-    public void assertDelivery( HandlingEventType handlingEventType,
-                                Location location,
-                                Date completion,
-                                Voyage voyage,
-
-                                TransportStatus transportStatus,
-                                Boolean isUnloadedAtDestination,
-
-                                RoutingStatus routingStatus,
-                                Boolean isMisdirected,
-                                Date eta,
-                                Integer itineraryProgress,
-
-                                HandlingEventType nextHandlingEventType,
-                                Location nextLocation,
-                                Date nextTime,
-                                Voyage nextVoyage
-    ) throws Exception
-    {
-        delivery = cargo.delivery().get();
-
-        // Last handling event
-        if (delivery.lastHandlingEvent().get() != null
-              || handlingEventType != null || location != null || completion != null || voyage != null)
-        {
-            assertThat( "lastHandlingEvent - handlingEventType",
-                        delivery.lastHandlingEvent().get().handlingEventType().get(), is( equalTo( handlingEventType ) ) );
-            assertThat( "lastHandlingEvent - location",
-                        delivery.lastHandlingEvent().get().location().get(), is( equalTo( location ) ) );
-            assertThat( "lastHandlingEvent - completionTime",
-                        delivery.lastHandlingEvent().get().completionTime().get(), is( equalTo( completion ) ) );
-            assertThat( "lastHandlingEvent - voyage",
-                        delivery.lastHandlingEvent().get().voyage().get(), is( equalTo( voyage ) ) );
-        }
-
-        // Other transport status
-        assertThat( "transportStatus",
-                    delivery.transportStatus().get(), is( equalTo( transportStatus ) ) );
-        assertThat( "isUnloadedAtDestination",
-                    delivery.isUnloadedAtDestination().get(), is( equalTo( isUnloadedAtDestination ) ) );
-
-
-        // Routing and direction
-        assertThat( "routingStatus",
-                    delivery.routingStatus().get(), is( equalTo( routingStatus ) ) );
-        assertThat( "isMisdirected",
-                    delivery.isMisdirected().get(), is( equalTo( isMisdirected ) ) );
-        assertThat( "eta",
-                    delivery.eta().get(), is( equalTo( eta ) ) );
-        assertThat( "itineraryProgressIndex",
-                    delivery.itineraryProgressIndex().get(), is( equalTo( itineraryProgress ) ) );
-
-
-        // Next handling event
-        if (nextHandlingEventType == null)
-        {
-            assertThat( "nextHandlingEvent - handlingEventType",
-                        delivery.nextHandlingEvent().get(), is( equalTo( null ) ) );
-        }
-        else
-        {
-            assertThat( "nextHandlingEvent - handlingEventType",
-                        delivery.nextHandlingEvent().get().handlingEventType().get(), is( equalTo( nextHandlingEventType ) ) );
-            assertThat( "nextHandlingEvent - location",
-                        delivery.nextHandlingEvent().get().location().get(), is( equalTo( nextLocation ) ) );
-
-
-            if (delivery.nextHandlingEvent().get().time().get() != null)
-            {
-                // Estimating a new carrier arrival time might be calculated a second
-                // after initial dates are set, so we skip the seconds
-                SimpleDateFormat parser = new SimpleDateFormat( "yyyy-MM-dd HH:mm" );
-                String calculatedTime = parser.format( delivery.nextHandlingEvent().get().time().get() );
-                String expectedTime = parser.format( nextTime );
-                assertThat( "nextHandlingEvent - time", calculatedTime, is( equalTo( expectedTime ) ) );
-            }
-            else
-                assertThat( "nextHandlingEvent - time", delivery.nextHandlingEvent().get().time().get(), is( equalTo( nextTime ) ) );
-
-            assertThat( "nextHandlingEvent - voyage",
-                        delivery.nextHandlingEvent().get().voyage().get(), is( equalTo( nextVoyage ) ) );
-        }
-    }
-
-
-    public void assertDelivery( HandlingEventType handlingEventType,
-                                Location location,
-                                Date completion,
-                                Voyage voyage,
-
-                                TransportStatus transportStatus,
-                                Boolean isUnloadedAtDestination,
-
-                                RoutingStatus routingStatus,
-                                Boolean isMisdirected,
-                                Date eta,
-                                Integer itineraryProgress,
-
-                                NextHandlingEvent noNextHandlingEvent
-    ) throws Exception
-    {
-        assertDelivery( handlingEventType, location, completion, voyage,
-                        transportStatus, isUnloadedAtDestination, routingStatus, isMisdirected, eta,
-                        itineraryProgress, null, null, null, null );
-    }
-
-    public void assertRouteSpec( Location origin, Location destination, Date earliestDeparture, Date deadline )
-    {
-        newRouteSpec = cargo.routeSpecification().get();
-
-        assertThat( newRouteSpec.origin().get(), is( equalTo( origin ) ) );
-        assertThat( newRouteSpec.destination().get(), is( equalTo( destination ) ) );
-        assertThat( newRouteSpec.earliestDeparture().get(), is( equalTo( earliestDeparture ) ) );
-        assertThat( newRouteSpec.arrivalDeadline().get(), is( equalTo( deadline ) ) );
-    }
-
-    protected Voyage voyage( String voyageNumberStr, Schedule schedule )
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        EntityBuilder<Voyage> voyage = uow.newEntityBuilder( Voyage.class, voyageNumberStr );
-
-        // VoyageNumber
-        ValueBuilder<VoyageNumber> voyageNumber = module.newValueBuilder( VoyageNumber.class );
-        voyageNumber.prototype().number().set( voyageNumberStr );
-        voyage.instance().voyageNumber().set( voyageNumber.newInstance() );
-
-        // Schedule
-        voyage.instance().schedule().set( schedule );
-        return voyage.newInstance();
-    }
-
-    private static Module findHostingModule()
-    {
-        return app.findModule( "BOOTSTRAP", "BOOTSTRAP-Bootstrap" );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/test/TestAssembler.java b/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/test/TestAssembler.java
deleted file mode 100644
index 639ec7b..0000000
--- a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/bootstrap/test/TestAssembler.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.bootstrap.test;
-
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.ApplicationAssemblyFactory;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.functional.Function;
-import org.qi4j.index.rdf.RdfIndexingEngineService;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.library.rdf.entity.EntityTypeSerializer;
-import org.qi4j.library.rdf.repository.MemoryRepositoryService;
-import org.qi4j.sample.dcicargo.pathfinder_b.api.GraphTraversalService;
-import org.qi4j.sample.dcicargo.pathfinder_b.internal.GraphDAO;
-import org.qi4j.sample.dcicargo.pathfinder_b.internal.GraphTraversalServiceImpl;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.sampledata.BaseDataService;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.ProcessHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.ParseHandlingEventData;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-import org.qi4j.sample.dcicargo.sample_b.context.rolemap.CargoRoleMap;
-import org.qi4j.sample.dcicargo.sample_b.context.rolemap.CargosRoleMap;
-import org.qi4j.sample.dcicargo.sample_b.context.rolemap.HandlingEventsRoleMap;
-import org.qi4j.sample.dcicargo.sample_b.context.service.routing.RoutingService;
-import org.qi4j.sample.dcicargo.sample_b.data.entity.HandlingEventEntity;
-import org.qi4j.sample.dcicargo.sample_b.data.entity.LocationEntity;
-import org.qi4j.sample.dcicargo.sample_b.data.entity.VoyageEntity;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.RouteSpecificationFactoryService;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.NextHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Leg;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.location.UnLocode;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.tracking.TrackingId;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.CarrierMovement;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.Schedule;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.voyage.VoyageNumber;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-import static org.qi4j.api.common.Visibility.application;
-import static org.qi4j.api.structure.Application.Mode.test;
-
-/**
- * Test application assembler
- *
- * (Has no communication layer)
- */
-@SuppressWarnings( "unchecked" )
-public class TestAssembler
-    implements ApplicationAssembler
-{
-    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-        throws AssemblyException
-    {
-        // Application assembly
-        ApplicationAssembly assembly = applicationFactory.newApplicationAssembly();
-        assembly.setName( "DCI Sample (version A) - TEST" );
-        assembly.setVersion( "B.1.0" );
-        assembly.setMode( test );
-
-        // Layers
-        LayerAssembly infrastructureLayer = assembly.layer( "INFRASTRUCTURE" );
-        LayerAssembly dataLayer = assembly.layer( "DATA" );
-        LayerAssembly contextLayer = assembly.layer( "CONTEXT" );
-        LayerAssembly bootstrapLayer = assembly.layer( "BOOTSTRAP" );
-
-        // Layer dependencies
-        bootstrapLayer.uses(
-            contextLayer,
-            dataLayer,
-            infrastructureLayer );
-
-        contextLayer.uses(
-            dataLayer,
-            infrastructureLayer );
-
-        dataLayer.uses(
-            infrastructureLayer
-        );
-
-        // Assemble
-        assembleDomainLayer( dataLayer );
-        assembleContextLayer( contextLayer );
-        assembleBootstrapLayer( bootstrapLayer );
-        assembleInfrastructureLayer( infrastructureLayer );
-
-        return assembly;
-    }
-
-    private void assembleBootstrapLayer( LayerAssembly bootstrapLayer )
-        throws AssemblyException
-    {
-        ModuleAssembly bootstrapModule = bootstrapLayer.module( "BOOTSTRAP-Bootstrap" );
-
-        // Load base data on startup
-        bootstrapModule
-            .services( BaseDataService.class )
-            .visibleIn( application )
-            .instantiateOnStartup();
-    }
-
-    private void assembleContextLayer( LayerAssembly contextLayer )
-        throws AssemblyException
-    {
-        ModuleAssembly roleMapModule = contextLayer.module( "CONTEXT-RoleMap" );
-
-        // Role-playing entities
-        roleMapModule
-            .entities(
-                CargoRoleMap.class,
-                CargosRoleMap.class,
-                HandlingEventsRoleMap.class )
-            .visibleIn( application );
-
-        // Non-role-playing entities
-        roleMapModule
-            .entities(
-                HandlingEventEntity.class,
-                LocationEntity.class,
-                VoyageEntity.class )
-            .visibleIn( application );
-
-        ModuleAssembly interactionModule = contextLayer.module( "CONTEXT-Interaction" );
-        interactionModule
-            .transients(
-                ProcessHandlingEvent.class )
-            .visibleIn( application );
-
-        ModuleAssembly contextServiceModule = contextLayer.module( "CONTEXT-Service" );
-        contextServiceModule
-            .services(
-                ParseHandlingEventData.class,
-                RoutingService.class,
-                RouteSpecificationFactoryService.class )
-            .visibleIn( application );
-
-        contextServiceModule
-            .values(
-                ParsedHandlingEventData.class )
-            .visibleIn( application );
-    }
-
-    private void assembleDomainLayer( LayerAssembly dataLayer )
-        throws AssemblyException
-    {
-        // Non-role-playing values
-        ModuleAssembly structureModule = dataLayer.module( "DATA-Structure" );
-        structureModule
-            .values(
-                TrackingId.class,
-                RouteSpecification.class,
-                Delivery.class,
-                NextHandlingEvent.class,
-                UnLocode.class,
-                Itinerary.class,
-                Leg.class,
-                CarrierMovement.class,
-                Schedule.class,
-                VoyageNumber.class )
-            .visibleIn( application );
-//        structureModule.entities( LocationEntity.class, VoyageEntity.class, HandlingEventEntity.class );
-    }
-
-    private void assembleInfrastructureLayer( LayerAssembly infrastructureLayer )
-        throws AssemblyException
-    {
-        ModuleAssembly serializationModule = infrastructureLayer.module( "INFRASTRUCTURE-Serialization" );
-        serializationModule
-            .services( OrgJsonValueSerializationService.class )
-            .taggedWith( ValueSerialization.Formats.JSON )
-            .setMetaInfo( new Function<Application, Module>()
-        {
-            @Override
-            public Module map( Application application )
-            {
-                return application.findModule( "CONTEXT", "CONTEXT-RoleMap" );
-            }
-        } )
-        .visibleIn( application );
-
-        ModuleAssembly indexingModule = infrastructureLayer.module( "INFRASTRUCTURE-Indexing" );
-        indexingModule
-            .objects(
-                EntityStateSerializer.class,
-                EntityTypeSerializer.class );
-
-        indexingModule
-            .services(
-                MemoryRepositoryService.class,
-                RdfIndexingEngineService.class )
-            .visibleIn( application )
-            .instantiateOnStartup();
-
-        ModuleAssembly entityStoreModule = infrastructureLayer.module( "INFRASTRUCTURE-EntityStore" );
-        entityStoreModule
-            .addServices(
-                MemoryEntityStoreService.class,
-                UuidIdentityGeneratorService.class )
-            .visibleIn( application );
-
-        ModuleAssembly externalServiceModule = infrastructureLayer.module( "INFRASTRUCTURE-ExternalService" );
-        externalServiceModule
-            .importedServices(
-                GraphTraversalService.class )
-            .setMetaInfo( new GraphTraversalServiceImpl( new GraphDAO() ) )
-            .visibleIn( application );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/booking/BookNewCargoTest.java b/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/booking/BookNewCargoTest.java
deleted file mode 100644
index 368ecf0..0000000
--- a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/booking/BookNewCargoTest.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.test.booking;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.test.TestApplication;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.BookNewCargo;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.CargoAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.entity.CargoEntity;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.exception.CannotCreateCargoException;
-import org.qi4j.sample.dcicargo.sample_b.data.factory.exception.CannotCreateRouteSpecificationException;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.NOT_ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.NOT_RECEIVED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.RECEIVE;
-
-/**
- * {@link BookNewCargo} tests
- *
- * FIXME: Every test method call the one above to allow ordered execution, ie. tests are not indepedants !
- */
-public class BookNewCargoTest extends TestApplication
-{
-
-    private CargoAggregateRoot CARGOS;
-
-    @Before
-    public void prepareTest()
-        throws Exception
-    {
-        super.prepareTest();
-        UnitOfWork uow = module.currentUnitOfWork();
-        CARGOS = uow.get( CargoAggregateRoot.class, CargoAggregateRoot.CARGOS_ID );
-    }
-
-    @Test
-    public void deviation_2a_OriginAndDestinationSame()
-        throws Exception
-    {
-        try
-        {
-            thrown.expect( CannotCreateRouteSpecificationException.class, "Origin location can't be same as destination location." );
-            new BookNewCargo( CARGOS, HONGKONG, HONGKONG, DAY24 ).getTrackingId();
-        }
-        catch( Exception ex )
-        {
-            ex.printStackTrace();
-            throw ex;
-        }
-    }
-
-    @Test
-    public void deviation_2b_DeadlineInThePastNotAccepted()
-        throws Exception
-    {
-        deviation_2a_OriginAndDestinationSame();
-        thrown.expect( CannotCreateRouteSpecificationException.class, "Arrival deadline is in the past or Today." );
-        new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, day( -1 ) ).getTrackingId();
-    }
-
-    @Test
-    public void deviation_2b_DeadlineTodayIsTooEarly()
-        throws Exception
-    {
-        deviation_2b_DeadlineInThePastNotAccepted();
-        thrown.expect( CannotCreateRouteSpecificationException.class, "Arrival deadline is in the past or Today." );
-        new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, day( 0 ) ).getTrackingId();
-    }
-
-    @Test
-    public void deviation_2b_DeadlineTomorrowIsOkay()
-        throws Exception
-    {
-        deviation_2b_DeadlineTodayIsTooEarly();
-        new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, DAY1 ).getTrackingId();
-    }
-
-    @Test
-    public void step_2_CanCreateRouteSpecification()
-        throws Exception
-    {
-        deviation_2b_DeadlineTomorrowIsOkay();
-        UnitOfWork uow = module.currentUnitOfWork();
-        trackingId = new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, DAY24 ).getTrackingId();
-        cargo = uow.get( CargoEntity.class, trackingId.id().get() );
-        assertThat( cargo.routeSpecification().get().origin().get(), is( equalTo( HONGKONG ) ) );
-        assertThat( cargo.routeSpecification().get().destination().get(), is( equalTo( STOCKHOLM ) ) );
-        assertThat( cargo.routeSpecification().get().arrivalDeadline().get(), is( equalTo( DAY24 ) ) );
-    }
-
-    @Test
-    public void step_3_CanDeriveInitialDeliveryData()
-        throws Exception
-    {
-        step_2_CanCreateRouteSpecification();
-        UnitOfWork uow = module.currentUnitOfWork();
-        trackingId = new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, DAY24 ).getTrackingId();
-        cargo = uow.get( CargoEntity.class, trackingId.id().get() );
-        assertDelivery( null, null, null, null,
-                        NOT_RECEIVED, notArrived,
-                        NOT_ROUTED, directed, unknownETA, unknownLeg,
-                        RECEIVE, HONGKONG, noSpecificDate, noVoyage );
-    }
-
-    @Test
-    public void deviation_4a_TrackingIdTooShort()
-        throws Exception
-    {
-        step_3_CanDeriveInitialDeliveryData();
-        thrown.expect( ConstraintViolationException.class, "for value 'no'" );
-        new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, DAY24 ).withTrackingId( "no" );
-    }
-
-    @Test
-    public void deviation_4a_TrackingIdNotTooShort()
-        throws Exception
-    {
-        deviation_4a_TrackingIdTooShort();
-        UnitOfWork uow = module.currentUnitOfWork();
-        trackingId = new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, DAY24 ).withTrackingId( "yes" );
-        cargo = uow.get( CargoEntity.class, trackingId.id().get() );
-        assertThat( cargo.trackingId().get().id().get(), is( equalTo( "yes" ) ) );
-    }
-
-    @Test
-    public void deviation_4a_TrackingIdTooLong()
-        throws Exception
-    {
-        deviation_4a_TrackingIdNotTooShort();
-        thrown.expect( ConstraintViolationException.class, "for value '1234567890123456789012345678901'" );
-        new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, DAY24 ).withTrackingId( "1234567890123456789012345678901" );
-    }
-
-    @Test
-    public void deviation_4a_TrackingIdNotTooLong()
-        throws Exception
-    {
-        deviation_4a_TrackingIdTooLong();
-        UnitOfWork uow = module.currentUnitOfWork();
-        trackingId = new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, DAY24 ).withTrackingId( "123456789012345678901234567890" );
-        cargo = uow.get( CargoEntity.class, trackingId.id().get() );
-        assertThat( cargo.trackingId().get().id().get(), is( equalTo( "123456789012345678901234567890" ) ) );
-    }
-
-    @Test
-    public void deviation_4a_TrackingIdWithWrongCharacter()
-        throws Exception
-    {
-        deviation_4a_TrackingIdNotTooLong();
-        thrown.expect( ConstraintViolationException.class, "for value 'Göteborg1234'" );
-        new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, DAY24 ).withTrackingId( "Göteborg1234" );
-    }
-
-    @Test
-    public void deviation_4b_TrackingIdNotUnique()
-        throws Exception
-    {
-        deviation_4a_TrackingIdWithWrongCharacter();
-        thrown.expect( CannotCreateCargoException.class, "Tracking id 'yes' is not unique." );
-        new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, DAY24 ).withTrackingId( "yes" );
-    }
-
-    @Test
-    public void step_4_CanAutoCreateTrackingIdFromEmptyString()
-        throws Exception
-    {
-        deviation_4b_TrackingIdNotUnique();
-        new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, DAY24 ).withTrackingId( "" );
-    }
-
-    @Test
-    public void step_4_CanAutoCreateTrackingIdFromNull()
-        throws Exception
-    {
-        step_4_CanAutoCreateTrackingIdFromEmptyString();
-        new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, DAY24 ).withTrackingId( null );
-    }
-
-    @Test
-    public void success_BookNewCargo()
-        throws Exception
-    {
-        step_4_CanAutoCreateTrackingIdFromNull();
-        UnitOfWork uow = module.currentUnitOfWork();
-        trackingId = new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, DAY24 ).withTrackingId( "ABC" );
-        cargo = uow.get( CargoEntity.class, trackingId.id().get() );
-
-        assertThat( cargo.trackingId().get(), is( equalTo( trackingId ) ) );
-        assertThat( cargo.trackingId().get().id().get(), is( equalTo( "ABC" ) ) );
-        assertThat( cargo.origin().get(), is( equalTo( HONGKONG ) ) );
-
-        assertDelivery( null, null, null, null,
-                        NOT_RECEIVED, notArrived,
-                        NOT_ROUTED, directed, unknownETA, unknownLeg,
-                        RECEIVE, HONGKONG, noSpecificDate, noVoyage );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/booking/routing/AssignCargoToRouteTest.java b/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/booking/routing/AssignCargoToRouteTest.java
deleted file mode 100644
index fc5b3f0..0000000
--- a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/booking/routing/AssignCargoToRouteTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.test.booking.routing;
-
-import java.util.Date;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.test.TestApplication;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.exception.RoutingException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.exception.UnsatisfyingRouteException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.routing.AssignCargoToRoute;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.CargoAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.HandlingEventAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Itinerary;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.NOT_ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.CLAIMED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.IN_PORT;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.NOT_RECEIVED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.ONBOARD_CARRIER;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.CUSTOMS;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.LOAD;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.RECEIVE;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.UNLOAD;
-
-/**
- * {@link AssignCargoToRoute} tests
- *
- * FIXME: Every test method call the one above to allow ordered execution, ie. tests are not independent!
- */
-public class AssignCargoToRouteTest extends TestApplication
-{
-    static Itinerary itinerary2;
-    private HandlingEventAggregateRoot HANDLING_EVENTS;
-
-    @Before
-    public void prepareTest()
-        throws Exception
-    {
-        super.prepareTest();
-        UnitOfWork uow = module.currentUnitOfWork();
-        HANDLING_EVENTS = uow.get( HandlingEventAggregateRoot.class, HandlingEventAggregateRoot.HANDLING_EVENTS_ID );
-        CargoAggregateRoot CARGOS = uow.get( CargoAggregateRoot.class, CargoAggregateRoot.CARGOS_ID );
-
-        // Create new cargo
-        routeSpec = routeSpecFactory.build( HONGKONG, STOCKHOLM, new Date(), deadline = DAY24 );
-        delivery = delivery( TODAY, NOT_RECEIVED, NOT_ROUTED, unknownLeg );
-        cargo = CARGOS.createCargo( routeSpec, delivery, "ABC" );
-        trackingId = cargo.trackingId().get();
-        delivery = cargo.delivery().get();
-    }
-
-    @Test
-    public void precondition_x1_CannotReRouteClaimedCargo()
-        throws Exception
-    {
-        cargo.delivery().set( delivery( TODAY, CLAIMED, ROUTED, unknownLeg ) );
-        thrown.expect( RoutingException.class, "Can't re-route claimed cargo" );
-        new AssignCargoToRoute( cargo, itinerary ).assign();
-    }
-
-    @Test
-    public void deviation_1a_UnsatisfyingItinerary()
-        throws Exception
-    {
-        precondition_x1_CannotReRouteClaimedCargo();
-
-        cargo.delivery().set( delivery( TODAY, NOT_RECEIVED, NOT_ROUTED, unknownLeg ) );
-        thrown.expect( UnsatisfyingRouteException.class, "Route specification was not satisfied with itinerary" );
-        new AssignCargoToRoute( cargo, wrongItinerary ).assign();
-    }
-
-    @Test
-    public void deviation_3a_Routing_UnhandledCargo()
-        throws Exception
-    {
-        deviation_1a_UnsatisfyingItinerary();
-
-        cargo.delivery().set( delivery( TODAY, NOT_RECEIVED, NOT_ROUTED, unknownLeg ) );
-        new AssignCargoToRoute( cargo, itinerary ).assign();
-        assertDelivery( null, null, null, null,
-                        NOT_RECEIVED, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg1,
-                        RECEIVE, HONGKONG, noSpecificDate, noVoyage );
-    }
-
-    @Test
-    public void deviation_3b_ReRouting_OnBoard()
-        throws Exception
-    {
-        deviation_3a_Routing_UnhandledCargo();
-
-        // Load cargo
-        cargo.itinerary().set( itinerary );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY5, DAY5, trackingId, LOAD, CHICAGO, V201 );
-        cargo.delivery().set( delivery( handlingEvent, ONBOARD_CARRIER, notArrived,
-                                        ROUTED, directed, DAY23, leg2,
-                                        nextHandlingEvent( UNLOAD, NEWYORK, DAY6, V201 ) ) );
-
-        // New itinerary with arrival location of current carrier movement
-        // Earliest departure date is after carrier arrival
-        itinerary2 = itinerary( leg( V202, NEWYORK, STOCKHOLM, DAY8, DAY17 ) );
-
-        // Re-route cargo while on board a carrier
-        new AssignCargoToRoute( cargo, itinerary2 ).assign();
-        assertDelivery( LOAD, CHICAGO, DAY5, V201,
-                        ONBOARD_CARRIER, notArrived,
-                        ROUTED, directed, itinerary2.eta(), leg1,
-                        UNLOAD, NEWYORK, DAY6, V201 ); // from old itinerary!
-    }
-
-    @Test
-    public void deviation_3c_ReRouting_InPort_Received()
-        throws Exception
-    {
-        deviation_3b_ReRouting_OnBoard();
-
-        // Receive cargo
-        cargo.itinerary().set( itinerary );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, RECEIVE, HONGKONG, noVoyage );
-        cargo.delivery().set( delivery( handlingEvent, IN_PORT, notArrived,
-                                        ROUTED, directed, unknownETA, unknownLeg,
-                                        nextHandlingEvent( LOAD, HONGKONG, DAY1, V201 ) ) );
-
-        // New itinerary going from current port
-        itinerary2 = itinerary( leg( V202, HONGKONG, STOCKHOLM, DAY3, DAY17 ) );
-
-        // Re-route cargo after receipt in port
-        new AssignCargoToRoute( cargo, itinerary2 ).assign();
-        assertDelivery( RECEIVE, HONGKONG, DAY1, noVoyage,
-                        IN_PORT, notArrived,
-                        ROUTED, directed, itinerary2.eta(), leg1,
-                        LOAD, HONGKONG, DAY3, V202 ); // from new itinerary!
-    }
-
-    @Test
-    public void deviation_3c_ReRouting_InPort_Unloaded()
-        throws Exception
-    {
-        deviation_3c_ReRouting_InPort_Received();
-
-        // Unload cargo
-        cargo.itinerary().set( itinerary );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY5, DAY5, trackingId, UNLOAD, CHICAGO, V201 );
-        cargo.delivery().set( delivery( handlingEvent, IN_PORT, notArrived,
-                                        ROUTED, directed, unknownETA, leg2,
-                                        nextHandlingEvent( UNLOAD, NEWYORK, DAY6, V201 ) ) );
-
-        // Re-route cargo unloaded in port
-        itinerary2 = itinerary( leg( V202, CHICAGO, STOCKHOLM, DAY6, DAY19 ) );
-        new AssignCargoToRoute( cargo, itinerary2 ).assign();
-        assertDelivery( UNLOAD, CHICAGO, DAY5, V201,
-                        IN_PORT, notArrived,
-                        ROUTED, directed, itinerary2.eta(), leg1,
-                        LOAD, CHICAGO, DAY6, V202 );
-    }
-
-    @Test
-    public void deviation_3c_ReRouting_InPort_InCustoms()
-        throws Exception
-    {
-        deviation_3c_ReRouting_InPort_Unloaded();
-
-        // Receive cargo
-        cargo.itinerary().set( itinerary );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY6, DAY6, trackingId, CUSTOMS, NEWYORK, noVoyage );
-        cargo.delivery().set( delivery( handlingEvent, IN_PORT, notArrived,
-                                        ROUTED, directed, unknownETA, leg3,
-                                        unknownNextHandlingEvent ) );
-
-        // Re-route cargo while in customs
-        itinerary2 = itinerary( leg( V202, NEWYORK, STOCKHOLM, DAY8, DAY18 ) );
-        new AssignCargoToRoute( cargo, itinerary2 ).assign();
-        assertDelivery( CUSTOMS, NEWYORK, DAY6, noVoyage,
-                        IN_PORT, notArrived,
-                        ROUTED, directed, itinerary2.eta(), leg1,
-                        LOAD, NEWYORK, DAY8, V202 );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/booking/routing/RegisterNewDestinationTest.java b/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/booking/routing/RegisterNewDestinationTest.java
deleted file mode 100644
index 38c548f..0000000
--- a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/booking/routing/RegisterNewDestinationTest.java
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.test.booking.routing;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.test.TestApplication;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.exception.ChangeDestinationException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.routing.RegisterNewDestination;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoMisroutedException;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.CargoAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.HandlingEventAggregateRoot;
-
-import static org.junit.Assert.fail;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.MISROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.NOT_ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.CLAIMED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.IN_PORT;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.NOT_RECEIVED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.ONBOARD_CARRIER;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.CUSTOMS;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.LOAD;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.RECEIVE;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.UNLOAD;
-
-/**
- * {@link RegisterNewDestination} tests
- *
- * FIXME: Every test method call the one above to allow ordered execution, ie. tests are not indepedants !
- */
-public class RegisterNewDestinationTest extends TestApplication
-{
-    private HandlingEventAggregateRoot HANDLING_EVENTS;
-
-    @Before
-    public void prepareTest()
-        throws Exception
-    {
-        super.prepareTest();
-        UnitOfWork uow = module.currentUnitOfWork();
-        HANDLING_EVENTS = uow.get( HandlingEventAggregateRoot.class, HandlingEventAggregateRoot.HANDLING_EVENTS_ID );
-        CargoAggregateRoot CARGOS = uow.get( CargoAggregateRoot.class, CargoAggregateRoot.CARGOS_ID );
-
-        // Create new cargo
-        routeSpec = routeSpecFactory.build( HONGKONG, STOCKHOLM, TODAY, deadline = DAY24 );
-        delivery = delivery( TODAY, NOT_RECEIVED, NOT_ROUTED, leg1 );
-        cargo = CARGOS.createCargo( routeSpec, delivery, "ABC" );
-        trackingId = cargo.trackingId().get();
-        delivery = cargo.delivery().get();
-    }
-
-    @Test
-    public void precondition_x1_CannotChangeDestinationOfClaimedCargo()
-        throws Exception
-    {
-        cargo.delivery().set( delivery( DAY1, CLAIMED, ROUTED, leg1 ) );
-        thrown.expect( ChangeDestinationException.class, "Can't change destination of claimed cargo" );
-        new RegisterNewDestination( cargo ).to( "USCHI" );
-    }
-
-    @Test
-    public void deviation_1a_UnrecognizedLocation()
-        throws Exception
-    {
-        precondition_x1_CannotChangeDestinationOfClaimedCargo();
-
-        cargo.delivery().set( delivery( DAY1, IN_PORT, ROUTED, leg1 ) );
-        thrown.expect( ChangeDestinationException.class, "Didn't recognize location 'XXXXX'" );
-        new RegisterNewDestination( cargo ).to( "XXXXX" );
-    }
-
-    @Test
-    public void deviation_1b_NewDestinationSameAsOldDestination()
-        throws Exception
-    {
-        deviation_1a_UnrecognizedLocation();
-
-        cargo.delivery().set( delivery( DAY1, IN_PORT, ROUTED, leg1 ) );
-        thrown.expect( ChangeDestinationException.class, "New destination is same as old destination." );
-        new RegisterNewDestination( cargo ).to( "SESTO" );
-    }
-
-    @Test
-    public void step_2_NotRouted()
-        throws Exception
-    {
-        deviation_1b_NewDestinationSameAsOldDestination();
-
-        cargo.routeSpecification().set( routeSpec );
-        cargo.delivery().set( delivery( DAY1, NOT_RECEIVED, NOT_ROUTED, leg1 ) );
-
-        assertRouteSpec( HONGKONG, STOCKHOLM, TODAY, DAY24 );
-        assertDelivery( null, null, null, null,
-                        NOT_RECEIVED, notArrived,
-                        NOT_ROUTED, directed, unknownETA, unknownLeg,
-                        unknownNextHandlingEvent );
-
-        new RegisterNewDestination( cargo ).to( "CNSHA" );
-
-        assertRouteSpec( HONGKONG, SHANGHAI, TODAY, DAY24 );
-        assertDelivery( null, null, null, null,
-                        NOT_RECEIVED, notArrived,
-                        NOT_ROUTED, directed, unknownETA, unknownLeg,
-                        RECEIVE, HONGKONG, noSpecificDate, noVoyage );
-    }
-
-    @Test
-    public void step_2_NotReceived()
-        throws Exception
-    {
-        step_2_NotRouted();
-
-        cargo.routeSpecification().set( routeSpec );
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( null, NOT_RECEIVED, notArrived,
-                                        ROUTED, directed, itinerary.eta(), leg1,
-                                        nextHandlingEvent( RECEIVE, HONGKONG, noSpecificDate, noVoyage ) ) );
-
-        assertRouteSpec( HONGKONG, STOCKHOLM, TODAY, DAY24 );
-
-        // No last handling event
-        assertDelivery( null, null, null, null,
-                        NOT_RECEIVED, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg1,
-                        RECEIVE, HONGKONG, noSpecificDate, noVoyage );
-
-        new RegisterNewDestination( cargo ).to( "CNSHA" );
-
-        // Destination changed, deadline is the same
-        assertRouteSpec( HONGKONG, SHANGHAI, TODAY, DAY24 );
-
-        /**
-         * Delivery status was updated in {@link InspectUnhandledCargo}
-         * Still expects receipt in cargo origin (Hong Kong).
-         * */
-        assertDelivery( null, null, null, null,
-                        NOT_RECEIVED, notArrived,
-                        MISROUTED, directed, unknownETA, unknownLeg,
-                        RECEIVE, HONGKONG, noSpecificDate, noVoyage );
-    }
-
-    @Test
-    public void step_2_Received()
-        throws Exception
-    {
-        step_2_NotReceived();
-
-        cargo.routeSpecification().set( routeSpec );
-        cargo.itinerary().set( itinerary );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, RECEIVE, HONGKONG, noVoyage );
-        cargo.delivery().set( delivery( handlingEvent, IN_PORT, notArrived,
-                                        ROUTED, directed, itinerary.eta(), leg1,
-                                        nextHandlingEvent( LOAD, HONGKONG, DAY1, V201 ) ) );
-
-        assertRouteSpec( HONGKONG, STOCKHOLM, TODAY, DAY24 );
-        assertDelivery( RECEIVE, HONGKONG, DAY1, noVoyage,
-                        IN_PORT, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg1,
-                        LOAD, HONGKONG, DAY1, V201 );
-
-        new RegisterNewDestination( cargo ).to( "CNSHA" );
-
-        assertRouteSpec( HONGKONG,  // Unchanged
-                         SHANGHAI,  // New destination
-                         DAY1,      // Completion time of last handling event
-                         DAY24 );   // Unchanged
-
-        /**
-         * Delivery status was updated in {@link InspectReceivedCargo}
-         * Before cargo has been re-routed we don't know which voyage the cargo is going with next.
-         * */
-        assertDelivery( RECEIVE, HONGKONG, DAY1, noVoyage,
-                        IN_PORT, notArrived,
-                        MISROUTED, directed, unknownETA, unknownLeg,
-                        unknownNextHandlingEvent );
-    }
-
-    @Test
-    public void deviation_2a_OnBoardCarrier()
-        throws Exception
-    {
-        step_2_Received();
-
-        cargo.routeSpecification().set( routeSpec );
-        cargo.itinerary().set( itinerary );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, LOAD, HONGKONG, V201 );
-        cargo.delivery().set( delivery( handlingEvent, ONBOARD_CARRIER, notArrived,
-                                        ROUTED, directed, itinerary.eta(), leg1,
-                                        nextHandlingEvent( UNLOAD, CHICAGO, DAY5, V201 ) ) );
-
-        assertRouteSpec( HONGKONG, STOCKHOLM, TODAY, DAY24 );
-        assertDelivery( LOAD, HONGKONG, DAY1, V201,
-                        ONBOARD_CARRIER, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg1,
-                        UNLOAD, CHICAGO, DAY5, V201 );
-        try
-        {
-            new RegisterNewDestination( cargo ).to( "CNSHA" );
-            fail();
-        }
-        catch( CargoMisroutedException e )
-        {
-            assertMessage( e, "MISROUTED! Route specification is not satisfied with itinerary" );
-            assertRouteSpec( CHICAGO,   // Arrival location of current carrier movement
-                             SHANGHAI,  // New destination
-                             DAY5,      // Arrival time of current carrier movement
-                             DAY24 );   // Unchanged
-
-            /**
-             * Delivery status was updated in {@link InspectLoadedCargo}
-             * We still expect unload in Chicago
-             * */
-            assertDelivery( LOAD, HONGKONG, DAY1, V201,
-                            ONBOARD_CARRIER, notArrived,
-                            MISROUTED, directed, unknownETA, unknownLeg,
-                            UNLOAD, CHICAGO, DAY5, V201 );
-        }
-    }
-
-    @Test
-    public void deviation_2b_InPort_Unloaded()
-        throws Exception
-    {
-        deviation_2a_OnBoardCarrier();
-
-        cargo.routeSpecification().set( routeSpec );
-        cargo.itinerary().set( itinerary );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY5, DAY5, trackingId, UNLOAD, CHICAGO, V201 );
-        cargo.delivery().set( delivery( handlingEvent, IN_PORT, notArrived,
-                                        ROUTED, directed, itinerary.eta(), leg2,
-                                        nextHandlingEvent( LOAD, CHICAGO, DAY5, V201 ) ) );
-
-        assertRouteSpec( HONGKONG, STOCKHOLM, TODAY, DAY24 );
-        assertDelivery( UNLOAD, CHICAGO, DAY5, V201,
-                        IN_PORT, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg2,
-                        LOAD, CHICAGO, DAY5, V201 );
-        try
-        {
-            new RegisterNewDestination( cargo ).to( "CNSHA" );
-            fail();
-        }
-        catch( CargoMisroutedException e )
-        {
-            assertMessage( e, "MISROUTED! Route specification is not satisfied with itinerary" );
-            assertRouteSpec( CHICAGO,   // Current location
-                             SHANGHAI,  // New destination
-                             DAY5,      // Last completion time
-                             DAY24 );   // Unchanged
-
-            /**
-             *  Delivery status was updated in {@link InspectUnloadedCargo}
-             *  We still expect unload in Chicago
-             * */
-            assertDelivery( UNLOAD, CHICAGO, DAY5, V201,
-                            IN_PORT, notArrived,
-                            MISROUTED, directed, unknownETA, unknownLeg,
-                            unknownNextHandlingEvent );
-        }
-    }
-
-    @Test
-    public void deviation_2b_InPort_InCustoms()
-        throws Exception
-    {
-        deviation_2b_InPort_Unloaded();
-
-        cargo.routeSpecification().set( routeSpec );
-        cargo.itinerary().set( itinerary );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY5, DAY5, trackingId, CUSTOMS, CHICAGO, noVoyage );
-        cargo.delivery().set( delivery( handlingEvent, IN_PORT, notArrived,
-                                        ROUTED, directed, itinerary.eta(), leg2,
-                                        unknownNextHandlingEvent ) );
-
-        assertRouteSpec( HONGKONG, STOCKHOLM, TODAY, DAY24 );
-        assertDelivery( CUSTOMS, CHICAGO, DAY5, noVoyage,
-                        IN_PORT, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg2,
-                        unknownNextHandlingEvent );
-
-        new RegisterNewDestination( cargo ).to( "CNSHA" );
-
-        assertRouteSpec( CHICAGO,   // Current location
-                         SHANGHAI,  // New destination
-                         DAY5,      // Last completion time
-                         DAY24 );   // Unchanged
-
-        /**
-         * Delivery status was updated in {@link InspectCargoInCustoms}
-         * We still expect unload in Chicago
-         */
-        assertDelivery( CUSTOMS, CHICAGO, DAY5, noVoyage,
-                        IN_PORT, notArrived,
-                        MISROUTED, directed, unknownETA, unknownLeg,
-                        unknownNextHandlingEvent );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/booking/specification/DeriveUpdatedRouteSpecTest.java b/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/booking/specification/DeriveUpdatedRouteSpecTest.java
deleted file mode 100644
index 7b859f0..0000000
--- a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/booking/specification/DeriveUpdatedRouteSpecTest.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.test.booking.specification;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.test.TestApplication;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.booking.specification.DeriveUpdatedRouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.CargoAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.HandlingEventAggregateRoot;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.IN_PORT;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.NOT_RECEIVED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.ONBOARD_CARRIER;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.LOAD;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.RECEIVE;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.UNLOAD;
-
-public class DeriveUpdatedRouteSpecTest extends TestApplication
-{
-    private HandlingEventAggregateRoot HANDLING_EVENTS;
-
-    @Before
-    public void prepareTest()
-        throws Exception
-    {
-        super.prepareTest();
-        UnitOfWork uow = module.currentUnitOfWork();
-        HANDLING_EVENTS = uow.get( HandlingEventAggregateRoot.class, HandlingEventAggregateRoot.HANDLING_EVENTS_ID );
-        CargoAggregateRoot CARGOS = uow.get( CargoAggregateRoot.class, CargoAggregateRoot.CARGOS_ID );
-
-        // Create new cargo
-        routeSpec = routeSpecFactory.build( HONGKONG, STOCKHOLM, TODAY, deadline = DAY24 );
-        delivery = delivery( TODAY, NOT_RECEIVED, ROUTED, unknownLeg );
-        cargo = CARGOS.createCargo( routeSpec, delivery, "ABC" );
-        cargo.itinerary().set( itinerary );
-        trackingId = cargo.trackingId().get();
-    }
-
-    @Test
-    public void deviation_1a_Destination_changed()
-        throws Exception
-    {
-        cargo.routeSpecification().set( routeSpec );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, RECEIVE, HONGKONG, noVoyage );
-        cargo.delivery().set( delivery( handlingEvent, IN_PORT, notArrived,
-                                        ROUTED, directed, itinerary.eta(), leg1,
-                                        nextHandlingEvent( LOAD, HONGKONG, DAY1, V201 ) ) );
-
-        assertRouteSpec( HONGKONG, STOCKHOLM, TODAY, DAY24 );
-
-        newRouteSpec = new DeriveUpdatedRouteSpecification( cargo, ROTTERDAM ).getRouteSpec();
-        cargo.routeSpecification().set( newRouteSpec );
-
-        assertRouteSpec( HONGKONG,  // Unchanged
-                         ROTTERDAM, // New destination
-                         DAY1,      // Completion time of last handling event
-                         DAY24 );   // Unchanged
-    }
-
-    @Test
-    public void step_1_Destination_unchanged()
-        throws Exception
-    {
-        cargo.routeSpecification().set( routeSpec );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, RECEIVE, HONGKONG, noVoyage );
-        cargo.delivery().set( delivery( handlingEvent, IN_PORT, notArrived,
-                                        ROUTED, directed, itinerary.eta(), leg1,
-                                        nextHandlingEvent( LOAD, HONGKONG, DAY1, V201 ) ) );
-
-        assertRouteSpec( HONGKONG, STOCKHOLM, TODAY, DAY24 );
-
-        newRouteSpec = new DeriveUpdatedRouteSpecification( cargo ).getRouteSpec();
-        cargo.routeSpecification().set( newRouteSpec );
-
-        assertRouteSpec( HONGKONG,  // Unchanged
-                         STOCKHOLM, // Unchanged
-                         DAY1,      // Completion time of last handling event
-                         DAY24 );   // Unchanged
-    }
-
-    @Test
-    public void deviation_2a_NotReceived()
-        throws Exception
-    {
-        cargo.routeSpecification().set( routeSpec );
-        cargo.delivery().set( delivery( TODAY, NOT_RECEIVED, ROUTED, unknownLeg ) );
-
-        assertRouteSpec( HONGKONG, STOCKHOLM, TODAY, DAY24 );
-
-        newRouteSpec = new DeriveUpdatedRouteSpecification( cargo ).getRouteSpec();
-        cargo.routeSpecification().set( newRouteSpec );
-
-        assertRouteSpec( HONGKONG,  // Unchanged
-                         STOCKHOLM, // Unchanged
-                         TODAY,     // Unchanged
-                         DAY24 );   // Unchanged
-    }
-
-    @Test
-    public void deviation_2b_OnBoardCarrier()
-        throws Exception
-    {
-        cargo.routeSpecification().set( routeSpec );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, LOAD, HONGKONG, V201 );
-        cargo.delivery().set( delivery( handlingEvent, ONBOARD_CARRIER, notArrived,
-                                        ROUTED, directed, itinerary.eta(), leg1,
-                                        nextHandlingEvent( UNLOAD, CHICAGO, DAY5, V201 ) ) );
-
-        assertRouteSpec( HONGKONG, STOCKHOLM, TODAY, DAY24 );
-
-        newRouteSpec = new DeriveUpdatedRouteSpecification( cargo ).getRouteSpec();
-        cargo.routeSpecification().set( newRouteSpec );
-
-        assertRouteSpec( CHICAGO,   // Arrival location of current carrier movement
-                         STOCKHOLM, // Unchanged
-                         DAY5,      // Arrival time of current carrier movement
-                         DAY24 );   // Unchanged
-    }
-
-    @Test
-    public void step_3_InPort()
-        throws Exception
-    {
-        cargo.routeSpecification().set( routeSpec );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY5, DAY5, trackingId, UNLOAD, CHICAGO, V201 );
-        cargo.delivery().set( delivery( handlingEvent, IN_PORT, notArrived,
-                                        ROUTED, directed, itinerary.eta(), leg2,
-                                        nextHandlingEvent( LOAD, CHICAGO, DAY5, V201 ) ) );
-
-        assertRouteSpec( HONGKONG, STOCKHOLM, TODAY, DAY24 );
-
-        newRouteSpec = new DeriveUpdatedRouteSpecification( cargo ).getRouteSpec();
-        cargo.routeSpecification().set( newRouteSpec );
-
-        assertRouteSpec( CHICAGO,   // Current location
-                         STOCKHOLM, // Unchanged
-                         DAY5,      // Last completion time
-                         DAY24 );   // Unchanged
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectArrivedCargoTest.java b/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectArrivedCargoTest.java
deleted file mode 100644
index df136e2..0000000
--- a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectArrivedCargoTest.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.test.handling.inspection.event;
-
-import java.util.Date;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.test.TestApplication;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectArrivedCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoArrivedException;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.CargoAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.HandlingEventAggregateRoot;
-
-import static org.junit.Assert.fail;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.MISROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.NOT_ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.IN_PORT;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.ONBOARD_CARRIER;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.CLAIM;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.UNLOAD;
-
-/**
- * {@link InspectArrivedCargo} tests
- */
-public class InspectArrivedCargoTest extends TestApplication
-{
-    private HandlingEventAggregateRoot HANDLING_EVENTS;
-
-    @Before
-    public void prepareTest()
-        throws Exception
-    {
-        super.prepareTest();
-        UnitOfWork uow = module.currentUnitOfWork();
-        HANDLING_EVENTS = uow.get( HandlingEventAggregateRoot.class, HandlingEventAggregateRoot.HANDLING_EVENTS_ID );
-        CargoAggregateRoot CARGOS = uow.get( CargoAggregateRoot.class, CargoAggregateRoot.CARGOS_ID );
-
-        // Create new cargo
-        routeSpec = routeSpecFactory.build( HONGKONG, STOCKHOLM, new Date(), deadline = DAY24 );
-        delivery = delivery( TODAY, IN_PORT, ROUTED, leg5 );
-        cargo = CARGOS.createCargo( routeSpec, delivery, "Arrived_CARGO" );
-        trackingId = cargo.trackingId().get();
-    }
-
-    @Test
-    public void deviation_2a_NotRouted_MissingItinerary_UnloadedInFinalDestination()
-        throws Exception
-    {
-        // Cargo not routed
-        cargo.itinerary().set( null );
-        cargo.delivery().set( delivery( TODAY, ONBOARD_CARRIER, NOT_ROUTED, leg5 ) );
-
-        // Unload in final destination (with no itinerary!)
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY23, DAY23, trackingId, UNLOAD, STOCKHOLM, V203 );
-        try
-        {
-            new InspectArrivedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( CargoArrivedException e )
-        {
-            assertMessage( e, "Cargo 'Arrived_CARGO' has arrived in destination Stockholm (SESTO)" );
-
-            // An unexpected unload shouldn't be considered an itinerary progress - legIndex stays unchanged
-            assertDelivery( UNLOAD, STOCKHOLM, DAY23, V203,
-                            IN_PORT, arrived,
-                            NOT_ROUTED, directed, unknownETA, unknownLeg,
-                            CLAIM, STOCKHOLM, DAY23, noVoyage );
-        }
-    }
-
-    @Test
-    public void deviation_2b_Misrouted_WrongItineraryWithoutCurrentUnloadLocation_UnloadedInFinalDestination()
-        throws Exception
-    {
-        // Misroute cargo - assign unsatisfying itinerary not going to Stockholm
-        cargo.itinerary().set( wrongItinerary );
-        cargo.delivery().set( delivery( TODAY, ONBOARD_CARRIER, MISROUTED, leg5 ) );
-
-        // Unload in final destination (with wrong itinerary)
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY23, DAY23, trackingId, UNLOAD, STOCKHOLM, V203 );
-        try
-        {
-            new InspectArrivedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( CargoArrivedException e )
-        {
-            assertMessage( e, "Cargo 'Arrived_CARGO' has arrived in destination Stockholm (SESTO)" );
-            assertDelivery( UNLOAD, STOCKHOLM, DAY23, V203,
-                            IN_PORT, arrived,
-                            MISROUTED, directed, unknownETA, unknownLeg,
-                            CLAIM, STOCKHOLM, DAY23, noVoyage );
-        }
-    }
-
-    @Test
-    public void success_UnloadInDestination()
-        throws Exception
-    {
-        // Assign satisfying route going to Stockholm
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, ONBOARD_CARRIER, ROUTED, leg5 ) );
-
-        // Unload in final destination (with satisfying itinerary)
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY23, DAY23, trackingId, UNLOAD, STOCKHOLM, V203 );
-        try
-        {
-            new InspectArrivedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( CargoArrivedException e )
-        {
-            assertMessage( e, "Cargo 'Arrived_CARGO' has arrived in destination Stockholm (SESTO)" );
-            assertDelivery( UNLOAD, STOCKHOLM, DAY23, V203,
-                            IN_PORT, arrived,
-                            ROUTED, directed, itinerary.eta(), leg5,
-                            CLAIM, STOCKHOLM, DAY23, noVoyage );
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectCargoInCustomsTest.java b/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectCargoInCustomsTest.java
deleted file mode 100644
index 6d58924..0000000
--- a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectCargoInCustomsTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.test.handling.inspection.event;
-
-import java.util.Date;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.test.TestApplication;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectCargoInCustoms;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionFailedException;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.CargoAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.HandlingEventAggregateRoot;
-
-import static org.junit.Assert.fail;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.MISROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.NOT_ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.IN_PORT;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.ONBOARD_CARRIER;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.CUSTOMS;
-
-/**
- * {@link InspectCargoInCustoms} tests
- */
-public class InspectCargoInCustomsTest extends TestApplication
-{
-    private HandlingEventAggregateRoot HANDLING_EVENTS;
-
-    @Before
-    public void prepareTest()
-        throws Exception
-    {
-        super.prepareTest();
-        UnitOfWork uow = module.currentUnitOfWork();
-        HANDLING_EVENTS = uow.get( HandlingEventAggregateRoot.class, HandlingEventAggregateRoot.HANDLING_EVENTS_ID );
-        CargoAggregateRoot CARGOS = uow.get( CargoAggregateRoot.class, CargoAggregateRoot.CARGOS_ID );
-
-        // Create new cargo
-        routeSpec = routeSpecFactory.build( HONGKONG, STOCKHOLM, new Date(), deadline = DAY24 );
-        delivery = delivery( TODAY, IN_PORT, ROUTED, leg1 );
-        cargo = CARGOS.createCargo( routeSpec, delivery, "CARGO_in_customs" );
-        trackingId = cargo.trackingId().get();
-    }
-
-    @Test
-    public void precondition_CustomsHandlingNotOnBoardCarrier()
-        throws Exception
-    {
-        cargo.itinerary().set( itinerary );
-
-        // No customs handling on board a carrier...
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, CUSTOMS, STOCKHOLM, noVoyage );
-        cargo.delivery().set( delivery( handlingEvent, ONBOARD_CARRIER, notArrived,
-                                        ROUTED, directed, unknownETA, unknownLeg,
-                                        unknownNextHandlingEvent ) );
-        try
-        {
-            new InspectCargoInCustoms( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( InspectionFailedException e )
-        {
-            assertMessage( e, "INTERNAL ERROR: Cannot handle cargo in customs on board a carrier." );
-        }
-    }
-
-    @Test
-    public void deviation_2a_NotRouted_CustomsLocation_FinalDestination()
-        throws Exception
-    {
-        // Cargo not routed
-        cargo.itinerary().set( null );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, NOT_ROUTED, leg5 ) );
-
-        // Handle in customs (without itinerary!)
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, CUSTOMS, STOCKHOLM, noVoyage );
-        new InspectCargoInCustoms( cargo, handlingEvent ).inspect();
-
-        assertDelivery( CUSTOMS, STOCKHOLM, DAY1, noVoyage,
-                        IN_PORT, notArrived,
-                        NOT_ROUTED, directed, unknownETA, unknownLeg,
-                        unknownNextHandlingEvent );
-    }
-
-    @Test
-    public void deviation_2b_Misrouted_CustomsLocation_DestinationOfWrongItinerary()
-        throws Exception
-    {
-        // Misroute cargo - assign unsatisfying itinerary not going to Stockholm
-        cargo.itinerary().set( wrongItinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, MISROUTED, leg3 ) );
-
-        // Handle in customs (with wrong itinerary)
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY20, DAY20, trackingId, CUSTOMS, MELBOURNE, noVoyage );
-        new InspectCargoInCustoms( cargo, handlingEvent ).inspect();
-
-        assertDelivery( CUSTOMS, MELBOURNE, DAY20, noVoyage,
-                        IN_PORT, notArrived,
-                        MISROUTED, directed, unknownETA, unknownLeg,
-                        unknownNextHandlingEvent );
-    }
-
-    @Test
-    public void step_2_Routed_CustomsLocation_FinalDestination()
-        throws Exception
-    {
-        // Assign satisfying route going to Stockholm
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, MISROUTED, leg5 ) );
-
-        // Handle in customs (without itinerary!)
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY24, DAY24, trackingId, CUSTOMS, STOCKHOLM, noVoyage );
-        new InspectCargoInCustoms( cargo, handlingEvent ).inspect();
-
-        assertDelivery( CUSTOMS, STOCKHOLM, DAY24, noVoyage,
-                        IN_PORT, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg5,
-                        unknownNextHandlingEvent );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectClaimedCargoTest.java b/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectClaimedCargoTest.java
deleted file mode 100644
index 95ae56f..0000000
--- a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectClaimedCargoTest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.test.handling.inspection.event;
-
-import java.util.Date;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.test.TestApplication;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectClaimedCargo;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.CargoAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.HandlingEventAggregateRoot;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.MISROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.NOT_ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.CLAIMED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.IN_PORT;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.CLAIM;
-
-/**
- * {@link InspectClaimedCargo} tests
- */
-public class InspectClaimedCargoTest extends TestApplication
-{
-    private HandlingEventAggregateRoot HANDLING_EVENTS;
-
-    @Before
-    public void prepareTest()
-        throws Exception
-    {
-        super.prepareTest();
-        UnitOfWork uow = module.currentUnitOfWork();
-        HANDLING_EVENTS = uow.get( HandlingEventAggregateRoot.class, HandlingEventAggregateRoot.HANDLING_EVENTS_ID );
-        CargoAggregateRoot CARGOS = uow.get( CargoAggregateRoot.class, CargoAggregateRoot.CARGOS_ID );
-
-        // Create new cargo
-        routeSpec = routeSpecFactory.build( HONGKONG, STOCKHOLM, new Date(), deadline = DAY24 );
-        delivery = delivery( TODAY, IN_PORT, ROUTED, leg1 );
-        cargo = CARGOS.createCargo( routeSpec, delivery, "Claimed_CARGO" );
-        trackingId = cargo.trackingId().get();
-    }
-
-    @Test
-    public void deviation_2a_NotRouted_ClaimInFinalDestination()
-        throws Exception
-    {
-        // Cargo not routed
-        cargo.itinerary().set( null );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, NOT_ROUTED, leg5 ) );
-
-        // Claim in final destination (without itinerary!)
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, CLAIM, STOCKHOLM, noVoyage );
-
-        new InspectClaimedCargo( cargo, handlingEvent ).inspect();
-
-        assertDelivery( CLAIM, STOCKHOLM, DAY1, noVoyage,
-                        CLAIMED, notArrived,
-                        NOT_ROUTED, directed, unknownETA, unknownLeg,
-                        unknownNextHandlingEvent );
-    }
-
-    @Test
-    public void deviation_2b_Misrouted_ClaimInDestinationOfWrongItinerary()
-        throws Exception
-    {
-        // Misroute cargo - assign unsatisfying itinerary not going to Stockholm
-        cargo.itinerary().set( wrongItinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, MISROUTED, leg3 ) );
-
-        // Claim in final destination (with wrong itinerary)
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY20, DAY20, trackingId, CLAIM, MELBOURNE, noVoyage );
-        new InspectClaimedCargo( cargo, handlingEvent ).inspect();
-
-        assertDelivery( CLAIM, MELBOURNE, DAY20, noVoyage,
-                        CLAIMED, notArrived,
-                        MISROUTED, directed, unknownETA, unknownLeg,
-                        unknownNextHandlingEvent );
-    }
-
-    @Test
-    public void step_2_Routed_ClaimInMidpointLocation()
-        throws Exception
-    {
-        // Assign satisfying route going to Stockholm
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, ROUTED, leg3 ) );
-
-        // Claim in midpoint before arrival at final destination
-        // Should this really be considered misdirected?!
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY9, DAY9, trackingId, CLAIM, DALLAS, noVoyage );
-        new InspectClaimedCargo( cargo, handlingEvent ).inspect();
-
-        assertDelivery( CLAIM, DALLAS, DAY9, noVoyage,
-                        CLAIMED, notArrived,
-                        ROUTED, misdirected, itinerary.eta(), leg3,
-                        unknownNextHandlingEvent );
-    }
-
-    @Test
-    public void step_2_Routed_ClaimInFinalDestination()
-        throws Exception
-    {
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, ROUTED, leg5 ) );
-
-        // Claim in final destination
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY24, DAY24, trackingId, CLAIM, STOCKHOLM, noVoyage );
-        new InspectClaimedCargo( cargo, handlingEvent ).inspect();
-
-        assertDelivery( CLAIM, STOCKHOLM, DAY24, noVoyage,
-                        CLAIMED, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg5,
-                        unknownNextHandlingEvent );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectLoadedCargoTest.java b/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectLoadedCargoTest.java
deleted file mode 100644
index c436024..0000000
--- a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectLoadedCargoTest.java
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.test.handling.inspection.event;
-
-import java.util.Date;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.test.TestApplication;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectLoadedCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoHijackedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoMisdirectedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoMisroutedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoNotRoutedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionFailedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.UnexpectedCarrierException;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.CargoAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.HandlingEventAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.cargo.RouteSpecification;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.Delivery;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Leg;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.MISROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.NOT_ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.IN_PORT;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.ONBOARD_CARRIER;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.LOAD;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.UNLOAD;
-
-/**
- * {@link InspectLoadedCargo} tests
- *
- * FIXME: Every test method call the one above to allow ordered execution, ie. tests are not indepedants !
- */
-public class InspectLoadedCargoTest extends TestApplication
-{
-    private HandlingEventAggregateRoot HANDLING_EVENTS;
-    private CargoAggregateRoot CARGOS;
-
-    @Before
-    public void prepareTest()
-        throws Exception
-    {
-        super.prepareTest();
-        UnitOfWork uow = module.currentUnitOfWork();
-        CARGOS = uow.get( CargoAggregateRoot.class, CargoAggregateRoot.CARGOS_ID );
-        HANDLING_EVENTS = uow.get( HandlingEventAggregateRoot.class, HandlingEventAggregateRoot.HANDLING_EVENTS_ID );
-        // Create new cargo
-        RouteSpecification routeSpec = routeSpecFactory.build( HONGKONG, STOCKHOLM, TODAY, deadline = DAY24 );
-        Delivery delivery = delivery( TODAY, IN_PORT, ROUTED, leg1 );
-        cargo = CARGOS.createCargo( routeSpec, delivery, "Loaded_CARGO" );
-        trackingId = cargo.trackingId().get();
-//        delivery = cargo.delivery().get();
-    }
-
-    @Test
-    public void deviation_2a_WrongCarrierSchedule()
-        throws Exception
-    {
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, ROUTED, leg1 ) );
-
-        // V202 doesn't expect a load in Hongkong - can't determine much more before we get a correct voyage schedule
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, LOAD, HONGKONG, V202 );
-        try
-        {
-            new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( UnexpectedCarrierException e )
-        {
-            assertMessage( e, "Carrier of voyage V202 didn't expect a load in Hongkong (CNHKG)" );
-            assertDelivery( LOAD, HONGKONG, DAY1, V202,
-                            ONBOARD_CARRIER, notArrived,
-                            ROUTED, misdirected, unknownETA, unknownLeg,
-                            unknownNextHandlingEvent );
-        }
-    }
-
-    @Test
-    public void deviation_2a_CarrierOnTime_ArrivalDate_Planned()
-        throws Exception
-    {
-        deviation_2a_WrongCarrierSchedule();
-
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, ROUTED, leg1 ) );
-
-        //
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, LOAD, HONGKONG, V201 );
-        new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-        assertDelivery( LOAD, HONGKONG, DAY1, V201,
-                        ONBOARD_CARRIER, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg1,
-                        UNLOAD, CHICAGO, DAY5, V201 );   // Arrival date 1 is planned
-    }
-
-    @Test
-    public void deviation_2a_CarrierDelayed_ArrivalDate_Estimated()
-        throws Exception
-    {
-        deviation_2a_CarrierOnTime_ArrivalDate_Planned();
-
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, ROUTED, leg1 ) );
-
-        //
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY2, DAY2, trackingId, LOAD, HONGKONG, V201 );
-        new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-        assertDelivery( LOAD, HONGKONG, DAY2, V201,
-                        ONBOARD_CARRIER, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg1,
-                        UNLOAD, CHICAGO, DAY6, V201 );  // Arrival date has been postponed 1 day
-    }
-
-    @Test
-    public void deviation_3a_NotRouted_MissingItinerary()
-        throws Exception
-    {
-        deviation_2a_CarrierDelayed_ArrivalDate_Estimated();
-
-        // Cargo not routed
-        cargo.itinerary().set( null );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, NOT_ROUTED, leg1 ) );
-
-        // Load cargo in Hong Kong (without an itinerary!)
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, LOAD, HONGKONG, V201 );
-        try
-        {
-            new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( CargoNotRoutedException e )
-        {
-            assertMessage( e, "NOT ROUTED while being handled!" );
-            assertDelivery( LOAD, HONGKONG, DAY1, V201,
-                            ONBOARD_CARRIER, notArrived,
-                            NOT_ROUTED, directed, unknownETA, unknownLeg,
-                            UNLOAD, CHICAGO, DAY5, V201 );
-        }
-    }
-
-    @Test
-    public void deviation_3b_Misrouted_LoadLocationOfWrongItinerary_Origin()
-        throws Exception
-    {
-        deviation_3a_NotRouted_MissingItinerary();
-
-        // Misroute cargo - assign unsatisfying itinerary not going to Stockholm
-        cargo.itinerary().set( wrongItinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, MISROUTED, leg1 ) );
-
-        // Load cargo in Hong Kong (with wrong itinerary)
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, LOAD, HONGKONG, V201 );
-        try
-        {
-            // Load in any location is unexpected when itinerary is wrong
-            new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( CargoMisroutedException e )
-        {
-            assertMessage( e, "MISROUTED! Route specification is not satisfied with itinerary" );
-            assertDelivery( LOAD, HONGKONG, DAY1, V201,
-                            ONBOARD_CARRIER, notArrived,
-                            MISROUTED, directed, unknownETA, unknownLeg,
-                            UNLOAD, CHICAGO, DAY5, V201 );
-        }
-    }
-
-    @Test
-    public void deviation_3b_Misrouted_LoadLocationOfWrongItinerary_Midpoint()
-        throws Exception
-    {
-        deviation_3b_Misrouted_LoadLocationOfWrongItinerary_Origin();
-
-        cargo.itinerary().set( wrongItinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, MISROUTED, leg1 ) );
-
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, LOAD, NEWYORK, V201 );
-        thrown.expect( CargoMisroutedException.class, "MISROUTED! Route specification is not satisfied with itinerary" );
-        new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-    }
-
-    @Test
-    public void deviation_3b_Misrouted_LoadLocationOfWrongItinerary_UnplannedLocation()
-        throws Exception
-    {
-        deviation_3b_Misrouted_LoadLocationOfWrongItinerary_Midpoint();
-
-        cargo.itinerary().set( wrongItinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, MISROUTED, leg1 ) );
-
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, LOAD, ROTTERDAM, V205 );
-        thrown.expect( CargoMisroutedException.class, "MISROUTED! Route specification is not satisfied with itinerary" );
-        new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-    }
-
-    @Test
-    public void step_3_Routed()
-        throws Exception
-    {
-        deviation_3b_Misrouted_LoadLocationOfWrongItinerary_UnplannedLocation();
-
-        // Assign satisfying route going to Stockholm
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, ROUTED, leg1 ) );
-
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, LOAD, HONGKONG, V201 );
-        new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-
-        assertDelivery( LOAD, HONGKONG, DAY1, V201,
-                        ONBOARD_CARRIER, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg1,
-                        UNLOAD, CHICAGO, DAY5, V201 );
-    }
-
-    @Test
-    public void deviation_4x_InternalError_InvalidItineraryProgressIndex()
-        throws Exception
-    {
-        step_3_Routed();
-
-        cargo.itinerary().set( itinerary );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, LOAD, HONGKONG, V201 );
-
-        Integer badLegIndex = 7;
-        cargo.delivery().set( delivery( handlingEvent, ONBOARD_CARRIER, notArrived,
-                                        ROUTED, directed, unknownETA, badLegIndex, unknownNextHandlingEvent ) );
-        try
-        {
-            new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( InspectionFailedException e )
-        {
-            assertMessage( e, "INTERNAL ERROR: Itinerary progress index '7' is invalid!" );
-            assertDelivery( LOAD, HONGKONG, DAY1, V201,
-                            ONBOARD_CARRIER, notArrived,
-                            ROUTED, directed, unknownETA, badLegIndex, unknownNextHandlingEvent );
-        }
-    }
-
-    @Test
-    public void deviation_4a_Misdirected_UnexpectedLoadLocation()
-        throws Exception
-    {
-        deviation_4x_InternalError_InvalidItineraryProgressIndex();
-
-        // Move the cargo ahead on the route. Third leg of itinerary expects load in Dallas.
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, ROUTED, leg3 ) );
-
-        // Unexpected load in previous load location of itinerary (onto expected voyage) - can't go back in time.
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY7, DAY5, trackingId, LOAD, ROTTERDAM, V202 );
-        try
-        {
-            new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( CargoMisdirectedException e )
-        {
-            assertMessage( e, "MISDIRECTED! Itinerary expected load in New York (USNYC)" );
-            assertDelivery( LOAD, ROTTERDAM, DAY5, V202,    // Itinerary expected: LOAD, NEWYORK, DAY7, V202
-                            ONBOARD_CARRIER, notArrived,
-                            ROUTED, misdirected, itinerary.eta(), leg3,
-                            unknownNextHandlingEvent );     // When location is wrong we have to investigate...
-        }
-    }
-
-    @Test
-    public void deviation_4b_Misdirected_UnexpectedLoadVoyage_PreviousInItinerary()
-        throws Exception
-    {
-        deviation_4a_Misdirected_UnexpectedLoadLocation();
-
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, ROUTED, leg3 ) );
-
-        // Unexpected load onto previous voyage (in expected location) - can't go back in time.
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY7, DAY7, trackingId, LOAD, NEWYORK, V201 );
-        try
-        {
-            new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( CargoMisdirectedException e )
-        {
-            assertMessage( e, "MISDIRECTED! Itinerary expected load onto voyage V202" );
-            assertDelivery( LOAD, NEWYORK, DAY7, V201,          // Itinerary expected: LOAD, NEWYORK, DAY7, V202
-                            ONBOARD_CARRIER, notArrived,
-                            ROUTED, misdirected, itinerary.eta(), leg3,
-                            UNLOAD, GOTHENBURG, DAY13, V201 );  // Itinerary expected: UNLOAD, DALLAS, DAY8, V202
-        }
-    }
-
-    @Test
-    public void deviation_4b_Misdirected_UnexpectedLoadVoyage_NextInItinerary()
-        throws Exception
-    {
-        deviation_4b_Misdirected_UnexpectedLoadVoyage_PreviousInItinerary();
-
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, ROUTED, leg3 ) );
-
-        // Unexpected load onto future voyage (in expected location) - can't jump ahead in route plan.
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY7, DAY7, trackingId, LOAD, NEWYORK, V203 );
-        thrown.expect( CargoMisdirectedException.class, "MISDIRECTED! Itinerary expected load onto voyage V202" );
-        new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-    }
-
-    @Test
-    public void deviation_4b_Misdirected_UnexpectedLoadVoyage_VoyageNotInItinerary()
-        throws Exception
-    {
-        deviation_4b_Misdirected_UnexpectedLoadVoyage_NextInItinerary();
-
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, ROUTED, leg3 ) );
-
-        // Unexpected load onto voyage not in itinerary
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY7, DAY7, trackingId, LOAD, NEWYORK, V204 );
-        thrown.expect( CargoMisdirectedException.class, "MISDIRECTED! Itinerary expected load onto voyage V202" );
-        new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-    }
-
-    @Test
-    public void deviation_4c_Misdirected_UnexpectedLoadVoyage_Unplanned_ButGoingToWantedLocation()
-        throws Exception
-    {
-        deviation_4b_Misdirected_UnexpectedLoadVoyage_VoyageNotInItinerary();
-
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, ROUTED, leg3 ) );
-
-        // Unexpected load onto voyage not in itinerary - but the carrier is going to our expected arrival location!
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY9, DAY9, trackingId, LOAD, NEWYORK, V205 );
-        try
-        {
-            new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( CargoMisdirectedException e )
-        {
-            assertMessage( e, "MISDIRECTED! Cargo is heading to expected arrival location USDAL but on unexpected voyage V205" );
-            assertDelivery( LOAD, NEWYORK, DAY9, V205,          // Itinerary expected: LOAD, NEWYORK, DAY7, V202
-                            ONBOARD_CARRIER, notArrived,
-                            ROUTED, misdirected, itinerary.eta(), leg3,
-                            UNLOAD, DALLAS, DAY10, V205 );      // Itinerary expected: UNLOAD, DALLAS, DAY8, V202
-        }
-    }
-
-    @Test
-    public void deviation_4d_Misdirected_ExpectedLoadVoyage_UnexpectedNewVoyageSchedule()
-        throws Exception
-    {
-        deviation_4c_Misdirected_UnexpectedLoadVoyage_Unplanned_ButGoingToWantedLocation();
-
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, ROUTED, leg3 ) );
-
-        // Unexpected voyage schedule change
-        V202 = voyage( "V202", schedule(
-            carrierMovement( CHICAGO, NEWYORK, DAY3, DAY5 ),
-            carrierMovement( NEWYORK, HAMBURG, DAY7, DAY15 ),
-            carrierMovement( HAMBURG, ROTTERDAM, DAY16, DAY17 ),
-            carrierMovement( ROTTERDAM, GOTHENBURG, DAY17, DAY19 )
-        ) );
-
-        // Expected load onto voyage - but carrier has changed arrival location!
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY7, DAY7, trackingId, LOAD, NEWYORK, V202 );
-        try
-        {
-            new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( CargoMisdirectedException e )
-        {
-            assertMessage( e, "MISDIRECTED! Itinerary expects voyage V202 to arrive in USDAL but carrier is now going to DEHAM" );
-            assertDelivery( LOAD, NEWYORK, DAY7, V202,          // Itinerary expected: LOAD, NEWYORK, DAY7, V202
-                            ONBOARD_CARRIER, notArrived,
-                            ROUTED, misdirected, itinerary.eta(), leg3,
-                            UNLOAD, HAMBURG, DAY15, V202 );     // Itinerary expected: UNLOAD, DALLAS, DAY8, V202
-        }
-    }
-
-    @Test
-    public void success_Load()
-        throws Exception
-    {
-        deviation_4d_Misdirected_ExpectedLoadVoyage_UnexpectedNewVoyageSchedule();
-
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, IN_PORT, ROUTED, leg3 ) );
-
-        // Restore expected voyage schedule change
-        V202 = voyage( "V202", schedule(
-            carrierMovement( CHICAGO, NEWYORK, DAY3, DAY5 ),
-            carrierMovement( NEWYORK, DALLAS, DAY7, DAY8 ),
-            carrierMovement( DALLAS, ROTTERDAM, DAY10, DAY17 ),
-            carrierMovement( ROTTERDAM, GOTHENBURG, DAY17, DAY19 )
-        ) );
-
-        // Expected load (leg 3)
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY7, DAY7, trackingId, LOAD, NEWYORK, V202 );
-        new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-
-        Leg currentCarrierMovement = itinerary.leg( delivery.itineraryProgressIndex().get() );
-        assertThat( currentCarrierMovement.unloadLocation().get(), is( equalTo( DALLAS ) ) );
-        assertThat( currentCarrierMovement.unloadTime().get(), is( equalTo( DAY8 ) ) );
-        assertThat( currentCarrierMovement.voyage().get(), is( equalTo( V202 ) ) );
-
-        assertDelivery( LOAD, NEWYORK, DAY7, V202,
-                        ONBOARD_CARRIER, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg3,
-                        UNLOAD, DALLAS, DAY8, V202 );
-    }
-
-    @Test
-    public void riskZoneDestination()
-        throws Exception
-    {
-        success_Load();
-
-        // Risk zone destination
-        routeSpec = routeSpecFactory.build( HANGZHOU, ROTTERDAM, new Date(), deadline = DAY24 );
-        delivery = delivery( TODAY, ONBOARD_CARRIER, ROUTED, leg1 );
-        cargo = CARGOS.createCargo( routeSpec, delivery, "Naive" );
-        trackingId = cargo.trackingId().get();
-        itinerary = itinerary(
-            leg( V205, HANGZHOU, MOGADISHU, DAY1, DAY2 ),
-            leg( V205, MOGADISHU, ROTTERDAM, DAY2, DAY4 )
-        );
-        cargo.itinerary().set( itinerary );
-
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, LOAD, HANGZHOU, V205 );
-        cargo.delivery().set( delivery( handlingEvent, ONBOARD_CARRIER, notArrived,
-                                        ROUTED, directed, itinerary.eta(), leg1,
-                                        nextHandlingEvent( UNLOAD, MOGADISHU, DAY2, V205 ) ) );
-
-        assertDelivery( LOAD, HANGZHOU, DAY1, V205,
-                        ONBOARD_CARRIER, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg1,
-                        UNLOAD, MOGADISHU, DAY2, V205 );
-        try
-        {
-            new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-        }
-        catch( CargoHijackedException e )
-        {
-            assertMessage( e, "Cargo 'Naive' was hijacked." );
-            assertDelivery( LOAD, HANGZHOU, DAY1, V205,
-                            TransportStatus.UNKNOWN, notArrived,
-                            ROUTED, directed, itinerary.eta(), leg1,
-                            UNLOAD, MOGADISHU, DAY2, V205 );
-        }
-    }
-
-    @Test
-    public void riskZoneDeparture()
-        throws Exception
-    {
-        riskZoneDestination();
-
-        // Risk zone departure (they know you now, so risk is higher)
-        cargo = CARGOS.createCargo( routeSpec, delivery, "Hopeful" );
-        trackingId = cargo.trackingId().get();
-        cargo.itinerary().set( itinerary ); // Risky itinerary
-
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY2, DAY2, trackingId, LOAD, MOGADISHU, V205 );
-        cargo.delivery().set( delivery( handlingEvent, ONBOARD_CARRIER, notArrived,
-                                        ROUTED, directed, itinerary.eta(), leg2,
-                                        nextHandlingEvent( UNLOAD, ROTTERDAM, DAY4, V205 ) ) );
-
-        assertDelivery( LOAD, MOGADISHU, DAY2, V205,
-                        ONBOARD_CARRIER, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg2,
-                        UNLOAD, ROTTERDAM, DAY4, V205 );
-        try
-        {
-            new InspectLoadedCargo( cargo, handlingEvent ).inspect();
-        }
-        catch( CargoHijackedException e )
-        {
-            assertMessage( e, "Cargo 'Hopeful' was hijacked." );
-            assertDelivery( LOAD, MOGADISHU, DAY2, V205,
-                            TransportStatus.UNKNOWN, notArrived,
-                            ROUTED, directed, itinerary.eta(), leg2,
-                            UNLOAD, ROTTERDAM, DAY4, V205 );
-        }
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectReceivedCargoTest.java b/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectReceivedCargoTest.java
deleted file mode 100644
index 5fd01c5..0000000
--- a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectReceivedCargoTest.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.test.handling.inspection.event;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.test.TestApplication;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectReceivedCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoMisdirectedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionFailedException;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.CargoAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.HandlingEventAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.NextHandlingEvent;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.MISROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.NOT_ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.IN_PORT;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.NOT_RECEIVED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.LOAD;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.RECEIVE;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.UNLOAD;
-
-/**
- * {@link InspectReceivedCargo} tests
- */
-public class InspectReceivedCargoTest extends TestApplication
-{
-    private HandlingEventAggregateRoot HANDLING_EVENTS;
-
-    @Before
-    public void prepareTest()
-        throws Exception
-    {
-        super.prepareTest();
-        UnitOfWork uow = module.currentUnitOfWork();
-        HANDLING_EVENTS = uow.get( HandlingEventAggregateRoot.class, HandlingEventAggregateRoot.HANDLING_EVENTS_ID );
-        CargoAggregateRoot CARGOS = uow.get( CargoAggregateRoot.class, CargoAggregateRoot.CARGOS_ID );
-
-        // Create new cargo
-        routeSpec = routeSpecFactory.build( HONGKONG, STOCKHOLM, TODAY, deadline = DAY24 );
-        delivery = delivery( TODAY, NOT_RECEIVED, NOT_ROUTED, unknownLeg );
-        cargo = CARGOS.createCargo( routeSpec, delivery, "Received_CARGO" );
-        trackingId = cargo.trackingId().get();
-    }
-
-    @Test
-    public void precondition_1_NotHandledBefore()
-        throws Exception
-    {
-        // Handle
-        cargo.itinerary().set( itinerary );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY5, DAY5, trackingId, UNLOAD, CHICAGO, V201 );
-        cargo.delivery().set( delivery( handlingEvent, IN_PORT, notArrived,
-                                        ROUTED, directed, itinerary.eta(), leg2,
-                                        nextHandlingEvent( LOAD, CHICAGO, DAY5, V201 ) ) );
-
-        assertRouteSpec( HONGKONG, STOCKHOLM, TODAY, DAY24 );
-        assertDelivery( UNLOAD, CHICAGO, DAY5, V201,
-                        IN_PORT, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg2,
-                        LOAD, CHICAGO, DAY5, V201 );
-
-        // Receive cargo again
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY2, DAY2, trackingId, RECEIVE, HONGKONG, noVoyage );
-        thrown.expect( InspectionFailedException.class, "INTERNAL ERROR: Can't receive cargo again" );
-        new InspectReceivedCargo( cargo, handlingEvent ).inspect();
-    }
-
-    @Test
-    public void deviation_2a_NotRouted_MissingItinerary()
-        throws Exception
-    {
-        // Cargo not routed
-        cargo.itinerary().set( null );
-        cargo.delivery().set( delivery( TODAY, NOT_RECEIVED, NOT_ROUTED, leg1 ) );
-
-        // Receive cargo in Hong Kong (without an itinerary!)
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, RECEIVE, HONGKONG, noVoyage );
-
-        new InspectReceivedCargo( cargo, handlingEvent ).inspect();
-
-        assertDelivery( RECEIVE, HONGKONG, DAY1, noVoyage,
-                        IN_PORT, notArrived,
-                        NOT_ROUTED, directed, unknownETA, unknownLeg,
-                        unknownNextHandlingEvent );
-    }
-
-    @Test
-    public void deviation_2b_Misrouted_ReceiveLocation_CargoOrigin()
-        throws Exception
-    {
-        // Misroute cargo - assign unsatisfying itinerary not going to Stockholm
-        cargo.itinerary().set( wrongItinerary );
-        cargo.delivery().set( delivery( TODAY, NOT_RECEIVED, MISROUTED, unknownLeg ) );
-
-        assertDelivery( null, null, null, null,
-                        NOT_RECEIVED, notArrived,
-                        MISROUTED, directed, unknownETA, unknownLeg,
-                        unknownNextHandlingEvent );
-
-        // Receive in cargo origin (Hong Kong) having a wrong itinerary
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, RECEIVE, HONGKONG, noVoyage );
-        new InspectReceivedCargo( cargo, handlingEvent ).inspect();
-
-        // Remains misrouted and directed
-        assertDelivery( RECEIVE, HONGKONG, DAY1, noVoyage,
-                        IN_PORT, notArrived,
-                        MISROUTED, directed, unknownETA, unknownLeg,
-                        unknownNextHandlingEvent );
-    }
-
-    @Test
-    public void deviation_2b_Misrouted_ReceiveLocationOfWrongItinerary_Midpoint()
-        throws Exception
-    {
-        cargo.itinerary().set( wrongItinerary );
-        cargo.delivery().set( delivery( TODAY, NOT_RECEIVED, MISROUTED, leg1 ) );
-
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, RECEIVE, NEWYORK, noVoyage );
-
-        new InspectReceivedCargo( cargo, handlingEvent ).inspect();
-
-        // Remains misrouted and directed
-        assertDelivery( RECEIVE, NEWYORK, DAY1, noVoyage,
-                        IN_PORT, notArrived,
-                        MISROUTED, directed, unknownETA, unknownLeg,
-                        unknownNextHandlingEvent );
-    }
-
-    @Test
-    public void deviation_2b_Misrouted_ReceiveLocationOfWrongItinerary_Destination()
-        throws Exception
-    {
-        cargo.itinerary().set( wrongItinerary );
-        cargo.delivery().set( delivery( TODAY, NOT_RECEIVED, MISROUTED, unknownLeg ) );
-
-        assertDelivery( null, null, null, null,
-                        NOT_RECEIVED, notArrived,
-                        MISROUTED, directed, unknownETA, unknownLeg,
-                        unknownNextHandlingEvent );
-
-        // Receipt in cargo destination = no transportation.
-        // This must be a mistake. Cargo owner should be notified.
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, RECEIVE, STOCKHOLM, noVoyage );
-        new InspectReceivedCargo( cargo, handlingEvent ).inspect();
-
-        // Remains misrouted and directed
-        assertDelivery( RECEIVE, STOCKHOLM, DAY1, noVoyage,
-                        IN_PORT, notArrived,
-                        MISROUTED, directed, unknownETA, unknownLeg,
-                        unknownNextHandlingEvent );
-    }
-
-    @Test
-    public void deviation_2b_Misrouted_ReceiveLocationOfWrongItinerary_UnplannedLocation()
-        throws Exception
-    {
-        cargo.itinerary().set( wrongItinerary );
-        cargo.delivery().set( delivery( TODAY, NOT_RECEIVED, MISROUTED, unknownLeg ) );
-
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, RECEIVE, HANGZHOU, noVoyage );
-
-        new InspectReceivedCargo( cargo, handlingEvent ).inspect();
-
-        // Remains misrouted and directed
-        assertDelivery( RECEIVE, HANGZHOU, DAY1, noVoyage,
-                        IN_PORT, notArrived,
-                        MISROUTED, directed, unknownETA, unknownLeg,
-                        unknownNextHandlingEvent );
-    }
-
-    @Test
-    public void deviation_3a_Misdirected_ReceiveLocationOfCorrectItinerary_Midpoint()
-        throws Exception
-    {
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, NOT_RECEIVED, ROUTED, leg1 ) );
-
-        assertDelivery( null, null, null, null,
-                        NOT_RECEIVED, notArrived,
-                        ROUTED, directed, unknownETA, unknownLeg,
-                        unknownNextHandlingEvent );
-
-        // Receive cargo in some location of valid itinerary - should this be accepted?!
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, RECEIVE, NEWYORK, noVoyage );
-        try
-        {
-            new InspectReceivedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( CargoMisdirectedException e )
-        {
-            assertMessage( e, "MISDIRECTED! Itinerary expected receipt in Hongkong (CNHKG)" );
-
-            // Now routed but misdirected
-            assertDelivery( RECEIVE, NEWYORK, DAY1, noVoyage,
-                            IN_PORT, notArrived,
-                            ROUTED, misdirected, unknownETA, unknownLeg,
-                            unknownNextHandlingEvent );
-        }
-    }
-
-    @Test
-    public void deviation_3a_Misdirected_ReceiveLocationOfCorrectItinerary_Destination()
-        throws Exception
-    {
-        // Assign satisfying route going to Stockholm
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, NOT_RECEIVED, ROUTED, leg1 ) );
-
-        // Receipt in cargo/routeSpec destination = no transportation.
-        // This must be a unintended booking. Cargo owner should be notified.
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, RECEIVE, STOCKHOLM, noVoyage );
-        try
-        {
-            new InspectReceivedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( CargoMisdirectedException e )
-        {
-            assertMessage( e, "MISDIRECTED! Itinerary expected receipt in Hongkong (CNHKG)" );
-            assertDelivery( RECEIVE, STOCKHOLM, DAY1, noVoyage,
-                            IN_PORT, notArrived,
-                            ROUTED, misdirected, unknownETA, unknownLeg,
-                            unknownNextHandlingEvent );
-        }
-    }
-
-    @Test
-    public void deviation_3a_Misdirected_UnexpectedReceiveLocation()
-        throws Exception
-    {
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, NOT_RECEIVED, ROUTED, leg1 ) );
-
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, RECEIVE, HANGZHOU, noVoyage );
-        thrown.expect( CargoMisdirectedException.class, "MISDIRECTED! Itinerary expected receipt in Hongkong (CNHKG)" );
-        new InspectReceivedCargo( cargo, handlingEvent ).inspect();
-    }
-
-    @Test
-    public void successful_Receipt()
-        throws Exception
-    {
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, NOT_RECEIVED, ROUTED, leg1 ) );
-
-        // Receive cargo as planned in origin
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, RECEIVE, HONGKONG, noVoyage );
-        new InspectReceivedCargo( cargo, handlingEvent ).inspect();
-
-        // Itinerary calculations
-        NextHandlingEvent nextLoad = cargo.delivery().get().nextHandlingEvent().get();
-        assertThat( nextLoad.location().get(), is( equalTo( itinerary.firstLeg().loadLocation().get() ) ) );
-        assertThat( nextLoad.time().get(), is( equalTo( itinerary.firstLeg().loadTime().get() ) ) );
-        assertThat( nextLoad.voyage().get(), is( equalTo( itinerary.firstLeg().voyage().get() ) ) );
-
-        assertDelivery( RECEIVE, HONGKONG, DAY1, noVoyage,
-                        IN_PORT, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg1,
-                        LOAD, HONGKONG, DAY1, V201 );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectUnhandledCargoTest.java b/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectUnhandledCargoTest.java
deleted file mode 100644
index 0be3b89..0000000
--- a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectUnhandledCargoTest.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.test.handling.inspection.event;
-
-import java.util.Date;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.test.TestApplication;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectUnhandledCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionFailedException;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.CargoAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.HandlingEventAggregateRoot;
-
-import static org.junit.Assert.fail;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.MISROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.NOT_ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.IN_PORT;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.NOT_RECEIVED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.RECEIVE;
-
-/**
- * {@link InspectUnhandledCargo} tests
- */
-public class InspectUnhandledCargoTest extends TestApplication
-{
-    private HandlingEventAggregateRoot HANDLING_EVENTS;
-
-    @Before
-    public void prepareTest()
-        throws Exception
-    {
-        super.prepareTest();
-        UnitOfWork uow = module.currentUnitOfWork();
-        HANDLING_EVENTS = uow.get( HandlingEventAggregateRoot.class, HandlingEventAggregateRoot.HANDLING_EVENTS_ID );
-        CargoAggregateRoot CARGOS = uow.get( CargoAggregateRoot.class, CargoAggregateRoot.CARGOS_ID );
-
-        // Create new cargo
-        routeSpec = routeSpecFactory.build( HONGKONG, STOCKHOLM, new Date(), deadline = DAY24 );
-        delivery = delivery( TODAY, NOT_RECEIVED, NOT_ROUTED, leg1 );
-        cargo = CARGOS.createCargo( routeSpec, delivery, "Claimed_CARGO" );
-        trackingId = cargo.trackingId().get();
-    }
-
-    @Test
-    public void precondition_CannotInspectUnloadInDestinationHere()
-        throws Exception
-    {
-        // Can't inspect handled cargo here...
-        cargo.itinerary().set( itinerary );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, RECEIVE, HONGKONG, noVoyage );
-        cargo.delivery().set( delivery( handlingEvent, IN_PORT, notArrived,
-                                        ROUTED, directed, itinerary.eta(), leg1, unknownNextHandlingEvent ) );
-        try
-        {
-            new InspectUnhandledCargo( cargo ).inspect();
-            fail();
-        }
-        catch( InspectionFailedException e )
-        {
-            assertMessage( e, "INTERNAL ERROR: Can only inspect unhandled cargo" );
-        }
-    }
-
-    @Test
-    public void deviation_2a_NotRouted()
-        throws Exception
-    {
-        // Cargo not routed
-        cargo.itinerary().set( null );
-        cargo.delivery().set( delivery( TODAY, NOT_RECEIVED, NOT_ROUTED, leg1 ) );
-
-        new InspectUnhandledCargo( cargo ).inspect();
-
-        assertDelivery( null, null, null, null,
-                        NOT_RECEIVED, notArrived,
-                        NOT_ROUTED, directed, unknownETA, unknownLeg,
-                        RECEIVE, HONGKONG, noSpecificDate, noVoyage );
-    }
-
-    @Test
-    public void deviation_2b_Misrouted()
-        throws Exception
-    {
-        // Misroute cargo - assign unsatisfying itinerary not going to Stockholm
-        cargo.itinerary().set( wrongItinerary );
-        cargo.delivery().set( delivery( TODAY, NOT_RECEIVED, MISROUTED, leg1 ) );
-
-        new InspectUnhandledCargo( cargo ).inspect();
-
-        assertDelivery( null, null, null, null,
-                        NOT_RECEIVED, notArrived,
-                        MISROUTED, directed, unknownETA, unknownLeg,
-                        RECEIVE, HONGKONG, noSpecificDate, noVoyage );
-    }
-
-    @Test
-    public void step_2_Routed()
-        throws Exception
-    {
-        // Assign satisfying route going to Stockholm
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, NOT_RECEIVED, ROUTED, leg1 ) );
-
-        new InspectUnhandledCargo( cargo ).inspect();
-
-        assertDelivery( null, null, null, null,
-                        NOT_RECEIVED, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg1,
-                        RECEIVE, HONGKONG, noSpecificDate, noVoyage );
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectUnloadedCargoTest.java b/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectUnloadedCargoTest.java
deleted file mode 100644
index 3ffa906..0000000
--- a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/inspection/event/InspectUnloadedCargoTest.java
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.test.handling.inspection.event;
-
-import java.util.Date;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.test.TestApplication;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.event.InspectUnloadedCargo;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoMisdirectedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoMisroutedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.CargoNotRoutedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.inspection.exception.InspectionFailedException;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.CargoAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.HandlingEventAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.itinerary.Leg;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.MISROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.NOT_ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.IN_PORT;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.ONBOARD_CARRIER;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.LOAD;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.UNLOAD;
-
-/**
- * {@link InspectUnloadedCargo} tests
- */
-public class InspectUnloadedCargoTest extends TestApplication
-{
-    private HandlingEventAggregateRoot HANDLING_EVENTS;
-
-    @Before
-    public void prepareTest()
-        throws Exception
-    {
-        super.prepareTest();
-        UnitOfWork uow = module.currentUnitOfWork();
-        HANDLING_EVENTS = uow.get( HandlingEventAggregateRoot.class, HandlingEventAggregateRoot.HANDLING_EVENTS_ID );
-        CargoAggregateRoot CARGOS = uow.get( CargoAggregateRoot.class, CargoAggregateRoot.CARGOS_ID );
-
-        // Create new cargo
-        routeSpec = routeSpecFactory.build( HONGKONG, STOCKHOLM, new Date(), deadline = DAY24 );
-        delivery = delivery( TODAY, ONBOARD_CARRIER, ROUTED, leg1 );
-        cargo = CARGOS.createCargo( routeSpec, delivery, "Unloaded_CARGO" );
-        trackingId = cargo.trackingId().get();
-    }
-
-    @Test
-    public void precondition_CannotInspectUnloadInDestinationHere()
-        throws Exception
-    {
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, UNLOAD, STOCKHOLM, V205 );
-        try
-        {
-            new InspectUnloadedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( InspectionFailedException e )
-        {
-            assertMessage( e, "INTERNAL ERROR: Can only inspect unloaded cargo that hasn't arrived at destination" );
-        }
-    }
-
-    @Test
-    public void deviation_2a_NotRouted()
-        throws Exception
-    {
-        // Cargo not routed
-        cargo.itinerary().set( null );
-        cargo.delivery().set( delivery( TODAY, ONBOARD_CARRIER, NOT_ROUTED, leg1 ) );
-
-        // Unload in Chicago (without an itinerary!)
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY5, DAY5, trackingId, UNLOAD, CHICAGO, V201 );
-        try
-        {
-            new InspectUnloadedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( CargoNotRoutedException e )
-        {
-            assertMessage( e, "NOT ROUTED while being handled!" );
-
-            // An unexpected unload shouldn't be considered an itinerary progress - legIndex stays unchanged
-            assertDelivery( UNLOAD, CHICAGO, DAY5, V201,
-                            IN_PORT, notArrived,
-                            NOT_ROUTED, directed, unknownETA, unknownLeg,
-                            unknownNextHandlingEvent );
-        }
-    }
-
-    @Test
-    public void deviation_2b_Misrouted_UnloadLocationOfWrongItinerary_Origin()
-        throws Exception
-    {
-        // Misroute cargo - assign unsatisfying itinerary not going to Stockholm
-        cargo.itinerary().set( wrongItinerary );
-        cargo.delivery().set( delivery( TODAY, ONBOARD_CARRIER, MISROUTED, leg1 ) );
-
-        // Unload in Hong Kong (with wrong itinerary)
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, UNLOAD, HONGKONG, V201 );
-        try
-        {
-            new InspectUnloadedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( CargoMisroutedException e )
-        {
-            assertMessage( e, "MISROUTED! Route specification is not satisfied with itinerary" );
-
-            // An unexpected unload shouldn't be considered an itinerary progress - legIndex stays unchanged
-            assertDelivery( UNLOAD, HONGKONG, DAY1, V201,
-                            IN_PORT, notArrived,
-                            MISROUTED, directed, unknownETA, unknownLeg,
-                            unknownNextHandlingEvent );
-        }
-    }
-
-    @Test
-    public void deviation_2b_Misrouted_UnloadLocationOfWrongItinerary_OtherItineraryLocation()
-        throws Exception
-    {
-        cargo.itinerary().set( wrongItinerary );
-        cargo.delivery().set( delivery( TODAY, ONBOARD_CARRIER, MISROUTED, leg1 ) );
-
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, UNLOAD, NEWYORK, V201 );
-        thrown.expect( CargoMisroutedException.class, "MISROUTED! Route specification is not satisfied with itinerary" );
-        new InspectUnloadedCargo( cargo, handlingEvent ).inspect();
-    }
-
-    @Test
-    public void deviation_2b_Misrouted_UnloadLocationOfWrongItinerary_UnplannedLocation()
-        throws Exception
-    {
-        cargo.itinerary().set( wrongItinerary );
-        cargo.delivery().set( delivery( TODAY, ONBOARD_CARRIER, MISROUTED, leg1 ) );
-
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, UNLOAD, ROTTERDAM, V204 );
-        thrown.expect( CargoMisroutedException.class, "MISROUTED! Route specification is not satisfied with itinerary" );
-        new InspectUnloadedCargo( cargo, handlingEvent ).inspect();
-    }
-
-    @Test
-    public void step_2_Routed_UnloadedInPlannedLocation()
-        throws Exception
-    {
-        // Assign satisfying route going to Stockholm
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, ONBOARD_CARRIER, ROUTED, leg1 ) );
-
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY5, DAY5, trackingId, UNLOAD, CHICAGO, V201 );
-        new InspectUnloadedCargo( cargo, handlingEvent ).inspect();
-
-        // Itinerary progresses to next leg
-        assertDelivery( UNLOAD, CHICAGO, DAY5, V201,
-                        IN_PORT, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg2,
-                        LOAD, CHICAGO, DAY5, V201 );
-    }
-
-    @Test
-    public void deviation_3x_InternalError_InvalidItineraryProgressIndex()
-        throws Exception
-    {
-        cargo.itinerary().set( itinerary );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY5, DAY5, trackingId, UNLOAD, CHICAGO, V201 );
-
-        Integer badLegIndex = 7;
-        cargo.delivery().set( delivery( handlingEvent, IN_PORT, notArrived,
-                                        ROUTED, directed, unknownETA, badLegIndex,
-                                        unknownNextHandlingEvent ) );
-        try
-        {
-            new InspectUnloadedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( InspectionFailedException e )
-        {
-            assertMessage( e, "INTERNAL ERROR: Itinerary progress index '7' is invalid!" );
-            assertDelivery( UNLOAD, CHICAGO, DAY5, V201,
-                            IN_PORT, notArrived,
-                            ROUTED, directed, unknownETA, badLegIndex,
-                            unknownNextHandlingEvent );
-        }
-    }
-
-    @Test
-    public void deviation_3a_ReRouted_UnloadInNewOrigin()
-        throws Exception
-    {
-        // Re-route with new satisfying itinerary
-        cargo.itinerary().set( itinerary );
-
-        // Cargo was re-route on board a carrier
-        cargo.delivery().set( delivery( null, ONBOARD_CARRIER, notArrived,
-                                        ROUTED, misdirected, itinerary.eta(), leg3,
-                                        nextHandlingEvent( UNLOAD, HONGKONG, DAY6, V201 ) ) );
-
-        // Unload in new route specification origin (load location of itinerary leg 1)
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, UNLOAD, HONGKONG, V204 );
-        new InspectUnloadedCargo( cargo, handlingEvent ).inspect();
-
-        // Itinerary progress starts over from leg 1 again
-        assertDelivery( UNLOAD, HONGKONG, DAY1, V204,
-                        IN_PORT, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg1,
-                        LOAD, HONGKONG, DAY1, V201 );
-    }
-
-    @Test
-    public void deviation_3b_Misdirected_UnexpectedUnloadLocation_Origin()
-        throws Exception
-    {
-        // Going fine so far
-        cargo.itinerary().set( itinerary );
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY5, DAY5, trackingId, LOAD, CHICAGO, V201 );
-        cargo.delivery().set( delivery( handlingEvent, ONBOARD_CARRIER, notArrived,
-                                        ROUTED, directed, itinerary.eta(), leg2,
-                                        nextHandlingEvent( UNLOAD, NEWYORK, DAY6, V201 ) ) );
-
-        // Unexpected unload in origin
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY6, DAY6, trackingId, UNLOAD, HONGKONG, V201 );
-        new InspectUnloadedCargo( cargo, handlingEvent ).inspect();
-
-        // Itinerary progress starts over from leg 1 again
-        assertDelivery( UNLOAD, HONGKONG, DAY6, V201,
-                        IN_PORT, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg1,
-                        LOAD, HONGKONG, DAY1, V201 );
-    }
-
-    @Test
-    public void deviation_3b_Misdirected_UnexpectedUnloadLocation_PreviousInItinerary()
-        throws Exception
-    {
-        // Move the cargo ahead on the route. Third leg of itinerary expects unload in Dallas.
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, ONBOARD_CARRIER, ROUTED, leg3 ) );
-
-        // Unexpected unload in previous unload location of itinerary.
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY7, DAY7, trackingId, UNLOAD, NEWYORK, V201 );
-        try
-        {
-            new InspectUnloadedCargo( cargo, handlingEvent ).inspect();
-            fail();
-        }
-        catch( CargoMisdirectedException e )
-        {
-            assertMessage( e, "MISDIRECTED! Itinerary expected unload in USDAL" );
-            assertDelivery( UNLOAD, NEWYORK, DAY7, V201,      // Itinerary expected: UNLOAD, DALLAS, DAY8, V202
-                            IN_PORT, notArrived,
-                            ROUTED, misdirected, itinerary.eta(), leg3,
-                            unknownNextHandlingEvent );
-        }
-    }
-
-    @Test
-    public void deviation_3b_Misdirected_UnexpectedUnloadLocation_NextInItinerary()
-        throws Exception
-    {
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, ONBOARD_CARRIER, ROUTED, leg3 ) );
-
-        // Unexpected load in next load location of itinerary (onto expected voyage) - can't jump ahead in route plan.
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY7, DAY7, trackingId, UNLOAD, GOTHENBURG, V202 );
-        thrown.expect( CargoMisdirectedException.class, "MISDIRECTED! Itinerary expected unload in USDAL" );
-        new InspectUnloadedCargo( cargo, handlingEvent ).inspect();
-    }
-
-    @Test
-    public void deviation_3b_Misdirected_UnexpectedUnloadLocation_Unplanned()
-        throws Exception
-    {
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, ONBOARD_CARRIER, ROUTED, leg3 ) );
-
-        // Unexpected load in unplanned location (onto expected voyage)
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY7, DAY7, trackingId, UNLOAD, HAMBURG, V202 );
-        thrown.expect( CargoMisdirectedException.class, "MISDIRECTED! Itinerary expected unload in USDAL" );
-        new InspectUnloadedCargo( cargo, handlingEvent ).inspect();
-    }
-
-    @Test
-    public void deviation_3c_ExpectedUnloadLocation_UnexpectedUnloadVoyage()
-        throws Exception
-    {
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, ONBOARD_CARRIER, ROUTED, leg3 ) );
-
-        // Unload in expected location but from unexpected voyage - do we care? For now not.
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY10, DAY10, trackingId, UNLOAD, DALLAS, V205 );
-        new InspectUnloadedCargo( cargo, handlingEvent ).inspect();
-
-        // Itinerary should have progressed to leg 4
-        assertDelivery( UNLOAD, DALLAS, DAY10, V205,      // Itinerary expected: UNLOAD, DALLAS, DAY8, V202
-                        IN_PORT, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg4,
-                        LOAD, DALLAS, DAY10, V202 ); // leg 4 load location
-    }
-
-    @Test
-    public void success_Unload()
-        throws Exception
-    {
-        cargo.itinerary().set( itinerary );
-        cargo.delivery().set( delivery( TODAY, ONBOARD_CARRIER, ROUTED, leg4 ) );
-
-        // Expected unload in leg 4 unload location (Rotterdam)
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY17, DAY17, trackingId, UNLOAD, ROTTERDAM, V202 );
-        new InspectUnloadedCargo( cargo, handlingEvent ).inspect();
-
-        // Itinerary should have progressed to leg 5
-        Leg nextCarrierMovement = itinerary.leg( cargo.delivery().get().itineraryProgressIndex().get() );
-        assertThat( nextCarrierMovement.loadLocation().get(), is( equalTo( ROTTERDAM ) ) );
-        assertThat( nextCarrierMovement.loadTime().get(), is( equalTo( DAY20 ) ) );
-        assertThat( nextCarrierMovement.voyage().get(), is( equalTo( V203 ) ) );
-
-        assertDelivery( UNLOAD, ROTTERDAM, DAY17, V202,
-                        IN_PORT, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg5,
-                        LOAD, ROTTERDAM, DAY20, V203 ); // leg 5 load location
-    }
-}
diff --git a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/parsing/ParseHandlingEventDataTest.java b/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/parsing/ParseHandlingEventDataTest.java
deleted file mode 100644
index 584c332..0000000
--- a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/parsing/ParseHandlingEventDataTest.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.test.handling.parsing;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.constraint.ConstraintViolationException;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.test.TestApplication;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.ParseHandlingEventData;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.exception.InvalidHandlingEventDataException;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.CargoAggregateRoot;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.NOT_RECEIVED;
-
-/**
- * {@link ParseHandlingEventData} tests
- */
-public class ParseHandlingEventDataTest extends TestApplication
-{
-    static ParseHandlingEventData handlingEventParser;
-    static String completionTime;
-
-    @Before
-    public void prepareTest()
-        throws Exception
-    {
-        super.prepareTest();
-        TestApplication.setup();
-        UnitOfWork uow = module.currentUnitOfWork();
-        CargoAggregateRoot CARGOS = uow.get( CargoAggregateRoot.class, CargoAggregateRoot.CARGOS_ID );
-
-        // Create new cargo
-        routeSpec = routeSpecFactory.build( HONGKONG, STOCKHOLM, new Date(), deadline = DAY24 );
-        delivery = delivery( TODAY, NOT_RECEIVED, ROUTED, unknownLeg );
-        cargo = CARGOS.createCargo( routeSpec, delivery, "ABC" );
-        trackingId = cargo.trackingId().get();
-        trackingIdString = trackingId.id().get();
-        cargo.itinerary().set( itinerary );
-        completionTime = new SimpleDateFormat( "yyyy-MM-dd HH:mm" ).format( new Date() );
-
-        // Start ParseHandlingEventData service
-        ServiceReference<ParseHandlingEventData> ParseHandlingEventDataRef =
-            module.findService( ParseHandlingEventData.class );
-        handlingEventParser = ParseHandlingEventDataRef.get();
-    }
-
-    // Null
-
-    @Test
-    public void deviation_2a_Null_CompletionTimeString()
-        throws Exception
-    {
-        thrown.expect( ConstraintViolationException.class, "constraint \"not optional(param1)\", for value 'null'" );
-        handlingEventParser.parse( null, trackingIdString, "RECEIVE", "CNHKG", null );
-    }
-
-    @Test
-    public void deviation_2a_Null_TrackingIdString()
-        throws Exception
-    {
-        thrown.expect( ConstraintViolationException.class, "constraint \"not optional(param2)\", for value 'null'" );
-        handlingEventParser.parse( completionTime, null, "RECEIVE", "CNHKG", null );
-    }
-
-    // etc...
-
-    @Test
-    public void step_2_Null_VoyageNumberString()
-        throws Exception
-    {
-        // No voyage number string is ok
-        handlingEventParser.parse( completionTime, trackingIdString, "RECEIVE", "CNHKG", null );
-    }
-
-    // Empty
-
-    @Test
-    public void deviation_2a_Empty_CompletionTimeString()
-        throws Exception
-    {
-        thrown.expect( ConstraintViolationException.class, "NotEmpty()(param1)\", for value ' '" );
-        handlingEventParser.parse( " ", trackingIdString, "RECEIVE", "CNHKG", null );
-    }
-
-    @Test
-    public void step_2_Empty_VoyageNumberString()
-        throws Exception
-    {
-        // Empty voyage number string is ok
-        handlingEventParser.parse( completionTime, trackingIdString, "RECEIVE", "CNHKG", " " );
-    }
-
-    // Basic type conversion
-
-    @Test
-    public void deviation_3a_TypeConversion_CompletionTimeString()
-        throws Exception
-    {
-        thrown.expect( InvalidHandlingEventDataException.class,
-                       "Invalid date format: '5/27/2011' must be on ISO 8601 format yyyy-MM-dd HH:mm" );
-        handlingEventParser.parse( "5/27/2011", trackingIdString, "RECEIVE", "CNHKG", null );
-    }
-
-    @Test
-    public void deviation_3a_TypeConversion_HandlingEventTypeString()
-        throws Exception
-    {
-        thrown.expect( InvalidHandlingEventDataException.class, "No enum const" );
-        handlingEventParser.parse( completionTime, trackingIdString, "HAND_OVER", "CNHKG", null );
-    }
-
-    // Successful parsing
-
-    @Test
-    public void success_Parsing()
-        throws Exception
-    {
-        handlingEventParser.parse( completionTime, trackingIdString, "RECEIVE", "CNHKG", null );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/registration/RegisterHandlingEventTest.java b/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/registration/RegisterHandlingEventTest.java
deleted file mode 100644
index a6ca313..0000000
--- a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/context/test/handling/registration/RegisterHandlingEventTest.java
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.context.test.handling.registration;
-
-import java.util.Date;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.sample.dcicargo.sample_b.bootstrap.test.TestApplication;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.parsing.dto.ParsedHandlingEventData;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.RegisterHandlingEvent;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception.AlreadyClaimedException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception.DuplicateEventException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception.MissingVoyageNumberException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception.UnknownCargoException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception.UnknownLocationException;
-import org.qi4j.sample.dcicargo.sample_b.context.interaction.handling.registration.exception.UnknownVoyageException;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.CargoAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.aggregateroot.HandlingEventAggregateRoot;
-import org.qi4j.sample.dcicargo.sample_b.data.entity.HandlingEventEntity;
-import org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEvent;
-
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.RoutingStatus.ROUTED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.IN_PORT;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.delivery.TransportStatus.NOT_RECEIVED;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.CLAIM;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.CUSTOMS;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.LOAD;
-import static org.qi4j.sample.dcicargo.sample_b.data.structure.handling.HandlingEventType.RECEIVE;
-
-/**
- * {@link RegisterHandlingEvent} tests
- *
- * FIXME: Every test method call the one above to allow ordered execution, ie. tests are not indepedants !
- */
-public class RegisterHandlingEventTest extends TestApplication
-{
-    private ParsedHandlingEventData parsedEventData;
-    private UnitOfWork tempUow;
-    private HandlingEventAggregateRoot HANDLING_EVENTS;
-
-    @Before
-    public void prepareTest()
-        throws Exception
-    {
-        super.prepareTest();
-        UnitOfWork uow = module.currentUnitOfWork();
-        HANDLING_EVENTS = uow.get( HandlingEventAggregateRoot.class, HandlingEventAggregateRoot.HANDLING_EVENTS_ID );
-        CargoAggregateRoot CARGOS = uow.get( CargoAggregateRoot.class, CargoAggregateRoot.CARGOS_ID );
-
-        // Create new cargo
-        routeSpec = routeSpecFactory.build( HONGKONG, STOCKHOLM, new Date(), deadline = DAY24 );
-        delivery = delivery( TODAY, NOT_RECEIVED, ROUTED, unknownLeg );
-        cargo = CARGOS.createCargo( routeSpec, delivery, "ABC" );
-        cargo.itinerary().set( itinerary );
-        trackingId = cargo.trackingId().get();
-    }
-
-    @Test
-    public void deviation_1a_UnknownCargo()
-        throws Exception
-    {
-        parsedEventData = parsedHandlingEventData( DAY1, DAY1, "XXX", RECEIVE, "CNHKG", null );
-        thrown.expect( UnknownCargoException.class, "Found no cargo with tracking id 'XXX'." );
-        handlingEvent = new RegisterHandlingEvent( parsedEventData ).getEvent();
-    }
-
-    @Test
-    public void deviation_2a_UnknownUnlocode()
-        throws Exception
-    {
-        deviation_1a_UnknownCargo();
-
-        parsedEventData = parsedHandlingEventData( DAY1, DAY1, "ABC", RECEIVE, "ZZZZZ", null );
-        thrown.expect( UnknownLocationException.class, "Found no location with UN locode 'ZZZZZ'." );
-        handlingEvent = new RegisterHandlingEvent( parsedEventData ).getEvent();
-    }
-
-    @Test
-    public void deviation_3a_VoyageNumber_SilentlySkipIfNotRequired()
-        throws Exception
-    {
-        deviation_2a_UnknownUnlocode();
-
-        parsedEventData = parsedHandlingEventData( DAY1, DAY1, "ABC", RECEIVE, "CNHKG", "V201" );
-        handlingEvent = new RegisterHandlingEvent( parsedEventData ).getEvent();
-    }
-
-    @Test
-    public void deviation_3b_VoyageNumber_Missing()
-        throws Exception
-    {
-        deviation_3a_VoyageNumber_SilentlySkipIfNotRequired();
-
-        parsedEventData = parsedHandlingEventData( DAY1, DAY1, "ABC", LOAD, "CNHKG", null );
-        thrown.expect( MissingVoyageNumberException.class, "Missing voyage number. Handling event LOAD requires a voyage." );
-        handlingEvent = new RegisterHandlingEvent( parsedEventData ).getEvent();
-    }
-
-    @Test
-    public void deviation_3c_VoyageNumber_Unknown()
-        throws Exception
-    {
-        deviation_3b_VoyageNumber_Missing();
-
-        parsedEventData = parsedHandlingEventData( DAY1, DAY1, "ABC", LOAD, "CNHKG", "V600S" );
-        thrown.expect( UnknownVoyageException.class, "Found no voyage with voyage number 'V600S'." );
-        handlingEvent = new RegisterHandlingEvent( parsedEventData ).getEvent();
-    }
-
-    @Test
-    public void deviation_4a_DuplicateEvent_Receive()
-        throws Exception
-    {
-        deviation_3c_VoyageNumber_Unknown();
-        UnitOfWork uow = module.currentUnitOfWork();
-
-        // Receive 1st time (store event so that it turns up in query)
-        uow.complete();
-        tempUow = module.newUnitOfWork();
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, RECEIVE, HONGKONG, noVoyage );
-        tempUow.complete();
-
-        // Receive 2nd time
-        parsedEventData = parsedHandlingEventData( DAY2, DAY2, "ABC", RECEIVE, "CNHKG", null );
-        thrown.expect( DuplicateEventException.class, "Cargo can't be received more than once" );
-        handlingEvent = new RegisterHandlingEvent( parsedEventData ).getEvent();
-    }
-
-    @Test
-    public void deviation_4a_DuplicateEvent_Customs()
-        throws Exception
-    {
-        deviation_4a_DuplicateEvent_Receive();
-        UnitOfWork uow = module.currentUnitOfWork();
-
-        uow.complete();
-        // In customs 1st time
-        tempUow = module.newUnitOfWork();
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, CUSTOMS, HONGKONG, noVoyage );
-        tempUow.complete();
-
-        // In customs 2nd time
-        parsedEventData = parsedHandlingEventData( DAY2, DAY2, "ABC", CUSTOMS, "CNHKG", null );
-        thrown.expect( DuplicateEventException.class, "Cargo can't be in customs more than once" );
-        handlingEvent = new RegisterHandlingEvent( parsedEventData ).getEvent();
-    }
-
-    @Test
-    public void deviation_4a_DuplicateEvent_Claim()
-        throws Exception
-    {
-        deviation_4a_DuplicateEvent_Customs();
-        UnitOfWork uow = module.currentUnitOfWork();
-
-        uow.complete();
-        // Claimed 1st time
-        tempUow = module.newUnitOfWork();
-        handlingEvent = HANDLING_EVENTS.createHandlingEvent( DAY1, DAY1, trackingId, CLAIM, HONGKONG, noVoyage );
-        tempUow.complete();
-
-        // Claimed 2nd time
-        parsedEventData = parsedHandlingEventData( DAY2, DAY2, "ABC", CLAIM, "CNHKG", null );
-        thrown.expect( DuplicateEventException.class, "Cargo can't be claimed more than once" );
-        new RegisterHandlingEvent( parsedEventData ).getEvent();
-    }
-
-    @Test
-    public void deviation_5a_NoHandlingAfterClaim()
-        throws Exception
-    {
-        deviation_4a_DuplicateEvent_Claim();
-
-        // Try loading (saved claim event in previous test will prevent this)
-        parsedEventData = parsedHandlingEventData( DAY2, DAY2, "ABC", LOAD, "CNHKG", "V201" );
-        thrown.expect( AlreadyClaimedException.class, "LOAD handling event can't be registered after cargo has been claimed" );
-        new RegisterHandlingEvent( parsedEventData ).getEvent();
-    }
-
-    @Test
-    public void successfull_Registration()
-        throws Exception
-    {
-        deviation_5a_NoHandlingAfterClaim();
-
-        // Delete handling events from memory
-        tempUow = module.newUnitOfWork();
-        Query<HandlingEventEntity> events = tempUow.newQuery( module.newQueryBuilder( HandlingEventEntity.class ) );
-        for( HandlingEvent event : events )
-        {
-            tempUow.remove( event );
-        }
-        tempUow.complete();
-
-        cargo.delivery().set( delivery( null, NOT_RECEIVED, notArrived,
-                                        ROUTED, directed, itinerary.eta(), leg1,
-                                        nextHandlingEvent( RECEIVE, HONGKONG, DAY1, noVoyage ) ) );
-
-        assertDelivery( null, null, null, null,
-                        NOT_RECEIVED, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg1,
-                        RECEIVE, HONGKONG, DAY1, noVoyage );
-
-        parsedEventData = parsedHandlingEventData( DAY1, DAY1, "ABC", RECEIVE, "CNHKG", null );
-        handlingEvent = new RegisterHandlingEvent( parsedEventData ).getEvent();
-
-        cargo.delivery().set( delivery( handlingEvent, IN_PORT, notArrived,
-                                        ROUTED, directed, itinerary.eta(), leg1,
-                                        nextHandlingEvent( LOAD, HONGKONG, DAY1, V201 ) ) );
-
-        assertDelivery( RECEIVE, HONGKONG, DAY1, noVoyage,  // Handling event has been registered
-                        IN_PORT, notArrived,
-                        ROUTED, directed, itinerary.eta(), leg1,
-                        LOAD, HONGKONG, DAY1, V201 );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/testing/ExpectedException.java b/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/testing/ExpectedException.java
deleted file mode 100644
index 568d750..0000000
--- a/samples/dci-cargo/dcisample_b/src/test/java/org/qi4j/sample/dcicargo/sample_b/infrastructure/testing/ExpectedException.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2011 Marc Grue.
- *
- * Licensed  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.qi4j.sample.dcicargo.sample_b.infrastructure.testing;
-
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-
-/**
- * ExpectedException.
- * <p>
- * Wrapper of {@link org.junit.rules.ExpectedException} in order to provide custom
- * expected exception one-liners for convenience.
- * </p>
- * <p>
- * If you're checking certain DomainSpecificException often, you could wrap it here too...
- * </p>
- * <p>
- * See <a href="http://alexruiz.developerblogs.com/?p=1530">http://alexruiz.developerblogs.com/?p=1530</a>
- * </p>
- * <p>
- * NOTE!
- * </p>
- * <p>
- * 1. the check for the expected exception must be immediately above the code that is expected to throw such exception
- * </p>
- * <p>
- * 2. the line of code that is expected to throw an exception should be the last line in the test method
- * </p>
- * <p>
- * See <a href="http://java.dzone.com/articles/unexpected-behavior-junits">http://java.dzone.com/articles/unexpected-behavior-junits</a>
- * </p>
- * <p>
- */
-public class ExpectedException implements TestRule
-{
-    private final org.junit.rules.ExpectedException delegate = org.junit.rules.ExpectedException.none();
-
-    public static ExpectedException none()
-    {
-        return new ExpectedException();
-    }
-
-    private ExpectedException() {}
-
-    public Statement apply( Statement base, Description description )
-    {
-        return delegate.apply( base, description );
-    }
-
-    // This one saves a little typing :-)
-    public void expect( Class<? extends Throwable> type, String substringOfMessage )
-    {
-        expect( type );
-        expectMessage( substringOfMessage );
-    }
-
-    public void expectAssertionError( String message )
-    {
-        expect( AssertionError.class );
-        expectMessage( message );
-    }
-
-    public void expectNullPointerException( String message )
-    {
-        expect( NullPointerException.class );
-        expectMessage( message );
-    }
-
-    public void expect( Throwable error )
-    {
-        expect( error.getClass() );
-        expectMessage( error.getMessage() );
-    }
-
-
-    public void expect( Class<? extends Throwable> type )
-    {
-        delegate.expect( type );
-    }
-
-    public void expectMessage( String message )
-    {
-        delegate.expectMessage( message );
-    }
-}
\ No newline at end of file
diff --git a/samples/dci/build.gradle b/samples/dci/build.gradle
index 2d9ee86..5210a58 100644
--- a/samples/dci/build.gradle
+++ b/samples/dci/build.gradle
@@ -1,34 +1,36 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
+apply plugin: 'polygene-sample'
 
-description = "Sample of how DCI (Data, Context & Interaction) pattern is implemented with Apache Zest™."
+description = "Sample of how DCI (Data, Context & Interaction) pattern is implemented with Apache Polygene™."
 
-jar { manifest { name = "Apache Zest™ Sample - DCI" }}
+jar { manifest { name = "Apache Polygene™ Sample - DCI" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile(project(":org.qi4j.core:org.qi4j.core.runtime"))  /* TODO: Get rid of this dependency */
-  compile(project(":org.qi4j.libraries:org.qi4j.library.constraints"))
+  implementation polygene.core.bootstrap
+  implementation polygene.core.runtime  /* TODO: Get rid of this dependency */
+  implementation polygene.library( 'constraints' )
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-  testCompile(libraries.easymock)
+  testImplementation polygene.core.testsupport
+  testImplementation libraries.easymock
 
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  testRuntimeOnly libraries.logback
+}
diff --git a/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/context/PayBillsContext.java b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/context/PayBillsContext.java
new file mode 100644
index 0000000..dac8153
--- /dev/null
+++ b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/context/PayBillsContext.java
@@ -0,0 +1,153 @@
+/*
+ *  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.polygene.dci.moneytransfer.context;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.dci.moneytransfer.domain.data.BalanceData;
+import org.apache.polygene.dci.moneytransfer.rolemap.CreditorRolemap;
+
+/**
+ * Context for paying bills from an account to a list of creditor accounts.
+ * <p>
+ * Roles are defined within the context. A RoleMap lists what Roles an entity can play.
+ * </p>
+ */
+public class PayBillsContext
+{
+    public SourceAccountRole sourceAccount;
+
+    public PayBillsContext bind( BalanceData account )
+    {
+        sourceAccount = (SourceAccountRole) account;
+        return this;
+    }
+
+    public void payBills()
+        throws Exception
+    {
+        sourceAccount.payBills();
+    }
+
+    /**
+     * The SourceAccountRole orchestrates the Pay Bills use case interactions.
+     * <p>
+     * Code matches the use case text carefully (see references below).
+     * </p>
+     * <p>
+     * Pay Bills use case scenario:
+     * </p>
+     * <ol>
+     * <li> Bank finds creditors (could be a use case scenario in itself)</li>
+     * <li> Bank calculates the amount owed to creditors</li>
+     * <li>Bank verifies sufficient funds</li>
+     * <li>Bank transfer money to each creditor</li>
+     * </ol>
+     *
+     * <p>
+     * Algorithm (steps to implement the scenario):
+     * </p>
+     * <p>
+     * 1a) Source Account finds list of creditors
+     * </p>
+     * <p>
+     * 2a) Source Account loops creditors to find the sum owed
+     * </p>
+     * <p>
+     * 3a) Source Account verifies that its current balance is greater than the sum owed, and throws an exception if not
+     * </p>
+     * <p>
+     * 4a) Source Account loops creditors
+     * </p>
+     * <p>
+     * 4b) Make a MoneyTransfer of the amount owed to each creditor
+     * </p>
+     */
+
+    @Mixins( SourceAccountRole.Mixin.class )
+    public interface SourceAccountRole
+    {
+        void payBills()
+            throws Exception;
+
+        class Mixin
+            implements SourceAccountRole
+        {
+            @Structure
+            UnitOfWorkFactory uowf;
+
+            @This
+            BalanceData data;
+
+            public void payBills()
+                throws IllegalArgumentException
+            {
+                List<BalanceData> creditors = getCreditors();                                             // 1a
+
+                Integer sumOwed = getSumOwedTo( creditors );                                              // 2a
+
+                if( data.getBalance() - sumOwed < 0 )                                                      // 3a
+                {
+                    throw new IllegalArgumentException( "Insufficient funds to pay bills." );
+                }
+
+                final TransferMoneyContext transferMoney = new TransferMoneyContext();
+                for( BalanceData creditor : creditors )                                                    // 4a
+                {
+                    if( creditor.getBalance() < 0 )
+                    {
+                        final Integer amountOwed = -creditor.getBalance();
+
+                        // Bind nested context and execute enactment
+                        transferMoney.bind( data, creditor ).transfer( amountOwed );                      // 4b
+                    }
+                }
+            }
+
+            // Internal helper methods to make the code above more readable / comparable to the algorithm text
+
+            private List<BalanceData> getCreditors()
+            {
+                // Creditor retrieval could be a use case in itself...
+                List<BalanceData> creditors = new ArrayList<BalanceData>();
+                creditors.add( uowf.currentUnitOfWork().get( CreditorRolemap.class, new StringIdentity( "BakerAccount" ) ) );
+                creditors.add( uowf.currentUnitOfWork().get( CreditorRolemap.class, new StringIdentity( "ButcherAccount" ) ) );
+                return creditors;
+            }
+
+            private Integer getSumOwedTo( List<BalanceData> creditors )
+            {
+                Integer sumOwed = 0;
+                for( BalanceData creditor : creditors )
+                {
+                    sumOwed += creditor.getBalance() < 0 ? -creditor.getBalance() : 0;
+                }
+
+                return sumOwed;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/context/PayBillsContext2.java b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/context/PayBillsContext2.java
new file mode 100644
index 0000000..85009f8
--- /dev/null
+++ b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/context/PayBillsContext2.java
@@ -0,0 +1,145 @@
+/*
+ *  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.polygene.dci.moneytransfer.context;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.dci.moneytransfer.domain.data.BalanceData;
+
+/**
+ * Context for paying bills from an account to a list of creditor accounts.
+ * <p>
+ * Roles are defined within the context.
+ * A RoleMap lists what Roles an entity can play.
+ * </p>
+ */
+public class PayBillsContext2
+{
+    @Structure
+    UnitOfWorkFactory uowf;
+
+    private SourceAccountRole sourceAccount = new SourceAccountRole();
+
+    public PayBillsContext2 bind( BalanceData account )
+    {
+        sourceAccount.bind( account );
+        return this;
+    }
+
+    public void payBills()
+        throws Exception
+    {
+        sourceAccount.payBills();
+    }
+
+    /**
+     * The SourceAccountRole orchestrates the Pay Bills use case interactions.
+     * <p>
+     * Code matches the use case text carefully (see references below).
+     * </p>
+     * <p>
+     * Pay Bills use case scenario:
+     * </p>
+     * <p>
+     * 1) Bank finds creditors (could be a use case scenario in itself)
+     * </p>
+     * <p>
+     * 2) Bank calculates the amount owed to creditors
+     * </p>
+     * <p>
+     * 3) Bank verifies sufficient funds
+     * </p>
+     * <p>
+     * 4) Bank transfer money to each creditor
+     * </p>
+     * <p>
+     * Algorithm (steps to implement the scenario):
+     * </p>
+     * <p>
+     * <p>
+     * 1a) Source Account finds list of creditors
+     * </p>
+     * <p>
+     * 2a) Source Account loops creditors to find the sum owed
+     * </p>
+     * <p>
+     * 3a) Source Account verifies that its current balance is greater than the sum owed, and throws an exception if not
+     * </p>
+     * <p>
+     * 4a) Source Account loops creditors
+     * <p>
+     * 4b) Make a MoneyTransfer of the amount owed to each creditor
+     * </p>
+     */
+    class SourceAccountRole
+        extends Role<BalanceData>
+    {
+        void payBills()
+            throws IllegalArgumentException
+        {
+            List<BalanceData> creditors = getCreditors();                                             // 1a
+
+            Integer sumOwed = getSumOwedTo( creditors );                                              // 2a
+
+            if( self.getBalance() - sumOwed < 0 )                                                      // 3a
+            {
+                throw new IllegalArgumentException( "Insufficient funds to pay bills." );
+            }
+
+            final TransferMoneyContext2 transferMoney = new TransferMoneyContext2();
+            for( BalanceData creditor : creditors )                                                    // 4a
+            {
+                if( creditor.getBalance() < 0 )
+                {
+                    final Integer amountOwed = -creditor.getBalance();
+
+                    // Bind nested context and execute enactment
+                    transferMoney.bind( self, creditor ).transfer( amountOwed );                      // 4b
+                }
+            }
+        }
+
+        // Internal helper methods to make the code above more readable / comparable to the algorithm text
+
+        private List<BalanceData> getCreditors()
+        {
+            // Creditor retrieval could be a use case in itself...
+            List<BalanceData> creditors = new ArrayList<>();
+            creditors.add( uowf.currentUnitOfWork().get( BalanceData.class, new StringIdentity( "BakerAccount" ) ) );
+            creditors.add( uowf.currentUnitOfWork().get( BalanceData.class, new StringIdentity( "ButcherAccount" ) ) );
+            return creditors;
+        }
+
+        private Integer getSumOwedTo( List<BalanceData> creditors )
+        {
+            Integer sumOwed = 0;
+            for( BalanceData creditor : creditors )
+            {
+                sumOwed += creditor.getBalance() < 0 ? -creditor.getBalance() : 0;
+            }
+
+            return sumOwed;
+        }
+    }
+}
\ No newline at end of file
diff --git a/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/context/Role.java b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/context/Role.java
new file mode 100644
index 0000000..4a69b63
--- /dev/null
+++ b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/context/Role.java
@@ -0,0 +1,76 @@
+/*
+ *  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.polygene.dci.moneytransfer.context;
+
+/**
+ * TODO
+ */
+
+/**
+ * Base class for methodful roles
+ */
+public class Role<T>
+    implements Comparable<Role<T>>
+{
+    // Self reference to the bound Data object
+    protected T self;
+
+    public Role()
+    {
+    }
+
+    public Role( T self )
+    {
+        this.self = self;
+    }
+
+    public void bind( T newSelf )
+    {
+        self = newSelf;
+    }
+
+    public T self()
+    {
+        return self;
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        if( obj == null )
+        {
+            return false;
+        }
+
+        if( obj instanceof Role )
+        {
+            return self.equals( ( (Role) obj ).self );
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    public int compareTo( Role<T> role )
+    {
+        return ( (Comparable<T>) self ).compareTo( role.self );
+    }
+}
diff --git a/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/context/TransferMoneyContext.java b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/context/TransferMoneyContext.java
new file mode 100644
index 0000000..27b3f3e
--- /dev/null
+++ b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/context/TransferMoneyContext.java
@@ -0,0 +1,119 @@
+/*
+ *  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.polygene.dci.moneytransfer.context;
+
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.dci.moneytransfer.domain.data.BalanceData;
+
+/**
+ * Context for transfer of money between two accounts. Roles are defined within the context,
+ * and only the role maps know about them outside of this context.
+ */
+public class TransferMoneyContext
+{
+    // Object->Role mappings
+    public SourceAccountRole sourceAccount;
+    public DestinationAccountRole destinationAccount;
+
+    // Context setup
+    // Objects are specified using their data interface, and then cast to the role interfaces
+    public TransferMoneyContext bind( BalanceData source, BalanceData destination )
+    {
+        this.sourceAccount = (SourceAccountRole) source;
+        this.destinationAccount = (DestinationAccountRole) destination;
+        return this;
+    }
+
+    // Interactions
+    public Integer availableFunds()
+    {
+        return sourceAccount.availableFunds();
+    }
+
+    public void transfer( int amount )
+        throws IllegalArgumentException
+    {
+        sourceAccount.transfer( amount, destinationAccount );
+    }
+
+    // More interactions could go here...
+
+    // Roles defined by this context, with default implementations
+    @Mixins( SourceAccountRole.Mixin.class )
+    public interface SourceAccountRole
+    {
+        // Role Methods
+        public void transfer( int amount, DestinationAccountRole destinationAccount )
+            throws IllegalArgumentException;
+
+        Integer availableFunds();
+
+        // Default implementation
+
+        class Mixin
+            implements SourceAccountRole
+        {
+            @This
+            BalanceData data;
+
+            public Integer availableFunds()
+            {
+                // Could be balance, or balance - non-confirmed transfers, or somesuch
+                return data.getBalance();
+            }
+
+            public void transfer( int amount, DestinationAccountRole destinationAccount )
+                throws IllegalArgumentException
+            {
+                // Validate command
+                if( !( data.getBalance() >= amount ) )
+                {
+                    throw new IllegalArgumentException( "Not enough available funds" );
+                }
+
+                // Command is ok - create events in the data
+                data.decreasedBalance( amount );
+
+                // Look up the destination account from the current transfer context
+                destinationAccount.deposit( amount );
+            }
+        }
+    }
+
+    @Mixins( DestinationAccountRole.Mixin.class )
+    public interface DestinationAccountRole
+    {
+        public void deposit( int amount );
+
+        class Mixin
+            implements DestinationAccountRole
+        {
+            @This
+            BalanceData data;
+
+            public void deposit( int amount )
+            {
+                data.increasedBalance( amount );
+            }
+        }
+    }
+}
diff --git a/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/context/TransferMoneyContext2.java b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/context/TransferMoneyContext2.java
new file mode 100644
index 0000000..95be11c
--- /dev/null
+++ b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/context/TransferMoneyContext2.java
@@ -0,0 +1,95 @@
+/*
+ *  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.polygene.dci.moneytransfer.context;
+
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.dci.moneytransfer.domain.data.BalanceData;
+import org.apache.polygene.library.constraints.annotation.GreaterThan;
+
+/**
+ * Context for transfer of money between two accounts. Roles are defined within the context,
+ * and only the role maps know about them outside of this context.
+ */
+public class TransferMoneyContext2
+    implements TransientComposite
+{
+    // Object->Role mappings
+    private SourceAccountRole sourceAccount = new SourceAccountRole();
+    private DestinationAccountRole destinationAccount = new DestinationAccountRole();
+
+    public TransferMoneyContext2 bind( BalanceData source, BalanceData destination )
+    {
+        // Bind methodful roles to data instances
+        sourceAccount.bind( source );
+        destinationAccount.bind( destination );
+        return this;
+    }
+
+    // Interactions
+    public Integer availableFunds()
+    {
+        return sourceAccount.availableFunds();
+    }
+
+    public void transfer( @GreaterThan( 0 ) int amount )
+        throws IllegalArgumentException
+    {
+        sourceAccount.transfer( amount );
+    }
+
+    // More interactions could go here...
+
+    // Roles defined by this context, with default implementations
+    class SourceAccountRole
+        extends Role<BalanceData>
+    {
+        Integer availableFunds()
+        {
+            // Could be balance, or balance - non-confirmed transfers, or somesuch
+            return self.getBalance();
+        }
+
+        void transfer( int amount )
+            throws IllegalArgumentException
+        {
+            // Validate command
+            if( !( self.getBalance() >= amount ) )
+            {
+                throw new IllegalArgumentException( "Not enough available funds" );
+            }
+
+            // Command is ok - create events in the data
+            self.decreasedBalance( amount );
+
+            // Look up the destination account from the current transfer context
+            destinationAccount.deposit( amount );
+        }
+    }
+
+    class DestinationAccountRole
+        extends Role<BalanceData>
+    {
+        void deposit( int amount )
+        {
+            self.increasedBalance( amount );
+        }
+    }
+}
diff --git a/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/domain/data/BalanceData.java b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/domain/data/BalanceData.java
new file mode 100644
index 0000000..11e0fe8
--- /dev/null
+++ b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/domain/data/BalanceData.java
@@ -0,0 +1,67 @@
+/*
+ *  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.polygene.dci.moneytransfer.domain.data;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.constraints.annotation.GreaterThan;
+
+/**
+ * Maintain a balance for an account, of any type. Methods are in past tense,
+ * and are considered events. Only minimal sanity checks are performed.
+ * The roles invoking these methods decide if it's ok to perform the change or not.
+ */
+@Mixins( BalanceData.Mixin.class )
+public interface BalanceData
+{
+    void increasedBalance( @GreaterThan( 0 ) Integer amount );
+
+    void decreasedBalance( @GreaterThan( 0 ) Integer amount );
+
+    Integer getBalance();
+
+    // Default implementation
+
+    class Mixin
+        implements BalanceData
+    {
+        @State
+        @UseDefaults
+        Property<Integer> balance;
+
+        public void increasedBalance( Integer amount )
+        {
+            balance.set( balance.get() + amount );
+        }
+
+        public void decreasedBalance( Integer amount )
+        {
+            balance.set( balance.get() - amount );
+        }
+
+        public Integer getBalance()
+        {
+            return balance.get();
+        }
+    }
+}
diff --git a/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/domain/entity/CheckingAccountEntity.java b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/domain/entity/CheckingAccountEntity.java
new file mode 100644
index 0000000..458bd8d
--- /dev/null
+++ b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/domain/entity/CheckingAccountEntity.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.dci.moneytransfer.domain.entity;
+
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.dci.moneytransfer.domain.data.BalanceData;
+
+/**
+ * You can transfer money to and from a checking account
+ */
+public interface CheckingAccountEntity
+    extends EntityComposite,
+    // Data
+            BalanceData
+{
+}
diff --git a/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/domain/entity/CreditorEntity.java b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/domain/entity/CreditorEntity.java
new file mode 100644
index 0000000..3c57099
--- /dev/null
+++ b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/domain/entity/CreditorEntity.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.dci.moneytransfer.domain.entity;
+
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.dci.moneytransfer.domain.data.BalanceData;
+
+/**
+ * You can transfer money to a creditor, but not get money out from it
+ */
+public interface CreditorEntity
+    extends EntityComposite,
+    // Data
+            BalanceData
+{
+}
diff --git a/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/domain/entity/SavingsAccountEntity.java b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/domain/entity/SavingsAccountEntity.java
new file mode 100644
index 0000000..bd22752
--- /dev/null
+++ b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/domain/entity/SavingsAccountEntity.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.dci.moneytransfer.domain.entity;
+
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.dci.moneytransfer.domain.data.BalanceData;
+
+/**
+ * A savings account can be a source account, but not a destination account
+ */
+public interface SavingsAccountEntity
+    extends EntityComposite,
+    // Data
+            BalanceData
+{
+}
diff --git a/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/rolemap/CheckingAccountRolemap.java b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/rolemap/CheckingAccountRolemap.java
new file mode 100644
index 0000000..947087f
--- /dev/null
+++ b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/rolemap/CheckingAccountRolemap.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.dci.moneytransfer.rolemap;
+
+import org.apache.polygene.dci.moneytransfer.context.PayBillsContext;
+import org.apache.polygene.dci.moneytransfer.context.TransferMoneyContext;
+import org.apache.polygene.dci.moneytransfer.domain.entity.CheckingAccountEntity;
+
+/**
+ * You can transfer money to and from a checking account
+ */
+public interface CheckingAccountRolemap
+    extends CheckingAccountEntity,
+    // Roles
+            TransferMoneyContext.SourceAccountRole,
+            TransferMoneyContext.DestinationAccountRole,
+
+            PayBillsContext.SourceAccountRole
+{
+}
diff --git a/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/rolemap/CreditorRolemap.java b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/rolemap/CreditorRolemap.java
new file mode 100644
index 0000000..2fc99b9
--- /dev/null
+++ b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/rolemap/CreditorRolemap.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.dci.moneytransfer.rolemap;
+
+import org.apache.polygene.dci.moneytransfer.context.TransferMoneyContext;
+import org.apache.polygene.dci.moneytransfer.domain.entity.CreditorEntity;
+
+/**
+ * You can transfer money to a creditor, but not get money out from it
+ */
+public interface CreditorRolemap
+    extends CreditorEntity,
+    // Roles
+            TransferMoneyContext.DestinationAccountRole
+{
+}
diff --git a/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/rolemap/SavingsAccountRolemap.java b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/rolemap/SavingsAccountRolemap.java
new file mode 100644
index 0000000..06b4428
--- /dev/null
+++ b/samples/dci/src/main/java/org/apache/polygene/dci/moneytransfer/rolemap/SavingsAccountRolemap.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.dci.moneytransfer.rolemap;
+
+import org.apache.polygene.dci.moneytransfer.context.TransferMoneyContext;
+import org.apache.polygene.dci.moneytransfer.domain.entity.SavingsAccountEntity;
+
+/**
+ * A savings account can be a source account, but not a destination account
+ */
+public interface SavingsAccountRolemap
+    extends SavingsAccountEntity,
+    // Roles
+            TransferMoneyContext.SourceAccountRole
+{
+}
diff --git a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/context/PayBillsContext.java b/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/context/PayBillsContext.java
deleted file mode 100644
index 3902a19..0000000
--- a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/context/PayBillsContext.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.dci.moneytransfer.context;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.dci.moneytransfer.domain.data.BalanceData;
-import org.qi4j.dci.moneytransfer.rolemap.CreditorRolemap;
-
-/**
- * Context for paying bills from an account to a list of creditor accounts.
- * <p>
- * Roles are defined within the context. A RoleMap lists what Roles an entity can play.
- * </p>
- */
-public class PayBillsContext
-{
-    public SourceAccountRole sourceAccount;
-
-    public PayBillsContext bind( BalanceData account )
-    {
-        sourceAccount = (SourceAccountRole) account;
-        return this;
-    }
-
-    public void payBills()
-        throws Exception
-    {
-        sourceAccount.payBills();
-    }
-
-    /**
-     * The SourceAccountRole orchestrates the Pay Bills use case interactions.
-     * <p>
-     * Code matches the use case text carefully (see references below).
-     * </p>
-     * <p>
-     * Pay Bills use case scenario:
-     * </p>
-     * <ol>
-     * <li> Bank finds creditors (could be a use case scenario in itself)</li>
-     * <li> Bank calculates the amount owed to creditors</li>
-     * <li>Bank verifies sufficient funds</li>
-     * <li>Bank transfer money to each creditor</li>
-     * </ol>
-     *
-     * <p>
-     * Algorithm (steps to implement the scenario):
-     * </p>
-     * <p>
-     * 1a) Source Account finds list of creditors
-     * </p>
-     * <p>
-     * 2a) Source Account loops creditors to find the sum owed
-     * </p>
-     * <p>
-     * 3a) Source Account verifies that its current balance is greater than the sum owed, and throws an exception if not
-     * </p>
-     * <p>
-     * 4a) Source Account loops creditors
-     * </p>
-     * <p>
-     * 4b) Make a MoneyTransfer of the amount owed to each creditor
-     * </p>
-     */
-
-    @Mixins( SourceAccountRole.Mixin.class )
-    public interface SourceAccountRole
-    {
-        void payBills()
-            throws Exception;
-
-        class Mixin
-            implements SourceAccountRole
-        {
-            @Structure
-            UnitOfWorkFactory uowf;
-
-            @This
-            BalanceData data;
-
-            public void payBills()
-                throws IllegalArgumentException
-            {
-                List<BalanceData> creditors = getCreditors();                                             // 1a
-
-                Integer sumOwed = getSumOwedTo( creditors );                                              // 2a
-
-                if( data.getBalance() - sumOwed < 0 )                                                      // 3a
-                {
-                    throw new IllegalArgumentException( "Insufficient funds to pay bills." );
-                }
-
-                final TransferMoneyContext transferMoney = new TransferMoneyContext();
-                for( BalanceData creditor : creditors )                                                    // 4a
-                {
-                    if( creditor.getBalance() < 0 )
-                    {
-                        final Integer amountOwed = -creditor.getBalance();
-
-                        // Bind nested context and execute enactment
-                        transferMoney.bind( data, creditor ).transfer( amountOwed );                      // 4b
-                    }
-                }
-            }
-
-            // Internal helper methods to make the code above more readable / comparable to the algorithm text
-
-            private List<BalanceData> getCreditors()
-            {
-                // Creditor retrieval could be a use case in itself...
-                List<BalanceData> creditors = new ArrayList<BalanceData>();
-                creditors.add( uowf.currentUnitOfWork().get( CreditorRolemap.class, "BakerAccount" ) );
-                creditors.add( uowf.currentUnitOfWork().get( CreditorRolemap.class, "ButcherAccount" ) );
-                return creditors;
-            }
-
-            private Integer getSumOwedTo( List<BalanceData> creditors )
-            {
-                Integer sumOwed = 0;
-                for( BalanceData creditor : creditors )
-                {
-                    sumOwed += creditor.getBalance() < 0 ? -creditor.getBalance() : 0;
-                }
-
-                return sumOwed;
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/context/PayBillsContext2.java b/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/context/PayBillsContext2.java
deleted file mode 100644
index c4030ba..0000000
--- a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/context/PayBillsContext2.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.dci.moneytransfer.context;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.dci.moneytransfer.domain.data.BalanceData;
-
-/**
- * Context for paying bills from an account to a list of creditor accounts.
- * <p>
- * Roles are defined within the context.
- * A RoleMap lists what Roles an entity can play.
- * </p>
- */
-public class PayBillsContext2
-{
-    @Structure
-    UnitOfWorkFactory uowf;
-
-    private SourceAccountRole sourceAccount = new SourceAccountRole();
-
-    public PayBillsContext2 bind( BalanceData account )
-    {
-        sourceAccount.bind( account );
-        return this;
-    }
-
-    public void payBills()
-        throws Exception
-    {
-        sourceAccount.payBills();
-    }
-
-    /**
-     * The SourceAccountRole orchestrates the Pay Bills use case interactions.
-     * <p>
-     * Code matches the use case text carefully (see references below).
-     * </p>
-     * <p>
-     * Pay Bills use case scenario:
-     * </p>
-     * <p>
-     * 1) Bank finds creditors (could be a use case scenario in itself)
-     * </p>
-     * <p>
-     * 2) Bank calculates the amount owed to creditors
-     * </p>
-     * <p>
-     * 3) Bank verifies sufficient funds
-     * </p>
-     * <p>
-     * 4) Bank transfer money to each creditor
-     * </p>
-     * <p>
-     * Algorithm (steps to implement the scenario):
-     * </p>
-     * <p>
-     * <p>
-     * 1a) Source Account finds list of creditors
-     * </p>
-     * <p>
-     * 2a) Source Account loops creditors to find the sum owed
-     * </p>
-     * <p>
-     * 3a) Source Account verifies that its current balance is greater than the sum owed, and throws an exception if not
-     * </p>
-     * <p>
-     * 4a) Source Account loops creditors
-     * <p>
-     * 4b) Make a MoneyTransfer of the amount owed to each creditor
-     * </p>
-     */
-    class SourceAccountRole
-        extends Role<BalanceData>
-    {
-        void payBills()
-            throws IllegalArgumentException
-        {
-            List<BalanceData> creditors = getCreditors();                                             // 1a
-
-            Integer sumOwed = getSumOwedTo( creditors );                                              // 2a
-
-            if( self.getBalance() - sumOwed < 0 )                                                      // 3a
-            {
-                throw new IllegalArgumentException( "Insufficient funds to pay bills." );
-            }
-
-            final TransferMoneyContext2 transferMoney = new TransferMoneyContext2();
-            for( BalanceData creditor : creditors )                                                    // 4a
-            {
-                if( creditor.getBalance() < 0 )
-                {
-                    final Integer amountOwed = -creditor.getBalance();
-
-                    // Bind nested context and execute enactment
-                    transferMoney.bind( self, creditor ).transfer( amountOwed );                      // 4b
-                }
-            }
-        }
-
-        // Internal helper methods to make the code above more readable / comparable to the algorithm text
-
-        private List<BalanceData> getCreditors()
-        {
-            // Creditor retrieval could be a use case in itself...
-            List<BalanceData> creditors = new ArrayList<BalanceData>();
-            creditors.add( uowf.currentUnitOfWork().get( BalanceData.class, "BakerAccount" ) );
-            creditors.add( uowf.currentUnitOfWork().get( BalanceData.class, "ButcherAccount" ) );
-            return creditors;
-        }
-
-        private Integer getSumOwedTo( List<BalanceData> creditors )
-        {
-            Integer sumOwed = 0;
-            for( BalanceData creditor : creditors )
-            {
-                sumOwed += creditor.getBalance() < 0 ? -creditor.getBalance() : 0;
-            }
-
-            return sumOwed;
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/context/Role.java b/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/context/Role.java
deleted file mode 100644
index 8cd32bf..0000000
--- a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/context/Role.java
+++ /dev/null
@@ -1,75 +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.qi4j.dci.moneytransfer.context;
-
-/**
- * TODO
- */
-
-/**
- * Base class for methodful roles
- */
-public class Role<T>
-    implements Comparable<Role<T>>
-{
-    // Self reference to the bound Data object
-    protected T self;
-
-    public Role()
-    {
-    }
-
-    public Role( T self )
-    {
-        this.self = self;
-    }
-
-    public void bind( T newSelf )
-    {
-        self = newSelf;
-    }
-
-    public T self()
-    {
-        return self;
-    }
-
-    @Override
-    public boolean equals( Object obj )
-    {
-        if( obj == null )
-        {
-            return false;
-        }
-
-        if( obj instanceof Role )
-        {
-            return self.equals( ( (Role) obj ).self );
-        }
-        else
-        {
-            return false;
-        }
-    }
-
-    public int compareTo( Role<T> role )
-    {
-        return ( (Comparable<T>) self ).compareTo( role.self );
-    }
-}
diff --git a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/context/TransferMoneyContext.java b/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/context/TransferMoneyContext.java
deleted file mode 100644
index 3a0b497..0000000
--- a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/context/TransferMoneyContext.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.dci.moneytransfer.context;
-
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.dci.moneytransfer.domain.data.BalanceData;
-
-/**
- * Context for transfer of money between two accounts. Roles are defined within the context,
- * and only the role maps know about them outside of this context.
- */
-public class TransferMoneyContext
-{
-    // Object->Role mappings
-    public SourceAccountRole sourceAccount;
-    public DestinationAccountRole destinationAccount;
-
-    // Context setup
-    // Objects are specified using their data interface, and then cast to the role interfaces
-    public TransferMoneyContext bind( BalanceData source, BalanceData destination )
-    {
-        this.sourceAccount = (SourceAccountRole) source;
-        this.destinationAccount = (DestinationAccountRole) destination;
-        return this;
-    }
-
-    // Interactions
-    public Integer availableFunds()
-    {
-        return sourceAccount.availableFunds();
-    }
-
-    public void transfer( int amount )
-        throws IllegalArgumentException
-    {
-        sourceAccount.transfer( amount, destinationAccount );
-    }
-
-    // More interactions could go here...
-
-    // Roles defined by this context, with default implementations
-    @Mixins( SourceAccountRole.Mixin.class )
-    public interface SourceAccountRole
-    {
-        // Role Methods
-        public void transfer( int amount, DestinationAccountRole destinationAccount )
-            throws IllegalArgumentException;
-
-        Integer availableFunds();
-
-        // Default implementation
-
-        class Mixin
-            implements SourceAccountRole
-        {
-            @This
-            BalanceData data;
-
-            public Integer availableFunds()
-            {
-                // Could be balance, or balance - non-confirmed transfers, or somesuch
-                return data.getBalance();
-            }
-
-            public void transfer( int amount, DestinationAccountRole destinationAccount )
-                throws IllegalArgumentException
-            {
-                // Validate command
-                if( !( data.getBalance() >= amount ) )
-                {
-                    throw new IllegalArgumentException( "Not enough available funds" );
-                }
-
-                // Command is ok - create events in the data
-                data.decreasedBalance( amount );
-
-                // Look up the destination account from the current transfer context
-                destinationAccount.deposit( amount );
-            }
-        }
-    }
-
-    @Mixins( DestinationAccountRole.Mixin.class )
-    public interface DestinationAccountRole
-    {
-        public void deposit( int amount );
-
-        class Mixin
-            implements DestinationAccountRole
-        {
-            @This
-            BalanceData data;
-
-            public void deposit( int amount )
-            {
-                data.increasedBalance( amount );
-            }
-        }
-    }
-}
diff --git a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/context/TransferMoneyContext2.java b/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/context/TransferMoneyContext2.java
deleted file mode 100644
index 5bc1898..0000000
--- a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/context/TransferMoneyContext2.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.dci.moneytransfer.context;
-
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.dci.moneytransfer.domain.data.BalanceData;
-import org.qi4j.library.constraints.annotation.GreaterThan;
-
-/**
- * Context for transfer of money between two accounts. Roles are defined within the context,
- * and only the role maps know about them outside of this context.
- */
-public class TransferMoneyContext2
-    implements TransientComposite
-{
-    // Object->Role mappings
-    private SourceAccountRole sourceAccount = new SourceAccountRole();
-    private DestinationAccountRole destinationAccount = new DestinationAccountRole();
-
-    public TransferMoneyContext2 bind( BalanceData source, BalanceData destination )
-    {
-        // Bind methodful roles to data instances
-        sourceAccount.bind( source );
-        destinationAccount.bind( destination );
-        return this;
-    }
-
-    // Interactions
-    public Integer availableFunds()
-    {
-        return sourceAccount.availableFunds();
-    }
-
-    public void transfer( @GreaterThan( 0 ) int amount )
-        throws IllegalArgumentException
-    {
-        sourceAccount.transfer( amount );
-    }
-
-    // More interactions could go here...
-
-    // Roles defined by this context, with default implementations
-    class SourceAccountRole
-        extends Role<BalanceData>
-    {
-        Integer availableFunds()
-        {
-            // Could be balance, or balance - non-confirmed transfers, or somesuch
-            return self.getBalance();
-        }
-
-        void transfer( int amount )
-            throws IllegalArgumentException
-        {
-            // Validate command
-            if( !( self.getBalance() >= amount ) )
-            {
-                throw new IllegalArgumentException( "Not enough available funds" );
-            }
-
-            // Command is ok - create events in the data
-            self.decreasedBalance( amount );
-
-            // Look up the destination account from the current transfer context
-            destinationAccount.deposit( amount );
-        }
-    }
-
-    class DestinationAccountRole
-        extends Role<BalanceData>
-    {
-        void deposit( int amount )
-        {
-            self.increasedBalance( amount );
-        }
-    }
-}
diff --git a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/domain/data/BalanceData.java b/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/domain/data/BalanceData.java
deleted file mode 100644
index 2551927..0000000
--- a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/domain/data/BalanceData.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.dci.moneytransfer.domain.data;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.injection.scope.State;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.library.constraints.annotation.GreaterThan;
-
-/**
- * Maintain a balance for an account, of any type. Methods are in past tense,
- * and are considered events. Only minimal sanity checks are performed.
- * The roles invoking these methods decide if it's ok to perform the change or not.
- */
-@Mixins( BalanceData.Mixin.class )
-public interface BalanceData
-{
-    void increasedBalance( @GreaterThan( 0 ) Integer amount );
-
-    void decreasedBalance( @GreaterThan( 0 ) Integer amount );
-
-    Integer getBalance();
-
-    // Default implementation
-
-    class Mixin
-        implements BalanceData
-    {
-        @State
-        @UseDefaults
-        Property<Integer> balance;
-
-        public void increasedBalance( Integer amount )
-        {
-            balance.set( balance.get() + amount );
-        }
-
-        public void decreasedBalance( Integer amount )
-        {
-            balance.set( balance.get() - amount );
-        }
-
-        public Integer getBalance()
-        {
-            return balance.get();
-        }
-    }
-}
diff --git a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/domain/entity/CheckingAccountEntity.java b/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/domain/entity/CheckingAccountEntity.java
deleted file mode 100644
index c061676..0000000
--- a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/domain/entity/CheckingAccountEntity.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.dci.moneytransfer.domain.entity;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.dci.moneytransfer.domain.data.BalanceData;
-
-/**
- * You can transfer money to and from a checking account
- */
-public interface CheckingAccountEntity
-    extends EntityComposite,
-    // Data
-            BalanceData
-{
-}
diff --git a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/domain/entity/CreditorEntity.java b/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/domain/entity/CreditorEntity.java
deleted file mode 100644
index 83dcd3d..0000000
--- a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/domain/entity/CreditorEntity.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.dci.moneytransfer.domain.entity;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.dci.moneytransfer.domain.data.BalanceData;
-
-/**
- * You can transfer money to a creditor, but not get money out from it
- */
-public interface CreditorEntity
-    extends EntityComposite,
-    // Data
-            BalanceData
-{
-}
diff --git a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/domain/entity/SavingsAccountEntity.java b/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/domain/entity/SavingsAccountEntity.java
deleted file mode 100644
index 9cb51f7..0000000
--- a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/domain/entity/SavingsAccountEntity.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.dci.moneytransfer.domain.entity;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.dci.moneytransfer.domain.data.BalanceData;
-
-/**
- * A savings account can be a source account, but not a destination account
- */
-public interface SavingsAccountEntity
-    extends EntityComposite,
-    // Data
-            BalanceData
-{
-}
diff --git a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/rolemap/CheckingAccountRolemap.java b/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/rolemap/CheckingAccountRolemap.java
deleted file mode 100644
index d4c8e29..0000000
--- a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/rolemap/CheckingAccountRolemap.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.dci.moneytransfer.rolemap;
-
-import org.qi4j.dci.moneytransfer.context.PayBillsContext;
-import org.qi4j.dci.moneytransfer.context.TransferMoneyContext;
-import org.qi4j.dci.moneytransfer.domain.entity.CheckingAccountEntity;
-
-/**
- * You can transfer money to and from a checking account
- */
-public interface CheckingAccountRolemap
-    extends CheckingAccountEntity,
-    // Roles
-            TransferMoneyContext.SourceAccountRole,
-            TransferMoneyContext.DestinationAccountRole,
-
-            PayBillsContext.SourceAccountRole
-{
-}
diff --git a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/rolemap/CreditorRolemap.java b/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/rolemap/CreditorRolemap.java
deleted file mode 100644
index 6154167..0000000
--- a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/rolemap/CreditorRolemap.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.dci.moneytransfer.rolemap;
-
-import org.qi4j.dci.moneytransfer.context.TransferMoneyContext;
-import org.qi4j.dci.moneytransfer.domain.entity.CreditorEntity;
-
-/**
- * You can transfer money to a creditor, but not get money out from it
- */
-public interface CreditorRolemap
-    extends CreditorEntity,
-    // Roles
-            TransferMoneyContext.DestinationAccountRole
-{
-}
diff --git a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/rolemap/SavingsAccountRolemap.java b/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/rolemap/SavingsAccountRolemap.java
deleted file mode 100644
index 457aee6..0000000
--- a/samples/dci/src/main/java/org/qi4j/dci/moneytransfer/rolemap/SavingsAccountRolemap.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.dci.moneytransfer.rolemap;
-
-import org.qi4j.dci.moneytransfer.context.TransferMoneyContext;
-import org.qi4j.dci.moneytransfer.domain.entity.SavingsAccountEntity;
-
-/**
- * A savings account can be a source account, but not a destination account
- */
-public interface SavingsAccountRolemap
-    extends SavingsAccountEntity,
-    // Roles
-            TransferMoneyContext.SourceAccountRole
-{
-}
diff --git a/samples/dci/src/test/java/org/apache/polygene/dci/moneytransfer/test/AccountIds.java b/samples/dci/src/test/java/org/apache/polygene/dci/moneytransfer/test/AccountIds.java
new file mode 100644
index 0000000..3530592
--- /dev/null
+++ b/samples/dci/src/test/java/org/apache/polygene/dci/moneytransfer/test/AccountIds.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.dci.moneytransfer.test;
+
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+
+public interface AccountIds
+{
+    Identity SAVINGS_ACCOUNT_ID = new StringIdentity( "SavingsAccountId" );
+    Identity CHECKING_ACCOUNT_ID = new StringIdentity( "CheckingAccountId" );
+    Identity CREDITOR_ID1 = new StringIdentity( "BakerAccount" );
+    Identity CREDITOR_ID2 = new StringIdentity( "ButcherAccount" );
+
+}
diff --git a/samples/dci/src/test/java/org/apache/polygene/dci/moneytransfer/test/TransferMoneyTest.java b/samples/dci/src/test/java/org/apache/polygene/dci/moneytransfer/test/TransferMoneyTest.java
new file mode 100644
index 0000000..f3814f7
--- /dev/null
+++ b/samples/dci/src/test/java/org/apache/polygene/dci/moneytransfer/test/TransferMoneyTest.java
@@ -0,0 +1,211 @@
+/*
+ *  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.polygene.dci.moneytransfer.test;
+
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.dci.moneytransfer.context.PayBillsContext;
+import org.apache.polygene.dci.moneytransfer.context.TransferMoneyContext;
+import org.apache.polygene.dci.moneytransfer.domain.data.BalanceData;
+import org.apache.polygene.dci.moneytransfer.domain.entity.CheckingAccountEntity;
+import org.apache.polygene.dci.moneytransfer.domain.entity.SavingsAccountEntity;
+import org.apache.polygene.dci.moneytransfer.rolemap.CheckingAccountRolemap;
+import org.apache.polygene.dci.moneytransfer.rolemap.CreditorRolemap;
+import org.apache.polygene.dci.moneytransfer.rolemap.SavingsAccountRolemap;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.apache.polygene.api.usecase.UsecaseBuilder.newUsecase;
+
+/**
+ * Test of TransferMoneyContext
+ */
+public class TransferMoneyTest
+        implements AccountIds
+{
+    private static SingletonAssembler assembler;
+    private static UnitOfWorkFactory uowf;
+
+    @BeforeClass
+    public static void setup()
+        throws Exception
+    {
+        assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.entities(
+                    CheckingAccountRolemap.class,
+                    SavingsAccountRolemap.class,
+                    CreditorRolemap.class );
+
+                new EntityTestAssembler().assemble( module );
+            }
+        };
+        uowf = assembler.module().unitOfWorkFactory();
+        bootstrapData( assembler );
+    }
+
+    @Before
+    public void beforeBalances()
+    {
+        System.out.println( "Before enactment:" );
+        printBalances();
+        System.out.println( "" );
+    }
+
+    @After
+    public void afterBalances()
+    {
+        System.out.println( "After enactment:" );
+        printBalances();
+        System.out.println( "-----------------" );
+    }
+
+    public void printBalances()
+    {
+        UnitOfWork uow = uowf.newUnitOfWork( UsecaseBuilder.newUsecase( "Print balances" ) );
+
+        try
+        {
+            System.out
+                .println( SAVINGS_ACCOUNT_ID + ":" + uow.get( BalanceData.class, SAVINGS_ACCOUNT_ID ).getBalance() );
+            System.out
+                .println( CHECKING_ACCOUNT_ID + ":" + uow.get( BalanceData.class, CHECKING_ACCOUNT_ID ).getBalance() );
+            System.out.println( CREDITOR_ID1 + ":" + uow.get( BalanceData.class, CREDITOR_ID1 ).getBalance() );
+            System.out.println( CREDITOR_ID2 + ":" + uow.get( BalanceData.class, CREDITOR_ID2 ).getBalance() );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    private static void bootstrapData( SingletonAssembler assembler )
+        throws Exception
+    {
+        UnitOfWork uow = uowf.newUnitOfWork( newUsecase( "Bootstrap data" ) );
+        try
+        {
+            SavingsAccountEntity savingsAccount = uow.newEntity( SavingsAccountEntity.class, SAVINGS_ACCOUNT_ID );
+            savingsAccount.increasedBalance(1000);
+
+            CheckingAccountEntity checkingAccount = uow.newEntity(CheckingAccountEntity.class, CHECKING_ACCOUNT_ID);
+            checkingAccount.increasedBalance(200);
+
+            // Create some creditor debt
+            BalanceData bakerAccount = uow.newEntity( CreditorRolemap.class, CREDITOR_ID1 );
+            bakerAccount.decreasedBalance( 50 );
+
+            BalanceData butcherAccount = uow.newEntity( CreditorRolemap.class, CREDITOR_ID2 );
+            butcherAccount.decreasedBalance( 90 );
+
+            // Save
+            uow.complete();
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void transferHalfOfMoneyFromSavingsToChecking()
+        throws Exception
+    {
+        UnitOfWork uow = uowf.newUnitOfWork( UsecaseBuilder.newUsecase( "Transfer from savings to checking" ) );
+
+        try
+        {
+            // Select source and destination
+            BalanceData source = uow.get( BalanceData.class, SAVINGS_ACCOUNT_ID );
+            BalanceData destination = uow.get( BalanceData.class, CHECKING_ACCOUNT_ID );
+
+            // Instantiate context and execute enactments with that context
+            TransferMoneyContext context = new TransferMoneyContext();
+            context.bind( source, destination );
+
+            // Query for half the balance
+            final Integer amountToTransfer = context.availableFunds() / 2;
+
+            // Transfer from savings to checking
+            context.transfer( amountToTransfer );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void transferTwiceOfMoneyFromSavingsToChecking()
+        throws Exception
+    {
+        UnitOfWork uow = uowf.newUnitOfWork( UsecaseBuilder.newUsecase( "Transfer from savings to checking" ) );
+
+        try
+        {
+            // Select source and destination
+            BalanceData source = uow.get( BalanceData.class, SAVINGS_ACCOUNT_ID );
+            BalanceData destination = uow.get( BalanceData.class, CHECKING_ACCOUNT_ID );
+
+            // Instantiate context and execute enactments with that context
+            TransferMoneyContext context = new TransferMoneyContext();
+            context.bind( source, destination );
+
+            // Query for double the balance
+            final Integer amountToTransfer = context.availableFunds() * 2;
+
+            // Transfer from savings to checking
+            context.transfer( amountToTransfer );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void payAllBills()
+        throws Exception
+    {
+        UnitOfWork uow = uowf.newUnitOfWork( newUsecase( "Pay all bills from checking to creditors" ) );
+        try
+        {
+            BalanceData source = uow.get( BalanceData.class, CHECKING_ACCOUNT_ID );
+
+            PayBillsContext context = new PayBillsContext();
+            context.bind( source ).payBills();
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+}
diff --git a/samples/dci/src/test/java/org/apache/polygene/dci/moneytransfer/test/TransferMoneyTest2.java b/samples/dci/src/test/java/org/apache/polygene/dci/moneytransfer/test/TransferMoneyTest2.java
new file mode 100644
index 0000000..19e0fb0
--- /dev/null
+++ b/samples/dci/src/test/java/org/apache/polygene/dci/moneytransfer/test/TransferMoneyTest2.java
@@ -0,0 +1,215 @@
+/*
+ *  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.polygene.dci.moneytransfer.test;
+
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.dci.moneytransfer.context.PayBillsContext2;
+import org.apache.polygene.dci.moneytransfer.context.TransferMoneyContext2;
+import org.apache.polygene.dci.moneytransfer.domain.data.BalanceData;
+import org.apache.polygene.dci.moneytransfer.domain.entity.CheckingAccountEntity;
+import org.apache.polygene.dci.moneytransfer.domain.entity.CreditorEntity;
+import org.apache.polygene.dci.moneytransfer.domain.entity.SavingsAccountEntity;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.apache.polygene.api.usecase.UsecaseBuilder.newUsecase;
+
+/**
+ * Test of TransferMoneyContext
+ */
+public class TransferMoneyTest2
+        implements AccountIds
+{
+    private static Module module;
+    private static UnitOfWorkFactory uowf;
+
+    @BeforeClass
+    public static void setup()
+        throws Exception
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.entities(
+                    CheckingAccountEntity.class,
+                    SavingsAccountEntity.class,
+                    CreditorEntity.class );
+
+                new EntityTestAssembler().assemble( module );
+
+                module.transients( TransferMoneyContext2.class );
+                module.objects( PayBillsContext2.class );
+            }
+        };
+
+        module = assembler.module();
+        uowf = module.unitOfWorkFactory();
+        bootstrapData();
+    }
+
+    @Before
+    public void beforeBalances()
+    {
+        System.out.println( "Before enactment:" );
+        printBalances();
+        System.out.println( "" );
+    }
+
+    @After
+    public void afterBalances()
+    {
+        System.out.println( "After enactment:" );
+        printBalances();
+        System.out.println( "-----------------" );
+    }
+
+    private void printBalances()
+    {
+        UnitOfWork uow = module.unitOfWorkFactory().newUnitOfWork( UsecaseBuilder.newUsecase( "Print balances" ) );
+
+        try
+        {
+            System.out
+                .println( SAVINGS_ACCOUNT_ID + ":" + uow.get( BalanceData.class, SAVINGS_ACCOUNT_ID ).getBalance() );
+            System.out
+                .println( CHECKING_ACCOUNT_ID + ":" + uow.get( BalanceData.class, CHECKING_ACCOUNT_ID ).getBalance() );
+            System.out.println( CREDITOR_ID1 + ":" + uow.get( BalanceData.class, CREDITOR_ID1 ).getBalance() );
+            System.out.println( CREDITOR_ID2 + ":" + uow.get( BalanceData.class, CREDITOR_ID2 ).getBalance() );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    private static void bootstrapData()
+        throws Exception
+    {
+        UnitOfWork uow = uowf.newUnitOfWork( newUsecase( "Bootstrap data" ) );
+        try
+        {
+            SavingsAccountEntity account = uow.newEntity( SavingsAccountEntity.class, SAVINGS_ACCOUNT_ID );
+            account.increasedBalance( 1000 );
+
+            CheckingAccountEntity checkingAccount = uow.newEntity(CheckingAccountEntity.class, CHECKING_ACCOUNT_ID);
+            checkingAccount.increasedBalance(200);
+
+            // Create some creditor debt
+            BalanceData bakerAccount = uow.newEntity( CreditorEntity.class, CREDITOR_ID1 );
+            bakerAccount.decreasedBalance( 50 );
+
+            BalanceData butcherAccount = uow.newEntity( CreditorEntity.class, CREDITOR_ID2 );
+            butcherAccount.decreasedBalance( 90 );
+
+            // Save
+            uow.complete();
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void transferHalfOfMoneyFromSavingsToChecking()
+        throws Exception
+    {
+        UnitOfWork uow = uowf.newUnitOfWork( UsecaseBuilder.newUsecase( "Transfer from savings to checking" ) );
+
+        try
+        {
+            // Select source and destination
+            BalanceData source = uow.get( BalanceData.class, SAVINGS_ACCOUNT_ID );
+            BalanceData destination = uow.get( BalanceData.class, CHECKING_ACCOUNT_ID );
+
+            // Instantiate context and execute enactments with that context
+            TransferMoneyContext2 context = module.newTransient( TransferMoneyContext2.class )
+                .bind( source, destination );
+
+            // Query for half the balance
+            final Integer amountToTransfer = context.availableFunds() / 2;
+
+            // Transfer from savings to checking
+            context.transfer( amountToTransfer );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test( expected = IllegalArgumentException.class )
+    public void transferTwiceOfMoneyFromSavingsToChecking()
+        throws Exception
+    {
+        UnitOfWork uow = uowf.newUnitOfWork( UsecaseBuilder.newUsecase( "Transfer from savings to checking" ) );
+
+        try
+        {
+            // Select source and destination
+            BalanceData source = uow.get( BalanceData.class, SAVINGS_ACCOUNT_ID );
+            BalanceData destination = uow.get( BalanceData.class, CHECKING_ACCOUNT_ID );
+
+            // Instantiate context and execute enactments with that context
+            TransferMoneyContext2 context = module.newTransient( TransferMoneyContext2.class )
+                .bind( source, destination );
+
+            // Query for double the balance
+            final Integer amountToTransfer = context.availableFunds() * 2;
+
+            // Transfer from savings to checking
+            context.transfer( amountToTransfer );
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+
+    @Test
+    public void payAllBills()
+        throws Exception
+    {
+        UnitOfWork uow = uowf.newUnitOfWork( newUsecase( "Pay all bills from checking to creditors" ) );
+        try
+        {
+            BalanceData source = uow.get( BalanceData.class, CHECKING_ACCOUNT_ID );
+
+            PayBillsContext2 context = module.newObject( PayBillsContext2.class );
+            context.bind( source ).payBills();
+        }
+        finally
+        {
+            uow.discard();
+        }
+    }
+}
diff --git a/samples/dci/src/test/java/org/qi4j/dci/moneytransfer/test/TransferMoneyTest.java b/samples/dci/src/test/java/org/qi4j/dci/moneytransfer/test/TransferMoneyTest.java
deleted file mode 100644
index 6096202..0000000
--- a/samples/dci/src/test/java/org/qi4j/dci/moneytransfer/test/TransferMoneyTest.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.dci.moneytransfer.test;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.dci.moneytransfer.context.PayBillsContext;
-import org.qi4j.dci.moneytransfer.context.TransferMoneyContext;
-import org.qi4j.dci.moneytransfer.domain.data.BalanceData;
-import org.qi4j.dci.moneytransfer.domain.entity.CheckingAccountEntity;
-import org.qi4j.dci.moneytransfer.domain.entity.SavingsAccountEntity;
-import org.qi4j.dci.moneytransfer.rolemap.CheckingAccountRolemap;
-import org.qi4j.dci.moneytransfer.rolemap.CreditorRolemap;
-import org.qi4j.dci.moneytransfer.rolemap.SavingsAccountRolemap;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.qi4j.api.usecase.UsecaseBuilder.newUsecase;
-
-/**
- * Test of TransferMoneyContext
- */
-public class TransferMoneyTest
-{
-    private static SingletonAssembler assembler;
-    public static final String SAVINGS_ACCOUNT_ID = "SavingsAccountId";
-    public static final String CHECKING_ACCOUNT_ID = "CheckingAccountId";
-    public static final String CREDITOR_ID1 = "BakerAccount";
-    public static final String CREDITOR_ID2 = "ButcherAccount";
-
-    @BeforeClass
-    public static void setup()
-        throws Exception
-    {
-        assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.entities(
-                    CheckingAccountRolemap.class,
-                    SavingsAccountRolemap.class,
-                    CreditorRolemap.class );
-
-                new EntityTestAssembler().assemble( module );
-            }
-        };
-
-        bootstrapData( assembler );
-    }
-
-    @Before
-    public void beforeBalances()
-    {
-        System.out.println( "Before enactment:" );
-        printBalances();
-        System.out.println( "" );
-    }
-
-    @After
-    public void afterBalances()
-    {
-        System.out.println( "After enactment:" );
-        printBalances();
-        System.out.println( "-----------------" );
-    }
-
-    public void printBalances()
-    {
-        UnitOfWork uow = assembler.module().newUnitOfWork( UsecaseBuilder.newUsecase( "Print balances" ) );
-
-        try
-        {
-            System.out
-                .println( SAVINGS_ACCOUNT_ID + ":" + uow.get( BalanceData.class, SAVINGS_ACCOUNT_ID ).getBalance() );
-            System.out
-                .println( CHECKING_ACCOUNT_ID + ":" + uow.get( BalanceData.class, CHECKING_ACCOUNT_ID ).getBalance() );
-            System.out.println( CREDITOR_ID1 + ":" + uow.get( BalanceData.class, CREDITOR_ID1 ).getBalance() );
-            System.out.println( CREDITOR_ID2 + ":" + uow.get( BalanceData.class, CREDITOR_ID2 ).getBalance() );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    private static void bootstrapData( SingletonAssembler assembler )
-        throws Exception
-    {
-        UnitOfWork uow = assembler.module().newUnitOfWork( newUsecase( "Bootstrap data" ) );
-        try
-        {
-            SavingsAccountEntity savingsAccount = uow.newEntity( SavingsAccountEntity.class, SAVINGS_ACCOUNT_ID );
-            savingsAccount.increasedBalance(1000);
-
-            CheckingAccountEntity checkingAccount = uow.newEntity(CheckingAccountEntity.class, CHECKING_ACCOUNT_ID);
-            checkingAccount.increasedBalance(200);
-
-            // Create some creditor debt
-            BalanceData bakerAccount = uow.newEntity( CreditorRolemap.class, CREDITOR_ID1 );
-            bakerAccount.decreasedBalance( 50 );
-
-            BalanceData butcherAccount = uow.newEntity( CreditorRolemap.class, CREDITOR_ID2 );
-            butcherAccount.decreasedBalance( 90 );
-
-            // Save
-            uow.complete();
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void transferHalfOfMoneyFromSavingsToChecking()
-        throws Exception
-    {
-        UnitOfWork uow = assembler.module()
-            .newUnitOfWork( UsecaseBuilder.newUsecase( "Transfer from savings to checking" ) );
-
-        try
-        {
-            // Select source and destination
-            BalanceData source = uow.get( BalanceData.class, SAVINGS_ACCOUNT_ID );
-            BalanceData destination = uow.get( BalanceData.class, CHECKING_ACCOUNT_ID );
-
-            // Instantiate context and execute enactments with that context
-            TransferMoneyContext context = new TransferMoneyContext();
-            context.bind( source, destination );
-
-            // Query for half the balance
-            final Integer amountToTransfer = context.availableFunds() / 2;
-
-            // Transfer from savings to checking
-            context.transfer( amountToTransfer );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void transferTwiceOfMoneyFromSavingsToChecking()
-        throws Exception
-    {
-        UnitOfWork uow = assembler.module()
-            .newUnitOfWork( UsecaseBuilder.newUsecase( "Transfer from savings to checking" ) );
-
-        try
-        {
-            // Select source and destination
-            BalanceData source = uow.get( BalanceData.class, SAVINGS_ACCOUNT_ID );
-            BalanceData destination = uow.get( BalanceData.class, CHECKING_ACCOUNT_ID );
-
-            // Instantiate context and execute enactments with that context
-            TransferMoneyContext context = new TransferMoneyContext();
-            context.bind( source, destination );
-
-            // Query for double the balance
-            final Integer amountToTransfer = context.availableFunds() * 2;
-
-            // Transfer from savings to checking
-            context.transfer( amountToTransfer );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void payAllBills()
-        throws Exception
-    {
-        UnitOfWork uow = assembler.module().newUnitOfWork( newUsecase( "Pay all bills from checking to creditors" ) );
-        try
-        {
-            BalanceData source = uow.get( BalanceData.class, CHECKING_ACCOUNT_ID );
-
-            PayBillsContext context = new PayBillsContext();
-            context.bind( source ).payBills();
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-}
diff --git a/samples/dci/src/test/java/org/qi4j/dci/moneytransfer/test/TransferMoneyTest2.java b/samples/dci/src/test/java/org/qi4j/dci/moneytransfer/test/TransferMoneyTest2.java
deleted file mode 100644
index ad0f5f4..0000000
--- a/samples/dci/src/test/java/org/qi4j/dci/moneytransfer/test/TransferMoneyTest2.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (c) 2010, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.dci.moneytransfer.test;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.dci.moneytransfer.context.PayBillsContext2;
-import org.qi4j.dci.moneytransfer.context.TransferMoneyContext2;
-import org.qi4j.dci.moneytransfer.domain.data.BalanceData;
-import org.qi4j.dci.moneytransfer.domain.entity.CheckingAccountEntity;
-import org.qi4j.dci.moneytransfer.domain.entity.CreditorEntity;
-import org.qi4j.dci.moneytransfer.domain.entity.SavingsAccountEntity;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.qi4j.api.usecase.UsecaseBuilder.newUsecase;
-
-/**
- * Test of TransferMoneyContext
- */
-public class TransferMoneyTest2
-{
-    private static Module module;
-    public static final String SAVINGS_ACCOUNT_ID = "SavingsAccountId";
-    public static final String CHECKING_ACCOUNT_ID = "CheckingAccountId";
-    public static final String CREDITOR_ID1 = "BakerAccount";
-    public static final String CREDITOR_ID2 = "ButcherAccount";
-
-    @BeforeClass
-    public static void setup()
-        throws Exception
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.entities(
-                    CheckingAccountEntity.class,
-                    SavingsAccountEntity.class,
-                    CreditorEntity.class );
-
-                new EntityTestAssembler().assemble( module );
-
-                module.transients( TransferMoneyContext2.class );
-                module.objects( PayBillsContext2.class );
-            }
-        };
-
-        module = assembler.module();
-
-        bootstrapData();
-    }
-
-    @Before
-    public void beforeBalances()
-    {
-        System.out.println( "Before enactment:" );
-        printBalances();
-        System.out.println( "" );
-    }
-
-    @After
-    public void afterBalances()
-    {
-        System.out.println( "After enactment:" );
-        printBalances();
-        System.out.println( "-----------------" );
-    }
-
-    private void printBalances()
-    {
-        UnitOfWork uow = module.newUnitOfWork( UsecaseBuilder.newUsecase( "Print balances" ) );
-
-        try
-        {
-            System.out
-                .println( SAVINGS_ACCOUNT_ID + ":" + uow.get( BalanceData.class, SAVINGS_ACCOUNT_ID ).getBalance() );
-            System.out
-                .println( CHECKING_ACCOUNT_ID + ":" + uow.get( BalanceData.class, CHECKING_ACCOUNT_ID ).getBalance() );
-            System.out.println( CREDITOR_ID1 + ":" + uow.get( BalanceData.class, CREDITOR_ID1 ).getBalance() );
-            System.out.println( CREDITOR_ID2 + ":" + uow.get( BalanceData.class, CREDITOR_ID2 ).getBalance() );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    private static void bootstrapData()
-        throws Exception
-    {
-        UnitOfWork uow = module.newUnitOfWork( newUsecase( "Bootstrap data" ) );
-        try
-        {
-            SavingsAccountEntity account = uow.newEntity( SavingsAccountEntity.class, SAVINGS_ACCOUNT_ID );
-            account.increasedBalance( 1000 );
-
-            CheckingAccountEntity checkingAccount = uow.newEntity(CheckingAccountEntity.class, CHECKING_ACCOUNT_ID);
-            checkingAccount.increasedBalance(200);
-
-            // Create some creditor debt
-            BalanceData bakerAccount = uow.newEntity( CreditorEntity.class, CREDITOR_ID1 );
-            bakerAccount.decreasedBalance( 50 );
-
-            BalanceData butcherAccount = uow.newEntity( CreditorEntity.class, CREDITOR_ID2 );
-            butcherAccount.decreasedBalance( 90 );
-
-            // Save
-            uow.complete();
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void transferHalfOfMoneyFromSavingsToChecking()
-        throws Exception
-    {
-        UnitOfWork uow = module.newUnitOfWork( UsecaseBuilder.newUsecase( "Transfer from savings to checking" ) );
-
-        try
-        {
-            // Select source and destination
-            BalanceData source = uow.get( BalanceData.class, SAVINGS_ACCOUNT_ID );
-            BalanceData destination = uow.get( BalanceData.class, CHECKING_ACCOUNT_ID );
-
-            // Instantiate context and execute enactments with that context
-            TransferMoneyContext2 context = module.newTransient( TransferMoneyContext2.class )
-                .bind( source, destination );
-
-            // Query for half the balance
-            final Integer amountToTransfer = context.availableFunds() / 2;
-
-            // Transfer from savings to checking
-            context.transfer( amountToTransfer );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test( expected = IllegalArgumentException.class )
-    public void transferTwiceOfMoneyFromSavingsToChecking()
-        throws Exception
-    {
-        UnitOfWork uow = module.newUnitOfWork( UsecaseBuilder.newUsecase( "Transfer from savings to checking" ) );
-
-        try
-        {
-            // Select source and destination
-            BalanceData source = uow.get( BalanceData.class, SAVINGS_ACCOUNT_ID );
-            BalanceData destination = uow.get( BalanceData.class, CHECKING_ACCOUNT_ID );
-
-            // Instantiate context and execute enactments with that context
-            TransferMoneyContext2 context = module.newTransient( TransferMoneyContext2.class )
-                .bind( source, destination );
-
-            // Query for double the balance
-            final Integer amountToTransfer = context.availableFunds() * 2;
-
-            // Transfer from savings to checking
-            context.transfer( amountToTransfer );
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    @Test
-    public void payAllBills()
-        throws Exception
-    {
-        UnitOfWork uow = module.newUnitOfWork( newUsecase( "Pay all bills from checking to creditors" ) );
-        try
-        {
-            BalanceData source = uow.get( BalanceData.class, CHECKING_ACCOUNT_ID );
-
-            PayBillsContext2 context = module.newObject( PayBillsContext2.class );
-            context.bind( source ).payBills();
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-}
diff --git a/samples/dddsample2/src/main/java/org/qi4j/samples/cargo/app1/model/cargo/Cargo.java b/samples/dddsample2/src/main/java/org/qi4j/samples/cargo/app1/model/cargo/Cargo.java
deleted file mode 100755
index 796c0eb..0000000
--- a/samples/dddsample2/src/main/java/org/qi4j/samples/cargo/app1/model/cargo/Cargo.java
+++ /dev/null
@@ -1,230 +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.qi4j.samples.cargo.app1.model.cargo;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.association.Association;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.samples.cargo.app1.model.handling.HandlingHistory;
-import org.qi4j.samples.cargo.app1.model.location.Location;
-import org.qi4j.samples.cargo.app1.system.factories.DeliveryFactory;
-
-/**
- * A Cargo. This is the central class in the domain model,
- * and it is the root of the Cargo-Itinerary-Leg-Delivery-RouteSpecification aggregate.
- * <p>
- * A cargo is identified by a unique tracking id, and it always has an origin
- * and a route specification. The life cycle of a cargo begins with the booking procedure,
- * when the tracking id is assigned. During a (short) period of time, between booking
- * and initial routing, the cargo has no itinerary.
- * </p>
- * <p>
- * The booking clerk requests a list of possible routes, matching the route specification,
- * and assigns the cargo to one route. The route to which a cargo is assigned is described
- * by an itinerary.
- * </p>
- * <p>
- * A cargo can be re-routed during transport, on demand of the customer, in which case
- * a new route is specified for the cargo and a new route is requested. The old itinerary,
- * being a value object, is discarded and a new one is attached.
- * </p>
- * <p>
- * It may also happen that a cargo is accidentally misrouted, which should notify the proper
- * personnel and also trigger a re-routing procedure.
- * </p>
- * <p>
- * When a cargo is handled, the status of the delivery changes. Everything about the delivery
- * of the cargo is contained in the Delivery value object, which is replaced whenever a cargo
- * is handled by an asynchronous event triggered by the registration of the handling event.
- * </p>
- * <p>
- * The delivery can also be affected by routing changes, i.e. when a the route specification
- * changes, or the cargo is assigned to a new route. In that case, the delivery update is performed
- * synchronously within the cargo aggregate.
- * </p>
- * <p>
- * The life cycle of a cargo ends when the cargo is claimed by the customer.
- * </p>
- * <p>
- * The cargo aggregate, and the entre domain model, is built to solve the problem
- * of booking and tracking cargo. All important business rules for determining whether
- * or not a cargo is misdirected, what the current status of the cargo is (on board carrier,
- * in port etc), are captured in this aggregate.
- * </p>
- */
-@Mixins( Cargo.CargoMixin.class )
-public interface Cargo
-    extends EntityComposite
-{
-
-    TrackingId trackingId();
-
-    Location origin();
-
-    RouteSpecification routeSpecification();
-
-    Itinerary itinerary();
-
-    Delivery delivery();
-
-    /**
-     * Specifies a new route for this cargo.
-     *
-     * @param routeSpecification route specification.
-     */
-    void specifyNewRoute( final RouteSpecification routeSpecification );
-
-    /**
-     * Attach a new itinerary to this cargo.
-     *
-     * @param itinerary an itinerary. May not be null.
-     */
-    void assignToRoute( final Itinerary itinerary );
-
-    /**
-     * Updates all aspects of the cargo aggregate status
-     * based on the current route specification, itinerary and handling of the cargo.
-     * <p>
-     * When either of those three changes, i.e. when a new route is specified for the cargo,
-     * the cargo is assigned to a route or when the cargo is handled, the status must be
-     * re-calculated.
-     * </p>
-     * <p>
-     * {@link RouteSpecification} and {@link Itinerary} are both inside the Cargo
-     * aggregate, so changes to them cause the status to be updated <b>synchronously</b>,
-     * but changes to the delivery history (when a cargo is handled) cause the status update
-     * to happen <b>asynchronously</b> since {@link org.qi4j.samples.cargo.app1.model.handling.HandlingEvent}
-     * is in a different aggregate.
-     * </p>
-     *
-     * @param handlingHistory handling history
-     */
-    void deriveDeliveryProgress( final HandlingHistory handlingHistory );
-
-    interface State
-    {
-        Association<Location> origin();
-
-        Property<RouteSpecification> routeSpecification();
-
-        @Optional
-        Property<Itinerary> itinerary();
-
-        @Optional
-        Property<Delivery> delivery();
-    }
-
-    public abstract class CargoMixin
-        implements Cargo
-    {
-
-        public static final String TRACKING_ID_PREFIX = "TrackingId:";
-
-        @This
-        private State state;
-
-        @Service
-        private DeliveryFactory deliveryFactory;
-
-        @Structure
-        private ValueBuilderFactory vbf;
-
-        private TrackingId trackingId;
-
-        public TrackingId trackingId()
-        {
-            if( trackingId == null )
-            {
-                final String identity = identity().get();
-                String id = identity.substring( TRACKING_ID_PREFIX.length() );
-                final ValueBuilder<TrackingId> builder = vbf.newValueBuilder( TrackingId.class );
-                builder.prototype().id().set( id );
-                trackingId = builder.newInstance();
-            }
-            return trackingId;
-        }
-
-        public Location origin()
-        {
-            return state.origin().get();
-        }
-
-        public RouteSpecification routeSpecification()
-        {
-            return state.routeSpecification().get();
-        }
-
-        public Itinerary itinerary()
-        {
-            return state.itinerary().get();
-        }
-
-        public Delivery delivery()
-        {
-            return state.delivery().get();
-        }
-
-        public void specifyNewRoute( final RouteSpecification routeSpecification )
-        {
-            state.routeSpecification().set( routeSpecification );
-            // Handling consistency within the Cargo aggregate synchronously
-            state.delivery().set( delivery().updateOnRouting( routeSpecification(), itinerary() ) );
-        }
-
-        public void assignToRoute( final Itinerary itinerary )
-        {
-            state.itinerary().set( itinerary );
-            // Handling consistency within the Cargo aggregate synchronously
-            state.delivery().set( delivery().updateOnRouting( routeSpecification(), itinerary() ) );
-        }
-
-        /**
-         * Updates all aspects of the cargo aggregate status
-         * based on the current route specification, itinerary and handling of the cargo.
-         * <p>
-         * When either of those three changes, i.e. when a new route is specified for the cargo,
-         * the cargo is assigned to a route or when the cargo is handled, the status must be
-         * re-calculated.
-         * </p>
-         * <p>
-         * {@link RouteSpecification} and {@link Itinerary} are both inside the Cargo
-         * aggregate, so changes to them cause the status to be updated <b>synchronously</b>,
-         * but changes to the delivery history (when a cargo is handled) cause the status update
-         * to happen <b>asynchronously</b> since
-         * {@link org.qi4j.samples.cargo.app1.model.handling.HandlingEvent} is in a different aggregate.
-         * </p>
-         * @param handlingHistory handling history
-         */
-        public void deriveDeliveryProgress( final HandlingHistory handlingHistory )
-        {
-            // TODO filter events on cargo (must be same as this cargo)
-
-            // Delivery is a value object, so we can simply discard the old one
-            // and replace it with a new
-            state.delivery().set( deliveryFactory.derivedFrom( routeSpecification(), itinerary(), handlingHistory ) );
-        }
-    }
-}
\ No newline at end of file
diff --git a/samples/forum/build.gradle b/samples/forum/build.gradle
index c3e9ddd..f11dcfe 100644
--- a/samples/forum/build.gradle
+++ b/samples/forum/build.gradle
@@ -1,43 +1,49 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
+import org.apache.polygene.gradle.TaskGroups
+
+apply plugin: 'polygene-sample'
 
 description = "Sample of how to build a web forum"
 
-jar { manifest { name = "Apache Zest™ Sample - Forum" }}
+jar { manifest { name = "Apache Polygene™ Sample - Forum" } }
 
 dependencies {
+  implementation polygene.core.bootstrap
+  implementation polygene.library( 'rest-server' )
+  implementation polygene.library( 'fileconfig' )
+  implementation polygene.extension( 'entitystore-memory' )
+  implementation polygene.extension( 'entitystore-file' )
+  implementation polygene.extension( 'indexing-rdf' )
+  implementation libraries.servlet_api
 
-  compile project( ":org.qi4j.core:org.qi4j.core.bootstrap" )
-  compile project( ":org.qi4j.libraries:org.qi4j.library.rest-server" )
-  compile project( ":org.qi4j.libraries:org.qi4j.library.fileconfig" )
-  compile project( ":org.qi4j.extensions:org.qi4j.extension.entitystore-file" )
-  compile project( ":org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson" )
-  compile libraries.servlet_api
+  runtimeOnly polygene.core.runtime
 
-  testCompile project( ":org.qi4j.core:org.qi4j.core.testsupport" )
+  testImplementation polygene.core.testsupport
 
-  testRuntime project( ":org.qi4j.core:org.qi4j.core.runtime" )
-  testRuntime libraries.logback
-
+  testRuntimeOnly libraries.logback
 }
 
-task(runSample, dependsOn: 'testClasses', type: JavaExec) {
-    main = 'org.qi4j.samples.forum.web.Main'
-    classpath = sourceSets.test.runtimeClasspath
+task( runForumSample, dependsOn: 'testClasses', type: JavaExec ) {
+  group = TaskGroups.SAMPLES
+  description = "Runs $project.name sample."
+  main = 'org.apache.polygene.sample.forum.web.Main'
+  classpath = sourceSets.test.runtimeClasspath
 }
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/assembler/ForumAssembler.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/assembler/ForumAssembler.java
new file mode 100644
index 0000000..5f3b0cc
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/assembler/ForumAssembler.java
@@ -0,0 +1,169 @@
+/*
+ *  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.polygene.sample.forum.assembler;
+
+import java.lang.reflect.Modifier;
+import java.util.List;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ClassScanner;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.file.assembly.FileEntityStoreAssembler;
+import org.apache.polygene.entitystore.memory.assembly.MemoryEntityStoreAssembler;
+import org.apache.polygene.index.rdf.assembly.RdfNativeSesameStoreAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+import org.apache.polygene.library.rdf.repository.NativeConfiguration;
+import org.apache.polygene.library.rest.common.ValueAssembler;
+import org.apache.polygene.library.rest.server.assembler.RestServerAssembler;
+import org.apache.polygene.library.rest.server.restlet.RequestReaderDelegator;
+import org.apache.polygene.library.rest.server.restlet.ResponseWriterDelegator;
+import org.apache.polygene.library.rest.server.spi.CommandResult;
+import org.apache.polygene.sample.forum.context.Context;
+import org.apache.polygene.sample.forum.context.EventsService;
+import org.apache.polygene.sample.forum.data.entity.User;
+import org.apache.polygene.sample.forum.domainevent.DomainCommandResult;
+import org.apache.polygene.sample.forum.domainevent.DomainEventValue;
+import org.apache.polygene.sample.forum.domainevent.ParameterValue;
+import org.apache.polygene.sample.forum.rest.ForumRestlet;
+import org.apache.polygene.sample.forum.rest.resource.RootResource;
+import org.apache.polygene.sample.forum.service.BootstrapData;
+import org.restlet.service.MetadataService;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.polygene.api.util.Classes.hasModifier;
+import static org.apache.polygene.api.util.Classes.isAssignableFrom;
+
+/**
+ * TODO
+ */
+public class ForumAssembler
+    implements ApplicationAssembler
+{
+    @Override
+    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+        throws AssemblyException
+    {
+        ApplicationAssembly assembly = applicationFactory.newApplicationAssembly();
+
+        assembly.setName( "Forum" );
+
+        ModuleAssembly configModule;
+        LayerAssembly configuration = assembly.layer( "Configuration" );
+        {
+            configModule = configuration.module( "Configuration" );
+            new MemoryEntityStoreAssembler().assemble( configModule );
+            new FileConfigurationAssembler().visibleIn( Visibility.application ).assemble( configModule );
+        }
+
+        LayerAssembly infrastructure = assembly.layer( "Infrastructure" ).uses( configuration );
+        {
+            ModuleAssembly entityStore = infrastructure.module( "EntityStore" );
+            new FileEntityStoreAssembler()
+                .visibleIn( Visibility.application )
+                .withConfig( configModule, Visibility.application )
+                .assemble( entityStore );
+
+            ModuleAssembly indexQuery = infrastructure.module( "IndexQuery" );
+            new RdfNativeSesameStoreAssembler( Visibility.application, Visibility.application )
+                .assemble( indexQuery );
+            configModule.entities( NativeConfiguration.class ).visibleIn( Visibility.application );
+        }
+
+        LayerAssembly data = assembly.layer( "Data" ).uses( infrastructure );
+        {
+            ModuleAssembly forum = data.module( "Forum" );
+            ClassScanner.findClasses( User.class )
+                        .filter( isAssignableFrom( EntityComposite.class ) )
+                        .filter( hasModifier( Modifier.INTERFACE ) )
+                        .forEach( dataClass -> forum.entities( dataClass ).visibleIn( Visibility.application ) );
+        }
+
+        LayerAssembly context = assembly.layer( "Context" ).uses( data );
+        {
+            ModuleAssembly contexts = context.module( "Context" );
+            List<? extends Class<?>> contextClasses = ClassScanner.findClasses( Context.class )
+                                                                  .filter( hasModifier( Modifier.INTERFACE ).negate() )
+                                                                  .collect( toList() );
+            for( Class<?> contextClass : contextClasses )
+            {
+                if( contextClass.getName().contains( "$" ) )
+                {
+                    contexts.transients( contextClass ).visibleIn( Visibility.application );
+                }
+                else
+                {
+                    contexts.objects( contextClass ).visibleIn( Visibility.application );
+                }
+            }
+
+            ClassScanner.findClasses( Context.class )
+                        .filter( isAssignableFrom( ValueComposite.class ) )
+                        .forEach( valueClass -> contexts.values( valueClass ).visibleIn( Visibility.application ) );
+
+            contexts.services( EventsService.class );
+
+            context.module( "Domain events" )
+                   .values( DomainEventValue.class, ParameterValue.class )
+                   .visibleIn( Visibility.application );
+        }
+
+        LayerAssembly services = assembly.layer( "Service" ).uses( data );
+        {
+            ModuleAssembly bootstrap = services.module( "Bootstrap" );
+            bootstrap.services( BootstrapData.class ).identifiedBy( "bootstrap" ).instantiateOnStartup();
+        }
+
+        LayerAssembly rest = assembly.layer( "REST" ).uses( context, data );
+        {
+            ModuleAssembly values = rest.module( "Values" );
+            {
+                new ValueAssembler().assemble( values );
+            }
+
+            ModuleAssembly transformation = rest.module( "Transformation" );
+            {
+                new RestServerAssembler().assemble( transformation );
+                transformation.objects( RequestReaderDelegator.class, ResponseWriterDelegator.class )
+                              .visibleIn( Visibility.layer );
+            }
+
+            ModuleAssembly resources = rest.module( "Resources" );
+            List<? extends Class<?>> resourceClasses = ClassScanner.findClasses( RootResource.class )
+                                                                   .collect( toList() );
+            for( Class<?> resourceClass : resourceClasses )
+            {
+                resources.objects( resourceClass ).visibleIn( Visibility.layer );
+            }
+
+            ModuleAssembly restlet = rest.module( "Restlet" );
+            restlet.objects( ForumRestlet.class );
+            restlet.importedServices( CommandResult.class ).setMetaInfo( new DomainCommandResult() );
+            restlet.importedServices( MetadataService.class );
+        }
+
+        return assembly;
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/Context.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/Context.java
new file mode 100644
index 0000000..0e20e16
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/Context.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.sample.forum.context;
+
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.structure.Module;
+
+/**
+ * TODO
+ */
+public class Context
+{
+    @Structure
+    protected Module module;
+
+    protected <T> T role( Class<T> roleType, Object data )
+    {
+        return module.newObject( roleType, data );
+    }
+
+    protected <T> T role( Object object, Class<T> roleType )
+    {
+        return PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF.apply( (Composite) object ).newProxy( roleType );
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/Events.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/Events.java
new file mode 100644
index 0000000..57a9927
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/Events.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.sample.forum.context;
+
+import org.apache.polygene.sample.forum.context.signup.Registration;
+
+/**
+ * Domain Events that can be triggered by the contexts
+ */
+public interface Events
+{
+    void signedup( Registration registration );
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/EventsService.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/EventsService.java
new file mode 100644
index 0000000..bae5cd1
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/EventsService.java
@@ -0,0 +1,120 @@
+/*
+ *  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.polygene.sample.forum.context;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCallback;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.library.rest.server.api.ObjectSelection;
+import org.apache.polygene.sample.forum.domainevent.DomainEventValue;
+import org.apache.polygene.sample.forum.domainevent.ParameterValue;
+import org.restlet.Request;
+
+import static java.util.stream.Collectors.toCollection;
+
+/**
+ * TODO
+ */
+@Mixins( EventsService.Mixin.class )
+public interface EventsService
+    extends Events, ServiceComposite
+{
+    public class Mixin
+        implements InvocationHandler
+    {
+        @Structure
+        UnitOfWorkFactory uowf;
+
+        @Structure
+        ValueBuilderFactory vbf;
+
+        @Structure
+        Application application;
+
+        @Override
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            UnitOfWork unitOfWork = uowf.currentUnitOfWork();
+
+            ValueBuilder<DomainEventValue> builder = vbf.newValueBuilder( DomainEventValue.class );
+            DomainEventValue prototype = builder.prototype();
+            prototype.version().set( application.version() );
+            prototype.timestamp().set( unitOfWork.currentTime() );
+            prototype.context().set( proxy.getClass().getSuperclass().getName().split( "\\$" )[ 0 ] );
+            prototype.name().set( method.getName() );
+
+            int idx = 0;
+            for( Object arg : args )
+            {
+                idx++;
+                String name = "param" + idx;
+                ValueBuilder<ParameterValue> parameterBuilder = vbf.newValueBuilder( ParameterValue.class );
+                parameterBuilder.prototype().name().set( name );
+                parameterBuilder.prototype().value().set( arg );
+                prototype.parameters().get().add( parameterBuilder.newInstance() );
+            }
+
+            ObjectSelection.current().selection().stream()
+                           .map( Object::toString )
+                           .collect( toCollection( () -> prototype.selection().get() ) );
+
+            final DomainEventValue domainEvent = builder.newInstance();
+
+            // Send event to all interested parties in the ObjectSelection
+            for( Object selectedObject : ObjectSelection.current().selection() )
+            {
+                if( selectedObject instanceof Events )
+                {
+                    method.invoke( selectedObject, args );
+                }
+            }
+
+            unitOfWork.addUnitOfWorkCallback( new UnitOfWorkCallback()
+            {
+                @Override
+                public void beforeCompletion()
+                    throws UnitOfWorkCompletionException
+                {
+                }
+
+                @Override
+                public void afterCompletion( UnitOfWorkStatus status )
+                {
+                    if( status.equals( UnitOfWorkStatus.COMPLETED ) )
+                    {
+                        Request.getCurrent().getAttributes().put( "event", domainEvent );
+                    }
+                }
+            } );
+
+            return null;
+        }
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/account/UpdateProfile.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/account/UpdateProfile.java
new file mode 100644
index 0000000..365afc3
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/account/UpdateProfile.java
@@ -0,0 +1,67 @@
+/*
+ *  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.polygene.sample.forum.context.account;
+
+import org.apache.polygene.api.constraint.Name;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.library.rest.server.api.ResourceIndex;
+import org.apache.polygene.library.rest.server.api.dci.Role;
+import org.apache.polygene.sample.forum.context.Context;
+import org.apache.polygene.sample.forum.data.entity.User;
+
+/**
+ * TODO
+ */
+public class UpdateProfile
+    extends Context
+    implements ResourceIndex<UpdateProfile.Profile>
+{
+    Profile profile;
+
+    public UpdateProfile bind( @Uses User user )
+    {
+        profile = role( Profile.class, user );
+        return this;
+    }
+
+    public Profile index()
+    {
+        return profile;
+    }
+
+    public void updateProfile( @Name( "name" ) String name,
+                               @Name( "realname" ) String realName,
+                               @Name( "email" ) String email
+    )
+    {
+        profile.updateProfile( name, realName, email );
+    }
+
+    protected class Profile
+        extends Role<User>
+    {
+        public void updateProfile( String name, String realName, String email )
+        {
+            self.name().set( name );
+            self.realName().set( realName );
+            self.email().set( email );
+        }
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/BoardAdministration.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/BoardAdministration.java
new file mode 100644
index 0000000..cbc02a0
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/BoardAdministration.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.sample.forum.context.administration;
+
+import org.apache.polygene.api.constraint.Name;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.library.rest.server.api.ResourceIndex;
+import org.apache.polygene.library.rest.server.api.dci.Role;
+import org.apache.polygene.sample.forum.data.entity.Board;
+import org.apache.polygene.sample.forum.data.entity.Forum;
+import org.apache.polygene.sample.forum.data.entity.User;
+
+/**
+ * TODO
+ */
+public class BoardAdministration
+    implements ResourceIndex<Board>
+{
+    @Structure
+    Module module;
+
+    BoardAdmin boardAdmin = new BoardAdmin();
+
+    public BoardAdministration bind( @Uses Forum forum, @Uses Board board, @Uses User user )
+    {
+        boardAdmin.bind( board );
+        return this;
+    }
+
+    public Board index()
+    {
+        return boardAdmin.self();
+    }
+
+    public void updateName( @Name( "name" ) String name )
+    {
+        boardAdmin.updateName( name );
+    }
+
+    protected class BoardAdmin
+        extends Role<Board>
+    {
+        @Structure
+        Module module;
+
+        public void updateName( String name )
+        {
+            self().name().set( name );
+        }
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/ForumAdministration.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/ForumAdministration.java
new file mode 100644
index 0000000..93b2499
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/ForumAdministration.java
@@ -0,0 +1,92 @@
+/*
+ *  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.polygene.sample.forum.context.administration;
+
+import org.apache.polygene.api.constraint.Name;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.library.rest.server.api.ResourceIndex;
+import org.apache.polygene.library.rest.server.api.dci.Role;
+import org.apache.polygene.sample.forum.data.entity.Board;
+import org.apache.polygene.sample.forum.data.entity.Forum;
+import org.apache.polygene.sample.forum.data.entity.User;
+
+/**
+ * TODO
+ */
+public class ForumAdministration
+    implements ResourceIndex<Query<Board>>
+{
+    @Structure
+    UnitOfWorkFactory uowf;
+
+    @Structure
+    QueryBuilderFactory qbf;
+
+    ForumAdmin forumAdmin = new ForumAdmin();
+    Administrator administrator = new Administrator();
+
+    public ForumAdministration bind( @Uses Forum forum, @Uses User user )
+    {
+        forumAdmin.bind( forum );
+        administrator.bind( user );
+        return this;
+    }
+
+    public Query<Board> index()
+    {
+        return forumAdmin.boards();
+    }
+
+    public Board createBoard( @Name( "name" ) String name )
+    {
+        return forumAdmin.createBoard( name );
+    }
+
+    protected class ForumAdmin
+        extends Role<Forum>
+    {
+
+        public Query<Board> boards()
+        {
+            return qbf.newQueryBuilder( Board.class ).newQuery( self.boards() );
+        }
+
+        public Board createBoard( String name )
+        {
+            Board board = uowf.currentUnitOfWork().newEntity( Board.class );
+            board.name().set( name );
+            administrator.makeModerator( board );
+            return board;
+        }
+    }
+
+    protected class Administrator
+        extends Role<User>
+    {
+        public void makeModerator( Board board )
+        {
+            board.moderators().add( self );
+        }
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/ForumsAdministration.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/ForumsAdministration.java
new file mode 100644
index 0000000..6cac835
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/ForumsAdministration.java
@@ -0,0 +1,87 @@
+/*
+ *  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.polygene.sample.forum.context.administration;
+
+import org.apache.polygene.api.constraint.Name;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.library.rest.server.api.ResourceIndex;
+import org.apache.polygene.library.rest.server.api.dci.Role;
+import org.apache.polygene.sample.forum.data.entity.Forum;
+import org.apache.polygene.sample.forum.data.entity.Forums;
+import org.apache.polygene.sample.forum.data.entity.User;
+
+/**
+ * TODO
+ */
+public class ForumsAdministration
+    implements ResourceIndex<Query<Forum>>
+{
+    @Structure
+    UnitOfWorkFactory uowf;
+
+    ForumsAdmin forumsAdmin = new ForumsAdmin();
+    Administrator administrator = new Administrator();
+
+    public ForumsAdministration bind( @Uses Forums forums, @Uses User user )
+    {
+        forumsAdmin.bind( forums );
+        administrator.bind( user );
+        return this;
+    }
+
+    public Query<Forum> index()
+    {
+        return forumsAdmin.forums();
+    }
+
+    public Forum createForum( @Name( "name" ) String name )
+    {
+        return forumsAdmin.createForum( name );
+    }
+
+    protected class ForumsAdmin
+        extends Role<Forums>
+    {
+        public Query<Forum> forums()
+        {
+            return self.forums();
+        }
+
+        public Forum createForum( String name )
+        {
+            Forum forum = uowf.currentUnitOfWork().newEntity( Forum.class );
+            forum.name().set( name );
+            administrator.makeModerator( forum );
+            return forum;
+        }
+    }
+
+    protected class Administrator
+        extends Role<User>
+    {
+        public void makeModerator( Forum forum )
+        {
+            forum.moderators().add( self );
+        }
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/ModeratorAdministration.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/ModeratorAdministration.java
new file mode 100644
index 0000000..c5979ca
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/ModeratorAdministration.java
@@ -0,0 +1,76 @@
+/*
+ *  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.polygene.sample.forum.context.administration;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.library.rest.server.api.ResourceDelete;
+import org.apache.polygene.library.rest.server.api.ResourceIndex;
+import org.apache.polygene.library.rest.server.api.dci.Role;
+import org.apache.polygene.sample.forum.data.Moderators;
+import org.apache.polygene.sample.forum.data.entity.User;
+
+/**
+ * TODO
+ */
+public class ModeratorAdministration
+    implements ResourceIndex<User>, ResourceDelete
+{
+    @Structure
+    Module module;
+
+    ModeratorAdmin moderatorAdmin = new ModeratorAdmin();
+    Moderator moderator = new Moderator();
+
+    public ModeratorAdministration bind( @Uses Moderators moderators, @Uses User user )
+    {
+        moderatorAdmin.bind( moderators );
+        moderator.bind( user );
+        return this;
+    }
+
+    public User index()
+    {
+        return moderator.self();
+    }
+
+    public void delete()
+    {
+        moderatorAdmin.removeModerator();
+    }
+
+    protected class Moderator
+        extends Role<User>
+    {
+    }
+
+    protected class ModeratorAdmin
+        extends Role<Moderators>
+    {
+        @Structure
+        Module module;
+
+        public void removeModerator()
+        {
+            self().moderators().remove( moderator.self() );
+        }
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/ModeratorsAdministration.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/ModeratorsAdministration.java
new file mode 100644
index 0000000..59a089d
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/ModeratorsAdministration.java
@@ -0,0 +1,84 @@
+/*
+ *  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.polygene.sample.forum.context.administration;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.library.rest.server.api.ResourceIndex;
+import org.apache.polygene.library.rest.server.api.dci.Role;
+import org.apache.polygene.sample.forum.data.Moderators;
+import org.apache.polygene.sample.forum.data.entity.User;
+
+/**
+ * TODO
+ */
+public class ModeratorsAdministration
+    implements ResourceIndex<Query<User>>
+{
+    @Structure
+    Module module;
+
+    ModeratorsAdmin moderatorsAdmin = new ModeratorsAdmin();
+
+    public ModeratorsAdministration bind( @Uses Moderators moderators )
+    {
+        moderatorsAdmin.bind( moderators );
+        return this;
+    }
+
+    public Query<User> index()
+    {
+        return moderatorsAdmin.moderators();
+    }
+
+    public void addModerator( User user )
+    {
+        moderatorsAdmin.addModerator( user );
+    }
+
+    public void removeModerator( User user )
+    {
+        moderatorsAdmin.removeModerator( user );
+    }
+
+    protected class ModeratorsAdmin
+        extends Role<Moderators>
+    {
+        @Structure
+        Module module;
+
+        public Query<User> moderators()
+        {
+            return module.newQueryBuilder( User.class ).newQuery( self.moderators() );
+        }
+
+        public void addModerator( User user )
+        {
+            self().moderators().add( user );
+        }
+
+        public void removeModerator( User user )
+        {
+            self().moderators().remove( user );
+        }
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/UsersAdministration.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/UsersAdministration.java
new file mode 100644
index 0000000..624f01b
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/administration/UsersAdministration.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.sample.forum.context.administration;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.library.rest.server.api.dci.Role;
+import org.apache.polygene.sample.forum.data.entity.User;
+import org.apache.polygene.sample.forum.data.entity.Users;
+
+/**
+ * TODO
+ */
+public class UsersAdministration
+{
+    @Structure
+    Module module;
+
+    UsersAdmin usersAdmin = new UsersAdmin();
+    Administrator administrator = new Administrator();
+
+    public UsersAdministration bind( @Uses Users users, @Uses User user )
+    {
+        usersAdmin.bind( users );
+        administrator.bind( user );
+        return this;
+    }
+
+    protected class UsersAdmin
+        extends Role<Users>
+    {
+    }
+
+    protected class Administrator
+        extends Role<User>
+    {
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/login/Login.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/login/Login.java
new file mode 100644
index 0000000..6b203b1
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/login/Login.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.sample.forum.context.login;
+
+import org.apache.polygene.api.constraint.Name;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.sample.forum.data.entity.User;
+
+import static org.apache.polygene.api.query.QueryExpressions.*;
+
+/**
+ * TODO
+ */
+public class Login
+{
+    @Structure
+    UnitOfWorkFactory uowf;
+
+    @Structure
+    QueryBuilderFactory qbf;
+
+    public void login( @Name( "name" ) String name, @Name( "password" ) String password )
+    {
+        QueryBuilder<User> builder = qbf.newQueryBuilder( User.class )
+            .where( eq( templateFor( User.class ).name(), name ) );
+
+        User user = uowf.currentUnitOfWork()
+            .newQuery( builder )
+            .find();
+
+        if( user == null || !user.isCorrectPassword( password ) )
+        {
+            throw new IllegalArgumentException( "Login incorrect" );
+        }
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/moderation/ModerationContext.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/moderation/ModerationContext.java
new file mode 100644
index 0000000..b10d29b
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/moderation/ModerationContext.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.sample.forum.context.moderation;
+
+/**
+ * TODO
+ */
+public class ModerationContext
+{
+
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/signup/Registration.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/signup/Registration.java
new file mode 100644
index 0000000..e670015
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/signup/Registration.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.sample.forum.context.signup;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * TODO
+ */
+public interface Registration
+    extends ValueComposite
+{
+    Property<String> name();
+
+    Property<String> realName();
+
+    Property<String> email();
+
+    Property<String> password();
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/signup/Signup.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/signup/Signup.java
new file mode 100644
index 0000000..a40ed04
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/signup/Signup.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.sample.forum.context.signup;
+
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.sample.forum.context.Context;
+import org.apache.polygene.sample.forum.context.Events;
+
+/**
+ * TODO
+ */
+public class Signup
+    extends Context
+{
+    @Uses
+    Users users;
+
+    @Service
+    Events events;
+
+    public void signup( Registration registration )
+    {
+        users.signup( registration );
+    }
+
+    protected class Users
+        implements TransientComposite
+    {
+        public void signup( Registration registration )
+        {
+            // Check if user with this name already exists
+            events.signedup( registration );
+        }
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/view/ViewBoard.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/view/ViewBoard.java
new file mode 100644
index 0000000..8f92411
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/view/ViewBoard.java
@@ -0,0 +1,128 @@
+/*
+ *  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.polygene.sample.forum.context.view;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.library.rest.server.api.ResourceIndex;
+import org.apache.polygene.library.rest.server.api.dci.Role;
+import org.apache.polygene.sample.forum.data.Moderators;
+import org.apache.polygene.sample.forum.data.entity.Board;
+import org.apache.polygene.sample.forum.data.entity.Forum;
+import org.apache.polygene.sample.forum.data.entity.Post;
+import org.apache.polygene.sample.forum.data.entity.Topic;
+import org.apache.polygene.sample.forum.data.entity.User;
+
+import static org.apache.polygene.api.property.Numbers.add;
+
+/**
+ * TODO
+ */
+public class ViewBoard
+    implements ResourceIndex<Board>
+{
+    private Posting posting;
+    private BoardViewer viewer;
+    private BoardModeration boardModeration;
+    private ForumModeration forumModeration;
+
+    public ViewBoard bind( @Uses Forum forum, @Uses Board board, @Uses User user )
+    {
+        posting.bind( board );
+        viewer.bind( user );
+        boardModeration.bind( board );
+        forumModeration.bind( forum );
+        return this;
+    }
+
+    @Override
+    public Board index()
+    {
+        return posting.self();
+    }
+
+    public Topic createTopic( String subject, String message )
+    {
+        return posting.createTopic( subject, message, viewer );
+    }
+
+    protected class BoardViewer
+        extends Role<User>
+    {
+        boolean isModerator( Moderators moderators )
+        {
+            return moderators.moderators().contains( self );
+        }
+    }
+
+    protected class BoardModeration
+        extends Role<Moderators>
+    {
+        boolean isModerator( BoardViewer user )
+        {
+            return user.isModerator( self ) || forumModeration.isModerator( user );
+        }
+    }
+
+    protected class ForumModeration
+        extends Role<Moderators>
+    {
+        boolean isModerator( BoardViewer user )
+        {
+            return user.isModerator( self );
+        }
+    }
+
+    protected class Posting
+        extends Role<Board>
+    {
+        @Structure
+        UnitOfWorkFactory uowf;
+
+        Topic createTopic( String subject, String message, BoardViewer poster )
+        {
+            Topic topic = uowf.currentUnitOfWork().newEntity( Topic.class );
+
+            topic.subject().set( subject );
+
+            Post post = uowf.currentUnitOfWork().newEntity( Post.class );
+            post.message().set( message );
+
+            // Moderation checks
+            if( boardModeration.isModerator( poster ) )
+            {
+                post.status().set( Post.Status.POSTED );
+
+                self.lastPost().set( post );
+                add( self.topicCount(), 1 );
+                add( self.postCount(), 1 );
+
+                return topic;
+            }
+            else
+            {
+                post.status().set( Post.Status.MODERATION );
+            }
+
+            return topic;
+        }
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/view/ViewForum.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/view/ViewForum.java
new file mode 100644
index 0000000..8fe8a37
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/view/ViewForum.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.sample.forum.context.view;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.library.rest.server.api.ResourceIndex;
+import org.apache.polygene.library.rest.server.api.dci.Role;
+import org.apache.polygene.sample.forum.data.entity.Board;
+import org.apache.polygene.sample.forum.data.entity.Forum;
+import org.apache.polygene.sample.forum.data.entity.User;
+
+/**
+ * TODO
+ */
+public class ViewForum
+    implements ResourceIndex<Query<Board>>
+{
+    private ForumView viewForum = new ForumView();
+
+    public ViewForum bind( @Uses Forum forum, @Uses User user )
+    {
+        viewForum.bind( forum );
+        return this;
+    }
+
+    public Query<Board> index()
+    {
+        return viewForum.boards();
+    }
+
+    protected class ForumView
+        extends Role<Forum>
+    {
+        @Structure
+        Module module;
+
+        public Query<Board> boards()
+        {
+            return module.newQueryBuilder( Board.class ).newQuery( self.boards() );
+        }
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/view/ViewPost.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/view/ViewPost.java
new file mode 100644
index 0000000..15cf78f
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/view/ViewPost.java
@@ -0,0 +1,91 @@
+/*
+ *  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.polygene.sample.forum.context.view;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.property.Numbers;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.library.rest.server.api.ResourceIndex;
+import org.apache.polygene.library.rest.server.api.dci.Role;
+import org.apache.polygene.sample.forum.data.entity.Post;
+import org.apache.polygene.sample.forum.data.entity.Topic;
+import org.apache.polygene.sample.forum.data.entity.User;
+
+/**
+ * TODO
+ */
+class ViewPost
+    implements ResourceIndex<Post>
+{
+    private PostView viewPost = new PostView();
+    private ReplyTopic replyTopic = new ReplyTopic();
+    private Poster poster = new Poster();
+
+    public ViewPost bind( @Uses Topic topic, @Uses Post post, @Uses User user )
+    {
+        viewPost.bind( post );
+        replyTopic.bind( topic );
+        poster.bind( user );
+        return this;
+    }
+
+    @Override
+    public Post index()
+    {
+        return viewPost.self();
+    }
+
+    public Post reply( String message )
+    {
+        return replyTopic.reply( message, viewPost );
+    }
+
+    public class ReplyTopic
+        extends Role<Topic>
+    {
+        @Structure
+        UnitOfWorkFactory uowf;
+
+        Post reply( String message, PostView viewPost )
+        {
+            Post post = uowf.currentUnitOfWork().newEntity( Post.class );
+            post.message().set( message );
+            post.createdBy().set( poster.self() );
+            post.createdOn().set( uowf.currentUnitOfWork().currentTime() );
+            post.replyTo().set( viewPost.self() );
+
+            self().lastPost().set( post );
+            Numbers.add( self().postCount(), 1 );
+
+            return post;
+        }
+    }
+
+    public class PostView
+        extends Role<Post>
+    {
+    }
+
+    public class Poster
+        extends Role<User>
+    {
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/view/ViewTopic.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/view/ViewTopic.java
new file mode 100644
index 0000000..4cf8c10
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/context/view/ViewTopic.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.sample.forum.context.view;
+
+import org.apache.polygene.library.rest.server.api.ResourceIndex;
+import org.apache.polygene.library.rest.server.api.dci.Role;
+import org.apache.polygene.sample.forum.data.entity.Topic;
+
+/**
+ * TODO
+ */
+public class ViewTopic
+    implements ResourceIndex<Topic>
+{
+    private TopicView topicView;
+
+    public ViewTopic bind( Topic topic )
+    {
+        topicView = (TopicView) topic;
+        return this;
+    }
+
+    @Override
+    public Topic index()
+    {
+        return topicView.self();
+    }
+
+    protected class TopicView
+        extends Role<Topic>
+    {
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/Administrators.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/Administrators.java
new file mode 100644
index 0000000..7e65c7a
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/Administrators.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.sample.forum.data;
+
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.sample.forum.data.entity.User;
+
+/**
+ * TODO
+ */
+public interface Administrators
+{
+    ManyAssociation<User> administrators();
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/Moderators.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/Moderators.java
new file mode 100644
index 0000000..2ebf31c
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/Moderators.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.sample.forum.data;
+
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.sample.forum.data.entity.User;
+
+/**
+ * TODO
+ */
+public interface Moderators
+{
+    ManyAssociation<User> moderators();
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Board.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Board.java
new file mode 100644
index 0000000..1ec03f3
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Board.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.sample.forum.data.entity;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.Aggregated;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.sample.forum.data.Moderators;
+
+/**
+ * TODO
+ */
+public interface Board
+    extends Moderators, EntityComposite
+{
+    Property<String> name();
+
+    @Aggregated
+    ManyAssociation<Topic> topics();
+
+    @UseDefaults
+    Property<Integer> postCount();
+
+    @UseDefaults
+    Property<Integer> topicCount();
+
+    @Optional
+    Association<Post> lastPost();
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Forum.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Forum.java
new file mode 100644
index 0000000..6b633a3
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Forum.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.sample.forum.data.entity;
+
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.entity.Aggregated;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.sample.forum.data.Moderators;
+import org.apache.polygene.sample.forum.data.Administrators;
+
+/**
+ * TODO
+ */
+public interface Forum
+    extends Moderators, Administrators, EntityComposite
+{
+    public Property<String> name();
+
+    @Aggregated
+    ManyAssociation<Board> boards();
+
+    Property<Integer> topicCount();
+
+    Property<Integer> postCount();
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Forums.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Forums.java
new file mode 100644
index 0000000..2ea7fb9
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Forums.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.sample.forum.data.entity;
+
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.sample.forum.data.Administrators;
+
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+
+/**
+ * TODO
+ */
+@Mixins( Forums.Mixin.class )
+public interface Forums
+    extends Administrators, EntityComposite
+{
+    Identity FORUMS_ID = new StringIdentity( "forums" );
+
+    public Query<Forum> forums();
+
+    abstract class Mixin
+        implements Forums
+    {
+        @Structure
+        UnitOfWorkFactory uowf;
+
+        @Structure
+        QueryBuilderFactory qbf;
+
+        public Query<Forum> forums()
+        {
+            return uowf.currentUnitOfWork()
+                .newQuery( qbf.newQueryBuilder( Forum.class ) )
+                .orderBy( templateFor( Forum.class ).name() );
+        }
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Post.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Post.java
new file mode 100644
index 0000000..0a86f41
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Post.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.sample.forum.data.entity;
+
+import java.time.Instant;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * TODO
+ */
+public interface Post
+    extends EntityComposite
+{
+    enum Status
+    {
+        POSTED,
+        MODERATION,
+        DELETED,
+        SPAM
+    }
+
+    @Optional
+    Association<Post> replyTo();
+
+    Property<String> message();
+
+    Association<User> poster();
+
+    Property<Status> status();
+
+    Property<User> createdBy();
+
+    Property<Instant> createdOn();
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Topic.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Topic.java
new file mode 100644
index 0000000..087f8d3
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Topic.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.polygene.sample.forum.data.entity;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.entity.Aggregated;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * TODO
+ */
+public interface Topic
+    extends EntityComposite
+{
+    enum Status
+    {
+        POSTED,
+        MODERATION,
+        DELETED,
+        SPAM
+    }
+
+    Property<String> subject();
+
+    Property<Status> status();
+
+    @Aggregated
+    ManyAssociation<Post> posts();
+
+    Association<Post> lastPost();
+
+    Property<Integer> postCount();
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/User.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/User.java
new file mode 100644
index 0000000..9dcf9b1
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/User.java
@@ -0,0 +1,81 @@
+/*
+ *  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.polygene.sample.forum.data.entity;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Base64;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Immutable;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * TODO
+ */
+@Mixins( User.Mixin.class )
+public interface User
+    extends EntityComposite
+{
+    @Immutable
+    public Property<String> name();
+
+    public Property<String> realName();
+
+    public Property<String> email();
+
+    public Property<String> password();
+
+    public String hashPassword( String password );
+
+    public boolean isCorrectPassword( String password );
+
+    abstract class Mixin
+        implements User
+    {
+        @Override
+        public String hashPassword( String password )
+        {
+            try
+            {
+                MessageDigest md = MessageDigest.getInstance( "SHA" );
+                md.update( password.getBytes( "UTF-8" ) );
+                byte raw[] = md.digest();
+
+                return Base64.getEncoder().encodeToString( raw );
+            }
+            catch( NoSuchAlgorithmException e )
+            {
+                throw new IllegalStateException( "No SHA algorithm found", e );
+            }
+            catch( UnsupportedEncodingException e )
+            {
+                throw new IllegalStateException( e.getMessage(), e );
+            }
+        }
+
+        @Override
+        public boolean isCorrectPassword( String password )
+        {
+            return password().get().equals( hashPassword( password ) );
+        }
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Users.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Users.java
new file mode 100644
index 0000000..31861b4
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/data/entity/Users.java
@@ -0,0 +1,87 @@
+/*
+ *  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.polygene.sample.forum.data.entity;
+
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.sample.forum.context.Events;
+import org.apache.polygene.sample.forum.context.signup.Registration;
+
+import static org.apache.polygene.api.query.QueryExpressions.eq;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+
+/**
+ * TODO
+ */
+@Mixins( Users.Mixin.class )
+public interface Users
+    extends EntityComposite, Events
+{
+    Identity USERS_ID = new StringIdentity( "users" );
+
+    Query<User> users();
+
+    User userNamed( String name );
+
+    abstract class Mixin
+        implements Users
+    {
+        @Structure
+        UnitOfWorkFactory uowf;
+
+        @Structure
+        QueryBuilderFactory qbf;
+
+        @Override
+        public Query<User> users()
+        {
+            return uowf.currentUnitOfWork()
+                .newQuery( qbf.newQueryBuilder( User.class ) )
+                .orderBy( templateFor( User.class ).realName() );
+        }
+
+        @Override
+        public User userNamed( String name )
+        {
+            return uowf.currentUnitOfWork().newQuery(
+                qbf.newQueryBuilder( User.class ).where( eq( templateFor( User.class ).name(), name ) )
+            ).find();
+        }
+
+        @Override
+        public void signedup( Registration registration )
+        {
+            EntityBuilder<User> builder = uowf.currentUnitOfWork().newEntityBuilder( User.class );
+            builder.instance().name().set( registration.name().get() );
+            builder.instance().realName().set( registration.realName().get() );
+            builder.instance().email().set( registration.email().get() );
+            builder.instance().password().set( builder.instance().hashPassword( registration.password().get() ) );
+
+            builder.newInstance();
+        }
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/domainevent/DomainCommandResult.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/domainevent/DomainCommandResult.java
new file mode 100644
index 0000000..7d4c70c
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/domainevent/DomainCommandResult.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.sample.forum.domainevent;
+
+import org.apache.polygene.library.rest.server.spi.CommandResult;
+import org.restlet.Request;
+
+/**
+ * TODO
+ */
+public class DomainCommandResult
+    implements CommandResult
+{
+    @Override
+    public Object getResult()
+    {
+        return Request.getCurrent().getAttributes().get( "event" );
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/domainevent/DomainEvent.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/domainevent/DomainEvent.java
new file mode 100644
index 0000000..2b55de8
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/domainevent/DomainEvent.java
@@ -0,0 +1,112 @@
+/*
+ *  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.polygene.sample.forum.domainevent;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.concern.GenericConcern;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCallback;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.library.rest.server.api.ObjectSelection;
+import org.restlet.Request;
+
+import static java.util.stream.Collectors.toCollection;
+
+/**
+ * TODO
+ */
+@Concerns( DomainEvent.DomainEventConcern.class )
+@Retention( RetentionPolicy.RUNTIME )
+public @interface DomainEvent
+{
+    class DomainEventConcern
+        extends GenericConcern
+    {
+        @Structure
+        ValueBuilderFactory vbf;
+
+        @Structure
+        UnitOfWorkFactory uowf;
+
+        @Structure
+        Application application;
+
+        @Override
+        public Object invoke( Object proxy, Method method, Object[] args )
+            throws Throwable
+        {
+            Object result = next.invoke( proxy, method, args );
+
+            UnitOfWork unitOfWork = uowf.currentUnitOfWork();
+
+            ValueBuilder<DomainEventValue> builder = vbf.newValueBuilder( DomainEventValue.class );
+            DomainEventValue prototype = builder.prototype();
+            prototype.version().set( application.version() );
+            prototype.timestamp().set( unitOfWork.currentTime() );
+            prototype.context().set( proxy.getClass().getSuperclass().getName().split( "\\$" )[ 0 ] );
+            prototype.name().set( method.getName() );
+
+            int idx = 0;
+            for( Object arg : args )
+            {
+                idx++;
+                String name = "param" + idx;
+                ValueBuilder<ParameterValue> parameterBuilder = vbf.newValueBuilder( ParameterValue.class );
+                parameterBuilder.prototype().name().set( name );
+                parameterBuilder.prototype().value().set( arg );
+                prototype.parameters().get().add( parameterBuilder.newInstance() );
+            }
+
+            ObjectSelection.current().selection().stream()
+                           .map( Object::toString )
+                           .collect( toCollection( () -> prototype.selection().get() ) );
+
+            final DomainEventValue domainEvent = builder.newInstance();
+
+            unitOfWork.addUnitOfWorkCallback( new UnitOfWorkCallback()
+            {
+                @Override
+                public void beforeCompletion()
+                    throws UnitOfWorkCompletionException
+                {
+                }
+
+                @Override
+                public void afterCompletion( UnitOfWorkStatus status )
+                {
+                    if( status.equals( UnitOfWorkStatus.COMPLETED ) )
+                    {
+                        Request.getCurrent().getAttributes().put( "event", domainEvent );
+                    }
+                }
+            } );
+
+            return result;
+        }
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/domainevent/DomainEventValue.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/domainevent/DomainEventValue.java
new file mode 100644
index 0000000..c2568fd
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/domainevent/DomainEventValue.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.sample.forum.domainevent;
+
+import java.time.Instant;
+import java.util.List;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * TODO
+ */
+public interface DomainEventValue
+    extends ValueComposite
+{
+    // Version of the application that created these events
+    Property<String> version();
+
+    // When the event occurred
+    Property<Instant> timestamp();
+
+    // Selected objects
+    @UseDefaults
+    Property<List<String>> selection();
+
+    // Type of the entity being invoked
+    Property<String> context();
+
+    // Name of method/event
+    Property<String> name();
+
+    // Method parameters as JSON
+    @UseDefaults
+    Property<List<ParameterValue>> parameters();
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/domainevent/ParameterValue.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/domainevent/ParameterValue.java
new file mode 100644
index 0000000..6b1f46b
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/domainevent/ParameterValue.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.sample.forum.domainevent;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+/**
+ * TODO
+ */
+public interface ParameterValue
+    extends ValueComposite
+{
+    Property<String> name();
+
+    Property<Object> value();
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/ForumRestlet.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/ForumRestlet.java
new file mode 100644
index 0000000..e735d42
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/ForumRestlet.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.sample.forum.rest;
+
+import org.apache.polygene.library.rest.server.api.ContextRestlet;
+import org.apache.polygene.sample.forum.rest.resource.RootResource;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.Uniform;
+
+/**
+ * TODO
+ */
+public class ForumRestlet
+    extends ContextRestlet
+{
+    @Override
+    protected Uniform createRoot( Request request, Response response )
+    {
+        return objectFactory.newObject( RootResource.class, this );
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/RootResource.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/RootResource.java
new file mode 100644
index 0000000..981f613
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/RootResource.java
@@ -0,0 +1,82 @@
+/*
+ *  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.polygene.sample.forum.rest.resource;
+
+import java.util.Collections;
+import org.apache.polygene.library.rest.server.api.ContextResource;
+import org.apache.polygene.library.rest.server.api.SubResource;
+import org.apache.polygene.library.rest.server.api.constraint.Requires;
+import org.apache.polygene.sample.forum.data.entity.User;
+import org.apache.polygene.sample.forum.data.entity.Users;
+import org.apache.polygene.sample.forum.rest.resource.administration.AdministrationResource;
+import org.apache.polygene.sample.forum.rest.resource.forum.ForumResource;
+import org.apache.polygene.sample.forum.rest.resource.signup.SignupResource;
+import org.restlet.Request;
+import org.restlet.Response;
+import org.restlet.data.ChallengeRequest;
+import org.restlet.data.ChallengeResponse;
+import org.restlet.data.ChallengeScheme;
+import org.restlet.data.Status;
+import org.restlet.resource.ResourceException;
+
+import static org.apache.polygene.library.rest.server.api.ObjectSelection.current;
+
+/**
+ * TODO
+ */
+public class RootResource
+    extends ContextResource
+{
+    @SubResource
+    public void signup()
+    {
+        select( Users.class, Users.USERS_ID );
+        subResource( SignupResource.class );
+    }
+
+    @SubResource
+    public void administration()
+    {
+        ChallengeResponse challenge = Request.getCurrent().getChallengeResponse();
+        if( challenge == null )
+        {
+            Response.getCurrent()
+                .setChallengeRequests( Collections.singletonList( new ChallengeRequest( ChallengeScheme.HTTP_BASIC, "Forum" ) ) );
+            throw new ResourceException( Status.CLIENT_ERROR_UNAUTHORIZED );
+        }
+
+        User user = select( Users.class, Users.USERS_ID ).userNamed( challenge.getIdentifier() );
+        if( user == null || !user.isCorrectPassword( new String( challenge.getSecret() ) ) )
+        {
+            throw new ResourceException( Status.CLIENT_ERROR_UNAUTHORIZED );
+        }
+
+        current().select( user );
+
+        subResource( AdministrationResource.class );
+    }
+
+    @SubResource
+    @Requires( User.class )
+    public void forum()
+    {
+        subResource( ForumResource.class );
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/administration/AdministrationResource.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/administration/AdministrationResource.java
new file mode 100644
index 0000000..012ac19
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/administration/AdministrationResource.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.sample.forum.rest.resource.administration;
+
+import org.apache.polygene.library.rest.server.api.ContextResource;
+import org.apache.polygene.library.rest.server.api.SubResource;
+import org.apache.polygene.sample.forum.data.entity.Forums;
+import org.apache.polygene.sample.forum.data.entity.Users;
+
+/**
+ * TODO
+ */
+public class AdministrationResource
+    extends ContextResource
+{
+    @SubResource
+    public void forums()
+    {
+        select( Forums.class, Forums.FORUMS_ID );
+        subResource( ForumsResource.class );
+    }
+
+    @SubResource
+    public void users()
+    {
+        select( Users.class, Users.USERS_ID );
+        subResource( UsersResource.class );
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/administration/ForumsResource.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/administration/ForumsResource.java
new file mode 100644
index 0000000..ef86c38
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/administration/ForumsResource.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.sample.forum.rest.resource.administration;
+
+import org.apache.polygene.library.rest.server.api.ContextResource;
+
+/**
+ * TODO
+ */
+public class ForumsResource
+    extends ContextResource
+{
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/administration/UsersResource.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/administration/UsersResource.java
new file mode 100644
index 0000000..302d44b
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/administration/UsersResource.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.sample.forum.rest.resource.administration;
+
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.library.rest.server.api.ContextResource;
+import org.apache.polygene.library.rest.server.api.ObjectSelection;
+import org.apache.polygene.library.rest.server.api.ResourceIndex;
+import org.apache.polygene.sample.forum.data.entity.User;
+import org.apache.polygene.sample.forum.data.entity.Users;
+
+/**
+ * TODO
+ */
+public class UsersResource
+    extends ContextResource
+    implements ResourceIndex<Query<User>>
+{
+    @Override
+    public Query<User> index()
+    {
+        return ObjectSelection.current().get( Users.class ).users();
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/forum/BoardResource.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/forum/BoardResource.java
new file mode 100644
index 0000000..164b0c8
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/forum/BoardResource.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.sample.forum.rest.resource.forum;
+
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.library.rest.server.api.ContextResource;
+import org.apache.polygene.library.rest.server.api.ObjectSelection;
+import org.apache.polygene.library.rest.server.api.SubResources;
+import org.apache.polygene.sample.forum.data.entity.Forum;
+import org.restlet.resource.ResourceException;
+
+/**
+ * TODO
+ */
+public class BoardResource
+    extends ContextResource
+    implements SubResources
+{
+    @Override
+    public void resource( String segment )
+        throws ResourceException
+    {
+        selectFromManyAssociation( ObjectSelection.current().get( Forum.class ).boards(),  new StringIdentity( segment ) );
+        subResource( BoardResource.class );
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/forum/ForumResource.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/forum/ForumResource.java
new file mode 100644
index 0000000..73ff700
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/forum/ForumResource.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.sample.forum.rest.resource.forum;
+
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.library.rest.server.api.ContextResource;
+import org.apache.polygene.library.rest.server.api.ObjectSelection;
+import org.apache.polygene.library.rest.server.api.SubResources;
+import org.apache.polygene.sample.forum.data.entity.Forum;
+import org.restlet.resource.ResourceException;
+
+/**
+ * TODO
+ */
+public class ForumResource
+    extends ContextResource
+    implements SubResources
+{
+    @Override
+    public void resource( String segment )
+        throws ResourceException
+    {
+        selectFromManyAssociation( ObjectSelection.current().get( Forum.class ).boards(), new StringIdentity( segment ) );
+        subResource( BoardResource.class );
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/forum/ForumsResource.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/forum/ForumsResource.java
new file mode 100644
index 0000000..45e9f7b
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/forum/ForumsResource.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.sample.forum.rest.resource.forum;
+
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.library.rest.server.api.ContextResource;
+import org.apache.polygene.library.rest.server.api.SubResources;
+import org.apache.polygene.sample.forum.data.entity.Forum;
+import org.restlet.resource.ResourceException;
+
+/**
+ * TODO
+ */
+public class ForumsResource
+    extends ContextResource
+    implements SubResources
+{
+    @Override
+    public void resource( String segment )
+        throws ResourceException
+    {
+        select( Forum.class, new StringIdentity( segment ) );
+        subResource( ForumResource.class );
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/login/LoginResource.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/login/LoginResource.java
new file mode 100644
index 0000000..620e6ce
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/login/LoginResource.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.sample.forum.rest.resource.login;
+
+import org.apache.polygene.library.rest.server.api.ContextResource;
+import org.apache.polygene.sample.forum.context.login.Login;
+import org.restlet.Response;
+import org.restlet.representation.EmptyRepresentation;
+import org.restlet.representation.Representation;
+
+/**
+ * TODO
+ */
+public class LoginResource
+    extends ContextResource
+{
+    public Representation login( String name, String password )
+    {
+        context( Login.class ).login( name, password );
+
+        EmptyRepresentation rep = new EmptyRepresentation();
+        Response.getCurrent().getCookieSettings().add( "user", name );
+        return rep;
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/signup/SignupResource.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/signup/SignupResource.java
new file mode 100644
index 0000000..e9248bf
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/rest/resource/signup/SignupResource.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.sample.forum.rest.resource.signup;
+
+import org.apache.polygene.library.rest.server.api.ContextResource;
+import org.apache.polygene.sample.forum.context.signup.Registration;
+import org.apache.polygene.sample.forum.context.signup.Signup;
+import org.restlet.data.Form;
+
+/**
+ * TODO
+ */
+public class SignupResource
+    extends ContextResource
+{
+    public void signup( Registration registration )
+    {
+        context( Signup.class ).signup( registration );
+    }
+
+    public Form signup()
+    {
+        Form form = new Form();
+        form.set( "name", "Rickard" );
+        form.set( "realName", "Rickard Öberg" );
+        form.set( "password", "rickard" );
+        form.set( "email", "rickard@polygene" );
+        return form;
+    }
+}
diff --git a/samples/forum/src/main/java/org/apache/polygene/sample/forum/service/BootstrapData.java b/samples/forum/src/main/java/org/apache/polygene/sample/forum/service/BootstrapData.java
new file mode 100644
index 0000000..13fa568
--- /dev/null
+++ b/samples/forum/src/main/java/org/apache/polygene/sample/forum/service/BootstrapData.java
@@ -0,0 +1,89 @@
+/*
+ *  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.polygene.sample.forum.service;
+
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.sample.forum.data.entity.Forums;
+import org.apache.polygene.sample.forum.data.entity.Users;
+
+/**
+ * TODO
+ */
+@Mixins( BootstrapData.Mixin.class )
+@Activators( BootstrapData.Activator.class )
+public interface BootstrapData
+    extends ServiceComposite
+{
+    void insertInitialData()
+        throws Exception;
+
+    class Activator
+        extends ActivatorAdapter<ServiceReference<BootstrapData>>
+    {
+        @Override
+        public void afterActivation( ServiceReference<BootstrapData> activated )
+            throws Exception
+        {
+            activated.get().insertInitialData();
+        }
+    }
+
+    abstract class Mixin
+        implements BootstrapData
+    {
+        @Structure
+        private UnitOfWorkFactory module;
+
+        @Override
+        public void insertInitialData()
+            throws Exception
+        {
+            UnitOfWork unitOfWork = module.newUnitOfWork();
+
+            try
+            {
+                unitOfWork.get( Forums.class, Forums.FORUMS_ID );
+            }
+            catch( NoSuchEntityException e )
+            {
+                unitOfWork.newEntity( Forums.class, Forums.FORUMS_ID );
+            }
+
+            try
+            {
+                unitOfWork.get( Users.class, Users.USERS_ID );
+            }
+            catch( NoSuchEntityException e )
+            {
+                unitOfWork.newEntity( Users.class, Users.USERS_ID );
+            }
+
+            unitOfWork.complete();
+        }
+    }
+}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/assembler/ForumAssembler.java b/samples/forum/src/main/java/org/qi4j/samples/forum/assembler/ForumAssembler.java
deleted file mode 100644
index a6fe814..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/assembler/ForumAssembler.java
+++ /dev/null
@@ -1,175 +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.qi4j.samples.forum.assembler;
-
-import java.lang.reflect.Modifier;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.ApplicationAssemblyFactory;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ClassScanner;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.file.assembly.FileEntityStoreAssembler;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.functional.Function;
-import org.qi4j.library.fileconfig.FileConfigurationService;
-import org.qi4j.library.rest.common.ValueAssembler;
-import org.qi4j.library.rest.server.assembler.RestServerAssembler;
-import org.qi4j.library.rest.server.restlet.RequestReaderDelegator;
-import org.qi4j.library.rest.server.restlet.ResponseWriterDelegator;
-import org.qi4j.library.rest.server.spi.CommandResult;
-import org.qi4j.samples.forum.context.Context;
-import org.qi4j.samples.forum.context.EventsService;
-import org.qi4j.samples.forum.data.entity.User;
-import org.qi4j.samples.forum.domainevent.DomainCommandResult;
-import org.qi4j.samples.forum.domainevent.DomainEventValue;
-import org.qi4j.samples.forum.domainevent.ParameterValue;
-import org.qi4j.samples.forum.rest.ForumRestlet;
-import org.qi4j.samples.forum.rest.resource.RootResource;
-import org.qi4j.samples.forum.service.BootstrapData;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-import org.restlet.service.MetadataService;
-
-import static org.qi4j.api.util.Classes.hasModifier;
-import static org.qi4j.api.util.Classes.isAssignableFrom;
-import static org.qi4j.functional.Iterables.filter;
-import static org.qi4j.functional.Specifications.not;
-
-/**
- * TODO
- */
-public class ForumAssembler
-    implements ApplicationAssembler
-{
-    @Override
-    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-        throws AssemblyException
-    {
-        ApplicationAssembly assembly = applicationFactory.newApplicationAssembly();
-
-        assembly.setName( "Forum" );
-
-        ModuleAssembly configModule;
-        LayerAssembly configuration = assembly.layer( "Configuration" );
-        {
-            configModule = configuration.module( "Configuration" );
-            configModule.services( MemoryEntityStoreService.class );
-            configModule.services( UuidIdentityGeneratorService.class );
-            new OrgJsonValueSerializationAssembler().assemble( configModule );
-        }
-
-        LayerAssembly infrastructure = assembly.layer( "Infrastructure" ).uses( configuration );
-        {
-            ModuleAssembly entityStore = infrastructure.module( "EntityStore" );
-            entityStore.services( FileConfigurationService.class );
-            new FileEntityStoreAssembler().withConfig( configModule, Visibility.application ).assemble( entityStore );
-            entityStore.services( UuidIdentityGeneratorService.class ).visibleIn( Visibility.application );
-            new OrgJsonValueSerializationAssembler().
-                visibleIn( Visibility.application ).
-                withValuesModuleFinder( new Function<Application, Module>()
-            {
-                @Override
-                public Module map( Application app )
-                {
-                    return app.findModule( "REST", "Values" );
-                }
-            } ).
-                assemble( entityStore );
-        }
-
-        LayerAssembly data = assembly.layer( "Data" ).uses( infrastructure );
-        {
-            ModuleAssembly forum = data.module( "Forum" );
-            for( Class<?> dataClass : filter( hasModifier( Modifier.INTERFACE ), filter( isAssignableFrom( EntityComposite.class ), ClassScanner
-                .findClasses( User.class ) ) ) )
-            {
-                forum.entities( dataClass ).visibleIn( Visibility.application );
-            }
-        }
-
-        LayerAssembly context = assembly.layer( "Context" ).uses( data );
-        {
-            ModuleAssembly contexts = context.module( "Context" );
-            for( Class<?> contextClass : filter( not( hasModifier( Modifier.INTERFACE ) ), ClassScanner.findClasses( Context.class ) ) )
-            {
-                if( contextClass.getName().contains( "$" ) )
-                {
-                    contexts.transients( contextClass ).visibleIn( Visibility.application );
-                }
-                else
-                {
-                    contexts.objects( contextClass ).visibleIn( Visibility.application );
-                }
-            }
-
-            for( Class<?> valueClass : filter( isAssignableFrom( ValueComposite.class ), ClassScanner.findClasses( Context.class ) ) )
-            {
-                contexts.values( valueClass ).visibleIn( Visibility.application );
-            }
-
-            contexts.services( EventsService.class );
-
-            context.module( "Domain events" )
-                .values( DomainEventValue.class, ParameterValue.class )
-                .visibleIn( Visibility.application );
-        }
-
-        LayerAssembly services = assembly.layer( "Service" ).uses( data );
-        {
-            ModuleAssembly bootstrap = services.module( "Bootstrap" );
-            bootstrap.services( BootstrapData.class ).identifiedBy( "bootstrap" ).instantiateOnStartup();
-        }
-
-        LayerAssembly rest = assembly.layer( "REST" ).uses( context, data );
-        {
-            ModuleAssembly values = rest.module( "Values" );
-            {
-                new ValueAssembler().assemble( values );
-            }
-
-            ModuleAssembly transformation = rest.module( "Transformation" );
-            {
-                new RestServerAssembler().assemble( transformation );
-                transformation.objects( RequestReaderDelegator.class, ResponseWriterDelegator.class )
-                    .visibleIn( Visibility.layer );
-                new OrgJsonValueSerializationAssembler().assemble( transformation );
-            }
-
-            ModuleAssembly resources = rest.module( "Resources" );
-            for( Class<?> resourceClass : ClassScanner.findClasses( RootResource.class ) )
-            {
-                resources.objects( resourceClass ).visibleIn( Visibility.layer );
-            }
-
-            ModuleAssembly restlet = rest.module( "Restlet" );
-            restlet.objects( ForumRestlet.class );
-            restlet.importedServices( CommandResult.class ).setMetaInfo( new DomainCommandResult() );
-            restlet.importedServices( MetadataService.class );
-        }
-
-        return assembly;
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/Context.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/Context.java
deleted file mode 100644
index e338833..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/Context.java
+++ /dev/null
@@ -1,43 +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.qi4j.samples.forum.context;
-
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.structure.Module;
-
-/**
- * TODO
- */
-public class Context
-{
-    @Structure
-    protected Module module;
-
-    protected <T> T role( Class<T> roleType, Object data )
-    {
-        return module.newObject( roleType, data );
-    }
-
-    protected <T> T role( Object object, Class<T> roleType )
-    {
-        return Qi4j.FUNCTION_COMPOSITE_INSTANCE_OF.map( (Composite) object ).newProxy( roleType );
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/Events.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/Events.java
deleted file mode 100644
index 1fdae35..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/Events.java
+++ /dev/null
@@ -1,29 +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.qi4j.samples.forum.context;
-
-import org.qi4j.samples.forum.context.signup.Registration;
-
-/**
- * Domain Events that can be triggered by the contexts
- */
-public interface Events
-{
-    void signedup( Registration registration );
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/EventsService.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/EventsService.java
deleted file mode 100644
index 047890a..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/EventsService.java
+++ /dev/null
@@ -1,119 +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.qi4j.samples.forum.context;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCallback;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.library.rest.server.api.ObjectSelection;
-import org.qi4j.samples.forum.domainevent.DomainEventValue;
-import org.qi4j.samples.forum.domainevent.ParameterValue;
-import org.restlet.Request;
-
-/**
- * TODO
- */
-@Mixins( EventsService.Mixin.class )
-public interface EventsService
-    extends Events, ServiceComposite
-{
-    public class Mixin
-        implements InvocationHandler
-    {
-        @Structure
-        Module module;
-        @Structure
-        Application application;
-
-        @Override
-        public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-        {
-            UnitOfWork unitOfWork = module.currentUnitOfWork();
-
-            ValueBuilder<DomainEventValue> builder = module.newValueBuilder( DomainEventValue.class );
-            DomainEventValue prototype = builder.prototype();
-            prototype.version().set( application.version() );
-            prototype.timestamp().set( unitOfWork.currentTime() );
-            prototype.context().set( proxy.getClass().getSuperclass().getName().split( "\\$" )[ 0 ] );
-            prototype.name().set( method.getName() );
-
-            int idx = 0;
-            for( Object arg : args )
-            {
-                idx++;
-                String name = "param" + idx;
-                ValueBuilder<ParameterValue> parameterBuilder = module.newValueBuilder( ParameterValue.class );
-                parameterBuilder.prototype().name().set( name );
-                parameterBuilder.prototype().value().set( arg );
-                prototype.parameters().get().add( parameterBuilder.newInstance() );
-            }
-
-            Iterables.addAll( prototype.selection().get(), Iterables.map( new Function<Object, String>()
-            {
-                @Override
-                public String map( Object o )
-                {
-                    return o.toString();
-                }
-            }, ObjectSelection.current().selection() ) );
-
-            final DomainEventValue domainEvent = builder.newInstance();
-
-            // Send event to all interested parties in the ObjectSelection
-            for( Object selectedObject : ObjectSelection.current().selection() )
-            {
-                if( selectedObject instanceof Events )
-                {
-                    method.invoke( selectedObject, args );
-                }
-            }
-
-            unitOfWork.addUnitOfWorkCallback( new UnitOfWorkCallback()
-            {
-                @Override
-                public void beforeCompletion()
-                    throws UnitOfWorkCompletionException
-                {
-                }
-
-                @Override
-                public void afterCompletion( UnitOfWorkStatus status )
-                {
-                    if( status.equals( UnitOfWorkStatus.COMPLETED ) )
-                    {
-                        Request.getCurrent().getAttributes().put( "event", domainEvent );
-                    }
-                }
-            } );
-
-            return null;
-        }
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/account/UpdateProfile.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/account/UpdateProfile.java
deleted file mode 100644
index b87766c..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/account/UpdateProfile.java
+++ /dev/null
@@ -1,66 +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.qi4j.samples.forum.context.account;
-
-import org.qi4j.api.constraint.Name;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.library.rest.server.api.ResourceIndex;
-import org.qi4j.library.rest.server.api.dci.Role;
-import org.qi4j.samples.forum.context.Context;
-import org.qi4j.samples.forum.data.entity.User;
-
-/**
- * TODO
- */
-public class UpdateProfile
-    extends Context
-    implements ResourceIndex<UpdateProfile.Profile>
-{
-    Profile profile;
-
-    public UpdateProfile bind( @Uses User user )
-    {
-        profile = role( Profile.class, user );
-        return this;
-    }
-
-    public Profile index()
-    {
-        return profile;
-    }
-
-    public void updateProfile( @Name( "name" ) String name,
-                               @Name( "realname" ) String realName,
-                               @Name( "email" ) String email
-    )
-    {
-        profile.updateProfile( name, realName, email );
-    }
-
-    protected class Profile
-        extends Role<User>
-    {
-        public void updateProfile( String name, String realName, String email )
-        {
-            self.name().set( name );
-            self.realName().set( realName );
-            self.email().set( email );
-        }
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/BoardAdministration.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/BoardAdministration.java
deleted file mode 100644
index 2797058..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/BoardAdministration.java
+++ /dev/null
@@ -1,69 +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.qi4j.samples.forum.context.administration;
-
-import org.qi4j.api.constraint.Name;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.server.api.ResourceIndex;
-import org.qi4j.library.rest.server.api.dci.Role;
-import org.qi4j.samples.forum.data.entity.Board;
-import org.qi4j.samples.forum.data.entity.Forum;
-import org.qi4j.samples.forum.data.entity.User;
-
-/**
- * TODO
- */
-public class BoardAdministration
-    implements ResourceIndex<Board>
-{
-    @Structure
-    Module module;
-
-    BoardAdmin boardAdmin = new BoardAdmin();
-
-    public BoardAdministration bind( @Uses Forum forum, @Uses Board board, @Uses User user )
-    {
-        boardAdmin.bind( board );
-        return this;
-    }
-
-    public Board index()
-    {
-        return boardAdmin.self();
-    }
-
-    public void updateName( @Name( "name" ) String name )
-    {
-        boardAdmin.updateName( name );
-    }
-
-    protected class BoardAdmin
-        extends Role<Board>
-    {
-        @Structure
-        Module module;
-
-        public void updateName( String name )
-        {
-            self().name().set( name );
-        }
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/ForumAdministration.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/ForumAdministration.java
deleted file mode 100644
index be5b3fd..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/ForumAdministration.java
+++ /dev/null
@@ -1,89 +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.qi4j.samples.forum.context.administration;
-
-import org.qi4j.api.constraint.Name;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.server.api.ResourceIndex;
-import org.qi4j.library.rest.server.api.dci.Role;
-import org.qi4j.samples.forum.data.entity.Board;
-import org.qi4j.samples.forum.data.entity.Forum;
-import org.qi4j.samples.forum.data.entity.User;
-
-/**
- * TODO
- */
-public class ForumAdministration
-    implements ResourceIndex<Query<Board>>
-{
-    @Structure
-    Module module;
-
-    ForumAdmin forumAdmin = new ForumAdmin();
-    Administrator administrator = new Administrator();
-
-    public ForumAdministration bind( @Uses Forum forum, @Uses User user )
-    {
-        forumAdmin.bind( forum );
-        administrator.bind( user );
-        return this;
-    }
-
-    public Query<Board> index()
-    {
-        return forumAdmin.boards();
-    }
-
-    public Board createBoard( @Name( "name" ) String name )
-    {
-        return forumAdmin.createBoard( name );
-    }
-
-    protected class ForumAdmin
-        extends Role<Forum>
-    {
-        @Structure
-        Module module;
-
-        public Query<Board> boards()
-        {
-            return module.newQueryBuilder( Board.class ).newQuery( self.boards() );
-        }
-
-        public Board createBoard( String name )
-        {
-            Board board = module.currentUnitOfWork().newEntity( Board.class );
-            board.name().set( name );
-            administrator.makeModerator( board );
-            return board;
-        }
-    }
-
-    protected class Administrator
-        extends Role<User>
-    {
-        public void makeModerator( Board board )
-        {
-            board.moderators().add( self );
-        }
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/ForumsAdministration.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/ForumsAdministration.java
deleted file mode 100644
index 10dfb96..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/ForumsAdministration.java
+++ /dev/null
@@ -1,86 +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.qi4j.samples.forum.context.administration;
-
-import org.qi4j.api.constraint.Name;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.server.api.ResourceIndex;
-import org.qi4j.library.rest.server.api.dci.Role;
-import org.qi4j.samples.forum.data.entity.Forum;
-import org.qi4j.samples.forum.data.entity.Forums;
-import org.qi4j.samples.forum.data.entity.User;
-
-/**
- * TODO
- */
-public class ForumsAdministration
-    implements ResourceIndex<Query<Forum>>
-{
-    @Structure
-    Module module;
-
-    ForumsAdmin forumsAdmin = new ForumsAdmin();
-    Administrator administrator = new Administrator();
-
-    public ForumsAdministration bind( @Uses Forums forums, @Uses User user )
-    {
-        forumsAdmin.bind( forums );
-        administrator.bind( user );
-        return this;
-    }
-
-    public Query<Forum> index()
-    {
-        return forumsAdmin.forums();
-    }
-
-    public Forum createForum( @Name( "name" ) String name )
-    {
-        return forumsAdmin.createForum( name );
-    }
-
-    protected class ForumsAdmin
-        extends Role<Forums>
-    {
-        public Query<Forum> forums()
-        {
-            return self.forums();
-        }
-
-        public Forum createForum( String name )
-        {
-            Forum forum = module.currentUnitOfWork().newEntity( Forum.class );
-            forum.name().set( name );
-            administrator.makeModerator( forum );
-            return forum;
-        }
-    }
-
-    protected class Administrator
-        extends Role<User>
-    {
-        public void makeModerator( Forum forum )
-        {
-            forum.moderators().add( self );
-        }
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/ModeratorAdministration.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/ModeratorAdministration.java
deleted file mode 100644
index 561c016..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/ModeratorAdministration.java
+++ /dev/null
@@ -1,75 +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.qi4j.samples.forum.context.administration;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.server.api.ResourceDelete;
-import org.qi4j.library.rest.server.api.ResourceIndex;
-import org.qi4j.library.rest.server.api.dci.Role;
-import org.qi4j.samples.forum.data.Moderators;
-import org.qi4j.samples.forum.data.entity.User;
-
-/**
- * TODO
- */
-public class ModeratorAdministration
-    implements ResourceIndex<User>, ResourceDelete
-{
-    @Structure
-    Module module;
-
-    ModeratorAdmin moderatorAdmin = new ModeratorAdmin();
-    Moderator moderator = new Moderator();
-
-    public ModeratorAdministration bind( @Uses Moderators moderators, @Uses User user )
-    {
-        moderatorAdmin.bind( moderators );
-        moderator.bind( user );
-        return this;
-    }
-
-    public User index()
-    {
-        return moderator.self();
-    }
-
-    public void delete()
-    {
-        moderatorAdmin.removeModerator();
-    }
-
-    protected class Moderator
-        extends Role<User>
-    {
-    }
-
-    protected class ModeratorAdmin
-        extends Role<Moderators>
-    {
-        @Structure
-        Module module;
-
-        public void removeModerator()
-        {
-            self().moderators().remove( moderator.self() );
-        }
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/ModeratorsAdministration.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/ModeratorsAdministration.java
deleted file mode 100644
index 0632368..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/ModeratorsAdministration.java
+++ /dev/null
@@ -1,83 +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.qi4j.samples.forum.context.administration;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.server.api.ResourceIndex;
-import org.qi4j.library.rest.server.api.dci.Role;
-import org.qi4j.samples.forum.data.Moderators;
-import org.qi4j.samples.forum.data.entity.User;
-
-/**
- * TODO
- */
-public class ModeratorsAdministration
-    implements ResourceIndex<Query<User>>
-{
-    @Structure
-    Module module;
-
-    ModeratorsAdmin moderatorsAdmin = new ModeratorsAdmin();
-
-    public ModeratorsAdministration bind( @Uses Moderators moderators )
-    {
-        moderatorsAdmin.bind( moderators );
-        return this;
-    }
-
-    public Query<User> index()
-    {
-        return moderatorsAdmin.moderators();
-    }
-
-    public void addModerator( User user )
-    {
-        moderatorsAdmin.addModerator( user );
-    }
-
-    public void removeModerator( User user )
-    {
-        moderatorsAdmin.removeModerator( user );
-    }
-
-    protected class ModeratorsAdmin
-        extends Role<Moderators>
-    {
-        @Structure
-        Module module;
-
-        public Query<User> moderators()
-        {
-            return module.newQueryBuilder( User.class ).newQuery( self.moderators() );
-        }
-
-        public void addModerator( User user )
-        {
-            self().moderators().add( user );
-        }
-
-        public void removeModerator( User user )
-        {
-            self().moderators().remove( user );
-        }
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/UsersAdministration.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/UsersAdministration.java
deleted file mode 100644
index 8329db3..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/administration/UsersAdministration.java
+++ /dev/null
@@ -1,55 +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.qi4j.samples.forum.context.administration;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.server.api.dci.Role;
-import org.qi4j.samples.forum.data.entity.User;
-import org.qi4j.samples.forum.data.entity.Users;
-
-/**
- * TODO
- */
-public class UsersAdministration
-{
-    @Structure
-    Module module;
-
-    UsersAdmin usersAdmin = new UsersAdmin();
-    Administrator administrator = new Administrator();
-
-    public UsersAdministration bind( @Uses Users users, @Uses User user )
-    {
-        usersAdmin.bind( users );
-        administrator.bind( user );
-        return this;
-    }
-
-    protected class UsersAdmin
-        extends Role<Users>
-    {
-    }
-
-    protected class Administrator
-        extends Role<User>
-    {
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/login/Login.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/login/Login.java
deleted file mode 100644
index 4694367..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/login/Login.java
+++ /dev/null
@@ -1,47 +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.qi4j.samples.forum.context.login;
-
-import org.qi4j.api.constraint.Name;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.query.QueryExpressions;
-import org.qi4j.api.structure.Module;
-import org.qi4j.samples.forum.data.entity.User;
-
-/**
- * TODO
- */
-public class Login
-{
-    @Structure
-    Module module;
-
-    public void login( @Name( "name" ) String name, @Name( "password" ) String password )
-    {
-        User user = module.currentUnitOfWork()
-            .newQuery( module.newQueryBuilder( User.class )
-                           .where( QueryExpressions.eq( QueryExpressions.templateFor( User.class ).name(), name ) ) )
-            .find();
-
-        if( user == null || !user.isCorrectPassword( password ) )
-        {
-            throw new IllegalArgumentException( "Login incorrect" );
-        }
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/moderation/ModerationContext.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/moderation/ModerationContext.java
deleted file mode 100644
index e86740b..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/moderation/ModerationContext.java
+++ /dev/null
@@ -1,27 +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.qi4j.samples.forum.context.moderation;
-
-/**
- * TODO
- */
-public class ModerationContext
-{
-
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/signup/Registration.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/signup/Registration.java
deleted file mode 100644
index 8110ba7..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/signup/Registration.java
+++ /dev/null
@@ -1,37 +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.qi4j.samples.forum.context.signup;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * TODO
- */
-public interface Registration
-    extends ValueComposite
-{
-    Property<String> name();
-
-    Property<String> realName();
-
-    Property<String> email();
-
-    Property<String> password();
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/signup/Signup.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/signup/Signup.java
deleted file mode 100644
index a07ec2d..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/signup/Signup.java
+++ /dev/null
@@ -1,53 +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.qi4j.samples.forum.context.signup;
-
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.samples.forum.context.Context;
-import org.qi4j.samples.forum.context.Events;
-
-/**
- * TODO
- */
-public class Signup
-    extends Context
-{
-    @Uses
-    Users users;
-
-    @Service
-    Events events;
-
-    public void signup( Registration registration )
-    {
-        users.signup( registration );
-    }
-
-    protected class Users
-        implements TransientComposite
-    {
-        public void signup( Registration registration )
-        {
-            // Check if user with this name already exists
-            events.signedup( registration );
-        }
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewBoard.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewBoard.java
deleted file mode 100644
index 63f3d91..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewBoard.java
+++ /dev/null
@@ -1,127 +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.qi4j.samples.forum.context.view;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.server.api.ResourceIndex;
-import org.qi4j.library.rest.server.api.dci.Role;
-import org.qi4j.samples.forum.data.Moderators;
-import org.qi4j.samples.forum.data.entity.Board;
-import org.qi4j.samples.forum.data.entity.Forum;
-import org.qi4j.samples.forum.data.entity.Post;
-import org.qi4j.samples.forum.data.entity.Topic;
-import org.qi4j.samples.forum.data.entity.User;
-
-import static org.qi4j.api.property.Numbers.add;
-
-/**
- * TODO
- */
-public class ViewBoard
-    implements ResourceIndex<Board>
-{
-    private Posting posting;
-    private BoardViewer viewer;
-    private BoardModeration boardModeration;
-    private ForumModeration forumModeration;
-
-    public ViewBoard bind( @Uses Forum forum, @Uses Board board, @Uses User user )
-    {
-        posting.bind( board );
-        viewer.bind( user );
-        boardModeration.bind( board );
-        forumModeration.bind( forum );
-        return this;
-    }
-
-    @Override
-    public Board index()
-    {
-        return posting.self();
-    }
-
-    public Topic createTopic( String subject, String message )
-    {
-        return posting.createTopic( subject, message, viewer );
-    }
-
-    protected class BoardViewer
-        extends Role<User>
-    {
-        boolean isModerator( Moderators moderators )
-        {
-            return moderators.moderators().contains( self );
-        }
-    }
-
-    protected class BoardModeration
-        extends Role<Moderators>
-    {
-        boolean isModerator( BoardViewer user )
-        {
-            return user.isModerator( self ) || forumModeration.isModerator( user );
-        }
-    }
-
-    protected class ForumModeration
-        extends Role<Moderators>
-    {
-        boolean isModerator( BoardViewer user )
-        {
-            return user.isModerator( self );
-        }
-    }
-
-    protected class Posting
-        extends Role<Board>
-    {
-        @Structure
-        Module module;
-
-        Topic createTopic( String subject, String message, BoardViewer poster )
-        {
-            Topic topic = module.currentUnitOfWork().newEntity( Topic.class );
-
-            topic.subject().set( subject );
-
-            Post post = module.currentUnitOfWork().newEntity( Post.class );
-            post.message().set( message );
-
-            // Moderation checks
-            if( boardModeration.isModerator( poster ) )
-            {
-                post.status().set( Post.Status.POSTED );
-
-                self.lastPost().set( post );
-                add( self.topicCount(), 1 );
-                add( self.postCount(), 1 );
-
-                return topic;
-            }
-            else
-            {
-                post.status().set( Post.Status.MODERATION );
-            }
-
-            return topic;
-        }
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewForum.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewForum.java
deleted file mode 100644
index 570b3cb..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewForum.java
+++ /dev/null
@@ -1,61 +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.qi4j.samples.forum.context.view;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.server.api.ResourceIndex;
-import org.qi4j.library.rest.server.api.dci.Role;
-import org.qi4j.samples.forum.data.entity.Board;
-import org.qi4j.samples.forum.data.entity.Forum;
-import org.qi4j.samples.forum.data.entity.User;
-
-/**
- * TODO
- */
-public class ViewForum
-    implements ResourceIndex<Query<Board>>
-{
-    private ForumView viewForum = new ForumView();
-
-    public org.qi4j.samples.forum.context.view.ViewForum bind( @Uses Forum forum, @Uses User user )
-    {
-        viewForum.bind( forum );
-        return this;
-    }
-
-    public Query<Board> index()
-    {
-        return viewForum.boards();
-    }
-
-    protected class ForumView
-        extends Role<Forum>
-    {
-        @Structure
-        Module module;
-
-        public Query<Board> boards()
-        {
-            return module.newQueryBuilder( Board.class ).newQuery( self.boards() );
-        }
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewPost.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewPost.java
deleted file mode 100644
index e927a42..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewPost.java
+++ /dev/null
@@ -1,91 +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.qi4j.samples.forum.context.view;
-
-import java.util.Date;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.property.Numbers;
-import org.qi4j.api.structure.Module;
-import org.qi4j.library.rest.server.api.ResourceIndex;
-import org.qi4j.library.rest.server.api.dci.Role;
-import org.qi4j.samples.forum.data.entity.Post;
-import org.qi4j.samples.forum.data.entity.Topic;
-import org.qi4j.samples.forum.data.entity.User;
-
-/**
- * TODO
- */
-public class ViewPost
-    implements ResourceIndex<Post>
-{
-    PostView viewPost = new PostView();
-    ReplyTopic replyTopic = new ReplyTopic();
-    Poster poster = new Poster();
-
-    public ViewPost bind( @Uses Topic topic, @Uses Post post, @Uses User user )
-    {
-        viewPost.bind( post );
-        replyTopic.bind( topic );
-        poster.bind( user );
-        return this;
-    }
-
-    @Override
-    public Post index()
-    {
-        return viewPost.self();
-    }
-
-    public Post reply( String message )
-    {
-        return replyTopic.reply( message, viewPost );
-    }
-
-    protected class ReplyTopic
-        extends Role<Topic>
-    {
-        @Structure
-        Module module;
-
-        public Post reply( String message, PostView viewPost )
-        {
-            Post post = module.currentUnitOfWork().newEntity( Post.class );
-            post.message().set( message );
-            post.createdBy().set( poster.self() );
-            post.createdOn().set( new Date( module.currentUnitOfWork().currentTime() ) );
-            post.replyTo().set( viewPost.self() );
-
-            self().lastPost().set( post );
-            Numbers.add( self().postCount(), 1 );
-
-            return post;
-        }
-    }
-
-    protected class PostView
-        extends Role<Post>
-    {
-    }
-
-    protected class Poster
-        extends Role<User>
-    {
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewTopic.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewTopic.java
deleted file mode 100644
index 4dd33db..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewTopic.java
+++ /dev/null
@@ -1,49 +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.qi4j.samples.forum.context.view;
-
-import org.qi4j.library.rest.server.api.ResourceIndex;
-import org.qi4j.library.rest.server.api.dci.Role;
-import org.qi4j.samples.forum.data.entity.Topic;
-
-/**
- * TODO
- */
-public class ViewTopic
-    implements ResourceIndex<Topic>
-{
-    private TopicView topicView;
-
-    public ViewTopic bind( Topic topic )
-    {
-        topicView = (TopicView) topic;
-        return this;
-    }
-
-    @Override
-    public Topic index()
-    {
-        return topicView.self();
-    }
-
-    protected class TopicView
-        extends Role<Topic>
-    {
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/data/Administrators.java b/samples/forum/src/main/java/org/qi4j/samples/forum/data/Administrators.java
deleted file mode 100644
index 513c6dd..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/data/Administrators.java
+++ /dev/null
@@ -1,30 +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.qi4j.samples.forum.data;
-
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.samples.forum.data.entity.User;
-
-/**
- * TODO
- */
-public interface Administrators
-{
-    ManyAssociation<User> administrators();
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/data/Moderators.java b/samples/forum/src/main/java/org/qi4j/samples/forum/data/Moderators.java
deleted file mode 100644
index 4203d1e..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/data/Moderators.java
+++ /dev/null
@@ -1,30 +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.qi4j.samples.forum.data;
-
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.samples.forum.data.entity.User;
-
-/**
- * TODO
- */
-public interface Moderators
-{
-    ManyAssociation<User> moderators();
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Board.java b/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Board.java
deleted file mode 100644
index 3b8e8be..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Board.java
+++ /dev/null
@@ -1,49 +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.qi4j.samples.forum.data.entity;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.Aggregated;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.samples.forum.data.Moderators;
-
-/**
- * TODO
- */
-public interface Board
-    extends Moderators, EntityComposite
-{
-    Property<String> name();
-
-    @Aggregated
-    ManyAssociation<Topic> topics();
-
-    @UseDefaults
-    Property<Integer> postCount();
-
-    @UseDefaults
-    Property<Integer> topicCount();
-
-    @Optional
-    Association<Post> lastPost();
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Forum.java b/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Forum.java
deleted file mode 100644
index 93f923e..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Forum.java
+++ /dev/null
@@ -1,42 +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.qi4j.samples.forum.data.entity;
-
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.entity.Aggregated;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.samples.forum.data.Administrators;
-import org.qi4j.samples.forum.data.Moderators;
-
-/**
- * TODO
- */
-public interface Forum
-    extends Moderators, Administrators, EntityComposite
-{
-    public Property<String> name();
-
-    @Aggregated
-    ManyAssociation<Board> boards();
-
-    Property<Integer> topicCount();
-
-    Property<Integer> postCount();
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Forums.java b/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Forums.java
deleted file mode 100644
index 512a41f..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Forums.java
+++ /dev/null
@@ -1,54 +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.qi4j.samples.forum.data.entity;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.structure.Module;
-import org.qi4j.samples.forum.data.Administrators;
-
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-/**
- * TODO
- */
-@Mixins( Forums.Mixin.class )
-public interface Forums
-    extends Administrators, EntityComposite
-{
-    String FORUMS_ID = "forums";
-
-    public Query<Forum> forums();
-
-    abstract class Mixin
-        implements Forums
-    {
-        @Structure
-        Module module;
-
-        public Query<Forum> forums()
-        {
-            return module.currentUnitOfWork()
-                .newQuery( module.newQueryBuilder( Forum.class ) )
-                .orderBy( templateFor( Forum.class ).name() );
-        }
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Post.java b/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Post.java
deleted file mode 100644
index db780d7..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Post.java
+++ /dev/null
@@ -1,53 +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.qi4j.samples.forum.data.entity;
-
-import java.util.Date;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-
-/**
- * TODO
- */
-public interface Post
-    extends EntityComposite
-{
-    enum Status
-    {
-        POSTED,
-        MODERATION,
-        DELETED,
-        SPAM
-    }
-
-    @Optional
-    Association<Post> replyTo();
-
-    Property<String> message();
-
-    Association<User> poster();
-
-    Property<Status> status();
-
-    Property<User> createdBy();
-
-    Property<Date> createdOn();
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Topic.java b/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Topic.java
deleted file mode 100644
index 3923d61..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Topic.java
+++ /dev/null
@@ -1,51 +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.qi4j.samples.forum.data.entity;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.entity.Aggregated;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-
-/**
- * TODO
- */
-public interface Topic
-    extends EntityComposite
-{
-    enum Status
-    {
-        POSTED,
-        MODERATION,
-        DELETED,
-        SPAM
-    }
-
-    Property<String> subject();
-
-    Property<Status> status();
-
-    @Aggregated
-    ManyAssociation<Post> posts();
-
-    Association<Post> lastPost();
-
-    Property<Integer> postCount();
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/User.java b/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/User.java
deleted file mode 100644
index a0a7601..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/User.java
+++ /dev/null
@@ -1,81 +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.qi4j.samples.forum.data.entity;
-
-import java.io.UnsupportedEncodingException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Immutable;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.util.Base64Encoder;
-
-/**
- * TODO
- */
-@Mixins( User.Mixin.class )
-public interface User
-    extends EntityComposite
-{
-    @Immutable
-    public Property<String> name();
-
-    public Property<String> realName();
-
-    public Property<String> email();
-
-    public Property<String> password();
-
-    public String hashPassword( String password );
-
-    public boolean isCorrectPassword( String password );
-
-    abstract class Mixin
-        implements User
-    {
-        @Override
-        public String hashPassword( String password )
-        {
-            try
-            {
-                MessageDigest md = MessageDigest.getInstance( "SHA" );
-                md.update( password.getBytes( "UTF-8" ) );
-                byte raw[] = md.digest();
-
-                String hash = new String( Base64Encoder.encode( raw, false ) );
-                return hash;
-            }
-            catch( NoSuchAlgorithmException e )
-            {
-                throw new IllegalStateException( "No SHA algorithm found", e );
-            }
-            catch( UnsupportedEncodingException e )
-            {
-                throw new IllegalStateException( e.getMessage(), e );
-            }
-        }
-
-        @Override
-        public boolean isCorrectPassword( String password )
-        {
-            return password().get().equals( hashPassword( password ) );
-        }
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Users.java b/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Users.java
deleted file mode 100644
index 8b591c4..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/data/entity/Users.java
+++ /dev/null
@@ -1,68 +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.qi4j.samples.forum.data.entity;
-
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.structure.Module;
-import org.qi4j.samples.forum.context.Events;
-import org.qi4j.samples.forum.context.signup.Registration;
-
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-/**
- * TODO
- */
-@Mixins( Users.Mixin.class )
-public interface Users
-    extends EntityComposite, Events
-{
-    String USERS_ID = "users";
-
-    public Query<User> users();
-
-    abstract class Mixin
-        implements Users
-    {
-        @Structure
-        Module module;
-
-        public Query<User> users()
-        {
-            return module.currentUnitOfWork()
-                .newQuery( module.newQueryBuilder( User.class ) )
-                .orderBy( templateFor( User.class ).realName() );
-        }
-
-        @Override
-        public void signedup( Registration registration )
-        {
-            EntityBuilder<User> builder = module.currentUnitOfWork().newEntityBuilder( User.class );
-            builder.instance().name().set( registration.name().get() );
-            builder.instance().realName().set( registration.realName().get() );
-            builder.instance().email().set( registration.email().get() );
-            builder.instance().password().set( builder.instance().hashPassword( registration.password().get() ) );
-
-            builder.newInstance();
-        }
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/domainevent/DomainCommandResult.java b/samples/forum/src/main/java/org/qi4j/samples/forum/domainevent/DomainCommandResult.java
deleted file mode 100644
index 8a8f2cd..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/domainevent/DomainCommandResult.java
+++ /dev/null
@@ -1,35 +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.qi4j.samples.forum.domainevent;
-
-import org.qi4j.library.rest.server.spi.CommandResult;
-import org.restlet.Request;
-
-/**
- * TODO
- */
-public class DomainCommandResult
-    implements CommandResult
-{
-    @Override
-    public Object getResult()
-    {
-        return Request.getCurrent().getAttributes().get( "event" );
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/domainevent/DomainEvent.java b/samples/forum/src/main/java/org/qi4j/samples/forum/domainevent/DomainEvent.java
deleted file mode 100644
index 7ba4e9f..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/domainevent/DomainEvent.java
+++ /dev/null
@@ -1,112 +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.qi4j.samples.forum.domainevent;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.reflect.Method;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.concern.GenericConcern;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCallback;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.functional.Function;
-import org.qi4j.functional.Iterables;
-import org.qi4j.library.rest.server.api.ObjectSelection;
-import org.restlet.Request;
-
-/**
- * TODO
- */
-@Concerns( DomainEvent.DomainEventConcern.class )
-@Retention( RetentionPolicy.RUNTIME )
-public @interface DomainEvent
-{
-    class DomainEventConcern
-        extends GenericConcern
-    {
-        @Structure
-        Module module;
-
-        @Structure
-        Application application;
-
-        @Override
-        public Object invoke( Object proxy, Method method, Object[] args )
-            throws Throwable
-        {
-            Object result = next.invoke( proxy, method, args );
-
-            UnitOfWork unitOfWork = module.currentUnitOfWork();
-
-            ValueBuilder<DomainEventValue> builder = module.newValueBuilder( DomainEventValue.class );
-            DomainEventValue prototype = builder.prototype();
-            prototype.version().set( application.version() );
-            prototype.timestamp().set( unitOfWork.currentTime() );
-            prototype.context().set( proxy.getClass().getSuperclass().getName().split( "\\$" )[ 0 ] );
-            prototype.name().set( method.getName() );
-
-            int idx = 0;
-            for( Object arg : args )
-            {
-                idx++;
-                String name = "param" + idx;
-                ValueBuilder<ParameterValue> parameterBuilder = module.newValueBuilder( ParameterValue.class );
-                parameterBuilder.prototype().name().set( name );
-                parameterBuilder.prototype().value().set( arg );
-                prototype.parameters().get().add( parameterBuilder.newInstance() );
-            }
-
-            Iterables.addAll( prototype.selection().get(), Iterables.map( new Function<Object, String>()
-            {
-                @Override
-                public String map( Object o )
-                {
-                    return o.toString();
-                }
-            }, ObjectSelection.current().selection() ) );
-
-            final DomainEventValue domainEvent = builder.newInstance();
-
-            unitOfWork.addUnitOfWorkCallback( new UnitOfWorkCallback()
-            {
-                @Override
-                public void beforeCompletion()
-                    throws UnitOfWorkCompletionException
-                {
-                }
-
-                @Override
-                public void afterCompletion( UnitOfWorkStatus status )
-                {
-                    if( status.equals( UnitOfWorkStatus.COMPLETED ) )
-                    {
-                        Request.getCurrent().getAttributes().put( "event", domainEvent );
-                    }
-                }
-            } );
-
-            return result;
-        }
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/domainevent/DomainEventValue.java b/samples/forum/src/main/java/org/qi4j/samples/forum/domainevent/DomainEventValue.java
deleted file mode 100644
index 9ba22d5..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/domainevent/DomainEventValue.java
+++ /dev/null
@@ -1,51 +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.qi4j.samples.forum.domainevent;
-
-import java.util.List;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * TODO
- */
-public interface DomainEventValue
-    extends ValueComposite
-{
-    // Version of the application that created these events
-    Property<String> version();
-
-    // When the event occurred
-    Property<Long> timestamp();
-
-    // Selected objects
-    @UseDefaults
-    Property<List<String>> selection();
-
-    // Type of the entity being invoked
-    Property<String> context();
-
-    // Name of method/event
-    Property<String> name();
-
-    // Method parameters as JSON
-    @UseDefaults
-    Property<List<ParameterValue>> parameters();
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/domainevent/ParameterValue.java b/samples/forum/src/main/java/org/qi4j/samples/forum/domainevent/ParameterValue.java
deleted file mode 100644
index 1f32b89..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/domainevent/ParameterValue.java
+++ /dev/null
@@ -1,33 +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.qi4j.samples.forum.domainevent;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-/**
- * TODO
- */
-public interface ParameterValue
-    extends ValueComposite
-{
-    Property<String> name();
-
-    Property<Object> value();
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/ForumRestlet.java b/samples/forum/src/main/java/org/qi4j/samples/forum/rest/ForumRestlet.java
deleted file mode 100644
index e573244..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/ForumRestlet.java
+++ /dev/null
@@ -1,38 +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.qi4j.samples.forum.rest;
-
-import org.qi4j.library.rest.server.api.ContextRestlet;
-import org.qi4j.samples.forum.rest.resource.RootResource;
-import org.restlet.Request;
-import org.restlet.Response;
-import org.restlet.Uniform;
-
-/**
- * TODO
- */
-public class ForumRestlet
-    extends ContextRestlet
-{
-    @Override
-    protected Uniform createRoot( Request request, Response response )
-    {
-        return module.newObject( RootResource.class, this );
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/RootResource.java b/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/RootResource.java
deleted file mode 100644
index 2d890b0..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/RootResource.java
+++ /dev/null
@@ -1,87 +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.qi4j.samples.forum.rest.resource;
-
-import java.util.Collections;
-import org.qi4j.api.query.QueryExpressions;
-import org.qi4j.library.rest.server.api.ContextResource;
-import org.qi4j.library.rest.server.api.SubResource;
-import org.qi4j.library.rest.server.api.constraint.Requires;
-import org.qi4j.samples.forum.data.entity.User;
-import org.qi4j.samples.forum.data.entity.Users;
-import org.qi4j.samples.forum.rest.resource.administration.AdministrationResource;
-import org.qi4j.samples.forum.rest.resource.forum.ForumResource;
-import org.qi4j.samples.forum.rest.resource.signup.SignupResource;
-import org.restlet.Request;
-import org.restlet.Response;
-import org.restlet.data.ChallengeRequest;
-import org.restlet.data.ChallengeResponse;
-import org.restlet.data.ChallengeScheme;
-import org.restlet.data.Status;
-import org.restlet.resource.ResourceException;
-
-import static org.qi4j.library.rest.server.api.ObjectSelection.current;
-
-/**
- * TODO
- */
-public class RootResource
-    extends ContextResource
-{
-    @SubResource
-    public void signup()
-    {
-        select( Users.class, Users.USERS_ID );
-        subResource( SignupResource.class );
-    }
-
-    @SubResource
-    public void administration()
-    {
-        ChallengeResponse challenge = Request.getCurrent().getChallengeResponse();
-        if( challenge == null )
-        {
-            Response.getCurrent()
-                .setChallengeRequests( Collections.singletonList( new ChallengeRequest( ChallengeScheme.HTTP_BASIC, "Forum" ) ) );
-            throw new ResourceException( Status.CLIENT_ERROR_UNAUTHORIZED );
-        }
-
-        User user = module.currentUnitOfWork().newQuery( module.newQueryBuilder( User.class ).where( QueryExpressions
-                                                                                                         .eq( QueryExpressions
-                                                                                                                  .templateFor( User.class )
-                                                                                                                  .name(), challenge
-                                                                                                             .getIdentifier() ) ) )
-            .find();
-        if( user == null || !user.isCorrectPassword( new String( challenge.getSecret() ) ) )
-        {
-            throw new ResourceException( Status.CLIENT_ERROR_UNAUTHORIZED );
-        }
-
-        current().select( user );
-
-        subResource( AdministrationResource.class );
-    }
-
-    @SubResource
-    @Requires( User.class )
-    public void forum()
-    {
-        subResource( ForumResource.class );
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/administration/AdministrationResource.java b/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/administration/AdministrationResource.java
deleted file mode 100644
index 53c94cd..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/administration/AdministrationResource.java
+++ /dev/null
@@ -1,45 +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.qi4j.samples.forum.rest.resource.administration;
-
-import org.qi4j.library.rest.server.api.ContextResource;
-import org.qi4j.library.rest.server.api.SubResource;
-import org.qi4j.samples.forum.data.entity.Forums;
-import org.qi4j.samples.forum.data.entity.Users;
-
-/**
- * TODO
- */
-public class AdministrationResource
-    extends ContextResource
-{
-    @SubResource
-    public void forums()
-    {
-        select( Forums.class, Forums.FORUMS_ID );
-        subResource( ForumsResource.class );
-    }
-
-    @SubResource
-    public void users()
-    {
-        select( Users.class, Users.USERS_ID );
-        subResource( UsersResource.class );
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/administration/ForumsResource.java b/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/administration/ForumsResource.java
deleted file mode 100644
index c2cecc8..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/administration/ForumsResource.java
+++ /dev/null
@@ -1,29 +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.qi4j.samples.forum.rest.resource.administration;
-
-import org.qi4j.library.rest.server.api.ContextResource;
-
-/**
- * TODO
- */
-public class ForumsResource
-    extends ContextResource
-{
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/administration/UsersResource.java b/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/administration/UsersResource.java
deleted file mode 100644
index 3aa09fb..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/administration/UsersResource.java
+++ /dev/null
@@ -1,40 +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.qi4j.samples.forum.rest.resource.administration;
-
-import org.qi4j.api.query.Query;
-import org.qi4j.library.rest.server.api.ContextResource;
-import org.qi4j.library.rest.server.api.ObjectSelection;
-import org.qi4j.library.rest.server.api.ResourceIndex;
-import org.qi4j.samples.forum.data.entity.User;
-import org.qi4j.samples.forum.data.entity.Users;
-
-/**
- * TODO
- */
-public class UsersResource
-    extends ContextResource
-    implements ResourceIndex<Query<User>>
-{
-    @Override
-    public Query<User> index()
-    {
-        return ObjectSelection.current().get( Users.class ).users();
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/forum/BoardResource.java b/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/forum/BoardResource.java
deleted file mode 100644
index f408927..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/forum/BoardResource.java
+++ /dev/null
@@ -1,41 +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.qi4j.samples.forum.rest.resource.forum;
-
-import org.qi4j.library.rest.server.api.ContextResource;
-import org.qi4j.library.rest.server.api.ObjectSelection;
-import org.qi4j.library.rest.server.api.SubResources;
-import org.qi4j.samples.forum.data.entity.Forum;
-import org.restlet.resource.ResourceException;
-
-/**
- * TODO
- */
-public class BoardResource
-    extends ContextResource
-    implements SubResources
-{
-    @Override
-    public void resource( String segment )
-        throws ResourceException
-    {
-        selectFromManyAssociation( ObjectSelection.current().get( Forum.class ).boards(), segment );
-        subResource( BoardResource.class );
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/forum/ForumResource.java b/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/forum/ForumResource.java
deleted file mode 100644
index 36864d7..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/forum/ForumResource.java
+++ /dev/null
@@ -1,41 +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.qi4j.samples.forum.rest.resource.forum;
-
-import org.qi4j.library.rest.server.api.ContextResource;
-import org.qi4j.library.rest.server.api.ObjectSelection;
-import org.qi4j.library.rest.server.api.SubResources;
-import org.qi4j.samples.forum.data.entity.Forum;
-import org.restlet.resource.ResourceException;
-
-/**
- * TODO
- */
-public class ForumResource
-    extends ContextResource
-    implements SubResources
-{
-    @Override
-    public void resource( String segment )
-        throws ResourceException
-    {
-        selectFromManyAssociation( ObjectSelection.current().get( Forum.class ).boards(), segment );
-        subResource( BoardResource.class );
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/forum/ForumsResource.java b/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/forum/ForumsResource.java
deleted file mode 100644
index c48a28a..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/forum/ForumsResource.java
+++ /dev/null
@@ -1,40 +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.qi4j.samples.forum.rest.resource.forum;
-
-import org.qi4j.library.rest.server.api.ContextResource;
-import org.qi4j.library.rest.server.api.SubResources;
-import org.qi4j.samples.forum.data.entity.Forum;
-import org.restlet.resource.ResourceException;
-
-/**
- * TODO
- */
-public class ForumsResource
-    extends ContextResource
-    implements SubResources
-{
-    @Override
-    public void resource( String segment )
-        throws ResourceException
-    {
-        select( Forum.class, segment );
-        subResource( ForumResource.class );
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/login/LoginResource.java b/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/login/LoginResource.java
deleted file mode 100644
index 76c4457..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/login/LoginResource.java
+++ /dev/null
@@ -1,41 +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.qi4j.samples.forum.rest.resource.login;
-
-import org.qi4j.library.rest.server.api.ContextResource;
-import org.qi4j.samples.forum.context.login.Login;
-import org.restlet.Response;
-import org.restlet.representation.EmptyRepresentation;
-import org.restlet.representation.Representation;
-
-/**
- * TODO
- */
-public class LoginResource
-    extends ContextResource
-{
-    public Representation login( String name, String password )
-    {
-        context( Login.class ).login( name, password );
-
-        EmptyRepresentation rep = new EmptyRepresentation();
-        Response.getCurrent().getCookieSettings().add( "user", name );
-        return rep;
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/signup/SignupResource.java b/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/signup/SignupResource.java
deleted file mode 100644
index 69a341a..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/rest/resource/signup/SignupResource.java
+++ /dev/null
@@ -1,45 +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.qi4j.samples.forum.rest.resource.signup;
-
-import org.qi4j.library.rest.server.api.ContextResource;
-import org.qi4j.samples.forum.context.signup.Registration;
-import org.qi4j.samples.forum.context.signup.Signup;
-import org.restlet.data.Form;
-
-/**
- * TODO
- */
-public class SignupResource
-    extends ContextResource
-{
-    public void signup( Registration registration )
-    {
-        context( Signup.class ).signup( registration );
-    }
-
-    public Form signup()
-    {
-        Form form = new Form();
-        form.set( "name", "Rickard" );
-        form.set( "realName", "Rickard Öberg" );
-        form.set( "password", "rickard" );
-        return form;
-    }
-}
diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/service/BootstrapData.java b/samples/forum/src/main/java/org/qi4j/samples/forum/service/BootstrapData.java
deleted file mode 100644
index 6800e6b..0000000
--- a/samples/forum/src/main/java/org/qi4j/samples/forum/service/BootstrapData.java
+++ /dev/null
@@ -1,101 +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.qi4j.samples.forum.service;
-
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.InitializationException;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.NoSuchEntityException;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.samples.forum.data.entity.Forums;
-import org.qi4j.samples.forum.data.entity.Users;
-
-/**
- * TODO
- */
-@Mixins( BootstrapData.Mixin.class )
-@Activators( BootstrapData.Activator.class )
-public interface BootstrapData
-    extends ServiceComposite
-{
-    
-    void insertInitialData()
-            throws Exception;
-
-    class Activator
-            extends ActivatorAdapter<ServiceReference<BootstrapData>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<BootstrapData> activated )
-                throws Exception
-        {
-            activated.get().insertInitialData();
-        }
-
-    }
-    
-    abstract class Mixin
-        implements BootstrapData
-    {
-        @Structure
-        Module module;
-
-        @Override
-        public void insertInitialData()
-            throws Exception
-        {
-            UnitOfWork unitOfWork = module.newUnitOfWork();
-
-            try
-            {
-                unitOfWork.get( Forums.class, Forums.FORUMS_ID );
-            }
-            catch( NoSuchEntityException e )
-            {
-                unitOfWork.newEntity( Forums.class, Forums.FORUMS_ID );
-            }
-
-            try
-            {
-                unitOfWork.get( Users.class, Users.USERS_ID );
-            }
-            catch( NoSuchEntityException e )
-            {
-                unitOfWork.newEntity( Users.class, Users.USERS_ID );
-            }
-
-            try
-            {
-                unitOfWork.complete();
-            }
-            catch( UnitOfWorkCompletionException e )
-            {
-                throw new InitializationException( e );
-            }
-        }
-
-    }
-}
diff --git a/samples/forum/src/main/webapp/WEB-INF/web.xml b/samples/forum/src/main/webapp/WEB-INF/web.xml
index a8f6a82..4594096 100644
--- a/samples/forum/src/main/webapp/WEB-INF/web.xml
+++ b/samples/forum/src/main/webapp/WEB-INF/web.xml
@@ -1,16 +1,19 @@
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
diff --git a/samples/forum/src/test/java/org/apache/polygene/sample/forum/web/Main.java b/samples/forum/src/test/java/org/apache/polygene/sample/forum/web/Main.java
new file mode 100644
index 0000000..102da80
--- /dev/null
+++ b/samples/forum/src/test/java/org/apache/polygene/sample/forum/web/Main.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.sample.forum.web;
+
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.library.rest.server.api.ContextRestlet;
+import org.apache.polygene.sample.forum.assembler.ForumAssembler;
+import org.restlet.Server;
+import org.restlet.data.ChallengeScheme;
+import org.restlet.data.Protocol;
+import org.restlet.security.ChallengeAuthenticator;
+import org.restlet.security.MapVerifier;
+import org.restlet.service.MetadataService;
+
+/**
+ * TODO
+ */
+public class Main
+{
+    public static void main( String[] args )
+        throws Exception
+    {
+        Energy4Java is = new Energy4Java(  );
+
+        Server server = new Server( Protocol.HTTP, 8888 );
+
+        Application app = is.newApplication( new ForumAssembler(), new MetadataService() );
+
+        app.activate();
+
+        ContextRestlet restlet = app.findModule( "REST", "Restlet" ).newObject( ContextRestlet.class, new org.restlet.Context() );
+
+        ChallengeAuthenticator guard = new ChallengeAuthenticator(null, ChallengeScheme.HTTP_BASIC, "testRealm");
+        MapVerifier mapVerifier = new MapVerifier();
+        mapVerifier.getLocalSecrets().put("rickard", "secret".toCharArray());
+        guard.setVerifier(mapVerifier);
+
+        guard.setNext(restlet);
+
+        server.setNext( restlet );
+        server.start();
+    }
+}
diff --git a/samples/forum/src/test/java/org/qi4j/samples/forum/web/Main.java b/samples/forum/src/test/java/org/qi4j/samples/forum/web/Main.java
deleted file mode 100644
index 298e66e..0000000
--- a/samples/forum/src/test/java/org/qi4j/samples/forum/web/Main.java
+++ /dev/null
@@ -1,60 +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.qi4j.samples.forum.web;
-
-import org.qi4j.api.structure.Application;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.library.rest.server.api.ContextRestlet;
-import org.qi4j.samples.forum.assembler.ForumAssembler;
-import org.restlet.Server;
-import org.restlet.data.ChallengeScheme;
-import org.restlet.data.Protocol;
-import org.restlet.security.ChallengeAuthenticator;
-import org.restlet.security.MapVerifier;
-import org.restlet.service.MetadataService;
-
-/**
- * TODO
- */
-public class Main
-{
-    public static void main( String[] args )
-        throws Exception
-    {
-        Energy4Java is = new Energy4Java(  );
-
-        Server server = new Server( Protocol.HTTP, 8888 );
-
-        Application app = is.newApplication( new ForumAssembler(), new MetadataService() );
-
-        app.activate();
-
-        ContextRestlet restlet = app.findModule( "REST", "Restlet" ).newObject( ContextRestlet.class, new org.restlet.Context() );
-
-        ChallengeAuthenticator guard = new ChallengeAuthenticator(null, ChallengeScheme.HTTP_BASIC, "testRealm");
-        MapVerifier mapVerifier = new MapVerifier();
-        mapVerifier.getLocalSecrets().put("rickard", "secret".toCharArray());
-        guard.setVerifier(mapVerifier);
-
-        guard.setNext(restlet);
-
-        server.setNext( restlet );
-        server.start();
-    }
-}
diff --git a/samples/rental/build.gradle b/samples/rental/build.gradle
index 6044b2b..427153e 100644
--- a/samples/rental/build.gradle
+++ b/samples/rental/build.gradle
@@ -1,41 +1,45 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
+buildscript {
+  repositories { maven { url "https://plugins.gradle.org/m2/" } }
+  dependencies { classpath "gradle.plugin.org.akhikhl.gretty:gretty:1.4.2" }
+}
+
+apply plugin: 'polygene-sample'
+apply plugin: 'war'
+apply plugin: 'org.akhikhl.gretty'
+
 description = "Sample of implementation of a Car Rental application."
 
-apply plugin: 'war'
-apply plugin: 'jetty'
-
 // To run in an embedded Jetty use:
-//      ../../gradlew jettyRun
+//      ../../gradlew appRunWar
 // And then go to:
-//      http://localhost:8080/org.qi4j.sample.rental/rental/main
+//      http://localhost:8080/rental/rental/main
 
-jar { manifest { name = "Apache Zest™ Sample - Car Rental" }}
+jar { manifest { name = "Apache Polygene™ Sample - Car Rental" } }
 
 dependencies {
-
-  compile project( ":org.qi4j.core:org.qi4j.core.bootstrap" )
-  compile project( ":org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson" )
+  implementation polygene.core.bootstrap
 
   providedCompile libraries.servlet_api
 
-  runtime project( ":org.qi4j.core:org.qi4j.core.runtime" )
-
+  runtimeOnly polygene.core.runtime
 }
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/Address.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/Address.java
new file mode 100644
index 0000000..ffbc7e0
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/Address.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.sample.rental.domain;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+public interface Address
+    extends ValueComposite
+{
+    Property<String> line1();
+
+    Property<String> line2();
+
+    Property<String> zipCode();
+
+    Property<String> city();
+
+    Property<String> country();
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/Booking.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/Booking.java
new file mode 100644
index 0000000..a04fea6
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/Booking.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.sample.rental.domain;
+
+import java.time.Instant;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+
+public interface Booking
+    extends EntityComposite
+{
+    Property<String> reference();
+
+    Association<Customer> customer();
+
+    Association<Car> car();
+
+    Property<Period> period();
+
+    @Optional
+        // if not set, the pickup has not occurred yet.
+    Property<Instant> pickedupTime();
+
+    @Optional
+        // if not set, the return has not occurred yet.
+    Property<Instant> returnedTime();
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/Car.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/Car.java
new file mode 100644
index 0000000..e9ed6e2
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/Car.java
@@ -0,0 +1,65 @@
+/*
+ *  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.polygene.sample.rental.domain;
+
+import java.time.LocalDate;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.Query;
+
+@Mixins( Car.CarMixin.class )
+public interface Car
+    extends EntityComposite
+{
+    Property<String> licensePlate();
+
+    Property<String> model();
+
+    Association<CarCategory> category();
+
+    @Optional
+    Property<LocalDate> purchasedDate();
+
+    @Optional
+    Property<LocalDate> soldDate();
+
+    Booking currentBooking();
+
+    Query<Booking> pastBookings();
+
+    abstract class CarMixin
+        implements Car
+    {
+
+        public Booking currentBooking()
+        {
+            return null;  //To change body of implemented methods use File | Settings | File Templates.
+        }
+
+        public Query<Booking> pastBookings()
+        {
+            return null;  //To change body of implemented methods use File | Settings | File Templates.
+        }
+    }
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/CarCategory.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/CarCategory.java
new file mode 100644
index 0000000..cc3b274
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/CarCategory.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.sample.rental.domain;
+
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+
+public interface CarCategory
+    extends EntityComposite
+{
+    Property<String> name();
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/Customer.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/Customer.java
new file mode 100644
index 0000000..5072c95
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/Customer.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.sample.rental.domain;
+
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.Query;
+
+@Mixins( Customer.CustomerMixin.class )
+public interface Customer
+    extends EntityComposite
+{
+    Property<String> name();
+
+    Property<Address> address();
+
+    Query<Booking> currentBookings();
+
+    Query<Booking> pastBookings();
+
+    abstract class CustomerMixin
+        implements Customer
+    {
+        public Query<Booking> currentBookings()
+        {
+            return null;  //To change body of implemented methods use File | Settings | File Templates.
+        }
+
+        public Query<Booking> pastBookings()
+        {
+            return null;  //To change body of implemented methods use File | Settings | File Templates.
+        }
+    }
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/Period.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/Period.java
new file mode 100644
index 0000000..cadee54
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/Period.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.sample.rental.domain;
+
+import java.time.LocalDate;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+public interface Period
+    extends ValueComposite
+{
+    Property<LocalDate> startOfPeriod();
+
+    Property<LocalDate> endOfPeriod();
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/RentalShop.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/RentalShop.java
new file mode 100644
index 0000000..b3bae5e
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/RentalShop.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.polygene.sample.rental.domain;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+@Mixins( RentalShop.RentalShopMixin.class )
+public interface RentalShop
+    extends EntityComposite
+{
+    Customer createCustomer( String name, String address1, String address2, String zip, String city, String country );
+
+    Car findAvailableCarByModel( String model );
+
+    Car findAvailableCarByCategory( CarCategory category );
+
+    List<CarCategory> findAllCarCategories();
+
+    List<Booking> findAllBookings();
+
+    Set<String> findAllCarModels();
+
+    Booking book( Customer customer, Car car, Period plannedPeriod );
+
+    void pickup( Booking booking, Instant time );
+
+    void returned( Booking booking, Instant time );
+
+    void boughtCar( Car car, LocalDate purchasedate );
+
+    void soldCar( Car car, LocalDate soldDate );
+
+    Car createCar( String category, String modelName, String licensePlate );
+
+    List<CarCategory> carCategories();
+
+    interface State
+    {
+        ManyAssociation<Car> carsOwned();
+
+        ManyAssociation<Car> carsAvailable();
+
+        ManyAssociation<Booking> bookings();
+
+        ManyAssociation<CarCategory> carCategories();
+    }
+
+    abstract class RentalShopMixin
+        implements RentalShop
+    {
+        @Structure
+        ValueBuilderFactory vbf;
+        @Structure
+        QueryBuilderFactory qbf;
+        @Structure
+        UnitOfWorkFactory uowf;
+        @This
+        private State state;
+
+        public Customer createCustomer( String name,
+                                        String address1,
+                                        String address2,
+                                        String zip,
+                                        String city,
+                                        String country
+        )
+        {
+            ValueBuilder<Address> addrBuilder = vbf.newValueBuilder( Address.class );
+            Address protoAddress = addrBuilder.prototype();
+            protoAddress.line1().set( address1 );
+            protoAddress.line2().set( address2 );
+            protoAddress.zipCode().set( zip );
+            protoAddress.city().set( city );
+            protoAddress.country().set( country );
+            Address address = addrBuilder.newInstance();
+            EntityBuilder<Customer> builder = uowf.currentUnitOfWork().newEntityBuilder( Customer.class );
+            builder.instance().name().set( name );
+            builder.instance().address().set( address );
+            return builder.newInstance();
+        }
+
+        public Car findAvailableCarByModel( String model )
+        {
+            for( Car car : state.carsAvailable().toList() )
+            {
+                if( car.model().get().equals( model ) )
+                {
+                    return car;
+                }
+            }
+            return null;
+        }
+
+        public Car findAvailableCarByCategory( CarCategory category )
+        {
+            for( Car car : state.carsAvailable().toList() )
+            {
+                if( car.category().get().equals( category ) )
+                {
+                    return car;
+                }
+            }
+            return null;
+        }
+
+        public List<CarCategory> findAllCarCategories()
+        {
+            return state.carCategories().toList();
+        }
+
+        public Set<String> findAllCarModels()
+        {
+            return state.carsOwned()
+                .toList()
+                .stream()
+                .map( car -> car.model().get() )
+                .collect( Collectors.toSet() );
+        }
+
+        public Booking book( Customer customer, Car car, Period plannedPeriod )
+        {
+            EntityBuilder<Booking> builder = uowf.currentUnitOfWork().newEntityBuilder( Booking.class );
+            Booking instance = builder.instance();
+            String refNo;
+            try
+            {
+                MessageDigest md;
+                md = MessageDigest.getInstance( "MD5" );
+                md.update( instance.identity().get().toBytes() );
+                StringBuilder buf = new StringBuilder();
+                byte[] data = md.digest();
+                for( int i = 0; i < 4; i++ )
+                {
+                    String hex = Integer.toHexString( Math.abs( data[ i ] ) );
+                    if( hex.length() == 1 )
+                    {
+                        buf.append( "0" );
+                    }
+                    buf.append( hex );
+                    if( i == 1 )
+                    {
+                        buf.append( "-" );
+                    }
+                }
+                refNo = buf.toString().toUpperCase();
+            }
+            catch( NoSuchAlgorithmException e )
+            {
+                // Can not happen.
+                throw new RuntimeException( e );
+            }
+            instance.reference().set( refNo );
+            instance.car().set( car );
+            instance.customer().set( customer );
+            instance.period().set( plannedPeriod );
+            Booking booking = builder.newInstance();
+            state.bookings().add( booking );
+            return booking;
+        }
+
+        public void pickup( Booking booking, Instant time )
+        {
+            booking.pickedupTime().set( time );
+        }
+
+        public void returned( Booking booking, Instant time )
+        {
+            booking.returnedTime().set( time );
+        }
+
+        public void boughtCar( Car car, LocalDate purchaseDate )
+        {
+            state.carsOwned().add( car );
+            car.purchasedDate().set( purchaseDate );
+        }
+
+        public void soldCar( Car car, LocalDate soldDate )
+        {
+            state.carsOwned().remove( car );
+            car.soldDate().set( soldDate );
+        }
+
+        public List<Booking> findAllBookings()
+        {
+            ManyAssociation<Booking> manyAssociation = state.bookings();
+            return manyAssociation.toList();
+        }
+
+        public List<CarCategory> carCategories()
+        {
+            return state.carCategories().toList();
+        }
+
+        public Car createCar( String category, String modelName, String licensePlate )
+        {
+            CarCategory carCategory = findCarCategory( category );
+            EntityBuilder<Car> builder = uowf.currentUnitOfWork().newEntityBuilder( Car.class );
+            builder.instance().model().set( modelName );
+            builder.instance().category().set( carCategory );
+            builder.instance().licensePlate().set( licensePlate );
+            return builder.newInstance();
+        }
+
+        private CarCategory findCarCategory( String categoryName )
+        {
+            for( CarCategory carCategory : state.carCategories() )
+            {
+                if( carCategory.name().get().equals( categoryName ) )
+                {
+                    return carCategory;
+                }
+            }
+            EntityBuilder<CarCategory> categoryBuilder = uowf.currentUnitOfWork().newEntityBuilder( CarCategory.class );
+            categoryBuilder.instance().name().set( categoryName );
+            return categoryBuilder.newInstance();
+        }
+    }
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/dev/InitialData.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/dev/InitialData.java
new file mode 100644
index 0000000..3bb475c
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/domain/dev/InitialData.java
@@ -0,0 +1,214 @@
+/*
+ *  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.polygene.sample.rental.domain.dev;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.Random;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.sample.rental.domain.Car;
+import org.apache.polygene.sample.rental.domain.Customer;
+import org.apache.polygene.sample.rental.domain.Period;
+import org.apache.polygene.sample.rental.domain.RentalShop;
+import org.apache.polygene.sample.rental.web.DataInitializer;
+
+@Mixins( InitialData.Mixin.class )
+public interface InitialData
+    extends DataInitializer, TransientComposite
+{
+    abstract class Mixin
+        implements DataInitializer
+    {
+        private static final Random random = new Random();
+
+        @Structure
+        UnitOfWorkFactory uowf;
+
+        @Structure
+        ValueBuilderFactory vbf;
+
+        private ArrayList<Customer> customers = new ArrayList<>();
+        private ArrayList<Car> cars = new ArrayList<>();
+
+        public void initialize()
+            throws Exception
+        {
+            UnitOfWork uow = uowf.newUnitOfWork();
+            try
+            {
+                RentalShop shop = createShop( uow );
+                createCustomers( shop );
+                createCars( shop );
+                createBookings( shop );
+                uow.complete();
+            }
+            finally
+            {
+                uow.discard();
+            }
+        }
+
+        private void createBookings( RentalShop shop )
+        {
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
+        }
+
+        private Period createRandomPeriod()
+        {
+            LocalDate start = LocalDate.now().plusDays( random.nextInt( 5));
+            LocalDate end = start.plusDays( random.nextInt(30));
+
+            ValueBuilder<Period> builder = vbf.newValueBuilder( Period.class );
+            builder.prototype().startOfPeriod().set( start );
+            builder.prototype().endOfPeriod().set( end );
+            return builder.newInstance();
+        }
+
+        private Car findRandomCar()
+        {
+            int index = (int) Math.floor( cars.size() * Math.random() );
+            return cars.get( index );
+        }
+
+        private Customer findRandomCustomer()
+        {
+            int index = (int) Math.floor( customers.size() * Math.random() );
+            return customers.get( index );
+        }
+
+        private void createCars( RentalShop shop )
+        {
+            Car car;
+            car = shop.createCar( "SUV", "Volvo XC90", "WHO 7878" );
+            shop.boughtCar( car, randomPastDate() );
+            cars.add( car );
+            car = shop.createCar( "SUV", "BMW X5", "WIT 23" );
+            shop.boughtCar( car, randomPastDate() );
+            cars.add( car );
+            car = shop.createCar( "SUV", "Volvo XC90", "WHO 7879" );
+            shop.boughtCar( car, randomPastDate() );
+            cars.add( car );
+            car = shop.createCar( "SUV", "Volvo XC90", "WHO 7880" );
+            shop.boughtCar( car, randomPastDate() );
+            cars.add( car );
+            car = shop.createCar( "SUV", "BMW X5", "WIT 24" );
+            shop.boughtCar( car, randomPastDate() );
+            cars.add( car );
+            car = shop.createCar( "SUV", "BMW X5", "WIT 25" );
+            shop.boughtCar( car, randomPastDate() );
+            cars.add( car );
+            car = shop.createCar( "SUV", "BMW X5", "WIT 26" );
+            shop.boughtCar( car, randomPastDate() );
+            cars.add( car );
+            car = shop.createCar( "SUV", "BMW X5", "WIT 27" );
+            shop.boughtCar( car, randomPastDate() );
+            cars.add( car );
+            car = shop.createCar( "Compact", "Mini Cooper S", "WMY 40" );
+            shop.boughtCar( car, randomPastDate() );
+            cars.add( car );
+            car = shop.createCar( "Compact", "Mini Cooper S", "WMY 41" );
+            shop.boughtCar( car, randomPastDate() );
+            cars.add( car );
+            car = shop.createCar( "Compact", "Mini Cooper S", "WMY 42" );
+            shop.boughtCar( car, randomPastDate() );
+            cars.add( car );
+            car = shop.createCar( "Compact", "Mini Cooper S", "WMY 43" );
+            shop.boughtCar( car, randomPastDate() );
+            cars.add( car );
+            car = shop.createCar( "Compact", "Mini Cooper S", "WMY 44" );
+            shop.boughtCar( car, randomPastDate() );
+            cars.add( car );
+            car = shop.createCar( "Compact", "Mini Cooper S", "WMY 45" );
+            shop.boughtCar( car, randomPastDate() );
+            cars.add( car );
+            car = shop.createCar( "Sedan", "BMW 318i", "WRY 900" );
+            shop.boughtCar( car, randomPastDate() );
+            cars.add( car );
+            car = shop.createCar( "Sedan", "BMW 318i", "WRY 901" );
+            shop.boughtCar( car, randomPastDate() );
+            cars.add( car );
+            car = shop.createCar( "Sedan", "BMW 318i", "WRY 902" );
+            shop.boughtCar( car, randomPastDate() );
+            cars.add( car );
+        }
+
+        private LocalDate randomPastDate()
+        {
+            return LocalDate.now().minusDays( random.nextInt( 700 ) );
+        }
+
+        private RentalShop createShop( UnitOfWork uow )
+            throws UnitOfWorkCompletionException
+        {
+            return uow.newEntity( RentalShop.class, new StringIdentity( "SHOP" ) );
+        }
+
+        private void createCustomers( RentalShop shop )
+        {
+            customers.add( shop.createCustomer( "Niclas Hedhman", "344-28-2, Vista Damai", "Jalan Tun Razak", "50400", "Kuala Lumpur", "Malaysia" ) );
+            customers.add( shop.createCustomer( "Peter Neubauer", "Sovstaden 24", "", "21212", "Malm�", "Sweden" ) );
+            customers.add( shop.createCustomer( "Rickard �berg", "GpsFree 123", "Bukit Antarabangsa", "68000", "Ampang", "Malaysia" ) );
+            customers.add( shop.createCustomer( "Mickey Mouse", "Playhouse 1", "", "1234", "Disneyland", "USA" ) );
+            customers.add( shop.createCustomer( "Michael Hunger", "Jederstrasse 1", "", "78787", "Dresden", "Germany" ) );
+            customers.add( shop.createCustomer( "Emil Eifrem", "Freeze Street 12", "WhereWindBlows", "23456", "Malm�", "Sweden" ) );
+        }
+    }
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/BookingPage.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/BookingPage.java
new file mode 100644
index 0000000..6d007f2
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/BookingPage.java
@@ -0,0 +1,89 @@
+/*
+ *  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.polygene.sample.rental.web;
+
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.sample.rental.domain.Booking;
+import org.apache.polygene.sample.rental.domain.Car;
+import org.apache.polygene.sample.rental.domain.Customer;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+@Mixins( BookingPage.BodyContributorMixin.class )
+public interface BookingPage
+    extends Page
+{
+    Node car( QuikitContext context );
+
+    Node customer( QuikitContext context );
+
+    abstract class BodyContributorMixin
+        implements BookingPage
+    {
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        public Node car( QuikitContext context )
+        {
+            Document dom = context.dom();
+            Element result = dom.createElementNS( Page.XHTML, "div" );
+            String bookingId = context.path();
+            UnitOfWork uow = uowf.currentUnitOfWork();
+            Booking booking = uow.get( Booking.class, new StringIdentity( bookingId ) );
+            Car car = booking.car().get();
+            createChildNode( dom, result, car.model().get() );
+            createChildNode( dom, result, car.licensePlate().get() );
+            createChildNode( dom, result, car.category().get().name().get() );
+            return result;
+        }
+
+        private void createChildNode( Document dom, Element result, String content )
+        {
+            Element modelElement = dom.createElement( "div" );
+            result.appendChild( modelElement );
+            modelElement.setTextContent( content );
+        }
+
+        public Node customer( QuikitContext context )
+        {
+            Document dom = context.dom();
+            Element result = dom.createElementNS( Page.XHTML, "div" );
+            String bookingId = context.path();
+            UnitOfWork uow = uowf.currentUnitOfWork();
+            Booking booking = uow.get( Booking.class, new StringIdentity( bookingId ) );
+            Customer customer = booking.customer().get();
+            createChildNode( dom, result, customer.name().get() );
+            createChildNode( dom, result, customer.address().get().line1().get() );
+            createChildNode( dom, result, customer.address().get().line2().get() );
+            createChildNode( dom, result, customer.address().get().zipCode().get() + " " + customer.address()
+                .get()
+                .city()
+                .get() );
+            createChildNode( dom, result, customer.address().get().country().get() );
+            return result;
+        }
+    }
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/DataInitializer.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/DataInitializer.java
new file mode 100644
index 0000000..51a6e2d
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/DataInitializer.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.sample.rental.web;
+
+public interface DataInitializer
+{
+    void initialize()
+        throws Exception;
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/MainPage.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/MainPage.java
new file mode 100644
index 0000000..68d868a
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/MainPage.java
@@ -0,0 +1,111 @@
+/*
+ *  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.polygene.sample.rental.web;
+
+import java.text.MessageFormat;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.sample.rental.domain.Booking;
+import org.apache.polygene.sample.rental.domain.Period;
+import org.apache.polygene.sample.rental.domain.RentalShop;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+@Mixins( { MainPage.BodyContributorMixin.class } )
+public interface MainPage
+    extends Page
+{
+    Node[] bookings( QuikitContext context );
+
+    abstract class BodyContributorMixin
+        implements MainPage
+    {
+        private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm" );
+
+        @Service
+        BookingPage bookingPage;
+        @Service
+        UrlService urlService;
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        public Node[] bookings( QuikitContext context )
+        {
+            ArrayList<Node> nodes = new ArrayList<Node>();
+            Document dom = context.dom();
+            UnitOfWork uow = uowf.currentUnitOfWork();
+            RentalShop shop = uow.get( RentalShop.class, new StringIdentity( "SHOP" ) );
+            for( Booking booking : shop.findAllBookings() )
+            {
+                String plate = booking.car().get().licensePlate().get();
+
+                // TODO: Next version;
+//                Node node = create( dom, "<li><a href='{1}'>{2}</a>{3}</li>", createLink( booking ), plate, createPeriod( booking.period().get() ) );
+//                nodes.add( node );
+
+                Element listItem = createElement( dom, "li" );
+                Element bookingLink = (Element) listItem.appendChild( createElement( dom, "a" ) );
+                bookingLink.setAttribute( "href", createLink( booking ) );
+                bookingLink.setTextContent( plate );
+                listItem.appendChild( dom.createTextNode( createPeriod( booking.period().get() ) ) );
+                nodes.add( listItem );
+            }
+            Node[] bookingList = new Node[ nodes.size() ];
+            nodes.toArray( bookingList );
+            return bookingList;
+        }
+
+        private Node create( Document dom, String pattern, Object... args )
+        {
+            String result = MessageFormat.format( pattern, args );
+            // TODO: fix up ANTLR to parse XML and generate the Node.
+            return null;
+        }
+
+        private String createPeriod( Period period )
+        {
+
+            return " / " +
+                   dateTimeFormatter.format( period.startOfPeriod().get() ) +
+                   " - " +
+                   dateTimeFormatter.format( period.endOfPeriod().get() );
+        }
+
+        private Element createElement( Document dom, String element )
+        {
+            return dom.createElementNS( Page.XHTML, element );
+        }
+
+        private String createLink( Booking booking )
+        {
+            String pageUrl = urlService.createLink( bookingPage );
+            String entityId = booking.identity().get().toString();
+            return pageUrl + "/" + entityId;
+        }
+    }
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/Page.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/Page.java
new file mode 100644
index 0000000..876e4ad
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/Page.java
@@ -0,0 +1,180 @@
+/*
+ *  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.polygene.sample.rental.web;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+@Concerns( PageUowManagement.class )
+@Mixins( { Page.MountPointMixin.class, Page.DefaultPageRenderMixin.class } )
+public interface Page
+    extends ServiceComposite
+{
+    String XHTML = "http://www.w3.org/1999/xhtml";
+    String QI = "http://polygene.apache.org/ns/2009/quikit";
+
+    /**
+     * Returns the URL where the Page is mounted.
+     *
+     * @return the URL mountpoint.
+     */
+    String mountPoint();
+
+    void render( QuikitContext context )
+        throws RenderException;
+
+    abstract class DefaultPageRenderMixin
+        implements Page
+    {
+        public void render( QuikitContext context )
+            throws RenderException
+        {
+            Document dom = context.dom();
+            Element htmlElement = dom.getDocumentElement();
+            Element bodyElement = (Element) htmlElement.getElementsByTagNameNS( Page.XHTML, "body" ).item( 0 );
+            parseElement( context, bodyElement, htmlElement );
+        }
+
+        private void parseElement( QuikitContext context, Element element, Element parent )
+            throws RenderException
+        {
+            String method = element.getAttributeNS( Page.QI, "method" );
+            if( method.length() > 0 )
+            {
+                context.setDynamic( method, element, parent );
+                execute( context, element, parent );
+                return;
+            }
+            NodeList nodes = element.getChildNodes();
+            for( int i = 0; i < nodes.getLength(); i++ )
+            {
+                Node node = nodes.item( i );
+                if( node instanceof Element )
+                {
+                    parseElement( context, (Element) node, element );
+                }
+            }
+        }
+
+        private void execute( QuikitContext context, Element element, Element parent )
+            throws RenderException
+        {
+            Class<? extends Composite> compositeType =
+                (Class<Composite>) PolygeneAPI.FUNCTION_DESCRIPTOR_FOR.apply( context.page() ).types().findFirst().orElse( null );
+            try
+            {
+                Method method = findMethod( context.methodName(), compositeType );
+                Object result = method.invoke( context.page(), context );
+                if( result instanceof String )
+                {
+                    element.setTextContent( (String) result );
+                    return;
+                }
+                if( result instanceof Node )
+                {
+                    parent.replaceChild( (Node) result, element );
+                    return;
+                }
+                if( result instanceof List )
+                {
+                    for( Node node : (List<Node>) result )
+                    {
+                        element.appendChild( node );
+                    }
+                    return;
+                }
+                if( result.getClass().isArray() )
+                {
+                    Class type = result.getClass().getComponentType();
+                    if( Node.class.isAssignableFrom( type ) )
+                    {
+                        for( Node node : (Node[]) result )
+                        {
+                            element.appendChild( node );
+                        }
+                    }
+                    return;
+                }
+//              TODO: Future!!!
+//                if( result instanceof EntityComposite )
+//                {
+                // Locate HTML template for reault.type()
+                // If not present, use EntityComposite.html
+                // repeat rendering.
+                // Need mechanism to pass the "reference"
+//                }
+                element.setTextContent( result.toString() );
+            }
+
+            catch( NoSuchMethodException e )
+            {
+                String message = "Method '" + context.methodName() + "' does not exist in " + compositeType.getSimpleName();
+                throw new RenderException( message, e );
+            }
+            catch( IllegalAccessException e )
+            {
+                String message = "Method '" + context.methodName() + "' is not public in " + compositeType.getSimpleName();
+                throw new RenderException( message, e );
+            }
+            catch( InvocationTargetException e )
+            {
+                if( e.getTargetException() instanceof RenderException )
+                {
+                    throw ( (RenderException) e.getTargetException() );
+                }
+                throw new RenderException( "Method '" + context.methodName() + "' threw an exception.", e );
+            }
+        }
+
+        private Method findMethod( String methodName, Class<? extends Composite> compositeType )
+            throws NoSuchMethodException
+        {
+            // TODO: Add caching since locating the methods and the throwing of exceptions are expensive.
+            Method method = compositeType.getMethod( methodName, QuikitContext.class );
+            method.setAccessible( true );
+            return method;
+        }
+    }
+
+    abstract class MountPointMixin
+        implements Page
+    {
+        @Uses
+        ServiceDescriptor descriptor;
+
+        public String mountPoint()
+        {
+            return descriptor.metaInfo( PageMetaInfo.class ).mountPoint();
+        }
+    }
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/PageMetaInfo.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/PageMetaInfo.java
new file mode 100644
index 0000000..9c9afa3
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/PageMetaInfo.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.sample.rental.web;
+
+import java.io.Serializable;
+
+public class PageMetaInfo
+    implements Serializable
+{
+    final static long serialVersionUID = 1L;
+
+    private String mountPoint;
+
+    public PageMetaInfo( String mountPoint )
+    {
+        while( mountPoint.startsWith( "/" ) )
+        {
+            mountPoint = mountPoint.substring( 1 );
+        }
+        while( mountPoint.endsWith( "/" ) )
+        {
+            mountPoint = mountPoint.substring( 0, mountPoint().length() - 1 );
+        }
+        this.mountPoint = "/" + mountPoint;
+    }
+
+    public String mountPoint()
+    {
+        return mountPoint;
+    }
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/PageUowManagement.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/PageUowManagement.java
new file mode 100644
index 0000000..97efad1
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/PageUowManagement.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.sample.rental.web;
+
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+
+public abstract class PageUowManagement
+    extends ConcernOf<Page>
+    implements Page
+{
+    @Structure
+    private UnitOfWorkFactory uowf;
+
+    public void render( QuikitContext context )
+    {
+        UnitOfWork uow = uowf.newUnitOfWork();
+        try
+        {
+            next.render( context );
+            uow.complete();
+        }
+        catch( Throwable e )
+        {
+            uow.discard();
+        }
+    }
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/QuikitContext.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/QuikitContext.java
new file mode 100644
index 0000000..769ab16
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/QuikitContext.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.sample.rental.web;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public interface QuikitContext
+{
+
+    Page page();
+
+    String methodName();
+
+    Document dom();
+
+    Element element();
+
+    Element parentElement();
+
+    /**
+     * Returns the request path, with the mountpoint removed.
+     *
+     * @return The request path.
+     */
+    String path();
+
+    /**
+     * Returns the queryString from the URL.
+     *
+     * @return the query string of the URL, i.e. the content after the question mark "?".
+     */
+    String queryString();
+
+    /**
+     * Returns the header from the request.
+     *
+     * @param headerKey the name of the header.
+     *
+     * @return the Header value of the named header.
+     */
+    String getHeader( String headerKey );
+
+    /**
+     * Returns the data of the request.
+     *
+     * @return the data part of the request.
+     */
+    byte[] data()
+        throws RenderException;
+
+    void setDynamic( String method, Element element, Element parent );
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/QuikitResolver.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/QuikitResolver.java
new file mode 100644
index 0000000..9209e6e
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/QuikitResolver.java
@@ -0,0 +1,128 @@
+/*
+ *  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.polygene.sample.rental.web;
+
+import java.io.BufferedInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+import javax.xml.parsers.DocumentBuilder;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.bootstrap.DOMImplementationRegistry;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+public class QuikitResolver
+    implements LSResourceResolver, EntityResolver
+{
+    private Properties local;
+    private final DocumentBuilder builder;
+
+    public QuikitResolver( DocumentBuilder builder )
+    {
+        this.builder = builder;
+        local = new Properties();
+        try
+        {
+            InputStream stream = getClass().getClassLoader().getResourceAsStream( "resolve.properties" );
+            BufferedInputStream in = new BufferedInputStream( stream );
+            local.load( in );
+        }
+        catch( FileNotFoundException e )
+        {
+            e.printStackTrace();
+        }
+        catch( IOException e )
+        {
+            e.printStackTrace();
+        }
+    }
+
+    public InputSource resolveEntity( String publicId, String systemId )
+        throws SAXException, IOException
+    {
+        String resourceName = local.getProperty( publicId );
+        if( resourceName == null )
+        {
+            System.out.println( "Not locally available: " + publicId + "  " + systemId );
+            return null;
+        }
+        InputStream in = getClass().getClassLoader().getResourceAsStream( resourceName );
+        return new InputSource( in );
+    }
+
+    public LSInput resolveResource( String type, String namespaceURI, String publicId, String systemId, String baseURI )
+    {
+        String resourceName = local.getProperty( systemId );
+        if( resourceName == null )
+        {
+            System.out.println( "type: " + type );
+            System.out.println( "namespaceURI: " + namespaceURI );
+            System.out.println( "publicId: " + publicId );
+            System.out.println( "systemId: " + systemId );
+            System.out.println( "baseURI: " + baseURI );
+            return null;
+        }
+
+        InputStream resource = getClass().getClassLoader().getResourceAsStream( resourceName );
+        LSInput input;
+        try
+        {
+            input = getLSInput();
+        }
+        catch( Exception e )
+        {
+            throw new UnsupportedOperationException( "Internal problem. Please report to dev@polygene.apache.org mailing list.", e  );
+        }
+        input.setBaseURI( baseURI );
+        input.setByteStream( resource );
+        input.setPublicId( publicId );
+        input.setSystemId( systemId );
+        return input;
+    }
+
+    private LSInput getLSInput() throws Exception {
+        DOMImplementationLS impl;
+        DOMImplementation docImpl = builder.getDOMImplementation();
+        // Try to get the DOMImplementation from doc first before
+        // defaulting to the sun implementation.
+        if (docImpl != null && docImpl.hasFeature("LS", "3.0")) {
+            impl = (DOMImplementationLS)docImpl.getFeature("LS", "3.0");
+        } else {
+            DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
+            impl = (DOMImplementationLS)registry.getDOMImplementation("LS");
+            if (impl == null) {
+                System.setProperty(DOMImplementationRegistry.PROPERTY,
+                                   "com.sun.org.apache.xerces.internal.dom.DOMImplementationSourceImpl");
+                registry = DOMImplementationRegistry.newInstance();
+                impl = (DOMImplementationLS)registry.getDOMImplementation("LS");
+            }
+        }
+        return impl.createLSInput();
+    }
+
+
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/QuikitServlet.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/QuikitServlet.java
new file mode 100644
index 0000000..4eec4af
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/QuikitServlet.java
@@ -0,0 +1,339 @@
+/*
+ *  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.polygene.sample.rental.web;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Map;
+import java.util.TreeMap;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.SAXException;
+
+public class QuikitServlet
+    extends HttpServlet
+{
+    private Application application;
+    private ServiceFinder finder;
+    private UrlService urlService;
+    private DocumentBuilderFactory documentFactory;
+    private TreeMap<String, Page> mountPoints;
+
+    @Override
+    public void init( ServletConfig config )
+        throws ServletException
+    {
+        try
+        {
+            mountPoints = new TreeMap<>();
+            documentFactory = DocumentBuilderFactory.newInstance();
+            documentFactory.setNamespaceAware( true );
+            ClassLoader cl = getClass().getClassLoader();
+            SchemaFactory schemaFactory = SchemaFactory.newInstance( "http://www.w3.org/2001/XMLSchema" );
+            Source[] schemaSources = new Source[ 2 ];
+            schemaSources[ 0 ] = new StreamSource( cl.getResourceAsStream( "xhtml1-strict.xsd" ) );
+            schemaSources[ 1 ] = new StreamSource( cl.getResourceAsStream( "xml.xsd" ) );
+            Schema schema = schemaFactory.newSchema( schemaSources );
+            documentFactory.setSchema( schema );
+
+            ApplicationAssembler assembler = createApplicationAssembler( config );
+
+            Energy4Java polygene = new Energy4Java();
+            application = polygene.newApplication( assembler );
+            application.activate();
+            Module module = application.findModule( "WebLayer", "PagesModule" );
+            finder = module;
+
+            if( application.mode() == Application.Mode.development )
+            {
+                DataInitializer initializer = module.newTransient( DataInitializer.class );
+                initializer.initialize();
+            }
+            finder.findServices( Page.class ).forEach(
+                page ->
+                {
+                    PageMetaInfo pageMetaInfo = page.metaInfo( PageMetaInfo.class );
+                    String mountPoint = pageMetaInfo.mountPoint();
+                    mountPoints.put( mountPoint, page.get() );
+                }
+            );
+        }
+        catch( Exception e )
+        {
+            throw new ServletException( "Can not initialize Polygene.", e );
+        }
+    }
+
+    private ApplicationAssembler createApplicationAssembler( ServletConfig config )
+        throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException
+    {
+        String assemblerClassname = config.getInitParameter( "polygene-assembler" );
+        ClassLoader loader = getClass().getClassLoader();
+        Class<?> assemblerClass = loader.loadClass( assemblerClassname );
+        ApplicationAssembler assembler;
+        Constructor cons = assemblerClass.getConstructor( Application.Mode.class );
+        if( cons == null )
+        {
+            assembler = (ApplicationAssembler) assemblerClass.newInstance();
+        }
+        else
+        {
+            Application.Mode mode;
+            String modeSetting = config.getInitParameter( "polygene-application-mode" );
+            if( modeSetting == null )
+            {
+                mode = Application.Mode.development;
+            }
+            else
+            {
+                mode = Application.Mode.valueOf( modeSetting );
+            }
+            assembler = (ApplicationAssembler) cons.newInstance( mode );
+        }
+        return assembler;
+    }
+
+    @Override
+    public void destroy()
+    {
+        try
+        {
+            application.passivate();
+        }
+        catch( Exception e )
+        {
+            throw new RuntimeException( "Problem to passivate Polygene", e );
+        }
+    }
+
+    @Override
+    protected void doGet( HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse )
+        throws ServletException, IOException
+    {
+        String path = httpServletRequest.getPathInfo();
+        if( urlService == null )
+        {
+            urlService = finder.findService( UrlService.class ).get();
+            String uri = httpServletRequest.getRequestURI();
+            String basePath = uri.substring( 0, uri.length() - path.length() );
+            urlService.registerBaseUri( basePath );
+        }
+        PrintWriter output = httpServletResponse.getWriter();
+        while( path.startsWith( "//" ) )
+        {
+            path = path.substring( 1 );
+        }
+        for( Map.Entry<String, Page> entry : mountPoints.entrySet() )
+        {
+            if( path.startsWith( entry.getKey() ) )
+            {
+                Page page = entry.getValue();
+                String subPath = path.substring( entry.getKey().length() );
+                try
+                {
+                    renderPage( page, subPath, output, httpServletRequest );
+                }
+                catch( Exception e )
+                {
+                    throw new ServletException( e );
+                }
+                break;
+            }
+        }
+        output.flush();
+    }
+
+    private void renderPage( Page page, String path, PrintWriter output, HttpServletRequest httpRequest )
+        throws ParserConfigurationException, SAXException, IOException, RenderException, TransformerException
+    {
+        @SuppressWarnings( "unchecked" )
+        Class<? extends Composite> pageClass =
+            (Class<Composite>) PolygeneAPI.FUNCTION_DESCRIPTOR_FOR.apply( page ).types().findFirst().orElse( null );
+
+        String pageName = pageClass.getSimpleName() + ".html";
+        DocumentBuilder documentBuilder = documentFactory.newDocumentBuilder();
+        documentBuilder.setEntityResolver( createEntityResolver( documentBuilder ) );
+        InputStream pageResource = pageClass.getResourceAsStream( pageName );
+        Document dom = documentBuilder.parse( pageResource );
+        try
+        {
+            Context context = new Context( dom, page, path, httpRequest );
+            page.render( context );
+        }
+        catch( Throwable e )
+        {
+            error( dom, e );
+        }
+        DOMSource source = new DOMSource( dom );
+        StreamResult result = new StreamResult( output );
+        Transformer transformer = TransformerFactory.newInstance().newTransformer();
+        transformer.transform( source, result );
+        output.flush();
+    }
+
+    private EntityResolver createEntityResolver( DocumentBuilder builder )
+        throws SAXException
+    {
+        QuikitResolver quickitResolver = new QuikitResolver( builder );
+        SchemaFactory schemaFactory = SchemaFactory.newInstance( "http://www.w3.org/2001/XMLSchema" );
+        schemaFactory.setResourceResolver( quickitResolver );
+        return quickitResolver;
+    }
+
+    private void error( Document dom, Throwable exception )
+    {
+        Element root = dom.getDocumentElement();
+        dom.removeChild( root );
+        Element preElement = (Element) dom.appendChild( dom.createElementNS( Page.XHTML, "html" ) )
+            .appendChild( dom.createElementNS( Page.XHTML, "body" ) )
+            .appendChild( dom.createElementNS( Page.XHTML, "code" ) )
+            .appendChild( dom.createElementNS( Page.XHTML, "pre" ) );
+
+        StringWriter stringWriter = new StringWriter( 2000 );
+        PrintWriter writer = new PrintWriter( stringWriter );
+        exception.printStackTrace( writer );
+        writer.close();
+        String content = stringWriter.getBuffer().toString();
+        preElement.setTextContent( content );
+    }
+
+    static class Context
+        implements QuikitContext
+    {
+        private final Page page;
+        private String methodName;
+        private Element element;
+        private Element parentElement;
+        private final Document dom;
+        private final String path;
+        private final HttpServletRequest request;
+        private byte[] data = null;
+
+        public Context( Document dom, Page page, String path, HttpServletRequest httpServletRequest )
+        {
+            this.dom = dom;
+            this.page = page;
+            this.path = path;
+            this.request = httpServletRequest;
+        }
+
+        public Page page()
+        {
+            return page;
+        }
+
+        public String methodName()
+        {
+            return methodName;
+        }
+
+        public Document dom()
+        {
+            return dom;
+        }
+
+        public Element element()
+        {
+            return element;
+        }
+
+        public Element parentElement()
+        {
+            return parentElement;
+        }
+
+        public String path()
+        {
+            return path;
+        }
+
+        public String queryString()
+        {
+            return request.getQueryString();
+        }
+
+        public String getHeader( String headerKey )
+        {
+            return request.getHeader( headerKey );
+        }
+
+        public byte[] data()
+            throws RenderException
+        {
+            if( data == null )
+            {
+                try
+                {
+                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                    InputStream in = request.getInputStream();
+                    int i;
+                    while( ( i = in.read() ) != -1 )
+                    {
+                        baos.write( i );
+                    }
+                    data = baos.toByteArray();
+                }
+                catch( IOException e )
+                {
+                    throw new RenderException( "I/O problems.", e );
+                }
+            }
+            return data;
+        }
+
+        public void setDynamic( String method, Element element, Element parent )
+        {
+            this.methodName = method;
+            this.element = element;
+            this.parentElement = parent;
+        }
+    }
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/RenderException.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/RenderException.java
new file mode 100644
index 0000000..1d50098
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/RenderException.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.sample.rental.web;
+
+import javax.servlet.ServletException;
+
+public class RenderException
+    extends ServletException
+{
+    public RenderException( String message )
+    {
+        super( message );
+    }
+
+    public RenderException( String message, Throwable throwable )
+    {
+        super( message, throwable );
+    }
+
+    public RenderException( Throwable throwable )
+    {
+        super( throwable );
+    }
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/UrlService.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/UrlService.java
new file mode 100644
index 0000000..6b40b46
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/UrlService.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.sample.rental.web;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.spi.PolygeneSPI;
+
+@Mixins( UrlService.UrlServiceMixin.class )
+public interface UrlService
+    extends ServiceComposite
+{
+    void registerBaseUri( String baseUri );
+
+    String createLink( Page page );
+
+    static abstract class UrlServiceMixin
+        implements UrlService
+    {
+        @Structure
+        PolygeneSPI spi;
+
+        private String baseUri;
+
+        public void registerBaseUri( String baseUri )
+        {
+            this.baseUri = baseUri;
+        }
+
+        public String createLink( Page page )
+        {
+            String mountPoint = spi.serviceDescriptorFor( page ).metaInfo( PageMetaInfo.class ).mountPoint();
+            return baseUri + mountPoint;
+        }
+    }
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/assembly/PagesModule.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/assembly/PagesModule.java
new file mode 100644
index 0000000..7321828
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/assembly/PagesModule.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.sample.rental.web.assembly;
+
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.sample.rental.web.BookingPage;
+import org.apache.polygene.sample.rental.web.MainPage;
+import org.apache.polygene.sample.rental.web.PageMetaInfo;
+import org.apache.polygene.sample.rental.web.UrlService;
+
+public class PagesModule
+    implements Assembler
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        PageMetaInfo mainpageMeta = new PageMetaInfo( "main" );
+        module.services( MainPage.class ).setMetaInfo( mainpageMeta );
+
+        PageMetaInfo bookingpageMeta = new PageMetaInfo( "booking" );
+        module.services( BookingPage.class ).setMetaInfo( bookingpageMeta );
+
+        module.services( UrlService.class );
+    }
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/assembly/RentalApplicationAssembler.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/assembly/RentalApplicationAssembler.java
new file mode 100644
index 0000000..a695610
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/assembly/RentalApplicationAssembler.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.sample.rental.web.assembly;
+
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+
+public class RentalApplicationAssembler
+    implements ApplicationAssembler
+{
+    private Application.Mode mode;
+
+    public RentalApplicationAssembler( Application.Mode mode )
+    {
+        this.mode = mode;
+    }
+
+    @Override
+    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+        throws AssemblyException
+    {
+        ApplicationAssembly assembly = applicationFactory.newApplicationAssembly();
+        assembly.setMode( mode );
+        LayerAssembly webLayer = assembly.layer( "WebLayer" );
+        new PagesModule().assemble( webLayer.module( "PagesModule" ) );
+        LayerAssembly domainLayer = assembly.layer( "DomainLayer" );
+        new RentalModule().assemble( domainLayer.module( "RentalModule" ) );
+        LayerAssembly infraLayer = assembly.layer( "InfraLayer" );
+        new StorageModule().assemble( infraLayer.module( "StorageModule" ) );
+
+        webLayer.uses( domainLayer );
+        domainLayer.uses( infraLayer );
+        return assembly;
+    }
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/assembly/RentalModule.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/assembly/RentalModule.java
new file mode 100644
index 0000000..4cece75
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/assembly/RentalModule.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.sample.rental.web.assembly;
+
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.sample.rental.domain.Address;
+import org.apache.polygene.sample.rental.domain.Booking;
+import org.apache.polygene.sample.rental.domain.Car;
+import org.apache.polygene.sample.rental.domain.CarCategory;
+import org.apache.polygene.sample.rental.domain.Customer;
+import org.apache.polygene.sample.rental.domain.Period;
+import org.apache.polygene.sample.rental.domain.RentalShop;
+import org.apache.polygene.sample.rental.domain.dev.InitialData;
+
+import static org.apache.polygene.api.common.Visibility.application;
+
+public class RentalModule
+    implements Assembler
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( Booking.class, Car.class, Customer.class, CarCategory.class ).visibleIn( application );
+        module.values( Address.class, Period.class );
+        module.entities( RentalShop.class ).visibleIn( application );
+
+        if( module.layer().application().mode().equals( Application.Mode.development ) )
+        {
+            module.transients( InitialData.class ).visibleIn( application );
+        }
+    }
+}
diff --git a/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/assembly/StorageModule.java b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/assembly/StorageModule.java
new file mode 100644
index 0000000..a7ca995
--- /dev/null
+++ b/samples/rental/src/main/java/org/apache/polygene/sample/rental/web/assembly/StorageModule.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.sample.rental.web.assembly;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+
+public class StorageModule
+    implements Assembler
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( MemoryEntityStoreService.class ).visibleIn( Visibility.application );
+    }
+}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/domain/Address.java b/samples/rental/src/main/java/org/qi4j/sample/rental/domain/Address.java
deleted file mode 100644
index 766f8ae..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/domain/Address.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.domain;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-public interface Address
-    extends ValueComposite
-{
-    Property<String> line1();
-
-    Property<String> line2();
-
-    Property<String> zipCode();
-
-    Property<String> city();
-
-    Property<String> country();
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/domain/Booking.java b/samples/rental/src/main/java/org/qi4j/sample/rental/domain/Booking.java
deleted file mode 100644
index cf5142b..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/domain/Booking.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.domain;
-
-import java.util.Date;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-
-public interface Booking
-    extends EntityComposite
-{
-    Property<String> reference();
-
-    Association<Customer> customer();
-
-    Association<Car> car();
-
-    Property<Period> period();
-
-    @Optional
-        // if not set, the pickup has not occurred yet.
-    Property<Date> pickedupTime();
-
-    @Optional
-        // if not set, the return has not occurred yet.
-    Property<Date> returnedTime();
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/domain/Car.java b/samples/rental/src/main/java/org/qi4j/sample/rental/domain/Car.java
deleted file mode 100644
index 0f26bcb..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/domain/Car.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.domain;
-
-import java.util.Date;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.Query;
-
-@Mixins( Car.CarMixin.class )
-public interface Car
-    extends EntityComposite
-{
-    Property<String> licensePlate();
-
-    Property<String> model();
-
-    Association<CarCategory> category();
-
-    @Optional
-    Property<Date> purchasedDate();
-
-    @Optional
-    Property<Date> soldDate();
-
-    Booking currentBooking();
-
-    Query<Booking> pastBookings();
-
-    abstract class CarMixin
-        implements Car
-    {
-
-        public Booking currentBooking()
-        {
-            return null;  //To change body of implemented methods use File | Settings | File Templates.
-        }
-
-        public Query<Booking> pastBookings()
-        {
-            return null;  //To change body of implemented methods use File | Settings | File Templates.
-        }
-    }
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/domain/CarCategory.java b/samples/rental/src/main/java/org/qi4j/sample/rental/domain/CarCategory.java
deleted file mode 100644
index b50f190..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/domain/CarCategory.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.domain;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-
-public interface CarCategory
-    extends EntityComposite
-{
-    Property<String> name();
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/domain/Customer.java b/samples/rental/src/main/java/org/qi4j/sample/rental/domain/Customer.java
deleted file mode 100644
index c1504af..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/domain/Customer.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.domain;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.Query;
-
-@Mixins( Customer.CustomerMixin.class )
-public interface Customer
-    extends EntityComposite
-{
-    Property<String> name();
-
-    Property<Address> address();
-
-    Query<Booking> currentBookings();
-
-    Query<Booking> pastBookings();
-
-    abstract class CustomerMixin
-        implements Customer
-    {
-        public Query<Booking> currentBookings()
-        {
-            return null;  //To change body of implemented methods use File | Settings | File Templates.
-        }
-
-        public Query<Booking> pastBookings()
-        {
-            return null;  //To change body of implemented methods use File | Settings | File Templates.
-        }
-    }
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/domain/Period.java b/samples/rental/src/main/java/org/qi4j/sample/rental/domain/Period.java
deleted file mode 100644
index ac783cd..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/domain/Period.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.domain;
-
-import java.util.Date;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-public interface Period
-    extends ValueComposite
-{
-    Property<Date> startOfPeriod();
-
-    Property<Date> endOfPeriod();
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/domain/RentalShop.java b/samples/rental/src/main/java/org/qi4j/sample/rental/domain/RentalShop.java
deleted file mode 100644
index 5941854..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/domain/RentalShop.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.domain;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.query.QueryBuilderFactory;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-
-@Mixins( RentalShop.RentalShopMixin.class )
-public interface RentalShop
-    extends EntityComposite
-{
-    Customer createCustomer( String name, String address1, String address2, String zip, String city, String country );
-
-    Car findAvailableCarByModel( String model );
-
-    Car findAvailableCarByCategory( CarCategory category );
-
-    List<CarCategory> findAllCarCategories();
-
-    List<Booking> findAllBookings();
-
-    Set<String> findAllCarModels();
-
-    Booking book( Customer customer, Car car, Period plannedPeriod );
-
-    void pickup( Booking booking, Date time );
-
-    void returned( Booking booking, Date time );
-
-    void boughtCar( Car car, Date purchasedate );
-
-    void soldCar( Car car, Date soldDate );
-
-    Car createCar( String category, String modelName, String licensePlate );
-
-    List<CarCategory> carCategories();
-
-    interface State
-    {
-        ManyAssociation<Car> carsOwned();
-
-        ManyAssociation<Car> carsAvailable();
-
-        ManyAssociation<Booking> bookings();
-
-        ManyAssociation<CarCategory> carCategories();
-    }
-
-    abstract class RentalShopMixin
-        implements RentalShop
-    {
-        @Structure
-        ValueBuilderFactory vbf;
-        @Structure
-        QueryBuilderFactory qbf;
-        @Structure
-        UnitOfWorkFactory uowf;
-        @This
-        private State state;
-
-        public Customer createCustomer( String name,
-                                        String address1,
-                                        String address2,
-                                        String zip,
-                                        String city,
-                                        String country
-        )
-        {
-            ValueBuilder<Address> addrBuilder = vbf.newValueBuilder( Address.class );
-            Address protoAddress = addrBuilder.prototype();
-            protoAddress.line1().set( address1 );
-            protoAddress.line2().set( address2 );
-            protoAddress.zipCode().set( zip );
-            protoAddress.city().set( city );
-            protoAddress.country().set( country );
-            Address address = addrBuilder.newInstance();
-            EntityBuilder<Customer> builder = uowf.currentUnitOfWork().newEntityBuilder( Customer.class );
-            builder.instance().name().set( name );
-            builder.instance().address().set( address );
-            return builder.newInstance();
-        }
-
-        public Car findAvailableCarByModel( String model )
-        {
-            for( Car car : state.carsAvailable().toList() )
-            {
-                if( car.model().get().equals( model ) )
-                {
-                    return car;
-                }
-            }
-            return null;
-        }
-
-        public Car findAvailableCarByCategory( CarCategory category )
-        {
-            for( Car car : state.carsAvailable().toList() )
-            {
-                if( car.category().get().equals( category ) )
-                {
-                    return car;
-                }
-            }
-            return null;
-        }
-
-        public List<CarCategory> findAllCarCategories()
-        {
-            return state.carCategories().toList();
-        }
-
-        public Set<String> findAllCarModels()
-        {
-            HashSet<String> result = new HashSet<String>();
-            for( Car car : state.carsOwned().toList() )
-            {
-                result.add( car.model().get() );
-            }
-            return result;
-        }
-
-        public Booking book( Customer customer, Car car, Period plannedPeriod )
-        {
-            EntityBuilder<Booking> builder = uowf.currentUnitOfWork().newEntityBuilder( Booking.class );
-            Booking instance = builder.instance();
-            String refNo;
-            try
-            {
-                MessageDigest md;
-                md = MessageDigest.getInstance( "MD5" );
-                md.update( instance.identity().get().getBytes() );
-                StringBuffer buf = new StringBuffer();
-                byte[] data = md.digest();
-                for( int i = 0; i < 4; i++ )
-                {
-                    String hex = Integer.toHexString( Math.abs( data[ i ] ) );
-                    if( hex.length() == 1 )
-                    {
-                        buf.append( "0" );
-                    }
-                    buf.append( hex );
-                    if( i == 1 )
-                    {
-                        buf.append( "-" );
-                    }
-                }
-                refNo = buf.toString().toUpperCase();
-            }
-            catch( NoSuchAlgorithmException e )
-            {
-                // Can not happen.
-                throw new RuntimeException( e );
-            }
-            instance.reference().set( refNo );
-            instance.car().set( car );
-            instance.customer().set( customer );
-            instance.period().set( plannedPeriod );
-            Booking booking = builder.newInstance();
-            state.bookings().add( booking );
-            return booking;
-        }
-
-        public void pickup( Booking booking, Date time )
-        {
-            booking.pickedupTime().set( time );
-        }
-
-        public void returned( Booking booking, Date time )
-        {
-            booking.returnedTime().set( time );
-        }
-
-        public void boughtCar( Car car, Date purchaseDate )
-        {
-            state.carsOwned().add( car );
-            car.purchasedDate().set( purchaseDate );
-        }
-
-        public void soldCar( Car car, Date soldDate )
-        {
-            state.carsOwned().remove( car );
-            car.soldDate().set( soldDate );
-        }
-
-        public List<Booking> findAllBookings()
-        {
-            ManyAssociation<Booking> manyAssociation = state.bookings();
-            return manyAssociation.toList();
-        }
-
-        public List<CarCategory> carCategories()
-        {
-            return state.carCategories().toList();
-        }
-
-        public Car createCar( String category, String modelName, String licensePlate )
-        {
-            CarCategory carCategory = findCarCategory( category );
-            EntityBuilder<Car> builder = uowf.currentUnitOfWork().newEntityBuilder( Car.class );
-            builder.instance().model().set( modelName );
-            builder.instance().category().set( carCategory );
-            builder.instance().licensePlate().set( licensePlate );
-            return builder.newInstance();
-        }
-
-        private CarCategory findCarCategory( String categoryName )
-        {
-            for( CarCategory carCategory : state.carCategories() )
-            {
-                if( carCategory.name().get().equals( categoryName ) )
-                {
-                    return carCategory;
-                }
-            }
-            EntityBuilder<CarCategory> categoryBuilder = uowf.currentUnitOfWork().newEntityBuilder( CarCategory.class );
-            categoryBuilder.instance().name().set( categoryName );
-            return categoryBuilder.newInstance();
-        }
-    }
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/domain/dev/InitialData.java b/samples/rental/src/main/java/org/qi4j/sample/rental/domain/dev/InitialData.java
deleted file mode 100644
index c34ebfe..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/domain/dev/InitialData.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.domain.dev;
-
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.sample.rental.domain.Car;
-import org.qi4j.sample.rental.domain.Customer;
-import org.qi4j.sample.rental.domain.Period;
-import org.qi4j.sample.rental.domain.RentalShop;
-import org.qi4j.sample.rental.web.DataInitializer;
-
-@Mixins( InitialData.Mixin.class )
-public interface InitialData
-    extends DataInitializer, TransientComposite
-{
-    abstract class Mixin
-        implements DataInitializer
-    {
-        @Structure
-        UnitOfWorkFactory uowf;
-        @Structure
-        ValueBuilderFactory vbf;
-        private ArrayList<Customer> customers = new ArrayList<Customer>();
-        private ArrayList<Car> cars = new ArrayList<Car>();
-
-        public void initialize()
-            throws Exception
-        {
-            UnitOfWork uow = uowf.newUnitOfWork();
-            try
-            {
-                RentalShop shop = createShop( uow );
-                createCustomers( shop );
-                createCars( shop );
-                createBookings( shop );
-                uow.complete();
-            }
-            finally
-            {
-                uow.discard();
-            }
-        }
-
-        private void createBookings( RentalShop shop )
-        {
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-            shop.book( findRandomCustomer(), findRandomCar(), createRandomPeriod() );
-        }
-
-        private Period createRandomPeriod()
-        {
-            Calendar cal = Calendar.getInstance();
-            cal.setTime( new Date() );
-            cal.add( Calendar.DATE, Math.abs( (int) ( Math.random() * 5.0 ) ) );
-            cal.set( Calendar.HOUR_OF_DAY, 15 );
-            cal.set( Calendar.MINUTE, 0 );
-            cal.set( Calendar.SECOND, 0 );
-            Date earliestPickup = cal.getTime();
-
-            cal.add( Calendar.DATE, Math.abs( (int) ( Math.random() * 30.0 ) ) );
-            cal.set( Calendar.HOUR_OF_DAY, 12 );
-            cal.set( Calendar.MINUTE, 0 );
-            cal.set( Calendar.SECOND, 0 );
-            Date latestReturn = cal.getTime();
-            ValueBuilder<Period> builder = vbf.newValueBuilder( Period.class );
-            builder.prototype().startOfPeriod().set( earliestPickup );
-            builder.prototype().endOfPeriod().set( latestReturn );
-            return builder.newInstance();
-        }
-
-        private Car findRandomCar()
-        {
-            int index = (int) Math.floor( cars.size() * Math.random() );
-            return cars.get( index );
-        }
-
-        private Customer findRandomCustomer()
-        {
-            int index = (int) Math.floor( customers.size() * Math.random() );
-            return customers.get( index );
-        }
-
-        private void createCars( RentalShop shop )
-        {
-            Car car;
-            car = shop.createCar( "SUV", "Volvo XC90", "WHO 7878" );
-            shop.boughtCar( car, new Date() );
-            cars.add( car );
-            car = shop.createCar( "SUV", "BMW X5", "WIT 23" );
-            shop.boughtCar( car, new Date() );
-            cars.add( car );
-            car = shop.createCar( "SUV", "Volvo XC90", "WHO 7879" );
-            shop.boughtCar( car, new Date() );
-            cars.add( car );
-            car = shop.createCar( "SUV", "Volvo XC90", "WHO 7880" );
-            shop.boughtCar( car, new Date() );
-            cars.add( car );
-            car = shop.createCar( "SUV", "BMW X5", "WIT 24" );
-            shop.boughtCar( car, new Date() );
-            cars.add( car );
-            car = shop.createCar( "SUV", "BMW X5", "WIT 25" );
-            shop.boughtCar( car, new Date() );
-            cars.add( car );
-            car = shop.createCar( "SUV", "BMW X5", "WIT 26" );
-            shop.boughtCar( car, new Date() );
-            cars.add( car );
-            car = shop.createCar( "SUV", "BMW X5", "WIT 27" );
-            shop.boughtCar( car, new Date() );
-            cars.add( car );
-            car = shop.createCar( "Compact", "Mini Cooper S", "WMY 40" );
-            shop.boughtCar( car, new Date() );
-            cars.add( car );
-            car = shop.createCar( "Compact", "Mini Cooper S", "WMY 41" );
-            shop.boughtCar( car, new Date() );
-            cars.add( car );
-            car = shop.createCar( "Compact", "Mini Cooper S", "WMY 42" );
-            shop.boughtCar( car, new Date() );
-            cars.add( car );
-            car = shop.createCar( "Compact", "Mini Cooper S", "WMY 43" );
-            shop.boughtCar( car, new Date() );
-            cars.add( car );
-            car = shop.createCar( "Compact", "Mini Cooper S", "WMY 44" );
-            shop.boughtCar( car, new Date() );
-            cars.add( car );
-            car = shop.createCar( "Compact", "Mini Cooper S", "WMY 45" );
-            shop.boughtCar( car, new Date() );
-            cars.add( car );
-            car = shop.createCar( "Sedan", "BMW 318i", "WRY 900" );
-            shop.boughtCar( car, new Date() );
-            cars.add( car );
-            car = shop.createCar( "Sedan", "BMW 318i", "WRY 901" );
-            shop.boughtCar( car, new Date() );
-            cars.add( car );
-            car = shop.createCar( "Sedan", "BMW 318i", "WRY 902" );
-            shop.boughtCar( car, new Date() );
-            cars.add( car );
-        }
-
-        private RentalShop createShop( UnitOfWork uow )
-            throws UnitOfWorkCompletionException
-        {
-            return uow.newEntity( RentalShop.class, "SHOP" );
-        }
-
-        private void createCustomers( RentalShop shop )
-        {
-            customers.add( shop.createCustomer( "Niclas Hedhman", "344-28-2, Vista Damai", "Jalan Tun Razak", "50400", "Kuala Lumpur", "Malaysia" ) );
-            customers.add( shop.createCustomer( "Peter Neubauer", "Sovstaden 24", "", "21212", "Malm�", "Sweden" ) );
-            customers.add( shop.createCustomer( "Rickard �berg", "GpsFree 123", "Bukit Antarabangsa", "68000", "Ampang", "Malaysia" ) );
-            customers.add( shop.createCustomer( "Mickey Mouse", "Playhouse 1", "", "1234", "Disneyland", "USA" ) );
-            customers.add( shop.createCustomer( "Michael Hunger", "Jederstrasse 1", "", "78787", "Dresden", "Germany" ) );
-            customers.add( shop.createCustomer( "Emil Eifrem", "Freeze Street 12", "WhereWindBlows", "23456", "Malm�", "Sweden" ) );
-        }
-    }
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/web/BookingPage.java b/samples/rental/src/main/java/org/qi4j/sample/rental/web/BookingPage.java
deleted file mode 100644
index 8b237d1..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/web/BookingPage.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.web;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.sample.rental.domain.Booking;
-import org.qi4j.sample.rental.domain.Car;
-import org.qi4j.sample.rental.domain.Customer;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-@Mixins( BookingPage.BodyContributorMixin.class )
-public interface BookingPage
-    extends Page
-{
-    Node car( QuikitContext context );
-
-    Node customer( QuikitContext context );
-
-    abstract class BodyContributorMixin
-        implements BookingPage
-    {
-        @Structure
-        private UnitOfWorkFactory uowf;
-
-        public Node car( QuikitContext context )
-        {
-            Document dom = context.dom();
-            Element result = dom.createElementNS( Page.XHTML, "div" );
-            String bookingId = context.path();
-            UnitOfWork uow = uowf.currentUnitOfWork();
-            Booking booking = uow.get( Booking.class, bookingId );
-            Car car = booking.car().get();
-            createChildNode( dom, result, car.model().get() );
-            createChildNode( dom, result, car.licensePlate().get() );
-            createChildNode( dom, result, car.category().get().name().get() );
-            return result;
-        }
-
-        private void createChildNode( Document dom, Element result, String content )
-        {
-            Element modelElement = dom.createElement( "div" );
-            result.appendChild( modelElement );
-            modelElement.setTextContent( content );
-        }
-
-        public Node customer( QuikitContext context )
-        {
-            Document dom = context.dom();
-            Element result = dom.createElementNS( Page.XHTML, "div" );
-            String bookingId = context.path();
-            UnitOfWork uow = uowf.currentUnitOfWork();
-            Booking booking = uow.get( Booking.class, bookingId );
-            Customer customer = booking.customer().get();
-            createChildNode( dom, result, customer.name().get() );
-            createChildNode( dom, result, customer.address().get().line1().get() );
-            createChildNode( dom, result, customer.address().get().line2().get() );
-            createChildNode( dom, result, customer.address().get().zipCode().get() + " " + customer.address()
-                .get()
-                .city()
-                .get() );
-            createChildNode( dom, result, customer.address().get().country().get() );
-            return result;
-        }
-    }
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/web/DataInitializer.java b/samples/rental/src/main/java/org/qi4j/sample/rental/web/DataInitializer.java
deleted file mode 100644
index a916728..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/web/DataInitializer.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.web;
-
-public interface DataInitializer
-{
-    void initialize()
-        throws Exception;
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/web/MainPage.java b/samples/rental/src/main/java/org/qi4j/sample/rental/web/MainPage.java
deleted file mode 100644
index e3577a7..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/web/MainPage.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.web;
-
-import java.text.MessageFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.sample.rental.domain.Booking;
-import org.qi4j.sample.rental.domain.Period;
-import org.qi4j.sample.rental.domain.RentalShop;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-@Mixins( { MainPage.BodyContributorMixin.class } )
-public interface MainPage
-    extends Page
-{
-    Node[] bookings( QuikitContext context );
-
-    abstract class BodyContributorMixin
-        implements MainPage
-    {
-        private SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm" );
-
-        @Service
-        BookingPage bookingPage;
-        @Service
-        UrlService urlService;
-        @Structure
-        private UnitOfWorkFactory uowf;
-
-        public Node[] bookings( QuikitContext context )
-        {
-            ArrayList<Node> nodes = new ArrayList<Node>();
-            Document dom = context.dom();
-            UnitOfWork uow = uowf.currentUnitOfWork();
-            RentalShop shop = uow.get( RentalShop.class, "SHOP" );
-            for( Booking booking : shop.findAllBookings() )
-            {
-                String plate = booking.car().get().licensePlate().get();
-
-                // TODO: Next version;
-//                Node node = create( dom, "<li><a href='{1}'>{2}</a>{3}</li>", createLink( booking ), plate, createPeriod( booking.period().get() ) );
-//                nodes.add( node );
-
-                Element listItem = createElement( dom, "li" );
-                Element bookingLink = (Element) listItem.appendChild( createElement( dom, "a" ) );
-                bookingLink.setAttribute( "href", createLink( booking ) );
-                bookingLink.setTextContent( plate );
-                listItem.appendChild( dom.createTextNode( createPeriod( booking.period().get() ) ) );
-                nodes.add( listItem );
-            }
-            Node[] bookingList = new Node[ nodes.size() ];
-            nodes.toArray( bookingList );
-            return bookingList;
-        }
-
-        private Node create( Document dom, String pattern, Object... args )
-        {
-            String result = MessageFormat.format( pattern, args );
-            // TODO: fix up ANTLR to parse XML and generate the Node.
-            return null;
-        }
-
-        private String createPeriod( Period period )
-        {
-
-            return " / " +
-                   sdf.format( period.startOfPeriod().get() ) +
-                   " - " +
-                   sdf.format( period.endOfPeriod().get() );
-        }
-
-        private Element createElement( Document dom, String element )
-        {
-            return dom.createElementNS( Page.XHTML, element );
-        }
-
-        private String createLink( Booking booking )
-        {
-            String pageUrl = urlService.createLink( bookingPage );
-            String entityId = booking.identity().get();
-            return pageUrl + "/" + entityId;
-        }
-    }
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/web/Page.java b/samples/rental/src/main/java/org/qi4j/sample/rental/web/Page.java
deleted file mode 100644
index 30d9d5b..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/web/Page.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.web;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.List;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import static org.qi4j.functional.Iterables.first;
-
-@Concerns( PageUowManagement.class )
-@Mixins( { Page.MountPointMixin.class, Page.DefaultPageRenderMixin.class } )
-public interface Page
-    extends ServiceComposite
-{
-    String XHTML = "http://www.w3.org/1999/xhtml";
-    String QI = "http://www.qi4j.org/ns/2009/quikit";
-
-    /**
-     * Returns the URL where the Page is mounted.
-     *
-     * @return the URL mountpoint.
-     */
-    String mountPoint();
-
-    void render( QuikitContext context )
-        throws RenderException;
-
-    abstract class DefaultPageRenderMixin
-        implements Page
-    {
-        public void render( QuikitContext context )
-            throws RenderException
-        {
-            Document dom = context.dom();
-            Element htmlElement = dom.getDocumentElement();
-            Element bodyElement = (Element) htmlElement.getElementsByTagNameNS( Page.XHTML, "body" ).item( 0 );
-            parseElement( context, bodyElement, htmlElement );
-        }
-
-        private void parseElement( QuikitContext context, Element element, Element parent )
-            throws RenderException
-        {
-            String method = element.getAttributeNS( Page.QI, "method" );
-            if( method.length() > 0 )
-            {
-                context.setDynamic( method, element, parent );
-                execute( context, element, parent );
-                return;
-            }
-            NodeList nodes = element.getChildNodes();
-            for( int i = 0; i < nodes.getLength(); i++ )
-            {
-                Node node = nodes.item( i );
-                if( node instanceof Element )
-                {
-                    parseElement( context, (Element) node, element );
-                }
-            }
-        }
-
-        private void execute( QuikitContext context, Element element, Element parent )
-            throws RenderException
-        {
-            Class<? extends Composite> compositeType = (Class<Composite>) first( Qi4j.FUNCTION_DESCRIPTOR_FOR
-                                                                                     .map( context.page() )
-                                                                                     .types() );
-            try
-            {
-                Method method = findMethod( context.methodName(), compositeType );
-                Object result = method.invoke( context.page(), context );
-                if( result instanceof String )
-                {
-                    element.setTextContent( (String) result );
-                    return;
-                }
-                if( result instanceof Node )
-                {
-                    parent.replaceChild( (Node) result, element );
-                    return;
-                }
-                if( result instanceof List )
-                {
-                    for( Node node : (List<Node>) result )
-                    {
-                        element.appendChild( node );
-                    }
-                    return;
-                }
-                if( result.getClass().isArray() )
-                {
-                    Class type = result.getClass().getComponentType();
-                    if( Node.class.isAssignableFrom( type ) )
-                    {
-                        for( Node node : (Node[]) result )
-                        {
-                            element.appendChild( node );
-                        }
-                    }
-                    return;
-                }
-//              TODO: Future!!!
-//                if( result instanceof EntityComposite )
-//                {
-                // Locate HTML template for reault.type()
-                // If not present, use EntityComposite.html
-                // repeat rendering.
-                // Need mechanism to pass the "reference"
-//                }
-                element.setTextContent( result.toString() );
-            }
-
-            catch( NoSuchMethodException e )
-            {
-                String message = "Method '" + context.methodName() + "' does not exist in " + compositeType.getSimpleName();
-                throw new RenderException( message, e );
-            }
-            catch( IllegalAccessException e )
-            {
-                String message = "Method '" + context.methodName() + "' is not public in " + compositeType.getSimpleName();
-                throw new RenderException( message, e );
-            }
-            catch( InvocationTargetException e )
-            {
-                if( e.getTargetException() instanceof RenderException )
-                {
-                    throw ( (RenderException) e.getTargetException() );
-                }
-                throw new RenderException( "Method '" + context.methodName() + "' threw an exception.", e );
-            }
-        }
-
-        private Method findMethod( String methodName, Class<? extends Composite> compositeType )
-            throws NoSuchMethodException
-        {
-            // TODO: Add caching since locating the methods and the throwing of exceptions are expensive.
-            Method method = compositeType.getMethod( methodName, QuikitContext.class );
-            method.setAccessible( true );
-            return method;
-        }
-    }
-
-    abstract class MountPointMixin
-        implements Page
-    {
-        @Uses
-        ServiceDescriptor descriptor;
-
-        public String mountPoint()
-        {
-            return descriptor.metaInfo( PageMetaInfo.class ).mountPoint();
-        }
-    }
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/web/PageMetaInfo.java b/samples/rental/src/main/java/org/qi4j/sample/rental/web/PageMetaInfo.java
deleted file mode 100644
index 9c28539..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/web/PageMetaInfo.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.web;
-
-import java.io.Serializable;
-
-public class PageMetaInfo
-    implements Serializable
-{
-    final static long serialVersionUID = 1L;
-
-    private String mountPoint;
-
-    public PageMetaInfo( String mountPoint )
-    {
-        while( mountPoint.startsWith( "/" ) )
-        {
-            mountPoint = mountPoint.substring( 1 );
-        }
-        while( mountPoint.endsWith( "/" ) )
-        {
-            mountPoint = mountPoint.substring( 0, mountPoint().length() - 1 );
-        }
-        this.mountPoint = "/" + mountPoint;
-    }
-
-    public String mountPoint()
-    {
-        return mountPoint;
-    }
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/web/PageUowManagement.java b/samples/rental/src/main/java/org/qi4j/sample/rental/web/PageUowManagement.java
deleted file mode 100644
index 690a062..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/web/PageUowManagement.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.web;
-
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-
-public abstract class PageUowManagement
-    extends ConcernOf<Page>
-    implements Page
-{
-    @Structure
-    private UnitOfWorkFactory uowf;
-
-    public void render( QuikitContext context )
-    {
-        UnitOfWork uow = uowf.newUnitOfWork();
-        try
-        {
-            next.render( context );
-            uow.complete();
-        }
-        catch( Throwable e )
-        {
-            uow.discard();
-        }
-    }
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/web/QuikitContext.java b/samples/rental/src/main/java/org/qi4j/sample/rental/web/QuikitContext.java
deleted file mode 100644
index 47c29a0..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/web/QuikitContext.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.web;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-public interface QuikitContext
-{
-
-    Page page();
-
-    String methodName();
-
-    Document dom();
-
-    Element element();
-
-    Element parentElement();
-
-    /**
-     * Returns the request path, with the mountpoint removed.
-     *
-     * @return The request path.
-     */
-    String path();
-
-    /**
-     * Returns the queryString from the URL.
-     *
-     * @return the query string of the URL, i.e. the content after the question mark "?".
-     */
-    String queryString();
-
-    /**
-     * Returns the header from the request.
-     *
-     * @param headerKey the name of the header.
-     *
-     * @return the Header value of the named header.
-     */
-    String getHeader( String headerKey );
-
-    /**
-     * Returns the data of the request.
-     *
-     * @return the data part of the request.
-     */
-    byte[] data()
-        throws RenderException;
-
-    void setDynamic( String method, Element element, Element parent );
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/web/QuikitResolver.java b/samples/rental/src/main/java/org/qi4j/sample/rental/web/QuikitResolver.java
deleted file mode 100644
index e6fb2b6..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/web/QuikitResolver.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.web;
-
-import java.io.BufferedInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Properties;
-import javax.xml.parsers.DocumentBuilder;
-import org.w3c.dom.DOMImplementation;
-import org.w3c.dom.bootstrap.DOMImplementationRegistry;
-import org.w3c.dom.ls.DOMImplementationLS;
-import org.w3c.dom.ls.LSInput;
-import org.w3c.dom.ls.LSResourceResolver;
-import org.xml.sax.EntityResolver;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
-public class QuikitResolver
-    implements LSResourceResolver, EntityResolver
-{
-    private Properties local;
-    private final DocumentBuilder builder;
-
-    public QuikitResolver( DocumentBuilder builder )
-    {
-        this.builder = builder;
-        local = new Properties();
-        try
-        {
-            InputStream stream = getClass().getClassLoader().getResourceAsStream( "resolve.properties" );
-            BufferedInputStream in = new BufferedInputStream( stream );
-            local.load( in );
-        }
-        catch( FileNotFoundException e )
-        {
-            e.printStackTrace();
-        }
-        catch( IOException e )
-        {
-            e.printStackTrace();
-        }
-    }
-
-    public InputSource resolveEntity( String publicId, String systemId )
-        throws SAXException, IOException
-    {
-        String resourceName = local.getProperty( publicId );
-        if( resourceName == null )
-        {
-            System.out.println( "Not locally available: " + publicId + "  " + systemId );
-            return null;
-        }
-        InputStream in = getClass().getClassLoader().getResourceAsStream( resourceName );
-        return new InputSource( in );
-    }
-
-    public LSInput resolveResource( String type, String namespaceURI, String publicId, String systemId, String baseURI )
-    {
-        String resourceName = local.getProperty( systemId );
-        if( resourceName == null )
-        {
-            System.out.println( "type: " + type );
-            System.out.println( "namespaceURI: " + namespaceURI );
-            System.out.println( "publicId: " + publicId );
-            System.out.println( "systemId: " + systemId );
-            System.out.println( "baseURI: " + baseURI );
-            return null;
-        }
-
-        InputStream resource = getClass().getClassLoader().getResourceAsStream( resourceName );
-        LSInput input;
-        try
-        {
-            input = getLSInput();
-        }
-        catch( Exception e )
-        {
-            throw new UnsupportedOperationException( "Internal problem. Please report to qi4j-dev forum at Google Groups.", e  );
-        }
-        input.setBaseURI( baseURI );
-        input.setByteStream( resource );
-        input.setPublicId( publicId );
-        input.setSystemId( systemId );
-        return input;
-    }
-
-    private LSInput getLSInput() throws Exception {
-        DOMImplementationLS impl;
-        DOMImplementation docImpl = builder.getDOMImplementation();
-        // Try to get the DOMImplementation from doc first before
-        // defaulting to the sun implementation.
-        if (docImpl != null && docImpl.hasFeature("LS", "3.0")) {
-            impl = (DOMImplementationLS)docImpl.getFeature("LS", "3.0");
-        } else {
-            DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
-            impl = (DOMImplementationLS)registry.getDOMImplementation("LS");
-            if (impl == null) {
-                System.setProperty(DOMImplementationRegistry.PROPERTY,
-                                   "com.sun.org.apache.xerces.internal.dom.DOMImplementationSourceImpl");
-                registry = DOMImplementationRegistry.newInstance();
-                impl = (DOMImplementationLS)registry.getDOMImplementation("LS");
-            }
-        }
-        return impl.createLSInput();
-    }
-
-
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/web/QuikitServlet.java b/samples/rental/src/main/java/org/qi4j/sample/rental/web/QuikitServlet.java
deleted file mode 100644
index f43328b..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/web/QuikitServlet.java
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.web;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Map;
-import java.util.TreeMap;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.Source;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import javax.xml.transform.stream.StreamSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.SchemaFactory;
-import org.qi4j.api.Qi4j;
-import org.qi4j.api.composite.Composite;
-import org.qi4j.api.service.ServiceFinder;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.Energy4Java;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.xml.sax.EntityResolver;
-import org.xml.sax.SAXException;
-
-import static org.qi4j.functional.Iterables.first;
-
-public class QuikitServlet
-    extends HttpServlet
-{
-    private Application application;
-    private ServiceFinder finder;
-    private UrlService urlService;
-    private DocumentBuilderFactory documentFactory;
-    private TreeMap<String, Page> mountPoints;
-
-    @Override
-    public void init( ServletConfig config )
-        throws ServletException
-    {
-        try
-        {
-            mountPoints = new TreeMap<String, Page>();
-            documentFactory = DocumentBuilderFactory.newInstance();
-            documentFactory.setNamespaceAware( true );
-            ClassLoader cl = getClass().getClassLoader();
-            SchemaFactory schemaFactory = SchemaFactory.newInstance( "http://www.w3.org/2001/XMLSchema" );
-            Source[] schemaSources = new Source[ 2 ];
-            schemaSources[ 0 ] = new StreamSource( cl.getResourceAsStream( "xhtml1-strict.xsd" ) );
-            schemaSources[ 1 ] = new StreamSource( cl.getResourceAsStream( "xml.xsd" ) );
-            Schema schema = schemaFactory.newSchema( schemaSources );
-            documentFactory.setSchema( schema );
-
-            ApplicationAssembler assembler = createApplicationAssembler( config );
-
-            Energy4Java qi4j = new Energy4Java();
-            application = qi4j.newApplication( assembler );
-            application.activate();
-            Module module = application.findModule( "WebLayer", "PagesModule" );
-            finder = module;
-
-            if( application.mode() == Application.Mode.development )
-            {
-                DataInitializer initializer = module.newTransient( DataInitializer.class );
-                initializer.initialize();
-            }
-            Iterable<ServiceReference<Page>> iterable = finder.findServices( Page.class );
-            for( ServiceReference<Page> page : iterable )
-            {
-                PageMetaInfo pageMetaInfo = page.metaInfo( PageMetaInfo.class );
-                String mountPoint = pageMetaInfo.mountPoint();
-                mountPoints.put( mountPoint, page.get() );
-            }
-        }
-        catch( Exception e )
-        {
-            throw new ServletException( "Can not initialize Zest.", e );
-        }
-    }
-
-    private ApplicationAssembler createApplicationAssembler( ServletConfig config )
-        throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException
-    {
-        String assemblerClassname = config.getInitParameter( "qi4j-assembler" );
-        ClassLoader loader = getClass().getClassLoader();
-        Class<?> assemblerClass = loader.loadClass( assemblerClassname );
-        ApplicationAssembler assembler;
-        Constructor cons = assemblerClass.getConstructor( Application.Mode.class );
-        if( cons == null )
-        {
-            assembler = (ApplicationAssembler) assemblerClass.newInstance();
-        }
-        else
-        {
-            Application.Mode mode;
-            String modeSetting = config.getInitParameter( "qi4j-application-mode" );
-            if( modeSetting == null )
-            {
-                mode = Application.Mode.development;
-            }
-            else
-            {
-                mode = Application.Mode.valueOf( modeSetting );
-            }
-            assembler = (ApplicationAssembler) cons.newInstance( mode );
-        }
-        return assembler;
-    }
-
-    @Override
-    public void destroy()
-    {
-        try
-        {
-            application.passivate();
-        }
-        catch( Exception e )
-        {
-            throw new RuntimeException( "Problem to passivate Zest", e );
-        }
-    }
-
-    @Override
-    protected void doGet( HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse )
-        throws ServletException, IOException
-    {
-        String path = httpServletRequest.getPathInfo();
-        if( urlService == null )
-        {
-            urlService = finder.findService( UrlService.class ).get();
-            String uri = httpServletRequest.getRequestURI();
-            String basePath = uri.substring( 0, uri.length() - path.length() );
-            urlService.registerBaseUri( basePath );
-        }
-        PrintWriter output = httpServletResponse.getWriter();
-        while( path.startsWith( "//" ) )
-        {
-            path = path.substring( 1 );
-        }
-        for( Map.Entry<String, Page> entry : mountPoints.entrySet() )
-        {
-            if( path.startsWith( entry.getKey() ) )
-            {
-                Page page = entry.getValue();
-                String subPath = path.substring( entry.getKey().length() );
-                try
-                {
-                    renderPage( page, subPath, output, httpServletRequest );
-                }
-                catch( Exception e )
-                {
-                    throw new ServletException( e );
-                }
-                break;
-            }
-        }
-        output.flush();
-    }
-
-    private void renderPage( Page page, String path, PrintWriter output, HttpServletRequest httpRequest )
-        throws ParserConfigurationException, SAXException, IOException, RenderException, TransformerException
-    {
-        Class<? extends Composite> pageClass = (Class<Composite>) first( Qi4j.FUNCTION_DESCRIPTOR_FOR
-                                                                             .map( page ).types() );
-
-        String pageName = pageClass.getSimpleName() + ".html";
-        DocumentBuilder documentBuilder = documentFactory.newDocumentBuilder();
-        documentBuilder.setEntityResolver( createEntityResolver( documentBuilder ) );
-        InputStream pageResource = pageClass.getResourceAsStream( pageName );
-        Document dom = documentBuilder.parse( pageResource );
-        try
-        {
-            Context context = new Context( dom, page, path, httpRequest );
-            page.render( context );
-        }
-        catch( Throwable e )
-        {
-            error( dom, e );
-        }
-        DOMSource source = new DOMSource( dom );
-        StreamResult result = new StreamResult( output );
-        Transformer transformer = TransformerFactory.newInstance().newTransformer();
-        transformer.transform( source, result );
-        output.flush();
-    }
-
-    private EntityResolver createEntityResolver( DocumentBuilder builder )
-        throws SAXException
-    {
-        QuikitResolver quickitResolver = new QuikitResolver( builder );
-        SchemaFactory schemaFactory = SchemaFactory.newInstance( "http://www.w3.org/2001/XMLSchema" );
-        schemaFactory.setResourceResolver( quickitResolver );
-        return quickitResolver;
-    }
-
-    private void error( Document dom, Throwable exception )
-    {
-        Element root = dom.getDocumentElement();
-        dom.removeChild( root );
-        Element preElement = (Element) dom.appendChild( dom.createElementNS( Page.XHTML, "html" ) )
-            .appendChild( dom.createElementNS( Page.XHTML, "body" ) )
-            .appendChild( dom.createElementNS( Page.XHTML, "code" ) )
-            .appendChild( dom.createElementNS( Page.XHTML, "pre" ) );
-
-        StringWriter stringWriter = new StringWriter( 2000 );
-        PrintWriter writer = new PrintWriter( stringWriter );
-        exception.printStackTrace( writer );
-        writer.close();
-        String content = stringWriter.getBuffer().toString();
-        preElement.setTextContent( content );
-    }
-
-    static class Context
-        implements QuikitContext
-    {
-        private final Page page;
-        private String methodName;
-        private Element element;
-        private Element parentElement;
-        private final Document dom;
-        private final String path;
-        private final HttpServletRequest request;
-        private byte[] data = null;
-
-        public Context( Document dom, Page page, String path, HttpServletRequest httpServletRequest )
-        {
-            this.dom = dom;
-            this.page = page;
-            this.path = path;
-            this.request = httpServletRequest;
-        }
-
-        public Page page()
-        {
-            return page;
-        }
-
-        public String methodName()
-        {
-            return methodName;
-        }
-
-        public Document dom()
-        {
-            return dom;
-        }
-
-        public Element element()
-        {
-            return element;
-        }
-
-        public Element parentElement()
-        {
-            return parentElement;
-        }
-
-        public String path()
-        {
-            return path;
-        }
-
-        public String queryString()
-        {
-            return request.getQueryString();
-        }
-
-        public String getHeader( String headerKey )
-        {
-            return request.getHeader( headerKey );
-        }
-
-        public byte[] data()
-            throws RenderException
-        {
-            if( data == null )
-            {
-                try
-                {
-                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                    InputStream in = request.getInputStream();
-                    int i;
-                    while( ( i = in.read() ) != -1 )
-                    {
-                        baos.write( i );
-                    }
-                    data = baos.toByteArray();
-                }
-                catch( IOException e )
-                {
-                    throw new RenderException( "I/O problems.", e );
-                }
-            }
-            return data;
-        }
-
-        public void setDynamic( String method, Element element, Element parent )
-        {
-            this.methodName = method;
-            this.element = element;
-            this.parentElement = parent;
-        }
-    }
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/web/RenderException.java b/samples/rental/src/main/java/org/qi4j/sample/rental/web/RenderException.java
deleted file mode 100644
index 1554575..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/web/RenderException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.web;
-
-import javax.servlet.ServletException;
-
-public class RenderException
-    extends ServletException
-{
-    public RenderException( String message )
-    {
-        super( message );
-    }
-
-    public RenderException( String message, Throwable throwable )
-    {
-        super( message, throwable );
-    }
-
-    public RenderException( Throwable throwable )
-    {
-        super( throwable );
-    }
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/web/UrlService.java b/samples/rental/src/main/java/org/qi4j/sample/rental/web/UrlService.java
deleted file mode 100644
index 0cf2181..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/web/UrlService.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.web;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.spi.Qi4jSPI;
-
-@Mixins( UrlService.UrlServiceMixin.class )
-public interface UrlService
-    extends ServiceComposite
-{
-    void registerBaseUri( String baseUri );
-
-    String createLink( Page page );
-
-    static abstract class UrlServiceMixin
-        implements UrlService
-    {
-        @Structure
-        Qi4jSPI spi;
-
-        private String baseUri;
-
-        public void registerBaseUri( String baseUri )
-        {
-            this.baseUri = baseUri;
-        }
-
-        public String createLink( Page page )
-        {
-            String mountPoint = spi.serviceDescriptorFor( page ).metaInfo( PageMetaInfo.class ).mountPoint();
-            return baseUri + mountPoint;
-        }
-    }
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/web/assembly/PagesModule.java b/samples/rental/src/main/java/org/qi4j/sample/rental/web/assembly/PagesModule.java
deleted file mode 100644
index bc71fda..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/web/assembly/PagesModule.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.web.assembly;
-
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.sample.rental.web.BookingPage;
-import org.qi4j.sample.rental.web.MainPage;
-import org.qi4j.sample.rental.web.PageMetaInfo;
-import org.qi4j.sample.rental.web.UrlService;
-
-public class PagesModule
-    implements Assembler
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        PageMetaInfo mainpageMeta = new PageMetaInfo( "main" );
-        module.services( MainPage.class ).setMetaInfo( mainpageMeta );
-
-        PageMetaInfo bookingpageMeta = new PageMetaInfo( "booking" );
-        module.services( BookingPage.class ).setMetaInfo( bookingpageMeta );
-
-        module.services( UrlService.class );
-    }
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/web/assembly/RentalApplicationAssembler.java b/samples/rental/src/main/java/org/qi4j/sample/rental/web/assembly/RentalApplicationAssembler.java
deleted file mode 100644
index 3824a0c..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/web/assembly/RentalApplicationAssembler.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.web.assembly;
-
-import org.qi4j.api.structure.Application;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.ApplicationAssemblyFactory;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.LayerAssembly;
-
-public class RentalApplicationAssembler
-    implements ApplicationAssembler
-{
-    private Application.Mode mode;
-
-    public RentalApplicationAssembler( Application.Mode mode )
-    {
-        this.mode = mode;
-    }
-
-    @Override
-    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-        throws AssemblyException
-    {
-        ApplicationAssembly assembly = applicationFactory.newApplicationAssembly();
-        assembly.setMode( mode );
-        LayerAssembly webLayer = assembly.layer( "WebLayer" );
-        new PagesModule().assemble( webLayer.module( "PagesModule" ) );
-        LayerAssembly domainLayer = assembly.layer( "DomainLayer" );
-        new RentalModule().assemble( domainLayer.module( "RentalModule" ) );
-        LayerAssembly infraLayer = assembly.layer( "InfraLayer" );
-        new StorageModule().assemble( infraLayer.module( "StorageModule" ) );
-
-        webLayer.uses( domainLayer );
-        domainLayer.uses( infraLayer );
-        return assembly;
-    }
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/web/assembly/RentalModule.java b/samples/rental/src/main/java/org/qi4j/sample/rental/web/assembly/RentalModule.java
deleted file mode 100644
index a09001c..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/web/assembly/RentalModule.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.web.assembly;
-
-import org.qi4j.api.structure.Application;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.sample.rental.domain.Address;
-import org.qi4j.sample.rental.domain.Booking;
-import org.qi4j.sample.rental.domain.Car;
-import org.qi4j.sample.rental.domain.CarCategory;
-import org.qi4j.sample.rental.domain.Customer;
-import org.qi4j.sample.rental.domain.Period;
-import org.qi4j.sample.rental.domain.RentalShop;
-import org.qi4j.sample.rental.domain.dev.InitialData;
-
-import static org.qi4j.api.common.Visibility.application;
-
-public class RentalModule
-    implements Assembler
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( Booking.class, Car.class, Customer.class, CarCategory.class ).visibleIn( application );
-        module.values( Address.class, Period.class );
-        module.entities( RentalShop.class ).visibleIn( application );
-
-        if( module.layer().application().mode().equals( Application.Mode.development ) )
-        {
-            module.transients( InitialData.class ).visibleIn( application );
-        }
-    }
-}
diff --git a/samples/rental/src/main/java/org/qi4j/sample/rental/web/assembly/StorageModule.java b/samples/rental/src/main/java/org/qi4j/sample/rental/web/assembly/StorageModule.java
deleted file mode 100644
index 71212cc..0000000
--- a/samples/rental/src/main/java/org/qi4j/sample/rental/web/assembly/StorageModule.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.sample.rental.web.assembly;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.functional.Function;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class StorageModule
-    implements Assembler
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( MemoryEntityStoreService.class ).visibleIn( Visibility.application );
-        module.services( UuidIdentityGeneratorService.class ).visibleIn( Visibility.application );
-        new OrgJsonValueSerializationAssembler().
-            visibleIn( Visibility.application ).
-            withValuesModuleFinder( new Function<Application, Module>()
-        {
-            @Override
-            public Module map( Application app )
-            {
-                return app.findModule( "DomainLayer", "RentalModule" );
-            }
-        } ).
-            assemble( module );
-    }
-}
diff --git a/samples/rental/src/main/resources/org/apache/polygene/sample/rental/index.html b/samples/rental/src/main/resources/org/apache/polygene/sample/rental/index.html
new file mode 100644
index 0000000..4594096
--- /dev/null
+++ b/samples/rental/src/main/resources/org/apache/polygene/sample/rental/index.html
@@ -0,0 +1,19 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
diff --git a/samples/rental/src/main/resources/org/apache/polygene/sample/rental/web/BookingPage.html b/samples/rental/src/main/resources/org/apache/polygene/sample/rental/web/BookingPage.html
new file mode 100644
index 0000000..3c1b5b8
--- /dev/null
+++ b/samples/rental/src/main/resources/org/apache/polygene/sample/rental/web/BookingPage.html
@@ -0,0 +1,51 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"
+      xmlns:qi="http://polygene.apache.org/ns/2009/quikit"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.w3.org/1999/xhtml
+                          http://www.w3.org/2002/08/xhtml/xhtml1-strict.xsd">
+<body>
+<h3>Booking - <span id="refNo">EB542D</span></h3>
+
+<div><strong>Customer:</strong>
+
+    <div qi:method="customer">
+        <div qi:method="name">Niclas Hedhman</div>
+        <div qi:method="line1">B-7-6, Megan Avenue 1</div>
+        <div qi:method="line2">189, Jalan Tun Razak</div>
+        <div><span qi:method="zipCode">50400</span><span qi:method="city">Kuala Lumpur</span></div>
+        <div qi:method="country">Malaysia</div>
+    </div>
+</div>
+
+<p></p>
+
+<div><strong>Car:</strong>
+
+    <div qi:method="car">
+        <div qi:method="carModel">Mini Cooper S</div>
+        <div qi:method="licensePlate">ABC123</div>
+        <div qi:method="category">Compact</div>
+    </div>
+</div>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/samples/rental/src/main/resources/org/apache/polygene/sample/rental/web/MainPage.html b/samples/rental/src/main/resources/org/apache/polygene/sample/rental/web/MainPage.html
new file mode 100644
index 0000000..895a36c
--- /dev/null
+++ b/samples/rental/src/main/resources/org/apache/polygene/sample/rental/web/MainPage.html
@@ -0,0 +1,32 @@
+<?xml version="1.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.
+  ~
+  ~
+  -->
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"
+      xmlns:qi="http://polygene.apache.org/ns/2009/quikit"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://www.w3.org/1999/xhtml
+                          http://www.w3.org/2002/08/xhtml/xhtml1-strict.xsd">
+<head>
+
+</head>
+<body>
+<ul qi:method="bookings"/>
+</body>
+</html>
\ No newline at end of file
diff --git a/samples/rental/src/main/resources/org/qi4j/sample/rental/index.html b/samples/rental/src/main/resources/org/qi4j/sample/rental/index.html
deleted file mode 100644
index a8f6a82..0000000
--- a/samples/rental/src/main/resources/org/qi4j/sample/rental/index.html
+++ /dev/null
@@ -1,16 +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.
--->
diff --git a/samples/rental/src/main/resources/org/qi4j/sample/rental/web/BookingPage.html b/samples/rental/src/main/resources/org/qi4j/sample/rental/web/BookingPage.html
deleted file mode 100644
index e777524..0000000
--- a/samples/rental/src/main/resources/org/qi4j/sample/rental/web/BookingPage.html
+++ /dev/null
@@ -1,48 +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.
--->
-<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"
-      xmlns:qi="http://www.qi4j.org/ns/2009/quikit"
-      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-      xsi:schemaLocation="http://www.w3.org/1999/xhtml
-                          http://www.w3.org/2002/08/xhtml/xhtml1-strict.xsd">
-<body>
-<h3>Booking - <span id="refNo">EB542D</span></h3>
-
-<div><strong>Customer:</strong>
-
-    <div qi:method="customer">
-        <div qi:method="name">Niclas Hedhman</div>
-        <div qi:method="line1">B-7-6, Megan Avenue 1</div>
-        <div qi:method="line2">189, Jalan Tun Razak</div>
-        <div><span qi:method="zipCode">50400</span><span qi:method="city">Kuala Lumpur</span></div>
-        <div qi:method="country">Malaysia</div>
-    </div>
-</div>
-
-<p></p>
-
-<div><strong>Car:</strong>
-
-    <div qi:method="car">
-        <div qi:method="carModel">Mini Cooper S</div>
-        <div qi:method="licensePlate">ABC123</div>
-        <div qi:method="category">Compact</div>
-    </div>
-</div>
-</body>
-
-</html>
\ No newline at end of file
diff --git a/samples/rental/src/main/resources/org/qi4j/sample/rental/web/MainPage.html b/samples/rental/src/main/resources/org/qi4j/sample/rental/web/MainPage.html
deleted file mode 100644
index a86b8ad..0000000
--- a/samples/rental/src/main/resources/org/qi4j/sample/rental/web/MainPage.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.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.
--->
-<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"
-      xmlns:qi="http://www.qi4j.org/ns/2009/quikit"
-      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-      xsi:schemaLocation="http://www.w3.org/1999/xhtml
-                          http://www.w3.org/2002/08/xhtml/xhtml1-strict.xsd">
-<head>
-
-</head>
-<body>
-<ul qi:method="bookings"/>
-</body>
-</html>
\ No newline at end of file
diff --git a/samples/rental/src/main/resources/resolve.properties b/samples/rental/src/main/resources/resolve.properties
index 0184c5d..47c205a 100644
--- a/samples/rental/src/main/resources/resolve.properties
+++ b/samples/rental/src/main/resources/resolve.properties
@@ -1,17 +1,22 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 http\://www.w3.org/2002/08/xhtml/xhtml1-strict.xsd=xhtml1-strict.xsd
 http\://www.w3.org/2001/xml.xsd=xml.xsd
\ No newline at end of file
diff --git a/samples/rental/src/main/resources/xhtml1-strict.xsd b/samples/rental/src/main/resources/xhtml1-strict.xsd
index 9f52685..bdef343 100644
--- a/samples/rental/src/main/resources/xhtml1-strict.xsd
+++ b/samples/rental/src/main/resources/xhtml1-strict.xsd
@@ -1,4 +1,24 @@
 <?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <xs:schema version="1.0"
            xml:lang="en"
            xmlns:xs="http://www.w3.org/2001/XMLSchema"
diff --git a/samples/rental/src/main/resources/xml.xsd b/samples/rental/src/main/resources/xml.xsd
index 62ebda2..7397d45 100644
--- a/samples/rental/src/main/resources/xml.xsd
+++ b/samples/rental/src/main/resources/xml.xsd
@@ -1,4 +1,24 @@
 <?xml version='1.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.
+  ~
+  ~
+  -->
+
 <xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace"
            xmlns:xs="http://www.w3.org/2001/XMLSchema"
            xmlns="http://www.w3.org/1999/xhtml"
diff --git a/samples/rental/src/main/webapp/WEB-INF/web.xml b/samples/rental/src/main/webapp/WEB-INF/web.xml
index 67a2248..02e4228 100644
--- a/samples/rental/src/main/webapp/WEB-INF/web.xml
+++ b/samples/rental/src/main/webapp/WEB-INF/web.xml
@@ -1,20 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <web-app xmlns="http://java.sun.com/xml/ns/javaee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
@@ -24,10 +27,10 @@
   <servlet>
     <display-name>Quikit Web Application Framework</display-name>
     <servlet-name>QuikitServlet</servlet-name>
-    <servlet-class>org.qi4j.sample.rental.web.QuikitServlet</servlet-class>
+    <servlet-class>org.apache.polygene.sample.rental.web.QuikitServlet</servlet-class>
     <init-param>
-      <param-name>qi4j-assembler</param-name>
-      <param-value>org.qi4j.sample.rental.web.assembly.RentalApplicationAssembler</param-value>
+      <param-name>polygene-assembler</param-name>
+      <param-value>org.apache.polygene.sample.rental.web.assembly.RentalApplicationAssembler</param-value>
     </init-param>
     <load-on-startup>1</load-on-startup>
   </servlet>
diff --git a/samples/sql-support/build.gradle b/samples/sql-support/build.gradle
index 21eba5b..1be908e 100644
--- a/samples/sql-support/build.gradle
+++ b/samples/sql-support/build.gradle
@@ -1,41 +1,46 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
+import org.apache.polygene.gradle.TaskGroups
+
+apply plugin: 'polygene-sample'
 
 description = "SQL Support Sample."
 
-jar { manifest { name = "Apache Zest™ Sample - SQL Support" }}
+jar { manifest { name = "Apache Polygene™ Sample - SQL Support" } }
 
 dependencies {
 
-    compile project( ":org.qi4j.core:org.qi4j.core.bootstrap" )
-    compile project( ":org.qi4j.libraries:org.qi4j.library.sql-dbcp" )
-    compile project( ":org.qi4j.extensions:org.qi4j.extension.entitystore-preferences" )
-    compile project( ":org.qi4j.extensions:org.qi4j.extension.entitystore-sql" )
-    compile project( ":org.qi4j.extensions:org.qi4j.extension.indexing-sql" )
+  implementation polygene.core.bootstrap
+  implementation polygene.library( 'sql-dbcp' )
+  implementation polygene.extension( 'entitystore-preferences' )
+  implementation polygene.extension( 'entitystore-sql' )
+  implementation polygene.extension( 'indexing-sql' )
 
-    runtime project(":org.qi4j.core:org.qi4j.core.runtime")
-    runtime libraries.postgres
-    runtime libraries.slf4j_simple
-
+  runtimeOnly polygene.core.runtime
+  runtimeOnly libraries.postgres
+  runtimeOnly libraries.logback
 }
 
-task( runSample, dependsOn: 'classes', type: JavaExec ) {
-    main = 'org.qi4j.sample.sqlsupport.Main'
-    classpath = sourceSets.main.runtimeClasspath
+task( runSqlSupportSample, dependsOn: 'classes', type: JavaExec ) {
+  group = TaskGroups.SAMPLES
+  description = "Runs $project.name sample."
+  main = 'org.apache.polygene.sample.sqlsupport.Main'
+  classpath = sourceSets.main.runtimeClasspath
 }
diff --git a/samples/sql-support/src/main/java/org/apache/polygene/sample/sqlsupport/AppAssembler.java b/samples/sql-support/src/main/java/org/apache/polygene/sample/sqlsupport/AppAssembler.java
new file mode 100644
index 0000000..9c9fee6
--- /dev/null
+++ b/samples/sql-support/src/main/java/org/apache/polygene/sample/sqlsupport/AppAssembler.java
@@ -0,0 +1,113 @@
+/*
+ *  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.polygene.sample.sqlsupport;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+import org.apache.polygene.entitystore.sql.assembly.PostgreSQLEntityStoreAssembler;
+import org.apache.polygene.index.sql.assembly.PostgreSQLIndexQueryAssembler;
+import org.apache.polygene.library.sql.assembly.DataSourceAssembler;
+import org.apache.polygene.library.sql.datasource.DataSources;
+import org.apache.polygene.library.sql.dbcp.DBCPDataSourceServiceAssembler;
+
+/**
+ * Assemble the Application.
+ *
+ * Use SQL EntityStore and SQL Index/Query for Persistence using PostgreSQL.
+ * EntityStore and Index/Query use different DataSource in order to allow splitting the two in two servers/databases.
+ */
+public class AppAssembler
+    implements ApplicationAssembler
+{
+
+    @Override
+    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+        throws AssemblyException
+    {
+        ApplicationAssembly appAss = applicationFactory.newApplicationAssembly();
+        appAss.setName( "SQL Support Sample" );
+
+        // Config
+        LayerAssembly configLayer = appAss.layer( "config" );
+        ModuleAssembly configModule = configLayer.module( "config" );
+        {
+            configModule.services( MemoryEntityStoreService.class ).
+                visibleIn( Visibility.module );
+            // Use a PreferenceEntityStore instead if you want the configuration to be persistent
+            // new PreferenceEntityStoreAssembler( Visibility.module ).assemble( configModule );
+        }
+
+        // Infra
+        LayerAssembly infraLayer = appAss.layer( "infra" );
+        ModuleAssembly persistenceModule = infraLayer.module( "persistence" );
+        {
+            // SQL DataSource Service
+            String dataSourceServiceIdentity = "postgresql-datasource-service";
+            new DBCPDataSourceServiceAssembler().
+                identifiedBy( dataSourceServiceIdentity ).
+                visibleIn( Visibility.module ).
+                withConfig( configModule, Visibility.application ).
+                assemble( persistenceModule );
+
+            // SQL EntityStore DataSource and Service
+            new DataSourceAssembler().
+                withDataSourceServiceIdentity( dataSourceServiceIdentity ).
+                identifiedBy( "postgresql-es-datasource" ).
+                visibleIn( Visibility.module ).
+                withCircuitBreaker( DataSources.newDataSourceCircuitBreaker() ).assemble( persistenceModule );
+            new PostgreSQLEntityStoreAssembler().
+                visibleIn( Visibility.application ).
+                withConfig( configModule, Visibility.application ).
+                assemble( persistenceModule );
+
+            // SQL Index/Query DataSource and Service
+            new DataSourceAssembler().
+                withDataSourceServiceIdentity( dataSourceServiceIdentity ).
+                identifiedBy( "postgresql-index-datasource" ).
+                visibleIn( Visibility.module ).
+                withCircuitBreaker().
+                assemble( persistenceModule );
+            new PostgreSQLIndexQueryAssembler().
+                visibleIn( Visibility.application ).
+                withConfig( configModule, Visibility.application ).
+                assemble( persistenceModule );
+        }
+
+        // App
+        LayerAssembly appLayer = appAss.layer( "app" );
+        ModuleAssembly domainModule = appLayer.module( "domain" );
+        {
+            domainModule.entities( PretextEntity.class );
+        }
+
+        // Uses
+        infraLayer.uses( configLayer );
+        appLayer.uses( infraLayer );
+
+        return appAss;
+    }
+
+}
diff --git a/samples/sql-support/src/main/java/org/apache/polygene/sample/sqlsupport/Main.java b/samples/sql-support/src/main/java/org/apache/polygene/sample/sqlsupport/Main.java
new file mode 100644
index 0000000..5a96f31
--- /dev/null
+++ b/samples/sql-support/src/main/java/org/apache/polygene/sample/sqlsupport/Main.java
@@ -0,0 +1,160 @@
+/*
+ *  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.polygene.sample.sqlsupport;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+import javax.sql.DataSource;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.entitystore.sql.assembly.PostgreSQLEntityStoreAssembler;
+import org.apache.polygene.index.sql.assembly.PostgreSQLIndexQueryAssembler;
+import org.apache.polygene.library.sql.common.SQLConfiguration;
+import org.apache.polygene.library.sql.common.SQLUtil;
+
+import static org.apache.polygene.api.query.QueryExpressions.eq;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+
+/**
+ * SQL Support Sample Main Class.
+ * <p><strong>psql postgres</strong></p>
+ * <p>CREATE USER jdbc_test_login WITH PASSWORD 'password';</p>
+ * <p>CREATE DATABASE jdbc_test_db;</p>
+ * <p>GRANT ALL PRIVILEGES ON DATABASE jdbc_test_db TO jdbc_test_login;</p>
+ * <p><strong>psql -d jdbc_test_db</strong></p>
+ * <p>CREATE EXTENSION ltree;</p>
+ */
+public class Main
+{
+
+    public static void main( String[] args )
+            throws Exception
+    {
+        final Application application = new Energy4Java().newApplication( new AppAssembler() );
+        application.activate();
+        Runtime.getRuntime().addShutdownHook( new Thread( new Runnable()
+        {
+            @Override
+            @SuppressWarnings( "CallToThreadDumpStack" )
+            public void run()
+            {
+                try {
+                    application.passivate();
+                } catch ( Exception ex ) {
+                    System.err.println( "Unable to passivate Polygene application!" );
+                    ex.printStackTrace();
+                }
+            }
+
+        } ) );
+        Module domainModule = application.findModule( "app", "domain" );
+
+        int exitStatus = 0;
+
+        try {
+
+            UnitOfWork uow = domainModule.unitOfWorkFactory().newUnitOfWork();
+            EntityBuilder<PretextEntity> builder = uow.newEntityBuilder( PretextEntity.class );
+            PretextEntity pretext = builder.instance();
+            pretext.reason().set( "Testing purpose" );
+            builder.newInstance();
+            uow.complete();
+
+            uow = domainModule.unitOfWorkFactory().newUnitOfWork();
+            QueryBuilder<PretextEntity> queryBuilder = domainModule.newQueryBuilder( PretextEntity.class );
+            queryBuilder = queryBuilder.where( eq( templateFor( PretextEntity.class ).reason(), "Testing purpose" ) );
+            Query<PretextEntity> query = uow.newQuery( queryBuilder );
+            pretext = query.find();
+            if ( pretext == null ) {
+                System.err.println( "ERROR: Unable to find pretext!" );
+                exitStatus = -1;
+            } else {
+                System.out.println( "SUCCESS: Found Pretext with reason: " + pretext.reason().get() );
+            }
+            uow.discard();
+
+        } finally {
+            deleteData( application.findModule( "infra", "persistence" ) );
+        }
+
+        System.exit( exitStatus );
+    }
+
+    /**
+     * Completely delete data so the sample can be run multiple times.
+     */
+    private static void deleteData( Module persistenceModule )
+            throws SQLException
+    {
+        // EntityStore Data
+        {
+            UnitOfWork uow = persistenceModule.unitOfWorkFactory().newUnitOfWork();
+            try {
+                SQLConfiguration config = uow.get( SQLConfiguration.class, PostgreSQLEntityStoreAssembler.DEFAULT_ENTITYSTORE_IDENTITY );
+                Connection connection = persistenceModule.findService( DataSource.class ).get().getConnection();
+                connection.setAutoCommit( false );
+                connection.setReadOnly( false );
+                String schemaName = config.schemaName().get();
+
+                Statement stmt = null;
+                try {
+                    stmt = connection.createStatement();
+                    stmt.execute( "DROP SCHEMA " + schemaName + " CASCADE" );
+                    connection.commit();
+                } finally {
+                    SQLUtil.closeQuietly( stmt );
+                }
+            } finally {
+                uow.discard();
+            }
+        }
+
+        // Indexing Data
+        {
+            UnitOfWork uow = persistenceModule.unitOfWorkFactory().newUnitOfWork();
+            try {
+                SQLConfiguration config = uow.get( SQLConfiguration.class, PostgreSQLIndexQueryAssembler.DEFAULT_IDENTITY  );
+                Connection connection = persistenceModule.findService( DataSource.class ).get().getConnection();
+                connection.setAutoCommit( false );
+                connection.setReadOnly( false );
+                String schemaName = config.schemaName().get();
+
+                Statement stmt = null;
+                try {
+                    stmt = connection.createStatement();
+                    stmt.execute( "DROP SCHEMA " + schemaName + " CASCADE" );
+                    connection.commit();
+                } finally {
+                    SQLUtil.closeQuietly( stmt );
+                    SQLUtil.closeQuietly( connection );
+                }
+            } finally {
+                uow.discard();
+            }
+        }
+    }
+
+}
diff --git a/samples/sql-support/src/main/java/org/apache/polygene/sample/sqlsupport/PretextEntity.java b/samples/sql-support/src/main/java/org/apache/polygene/sample/sqlsupport/PretextEntity.java
new file mode 100644
index 0000000..f487a57
--- /dev/null
+++ b/samples/sql-support/src/main/java/org/apache/polygene/sample/sqlsupport/PretextEntity.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.sample.sqlsupport;
+
+import org.apache.polygene.api.property.Property;
+
+public interface PretextEntity
+{
+
+    Property<String> reason();
+
+}
diff --git a/samples/sql-support/src/main/java/org/qi4j/sample/sqlsupport/AppAssembler.java b/samples/sql-support/src/main/java/org/qi4j/sample/sqlsupport/AppAssembler.java
deleted file mode 100644
index db6a43b..0000000
--- a/samples/sql-support/src/main/java/org/qi4j/sample/sqlsupport/AppAssembler.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.sample.sqlsupport;
-
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.value.ValueSerialization;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.ApplicationAssemblyFactory;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.entitystore.sql.assembly.PostgreSQLEntityStoreAssembler;
-import org.qi4j.index.sql.assembly.PostgreSQLIndexQueryAssembler;
-import org.qi4j.library.sql.assembly.DataSourceAssembler;
-import org.qi4j.library.sql.datasource.DataSources;
-import org.qi4j.library.sql.dbcp.DBCPDataSourceServiceAssembler;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-/**
- * Assemble the Application.
- *
- * Use SQL EntityStore and SQL Index/Query for Persistence using PostgreSQL.
- * EntityStore and Index/Query use different DataSource in order to allow splitting the two in two servers/databases.
- */
-public class AppAssembler
-    implements ApplicationAssembler
-{
-
-    @Override
-    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-        throws AssemblyException
-    {
-        ApplicationAssembly appAss = applicationFactory.newApplicationAssembly();
-        appAss.setName( "SQL Support Sample" );
-
-        // Config
-        LayerAssembly configLayer = appAss.layer( "config" );
-        ModuleAssembly configModule = configLayer.module( "config" );
-        {
-            configModule.services( OrgJsonValueSerializationService.class ).
-                taggedWith( ValueSerialization.Formats.JSON );
-            configModule.services( MemoryEntityStoreService.class ).
-                visibleIn( Visibility.module );
-            // Use a PreferenceEntityStore instead if you want the configuration to be persistent
-            // new PreferenceEntityStoreAssembler( Visibility.module ).assemble( configModule );
-        }
-
-        // Infra
-        LayerAssembly infraLayer = appAss.layer( "infra" );
-        ModuleAssembly persistenceModule = infraLayer.module( "persistence" );
-        {
-            persistenceModule.services( OrgJsonValueSerializationService.class ).
-                taggedWith( ValueSerialization.Formats.JSON );
-
-            // SQL DataSource Service
-            String dataSourceServiceIdentity = "postgresql-datasource-service";
-            new DBCPDataSourceServiceAssembler().
-                identifiedBy( dataSourceServiceIdentity ).
-                visibleIn( Visibility.module ).
-                withConfig( configModule, Visibility.application ).
-                assemble( persistenceModule );
-
-            // SQL EntityStore DataSource and Service
-            new DataSourceAssembler().
-                withDataSourceServiceIdentity( dataSourceServiceIdentity ).
-                identifiedBy( "postgresql-es-datasource" ).
-                visibleIn( Visibility.module ).
-                withCircuitBreaker( DataSources.newDataSourceCircuitBreaker() ).assemble( persistenceModule );
-            new PostgreSQLEntityStoreAssembler().
-                visibleIn( Visibility.application ).
-                withConfig( configModule, Visibility.application ).
-                assemble( persistenceModule );
-
-            // SQL Index/Query DataSource and Service
-            new DataSourceAssembler().
-                withDataSourceServiceIdentity( dataSourceServiceIdentity ).
-                identifiedBy( "postgresql-index-datasource" ).
-                visibleIn( Visibility.module ).
-                withCircuitBreaker().
-                assemble( persistenceModule );
-            new PostgreSQLIndexQueryAssembler().
-                visibleIn( Visibility.application ).
-                withConfig( configModule, Visibility.application ).
-                assemble( persistenceModule );
-        }
-
-        // App
-        LayerAssembly appLayer = appAss.layer( "app" );
-        ModuleAssembly domainModule = appLayer.module( "domain" );
-        {
-            domainModule.entities( PretextEntity.class );
-        }
-
-        // Uses
-        infraLayer.uses( configLayer );
-        appLayer.uses( infraLayer );
-
-        return appAss;
-    }
-
-}
diff --git a/samples/sql-support/src/main/java/org/qi4j/sample/sqlsupport/Main.java b/samples/sql-support/src/main/java/org/qi4j/sample/sqlsupport/Main.java
deleted file mode 100644
index bf529a7..0000000
--- a/samples/sql-support/src/main/java/org/qi4j/sample/sqlsupport/Main.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.sample.sqlsupport;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.Statement;
-import javax.sql.DataSource;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.entitystore.sql.assembly.PostgreSQLEntityStoreAssembler;
-import org.qi4j.entitystore.sql.internal.SQLs;
-import org.qi4j.index.sql.assembly.PostgreSQLIndexQueryAssembler;
-import org.qi4j.index.sql.support.postgresql.PostgreSQLAppStartup;
-import org.qi4j.library.sql.common.SQLConfiguration;
-import org.qi4j.library.sql.common.SQLUtil;
-
-import static org.qi4j.api.query.QueryExpressions.eq;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-/**
- * SQL Support Sample Main Class.
- * <p><strong>psql postgres</strong></p>
- * <p>CREATE USER jdbc_test_login WITH PASSWORD 'password';</p>
- * <p>CREATE DATABASE jdbc_test_db;</p>
- * <p>GRANT ALL PRIVILEGES ON DATABASE jdbc_test_db TO jdbc_test_login;</p>
- * <p><strong>psql -d jdbc_test_db</strong></p>
- * <p>CREATE EXTENSION ltree;</p>
- */
-public class Main
-{
-
-    public static void main( String[] args )
-            throws Exception
-    {
-        final Application application = new Energy4Java().newApplication( new AppAssembler() );
-        application.activate();
-        Runtime.getRuntime().addShutdownHook( new Thread( new Runnable()
-        {
-            @Override
-            @SuppressWarnings( "CallToThreadDumpStack" )
-            public void run()
-            {
-                try {
-                    application.passivate();
-                } catch ( Exception ex ) {
-                    System.err.println( "Unable to passivate Zest application!" );
-                    ex.printStackTrace();
-                }
-            }
-
-        } ) );
-        Module domainModule = application.findModule( "app", "domain" );
-
-        int exitStatus = 0;
-
-        try {
-
-            UnitOfWork uow = domainModule.newUnitOfWork();
-            EntityBuilder<PretextEntity> builder = uow.newEntityBuilder( PretextEntity.class );
-            PretextEntity pretext = builder.instance();
-            pretext.reason().set( "Testing purpose" );
-            builder.newInstance();
-            uow.complete();
-
-            uow = domainModule.newUnitOfWork();
-            QueryBuilder<PretextEntity> queryBuilder = domainModule.newQueryBuilder( PretextEntity.class );
-            queryBuilder = queryBuilder.where( eq( templateFor( PretextEntity.class ).reason(), "Testing purpose" ) );
-            Query<PretextEntity> query = uow.newQuery( queryBuilder );
-            pretext = query.find();
-            if ( pretext == null ) {
-                System.err.println( "ERROR: Unable to find pretext!" );
-                exitStatus = -1;
-            } else {
-                System.out.println( "SUCCESS: Found Pretext with reason: " + pretext.reason().get() );
-            }
-            uow.discard();
-
-        } finally {
-            deleteData( application.findModule( "infra", "persistence" ) );
-        }
-
-        System.exit( exitStatus );
-    }
-
-    /**
-     * Completely delete data so the sample can be run multiple times.
-     */
-    private static void deleteData( Module persistenceModule )
-            throws SQLException
-    {
-        // EntityStore Data
-        {
-            UnitOfWork uow = persistenceModule.newUnitOfWork();
-            try {
-                SQLConfiguration config = uow.get( SQLConfiguration.class,
-                                                   PostgreSQLEntityStoreAssembler.DEFAULT_ENTITYSTORE_IDENTITY );
-                Connection connection = persistenceModule.findService( DataSource.class ).get().getConnection();
-                connection.setAutoCommit( false );
-                connection.setReadOnly( false );
-                String schemaName = config.schemaName().get();
-                if ( schemaName == null ) {
-                    schemaName = SQLs.DEFAULT_SCHEMA_NAME;
-                }
-
-                Statement stmt = null;
-                try {
-                    stmt = connection.createStatement();
-                    stmt.execute( "DROP SCHEMA " + schemaName + " CASCADE" );
-                    connection.commit();
-                } finally {
-                    SQLUtil.closeQuietly( stmt );
-                }
-            } finally {
-                uow.discard();
-            }
-        }
-
-        // Indexing Data
-        {
-            UnitOfWork uow = persistenceModule.newUnitOfWork();
-            try {
-                SQLConfiguration config = uow.get( SQLConfiguration.class, PostgreSQLIndexQueryAssembler.DEFAULT_IDENTITY );
-                Connection connection = persistenceModule.findService( DataSource.class ).get().getConnection();
-                connection.setAutoCommit( false );
-                connection.setReadOnly( false );
-                String schemaName = config.schemaName().get();
-                if ( schemaName == null ) {
-                    schemaName = PostgreSQLAppStartup.DEFAULT_SCHEMA_NAME;
-                }
-
-                Statement stmt = null;
-                try {
-                    stmt = connection.createStatement();
-                    stmt.execute( "DROP SCHEMA " + schemaName + " CASCADE" );
-                    connection.commit();
-                } finally {
-                    SQLUtil.closeQuietly( stmt );
-                    SQLUtil.closeQuietly( connection );
-                }
-            } finally {
-                uow.discard();
-            }
-        }
-    }
-
-}
diff --git a/samples/sql-support/src/main/java/org/qi4j/sample/sqlsupport/PretextEntity.java b/samples/sql-support/src/main/java/org/qi4j/sample/sqlsupport/PretextEntity.java
deleted file mode 100644
index cfc8a2d..0000000
--- a/samples/sql-support/src/main/java/org/qi4j/sample/sqlsupport/PretextEntity.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2010, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.sample.sqlsupport;
-
-import org.qi4j.api.property.Property;
-
-public interface PretextEntity
-{
-
-    Property<String> reason();
-
-}
diff --git a/samples/sql-support/src/main/resources/entitystore-postgresql.properties b/samples/sql-support/src/main/resources/entitystore-postgresql.properties
index ea8d622..48cd452 100644
--- a/samples/sql-support/src/main/resources/entitystore-postgresql.properties
+++ b/samples/sql-support/src/main/resources/entitystore-postgresql.properties
@@ -1,17 +1,22 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 
 schemaName=sql_sample_entitystore
diff --git a/samples/sql-support/src/main/resources/indexing-sql.properties b/samples/sql-support/src/main/resources/indexing-sql.properties
index 83c837a..700b84f 100644
--- a/samples/sql-support/src/main/resources/indexing-sql.properties
+++ b/samples/sql-support/src/main/resources/indexing-sql.properties
@@ -1,17 +1,22 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 
 schemaName=sql_sample_indexing
diff --git a/samples/sql-support/src/main/resources/postgresql-es-datasource.properties b/samples/sql-support/src/main/resources/postgresql-es-datasource.properties
index f7d7ad5..ea16c45 100644
--- a/samples/sql-support/src/main/resources/postgresql-es-datasource.properties
+++ b/samples/sql-support/src/main/resources/postgresql-es-datasource.properties
@@ -1,17 +1,22 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 enabled=true
 url=jdbc:postgresql://localhost:5432/jdbc_test_db
diff --git a/samples/sql-support/src/main/resources/postgresql-index-datasource.properties b/samples/sql-support/src/main/resources/postgresql-index-datasource.properties
index f7d7ad5..ea16c45 100644
--- a/samples/sql-support/src/main/resources/postgresql-index-datasource.properties
+++ b/samples/sql-support/src/main/resources/postgresql-index-datasource.properties
@@ -1,17 +1,22 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 enabled=true
 url=jdbc:postgresql://localhost:5432/jdbc_test_db
diff --git a/samples/swing/build.gradle b/samples/swing/build.gradle
index 918363c..387361f 100644
--- a/samples/swing/build.gradle
+++ b/samples/swing/build.gradle
@@ -1,26 +1,39 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
+import org.apache.polygene.gradle.TaskGroups
+
+apply plugin: 'polygene-sample'
 
 description = "Sample of how to use the Swing bindings."
 
-jar { manifest { name = "Apache Zest™ Sample - Swing Bindings" }}
+jar { manifest { name = "Apache Polygene™ Sample - Swing Bindings" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-}
\ No newline at end of file
+  implementation polygene.core.bootstrap
+
+  runtimeOnly polygene.core.runtime
+}
+
+task( runSwingSample, dependsOn: 'classes', type: JavaExec ) {
+  group = TaskGroups.SAMPLES
+  description = "Runs $project.name sample."
+  main = 'org.apache.polygene.sample.swing.binding.example.Main'
+  classpath = sourceSets.main.runtimeClasspath
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/Binding.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/Binding.java
new file mode 100644
index 0000000..81e4870
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/Binding.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.sample.swing.binding;
+
+import javax.swing.*;
+
+public interface Binding
+{
+    void to( JComponent component );
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/IllegalBindingException.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/IllegalBindingException.java
new file mode 100644
index 0000000..c4432f5
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/IllegalBindingException.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.sample.swing.binding;
+
+import javax.swing.*;
+
+/** This exception is thrown when attempt to bind incompatible types and swing components.
+*/
+public class IllegalBindingException extends RuntimeException
+{
+    public IllegalBindingException( JComponent component, Class<?> type )
+    {
+        super( "Binding not supported from " + type + " to " + component );
+    }
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/StateModel.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/StateModel.java
new file mode 100644
index 0000000..8b9aea8
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/StateModel.java
@@ -0,0 +1,76 @@
+/*
+ *  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.polygene.sample.swing.binding;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.sample.swing.binding.internal.BoundProperty;
+import org.apache.polygene.sample.swing.binding.internal.StateInvocationHandler;
+
+import static java.lang.reflect.Proxy.newProxyInstance;
+
+public class StateModel<T>
+{
+    private T currentData;
+    private final Class<T> type;
+    private StateInvocationHandler<T> childModel;
+
+    public StateModel( @Uses Class<T> aType, @Structure ObjectFactory objectBuilderFactory )
+    {
+        type = aType;
+        //noinspection unchecked
+        childModel = objectBuilderFactory.newObject( StateInvocationHandler.class, aType );
+    }
+
+    /**
+     * Sets the data to this component model and its children.
+     *
+     * @param aData The data to set.
+     */
+    public void use( T aData )
+    {
+        currentData = aData;
+        childModel.use( aData );
+    }
+
+    public T stateInUse()
+    {
+        return currentData;
+    }
+
+    @SuppressWarnings( { "unchecked" } )
+    public final T state()
+    {
+        ClassLoader loader = StateInvocationHandler.class.getClassLoader();
+        Class[] typeInterfaces = new Class[]{ type };
+        return (T) newProxyInstance( loader, typeInterfaces, childModel );
+    }
+
+    public Binding bind( Property property )
+    {
+        if( property instanceof BoundProperty )
+        {
+            return (BoundProperty) property;
+        }
+        throw new IllegalArgumentException( "Unknown property template: " + property );
+    }
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/SwingAdapter.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/SwingAdapter.java
new file mode 100644
index 0000000..94d66b2
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/SwingAdapter.java
@@ -0,0 +1,73 @@
+/*
+ *  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.polygene.sample.swing.binding;
+
+import java.util.Set;
+import javax.swing.JComponent;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.property.Property;
+
+public interface SwingAdapter
+{
+    Set<Capabilities> canHandle();
+
+    void fromSwingToProperty( JComponent component, Property<?> property );
+
+    void fromPropertyToSwing( JComponent component, Property<?> property );
+
+    void fromSwingToAssociation( JComponent component, Association<?> property );
+
+    void fromAssociationToSwing( JComponent component, Association<?> property );
+
+    void fromSwingToSetAssociation( JComponent component, ManyAssociation<?> property );
+
+    void fromSetAssociationToSwing( JComponent component, ManyAssociation<?> property );
+
+    void fromSwingToNamedAssociation( JComponent component, NamedAssociation<?> namedAssociation );
+
+    void fromNamedAssociationToSwing( JComponent component, NamedAssociation<?> namedAssociation );
+
+    public class Capabilities
+    {
+        public final Class<? extends JComponent> component;
+        public final Class<?> type;
+        public final boolean property;
+        public final boolean association;
+        public final boolean listAssociation;
+        public final boolean setAssociation;
+        public final boolean namedAssociation;
+
+        public Capabilities( Class<? extends JComponent> component, Class<?> type,
+                             boolean property, boolean association, boolean setAssociation,
+                             boolean listAssociation, boolean namedAssociation )
+        {
+            this.component = component;
+            this.type = type;
+            this.property = property;
+            this.association = association;
+            this.listAssociation = listAssociation;
+            this.setAssociation = setAssociation;
+            this.namedAssociation = namedAssociation;
+        }
+    }
+
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/SwingBinding.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/SwingBinding.java
new file mode 100644
index 0000000..ac76b97
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/SwingBinding.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.sample.swing.binding;
+
+import javax.swing.*;
+
+public interface SwingBinding
+{
+    void to( JComponent component );
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/SwingBindingAssembler.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/SwingBindingAssembler.java
new file mode 100644
index 0000000..31cfbc9
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/SwingBindingAssembler.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.sample.swing.binding;
+
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.sample.swing.binding.adapters.StringToTextFieldAdapterService;
+import org.apache.polygene.sample.swing.binding.internal.BoundProperty;
+import org.apache.polygene.sample.swing.binding.internal.StateInvocationHandler;
+
+public class SwingBindingAssembler
+    implements Assembler
+{
+
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.objects( StateModel.class, StateInvocationHandler.class, BoundProperty.class );
+        addStringToTextFieldAdapter( module );
+    }
+
+    protected void addStringToTextFieldAdapter( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( StringToTextFieldAdapterService.class );
+    }
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/adapters/StringToTextFieldAdapterService.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/adapters/StringToTextFieldAdapterService.java
new file mode 100644
index 0000000..3a73ad7
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/adapters/StringToTextFieldAdapterService.java
@@ -0,0 +1,142 @@
+/*
+ *  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.polygene.sample.swing.binding.adapters;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.text.JTextComponent;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.mixin.NoopMixin;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.sample.swing.binding.SwingAdapter;
+
+@Concerns( StringToTextFieldAdapterService.StringToTextFieldAdapterConcern.class )
+@Mixins( NoopMixin.class )
+public interface StringToTextFieldAdapterService
+    extends SwingAdapter, ServiceComposite
+{
+
+    class StringToTextFieldAdapterConcern
+        extends ConcernOf<SwingAdapter>
+        implements SwingAdapter
+    {
+
+        private HashSet<Capabilities> canHandle;
+
+        public StringToTextFieldAdapterConcern()
+        {
+            canHandle = new HashSet<>();
+            canHandle.add( new Capabilities( JTextArea.class, String.class, true, false, false, false, false ) );
+            canHandle.add( new Capabilities( JTextField.class, String.class, true, false, false, false, false ) );
+            canHandle.add( new Capabilities( JLabel.class, String.class, true, false, false, false, false ) );
+        }
+
+        @Override
+        public Set<Capabilities> canHandle()
+        {
+            return canHandle;
+        }
+
+        @Override
+        public void fromSwingToProperty( JComponent component, Property property )
+        {
+            if( property == null )
+            {
+                return;
+            }
+            if( component instanceof JTextComponent )
+            {
+                JTextComponent textComponent = (JTextComponent) component;
+                property.set( textComponent.getText() );
+            }
+            else
+            {
+                JLabel labelComponent = (JLabel) component;
+                property.set( labelComponent.getText() );
+            }
+        }
+
+        @Override
+        public void fromPropertyToSwing( JComponent component, Property<?> property )
+        {
+            String value;
+            if( property == null )
+            {
+                value = "";
+            }
+            else
+            {
+                value = (String) property.get();
+            }
+            if( component instanceof JTextComponent )
+            {
+                JTextComponent textComponent = (JTextComponent) component;
+                textComponent.setText( value );
+            }
+            else
+            {
+                JLabel labelComponent = (JLabel) component;
+                labelComponent.setText( value );
+            }
+        }
+
+        @Override
+        public void fromSwingToAssociation( JComponent component, Association<?> association )
+        {
+        }
+
+        @Override
+        public void fromAssociationToSwing( JComponent component, Association<?> association )
+        {
+        }
+
+        @Override
+        public void fromSwingToSetAssociation( JComponent component, ManyAssociation<?> setAssociation )
+        {
+        }
+
+        @Override
+        public void fromSetAssociationToSwing( JComponent component, ManyAssociation<?> setAssociation )
+        {
+        }
+
+        @Override
+        public void fromSwingToNamedAssociation( JComponent component, NamedAssociation<?> namedAssociation )
+        {
+        }
+
+        @Override
+        public void fromNamedAssociationToSwing( JComponent component, NamedAssociation<?> namedAssociation )
+        {
+        }
+
+    }
+
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/Address.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/Address.java
new file mode 100644
index 0000000..9c245ba
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/Address.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.sample.swing.binding.example;
+
+import org.apache.polygene.api.property.Property;
+
+public interface Address extends HasCity
+{
+    Property<String> line1();
+    Property<String> line2();
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/AddressTransient.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/AddressTransient.java
new file mode 100644
index 0000000..5548047
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/AddressTransient.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.sample.swing.binding.example;
+
+import org.apache.polygene.api.composite.TransientComposite;
+
+public interface AddressTransient extends Address, TransientComposite
+{
+
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/BoundPersonComposite.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/BoundPersonComposite.java
new file mode 100644
index 0000000..f179c36
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/BoundPersonComposite.java
@@ -0,0 +1,24 @@
+/*
+ *  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.polygene.sample.swing.binding.example;
+
+public interface BoundPersonComposite extends PersonComposite
+{
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/City.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/City.java
new file mode 100644
index 0000000..3ecc292
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/City.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.sample.swing.binding.example;
+
+public interface City extends HasCountry, HasName
+{
+
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/CityValue.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/CityValue.java
new file mode 100644
index 0000000..c8fffcd
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/CityValue.java
@@ -0,0 +1,26 @@
+/*
+ *  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.polygene.sample.swing.binding.example;
+
+import org.apache.polygene.api.value.ValueComposite;
+
+public interface CityValue extends City, ValueComposite
+{
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/Country.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/Country.java
new file mode 100644
index 0000000..0339f05
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/Country.java
@@ -0,0 +1,24 @@
+/*
+ *  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.polygene.sample.swing.binding.example;
+
+public interface Country extends HasName
+{
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/CountryValue.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/CountryValue.java
new file mode 100644
index 0000000..e22674e
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/CountryValue.java
@@ -0,0 +1,26 @@
+/*
+ *  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.polygene.sample.swing.binding.example;
+
+import org.apache.polygene.api.value.ValueComposite;
+
+public interface CountryValue extends Country, ValueComposite
+{
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/Form.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/Form.java
new file mode 100644
index 0000000..8964257
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/Form.java
@@ -0,0 +1,98 @@
+/*
+ *  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.polygene.sample.swing.binding.example;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.sample.swing.binding.StateModel;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class Form<T extends BoundPersonComposite> extends JPanel
+{
+
+    private final StateModel<T> aModel;
+
+    public Form( StateModel<T> aModel )
+    {
+        this.aModel = aModel;
+        T state = aModel.state();
+
+        JPanel firstNameField = newPersonFirstNameField( aModel, state );
+        add( firstNameField );
+        JPanel userAddressLine1Field = newUserFirstLineAddressField( aModel, state );
+        add( userAddressLine1Field );
+        JPanel userAddressLine2Field = newUserSecondLineAddressField( aModel, state );
+        add( userAddressLine2Field );
+        JPanel userCityField = newUserCityField( aModel, state );
+        add( userCityField );
+        JPanel userCountryField = newUserCountryField( aModel, state );
+        add( userCountryField );
+        setLayout( new BoxLayout( this, BoxLayout.Y_AXIS ) );
+    }
+
+    public StateModel<T> getAModel()
+    {
+        return aModel;
+    }
+
+    private JPanel newPersonFirstNameField( StateModel<T> aModel, T aModelState )
+    {
+        Property<String> property = aModelState.firstName();
+        return newTextPanel( aModel, property, "First Name:" );
+    }
+
+    private JPanel newUserFirstLineAddressField( StateModel<T> aModel, T aModelState )
+    {
+        Property<String> property = aModelState.address().get().line1();
+        return newTextPanel( aModel, property, "Address:" );
+    }
+
+    private JPanel newUserSecondLineAddressField( StateModel<T> aModel, T state )
+    {
+        Property<String> property = state.address().get().line2();
+        return newTextPanel( aModel, property, "" );
+    }
+
+    private JPanel newUserCityField( StateModel<T> aModel, T state )
+    {
+        Property<String> property = state.address().get().city().get().name();
+        return newTextPanel( aModel, property, "City:" );
+    }
+
+    private JPanel newUserCountryField( StateModel<T> aModel, T state )
+    {
+        Property<String> property = state.address().get().city().get().country().get().name();
+        return newTextPanel( aModel, property, "Country:" );
+    }
+
+    private JPanel newTextPanel( StateModel<T> aModel, Property<String> property, String fieldName )
+    {
+        JPanel panel = new JPanel();
+        JLabel label = new JLabel( fieldName );
+        label.setPreferredSize( new Dimension( 100, 20 ) );
+        panel.add( label );
+        JTextField textField = new JTextField();
+        panel.add( textField );
+        textField.setPreferredSize( new Dimension( 100, 20 ) );
+        aModel.bind( property ).to( textField );
+        return panel;
+    }
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/HasAddress.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/HasAddress.java
new file mode 100644
index 0000000..186495c
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/HasAddress.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.sample.swing.binding.example;
+
+import org.apache.polygene.api.property.Property;
+
+public interface HasAddress
+{
+    Property<Address> address();
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/HasCity.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/HasCity.java
new file mode 100644
index 0000000..e5f827d
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/HasCity.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.sample.swing.binding.example;
+
+import org.apache.polygene.api.property.Property;
+
+public interface HasCity
+{
+    Property<City> city();
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/HasCountry.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/HasCountry.java
new file mode 100644
index 0000000..9851138
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/HasCountry.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.sample.swing.binding.example;
+
+import org.apache.polygene.api.property.Property;
+
+public interface HasCountry
+{
+    Property<Country> country();
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/HasName.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/HasName.java
new file mode 100644
index 0000000..396ca55
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/HasName.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.sample.swing.binding.example;
+
+import org.apache.polygene.api.property.Property;
+
+public interface HasName
+{
+    Property<String> name();
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/Main.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/Main.java
new file mode 100644
index 0000000..ed35f13
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/Main.java
@@ -0,0 +1,144 @@
+/*
+ *  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.polygene.sample.swing.binding.example;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import javax.swing.JCheckBox;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.sample.swing.binding.StateModel;
+import org.apache.polygene.sample.swing.binding.SwingBindingAssembler;
+
+public class Main
+{
+
+    private static Module module;
+
+    public static void main( String[] args )
+        throws Exception
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( BoundPersonComposite.class );
+                module.transients( AddressTransient.class );
+                module.values( CityValue.class, CountryValue.class );
+                new SwingBindingAssembler().assemble( module );
+            }
+        };
+        module = assembler.module();
+        Address address1 = createAddress( "Vista Damai", "Jalan Tun Razak" );
+        Address address2 = createAddress( "Mutiara", "Jalan Ceylon" );
+
+        TransientBuilder<BoundPersonComposite> builder = module.newTransientBuilder( BoundPersonComposite.class );
+        PersonComposite prototype = builder.prototype();
+        prototype.address().set( address1 );
+        prototype.firstName().set( "Niclas" );
+        final BoundPersonComposite p1 = builder.newInstance();
+
+        prototype.address().set( address2 );
+        prototype.firstName().set( "Edward" );
+        final BoundPersonComposite p2 = builder.newInstance();
+
+        final StateModel<BoundPersonComposite> model = module.newObject( StateModel.class, BoundPersonComposite.class );
+        Form form = new Form<BoundPersonComposite>( model );
+
+        JFrame frame = new JFrame( "testing" );
+
+        frame.add( form, BorderLayout.CENTER );
+        JPanel checkBoxPanel = new JPanel();
+        checkBoxPanel.setFocusable( true );
+        checkBoxPanel.addFocusListener( new FocusListener()
+        {
+
+            public void focusGained( FocusEvent e )
+            {
+                System.out.println( "Gained!" );
+            }
+
+            public void focusLost( FocusEvent e )
+            {
+                System.out.println( "LOst!" );
+            }
+        } );
+        JCheckBox sw = new JCheckBox( "Toggle" );
+        sw.addActionListener( new ActionListener()
+        {
+
+            public void actionPerformed( ActionEvent e )
+            {
+                if( ( (JCheckBox) e.getSource() ).isSelected() )
+                {
+                    model.use( p1 );
+                    System.out.println( p1.firstName().get() );
+                }
+                else
+                {
+                    model.use( p2 );
+                    System.out.println( p2.firstName().get() );
+                }
+            }
+        }
+        );
+        checkBoxPanel.add( sw );
+        frame.add( checkBoxPanel, BorderLayout.EAST );
+        frame.pack();
+        System.out.println( model );
+        frame.setVisible( true );
+        frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
+    }
+
+    private static Address createAddress( String line1, String line2 )
+    {
+        TransientBuilder<Address> addressBuilder = module.newTransientBuilder( Address.class );
+        addressBuilder.prototype().line1().set( line1 );
+        addressBuilder.prototype().line2().set( line2 );
+        addressBuilder.prototype().city().set( createCity("Kuala Lumpur") );
+        return addressBuilder.newInstance();
+    }
+
+    private static City createCity( String cityName )
+    {
+        ValueBuilder<City> builder = module.newValueBuilder( City.class );
+        builder.prototype().name().set( cityName );
+        builder.prototype().country().set( createCountry( "Malaysia" ) );
+        return builder.newInstance();
+    }
+
+    private static Country createCountry( String countryName )
+    {
+        ValueBuilder<Country> builder = module.newValueBuilder( Country.class );
+        builder.prototype().name().set( countryName );
+        return builder.newInstance();
+    }
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/Person.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/Person.java
new file mode 100644
index 0000000..1f968c7
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/Person.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.sample.swing.binding.example;
+
+import org.apache.polygene.api.property.Property;
+
+public interface Person extends HasAddress
+{
+    Property<String> firstName();
+//    Property<String> lastName();
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/PersonComposite.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/PersonComposite.java
new file mode 100644
index 0000000..a6c1ced
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/example/PersonComposite.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.sample.swing.binding.example;
+
+import org.apache.polygene.api.composite.TransientComposite;
+
+public interface PersonComposite extends Person, TransientComposite
+{
+
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/AbstractBinding.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/AbstractBinding.java
new file mode 100644
index 0000000..09bea51
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/AbstractBinding.java
@@ -0,0 +1,117 @@
+/*
+ *  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.polygene.sample.swing.binding.internal;
+
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.sample.swing.binding.StateModel;
+import org.apache.polygene.sample.swing.binding.SwingAdapter;
+import org.apache.polygene.sample.swing.binding.SwingBinding;
+
+import javax.swing.*;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+public abstract class AbstractBinding<T>
+    implements SwingBinding
+{
+
+    private final Class<T> type;
+    protected StateModel<T> stateModel;
+    protected Set<JComponent> components;
+    private PropertyFocusLostListener focusListener;
+    protected HashMap<Class<? extends JComponent>, SwingAdapter> adapters;
+    private String name;
+    protected Method method;
+
+    @SuppressWarnings( "unchecked" )
+    public AbstractBinding( @Uses Method method, @Structure ObjectFactory objectBuilderFactory,
+                            @Service Iterable<SwingAdapter> allAdapters )
+        throws IllegalArgumentException
+    {
+        this.method = method;
+        ParameterizedType parameterType = (ParameterizedType) method.getGenericReturnType();
+        Type[] actualTypeArguments = parameterType.getActualTypeArguments();
+        type = (Class<T>) actualTypeArguments[ 0 ];
+        name = method.getName();
+        stateModel = objectBuilderFactory.newObject( StateModel.class, type );
+        components = new HashSet<JComponent>();
+        setupAdapters( allAdapters );
+    }
+
+    public void to( final JComponent component )
+    {
+        if( components.add( component ) )
+        {
+            focusListener = new PropertyFocusLostListener( component );
+            component.addFocusListener( focusListener );
+        }
+    }
+
+    public String toString()
+    {
+        return name + "[" + type.getSimpleName() + "] -> " + stateModel.toString();
+    }
+
+    private void setupAdapters( Iterable<SwingAdapter> allAdapters )
+    {
+        adapters = new HashMap<Class<? extends JComponent>, SwingAdapter>();
+        for( SwingAdapter adapterCandidate : allAdapters )
+        {
+            Set<SwingAdapter.Capabilities> canHandle = adapterCandidate.canHandle();
+            for( SwingAdapter.Capabilities capabilities : canHandle )
+            {
+                if( requiredCapabilitySatisfied( capabilities ) )
+                {
+                    if( capabilities.type.equals( this.type ) )
+                    {
+                        Class<? extends JComponent> component = capabilities.component;
+                        adapters.put( component, adapterCandidate );
+                    }
+                }
+            }
+        }
+    }
+
+    protected abstract boolean requiredCapabilitySatisfied( SwingAdapter.Capabilities capabilities );
+
+    public final T get()
+    {
+        return stateModel.state();
+    }
+
+    public final Class type()
+    {
+        return type;
+    }
+
+    public void set( T newValue )
+        throws IllegalArgumentException
+    {
+        throw new IllegalArgumentException( "set() is not allowed in binding templates." );
+    }
+
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/AssociationFocusLostListener.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/AssociationFocusLostListener.java
new file mode 100644
index 0000000..dbf15c1
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/AssociationFocusLostListener.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.sample.swing.binding.internal;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.sample.swing.binding.SwingAdapter;
+
+import javax.swing.*;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+
+public class AssociationFocusLostListener
+    implements FocusListener
+{
+
+    private final JComponent component;
+    private SwingAdapter adapter;
+    private Association actual;
+
+    public AssociationFocusLostListener( JComponent component )
+    {
+        this.component = component;
+    }
+
+    void use( SwingAdapter adapterToUse, Association actual )
+    {
+        adapter = adapterToUse;
+        this.actual = actual;
+    }
+
+    public void focusGained( FocusEvent e )
+    {
+    }
+
+    public void focusLost( FocusEvent e )
+    {
+        if( adapter != null )
+        {
+            adapter.fromSwingToAssociation( component, actual );
+        }
+    }
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/BoundAssociation.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/BoundAssociation.java
new file mode 100644
index 0000000..98b9371
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/BoundAssociation.java
@@ -0,0 +1,94 @@
+/*
+ *  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.polygene.sample.swing.binding.internal;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.sample.swing.binding.Binding;
+import org.apache.polygene.sample.swing.binding.SwingAdapter;
+
+import javax.swing.*;
+import java.awt.event.FocusListener;
+import java.lang.reflect.Method;
+
+public final class BoundAssociation<T> extends AbstractBinding<T>
+    implements Association<T>, Binding
+{
+
+    private Association<T> actual;
+
+    /**
+     * Construct an instance of {@code BoundAssociation} with the specified arguments.
+     *
+     * @param associationMethod The method that returns Assocation. This argument must not be {@code null}.
+     *
+     * @throws IllegalArgumentException Thrown if the specified {@code aMethod} is {@code null}.
+     */
+    public BoundAssociation( @Uses Method associationMethod, @Structure ObjectFactory objectBuilderFactory,
+                             @Service Iterable<SwingAdapter> allAdapters )
+        throws IllegalArgumentException
+    {
+        super( associationMethod, objectBuilderFactory, allAdapters );
+
+    }
+
+    public void use( Association<T> actualAssociation )
+    {
+        actual = actualAssociation;
+        T value = null;
+        if( actualAssociation != null )
+        {
+            value = actualAssociation.get();
+        }
+        stateModel.use( value );
+        for( JComponent component : components )
+        {
+            SwingAdapter adapter = adapters.get( component.getClass() );
+            adapter.fromAssociationToSwing( component, actualAssociation );
+            for( FocusListener listener : component.getFocusListeners() )
+            {
+                if( AssociationFocusLostListener.class.isInstance( listener ) )
+                {
+                    ( (AssociationFocusLostListener) listener ).use( adapter, actual );
+                }
+            }
+        }
+    }
+
+    protected boolean requiredCapabilitySatisfied( SwingAdapter.Capabilities capabilities )
+    {
+        return capabilities.association;
+    }
+
+    public void to( JComponent component )
+    {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @Override
+    public EntityReference reference()
+    {
+        return actual.reference();
+    }
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/BoundManyAssociation.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/BoundManyAssociation.java
new file mode 100644
index 0000000..4f9cee1
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/BoundManyAssociation.java
@@ -0,0 +1,116 @@
+/*
+ *  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.polygene.sample.swing.binding.internal;
+
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.sample.swing.binding.Binding;
+import org.apache.polygene.sample.swing.binding.SwingAdapter;
+
+public class BoundManyAssociation<T> extends AbstractBinding<T>
+    implements Binding, ManyAssociation<T>
+{
+
+    private ManyAssociation<T> actualAssociations;
+
+    public BoundManyAssociation( @Uses Method method, @Structure ObjectFactory objectBuilderFactory,
+                                 @Service Iterable<SwingAdapter> allAdapters
+    )
+        throws IllegalArgumentException
+    {
+        super( method, objectBuilderFactory, allAdapters );
+    }
+
+    protected boolean requiredCapabilitySatisfied( SwingAdapter.Capabilities capabilities )
+    {
+        return false;
+    }
+
+    public boolean add( T o )
+    {
+        return actualAssociations.add( o );
+    }
+
+    public boolean remove( T o )
+    {
+        return actualAssociations.remove( o );
+    }
+
+    @Override
+    public boolean clear()
+    {
+        return actualAssociations.clear();
+    }
+
+    public T get( int index )
+    {
+        return actualAssociations.get( index );
+    }
+
+    @Override
+    public List<T> toList()
+    {
+        return actualAssociations.toList();
+    }
+
+    @Override
+    public Set<T> toSet()
+    {
+        return actualAssociations.toSet();
+    }
+
+    @Override
+    public Stream<EntityReference> references()
+    {
+        return actualAssociations.references();
+    }
+
+    @Override
+    public int count()
+    {
+        return actualAssociations.count();
+    }
+
+    @Override
+    public boolean contains( T entity )
+    {
+        return actualAssociations.contains( entity );
+    }
+
+    public boolean add( int index, T element )
+    {
+        return actualAssociations.add( index, element );
+    }
+
+    @Override
+    public Iterator<T> iterator()
+    {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/BoundNamedAssociation.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/BoundNamedAssociation.java
new file mode 100644
index 0000000..e7116e6
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/BoundNamedAssociation.java
@@ -0,0 +1,122 @@
+/*
+ *  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.polygene.sample.swing.binding.internal;
+
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.sample.swing.binding.Binding;
+import org.apache.polygene.sample.swing.binding.SwingAdapter;
+
+public class BoundNamedAssociation<T>
+    extends AbstractBinding<T>
+    implements Binding, NamedAssociation<T>
+{
+
+    private NamedAssociation<T> actualAssociations;
+
+    public BoundNamedAssociation( @Uses Method method, @Structure ObjectFactory objectBuilderFactory,
+                                  @Service Iterable<SwingAdapter> allAdapters
+    )
+        throws IllegalArgumentException
+    {
+        super( method, objectBuilderFactory, allAdapters );
+    }
+
+    @Override
+    protected boolean requiredCapabilitySatisfied( SwingAdapter.Capabilities capabilities )
+    {
+        return false;
+    }
+
+    @Override
+    public int count()
+    {
+        return actualAssociations.count();
+    }
+
+    @Override
+    public boolean containsName( String name )
+    {
+        return actualAssociations.containsName( name );
+    }
+
+    @Override
+    public boolean put( String name, T entity )
+    {
+        return actualAssociations.put( name, entity );
+    }
+
+    @Override
+    public boolean remove( String name )
+    {
+        return actualAssociations.remove( name );
+    }
+
+    @Override
+    public boolean clear()
+    {
+        return actualAssociations.clear();
+    }
+
+    @Override
+    public T get( String name )
+    {
+        return actualAssociations.get( name );
+    }
+
+    @Override
+    public String nameOf( T entity )
+    {
+        return actualAssociations.nameOf( entity );
+    }
+
+    @Override
+    public Map<String, T> toMap()
+    {
+        return actualAssociations.toMap();
+    }
+
+    @Override
+    public Stream<Map.Entry<String, EntityReference>> references()
+    {
+        return actualAssociations.references();
+    }
+
+    @Override
+    public EntityReference referenceOf( String name )
+    {
+        return actualAssociations.referenceOf( name );
+    }
+
+    @Override
+    public Iterator<String> iterator()
+    {
+        return actualAssociations.iterator();
+    }
+
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/BoundProperty.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/BoundProperty.java
new file mode 100644
index 0000000..530267c
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/BoundProperty.java
@@ -0,0 +1,80 @@
+/*
+ *  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.polygene.sample.swing.binding.internal;
+
+import java.awt.event.FocusListener;
+import java.lang.reflect.Method;
+import javax.swing.JComponent;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.sample.swing.binding.Binding;
+import org.apache.polygene.sample.swing.binding.SwingAdapter;
+
+public final class BoundProperty<T> extends AbstractBinding<T>
+    implements Property<T>, Binding
+{
+
+    private Property propertyInfo;
+
+    /**
+     * Construct an instance of {@code BoundProperty} with the specified arguments.
+     *
+     * @param propertyMethod The method that returns Property. This argument must not be {@code null}.
+     *
+     * @throws IllegalArgumentException Thrown if the specified {@code aMethod} is {@code null}.
+     */
+    public BoundProperty( @Uses Method propertyMethod, @Structure ObjectFactory objectBuilderFactory,
+                          @Service Iterable<SwingAdapter> allAdapters
+    )
+        throws IllegalArgumentException
+    {
+        super( propertyMethod, objectBuilderFactory, allAdapters );
+    }
+
+    public void use( Property<T> actualProperty )
+    {
+        T value = null;
+        if( actualProperty != null )
+        {
+            value = actualProperty.get();
+        }
+        stateModel.use( value );
+        for( JComponent component : components )
+        {
+            SwingAdapter adapter = adapters.get( component.getClass() );
+            adapter.fromPropertyToSwing( component, actualProperty );
+            for( FocusListener listener : component.getFocusListeners() )
+            {
+                if( PropertyFocusLostListener.class.isInstance( listener ) )
+                {
+                    ( (PropertyFocusLostListener) listener ).use( adapter, actualProperty );
+                }
+            }
+        }
+    }
+
+    protected boolean requiredCapabilitySatisfied( SwingAdapter.Capabilities capabilities )
+    {
+        return capabilities.property;
+    }
+}
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/PropertyFocusLostListener.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/PropertyFocusLostListener.java
new file mode 100644
index 0000000..762f2dc
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/PropertyFocusLostListener.java
@@ -0,0 +1,60 @@
+/*
+ *  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.polygene.sample.swing.binding.internal;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.sample.swing.binding.SwingAdapter;
+
+import javax.swing.*;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+
+class PropertyFocusLostListener
+    implements FocusListener
+{
+
+    private final JComponent component;
+    private SwingAdapter adapter;
+    private Property actual;
+
+    public PropertyFocusLostListener( JComponent component )
+    {
+        this.component = component;
+    }
+
+    void use( SwingAdapter adapterToUse, Property actual )
+    {
+        adapter = adapterToUse;
+        this.actual = actual;
+    }
+
+    public void focusGained( FocusEvent e )
+    {
+    }
+
+    public void focusLost( FocusEvent e )
+    {
+        if( adapter != null )
+        {
+            adapter.fromSwingToProperty( component, actual );
+        }
+    }
+}
+
diff --git a/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/StateInvocationHandler.java b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/StateInvocationHandler.java
new file mode 100644
index 0000000..7bf269f
--- /dev/null
+++ b/samples/swing/src/main/java/org/apache/polygene/sample/swing/binding/internal/StateInvocationHandler.java
@@ -0,0 +1,130 @@
+/*
+ *  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.polygene.sample.swing.binding.internal;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.structure.Module;
+
+public final class StateInvocationHandler<T>
+    implements InvocationHandler
+{
+
+    @Structure
+    private Module module;
+
+    private final HashMap<Method, BoundProperty> properties;
+    private final HashMap<Method, BoundAssociation> associations;
+    private final HashMap<Method, BoundManyAssociation> manyassociations;
+    private final HashMap<Method, BoundNamedAssociation> namedassociations;
+    private final Class<?> type;
+
+    public StateInvocationHandler( @Uses Class<?> aType )
+    {
+        type = aType;
+        properties = new HashMap<>();
+        associations = new HashMap<>();
+        manyassociations = new HashMap<>();
+        namedassociations = new HashMap<>();
+    }
+
+    public final Object invoke( Object aProxy, Method aMethod, Object[] args )
+        throws Throwable
+    {
+        if( "toString".equals( aMethod.getName() ) )
+        {
+            return type.toString() + "( " + properties.values() + ")";
+        }
+        Class<?> methodReturnType = aMethod.getReturnType();
+        if( Property.class.isAssignableFrom( methodReturnType ) )
+        {
+            BoundProperty property = properties.get( aMethod );
+            if( property == null )
+            {
+                property = module.newObject( BoundProperty.class, aMethod );
+                properties.put( aMethod, property );
+            }
+
+            return property;
+        }
+        else if( NamedAssociation.class.isAssignableFrom( methodReturnType ) )
+        {
+            BoundNamedAssociation association = namedassociations.get( aMethod );
+            if( association == null )
+            {
+                association = module.newObject( BoundNamedAssociation.class, aMethod );
+                namedassociations.put( aMethod, association );
+            }
+            return association;
+        }
+        else if( ManyAssociation.class.isAssignableFrom( methodReturnType ) )
+        {
+            BoundManyAssociation association = manyassociations.get( aMethod );
+            if( association == null )
+            {
+                association = module.newObject( BoundManyAssociation.class, aMethod );
+                manyassociations.put( aMethod, association );
+            }
+            return association;
+        }
+        else if( Association.class.isAssignableFrom( methodReturnType ) )
+        {
+            BoundAssociation association = associations.get( aMethod );
+            if( association == null )
+            {
+                association = module.newObject( BoundAssociation.class, aMethod );
+                associations.put( aMethod, association );
+            }
+            return association;
+        }
+        return null;
+    }
+
+    public void use( T actualData )
+    {
+        for( Map.Entry<Method, BoundProperty> entry : properties.entrySet() )
+        {
+            BoundProperty bound = entry.getValue();
+            Property actualProperty = null;
+            if( actualData != null )
+            {
+                Method method = entry.getKey();
+                try
+                {
+                    actualProperty = (Property) method.invoke( actualData );
+                }
+                catch( IllegalAccessException | InvocationTargetException e )
+                {
+                    e.printStackTrace();  //TODO: Auto-generated, need attention.
+                }
+            }
+            bound.use( actualProperty );
+        }
+    }
+}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/Binding.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/Binding.java
deleted file mode 100644
index 434284a..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/Binding.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding;
-
-import javax.swing.*;
-
-public interface Binding
-{
-    void to( JComponent component );
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/IllegalBindingException.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/IllegalBindingException.java
deleted file mode 100644
index c13f393..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/IllegalBindingException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding;
-
-import javax.swing.*;
-
-/** This exception is thrown when attempt to bind incompatible types and swing components.
-*/
-public class IllegalBindingException extends RuntimeException
-{
-    public IllegalBindingException( JComponent component, Class<?> type )
-    {
-        super( "Binding not supported from " + type + " to " + component );
-    }
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/StateModel.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/StateModel.java
deleted file mode 100644
index 1b32ad6..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/StateModel.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.object.ObjectFactory;
-import org.qi4j.api.property.Property;
-import org.qi4j.lib.swing.binding.internal.BoundProperty;
-import org.qi4j.lib.swing.binding.internal.StateInvocationHandler;
-
-import static java.lang.reflect.Proxy.newProxyInstance;
-
-public class StateModel<T>
-{
-    private T currentData;
-    private final Class<T> type;
-    private StateInvocationHandler<T> childModel;
-
-    public StateModel( @Uses Class<T> aType, @Structure ObjectFactory objectBuilderFactory )
-    {
-        type = aType;
-        //noinspection unchecked
-        childModel = objectBuilderFactory.newObject( StateInvocationHandler.class, aType );
-    }
-
-    /**
-     * Sets the data to this component model and its children.
-     *
-     * @param aData The data to set.
-     */
-    public void use( T aData )
-    {
-        currentData = aData;
-        childModel.use( aData );
-    }
-
-    public T stateInUse()
-    {
-        return currentData;
-    }
-
-    @SuppressWarnings( { "unchecked" } )
-    public final T state()
-    {
-        ClassLoader loader = StateInvocationHandler.class.getClassLoader();
-        Class[] typeInterfaces = new Class[]{ type };
-        return (T) newProxyInstance( loader, typeInterfaces, childModel );
-    }
-
-    public Binding bind( Property property )
-    {
-        if( property instanceof BoundProperty )
-        {
-            return (BoundProperty) property;
-        }
-        throw new IllegalArgumentException( "Unknown property template: " + property );
-    }
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/SwingAdapter.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/SwingAdapter.java
deleted file mode 100644
index 1bff3c4..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/SwingAdapter.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding;
-
-import java.util.Set;
-import javax.swing.JComponent;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.property.Property;
-
-public interface SwingAdapter
-{
-    Set<Capabilities> canHandle();
-
-    void fromSwingToProperty( JComponent component, Property<?> property );
-
-    void fromPropertyToSwing( JComponent component, Property<?> property );
-
-    void fromSwingToAssociation( JComponent component, Association<?> property );
-
-    void fromAssociationToSwing( JComponent component, Association<?> property );
-
-    void fromSwingToSetAssociation( JComponent component, ManyAssociation<?> property );
-
-    void fromSetAssociationToSwing( JComponent component, ManyAssociation<?> property );
-
-    void fromSwingToNamedAssociation( JComponent component, NamedAssociation<?> namedAssociation );
-
-    void fromNamedAssociationToSwing( JComponent component, NamedAssociation<?> namedAssociation );
-
-    public class Capabilities
-    {
-        public final Class<? extends JComponent> component;
-        public final Class<?> type;
-        public final boolean property;
-        public final boolean association;
-        public final boolean listAssociation;
-        public final boolean setAssociation;
-        public final boolean namedAssociation;
-
-        public Capabilities( Class<? extends JComponent> component, Class<?> type,
-                             boolean property, boolean association, boolean setAssociation,
-                             boolean listAssociation, boolean namedAssociation )
-        {
-            this.component = component;
-            this.type = type;
-            this.property = property;
-            this.association = association;
-            this.listAssociation = listAssociation;
-            this.setAssociation = setAssociation;
-            this.namedAssociation = namedAssociation;
-        }
-    }
-
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/SwingBinding.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/SwingBinding.java
deleted file mode 100644
index 34a96e9..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/SwingBinding.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding;
-
-import javax.swing.*;
-
-public interface SwingBinding
-{
-    void to( JComponent component );
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/SwingBindingAssembler.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/SwingBindingAssembler.java
deleted file mode 100644
index c0ae2a3..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/SwingBindingAssembler.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding;
-
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.lib.swing.binding.adapters.StringToTextFieldAdapterService;
-import org.qi4j.lib.swing.binding.internal.BoundProperty;
-import org.qi4j.lib.swing.binding.internal.StateInvocationHandler;
-
-public class SwingBindingAssembler
-    implements Assembler
-{
-
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.objects( StateModel.class, StateInvocationHandler.class, BoundProperty.class );
-        addStringToTextFieldAdapter( module );
-    }
-
-    protected void addStringToTextFieldAdapter( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( StringToTextFieldAdapterService.class );
-    }
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/adapters/StringToTextFieldAdapterService.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/adapters/StringToTextFieldAdapterService.java
deleted file mode 100644
index c5b3de2..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/adapters/StringToTextFieldAdapterService.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding.adapters;
-
-import java.util.HashSet;
-import java.util.Set;
-import javax.swing.JComponent;
-import javax.swing.JLabel;
-import javax.swing.JTextArea;
-import javax.swing.JTextField;
-import javax.swing.text.JTextComponent;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.mixin.NoopMixin;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.lib.swing.binding.SwingAdapter;
-
-@Concerns( StringToTextFieldAdapterService.StringToTextFieldAdapterConcern.class )
-@Mixins( NoopMixin.class )
-public interface StringToTextFieldAdapterService
-    extends SwingAdapter, ServiceComposite
-{
-
-    class StringToTextFieldAdapterConcern
-        extends ConcernOf<SwingAdapter>
-        implements SwingAdapter
-    {
-
-        private HashSet<Capabilities> canHandle;
-
-        public StringToTextFieldAdapterConcern()
-        {
-            canHandle = new HashSet<>();
-            canHandle.add( new Capabilities( JTextArea.class, String.class, true, false, false, false, false ) );
-            canHandle.add( new Capabilities( JTextField.class, String.class, true, false, false, false, false ) );
-            canHandle.add( new Capabilities( JLabel.class, String.class, true, false, false, false, false ) );
-        }
-
-        @Override
-        public Set<Capabilities> canHandle()
-        {
-            return canHandle;
-        }
-
-        @Override
-        public void fromSwingToProperty( JComponent component, Property property )
-        {
-            if( property == null )
-            {
-                return;
-            }
-            if( component instanceof JTextComponent )
-            {
-                JTextComponent textComponent = (JTextComponent) component;
-                property.set( textComponent.getText() );
-            }
-            else
-            {
-                JLabel labelComponent = (JLabel) component;
-                property.set( labelComponent.getText() );
-            }
-        }
-
-        @Override
-        public void fromPropertyToSwing( JComponent component, Property<?> property )
-        {
-            String value;
-            if( property == null )
-            {
-                value = "";
-            }
-            else
-            {
-                value = (String) property.get();
-            }
-            if( component instanceof JTextComponent )
-            {
-                JTextComponent textComponent = (JTextComponent) component;
-                textComponent.setText( value );
-            }
-            else
-            {
-                JLabel labelComponent = (JLabel) component;
-                labelComponent.setText( value );
-            }
-        }
-
-        @Override
-        public void fromSwingToAssociation( JComponent component, Association<?> association )
-        {
-        }
-
-        @Override
-        public void fromAssociationToSwing( JComponent component, Association<?> association )
-        {
-        }
-
-        @Override
-        public void fromSwingToSetAssociation( JComponent component, ManyAssociation<?> setAssociation )
-        {
-        }
-
-        @Override
-        public void fromSetAssociationToSwing( JComponent component, ManyAssociation<?> setAssociation )
-        {
-        }
-
-        @Override
-        public void fromSwingToNamedAssociation( JComponent component, NamedAssociation<?> namedAssociation )
-        {
-        }
-
-        @Override
-        public void fromNamedAssociationToSwing( JComponent component, NamedAssociation<?> namedAssociation )
-        {
-        }
-
-    }
-
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/Address.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/Address.java
deleted file mode 100644
index ce3447e..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/Address.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding.example;
-
-import org.qi4j.api.property.Property;
-
-public interface Address extends HasCity
-{
-    Property<String> line1();
-    Property<String> line2();
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/AddressTransient.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/AddressTransient.java
deleted file mode 100644
index 74bc153..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/AddressTransient.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding.example;
-
-import org.qi4j.api.composite.TransientComposite;
-
-public interface AddressTransient extends Address, TransientComposite
-{
-
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/BoundPersonComposite.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/BoundPersonComposite.java
deleted file mode 100644
index b6862d0..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/BoundPersonComposite.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding.example;
-
-public interface BoundPersonComposite extends PersonComposite
-{
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/City.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/City.java
deleted file mode 100644
index 978365f..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/City.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding.example;
-
-public interface City extends HasCountry, HasName
-{
-
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/CityValue.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/CityValue.java
deleted file mode 100644
index bafdaf1..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/CityValue.java
+++ /dev/null
@@ -1,25 +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.qi4j.lib.swing.binding.example;
-
-import org.qi4j.api.value.ValueComposite;
-
-public interface CityValue extends City, ValueComposite
-{
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/Country.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/Country.java
deleted file mode 100644
index 6c49c49..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/Country.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding.example;
-
-public interface Country extends HasName
-{
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/CountryValue.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/CountryValue.java
deleted file mode 100644
index 5580ddb..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/CountryValue.java
+++ /dev/null
@@ -1,25 +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.qi4j.lib.swing.binding.example;
-
-import org.qi4j.api.value.ValueComposite;
-
-public interface CountryValue extends Country, ValueComposite
-{
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/Form.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/Form.java
deleted file mode 100644
index 8bd0c8d..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/Form.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding.example;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.lib.swing.binding.StateModel;
-
-import javax.swing.*;
-import java.awt.*;
-
-public class Form<T extends BoundPersonComposite> extends JPanel
-{
-
-    private final StateModel<T> aModel;
-
-    public Form( StateModel<T> aModel )
-    {
-        this.aModel = aModel;
-        T state = aModel.state();
-
-        JPanel firstNameField = newPersonFirstNameField( aModel, state );
-        add( firstNameField );
-        JPanel userAddressLine1Field = newUserFirstLineAddressField( aModel, state );
-        add( userAddressLine1Field );
-        JPanel userAddressLine2Field = newUserSecondLineAddressField( aModel, state );
-        add( userAddressLine2Field );
-        JPanel userCityField = newUserCityField( aModel, state );
-        add( userCityField );
-        JPanel userCountryField = newUserCountryField( aModel, state );
-        add( userCountryField );
-        setLayout( new BoxLayout( this, BoxLayout.Y_AXIS ) );
-    }
-
-    public StateModel<T> getAModel()
-    {
-        return aModel;
-    }
-
-    private JPanel newPersonFirstNameField( StateModel<T> aModel, T aModelState )
-    {
-        Property<String> property = aModelState.firstName();
-        return newTextPanel( aModel, property, "First Name:" );
-    }
-
-    private JPanel newUserFirstLineAddressField( StateModel<T> aModel, T aModelState )
-    {
-        Property<String> property = aModelState.address().get().line1();
-        return newTextPanel( aModel, property, "Address:" );
-    }
-
-    private JPanel newUserSecondLineAddressField( StateModel<T> aModel, T state )
-    {
-        Property<String> property = state.address().get().line2();
-        return newTextPanel( aModel, property, "" );
-    }
-
-    private JPanel newUserCityField( StateModel<T> aModel, T state )
-    {
-        Property<String> property = state.address().get().city().get().name();
-        return newTextPanel( aModel, property, "City:" );
-    }
-
-    private JPanel newUserCountryField( StateModel<T> aModel, T state )
-    {
-        Property<String> property = state.address().get().city().get().country().get().name();
-        return newTextPanel( aModel, property, "Country:" );
-    }
-
-    private JPanel newTextPanel( StateModel<T> aModel, Property<String> property, String fieldName )
-    {
-        JPanel panel = new JPanel();
-        JLabel label = new JLabel( fieldName );
-        label.setPreferredSize( new Dimension( 100, 20 ) );
-        panel.add( label );
-        JTextField textField = new JTextField();
-        panel.add( textField );
-        textField.setPreferredSize( new Dimension( 100, 20 ) );
-        aModel.bind( property ).to( textField );
-        return panel;
-    }
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/HasAddress.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/HasAddress.java
deleted file mode 100644
index e8d190d..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/HasAddress.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding.example;
-
-import org.qi4j.api.property.Property;
-
-public interface HasAddress
-{
-    Property<Address> address();
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/HasCity.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/HasCity.java
deleted file mode 100644
index 086469e..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/HasCity.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding.example;
-
-import org.qi4j.api.property.Property;
-
-public interface HasCity
-{
-    Property<City> city();
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/HasCountry.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/HasCountry.java
deleted file mode 100644
index ab5e747..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/HasCountry.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding.example;
-
-import org.qi4j.api.property.Property;
-
-public interface HasCountry
-{
-    Property<Country> country();
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/HasName.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/HasName.java
deleted file mode 100644
index 52b7e6f..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/HasName.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding.example;
-
-import org.qi4j.api.property.Property;
-
-public interface HasName
-{
-    Property<String> name();
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/Main.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/Main.java
deleted file mode 100644
index 4d858a7..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/Main.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding.example;
-
-import java.awt.BorderLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.FocusEvent;
-import java.awt.event.FocusListener;
-import javax.swing.JCheckBox;
-import javax.swing.JFrame;
-import javax.swing.JPanel;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.lib.swing.binding.StateModel;
-import org.qi4j.lib.swing.binding.SwingBindingAssembler;
-
-public class Main
-{
-
-    private static Module module;
-
-    public static void main( String[] args )
-        throws Exception
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( BoundPersonComposite.class );
-                module.transients( AddressTransient.class );
-                module.values( CityValue.class, CountryValue.class );
-                new SwingBindingAssembler().assemble( module );
-            }
-        };
-        module = assembler.module();
-        Address address1 = createAddress( "Vista Damai", "Jalan Tun Razak" );
-        Address address2 = createAddress( "Mutiara", "Jalan Ceylon" );
-
-        TransientBuilder<BoundPersonComposite> builder = module.newTransientBuilder( BoundPersonComposite.class );
-        PersonComposite prototype = builder.prototype();
-        prototype.address().set( address1 );
-        prototype.firstName().set( "Niclas" );
-        final BoundPersonComposite p1 = builder.newInstance();
-
-        prototype.address().set( address2 );
-        prototype.firstName().set( "Edward" );
-        final BoundPersonComposite p2 = builder.newInstance();
-
-        final StateModel<BoundPersonComposite> model = module.newObject( StateModel.class, BoundPersonComposite.class );
-        Form form = new Form<BoundPersonComposite>( model );
-
-        JFrame frame = new JFrame( "testing" );
-
-        frame.add( form, BorderLayout.CENTER );
-        JPanel checkBoxPanel = new JPanel();
-        checkBoxPanel.setFocusable( true );
-        checkBoxPanel.addFocusListener( new FocusListener()
-        {
-
-            public void focusGained( FocusEvent e )
-            {
-                System.out.println( "Gained!" );
-            }
-
-            public void focusLost( FocusEvent e )
-            {
-                System.out.println( "LOst!" );
-            }
-        } );
-        JCheckBox sw = new JCheckBox( "Toggle" );
-        sw.addActionListener( new ActionListener()
-        {
-
-            public void actionPerformed( ActionEvent e )
-            {
-                if( ( (JCheckBox) e.getSource() ).isSelected() )
-                {
-                    model.use( p1 );
-                    System.out.println( p1.firstName().get() );
-                }
-                else
-                {
-                    model.use( p2 );
-                    System.out.println( p2.firstName().get() );
-                }
-            }
-        }
-        );
-        checkBoxPanel.add( sw );
-        frame.add( checkBoxPanel, BorderLayout.EAST );
-        frame.pack();
-        System.out.println( model );
-        frame.setVisible( true );
-        frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
-    }
-
-    private static Address createAddress( String line1, String line2 )
-    {
-        TransientBuilder<Address> addressBuilder = module.newTransientBuilder( Address.class );
-        addressBuilder.prototype().line1().set( line1 );
-        addressBuilder.prototype().line2().set( line2 );
-        addressBuilder.prototype().city().set( createCity("Kuala Lumpur") );
-        return addressBuilder.newInstance();
-    }
-
-    private static City createCity( String cityName )
-    {
-        ValueBuilder<City> builder = module.newValueBuilder( City.class );
-        builder.prototype().name().set( cityName );
-        builder.prototype().country().set( createCountry( "Malaysia" ) );
-        return builder.newInstance();
-    }
-
-    private static Country createCountry( String countryName )
-    {
-        ValueBuilder<Country> builder = module.newValueBuilder( Country.class );
-        builder.prototype().name().set( countryName );
-        return builder.newInstance();
-    }
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/Person.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/Person.java
deleted file mode 100644
index 045833a..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/Person.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding.example;
-
-import org.qi4j.api.property.Property;
-
-public interface Person extends HasAddress
-{
-    Property<String> firstName();
-//    Property<String> lastName();
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/PersonComposite.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/PersonComposite.java
deleted file mode 100644
index 22f3a94..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/example/PersonComposite.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding.example;
-
-import org.qi4j.api.composite.TransientComposite;
-
-public interface PersonComposite extends Person, TransientComposite
-{
-
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/AbstractBinding.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/AbstractBinding.java
deleted file mode 100644
index 17396db..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/AbstractBinding.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding.internal;
-
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.object.ObjectFactory;
-import org.qi4j.lib.swing.binding.StateModel;
-import org.qi4j.lib.swing.binding.SwingAdapter;
-import org.qi4j.lib.swing.binding.SwingBinding;
-
-import javax.swing.*;
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
-
-public abstract class AbstractBinding<T>
-    implements SwingBinding
-{
-
-    private final Class<T> type;
-    protected StateModel<T> stateModel;
-    protected Set<JComponent> components;
-    private PropertyFocusLostListener focusListener;
-    protected HashMap<Class<? extends JComponent>, SwingAdapter> adapters;
-    private String name;
-    protected Method method;
-
-    @SuppressWarnings( "unchecked" )
-    public AbstractBinding( @Uses Method method, @Structure ObjectFactory objectBuilderFactory,
-                            @Service Iterable<SwingAdapter> allAdapters )
-        throws IllegalArgumentException
-    {
-        this.method = method;
-        ParameterizedType parameterType = (ParameterizedType) method.getGenericReturnType();
-        Type[] actualTypeArguments = parameterType.getActualTypeArguments();
-        type = (Class<T>) actualTypeArguments[ 0 ];
-        name = method.getName();
-        stateModel = objectBuilderFactory.newObject( StateModel.class, type );
-        components = new HashSet<JComponent>();
-        setupAdapters( allAdapters );
-    }
-
-    public void to( final JComponent component )
-    {
-        if( components.add( component ) )
-        {
-            focusListener = new PropertyFocusLostListener( component );
-            component.addFocusListener( focusListener );
-        }
-    }
-
-    public String toString()
-    {
-        return name + "[" + type.getSimpleName() + "] -> " + stateModel.toString();
-    }
-
-    private void setupAdapters( Iterable<SwingAdapter> allAdapters )
-    {
-        adapters = new HashMap<Class<? extends JComponent>, SwingAdapter>();
-        for( SwingAdapter adapterCandidate : allAdapters )
-        {
-            Set<SwingAdapter.Capabilities> canHandle = adapterCandidate.canHandle();
-            for( SwingAdapter.Capabilities capabilities : canHandle )
-            {
-                if( requiredCapabilitySatisfied( capabilities ) )
-                {
-                    if( capabilities.type.equals( this.type ) )
-                    {
-                        Class<? extends JComponent> component = capabilities.component;
-                        adapters.put( component, adapterCandidate );
-                    }
-                }
-            }
-        }
-    }
-
-    protected abstract boolean requiredCapabilitySatisfied( SwingAdapter.Capabilities capabilities );
-
-    public final T get()
-    {
-        return stateModel.state();
-    }
-
-    public final Class type()
-    {
-        return type;
-    }
-
-    public void set( T newValue )
-        throws IllegalArgumentException
-    {
-        throw new IllegalArgumentException( "set() is not allowed in binding templates." );
-    }
-
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/AssociationFocusLostListener.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/AssociationFocusLostListener.java
deleted file mode 100644
index 425c94c..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/AssociationFocusLostListener.java
+++ /dev/null
@@ -1,58 +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.qi4j.lib.swing.binding.internal;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.lib.swing.binding.SwingAdapter;
-
-import javax.swing.*;
-import java.awt.event.FocusEvent;
-import java.awt.event.FocusListener;
-
-public class AssociationFocusLostListener
-    implements FocusListener
-{
-
-    private final JComponent component;
-    private SwingAdapter adapter;
-    private Association actual;
-
-    public AssociationFocusLostListener( JComponent component )
-    {
-        this.component = component;
-    }
-
-    void use( SwingAdapter adapterToUse, Association actual )
-    {
-        adapter = adapterToUse;
-        this.actual = actual;
-    }
-
-    public void focusGained( FocusEvent e )
-    {
-    }
-
-    public void focusLost( FocusEvent e )
-    {
-        if( adapter != null )
-        {
-            adapter.fromSwingToAssociation( component, actual );
-        }
-    }
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundAssociation.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundAssociation.java
deleted file mode 100644
index b927cc3..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundAssociation.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding.internal;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.object.ObjectFactory;
-import org.qi4j.lib.swing.binding.Binding;
-import org.qi4j.lib.swing.binding.SwingAdapter;
-
-import javax.swing.*;
-import java.awt.event.FocusListener;
-import java.lang.reflect.Method;
-
-public final class BoundAssociation<T> extends AbstractBinding<T>
-    implements Association<T>, Binding
-{
-
-    private Association<T> actual;
-
-    /**
-     * Construct an instance of {@code BoundAssociation} with the specified arguments.
-     *
-     * @param associationMethod The method that returns Assocation. This argument must not be {@code null}.
-     *
-     * @throws IllegalArgumentException Thrown if the specified {@code aMethod} is {@code null}.
-     */
-    public BoundAssociation( @Uses Method associationMethod, @Structure ObjectFactory objectBuilderFactory,
-                             @Service Iterable<SwingAdapter> allAdapters )
-        throws IllegalArgumentException
-    {
-        super( associationMethod, objectBuilderFactory, allAdapters );
-
-    }
-
-    public void use( Association<T> actualAssociation )
-    {
-        actual = actualAssociation;
-        T value = null;
-        if( actualAssociation != null )
-        {
-            value = actualAssociation.get();
-        }
-        stateModel.use( value );
-        for( JComponent component : components )
-        {
-            SwingAdapter adapter = adapters.get( component.getClass() );
-            adapter.fromAssociationToSwing( component, actualAssociation );
-            for( FocusListener listener : component.getFocusListeners() )
-            {
-                if( AssociationFocusLostListener.class.isInstance( listener ) )
-                {
-                    ( (AssociationFocusLostListener) listener ).use( adapter, actual );
-                }
-            }
-        }
-    }
-
-    protected boolean requiredCapabilitySatisfied( SwingAdapter.Capabilities capabilities )
-    {
-        return capabilities.association;
-    }
-
-    public void to( JComponent component )
-    {
-        //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @Override
-    public EntityReference reference()
-    {
-        return actual.reference();
-    }
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundManyAssociation.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundManyAssociation.java
deleted file mode 100644
index 19a0a36..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundManyAssociation.java
+++ /dev/null
@@ -1,108 +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.qi4j.lib.swing.binding.internal;
-
-import java.lang.reflect.Method;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.object.ObjectFactory;
-import org.qi4j.lib.swing.binding.Binding;
-import org.qi4j.lib.swing.binding.SwingAdapter;
-
-public class BoundManyAssociation<T> extends AbstractBinding<T>
-    implements Binding, ManyAssociation<T>
-{
-
-    private ManyAssociation<T> actualAssociations;
-
-    public BoundManyAssociation( @Uses Method method, @Structure ObjectFactory objectBuilderFactory,
-                                 @Service Iterable<SwingAdapter> allAdapters
-    )
-        throws IllegalArgumentException
-    {
-        super( method, objectBuilderFactory, allAdapters );
-    }
-
-    protected boolean requiredCapabilitySatisfied( SwingAdapter.Capabilities capabilities )
-    {
-        return false;
-    }
-
-    public boolean add( T o )
-    {
-        return actualAssociations.add( o );
-    }
-
-    public boolean remove( T o )
-    {
-        return actualAssociations.remove( o );
-    }
-
-    public T get( int index )
-    {
-        return actualAssociations.get( index );
-    }
-
-    @Override
-    public List<T> toList()
-    {
-        return actualAssociations.toList();
-    }
-
-    @Override
-    public Set<T> toSet()
-    {
-        return actualAssociations.toSet();
-    }
-
-    @Override
-    public Iterable<EntityReference> references()
-    {
-        return actualAssociations.references();
-    }
-
-    @Override
-    public int count()
-    {
-        return actualAssociations.count();
-    }
-
-    @Override
-    public boolean contains( T entity )
-    {
-        return actualAssociations.contains( entity );
-    }
-
-    public boolean add( int index, T element )
-    {
-        return actualAssociations.add( index, element );
-    }
-
-    @Override
-    public Iterator<T> iterator()
-    {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundNamedAssociation.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundNamedAssociation.java
deleted file mode 100644
index 553adcc..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundNamedAssociation.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.qi4j.lib.swing.binding.internal;
-
-import java.lang.reflect.Method;
-import java.util.Iterator;
-import java.util.Map;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.entity.EntityReference;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.object.ObjectFactory;
-import org.qi4j.lib.swing.binding.Binding;
-import org.qi4j.lib.swing.binding.SwingAdapter;
-
-public class BoundNamedAssociation<T>
-    extends AbstractBinding<T>
-    implements Binding, NamedAssociation<T>
-{
-
-    private NamedAssociation<T> actualAssociations;
-
-    public BoundNamedAssociation( @Uses Method method, @Structure ObjectFactory objectBuilderFactory,
-                                  @Service Iterable<SwingAdapter> allAdapters
-    )
-        throws IllegalArgumentException
-    {
-        super( method, objectBuilderFactory, allAdapters );
-    }
-
-    @Override
-    protected boolean requiredCapabilitySatisfied( SwingAdapter.Capabilities capabilities )
-    {
-        return false;
-    }
-
-    @Override
-    public int count()
-    {
-        return actualAssociations.count();
-    }
-
-    @Override
-    public boolean containsName( String name )
-    {
-        return actualAssociations.containsName( name );
-    }
-
-    @Override
-    public boolean put( String name, T entity )
-    {
-        return actualAssociations.put( name, entity );
-    }
-
-    @Override
-    public boolean remove( String name )
-    {
-        return actualAssociations.remove( name );
-    }
-
-    @Override
-    public T get( String name )
-    {
-        return actualAssociations.get( name );
-    }
-
-    @Override
-    public String nameOf( T entity )
-    {
-        return actualAssociations.nameOf( entity );
-    }
-
-    @Override
-    public Map<String, T> toMap()
-    {
-        return actualAssociations.toMap();
-    }
-
-    @Override
-    public Iterable<EntityReference> references()
-    {
-        return actualAssociations.references();
-    }
-
-    @Override
-    public EntityReference referenceOf( String name )
-    {
-        return actualAssociations.referenceOf( name );
-    }
-
-    @Override
-    public Iterator<String> iterator()
-    {
-        return actualAssociations.iterator();
-    }
-
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundProperty.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundProperty.java
deleted file mode 100644
index 7d22b44..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundProperty.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman. All rights Reserved.
- *
- * Licensed  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.qi4j.lib.swing.binding.internal;
-
-import java.awt.event.FocusListener;
-import java.lang.reflect.Method;
-import javax.swing.JComponent;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.object.ObjectFactory;
-import org.qi4j.api.property.Property;
-import org.qi4j.lib.swing.binding.Binding;
-import org.qi4j.lib.swing.binding.SwingAdapter;
-
-public final class BoundProperty<T> extends AbstractBinding<T>
-    implements Property<T>, Binding
-{
-
-    private Property propertyInfo;
-
-    /**
-     * Construct an instance of {@code BoundProperty} with the specified arguments.
-     *
-     * @param propertyMethod The method that returns Property. This argument must not be {@code null}.
-     *
-     * @throws IllegalArgumentException Thrown if the specified {@code aMethod} is {@code null}.
-     */
-    public BoundProperty( @Uses Method propertyMethod, @Structure ObjectFactory objectBuilderFactory,
-                          @Service Iterable<SwingAdapter> allAdapters
-    )
-        throws IllegalArgumentException
-    {
-        super( propertyMethod, objectBuilderFactory, allAdapters );
-    }
-
-    public void use( Property<T> actualProperty )
-    {
-        T value = null;
-        if( actualProperty != null )
-        {
-            value = actualProperty.get();
-        }
-        stateModel.use( value );
-        for( JComponent component : components )
-        {
-            SwingAdapter adapter = adapters.get( component.getClass() );
-            adapter.fromPropertyToSwing( component, actualProperty );
-            for( FocusListener listener : component.getFocusListeners() )
-            {
-                if( PropertyFocusLostListener.class.isInstance( listener ) )
-                {
-                    ( (PropertyFocusLostListener) listener ).use( adapter, actualProperty );
-                }
-            }
-        }
-    }
-
-    protected boolean requiredCapabilitySatisfied( SwingAdapter.Capabilities capabilities )
-    {
-        return capabilities.property;
-    }
-}
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/PropertyFocusLostListener.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/PropertyFocusLostListener.java
deleted file mode 100644
index e04702a..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/PropertyFocusLostListener.java
+++ /dev/null
@@ -1,59 +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.qi4j.lib.swing.binding.internal;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.lib.swing.binding.SwingAdapter;
-
-import javax.swing.*;
-import java.awt.event.FocusEvent;
-import java.awt.event.FocusListener;
-
-class PropertyFocusLostListener
-    implements FocusListener
-{
-
-    private final JComponent component;
-    private SwingAdapter adapter;
-    private Property actual;
-
-    public PropertyFocusLostListener( JComponent component )
-    {
-        this.component = component;
-    }
-
-    void use( SwingAdapter adapterToUse, Property actual )
-    {
-        adapter = adapterToUse;
-        this.actual = actual;
-    }
-
-    public void focusGained( FocusEvent e )
-    {
-    }
-
-    public void focusLost( FocusEvent e )
-    {
-        if( adapter != null )
-        {
-            adapter.fromSwingToProperty( component, actual );
-        }
-    }
-}
-
diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/StateInvocationHandler.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/StateInvocationHandler.java
deleted file mode 100644
index e326d9e..0000000
--- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/StateInvocationHandler.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
- *
- * Licensed 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.qi4j.lib.swing.binding.internal;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Map;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.structure.Module;
-
-public final class StateInvocationHandler<T>
-    implements InvocationHandler
-{
-
-    @Structure
-    private Module module;
-
-    private final HashMap<Method, BoundProperty> properties;
-    private final HashMap<Method, BoundAssociation> associations;
-    private final HashMap<Method, BoundManyAssociation> manyassociations;
-    private final HashMap<Method, BoundNamedAssociation> namedassociations;
-    private final Class<?> type;
-
-    public StateInvocationHandler( @Uses Class<?> aType )
-    {
-        type = aType;
-        properties = new HashMap<>();
-        associations = new HashMap<>();
-        manyassociations = new HashMap<>();
-        namedassociations = new HashMap<>();
-    }
-
-    public final Object invoke( Object aProxy, Method aMethod, Object[] args )
-        throws Throwable
-    {
-        if( "toString".equals( aMethod.getName() ) )
-        {
-            return type.toString() + "( " + properties.values() + ")";
-        }
-        Class<?> methodReturnType = aMethod.getReturnType();
-        if( Property.class.isAssignableFrom( methodReturnType ) )
-        {
-            BoundProperty property = properties.get( aMethod );
-            if( property == null )
-            {
-                property = module.newObject( BoundProperty.class, aMethod );
-                properties.put( aMethod, property );
-            }
-
-            return property;
-        }
-        else if( NamedAssociation.class.isAssignableFrom( methodReturnType ) )
-        {
-            BoundNamedAssociation association = namedassociations.get( aMethod );
-            if( association == null )
-            {
-                association = module.newObject( BoundNamedAssociation.class, aMethod );
-                namedassociations.put( aMethod, association );
-            }
-            return association;
-        }
-        else if( ManyAssociation.class.isAssignableFrom( methodReturnType ) )
-        {
-            BoundManyAssociation association = manyassociations.get( aMethod );
-            if( association == null )
-            {
-                association = module.newObject( BoundManyAssociation.class, aMethod );
-                manyassociations.put( aMethod, association );
-            }
-            return association;
-        }
-        else if( Association.class.isAssignableFrom( methodReturnType ) )
-        {
-            BoundAssociation association = associations.get( aMethod );
-            if( association == null )
-            {
-                association = module.newObject( BoundAssociation.class, aMethod );
-                associations.put( aMethod, association );
-            }
-            return association;
-        }
-        return null;
-    }
-
-    public void use( T actualData )
-    {
-        for( Map.Entry<Method, BoundProperty> entry : properties.entrySet() )
-        {
-            BoundProperty bound = entry.getValue();
-            Property actualProperty = null;
-            if( actualData != null )
-            {
-                Method method = entry.getKey();
-                try
-                {
-                    actualProperty = (Property) method.invoke( actualData );
-                }
-                catch( IllegalAccessException | InvocationTargetException e )
-                {
-                    e.printStackTrace();  //TODO: Auto-generated, need attention.
-                }
-            }
-            bound.use( actualProperty );
-        }
-    }
-}
diff --git a/settings.gradle b/settings.gradle
index a66fd66..3c44077 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,25 +1,26 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
  */
 
-include 'core:functional',
-        'core:io',
-        'core:api',
+apply plugin: 'polygene-settings'
+
+rootProject.name = 'polygene-java'
+
+include 'core:api',
         'core:spi',
         'core:testsupport',
         'core:bootstrap',
@@ -27,27 +28,19 @@
         'libraries:alarm',
         'libraries:circuitbreaker',
         'libraries:constraints',
-        'libraries:conversion',
-        'libraries:eventsourcing',
-        'libraries:eventsourcing-jdbm',
-        'libraries:eventsourcing-rest',
         'libraries:fileconfig',
         'libraries:http',
         'libraries:invocation-cache',
-        'libraries:lang-groovy',
-        'libraries:lang-javascript',
-        'libraries:lang-scala',
         'libraries:jmx',
         'libraries:locking',
         'libraries:logging',
-        'libraries:metrics',
         'libraries:osgi',
         'libraries:rdf',
         'libraries:rest',
         'libraries:rest-client',
         'libraries:rest-common',
         'libraries:rest-server',
-        'libraries:scheduler',
+        'libraries:restlet',
         'libraries:scripting',
         'libraries:servlet',
         'libraries:shiro-core',
@@ -56,17 +49,20 @@
         'libraries:sql',
         'libraries:sql-bonecp',
         'libraries:sql-dbcp',
+        'libraries:sql-generator',
         'libraries:sql-liquibase',
         'libraries:uid',
         'libraries:uowfile',
         'extensions:cache-ehcache',
         'extensions:cache-memcache',
-        'extensions:entitystore-memory',
+        'extensions:entitystore-cassandra',
         'extensions:entitystore-file',
+        'extensions:entitystore-geode',
         'extensions:entitystore-hazelcast',
         'extensions:entitystore-jclouds',
         'extensions:entitystore-jdbm',
         'extensions:entitystore-leveldb',
+        'extensions:entitystore-memory',
         'extensions:entitystore-mongodb',
         'extensions:entitystore-preferences',
         'extensions:entitystore-redis',
@@ -76,24 +72,18 @@
         'extensions:indexing-rdf',
         'extensions:indexing-solr',
         'extensions:indexing-sql',
-        'extensions:metrics-yammer',
+        'extensions:metrics-codahale',
         'extensions:migration',
         'extensions:reindexer',
-        'extensions:valueserialization-orgjson',
-        'extensions:valueserialization-jackson',
-        'extensions:valueserialization-stax',
-        'manual',
-        'samples:dci',
-        'samples:dci-cargo:dcisample_a',
-        'samples:dci-cargo:dcisample_b',
-        'samples:forum',
-        'samples:rental',
-        'samples:sql-support',
-        'samples:swing',
+        'extensions:serialization-javaxjson',
+        'extensions:serialization-javaxxml',
+        'extensions:serialization-messagepack',
         'tools:model-detail',
         'tools:envisage',
-        'tools:shell',
+        'tools:generator-polygene',
 //        'tools:qidea',
+        'tests:regression',
+        'tests:performance',
         'tutorials:cargo',
         'tutorials:composites',
         'tutorials:hello',
@@ -103,35 +93,12 @@
         'tutorials:introduction:thirtyminutes',
 //        'tutorials:introduction:twohours',
         'tutorials:services',
-        'tests:regression',
-        'tests:performance'
+        'samples:dci',
+        'samples:forum',
+        'samples:rental',
+        'samples:sql-support',
+        'samples:swing'
 
-rootProject.name = "org.qi4j"
+include 'internals:testsupport-internal'
 
-validateProject(rootProject, "")
-
-def validateProject(project, parentName)
-{
-    assert project.projectDir.isDirectory()
-    if( new File("$project.projectDir/src/main/java").exists() )
-    {
-        assert project.buildFile.isFile()
-    }
-    if( parentName == 'org.qi4j.libraries' )
-    {
-        parentName = 'org.qi4j.library'
-    }
-    if( parentName.endsWith('s') )
-    {
-        parentName = parentName.substring(0, parentName.length() - 1)
-    }
-    if( parentName.length() > 0 )
-    {
-        project.name = parentName + "." + project.name
-    }
-    println "Project: " + project.name
-    project.children.each { child ->
-        validateProject(child, project.name)
-    }
-}
-
+include 'manual', 'reports', 'distributions', 'release'
diff --git a/src/bin-dist/NOTICE.txt b/src/bin-dist/NOTICE.txt
deleted file mode 100644
index 9f7b1a6..0000000
--- a/src/bin-dist/NOTICE.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Apache Zest™ (Java Edition) SDK Binary Distribution
-Copyright 2015 The Apache Software Foundation.
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
diff --git a/src/bin-dist/README.txt b/src/bin-dist/README.txt
deleted file mode 100644
index e83242a..0000000
--- a/src/bin-dist/README.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-
-Welcome to the world of Apache Zest
-   - Composite Oriented Programming on the Java platform.
-
-
-This Apache Zest™ Binary Distribution contains everything you need to
-create Zest™ applications.
-
-
-Zest™ (then Zest™) started in 2007, and is still in heavy development
-at the Apache Software Foundation. We would like
-developers around the world to participate in the advancement of this
-cool, new and challenging technology. We are especially interested in
-people willing to help improve the SDK, samples, tutorials, documentation
-and other supporting material.
-
-Please see https://zest.apache.org for more information.
-
-
-Licensing
----------
-All Apache Zest™ code is licensed under an Apache License.
-
-Third-Party Dependencies may be licensed under other terms. The only
-required dependencies are SLF4J (MIT Licence), ASM (BSD Licence) and
-Joda-Time (Apache Licence).
-
-Finally, Zest™ TestSupport depends on JUnit 4.x and its dependencies, which
-is also not included in the SDK itself, as it is present among most Java
-developers.
-
-
-Dependencies not included
--------------------------
-The binary distributions contains Zest™ artifacts only to keep the download
-size small. Each Zest™ artifact comes with a file prefixed ..-runtime-deps.txt
-that contains the list of its dependencies. Moreover, at the binary
-distribution's root, you'll find both Maven (go-offline.pom) and Gradle
-(go-offline.gradle) build files whoses sole purpose is to easily download all
-needed dependencies jars. Instructions are given into theses files.
-
-If you prefer to use a dependency management system, go to:
-https://zest.apache.org/java/latest/howto-depend-on-zest.html
-
-
-Thank you for trying out Apache Zest™ and Composite Oriented Programming.
-
-
--- Apache Zest™ Team
-
diff --git a/src/javadoc/overview.html b/src/javadoc/overview.html
deleted file mode 100644
index 38affee..0000000
--- a/src/javadoc/overview.html
+++ /dev/null
@@ -1,23 +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.
--->
-<html>
-    <body>
-        <h3>Welcome to the Apache Zest™ (Java Edition) SDK Javadoc.</h3>
-        <p>Apache Zest™ is a framework for domain centric application development, including evolved concepts from AOP, DI and DDD.</p>
-        <p><a href="https://zest.apache.org" target="_blank">zest.apache.org</a></p>
-    </body>
-</html>
diff --git a/tests/performance/build.gradle b/tests/performance/build.gradle
index 8ebd698..1ff9b45 100644
--- a/tests/performance/build.gradle
+++ b/tests/performance/build.gradle
@@ -1,60 +1,44 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
  */
+import org.apache.polygene.gradle.structure.tests.PerformanceTestsPlugin
 
-description = "Apache Zest™ Performance Test Suite."
+apply plugin: 'polygene-test'
 
-jar { manifest { name = "Apache Zest™ Tests - Performance" }}
+description = "Apache Polygene™ Performance Test Suite."
 
-sourceSets {
-    perf
-}
+jar { manifest { name = "Apache Polygene™ Tests - Performance" } }
+
+apply plugin: PerformanceTestsPlugin
 
 dependencies {
+  implementation polygene.core.bootstrap
+  implementation libraries.junit
+  implementation libraries.slf4j_api
 
-    compile project( ":org.qi4j.core:org.qi4j.core.bootstrap" )
-    compile libraries.junit
-    compile libraries.slf4j_api
+  perfImplementation polygene.core.testsupport
+  perfImplementation polygene.library( 'sql-dbcp' )
+  perfImplementation polygene.extension( 'entitystore-memory' )
+  perfImplementation polygene.extension( 'entitystore-jdbm' )
+  perfImplementation polygene.extension( 'entitystore-sql' )
+  perfImplementation polygene.extension( 'cache-ehcache' )
+  perfImplementation polygene.extension( 'indexing-rdf' )
+  perfImplementation libraries.derby
 
-    perfCompile sourceSets.main.output
-    perfCompile configurations.testCompile
-    perfCompile sourceSets.test.output
-    perfRuntime configurations.testRuntime
-    
-    perfCompile project( ":org.qi4j.core:org.qi4j.core.testsupport" )
-    perfCompile project( ":org.qi4j.libraries:org.qi4j.library.sql-dbcp" )
-    perfCompile project( ':org.qi4j.extensions:org.qi4j.extension.valueserialization-orgjson' )
-    perfCompile project( ":org.qi4j.extensions:org.qi4j.extension.entitystore-memory" )
-    perfCompile project( ":org.qi4j.extensions:org.qi4j.extension.entitystore-jdbm" )
-    perfCompile project( ":org.qi4j.extensions:org.qi4j.extension.entitystore-sql" )
-    perfCompile project( ":org.qi4j.extensions:org.qi4j.extension.cache-ehcache" )
-    perfCompile project( ":org.qi4j.extensions:org.qi4j.extension.indexing-rdf" )
-    perfCompile libraries.derby
-
-    perfRuntime project(":org.qi4j.core:org.qi4j.core.runtime")
-    perfRuntime libraries.logback
-
-}
-
-check.dependsOn compilePerfJava
-
-task testPerf( type: Test, dependsOn: jar ) {
-    testClassesDir = sourceSets.perf.output.classesDir
-    classpath = sourceSets.perf.runtimeClasspath
-    systemProperties['jar.path'] = jar.archivePath
+  perfRuntimeOnly polygene.core.runtime
+  perfRuntimeOnly libraries.logback
 }
diff --git a/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/AbstractEntityStorePerformanceTest.java b/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/AbstractEntityStorePerformanceTest.java
new file mode 100644
index 0000000..69d1f69
--- /dev/null
+++ b/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/AbstractEntityStorePerformanceTest.java
@@ -0,0 +1,368 @@
+/*
+ *  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.polygene.test.performance.entitystore;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Random;
+import java.util.concurrent.Callable;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.bootstrap.ApplicationAssemblerAdapter;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.polygene.api.usecase.UsecaseBuilder.newUsecase;
+
+/**
+ * Performance Test Suite for Entity Stores.
+ */
+public abstract class AbstractEntityStorePerformanceTest
+{
+    private final String storeName;
+    private final Assembler infrastructure;
+    private final Logger logger;
+    private Application application;
+    protected UnitOfWorkFactory uowf;
+    protected ServiceFinder serviceFinder;
+
+    private final int ITERATIONS = 20000;
+
+    protected AbstractEntityStorePerformanceTest( String storeName, Assembler infrastructure )
+    {
+        this.storeName = storeName;
+        this.infrastructure = infrastructure;
+        this.logger = LoggerFactory.getLogger( getClass().getPackage().getName() + "." + storeName );
+    }
+
+    @Before
+    public void warmup()
+        throws Exception
+    {
+        try
+        {
+            Assembler assembler = module -> module.entities( SimpleProduct.class );
+            createPolygeneRuntime( assembler );
+
+            for( int i = 0; i < 10000; i++ )
+            {
+                try (UnitOfWork uow = uowf.newUnitOfWork( newUsecase( "Warmup " + i ) ))
+                {
+                    SimpleProduct product = uow.newEntity( SimpleProduct.class );
+                    product.identity().get();
+                }
+            }
+        }
+        catch( Exception ex )
+        {
+            logger.error( "Unable to warmup: {}", ex.getMessage(), ex );
+            throw ex;
+        }
+        finally
+        {
+            cleanUp();
+        }
+    }
+
+    @Test
+    public void whenCreateEntityWithSinglePropertyThenRecordIterationsPerSecond()
+        throws Exception
+    {
+        try
+        {
+            Assembler assembler = module -> module.entities( SimpleProduct.class );
+            createPolygeneRuntime( assembler );
+
+            profile( () -> {
+                Report report = new Report( storeName );
+                report.start( "createEntityWithSingleProperty" );
+                for( int i = 0; i < ITERATIONS; i++ )
+                {
+                    try (UnitOfWork uow = uowf.newUnitOfWork( newUsecase( "createEntityWithSingleProperty " + i ) ))
+                    {
+                        SimpleProduct product = uow.newEntity( SimpleProduct.class );
+                        product.identity().get();
+                        uow.complete();
+                    }
+                    if( i % 1000 == 0 )
+                    {
+                        logger.info( "Iteration {}", i );
+                    }
+                }
+                report.stop( ITERATIONS );
+                writeReport( report );
+                return null;
+            } );
+        }
+        finally
+        {
+            cleanUp();
+        }
+    }
+
+    @Test
+    public void whenCreateEntityWithSinglePropertyInBatchThenRecordIterationsPerSecond()
+        throws Exception
+    {
+        try
+        {
+            Assembler assembler = module -> module.entities( SimpleProduct.class );
+            createPolygeneRuntime( assembler );
+            profile( () -> {
+                Report report = new Report( storeName );
+                report.start( "createEntityInBulkWithSingleProperty" );
+                int bulk = 0;
+                UnitOfWork uow = uowf.newUnitOfWork( newUsecase( "createEntityInBulkWithSingleProperty " + bulk ) );
+                for( int i = 0; i < ITERATIONS; i++ )
+                {
+                    SimpleProduct product = uow.newEntity( SimpleProduct.class );
+                    product.identity().get();
+                    if( i % 1000 == 0 )
+                    {
+                        uow.complete();
+                        bulk++;
+                        uow = uowf.newUnitOfWork( newUsecase( "createEntityInBulkWithSingleProperty " + bulk ) );
+                    }
+                }
+                uow.complete();
+                report.stop( ITERATIONS );
+                writeReport( report );
+                return null;
+            } );
+        }
+        finally
+        {
+            cleanUp();
+        }
+    }
+
+    @Test
+    public void whenCreateEntityWithComplexTypeThenRecordIterationsPerSecond()
+        throws Exception
+    {
+        try
+        {
+            Assembler assembler = module -> module.entities( ComplexProduct.class );
+            createPolygeneRuntime( assembler );
+            profile( () -> {
+                Report report = new Report( storeName );
+                report.start( "createEntityWithComplexType" );
+                for( int i = 0; i < ITERATIONS; i++ )
+                {
+                    try (UnitOfWork uow = uowf.newUnitOfWork( newUsecase( "createEntityWithComplexType " + i ) ))
+                    {
+                        ComplexProduct product = uow.newEntity( ComplexProduct.class );
+                        product.identity().get();
+                        uow.complete();
+                    }
+                }
+                report.stop( ITERATIONS );
+                writeReport( report );
+                return null;
+            } );
+        }
+        finally
+        {
+            cleanUp();
+        }
+    }
+
+    @Test
+    public void whenCreateEntityWithComplexTypeInBatchThenRecordIterationsPerSecond()
+        throws Exception
+    {
+        try
+        {
+            Assembler assembler = module -> module.entities( ComplexProduct.class );
+            createPolygeneRuntime( assembler );
+            profile( () -> {
+                Report report = new Report( storeName );
+                report.start( "createEntityInBulkWithComplexType" );
+                int bulk = 0;
+                UnitOfWork uow = uowf.newUnitOfWork( newUsecase( "createEntityInBulkWithComplexType " + bulk ) );
+                for( int i = 0; i < ITERATIONS; i++ )
+                {
+                    ComplexProduct product = uow.newEntity( ComplexProduct.class );
+                    product.identity().get();
+                    if( i % 1000 == 0 )
+                    {
+                        uow.complete();
+                        bulk++;
+                        uow = uowf.newUnitOfWork( newUsecase( "createEntityInBulkWithComplexType " + bulk ) );
+                    }
+                }
+                uow.complete();
+                report.stop( ITERATIONS );
+                writeReport( report );
+                return null;
+            } );
+        }
+        finally
+        {
+            cleanUp();
+        }
+    }
+
+    @Test
+    public void whenReadEntityWithComplexTypeThenRecordIterationsPerSecond()
+        throws Exception
+    {
+        try
+        {
+            Assembler assembler = module -> module.entities( ComplexProduct.class );
+            createPolygeneRuntime( assembler );
+            {
+                int bulk = 0;
+                UnitOfWork uow = uowf.newUnitOfWork( newUsecase( "readEntityWithComplexType PREPARE " + bulk ) );
+                for( int i = 0; i < ITERATIONS; i++ )
+                {
+                    ComplexProduct product = uow.newEntity( ComplexProduct.class, new StringIdentity( "product" + i ) );
+                    product.name().set( "Product " + i );
+
+                    if( i % 1000 == 0 )
+                    {
+                        uow.complete();
+                        bulk++;
+                        uow = uowf.newUnitOfWork( newUsecase( "readEntityWithComplexType PREPARE " + bulk ) );
+                    }
+                }
+                uow.complete();
+            }
+
+            profile( () -> {
+                Report report = new Report( storeName );
+                int bulk = 0;
+                UnitOfWork uow = uowf.newUnitOfWork( newUsecase( "readEntityWithComplexType " + bulk ) );
+                Random rnd = new Random();
+                report.start( "readEntityWithComplexType" );
+                String id = rnd.nextInt( ITERATIONS ) + "";
+                for( int i = 0; i < ITERATIONS; i++ )
+                {
+                    ComplexProduct product = uow.get( ComplexProduct.class, new StringIdentity( "product" + id ) );
+                    product.name().get();
+                    if( i % 100 == 0 )
+                    {
+                        uow.discard();
+                        bulk++;
+                        uow = uowf.newUnitOfWork( newUsecase( "readEntityWithComplexType " + bulk ) );
+                    }
+                }
+                uow.complete();
+                report.stop( ITERATIONS );
+                writeReport( report );
+                return null;
+            } );
+        }
+        finally
+        {
+            cleanUp();
+        }
+    }
+
+    // If you want to profile this test, then tell profiler to only check
+    // below this method call
+    private void profile( Callable<Void> runnable )
+        throws Exception
+    {
+        runnable.call();
+    }
+
+    private void writeReport( Report report )
+        throws IOException
+    {
+        File dir = new File( "build/reports/perf/" );
+        if( !dir.exists() && !dir.mkdirs() )
+        {
+            System.out.println( "Couldn't create Performance result directory." );
+        }
+        String name = dir.getAbsolutePath() + "/result-" + report.name() + ".xml";
+        FileWriter writer = new FileWriter( name, true );
+        try (BufferedWriter out = new BufferedWriter( writer ))
+        {
+            report.writeTo( out );
+            out.flush();
+        }
+        System.out.println( "Report written to " + name );
+    }
+
+    private void createPolygeneRuntime( Assembler testSetup )
+        throws Exception
+    {
+        Energy4Java polygene = new Energy4Java();
+        Assembler[][][] assemblers = new Assembler[][][]
+            {
+                {
+                    {
+                        infrastructure, testSetup
+                    }
+                }
+            };
+        application = polygene.newApplication( new ApplicationAssemblerAdapter( assemblers )
+        {
+        } );
+        application.activate();
+
+        Module moduleInstance = application.findModule( "Layer 1", "Module 1" );
+        uowf = moduleInstance.unitOfWorkFactory();
+        serviceFinder = moduleInstance;
+    }
+
+    protected void cleanUp()
+        throws Exception
+    {
+        try
+        {
+            if( uowf != null && uowf.isUnitOfWorkActive() )
+            {
+                UnitOfWork current;
+                while( uowf.isUnitOfWorkActive() && ( current = uowf.currentUnitOfWork() ) != null )
+                {
+                    if( current.isOpen() )
+                    {
+                        current.discard();
+                    }
+                    else
+                    {
+                        throw new InternalError( "I have seen a case where a UoW is on the stack, but not opened: "
+                                                 + current.usecase().name() );
+                    }
+                }
+                new Exception( "UnitOfWork not properly cleaned up" ).printStackTrace();
+            }
+        }
+        finally
+        {
+            if( application != null )
+            {
+                application.passivate();
+            }
+        }
+    }
+}
diff --git a/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/ComplexProduct.java b/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/ComplexProduct.java
new file mode 100644
index 0000000..ced217a
--- /dev/null
+++ b/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/ComplexProduct.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.test.performance.entitystore;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+
+public interface ComplexProduct
+    extends EntityComposite
+{
+    @UseDefaults
+    Property<String> name();
+
+    @Optional
+    Property<String> description();
+
+    @Optional
+    Property<Money> unitPrice();
+}
diff --git a/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/Money.java b/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/Money.java
new file mode 100644
index 0000000..027448f
--- /dev/null
+++ b/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/Money.java
@@ -0,0 +1,67 @@
+/*
+ *  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.polygene.test.performance.entitystore;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Currency;
+
+public class Money
+    implements Serializable
+{
+    private final BigDecimal amount;
+    private final Currency currency;
+    private final boolean prefixed;
+
+    public Money( BigDecimal amount, Currency currency, boolean prefixed )
+    {
+        this.amount = amount;
+        this.currency = currency;
+        this.prefixed = prefixed;
+    }
+
+    public boolean isPrefixed()
+    {
+        return prefixed;
+    }
+
+    public BigDecimal amount()
+    {
+        return amount;
+    }
+
+    public Currency currency()
+    {
+        return currency;
+    }
+
+    @Override
+    public String toString()
+    {
+        if( prefixed )
+        {
+            return currency.toString() + amount.toPlainString();
+        }
+        else
+        {
+            return amount.toPlainString() + currency.toString();
+        }
+    }
+}
diff --git a/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/Report.java b/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/Report.java
new file mode 100644
index 0000000..b1d5ff8
--- /dev/null
+++ b/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/Report.java
@@ -0,0 +1,102 @@
+/*
+ *  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.polygene.test.performance.entitystore;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Report
+{
+    private final HashMap<String, Long> results;
+    private String current;
+    private long start;
+    private final String name;
+
+    public Report( String name )
+    {
+        results = new HashMap<>();
+        this.name = name;
+    }
+
+    public void start( String type )
+    {
+        current = type;
+        start = System.nanoTime();
+    }
+
+    public void stop( int iterations )
+    {
+        long end = System.nanoTime();
+        long duration = end - start;
+        results.put( current, ( 1000000000L * iterations ) / duration );
+    }
+
+    public long intermediate( int iterations )
+    {
+        long end = System.nanoTime();
+        long duration = end - start;
+        return ( 1000000000L * iterations ) / duration;
+    }
+
+    public long duration( String type )
+    {
+        return results.get( type );
+    }
+
+    public String name()
+    {
+        return name;
+    }
+
+    public String toXML()
+    {
+        StringBuilder buffer = new StringBuilder();
+        buffer.append( "  <test unit=\"per sec\">\n" );
+        for( Map.Entry entry : results.entrySet() )
+        {
+            buffer.append( "    <result id=\"" );
+            buffer.append( entry.getKey() );
+            buffer.append( "\">" );
+            buffer.append( entry.getValue() );
+            buffer.append( "</result>\n" );
+        }
+        buffer.append( "  </test>\n" );
+        return buffer.toString();
+    }
+
+    public void writeTo( Writer writer )
+        throws IOException
+    {
+        BufferedWriter out;
+        if( writer instanceof BufferedWriter )
+        {
+            out = (BufferedWriter) writer;
+        }
+        else
+        {
+            out = new BufferedWriter( writer );
+        }
+        out.write( toXML() );
+        out.flush();
+    }
+}
diff --git a/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/ReportTypes.java b/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/ReportTypes.java
new file mode 100644
index 0000000..bf4bffd
--- /dev/null
+++ b/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/ReportTypes.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.test.performance.entitystore;
+
+public interface ReportTypes
+{
+    String CREATE_ENTITY_WITH_SINGLE_PROPERTY = "createEntityWithSingleProperty";
+    String CREATE_ENTITY_WITH_ONLY_PROPERTIES = "createEntityWithOnlyProperties";
+    String CREATE_ENTITY_WITH_SINGLE_ASSOCIATION = "createEntityWithSingleAssociation";
+    String CREATE_ENTITY_WITH_SEVERAL_ASSOCIATIONS = "createEntityWithSeveralAssociations";
+    String CREATE_ENTITY_WITH_SINGLE_MANYASSOCIATION = "createEntityWithSingleManyAssociations";
+    String CREATE_ENTITY_WITH_SEVERAL_MANYASSOCIATIONS = "createEntityWithSeveralManyAssociations";
+    String CREATE_ENTITY_WITH_MIXED_COMPOSITION = "createEntityWithMixedComposition";
+
+    String READ_ENTITY_WITH_SINGLE_PROPERTY = "readEntityWithSingleProperty";
+    String READ_ENTITY_WITH_ONLY_PROPERTIES = "readEntityWithOnlyProperties";
+    String READ_ENTITY_WITH_SINGLE_ASSOCIATION = "readEntityWithSingleAssociation";
+    String READ_ENTITY_WITH_SEVERAL_ASSOCIATIONS = "readEntityWithSeveralAssociations";
+    String READ_ENTITY_WITH_SINGLE_MANYASSOCIATION = "readEntityWithSingleManyAssociations";
+    String READ_ENTITY_WITH_SEVERAL_MANYASSOCIATIONS = "readEntityWithSeveralManyAssociations";
+    String READ_ENTITY_WITH_MIXED_COMPOSITION = "readEntityWithMixedComposition";
+
+    String TRAVERSE_ONE_LEVEL = "traverseOneLevel";
+    String TRAVERSE_TWO_LEVEL = "traverseTwoLevel";
+    String TRAVERSE_THREE_LEVEL = "traverseThreeLevel";
+    String TRAVERSE_FIVE_LEVEL = "traverseFiveLevel";
+}
diff --git a/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/SimpleProduct.java b/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/SimpleProduct.java
new file mode 100644
index 0000000..5128cbf
--- /dev/null
+++ b/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/SimpleProduct.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.test.performance.entitystore;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.property.Property;
+
+public interface SimpleProduct
+    extends EntityComposite
+{
+    @Optional
+    Property<String> name();
+}
diff --git a/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/package.html b/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/package.html
new file mode 100644
index 0000000..4289ef8
--- /dev/null
+++ b/tests/performance/src/main/java/org/apache/polygene/test/performance/entitystore/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Performance Tests for EntityStores.</h2>
+    </body>
+</html>
diff --git a/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/AbstractEntityStorePerformanceTest.java b/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/AbstractEntityStorePerformanceTest.java
deleted file mode 100644
index c5b0fcb..0000000
--- a/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/AbstractEntityStorePerformanceTest.java
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.test.performance.entitystore;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.Random;
-import java.util.concurrent.Callable;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.ApplicationAssemblerAdapter;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.qi4j.api.usecase.UsecaseBuilder.newUsecase;
-
-/**
- * Performance Test Suite for Entity Stores.
- */
-public abstract class AbstractEntityStorePerformanceTest
-{
-    private final String storeName;
-    private final Assembler infrastructure;
-    private final Logger logger;
-    private Application application;
-    protected Module module;
-
-    private final int ITERATIONS = 20000;
-
-    protected AbstractEntityStorePerformanceTest( String storeName, Assembler infrastructure )
-    {
-        this.storeName = storeName;
-        this.infrastructure = infrastructure;
-        this.logger = LoggerFactory.getLogger( getClass().getPackage().getName() + "." + storeName );
-    }
-
-    @Before
-    public void warmup()
-        throws Exception
-    {
-        try
-        {
-            Assembler assembler = new Assembler()
-            {
-                @Override
-                public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-                {
-                    module.entities( SimpleProduct.class );
-                }
-            };
-            createQi4jRuntime( assembler );
-
-            for( int i = 0; i < 10000; i++ )
-            {
-                try( UnitOfWork uow = module.newUnitOfWork( newUsecase( "Warmup " + i ) ) )
-                {
-                    SimpleProduct product = uow.newEntity( SimpleProduct.class );
-                    String id = product.identity().get();
-                }
-            }
-        }
-        catch( Exception ex )
-        {
-            logger.error( "Unable to warmup: {}", ex.getMessage(), ex );
-            throw ex;
-        }
-        finally
-        {
-            cleanUp();
-        }
-    }
-
-    @Test
-    public void whenCreateEntityWithSinglePropertyThenRecordIterationsPerSecond()
-        throws Exception
-    {
-        try
-        {
-            Assembler assembler = new Assembler()
-            {
-                @Override
-                public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-                {
-                    module.entities( SimpleProduct.class );
-                }
-            };
-            createQi4jRuntime( assembler );
-
-            profile( new Callable<Void>()
-            {
-                @Override
-                public Void call()
-                    throws Exception
-                {
-                    Report report = new Report( storeName );
-                    report.start( "createEntityWithSingleProperty" );
-                    for( int i = 0; i < ITERATIONS; i++ )
-                    {
-                        try( UnitOfWork uow = module.newUnitOfWork( newUsecase( "createEntityWithSingleProperty " + i ) ) )
-                        {
-                            SimpleProduct product = uow.newEntity( SimpleProduct.class );
-                            String id = product.identity().get();
-                            uow.complete();
-                        }
-                        if( i % 1000 == 0 )
-                        {
-                            logger.info( "Iteration {}", i );
-                        }
-                    }
-                    report.stop( ITERATIONS );
-                    writeReport( report );
-                    return null;
-                }
-            } );
-        }
-        finally
-        {
-            cleanUp();
-        }
-    }
-
-    @Test
-    public void whenCreateEntityWithSinglePropertyInBatchThenRecordIterationsPerSecond()
-        throws Exception
-    {
-        try
-        {
-            Assembler assembler = new Assembler()
-            {
-                @Override
-                public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-                {
-                    module.entities( SimpleProduct.class );
-                }
-            };
-            createQi4jRuntime( assembler );
-            profile( new Callable<Void>()
-            {
-                @Override
-                public Void call()
-                    throws Exception
-                {
-                    Report report = new Report( storeName );
-                    report.start( "createEntityInBulkWithSingleProperty" );
-                    int bulk = 0;
-                    UnitOfWork uow = module.newUnitOfWork( newUsecase( "createEntityInBulkWithSingleProperty " + bulk ) );
-                    for( int i = 0; i < ITERATIONS; i++ )
-                    {
-                        SimpleProduct product = uow.newEntity( SimpleProduct.class );
-                        String id = product.identity().get();
-                        if( i % 1000 == 0 )
-                        {
-                            uow.complete();
-                            bulk++;
-                            uow = module.newUnitOfWork( newUsecase( "createEntityInBulkWithSingleProperty " + bulk ) );
-                        }
-                    }
-                    uow.complete();
-                    report.stop( ITERATIONS );
-                    writeReport( report );
-                    return null;
-                }
-            } );
-        }
-        finally
-        {
-            cleanUp();
-        }
-    }
-
-    @Test
-    public void whenCreateEntityWithComplexTypeThenRecordIterationsPerSecond()
-        throws Exception
-    {
-        try
-        {
-            Assembler assembler = new Assembler()
-            {
-                @Override
-                public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-                {
-                    module.entities( ComplexProduct.class );
-                }
-            };
-            createQi4jRuntime( assembler );
-            profile( new Callable<Void>()
-            {
-                @Override
-                public Void call()
-                    throws Exception
-                {
-                    Report report = new Report( storeName );
-                    report.start( "createEntityWithComplexType" );
-                    for( int i = 0; i < ITERATIONS; i++ )
-                    {
-                        try( UnitOfWork uow = module.newUnitOfWork( newUsecase( "createEntityWithComplexType " + i ) ) )
-                        {
-                            ComplexProduct product = uow.newEntity( ComplexProduct.class );
-                            String id = product.identity().get();
-                            uow.complete();
-                        }
-                    }
-                    report.stop( ITERATIONS );
-                    writeReport( report );
-                    return null;
-                }
-            } );
-        }
-        finally
-        {
-            cleanUp();
-        }
-    }
-
-    @Test
-    public void whenCreateEntityWithComplexTypeInBatchThenRecordIterationsPerSecond()
-        throws Exception
-    {
-        try
-        {
-            Assembler assembler = new Assembler()
-            {
-                @Override
-                public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-                {
-                    module.entities( ComplexProduct.class );
-                }
-            };
-            createQi4jRuntime( assembler );
-            profile( new Callable<Void>()
-            {
-                @Override
-                public Void call()
-                    throws Exception
-                {
-                    Report report = new Report( storeName );
-                    report.start( "createEntityInBulkWithComplexType" );
-                    int bulk = 0;
-                    UnitOfWork uow = module.newUnitOfWork( newUsecase( "createEntityInBulkWithComplexType " + bulk ) );
-                    for( int i = 0; i < ITERATIONS; i++ )
-                    {
-                        ComplexProduct product = uow.newEntity( ComplexProduct.class );
-                        String id = product.identity().get();
-                        if( i % 1000 == 0 )
-                        {
-                            uow.complete();
-                            bulk++;
-                            uow = module.newUnitOfWork( newUsecase( "createEntityInBulkWithComplexType " + bulk ) );
-                        }
-                    }
-                    uow.complete();
-                    report.stop( ITERATIONS );
-                    writeReport( report );
-                    return null;
-                }
-            } );
-        }
-        finally
-        {
-            cleanUp();
-        }
-    }
-
-    @Test
-    public void whenReadEntityWithComplexTypeThenRecordIterationsPerSecond()
-        throws Exception
-    {
-        try
-        {
-            Assembler assembler = new Assembler()
-            {
-                @Override
-                public void assemble( ModuleAssembly module )
-                    throws AssemblyException
-                {
-                    module.entities( ComplexProduct.class );
-                }
-            };
-            createQi4jRuntime( assembler );
-            {
-                int bulk = 0;
-                UnitOfWork uow = module.newUnitOfWork( newUsecase( "readEntityWithComplexType PREPARE " + bulk ) );
-                for( int i = 0; i < ITERATIONS; i++ )
-                {
-                    ComplexProduct product = uow.newEntity( ComplexProduct.class, "product" + i );
-                    product.name().set( "Product " + i );
-
-                    if( i % 1000 == 0 )
-                    {
-                        uow.complete();
-                        bulk++;
-                        uow = module.newUnitOfWork( newUsecase( "readEntityWithComplexType PREPARE " + bulk ) );
-                    }
-                }
-                uow.complete();
-            }
-
-            profile( new Callable<Void>()
-            {
-                @Override
-                public Void call()
-                    throws Exception
-                {
-                    Report report = new Report( storeName );
-                    int bulk = 0;
-                    UnitOfWork uow = module.newUnitOfWork( newUsecase( "readEntityWithComplexType " + bulk ) );
-                    Random rnd = new Random();
-                    report.start( "readEntityWithComplexType" );
-                    String id = rnd.nextInt( ITERATIONS ) + "";
-                    for( int i = 0; i < ITERATIONS; i++ )
-                    {
-                        ComplexProduct product = uow.get( ComplexProduct.class, "product" + id );
-
-                        String name = product.name().get();
-
-                        if( i % 100 == 0 )
-                        {
-                            uow.discard();
-                            bulk++;
-                            uow = module.newUnitOfWork( newUsecase( "readEntityWithComplexType " + bulk ) );
-                        }
-                    }
-                    uow.complete();
-                    report.stop( ITERATIONS );
-                    writeReport( report );
-                    return null;
-                }
-            } );
-        }
-        finally
-        {
-            cleanUp();
-        }
-    }
-
-    // If you want to profile this test, then tell profiler to only check
-    // below this method call
-    private void profile( Callable<Void> runnable )
-        throws Exception
-    {
-        runnable.call();
-    }
-
-    private void writeReport( Report report )
-        throws IOException
-    {
-        File dir = new File( "build/reports/perf/" );
-        dir.mkdirs();
-        String name = dir.getAbsolutePath() + "/result-" + report.name() + ".xml";
-        FileWriter writer = new FileWriter( name, true );
-        try( BufferedWriter out = new BufferedWriter( writer ) )
-        {
-            report.writeTo( out );
-            out.flush();
-        }
-        System.out.println( "Report written to " + name );
-    }
-
-    private void createQi4jRuntime( Assembler testSetup )
-        throws Exception
-    {
-        Energy4Java qi4j = new Energy4Java();
-        Assembler[][][] assemblers = new Assembler[][][]
-        {
-            {
-                {
-                    infrastructure, testSetup
-                }
-            }
-        };
-        application = qi4j.newApplication( new ApplicationAssemblerAdapter( assemblers )
-        {
-        } );
-        application.activate();
-
-        Module moduleInstance = application.findModule( "Layer 1", "Module 1" );
-        module = moduleInstance;
-    }
-
-    protected void cleanUp()
-        throws Exception
-    {
-        try
-        {
-            if( module != null && module.isUnitOfWorkActive() )
-            {
-                UnitOfWork current;
-                while( module.isUnitOfWorkActive() && ( current = module.currentUnitOfWork() ) != null )
-                {
-                    if( current.isOpen() )
-                    {
-                        current.discard();
-                    }
-                    else
-                    {
-                        throw new InternalError( "I have seen a case where a UoW is on the stack, but not opened: "
-                                                 + current.usecase().name() );
-                    }
-                }
-                new Exception( "UnitOfWork not properly cleaned up" ).printStackTrace();
-            }
-        }
-        finally
-        {
-            if( application != null )
-            {
-                application.passivate();
-            }
-        }
-    }
-}
diff --git a/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/ComplexProduct.java b/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/ComplexProduct.java
deleted file mode 100644
index 4b0ea49..0000000
--- a/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/ComplexProduct.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.test.performance.entitystore;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-
-public interface ComplexProduct
-    extends EntityComposite
-{
-    @UseDefaults
-    Property<String> name();
-
-    @Optional
-    Property<String> description();
-
-    @Optional
-    Property<Money> unitPrice();
-}
diff --git a/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/Money.java b/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/Money.java
deleted file mode 100644
index 6855569..0000000
--- a/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/Money.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.test.performance.entitystore;
-
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.util.Currency;
-
-public class Money
-    implements Serializable
-{
-    private final BigDecimal amount;
-    private final Currency currency;
-    private final boolean prefixed;
-
-    public Money( BigDecimal amount, Currency currency, boolean prefixed )
-    {
-        this.amount = amount;
-        this.currency = currency;
-        this.prefixed = prefixed;
-    }
-
-    public boolean isPrefixed()
-    {
-        return prefixed;
-    }
-
-    public BigDecimal amount()
-    {
-        return amount;
-    }
-
-    public Currency currency()
-    {
-        return currency;
-    }
-
-    @Override
-    public String toString()
-    {
-        if( prefixed )
-        {
-            return currency.toString() + amount.toPlainString();
-        }
-        else
-        {
-            return amount.toPlainString() + currency.toString();
-        }
-    }
-}
diff --git a/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/Report.java b/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/Report.java
deleted file mode 100644
index 795a896..0000000
--- a/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/Report.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.test.performance.entitystore;
-
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.HashMap;
-import java.util.Map;
-
-public class Report
-{
-    private final HashMap<String, Long> results;
-    private String current;
-    private long start;
-    private final String name;
-
-    public Report( String name )
-    {
-        results = new HashMap<>();
-        this.name = name;
-    }
-
-    public void start( String type )
-    {
-        current = type;
-        start = System.nanoTime();
-    }
-
-    public void stop( int iterations )
-    {
-        long end = System.nanoTime();
-        long duration = end - start;
-        results.put( current, ( 1000000000L * iterations ) / duration );
-    }
-
-    public long intermediate( int iterations )
-    {
-        long end = System.nanoTime();
-        long duration = end - start;
-        return ( 1000000000L * iterations ) / duration;
-    }
-
-    public long duration( String type )
-    {
-        return results.get( type );
-    }
-
-    public String name()
-    {
-        return name;
-    }
-
-    public String toXML()
-    {
-        StringBuilder buffer = new StringBuilder();
-        buffer.append( "  <test unit=\"per sec\">\n" );
-        for( Map.Entry entry : results.entrySet() )
-        {
-            buffer.append( "    <result id=\"" );
-            buffer.append( entry.getKey() );
-            buffer.append( "\">" );
-            buffer.append( entry.getValue() );
-            buffer.append( "</result>\n" );
-        }
-        buffer.append( "  </test>\n" );
-        return buffer.toString();
-    }
-
-    public void writeTo( Writer writer )
-        throws IOException
-    {
-        BufferedWriter out;
-        if( writer instanceof BufferedWriter )
-        {
-            out = (BufferedWriter) writer;
-        }
-        else
-        {
-            out = new BufferedWriter( writer );
-        }
-        out.write( toXML() );
-        out.flush();
-    }
-}
diff --git a/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/ReportTypes.java b/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/ReportTypes.java
deleted file mode 100644
index ad27fa1..0000000
--- a/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/ReportTypes.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.test.performance.entitystore;
-
-public interface ReportTypes
-{
-    String CREATE_ENTITY_WITH_SINGLE_PROPERTY = "createEntityWithSingleProperty";
-    String CREATE_ENTITY_WITH_ONLY_PROPERTIES = "createEntityWithOnlyProperties";
-    String CREATE_ENTITY_WITH_SINGLE_ASSOCIATION = "createEntityWithSingleAssociation";
-    String CREATE_ENTITY_WITH_SEVERAL_ASSOCIATIONS = "createEntityWithSeveralAssociations";
-    String CREATE_ENTITY_WITH_SINGLE_MANYASSOCIATION = "createEntityWithSingleManyAssociations";
-    String CREATE_ENTITY_WITH_SEVERAL_MANYASSOCIATIONS = "createEntityWithSeveralManyAssociations";
-    String CREATE_ENTITY_WITH_MIXED_COMPOSITION = "createEntityWithMixedComposition";
-
-    String READ_ENTITY_WITH_SINGLE_PROPERTY = "readEntityWithSingleProperty";
-    String READ_ENTITY_WITH_ONLY_PROPERTIES = "readEntityWithOnlyProperties";
-    String READ_ENTITY_WITH_SINGLE_ASSOCIATION = "readEntityWithSingleAssociation";
-    String READ_ENTITY_WITH_SEVERAL_ASSOCIATIONS = "readEntityWithSeveralAssociations";
-    String READ_ENTITY_WITH_SINGLE_MANYASSOCIATION = "readEntityWithSingleManyAssociations";
-    String READ_ENTITY_WITH_SEVERAL_MANYASSOCIATIONS = "readEntityWithSeveralManyAssociations";
-    String READ_ENTITY_WITH_MIXED_COMPOSITION = "readEntityWithMixedComposition";
-
-    String TRAVERSE_ONE_LEVEL = "traverseOneLevel";
-    String TRAVERSE_TWO_LEVEL = "traverseTwoLevel";
-    String TRAVERSE_THREE_LEVEL = "traverseThreeLevel";
-    String TRAVERSE_FIVE_LEVEL = "traverseFiveLevel";
-}
diff --git a/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/SimpleProduct.java b/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/SimpleProduct.java
deleted file mode 100644
index 88d3605..0000000
--- a/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/SimpleProduct.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.test.performance.entitystore;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-
-public interface SimpleProduct
-    extends EntityComposite
-{
-    @Optional
-    Property<String> name();
-}
diff --git a/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/package.html b/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/package.html
deleted file mode 100644
index 1f0f21a..0000000
--- a/tests/performance/src/main/java/org/qi4j/test/performance/entitystore/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Performance Tests for EntityStores.</h2>
-    </body>
-</html>
diff --git a/tests/performance/src/perf/java/org/apache/polygene/test/performance/entitystore/jdbm/JdbmEntityStorePerformanceTest.java b/tests/performance/src/perf/java/org/apache/polygene/test/performance/entitystore/jdbm/JdbmEntityStorePerformanceTest.java
new file mode 100644
index 0000000..3b4e179
--- /dev/null
+++ b/tests/performance/src/perf/java/org/apache/polygene/test/performance/entitystore/jdbm/JdbmEntityStorePerformanceTest.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.test.performance.entitystore.jdbm;
+
+import java.io.File;
+import org.apache.derby.iapi.services.io.FileUtil;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.cache.ehcache.EhCacheConfiguration;
+import org.apache.polygene.cache.ehcache.EhCachePoolService;
+import org.apache.polygene.entitystore.jdbm.JdbmConfiguration;
+import org.apache.polygene.entitystore.jdbm.assembly.JdbmEntityStoreAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.performance.entitystore.AbstractEntityStorePerformanceTest;
+
+/**
+ * Performance test for JdbmEntityStoreComposite
+ */
+public class JdbmEntityStorePerformanceTest
+    extends AbstractEntityStorePerformanceTest
+{
+    public JdbmEntityStorePerformanceTest()
+    {
+        super( "JdbmEntityStore", createAssembler() );
+    }
+
+    private static Assembler createAssembler()
+    {
+        return module ->
+        {
+            new JdbmEntityStoreAssembler().assemble( module );
+            ModuleAssembly configModule = module.layer().module( "Config" );
+            configModule.entities( JdbmConfiguration.class ).visibleIn( Visibility.layer );
+            new EntityTestAssembler().assemble( configModule );
+
+            module.services( EhCachePoolService.class );
+            configModule.entities( EhCacheConfiguration.class ).visibleIn( Visibility.layer );
+        };
+    }
+
+    @Override
+    public void cleanUp()
+        throws Exception
+    {
+        super.cleanUp();
+        FileUtil.removeDirectory( new File( "build/tmp/jdbm" ) );
+    }
+}
diff --git a/tests/performance/src/perf/java/org/apache/polygene/test/performance/entitystore/memory/MemoryEntityStorePerformanceTest.java b/tests/performance/src/perf/java/org/apache/polygene/test/performance/entitystore/memory/MemoryEntityStorePerformanceTest.java
new file mode 100644
index 0000000..956cc7a
--- /dev/null
+++ b/tests/performance/src/perf/java/org/apache/polygene/test/performance/entitystore/memory/MemoryEntityStorePerformanceTest.java
@@ -0,0 +1,58 @@
+/*
+ *  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.polygene.test.performance.entitystore.memory;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+import org.apache.polygene.entitystore.memory.assembly.MemoryEntityStoreAssembler;
+import org.apache.polygene.spi.entitystore.helpers.MapEntityStoreMixin;
+import org.apache.polygene.test.performance.entitystore.AbstractEntityStorePerformanceTest;
+
+public class MemoryEntityStorePerformanceTest
+    extends AbstractEntityStorePerformanceTest
+{
+
+    public MemoryEntityStorePerformanceTest()
+    {
+        super( "MemoryEntityStore", createAssembler() );
+    }
+
+    private static Assembler createAssembler()
+    {
+        return new Assembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                new MemoryEntityStoreAssembler().assemble( module );
+            }
+        };
+    }
+
+    // Alternate variant that uses the standard MapEntityStore
+    @Mixins( MapEntityStoreMixin.class )
+    interface MemoryEntityStoreService2
+        extends MemoryEntityStoreService
+    {
+    }
+
+}
diff --git a/tests/performance/src/perf/java/org/apache/polygene/test/performance/entitystore/sql/DerbySQLEntityStorePerformanceTest.java b/tests/performance/src/perf/java/org/apache/polygene/test/performance/entitystore/sql/DerbySQLEntityStorePerformanceTest.java
new file mode 100644
index 0000000..09a0331
--- /dev/null
+++ b/tests/performance/src/perf/java/org/apache/polygene/test/performance/entitystore/sql/DerbySQLEntityStorePerformanceTest.java
@@ -0,0 +1,114 @@
+/*
+ *  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.polygene.test.performance.entitystore.sql;
+
+import java.sql.Connection;
+import java.sql.Statement;
+import javax.sql.DataSource;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.sql.SQLMapEntityStoreConfiguration;
+import org.apache.polygene.entitystore.sql.assembly.DerbySQLEntityStoreAssembler;
+import org.apache.polygene.library.sql.assembly.DataSourceAssembler;
+import org.apache.polygene.library.sql.dbcp.DBCPDataSourceServiceAssembler;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.apache.polygene.test.performance.entitystore.AbstractEntityStorePerformanceTest;
+
+import static org.apache.polygene.entitystore.sql.assembly.DerbySQLEntityStoreAssembler.DEFAULT_ENTITYSTORE_IDENTITY;
+
+/**
+ * Performance test for DerbySQLEntityStore.
+ */
+public class DerbySQLEntityStorePerformanceTest
+    extends AbstractEntityStorePerformanceTest
+{
+
+    public DerbySQLEntityStorePerformanceTest()
+    {
+        super( "DerbySQLEntityStore", createAssembler() );
+    }
+
+    private static Assembler createAssembler()
+    {
+        return new Assembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                ModuleAssembly config = module.layer().module( "config" );
+                new EntityTestAssembler().assemble( config );
+
+                // DataSourceService
+                new DBCPDataSourceServiceAssembler().
+                    identifiedBy( "derby-datasource-service" ).
+                    visibleIn( Visibility.module ).
+                    withConfig( config, Visibility.layer ).
+                    assemble( module );
+
+                // DataSource
+                new DataSourceAssembler().
+                    withDataSourceServiceIdentity( "derby-datasource-service" ).
+                    identifiedBy( "derby-datasource" ).
+                    withCircuitBreaker().
+                    assemble( module );
+
+                // SQL EntityStore
+                new DerbySQLEntityStoreAssembler().
+                    withConfig( config, Visibility.layer ).
+                    assemble( module );
+            }
+        };
+    }
+
+    @Override
+    protected void cleanUp()
+        throws Exception
+    {
+        if( uowf == null )
+        {
+            return;
+        }
+        UnitOfWork uow = uowf.newUnitOfWork( UsecaseBuilder.newUsecase(
+            "Delete " + getClass().getSimpleName() + " test data" )
+        );
+        try
+        {
+            SQLMapEntityStoreConfiguration config = uow.get( SQLMapEntityStoreConfiguration.class,
+                                                             DEFAULT_ENTITYSTORE_IDENTITY );
+            Connection connection = serviceFinder.findService( DataSource.class ).get().getConnection();
+            connection.setAutoCommit( false );
+            try( Statement stmt = connection.createStatement() )
+            {
+                stmt.execute( String.format( "DELETE FROM %s.%s",
+                                             config.schemaName().get(),
+                                             config.entityTableName().get() ) );
+                connection.commit();
+            }
+        }
+        finally
+        {
+            uow.discard();
+            super.cleanUp();
+        }
+    }
+}
diff --git a/tests/performance/src/perf/java/org/apache/polygene/test/performance/entitystore/sql/PostgreSQLEntityStorePerformanceTest.java b/tests/performance/src/perf/java/org/apache/polygene/test/performance/entitystore/sql/PostgreSQLEntityStorePerformanceTest.java
new file mode 100644
index 0000000..b1e8a17
--- /dev/null
+++ b/tests/performance/src/perf/java/org/apache/polygene/test/performance/entitystore/sql/PostgreSQLEntityStorePerformanceTest.java
@@ -0,0 +1,146 @@
+/*
+ *  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.polygene.test.performance.entitystore.sql;
+
+import java.sql.Connection;
+import java.sql.Statement;
+import javax.sql.DataSource;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+import org.apache.polygene.bootstrap.ApplicationAssemblerAdapter;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+import org.apache.polygene.entitystore.sql.assembly.PostgreSQLEntityStoreAssembler;
+import org.apache.polygene.library.sql.assembly.DataSourceAssembler;
+import org.apache.polygene.library.sql.common.SQLConfiguration;
+import org.apache.polygene.library.sql.dbcp.DBCPDataSourceServiceAssembler;
+import org.apache.polygene.test.performance.entitystore.AbstractEntityStorePerformanceTest;
+import org.junit.Ignore;
+
+import static org.apache.polygene.entitystore.sql.assembly.PostgreSQLEntityStoreAssembler.DEFAULT_ENTITYSTORE_IDENTITY;
+
+/**
+ * Performance test for PostgreSQLEntityStore.
+ * <p>
+ * WARN This test is deactivated on purpose, please do not commit it activated.
+ * </p>
+ * <p>
+ * To run it see PostgreSQLEntityStoreTest.
+ * </p>
+ */
+@Ignore( "WARN Tearing down this test is broken!" )
+public class PostgreSQLEntityStorePerformanceTest
+    extends AbstractEntityStorePerformanceTest
+{
+
+    public PostgreSQLEntityStorePerformanceTest()
+    {
+        super( "PostgreSQLEntityStore", createAssembler() );
+    }
+
+    private static Assembler createAssembler()
+    {
+        return new Assembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                ModuleAssembly config = module.layer().module( "config" );
+                config.services( MemoryEntityStoreService.class );
+
+                // DataSourceService
+                new DBCPDataSourceServiceAssembler().
+                    identifiedBy( "postgresql-datasource-service" ).
+                    visibleIn( Visibility.module ).
+                    withConfig( config, Visibility.layer ).
+                    assemble( module );
+
+                // DataSource
+                new DataSourceAssembler().
+                    withDataSourceServiceIdentity( "postgresql-datasource-service" ).
+                    identifiedBy( "postgresql-datasource" ).
+                    withCircuitBreaker().
+                    assemble( module );
+
+                // SQL EntityStore
+                new PostgreSQLEntityStoreAssembler().
+                    withConfig( config, Visibility.layer ).
+                    assemble( module );
+            }
+
+        };
+    }
+
+    @Override
+    protected void cleanUp()
+        throws Exception
+    {
+        try
+        {
+            super.cleanUp();
+        }
+        finally
+        {
+
+            Energy4Java polygene = new Energy4Java();
+            Assembler[][][] assemblers = new Assembler[][][]
+            {
+                {
+                    {
+                        createAssembler()
+                    }
+                }
+            };
+            Application application = polygene.newApplication( new ApplicationAssemblerAdapter( assemblers )
+            {
+            } );
+            application.activate();
+
+            Module moduleInstance = application.findModule( "Layer 1", "config" );
+            UnitOfWorkFactory uowf = moduleInstance.unitOfWorkFactory();
+            UnitOfWork uow = uowf.newUnitOfWork(
+                UsecaseBuilder.newUsecase( "Delete " + getClass().getSimpleName() + " test data" )
+            );
+            try
+            {
+                SQLConfiguration config = uow.get( SQLConfiguration.class, DEFAULT_ENTITYSTORE_IDENTITY );
+                Connection connection = serviceFinder.findService( DataSource.class ).get().getConnection();
+                connection.setAutoCommit( false );
+                String schemaName = config.schemaName().get();
+                try( Statement stmt = connection.createStatement() )
+                {
+                    stmt.execute( String.format( "DROP SCHEMA \"%s\" CASCADE", schemaName ) );
+                    connection.commit();
+                }
+            }
+            finally
+            {
+                uow.discard();
+            }
+        }
+    }
+
+}
diff --git a/tests/performance/src/perf/java/org/apache/polygene/test/performance/indexing/rdf/QueryPerformanceTest.java b/tests/performance/src/perf/java/org/apache/polygene/test/performance/indexing/rdf/QueryPerformanceTest.java
new file mode 100644
index 0000000..c83356a
--- /dev/null
+++ b/tests/performance/src/perf/java/org/apache/polygene/test/performance/indexing/rdf/QueryPerformanceTest.java
@@ -0,0 +1,397 @@
+/*
+ *  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.polygene.test.performance.indexing.rdf;
+
+import java.io.File;
+import org.apache.derby.iapi.services.io.FileUtil;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.assembly.MemoryEntityStoreAssembler;
+import org.apache.polygene.index.rdf.assembly.RdfNativeSesameStoreAssembler;
+import org.apache.polygene.index.rdf.indexing.RdfIndexingService;
+import org.apache.polygene.index.rdf.query.SesameExpressions;
+import org.apache.polygene.library.rdf.repository.NativeConfiguration;
+import org.apache.polygene.test.EntityTestAssembler;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.apache.polygene.api.query.QueryExpressions.eq;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+
+@SuppressWarnings( "ResultOfMethodCallIgnored" )
+public class QueryPerformanceTest
+    implements ApplicationAssembler
+{
+    private static final int NUMBER_OF_ENTITIES = 100000;
+    private static final String LAYER_INFRASTRUCTURE = "LAYER_INFRASTRUCTURE";
+    private static final String MODULE_PERSISTENCE = "MODULE_PERSISTENCE";
+    private static final String LAYER_CONFIGURATION = "CONFIGURATION";
+    private static final String LAYER_DOMAIN = "LAYER_DOMAIN";
+    private static final String MODULE_DOMAIN = "MODULE_DOMAIN";
+    private static final String MODULE_CONFIG = "MODULE_CONFIG";
+
+    private Application application;
+    private Module module;
+    private UnitOfWorkFactory uowf;
+    private static final String QUERY1 = "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+                                         + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+                                         + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
+                                         + "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.performance.indexing.rdf.QueryPerformanceTest-Lead#> \n"
+                                         + "SELECT ?entityType ?reference\n"
+                                         + "WHERE {\n"
+                                         + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.performance.indexing.rdf.QueryPerformanceTest-Lead>. \n"
+                                         + "?entity rdf:type ?entityType. \n"
+                                         + "?entity ns0:reference ?reference. \n"
+                                         + "?entity ns1:name \"Lead64532\". \n"
+                                         + "}";
+    private static final String QUERY2 = "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+                                         + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+                                         + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
+                                         + "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.performance.indexing.rdf.QueryPerformanceTest-Lead#> \n"
+                                         + "SELECT ?entityType ?reference\n"
+                                         + "WHERE {\n"
+                                         + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.performance.indexing.rdf.QueryPerformanceTest-Lead>. \n"
+                                         + "?entity rdf:type ?entityType. \n"
+                                         + "?entity ns0:reference ?reference. \n"
+                                         + "?entity ns1:name \"Lead98276\". \n"
+                                         + "}";
+    private static final String QUERY3 = "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+                                         + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+                                         + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
+                                         + "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.performance.indexing.rdf.QueryPerformanceTest-Lead#> \n"
+                                         + "SELECT ?entityType ?reference\n"
+                                         + "WHERE {\n"
+                                         + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.performance.indexing.rdf.QueryPerformanceTest-Lead>. \n"
+                                         + "?entity rdf:type ?entityType. \n"
+                                         + "?entity ns0:reference ?reference. \n"
+                                         + "?entity ns1:name \"Lead2\". \n"
+                                         + "}";
+    private static final String QUERY4 = "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+                                         + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+                                         + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
+                                         + "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.performance.indexing.rdf.QueryPerformanceTest-Lead#> \n"
+                                         + "SELECT ?entityType ?reference\n"
+                                         + "WHERE {\n"
+                                         + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.performance.indexing.rdf.QueryPerformanceTest-Lead>. \n"
+                                         + "?entity rdf:type ?entityType. \n"
+                                         + "?entity ns0:reference ?reference. \n"
+                                         + "?entity ns1:name \"Lead14332\". \n"
+                                         + "}";
+    private static final String QUERY5 = "PREFIX ns0: <urn:polygene:type:org.apache.polygene.api.identity.HasIdentity#> \n"
+                                         + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
+                                         + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
+                                         + "PREFIX ns1: <urn:polygene:type:org.apache.polygene.test.performance.indexing.rdf.QueryPerformanceTest-Lead#> \n"
+                                         + "SELECT ?entityType ?reference\n"
+                                         + "WHERE {\n"
+                                         + "?entityType rdfs:subClassOf <urn:polygene:type:org.apache.polygene.test.performance.indexing.rdf.QueryPerformanceTest-Lead>. \n"
+                                         + "?entity rdf:type ?entityType. \n"
+                                         + "?entity ns0:reference ?reference. \n"
+                                         + "?entity ns1:name \"Lead632\". \n"
+                                         + "}";
+    private File indexingDataDir;
+
+    @Before
+    public void setup()
+        throws Exception
+    {
+        Energy4Java polygene = new Energy4Java();
+        application = polygene.newApplication( this );
+        module = application.findModule( LAYER_DOMAIN, MODULE_DOMAIN );
+        application.activate();
+        indexingDataDir = module.findService( RdfIndexingService.class ).get().dataDir();
+        uowf = module.unitOfWorkFactory();
+    }
+
+    @After
+    public void tearDown()
+        throws Exception
+    {
+        try
+        {
+            if( application != null )
+            {
+                System.out.println( "Shutting Down test." );
+                application.passivate();
+            }
+        }
+        finally
+        {
+            FileUtil.removeDirectory( indexingDataDir );
+        }
+    }
+
+    @Override
+    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+        throws AssemblyException
+    {
+        ApplicationAssembly applicationAssembly = applicationFactory.newApplicationAssembly();
+        LayerAssembly infra = createInfrastructureLayer( applicationAssembly );
+        LayerAssembly domain = createDomainLayer( applicationAssembly );
+        LayerAssembly config = createConfigurationLayer( applicationAssembly );
+        infra.uses( config );
+        domain.uses( infra );
+        return applicationAssembly;
+    }
+
+    @Test
+    public void testIndexingFluentQueries()
+        throws Exception
+    {
+        LeadRepository leadRepo = populateEntityStore();
+        measureFluentQuery( leadRepo, "Lead64531" );
+        measureFluentQuery( leadRepo, "Lead98275" );
+        measureFluentQuery( leadRepo, "Lead3" );
+        measureFluentQuery( leadRepo, "Lead14331" );
+        measureFluentQuery( leadRepo, "Lead631" );
+    }
+
+    @Test
+    public void testIndexingNamedQueries()
+        throws Exception
+    {
+        LeadRepository leadRepo = populateEntityStore();
+        measureNamedQuery( leadRepo, QUERY1 );
+        measureNamedQuery( leadRepo, QUERY2 );
+        measureNamedQuery( leadRepo, QUERY3 );
+        measureNamedQuery( leadRepo, QUERY4 );
+        measureNamedQuery( leadRepo, QUERY5 );
+    }
+
+    private LeadRepository populateEntityStore()
+        throws UnitOfWorkCompletionException
+    {
+        UnitOfWork uow = uowf.newUnitOfWork();
+        try
+        {
+            LeadRepository leadRepo = module.findService( LeadRepositoryService.class ).get();
+            if( leadRepo.findByName( "Lead99999" ) == null )
+            {
+                ServiceReference<LeadEntityFactoryService> leadFactoryRef = module.findService( LeadEntityFactoryService.class );
+                LeadEntityFactory leadFactory = leadFactoryRef.get();
+                long start, end;
+                start = System.currentTimeMillis();
+                for( int i = 1; i < NUMBER_OF_ENTITIES; i++ )
+                {
+                    if( ( i % 10000 ) == 0 )
+                    {
+                        System.out.print( "\r" + i );
+                        uow.complete();
+                        uow = uowf.newUnitOfWork();
+                    }
+                    leadFactory.create( "Lead" + i );
+                }
+                System.out.println();
+                uow.complete();
+                end = System.currentTimeMillis();
+                System.out.println( "Population time: " + ( end - start ) );
+            }
+            return leadRepo;
+        }
+        finally
+        {
+            if( uow != null && uow.isOpen() )
+            {
+                uow.discard();
+            }
+        }
+    }
+
+    private void measureFluentQuery( LeadRepository leadRepo, String nameOfEntity )
+        throws Exception
+    {
+        long start;
+        long end;
+        try( UnitOfWork uow = uowf.newUnitOfWork() )
+        {
+            start = System.currentTimeMillis();
+            Lead lead = leadRepo.findByName( nameOfEntity );
+            end = System.currentTimeMillis();
+            if( lead == null )
+            {
+                Assert.fail( "Entity was not found or more than one entity was found." );
+                return;
+            }
+            System.out.println( "Lead: " + lead );
+            System.out.println( "Retrieval time of " + lead.name().get() + " by name: " + ( end - start ) );
+            uow.complete();
+        }
+    }
+
+    private void measureNamedQuery( LeadRepository leadRepo, String queryName )
+        throws Exception
+    {
+        long start;
+        long end;
+        try( UnitOfWork uow = uowf.newUnitOfWork() )
+        {
+            start = System.currentTimeMillis();
+            Lead lead = leadRepo.findByFixedQuery( queryName );
+            end = System.currentTimeMillis();
+            if( lead == null )
+            {
+                Assert.fail( "Entity was not found or more than one entity was found." );
+                return;
+            }
+            System.out.println( "Lead: " + lead );
+            System.out.println( "Retrieval time of " + lead.name().get() + " by name: " + ( end - start ) );
+            uow.complete();
+        }
+    }
+
+    private LayerAssembly createDomainLayer( ApplicationAssembly applicationAssembly )
+        throws AssemblyException
+    {
+        LayerAssembly domainLayer = applicationAssembly.layer( LAYER_DOMAIN );
+        ModuleAssembly domainModule = domainLayer.module( MODULE_DOMAIN );
+        domainModule.addServices( LeadRepositoryService.class );
+        domainModule.addServices( LeadEntityFactoryService.class );
+        domainModule.entities( LeadEntity.class );
+        return domainLayer;
+    }
+
+    private LayerAssembly createInfrastructureLayer( ApplicationAssembly applicationAssembly )
+        throws AssemblyException
+    {
+        LayerAssembly infrastructureLayer = applicationAssembly.layer( LAYER_INFRASTRUCTURE );
+
+        // Persistence module
+        ModuleAssembly persistenceModule = infrastructureLayer.module( MODULE_PERSISTENCE );
+
+        // Indexing
+        new RdfNativeSesameStoreAssembler().assemble( persistenceModule );
+
+        // Entity store
+        new MemoryEntityStoreAssembler().visibleIn( Visibility.application ).assemble( persistenceModule );
+
+        return infrastructureLayer;
+    }
+
+    private LayerAssembly createConfigurationLayer( ApplicationAssembly applicationAssembly )
+        throws AssemblyException
+    {
+        LayerAssembly layer = applicationAssembly.layer( LAYER_CONFIGURATION );
+        ModuleAssembly configModule = layer.module( MODULE_CONFIG );
+        configModule.entities( NativeConfiguration.class ).visibleIn( Visibility.application );
+        new EntityTestAssembler().assemble( configModule );
+        return layer;
+    }
+
+    public interface Lead
+    {
+        Property<String> name();
+    }
+
+    public interface LeadEntity
+        extends Lead, EntityComposite
+    {
+    }
+
+    @Mixins( LeadEntityFactoryMixin.class )
+    public interface LeadEntityFactoryService
+        extends LeadEntityFactory, ServiceComposite
+    {
+    }
+
+    public interface LeadEntityFactory
+    {
+        Lead create( String name );
+    }
+
+    public static class LeadEntityFactoryMixin
+        implements LeadEntityFactory
+    {
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @Override
+        public Lead create( String name )
+        {
+            UnitOfWork uow = uowf.currentUnitOfWork();
+            EntityBuilder<LeadEntity> builder = uow.newEntityBuilder( LeadEntity.class );
+            Lead prototype = builder.instanceFor( LeadEntity.class );
+            prototype.name().set( name );
+            return builder.newInstance();
+        }
+    }
+
+    public interface LeadRepository
+    {
+        Lead findByFixedQuery( String name );
+
+        Lead findByName( String name );
+    }
+
+    @Mixins( LeadRepositoryMixin.class )
+    public interface LeadRepositoryService
+        extends LeadRepository, ServiceComposite
+    {
+    }
+
+    public static class LeadRepositoryMixin
+        implements LeadRepository
+    {
+        @Structure
+        private QueryBuilderFactory qbf;
+
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @Override
+        public Lead findByFixedQuery( String queryString )
+        {
+            UnitOfWork uow = uowf.currentUnitOfWork();
+            Query<Lead> query = uow.newQuery( qbf.newQueryBuilder( Lead.class ).where( SesameExpressions.sparql( queryString ) ) );
+            return query.find();
+        }
+
+        @Override
+        public Lead findByName( String name )
+        {
+            UnitOfWork uow = uowf.currentUnitOfWork();
+            QueryBuilder<Lead> builder = qbf.newQueryBuilder( Lead.class );
+            Lead template = templateFor( Lead.class );
+
+            Query<Lead> query = uow.newQuery( builder.where( eq( template.name(), name ) ) );
+            return query.find();
+        }
+    }
+
+}
diff --git a/tests/performance/src/perf/java/org/apache/polygene/test/performance/runtime/composite/CompositeCreationPerformanceTest.java b/tests/performance/src/perf/java/org/apache/polygene/test/performance/runtime/composite/CompositeCreationPerformanceTest.java
new file mode 100644
index 0000000..449ecf4
--- /dev/null
+++ b/tests/performance/src/perf/java/org/apache/polygene/test/performance/runtime/composite/CompositeCreationPerformanceTest.java
@@ -0,0 +1,287 @@
+/*
+ *  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.polygene.test.performance.runtime.composite;
+
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.junit.Test;
+
+/**
+ * Tests performance of new composite creation.
+ */
+public class CompositeCreationPerformanceTest
+{
+    @Test
+    public void newInstanceForRegisteredCompositePerformance()
+        throws ActivationException, AssemblyException, InterruptedException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( AnyComposite.class );
+                module.objects( AnyObject.class );
+                module.values( AnyValue.class );
+            }
+        };
+        int warmups = 10;
+        int runs = 20;
+        long waitBeforeRun = 1000;
+        long waitBetweenRuns = 500;
+        long timeForJavaObject = 0;
+        {
+            // Warmup
+            for( int i = 0; i < warmups; i++ )
+            {
+                testJavaObjectCreationPerformance( false );
+            }
+            Thread.sleep( waitBeforeRun );
+            // Run
+            for( int i = 0; i < runs; i++ )
+            {
+                timeForJavaObject += testJavaObjectCreationPerformance( true );
+                Thread.sleep( waitBetweenRuns );
+            }
+            timeForJavaObject = timeForJavaObject / runs;
+        }
+        long timeForTransientComposite = 0;
+        {
+            TransientBuilderFactory module = assembler.module();
+            // Warmup
+            for( int i = 0; i < warmups; i++ )
+            {
+                testCompositeCreationPerformance( module, false );
+            }
+            Thread.sleep( waitBeforeRun );
+            // Run
+            for( int i = 0; i < runs; i++ )
+            {
+                timeForTransientComposite += testCompositeCreationPerformance( module, true );
+                Thread.sleep( waitBetweenRuns );
+            }
+            timeForTransientComposite = timeForTransientComposite / runs;
+        }
+        long timeForManagedObject = 0;
+        {
+            ObjectFactory objectFactory = assembler.module();
+            // Warmup
+            for( int i = 0; i < warmups; i++ )
+            {
+                testObjectCreationPerformance( objectFactory, false );
+            }
+            Thread.sleep( waitBeforeRun );
+            // Run
+            for( int i = 0; i < runs; i++ )
+            {
+                timeForManagedObject += testObjectCreationPerformance( objectFactory, true );
+                Thread.sleep( waitBetweenRuns );
+            }
+            timeForManagedObject = timeForManagedObject / runs;
+        }
+        long timeForValueComposite = 0;
+        {
+            ValueBuilderFactory valueBuilderFactory = assembler.module();
+            // Warmup
+            for( int i = 0; i < warmups; i++ )
+            {
+                testValueCreationPerformance( valueBuilderFactory, false );
+            }
+            Thread.sleep( waitBeforeRun );
+            // Run
+            for( int i = 0; i < runs; i++ )
+            {
+                timeForValueComposite += testValueCreationPerformance( valueBuilderFactory, true );
+                Thread.sleep( waitBetweenRuns );
+            }
+            timeForValueComposite = timeForValueComposite / runs;
+        }
+
+        long timeForTransientCompositeBuilder = 0;
+        {
+            TransientBuilderFactory module = assembler.module();
+            // Warmup
+            for( int i = 0; i < warmups; i++ )
+            {
+                testCompositeCreationWithBuilderPerformance( module, false );
+            }
+            Thread.sleep( waitBeforeRun );
+            // Run
+            for( int i = 0; i < runs; i++ )
+            {
+                timeForTransientCompositeBuilder += testCompositeCreationWithBuilderPerformance( module, true );
+                Thread.sleep( waitBetweenRuns );
+            }
+            timeForTransientCompositeBuilder = timeForTransientCompositeBuilder / runs;
+        }
+        long timeForValueCompositeBuilder = 0;
+        {
+            ValueBuilderFactory valueBuilderFactory = assembler.module();
+            // Warmup
+            for( int i = 0; i < warmups; i++ )
+            {
+                testValueCreationWithBuilderPerformance( valueBuilderFactory, false );
+            }
+            Thread.sleep( waitBeforeRun );
+            // Run
+            for( int i = 0; i < runs; i++ )
+            {
+                timeForValueCompositeBuilder += testValueCreationWithBuilderPerformance( valueBuilderFactory, true );
+                Thread.sleep( waitBetweenRuns );
+            }
+            timeForValueCompositeBuilder = timeForValueCompositeBuilder / runs;
+        }
+
+        System.out.println( "----" );
+        System.out.println( "Transient: " + ( timeForTransientComposite / timeForJavaObject ) + "x" );
+        System.out.println( "TransientBuilder: " + ( timeForTransientCompositeBuilder / timeForJavaObject ) + "x" );
+        System.out.println( "Value: " + ( timeForValueComposite / timeForJavaObject ) + "x" );
+        System.out.println( "ValueBuilder: " + ( timeForValueCompositeBuilder / timeForJavaObject ) + "x" );
+        System.out.println( "Object: " + ( timeForManagedObject / timeForJavaObject ) + "x" );
+    }
+
+    private long testCompositeCreationPerformance( TransientBuilderFactory module, boolean run )
+    {
+        long start = System.currentTimeMillis();
+        int iter = 1000000;
+        for( int i = 0; i < iter; i++ )
+        {
+            module.newTransient( AnyComposite.class );
+        }
+
+        long end = System.currentTimeMillis();
+        long time = 1000000L * ( end - start ) / iter;
+        if( run )
+        {
+            System.out.println( "Composite Creation Time:" + time + " nanoseconds per composite" );
+        }
+        return time;
+    }
+
+    private long testCompositeCreationWithBuilderPerformance( TransientBuilderFactory module, boolean run )
+    {
+        long start = System.currentTimeMillis();
+        int iter = 1000000;
+        for( int i = 0; i < iter; i++ )
+        {
+            module.newTransientBuilder( AnyComposite.class ).newInstance();
+        }
+
+        long end = System.currentTimeMillis();
+        long time = 1000000L * ( end - start ) / iter;
+        if( run )
+        {
+            System.out.println( "Composite (builder) Creation Time:" + time + " nanoseconds per composite" );
+        }
+        return time;
+    }
+
+    private long testValueCreationPerformance( ValueBuilderFactory valueBuilderFactory, boolean run )
+    {
+        long start = System.currentTimeMillis();
+        int iter = 1000000;
+        for( int i = 0; i < iter; i++ )
+        {
+            valueBuilderFactory.newValue( AnyValue.class );
+        }
+
+        long end = System.currentTimeMillis();
+        long time = 1000000L * ( end - start ) / iter;
+        if( run )
+        {
+            System.out.println( "Value Creation Time:" + time + " nanoseconds per composite" );
+        }
+        return time;
+    }
+
+    private long testValueCreationWithBuilderPerformance( ValueBuilderFactory valueBuilderFactory, boolean run )
+    {
+        long start = System.currentTimeMillis();
+        int iter = 1000000;
+        for( int i = 0; i < iter; i++ )
+        {
+            valueBuilderFactory.newValueBuilder( AnyValue.class ).newInstance();
+        }
+
+        long end = System.currentTimeMillis();
+        long time = 1000000L * ( end - start ) / iter;
+        if( run )
+        {
+            System.out.println( "Value (builder) Creation Time:" + time + " nanoseconds per composite" );
+        }
+        return time;
+    }
+
+    private long testObjectCreationPerformance( ObjectFactory objectFactory, boolean run )
+    {
+        long start = System.currentTimeMillis();
+        int iter = 1000000;
+        for( int i = 0; i < iter; i++ )
+        {
+            objectFactory.newObject( AnyObject.class );
+        }
+
+        long end = System.currentTimeMillis();
+        long time = 1000000L * ( end - start ) / iter;
+        if( run )
+        {
+            System.out.println( "Polygene Object Creation Time:" + time + " nanoseconds per object" );
+        }
+        return time;
+    }
+
+    private long testJavaObjectCreationPerformance( boolean run )
+    {
+        long start = System.currentTimeMillis();
+        int iter = 1000000;
+        for( int i = 0; i < iter; i++ )
+        {
+            new AnyObject();
+        }
+
+        long end = System.currentTimeMillis();
+        long time = 1000000L * ( end - start ) / iter;
+        if( run )
+        {
+            System.out.println( "Java Object Creation Time:" + time + " nanoseconds per object" );
+        }
+        return time;
+    }
+
+    public interface AnyComposite
+        extends TransientComposite
+    {
+    }
+
+    public interface AnyValue
+        extends ValueComposite
+    {
+    }
+
+    public static class AnyObject
+    {
+    }
+}
diff --git a/tests/performance/src/perf/java/org/apache/polygene/test/performance/runtime/composite/InvocationPerformanceTest.java b/tests/performance/src/perf/java/org/apache/polygene/test/performance/runtime/composite/InvocationPerformanceTest.java
new file mode 100644
index 0000000..c63e33a
--- /dev/null
+++ b/tests/performance/src/perf/java/org/apache/polygene/test/performance/runtime/composite/InvocationPerformanceTest.java
@@ -0,0 +1,204 @@
+/*
+ *  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.polygene.test.performance.runtime.composite;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.text.NumberFormat;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+/**
+ * Invocation performance test.
+ * <p>
+ * Don't forget to add VM value "-server" before running this test!
+ * </p>
+ * <p>
+ * These tests are very sensitive to warmup of JVM, hence the duplication. Often the first round
+ * is only for getting the code jitted, and the second round is what you want to look at.
+ * </p>
+ */
+public class InvocationPerformanceTest
+    extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( SimpleComposite.class );
+        module.transients( SimpleWithTypedConcernComposite.class );
+        module.transients( SimpleWithGenericConcernComposite.class );
+    }
+
+    @Test
+    public void testInvokeMixin()
+    {
+        // Create instance
+        TransientBuilder<SimpleComposite> builder = transientBuilderFactory.newTransientBuilder( SimpleComposite.class );
+        Simple simple = builder.newInstance();
+
+        for( int i = 0; i < 60000; i++ )
+        {
+            simple.test();
+        }
+
+        int rounds = 10;
+        for( int i = 0; i < rounds; i++ )
+        {
+            System.gc();
+            performanceCheck( simple );
+        }
+    }
+
+    @Test
+    public void testInvokeMixinWithTypedConcern()
+    {
+        // Create instance
+        Simple simple = transientBuilderFactory.newTransient( SimpleWithTypedConcernComposite.class );
+
+        for( int i = 0; i < 60000; i++ )
+        {
+            simple.test();
+        }
+
+        int rounds = 3;
+        for( int i = 0; i < rounds; i++ )
+        {
+            performanceCheck( simple );
+        }
+    }
+
+    @Test
+    public void testInvokeMixinWithGenericConcern()
+    {
+        // Create instance
+        Simple simple = transientBuilderFactory.newTransient( SimpleWithGenericConcernComposite.class );
+
+        for( int i = 0; i < 60000; i++ )
+        {
+            simple.test();
+        }
+
+        int rounds = 3;
+        for( int i = 0; i < rounds; i++ )
+        {
+            performanceCheck( simple );
+        }
+    }
+
+    @Test
+    public void testInvokeMixin2()
+    {
+        testInvokeMixin();
+    }
+
+    @Test
+    public void testInvokeMixinWithTypedConcern2()
+    {
+        testInvokeMixinWithTypedConcern();
+    }
+
+    @Test
+    public void testInvokeMixinWithGenericConcern2()
+    {
+        testInvokeMixinWithGenericConcern();
+    }
+
+    private void performanceCheck( Simple simple )
+    {
+        long count = 10000000L;
+
+        long start = System.currentTimeMillis();
+        for( long i = 0; i < count; i++ )
+        {
+            simple.test();
+        }
+        long end = System.currentTimeMillis();
+        long time = end - start;
+        long callsPerSecond = ( count / time ) * 1000;
+        System.out.println( "Calls per second: " + NumberFormat.getIntegerInstance().format( callsPerSecond ) );
+    }
+
+    @Mixins( SimpleMixin.class )
+    @Concerns( SimpleTypedConcern.class )
+    public interface SimpleWithTypedConcernComposite
+        extends Simple, TransientComposite
+    {
+    }
+
+    @Mixins( SimpleMixin.class )
+    @Concerns( SimpleGenericConcern.class )
+    public interface SimpleWithGenericConcernComposite
+        extends Simple, TransientComposite
+    {
+    }
+
+    @Mixins( SimpleMixin.class )
+    public interface SimpleComposite
+        extends Simple, TransientComposite
+    {
+    }
+
+    public interface Simple
+    {
+        public void test();
+    }
+
+    public static class SimpleMixin
+        implements Simple
+    {
+        long count = 0;
+
+        @Override
+        public void test()
+        {
+            count++; // Do nothing
+        }
+    }
+
+    public static class SimpleTypedConcern
+        extends ConcernOf<Simple>
+        implements Simple
+    {
+        @Override
+        public void test()
+        {
+            next.test();
+        }
+    }
+
+    public static class SimpleGenericConcern
+        extends ConcernOf<InvocationHandler>
+        implements InvocationHandler
+    {
+        @Override
+        public Object invoke( Object o, Method method, Object[] objects )
+            throws Throwable
+        {
+            return next.invoke( o, method, objects );
+        }
+    }
+
+}
diff --git a/tests/performance/src/perf/java/org/apache/polygene/test/performance/runtime/composite/PropertyMixinInvocationPerformanceTest.java b/tests/performance/src/perf/java/org/apache/polygene/test/performance/runtime/composite/PropertyMixinInvocationPerformanceTest.java
new file mode 100644
index 0000000..7508fe2
--- /dev/null
+++ b/tests/performance/src/perf/java/org/apache/polygene/test/performance/runtime/composite/PropertyMixinInvocationPerformanceTest.java
@@ -0,0 +1,134 @@
+/*
+ *  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.polygene.test.performance.runtime.composite;
+
+import java.text.NumberFormat;
+import java.util.Locale;
+import org.junit.Test;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+/**
+ * PropertyMixin invocation performance test.
+ * <p>
+ * Don't forget to add VM value "-server" before running this test!
+ * </p>
+ */
+public class PropertyMixinInvocationPerformanceTest
+    extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( SimpleComposite.class );
+        module.transients( SimpleComposite2.class );
+    }
+
+    @Test
+    public void testNewInstance()
+    {
+        {
+            TransientBuilder<SimpleComposite> builder = transientBuilderFactory.newTransientBuilder( SimpleComposite.class );
+            SimpleComposite simple = builder.newInstance();
+
+            int rounds = 1;
+            for( int i = 0; i < rounds; i++ )
+            {
+                performanceCheck( simple );
+            }
+        }
+
+        {
+            TransientBuilder<SimpleComposite> builder = transientBuilderFactory.newTransientBuilder( SimpleComposite.class );
+            SimpleComposite simple = builder.newInstance();
+
+            int rounds = 1;
+            for( int i = 0; i < rounds; i++ )
+            {
+                performanceCheck( simple );
+            }
+        }
+    }
+
+    private void performanceCheck( SimpleComposite simple )
+    {
+        long count = 10000000L;
+
+        {
+            long start = System.currentTimeMillis();
+            for( long i = 0; i < count; i++ )
+            {
+                simple.test();
+            }
+            long end = System.currentTimeMillis();
+            long time = end - start;
+            long callsPerSecond = ( count / time ) * 1000;
+            System.out.println( "Accesses per second: "
+                                + NumberFormat.getIntegerInstance( Locale.US ).format( callsPerSecond ) );
+        }
+
+        {
+            long start = System.currentTimeMillis();
+            for( long i = 0; i < count; i++ )
+            {
+                simple.test().get();
+            }
+            long end = System.currentTimeMillis();
+            long time = end - start;
+            long callsPerSecond = ( count / time ) * 1000;
+            System.out.println( "Gets per second: "
+                                + NumberFormat.getIntegerInstance( Locale.US ).format( callsPerSecond ) );
+        }
+    }
+
+    public interface SimpleComposite
+        extends TransientComposite
+    {
+        @Optional
+        Property<String> test();
+    }
+
+    @Mixins( SimpleMixin.class )
+    public interface SimpleComposite2
+        extends SimpleComposite
+    {
+    }
+
+    public abstract static class SimpleMixin
+        implements SimpleComposite2
+    {
+        @State
+        Property<String> test;
+
+        @Override
+        public Property<String> test()
+        {
+            return test;
+        }
+    }
+
+}
diff --git a/tests/performance/src/perf/java/org/apache/polygene/test/performance/runtime/object/ObjectCreationPerformanceTest.java b/tests/performance/src/perf/java/org/apache/polygene/test/performance/runtime/object/ObjectCreationPerformanceTest.java
new file mode 100644
index 0000000..b995770
--- /dev/null
+++ b/tests/performance/src/perf/java/org/apache/polygene/test/performance/runtime/object/ObjectCreationPerformanceTest.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.test.performance.runtime.object;
+
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+/**
+ * Tests performance of new object creation.
+ */
+public class ObjectCreationPerformanceTest
+{
+
+    @Test
+    public void newInstanceForRegisteredObjectPerformance()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.objects( AnyObject.class );
+            }
+        };
+        ObjectFactory objectFactory = assembler.module();
+        for( int i = 0; i < 10; i++ )
+        {
+            testPerformance( objectFactory );
+        }
+    }
+
+    private void testPerformance( ObjectFactory objectFactory )
+    {
+        long start = System.currentTimeMillis();
+        int iter = 1000000;
+        for( int i = 0; i < iter; i++ )
+        {
+            objectFactory.newObject( AnyObject.class );
+        }
+
+        long end = System.currentTimeMillis();
+        System.out.println( end - start );
+    }
+
+    public static final class AnyObject
+    {
+    }
+
+}
diff --git a/tests/performance/src/perf/java/org/apache/polygene/test/performance/runtime/service/ServiceInvocationPerformanceTest.java b/tests/performance/src/perf/java/org/apache/polygene/test/performance/runtime/service/ServiceInvocationPerformanceTest.java
new file mode 100644
index 0000000..c599f6e
--- /dev/null
+++ b/tests/performance/src/perf/java/org/apache/polygene/test/performance/runtime/service/ServiceInvocationPerformanceTest.java
@@ -0,0 +1,113 @@
+/*
+ *  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.polygene.test.performance.runtime.service;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.text.NumberFormat;
+import junit.framework.TestCase;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+public class ServiceInvocationPerformanceTest
+    extends TestCase
+{
+    @Service
+    ServiceInvocationPerformanceTest.MyService service;
+
+    public void testInjectService()
+        throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.services( ServiceInvocationPerformanceTest.MyServiceComposite.class );
+                module.objects( ServiceInvocationPerformanceTest.class );
+            }
+        };
+
+        assembly.module().injectTo( this );
+
+        // Warmup
+        for( int i = 0; i < 60000; i++ )
+        {
+            service.test();
+        }
+
+        int rounds = 5;
+        for( int i = 0; i < rounds; i++ )
+        {
+            performanceCheck( service );
+        }
+    }
+
+    private void performanceCheck( MyService simple )
+    {
+        long count = 10000000L;
+
+        long start = System.currentTimeMillis();
+        for( long i = 0; i < count; i++ )
+        {
+            simple.test();
+        }
+        long end = System.currentTimeMillis();
+        long time = end - start;
+        long callsPerSecond = ( count / time ) * 1000;
+        System.out.println( "Calls per second: " + NumberFormat.getIntegerInstance().format( callsPerSecond ) );
+    }
+
+    @Mixins( NoopMixin.class )
+    public static interface MyServiceComposite
+        extends ServiceInvocationPerformanceTest.MyService, ServiceComposite
+    {
+    }
+
+    public static interface MyService
+    {
+        void test();
+    }
+
+    public static class MyServiceMixin
+        implements ServiceInvocationPerformanceTest.MyService
+    {
+        @Override
+        public void test()
+        {
+        }
+    }
+
+    public final static class NoopMixin
+        implements InvocationHandler
+    {
+        @Override
+        public Object invoke( Object object, Method method, Object[] objects )
+            throws Throwable
+        {
+            return null;
+        }
+    }
+
+}
diff --git a/tests/performance/src/perf/java/org/qi4j/test/performance/entitystore/jdbm/JdbmEntityStorePerformanceTest.java b/tests/performance/src/perf/java/org/qi4j/test/performance/entitystore/jdbm/JdbmEntityStorePerformanceTest.java
deleted file mode 100644
index bbfe0cb..0000000
--- a/tests/performance/src/perf/java/org/qi4j/test/performance/entitystore/jdbm/JdbmEntityStorePerformanceTest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.test.performance.entitystore.jdbm;
-
-import java.io.File;
-import org.apache.derby.iapi.services.io.FileUtil;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.cache.ehcache.EhCacheConfiguration;
-import org.qi4j.cache.ehcache.EhCachePoolService;
-import org.qi4j.entitystore.jdbm.JdbmConfiguration;
-import org.qi4j.entitystore.jdbm.assembly.JdbmEntityStoreAssembler;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.performance.entitystore.AbstractEntityStorePerformanceTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-/**
- * Performance test for JdbmEntityStoreComposite
- */
-public class JdbmEntityStorePerformanceTest
-    extends AbstractEntityStorePerformanceTest
-{
-    public JdbmEntityStorePerformanceTest()
-    {
-        super( "JdbmEntityStore", createAssembler() );
-    }
-
-    private static Assembler createAssembler()
-    {
-        return new Assembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                new JdbmEntityStoreAssembler().assemble( module );
-                new OrgJsonValueSerializationAssembler().assemble( module );
-                ModuleAssembly configModule = module.layer().module( "Config" );
-                configModule.entities( JdbmConfiguration.class ).visibleIn( Visibility.layer );
-                new EntityTestAssembler().assemble( configModule );
-
-                module.services( EhCachePoolService.class );
-                configModule.entities( EhCacheConfiguration.class ).visibleIn( Visibility.layer );
-            }
-        };
-    }
-
-    @Override
-    public void cleanUp()
-        throws Exception
-    {
-        super.cleanUp();
-        FileUtil.removeDirectory( new File( "build/tmp/jdbm" ) );
-    }
-}
diff --git a/tests/performance/src/perf/java/org/qi4j/test/performance/entitystore/memory/MemoryEntityStorePerformanceTest.java b/tests/performance/src/perf/java/org/qi4j/test/performance/entitystore/memory/MemoryEntityStorePerformanceTest.java
deleted file mode 100644
index 3fe07a7..0000000
--- a/tests/performance/src/perf/java/org/qi4j/test/performance/entitystore/memory/MemoryEntityStorePerformanceTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.test.performance.entitystore.memory;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreAssembler;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.spi.entitystore.helpers.MapEntityStoreMixin;
-import org.qi4j.test.performance.entitystore.AbstractEntityStorePerformanceTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-public class MemoryEntityStorePerformanceTest
-    extends AbstractEntityStorePerformanceTest
-{
-
-    public MemoryEntityStorePerformanceTest()
-    {
-        super( "MemoryEntityStore", createAssembler() );
-    }
-
-    private static Assembler createAssembler()
-    {
-        return new Assembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                new MemoryEntityStoreAssembler().assemble( module );
-                new OrgJsonValueSerializationAssembler().assemble( module );
-            }
-        };
-    }
-
-    // Alternate variant that uses the standard MapEntityStore
-    @Mixins( MapEntityStoreMixin.class )
-    interface MemoryEntityStoreService2
-        extends MemoryEntityStoreService
-    {
-    }
-
-}
diff --git a/tests/performance/src/perf/java/org/qi4j/test/performance/entitystore/sql/DerbySQLEntityStorePerformanceTest.java b/tests/performance/src/perf/java/org/qi4j/test/performance/entitystore/sql/DerbySQLEntityStorePerformanceTest.java
deleted file mode 100644
index a37d24a..0000000
--- a/tests/performance/src/perf/java/org/qi4j/test/performance/entitystore/sql/DerbySQLEntityStorePerformanceTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.test.performance.entitystore.sql;
-
-import java.sql.Connection;
-import java.sql.Statement;
-import javax.sql.DataSource;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.usecase.UsecaseBuilder;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.sql.assembly.DerbySQLEntityStoreAssembler;
-import org.qi4j.entitystore.sql.internal.SQLs;
-import org.qi4j.library.sql.assembly.DataSourceAssembler;
-import org.qi4j.library.sql.common.SQLConfiguration;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.qi4j.library.sql.dbcp.DBCPDataSourceServiceAssembler;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.test.performance.entitystore.AbstractEntityStorePerformanceTest;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-/**
- * Performance test for DerbySQLEntityStore.
- */
-public class DerbySQLEntityStorePerformanceTest
-    extends AbstractEntityStorePerformanceTest
-{
-
-    public DerbySQLEntityStorePerformanceTest()
-    {
-        super( "DerbySQLEntityStore", createAssembler() );
-    }
-
-    private static Assembler createAssembler()
-    {
-        return new Assembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                ModuleAssembly config = module.layer().module( "config" );
-                new EntityTestAssembler().assemble( config );
-
-                new OrgJsonValueSerializationAssembler().assemble( module );
-
-                // DataSourceService
-                new DBCPDataSourceServiceAssembler().
-                    identifiedBy( "derby-datasource-service" ).
-                    visibleIn( Visibility.module ).
-                    withConfig( config, Visibility.layer ).
-                    assemble( module );
-
-                // DataSource
-                new DataSourceAssembler().
-                    withDataSourceServiceIdentity( "derby-datasource-service" ).
-                    identifiedBy( "derby-datasource" ).
-                    withCircuitBreaker().
-                    assemble( module );
-
-                // SQL EntityStore
-                new DerbySQLEntityStoreAssembler().
-                    withConfig( config, Visibility.layer ).
-                    assemble( module );
-            }
-        };
-    }
-
-    @Override
-    protected void cleanUp()
-        throws Exception
-    {
-        if( module == null )
-        {
-            return;
-        }
-        UnitOfWork uow = this.module.newUnitOfWork( UsecaseBuilder.newUsecase(
-            "Delete " + getClass().getSimpleName() + " test data" ) );
-        try
-        {
-            SQLConfiguration config = uow.get( SQLConfiguration.class,
-                                               DerbySQLEntityStoreAssembler.DEFAULT_ENTITYSTORE_IDENTITY );
-            Connection connection = module.findService( DataSource.class ).get().getConnection();
-            String schemaName = config.schemaName().get();
-            if( schemaName == null )
-            {
-                schemaName = SQLs.DEFAULT_SCHEMA_NAME;
-            }
-
-            Statement stmt = null;
-            try
-            {
-                stmt = connection.createStatement();
-                stmt.execute( String.format( "DELETE FROM %s." + SQLs.TABLE_NAME, schemaName ) );
-                connection.commit();
-            }
-            finally
-            {
-                SQLUtil.closeQuietly( stmt );
-            }
-        }
-        finally
-        {
-            uow.discard();
-            super.cleanUp();
-        }
-    }
-
-}
diff --git a/tests/performance/src/perf/java/org/qi4j/test/performance/entitystore/sql/PostgreSQLEntityStorePerformanceTest.java b/tests/performance/src/perf/java/org/qi4j/test/performance/entitystore/sql/PostgreSQLEntityStorePerformanceTest.java
deleted file mode 100644
index 4291297..0000000
--- a/tests/performance/src/perf/java/org/qi4j/test/performance/entitystore/sql/PostgreSQLEntityStorePerformanceTest.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 2010-2012, Stanislav Muhametsin. All Rights Reserved.
- * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.test.performance.entitystore.sql;
-
-import java.sql.Connection;
-import java.sql.Statement;
-import org.junit.Ignore;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.bootstrap.ApplicationAssemblerAdapter;
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.entitystore.sql.assembly.PostgreSQLEntityStoreAssembler;
-import org.qi4j.entitystore.sql.internal.SQLs;
-import org.qi4j.library.sql.assembly.DataSourceAssembler;
-import org.qi4j.library.sql.common.SQLConfiguration;
-import org.qi4j.library.sql.common.SQLUtil;
-import org.qi4j.library.sql.dbcp.DBCPDataSourceServiceAssembler;
-import org.qi4j.test.performance.entitystore.AbstractEntityStorePerformanceTest;
-
-/**
- * Performance test for PostgreSQLEntityStore.
- * <p>
- * WARN This test is deactivated on purpose, please do not commit it activated.
- * </p>
- * <p>
- * To run it see PostgreSQLEntityStoreTest.
- * </p>
- */
-@Ignore( "WARN Tearing down this test is broken!" )
-public class PostgreSQLEntityStorePerformanceTest
-    extends AbstractEntityStorePerformanceTest
-{
-
-    public PostgreSQLEntityStorePerformanceTest()
-    {
-        super( "PostgreSQLEntityStore", createAssembler() );
-    }
-
-    private static Assembler createAssembler()
-    {
-        return new Assembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                ModuleAssembly config = module.layer().module( "config" );
-                config.services( MemoryEntityStoreService.class );
-
-                // DataSourceService
-                new DBCPDataSourceServiceAssembler().
-                    identifiedBy( "postgresql-datasource-service" ).
-                    visibleIn( Visibility.module ).
-                    withConfig( config, Visibility.layer ).
-                    assemble( module );
-
-                // DataSource
-                new DataSourceAssembler().
-                    withDataSourceServiceIdentity( "postgresql-datasource-service" ).
-                    identifiedBy( "postgresql-datasource" ).
-                    withCircuitBreaker().
-                    assemble( module );
-
-                // SQL EntityStore
-                new PostgreSQLEntityStoreAssembler().
-                    withConfig( config, Visibility.layer ).
-                    assemble( module );
-            }
-
-        };
-    }
-
-    @Override
-    protected void cleanUp()
-        throws Exception
-    {
-        try
-        {
-            super.cleanUp();
-        }
-        finally
-        {
-
-            Energy4Java qi4j = new Energy4Java();
-            Assembler[][][] assemblers = new Assembler[][][]
-            {
-                {
-                    {
-                        createAssembler()
-                    }
-                }
-            };
-            Application application = qi4j.newApplication( new ApplicationAssemblerAdapter( assemblers )
-            {
-            } );
-            application.activate();
-
-            Module moduleInstance = application.findModule( "Layer 1", "config" );
-            UnitOfWorkFactory uowf = moduleInstance;
-            UnitOfWork uow = uowf.newUnitOfWork();
-            try
-            {
-                SQLConfiguration config = uow.get( SQLConfiguration.class,
-                                                   PostgreSQLEntityStoreAssembler.DEFAULT_ENTITYSTORE_IDENTITY );
-                // TODO fix AbstractEntityStorePerformanceTest to extend from AbstractQi4jTest
-                Connection connection = null; // SQLUtil.getConnection( this.serviceLocator );
-                String schemaName = config.schemaName().get();
-                if( schemaName == null )
-                {
-                    schemaName = SQLs.DEFAULT_SCHEMA_NAME;
-                }
-
-                Statement stmt = null;
-                try
-                {
-                    stmt = connection.createStatement();
-                    stmt.execute( String.format( "DELETE FROM %s." + SQLs.TABLE_NAME, schemaName ) );
-                    connection.commit();
-                }
-                finally
-                {
-                    SQLUtil.closeQuietly( stmt );
-                }
-            }
-            finally
-            {
-                uow.discard();
-            }
-        }
-    }
-
-}
diff --git a/tests/performance/src/perf/java/org/qi4j/test/performance/indexing/rdf/QueryPerformanceTest.java b/tests/performance/src/perf/java/org/qi4j/test/performance/indexing/rdf/QueryPerformanceTest.java
deleted file mode 100644
index 0a8fc20..0000000
--- a/tests/performance/src/perf/java/org/qi4j/test/performance/indexing/rdf/QueryPerformanceTest.java
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Copyright (c) 2009-2013, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.test.performance.indexing.rdf;
-
-import java.io.File;
-import org.apache.derby.iapi.services.io.FileUtil;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-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;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreAssembler;
-import org.qi4j.index.rdf.assembly.RdfNativeSesameStoreAssembler;
-import org.qi4j.index.rdf.indexing.RdfIndexingService;
-import org.qi4j.index.rdf.query.SesameExpressions;
-import org.qi4j.library.rdf.repository.NativeConfiguration;
-import org.qi4j.test.EntityTestAssembler;
-import org.qi4j.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
-
-import static org.qi4j.api.query.QueryExpressions.eq;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-@SuppressWarnings( "ResultOfMethodCallIgnored" )
-public class QueryPerformanceTest
-    implements ApplicationAssembler
-{
-    private static final int NUMBER_OF_ENTITIES = 100000;
-    private static final String LAYER_INFRASTRUCTURE = "LAYER_INFRASTRUCTURE";
-    private static final String MODULE_PERSISTENCE = "MODULE_PERSISTENCE";
-    private static final String LAYER_CONFIGURATION = "CONFIGURATION";
-    private static final String LAYER_DOMAIN = "LAYER_DOMAIN";
-    private static final String MODULE_DOMAIN = "MODULE_DOMAIN";
-    private static final String MODULE_CONFIG = "MODULE_CONFIG";
-
-    private Application application;
-    private Module module;
-    private static final String QUERY1 = "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-                                         + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-                                         + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
-                                         + "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.performance.indexing.rdf.QueryPerformanceTest-Lead#> \n"
-                                         + "SELECT ?entityType ?identity\n"
-                                         + "WHERE {\n"
-                                         + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.performance.indexing.rdf.QueryPerformanceTest-Lead>. \n"
-                                         + "?entity rdf:type ?entityType. \n"
-                                         + "?entity ns0:identity ?identity. \n"
-                                         + "?entity ns1:name \"Lead64532\". \n"
-                                         + "}";
-    private static final String QUERY2 = "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-                                         + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-                                         + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
-                                         + "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.performance.indexing.rdf.QueryPerformanceTest-Lead#> \n"
-                                         + "SELECT ?entityType ?identity\n"
-                                         + "WHERE {\n"
-                                         + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.performance.indexing.rdf.QueryPerformanceTest-Lead>. \n"
-                                         + "?entity rdf:type ?entityType. \n"
-                                         + "?entity ns0:identity ?identity. \n"
-                                         + "?entity ns1:name \"Lead98276\". \n"
-                                         + "}";
-    private static final String QUERY3 = "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-                                         + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-                                         + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
-                                         + "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.performance.indexing.rdf.QueryPerformanceTest-Lead#> \n"
-                                         + "SELECT ?entityType ?identity\n"
-                                         + "WHERE {\n"
-                                         + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.performance.indexing.rdf.QueryPerformanceTest-Lead>. \n"
-                                         + "?entity rdf:type ?entityType. \n"
-                                         + "?entity ns0:identity ?identity. \n"
-                                         + "?entity ns1:name \"Lead2\". \n"
-                                         + "}";
-    private static final String QUERY4 = "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-                                         + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-                                         + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
-                                         + "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.performance.indexing.rdf.QueryPerformanceTest-Lead#> \n"
-                                         + "SELECT ?entityType ?identity\n"
-                                         + "WHERE {\n"
-                                         + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.performance.indexing.rdf.QueryPerformanceTest-Lead>. \n"
-                                         + "?entity rdf:type ?entityType. \n"
-                                         + "?entity ns0:identity ?identity. \n"
-                                         + "?entity ns1:name \"Lead14332\". \n"
-                                         + "}";
-    private static final String QUERY5 = "PREFIX ns0: <urn:qi4j:type:org.qi4j.api.entity.Identity#> \n"
-                                         + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
-                                         + "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
-                                         + "PREFIX ns1: <urn:qi4j:type:org.qi4j.test.performance.indexing.rdf.QueryPerformanceTest-Lead#> \n"
-                                         + "SELECT ?entityType ?identity\n"
-                                         + "WHERE {\n"
-                                         + "?entityType rdfs:subClassOf <urn:qi4j:type:org.qi4j.test.performance.indexing.rdf.QueryPerformanceTest-Lead>. \n"
-                                         + "?entity rdf:type ?entityType. \n"
-                                         + "?entity ns0:identity ?identity. \n"
-                                         + "?entity ns1:name \"Lead632\". \n"
-                                         + "}";
-    private File indexingDataDir;
-
-    @Before
-    public void setup()
-        throws Exception
-    {
-        Energy4Java qi4j = new Energy4Java();
-        application = qi4j.newApplication( this );
-        module = application.findModule( LAYER_DOMAIN, MODULE_DOMAIN );
-        application.activate();
-        indexingDataDir = module.findService( RdfIndexingService.class ).get().dataDir();
-    }
-
-    @After
-    public void tearDown()
-        throws Exception
-    {
-        try
-        {
-            if( application != null )
-            {
-                System.out.println( "Shutting Down test." );
-                application.passivate();
-            }
-        }
-        finally
-        {
-            FileUtil.removeDirectory( indexingDataDir );
-        }
-    }
-
-    @Override
-    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-        throws AssemblyException
-    {
-        ApplicationAssembly applicationAssembly = applicationFactory.newApplicationAssembly();
-        LayerAssembly infra = createInfrastructureLayer( applicationAssembly );
-        LayerAssembly domain = createDomainLayer( applicationAssembly );
-        LayerAssembly config = createConfigurationLayer( applicationAssembly );
-        infra.uses( config );
-        domain.uses( infra );
-        return applicationAssembly;
-    }
-
-    @Test
-    public void testIndexingFluentQueries()
-        throws Exception
-    {
-        LeadRepository leadRepo = populateEntityStore();
-        measureFluentQuery( leadRepo, "Lead64531" );
-        measureFluentQuery( leadRepo, "Lead98275" );
-        measureFluentQuery( leadRepo, "Lead3" );
-        measureFluentQuery( leadRepo, "Lead14331" );
-        measureFluentQuery( leadRepo, "Lead631" );
-    }
-
-    @Test
-    public void testIndexingNamedQueries()
-        throws Exception
-    {
-        LeadRepository leadRepo = populateEntityStore();
-        measureNamedQuery( leadRepo, QUERY1 );
-        measureNamedQuery( leadRepo, QUERY2 );
-        measureNamedQuery( leadRepo, QUERY3 );
-        measureNamedQuery( leadRepo, QUERY4 );
-        measureNamedQuery( leadRepo, QUERY5 );
-    }
-
-    private LeadRepository populateEntityStore()
-        throws UnitOfWorkCompletionException
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            LeadRepository leadRepo = module.findService( LeadRepositoryService.class ).get();
-            if( leadRepo.findByName( "Lead99999" ) == null )
-            {
-                ServiceReference<LeadEntityFactoryService> leadFactoryRef = module.findService( LeadEntityFactoryService.class );
-                LeadEntityFactory leadFactory = leadFactoryRef.get();
-                long start, end;
-                start = System.currentTimeMillis();
-                for( int i = 1; i < NUMBER_OF_ENTITIES; i++ )
-                {
-                    if( ( i % 10000 ) == 0 )
-                    {
-                        System.out.print( "\r" + i );
-                        uow.complete();
-                        uow = module.newUnitOfWork();
-                    }
-                    leadFactory.create( "Lead" + i );
-                }
-                System.out.println();
-                uow.complete();
-                end = System.currentTimeMillis();
-                System.out.println( "Population time: " + ( end - start ) );
-            }
-            return leadRepo;
-        }
-        finally
-        {
-            if( uow != null && uow.isOpen() )
-            {
-                uow.discard();
-            }
-        }
-    }
-
-    private void measureFluentQuery( LeadRepository leadRepo, String nameOfEntity )
-        throws Exception
-    {
-        long start;
-        long end;
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            start = System.currentTimeMillis();
-            Lead lead = leadRepo.findByName( nameOfEntity );
-            end = System.currentTimeMillis();
-            if( lead == null )
-            {
-                Assert.fail( "Entity was not found or more than one entity was found." );
-                return;
-            }
-            System.out.println( "Lead: " + lead );
-            System.out.println( "Retrieval time of " + lead.name().get() + " by name: " + ( end - start ) );
-            uow.complete();
-        }
-    }
-
-    private void measureNamedQuery( LeadRepository leadRepo, String queryName )
-        throws Exception
-    {
-        long start;
-        long end;
-        try( UnitOfWork uow = module.newUnitOfWork() )
-        {
-            start = System.currentTimeMillis();
-            Lead lead = leadRepo.findByFixedQuery( queryName );
-            end = System.currentTimeMillis();
-            if( lead == null )
-            {
-                Assert.fail( "Entity was not found or more than one entity was found." );
-                return;
-            }
-            System.out.println( "Lead: " + lead );
-            System.out.println( "Retrieval time of " + lead.name().get() + " by name: " + ( end - start ) );
-            uow.complete();
-        }
-    }
-
-    private LayerAssembly createDomainLayer( ApplicationAssembly applicationAssembly )
-        throws AssemblyException
-    {
-        LayerAssembly domainLayer = applicationAssembly.layer( LAYER_DOMAIN );
-        ModuleAssembly domainModule = domainLayer.module( MODULE_DOMAIN );
-        domainModule.addServices( LeadRepositoryService.class );
-        domainModule.addServices( LeadEntityFactoryService.class );
-        domainModule.entities( LeadEntity.class );
-        return domainLayer;
-    }
-
-    private LayerAssembly createInfrastructureLayer( ApplicationAssembly applicationAssembly )
-        throws AssemblyException
-    {
-        LayerAssembly infrastructureLayer = applicationAssembly.layer( LAYER_INFRASTRUCTURE );
-
-        // Persistence module
-        ModuleAssembly persistenceModule = infrastructureLayer.module( MODULE_PERSISTENCE );
-
-        // Indexing
-        new RdfNativeSesameStoreAssembler().assemble( persistenceModule );
-
-        // Entity store
-        new OrgJsonValueSerializationAssembler().assemble( persistenceModule );
-        new MemoryEntityStoreAssembler().visibleIn( Visibility.application ).assemble( persistenceModule );
-
-        return infrastructureLayer;
-    }
-
-    private LayerAssembly createConfigurationLayer( ApplicationAssembly applicationAssembly )
-        throws AssemblyException
-    {
-        LayerAssembly layer = applicationAssembly.layer( LAYER_CONFIGURATION );
-        ModuleAssembly configModule = layer.module( MODULE_CONFIG );
-        configModule.entities( NativeConfiguration.class ).visibleIn( Visibility.application );
-        new EntityTestAssembler().assemble( configModule );
-        return layer;
-    }
-
-    public interface Lead
-    {
-        Property<String> name();
-    }
-
-    public interface LeadEntity
-        extends Lead, EntityComposite
-    {
-    }
-
-    @Mixins( LeadEntityFactoryMixin.class )
-    public interface LeadEntityFactoryService
-        extends LeadEntityFactory, ServiceComposite
-    {
-    }
-
-    public interface LeadEntityFactory
-    {
-        Lead create( String name );
-    }
-
-    public static class LeadEntityFactoryMixin
-        implements LeadEntityFactory
-    {
-        @Structure
-        private Module module;
-
-        @Override
-        public Lead create( String name )
-        {
-            UnitOfWork uow = module.currentUnitOfWork();
-            EntityBuilder<LeadEntity> builder = uow.newEntityBuilder( LeadEntity.class );
-            Lead prototype = builder.instanceFor( LeadEntity.class );
-            prototype.name().set( name );
-            return builder.newInstance();
-        }
-    }
-
-    public interface LeadRepository
-    {
-        Lead findByFixedQuery( String name );
-
-        Lead findByName( String name );
-    }
-
-    @Mixins( LeadRepositoryMixin.class )
-    public interface LeadRepositoryService
-        extends LeadRepository, ServiceComposite
-    {
-    }
-
-    public static class LeadRepositoryMixin
-        implements LeadRepository
-    {
-        @Structure
-        private Module module;
-
-        @Override
-        public Lead findByFixedQuery( String queryString )
-        {
-            UnitOfWork uow = module.currentUnitOfWork();
-            Query<Lead> query = uow.newQuery( module.newQueryBuilder( Lead.class ).where( SesameExpressions.sparql( queryString ) ) );
-            return query.find();
-        }
-
-        @Override
-        public Lead findByName( String name )
-        {
-            UnitOfWork uow = module.currentUnitOfWork();
-            QueryBuilder<Lead> builder = module.newQueryBuilder( Lead.class );
-            Lead template = templateFor( Lead.class );
-
-            Query<Lead> query = uow.newQuery( builder.where( eq( template.name(), name ) ) );
-            return query.find();
-        }
-    }
-
-}
diff --git a/tests/performance/src/perf/java/org/qi4j/test/performance/runtime/composite/CompositeCreationPerformanceTest.java b/tests/performance/src/perf/java/org/qi4j/test/performance/runtime/composite/CompositeCreationPerformanceTest.java
deleted file mode 100644
index d287907..0000000
--- a/tests/performance/src/perf/java/org/qi4j/test/performance/runtime/composite/CompositeCreationPerformanceTest.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.test.performance.runtime.composite;
-
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientBuilderFactory;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.object.ObjectFactory;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-/**
- * Tests performance of new composite creation.
- */
-public class CompositeCreationPerformanceTest
-{
-    @Test
-    public void newInstanceForRegisteredCompositePerformance()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( AnyComposite.class );
-                module.objects( AnyObject.class );
-                module.values( AnyValue.class );
-            }
-        };
-        int loops = 2;
-        long t0 = 0;
-        {
-            for( int i = 0; i < loops; i++ )
-            {
-                t0 = t0 + testJavaObjectCreationPerformance();
-            }
-            t0 = t0 / loops;
-        }
-        long t1 = 0;
-        {
-            TransientBuilderFactory module = assembler.module();
-            for( int i = 0; i < loops; i++ )
-            {
-                t1 = t1 + testCompositeCreationPerformance( module );
-            }
-            t1 = t1 / loops;
-        }
-        long t2 = 0;
-        {
-            ObjectFactory objectFactory = assembler.module();
-            for( int i = 0; i < loops; i++ )
-            {
-                t2 = t2 + testObjectCreationPerformance( objectFactory );
-            }
-            t2 = t2 / loops;
-        }
-        long t3 = 0;
-        {
-            ValueBuilderFactory valueBuilderFactory = assembler.module();
-            for( int i = 0; i < loops; i++ )
-            {
-                t3 = t3 + testValueCreationPerformance( valueBuilderFactory );
-            }
-            t3 = t3 / loops;
-        }
-
-        long t4 = 0;
-        {
-            TransientBuilderFactory module = assembler.module();
-            for( int i = 0; i < loops; i++ )
-            {
-                t4 = t4 + testCompositeCreationWithBuilderPerformance( module );
-            }
-            t4 = t4 / loops;
-        }
-        long t6 = 0;
-        {
-            ValueBuilderFactory valueBuilderFactory = assembler.module();
-            for( int i = 0; i < loops; i++ )
-            {
-                t6 = t6 + testValueCreationWithBuilderPerformance( valueBuilderFactory );
-            }
-            t6 = t6 / loops;
-        }
-
-        System.out.println( "Transient: " + ( t1 / t0 ) + "x" );
-        System.out.println( "TransientBuilder: " + ( t4 / t0 ) + "x" );
-        System.out.println( "Value: " + ( t3 / t0 ) + "x" );
-        System.out.println( "ValueBuilder: " + ( t6 / t0 ) + "x" );
-        System.out.println( "Object: " + ( t2 / t0 ) + "x" );
-    }
-
-    private long testCompositeCreationPerformance( TransientBuilderFactory module )
-    {
-        long start = System.currentTimeMillis();
-        int iter = 1000000;
-        for( int i = 0; i < iter; i++ )
-        {
-            module.newTransient( AnyComposite.class );
-        }
-
-        long end = System.currentTimeMillis();
-        long time = 1000000L * ( end - start ) / iter;
-        System.out.println( "Minimum Composite Creation Time:" + time + " nanoseconds per composite" );
-        return time;
-    }
-
-    private long testCompositeCreationWithBuilderPerformance( TransientBuilderFactory module )
-    {
-        long start = System.currentTimeMillis();
-        int iter = 1000000;
-        for( int i = 0; i < iter; i++ )
-        {
-            TransientBuilder<AnyComposite> builder = module.newTransientBuilder( AnyComposite.class );
-            builder.newInstance();
-        }
-
-        long end = System.currentTimeMillis();
-        long time = 1000000L * ( end - start ) / iter;
-        System.out.println( "Minimum Composite (builder) Creation Time:" + time + " nanoseconds per composite" );
-        return time;
-    }
-
-    private long testValueCreationPerformance( ValueBuilderFactory valueBuilderFactory )
-    {
-        long start = System.currentTimeMillis();
-        int iter = 1000000;
-        for( int i = 0; i < iter; i++ )
-        {
-            valueBuilderFactory.newValue( AnyValue.class );
-        }
-
-        long end = System.currentTimeMillis();
-        long time = 1000000L * ( end - start ) / iter;
-        System.out.println( "Minimum Value Creation Time:" + time + " nanoseconds per composite" );
-        return time;
-    }
-
-    private long testValueCreationWithBuilderPerformance( ValueBuilderFactory valueBuilderFactory )
-    {
-        long start = System.currentTimeMillis();
-        int iter = 1000000;
-        for( int i = 0; i < iter; i++ )
-        {
-            ValueBuilder<AnyValue> builder = valueBuilderFactory.newValueBuilder( AnyValue.class );
-            builder.newInstance();
-        }
-
-        long end = System.currentTimeMillis();
-        long time = 1000000L * ( end - start ) / iter;
-        System.out.println( "Minimum Value (builder) Creation Time:" + time + " nanoseconds per composite" );
-        return time;
-    }
-
-    private long testObjectCreationPerformance( ObjectFactory objectFactory )
-    {
-        long start = System.currentTimeMillis();
-        int iter = 1000000;
-        for( int i = 0; i < iter; i++ )
-        {
-            objectFactory.newObject( AnyObject.class );
-        }
-
-        long end = System.currentTimeMillis();
-        long time = 1000000L * ( end - start ) / iter;
-        System.out.println( "Minimum Zest Object Creation Time:" + time + " nanoseconds per object" );
-        return time;
-    }
-
-    private long testJavaObjectCreationPerformance()
-    {
-        long start = System.currentTimeMillis();
-        int iter = 1000000;
-        for( int i = 0; i < iter; i++ )
-        {
-            new AnyObject();
-        }
-
-        long end = System.currentTimeMillis();
-        long time = 1000000L * ( end - start ) / iter;
-        System.out.println( "Minimum Java Object Creation Time:" + time + " nanoseconds per object" );
-        return time;
-    }
-
-    public static interface AnyComposite
-        extends TransientComposite
-    {
-    }
-
-    public static interface AnyValue
-        extends ValueComposite
-    {
-    }
-
-    public static class AnyObject
-    {
-    }
-
-}
diff --git a/tests/performance/src/perf/java/org/qi4j/test/performance/runtime/composite/InvocationPerformanceTest.java b/tests/performance/src/perf/java/org/qi4j/test/performance/runtime/composite/InvocationPerformanceTest.java
deleted file mode 100644
index 0e495ed..0000000
--- a/tests/performance/src/perf/java/org/qi4j/test/performance/runtime/composite/InvocationPerformanceTest.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 2007-2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed  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.qi4j.test.performance.runtime.composite;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.text.NumberFormat;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-/**
- * Invocation performance test.
- * <p>
- * Don't forget to add VM value "-server" before running this test!
- * </p>
- * <p>
- * These tests are very sensitive to warmup of JVM, hence the duplication. Often the first round
- * is only for getting the code jitted, and the second round is what you want to look at.
- * </p>
- */
-public class InvocationPerformanceTest
-    extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( SimpleComposite.class );
-        module.transients( SimpleWithTypedConcernComposite.class );
-        module.transients( SimpleWithGenericConcernComposite.class );
-    }
-
-    @Test
-    public void testInvokeMixin()
-    {
-        // Create instance
-        TransientBuilder<SimpleComposite> builder = module.newTransientBuilder( SimpleComposite.class );
-        Simple simple = builder.newInstance();
-
-        for( int i = 0; i < 60000; i++ )
-        {
-            simple.test();
-        }
-
-        int rounds = 10;
-        for( int i = 0; i < rounds; i++ )
-        {
-            System.gc();
-            performanceCheck( simple );
-        }
-    }
-
-    @Test
-    public void testInvokeMixinWithTypedConcern()
-    {
-        // Create instance
-        Simple simple = module.newTransient( SimpleWithTypedConcernComposite.class );
-
-        for( int i = 0; i < 60000; i++ )
-        {
-            simple.test();
-        }
-
-        int rounds = 3;
-        for( int i = 0; i < rounds; i++ )
-        {
-            performanceCheck( simple );
-        }
-    }
-
-    @Test
-    public void testInvokeMixinWithGenericConcern()
-    {
-        // Create instance
-        Simple simple = module.newTransient( SimpleWithGenericConcernComposite.class );
-
-        for( int i = 0; i < 60000; i++ )
-        {
-            simple.test();
-        }
-
-        int rounds = 3;
-        for( int i = 0; i < rounds; i++ )
-        {
-            performanceCheck( simple );
-        }
-    }
-
-    @Test
-    public void testInvokeMixin2()
-    {
-        testInvokeMixin();
-    }
-
-    @Test
-    public void testInvokeMixinWithTypedConcern2()
-    {
-        testInvokeMixinWithTypedConcern();
-    }
-
-    @Test
-    public void testInvokeMixinWithGenericConcern2()
-    {
-        testInvokeMixinWithGenericConcern();
-    }
-
-    private void performanceCheck( Simple simple )
-    {
-        long count = 10000000L;
-
-        long start = System.currentTimeMillis();
-        for( long i = 0; i < count; i++ )
-        {
-            simple.test();
-        }
-        long end = System.currentTimeMillis();
-        long time = end - start;
-        long callsPerSecond = ( count / time ) * 1000;
-        System.out.println( "Calls per second: " + NumberFormat.getIntegerInstance().format( callsPerSecond ) );
-    }
-
-    @Mixins( SimpleMixin.class )
-    @Concerns( SimpleTypedConcern.class )
-    public interface SimpleWithTypedConcernComposite
-        extends Simple, TransientComposite
-    {
-    }
-
-    @Mixins( SimpleMixin.class )
-    @Concerns( SimpleGenericConcern.class )
-    public interface SimpleWithGenericConcernComposite
-        extends Simple, TransientComposite
-    {
-    }
-
-    @Mixins( SimpleMixin.class )
-    public interface SimpleComposite
-        extends Simple, TransientComposite
-    {
-    }
-
-    public interface Simple
-    {
-        public void test();
-    }
-
-    public static class SimpleMixin
-        implements Simple
-    {
-        long count = 0;
-
-        @Override
-        public void test()
-        {
-            count++; // Do nothing
-        }
-    }
-
-    public static class SimpleTypedConcern
-        extends ConcernOf<Simple>
-        implements Simple
-    {
-        @Override
-        public void test()
-        {
-            next.test();
-        }
-    }
-
-    public static class SimpleGenericConcern
-        extends ConcernOf<InvocationHandler>
-        implements InvocationHandler
-    {
-        @Override
-        public Object invoke( Object o, Method method, Object[] objects )
-            throws Throwable
-        {
-            return next.invoke( o, method, objects );
-        }
-    }
-
-}
diff --git a/tests/performance/src/perf/java/org/qi4j/test/performance/runtime/composite/PropertyMixinInvocationPerformanceTest.java b/tests/performance/src/perf/java/org/qi4j/test/performance/runtime/composite/PropertyMixinInvocationPerformanceTest.java
deleted file mode 100644
index 6e38584..0000000
--- a/tests/performance/src/perf/java/org/qi4j/test/performance/runtime/composite/PropertyMixinInvocationPerformanceTest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed  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.qi4j.test.performance.runtime.composite;
-
-import java.text.NumberFormat;
-import java.util.Locale;
-import org.junit.Test;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.State;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-/**
- * PropertyMixin invocation performance test.
- * <p>
- * Don't forget to add VM value "-server" before running this test!
- * </p>
- */
-public class PropertyMixinInvocationPerformanceTest
-    extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( SimpleComposite.class );
-        module.transients( SimpleComposite2.class );
-    }
-
-    @Test
-    public void testNewInstance()
-    {
-        {
-            TransientBuilder<SimpleComposite> builder = module.newTransientBuilder( SimpleComposite.class );
-            SimpleComposite simple = builder.newInstance();
-
-            int rounds = 1;
-            for( int i = 0; i < rounds; i++ )
-            {
-                performanceCheck( simple );
-            }
-        }
-
-        {
-            TransientBuilder<SimpleComposite> builder = module.newTransientBuilder( SimpleComposite.class );
-            SimpleComposite simple = builder.newInstance();
-
-            int rounds = 1;
-            for( int i = 0; i < rounds; i++ )
-            {
-                performanceCheck( simple );
-            }
-        }
-    }
-
-    private void performanceCheck( SimpleComposite simple )
-    {
-        long count = 10000000L;
-
-        {
-            long start = System.currentTimeMillis();
-            for( long i = 0; i < count; i++ )
-            {
-                simple.test();
-            }
-            long end = System.currentTimeMillis();
-            long time = end - start;
-            long callsPerSecond = ( count / time ) * 1000;
-            System.out.println( "Accesses per second: "
-                                + NumberFormat.getIntegerInstance( Locale.US ).format( callsPerSecond ) );
-        }
-
-        {
-            long start = System.currentTimeMillis();
-            for( long i = 0; i < count; i++ )
-            {
-                simple.test().get();
-            }
-            long end = System.currentTimeMillis();
-            long time = end - start;
-            long callsPerSecond = ( count / time ) * 1000;
-            System.out.println( "Gets per second: "
-                                + NumberFormat.getIntegerInstance( Locale.US ).format( callsPerSecond ) );
-        }
-    }
-
-    public interface SimpleComposite
-        extends TransientComposite
-    {
-        @Optional
-        Property<String> test();
-    }
-
-    @Mixins( SimpleMixin.class )
-    public interface SimpleComposite2
-        extends SimpleComposite
-    {
-    }
-
-    public abstract static class SimpleMixin
-        implements SimpleComposite2
-    {
-        @State
-        Property<String> test;
-
-        @Override
-        public Property<String> test()
-        {
-            return test;
-        }
-    }
-
-}
diff --git a/tests/performance/src/perf/java/org/qi4j/test/performance/runtime/object/ObjectCreationPerformanceTest.java b/tests/performance/src/perf/java/org/qi4j/test/performance/runtime/object/ObjectCreationPerformanceTest.java
deleted file mode 100644
index a408160..0000000
--- a/tests/performance/src/perf/java/org/qi4j/test/performance/runtime/object/ObjectCreationPerformanceTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.test.performance.runtime.object;
-
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.object.ObjectFactory;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-/**
- * Tests performance of new object creation.
- */
-public class ObjectCreationPerformanceTest
-{
-
-    @Test
-    public void newInstanceForRegisteredObjectPerformance()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.objects( AnyObject.class );
-            }
-        };
-        ObjectFactory objectFactory = assembler.module();
-        for( int i = 0; i < 10; i++ )
-        {
-            testPerformance( objectFactory );
-        }
-    }
-
-    private void testPerformance( ObjectFactory objectFactory )
-    {
-        long start = System.currentTimeMillis();
-        int iter = 1000000;
-        for( int i = 0; i < iter; i++ )
-        {
-            objectFactory.newObject( AnyObject.class );
-        }
-
-        long end = System.currentTimeMillis();
-        System.out.println( end - start );
-    }
-
-    public static final class AnyObject
-    {
-    }
-
-}
diff --git a/tests/performance/src/perf/java/org/qi4j/test/performance/runtime/service/ServiceInvocationPerformanceTest.java b/tests/performance/src/perf/java/org/qi4j/test/performance/runtime/service/ServiceInvocationPerformanceTest.java
deleted file mode 100644
index 22af051..0000000
--- a/tests/performance/src/perf/java/org/qi4j/test/performance/runtime/service/ServiceInvocationPerformanceTest.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
- *
- * Licensed  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.qi4j.test.performance.runtime.service;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.text.NumberFormat;
-import junit.framework.TestCase;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-public class ServiceInvocationPerformanceTest
-    extends TestCase
-{
-    @Service
-    ServiceInvocationPerformanceTest.MyService service;
-
-    public void testInjectService()
-        throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.services( ServiceInvocationPerformanceTest.MyServiceComposite.class );
-                module.objects( ServiceInvocationPerformanceTest.class );
-            }
-        };
-
-        assembly.module().injectTo( this );
-
-        // Warmup
-        for( int i = 0; i < 60000; i++ )
-        {
-            service.test();
-        }
-
-        int rounds = 5;
-        for( int i = 0; i < rounds; i++ )
-        {
-            performanceCheck( service );
-        }
-    }
-
-    private void performanceCheck( MyService simple )
-    {
-        long count = 10000000L;
-
-        long start = System.currentTimeMillis();
-        for( long i = 0; i < count; i++ )
-        {
-            simple.test();
-        }
-        long end = System.currentTimeMillis();
-        long time = end - start;
-        long callsPerSecond = ( count / time ) * 1000;
-        System.out.println( "Calls per second: " + NumberFormat.getIntegerInstance().format( callsPerSecond ) );
-    }
-
-    @Mixins( NoopMixin.class )
-    public static interface MyServiceComposite
-        extends ServiceInvocationPerformanceTest.MyService, ServiceComposite
-    {
-    }
-
-    public static interface MyService
-    {
-        void test();
-    }
-
-    public static class MyServiceMixin
-        implements ServiceInvocationPerformanceTest.MyService
-    {
-        @Override
-        public void test()
-        {
-        }
-    }
-
-    public final static class NoopMixin
-        implements InvocationHandler
-    {
-        @Override
-        public Object invoke( Object object, Method method, Object[] objects )
-            throws Throwable
-        {
-            return null;
-        }
-    }
-
-}
diff --git a/tests/performance/src/perf/resources/derby-datasource.properties b/tests/performance/src/perf/resources/derby-datasource.properties
index 8fc9229..35261ab 100644
--- a/tests/performance/src/perf/resources/derby-datasource.properties
+++ b/tests/performance/src/perf/resources/derby-datasource.properties
@@ -1,17 +1,22 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 enabled=true
 url=jdbc:derby:memory:testdb;create=true
diff --git a/tests/performance/src/perf/resources/logback.xml b/tests/performance/src/perf/resources/logback.xml
index 46ad47d..6b2e88b 100644
--- a/tests/performance/src/perf/resources/logback.xml
+++ b/tests/performance/src/perf/resources/logback.xml
@@ -1,20 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
 <configuration>
 
     <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
diff --git a/tests/performance/src/perf/resources/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreService.properties b/tests/performance/src/perf/resources/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreService.properties
new file mode 100644
index 0000000..8527b21
--- /dev/null
+++ b/tests/performance/src/perf/resources/org/apache/polygene/entitystore/jdbm/JdbmEntityStoreService.properties
@@ -0,0 +1,25 @@
+#
+#  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.
+#
+#
+#
+
+
+# The file that will contain the JDBM data.
+file=build/tmp/jdbm/jdbmstore.data
+
+disableTransactions=false
diff --git a/tests/performance/src/perf/resources/org/apache/polygene/library/rdf/repository/rdf-indexing.properties b/tests/performance/src/perf/resources/org/apache/polygene/library/rdf/repository/rdf-indexing.properties
new file mode 100644
index 0000000..2cb86eb
--- /dev/null
+++ b/tests/performance/src/perf/resources/org/apache/polygene/library/rdf/repository/rdf-indexing.properties
@@ -0,0 +1,22 @@
+#
+#  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.
+#
+#
+#
+
+tripleIndexes=spoc,ospc
+dataDirectory=build/tmp/rdf
\ No newline at end of file
diff --git a/tests/performance/src/perf/resources/org/qi4j/entitystore/jdbm/JdbmEntityStoreService.properties b/tests/performance/src/perf/resources/org/qi4j/entitystore/jdbm/JdbmEntityStoreService.properties
deleted file mode 100644
index 56592c6..0000000
--- a/tests/performance/src/perf/resources/org/qi4j/entitystore/jdbm/JdbmEntityStoreService.properties
+++ /dev/null
@@ -1,20 +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.
-
-
-# The file that will contain the JDBM data.
-file=build/tmp/jdbm/jdbmstore.data
-
-disableTransactions=false
diff --git a/tests/performance/src/perf/resources/org/qi4j/library/rdf/repository/rdf-indexing.properties b/tests/performance/src/perf/resources/org/qi4j/library/rdf/repository/rdf-indexing.properties
deleted file mode 100644
index 4685ef4..0000000
--- a/tests/performance/src/perf/resources/org/qi4j/library/rdf/repository/rdf-indexing.properties
+++ /dev/null
@@ -1,17 +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.
-
-tripleIndexes=spoc,ospc
-dataDirectory=build/tmp/rdf
\ No newline at end of file
diff --git a/tests/performance/src/perf/resources/postgresql-datasource.properties b/tests/performance/src/perf/resources/postgresql-datasource.properties
index f7d7ad5..ea16c45 100644
--- a/tests/performance/src/perf/resources/postgresql-datasource.properties
+++ b/tests/performance/src/perf/resources/postgresql-datasource.properties
@@ -1,17 +1,22 @@
-# 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.
+#
+#  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.
+#
+#
+#
 
 enabled=true
 url=jdbc:postgresql://localhost:5432/jdbc_test_db
diff --git a/tests/regression/README-for-regression-reporting.txt b/tests/regression/README-for-regression-reporting.txt
index 5a8cb40..872a2ed 100644
--- a/tests/regression/README-for-regression-reporting.txt
+++ b/tests/regression/README-for-regression-reporting.txt
@@ -3,14 +3,14 @@
 
 1. Go to http://ops4j1.jira.com/browse/QI and create a new JIRA issue about the problem.
 
-2. Create a package named org.qi4j.tests.regression.qi123 (for QI-123) in $QI4J/tests/regression/src/main/java.
+2. Create a package named org.apache.polygene.tests.regression.qi123 (for QI-123) in $POLYGENE/tests/regression/src/main/java.
    NOTE: observe that the test MUST sit in the src/MAIN/java and not under src/test
 
 3. Create a JUnit or TestNG test capturing the issue described in JIRA.
 
 4. Commit and push this to the 'origin develop' branch.
 
-5. Ping the community on the qi4j-dev forum at Google Groups.
+5. Ping the community on the dev@polygene.apache.org mailing list.
 
 
 Once the reported problem has been solved, the test will be moved to the sub-project's unit test area.
diff --git a/tests/regression/build.gradle b/tests/regression/build.gradle
index 73bb428..d7d06e5 100644
--- a/tests/regression/build.gradle
+++ b/tests/regression/build.gradle
@@ -1,38 +1,36 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Apache Zest™ Regression Tests are added by community members who find bugs and typically reported via Jira issues. These tests are not run as part of the normal build, but is accessible from './gradlew regression' to allow builds to still work."
+apply plugin: 'polygene-test'
 
-jar { manifest { name = "Apache Zest™ Tests - Regression" }}
+description = "Apache Polygene™ Regression Tests are added by community members who find bugs and typically reported via Jira issues. These tests are not run as part of the normal build, but is accessible from './gradlew regression' to allow builds to still work."
+
+jar { manifest { name = "Apache Polygene™ Tests - Regression" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.api"))
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile(libraries.slf4j_api)
-  compile(libraries.junit)
-  runtime(libraries.asm)
-  runtime(libraries.asm_commons)
-  runtime(libraries.slf4j_simple)
-  compile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-  compile(project(":org.qi4j.libraries:org.qi4j.library.logging"))
-  compile(project(":org.qi4j.extensions:org.qi4j.extension.indexing-rdf"))
-  compile(project(":org.qi4j.extensions:org.qi4j.extension.entitystore-jdbm"))
-  runtime(project(":org.qi4j.core:org.qi4j.core.spi"))
-  runtime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-}
\ No newline at end of file
+  implementation polygene.core.testsupport
+  implementation polygene.library( 'logging' )
+  implementation polygene.extension( 'entitystore-jdbm' )
+  implementation libraries.slf4j_api
+  implementation libraries.junit
+
+  runtimeOnly polygene.core.runtime
+  runtimeOnly libraries.logback
+}
diff --git a/tests/regression/src/main/java/org/apache/polygene/test/regression/ConcernsOnPropertyTest.java b/tests/regression/src/main/java/org/apache/polygene/test/regression/ConcernsOnPropertyTest.java
new file mode 100644
index 0000000..7ecdfd5
--- /dev/null
+++ b/tests/regression/src/main/java/org/apache/polygene/test/regression/ConcernsOnPropertyTest.java
@@ -0,0 +1,115 @@
+/*
+ *  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.polygene.test.regression;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.sideeffect.SideEffectOf;
+import org.apache.polygene.api.sideeffect.SideEffects;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+
+public class ConcernsOnPropertyTest
+    extends AbstractPolygeneTest
+{
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( CarComposite.class );
+    }
+
+    @Test
+    public void whenConcernOnPropertyThenConcernIsInvoked()
+    {
+        TransientBuilder<Car> builder = transientBuilderFactory.newTransientBuilder( Car.class );
+        Car prototype = builder.prototypeFor( Car.class );
+        prototype.manufacturer().set( "Volvo" );
+        Car car = builder.newInstance();
+        Assert.assertEquals( "Concern on Property methods.", "Simon says: Volvo", car.manufacturer().get() );
+    }
+
+    public interface CarComposite
+        extends Car, TransientComposite
+    {
+    }
+
+    public interface Car
+    {
+        Manufacturer manufacturer();
+    }
+
+    @SideEffects( SystemOutSideEffect.class )
+    @Concerns( SimonSays.class )
+    public interface Manufacturer
+        extends Property<String>
+    {
+    }
+
+    public class SimonSays
+        extends ConcernOf<InvocationHandler>
+        implements InvocationHandler
+    {
+
+        public Object invoke( Object o, Method method, Object[] objects )
+            throws Throwable
+        {
+            Object result = next.invoke( o, method, objects );
+            if( result instanceof String )
+            {
+                return "Simon says: " + result;
+            }
+            return result;
+        }
+    }
+
+    public class SystemOutSideEffect
+        extends SideEffectOf<InvocationHandler>
+        implements InvocationHandler
+    {
+
+        public Object invoke( Object o, Method method, Object[] objects )
+            throws Throwable
+        {
+            try
+            {
+                Object result = this.result.invoke( o, method, objects );
+                if( result instanceof String )
+                {
+                    System.out.println( "[INFO] " + result );
+                }
+                return result;
+            }
+            catch( Exception e )
+            {
+                e.printStackTrace( System.out );
+                throw e;
+            }
+        }
+    }
+}
diff --git a/tests/regression/src/main/java/org/qi4j/test/regression/Regressions.java b/tests/regression/src/main/java/org/qi4j/test/regression/Regressions.java
deleted file mode 100644
index 021f813..0000000
--- a/tests/regression/src/main/java/org/qi4j/test/regression/Regressions.java
+++ /dev/null
@@ -1,29 +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.qi4j.test.regression;
-
-/**
- * Placeholder class to prevent the build to fail when no source code.
- */
-public final class Regressions
-{
-    private Regressions()
-    {
-    }
-}
diff --git a/tests/regression/src/main/java/org/qi4j/tests/regression/niclas2/ConcernsOnPropertyTest.java b/tests/regression/src/main/java/org/qi4j/tests/regression/niclas2/ConcernsOnPropertyTest.java
deleted file mode 100644
index d4f3c04..0000000
--- a/tests/regression/src/main/java/org/qi4j/tests/regression/niclas2/ConcernsOnPropertyTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tests.regression.niclas2;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.junit.Assert;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.sideeffect.SideEffectOf;
-import org.qi4j.api.sideeffect.SideEffects;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-
-public class ConcernsOnPropertyTest
-    extends AbstractQi4jTest
-{
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( CarComposite.class );
-    }
-
-
-    @Test
-    public void whenConcernOnPropertyThenConcernIsInvoked()
-    {
-        TransientBuilder<Car> builder = module.newTransientBuilder( Car.class );
-        Car prototype = builder.prototypeFor( Car.class );
-        prototype.manufacturer().set( "Volvo" );
-        Car car = builder.newInstance();
-        Assert.assertEquals( "Concern on Property methods.", "Simon says: Volvo", car.manufacturer().get() );
-    }
-
-    public interface CarComposite
-        extends Car, TransientComposite
-    {
-    }
-
-    public interface Car
-    {
-        Manufacturer manufacturer();
-    }
-
-    @SideEffects( SystemOutSideEffect.class )
-    @Concerns( SimonSays.class )
-    public interface Manufacturer
-        extends Property<String>
-    {
-    }
-
-    public class SimonSays
-        extends ConcernOf<InvocationHandler>
-        implements InvocationHandler
-    {
-
-        public Object invoke( Object o, Method method, Object[] objects )
-            throws Throwable
-        {
-            Object result = next.invoke( o, method, objects );
-            if( result instanceof String )
-            {
-                return "Simon says: " + result;
-            }
-            return result;
-        }
-    }
-
-    public class SystemOutSideEffect
-        extends SideEffectOf<InvocationHandler>
-        implements InvocationHandler
-    {
-
-        public Object invoke( Object o, Method method, Object[] objects )
-            throws Throwable
-        {
-            try
-            {
-                Object result = this.result.invoke( o, method, objects );
-                if( result instanceof String )
-                {
-                    System.out.println( "[INFO] " + result );
-                }
-                return result;
-            }
-            catch( Exception e )
-            {
-                e.printStackTrace( System.out );
-                throw e;
-            }
-        }
-    }
-}
diff --git a/tests/unit/README.txt b/tests/unit/README.txt
deleted file mode 100644
index f3e97da..0000000
--- a/tests/unit/README.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-
-You will not find Unit Tests here.
-
-By the nature of unit tests, they are located near the actual code
-under src/test/java in each code source tree.
-
-
diff --git a/tools/envisage/build.gradle b/tools/envisage/build.gradle
index 65cca01..c73dbb3 100644
--- a/tools/envisage/build.gradle
+++ b/tools/envisage/build.gradle
@@ -1,48 +1,56 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
+import org.apache.polygene.gradle.TaskGroups
 
-description = "Visualizer of a Apache Zest™ Application Structure."
+apply plugin: 'polygene-tool'
 
-jar { manifest { name = "Apache Zest™ Envisage" }}
+description = "Visualizer of a Apache Polygene™ Application Structure."
+
+jar { manifest { name = "Apache Polygene™ Envisage" } }
 
 dependencies {
+  api polygene.core.bootstrap
 
-  compile project( ":org.qi4j.core:org.qi4j.core.bootstrap" )
-  compile project( ":org.qi4j.tools:org.qi4j.tool.model-detail" )
-  compile libraries.jgoodies_looks
-  compile libraries.pdfbox
-  compile libraries.prefuse
+  implementation polygene.tool( 'model-detail' )
+  implementation libraries.jgoodies_looks
+  implementation libraries.pdfbox
+  implementation libraries.prefuse
 
-  testCompile project( ":org.qi4j.core:org.qi4j.core.testsupport" )
-  testCompile project( ":org.qi4j.extensions:org.qi4j.extension.indexing-rdf" )
+  runtimeOnly polygene.core.runtime
 
-  testRuntime project( ":org.qi4j.core:org.qi4j.core.runtime" )
-  testRuntime libraries.logback
+  testImplementation polygene.core.testsupport
+  testImplementation polygene.extension( 'indexing-rdf' )
 
+  testRuntimeOnly libraries.logback
 }
 
-task(runSample, dependsOn: 'testClasses', type: JavaExec) {
-    main = 'org.qi4j.envisage.sample.EnvisageSample'
-    classpath = sourceSets.test.runtimeClasspath
+task( runEnvisageSample, dependsOn: 'testClasses', type: JavaExec ) {
+  group = TaskGroups.SAMPLES
+  description = "Runs $project.name sample."
+  main = 'org.apache.polygene.envisage.sample.EnvisageSample'
+  classpath = sourceSets.test.runtimeClasspath
 }
 
-task(runSchool, dependsOn: 'testClasses', type: JavaExec) {
-    main = 'org.qi4j.envisage.school.EnvisageSchoolSample'
-    classpath = sourceSets.test.runtimeClasspath
+task( runEnvisageSchoolSample, dependsOn: 'testClasses', type: JavaExec ) {
+  group = TaskGroups.SAMPLES
+  description = "Runs $project.name School sample."
+  main = 'org.apache.polygene.envisage.school.EnvisageSchoolSample'
+  classpath = sourceSets.test.runtimeClasspath
 }
diff --git a/tools/envisage/dev-status.xml b/tools/envisage/dev-status.xml
index 4458bbb..e124151 100644
--- a/tools/envisage/dev-status.xml
+++ b/tools/envisage/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/tools/envisage/src/docs/envisage.txt b/tools/envisage/src/docs/envisage.txt
deleted file mode 100644
index 01551c0..0000000
--- a/tools/envisage/src/docs/envisage.txt
+++ /dev/null
@@ -1,55 +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.
-///////////////////////////////////////////////////////////////
-
-[[tools-envisage,Envisage Tool]]
-= Envisage =
-
-Envisage is a Swing based visualization tool for the Zest™ Application model.
-Visualizations can be printed to PDFs.
-
-== Usage ==
-
-Envisage can be easily used directly and prior your Application activation:
-
-[snippet,java]
-----
-source=tools/envisage/src/test/java/org/qi4j/envisage/school/EnvisageSchoolSample.java
-tag=envisage
-----
-
-As you can see, Envisage operates on the ApplicationModel, this means that you
-can easily embedd it in your own Applications too.
-
-Two gradle tasks runSample and runSchool are defined in this module as a
-shortcut to run the examples. See <<build-system>>.
-
-== Screenshots ==
-
-image:tools-envisage-structure.png[width="800px"]
-
-image:tools-envisage-type.png[width="800px"]
-
-image:tools-envisage-stacked.png[width="800px"]
-
-image:tools-envisage-stacked-collapsed.png[width="800px"]
-
-== Embedd in your Application ==
-
-include::../../build/docs/buildinfo/artifact.txt[]
-
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/Envisage.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/Envisage.java
new file mode 100644
index 0000000..c61e9c1
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/Envisage.java
@@ -0,0 +1,135 @@
+/*
+ *  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.polygene.envisage;
+
+import com.jgoodies.looks.LookUtils;
+import com.jgoodies.looks.Options;
+import com.jgoodies.looks.plastic.PlasticLookAndFeel;
+import com.jgoodies.looks.plastic.theme.ExperienceBlue;
+import java.awt.Dimension;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import javax.swing.JFrame;
+import javax.swing.LookAndFeel;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+
+/**
+ * Apache Polygene Application Viewer
+ */
+public class Envisage
+{
+
+    protected ApplicationDescriptor application;
+
+    private EnvisageFrame mainFrame;
+
+    public void run( ApplicationDescriptor application )
+    {
+        initLookAndFeel();
+
+        this.application = application;
+
+        SwingUtilities.invokeLater( this::showMainFrame );
+    }
+
+    public void stop()
+    {
+        if( mainFrame != null && mainFrame.isDisplayable() )
+        {
+            mainFrame.dispose();
+            mainFrame = null;
+        }
+    }
+
+    private void showMainFrame()
+    {
+        mainFrame = new EnvisageFrame( application );
+        mainFrame.setLocationByPlatform( true );
+        mainFrame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
+        mainFrame.setSize( new Dimension( 1024, 768 ) );
+        mainFrame.setVisible( true );
+
+        mainFrame.addWindowListener( new WindowAdapter()
+        {
+            @Override
+            public void windowOpened( WindowEvent evt )
+            {
+                SwingUtilities.invokeLater( () -> mainFrame.initPolygene() );
+            }
+        } );
+    }
+
+    private void initLookAndFeel()
+    {
+        String osName = System.getProperty( "os.name" ).toUpperCase();
+
+        // set to use swing anti alias text only for JVM <= 1.5
+        System.setProperty( "swing.aatext", "true" );
+
+        // set default swing bold to false, only for JVM 1.5 or above
+        UIManager.put( "swing.boldMetal", Boolean.FALSE );
+
+        // set LaF
+        LookAndFeel lnf = UIManager.getLookAndFeel();
+        if( lnf != null && lnf.getID().equalsIgnoreCase( "Metal" ) )
+        {
+            final String lnfClassName;
+            if( osName.startsWith( "MAC" ) )
+            {
+                System.setProperty( "com.apple.mrj.application.apple.menu.about.name", "Envisage" ); //TODO i18n
+                System.setProperty( "apple.laf.useScreenMenuBar", "true" );
+                lnfClassName = UIManager.getSystemLookAndFeelClassName();
+            }
+            else if( osName.startsWith( "WINDOWS" ) )
+            {
+                UIManager.put( "ClassLoader", LookUtils.class.getClassLoader() );
+                lnfClassName = Options.getSystemLookAndFeelClassName();
+                Options.setUseNarrowButtons( false );
+            }
+            else
+            {
+                UIManager.put( "ClassLoader", LookUtils.class.getClassLoader() );
+                lnfClassName = Options.getCrossPlatformLookAndFeelClassName();
+                PlasticLookAndFeel.setTabStyle( PlasticLookAndFeel.TAB_STYLE_METAL_VALUE );
+                PlasticLookAndFeel.setPlasticTheme( new ExperienceBlue() );
+                Options.setUseNarrowButtons( false );
+                //PlasticLookAndFeel.setMyCurrentTheme(new ExperienceBlueDefaultFont());  // for CJK Font
+            }
+
+            if( lnfClassName != null )
+            {
+                try
+                {
+                    UIManager.setLookAndFeel( lnfClassName );
+                }
+                catch( ClassNotFoundException | IllegalAccessException | InstantiationException |
+                       UnsupportedLookAndFeelException ex )
+                {
+                    System.err.println( "Unable to set LookAndFeel, use default LookAndFeel.\n" + ex.getMessage() );
+                }
+            }
+        }
+    }
+
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/EnvisageFrame.form b/tools/envisage/src/main/java/org/apache/polygene/envisage/EnvisageFrame.form
new file mode 100644
index 0000000..77792aa
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/EnvisageFrame.form
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.apache.polygene.envisage.EnvisageFrame">
+  <grid id="27dc6" binding="contentPane" layout-manager="BorderLayout" hgap="0" vgap="0">
+    <constraints>
+      <xy x="20" y="20" width="500" height="400"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children/>
+  </grid>
+</form>
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/EnvisageFrame.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/EnvisageFrame.java
new file mode 100644
index 0000000..6a120c0
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/EnvisageFrame.java
@@ -0,0 +1,248 @@
+/*
+ *  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.polygene.envisage;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.util.ResourceBundle;
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JSplitPane;
+import javax.swing.KeyStroke;
+import javax.swing.SwingUtilities;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.envisage.detail.DetailModelPane;
+import org.apache.polygene.envisage.event.LinkEvent;
+import org.apache.polygene.envisage.event.LinkListener;
+import org.apache.polygene.envisage.graph.GraphPane;
+import org.apache.polygene.envisage.print.PDFWriter;
+import org.apache.polygene.envisage.tree.TreeModelPane;
+import org.apache.polygene.tools.model.descriptor.ApplicationDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ApplicationDetailDescriptorBuilder;
+
+/**
+ * Envisage Main Frame
+ */
+public final class EnvisageFrame
+    extends JFrame
+{
+    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( EnvisageFrame.class.getName() );
+
+    private JPanel contentPane;
+    private final JSplitPane graphSplitPane;
+    private final JSplitPane modelSplitPane;
+
+    private final GraphPane graphPane;
+    private final TreeModelPane treeModelPane;
+    private final DetailModelPane detailModelPane;
+
+    private final ApplicationDescriptor application;
+    private ApplicationDetailDescriptor descriptor;
+
+    private boolean graphItemSelectionInProgress;
+
+    public EnvisageFrame( ApplicationDescriptor application )
+    {
+        this.application = application;
+
+        setTitle( BUNDLE.getString( "Application.Title" ) );
+        setContentPane( contentPane );
+
+        graphPane = new GraphPane();
+        treeModelPane = new TreeModelPane();
+        detailModelPane = new DetailModelPane();
+
+        treeModelPane.addTreeSelectionListener( new TreeSelectionListener()
+        {
+            @Override
+            public void valueChanged( TreeSelectionEvent evt )
+            {
+                applicationModelPaneValueChanged();
+            }
+        } );
+
+        graphPane.addLinkListener( new LinkListener()
+        {
+            @Override
+            public void activated( LinkEvent evt )
+            {
+                graphItemLinkActivated( evt );
+            }
+        } );
+
+        detailModelPane.addLinkListener( new LinkListener()
+        {
+            @Override
+            public void activated( LinkEvent evt )
+            {
+                detailModelPaneLinkActivated( evt );
+            }
+        } );
+
+        modelSplitPane = new JSplitPane();
+        modelSplitPane.setOrientation( JSplitPane.HORIZONTAL_SPLIT );
+        modelSplitPane.setDividerLocation( 300 );
+        modelSplitPane.setOneTouchExpandable( true );
+        modelSplitPane.setLeftComponent( treeModelPane );
+        modelSplitPane.setRightComponent( detailModelPane );
+
+        graphSplitPane = new JSplitPane();
+        graphSplitPane.setOrientation( JSplitPane.VERTICAL_SPLIT );
+        graphSplitPane.setDividerLocation( 384 ); // 768/2
+        graphSplitPane.setOneTouchExpandable( true );
+        //graphSplitPane.setTopComponent( graphPane );
+        //graphSplitPane.setBottomComponent( modelSplitPane );
+        graphSplitPane.setTopComponent( modelSplitPane );
+        graphSplitPane.setBottomComponent( graphPane );
+
+        this.setJMenuBar( createMenu() );
+
+        contentPane.add( graphSplitPane, BorderLayout.CENTER );
+    }
+
+    public void initPolygene()
+    {
+        modelSplitPane.setDividerLocation( 300 );
+        graphSplitPane.setDividerLocation( 384 );
+
+        descriptor = ApplicationDetailDescriptorBuilder.createApplicationDetailDescriptor( application );
+        treeModelPane.initPolygene( descriptor );
+        graphPane.initPolygene( descriptor );
+    }
+
+    /**
+     * Create menubar
+     *
+     * @return JMenuBar
+     */
+    protected JMenuBar createMenu()
+    {
+        ActionListener menuActionListener = new ActionListener()
+        {
+            @Override
+            public void actionPerformed( ActionEvent evt )
+            {
+                if( evt.getActionCommand().equals( "export" ) )
+                {
+                    exportAsPDF();
+                }
+                if( evt.getActionCommand().equals( "exit" ) )
+                {
+                    System.exit( 0 );
+                }
+            }
+        };
+
+        // TODO i18n
+        JMenuBar menuBar = new JMenuBar();
+
+        JMenu menu = new JMenu( "File" );
+        menu.setMnemonic( KeyEvent.VK_F );
+        menuBar.add( menu );
+
+        JMenuItem menuItem = new JMenuItem( "Export As PDF", KeyEvent.VK_E );
+        menuItem.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_E, ActionEvent.CTRL_MASK ) );
+        menuItem.setActionCommand( "export" );
+        menuItem.addActionListener( menuActionListener );
+        menu.add( menuItem );
+
+        menuItem = new JMenuItem( "Exit", KeyEvent.VK_X );
+        menuItem.setActionCommand( "exit" );
+        menuItem.addActionListener( menuActionListener );
+        menu.add( menuItem );
+
+        return menuBar;
+    }
+
+    protected void applicationModelPaneValueChanged()
+    {
+        Object obj = treeModelPane.getLastSelected();
+        detailModelPane.setDescriptor( obj );
+        if( !graphItemSelectionInProgress )
+        {
+            graphPane.setSelectedValue( obj );
+        }
+    }
+
+    protected void graphItemLinkActivated( LinkEvent evt )
+    {
+        graphItemSelectionInProgress = true;
+        try
+        {
+            treeModelPane.setSelectedValue( evt.getObject() );
+        }
+        finally
+        {
+            graphItemSelectionInProgress = false;
+        }
+    }
+
+    protected void detailModelPaneLinkActivated( LinkEvent evt )
+    {
+        treeModelPane.setSelectedValue( evt.getObject() );
+    }
+
+    protected void exportAsPDF()
+    {
+        SwingUtilities.invokeLater( new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                PDFWriter pdf = new PDFWriter();
+                pdf.write( EnvisageFrame.this, descriptor, graphPane.getGraphDisplays() );
+            }
+        } );
+    }
+
+    
+    {
+// GUI initializer generated by IntelliJ IDEA GUI Designer
+// >>> IMPORTANT!! <<<
+// DO NOT EDIT OR ADD ANY CODE HERE!
+        $$$setupUI$$$();
+    }
+
+    /**
+     * Method generated by IntelliJ IDEA GUI Designer
+     * >>> IMPORTANT!! <<<
+     * DO NOT edit this method OR call it in your code!
+     *
+     */
+    private void $$$setupUI$$$()
+    {
+        contentPane = new JPanel();
+        contentPane.setLayout( new BorderLayout( 0, 0 ) );
+    }
+
+    public JComponent $$$getRootComponent$$$()
+    {
+        return contentPane;
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/Main.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/Main.java
new file mode 100644
index 0000000..27521ce
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/Main.java
@@ -0,0 +1,47 @@
+/*
+ *  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.polygene.envisage;
+
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+
+/**
+ * Start Envisage with a specified application assembler. Specify assembler class
+ * as first parameter.
+ */
+public class Main
+{
+    public static void main( String[] args )
+        throws ClassNotFoundException, IllegalAccessException, InstantiationException, AssemblyException
+    {
+        String applicationAssemblerName = args[0];
+        Class applicationAssemblerClass = Class.forName( applicationAssemblerName );
+        ApplicationAssembler assembler = (ApplicationAssembler) applicationAssemblerClass.newInstance();
+
+        Energy4Java energy4Java = new Energy4Java();
+
+        ApplicationDescriptor application = energy4Java.newApplicationModel( assembler );
+
+        new Envisage().run( application );
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/APIPane.form b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/APIPane.form
new file mode 100644
index 0000000..4523c45
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/APIPane.form
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.apache.polygene.envisage.detail.APIPane">
+  <grid id="27dc6" binding="contentPane" layout-manager="BorderLayout" hgap="0" vgap="0">
+    <constraints>
+      <xy x="20" y="20" width="500" height="400"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <scrollpane id="2c325">
+        <constraints border-constraint="Center"/>
+        <properties/>
+        <border type="none"/>
+        <children>
+          <component id="a2e7d" class="javax.swing.JTable" binding="apiTable">
+            <constraints/>
+            <properties>
+              <showVerticalLines value="true"/>
+            </properties>
+          </component>
+        </children>
+      </scrollpane>
+    </children>
+  </grid>
+</form>
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/APIPane.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/APIPane.java
new file mode 100644
index 0000000..73d6297
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/APIPane.java
@@ -0,0 +1,297 @@
+/*
+ *  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.polygene.envisage.detail;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ResourceBundle;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.MouseInputAdapter;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableColumnModel;
+import org.apache.polygene.envisage.event.LinkEvent;
+import org.apache.polygene.envisage.util.TableRow;
+import org.apache.polygene.tools.model.descriptor.LayerDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ModuleDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ServiceDetailDescriptor;
+import org.apache.polygene.tools.model.util.DescriptorUtilities;
+
+/**
+ * API would be defined as "All service interfaces which are visible for layer
+ * or application" and SPI would be defined as "All service dependencies which
+ * are not satisfied from within the module". And then similar for Layer. This
+ * way you can select a Module/Layer and immediately see what it produces as
+ * output and requires as input. This is also very very nice for documentation
+ * purposes.
+ */
+/* package */ final class APIPane
+    extends DetailPane
+{
+    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( APIPane.class.getName() );
+
+    private JPanel contentPane;
+    private JTable apiTable;
+    private APITableModel apiTableModel;
+
+    private Object linkObject;
+    private Cursor defaultCursor;
+    private Cursor linkCursor;
+
+    /* package */ APIPane( DetailModelPane detailModelPane )
+    {
+        super( detailModelPane );
+        this.setLayout( new BorderLayout() );
+        this.add( contentPane, BorderLayout.CENTER );
+
+        apiTableModel = new APITableModel();
+        apiTable.setModel( apiTableModel );
+        apiTable.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
+
+        TableColumnModel columnModel = apiTable.getColumnModel();
+        columnModel.getColumn( 0 ).setCellRenderer( new ServiceCellRenderer() );
+
+        defaultCursor = getCursor();
+        linkCursor = LinkEvent.LINK_CURSOR;
+
+        MouseInputAdapter mouseInputListener = new MouseInputAdapter()
+        {
+            @Override
+            public void mouseMoved( MouseEvent evt )
+            {
+                // Column 1 is the Service Column
+                int col = apiTable.columnAtPoint( evt.getPoint() );
+                if( col == 0 )
+                {
+                    setCursor( linkCursor );
+                }
+                else
+                {
+                    if( !getCursor().equals( defaultCursor ) )
+                    {
+                        setCursor( defaultCursor );
+                    }
+                }
+            }
+
+            @Override
+            public void mouseClicked( MouseEvent evt )
+            {
+                int col = apiTable.columnAtPoint( evt.getPoint() );
+                if( col != 0 )
+                {
+                    return;
+                }
+
+                int row = apiTable.rowAtPoint( evt.getPoint() );
+                if( row < 0 )
+                {
+                    return;
+                }
+
+                linkObject = apiTableModel.getValueAt( row, col );
+                linkActivated();
+                linkObject = null;
+            }
+        };
+
+        apiTable.addMouseMotionListener( mouseInputListener );
+        apiTable.addMouseListener( mouseInputListener );
+    }
+
+    @Override
+    protected void setDescriptor( Object objectDesciptor )
+    {
+        clear();
+
+        List<ServiceDetailDescriptor> list = null;
+        if( objectDesciptor instanceof LayerDetailDescriptor )
+        {
+            list = DescriptorUtilities.findLayerAPI( (LayerDetailDescriptor) objectDesciptor );
+        }
+        else if( objectDesciptor instanceof ModuleDetailDescriptor )
+        {
+            list = DescriptorUtilities.findModuleAPI( (ModuleDetailDescriptor) objectDesciptor );
+        }
+
+        if( list != null )
+        {
+            apiTableModel.addRow( list );
+        }
+    }
+
+    private void clear()
+    {
+        linkObject = null;
+        apiTableModel.clear();
+    }
+
+    private void linkActivated()
+    {
+        if( linkObject == null )
+        {
+            return;
+        }
+        LinkEvent linkEvt = new LinkEvent( this, linkObject );
+        detailModelPane.fireLinkActivated( linkEvt );
+    }
+
+    
+    {
+// GUI initializer generated by IntelliJ IDEA GUI Designer
+// >>> IMPORTANT!! <<<
+// DO NOT EDIT OR ADD ANY CODE HERE!
+        $$$setupUI$$$();
+    }
+
+    /**
+     * Method generated by IntelliJ IDEA GUI Designer
+     * >>> IMPORTANT!! <<<
+     * DO NOT edit this method OR call it in your code!
+     *
+     */
+    private void $$$setupUI$$$()
+    {
+        contentPane = new JPanel();
+        contentPane.setLayout( new BorderLayout( 0, 0 ) );
+        final JScrollPane scrollPane1 = new JScrollPane();
+        contentPane.add( scrollPane1, BorderLayout.CENTER );
+        apiTable = new JTable();
+        apiTable.setShowVerticalLines( true );
+        scrollPane1.setViewportView( apiTable );
+    }
+
+    public JComponent $$$getRootComponent$$$()
+    {
+        return contentPane;
+    }
+
+    private static class APITableModel
+        extends AbstractTableModel
+    {
+        /**
+         * the column names for this model
+         */
+        private static final String[] COLUMN_NAMES =
+        {
+            BUNDLE.getString( "Service.Column" ),
+            BUNDLE.getString( "Module.Column" ),
+            BUNDLE.getString( "Visibility.Column" )
+        };
+        private final ArrayList<TableRow> rows;
+
+        private APITableModel()
+        {
+            rows = new ArrayList<>();
+        }
+
+        private void addRow( List<ServiceDetailDescriptor> list )
+        {
+            if( list.isEmpty() )
+            {
+                return;
+            }
+
+            int i1 = rows.size();
+            if( i1 > 0 )
+            {
+                i1--;
+            }
+
+            int i2 = 0;
+
+            for( ServiceDetailDescriptor descriptor : list )
+            {
+                TableRow row = new TableRow( COLUMN_NAMES.length );
+                row.set( 0, descriptor );
+                row.set( 1, descriptor.module() );
+                row.set( 2, descriptor.descriptor().visibility().toString() );
+                this.rows.add( row );
+                i2++;
+            }
+
+            fireTableRowsInserted( i1, i1 + i2 );
+        }
+
+        @Override
+        public Object getValueAt( int rowIndex, int columnIndex )
+        {
+            TableRow row = rows.get( rowIndex );
+            return row.get( columnIndex );
+        }
+
+        private void clear()
+        {
+            rows.clear();
+            fireTableDataChanged();
+        }
+
+        @Override
+        public int getColumnCount()
+        {
+            return COLUMN_NAMES.length;
+        }
+
+        @Override
+        public String getColumnName( int col )
+        {
+            return COLUMN_NAMES[ col];
+        }
+
+        @Override
+        public int getRowCount()
+        {
+            return rows.size();
+        }
+    }
+
+    private static class ServiceCellRenderer
+        extends DefaultTableCellRenderer
+    {
+        @Override
+        public final Component getTableCellRendererComponent( JTable table,
+                                                              Object value,
+                                                              boolean isSelected,
+                                                              boolean hasFocus,
+                                                              int row,
+                                                              int column
+        )
+        {
+            if( value != null )
+            {
+                value = "<html><a href=\"" + value.toString() + "\">" + value.toString() + "</a></html>";
+            }
+
+            super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );
+
+            return this;
+        }
+    }
+
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/DependencyPane.form b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/DependencyPane.form
new file mode 100644
index 0000000..8535ed6
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/DependencyPane.form
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.apache.polygene.envisage.detail.DependencyPane">
+  <grid id="27dc6" binding="contentPane" layout-manager="BorderLayout" hgap="0" vgap="0">
+    <constraints>
+      <xy x="20" y="20" width="598" height="415"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <splitpane id="1f500" binding="splitPane">
+        <constraints border-constraint="Center"/>
+        <properties/>
+        <border type="none"/>
+        <children>
+          <scrollpane id="1c16d">
+            <constraints>
+              <splitpane position="left"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <component id="1b715" class="javax.swing.JList" binding="fieldList">
+                <constraints/>
+                <properties/>
+              </component>
+            </children>
+          </scrollpane>
+          <grid id="84919" binding="detailPane" layout-manager="GridBagLayout">
+            <constraints>
+              <splitpane position="right"/>
+            </constraints>
+            <properties/>
+            <border type="empty">
+              <size top="8" left="8" bottom="8" right="8"/>
+            </border>
+            <children>
+              <component id="6df32" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="0.0"/>
+                </constraints>
+                <properties>
+                  <text resource-bundle="org/apache/polygene/envisage/detail/DependencyPane" key="CTL_ClassName.Text"/>
+                </properties>
+              </component>
+              <hspacer id="ef53d">
+                <constraints>
+                  <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="0.0"/>
+                </constraints>
+              </hspacer>
+              <vspacer id="74134">
+                <constraints>
+                  <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="0.0"/>
+                </constraints>
+              </vspacer>
+              <component id="5284c" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="0.0"/>
+                </constraints>
+                <properties>
+                  <text resource-bundle="org/apache/polygene/envisage/detail/DependencyPane" key="CTL_Optional.Text"/>
+                </properties>
+              </component>
+              <component id="dcc55" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="0.0"/>
+                </constraints>
+                <properties>
+                  <text resource-bundle="org/apache/polygene/envisage/detail/DependencyPane" key="CTL_Annotation.Text"/>
+                </properties>
+              </component>
+              <vspacer id="90e22">
+                <constraints>
+                  <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="0.0"/>
+                </constraints>
+              </vspacer>
+              <vspacer id="a26b7">
+                <constraints>
+                  <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="0.0"/>
+                </constraints>
+              </vspacer>
+              <vspacer id="dc18d">
+                <constraints>
+                  <grid row="9" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="0.0"/>
+                </constraints>
+              </vspacer>
+              <component id="f44fe" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="10" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="0.0"/>
+                </constraints>
+                <properties>
+                  <text resource-bundle="org/apache/polygene/envisage/detail/DependencyPane" key="CTL_InjectionType.Text"/>
+                </properties>
+              </component>
+              <component id="d289f" class="javax.swing.JLabel" binding="classNameLabel">
+                <constraints>
+                  <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="1.0" weighty="0.0"/>
+                </constraints>
+                <properties>
+                  <text value="none" noi18n="true"/>
+                </properties>
+              </component>
+              <component id="86b9a" class="javax.swing.JLabel" binding="annotationLabel">
+                <constraints>
+                  <grid row="4" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="0.0"/>
+                </constraints>
+                <properties>
+                  <text value="none" noi18n="true"/>
+                </properties>
+              </component>
+              <component id="d98ad" class="javax.swing.JLabel" binding="injectionTypeLabel">
+                <constraints>
+                  <grid row="10" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="0.0"/>
+                </constraints>
+                <properties>
+                  <text value="none" noi18n="true"/>
+                </properties>
+              </component>
+              <component id="ba440" class="javax.swing.JLabel" binding="optionalLabel">
+                <constraints>
+                  <grid row="2" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="0.0"/>
+                </constraints>
+                <properties>
+                  <text value="none" noi18n="true"/>
+                </properties>
+              </component>
+              <vspacer id="bce66">
+                <constraints>
+                  <grid row="7" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="0.0"/>
+                </constraints>
+              </vspacer>
+              <component id="43385" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="8" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="0.0"/>
+                </constraints>
+                <properties>
+                  <text resource-bundle="org/apache/polygene/envisage/detail/DependencyPane" key="CTL_Injection.Text"/>
+                </properties>
+              </component>
+              <scrollpane id="8506a">
+                <constraints>
+                  <grid row="12" column="2" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="1.0"/>
+                </constraints>
+                <properties/>
+                <border type="none"/>
+                <children>
+                  <component id="c96b8" class="javax.swing.JList" binding="injectedServiceList">
+                    <constraints/>
+                    <properties/>
+                  </component>
+                </children>
+              </scrollpane>
+              <vspacer id="3378c">
+                <constraints>
+                  <grid row="11" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="0.0"/>
+                </constraints>
+              </vspacer>
+              <component id="9cfc4" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="12" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="5" fill="0" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="0.0"/>
+                </constraints>
+                <properties>
+                  <text resource-bundle="org/apache/polygene/envisage/detail/DependencyPane" key="CTL_InjectedServices.Text"/>
+                </properties>
+              </component>
+              <component id="fb56b" class="javax.swing.JSeparator">
+                <constraints>
+                  <grid row="6" column="0" row-span="1" col-span="3" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+                  <gridbag weightx="0.0" weighty="0.0"/>
+                </constraints>
+                <properties/>
+              </component>
+            </children>
+          </grid>
+        </children>
+      </splitpane>
+    </children>
+  </grid>
+</form>
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/DependencyPane.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/DependencyPane.java
new file mode 100644
index 0000000..e93818f
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/DependencyPane.java
@@ -0,0 +1,470 @@
+/*
+ *  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.polygene.envisage.detail;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.MouseEvent;
+import java.lang.annotation.Annotation;
+import java.util.ResourceBundle;
+import javax.swing.BorderFactory;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.DefaultListModel;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSeparator;
+import javax.swing.JSplitPane;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.MouseInputAdapter;
+import org.apache.polygene.api.composite.DependencyDescriptor;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.envisage.event.LinkEvent;
+import org.apache.polygene.tools.model.descriptor.CompositeDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.InjectedFieldDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.MixinDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ObjectDetailDescriptor;
+
+/* package */ final class DependencyPane
+    extends DetailPane
+{
+    private JPanel contentPane;
+    private JSplitPane splitPane;
+    private JList fieldList;
+    private JLabel classNameLabel;
+    private JLabel optionalLabel;
+    private JLabel annotationLabel;
+    private JLabel injectionTypeLabel;
+    private JList injectedServiceList;
+    private JPanel detailPane;
+
+    private final DefaultListModel fieldListModel;
+    private DefaultListModel injectedServiceListModel;
+
+    private Cursor defaultCursor;
+    private Cursor linkCursor;
+
+    /* package */ DependencyPane( DetailModelPane detailModelPane )
+    {
+        super( detailModelPane );
+        this.setLayout( new BorderLayout() );
+        this.add( contentPane, BorderLayout.CENTER );
+
+        fieldListModel = new DefaultListModel();
+        fieldList.setModel( fieldListModel );
+        fieldList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
+        fieldList.setPrototypeCellValue( "123456789012345" );
+
+        injectedServiceListModel = new DefaultListModel();
+        injectedServiceList.setModel( injectedServiceListModel );
+        injectedServiceList.setCellRenderer( new InjectedServiceListCellRenderer() );
+        injectedServiceList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
+        injectedServiceList.setPrototypeCellValue( "123456789012345" );
+
+        Dimension minSize = new Dimension( 20, 20 );
+        detailPane.setMinimumSize( minSize );
+
+        fieldList.addListSelectionListener( this::fieldListValueChanged );
+
+        defaultCursor = getCursor();
+        linkCursor = LinkEvent.LINK_CURSOR;
+
+        MouseInputAdapter mouseInputListener = new MouseInputAdapter()
+        {
+            @Override
+            public void mouseMoved( MouseEvent evt )
+            {
+                int i = injectedServiceList.locationToIndex( evt.getPoint() );
+                if( i != -1 )
+                {
+                    setCursor( linkCursor );
+                }
+                else
+                {
+                    setCursor( defaultCursor );
+                }
+            }
+
+            @Override
+            public void mouseExited( MouseEvent evt )
+            {
+                setCursor( defaultCursor );
+            }
+
+            @Override
+            public void mouseClicked( MouseEvent evt )
+            {
+                /*if( evt.getClickCount() < 2 )
+                 {
+                 return;
+                 }*/
+
+                int i = injectedServiceList.locationToIndex( evt.getPoint() );
+                if( i != -1 )
+                {
+                    Object linkObject = injectedServiceListModel.get( i );
+                    linkActivated( linkObject );
+                }
+            }
+        };
+
+        injectedServiceList.addMouseListener( mouseInputListener );
+        injectedServiceList.addMouseMotionListener( mouseInputListener );
+    }
+
+    private void linkActivated( Object linkObject )
+    {
+        if( linkObject == null )
+        {
+            return;
+        }
+        LinkEvent linkEvt = new LinkEvent( this, linkObject );
+        detailModelPane.fireLinkActivated( linkEvt );
+    }
+
+    private void clear()
+    {
+        fieldListModel.clear();
+        clearDetail();
+    }
+
+    private void clearDetail()
+    {
+        classNameLabel.setText( null );
+        classNameLabel.setToolTipText( null );
+        optionalLabel.setText( null );
+        annotationLabel.setText( null );
+        injectionTypeLabel.setText( null );
+        injectionTypeLabel.setToolTipText( null );
+        injectedServiceListModel.clear();
+    }
+
+    @Override
+    protected void setDescriptor( Object objectDesciptor )
+    {
+        clear();
+
+        if( objectDesciptor instanceof CompositeDetailDescriptor )
+        {
+            CompositeDetailDescriptor descriptor = ( (CompositeDetailDescriptor) objectDesciptor );
+            Iterable<MixinDetailDescriptor> iter = descriptor.mixins();
+            for( MixinDetailDescriptor mixinDescriptor : iter )
+            {
+                reload( mixinDescriptor.injectedFields() );
+            }
+        }
+        else if( objectDesciptor instanceof ObjectDetailDescriptor )
+        {
+            ObjectDetailDescriptor descriptor = ( (ObjectDetailDescriptor) objectDesciptor );
+            reload( descriptor.injectedFields() );
+        }
+
+        if( !fieldListModel.isEmpty() )
+        {
+            fieldList.setSelectedIndex( 0 );
+        }
+    }
+
+    private void reload( Iterable<InjectedFieldDetailDescriptor> iter )
+    {
+        for( InjectedFieldDetailDescriptor descriptor : iter )
+        {
+            DependencyDescriptor dependencyDescriptor = descriptor.descriptor().dependency();
+            Annotation annotation = dependencyDescriptor.injectionAnnotation();
+
+            if( isDependencyField( annotation.annotationType() ) )
+            {
+                fieldListModel.addElement( descriptor );
+            }
+        }
+    }
+
+    private void reloadDetail( InjectedFieldDetailDescriptor descriptor )
+    {
+        clearDetail();
+        if( descriptor == null )
+        {
+            return;
+        }
+
+        DependencyDescriptor dependencyDescriptor = descriptor.descriptor().dependency();
+
+        classNameLabel.setText( dependencyDescriptor.injectedClass().getSimpleName() );
+        classNameLabel.setToolTipText( dependencyDescriptor.injectedClass().getName() );
+        annotationLabel.setText( "@" + dependencyDescriptor.injectionAnnotation().annotationType().getSimpleName() );
+        optionalLabel.setText( Boolean.toString( dependencyDescriptor.optional() ) );
+        injectionTypeLabel.setText( Classes.simpleGenericNameOf( dependencyDescriptor.injectionType() ) );
+        injectionTypeLabel.setToolTipText( dependencyDescriptor.injectionType().toString() );
+    }
+
+    /**
+     * Check whether the type is a dependency field (Service and Use only)
+     *
+     * @param clazz the type
+     *
+     * @return true or false
+     */
+    private boolean isDependencyField( Class<? extends Annotation> clazz )
+    {
+        return Uses.class.equals( clazz ) || Service.class.equals( clazz );
+    }
+
+    private void fieldListValueChanged( ListSelectionEvent evt )
+    {
+        if( evt.getValueIsAdjusting() )
+        {
+            return;
+        }
+
+        reloadDetail( (InjectedFieldDetailDescriptor) fieldList.getSelectedValue() );
+    }
+
+    
+    {
+// GUI initializer generated by IntelliJ IDEA GUI Designer
+// >>> IMPORTANT!! <<<
+// DO NOT EDIT OR ADD ANY CODE HERE!
+        $$$setupUI$$$();
+    }
+
+    /**
+     * Method generated by IntelliJ IDEA GUI Designer
+     * >>> IMPORTANT!! <<<
+     * DO NOT edit this method OR call it in your code!
+     *
+     */
+    private void $$$setupUI$$$()
+    {
+        contentPane = new JPanel();
+        contentPane.setLayout( new BorderLayout( 0, 0 ) );
+        splitPane = new JSplitPane();
+        contentPane.add( splitPane, BorderLayout.CENTER );
+        final JScrollPane scrollPane1 = new JScrollPane();
+        splitPane.setLeftComponent( scrollPane1 );
+        fieldList = new JList();
+        scrollPane1.setViewportView( fieldList );
+        detailPane = new JPanel();
+        detailPane.setLayout( new GridBagLayout() );
+        splitPane.setRightComponent( detailPane );
+        detailPane.setBorder( BorderFactory.createTitledBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ), null ) );
+        final JLabel label1 = new JLabel();
+        this.$$$loadLabelText$$$( label1, ResourceBundle.getBundle( "org/apache/polygene/envisage/detail/DependencyPane" ).getString( "CTL_ClassName.Text" ) );
+        GridBagConstraints gbc;
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.anchor = GridBagConstraints.EAST;
+        detailPane.add( label1, gbc );
+        final JPanel spacer1 = new JPanel();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 1;
+        gbc.gridy = 0;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        detailPane.add( spacer1, gbc );
+        final JPanel spacer2 = new JPanel();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 1;
+        gbc.fill = GridBagConstraints.VERTICAL;
+        detailPane.add( spacer2, gbc );
+        final JLabel label2 = new JLabel();
+        this.$$$loadLabelText$$$( label2, ResourceBundle.getBundle( "org/apache/polygene/envisage/detail/DependencyPane" ).getString( "CTL_Optional.Text" ) );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 2;
+        gbc.anchor = GridBagConstraints.EAST;
+        detailPane.add( label2, gbc );
+        final JLabel label3 = new JLabel();
+        this.$$$loadLabelText$$$( label3, ResourceBundle.getBundle( "org/apache/polygene/envisage/detail/DependencyPane" ).getString( "CTL_Annotation.Text" ) );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 4;
+        gbc.anchor = GridBagConstraints.EAST;
+        detailPane.add( label3, gbc );
+        final JPanel spacer3 = new JPanel();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 3;
+        gbc.fill = GridBagConstraints.VERTICAL;
+        detailPane.add( spacer3, gbc );
+        final JPanel spacer4 = new JPanel();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 5;
+        gbc.fill = GridBagConstraints.VERTICAL;
+        detailPane.add( spacer4, gbc );
+        final JPanel spacer5 = new JPanel();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 9;
+        gbc.fill = GridBagConstraints.VERTICAL;
+        detailPane.add( spacer5, gbc );
+        final JLabel label4 = new JLabel();
+        this.$$$loadLabelText$$$( label4, ResourceBundle.getBundle( "org/apache/polygene/envisage/detail/DependencyPane" ).getString( "CTL_InjectionType.Text" ) );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 10;
+        gbc.anchor = GridBagConstraints.EAST;
+        detailPane.add( label4, gbc );
+        classNameLabel = new JLabel();
+        classNameLabel.setText( "none" );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 2;
+        gbc.gridy = 0;
+        gbc.weightx = 1.0;
+        gbc.anchor = GridBagConstraints.WEST;
+        detailPane.add( classNameLabel, gbc );
+        annotationLabel = new JLabel();
+        annotationLabel.setText( "none" );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 2;
+        gbc.gridy = 4;
+        gbc.anchor = GridBagConstraints.WEST;
+        detailPane.add( annotationLabel, gbc );
+        injectionTypeLabel = new JLabel();
+        injectionTypeLabel.setText( "none" );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 2;
+        gbc.gridy = 10;
+        gbc.anchor = GridBagConstraints.WEST;
+        detailPane.add( injectionTypeLabel, gbc );
+        optionalLabel = new JLabel();
+        optionalLabel.setText( "none" );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 2;
+        gbc.gridy = 2;
+        gbc.anchor = GridBagConstraints.WEST;
+        detailPane.add( optionalLabel, gbc );
+        final JPanel spacer6 = new JPanel();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 7;
+        gbc.fill = GridBagConstraints.VERTICAL;
+        detailPane.add( spacer6, gbc );
+        final JLabel label5 = new JLabel();
+        this.$$$loadLabelText$$$( label5, ResourceBundle.getBundle( "org/apache/polygene/envisage/detail/DependencyPane" ).getString( "CTL_Injection.Text" ) );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 8;
+        gbc.anchor = GridBagConstraints.WEST;
+        detailPane.add( label5, gbc );
+        final JScrollPane scrollPane2 = new JScrollPane();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 2;
+        gbc.gridy = 12;
+        gbc.weighty = 1.0;
+        gbc.fill = GridBagConstraints.BOTH;
+        detailPane.add( scrollPane2, gbc );
+        injectedServiceList = new JList();
+        scrollPane2.setViewportView( injectedServiceList );
+        final JPanel spacer7 = new JPanel();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 11;
+        gbc.fill = GridBagConstraints.VERTICAL;
+        detailPane.add( spacer7, gbc );
+        final JLabel label6 = new JLabel();
+        this.$$$loadLabelText$$$( label6, ResourceBundle.getBundle( "org/apache/polygene/envisage/detail/DependencyPane" ).getString( "CTL_InjectedServices.Text" ) );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 12;
+        gbc.anchor = GridBagConstraints.NORTHEAST;
+        detailPane.add( label6, gbc );
+        final JSeparator separator1 = new JSeparator();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 6;
+        gbc.gridwidth = 3;
+        gbc.fill = GridBagConstraints.BOTH;
+        detailPane.add( separator1, gbc );
+    }
+
+    private void $$$loadLabelText$$$( JLabel component, String text )
+    {
+        StringBuffer result = new StringBuffer();
+        boolean haveMnemonic = false;
+        char mnemonic = '\0';
+        int mnemonicIndex = -1;
+        for( int i = 0; i < text.length(); i++ )
+        {
+            if( text.charAt( i ) == '&' )
+            {
+                i++;
+                if( i == text.length() )
+                {
+                    break;
+                }
+                if( !haveMnemonic && text.charAt( i ) != '&' )
+                {
+                    haveMnemonic = true;
+                    mnemonic = text.charAt( i );
+                    mnemonicIndex = result.length();
+                }
+            }
+            result.append( text.charAt( i ) );
+        }
+        component.setText( result.toString() );
+        if( haveMnemonic )
+        {
+            component.setDisplayedMnemonic( mnemonic );
+            component.setDisplayedMnemonicIndex( mnemonicIndex );
+        }
+    }
+
+    public JComponent $$$getRootComponent$$$()
+    {
+        return contentPane;
+    }
+
+    private static class InjectedServiceListCellRenderer
+        extends DefaultListCellRenderer
+    {
+        @Override
+        public Component getListCellRendererComponent( JList list,
+                                                       Object value,
+                                                       int index,
+                                                       boolean isSelected,
+                                                       boolean cellHasFocus
+        )
+        {
+            if( value != null )
+            {
+                String id = (String) value;
+                value = "<html><a href=\"" + id + "\">" + id + "</a></html>";
+            }
+
+            super.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
+
+            return this;
+        }
+    }
+
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/DetailModelPane.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/DetailModelPane.java
new file mode 100644
index 0000000..691d031
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/DetailModelPane.java
@@ -0,0 +1,225 @@
+/*
+ *  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.polygene.envisage.detail;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.util.ResourceBundle;
+import javax.swing.BorderFactory;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.SwingUtilities;
+import org.apache.polygene.envisage.event.LinkEvent;
+import org.apache.polygene.envisage.event.LinkListener;
+import org.apache.polygene.tools.model.descriptor.EntityDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ImportedServiceDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.LayerDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ModuleDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ObjectDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ServiceDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.TransientDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ValueDetailDescriptor;
+
+public final class DetailModelPane
+    extends JPanel
+{
+
+    protected ResourceBundle bundle = ResourceBundle.getBundle( this.getClass().getName() );
+
+    protected JTabbedPane tabPane;
+    protected GeneralPane generalPane;
+    protected MethodPane methodPane;
+    protected StatePane statePane;
+    protected DependencyPane dependencyPane;
+    protected ServiceConfigurationPane serviceConfigurationPane;
+    protected ServiceUsagePane serviceUsagePane;
+    protected ImportedByPane importedByPane;
+    protected APIPane apiPane;
+    protected SPIPane spiPane;
+
+    protected boolean linkActivatedInProgress;
+
+    public DetailModelPane()
+    {
+        tabPane = new JTabbedPane();
+
+        this.setLayout( new BorderLayout() );
+        this.add( tabPane, BorderLayout.CENTER );
+
+        createDetailPane();
+    }
+
+    private void createDetailPane()
+    {
+        generalPane = new GeneralPane( this );
+        generalPane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
+
+        statePane = new StatePane( this );
+        statePane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
+
+        methodPane = new MethodPane( this );
+        methodPane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
+
+        dependencyPane = new DependencyPane( this );
+        dependencyPane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
+
+        serviceConfigurationPane = new ServiceConfigurationPane( this );
+        serviceConfigurationPane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
+
+        serviceUsagePane = new ServiceUsagePane( this );
+        serviceUsagePane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
+
+        importedByPane = new ImportedByPane( this );
+        importedByPane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
+
+        apiPane = new APIPane( this );
+        apiPane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
+
+        spiPane = new SPIPane( this );
+        spiPane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
+    }
+
+    public void setDescriptor( final Object objectDescriptor )
+    {
+        SwingUtilities.invokeLater( () -> setDescriptorImpl( objectDescriptor ) );
+    }
+
+    private void setDescriptorImpl( Object objectDescriptor )
+    {
+        Component curSelectedComp = tabPane.getSelectedComponent();
+        tabPane.removeAll();
+
+        generalPane.setDescriptor( objectDescriptor );
+        dependencyPane.setDescriptor( objectDescriptor );
+        methodPane.setDescriptor( objectDescriptor );
+        statePane.setDescriptor( objectDescriptor );
+        serviceConfigurationPane.setDescriptor( objectDescriptor );
+        serviceUsagePane.setDescriptor( objectDescriptor );
+        importedByPane.setDescriptor( objectDescriptor );
+        apiPane.setDescriptor( objectDescriptor );
+        spiPane.setDescriptor( objectDescriptor );
+
+        if( objectDescriptor instanceof LayerDetailDescriptor
+            || objectDescriptor instanceof ModuleDetailDescriptor )
+        {
+            tabPane.add( bundle.getString( "CTL_APITab.Text" ), apiPane );
+            tabPane.add( bundle.getString( "CTL_SPITab.Text" ), spiPane );
+        }
+        else if( objectDescriptor instanceof ServiceDetailDescriptor )
+        {
+            tabPane.add( bundle.getString( "CTL_GeneralTab.Text" ), generalPane );
+            tabPane.add( bundle.getString( "CTL_DependencyTab.Text" ), dependencyPane );
+            tabPane.add( bundle.getString( "CTL_MethodTab.Text" ), methodPane );
+            tabPane.add( bundle.getString( "CTL_StateTab.Text" ), statePane );
+            tabPane.add( bundle.getString( "CTL_ServiceConfiguration.Text" ), serviceConfigurationPane );
+            tabPane.add( bundle.getString( "CTL_ServiceUsage.Text" ), serviceUsagePane );
+        }
+        else if( objectDescriptor instanceof ImportedServiceDetailDescriptor )
+        {
+            tabPane.add( bundle.getString( "CTL_GeneralTab.Text" ), generalPane );
+            tabPane.add( bundle.getString( "CTL_MethodTab.Text" ), methodPane );
+            tabPane.add( bundle.getString( "CTL_ServiceUsage.Text" ), serviceUsagePane );
+            tabPane.add( bundle.getString( "CTL_ImportedBy.Text" ), importedByPane );
+        }
+        else if( objectDescriptor instanceof EntityDetailDescriptor )
+        {
+            tabPane.add( bundle.getString( "CTL_GeneralTab.Text" ), generalPane );
+            tabPane.add( bundle.getString( "CTL_DependencyTab.Text" ), dependencyPane );
+            tabPane.add( bundle.getString( "CTL_MethodTab.Text" ), methodPane );
+            tabPane.add( bundle.getString( "CTL_StateTab.Text" ), statePane );
+        }
+        else if( objectDescriptor instanceof ValueDetailDescriptor )
+        {
+            tabPane.add( bundle.getString( "CTL_GeneralTab.Text" ), generalPane );
+            tabPane.add( bundle.getString( "CTL_DependencyTab.Text" ), dependencyPane );
+            tabPane.add( bundle.getString( "CTL_MethodTab.Text" ), methodPane );
+            tabPane.add( bundle.getString( "CTL_StateTab.Text" ), statePane );
+        }
+        else if( objectDescriptor instanceof ObjectDetailDescriptor )
+        {
+            tabPane.add( bundle.getString( "CTL_GeneralTab.Text" ), generalPane );
+            tabPane.add( bundle.getString( "CTL_DependencyTab.Text" ), dependencyPane );
+            tabPane.add( bundle.getString( "CTL_MethodTab.Text" ), methodPane );
+        }
+        else if( objectDescriptor instanceof TransientDetailDescriptor )
+        {
+            tabPane.add( bundle.getString( "CTL_GeneralTab.Text" ), generalPane );
+            tabPane.add( bundle.getString( "CTL_DependencyTab.Text" ), dependencyPane );
+            tabPane.add( bundle.getString( "CTL_MethodTab.Text" ), methodPane );
+            tabPane.add( bundle.getString( "CTL_StateTab.Text" ), statePane );
+        }
+
+        if( linkActivatedInProgress )
+        {
+            // for linking always display the first tab (General)
+            linkActivatedInProgress = false;
+            tabPane.setSelectedIndex( 0 );
+        }
+        else
+        {
+            // if not linking, then maintain the current selected tab
+            if( curSelectedComp != null )
+            {
+                int index = tabPane.indexOfComponent( curSelectedComp );
+                if( index != -1 )
+                {
+                    tabPane.setSelectedIndex( index );
+                }
+            }
+        }
+    }
+
+    /**
+     * Add a listener that's notified each time a LinkEvent occurs.
+     *
+     * @param listener the LinkListener to add
+     */
+    public void addLinkListener( LinkListener listener )
+    {
+        listenerList.add( LinkListener.class, listener );
+    }
+
+    /**
+     * Remove a listener that's notified each time a LinkEvent occurs.
+     *
+     * @param listener the LinkListener to remove
+     */
+    public void removeLinkListener( LinkListener listener )
+    {
+        listenerList.remove( LinkListener.class, listener );
+    }
+
+    /* package */ void fireLinkActivated( LinkEvent evt )
+    {
+        linkActivatedInProgress = true;
+        // Guaranteed to return a non-null array
+        Object[] listeners = listenerList.getListenerList();
+        // Process the listeners last to first, notifying
+        // those that are interested in this event
+        for( int i = listeners.length - 2; i >= 0; i -= 2 )
+        {
+            if( listeners[i] == LinkListener.class )
+            {
+                ( (LinkListener) listeners[i + 1] ).activated( evt );
+            }
+        }
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/DetailPane.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/DetailPane.java
new file mode 100644
index 0000000..ca356e6
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/DetailPane.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.envisage.detail;
+
+import javax.swing.JPanel;
+
+/**
+ * Abstract Base class for DetailPane
+ */
+/* package */ abstract class DetailPane
+    extends JPanel
+{
+    protected final DetailModelPane detailModelPane;
+
+    protected DetailPane( DetailModelPane detailModelPane )
+    {
+        if( detailModelPane == null )
+        {
+            throw new IllegalArgumentException( "detailModelPane could not null" );
+        }
+        this.detailModelPane = detailModelPane;
+    }
+
+    protected abstract void setDescriptor( Object objectDescriptor );
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/GeneralPane.form b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/GeneralPane.form
new file mode 100644
index 0000000..103f34b
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/GeneralPane.form
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.apache.polygene.envisage.detail.GeneralPane">
+  <grid id="27dc6" binding="contentPane" layout-manager="BorderLayout" hgap="0" vgap="0">
+    <constraints>
+      <xy x="20" y="20" width="299" height="260"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <scrollpane id="af7b6">
+        <constraints border-constraint="Center"/>
+        <properties/>
+        <border type="none"/>
+        <children>
+          <component id="53425" class="javax.swing.JTable" binding="table">
+            <constraints/>
+            <properties/>
+          </component>
+        </children>
+      </scrollpane>
+    </children>
+  </grid>
+</form>
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/GeneralPane.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/GeneralPane.java
new file mode 100644
index 0000000..15e2987
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/GeneralPane.java
@@ -0,0 +1,235 @@
+/*
+ *  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.polygene.envisage.detail;
+
+import java.awt.BorderLayout;
+import java.util.ArrayList;
+import java.util.ResourceBundle;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableColumnModel;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.envisage.util.TableRow;
+import org.apache.polygene.tools.model.descriptor.EntityDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ImportedServiceCompositeDescriptor;
+import org.apache.polygene.tools.model.descriptor.ImportedServiceDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ObjectDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ServiceDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.TransientDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ValueDetailDescriptor;
+
+/**
+ * Implementation of General DetailPane
+ */
+/* package */ final class GeneralPane
+    extends DetailPane
+{
+    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( GeneralPane.class.getName() );
+
+    private JPanel contentPane;
+    private JTable table;
+    private final GeneralTableModel tableModel;
+
+    /* package */ GeneralPane( DetailModelPane detailModelPane )
+    {
+        super( detailModelPane );
+        this.setLayout( new BorderLayout() );
+        this.add( contentPane, BorderLayout.CENTER );
+
+        tableModel = new GeneralTableModel();
+        table.setModel( tableModel );
+
+        TableColumnModel columnModel = table.getColumnModel();
+        columnModel.getColumn( 0 ).setPreferredWidth( 90 );
+        columnModel.getColumn( 1 ).setPreferredWidth( 550 );
+    }
+
+    private void clear()
+    {
+        tableModel.clear();
+    }
+
+    @Override
+    protected void setDescriptor( Object objectDesciptor )
+    {
+        clear();
+        tableModel.reload( objectDesciptor );
+    }
+
+    {
+// GUI initializer generated by IntelliJ IDEA GUI Designer
+// >>> IMPORTANT!! <<<
+// DO NOT EDIT OR ADD ANY CODE HERE!
+        $$$setupUI$$$();
+    }
+
+    /**
+     * Method generated by IntelliJ IDEA GUI Designer
+     * >>> IMPORTANT!! <<<
+     * DO NOT edit this method OR call it in your code!
+     */
+    private void $$$setupUI$$$()
+    {
+        contentPane = new JPanel();
+        contentPane.setLayout( new BorderLayout( 0, 0 ) );
+        final JScrollPane scrollPane1 = new JScrollPane();
+        contentPane.add( scrollPane1, BorderLayout.CENTER );
+        table = new JTable();
+        scrollPane1.setViewportView( table );
+    }
+
+    public JComponent $$$getRootComponent$$$()
+    {
+        return contentPane;
+    }
+
+    private static class GeneralTableModel
+        extends AbstractTableModel
+    {
+        /**
+         * the column names for this model
+         */
+        private static final String[] COLUMN_NAMES =
+            {
+                BUNDLE.getString( "Name.Column" ),
+                BUNDLE.getString( "Value.Column" )
+            };
+        private final ArrayList<TableRow> rows;
+
+        private final String nameRow = "name";
+        private final String classRow = "class";
+        private final String visibilityRow = "visibility";
+        private final String moduleRow = "module";
+        private final String layerRow = "layer";
+
+        private GeneralTableModel()
+        {
+            rows = new ArrayList<>();
+        }
+
+        private void reload( Object objectDesciptor )
+        {
+            if( objectDesciptor instanceof ServiceDetailDescriptor )
+            {
+                ServiceDescriptor descriptor = ( (ServiceDetailDescriptor) objectDesciptor ).descriptor();
+                Class<?> type = descriptor.types().findFirst().get();
+                rows.add( new TableRow( 2, nameRow, type.getSimpleName() ) );
+                rows.add( new TableRow( 2, classRow, type.getName() ) );
+                rows.add( new TableRow( 2, visibilityRow, descriptor.visibility().toString() ) );
+                rows.add( new TableRow( 2, moduleRow, ( (ServiceDetailDescriptor) objectDesciptor ).module() ) );
+                rows.add( new TableRow( 2, layerRow, ( (ServiceDetailDescriptor) objectDesciptor ).module().layer() ) );
+                rows.add( new TableRow( 2, "startup", ( (ServiceDetailDescriptor) objectDesciptor ).descriptor()
+                    .isInstantiateOnStartup() ) );
+            }
+            else if( objectDesciptor instanceof ImportedServiceDetailDescriptor )
+            {
+                ImportedServiceCompositeDescriptor descriptor = ( (ImportedServiceDetailDescriptor) objectDesciptor ).descriptor();
+                rows.add( new TableRow( 2, nameRow, descriptor.primaryType().getSimpleName() ) );
+                rows.add( new TableRow( 2, classRow, descriptor.primaryType().getName() ) );
+                rows.add( new TableRow( 2, visibilityRow, descriptor.visibility().toString() ) );
+                rows.add( new TableRow( 2, moduleRow, ( (ImportedServiceDetailDescriptor) objectDesciptor ).module() ) );
+                rows.add( new TableRow( 2, layerRow, ( (ImportedServiceDetailDescriptor) objectDesciptor ).module()
+                    .layer() ) );
+            }
+            else if( objectDesciptor instanceof EntityDetailDescriptor )
+            {
+                EntityDescriptor descriptor = ( (EntityDetailDescriptor) objectDesciptor ).descriptor();
+                Class<?> type = descriptor.types().findFirst().orElse( null );
+                rows.add( new TableRow( 2, nameRow, type.getSimpleName() ) );
+                rows.add( new TableRow( 2, classRow, type.getName() ) );
+                rows.add( new TableRow( 2, visibilityRow, descriptor.visibility().toString() ) );
+                rows.add( new TableRow( 2, moduleRow, ( (EntityDetailDescriptor) objectDesciptor ).module() ) );
+                rows.add( new TableRow( 2, layerRow, ( (EntityDetailDescriptor) objectDesciptor ).module().layer() ) );
+            }
+            else if( objectDesciptor instanceof ValueDetailDescriptor )
+            {
+                ValueDescriptor descriptor = ( (ValueDetailDescriptor) objectDesciptor ).descriptor();
+                Class<?> type = descriptor.types().findFirst().orElse( null );
+                rows.add( new TableRow( 2, nameRow, type.getSimpleName() ) );
+                rows.add( new TableRow( 2, classRow, type.getName() ) );
+                rows.add( new TableRow( 2, visibilityRow, descriptor.visibility().toString() ) );
+                rows.add( new TableRow( 2, moduleRow, ( (ValueDetailDescriptor) objectDesciptor ).module() ) );
+                rows.add( new TableRow( 2, layerRow, ( (ValueDetailDescriptor) objectDesciptor ).module().layer() ) );
+            }
+            else if( objectDesciptor instanceof ObjectDetailDescriptor )
+            {
+                ObjectDescriptor descriptor = ( (ObjectDetailDescriptor) objectDesciptor ).descriptor();
+                Class<?> type = descriptor.types().findFirst().orElse( null );
+                rows.add( new TableRow( 2, nameRow, type.getSimpleName() ) );
+                rows.add( new TableRow( 2, classRow, type.getName() ) );
+                rows.add( new TableRow( 2, visibilityRow, descriptor.visibility().toString() ) );
+                rows.add( new TableRow( 2, moduleRow, ( (ObjectDetailDescriptor) objectDesciptor ).module() ) );
+                rows.add( new TableRow( 2, layerRow, ( (ObjectDetailDescriptor) objectDesciptor ).module().layer() ) );
+            }
+            else if( objectDesciptor instanceof TransientDetailDescriptor )
+            {
+                CompositeDescriptor descriptor = ( (TransientDetailDescriptor) objectDesciptor ).descriptor();
+                Class<?> type = descriptor.types().findFirst().orElse( null );
+                rows.add( new TableRow( 2, nameRow, type.getSimpleName() ) );
+                rows.add( new TableRow( 2, classRow, type.getName() ) );
+                rows.add( new TableRow( 2, visibilityRow, descriptor.visibility().toString() ) );
+                rows.add( new TableRow( 2, moduleRow, ( (TransientDetailDescriptor) objectDesciptor ).module() ) );
+                rows.add( new TableRow( 2, layerRow, ( (TransientDetailDescriptor) objectDesciptor ).module()
+                    .layer() ) );
+            }
+
+            fireTableDataChanged();
+        }
+
+        @Override
+        public Object getValueAt( int rowIndex, int columnIndex )
+        {
+            TableRow row = this.rows.get( rowIndex );
+            return row.get( columnIndex );
+        }
+
+        private void clear()
+        {
+            rows.clear();
+            fireTableDataChanged();
+        }
+
+        @Override
+        public int getColumnCount()
+        {
+            return COLUMN_NAMES.length;
+        }
+
+        @Override
+        public String getColumnName( int col )
+        {
+            return COLUMN_NAMES[ col ];
+        }
+
+        @Override
+        public int getRowCount()
+        {
+            return rows.size();
+        }
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ImportedByPane.form b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ImportedByPane.form
new file mode 100644
index 0000000..f6dc305
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ImportedByPane.form
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.apache.polygene.envisage.detail.ImportedByPane">
+  <grid id="27dc6" binding="contentPane" layout-manager="GridBagLayout">
+    <constraints>
+      <xy x="20" y="20" width="500" height="400"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <component id="52fba" class="javax.swing.JLabel">
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="0.0"/>
+        </constraints>
+        <properties>
+          <text resource-bundle="org/apache/polygene/envisage/detail/ImportedByPane" key="CTL_Name.Text"/>
+        </properties>
+      </component>
+      <hspacer id="3491d">
+        <constraints>
+          <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="0.0"/>
+        </constraints>
+      </hspacer>
+      <vspacer id="834de">
+        <constraints>
+          <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="0.0"/>
+        </constraints>
+      </vspacer>
+      <component id="bad85" class="javax.swing.JLabel" binding="nameLabel">
+        <constraints>
+          <grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="0.0"/>
+        </constraints>
+        <properties>
+          <text value="Label"/>
+        </properties>
+      </component>
+      <component id="48183" class="javax.swing.JLabel">
+        <constraints>
+          <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="0.0"/>
+        </constraints>
+        <properties>
+          <text resource-bundle="org/apache/polygene/envisage/detail/ImportedByPane" key="CTL_Class.Text"/>
+        </properties>
+      </component>
+      <component id="17892" class="javax.swing.JLabel" binding="classLabel">
+        <constraints>
+          <grid row="3" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="1.0" weighty="0.0"/>
+        </constraints>
+        <properties>
+          <text value="Label"/>
+        </properties>
+      </component>
+      <vspacer id="9dbec">
+        <constraints>
+          <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="1.0"/>
+        </constraints>
+      </vspacer>
+      <vspacer id="2e566">
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="0.0"/>
+        </constraints>
+      </vspacer>
+    </children>
+  </grid>
+</form>
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ImportedByPane.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ImportedByPane.java
new file mode 100644
index 0000000..ec6646f
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ImportedByPane.java
@@ -0,0 +1,186 @@
+/*
+ *  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.polygene.envisage.detail;
+
+import java.awt.BorderLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.util.ResourceBundle;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.tools.model.descriptor.ImportedServiceDetailDescriptor;
+
+/**
+ * Implementation of ImportedService imported by
+ */
+/* package */ final class ImportedByPane
+    extends DetailPane
+{
+    private JPanel contentPane;
+    private JLabel nameLabel;
+    private JLabel classLabel;
+
+    /* package */ ImportedByPane( DetailModelPane detailModelPane )
+    {
+        super( detailModelPane );
+        this.setLayout( new BorderLayout() );
+        this.add( contentPane, BorderLayout.CENTER );
+    }
+
+    @Override
+    protected void setDescriptor( Object objectDesciptor )
+    {
+        clear();
+
+        if( !( objectDesciptor instanceof ImportedServiceDetailDescriptor ) )
+        {
+            return;
+        }
+
+        ImportedServiceDetailDescriptor detailDescriptor = (ImportedServiceDetailDescriptor) objectDesciptor;
+        ImportedServiceDescriptor descriptor = detailDescriptor.descriptor().importedService();
+
+        Class<? extends ServiceImporter> importer = descriptor.serviceImporter();
+        nameLabel.setText( importer.getSimpleName() );
+        classLabel.setText( importer.toString() );
+    }
+
+    private void clear()
+    {
+        nameLabel.setText( null );
+        classLabel.setText( null );
+    }
+
+    
+    {
+// GUI initializer generated by IntelliJ IDEA GUI Designer
+// >>> IMPORTANT!! <<<
+// DO NOT EDIT OR ADD ANY CODE HERE!
+        $$$setupUI$$$();
+    }
+
+    /**
+     * Method generated by IntelliJ IDEA GUI Designer
+     * >>> IMPORTANT!! <<<
+     * DO NOT edit this method OR call it in your code!
+     *
+     */
+    private void $$$setupUI$$$()
+    {
+        contentPane = new JPanel();
+        contentPane.setLayout( new GridBagLayout() );
+        final JLabel label1 = new JLabel();
+        this.$$$loadLabelText$$$( label1, ResourceBundle.getBundle( "org/apache/polygene/envisage/detail/ImportedByPane" ).getString( "CTL_Name.Text" ) );
+        GridBagConstraints gbc;
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 1;
+        gbc.anchor = GridBagConstraints.WEST;
+        contentPane.add( label1, gbc );
+        final JPanel spacer1 = new JPanel();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 1;
+        gbc.gridy = 1;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        contentPane.add( spacer1, gbc );
+        final JPanel spacer2 = new JPanel();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 2;
+        gbc.fill = GridBagConstraints.VERTICAL;
+        contentPane.add( spacer2, gbc );
+        nameLabel = new JLabel();
+        nameLabel.setText( "Label" );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 2;
+        gbc.gridy = 1;
+        gbc.anchor = GridBagConstraints.WEST;
+        contentPane.add( nameLabel, gbc );
+        final JLabel label2 = new JLabel();
+        this.$$$loadLabelText$$$( label2, ResourceBundle.getBundle( "org/apache/polygene/envisage/detail/ImportedByPane" ).getString( "CTL_Class.Text" ) );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 3;
+        gbc.anchor = GridBagConstraints.WEST;
+        contentPane.add( label2, gbc );
+        classLabel = new JLabel();
+        classLabel.setText( "Label" );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 2;
+        gbc.gridy = 3;
+        gbc.weightx = 1.0;
+        gbc.anchor = GridBagConstraints.WEST;
+        contentPane.add( classLabel, gbc );
+        final JPanel spacer3 = new JPanel();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 4;
+        gbc.weighty = 1.0;
+        gbc.fill = GridBagConstraints.VERTICAL;
+        contentPane.add( spacer3, gbc );
+        final JPanel spacer4 = new JPanel();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.fill = GridBagConstraints.VERTICAL;
+        contentPane.add( spacer4, gbc );
+    }
+
+    private void $$$loadLabelText$$$( JLabel component, String text )
+    {
+        StringBuffer result = new StringBuffer();
+        boolean haveMnemonic = false;
+        char mnemonic = '\0';
+        int mnemonicIndex = -1;
+        for( int i = 0; i < text.length(); i++ )
+        {
+            if( text.charAt( i ) == '&' )
+            {
+                i++;
+                if( i == text.length() )
+                {
+                    break;
+                }
+                if( !haveMnemonic && text.charAt( i ) != '&' )
+                {
+                    haveMnemonic = true;
+                    mnemonic = text.charAt( i );
+                    mnemonicIndex = result.length();
+                }
+            }
+            result.append( text.charAt( i ) );
+        }
+        component.setText( result.toString() );
+        if( haveMnemonic )
+        {
+            component.setDisplayedMnemonic( mnemonic );
+            component.setDisplayedMnemonicIndex( mnemonicIndex );
+        }
+    }
+
+    public JComponent $$$getRootComponent$$$()
+    {
+        return contentPane;
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/MethodPane.form b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/MethodPane.form
new file mode 100644
index 0000000..58ceda7
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/MethodPane.form
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.apache.polygene.envisage.detail.MethodPane">
+  <grid id="27dc6" binding="contentPane" layout-manager="BorderLayout" hgap="0" vgap="0">
+    <constraints>
+      <xy x="20" y="20" width="500" height="400"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <splitpane id="24b86" binding="splitPane">
+        <constraints border-constraint="Center"/>
+        <properties/>
+        <border type="none"/>
+        <children>
+          <scrollpane id="b00c1">
+            <constraints>
+              <splitpane position="left"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <component id="19b04" class="javax.swing.JList" binding="methodList">
+                <constraints/>
+                <properties/>
+              </component>
+            </children>
+          </scrollpane>
+          <scrollpane id="fb413">
+            <constraints>
+              <splitpane position="right"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <component id="f694" class="javax.swing.JTable" binding="methodDetailTable">
+                <constraints/>
+                <properties/>
+              </component>
+            </children>
+          </scrollpane>
+        </children>
+      </splitpane>
+    </children>
+  </grid>
+</form>
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/MethodPane.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/MethodPane.java
new file mode 100644
index 0000000..75db886
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/MethodPane.java
@@ -0,0 +1,348 @@
+/*
+ *  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.polygene.envisage.detail;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ResourceBundle;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.DefaultListModel;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JComponent;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableColumnModel;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.envisage.util.TableRow;
+import org.apache.polygene.tools.model.descriptor.CompositeDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.CompositeMethodDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.MethodConcernDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.MethodSideEffectDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ObjectDetailDescriptor;
+import org.apache.polygene.tools.model.util.DescriptorUtilities;
+
+/**
+ * Implementation of Composite Method Panel
+ */
+/* package */ final class MethodPane
+    extends DetailPane
+{
+    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( MethodPane.class.getName() );
+
+    private JPanel contentPane;
+    private JList methodList;
+    private JTable methodDetailTable;
+    private JSplitPane splitPane;
+
+    private final DefaultListModel methodListModel;
+    private final MethodDetailTableModel methodDetailTableModel;
+
+    /* package */ MethodPane( DetailModelPane detailModelPane )
+    {
+        super( detailModelPane );
+        this.setLayout( new BorderLayout() );
+        this.add( contentPane, BorderLayout.CENTER );
+
+        methodListModel = new DefaultListModel();
+        methodList.setModel( methodListModel );
+        methodList.setCellRenderer( new MethodListCellRenderer() );
+        methodList.setPrototypeCellValue( "12345678901234567890" );
+        methodList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
+
+        methodDetailTableModel = new MethodDetailTableModel();
+        methodDetailTable.setModel( methodDetailTableModel );
+
+        TableColumnModel columnModel = methodDetailTable.getColumnModel();
+        columnModel.getColumn( 0 ).setPreferredWidth( 75 );
+        columnModel.getColumn( 1 ).setPreferredWidth( 400 );
+
+        //splitPane.setResizeWeight( .1 );
+        //splitPane.setDividerLocation( .3 );
+        methodList.addListSelectionListener( this::methodListValueChanged );
+    }
+
+    @Override
+    protected void setDescriptor( Object objectDesciptor )
+    {
+        clear();
+
+        if( objectDesciptor instanceof CompositeDetailDescriptor )
+        {
+            CompositeDetailDescriptor descriptor = ( (CompositeDetailDescriptor) objectDesciptor );
+            List<CompositeMethodDetailDescriptor> list = DescriptorUtilities.findMethod( descriptor );
+            for( CompositeMethodDetailDescriptor methodDescriptor : list )
+            {
+                methodListModel.addElement( methodDescriptor );
+            }
+
+            if( !methodListModel.isEmpty() )
+            {
+                methodList.setSelectedIndex( 0 );
+            }
+        }
+        else if( objectDesciptor instanceof ObjectDetailDescriptor )
+        {
+            // Object does not have methods
+        }
+    }
+
+    private void clear()
+    {
+        methodListModel.clear();
+        methodDetailTableModel.clear();
+    }
+
+    private void methodListValueChanged( ListSelectionEvent evt )
+    {
+        if( evt.getValueIsAdjusting() )
+        {
+            return;
+        }
+        Object obj = methodList.getSelectedValue();
+        if( obj == null )
+        {
+            methodDetailTableModel.clear();
+            return;
+        }
+        methodDetailTableModel.reload( (CompositeMethodDetailDescriptor) obj );
+    }
+
+    
+    {
+// GUI initializer generated by IntelliJ IDEA GUI Designer
+// >>> IMPORTANT!! <<<
+// DO NOT EDIT OR ADD ANY CODE HERE!
+        $$$setupUI$$$();
+    }
+
+    /**
+     * Method generated by IntelliJ IDEA GUI Designer
+     * >>> IMPORTANT!! <<<
+     * DO NOT edit this method OR call it in your code!
+     *
+     */
+    private void $$$setupUI$$$()
+    {
+        contentPane = new JPanel();
+        contentPane.setLayout( new BorderLayout( 0, 0 ) );
+        splitPane = new JSplitPane();
+        contentPane.add( splitPane, BorderLayout.CENTER );
+        final JScrollPane scrollPane1 = new JScrollPane();
+        splitPane.setLeftComponent( scrollPane1 );
+        methodList = new JList();
+        scrollPane1.setViewportView( methodList );
+        final JScrollPane scrollPane2 = new JScrollPane();
+        splitPane.setRightComponent( scrollPane2 );
+        methodDetailTable = new JTable();
+        scrollPane2.setViewportView( methodDetailTable );
+    }
+
+    public JComponent $$$getRootComponent$$$()
+    {
+        return contentPane;
+    }
+
+    private static class MethodDetailTableModel
+        extends AbstractTableModel
+    {
+        /**
+         * the column names for this model
+         */
+        private static final String[] COLUMN_NAMES =
+        {
+            "Name",
+            "Value"
+        };
+        private final ArrayList<TableRow> rows;
+
+        private MethodDetailTableModel()
+        {
+            rows = new ArrayList<>();
+        }
+
+        private void reload( CompositeMethodDetailDescriptor descriptor )
+        {
+            Method method = descriptor.descriptor().method();
+
+            clear();
+
+            // mixin type
+            rows.add( new TableRow( 2, "return", Classes.simpleGenericNameOf( method.getGenericReturnType() ) ) );
+
+            // method
+            StringBuilder parameters = new StringBuilder();
+            for( int idx = 0; idx < method.getGenericParameterTypes().length; idx++ )
+            {
+                Type type = method.getGenericParameterTypes()[idx];
+                Annotation[] annotations = method.getParameterAnnotations()[idx];
+
+                if( parameters.length() > 0 )
+                {
+                    parameters.append( ", " );
+                }
+
+                for( Annotation annotation : annotations )
+                {
+                    String ann = annotation.toString();
+                    ann = "@" + ann.substring( ann.lastIndexOf( '.' ) + 1 );
+                    parameters.append( ann ).append( " " );
+                }
+
+                parameters.append( Classes.simpleGenericNameOf( type ) );
+            }
+
+            rows.add( new TableRow( 2, "parameters", parameters.toString() ) );
+
+            // concern
+            boolean first = true;
+            for( MethodConcernDetailDescriptor concern : descriptor.concerns().concerns() )
+            {
+                if( first )
+                {
+                    rows.add( new TableRow( 2, "concern", concern.descriptor().modifierClass().getSimpleName() ) );
+                    first = false;
+                }
+                else
+                {
+                    rows.add( new TableRow( 2, "", concern.descriptor().modifierClass().getSimpleName() ) );
+                }
+            }
+
+            // sideEffect
+            first = false;
+            for( MethodSideEffectDetailDescriptor sideEffect : descriptor.sideEffects().sideEffects() )
+            {
+                if( first )
+                {
+                    rows.add( new TableRow( 2, "sideEffect", sideEffect.descriptor().modifierClass().getSimpleName() ) );
+                    first = false;
+                }
+                else
+                {
+                    rows.add( new TableRow( 2, "", sideEffect.descriptor().modifierClass().getSimpleName() ) );
+                }
+            }
+
+            fireTableDataChanged();
+        }
+
+        @Override
+        public Object getValueAt( int rowIndex, int columnIndex )
+        {
+            TableRow row = this.rows.get( rowIndex );
+            return row.get( columnIndex );
+        }
+
+        private void clear()
+        {
+            rows.clear();
+            fireTableDataChanged();
+        }
+
+        @Override
+        public int getColumnCount()
+        {
+            return COLUMN_NAMES.length;
+        }
+
+        @Override
+        public String getColumnName( int col )
+        {
+            return COLUMN_NAMES[ col];
+        }
+
+        @Override
+        public int getRowCount()
+        {
+            return rows.size();
+        }
+    }
+
+    private static class MethodListCellRenderer
+        extends DefaultListCellRenderer
+    {
+        private final Icon publicIcon;
+        private final Icon privateIcon;
+
+        public MethodListCellRenderer()
+        {
+            try
+            {
+                publicIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Public" ) ) );
+                privateIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Private" ) ) );
+            }
+            catch( Exception ex )
+            {
+                throw new RuntimeException( ex );
+            }
+        }
+
+        @Override
+        public Component getListCellRendererComponent( JList list,
+                                                       Object value,
+                                                       int index,
+                                                       boolean isSelected,
+                                                       boolean cellHasFocus
+        )
+        {
+            super.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
+            if( !( value instanceof CompositeMethodDetailDescriptor ) )
+            {
+                return this;
+            }
+
+            Icon icon;
+            CompositeMethodDetailDescriptor descriptor = (CompositeMethodDetailDescriptor) value;
+
+            Class compositeClass = descriptor.composite().descriptor().types().findFirst().get();
+            Class mixinMethodClass = descriptor.descriptor().method().getDeclaringClass();
+            if( mixinMethodClass.isAssignableFrom( compositeClass ) )
+            {
+                icon = publicIcon;
+            }
+            else
+            {
+                icon = privateIcon;
+            }
+
+            if( icon != null )
+            {
+                setIcon( icon );
+            }
+
+            return this;
+        }
+    }
+
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/SPIPane.form b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/SPIPane.form
new file mode 100644
index 0000000..395d8c6
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/SPIPane.form
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.apache.polygene.envisage.detail.SPIPane">
+  <grid id="27dc6" binding="contentPane" layout-manager="BorderLayout" hgap="0" vgap="0">
+    <constraints>
+      <xy x="20" y="20" width="500" height="400"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <scrollpane id="62a5">
+        <constraints border-constraint="Center"/>
+        <properties/>
+        <border type="none"/>
+        <children>
+          <component id="ca0ba" class="javax.swing.JTable" binding="spiTable">
+            <constraints/>
+            <properties/>
+          </component>
+        </children>
+      </scrollpane>
+    </children>
+  </grid>
+</form>
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/SPIPane.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/SPIPane.java
new file mode 100644
index 0000000..0f84014
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/SPIPane.java
@@ -0,0 +1,296 @@
+/*
+ *  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.polygene.envisage.detail;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ResourceBundle;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.MouseInputAdapter;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableColumnModel;
+import org.apache.polygene.envisage.event.LinkEvent;
+import org.apache.polygene.envisage.util.TableRow;
+import org.apache.polygene.tools.model.descriptor.LayerDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ModuleDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ServiceDetailDescriptor;
+import org.apache.polygene.tools.model.util.DescriptorUtilities;
+
+/**
+ * API would be defined as "All service interfaces which are visible for layer
+ * or application" and SPI would be defined as "All service dependencies which
+ * are not satisfied from within the module". And then similar for Layer. This
+ * way you can select a Module/Layer and immediately see what it produces as
+ * output and requires as input. This is also very very nice for documentation
+ * purposes.
+ */
+/* package */ final class SPIPane
+    extends DetailPane
+{
+    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( SPIPane.class.getName() );
+
+    private JPanel contentPane;
+    private JTable spiTable;
+    private SPITableModel spiTableModel;
+
+    private Object linkObject;
+    private Cursor defaultCursor;
+    private Cursor linkCursor;
+
+    /* package */ SPIPane( DetailModelPane detailModelPane )
+    {
+        super( detailModelPane );
+        this.setLayout( new BorderLayout() );
+        this.add( contentPane, BorderLayout.CENTER );
+
+        spiTableModel = new SPITableModel();
+        spiTable.setModel( spiTableModel );
+        spiTable.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
+
+        TableColumnModel columnModel = spiTable.getColumnModel();
+        columnModel.getColumn( 0 ).setCellRenderer( new DependencyCellRenderer() );
+
+        defaultCursor = getCursor();
+        linkCursor = LinkEvent.LINK_CURSOR;
+
+        MouseInputAdapter mouseInputListener = new MouseInputAdapter()
+        {
+            @Override
+            public void mouseMoved( MouseEvent evt )
+            {
+                // Column 1 is the Service Column
+                int col = spiTable.columnAtPoint( evt.getPoint() );
+                if( col == 0 )
+                {
+                    setCursor( linkCursor );
+                }
+                else
+                {
+                    if( !getCursor().equals( defaultCursor ) )
+                    {
+                        setCursor( defaultCursor );
+                    }
+                }
+            }
+
+            @Override
+            public void mouseClicked( MouseEvent evt )
+            {
+                int col = spiTable.columnAtPoint( evt.getPoint() );
+                if( col != 0 )
+                {
+                    return;
+                }
+
+                int row = spiTable.rowAtPoint( evt.getPoint() );
+                if( row < 0 )
+                {
+                    return;
+                }
+
+                linkObject = spiTable.getValueAt( row, col );
+                linkActivated();
+                linkObject = null;
+            }
+        };
+
+        spiTable.addMouseMotionListener( mouseInputListener );
+        spiTable.addMouseListener( mouseInputListener );
+    }
+
+    @Override
+    protected void setDescriptor( Object objectDesciptor )
+    {
+        clear();
+
+        List<ServiceDetailDescriptor> list = null;
+        if( objectDesciptor instanceof LayerDetailDescriptor )
+        {
+            list = DescriptorUtilities.findLayerSPI( (LayerDetailDescriptor) objectDesciptor );
+        }
+        else if( objectDesciptor instanceof ModuleDetailDescriptor )
+        {
+            list = DescriptorUtilities.findModule( (ModuleDetailDescriptor) objectDesciptor );
+        }
+
+        if( list != null )
+        {
+            spiTableModel.addRow( list );
+        }
+    }
+
+    private void clear()
+    {
+        linkObject = null;
+        spiTableModel.clear();
+    }
+
+    private void linkActivated()
+    {
+        if( linkObject == null )
+        {
+            return;
+        }
+        LinkEvent linkEvt = new LinkEvent( this, linkObject );
+        detailModelPane.fireLinkActivated( linkEvt );
+    }
+
+    
+    {
+// GUI initializer generated by IntelliJ IDEA GUI Designer
+// >>> IMPORTANT!! <<<
+// DO NOT EDIT OR ADD ANY CODE HERE!
+        $$$setupUI$$$();
+    }
+
+    /**
+     * Method generated by IntelliJ IDEA GUI Designer
+     * >>> IMPORTANT!! <<<
+     * DO NOT edit this method OR call it in your code!
+     *
+     */
+    private void $$$setupUI$$$()
+    {
+        contentPane = new JPanel();
+        contentPane.setLayout( new BorderLayout( 0, 0 ) );
+        final JScrollPane scrollPane1 = new JScrollPane();
+        contentPane.add( scrollPane1, BorderLayout.CENTER );
+        spiTable = new JTable();
+        scrollPane1.setViewportView( spiTable );
+    }
+
+    public JComponent $$$getRootComponent$$$()
+    {
+        return contentPane;
+    }
+
+    private static class SPITableModel
+        extends AbstractTableModel
+    {
+        /**
+         * the column names for this model
+         */
+        private static final String[] COLUMN_NAMES =
+        {
+            BUNDLE.getString( "Dependency.Column" ),
+            BUNDLE.getString( "Module.Column" ),
+            BUNDLE.getString( "Layer.Column" )
+        };
+        private final ArrayList<TableRow> rows;
+
+        private SPITableModel()
+        {
+            rows = new ArrayList<>();
+        }
+
+        private void addRow( List<ServiceDetailDescriptor> list )
+        {
+            if( list.isEmpty() )
+            {
+                return;
+            }
+
+            int i1 = rows.size();
+            if( i1 > 0 )
+            {
+                i1--;
+            }
+
+            int i2 = 0;
+
+            for( ServiceDetailDescriptor descriptor : list )
+            {
+                TableRow row = new TableRow( COLUMN_NAMES.length );
+                row.set( 0, descriptor );
+                row.set( 1, descriptor.module() );
+                row.set( 2, descriptor.module().layer() );
+                this.rows.add( row );
+                i2++;
+            }
+
+            fireTableRowsInserted( i1, i1 + i2 );
+        }
+
+        @Override
+        public Object getValueAt( int rowIndex, int columnIndex )
+        {
+            TableRow row = rows.get( rowIndex );
+            return row.get( columnIndex );
+        }
+
+        private void clear()
+        {
+            rows.clear();
+            fireTableDataChanged();
+        }
+
+        @Override
+        public int getColumnCount()
+        {
+            return COLUMN_NAMES.length;
+        }
+
+        @Override
+        public String getColumnName( int col )
+        {
+            return COLUMN_NAMES[ col];
+        }
+
+        @Override
+        public int getRowCount()
+        {
+            return rows.size();
+        }
+    }
+
+    private static class DependencyCellRenderer
+        extends DefaultTableCellRenderer
+    {
+        @Override
+        public final Component getTableCellRendererComponent( JTable table,
+                                                              Object value,
+                                                              boolean isSelected,
+                                                              boolean hasFocus,
+                                                              int row,
+                                                              int column
+        )
+        {
+            if( value != null )
+            {
+                value = "<html><a href=\"" + value.toString() + "\">" + value.toString() + "</a></html>";
+            }
+
+            super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );
+
+            return this;
+        }
+    }
+
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ServiceConfigurationPane.form b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ServiceConfigurationPane.form
new file mode 100644
index 0000000..2c0fa30
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ServiceConfigurationPane.form
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.apache.polygene.envisage.detail.ServiceConfigurationPane">
+  <grid id="27dc6" binding="contentPane" layout-manager="GridBagLayout">
+    <constraints>
+      <xy x="20" y="20" width="1045" height="266"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <component id="9d75a" class="javax.swing.JLabel">
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="0.0"/>
+        </constraints>
+        <properties>
+          <text resource-bundle="org/apache/polygene/envisage/detail/ServiceConfigurationPane" key="CTL_Name.Text"/>
+        </properties>
+      </component>
+      <hspacer id="f7748">
+        <constraints>
+          <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="0.0"/>
+        </constraints>
+      </hspacer>
+      <vspacer id="4ccd5">
+        <constraints>
+          <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="0.0"/>
+        </constraints>
+      </vspacer>
+      <component id="f0ff0" class="javax.swing.JLabel" binding="nameLabel">
+        <constraints>
+          <grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="0.0"/>
+        </constraints>
+        <properties>
+          <text value="Label"/>
+        </properties>
+      </component>
+      <vspacer id="97950">
+        <constraints>
+          <grid row="8" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="1.0"/>
+        </constraints>
+      </vspacer>
+      <component id="50b2b" class="javax.swing.JLabel">
+        <constraints>
+          <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="0.0"/>
+        </constraints>
+        <properties>
+          <text resource-bundle="org/apache/polygene/envisage/detail/ServiceConfigurationPane" key="CTL_Class.Text"/>
+        </properties>
+      </component>
+      <component id="86ec7" class="javax.swing.JLabel" binding="classLabel">
+        <constraints>
+          <grid row="3" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="1.0" weighty="0.0"/>
+        </constraints>
+        <properties>
+          <text value="Label"/>
+        </properties>
+      </component>
+      <vspacer id="bd0b9">
+        <constraints>
+          <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="0.0"/>
+        </constraints>
+      </vspacer>
+      <component id="43766" class="javax.swing.JButton" binding="linkButton">
+        <constraints>
+          <grid row="7" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="0.0"/>
+        </constraints>
+        <properties>
+          <text resource-bundle="org/apache/polygene/envisage/detail/ServiceConfigurationPane" key="CTL_Link.Text"/>
+        </properties>
+      </component>
+      <vspacer id="ab189">
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="0.0"/>
+        </constraints>
+      </vspacer>
+      <component id="cbdeb" class="javax.swing.JLabel">
+        <constraints>
+          <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="0.0"/>
+        </constraints>
+        <properties>
+          <text resource-bundle="org/apache/polygene/envisage/detail/ServiceConfigurationPane" key="CTL_Type.Text"/>
+        </properties>
+      </component>
+      <component id="845aa" class="javax.swing.JLabel" binding="typeLabel">
+        <constraints>
+          <grid row="5" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="0.0"/>
+        </constraints>
+        <properties>
+          <text value="Label"/>
+        </properties>
+      </component>
+      <vspacer id="f9c4">
+        <constraints>
+          <grid row="6" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+          <gridbag weightx="0.0" weighty="0.0"/>
+        </constraints>
+      </vspacer>
+    </children>
+  </grid>
+</form>
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ServiceConfigurationPane.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ServiceConfigurationPane.java
new file mode 100644
index 0000000..69eb8fc
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ServiceConfigurationPane.java
@@ -0,0 +1,354 @@
+/*
+ *  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.polygene.envisage.detail;
+
+import java.awt.BorderLayout;
+import java.awt.Cursor;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ResourceBundle;
+import javax.swing.AbstractButton;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.envisage.event.LinkEvent;
+import org.apache.polygene.tools.model.descriptor.CompositeDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.EntityDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ObjectDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ServiceDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ValueDetailDescriptor;
+import org.apache.polygene.tools.model.util.DescriptorUtilities;
+
+/**
+ * Implementation of Service Configuration Panel
+ */
+/* package */ final class ServiceConfigurationPane
+    extends DetailPane
+{
+    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( ServiceConfigurationPane.class.getName() );
+
+    private JPanel contentPane;
+    private JLabel nameLabel;
+    private JLabel classLabel;
+    private JButton linkButton;
+    private JLabel typeLabel;
+
+    private Object configDescriptor;
+    private Cursor defaultCursor;
+    private Cursor linkCursor;
+
+    /* package */ ServiceConfigurationPane( DetailModelPane detailModelPane )
+    {
+        super( detailModelPane );
+        this.setLayout( new BorderLayout() );
+        this.add( contentPane, BorderLayout.CENTER );
+
+        defaultCursor = getCursor();
+        linkCursor = LinkEvent.LINK_CURSOR;
+
+        linkButton.addActionListener( new ActionListener()
+        {
+            @Override
+            public void actionPerformed( ActionEvent evt )
+            {
+                linkActivated();
+            }
+        } );
+
+        nameLabel.addMouseListener( new MouseAdapter()
+        {
+            @Override
+            public void mouseClicked( MouseEvent evt )
+            {
+                linkActivated();
+            }
+
+            @Override
+            public void mouseEntered( MouseEvent evt )
+            {
+                setCursor( linkCursor );
+            }
+
+            @Override
+            public void mouseExited( MouseEvent evt )
+            {
+                setCursor( defaultCursor );
+            }
+        } );
+    }
+
+    private void linkActivated()
+    {
+        if( configDescriptor == null )
+        {
+            return;
+        }
+        LinkEvent linkEvt = new LinkEvent( this, configDescriptor );
+        detailModelPane.fireLinkActivated( linkEvt );
+    }
+
+    private void clear()
+    {
+        nameLabel.setText( null );
+        classLabel.setText( null );
+        typeLabel.setText( null );
+        linkButton.setEnabled( false );
+        configDescriptor = null;
+    }
+
+    @Override
+    protected void setDescriptor( Object objectDesciptor )
+    {
+        clear();
+
+        if( !( objectDesciptor instanceof ServiceDetailDescriptor ) )
+        {
+            return;
+        }
+
+        configDescriptor = DescriptorUtilities.findServiceConfiguration( (ServiceDetailDescriptor) objectDesciptor );
+        if( configDescriptor == null )
+        {
+            return;
+        }
+
+        ModelDescriptor spiDescriptor = null;
+        String typeString = null;
+        if( configDescriptor instanceof ServiceDetailDescriptor )
+        {
+            spiDescriptor = ( (ServiceDetailDescriptor) configDescriptor ).descriptor();
+            typeString = "Service";
+        }
+        else if( configDescriptor instanceof EntityDetailDescriptor )
+        {
+            spiDescriptor = ( (EntityDetailDescriptor) configDescriptor ).descriptor();
+            typeString = "Entity";
+        }
+        else if( configDescriptor instanceof ValueDetailDescriptor )
+        {
+            spiDescriptor = ( (ValueDetailDescriptor) configDescriptor ).descriptor();
+            typeString = "Value";
+        }
+        else if( configDescriptor instanceof ObjectDetailDescriptor )
+        {
+            spiDescriptor = ( (ObjectDetailDescriptor) configDescriptor ).descriptor();
+            typeString = "Object";
+        }
+        else if( configDescriptor instanceof CompositeDetailDescriptor )
+        {
+            spiDescriptor = ( (CompositeDetailDescriptor) configDescriptor ).descriptor();
+            typeString = "Transient";
+        }
+        else
+        {
+            throw new InternalError( "Unknown Config descriptor type" );
+        }
+        Class<?> type = spiDescriptor.types().findFirst().orElse( null );
+        String simpleName = type.getSimpleName();
+        nameLabel.setText( "<html><a href='" + simpleName + "'>" + simpleName + "</a></html>" );
+        classLabel.setText( type.getName() );
+        typeLabel.setText( typeString );
+        linkButton.setEnabled( true );
+    }
+
+    
+    {
+// GUI initializer generated by IntelliJ IDEA GUI Designer
+// >>> IMPORTANT!! <<<
+// DO NOT EDIT OR ADD ANY CODE HERE!
+        $$$setupUI$$$();
+    }
+
+    /**
+     * Method generated by IntelliJ IDEA GUI Designer
+     * >>> IMPORTANT!! <<<
+     * DO NOT edit this method OR call it in your code!
+     *
+     */
+    private void $$$setupUI$$$()
+    {
+        contentPane = new JPanel();
+        contentPane.setLayout( new GridBagLayout() );
+        final JLabel label1 = new JLabel();
+        this.$$$loadLabelText$$$( label1, ResourceBundle.getBundle( "org/apache/polygene/envisage/detail/ServiceConfigurationPane" ).getString( "CTL_Name.Text" ) );
+        GridBagConstraints gbc;
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 1;
+        gbc.anchor = GridBagConstraints.EAST;
+        contentPane.add( label1, gbc );
+        final JPanel spacer1 = new JPanel();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 1;
+        gbc.gridy = 1;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        contentPane.add( spacer1, gbc );
+        final JPanel spacer2 = new JPanel();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 2;
+        gbc.fill = GridBagConstraints.VERTICAL;
+        contentPane.add( spacer2, gbc );
+        nameLabel = new JLabel();
+        nameLabel.setText( "Label" );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 2;
+        gbc.gridy = 1;
+        gbc.anchor = GridBagConstraints.WEST;
+        contentPane.add( nameLabel, gbc );
+        final JPanel spacer3 = new JPanel();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 8;
+        gbc.weighty = 1.0;
+        gbc.fill = GridBagConstraints.VERTICAL;
+        contentPane.add( spacer3, gbc );
+        final JLabel label2 = new JLabel();
+        this.$$$loadLabelText$$$( label2, ResourceBundle.getBundle( "org/apache/polygene/envisage/detail/ServiceConfigurationPane" ).getString( "CTL_Class.Text" ) );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 3;
+        gbc.anchor = GridBagConstraints.EAST;
+        contentPane.add( label2, gbc );
+        classLabel = new JLabel();
+        classLabel.setText( "Label" );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 2;
+        gbc.gridy = 3;
+        gbc.weightx = 1.0;
+        gbc.anchor = GridBagConstraints.WEST;
+        contentPane.add( classLabel, gbc );
+        final JPanel spacer4 = new JPanel();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 4;
+        gbc.fill = GridBagConstraints.VERTICAL;
+        contentPane.add( spacer4, gbc );
+        linkButton = new JButton();
+        this.$$$loadButtonText$$$( linkButton, ResourceBundle.getBundle( "org/apache/polygene/envisage/detail/ServiceConfigurationPane" ).getString( "CTL_Link.Text" ) );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 2;
+        gbc.gridy = 7;
+        gbc.anchor = GridBagConstraints.WEST;
+        contentPane.add( linkButton, gbc );
+        final JPanel spacer5 = new JPanel();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.fill = GridBagConstraints.VERTICAL;
+        contentPane.add( spacer5, gbc );
+        final JLabel label3 = new JLabel();
+        this.$$$loadLabelText$$$( label3, ResourceBundle.getBundle( "org/apache/polygene/envisage/detail/ServiceConfigurationPane" ).getString( "CTL_Type.Text" ) );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 5;
+        gbc.anchor = GridBagConstraints.EAST;
+        contentPane.add( label3, gbc );
+        typeLabel = new JLabel();
+        typeLabel.setText( "Label" );
+        gbc = new GridBagConstraints();
+        gbc.gridx = 2;
+        gbc.gridy = 5;
+        gbc.anchor = GridBagConstraints.WEST;
+        contentPane.add( typeLabel, gbc );
+        final JPanel spacer6 = new JPanel();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 6;
+        gbc.fill = GridBagConstraints.VERTICAL;
+        contentPane.add( spacer6, gbc );
+    }
+
+    private void $$$loadLabelText$$$( JLabel component, String text )
+    {
+        StringBuffer result = new StringBuffer();
+        boolean haveMnemonic = false;
+        char mnemonic = '\0';
+        int mnemonicIndex = -1;
+        for( int i = 0; i < text.length(); i++ )
+        {
+            if( text.charAt( i ) == '&' )
+            {
+                i++;
+                if( i == text.length() )
+                {
+                    break;
+                }
+                if( !haveMnemonic && text.charAt( i ) != '&' )
+                {
+                    haveMnemonic = true;
+                    mnemonic = text.charAt( i );
+                    mnemonicIndex = result.length();
+                }
+            }
+            result.append( text.charAt( i ) );
+        }
+        component.setText( result.toString() );
+        if( haveMnemonic )
+        {
+            component.setDisplayedMnemonic( mnemonic );
+            component.setDisplayedMnemonicIndex( mnemonicIndex );
+        }
+    }
+
+    private void $$$loadButtonText$$$( AbstractButton component, String text )
+    {
+        StringBuffer result = new StringBuffer();
+        boolean haveMnemonic = false;
+        char mnemonic = '\0';
+        int mnemonicIndex = -1;
+        for( int i = 0; i < text.length(); i++ )
+        {
+            if( text.charAt( i ) == '&' )
+            {
+                i++;
+                if( i == text.length() )
+                {
+                    break;
+                }
+                if( !haveMnemonic && text.charAt( i ) != '&' )
+                {
+                    haveMnemonic = true;
+                    mnemonic = text.charAt( i );
+                    mnemonicIndex = result.length();
+                }
+            }
+            result.append( text.charAt( i ) );
+        }
+        component.setText( result.toString() );
+        if( haveMnemonic )
+        {
+            component.setMnemonic( mnemonic );
+            component.setDisplayedMnemonicIndex( mnemonicIndex );
+        }
+    }
+
+    public JComponent $$$getRootComponent$$$()
+    {
+        return contentPane;
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ServiceUsagePane.form b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ServiceUsagePane.form
new file mode 100644
index 0000000..86fb661
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ServiceUsagePane.form
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.apache.polygene.envisage.detail.ServiceUsagePane">
+  <grid id="27dc6" binding="contentPane" layout-manager="BorderLayout" hgap="0" vgap="0">
+    <constraints>
+      <xy x="20" y="20" width="374" height="274"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <scrollpane id="da4b1">
+        <constraints border-constraint="Center"/>
+        <properties/>
+        <border type="none"/>
+        <children>
+          <component id="7dfce" class="javax.swing.JTable" binding="usageTable">
+            <constraints/>
+            <properties/>
+          </component>
+        </children>
+      </scrollpane>
+    </children>
+  </grid>
+</form>
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ServiceUsagePane.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ServiceUsagePane.java
new file mode 100644
index 0000000..020c5d3
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/ServiceUsagePane.java
@@ -0,0 +1,338 @@
+/*
+ *  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.polygene.envisage.detail;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.event.MouseEvent;
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ResourceBundle;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.MouseInputAdapter;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableColumnModel;
+import org.apache.polygene.api.composite.DependencyDescriptor;
+import org.apache.polygene.envisage.event.LinkEvent;
+import org.apache.polygene.envisage.util.TableRow;
+import org.apache.polygene.envisage.util.TableRowUtilities;
+import org.apache.polygene.tools.model.descriptor.InjectedFieldDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ServiceDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ServiceUsage;
+import org.apache.polygene.tools.model.util.DescriptorUtilities;
+
+/**
+ * Service Usage tab, which shows all the 'users' of the Service,
+ * meaning the 'reverse' of a Dependency, all 'links' pointing into the Service should be listed here.
+ * The list should be in three 'sections' according to the Visibility,
+ * i.e. one section for all usages from within the same Module,
+ * one section for usages within the same Layer
+ * and one section for usages from Layers above.
+ * I think the order of these sections
+ * should be "LayersAbove", "WithinLayer" and "WithinModule"
+ * in that order from top.
+ */
+/* package */ final class ServiceUsagePane
+    extends DetailPane
+{
+    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( ServiceUsagePane.class.getName() );
+
+    private UsageTableModel usageTableModel;
+    private JTable usageTable;
+    private JPanel contentPane;
+
+    private Object linkObject;
+    private Cursor defaultCursor;
+    private Cursor linkCursor;
+
+    /* package */ ServiceUsagePane( DetailModelPane detailModelPane )
+    {
+        super( detailModelPane );
+        this.setLayout( new BorderLayout() );
+        this.add( contentPane, BorderLayout.CENTER );
+
+        usageTableModel = new UsageTableModel();
+        usageTable.setModel( usageTableModel );
+        usageTable.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
+
+        TableColumnModel columnModel = usageTable.getColumnModel();
+        columnModel.getColumn( 0 ).setCellRenderer( new OwnerCellRenderer() );
+        columnModel.getColumn( 1 ).setCellRenderer( new FieldCellRenderer() );
+
+        /*columnModel.getColumn( 0 ).setPreferredWidth( 90 );
+         columnModel.getColumn( 1 ).setPreferredWidth( 550 );
+         */
+        defaultCursor = getCursor();
+        linkCursor = LinkEvent.LINK_CURSOR;
+
+        MouseInputAdapter mouseInputListener = new MouseInputAdapter()
+        {
+            @Override
+            public void mouseMoved( MouseEvent evt )
+            {
+                // Column 1 is the Owner Column
+                int col = usageTable.columnAtPoint( evt.getPoint() );
+                if( col == 0 )
+                {
+                    setCursor( linkCursor );
+                }
+                else
+                {
+                    if( !getCursor().equals( defaultCursor ) )
+                    {
+                        setCursor( defaultCursor );
+                    }
+                }
+            }
+
+            @Override
+            public void mouseClicked( MouseEvent evt )
+            {
+                /*if( evt.getClickCount() < 2 )
+                 {
+                 return;
+                 }*/
+
+                int col = usageTable.columnAtPoint( evt.getPoint() );
+                if( col != 0 )
+                {
+                    return;
+                }
+
+                int row = usageTable.rowAtPoint( evt.getPoint() );
+                if( row < 0 )
+                {
+                    return;
+                }
+
+                linkObject = usageTableModel.getValueAt( row, col );
+                linkActivated();
+                linkObject = null;
+            }
+        };
+
+        usageTable.addMouseMotionListener( mouseInputListener );
+        usageTable.addMouseListener( mouseInputListener );
+    }
+
+    private void linkActivated()
+    {
+        if( linkObject == null )
+        {
+            return;
+        }
+        LinkEvent linkEvt = new LinkEvent( this, linkObject );
+        detailModelPane.fireLinkActivated( linkEvt );
+    }
+
+    @Override
+    protected void setDescriptor( Object objectDesciptor )
+    {
+        clear();
+
+        if( !( objectDesciptor instanceof ServiceDetailDescriptor ) )
+        {
+            return;
+        }
+
+        ServiceDetailDescriptor descriptor = (ServiceDetailDescriptor) objectDesciptor;
+
+        List<ServiceUsage> serviceUsages = DescriptorUtilities.findServiceUsage( descriptor );
+        usageTableModel.addRows( TableRowUtilities.toTableRows( serviceUsages ) );
+    }
+
+    private void clear()
+    {
+        linkObject = null;
+        usageTableModel.clear();
+    }
+
+    
+    {
+// GUI initializer generated by IntelliJ IDEA GUI Designer
+// >>> IMPORTANT!! <<<
+// DO NOT EDIT OR ADD ANY CODE HERE!
+        $$$setupUI$$$();
+    }
+
+    /**
+     * Method generated by IntelliJ IDEA GUI Designer
+     * >>> IMPORTANT!! <<<
+     * DO NOT edit this method OR call it in your code!
+     *
+     */
+    private void $$$setupUI$$$()
+    {
+        contentPane = new JPanel();
+        contentPane.setLayout( new BorderLayout( 0, 0 ) );
+        final JScrollPane scrollPane1 = new JScrollPane();
+        contentPane.add( scrollPane1, BorderLayout.CENTER );
+        usageTable = new JTable();
+        scrollPane1.setViewportView( usageTable );
+    }
+
+    public JComponent $$$getRootComponent$$$()
+    {
+        return contentPane;
+    }
+
+    private static class UsageTableModel
+        extends AbstractTableModel
+    {
+        /**
+         * the column names for this model
+         */
+        private static final String[] COLUMN_NAMES =
+        {
+            BUNDLE.getString( "Owner.Column" ),
+            BUNDLE.getString( "Usage.Column" ),
+            BUNDLE.getString( "Module.Column" ),
+            BUNDLE.getString( "Layer.Column" )
+        };
+        private final ArrayList<TableRow> rows;
+
+        private UsageTableModel()
+        {
+            rows = new ArrayList<>();
+        }
+
+        private void addRows( List<TableRow> rows )
+        {
+            int i1 = rows.size();
+            if( i1 > 0 )
+            {
+                i1--;
+            }
+
+            int i2 = 0;
+            for( TableRow row : rows )
+            {
+                this.rows.add( row );
+                i2++;
+            }
+
+            fireTableRowsInserted( i1, i1 + i2 );
+        }
+
+        /**
+         * Add row data
+         *
+         * @param row TableRow to be added
+         */
+        private void addRow( TableRow row )
+        {
+            int i1 = rows.size();
+            if( i1 > 0 )
+            {
+                i1--;
+            }
+
+            rows.add( row );
+            fireTableRowsInserted( i1, i1 + 1 );
+        }
+
+        @Override
+        public Object getValueAt( int rowIndex, int columnIndex )
+        {
+            TableRow row = rows.get( rowIndex );
+            return row.get( columnIndex );
+        }
+
+        private void clear()
+        {
+            rows.clear();
+            fireTableDataChanged();
+        }
+
+        @Override
+        public int getColumnCount()
+        {
+            return COLUMN_NAMES.length;
+        }
+
+        @Override
+        public String getColumnName( int col )
+        {
+            return COLUMN_NAMES[ col];
+        }
+
+        @Override
+        public int getRowCount()
+        {
+            return rows.size();
+        }
+    }
+
+    private static class OwnerCellRenderer
+        extends DefaultTableCellRenderer
+    {
+        @Override
+        public final Component getTableCellRendererComponent( JTable table,
+                                                              Object value,
+                                                              boolean isSelected,
+                                                              boolean hasFocus,
+                                                              int row,
+                                                              int column
+        )
+        {
+            if( value != null )
+            {
+                value = "<html><a href=\"" + value.toString() + "\">" + value.toString() + "</a></html>";
+            }
+
+            super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );
+
+            return this;
+        }
+    }
+
+    private static class FieldCellRenderer
+        extends DefaultTableCellRenderer
+    {
+        @Override
+        public final Component getTableCellRendererComponent( JTable table,
+                                                              Object value,
+                                                              boolean isSelected,
+                                                              boolean hasFocus,
+                                                              int row,
+                                                              int column
+        )
+        {
+            if( value != null )
+            {
+                InjectedFieldDetailDescriptor descriptor = (InjectedFieldDetailDescriptor) value;
+                DependencyDescriptor dependencyDescriptor = descriptor.descriptor().dependency();
+                Annotation annotation = dependencyDescriptor.injectionAnnotation();
+                value = descriptor.toString() + " (@" + annotation.annotationType().getSimpleName() + ")";
+            }
+
+            return super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );
+        }
+    }
+
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/StatePane.form b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/StatePane.form
new file mode 100644
index 0000000..9954302
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/StatePane.form
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.apache.polygene.envisage.detail.StatePane">
+  <grid id="27dc6" binding="contentPane" layout-manager="BorderLayout" hgap="0" vgap="0">
+    <constraints>
+      <xy x="20" y="20" width="500" height="400"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <splitpane id="e5c0d" binding="splitPane">
+        <constraints border-constraint="Center"/>
+        <properties/>
+        <border type="none"/>
+        <children>
+          <scrollpane id="321ea">
+            <constraints>
+              <splitpane position="left"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <component id="975eb" class="javax.swing.JList" binding="methodList">
+                <constraints/>
+                <properties/>
+              </component>
+            </children>
+          </scrollpane>
+          <scrollpane id="5fb60">
+            <constraints>
+              <splitpane position="right"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <component id="cc763" class="javax.swing.JTable" binding="methodDetailTable">
+                <constraints/>
+                <properties/>
+              </component>
+            </children>
+          </scrollpane>
+        </children>
+      </splitpane>
+    </children>
+  </grid>
+</form>
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/StatePane.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/StatePane.java
new file mode 100644
index 0000000..7f6df3c
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/StatePane.java
@@ -0,0 +1,373 @@
+/*
+ *  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.polygene.envisage.detail;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ResourceBundle;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.DefaultListModel;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JComponent;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableColumnModel;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.GenericAssociationInfo;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.property.GenericPropertyInfo;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.envisage.util.TableRow;
+import org.apache.polygene.tools.model.descriptor.CompositeDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.CompositeMethodDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.MethodConcernDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.MethodSideEffectDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ObjectDetailDescriptor;
+import org.apache.polygene.tools.model.util.DescriptorUtilities;
+
+/**
+ * Implementation of Composite State Panel
+ */
+/* package */ final class StatePane
+    extends DetailPane
+{
+    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( StatePane.class.getName() );
+
+    private JPanel contentPane;
+    private JList methodList;
+    private JSplitPane splitPane;
+    private JTable methodDetailTable;
+
+    private final DefaultListModel methodListModel;
+    private final MethodDetailTableModel methodDetailTableModel;
+
+    /* package */ StatePane( DetailModelPane detailModelPane )
+    {
+        super( detailModelPane );
+        this.setLayout( new BorderLayout() );
+        this.add( contentPane, BorderLayout.CENTER );
+
+        methodListModel = new DefaultListModel();
+        methodList.setModel( methodListModel );
+        methodList.setCellRenderer( new MethodListCellRenderer() );
+        methodList.setPrototypeCellValue( "12345678901234567890" );
+        methodList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
+
+        methodDetailTableModel = new MethodDetailTableModel();
+        methodDetailTable.setModel( methodDetailTableModel );
+
+        TableColumnModel columnModel = methodDetailTable.getColumnModel();
+        columnModel.getColumn( 0 ).setPreferredWidth( 75 );
+        columnModel.getColumn( 1 ).setPreferredWidth( 400 );
+
+        //splitPane.setDividerLocation( .1 );
+        methodList.addListSelectionListener( this::methodListValueChanged );
+    }
+
+    @Override
+    protected void setDescriptor( Object objectDesciptor )
+    {
+        clear();
+
+        if( objectDesciptor instanceof CompositeDetailDescriptor )
+        {
+            CompositeDetailDescriptor descriptor = ( (CompositeDetailDescriptor) objectDesciptor );
+            List<CompositeMethodDetailDescriptor> list = DescriptorUtilities.findState( descriptor );
+            for( CompositeMethodDetailDescriptor methodDescriptor : list )
+            {
+                methodListModel.addElement( methodDescriptor );
+            }
+
+            if( !methodListModel.isEmpty() )
+            {
+                methodList.setSelectedIndex( 0 );
+            }
+        }
+        else if( objectDesciptor instanceof ObjectDetailDescriptor )
+        {
+            // Object does not have state
+        }
+    }
+
+    private void clear()
+    {
+        methodListModel.clear();
+        methodDetailTableModel.clear();
+    }
+
+    private void methodListValueChanged( ListSelectionEvent evt )
+    {
+        if( evt.getValueIsAdjusting() )
+        {
+            return;
+        }
+        Object obj = methodList.getSelectedValue();
+        if( obj == null )
+        {
+            methodDetailTableModel.clear();
+            return;
+        }
+        methodDetailTableModel.reload( (CompositeMethodDetailDescriptor) obj );
+    }
+
+    
+    {
+// GUI initializer generated by IntelliJ IDEA GUI Designer
+// >>> IMPORTANT!! <<<
+// DO NOT EDIT OR ADD ANY CODE HERE!
+        $$$setupUI$$$();
+    }
+
+    /**
+     * Method generated by IntelliJ IDEA GUI Designer
+     * >>> IMPORTANT!! <<<
+     * DO NOT edit this method OR call it in your code!
+     *
+     */
+    private void $$$setupUI$$$()
+    {
+        contentPane = new JPanel();
+        contentPane.setLayout( new BorderLayout( 0, 0 ) );
+        splitPane = new JSplitPane();
+        contentPane.add( splitPane, BorderLayout.CENTER );
+        final JScrollPane scrollPane1 = new JScrollPane();
+        splitPane.setLeftComponent( scrollPane1 );
+        methodList = new JList();
+        scrollPane1.setViewportView( methodList );
+        final JScrollPane scrollPane2 = new JScrollPane();
+        splitPane.setRightComponent( scrollPane2 );
+        methodDetailTable = new JTable();
+        scrollPane2.setViewportView( methodDetailTable );
+    }
+
+    public JComponent $$$getRootComponent$$$()
+    {
+        return contentPane;
+    }
+
+    private static class MethodDetailTableModel
+        extends AbstractTableModel
+    {
+        /**
+         * the column names for this model
+         */
+        private static final String[] COLUMN_NAMES =
+        {
+            "Name",
+            "Value"
+        };
+        private final ArrayList<TableRow> rows;
+
+        private MethodDetailTableModel()
+        {
+            rows = new ArrayList<>();
+        }
+
+        private void reload( CompositeMethodDetailDescriptor descriptor )
+        {
+            clear();
+
+            // mixin type
+            rows.add( new TableRow( 2, "interface", descriptor.descriptor().method().getDeclaringClass().getSimpleName() ) );
+
+            StringBuilder str = new StringBuilder();
+            for( Annotation annotation : descriptor.descriptor().method().getAnnotations() )
+            {
+                String ann = annotation.toString();
+                ann = "@" + ann.substring( ann.lastIndexOf( '.' ) + 1 );
+                str.append( ann ).append( " " );
+            }
+            str.append( Classes.simpleGenericNameOf( descriptor.descriptor().method().getGenericReturnType() ) );
+
+            rows.add( new TableRow( 2, "return", str.toString() ) );
+
+            // concern
+            boolean first = true;
+            for( MethodConcernDetailDescriptor concern : descriptor.concerns().concerns() )
+            {
+                if( first )
+                {
+                    rows.add( new TableRow( 2, "concern", concern.toString() ) );
+                    first = false;
+                }
+                else
+                {
+                    rows.add( new TableRow( 2, "", concern.toString() ) );
+                }
+            }
+
+            // sideEffect
+            first = false;
+            for( MethodSideEffectDetailDescriptor sideEffect : descriptor.sideEffects().sideEffects() )
+            {
+                if( first )
+                {
+                    rows.add( new TableRow( 2, "sideEffect", sideEffect.toString() ) );
+                    first = false;
+                }
+                else
+                {
+                    rows.add( new TableRow( 2, "", sideEffect.toString() ) );
+                }
+            }
+
+            fireTableDataChanged();
+        }
+
+        @Override
+        public Object getValueAt( int rowIndex, int columnIndex )
+        {
+            TableRow row = this.rows.get( rowIndex );
+            return row.get( columnIndex );
+        }
+
+        private void clear()
+        {
+            rows.clear();
+            fireTableDataChanged();
+        }
+
+        @Override
+        public int getColumnCount()
+        {
+            return COLUMN_NAMES.length;
+        }
+
+        @Override
+        public String getColumnName( int col )
+        {
+            return COLUMN_NAMES[ col];
+        }
+
+        @Override
+        public int getRowCount()
+        {
+            return rows.size();
+        }
+    }
+
+    private static class MethodListCellRenderer
+        extends DefaultListCellRenderer
+    {
+        private final Icon publicIcon;
+        private final Icon privateIcon;
+
+        private MethodListCellRenderer()
+        {
+            try
+            {
+                publicIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Public" ) ) );
+                privateIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Private" ) ) );
+            }
+            catch( Exception ex )
+            {
+                throw new RuntimeException( ex );
+            }
+        }
+
+        @Override
+        public Component getListCellRendererComponent( JList list,
+                                                       Object value,
+                                                       int index,
+                                                       boolean isSelected,
+                                                       boolean cellHasFocus
+        )
+        {
+            super.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
+            if( !( value instanceof CompositeMethodDetailDescriptor ) )
+            {
+                return this;
+            }
+
+            Icon icon;
+            CompositeMethodDetailDescriptor descriptor = (CompositeMethodDetailDescriptor) value;
+            Class compositeClass = descriptor.composite().descriptor().types().findFirst().orElse( null );
+            Class mixinMethodClass = descriptor.descriptor().method().getDeclaringClass();
+            if( mixinMethodClass.isAssignableFrom( compositeClass ) )
+            {
+                icon = publicIcon;
+            }
+            else
+            {
+                icon = privateIcon;
+            }
+
+            if( icon != null )
+            {
+                setIcon( icon );
+            }
+
+            Method method = descriptor.descriptor().method();
+            Class<?> methodReturnType = method.getReturnType();
+
+            if( Property.class.isAssignableFrom( methodReturnType ) )
+            {
+                Type t = GenericPropertyInfo.propertyTypeOf( method );
+                if( t instanceof Class )
+                {
+                    setText( method.getName() + ":" + ( (Class) t ).getSimpleName() );
+                }
+            }
+            else if( Association.class.isAssignableFrom( methodReturnType ) )
+            {
+                Type t = GenericAssociationInfo.associationTypeOf( method );
+                if( t instanceof Class )
+                {
+                    setText( method.getName() + "->" + ( (Class) t ).getSimpleName() );
+                }
+            }
+            else if( ManyAssociation.class.isAssignableFrom( methodReturnType ) )
+            {
+                Type t = GenericAssociationInfo.associationTypeOf( method );
+                if( t instanceof Class )
+                {
+                    setText( method.getName() + "=>" + ( (Class) t ).getSimpleName() );
+                }
+            }
+            else if( NamedAssociation.class.isAssignableFrom( methodReturnType ) )
+            {
+                Type t = GenericAssociationInfo.associationTypeOf( method );
+                if( t instanceof Class )
+                {
+                    setText( method.getName() + ">>" + ( (Class) t ).getSimpleName() );
+                }
+            }
+
+            return this;
+        }
+    }
+
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/package.html b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/package.html
new file mode 100644
index 0000000..da559a8
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/detail/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Envisage Tool Detail UI.</h2>
+    </body>
+</html>
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/event/LinkEvent.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/event/LinkEvent.java
new file mode 100644
index 0000000..2f4e532
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/event/LinkEvent.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.envisage.event;
+
+import java.awt.Cursor;
+import java.util.EventObject;
+import javax.swing.text.html.HTMLEditorKit;
+
+public final class LinkEvent
+    extends EventObject
+{
+    public static final Cursor LINK_CURSOR = new HTMLEditorKit().getLinkCursor();
+
+    protected final Object object;
+
+    public LinkEvent( Object source, Object object )
+    {
+        super( source );
+        this.object = object;
+    }
+
+    public Object getObject()
+    {
+        return object;
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/event/LinkListener.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/event/LinkListener.java
new file mode 100644
index 0000000..3cb86db
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/event/LinkListener.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.envisage.event;
+
+import java.util.EventListener;
+
+public interface LinkListener
+    extends EventListener
+{
+    void activated( LinkEvent evt );
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/event/package.html b/tools/envisage/src/main/java/org/apache/polygene/envisage/event/package.html
new file mode 100644
index 0000000..ee1a72c
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/event/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Envisage Tool UI Events.</h2>
+    </body>
+</html>
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/GraphBuilder.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/GraphBuilder.java
new file mode 100644
index 0000000..935f768
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/GraphBuilder.java
@@ -0,0 +1,272 @@
+/*
+ *  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.polygene.envisage.graph;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.tools.model.descriptor.ApplicationDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.EntityDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ImportedServiceDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.LayerDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ModuleDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ObjectDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ServiceDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.TransientDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ValueDetailDescriptor;
+import org.apache.polygene.tools.model.util.DescriptorNameComparator;
+import prefuse.data.Edge;
+import prefuse.data.Graph;
+import prefuse.data.Node;
+import prefuse.data.Table;
+
+/**
+ * Build Apache Polygene application model as Prefuse Tree Graph
+ */
+/* package */ final class GraphBuilder
+{
+    private final DescriptorNameComparator<Object> nameComparator = new DescriptorNameComparator<>();
+    private final Graph graph;
+    private final List childList;
+
+    /* package */ static Graph buildGraph( ApplicationDetailDescriptor descriptor )
+    {
+        GraphBuilder builder = new GraphBuilder();
+        return builder.buildApplicationNode( descriptor );
+    }
+
+    /* package */ GraphBuilder()
+    {
+        graph = new Graph( true );
+
+        Table nodeTable = graph.getNodeTable();
+        nodeTable.addColumn( GraphDisplay.NAME_LABEL, String.class );
+        nodeTable.addColumn( GraphDisplay.USER_OBJECT, Object.class );
+
+        Table edgeTable = graph.getEdgeTable();
+        edgeTable.addColumn( GraphDisplay.USES_EDGES, boolean.class, false );
+
+        childList = new ArrayList();
+    }
+
+    private Graph buildApplicationNode( ApplicationDetailDescriptor descriptor )
+    {
+        Node node = addChild( null, descriptor.descriptor().name(), descriptor );
+
+        buildLayersNode( node, descriptor.layers() );
+        buildUsesNode( node, descriptor.layers() );
+
+        return graph;
+    }
+
+    private void buildUsesNode( Node parent, Iterable<LayerDetailDescriptor> iter )
+    {
+        for( LayerDetailDescriptor descriptor : iter )
+        {
+            Node source = findNode( parent, descriptor );
+
+            for( LayerDetailDescriptor usesDescriptor : descriptor.usedLayers() )
+            {
+                Node target = findNode( parent, usesDescriptor );
+                if( target == null )
+                {
+                    continue;
+                }
+                Edge edge = graph.addEdge( source, target );
+                edge.setBoolean( GraphDisplay.USES_EDGES, true );
+            }
+        }
+    }
+
+    private Node findNode( Node parent, Object userObject )
+    {
+        Node node = null;
+
+        for( int i = 0; i < parent.getChildCount(); i++ )
+        {
+            Node tNode = parent.getChild( i );
+            Object obj = tNode.get( GraphDisplay.USER_OBJECT );
+            if( obj.equals( userObject ) )
+            {
+                node = tNode;
+                break;
+            }
+        }
+
+        return node;
+    }
+
+    private Node addChild( Node parent, String name, Object object )
+    {
+        Node childNode = graph.addNode();
+        childNode.set( GraphDisplay.NAME_LABEL, name );
+        childNode.set( GraphDisplay.USER_OBJECT, object );
+
+        // check for application node
+        if( parent != null )
+        {
+            graph.addEdge( parent, childNode );
+        }
+        return childNode;
+    }
+
+    private void buildLayersNode( Node parent, Iterable<LayerDetailDescriptor> iter )
+    {
+        for( LayerDetailDescriptor descriptor : iter )
+        {
+            Node childNode = addChild( parent, descriptor.descriptor().name(), descriptor );
+            buildModulesNode( childNode, descriptor.modules() );
+        }
+    }
+
+    private void buildModulesNode( Node parent, Iterable<ModuleDetailDescriptor> iter )
+    {
+        for( ModuleDetailDescriptor descriptor : iter )
+        {
+            Node childNode = addChild( parent, descriptor.descriptor().name(), descriptor );
+
+            buildServicesNode( childNode, descriptor.services() );
+            buildImportedServicesNode( childNode, descriptor.importedServices() );
+            buildEntitiesNode( childNode, descriptor.entities() );
+            buildTransientsNode( childNode, descriptor.transients() );
+            buildValuesNode( childNode, descriptor.values() );
+            buildObjectsNode( childNode, descriptor.objects() );
+        }
+    }
+
+    private void sortTypeChildren( Iterable iter )
+    {
+        childList.clear();
+        for( Object obj : iter )
+        {
+            childList.add( obj );
+        }
+
+        childList.sort( nameComparator );
+    }
+
+    private void buildServicesNode( Node parent, Iterable<ServiceDetailDescriptor> iter )
+    {
+        sortTypeChildren( iter );
+
+        boolean first = true;
+        for( Object obj : childList )
+        {
+            ServiceDetailDescriptor descriptor = (ServiceDetailDescriptor) obj;
+            if( first )
+            {
+                String name = "Services";
+                parent = addChild( parent, name, name );
+                first = false;
+            }
+            addChild( parent, descriptor.descriptor().toString(), descriptor );
+        }
+    }
+
+    private void buildImportedServicesNode( Node parent, Iterable<ImportedServiceDetailDescriptor> iter )
+    {
+        sortTypeChildren( iter );
+
+        boolean first = true;
+        for( Object obj : childList )
+        {
+            ImportedServiceDetailDescriptor descriptor = (ImportedServiceDetailDescriptor) obj;
+            if( first )
+            {
+                String name = "Imported Services";
+                parent = addChild( parent, name, name );
+                first = false;
+            }
+            addChild( parent, descriptor.descriptor().primaryType().getSimpleName(), descriptor );
+        }
+    }
+
+    private void buildEntitiesNode( Node parent, Iterable<EntityDetailDescriptor> iter )
+    {
+        sortTypeChildren( iter );
+
+        boolean first = true;
+        for( Object obj : childList )
+        {
+            EntityDetailDescriptor descriptor = (EntityDetailDescriptor) obj;
+            if( first )
+            {
+                String name = "Entities";
+                parent = addChild( parent, name, name );
+                first = false;
+            }
+            addChild( parent, descriptor.descriptor().toString(), descriptor );
+        }
+    }
+
+    private void buildTransientsNode( Node parent, Iterable<TransientDetailDescriptor> iter )
+    {
+        sortTypeChildren( iter );
+
+        boolean first = true;
+        for( Object obj : childList )
+        {
+            TransientDetailDescriptor descriptor = (TransientDetailDescriptor) obj;
+            if( first )
+            {
+                String name = "Transients";
+                parent = addChild( parent, name, name );
+                first = false;
+            }
+            addChild( parent, descriptor.descriptor().toString(), descriptor );
+        }
+    }
+
+    private void buildValuesNode( Node parent, Iterable<ValueDetailDescriptor> iter )
+    {
+        sortTypeChildren( iter );
+
+        boolean first = true;
+        for( Object obj : childList )
+        {
+            ValueDetailDescriptor descriptor = (ValueDetailDescriptor) obj;
+            if( first )
+            {
+                String name = "Values";
+                parent = addChild( parent, name, name );
+                first = false;
+            }
+            addChild( parent, descriptor.descriptor().toString(), descriptor );
+        }
+    }
+
+    private void buildObjectsNode( Node parent, Iterable<ObjectDetailDescriptor> iter )
+    {
+        sortTypeChildren( iter );
+
+        boolean first = true;
+        for( Object obj : childList )
+        {
+            ObjectDetailDescriptor descriptor = (ObjectDetailDescriptor) obj;
+            if( first )
+            {
+                String name = "Objects";
+                parent = addChild( parent, name, name );
+                first = false;
+            }
+            addChild( parent, descriptor.descriptor().toString(), descriptor );
+        }
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/GraphDisplay.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/GraphDisplay.java
new file mode 100644
index 0000000..32d7d9a
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/GraphDisplay.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.envisage.graph;
+
+import org.apache.polygene.envisage.event.LinkEvent;
+import org.apache.polygene.envisage.event.LinkListener;
+import prefuse.Display;
+import prefuse.Visualization;
+import prefuse.data.Graph;
+
+public abstract class GraphDisplay
+    extends Display
+{
+    public static final String NAME_LABEL = "name";
+    public static final String USER_OBJECT = "userObject";
+
+    public static final String GRAPH = "graph";
+    public static final String GRAPH_NODES = "graph.nodes";
+    public static final String GRAPH_EDGES = "graph.edges";
+    public static final String USES_EDGES = "uses.edges";
+
+    protected GraphDisplay( Visualization visualization )
+    {
+        super( visualization );
+    }
+
+    public abstract void run( Graph graph );
+
+    public abstract void run();
+
+    public abstract void setSelectedValue( Object object );
+
+    /**
+     * Add a listener that's notified each time a change to the selection occurs.
+     *
+     * @param listener the LinkListener to add
+     */
+    public final void addLinkListener( LinkListener listener )
+    {
+        listenerList.add( LinkListener.class, listener );
+    }
+
+    /**
+     * Remove a listener from the list that's notified each time a change to the selection occurs.
+     *
+     * @param listener the LinkListener to remove
+     */
+    public final void removeLinkListener( LinkListener listener )
+    {
+        listenerList.remove( LinkListener.class, listener );
+    }
+
+    protected final void fireLinkActivated( LinkEvent evt )
+    {
+        // Guaranteed to return a non-null array
+        Object[] listeners = listenerList.getListenerList();
+        // Process the listeners last to first, notifying
+        // those that are interested in this event
+        for( int i = listeners.length - 2; i >= 0; i -= 2 )
+        {
+            if( listeners[i] == LinkListener.class )
+            {
+                ( (LinkListener) listeners[i + 1] ).activated( evt );
+            }
+        }
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/GraphPane.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/GraphPane.java
new file mode 100644
index 0000000..feac087
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/GraphPane.java
@@ -0,0 +1,153 @@
+/*
+ *  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.polygene.envisage.graph;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import org.apache.polygene.envisage.event.LinkEvent;
+import org.apache.polygene.envisage.event.LinkListener;
+import org.apache.polygene.tools.model.descriptor.ApplicationDetailDescriptor;
+import prefuse.data.Graph;
+
+/**
+ * Just a simple wrapper for ApplicationModel Graph Display
+ */
+public final class GraphPane
+    extends JPanel
+{
+    private TreeGraphDisplay treeDisplay;
+    private final StackedGraphDisplay stackedDisplay;
+    private final List<GraphDisplay> displays;
+
+    private JTabbedPane tabPane;
+    private final JScrollPane scrollPane;
+
+    public GraphPane()
+    {
+        treeDisplay = new TreeGraphDisplay();
+        stackedDisplay = new StackedGraphDisplay();
+
+        List<GraphDisplay> tmpList = new ArrayList<>( 2 );
+        tmpList.add( treeDisplay );
+        tmpList.add( stackedDisplay );
+        displays = Collections.unmodifiableList( tmpList );
+
+        scrollPane = new JScrollPane();
+        scrollPane.setViewportView( stackedDisplay );
+        int unitInc = 50;
+        scrollPane.getVerticalScrollBar().setUnitIncrement( unitInc );
+        scrollPane.getHorizontalScrollBar().setUnitIncrement( unitInc );
+
+        tabPane = new JTabbedPane();
+        tabPane.add( "Tree", treeDisplay );
+        tabPane.add( "Stacked", scrollPane );
+
+        this.setLayout( new BorderLayout() );
+        add( tabPane, BorderLayout.CENTER );
+
+        treeDisplay.addLinkListener( this::graphItemLinkActivated );
+
+        stackedDisplay.addLinkListener( this::graphItemLinkActivated );
+
+        this.addComponentListener( new ComponentAdapter()
+        {
+            @Override
+            public void componentResized( ComponentEvent evt )
+            {
+                Dimension size = GraphPane.this.getSize();
+                treeDisplay.setSize( size.width, size.height );
+                tabPane.revalidate();
+                tabPane.repaint();
+            }
+        } );
+    }
+
+    public void initPolygene( ApplicationDetailDescriptor descriptor )
+    {
+        Graph graph = GraphBuilder.buildGraph( descriptor );
+        Dimension size = getSize();
+        treeDisplay.setSize( size.width, size.height );
+        treeDisplay.run( graph );
+
+        graph = GraphBuilder.buildGraph( descriptor );
+        stackedDisplay.setSize( size.width, size.height );
+        stackedDisplay.run( graph );
+    }
+
+    public void refresh()
+    {
+        treeDisplay.run();
+        stackedDisplay.run();
+    }
+
+    public List<GraphDisplay> getGraphDisplays()
+    {
+        return displays;
+    }
+
+    public void setSelectedValue( Object obj )
+    {
+        treeDisplay.setSelectedValue( obj );
+        stackedDisplay.setSelectedValue( obj );
+    }
+
+    private void graphItemLinkActivated( LinkEvent evt )
+    {
+        if( evt.getSource().equals( treeDisplay ) )
+        {
+            stackedDisplay.setSelectedValue( evt.getObject() );
+        }
+        else if( evt.getSource().equals( stackedDisplay ) )
+        {
+            treeDisplay.setSelectedValue( evt.getObject() );
+        }
+    }
+
+    /**
+     * Add a listener from the list that's notified each time a change to the selection occurs.
+     *
+     * @param listener the LinkListener to add
+     */
+    public void addLinkListener( LinkListener listener )
+    {
+        treeDisplay.addLinkListener( listener );
+        stackedDisplay.addLinkListener( listener );
+    }
+
+    /**
+     * Remove a listener from the list that's notified each time a change to the selection occurs.
+     *
+     * @param listener the LinkListener to remove
+     */
+    public void removeLinkListener( LinkListener listener )
+    {
+        treeDisplay.removeLinkListener( listener );
+        stackedDisplay.removeLinkListener( listener );
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/StackedGraphDisplay.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/StackedGraphDisplay.java
new file mode 100644
index 0000000..24fa2fa
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/StackedGraphDisplay.java
@@ -0,0 +1,581 @@
+/*
+ *  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.polygene.envisage.graph;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Shape;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Rectangle2D;
+import java.util.Iterator;
+import javax.swing.JViewport;
+import javax.swing.SwingUtilities;
+import org.apache.polygene.envisage.event.LinkEvent;
+import prefuse.Constants;
+import prefuse.Visualization;
+import prefuse.action.Action;
+import prefuse.action.ActionList;
+import prefuse.action.ItemAction;
+import prefuse.action.RepaintAction;
+import prefuse.action.assignment.ColorAction;
+import prefuse.action.layout.Layout;
+import prefuse.activity.Activity;
+import prefuse.controls.ControlAdapter;
+import prefuse.controls.FocusControl;
+import prefuse.controls.PanControl;
+import prefuse.data.Graph;
+import prefuse.data.Schema;
+import prefuse.data.expression.Predicate;
+import prefuse.data.expression.parser.ExpressionParser;
+import prefuse.data.tuple.TupleSet;
+import prefuse.render.AbstractShapeRenderer;
+import prefuse.render.DefaultRendererFactory;
+import prefuse.render.EdgeRenderer;
+import prefuse.render.LabelRenderer;
+import prefuse.util.ColorLib;
+import prefuse.util.ColorMap;
+import prefuse.util.FontLib;
+import prefuse.util.PrefuseLib;
+import prefuse.visual.DecoratorItem;
+import prefuse.visual.EdgeItem;
+import prefuse.visual.NodeItem;
+import prefuse.visual.VisualItem;
+import prefuse.visual.expression.InGroupPredicate;
+import prefuse.visual.sort.TreeDepthItemSorter;
+
+/* package */ class StackedGraphDisplay
+    extends GraphDisplay
+{
+    /* package */ static final Font FONT = FontLib.getFont( "Tahoma", 12 );
+
+    // create data description of LABELS, setting colors, fonts ahead of time
+    private static final Schema LABEL_SCHEMA = PrefuseLib.getVisualItemSchema();
+
+    static
+    {
+        LABEL_SCHEMA.setDefault( VisualItem.INTERACTIVE, false );
+        LABEL_SCHEMA.setDefault( VisualItem.TEXTCOLOR, ColorLib.rgb( 255, 255, 255 ) );
+        LABEL_SCHEMA.setDefault( VisualItem.FONT, FONT );
+    }
+
+    private static final String LABELS = "labels";
+
+    private static final String LAYOUT_ACTION = "layout";
+    private static final String COLORS_ACTION = "colors";
+    private static final String AUTO_PAN_ACTION = "autoPan";
+
+    private static int OUTLINE_COLOR = ColorLib.rgb( 33, 115, 170 );
+    private static int OUTLINE_FOCUS_COLOR = ColorLib.rgb( 255, 255, 255 );  // alternative color ColorLib.rgb(150,200,200);
+
+    private StackedLayout stackedLayout;
+
+    private Activity activity;
+
+    /* package */ StackedGraphDisplay()
+    {
+        super( new Visualization() );
+
+        setBackground( ColorLib.getColor( 0, 51, 88 ) );
+
+        LabelRenderer labelRenderer = new LabelRenderer( NAME_LABEL );
+        labelRenderer.setVerticalAlignment( Constants.BOTTOM );
+        labelRenderer.setHorizontalAlignment( Constants.LEFT );
+
+        EdgeRenderer usesRenderer = new EdgeRenderer( Constants.EDGE_TYPE_CURVE, Constants.EDGE_ARROW_FORWARD );
+        usesRenderer.setHorizontalAlignment1( Constants.CENTER );
+        usesRenderer.setHorizontalAlignment2( Constants.CENTER );
+        usesRenderer.setVerticalAlignment1( Constants.BOTTOM );
+        usesRenderer.setVerticalAlignment2( Constants.TOP );
+
+        Predicate usesPredicate = (Predicate) ExpressionParser.parse( "ingroup('graph.edges') AND [" + USES_EDGES + "]==true", true );
+
+        // set up the renderers - one for nodes and one for LABELS
+        DefaultRendererFactory rf = new DefaultRendererFactory();
+        rf.add( new InGroupPredicate( GRAPH_NODES ), new NodeRenderer() );
+        rf.add( new InGroupPredicate( LABELS ), labelRenderer );
+        rf.add( usesPredicate, usesRenderer );
+        m_vis.setRendererFactory( rf );
+
+        // border colors
+        ColorAction borderColor = new BorderColorAction( GRAPH_NODES );
+        ColorAction fillColor = new FillColorAction( GRAPH_NODES );
+
+        // uses edge colors
+        ItemAction usesColor = new ColorAction( GRAPH_EDGES, usesPredicate, VisualItem.STROKECOLOR, ColorLib.rgb( 50, 50, 50 ) );
+        ItemAction usesArrow = new ColorAction( GRAPH_EDGES, usesPredicate, VisualItem.FILLCOLOR, ColorLib.rgb( 50, 50, 50 ) );
+
+        // color settings
+        ActionList colors = new ActionList();
+        colors.add( fillColor );
+        colors.add( borderColor );
+        colors.add( usesColor );
+        colors.add( usesArrow );
+        m_vis.putAction( COLORS_ACTION, colors );
+
+        ActionList autoPan = new ActionList();
+        autoPan.add( colors );
+        autoPan.add( new AutoPanAction() );
+        autoPan.add( new RepaintAction() );
+        m_vis.putAction( AUTO_PAN_ACTION, autoPan );
+
+        // create the layout action list
+        stackedLayout = new StackedLayout( GRAPH );
+        ActionList layout = new ActionList();
+        layout.add( stackedLayout );
+        layout.add( new LabelLayout( LABELS ) );
+        layout.add( autoPan );
+        m_vis.putAction( LAYOUT_ACTION, layout );
+
+        // initialize our display
+        Dimension size = new Dimension( 400, 400 );
+        setSize( size );
+        setPreferredSize( size );
+        setItemSorter( new ExtendedTreeDepthItemSorter( true ) );
+        addControlListener( new HoverControl() );
+        addControlListener( new FocusControl( 1, COLORS_ACTION ) );
+        addControlListener( new WheelMouseControl() );
+        addControlListener( new PanControl( true ) );
+        addControlListener( new ItemSelectionControl() );
+
+        setDamageRedraw( true );
+    }
+
+    @Override
+    public void run( Graph graph )
+    {
+        // add the GRAPH to the visualization
+        m_vis.add( GRAPH, graph );
+
+        // hide edges
+        Predicate edgesPredicate = (Predicate) ExpressionParser.parse( "ingroup('graph.edges') AND [" + USES_EDGES + "]==false", true );
+        m_vis.setVisible( GRAPH_EDGES, edgesPredicate, false );
+
+        m_vis.setInteractive( GRAPH_EDGES, null, false );
+
+        // make node interactive
+        m_vis.setInteractive( GRAPH_NODES, null, true );
+
+        // add LABELS to the visualization
+        Predicate labelP = (Predicate) ExpressionParser.parse( "VISIBLE()" );
+        m_vis.addDecorators( LABELS, GRAPH_NODES, labelP, LABEL_SCHEMA );
+
+        run();
+    }
+
+    @Override
+    public void run()
+    {
+        if( isInProgress() )
+        {
+            return;
+        }
+
+        // perform layout
+        m_vis.invalidate( GRAPH_NODES );
+        activity = m_vis.run( LAYOUT_ACTION );
+    }
+
+    @Override
+    public void setSelectedValue( Object object )
+    {
+        if( object == null )
+        {
+            return;
+        }
+
+        NodeItem item = null;
+
+        Iterator iter = m_vis.items( GRAPH_NODES );
+        while( iter.hasNext() )
+        {
+            NodeItem tItem = (NodeItem) iter.next();
+            Object tObj = tItem.get( USER_OBJECT );
+            if( tObj.equals( object ) )
+            {
+                item = tItem;
+                break;
+            }
+        }
+
+        if( item != null )
+        {
+            int depth = item.getDepth();
+            boolean relayout = false;
+            if( depth > stackedLayout.getZoom() )
+            {
+                stackedLayout.zoom( depth );
+                relayout = true;
+            }
+
+            TupleSet ts = m_vis.getFocusGroup( Visualization.FOCUS_ITEMS );
+            ts.setTuple( item );
+            if( relayout )
+            {
+                run();
+            }
+            else
+            {
+                m_vis.run( AUTO_PAN_ACTION );
+            }
+        }
+    }
+
+    private void zoomIn()
+    {
+        if( isInProgress() )
+        {
+            return;
+        }
+
+        stackedLayout.zoomIn();
+        run();
+    }
+
+    private void zoomOut()
+    {
+        if( isInProgress() )
+        {
+            return;
+        }
+
+        stackedLayout.zoomOut();
+        run();
+    }
+
+    private boolean isInProgress()
+    {
+        if( isTranformInProgress() )
+        {
+            return true;
+        }
+
+        if( activity != null )
+        {
+            if( activity.isRunning() )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    // ------------------------------------------------------------------------
+    /**
+     * Set the stroke color for drawing border node outlines.
+     */
+    private static class BorderColorAction
+        extends ColorAction
+    {
+
+        private BorderColorAction( String group )
+        {
+            super( group, VisualItem.STROKECOLOR );
+        }
+
+        @Override
+        public int getColor( VisualItem item )
+        {
+            if( !( item instanceof NodeItem ) )
+            {
+                return 0;
+            }
+            NodeItem nItem = (NodeItem) item;
+            if( m_vis.isInGroup( nItem, Visualization.FOCUS_ITEMS ) )
+            {
+                return OUTLINE_FOCUS_COLOR;
+            }
+
+            return OUTLINE_COLOR;
+        }
+    }
+
+    /**
+     * Set fill colors for treemap nodes. Normal nodes are shaded according to their
+     * depth in the tree.
+     */
+    private static class FillColorAction
+        extends ColorAction
+    {
+        private static final ColorMap CMAP = new ColorMap( new int[]
+        {
+            ColorLib.rgb( 11, 117, 188 ),
+            ColorLib.rgb( 8, 99, 160 ),
+            ColorLib.rgb( 5, 77, 126 ),
+            ColorLib.rgb( 2, 61, 100 ),
+            ColorLib.rgb( 148, 55, 87 )
+        }, 0, 4 );
+
+        private FillColorAction( String group )
+        {
+            super( group, VisualItem.FILLCOLOR );
+        }
+
+        @Override
+        public int getColor( VisualItem item )
+        {
+            if( item instanceof NodeItem )
+            {
+                NodeItem nItem = (NodeItem) item;
+                if( m_vis.isInGroup( nItem, Visualization.FOCUS_ITEMS ) )
+                {
+                    int c = CMAP.getColor( nItem.getDepth() );
+                    return ColorLib.darker( c );
+                }
+                return CMAP.getColor( nItem.getDepth() );
+            }
+            else
+            {
+                return CMAP.getColor( 0 );
+            }
+        }
+    } // end of inner class FillColorAction
+
+    private static class HoverControl
+        extends ControlAdapter
+    {
+        @Override
+        public void itemEntered( VisualItem item, MouseEvent evt )
+        {
+            item.setStrokeColor( OUTLINE_FOCUS_COLOR );
+            item.getVisualization().repaint();
+        }
+
+        @Override
+        public void itemExited( VisualItem item, MouseEvent evt )
+        {
+            item.setStrokeColor( item.getEndStrokeColor() );
+            item.getVisualization().repaint();
+        }
+    }
+
+    /**
+     * Set label positions. Labels are assumed to be DecoratorItem instances,
+     * decorating their respective nodes. The layout simply gets the bounds
+     * of the decorated node and assigns the label coordinates to the center
+     * of those bounds.
+     */
+    private static class LabelLayout
+        extends Layout
+    {
+        private LabelLayout( String group )
+        {
+            super( group );
+        }
+
+        @Override
+        public void run( double frac )
+        {
+            Iterator iter = m_vis.items( m_group );
+            while( iter.hasNext() )
+            {
+                DecoratorItem item = (DecoratorItem) iter.next();
+                VisualItem node = item.getDecoratedItem();
+                Rectangle2D bounds = node.getBounds();
+                setX( item, node, bounds.getX() + StackedLayout.INSET );
+                setY( item, node, bounds.getY() + StackedLayout.INSET + 12 );
+            }
+        }
+    } // end of inner class LabelLayout
+
+    /**
+     * A renderer for treemap nodes. Draws simple rectangles, but defers
+     * the bounds management to the layout.
+     */
+    private static class NodeRenderer
+        extends AbstractShapeRenderer
+    {
+        private Rectangle2D m_bounds = new Rectangle2D.Double();
+
+        private NodeRenderer()
+        {
+            m_manageBounds = false;
+        }
+
+        @Override
+        protected Shape getRawShape( VisualItem item )
+        {
+            m_bounds.setRect( item.getBounds() );
+            return m_bounds;
+        }
+    } // end of inner class NodeRenderer
+
+    private class WheelMouseControl
+        extends ControlAdapter
+    {
+        @Override
+        public void itemWheelMoved( VisualItem item, MouseWheelEvent evt )
+        {
+            zoom( evt.getWheelRotation() );
+        }
+
+        @Override
+        public void mouseWheelMoved( MouseWheelEvent evt )
+        {
+            zoom( evt.getWheelRotation() );
+        }
+
+        private void zoom( final int rotation )
+        {
+            SwingUtilities.invokeLater(
+                () ->
+                {
+                    if( rotation == 0 )
+                    {
+                        return;
+                    }
+                    if( rotation < 0 )
+                    {
+                        zoomOut();
+                    }
+                    else
+                    {
+                        zoomIn();
+                    }
+                } );
+        }
+    }
+
+    private class ItemSelectionControl
+        extends ControlAdapter
+    {
+        @Override
+        public final void itemClicked( VisualItem anItem, MouseEvent anEvent )
+        {
+            // update the display
+            anItem.getVisualization().repaint();
+
+            if( !anItem.canGet( USER_OBJECT, Object.class ) )
+            {
+                return;
+            }
+
+            Object object = anItem.get( USER_OBJECT );
+            LinkEvent evt = new LinkEvent( StackedGraphDisplay.this, object );
+            fireLinkActivated( evt );
+        }
+    }
+
+    private class AutoPanAction
+        extends Action
+    {
+        @Override
+        public void run( double frac )
+        {
+            Rectangle2D displayBounds = new Rectangle2D.Double( 0, 0, getWidth(), getHeight() );
+
+            Container container = getParent();
+            if( container == null )
+            {
+                return;
+            }
+
+            // HACK check the container size
+            if( container instanceof JViewport )
+            {
+                Dimension size = ( (JViewport) container ).getExtentSize();
+                displayBounds.setRect( 0, 0, size.getWidth(), size.getHeight() );
+            }
+            else
+            {
+                Dimension size = container.getSize();
+                displayBounds.setRect( 0, 0, size.getWidth(), size.getHeight() );
+            }
+
+            Rectangle2D bounds = stackedLayout.getLayoutRoot().getBounds();
+
+            // Pan center
+            double x = ( displayBounds.getWidth() - bounds.getWidth() ) / 2;
+            double y = ( displayBounds.getHeight() - bounds.getHeight() ) / 2;
+
+            // reset the transform
+            try
+            {
+                setTransform( new AffineTransform() );
+            }
+            catch( NoninvertibleTransformException ex )
+            {
+                return;
+            }
+            if( x < 0 )
+            {
+                x = 0;
+            }
+
+            if( y < 0 )
+            {
+                y = 0;
+            }
+            pan( x, y );
+
+            TupleSet ts = m_vis.getFocusGroup( Visualization.FOCUS_ITEMS );
+            if( ts.getTupleCount() != 0 )
+            {
+                // get the first selected item and pan center it
+                VisualItem vi = (VisualItem) ts.tuples().next();
+
+                //update scrollbar position
+                if( container instanceof JViewport )
+                {
+                    // TODO there is a bug on Swing scrollRectToVisible
+                    ( (JViewport) container ).scrollRectToVisible( vi.getBounds().getBounds() );
+                }
+            }
+        }
+    }
+
+    /**
+     * ExtenedTreeDepthItemSorter to alter the default ordering/sorter,
+     * to make sure Edge item is drawn in front. This is for Edge Uses
+     */
+    private static class ExtendedTreeDepthItemSorter
+        extends TreeDepthItemSorter
+    {
+        private ExtendedTreeDepthItemSorter()
+        {
+            this( false );
+        }
+
+        private ExtendedTreeDepthItemSorter( boolean childrenAbove )
+        {
+            super( childrenAbove );
+        }
+
+        @Override
+        public int score( VisualItem item )
+        {
+            int score = super.score( item );
+            if( item instanceof EdgeItem )
+            {
+                // make it drawn in front of NODE
+                score = ( 1 << ( 25 + EDGE + NODE ) );
+            }
+
+            return score;
+        }
+    }
+
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/StackedLayout.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/StackedLayout.java
new file mode 100644
index 0000000..20957ea
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/StackedLayout.java
@@ -0,0 +1,224 @@
+/*
+ *  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.polygene.envisage.graph;
+
+import java.awt.Dimension;
+import java.awt.FontMetrics;
+import java.awt.geom.Area;
+import java.awt.geom.Rectangle2D;
+import prefuse.Display;
+import prefuse.action.layout.graph.TreeLayout;
+import prefuse.render.Renderer;
+import prefuse.visual.NodeItem;
+
+/* package */ final class StackedLayout
+    extends TreeLayout
+{
+    /* package */ static int INSET = 10;
+
+    private int zoom = 2;
+
+    /* package */ StackedLayout( String group )
+    {
+        super( group );
+    }
+
+    @Override
+    public void run( double frac )
+    {
+        // setup
+        NodeItem root = getLayoutRoot();
+        layout( root, 0, 0 );
+
+        Rectangle2D bounds = root.getBounds();
+        Display display = this.getVisualization().getDisplay( 0 );
+        Dimension size = new Dimension( (int) bounds.getWidth(), (int) bounds.getHeight() );
+        display.setSize( size );
+
+        if( !display.isValid() )
+        {
+            display.validate();
+        }
+    }
+
+    /* package */ void zoomOut()
+    {
+        zoom--;
+        if( zoom < 1 )
+        {
+            zoom = 1;
+        }
+    }
+
+    /* package */ void zoomIn()
+    {
+        zoom++;
+        if( zoom > 4 )
+        {
+            zoom = 4;
+        }
+    }
+
+    /* package */ void zoom( int zoom )
+    {
+        this.zoom = zoom;
+    }
+
+    /* package */ int getZoom()
+    {
+        return zoom;
+    }
+
+    private Dimension getItemMinSize( NodeItem node, Dimension minSize )
+    {
+        if( minSize == null )
+        {
+            minSize = new Dimension( 0, 0 );
+        }
+
+        String label = node.getString( "name" );
+        FontMetrics fm = Renderer.DEFAULT_GRAPHICS.getFontMetrics( StackedGraphDisplay.FONT );
+        int width = fm.stringWidth( label );
+        int height = fm.getHeight();
+        minSize.setSize( width + INSET + INSET, height + INSET + INSET );
+
+        return minSize;
+    }
+
+    private void layout( NodeItem node, double x, double y )
+    {
+        Dimension minSize = getItemMinSize( node, null );
+        node.setBounds( x, y, minSize.width, minSize.height );
+
+        int depth = node.getDepth();
+
+        if( depth > zoom )
+        {
+            node.setBounds( x, y, 0, 0 );
+            node.setVisible( false );
+        }
+        else
+        {
+            node.setVisible( true );
+        }
+
+        double cx = x + INSET;
+        double cy = y + minSize.height;
+
+        Area area = new Area( node.getBounds() );
+
+        boolean hasChild = false;
+        for( int i = 0; i < node.getChildCount(); i++ )
+        {
+            hasChild = true;
+            NodeItem child = (NodeItem) node.getChild( i );
+
+            layout( child, cx, cy );
+            area.add( new Area( child.getBounds() ) );
+
+            // shifting location calculation
+            Rectangle2D nodeRect = child.getBounds();
+            if( depth == 0 )
+            {
+                // layer
+                cy = cy + ( INSET * 2 ) + nodeRect.getHeight();
+            }
+            if( depth == 1 )
+            {
+                // module
+                cx = cx + INSET + nodeRect.getWidth();
+            }
+            else if( depth == 2 )
+            {
+                // type container
+                cx = cx + INSET + nodeRect.getWidth();
+            }
+            else if( depth == 3 )
+            {
+                // type
+                cy = cy + INSET + nodeRect.getHeight();
+            }
+        }
+
+        Rectangle2D bounds = area.getBounds2D();
+        if( hasChild && depth <= zoom )
+        {
+            bounds.setRect( x, y, bounds.getWidth() + INSET, bounds.getHeight() + INSET );
+        }
+
+        node.setBounds( x, y, bounds.getWidth(), bounds.getHeight() );
+
+        // relayout the child so it have consistent width or height
+        //int depth = parent.getDepth();
+        if( depth == 0 )
+        {
+            arrangeChildVertically( node );
+        }
+        else if( depth == 1 )
+        {
+            arrangeChildHorizontally( node );
+        }
+        else if( depth == 2 )
+        {
+            arrangeChildHorizontally( node );
+        }
+        else if( depth == 3 )
+        {
+            arrangeChildVertically( node );
+        }
+    }
+
+    private void arrangeChildVertically( NodeItem parent )
+    {
+        double maxW = 0;
+        for( int i = 0; i < parent.getChildCount(); i++ )
+        {
+            NodeItem node = (NodeItem) parent.getChild( i );
+            Rectangle2D bounds = node.getBounds();
+            maxW = Math.max( maxW, bounds.getWidth() );
+        }
+
+        for( int i = 0; i < parent.getChildCount(); i++ )
+        {
+            NodeItem node = (NodeItem) parent.getChild( i );
+            Rectangle2D bounds = node.getBounds();
+            node.setBounds( bounds.getX(), bounds.getY(), maxW, bounds.getHeight() );
+        }
+    }
+
+    private void arrangeChildHorizontally( NodeItem parent )
+    {
+        double maxH = 0;
+        for( int i = 0; i < parent.getChildCount(); i++ )
+        {
+            NodeItem node = (NodeItem) parent.getChild( i );
+            Rectangle2D bounds = node.getBounds();
+            maxH = Math.max( maxH, bounds.getHeight() );
+        }
+
+        for( int i = 0; i < parent.getChildCount(); i++ )
+        {
+            NodeItem node = (NodeItem) parent.getChild( i );
+            Rectangle2D bounds = node.getBounds();
+            node.setBounds( bounds.getX(), bounds.getY(), bounds.getWidth(), maxH );
+        }
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/TreeGraphDisplay.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/TreeGraphDisplay.java
new file mode 100644
index 0000000..457dea9
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/TreeGraphDisplay.java
@@ -0,0 +1,391 @@
+/*
+ *  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.polygene.envisage.graph;
+
+import java.awt.Color;
+import java.awt.event.MouseEvent;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.Iterator;
+import org.apache.polygene.envisage.event.LinkEvent;
+import prefuse.Constants;
+import prefuse.Visualization;
+import prefuse.action.Action;
+import prefuse.action.ActionList;
+import prefuse.action.ItemAction;
+import prefuse.action.RepaintAction;
+import prefuse.action.animate.ColorAnimator;
+import prefuse.action.animate.LocationAnimator;
+import prefuse.action.animate.QualityControlAnimator;
+import prefuse.action.animate.VisibilityAnimator;
+import prefuse.action.assignment.ColorAction;
+import prefuse.action.assignment.FontAction;
+import prefuse.action.filter.FisheyeTreeFilter;
+import prefuse.action.layout.CollapsedSubtreeLayout;
+import prefuse.action.layout.graph.NodeLinkTreeLayout;
+import prefuse.activity.SlowInSlowOutPacer;
+import prefuse.controls.ControlAdapter;
+import prefuse.controls.FocusControl;
+import prefuse.controls.PanControl;
+import prefuse.controls.WheelZoomControl;
+import prefuse.controls.ZoomControl;
+import prefuse.controls.ZoomToFitControl;
+import prefuse.data.Graph;
+import prefuse.data.expression.Predicate;
+import prefuse.data.expression.parser.ExpressionParser;
+import prefuse.data.tuple.TupleSet;
+import prefuse.render.AbstractShapeRenderer;
+import prefuse.render.DefaultRendererFactory;
+import prefuse.render.EdgeRenderer;
+import prefuse.render.LabelRenderer;
+import prefuse.util.ColorLib;
+import prefuse.util.FontLib;
+import prefuse.util.GraphicsLib;
+import prefuse.util.PrefuseLib;
+import prefuse.util.display.DisplayLib;
+import prefuse.visual.VisualItem;
+import prefuse.visual.sort.TreeDepthItemSorter;
+
+public final class TreeGraphDisplay
+    extends GraphDisplay
+{
+
+    static final String FILTER_ACTION = "filter";
+    static final String REPAINT_ACTION = "repaint";
+    static final String FULL_PAINT_ACTION = "fullPaint";
+    static final String ANIMATE_PAINT_ACTION = "animatePaint";
+    static final String ANIMATE_ACTION = "animate";
+    static final String LAYOUT_ACTION = "layout";
+    static final String SUB_LAYOUT_ACTION = "subLayout";
+    static final String AUTO_ZOOM_ACTION = "autoZoom";
+
+    private final LabelRenderer nodeRenderer;
+    private final EdgeRenderer edgeRenderer;
+    private final EdgeRenderer usesRenderer;
+
+    private final int orientation = Constants.ORIENT_LEFT_RIGHT;
+
+    public TreeGraphDisplay()
+    {
+        super( new Visualization() );
+
+        Color BACKGROUND = Color.WHITE;
+        Color FOREGROUND = Color.BLACK;
+
+        setBackground( BACKGROUND );
+        setForeground( FOREGROUND );
+
+        nodeRenderer = new LabelRenderer( NAME_LABEL );
+        nodeRenderer.setRenderType( AbstractShapeRenderer.RENDER_TYPE_FILL );
+        nodeRenderer.setHorizontalAlignment( Constants.LEFT );
+        nodeRenderer.setRoundedCorner( 8, 8 );
+        edgeRenderer = new EdgeRenderer( Constants.EDGE_TYPE_CURVE );
+        usesRenderer = new EdgeRenderer( Constants.EDGE_TYPE_CURVE, Constants.EDGE_ARROW_FORWARD );
+
+        Predicate edgesPredicate = (Predicate) ExpressionParser.parse( "ingroup('graph.edges') AND [" + USES_EDGES + "]==false", true );
+        Predicate usesPredicate = (Predicate) ExpressionParser.parse( "ingroup('graph.edges') AND [" + USES_EDGES + "]==true", true );
+
+        DefaultRendererFactory rf = new DefaultRendererFactory( nodeRenderer );
+        rf.add( edgesPredicate, edgeRenderer );
+        rf.add( usesPredicate, usesRenderer );
+        m_vis.setRendererFactory( rf );
+
+        // colors
+        ItemAction nodeColor = new NodeColorAction( GRAPH_NODES );
+        ItemAction textColor = new ColorAction( GRAPH_NODES, VisualItem.TEXTCOLOR, ColorLib.rgb( 0, 0, 0 ) );
+        m_vis.putAction( "textColor", textColor );
+
+        ItemAction edgeColor = new ColorAction( GRAPH_EDGES, edgesPredicate, VisualItem.STROKECOLOR, ColorLib.rgb( 200, 200, 200 ) );
+        ItemAction usesColor = new ColorAction( GRAPH_EDGES, usesPredicate, VisualItem.STROKECOLOR, ColorLib.rgb( 255, 100, 100 ) );
+        ItemAction usesArrow = new ColorAction( GRAPH_EDGES, usesPredicate, VisualItem.FILLCOLOR, ColorLib.rgb( 255, 100, 100 ) );
+
+        // quick repaint
+        ActionList repaint = new ActionList();
+        repaint.add( nodeColor );
+        repaint.add( new RepaintAction() );
+        m_vis.putAction( REPAINT_ACTION, repaint );
+
+        // full paint
+        ActionList fullPaint = new ActionList();
+        fullPaint.add( nodeColor );
+        m_vis.putAction( FULL_PAINT_ACTION, fullPaint );
+
+        // animate paint change
+        //ActionList animatePaint = new ActionList( 0 );
+        ActionList animatePaint = new ActionList();
+        animatePaint.add( new ColorAnimator( GRAPH_NODES ) );
+        animatePaint.add( new RepaintAction() );
+        m_vis.putAction( ANIMATE_PAINT_ACTION, animatePaint );
+
+        // create the GRAPH layout action
+        NodeLinkTreeLayout treeLayout = new NodeLinkTreeLayout( GRAPH, orientation, 40, 0, 8 );
+        treeLayout.setLayoutAnchor( new Point2D.Double( 25, 300 ) );
+        m_vis.putAction( LAYOUT_ACTION, treeLayout );
+
+        CollapsedSubtreeLayout subLayout = new CollapsedSubtreeLayout( GRAPH, orientation );
+        m_vis.putAction( SUB_LAYOUT_ACTION, subLayout );
+
+        // create the filtering and layout
+        ActionList filter = new ActionList();
+        filter.add( new ExtendedFisheyeTreeFilter( GRAPH, 2 ) );
+        filter.add( new FontAction( GRAPH_NODES, FontLib.getFont( "Tahoma", 14 ) ) );
+        filter.add( treeLayout );
+        filter.add( subLayout );
+        filter.add( textColor );
+        filter.add( nodeColor );
+        filter.add( edgeColor );
+        filter.add( usesColor );
+        filter.add( usesArrow );
+        m_vis.putAction( FILTER_ACTION, filter );
+
+        // animated transition
+        AutoPanAction autoPan = new AutoPanAction();
+        ActionList animate = new ActionList( 750 );
+        animate.setPacingFunction( new SlowInSlowOutPacer() );
+        animate.add( autoPan );
+        animate.add( new QualityControlAnimator() );
+        animate.add( new VisibilityAnimator( GRAPH ) );
+        animate.add( new LocationAnimator( GRAPH_NODES ) );
+        animate.add( new ColorAnimator( GRAPH_NODES ) );
+        animate.add( new RepaintAction() );
+        m_vis.putAction( ANIMATE_ACTION, animate );
+        m_vis.alwaysRunAfter( FILTER_ACTION, ANIMATE_ACTION );
+
+        m_vis.putAction( AUTO_ZOOM_ACTION, new AutoZoomAction() );
+
+        // initialize the display
+        setItemSorter( new TreeDepthItemSorter() );
+        addControlListener( new ZoomToFitControl() );
+        addControlListener( new ZoomControl() );
+        addControlListener( new WheelZoomControl() );
+        addControlListener( new PanControl() );
+        addControlListener( new FocusControl( 1, FILTER_ACTION ) );
+        addControlListener( new ItemSelectionControl() );
+
+        // set orientation
+        nodeRenderer.setHorizontalAlignment( Constants.LEFT );
+        edgeRenderer.setHorizontalAlignment1( Constants.RIGHT );
+        edgeRenderer.setHorizontalAlignment2( Constants.LEFT );
+        edgeRenderer.setVerticalAlignment1( Constants.CENTER );
+        edgeRenderer.setVerticalAlignment2( Constants.CENTER );
+        usesRenderer.setHorizontalAlignment1( Constants.CENTER );
+        usesRenderer.setHorizontalAlignment2( Constants.CENTER );
+        usesRenderer.setVerticalAlignment1( Constants.BOTTOM );
+        usesRenderer.setVerticalAlignment2( Constants.CENTER );
+        NodeLinkTreeLayout rtl = (NodeLinkTreeLayout) m_vis.getAction( LAYOUT_ACTION );
+        CollapsedSubtreeLayout stl = (CollapsedSubtreeLayout) m_vis.getAction( SUB_LAYOUT_ACTION );
+        rtl.setOrientation( orientation );
+        stl.setOrientation( orientation );
+    }
+
+    @Override
+    public void run( Graph graph )
+    {
+        m_vis.add( GRAPH, graph );
+        run();
+        m_vis.run( AUTO_ZOOM_ACTION );
+
+        // disable edges interactive
+        m_vis.setInteractive( GRAPH_EDGES, null, false );
+    }
+
+    @Override
+    public void run()
+    {
+        m_vis.run( FILTER_ACTION );
+    }
+
+    /**
+     * select the specified object
+     *
+     * @param object the object to select eg: Descriptor
+     */
+    @Override
+    public void setSelectedValue( Object object )
+    {
+        if( object == null )
+        {
+            return;
+        }
+
+        VisualItem item = null;
+
+        Iterator iter = m_vis.items( GRAPH_NODES );
+        while( iter.hasNext() )
+        {
+            VisualItem tItem = (VisualItem) iter.next();
+            Object tObj = tItem.get( USER_OBJECT );
+            if( tObj.equals( object ) )
+            {
+                item = tItem;
+                break;
+            }
+        }
+
+        if( item != null )
+        {
+            TupleSet ts = m_vis.getFocusGroup( Visualization.FOCUS_ITEMS );
+            ts.setTuple( item );
+            m_vis.run( FILTER_ACTION );
+        }
+    }
+
+    private class AutoZoomAction
+        extends Action
+    {
+        @Override
+        public void run( double frac )
+        {
+            int duration = 20;
+            int margin = 50;
+            Visualization vis = getVisualization();
+            Rectangle2D bounds = vis.getBounds( Visualization.ALL_ITEMS );
+            GraphicsLib.expand( bounds, margin + (int) ( 1 / getScale() ) );
+            DisplayLib.fitViewToBounds( TreeGraphDisplay.this, bounds, duration );
+        }
+    }
+
+    private class AutoPanAction
+        extends Action
+    {
+        private final Point2D m_start = new Point2D.Double();
+        private final Point2D m_end = new Point2D.Double();
+        private final Point2D m_cur = new Point2D.Double();
+        private final int m_bias = 150;
+
+        @Override
+        public void run( double frac )
+        {
+            TupleSet ts = m_vis.getFocusGroup( Visualization.FOCUS_ITEMS );
+            if( ts.getTupleCount() == 0 )
+            {
+                return;
+            }
+
+            if( frac == 0.0 )
+            {
+                int xbias, ybias = 0;
+
+                xbias = m_bias;
+                switch( orientation )
+                {
+                    case Constants.ORIENT_LEFT_RIGHT:
+
+                        break;
+                    case Constants.ORIENT_RIGHT_LEFT:
+                        xbias = -m_bias;
+                        break;
+                    case Constants.ORIENT_TOP_BOTTOM:
+                        ybias = m_bias;
+                        break;
+                    case Constants.ORIENT_BOTTOM_TOP:
+                        ybias = -m_bias;
+                        break;
+                }
+
+                VisualItem vi = (VisualItem) ts.tuples().next();
+                m_cur.setLocation( getWidth() / 2, getHeight() / 2 );
+                getAbsoluteCoordinate( m_cur, m_start );
+                m_end.setLocation( vi.getX() + xbias, vi.getY() + ybias );
+            }
+            else
+            {
+                m_cur.setLocation( m_start.getX() + frac * ( m_end.getX() - m_start.getX() ),
+                                   m_start.getY() + frac * ( m_end.getY() - m_start.getY() ) );
+                panToAbs( m_cur );
+            }
+        }
+    }
+
+    private static class NodeColorAction
+        extends ColorAction
+    {
+
+        private NodeColorAction( String group )
+        {
+            super( group, VisualItem.FILLCOLOR );
+        }
+
+        @Override
+        public int getColor( VisualItem item )
+        {
+            if( m_vis.isInGroup( item, Visualization.SEARCH_ITEMS ) )
+            {
+                return ColorLib.rgb( 255, 190, 190 );
+            }
+            else if( m_vis.isInGroup( item, Visualization.FOCUS_ITEMS ) )
+            {
+                return ColorLib.rgb( 198, 229, 229 );
+            }
+            else if( item.getDOI() > -1 )
+            {
+                return ColorLib.rgb( 164, 193, 193 );
+            }
+            else
+            {
+                return ColorLib.rgba( 255, 255, 255, 0 );
+            }
+        }
+    }
+
+    private class ItemSelectionControl
+        extends ControlAdapter
+    {
+        @Override
+        public final void itemClicked( VisualItem anItem, MouseEvent anEvent )
+        {
+            if( !anItem.canGet( USER_OBJECT, Object.class ) )
+            {
+                return;
+            }
+            Object object = anItem.get( USER_OBJECT );
+            LinkEvent evt = new LinkEvent( TreeGraphDisplay.this, object );
+            fireLinkActivated( evt );
+        }
+    }
+
+    private static class ExtendedFisheyeTreeFilter
+        extends FisheyeTreeFilter
+    {
+        private ExtendedFisheyeTreeFilter( String group, int distance )
+        {
+            super( group, distance );
+        }
+
+        @Override
+        public void run( double frac )
+        {
+            super.run( frac );
+
+            // set uses_edges always visible
+            Iterator items = m_vis.items( GRAPH_EDGES );
+            while( items.hasNext() )
+            {
+                VisualItem item = (VisualItem) items.next();
+                if( item.getBoolean( USES_EDGES ) )
+                {
+                    PrefuseLib.updateVisible( item, true );
+                }
+            }
+        }
+    }
+
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/package.html b/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/package.html
new file mode 100644
index 0000000..dc4b400
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/graph/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Envisage Tool Graph Visualization.</h2>
+    </body>
+</html>
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/package.html b/tools/envisage/src/main/java/org/apache/polygene/envisage/package.html
new file mode 100644
index 0000000..ab89398
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Envisage Tool.</h2>
+    </body>
+</html>
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/print/PDFWriter.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/print/PDFWriter.java
new file mode 100644
index 0000000..3ab9bff
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/print/PDFWriter.java
@@ -0,0 +1,827 @@
+/*
+ *  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.polygene.envisage.print;
+
+import java.awt.Component;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.HashSet;
+import java.util.List;
+import javax.imageio.ImageIO;
+import javax.swing.JFileChooser;
+import javax.swing.filechooser.FileFilter;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDPageContentStream;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.pdmodel.font.PDType1Font;
+import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.DependencyDescriptor;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.envisage.graph.GraphDisplay;
+import org.apache.polygene.envisage.util.TableRow;
+import org.apache.polygene.envisage.util.TableRowUtilities;
+import org.apache.polygene.tools.model.descriptor.*;
+import org.apache.polygene.tools.model.util.DescriptorUtilities;
+
+public class PDFWriter
+{
+    protected PDDocument doc = null;
+    protected PDPageContentStream curContentStream = null;
+    protected PDRectangle curPageSize;
+    protected float curY;
+    protected PDFont curFont;
+    protected float curFontSize;
+
+    protected String APPLICATION = "Application";
+    protected String LAYER = "Layer";
+    protected String MODULE = "Module";
+
+    protected PDFont normalFont = PDType1Font.HELVETICA;
+    protected PDFont header1Font = PDType1Font.HELVETICA_BOLD;  // Application
+    protected PDFont header2Font = PDType1Font.HELVETICA_BOLD;  // Layer
+    protected PDFont header3Font = PDType1Font.HELVETICA_BOLD; // Module
+    protected PDFont header4Font = PDType1Font.HELVETICA_BOLD; // Type Container
+    protected PDFont header5Font = PDType1Font.HELVETICA_BOLD_OBLIQUE; // Type
+    protected float normalFontSize = 10;
+    protected float header1FontSize = 18;
+    protected float header2FontSize = 16;
+    protected float header3FontSize = 14;
+    protected float header4FontSize = 12;
+    protected float header5FontSize = 12;
+
+    protected float startX = 40;
+    protected float startY = 40;
+    protected float lineSpace = 15;
+    protected float headerLineSpace = 25;
+
+    public void write( Component parent, ApplicationDetailDescriptor descriptor, List<GraphDisplay> graphDisplays )
+    {
+        JFileChooser fc = new JFileChooser();
+        PDFFileFilter pdfFileFilter = new PDFFileFilter();
+        fc.setFileFilter( pdfFileFilter );
+
+        int choice = fc.showSaveDialog( parent );
+        if( choice != JFileChooser.APPROVE_OPTION )
+        {
+            return;
+        }
+
+        File file = fc.getSelectedFile();
+        String filename = file.toString();
+        String ext = ".pdf";
+        if( !filename.endsWith( ext ) )
+        {
+            filename = filename + ext;
+            file = new File( filename );
+        }
+
+        write( file, descriptor, graphDisplays );
+    }
+
+    public void write( File file, ApplicationDetailDescriptor descriptor, List<GraphDisplay> graphDisplays )
+    {
+        try
+        {
+            writeImpl( file, descriptor, graphDisplays );
+        }
+        catch( IOException ex )
+        {
+            ex.printStackTrace();
+        }
+    }
+
+    protected void writeImpl( File file, ApplicationDetailDescriptor descriptor, List<GraphDisplay> graphDisplays )
+        throws IOException
+    {
+        try
+        {
+            doc = new PDDocument();
+            for( GraphDisplay graphDisplay : graphDisplays )
+            {
+                writeGraphPage( graphDisplay );
+            }
+            writePage( descriptor );
+            if( curContentStream != null )
+            {
+                curContentStream.close();
+                curContentStream = null;
+            }
+            doc.save( new FileOutputStream( file ) );
+        }
+        finally
+        {
+            if( curContentStream != null )
+            {
+                curContentStream.close();
+                curContentStream = null;
+            }
+
+            if( doc != null )
+            {
+                doc.close();
+                doc = null;
+            }
+        }
+    }
+
+    private void writeGraphPage( GraphDisplay graphDisplay )
+        throws IOException
+    {
+        File tFile = File.createTempFile( "envisage", ".png" );
+        graphDisplay.saveImage( new FileOutputStream( tFile ), "png", 1d );
+
+        BufferedImage img = ImageIO.read( tFile );
+
+        int w = img.getWidth();
+        int h = img.getHeight();
+
+        int inset = 40;
+        PDRectangle pdRect = new PDRectangle( w + inset, h + inset );
+        PDPage page = new PDPage();
+        page.setMediaBox( pdRect );
+        doc.addPage( page );
+
+        PDImageXObject xImage = PDImageXObject.createFromFileByExtension( tFile, doc );
+
+        PDPageContentStream contentStream = new PDPageContentStream( doc, page );
+        contentStream.drawImage( xImage, ( pdRect.getWidth() - w ) / 2, ( pdRect.getHeight() - h ) / 2 );
+        contentStream.close();
+    }
+
+    private void writePage( ApplicationDetailDescriptor descriptor )
+    {
+        createNewPage();
+        setFont( header1Font, header1FontSize );
+        writeString( APPLICATION + " : " + descriptor.toString() );
+
+        writeLayersPage( descriptor.layers() );
+    }
+
+    private void writeLayersPage( Iterable<LayerDetailDescriptor> iter )
+    {
+        for( LayerDetailDescriptor descriptor : iter )
+        {
+            setFont( header2Font, header2FontSize );
+            writeString( LAYER + " : " + descriptor.toString(), headerLineSpace );
+
+            writeModulesPage( descriptor.modules() );
+        }
+    }
+
+    private void writeModulesPage( Iterable<ModuleDetailDescriptor> iter )
+    {
+        for( ModuleDetailDescriptor descriptor : iter )
+        {
+            setFont( header3Font, header3FontSize );
+            writeString( MODULE + " : " + descriptor.toString(), headerLineSpace );
+
+            writeServicesPage( descriptor.services() );
+            writeImportedServicesPage( descriptor.importedServices() );
+            writeEntitiesPage( descriptor.entities() );
+            writeTransientsPage( descriptor.transients() );
+            writeValuesPage( descriptor.values() );
+            writeObjectsPage( descriptor.objects() );
+        }
+    }
+
+    private void writeServicesPage( Iterable<ServiceDetailDescriptor> iter )
+    {
+        for( ServiceDetailDescriptor descriptor : iter )
+        {
+            setFont( header4Font, header4FontSize );
+            writeString( descriptor.toString(), headerLineSpace );
+            writeTypeGeneralPage( descriptor );
+            writeTypeDependenciesPage( descriptor );
+            writeTypeMethodsPage( descriptor );
+            writeTypeStatesPage( descriptor );
+            writeTypeServiceConfigurationPage( descriptor );
+            writeTypeServiceUsagePage( descriptor );
+        }
+    }
+
+    private void writeImportedServicesPage( Iterable<ImportedServiceDetailDescriptor> iter )
+    {
+        for( ImportedServiceDetailDescriptor descriptor : iter )
+        {
+            setFont( header4Font, header4FontSize );
+            writeString( descriptor.toString(), headerLineSpace );
+            writeTypeGeneralPage( descriptor );
+            writeTypeMethodsPage( descriptor );
+            writeTypeServiceUsagePage( descriptor );
+            writeTypeImportedByPage( descriptor );
+        }
+    }
+
+    private void writeEntitiesPage( Iterable<EntityDetailDescriptor> iter )
+    {
+        for( EntityDetailDescriptor descriptor : iter )
+        {
+            setFont( header4Font, header4FontSize );
+            writeString( descriptor.toString(), headerLineSpace );
+            writeTypeGeneralPage( descriptor );
+            writeTypeDependenciesPage( descriptor );
+            writeTypeMethodsPage( descriptor );
+            writeTypeStatesPage( descriptor );
+        }
+    }
+
+    private void writeTransientsPage( Iterable<TransientDetailDescriptor> iter )
+    {
+        for( TransientDetailDescriptor descriptor : iter )
+        {
+            setFont( header4Font, header4FontSize );
+            writeString( descriptor.toString(), headerLineSpace );
+            writeTypeGeneralPage( descriptor );
+            writeTypeDependenciesPage( descriptor );
+            writeTypeMethodsPage( descriptor );
+            writeTypeStatesPage( descriptor );
+        }
+    }
+
+    private void writeValuesPage( Iterable<ValueDetailDescriptor> iter )
+    {
+        for( ValueDetailDescriptor descriptor : iter )
+        {
+            setFont( header4Font, header4FontSize );
+            writeString( descriptor.toString(), headerLineSpace );
+            writeTypeGeneralPage( descriptor );
+            writeTypeDependenciesPage( descriptor );
+            writeTypeMethodsPage( descriptor );
+            writeTypeStatesPage( descriptor );
+        }
+    }
+
+    private void writeObjectsPage( Iterable<ObjectDetailDescriptor> iter )
+    {
+        for( ObjectDetailDescriptor descriptor : iter )
+        {
+            setFont( header4Font, header4FontSize );
+            writeString( descriptor.toString(), headerLineSpace );
+            writeTypeGeneralPage( descriptor );
+            writeTypeDependenciesPage( descriptor );
+            // object don't have methods
+        }
+    }
+
+    private void writeTypeGeneralPage( Object objectDesciptor )
+    {
+
+        setFont( header5Font, header5FontSize );
+        writeString( "General: ", headerLineSpace );
+
+        setFont( normalFont, normalFontSize );
+
+        if( objectDesciptor instanceof ServiceDetailDescriptor )
+        {
+            ServiceDescriptor descriptor = ( (ServiceDetailDescriptor) objectDesciptor ).descriptor();
+            writeString( "- reference: " + descriptor.identity() );
+            writeString( "- class: " + descriptor.toString() );
+            writeString( "- visibility: " + descriptor.visibility().toString() );
+            writeString( "- startup: " + ( (ServiceDetailDescriptor) objectDesciptor ).descriptor()
+                .isInstantiateOnStartup() );
+        }
+        else if( objectDesciptor instanceof EntityDetailDescriptor )
+        {
+            EntityDescriptor descriptor = ( (EntityDetailDescriptor) objectDesciptor ).descriptor();
+            writeString( "- name: " + descriptor.toString() );
+            writeString( "- class: " + descriptor.toString() );
+            writeString( "- visibility: " + descriptor.visibility().toString() );
+        }
+        else if( objectDesciptor instanceof ValueDetailDescriptor )
+        {
+            ValueDescriptor descriptor = ( (ValueDetailDescriptor) objectDesciptor ).descriptor();
+            writeString( "- name: " + descriptor.toString() );
+            writeString( "- class: " + descriptor.toString() );
+            writeString( "- visibility: " + descriptor.visibility().toString() );
+        }
+        else if( objectDesciptor instanceof ObjectDetailDescriptor )
+        {
+            ObjectDescriptor descriptor = ( (ObjectDetailDescriptor) objectDesciptor ).descriptor();
+            writeString( "- name: " + descriptor.toString() );
+            writeString( "- class: " + descriptor.toString() );
+            writeString( "- visibility: " + descriptor.visibility().toString() );
+        }
+        else if( objectDesciptor instanceof CompositeDetailDescriptor )
+        {
+            CompositeDescriptor descriptor = ( (CompositeDetailDescriptor) objectDesciptor ).descriptor();
+            writeString( "- name: " + descriptor.toString() );
+            writeString( "- class: " + descriptor.toString() );
+            writeString( "- visibility: " + descriptor.visibility().toString() );
+        }
+    }
+
+    private void writeTypeDependenciesPage( Object objectDesciptor )
+    {
+        setFont( header5Font, header5FontSize );
+        writeString( "Dependencies: ", headerLineSpace );
+
+        if( objectDesciptor instanceof CompositeDetailDescriptor )
+        {
+            CompositeDetailDescriptor descriptor = (CompositeDetailDescriptor) objectDesciptor;
+            Iterable<MixinDetailDescriptor> iter = descriptor.mixins();
+            for( MixinDetailDescriptor mixinDescriptor : iter )
+            {
+                writeTypeDependenciesPage( mixinDescriptor.injectedFields() );
+            }
+        }
+        else if( objectDesciptor instanceof ObjectDetailDescriptor )
+        {
+            ObjectDetailDescriptor descriptor = ( (ObjectDetailDescriptor) objectDesciptor );
+            writeTypeDependenciesPage( descriptor.injectedFields() );
+        }
+    }
+
+    private void writeTypeDependenciesPage( Iterable<InjectedFieldDetailDescriptor> iter )
+    {
+        setFont( normalFont, normalFontSize );
+        for( InjectedFieldDetailDescriptor descriptor : iter )
+        {
+            DependencyDescriptor dependencyDescriptor = descriptor.descriptor().dependency();
+            writeString( "- name: " + dependencyDescriptor.injectedClass().getSimpleName() );
+            writeString( "    * annotation: @" + dependencyDescriptor.injectionAnnotation()
+                .annotationType()
+                .getSimpleName() );
+            writeString( "    * optional: " + Boolean.toString( dependencyDescriptor.optional() ) );
+            writeString( "    * type: " + dependencyDescriptor.injectionType().getClass().getSimpleName() );
+        }
+    }
+
+    private void writeTypeMethodsPage( Object objectDesciptor )
+    {
+        if( !CompositeDetailDescriptor.class.isAssignableFrom( objectDesciptor.getClass() ) )
+        {
+            return;
+        }
+
+        setFont( header5Font, header5FontSize );
+        writeString( "Methods: ", headerLineSpace );
+        setFont( normalFont, normalFontSize );
+
+        CompositeDetailDescriptor descriptor = (CompositeDetailDescriptor) objectDesciptor;
+        List<CompositeMethodDetailDescriptor> list = DescriptorUtilities.findMethod( descriptor );
+
+        HashSet<String> imports = new HashSet<>();
+        for( CompositeMethodDetailDescriptor methodDescriptor : list )
+        {
+            addImport( imports, methodDescriptor.descriptor().method().getGenericReturnType() );
+            for( Class parameter : methodDescriptor.descriptor().method().getParameterTypes() )
+            {
+                addImport( imports, parameter );
+            }
+        }
+        for( String imp : imports )
+        {
+            writeString( "    import " + imp + ";" );
+        }
+        writeString( "" );
+
+        for( CompositeMethodDetailDescriptor methodDescriptor : list )
+        {
+            Type returnType = methodDescriptor.descriptor().method().getGenericReturnType();
+            writeString( "    " + formatType( returnType ) + "."
+                         + methodDescriptor.toString()
+                         + formatParameters( methodDescriptor.descriptor().method().getParameterTypes() )
+            );
+        }
+    }
+
+    private String formatParameters( Class<?>[] parameterTypes )
+    {
+        StringBuilder result = new StringBuilder();
+        result.append( "(" );
+        boolean first = true;
+        int count = 1;
+        for( Class parameter : parameterTypes )
+        {
+            if( !first )
+            {
+                result.append( "," );
+            }
+            first = false;
+            result.append( " " );
+            result.append( formatType( parameter ) );
+            result.append( " " );
+            result.append( "p" );
+            result.append( count++ );
+        }
+        if( first )
+        {
+            // No parameters appended.
+            result.append( ");" );
+        }
+        else
+        {
+            result.append( " );" );
+        }
+        return result.toString();
+    }
+
+    private String formatType( Type type )
+    {
+        if( type instanceof Class )
+        {
+            Class clazz = (Class) type;
+            return clazz.getSimpleName();
+        }
+        else if( type instanceof ParameterizedType )
+        {
+            ParameterizedType pType = (ParameterizedType) type;
+            Type[] actuals = pType.getActualTypeArguments();
+            Type ownerType = pType.getOwnerType();
+            Type rawType = pType.getRawType();
+            StringBuilder result = new StringBuilder();
+            result.append( ( (Class) rawType ).getSimpleName() );
+            result.append( "<" );
+            boolean first = true;
+            for( Type actual : actuals )
+            {
+                if( !first )
+                {
+                    result.append( "," );
+                }
+                first = false;
+                result.append( formatType( actual ) );
+            }
+            result.append( ">" );
+
+            return result.toString();
+        }
+        else if( type instanceof WildcardType )
+        {
+            // TODO: I am sure there are other wildcard constructs that will format incorrectly. Fix that!
+            //
+            WildcardType wildcard = (WildcardType) type;
+            Type[] lowers = wildcard.getLowerBounds();
+            Type[] uppers = wildcard.getUpperBounds();
+            StringBuilder result = new StringBuilder();
+            result.append( "? extends " );
+            boolean first = true;
+            for( Type upper : uppers )
+            {
+                if( !first )
+                {
+                    result.append( ", " );
+                }
+                result.append( formatType( upper ) );
+            }
+            return result.toString();
+        }
+        else if( type instanceof TypeVariable )
+        {
+            return type.toString();
+        }
+
+        return type.toString();
+    }
+
+    private void addImport( HashSet<String> imports, Type type )
+    {
+        if( type instanceof Class )
+        {
+            Class clazz = (Class) type;
+            Package pkkage = clazz.getPackage();
+            if( pkkage == null )
+            {
+                return;
+            }
+            String packageName = pkkage.getName();
+            if( packageName.startsWith( "java" ) )
+            {
+                return;
+            }
+            imports.add( clazz.getName() );
+        }
+        else if( type instanceof ParameterizedType )
+        {
+            ParameterizedType pType = (ParameterizedType) type;
+            Type[] actuals = pType.getActualTypeArguments();
+            Type ownerType = pType.getOwnerType();
+            Type rawType = pType.getRawType();
+            addImport( imports, ownerType );
+            addImport( imports, rawType );
+            for( Type actual : actuals )
+            {
+                addImport( imports, actual );
+            }
+        }
+    }
+
+    private void writeTypeStatesPage( Object objectDesciptor )
+    {
+        if( !CompositeDetailDescriptor.class.isAssignableFrom( objectDesciptor.getClass() ) )
+        {
+            return;
+        }
+
+        setFont( header5Font, header5FontSize );
+        writeString( "States: ", headerLineSpace );
+
+        CompositeDetailDescriptor descriptor = (CompositeDetailDescriptor) objectDesciptor;
+        List<CompositeMethodDetailDescriptor> list = DescriptorUtilities.findState( descriptor );
+
+        setFont( normalFont, normalFontSize );
+        for( CompositeMethodDetailDescriptor methodDescriptor : list )
+        {
+            writeString( "- name: " + methodDescriptor.toString() );
+            writeString( "    * return: " + methodDescriptor.descriptor().method().getGenericReturnType() );
+        }
+    }
+
+    private void writeTypeServiceConfigurationPage( Object objectDesciptor )
+    {
+        setFont( header5Font, header5FontSize );
+        writeString( "Configuration: ", headerLineSpace );
+
+        Object configDescriptor = DescriptorUtilities.findServiceConfiguration( (ServiceDetailDescriptor) objectDesciptor );
+
+        if( configDescriptor == null )
+        {
+            return;
+        }
+
+        ModelDescriptor spiDescriptor;
+        String typeString;
+        if( configDescriptor instanceof ServiceDetailDescriptor )
+        {
+            spiDescriptor = ( (ServiceDetailDescriptor) configDescriptor ).descriptor();
+            typeString = "Service";
+        }
+        else if( configDescriptor instanceof EntityDetailDescriptor )
+        {
+            spiDescriptor = ( (EntityDetailDescriptor) configDescriptor ).descriptor();
+            typeString = "Entity";
+        }
+        else if( configDescriptor instanceof ValueDetailDescriptor )
+        {
+            spiDescriptor = ( (ValueDetailDescriptor) configDescriptor ).descriptor();
+            typeString = "Value";
+        }
+        else if( configDescriptor instanceof ObjectDetailDescriptor )
+        {
+            spiDescriptor = ( (ObjectDetailDescriptor) configDescriptor ).descriptor();
+            typeString = "Object";
+        }
+        else if( configDescriptor instanceof CompositeDetailDescriptor )
+        {
+            spiDescriptor = ( (CompositeDetailDescriptor) configDescriptor ).descriptor();
+            typeString = "Transient";
+        }
+        else
+        {
+            throw new PrintingException( "Unknown configuration descriptor: " + configDescriptor.getClass()
+                .getName(), null );
+        }
+
+        setFont( normalFont, normalFontSize );
+        writeString( "- name: " + spiDescriptor.toString() );
+        writeString( "- class: " + spiDescriptor.toString() );
+        writeString( "- type: " + typeString );
+    }
+
+    private void writeTypeServiceUsagePage( Object objectDesciptor )
+    {
+        setFont( header5Font, header5FontSize );
+        writeString( "Usage: ", headerLineSpace );
+
+        setFont( normalFont, normalFontSize );
+        List<ServiceUsage> serviceUsages = DescriptorUtilities.findServiceUsage( (ServiceDetailDescriptor) objectDesciptor );
+        List<TableRow> rows = TableRowUtilities.toTableRows( serviceUsages );
+        for( TableRow row : rows )
+        {
+
+            //String owner;
+            String usage;
+            String module;
+            String layer;
+
+            Object obj = row.get( 0 );
+            if( obj instanceof CompositeDetailDescriptor )
+            {
+                CompositeDetailDescriptor descriptor = (CompositeDetailDescriptor) obj;
+                //owner = descriptor.toString();
+                module = descriptor.module().toString();
+                layer = descriptor.module().layer().toString();
+            }
+            else
+            {
+                ObjectDetailDescriptor descriptor = (ObjectDetailDescriptor) obj;
+                //owner = descriptor.toString();
+                module = descriptor.module().toString();
+                layer = descriptor.module().layer().toString();
+            }
+
+            InjectedFieldDetailDescriptor injectedFieldescriptor = (InjectedFieldDetailDescriptor) row.get( 1 );
+            DependencyDescriptor dependencyDescriptor = injectedFieldescriptor.descriptor().dependency();
+            Annotation annotation = dependencyDescriptor.injectionAnnotation();
+            usage = injectedFieldescriptor.toString() + " (@" + annotation.annotationType().getSimpleName() + ")";
+
+            writeString( "- owner: " + row.get( 0 ).toString() );
+            writeString( "    * usage: " + usage );
+            writeString( "    * module: " + module );
+            writeString( "    * layer: " + layer );
+        }
+    }
+
+    private void writeTypeImportedByPage( Object objectDesciptor )
+    {
+        setFont( header5Font, header5FontSize );
+        writeString( "Imported by: ", headerLineSpace );
+
+        ImportedServiceDetailDescriptor detailDescriptor = (ImportedServiceDetailDescriptor) objectDesciptor;
+        ImportedServiceDescriptor descriptor = detailDescriptor.descriptor().importedService();
+        Class<? extends ServiceImporter> importer = descriptor.serviceImporter();
+
+        setFont( normalFont, normalFontSize );
+        writeString( "- name: " + importer.getSimpleName() );
+        writeString( "- class: " + importer.toString() );
+    }
+
+    private void writeString( String text )
+    {
+        writeString( text, this.lineSpace );
+    }
+
+    private void writeString( String text, float lineSpace )
+    {
+        // check for page size, if necessary create new page
+        if( ( curY - lineSpace ) <= startY )
+        {
+            createNewPage();
+        }
+
+        curY = curY - lineSpace;
+
+        try
+        {
+            curContentStream.moveTextPositionByAmount( 0, -lineSpace );
+            curContentStream.drawString( text );
+        }
+        catch( IOException e )
+        {
+            throw new PrintingException( "Unable to write string: " + text, e );
+        }
+    }
+
+    private void setFont( PDFont font, float fontSize )
+    {
+        curFont = font;
+        curFontSize = fontSize;
+        try
+        {
+            curContentStream.setFont( curFont, curFontSize );
+        }
+        catch( IOException e )
+        {
+            throw new PrintingException( "Unable to set font: " + font.toString() + ", " + fontSize + "pt", e );
+        }
+    }
+
+    private void createNewPage()
+    {
+        try
+        {
+            if( curContentStream != null )
+            {
+                curContentStream.endText();
+                curContentStream.close();
+            }
+
+            PDPage page = new PDPage();
+            doc.addPage( page );
+
+            curContentStream = new PDPageContentStream( doc, page );
+
+            curPageSize = page.getArtBox();
+
+            curContentStream.beginText();
+            curY = curPageSize.getHeight() - startY;
+            curContentStream.moveTextPositionByAmount( startX, curY );
+
+            if( curFont != null )
+            {
+                setFont( curFont, curFontSize );
+            }
+        }
+        catch( IOException e )
+        {
+            throw new PrintingException( "Unable to create page.", e );
+        }
+    }
+
+    private double scaleToFit( double srcW, double srcH, double destW, double destH )
+    {
+        double scale = 1;
+        if( srcW > srcH )
+        {
+            if( srcW > destW )
+            {
+                scale = destW / srcW;
+            }
+            srcH = srcH * scale;
+            if( srcH > destH )
+            {
+                scale = scale * ( destH / srcH );
+            }
+        }
+        else
+        {
+            if( srcH > destH )
+            {
+                scale = destH / srcH;
+            }
+            srcW = srcW * scale;
+            if( srcW > destW )
+            {
+                scale = scale * ( destW / srcW );
+            }
+        }
+        return scale;
+    }
+
+    static class PDFFileFilter
+        extends FileFilter
+    {
+
+        private final String description;
+        protected String extension = null;
+
+        public PDFFileFilter()
+        {
+            extension = "pdf";
+            description = "PDF - Portable Document Format";
+        }
+
+        @Override
+        public boolean accept( File f )
+        {
+            if( f != null )
+            {
+                if( f.isDirectory() )
+                {
+                    return true;
+                }
+                String str = getExtension( f );
+                if( str != null && str.equals( extension ) )
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        public String getExtension( File f )
+        {
+            if( f != null )
+            {
+                String filename = f.getName();
+                int i = filename.lastIndexOf( '.' );
+                if( i > 0 && i < filename.length() - 1 )
+                {
+                    return filename.substring( i + 1 ).toLowerCase();
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public String getDescription()
+        {
+            return description;
+        }
+    }
+
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/print/PrintingException.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/print/PrintingException.java
new file mode 100644
index 0000000..f54738a
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/print/PrintingException.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.envisage.print;
+
+public class PrintingException
+    extends RuntimeException
+{
+    public PrintingException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/print/package.html b/tools/envisage/src/main/java/org/apache/polygene/envisage/print/package.html
new file mode 100644
index 0000000..3ef49fd
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/print/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Envisage Tool PDF Print Support.</h2>
+    </body>
+</html>
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/tree/StructureModelBuilder.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/tree/StructureModelBuilder.java
new file mode 100644
index 0000000..a59552d
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/tree/StructureModelBuilder.java
@@ -0,0 +1,153 @@
+/*
+ *  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.polygene.envisage.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.MutableTreeNode;
+import org.apache.polygene.tools.model.descriptor.*;
+import org.apache.polygene.tools.model.util.DescriptorNameComparator;
+
+/**
+ * Helper class to build tree model for Apache Polygene model as Structure Tree
+ */
+/* package */ final class StructureModelBuilder
+{
+    private final DescriptorNameComparator<Object> nameComparator = new DescriptorNameComparator<>();
+    private final List<Object> tempList = new ArrayList<>();   // used for sorting
+
+    /* package */ static MutableTreeNode build( ApplicationDetailDescriptor descriptor )
+    {
+        StructureModelBuilder builder = new StructureModelBuilder();
+        return builder.buildApplicationNode( descriptor );
+    }
+
+    private MutableTreeNode buildApplicationNode( ApplicationDetailDescriptor descriptor )
+    {
+        DefaultMutableTreeNode node = new DefaultMutableTreeNode( descriptor );
+        buildLayersNode( node, descriptor.layers() );
+        return node;
+    }
+
+    private void buildLayersNode( DefaultMutableTreeNode parent, Iterable<LayerDetailDescriptor> iter )
+    {
+        for( LayerDetailDescriptor descriptor : iter )
+        {
+            DefaultMutableTreeNode node = new DefaultMutableTreeNode( descriptor );
+            buildModulesNode( node, descriptor.modules() );
+            parent.add( node );
+        }
+    }
+
+    private void buildModulesNode( DefaultMutableTreeNode parent, Iterable<ModuleDetailDescriptor> iter )
+    {
+        for( ModuleDetailDescriptor descriptor : iter )
+        {
+            DefaultMutableTreeNode node = new DefaultMutableTreeNode( descriptor );
+            buildServicesNode( node, descriptor.services() );
+            buildImportedServicesNode( node, descriptor.importedServices() );
+            buildEntitiesNode( node, descriptor.entities() );
+            buildTransientsNode( node, descriptor.transients() );
+            buildValuesNode( node, descriptor.values() );
+            buildObjectsNode( node, descriptor.objects() );
+            parent.add( node );
+        }
+    }
+
+    private void addTypeChildren( DefaultMutableTreeNode parent, List<Object> childList )
+    {
+        childList.sort( nameComparator );
+
+        for( Object child : childList )
+        {
+            parent.add( new DefaultMutableTreeNode( child ) );
+        }
+    }
+
+    private void buildServicesNode( DefaultMutableTreeNode parent, Iterable<ServiceDetailDescriptor> iter )
+    {
+        tempList.clear();
+        for( ServiceDetailDescriptor descriptor : iter )
+        {
+            tempList.add( descriptor );
+        }
+
+        addTypeChildren( parent, tempList );
+    }
+
+    private void buildImportedServicesNode( DefaultMutableTreeNode parent,
+                                            Iterable<ImportedServiceDetailDescriptor> iter
+    )
+    {
+        tempList.clear();
+        for( ImportedServiceDetailDescriptor descriptor : iter )
+        {
+            tempList.add( descriptor );
+        }
+
+        addTypeChildren( parent, tempList );
+    }
+
+    private void buildEntitiesNode( DefaultMutableTreeNode parent, Iterable<EntityDetailDescriptor> iter )
+    {
+        tempList.clear();
+        for( EntityDetailDescriptor descriptor : iter )
+        {
+            tempList.add( descriptor );
+        }
+
+        addTypeChildren( parent, tempList );
+    }
+
+    private void buildTransientsNode( DefaultMutableTreeNode parent, Iterable<TransientDetailDescriptor> iter )
+    {
+        tempList.clear();
+        for( TransientDetailDescriptor descriptor : iter )
+        {
+            tempList.add( descriptor );
+        }
+
+        addTypeChildren( parent, tempList );
+    }
+
+    private void buildValuesNode( DefaultMutableTreeNode parent, Iterable<ValueDetailDescriptor> iter )
+    {
+        tempList.clear();
+        for( ValueDetailDescriptor descriptor : iter )
+        {
+            tempList.add( descriptor );
+        }
+
+        addTypeChildren( parent, tempList );
+    }
+
+    private void buildObjectsNode( DefaultMutableTreeNode parent, Iterable<ObjectDetailDescriptor> iter )
+    {
+        tempList.clear();
+        for( ObjectDetailDescriptor descriptor : iter )
+        {
+            tempList.add( descriptor );
+        }
+
+        addTypeChildren( parent, tempList );
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/tree/TreeModelCellRenderer.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/tree/TreeModelCellRenderer.java
new file mode 100644
index 0000000..cf26fb7
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/tree/TreeModelCellRenderer.java
@@ -0,0 +1,156 @@
+/*
+ *  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.polygene.envisage.tree;
+
+import java.awt.Component;
+import java.util.ResourceBundle;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import org.apache.polygene.tools.model.descriptor.*;
+
+/**
+ * TreeCellRenderer
+ */
+/* package */ final class TreeModelCellRenderer
+    extends DefaultTreeCellRenderer
+{
+    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( TreeModelCellRenderer.class.getName() );
+
+    private final Icon applicationIcon;
+    private final Icon layerIcon;
+    private final Icon moduleIcon;
+    private final Icon serviceIcon;
+    private final Icon importedServiceIcon;
+    private final Icon entityIcon;
+    private final Icon valueIcon;
+    private final Icon transientIcon;
+    private final Icon objectIcon;
+
+    /* package */ TreeModelCellRenderer()
+    {
+        try
+        {
+            applicationIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Application" ) ) );
+            layerIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Layer" ) ) );
+            moduleIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Module" ) ) );
+            serviceIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Service" ) ) );
+            importedServiceIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_ImportedService" ) ) );
+            entityIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Entity" ) ) );
+            valueIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Value" ) ) );
+            transientIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Transient" ) ) );
+            objectIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Object" ) ) );
+        }
+        catch( Exception ex )
+        {
+            throw new RuntimeException( ex );
+        }
+    }
+
+    @Override
+    public final Component getTreeCellRendererComponent(
+        JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus
+    )
+    {
+        super.getTreeCellRendererComponent( tree, value, sel, expanded, leaf, row, hasFocus );
+
+        DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value;
+        Object userObject = treeNode.getUserObject();
+
+        // determine icon
+        Icon icon = null;
+
+        if( userObject instanceof ApplicationDetailDescriptor )
+        {
+            icon = applicationIcon;
+        }
+        else if( userObject instanceof LayerDetailDescriptor )
+        {
+            icon = layerIcon;
+        }
+        else if( userObject instanceof ModuleDetailDescriptor )
+        {
+            icon = moduleIcon;
+        }
+        else if( userObject instanceof ServiceDetailDescriptor )
+        {
+            icon = serviceIcon;
+        }
+        else if( userObject instanceof ImportedServiceDetailDescriptor )
+        {
+            icon = importedServiceIcon;
+        }
+        else if( userObject instanceof EntityDetailDescriptor )
+        {
+            icon = entityIcon;
+        }
+        else if( userObject instanceof ValueDetailDescriptor )
+        {
+            icon = valueIcon;
+        }
+        else if( userObject instanceof TransientDetailDescriptor )
+        {
+            icon = transientIcon;
+        }
+        else if( userObject instanceof ObjectDetailDescriptor )
+        {
+            icon = objectIcon;
+        }
+        else
+        {
+            // assume it is string
+            String str = userObject.toString();
+            if( str.equalsIgnoreCase( "Services" ) )
+            {
+                icon = serviceIcon;
+            }
+            else if( str.equalsIgnoreCase( "Imported Services" ) )
+            {
+                icon = importedServiceIcon;
+            }
+            else if( str.equalsIgnoreCase( "Entities" ) )
+            {
+                icon = entityIcon;
+            }
+            else if( str.equalsIgnoreCase( "Values" ) )
+            {
+                icon = valueIcon;
+            }
+            else if( str.equalsIgnoreCase( "Transients" ) )
+            {
+                icon = transientIcon;
+            }
+            else if( str.equalsIgnoreCase( "Objects" ) )
+            {
+                icon = objectIcon;
+            }
+        }
+
+        if( icon != null )
+        {
+            setIcon( icon );
+        }
+
+        return this;
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/tree/TreeModelPane.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/tree/TreeModelPane.java
new file mode 100644
index 0000000..48183e1
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/tree/TreeModelPane.java
@@ -0,0 +1,287 @@
+/*
+ *  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.polygene.envisage.tree;
+
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.GridBagConstraints;
+import java.awt.Insets;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.util.ResourceBundle;
+import javax.swing.BorderFactory;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.*;
+import org.apache.polygene.tools.model.descriptor.ApplicationDetailDescriptor;
+
+/**
+ * Application Model View as Swing Component.
+ * It support 2 view:
+ * <pre><code>
+ * - by Structure
+ * - by Type
+ * </code></pre>
+ */
+public final class TreeModelPane
+    extends JPanel
+{
+    private static final String STRUCTURE_VIEW = "Structure";
+    private static final String TYPE_VIEW = "Type";
+
+    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( TreeModelPane.class.getName() );
+
+    private JPanel mainPane;
+    private CardLayout cardLayout;
+    private JTree structureTree;
+    private JTree typeTree;
+    private JComboBox viewAsCombo;
+
+    private boolean selectionInProgress;
+
+    public TreeModelPane()
+    {
+        setLayout( new BorderLayout() );
+
+        // init mainPane
+        structureTree = new JTree();
+        structureTree.setRootVisible( false );
+        structureTree.setShowsRootHandles( true );
+        structureTree.setExpandsSelectedPaths( true );
+        structureTree.setScrollsOnExpand( true );
+        structureTree.setName( STRUCTURE_VIEW );
+        structureTree.setCellRenderer( new TreeModelCellRenderer() );
+
+        typeTree = new JTree();
+        typeTree.setRootVisible( false );
+        typeTree.setShowsRootHandles( true );
+        typeTree.setExpandsSelectedPaths( true );
+        typeTree.setScrollsOnExpand( true );
+        typeTree.setName( TYPE_VIEW );
+        typeTree.setCellRenderer( new TreeModelCellRenderer() );
+
+        mainPane = new JPanel();
+        cardLayout = new CardLayout();
+        mainPane.setLayout( cardLayout );
+        mainPane.add( new JScrollPane( structureTree ), STRUCTURE_VIEW );
+        mainPane.add( new JScrollPane( typeTree ), TYPE_VIEW );
+        add( mainPane, BorderLayout.CENTER );
+
+        // init viewAsCombo
+        JPanel viewAsPane = new JPanel();
+        viewAsPane.setBorder( BorderFactory.createEmptyBorder( 3, 6, 3, 0 ) );
+        viewAsPane.setLayout( new java.awt.GridBagLayout() );
+
+        GridBagConstraints gridBagConstraints;
+        JLabel viewAsLabel = new JLabel( BUNDLE.getString( "CTL_ViewAs.Text" ) );
+        gridBagConstraints = new GridBagConstraints();
+        gridBagConstraints.anchor = GridBagConstraints.WEST;
+        gridBagConstraints.insets = new Insets( 0, 0, 0, 6 );
+        viewAsPane.add( viewAsLabel, gridBagConstraints );
+
+        viewAsCombo = new JComboBox( new DefaultComboBoxModel( new String[]
+        {
+            STRUCTURE_VIEW, TYPE_VIEW
+        } ) );
+        gridBagConstraints = new GridBagConstraints();
+        gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
+        gridBagConstraints.weightx = 1.0;
+        viewAsPane.add( viewAsCombo, gridBagConstraints );
+
+        viewAsCombo.addItemListener(
+            evt ->
+            {
+                if( evt.getStateChange() == ItemEvent.DESELECTED )
+                {
+                    return;
+                }
+                cardLayout.show( mainPane, evt.getItem().toString() );
+                repaint();
+            } );
+
+        add( viewAsPane, BorderLayout.PAGE_START );
+    }
+
+    /**
+     * Initialize Apache Polygene for this component
+     *
+     * @param descriptor the Application descriptor
+     */
+    public void initPolygene( ApplicationDetailDescriptor descriptor )
+    {
+        // traverse the model and build JTree representation
+        MutableTreeNode rootNode1 = StructureModelBuilder.build( descriptor );
+        MutableTreeNode rootNode2 = TypeModelBuilder.build( descriptor );
+
+        structureTree.setModel( new DefaultTreeModel( rootNode1 ) );
+        typeTree.setModel( new DefaultTreeModel( rootNode2 ) );
+
+        structureTree.addTreeSelectionListener( evt -> structureTreeValueChanged() );
+
+        typeTree.addTreeSelectionListener( evt -> typeTreeValueChanged() );
+    }
+
+    public Object getLastSelected()
+    {
+        Object obj = structureTree.getLastSelectedPathComponent();
+        if( obj != null )
+        {
+            return ( (DefaultMutableTreeNode) obj ).getUserObject();
+        }
+        return null;
+    }
+
+    public void setSelectedValue( Object obj )
+    {
+        if( obj == null )
+        {
+            return;
+        }
+
+        TreeNode node = findNode( structureTree, obj );
+        if( node != null )
+        {
+            DefaultTreeModel treeModel = (DefaultTreeModel) structureTree.getModel();
+            TreePath treePath = new TreePath( treeModel.getPathToRoot( node ) );
+            structureTree.setSelectionPath( treePath );
+            structureTree.scrollPathToVisible( treePath );
+        }
+        else
+        {
+            structureTree.clearSelection();
+        }
+    }
+
+    /**
+     * Just a helper method to find the node which contains the userObject
+     *
+     * @param tree   the JTree to search into
+     * @param object the user object
+     *
+     * @return TreeNode or null
+     */
+    protected TreeNode findNode( JTree tree, Object object )
+    {
+        DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getModel().getRoot();
+        return findNode( node, object );
+    }
+
+    /**
+     * Recurvice search or find node that contains the obj
+     *
+     * @param node DefaultMutableTreeNode
+     * @param obj  userObject
+     *
+     * @return TreeNode or null if could not find
+     */
+    private TreeNode findNode( DefaultMutableTreeNode node, Object obj )
+    {
+        if( obj instanceof String )
+        {
+            if( node.getUserObject().toString().equals( obj.toString() ) )
+            {
+                return node;
+            }
+        }
+        else if( node.getUserObject().equals( obj ) )
+        {
+            return node;
+        }
+
+        TreeNode foundNode = null;
+        for( int i = 0; i < node.getChildCount(); i++ )
+        {
+            DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) node.getChildAt( i );
+            foundNode = findNode( childNode, obj );
+            if( foundNode != null )
+            {
+                break;
+            }
+        }
+
+        return foundNode;
+    }
+
+    public final void addTreeSelectionListener( TreeSelectionListener listener )
+    {
+        structureTree.addTreeSelectionListener( listener );
+    }
+
+    public final void removeTreeSelectionListener( TreeSelectionListener listener )
+    {
+        structureTree.removeTreeSelectionListener( listener );
+    }
+
+    protected void structureTreeValueChanged()
+    {
+        if( selectionInProgress )
+        {
+            return;
+        }
+
+        Object userObject = getLastSelected();
+        if( userObject == null )
+        {
+            return;
+        }
+        TreeNode node = findNode( typeTree, userObject );
+        if( node != null )
+        {
+            DefaultTreeModel treeModel = (DefaultTreeModel) typeTree.getModel();
+            TreePath treePath = new TreePath( treeModel.getPathToRoot( node ) );
+            typeTree.setSelectionPath( treePath );
+            typeTree.scrollPathToVisible( treePath );
+        }
+    }
+
+    protected void typeTreeValueChanged()
+    {
+        Object obj = typeTree.getLastSelectedPathComponent();
+        if( obj == null )
+        {
+            return;
+        }
+        Object userObject = ( (DefaultMutableTreeNode) obj ).getUserObject();
+        TreeNode node = findNode( structureTree, userObject );
+        if( node != null )
+        {
+            DefaultTreeModel treeModel = (DefaultTreeModel) structureTree.getModel();
+            TreePath treePath = new TreePath( treeModel.getPathToRoot( node ) );
+
+            selectionInProgress = true;
+            try
+            {
+                structureTree.setSelectionPath( treePath );
+            }
+            finally
+            {
+                selectionInProgress = false;
+            }
+            structureTree.scrollPathToVisible( treePath );
+        }
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/tree/TypeModelBuilder.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/tree/TypeModelBuilder.java
new file mode 100644
index 0000000..f3c0800
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/tree/TypeModelBuilder.java
@@ -0,0 +1,154 @@
+/*
+ *  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.polygene.envisage.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.MutableTreeNode;
+import org.apache.polygene.tools.model.descriptor.*;
+import org.apache.polygene.tools.model.util.DescriptorNameComparator;
+
+/**
+ * Helper class to build tree model for Polygene model as Type Tree
+ */
+/* package */ final class TypeModelBuilder
+{
+    private final List<ServiceDetailDescriptor> serviceList = new ArrayList<>();
+    private final List<ImportedServiceDetailDescriptor> importedServiceList = new ArrayList<>();
+    private final List<EntityDetailDescriptor> entityList = new ArrayList<>();
+    private final List<TransientDetailDescriptor> transientList = new ArrayList<>();
+    private final List<ValueDetailDescriptor> valueList = new ArrayList<>();
+    private final List<ObjectDetailDescriptor> objectList = new ArrayList<>();
+
+    /* package */ static MutableTreeNode build( ApplicationDetailDescriptor descriptor )
+    {
+        TypeModelBuilder builder = new TypeModelBuilder();
+        return builder.buildNode( descriptor );
+    }
+
+    private TypeModelBuilder()
+    {
+    }
+
+    private MutableTreeNode buildNode( ApplicationDetailDescriptor descriptor )
+    {
+        traverseLayers( descriptor.layers() );
+
+        DescriptorNameComparator<Object> nameComparator = new DescriptorNameComparator<>();
+
+        // sort based on name order
+        serviceList.sort( nameComparator );
+        importedServiceList.sort( nameComparator );
+        entityList.sort( nameComparator );
+        transientList.sort( nameComparator );
+        valueList.sort( nameComparator );
+        objectList.sort( nameComparator );
+
+        DefaultMutableTreeNode root = new DefaultMutableTreeNode( descriptor );
+        DefaultMutableTreeNode child;
+
+        child = new DefaultMutableTreeNode( "Services" );
+        addChild( child, serviceList );
+        root.add( child );
+
+        child = new DefaultMutableTreeNode( "Imported Services" );
+        addChild( child, importedServiceList );
+        root.add( child );
+
+        child = new DefaultMutableTreeNode( "Entities" );
+        addChild( child, entityList );
+        root.add( child );
+
+        child = new DefaultMutableTreeNode( "Transients" );
+        addChild( child, transientList );
+        root.add( child );
+
+        child = new DefaultMutableTreeNode( "Values" );
+        addChild( child, valueList );
+        root.add( child );
+
+        child = new DefaultMutableTreeNode( "Objects" );
+        addChild( child, objectList );
+        root.add( child );
+
+        return root;
+    }
+
+    private void addChild( DefaultMutableTreeNode node, List list )
+    {
+        for( Object obj : list )
+        {
+            node.add( new DefaultMutableTreeNode( obj ) );
+        }
+    }
+
+    private void traverseLayers( Iterable<LayerDetailDescriptor> iter )
+    {
+        for( LayerDetailDescriptor descriptor : iter )
+        {
+            traverseModules( descriptor.modules() );
+        }
+    }
+
+    private void traverseModules( Iterable<ModuleDetailDescriptor> iter )
+    {
+        for( ModuleDetailDescriptor descriptor : iter )
+        {
+
+            // Services
+            for( ServiceDetailDescriptor child : descriptor.services() )
+            {
+                serviceList.add( child );
+            }
+
+            // Imported Services
+            for( ImportedServiceDetailDescriptor child : descriptor.importedServices() )
+            {
+                importedServiceList.add( child );
+            }
+
+            // Entities
+            for( EntityDetailDescriptor child : descriptor.entities() )
+            {
+                entityList.add( child );
+            }
+
+            // Transient
+            for( TransientDetailDescriptor child : descriptor.transients() )
+            {
+                transientList.add( child );
+            }
+
+            //Values
+            for( ValueDetailDescriptor child : descriptor.values() )
+            {
+                valueList.add( child );
+            }
+
+            // Objects
+            for( ObjectDetailDescriptor child : descriptor.objects() )
+            {
+                objectList.add( child );
+            }
+        }
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/tree/package.html b/tools/envisage/src/main/java/org/apache/polygene/envisage/tree/package.html
new file mode 100644
index 0000000..8d1d1f3
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/tree/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Envisage Tool Application Tree.</h2>
+    </body>
+</html>
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/util/ColorUtilities.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/util/ColorUtilities.java
new file mode 100644
index 0000000..59dee17
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/util/ColorUtilities.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.envisage.util;
+
+import java.awt.Color;
+
+/**
+ * Collection of Color Utilities
+ */
+public class ColorUtilities
+{
+
+    /**
+     * Return the equivalent AWT {@code Color} of the supplied hexString in format eg #FF33D2.
+     *
+     * @param hexString Color in hexString format eg: #FF33D2
+     * @return the AWT {@code Color} or null if fail to parse
+     */
+    public static Color hexStringToColor( String hexString )
+    {
+        Color color = null;
+        int r, g, b;
+        try
+        {
+            String tmpStr = hexString.substring( 1, 3 );
+            r = Integer.parseInt( tmpStr, 16 );
+            tmpStr = hexString.substring( 3, 5 );
+            g = Integer.parseInt( tmpStr, 16 );
+            tmpStr = hexString.substring( 5, 7 );
+            b = Integer.parseInt( tmpStr, 16 );
+            color = new Color( r, g, b );
+        }
+        catch( NumberFormatException | IndexOutOfBoundsException e )
+        {
+            e.printStackTrace();
+        }
+        return color;
+    }
+
+    private ColorUtilities()
+    {
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/util/TableRow.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/util/TableRow.java
new file mode 100644
index 0000000..fbd9147
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/util/TableRow.java
@@ -0,0 +1,71 @@
+/*
+ *  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.polygene.envisage.util;
+
+import java.util.ArrayList;
+
+/**
+ * A simple data structure like table row
+ */
+public final class TableRow
+{
+
+    protected ArrayList data;
+
+    public TableRow( int col )
+    {
+        this( col, new Object[ 0 ] );
+    }
+
+    public TableRow( int col, Object... values )
+    {
+        data = new ArrayList( col );
+
+        for( int i = 0; i < col; i++ )
+        {
+            if( values == null || values.length == 0 )
+            {
+                set( i, null );
+            }
+            else
+            {
+                if( values.length > i )
+                {
+                    set( i, values[ i] );
+                }
+                else
+                {
+                    set( i, values[ i] );
+                }
+            }
+        }
+    }
+
+    public void set( int col, Object object )
+    {
+        data.add( col, object );
+    }
+
+    public Object get( int col )
+    {
+        return data.get( col );
+    }
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/util/TableRowUtilities.java b/tools/envisage/src/main/java/org/apache/polygene/envisage/util/TableRowUtilities.java
new file mode 100644
index 0000000..1a03c36
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/util/TableRowUtilities.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.envisage.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.tools.model.descriptor.MixinDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ObjectDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ServiceUsage;
+
+public final class TableRowUtilities
+{
+
+    public static List<TableRow> toTableRows( List<ServiceUsage> serviceUsages )
+    {
+        List<TableRow> rows = new ArrayList<>();
+        for( ServiceUsage usage : serviceUsages )
+        {
+            TableRow row = new TableRow( 5 );
+            if( usage.ownerDescriptor() instanceof MixinDetailDescriptor )
+            {
+                MixinDetailDescriptor mixinDescriptor = (MixinDetailDescriptor) usage.ownerDescriptor();
+                row.set( 0, mixinDescriptor.composite() );
+                row.set( 1, usage.field() );
+                row.set( 2, mixinDescriptor.composite().module() );
+                row.set( 3, mixinDescriptor.composite().module().layer() );
+            }
+            else
+            {
+                // assume ObjectDetailDescriptor
+                ObjectDetailDescriptor objectDescriptor = (ObjectDetailDescriptor) usage.ownerDescriptor();
+                row.set( 0, objectDescriptor );
+                row.set( 1, usage.field() );
+                row.set( 2, objectDescriptor.module() );
+                row.set( 3, objectDescriptor.module().layer() );
+            }
+            rows.add( row );
+        }
+        return rows;
+    }
+
+    private TableRowUtilities()
+    {
+    }
+
+}
diff --git a/tools/envisage/src/main/java/org/apache/polygene/envisage/util/package.html b/tools/envisage/src/main/java/org/apache/polygene/envisage/util/package.html
new file mode 100644
index 0000000..b6d836b
--- /dev/null
+++ b/tools/envisage/src/main/java/org/apache/polygene/envisage/util/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Envisage Tool Utilities.</h2>
+    </body>
+</html>
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/Envisage.java b/tools/envisage/src/main/java/org/qi4j/envisage/Envisage.java
deleted file mode 100644
index 5f8128d..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/Envisage.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage;
-
-import com.jgoodies.looks.LookUtils;
-import com.jgoodies.looks.Options;
-import com.jgoodies.looks.plastic.PlasticLookAndFeel;
-import com.jgoodies.looks.plastic.theme.ExperienceBlue;
-import java.awt.Dimension;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-import javax.swing.JFrame;
-import javax.swing.LookAndFeel;
-import javax.swing.SwingUtilities;
-import javax.swing.UIManager;
-import javax.swing.UnsupportedLookAndFeelException;
-import org.qi4j.api.structure.ApplicationDescriptor;
-
-/**
- * Qi4J Application Viewer
- */
-public class Envisage
-{
-
-    protected ApplicationDescriptor application;
-
-    private EnvisageFrame mainFrame;
-
-    public void run( ApplicationDescriptor application )
-    {
-        initLookAndFeel();
-
-        this.application = application;
-
-        SwingUtilities.invokeLater( new Runnable()
-        {
-            @Override
-            public void run()
-            {
-                showMainFrame();
-            }
-        } );
-    }
-
-    public void stop()
-    {
-        if( mainFrame != null && mainFrame.isDisplayable() )
-        {
-            mainFrame.dispose();
-            mainFrame = null;
-        }
-    }
-
-    private void showMainFrame()
-    {
-        mainFrame = new EnvisageFrame( application );
-        mainFrame.setLocationByPlatform( true );
-        mainFrame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
-        mainFrame.setSize( new Dimension( 1024, 768 ) );
-        mainFrame.setVisible( true );
-
-        mainFrame.addWindowListener( new WindowAdapter()
-        {
-            @Override
-            public void windowOpened( WindowEvent evt )
-            {
-                SwingUtilities.invokeLater( new Runnable()
-                {
-                    @Override
-                    public void run()
-                    {
-                        mainFrame.initQi4J();
-                    }
-                } );
-            }
-        } );
-    }
-
-    private void initLookAndFeel()
-    {
-        String osName = System.getProperty( "os.name" ).toUpperCase();
-
-        // set to use swing anti alias text only for JVM <= 1.5
-        System.setProperty( "swing.aatext", "true" );
-
-        // set default swing bold to false, only for JVM 1.5 or above
-        UIManager.put( "swing.boldMetal", Boolean.FALSE );
-
-        // set LaF
-        LookAndFeel lnf = UIManager.getLookAndFeel();
-        if( lnf != null && lnf.getID().equalsIgnoreCase( "Metal" ) )
-        {
-            final String lnfClassName;
-            if( osName.startsWith( "MAC" ) )
-            {
-                System.setProperty( "com.apple.mrj.application.apple.menu.about.name", "Envisage" ); //TODO i18n
-                System.setProperty( "apple.laf.useScreenMenuBar", "true" );
-                lnfClassName = UIManager.getSystemLookAndFeelClassName();
-            }
-            else if( osName.startsWith( "WINDOWS" ) )
-            {
-                UIManager.put( "ClassLoader", LookUtils.class.getClassLoader() );
-                lnfClassName = Options.getSystemLookAndFeelClassName();
-                Options.setUseNarrowButtons( false );
-            }
-            else
-            {
-                UIManager.put( "ClassLoader", LookUtils.class.getClassLoader() );
-                lnfClassName = Options.getCrossPlatformLookAndFeelClassName();
-                PlasticLookAndFeel.setTabStyle( PlasticLookAndFeel.TAB_STYLE_METAL_VALUE );
-                PlasticLookAndFeel.setPlasticTheme( new ExperienceBlue() );
-                Options.setUseNarrowButtons( false );
-                //PlasticLookAndFeel.setMyCurrentTheme(new ExperienceBlueDefaultFont());  // for CJK Font
-            }
-
-            if( lnfClassName != null )
-            {
-                try
-                {
-                    UIManager.setLookAndFeel( lnfClassName );
-                }
-                catch( ClassNotFoundException | IllegalAccessException | InstantiationException |
-                       UnsupportedLookAndFeelException ex )
-                {
-                    System.err.println( "Unable to set LookAndFeel, use default LookAndFeel.\n" + ex.getMessage() );
-                }
-            }
-        }
-    }
-
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/EnvisageFrame.form b/tools/envisage/src/main/java/org/qi4j/envisage/EnvisageFrame.form
deleted file mode 100644
index 07a444e..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/EnvisageFrame.form
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.qi4j.envisage.EnvisageFrame">
-  <grid id="27dc6" binding="contentPane" layout-manager="BorderLayout" hgap="0" vgap="0">
-    <constraints>
-      <xy x="20" y="20" width="500" height="400"/>
-    </constraints>
-    <properties/>
-    <border type="none"/>
-    <children/>
-  </grid>
-</form>
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/EnvisageFrame.java b/tools/envisage/src/main/java/org/qi4j/envisage/EnvisageFrame.java
deleted file mode 100644
index dd0eed5..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/EnvisageFrame.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage;
-
-import java.awt.BorderLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.KeyEvent;
-import java.util.ResourceBundle;
-import javax.swing.JComponent;
-import javax.swing.JFrame;
-import javax.swing.JMenu;
-import javax.swing.JMenuBar;
-import javax.swing.JMenuItem;
-import javax.swing.JPanel;
-import javax.swing.JSplitPane;
-import javax.swing.KeyStroke;
-import javax.swing.SwingUtilities;
-import javax.swing.event.TreeSelectionEvent;
-import javax.swing.event.TreeSelectionListener;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.envisage.detail.DetailModelPane;
-import org.qi4j.envisage.event.LinkEvent;
-import org.qi4j.envisage.event.LinkListener;
-import org.qi4j.envisage.graph.GraphPane;
-import org.qi4j.envisage.print.PDFWriter;
-import org.qi4j.envisage.tree.TreeModelPane;
-import org.qi4j.tools.model.descriptor.ApplicationDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ApplicationDetailDescriptorBuilder;
-
-/**
- * Envisage Main Frame
- */
-public final class EnvisageFrame
-    extends JFrame
-{
-    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( EnvisageFrame.class.getName() );
-
-    private JPanel contentPane;
-    private final JSplitPane graphSplitPane;
-    private final JSplitPane modelSplitPane;
-
-    private final GraphPane graphPane;
-    private final TreeModelPane treeModelPane;
-    private final DetailModelPane detailModelPane;
-
-    private final ApplicationDescriptor application;
-    private ApplicationDetailDescriptor descriptor;
-
-    private boolean graphItemSelectionInProgress;
-
-    public EnvisageFrame( ApplicationDescriptor application )
-    {
-        this.application = application;
-
-        setTitle( BUNDLE.getString( "Application.Title" ) );
-        setContentPane( contentPane );
-
-        graphPane = new GraphPane();
-        treeModelPane = new TreeModelPane();
-        detailModelPane = new DetailModelPane();
-
-        treeModelPane.addTreeSelectionListener( new TreeSelectionListener()
-        {
-            @Override
-            public void valueChanged( TreeSelectionEvent evt )
-            {
-                applicationModelPaneValueChanged();
-            }
-        } );
-
-        graphPane.addLinkListener( new LinkListener()
-        {
-            @Override
-            public void activated( LinkEvent evt )
-            {
-                graphItemLinkActivated( evt );
-            }
-        } );
-
-        detailModelPane.addLinkListener( new LinkListener()
-        {
-            @Override
-            public void activated( LinkEvent evt )
-            {
-                detailModelPaneLinkActivated( evt );
-            }
-        } );
-
-        modelSplitPane = new JSplitPane();
-        modelSplitPane.setOrientation( JSplitPane.HORIZONTAL_SPLIT );
-        modelSplitPane.setDividerLocation( 300 );
-        modelSplitPane.setOneTouchExpandable( true );
-        modelSplitPane.setLeftComponent( treeModelPane );
-        modelSplitPane.setRightComponent( detailModelPane );
-
-        graphSplitPane = new JSplitPane();
-        graphSplitPane.setOrientation( JSplitPane.VERTICAL_SPLIT );
-        graphSplitPane.setDividerLocation( 384 ); // 768/2
-        graphSplitPane.setOneTouchExpandable( true );
-        //graphSplitPane.setTopComponent( graphPane );
-        //graphSplitPane.setBottomComponent( modelSplitPane );
-        graphSplitPane.setTopComponent( modelSplitPane );
-        graphSplitPane.setBottomComponent( graphPane );
-
-        this.setJMenuBar( createMenu() );
-
-        contentPane.add( graphSplitPane, BorderLayout.CENTER );
-    }
-
-    public void initQi4J()
-    {
-        modelSplitPane.setDividerLocation( 300 );
-        graphSplitPane.setDividerLocation( 384 );
-
-        descriptor = ApplicationDetailDescriptorBuilder.createApplicationDetailDescriptor( application );
-        treeModelPane.initQi4J( descriptor );
-        graphPane.initQi4J( descriptor );
-    }
-
-    /**
-     * Create menubar
-     *
-     * @return JMenuBar
-     */
-    protected JMenuBar createMenu()
-    {
-        ActionListener menuActionListener = new ActionListener()
-        {
-            @Override
-            public void actionPerformed( ActionEvent evt )
-            {
-                if( evt.getActionCommand().equals( "export" ) )
-                {
-                    exportAsPDF();
-                }
-                if( evt.getActionCommand().equals( "exit" ) )
-                {
-                    System.exit( 0 );
-                }
-            }
-        };
-
-        // TODO i18n
-        JMenuBar menuBar = new JMenuBar();
-
-        JMenu menu = new JMenu( "File" );
-        menu.setMnemonic( KeyEvent.VK_F );
-        menuBar.add( menu );
-
-        JMenuItem menuItem = new JMenuItem( "Export As PDF", KeyEvent.VK_E );
-        menuItem.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_E, ActionEvent.CTRL_MASK ) );
-        menuItem.setActionCommand( "export" );
-        menuItem.addActionListener( menuActionListener );
-        menu.add( menuItem );
-
-        menuItem = new JMenuItem( "Exit", KeyEvent.VK_X );
-        menuItem.setActionCommand( "exit" );
-        menuItem.addActionListener( menuActionListener );
-        menu.add( menuItem );
-
-        return menuBar;
-    }
-
-    protected void applicationModelPaneValueChanged()
-    {
-        Object obj = treeModelPane.getLastSelected();
-        detailModelPane.setDescriptor( obj );
-        if( !graphItemSelectionInProgress )
-        {
-            graphPane.setSelectedValue( obj );
-        }
-    }
-
-    protected void graphItemLinkActivated( LinkEvent evt )
-    {
-        graphItemSelectionInProgress = true;
-        try
-        {
-            treeModelPane.setSelectedValue( evt.getObject() );
-        }
-        finally
-        {
-            graphItemSelectionInProgress = false;
-        }
-    }
-
-    protected void detailModelPaneLinkActivated( LinkEvent evt )
-    {
-        treeModelPane.setSelectedValue( evt.getObject() );
-    }
-
-    protected void exportAsPDF()
-    {
-        SwingUtilities.invokeLater( new Runnable()
-        {
-            @Override
-            public void run()
-            {
-                PDFWriter pdf = new PDFWriter();
-                pdf.write( EnvisageFrame.this, descriptor, graphPane.getGraphDisplays() );
-            }
-        } );
-    }
-
-    
-    {
-// GUI initializer generated by IntelliJ IDEA GUI Designer
-// >>> IMPORTANT!! <<<
-// DO NOT EDIT OR ADD ANY CODE HERE!
-        $$$setupUI$$$();
-    }
-
-    /**
-     * Method generated by IntelliJ IDEA GUI Designer
-     * >>> IMPORTANT!! <<<
-     * DO NOT edit this method OR call it in your code!
-     *
-     */
-    private void $$$setupUI$$$()
-    {
-        contentPane = new JPanel();
-        contentPane.setLayout( new BorderLayout( 0, 0 ) );
-    }
-
-    public JComponent $$$getRootComponent$$$()
-    {
-        return contentPane;
-    }
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/Main.java b/tools/envisage/src/main/java/org/qi4j/envisage/Main.java
deleted file mode 100644
index 83414c6..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/Main.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage;
-
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.Energy4Java;
-
-/**
- * Start Envisage with a specified application assembler. Specify assembler class
- * as first parameter.
- */
-public class Main
-{
-    public static void main( String[] args )
-        throws ClassNotFoundException, IllegalAccessException, InstantiationException, AssemblyException
-    {
-        String applicationAssemblerName = args[0];
-        Class applicationAssemblerClass = Class.forName( applicationAssemblerName );
-        ApplicationAssembler assembler = (ApplicationAssembler) applicationAssemblerClass.newInstance();
-
-        Energy4Java energy4Java = new Energy4Java();
-
-        ApplicationDescriptor application = energy4Java.newApplicationModel( assembler );
-
-        new Envisage().run( application );
-    }
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/APIPane.form b/tools/envisage/src/main/java/org/qi4j/envisage/detail/APIPane.form
deleted file mode 100644
index d59d086..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/APIPane.form
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.qi4j.envisage.detail.APIPane">
-  <grid id="27dc6" binding="contentPane" layout-manager="BorderLayout" hgap="0" vgap="0">
-    <constraints>
-      <xy x="20" y="20" width="500" height="400"/>
-    </constraints>
-    <properties/>
-    <border type="none"/>
-    <children>
-      <scrollpane id="2c325">
-        <constraints border-constraint="Center"/>
-        <properties/>
-        <border type="none"/>
-        <children>
-          <component id="a2e7d" class="javax.swing.JTable" binding="apiTable">
-            <constraints/>
-            <properties>
-              <showVerticalLines value="true"/>
-            </properties>
-          </component>
-        </children>
-      </scrollpane>
-    </children>
-  </grid>
-</form>
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/APIPane.java b/tools/envisage/src/main/java/org/qi4j/envisage/detail/APIPane.java
deleted file mode 100644
index b1c4925..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/APIPane.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.detail;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.Cursor;
-import java.awt.event.MouseEvent;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ResourceBundle;
-import javax.swing.JComponent;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTable;
-import javax.swing.ListSelectionModel;
-import javax.swing.event.MouseInputAdapter;
-import javax.swing.table.AbstractTableModel;
-import javax.swing.table.DefaultTableCellRenderer;
-import javax.swing.table.TableColumnModel;
-import org.qi4j.envisage.event.LinkEvent;
-import org.qi4j.envisage.util.TableRow;
-import org.qi4j.tools.model.descriptor.LayerDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ModuleDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ServiceDetailDescriptor;
-import org.qi4j.tools.model.util.DescriptorUtilities;
-
-/**
- * API would be defined as "All service interfaces which are visible for layer
- * or application" and SPI would be defined as "All service dependencies which
- * are not satisfied from within the module". And then similar for Layer. This
- * way you can select a Module/Layer and immediately see what it produces as
- * output and requires as input. This is also very very nice for documentation
- * purposes.
- */
-/* package */ final class APIPane
-    extends DetailPane
-{
-    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( APIPane.class.getName() );
-
-    private JPanel contentPane;
-    private JTable apiTable;
-    private APITableModel apiTableModel;
-
-    private Object linkObject;
-    private Cursor defaultCursor;
-    private Cursor linkCursor;
-
-    /* package */ APIPane( DetailModelPane detailModelPane )
-    {
-        super( detailModelPane );
-        this.setLayout( new BorderLayout() );
-        this.add( contentPane, BorderLayout.CENTER );
-
-        apiTableModel = new APITableModel();
-        apiTable.setModel( apiTableModel );
-        apiTable.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
-
-        TableColumnModel columnModel = apiTable.getColumnModel();
-        columnModel.getColumn( 0 ).setCellRenderer( new ServiceCellRenderer() );
-
-        defaultCursor = getCursor();
-        linkCursor = LinkEvent.LINK_CURSOR;
-
-        MouseInputAdapter mouseInputListener = new MouseInputAdapter()
-        {
-            @Override
-            public void mouseMoved( MouseEvent evt )
-            {
-                // Column 1 is the Service Column
-                int col = apiTable.columnAtPoint( evt.getPoint() );
-                if( col == 0 )
-                {
-                    setCursor( linkCursor );
-                }
-                else
-                {
-                    if( !getCursor().equals( defaultCursor ) )
-                    {
-                        setCursor( defaultCursor );
-                    }
-                }
-            }
-
-            @Override
-            public void mouseClicked( MouseEvent evt )
-            {
-                int col = apiTable.columnAtPoint( evt.getPoint() );
-                if( col != 0 )
-                {
-                    return;
-                }
-
-                int row = apiTable.rowAtPoint( evt.getPoint() );
-                if( row < 0 )
-                {
-                    return;
-                }
-
-                linkObject = apiTableModel.getValueAt( row, col );
-                linkActivated();
-                linkObject = null;
-            }
-        };
-
-        apiTable.addMouseMotionListener( mouseInputListener );
-        apiTable.addMouseListener( mouseInputListener );
-    }
-
-    @Override
-    protected void setDescriptor( Object objectDesciptor )
-    {
-        clear();
-
-        List<ServiceDetailDescriptor> list = null;
-        if( objectDesciptor instanceof LayerDetailDescriptor )
-        {
-            list = DescriptorUtilities.findLayerAPI( (LayerDetailDescriptor) objectDesciptor );
-        }
-        else if( objectDesciptor instanceof ModuleDetailDescriptor )
-        {
-            list = DescriptorUtilities.findModuleAPI( (ModuleDetailDescriptor) objectDesciptor );
-        }
-
-        if( list != null )
-        {
-            apiTableModel.addRow( list );
-        }
-    }
-
-    private void clear()
-    {
-        linkObject = null;
-        apiTableModel.clear();
-    }
-
-    private void linkActivated()
-    {
-        if( linkObject == null )
-        {
-            return;
-        }
-        LinkEvent linkEvt = new LinkEvent( this, linkObject );
-        detailModelPane.fireLinkActivated( linkEvt );
-    }
-
-    
-    {
-// GUI initializer generated by IntelliJ IDEA GUI Designer
-// >>> IMPORTANT!! <<<
-// DO NOT EDIT OR ADD ANY CODE HERE!
-        $$$setupUI$$$();
-    }
-
-    /**
-     * Method generated by IntelliJ IDEA GUI Designer
-     * >>> IMPORTANT!! <<<
-     * DO NOT edit this method OR call it in your code!
-     *
-     */
-    private void $$$setupUI$$$()
-    {
-        contentPane = new JPanel();
-        contentPane.setLayout( new BorderLayout( 0, 0 ) );
-        final JScrollPane scrollPane1 = new JScrollPane();
-        contentPane.add( scrollPane1, BorderLayout.CENTER );
-        apiTable = new JTable();
-        apiTable.setShowVerticalLines( true );
-        scrollPane1.setViewportView( apiTable );
-    }
-
-    public JComponent $$$getRootComponent$$$()
-    {
-        return contentPane;
-    }
-
-    private static class APITableModel
-        extends AbstractTableModel
-    {
-        /**
-         * the column names for this model
-         */
-        private static final String[] COLUMN_NAMES =
-        {
-            BUNDLE.getString( "Service.Column" ),
-            BUNDLE.getString( "Module.Column" ),
-            BUNDLE.getString( "Visibility.Column" )
-        };
-        private final ArrayList<TableRow> rows;
-
-        private APITableModel()
-        {
-            rows = new ArrayList<>();
-        }
-
-        private void addRow( List<ServiceDetailDescriptor> list )
-        {
-            if( list.isEmpty() )
-            {
-                return;
-            }
-
-            int i1 = rows.size();
-            if( i1 > 0 )
-            {
-                i1--;
-            }
-
-            int i2 = 0;
-
-            for( ServiceDetailDescriptor descriptor : list )
-            {
-                TableRow row = new TableRow( COLUMN_NAMES.length );
-                row.set( 0, descriptor );
-                row.set( 1, descriptor.module() );
-                row.set( 2, descriptor.descriptor().visibility().toString() );
-                this.rows.add( row );
-                i2++;
-            }
-
-            fireTableRowsInserted( i1, i1 + i2 );
-        }
-
-        @Override
-        public Object getValueAt( int rowIndex, int columnIndex )
-        {
-            TableRow row = rows.get( rowIndex );
-            return row.get( columnIndex );
-        }
-
-        private void clear()
-        {
-            rows.clear();
-            fireTableDataChanged();
-        }
-
-        @Override
-        public int getColumnCount()
-        {
-            return COLUMN_NAMES.length;
-        }
-
-        @Override
-        public String getColumnName( int col )
-        {
-            return COLUMN_NAMES[ col];
-        }
-
-        @Override
-        public int getRowCount()
-        {
-            return rows.size();
-        }
-    }
-
-    private static class ServiceCellRenderer
-        extends DefaultTableCellRenderer
-    {
-        @Override
-        public final Component getTableCellRendererComponent( JTable table,
-                                                              Object value,
-                                                              boolean isSelected,
-                                                              boolean hasFocus,
-                                                              int row,
-                                                              int column
-        )
-        {
-            if( value != null )
-            {
-                value = "<html><a href=\"" + value.toString() + "\">" + value.toString() + "</a></html>";
-            }
-
-            super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );
-
-            return this;
-        }
-    }
-
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/DependencyPane.form b/tools/envisage/src/main/java/org/qi4j/envisage/detail/DependencyPane.form
deleted file mode 100644
index c69348b..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/DependencyPane.form
+++ /dev/null
@@ -1,212 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.qi4j.envisage.detail.DependencyPane">
-  <grid id="27dc6" binding="contentPane" layout-manager="BorderLayout" hgap="0" vgap="0">
-    <constraints>
-      <xy x="20" y="20" width="545" height="400"/>
-    </constraints>
-    <properties/>
-    <border type="none"/>
-    <children>
-      <splitpane id="1f500" binding="splitPane">
-        <constraints border-constraint="Center"/>
-        <properties/>
-        <border type="none"/>
-        <children>
-          <scrollpane id="1c16d">
-            <constraints>
-              <splitpane position="left"/>
-            </constraints>
-            <properties/>
-            <border type="none"/>
-            <children>
-              <component id="1b715" class="javax.swing.JList" binding="fieldList">
-                <constraints/>
-                <properties/>
-              </component>
-            </children>
-          </scrollpane>
-          <grid id="84919" binding="detailPane" layout-manager="GridBagLayout">
-            <constraints>
-              <splitpane position="right"/>
-            </constraints>
-            <properties/>
-            <border type="empty">
-              <size top="8" left="8" bottom="8" right="8"/>
-            </border>
-            <children>
-              <component id="6df32" class="javax.swing.JLabel">
-                <constraints>
-                  <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="0.0"/>
-                </constraints>
-                <properties>
-                  <text resource-bundle="org/qi4j/envisage/detail/DependencyPane" key="CTL_ClassName.Text"/>
-                </properties>
-              </component>
-              <hspacer id="ef53d">
-                <constraints>
-                  <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="0.0"/>
-                </constraints>
-              </hspacer>
-              <vspacer id="74134">
-                <constraints>
-                  <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="0.0"/>
-                </constraints>
-              </vspacer>
-              <component id="5284c" class="javax.swing.JLabel">
-                <constraints>
-                  <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="0.0"/>
-                </constraints>
-                <properties>
-                  <text resource-bundle="org/qi4j/envisage/detail/DependencyPane" key="CTL_Optional.Text"/>
-                </properties>
-              </component>
-              <component id="dcc55" class="javax.swing.JLabel">
-                <constraints>
-                  <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="0.0"/>
-                </constraints>
-                <properties>
-                  <text resource-bundle="org/qi4j/envisage/detail/DependencyPane" key="CTL_Annotation.Text"/>
-                </properties>
-              </component>
-              <vspacer id="90e22">
-                <constraints>
-                  <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="0.0"/>
-                </constraints>
-              </vspacer>
-              <vspacer id="a26b7">
-                <constraints>
-                  <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="0.0"/>
-                </constraints>
-              </vspacer>
-              <vspacer id="dc18d">
-                <constraints>
-                  <grid row="9" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="0.0"/>
-                </constraints>
-              </vspacer>
-              <component id="f44fe" class="javax.swing.JLabel">
-                <constraints>
-                  <grid row="10" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="0.0"/>
-                </constraints>
-                <properties>
-                  <text resource-bundle="org/qi4j/envisage/detail/DependencyPane" key="CTL_InjectionType.Text"/>
-                </properties>
-              </component>
-              <component id="d289f" class="javax.swing.JLabel" binding="classNameLabel">
-                <constraints>
-                  <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="1.0" weighty="0.0"/>
-                </constraints>
-                <properties>
-                  <text value="none" noi18n="true"/>
-                </properties>
-              </component>
-              <component id="86b9a" class="javax.swing.JLabel" binding="annotationLabel">
-                <constraints>
-                  <grid row="4" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="0.0"/>
-                </constraints>
-                <properties>
-                  <text value="none" noi18n="true"/>
-                </properties>
-              </component>
-              <component id="d98ad" class="javax.swing.JLabel" binding="injectionTypeLabel">
-                <constraints>
-                  <grid row="10" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="0.0"/>
-                </constraints>
-                <properties>
-                  <text value="none" noi18n="true"/>
-                </properties>
-              </component>
-              <component id="ba440" class="javax.swing.JLabel" binding="optionalLabel">
-                <constraints>
-                  <grid row="2" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="0.0"/>
-                </constraints>
-                <properties>
-                  <text value="none" noi18n="true"/>
-                </properties>
-              </component>
-              <vspacer id="bce66">
-                <constraints>
-                  <grid row="7" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="0.0"/>
-                </constraints>
-              </vspacer>
-              <component id="43385" class="javax.swing.JLabel">
-                <constraints>
-                  <grid row="8" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="0.0"/>
-                </constraints>
-                <properties>
-                  <text resource-bundle="org/qi4j/envisage/detail/DependencyPane" key="CTL_Injection.Text"/>
-                </properties>
-              </component>
-              <scrollpane id="8506a">
-                <constraints>
-                  <grid row="12" column="2" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="1.0"/>
-                </constraints>
-                <properties/>
-                <border type="none"/>
-                <children>
-                  <component id="c96b8" class="javax.swing.JList" binding="injectedServiceList">
-                    <constraints/>
-                    <properties/>
-                  </component>
-                </children>
-              </scrollpane>
-              <vspacer id="3378c">
-                <constraints>
-                  <grid row="11" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="0.0"/>
-                </constraints>
-              </vspacer>
-              <component id="9cfc4" class="javax.swing.JLabel">
-                <constraints>
-                  <grid row="12" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="5" fill="0" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="0.0"/>
-                </constraints>
-                <properties>
-                  <text resource-bundle="org/qi4j/envisage/detail/DependencyPane" key="CTL_InjectedServices.Text"/>
-                </properties>
-              </component>
-              <component id="fb56b" class="javax.swing.JSeparator">
-                <constraints>
-                  <grid row="6" column="0" row-span="1" col-span="3" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
-                  <gridbag weightx="0.0" weighty="0.0"/>
-                </constraints>
-                <properties/>
-              </component>
-            </children>
-          </grid>
-        </children>
-      </splitpane>
-    </children>
-  </grid>
-</form>
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/DependencyPane.java b/tools/envisage/src/main/java/org/qi4j/envisage/detail/DependencyPane.java
deleted file mode 100644
index e593af0..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/DependencyPane.java
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.detail;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.Cursor;
-import java.awt.Dimension;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.event.MouseEvent;
-import java.lang.annotation.Annotation;
-import java.util.ResourceBundle;
-import javax.swing.BorderFactory;
-import javax.swing.DefaultListCellRenderer;
-import javax.swing.DefaultListModel;
-import javax.swing.JComponent;
-import javax.swing.JLabel;
-import javax.swing.JList;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JSeparator;
-import javax.swing.JSplitPane;
-import javax.swing.ListSelectionModel;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.event.MouseInputAdapter;
-import org.qi4j.api.composite.DependencyDescriptor;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.api.util.Classes;
-import org.qi4j.envisage.event.LinkEvent;
-import org.qi4j.tools.model.descriptor.CompositeDetailDescriptor;
-import org.qi4j.tools.model.descriptor.InjectedFieldDetailDescriptor;
-import org.qi4j.tools.model.descriptor.MixinDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ObjectDetailDescriptor;
-
-/* package */ final class DependencyPane
-    extends DetailPane
-{
-    private JPanel contentPane;
-    private JSplitPane splitPane;
-    private JList fieldList;
-    private JLabel classNameLabel;
-    private JLabel optionalLabel;
-    private JLabel annotationLabel;
-    private JLabel injectionTypeLabel;
-    private JList injectedServiceList;
-    private JPanel detailPane;
-
-    private final DefaultListModel fieldListModel;
-    private DefaultListModel injectedServiceListModel;
-
-    private Cursor defaultCursor;
-    private Cursor linkCursor;
-
-    /* package */ DependencyPane( DetailModelPane detailModelPane )
-    {
-        super( detailModelPane );
-        this.setLayout( new BorderLayout() );
-        this.add( contentPane, BorderLayout.CENTER );
-
-        fieldListModel = new DefaultListModel();
-        fieldList.setModel( fieldListModel );
-        fieldList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
-        fieldList.setPrototypeCellValue( "123456789012345" );
-
-        injectedServiceListModel = new DefaultListModel();
-        injectedServiceList.setModel( injectedServiceListModel );
-        injectedServiceList.setCellRenderer( new InjectedServiceListCellRenderer() );
-        injectedServiceList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
-        injectedServiceList.setPrototypeCellValue( "123456789012345" );
-
-        Dimension minSize = new Dimension( 20, 20 );
-        detailPane.setMinimumSize( minSize );
-
-        fieldList.addListSelectionListener( new ListSelectionListener()
-        {
-            @Override
-            public void valueChanged( ListSelectionEvent evt )
-            {
-                fieldListValueChanged( evt );
-            }
-        } );
-
-        defaultCursor = getCursor();
-        linkCursor = LinkEvent.LINK_CURSOR;
-
-        MouseInputAdapter mouseInputListener = new MouseInputAdapter()
-        {
-            @Override
-            public void mouseMoved( MouseEvent evt )
-            {
-                int i = injectedServiceList.locationToIndex( evt.getPoint() );
-                if( i != -1 )
-                {
-                    setCursor( linkCursor );
-                }
-                else
-                {
-                    setCursor( defaultCursor );
-                }
-            }
-
-            @Override
-            public void mouseExited( MouseEvent evt )
-            {
-                setCursor( defaultCursor );
-            }
-
-            @Override
-            public void mouseClicked( MouseEvent evt )
-            {
-                /*if( evt.getClickCount() < 2 )
-                 {
-                 return;
-                 }*/
-
-                int i = injectedServiceList.locationToIndex( evt.getPoint() );
-                if( i != -1 )
-                {
-                    Object linkObject = injectedServiceListModel.get( i );
-                    linkActivated( linkObject );
-                }
-            }
-        };
-
-        injectedServiceList.addMouseListener( mouseInputListener );
-        injectedServiceList.addMouseMotionListener( mouseInputListener );
-    }
-
-    private void linkActivated( Object linkObject )
-    {
-        if( linkObject == null )
-        {
-            return;
-        }
-        LinkEvent linkEvt = new LinkEvent( this, linkObject );
-        detailModelPane.fireLinkActivated( linkEvt );
-    }
-
-    private void clear()
-    {
-        fieldListModel.clear();
-        clearDetail();
-    }
-
-    private void clearDetail()
-    {
-        classNameLabel.setText( null );
-        classNameLabel.setToolTipText( null );
-        optionalLabel.setText( null );
-        annotationLabel.setText( null );
-        injectionTypeLabel.setText( null );
-        injectionTypeLabel.setToolTipText( null );
-        injectedServiceListModel.clear();
-    }
-
-    @Override
-    protected void setDescriptor( Object objectDesciptor )
-    {
-        clear();
-
-        if( objectDesciptor instanceof CompositeDetailDescriptor )
-        {
-            CompositeDetailDescriptor descriptor = ( (CompositeDetailDescriptor) objectDesciptor );
-            Iterable<MixinDetailDescriptor> iter = descriptor.mixins();
-            for( MixinDetailDescriptor mixinDescriptor : iter )
-            {
-                reload( mixinDescriptor.injectedFields() );
-            }
-        }
-        else if( objectDesciptor instanceof ObjectDetailDescriptor )
-        {
-            ObjectDetailDescriptor descriptor = ( (ObjectDetailDescriptor) objectDesciptor );
-            reload( descriptor.injectedFields() );
-        }
-
-        if( !fieldListModel.isEmpty() )
-        {
-            fieldList.setSelectedIndex( 0 );
-        }
-    }
-
-    private void reload( Iterable<InjectedFieldDetailDescriptor> iter )
-    {
-        for( InjectedFieldDetailDescriptor descriptor : iter )
-        {
-            DependencyDescriptor dependencyDescriptor = descriptor.descriptor().dependency();
-            Annotation annotation = dependencyDescriptor.injectionAnnotation();
-
-            if( isDependencyField( annotation.annotationType() ) )
-            {
-                fieldListModel.addElement( descriptor );
-            }
-        }
-    }
-
-    private void reloadDetail( InjectedFieldDetailDescriptor descriptor )
-    {
-        clearDetail();
-        if( descriptor == null )
-        {
-            return;
-        }
-
-        DependencyDescriptor dependencyDescriptor = descriptor.descriptor().dependency();
-
-        classNameLabel.setText( dependencyDescriptor.injectedClass().getSimpleName() );
-        classNameLabel.setToolTipText( dependencyDescriptor.injectedClass().getName() );
-        annotationLabel.setText( "@" + dependencyDescriptor.injectionAnnotation().annotationType().getSimpleName() );
-        optionalLabel.setText( Boolean.toString( dependencyDescriptor.optional() ) );
-        injectionTypeLabel.setText( Classes.simpleGenericNameOf( dependencyDescriptor.injectionType() ) );
-        injectionTypeLabel.setToolTipText( dependencyDescriptor.injectionType().toString() );
-    }
-
-    /**
-     * Check whether the type is a dependency field (Service and Use only)
-     *
-     * @param clazz the type
-     *
-     * @return true or false
-     */
-    private boolean isDependencyField( Class<? extends Annotation> clazz )
-    {
-        return Uses.class.equals( clazz ) || Service.class.equals( clazz );
-    }
-
-    private void fieldListValueChanged( ListSelectionEvent evt )
-    {
-        if( evt.getValueIsAdjusting() )
-        {
-            return;
-        }
-
-        reloadDetail( (InjectedFieldDetailDescriptor) fieldList.getSelectedValue() );
-    }
-
-    
-    {
-// GUI initializer generated by IntelliJ IDEA GUI Designer
-// >>> IMPORTANT!! <<<
-// DO NOT EDIT OR ADD ANY CODE HERE!
-        $$$setupUI$$$();
-    }
-
-    /**
-     * Method generated by IntelliJ IDEA GUI Designer
-     * >>> IMPORTANT!! <<<
-     * DO NOT edit this method OR call it in your code!
-     *
-     */
-    private void $$$setupUI$$$()
-    {
-        contentPane = new JPanel();
-        contentPane.setLayout( new BorderLayout( 0, 0 ) );
-        splitPane = new JSplitPane();
-        contentPane.add( splitPane, BorderLayout.CENTER );
-        final JScrollPane scrollPane1 = new JScrollPane();
-        splitPane.setLeftComponent( scrollPane1 );
-        fieldList = new JList();
-        scrollPane1.setViewportView( fieldList );
-        detailPane = new JPanel();
-        detailPane.setLayout( new GridBagLayout() );
-        splitPane.setRightComponent( detailPane );
-        detailPane.setBorder( BorderFactory.createTitledBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ), null ) );
-        final JLabel label1 = new JLabel();
-        this.$$$loadLabelText$$$( label1, ResourceBundle.getBundle( "org/qi4j/envisage/detail/DependencyPane" ).getString( "CTL_ClassName.Text" ) );
-        GridBagConstraints gbc;
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 0;
-        gbc.anchor = GridBagConstraints.EAST;
-        detailPane.add( label1, gbc );
-        final JPanel spacer1 = new JPanel();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 1;
-        gbc.gridy = 0;
-        gbc.fill = GridBagConstraints.HORIZONTAL;
-        detailPane.add( spacer1, gbc );
-        final JPanel spacer2 = new JPanel();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 1;
-        gbc.fill = GridBagConstraints.VERTICAL;
-        detailPane.add( spacer2, gbc );
-        final JLabel label2 = new JLabel();
-        this.$$$loadLabelText$$$( label2, ResourceBundle.getBundle( "org/qi4j/envisage/detail/DependencyPane" ).getString( "CTL_Optional.Text" ) );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 2;
-        gbc.anchor = GridBagConstraints.EAST;
-        detailPane.add( label2, gbc );
-        final JLabel label3 = new JLabel();
-        this.$$$loadLabelText$$$( label3, ResourceBundle.getBundle( "org/qi4j/envisage/detail/DependencyPane" ).getString( "CTL_Annotation.Text" ) );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 4;
-        gbc.anchor = GridBagConstraints.EAST;
-        detailPane.add( label3, gbc );
-        final JPanel spacer3 = new JPanel();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 3;
-        gbc.fill = GridBagConstraints.VERTICAL;
-        detailPane.add( spacer3, gbc );
-        final JPanel spacer4 = new JPanel();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 5;
-        gbc.fill = GridBagConstraints.VERTICAL;
-        detailPane.add( spacer4, gbc );
-        final JPanel spacer5 = new JPanel();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 9;
-        gbc.fill = GridBagConstraints.VERTICAL;
-        detailPane.add( spacer5, gbc );
-        final JLabel label4 = new JLabel();
-        this.$$$loadLabelText$$$( label4, ResourceBundle.getBundle( "org/qi4j/envisage/detail/DependencyPane" ).getString( "CTL_InjectionType.Text" ) );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 10;
-        gbc.anchor = GridBagConstraints.EAST;
-        detailPane.add( label4, gbc );
-        classNameLabel = new JLabel();
-        classNameLabel.setText( "none" );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 2;
-        gbc.gridy = 0;
-        gbc.weightx = 1.0;
-        gbc.anchor = GridBagConstraints.WEST;
-        detailPane.add( classNameLabel, gbc );
-        annotationLabel = new JLabel();
-        annotationLabel.setText( "none" );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 2;
-        gbc.gridy = 4;
-        gbc.anchor = GridBagConstraints.WEST;
-        detailPane.add( annotationLabel, gbc );
-        injectionTypeLabel = new JLabel();
-        injectionTypeLabel.setText( "none" );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 2;
-        gbc.gridy = 10;
-        gbc.anchor = GridBagConstraints.WEST;
-        detailPane.add( injectionTypeLabel, gbc );
-        optionalLabel = new JLabel();
-        optionalLabel.setText( "none" );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 2;
-        gbc.gridy = 2;
-        gbc.anchor = GridBagConstraints.WEST;
-        detailPane.add( optionalLabel, gbc );
-        final JPanel spacer6 = new JPanel();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 7;
-        gbc.fill = GridBagConstraints.VERTICAL;
-        detailPane.add( spacer6, gbc );
-        final JLabel label5 = new JLabel();
-        this.$$$loadLabelText$$$( label5, ResourceBundle.getBundle( "org/qi4j/envisage/detail/DependencyPane" ).getString( "CTL_Injection.Text" ) );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 8;
-        gbc.anchor = GridBagConstraints.WEST;
-        detailPane.add( label5, gbc );
-        final JScrollPane scrollPane2 = new JScrollPane();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 2;
-        gbc.gridy = 12;
-        gbc.weighty = 1.0;
-        gbc.fill = GridBagConstraints.BOTH;
-        detailPane.add( scrollPane2, gbc );
-        injectedServiceList = new JList();
-        scrollPane2.setViewportView( injectedServiceList );
-        final JPanel spacer7 = new JPanel();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 11;
-        gbc.fill = GridBagConstraints.VERTICAL;
-        detailPane.add( spacer7, gbc );
-        final JLabel label6 = new JLabel();
-        this.$$$loadLabelText$$$( label6, ResourceBundle.getBundle( "org/qi4j/envisage/detail/DependencyPane" ).getString( "CTL_InjectedServices.Text" ) );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 12;
-        gbc.anchor = GridBagConstraints.NORTHEAST;
-        detailPane.add( label6, gbc );
-        final JSeparator separator1 = new JSeparator();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 6;
-        gbc.gridwidth = 3;
-        gbc.fill = GridBagConstraints.BOTH;
-        detailPane.add( separator1, gbc );
-    }
-
-    private void $$$loadLabelText$$$( JLabel component, String text )
-    {
-        StringBuffer result = new StringBuffer();
-        boolean haveMnemonic = false;
-        char mnemonic = '\0';
-        int mnemonicIndex = -1;
-        for( int i = 0; i < text.length(); i++ )
-        {
-            if( text.charAt( i ) == '&' )
-            {
-                i++;
-                if( i == text.length() )
-                {
-                    break;
-                }
-                if( !haveMnemonic && text.charAt( i ) != '&' )
-                {
-                    haveMnemonic = true;
-                    mnemonic = text.charAt( i );
-                    mnemonicIndex = result.length();
-                }
-            }
-            result.append( text.charAt( i ) );
-        }
-        component.setText( result.toString() );
-        if( haveMnemonic )
-        {
-            component.setDisplayedMnemonic( mnemonic );
-            component.setDisplayedMnemonicIndex( mnemonicIndex );
-        }
-    }
-
-    public JComponent $$$getRootComponent$$$()
-    {
-        return contentPane;
-    }
-
-    private static class InjectedServiceListCellRenderer
-        extends DefaultListCellRenderer
-    {
-        @Override
-        public Component getListCellRendererComponent( JList list,
-                                                       Object value,
-                                                       int index,
-                                                       boolean isSelected,
-                                                       boolean cellHasFocus
-        )
-        {
-            if( value != null )
-            {
-                String id = (String) value;
-                value = "<html><a href=\"" + id + "\">" + id + "</a></html>";
-            }
-
-            super.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
-
-            return this;
-        }
-    }
-
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/DetailModelPane.java b/tools/envisage/src/main/java/org/qi4j/envisage/detail/DetailModelPane.java
deleted file mode 100644
index c92886b..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/DetailModelPane.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.detail;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.util.ResourceBundle;
-import javax.swing.BorderFactory;
-import javax.swing.JPanel;
-import javax.swing.JTabbedPane;
-import javax.swing.SwingUtilities;
-import org.qi4j.envisage.event.LinkEvent;
-import org.qi4j.envisage.event.LinkListener;
-import org.qi4j.tools.model.descriptor.EntityDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ImportedServiceDetailDescriptor;
-import org.qi4j.tools.model.descriptor.LayerDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ModuleDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ObjectDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ServiceDetailDescriptor;
-import org.qi4j.tools.model.descriptor.TransientDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ValueDetailDescriptor;
-
-public final class DetailModelPane
-    extends JPanel
-{
-
-    protected ResourceBundle bundle = ResourceBundle.getBundle( this.getClass().getName() );
-
-    protected JTabbedPane tabPane;
-    protected GeneralPane generalPane;
-    protected MethodPane methodPane;
-    protected StatePane statePane;
-    protected DependencyPane dependencyPane;
-    protected ServiceConfigurationPane serviceConfigurationPane;
-    protected ServiceUsagePane serviceUsagePane;
-    protected ImportedByPane importedByPane;
-    protected APIPane apiPane;
-    protected SPIPane spiPane;
-
-    protected boolean linkActivatedInProgress;
-
-    public DetailModelPane()
-    {
-        tabPane = new JTabbedPane();
-
-        this.setLayout( new BorderLayout() );
-        this.add( tabPane, BorderLayout.CENTER );
-
-        createDetailPane();
-    }
-
-    private void createDetailPane()
-    {
-        generalPane = new GeneralPane( this );
-        generalPane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
-
-        statePane = new StatePane( this );
-        statePane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
-
-        methodPane = new MethodPane( this );
-        methodPane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
-
-        dependencyPane = new DependencyPane( this );
-        dependencyPane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
-
-        serviceConfigurationPane = new ServiceConfigurationPane( this );
-        serviceConfigurationPane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
-
-        serviceUsagePane = new ServiceUsagePane( this );
-        serviceUsagePane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
-
-        importedByPane = new ImportedByPane( this );
-        importedByPane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
-
-        apiPane = new APIPane( this );
-        apiPane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
-
-        spiPane = new SPIPane( this );
-        spiPane.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) );
-    }
-
-    public void setDescriptor( final Object objectDescriptor )
-    {
-        SwingUtilities.invokeLater( new Runnable()
-        {
-            @Override
-            public void run()
-            {
-                setDescriptorImpl( objectDescriptor );
-            }
-        } );
-    }
-
-    private void setDescriptorImpl( Object objectDescriptor )
-    {
-        Component curSelectedComp = tabPane.getSelectedComponent();
-        tabPane.removeAll();
-
-        generalPane.setDescriptor( objectDescriptor );
-        dependencyPane.setDescriptor( objectDescriptor );
-        methodPane.setDescriptor( objectDescriptor );
-        statePane.setDescriptor( objectDescriptor );
-        serviceConfigurationPane.setDescriptor( objectDescriptor );
-        serviceUsagePane.setDescriptor( objectDescriptor );
-        importedByPane.setDescriptor( objectDescriptor );
-        apiPane.setDescriptor( objectDescriptor );
-        spiPane.setDescriptor( objectDescriptor );
-
-        if( objectDescriptor instanceof LayerDetailDescriptor
-            || objectDescriptor instanceof ModuleDetailDescriptor )
-        {
-            tabPane.add( bundle.getString( "CTL_APITab.Text" ), apiPane );
-            tabPane.add( bundle.getString( "CTL_SPITab.Text" ), spiPane );
-        }
-        else if( objectDescriptor instanceof ServiceDetailDescriptor )
-        {
-            tabPane.add( bundle.getString( "CTL_GeneralTab.Text" ), generalPane );
-            tabPane.add( bundle.getString( "CTL_DependencyTab.Text" ), dependencyPane );
-            tabPane.add( bundle.getString( "CTL_MethodTab.Text" ), methodPane );
-            tabPane.add( bundle.getString( "CTL_StateTab.Text" ), statePane );
-            tabPane.add( bundle.getString( "CTL_ServiceConfiguration.Text" ), serviceConfigurationPane );
-            tabPane.add( bundle.getString( "CTL_ServiceUsage.Text" ), serviceUsagePane );
-        }
-        else if( objectDescriptor instanceof ImportedServiceDetailDescriptor )
-        {
-            tabPane.add( bundle.getString( "CTL_GeneralTab.Text" ), generalPane );
-            tabPane.add( bundle.getString( "CTL_MethodTab.Text" ), methodPane );
-            tabPane.add( bundle.getString( "CTL_ServiceUsage.Text" ), serviceUsagePane );
-            tabPane.add( bundle.getString( "CTL_ImportedBy.Text" ), importedByPane );
-        }
-        else if( objectDescriptor instanceof EntityDetailDescriptor )
-        {
-            tabPane.add( bundle.getString( "CTL_GeneralTab.Text" ), generalPane );
-            tabPane.add( bundle.getString( "CTL_DependencyTab.Text" ), dependencyPane );
-            tabPane.add( bundle.getString( "CTL_MethodTab.Text" ), methodPane );
-            tabPane.add( bundle.getString( "CTL_StateTab.Text" ), statePane );
-        }
-        else if( objectDescriptor instanceof ValueDetailDescriptor )
-        {
-            tabPane.add( bundle.getString( "CTL_GeneralTab.Text" ), generalPane );
-            tabPane.add( bundle.getString( "CTL_DependencyTab.Text" ), dependencyPane );
-            tabPane.add( bundle.getString( "CTL_MethodTab.Text" ), methodPane );
-            tabPane.add( bundle.getString( "CTL_StateTab.Text" ), statePane );
-        }
-        else if( objectDescriptor instanceof ObjectDetailDescriptor )
-        {
-            tabPane.add( bundle.getString( "CTL_GeneralTab.Text" ), generalPane );
-            tabPane.add( bundle.getString( "CTL_DependencyTab.Text" ), dependencyPane );
-            tabPane.add( bundle.getString( "CTL_MethodTab.Text" ), methodPane );
-        }
-        else if( objectDescriptor instanceof TransientDetailDescriptor )
-        {
-            tabPane.add( bundle.getString( "CTL_GeneralTab.Text" ), generalPane );
-            tabPane.add( bundle.getString( "CTL_DependencyTab.Text" ), dependencyPane );
-            tabPane.add( bundle.getString( "CTL_MethodTab.Text" ), methodPane );
-            tabPane.add( bundle.getString( "CTL_StateTab.Text" ), statePane );
-        }
-
-        if( linkActivatedInProgress )
-        {
-            // for linking always display the first tab (General)
-            linkActivatedInProgress = false;
-            tabPane.setSelectedIndex( 0 );
-        }
-        else
-        {
-            // if not linking, then maintain the current selected tab
-            if( curSelectedComp != null )
-            {
-                int index = tabPane.indexOfComponent( curSelectedComp );
-                if( index != -1 )
-                {
-                    tabPane.setSelectedIndex( index );
-                }
-            }
-        }
-    }
-
-    /**
-     * Add a listener that's notified each time a LinkEvent occurs.
-     *
-     * @param listener the LinkListener to add
-     */
-    public void addLinkListener( LinkListener listener )
-    {
-        listenerList.add( LinkListener.class, listener );
-    }
-
-    /**
-     * Remove a listener that's notified each time a LinkEvent occurs.
-     *
-     * @param listener the LinkListener to remove
-     */
-    public void removeLinkListener( LinkListener listener )
-    {
-        listenerList.remove( LinkListener.class, listener );
-    }
-
-    /* package */ void fireLinkActivated( LinkEvent evt )
-    {
-        linkActivatedInProgress = true;
-        // Guaranteed to return a non-null array
-        Object[] listeners = listenerList.getListenerList();
-        // Process the listeners last to first, notifying
-        // those that are interested in this event
-        for( int i = listeners.length - 2; i >= 0; i -= 2 )
-        {
-            if( listeners[i] == LinkListener.class )
-            {
-                ( (LinkListener) listeners[i + 1] ).activated( evt );
-            }
-        }
-    }
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/DetailPane.java b/tools/envisage/src/main/java/org/qi4j/envisage/detail/DetailPane.java
deleted file mode 100644
index d176c9c..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/DetailPane.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.detail;
-
-import javax.swing.JPanel;
-
-/**
- * Abstract Base class for DetailPane
- */
-/* package */ abstract class DetailPane
-    extends JPanel
-{
-    protected final DetailModelPane detailModelPane;
-
-    protected DetailPane( DetailModelPane detailModelPane )
-    {
-        if( detailModelPane == null )
-        {
-            throw new IllegalArgumentException( "detailModelPane could not null" );
-        }
-        this.detailModelPane = detailModelPane;
-    }
-
-    protected abstract void setDescriptor( Object objectDescriptor );
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/GeneralPane.form b/tools/envisage/src/main/java/org/qi4j/envisage/detail/GeneralPane.form
deleted file mode 100644
index 6a4d975..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/GeneralPane.form
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.qi4j.envisage.detail.GeneralPane">
-  <grid id="27dc6" binding="contentPane" layout-manager="BorderLayout" hgap="0" vgap="0">
-    <constraints>
-      <xy x="20" y="20" width="299" height="260"/>
-    </constraints>
-    <properties/>
-    <border type="none"/>
-    <children>
-      <scrollpane id="af7b6">
-        <constraints border-constraint="Center"/>
-        <properties/>
-        <border type="none"/>
-        <children>
-          <component id="53425" class="javax.swing.JTable" binding="table">
-            <constraints/>
-            <properties/>
-          </component>
-        </children>
-      </scrollpane>
-    </children>
-  </grid>
-</form>
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/GeneralPane.java b/tools/envisage/src/main/java/org/qi4j/envisage/detail/GeneralPane.java
deleted file mode 100644
index 233bfe8..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/GeneralPane.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.detail;
-
-import java.awt.BorderLayout;
-import java.util.ArrayList;
-import java.util.ResourceBundle;
-import javax.swing.JComponent;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTable;
-import javax.swing.table.AbstractTableModel;
-import javax.swing.table.TableColumnModel;
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.object.ObjectDescriptor;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.envisage.util.TableRow;
-import org.qi4j.tools.model.descriptor.EntityDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ImportedServiceCompositeDescriptor;
-import org.qi4j.tools.model.descriptor.ImportedServiceDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ObjectDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ServiceDetailDescriptor;
-import org.qi4j.tools.model.descriptor.TransientDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ValueDetailDescriptor;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Implementation of General DetailPane
- */
-/* package */ final class GeneralPane
-    extends DetailPane
-{
-    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( GeneralPane.class.getName() );
-
-    private JPanel contentPane;
-    private JTable table;
-    private final GeneralTableModel tableModel;
-
-    /* package */ GeneralPane( DetailModelPane detailModelPane )
-    {
-        super( detailModelPane );
-        this.setLayout( new BorderLayout() );
-        this.add( contentPane, BorderLayout.CENTER );
-
-        tableModel = new GeneralTableModel();
-        table.setModel( tableModel );
-
-        TableColumnModel columnModel = table.getColumnModel();
-        columnModel.getColumn( 0 ).setPreferredWidth( 90 );
-        columnModel.getColumn( 1 ).setPreferredWidth( 550 );
-    }
-
-    private void clear()
-    {
-        tableModel.clear();
-    }
-
-    @Override
-    protected void setDescriptor( Object objectDesciptor )
-    {
-        clear();
-        tableModel.reload( objectDesciptor );
-    }
-
-    
-    {
-// GUI initializer generated by IntelliJ IDEA GUI Designer
-// >>> IMPORTANT!! <<<
-// DO NOT EDIT OR ADD ANY CODE HERE!
-        $$$setupUI$$$();
-    }
-
-    /**
-     * Method generated by IntelliJ IDEA GUI Designer
-     * >>> IMPORTANT!! <<<
-     * DO NOT edit this method OR call it in your code!
-     *
-     */
-    private void $$$setupUI$$$()
-    {
-        contentPane = new JPanel();
-        contentPane.setLayout( new BorderLayout( 0, 0 ) );
-        final JScrollPane scrollPane1 = new JScrollPane();
-        contentPane.add( scrollPane1, BorderLayout.CENTER );
-        table = new JTable();
-        scrollPane1.setViewportView( table );
-    }
-
-    public JComponent $$$getRootComponent$$$()
-    {
-        return contentPane;
-    }
-
-    private static class GeneralTableModel
-        extends AbstractTableModel
-    {
-        /**
-         * the column names for this model
-         */
-        private static final String[] COLUMN_NAMES =
-        {
-            BUNDLE.getString( "Name.Column" ),
-            BUNDLE.getString( "Value.Column" )
-        };
-        private final ArrayList<TableRow> rows;
-
-        private final String nameRow = "name";
-        private final String classRow = "class";
-        private final String visibilityRow = "visibility";
-        private final String moduleRow = "module";
-        private final String layerRow = "layer";
-
-        private GeneralTableModel()
-        {
-            rows = new ArrayList<>();
-        }
-
-        private void reload( Object objectDesciptor )
-        {
-            if( objectDesciptor instanceof ServiceDetailDescriptor )
-            {
-                ServiceDescriptor descriptor = ( (ServiceDetailDescriptor) objectDesciptor ).descriptor();
-                Class<?> type = first( descriptor.types() );
-                rows.add( new TableRow( 2, nameRow, type.getSimpleName() ) );
-                rows.add( new TableRow( 2, classRow, type.getName() ) );
-                rows.add( new TableRow( 2, visibilityRow, descriptor.visibility().toString() ) );
-                rows.add( new TableRow( 2, moduleRow, ( (ServiceDetailDescriptor) objectDesciptor ).module() ) );
-                rows.add( new TableRow( 2, layerRow, ( (ServiceDetailDescriptor) objectDesciptor ).module().layer() ) );
-                rows.add( new TableRow( 2, "startup", ( (ServiceDetailDescriptor) objectDesciptor ).descriptor().isInstantiateOnStartup() ) );
-            }
-            else if( objectDesciptor instanceof ImportedServiceDetailDescriptor )
-            {
-                ImportedServiceCompositeDescriptor descriptor = ( (ImportedServiceDetailDescriptor) objectDesciptor ).descriptor();
-                rows.add( new TableRow( 2, nameRow, descriptor.primaryType().getSimpleName() ) );
-                rows.add( new TableRow( 2, classRow, descriptor.primaryType().getName() ) );
-                rows.add( new TableRow( 2, visibilityRow, descriptor.visibility().toString() ) );
-                rows.add( new TableRow( 2, moduleRow, ( (ImportedServiceDetailDescriptor) objectDesciptor ).module() ) );
-                rows.add( new TableRow( 2, layerRow, ( (ImportedServiceDetailDescriptor) objectDesciptor ).module().layer() ) );
-            }
-            else if( objectDesciptor instanceof EntityDetailDescriptor )
-            {
-                EntityDescriptor descriptor = ( (EntityDetailDescriptor) objectDesciptor ).descriptor();
-                Class<?> type = first( descriptor.types() );
-                rows.add( new TableRow( 2, nameRow, type.getSimpleName() ) );
-                rows.add( new TableRow( 2, classRow, type.getName() ) );
-                rows.add( new TableRow( 2, visibilityRow, descriptor.visibility().toString() ) );
-                rows.add( new TableRow( 2, moduleRow, ( (EntityDetailDescriptor) objectDesciptor ).module() ) );
-                rows.add( new TableRow( 2, layerRow, ( (EntityDetailDescriptor) objectDesciptor ).module().layer() ) );
-            }
-            else if( objectDesciptor instanceof ValueDetailDescriptor )
-            {
-                ValueDescriptor descriptor = ( (ValueDetailDescriptor) objectDesciptor ).descriptor();
-                Class<?> type = first( descriptor.types() );
-                rows.add( new TableRow( 2, new Object[]
-                {
-                    nameRow, type.getSimpleName()
-                } ) );
-                rows.add( new TableRow( 2, new Object[]
-                {
-                    classRow, type.getName()
-                } ) );
-                rows.add( new TableRow( 2, new Object[]
-                {
-                    visibilityRow, descriptor.visibility().toString()
-                } ) );
-                rows.add( new TableRow( 2, new Object[]
-                {
-                    moduleRow, ( (ValueDetailDescriptor) objectDesciptor ).module()
-                } ) );
-                rows.add( new TableRow( 2, new Object[]
-                {
-                    layerRow, ( (ValueDetailDescriptor) objectDesciptor ).module().layer()
-                } ) );
-            }
-            else if( objectDesciptor instanceof ObjectDetailDescriptor )
-            {
-                ObjectDescriptor descriptor = ( (ObjectDetailDescriptor) objectDesciptor ).descriptor();
-                Class<?> type = first( descriptor.types() );
-                rows.add( new TableRow( 2, nameRow, type.getSimpleName() ) );
-                rows.add( new TableRow( 2, classRow, type.getName() ) );
-                rows.add( new TableRow( 2, visibilityRow, descriptor.visibility().toString() ) );
-                rows.add( new TableRow( 2, moduleRow, ( (ObjectDetailDescriptor) objectDesciptor ).module() ) );
-                rows.add( new TableRow( 2, layerRow, ( (ObjectDetailDescriptor) objectDesciptor ).module().layer() ) );
-            }
-            else if( objectDesciptor instanceof TransientDetailDescriptor )
-            {
-                CompositeDescriptor descriptor = ( (TransientDetailDescriptor) objectDesciptor ).descriptor();
-                Class<?> type = first( descriptor.types() );
-                rows.add( new TableRow( 2, nameRow, type.getSimpleName() ) );
-                rows.add( new TableRow( 2, classRow, type.getName() ) );
-                rows.add( new TableRow( 2, visibilityRow, descriptor.visibility().toString() ) );
-                rows.add( new TableRow( 2, moduleRow, ( (TransientDetailDescriptor) objectDesciptor ).module() ) );
-                rows.add( new TableRow( 2, layerRow, ( (TransientDetailDescriptor) objectDesciptor ).module().layer() ) );
-            }
-
-            fireTableDataChanged();
-        }
-
-        @Override
-        public Object getValueAt( int rowIndex, int columnIndex )
-        {
-            TableRow row = this.rows.get( rowIndex );
-            return row.get( columnIndex );
-        }
-
-        private void clear()
-        {
-            rows.clear();
-            fireTableDataChanged();
-        }
-
-        @Override
-        public int getColumnCount()
-        {
-            return COLUMN_NAMES.length;
-        }
-
-        @Override
-        public String getColumnName( int col )
-        {
-            return COLUMN_NAMES[ col];
-        }
-
-        @Override
-        public int getRowCount()
-        {
-            return rows.size();
-        }
-    }
-
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/ImportedByPane.form b/tools/envisage/src/main/java/org/qi4j/envisage/detail/ImportedByPane.form
deleted file mode 100644
index 09ab310..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/ImportedByPane.form
+++ /dev/null
@@ -1,88 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.qi4j.envisage.detail.ImportedByPane">
-  <grid id="27dc6" binding="contentPane" layout-manager="GridBagLayout">
-    <constraints>
-      <xy x="20" y="20" width="500" height="400"/>
-    </constraints>
-    <properties/>
-    <border type="none"/>
-    <children>
-      <component id="52fba" class="javax.swing.JLabel">
-        <constraints>
-          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="0.0"/>
-        </constraints>
-        <properties>
-          <text resource-bundle="org/qi4j/envisage/detail/ImportedByPane" key="CTL_Name.Text"/>
-        </properties>
-      </component>
-      <hspacer id="3491d">
-        <constraints>
-          <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="0.0"/>
-        </constraints>
-      </hspacer>
-      <vspacer id="834de">
-        <constraints>
-          <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="0.0"/>
-        </constraints>
-      </vspacer>
-      <component id="bad85" class="javax.swing.JLabel" binding="nameLabel">
-        <constraints>
-          <grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="0.0"/>
-        </constraints>
-        <properties>
-          <text value="Label"/>
-        </properties>
-      </component>
-      <component id="48183" class="javax.swing.JLabel">
-        <constraints>
-          <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="0.0"/>
-        </constraints>
-        <properties>
-          <text resource-bundle="org/qi4j/envisage/detail/ImportedByPane" key="CTL_Class.Text"/>
-        </properties>
-      </component>
-      <component id="17892" class="javax.swing.JLabel" binding="classLabel">
-        <constraints>
-          <grid row="3" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="1.0" weighty="0.0"/>
-        </constraints>
-        <properties>
-          <text value="Label"/>
-        </properties>
-      </component>
-      <vspacer id="9dbec">
-        <constraints>
-          <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="1.0"/>
-        </constraints>
-      </vspacer>
-      <vspacer id="2e566">
-        <constraints>
-          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="0.0"/>
-        </constraints>
-      </vspacer>
-    </children>
-  </grid>
-</form>
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/ImportedByPane.java b/tools/envisage/src/main/java/org/qi4j/envisage/detail/ImportedByPane.java
deleted file mode 100644
index d16af5a..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/ImportedByPane.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.detail;
-
-import java.awt.BorderLayout;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.util.ResourceBundle;
-import javax.swing.JComponent;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.tools.model.descriptor.ImportedServiceDetailDescriptor;
-
-/**
- * Implementation of ImportedService imported by
- */
-/* package */ final class ImportedByPane
-    extends DetailPane
-{
-    private JPanel contentPane;
-    private JLabel nameLabel;
-    private JLabel classLabel;
-
-    /* package */ ImportedByPane( DetailModelPane detailModelPane )
-    {
-        super( detailModelPane );
-        this.setLayout( new BorderLayout() );
-        this.add( contentPane, BorderLayout.CENTER );
-    }
-
-    @Override
-    protected void setDescriptor( Object objectDesciptor )
-    {
-        clear();
-
-        if( !( objectDesciptor instanceof ImportedServiceDetailDescriptor ) )
-        {
-            return;
-        }
-
-        ImportedServiceDetailDescriptor detailDescriptor = (ImportedServiceDetailDescriptor) objectDesciptor;
-        ImportedServiceDescriptor descriptor = detailDescriptor.descriptor().importedService();
-
-        Class<? extends ServiceImporter> importer = descriptor.serviceImporter();
-        nameLabel.setText( importer.getSimpleName() );
-        classLabel.setText( importer.toString() );
-    }
-
-    private void clear()
-    {
-        nameLabel.setText( null );
-        classLabel.setText( null );
-    }
-
-    
-    {
-// GUI initializer generated by IntelliJ IDEA GUI Designer
-// >>> IMPORTANT!! <<<
-// DO NOT EDIT OR ADD ANY CODE HERE!
-        $$$setupUI$$$();
-    }
-
-    /**
-     * Method generated by IntelliJ IDEA GUI Designer
-     * >>> IMPORTANT!! <<<
-     * DO NOT edit this method OR call it in your code!
-     *
-     */
-    private void $$$setupUI$$$()
-    {
-        contentPane = new JPanel();
-        contentPane.setLayout( new GridBagLayout() );
-        final JLabel label1 = new JLabel();
-        this.$$$loadLabelText$$$( label1, ResourceBundle.getBundle( "org/qi4j/envisage/detail/ImportedByPane" ).getString( "CTL_Name.Text" ) );
-        GridBagConstraints gbc;
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 1;
-        gbc.anchor = GridBagConstraints.WEST;
-        contentPane.add( label1, gbc );
-        final JPanel spacer1 = new JPanel();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 1;
-        gbc.gridy = 1;
-        gbc.fill = GridBagConstraints.HORIZONTAL;
-        contentPane.add( spacer1, gbc );
-        final JPanel spacer2 = new JPanel();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 2;
-        gbc.fill = GridBagConstraints.VERTICAL;
-        contentPane.add( spacer2, gbc );
-        nameLabel = new JLabel();
-        nameLabel.setText( "Label" );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 2;
-        gbc.gridy = 1;
-        gbc.anchor = GridBagConstraints.WEST;
-        contentPane.add( nameLabel, gbc );
-        final JLabel label2 = new JLabel();
-        this.$$$loadLabelText$$$( label2, ResourceBundle.getBundle( "org/qi4j/envisage/detail/ImportedByPane" ).getString( "CTL_Class.Text" ) );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 3;
-        gbc.anchor = GridBagConstraints.WEST;
-        contentPane.add( label2, gbc );
-        classLabel = new JLabel();
-        classLabel.setText( "Label" );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 2;
-        gbc.gridy = 3;
-        gbc.weightx = 1.0;
-        gbc.anchor = GridBagConstraints.WEST;
-        contentPane.add( classLabel, gbc );
-        final JPanel spacer3 = new JPanel();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 4;
-        gbc.weighty = 1.0;
-        gbc.fill = GridBagConstraints.VERTICAL;
-        contentPane.add( spacer3, gbc );
-        final JPanel spacer4 = new JPanel();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 0;
-        gbc.fill = GridBagConstraints.VERTICAL;
-        contentPane.add( spacer4, gbc );
-    }
-
-    private void $$$loadLabelText$$$( JLabel component, String text )
-    {
-        StringBuffer result = new StringBuffer();
-        boolean haveMnemonic = false;
-        char mnemonic = '\0';
-        int mnemonicIndex = -1;
-        for( int i = 0; i < text.length(); i++ )
-        {
-            if( text.charAt( i ) == '&' )
-            {
-                i++;
-                if( i == text.length() )
-                {
-                    break;
-                }
-                if( !haveMnemonic && text.charAt( i ) != '&' )
-                {
-                    haveMnemonic = true;
-                    mnemonic = text.charAt( i );
-                    mnemonicIndex = result.length();
-                }
-            }
-            result.append( text.charAt( i ) );
-        }
-        component.setText( result.toString() );
-        if( haveMnemonic )
-        {
-            component.setDisplayedMnemonic( mnemonic );
-            component.setDisplayedMnemonicIndex( mnemonicIndex );
-        }
-    }
-
-    public JComponent $$$getRootComponent$$$()
-    {
-        return contentPane;
-    }
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/MethodPane.form b/tools/envisage/src/main/java/org/qi4j/envisage/detail/MethodPane.form
deleted file mode 100644
index 9cc7068..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/MethodPane.form
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.qi4j.envisage.detail.MethodPane">
-  <grid id="27dc6" binding="contentPane" layout-manager="BorderLayout" hgap="0" vgap="0">
-    <constraints>
-      <xy x="20" y="20" width="500" height="400"/>
-    </constraints>
-    <properties/>
-    <border type="none"/>
-    <children>
-      <splitpane id="24b86" binding="splitPane">
-        <constraints border-constraint="Center"/>
-        <properties/>
-        <border type="none"/>
-        <children>
-          <scrollpane id="b00c1">
-            <constraints>
-              <splitpane position="left"/>
-            </constraints>
-            <properties/>
-            <border type="none"/>
-            <children>
-              <component id="19b04" class="javax.swing.JList" binding="methodList">
-                <constraints/>
-                <properties/>
-              </component>
-            </children>
-          </scrollpane>
-          <scrollpane id="fb413">
-            <constraints>
-              <splitpane position="right"/>
-            </constraints>
-            <properties/>
-            <border type="none"/>
-            <children>
-              <component id="f694" class="javax.swing.JTable" binding="methodDetailTable">
-                <constraints/>
-                <properties/>
-              </component>
-            </children>
-          </scrollpane>
-        </children>
-      </splitpane>
-    </children>
-  </grid>
-</form>
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/MethodPane.java b/tools/envisage/src/main/java/org/qi4j/envisage/detail/MethodPane.java
deleted file mode 100644
index c89c1c5..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/MethodPane.java
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.detail;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ResourceBundle;
-import javax.swing.DefaultListCellRenderer;
-import javax.swing.DefaultListModel;
-import javax.swing.Icon;
-import javax.swing.ImageIcon;
-import javax.swing.JComponent;
-import javax.swing.JList;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JSplitPane;
-import javax.swing.JTable;
-import javax.swing.ListSelectionModel;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.table.AbstractTableModel;
-import javax.swing.table.TableColumnModel;
-import org.qi4j.api.util.Classes;
-import org.qi4j.envisage.util.TableRow;
-import org.qi4j.tools.model.descriptor.CompositeDetailDescriptor;
-import org.qi4j.tools.model.descriptor.CompositeMethodDetailDescriptor;
-import org.qi4j.tools.model.descriptor.MethodConcernDetailDescriptor;
-import org.qi4j.tools.model.descriptor.MethodSideEffectDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ObjectDetailDescriptor;
-import org.qi4j.tools.model.util.DescriptorUtilities;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Implementation of Composite Method Panel
- */
-/* package */ final class MethodPane
-    extends DetailPane
-{
-    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( MethodPane.class.getName() );
-
-    private JPanel contentPane;
-    private JList methodList;
-    private JTable methodDetailTable;
-    private JSplitPane splitPane;
-
-    private final DefaultListModel methodListModel;
-    private final MethodDetailTableModel methodDetailTableModel;
-
-    /* package */ MethodPane( DetailModelPane detailModelPane )
-    {
-        super( detailModelPane );
-        this.setLayout( new BorderLayout() );
-        this.add( contentPane, BorderLayout.CENTER );
-
-        methodListModel = new DefaultListModel();
-        methodList.setModel( methodListModel );
-        methodList.setCellRenderer( new MethodListCellRenderer() );
-        methodList.setPrototypeCellValue( "12345678901234567890" );
-        methodList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
-
-        methodDetailTableModel = new MethodDetailTableModel();
-        methodDetailTable.setModel( methodDetailTableModel );
-
-        TableColumnModel columnModel = methodDetailTable.getColumnModel();
-        columnModel.getColumn( 0 ).setPreferredWidth( 75 );
-        columnModel.getColumn( 1 ).setPreferredWidth( 400 );
-
-        //splitPane.setResizeWeight( .1 );
-        //splitPane.setDividerLocation( .3 );
-        methodList.addListSelectionListener( new ListSelectionListener()
-        {
-            @Override
-            public void valueChanged( ListSelectionEvent evt )
-            {
-                methodListValueChanged( evt );
-            }
-        } );
-    }
-
-    @Override
-    protected void setDescriptor( Object objectDesciptor )
-    {
-        clear();
-
-        if( objectDesciptor instanceof CompositeDetailDescriptor )
-        {
-            CompositeDetailDescriptor descriptor = ( (CompositeDetailDescriptor) objectDesciptor );
-            List<CompositeMethodDetailDescriptor> list = DescriptorUtilities.findMethod( descriptor );
-            for( CompositeMethodDetailDescriptor methodDescriptor : list )
-            {
-                methodListModel.addElement( methodDescriptor );
-            }
-
-            if( !methodListModel.isEmpty() )
-            {
-                methodList.setSelectedIndex( 0 );
-            }
-        }
-        else if( objectDesciptor instanceof ObjectDetailDescriptor )
-        {
-            // Object does not have methods
-        }
-    }
-
-    private void clear()
-    {
-        methodListModel.clear();
-        methodDetailTableModel.clear();
-    }
-
-    private void methodListValueChanged( ListSelectionEvent evt )
-    {
-        if( evt.getValueIsAdjusting() )
-        {
-            return;
-        }
-        Object obj = methodList.getSelectedValue();
-        if( obj == null )
-        {
-            methodDetailTableModel.clear();
-            return;
-        }
-        methodDetailTableModel.reload( (CompositeMethodDetailDescriptor) obj );
-    }
-
-    
-    {
-// GUI initializer generated by IntelliJ IDEA GUI Designer
-// >>> IMPORTANT!! <<<
-// DO NOT EDIT OR ADD ANY CODE HERE!
-        $$$setupUI$$$();
-    }
-
-    /**
-     * Method generated by IntelliJ IDEA GUI Designer
-     * >>> IMPORTANT!! <<<
-     * DO NOT edit this method OR call it in your code!
-     *
-     */
-    private void $$$setupUI$$$()
-    {
-        contentPane = new JPanel();
-        contentPane.setLayout( new BorderLayout( 0, 0 ) );
-        splitPane = new JSplitPane();
-        contentPane.add( splitPane, BorderLayout.CENTER );
-        final JScrollPane scrollPane1 = new JScrollPane();
-        splitPane.setLeftComponent( scrollPane1 );
-        methodList = new JList();
-        scrollPane1.setViewportView( methodList );
-        final JScrollPane scrollPane2 = new JScrollPane();
-        splitPane.setRightComponent( scrollPane2 );
-        methodDetailTable = new JTable();
-        scrollPane2.setViewportView( methodDetailTable );
-    }
-
-    public JComponent $$$getRootComponent$$$()
-    {
-        return contentPane;
-    }
-
-    private static class MethodDetailTableModel
-        extends AbstractTableModel
-    {
-        /**
-         * the column names for this model
-         */
-        private static final String[] COLUMN_NAMES =
-        {
-            "Name",
-            "Value"
-        };
-        private final ArrayList<TableRow> rows;
-
-        private MethodDetailTableModel()
-        {
-            rows = new ArrayList<>();
-        }
-
-        private void reload( CompositeMethodDetailDescriptor descriptor )
-        {
-            Method method = descriptor.descriptor().method();
-
-            clear();
-
-            // mixin type
-            rows.add( new TableRow( 2, new Object[]
-            {
-                "return", Classes.simpleGenericNameOf( method.getGenericReturnType() )
-            } ) );
-
-            // method
-            StringBuilder parameters = new StringBuilder();
-            for( int idx = 0; idx < method.getGenericParameterTypes().length; idx++ )
-            {
-                Type type = method.getGenericParameterTypes()[idx];
-                Annotation[] annotations = method.getParameterAnnotations()[idx];
-
-                if( parameters.length() > 0 )
-                {
-                    parameters.append( ", " );
-                }
-
-                for( Annotation annotation : annotations )
-                {
-                    String ann = annotation.toString();
-                    ann = "@" + ann.substring( ann.lastIndexOf( '.' ) + 1 );
-                    parameters.append( ann ).append( " " );
-                }
-
-                parameters.append( Classes.simpleGenericNameOf( type ) );
-            }
-
-            rows.add( new TableRow( 2, "parameters", parameters.toString() ) );
-
-            // concern
-            boolean first = true;
-            for( MethodConcernDetailDescriptor concern : descriptor.concerns().concerns() )
-            {
-                if( first )
-                {
-                    rows.add( new TableRow( 2, "concern", concern.descriptor().modifierClass().getSimpleName() ) );
-                    first = false;
-                }
-                else
-                {
-                    rows.add( new TableRow( 2, "", concern.descriptor().modifierClass().getSimpleName() ) );
-                }
-            }
-
-            // sideEffect
-            first = false;
-            for( MethodSideEffectDetailDescriptor sideEffect : descriptor.sideEffects().sideEffects() )
-            {
-                if( first )
-                {
-                    rows.add( new TableRow( 2, "sideEffect", sideEffect.descriptor().modifierClass().getSimpleName() ) );
-                    first = false;
-                }
-                else
-                {
-                    rows.add( new TableRow( 2, "", sideEffect.descriptor().modifierClass().getSimpleName() ) );
-                }
-            }
-
-            fireTableDataChanged();
-        }
-
-        @Override
-        public Object getValueAt( int rowIndex, int columnIndex )
-        {
-            TableRow row = this.rows.get( rowIndex );
-            return row.get( columnIndex );
-        }
-
-        private void clear()
-        {
-            rows.clear();
-            fireTableDataChanged();
-        }
-
-        @Override
-        public int getColumnCount()
-        {
-            return COLUMN_NAMES.length;
-        }
-
-        @Override
-        public String getColumnName( int col )
-        {
-            return COLUMN_NAMES[ col];
-        }
-
-        @Override
-        public int getRowCount()
-        {
-            return rows.size();
-        }
-    }
-
-    private static class MethodListCellRenderer
-        extends DefaultListCellRenderer
-    {
-        private final Icon publicIcon;
-        private final Icon privateIcon;
-
-        public MethodListCellRenderer()
-        {
-            try
-            {
-                publicIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Public" ) ) );
-                privateIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Private" ) ) );
-            }
-            catch( Exception ex )
-            {
-                throw new RuntimeException( ex );
-            }
-        }
-
-        @Override
-        public Component getListCellRendererComponent( JList list,
-                                                       Object value,
-                                                       int index,
-                                                       boolean isSelected,
-                                                       boolean cellHasFocus
-        )
-        {
-            super.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
-            if( !( value instanceof CompositeMethodDetailDescriptor ) )
-            {
-                return this;
-            }
-
-            Icon icon;
-            CompositeMethodDetailDescriptor descriptor = (CompositeMethodDetailDescriptor) value;
-
-            Class compositeClass = first( descriptor.composite().descriptor().types() );
-            Class mixinMethodClass = descriptor.descriptor().method().getDeclaringClass();
-            if( mixinMethodClass.isAssignableFrom( compositeClass ) )
-            {
-                icon = publicIcon;
-            }
-            else
-            {
-                icon = privateIcon;
-            }
-
-            if( icon != null )
-            {
-                setIcon( icon );
-            }
-
-            return this;
-        }
-    }
-
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/SPIPane.form b/tools/envisage/src/main/java/org/qi4j/envisage/detail/SPIPane.form
deleted file mode 100644
index c50407a..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/SPIPane.form
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.qi4j.envisage.detail.SPIPane">
-  <grid id="27dc6" binding="contentPane" layout-manager="BorderLayout" hgap="0" vgap="0">
-    <constraints>
-      <xy x="20" y="20" width="500" height="400"/>
-    </constraints>
-    <properties/>
-    <border type="none"/>
-    <children>
-      <scrollpane id="62a5">
-        <constraints border-constraint="Center"/>
-        <properties/>
-        <border type="none"/>
-        <children>
-          <component id="ca0ba" class="javax.swing.JTable" binding="spiTable">
-            <constraints/>
-            <properties/>
-          </component>
-        </children>
-      </scrollpane>
-    </children>
-  </grid>
-</form>
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/SPIPane.java b/tools/envisage/src/main/java/org/qi4j/envisage/detail/SPIPane.java
deleted file mode 100644
index b2b35a0..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/SPIPane.java
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.detail;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.Cursor;
-import java.awt.event.MouseEvent;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ResourceBundle;
-import javax.swing.JComponent;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTable;
-import javax.swing.ListSelectionModel;
-import javax.swing.event.MouseInputAdapter;
-import javax.swing.table.AbstractTableModel;
-import javax.swing.table.DefaultTableCellRenderer;
-import javax.swing.table.TableColumnModel;
-import org.qi4j.envisage.event.LinkEvent;
-import org.qi4j.envisage.util.TableRow;
-import org.qi4j.tools.model.descriptor.LayerDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ModuleDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ServiceDetailDescriptor;
-import org.qi4j.tools.model.util.DescriptorUtilities;
-
-/**
- * API would be defined as "All service interfaces which are visible for layer
- * or application" and SPI would be defined as "All service dependencies which
- * are not satisfied from within the module". And then similar for Layer. This
- * way you can select a Module/Layer and immediately see what it produces as
- * output and requires as input. This is also very very nice for documentation
- * purposes.
- */
-/* package */ final class SPIPane
-    extends DetailPane
-{
-    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( SPIPane.class.getName() );
-
-    private JPanel contentPane;
-    private JTable spiTable;
-    private SPITableModel spiTableModel;
-
-    private Object linkObject;
-    private Cursor defaultCursor;
-    private Cursor linkCursor;
-
-    /* package */ SPIPane( DetailModelPane detailModelPane )
-    {
-        super( detailModelPane );
-        this.setLayout( new BorderLayout() );
-        this.add( contentPane, BorderLayout.CENTER );
-
-        spiTableModel = new SPITableModel();
-        spiTable.setModel( spiTableModel );
-        spiTable.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
-
-        TableColumnModel columnModel = spiTable.getColumnModel();
-        columnModel.getColumn( 0 ).setCellRenderer( new DependencyCellRenderer() );
-
-        defaultCursor = getCursor();
-        linkCursor = LinkEvent.LINK_CURSOR;
-
-        MouseInputAdapter mouseInputListener = new MouseInputAdapter()
-        {
-            @Override
-            public void mouseMoved( MouseEvent evt )
-            {
-                // Column 1 is the Service Column
-                int col = spiTable.columnAtPoint( evt.getPoint() );
-                if( col == 0 )
-                {
-                    setCursor( linkCursor );
-                }
-                else
-                {
-                    if( !getCursor().equals( defaultCursor ) )
-                    {
-                        setCursor( defaultCursor );
-                    }
-                }
-            }
-
-            @Override
-            public void mouseClicked( MouseEvent evt )
-            {
-                int col = spiTable.columnAtPoint( evt.getPoint() );
-                if( col != 0 )
-                {
-                    return;
-                }
-
-                int row = spiTable.rowAtPoint( evt.getPoint() );
-                if( row < 0 )
-                {
-                    return;
-                }
-
-                linkObject = spiTable.getValueAt( row, col );
-                linkActivated();
-                linkObject = null;
-            }
-        };
-
-        spiTable.addMouseMotionListener( mouseInputListener );
-        spiTable.addMouseListener( mouseInputListener );
-    }
-
-    @Override
-    protected void setDescriptor( Object objectDesciptor )
-    {
-        clear();
-
-        List<ServiceDetailDescriptor> list = null;
-        if( objectDesciptor instanceof LayerDetailDescriptor )
-        {
-            list = DescriptorUtilities.findLayerSPI( (LayerDetailDescriptor) objectDesciptor );
-        }
-        else if( objectDesciptor instanceof ModuleDetailDescriptor )
-        {
-            list = DescriptorUtilities.findModule( (ModuleDetailDescriptor) objectDesciptor );
-        }
-
-        if( list != null )
-        {
-            spiTableModel.addRow( list );
-        }
-    }
-
-    private void clear()
-    {
-        linkObject = null;
-        spiTableModel.clear();
-    }
-
-    private void linkActivated()
-    {
-        if( linkObject == null )
-        {
-            return;
-        }
-        LinkEvent linkEvt = new LinkEvent( this, linkObject );
-        detailModelPane.fireLinkActivated( linkEvt );
-    }
-
-    
-    {
-// GUI initializer generated by IntelliJ IDEA GUI Designer
-// >>> IMPORTANT!! <<<
-// DO NOT EDIT OR ADD ANY CODE HERE!
-        $$$setupUI$$$();
-    }
-
-    /**
-     * Method generated by IntelliJ IDEA GUI Designer
-     * >>> IMPORTANT!! <<<
-     * DO NOT edit this method OR call it in your code!
-     *
-     */
-    private void $$$setupUI$$$()
-    {
-        contentPane = new JPanel();
-        contentPane.setLayout( new BorderLayout( 0, 0 ) );
-        final JScrollPane scrollPane1 = new JScrollPane();
-        contentPane.add( scrollPane1, BorderLayout.CENTER );
-        spiTable = new JTable();
-        scrollPane1.setViewportView( spiTable );
-    }
-
-    public JComponent $$$getRootComponent$$$()
-    {
-        return contentPane;
-    }
-
-    private static class SPITableModel
-        extends AbstractTableModel
-    {
-        /**
-         * the column names for this model
-         */
-        private static final String[] COLUMN_NAMES =
-        {
-            BUNDLE.getString( "Dependency.Column" ),
-            BUNDLE.getString( "Module.Column" ),
-            BUNDLE.getString( "Layer.Column" )
-        };
-        private final ArrayList<TableRow> rows;
-
-        private SPITableModel()
-        {
-            rows = new ArrayList<>();
-        }
-
-        private void addRow( List<ServiceDetailDescriptor> list )
-        {
-            if( list.isEmpty() )
-            {
-                return;
-            }
-
-            int i1 = rows.size();
-            if( i1 > 0 )
-            {
-                i1--;
-            }
-
-            int i2 = 0;
-
-            for( ServiceDetailDescriptor descriptor : list )
-            {
-                TableRow row = new TableRow( COLUMN_NAMES.length );
-                row.set( 0, descriptor );
-                row.set( 1, descriptor.module() );
-                row.set( 2, descriptor.module().layer() );
-                this.rows.add( row );
-                i2++;
-            }
-
-            fireTableRowsInserted( i1, i1 + i2 );
-        }
-
-        @Override
-        public Object getValueAt( int rowIndex, int columnIndex )
-        {
-            TableRow row = rows.get( rowIndex );
-            return row.get( columnIndex );
-        }
-
-        private void clear()
-        {
-            rows.clear();
-            fireTableDataChanged();
-        }
-
-        @Override
-        public int getColumnCount()
-        {
-            return COLUMN_NAMES.length;
-        }
-
-        @Override
-        public String getColumnName( int col )
-        {
-            return COLUMN_NAMES[ col];
-        }
-
-        @Override
-        public int getRowCount()
-        {
-            return rows.size();
-        }
-    }
-
-    private static class DependencyCellRenderer
-        extends DefaultTableCellRenderer
-    {
-        @Override
-        public final Component getTableCellRendererComponent( JTable table,
-                                                              Object value,
-                                                              boolean isSelected,
-                                                              boolean hasFocus,
-                                                              int row,
-                                                              int column
-        )
-        {
-            if( value != null )
-            {
-                value = "<html><a href=\"" + value.toString() + "\">" + value.toString() + "</a></html>";
-            }
-
-            super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );
-
-            return this;
-        }
-    }
-
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/ServiceConfigurationPane.form b/tools/envisage/src/main/java/org/qi4j/envisage/detail/ServiceConfigurationPane.form
deleted file mode 100644
index e6e4aae..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/ServiceConfigurationPane.form
+++ /dev/null
@@ -1,127 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.qi4j.envisage.detail.ServiceConfigurationPane">
-  <grid id="27dc6" binding="contentPane" layout-manager="GridBagLayout">
-    <constraints>
-      <xy x="20" y="20" width="311" height="266"/>
-    </constraints>
-    <properties/>
-    <border type="none"/>
-    <children>
-      <component id="9d75a" class="javax.swing.JLabel">
-        <constraints>
-          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="0.0"/>
-        </constraints>
-        <properties>
-          <text resource-bundle="org/qi4j/envisage/detail/ServiceConfigurationPane" key="CTL_Name.Text"/>
-        </properties>
-      </component>
-      <hspacer id="f7748">
-        <constraints>
-          <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="0.0"/>
-        </constraints>
-      </hspacer>
-      <vspacer id="4ccd5">
-        <constraints>
-          <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="0.0"/>
-        </constraints>
-      </vspacer>
-      <component id="f0ff0" class="javax.swing.JLabel" binding="nameLabel">
-        <constraints>
-          <grid row="1" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="0.0"/>
-        </constraints>
-        <properties>
-          <text value="Label"/>
-        </properties>
-      </component>
-      <vspacer id="97950">
-        <constraints>
-          <grid row="8" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="1.0"/>
-        </constraints>
-      </vspacer>
-      <component id="50b2b" class="javax.swing.JLabel">
-        <constraints>
-          <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="0.0"/>
-        </constraints>
-        <properties>
-          <text resource-bundle="org/qi4j/envisage/detail/ServiceConfigurationPane" key="CTL_Class.Text"/>
-        </properties>
-      </component>
-      <component id="86ec7" class="javax.swing.JLabel" binding="classLabel">
-        <constraints>
-          <grid row="3" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="1.0" weighty="0.0"/>
-        </constraints>
-        <properties>
-          <text value="Label"/>
-        </properties>
-      </component>
-      <vspacer id="bd0b9">
-        <constraints>
-          <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="0.0"/>
-        </constraints>
-      </vspacer>
-      <component id="43766" class="javax.swing.JButton" binding="linkButton">
-        <constraints>
-          <grid row="7" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="0.0"/>
-        </constraints>
-        <properties>
-          <text resource-bundle="org/qi4j/envisage/detail/ServiceConfigurationPane" key="CTL_Link.Text"/>
-        </properties>
-      </component>
-      <vspacer id="ab189">
-        <constraints>
-          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="0.0"/>
-        </constraints>
-      </vspacer>
-      <component id="cbdeb" class="javax.swing.JLabel">
-        <constraints>
-          <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="0.0"/>
-        </constraints>
-        <properties>
-          <text resource-bundle="org/qi4j/envisage/detail/ServiceConfigurationPane" key="CTL_Type.Text"/>
-        </properties>
-      </component>
-      <component id="845aa" class="javax.swing.JLabel" binding="typeLabel">
-        <constraints>
-          <grid row="5" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="0.0"/>
-        </constraints>
-        <properties>
-          <text value="Label"/>
-        </properties>
-      </component>
-      <vspacer id="f9c4">
-        <constraints>
-          <grid row="6" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
-          <gridbag weightx="0.0" weighty="0.0"/>
-        </constraints>
-      </vspacer>
-    </children>
-  </grid>
-</form>
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/ServiceConfigurationPane.java b/tools/envisage/src/main/java/org/qi4j/envisage/detail/ServiceConfigurationPane.java
deleted file mode 100644
index 129b059..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/ServiceConfigurationPane.java
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.detail;
-
-import java.awt.BorderLayout;
-import java.awt.Cursor;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.util.ResourceBundle;
-import javax.swing.AbstractButton;
-import javax.swing.JButton;
-import javax.swing.JComponent;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import org.qi4j.api.composite.ModelDescriptor;
-import org.qi4j.envisage.event.LinkEvent;
-import org.qi4j.tools.model.descriptor.CompositeDetailDescriptor;
-import org.qi4j.tools.model.descriptor.EntityDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ObjectDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ServiceDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ValueDetailDescriptor;
-import org.qi4j.tools.model.util.DescriptorUtilities;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Implementation of Service Configuration Panel
- */
-/* package */ final class ServiceConfigurationPane
-    extends DetailPane
-{
-    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( ServiceConfigurationPane.class.getName() );
-
-    private JPanel contentPane;
-    private JLabel nameLabel;
-    private JLabel classLabel;
-    private JButton linkButton;
-    private JLabel typeLabel;
-
-    private Object configDescriptor;
-    private Cursor defaultCursor;
-    private Cursor linkCursor;
-
-    /* package */ ServiceConfigurationPane( DetailModelPane detailModelPane )
-    {
-        super( detailModelPane );
-        this.setLayout( new BorderLayout() );
-        this.add( contentPane, BorderLayout.CENTER );
-
-        defaultCursor = getCursor();
-        linkCursor = LinkEvent.LINK_CURSOR;
-
-        linkButton.addActionListener( new ActionListener()
-        {
-            @Override
-            public void actionPerformed( ActionEvent evt )
-            {
-                linkActivated();
-            }
-        } );
-
-        nameLabel.addMouseListener( new MouseAdapter()
-        {
-            @Override
-            public void mouseClicked( MouseEvent evt )
-            {
-                linkActivated();
-            }
-
-            @Override
-            public void mouseEntered( MouseEvent evt )
-            {
-                setCursor( linkCursor );
-            }
-
-            @Override
-            public void mouseExited( MouseEvent evt )
-            {
-                setCursor( defaultCursor );
-            }
-        } );
-    }
-
-    private void linkActivated()
-    {
-        if( configDescriptor == null )
-        {
-            return;
-        }
-        LinkEvent linkEvt = new LinkEvent( this, configDescriptor );
-        detailModelPane.fireLinkActivated( linkEvt );
-    }
-
-    private void clear()
-    {
-        nameLabel.setText( null );
-        classLabel.setText( null );
-        typeLabel.setText( null );
-        linkButton.setEnabled( false );
-        configDescriptor = null;
-    }
-
-    @Override
-    protected void setDescriptor( Object objectDesciptor )
-    {
-        clear();
-
-        if( !( objectDesciptor instanceof ServiceDetailDescriptor ) )
-        {
-            return;
-        }
-
-        configDescriptor = DescriptorUtilities.findServiceConfiguration( (ServiceDetailDescriptor) objectDesciptor );
-        if( configDescriptor == null )
-        {
-            return;
-        }
-
-        ModelDescriptor spiDescriptor = null;
-        String typeString = null;
-        if( configDescriptor instanceof ServiceDetailDescriptor )
-        {
-            spiDescriptor = ( (ServiceDetailDescriptor) configDescriptor ).descriptor();
-            typeString = "Service";
-        }
-        else if( configDescriptor instanceof EntityDetailDescriptor )
-        {
-            spiDescriptor = ( (EntityDetailDescriptor) configDescriptor ).descriptor();
-            typeString = "Entity";
-        }
-        else if( configDescriptor instanceof ValueDetailDescriptor )
-        {
-            spiDescriptor = ( (ValueDetailDescriptor) configDescriptor ).descriptor();
-            typeString = "Value";
-        }
-        else if( configDescriptor instanceof ObjectDetailDescriptor )
-        {
-            spiDescriptor = ( (ObjectDetailDescriptor) configDescriptor ).descriptor();
-            typeString = "Object";
-        }
-        else if( configDescriptor instanceof CompositeDetailDescriptor )
-        {
-            spiDescriptor = ( (ObjectDetailDescriptor) configDescriptor ).descriptor();
-            typeString = "Transient";
-        }
-
-        Class<?> type = first( spiDescriptor.types() );
-        String simpleName = type.getSimpleName();
-        nameLabel.setText( "<html><a href='" + simpleName + "'>" + simpleName + "</a></html>" );
-        classLabel.setText( type.getName() );
-        typeLabel.setText( typeString );
-        linkButton.setEnabled( true );
-    }
-
-    
-    {
-// GUI initializer generated by IntelliJ IDEA GUI Designer
-// >>> IMPORTANT!! <<<
-// DO NOT EDIT OR ADD ANY CODE HERE!
-        $$$setupUI$$$();
-    }
-
-    /**
-     * Method generated by IntelliJ IDEA GUI Designer
-     * >>> IMPORTANT!! <<<
-     * DO NOT edit this method OR call it in your code!
-     *
-     */
-    private void $$$setupUI$$$()
-    {
-        contentPane = new JPanel();
-        contentPane.setLayout( new GridBagLayout() );
-        final JLabel label1 = new JLabel();
-        this.$$$loadLabelText$$$( label1, ResourceBundle.getBundle( "org/qi4j/envisage/detail/ServiceConfigurationPane" ).getString( "CTL_Name.Text" ) );
-        GridBagConstraints gbc;
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 1;
-        gbc.anchor = GridBagConstraints.EAST;
-        contentPane.add( label1, gbc );
-        final JPanel spacer1 = new JPanel();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 1;
-        gbc.gridy = 1;
-        gbc.fill = GridBagConstraints.HORIZONTAL;
-        contentPane.add( spacer1, gbc );
-        final JPanel spacer2 = new JPanel();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 2;
-        gbc.fill = GridBagConstraints.VERTICAL;
-        contentPane.add( spacer2, gbc );
-        nameLabel = new JLabel();
-        nameLabel.setText( "Label" );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 2;
-        gbc.gridy = 1;
-        gbc.anchor = GridBagConstraints.WEST;
-        contentPane.add( nameLabel, gbc );
-        final JPanel spacer3 = new JPanel();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 8;
-        gbc.weighty = 1.0;
-        gbc.fill = GridBagConstraints.VERTICAL;
-        contentPane.add( spacer3, gbc );
-        final JLabel label2 = new JLabel();
-        this.$$$loadLabelText$$$( label2, ResourceBundle.getBundle( "org/qi4j/envisage/detail/ServiceConfigurationPane" ).getString( "CTL_Class.Text" ) );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 3;
-        gbc.anchor = GridBagConstraints.EAST;
-        contentPane.add( label2, gbc );
-        classLabel = new JLabel();
-        classLabel.setText( "Label" );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 2;
-        gbc.gridy = 3;
-        gbc.weightx = 1.0;
-        gbc.anchor = GridBagConstraints.WEST;
-        contentPane.add( classLabel, gbc );
-        final JPanel spacer4 = new JPanel();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 4;
-        gbc.fill = GridBagConstraints.VERTICAL;
-        contentPane.add( spacer4, gbc );
-        linkButton = new JButton();
-        this.$$$loadButtonText$$$( linkButton, ResourceBundle.getBundle( "org/qi4j/envisage/detail/ServiceConfigurationPane" ).getString( "CTL_Link.Text" ) );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 2;
-        gbc.gridy = 7;
-        gbc.anchor = GridBagConstraints.WEST;
-        contentPane.add( linkButton, gbc );
-        final JPanel spacer5 = new JPanel();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 0;
-        gbc.fill = GridBagConstraints.VERTICAL;
-        contentPane.add( spacer5, gbc );
-        final JLabel label3 = new JLabel();
-        this.$$$loadLabelText$$$( label3, ResourceBundle.getBundle( "org/qi4j/envisage/detail/ServiceConfigurationPane" ).getString( "CTL_Type.Text" ) );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 5;
-        gbc.anchor = GridBagConstraints.EAST;
-        contentPane.add( label3, gbc );
-        typeLabel = new JLabel();
-        typeLabel.setText( "Label" );
-        gbc = new GridBagConstraints();
-        gbc.gridx = 2;
-        gbc.gridy = 5;
-        gbc.anchor = GridBagConstraints.WEST;
-        contentPane.add( typeLabel, gbc );
-        final JPanel spacer6 = new JPanel();
-        gbc = new GridBagConstraints();
-        gbc.gridx = 0;
-        gbc.gridy = 6;
-        gbc.fill = GridBagConstraints.VERTICAL;
-        contentPane.add( spacer6, gbc );
-    }
-
-    private void $$$loadLabelText$$$( JLabel component, String text )
-    {
-        StringBuffer result = new StringBuffer();
-        boolean haveMnemonic = false;
-        char mnemonic = '\0';
-        int mnemonicIndex = -1;
-        for( int i = 0; i < text.length(); i++ )
-        {
-            if( text.charAt( i ) == '&' )
-            {
-                i++;
-                if( i == text.length() )
-                {
-                    break;
-                }
-                if( !haveMnemonic && text.charAt( i ) != '&' )
-                {
-                    haveMnemonic = true;
-                    mnemonic = text.charAt( i );
-                    mnemonicIndex = result.length();
-                }
-            }
-            result.append( text.charAt( i ) );
-        }
-        component.setText( result.toString() );
-        if( haveMnemonic )
-        {
-            component.setDisplayedMnemonic( mnemonic );
-            component.setDisplayedMnemonicIndex( mnemonicIndex );
-        }
-    }
-
-    private void $$$loadButtonText$$$( AbstractButton component, String text )
-    {
-        StringBuffer result = new StringBuffer();
-        boolean haveMnemonic = false;
-        char mnemonic = '\0';
-        int mnemonicIndex = -1;
-        for( int i = 0; i < text.length(); i++ )
-        {
-            if( text.charAt( i ) == '&' )
-            {
-                i++;
-                if( i == text.length() )
-                {
-                    break;
-                }
-                if( !haveMnemonic && text.charAt( i ) != '&' )
-                {
-                    haveMnemonic = true;
-                    mnemonic = text.charAt( i );
-                    mnemonicIndex = result.length();
-                }
-            }
-            result.append( text.charAt( i ) );
-        }
-        component.setText( result.toString() );
-        if( haveMnemonic )
-        {
-            component.setMnemonic( mnemonic );
-            component.setDisplayedMnemonicIndex( mnemonicIndex );
-        }
-    }
-
-    public JComponent $$$getRootComponent$$$()
-    {
-        return contentPane;
-    }
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/ServiceUsagePane.form b/tools/envisage/src/main/java/org/qi4j/envisage/detail/ServiceUsagePane.form
deleted file mode 100644
index bcf1ee5..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/ServiceUsagePane.form
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.qi4j.envisage.detail.ServiceUsagePane">
-  <grid id="27dc6" binding="contentPane" layout-manager="BorderLayout" hgap="0" vgap="0">
-    <constraints>
-      <xy x="20" y="20" width="374" height="274"/>
-    </constraints>
-    <properties/>
-    <border type="none"/>
-    <children>
-      <scrollpane id="da4b1">
-        <constraints border-constraint="Center"/>
-        <properties/>
-        <border type="none"/>
-        <children>
-          <component id="7dfce" class="javax.swing.JTable" binding="usageTable">
-            <constraints/>
-            <properties/>
-          </component>
-        </children>
-      </scrollpane>
-    </children>
-  </grid>
-</form>
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/ServiceUsagePane.java b/tools/envisage/src/main/java/org/qi4j/envisage/detail/ServiceUsagePane.java
deleted file mode 100644
index fcd2f19..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/ServiceUsagePane.java
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.detail;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.Cursor;
-import java.awt.event.MouseEvent;
-import java.lang.annotation.Annotation;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ResourceBundle;
-import javax.swing.JComponent;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTable;
-import javax.swing.ListSelectionModel;
-import javax.swing.event.MouseInputAdapter;
-import javax.swing.table.AbstractTableModel;
-import javax.swing.table.DefaultTableCellRenderer;
-import javax.swing.table.TableColumnModel;
-import org.qi4j.api.composite.DependencyDescriptor;
-import org.qi4j.envisage.event.LinkEvent;
-import org.qi4j.envisage.util.TableRow;
-import org.qi4j.envisage.util.TableRowUtilities;
-import org.qi4j.tools.model.descriptor.InjectedFieldDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ServiceDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ServiceUsage;
-import org.qi4j.tools.model.util.DescriptorUtilities;
-
-/**
- * Service Usage tab, which shows all the 'users' of the Service,
- * meaning the 'reverse' of a Dependency, all 'links' pointing into the Service should be listed here.
- * The list should be in three 'sections' according to the Visibility,
- * i.e. one section for all usages from within the same Module,
- * one section for usages within the same Layer
- * and one section for usages from Layers above.
- * I think the order of these sections
- * should be "LayersAbove", "WithinLayer" and "WithinModule"
- * in that order from top.
- */
-/* package */ final class ServiceUsagePane
-    extends DetailPane
-{
-    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( ServiceUsagePane.class.getName() );
-
-    private UsageTableModel usageTableModel;
-    private JTable usageTable;
-    private JPanel contentPane;
-
-    private Object linkObject;
-    private Cursor defaultCursor;
-    private Cursor linkCursor;
-
-    /* package */ ServiceUsagePane( DetailModelPane detailModelPane )
-    {
-        super( detailModelPane );
-        this.setLayout( new BorderLayout() );
-        this.add( contentPane, BorderLayout.CENTER );
-
-        usageTableModel = new UsageTableModel();
-        usageTable.setModel( usageTableModel );
-        usageTable.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
-
-        TableColumnModel columnModel = usageTable.getColumnModel();
-        columnModel.getColumn( 0 ).setCellRenderer( new OwnerCellRenderer() );
-        columnModel.getColumn( 1 ).setCellRenderer( new FieldCellRenderer() );
-
-        /*columnModel.getColumn( 0 ).setPreferredWidth( 90 );
-         columnModel.getColumn( 1 ).setPreferredWidth( 550 );
-         */
-        defaultCursor = getCursor();
-        linkCursor = LinkEvent.LINK_CURSOR;
-
-        MouseInputAdapter mouseInputListener = new MouseInputAdapter()
-        {
-            @Override
-            public void mouseMoved( MouseEvent evt )
-            {
-                // Column 1 is the Owner Column
-                int col = usageTable.columnAtPoint( evt.getPoint() );
-                if( col == 0 )
-                {
-                    setCursor( linkCursor );
-                }
-                else
-                {
-                    if( !getCursor().equals( defaultCursor ) )
-                    {
-                        setCursor( defaultCursor );
-                    }
-                }
-            }
-
-            @Override
-            public void mouseClicked( MouseEvent evt )
-            {
-                /*if( evt.getClickCount() < 2 )
-                 {
-                 return;
-                 }*/
-
-                int col = usageTable.columnAtPoint( evt.getPoint() );
-                if( col != 0 )
-                {
-                    return;
-                }
-
-                int row = usageTable.rowAtPoint( evt.getPoint() );
-                if( row < 0 )
-                {
-                    return;
-                }
-
-                linkObject = usageTableModel.getValueAt( row, col );
-                linkActivated();
-                linkObject = null;
-            }
-        };
-
-        usageTable.addMouseMotionListener( mouseInputListener );
-        usageTable.addMouseListener( mouseInputListener );
-    }
-
-    private void linkActivated()
-    {
-        if( linkObject == null )
-        {
-            return;
-        }
-        LinkEvent linkEvt = new LinkEvent( this, linkObject );
-        detailModelPane.fireLinkActivated( linkEvt );
-    }
-
-    @Override
-    protected void setDescriptor( Object objectDesciptor )
-    {
-        clear();
-
-        if( !( objectDesciptor instanceof ServiceDetailDescriptor ) )
-        {
-            return;
-        }
-
-        ServiceDetailDescriptor descriptor = (ServiceDetailDescriptor) objectDesciptor;
-
-        List<ServiceUsage> serviceUsages = DescriptorUtilities.findServiceUsage( descriptor );
-        usageTableModel.addRows( TableRowUtilities.toTableRows( serviceUsages ) );
-    }
-
-    private void clear()
-    {
-        linkObject = null;
-        usageTableModel.clear();
-    }
-
-    
-    {
-// GUI initializer generated by IntelliJ IDEA GUI Designer
-// >>> IMPORTANT!! <<<
-// DO NOT EDIT OR ADD ANY CODE HERE!
-        $$$setupUI$$$();
-    }
-
-    /**
-     * Method generated by IntelliJ IDEA GUI Designer
-     * >>> IMPORTANT!! <<<
-     * DO NOT edit this method OR call it in your code!
-     *
-     */
-    private void $$$setupUI$$$()
-    {
-        contentPane = new JPanel();
-        contentPane.setLayout( new BorderLayout( 0, 0 ) );
-        final JScrollPane scrollPane1 = new JScrollPane();
-        contentPane.add( scrollPane1, BorderLayout.CENTER );
-        usageTable = new JTable();
-        scrollPane1.setViewportView( usageTable );
-    }
-
-    public JComponent $$$getRootComponent$$$()
-    {
-        return contentPane;
-    }
-
-    private static class UsageTableModel
-        extends AbstractTableModel
-    {
-        /**
-         * the column names for this model
-         */
-        private static final String[] COLUMN_NAMES =
-        {
-            BUNDLE.getString( "Owner.Column" ),
-            BUNDLE.getString( "Usage.Column" ),
-            BUNDLE.getString( "Module.Column" ),
-            BUNDLE.getString( "Layer.Column" )
-        };
-        private final ArrayList<TableRow> rows;
-
-        private UsageTableModel()
-        {
-            rows = new ArrayList<>();
-        }
-
-        private void addRows( List<TableRow> rows )
-        {
-            int i1 = rows.size();
-            if( i1 > 0 )
-            {
-                i1--;
-            }
-
-            int i2 = 0;
-            for( TableRow row : rows )
-            {
-                this.rows.add( row );
-                i2++;
-            }
-
-            fireTableRowsInserted( i1, i1 + i2 );
-        }
-
-        /**
-         * Add row data
-         *
-         * @param row TableRow to be added
-         */
-        private void addRow( TableRow row )
-        {
-            int i1 = rows.size();
-            if( i1 > 0 )
-            {
-                i1--;
-            }
-
-            rows.add( row );
-            fireTableRowsInserted( i1, i1 + 1 );
-        }
-
-        @Override
-        public Object getValueAt( int rowIndex, int columnIndex )
-        {
-            TableRow row = rows.get( rowIndex );
-            return row.get( columnIndex );
-        }
-
-        private void clear()
-        {
-            rows.clear();
-            fireTableDataChanged();
-        }
-
-        @Override
-        public int getColumnCount()
-        {
-            return COLUMN_NAMES.length;
-        }
-
-        @Override
-        public String getColumnName( int col )
-        {
-            return COLUMN_NAMES[ col];
-        }
-
-        @Override
-        public int getRowCount()
-        {
-            return rows.size();
-        }
-    }
-
-    private static class OwnerCellRenderer
-        extends DefaultTableCellRenderer
-    {
-        @Override
-        public final Component getTableCellRendererComponent( JTable table,
-                                                              Object value,
-                                                              boolean isSelected,
-                                                              boolean hasFocus,
-                                                              int row,
-                                                              int column
-        )
-        {
-            if( value != null )
-            {
-                value = "<html><a href=\"" + value.toString() + "\">" + value.toString() + "</a></html>";
-            }
-
-            super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );
-
-            return this;
-        }
-    }
-
-    private static class FieldCellRenderer
-        extends DefaultTableCellRenderer
-    {
-        @Override
-        public final Component getTableCellRendererComponent( JTable table,
-                                                              Object value,
-                                                              boolean isSelected,
-                                                              boolean hasFocus,
-                                                              int row,
-                                                              int column
-        )
-        {
-            if( value != null )
-            {
-                InjectedFieldDetailDescriptor descriptor = (InjectedFieldDetailDescriptor) value;
-                DependencyDescriptor dependencyDescriptor = descriptor.descriptor().dependency();
-                Annotation annotation = dependencyDescriptor.injectionAnnotation();
-                value = descriptor.toString() + " (@" + annotation.annotationType().getSimpleName() + ")";
-            }
-
-            return super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column );
-        }
-    }
-
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/StatePane.form b/tools/envisage/src/main/java/org/qi4j/envisage/detail/StatePane.form
deleted file mode 100644
index 90fb4e4..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/StatePane.form
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.qi4j.envisage.detail.StatePane">
-  <grid id="27dc6" binding="contentPane" layout-manager="BorderLayout" hgap="0" vgap="0">
-    <constraints>
-      <xy x="20" y="20" width="500" height="400"/>
-    </constraints>
-    <properties/>
-    <border type="none"/>
-    <children>
-      <splitpane id="e5c0d" binding="splitPane">
-        <constraints border-constraint="Center"/>
-        <properties/>
-        <border type="none"/>
-        <children>
-          <scrollpane id="321ea">
-            <constraints>
-              <splitpane position="left"/>
-            </constraints>
-            <properties/>
-            <border type="none"/>
-            <children>
-              <component id="975eb" class="javax.swing.JList" binding="methodList">
-                <constraints/>
-                <properties/>
-              </component>
-            </children>
-          </scrollpane>
-          <scrollpane id="5fb60">
-            <constraints>
-              <splitpane position="right"/>
-            </constraints>
-            <properties/>
-            <border type="none"/>
-            <children>
-              <component id="cc763" class="javax.swing.JTable" binding="methodDetailTable">
-                <constraints/>
-                <properties/>
-              </component>
-            </children>
-          </scrollpane>
-        </children>
-      </splitpane>
-    </children>
-  </grid>
-</form>
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/StatePane.java b/tools/envisage/src/main/java/org/qi4j/envisage/detail/StatePane.java
deleted file mode 100644
index 31f1be8..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/StatePane.java
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.detail;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ResourceBundle;
-import javax.swing.DefaultListCellRenderer;
-import javax.swing.DefaultListModel;
-import javax.swing.Icon;
-import javax.swing.ImageIcon;
-import javax.swing.JComponent;
-import javax.swing.JList;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JSplitPane;
-import javax.swing.JTable;
-import javax.swing.ListSelectionModel;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.table.AbstractTableModel;
-import javax.swing.table.TableColumnModel;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.GenericAssociationInfo;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.property.GenericPropertyInfo;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.util.Classes;
-import org.qi4j.envisage.util.TableRow;
-import org.qi4j.tools.model.descriptor.CompositeDetailDescriptor;
-import org.qi4j.tools.model.descriptor.CompositeMethodDetailDescriptor;
-import org.qi4j.tools.model.descriptor.MethodConcernDetailDescriptor;
-import org.qi4j.tools.model.descriptor.MethodSideEffectDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ObjectDetailDescriptor;
-import org.qi4j.tools.model.util.DescriptorUtilities;
-
-import static org.qi4j.functional.Iterables.first;
-
-/**
- * Implementation of Composite State Panel
- */
-/* package */ final class StatePane
-    extends DetailPane
-{
-    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( StatePane.class.getName() );
-
-    private JPanel contentPane;
-    private JList methodList;
-    private JSplitPane splitPane;
-    private JTable methodDetailTable;
-
-    private final DefaultListModel methodListModel;
-    private final MethodDetailTableModel methodDetailTableModel;
-
-    /* package */ StatePane( DetailModelPane detailModelPane )
-    {
-        super( detailModelPane );
-        this.setLayout( new BorderLayout() );
-        this.add( contentPane, BorderLayout.CENTER );
-
-        methodListModel = new DefaultListModel();
-        methodList.setModel( methodListModel );
-        methodList.setCellRenderer( new MethodListCellRenderer() );
-        methodList.setPrototypeCellValue( "12345678901234567890" );
-        methodList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
-
-        methodDetailTableModel = new MethodDetailTableModel();
-        methodDetailTable.setModel( methodDetailTableModel );
-
-        TableColumnModel columnModel = methodDetailTable.getColumnModel();
-        columnModel.getColumn( 0 ).setPreferredWidth( 75 );
-        columnModel.getColumn( 1 ).setPreferredWidth( 400 );
-
-        //splitPane.setDividerLocation( .1 );
-        methodList.addListSelectionListener( new ListSelectionListener()
-        {
-            @Override
-            public void valueChanged( ListSelectionEvent evt )
-            {
-                methodListValueChanged( evt );
-            }
-        } );
-    }
-
-    @Override
-    protected void setDescriptor( Object objectDesciptor )
-    {
-        clear();
-
-        if( objectDesciptor instanceof CompositeDetailDescriptor )
-        {
-            CompositeDetailDescriptor descriptor = ( (CompositeDetailDescriptor) objectDesciptor );
-            List<CompositeMethodDetailDescriptor> list = DescriptorUtilities.findState( descriptor );
-            for( CompositeMethodDetailDescriptor methodDescriptor : list )
-            {
-                methodListModel.addElement( methodDescriptor );
-            }
-
-            if( !methodListModel.isEmpty() )
-            {
-                methodList.setSelectedIndex( 0 );
-            }
-        }
-        else if( objectDesciptor instanceof ObjectDetailDescriptor )
-        {
-            // Object does not have state
-        }
-    }
-
-    private void clear()
-    {
-        methodListModel.clear();
-        methodDetailTableModel.clear();
-    }
-
-    private void methodListValueChanged( ListSelectionEvent evt )
-    {
-        if( evt.getValueIsAdjusting() )
-        {
-            return;
-        }
-        Object obj = methodList.getSelectedValue();
-        if( obj == null )
-        {
-            methodDetailTableModel.clear();
-            return;
-        }
-        methodDetailTableModel.reload( (CompositeMethodDetailDescriptor) obj );
-    }
-
-    
-    {
-// GUI initializer generated by IntelliJ IDEA GUI Designer
-// >>> IMPORTANT!! <<<
-// DO NOT EDIT OR ADD ANY CODE HERE!
-        $$$setupUI$$$();
-    }
-
-    /**
-     * Method generated by IntelliJ IDEA GUI Designer
-     * >>> IMPORTANT!! <<<
-     * DO NOT edit this method OR call it in your code!
-     *
-     */
-    private void $$$setupUI$$$()
-    {
-        contentPane = new JPanel();
-        contentPane.setLayout( new BorderLayout( 0, 0 ) );
-        splitPane = new JSplitPane();
-        contentPane.add( splitPane, BorderLayout.CENTER );
-        final JScrollPane scrollPane1 = new JScrollPane();
-        splitPane.setLeftComponent( scrollPane1 );
-        methodList = new JList();
-        scrollPane1.setViewportView( methodList );
-        final JScrollPane scrollPane2 = new JScrollPane();
-        splitPane.setRightComponent( scrollPane2 );
-        methodDetailTable = new JTable();
-        scrollPane2.setViewportView( methodDetailTable );
-    }
-
-    public JComponent $$$getRootComponent$$$()
-    {
-        return contentPane;
-    }
-
-    private static class MethodDetailTableModel
-        extends AbstractTableModel
-    {
-        /**
-         * the column names for this model
-         */
-        private static final String[] COLUMN_NAMES =
-        {
-            "Name",
-            "Value"
-        };
-        private final ArrayList<TableRow> rows;
-
-        private MethodDetailTableModel()
-        {
-            rows = new ArrayList<>();
-        }
-
-        private void reload( CompositeMethodDetailDescriptor descriptor )
-        {
-            clear();
-
-            // mixin type
-            rows.add( new TableRow( 2, "interface", descriptor.descriptor().method().getDeclaringClass().getSimpleName() ) );
-
-            StringBuilder str = new StringBuilder();
-            for( Annotation annotation : descriptor.descriptor().method().getAnnotations() )
-            {
-                String ann = annotation.toString();
-                ann = "@" + ann.substring( ann.lastIndexOf( '.' ) + 1 );
-                str.append( ann ).append( " " );
-            }
-            str.append( Classes.simpleGenericNameOf( descriptor.descriptor().method().getGenericReturnType() ) );
-
-            rows.add( new TableRow( 2, "return", str.toString() ) );
-
-            // concern
-            boolean first = true;
-            for( MethodConcernDetailDescriptor concern : descriptor.concerns().concerns() )
-            {
-                if( first )
-                {
-                    rows.add( new TableRow( 2, "concern", concern.toString() ) );
-                    first = false;
-                }
-                else
-                {
-                    rows.add( new TableRow( 2, "", concern.toString() ) );
-                }
-            }
-
-            // sideEffect
-            first = false;
-            for( MethodSideEffectDetailDescriptor sideEffect : descriptor.sideEffects().sideEffects() )
-            {
-                if( first )
-                {
-                    rows.add( new TableRow( 2, "sideEffect", sideEffect.toString() ) );
-                    first = false;
-                }
-                else
-                {
-                    rows.add( new TableRow( 2, "", sideEffect.toString() ) );
-                }
-            }
-
-            fireTableDataChanged();
-        }
-
-        @Override
-        public Object getValueAt( int rowIndex, int columnIndex )
-        {
-            TableRow row = this.rows.get( rowIndex );
-            return row.get( columnIndex );
-        }
-
-        private void clear()
-        {
-            rows.clear();
-            fireTableDataChanged();
-        }
-
-        @Override
-        public int getColumnCount()
-        {
-            return COLUMN_NAMES.length;
-        }
-
-        @Override
-        public String getColumnName( int col )
-        {
-            return COLUMN_NAMES[ col];
-        }
-
-        @Override
-        public int getRowCount()
-        {
-            return rows.size();
-        }
-    }
-
-    private static class MethodListCellRenderer
-        extends DefaultListCellRenderer
-    {
-        private final Icon publicIcon;
-        private final Icon privateIcon;
-
-        private MethodListCellRenderer()
-        {
-            try
-            {
-                publicIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Public" ) ) );
-                privateIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Private" ) ) );
-            }
-            catch( Exception ex )
-            {
-                throw new RuntimeException( ex );
-            }
-        }
-
-        @Override
-        public Component getListCellRendererComponent( JList list,
-                                                       Object value,
-                                                       int index,
-                                                       boolean isSelected,
-                                                       boolean cellHasFocus
-        )
-        {
-            super.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus );
-            if( !( value instanceof CompositeMethodDetailDescriptor ) )
-            {
-                return this;
-            }
-
-            Icon icon;
-            CompositeMethodDetailDescriptor descriptor = (CompositeMethodDetailDescriptor) value;
-            Class compositeClass = first( descriptor.composite().descriptor().types() );
-            Class mixinMethodClass = descriptor.descriptor().method().getDeclaringClass();
-            if( mixinMethodClass.isAssignableFrom( compositeClass ) )
-            {
-                icon = publicIcon;
-            }
-            else
-            {
-                icon = privateIcon;
-            }
-
-            if( icon != null )
-            {
-                setIcon( icon );
-            }
-
-            Method method = descriptor.descriptor().method();
-            Class<?> methodReturnType = method.getReturnType();
-
-            if( Property.class.isAssignableFrom( methodReturnType ) )
-            {
-                Type t = GenericPropertyInfo.propertyTypeOf( method );
-                if( t instanceof Class )
-                {
-                    setText( method.getName() + ":" + ( (Class) t ).getSimpleName() );
-                }
-            }
-            else if( Association.class.isAssignableFrom( methodReturnType ) )
-            {
-                Type t = GenericAssociationInfo.associationTypeOf( method );
-                if( t instanceof Class )
-                {
-                    setText( method.getName() + "->" + ( (Class) t ).getSimpleName() );
-                }
-            }
-            else if( ManyAssociation.class.isAssignableFrom( methodReturnType ) )
-            {
-                Type t = GenericAssociationInfo.associationTypeOf( method );
-                if( t instanceof Class )
-                {
-                    setText( method.getName() + "=>" + ( (Class) t ).getSimpleName() );
-                }
-            }
-            else if( NamedAssociation.class.isAssignableFrom( methodReturnType ) )
-            {
-                Type t = GenericAssociationInfo.associationTypeOf( method );
-                if( t instanceof Class )
-                {
-                    setText( method.getName() + ">>" + ( (Class) t ).getSimpleName() );
-                }
-            }
-
-            return this;
-        }
-    }
-
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/detail/package.html b/tools/envisage/src/main/java/org/qi4j/envisage/detail/package.html
deleted file mode 100644
index 7778987..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/detail/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Envisage Tool Detail UI.</h2>
-    </body>
-</html>
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/event/LinkEvent.java b/tools/envisage/src/main/java/org/qi4j/envisage/event/LinkEvent.java
deleted file mode 100644
index 7224751..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/event/LinkEvent.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.event;
-
-import java.awt.Cursor;
-import java.util.EventObject;
-import javax.swing.text.html.HTMLEditorKit;
-
-public final class LinkEvent
-    extends EventObject
-{
-    public static final Cursor LINK_CURSOR = new HTMLEditorKit().getLinkCursor();
-
-    protected final Object object;
-
-    public LinkEvent( Object source, Object object )
-    {
-        super( source );
-        this.object = object;
-    }
-
-    public Object getObject()
-    {
-        return object;
-    }
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/event/LinkListener.java b/tools/envisage/src/main/java/org/qi4j/envisage/event/LinkListener.java
deleted file mode 100644
index 669e0df..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/event/LinkListener.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.event;
-
-import java.util.EventListener;
-
-public interface LinkListener
-    extends EventListener
-{
-    void activated( LinkEvent evt );
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/event/package.html b/tools/envisage/src/main/java/org/qi4j/envisage/event/package.html
deleted file mode 100644
index 949d2e1..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/event/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Envisage Tool UI Events.</h2>
-    </body>
-</html>
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/graph/GraphBuilder.java b/tools/envisage/src/main/java/org/qi4j/envisage/graph/GraphBuilder.java
deleted file mode 100644
index 656c96b..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/graph/GraphBuilder.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.graph;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import org.qi4j.tools.model.descriptor.ApplicationDetailDescriptor;
-import org.qi4j.tools.model.descriptor.EntityDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ImportedServiceDetailDescriptor;
-import org.qi4j.tools.model.descriptor.LayerDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ModuleDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ObjectDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ServiceDetailDescriptor;
-import org.qi4j.tools.model.descriptor.TransientDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ValueDetailDescriptor;
-import org.qi4j.tools.model.util.DescriptorNameComparator;
-import prefuse.data.Edge;
-import prefuse.data.Graph;
-import prefuse.data.Node;
-import prefuse.data.Table;
-
-/**
- * Build Qi4J application model as Prefuse Tree Graph
- */
-/* package */ final class GraphBuilder
-{
-    private final DescriptorNameComparator<Object> nameComparator = new DescriptorNameComparator<>();
-    private final Graph graph;
-    private final List childList;
-
-    /* package */ static Graph buildGraph( ApplicationDetailDescriptor descriptor )
-    {
-        GraphBuilder builder = new GraphBuilder();
-        return builder.buildApplicationNode( descriptor );
-    }
-
-    /* package */ GraphBuilder()
-    {
-        graph = new Graph( true );
-
-        Table nodeTable = graph.getNodeTable();
-        nodeTable.addColumn( GraphDisplay.NAME_LABEL, String.class );
-        nodeTable.addColumn( GraphDisplay.USER_OBJECT, Object.class );
-
-        Table edgeTable = graph.getEdgeTable();
-        edgeTable.addColumn( GraphDisplay.USES_EDGES, boolean.class, false );
-
-        childList = new ArrayList();
-    }
-
-    private Graph buildApplicationNode( ApplicationDetailDescriptor descriptor )
-    {
-        Node node = addChild( null, descriptor.descriptor().name(), descriptor );
-
-        buildLayersNode( node, descriptor.layers() );
-        buildUsesNode( node, descriptor.layers() );
-
-        return graph;
-    }
-
-    private void buildUsesNode( Node parent, Iterable<LayerDetailDescriptor> iter )
-    {
-        for( LayerDetailDescriptor descriptor : iter )
-        {
-            Node source = findNode( parent, descriptor );
-
-            for( LayerDetailDescriptor usesDescriptor : descriptor.usedLayers() )
-            {
-                Node target = findNode( parent, usesDescriptor );
-                if( target == null )
-                {
-                    continue;
-                }
-                Edge edge = graph.addEdge( source, target );
-                edge.setBoolean( GraphDisplay.USES_EDGES, true );
-            }
-        }
-    }
-
-    private Node findNode( Node parent, Object userObject )
-    {
-        Node node = null;
-
-        for( int i = 0; i < parent.getChildCount(); i++ )
-        {
-            Node tNode = parent.getChild( i );
-            Object obj = tNode.get( GraphDisplay.USER_OBJECT );
-            if( obj.equals( userObject ) )
-            {
-                node = tNode;
-                break;
-            }
-        }
-
-        return node;
-    }
-
-    private Node addChild( Node parent, String name, Object object )
-    {
-        Node childNode = graph.addNode();
-        childNode.set( GraphDisplay.NAME_LABEL, name );
-        childNode.set( GraphDisplay.USER_OBJECT, object );
-
-        // check for application node
-        if( parent != null )
-        {
-            graph.addEdge( parent, childNode );
-        }
-        return childNode;
-    }
-
-    private void buildLayersNode( Node parent, Iterable<LayerDetailDescriptor> iter )
-    {
-        for( LayerDetailDescriptor descriptor : iter )
-        {
-            Node childNode = addChild( parent, descriptor.descriptor().name(), descriptor );
-            buildModulesNode( childNode, descriptor.modules() );
-        }
-    }
-
-    private void buildModulesNode( Node parent, Iterable<ModuleDetailDescriptor> iter )
-    {
-        for( ModuleDetailDescriptor descriptor : iter )
-        {
-            Node childNode = addChild( parent, descriptor.descriptor().name(), descriptor );
-
-            buildServicesNode( childNode, descriptor.services() );
-            buildImportedServicesNode( childNode, descriptor.importedServices() );
-            buildEntitiesNode( childNode, descriptor.entities() );
-            buildTransientsNode( childNode, descriptor.transients() );
-            buildValuesNode( childNode, descriptor.values() );
-            buildObjectsNode( childNode, descriptor.objects() );
-        }
-    }
-
-    private void sortTypeChildren( Iterable iter )
-    {
-        childList.clear();
-        for( Object obj : iter )
-        {
-            childList.add( obj );
-        }
-
-        Collections.sort( childList, nameComparator );
-    }
-
-    private void buildServicesNode( Node parent, Iterable<ServiceDetailDescriptor> iter )
-    {
-        sortTypeChildren( iter );
-
-        boolean first = true;
-        for( Object obj : childList )
-        {
-            ServiceDetailDescriptor descriptor = (ServiceDetailDescriptor) obj;
-            if( first )
-            {
-                String name = "Services";
-                parent = addChild( parent, name, name );
-                first = false;
-            }
-            addChild( parent, descriptor.descriptor().toString(), descriptor );
-        }
-    }
-
-    private void buildImportedServicesNode( Node parent, Iterable<ImportedServiceDetailDescriptor> iter )
-    {
-        sortTypeChildren( iter );
-
-        boolean first = true;
-        for( Object obj : childList )
-        {
-            ImportedServiceDetailDescriptor descriptor = (ImportedServiceDetailDescriptor) obj;
-            if( first )
-            {
-                String name = "Imported Services";
-                parent = addChild( parent, name, name );
-                first = false;
-            }
-            addChild( parent, descriptor.descriptor().primaryType().getSimpleName(), descriptor );
-        }
-    }
-
-    private void buildEntitiesNode( Node parent, Iterable<EntityDetailDescriptor> iter )
-    {
-        sortTypeChildren( iter );
-
-        boolean first = true;
-        for( Object obj : childList )
-        {
-            EntityDetailDescriptor descriptor = (EntityDetailDescriptor) obj;
-            if( first )
-            {
-                String name = "Entities";
-                parent = addChild( parent, name, name );
-                first = false;
-            }
-            addChild( parent, descriptor.descriptor().toString(), descriptor );
-        }
-    }
-
-    private void buildTransientsNode( Node parent, Iterable<TransientDetailDescriptor> iter )
-    {
-        sortTypeChildren( iter );
-
-        boolean first = true;
-        for( Object obj : childList )
-        {
-            TransientDetailDescriptor descriptor = (TransientDetailDescriptor) obj;
-            if( first )
-            {
-                String name = "Transients";
-                parent = addChild( parent, name, name );
-                first = false;
-            }
-            addChild( parent, descriptor.descriptor().toString(), descriptor );
-        }
-    }
-
-    private void buildValuesNode( Node parent, Iterable<ValueDetailDescriptor> iter )
-    {
-        sortTypeChildren( iter );
-
-        boolean first = true;
-        for( Object obj : childList )
-        {
-            ValueDetailDescriptor descriptor = (ValueDetailDescriptor) obj;
-            if( first )
-            {
-                String name = "Values";
-                parent = addChild( parent, name, name );
-                first = false;
-            }
-            addChild( parent, descriptor.descriptor().toString(), descriptor );
-        }
-    }
-
-    private void buildObjectsNode( Node parent, Iterable<ObjectDetailDescriptor> iter )
-    {
-        sortTypeChildren( iter );
-
-        boolean first = true;
-        for( Object obj : childList )
-        {
-            ObjectDetailDescriptor descriptor = (ObjectDetailDescriptor) obj;
-            if( first )
-            {
-                String name = "Objects";
-                parent = addChild( parent, name, name );
-                first = false;
-            }
-            addChild( parent, descriptor.descriptor().toString(), descriptor );
-        }
-    }
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/graph/GraphDisplay.java b/tools/envisage/src/main/java/org/qi4j/envisage/graph/GraphDisplay.java
deleted file mode 100644
index 0f6f1e4..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/graph/GraphDisplay.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.graph;
-
-import org.qi4j.envisage.event.LinkEvent;
-import org.qi4j.envisage.event.LinkListener;
-import prefuse.Display;
-import prefuse.Visualization;
-import prefuse.data.Graph;
-
-public abstract class GraphDisplay
-    extends Display
-{
-    public static final String NAME_LABEL = "name";
-    public static final String USER_OBJECT = "userObject";
-
-    public static final String GRAPH = "graph";
-    public static final String GRAPH_NODES = "graph.nodes";
-    public static final String GRAPH_EDGES = "graph.edges";
-    public static final String USES_EDGES = "uses.edges";
-
-    protected GraphDisplay( Visualization visualization )
-    {
-        super( visualization );
-    }
-
-    public abstract void run( Graph graph );
-
-    public abstract void run();
-
-    public abstract void setSelectedValue( Object object );
-
-    /**
-     * Add a listener that's notified each time a change to the selection occurs.
-     *
-     * @param listener the LinkListener to add
-     */
-    public final void addLinkListener( LinkListener listener )
-    {
-        listenerList.add( LinkListener.class, listener );
-    }
-
-    /**
-     * Remove a listener from the list that's notified each time a change to the selection occurs.
-     *
-     * @param listener the LinkListener to remove
-     */
-    public final void removeLinkListener( LinkListener listener )
-    {
-        listenerList.remove( LinkListener.class, listener );
-    }
-
-    protected final void fireLinkActivated( LinkEvent evt )
-    {
-        // Guaranteed to return a non-null array
-        Object[] listeners = listenerList.getListenerList();
-        // Process the listeners last to first, notifying
-        // those that are interested in this event
-        for( int i = listeners.length - 2; i >= 0; i -= 2 )
-        {
-            if( listeners[i] == LinkListener.class )
-            {
-                ( (LinkListener) listeners[i + 1] ).activated( evt );
-            }
-        }
-    }
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/graph/GraphPane.java b/tools/envisage/src/main/java/org/qi4j/envisage/graph/GraphPane.java
deleted file mode 100644
index a94a814..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/graph/GraphPane.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.graph;
-
-import java.awt.BorderLayout;
-import java.awt.Dimension;
-import java.awt.event.ComponentAdapter;
-import java.awt.event.ComponentEvent;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTabbedPane;
-import org.qi4j.envisage.event.LinkEvent;
-import org.qi4j.envisage.event.LinkListener;
-import org.qi4j.tools.model.descriptor.ApplicationDetailDescriptor;
-import prefuse.data.Graph;
-
-/**
- * Just a simple wrapper for ApplicationModel Graph Display
- */
-public final class GraphPane
-    extends JPanel
-{
-    private TreeGraphDisplay treeDisplay;
-    private final StackedGraphDisplay stackedDisplay;
-    private final List<GraphDisplay> displays;
-
-    private JTabbedPane tabPane;
-    private final JScrollPane scrollPane;
-
-    public GraphPane()
-    {
-        treeDisplay = new TreeGraphDisplay();
-        stackedDisplay = new StackedGraphDisplay();
-
-        List<GraphDisplay> tmpList = new ArrayList<>( 2 );
-        tmpList.add( treeDisplay );
-        tmpList.add( stackedDisplay );
-        displays = Collections.unmodifiableList( tmpList );
-
-        scrollPane = new JScrollPane();
-        scrollPane.setViewportView( stackedDisplay );
-        int unitInc = 50;
-        scrollPane.getVerticalScrollBar().setUnitIncrement( unitInc );
-        scrollPane.getHorizontalScrollBar().setUnitIncrement( unitInc );
-
-        tabPane = new JTabbedPane();
-        tabPane.add( "Tree", treeDisplay );
-        tabPane.add( "Stacked", scrollPane );
-
-        this.setLayout( new BorderLayout() );
-        add( tabPane, BorderLayout.CENTER );
-
-        treeDisplay.addLinkListener( new LinkListener()
-        {
-            @Override
-            public void activated( LinkEvent evt )
-            {
-                graphItemLinkActivated( evt );
-            }
-        } );
-
-        stackedDisplay.addLinkListener( new LinkListener()
-        {
-            @Override
-            public void activated( LinkEvent evt )
-            {
-                graphItemLinkActivated( evt );
-            }
-        } );
-
-        this.addComponentListener( new ComponentAdapter()
-        {
-            @Override
-            public void componentResized( ComponentEvent evt )
-            {
-                Dimension size = GraphPane.this.getSize();
-                treeDisplay.setSize( size.width, size.height );
-                tabPane.revalidate();
-                tabPane.repaint();
-            }
-        } );
-    }
-
-    public void initQi4J( ApplicationDetailDescriptor descriptor )
-    {
-        Graph graph = GraphBuilder.buildGraph( descriptor );
-        Dimension size = getSize();
-        treeDisplay.setSize( size.width, size.height );
-        treeDisplay.run( graph );
-
-        graph = GraphBuilder.buildGraph( descriptor );
-        stackedDisplay.setSize( size.width, size.height );
-        stackedDisplay.run( graph );
-    }
-
-    public void refresh()
-    {
-        treeDisplay.run();
-        stackedDisplay.run();
-    }
-
-    public List<GraphDisplay> getGraphDisplays()
-    {
-        return displays;
-    }
-
-    public void setSelectedValue( Object obj )
-    {
-        treeDisplay.setSelectedValue( obj );
-        stackedDisplay.setSelectedValue( obj );
-    }
-
-    private void graphItemLinkActivated( LinkEvent evt )
-    {
-        if( evt.getSource().equals( treeDisplay ) )
-        {
-            stackedDisplay.setSelectedValue( evt.getObject() );
-        }
-        else if( evt.getSource().equals( stackedDisplay ) )
-        {
-            treeDisplay.setSelectedValue( evt.getObject() );
-        }
-    }
-
-    /**
-     * Add a listener from the list that's notified each time a change to the selection occurs.
-     *
-     * @param listener the LinkListener to add
-     */
-    public void addLinkListener( LinkListener listener )
-    {
-        treeDisplay.addLinkListener( listener );
-        stackedDisplay.addLinkListener( listener );
-    }
-
-    /**
-     * Remove a listener from the list that's notified each time a change to the selection occurs.
-     *
-     * @param listener the LinkListener to remove
-     */
-    public void removeLinkListener( LinkListener listener )
-    {
-        treeDisplay.removeLinkListener( listener );
-        stackedDisplay.removeLinkListener( listener );
-    }
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/graph/StackedGraphDisplay.java b/tools/envisage/src/main/java/org/qi4j/envisage/graph/StackedGraphDisplay.java
deleted file mode 100644
index 84fe306..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/graph/StackedGraphDisplay.java
+++ /dev/null
@@ -1,580 +0,0 @@
-/*  Copyright 2009 Tonny Kohar.
- *
- * Licensed 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.qi4j.envisage.graph;
-
-import java.awt.Component;
-import java.awt.Container;
-import java.awt.Dimension;
-import java.awt.Font;
-import java.awt.Shape;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseWheelEvent;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.NoninvertibleTransformException;
-import java.awt.geom.Rectangle2D;
-import java.util.Iterator;
-import javax.swing.JViewport;
-import javax.swing.SwingUtilities;
-import org.qi4j.envisage.event.LinkEvent;
-import prefuse.Constants;
-import prefuse.Visualization;
-import prefuse.action.Action;
-import prefuse.action.ActionList;
-import prefuse.action.ItemAction;
-import prefuse.action.RepaintAction;
-import prefuse.action.assignment.ColorAction;
-import prefuse.action.layout.Layout;
-import prefuse.activity.Activity;
-import prefuse.controls.ControlAdapter;
-import prefuse.controls.FocusControl;
-import prefuse.controls.PanControl;
-import prefuse.data.Graph;
-import prefuse.data.Schema;
-import prefuse.data.expression.Predicate;
-import prefuse.data.expression.parser.ExpressionParser;
-import prefuse.data.tuple.TupleSet;
-import prefuse.render.AbstractShapeRenderer;
-import prefuse.render.DefaultRendererFactory;
-import prefuse.render.EdgeRenderer;
-import prefuse.render.LabelRenderer;
-import prefuse.util.ColorLib;
-import prefuse.util.ColorMap;
-import prefuse.util.FontLib;
-import prefuse.util.PrefuseLib;
-import prefuse.visual.DecoratorItem;
-import prefuse.visual.EdgeItem;
-import prefuse.visual.NodeItem;
-import prefuse.visual.VisualItem;
-import prefuse.visual.expression.InGroupPredicate;
-import prefuse.visual.sort.TreeDepthItemSorter;
-
-/* package */ class StackedGraphDisplay
-    extends GraphDisplay
-{
-    /* package */ static final Font FONT = FontLib.getFont( "Tahoma", 12 );
-
-    // create data description of LABELS, setting colors, fonts ahead of time
-    private static final Schema LABEL_SCHEMA = PrefuseLib.getVisualItemSchema();
-
-    static
-    {
-        LABEL_SCHEMA.setDefault( VisualItem.INTERACTIVE, false );
-        LABEL_SCHEMA.setDefault( VisualItem.TEXTCOLOR, ColorLib.rgb( 255, 255, 255 ) );
-        LABEL_SCHEMA.setDefault( VisualItem.FONT, FONT );
-    }
-
-    private static final String LABELS = "labels";
-
-    private static final String LAYOUT_ACTION = "layout";
-    private static final String COLORS_ACTION = "colors";
-    private static final String AUTO_PAN_ACTION = "autoPan";
-
-    private static int OUTLINE_COLOR = ColorLib.rgb( 33, 115, 170 );
-    private static int OUTLINE_FOCUS_COLOR = ColorLib.rgb( 255, 255, 255 );  // alternative color ColorLib.rgb(150,200,200);
-
-    private StackedLayout stackedLayout;
-
-    private Activity activity;
-
-    /* package */ StackedGraphDisplay()
-    {
-        super( new Visualization() );
-
-        setBackground( ColorLib.getColor( 0, 51, 88 ) );
-
-        LabelRenderer labelRenderer = new LabelRenderer( NAME_LABEL );
-        labelRenderer.setVerticalAlignment( Constants.BOTTOM );
-        labelRenderer.setHorizontalAlignment( Constants.LEFT );
-
-        EdgeRenderer usesRenderer = new EdgeRenderer( Constants.EDGE_TYPE_CURVE, Constants.EDGE_ARROW_FORWARD );
-        usesRenderer.setHorizontalAlignment1( Constants.CENTER );
-        usesRenderer.setHorizontalAlignment2( Constants.CENTER );
-        usesRenderer.setVerticalAlignment1( Constants.BOTTOM );
-        usesRenderer.setVerticalAlignment2( Constants.TOP );
-
-        Predicate usesPredicate = (Predicate) ExpressionParser.parse( "ingroup('graph.edges') AND [" + USES_EDGES + "]==true", true );
-
-        // set up the renderers - one for nodes and one for LABELS
-        DefaultRendererFactory rf = new DefaultRendererFactory();
-        rf.add( new InGroupPredicate( GRAPH_NODES ), new NodeRenderer() );
-        rf.add( new InGroupPredicate( LABELS ), labelRenderer );
-        rf.add( usesPredicate, usesRenderer );
-        m_vis.setRendererFactory( rf );
-
-        // border colors
-        ColorAction borderColor = new BorderColorAction( GRAPH_NODES );
-        ColorAction fillColor = new FillColorAction( GRAPH_NODES );
-
-        // uses edge colors
-        ItemAction usesColor = new ColorAction( GRAPH_EDGES, usesPredicate, VisualItem.STROKECOLOR, ColorLib.rgb( 50, 50, 50 ) );
-        ItemAction usesArrow = new ColorAction( GRAPH_EDGES, usesPredicate, VisualItem.FILLCOLOR, ColorLib.rgb( 50, 50, 50 ) );
-
-        // color settings
-        ActionList colors = new ActionList();
-        colors.add( fillColor );
-        colors.add( borderColor );
-        colors.add( usesColor );
-        colors.add( usesArrow );
-        m_vis.putAction( COLORS_ACTION, colors );
-
-        ActionList autoPan = new ActionList();
-        autoPan.add( colors );
-        autoPan.add( new AutoPanAction() );
-        autoPan.add( new RepaintAction() );
-        m_vis.putAction( AUTO_PAN_ACTION, autoPan );
-
-        // create the layout action list
-        stackedLayout = new StackedLayout( GRAPH );
-        ActionList layout = new ActionList();
-        layout.add( stackedLayout );
-        layout.add( new LabelLayout( LABELS ) );
-        layout.add( autoPan );
-        m_vis.putAction( LAYOUT_ACTION, layout );
-
-        // initialize our display
-        Dimension size = new Dimension( 400, 400 );
-        setSize( size );
-        setPreferredSize( size );
-        setItemSorter( new ExtendedTreeDepthItemSorter( true ) );
-        addControlListener( new HoverControl() );
-        addControlListener( new FocusControl( 1, COLORS_ACTION ) );
-        addControlListener( new WheelMouseControl() );
-        addControlListener( new PanControl( true ) );
-        addControlListener( new ItemSelectionControl() );
-
-        setDamageRedraw( true );
-    }
-
-    @Override
-    public void run( Graph graph )
-    {
-        // add the GRAPH to the visualization
-        m_vis.add( GRAPH, graph );
-
-        // hide edges
-        Predicate edgesPredicate = (Predicate) ExpressionParser.parse( "ingroup('graph.edges') AND [" + USES_EDGES + "]==false", true );
-        m_vis.setVisible( GRAPH_EDGES, edgesPredicate, false );
-
-        m_vis.setInteractive( GRAPH_EDGES, null, false );
-
-        // make node interactive
-        m_vis.setInteractive( GRAPH_NODES, null, true );
-
-        // add LABELS to the visualization
-        Predicate labelP = (Predicate) ExpressionParser.parse( "VISIBLE()" );
-        m_vis.addDecorators( LABELS, GRAPH_NODES, labelP, LABEL_SCHEMA );
-
-        run();
-    }
-
-    @Override
-    public void run()
-    {
-        if( isInProgress() )
-        {
-            return;
-        }
-
-        // perform layout
-        m_vis.invalidate( GRAPH_NODES );
-        activity = m_vis.run( LAYOUT_ACTION );
-    }
-
-    @Override
-    public void setSelectedValue( Object object )
-    {
-        if( object == null )
-        {
-            return;
-        }
-
-        NodeItem item = null;
-
-        Iterator iter = m_vis.items( GRAPH_NODES );
-        while( iter.hasNext() )
-        {
-            NodeItem tItem = (NodeItem) iter.next();
-            Object tObj = tItem.get( USER_OBJECT );
-            if( tObj.equals( object ) )
-            {
-                item = tItem;
-                break;
-            }
-        }
-
-        if( item != null )
-        {
-            int depth = item.getDepth();
-            boolean relayout = false;
-            if( depth > stackedLayout.getZoom() )
-            {
-                stackedLayout.zoom( depth );
-                relayout = true;
-            }
-
-            TupleSet ts = m_vis.getFocusGroup( Visualization.FOCUS_ITEMS );
-            ts.setTuple( item );
-            if( relayout )
-            {
-                run();
-            }
-            else
-            {
-                m_vis.run( AUTO_PAN_ACTION );
-            }
-        }
-    }
-
-    private void zoomIn()
-    {
-        if( isInProgress() )
-        {
-            return;
-        }
-
-        stackedLayout.zoomIn();
-        run();
-    }
-
-    private void zoomOut()
-    {
-        if( isInProgress() )
-        {
-            return;
-        }
-
-        stackedLayout.zoomOut();
-        run();
-    }
-
-    private boolean isInProgress()
-    {
-        if( isTranformInProgress() )
-        {
-            return true;
-        }
-
-        if( activity != null )
-        {
-            if( activity.isRunning() )
-            {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    // ------------------------------------------------------------------------
-    /**
-     * Set the stroke color for drawing border node outlines.
-     */
-    private static class BorderColorAction
-        extends ColorAction
-    {
-
-        private BorderColorAction( String group )
-        {
-            super( group, VisualItem.STROKECOLOR );
-        }
-
-        @Override
-        public int getColor( VisualItem item )
-        {
-            if( !( item instanceof NodeItem ) )
-            {
-                return 0;
-            }
-            NodeItem nItem = (NodeItem) item;
-            if( m_vis.isInGroup( nItem, Visualization.FOCUS_ITEMS ) )
-            {
-                return OUTLINE_FOCUS_COLOR;
-            }
-
-            return OUTLINE_COLOR;
-        }
-    }
-
-    /**
-     * Set fill colors for treemap nodes. Normal nodes are shaded according to their
-     * depth in the tree.
-     */
-    private static class FillColorAction
-        extends ColorAction
-    {
-        private static final ColorMap CMAP = new ColorMap( new int[]
-        {
-            ColorLib.rgb( 11, 117, 188 ),
-            ColorLib.rgb( 8, 99, 160 ),
-            ColorLib.rgb( 5, 77, 126 ),
-            ColorLib.rgb( 2, 61, 100 ),
-            ColorLib.rgb( 148, 55, 87 )
-        }, 0, 4 );
-
-        private FillColorAction( String group )
-        {
-            super( group, VisualItem.FILLCOLOR );
-        }
-
-        @Override
-        public int getColor( VisualItem item )
-        {
-            if( item instanceof NodeItem )
-            {
-                NodeItem nItem = (NodeItem) item;
-                if( m_vis.isInGroup( nItem, Visualization.FOCUS_ITEMS ) )
-                {
-                    int c = CMAP.getColor( nItem.getDepth() );
-                    return ColorLib.darker( c );
-                }
-                return CMAP.getColor( nItem.getDepth() );
-            }
-            else
-            {
-                return CMAP.getColor( 0 );
-            }
-        }
-    } // end of inner class FillColorAction
-
-    private static class HoverControl
-        extends ControlAdapter
-    {
-        @Override
-        public void itemEntered( VisualItem item, MouseEvent evt )
-        {
-            item.setStrokeColor( OUTLINE_FOCUS_COLOR );
-            item.getVisualization().repaint();
-        }
-
-        @Override
-        public void itemExited( VisualItem item, MouseEvent evt )
-        {
-            item.setStrokeColor( item.getEndStrokeColor() );
-            item.getVisualization().repaint();
-        }
-    }
-
-    /**
-     * Set label positions. Labels are assumed to be DecoratorItem instances,
-     * decorating their respective nodes. The layout simply gets the bounds
-     * of the decorated node and assigns the label coordinates to the center
-     * of those bounds.
-     */
-    private static class LabelLayout
-        extends Layout
-    {
-        private LabelLayout( String group )
-        {
-            super( group );
-        }
-
-        @Override
-        public void run( double frac )
-        {
-            Iterator iter = m_vis.items( m_group );
-            while( iter.hasNext() )
-            {
-                DecoratorItem item = (DecoratorItem) iter.next();
-                VisualItem node = item.getDecoratedItem();
-                Rectangle2D bounds = node.getBounds();
-                setX( item, node, bounds.getX() + StackedLayout.INSET );
-                setY( item, node, bounds.getY() + StackedLayout.INSET + 12 );
-            }
-        }
-    } // end of inner class LabelLayout
-
-    /**
-     * A renderer for treemap nodes. Draws simple rectangles, but defers
-     * the bounds management to the layout.
-     */
-    private static class NodeRenderer
-        extends AbstractShapeRenderer
-    {
-        private Rectangle2D m_bounds = new Rectangle2D.Double();
-
-        private NodeRenderer()
-        {
-            m_manageBounds = false;
-        }
-
-        @Override
-        protected Shape getRawShape( VisualItem item )
-        {
-            m_bounds.setRect( item.getBounds() );
-            return m_bounds;
-        }
-    } // end of inner class NodeRenderer
-
-    private class WheelMouseControl
-        extends ControlAdapter
-    {
-        @Override
-        public void itemWheelMoved( VisualItem item, MouseWheelEvent evt )
-        {
-            zoom( evt.getWheelRotation() );
-        }
-
-        @Override
-        public void mouseWheelMoved( MouseWheelEvent evt )
-        {
-            zoom( evt.getWheelRotation() );
-        }
-
-        private void zoom( final int rotation )
-        {
-            SwingUtilities.invokeLater( new Runnable()
-            {
-                @Override
-                public void run()
-                {
-                    if( rotation == 0 )
-                    {
-                        return;
-                    }
-                    if( rotation < 0 )
-                    {
-                        zoomOut();
-                    }
-                    else
-                    {
-                        zoomIn();
-                    }
-                }
-            } );
-        }
-    }
-
-    private class ItemSelectionControl
-        extends ControlAdapter
-    {
-        @Override
-        public final void itemClicked( VisualItem anItem, MouseEvent anEvent )
-        {
-            // update the display
-            anItem.getVisualization().repaint();
-
-            if( !anItem.canGet( USER_OBJECT, Object.class ) )
-            {
-                return;
-            }
-
-            Object object = anItem.get( USER_OBJECT );
-            LinkEvent evt = new LinkEvent( StackedGraphDisplay.this, object );
-            fireLinkActivated( evt );
-        }
-    }
-
-    private class AutoPanAction
-        extends Action
-    {
-        @Override
-        public void run( double frac )
-        {
-            Rectangle2D displayBounds = new Rectangle2D.Double( 0, 0, getWidth(), getHeight() );
-
-            Container container = getParent();
-            if( container == null )
-            {
-                return;
-            }
-
-            // HACK check the container size
-            if( container instanceof JViewport )
-            {
-                Dimension size = ( (JViewport) container ).getExtentSize();
-                displayBounds.setRect( 0, 0, size.getWidth(), size.getHeight() );
-            }
-            else
-            {
-                Dimension size = ( (Component) container ).getSize();
-                displayBounds.setRect( 0, 0, size.getWidth(), size.getHeight() );
-            }
-
-            Rectangle2D bounds = stackedLayout.getLayoutRoot().getBounds();
-
-            // Pan center
-            double x = ( displayBounds.getWidth() - bounds.getWidth() ) / 2;
-            double y = ( displayBounds.getHeight() - bounds.getHeight() ) / 2;
-
-            // reset the transform
-            try
-            {
-                setTransform( new AffineTransform() );
-            }
-            catch( NoninvertibleTransformException ex )
-            {
-                return;
-            }
-            if( x < 0 )
-            {
-                x = 0;
-            }
-
-            if( y < 0 )
-            {
-                y = 0;
-            }
-            pan( x, y );
-
-            TupleSet ts = m_vis.getFocusGroup( Visualization.FOCUS_ITEMS );
-            if( ts.getTupleCount() != 0 )
-            {
-                // get the first selected item and pan center it
-                VisualItem vi = (VisualItem) ts.tuples().next();
-
-                //update scrollbar position
-                if( container instanceof JViewport )
-                {
-                    // TODO there is a bug on Swing scrollRectToVisible
-                    ( (JViewport) container ).scrollRectToVisible( vi.getBounds().getBounds() );
-                }
-            }
-        }
-    }
-
-    /**
-     * ExtenedTreeDepthItemSorter to alter the default ordering/sorter,
-     * to make sure Edge item is drawn in front. This is for Edge Uses
-     */
-    private static class ExtendedTreeDepthItemSorter
-        extends TreeDepthItemSorter
-    {
-        private ExtendedTreeDepthItemSorter()
-        {
-            this( false );
-        }
-
-        private ExtendedTreeDepthItemSorter( boolean childrenAbove )
-        {
-            super( childrenAbove );
-        }
-
-        @Override
-        public int score( VisualItem item )
-        {
-            int score = super.score( item );
-            if( item instanceof EdgeItem )
-            {
-                // make it drawn in front of NODE
-                score = ( 1 << ( 25 + EDGE + NODE ) );
-            }
-
-            return score;
-        }
-    }
-
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/graph/StackedLayout.java b/tools/envisage/src/main/java/org/qi4j/envisage/graph/StackedLayout.java
deleted file mode 100644
index 959f050..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/graph/StackedLayout.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.graph;
-
-import java.awt.Dimension;
-import java.awt.FontMetrics;
-import java.awt.geom.Area;
-import java.awt.geom.Rectangle2D;
-import prefuse.Display;
-import prefuse.action.layout.graph.TreeLayout;
-import prefuse.render.Renderer;
-import prefuse.visual.NodeItem;
-
-/* package */ final class StackedLayout
-    extends TreeLayout
-{
-    /* package */ static int INSET = 10;
-
-    private int zoom = 2;
-
-    /* package */ StackedLayout( String group )
-    {
-        super( group );
-    }
-
-    @Override
-    public void run( double frac )
-    {
-        // setup
-        NodeItem root = getLayoutRoot();
-        layout( root, 0, 0 );
-
-        Rectangle2D bounds = root.getBounds();
-        Display display = this.getVisualization().getDisplay( 0 );
-        Dimension size = new Dimension( (int) bounds.getWidth(), (int) bounds.getHeight() );
-        display.setSize( size );
-
-        if( !display.isValid() )
-        {
-            display.validate();
-        }
-    }
-
-    /* package */ void zoomOut()
-    {
-        zoom--;
-        if( zoom < 1 )
-        {
-            zoom = 1;
-        }
-    }
-
-    /* package */ void zoomIn()
-    {
-        zoom++;
-        if( zoom > 4 )
-        {
-            zoom = 4;
-        }
-    }
-
-    /* package */ void zoom( int zoom )
-    {
-        this.zoom = zoom;
-    }
-
-    /* package */ int getZoom()
-    {
-        return zoom;
-    }
-
-    private Dimension getItemMinSize( NodeItem node, Dimension minSize )
-    {
-        if( minSize == null )
-        {
-            minSize = new Dimension( 0, 0 );
-        }
-
-        String label = node.getString( "name" );
-        FontMetrics fm = Renderer.DEFAULT_GRAPHICS.getFontMetrics( StackedGraphDisplay.FONT );
-        int width = fm.stringWidth( label );
-        int height = fm.getHeight();
-        minSize.setSize( width + INSET + INSET, height + INSET + INSET );
-
-        return minSize;
-    }
-
-    private void layout( NodeItem node, double x, double y )
-    {
-        Dimension minSize = getItemMinSize( node, null );
-        node.setBounds( x, y, minSize.width, minSize.height );
-
-        int depth = node.getDepth();
-
-        if( depth > zoom )
-        {
-            node.setBounds( x, y, 0, 0 );
-            node.setVisible( false );
-        }
-        else
-        {
-            node.setVisible( true );
-        }
-
-        double cx = x + INSET;
-        double cy = y + minSize.height;
-
-        Area area = new Area( node.getBounds() );
-
-        boolean hasChild = false;
-        for( int i = 0; i < node.getChildCount(); i++ )
-        {
-            hasChild = true;
-            NodeItem child = (NodeItem) node.getChild( i );
-
-            layout( child, cx, cy );
-            area.add( new Area( child.getBounds() ) );
-
-            // shifting location calculation
-            Rectangle2D nodeRect = child.getBounds();
-            if( depth == 0 )
-            {
-                // layer
-                cy = cy + ( INSET * 2 ) + nodeRect.getHeight();
-            }
-            if( depth == 1 )
-            {
-                // module
-                cx = cx + INSET + nodeRect.getWidth();
-            }
-            else if( depth == 2 )
-            {
-                // type container
-                cx = cx + INSET + nodeRect.getWidth();
-            }
-            else if( depth == 3 )
-            {
-                // type
-                cy = cy + INSET + nodeRect.getHeight();
-            }
-        }
-
-        Rectangle2D bounds = area.getBounds2D();
-        if( hasChild && depth <= zoom )
-        {
-            bounds.setRect( x, y, bounds.getWidth() + INSET, bounds.getHeight() + INSET );
-        }
-
-        node.setBounds( x, y, bounds.getWidth(), bounds.getHeight() );
-
-        // relayout the child so it have consistent width or height
-        //int depth = parent.getDepth();
-        if( depth == 0 )
-        {
-            arrangeChildVertically( node );
-        }
-        else if( depth == 1 )
-        {
-            arrangeChildHorizontally( node );
-        }
-        else if( depth == 2 )
-        {
-            arrangeChildHorizontally( node );
-        }
-        else if( depth == 3 )
-        {
-            arrangeChildVertically( node );
-        }
-    }
-
-    private void arrangeChildVertically( NodeItem parent )
-    {
-        double maxW = 0;
-        for( int i = 0; i < parent.getChildCount(); i++ )
-        {
-            NodeItem node = (NodeItem) parent.getChild( i );
-            Rectangle2D bounds = node.getBounds();
-            maxW = Math.max( maxW, bounds.getWidth() );
-        }
-
-        for( int i = 0; i < parent.getChildCount(); i++ )
-        {
-            NodeItem node = (NodeItem) parent.getChild( i );
-            Rectangle2D bounds = node.getBounds();
-            node.setBounds( bounds.getX(), bounds.getY(), maxW, bounds.getHeight() );
-        }
-    }
-
-    private void arrangeChildHorizontally( NodeItem parent )
-    {
-        double maxH = 0;
-        for( int i = 0; i < parent.getChildCount(); i++ )
-        {
-            NodeItem node = (NodeItem) parent.getChild( i );
-            Rectangle2D bounds = node.getBounds();
-            maxH = Math.max( maxH, bounds.getHeight() );
-        }
-
-        for( int i = 0; i < parent.getChildCount(); i++ )
-        {
-            NodeItem node = (NodeItem) parent.getChild( i );
-            Rectangle2D bounds = node.getBounds();
-            node.setBounds( bounds.getX(), bounds.getY(), bounds.getWidth(), maxH );
-        }
-    }
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/graph/TreeGraphDisplay.java b/tools/envisage/src/main/java/org/qi4j/envisage/graph/TreeGraphDisplay.java
deleted file mode 100644
index ff7fff9..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/graph/TreeGraphDisplay.java
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.graph;
-
-import java.awt.Color;
-import java.awt.event.MouseEvent;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.util.Iterator;
-import org.qi4j.envisage.event.LinkEvent;
-import prefuse.Constants;
-import prefuse.Visualization;
-import prefuse.action.Action;
-import prefuse.action.ActionList;
-import prefuse.action.ItemAction;
-import prefuse.action.RepaintAction;
-import prefuse.action.animate.ColorAnimator;
-import prefuse.action.animate.LocationAnimator;
-import prefuse.action.animate.QualityControlAnimator;
-import prefuse.action.animate.VisibilityAnimator;
-import prefuse.action.assignment.ColorAction;
-import prefuse.action.assignment.FontAction;
-import prefuse.action.filter.FisheyeTreeFilter;
-import prefuse.action.layout.CollapsedSubtreeLayout;
-import prefuse.action.layout.graph.NodeLinkTreeLayout;
-import prefuse.activity.SlowInSlowOutPacer;
-import prefuse.controls.ControlAdapter;
-import prefuse.controls.FocusControl;
-import prefuse.controls.PanControl;
-import prefuse.controls.WheelZoomControl;
-import prefuse.controls.ZoomControl;
-import prefuse.controls.ZoomToFitControl;
-import prefuse.data.Graph;
-import prefuse.data.expression.Predicate;
-import prefuse.data.expression.parser.ExpressionParser;
-import prefuse.data.tuple.TupleSet;
-import prefuse.render.AbstractShapeRenderer;
-import prefuse.render.DefaultRendererFactory;
-import prefuse.render.EdgeRenderer;
-import prefuse.render.LabelRenderer;
-import prefuse.util.ColorLib;
-import prefuse.util.FontLib;
-import prefuse.util.GraphicsLib;
-import prefuse.util.PrefuseLib;
-import prefuse.util.display.DisplayLib;
-import prefuse.visual.VisualItem;
-import prefuse.visual.sort.TreeDepthItemSorter;
-
-public final class TreeGraphDisplay
-    extends GraphDisplay
-{
-
-    static final String FILTER_ACTION = "filter";
-    static final String REPAINT_ACTION = "repaint";
-    static final String FULL_PAINT_ACTION = "fullPaint";
-    static final String ANIMATE_PAINT_ACTION = "animatePaint";
-    static final String ANIMATE_ACTION = "animate";
-    static final String LAYOUT_ACTION = "layout";
-    static final String SUB_LAYOUT_ACTION = "subLayout";
-    static final String AUTO_ZOOM_ACTION = "autoZoom";
-
-    private final LabelRenderer nodeRenderer;
-    private final EdgeRenderer edgeRenderer;
-    private final EdgeRenderer usesRenderer;
-
-    private final int orientation = Constants.ORIENT_LEFT_RIGHT;
-
-    public TreeGraphDisplay()
-    {
-        super( new Visualization() );
-
-        Color BACKGROUND = Color.WHITE;
-        Color FOREGROUND = Color.BLACK;
-
-        setBackground( BACKGROUND );
-        setForeground( FOREGROUND );
-
-        nodeRenderer = new LabelRenderer( NAME_LABEL );
-        nodeRenderer.setRenderType( AbstractShapeRenderer.RENDER_TYPE_FILL );
-        nodeRenderer.setHorizontalAlignment( Constants.LEFT );
-        nodeRenderer.setRoundedCorner( 8, 8 );
-        edgeRenderer = new EdgeRenderer( Constants.EDGE_TYPE_CURVE );
-        usesRenderer = new EdgeRenderer( Constants.EDGE_TYPE_CURVE, Constants.EDGE_ARROW_FORWARD );
-
-        Predicate edgesPredicate = (Predicate) ExpressionParser.parse( "ingroup('graph.edges') AND [" + USES_EDGES + "]==false", true );
-        Predicate usesPredicate = (Predicate) ExpressionParser.parse( "ingroup('graph.edges') AND [" + USES_EDGES + "]==true", true );
-
-        DefaultRendererFactory rf = new DefaultRendererFactory( nodeRenderer );
-        rf.add( edgesPredicate, edgeRenderer );
-        rf.add( usesPredicate, usesRenderer );
-        m_vis.setRendererFactory( rf );
-
-        // colors
-        ItemAction nodeColor = new NodeColorAction( GRAPH_NODES );
-        ItemAction textColor = new ColorAction( GRAPH_NODES, VisualItem.TEXTCOLOR, ColorLib.rgb( 0, 0, 0 ) );
-        m_vis.putAction( "textColor", textColor );
-
-        ItemAction edgeColor = new ColorAction( GRAPH_EDGES, edgesPredicate, VisualItem.STROKECOLOR, ColorLib.rgb( 200, 200, 200 ) );
-        ItemAction usesColor = new ColorAction( GRAPH_EDGES, usesPredicate, VisualItem.STROKECOLOR, ColorLib.rgb( 255, 100, 100 ) );
-        ItemAction usesArrow = new ColorAction( GRAPH_EDGES, usesPredicate, VisualItem.FILLCOLOR, ColorLib.rgb( 255, 100, 100 ) );
-
-        // quick repaint
-        ActionList repaint = new ActionList();
-        repaint.add( nodeColor );
-        repaint.add( new RepaintAction() );
-        m_vis.putAction( REPAINT_ACTION, repaint );
-
-        // full paint
-        ActionList fullPaint = new ActionList();
-        fullPaint.add( nodeColor );
-        m_vis.putAction( FULL_PAINT_ACTION, fullPaint );
-
-        // animate paint change
-        //ActionList animatePaint = new ActionList( 0 );
-        ActionList animatePaint = new ActionList();
-        animatePaint.add( new ColorAnimator( GRAPH_NODES ) );
-        animatePaint.add( new RepaintAction() );
-        m_vis.putAction( ANIMATE_PAINT_ACTION, animatePaint );
-
-        // create the GRAPH layout action
-        NodeLinkTreeLayout treeLayout = new NodeLinkTreeLayout( GRAPH, orientation, 40, 0, 8 );
-        treeLayout.setLayoutAnchor( new Point2D.Double( 25, 300 ) );
-        m_vis.putAction( LAYOUT_ACTION, treeLayout );
-
-        CollapsedSubtreeLayout subLayout = new CollapsedSubtreeLayout( GRAPH, orientation );
-        m_vis.putAction( SUB_LAYOUT_ACTION, subLayout );
-
-        // create the filtering and layout
-        ActionList filter = new ActionList();
-        filter.add( new ExtendedFisheyeTreeFilter( GRAPH, 2 ) );
-        filter.add( new FontAction( GRAPH_NODES, FontLib.getFont( "Tahoma", 14 ) ) );
-        filter.add( treeLayout );
-        filter.add( subLayout );
-        filter.add( textColor );
-        filter.add( nodeColor );
-        filter.add( edgeColor );
-        filter.add( usesColor );
-        filter.add( usesArrow );
-        m_vis.putAction( FILTER_ACTION, filter );
-
-        // animated transition
-        AutoPanAction autoPan = new AutoPanAction();
-        ActionList animate = new ActionList( 750 );
-        animate.setPacingFunction( new SlowInSlowOutPacer() );
-        animate.add( autoPan );
-        animate.add( new QualityControlAnimator() );
-        animate.add( new VisibilityAnimator( GRAPH ) );
-        animate.add( new LocationAnimator( GRAPH_NODES ) );
-        animate.add( new ColorAnimator( GRAPH_NODES ) );
-        animate.add( new RepaintAction() );
-        m_vis.putAction( ANIMATE_ACTION, animate );
-        m_vis.alwaysRunAfter( FILTER_ACTION, ANIMATE_ACTION );
-
-        m_vis.putAction( AUTO_ZOOM_ACTION, new AutoZoomAction() );
-
-        // initialize the display
-        setItemSorter( new TreeDepthItemSorter() );
-        addControlListener( new ZoomToFitControl() );
-        addControlListener( new ZoomControl() );
-        addControlListener( new WheelZoomControl() );
-        addControlListener( new PanControl() );
-        addControlListener( new FocusControl( 1, FILTER_ACTION ) );
-        addControlListener( new ItemSelectionControl() );
-
-        // set orientation
-        nodeRenderer.setHorizontalAlignment( Constants.LEFT );
-        edgeRenderer.setHorizontalAlignment1( Constants.RIGHT );
-        edgeRenderer.setHorizontalAlignment2( Constants.LEFT );
-        edgeRenderer.setVerticalAlignment1( Constants.CENTER );
-        edgeRenderer.setVerticalAlignment2( Constants.CENTER );
-        usesRenderer.setHorizontalAlignment1( Constants.CENTER );
-        usesRenderer.setHorizontalAlignment2( Constants.CENTER );
-        usesRenderer.setVerticalAlignment1( Constants.BOTTOM );
-        usesRenderer.setVerticalAlignment2( Constants.CENTER );
-        NodeLinkTreeLayout rtl = (NodeLinkTreeLayout) m_vis.getAction( LAYOUT_ACTION );
-        CollapsedSubtreeLayout stl = (CollapsedSubtreeLayout) m_vis.getAction( SUB_LAYOUT_ACTION );
-        rtl.setOrientation( orientation );
-        stl.setOrientation( orientation );
-    }
-
-    @Override
-    public void run( Graph graph )
-    {
-        m_vis.add( GRAPH, graph );
-        run();
-        m_vis.run( AUTO_ZOOM_ACTION );
-
-        // disable edges interactive
-        m_vis.setInteractive( GRAPH_EDGES, null, false );
-    }
-
-    @Override
-    public void run()
-    {
-        m_vis.run( FILTER_ACTION );
-    }
-
-    /**
-     * select the specified object
-     *
-     * @param object the object to select eg: Descriptor
-     */
-    @Override
-    public void setSelectedValue( Object object )
-    {
-        if( object == null )
-        {
-            return;
-        }
-
-        VisualItem item = null;
-
-        Iterator iter = m_vis.items( GRAPH_NODES );
-        while( iter.hasNext() )
-        {
-            VisualItem tItem = (VisualItem) iter.next();
-            Object tObj = tItem.get( USER_OBJECT );
-            if( tObj.equals( object ) )
-            {
-                item = tItem;
-                break;
-            }
-        }
-
-        if( item != null )
-        {
-            TupleSet ts = m_vis.getFocusGroup( Visualization.FOCUS_ITEMS );
-            ts.setTuple( item );
-            m_vis.run( FILTER_ACTION );
-        }
-    }
-
-    private class AutoZoomAction
-        extends Action
-    {
-        @Override
-        public void run( double frac )
-        {
-            int duration = 20;
-            int margin = 50;
-            Visualization vis = getVisualization();
-            Rectangle2D bounds = vis.getBounds( Visualization.ALL_ITEMS );
-            GraphicsLib.expand( bounds, margin + (int) ( 1 / getScale() ) );
-            DisplayLib.fitViewToBounds( TreeGraphDisplay.this, bounds, duration );
-        }
-    }
-
-    private class AutoPanAction
-        extends Action
-    {
-        private final Point2D m_start = new Point2D.Double();
-        private final Point2D m_end = new Point2D.Double();
-        private final Point2D m_cur = new Point2D.Double();
-        private final int m_bias = 150;
-
-        @Override
-        public void run( double frac )
-        {
-            TupleSet ts = m_vis.getFocusGroup( Visualization.FOCUS_ITEMS );
-            if( ts.getTupleCount() == 0 )
-            {
-                return;
-            }
-
-            if( frac == 0.0 )
-            {
-                int xbias, ybias = 0;
-
-                xbias = m_bias;
-                switch( orientation )
-                {
-                    case Constants.ORIENT_LEFT_RIGHT:
-
-                        break;
-                    case Constants.ORIENT_RIGHT_LEFT:
-                        xbias = -m_bias;
-                        break;
-                    case Constants.ORIENT_TOP_BOTTOM:
-                        ybias = m_bias;
-                        break;
-                    case Constants.ORIENT_BOTTOM_TOP:
-                        ybias = -m_bias;
-                        break;
-                }
-
-                VisualItem vi = (VisualItem) ts.tuples().next();
-                m_cur.setLocation( getWidth() / 2, getHeight() / 2 );
-                getAbsoluteCoordinate( m_cur, m_start );
-                m_end.setLocation( vi.getX() + xbias, vi.getY() + ybias );
-            }
-            else
-            {
-                m_cur.setLocation( m_start.getX() + frac * ( m_end.getX() - m_start.getX() ),
-                                   m_start.getY() + frac * ( m_end.getY() - m_start.getY() ) );
-                panToAbs( m_cur );
-            }
-        }
-    }
-
-    private static class NodeColorAction
-        extends ColorAction
-    {
-
-        private NodeColorAction( String group )
-        {
-            super( group, VisualItem.FILLCOLOR );
-        }
-
-        @Override
-        public int getColor( VisualItem item )
-        {
-            if( m_vis.isInGroup( item, Visualization.SEARCH_ITEMS ) )
-            {
-                return ColorLib.rgb( 255, 190, 190 );
-            }
-            else if( m_vis.isInGroup( item, Visualization.FOCUS_ITEMS ) )
-            {
-                return ColorLib.rgb( 198, 229, 229 );
-            }
-            else if( item.getDOI() > -1 )
-            {
-                return ColorLib.rgb( 164, 193, 193 );
-            }
-            else
-            {
-                return ColorLib.rgba( 255, 255, 255, 0 );
-            }
-        }
-    }
-
-    private class ItemSelectionControl
-        extends ControlAdapter
-    {
-        @Override
-        public final void itemClicked( VisualItem anItem, MouseEvent anEvent )
-        {
-            if( !anItem.canGet( USER_OBJECT, Object.class ) )
-            {
-                return;
-            }
-            Object object = anItem.get( USER_OBJECT );
-            LinkEvent evt = new LinkEvent( TreeGraphDisplay.this, object );
-            fireLinkActivated( evt );
-        }
-    }
-
-    private static class ExtendedFisheyeTreeFilter
-        extends FisheyeTreeFilter
-    {
-        private ExtendedFisheyeTreeFilter( String group, int distance )
-        {
-            super( group, distance );
-        }
-
-        @Override
-        public void run( double frac )
-        {
-            super.run( frac );
-
-            // set uses_edges always visible
-            Iterator items = m_vis.items( GRAPH_EDGES );
-            while( items.hasNext() )
-            {
-                VisualItem item = (VisualItem) items.next();
-                if( item.getBoolean( USES_EDGES ) )
-                {
-                    PrefuseLib.updateVisible( item, true );
-                }
-            }
-        }
-    }
-
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/graph/package.html b/tools/envisage/src/main/java/org/qi4j/envisage/graph/package.html
deleted file mode 100644
index becdd99..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/graph/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Envisage Tool Graph Visualization.</h2>
-    </body>
-</html>
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/package.html b/tools/envisage/src/main/java/org/qi4j/envisage/package.html
deleted file mode 100644
index be039d1..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Envisage Tool.</h2>
-    </body>
-</html>
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/print/PDFWriter.java b/tools/envisage/src/main/java/org/qi4j/envisage/print/PDFWriter.java
deleted file mode 100644
index 59e0d55..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/print/PDFWriter.java
+++ /dev/null
@@ -1,825 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.print;
-
-import java.awt.Component;
-import java.awt.image.BufferedImage;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.lang.reflect.WildcardType;
-import java.util.HashSet;
-import java.util.List;
-import javax.imageio.ImageIO;
-import javax.swing.JFileChooser;
-import javax.swing.filechooser.FileFilter;
-import org.apache.pdfbox.exceptions.COSVisitorException;
-import org.apache.pdfbox.pdmodel.PDDocument;
-import org.apache.pdfbox.pdmodel.PDPage;
-import org.apache.pdfbox.pdmodel.common.PDRectangle;
-import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
-import org.apache.pdfbox.pdmodel.font.PDFont;
-import org.apache.pdfbox.pdmodel.font.PDType1Font;
-import org.apache.pdfbox.pdmodel.graphics.xobject.PDJpeg;
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.composite.DependencyDescriptor;
-import org.qi4j.api.composite.ModelDescriptor;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.object.ObjectDescriptor;
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.envisage.graph.GraphDisplay;
-import org.qi4j.envisage.util.TableRow;
-import org.qi4j.envisage.util.TableRowUtilities;
-import org.qi4j.tools.model.descriptor.*;
-import org.qi4j.tools.model.util.DescriptorUtilities;
-
-public class PDFWriter
-{
-    protected PDDocument doc = null;
-    protected PDPageContentStream curContentStream = null;
-    protected PDRectangle curPageSize;
-    protected float curY;
-    protected PDFont curFont;
-    protected float curFontSize;
-
-    protected String APPLICATION = "Application";
-    protected String LAYER = "Layer";
-    protected String MODULE = "Module";
-
-    protected PDFont normalFont = PDType1Font.HELVETICA;
-    protected PDFont header1Font = PDType1Font.HELVETICA_BOLD;  // Application
-    protected PDFont header2Font = PDType1Font.HELVETICA_BOLD;  // Layer
-    protected PDFont header3Font = PDType1Font.HELVETICA_BOLD; // Module
-    protected PDFont header4Font = PDType1Font.HELVETICA_BOLD; // Type Container
-    protected PDFont header5Font = PDType1Font.HELVETICA_BOLD_OBLIQUE; // Type
-    protected float normalFontSize = 10;
-    protected float header1FontSize = 18;
-    protected float header2FontSize = 16;
-    protected float header3FontSize = 14;
-    protected float header4FontSize = 12;
-    protected float header5FontSize = 12;
-
-    protected float startX = 40;
-    protected float startY = 40;
-    protected float lineSpace = 15;
-    protected float headerLineSpace = 25;
-
-    public void write( Component parent, ApplicationDetailDescriptor descriptor, List<GraphDisplay> graphDisplays )
-    {
-        JFileChooser fc = new JFileChooser();
-        PDFFileFilter pdfFileFilter = new PDFFileFilter();
-        fc.setFileFilter( pdfFileFilter );
-
-        int choice = fc.showSaveDialog( parent );
-        if( choice != JFileChooser.APPROVE_OPTION )
-        {
-            return;
-        }
-
-        File file = fc.getSelectedFile();
-        String filename = file.toString();
-        String ext = ".pdf";
-        if( !filename.endsWith( ext ) )
-        {
-            filename = filename + ext;
-            file = new File( filename );
-        }
-
-        write( file, descriptor, graphDisplays );
-    }
-
-    public void write( File file, ApplicationDetailDescriptor descriptor, List<GraphDisplay> graphDisplays )
-    {
-        try
-        {
-            writeImpl( file, descriptor, graphDisplays );
-        }
-        catch( IOException | COSVisitorException ex )
-        {
-            ex.printStackTrace();
-        }
-    }
-
-    protected void writeImpl( File file, ApplicationDetailDescriptor descriptor, List<GraphDisplay> graphDisplays )
-        throws IOException, COSVisitorException
-    {
-        try
-        {
-            doc = new PDDocument();
-            for( GraphDisplay graphDisplay : graphDisplays )
-            {
-                writeGraphPage( graphDisplay );
-            }
-            writePage( descriptor );
-            if( curContentStream != null )
-            {
-                curContentStream.close();
-                curContentStream = null;
-            }
-            doc.save( new FileOutputStream( file ) );
-        }
-        finally
-        {
-            if( curContentStream != null )
-            {
-                curContentStream.close();
-                curContentStream = null;
-            }
-
-            if( doc != null )
-            {
-                doc.close();
-                doc = null;
-            }
-        }
-    }
-
-    private void writeGraphPage( GraphDisplay graphDisplay )
-        throws IOException
-    {
-        File tFile = File.createTempFile( "envisage", "png" );
-        graphDisplay.saveImage( new FileOutputStream( tFile ), "png", 1d );
-
-        BufferedImage img = ImageIO.read( tFile );
-
-        int w = img.getWidth();
-        int h = img.getHeight();
-
-        int inset = 40;
-        PDRectangle pdRect = new PDRectangle( w + inset, h + inset );
-        PDPage page = new PDPage();
-        page.setMediaBox( pdRect );
-        doc.addPage( page );
-
-        PDJpeg xImage = new PDJpeg( doc, img );
-
-        PDPageContentStream contentStream = new PDPageContentStream( doc, page );
-        contentStream.drawImage( xImage, ( pdRect.getWidth() - w ) / 2, ( pdRect.getHeight() - h ) / 2 );
-        contentStream.close();
-    }
-
-    private void writePage( ApplicationDetailDescriptor descriptor )
-    {
-        createNewPage();
-        setFont( header1Font, header1FontSize );
-        writeString( APPLICATION + " : " + descriptor.toString() );
-
-        writeLayersPage( descriptor.layers() );
-    }
-
-    private void writeLayersPage( Iterable<LayerDetailDescriptor> iter )
-    {
-        for( LayerDetailDescriptor descriptor : iter )
-        {
-            setFont( header2Font, header2FontSize );
-            writeString( LAYER + " : " + descriptor.toString(), headerLineSpace );
-
-            writeModulesPage( descriptor.modules() );
-        }
-    }
-
-    private void writeModulesPage( Iterable<ModuleDetailDescriptor> iter )
-    {
-        for( ModuleDetailDescriptor descriptor : iter )
-        {
-            setFont( header3Font, header3FontSize );
-            writeString( MODULE + " : " + descriptor.toString(), headerLineSpace );
-
-            writeServicesPage( descriptor.services() );
-            writeImportedServicesPage( descriptor.importedServices() );
-            writeEntitiesPage( descriptor.entities() );
-            writeTransientsPage( descriptor.transients() );
-            writeValuesPage( descriptor.values() );
-            writeObjectsPage( descriptor.objects() );
-        }
-    }
-
-    private void writeServicesPage( Iterable<ServiceDetailDescriptor> iter )
-    {
-        for( ServiceDetailDescriptor descriptor : iter )
-        {
-            setFont( header4Font, header4FontSize );
-            writeString( descriptor.toString(), headerLineSpace );
-            writeTypeGeneralPage( descriptor );
-            writeTypeDependenciesPage( descriptor );
-            writeTypeMethodsPage( descriptor );
-            writeTypeStatesPage( descriptor );
-            writeTypeServiceConfigurationPage( descriptor );
-            writeTypeServiceUsagePage( descriptor );
-        }
-    }
-
-    private void writeImportedServicesPage( Iterable<ImportedServiceDetailDescriptor> iter )
-    {
-        for( ImportedServiceDetailDescriptor descriptor : iter )
-        {
-            setFont( header4Font, header4FontSize );
-            writeString( descriptor.toString(), headerLineSpace );
-            writeTypeGeneralPage( descriptor );
-            writeTypeMethodsPage( descriptor );
-            writeTypeServiceUsagePage( descriptor );
-            writeTypeImportedByPage( descriptor );
-        }
-    }
-
-    private void writeEntitiesPage( Iterable<EntityDetailDescriptor> iter )
-    {
-        for( EntityDetailDescriptor descriptor : iter )
-        {
-            setFont( header4Font, header4FontSize );
-            writeString( descriptor.toString(), headerLineSpace );
-            writeTypeGeneralPage( descriptor );
-            writeTypeDependenciesPage( descriptor );
-            writeTypeMethodsPage( descriptor );
-            writeTypeStatesPage( descriptor );
-        }
-    }
-
-    private void writeTransientsPage( Iterable<TransientDetailDescriptor> iter )
-    {
-        for( TransientDetailDescriptor descriptor : iter )
-        {
-            setFont( header4Font, header4FontSize );
-            writeString( descriptor.toString(), headerLineSpace );
-            writeTypeGeneralPage( descriptor );
-            writeTypeDependenciesPage( descriptor );
-            writeTypeMethodsPage( descriptor );
-            writeTypeStatesPage( descriptor );
-        }
-    }
-
-    private void writeValuesPage( Iterable<ValueDetailDescriptor> iter )
-    {
-        for( ValueDetailDescriptor descriptor : iter )
-        {
-            setFont( header4Font, header4FontSize );
-            writeString( descriptor.toString(), headerLineSpace );
-            writeTypeGeneralPage( descriptor );
-            writeTypeDependenciesPage( descriptor );
-            writeTypeMethodsPage( descriptor );
-            writeTypeStatesPage( descriptor );
-        }
-    }
-
-    private void writeObjectsPage( Iterable<ObjectDetailDescriptor> iter )
-    {
-        for( ObjectDetailDescriptor descriptor : iter )
-        {
-            setFont( header4Font, header4FontSize );
-            writeString( descriptor.toString(), headerLineSpace );
-            writeTypeGeneralPage( descriptor );
-            writeTypeDependenciesPage( descriptor );
-            // object don't have methods
-        }
-    }
-
-    private void writeTypeGeneralPage( Object objectDesciptor )
-    {
-
-        setFont( header5Font, header5FontSize );
-        writeString( "General: ", headerLineSpace );
-
-        setFont( normalFont, normalFontSize );
-
-        if( objectDesciptor instanceof ServiceDetailDescriptor )
-        {
-            ServiceDescriptor descriptor = ( (ServiceDetailDescriptor) objectDesciptor ).descriptor();
-            writeString( "- identity: " + descriptor.identity() );
-            writeString( "- class: " + descriptor.toString() );
-            writeString( "- visibility: " + descriptor.visibility().toString() );
-            writeString( "- startup: " + ( (ServiceDetailDescriptor) objectDesciptor ).descriptor()
-                .isInstantiateOnStartup() );
-        }
-        else if( objectDesciptor instanceof EntityDetailDescriptor )
-        {
-            EntityDescriptor descriptor = ( (EntityDetailDescriptor) objectDesciptor ).descriptor();
-            writeString( "- name: " + descriptor.toString() );
-            writeString( "- class: " + descriptor.toString() );
-            writeString( "- visibility: " + descriptor.visibility().toString() );
-        }
-        else if( objectDesciptor instanceof ValueDetailDescriptor )
-        {
-            ValueDescriptor descriptor = ( (ValueDetailDescriptor) objectDesciptor ).descriptor();
-            writeString( "- name: " + descriptor.toString() );
-            writeString( "- class: " + descriptor.toString() );
-            writeString( "- visibility: " + descriptor.visibility().toString() );
-        }
-        else if( objectDesciptor instanceof ObjectDetailDescriptor )
-        {
-            ObjectDescriptor descriptor = ( (ObjectDetailDescriptor) objectDesciptor ).descriptor();
-            writeString( "- name: " + descriptor.toString() );
-            writeString( "- class: " + descriptor.toString() );
-            writeString( "- visibility: " + descriptor.visibility().toString() );
-        }
-        else if( objectDesciptor instanceof CompositeDetailDescriptor )
-        {
-            CompositeDescriptor descriptor = ( (CompositeDetailDescriptor) objectDesciptor ).descriptor();
-            writeString( "- name: " + descriptor.toString() );
-            writeString( "- class: " + descriptor.toString() );
-            writeString( "- visibility: " + descriptor.visibility().toString() );
-        }
-    }
-
-    private void writeTypeDependenciesPage( Object objectDesciptor )
-    {
-        setFont( header5Font, header5FontSize );
-        writeString( "Dependencies: ", headerLineSpace );
-
-        if( objectDesciptor instanceof CompositeDetailDescriptor )
-        {
-            CompositeDetailDescriptor descriptor = (CompositeDetailDescriptor) objectDesciptor;
-            Iterable<MixinDetailDescriptor> iter = descriptor.mixins();
-            for( MixinDetailDescriptor mixinDescriptor : iter )
-            {
-                writeTypeDependenciesPage( mixinDescriptor.injectedFields() );
-            }
-        }
-        else if( objectDesciptor instanceof ObjectDetailDescriptor )
-        {
-            ObjectDetailDescriptor descriptor = ( (ObjectDetailDescriptor) objectDesciptor );
-            writeTypeDependenciesPage( descriptor.injectedFields() );
-        }
-    }
-
-    private void writeTypeDependenciesPage( Iterable<InjectedFieldDetailDescriptor> iter )
-    {
-        setFont( normalFont, normalFontSize );
-        for( InjectedFieldDetailDescriptor descriptor : iter )
-        {
-            DependencyDescriptor dependencyDescriptor = descriptor.descriptor().dependency();
-            writeString( "- name: " + dependencyDescriptor.injectedClass().getSimpleName() );
-            writeString( "    * annotation: @" + dependencyDescriptor.injectionAnnotation()
-                .annotationType()
-                .getSimpleName() );
-            writeString( "    * optional: " + Boolean.toString( dependencyDescriptor.optional() ) );
-            writeString( "    * type: " + dependencyDescriptor.injectionType().getClass().getSimpleName() );
-        }
-    }
-
-    private void writeTypeMethodsPage( Object objectDesciptor )
-    {
-        if( !CompositeDetailDescriptor.class.isAssignableFrom( objectDesciptor.getClass() ) )
-        {
-            return;
-        }
-
-        setFont( header5Font, header5FontSize );
-        writeString( "Methods: ", headerLineSpace );
-        setFont( normalFont, normalFontSize );
-
-        CompositeDetailDescriptor descriptor = (CompositeDetailDescriptor) objectDesciptor;
-        List<CompositeMethodDetailDescriptor> list = DescriptorUtilities.findMethod( descriptor );
-
-        HashSet<String> imports = new HashSet<>();
-        for( CompositeMethodDetailDescriptor methodDescriptor : list )
-        {
-            addImport( imports, methodDescriptor.descriptor().method().getGenericReturnType() );
-            for( Class parameter : methodDescriptor.descriptor().method().getParameterTypes() )
-            {
-                addImport( imports, parameter );
-            }
-        }
-        for( String imp : imports )
-        {
-            writeString( "    import " + imp + ";" );
-        }
-        writeString( "" );
-
-        for( CompositeMethodDetailDescriptor methodDescriptor : list )
-        {
-            Type returnType = methodDescriptor.descriptor().method().getGenericReturnType();
-            writeString( "    " + formatType( returnType ) + "."
-                         + methodDescriptor.toString()
-                         + formatParameters( methodDescriptor.descriptor().method().getParameterTypes() )
-            );
-        }
-    }
-
-    private String formatParameters( Class<?>[] parameterTypes )
-    {
-        StringBuilder result = new StringBuilder();
-        result.append( "(" );
-        boolean first = true;
-        int count = 1;
-        for( Class parameter : parameterTypes )
-        {
-            if( !first )
-            {
-                result.append( "," );
-            }
-            first = false;
-            result.append( " " );
-            result.append( formatType( parameter ) );
-            result.append( " " );
-            result.append( "p" );
-            result.append( count++ );
-        }
-        if( first )
-        {
-            // No parameters appended.
-            result.append( ");" );
-        }
-        else
-        {
-            result.append( " );" );
-        }
-        return result.toString();
-    }
-
-    private String formatType( Type type )
-    {
-        if( type instanceof Class )
-        {
-            Class clazz = (Class) type;
-            return clazz.getSimpleName();
-        }
-        else if( type instanceof ParameterizedType )
-        {
-            ParameterizedType pType = (ParameterizedType) type;
-            Type[] actuals = pType.getActualTypeArguments();
-            Type ownerType = pType.getOwnerType();
-            Type rawType = pType.getRawType();
-            StringBuilder result = new StringBuilder();
-            result.append( ( (Class) rawType ).getSimpleName() );
-            result.append( "<" );
-            boolean first = true;
-            for( Type actual : actuals )
-            {
-                if( !first )
-                {
-                    result.append( "," );
-                }
-                first = false;
-                result.append( formatType( actual ) );
-            }
-            result.append( ">" );
-
-            return result.toString();
-        }
-        else if( type instanceof WildcardType )
-        {
-            // TODO: I am sure there are other wildcard constructs that will format incorrectly. Fix that!
-            //
-            WildcardType wildcard = (WildcardType) type;
-            Type[] lowers = wildcard.getLowerBounds();
-            Type[] uppers = wildcard.getUpperBounds();
-            StringBuilder result = new StringBuilder();
-            result.append( "? extends " );
-            boolean first = true;
-            for( Type upper : uppers )
-            {
-                if( !first )
-                {
-                    result.append( ", " );
-                }
-                result.append( formatType( upper ) );
-            }
-            return result.toString();
-        }
-        else if( type instanceof TypeVariable )
-        {
-            return type.toString();
-        }
-
-        return type.toString();
-    }
-
-    private void addImport( HashSet<String> imports, Type type )
-    {
-        if( type instanceof Class )
-        {
-            Class clazz = (Class) type;
-            Package pkkage = clazz.getPackage();
-            if( pkkage == null )
-            {
-                return;
-            }
-            String packageName = pkkage.getName();
-            if( packageName.startsWith( "java" ) )
-            {
-                return;
-            }
-            imports.add( clazz.getName() );
-        }
-        else if( type instanceof ParameterizedType )
-        {
-            ParameterizedType pType = (ParameterizedType) type;
-            Type[] actuals = pType.getActualTypeArguments();
-            Type ownerType = pType.getOwnerType();
-            Type rawType = pType.getRawType();
-            addImport( imports, ownerType );
-            addImport( imports, rawType );
-            for( Type actual : actuals )
-            {
-                addImport( imports, actual );
-            }
-        }
-    }
-
-    private void writeTypeStatesPage( Object objectDesciptor )
-    {
-        if( !CompositeDetailDescriptor.class.isAssignableFrom( objectDesciptor.getClass() ) )
-        {
-            return;
-        }
-
-        setFont( header5Font, header5FontSize );
-        writeString( "States: ", headerLineSpace );
-
-        CompositeDetailDescriptor descriptor = (CompositeDetailDescriptor) objectDesciptor;
-        List<CompositeMethodDetailDescriptor> list = DescriptorUtilities.findState( descriptor );
-
-        setFont( normalFont, normalFontSize );
-        for( CompositeMethodDetailDescriptor methodDescriptor : list )
-        {
-            writeString( "- name: " + methodDescriptor.toString() );
-            writeString( "    * return: " + methodDescriptor.descriptor().method().getGenericReturnType() );
-        }
-    }
-
-    private void writeTypeServiceConfigurationPage( Object objectDesciptor )
-    {
-        setFont( header5Font, header5FontSize );
-        writeString( "Configuration: ", headerLineSpace );
-
-        Object configDescriptor = DescriptorUtilities.findServiceConfiguration( (ServiceDetailDescriptor) objectDesciptor );
-
-        if( configDescriptor == null )
-        {
-            return;
-        }
-
-        ModelDescriptor spiDescriptor;
-        String typeString;
-        if( configDescriptor instanceof ServiceDetailDescriptor )
-        {
-            spiDescriptor = ( (ServiceDetailDescriptor) configDescriptor ).descriptor();
-            typeString = "Service";
-        }
-        else if( configDescriptor instanceof EntityDetailDescriptor )
-        {
-            spiDescriptor = ( (EntityDetailDescriptor) configDescriptor ).descriptor();
-            typeString = "Entity";
-        }
-        else if( configDescriptor instanceof ValueDetailDescriptor )
-        {
-            spiDescriptor = ( (ValueDetailDescriptor) configDescriptor ).descriptor();
-            typeString = "Value";
-        }
-        else if( configDescriptor instanceof ObjectDetailDescriptor )
-        {
-            spiDescriptor = ( (ObjectDetailDescriptor) configDescriptor ).descriptor();
-            typeString = "Object";
-        }
-        else if( configDescriptor instanceof CompositeDetailDescriptor )
-        {
-            spiDescriptor = ( (CompositeDetailDescriptor) configDescriptor ).descriptor();
-            typeString = "Transient";
-        }
-        else
-        {
-            throw new PrintingException( "Unknown configuration descriptor: " + configDescriptor.getClass()
-                .getName(), null );
-        }
-
-        setFont( normalFont, normalFontSize );
-        writeString( "- name: " + spiDescriptor.toString() );
-        writeString( "- class: " + spiDescriptor.toString() );
-        writeString( "- type: " + typeString );
-    }
-
-    private void writeTypeServiceUsagePage( Object objectDesciptor )
-    {
-        setFont( header5Font, header5FontSize );
-        writeString( "Usage: ", headerLineSpace );
-
-        setFont( normalFont, normalFontSize );
-        List<ServiceUsage> serviceUsages = DescriptorUtilities.findServiceUsage( (ServiceDetailDescriptor) objectDesciptor );
-        List<TableRow> rows = TableRowUtilities.toTableRows( serviceUsages );
-        for( TableRow row : rows )
-        {
-
-            //String owner;
-            String usage;
-            String module;
-            String layer;
-
-            Object obj = row.get( 0 );
-            if( obj instanceof CompositeDetailDescriptor )
-            {
-                CompositeDetailDescriptor descriptor = (CompositeDetailDescriptor) obj;
-                //owner = descriptor.toString();
-                module = descriptor.module().toString();
-                layer = descriptor.module().layer().toString();
-            }
-            else
-            {
-                ObjectDetailDescriptor descriptor = (ObjectDetailDescriptor) obj;
-                //owner = descriptor.toString();
-                module = descriptor.module().toString();
-                layer = descriptor.module().layer().toString();
-            }
-
-            InjectedFieldDetailDescriptor injectedFieldescriptor = (InjectedFieldDetailDescriptor) row.get( 1 );
-            DependencyDescriptor dependencyDescriptor = injectedFieldescriptor.descriptor().dependency();
-            Annotation annotation = dependencyDescriptor.injectionAnnotation();
-            usage = injectedFieldescriptor.toString() + " (@" + annotation.annotationType().getSimpleName() + ")";
-
-            writeString( "- owner: " + row.get( 0 ).toString() );
-            writeString( "    * usage: " + usage );
-            writeString( "    * module: " + module );
-            writeString( "    * layer: " + layer );
-        }
-    }
-
-    private void writeTypeImportedByPage( Object objectDesciptor )
-    {
-        setFont( header5Font, header5FontSize );
-        writeString( "Imported by: ", headerLineSpace );
-
-        ImportedServiceDetailDescriptor detailDescriptor = (ImportedServiceDetailDescriptor) objectDesciptor;
-        ImportedServiceDescriptor descriptor = detailDescriptor.descriptor().importedService();
-        Class<? extends ServiceImporter> importer = descriptor.serviceImporter();
-
-        setFont( normalFont, normalFontSize );
-        writeString( "- name: " + importer.getSimpleName() );
-        writeString( "- class: " + importer.toString() );
-    }
-
-    private void writeString( String text )
-    {
-        writeString( text, this.lineSpace );
-    }
-
-    private void writeString( String text, float lineSpace )
-    {
-        // check for page size, if necessary create new page
-        if( ( curY - lineSpace ) <= startY )
-        {
-            createNewPage();
-        }
-
-        curY = curY - lineSpace;
-
-        try
-        {
-            curContentStream.moveTextPositionByAmount( 0, -lineSpace );
-            curContentStream.drawString( text );
-        }
-        catch( IOException e )
-        {
-            throw new PrintingException( "Unable to write string: " + text, e );
-        }
-    }
-
-    private void setFont( PDFont font, float fontSize )
-    {
-        curFont = font;
-        curFontSize = fontSize;
-        try
-        {
-            curContentStream.setFont( curFont, curFontSize );
-        }
-        catch( IOException e )
-        {
-            throw new PrintingException( "Unable to set font: " + font.toString() + ", " + fontSize + "pt", e );
-        }
-    }
-
-    private void createNewPage()
-    {
-        try
-        {
-            if( curContentStream != null )
-            {
-                curContentStream.endText();
-                curContentStream.close();
-            }
-
-            PDPage page = new PDPage();
-            doc.addPage( page );
-
-            curContentStream = new PDPageContentStream( doc, page );
-
-            curPageSize = page.getArtBox();
-
-            curContentStream.beginText();
-            curY = curPageSize.getHeight() - startY;
-            curContentStream.moveTextPositionByAmount( startX, curY );
-
-            if( curFont != null )
-            {
-                setFont( curFont, curFontSize );
-            }
-        }
-        catch( IOException e )
-        {
-            throw new PrintingException( "Unable to create page.", e );
-        }
-    }
-
-    private double scaleToFit( double srcW, double srcH, double destW, double destH )
-    {
-        double scale = 1;
-        if( srcW > srcH )
-        {
-            if( srcW > destW )
-            {
-                scale = destW / srcW;
-            }
-            srcH = srcH * scale;
-            if( srcH > destH )
-            {
-                scale = scale * ( destH / srcH );
-            }
-        }
-        else
-        {
-            if( srcH > destH )
-            {
-                scale = destH / srcH;
-            }
-            srcW = srcW * scale;
-            if( srcW > destW )
-            {
-                scale = scale * ( destW / srcW );
-            }
-        }
-        return scale;
-    }
-
-    static class PDFFileFilter
-        extends FileFilter
-    {
-
-        private final String description;
-        protected String extension = null;
-
-        public PDFFileFilter()
-        {
-            extension = "pdf";
-            description = "PDF - Portable Document Format";
-        }
-
-        @Override
-        public boolean accept( File f )
-        {
-            if( f != null )
-            {
-                if( f.isDirectory() )
-                {
-                    return true;
-                }
-                String str = getExtension( f );
-                if( str != null && str.equals( extension ) )
-                {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        public String getExtension( File f )
-        {
-            if( f != null )
-            {
-                String filename = f.getName();
-                int i = filename.lastIndexOf( '.' );
-                if( i > 0 && i < filename.length() - 1 )
-                {
-                    return filename.substring( i + 1 ).toLowerCase();
-                }
-            }
-            return null;
-        }
-
-        @Override
-        public String getDescription()
-        {
-            return description;
-        }
-    }
-
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/print/PrintingException.java b/tools/envisage/src/main/java/org/qi4j/envisage/print/PrintingException.java
deleted file mode 100644
index ef12097..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/print/PrintingException.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.print;
-
-public class PrintingException
-    extends RuntimeException
-{
-    public PrintingException( String message, Throwable cause )
-    {
-        super( message, cause );
-    }
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/print/package.html b/tools/envisage/src/main/java/org/qi4j/envisage/print/package.html
deleted file mode 100644
index d281483..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/print/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Envisage Tool PDF Print Support.</h2>
-    </body>
-</html>
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/tree/StructureModelBuilder.java b/tools/envisage/src/main/java/org/qi4j/envisage/tree/StructureModelBuilder.java
deleted file mode 100644
index b19f359..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/tree/StructureModelBuilder.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.tree;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.MutableTreeNode;
-import org.qi4j.tools.model.descriptor.*;
-import org.qi4j.tools.model.util.DescriptorNameComparator;
-
-/**
- * Helper class to build tree model for Qi4J model as Structure Tree
- */
-/* package */ final class StructureModelBuilder
-{
-    private final DescriptorNameComparator<Object> nameComparator = new DescriptorNameComparator<>();
-    private final List<Object> tempList = new ArrayList<>();   // used for sorting
-
-    /* package */ static MutableTreeNode build( ApplicationDetailDescriptor descriptor )
-    {
-        StructureModelBuilder builder = new StructureModelBuilder();
-        return builder.buildApplicationNode( descriptor );
-    }
-
-    private MutableTreeNode buildApplicationNode( ApplicationDetailDescriptor descriptor )
-    {
-        DefaultMutableTreeNode node = new DefaultMutableTreeNode( descriptor );
-        buildLayersNode( node, descriptor.layers() );
-        return node;
-    }
-
-    private void buildLayersNode( DefaultMutableTreeNode parent, Iterable<LayerDetailDescriptor> iter )
-    {
-        for( LayerDetailDescriptor descriptor : iter )
-        {
-            DefaultMutableTreeNode node = new DefaultMutableTreeNode( descriptor );
-            buildModulesNode( node, descriptor.modules() );
-            parent.add( node );
-        }
-    }
-
-    private void buildModulesNode( DefaultMutableTreeNode parent, Iterable<ModuleDetailDescriptor> iter )
-    {
-        for( ModuleDetailDescriptor descriptor : iter )
-        {
-            DefaultMutableTreeNode node = new DefaultMutableTreeNode( descriptor );
-            buildServicesNode( node, descriptor.services() );
-            buildImportedServicesNode( node, descriptor.importedServices() );
-            buildEntitiesNode( node, descriptor.entities() );
-            buildTransientsNode( node, descriptor.transients() );
-            buildValuesNode( node, descriptor.values() );
-            buildObjectsNode( node, descriptor.objects() );
-            parent.add( node );
-        }
-    }
-
-    private void addTypeChildren( DefaultMutableTreeNode parent, List<Object> childList )
-    {
-        Collections.sort( childList, nameComparator );
-
-        for( int i = 0; i < childList.size(); i++ )
-        {
-            DefaultMutableTreeNode node = new DefaultMutableTreeNode( childList.get( i ) );
-            parent.add( node );
-        }
-    }
-
-    private void buildServicesNode( DefaultMutableTreeNode parent, Iterable<ServiceDetailDescriptor> iter )
-    {
-        tempList.clear();
-        for( ServiceDetailDescriptor descriptor : iter )
-        {
-            tempList.add( descriptor );
-        }
-
-        addTypeChildren( parent, tempList );
-    }
-
-    private void buildImportedServicesNode( DefaultMutableTreeNode parent,
-                                            Iterable<ImportedServiceDetailDescriptor> iter
-    )
-    {
-        tempList.clear();
-        for( ImportedServiceDetailDescriptor descriptor : iter )
-        {
-            tempList.add( descriptor );
-        }
-
-        addTypeChildren( parent, tempList );
-    }
-
-    private void buildEntitiesNode( DefaultMutableTreeNode parent, Iterable<EntityDetailDescriptor> iter )
-    {
-        tempList.clear();
-        for( EntityDetailDescriptor descriptor : iter )
-        {
-            tempList.add( descriptor );
-        }
-
-        addTypeChildren( parent, tempList );
-    }
-
-    private void buildTransientsNode( DefaultMutableTreeNode parent, Iterable<TransientDetailDescriptor> iter )
-    {
-        tempList.clear();
-        for( TransientDetailDescriptor descriptor : iter )
-        {
-            tempList.add( descriptor );
-        }
-
-        addTypeChildren( parent, tempList );
-    }
-
-    private void buildValuesNode( DefaultMutableTreeNode parent, Iterable<ValueDetailDescriptor> iter )
-    {
-        tempList.clear();
-        for( ValueDetailDescriptor descriptor : iter )
-        {
-            tempList.add( descriptor );
-        }
-
-        addTypeChildren( parent, tempList );
-    }
-
-    private void buildObjectsNode( DefaultMutableTreeNode parent, Iterable<ObjectDetailDescriptor> iter )
-    {
-        tempList.clear();
-        for( ObjectDetailDescriptor descriptor : iter )
-        {
-            tempList.add( descriptor );
-        }
-
-        addTypeChildren( parent, tempList );
-    }
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/tree/TreeModelCellRenderer.java b/tools/envisage/src/main/java/org/qi4j/envisage/tree/TreeModelCellRenderer.java
deleted file mode 100644
index 551bcca..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/tree/TreeModelCellRenderer.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.tree;
-
-import java.awt.Component;
-import java.util.ResourceBundle;
-import javax.swing.Icon;
-import javax.swing.ImageIcon;
-import javax.swing.JTree;
-import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.DefaultTreeCellRenderer;
-import org.qi4j.tools.model.descriptor.*;
-
-/**
- * TreeCellRenderer
- */
-/* package */ final class TreeModelCellRenderer
-    extends DefaultTreeCellRenderer
-{
-    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( TreeModelCellRenderer.class.getName() );
-
-    private final Icon applicationIcon;
-    private final Icon layerIcon;
-    private final Icon moduleIcon;
-    private final Icon serviceIcon;
-    private final Icon importedServiceIcon;
-    private final Icon entityIcon;
-    private final Icon valueIcon;
-    private final Icon transientIcon;
-    private final Icon objectIcon;
-
-    /* package */ TreeModelCellRenderer()
-    {
-        try
-        {
-            applicationIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Application" ) ) );
-            layerIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Layer" ) ) );
-            moduleIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Module" ) ) );
-            serviceIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Service" ) ) );
-            importedServiceIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_ImportedService" ) ) );
-            entityIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Entity" ) ) );
-            valueIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Value" ) ) );
-            transientIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Transient" ) ) );
-            objectIcon = new ImageIcon( getClass().getResource( BUNDLE.getString( "ICON_Object" ) ) );
-        }
-        catch( Exception ex )
-        {
-            throw new RuntimeException( ex );
-        }
-    }
-
-    @Override
-    public final Component getTreeCellRendererComponent(
-        JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus
-    )
-    {
-        super.getTreeCellRendererComponent( tree, value, sel, expanded, leaf, row, hasFocus );
-
-        DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value;
-        Object userObject = treeNode.getUserObject();
-
-        // determine icon
-        Icon icon = null;
-
-        if( userObject instanceof ApplicationDetailDescriptor )
-        {
-            icon = applicationIcon;
-        }
-        else if( userObject instanceof LayerDetailDescriptor )
-        {
-            icon = layerIcon;
-        }
-        else if( userObject instanceof ModuleDetailDescriptor )
-        {
-            icon = moduleIcon;
-        }
-        else if( userObject instanceof ServiceDetailDescriptor )
-        {
-            icon = serviceIcon;
-        }
-        else if( userObject instanceof ImportedServiceDetailDescriptor )
-        {
-            icon = importedServiceIcon;
-        }
-        else if( userObject instanceof EntityDetailDescriptor )
-        {
-            icon = entityIcon;
-        }
-        else if( userObject instanceof ValueDetailDescriptor )
-        {
-            icon = valueIcon;
-        }
-        else if( userObject instanceof TransientDetailDescriptor )
-        {
-            icon = transientIcon;
-        }
-        else if( userObject instanceof ObjectDetailDescriptor )
-        {
-            icon = objectIcon;
-        }
-        else
-        {
-            // assume it is string
-            String str = userObject.toString();
-            if( str.equalsIgnoreCase( "Services" ) )
-            {
-                icon = serviceIcon;
-            }
-            else if( str.equalsIgnoreCase( "Imported Services" ) )
-            {
-                icon = importedServiceIcon;
-            }
-            else if( str.equalsIgnoreCase( "Entities" ) )
-            {
-                icon = entityIcon;
-            }
-            else if( str.equalsIgnoreCase( "Values" ) )
-            {
-                icon = valueIcon;
-            }
-            else if( str.equalsIgnoreCase( "Transients" ) )
-            {
-                icon = transientIcon;
-            }
-            else if( str.equalsIgnoreCase( "Objects" ) )
-            {
-                icon = objectIcon;
-            }
-        }
-
-        if( icon != null )
-        {
-            setIcon( icon );
-        }
-
-        return this;
-    }
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/tree/TreeModelPane.java b/tools/envisage/src/main/java/org/qi4j/envisage/tree/TreeModelPane.java
deleted file mode 100644
index 591041e..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/tree/TreeModelPane.java
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.tree;
-
-import java.awt.BorderLayout;
-import java.awt.CardLayout;
-import java.awt.GridBagConstraints;
-import java.awt.Insets;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
-import java.util.ResourceBundle;
-import javax.swing.BorderFactory;
-import javax.swing.DefaultComboBoxModel;
-import javax.swing.JComboBox;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTree;
-import javax.swing.event.TreeSelectionEvent;
-import javax.swing.event.TreeSelectionListener;
-import javax.swing.tree.*;
-import org.qi4j.tools.model.descriptor.ApplicationDetailDescriptor;
-
-/**
- * Application Model View as Swing Component.
- * It support 2 view:
- * <pre><code>
- * - by Structure
- * - by Type
- * </code></pre>
- */
-public final class TreeModelPane
-    extends JPanel
-{
-    private static final String STRUCTURE_VIEW = "Structure";
-    private static final String TYPE_VIEW = "Type";
-
-    private static final ResourceBundle BUNDLE = ResourceBundle.getBundle( TreeModelPane.class.getName() );
-
-    private JPanel mainPane;
-    private CardLayout cardLayout;
-    private JTree structureTree;
-    private JTree typeTree;
-    private JComboBox viewAsCombo;
-
-    private boolean selectionInProgress;
-
-    public TreeModelPane()
-    {
-        setLayout( new BorderLayout() );
-
-        // init mainPane
-        structureTree = new JTree();
-        structureTree.setRootVisible( false );
-        structureTree.setShowsRootHandles( true );
-        structureTree.setExpandsSelectedPaths( true );
-        structureTree.setScrollsOnExpand( true );
-        structureTree.setName( STRUCTURE_VIEW );
-        structureTree.setCellRenderer( new TreeModelCellRenderer() );
-
-        typeTree = new JTree();
-        typeTree.setRootVisible( false );
-        typeTree.setShowsRootHandles( true );
-        typeTree.setExpandsSelectedPaths( true );
-        typeTree.setScrollsOnExpand( true );
-        typeTree.setName( TYPE_VIEW );
-        typeTree.setCellRenderer( new TreeModelCellRenderer() );
-
-        mainPane = new JPanel();
-        cardLayout = new CardLayout();
-        mainPane.setLayout( cardLayout );
-        mainPane.add( new JScrollPane( structureTree ), STRUCTURE_VIEW );
-        mainPane.add( new JScrollPane( typeTree ), TYPE_VIEW );
-        add( mainPane, BorderLayout.CENTER );
-
-        // init viewAsCombo
-        JPanel viewAsPane = new JPanel();
-        viewAsPane.setBorder( BorderFactory.createEmptyBorder( 3, 6, 3, 0 ) );
-        viewAsPane.setLayout( new java.awt.GridBagLayout() );
-
-        GridBagConstraints gridBagConstraints;
-        JLabel viewAsLabel = new JLabel( BUNDLE.getString( "CTL_ViewAs.Text" ) );
-        gridBagConstraints = new GridBagConstraints();
-        gridBagConstraints.anchor = GridBagConstraints.WEST;
-        gridBagConstraints.insets = new Insets( 0, 0, 0, 6 );
-        viewAsPane.add( viewAsLabel, gridBagConstraints );
-
-        viewAsCombo = new JComboBox( new DefaultComboBoxModel( new String[]
-        {
-            STRUCTURE_VIEW, TYPE_VIEW
-        } ) );
-        gridBagConstraints = new GridBagConstraints();
-        gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
-        gridBagConstraints.weightx = 1.0;
-        viewAsPane.add( viewAsCombo, gridBagConstraints );
-
-        viewAsCombo.addItemListener( new ItemListener()
-        {
-            @Override
-            public void itemStateChanged( ItemEvent evt )
-            {
-                if( evt.getStateChange() == ItemEvent.DESELECTED )
-                {
-                    return;
-                }
-                cardLayout.show( mainPane, evt.getItem().toString() );
-                repaint();
-            }
-        } );
-
-        add( viewAsPane, BorderLayout.PAGE_START );
-    }
-
-    /**
-     * Initialize Qi4J for this component
-     *
-     * @param descriptor the Application descriptor
-     */
-    public void initQi4J( ApplicationDetailDescriptor descriptor )
-    {
-        // traverse the model and build JTree representation
-        MutableTreeNode rootNode1 = StructureModelBuilder.build( descriptor );
-        MutableTreeNode rootNode2 = TypeModelBuilder.build( descriptor );
-
-        structureTree.setModel( new DefaultTreeModel( rootNode1 ) );
-        typeTree.setModel( new DefaultTreeModel( rootNode2 ) );
-
-        structureTree.addTreeSelectionListener( new TreeSelectionListener()
-        {
-            @Override
-            public void valueChanged( TreeSelectionEvent evt )
-            {
-                structureTreeValueChanged();
-            }
-        } );
-
-        typeTree.addTreeSelectionListener( new TreeSelectionListener()
-        {
-            @Override
-            public void valueChanged( TreeSelectionEvent evt )
-            {
-                typeTreeValueChanged();
-            }
-        } );
-    }
-
-    public Object getLastSelected()
-    {
-        Object obj = structureTree.getLastSelectedPathComponent();
-        if( obj != null )
-        {
-            return ( (DefaultMutableTreeNode) obj ).getUserObject();
-        }
-        return null;
-    }
-
-    public void setSelectedValue( Object obj )
-    {
-        if( obj == null )
-        {
-            return;
-        }
-
-        TreeNode node = findNode( structureTree, obj );
-        if( node != null )
-        {
-            DefaultTreeModel treeModel = (DefaultTreeModel) structureTree.getModel();
-            TreePath treePath = new TreePath( treeModel.getPathToRoot( node ) );
-            structureTree.setSelectionPath( treePath );
-            structureTree.scrollPathToVisible( treePath );
-        }
-        else
-        {
-            structureTree.clearSelection();
-        }
-    }
-
-    /**
-     * Just a helper method to find the node which contains the userObject
-     *
-     * @param tree   the JTree to search into
-     * @param object the user object
-     *
-     * @return TreeNode or null
-     */
-    protected TreeNode findNode( JTree tree, Object object )
-    {
-        DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getModel().getRoot();
-        return findNode( node, object );
-    }
-
-    /**
-     * Recurvice search or find node that contains the obj
-     *
-     * @param node DefaultMutableTreeNode
-     * @param obj  userObject
-     *
-     * @return TreeNode or null if could not find
-     */
-    private TreeNode findNode( DefaultMutableTreeNode node, Object obj )
-    {
-        if( obj instanceof String )
-        {
-            if( node.getUserObject().toString().equals( obj.toString() ) )
-            {
-                return node;
-            }
-        }
-        else if( node.getUserObject().equals( obj ) )
-        {
-            return node;
-        }
-
-        TreeNode foundNode = null;
-        for( int i = 0; i < node.getChildCount(); i++ )
-        {
-            DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) node.getChildAt( i );
-            foundNode = findNode( childNode, obj );
-            if( foundNode != null )
-            {
-                break;
-            }
-        }
-
-        return foundNode;
-    }
-
-    public final void addTreeSelectionListener( TreeSelectionListener listener )
-    {
-        structureTree.addTreeSelectionListener( listener );
-    }
-
-    public final void removeTreeSelectionListener( TreeSelectionListener listener )
-    {
-        structureTree.removeTreeSelectionListener( listener );
-    }
-
-    protected void structureTreeValueChanged()
-    {
-        if( selectionInProgress )
-        {
-            return;
-        }
-
-        Object userObject = getLastSelected();
-        if( userObject == null )
-        {
-            return;
-        }
-        TreeNode node = findNode( typeTree, userObject );
-        if( node != null )
-        {
-            DefaultTreeModel treeModel = (DefaultTreeModel) typeTree.getModel();
-            TreePath treePath = new TreePath( treeModel.getPathToRoot( node ) );
-            typeTree.setSelectionPath( treePath );
-            typeTree.scrollPathToVisible( treePath );
-        }
-    }
-
-    protected void typeTreeValueChanged()
-    {
-        Object obj = typeTree.getLastSelectedPathComponent();
-        if( obj == null )
-        {
-            return;
-        }
-        Object userObject = ( (DefaultMutableTreeNode) obj ).getUserObject();
-        TreeNode node = findNode( structureTree, userObject );
-        if( node != null )
-        {
-            DefaultTreeModel treeModel = (DefaultTreeModel) structureTree.getModel();
-            TreePath treePath = new TreePath( treeModel.getPathToRoot( node ) );
-
-            selectionInProgress = true;
-            try
-            {
-                structureTree.setSelectionPath( treePath );
-            }
-            finally
-            {
-                selectionInProgress = false;
-            }
-            structureTree.scrollPathToVisible( treePath );
-        }
-    }
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/tree/TypeModelBuilder.java b/tools/envisage/src/main/java/org/qi4j/envisage/tree/TypeModelBuilder.java
deleted file mode 100644
index 7b50aee..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/tree/TypeModelBuilder.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.tree;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.MutableTreeNode;
-import org.qi4j.tools.model.descriptor.*;
-import org.qi4j.tools.model.util.DescriptorNameComparator;
-
-/**
- * Helper class to build tree model for Qi4J model as Type Tree
- */
-/* package */ final class TypeModelBuilder
-{
-    private final List<ServiceDetailDescriptor> serviceList = new ArrayList<>();
-    private final List<ImportedServiceDetailDescriptor> importedServiceList = new ArrayList<>();
-    private final List<EntityDetailDescriptor> entityList = new ArrayList<>();
-    private final List<TransientDetailDescriptor> transientList = new ArrayList<>();
-    private final List<ValueDetailDescriptor> valueList = new ArrayList<>();
-    private final List<ObjectDetailDescriptor> objectList = new ArrayList<>();
-
-    /* package */ static MutableTreeNode build( ApplicationDetailDescriptor descriptor )
-    {
-        TypeModelBuilder builder = new TypeModelBuilder();
-        return builder.buildNode( descriptor );
-    }
-
-    private TypeModelBuilder()
-    {
-    }
-
-    private MutableTreeNode buildNode( ApplicationDetailDescriptor descriptor )
-    {
-        traverseLayers( descriptor.layers() );
-
-        DescriptorNameComparator<Object> nameComparator = new DescriptorNameComparator<>();
-
-        // sort based on name order
-        Collections.sort( serviceList, nameComparator );
-        Collections.sort( importedServiceList, nameComparator );
-        Collections.sort( entityList, nameComparator );
-        Collections.sort( transientList, nameComparator );
-        Collections.sort( valueList, nameComparator );
-        Collections.sort( objectList, nameComparator );
-
-        DefaultMutableTreeNode root = new DefaultMutableTreeNode( descriptor );
-        DefaultMutableTreeNode child;
-
-        child = new DefaultMutableTreeNode( "Services" );
-        addChild( child, serviceList );
-        root.add( child );
-
-        child = new DefaultMutableTreeNode( "Imported Services" );
-        addChild( child, importedServiceList );
-        root.add( child );
-
-        child = new DefaultMutableTreeNode( "Entities" );
-        addChild( child, entityList );
-        root.add( child );
-
-        child = new DefaultMutableTreeNode( "Transients" );
-        addChild( child, transientList );
-        root.add( child );
-
-        child = new DefaultMutableTreeNode( "Values" );
-        addChild( child, valueList );
-        root.add( child );
-
-        child = new DefaultMutableTreeNode( "Objects" );
-        addChild( child, objectList );
-        root.add( child );
-
-        return root;
-    }
-
-    private void addChild( DefaultMutableTreeNode node, List list )
-    {
-        for( int i = 0; i < list.size(); i++ )
-        {
-            node.add( new DefaultMutableTreeNode( list.get( i ) ) );
-        }
-    }
-
-    private void traverseLayers( Iterable<LayerDetailDescriptor> iter )
-    {
-        for( LayerDetailDescriptor descriptor : iter )
-        {
-            traverseModules( descriptor.modules() );
-        }
-    }
-
-    private void traverseModules( Iterable<ModuleDetailDescriptor> iter )
-    {
-        for( ModuleDetailDescriptor descriptor : iter )
-        {
-
-            // Services
-            for( ServiceDetailDescriptor child : descriptor.services() )
-            {
-                serviceList.add( child );
-            }
-
-            // Imported Services
-            for( ImportedServiceDetailDescriptor child : descriptor.importedServices() )
-            {
-                importedServiceList.add( child );
-            }
-
-            // Entities
-            for( EntityDetailDescriptor child : descriptor.entities() )
-            {
-                entityList.add( child );
-            }
-
-            // Transient
-            for( TransientDetailDescriptor child : descriptor.transients() )
-            {
-                transientList.add( child );
-            }
-
-            //Values
-            for( ValueDetailDescriptor child : descriptor.values() )
-            {
-                valueList.add( child );
-            }
-
-            // Objects
-            for( ObjectDetailDescriptor child : descriptor.objects() )
-            {
-                objectList.add( child );
-            }
-        }
-    }
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/tree/package.html b/tools/envisage/src/main/java/org/qi4j/envisage/tree/package.html
deleted file mode 100644
index 67eb29a..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/tree/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Envisage Tool Application Tree.</h2>
-    </body>
-</html>
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/util/ColorUtilities.java b/tools/envisage/src/main/java/org/qi4j/envisage/util/ColorUtilities.java
deleted file mode 100644
index 1e8a105..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/util/ColorUtilities.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.util;
-
-import java.awt.Color;
-
-/**
- * Collection of Color Utilities
- */
-public class ColorUtilities
-{
-
-    /**
-     * Return the equivalent AWT {@code Color} of the supplied hexString in format eg #FF33D2.
-     *
-     * @param hexString Color in hexString format eg: #FF33D2
-     * @return the AWT {@code Color} or null if fail to parse
-     */
-    public static Color hexStringToColor( String hexString )
-    {
-        Color color = null;
-        int r, g, b;
-        try
-        {
-            String tmpStr = hexString.substring( 1, 3 );
-            r = Integer.parseInt( tmpStr, 16 );
-            tmpStr = hexString.substring( 3, 5 );
-            g = Integer.parseInt( tmpStr, 16 );
-            tmpStr = hexString.substring( 5, 7 );
-            b = Integer.parseInt( tmpStr, 16 );
-            color = new Color( r, g, b );
-        }
-        catch( NumberFormatException | IndexOutOfBoundsException e )
-        {
-            e.printStackTrace();
-        }
-        return color;
-    }
-
-    private ColorUtilities()
-    {
-    }
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/util/TableRow.java b/tools/envisage/src/main/java/org/qi4j/envisage/util/TableRow.java
deleted file mode 100644
index b81081d..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/util/TableRow.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.util;
-
-import java.util.ArrayList;
-
-/**
- * A simple data structure like table row
- */
-public final class TableRow
-{
-
-    protected ArrayList data;
-
-    public TableRow( int col )
-    {
-        this( col, new Object[ 0 ] );
-    }
-
-    public TableRow( int col, Object... values )
-    {
-        data = new ArrayList( col );
-
-        for( int i = 0; i < col; i++ )
-        {
-            if( values == null || values.length == 0 )
-            {
-                set( i, null );
-            }
-            else
-            {
-                if( values.length > i )
-                {
-                    set( i, values[ i] );
-                }
-                else
-                {
-                    set( i, values[ i] );
-                }
-            }
-        }
-    }
-
-    public void set( int col, Object object )
-    {
-        data.add( col, object );
-    }
-
-    public Object get( int col )
-    {
-        return data.get( col );
-    }
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/util/TableRowUtilities.java b/tools/envisage/src/main/java/org/qi4j/envisage/util/TableRowUtilities.java
deleted file mode 100644
index 592ce7b..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/util/TableRowUtilities.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.util;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.tools.model.descriptor.MixinDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ObjectDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ServiceUsage;
-
-public final class TableRowUtilities
-{
-
-    public static List<TableRow> toTableRows( List<ServiceUsage> serviceUsages )
-    {
-        List<TableRow> rows = new ArrayList<>();
-        for( ServiceUsage usage : serviceUsages )
-        {
-            TableRow row = new TableRow( 5 );
-            if( usage.ownerDescriptor() instanceof MixinDetailDescriptor )
-            {
-                MixinDetailDescriptor mixinDescriptor = (MixinDetailDescriptor) usage.ownerDescriptor();
-                row.set( 0, mixinDescriptor.composite() );
-                row.set( 1, usage.field() );
-                row.set( 2, mixinDescriptor.composite().module() );
-                row.set( 3, mixinDescriptor.composite().module().layer() );
-            }
-            else
-            {
-                // assume ObjectDetailDescriptor
-                ObjectDetailDescriptor objectDescriptor = (ObjectDetailDescriptor) usage.ownerDescriptor();
-                row.set( 0, objectDescriptor );
-                row.set( 1, usage.field() );
-                row.set( 2, objectDescriptor.module() );
-                row.set( 3, objectDescriptor.module().layer() );
-            }
-            rows.add( row );
-        }
-        return rows;
-    }
-
-    private TableRowUtilities()
-    {
-    }
-
-}
diff --git a/tools/envisage/src/main/java/org/qi4j/envisage/util/package.html b/tools/envisage/src/main/java/org/qi4j/envisage/util/package.html
deleted file mode 100644
index c6b3955..0000000
--- a/tools/envisage/src/main/java/org/qi4j/envisage/util/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Envisage Tool Utilities.</h2>
-    </body>
-</html>
diff --git a/tools/envisage/src/main/resources/org/apache/polygene/envisage/EnvisageFrame.properties b/tools/envisage/src/main/resources/org/apache/polygene/envisage/EnvisageFrame.properties
new file mode 100644
index 0000000..8728f0c
--- /dev/null
+++ b/tools/envisage/src/main/resources/org/apache/polygene/envisage/EnvisageFrame.properties
@@ -0,0 +1,21 @@
+#
+#  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.
+#
+#
+#
+
+Application.Title=Apache Polygene Envisage
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/APIPane.properties b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/APIPane.properties
new file mode 100644
index 0000000..92cdd33
--- /dev/null
+++ b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/APIPane.properties
@@ -0,0 +1,23 @@
+#
+#  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.
+#
+#
+#
+
+Service.Column=Service
+Module.Column=Module
+Visibility.Column=Visibility
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/DependencyPane.properties b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/DependencyPane.properties
new file mode 100644
index 0000000..4c1ec6d
--- /dev/null
+++ b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/DependencyPane.properties
@@ -0,0 +1,28 @@
+#
+#  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.
+#
+#
+#
+
+CTL_ClassName.Text = [CTL_ClassName.Text / org/apache/polygene/envisage/detail/DependencyPane]
+CTL_Optional.Text = [CTL_Optional.Text / org/apache/polygene/envisage/detail/DependencyPane]
+CTL_Annotation.Text = [CTL_Annotation.Text / org/apache/polygene/envisage/detail/DependencyPane]
+CTL_Injection.Text = [CTL_Injection.Text / org/apache/polygene/envisage/detail/DependencyPane]
+CTL_InjectionClass.Text = Class:
+CTL_InjectionType.Text = [CTL_InjectionType.Text / org/apache/polygene/envisage/detail/DependencyPane]
+CTL_InjectionTypeRaw.Text = Raw:
+CTL_InjectedServices.Text=[CTL_InjectedServices.Text / org/apache/polygene/envisage/detail/DependencyPane]
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/DetailModelPane.properties b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/DetailModelPane.properties
new file mode 100644
index 0000000..cb8a6b0
--- /dev/null
+++ b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/DetailModelPane.properties
@@ -0,0 +1,29 @@
+#
+#  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.
+#
+#
+#
+
+CTL_GeneralTab.Text = General
+CTL_MethodTab.Text = Methods
+CTL_StateTab.Text = States
+CTL_DependencyTab.Text = Dependencies
+CTL_ServiceConfiguration.Text = Configuration
+CTL_ServiceUsage.Text = Usage
+CTL_ImportedBy.Text = Imported by
+CTL_SPITab.Text = SPI
+CTL_APITab.Text = API
diff --git a/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/GeneralPane.properties b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/GeneralPane.properties
new file mode 100644
index 0000000..24c4b6e
--- /dev/null
+++ b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/GeneralPane.properties
@@ -0,0 +1,22 @@
+#
+#  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.
+#
+#
+#
+
+Name.Column=Name
+Value.Column=Value
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/ImportedByPane.properties b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/ImportedByPane.properties
new file mode 100644
index 0000000..5f22b36
--- /dev/null
+++ b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/ImportedByPane.properties
@@ -0,0 +1,22 @@
+#
+#  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.
+#
+#
+#
+
+CTL_Name.Text=[CTL_Name.Text / org/apache/polygene/envisage/detail/ImportedByPane]
+CTL_Class.Text=[CTL_Class.Text / org/apache/polygene/envisage/detail/ImportedByPane]
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/MethodPane.properties b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/MethodPane.properties
new file mode 100644
index 0000000..86f8eea
--- /dev/null
+++ b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/MethodPane.properties
@@ -0,0 +1,22 @@
+#
+#  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.
+#
+#
+#
+
+ICON_Public=public.png
+ICON_Private=private.png
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/SPIPane.properties b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/SPIPane.properties
new file mode 100644
index 0000000..05342d7
--- /dev/null
+++ b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/SPIPane.properties
@@ -0,0 +1,23 @@
+#
+#  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.
+#
+#
+#
+
+Dependency.Column=Dependency
+Module.Column=Module
+Layer.Column=Layer
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/ServiceConfigurationPane.properties b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/ServiceConfigurationPane.properties
new file mode 100644
index 0000000..10aa0b4
--- /dev/null
+++ b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/ServiceConfigurationPane.properties
@@ -0,0 +1,24 @@
+#
+#  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.
+#
+#
+#
+
+CTL_Name.Text=[CTL_Name.Text / org/apache/polygene/envisage/detail/ServiceConfigurationPane]
+CTL_Class.Text=[CTL_Class.Text / org/apache/polygene/envisage/detail/ServiceConfigurationPane]
+CTL_Type.Text=[CTL_Type.Text / org/apache/polygene/envisage/detail/ServiceConfigurationPane]
+CTL_Link.Text=[CTL_Link.Text / org/apache/polygene/envisage/detail/ServiceConfigurationPane]
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/ServiceUsagePane.properties b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/ServiceUsagePane.properties
new file mode 100644
index 0000000..44d3f4a
--- /dev/null
+++ b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/ServiceUsagePane.properties
@@ -0,0 +1,25 @@
+#
+#  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.
+#
+#
+#
+
+Owner.Column=Owner
+Usage.Column=Usage
+Annotation.Column=Annotation
+Module.Column=Module
+Layer.Column=Layer
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/StatePane.properties b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/StatePane.properties
new file mode 100644
index 0000000..86f8eea
--- /dev/null
+++ b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/StatePane.properties
@@ -0,0 +1,22 @@
+#
+#  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.
+#
+#
+#
+
+ICON_Public=public.png
+ICON_Private=private.png
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/private.png b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/private.png
similarity index 100%
rename from tools/envisage/src/main/resources/org/qi4j/envisage/detail/private.png
rename to tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/private.png
Binary files differ
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/public.png b/tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/public.png
similarity index 100%
rename from tools/envisage/src/main/resources/org/qi4j/envisage/detail/public.png
rename to tools/envisage/src/main/resources/org/apache/polygene/envisage/detail/public.png
Binary files differ
diff --git a/tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/TreeModelCellRenderer.properties b/tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/TreeModelCellRenderer.properties
new file mode 100644
index 0000000..e765041
--- /dev/null
+++ b/tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/TreeModelCellRenderer.properties
@@ -0,0 +1,29 @@
+#
+#  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.
+#
+#
+#
+
+ICON_Application=application.png
+ICON_Layer=layer.png
+ICON_Module=module.png
+ICON_Service=service.png
+ICON_ImportedService=importedService.png
+ICON_Entity=entity.png
+ICON_Value=value.png
+ICON_Transient=transient.png
+ICON_Object=object.png
diff --git a/tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/TreeModelPane.properties b/tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/TreeModelPane.properties
new file mode 100644
index 0000000..28280f8
--- /dev/null
+++ b/tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/TreeModelPane.properties
@@ -0,0 +1,21 @@
+#
+#  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.
+#
+#
+#
+
+CTL_ViewAs.Text = View
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/tree/application.png b/tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/application.png
similarity index 100%
rename from tools/envisage/src/main/resources/org/qi4j/envisage/tree/application.png
rename to tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/application.png
Binary files differ
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/tree/entity.png b/tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/entity.png
similarity index 100%
rename from tools/envisage/src/main/resources/org/qi4j/envisage/tree/entity.png
rename to tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/entity.png
Binary files differ
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/tree/importedService.png b/tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/importedService.png
similarity index 100%
rename from tools/envisage/src/main/resources/org/qi4j/envisage/tree/importedService.png
rename to tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/importedService.png
Binary files differ
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/tree/layer.png b/tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/layer.png
similarity index 100%
rename from tools/envisage/src/main/resources/org/qi4j/envisage/tree/layer.png
rename to tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/layer.png
Binary files differ
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/tree/module.png b/tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/module.png
similarity index 100%
rename from tools/envisage/src/main/resources/org/qi4j/envisage/tree/module.png
rename to tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/module.png
Binary files differ
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/tree/object.png b/tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/object.png
similarity index 100%
rename from tools/envisage/src/main/resources/org/qi4j/envisage/tree/object.png
rename to tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/object.png
Binary files differ
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/tree/service.png b/tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/service.png
similarity index 100%
rename from tools/envisage/src/main/resources/org/qi4j/envisage/tree/service.png
rename to tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/service.png
Binary files differ
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/tree/transient.png b/tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/transient.png
similarity index 100%
rename from tools/envisage/src/main/resources/org/qi4j/envisage/tree/transient.png
rename to tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/transient.png
Binary files differ
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/tree/value.png b/tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/value.png
similarity index 100%
rename from tools/envisage/src/main/resources/org/qi4j/envisage/tree/value.png
rename to tools/envisage/src/main/resources/org/apache/polygene/envisage/tree/value.png
Binary files differ
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/EnvisageFrame.properties b/tools/envisage/src/main/resources/org/qi4j/envisage/EnvisageFrame.properties
deleted file mode 100644
index 639258b..0000000
--- a/tools/envisage/src/main/resources/org/qi4j/envisage/EnvisageFrame.properties
+++ /dev/null
@@ -1,16 +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.
-
-Application.Title=Qi4J Envisage
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/APIPane.properties b/tools/envisage/src/main/resources/org/qi4j/envisage/detail/APIPane.properties
deleted file mode 100644
index 9faf717..0000000
--- a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/APIPane.properties
+++ /dev/null
@@ -1,18 +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.
-
-Service.Column=Service
-Module.Column=Module
-Visibility.Column=Visibility
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/DependencyPane.properties b/tools/envisage/src/main/resources/org/qi4j/envisage/detail/DependencyPane.properties
deleted file mode 100644
index 7103ac5..0000000
--- a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/DependencyPane.properties
+++ /dev/null
@@ -1,23 +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.
-
-CTL_ClassName.Text = Class Name:
-CTL_Optional.Text = Optional:
-CTL_Annotation.Text = Annotation:
-CTL_Injection.Text = Injection
-CTL_InjectionClass.Text = Class:
-CTL_InjectionType.Text = Type:
-CTL_InjectionTypeRaw.Text = Raw:
-CTL_InjectedServices.Text=Services:
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/DetailModelPane.properties b/tools/envisage/src/main/resources/org/qi4j/envisage/detail/DetailModelPane.properties
deleted file mode 100644
index e461a4a..0000000
--- a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/DetailModelPane.properties
+++ /dev/null
@@ -1,24 +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.
-
-CTL_GeneralTab.Text = General
-CTL_MethodTab.Text = Methods
-CTL_StateTab.Text = States
-CTL_DependencyTab.Text = Dependencies
-CTL_ServiceConfiguration.Text = Configuration
-CTL_ServiceUsage.Text = Usage
-CTL_ImportedBy.Text = Imported by
-CTL_SPITab.Text = SPI
-CTL_APITab.Text = API
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/GeneralPane.properties b/tools/envisage/src/main/resources/org/qi4j/envisage/detail/GeneralPane.properties
deleted file mode 100644
index 8104bdf..0000000
--- a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/GeneralPane.properties
+++ /dev/null
@@ -1,17 +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.
-
-Name.Column=Name
-Value.Column=Value
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/ImportedByPane.properties b/tools/envisage/src/main/resources/org/qi4j/envisage/detail/ImportedByPane.properties
deleted file mode 100644
index 20edb8c..0000000
--- a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/ImportedByPane.properties
+++ /dev/null
@@ -1,17 +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.
-
-CTL_Name.Text=Name:
-CTL_Class.Text=Class:
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/MethodPane.properties b/tools/envisage/src/main/resources/org/qi4j/envisage/detail/MethodPane.properties
deleted file mode 100644
index c44c39a..0000000
--- a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/MethodPane.properties
+++ /dev/null
@@ -1,17 +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.
-
-ICON_Public=public.png
-ICON_Private=private.png
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/SPIPane.properties b/tools/envisage/src/main/resources/org/qi4j/envisage/detail/SPIPane.properties
deleted file mode 100644
index 8f98011..0000000
--- a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/SPIPane.properties
+++ /dev/null
@@ -1,18 +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.
-
-Dependency.Column=Dependency
-Module.Column=Module
-Layer.Column=Layer
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/ServiceConfigurationPane.properties b/tools/envisage/src/main/resources/org/qi4j/envisage/detail/ServiceConfigurationPane.properties
deleted file mode 100644
index 3229a12..0000000
--- a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/ServiceConfigurationPane.properties
+++ /dev/null
@@ -1,19 +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.
-
-CTL_Name.Text=Name:
-CTL_Class.Text=Class:
-CTL_Type.Text=Type:
-CTL_Link.Text=Goto
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/ServiceUsagePane.properties b/tools/envisage/src/main/resources/org/qi4j/envisage/detail/ServiceUsagePane.properties
deleted file mode 100644
index a6adce0..0000000
--- a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/ServiceUsagePane.properties
+++ /dev/null
@@ -1,20 +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.
-
-Owner.Column=Owner
-Usage.Column=Usage
-Annotation.Column=Annotation
-Module.Column=Module
-Layer.Column=Layer
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/StatePane.properties b/tools/envisage/src/main/resources/org/qi4j/envisage/detail/StatePane.properties
deleted file mode 100644
index c44c39a..0000000
--- a/tools/envisage/src/main/resources/org/qi4j/envisage/detail/StatePane.properties
+++ /dev/null
@@ -1,17 +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.
-
-ICON_Public=public.png
-ICON_Private=private.png
\ No newline at end of file
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/tree/TreeModelCellRenderer.properties b/tools/envisage/src/main/resources/org/qi4j/envisage/tree/TreeModelCellRenderer.properties
deleted file mode 100644
index b694372..0000000
--- a/tools/envisage/src/main/resources/org/qi4j/envisage/tree/TreeModelCellRenderer.properties
+++ /dev/null
@@ -1,24 +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.
-
-ICON_Application=application.png
-ICON_Layer=layer.png
-ICON_Module=module.png
-ICON_Service=service.png
-ICON_ImportedService=importedService.png
-ICON_Entity=entity.png
-ICON_Value=value.png
-ICON_Transient=transient.png
-ICON_Object=object.png
diff --git a/tools/envisage/src/main/resources/org/qi4j/envisage/tree/TreeModelPane.properties b/tools/envisage/src/main/resources/org/qi4j/envisage/tree/TreeModelPane.properties
deleted file mode 100644
index 8cedb43..0000000
--- a/tools/envisage/src/main/resources/org/qi4j/envisage/tree/TreeModelPane.properties
+++ /dev/null
@@ -1,16 +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.
-
-CTL_ViewAs.Text = View
\ No newline at end of file
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/sample/EnvisageSample.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/sample/EnvisageSample.java
new file mode 100644
index 0000000..03be674
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/sample/EnvisageSample.java
@@ -0,0 +1,155 @@
+/*
+ *  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.polygene.envisage.sample;
+
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.envisage.Envisage;
+import org.apache.polygene.index.rdf.assembly.RdfMemoryStoreAssembler;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+import static org.apache.polygene.test.util.Assume.assumeDisplayPresent;
+
+public class EnvisageSample
+    extends AbstractPolygeneTest
+{
+
+    public static void main( String[] args )
+        throws Exception
+    {
+        EnvisageSample sample = new EnvisageSample();
+        sample.runSample();
+    }
+
+    @BeforeClass
+    public static void assumeDisplay()
+    {
+        assumeDisplayPresent();
+    }
+
+    @Test
+    public void runSample()
+        throws Exception
+    {
+        setUp();
+        createTestData();
+        //createTestData2();
+        //createTestData3();
+
+        new Envisage().run( applicationModel );
+//        Thread.sleep( 1113000 );
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( CarEntity.class );
+        module.entities( AnimalEntity.class );
+        new RdfMemoryStoreAssembler().assemble( module );
+        new EntityTestAssembler().assemble( module );
+    }
+
+    public void createTestData()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            createCar( "Volvo", "S80", 2007 );
+            createCar( "Volvo", "C70", 2006 );
+            createCar( "Ford", "Transit", 2007 );
+            createCar( "Ford", "Mustang", 2007 );
+            createCar( "Ford", "Mustang", 2006 );
+            createCar( "Ford", "Mustang", 2005 );
+
+            createAnimal( "Cat", "Miaow" );
+            createAnimal( "Duck", "Kwek Kwek" );
+            createAnimal( "Dog", "Guk Guk" );
+            createAnimal( "Cow", "Moooo" );
+
+            uow.complete();
+        }
+        catch( UnitOfWorkCompletionException e )
+        {
+            // Can not happen.
+            e.printStackTrace();
+        }
+    }
+
+    private Identity createCar(String manufacturer, String model, int year )
+    {
+        UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+        EntityBuilder<Car> builder = uow.newEntityBuilder( Car.class );
+        Car prototype = builder.instanceFor( CarEntity.class );
+        prototype.manufacturer().set( manufacturer );
+        prototype.model().set( model );
+        prototype.year().set( year );
+        CarEntity entity = (CarEntity) builder.newInstance();
+        return entity.identity().get();
+    }
+
+    private Identity createAnimal( String name, String sound )
+    {
+        UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+        EntityBuilder<Animal> builder = uow.newEntityBuilder( Animal.class );
+        Animal prototype = builder.instanceFor( AnimalEntity.class );
+        prototype.name().set( name );
+        prototype.sound().set( sound );
+        AnimalEntity entity = (AnimalEntity) builder.newInstance();
+        return entity.identity().get();
+    }
+
+    public interface Car
+    {
+        Property<String> manufacturer();
+
+        Property<String> model();
+
+        Property<Integer> year();
+    }
+
+    public interface CarEntity
+        extends Car, HasIdentity
+    {
+    }
+
+    public interface Animal
+    {
+        Property<String> name();
+
+        Property<String> sound();
+    }
+
+    public interface AnimalEntity
+        extends Animal, HasIdentity
+    {
+    }
+
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/EnvisageSchoolSample.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/EnvisageSchoolSample.java
new file mode 100644
index 0000000..b89cf41
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/EnvisageSchoolSample.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.envisage.school;
+
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.envisage.Envisage;
+
+public class EnvisageSchoolSample
+{
+    // START SNIPPET: envisage
+    public static void main( String[] args )
+        throws Exception
+    {
+        Energy4Java energy4Java = new Energy4Java();
+
+        ApplicationDescriptor applicationModel
+                              = energy4Java.newApplicationModel( new SchoolAssembler() );
+
+        new Envisage().run( applicationModel );
+    }
+    // END SNIPPET: envisage
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/SchoolAssembler.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/SchoolAssembler.java
new file mode 100644
index 0000000..b9148af
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/SchoolAssembler.java
@@ -0,0 +1,111 @@
+/*
+ *  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.polygene.envisage.school;
+
+import org.apache.polygene.bootstrap.ApplicationAssembler;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.envisage.school.config.persistence.PersistenceConfigAssembler;
+import org.apache.polygene.envisage.school.domain.person.assembly.PersonModelAssembler;
+import org.apache.polygene.envisage.school.domain.school.assembly.SchoolModelAssembler;
+import org.apache.polygene.envisage.school.infrastructure.mail.assembly.MailServiceAssembler;
+import org.apache.polygene.envisage.school.infrastructure.persistence.PersistenceAssembler;
+import org.apache.polygene.envisage.school.ui.admin.AdminAssembler;
+
+/**
+ * Application assembler for the School sample
+ */
+public class SchoolAssembler
+    implements ApplicationAssembler
+{
+    @Override
+    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
+        throws AssemblyException
+    {
+        final ApplicationAssembly appAssembly = applicationFactory.newApplicationAssembly();
+        appAssembly.setName( "School" );
+
+        // Create layers
+        LayerAssembly layerUI = createUILayer( appAssembly );
+        LayerAssembly layerDomain = createDomainLayer( appAssembly );
+        LayerAssembly layerInfra = createInfrastructureLayer( appAssembly );
+        LayerAssembly layerConfig = createConfigLayer( appAssembly );
+
+        layerUI.uses( layerDomain );
+        layerDomain.uses( layerInfra );
+        layerDomain.uses( layerConfig );
+
+        return appAssembly;
+    }
+
+    private LayerAssembly createInfrastructureLayer( ApplicationAssembly appAssembly )
+        throws AssemblyException
+    {
+        LayerAssembly layerInfrastructure = appAssembly.layer( "Infrastructure" );
+
+        ModuleAssembly moduleMail = layerInfrastructure.module( "Mail" );
+        new MailServiceAssembler().assemble( moduleMail );
+
+        ModuleAssembly modulePersistence = layerInfrastructure.module( "Persistence" );
+        new PersistenceAssembler().assemble( modulePersistence );
+
+        return layerInfrastructure;
+    }
+
+    private LayerAssembly createConfigLayer( ApplicationAssembly appAssembly )
+        throws AssemblyException
+    {
+        LayerAssembly layerConfig = appAssembly.layer( "configuration" );
+
+        ModuleAssembly persistenceConfig = layerConfig.module( "persistence" );
+        new PersistenceConfigAssembler().assemble( persistenceConfig );
+        return layerConfig;
+    }
+
+    private LayerAssembly createDomainLayer( ApplicationAssembly appAssembly )
+        throws AssemblyException
+    {
+        LayerAssembly layerDomain = appAssembly.layer( "domain" );
+
+        ModuleAssembly modulePerson = layerDomain.module( "person" );
+        new PersonModelAssembler().assemble( modulePerson );
+
+        ModuleAssembly moduleSchool = layerDomain.module( "school" );
+        new SchoolModelAssembler().assemble( moduleSchool );
+
+        return layerDomain;
+    }
+
+    private LayerAssembly createUILayer( ApplicationAssembly appAssembly )
+        throws AssemblyException
+    {
+        LayerAssembly layerUI = appAssembly.layer( "UI" );
+
+        // Add admin
+        ModuleAssembly moduleAdmin = layerUI.module( "admin" );
+        new AdminAssembler().assemble( moduleAdmin );
+
+        return layerUI;
+    }
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/config/mail/MailConfigAssembler.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/config/mail/MailConfigAssembler.java
new file mode 100644
index 0000000..bec3c71
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/config/mail/MailConfigAssembler.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.envisage.school.config.mail;
+
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+public class MailConfigAssembler
+    implements Assembler
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( MailConfiguration.class );
+    }
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/config/mail/MailConfiguration.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/config/mail/MailConfiguration.java
new file mode 100644
index 0000000..15888c7
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/config/mail/MailConfiguration.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.envisage.school.config.mail;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+public interface MailConfiguration
+{
+    @UseDefaults
+    Property<String> host();
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/config/persistence/PersistenceConfigAssembler.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/config/persistence/PersistenceConfigAssembler.java
new file mode 100644
index 0000000..357669f
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/config/persistence/PersistenceConfigAssembler.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.envisage.school.config.persistence;
+
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+
+import static org.apache.polygene.api.common.Visibility.layer;
+
+public class PersistenceConfigAssembler
+    implements Assembler
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( MemoryEntityStoreService.class ).visibleIn( layer ).instantiateOnStartup();
+    }
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/person/Person.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/person/Person.java
new file mode 100644
index 0000000..34b5651
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/person/Person.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.envisage.school.domain.person;
+
+public interface Person
+{
+    String firstName();
+
+    String lastName();
+
+    Iterable<Role> roles();
+
+    void addRole( Role role );
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/person/Role.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/person/Role.java
new file mode 100644
index 0000000..f513352
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/person/Role.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.envisage.school.domain.person;
+
+public interface Role
+{
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/person/assembly/PersonEntity.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/person/assembly/PersonEntity.java
new file mode 100644
index 0000000..10f0fe3
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/person/assembly/PersonEntity.java
@@ -0,0 +1,75 @@
+/*
+ *  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.polygene.envisage.school.domain.person.assembly;
+
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.envisage.school.domain.person.Person;
+import org.apache.polygene.envisage.school.domain.person.Role;
+
+@Mixins( PersonEntity.PersonMixin.class )
+public interface PersonEntity
+    extends Person, HasIdentity
+{
+    class PersonMixin
+        implements Person
+    {
+        @This
+        private PersonState state;
+
+        @Override
+        public String firstName()
+        {
+            return state.firstName().get();
+        }
+
+        @Override
+        public String lastName()
+        {
+            return state.lastName().get();
+        }
+
+        @Override
+        public Iterable<Role> roles()
+        {
+            return state.roles();
+        }
+
+        @Override
+        public void addRole( Role role )
+        {
+            state.roles().add( 0, role );
+        }
+    }
+
+    static interface PersonState
+    {
+        Property<String> firstName();
+
+        Property<String> lastName();
+
+        ManyAssociation<Role> roles();
+    }
+
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/person/assembly/PersonModelAssembler.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/person/assembly/PersonModelAssembler.java
new file mode 100644
index 0000000..a18cbf9
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/person/assembly/PersonModelAssembler.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.envisage.school.domain.person.assembly;
+
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.envisage.school.domain.person.initialdata.SamplePersonInitialData;
+
+import static org.apache.polygene.api.common.Visibility.application;
+import static org.apache.polygene.api.common.Visibility.layer;
+
+public final class PersonModelAssembler
+    implements Assembler
+{
+    @Override
+    public final void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( PersonEntity.class )
+            .visibleIn( layer );
+
+        module.services( SamplePersonInitialData.class )
+            .visibleIn( application )
+            .instantiateOnStartup();
+    }
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/person/initialdata/SamplePersonInitialData.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/person/initialdata/SamplePersonInitialData.java
new file mode 100644
index 0000000..e3bf5ce
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/person/initialdata/SamplePersonInitialData.java
@@ -0,0 +1,108 @@
+/*
+ *  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.polygene.envisage.school.domain.person.initialdata;
+
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.envisage.school.domain.person.Person;
+import org.apache.polygene.envisage.school.domain.person.assembly.PersonEntity;
+
+@Mixins( SamplePersonInitialData.SamplePersonBootstrapMixin.class )
+@Activators( SamplePersonInitialData.Activator.class )
+public interface SamplePersonInitialData
+{
+    String EDWARD = "edward";
+    String NICLAS = "niclas";
+    String RICKARD = "rickard";
+
+    void insertInitialData()
+        throws Exception;
+
+    class Activator
+        extends ActivatorAdapter<ServiceReference<SamplePersonInitialData>>
+    {
+
+        @Override
+        public void afterActivation( ServiceReference<SamplePersonInitialData> activated )
+            throws Exception
+        {
+            activated.get().insertInitialData();
+        }
+
+    }
+
+    abstract class SamplePersonBootstrapMixin
+        implements SamplePersonInitialData
+    {
+        private static final String[][] DATAS =
+        {
+            {
+                EDWARD, "Edward", "Yakop"
+            },
+            {
+                NICLAS, "Niclas", "Hedhman"
+            },
+            {
+                RICKARD, "Rickard", "Öberg"
+            }
+        };
+
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @Override
+        public void insertInitialData()
+            throws Exception
+        {
+            UnitOfWork uow = uowf.currentUnitOfWork();
+
+            for( String[] data : DATAS )
+            {
+                String personId = data[ 0];
+                String firstName = data[ 1];
+                String lastName = data[ 2];
+                createPerson( uow, personId, firstName, lastName );
+            }
+
+            uow.complete();
+        }
+
+        private void createPerson( UnitOfWork uow, String personId, String firstName, String lastName )
+        {
+            EntityBuilder<Person> person = uow.newEntityBuilder( Person.class, new StringIdentity( personId ) );
+
+            PersonEntity.PersonState state = person.instanceFor( PersonEntity.PersonState.class );
+            state.firstName().set( firstName );
+            state.lastName().set( lastName );
+
+            person.newInstance();
+        }
+
+    }
+
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/School.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/School.java
new file mode 100644
index 0000000..37b12ae
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/School.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.envisage.school.domain.school;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.envisage.school.domain.person.Person;
+
+public interface School
+{
+    String name();
+
+    Query<Subject> availableSubjects();
+
+    Query<Student> students();
+
+    void enroll( @Optional Person person, Subject subject );
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/SchoolRepository.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/SchoolRepository.java
new file mode 100644
index 0000000..a6f98c9
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/SchoolRepository.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.envisage.school.domain.school;
+
+import org.apache.polygene.api.query.Query;
+
+public interface SchoolRepository
+{
+    Query<School> findAll();
+
+    School findSchoolByName( String schoolName );
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/Student.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/Student.java
new file mode 100644
index 0000000..9c4f4ed
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/Student.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.envisage.school.domain.school;
+
+import org.apache.polygene.envisage.school.domain.person.Role;
+
+public interface Student
+    extends Role
+{
+    School school();
+
+    Iterable<Subject> subjects();
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/Subject.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/Subject.java
new file mode 100644
index 0000000..7a88543
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/Subject.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.envisage.school.domain.school;
+
+public interface Subject
+{
+    String name();
+
+    String description();
+
+    School school();
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/assembly/SchoolEntity.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/assembly/SchoolEntity.java
new file mode 100644
index 0000000..2ee8b0c
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/assembly/SchoolEntity.java
@@ -0,0 +1,119 @@
+/*
+ *  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.polygene.envisage.school.domain.school.assembly;
+
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.envisage.school.domain.person.Person;
+import org.apache.polygene.envisage.school.domain.school.School;
+import org.apache.polygene.envisage.school.domain.school.Student;
+import org.apache.polygene.envisage.school.domain.school.Subject;
+import org.apache.polygene.envisage.school.infrastructure.mail.MailService;
+
+import static org.apache.polygene.api.query.QueryExpressions.eq;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+
+@Mixins( SchoolEntity.SchoolMixin.class )
+public interface SchoolEntity
+    extends School, HasIdentity
+{
+    class SchoolMixin
+        implements School
+    {
+        @Structure
+        private UnitOfWorkFactory uowf;
+        @Structure
+        private QueryBuilderFactory qbf;
+        @This
+        private SchoolState state;
+        @Service
+        private MailService mailer;
+        private final Identity schoolId;
+
+        public SchoolMixin( @This HasIdentity identity )
+        {
+            schoolId = identity.identity().get();
+        }
+
+        @Override
+        public String name()
+        {
+            return state.name().get();
+        }
+
+        @Override
+        public Query<Subject> availableSubjects()
+        {
+            UnitOfWork uow = uowf.currentUnitOfWork();
+            try
+            {
+                QueryBuilder<Subject> builder = qbf.newQueryBuilder( Subject.class );
+                SubjectEntity.SubjectState subject = templateFor( SubjectEntity.SubjectState.class );
+                builder.where( eq( subject.schoolId(), schoolId ) );
+                return uow.newQuery( builder );
+            }
+            finally
+            {
+                uow.pause();
+            }
+        }
+
+        @Override
+        public Query<Student> students()
+        {
+            UnitOfWork uow = uowf.currentUnitOfWork();
+            try
+            {
+                QueryBuilder<Student> builder = qbf.newQueryBuilder( Student.class );
+                StudentEntity.StudentState studentState = templateFor( StudentEntity.StudentState.class );
+                builder.where( eq( studentState.schoolId(), schoolId ) );
+                return uow.newQuery( builder );
+            }
+            finally
+            {
+                uow.pause();
+            }
+        }
+
+        @Override
+        public void enroll( Person person, Subject subject )
+        {
+            // TODO
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    interface SchoolState
+    {
+        Property<String> name();
+    }
+
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/assembly/SchoolModelAssembler.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/assembly/SchoolModelAssembler.java
new file mode 100644
index 0000000..fbcef85
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/assembly/SchoolModelAssembler.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.envisage.school.domain.school.assembly;
+
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.apache.polygene.api.common.Visibility.application;
+import static org.apache.polygene.api.common.Visibility.layer;
+
+public final class SchoolModelAssembler
+    implements Assembler
+{
+    @Override
+    public final void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities(
+            StudentEntity.class,
+            SchoolEntity.class,
+            SubjectEntity.class
+        ).visibleIn( layer );
+
+        module.services( SchoolRepositoryService.class )
+            .visibleIn( application );
+    }
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/assembly/SchoolRepositoryService.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/assembly/SchoolRepositoryService.java
new file mode 100644
index 0000000..f850b3c
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/assembly/SchoolRepositoryService.java
@@ -0,0 +1,65 @@
+/*
+ *  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.polygene.envisage.school.domain.school.assembly;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.envisage.school.domain.school.School;
+import org.apache.polygene.envisage.school.domain.school.SchoolRepository;
+
+import static org.apache.polygene.api.query.QueryExpressions.eq;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+
+@Mixins( SchoolRepositoryService.SchoolRepositoryMixin.class )
+public interface SchoolRepositoryService
+    extends SchoolRepository
+{
+
+    class SchoolRepositoryMixin
+        implements SchoolRepository
+    {
+        @Structure
+        private UnitOfWorkFactory uowf;
+        @Structure
+        private QueryBuilderFactory qbf;
+
+        @Override
+        public Query<School> findAll()
+        {
+            return uowf.currentUnitOfWork().newQuery( qbf.newQueryBuilder( School.class ) );
+        }
+
+        @Override
+        public School findSchoolByName( String schoolName )
+        {
+            QueryBuilder<School> builder = qbf.newQueryBuilder( School.class );
+            SchoolEntity.SchoolState template = templateFor( SchoolEntity.SchoolState.class );
+            builder.where( eq( template.name(), schoolName ) );
+            Query<School> query = uowf.currentUnitOfWork().newQuery( builder );
+            return query.find();
+        }
+    }
+
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/assembly/StudentEntity.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/assembly/StudentEntity.java
new file mode 100644
index 0000000..da174ec
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/assembly/StudentEntity.java
@@ -0,0 +1,66 @@
+/*
+ *  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.polygene.envisage.school.domain.school.assembly;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.envisage.school.domain.school.School;
+import org.apache.polygene.envisage.school.domain.school.Student;
+import org.apache.polygene.envisage.school.domain.school.Subject;
+
+@Mixins( StudentEntity.StudentMixin.class )
+public interface StudentEntity
+    extends Student, HasIdentity
+{
+    class StudentMixin
+        implements Student
+    {
+        @This
+        private StudentState state;
+
+        @Override
+        public School school()
+        {
+            return state.school().get();
+        }
+
+        @Override
+        public Iterable<Subject> subjects()
+        {
+            return state.subjects();
+        }
+    }
+
+    interface StudentState
+    {
+        ManyAssociation<Subject> subjects();
+
+        Association<School> school();
+
+        Property<Identity> schoolId();
+    }
+
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/assembly/SubjectEntity.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/assembly/SubjectEntity.java
new file mode 100644
index 0000000..b89a40f
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/domain/school/assembly/SubjectEntity.java
@@ -0,0 +1,72 @@
+/*
+ *  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.polygene.envisage.school.domain.school.assembly;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.envisage.school.domain.school.School;
+import org.apache.polygene.envisage.school.domain.school.Subject;
+
+@Mixins( SubjectEntity.SubjectMixin.class )
+public interface SubjectEntity
+    extends Subject, HasIdentity
+{
+    class SubjectMixin
+        implements Subject
+    {
+        @This
+        private SubjectState state;
+
+        @Override
+        public String name()
+        {
+            return state.name().get();
+        }
+
+        @Override
+        public String description()
+        {
+            return state.description().get();
+        }
+
+        @Override
+        public School school()
+        {
+            return state.school().get();
+        }
+    }
+
+    interface SubjectState
+    {
+        Property<String> name();
+
+        Property<String> description();
+
+        Property<Identity> schoolId();
+
+        Association<School> school();
+    }
+
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/mail/Mail.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/mail/Mail.java
new file mode 100644
index 0000000..f736f85
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/mail/Mail.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.envisage.school.infrastructure.mail;
+
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.property.Property;
+
+public interface Mail
+{
+    Property<String[]> to();
+
+    @Optional
+    Property<String[]> ccs();
+
+    @Optional
+    Property<String[]> bccs();
+
+    Property<String> subject();
+
+    Property<String> message();
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/mail/MailService.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/mail/MailService.java
new file mode 100644
index 0000000..ecdb1b0
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/mail/MailService.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.envisage.school.infrastructure.mail;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.envisage.school.infrastructure.mail.assembly.MailServiceComposite;
+
+@Mixins( MailServiceComposite.MailServiceMixin.class )
+public interface MailService
+{
+    void send( Mail... mails );
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/mail/assembly/MailServiceAssembler.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/mail/assembly/MailServiceAssembler.java
new file mode 100644
index 0000000..f516d483
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/mail/assembly/MailServiceAssembler.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.envisage.school.infrastructure.mail.assembly;
+
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.apache.polygene.api.common.Visibility.application;
+
+public class MailServiceAssembler
+    implements Assembler
+{
+    @Override
+    public void assemble( ModuleAssembly assembly )
+        throws AssemblyException
+    {
+        assembly.values(
+            MailValue.class
+        ).visibleIn( application );
+
+        assembly.services(
+            MailServiceComposite.class
+        ).visibleIn( application );
+    }
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/mail/assembly/MailServiceComposite.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/mail/assembly/MailServiceComposite.java
new file mode 100644
index 0000000..4912254
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/mail/assembly/MailServiceComposite.java
@@ -0,0 +1,54 @@
+/*
+ *  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.polygene.envisage.school.infrastructure.mail.assembly;
+
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.envisage.school.config.mail.MailConfiguration;
+import org.apache.polygene.envisage.school.infrastructure.mail.Mail;
+import org.apache.polygene.envisage.school.infrastructure.mail.MailService;
+
+import java.util.Arrays;
+
+public interface MailServiceComposite
+    extends MailService
+{
+    class MailServiceMixin
+        implements MailService
+    {
+        @This
+        Configuration<MailConfiguration> config;
+
+        @Override
+        public void send( Mail... mails )
+        {
+            for( Mail mail : mails )
+            {
+                String[] recipients = mail.to().get();
+                String mailSubject = mail.subject().toString();
+                System.out.println(
+                    "Sent email to [" + Arrays.toString( recipients ) + "] with subject [" + mailSubject + "]"
+                );
+            }
+        }
+    }
+
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/mail/assembly/MailValue.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/mail/assembly/MailValue.java
new file mode 100644
index 0000000..e1a0e36
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/mail/assembly/MailValue.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.envisage.school.infrastructure.mail.assembly;
+
+import org.apache.polygene.envisage.school.infrastructure.mail.Mail;
+
+public interface MailValue
+    extends Mail
+{
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/persistence/PersistenceAssembler.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/persistence/PersistenceAssembler.java
new file mode 100644
index 0000000..ffdab72
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/infrastructure/persistence/PersistenceAssembler.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.envisage.school.infrastructure.persistence;
+
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+import org.apache.polygene.index.rdf.RdfIndexingEngineService;
+import org.apache.polygene.index.rdf.query.RdfQueryParserFactory;
+import org.apache.polygene.library.rdf.entity.EntityStateSerializer;
+import org.apache.polygene.library.rdf.entity.EntityTypeSerializer;
+import org.apache.polygene.library.rdf.repository.MemoryRepositoryService;
+
+import static org.apache.polygene.api.common.Visibility.application;
+
+public class PersistenceAssembler
+    implements Assembler
+{
+    @Override
+    public final void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.objects( EntityStateSerializer.class, EntityTypeSerializer.class );
+
+        module.services(
+            MemoryEntityStoreService.class,
+            // Query
+            RdfQueryParserFactory.class, RdfIndexingEngineService.class,
+            MemoryRepositoryService.class
+        ).visibleIn( application ).instantiateOnStartup();
+    }
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/AdminAssembler.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/AdminAssembler.java
new file mode 100644
index 0000000..e3be4ec
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/AdminAssembler.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.envisage.school.ui.admin;
+
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.envisage.school.ui.admin.pages.composites.ListSchoolsPageComposite;
+import org.apache.polygene.envisage.school.ui.admin.pages.composites.ListUserPageComposite;
+import org.apache.polygene.envisage.school.ui.admin.pages.composites.UserDetailPageComposite;
+
+import static org.apache.polygene.api.common.Visibility.layer;
+
+public class AdminAssembler
+    implements Assembler
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients(
+            ListSchoolsPageComposite.class,
+            ListUserPageComposite.class,
+            UserDetailPageComposite.class
+        ).visibleIn( layer );
+    }
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/ListUserPage.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/ListUserPage.java
new file mode 100644
index 0000000..6ac8f52
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/ListUserPage.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.envisage.school.ui.admin.pages;
+
+import org.apache.polygene.envisage.school.ui.admin.pages.mixins.Page;
+
+public interface ListUserPage
+    extends Page
+{
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/UserDetailPage.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/UserDetailPage.java
new file mode 100644
index 0000000..7bfc6dc
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/UserDetailPage.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.envisage.school.ui.admin.pages;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.envisage.school.domain.person.Person;
+import org.apache.polygene.envisage.school.ui.admin.pages.mixins.AuthenticationConcern;
+import org.apache.polygene.envisage.school.ui.admin.pages.mixins.DetailPage;
+import org.apache.polygene.envisage.school.ui.admin.pages.mixins.UserDetailPageMixin;
+
+@Concerns( AuthenticationConcern.class )
+@Mixins( UserDetailPageMixin.class )
+public interface UserDetailPage
+    extends DetailPage<Person>
+{
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/composites/ListSchoolsPageComposite.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/composites/ListSchoolsPageComposite.java
new file mode 100644
index 0000000..b7dcbc8
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/composites/ListSchoolsPageComposite.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.envisage.school.ui.admin.pages.composites;
+
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.envisage.school.domain.school.School;
+import org.apache.polygene.envisage.school.domain.school.SchoolRepository;
+import org.apache.polygene.envisage.school.ui.admin.pages.mixins.Page;
+
+@Mixins( ListSchoolsPageComposite.ListSchoolsPageMixin.class )
+public interface ListSchoolsPageComposite
+    extends Page, TransientComposite
+{
+
+    class ListSchoolsPageMixin
+        implements Page
+    {
+
+        @Service
+        Iterable<ServiceComposite> services;
+        @Service
+        SchoolRepository schools;
+
+        @Override
+        public String generateHtml()
+        {
+            String html = "<ul>";
+            for( School school : schools.findAll() )
+            {
+                html += "<li>" + school.name() + "</li>";
+            }
+            html += "</ul>";
+
+            return html;
+        }
+    }
+
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/composites/ListUserPageComposite.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/composites/ListUserPageComposite.java
new file mode 100644
index 0000000..82a98b0
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/composites/ListUserPageComposite.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.envisage.school.ui.admin.pages.composites;
+
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.envisage.school.ui.admin.pages.ListUserPage;
+
+public interface ListUserPageComposite
+    extends ListUserPage, TransientComposite
+{
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/composites/UserDetailPageComposite.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/composites/UserDetailPageComposite.java
new file mode 100644
index 0000000..def1a4a
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/composites/UserDetailPageComposite.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.envisage.school.ui.admin.pages.composites;
+
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.envisage.school.ui.admin.pages.UserDetailPage;
+
+public interface UserDetailPageComposite
+    extends UserDetailPage, TransientComposite
+{
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/mixins/AuthenticationConcern.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/mixins/AuthenticationConcern.java
new file mode 100644
index 0000000..e0e9fa8
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/mixins/AuthenticationConcern.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.envisage.school.ui.admin.pages.mixins;
+
+import org.apache.polygene.api.concern.ConcernOf;
+
+import static java.lang.System.err;
+
+public class AuthenticationConcern
+    extends ConcernOf<DetailPage>
+    implements Page, DetailPage
+{
+    @Override
+    public final String generateHtml()
+    {
+        err.println( "Bogus Authentication" );
+        return next.generateHtml();
+    }
+
+    @SuppressWarnings( "unchecked" )
+    @Override
+    public final void edit( Object context )
+    {
+        err.println( "Bogus Authentication" );
+        next.edit( context );
+    }
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/mixins/DetailPage.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/mixins/DetailPage.java
new file mode 100644
index 0000000..af63d6e
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/mixins/DetailPage.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.envisage.school.ui.admin.pages.mixins;
+
+public interface DetailPage<T>
+    extends Page
+{
+    void edit( T context );
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/mixins/Page.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/mixins/Page.java
new file mode 100644
index 0000000..cf0d5e1
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/mixins/Page.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.envisage.school.ui.admin.pages.mixins;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+@Mixins( PageMixin.class )
+public interface Page
+{
+    String generateHtml();
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/mixins/PageMixin.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/mixins/PageMixin.java
new file mode 100644
index 0000000..59b2c09
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/mixins/PageMixin.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.envisage.school.ui.admin.pages.mixins;
+
+public class PageMixin
+    implements Page
+{
+    @Override
+    public String generateHtml()
+    {
+        return null;
+    }
+}
diff --git a/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/mixins/UserDetailPageMixin.java b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/mixins/UserDetailPageMixin.java
new file mode 100644
index 0000000..251b7cf
--- /dev/null
+++ b/tools/envisage/src/test/java/org/apache/polygene/envisage/school/ui/admin/pages/mixins/UserDetailPageMixin.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.polygene.envisage.school.ui.admin.pages.mixins;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.envisage.school.domain.person.Person;
+import org.apache.polygene.envisage.school.ui.admin.pages.UserDetailPage;
+
+public class UserDetailPageMixin
+    implements UserDetailPage
+{
+    // Note: Don't remove
+    @Structure
+    private Layer layer;
+
+    // Note: Don't remove
+    public UserDetailPageMixin( @Structure Module module )
+    {
+    }
+
+    @Override
+    public void edit( Person context )
+    {
+        System.err.println( "Edit user [" + context + "]" );
+    }
+
+    @Override
+    public String generateHtml()
+    {
+        return "UserDetailPage";
+    }
+}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/sample/EnvisageSample.java b/tools/envisage/src/test/java/org/qi4j/envisage/sample/EnvisageSample.java
deleted file mode 100644
index add3dbb..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/sample/EnvisageSample.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.sample;
-
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkCompletionException;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.envisage.Envisage;
-import org.qi4j.index.rdf.assembly.RdfMemoryStoreAssembler;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-import static org.qi4j.test.util.Assume.assumeDisplayPresent;
-
-public class EnvisageSample
-    extends AbstractQi4jTest
-{
-
-    public static void main( String[] args )
-        throws Exception
-    {
-        EnvisageSample sample = new EnvisageSample();
-        sample.runSample();
-    }
-
-    @BeforeClass
-    public static void assumeDisplay()
-    {
-        assumeDisplayPresent();
-    }
-
-    @Test
-    public void runSample()
-        throws Exception
-    {
-        setUp();
-        createTestData();
-        //createTestData2();
-        //createTestData3();
-
-        new Envisage().run( applicationModel );
-//        Thread.sleep( 1113000 );
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( CarEntity.class );
-        module.entities( AnimalEntity.class );
-        new RdfMemoryStoreAssembler().assemble( module );
-        new EntityTestAssembler().assemble( module );
-    }
-
-    public void createTestData()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            createCar( "Volvo", "S80", 2007 );
-            createCar( "Volvo", "C70", 2006 );
-            createCar( "Ford", "Transit", 2007 );
-            createCar( "Ford", "Mustang", 2007 );
-            createCar( "Ford", "Mustang", 2006 );
-            createCar( "Ford", "Mustang", 2005 );
-
-            createAnimal( "Cat", "Miaow" );
-            createAnimal( "Duck", "Kwek Kwek" );
-            createAnimal( "Dog", "Guk Guk" );
-            createAnimal( "Cow", "Moooo" );
-
-            uow.complete();
-        }
-        catch( UnitOfWorkCompletionException e )
-        {
-            // Can not happen.
-            e.printStackTrace();
-        }
-    }
-
-    private String createCar( String manufacturer, String model, int year )
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        EntityBuilder<Car> builder = uow.newEntityBuilder( Car.class );
-        Car prototype = builder.instanceFor( CarEntity.class );
-        prototype.manufacturer().set( manufacturer );
-        prototype.model().set( model );
-        prototype.year().set( year );
-        CarEntity entity = (CarEntity) builder.newInstance();
-        return entity.identity().get();
-    }
-
-    private String createAnimal( String name, String sound )
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        EntityBuilder<Animal> builder = uow.newEntityBuilder( Animal.class );
-        Animal prototype = builder.instanceFor( AnimalEntity.class );
-        prototype.name().set( name );
-        prototype.sound().set( sound );
-        AnimalEntity entity = (AnimalEntity) builder.newInstance();
-        return entity.identity().get();
-    }
-
-    public interface Car
-    {
-        Property<String> manufacturer();
-
-        Property<String> model();
-
-        Property<Integer> year();
-    }
-
-    public interface CarEntity
-        extends Car, EntityComposite
-    {
-    }
-
-    public interface Animal
-    {
-        Property<String> name();
-
-        Property<String> sound();
-    }
-
-    public interface AnimalEntity
-        extends Animal, EntityComposite
-    {
-    }
-
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/EnvisageSchoolSample.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/EnvisageSchoolSample.java
deleted file mode 100644
index b5ce205..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/EnvisageSchoolSample.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2009, Tony Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school;
-
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.bootstrap.Energy4Java;
-import org.qi4j.envisage.Envisage;
-
-public class EnvisageSchoolSample
-{
-    // START SNIPPET: envisage
-    public static void main( String[] args )
-        throws Exception
-    {
-        Energy4Java energy4Java = new Energy4Java();
-
-        ApplicationDescriptor applicationModel
-                              = energy4Java.newApplicationModel( new SchoolAssembler() );
-
-        new Envisage().run( applicationModel );
-    }
-    // END SNIPPET: envisage
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/SchoolAssembler.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/SchoolAssembler.java
deleted file mode 100644
index 3d193a4..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/SchoolAssembler.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school;
-
-import org.qi4j.bootstrap.ApplicationAssembler;
-import org.qi4j.bootstrap.ApplicationAssembly;
-import org.qi4j.bootstrap.ApplicationAssemblyFactory;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.LayerAssembly;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.envisage.school.config.persistence.PersistenceConfigAssembler;
-import org.qi4j.envisage.school.domain.person.assembly.PersonModelAssembler;
-import org.qi4j.envisage.school.domain.school.assembly.SchoolModelAssembler;
-import org.qi4j.envisage.school.infrastructure.mail.assembly.MailServiceAssembler;
-import org.qi4j.envisage.school.infrastructure.persistence.PersistenceAssembler;
-import org.qi4j.envisage.school.ui.admin.AdminAssembler;
-
-/**
- * Application assembler for the School sample
- */
-public class SchoolAssembler
-    implements ApplicationAssembler
-{
-    @Override
-    public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-        throws AssemblyException
-    {
-        final ApplicationAssembly appAssembly = applicationFactory.newApplicationAssembly();
-        appAssembly.setName( "School" );
-
-        // Create layers
-        LayerAssembly layerUI = createUILayer( appAssembly );
-        LayerAssembly layerDomain = createDomainLayer( appAssembly );
-        LayerAssembly layerInfra = createInfrastructureLayer( appAssembly );
-        LayerAssembly layerConfig = createConfigLayer( appAssembly );
-
-        layerUI.uses( layerDomain );
-        layerDomain.uses( layerInfra );
-        layerDomain.uses( layerConfig );
-
-        return appAssembly;
-    }
-
-    private LayerAssembly createInfrastructureLayer( ApplicationAssembly appAssembly )
-        throws AssemblyException
-    {
-        LayerAssembly layerInfrastructure = appAssembly.layer( "Infrastructure" );
-
-        ModuleAssembly moduleMail = layerInfrastructure.module( "Mail" );
-        new MailServiceAssembler().assemble( moduleMail );
-
-        ModuleAssembly modulePersistence = layerInfrastructure.module( "Persistence" );
-        new PersistenceAssembler().assemble( modulePersistence );
-
-        return layerInfrastructure;
-    }
-
-    private LayerAssembly createConfigLayer( ApplicationAssembly appAssembly )
-        throws AssemblyException
-    {
-        LayerAssembly layerConfig = appAssembly.layer( "configuration" );
-
-        ModuleAssembly persistenceConfig = layerConfig.module( "persistence" );
-        new PersistenceConfigAssembler().assemble( persistenceConfig );
-        return layerConfig;
-    }
-
-    private LayerAssembly createDomainLayer( ApplicationAssembly appAssembly )
-        throws AssemblyException
-    {
-        LayerAssembly layerDomain = appAssembly.layer( "domain" );
-
-        ModuleAssembly modulePerson = layerDomain.module( "person" );
-        new PersonModelAssembler().assemble( modulePerson );
-
-        ModuleAssembly moduleSchool = layerDomain.module( "school" );
-        new SchoolModelAssembler().assemble( moduleSchool );
-
-        return layerDomain;
-    }
-
-    private LayerAssembly createUILayer( ApplicationAssembly appAssembly )
-        throws AssemblyException
-    {
-        LayerAssembly layerUI = appAssembly.layer( "UI" );
-
-        // Add admin
-        ModuleAssembly moduleAdmin = layerUI.module( "admin" );
-        new AdminAssembler().assemble( moduleAdmin );
-
-        return layerUI;
-    }
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/config/mail/MailConfigAssembler.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/config/mail/MailConfigAssembler.java
deleted file mode 100644
index a10f68c..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/config/mail/MailConfigAssembler.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.config.mail;
-
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-public class MailConfigAssembler
-    implements Assembler
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( MailConfiguration.class );
-    }
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/config/mail/MailConfiguration.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/config/mail/MailConfiguration.java
deleted file mode 100644
index 7fd2a0b..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/config/mail/MailConfiguration.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.config.mail;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-public interface MailConfiguration
-    extends ConfigurationComposite
-{
-    @UseDefaults
-    Property<String> host();
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/config/persistence/PersistenceConfigAssembler.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/config/persistence/PersistenceConfigAssembler.java
deleted file mode 100644
index 7b52ebf..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/config/persistence/PersistenceConfigAssembler.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.config.persistence;
-
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-
-import static org.qi4j.api.common.Visibility.layer;
-
-public class PersistenceConfigAssembler
-    implements Assembler
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services(
-            UuidIdentityGeneratorService.class,
-            MemoryEntityStoreService.class
-        ).visibleIn( layer ).instantiateOnStartup();
-    }
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/person/Person.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/person/Person.java
deleted file mode 100644
index 1f0f7dd..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/person/Person.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.domain.person;
-
-public interface Person
-{
-    String firstName();
-
-    String lastName();
-
-    Iterable<Role> roles();
-
-    void addRole( Role role );
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/person/Role.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/person/Role.java
deleted file mode 100644
index a396d83..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/person/Role.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.domain.person;
-
-public interface Role
-{
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/person/assembly/PersonEntity.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/person/assembly/PersonEntity.java
deleted file mode 100644
index 91e3698..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/person/assembly/PersonEntity.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.domain.person.assembly;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.envisage.school.domain.person.Person;
-import org.qi4j.envisage.school.domain.person.Role;
-
-@Mixins( PersonEntity.PersonMixin.class )
-public interface PersonEntity
-    extends Person, EntityComposite
-{
-    class PersonMixin
-        implements Person
-    {
-        @This
-        private PersonState state;
-
-        @Override
-        public String firstName()
-        {
-            return state.firstName().get();
-        }
-
-        @Override
-        public String lastName()
-        {
-            return state.lastName().get();
-        }
-
-        @Override
-        public Iterable<Role> roles()
-        {
-            return state.roles();
-        }
-
-        @Override
-        public void addRole( Role role )
-        {
-            state.roles().add( 0, role );
-        }
-    }
-
-    static interface PersonState
-    {
-        Property<String> firstName();
-
-        Property<String> lastName();
-
-        ManyAssociation<Role> roles();
-    }
-
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/person/assembly/PersonModelAssembler.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/person/assembly/PersonModelAssembler.java
deleted file mode 100644
index 3c5d646..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/person/assembly/PersonModelAssembler.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.domain.person.assembly;
-
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.envisage.school.domain.person.initialdata.SamplePersonInitialData;
-
-import static org.qi4j.api.common.Visibility.application;
-import static org.qi4j.api.common.Visibility.layer;
-
-public final class PersonModelAssembler
-    implements Assembler
-{
-    @Override
-    public final void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( PersonEntity.class )
-            .visibleIn( layer );
-
-        module.services( SamplePersonInitialData.class )
-            .visibleIn( application )
-            .instantiateOnStartup();
-    }
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/person/initialdata/SamplePersonInitialData.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/person/initialdata/SamplePersonInitialData.java
deleted file mode 100644
index 911c944..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/person/initialdata/SamplePersonInitialData.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.domain.person.initialdata;
-
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.envisage.school.domain.person.Person;
-import org.qi4j.envisage.school.domain.person.assembly.PersonEntity;
-
-@Mixins( SamplePersonInitialData.SamplePersonBootstrapMixin.class )
-@Activators( SamplePersonInitialData.Activator.class )
-public interface SamplePersonInitialData
-    extends ServiceComposite
-{
-    String EDWARD = "edward";
-    String NICLAS = "niclas";
-    String RICKARD = "rickard";
-
-    void insertInitialData()
-        throws Exception;
-
-    class Activator
-        extends ActivatorAdapter<ServiceReference<SamplePersonInitialData>>
-    {
-
-        @Override
-        public void afterActivation( ServiceReference<SamplePersonInitialData> activated )
-            throws Exception
-        {
-            activated.get().insertInitialData();
-        }
-
-    }
-
-    public abstract class SamplePersonBootstrapMixin
-        implements SamplePersonInitialData
-    {
-        private static final String[][] DATAS =
-        {
-            {
-                EDWARD, "Edward", "Yakop"
-            },
-            {
-                NICLAS, "Niclas", "Hedhman"
-            },
-            {
-                RICKARD, "Rickard", "Öberg"
-            }
-        };
-
-        @Structure
-        private UnitOfWorkFactory uowf;
-
-        @Override
-        public void insertInitialData()
-            throws Exception
-        {
-            UnitOfWork uow = uowf.currentUnitOfWork();
-
-            for( String[] data : DATAS )
-            {
-                String personId = data[ 0];
-                String firstName = data[ 1];
-                String lastName = data[ 2];
-                createPerson( uow, personId, firstName, lastName );
-            }
-
-            uow.complete();
-        }
-
-        private void createPerson( UnitOfWork uow, String personId, String firstName, String lastName )
-        {
-            EntityBuilder<Person> person = uow.newEntityBuilder( Person.class, personId );
-
-            PersonEntity.PersonState state = person.instanceFor( PersonEntity.PersonState.class );
-            state.firstName().set( firstName );
-            state.lastName().set( lastName );
-
-            person.newInstance();
-        }
-
-    }
-
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/School.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/School.java
deleted file mode 100644
index 0a59e54..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/School.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.domain.school;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.query.Query;
-import org.qi4j.envisage.school.domain.person.Person;
-
-public interface School
-{
-    String name();
-
-    Query<Subject> availableSubjects();
-
-    Query<Student> students();
-
-    void enroll( @Optional Person person, Subject subject );
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/SchoolRepository.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/SchoolRepository.java
deleted file mode 100644
index f84debf..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/SchoolRepository.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.domain.school;
-
-import org.qi4j.api.query.Query;
-
-public interface SchoolRepository
-{
-    Query<School> findAll();
-
-    School findSchoolByName( String schoolName );
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/Student.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/Student.java
deleted file mode 100644
index b3731cb..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/Student.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.domain.school;
-
-import org.qi4j.envisage.school.domain.person.Role;
-
-public interface Student
-    extends Role
-{
-    School school();
-
-    Iterable<Subject> subjects();
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/Subject.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/Subject.java
deleted file mode 100644
index 85c734c..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/Subject.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.domain.school;
-
-public interface Subject
-{
-    String name();
-
-    String description();
-
-    School school();
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/assembly/SchoolEntity.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/assembly/SchoolEntity.java
deleted file mode 100644
index 8e2c733..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/assembly/SchoolEntity.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.domain.school.assembly;
-
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.entity.Identity;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.QueryBuilderFactory;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.envisage.school.domain.person.Person;
-import org.qi4j.envisage.school.domain.school.School;
-import org.qi4j.envisage.school.domain.school.Student;
-import org.qi4j.envisage.school.domain.school.Subject;
-import org.qi4j.envisage.school.infrastructure.mail.MailService;
-
-import static org.qi4j.api.query.QueryExpressions.eq;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-@Mixins( SchoolEntity.SchoolMixin.class )
-public interface SchoolEntity
-    extends School, EntityComposite
-{
-    class SchoolMixin
-        implements School
-    {
-        @Structure
-        private UnitOfWorkFactory uowf;
-        @Structure
-        private QueryBuilderFactory qbf;
-        @This
-        private SchoolState state;
-        @Service
-        private MailService mailer;
-        private final String schoolId;
-
-        public SchoolMixin( @This Identity identity )
-        {
-            schoolId = identity.identity().get();
-        }
-
-        @Override
-        public String name()
-        {
-            return state.name().get();
-        }
-
-        @Override
-        public Query<Subject> availableSubjects()
-        {
-            UnitOfWork uow = uowf.currentUnitOfWork();
-            try
-            {
-                QueryBuilder<Subject> builder = qbf.newQueryBuilder( Subject.class );
-                SubjectEntity.SubjectState subject = templateFor( SubjectEntity.SubjectState.class );
-                builder.where( eq( subject.schoolId(), schoolId ) );
-                return uow.newQuery( builder );
-            }
-            finally
-            {
-                uow.pause();
-            }
-        }
-
-        @Override
-        public Query<Student> students()
-        {
-            UnitOfWork uow = uowf.currentUnitOfWork();
-            try
-            {
-                QueryBuilder<Student> builder = qbf.newQueryBuilder( Student.class );
-                StudentEntity.StudentState studentState = templateFor( StudentEntity.StudentState.class );
-                builder.where( eq( studentState.schoolId(), schoolId ) );
-                return uow.newQuery( builder );
-            }
-            finally
-            {
-                uow.pause();
-            }
-        }
-
-        @Override
-        public void enroll( Person person, Subject subject )
-        {
-            // TODO
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    static interface SchoolState
-    {
-        Property<String> name();
-    }
-
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/assembly/SchoolModelAssembler.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/assembly/SchoolModelAssembler.java
deleted file mode 100644
index d89a607..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/assembly/SchoolModelAssembler.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.domain.school.assembly;
-
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-import static org.qi4j.api.common.Visibility.application;
-import static org.qi4j.api.common.Visibility.layer;
-
-public final class SchoolModelAssembler
-    implements Assembler
-{
-    @Override
-    public final void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities(
-            StudentEntity.class,
-            SchoolEntity.class,
-            SubjectEntity.class
-        ).visibleIn( layer );
-
-        module.services( SchoolRepositoryService.class )
-            .visibleIn( application );
-    }
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/assembly/SchoolRepositoryService.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/assembly/SchoolRepositoryService.java
deleted file mode 100644
index 7b495dc..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/assembly/SchoolRepositoryService.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.domain.school.assembly;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.query.QueryBuilder;
-import org.qi4j.api.query.QueryBuilderFactory;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.envisage.school.domain.school.School;
-import org.qi4j.envisage.school.domain.school.SchoolRepository;
-
-import static org.qi4j.api.query.QueryExpressions.eq;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-@Mixins( SchoolRepositoryService.SchoolRepositoryMixin.class )
-public interface SchoolRepositoryService
-    extends SchoolRepository, ServiceComposite
-{
-
-    class SchoolRepositoryMixin
-        implements SchoolRepository
-    {
-        @Structure
-        private UnitOfWorkFactory uowf;
-        @Structure
-        private QueryBuilderFactory qbf;
-
-        @Override
-        public Query<School> findAll()
-        {
-            return uowf.currentUnitOfWork().newQuery( qbf.newQueryBuilder( School.class ) );
-        }
-
-        @Override
-        public School findSchoolByName( String schoolName )
-        {
-            QueryBuilder<School> builder = qbf.newQueryBuilder( School.class );
-            SchoolEntity.SchoolState template = templateFor( SchoolEntity.SchoolState.class );
-            builder.where( eq( template.name(), schoolName ) );
-            Query<School> query = uowf.currentUnitOfWork().newQuery( builder );
-            return query.find();
-        }
-    }
-
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/assembly/StudentEntity.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/assembly/StudentEntity.java
deleted file mode 100644
index 55c77c8..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/assembly/StudentEntity.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.domain.school.assembly;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.envisage.school.domain.school.School;
-import org.qi4j.envisage.school.domain.school.Student;
-import org.qi4j.envisage.school.domain.school.Subject;
-
-@Mixins( StudentEntity.StudentMixin.class )
-public interface StudentEntity
-    extends Student, EntityComposite
-{
-    class StudentMixin
-        implements Student
-    {
-        @This
-        private StudentState state;
-
-        @Override
-        public School school()
-        {
-            return state.school().get();
-        }
-
-        @Override
-        public Iterable<Subject> subjects()
-        {
-            return state.subjects();
-        }
-    }
-
-    static interface StudentState
-    {
-        ManyAssociation<Subject> subjects();
-
-        Association<School> school();
-
-        Property<String> schoolId();
-    }
-
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/assembly/SubjectEntity.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/assembly/SubjectEntity.java
deleted file mode 100644
index 981f336..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/domain/school/assembly/SubjectEntity.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2009, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.domain.school.assembly;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.envisage.school.domain.school.School;
-import org.qi4j.envisage.school.domain.school.Subject;
-
-@Mixins( SubjectEntity.SubjectMixin.class )
-public interface SubjectEntity
-    extends Subject, EntityComposite
-{
-    public class SubjectMixin
-        implements Subject
-    {
-        @This
-        private SubjectState state;
-
-        @Override
-        public String name()
-        {
-            return state.name().get();
-        }
-
-        @Override
-        public String description()
-        {
-            return state.description().get();
-        }
-
-        @Override
-        public School school()
-        {
-            return state.school().get();
-        }
-    }
-
-    static interface SubjectState
-    {
-        Property<String> name();
-
-        Property<String> description();
-
-        Property<String> schoolId();
-
-        Association<School> school();
-    }
-
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/mail/Mail.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/mail/Mail.java
deleted file mode 100644
index 5a558c0..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/mail/Mail.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.infrastructure.mail;
-
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.property.Property;
-
-public interface Mail
-{
-    Property<String[]> to();
-
-    @Optional
-    Property<String[]> ccs();
-
-    @Optional
-    Property<String[]> bccs();
-
-    Property<String> subject();
-
-    Property<String> message();
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/mail/MailService.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/mail/MailService.java
deleted file mode 100644
index f24d502..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/mail/MailService.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.infrastructure.mail;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.envisage.school.infrastructure.mail.assembly.MailServiceComposite;
-
-@Mixins( MailServiceComposite.MailServiceMixin.class )
-public interface MailService
-{
-    void send( Mail... mails );
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/mail/assembly/MailServiceAssembler.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/mail/assembly/MailServiceAssembler.java
deleted file mode 100644
index e9e861f..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/mail/assembly/MailServiceAssembler.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.infrastructure.mail.assembly;
-
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-
-import static org.qi4j.api.common.Visibility.application;
-
-public class MailServiceAssembler
-    implements Assembler
-{
-    @Override
-    public void assemble( ModuleAssembly assembly )
-        throws AssemblyException
-    {
-        assembly.values(
-            MailValue.class
-        ).visibleIn( application );
-
-        assembly.services(
-            MailServiceComposite.class
-        ).visibleIn( application );
-    }
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/mail/assembly/MailServiceComposite.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/mail/assembly/MailServiceComposite.java
deleted file mode 100644
index d384d56..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/mail/assembly/MailServiceComposite.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.infrastructure.mail.assembly;
-
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.envisage.school.config.mail.MailConfiguration;
-import org.qi4j.envisage.school.infrastructure.mail.Mail;
-import org.qi4j.envisage.school.infrastructure.mail.MailService;
-
-import java.util.Arrays;
-
-public interface MailServiceComposite
-    extends MailService, ServiceComposite
-{
-    public static class MailServiceMixin
-        implements MailService
-    {
-        @This
-        Configuration<MailConfiguration> config;
-
-        @Override
-        public void send( Mail... mails )
-        {
-            for( Mail mail : mails )
-            {
-                String[] recipients = mail.to().get();
-                String mailSubject = mail.subject().toString();
-                System.out.println(
-                    "Sent email to [" + Arrays.toString( recipients ) + "] with subject [" + mailSubject + "]"
-                );
-            }
-        }
-    }
-
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/mail/assembly/MailValue.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/mail/assembly/MailValue.java
deleted file mode 100644
index 1b60f1e..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/mail/assembly/MailValue.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.infrastructure.mail.assembly;
-
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.envisage.school.infrastructure.mail.Mail;
-
-public interface MailValue
-    extends Mail, ValueComposite
-{
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/persistence/PersistenceAssembler.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/persistence/PersistenceAssembler.java
deleted file mode 100644
index 5cfac81..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/infrastructure/persistence/PersistenceAssembler.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.infrastructure.persistence;
-
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.index.rdf.RdfIndexingEngineService;
-import org.qi4j.index.rdf.query.RdfQueryParserFactory;
-import org.qi4j.library.rdf.entity.EntityStateSerializer;
-import org.qi4j.library.rdf.entity.EntityTypeSerializer;
-import org.qi4j.library.rdf.repository.MemoryRepositoryService;
-import org.qi4j.spi.uuid.UuidIdentityGeneratorService;
-
-import static org.qi4j.api.common.Visibility.application;
-
-public class PersistenceAssembler
-    implements Assembler
-{
-    @Override
-    public final void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.objects( EntityStateSerializer.class, EntityTypeSerializer.class );
-
-        module.services(
-            UuidIdentityGeneratorService.class,
-            MemoryEntityStoreService.class,
-            // Query
-            RdfQueryParserFactory.class, RdfIndexingEngineService.class,
-            MemoryRepositoryService.class
-        ).visibleIn( application ).instantiateOnStartup();
-    }
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/AdminAssembler.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/AdminAssembler.java
deleted file mode 100644
index 9d6844d..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/AdminAssembler.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.ui.admin;
-
-import org.qi4j.bootstrap.Assembler;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.envisage.school.ui.admin.pages.composites.ListSchoolsPageComposite;
-import org.qi4j.envisage.school.ui.admin.pages.composites.ListUserPageComposite;
-import org.qi4j.envisage.school.ui.admin.pages.composites.UserDetailPageComposite;
-
-import static org.qi4j.api.common.Visibility.layer;
-
-public class AdminAssembler
-    implements Assembler
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients(
-            ListSchoolsPageComposite.class,
-            ListUserPageComposite.class,
-            UserDetailPageComposite.class
-        ).visibleIn( layer );
-    }
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/ListUserPage.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/ListUserPage.java
deleted file mode 100644
index 0b5887f..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/ListUserPage.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.ui.admin.pages;
-
-import org.qi4j.envisage.school.ui.admin.pages.mixins.Page;
-
-public interface ListUserPage
-    extends Page
-{
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/UserDetailPage.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/UserDetailPage.java
deleted file mode 100644
index f90e897..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/UserDetailPage.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.ui.admin.pages;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.envisage.school.domain.person.Person;
-import org.qi4j.envisage.school.ui.admin.pages.mixins.AuthenticationConcern;
-import org.qi4j.envisage.school.ui.admin.pages.mixins.DetailPage;
-import org.qi4j.envisage.school.ui.admin.pages.mixins.UserDetailPageMixin;
-
-@Concerns( AuthenticationConcern.class )
-@Mixins( UserDetailPageMixin.class )
-public interface UserDetailPage
-    extends DetailPage<Person>
-{
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/composites/ListSchoolsPageComposite.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/composites/ListSchoolsPageComposite.java
deleted file mode 100644
index fae0c10..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/composites/ListSchoolsPageComposite.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.ui.admin.pages.composites;
-
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.envisage.school.domain.school.School;
-import org.qi4j.envisage.school.domain.school.SchoolRepository;
-import org.qi4j.envisage.school.ui.admin.pages.mixins.Page;
-
-@Mixins( ListSchoolsPageComposite.ListSchoolsPageMixin.class )
-public interface ListSchoolsPageComposite
-    extends Page, TransientComposite
-{
-
-    class ListSchoolsPageMixin
-        implements Page
-    {
-
-        @Service
-        Iterable<ServiceComposite> services;
-        @Service
-        SchoolRepository schools;
-
-        @Override
-        public String generateHtml()
-        {
-            String html = "<ul>";
-            for( School school : schools.findAll() )
-            {
-                html += "<li>" + school.name() + "</li>";
-            }
-            html += "</ul>";
-
-            return html;
-        }
-    }
-
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/composites/ListUserPageComposite.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/composites/ListUserPageComposite.java
deleted file mode 100644
index af5233b..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/composites/ListUserPageComposite.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.ui.admin.pages.composites;
-
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.envisage.school.ui.admin.pages.ListUserPage;
-
-public interface ListUserPageComposite
-    extends ListUserPage, TransientComposite
-{
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/composites/UserDetailPageComposite.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/composites/UserDetailPageComposite.java
deleted file mode 100644
index 1f3161b..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/composites/UserDetailPageComposite.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.ui.admin.pages.composites;
-
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.envisage.school.ui.admin.pages.UserDetailPage;
-
-public interface UserDetailPageComposite
-    extends UserDetailPage, TransientComposite
-{
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/mixins/AuthenticationConcern.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/mixins/AuthenticationConcern.java
deleted file mode 100644
index cef3c05..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/mixins/AuthenticationConcern.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.ui.admin.pages.mixins;
-
-import org.qi4j.api.concern.ConcernOf;
-
-import static java.lang.System.err;
-
-public class AuthenticationConcern
-    extends ConcernOf<DetailPage>
-    implements Page, DetailPage
-{
-    @Override
-    public final String generateHtml()
-    {
-        err.println( "Bogus Authentication" );
-        return next.generateHtml();
-    }
-
-    @SuppressWarnings( "unchecked" )
-    @Override
-    public final void edit( Object context )
-    {
-        err.println( "Bogus Authentication" );
-        next.edit( context );
-    }
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/mixins/DetailPage.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/mixins/DetailPage.java
deleted file mode 100644
index df6ff19..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/mixins/DetailPage.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.ui.admin.pages.mixins;
-
-public interface DetailPage<T>
-    extends Page
-{
-    void edit( T context );
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/mixins/Page.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/mixins/Page.java
deleted file mode 100644
index f060430..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/mixins/Page.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.ui.admin.pages.mixins;
-
-import org.qi4j.api.mixin.Mixins;
-
-@Mixins( PageMixin.class )
-public interface Page
-{
-    String generateHtml();
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/mixins/PageMixin.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/mixins/PageMixin.java
deleted file mode 100644
index a5c522f..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/mixins/PageMixin.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.ui.admin.pages.mixins;
-
-public class PageMixin
-    implements Page
-{
-    @Override
-    public String generateHtml()
-    {
-        return null;
-    }
-}
diff --git a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/mixins/UserDetailPageMixin.java b/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/mixins/UserDetailPageMixin.java
deleted file mode 100644
index 110aa17..0000000
--- a/tools/envisage/src/test/java/org/qi4j/envisage/school/ui/admin/pages/mixins/UserDetailPageMixin.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.envisage.school.ui.admin.pages.mixins;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.structure.Layer;
-import org.qi4j.api.structure.Module;
-import org.qi4j.envisage.school.domain.person.Person;
-import org.qi4j.envisage.school.ui.admin.pages.UserDetailPage;
-
-public class UserDetailPageMixin
-    implements UserDetailPage
-{
-    // Note: Don't remove
-    @Structure
-    private Layer layer;
-
-    // Note: Don't remove
-    public UserDetailPageMixin( @Structure Module module )
-    {
-    }
-
-    @Override
-    public void edit( Person context )
-    {
-        System.err.println( "Edit user [" + context + "]" );
-    }
-
-    @Override
-    public String generateHtml()
-    {
-        return "UserDetailPage";
-    }
-}
diff --git a/tools/generator-polygene/README.md b/tools/generator-polygene/README.md
new file mode 100644
index 0000000..40f68fc
--- /dev/null
+++ b/tools/generator-polygene/README.md
@@ -0,0 +1,47 @@
+# Apache Polygene™ Project Generator
+
+
+## What is Apache Polygene™
+
+The short answer is that **Apache Polygene™** is a community based effort exploring Composite Oriented Programming for
+domain centric application development. This includes evolved concepts from
+[Aspect Oriented Programming](https://en.wikipedia.org/wiki/Aspect-oriented_programming),
+[Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection)
+and [Domain Driven Design](https://en.wikipedia.org/wiki/Domain-driven_design).
+
+Please see [polygene.apache.org](https://polygene.apache.org) for more information.
+
+
+## How to install
+
+You will need node installed in your machine. In case you don't have it
+(you can check this typing `node --version` in your terminal) please visit this [link](https://nodejs.org/en/download/).
+
+Then run the following command:
+
+    $ npm install -g yo generator-polygene
+
+
+## Running the generator
+
+    $ yo polygene
+
+
+## Licensing
+
+    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.
+
+
diff --git a/tools/generator-polygene/app/index.js b/tools/generator-polygene/app/index.js
new file mode 100644
index 0000000..e106698
--- /dev/null
+++ b/tools/generator-polygene/app/index.js
@@ -0,0 +1,409 @@
+/*
+ *  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.
+ *
+ *
+ */
+
+var generators = require('yeoman-generator');
+var fs = require('fs');
+
+var polygeneVersion = require(__dirname + '/../package.json').polygene_version;
+
+var polygene = {};
+
+module.exports = generators.Base.extend(
+    {
+        constructor: function () {
+            generators.Base.apply(this, arguments);
+
+            this.option('import-model', {
+                name: "import",
+                desc: 'Reads a model file and creates the domain model for it.',
+                type: String,
+                default: "./model.json",
+                hide: false
+            });
+
+            this.option('export-model', {
+                name: "export",
+                desc: 'Writes the model of the application into a json file.',
+                type: String,
+                default: "exported-model",
+                hide: false
+            });
+
+            this.option('noPrompt', {
+                name: "noPrompt",
+                desc: 'If specified, the interactive prompts will be disabled.',
+                type: Boolean,
+                default: false,
+                hide: false
+            });
+
+            if (this.options.import) {
+                polygene = importModel(this.options.import);
+                polygene.name = polygene.name ? polygene.name : firstUpper(this.appname);
+                polygene.packageName = polygene.packageName ? polygene.packageName : ("com.acme." + this.appname);
+                polygene.applicationtype = "Rest API";
+                polygene.features = polygene.features ? polygene.features : [];
+                polygene.modules = polygene.modules ? polygene.modules : {};
+                polygene.indexing = polygene.indexing ? polygene.indexing : null;
+                polygene.entitystore = polygene.entitystore ? polygene.entitystore : null;
+                polygene.caching = polygene.caching ? polygene.caching : null;
+                polygene.serialization = polygene.serialization ? polygene.serialization : null;
+            }
+        },
+
+        prompting: function () {
+            if (this.options.noPrompt) {
+                return this.prompt([]);
+            }
+            else {
+                return this.prompt(
+                    [
+                        {
+                            type: 'input',
+                            name: 'name',
+                            message: 'Your project name',
+                            default: polygene.name ? polygene.name : firstUpper(this.appname)
+                        },
+                        {
+                            type: 'input',
+                            name: 'packageName',
+                            message: 'Java package name',
+                            default: polygene.packageName ? polygene.packageName : "com.acme"
+                        },
+                        {
+                            type: 'list',
+                            name: 'applicationtype',
+                            choices: [
+                                'Command Line',
+                                // 'Web Application',
+                                'Rest API'
+                            ],
+                            message: 'what type of application do you want to create?',
+                            default: polygene.applicationtype ? polygene.applicationtype : "Rest API"
+                        },
+                        {
+                            type: 'list',
+                            name: 'entitystore',
+                            choices: [
+                                'Cassandra',
+                                'File',
+                                'DerbySQL',
+                                'Geode',
+                                'H2SQL',
+                                'Hazelcast',
+                                'JClouds',
+                                'Jdbm',
+                                'LevelDB',
+                                'Memory',
+                                'MongoDB',
+                                'MySQL',
+                                'Preferences',
+                                'Redis',
+                                'Riak',
+                                'PostgreSQL',
+                                'SQLite'
+                            ],
+                            message: 'Which entity store do you want to use?',
+                            default: polygene.entitystore ? polygene.entitystore : "Memory"
+                        },
+                        {
+                            type: 'list',
+                            name: 'indexing',
+                            choices: [
+                                'Rdf',
+                                'ElasticSearch',
+                                'Solr',
+                                'SQL'
+                            ],
+                            message: 'Which indexing system do you want to use?',
+                            default: polygene.indexing ? polygene.indexing : "Rdf"
+                        },
+                        {
+                            type: 'list',
+                            name: 'caching',
+                            choices: [
+                                'None',
+                                'Memcache',
+                                'EhCache'
+                            ],
+                            message: 'Which caching system do you want to use?',
+                            default: polygene.caching ? polygene.caching : "None"
+                        },
+                        {
+                            type: 'list',
+                            name: 'serialization',
+                            choices: [
+                                'JavaxJson',
+                                'JavaxXml',
+                                'MessagePack'
+                            ],
+                            message: 'Which serialization system do you want to use?',
+                            default: polygene.serialization ? polygene.serialization : "JavaxJson"
+                        },
+                        {
+                            type: 'list',
+                            name: 'metrics',
+                            choices: [
+                                'None',
+                                'Codahale'
+                            ],
+                            message: 'Which metrics capturing system do you want to use?',
+                            default: polygene.metrics ? polygene.metrics : "None"
+                        },
+                        {
+                            type: 'checkbox',
+                            name: 'features',
+                            choices: [
+                                // 'alarms'
+                                // 'circuit breakers'
+                                // 'file transactions'
+                                // 'logging'
+                                'jmx',
+                                // 'spring integration'
+                                // 'scheduling'
+                                'mixin scripting',
+                                'security'
+                                // ,'version migration'
+                            ],
+                            message: 'Other features?',
+                            default: polygene.features ? polygene.features : []
+                        }
+                    ]
+                ).then(function (answers) {
+                        this.log('app name', answers.name);
+                        this.log('Entity Stores:', answers.entitystore);
+                        this.log('Indexing:', answers.indexing);
+                        this.log('Caching:', answers.caching);
+                        this.log('Serialization:', answers.serialization);
+                        this.log('Features:', answers.features);
+                        polygene = answers;
+                    }.bind(this)
+                );
+            }
+        },
+
+        writing: function () {
+            polygene.version = polygeneVersion;
+            polygene.entitystoremodule = polygene.entitystore.toLowerCase();
+            if (polygene.entitystore === "DerbySQL") {
+                polygene.entitystoremodule = "sql";
+            }
+            if (polygene.entitystore === "H2SQL") {
+                polygene.entitystoremodule = "sql";
+            }
+            if (polygene.entitystore === "MySQL") {
+                polygene.entitystoremodule = "sql";
+            }
+            if (polygene.entitystore === "PostgreSQL") {
+                polygene.entitystoremodule = "sql";
+            }
+            if (polygene.entitystore === "SQLite") {
+                polygene.entitystoremodule = "sql";
+            }
+            assignFunctions(polygene);
+            polygene.javaPackageDir = polygene.packageName.replace(/[.]/g, '/');
+            polygene.ctx = this;
+            var app = require(__dirname + '/templates/' + polygene.applicationtype.replace(/ /g, '') + 'Application/app.js');
+            app.write(polygene);
+            var buildToolChain = require(__dirname + '/templates/buildtool/build.js');
+            buildToolChain.write(polygene);
+            if (this.options.export) {
+                exportModel(this.options.export);
+            }
+        }
+    }
+);
+
+function hasFeature(feature) {
+    return polygene.features.indexOf(feature) >= 0;
+}
+
+function firstUpper(text) {
+    return text.charAt(0).toUpperCase() + text.substring(1);
+}
+
+function importModel(filename) {
+    if (typeof filename !== 'string') {
+        filename = "./model.json";
+    }
+    return JSON.parse(fs.readFileSync(filename, 'utf8'));
+}
+
+function exportModel(filename) {
+    if (typeof filename !== 'string') {
+        filename = "exported-model.json";
+    }
+    delete polygene.current;
+    return fs.writeFileSync(filename, JSON.stringify(polygene, null, 4) + "\n", 'utf8');
+}
+
+function assignFunctions(polygene) {
+
+    polygene.hasFeature = function (feature) {
+        return polygene.features.indexOf(feature) >= 0;
+    };
+
+    polygene.copyTemplate = function (ctx, from, to) {
+        ctx.fs.copyTpl(
+            ctx.templatePath(from),
+            ctx.destinationPath(to),
+            {
+                hasFeature: hasFeature,
+                firstUpper: firstUpper,
+                polygene: polygene
+            }
+        );
+    };
+
+    polygene.copyPolygeneBootstrap = function (ctx, layer, moduleName, condition) {
+        if (condition) {
+            copyTemplate(ctx,
+                moduleName + '/bootstrap.tmpl',
+                'bootstrap/src/main/java/' + polygene.javaPackageDir + '/bootstrap/' + layer + '/' + moduleName + '.java');
+        }
+    };
+
+    polygene.copyEntityStore = function (ctx, entityStoreName) {
+        copyTemplate(ctx,
+            'StorageModule/bootstrap.tmpl',
+            'bootstrap/src/main/java/' + polygene.javaPackageDir + '/bootstrap/infrastructure/' + entityStoreName + 'StorageModule.java');
+    };
+
+    polygene.copyModules = function (dirname) {
+        fs.readdir(dirname, function (err, files) {
+            if (files !== undefined) {
+                files.forEach(function (directory) {
+                    if (directory.endsWith("Module")) {
+                        var module = require(dirname + "/" + directory + '/module.js');
+                        module.write(polygene);
+                    }
+                });
+            }
+        });
+    };
+    polygene.firstUpper = function (text) {
+        return text.charAt(0).toUpperCase() + text.substring(1);
+    };
+    polygene.typeNameOnly = function (text) {
+        var lastPos = text.lastIndexOf(".");
+        if (lastPos < 0) {
+            return text;
+        }
+        return text.substring(lastPos + 1);
+    };
+
+    polygene.configurationClassName = function (clazzName) {
+        if (clazzName.endsWith("Service")) {
+            clazzName = clazzName.substring(0, clazzName.length - 7);
+        }
+        return clazzName + "Configuration";
+    };
+
+    polygene.prepareClazz = function (current) {
+        var state = [];
+        var imported = {};
+        var props = current.clazz.properties;
+        if (props) {
+            imported["org.apache.polygene.api.property.Property"] = true;
+            for (var idx in props) {
+                var prop = props[idx];
+                state.push('Property' + '<' + polygene.typeNameOnly(prop.type) + "> " + prop.name + "();");
+                imported[prop.type] = true;
+            }
+        } else {
+            imported["org.apache.polygene.api.property.Property"] = true;
+            state.push('Property<String> name();    // TODO: remove sample property')
+        }
+        var assocs = current.clazz.associations;
+        if (assocs) {
+            imported["org.apache.polygene.api.association.Association"] = true;
+            for (var idx in assocs) {
+                var assoc = assocs[idx];
+                state.push("Association" + '<' + polygene.typeNameOnly(assoc.type) + "> " + assoc.name + "();");
+                imported[assoc.type] = true;
+            }
+        }
+        assocs = current.clazz.manyassociations;
+        if (assocs) {
+            imported["org.apache.polygene.api.association.ManyAssociation"] = true;
+            for (var idx in assocs) {
+                var assoc = assocs[idx];
+                state.push("ManyAssociation<" + polygene.typeNameOnly(assoc.type) + "> " + assoc.name + "();");
+                imported[assoc.type] = true;
+            }
+        }
+        assocs = current.clazz.namedassociations;
+        if (assocs) {
+            imported["org.apache.polygene.api.association.NamedAssociation"] = true;
+            for (var idx in assocs) {
+                var assoc = assocs[idx];
+                state.push("NamedAssociation<" + polygene.typeNameOnly(assoc.type) + "> " + assoc.name + "();");
+                imported[assoc.type] = true;
+            }
+        }
+        current.state = state;
+        current.imported = imported;
+    };
+
+    polygene.prepareConfigClazz = function (current) {
+        var state = [];
+        var yaml = [];
+        var imported = {};
+        var props = current.clazz.configuration;
+        if (props) {
+            imported["org.apache.polygene.api.property.Property"] = true;
+            for (var idx in props) {
+                var prop = props[idx];
+                state.push('Property' + '<' + polygene.typeNameOnly(prop.type) + "> " + prop.name + "();");
+                imported[prop.type] = true;
+                var yamlDefault;
+                if (prop.type === "java.lang.String") {
+                    yamlDefault = '""';
+                }
+                else if (prop.type === "java.lang.Boolean") {
+                    yamlDefault = 'false';
+                }
+                else if (prop.type === "java.lang.Long") {
+                    yamlDefault = '0';
+                }
+                else if (prop.type === "java.lang.Integer") {
+                    yamlDefault = '0';
+                }
+                else if (prop.type === "java.lang.Double") {
+                    yamlDefault = '0.0';
+                }
+                else if (prop.type === "java.lang.Float") {
+                    yamlDefault = '0.0';
+                }
+                else {
+                    yamlDefault = '\n    # TODO: complex configuration type. ';
+                }
+                yaml.push(prop.name + " : " + yamlDefault);
+            }
+        } else {
+            imported["org.apache.polygene.api.property.Property"] = true;
+            state.push('Property<String> name();    // TODO: remove sample property');
+            yaml.push('name : "sample config value"');
+        }
+        current.state = state;
+        current.yaml = yaml;
+        current.imported = imported;
+    };
+}
diff --git a/tools/generator-polygene/app/templates/CommandLineApplication/app.js b/tools/generator-polygene/app/templates/CommandLineApplication/app.js
new file mode 100644
index 0000000..f3eb324
--- /dev/null
+++ b/tools/generator-polygene/app/templates/CommandLineApplication/app.js
@@ -0,0 +1,35 @@
+/*
+ *  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.
+ */
+module.exports = {
+
+    write: function (p) {
+        copyLayer(p, "Configuration");
+        copyLayer(p, "Infrastructure");
+        copyLayer(p, "Domain");
+        copyLayer(p, "UserInterface");
+
+
+
+
+    }
+};
+
+function copyLayer(p, layerName) {
+    var layer = require(__dirname + '/../' + layerName + 'Layer/layer.js');
+    layer.write(p);
+}
diff --git a/tools/generator-polygene/app/templates/ConfigurationLayer/ConfigModule/bootstrap.tmpl b/tools/generator-polygene/app/templates/ConfigurationLayer/ConfigModule/bootstrap.tmpl
new file mode 100644
index 0000000..7aee6a8
--- /dev/null
+++ b/tools/generator-polygene/app/templates/ConfigurationLayer/ConfigModule/bootstrap.tmpl
@@ -0,0 +1,39 @@
+<%#
+ *  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 <%= polygene.packageName %>.bootstrap.config;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+
+public class ConfigModule
+    implements ModuleAssembler
+{
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( MemoryEntityStoreService.class ).visibleIn( Visibility.layer );
+        return module;
+    }
+}
diff --git a/tools/generator-polygene/app/templates/ConfigurationLayer/ConfigModule/module.js b/tools/generator-polygene/app/templates/ConfigurationLayer/ConfigModule/module.js
new file mode 100644
index 0000000..5056397
--- /dev/null
+++ b/tools/generator-polygene/app/templates/ConfigurationLayer/ConfigModule/module.js
@@ -0,0 +1,25 @@
+/*
+ *  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.
+ */
+module.exports = {
+
+    write: function (p) {
+        p.copyTemplate(p.ctx,
+            'ConfigurationLayer/ConfigModule/bootstrap.tmpl',
+            'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/config/ConfigModule.java');
+    }
+};
diff --git a/tools/generator-polygene/app/templates/ConfigurationLayer/bootstrap.tmpl b/tools/generator-polygene/app/templates/ConfigurationLayer/bootstrap.tmpl
new file mode 100644
index 0000000..d83ae32
--- /dev/null
+++ b/tools/generator-polygene/app/templates/ConfigurationLayer/bootstrap.tmpl
@@ -0,0 +1,46 @@
+<%#
+ *  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 <%= polygene.packageName %>.bootstrap.config;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.LayerAssembler;
+import org.apache.polygene.bootstrap.layered.LayeredLayerAssembler;
+
+public class ConfigurationLayer extends LayeredLayerAssembler
+    implements LayerAssembler
+{
+    public static String NAME;
+    private ModuleAssembly configModule;
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        configModule = createModule( layer, ConfigModule.class );
+        return layer;
+    }
+
+    public ModuleAssembly configModule()
+    {
+        return configModule;
+    }
+}
\ No newline at end of file
diff --git a/tools/generator-polygene/app/templates/ConfigurationLayer/layer.js b/tools/generator-polygene/app/templates/ConfigurationLayer/layer.js
new file mode 100644
index 0000000..9f00ed8
--- /dev/null
+++ b/tools/generator-polygene/app/templates/ConfigurationLayer/layer.js
@@ -0,0 +1,27 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        p.copyTemplate(p.ctx,
+            'ConfigurationLayer/bootstrap.tmpl',
+            'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/config/ConfigurationLayer.java');
+        p.copyModules(__dirname );
+    }
+};
diff --git a/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/DefaultEnroler.tmpl b/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/DefaultEnroler.tmpl
new file mode 100644
index 0000000..31d4588
--- /dev/null
+++ b/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/DefaultEnroler.tmpl
@@ -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 <%= polygene.packageName %>.rest.security;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.restlet.Application;
+import org.restlet.data.ClientInfo;
+import org.restlet.security.Enroler;
+import org.restlet.security.Role;
+import <%= polygene.packageName %>.model.security.SecurityRepository;
+
+
+public class DefaultEnroler
+    implements Enroler
+{
+    @Service
+    private SecurityRepository repository;
+
+    @Uses
+    private Application application;
+
+    @Override
+    public void enrole( ClientInfo clientInfo )
+    {
+        org.restlet.security.User user = clientInfo.getUser();
+        String name = user.getName();
+        List<String> roleList = repository.findRoleNamesOfUser( name );
+        List<Role> restletRoles = new ArrayList<>();
+        roleList.stream().map( roleName -> Role.get( application, roleName ) );
+        clientInfo.setRoles( restletRoles );
+    }
+}
diff --git a/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/DefaultVerifier.tmpl b/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/DefaultVerifier.tmpl
new file mode 100644
index 0000000..e31e240
--- /dev/null
+++ b/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/DefaultVerifier.tmpl
@@ -0,0 +1,46 @@
+<%#
+ *  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 <%= polygene.packageName %>.rest.security;
+
+import org.apache.polygene.api.injection.scope.Service;
+import org.restlet.security.SecretVerifier;
+import org.restlet.security.Verifier;
+import <%= polygene.packageName %>.model.security.SecurityRepository;
+
+public class DefaultVerifier extends SecretVerifier
+    implements Verifier
+{
+    @Service
+    private SecurityRepository repository;
+
+    @Override
+    public int verify( String user, char[] secret )
+    {
+        if( user == null || secret == null )
+        {
+            return RESULT_UNKNOWN;
+        }
+        if( repository.verifyPassword( user, String.valueOf( secret ) ) )
+        {
+            return RESULT_VALID;
+        }
+        return RESULT_INVALID;
+    }
+}
diff --git a/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/NullEnroler.tmpl b/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/NullEnroler.tmpl
new file mode 100644
index 0000000..c24ddce
--- /dev/null
+++ b/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/NullEnroler.tmpl
@@ -0,0 +1,32 @@
+<%#
+ *  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 <%= polygene.packageName %>.rest.security;
+
+import org.restlet.data.ClientInfo;
+import org.restlet.security.Enroler;
+
+public class NullEnroler
+    implements Enroler
+{
+    @Override
+    public void enrole( ClientInfo clientInfo )
+    {
+    }
+}
diff --git a/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/NullVerifier.tmpl b/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/NullVerifier.tmpl
new file mode 100644
index 0000000..5d6b349
--- /dev/null
+++ b/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/NullVerifier.tmpl
@@ -0,0 +1,34 @@
+<%#
+ *  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 <%= polygene.packageName %>.rest.security;
+
+import org.restlet.security.SecretVerifier;
+import org.restlet.security.Verifier;
+
+public class NullVerifier extends SecretVerifier
+    implements Verifier
+{
+
+    @Override
+    public int verify( String user, char[] secret )
+    {
+        return RESULT_VALID;
+    }
+}
diff --git a/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/bootstrap.tmpl b/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/bootstrap.tmpl
new file mode 100644
index 0000000..0594546
--- /dev/null
+++ b/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/bootstrap.tmpl
@@ -0,0 +1,56 @@
+<%#
+ *  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 <%= polygene.packageName %>.bootstrap.connectivity;
+
+<% if( hasFeature('security') ) { %>
+import <%= polygene.packageName %>.rest.security.DefaultEnroler;
+import <%= polygene.packageName %>.rest.security.DefaultVerifier;
+<% } else { %>
+import <%= polygene.packageName %>.rest.security.NullEnroler;
+import <%= polygene.packageName %>.rest.security.NullVerifier;
+<% } %>
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.library.restlet.assembly.RestletCrudConnectivityAssembler;
+import org.apache.polygene.library.restlet.resource.EntryPoint;
+
+public class RestApiModule
+    implements ModuleAssembler
+{
+    public static String NAME;
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+<% if( hasFeature('security') ) { %>
+        module.objects( DefaultVerifier.class, DefaultEnroler.class);
+<% } else {%>
+        module.objects( NullVerifier.class, NullEnroler.class);
+<% } %>
+        new RestletCrudConnectivityAssembler().assemble( module );
+        module.values( EntryPoint.class );
+        module.values( /* add value types */   );
+        module.services(  /* add services */  );
+        return module;
+    }
+}
diff --git a/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/module.js b/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/module.js
new file mode 100644
index 0000000..8d4ad47
--- /dev/null
+++ b/tools/generator-polygene/app/templates/ConnectivityLayer/RestApiModule/module.js
@@ -0,0 +1,42 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        if (p.applicationtype === 'Rest API') {
+            p.copyTemplate(p.ctx,
+                'ConnectivityLayer/RestApiModule/bootstrap.tmpl',
+                'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/connectivity/RestApiModule.java');
+            if (p.hasFeature("security")) {
+                copyFile(p, "DefaultEnroler");
+                copyFile(p, "DefaultVerifier");
+            }
+            else {
+                copyFile(p, "NullEnroler");
+                copyFile(p, "NullVerifier");
+            }
+        }
+    }
+};
+
+function copyFile(p, clazz) {
+    p.copyTemplate(p.ctx,
+        'ConnectivityLayer/RestApiModule/' + clazz + '.tmpl',
+        'rest/src/main/java/' + p.javaPackageDir + '/rest/security/' + clazz + '.java');
+}
diff --git a/tools/generator-polygene/app/templates/ConnectivityLayer/bootstrap.tmpl b/tools/generator-polygene/app/templates/ConnectivityLayer/bootstrap.tmpl
new file mode 100644
index 0000000..5623b6f
--- /dev/null
+++ b/tools/generator-polygene/app/templates/ConnectivityLayer/bootstrap.tmpl
@@ -0,0 +1,39 @@
+<%#
+ *  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 <%= polygene.packageName %>.bootstrap.connectivity;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.layered.LayerAssembler;
+import org.apache.polygene.bootstrap.layered.LayeredLayerAssembler;
+
+public class ConnectivityLayer extends LayeredLayerAssembler
+    implements LayerAssembler
+{
+    public static String NAME;
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        createModule( layer, RestApiModule.class );
+        return layer;
+    }
+}
\ No newline at end of file
diff --git a/tools/generator-polygene/app/templates/ConnectivityLayer/layer.js b/tools/generator-polygene/app/templates/ConnectivityLayer/layer.js
new file mode 100644
index 0000000..a9d2a9b
--- /dev/null
+++ b/tools/generator-polygene/app/templates/ConnectivityLayer/layer.js
@@ -0,0 +1,27 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        p.copyTemplate(p.ctx,
+            'ConnectivityLayer/bootstrap.tmpl',
+            'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/connectivity/ConnectivityLayer.java');
+        p.copyModules(__dirname );
+    }
+};
diff --git a/tools/generator-polygene/app/templates/DomainLayer/CrudModule/bootstrap.tmpl b/tools/generator-polygene/app/templates/DomainLayer/CrudModule/bootstrap.tmpl
new file mode 100644
index 0000000..2c50918
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/CrudModule/bootstrap.tmpl
@@ -0,0 +1,38 @@
+<%#
+ *  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 <%= polygene.packageName %>.bootstrap.domain;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.library.restlet.assembly.CrudServiceAssembler;
+
+public class CrudModule
+    implements ModuleAssembler
+{
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        new CrudServiceAssembler().assemble( module );
+        return module;
+    }
+}
\ No newline at end of file
diff --git a/tools/generator-polygene/app/templates/DomainLayer/CrudModule/module.js b/tools/generator-polygene/app/templates/DomainLayer/CrudModule/module.js
new file mode 100644
index 0000000..4689e13
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/CrudModule/module.js
@@ -0,0 +1,28 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        if( p.applicationtype === 'Rest API' ) {
+            p.copyTemplate(p.ctx,
+                'DomainLayer/CrudModule/bootstrap.tmpl',
+                'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/domain/CrudModule.java');
+        }
+    }
+};
diff --git a/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Configuration.tmpl b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Configuration.tmpl
new file mode 100644
index 0000000..b7acd94
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Configuration.tmpl
@@ -0,0 +1,35 @@
+<%#
+ *  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 <%= polygene.packageName %>.model.<%= polygene.current.name %>;
+<%
+for( var imp in polygene.current.imported ) {
+    if( !imp.startsWith( "java.lang" )
+        && imp.includes(".") ) {
+        %><%- "import " + imp + ";"; %>
+<%
+    }
+} %>
+
+public interface <%= polygene.current.clazz.name %>
+{
+<% for( var idx in polygene.current.state ) {
+%>    <%- polygene.current.state[idx]; %>
+<% } %>
+}
diff --git a/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Crud.tmpl b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Crud.tmpl
new file mode 100644
index 0000000..60d7528
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Crud.tmpl
@@ -0,0 +1,50 @@
+<%#
+ *  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 <%= polygene.packageName %>.model.<%= polygene.current.name %>;
+
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+<%
+for( var imp in polygene.current.imported ) {
+    if( !imp.startsWith( "java.lang" )
+        && imp.includes(".") ) {
+        %><%- "import " + imp + ";"; %>
+<%
+    }
+} %>
+
+@Mixins( { <%= polygene.current.clazz.name %>.Mixin.class } )
+public interface <%= polygene.current.clazz.name %>
+{
+    interface State
+    {
+<% for( var idx in polygene.current.state ) {
+%>        <%- polygene.current.state[idx]; %>
+<% }
+%>    }
+
+    class Mixin
+        implements <%= polygene.current.clazz.name %>
+    {
+        @This
+        private State state;        // Sample reference to hidden property
+
+    }
+}
diff --git a/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Entity.tmpl b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Entity.tmpl
new file mode 100644
index 0000000..60d7528
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Entity.tmpl
@@ -0,0 +1,50 @@
+<%#
+ *  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 <%= polygene.packageName %>.model.<%= polygene.current.name %>;
+
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+<%
+for( var imp in polygene.current.imported ) {
+    if( !imp.startsWith( "java.lang" )
+        && imp.includes(".") ) {
+        %><%- "import " + imp + ";"; %>
+<%
+    }
+} %>
+
+@Mixins( { <%= polygene.current.clazz.name %>.Mixin.class } )
+public interface <%= polygene.current.clazz.name %>
+{
+    interface State
+    {
+<% for( var idx in polygene.current.state ) {
+%>        <%- polygene.current.state[idx]; %>
+<% }
+%>    }
+
+    class Mixin
+        implements <%= polygene.current.clazz.name %>
+    {
+        @This
+        private State state;        // Sample reference to hidden property
+
+    }
+}
diff --git a/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Object.tmpl b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Object.tmpl
new file mode 100644
index 0000000..fb8908b
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Object.tmpl
@@ -0,0 +1,43 @@
+<%#
+ *  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 <%= polygene.packageName %>.model.<%= polygene.current.name %>;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+<%
+for( var imp in polygene.current.imported ) {
+    if( !imp.startsWith( "java.lang" )
+        && imp.includes(".") ) {
+        %><%- "import " + imp + ";"; %>
+<%
+    }
+} %>
+
+public class <%= polygene.current.clazz.name %>
+{
+    @Uses
+    private String name;   // Sample @Uses injection
+
+    @Structure
+    private ValueBuilderFactory vbf;  // Sample @Structure injection
+
+}
diff --git a/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Plain.tmpl b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Plain.tmpl
new file mode 100644
index 0000000..c7a1c04
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Plain.tmpl
@@ -0,0 +1,37 @@
+<%#
+ *  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 <%= polygene.packageName %>.model.<%= polygene.current.name %>;
+<%
+for( var imp in polygene.current.imported ) {
+    if( !imp.startsWith( "java.lang" )
+        && imp.includes(".") ) {
+        %><%- "import " + imp + ";"; %>
+<%
+    }
+} %>
+
+public <%- polygene.current.clazz.type %> <%= polygene.current.clazz.name %>
+{<%
+if( polygene.current.clazz.type === 'enum' ) {
+%>
+    <%- polygene.current.clazz.values %>
+<%
+}
+%>}
diff --git a/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Service.tmpl b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Service.tmpl
new file mode 100644
index 0000000..b5fafdb
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Service.tmpl
@@ -0,0 +1,54 @@
+<%#
+ *  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 <%= polygene.packageName %>.model.<%= polygene.current.name %>;
+
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+<%
+for( var imp in polygene.current.imported ) {
+    if( !imp.startsWith( "java.lang" )
+        && imp.includes(".") ) {
+        %><%- "import " + imp + ";"; %>
+<%
+    }
+} %>
+
+@Mixins( { <%= polygene.current.clazz.name %>.Mixin.class } )
+public interface <%= polygene.current.clazz.name %>
+{
+
+    class Mixin
+        implements <%= polygene.current.clazz.name %>
+    {
+        @This
+        private Configuration<<%- polygene.configurationClassName( polygene.current.clazz.name ); %>> configuration;
+
+        @Structure
+        private ValueBuilderFactory vbf;
+
+        @Structure
+        private UnitOfWorkFactory uowf;
+    }
+}
+
diff --git a/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Transient.tmpl b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Transient.tmpl
new file mode 100644
index 0000000..c8012ba
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Transient.tmpl
@@ -0,0 +1,56 @@
+<%#
+ *  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 <%= polygene.packageName %>.model.<%= polygene.current.name %>;
+
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.mixin.Mixins;
+<%
+for( var imp in polygene.current.imported ) {
+    if( !imp.startsWith( "java.lang" )
+        && imp.includes(".") ) {
+        %><%- "import " + imp + ";"; %>
+<%
+    }
+} %>
+
+@Mixins( { <%= polygene.current.clazz.name %>.Mixin.class } )
+public interface <%= polygene.current.clazz.name %>
+{
+<% for( var idx in polygene.current.state ) { %>
+    <%- polygene.current.state[idx]; %>
+<% } %>
+
+    // If Property declarations are public, the Mixin must be abstract, because PropertyMixin will implement those methods.
+    abstract class Mixin
+        implements <%= polygene.current.clazz.name %>
+    {
+        // Transients supports @Uses injection
+        //
+        //  Socket socket = serverSockete.accept();
+        //  TransientBuilder<<%= polygene.current.clazz.name %>> builder = transientBuilderFactory.newTransientBuilder(<%= polygene.current.clazz.name %>.class);
+        //  builder.use( socket );
+        //  builder.prototype().name().set( name + counter++ );
+        //  <%= polygene.current.clazz.name %> <%= polygene.current.clazz.name.toLowerCase() %> = builder.newInstance();
+
+//        @Uses
+//        private Socket items;
+
+    }
+}
diff --git a/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Value.tmpl b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Value.tmpl
new file mode 100644
index 0000000..beae662
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/Value.tmpl
@@ -0,0 +1,49 @@
+<%#
+ *  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 <%= polygene.packageName %>.model.<%= polygene.current.name %>;
+
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+<%
+for( var imp in polygene.current.imported ) {
+    if( !imp.startsWith( "java.lang" )
+        && imp.includes(".") ) {
+        %><%- "import " + imp + ";"; %>
+<%
+    }
+} %>
+
+@Mixins( { <%= polygene.current.clazz.name %>.Mixin.class } )
+public interface <%= polygene.current.clazz.name %>
+{
+    interface State
+    {
+<% for( var idx in polygene.current.state ) {
+%>        <%- polygene.current.state[idx]; %>
+<% }
+%>    }
+
+    class Mixin
+        implements <%= polygene.current.clazz.name %>
+    {
+        @This
+        private State state;        // Reference to private State instance
+    }
+}
diff --git a/tools/generator-polygene/app/templates/DomainLayer/DomainModule/bootstrap.tmpl b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/bootstrap.tmpl
new file mode 100644
index 0000000..092d683
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/bootstrap.tmpl
@@ -0,0 +1,120 @@
+<%#
+ *  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 <%= polygene.packageName %>.bootstrap.domain;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+
+<% for( var idx in polygene.current.cruds) {
+%><%= "import " + polygene.packageName + ".model." + polygene.current.name + "." + polygene.current.cruds[idx].name + ";" %>
+<%
+}
+
+for( var idx in polygene.current.values) {
+%><%= "import " + polygene.packageName + ".model." + polygene.current.name + "." + polygene.current.values[idx].name + ";" %>
+<%
+}
+for( var idx in polygene.current.entities) {
+%><%= "import " + polygene.packageName + ".model." + polygene.current.name + "." + polygene.current.entities[idx].name + ";" %>
+<%
+}
+
+for( var idx in polygene.current.transients) {
+%><%= "import " + polygene.packageName + ".model." + polygene.current.name + "." + polygene.current.transients[idx].name + ";" %>
+<%
+}
+
+for( var idx in polygene.current.objects) {
+%><%= "import " + polygene.packageName + ".model." + polygene.current.name + "." + polygene.current.objects[idx].name + ";" %>
+<%
+}
+
+for( var idx in polygene.current.services) {
+%><%= "import " + polygene.packageName + ".model." + polygene.current.name + "." + polygene.current.services[idx].name + ";" %>
+<%= "import " + polygene.packageName + ".model." + polygene.current.name + "." + polygene.configurationClassName(polygene.current.services[idx].name) + ";" %>
+<%
+} %>
+
+import static org.apache.polygene.api.common.Visibility.layer;
+import static org.apache.polygene.api.common.Visibility.application;
+
+public class <%- firstUpper(polygene.current.name) %>Module
+    implements ModuleAssembler
+{
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+<%
+if( polygene.current.cruds ) {
+    for( var value in polygene.current.cruds ) {
+        var crud = polygene.current.cruds[value];
+%>
+        <%- "module.values( " + crud.name + ".class )" + (crud.visibility ? ".visibleIn(" + crud.visibility +")" : "" ) %>;
+        <%- "module.entities( " + crud.name + ".class )" + (crud.visibility ? ".visibleIn(" + crud.visibility +")" : "" ) %>;
+<%
+    }
+}
+if( polygene.current.values ) {
+    for( var value in polygene.current.values ) {
+        var v = polygene.current.values[value];
+%>
+        <%- "module.values( " + v.name + ".class )" + (v.visibility ? ".visibleIn(" + v.visibility +")" : "" ) %>;
+<%
+    }
+}
+if( polygene.current.entities ) {
+    for( var value in polygene.current.entities ) {
+        var entity = polygene.current.entities[value];
+%>
+        <%- "module.entities( " + entity.name + ".class )" + (entity.visibility ? ".visibleIn(" + entity.visibility +")" : "" ) %>;
+<%
+    }
+}
+if( polygene.current.transients ) {
+    for( var value in polygene.current.transients ) {
+        var trans = polygene.current.transients[value];
+%>
+        <%- "module.transients( " + trans.name + ".class )" + (trans.visibility ? ".visibleIn(" + trans.visibility +")" : "" ) %>;
+<%
+    }
+}
+if( polygene.current.objects ) {
+    for( var value in polygene.current.objects ) {
+        var obj = polygene.current.objects[value];
+%>
+        <%- "module.objects( " + obj.name + ".class )" + (obj.visibility ? ".visibleIn(" + obj.visibility +")" : "" ) %>;
+<%
+    }
+}
+if( polygene.current.services ) {
+    for( var value in polygene.current.services ) {
+        var service = polygene.current.services[value];
+%>
+        <%- "module.services( " + service.name + ".class )" + (service.visibility ? ".visibleIn(" + service.visibility + ")" : "" ) %>;
+        <%- "module.entities( " + polygene.configurationClassName(service.name) + ".class )" %>;
+<%
+    }
+} %>
+        return module;
+    }
+}
diff --git a/tools/generator-polygene/app/templates/DomainLayer/DomainModule/config.yaml.tmpl b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/config.yaml.tmpl
new file mode 100644
index 0000000..e2629d5
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/config.yaml.tmpl
@@ -0,0 +1,23 @@
+<%#
+ *  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.
+ *
+ *
+-%>
+-
+<% for( var idx in polygene.current.yaml ) {
+%>    <%- polygene.current.yaml[idx]; %>
+<% } %>
diff --git a/tools/generator-polygene/app/templates/DomainLayer/DomainModule/module.js b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/module.js
new file mode 100644
index 0000000..8855bc3
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/DomainModule/module.js
@@ -0,0 +1,83 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        if(!p.modules) return;
+        Object.keys(p.modules).forEach(function (moduleName, index) {
+            copyPolygeneDomainModule(p, moduleName, p.modules[moduleName])
+        });
+    }
+
+};
+
+function copyFile(p, module, clazz) {
+    p.copyTemplate(p.ctx,
+        p.firstUpper(module) + 'Module/' + clazz + '.tmpl',
+        'model/src/main/java/' + p.javaPackageDir + '/model/' + module + '/' + clazz + '.java');
+}
+
+function copyPolygeneDomainModule(p, moduleName, moduleDef) {
+    p.current = moduleDef;
+    p.current.name = moduleName;
+    var clazz = p.firstUpper(moduleName) + "Module";
+    p.copyTemplate(p.ctx,
+        'DomainLayer/DomainModule/bootstrap.tmpl',
+        'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/domain/' + clazz + '.java');
+    copyComposites(p, moduleDef.cruds, "Crud");
+    copyComposites(p, moduleDef.entities, "Entity");
+    copyComposites(p, moduleDef.values, "Value");
+    copyComposites(p, moduleDef.transients, "Transient");
+    copyComposites(p, moduleDef.objects, "Object");
+    copyComposites(p, moduleDef.services, "Service");
+    copyComposites(p, moduleDef.plainTypes, "Plain");
+    copyComposites(p, moduleDef.services, "Configuration");
+
+    copyConfigurationYaml(p, moduleDef.services )
+}
+
+function copyComposites(p, composites, type) {
+    for (var idx in composites) {
+        if (composites.hasOwnProperty(idx)) {
+            if( type === "Configuration"){
+                p.current.clazz.name = p.configurationClassName(composites[idx].name);
+                p.prepareConfigClazz(p.current);
+            } else {
+                p.current.clazz = composites[idx];
+                p.prepareClazz(p.current);
+            }
+            p.copyTemplate(p.ctx,
+                'DomainLayer/DomainModule/' + type + '.tmpl',
+                'model/src/main/java/' + p.javaPackageDir + '/model/' + p.current.name  + '/' + p.current.clazz.name + '.java');
+        }
+    }
+}
+
+function copyConfigurationYaml(p, composites) {
+    for (var idx in composites) {
+        if (composites.hasOwnProperty(idx)) {
+            p.current.clazz = composites[idx];
+            p.prepareClazz(p.current);
+            p.copyTemplate(p.ctx,
+                'DomainLayer/DomainModule/config.yaml.tmpl',
+                'model/src/main/resources/' + p.javaPackageDir + '/model/' + p.current.name + '/' + p.current.clazz.name + '.yaml');
+        }
+    }
+}
+
diff --git a/tools/generator-polygene/app/templates/DomainLayer/JmxModule/bootstrap.tmpl b/tools/generator-polygene/app/templates/DomainLayer/JmxModule/bootstrap.tmpl
new file mode 100644
index 0000000..e0f3ade
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/JmxModule/bootstrap.tmpl
@@ -0,0 +1,46 @@
+<%#
+ *  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 <%= polygene.packageName %>.bootstrap.config;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+import org.apache.polygene.library.jmx.JMXAssembler;
+import org.apache.polygene.library.jmx.JMXConnectorService;
+import org.apache.polygene.library.jmx.JMXConnectorConfiguration;
+
+public class JmxModule
+    implements ModuleAssembler
+{
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        new JMXAssembler().assemble( module );
+        module.services( JMXConnectorService.class ).instantiateOnStartup();
+        module.entities( JMXConnectorConfiguration.class );
+        module.forMixin( JMXConnectorConfiguration.class ).declareDefaults().port().set( 1099 );
+        return module;
+    }
+}
+
diff --git a/tools/generator-polygene/app/templates/DomainLayer/JmxModule/module.js b/tools/generator-polygene/app/templates/DomainLayer/JmxModule/module.js
new file mode 100644
index 0000000..18d1f00
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/JmxModule/module.js
@@ -0,0 +1,28 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        if( p.hasFeature('jmx')) {
+            p.copyTemplate(p.ctx,
+                'DomainLayer/JmxModule/bootstrap.tmpl',
+                'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/domain/JmxModule.java');
+        }
+    }
+};
diff --git a/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/CryptoConfiguration.tmpl b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/CryptoConfiguration.tmpl
new file mode 100644
index 0000000..3262390
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/CryptoConfiguration.tmpl
@@ -0,0 +1,38 @@
+<%#
+ *  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 <%= polygene.packageName %>.model.security;
+
+import org.apache.polygene.api.configuration.ConfigurationComposite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.common.Optional;
+
+public interface CryptoConfiguration extends ConfigurationComposite
+{
+    @Optional
+    Property<String> digestAlgorithm();
+
+    @Optional
+    Property<String> encryptionAlgorithm();
+
+    Property<String> secret1();
+
+    Property<String> secret2();
+
+}
diff --git a/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/CryptoException.tmpl b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/CryptoException.tmpl
new file mode 100644
index 0000000..d6e8d38
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/CryptoException.tmpl
@@ -0,0 +1,28 @@
+<%#
+ *  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 <%= polygene.packageName %>.model.security;
+
+public class CryptoException extends RuntimeException
+{
+    public CryptoException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
\ No newline at end of file
diff --git a/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/CryptoService.tmpl b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/CryptoService.tmpl
new file mode 100644
index 0000000..588e70d
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/CryptoService.tmpl
@@ -0,0 +1,113 @@
+<%#
+ *  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 <%= polygene.packageName %>.model.security;
+
+import java.security.MessageDigest;
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+
+@Mixins( { CryptoService.Mixin.class } )
+public interface CryptoService
+{
+    String encrypt( String clear );
+
+    String decrypt( String encrypted );
+
+    class Mixin
+        implements CryptoService
+    {
+        private SecretKeySpec key;
+        private IvParameterSpec ivSpec;
+        private Cipher cipher;
+        private MessageDigest digest;
+
+        public Mixin( @This Configuration<CryptoConfiguration> configuration)
+            throws Exception
+        {
+            CryptoConfiguration config = configuration.get();
+            String digestAlgorithm = config.digestAlgorithm().get();
+            if( digestAlgorithm == null )
+            {
+                digestAlgorithm = "SHA-1";
+            }
+            digest = MessageDigest.getInstance( digestAlgorithm );
+            byte[] keyBytes = hashed( config.secret1().get() );
+            byte[] ivBytes = hashed( config.secret2().get() );
+
+            key = new SecretKeySpec(keyBytes, "DES");
+            ivSpec = new IvParameterSpec(ivBytes);
+
+            String encryptionAlgorithm = config.encryptionAlgorithm().get();
+            if( encryptionAlgorithm == null )
+            {
+                encryptionAlgorithm = "AES";
+            }
+            cipher = Cipher.getInstance( encryptionAlgorithm );
+        }
+
+        public String encrypt( String clear )
+            throws CryptoException
+        {
+            try
+            {
+                cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
+
+                byte[] input = clear.getBytes();
+                byte[] encrypted= new byte[cipher.getOutputSize(input.length)];
+                int enc_len = cipher.update(input, 0, input.length, encrypted, 0);
+                enc_len += cipher.doFinal(encrypted, enc_len);
+                return new String( encrypted, 0, enc_len );
+
+            } catch( Exception e ) {
+                throw new CryptoException( "Unable to encrypt.", e );
+            }
+        }
+
+        public String decrypt( String encryptedString )
+            throws CryptoException
+        {
+            try
+            {
+                cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
+
+                byte[] encrypted = encryptedString.getBytes();
+                int enc_len = encrypted.length;
+                byte[] decrypted = new byte[cipher.getOutputSize(encrypted.length)];
+                int dec_len = cipher.update(encrypted, 0, enc_len, decrypted, 0);
+                dec_len += cipher.doFinal(decrypted, dec_len);
+                return new String( decrypted, 0, dec_len );
+            } catch( Exception e ) {
+                throw new CryptoException( "Unable to decrypt.", e );
+            }
+        }
+
+        private byte[] hashed( String data )
+        {
+            digest.reset();
+            return digest.digest( data.getBytes() );
+        }
+    }
+}
\ No newline at end of file
diff --git a/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/EncryptedStringPropertyConcern.tmpl b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/EncryptedStringPropertyConcern.tmpl
new file mode 100644
index 0000000..5db973c
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/EncryptedStringPropertyConcern.tmpl
@@ -0,0 +1,41 @@
+<%#
+ *  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 <%= polygene.packageName %>.model.security;
+
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.injection.scope.Service;
+
+public class EncryptedStringPropertyConcern extends ConcernOf<Property<String>>
+    implements Property<String>
+{
+    @Service
+    private CryptoService crypto;
+
+    public String get() {
+        String value = next.get();
+        return crypto.decrypt( value );
+    }
+
+    public void set( String value ) {
+        String encrypted = crypto.encrypt( value );
+        next.set( value );
+    }
+}
diff --git a/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/Group.tmpl b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/Group.tmpl
new file mode 100644
index 0000000..ea212d2
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/Group.tmpl
@@ -0,0 +1,26 @@
+<%#
+ *  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 <%= polygene.packageName %>.model.security;
+
+import org.apache.polygene.library.shiro.domain.permissions.RoleAssignee;
+
+public interface Group extends RoleAssignee
+{
+}
diff --git a/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/RealmService.tmpl b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/RealmService.tmpl
new file mode 100644
index 0000000..106975f
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/RealmService.tmpl
@@ -0,0 +1,62 @@
+<%#
+ *  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 <%= polygene.packageName %>.model.security;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.service.ServiceActivation;
+
+import org.apache.shiro.authc.credential.DefaultPasswordService;
+import org.apache.shiro.authc.credential.PasswordMatcher;
+import org.apache.shiro.authc.credential.PasswordService;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.realm.SimpleAccountRealm;
+
+@Mixins( RealmService.Mixin.class )
+public interface RealmService
+        extends Realm, ServiceActivation
+{
+    class Mixin extends SimpleAccountRealm
+            implements ServiceActivation
+    {
+
+        private final PasswordService passwordService;
+
+        public Mixin()
+        {
+            super();
+            passwordService = new DefaultPasswordService();
+            PasswordMatcher matcher = new PasswordMatcher();
+            matcher.setPasswordService( passwordService );
+            setCredentialsMatcher( matcher );
+        }
+
+        public void activateService()
+                throws Exception
+        {
+            // Create a test account
+            addAccount( "foo", passwordService.encryptPassword( "bar" ) );
+        }
+
+        public void passivateService()
+                throws Exception
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/SecurityRepository.tmpl b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/SecurityRepository.tmpl
new file mode 100644
index 0000000..06eb69c
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/SecurityRepository.tmpl
@@ -0,0 +1,71 @@
+<%#
+ *  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 <%= polygene.packageName %>.model.security;
+
+import java.util.Collections;
+import java.util.List;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkConcern;
+import org.apache.polygene.api.unitofwork.concern.UnitOfWorkPropagation;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.subject.Subject;
+
+@Concerns( UnitOfWorkConcern.class )
+@Mixins( { SecurityRepository.ShiroBackedSecurityRepositoryMixin.class } )
+public interface SecurityRepository
+{
+    @UnitOfWorkPropagation
+    boolean verifyPassword( String user, String password );
+
+    @UnitOfWorkPropagation
+    List<String> findRoleNamesOfUser( String name );
+
+
+    class ShiroBackedSecurityRepositoryMixin
+        implements SecurityRepository
+    {
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @Override
+        @UnitOfWorkPropagation
+        public boolean verifyPassword( String userName, String password )
+        {
+            Subject currentUser = SecurityUtils.getSubject();
+            return currentUser.isAuthenticated();
+        }
+
+        @UnitOfWorkPropagation
+        public List<String> findRoleNamesOfUser( String name )
+        {
+            if( "admin".equals( name ) )
+            {
+                return Collections.singletonList("admin");
+            }
+            return Collections.singletonList("user");
+        }
+    }
+}
diff --git a/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/User.tmpl b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/User.tmpl
new file mode 100644
index 0000000..08db130
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/User.tmpl
@@ -0,0 +1,51 @@
+<%#
+ *  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 <%= polygene.packageName %>.model.security;
+
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.shiro.domain.passwords.PasswordSecurable;
+import org.apache.polygene.library.shiro.domain.permissions.RoleAssignee;
+
+@Mixins( { User.GroupsMixin.class } )
+public interface User extends PasswordSecurable, RoleAssignee
+{
+    boolean isMemberOf( Group group );
+
+    interface State
+    {
+        ManyAssociation<Group> memberOf();
+    }
+
+    abstract class GroupsMixin
+        implements User
+    {
+        @This
+        private State state;
+
+        public boolean isMemberOf( Group group )
+        {
+            return state.memberOf().contains( group );
+        }
+    }
+}
diff --git a/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/UserFactory.tmpl b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/UserFactory.tmpl
new file mode 100644
index 0000000..298950e
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/UserFactory.tmpl
@@ -0,0 +1,55 @@
+<%#
+ *  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 <%= polygene.packageName %>.model.security;
+
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+
+import org.apache.shiro.authc.credential.PasswordService;
+
+@Mixins( UserFactory.Mixin.class )
+public interface UserFactory
+{
+
+    User createNewUser( String username, String password );
+
+    class Mixin
+        implements UserFactory
+    {
+        @Structure
+        private UnitOfWorkFactory uowf;
+
+        @Service
+        private PasswordService passwordService;
+
+        @Override
+        public User createNewUser( String username, String password )
+        {
+            EntityBuilder<User> userBuilder = uowf.currentUnitOfWork().newEntityBuilder( User.class );
+            User user = userBuilder.instance();
+            user.subjectIdentifier().set( username );
+            user.password().set( passwordService.encryptPassword( password ) );
+            return userBuilder.newInstance();
+        }
+    }
+}
diff --git a/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/bootstrap.tmpl b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/bootstrap.tmpl
new file mode 100644
index 0000000..e60c563
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/bootstrap.tmpl
@@ -0,0 +1,69 @@
+<%#
+ *  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 <%= polygene.packageName %>.bootstrap.domain;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.library.shiro.assembly.PasswordDomainAssembler;
+import org.apache.polygene.library.shiro.assembly.PermissionsDomainAssembler;
+import org.apache.polygene.library.shiro.assembly.StandaloneShiroAssembler;
+import org.apache.polygene.library.shiro.ini.ShiroIniConfiguration;
+import <%= polygene.packageName %>.model.security.RealmService;
+import <%= polygene.packageName %>.model.security.SecurityRepository;
+import <%= polygene.packageName %>.model.security.User;
+import <%= polygene.packageName %>.model.security.UserFactory;
+
+public class SecurityModule
+    implements ModuleAssembler
+{
+    public static String NAME;
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( SecurityRepository.class )
+            .visibleIn( Visibility.application )
+            .instantiateOnStartup();
+
+        new StandaloneShiroAssembler()
+            .withConfig( module, Visibility.layer )
+            .assemble( module );
+        module.services( RealmService.class );
+
+        module.forMixin( ShiroIniConfiguration.class )
+            .declareDefaults()
+            .iniResourcePath().set( "classpath:standalone-shiro.ini" );
+
+        new PasswordDomainAssembler()
+            .withConfig( module, Visibility.layer )
+            .assemble( module );
+
+        new PermissionsDomainAssembler().assemble( module );
+
+        module.entities( User.class );
+        module.services( UserFactory.class );
+
+        return module;
+    }
+}
\ No newline at end of file
diff --git a/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/module.js b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/module.js
new file mode 100644
index 0000000..fed3dd6
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/SecurityModule/module.js
@@ -0,0 +1,46 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        if( p.hasFeature("security")) {
+
+            p.copyTemplate(p.ctx,
+                'DomainLayer/SecurityModule/bootstrap.tmpl',
+                'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/domain/SecurityModule.java');
+
+            copyFile(p, "CryptoConfiguration");
+            copyFile(p, "CryptoException");
+            copyFile(p, "CryptoService");
+            copyFile(p, "EncryptedStringPropertyConcern");
+            copyFile(p, "Group");
+            copyFile(p, "RealmService");
+            copyFile(p, "SecurityRepository");
+            copyFile(p, "User");
+            copyFile(p, "UserFactory");
+        }
+    }
+
+};
+
+function copyFile(p, clazz) {
+    p.copyTemplate(p.ctx,
+        'DomainLayer/SecurityModule/' + clazz + '.tmpl',
+        'model/src/main/java/' + p.javaPackageDir + '/model/security/' + clazz + '.java');
+}
diff --git a/tools/generator-polygene/app/templates/DomainLayer/bootstrap.tmpl b/tools/generator-polygene/app/templates/DomainLayer/bootstrap.tmpl
new file mode 100644
index 0000000..638941f
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/bootstrap.tmpl
@@ -0,0 +1,45 @@
+<%#
+ *  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 <%= polygene.packageName %>.bootstrap.domain;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.layered.LayerAssembler;
+import org.apache.polygene.bootstrap.layered.LayeredLayerAssembler;
+
+public class DomainLayer extends LayeredLayerAssembler
+    implements LayerAssembler
+{
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+<% if( polygene.applicationtype === 'Rest API' ) {
+%>        createModule( layer, CrudModule.class );<%
+}
+for( var mod in polygene.modules ) {%>
+<%- "        createModule( layer, " + polygene.firstUpper(mod) + "Module.class );" %><%
+}
+if( hasFeature( 'security' ) ) {
+%>        createModule( layer, SecurityModule.class );<%
+} %>
+        return layer;
+    }
+}
\ No newline at end of file
diff --git a/tools/generator-polygene/app/templates/DomainLayer/layer.js b/tools/generator-polygene/app/templates/DomainLayer/layer.js
new file mode 100644
index 0000000..7ed9307
--- /dev/null
+++ b/tools/generator-polygene/app/templates/DomainLayer/layer.js
@@ -0,0 +1,27 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        p.copyTemplate(p.ctx,
+            'DomainLayer/bootstrap.tmpl',
+            'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/domain/DomainLayer.java');
+        p.copyModules(__dirname );
+    }
+};
diff --git a/tools/generator-polygene/app/templates/InfrastructureLayer/CachingModule/bootstrap.tmpl b/tools/generator-polygene/app/templates/InfrastructureLayer/CachingModule/bootstrap.tmpl
new file mode 100644
index 0000000..d9d86a9
--- /dev/null
+++ b/tools/generator-polygene/app/templates/InfrastructureLayer/CachingModule/bootstrap.tmpl
@@ -0,0 +1,51 @@
+<%#
+ *  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 <%= polygene.packageName %>.bootstrap.infrastructure;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.cache.<%- polygene.caching.toLowerCase() %>.assembly.<%- polygene.caching %>Assembler;
+
+public class <%- polygene.caching %>CachingModule
+    implements ModuleAssembler
+{
+    public static final String NAME = "<%- polygene.caching %> Caching Module";
+    private final ModuleAssembly configModule;
+
+    public <%- polygene.caching %>CachingModule( ModuleAssembly configModule )
+    {
+        this.configModule = configModule;
+    }
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        new <%- polygene.caching %>Assembler()
+            .visibleIn(Visibility.layer)
+            .withConfig( configModule, Visibility.application )
+            .assemble( module );
+
+        return module;
+    }
+}
\ No newline at end of file
diff --git a/tools/generator-polygene/app/templates/InfrastructureLayer/CachingModule/module.js b/tools/generator-polygene/app/templates/InfrastructureLayer/CachingModule/module.js
new file mode 100644
index 0000000..70be49c
--- /dev/null
+++ b/tools/generator-polygene/app/templates/InfrastructureLayer/CachingModule/module.js
@@ -0,0 +1,29 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        if (p.caching !== "None") {
+
+            p.copyTemplate(p.ctx,
+                'InfrastructureLayer/CachingModule/bootstrap.tmpl',
+                'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/infrastructure/' + p.caching + 'CachingModule.java');
+        }
+    }
+};
diff --git a/tools/generator-polygene/app/templates/InfrastructureLayer/FileConfigurationModule/bootstrap.tmpl b/tools/generator-polygene/app/templates/InfrastructureLayer/FileConfigurationModule/bootstrap.tmpl
new file mode 100644
index 0000000..380cc19
--- /dev/null
+++ b/tools/generator-polygene/app/templates/InfrastructureLayer/FileConfigurationModule/bootstrap.tmpl
@@ -0,0 +1,41 @@
+<%#
+ *  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 <%= polygene.packageName %>.bootstrap.infrastructure;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.library.fileconfig.FileConfigurationAssembler;
+
+public class FileConfigurationModule
+    implements ModuleAssembler
+{
+    public static String NAME;
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        new FileConfigurationAssembler().visibleIn( Visibility.layer ).assemble( module );
+        return module;
+    }
+}
\ No newline at end of file
diff --git a/tools/generator-polygene/app/templates/InfrastructureLayer/FileConfigurationModule/module.js b/tools/generator-polygene/app/templates/InfrastructureLayer/FileConfigurationModule/module.js
new file mode 100644
index 0000000..3caecab
--- /dev/null
+++ b/tools/generator-polygene/app/templates/InfrastructureLayer/FileConfigurationModule/module.js
@@ -0,0 +1,26 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        p.copyTemplate(p.ctx,
+            'InfrastructureLayer/FileConfigurationModule/bootstrap.tmpl',
+            'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/infrastructure/FileConfigurationModule.java');
+    }
+};
diff --git a/tools/generator-polygene/app/templates/InfrastructureLayer/IndexingModule/bootstrap.tmpl b/tools/generator-polygene/app/templates/InfrastructureLayer/IndexingModule/bootstrap.tmpl
new file mode 100644
index 0000000..6648c9f
--- /dev/null
+++ b/tools/generator-polygene/app/templates/InfrastructureLayer/IndexingModule/bootstrap.tmpl
@@ -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 <%= polygene.packageName %>.bootstrap.infrastructure;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.index.<%- polygene.indexing.toLowerCase() %>.assembly.<%- polygene.indexing %>IndexingAssembler;
+
+public class <%- polygene.indexing %>IndexingModule
+    implements ModuleAssembler
+{
+    public static final String NAME = "<%- polygene.indexing %> Indexing Module";
+    private final ModuleAssembly configModule;
+
+    public <%- polygene.indexing %>IndexingModule( ModuleAssembly configModule )
+    {
+        this.configModule = configModule;
+    }
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        new <%- polygene.indexing %>IndexingAssembler()
+            .visibleIn( Visibility.application )
+            .identifiedBy( "indexing-<%- polygene.indexing.toLowerCase() %>" )
+            .withConfig( configModule, Visibility.application )
+            .assemble( module );
+        return module;
+    }
+}
+
diff --git a/tools/generator-polygene/app/templates/InfrastructureLayer/IndexingModule/module.js b/tools/generator-polygene/app/templates/InfrastructureLayer/IndexingModule/module.js
new file mode 100644
index 0000000..9d7f4e4
--- /dev/null
+++ b/tools/generator-polygene/app/templates/InfrastructureLayer/IndexingModule/module.js
@@ -0,0 +1,26 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        p.copyTemplate(p.ctx,
+            'InfrastructureLayer/IndexingModule/bootstrap.tmpl',
+            'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/infrastructure/' + p.indexing + 'IndexingModule.java');
+    }
+};
diff --git a/tools/generator-polygene/app/templates/InfrastructureLayer/MetricsModule/bootstrap.tmpl b/tools/generator-polygene/app/templates/InfrastructureLayer/MetricsModule/bootstrap.tmpl
new file mode 100644
index 0000000..d06c9cc
--- /dev/null
+++ b/tools/generator-polygene/app/templates/InfrastructureLayer/MetricsModule/bootstrap.tmpl
@@ -0,0 +1,48 @@
+<%#
+ *  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 <%= polygene.packageName %>.bootstrap.infrastructure;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.metrics.<%- polygene.metrics.toLowerCase() %>.assembly.<%- polygene.metrics %>MetricsAssembler;
+
+public class <%- polygene.metrics %>MetricsModule
+    implements ModuleAssembler
+{
+    public static final String NAME = "<%- polygene.metrics %> Metrics Module";
+    private final ModuleAssembly configModule;
+
+    public <%- polygene.metrics %>MetricsModule( ModuleAssembly configModule )
+    {
+        this.configModule = configModule;
+    }
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        new <%- polygene.metrics %>MetricsAssembler().assemble( module );
+        return module;
+    }
+}
+
diff --git a/tools/generator-polygene/app/templates/InfrastructureLayer/MetricsModule/module.js b/tools/generator-polygene/app/templates/InfrastructureLayer/MetricsModule/module.js
new file mode 100644
index 0000000..2d426b9
--- /dev/null
+++ b/tools/generator-polygene/app/templates/InfrastructureLayer/MetricsModule/module.js
@@ -0,0 +1,28 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        if (p.metrics !== "None") {
+            p.copyTemplate(p.ctx,
+                'InfrastructureLayer/MetricsModule/bootstrap.tmpl',
+                'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/infrastructure/' + p.metrics + 'MetricsModule.java');
+        }
+    }
+};
diff --git a/tools/generator-polygene/app/templates/InfrastructureLayer/SerializationModule/bootstrap.tmpl b/tools/generator-polygene/app/templates/InfrastructureLayer/SerializationModule/bootstrap.tmpl
new file mode 100644
index 0000000..7ff8b96
--- /dev/null
+++ b/tools/generator-polygene/app/templates/InfrastructureLayer/SerializationModule/bootstrap.tmpl
@@ -0,0 +1,43 @@
+<%#
+ *  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 <%= polygene.packageName %>.bootstrap.infrastructure;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.serialization.<%- polygene.serialization.toLowerCase() %>.assembly.<%- polygene.serialization %>SerializationAssembler;
+
+public class <%- polygene.serialization %>SerializationModule
+    implements ModuleAssembler
+{
+    public static final String NAME = "<%- polygene.serialization %> Serialization Module";
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        new <%- polygene.serialization %>SerializationAssembler()
+            .visibleIn( Visibility.application )
+            .assemble( module );
+        return module;
+    }
+}
diff --git a/tools/generator-polygene/app/templates/InfrastructureLayer/SerializationModule/module.js b/tools/generator-polygene/app/templates/InfrastructureLayer/SerializationModule/module.js
new file mode 100644
index 0000000..6afd62e
--- /dev/null
+++ b/tools/generator-polygene/app/templates/InfrastructureLayer/SerializationModule/module.js
@@ -0,0 +1,26 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        p.copyTemplate(p.ctx,
+            'InfrastructureLayer/SerializationModule/bootstrap.tmpl',
+            'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/infrastructure/' + p.serialization + 'SerializationModule.java');
+    }
+};
diff --git a/tools/generator-polygene/app/templates/InfrastructureLayer/StorageModule/bootstrap.tmpl b/tools/generator-polygene/app/templates/InfrastructureLayer/StorageModule/bootstrap.tmpl
new file mode 100644
index 0000000..1583636
--- /dev/null
+++ b/tools/generator-polygene/app/templates/InfrastructureLayer/StorageModule/bootstrap.tmpl
@@ -0,0 +1,51 @@
+<%#
+ *  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 <%= polygene.packageName %>.bootstrap.infrastructure;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+import org.apache.polygene.entitystore.<%- polygene.entitystoremodule %>.assembly.<%- polygene.entitystore %>EntityStoreAssembler;
+
+public class <%- polygene.entitystore %>StorageModule
+    implements ModuleAssembler
+{
+    public static final String NAME = "<%- polygene.entitystore %> Storage Module";
+    private final ModuleAssembly configModule;
+
+    public <%- polygene.entitystore %>StorageModule( ModuleAssembly configModule )
+    {
+        this.configModule = configModule;
+    }
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        new <%- polygene.entitystore %>EntityStoreAssembler()
+            .visibleIn( Visibility.application  )
+            .withConfig( configModule, Visibility.application )
+            .identifiedBy( "entitystore-<%- polygene.entitystore.toLowerCase() %>" )
+            .assemble( module );
+        return module;
+    }
+}
\ No newline at end of file
diff --git a/tools/generator-polygene/app/templates/InfrastructureLayer/StorageModule/module.js b/tools/generator-polygene/app/templates/InfrastructureLayer/StorageModule/module.js
new file mode 100644
index 0000000..3c17fcc
--- /dev/null
+++ b/tools/generator-polygene/app/templates/InfrastructureLayer/StorageModule/module.js
@@ -0,0 +1,26 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        p.copyTemplate(p.ctx,
+            'InfrastructureLayer/StorageModule/bootstrap.tmpl',
+            'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/infrastructure/' + p.entitystore + 'StorageModule.java');
+    }
+};
diff --git a/tools/generator-polygene/app/templates/InfrastructureLayer/bootstrap.tmpl b/tools/generator-polygene/app/templates/InfrastructureLayer/bootstrap.tmpl
new file mode 100644
index 0000000..1ba3098
--- /dev/null
+++ b/tools/generator-polygene/app/templates/InfrastructureLayer/bootstrap.tmpl
@@ -0,0 +1,55 @@
+<%#
+ *  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 <%= polygene.packageName %>.bootstrap.infrastructure;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.LayerAssembler;
+import org.apache.polygene.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
+    {
+        createModule( layer, FileConfigurationModule.class );
+        createModule( layer, <%= polygene.serialization %>SerializationModule.class );
+<% if( polygene.metrics !== "None" ) { %>
+        createModule( layer, <%= polygene.metrics %>MetricsModule.class );
+<% } %>
+<% if( polygene.caching !== "None" ) { %>
+        createModule( layer, <%= polygene.caching %>CachingModule.class );
+<% } %>
+        new <%= polygene.entitystore %>StorageModule( configModule ).assemble( layer, layer.module( <%= polygene.entitystore %>StorageModule.NAME ) );
+        new <%= polygene.indexing %>IndexingModule( configModule ).assemble( layer, layer.module( <%= polygene.indexing %>IndexingModule.NAME ) );
+        return layer;
+    }
+}
\ No newline at end of file
diff --git a/tools/generator-polygene/app/templates/InfrastructureLayer/layer.js b/tools/generator-polygene/app/templates/InfrastructureLayer/layer.js
new file mode 100644
index 0000000..8e7930c
--- /dev/null
+++ b/tools/generator-polygene/app/templates/InfrastructureLayer/layer.js
@@ -0,0 +1,27 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        p.copyTemplate(p.ctx,
+            'InfrastructureLayer/bootstrap.tmpl',
+            'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/infrastructure/InfrastructureLayer.java');
+        p.copyModules(__dirname );
+    }
+};
diff --git a/tools/generator-polygene/app/templates/RestAPIApplication/app.js b/tools/generator-polygene/app/templates/RestAPIApplication/app.js
new file mode 100644
index 0000000..80380c7
--- /dev/null
+++ b/tools/generator-polygene/app/templates/RestAPIApplication/app.js
@@ -0,0 +1,36 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        copyLayer(p, "Configuration");
+        copyLayer(p, "Infrastructure");
+        copyLayer(p, "Domain");
+        copyLayer(p, "Connectivity");
+
+        p.copyTemplate(p.ctx,
+            'RestAPIApplication/web.xml.tmpl',
+            'app/src/main/webapp/WEB-INF/web.xml');
+    }
+};
+
+function copyLayer(p, layerName) {
+    var layer = require(__dirname + '/../' + layerName + 'Layer/layer.js');
+    layer.write(p);
+}
diff --git a/tools/generator-polygene/app/templates/RestAPIApplication/web.xml.tmpl b/tools/generator-polygene/app/templates/RestAPIApplication/web.xml.tmpl
new file mode 100644
index 0000000..bdc6301
--- /dev/null
+++ b/tools/generator-polygene/app/templates/RestAPIApplication/web.xml.tmpl
@@ -0,0 +1,46 @@
+<%#
+  ~  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.
+  ~
+  ~
+%><?xml version="1.0" encoding="UTF-8"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+         version="2.5">
+
+    <display-name><%= polygene.name %></display-name>
+<% if( polygene.hasFeature( "security" )) { %>
+    <listener>
+        <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
+    </listener>
+<% } %>
+<% if( polygene.hasFeature( "security" ) ) { %>
+    <filter>
+        <filter-name>ShiroFilter</filter-name>
+        <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
+    </filter>
+<% } %>
+<% if( polygene.hasFeature( "security" ) ) { %>
+    <!-- Filter all web requests.  This filter mapping is typically declared
+        before all others to ensure any other filters are secured as well: -->
+    <filter-mapping>
+        <filter-name>ShiroFilter</filter-name>
+        <url-pattern>/*</url-pattern>
+    </filter-mapping>
+<% } %>
+
+</web-app>
diff --git a/tools/generator-polygene/app/templates/UserInterfaceLayer/CommandLineModule/bootstrap.tmpl b/tools/generator-polygene/app/templates/UserInterfaceLayer/CommandLineModule/bootstrap.tmpl
new file mode 100644
index 0000000..eb158c8
--- /dev/null
+++ b/tools/generator-polygene/app/templates/UserInterfaceLayer/CommandLineModule/bootstrap.tmpl
@@ -0,0 +1,38 @@
+<%#
+ *  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 <%= polygene.packageName %>.bootstrap.ui;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.layered.ModuleAssembler;
+
+public class CommandLineModule
+    implements ModuleAssembler
+{
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException
+    {
+        // AUTO-GENERATION not supported yet.
+        return module;
+    }
+}
\ No newline at end of file
diff --git a/tools/generator-polygene/app/templates/UserInterfaceLayer/CommandLineModule/module.js b/tools/generator-polygene/app/templates/UserInterfaceLayer/CommandLineModule/module.js
new file mode 100644
index 0000000..3da8821
--- /dev/null
+++ b/tools/generator-polygene/app/templates/UserInterfaceLayer/CommandLineModule/module.js
@@ -0,0 +1,29 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        if (p.applicationtype === 'Command Line') {
+            // NOT SUPPORTED YET!!!
+            p.copyTemplate(p.ctx,
+                'UserInterfaceLayer/CommandLineModule/bootstrap.tmpl',
+                'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/ui/CommandLineModule.java');
+        }
+    }
+};
diff --git a/tools/generator-polygene/app/templates/UserInterfaceLayer/bootstrap.tmpl b/tools/generator-polygene/app/templates/UserInterfaceLayer/bootstrap.tmpl
new file mode 100644
index 0000000..a0208b0
--- /dev/null
+++ b/tools/generator-polygene/app/templates/UserInterfaceLayer/bootstrap.tmpl
@@ -0,0 +1,39 @@
+<%#
+ *  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 <%= polygene.packageName %>.bootstrap.ui;
+
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.layered.LayerAssembler;
+import org.apache.polygene.bootstrap.layered.LayeredLayerAssembler;
+
+public class UserInterfaceLayer extends LayeredLayerAssembler
+    implements LayerAssembler
+{
+    public static String NAME;
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        createModule( layer, CommandLineModule.class );
+        return layer;
+    }
+}
\ No newline at end of file
diff --git a/tools/generator-polygene/app/templates/UserInterfaceLayer/layer.js b/tools/generator-polygene/app/templates/UserInterfaceLayer/layer.js
new file mode 100644
index 0000000..36e0060
--- /dev/null
+++ b/tools/generator-polygene/app/templates/UserInterfaceLayer/layer.js
@@ -0,0 +1,27 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        p.copyTemplate(p.ctx,
+            'UserInterfaceLayer/bootstrap.tmpl',
+            'bootstrap/src/main/java/' + p.javaPackageDir + '/bootstrap/ui/UserInterfaceLayer.java');
+        p.copyModules(__dirname );
+    }
+};
diff --git a/tools/generator-polygene/app/templates/buildtool/build.js b/tools/generator-polygene/app/templates/buildtool/build.js
new file mode 100644
index 0000000..630908f
--- /dev/null
+++ b/tools/generator-polygene/app/templates/buildtool/build.js
@@ -0,0 +1,42 @@
+/*
+ *  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.
+ */
+
+module.exports = {
+
+    write: function (p) {
+        copyBuildFile(p, "app");
+        copyBuildFile(p, "bootstrap");
+        copyBuildFile(p, "model");
+        if( p.applicationtype === 'Rest API'){
+            copyBuildFile(p, "rest");
+        }
+        p.copyTemplate(p.ctx, 'buildtool/gradle-root.tmpl', 'build.gradle');
+        p.copyTemplate(p.ctx, 'buildtool/settings.tmpl', 'settings.gradle');
+        p.copyTemplate(p.ctx, 'buildtool/gradlew.tmpl', 'gradlew');
+        p.copyTemplate(p.ctx, 'buildtool/gradlew-bat.tmpl', 'gradlew.bat');
+
+        p.ctx.fs.copy(p.ctx.templatePath('buildtool/gradle-wrapper.jar_'), p.ctx.destinationPath('gradle/wrapper/gradle-wrapper.jar'));
+        p.ctx.fs.copy(p.ctx.templatePath('buildtool/gradle-wrapper.properties_'), p.ctx.destinationPath('gradle/wrapper/gradle-wrapper.properties'));
+    }
+};
+
+function copyBuildFile(p, subproject) {
+    p.copyTemplate(p.ctx,
+        'buildtool/gradle-' + subproject + '.tmpl',
+        subproject + '/build.gradle');
+}
diff --git a/tools/generator-polygene/app/templates/buildtool/gradle-app.tmpl b/tools/generator-polygene/app/templates/buildtool/gradle-app.tmpl
new file mode 100644
index 0000000..623ee78
--- /dev/null
+++ b/tools/generator-polygene/app/templates/buildtool/gradle-app.tmpl
@@ -0,0 +1,42 @@
+<%#
+ *  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.
+ *
+ *
+-%>
+
+plugins {
+  id 'war'
+  id "org.akhikhl.gretty" version "1.4.0"
+}
+
+dependencies {
+  compile project( ":bootstrap" )
+  compile project( ":model" )
+<% if( polygene.applicationtype === 'Rest API' ) {
+%>  compile project( ":rest" )<% } %>
+
+  compile "org.apache.polygene.core:org.apache.polygene.core.spi:$polygeneVersion"
+  compile "org.apache.polygene.core:org.apache.polygene.core.bootstrap:$polygeneVersion"
+  compile "org.apache.polygene.libraries:org.apache.polygene.library.servlet:$polygeneVersion"
+<% if( polygene.applicationtype === 'Rest API' ) {
+%>  compile "javax.servlet:servlet-api:2.5"
+  compile "org.restlet.jee:org.restlet:2.3.4"<% } %>
+
+  runtime "org.apache.polygene.core:org.apache.polygene.core.runtime:$polygeneVersion"
+  runtime "org.restlet.jee:org.restlet.ext.servlet:2.3.4"
+
+}
diff --git a/tools/generator-polygene/app/templates/buildtool/gradle-bootstrap.tmpl b/tools/generator-polygene/app/templates/buildtool/gradle-bootstrap.tmpl
new file mode 100644
index 0000000..0d8dab2
--- /dev/null
+++ b/tools/generator-polygene/app/templates/buildtool/gradle-bootstrap.tmpl
@@ -0,0 +1,44 @@
+<%#
+ *  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.
+ *
+ *
+-%>
+dependencies {
+  compile project( ":model" )
+<% if( polygene.applicationtype === 'Rest API' ) {
+%>  compile project( ":rest" )<% } %>
+
+  compile "org.apache.polygene.core:org.apache.polygene.core.spi:$polygeneVersion"
+  compile "org.apache.polygene.core:org.apache.polygene.core.bootstrap:$polygeneVersion"
+
+  compile "org.apache.polygene.libraries:org.apache.polygene.library.fileconfig:$polygeneVersion"
+<% if( polygene.applicationtype === 'Rest API' ) { %>
+  compile "org.apache.polygene.libraries:org.apache.polygene.library.restlet:$polygeneVersion"
+<% } %>
+  compile "org.apache.polygene.extensions:org.apache.polygene.extension.entitystore-<%= polygene.entitystoremodule.toLowerCase() %>:$polygeneVersion"
+  compile "org.apache.polygene.extensions:org.apache.polygene.extension.indexing-<%= polygene.indexing.toLowerCase() %>:$polygeneVersion"
+  compile "org.apache.polygene.extensions:org.apache.polygene.extension.serialization-<%= polygene.serialization.toLowerCase() %>:$polygeneVersion"
+
+<% if( polygene.caching !== "None" ) { %>
+  compile "org.apache.polygene.extensions:org.apache.polygene.extension.cache-<%= polygene.caching.toLowerCase() %>:$polygeneVersion"
+<% } %>
+
+<% if( polygene.metrics !== "None" ) { %>
+  compile "org.apache.polygene.extensions:org.apache.polygene.extension.metrics-<%= polygene.metrics.toLowerCase() %>:$polygeneVersion"
+<% } %>
+
+}
\ No newline at end of file
diff --git a/tools/generator-polygene/app/templates/buildtool/gradle-model.tmpl b/tools/generator-polygene/app/templates/buildtool/gradle-model.tmpl
new file mode 100644
index 0000000..d9a954f
--- /dev/null
+++ b/tools/generator-polygene/app/templates/buildtool/gradle-model.tmpl
@@ -0,0 +1,36 @@
+<%#
+ *  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.
+ *
+ *
+-%>
+
+dependencies {
+
+<% if( hasFeature( 'security' ) ) {
+%>    compile "org.apache.polygene.libraries:org.apache.polygene.library.shiro-core:$polygeneVersion"
+<% } %>
+<% if( polygene.applicationtype === 'Rest API' ) {
+%>    compile "org.apache.polygene.libraries:org.apache.polygene.library.restlet:$polygeneVersion"
+<% } %>
+<% if( polygene.hasFeature( 'mixin scripting' ) ) {
+%>    compile "org.apache.polygene.libraries:org.apache.polygene.library.scripting:$polygeneVersion"
+<% } %>
+<% if( polygene.hasFeature( 'jmx' ) ) {
+%>    compile "org.apache.polygene.libraries:org.apache.polygene.library.jmx:$polygeneVersion"
+<% } %>
+
+}
diff --git a/tools/generator-polygene/app/templates/buildtool/gradle-rest.tmpl b/tools/generator-polygene/app/templates/buildtool/gradle-rest.tmpl
new file mode 100644
index 0000000..d07ac02
--- /dev/null
+++ b/tools/generator-polygene/app/templates/buildtool/gradle-rest.tmpl
@@ -0,0 +1,29 @@
+<%#
+ *  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.
+ *
+ *
+-%>
+
+dependencies {
+  compile project( ":model" )
+
+  compile "org.apache.polygene.core:org.apache.polygene.core.api:$polygeneVersion"
+<% if( polygene.applicationtype === 'Rest API' ) {
+%>    compile "org.apache.polygene.libraries:org.apache.polygene.library.restlet:$polygeneVersion"
+<% } %>
+
+}
\ No newline at end of file
diff --git a/tools/generator-polygene/app/templates/buildtool/gradle-root.tmpl b/tools/generator-polygene/app/templates/buildtool/gradle-root.tmpl
new file mode 100644
index 0000000..52b61d5
--- /dev/null
+++ b/tools/generator-polygene/app/templates/buildtool/gradle-root.tmpl
@@ -0,0 +1,44 @@
+<%#
+ *  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.
+ *
+ *
+-%>
+
+version = 1.0
+
+rootProject.ext {
+  polygeneVersion = "<%=polygene.version %>"
+}
+
+allprojects() {
+  apply plugin: 'java'
+  apply plugin: 'maven'
+
+  defaultTasks 'assemble'
+
+  repositories {
+    mavenCentral()
+    maven { name 'restlet-repo'; url 'http://maven.restlet.org/' }
+<% if( polygene.entitystore == 'Jdbm' ) {
+-%>    maven { name 'clojure-repo'; url 'http://clojars.org/repo/' }<% } -%>
+  }
+
+  dependencies {
+    compile "org.apache.polygene.core:org.apache.polygene.core.api:$polygeneVersion"
+    testCompile "org.apache.polygene.core:org.apache.polygene.core.testsupport:$polygeneVersion"
+  }
+}
diff --git a/tools/generator-polygene/app/templates/buildtool/gradle-wrapper.jar_ b/tools/generator-polygene/app/templates/buildtool/gradle-wrapper.jar_
new file mode 100644
index 0000000..0087cd3
--- /dev/null
+++ b/tools/generator-polygene/app/templates/buildtool/gradle-wrapper.jar_
Binary files differ
diff --git a/tools/generator-polygene/app/templates/buildtool/gradle-wrapper.properties_ b/tools/generator-polygene/app/templates/buildtool/gradle-wrapper.properties_
new file mode 100644
index 0000000..63a2f23
--- /dev/null
+++ b/tools/generator-polygene/app/templates/buildtool/gradle-wrapper.properties_
@@ -0,0 +1,24 @@
+<%#
+ *  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.
+ *
+ *
+-%>
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-all.zip
diff --git a/tools/generator-polygene/app/templates/buildtool/gradlew-bat.tmpl b/tools/generator-polygene/app/templates/buildtool/gradlew-bat.tmpl
new file mode 100644
index 0000000..3d06f18
--- /dev/null
+++ b/tools/generator-polygene/app/templates/buildtool/gradlew-bat.tmpl
@@ -0,0 +1,109 @@
+<%#
+ *  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.
+ *
+ *
+-%>
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/tools/generator-polygene/app/templates/buildtool/gradlew.tmpl b/tools/generator-polygene/app/templates/buildtool/gradlew.tmpl
new file mode 100755
index 0000000..11c35cc
--- /dev/null
+++ b/tools/generator-polygene/app/templates/buildtool/gradlew.tmpl
@@ -0,0 +1,183 @@
+<%#
+ *  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.
+ *
+ *
+-%>
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/tools/generator-polygene/app/templates/buildtool/settings.tmpl b/tools/generator-polygene/app/templates/buildtool/settings.tmpl
new file mode 100644
index 0000000..b46209f
--- /dev/null
+++ b/tools/generator-polygene/app/templates/buildtool/settings.tmpl
@@ -0,0 +1,28 @@
+<%#
+ *  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.
+ *
+ *
+-%>
+include 'app',
+        'bootstrap',<%
+if( polygene.applicationtype === 'Rest API' ) { %>
+        'model',
+        'rest'<% } else { %>
+        'model'
+<% } %>
+
+rootProject.name = '<%= polygene.name %>'
diff --git a/tools/generator-polygene/build.gradle b/tools/generator-polygene/build.gradle
new file mode 100644
index 0000000..06eaa0e
--- /dev/null
+++ b/tools/generator-polygene/build.gradle
@@ -0,0 +1,100 @@
+/*
+ *  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.
+ *
+ *
+ */
+
+apply plugin: 'polygene-tool-npm'
+
+description = "Apache Polygene™ Project Generator."
+
+/**
+ * Modifies package.json in-place to set `polygene_version`.
+ * Loaded by the generator, see `app/index.js`
+ */
+def setsCurrentVersionToPackageJson = task( 'setsCurrentVersionToPackageJson' ) {
+  outputs.upToDateWhen { false }
+  doLast {
+    def packageJson = file( 'package.json' )
+    packageJson.text = packageJson.text.replaceFirst( /\"polygene_version\": \".*\"/,
+                                                      "\"polygene_version\": \"${ project.version }\"" )
+  }
+}
+
+/**
+ * Generate a Gradle init script that registers a maven repository with the currently built artifacts.
+ * Used by the generator tests.
+ */
+def generateStageMavenRepositoryInitScript = task( 'generateStageMavenRepositoryInitScript' ) {
+  def initScript = file( "$buildDir/stagedMavenRepoInitScript.gradle" )
+  def repoDir = file( "${ rootProject.rootDir }/distributions/build/stage/maven-binaries" )
+  dependsOn ':distributions:stageBinariesMavenRepository'
+  inputs.property 'polygene_version', project.version
+  outputs.file initScript
+  doLast {
+    initScript.parentFile.mkdirs()
+    initScript.text = """
+      allprojects {
+        repositories {
+          maven { url = "file://${ repoDir.absolutePath }" }
+        }
+      }
+    """.stripIndent()
+  }
+}
+
+/**
+ * Runs the generator tests.
+ */
+def npmTest = task( 'npmTest', type: NpmTask ) {
+  dependsOn 'npmInstall', setsCurrentVersionToPackageJson, generateStageMavenRepositoryInitScript
+  description = 'Runs Polygene generator tests'
+  args = [ 'run', 'test' ]
+  inputs.file file( 'package.json' )
+  inputs.dir file( 'app' )
+  inputs.dir file( 'test' )
+  outputs.dir file( "${ buildDir }/reports/tests/npmTest" )
+  doFirst {
+    // Cleanup generated projects to always run from a fresh state
+    file( "$buildDir/build/npm-test" ).deleteDir()
+  }
+}
+check.dependsOn npmTest
+
+/**
+ * Runs ALL the generator tests.
+ */
+task( 'npmTestAll', type: NpmTask ) {
+  dependsOn 'npmInstall', setsCurrentVersionToPackageJson, generateStageMavenRepositoryInitScript
+  description = 'Runs ALL possible permutations of the Polygene generator tests'
+  args = [ 'run', 'test_all' ]
+  inputs.file file( 'package.json' )
+  inputs.dir file( 'app' )
+  inputs.dir file( 'test' )
+  outputs.dir file( "${ buildDir }/reports/tests/npmTestAll" )
+  doFirst {
+    // Cleanup generated projects to always run from a fresh state
+    file( "$buildDir/build/npm-test" ).deleteDir()
+  }
+}
+
+// TODO This disable generator checks that fails on CI - TODO REMOVE ME
+// See https://builds.apache.org/view/P/view/Polygene/job/Polygene(JavaEdition)-develop-java8-check/341/console
+if( System.getenv( 'BUILD_ID' ) != null )
+{
+  npmTest.enabled = false
+}
diff --git a/tools/generator-polygene/dev-status.xml b/tools/generator-polygene/dev-status.xml
new file mode 100644
index 0000000..dc6c0e6
--- /dev/null
+++ b/tools/generator-polygene/dev-status.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
+  <status>
+    <!--none,early,beta,stable,mature-->
+    <codebase>stable</codebase>
+
+    <!-- none, brief, good, complete -->
+    <documentation>good</documentation>
+
+    <!-- none, some, good, complete -->
+    <unittests>complete</unittests>
+
+  </status>
+  <licenses>
+    <license>ALv2</license>
+  </licenses>
+</module>
diff --git a/tools/generator-polygene/package.json b/tools/generator-polygene/package.json
new file mode 100644
index 0000000..57ac117
--- /dev/null
+++ b/tools/generator-polygene/package.json
@@ -0,0 +1,39 @@
+{
+  "name": "generator-polygene",
+  "version": "3.0.0",
+  "polygene_version": "3.0.0",
+  "description": "Generates an Apache Polygene project.",
+  "homepage": "https://polygene.apache.org",
+  "license": "Apache-2.0",
+  "bugs": {
+    "mail": "dev@polygene.apache.org",
+    "url": "https://issues.apache.org/jira/browse/POLYGENE"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://git-wip-us.apache.org/repos/asf/polygene-java.git"
+  },
+  "scripts": {
+    "test": "mocha ./test/generator_test.js --reporter mocha-junit-reporter --reporter-options mochaFile=../../reports/tests/npmTest/generator-polygene.xml",
+    "test_all": "TEST_ALL=yes mocha ./test/generator_test.js --reporter mocha-junit-reporter --reporter-options mochaFile=../../reports/tests/npmTestAll/generator-polygene.xml"
+  },
+  "keywords": [
+    "yeoman-generator",
+    "apache-polygene"
+  ],
+  "preferGlobal": true,
+  "files": [
+    "app"
+  ],
+  "dependencies": {
+    "yeoman-generator": "0.24.1"
+  },
+  "devDependencies": {
+    "mocha": "3.2.0",
+    "mocha-junit-reporter": "1.13.0",
+    "path": "0.12.7",
+    "shelljs": "0.7.7",
+    "yeoman-assert": "3.0.0",
+    "yeoman-test": "1.6.0"
+  }
+}
diff --git a/tools/generator-polygene/test/generator_test.js b/tools/generator-polygene/test/generator_test.js
new file mode 100644
index 0000000..d4ee454
--- /dev/null
+++ b/tools/generator-polygene/test/generator_test.js
@@ -0,0 +1,173 @@
+/*
+ *  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.
+ */
+
+var path = require('path');
+var helpers = require('yeoman-test');
+var assert = require('yeoman-assert');
+var shell = require('shelljs');
+
+//See http://yeoman.io/authoring/testing.html
+
+// test with all defaults first.
+test();
+
+var appTypes = [
+    "Rest API",
+    'Command Line'
+];
+
+var entityStores = [
+    'Cassandra',
+    'File',
+    'DerbySQL',
+    'Geode',
+    'H2SQL',
+    'Hazelcast',
+    'JClouds',
+    'Jdbm',
+    'LevelDB',
+    'MongoDB',
+    'MySQL',
+    'Preferences',
+    'Redis',
+    'Riak',
+    'PostgreSQL',
+    'SQLite',
+    'Memory'   // Somehow the last EntityStore is used in subsequent test arrays. Pick the fastest.
+];
+
+var indexings = [
+    'Rdf',
+    'ElasticSearch',
+    'Solr',
+    'SQL'
+];
+
+var cachings = [
+    'None',
+    'Memcache',
+    'EhCache'
+];
+
+var serializations = [
+    'JavaxJson',
+    'JavaxXml',
+    'MessagePack'
+];
+
+var metricses = [
+    'None',
+    'Codahale'
+];
+
+var featuresset = [
+    [],
+    ['jmx'],
+    ['mixin scripting'],
+    ['security'],
+    ['jmx', 'mixin scripting'],
+    ['jmx', 'scripting'],
+    ['mixin scripting', 'scripting'],
+    ['jmx', 'mixin scripting', 'scripting']
+];
+
+appTypes.forEach(function (appType) {
+    test(appType, "Memory", "Rdf", "JavaxJson", "Memcache", "Codahale", "[]");
+});
+
+entityStores.forEach(function (entityStore) {
+    test("Rest API", entityStore, "Rdf", "JavaxJson", "Memcache", "Codahale", "[]");
+});
+
+indexings.forEach(function (indexing) {
+    test("Rest API", "Memory", indexing, "JavaxJson", "Memcache", "Codahale", "[]");
+});
+
+serializations.forEach(function (serialization) {
+    test("Rest API", "Memory", "Rdf", serialization, "Memcache", "Codahale", "[]");
+});
+
+cachings.forEach(function (caching) {
+    test("Rest API", "Memory", "Rdf", "JavaxJson", caching, "Codahale", "[]");
+});
+
+metricses.forEach(function (metrics) {
+    test("Rest API", "Memory", "Rdf", "JavaxJson", "Memcache", metrics, "[]");
+});
+
+featuresset.forEach(function (feature) {
+    test("Rest API", "Memory", "Rdf", "JavaxJson", "Memcache", "Codahale", feature);
+});
+
+// All Tests !!!!
+if(process.env.TEST_ALL == 'yes') {
+    appTypes.forEach(function (appType) {
+        entityStores.forEach(function (entitystore) {
+            indexings.forEach(function (indexing) {
+                serializations.forEach(function (serialization) {
+                    cachings.forEach(function (caching) {
+                        metricses.forEach(function (metrics) {
+                            featuresset.forEach(function (features) {
+                                test(appType, entitystore, indexing, serialization, caching, metrics, features)
+                            });
+                        });
+                    });
+                });
+            });
+        });
+    });
+}
+
+function test(appType, entityStore, indexing, serialization, caching, metrics, features) {
+    describe('polygene-generator', function () {
+        var testName = 'generates a Gradle buildable Apache Polygene project with '
+            + entityStore + 'EntityStore, '
+            + indexing + 'Indexing, '
+            + serialization + 'Serialization, '
+            + caching + 'Caching, '
+            + metrics + 'Metrics';
+        if(features) {
+            testName += ', and ' + features;
+        }
+        testName += '.';
+        var testDirName = testName.replace(new RegExp('[, ]','g'), '_');
+        it(testName,
+            function () {
+                this.timeout(10000);
+                return helpers.run(path.join(__dirname, '../app'))
+                    .inDir(path.join(__dirname, '../build/npm-test/'+testDirName))
+                    .withPrompts({
+                        name: 'test-project',
+                        packageName: 'org.apache.polygene.generator.test',
+                        applicationtype: appType,
+                        entitystore: entityStore,
+                        serialization: serialization,
+                        indexing: indexing,
+                        caching: caching,
+                        metrics: metrics,
+                        features: features
+                    })
+                    .then(buildAndVerify);
+            });
+    });
+}
+
+function buildAndVerify(dir) {
+    assert.file(['gradlew', 'settings.gradle', 'build.gradle']);
+    assert(shell.exec(path.join(dir, 'gradlew') + ' classes --init-script ../../stagedMavenRepoInitScript.gradle').code == 0);
+}
diff --git a/tools/model-detail/build.gradle b/tools/model-detail/build.gradle
index 2879371..c6cd684 100644
--- a/tools/model-detail/build.gradle
+++ b/tools/model-detail/build.gradle
@@ -1,33 +1,36 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Detailled Model of a Apache Zest™ Application Structure."
+apply plugin: 'polygene-tool'
 
-jar { manifest { name = "Apache Zest™ Model Detail" }}
+description = "Detailled Model of a Apache Polygene™ Application Structure."
+
+jar { manifest { name = "Apache Polygene™ Model Detail" }}
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
+  api polygene.core.bootstrap
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-  testCompile(project(":org.qi4j.extensions:org.qi4j.extension.indexing-rdf"))
+  runtimeOnly polygene.core.runtime
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
+  testImplementation polygene.core.testsupport
+  testImplementation polygene.extension( 'indexing-rdf' )
+
+  testRuntimeOnly libraries.logback
 }
-
diff --git a/tools/model-detail/dev-status.xml b/tools/model-detail/dev-status.xml
index 4458bbb..e124151 100644
--- a/tools/model-detail/dev-status.xml
+++ b/tools/model-detail/dev-status.xml
@@ -1,24 +1,27 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <!--
-  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.
--->
-<module xmlns="http://www.qi4j.org/schemas/2008/dev-status/1"
+  ~  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.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xsi:schemaLocation="http://www.qi4j.org/schemas/2008/dev-status/1
-        http://www.qi4j.org/schemas/2008/dev-status/1/dev-status.xsd">
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
   <status>
     <!--none,early,beta,stable,mature-->
     <codebase>stable</codebase>
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ActivateeDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ActivateeDetailDescriptor.java
new file mode 100644
index 0000000..83e9607
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ActivateeDetailDescriptor.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+/**
+ * Activatee Detail Descriptor.
+ */
+public interface ActivateeDetailDescriptor
+{
+    /**
+     * @return Activators of this {@literal Activatee}. Never return {@code null}.
+     */
+    Iterable<ActivatorDetailDescriptor> activators();
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ActivatorDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ActivatorDetailDescriptor.java
new file mode 100644
index 0000000..0b331e2
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ActivatorDetailDescriptor.java
@@ -0,0 +1,177 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.api.activation.ActivatorDescriptor;
+import org.apache.polygene.api.util.Visitable;
+import org.apache.polygene.api.util.Visitor;
+
+/**
+ * Activator Detail Descriptor.
+ */
+public class ActivatorDetailDescriptor
+    implements InjectableDetailDescriptor, Visitable<ActivatorDetailDescriptor>
+{
+    private final ActivatorDescriptor descriptor;
+    private final List<ConstructorDetailDescriptor> constructors;
+    private final List<InjectedMethodDetailDescriptor> injectedMethods;
+    private final List<InjectedFieldDetailDescriptor> injectedFields;
+    private ServiceDetailDescriptor service;
+    private ImportedServiceDetailDescriptor importedService;
+    private ModuleDetailDescriptor module;
+    private LayerDetailDescriptor layer;
+    private ApplicationDetailDescriptor application;
+
+    public ActivatorDetailDescriptor( ActivatorDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "Activator Descriptor" );
+        this.descriptor = descriptor;
+        constructors = new LinkedList<>();
+        injectedMethods = new LinkedList<>();
+        injectedFields = new LinkedList<>();
+    }
+
+    /**
+     * @return Service that own this {@code ActivatorDetailDescriptor}.
+     */
+    public ServiceDetailDescriptor service()
+    {
+        return service;
+    }
+
+    /**
+     * @return Imported Service that own this {@code ActivatorDetailDescriptor}.
+     */
+    public ImportedServiceDetailDescriptor importedService()
+    {
+        return importedService;
+    }
+
+    /**
+     * @return Module that own this {@code ActivatorDetailDescriptor}.
+     */
+    public ModuleDetailDescriptor module()
+    {
+        return module;
+    }
+
+    /**
+     * @return Layer that own this {@code ActivatorDetailDescriptor}.
+     */
+    public LayerDetailDescriptor layer()
+    {
+        return layer;
+    }
+
+    /**
+     * @return Application that own this {@code ActivatorDetailDescriptor}.
+     */
+    public ApplicationDetailDescriptor application()
+    {
+        return application;
+    }
+
+    @Override
+    public Iterable<ConstructorDetailDescriptor> constructors()
+    {
+        return constructors;
+    }
+
+    @Override
+    public Iterable<InjectedMethodDetailDescriptor> injectedMethods()
+    {
+        return injectedMethods;
+    }
+
+    @Override
+    public Iterable<InjectedFieldDetailDescriptor> injectedFields()
+    {
+        return injectedFields;
+    }
+
+    final void setService( ServiceDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ServiceDetailDescriptor" );
+        service = descriptor;
+    }
+
+    final void setImportedService( ImportedServiceDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ImportedServiceDetailDescriptor" );
+        importedService = descriptor;
+    }
+
+    final void setModule( ModuleDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ModuleDetailDescriptor" );
+        module = descriptor;
+    }
+
+    final void setLayer( LayerDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "LayerDetailDescriptor" );
+        layer = descriptor;
+    }
+
+    final void setApplication( ApplicationDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ApplicationDetailDescriptor" );
+        application = descriptor;
+    }
+
+    final void addConstructor( ConstructorDetailDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "ConstructorDetailDescriptor" );
+        descriptor.setActivator( this );
+        constructors.add( descriptor );
+    }
+
+    final void addInjectedMethod( InjectedMethodDetailDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "InjectedMethodDetailDescriptor" );
+        descriptor.setActivator( this );
+        injectedMethods.add( descriptor );
+    }
+
+    final void addInjectedField( InjectedFieldDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "InjectedFieldDetailDescriptor" );
+        descriptor.setActivator( this );
+        injectedFields.add( descriptor );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( Visitor<? super ActivatorDetailDescriptor, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        return visitor.visit( this );
+    }
+
+    @Override
+    public String toString()
+    {
+        return descriptor.toString();
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ApplicationDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ApplicationDetailDescriptor.java
new file mode 100644
index 0000000..fd3abc3
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ApplicationDetailDescriptor.java
@@ -0,0 +1,113 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * Application Detail Descriptor.
+ * <p>
+ * Visitable hierarchy with Activators and Layers children.
+ */
+public final class ApplicationDetailDescriptor
+    implements ActivateeDetailDescriptor, VisitableHierarchy<Object, Object>
+{
+    private final ApplicationDescriptor descriptor;
+    private final List<ActivatorDetailDescriptor> activators = new LinkedList<>();
+    private final List<LayerDetailDescriptor> layers = new LinkedList<>();
+
+    ApplicationDetailDescriptor( ApplicationDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "ApplicationDescriptor" );
+        this.descriptor = descriptor;
+    }
+
+    /**
+     * @return Descriptor of this {@code ApplicationDetailDescriptor}. Never return {@code null}.
+     */
+    public final ApplicationDescriptor descriptor()
+    {
+        return descriptor;
+    }
+
+    @Override
+    public Iterable<ActivatorDetailDescriptor> activators()
+    {
+        return activators;
+    }
+
+    /**
+     * @return Layers of this {@code ApplicationDetailDescriptor}. Never return {@code null}.
+     */
+    public final Iterable<LayerDetailDescriptor> layers()
+    {
+        return layers;
+    }
+
+    final void addActivator( ActivatorDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ActivatorDetailDescriptor" );
+        descriptor.setApplication( this );
+        activators.add( descriptor );
+    }
+
+    final void addLayer( LayerDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "LayerDetailDescriptor" );
+        descriptor.setApplication( this );
+        layers.add( descriptor );
+    }
+
+    @Override
+    public final String toString()
+    {
+        return descriptor.name();
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( ActivatorDetailDescriptor activator : activators )
+            {
+                if( !activator.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+            for( LayerDetailDescriptor layer : layers )
+            {
+                if( !layer.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ApplicationDetailDescriptorBuilder.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ApplicationDetailDescriptorBuilder.java
new file mode 100644
index 0000000..6957732
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ApplicationDetailDescriptorBuilder.java
@@ -0,0 +1,474 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.api.activation.ActivatorDescriptor;
+import org.apache.polygene.api.composite.ConstructorDescriptor;
+import org.apache.polygene.api.composite.InjectedFieldDescriptor;
+import org.apache.polygene.api.composite.InjectedMethodDescriptor;
+import org.apache.polygene.api.composite.InjectedParametersDescriptor;
+import org.apache.polygene.api.composite.MethodDescriptor;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.concern.ConcernDescriptor;
+import org.apache.polygene.api.concern.ConcernsDescriptor;
+import org.apache.polygene.api.constraint.ConstraintDescriptor;
+import org.apache.polygene.api.constraint.ConstraintsDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.mixin.MixinDescriptor;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.sideeffect.SideEffectDescriptor;
+import org.apache.polygene.api.sideeffect.SideEffectsDescriptor;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.value.ValueDescriptor;
+
+public final class ApplicationDetailDescriptorBuilder
+{
+    private ApplicationDetailDescriptorBuilder()
+    {
+    }
+
+    public static ApplicationDetailDescriptor createApplicationDetailDescriptor( ApplicationDescriptor anApplication )
+    {
+        ApplicationDescriptorVisitor visitor = new ApplicationDescriptorVisitor();
+        anApplication.accept( visitor );
+
+        return visitor.applicationDescriptor;
+    }
+
+    static final class ApplicationDescriptorVisitor
+        implements HierarchicalVisitor<Object, Object, RuntimeException>
+    {
+        // Temp: application
+        private ApplicationDetailDescriptor applicationDescriptor;
+
+        // Temp: Layer variables
+        private LayerDetailDescriptor currLayerDescriptor;
+        // Cache to lookup layer descriptor -> node
+        private final Map<LayerDescriptor, LayerDetailDescriptor> layerDescToDetail;
+
+        // Temp: current module
+        private ModuleDetailDescriptor currModuleDescriptor;
+
+        // Temp: current composite
+        private CompositeDetailDescriptor currCompositeDescriptor;
+
+        // Temp: curr activator
+        private ActivatorDetailDescriptor currActivatorDescriptor;
+
+        // Temp: curr mixin
+        private MixinDetailDescriptor currMixinDescriptor;
+
+        // Temp: current constructor
+        private ConstructorDetailDescriptor currConstructorDescriptor;
+
+        // Temp: current injected method
+        private InjectedMethodDetailDescriptor currInjectedMethodDescriptor;
+
+        // Temp: current composite method
+        private CompositeMethodDetailDescriptor currMethodDesciptor;
+
+        // Temp: current method constraints
+        private MethodConstraintsDetailDescriptor currMethodConstraintsDescriptor;
+
+        // Temp: current object
+        private ObjectDetailDescriptor currObjectDescriptor;
+
+        // Temp: current method concerns
+        private MethodConcernsDetailDescriptor currMethodConcernsDescriptor;
+
+        // Temp: current method concern
+        private MethodConcernDetailDescriptor currMethodConcernDescriptor;
+
+        // Temp: current method side effects
+        private MethodSideEffectsDetailDescriptor currMethodSideEffectsDescriptor;
+
+        // Temp: current side effect
+        private MethodSideEffectDetailDescriptor currMethodSideEffectDescriptor;
+
+        private ApplicationDescriptorVisitor()
+        {
+            layerDescToDetail = new HashMap<>();
+        }
+
+        @Override
+        public boolean visitEnter( Object visited )
+            throws RuntimeException
+        {
+            if( visited instanceof ApplicationDescriptor )
+            {
+                applicationDescriptor = new ApplicationDetailDescriptor( (ApplicationDescriptor) visited );
+            }
+            else if( visited instanceof LayerDescriptor )
+            {
+                LayerDescriptor layerDescriptor = (LayerDescriptor) visited;
+                currLayerDescriptor = getLayerDetailDescriptor( layerDescriptor );
+                applicationDescriptor.addLayer( currLayerDescriptor );
+
+                layerDescriptor.usedLayers().layers().forEach(
+                    usedLayer ->
+                    {
+                        LayerDetailDescriptor usedLayerDetailDesc = getLayerDetailDescriptor( usedLayer );
+                        currLayerDescriptor.addUsedLayer( usedLayerDetailDesc );
+                    }
+                );
+            }
+            else if( visited instanceof ModuleDescriptor )
+            {
+                ModuleDescriptor moduleDescriptor = (ModuleDescriptor) visited;
+                currModuleDescriptor = new ModuleDetailDescriptor( moduleDescriptor );
+                currLayerDescriptor.addModule( currModuleDescriptor );
+            }
+            else if( visited instanceof ActivatorDescriptor )
+            {
+                ActivatorDescriptor activatorDescriptor = (ActivatorDescriptor) visited;
+                currActivatorDescriptor = new ActivatorDetailDescriptor( activatorDescriptor );
+                if( currCompositeDescriptor != null )
+                {
+                    if( currCompositeDescriptor instanceof ServiceDetailDescriptor )
+                    {
+                        ( (ServiceDetailDescriptor) currCompositeDescriptor ).addActivator( currActivatorDescriptor );
+                    }
+                    else if( currCompositeDescriptor instanceof ImportedServiceDetailDescriptor )
+                    {
+                        ( (ImportedServiceDetailDescriptor) currCompositeDescriptor ).addActivator( currActivatorDescriptor );
+                    }
+                    else
+                    {
+                        throw new IllegalStateException( "ActivatorDescriptor is only valid for "
+                                                         + "services, modules, layers and application." );
+                    }
+                }
+                else if( currModuleDescriptor != null )
+                {
+                    currModuleDescriptor.addActivator( currActivatorDescriptor );
+                }
+                else if( currLayerDescriptor != null )
+                {
+                    currLayerDescriptor.addActivator( currActivatorDescriptor );
+                }
+                else if( applicationDescriptor != null )
+                {
+                    applicationDescriptor.addActivator( currActivatorDescriptor );
+                }
+                else
+                {
+                    throw new IllegalStateException( "ActivatorDescriptor is only valid for "
+                                                     + "services, modules, layers and application." );
+                }
+            }
+            else if( visited instanceof ServiceDescriptor )
+            {
+                ServiceDetailDescriptor descriptor = new ServiceDetailDescriptor( (ServiceDescriptor) visited );
+                currModuleDescriptor.addService( descriptor );
+                currCompositeDescriptor = descriptor;
+            }
+            else if( visited instanceof ImportedServiceDescriptor )
+            {
+                ImportedServiceDetailDescriptor descriptor = new ImportedServiceDetailDescriptor( new ImportedServiceCompositeDescriptor( (ImportedServiceDescriptor) visited ) );
+                currModuleDescriptor.addImportedService( descriptor );
+                currCompositeDescriptor = descriptor;
+            }
+            else if( visited instanceof EntityDescriptor )
+            {
+                EntityDetailDescriptor descriptor = new EntityDetailDescriptor( (EntityDescriptor) visited );
+                currModuleDescriptor.addEntity( descriptor );
+                currCompositeDescriptor = descriptor;
+            }
+            else if( visited instanceof ValueDescriptor )
+            {
+                ValueDetailDescriptor descriptor = new ValueDetailDescriptor( (ValueDescriptor) visited );
+                currModuleDescriptor.addValue( descriptor );
+                currCompositeDescriptor = descriptor;
+            }
+            else if( visited instanceof TransientDescriptor )
+            {
+                TransientDetailDescriptor descriptor = new TransientDetailDescriptor( (TransientDescriptor) visited );
+                currModuleDescriptor.addTransient( descriptor );
+                currCompositeDescriptor = descriptor;
+            }
+            else if( visited instanceof MethodDescriptor )
+            {
+                if( currCompositeDescriptor == null )
+                {
+                    // Service via CompositeDescriptor in progress )
+                    return false;
+                }
+                currMethodDesciptor = new CompositeMethodDetailDescriptor( (MethodDescriptor) visited );
+                currCompositeDescriptor.addMethod( currMethodDesciptor );
+            }
+            else if( visited instanceof ConstraintsDescriptor )
+            {
+                if( currCompositeDescriptor == null )
+                {
+                    // Service via CompositeDescriptor in progress )
+                    return false;
+                }
+                currMethodConstraintsDescriptor = new MethodConstraintsDetailDescriptor( (ConstraintsDescriptor) visited );
+                currMethodDesciptor.setConstraints( currMethodConstraintsDescriptor );
+            }
+            else if( visited instanceof ConcernsDescriptor )
+            {
+                if( currCompositeDescriptor == null )
+                {
+                    // Service via CompositeDescriptor in progress )
+                    return false;
+                }
+                currMethodConcernsDescriptor = new MethodConcernsDetailDescriptor( (ConcernsDescriptor) visited );
+                currMethodDesciptor.setConcerns( currMethodConcernsDescriptor );
+            }
+            else if( visited instanceof ConcernDescriptor )
+            {
+                if( currCompositeDescriptor == null )
+                {
+                    // Service via CompositeDescriptor in progress )
+                    return false;
+                }
+                resetInjectableRelatedVariables();
+
+                currMethodConcernDescriptor = new MethodConcernDetailDescriptor( (ConcernDescriptor) visited );
+                currMethodConcernsDescriptor.addConcern( currMethodConcernDescriptor );
+            }
+            else if( visited instanceof SideEffectsDescriptor )
+            {
+                if( currCompositeDescriptor == null )
+                {
+                    // Service via CompositeDescriptor in progress )
+                    return false;
+                }
+                currMethodSideEffectsDescriptor = new MethodSideEffectsDetailDescriptor( (SideEffectsDescriptor) visited );
+                currMethodDesciptor.setSideEffects( currMethodSideEffectsDescriptor );
+            }
+            else if( visited instanceof SideEffectDescriptor )
+            {
+                if( currCompositeDescriptor == null )
+                {
+                    // Service via CompositeDescriptor in progress )
+                    return false;
+                }
+                resetInjectableRelatedVariables();
+
+                currMethodSideEffectDescriptor = new MethodSideEffectDetailDescriptor( (SideEffectDescriptor) visited );
+                currMethodSideEffectsDescriptor.addSideEffect( currMethodSideEffectDescriptor );
+            }
+            else if( visited instanceof MixinDescriptor )
+            {
+                if( currCompositeDescriptor == null )
+                {
+                    // Service via CompositeDescriptor in progress )
+                    return false;
+                }
+                resetInjectableRelatedVariables();
+
+                currMixinDescriptor = new MixinDetailDescriptor( (MixinDescriptor) visited );
+                currCompositeDescriptor.addMixin( currMixinDescriptor );
+            }
+            else if( visited instanceof ObjectDescriptor )
+            {
+                resetInjectableRelatedVariables();
+
+                currObjectDescriptor = new ObjectDetailDescriptor( (ObjectDescriptor) visited );
+                currModuleDescriptor.addObject( currObjectDescriptor );
+            }
+            else if( visited instanceof ConstructorDescriptor )
+            {
+                if( currCompositeDescriptor == null )
+                {
+                    // Service via CompositeDescriptor in progress )
+                    return false;
+                }
+                currConstructorDescriptor = new ConstructorDetailDescriptor( (ConstructorDescriptor) visited );
+                currInjectedMethodDescriptor = null;
+
+                // Invoked for mixin and object
+                if( currActivatorDescriptor != null )
+                {
+                    currActivatorDescriptor.addConstructor( currConstructorDescriptor );
+                }
+                else if( currMixinDescriptor != null )
+                {
+                    currMixinDescriptor.addConstructor( currConstructorDescriptor );
+                }
+                else if( currObjectDescriptor != null )
+                {
+                    currObjectDescriptor.addConstructor( currConstructorDescriptor );
+                }
+                else if( currMethodConcernDescriptor != null )
+                {
+                    currMethodConcernDescriptor.addConstructor( currConstructorDescriptor );
+                }
+                else if( currMethodSideEffectDescriptor != null )
+                {
+                    currMethodSideEffectDescriptor.addConstructor( currConstructorDescriptor );
+                }
+                else
+                {
+                    throw new IllegalStateException( "ConstructorDescriptor is only valid for "
+                                                     + "activator, mixin, object, concern and side-effect. "
+                                                     + "Visiting [" + visited + "]" );
+                }
+            }
+            else if( visited instanceof InjectedParametersDescriptor )
+            {
+                if( currCompositeDescriptor == null )
+                {
+                    // Service via CompositeDescriptor in progress )
+                    return false;
+                }
+                InjectedParametersDetailDescriptor detailDescriptor = new InjectedParametersDetailDescriptor( (InjectedParametersDescriptor) visited );
+
+                // Invoked for constructor and injected method
+                if( currConstructorDescriptor != null )
+                {
+                    currConstructorDescriptor.setInjectedParameter( detailDescriptor );
+                }
+                else if( currInjectedMethodDescriptor != null )
+                {
+                    currInjectedMethodDescriptor.setInjectedParameter( detailDescriptor );
+                }
+                else
+                {
+                    throw new IllegalStateException( "InjectedParametersDescriptor is only valid for "
+                                                     + "constructor and injector method descriptor." );
+                }
+            }
+            else if( visited instanceof InjectedMethodDescriptor )
+            {
+                if( currCompositeDescriptor == null )
+                {
+                    // Service via CompositeDescriptor in progress )
+                    return false;
+                }
+                // Invoked for mixin and object
+                currInjectedMethodDescriptor = new InjectedMethodDetailDescriptor( (InjectedMethodDescriptor) visited );
+                currConstructorDescriptor = null;
+
+                // Invoked for mixin and object
+                if( currActivatorDescriptor != null )
+                {
+                    currActivatorDescriptor.addInjectedMethod( currInjectedMethodDescriptor );
+                }
+                else if( currMixinDescriptor != null )
+                {
+                    currMixinDescriptor.addInjectedMethod( currInjectedMethodDescriptor );
+                }
+                else if( currObjectDescriptor != null )
+                {
+                    currObjectDescriptor.addInjectedMethod( currInjectedMethodDescriptor );
+                }
+                else if( currMethodConcernDescriptor != null )
+                {
+                    currMethodConcernDescriptor.addInjectedMethod( currInjectedMethodDescriptor );
+                }
+                else if( currMethodSideEffectDescriptor != null )
+                {
+                    currMethodSideEffectDescriptor.addInjectedMethod( currInjectedMethodDescriptor );
+                }
+                else
+                {
+                    throw new IllegalStateException( "InjectedMethodDescriptor is only valid for "
+                                                     + "mixin, object, concern and side-effect." );
+                }
+            }
+
+            return true;
+        }
+
+        @Override
+        public boolean visitLeave( Object visited )
+            throws RuntimeException
+        {
+            return true;
+        }
+
+        @Override
+        public boolean visit( Object visited )
+            throws RuntimeException
+        {
+            if( visited instanceof ConstraintDescriptor )
+            {
+                if( currCompositeDescriptor == null )
+                {
+                    // Service via CompositeDescriptor in progress )
+                    return false;
+                }
+                MethodConstraintDetailDescriptor detailDescriptor = new MethodConstraintDetailDescriptor( (ConstraintDescriptor) visited );
+                currMethodConstraintsDescriptor.addConstraint( detailDescriptor );
+            }
+            else if( visited instanceof InjectedFieldDescriptor )
+            {
+                if( currCompositeDescriptor == null )
+                {
+                    // Service via CompositeDescriptor in progress )
+                    return false;
+                }
+                InjectedFieldDetailDescriptor detailDescriptor = new InjectedFieldDetailDescriptor( (InjectedFieldDescriptor) visited );
+
+                // Invoked for mixin and object
+                if( currActivatorDescriptor != null )
+                {
+                    currActivatorDescriptor.addInjectedField( detailDescriptor );
+                }
+                else if( currMixinDescriptor != null )
+                {
+                    currMixinDescriptor.addInjectedField( detailDescriptor );
+                }
+                else if( currObjectDescriptor != null )
+                {
+                    currObjectDescriptor.addInjectedField( detailDescriptor );
+                }
+                else if( currMethodConcernDescriptor != null )
+                {
+                    currMethodConcernDescriptor.addInjectedField( detailDescriptor );
+                }
+                else if( currMethodSideEffectDescriptor != null )
+                {
+                    currMethodSideEffectDescriptor.addInjectedField( detailDescriptor );
+                }
+                else
+                {
+                    throw new IllegalStateException( "InjectedFieldDescriptor is only valid for "
+                                                     + "mixin, object, concern and side-effect." );
+                }
+            }
+
+            return true;
+        }
+
+        private LayerDetailDescriptor getLayerDetailDescriptor( LayerDescriptor aDescriptor )
+        {
+            return layerDescToDetail.computeIfAbsent( aDescriptor, LayerDetailDescriptor::new );
+        }
+
+        private void resetInjectableRelatedVariables()
+        {
+            currMixinDescriptor = null;
+            currObjectDescriptor = null;
+            currMethodConcernDescriptor = null;
+            currMethodSideEffectDescriptor = null;
+        }
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/CompositeDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/CompositeDetailDescriptor.java
new file mode 100644
index 0000000..3b5e0e3
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/CompositeDetailDescriptor.java
@@ -0,0 +1,144 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.MethodDescriptor;
+
+/**
+ * Composite Detail Descriptor.
+ *
+ * @param <T> CompositeDescriptor type
+ */
+public abstract class CompositeDetailDescriptor<T extends CompositeDescriptor>
+{
+    protected final T descriptor;
+    protected ModuleDetailDescriptor module;
+    protected final List<CompositeMethodDetailDescriptor> methods;
+    protected final List<MixinDetailDescriptor> mixins;
+
+    CompositeDetailDescriptor( T aDescriptor )
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        descriptor = aDescriptor;
+        methods = new LinkedList<>();
+        mixins = new LinkedList<>();
+    }
+
+    /**
+     * @return Descriptor of this {@code CompositeDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    public final T descriptor()
+    {
+        return descriptor;
+    }
+
+    /**
+     * @return Methods of this {@code CompositeDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    public final Iterable<CompositeMethodDetailDescriptor> methods()
+    {
+        return methods;
+    }
+
+    /**
+     * @return Mixins of this {@code CompositeDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    public final Iterable<MixinDetailDescriptor> mixins()
+    {
+        return mixins;
+    }
+
+    /**
+     * Return method detail descriptor of the requested method. Returns {@code null} if not found.
+     *
+     * @param aMethod Method to look up. This argument must not be {@code null}.
+     *
+     * @return method detail descriptor of the requested method.
+     *
+     * @since 0.5
+     */
+    public final CompositeMethodDetailDescriptor getMethodDescriptor( Method aMethod )
+    {
+        for( CompositeMethodDetailDescriptor descriptor : methods )
+        {
+            MethodDescriptor methodDescriptor = descriptor.descriptor();
+            Method method = methodDescriptor.method();
+            if( method.equals( aMethod ) )
+            {
+                return descriptor;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * @return Module that own this {@code CompositeDetailDescriptor}.
+     *
+     * @since 0.5
+     */
+    public final ModuleDetailDescriptor module()
+    {
+        return module;
+    }
+
+    final void setModule( ModuleDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+        module = aDescriptor;
+    }
+
+    final void addMethod( CompositeMethodDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        aDescriptor.setComposite( this );
+        methods.add( aDescriptor );
+    }
+
+    final void addMixin( MixinDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        aDescriptor.setComposite( this );
+        mixins.add( aDescriptor );
+    }
+
+    @Override
+    public String toString()
+    {
+        return descriptor.toString();
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/CompositeMethodDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/CompositeMethodDetailDescriptor.java
new file mode 100644
index 0000000..7a2bda4
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/CompositeMethodDetailDescriptor.java
@@ -0,0 +1,135 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.Objects;
+import org.apache.polygene.api.composite.MethodDescriptor;
+
+public final class CompositeMethodDetailDescriptor
+{
+    private final MethodDescriptor descriptor;
+
+    private CompositeDetailDescriptor composite;
+    private MethodConstraintsDetailDescriptor constraints;
+    private MethodConcernsDetailDescriptor concerns;
+    private MethodSideEffectsDetailDescriptor sideEffects;
+
+    CompositeMethodDetailDescriptor( MethodDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+        descriptor = aDescriptor;
+
+        composite = null;
+        constraints = null;
+        sideEffects = null;
+    }
+
+    /**
+     * @return Descriptor of this {@code CompositeMethodDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    public final MethodDescriptor descriptor()
+    {
+        return descriptor;
+    }
+
+    /**
+     * @return Constraints of this {@code CompositeMethodDetailDescriptor}.
+     *         Returns {@code null} if this method does not have any constraints.
+     *
+     * @since 0.5
+     */
+    public final MethodConstraintsDetailDescriptor constraints()
+    {
+        return constraints;
+    }
+
+    /**
+     * @return Concerns of this {@code CompositeMethodDetailDescriptor}. Returns {@code null} if this method does not
+     *         have any concerns.
+     *
+     * @since 0.5
+     */
+    public final MethodConcernsDetailDescriptor concerns()
+    {
+        return concerns;
+    }
+
+    /**
+     * @return Side-effects of this {@code CompositeMethodDetailDescriptor}. Returns {@code null}
+     *         if this method does not have any side effects.
+     *
+     * @since 0.5
+     */
+    public final MethodSideEffectsDetailDescriptor sideEffects()
+    {
+        return sideEffects;
+    }
+
+    /**
+     * @return Composite that owns this {@code CompositeMethodDetailDescriptor}.
+     *
+     * @since 0.5
+     */
+    public final CompositeDetailDescriptor composite()
+    {
+        return composite;
+    }
+
+    final void setComposite( CompositeDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+        composite = aDescriptor;
+    }
+
+    final void setConstraints( MethodConstraintsDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        aDescriptor.setMethod( this );
+        constraints = aDescriptor;
+    }
+
+    public void setConcerns( MethodConcernsDetailDescriptor aDescriptor )
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        aDescriptor.setMethod( this );
+        concerns = aDescriptor;
+    }
+
+    final void setSideEffects( MethodSideEffectsDetailDescriptor aDescriptor )
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        aDescriptor.setMethod( this );
+        sideEffects = aDescriptor;
+    }
+
+    @Override
+    public final String toString()
+    {
+        return descriptor.method().getName();
+    }
+}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ConstructorDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ConstructorDetailDescriptor.java
new file mode 100644
index 0000000..152fdaa
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ConstructorDetailDescriptor.java
@@ -0,0 +1,145 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.Objects;
+import org.apache.polygene.api.composite.ConstructorDescriptor;
+
+/**
+ * Constructor Detail Descriptor.
+ */
+public final class ConstructorDetailDescriptor
+{
+    private final ConstructorDescriptor descriptor;
+    private ActivatorDetailDescriptor activator;
+    private ObjectDetailDescriptor object;
+    private MixinDetailDescriptor mixin;
+    private MethodConcernDetailDescriptor methodConcern;
+    private MethodSideEffectDetailDescriptor methodSideEffect;
+    private InjectedParametersDetailDescriptor parameters;
+
+    ConstructorDetailDescriptor( ConstructorDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "ConstructorDescriptor" );
+        this.descriptor = descriptor;
+        this.parameters = null;
+    }
+
+    /**
+     * @return Descriptor of this {@code ConstructorDetailDescriptor}. Never return {@code null}.
+     */
+    public final ConstructorDescriptor descriptor()
+    {
+        return descriptor;
+    }
+
+    /**
+     * @return Constructor parameters of this {@code ConstructorDetailDescriptor}. Never return {@code null}.
+     */
+    public final InjectedParametersDetailDescriptor parameters()
+    {
+        return parameters;
+    }
+
+    /**
+     * @return Activator that own this {@code ConstructorDetailDescriptor}.
+     */
+    public final ActivatorDetailDescriptor activator()
+    {
+        return activator;
+    }
+
+    /**
+     * @return Object that own this {@code ConstructorDetailDescriptor}.
+     */
+    public final ObjectDetailDescriptor object()
+    {
+        return object;
+    }
+
+    /**
+     * @return Mixin that own this {@code ConstructorDetailDescriptor}.
+     */
+    public final MixinDetailDescriptor mixin()
+    {
+        return mixin;
+    }
+
+    /**
+     * @return Method concern that own this {@code ConstructorDetailDescriptor}.
+     */
+    public final MethodConcernDetailDescriptor methodConcern()
+    {
+        return methodConcern;
+    }
+
+    /**
+     * @return Method side effect that own this {@code ConstructorDetailDescriptor}.
+     */
+    public final MethodSideEffectDetailDescriptor methodSideEffect()
+    {
+        return methodSideEffect;
+    }
+
+    final void setActivator( ActivatorDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ActivatorDetailDescriptor" );
+        activator = descriptor;
+    }
+
+    final void setObject( ObjectDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ObjectDetailDescriptor" );
+        object = descriptor;
+    }
+
+    final void setMixin( MixinDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "MixinDetailDescriptor" );
+        mixin = descriptor;
+    }
+
+    final void setMethodConcern( MethodConcernDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "MethodConcernDetailDescriptor" );
+        methodConcern = descriptor;
+    }
+
+    final void setInjectedParameter( InjectedParametersDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "InjectedParametersDetailDescriptor" );
+        descriptor.setConstructor( this );
+        parameters = descriptor;
+    }
+
+    final void setMethodSideEffect( MethodSideEffectDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "MethodSideEffectDetailDescriptor" );
+        methodSideEffect = descriptor;
+    }
+
+    @Override
+    public final String toString()
+    {
+        return descriptor.constructor().getDeclaringClass().getSimpleName();
+    }
+
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/EntityDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/EntityDetailDescriptor.java
new file mode 100644
index 0000000..a08f6a2
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/EntityDetailDescriptor.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.util.Visitable;
+import org.apache.polygene.api.util.Visitor;
+
+/**
+ * Entity Detail Descriptor.
+ */
+public final class EntityDetailDescriptor
+    extends CompositeDetailDescriptor<EntityDescriptor>
+    implements Visitable<EntityDetailDescriptor>
+{
+    EntityDetailDescriptor( EntityDescriptor aDescriptor )
+    {
+        super( aDescriptor );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( Visitor<? super EntityDetailDescriptor, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        return visitor.visit( this );
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ImportedServiceCompositeDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ImportedServiceCompositeDescriptor.java
new file mode 100644
index 0000000..629a6fd
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ImportedServiceCompositeDescriptor.java
@@ -0,0 +1,103 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.Classes;
+
+/**
+ * XXX Workaround for inconsistency in Polygene core-api/spi
+ * ImportedServiceDescriptor wrapper as composite
+ */
+public class ImportedServiceCompositeDescriptor
+    implements CompositeDescriptor
+{
+    protected ImportedServiceDescriptor importedService;
+    protected final List<Class<?>> mixins = new LinkedList<>();
+
+    public ImportedServiceCompositeDescriptor( ImportedServiceDescriptor descriptor )
+    {
+        this.importedService = descriptor;
+    }
+
+    public ImportedServiceDescriptor importedService()
+    {
+        return importedService;
+    }
+
+    @Override
+    public ModuleDescriptor module()
+    {
+        return importedService.module();
+    }
+
+    @Override
+    public Stream<Class<?>> mixinTypes()
+    {
+        return mixins.stream();
+    }
+
+    @Override
+    public Class<?> primaryType()
+    {
+        return importedService.type();
+    }
+
+    @Override
+    public Visibility visibility()
+    {
+        return importedService.visibility();
+    }
+
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return importedService.metaInfo( infoType );
+    }
+
+    @Override
+    public Stream<Class<?>> types()
+    {
+        return importedService.types();
+    }
+
+    @Override
+    public boolean isAssignableTo( Class<?> type )
+    {
+        return importedService.isAssignableTo( type );
+    }
+
+    public Class<? extends ServiceImporter> serviceImporter()
+    {
+        return importedService.serviceImporter();
+    }
+
+    public String toURI()
+    {
+        return Classes.toURI( primaryType() );
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ImportedServiceDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ImportedServiceDetailDescriptor.java
new file mode 100644
index 0000000..7f64a79
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ImportedServiceDetailDescriptor.java
@@ -0,0 +1,74 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * Imported Service Detail Descriptor.
+ * <p>
+ * Visitable hierarchy with Activators children.
+ */
+// TODO need to refactor later, but wait until Polygene core/spi have proper and consistent API for ImportedService.
+public class ImportedServiceDetailDescriptor
+    extends CompositeDetailDescriptor<ImportedServiceCompositeDescriptor>
+    implements ActivateeDetailDescriptor, VisitableHierarchy<Object, Object>
+{
+    private final List<ActivatorDetailDescriptor> activators = new LinkedList<>();
+
+    ImportedServiceDetailDescriptor( ImportedServiceCompositeDescriptor descriptor )
+    {
+        super( descriptor );
+    }
+
+    @Override
+    public Iterable<ActivatorDetailDescriptor> activators()
+    {
+        return activators;
+    }
+
+    final void addActivator( ActivatorDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ActivatorDetailDescriptor" );
+        descriptor.setImportedService( this );
+        activators.add( descriptor );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( ActivatorDetailDescriptor activator : activators )
+            {
+                if( !activator.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/InjectableDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/InjectableDetailDescriptor.java
new file mode 100644
index 0000000..ce1da0c
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/InjectableDetailDescriptor.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+public interface InjectableDetailDescriptor
+{
+    /**
+     * @return Constructors. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    Iterable<ConstructorDetailDescriptor> constructors();
+
+    /**
+     * @return Injected methods. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    Iterable<InjectedMethodDetailDescriptor> injectedMethods();
+
+    /**
+     * @return Injected fields. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    Iterable<InjectedFieldDetailDescriptor> injectedFields();
+}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/InjectedFieldDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/InjectedFieldDetailDescriptor.java
new file mode 100644
index 0000000..b1a635c
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/InjectedFieldDetailDescriptor.java
@@ -0,0 +1,129 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.Objects;
+import org.apache.polygene.api.composite.InjectedFieldDescriptor;
+
+public final class InjectedFieldDetailDescriptor
+{
+    private final InjectedFieldDescriptor descriptor;
+    private ActivatorDetailDescriptor activator;
+    private ObjectDetailDescriptor object;
+    private MixinDetailDescriptor mixin;
+    private MethodConcernDetailDescriptor methodConcern;
+    private MethodSideEffectDetailDescriptor methodSideEffect;
+
+    InjectedFieldDetailDescriptor( InjectedFieldDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "InjectedFieldDescriptor" );
+        this.descriptor = descriptor;
+    }
+
+    /**
+     * @return Descriptor of this {@code InjectedFieldDetailDescriptor}. Never returns {@code null}.
+     */
+    public final InjectedFieldDescriptor descriptor()
+    {
+        return descriptor;
+    }
+
+    /**
+     * @return Activator that own this {@code InjectedFieldDetailDescriptor}.
+     */
+    public final ActivatorDetailDescriptor activator()
+    {
+        return activator;
+    }
+
+    /**
+     * @return Object that own this {@code InjectedFieldDetailDescriptor}.
+     */
+    public final ObjectDetailDescriptor object()
+    {
+        return object;
+    }
+
+    /**
+     * @return Mixin that own this {@code InjectedFieldDetailDescriptor}.
+     */
+    public final MixinDetailDescriptor mixin()
+    {
+        return mixin;
+    }
+
+    /**
+     * @return Method concern that own this {@code InjectedFieldDetailDescriptor}.
+     */
+    public final MethodConcernDetailDescriptor methodConcern()
+    {
+        return methodConcern;
+    }
+
+    /**
+     * @return Method side effect that own this {@code InjectedFieldDetailDescriptor}.
+     */
+    public final MethodSideEffectDetailDescriptor methodSideEffect()
+    {
+        return methodSideEffect;
+    }
+
+    final void setActivator( ActivatorDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ActivatorDetailDescriptor" );
+        activator = descriptor;
+    }
+
+    final void setObject( ObjectDetailDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "ObjectDetailDescriptor" );
+        object = descriptor;
+    }
+
+    final void setMixin( MixinDetailDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "MixinDetailDescriptor" );
+        mixin = descriptor;
+    }
+
+    final void setMethodConcern( MethodConcernDetailDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "MethodConcernDetailDescriptor" );
+        methodConcern = descriptor;
+    }
+
+    final void setMethodSideEffect( MethodSideEffectDetailDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "MethodSideEffectDetailDescriptor" );
+        methodSideEffect = descriptor;
+    }
+
+    @Override
+    public final String toString()
+    {
+        return descriptor.field().getName();
+    }
+
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/InjectedMethodDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/InjectedMethodDetailDescriptor.java
new file mode 100644
index 0000000..a7e6fe7
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/InjectedMethodDetailDescriptor.java
@@ -0,0 +1,143 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.Objects;
+import org.apache.polygene.api.composite.InjectedMethodDescriptor;
+
+
+public final class InjectedMethodDetailDescriptor
+{
+    private final InjectedMethodDescriptor descriptor;
+    private ActivatorDetailDescriptor activator;
+    private ObjectDetailDescriptor object;
+    private MixinDetailDescriptor mixin;
+    private MethodSideEffectDetailDescriptor methodSideEffect;
+    private MethodConcernDetailDescriptor methodConcern;
+    private InjectedParametersDetailDescriptor parameters;
+
+    InjectedMethodDetailDescriptor( InjectedMethodDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "InjectedMethodDescriptor" );
+        this.descriptor = descriptor;
+        this.parameters = null;
+    }
+
+    /**
+     * @return Descriptor of this {@code InjectedMethodDetailDescriptor}. Never return {@code null}.
+     */
+    public final InjectedMethodDescriptor descriptor()
+    {
+        return descriptor;
+    }
+
+    /**
+     * @return Method parameters of this {@code InjectedMethodDetailDescriptor}. Never return {@code null}.
+     */
+    public final InjectedParametersDetailDescriptor parameters()
+    {
+        return parameters;
+    }
+
+    /**
+     * @return Activator that owns this {@code InjectedMethodDetailDescriptor}.
+     */
+    public final ActivatorDetailDescriptor activator()
+    {
+        return activator;
+    }
+
+    /**
+     * @return Object that owns this {@code InjectedMethodDetailDescriptor}.
+     */
+    public final ObjectDetailDescriptor object()
+    {
+        return object;
+    }
+
+    /**
+     * @return Mixin that owns this {@code InjectedMethodDetailDescriptor}.
+     */
+    public final MixinDetailDescriptor mixin()
+    {
+        return mixin;
+    }
+
+    /**
+     * @return Method side effect that owns this {@code InjectedMethodDetailDescriptor}.
+     */
+    public final MethodSideEffectDetailDescriptor methodSideEffect()
+    {
+        return methodSideEffect;
+    }
+
+    /**
+     * @return Method concern that owns this {@code InjectedMethodDetailDescriptor}.
+     */
+    public final MethodConcernDetailDescriptor methodConcern()
+    {
+        return methodConcern;
+    }
+
+    final void setActivator( ActivatorDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ActivatorDetailDescriptor" );
+        activator = descriptor;
+    }
+
+    final void setObject( ObjectDetailDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "ObjectDetailDescriptor" );
+        object = descriptor;
+    }
+
+    final void setMixin( MixinDetailDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "MixinDetailDescriptor" );
+        mixin = descriptor;
+    }
+
+    final void setInjectedParameter( InjectedParametersDetailDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "InjectedParametersDetailDescriptor" );
+
+        descriptor.setMethod( this );
+        parameters = descriptor;
+    }
+
+    final void setMethodSideEffect( MethodSideEffectDetailDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "MethodSideEffectDetailDescriptor" );
+        methodSideEffect = descriptor;
+    }
+
+    final void setMethodConcern( MethodConcernDetailDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "MethodConcernDetailDescriptor" );
+        methodConcern = descriptor;
+    }
+
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/InjectedParametersDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/InjectedParametersDetailDescriptor.java
new file mode 100644
index 0000000..33d4b45
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/InjectedParametersDetailDescriptor.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.Objects;
+import org.apache.polygene.api.composite.InjectedParametersDescriptor;
+
+public class InjectedParametersDetailDescriptor
+{
+    private final InjectedParametersDescriptor descriptor;
+    private ConstructorDetailDescriptor constructor;
+    private InjectedMethodDetailDescriptor method;
+
+    InjectedParametersDetailDescriptor( InjectedParametersDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+        descriptor = aDescriptor;
+    }
+
+    /**
+     * @return Descriptor of this {@code InjectedParametersDetailDescriptor}. Never returns {@code null}.
+     *
+     * @since 0.5
+     */
+    public final InjectedParametersDescriptor descriptor()
+    {
+        return descriptor;
+    }
+
+    /**
+     * @return Constructor that owns this {@code InjectedParametersDetailDescriptor}.
+     *         If {@code null}, this {@code InjectedParametersDetailDescriptor} is owned by a method.
+     *
+     * @see #method()
+     * @since 0.5
+     */
+    public final ConstructorDetailDescriptor constructor()
+    {
+        return constructor;
+    }
+
+    /**
+     * @return Method that owns this {@code InjectedParametersDetailDescriptor}.
+     *         If {@code null}, this {@code InjectedParametersDetailDescriptor} is owned by a constructor.
+     *
+     * @see #constructor() ()
+     * @since 0.5
+     */
+    public final InjectedMethodDetailDescriptor method()
+    {
+        return method;
+    }
+
+    final void setConstructor( ConstructorDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+        constructor = aDescriptor;
+    }
+
+    final void setMethod( InjectedMethodDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+        method = aDescriptor;
+    }
+}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/LayerDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/LayerDetailDescriptor.java
new file mode 100644
index 0000000..e312701
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/LayerDetailDescriptor.java
@@ -0,0 +1,163 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * Layer Detail Descriptor.
+ * <p>
+ * Visitable hierarchy with Activators and Modules children.
+ */
+public final class LayerDetailDescriptor
+    implements ActivateeDetailDescriptor, VisitableHierarchy<Object, Object>
+{
+    private final LayerDescriptor descriptor;
+    private ApplicationDetailDescriptor application;
+    private final List<LayerDetailDescriptor> usedLayers = new LinkedList<>();
+    private final List<ActivatorDetailDescriptor> activators = new LinkedList<>();
+    private final List<ModuleDetailDescriptor> modules = new LinkedList<>();
+
+    LayerDetailDescriptor( LayerDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "LayerDescriptor" );
+        this.descriptor = descriptor;
+    }
+
+    /**
+     * @return Descriptor of this {@code LayerDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    public final LayerDescriptor descriptor()
+    {
+        return descriptor;
+    }
+
+    /**
+     * @return Used layers of this {@code LayerDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    public final Iterable<LayerDetailDescriptor> usedLayers()
+    {
+        return usedLayers;
+    }
+
+    /**
+     * @return Layers that used this layer.
+     */
+    public final List<LayerDetailDescriptor> usedBy()
+    {
+        List<LayerDetailDescriptor> usedBy = new LinkedList<>();
+        for( LayerDetailDescriptor layer : application.layers() )
+        {
+            if( layer.usedLayers.contains( this ) )
+            {
+                usedBy.add( layer );
+            }
+        }
+        return usedBy;
+    }
+
+    @Override
+    public Iterable<ActivatorDetailDescriptor> activators()
+    {
+        return activators;
+    }
+
+    /**
+     * @return Modules of this {@code LayerDetailDescriptor}. Never return {@code null}.
+     */
+    public final Iterable<ModuleDetailDescriptor> modules()
+    {
+        return modules;
+    }
+
+    /**
+     * @return Application that owns this {@code LayerDetailDescriptor}. Never return {@code null}.
+     */
+    public final ApplicationDetailDescriptor application()
+    {
+        return application;
+    }
+
+    final void setApplication( ApplicationDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ApplicationDetailDescriptor" );
+        application = descriptor;
+    }
+
+    final void addActivator( ActivatorDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ActivatorDetailDescriptor" );
+        descriptor.setLayer( this );
+        activators.add( descriptor );
+    }
+
+    final void addUsedLayer( LayerDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "LayerDetailDescriptor" );
+        usedLayers.add( descriptor );
+    }
+
+    final void addModule( ModuleDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ModuleDetailDescriptor" );
+        descriptor.setLayer( this );
+        modules.add( descriptor );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( ActivatorDetailDescriptor activator : activators )
+            {
+                if( !activator.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+            for( ModuleDetailDescriptor module : modules )
+            {
+                if( !module.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    @Override
+    public final String toString()
+    {
+        return descriptor.name();
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodConcernDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodConcernDetailDescriptor.java
new file mode 100644
index 0000000..82a6264
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodConcernDetailDescriptor.java
@@ -0,0 +1,141 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.api.concern.ConcernDescriptor;
+
+public final class MethodConcernDetailDescriptor
+    implements InjectableDetailDescriptor
+{
+    private final ConcernDescriptor descriptor;
+    private MethodConcernsDetailDescriptor concerns;
+
+    private final List<ConstructorDetailDescriptor> constructors;
+    private final List<InjectedMethodDetailDescriptor> injectedMethods;
+    private final List<InjectedFieldDetailDescriptor> injectedFields;
+
+    MethodConcernDetailDescriptor( ConcernDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        descriptor = aDescriptor;
+
+        constructors = new LinkedList<>();
+        injectedMethods = new LinkedList<>();
+        injectedFields = new LinkedList<>();
+    }
+
+    /**
+     * @return Descriptor of this {@code MethodConcernDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    public final ConcernDescriptor descriptor()
+    {
+        return descriptor;
+    }
+
+    /**
+     * @return Method concerns that owns this {@code MethodConcernDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    public final MethodConcernsDetailDescriptor method()
+    {
+        return concerns;
+    }
+
+    /**
+     * @return Constructors of this {@code MethodConcernDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    @Override
+    public final Iterable<ConstructorDetailDescriptor> constructors()
+    {
+        return constructors;
+    }
+
+    /**
+     * @return Injected methods of this {@code MethodConcernDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    @Override
+    public final Iterable<InjectedMethodDetailDescriptor> injectedMethods()
+    {
+        return injectedMethods;
+    }
+
+    /**
+     * @return Injected methods of this {@code MethodConcernDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    @Override
+    public final Iterable<InjectedFieldDetailDescriptor> injectedFields()
+    {
+        return injectedFields;
+    }
+
+   @Override
+   public String toString()
+   {
+      return descriptor.modifierClass().getName();
+   }
+
+   final void setConcerns( MethodConcernsDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+        concerns = aDescriptor;
+    }
+
+    final void addConstructor( ConstructorDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        aDescriptor.setMethodConcern( this );
+        constructors.add( aDescriptor );
+    }
+
+    final void addInjectedMethod( InjectedMethodDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        aDescriptor.setMethodConcern( this );
+        injectedMethods.add( aDescriptor );
+    }
+
+    final void addInjectedField( InjectedFieldDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        aDescriptor.setMethodConcern( this );
+        injectedFields.add( aDescriptor );
+    }
+}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodConcernsDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodConcernsDetailDescriptor.java
new file mode 100644
index 0000000..0d644b5
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodConcernsDetailDescriptor.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.api.concern.ConcernsDescriptor;
+
+public final class MethodConcernsDetailDescriptor
+{
+    private final ConcernsDescriptor descriptor;
+    private CompositeMethodDetailDescriptor method;
+    private final List<MethodConcernDetailDescriptor> concerns;
+
+    MethodConcernsDetailDescriptor( ConcernsDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+        descriptor = aDescriptor;
+        concerns = new LinkedList<>();
+    }
+
+    /**
+     * @return Descriptor of this {@code MethodConcernsDescriptor}.
+     *
+     * @since 0.5
+     */
+    public final ConcernsDescriptor descriptor()
+    {
+        return descriptor;
+    }
+
+    /**
+     * @return Method that owns this {@code MethodConcernsDescriptor}.
+     *
+     * @since 0.5
+     */
+    public final CompositeMethodDetailDescriptor method()
+    {
+        return method;
+    }
+
+    /**
+     * @return concerns of this {@code MethodConcernDetailDescriptor}.
+     *
+     * @since 0.5
+     */
+    public final Iterable<MethodConcernDetailDescriptor> concerns()
+    {
+        return concerns;
+    }
+
+    final void setMethod( CompositeMethodDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+        method = aDescriptor;
+    }
+
+    final void addConcern( MethodConcernDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+        aDescriptor.setConcerns( this );
+        concerns.add( aDescriptor );
+    }
+}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodConstraintDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodConstraintDetailDescriptor.java
new file mode 100644
index 0000000..7dc3102
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodConstraintDetailDescriptor.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.Objects;
+import org.apache.polygene.api.constraint.ConstraintDescriptor;
+
+public final class MethodConstraintDetailDescriptor
+{
+    private final ConstraintDescriptor descriptor;
+    private MethodConstraintsDetailDescriptor constraints;
+
+    MethodConstraintDetailDescriptor( ConstraintDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        descriptor = aDescriptor;
+    }
+
+    /**
+     * @return Descriptor of this {@code MethodConstraintDetailDescriptor}. Never returns {@code null}.
+     *
+     * @since 0.5
+     */
+    public final ConstraintDescriptor descriptor()
+    {
+        return descriptor;
+    }
+
+    /**
+     * @return Constraints that own this {@code MethodConstraintDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    public final MethodConstraintsDetailDescriptor constraints()
+    {
+        return constraints;
+    }
+
+   @Override
+   public String toString()
+   {
+      return descriptor.annotation().toString();
+   }
+
+   final void setConstraints( MethodConstraintsDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+        constraints = aDescriptor;
+    }
+}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodConstraintsDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodConstraintsDetailDescriptor.java
new file mode 100644
index 0000000..8b0f6cd
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodConstraintsDetailDescriptor.java
@@ -0,0 +1,86 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.api.constraint.ConstraintsDescriptor;
+
+public final class MethodConstraintsDetailDescriptor
+{
+    private final ConstraintsDescriptor descriptor;
+    private CompositeMethodDetailDescriptor method;
+    private final List<MethodConstraintDetailDescriptor> constraints;
+
+    MethodConstraintsDetailDescriptor( ConstraintsDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+        descriptor = aDescriptor;
+        constraints = new LinkedList<>();
+    }
+
+    /**
+     * @return Descriptor of this {@code CompositeMethodConstrainsDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    public final ConstraintsDescriptor descriptor()
+    {
+        return descriptor;
+    }
+
+    /**
+     * @return Constraints of this {@code CompositeMethodConstrainsDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    public final Iterable<MethodConstraintDetailDescriptor> constraints()
+    {
+        return constraints;
+    }
+
+    /**
+     * @return Method that owns this {@code CompositeMethodConstrainsDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    public final CompositeMethodDetailDescriptor method()
+    {
+        return method;
+    }
+
+    final void setMethod( CompositeMethodDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        method = aDescriptor;
+    }
+
+    final void addConstraint( MethodConstraintDetailDescriptor aDescriptor )
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        aDescriptor.setConstraints( this );
+        constraints.add( aDescriptor );
+    }
+}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodSideEffectDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodSideEffectDetailDescriptor.java
new file mode 100644
index 0000000..484e031
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodSideEffectDetailDescriptor.java
@@ -0,0 +1,138 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.api.sideeffect.SideEffectDescriptor;
+
+public final class MethodSideEffectDetailDescriptor
+    implements InjectableDetailDescriptor
+{
+    private final SideEffectDescriptor descriptor;
+    private MethodSideEffectDetailDescriptor sideEffects;
+
+    private final List<ConstructorDetailDescriptor> constructors;
+    private final List<InjectedMethodDetailDescriptor> injectedMethods;
+    private final List<InjectedFieldDetailDescriptor> injectedFields;
+
+    MethodSideEffectDetailDescriptor( SideEffectDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+        descriptor = aDescriptor;
+        constructors = new LinkedList<>();
+        injectedMethods = new LinkedList<>();
+        injectedFields = new LinkedList<>();
+    }
+
+    /**
+     * @return Descriptor of this {@code MethodSideEffectDetailDescriptor}. Never returns {@code null}.
+     *
+     * @since 0.5
+     */
+    public final SideEffectDescriptor descriptor()
+    {
+        return descriptor;
+    }
+
+    /**
+     * @return Method side effects that owns this {@code MethodSideEffectDetailDescriptor}. Never returns {@code null}.
+     *
+     * @since 0.5
+     */
+    public final MethodSideEffectDetailDescriptor sideEffects()
+    {
+        return sideEffects;
+    }
+
+    /**
+     * @return Constructors of this {@code MethodSideEffectDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    @Override
+    public final Iterable<ConstructorDetailDescriptor> constructors()
+    {
+        return constructors;
+    }
+
+    /**
+     * @return Injected methods of this {@code MethodSideEffectDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    @Override
+    public final Iterable<InjectedMethodDetailDescriptor> injectedMethods()
+    {
+        return injectedMethods;
+    }
+
+    /**
+     * @return Injected fields of this {@code MethodSideEffectDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    @Override
+    public final Iterable<InjectedFieldDetailDescriptor> injectedFields()
+    {
+        return injectedFields;
+    }
+
+    final void setSideEffects( MethodSideEffectDetailDescriptor aDescriptor )
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+        sideEffects = aDescriptor;
+    }
+
+   @Override
+   public String toString()
+   {
+      return descriptor.modifierClass().getName();
+   }
+
+   final void addConstructor( ConstructorDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        aDescriptor.setMethodSideEffect( this );
+        constructors.add( aDescriptor );
+    }
+
+    final void addInjectedMethod( InjectedMethodDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        aDescriptor.setMethodSideEffect( this );
+        injectedMethods.add( aDescriptor );
+    }
+
+    final void addInjectedField( InjectedFieldDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        aDescriptor.setMethodSideEffect( this );
+        injectedFields.add( aDescriptor );
+    }
+}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodSideEffectsDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodSideEffectsDetailDescriptor.java
new file mode 100644
index 0000000..9be166b
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MethodSideEffectsDetailDescriptor.java
@@ -0,0 +1,87 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.api.sideeffect.SideEffectsDescriptor;
+
+public final class MethodSideEffectsDetailDescriptor
+{
+    private final SideEffectsDescriptor descriptor;
+    private CompositeMethodDetailDescriptor method;
+    private final List<MethodSideEffectDetailDescriptor> sideEffects;
+
+    MethodSideEffectsDetailDescriptor( SideEffectsDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        descriptor = aDescriptor;
+        sideEffects = new LinkedList<>();
+    }
+
+    /**
+     * @return Descriptor of this {@code MethodSideEffectsDescriptor}.
+     *
+     * @since 0.5
+     */
+    public final SideEffectsDescriptor descriptor()
+    {
+        return descriptor;
+    }
+
+    /**
+     * @return Composite method that owns this {@code MethodSideEffectsDescriptor}.
+     *
+     * @since 0.5
+     */
+    public final CompositeMethodDetailDescriptor method()
+    {
+        return method;
+    }
+
+    /**
+     * @return Side effects of this {@code MethodSideEffectDetailDescriptor}.
+     *
+     * @since 0.5
+     */
+    public final Iterable<MethodSideEffectDetailDescriptor> sideEffects()
+    {
+        return sideEffects;
+    }
+
+    final void setMethod( CompositeMethodDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+        method = aDescriptor;
+    }
+
+    final void addSideEffect( MethodSideEffectDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        aDescriptor.setSideEffects( aDescriptor );
+        sideEffects.add( aDescriptor );
+    }
+}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MixinDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MixinDetailDescriptor.java
new file mode 100644
index 0000000..544efdb
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/MixinDetailDescriptor.java
@@ -0,0 +1,136 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.api.mixin.MixinDescriptor;
+
+public final class MixinDetailDescriptor
+    implements InjectableDetailDescriptor
+{
+    private final MixinDescriptor descriptor;
+    private CompositeDetailDescriptor composite;
+    private final List<ConstructorDetailDescriptor> constructors;
+    private final List<InjectedMethodDetailDescriptor> injectedMethods;
+    private final List<InjectedFieldDetailDescriptor> injectedFields;
+
+    MixinDetailDescriptor( MixinDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+        descriptor = aDescriptor;
+        constructors = new LinkedList<>();
+        injectedMethods = new LinkedList<>();
+        injectedFields = new LinkedList<>();
+    }
+
+    /**
+     * @return Descriptor of this {@code MixinDetailDescriptor}.
+     *
+     * @since 0.5
+     */
+    public final MixinDescriptor descriptor()
+    {
+        return descriptor;
+    }
+
+    /**
+     * @return Constructors of this {@code MixinDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    @Override
+    public final Iterable<ConstructorDetailDescriptor> constructors()
+    {
+        return constructors;
+    }
+
+    /**
+     * @return Injected methods of this {@code MixinDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    @Override
+    public final Iterable<InjectedMethodDetailDescriptor> injectedMethods()
+    {
+        return injectedMethods;
+    }
+
+    /**
+     * @return Injected fields of this {@code MixinDetailDescriptor}. Never return {@code null}.
+     *
+     * @since 0.5
+     */
+    @Override
+    public final Iterable<InjectedFieldDetailDescriptor> injectedFields()
+    {
+        return injectedFields;
+    }
+
+    /**
+     * @return Composite that owns this {@code MixinDetailDescriptor}. Never return {@code null}.
+     */
+    public final CompositeDetailDescriptor composite()
+    {
+        return composite;
+    }
+
+    final void setComposite( CompositeDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+        composite = aDescriptor;
+    }
+
+    final void addConstructor( ConstructorDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        aDescriptor.setMixin( this );
+        constructors.add( aDescriptor );
+    }
+
+    final void addInjectedMethod( InjectedMethodDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        aDescriptor.setMixin( this );
+        injectedMethods.add( aDescriptor );
+    }
+
+    final void addInjectedField( InjectedFieldDetailDescriptor aDescriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( aDescriptor, "aDescriptor" );
+
+        aDescriptor.setMixin( this );
+        injectedFields.add( aDescriptor );
+    }
+
+    @Override
+    public String toString()
+    {
+        return descriptor.mixinClass().getSimpleName();
+    }
+}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ModuleDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ModuleDetailDescriptor.java
new file mode 100644
index 0000000..d956b13
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ModuleDetailDescriptor.java
@@ -0,0 +1,244 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * Module Detail Descriptor.
+ * <p>
+ * Visitable hierarchy with Activators and Composites children.
+ */
+public final class ModuleDetailDescriptor
+    implements ActivateeDetailDescriptor, VisitableHierarchy<Object, Object>
+{
+    private final ModuleDescriptor descriptor;
+    private LayerDetailDescriptor layer;
+    private final List<ActivatorDetailDescriptor> activators = new LinkedList<>();
+    private final List<ServiceDetailDescriptor> services = new LinkedList<>();
+    private final List<ImportedServiceDetailDescriptor> importedServices = new LinkedList<>();
+    private final List<EntityDetailDescriptor> entities = new LinkedList<>();
+    private final List<TransientDetailDescriptor> transients = new LinkedList<>();
+    private final List<ValueDetailDescriptor> values = new LinkedList<>();
+    private final List<ObjectDetailDescriptor> objects = new LinkedList<>();
+
+    ModuleDetailDescriptor( ModuleDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "ModuleDescriptor" );
+        this.descriptor = descriptor;
+    }
+
+    /**
+     * @return Descriptor of this {@code ModuleDetailDescriptor}. Never return {@code null}.
+     */
+    public final ModuleDescriptor descriptor()
+    {
+        return descriptor;
+    }
+
+    @Override
+    public Iterable<ActivatorDetailDescriptor> activators()
+    {
+        return activators;
+    }
+
+    /**
+     * @return Services of this {@code ModuleDetailDescriptor}. Never return {@code null}.
+     */
+    public final Iterable<ServiceDetailDescriptor> services()
+    {
+        return services;
+    }
+
+    /**
+     * @return Values of this {@code ModuleDetailDescriptor}. Never return {@code null}.
+     */
+    public final Iterable<ImportedServiceDetailDescriptor> importedServices()
+    {
+        return importedServices;
+    }
+
+    /**
+     * @return Entities of this {@code ModuleDetailDescriptor}. Never return {@code null}.
+     */
+    public final Iterable<EntityDetailDescriptor> entities()
+    {
+        return entities;
+    }
+
+    /**
+     * @return Values of this {@code ModuleDetailDescriptor}. Never return {@code null}.
+     */
+    public final Iterable<ValueDetailDescriptor> values()
+    {
+        return values;
+    }
+
+    /**
+     * @return Transients of this {@code ModuleDetailDescriptor}. Never return {@code null}.
+     */
+    public final Iterable<TransientDetailDescriptor> transients()
+    {
+        return transients;
+    }
+
+    /**
+     * @return Objects of this {@code ModuleDetailDescriptor}. Never return {@code null}.
+     */
+    public final Iterable<ObjectDetailDescriptor> objects()
+    {
+        return objects;
+    }
+
+    /**
+     * @return Layer that own this {@code ModuleDetailDescriptor}. Never return {@code null}.
+     */
+    public final LayerDetailDescriptor layer()
+    {
+        return layer;
+    }
+
+    final void setLayer( LayerDetailDescriptor descriptor )
+        throws IllegalArgumentException
+    {
+        Objects.requireNonNull( descriptor, "LayerDetailDescriptor" );
+        layer = descriptor;
+    }
+
+    final void addActivator( ActivatorDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ActivatorDetailDescriptor" );
+        descriptor.setModule( this );
+        activators.add( descriptor );
+    }
+
+    final void addService( ServiceDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ServiceDetailDescriptor" );
+        descriptor.setModule( this );
+        services.add( descriptor );
+    }
+
+    final void addImportedService( ImportedServiceDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ImportedServiceDetailDescriptor" );
+        descriptor.setModule( this );
+        importedServices.add( descriptor );
+    }
+
+    final void addEntity( EntityDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "EntityDetailDescriptor" );
+        descriptor.setModule( this );
+        entities.add( descriptor );
+    }
+
+    final void addValue( ValueDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ValueDetailDescriptor" );
+        descriptor.setModule( this );
+        values.add( descriptor );
+    }
+
+    final void addTransient( TransientDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "TransientDetailDescriptor" );
+        descriptor.setModule( this );
+        transients.add( descriptor );
+    }
+
+    final void addObject( ObjectDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ObjectDetailDescriptor" );
+        descriptor.setModule( this );
+        objects.add( descriptor );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( ActivatorDetailDescriptor activator : activators )
+            {
+                if( !activator.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+            for( ServiceDetailDescriptor service : services )
+            {
+                if( !service.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+            for( ImportedServiceDetailDescriptor importedService : importedServices )
+            {
+                if( !importedService.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+            for( EntityDetailDescriptor entity : entities )
+            {
+                if( !entity.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+            for( ValueDetailDescriptor value : values )
+            {
+                if( !value.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+            for( TransientDetailDescriptor composite : transients )
+            {
+                if( !composite.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+            for( ObjectDetailDescriptor object : objects )
+            {
+                if( !object.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    @Override
+    public final String toString()
+    {
+        return descriptor.name();
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ObjectDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ObjectDetailDescriptor.java
new file mode 100644
index 0000000..7c90e58
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ObjectDetailDescriptor.java
@@ -0,0 +1,129 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.util.Visitable;
+import org.apache.polygene.api.util.Visitor;
+
+/**
+ * Object Detail Descriptor.
+ */
+public final class ObjectDetailDescriptor
+    implements InjectableDetailDescriptor, Visitable<ObjectDetailDescriptor>
+{
+    private final ObjectDescriptor descriptor;
+    private ModuleDetailDescriptor module;
+    private final List<ConstructorDetailDescriptor> constructors = new LinkedList<>();
+    private final List<InjectedMethodDetailDescriptor> injectedMethods = new LinkedList<>();
+    private final List<InjectedFieldDetailDescriptor> injectedFields = new LinkedList<>();
+
+    ObjectDetailDescriptor( ObjectDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ObjectDescriptor" );
+        this.descriptor = descriptor;
+    }
+
+    /**
+     * @return Descriptor of this {@code ObjectDetailDescriptor}. Never return {@code null}.
+     */
+    public final ObjectDescriptor descriptor()
+    {
+        return descriptor;
+    }
+
+    /**
+     * @return Constructors of this {@code ObjectDetailDescriptor}. Never return {@code null}.
+     */
+    @Override
+    public final Iterable<ConstructorDetailDescriptor> constructors()
+    {
+        return constructors;
+    }
+
+    /**
+     * @return Injected methods of this {@code ObjectDetailDescriptor}. Never return {@code null}.
+     */
+    @Override
+    public final Iterable<InjectedMethodDetailDescriptor> injectedMethods()
+    {
+        return injectedMethods;
+    }
+
+    /**
+     * @return Injected fields of this {@code ObjectDetailDescriptor}. Never return {@code null}.
+     */
+    @Override
+    public final Iterable<InjectedFieldDetailDescriptor> injectedFields()
+    {
+        return injectedFields;
+    }
+
+    /**
+     * @return Module that own this {@code ObjectDetailDescriptor}. Never return {@code null}.
+     */
+    public final ModuleDetailDescriptor module()
+    {
+        return module;
+    }
+
+    final void setModule( ModuleDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ModuleDetailDescriptor" );
+        module = descriptor;
+    }
+
+    final void addConstructor( ConstructorDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ConstructorDetailDescriptor" );
+        descriptor.setObject( this );
+        constructors.add( descriptor );
+    }
+
+    final void addInjectedMethod( InjectedMethodDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "InjectedMethodDetailDescriptor" );
+        descriptor.setObject( this );
+        injectedMethods.add( descriptor );
+    }
+
+    final void addInjectedField( InjectedFieldDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "InjectedFieldDetailDescriptor" );
+        descriptor.setObject( this );
+        injectedFields.add( descriptor );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( Visitor<? super ObjectDetailDescriptor, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        return visitor.visit( this );
+    }
+
+    @Override
+    public String toString()
+    {
+        return descriptor.toString();
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ServiceDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ServiceDetailDescriptor.java
new file mode 100644
index 0000000..c2ab9f3
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ServiceDetailDescriptor.java
@@ -0,0 +1,99 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * Service Detail Descriptor.
+ * <p>
+ * Visitable hierarchy with Activators children.
+ */
+public final class ServiceDetailDescriptor
+    extends CompositeDetailDescriptor<ServiceDescriptor>
+    implements ActivateeDetailDescriptor, VisitableHierarchy<Object, Object>
+{
+    private final List<ActivatorDetailDescriptor> activators = new LinkedList<>();
+
+    ServiceDetailDescriptor( ServiceDescriptor descriptor )
+    {
+        super( descriptor );
+    }
+
+    /**
+     * @return layers that can access this service. Never return {@code null}.
+     */
+    public final List<LayerDetailDescriptor> accessibleToLayers()
+    {
+        Visibility visibility = descriptor.visibility();
+        if( visibility == Visibility.module )
+        {
+            return new LinkedList<>();
+        }
+
+        LayerDetailDescriptor layer = module.layer();
+        if( visibility == Visibility.layer )
+        {
+            List<LayerDetailDescriptor> layers = new LinkedList<>();
+            layers.add( layer );
+            return layers;
+        }
+        else
+        {
+            return layer.usedBy();
+        }
+    }
+
+    @Override
+    public Iterable<ActivatorDetailDescriptor> activators()
+    {
+        return activators;
+    }
+
+    final void addActivator( ActivatorDetailDescriptor descriptor )
+    {
+        Objects.requireNonNull( descriptor, "ActivatorDetailDescriptor" );
+        descriptor.setService( this );
+        activators.add( descriptor );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( ActivatorDetailDescriptor activator : activators )
+            {
+                if( !activator.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ServiceUsage.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ServiceUsage.java
new file mode 100644
index 0000000..2504138
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ServiceUsage.java
@@ -0,0 +1,61 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+public final class ServiceUsage
+{
+
+    private final Object ownerDescriptor;
+
+    private final InjectedFieldDetailDescriptor field;
+
+    private final ModuleDetailDescriptor module;
+
+    private final LayerDetailDescriptor layer;
+
+    public ServiceUsage( Object ownerDescriptor, InjectedFieldDetailDescriptor field, ModuleDetailDescriptor module, LayerDetailDescriptor layer )
+    {
+        this.ownerDescriptor = ownerDescriptor;
+        this.field = field;
+        this.module = module;
+        this.layer = layer;
+    }
+
+    public Object ownerDescriptor()
+    {
+        return ownerDescriptor;
+    }
+
+    public InjectedFieldDetailDescriptor field()
+    {
+        return field;
+    }
+
+    public ModuleDetailDescriptor module()
+    {
+        return module;
+    }
+
+    public LayerDetailDescriptor layer()
+    {
+        return layer;
+    }
+
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/TransientDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/TransientDetailDescriptor.java
new file mode 100644
index 0000000..e66087a
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/TransientDetailDescriptor.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.util.Visitable;
+import org.apache.polygene.api.util.Visitor;
+
+/**
+ * Transient Detail Descriptor.
+ */
+public class TransientDetailDescriptor
+    extends CompositeDetailDescriptor<TransientDescriptor>
+    implements Visitable<TransientDetailDescriptor>
+{
+    TransientDetailDescriptor( TransientDescriptor aDescriptor )
+    {
+        super( aDescriptor );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( Visitor<? super TransientDetailDescriptor, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        return visitor.visit( this );
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ValueDetailDescriptor.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ValueDetailDescriptor.java
new file mode 100644
index 0000000..3e2dbe5
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/ValueDetailDescriptor.java
@@ -0,0 +1,44 @@
+/*
+ *  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.polygene.tools.model.descriptor;
+
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.api.util.Visitable;
+import org.apache.polygene.api.util.Visitor;
+
+/**
+ * Value Detail Descriptor.
+ */
+public class ValueDetailDescriptor
+    extends CompositeDetailDescriptor<ValueDescriptor>
+    implements Visitable<ValueDetailDescriptor>
+{
+    ValueDetailDescriptor( ValueDescriptor aDescriptor )
+    {
+        super( aDescriptor );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( Visitor<? super ValueDetailDescriptor, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        return visitor.visit( this );
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/package.html b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/package.html
new file mode 100644
index 0000000..29e572d
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/descriptor/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Detailled Application Model Descriptors.</h2>
+    </body>
+</html>
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/APIFinder.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/APIFinder.java
new file mode 100644
index 0000000..6035836
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/APIFinder.java
@@ -0,0 +1,58 @@
+/*
+ *  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.polygene.tools.model.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.tools.model.descriptor.LayerDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ModuleDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ServiceDetailDescriptor;
+
+/**
+ * API would be defined as "All service interfaces which are visible for layer
+ * or application"
+ */
+class APIFinder
+{
+
+    public List<ServiceDetailDescriptor> findModuleAPI( ModuleDetailDescriptor descriptor )
+    {
+        ArrayList<ServiceDetailDescriptor> list = new ArrayList<ServiceDetailDescriptor>();
+
+        for( ServiceDetailDescriptor serviceDetailDescriptor : descriptor.services() )
+        {
+            list.add( serviceDetailDescriptor );
+        }
+
+        return list;
+    }
+
+    public List<ServiceDetailDescriptor> findLayerAPI( LayerDetailDescriptor descriptor )
+    {
+        ArrayList<ServiceDetailDescriptor> list = new ArrayList<ServiceDetailDescriptor>();
+
+        for( ModuleDetailDescriptor moduleDetailDescriptor : descriptor.modules() )
+        {
+            list.addAll( findModuleAPI( moduleDetailDescriptor ) );
+        }
+
+        return list;
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/DescriptorNameComparator.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/DescriptorNameComparator.java
new file mode 100644
index 0000000..da433fb
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/DescriptorNameComparator.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.tools.model.util;
+
+import java.util.Comparator;
+
+/**
+ * DescriptorName comparator.
+ * Implementation is using toString() for comparing
+ * @param <T> Parameterized descriptor type
+ */
+public class DescriptorNameComparator<T>
+    implements Comparator<T>
+{
+    @Override
+    public int compare( T o1, T o2 )
+    {
+        return o1.toString().compareTo( o2.toString() );
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/DescriptorUtilities.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/DescriptorUtilities.java
new file mode 100644
index 0000000..da974b0
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/DescriptorUtilities.java
@@ -0,0 +1,137 @@
+/*
+ *  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.polygene.tools.model.util;
+
+import java.util.List;
+import org.apache.polygene.tools.model.descriptor.CompositeDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.CompositeMethodDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.LayerDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ModuleDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ServiceDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ServiceUsage;
+
+/**
+ * Collection of Desciptor Utilities
+ */
+public class DescriptorUtilities
+{
+    private DescriptorUtilities()
+    {
+        throw new Error( "This is a utility class for static methods" );
+    }
+
+    /**
+     * Return Descriptor Detail
+     *
+     * @param descriptor ServiceDetailDescriptor
+     *
+     * @return list of Descritpor Detail (never return null)
+     */
+    public static List<CompositeMethodDetailDescriptor> findMethod( CompositeDetailDescriptor descriptor )
+    {
+        return new MethodFinder().findMethod( descriptor );
+    }
+
+    /**
+     * Return Descriptor Detail
+     *
+     * @param descriptor ServiceDetailDescriptor
+     *
+     * @return list of Descritpor Detail (never return null)
+     */
+    public static List<CompositeMethodDetailDescriptor> findState( CompositeDetailDescriptor descriptor )
+    {
+        return new StateFinder().findState( descriptor );
+    }
+
+    /**
+     * Return Descriptor Detail
+     *
+     * @param descriptor ServiceDetailDescriptor
+     *
+     * @return Descritpor Detail or null
+     */
+    public static Object findServiceConfiguration( ServiceDetailDescriptor descriptor )
+    {
+        return new ServiceConfigurationFinder().findConfigurationDescriptor( descriptor );
+    }
+
+    /**
+     * Return list of Descriptor Detail for particular Service Usage
+     *
+     * @param descriptor ServiceDetailDescriptor
+     *
+     * @return list of service usage (never return null)
+     */
+    public static List<ServiceUsage> findServiceUsage( ServiceDetailDescriptor descriptor )
+    {
+        return new ServiceUsageFinder().findServiceUsage( descriptor );
+    }
+
+    /**
+     * Return list of Descriptor Detail for All service interfaces which are visible for the module
+     *
+     * @param descriptor ModuleDetailDescriptor
+     *
+     * @return list of ServiceDetailDescriptor (never return null)
+     */
+    public static List<ServiceDetailDescriptor> findModuleAPI( ModuleDetailDescriptor descriptor )
+    {
+        return new APIFinder().findModuleAPI( descriptor );
+    }
+
+    /**
+     * Return list of Descriptor Detail for All service interfaces which are visible for the layer
+     *
+     * @param descriptor ModuleDetailDescriptor
+     *
+     * @return list of ServiceDetailDescriptor (never return null)
+     */
+    public static List<ServiceDetailDescriptor> findLayerAPI( LayerDetailDescriptor descriptor )
+    {
+        return new APIFinder().findLayerAPI( descriptor );
+    }
+
+    /**
+     * Return list of Descriptor Detail for all service dependencies which
+     * are not satisfied from within the module
+     *
+     * @param descriptor ModuleDetailDescriptor
+     *
+     * @return list of ServiceDetailDescriptor (never return null)
+     */
+    public static List<ServiceDetailDescriptor> findModule( ModuleDetailDescriptor descriptor )
+    {
+        return new SPIFinder().findModule( descriptor );
+    }
+
+    /**
+     * Return list of Descriptor Detail for all service dependencies which
+     * are not satisfied from within the layer
+     *
+     * @param descriptor ModuleDetailDescriptor
+     *
+     * @return list of ServiceDetailDescriptor (never return null)
+     */
+    public static List<ServiceDetailDescriptor> findLayerSPI( LayerDetailDescriptor descriptor )
+    {
+        return new SPIFinder().findLayerSPI( descriptor );
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/MethodFinder.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/MethodFinder.java
new file mode 100644
index 0000000..63b18cf
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/MethodFinder.java
@@ -0,0 +1,116 @@
+/*
+ *  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.polygene.tools.model.util;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.tools.model.descriptor.CompositeDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.CompositeMethodDetailDescriptor;
+
+public class MethodFinder
+{
+    public List<CompositeMethodDetailDescriptor> findMethod( CompositeDetailDescriptor<?> descriptor )
+    {
+        return findMethod( descriptor.methods() );
+    }
+
+    /**
+     * The Methods tab should show all the methods of all Mixins (private and public separated)
+     * that don't return one of Property, Association or ManyAssociation.
+     *
+     * "private" and "public" refers to if the interface they are declared in is extended by the Composite.
+     * If yes, then it is a public method, meaning, clients can call it.
+     * If no, then it is a private mixin type, and can only be used internally through @This injections.
+     */
+    private List<CompositeMethodDetailDescriptor> findMethod( Iterable<CompositeMethodDetailDescriptor> iter )
+    {
+        List<CompositeMethodDetailDescriptor> publicList = new ArrayList<>();
+        List<CompositeMethodDetailDescriptor> privateList = new ArrayList<>();
+
+        for( CompositeMethodDetailDescriptor descriptor : iter )
+        {
+            CompositeDescriptor compositeDescriptor = descriptor.composite().descriptor();
+            Class<?> mixinMethodClass = descriptor.descriptor().method().getDeclaringClass();
+            compositeDescriptor.types().forEach( mixinType ->
+            {
+                if( mixinMethodClass.isAssignableFrom( mixinType ) )
+                {
+                    publicList.add( descriptor );
+                }
+                else
+                {
+                    privateList.add( descriptor );
+                }
+            } );
+        }
+
+        // combine into one list, with public listed first then private
+        publicList.addAll( privateList );
+
+        // filter Property, Association, ManyAssociation and NamedAssociation
+        doFilter( publicList );
+
+        return publicList;
+    }
+
+    /**
+     * Do the filter for method return type (Property, Association, ManyAssociation, NamedAssociation)
+     * by removing the entry from the list.
+     *
+     * @param list list of CompositeMethodDetailDescriptor
+     */
+    private void doFilter( List<CompositeMethodDetailDescriptor> list )
+    {
+        if( list.isEmpty() )
+        {
+            return;
+        }
+
+        Iterator<CompositeMethodDetailDescriptor> iter = list.iterator();
+        while( iter.hasNext() )
+        {
+            CompositeMethodDetailDescriptor descriptor = iter.next();
+            Method method = descriptor.descriptor().method();
+            if( Property.class.isAssignableFrom( method.getReturnType() ) )
+            {
+                iter.remove();
+            }
+            else if( Association.class.isAssignableFrom( method.getReturnType() ) )
+            {
+                iter.remove();
+            }
+            else if( ManyAssociation.class.isAssignableFrom( method.getReturnType() ) )
+            {
+                iter.remove();
+            }
+            else if( NamedAssociation.class.isAssignableFrom( method.getReturnType() ) )
+            {
+                iter.remove();
+            }
+        }
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/SPIFinder.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/SPIFinder.java
new file mode 100644
index 0000000..e136a10
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/SPIFinder.java
@@ -0,0 +1,171 @@
+/*
+ *  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.polygene.tools.model.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.tools.model.descriptor.ApplicationDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.EntityDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.InjectedFieldDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.LayerDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.MixinDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ModuleDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ObjectDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ServiceDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.TransientDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ValueDetailDescriptor;
+
+/**
+ * SPI would be defined as "All service dependencies which are not satisfied from within the module or Layer".
+ */
+class SPIFinder
+{
+    private ApplicationDetailDescriptor appDetailDescriptor;
+
+    public List<ServiceDetailDescriptor> findModule( ModuleDetailDescriptor descriptor )
+    {
+        appDetailDescriptor = descriptor.layer().application();
+
+        ArrayList<ServiceDetailDescriptor> list = new ArrayList<>();
+
+        findInServices( descriptor.services(), list );
+        findInEntities( descriptor.entities(), list );
+        findInValues( descriptor.values(), list );
+        findInTransients( descriptor.transients(), list );
+        findInObjects( descriptor.objects(), list );
+
+        return list;
+    }
+
+    public List<ServiceDetailDescriptor> findLayerSPI( LayerDetailDescriptor descriptor )
+    {
+        List<ServiceDetailDescriptor> list = new ArrayList<>();
+
+        for( ModuleDetailDescriptor moduleDetailDescriptor : descriptor.modules() )
+        {
+            list.addAll( findModule( moduleDetailDescriptor ) );
+        }
+
+        return list;
+    }
+
+    private void findInMixin( Iterable<MixinDetailDescriptor> iter, ArrayList<ServiceDetailDescriptor> list )
+    {
+        for( MixinDetailDescriptor descriptor : iter )
+        {
+            findInInjectedField( descriptor.injectedFields(), list );
+        }
+    }
+
+    private void findInInjectedField( Iterable<InjectedFieldDetailDescriptor> iter,
+                                      ArrayList<ServiceDetailDescriptor> list
+    )
+    {
+//        for( InjectedFieldDetailDescriptor descriptorField : iter )
+//        {
+//            DependencyDescriptor dependencyDescriptor = descriptorField.descriptor().dependency();
+//            Annotation annotation = dependencyDescriptor.injectionAnnotation();
+
+//            Class<? extends Annotation> clazz = annotation.annotationType();
+//            if( Uses.class.equals( clazz ) || Service.class.equals( clazz ) )
+//            {
+//                for( String name : dependencyDescriptor.injectedServices() )
+//                {
+//                    ServiceDetailDescriptor serviceDetailDescriptor = lookupServiceDetailDescriptor( name );
+//                    if( serviceDetailDescriptor != null )
+//                    {
+//                        if( !list.contains( serviceDetailDescriptor ) )
+//                        {
+//                            list.add( serviceDetailDescriptor );
+//                        }
+//                    }
+//                }
+//            }
+//        }
+    }
+
+    private void findInServices( Iterable<ServiceDetailDescriptor> iter, ArrayList<ServiceDetailDescriptor> list )
+    {
+        for( ServiceDetailDescriptor descriptor : iter )
+        {
+            findInMixin( descriptor.mixins(), list );
+        }
+    }
+
+    private void findInEntities( Iterable<EntityDetailDescriptor> iter, ArrayList<ServiceDetailDescriptor> list )
+    {
+        for( EntityDetailDescriptor descriptor : iter )
+        {
+            findInMixin( descriptor.mixins(), list );
+        }
+    }
+
+    private void findInValues( Iterable<ValueDetailDescriptor> iter, ArrayList<ServiceDetailDescriptor> list )
+    {
+        for( ValueDetailDescriptor descriptor : iter )
+        {
+            findInMixin( descriptor.mixins(), list );
+        }
+    }
+
+    private void findInTransients( Iterable<TransientDetailDescriptor> iter, ArrayList<ServiceDetailDescriptor> list )
+    {
+        for( TransientDetailDescriptor descriptor : iter )
+        {
+            findInMixin( descriptor.mixins(), list );
+        }
+    }
+
+    private void findInObjects( Iterable<ObjectDetailDescriptor> iter, ArrayList<ServiceDetailDescriptor> list )
+    {
+        for( ObjectDetailDescriptor descriptor : iter )
+        {
+            findInInjectedField( descriptor.injectedFields(), list );
+        }
+    }
+
+    private ServiceDetailDescriptor lookupServiceDetailDescriptor( String name )
+    {
+        ServiceDetailDescriptor serviceDetailDescriptor = null;
+        for( LayerDetailDescriptor layer : appDetailDescriptor.layers() )
+        {
+            for( ModuleDetailDescriptor module : layer.modules() )
+            {
+                for( ServiceDetailDescriptor service : module.services() )
+                {
+                    if( service.toString().equals( name ) )
+                    {
+                        serviceDetailDescriptor = service;
+                        break;
+                    }
+                }
+                if( serviceDetailDescriptor != null )
+                {
+                    break;
+                }
+            }
+            if( serviceDetailDescriptor != null )
+            {
+                break;
+            }
+        }
+        return serviceDetailDescriptor;
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/ServiceConfigurationFinder.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/ServiceConfigurationFinder.java
new file mode 100644
index 0000000..64c9081
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/ServiceConfigurationFinder.java
@@ -0,0 +1,158 @@
+/*
+ *  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.polygene.tools.model.util;
+
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.tools.model.descriptor.ApplicationDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.CompositeDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.EntityDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.LayerDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ModuleDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ObjectDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ServiceDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.TransientDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ValueDetailDescriptor;
+
+class ServiceConfigurationFinder
+{
+    public Object findConfigurationDescriptor( ServiceDetailDescriptor descriptor )
+    {
+        Class<?> configType = descriptor.descriptor().configurationType();
+
+        if( configType == null )
+        {
+            return null;
+        }
+
+        // traverse the appDescriptor to find the configurationDescriptor
+        ApplicationDetailDescriptor appDescriptor = descriptor.module().layer().application();
+        Object obj = findConfigurationDescriptor( appDescriptor, configType );
+        if( obj == null )
+        {
+            return null;
+        }
+
+        return obj;
+    }
+
+    private Object findConfigurationDescriptor( ApplicationDetailDescriptor descriptor, Class<?> configType )
+    {
+        Object configDescriptor = null;
+        for( LayerDetailDescriptor childDescriptor : descriptor.layers() )
+        {
+            Object obj = findInModules( childDescriptor.modules(), configType );
+            if( obj != null )
+            {
+                configDescriptor = obj;
+                break;
+            }
+        }
+
+        return configDescriptor;
+    }
+
+    private Object findInModules( Iterable<ModuleDetailDescriptor> iter, Class<?> configType )
+    {
+        Object configDescriptor = null;
+
+        for( ModuleDetailDescriptor descriptor : iter )
+        {
+            Object obj = findInTypes( descriptor.services(), configType );
+            if( obj != null )
+            {
+                configDescriptor = obj;
+                break;
+            }
+
+            obj = findInTypes( descriptor.entities(), configType );
+            if( obj != null )
+            {
+                configDescriptor = obj;
+                break;
+            }
+
+            obj = findInTypes( descriptor.transients(), configType );
+            if( obj != null )
+            {
+                configDescriptor = obj;
+                break;
+            }
+
+            obj = findInTypes( descriptor.values(), configType );
+            if( obj != null )
+            {
+                configDescriptor = obj;
+                break;
+            }
+
+            obj = findInTypes( descriptor.objects(), configType );
+            if( obj != null )
+            {
+                configDescriptor = obj;
+                break;
+            }
+        }
+
+        return configDescriptor;
+    }
+
+    private Object findInTypes( Iterable iter, Class<?> configType )
+    {
+        Object configDescriptor = null;
+
+        for( Object obj : iter )
+        {
+            ModelDescriptor descriptor;
+
+            if( obj instanceof ServiceDetailDescriptor )
+            {
+                descriptor = ( (ServiceDetailDescriptor) obj ).descriptor();
+            }
+            else if( obj instanceof EntityDetailDescriptor )
+            {
+                descriptor = ( (EntityDetailDescriptor) obj ).descriptor();
+            }
+            else if( obj instanceof ValueDetailDescriptor )
+            {
+                descriptor = ( (ValueDetailDescriptor) obj ).descriptor();
+            }
+            else if( obj instanceof ObjectDetailDescriptor )
+            {
+                descriptor = ( (ObjectDetailDescriptor) obj ).descriptor();
+            }
+            else if( obj instanceof TransientDetailDescriptor )
+            {
+                descriptor = ( (TransientDetailDescriptor) obj ).descriptor();
+            }
+            else
+            {
+                descriptor = ( (CompositeDetailDescriptor) obj ).descriptor();
+            }
+
+            if( configType.equals( descriptor.types().findFirst().orElse( null ) ) )
+            {
+                configDescriptor = obj;
+                break;
+            }
+        }
+
+        return configDescriptor;
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/ServiceUsageFinder.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/ServiceUsageFinder.java
new file mode 100644
index 0000000..7c6dd8e
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/ServiceUsageFinder.java
@@ -0,0 +1,163 @@
+/*
+ *  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.polygene.tools.model.util;
+
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.composite.DependencyDescriptor;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.tools.model.descriptor.ApplicationDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.EntityDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.InjectedFieldDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.LayerDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.MixinDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ModuleDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ObjectDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ServiceDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ServiceUsage;
+import org.apache.polygene.tools.model.descriptor.TransientDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.ValueDetailDescriptor;
+
+/* package */ class ServiceUsageFinder
+{
+    private ServiceDetailDescriptor descriptor;
+    private ArrayList<ServiceUsage> usages;
+
+    public List<ServiceUsage> findServiceUsage( ServiceDetailDescriptor descriptor )
+    {
+        usages = new ArrayList<>();
+
+        this.descriptor = descriptor;
+
+        // traverse the appDescritor/model to find the usage
+        ApplicationDetailDescriptor appDescriptor = descriptor.module().layer().application();
+        collectUsage( appDescriptor );
+
+        return usages;
+    }
+
+    private void collectUsage( ApplicationDetailDescriptor descriptor )
+    {
+        for( LayerDetailDescriptor childDescriptor : descriptor.layers() )
+        {
+            collectInModules( childDescriptor.modules() );
+        }
+    }
+
+    private void collectInModules( Iterable<ModuleDetailDescriptor> iter )
+    {
+        for( ModuleDetailDescriptor descriptor : iter )
+        {
+            collectInServices( descriptor.services() );
+            collectInEntities( descriptor.entities() );
+            collectInValues( descriptor.values() );
+            collectInTransients( descriptor.transients() );
+            collectInObjects( descriptor.objects() );
+        }
+    }
+
+    private void collectInServices( Iterable<ServiceDetailDescriptor> iter )
+    {
+        for( ServiceDetailDescriptor descriptor : iter )
+        {
+            if( descriptor.equals( this.descriptor ) )
+            {
+                continue;
+            }
+            collectInMixin( descriptor.mixins() );
+        }
+    }
+
+    private void collectInEntities( Iterable<EntityDetailDescriptor> iter )
+    {
+        for( EntityDetailDescriptor descriptor : iter )
+        {
+            collectInMixin( descriptor.mixins() );
+        }
+    }
+
+    private void collectInValues( Iterable<ValueDetailDescriptor> iter )
+    {
+        for( ValueDetailDescriptor descriptor : iter )
+        {
+            collectInMixin( descriptor.mixins() );
+        }
+    }
+
+    private void collectInTransients( Iterable<TransientDetailDescriptor> iter )
+    {
+        for( TransientDetailDescriptor descriptor : iter )
+        {
+            collectInMixin( descriptor.mixins() );
+        }
+    }
+
+    private void collectInObjects( Iterable<ObjectDetailDescriptor> iter )
+    {
+        for( ObjectDetailDescriptor descriptor : iter )
+        {
+            collectInInjectedField( descriptor.injectedFields(), descriptor );
+        }
+    }
+
+    private void collectInMixin( Iterable<MixinDetailDescriptor> iter )
+    {
+        for( MixinDetailDescriptor descriptor : iter )
+        {
+            collectInInjectedField( descriptor.injectedFields(), descriptor );
+        }
+    }
+
+    private void collectInInjectedField( Iterable<InjectedFieldDetailDescriptor> iter, Object ownerDescriptor )
+    {
+        for( InjectedFieldDetailDescriptor descriptorField : iter )
+        {
+            DependencyDescriptor dependencyDescriptor = descriptorField.descriptor().dependency();
+            Annotation annotation = dependencyDescriptor.injectionAnnotation();
+
+            Class<? extends Annotation> clazz = annotation.annotationType();
+            if( Uses.class.equals( clazz ) || Service.class.equals( clazz ) )
+            {
+                if( dependencyDescriptor.injectionType()
+                    .equals( this.descriptor.descriptor().types().findFirst().orElse( null ) ) )
+                {
+                    ServiceUsage usage;
+                    if( ownerDescriptor instanceof MixinDetailDescriptor )
+                    {
+                        MixinDetailDescriptor mixinDescriptor = (MixinDetailDescriptor) ownerDescriptor;
+                        usage = new ServiceUsage( mixinDescriptor.composite(), descriptorField, mixinDescriptor.composite()
+                            .module(), mixinDescriptor.composite().module().layer() );
+                    }
+                    else
+                    {
+                        // assume ObjectDetailDescriptor
+                        ObjectDetailDescriptor objectDescriptor = (ObjectDetailDescriptor) ownerDescriptor;
+                        usage = new ServiceUsage( objectDescriptor, descriptorField, objectDescriptor.module(), objectDescriptor
+                            .module()
+                            .layer() );
+                    }
+                    usages.add( usage );
+                }
+            }
+        }
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/StateFinder.java b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/StateFinder.java
new file mode 100644
index 0000000..1bc444f
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/StateFinder.java
@@ -0,0 +1,96 @@
+/*
+ *  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.polygene.tools.model.util;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.tools.model.descriptor.CompositeDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.CompositeMethodDetailDescriptor;
+
+public class StateFinder
+{
+    public List<CompositeMethodDetailDescriptor> findState( CompositeDetailDescriptor<?> descriptor )
+    {
+        return findState( descriptor.methods() );
+    }
+
+    private List<CompositeMethodDetailDescriptor> findState( Iterable<CompositeMethodDetailDescriptor> iter )
+    {
+        List<CompositeMethodDetailDescriptor> publicList = new ArrayList<>();
+        List<CompositeMethodDetailDescriptor> privateList = new ArrayList<>();
+
+        for( CompositeMethodDetailDescriptor descriptor : iter )
+        {
+            Class<?> compositeClass = descriptor.composite().descriptor().types().findFirst().orElse( null );
+            Class<?> mixinMethodClass = descriptor.descriptor().method().getDeclaringClass();
+            if( mixinMethodClass.isAssignableFrom( compositeClass ) )
+            {
+                publicList.add( descriptor );
+            }
+            else
+            {
+                privateList.add( descriptor );
+            }
+        }
+
+        // combine into one list, with public listed first then private
+        publicList.addAll( privateList );
+
+        // filter Property, Association, ManyAssociation and NamedAssociation
+        doFilter( publicList );
+
+        return publicList;
+    }
+
+    /**
+     * Do the filter for method return type (Property, Association, ManyAssociation, NamedAssociation)
+     * by removing the entry from the list if not the above.
+     *
+     * @param list list of CompositeMethodDetailDescriptor
+     */
+    private void doFilter( List<CompositeMethodDetailDescriptor> list )
+    {
+        if( list.isEmpty() )
+        {
+            return;
+        }
+
+        Iterator<CompositeMethodDetailDescriptor> iter = list.iterator();
+        while( iter.hasNext() )
+        {
+            CompositeMethodDetailDescriptor descriptor = iter.next();
+            Method method = descriptor.descriptor().method();
+            if( Property.class.isAssignableFrom( method.getReturnType() )
+                || Association.class.isAssignableFrom( method.getReturnType() )
+                || ManyAssociation.class.isAssignableFrom( method.getReturnType() )
+                || NamedAssociation.class.isAssignableFrom( method.getReturnType() ) )
+            {
+                continue;
+            }
+            iter.remove();
+        }
+    }
+}
diff --git a/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/package.html b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/package.html
new file mode 100644
index 0000000..da040d9
--- /dev/null
+++ b/tools/model-detail/src/main/java/org/apache/polygene/tools/model/util/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Detailled Application Model Utilities.</h2>
+    </body>
+</html>
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ActivateeDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ActivateeDetailDescriptor.java
deleted file mode 100644
index d9344bc..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ActivateeDetailDescriptor.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-/**
- * Activatee Detail Descriptor.
- */
-public interface ActivateeDetailDescriptor
-{
-    /**
-     * @return Activators of this {@literal Activatee}. Never return {@code null}.
-     */
-    Iterable<ActivatorDetailDescriptor> activators();
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ActivatorDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ActivatorDetailDescriptor.java
deleted file mode 100644
index e894d6e..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ActivatorDetailDescriptor.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2014-2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.qi4j.api.activation.ActivatorDescriptor;
-import org.qi4j.functional.Visitable;
-import org.qi4j.functional.Visitor;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-/**
- * Activator Detail Descriptor.
- */
-public class ActivatorDetailDescriptor
-    implements InjectableDetailDescriptor, Visitable<ActivatorDetailDescriptor>
-{
-    private final ActivatorDescriptor descriptor;
-    private final List<ConstructorDetailDescriptor> constructors;
-    private final List<InjectedMethodDetailDescriptor> injectedMethods;
-    private final List<InjectedFieldDetailDescriptor> injectedFields;
-    private ServiceDetailDescriptor service;
-    private ImportedServiceDetailDescriptor importedService;
-    private ModuleDetailDescriptor module;
-    private LayerDetailDescriptor layer;
-    private ApplicationDetailDescriptor application;
-
-    public ActivatorDetailDescriptor( ActivatorDescriptor descriptor )
-    {
-        validateNotNull( "Activator Descriptor", descriptor );
-        this.descriptor = descriptor;
-        constructors = new LinkedList<>();
-        injectedMethods = new LinkedList<>();
-        injectedFields = new LinkedList<>();
-    }
-
-    /**
-     * @return Service that own this {@code ActivatorDetailDescriptor}.
-     */
-    public ServiceDetailDescriptor service()
-    {
-        return service;
-    }
-
-    /**
-     * @return Imported Service that own this {@code ActivatorDetailDescriptor}.
-     */
-    public ImportedServiceDetailDescriptor importedService()
-    {
-        return importedService;
-    }
-
-    /**
-     * @return Module that own this {@code ActivatorDetailDescriptor}.
-     */
-    public ModuleDetailDescriptor module()
-    {
-        return module;
-    }
-
-    /**
-     * @return Layer that own this {@code ActivatorDetailDescriptor}.
-     */
-    public LayerDetailDescriptor layer()
-    {
-        return layer;
-    }
-
-    /**
-     * @return Application that own this {@code ActivatorDetailDescriptor}.
-     */
-    public ApplicationDetailDescriptor application()
-    {
-        return application;
-    }
-
-    @Override
-    public Iterable<ConstructorDetailDescriptor> constructors()
-    {
-        return constructors;
-    }
-
-    @Override
-    public Iterable<InjectedMethodDetailDescriptor> injectedMethods()
-    {
-        return injectedMethods;
-    }
-
-    @Override
-    public Iterable<InjectedFieldDetailDescriptor> injectedFields()
-    {
-        return injectedFields;
-    }
-
-    final void setService( ServiceDetailDescriptor descriptor )
-    {
-        validateNotNull( "ServiceDetailDescriptor", descriptor );
-        service = descriptor;
-    }
-
-    final void setImportedService( ImportedServiceDetailDescriptor descriptor )
-    {
-        validateNotNull( "ImportedServiceDetailDescriptor", descriptor );
-        importedService = descriptor;
-    }
-
-    final void setModule( ModuleDetailDescriptor descriptor )
-    {
-        validateNotNull( "ModuleDetailDescriptor", descriptor );
-        module = descriptor;
-    }
-
-    final void setLayer( LayerDetailDescriptor descriptor )
-    {
-        validateNotNull( "LayerDetailDescriptor", descriptor );
-        layer = descriptor;
-    }
-
-    final void setApplication( ApplicationDetailDescriptor descriptor )
-    {
-        validateNotNull( "ApplicationDetailDescriptor", descriptor );
-        application = descriptor;
-    }
-
-    final void addConstructor( ConstructorDetailDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "ConstructorDetailDescriptor", descriptor );
-        descriptor.setActivator( this );
-        constructors.add( descriptor );
-    }
-
-    final void addInjectedMethod( InjectedMethodDetailDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "InjectedMethodDetailDescriptor", descriptor );
-        descriptor.setActivator( this );
-        injectedMethods.add( descriptor );
-    }
-
-    final void addInjectedField( InjectedFieldDetailDescriptor descriptor )
-    {
-        validateNotNull( "InjectedFieldDetailDescriptor", descriptor );
-        descriptor.setActivator( this );
-        injectedFields.add( descriptor );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( Visitor<? super ActivatorDetailDescriptor, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        return visitor.visit( this );
-    }
-
-    @Override
-    public String toString()
-    {
-        return descriptor.toString();
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ApplicationDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ApplicationDetailDescriptor.java
deleted file mode 100644
index 1ec8b46..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ApplicationDetailDescriptor.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2014-2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-/**
- * Application Detail Descriptor.
- * <p>
- * Visitable hierarchy with Activators and Layers children.
- */
-public final class ApplicationDetailDescriptor
-    implements ActivateeDetailDescriptor, VisitableHierarchy<Object, Object>
-{
-    private final ApplicationDescriptor descriptor;
-    private final List<ActivatorDetailDescriptor> activators = new LinkedList<>();
-    private final List<LayerDetailDescriptor> layers = new LinkedList<>();
-
-    ApplicationDetailDescriptor( ApplicationDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "ApplicationDescriptor", descriptor );
-        this.descriptor = descriptor;
-    }
-
-    /**
-     * @return Descriptor of this {@code ApplicationDetailDescriptor}. Never return {@code null}.
-     */
-    public final ApplicationDescriptor descriptor()
-    {
-        return descriptor;
-    }
-
-    @Override
-    public Iterable<ActivatorDetailDescriptor> activators()
-    {
-        return activators;
-    }
-
-    /**
-     * @return Layers of this {@code ApplicationDetailDescriptor}. Never return {@code null}.
-     */
-    public final Iterable<LayerDetailDescriptor> layers()
-    {
-        return layers;
-    }
-
-    final void addActivator( ActivatorDetailDescriptor descriptor )
-    {
-        validateNotNull( "ActivatorDetailDescriptor", descriptor );
-        descriptor.setApplication( this );
-        activators.add( descriptor );
-    }
-
-    final void addLayer( LayerDetailDescriptor descriptor )
-    {
-        validateNotNull( "LayerDetailDescriptor", descriptor );
-        descriptor.setApplication( this );
-        layers.add( descriptor );
-    }
-
-    @Override
-    public final String toString()
-    {
-        return descriptor.name();
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( ActivatorDetailDescriptor activator : activators )
-            {
-                if( !activator.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-            for( LayerDetailDescriptor layer : layers )
-            {
-                if( !layer.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ApplicationDetailDescriptorBuilder.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ApplicationDetailDescriptorBuilder.java
deleted file mode 100644
index 4d4e0cc..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ApplicationDetailDescriptorBuilder.java
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2008, Sonny Gill. All Rights Reserved.
- * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
- * Copyright (c) 2014-2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import java.util.HashMap;
-import java.util.Map;
-import org.qi4j.api.activation.ActivatorDescriptor;
-import org.qi4j.api.composite.ConstructorDescriptor;
-import org.qi4j.api.composite.InjectedFieldDescriptor;
-import org.qi4j.api.composite.InjectedMethodDescriptor;
-import org.qi4j.api.composite.InjectedParametersDescriptor;
-import org.qi4j.api.composite.MethodDescriptor;
-import org.qi4j.api.composite.TransientDescriptor;
-import org.qi4j.api.concern.ConcernDescriptor;
-import org.qi4j.api.concern.ConcernsDescriptor;
-import org.qi4j.api.constraint.ConstraintDescriptor;
-import org.qi4j.api.constraint.ConstraintsDescriptor;
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.api.mixin.MixinDescriptor;
-import org.qi4j.api.object.ObjectDescriptor;
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.api.sideeffect.SideEffectDescriptor;
-import org.qi4j.api.sideeffect.SideEffectsDescriptor;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.api.structure.LayerDescriptor;
-import org.qi4j.api.structure.ModuleDescriptor;
-import org.qi4j.api.structure.UsedLayersDescriptor;
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.functional.HierarchicalVisitor;
-
-public final class ApplicationDetailDescriptorBuilder
-{
-    private ApplicationDetailDescriptorBuilder()
-    {
-    }
-
-    public static ApplicationDetailDescriptor createApplicationDetailDescriptor( ApplicationDescriptor anApplication )
-    {
-        ApplicationDescriptorVisitor visitor = new ApplicationDescriptorVisitor();
-        anApplication.accept( visitor );
-
-        return visitor.applicationDescriptor;
-    }
-
-    static final class ApplicationDescriptorVisitor
-        implements HierarchicalVisitor<Object, Object, RuntimeException>
-    {
-        // Temp: application
-        private ApplicationDetailDescriptor applicationDescriptor;
-
-        // Temp: Layer variables
-        private LayerDetailDescriptor currLayerDescriptor;
-        // Cache to lookup layer descriptor -> node
-        private final Map<LayerDescriptor, LayerDetailDescriptor> layerDescToDetail;
-
-        // Temp: current module
-        private ModuleDetailDescriptor currModuleDescriptor;
-
-        // Temp: current composite
-        private CompositeDetailDescriptor currCompositeDescriptor;
-
-        // Temp: curr activator
-        private ActivatorDetailDescriptor currActivatorDescriptor;
-
-        // Temp: curr mixin
-        private MixinDetailDescriptor currMixinDescriptor;
-
-        // Temp: current constructor
-        private ConstructorDetailDescriptor currConstructorDescriptor;
-
-        // Temp: current injected method
-        private InjectedMethodDetailDescriptor currInjectedMethodDescriptor;
-
-        // Temp: current composite method
-        private CompositeMethodDetailDescriptor currMethodDesciptor;
-
-        // Temp: current method constraints
-        private MethodConstraintsDetailDescriptor currMethodConstraintsDescriptor;
-
-        // Temp: current object
-        private ObjectDetailDescriptor currObjectDescriptor;
-
-        // Temp: current method concerns
-        private MethodConcernsDetailDescriptor currMethodConcernsDescriptor;
-
-        // Temp: current method concern
-        private MethodConcernDetailDescriptor currMethodConcernDescriptor;
-
-        // Temp: current method side effects
-        private MethodSideEffectsDetailDescriptor currMethodSideEffectsDescriptor;
-
-        // Temp: current side effect
-        private MethodSideEffectDetailDescriptor currMethodSideEffectDescriptor;
-
-        private ApplicationDescriptorVisitor()
-        {
-            layerDescToDetail = new HashMap<>();
-        }
-
-        @Override
-        public boolean visitEnter( Object visited )
-            throws RuntimeException
-        {
-            if( visited instanceof ApplicationDescriptor )
-            {
-                applicationDescriptor = new ApplicationDetailDescriptor( (ApplicationDescriptor) visited );
-            }
-            else if( visited instanceof LayerDescriptor )
-            {
-                LayerDescriptor layerDescriptor = (LayerDescriptor) visited;
-                currLayerDescriptor = getLayerDetailDescriptor( layerDescriptor );
-                applicationDescriptor.addLayer( currLayerDescriptor );
-
-                UsedLayersDescriptor usedLayesDescriptor = layerDescriptor.usedLayers();
-                Iterable<? extends LayerDescriptor> usedLayers = usedLayesDescriptor.layers();
-                for( LayerDescriptor usedLayer : usedLayers )
-                {
-                    LayerDetailDescriptor usedLayerDetailDesc = getLayerDetailDescriptor( usedLayer );
-                    currLayerDescriptor.addUsedLayer( usedLayerDetailDesc );
-                }
-            }
-            else if( visited instanceof ModuleDescriptor )
-            {
-                ModuleDescriptor moduleDescriptor = (ModuleDescriptor) visited;
-                currModuleDescriptor = new ModuleDetailDescriptor( moduleDescriptor );
-                currLayerDescriptor.addModule( currModuleDescriptor );
-            }
-            else if( visited instanceof ActivatorDescriptor )
-            {
-                ActivatorDescriptor activatorDescriptor = (ActivatorDescriptor) visited;
-                currActivatorDescriptor = new ActivatorDetailDescriptor( activatorDescriptor );
-                if( currCompositeDescriptor != null )
-                {
-                    if( currCompositeDescriptor instanceof ServiceDetailDescriptor )
-                    {
-                        ( (ServiceDetailDescriptor) currCompositeDescriptor ).addActivator( currActivatorDescriptor );
-                    }
-                    else if( currCompositeDescriptor instanceof ImportedServiceDetailDescriptor )
-                    {
-                        ( (ImportedServiceDetailDescriptor) currCompositeDescriptor ).addActivator( currActivatorDescriptor );
-                    }
-                    else
-                    {
-                        throw new IllegalStateException( "ActivatorDescriptor is only valid for "
-                                                         + "services, modules, layers and application." );
-                    }
-                }
-                else if( currModuleDescriptor != null )
-                {
-                    currModuleDescriptor.addActivator( currActivatorDescriptor );
-                }
-                else if( currLayerDescriptor != null )
-                {
-                    currLayerDescriptor.addActivator( currActivatorDescriptor );
-                }
-                else if( applicationDescriptor != null )
-                {
-                    applicationDescriptor.addActivator( currActivatorDescriptor );
-                }
-                else
-                {
-                    throw new IllegalStateException( "ActivatorDescriptor is only valid for "
-                                                     + "services, modules, layers and application." );
-                }
-            }
-            else if( visited instanceof ServiceDescriptor )
-            {
-                ServiceDetailDescriptor descriptor = new ServiceDetailDescriptor( (ServiceDescriptor) visited );
-                currModuleDescriptor.addService( descriptor );
-                currCompositeDescriptor = descriptor;
-            }
-            else if( visited instanceof ImportedServiceDescriptor )
-            {
-                ImportedServiceDetailDescriptor descriptor = new ImportedServiceDetailDescriptor( new ImportedServiceCompositeDescriptor( (ImportedServiceDescriptor) visited ) );
-                currModuleDescriptor.addImportedService( descriptor );
-                currCompositeDescriptor = descriptor;
-            }
-            else if( visited instanceof EntityDescriptor )
-            {
-                EntityDetailDescriptor descriptor = new EntityDetailDescriptor( (EntityDescriptor) visited );
-                currModuleDescriptor.addEntity( descriptor );
-                currCompositeDescriptor = descriptor;
-            }
-            else if( visited instanceof ValueDescriptor )
-            {
-                ValueDetailDescriptor descriptor = new ValueDetailDescriptor( (ValueDescriptor) visited );
-                currModuleDescriptor.addValue( descriptor );
-                currCompositeDescriptor = descriptor;
-            }
-            else if( visited instanceof TransientDescriptor )
-            {
-                TransientDetailDescriptor descriptor = new TransientDetailDescriptor( (TransientDescriptor) visited );
-                currModuleDescriptor.addTransient( descriptor );
-                currCompositeDescriptor = descriptor;
-            }
-            else if( visited instanceof MethodDescriptor )
-            {
-                if( currCompositeDescriptor == null )
-                {
-                    // Service via CompositeDescriptor in progress )
-                    return false;
-                }
-                currMethodDesciptor = new CompositeMethodDetailDescriptor( (MethodDescriptor) visited );
-                currCompositeDescriptor.addMethod( currMethodDesciptor );
-            }
-            else if( visited instanceof ConstraintsDescriptor )
-            {
-                if( currCompositeDescriptor == null )
-                {
-                    // Service via CompositeDescriptor in progress )
-                    return false;
-                }
-                currMethodConstraintsDescriptor = new MethodConstraintsDetailDescriptor( (ConstraintsDescriptor) visited );
-                currMethodDesciptor.setConstraints( currMethodConstraintsDescriptor );
-            }
-            else if( visited instanceof ConcernsDescriptor )
-            {
-                if( currCompositeDescriptor == null )
-                {
-                    // Service via CompositeDescriptor in progress )
-                    return false;
-                }
-                currMethodConcernsDescriptor = new MethodConcernsDetailDescriptor( (ConcernsDescriptor) visited );
-                currMethodDesciptor.setConcerns( currMethodConcernsDescriptor );
-            }
-            else if( visited instanceof ConcernDescriptor )
-            {
-                if( currCompositeDescriptor == null )
-                {
-                    // Service via CompositeDescriptor in progress )
-                    return false;
-                }
-                resetInjectableRelatedVariables();
-
-                currMethodConcernDescriptor = new MethodConcernDetailDescriptor( (ConcernDescriptor) visited );
-                currMethodConcernsDescriptor.addConcern( currMethodConcernDescriptor );
-            }
-            else if( visited instanceof SideEffectsDescriptor )
-            {
-                if( currCompositeDescriptor == null )
-                {
-                    // Service via CompositeDescriptor in progress )
-                    return false;
-                }
-                currMethodSideEffectsDescriptor = new MethodSideEffectsDetailDescriptor( (SideEffectsDescriptor) visited );
-                currMethodDesciptor.setSideEffects( currMethodSideEffectsDescriptor );
-            }
-            else if( visited instanceof SideEffectDescriptor )
-            {
-                if( currCompositeDescriptor == null )
-                {
-                    // Service via CompositeDescriptor in progress )
-                    return false;
-                }
-                resetInjectableRelatedVariables();
-
-                currMethodSideEffectDescriptor = new MethodSideEffectDetailDescriptor( (SideEffectDescriptor) visited );
-                currMethodSideEffectsDescriptor.addSideEffect( currMethodSideEffectDescriptor );
-            }
-            else if( visited instanceof MixinDescriptor )
-            {
-                if( currCompositeDescriptor == null )
-                {
-                    // Service via CompositeDescriptor in progress )
-                    return false;
-                }
-                resetInjectableRelatedVariables();
-
-                currMixinDescriptor = new MixinDetailDescriptor( (MixinDescriptor) visited );
-                currCompositeDescriptor.addMixin( currMixinDescriptor );
-            }
-            else if( visited instanceof ObjectDescriptor )
-            {
-                resetInjectableRelatedVariables();
-
-                currObjectDescriptor = new ObjectDetailDescriptor( (ObjectDescriptor) visited );
-                currModuleDescriptor.addObject( currObjectDescriptor );
-            }
-            else if( visited instanceof ConstructorDescriptor )
-            {
-                if( currCompositeDescriptor == null )
-                {
-                    // Service via CompositeDescriptor in progress )
-                    return false;
-                }
-                currConstructorDescriptor = new ConstructorDetailDescriptor( (ConstructorDescriptor) visited );
-                currInjectedMethodDescriptor = null;
-
-                // Invoked for mixin and object
-                if( currActivatorDescriptor != null )
-                {
-                    currActivatorDescriptor.addConstructor( currConstructorDescriptor );
-                }
-                else if( currMixinDescriptor != null )
-                {
-                    currMixinDescriptor.addConstructor( currConstructorDescriptor );
-                }
-                else if( currObjectDescriptor != null )
-                {
-                    currObjectDescriptor.addConstructor( currConstructorDescriptor );
-                }
-                else if( currMethodConcernDescriptor != null )
-                {
-                    currMethodConcernDescriptor.addConstructor( currConstructorDescriptor );
-                }
-                else if( currMethodSideEffectDescriptor != null )
-                {
-                    currMethodSideEffectDescriptor.addConstructor( currConstructorDescriptor );
-                }
-                else
-                {
-                    throw new IllegalStateException( "ConstructorDescriptor is only valid for "
-                                                     + "activator, mixin, object, concern and side-effect. "
-                                                     + "Visiting [" + visited + "]" );
-                }
-            }
-            else if( visited instanceof InjectedParametersDescriptor )
-            {
-                if( currCompositeDescriptor == null )
-                {
-                    // Service via CompositeDescriptor in progress )
-                    return false;
-                }
-                InjectedParametersDetailDescriptor detailDescriptor = new InjectedParametersDetailDescriptor( (InjectedParametersDescriptor) visited );
-
-                // Invoked for constructor and injected method
-                if( currConstructorDescriptor != null )
-                {
-                    currConstructorDescriptor.setInjectedParameter( detailDescriptor );
-                }
-                else if( currInjectedMethodDescriptor != null )
-                {
-                    currInjectedMethodDescriptor.setInjectedParameter( detailDescriptor );
-                }
-                else
-                {
-                    throw new IllegalStateException( "InjectedParametersDescriptor is only valid for "
-                                                     + "constructor and injector method descriptor." );
-                }
-            }
-            else if( visited instanceof InjectedMethodDescriptor )
-            {
-                if( currCompositeDescriptor == null )
-                {
-                    // Service via CompositeDescriptor in progress )
-                    return false;
-                }
-                // Invoked for mixin and object
-                currInjectedMethodDescriptor = new InjectedMethodDetailDescriptor( (InjectedMethodDescriptor) visited );
-                currConstructorDescriptor = null;
-
-                // Invoked for mixin and object
-                if( currActivatorDescriptor != null )
-                {
-                    currActivatorDescriptor.addInjectedMethod( currInjectedMethodDescriptor );
-                }
-                else if( currMixinDescriptor != null )
-                {
-                    currMixinDescriptor.addInjectedMethod( currInjectedMethodDescriptor );
-                }
-                else if( currObjectDescriptor != null )
-                {
-                    currObjectDescriptor.addInjectedMethod( currInjectedMethodDescriptor );
-                }
-                else if( currMethodConcernDescriptor != null )
-                {
-                    currMethodConcernDescriptor.addInjectedMethod( currInjectedMethodDescriptor );
-                }
-                else if( currMethodSideEffectDescriptor != null )
-                {
-                    currMethodSideEffectDescriptor.addInjectedMethod( currInjectedMethodDescriptor );
-                }
-                else
-                {
-                    throw new IllegalStateException( "InjectedMethodDescriptor is only valid for "
-                                                     + "mixin, object, concern and side-effect." );
-                }
-            }
-
-            return true;
-        }
-
-        @Override
-        public boolean visitLeave( Object visited )
-            throws RuntimeException
-        {
-            return true;
-        }
-
-        @Override
-        public boolean visit( Object visited )
-            throws RuntimeException
-        {
-            if( visited instanceof ConstraintDescriptor )
-            {
-                if( currCompositeDescriptor == null )
-                {
-                    // Service via CompositeDescriptor in progress )
-                    return false;
-                }
-                MethodConstraintDetailDescriptor detailDescriptor = new MethodConstraintDetailDescriptor( (ConstraintDescriptor) visited );
-                currMethodConstraintsDescriptor.addConstraint( detailDescriptor );
-            }
-            else if( visited instanceof InjectedFieldDescriptor )
-            {
-                if( currCompositeDescriptor == null )
-                {
-                    // Service via CompositeDescriptor in progress )
-                    return false;
-                }
-                InjectedFieldDetailDescriptor detailDescriptor = new InjectedFieldDetailDescriptor( (InjectedFieldDescriptor) visited );
-
-                // Invoked for mixin and object
-                if( currActivatorDescriptor != null )
-                {
-                    currActivatorDescriptor.addInjectedField( detailDescriptor );
-                }
-                else if( currMixinDescriptor != null )
-                {
-                    currMixinDescriptor.addInjectedField( detailDescriptor );
-                }
-                else if( currObjectDescriptor != null )
-                {
-                    currObjectDescriptor.addInjectedField( detailDescriptor );
-                }
-                else if( currMethodConcernDescriptor != null )
-                {
-                    currMethodConcernDescriptor.addInjectedField( detailDescriptor );
-                }
-                else if( currMethodSideEffectDescriptor != null )
-                {
-                    currMethodSideEffectDescriptor.addInjectedField( detailDescriptor );
-                }
-                else
-                {
-                    throw new IllegalStateException( "InjectedFieldDescriptor is only valid for "
-                                                     + "mixin, object, concern and side-effect." );
-                }
-            }
-
-            return true;
-        }
-
-        private LayerDetailDescriptor getLayerDetailDescriptor( LayerDescriptor aDescriptor )
-        {
-            LayerDetailDescriptor detailDescriptor = layerDescToDetail.get( aDescriptor );
-            if( detailDescriptor == null )
-            {
-                detailDescriptor = new LayerDetailDescriptor( aDescriptor );
-                layerDescToDetail.put( aDescriptor, detailDescriptor );
-            }
-
-            return detailDescriptor;
-        }
-
-        private void resetInjectableRelatedVariables()
-        {
-            currMixinDescriptor = null;
-            currObjectDescriptor = null;
-            currMethodConcernDescriptor = null;
-            currMethodSideEffectDescriptor = null;
-        }
-    }
-
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/CompositeDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/CompositeDetailDescriptor.java
deleted file mode 100644
index 02cb99b..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/CompositeDetailDescriptor.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import java.lang.reflect.Method;
-import java.util.LinkedList;
-import java.util.List;
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.composite.MethodDescriptor;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-/**
- * Composite Detail Descriptor.
- *
- * @param <T> CompositeDescriptor type
- */
-public abstract class CompositeDetailDescriptor<T extends CompositeDescriptor>
-{
-    protected final T descriptor;
-    protected ModuleDetailDescriptor module;
-    protected final List<CompositeMethodDetailDescriptor> methods;
-    protected final List<MixinDetailDescriptor> mixins;
-
-    CompositeDetailDescriptor( T aDescriptor )
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        descriptor = aDescriptor;
-        methods = new LinkedList<>();
-        mixins = new LinkedList<>();
-    }
-
-    /**
-     * @return Descriptor of this {@code CompositeDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    public final T descriptor()
-    {
-        return descriptor;
-    }
-
-    /**
-     * @return Methods of this {@code CompositeDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    public final Iterable<CompositeMethodDetailDescriptor> methods()
-    {
-        return methods;
-    }
-
-    /**
-     * @return Mixins of this {@code CompositeDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    public final Iterable<MixinDetailDescriptor> mixins()
-    {
-        return mixins;
-    }
-
-    /**
-     * Return method detail descriptor of the requested method. Returns {@code null} if not found.
-     *
-     * @param aMethod Method to look up. This argument must not be {@code null}.
-     *
-     * @return method detail descriptor of the requested method.
-     *
-     * @since 0.5
-     */
-    public final CompositeMethodDetailDescriptor getMethodDescriptor( Method aMethod )
-    {
-        for( CompositeMethodDetailDescriptor descriptor : methods )
-        {
-            MethodDescriptor methodDescriptor = descriptor.descriptor();
-            Method method = methodDescriptor.method();
-            if( method.equals( aMethod ) )
-            {
-                return descriptor;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * @return Module that own this {@code CompositeDetailDescriptor}.
-     *
-     * @since 0.5
-     */
-    public final ModuleDetailDescriptor module()
-    {
-        return module;
-    }
-
-    final void setModule( ModuleDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-        module = aDescriptor;
-    }
-
-    final void addMethod( CompositeMethodDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        aDescriptor.setComposite( this );
-        methods.add( aDescriptor );
-    }
-
-    final void addMixin( MixinDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        aDescriptor.setComposite( this );
-        mixins.add( aDescriptor );
-    }
-
-    @Override
-    public String toString()
-    {
-        return descriptor.toString();
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/CompositeMethodDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/CompositeMethodDetailDescriptor.java
deleted file mode 100644
index 8b5463d..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/CompositeMethodDetailDescriptor.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import org.qi4j.api.composite.MethodDescriptor;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-public final class CompositeMethodDetailDescriptor
-{
-    private final MethodDescriptor descriptor;
-
-    private CompositeDetailDescriptor composite;
-    private MethodConstraintsDetailDescriptor constraints;
-    private MethodConcernsDetailDescriptor concerns;
-    private MethodSideEffectsDetailDescriptor sideEffects;
-
-    CompositeMethodDetailDescriptor( MethodDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-        descriptor = aDescriptor;
-
-        composite = null;
-        constraints = null;
-        sideEffects = null;
-    }
-
-    /**
-     * @return Descriptor of this {@code CompositeMethodDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    public final MethodDescriptor descriptor()
-    {
-        return descriptor;
-    }
-
-    /**
-     * @return Constraints of this {@code CompositeMethodDetailDescriptor}.
-     *         Returns {@code null} if this method does not have any constraints.
-     *
-     * @since 0.5
-     */
-    public final MethodConstraintsDetailDescriptor constraints()
-    {
-        return constraints;
-    }
-
-    /**
-     * @return Concerns of this {@code CompositeMethodDetailDescriptor}. Returns {@code null} if this method does not
-     *         have any concerns.
-     *
-     * @since 0.5
-     */
-    public final MethodConcernsDetailDescriptor concerns()
-    {
-        return concerns;
-    }
-
-    /**
-     * @return Side-effects of this {@code CompositeMethodDetailDescriptor}. Returns {@code null}
-     *         if this method does not have any side effects.
-     *
-     * @since 0.5
-     */
-    public final MethodSideEffectsDetailDescriptor sideEffects()
-    {
-        return sideEffects;
-    }
-
-    /**
-     * @return Composite that owns this {@code CompositeMethodDetailDescriptor}.
-     *
-     * @since 0.5
-     */
-    public final CompositeDetailDescriptor composite()
-    {
-        return composite;
-    }
-
-    final void setComposite( CompositeDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-        composite = aDescriptor;
-    }
-
-    final void setConstraints( MethodConstraintsDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        aDescriptor.setMethod( this );
-        constraints = aDescriptor;
-    }
-
-    public void setConcerns( MethodConcernsDetailDescriptor aDescriptor )
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        aDescriptor.setMethod( this );
-        concerns = aDescriptor;
-    }
-
-    final void setSideEffects( MethodSideEffectsDetailDescriptor aDescriptor )
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        aDescriptor.setMethod( this );
-        sideEffects = aDescriptor;
-    }
-
-    @Override
-    public final String toString()
-    {
-        return descriptor.method().getName();
-    }
-}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ConstructorDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ConstructorDetailDescriptor.java
deleted file mode 100644
index 646e80e..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ConstructorDetailDescriptor.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import org.qi4j.api.composite.ConstructorDescriptor;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-/**
- * Constructor Detail Descriptor.
- */
-public final class ConstructorDetailDescriptor
-{
-    private final ConstructorDescriptor descriptor;
-    private ActivatorDetailDescriptor activator;
-    private ObjectDetailDescriptor object;
-    private MixinDetailDescriptor mixin;
-    private MethodConcernDetailDescriptor methodConcern;
-    private MethodSideEffectDetailDescriptor methodSideEffect;
-    private InjectedParametersDetailDescriptor parameters;
-
-    ConstructorDetailDescriptor( ConstructorDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "ConstructorDescriptor", descriptor );
-        this.descriptor = descriptor;
-        this.parameters = null;
-    }
-
-    /**
-     * @return Descriptor of this {@code ConstructorDetailDescriptor}. Never return {@code null}.
-     */
-    public final ConstructorDescriptor descriptor()
-    {
-        return descriptor;
-    }
-
-    /**
-     * @return Constructor parameters of this {@code ConstructorDetailDescriptor}. Never return {@code null}.
-     */
-    public final InjectedParametersDetailDescriptor parameters()
-    {
-        return parameters;
-    }
-
-    /**
-     * @return Activator that own this {@code ConstructorDetailDescriptor}.
-     */
-    public final ActivatorDetailDescriptor activator()
-    {
-        return activator;
-    }
-
-    /**
-     * @return Object that own this {@code ConstructorDetailDescriptor}.
-     */
-    public final ObjectDetailDescriptor object()
-    {
-        return object;
-    }
-
-    /**
-     * @return Mixin that own this {@code ConstructorDetailDescriptor}.
-     */
-    public final MixinDetailDescriptor mixin()
-    {
-        return mixin;
-    }
-
-    /**
-     * @return Method concern that own this {@code ConstructorDetailDescriptor}.
-     */
-    public final MethodConcernDetailDescriptor methodConcern()
-    {
-        return methodConcern;
-    }
-
-    /**
-     * @return Method side effect that own this {@code ConstructorDetailDescriptor}.
-     */
-    public final MethodSideEffectDetailDescriptor methodSideEffect()
-    {
-        return methodSideEffect;
-    }
-
-    final void setActivator( ActivatorDetailDescriptor descriptor )
-    {
-        validateNotNull( "ActivatorDetailDescriptor", descriptor );
-        activator = descriptor;
-    }
-
-    final void setObject( ObjectDetailDescriptor descriptor )
-    {
-        validateNotNull( "ObjectDetailDescriptor", descriptor );
-        object = descriptor;
-    }
-
-    final void setMixin( MixinDetailDescriptor descriptor )
-    {
-        validateNotNull( "MixinDetailDescriptor", descriptor );
-        mixin = descriptor;
-    }
-
-    final void setMethodConcern( MethodConcernDetailDescriptor descriptor )
-    {
-        validateNotNull( "MethodConcernDetailDescriptor", descriptor );
-        methodConcern = descriptor;
-    }
-
-    final void setInjectedParameter( InjectedParametersDetailDescriptor descriptor )
-    {
-        validateNotNull( "InjectedParametersDetailDescriptor", descriptor );
-        descriptor.setConstructor( this );
-        parameters = descriptor;
-    }
-
-    final void setMethodSideEffect( MethodSideEffectDetailDescriptor descriptor )
-    {
-        validateNotNull( "MethodSideEffectDetailDescriptor", descriptor );
-        methodSideEffect = descriptor;
-    }
-
-    @Override
-    public final String toString()
-    {
-        return descriptor.constructor().getDeclaringClass().getSimpleName();
-    }
-
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/EntityDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/EntityDetailDescriptor.java
deleted file mode 100644
index 7bfef2a..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/EntityDetailDescriptor.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import org.qi4j.api.entity.EntityDescriptor;
-import org.qi4j.functional.Visitable;
-import org.qi4j.functional.Visitor;
-
-/**
- * Entity Detail Descriptor.
- */
-public final class EntityDetailDescriptor
-    extends CompositeDetailDescriptor<EntityDescriptor>
-    implements Visitable<EntityDetailDescriptor>
-{
-    EntityDetailDescriptor( EntityDescriptor aDescriptor )
-    {
-        super( aDescriptor );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( Visitor<? super EntityDetailDescriptor, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        return visitor.visit( this );
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ImportedServiceCompositeDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ImportedServiceCompositeDescriptor.java
deleted file mode 100644
index 993e1f3..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ImportedServiceCompositeDescriptor.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2009, Tonny Kohar. All Rights Reserved.
- * Copyright (c) 2011, Rickard Öberg. All Rights Reserved.
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.service.ImportedServiceDescriptor;
-import org.qi4j.api.service.ServiceImporter;
-import org.qi4j.api.util.Classes;
-import org.qi4j.functional.Iterables;
-
-/**
- * XXX Workaround for inconsistency in Qi4J core-api/spi
- * ImportedServiceDescriptor wrapper as composite
- */
-public class ImportedServiceCompositeDescriptor
-    implements CompositeDescriptor
-{
-    protected ImportedServiceDescriptor importedService;
-    protected final List<Class<?>> mixins = new LinkedList<>();
-
-    public ImportedServiceCompositeDescriptor( ImportedServiceDescriptor descriptor )
-    {
-        this.importedService = descriptor;
-    }
-
-    public ImportedServiceDescriptor importedService()
-    {
-        return importedService;
-    }
-
-    @Override
-    public Iterable<Class<?>> mixinTypes()
-    {
-        return mixins;
-    }
-
-    @Override
-    public Class<?> primaryType()
-    {
-        return importedService.type();
-    }
-
-    @Override
-    public Visibility visibility()
-    {
-        return importedService.visibility();
-    }
-
-    @Override
-    public <T> T metaInfo( Class<T> infoType )
-    {
-        return importedService.metaInfo( infoType );
-    }
-
-    @Override
-    public Iterable<Class<?>> types()
-    {
-        return Iterables.cast( Iterables.iterable( importedService.type() ) );
-    }
-
-    @Override
-    public boolean isAssignableTo( Class<?> type )
-    {
-        return importedService.isAssignableTo( type );
-    }
-
-    public Class<? extends ServiceImporter> serviceImporter()
-    {
-        return importedService.serviceImporter();
-    }
-
-    public String toURI()
-    {
-        return Classes.toURI( primaryType() );
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ImportedServiceDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ImportedServiceDetailDescriptor.java
deleted file mode 100644
index a7fea24..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ImportedServiceDetailDescriptor.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2009, Tonny Kohar. All Rights Reserved.
- * Copyright (c) 2014-2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-/**
- * Imported Service Detail Descriptor.
- * <p>
- * Visitable hierarchy with Activators children.
- */
-// TODO need to refactor later, but wait until Qi4J core/spi have proper and consistent API for ImportedService.
-public class ImportedServiceDetailDescriptor
-    extends CompositeDetailDescriptor<ImportedServiceCompositeDescriptor>
-    implements ActivateeDetailDescriptor, VisitableHierarchy<Object, Object>
-{
-    private final List<ActivatorDetailDescriptor> activators = new LinkedList<>();
-
-    ImportedServiceDetailDescriptor( ImportedServiceCompositeDescriptor descriptor )
-    {
-        super( descriptor );
-    }
-
-    @Override
-    public Iterable<ActivatorDetailDescriptor> activators()
-    {
-        return activators;
-    }
-
-    final void addActivator( ActivatorDetailDescriptor descriptor )
-    {
-        validateNotNull( "ActivatorDetailDescriptor", descriptor );
-        descriptor.setImportedService( this );
-        activators.add( descriptor );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( ActivatorDetailDescriptor activator : activators )
-            {
-                if( !activator.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/InjectableDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/InjectableDetailDescriptor.java
deleted file mode 100644
index fe34d0c..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/InjectableDetailDescriptor.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-public interface InjectableDetailDescriptor
-{
-    /**
-     * @return Constructors. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    Iterable<ConstructorDetailDescriptor> constructors();
-
-    /**
-     * @return Injected methods. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    Iterable<InjectedMethodDetailDescriptor> injectedMethods();
-
-    /**
-     * @return Injected fields. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    Iterable<InjectedFieldDetailDescriptor> injectedFields();
-}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/InjectedFieldDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/InjectedFieldDetailDescriptor.java
deleted file mode 100644
index 32b0373..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/InjectedFieldDetailDescriptor.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import org.qi4j.api.composite.InjectedFieldDescriptor;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-public final class InjectedFieldDetailDescriptor
-{
-    private final InjectedFieldDescriptor descriptor;
-    private ActivatorDetailDescriptor activator;
-    private ObjectDetailDescriptor object;
-    private MixinDetailDescriptor mixin;
-    private MethodConcernDetailDescriptor methodConcern;
-    private MethodSideEffectDetailDescriptor methodSideEffect;
-
-    InjectedFieldDetailDescriptor( InjectedFieldDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "InjectedFieldDescriptor", descriptor );
-        this.descriptor = descriptor;
-    }
-
-    /**
-     * @return Descriptor of this {@code InjectedFieldDetailDescriptor}. Never returns {@code null}.
-     */
-    public final InjectedFieldDescriptor descriptor()
-    {
-        return descriptor;
-    }
-
-    /**
-     * @return Activator that own this {@code InjectedFieldDetailDescriptor}.
-     */
-    public final ActivatorDetailDescriptor activator()
-    {
-        return activator;
-    }
-
-    /**
-     * @return Object that own this {@code InjectedFieldDetailDescriptor}.
-     */
-    public final ObjectDetailDescriptor object()
-    {
-        return object;
-    }
-
-    /**
-     * @return Mixin that own this {@code InjectedFieldDetailDescriptor}.
-     */
-    public final MixinDetailDescriptor mixin()
-    {
-        return mixin;
-    }
-
-    /**
-     * @return Method concern that own this {@code InjectedFieldDetailDescriptor}.
-     */
-    public final MethodConcernDetailDescriptor methodConcern()
-    {
-        return methodConcern;
-    }
-
-    /**
-     * @return Method side effect that own this {@code InjectedFieldDetailDescriptor}.
-     */
-    public final MethodSideEffectDetailDescriptor methodSideEffect()
-    {
-        return methodSideEffect;
-    }
-
-    final void setActivator( ActivatorDetailDescriptor descriptor )
-    {
-        validateNotNull( "ActivatorDetailDescriptor", descriptor );
-        activator = descriptor;
-    }
-
-    final void setObject( ObjectDetailDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "ObjectDetailDescriptor", descriptor );
-        object = descriptor;
-    }
-
-    final void setMixin( MixinDetailDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "MixinDetailDescriptor", descriptor );
-        mixin = descriptor;
-    }
-
-    final void setMethodConcern( MethodConcernDetailDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "MethodConcernDetailDescriptor", descriptor );
-        methodConcern = descriptor;
-    }
-
-    final void setMethodSideEffect( MethodSideEffectDetailDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "MethodSideEffectDetailDescriptor", descriptor );
-        methodSideEffect = descriptor;
-    }
-
-    @Override
-    public final String toString()
-    {
-        return descriptor.field().getName();
-    }
-
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/InjectedMethodDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/InjectedMethodDetailDescriptor.java
deleted file mode 100644
index f51ebe2..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/InjectedMethodDetailDescriptor.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2014, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import org.qi4j.api.composite.InjectedMethodDescriptor;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-public final class InjectedMethodDetailDescriptor
-{
-    private final InjectedMethodDescriptor descriptor;
-    private ActivatorDetailDescriptor activator;
-    private ObjectDetailDescriptor object;
-    private MixinDetailDescriptor mixin;
-    private MethodSideEffectDetailDescriptor methodSideEffect;
-    private MethodConcernDetailDescriptor methodConcern;
-    private InjectedParametersDetailDescriptor parameters;
-
-    InjectedMethodDetailDescriptor( InjectedMethodDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "InjectedMethodDescriptor", descriptor );
-        this.descriptor = descriptor;
-        this.parameters = null;
-    }
-
-    /**
-     * @return Descriptor of this {@code InjectedMethodDetailDescriptor}. Never return {@code null}.
-     */
-    public final InjectedMethodDescriptor descriptor()
-    {
-        return descriptor;
-    }
-
-    /**
-     * @return Method parameters of this {@code InjectedMethodDetailDescriptor}. Never return {@code null}.
-     */
-    public final InjectedParametersDetailDescriptor parameters()
-    {
-        return parameters;
-    }
-
-    /**
-     * @return Activator that owns this {@code InjectedMethodDetailDescriptor}.
-     */
-    public final ActivatorDetailDescriptor activator()
-    {
-        return activator;
-    }
-
-    /**
-     * @return Object that owns this {@code InjectedMethodDetailDescriptor}.
-     */
-    public final ObjectDetailDescriptor object()
-    {
-        return object;
-    }
-
-    /**
-     * @return Mixin that owns this {@code InjectedMethodDetailDescriptor}.
-     */
-    public final MixinDetailDescriptor mixin()
-    {
-        return mixin;
-    }
-
-    /**
-     * @return Method side effect that owns this {@code InjectedMethodDetailDescriptor}.
-     */
-    public final MethodSideEffectDetailDescriptor methodSideEffect()
-    {
-        return methodSideEffect;
-    }
-
-    /**
-     * @return Method concern that owns this {@code InjectedMethodDetailDescriptor}.
-     */
-    public final MethodConcernDetailDescriptor methodConcern()
-    {
-        return methodConcern;
-    }
-
-    final void setActivator( ActivatorDetailDescriptor descriptor )
-    {
-        validateNotNull( "ActivatorDetailDescriptor", descriptor );
-        activator = descriptor;
-    }
-
-    final void setObject( ObjectDetailDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "ObjectDetailDescriptor", descriptor );
-        object = descriptor;
-    }
-
-    final void setMixin( MixinDetailDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "MixinDetailDescriptor", descriptor );
-        mixin = descriptor;
-    }
-
-    final void setInjectedParameter( InjectedParametersDetailDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "InjectedParametersDetailDescriptor", descriptor );
-
-        descriptor.setMethod( this );
-        parameters = descriptor;
-    }
-
-    final void setMethodSideEffect( MethodSideEffectDetailDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "MethodSideEffectDetailDescriptor", descriptor );
-        methodSideEffect = descriptor;
-    }
-
-    final void setMethodConcern( MethodConcernDetailDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "MethodConcernDetailDescriptor", descriptor );
-        methodConcern = descriptor;
-    }
-
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/InjectedParametersDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/InjectedParametersDetailDescriptor.java
deleted file mode 100644
index 00cdae4..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/InjectedParametersDetailDescriptor.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import org.qi4j.api.composite.InjectedParametersDescriptor;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-public class InjectedParametersDetailDescriptor
-{
-    private final InjectedParametersDescriptor descriptor;
-    private ConstructorDetailDescriptor constructor;
-    private InjectedMethodDetailDescriptor method;
-
-    InjectedParametersDetailDescriptor( InjectedParametersDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        descriptor = aDescriptor;
-    }
-
-    /**
-     * @return Descriptor of this {@code InjectedParametersDetailDescriptor}. Never returns {@code null}.
-     *
-     * @since 0.5
-     */
-    public final InjectedParametersDescriptor descriptor()
-    {
-        return descriptor;
-    }
-
-    /**
-     * @return Constructor that owns this {@code InjectedParametersDetailDescriptor}.
-     *         If {@code null}, this {@code InjectedParametersDetailDescriptor} is owned by a method.
-     *
-     * @see #method()
-     * @since 0.5
-     */
-    public final ConstructorDetailDescriptor constructor()
-    {
-        return constructor;
-    }
-
-    /**
-     * @return Method that owns this {@code InjectedParametersDetailDescriptor}.
-     *         If {@code null}, this {@code InjectedParametersDetailDescriptor} is owned by a constructor.
-     *
-     * @see #constructor() ()
-     * @since 0.5
-     */
-    public final InjectedMethodDetailDescriptor method()
-    {
-        return method;
-    }
-
-    final void setConstructor( ConstructorDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-        constructor = aDescriptor;
-    }
-
-    final void setMethod( InjectedMethodDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-        method = aDescriptor;
-    }
-}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/LayerDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/LayerDetailDescriptor.java
deleted file mode 100644
index 8842de6..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/LayerDetailDescriptor.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2014-2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.qi4j.api.structure.LayerDescriptor;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-/**
- * Layer Detail Descriptor.
- * <p>
- * Visitable hierarchy with Activators and Modules children.
- */
-public final class LayerDetailDescriptor
-    implements ActivateeDetailDescriptor, VisitableHierarchy<Object, Object>
-{
-    private final LayerDescriptor descriptor;
-    private ApplicationDetailDescriptor application;
-    private final List<LayerDetailDescriptor> usedLayers = new LinkedList<>();
-    private final List<ActivatorDetailDescriptor> activators = new LinkedList<>();
-    private final List<ModuleDetailDescriptor> modules = new LinkedList<>();
-
-    LayerDetailDescriptor( LayerDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "LayerDescriptor", descriptor );
-        this.descriptor = descriptor;
-    }
-
-    /**
-     * @return Descriptor of this {@code LayerDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    public final LayerDescriptor descriptor()
-    {
-        return descriptor;
-    }
-
-    /**
-     * @return Used layers of this {@code LayerDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    public final Iterable<LayerDetailDescriptor> usedLayers()
-    {
-        return usedLayers;
-    }
-
-    /**
-     * @return Layers that used this layer.
-     */
-    public final List<LayerDetailDescriptor> usedBy()
-    {
-        List<LayerDetailDescriptor> usedBy = new LinkedList<>();
-        for( LayerDetailDescriptor layer : application.layers() )
-        {
-            if( layer.usedLayers.contains( this ) )
-            {
-                usedBy.add( layer );
-            }
-        }
-        return usedBy;
-    }
-
-    @Override
-    public Iterable<ActivatorDetailDescriptor> activators()
-    {
-        return activators;
-    }
-
-    /**
-     * @return Modules of this {@code LayerDetailDescriptor}. Never return {@code null}.
-     */
-    public final Iterable<ModuleDetailDescriptor> modules()
-    {
-        return modules;
-    }
-
-    /**
-     * @return Application that owns this {@code LayerDetailDescriptor}. Never return {@code null}.
-     */
-    public final ApplicationDetailDescriptor application()
-    {
-        return application;
-    }
-
-    final void setApplication( ApplicationDetailDescriptor descriptor )
-    {
-        validateNotNull( "ApplicationDetailDescriptor", descriptor );
-        application = descriptor;
-    }
-
-    final void addActivator( ActivatorDetailDescriptor descriptor )
-    {
-        validateNotNull( "ActivatorDetailDescriptor", descriptor );
-        descriptor.setLayer( this );
-        activators.add( descriptor );
-    }
-
-    final void addUsedLayer( LayerDetailDescriptor descriptor )
-    {
-        validateNotNull( "LayerDetailDescriptor", descriptor );
-        usedLayers.add( descriptor );
-    }
-
-    final void addModule( ModuleDetailDescriptor descriptor )
-    {
-        validateNotNull( "ModuleDetailDescriptor", descriptor );
-        descriptor.setLayer( this );
-        modules.add( descriptor );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( ActivatorDetailDescriptor activator : activators )
-            {
-                if( !activator.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-            for( ModuleDetailDescriptor module : modules )
-            {
-                if( !module.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-
-    @Override
-    public final String toString()
-    {
-        return descriptor.name();
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodConcernDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodConcernDetailDescriptor.java
deleted file mode 100644
index 8a2fa2d..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodConcernDetailDescriptor.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.qi4j.api.concern.ConcernDescriptor;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-public final class MethodConcernDetailDescriptor
-    implements InjectableDetailDescriptor
-{
-    private final ConcernDescriptor descriptor;
-    private MethodConcernsDetailDescriptor concerns;
-
-    private final List<ConstructorDetailDescriptor> constructors;
-    private final List<InjectedMethodDetailDescriptor> injectedMethods;
-    private final List<InjectedFieldDetailDescriptor> injectedFields;
-
-    MethodConcernDetailDescriptor( ConcernDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        descriptor = aDescriptor;
-
-        constructors = new LinkedList<>();
-        injectedMethods = new LinkedList<>();
-        injectedFields = new LinkedList<>();
-    }
-
-    /**
-     * @return Descriptor of this {@code MethodConcernDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    public final ConcernDescriptor descriptor()
-    {
-        return descriptor;
-    }
-
-    /**
-     * @return Method concerns that owns this {@code MethodConcernDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    public final MethodConcernsDetailDescriptor method()
-    {
-        return concerns;
-    }
-
-    /**
-     * @return Constructors of this {@code MethodConcernDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    @Override
-    public final Iterable<ConstructorDetailDescriptor> constructors()
-    {
-        return constructors;
-    }
-
-    /**
-     * @return Injected methods of this {@code MethodConcernDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    @Override
-    public final Iterable<InjectedMethodDetailDescriptor> injectedMethods()
-    {
-        return injectedMethods;
-    }
-
-    /**
-     * @return Injected methods of this {@code MethodConcernDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    @Override
-    public final Iterable<InjectedFieldDetailDescriptor> injectedFields()
-    {
-        return injectedFields;
-    }
-
-   @Override
-   public String toString()
-   {
-      return descriptor.modifierClass().getName();
-   }
-
-   final void setConcerns( MethodConcernsDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-        concerns = aDescriptor;
-    }
-
-    final void addConstructor( ConstructorDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        aDescriptor.setMethodConcern( this );
-        constructors.add( aDescriptor );
-    }
-
-    final void addInjectedMethod( InjectedMethodDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        aDescriptor.setMethodConcern( this );
-        injectedMethods.add( aDescriptor );
-    }
-
-    final void addInjectedField( InjectedFieldDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        aDescriptor.setMethodConcern( this );
-        injectedFields.add( aDescriptor );
-    }
-}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodConcernsDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodConcernsDetailDescriptor.java
deleted file mode 100644
index ef4529f..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodConcernsDetailDescriptor.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.qi4j.api.concern.ConcernsDescriptor;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-public final class MethodConcernsDetailDescriptor
-{
-    private final ConcernsDescriptor descriptor;
-    private CompositeMethodDetailDescriptor method;
-    private final List<MethodConcernDetailDescriptor> concerns;
-
-    MethodConcernsDetailDescriptor( ConcernsDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-        descriptor = aDescriptor;
-        concerns = new LinkedList<MethodConcernDetailDescriptor>();
-    }
-
-    /**
-     * @return Descriptor of this {@code MethodConcernsDescriptor}.
-     *
-     * @since 0.5
-     */
-    public final ConcernsDescriptor descriptor()
-    {
-        return descriptor;
-    }
-
-    /**
-     * @return Method that owns this {@code MethodConcernsDescriptor}.
-     *
-     * @since 0.5
-     */
-    public final CompositeMethodDetailDescriptor method()
-    {
-        return method;
-    }
-
-    /**
-     * @return concerns of this {@code MethodConcernDetailDescriptor}.
-     *
-     * @since 0.5
-     */
-    public final Iterable<MethodConcernDetailDescriptor> concerns()
-    {
-        return concerns;
-    }
-
-    final void setMethod( CompositeMethodDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-        method = aDescriptor;
-    }
-
-    final void addConcern( MethodConcernDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-        aDescriptor.setConcerns( this );
-        concerns.add( aDescriptor );
-    }
-}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodConstraintDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodConstraintDetailDescriptor.java
deleted file mode 100644
index 28b4428..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodConstraintDetailDescriptor.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import org.qi4j.api.constraint.ConstraintDescriptor;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-public final class MethodConstraintDetailDescriptor
-{
-    private final ConstraintDescriptor descriptor;
-    private MethodConstraintsDetailDescriptor constraints;
-
-    MethodConstraintDetailDescriptor( ConstraintDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        descriptor = aDescriptor;
-    }
-
-    /**
-     * @return Descriptor of this {@code MethodConstraintDetailDescriptor}. Never returns {@code null}.
-     *
-     * @since 0.5
-     */
-    public final ConstraintDescriptor descriptor()
-    {
-        return descriptor;
-    }
-
-    /**
-     * @return Constraints that own this {@code MethodConstraintDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    public final MethodConstraintsDetailDescriptor constraints()
-    {
-        return constraints;
-    }
-
-   @Override
-   public String toString()
-   {
-      return descriptor.annotation().toString();
-   }
-
-   final void setConstraints( MethodConstraintsDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        constraints = aDescriptor;
-    }
-}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodConstraintsDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodConstraintsDetailDescriptor.java
deleted file mode 100644
index 2ea0cbe..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodConstraintsDetailDescriptor.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.qi4j.api.constraint.ConstraintsDescriptor;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-public final class MethodConstraintsDetailDescriptor
-{
-    private final ConstraintsDescriptor descriptor;
-    private CompositeMethodDetailDescriptor method;
-    private final List<MethodConstraintDetailDescriptor> constraints;
-
-    MethodConstraintsDetailDescriptor( ConstraintsDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        descriptor = aDescriptor;
-        constraints = new LinkedList<MethodConstraintDetailDescriptor>();
-    }
-
-    /**
-     * @return Descriptor of this {@code CompositeMethodConstrainsDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    public final ConstraintsDescriptor descriptor()
-    {
-        return descriptor;
-    }
-
-    /**
-     * @return Constraints of this {@code CompositeMethodConstrainsDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    public final Iterable<MethodConstraintDetailDescriptor> constraints()
-    {
-        return constraints;
-    }
-
-    /**
-     * @return Method that owns this {@code CompositeMethodConstrainsDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    public final CompositeMethodDetailDescriptor method()
-    {
-        return method;
-    }
-
-    final void setMethod( CompositeMethodDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        method = aDescriptor;
-    }
-
-    final void addConstraint( MethodConstraintDetailDescriptor aDescriptor )
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        aDescriptor.setConstraints( this );
-        constraints.add( aDescriptor );
-    }
-}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodSideEffectDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodSideEffectDetailDescriptor.java
deleted file mode 100644
index fd18e3c..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodSideEffectDetailDescriptor.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.qi4j.api.sideeffect.SideEffectDescriptor;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-public final class MethodSideEffectDetailDescriptor
-    implements InjectableDetailDescriptor
-{
-    private final SideEffectDescriptor descriptor;
-    private MethodSideEffectDetailDescriptor sideEffects;
-
-    private final List<ConstructorDetailDescriptor> constructors;
-    private final List<InjectedMethodDetailDescriptor> injectedMethods;
-    private final List<InjectedFieldDetailDescriptor> injectedFields;
-
-    MethodSideEffectDetailDescriptor( SideEffectDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        descriptor = aDescriptor;
-        constructors = new LinkedList<ConstructorDetailDescriptor>();
-        injectedMethods = new LinkedList<InjectedMethodDetailDescriptor>();
-        injectedFields = new LinkedList<InjectedFieldDetailDescriptor>();
-    }
-
-    /**
-     * @return Descriptor of this {@code MethodSideEffectDetailDescriptor}. Never returns {@code null}.
-     *
-     * @since 0.5
-     */
-    public final SideEffectDescriptor descriptor()
-    {
-        return descriptor;
-    }
-
-    /**
-     * @return Method side effects that owns this {@code MethodSideEffectDetailDescriptor}. Never returns {@code null}.
-     *
-     * @since 0.5
-     */
-    public final MethodSideEffectDetailDescriptor sideEffects()
-    {
-        return sideEffects;
-    }
-
-    /**
-     * @return Constructors of this {@code MethodSideEffectDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    @Override
-    public final Iterable<ConstructorDetailDescriptor> constructors()
-    {
-        return constructors;
-    }
-
-    /**
-     * @return Injected methods of this {@code MethodSideEffectDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    @Override
-    public final Iterable<InjectedMethodDetailDescriptor> injectedMethods()
-    {
-        return injectedMethods;
-    }
-
-    /**
-     * @return Injected fields of this {@code MethodSideEffectDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    @Override
-    public final Iterable<InjectedFieldDetailDescriptor> injectedFields()
-    {
-        return injectedFields;
-    }
-
-    final void setSideEffects( MethodSideEffectDetailDescriptor aDescriptor )
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        sideEffects = aDescriptor;
-    }
-
-   @Override
-   public String toString()
-   {
-      return descriptor.modifierClass().getName();
-   }
-
-   final void addConstructor( ConstructorDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        aDescriptor.setMethodSideEffect( this );
-        constructors.add( aDescriptor );
-    }
-
-    final void addInjectedMethod( InjectedMethodDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        aDescriptor.setMethodSideEffect( this );
-        injectedMethods.add( aDescriptor );
-    }
-
-    final void addInjectedField( InjectedFieldDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        aDescriptor.setMethodSideEffect( this );
-        injectedFields.add( aDescriptor );
-    }
-}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodSideEffectsDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodSideEffectsDetailDescriptor.java
deleted file mode 100644
index 14aca65..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MethodSideEffectsDetailDescriptor.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.qi4j.api.sideeffect.SideEffectsDescriptor;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-public final class MethodSideEffectsDetailDescriptor
-{
-    private final SideEffectsDescriptor descriptor;
-    private CompositeMethodDetailDescriptor method;
-    private final List<MethodSideEffectDetailDescriptor> sideEffects;
-
-    MethodSideEffectsDetailDescriptor( SideEffectsDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        descriptor = aDescriptor;
-        sideEffects = new LinkedList<MethodSideEffectDetailDescriptor>();
-    }
-
-    /**
-     * @return Descriptor of this {@code MethodSideEffectsDescriptor}.
-     *
-     * @since 0.5
-     */
-    public final SideEffectsDescriptor descriptor()
-    {
-        return descriptor;
-    }
-
-    /**
-     * @return Composite method that owns this {@code MethodSideEffectsDescriptor}.
-     *
-     * @since 0.5
-     */
-    public final CompositeMethodDetailDescriptor method()
-    {
-        return method;
-    }
-
-    /**
-     * @return Side effects of this {@code MethodSideEffectDetailDescriptor}.
-     *
-     * @since 0.5
-     */
-    public final Iterable<MethodSideEffectDetailDescriptor> sideEffects()
-    {
-        return sideEffects;
-    }
-
-    final void setMethod( CompositeMethodDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-        method = aDescriptor;
-    }
-
-    final void addSideEffect( MethodSideEffectDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        aDescriptor.setSideEffects( aDescriptor );
-        sideEffects.add( aDescriptor );
-    }
-}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MixinDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MixinDetailDescriptor.java
deleted file mode 100644
index 6c7a11f..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/MixinDetailDescriptor.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.qi4j.api.mixin.MixinDescriptor;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-public final class MixinDetailDescriptor
-    implements InjectableDetailDescriptor
-{
-    private final MixinDescriptor descriptor;
-    private CompositeDetailDescriptor composite;
-    private final List<ConstructorDetailDescriptor> constructors;
-    private final List<InjectedMethodDetailDescriptor> injectedMethods;
-    private final List<InjectedFieldDetailDescriptor> injectedFields;
-
-    MixinDetailDescriptor( MixinDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        descriptor = aDescriptor;
-        constructors = new LinkedList<ConstructorDetailDescriptor>();
-        injectedMethods = new LinkedList<InjectedMethodDetailDescriptor>();
-        injectedFields = new LinkedList<InjectedFieldDetailDescriptor>();
-    }
-
-    /**
-     * @return Descriptor of this {@code MixinDetailDescriptor}.
-     *
-     * @since 0.5
-     */
-    public final MixinDescriptor descriptor()
-    {
-        return descriptor;
-    }
-
-    /**
-     * @return Constructors of this {@code MixinDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    @Override
-    public final Iterable<ConstructorDetailDescriptor> constructors()
-    {
-        return constructors;
-    }
-
-    /**
-     * @return Injected methods of this {@code MixinDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    @Override
-    public final Iterable<InjectedMethodDetailDescriptor> injectedMethods()
-    {
-        return injectedMethods;
-    }
-
-    /**
-     * @return Injected fields of this {@code MixinDetailDescriptor}. Never return {@code null}.
-     *
-     * @since 0.5
-     */
-    @Override
-    public final Iterable<InjectedFieldDetailDescriptor> injectedFields()
-    {
-        return injectedFields;
-    }
-
-    /**
-     * @return Composite that owns this {@code MixinDetailDescriptor}. Never return {@code null}.
-     */
-    public final CompositeDetailDescriptor composite()
-    {
-        return composite;
-    }
-
-    final void setComposite( CompositeDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-        composite = aDescriptor;
-    }
-
-    final void addConstructor( ConstructorDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        aDescriptor.setMixin( this );
-        constructors.add( aDescriptor );
-    }
-
-    final void addInjectedMethod( InjectedMethodDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        aDescriptor.setMixin( this );
-        injectedMethods.add( aDescriptor );
-    }
-
-    final void addInjectedField( InjectedFieldDetailDescriptor aDescriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "aDescriptor", aDescriptor );
-
-        aDescriptor.setMixin( this );
-        injectedFields.add( aDescriptor );
-    }
-
-    @Override
-    public String toString()
-    {
-        return descriptor.mixinClass().getSimpleName();
-    }
-}
\ No newline at end of file
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ModuleDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ModuleDetailDescriptor.java
deleted file mode 100644
index 55625f9..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ModuleDetailDescriptor.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2014-2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.qi4j.api.structure.ModuleDescriptor;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-/**
- * Module Detail Descriptor.
- * <p>
- * Visitable hierarchy with Activators and Composites children.
- */
-public final class ModuleDetailDescriptor
-    implements ActivateeDetailDescriptor, VisitableHierarchy<Object, Object>
-{
-    private final ModuleDescriptor descriptor;
-    private LayerDetailDescriptor layer;
-    private final List<ActivatorDetailDescriptor> activators = new LinkedList<>();
-    private final List<ServiceDetailDescriptor> services = new LinkedList<>();
-    private final List<ImportedServiceDetailDescriptor> importedServices = new LinkedList<>();
-    private final List<EntityDetailDescriptor> entities = new LinkedList<>();
-    private final List<TransientDetailDescriptor> transients = new LinkedList<>();
-    private final List<ValueDetailDescriptor> values = new LinkedList<>();
-    private final List<ObjectDetailDescriptor> objects = new LinkedList<>();
-
-    ModuleDetailDescriptor( ModuleDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "ModuleDescriptor", descriptor );
-        this.descriptor = descriptor;
-    }
-
-    /**
-     * @return Descriptor of this {@code ModuleDetailDescriptor}. Never return {@code null}.
-     */
-    public final ModuleDescriptor descriptor()
-    {
-        return descriptor;
-    }
-
-    @Override
-    public Iterable<ActivatorDetailDescriptor> activators()
-    {
-        return activators;
-    }
-
-    /**
-     * @return Services of this {@code ModuleDetailDescriptor}. Never return {@code null}.
-     */
-    public final Iterable<ServiceDetailDescriptor> services()
-    {
-        return services;
-    }
-
-    /**
-     * @return Values of this {@code ModuleDetailDescriptor}. Never return {@code null}.
-     */
-    public final Iterable<ImportedServiceDetailDescriptor> importedServices()
-    {
-        return importedServices;
-    }
-
-    /**
-     * @return Entities of this {@code ModuleDetailDescriptor}. Never return {@code null}.
-     */
-    public final Iterable<EntityDetailDescriptor> entities()
-    {
-        return entities;
-    }
-
-    /**
-     * @return Values of this {@code ModuleDetailDescriptor}. Never return {@code null}.
-     */
-    public final Iterable<ValueDetailDescriptor> values()
-    {
-        return values;
-    }
-
-    /**
-     * @return Transients of this {@code ModuleDetailDescriptor}. Never return {@code null}.
-     */
-    public final Iterable<TransientDetailDescriptor> transients()
-    {
-        return transients;
-    }
-
-    /**
-     * @return Objects of this {@code ModuleDetailDescriptor}. Never return {@code null}.
-     */
-    public final Iterable<ObjectDetailDescriptor> objects()
-    {
-        return objects;
-    }
-
-    /**
-     * @return Layer that own this {@code ModuleDetailDescriptor}. Never return {@code null}.
-     */
-    public final LayerDetailDescriptor layer()
-    {
-        return layer;
-    }
-
-    final void setLayer( LayerDetailDescriptor descriptor )
-        throws IllegalArgumentException
-    {
-        validateNotNull( "LayerDetailDescriptor", descriptor );
-        layer = descriptor;
-    }
-
-    final void addActivator( ActivatorDetailDescriptor descriptor )
-    {
-        validateNotNull( "ActivatorDetailDescriptor", descriptor );
-        descriptor.setModule( this );
-        activators.add( descriptor );
-    }
-
-    final void addService( ServiceDetailDescriptor descriptor )
-    {
-        validateNotNull( "ServiceDetailDescriptor", descriptor );
-        descriptor.setModule( this );
-        services.add( descriptor );
-    }
-
-    final void addImportedService( ImportedServiceDetailDescriptor descriptor )
-    {
-        validateNotNull( "ImportedServiceDetailDescriptor", descriptor );
-        descriptor.setModule( this );
-        importedServices.add( descriptor );
-    }
-
-    final void addEntity( EntityDetailDescriptor descriptor )
-    {
-        validateNotNull( "EntityDetailDescriptor", descriptor );
-        descriptor.setModule( this );
-        entities.add( descriptor );
-    }
-
-    final void addValue( ValueDetailDescriptor descriptor )
-    {
-        validateNotNull( "ValueDetailDescriptor", descriptor );
-        descriptor.setModule( this );
-        values.add( descriptor );
-    }
-
-    final void addTransient( TransientDetailDescriptor descriptor )
-    {
-        validateNotNull( "TransientDetailDescriptor", descriptor );
-        descriptor.setModule( this );
-        transients.add( descriptor );
-    }
-
-    final void addObject( ObjectDetailDescriptor descriptor )
-    {
-        validateNotNull( "ObjectDetailDescriptor", descriptor );
-        descriptor.setModule( this );
-        objects.add( descriptor );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( ActivatorDetailDescriptor activator : activators )
-            {
-                if( !activator.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-            for( ServiceDetailDescriptor service : services )
-            {
-                if( !service.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-            for( ImportedServiceDetailDescriptor importedService : importedServices )
-            {
-                if( !importedService.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-            for( EntityDetailDescriptor entity : entities )
-            {
-                if( !entity.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-            for( ValueDetailDescriptor value : values )
-            {
-                if( !value.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-            for( TransientDetailDescriptor composite : transients )
-            {
-                if( !composite.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-            for( ObjectDetailDescriptor object : objects )
-            {
-                if( !object.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-
-    @Override
-    public final String toString()
-    {
-        return descriptor.name();
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ObjectDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ObjectDetailDescriptor.java
deleted file mode 100644
index 595e8e5..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ObjectDetailDescriptor.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.qi4j.api.object.ObjectDescriptor;
-import org.qi4j.functional.Visitable;
-import org.qi4j.functional.Visitor;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-/**
- * Object Detail Descriptor.
- */
-public final class ObjectDetailDescriptor
-    implements InjectableDetailDescriptor, Visitable<ObjectDetailDescriptor>
-{
-    private final ObjectDescriptor descriptor;
-    private ModuleDetailDescriptor module;
-    private final List<ConstructorDetailDescriptor> constructors = new LinkedList<>();
-    private final List<InjectedMethodDetailDescriptor> injectedMethods = new LinkedList<>();
-    private final List<InjectedFieldDetailDescriptor> injectedFields = new LinkedList<>();
-
-    ObjectDetailDescriptor( ObjectDescriptor descriptor )
-    {
-        validateNotNull( "ObjectDescriptor", descriptor );
-        this.descriptor = descriptor;
-    }
-
-    /**
-     * @return Descriptor of this {@code ObjectDetailDescriptor}. Never return {@code null}.
-     */
-    public final ObjectDescriptor descriptor()
-    {
-        return descriptor;
-    }
-
-    /**
-     * @return Constructors of this {@code ObjectDetailDescriptor}. Never return {@code null}.
-     */
-    @Override
-    public final Iterable<ConstructorDetailDescriptor> constructors()
-    {
-        return constructors;
-    }
-
-    /**
-     * @return Injected methods of this {@code ObjectDetailDescriptor}. Never return {@code null}.
-     */
-    @Override
-    public final Iterable<InjectedMethodDetailDescriptor> injectedMethods()
-    {
-        return injectedMethods;
-    }
-
-    /**
-     * @return Injected fields of this {@code ObjectDetailDescriptor}. Never return {@code null}.
-     */
-    @Override
-    public final Iterable<InjectedFieldDetailDescriptor> injectedFields()
-    {
-        return injectedFields;
-    }
-
-    /**
-     * @return Module that own this {@code ObjectDetailDescriptor}. Never return {@code null}.
-     */
-    public final ModuleDetailDescriptor module()
-    {
-        return module;
-    }
-
-    final void setModule( ModuleDetailDescriptor descriptor )
-    {
-        validateNotNull( "ModuleDetailDescriptor", descriptor );
-        module = descriptor;
-    }
-
-    final void addConstructor( ConstructorDetailDescriptor descriptor )
-    {
-        validateNotNull( "ConstructorDetailDescriptor", descriptor );
-        descriptor.setObject( this );
-        constructors.add( descriptor );
-    }
-
-    final void addInjectedMethod( InjectedMethodDetailDescriptor descriptor )
-    {
-        validateNotNull( "InjectedMethodDetailDescriptor", descriptor );
-        descriptor.setObject( this );
-        injectedMethods.add( descriptor );
-    }
-
-    final void addInjectedField( InjectedFieldDetailDescriptor descriptor )
-    {
-        validateNotNull( "InjectedFieldDetailDescriptor", descriptor );
-        descriptor.setObject( this );
-        injectedFields.add( descriptor );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( Visitor<? super ObjectDetailDescriptor, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        return visitor.visit( this );
-    }
-
-    @Override
-    public String toString()
-    {
-        return descriptor.toString();
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ServiceDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ServiceDetailDescriptor.java
deleted file mode 100644
index 52625d0..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ServiceDetailDescriptor.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2008, Edward Yakop. All Rights Reserved.
- * Copyright (c) 2014-2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.qi4j.api.common.Visibility;
-import org.qi4j.api.service.ServiceDescriptor;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.functional.VisitableHierarchy;
-
-import static org.qi4j.api.util.NullArgumentException.validateNotNull;
-
-/**
- * Service Detail Descriptor.
- * <p>
- * Visitable hierarchy with Activators children.
- */
-public final class ServiceDetailDescriptor
-    extends CompositeDetailDescriptor<ServiceDescriptor>
-    implements ActivateeDetailDescriptor, VisitableHierarchy<Object, Object>
-{
-    private final List<ActivatorDetailDescriptor> activators = new LinkedList<>();
-
-    ServiceDetailDescriptor( ServiceDescriptor descriptor )
-    {
-        super( descriptor );
-    }
-
-    /**
-     * @return layers that can access this service. Never return {@code null}.
-     */
-    public final List<LayerDetailDescriptor> accessibleToLayers()
-    {
-        Visibility visibility = descriptor.visibility();
-        if( visibility == Visibility.module )
-        {
-            return new LinkedList<>();
-        }
-
-        LayerDetailDescriptor layer = module.layer();
-        if( visibility == Visibility.layer )
-        {
-            List<LayerDetailDescriptor> layers = new LinkedList<>();
-            layers.add( layer );
-            return layers;
-        }
-        else
-        {
-            return layer.usedBy();
-        }
-    }
-
-    @Override
-    public Iterable<ActivatorDetailDescriptor> activators()
-    {
-        return activators;
-    }
-
-    final void addActivator( ActivatorDetailDescriptor descriptor )
-    {
-        validateNotNull( "ActivatorDetailDescriptor", descriptor );
-        descriptor.setService( this );
-        activators.add( descriptor );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        if( visitor.visitEnter( this ) )
-        {
-            for( ActivatorDetailDescriptor activator : activators )
-            {
-                if( !activator.accept( visitor ) )
-                {
-                    break;
-                }
-            }
-        }
-        return visitor.visitLeave( this );
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ServiceUsage.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ServiceUsage.java
deleted file mode 100644
index 5500efd..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ServiceUsage.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.tools.model.descriptor;
-
-public final class ServiceUsage
-{
-
-    private final Object ownerDescriptor;
-
-    private final InjectedFieldDetailDescriptor field;
-
-    private final ModuleDetailDescriptor module;
-
-    private final LayerDetailDescriptor layer;
-
-    public ServiceUsage( Object ownerDescriptor, InjectedFieldDetailDescriptor field, ModuleDetailDescriptor module, LayerDetailDescriptor layer )
-    {
-        this.ownerDescriptor = ownerDescriptor;
-        this.field = field;
-        this.module = module;
-        this.layer = layer;
-    }
-
-    public Object ownerDescriptor()
-    {
-        return ownerDescriptor;
-    }
-
-    public InjectedFieldDetailDescriptor field()
-    {
-        return field;
-    }
-
-    public ModuleDetailDescriptor module()
-    {
-        return module;
-    }
-
-    public LayerDetailDescriptor layer()
-    {
-        return layer;
-    }
-
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/TransientDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/TransientDetailDescriptor.java
deleted file mode 100644
index f7a39ed..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/TransientDetailDescriptor.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed 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.qi4j.tools.model.descriptor;
-
-import org.qi4j.api.composite.TransientDescriptor;
-import org.qi4j.functional.Visitable;
-import org.qi4j.functional.Visitor;
-
-/**
- * Transient Detail Descriptor.
- */
-public class TransientDetailDescriptor
-    extends CompositeDetailDescriptor<TransientDescriptor>
-    implements Visitable<TransientDetailDescriptor>
-{
-    TransientDetailDescriptor( TransientDescriptor aDescriptor )
-    {
-        super( aDescriptor );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( Visitor<? super TransientDetailDescriptor, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        return visitor.visit( this );
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ValueDetailDescriptor.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ValueDetailDescriptor.java
deleted file mode 100644
index b09c987..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/ValueDetailDescriptor.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2009, Tonny Kohar. All Rights Reserved.
- * Copyright (c) 2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.descriptor;
-
-import org.qi4j.api.value.ValueDescriptor;
-import org.qi4j.functional.Visitable;
-import org.qi4j.functional.Visitor;
-
-/**
- * Value Detail Descriptor.
- */
-public class ValueDetailDescriptor
-    extends CompositeDetailDescriptor<ValueDescriptor>
-    implements Visitable<ValueDetailDescriptor>
-{
-    ValueDetailDescriptor( ValueDescriptor aDescriptor )
-    {
-        super( aDescriptor );
-    }
-
-    @Override
-    public <ThrowableType extends Throwable> boolean accept( Visitor<? super ValueDetailDescriptor, ThrowableType> visitor )
-        throws ThrowableType
-    {
-        return visitor.visit( this );
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/package.html b/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/package.html
deleted file mode 100644
index 4ece360..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/descriptor/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Detailled Application Model Descriptors.</h2>
-    </body>
-</html>
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/APIFinder.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/util/APIFinder.java
deleted file mode 100644
index 7ac73f9..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/APIFinder.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*  Copyright 2009 Tonny Kohar.
-*
-* Licensed 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.qi4j.tools.model.util;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.tools.model.descriptor.LayerDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ModuleDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ServiceDetailDescriptor;
-
-/**
- * API would be defined as "All service interfaces which are visible for layer
- * or application"
- */
-class APIFinder
-{
-
-    public List<ServiceDetailDescriptor> findModuleAPI( ModuleDetailDescriptor descriptor )
-    {
-        ArrayList<ServiceDetailDescriptor> list = new ArrayList<ServiceDetailDescriptor>();
-
-        for( ServiceDetailDescriptor serviceDetailDescriptor : descriptor.services() )
-        {
-            list.add( serviceDetailDescriptor );
-        }
-
-        return list;
-    }
-
-    public List<ServiceDetailDescriptor> findLayerAPI( LayerDetailDescriptor descriptor )
-    {
-        ArrayList<ServiceDetailDescriptor> list = new ArrayList<ServiceDetailDescriptor>();
-
-        for( ModuleDetailDescriptor moduleDetailDescriptor : descriptor.modules() )
-        {
-            list.addAll( findModuleAPI( moduleDetailDescriptor ) );
-        }
-
-        return list;
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/DescriptorNameComparator.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/util/DescriptorNameComparator.java
deleted file mode 100644
index a309711..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/DescriptorNameComparator.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*  Copyright 2009 Tonny Kohar.
-*
-* Licensed 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.qi4j.tools.model.util;
-
-import java.util.Comparator;
-
-/**
- * DescriptorName comparator.
- * Implementation is using toString() for comparing
- * @param <T> Parameterized descriptor type
- */
-public class DescriptorNameComparator<T>
-    implements Comparator<T>
-{
-    @Override
-    public int compare( T o1, T o2 )
-    {
-        return o1.toString().compareTo( o2.toString() );
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/DescriptorUtilities.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/util/DescriptorUtilities.java
deleted file mode 100644
index fb44a60..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/DescriptorUtilities.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*  Copyright 2009 Tonny Kohar.
-*
-* Licensed 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.qi4j.tools.model.util;
-
-import java.util.List;
-import org.qi4j.tools.model.descriptor.CompositeDetailDescriptor;
-import org.qi4j.tools.model.descriptor.CompositeMethodDetailDescriptor;
-import org.qi4j.tools.model.descriptor.LayerDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ModuleDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ServiceDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ServiceUsage;
-
-/**
- * Collection of Desciptor Utilities
- */
-public class DescriptorUtilities
-{
-    private DescriptorUtilities()
-    {
-        throw new Error( "This is a utility class for static methods" );
-    }
-
-    /**
-     * Return Descriptor Detail
-     *
-     * @param descriptor ServiceDetailDescriptor
-     *
-     * @return list of Descritpor Detail (never return null)
-     */
-    public static List<CompositeMethodDetailDescriptor> findMethod( CompositeDetailDescriptor descriptor )
-    {
-        return new MethodFinder().findMethod( descriptor );
-    }
-
-    /**
-     * Return Descriptor Detail
-     *
-     * @param descriptor ServiceDetailDescriptor
-     *
-     * @return list of Descritpor Detail (never return null)
-     */
-    public static List<CompositeMethodDetailDescriptor> findState( CompositeDetailDescriptor descriptor )
-    {
-        return new StateFinder().findState( descriptor );
-    }
-
-    /**
-     * Return Descriptor Detail
-     *
-     * @param descriptor ServiceDetailDescriptor
-     *
-     * @return Descritpor Detail or null
-     */
-    public static Object findServiceConfiguration( ServiceDetailDescriptor descriptor )
-    {
-        return new ServiceConfigurationFinder().findConfigurationDescriptor( descriptor );
-    }
-
-    /**
-     * Return list of Descriptor Detail for particular Service Usage
-     *
-     * @param descriptor ServiceDetailDescriptor
-     *
-     * @return list of service usage (never return null)
-     */
-    public static List<ServiceUsage> findServiceUsage( ServiceDetailDescriptor descriptor )
-    {
-        return new ServiceUsageFinder().findServiceUsage( descriptor );
-    }
-
-    /**
-     * Return list of Descriptor Detail for All service interfaces which are visible for the module
-     *
-     * @param descriptor ModuleDetailDescriptor
-     *
-     * @return list of ServiceDetailDescriptor (never return null)
-     */
-    public static List<ServiceDetailDescriptor> findModuleAPI( ModuleDetailDescriptor descriptor )
-    {
-        return new APIFinder().findModuleAPI( descriptor );
-    }
-
-    /**
-     * Return list of Descriptor Detail for All service interfaces which are visible for the layer
-     *
-     * @param descriptor ModuleDetailDescriptor
-     *
-     * @return list of ServiceDetailDescriptor (never return null)
-     */
-    public static List<ServiceDetailDescriptor> findLayerAPI( LayerDetailDescriptor descriptor )
-    {
-        return new APIFinder().findLayerAPI( descriptor );
-    }
-
-    /**
-     * Return list of Descriptor Detail for all service dependencies which
-     * are not satisfied from within the module
-     *
-     * @param descriptor ModuleDetailDescriptor
-     *
-     * @return list of ServiceDetailDescriptor (never return null)
-     */
-    public static List<ServiceDetailDescriptor> findModule( ModuleDetailDescriptor descriptor )
-    {
-        return new SPIFinder().findModule( descriptor );
-    }
-
-    /**
-     * Return list of Descriptor Detail for all service dependencies which
-     * are not satisfied from within the layer
-     *
-     * @param descriptor ModuleDetailDescriptor
-     *
-     * @return list of ServiceDetailDescriptor (never return null)
-     */
-    public static List<ServiceDetailDescriptor> findLayerSPI( LayerDetailDescriptor descriptor )
-    {
-        return new SPIFinder().findLayerSPI( descriptor );
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/MethodFinder.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/util/MethodFinder.java
deleted file mode 100644
index 2a844a1..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/MethodFinder.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*  Copyright 2009 Tonny Kohar.
- *
- * Licensed 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.qi4j.tools.model.util;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.composite.CompositeDescriptor;
-import org.qi4j.api.property.Property;
-import org.qi4j.tools.model.descriptor.CompositeDetailDescriptor;
-import org.qi4j.tools.model.descriptor.CompositeMethodDetailDescriptor;
-
-public class MethodFinder
-{
-    public List<CompositeMethodDetailDescriptor> findMethod( CompositeDetailDescriptor<?> descriptor )
-    {
-        return findMethod( descriptor.methods() );
-    }
-
-    /**
-     * The Methods tab should show all the methods of all Mixins (private and public separated)
-     * that don't return one of Property, Association or ManyAssociation.
-     *
-     * "private" and "public" refers to if the interface they are declared in is extended by the Composite.
-     * If yes, then it is a public method, meaning, clients can call it.
-     * If no, then it is a private mixin type, and can only be used internally through @This injections.
-     */
-    private List<CompositeMethodDetailDescriptor> findMethod( Iterable<CompositeMethodDetailDescriptor> iter )
-    {
-        List<CompositeMethodDetailDescriptor> publicList = new ArrayList<>();
-        List<CompositeMethodDetailDescriptor> privateList = new ArrayList<>();
-
-        for( CompositeMethodDetailDescriptor descriptor : iter )
-        {
-            CompositeDescriptor compositeDescriptor = descriptor.composite().descriptor();
-            Iterable<Class<?>> compositeType = compositeDescriptor.types();
-            Class<?> mixinMethodClass = descriptor.descriptor().method().getDeclaringClass();
-            for( Class<?> compositeClass : compositeType )
-            {
-                if( mixinMethodClass.isAssignableFrom( compositeClass ) )
-                {
-                    publicList.add( descriptor );
-                }
-                else
-                {
-                    privateList.add( descriptor );
-                }
-            }
-        }
-
-        // combine into one list, with public listed first then private
-        publicList.addAll( privateList );
-
-        // filter Property, Association, ManyAssociation and NamedAssociation
-        doFilter( publicList );
-
-        return publicList;
-    }
-
-    /**
-     * Do the filter for method return type (Property, Association, ManyAssociation, NamedAssociation)
-     * by removing the entry from the list.
-     *
-     * @param list list of CompositeMethodDetailDescriptor
-     */
-    private void doFilter( List<CompositeMethodDetailDescriptor> list )
-    {
-        if( list.isEmpty() )
-        {
-            return;
-        }
-
-        Iterator<CompositeMethodDetailDescriptor> iter = list.iterator();
-        while( iter.hasNext() )
-        {
-            CompositeMethodDetailDescriptor descriptor = iter.next();
-            Method method = descriptor.descriptor().method();
-            if( Property.class.isAssignableFrom( method.getReturnType() ) )
-            {
-                iter.remove();
-            }
-            else if( Association.class.isAssignableFrom( method.getReturnType() ) )
-            {
-                iter.remove();
-            }
-            else if( ManyAssociation.class.isAssignableFrom( method.getReturnType() ) )
-            {
-                iter.remove();
-            }
-            else if( NamedAssociation.class.isAssignableFrom( method.getReturnType() ) )
-            {
-                iter.remove();
-            }
-        }
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/SPIFinder.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/util/SPIFinder.java
deleted file mode 100644
index 86adff2..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/SPIFinder.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2009, Tonny Kohar. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.util;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.tools.model.descriptor.ApplicationDetailDescriptor;
-import org.qi4j.tools.model.descriptor.EntityDetailDescriptor;
-import org.qi4j.tools.model.descriptor.InjectedFieldDetailDescriptor;
-import org.qi4j.tools.model.descriptor.LayerDetailDescriptor;
-import org.qi4j.tools.model.descriptor.MixinDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ModuleDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ObjectDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ServiceDetailDescriptor;
-import org.qi4j.tools.model.descriptor.TransientDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ValueDetailDescriptor;
-
-/**
- * SPI would be defined as "All service dependencies which are not satisfied from within the module or Layer".
- */
-class SPIFinder
-{
-    private ApplicationDetailDescriptor appDetailDescriptor;
-
-    public List<ServiceDetailDescriptor> findModule( ModuleDetailDescriptor descriptor )
-    {
-        appDetailDescriptor = descriptor.layer().application();
-
-        ArrayList<ServiceDetailDescriptor> list = new ArrayList<>();
-
-        findInServices( descriptor.services(), list );
-        findInEntities( descriptor.entities(), list );
-        findInValues( descriptor.values(), list );
-        findInTransients( descriptor.transients(), list );
-        findInObjects( descriptor.objects(), list );
-
-        return list;
-    }
-
-    public List<ServiceDetailDescriptor> findLayerSPI( LayerDetailDescriptor descriptor )
-    {
-        List<ServiceDetailDescriptor> list = new ArrayList<>();
-
-        for( ModuleDetailDescriptor moduleDetailDescriptor : descriptor.modules() )
-        {
-            list.addAll( findModule( moduleDetailDescriptor ) );
-        }
-
-        return list;
-    }
-
-    private void findInMixin( Iterable<MixinDetailDescriptor> iter, ArrayList<ServiceDetailDescriptor> list )
-    {
-        for( MixinDetailDescriptor descriptor : iter )
-        {
-            findInInjectedField( descriptor.injectedFields(), list );
-        }
-    }
-
-    private void findInInjectedField( Iterable<InjectedFieldDetailDescriptor> iter,
-                                      ArrayList<ServiceDetailDescriptor> list
-    )
-    {
-//        for( InjectedFieldDetailDescriptor descriptorField : iter )
-//        {
-//            DependencyDescriptor dependencyDescriptor = descriptorField.descriptor().dependency();
-//            Annotation annotation = dependencyDescriptor.injectionAnnotation();
-
-//            Class<? extends Annotation> clazz = annotation.annotationType();
-//            if( Uses.class.equals( clazz ) || Service.class.equals( clazz ) )
-//            {
-//                for( String name : dependencyDescriptor.injectedServices() )
-//                {
-//                    ServiceDetailDescriptor serviceDetailDescriptor = lookupServiceDetailDescriptor( name );
-//                    if( serviceDetailDescriptor != null )
-//                    {
-//                        if( !list.contains( serviceDetailDescriptor ) )
-//                        {
-//                            list.add( serviceDetailDescriptor );
-//                        }
-//                    }
-//                }
-//            }
-//        }
-    }
-
-    private void findInServices( Iterable<ServiceDetailDescriptor> iter, ArrayList<ServiceDetailDescriptor> list )
-    {
-        for( ServiceDetailDescriptor descriptor : iter )
-        {
-            findInMixin( descriptor.mixins(), list );
-        }
-    }
-
-    private void findInEntities( Iterable<EntityDetailDescriptor> iter, ArrayList<ServiceDetailDescriptor> list )
-    {
-        for( EntityDetailDescriptor descriptor : iter )
-        {
-            findInMixin( descriptor.mixins(), list );
-        }
-    }
-
-    private void findInValues( Iterable<ValueDetailDescriptor> iter, ArrayList<ServiceDetailDescriptor> list )
-    {
-        for( ValueDetailDescriptor descriptor : iter )
-        {
-            findInMixin( descriptor.mixins(), list );
-        }
-    }
-
-    private void findInTransients( Iterable<TransientDetailDescriptor> iter, ArrayList<ServiceDetailDescriptor> list )
-    {
-        for( TransientDetailDescriptor descriptor : iter )
-        {
-            findInMixin( descriptor.mixins(), list );
-        }
-    }
-
-    private void findInObjects( Iterable<ObjectDetailDescriptor> iter, ArrayList<ServiceDetailDescriptor> list )
-    {
-        for( ObjectDetailDescriptor descriptor : iter )
-        {
-            findInInjectedField( descriptor.injectedFields(), list );
-        }
-    }
-
-    private ServiceDetailDescriptor lookupServiceDetailDescriptor( String name )
-    {
-        ServiceDetailDescriptor serviceDetailDescriptor = null;
-        for( LayerDetailDescriptor layer : appDetailDescriptor.layers() )
-        {
-            for( ModuleDetailDescriptor module : layer.modules() )
-            {
-                for( ServiceDetailDescriptor service : module.services() )
-                {
-                    if( service.toString().equals( name ) )
-                    {
-                        serviceDetailDescriptor = service;
-                        break;
-                    }
-                }
-                if( serviceDetailDescriptor != null )
-                {
-                    break;
-                }
-            }
-            if( serviceDetailDescriptor != null )
-            {
-                break;
-            }
-        }
-        return serviceDetailDescriptor;
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/ServiceConfigurationFinder.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/util/ServiceConfigurationFinder.java
deleted file mode 100644
index 999ad28..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/ServiceConfigurationFinder.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*  Copyright 2009 Tonny Kohar.
-*
-* Licensed 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.qi4j.tools.model.util;
-
-import org.qi4j.api.composite.ModelDescriptor;
-import org.qi4j.tools.model.descriptor.ApplicationDetailDescriptor;
-import org.qi4j.tools.model.descriptor.CompositeDetailDescriptor;
-import org.qi4j.tools.model.descriptor.EntityDetailDescriptor;
-import org.qi4j.tools.model.descriptor.LayerDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ModuleDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ObjectDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ServiceDetailDescriptor;
-import org.qi4j.tools.model.descriptor.TransientDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ValueDetailDescriptor;
-
-import static org.qi4j.functional.Iterables.first;
-
-class ServiceConfigurationFinder
-{
-    public Object findConfigurationDescriptor( ServiceDetailDescriptor descriptor )
-    {
-        Class<?> configType = descriptor.descriptor().configurationType();
-
-        if( configType == null )
-        {
-            return null;
-        }
-
-        // traverse the appDescritor to find the configurationDescriptor
-        ApplicationDetailDescriptor appDescriptor = descriptor.module().layer().application();
-        Object obj = findConfigurationDescriptor( appDescriptor, configType );
-        if( obj == null )
-        {
-            return null;
-        }
-
-        return obj;
-    }
-
-    private Object findConfigurationDescriptor( ApplicationDetailDescriptor descriptor, Class<?> configType )
-    {
-        Object configDescriptor = null;
-        for( LayerDetailDescriptor childDescriptor : descriptor.layers() )
-        {
-            Object obj = findInModules( childDescriptor.modules(), configType );
-            if( obj != null )
-            {
-                configDescriptor = obj;
-                break;
-            }
-        }
-
-        return configDescriptor;
-    }
-
-    private Object findInModules( Iterable<ModuleDetailDescriptor> iter, Class<?> configType )
-    {
-        Object configDescriptor = null;
-
-        for( ModuleDetailDescriptor descriptor : iter )
-        {
-            Object obj = findInTypes( descriptor.services(), configType );
-            if( obj != null )
-            {
-                configDescriptor = obj;
-                break;
-            }
-
-            obj = findInTypes( descriptor.entities(), configType );
-            if( obj != null )
-            {
-                configDescriptor = obj;
-                break;
-            }
-
-            obj = findInTypes( descriptor.transients(), configType );
-            if( obj != null )
-            {
-                configDescriptor = obj;
-                break;
-            }
-
-            obj = findInTypes( descriptor.values(), configType );
-            if( obj != null )
-            {
-                configDescriptor = obj;
-                break;
-            }
-
-            obj = findInTypes( descriptor.objects(), configType );
-            if( obj != null )
-            {
-                configDescriptor = obj;
-                break;
-            }
-        }
-
-        return configDescriptor;
-    }
-
-    private Object findInTypes( Iterable iter, Class<?> configType )
-    {
-        Object configDescriptor = null;
-
-        for( Object obj : iter )
-        {
-            ModelDescriptor descriptor;
-
-            if( obj instanceof ServiceDetailDescriptor )
-            {
-                descriptor = ( (ServiceDetailDescriptor) obj ).descriptor();
-            }
-            else if( obj instanceof EntityDetailDescriptor )
-            {
-                descriptor = ( (EntityDetailDescriptor) obj ).descriptor();
-            }
-            else if( obj instanceof ValueDetailDescriptor )
-            {
-                descriptor = ( (ValueDetailDescriptor) obj ).descriptor();
-            }
-            else if( obj instanceof ObjectDetailDescriptor )
-            {
-                descriptor = ( (ObjectDetailDescriptor) obj ).descriptor();
-            }
-            else if( obj instanceof TransientDetailDescriptor )
-            {
-                descriptor = ( (TransientDetailDescriptor) obj ).descriptor();
-            }
-            else
-            {
-                descriptor = ( (CompositeDetailDescriptor) obj ).descriptor();
-            }
-
-            if( configType.equals( first( descriptor.types() ) ) )
-            {
-                configDescriptor = obj;
-                break;
-            }
-        }
-
-        return configDescriptor;
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/ServiceUsageFinder.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/util/ServiceUsageFinder.java
deleted file mode 100644
index 3bf2cc0..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/ServiceUsageFinder.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 2009, Tonny Kohar. All Rights Reserved.
- * Copyright (c) 2012-2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model.util;
-
-import java.lang.annotation.Annotation;
-import java.util.ArrayList;
-import java.util.List;
-import org.qi4j.api.composite.DependencyDescriptor;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.Uses;
-import org.qi4j.tools.model.descriptor.ApplicationDetailDescriptor;
-import org.qi4j.tools.model.descriptor.EntityDetailDescriptor;
-import org.qi4j.tools.model.descriptor.InjectedFieldDetailDescriptor;
-import org.qi4j.tools.model.descriptor.LayerDetailDescriptor;
-import org.qi4j.tools.model.descriptor.MixinDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ModuleDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ObjectDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ServiceDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ServiceUsage;
-import org.qi4j.tools.model.descriptor.TransientDetailDescriptor;
-import org.qi4j.tools.model.descriptor.ValueDetailDescriptor;
-
-import static org.qi4j.functional.Iterables.first;
-
-/* package */ class ServiceUsageFinder
-{
-    private ServiceDetailDescriptor descriptor;
-    private ArrayList<ServiceUsage> usages;
-
-    public List<ServiceUsage> findServiceUsage( ServiceDetailDescriptor descriptor )
-    {
-        usages = new ArrayList<>();
-
-        this.descriptor = descriptor;
-
-        // traverse the appDescritor/model to find the usage
-        ApplicationDetailDescriptor appDescriptor = descriptor.module().layer().application();
-        collectUsage( appDescriptor );
-
-        return usages;
-    }
-
-    private void collectUsage( ApplicationDetailDescriptor descriptor )
-    {
-        for( LayerDetailDescriptor childDescriptor : descriptor.layers() )
-        {
-            collectInModules( childDescriptor.modules() );
-        }
-    }
-
-    private void collectInModules( Iterable<ModuleDetailDescriptor> iter )
-    {
-        for( ModuleDetailDescriptor descriptor : iter )
-        {
-            collectInServices( descriptor.services() );
-            collectInEntities( descriptor.entities() );
-            collectInValues( descriptor.values() );
-            collectInTransients( descriptor.transients() );
-            collectInObjects( descriptor.objects() );
-        }
-    }
-
-    private void collectInServices( Iterable<ServiceDetailDescriptor> iter )
-    {
-        for( ServiceDetailDescriptor descriptor : iter )
-        {
-            if( descriptor.equals( this.descriptor ) )
-            {
-                continue;
-            }
-            collectInMixin( descriptor.mixins() );
-        }
-    }
-
-    private void collectInEntities( Iterable<EntityDetailDescriptor> iter )
-    {
-        for( EntityDetailDescriptor descriptor : iter )
-        {
-            collectInMixin( descriptor.mixins() );
-        }
-    }
-
-    private void collectInValues( Iterable<ValueDetailDescriptor> iter )
-    {
-        for( ValueDetailDescriptor descriptor : iter )
-        {
-            collectInMixin( descriptor.mixins() );
-        }
-    }
-
-    private void collectInTransients( Iterable<TransientDetailDescriptor> iter )
-    {
-        for( TransientDetailDescriptor descriptor : iter )
-        {
-            collectInMixin( descriptor.mixins() );
-        }
-    }
-
-    private void collectInObjects( Iterable<ObjectDetailDescriptor> iter )
-    {
-        for( ObjectDetailDescriptor descriptor : iter )
-        {
-            collectInInjectedField( descriptor.injectedFields(), descriptor );
-        }
-    }
-
-    private void collectInMixin( Iterable<MixinDetailDescriptor> iter )
-    {
-        for( MixinDetailDescriptor descriptor : iter )
-        {
-            collectInInjectedField( descriptor.injectedFields(), descriptor );
-        }
-    }
-
-    private void collectInInjectedField( Iterable<InjectedFieldDetailDescriptor> iter, Object ownerDescriptor )
-    {
-        for( InjectedFieldDetailDescriptor descriptorField : iter )
-        {
-            DependencyDescriptor dependencyDescriptor = descriptorField.descriptor().dependency();
-            Annotation annotation = dependencyDescriptor.injectionAnnotation();
-
-            Class<? extends Annotation> clazz = annotation.annotationType();
-            if( Uses.class.equals( clazz ) || Service.class.equals( clazz ) )
-            {
-                boolean used = false;
-                if( dependencyDescriptor.injectionType().equals( first( this.descriptor.descriptor().types() ) ) )
-                {
-                    ServiceUsage usage;
-                    if( ownerDescriptor instanceof MixinDetailDescriptor )
-                    {
-                        MixinDetailDescriptor mixinDescriptor = (MixinDetailDescriptor) ownerDescriptor;
-                        usage = new ServiceUsage( mixinDescriptor.composite(), descriptorField, mixinDescriptor.composite().module(), mixinDescriptor.composite().module().layer() );
-                    }
-                    else
-                    {
-                        // assume ObjectDetailDescriptor
-                        ObjectDetailDescriptor objectDescriptor = (ObjectDetailDescriptor) ownerDescriptor;
-                        usage = new ServiceUsage( objectDescriptor, descriptorField, objectDescriptor.module(), objectDescriptor.module().layer() );
-                    }
-                    usages.add( usage );
-                }
-            }
-        }
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/StateFinder.java b/tools/model-detail/src/main/java/org/qi4j/tools/model/util/StateFinder.java
deleted file mode 100644
index e3ac7cb..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/StateFinder.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*  Copyright 2009 Tonny Kohar.
- *
- * Licensed 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.qi4j.tools.model.util;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.association.NamedAssociation;
-import org.qi4j.api.property.Property;
-import org.qi4j.tools.model.descriptor.CompositeDetailDescriptor;
-import org.qi4j.tools.model.descriptor.CompositeMethodDetailDescriptor;
-
-import static org.qi4j.functional.Iterables.first;
-
-public class StateFinder
-{
-    public List<CompositeMethodDetailDescriptor> findState( CompositeDetailDescriptor<?> descriptor )
-    {
-        return findState( descriptor.methods() );
-    }
-
-    private List<CompositeMethodDetailDescriptor> findState( Iterable<CompositeMethodDetailDescriptor> iter )
-    {
-        List<CompositeMethodDetailDescriptor> publicList = new ArrayList<>();
-        List<CompositeMethodDetailDescriptor> privateList = new ArrayList<>();
-
-        for( CompositeMethodDetailDescriptor descriptor : iter )
-        {
-            Class<?> compositeClass = first( descriptor.composite().descriptor().types() );
-            Class<?> mixinMethodClass = descriptor.descriptor().method().getDeclaringClass();
-            if( mixinMethodClass.isAssignableFrom( compositeClass ) )
-            {
-                publicList.add( descriptor );
-            }
-            else
-            {
-                privateList.add( descriptor );
-            }
-        }
-
-        // combine into one list, with public listed first then private
-        publicList.addAll( privateList );
-
-        // filter Property, Association, ManyAssociation and NamedAssociation
-        doFilter( publicList );
-
-        return publicList;
-    }
-
-    /**
-     * Do the filter for method return type (Property, Association, ManyAssociation, NamedAssociation)
-     * by removing the entry from the list if not the above.
-     *
-     * @param list list of CompositeMethodDetailDescriptor
-     */
-    private void doFilter( List<CompositeMethodDetailDescriptor> list )
-    {
-        if( list.isEmpty() )
-        {
-            return;
-        }
-
-        Iterator<CompositeMethodDetailDescriptor> iter = list.iterator();
-        while( iter.hasNext() )
-        {
-            CompositeMethodDetailDescriptor descriptor = iter.next();
-            Method method = descriptor.descriptor().method();
-            if( Property.class.isAssignableFrom( method.getReturnType() )
-                || Association.class.isAssignableFrom( method.getReturnType() )
-                || ManyAssociation.class.isAssignableFrom( method.getReturnType() )
-                || NamedAssociation.class.isAssignableFrom( method.getReturnType() ) )
-            {
-                continue;
-            }
-            iter.remove();
-        }
-    }
-}
diff --git a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/package.html b/tools/model-detail/src/main/java/org/qi4j/tools/model/util/package.html
deleted file mode 100644
index 430bb8f..0000000
--- a/tools/model-detail/src/main/java/org/qi4j/tools/model/util/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Detailled Application Model Utilities.</h2>
-    </body>
-</html>
diff --git a/tools/model-detail/src/test/java/org/apache/polygene/tools/model/VisitableDetailTest.java b/tools/model-detail/src/test/java/org/apache/polygene/tools/model/VisitableDetailTest.java
new file mode 100644
index 0000000..d6af619
--- /dev/null
+++ b/tools/model-detail/src/test/java/org/apache/polygene/tools/model/VisitableDetailTest.java
@@ -0,0 +1,156 @@
+/*
+ *  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.polygene.tools.model;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.apache.polygene.tools.model.descriptor.ServiceDetailDescriptor;
+import org.apache.polygene.tools.model.descriptor.TransientDetailDescriptor;
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.Energy4Java;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.tools.model.descriptor.ApplicationDetailDescriptor;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.apache.polygene.tools.model.descriptor.ApplicationDetailDescriptorBuilder.createApplicationDetailDescriptor;
+
+/**
+ * Visitable Detail Test.
+ */
+public class VisitableDetailTest
+{
+    @Test
+    public void visit()
+        throws AssemblyException, ActivationException
+    {
+        ApplicationDescriptor application = new Energy4Java().newApplicationModel(
+            applicationFactory -> {
+                ApplicationAssembly app = applicationFactory.newApplicationAssembly();
+                app.setName( "UnderTestApp" );
+                app.withActivators( ApplicationActivator.class );
+
+                LayerAssembly layer = app.layer( "LayerName" );
+                layer.withActivators( LayerActivator.class );
+
+                ModuleAssembly module = layer.module( "ModuleName" );
+                module.withActivators( ModuleActivator.class );
+
+                return app;
+            }
+        );
+        ApplicationDetailDescriptor detail = createApplicationDetailDescriptor( application );
+        Visitor visitor = new Visitor();
+        detail.accept( visitor );
+        assertThat(
+            visitor.events,
+            equalTo( Arrays.asList(
+                    // Application
+                    "visitEnter( UnderTestApp )",
+                    "visit( " + ApplicationActivator.class.getName() + " )",
+                    // Layer
+                    "visitEnter( LayerName )",
+                    "visit( " + LayerActivator.class.getName() + " )",
+                    // Module
+                    "visitEnter( ModuleName )",
+                    "visit( " + ModuleActivator.class.getName() + " )",
+                    // Leaving Structure
+                    "visitLeave( ModuleName )",
+                    "visitLeave( LayerName )",
+                    "visitLeave( UnderTestApp )"
+                )
+            )
+        );
+    }
+
+    private static final class Visitor
+        implements HierarchicalVisitor<Object, Object, RuntimeException>
+    {
+        private final List<String> events = new ArrayList<>();
+
+        @Override
+        public boolean visitEnter( Object visited )
+            throws RuntimeException
+        {
+            if( visited instanceof ServiceDetailDescriptor)
+            {
+                return true;
+            }
+            String event = "visitEnter( " + visited + " )";
+            events.add( event );
+            System.out.println( event );
+            return true;
+        }
+
+        @Override
+        public boolean visitLeave( Object visited )
+            throws RuntimeException
+        {
+            if( visited instanceof ServiceDetailDescriptor)
+            {
+                return true;
+            }
+            String event = "visitLeave( " + visited + " )";
+            events.add( event );
+            System.out.println( event );
+            return true;
+        }
+
+        @Override
+        public boolean visit( Object visited )
+            throws RuntimeException
+        {
+            if( visited instanceof TransientDetailDescriptor)
+            {
+                return true;
+            }
+            String event = "visit( " + visited + " )";
+            events.add( event );
+            System.out.println( event );
+            return true;
+        }
+    }
+
+    static class ApplicationActivator
+        extends ActivatorAdapter<Application>
+    {
+    }
+
+    static class LayerActivator
+        extends ActivatorAdapter<Layer>
+    {
+    }
+
+    static class ModuleActivator
+        extends ActivatorAdapter<Module>
+    {
+    }
+}
diff --git a/tools/model-detail/src/test/java/org/qi4j/tools/model/VisitableDetailTest.java b/tools/model-detail/src/test/java/org/qi4j/tools/model/VisitableDetailTest.java
deleted file mode 100644
index b0e5a9b..0000000
--- a/tools/model-detail/src/test/java/org/qi4j/tools/model/VisitableDetailTest.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2015, Paul Merlin. All Rights Reserved.
- *
- * Licensed  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.qi4j.tools.model;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.structure.Application;
-import org.qi4j.api.structure.ApplicationDescriptor;
-import org.qi4j.api.structure.Layer;
-import org.qi4j.api.structure.Module;
-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;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.functional.HierarchicalVisitor;
-import org.qi4j.tools.model.descriptor.ApplicationDetailDescriptor;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.qi4j.tools.model.descriptor.ApplicationDetailDescriptorBuilder.createApplicationDetailDescriptor;
-
-/**
- * Visitable Detail Test.
- */
-public class VisitableDetailTest
-{
-    @Test
-    public void visit()
-        throws AssemblyException, ActivationException
-    {
-        ApplicationDescriptor application = new Energy4Java().newApplicationModel(
-            new ApplicationAssembler()
-            {
-                @Override
-                public ApplicationAssembly assemble( ApplicationAssemblyFactory applicationFactory )
-                throws AssemblyException
-                {
-                    ApplicationAssembly app = applicationFactory.newApplicationAssembly();
-                    app.setName( "UnderTestApp" );
-                    app.withActivators( ApplicationActivator.class );
-
-                    LayerAssembly layer = app.layer( "LayerName" );
-                    layer.withActivators( LayerActivator.class );
-
-                    ModuleAssembly module = layer.module( "ModuleName" );
-                    module.withActivators( ModuleActivator.class );
-
-                    return app;
-                }
-            }
-        );
-        ApplicationDetailDescriptor detail = createApplicationDetailDescriptor( application );
-        Visitor visitor = new Visitor();
-        detail.accept( visitor );
-        assertThat(
-            visitor.events,
-            equalTo( Arrays.asList(
-                    // Application
-                    "visitEnter( UnderTestApp )",
-                    "visit( " + ApplicationActivator.class.getName() + " )",
-                    // Layer
-                    "visitEnter( LayerName )",
-                    "visit( " + LayerActivator.class.getName() + " )",
-                    // Module
-                    "visitEnter( ModuleName )",
-                    "visit( " + ModuleActivator.class.getName() + " )",
-                    // Leaving Structure
-                    "visitLeave( ModuleName )",
-                    "visitLeave( LayerName )",
-                    "visitLeave( UnderTestApp )"
-                )
-            )
-        );
-    }
-
-    private static final class Visitor
-        implements HierarchicalVisitor<Object, Object, RuntimeException>
-    {
-        private final List<String> events = new ArrayList<>();
-
-        @Override
-        public boolean visitEnter( Object visited )
-            throws RuntimeException
-        {
-            String event = "visitEnter( " + visited + " )";
-            events.add( event );
-            System.out.println( event );
-            return true;
-        }
-
-        @Override
-        public boolean visitLeave( Object visited )
-            throws RuntimeException
-        {
-            String event = "visitLeave( " + visited + " )";
-            events.add( event );
-            System.out.println( event );
-            return true;
-        }
-
-        @Override
-        public boolean visit( Object visited )
-            throws RuntimeException
-        {
-            String event = "visit( " + visited + " )";
-            events.add( event );
-            System.out.println( event );
-            return true;
-        }
-    }
-
-    static class ApplicationActivator
-        extends ActivatorAdapter<Application>
-    {
-    }
-
-    static class LayerActivator
-        extends ActivatorAdapter<Layer>
-    {
-    }
-
-    static class ModuleActivator
-        extends ActivatorAdapter<Module>
-    {
-    }
-}
diff --git a/tools/qidea/build.gradle b/tools/qidea/build.gradle
index 559acdb..bcd84ab 100644
--- a/tools/qidea/build.gradle
+++ b/tools/qidea/build.gradle
@@ -1,31 +1,35 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "IntelliJ IDEA Plugin for Apache Zest™ development."
+apply plugin: 'polygene-tool'
 
-jar { manifest { name = "Apache Zest™ IDEA plugin" }}
+description = "IntelliJ IDEA Plugin for Apache Polygene™ development."
+
+jar { manifest { name = "Apache Polygene™ IDEA plugin" }}
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
+  api polygene.core.bootstrap
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
+  runtimeOnly polygene.core.runtime
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/PolygeneApplicationComponent.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/PolygeneApplicationComponent.java
new file mode 100644
index 0000000..42d1104
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/PolygeneApplicationComponent.java
@@ -0,0 +1,133 @@
+/*
+ *  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.polygene.ide.plugin.idea;
+
+import com.intellij.codeInspection.InspectionToolProvider;
+import com.intellij.facet.FacetTypeRegistry;
+import com.intellij.ide.fileTemplates.FileTemplateDescriptor;
+import com.intellij.ide.fileTemplates.FileTemplateGroupDescriptor;
+import com.intellij.ide.fileTemplates.FileTemplateGroupDescriptorFactory;
+import com.intellij.openapi.components.ApplicationComponent;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.apache.polygene.ide.plugin.idea.appliesTo.inspections.AppliesToAnnotationDeclaredCorrectlyInspection;
+import org.apache.polygene.ide.plugin.idea.common.facet.PolygeneFacetType;
+import org.apache.polygene.ide.plugin.idea.concerns.inspections.ConcernsAnnotationDeclaredCorrectlyInspection;
+import org.apache.polygene.ide.plugin.idea.injections.invocation.inspections.InvocationAnnotationDeclaredCorrectlyInspection;
+import org.apache.polygene.ide.plugin.idea.injections.service.inspections.ServiceAnnotationDeclaredCorrectlyInspection;
+import org.apache.polygene.ide.plugin.idea.injections.structure.inspections.StructureAnnotationDeclaredCorrectlyInspection;
+import org.apache.polygene.ide.plugin.idea.mixins.inspections.MixinImplementsMixinType;
+import org.apache.polygene.ide.plugin.idea.mixins.inspections.MixinsAnnotationDeclaredOnMixinType;
+import org.apache.polygene.ide.plugin.idea.sideEffects.inspections.SideEffectsAnnotationDeclaredCorrectlyInspection;
+
+import javax.swing.*;
+
+import static org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle.message;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneApplicationComponent
+    implements ApplicationComponent, InspectionToolProvider, FileTemplateGroupDescriptorFactory
+{
+    @NonNls
+    private static String[] FILE_TEMPLATES = {
+        "GenericConcernOf.java"
+    };
+
+    private final PolygeneFacetType polygeneFacetType;
+
+    public PolygeneApplicationComponent()
+    {
+        polygeneFacetType = new PolygeneFacetType();
+    }
+
+    @NotNull
+    public final String getComponentName()
+    {
+        return "PolygeneApplicationComponent";
+    }
+
+    public final void initComponent()
+    {
+        registerFacet();
+        registerIntentions();
+    }
+
+    private void registerFacet()
+    {
+        FacetTypeRegistry facetTypeRegistry = FacetTypeRegistry.getInstance();
+        facetTypeRegistry.registerFacetType( polygeneFacetType );
+    }
+
+    private void registerIntentions()
+    {
+//        IntentionManager intentionManager = IntentionManager.getInstance();
+//        intentionManager.registerIntentionAndMetaData( new AddConcernOnType(), "intention.category.control.flow" );
+    }
+
+    public final void disposeComponent()
+    {
+        unregisterFacet();
+    }
+
+    private void unregisterFacet()
+    {
+        FacetTypeRegistry facetTypeRegistry = FacetTypeRegistry.getInstance();
+        facetTypeRegistry.unregisterFacetType( polygeneFacetType );
+    }
+
+    public final Class[] getInspectionClasses()
+    {
+        return new Class[]{
+            // Concerns
+            ConcernsAnnotationDeclaredCorrectlyInspection.class,
+            // Mixins
+            MixinImplementsMixinType.class,
+            MixinsAnnotationDeclaredOnMixinType.class,
+            // Side effects
+            SideEffectsAnnotationDeclaredCorrectlyInspection.class,
+            // Injections
+            InvocationAnnotationDeclaredCorrectlyInspection.class,
+            ServiceAnnotationDeclaredCorrectlyInspection.class,
+            StructureAnnotationDeclaredCorrectlyInspection.class,
+            // AppliesTo
+            AppliesToAnnotationDeclaredCorrectlyInspection.class
+        };
+    }
+
+    public final FileTemplateGroupDescriptor getFileTemplatesDescriptor()
+    {
+        FileTemplateGroupDescriptor group = new FileTemplateGroupDescriptor(
+            message( "polygene.file.template.group.title" ), null
+        );
+
+        FileTypeManager fileTypeManager = FileTypeManager.getInstance();
+        for( @NonNls String template : FILE_TEMPLATES )
+        {
+            Icon icon = fileTypeManager.getFileTypeByFileName( template ).getIcon();
+            group.addTemplate( new FileTemplateDescriptor( template, icon ) );
+        }
+
+        return group;
+    }
+
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/appliesTo/common/PolygeneAppliesToConstants.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/appliesTo/common/PolygeneAppliesToConstants.java
new file mode 100644
index 0000000..e50589d
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/appliesTo/common/PolygeneAppliesToConstants.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.ide.plugin.idea.appliesTo.common;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneAppliesToConstants
+{
+    public static final String QUALIFIED_NAME_APPLIES_TO = "org.apache.polygene.api.common.AppliesTo";
+    public static final String QUALIFIED_NAME_APPLIES_TO_FILTER = "org.apache.polygene.api.common.AppliesToFilter";
+
+    private PolygeneAppliesToConstants()
+    {
+    }
+}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/appliesTo/common/PolygeneAppliesToUtil.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/appliesTo/common/PolygeneAppliesToUtil.java
new file mode 100644
index 0000000..fd56b6b
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/appliesTo/common/PolygeneAppliesToUtil.java
@@ -0,0 +1,138 @@
+/*
+ *  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.polygene.ide.plugin.idea.appliesTo.common;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+import java.util.List;
+
+import static com.intellij.codeInsight.AnnotationUtil.findAnnotation;
+import static java.util.Collections.emptyList;
+import static org.apache.polygene.ide.plugin.idea.appliesTo.common.PolygeneAppliesToConstants.QUALIFIED_NAME_APPLIES_TO;
+import static org.apache.polygene.ide.plugin.idea.appliesTo.common.PolygeneAppliesToConstants.QUALIFIED_NAME_APPLIES_TO_FILTER;
+import static org.apache.polygene.ide.plugin.idea.common.psi.PsiAnnotationUtil.getAnnotationDefaultParameterValue;
+import static org.apache.polygene.ide.plugin.idea.common.psi.PsiAnnotationUtil.getClassReference;
+import static org.apache.polygene.ide.plugin.idea.common.psi.PsiClassUtil.getPSIClass;
+import static org.apache.polygene.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneAppliesToUtil
+{
+    /**
+     * @param searchContext Search context.
+     * @return {@code AppliesToFilter} class given the search context. {@code null} if not found.
+     * @since 0.1
+     */
+    @Nullable
+    public static PsiClass getAppliesToFilterClass( @NotNull PsiElement searchContext )
+    {
+        Project project = searchContext.getProject();
+        GlobalSearchScope searchScope = determineSearchScope( searchContext );
+        return getAppliesToFilterClass( project, searchScope );
+    }
+
+    /**
+     * @param project project.
+     * @param scope   search scope.
+     * @return {@code AppliesToFilter} class given {@code project} and {@code scope} parameters.
+     *         Returns {@code null} if not found.
+     * @since 0.1
+     */
+    @Nullable
+    public static PsiClass getAppliesToFilterClass( @NotNull Project project,
+                                                    @Nullable GlobalSearchScope scope )
+    {
+        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( project );
+        return scope == null ? null : psiFacade.findClass( QUALIFIED_NAME_APPLIES_TO_FILTER, scope );
+    }
+
+    /**
+     * @param elementWithinJavaClass element within java class.
+     * @return {@code @AppliesTo} annotation declaration of the class that contains the element.
+     *         Returns {@code null} if not found, or {@code element} is an invalid context.
+     * @since 0.1
+     */
+    @Nullable
+    public static PsiAnnotation getAppliesToAnnotation( @NotNull PsiElement elementWithinJavaClass )
+    {
+        PsiClass psiClass = getPSIClass( elementWithinJavaClass );
+        return findAnnotation( psiClass, QUALIFIED_NAME_APPLIES_TO );
+    }
+
+    /**
+     * @param annotation annotation to process.
+     * @return {@code @AppliesTo} annotation value. Returns {@link Collections#emptyList()} if {@code annotation} is
+     *         {@code null} or annotation is not a {@code @AppliesTo} annotation.
+     * @since 0.1
+     */
+    @NotNull
+    public static List<PsiAnnotationMemberValue> getAppliesToAnnotationValue( @Nullable PsiAnnotation annotation )
+    {
+        if( annotation == null )
+        {
+            return emptyList();
+        }
+
+        String concernsQualifiedName = annotation.getQualifiedName();
+        if( !QUALIFIED_NAME_APPLIES_TO.equals( concernsQualifiedName ) )
+        {
+            return emptyList();
+        }
+
+        return getAnnotationDefaultParameterValue( annotation );
+    }
+
+    /**
+     * @param value annotation member value.
+     * @return Applies to class reference given the {@code value} parameter. Returns {@code null} if it's not a
+     *         class reference.
+     * @since 0.1
+     */
+    @Nullable
+    public static PsiJavaCodeReferenceElement getAppliesToValueClassReference( @NotNull PsiAnnotationMemberValue value )
+    {
+        return getClassReference( value );
+    }
+
+    /**
+     * Returns a {@code boolean} indicator whether the specified {@code psiClass} is implements
+     * {@code AppliesToFilter} class.
+     *
+     * @param psiClass             class to check.
+     * @param appliesToFilterClass {@code AppliesToFilter} class.
+     * @return {@code true} if {@code psiClass} implements {@code AppliesToFilter} class, {@code false} otherwise.
+     * @since 0.1
+     */
+    public static boolean isAnAppliesToFilter( @NotNull PsiClass psiClass, @NotNull PsiClass appliesToFilterClass )
+    {
+        return !psiClass.isInterface() && psiClass.isInheritor( appliesToFilterClass, true );
+    }
+
+    private PolygeneAppliesToUtil()
+    {
+    }
+}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/appliesTo/inspections/AppliesToAnnotationDeclaredCorrectlyInspection.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/appliesTo/inspections/AppliesToAnnotationDeclaredCorrectlyInspection.java
new file mode 100644
index 0000000..b64d762
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/appliesTo/inspections/AppliesToAnnotationDeclaredCorrectlyInspection.java
@@ -0,0 +1,294 @@
+/*
+ *  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.polygene.ide.plugin.idea.appliesTo.inspections;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
+import org.apache.polygene.ide.plugin.idea.common.inspections.AbstractFix;
+import org.apache.polygene.ide.plugin.idea.common.inspections.AbstractInspection;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
+import static org.apache.polygene.ide.plugin.idea.appliesTo.common.PolygeneAppliesToUtil.*;
+import static org.apache.polygene.ide.plugin.idea.common.psi.PsiClassUtil.isImplementsInvocationHandler;
+import static org.apache.polygene.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
+import static org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle.message;
+import static org.apache.polygene.ide.plugin.idea.concerns.common.PolygeneConcernUtil.isAConcern;
+import static org.apache.polygene.ide.plugin.idea.concerns.common.PolygeneConcernUtil.isAGenericConcern;
+import static org.apache.polygene.ide.plugin.idea.sideEffects.common.PolygeneSideEffectUtil.isAGenericSideEffect;
+import static org.apache.polygene.ide.plugin.idea.sideEffects.common.PolygeneSideEffectUtil.isASideEffect;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class AppliesToAnnotationDeclaredCorrectlyInspection extends AbstractInspection
+{
+    @NotNull
+    protected final String resourceBundlePrefixId()
+    {
+        return "applies.to.annotation.declared.correctly";
+    }
+
+    @NotNull
+    public final String getShortName()
+    {
+        return "AppliesToAnnotationDeclaredCorrectlyInspection";
+    }
+
+    @Override
+    public final ProblemDescriptor[] checkClass( @NotNull PsiClass psiClass,
+                                                 @NotNull InspectionManager manager,
+                                                 boolean isOnTheFly )
+    {
+        PsiAnnotation appliesToAnnotation = getAppliesToAnnotation( psiClass );
+        if( appliesToAnnotation == null )
+        {
+            // If class does not have @AppliesTo, ignore
+            return null;
+        }
+
+        String classQualifiedName = psiClass.getQualifiedName();
+        // @AppliesTo can only be declared on class
+        if( psiClass.isInterface() )
+        {
+            // Suggest remove applies to
+            String message = message(
+                "applies.to.annotation.declared.correctly.error.annotation.must.be.declared.on.class"
+            );
+            ProblemDescriptor problemDescriptor = createRemoveAppliesToFilterProblemDescriptor(
+                manager, message, appliesToAnnotation );
+            return new ProblemDescriptor[]{ problemDescriptor };
+        }
+
+        // If @AppliesTo annotation is empty, ignore
+        List<PsiAnnotationMemberValue> appliesToAnnotationValues = getAppliesToAnnotationValue( appliesToAnnotation );
+        if( appliesToAnnotationValues.isEmpty() )
+        {
+            return null;
+        }
+
+        // If AppliesToFilter is not resolved, ignore
+        Project project = psiClass.getProject();
+        GlobalSearchScope searchScope = determineSearchScope( psiClass );
+        PsiClass appliesToFilterClass = getAppliesToFilterClass( project, searchScope );
+        if( appliesToFilterClass == null )
+        {
+            return null;
+        }
+
+        boolean classIsAConcern = isAConcern( psiClass );
+        boolean classIsASideEffect = isASideEffect( psiClass );
+        boolean classIsAGenericConcern = classIsAConcern && isAGenericConcern( psiClass );
+        boolean classIsAGenericSideEffect = classIsASideEffect && isAGenericSideEffect( psiClass );
+        boolean classIsAMixin = !classIsAConcern && !classIsASideEffect;
+        boolean classIsAGenericMixin = classIsAMixin && isImplementsInvocationHandler( psiClass );
+
+        List<ProblemDescriptor> problems = new LinkedList<ProblemDescriptor>();
+        for( PsiAnnotationMemberValue appliesToAnnotationValue : appliesToAnnotationValues )
+        {
+            PsiJavaCodeReferenceElement appliesToValueClassReference =
+                getAppliesToValueClassReference( appliesToAnnotationValue );
+
+            // If it's not a class reference, ignore
+            if( appliesToValueClassReference == null )
+            {
+                continue;
+            }
+
+            // If class reference can't be resolved, ignore
+            PsiClass appliesToValueClass = (PsiClass) appliesToValueClassReference.resolve();
+            if( appliesToValueClass == null )
+            {
+                continue;
+            }
+
+            String appliesToValueQualifiedName = appliesToValueClass.getQualifiedName();
+            boolean appliesToValueIsAnAnnotation = appliesToValueClass.isAnnotationType();
+            boolean appliesToValueIsImplementingAppliesToFilter =
+                appliesToValueClass.isInheritor( appliesToFilterClass, true );
+
+            String message = null;
+            if( appliesToValueIsAnAnnotation && classIsAMixin )
+            {
+                // If Class is a mixin and appliesToValueClass is an annotation
+                message = message(
+                    "applies.to.annotation.declared.correctly.error.value.is.invalid.for.mixin",
+                    appliesToValueQualifiedName
+                );
+            }
+            else if( appliesToValueIsAnAnnotation || appliesToValueIsImplementingAppliesToFilter )
+            {
+                if( classIsAConcern && !classIsAGenericConcern )
+                {
+                    // If psiClass is a concern but not generic concern
+                    message = message(
+                        "applies.to.annotation.declared.correctly.error.value.requires.class.to.extends.GenericConcern",
+                        appliesToValueQualifiedName, classQualifiedName
+                    );
+                }
+                else if( classIsASideEffect && !classIsAGenericSideEffect )
+                {
+                    // If psiClass a side effect but not a generic side effect
+                    message = message(
+                        "applies.to.annotation.declared.correctly.error.value.requires.class.to.extends.GenericSideEffect",
+                        appliesToValueQualifiedName, classQualifiedName
+                    );
+                }
+                else if( appliesToValueIsImplementingAppliesToFilter && !classIsAGenericMixin )
+                {
+                    message = message(
+                        "applies.to.annotation.declared.correctly.error.value.requires.class.to.implements.InvocationHandler",
+                        appliesToValueQualifiedName, classQualifiedName
+                    );
+                }
+            }
+            else if( appliesToValueClass.isInterface() )
+            {
+                if( !psiClass.isInheritor( appliesToValueClass, true ) &&
+                    !( classIsAGenericConcern || classIsAGenericSideEffect ) )
+                {
+                    // If psiClass does not implement that interface and it's not a generic concern or generic side effect
+                    if( classIsAConcern )
+                    {
+                        message = message(
+                            "applies.to.annotation.declared.correctly.error.value.requires.class.to.implement.interface.or.extends.GenericConcern",
+                            appliesToValueQualifiedName, classQualifiedName );
+                    }
+                    else if( classIsASideEffect )
+                    {
+                        message = message(
+                            "applies.to.annotation.declared.correctly.error.value.requires.class.to.implement.interface.or.extends.GenericSideEffect",
+                            appliesToValueQualifiedName, classQualifiedName );
+                    }
+                    else
+                    {
+                        message = message(
+                            "applies.to.annotation.declared.correctly.error.value.requires.class.to.implement.value.interface.or.implements.InvocationHandler",
+                            appliesToValueQualifiedName, classQualifiedName );
+                    }
+                }
+            }
+            else
+            {
+                if( classIsAMixin )
+                {
+                    message = message(
+                        "applies.to.annotation.declared.correctly.error.value.is.invalid.for.mixin",
+                        appliesToValueQualifiedName
+                    );
+                }
+                else
+                {
+                    message = message(
+                        "applies.to.annotation.declared.correctly.error.annotation.value.is.invalid.for.non.mixin",
+                        appliesToValueQualifiedName
+                    );
+                }
+            }
+
+            if( message != null )
+            {
+                ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(
+                    appliesToAnnotationValue,
+                    message,
+                    new RemoveAnnotationValueFix( appliesToAnnotationValue, appliesToValueClassReference ),
+                    GENERIC_ERROR_OR_WARNING );
+                problems.add( problemDescriptor );
+            }
+        }
+
+        return problems.toArray( new ProblemDescriptor[problems.size()] );
+    }
+
+    @NotNull
+    private ProblemDescriptor createRemoveAppliesToFilterProblemDescriptor( @NotNull InspectionManager manager,
+                                                                            @NotNull String problemMessage,
+                                                                            @NotNull PsiAnnotation appliesToAnnotation )
+    {
+        RemoveAppliesToFilterAnnotationFix fix = new RemoveAppliesToFilterAnnotationFix( appliesToAnnotation );
+        return manager.createProblemDescriptor( appliesToAnnotation, problemMessage, fix, GENERIC_ERROR_OR_WARNING );
+    }
+
+    private static class RemoveAppliesToFilterAnnotationFix extends AbstractFix
+    {
+        private final PsiAnnotation appliesToFilterAnnotation;
+
+        private RemoveAppliesToFilterAnnotationFix( @NotNull PsiAnnotation appliesToFilterAnnotation )
+        {
+            super( message( "applies.to.annotation.declared.correctly.fix.remove.annotation" ) );
+            this.appliesToFilterAnnotation = appliesToFilterAnnotation;
+        }
+
+        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
+        {
+            appliesToFilterAnnotation.delete();
+        }
+    }
+
+    private static class RemoveAnnotationValueFix extends AbstractFix
+    {
+        private final PsiAnnotationMemberValue annotationValueToRemove;
+
+        private RemoveAnnotationValueFix( @NotNull PsiAnnotationMemberValue annotationValueToRemove,
+                                          @NotNull PsiJavaCodeReferenceElement appliesToValueClassReference )
+        {
+            super( message( "applies.to.annotation.declared.correctly.fix.remove.class.reference",
+                            appliesToValueClassReference.getQualifiedName() ) );
+            this.annotationValueToRemove = annotationValueToRemove;
+        }
+
+        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
+        {
+            annotationValueToRemove.delete();
+        }
+    }
+
+    private static class ClassImplementInterfaceFix extends AbstractFix
+    {
+        private final PsiClass psiClass;
+        private final PsiClass interfaceToImplement;
+
+        private ClassImplementInterfaceFix( @NotNull PsiClass psiClass,
+                                            @NotNull PsiClass interfaceToImplement )
+        {
+            super( message( "applies.to.annotation.declared.correctly.fix.remove.class.reference",
+                            interfaceToImplement.getQualifiedName() ) );
+            this.psiClass = psiClass;
+            this.interfaceToImplement = interfaceToImplement;
+        }
+
+        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
+        {
+            PsiReferenceList implementList = psiClass.getImplementsList();
+            if( implementList != null )
+            {
+
+                implementList.add( interfaceToImplement );
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/actions/AbstractCreateElementActionBase.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/actions/AbstractCreateElementActionBase.java
new file mode 100644
index 0000000..b47a045
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/actions/AbstractCreateElementActionBase.java
@@ -0,0 +1,153 @@
+/*
+ *  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.polygene.ide.plugin.idea.common.actions;
+
+import com.intellij.CommonBundle;
+import com.intellij.ide.actions.CreateElementActionBase;
+import com.intellij.ide.fileTemplates.FileTemplate;
+import com.intellij.ide.fileTemplates.FileTemplateManager;
+import com.intellij.ide.fileTemplates.JavaTemplateUtil;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtil;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.CodeStyleManager;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Properties;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public abstract class AbstractCreateElementActionBase extends CreateElementActionBase
+{
+    @NonNls
+    private static final String NAME_TEMPLATE_PROPERTY = "NAME";
+
+    protected AbstractCreateElementActionBase( String text, String description )
+    {
+        super( text, description, null );
+    }
+
+    @NotNull
+    protected final PsiElement[] invokeDialog( Project project, PsiDirectory directory )
+    {
+        Module module = ModuleUtil.findModuleForFile( directory.getVirtualFile(), project );
+        if( module == null )
+        {
+            return PsiElement.EMPTY_ARRAY;
+        }
+
+        MyInputValidator validator = doInvokeDialog( project, directory );
+        return validator.getCreatedElements();
+    }
+
+    protected MyInputValidator doInvokeDialog( Project project, PsiDirectory directory )
+    {
+        MyInputValidator validator = new MyInputValidator( project, directory );
+        Messages.showInputDialog( project, getDialogPrompt(), getDialogTitle(), Messages.getQuestionIcon(), "", validator );
+        return validator;
+    }
+
+    /**
+     * @return Dialog prompt.
+     */
+    protected abstract String getDialogPrompt();
+
+    /**
+     * @return Dialog title.
+     */
+    protected abstract String getDialogTitle();
+
+    protected String getErrorTitle()
+    {
+        return CommonBundle.getErrorTitle();
+    }
+
+    protected final void checkBeforeCreate( String newName, PsiDirectory directory )
+        throws IncorrectOperationException
+    {
+        JavaDirectoryService javaDirectoryService = JavaDirectoryService.getInstance();
+        javaDirectoryService.checkCreateClass( directory, newName );
+    }
+
+    protected static PsiClass createClassFromTemplate( @NotNull PsiDirectory directory,
+                                                       @NotNull String className,
+                                                       @NotNull String templateName,
+                                                       @NonNls String... parameters )
+        throws IncorrectOperationException
+    {
+        String classFileName = className + "." + StdFileTypes.JAVA.getDefaultExtension();
+        PsiFile file = createFromTemplateInternal( directory, className, classFileName, templateName, parameters );
+        return ( (PsiJavaFile) file ).getClasses()[ 0 ];
+    }
+
+    protected static PsiFile createFromTemplateInternal( @NotNull PsiDirectory directory,
+                                                         @NotNull String name,
+                                                         @NotNull String fileName,
+                                                         @NotNull String templateName,
+                                                         @NonNls String... parameters )
+        throws IncorrectOperationException
+    {
+        // Load template
+        FileTemplateManager fileTemplateManager = FileTemplateManager.getInstance();
+        FileTemplate template = fileTemplateManager.getJ2eeTemplate( templateName );
+
+        // Process template properties
+        Properties properties = new Properties( fileTemplateManager.getDefaultProperties() );
+        JavaTemplateUtil.setPackageNameAttribute( properties, directory );
+        properties.setProperty( NAME_TEMPLATE_PROPERTY, name );
+
+        // Add parameters
+        for( int i = 0; i < parameters.length; i += 2 )
+        {
+            properties.setProperty( parameters[ i ], parameters[ i + 1 ] );
+        }
+
+        // Create text from template with specified properties
+        String text;
+        try
+        {
+            text = template.getText( properties );
+        }
+        catch( Exception e )
+        {
+            String message = "Unable to load template for " +
+                             fileTemplateManager.internalTemplateToSubject( templateName );
+            throw new RuntimeException( message, e );
+        }
+
+        // Serialized text to file
+        PsiManager psiManager = PsiManager.getInstance( directory.getProject() );
+        PsiFileFactory fileFactory = PsiFileFactory.getInstance( directory.getProject() );
+        PsiFile file = fileFactory.createFileFromText( fileName, text );
+
+        // Reformat the file according to project/default style
+        CodeStyleManager codeStyleManager = CodeStyleManager.getInstance( psiManager );
+        codeStyleManager.reformat( file );
+
+        // Add newly created file to directory
+        return (PsiFile) directory.add( file );
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/actions/PolygeneCreateActionGroup.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/actions/PolygeneCreateActionGroup.java
new file mode 100644
index 0000000..d53e0e1
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/actions/PolygeneCreateActionGroup.java
@@ -0,0 +1,82 @@
+/*
+ *  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.polygene.ide.plugin.idea.common.actions;
+
+import com.intellij.ide.IdeView;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectFileIndex;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.psi.JavaDirectoryService;
+import com.intellij.psi.PsiDirectory;
+
+import static org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle.message;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneCreateActionGroup extends DefaultActionGroup
+{
+    public PolygeneCreateActionGroup()
+    {
+        super( message( "polygene.action.group.title" ), true );
+        getTemplatePresentation().setDescription( message( "polygene.action.group.description" ) );
+    }
+
+    public void update( AnActionEvent e )
+    {
+        Presentation presentation = e.getPresentation();
+        presentation.setVisible( shouldActionGroupVisible( e ) );
+    }
+
+    private boolean shouldActionGroupVisible( AnActionEvent e )
+    {
+        Module module = e.getData( LangDataKeys.MODULE );
+        if( module == null )
+        {
+            return false;
+        }
+
+        // TODO: Enable this once PolygeneFacet can be automatically added/removed
+//        if( PolygeneFacet.getInstance( module ) == null )
+//        {
+//            return false;
+//        }
+
+        // Are we on IDE View and under project source folder?
+        Project project = e.getData( PlatformDataKeys.PROJECT );
+        IdeView view = e.getData( LangDataKeys.IDE_VIEW );
+        if( view != null && project != null )
+        {
+            ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance( project ).getFileIndex();
+            PsiDirectory[] dirs = view.getDirectories();
+            for( PsiDirectory dir : dirs )
+            {
+                if( projectFileIndex.isInSourceContent( dir.getVirtualFile() ) && JavaDirectoryService.getInstance().getPackage( dir ) != null )
+                {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/facet/PolygeneFacet.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/facet/PolygeneFacet.java
new file mode 100644
index 0000000..7342707
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/facet/PolygeneFacet.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.ide.plugin.idea.common.facet;
+
+import com.intellij.facet.Facet;
+import com.intellij.facet.FacetManager;
+import com.intellij.facet.FacetType;
+import com.intellij.openapi.module.Module;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneFacet extends Facet<PolygeneFacetConfiguration>
+{
+    public PolygeneFacet( @NotNull FacetType facetType,
+                      @NotNull Module module,
+                      String name,
+                      @NotNull PolygeneFacetConfiguration configuration,
+                      Facet underlyingFacet
+    )
+    {
+        super( facetType, module, name, configuration, underlyingFacet );
+    }
+
+    @Nullable
+    public static PolygeneFacet getInstance( @NotNull Module module )
+    {
+        return FacetManager.getInstance( module ).getFacetByType( PolygeneFacetType.ID );
+    }
+
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/facet/PolygeneFacetConfiguration.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/facet/PolygeneFacetConfiguration.java
new file mode 100644
index 0000000..6a6f28e
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/facet/PolygeneFacetConfiguration.java
@@ -0,0 +1,56 @@
+/*
+ *  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.polygene.ide.plugin.idea.common.facet;
+
+import com.intellij.facet.FacetConfiguration;
+import com.intellij.facet.ui.FacetEditorContext;
+import com.intellij.facet.ui.FacetEditorTab;
+import com.intellij.facet.ui.FacetValidatorsManager;
+import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.WriteExternalException;
+import org.jdom.Element;
+import org.apache.polygene.ide.plugin.idea.common.facet.ui.PolygeneFacetEditorTab;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneFacetConfiguration
+    implements FacetConfiguration
+{
+    public FacetEditorTab[] createEditorTabs( FacetEditorContext editorContext,
+                                              FacetValidatorsManager validatorsManager )
+    {
+        return new FacetEditorTab[]{
+            new PolygeneFacetEditorTab( editorContext )
+        };
+    }
+
+    public final void readExternal( Element element )
+        throws InvalidDataException
+    {
+        // Do nothing
+    }
+
+    public final void writeExternal( Element element )
+        throws WriteExternalException
+    {
+        // Do nothing
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/facet/PolygeneFacetType.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/facet/PolygeneFacetType.java
new file mode 100644
index 0000000..b45de9f
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/facet/PolygeneFacetType.java
@@ -0,0 +1,122 @@
+/*
+ *  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.polygene.ide.plugin.idea.common.facet;
+
+import com.intellij.facet.Facet;
+import com.intellij.facet.FacetType;
+import com.intellij.facet.FacetTypeId;
+import com.intellij.facet.autodetecting.FacetDetector;
+import com.intellij.facet.autodetecting.FacetDetectorRegistry;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.module.JavaModuleType;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleType;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.vfs.VirtualFileFilter;
+import com.intellij.psi.JavaElementVisitor;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiImportStatement;
+import com.intellij.psi.PsiReferenceExpression;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneFacetType extends FacetType<PolygeneFacet, PolygeneFacetConfiguration>
+{
+    public static final FacetTypeId<PolygeneFacet> ID = new FacetTypeId<PolygeneFacet>();
+
+    public PolygeneFacetType()
+    {
+        super( ID, "PolygeneFacet", "Polygene Facet" );
+    }
+
+    public final PolygeneFacetConfiguration createDefaultConfiguration()
+    {
+        return new PolygeneFacetConfiguration();
+    }
+
+    public final PolygeneFacet createFacet( @NotNull Module module,
+                                        String name,
+                                        @NotNull PolygeneFacetConfiguration configuration,
+                                        @Nullable Facet underlyingFacet )
+    {
+        return new PolygeneFacet( this, module, name, configuration, underlyingFacet );
+    }
+
+    public final boolean isSuitableModuleType( ModuleType moduleType )
+    {
+        return moduleType instanceof JavaModuleType;
+    }
+
+    @Override
+    public final void registerDetectors( FacetDetectorRegistry<PolygeneFacetConfiguration> registry )
+    {
+        registry.registerOnTheFlyDetector(
+            StdFileTypes.JAVA, VirtualFileFilter.ALL, new HasPolygeneImportPackageCondition(),
+            new FacetDetector<PsiFile, PolygeneFacetConfiguration>( "PolygeneFacetDetector" )
+            {
+                @Override
+                public PolygeneFacetConfiguration detectFacet( PsiFile source,
+                                                           Collection<PolygeneFacetConfiguration> existingConfigurations )
+                {
+                    if( !existingConfigurations.isEmpty() )
+                    {
+                        return existingConfigurations.iterator().next();
+                    }
+
+                    return createDefaultConfiguration();
+                }
+            }
+        );
+    }
+
+    private static class HasPolygeneImportPackageCondition
+        implements Condition<PsiFile>
+    {
+        public final boolean value( PsiFile psiFile )
+        {
+            final boolean[] hasPolygeneImportPackage = new boolean[]{ false };
+
+            psiFile.accept( new JavaElementVisitor()
+            {
+                @Override
+                public final void visitImportStatement( PsiImportStatement statement )
+                {
+                    String packageName = statement.getQualifiedName();
+                    if( packageName != null && packageName.startsWith( "org.apache.polygene" ) )
+                    {
+                        hasPolygeneImportPackage[ 0 ] = true;
+                    }
+                }
+
+                @Override
+                public void visitReferenceExpression( PsiReferenceExpression expression )
+                {
+                    // Ignore
+                }
+            } );
+            return hasPolygeneImportPackage[ 0 ];
+        }
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/facet/ui/PolygeneFacetEditorTab.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/facet/ui/PolygeneFacetEditorTab.java
new file mode 100644
index 0000000..dc4b121
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/facet/ui/PolygeneFacetEditorTab.java
@@ -0,0 +1,72 @@
+/*
+ *  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.polygene.ide.plugin.idea.common.facet.ui;
+
+import com.intellij.facet.ui.FacetEditorContext;
+import com.intellij.facet.ui.FacetEditorTab;
+import com.intellij.openapi.options.ConfigurationException;
+import org.jetbrains.annotations.Nls;
+
+import javax.swing.*;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneFacetEditorTab extends FacetEditorTab
+{
+    private final FacetEditorContext editorContext;
+
+    public PolygeneFacetEditorTab( FacetEditorContext aContext )
+    {
+        editorContext = aContext;
+    }
+
+    @Nls
+    public final String getDisplayName()
+    {
+        return "Polygene";
+    }
+
+    public JComponent createComponent()
+    {
+        return new JPanel();
+    }
+
+    public final boolean isModified()
+    {
+        return false;
+    }
+
+    public final void apply()
+        throws ConfigurationException
+    {
+        // From UI to configuration
+    }
+
+    public final void reset()
+    {
+        // From Configuration to UI
+    }
+
+    public final void disposeUIResources()
+    {
+        // Do nothing for now
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/inspections/AbstractFix.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/inspections/AbstractFix.java
new file mode 100644
index 0000000..1369766
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/inspections/AbstractFix.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.ide.plugin.idea.common.inspections;
+
+import com.intellij.codeInspection.LocalQuickFix;
+import org.jetbrains.annotations.NotNull;
+
+import static org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle.message;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public abstract class AbstractFix
+    implements LocalQuickFix
+{
+    private String fixName;
+
+    protected AbstractFix( @NotNull String name )
+    {
+        fixName = name;
+    }
+
+    @NotNull
+    public final String getName()
+    {
+        return fixName;
+    }
+
+    @NotNull
+    public final String getFamilyName()
+    {
+        return message( "polygene.quick.fixes.family.name" );
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/inspections/AbstractInspection.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/inspections/AbstractInspection.java
new file mode 100644
index 0000000..a6d0a38
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/inspections/AbstractInspection.java
@@ -0,0 +1,62 @@
+/*
+ *  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.polygene.ide.plugin.idea.common.inspections;
+
+import com.intellij.codeHighlighting.HighlightDisplayLevel;
+import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+import org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle;
+
+import static com.intellij.codeHighlighting.HighlightDisplayLevel.ERROR;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public abstract class AbstractInspection extends BaseJavaLocalInspectionTool
+{
+    private static final String POLYGENE_IDEA_INSPECTIONS_NAME = "polygene.inspections.name";
+
+    @Nls @NotNull public String getGroupDisplayName()
+    {
+        return PolygeneResourceBundle.message( POLYGENE_IDEA_INSPECTIONS_NAME );
+    }
+
+    @NotNull
+    protected abstract String resourceBundlePrefixId();
+
+    @Nls @NotNull
+    public final String getDisplayName()
+    {
+        return PolygeneResourceBundle.message( resourceBundlePrefixId() + ".name.display" );
+    }
+
+    @NotNull @Override
+    public HighlightDisplayLevel getDefaultLevel()
+    {
+        return ERROR;
+    }
+
+    @Override
+    public boolean isEnabledByDefault()
+    {
+        return true;
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/intentions/AbstractIntention.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/intentions/AbstractIntention.java
new file mode 100644
index 0000000..d50693f
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/intentions/AbstractIntention.java
@@ -0,0 +1,132 @@
+/*
+ *  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.polygene.ide.plugin.idea.common.intentions;
+
+import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
+import com.intellij.openapi.editor.CaretModel;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.ReadonlyStatusHandler;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle.message;
+
+/**
+ * This class is based from {@code com.siyeh.ipp.base.Intention}
+ *
+ * @author edward.yakop@gmail.com
+ */
+public abstract class AbstractIntention extends PsiElementBaseIntentionAction
+{
+    protected abstract boolean isIntentionValidFor( PsiElement element );
+
+    protected abstract String resourceBundlePrefixId();
+
+    /**
+     * Implement this method to process intention.
+     *
+     * @param project The project in which the availability is checked.
+     * @param editor  The editor in which the intention will be invoked.
+     * @param element The element under caret.
+     */
+    protected abstract void processIntention( @NotNull Project project,
+                                              @NotNull Editor editor,
+                                              @NotNull PsiElement element );
+
+    public void invoke( @NotNull Project project, Editor editor, PsiFile file )
+        throws IncorrectOperationException
+    {
+        if( isFileReadOnly( project, file ) )
+        {
+            return;
+        }
+
+        final PsiElement element = findMatchingElement( file, editor );
+        if( element == null )
+        {
+            return;
+        }
+
+        processIntention( project, editor, element );
+    }
+
+    protected static boolean isFileReadOnly( @NotNull Project project, @NotNull PsiFile file )
+    {
+        VirtualFile virtualFile = file.getVirtualFile();
+        ReadonlyStatusHandler readonlyStatusHandler = ReadonlyStatusHandler.getInstance( project );
+        ReadonlyStatusHandler.OperationStatus operationStatus =
+            readonlyStatusHandler.ensureFilesWritable( virtualFile );
+        return operationStatus.hasReadonlyFiles();
+    }
+
+    @Nullable
+    private PsiElement findMatchingElement( @NotNull PsiFile file, @NotNull Editor editor )
+    {
+        CaretModel caretModel = editor.getCaretModel();
+        int position = caretModel.getOffset();
+        PsiElement element = file.findElementAt( position );
+        return findMatchingElement( element );
+    }
+
+    @Nullable
+    private PsiElement findMatchingElement( @Nullable PsiElement element )
+    {
+        while( element != null )
+        {
+            if( isIntentionValidFor( element ) )
+            {
+                return element;
+            }
+            else
+            {
+                element = element.getParent();
+                if( element instanceof PsiFile )
+                {
+                    break;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public boolean isAvailable( @NotNull Project project, Editor editor, @Nullable PsiElement element )
+    {
+        return isIntentionValidFor( element );
+    }
+
+    @NotNull
+    public final String getFamilyName()
+    {
+        return message( resourceBundlePrefixId() + ".family.name" );
+    }
+
+    @NotNull
+    @Override
+    public final String getText()
+    {
+        return message( resourceBundlePrefixId() + ".name" );
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/psi/PsiAnnotationUtil.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/psi/PsiAnnotationUtil.java
new file mode 100644
index 0000000..4840a04
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/psi/PsiAnnotationUtil.java
@@ -0,0 +1,97 @@
+/*
+ *  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.polygene.ide.plugin.idea.common.psi;
+
+import com.intellij.psi.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static java.util.Collections.emptyList;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public class PsiAnnotationUtil
+{
+    @NotNull
+    public static List<PsiAnnotationMemberValue> getAnnotationDefaultParameterValue( @Nullable PsiAnnotation annotation )
+    {
+        if( annotation == null )
+        {
+            return emptyList();
+        }
+
+        List<PsiAnnotationMemberValue> defaultParameterValues = new LinkedList<PsiAnnotationMemberValue>();
+
+        PsiAnnotationParameterList list = annotation.getParameterList();
+        PsiNameValuePair[] attributes = list.getAttributes();
+        for( PsiNameValuePair valuePair : attributes )
+        {
+            String parameterName = valuePair.getName();
+            if( parameterName == null || PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.equals( parameterName ) )
+            {
+                PsiAnnotationMemberValue value = valuePair.getValue();
+                if( value == null )
+                {
+                    continue;
+                }
+
+                if( value instanceof PsiArrayInitializerMemberValue )
+                {
+                    // If It's an array
+                    PsiArrayInitializerMemberValue valueWrapper = (PsiArrayInitializerMemberValue) value;
+                    PsiAnnotationMemberValue[] values = valueWrapper.getInitializers();
+                    for( PsiAnnotationMemberValue psiAnnotationMemberValue : values )
+                    {
+                        if( psiAnnotationMemberValue != null )
+                        {
+                            defaultParameterValues.add( psiAnnotationMemberValue );
+                        }
+                    }
+                }
+                else
+                {
+                    // If there's only one value
+                    defaultParameterValues.add( value );
+                }
+
+                break;
+            }
+        }
+
+        return defaultParameterValues;
+    }
+
+    @Nullable
+    public static PsiJavaCodeReferenceElement getClassReference( @NotNull PsiAnnotationMemberValue value )
+    {
+        if( value instanceof PsiClassObjectAccessExpression )
+        {
+            PsiClassObjectAccessExpression objectAccessExpression = (PsiClassObjectAccessExpression) value;
+            PsiTypeElement typeElement = objectAccessExpression.getOperand();
+            return typeElement.getInnermostComponentReferenceElement();
+        }
+
+        return null;
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/psi/PsiClassUtil.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/psi/PsiClassUtil.java
new file mode 100644
index 0000000..1f7dbb2
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/psi/PsiClassUtil.java
@@ -0,0 +1,134 @@
+/*
+ *  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.polygene.ide.plugin.idea.common.psi;
+
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.InvocationHandler;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.apache.polygene.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PsiClassUtil
+{
+    @Nullable
+    public static PsiClass getPSIClass( @NotNull PsiElement element )
+    {
+        if( element instanceof PsiClass )
+        {
+            return (PsiClass) element;
+        }
+
+        if( element instanceof PsiTypeElement )
+        {
+            PsiTypeElement psiTypeElement = (PsiTypeElement) element;
+            PsiJavaCodeReferenceElement componentRef = psiTypeElement.getInnermostComponentReferenceElement();
+            if( componentRef == null )
+            {
+                return null;
+            }
+
+            return (PsiClass) componentRef.resolve();
+        }
+
+        PsiElement context = element.getContext();
+        if( context instanceof PsiClass )
+        {
+            return (PsiClass) context;
+        }
+
+        return null;
+    }
+
+    @NotNull
+    public static Set<PsiClass> getExtends( @NotNull PsiClass psiClass )
+    {
+        HashSet<PsiClass> extendsClasses = new HashSet<PsiClass>();
+        PsiClassType[] extendsClassTypes = psiClass.getExtendsListTypes();
+        for( PsiClassType extendClassType : extendsClassTypes )
+        {
+            PsiClass extendClass = extendClassType.resolve();
+            if( extendClass != null )
+            {
+                extendsClasses.add( extendClass );
+            }
+        }
+
+        return extendsClasses;
+    }
+
+    /**
+     * Returns all extends of the specified {@code psiClass}.
+     *
+     * @param psiClass class to process.
+     * @return all extends of the specified {@code psiClass}.
+     * @since 0.1
+     */
+    @NotNull
+    public static Set<PsiClass> getExtendsDeep( @NotNull PsiClass psiClass )
+    {
+        HashSet<PsiClass> extendsClasses = new HashSet<PsiClass>();
+        PsiClassType[] extendsClassTypes = psiClass.getExtendsListTypes();
+        for( PsiClassType extendClassType : extendsClassTypes )
+        {
+            PsiClass extendClass = extendClassType.resolve();
+            if( extendClass != null )
+            {
+                extendsClasses.add( extendClass );
+                extendsClasses.addAll( getExtendsDeep( extendClass ) );
+            }
+        }
+
+        return extendsClasses;
+    }
+
+    /**
+     * @param psiClass Psi class to check.
+     * @return {@code true} if psi class implements {@code InvocationHandler}, {@code false} otherwise.
+     * @see InvocationHandler
+     */
+    public static boolean isImplementsInvocationHandler( @NotNull PsiClass psiClass )
+    {
+        if( psiClass.isInterface() )
+        {
+            return false;
+        }
+
+        GlobalSearchScope searchScope = determineSearchScope( psiClass );
+        assert searchScope != null;
+
+        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( psiClass.getProject() );
+        PsiClass invocationHandler = psiFacade.findClass( "java.lang.reflect.InvocationHandler", searchScope );
+        assert invocationHandler != null;
+
+        return psiClass.isInheritor( invocationHandler, true );
+    }
+
+    private PsiClassUtil()
+    {
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/psi/search/GlobalSearchScopeUtil.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/psi/search/GlobalSearchScopeUtil.java
new file mode 100644
index 0000000..4beda1f
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/psi/search/GlobalSearchScopeUtil.java
@@ -0,0 +1,67 @@
+/*
+ *  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.polygene.ide.plugin.idea.common.psi.search;
+
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import static com.intellij.openapi.module.ModuleUtil.findModuleForPsiElement;
+import static org.apache.polygene.ide.plugin.idea.common.vfs.VirtualFileUtil.getVirtualFile;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public class GlobalSearchScopeUtil
+{
+    /**
+     * Determine search scope given a psi element.
+     *
+     * @param psiElement context.
+     * @return Search scope given psi class.
+     * @since 0.1
+     */
+    @Nullable
+    public static GlobalSearchScope determineSearchScope( @NotNull PsiElement psiElement )
+    {
+        VirtualFile classVirtualFile = getVirtualFile( psiElement );
+        if( classVirtualFile == null )
+        {
+            return null;
+        }
+
+        Module module = findModuleForPsiElement( psiElement );
+        if( module == null )
+        {
+            return null;
+        }
+
+        Project project = psiElement.getProject();
+        ProjectRootManager projectRootManager = ProjectRootManager.getInstance( project );
+        boolean includeTestClasses = projectRootManager.getFileIndex().isInTestSourceContent( classVirtualFile );
+        return module.getModuleWithDependenciesAndLibrariesScope( includeTestClasses );
+    }
+
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/resource/PolygeneResourceBundle.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/resource/PolygeneResourceBundle.java
new file mode 100644
index 0000000..c5f29b4
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/resource/PolygeneResourceBundle.java
@@ -0,0 +1,68 @@
+/*
+ *  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.polygene.ide.plugin.idea.common.resource;
+
+import com.intellij.CommonBundle;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.PropertyKey;
+
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.util.ResourceBundle;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneResourceBundle
+{
+
+    @NonNls
+    private static final String RESOURCE_BUNDLE_NAME = "org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle";
+
+    private static Reference<ResourceBundle> BUNDLE_REF;
+
+    private PolygeneResourceBundle()
+    {
+    }
+
+    public static String message( @PropertyKey( resourceBundle = RESOURCE_BUNDLE_NAME ) String key,
+                                  Object... params )
+    {
+        ResourceBundle resourceBundle = getBundle();
+        return CommonBundle.message( resourceBundle, key, params );
+    }
+
+    private static ResourceBundle getBundle()
+    {
+        ResourceBundle bundle = null;
+        if( BUNDLE_REF != null )
+        {
+            bundle = BUNDLE_REF.get();
+        }
+
+        if( bundle == null )
+        {
+            bundle = ResourceBundle.getBundle( PolygeneResourceBundle.class.getName() );
+            BUNDLE_REF = new SoftReference<ResourceBundle>( bundle );
+        }
+
+        return bundle;
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/vfs/VirtualFileUtil.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/vfs/VirtualFileUtil.java
new file mode 100644
index 0000000..d5b95b6
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/common/vfs/VirtualFileUtil.java
@@ -0,0 +1,73 @@
+/*
+ *  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.polygene.ide.plugin.idea.common.vfs;
+
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiFileSystemItem;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class VirtualFileUtil
+{
+    /**
+     * @param element element to process.
+     * @return The containing virtual file of the element.
+     * @since 0.1
+     */
+    @Nullable
+    public static VirtualFile getVirtualFile( @NotNull PsiElement element )
+    {
+        if( element instanceof PsiFileSystemItem )
+        {
+            PsiFileSystemItem fileSystemItem = (PsiFileSystemItem) element;
+            return fileSystemItem.getVirtualFile();
+        }
+
+        // If it's not a file system, assume that this is an element within a file
+        PsiFile containingFile = element.getContainingFile();
+        if( containingFile == null )
+        {
+            return null;
+        }
+
+        VirtualFile virtualFile = containingFile.getVirtualFile();
+        if( virtualFile != null )
+        {
+            return virtualFile;
+        }
+
+        PsiFile originalFile = containingFile.getOriginalFile();
+        if( originalFile == null )
+        {
+            return null;
+        }
+
+        return originalFile.getVirtualFile();
+    }
+
+    private VirtualFileUtil()
+    {
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/actions/create/CreateConcernFromMixinTypeOrCompositeAction.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/actions/create/CreateConcernFromMixinTypeOrCompositeAction.java
new file mode 100644
index 0000000..b6abdfb
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/actions/create/CreateConcernFromMixinTypeOrCompositeAction.java
@@ -0,0 +1,62 @@
+/*
+ * 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.polygene.ide.plugin.idea.concerns.actions.create;
+
+import com.intellij.psi.PsiDirectory;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+import org.apache.polygene.ide.plugin.idea.common.actions.AbstractCreateElementActionBase;
+
+/**
+ * @author edward.yakop@gmail.com
+ */
+public class CreateConcernFromMixinTypeOrCompositeAction extends AbstractCreateElementActionBase
+{
+    public CreateConcernFromMixinTypeOrCompositeAction()
+    {
+        super( "TODO", "TODO" );
+    }
+
+    protected String getCommandName()
+    {
+        return "CreateConcernFromMixinTypeOrCompositeAction";
+    }
+
+    protected String getActionName( PsiDirectory directory, String newName )
+    {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    protected String getDialogPrompt()
+    {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    protected String getDialogTitle()
+    {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    @NotNull
+    protected PsiElement[] create( String newName, PsiDirectory directory )
+        throws Exception
+    {
+        return new PsiElement[0];  //To change body of implemented methods use File | Settings | File Templates.
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/actions/create/inPackage/CreateConcernOfInPackageAction.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/actions/create/inPackage/CreateConcernOfInPackageAction.java
new file mode 100644
index 0000000..402df3e
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/actions/create/inPackage/CreateConcernOfInPackageAction.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.polygene.ide.plugin.idea.concerns.actions.create.inPackage;
+
+import com.intellij.ide.actions.CreateInPackageActionBase;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.psi.JavaDirectoryService;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiDirectory;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+
+import static com.intellij.openapi.actionSystem.DataKeys.PROJECT;
+import static com.intellij.openapi.actionSystem.DataKeys.PSI_ELEMENT;
+import static com.intellij.util.Icons.CLASS_ICON;
+import static org.apache.polygene.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
+import static org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle.message;
+import static org.apache.polygene.ide.plugin.idea.concerns.common.PolygeneConcernConstants.TEMPLATE_GENERIC_CONCERN_OF;
+import static org.apache.polygene.ide.plugin.idea.concerns.common.PolygeneConcernUtil.getConcernOfClass;
+
+/**
+ * JAVADOC: Non generic concern
+ *
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public class CreateConcernOfInPackageAction extends CreateInPackageActionBase
+{
+    protected CreateConcernOfInPackageAction()
+    {
+        super( message( "createConcernOfInPackage.menu.action.text" ),
+               message( "createConcernOfInPackage.menu.action.description" ),
+               CLASS_ICON );
+    }
+
+    @Override
+    protected final boolean isAvailable( DataContext dataContext )
+    {
+        boolean isAvailable = super.isAvailable( dataContext );
+        if( !isAvailable )
+        {
+            return false;
+        }
+
+        PsiElement psiElement = PSI_ELEMENT.getData( dataContext );
+        if( psiElement == null )
+        {
+            return false;
+        }
+
+        GlobalSearchScope searchScope = determineSearchScope( psiElement );
+        if( searchScope == null )
+        {
+            return false;
+        }
+
+        Project project = PROJECT.getData( dataContext );
+        PsiClass psiClass = getConcernOfClass( project, searchScope );
+        return psiClass != null;
+    }
+
+    @NotNull
+    protected final PsiElement[] invokeDialog( Project project, PsiDirectory directory )
+    {
+        MyInputValidator validator = new MyInputValidator( project, directory );
+        Messages.showInputDialog( project, message( "createConcernOfInPackage.dlg.prompt" ),
+                                  message( "createConcernOfInPackage.dlg.title" ),
+                                  Messages.getQuestionIcon(), "", validator );
+        return validator.getCreatedElements();
+    }
+
+    protected final String getCommandName()
+    {
+        return message( "createConcernOfInPackage.command.name" );
+    }
+
+    protected final String getErrorTitle()
+    {
+        return message( "createConcernOfInPackage.error.title" );
+    }
+
+    protected final String getActionName( PsiDirectory directory, String newName )
+    {
+        return message( "createConcernOfInPackage.progress.text", newName );
+    }
+
+    protected final void doCheckCreate( final PsiDirectory dir, final String className )
+        throws IncorrectOperationException
+    {
+        JavaDirectoryService javaDirectoryService = JavaDirectoryService.getInstance();
+        javaDirectoryService.checkCreateClass( dir, className );
+    }
+
+    @NotNull
+    protected PsiClass doCreate( final PsiDirectory dir, final String className )
+        throws IncorrectOperationException
+    {
+        JavaDirectoryService javaDirectoryService = JavaDirectoryService.getInstance();
+        return javaDirectoryService.createClass( dir, className, TEMPLATE_GENERIC_CONCERN_OF );
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/common/PolygeneConcernConstants.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/common/PolygeneConcernConstants.java
new file mode 100644
index 0000000..0bbe3a1
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/common/PolygeneConcernConstants.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.ide.plugin.idea.concerns.common;
+
+import org.jetbrains.annotations.NonNls;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneConcernConstants
+{
+    public static final String QUALIFIED_NAME_CONCERNS = "org.apache.polygene.api.concern.Concerns";
+
+    public static final String QUALIFIED_NAME_CONCERN_OF = "org.apache.polygene.api.concern.ConcernOf";
+    public static final String QUALIFIED_NAME_GENERIC_CONCERN = "org.apache.polygene.api.concern.GenericConcern";
+
+    @NonNls
+    public static final String TEMPLATE_GENERIC_CONCERN_OF = "GenericConcernOf.java";
+
+    private PolygeneConcernConstants()
+    {
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/common/PolygeneConcernUtil.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/common/PolygeneConcernUtil.java
new file mode 100644
index 0000000..4499143
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/common/PolygeneConcernUtil.java
@@ -0,0 +1,228 @@
+/*
+ *  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.polygene.ide.plugin.idea.concerns.common;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+import static com.intellij.codeInsight.AnnotationUtil.findAnnotation;
+import static java.util.Collections.emptyList;
+import static org.apache.polygene.ide.plugin.idea.common.psi.PsiAnnotationUtil.getAnnotationDefaultParameterValue;
+import static org.apache.polygene.ide.plugin.idea.common.psi.PsiAnnotationUtil.getClassReference;
+import static org.apache.polygene.ide.plugin.idea.common.psi.PsiClassUtil.getPSIClass;
+import static org.apache.polygene.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
+import static org.apache.polygene.ide.plugin.idea.concerns.common.PolygeneConcernConstants.*;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneConcernUtil
+{
+
+
+    /**
+     * @param searchContext Search context.
+     * @return {@code GenericConcern} psi class if found, {@code null} otherwise.
+     * @since 0.1
+     */
+    @Nullable
+    public static PsiClass getGenericConcernClass( @NotNull PsiElement searchContext )
+    {
+        Project project = searchContext.getProject();
+        GlobalSearchScope searchScope = determineSearchScope( searchContext );
+        return getGenericConcernClass( project, searchScope );
+    }
+
+    /**
+     * @param project project.
+     * @param scope   search scope.
+     * @return {@code GenericConcern} psi class if found, {@code null} otherwise.
+     * @since 0.1
+     */
+    @Nullable
+    public static PsiClass getGenericConcernClass( @NotNull Project project,
+                                                   @Nullable GlobalSearchScope scope )
+    {
+        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( project );
+        return scope != null ? psiFacade.findClass( QUALIFIED_NAME_GENERIC_CONCERN, scope ) : null;
+    }
+
+    @Nullable
+    public static PsiClass getConcernOfClass( @NotNull PsiElement searchContext )
+    {
+        Project project = searchContext.getProject();
+        GlobalSearchScope searchScope = determineSearchScope( searchContext );
+        return getConcernOfClass( project, searchScope );
+    }
+
+    @Nullable
+    public static PsiClass getConcernOfClass( @NotNull Project project,
+                                              @Nullable GlobalSearchScope scope )
+    {
+        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( project );
+        return scope != null ? psiFacade.findClass( QUALIFIED_NAME_CONCERN_OF, scope ) : null;
+    }
+
+    @Nullable
+    public static PsiAnnotation getConcernsAnnotation( @NotNull PsiElement element )
+    {
+        PsiClass psiClass = getPSIClass( element );
+        return findAnnotation( psiClass, QUALIFIED_NAME_CONCERNS );
+    }
+
+    @NotNull
+    public static PsiAnnotation addOrReplaceConcernAnnotation( @NotNull PsiModifierListOwner modifierListOwner,
+                                                               @NotNull PsiClass concernClassToAdd )
+    {
+        Project project = modifierListOwner.getProject();
+        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( project );
+        PsiElementFactory factory = psiFacade.getElementFactory();
+        PsiAnnotation existingConcernsAnnotation = findAnnotation( modifierListOwner, QUALIFIED_NAME_CONCERNS );
+
+        boolean isReplace = false;
+        PsiAnnotation newConcernsAnnotation;
+        if( existingConcernsAnnotation != null )
+        {
+            // Check duplicate
+            List<PsiAnnotationMemberValue> concernsValues = getConcernsAnnotationValue( existingConcernsAnnotation );
+            for( PsiAnnotationMemberValue concernValue : concernsValues )
+            {
+                PsiJavaCodeReferenceElement concernClassReference = getConcernClassReference( concernValue );
+                if( concernClassReference == null )
+                {
+                    continue;
+                }
+
+                PsiElement concernClass = concernClassReference.resolve();
+                if( concernClassToAdd.equals( concernClass ) )
+                {
+                    return existingConcernsAnnotation;
+                }
+            }
+
+            isReplace = true;
+        }
+
+        String concernAnnotationText = createConcernAnnotationText( existingConcernsAnnotation, concernClassToAdd );
+        newConcernsAnnotation =
+            factory.createAnnotationFromText( concernAnnotationText, modifierListOwner );
+
+        if( isReplace )
+        {
+            // Replace @Concerns instead
+            existingConcernsAnnotation.replace( newConcernsAnnotation );
+        }
+        else
+        {
+            // @Concerns doesn't exists, add it as first child
+            PsiModifierList modifierList = modifierListOwner.getModifierList();
+            modifierList.addBefore( newConcernsAnnotation, modifierList.getFirstChild() );
+        }
+
+        // Shorten all class references if possible
+        JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance( project );
+        codeStyleManager.shortenClassReferences( newConcernsAnnotation );
+
+        return newConcernsAnnotation;
+    }
+
+    @NotNull
+    private static String createConcernAnnotationText( @Nullable PsiAnnotation concernAnnotationBase,
+                                                       @NotNull PsiClass concernClassToAdd )
+    {
+        StringBuilder annotationTextBuilder = new StringBuilder();
+        annotationTextBuilder.append( "@" ).append( QUALIFIED_NAME_CONCERNS ).append( "( {" );
+        List<PsiAnnotationMemberValue> concernsAnnotationValue = getConcernsAnnotationValue( concernAnnotationBase );
+        for( PsiAnnotationMemberValue concernValue : concernsAnnotationValue )
+        {
+            annotationTextBuilder.append( concernValue.getText() ).append( ", " );
+        }
+        annotationTextBuilder.append( concernClassToAdd.getQualifiedName() ).append( ".class" );
+        annotationTextBuilder.append( "} )" );
+        return annotationTextBuilder.toString();
+    }
+
+    @NotNull
+    public static List<PsiAnnotationMemberValue> getConcernsAnnotationValue( @Nullable PsiAnnotation concernsAnnotation )
+    {
+        if( concernsAnnotation == null )
+        {
+            return emptyList();
+        }
+
+        String concernsQualifiedName = concernsAnnotation.getQualifiedName();
+        if( !QUALIFIED_NAME_CONCERNS.equals( concernsQualifiedName ) )
+        {
+            return emptyList();
+        }
+
+        return getAnnotationDefaultParameterValue( concernsAnnotation );
+    }
+
+    @Nullable
+    public static PsiJavaCodeReferenceElement getConcernClassReference( @NotNull PsiAnnotationMemberValue value )
+    {
+        return getClassReference( value );
+    }
+
+    /**
+     * @param psiClass psi class to check.
+     * @return {@code true} if {@code psiClass} extends {@code ConcernOf}, {@code false} if {@code psiClass} does
+     *         not extends {@code ConcernOf} or {@code ConcernOf} is not found.
+     * @since 0.1
+     */
+    public static boolean isAConcern( @NotNull PsiClass psiClass )
+    {
+        if( psiClass.isInterface() )
+        {
+            return false;
+        }
+
+        PsiClass concernOfClass = getConcernOfClass( psiClass );
+        return concernOfClass != null && psiClass.isInheritor( concernOfClass, true );
+    }
+
+    /**
+     * @param psiClass psi class to check.
+     * @return {@code true} if {@code psiClass} extends {@code GenericConcern}, {@code false} if {@code psiClass} does
+     *         not extends {@code GenericConcern} or {@code GenericConcern} is not found.
+     * @since 0.1
+     */
+    public static boolean isAGenericConcern( @NotNull PsiClass psiClass )
+    {
+        if( psiClass.isInterface() )
+        {
+            return false;
+        }
+
+        PsiClass genericConcern = getGenericConcernClass( psiClass );
+        return genericConcern != null && psiClass.isInheritor( genericConcern, true );
+    }
+
+    private PolygeneConcernUtil()
+    {
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/inspections/ConcernsAnnotationDeclaredCorrectlyInspection.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/inspections/ConcernsAnnotationDeclaredCorrectlyInspection.java
new file mode 100644
index 0000000..4549efe
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/inspections/ConcernsAnnotationDeclaredCorrectlyInspection.java
@@ -0,0 +1,175 @@
+/*
+ *  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.polygene.ide.plugin.idea.concerns.inspections;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiAnnotation;
+import com.intellij.psi.PsiAnnotationMemberValue;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiJavaCodeReferenceElement;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
+import org.apache.polygene.ide.plugin.idea.common.inspections.AbstractFix;
+import org.apache.polygene.ide.plugin.idea.common.inspections.AbstractInspection;
+import org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
+import static org.apache.polygene.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
+import static org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle.message;
+import static org.apache.polygene.ide.plugin.idea.concerns.common.PolygeneConcernUtil.*;
+
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class ConcernsAnnotationDeclaredCorrectlyInspection extends AbstractInspection
+{
+    @NotNull
+    protected final String resourceBundlePrefixId()
+    {
+        return "concerns.annotation.declared.correctly";
+    }
+
+    @NotNull
+    public final String getShortName()
+    {
+        return "ConcernsAnnotationDeclaredCorrectlyInspection";
+    }
+
+    @Override
+    public final ProblemDescriptor[] checkClass( @NotNull PsiClass psiClass,
+                                                 @NotNull InspectionManager manager,
+                                                 boolean isOnTheFly )
+    {
+        // If class does not have @Concerns, ignore
+        PsiAnnotation concernsAnnotation = getConcernsAnnotation( psiClass );
+        if( concernsAnnotation == null )
+        {
+            return null;
+        }
+
+        // If @Concerns declared in class, suggest remove @Concerns annotation
+        if( !psiClass.isInterface() )
+        {
+            String message = message( "concerns.annotation.declared.correctly.error.annotation.declared.in.class" );
+            RemoveConcernsAnnotationFix fix = new RemoveConcernsAnnotationFix( concernsAnnotation );
+            ProblemDescriptor problemDescriptor = manager.createProblemDescriptor( concernsAnnotation, message, fix,
+                                                                                   GENERIC_ERROR_OR_WARNING );
+            return new ProblemDescriptor[]{ problemDescriptor };
+        }
+
+        // If @Concerns annotation is empty, ignore
+        List<PsiAnnotationMemberValue> concernsAnnotationValue = getConcernsAnnotationValue( concernsAnnotation );
+        if( concernsAnnotationValue.isEmpty() )
+        {
+            return null;
+        }
+
+        // If ConcernOfClass is not resolved, ignore
+        Project project = psiClass.getProject();
+        GlobalSearchScope searchScope = determineSearchScope( psiClass );
+        PsiClass concernOfClass = getConcernOfClass( project, searchScope );
+        if( concernOfClass == null )
+        {
+            return null;
+        }
+
+        List<ProblemDescriptor> problems = new LinkedList<ProblemDescriptor>();
+        for( PsiAnnotationMemberValue concernClassAnnotationValue : concernsAnnotationValue )
+        {
+            PsiJavaCodeReferenceElement concernClassReference = getConcernClassReference( concernClassAnnotationValue );
+
+            // If it's not a class reference, ignore
+            if( concernClassReference == null )
+            {
+                continue;
+            }
+
+            // If class reference can't be resolved, ignore
+            PsiClass concernClass = (PsiClass) concernClassReference.resolve();
+            if( concernClass == null )
+            {
+                continue;
+            }
+
+            // If concern class does not inherit concern class, suggest remove that reference.
+            if( !concernClass.isInheritor( concernOfClass, true ) )
+            {
+                String message = PolygeneResourceBundle.message(
+                    "concerns.annotation.declared.correctly.error.concern.class.does.not.extend.ConcernOf",
+                    concernClass.getQualifiedName()
+                );
+
+                RemoveInvalidConcernClassReferenceFix fix = new RemoveInvalidConcernClassReferenceFix(
+                    concernClassAnnotationValue, concernClassReference
+                );
+                ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(
+                    concernClassAnnotationValue, message, fix, GENERIC_ERROR_OR_WARNING );
+                problems.add( problemDescriptor );
+            }
+            else
+            {
+                // TODO: Test whether it is a generic concern
+                // TODO: Test whether it is a specific concern
+            }
+        }
+
+        return problems.toArray( new ProblemDescriptor[problems.size()] );
+    }
+
+    private static class RemoveConcernsAnnotationFix extends AbstractFix
+    {
+        private final PsiAnnotation annotationToRemove;
+
+        private RemoveConcernsAnnotationFix( @NotNull PsiAnnotation annotationToRemove )
+        {
+            super( message( "concerns.annotation.declared.correctly.fix.remove.annotation" ) );
+            this.annotationToRemove = annotationToRemove;
+        }
+
+        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
+        {
+            annotationToRemove.delete();
+        }
+    }
+
+    private static class RemoveInvalidConcernClassReferenceFix extends AbstractFix
+    {
+        private final PsiAnnotationMemberValue concernClassAnnotationValue;
+
+        public RemoveInvalidConcernClassReferenceFix( @NotNull PsiAnnotationMemberValue annotationValueToRemove,
+                                                      @NotNull PsiJavaCodeReferenceElement concernClassReference )
+        {
+            super( message( "concerns.annotation.declared.correctly.fix.remove.concern.class.reference",
+                            concernClassReference.getQualifiedName() ) );
+            this.concernClassAnnotationValue = annotationValueToRemove;
+        }
+
+        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
+        {
+            concernClassAnnotationValue.delete();
+        }
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/intentions/add/AddConcernOnType.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/intentions/add/AddConcernOnType.java
new file mode 100644
index 0000000..5dc21bf
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/concerns/intentions/add/AddConcernOnType.java
@@ -0,0 +1,140 @@
+/*
+ *  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.polygene.ide.plugin.idea.concerns.intentions.add;
+
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.Processor;
+import com.intellij.util.Query;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.apache.polygene.ide.plugin.idea.common.intentions.AbstractIntention;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.intellij.psi.search.searches.ClassInheritorsSearch.search;
+import static java.util.Collections.emptyList;
+import static org.apache.polygene.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
+import static org.apache.polygene.ide.plugin.idea.concerns.common.PolygeneConcernUtil.addOrReplaceConcernAnnotation;
+import static org.apache.polygene.ide.plugin.idea.concerns.common.PolygeneConcernUtil.getConcernOfClass;
+
+/**
+ * JAVADOC: This is disabled in PolygeneApplicationComponent.
+ *
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class AddConcernOnType
+    extends AbstractIntention
+{
+    protected boolean isIntentionValidFor( PsiElement element )
+    {
+        if( !( element instanceof PsiClass ) )
+        {
+            return false;
+        }
+
+        // If it's not interface, ignore it
+        PsiClass psiClass = (PsiClass) element;
+        if( !psiClass.isInterface() )
+        {
+            return false;
+        }
+
+        // Is @Concerns accesible within module
+        GlobalSearchScope searchScope = determineSearchScope( psiClass );
+        PsiClass concernOfClass = getConcernOfClass( psiClass.getProject(), searchScope );
+        return concernOfClass != null;
+    }
+
+    protected final String resourceBundlePrefixId()
+    {
+        return "add.concern";
+    }
+
+    @Override
+    public boolean isAvailable( @NotNull Project project, Editor editor, @Nullable PsiElement element )
+    {
+        while( element != null )
+        {
+            if( element instanceof PsiFile ||
+                element instanceof PsiMethod )
+            {
+                break;
+            }
+
+            if( isIntentionValidFor( element ) )
+            {
+                return true;
+            }
+
+            element = element.getParent();
+        }
+
+        return false;
+    }
+
+    @SuppressWarnings( "unchecked" )
+    protected void processIntention( @NotNull Project project, @NotNull Editor editor, @NotNull PsiElement element )
+    {
+        PsiClass psiClass = (PsiClass) element;
+        List<PsiClass> concernCandidates = findConcernsCandidates( psiClass );
+        if( concernCandidates.size() == 1 )
+        {
+            PsiClass concernCandidate = concernCandidates.get( 0 );
+            addOrReplaceConcernAnnotation( psiClass, concernCandidate );
+        }
+    }
+
+    private static List<PsiClass> findConcernsCandidates( final @NotNull PsiClass classToCheck )
+    {
+        GlobalSearchScope searchScope = determineSearchScope( classToCheck );
+        PsiClass concernOfClass = getConcernOfClass( classToCheck.getProject(), searchScope );
+        if( concernOfClass == null )
+        {
+            return emptyList();
+        }
+
+        Query<PsiClass> psiClassQuery = search( concernOfClass, searchScope, true, false );
+        final List<PsiClass> concernCandidates = new ArrayList<PsiClass>();
+        psiClassQuery.forEach( new Processor<PsiClass>()
+        {
+            public boolean process( PsiClass psiClass )
+            {
+                // TODO: Ideally search for all "extends" as well
+                boolean isInheritor = psiClass.isInheritor( classToCheck, true );
+                if( isInheritor )
+                {
+                    concernCandidates.add( psiClass );
+                }
+
+                return true;
+            }
+        } );
+
+        return concernCandidates;
+    }
+}
+
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/common/inspections/AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/common/inspections/AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection.java
new file mode 100644
index 0000000..4b4bb9c
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/common/inspections/AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection.java
@@ -0,0 +1,92 @@
+/*
+ *  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.polygene.ide.plugin.idea.injections.common.inspections;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.psi.PsiAnnotation;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiParameter;
+import com.intellij.psi.PsiParameterList;
+import org.jetbrains.annotations.NotNull;
+import org.apache.polygene.ide.plugin.idea.common.inspections.AbstractFix;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
+import static java.util.Arrays.asList;
+
+/**
+ * {@code AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection} is a helper method to check whether
+ * injection annotation are declared in either constructor or non static field.
+ *
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public abstract class AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection
+    extends AbstractInjectionAnnotationDeclarationOnFieldInspection
+{
+    @Override
+    public final ProblemDescriptor[] checkMethod( @NotNull PsiMethod method,
+                                                  @NotNull InspectionManager manager,
+                                                  boolean isOnTheFly )
+    {
+        PsiParameterList parameterList = method.getParameterList();
+        PsiParameter[] parameters = parameterList.getParameters();
+        if( method.isConstructor() )
+        {
+            List<ProblemDescriptor> problems = new LinkedList<ProblemDescriptor>();
+            for( PsiParameter parameter : parameters )
+            {
+                PsiAnnotation annotation = getAnnotationToCheck( parameter );
+                if( annotation != null )
+                {
+                    ProblemDescriptor[] descriptors =
+                        verifyAnnotationDeclaredCorrectly( parameter, annotation, manager );
+                    if( descriptors != null )
+                    {
+                        problems.addAll( asList( descriptors ) );
+                    }
+                }
+            }
+
+            return problems.toArray( new ProblemDescriptor[problems.size()] );
+        }
+        else
+        {
+            List<ProblemDescriptor> problems = new LinkedList<ProblemDescriptor>();
+            for( PsiParameter parameter : parameters )
+            {
+                PsiAnnotation annotationToCheck = getAnnotationToCheck( parameter );
+                if( annotationToCheck != null )
+                {
+                    String message = getInjectionAnnotationValidDeclarationMessage();
+                    AbstractFix removeAnnotationFix = createRemoveAnnotationFix( annotationToCheck );
+                    ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(
+                        annotationToCheck, message, removeAnnotationFix, GENERIC_ERROR_OR_WARNING
+                    );
+                    problems.add( problemDescriptor );
+                }
+            }
+
+            return problems.toArray( new ProblemDescriptor[problems.size()] );
+        }
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/common/inspections/AbstractInjectionAnnotationDeclarationOnFieldInspection.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/common/inspections/AbstractInjectionAnnotationDeclarationOnFieldInspection.java
new file mode 100644
index 0000000..f93f396
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/common/inspections/AbstractInjectionAnnotationDeclarationOnFieldInspection.java
@@ -0,0 +1,141 @@
+/*
+ *  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.polygene.ide.plugin.idea.injections.common.inspections;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiAnnotation;
+import com.intellij.psi.PsiField;
+import com.intellij.psi.PsiModifierList;
+import com.intellij.psi.PsiVariable;
+import org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.apache.polygene.ide.plugin.idea.common.inspections.AbstractFix;
+import org.apache.polygene.ide.plugin.idea.common.inspections.AbstractInspection;
+
+import static com.intellij.codeInsight.AnnotationUtil.findAnnotation;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public abstract class AbstractInjectionAnnotationDeclarationOnFieldInspection extends AbstractInspection
+{
+    /**
+     * @return Remove annotation message fix.
+     * @since 0.1
+     */
+    @NotNull
+    protected abstract String getRemoveAnnotationMessageFix();
+
+    /**
+     * @return Annotation to check qualified name.
+     * @since 0.1
+     */
+    @NotNull
+    protected abstract String getAnnotationToCheckQualifiedName();
+
+    /**
+     * Verified that {@link #getAnnotationToCheck(com.intellij.psi.PsiVariable)} is declared correctly.
+     *
+     * @param psiVariable       Variable to check. This could be class field member or constructor parameter.
+     * @param annotationToCheck annotation declared at variable to check.
+     * @param manager           Inspection manager to use to create problem descriptor.
+     * @return {@code null} if annotation is declared correctly, otherwise an array of problem descriptor.
+     * @since 0.1
+     */
+    @Nullable
+    protected abstract ProblemDescriptor[] verifyAnnotationDeclaredCorrectly( @NotNull PsiVariable psiVariable,
+                                                                              @NotNull PsiAnnotation annotationToCheck,
+                                                                              @NotNull InspectionManager manager );
+
+    @Override
+    public final ProblemDescriptor[] checkField( @NotNull PsiField field,
+                                                 @NotNull InspectionManager manager,
+                                                 boolean isOnTheFly )
+    {
+        PsiAnnotation annotationToCheck = getAnnotationToCheck( field );
+        if( annotationToCheck == null )
+        {
+            return null;
+        }
+
+        PsiModifierList modifierList = field.getModifierList();
+        if( modifierList != null )
+        {
+            if( modifierList.hasModifierProperty( com.intellij.psi.PsiModifier.STATIC ) )
+            {
+                String message = getInjectionAnnotationValidDeclarationMessage();
+                AbstractFix removeAnnotationFix = createRemoveAnnotationFix( annotationToCheck );
+                ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(
+                    annotationToCheck, message, removeAnnotationFix, com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING
+                );
+
+                return new ProblemDescriptor[]{ problemDescriptor };
+            }
+        }
+
+        return verifyAnnotationDeclaredCorrectly( field, annotationToCheck, manager );
+    }
+
+    /**
+     * @param variable variable to check.
+     * @return Annotation to check.
+     * @see #getAnnotationToCheckQualifiedName()
+     * @since 0.1
+     */
+    @Nullable
+    protected final PsiAnnotation getAnnotationToCheck( @NotNull PsiVariable variable )
+    {
+        String annotationQualifiedName = getAnnotationToCheckQualifiedName();
+        return findAnnotation( variable, annotationQualifiedName );
+    }
+
+    @NotNull protected String getInjectionAnnotationValidDeclarationMessage()
+    {
+        String annotationQualifiedName = getAnnotationToCheckQualifiedName();
+        return PolygeneResourceBundle.message( "abstract.injection.annotation.declaration.inspection.error.annotation.not.declared.correctly",
+                                           annotationQualifiedName );
+    }
+
+    @NotNull
+    protected final AbstractFix createRemoveAnnotationFix( @NotNull PsiAnnotation annotationToRemove )
+    {
+        String fixMessage = getRemoveAnnotationMessageFix();
+        return new RemoveAnnotationFix( fixMessage, annotationToRemove );
+    }
+
+    private static class RemoveAnnotationFix extends AbstractFix
+    {
+        private final PsiAnnotation annotationToRemove;
+
+        public RemoveAnnotationFix( @NotNull String fixMessage, @NotNull PsiAnnotation annotationToRemove )
+        {
+            super( fixMessage );
+            this.annotationToRemove = annotationToRemove;
+        }
+
+        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
+        {
+            annotationToRemove.delete();
+        }
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/invocation/common/PolygeneInvocationAnnotationConstants.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/invocation/common/PolygeneInvocationAnnotationConstants.java
new file mode 100644
index 0000000..25c1267
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/invocation/common/PolygeneInvocationAnnotationConstants.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.ide.plugin.idea.injections.invocation.common;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneInvocationAnnotationConstants
+{
+    public static final String QUALIFIED_NAME_INVOCATION_ANNOTATION = "org.apache.polygene.api.injection.scope.Invocation";
+
+    private PolygeneInvocationAnnotationConstants()
+    {
+    }
+}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/invocation/common/PolygeneInvocationAnnotationUtil.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/invocation/common/PolygeneInvocationAnnotationUtil.java
new file mode 100644
index 0000000..334918d
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/invocation/common/PolygeneInvocationAnnotationUtil.java
@@ -0,0 +1,129 @@
+/*
+ *  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.polygene.ide.plugin.idea.injections.invocation.common;
+
+import com.intellij.psi.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import static com.intellij.codeInsight.AnnotationUtil.findAnnotation;
+import static com.intellij.psi.PsiModifier.STATIC;
+import static org.apache.polygene.ide.plugin.idea.common.psi.PsiClassUtil.getPSIClass;
+import static org.apache.polygene.ide.plugin.idea.injections.invocation.common.PolygeneInvocationAnnotationConstants.QUALIFIED_NAME_INVOCATION_ANNOTATION;
+import static org.apache.polygene.ide.plugin.idea.injections.invocation.common.PolygeneInvocationAnnotationUtil.InvocationAnnotationDeclarationValidationResult.*;
+import static org.apache.polygene.ide.plugin.idea.injections.structure.common.PolygeneStructureAnnotationUtil.isInjecteableByStructureAnnotation;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneInvocationAnnotationUtil
+{
+    /**
+     * Returns {@code @Invocation} annotation if exists.
+     *
+     * @param modifierListOwner modifier list owner to process.
+     * @return {@code @Invocation} annotation if exists, {@code null} otherwise.
+     * @since 0.1
+     */
+    @Nullable
+    public static PsiAnnotation getInvocationAnnotation( @NotNull PsiModifierListOwner modifierListOwner )
+    {
+        return findAnnotation( modifierListOwner, QUALIFIED_NAME_INVOCATION_ANNOTATION );
+    }
+
+    /**
+     * @param psiClass psi class to check.
+     * @return {@code true} if the specified psiClass is injectable by invocation annotation, {@code false} otherwise.
+     */
+    public static boolean isInjectableByInvocationAnnotation( @NotNull PsiClass psiClass )
+    {
+        if( psiClass.isAnnotationType() )
+        {
+            return true;
+        }
+
+        String classQualifiedName = psiClass.getQualifiedName();
+        return "java.lang.reflect.Method".equals( classQualifiedName ) ||
+               "java.lang.reflect.AnnotatedElement".equals( classQualifiedName );
+    }
+
+    /**
+     * Validates whether the variable has {@code @Invocation} annotation declared correctly.
+     *
+     * @param variable variable to check.
+     * @return Look at {@link InvocationAnnotationDeclarationValidationResult}.
+     * @since 0.1
+     */
+    @NotNull
+    public static InvocationAnnotationDeclarationValidationResult isValidInvocationAnnotationDeclaration(
+        @NotNull PsiVariable variable )
+    {
+        PsiAnnotation invocationAnnotation = getInvocationAnnotation( variable );
+        if( invocationAnnotation == null )
+        {
+            return invalidInvocationAnnotationNotDeclared;
+        }
+
+        PsiModifierList modifierList = variable.getModifierList();
+        if( modifierList != null )
+        {
+            if( modifierList.hasModifierProperty( STATIC ) )
+            {
+                return invalidDeclaredOnStaticVariable;
+            }
+        }
+
+        // TODO: Check whether variable is either an instance of java.lang.reflect.Method or
+        // java.lang.reflect.AnnotatedElement or Annotation
+        PsiTypeElement typeElement = variable.getTypeElement();
+        if( typeElement != null )
+        {
+            PsiClass psiClass = getPSIClass( typeElement );
+            if( psiClass != null )
+            {
+                if( !isInjectableByInvocationAnnotation( psiClass ) )
+                {
+                    // Can't be type that is injected by @Structure
+                    if( isInjecteableByStructureAnnotation( variable ) )
+                    {
+                        return invalidTypeIsInjectedViaStructureAnnotation;
+                    }
+
+                    return invalidType;
+                }
+            }
+        }
+
+        return valid;
+    }
+
+    public enum InvocationAnnotationDeclarationValidationResult
+    {
+        invalidInvocationAnnotationNotDeclared,
+        invalidDeclaredOnStaticVariable,
+        invalidTypeIsInjectedViaStructureAnnotation,
+        invalidType,
+        valid,
+    }
+
+    private PolygeneInvocationAnnotationUtil()
+    {
+    }
+}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/invocation/inspections/InvocationAnnotationDeclaredCorrectlyInspection.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/invocation/inspections/InvocationAnnotationDeclaredCorrectlyInspection.java
new file mode 100644
index 0000000..e8dc1d4
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/invocation/inspections/InvocationAnnotationDeclaredCorrectlyInspection.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.polygene.ide.plugin.idea.injections.invocation.inspections;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.psi.PsiAnnotation;
+import com.intellij.psi.PsiVariable;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.apache.polygene.ide.plugin.idea.injections.common.inspections.AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection;
+import org.apache.polygene.ide.plugin.idea.injections.structure.common.ReplaceWithStructureAnnotation;
+
+import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
+import static org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle.message;
+import static org.apache.polygene.ide.plugin.idea.injections.invocation.common.PolygeneInvocationAnnotationConstants.QUALIFIED_NAME_INVOCATION_ANNOTATION;
+import static org.apache.polygene.ide.plugin.idea.injections.invocation.common.PolygeneInvocationAnnotationUtil.InvocationAnnotationDeclarationValidationResult;
+import static org.apache.polygene.ide.plugin.idea.injections.invocation.common.PolygeneInvocationAnnotationUtil.isValidInvocationAnnotationDeclaration;
+import static org.apache.polygene.ide.plugin.idea.injections.structure.common.PolygeneStructureAnnotationUtil.getStructureAnnotation;
+
+/**
+ * {@code InvocationAnnotationDeclaredCorrectlyInspection} validates {@code @Invocation} injection annotation
+ * declaration.
+ *
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public class InvocationAnnotationDeclaredCorrectlyInspection
+    extends AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection
+{
+    @NotNull
+    protected final String resourceBundlePrefixId()
+    {
+        return "injections.invocation.annotation.declared.correctly";
+    }
+
+    @NotNull
+    public final String getShortName()
+    {
+        return "InvocationAnnotationDeclaredCorrectlyInspection";
+    }
+
+    @NotNull
+    protected final String getRemoveAnnotationMessageFix()
+    {
+        return message( "injections.invocation.annotation.declared.correctly.fix.remove.annotation" );
+    }
+
+    @NotNull
+    protected final String getAnnotationToCheckQualifiedName()
+    {
+        return QUALIFIED_NAME_INVOCATION_ANNOTATION;
+    }
+
+    @Nullable
+    protected final ProblemDescriptor[] verifyAnnotationDeclaredCorrectly( @NotNull PsiVariable psiVariable,
+                                                                           @NotNull PsiAnnotation invocationAnnotation,
+                                                                           @NotNull InspectionManager manager )
+    {
+        LocalQuickFix fix = null;
+        String message = null;
+
+        String variableTypeQualifiedName = psiVariable.getType().getCanonicalText();
+
+        InvocationAnnotationDeclarationValidationResult validationResult =
+            isValidInvocationAnnotationDeclaration( psiVariable );
+        switch( validationResult )
+        {
+        case invalidTypeIsInjectedViaStructureAnnotation:
+            if( getStructureAnnotation( psiVariable ) == null )
+            {
+                fix = new ReplaceWithStructureAnnotation(
+                    message( "injections.invocation.annotation.declared.correctly.fix.replace.with.structure.annotation" ),
+                    invocationAnnotation );
+            }
+            message = message(
+                "injections.invocation.annotation.declared.correctly.error.type.is.injected.by.structure",
+                variableTypeQualifiedName
+            );
+            break;
+
+        case invalidType:
+            message = message( "injections.invocation.annotation.declared.correctly.error.type.is.not.injectable",
+                               variableTypeQualifiedName );
+            break;
+        }
+
+        // If it's not an error, return null
+        if( message == null )
+        {
+            return null;
+        }
+
+        // If Fix not defined, by default we remove it.
+        if( fix == null )
+        {
+            fix = createRemoveAnnotationFix( invocationAnnotation );
+        }
+
+        ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(
+            invocationAnnotation, message, fix, GENERIC_ERROR_OR_WARNING );
+        return new ProblemDescriptor[]{ problemDescriptor };
+    }
+}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/service/common/PolygeneServiceAnnotationConstants.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/service/common/PolygeneServiceAnnotationConstants.java
new file mode 100644
index 0000000..5a95513
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/service/common/PolygeneServiceAnnotationConstants.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.ide.plugin.idea.injections.service.common;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneServiceAnnotationConstants
+{
+    public static final String QUALIFIED_NAME_SERVICE_ANNOTATION = "org.apache.polygene.api.injection.scope.Service";
+
+    private PolygeneServiceAnnotationConstants()
+    {
+    }
+}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/service/common/PolygeneServiceAnnotationUtil.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/service/common/PolygeneServiceAnnotationUtil.java
new file mode 100644
index 0000000..962c1bb
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/service/common/PolygeneServiceAnnotationUtil.java
@@ -0,0 +1,99 @@
+/*
+ *  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.polygene.ide.plugin.idea.injections.service.common;
+
+import com.intellij.psi.PsiAnnotation;
+import com.intellij.psi.PsiModifierList;
+import com.intellij.psi.PsiModifierListOwner;
+import com.intellij.psi.PsiVariable;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import static com.intellij.codeInsight.AnnotationUtil.findAnnotation;
+import static com.intellij.psi.PsiModifier.STATIC;
+import static org.apache.polygene.ide.plugin.idea.injections.service.common.PolygeneServiceAnnotationConstants.QUALIFIED_NAME_SERVICE_ANNOTATION;
+import static org.apache.polygene.ide.plugin.idea.injections.service.common.PolygeneServiceAnnotationUtil.ServiceAnnotationDeclarationValidationResult.*;
+import static org.apache.polygene.ide.plugin.idea.injections.structure.common.PolygeneStructureAnnotationUtil.isInjecteableByStructureAnnotation;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneServiceAnnotationUtil
+{
+    /**
+     * Returns {@code @Service} annotation if exists.
+     *
+     * @param modifierListOwner modifier list owner to process.
+     * @return {@code @Service} annotation if exists, {@code null} otherwise.
+     * @since 0.1
+     */
+    @Nullable
+    public static PsiAnnotation getServiceAnnotation( @NotNull PsiModifierListOwner modifierListOwner )
+    {
+        return findAnnotation( modifierListOwner, QUALIFIED_NAME_SERVICE_ANNOTATION );
+    }
+
+    /**
+     * Validates whether the variable has {@code @Service} annotation declared correctly.
+     *
+     * @param variable variable to check.
+     * @return Look at {@link ServiceAnnotationDeclarationValidationResult}.
+     * @since 0.1
+     */
+    @NotNull
+    public static ServiceAnnotationDeclarationValidationResult isValidServiceAnnotationDeclaration(
+        @NotNull PsiVariable variable )
+    {
+        PsiAnnotation serviceAnnotation = getServiceAnnotation( variable );
+        if( serviceAnnotation == null )
+        {
+            return invalidServiceAnnotationNotDeclared;
+        }
+
+        PsiModifierList modifierList = variable.getModifierList();
+        if( modifierList != null )
+        {
+            if( modifierList.hasModifierProperty( STATIC ) )
+            {
+                return invalidDeclaredOnStaticVariable;
+            }
+        }
+
+        // Can't be type that is injected by @Structure
+        if( isInjecteableByStructureAnnotation( variable ) )
+        {
+            return invalidTypeIsInjectedViaStructureAnnotation;
+        }
+
+        return valid;
+    }
+
+    public enum ServiceAnnotationDeclarationValidationResult
+    {
+        invalidServiceAnnotationNotDeclared,
+        invalidDeclaredOnStaticVariable,
+        invalidTypeIsInjectedViaStructureAnnotation,
+        valid,
+    }
+
+    private PolygeneServiceAnnotationUtil()
+    {
+    }
+}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/service/inspections/ServiceAnnotationDeclaredCorrectlyInspection.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/service/inspections/ServiceAnnotationDeclaredCorrectlyInspection.java
new file mode 100644
index 0000000..afc43f1
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/service/inspections/ServiceAnnotationDeclaredCorrectlyInspection.java
@@ -0,0 +1,112 @@
+/*
+ *  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.polygene.ide.plugin.idea.injections.service.inspections;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.psi.PsiAnnotation;
+import com.intellij.psi.PsiVariable;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.apache.polygene.ide.plugin.idea.injections.common.inspections.AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection;
+import org.apache.polygene.ide.plugin.idea.injections.structure.common.ReplaceWithStructureAnnotation;
+
+import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
+import static org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle.message;
+import static org.apache.polygene.ide.plugin.idea.injections.service.common.PolygeneServiceAnnotationConstants.QUALIFIED_NAME_SERVICE_ANNOTATION;
+import static org.apache.polygene.ide.plugin.idea.injections.service.common.PolygeneServiceAnnotationUtil.ServiceAnnotationDeclarationValidationResult;
+import static org.apache.polygene.ide.plugin.idea.injections.service.common.PolygeneServiceAnnotationUtil.isValidServiceAnnotationDeclaration;
+import static org.apache.polygene.ide.plugin.idea.injections.structure.common.PolygeneStructureAnnotationUtil.getStructureAnnotation;
+
+/**
+ * {@code ServiceAnnotationDeclaredCorrectly} validates {@code @Service} injection annotation declaration.
+ *
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public class ServiceAnnotationDeclaredCorrectlyInspection
+    extends AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection
+{
+    @NotNull
+    protected final String resourceBundlePrefixId()
+    {
+        return "injections.service.annotation.declared.correctly";
+    }
+
+    @NotNull
+    public final String getShortName()
+    {
+        return "ServiceAnnotationDeclaredCorrectlyInspection";
+    }
+
+    @NotNull
+    protected final String getRemoveAnnotationMessageFix()
+    {
+        return message( "injections.service.annotation.declared.correctly.fix.remove.annotation" );
+    }
+
+    @NotNull
+    protected final String getAnnotationToCheckQualifiedName()
+    {
+        return QUALIFIED_NAME_SERVICE_ANNOTATION;
+    }
+
+    @Nullable
+    protected final ProblemDescriptor[] verifyAnnotationDeclaredCorrectly( @NotNull PsiVariable psiVariable,
+                                                                           @NotNull PsiAnnotation serviceAnnotation,
+                                                                           @NotNull InspectionManager manager )
+    {
+        ServiceAnnotationDeclarationValidationResult annotationCheck =
+            isValidServiceAnnotationDeclaration( psiVariable );
+        String message = null;
+        LocalQuickFix fix = null;
+        switch( annotationCheck )
+        {
+        case invalidTypeIsInjectedViaStructureAnnotation:
+            if( getStructureAnnotation( psiVariable ) == null )
+            {
+                fix = new ReplaceWithStructureAnnotation(
+                    message( "injections.service.annotation.declared.correctly.fix.replace.with.structure.annotation" ),
+                    serviceAnnotation );
+            }
+            message = message(
+                "injections.service.annotation.declared.correctly.error.type.is.injected.by.structure",
+                psiVariable.getType().getCanonicalText()
+            );
+            break;
+        }
+
+        // If it's not an error, return null
+        if( message == null )
+        {
+            return null;
+        }
+
+        // Default behavior to remove @Service annotation
+        if( fix == null )
+        {
+            fix = createRemoveAnnotationFix( serviceAnnotation );
+        }
+
+        ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(
+            serviceAnnotation, message, fix, GENERIC_ERROR_OR_WARNING );
+        return new ProblemDescriptor[]{ problemDescriptor };
+    }
+}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/structure/common/PolygeneStructureAnnotationConstants.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/structure/common/PolygeneStructureAnnotationConstants.java
new file mode 100644
index 0000000..2a5d3bf
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/structure/common/PolygeneStructureAnnotationConstants.java
@@ -0,0 +1,53 @@
+/*
+ *  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.polygene.ide.plugin.idea.injections.structure.common;
+
+import static java.util.Arrays.sort;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneStructureAnnotationConstants
+{
+    public static final String QUALIFIED_NAME_STRUCTURE_ANNOTATION = "org.apache.polygene.api.injection.scope.Structure";
+
+    public static final String[] VALID_STRUCTURE_INJECTION_TYPE;
+
+    static
+    {
+        VALID_STRUCTURE_INJECTION_TYPE = new String[]
+            {
+                "org.apache.polygene.composite.CompositeBuilderFactory",
+                "org.apache.polygene.object.ObjectBuilderFactory",
+                "org.apache.polygene.entity.UnitOfWorkFactory",
+                "org.apache.polygene.service.ServiceFinder",
+                "org.apache.polygene.structure.Module",
+                "org.apache.polygene.structure.Layer",
+                "org.apache.polygene.structure.Application",
+                "org.apache.polygene.api.PolygeneAPI",
+                "org.apache.polygene.spi.PolygeneSPI"
+            };
+        sort( VALID_STRUCTURE_INJECTION_TYPE );
+    }
+
+    private PolygeneStructureAnnotationConstants()
+    {
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/structure/common/PolygeneStructureAnnotationUtil.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/structure/common/PolygeneStructureAnnotationUtil.java
new file mode 100644
index 0000000..c334276
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/structure/common/PolygeneStructureAnnotationUtil.java
@@ -0,0 +1,124 @@
+/*
+ *  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.polygene.ide.plugin.idea.injections.structure.common;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import static com.intellij.codeInsight.AnnotationUtil.findAnnotation;
+import static com.intellij.psi.PsiModifier.STATIC;
+import static org.apache.polygene.ide.plugin.idea.injections.structure.common.PolygeneStructureAnnotationConstants.QUALIFIED_NAME_STRUCTURE_ANNOTATION;
+import static org.apache.polygene.ide.plugin.idea.injections.structure.common.PolygeneStructureAnnotationConstants.VALID_STRUCTURE_INJECTION_TYPE;
+import static org.apache.polygene.ide.plugin.idea.injections.structure.common.PolygeneStructureAnnotationUtil.StructureAnnotationDeclarationValidationResult.*;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneStructureAnnotationUtil
+{
+    /**
+     * Returns {@code Structure} annotation if exists.
+     *
+     * @param modifierListOwner Modifier list owner.
+     * @return @Structure annotation if exists, {@code null} otherwise.
+     * @since 0.1
+     */
+    @Nullable
+    public static PsiAnnotation getStructureAnnotation( @NotNull PsiModifierListOwner modifierListOwner )
+    {
+        return findAnnotation( modifierListOwner, QUALIFIED_NAME_STRUCTURE_ANNOTATION );
+    }
+
+    /**
+     * Create structure annotation.
+     *
+     * @param project project to create structure annotation.
+     * @param context the context to create structure annotation.
+     * @return @Structure annotation.
+     */
+    @NotNull
+    public static PsiAnnotation createStructureAnnotation( @NotNull Project project,
+                                                           @NotNull PsiElement context )
+    {
+        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( project );
+        PsiElementFactory factory = psiFacade.getElementFactory();
+        return factory.createAnnotationFromText( "@" + QUALIFIED_NAME_STRUCTURE_ANNOTATION, context );
+    }
+
+    /**
+     * @param variable variable to check.
+     * @return Look at {@link StructureAnnotationDeclarationValidationResult}.
+     * @since 0.1
+     */
+    @NotNull
+    public static StructureAnnotationDeclarationValidationResult validateStructureAnnotationDeclaration(
+        @NotNull PsiVariable variable )
+    {
+        PsiAnnotation structureAnnotation = getStructureAnnotation( variable );
+        if( structureAnnotation == null )
+        {
+            return invalidStructureAnnotationNotDeclared;
+        }
+
+        PsiModifierList modifierList = variable.getModifierList();
+        if( modifierList != null )
+        {
+            if( modifierList.hasModifierProperty( STATIC ) )
+            {
+                return invalidDeclaredOnStaticVariable;
+            }
+        }
+
+        if( !isInjecteableByStructureAnnotation( variable ) )
+        {
+            return invalidInjectionType;
+        }
+
+        return valid;
+    }
+
+    /**
+     * Returns a {@code boolean} indicator whether variable type is injectable by @Structure annotation.
+     *
+     * @param variable variable to check.
+     * @return {@code true} if variable type is injecteable by @Structure annotation.
+     * @since 0.1
+     */
+    public static boolean isInjecteableByStructureAnnotation( @NotNull PsiVariable variable )
+    {
+        PsiType type = variable.getType();
+        String fieldClassQualifiedName = type.getCanonicalText();
+        return binarySearch( VALID_STRUCTURE_INJECTION_TYPE, fieldClassQualifiedName ) > -1;
+    }
+
+    private PolygeneStructureAnnotationUtil()
+    {
+    }
+
+    public enum StructureAnnotationDeclarationValidationResult
+    {
+        invalidStructureAnnotationNotDeclared,
+        invalidDeclaredOnStaticVariable,
+        invalidInjectionType,
+        valid,
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/structure/common/ReplaceWithStructureAnnotation.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/structure/common/ReplaceWithStructureAnnotation.java
new file mode 100644
index 0000000..3659db3
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/structure/common/ReplaceWithStructureAnnotation.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.ide.plugin.idea.injections.structure.common;
+
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiAnnotation;
+import org.jetbrains.annotations.NotNull;
+import org.apache.polygene.ide.plugin.idea.common.inspections.AbstractFix;
+
+import static org.apache.polygene.ide.plugin.idea.injections.structure.common.PolygeneStructureAnnotationUtil.createStructureAnnotation;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class ReplaceWithStructureAnnotation extends AbstractFix
+{
+    private final PsiAnnotation annotation;
+
+    public ReplaceWithStructureAnnotation( @NotNull String fixMessage,
+                                           @NotNull PsiAnnotation annotationToReplace )
+    {
+        super( fixMessage );
+        this.annotation = annotationToReplace;
+    }
+
+    public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
+    {
+        PsiAnnotation structureAnnotation = createStructureAnnotation( project, annotation );
+        annotation.replace( structureAnnotation );
+    }
+}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/structure/inspections/StructureAnnotationDeclaredCorrectlyInspection.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/structure/inspections/StructureAnnotationDeclaredCorrectlyInspection.java
new file mode 100644
index 0000000..a972acd
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/injections/structure/inspections/StructureAnnotationDeclaredCorrectlyInspection.java
@@ -0,0 +1,92 @@
+/*
+ *  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.polygene.ide.plugin.idea.injections.structure.inspections;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.psi.PsiAnnotation;
+import com.intellij.psi.PsiVariable;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.apache.polygene.ide.plugin.idea.common.inspections.AbstractFix;
+import org.apache.polygene.ide.plugin.idea.injections.common.inspections.AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection;
+
+import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
+import static org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle.message;
+import static org.apache.polygene.ide.plugin.idea.injections.structure.common.PolygeneStructureAnnotationConstants.QUALIFIED_NAME_STRUCTURE_ANNOTATION;
+import static org.apache.polygene.ide.plugin.idea.injections.structure.common.PolygeneStructureAnnotationUtil.StructureAnnotationDeclarationValidationResult;
+import static org.apache.polygene.ide.plugin.idea.injections.structure.common.PolygeneStructureAnnotationUtil.validateStructureAnnotationDeclaration;
+
+/**
+ * {@code StructureAnnotationUsedCorrectly} validates {@code @Structure} injection annotation declaration.
+ *
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public class StructureAnnotationDeclaredCorrectlyInspection
+    extends AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection
+{
+    @NotNull
+    protected final String resourceBundlePrefixId()
+    {
+        return "injections.structure.annotation.declared.correctly";
+    }
+
+    @NotNull
+    public final String getShortName()
+    {
+        return "StructureAnnotationDeclaredCorrectlyInspection";
+    }
+
+    @NotNull
+    protected final String getRemoveAnnotationMessageFix()
+    {
+        return message( "injections.structure.annotation.declared.correctly.fix.remove.annotation" );
+    }
+
+    @NotNull
+    protected final String getAnnotationToCheckQualifiedName()
+    {
+        return QUALIFIED_NAME_STRUCTURE_ANNOTATION;
+    }
+
+    @Nullable
+    protected final ProblemDescriptor[] verifyAnnotationDeclaredCorrectly( @NotNull PsiVariable psiVariable,
+                                                                           @NotNull PsiAnnotation structureAnnotation,
+                                                                           @NotNull InspectionManager manager )
+    {
+        StructureAnnotationDeclarationValidationResult annotationCheck =
+            validateStructureAnnotationDeclaration( psiVariable );
+        switch( annotationCheck )
+        {
+        case invalidInjectionType:
+            String message = message(
+                "injections.structure.annotation.declared.correctly.error.invalid.injection.type",
+                psiVariable.getType().getCanonicalText()
+            );
+            AbstractFix removeStructureAnnotationFix = createRemoveAnnotationFix( structureAnnotation );
+            ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(
+                structureAnnotation, message, removeStructureAnnotationFix, GENERIC_ERROR_OR_WARNING
+            );
+            return new ProblemDescriptor[]{ problemDescriptor };
+        }
+
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/mixins/common/PolygeneMixinConstants.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/mixins/common/PolygeneMixinConstants.java
new file mode 100644
index 0000000..c871b3d
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/mixins/common/PolygeneMixinConstants.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.ide.plugin.idea.mixins.common;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneMixinConstants
+{
+    public static final String QUALIFIED_NAME_MIXINS = "org.apache.polygene.api.mixin.Mixins";
+
+    private PolygeneMixinConstants()
+    {
+    }
+}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/mixins/common/PolygeneMixinUtil.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/mixins/common/PolygeneMixinUtil.java
new file mode 100644
index 0000000..729ff58
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/mixins/common/PolygeneMixinUtil.java
@@ -0,0 +1,196 @@
+/*
+ *  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.polygene.ide.plugin.idea.mixins.common;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.Set;
+
+import static com.intellij.codeInsight.AnnotationUtil.findAnnotation;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.emptySet;
+import static org.apache.polygene.ide.plugin.idea.common.psi.PsiAnnotationUtil.getAnnotationDefaultParameterValue;
+import static org.apache.polygene.ide.plugin.idea.common.psi.PsiAnnotationUtil.getClassReference;
+import static org.apache.polygene.ide.plugin.idea.common.psi.PsiClassUtil.getExtendsDeep;
+import static org.apache.polygene.ide.plugin.idea.common.psi.PsiClassUtil.getPSIClass;
+import static org.apache.polygene.ide.plugin.idea.concerns.common.PolygeneConcernUtil.isAConcern;
+import static org.apache.polygene.ide.plugin.idea.mixins.common.PolygeneMixinConstants.QUALIFIED_NAME_MIXINS;
+import static org.apache.polygene.ide.plugin.idea.sideEffects.common.PolygeneSideEffectUtil.isASideEffect;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneMixinUtil
+{
+    /**
+     * Get all valid mixin types of given the {@code psiClass} argument.
+     *
+     * @param psiClass The psi class to check.
+     * @return all vlaid mixin types of the given {@code psiClass} argument.
+     * @since 0.1
+     */
+    @NotNull
+    public static Set<PsiClass> getAllValidMixinTypes( @NotNull PsiClass psiClass )
+    {
+        PsiAnnotation mixinsAnnotation = getMixinsAnnotation( psiClass );
+        if( mixinsAnnotation == null )
+        {
+            return emptySet();
+        }
+
+        Set<PsiClass> validMixinsType = getExtendsDeep( psiClass );
+        validMixinsType.add( psiClass );
+        return validMixinsType;
+    }
+
+    @NotNull
+    public static List<PsiAnnotationMemberValue> getMixinsAnnotationValue( @NotNull PsiClass psiClass )
+    {
+        return getMixinsAnnotationValue( getMixinsAnnotation( psiClass ) );
+    }
+
+    @NotNull
+    public static List<PsiAnnotationMemberValue> getMixinsAnnotationValue( @Nullable PsiAnnotation mixinsAnnotation )
+    {
+        if( mixinsAnnotation == null )
+        {
+            return emptyList();
+        }
+
+        String mixinsQualifiedName = mixinsAnnotation.getQualifiedName();
+        if( !QUALIFIED_NAME_MIXINS.equals( mixinsQualifiedName ) )
+        {
+            return emptyList();
+        }
+
+        return getAnnotationDefaultParameterValue( mixinsAnnotation );
+    }
+
+    @Nullable
+    public static PsiAnnotation getMixinsAnnotation( PsiElement element )
+    {
+        PsiClass psiClass = getPSIClass( element );
+        if( psiClass == null )
+        {
+            return null;
+        }
+
+        return findAnnotation( psiClass, QUALIFIED_NAME_MIXINS );
+    }
+
+    @NotNull
+    public static PsiAnnotation addOrReplaceMixinAnnotation( @NotNull PsiModifierListOwner modifierListOwner,
+                                                             @NotNull PsiClass mixinClassToAdd )
+    {
+        Project project = modifierListOwner.getProject();
+        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( project );
+        PsiElementFactory factory = psiFacade.getElementFactory();
+        PsiAnnotation existingMixinsAnnotation = findAnnotation( modifierListOwner, QUALIFIED_NAME_MIXINS );
+
+        boolean isReplace = false;
+        PsiAnnotation newMixinsAnnotation;
+        if( existingMixinsAnnotation != null )
+        {
+            // Check duplicate
+            List<PsiAnnotationMemberValue> mixinsValues = getMixinsAnnotationValue( existingMixinsAnnotation );
+            for( PsiAnnotationMemberValue mixinValue : mixinsValues )
+            {
+                PsiJavaCodeReferenceElement mixinClassReference = getMixinClassReference( mixinValue );
+                if( mixinClassReference == null )
+                {
+                    continue;
+                }
+
+                PsiElement mixinClass = mixinClassReference.resolve();
+                if( mixinClassToAdd.equals( mixinClass ) )
+                {
+                    return existingMixinsAnnotation;
+                }
+            }
+
+            isReplace = true;
+        }
+
+        String mixinsAnnotationText = createMixinsAnnotationText( existingMixinsAnnotation, mixinClassToAdd );
+        newMixinsAnnotation = factory.createAnnotationFromText( mixinsAnnotationText, modifierListOwner );
+
+        if( isReplace )
+        {
+            // Replace @Mixins instead
+            existingMixinsAnnotation.replace( newMixinsAnnotation );
+        }
+        else
+        {
+            // @Mixins doesn't exists, add it as first child
+            PsiModifierList modifierList = modifierListOwner.getModifierList();
+            modifierList.addBefore( newMixinsAnnotation, modifierList.getFirstChild() );
+        }
+
+        // Shorten all class references if possible
+        JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance( project );
+        codeStyleManager.shortenClassReferences( newMixinsAnnotation );
+
+        return newMixinsAnnotation;
+    }
+
+    @NotNull
+    private static String createMixinsAnnotationText( @Nullable PsiAnnotation mixinsAnnotationBase,
+                                                      @NotNull PsiClass mixinClassToAdd )
+    {
+        StringBuilder annotationTextBuilder = new StringBuilder();
+        annotationTextBuilder.append( "@" ).append( QUALIFIED_NAME_MIXINS ).append( "( {" );
+        List<PsiAnnotationMemberValue> mixinsValues = getMixinsAnnotationValue( mixinsAnnotationBase );
+        for( PsiAnnotationMemberValue mixinValue : mixinsValues )
+        {
+            annotationTextBuilder.append( mixinValue.getText() ).append( ", " );
+        }
+        annotationTextBuilder.append( mixinClassToAdd.getQualifiedName() ).append( ".class" );
+        annotationTextBuilder.append( "} )" );
+
+        return annotationTextBuilder.toString();
+    }
+
+
+    @Nullable
+    public static PsiJavaCodeReferenceElement getMixinClassReference( @NotNull PsiAnnotationMemberValue value )
+    {
+        return getClassReference( value );
+    }
+
+    /**
+     * Validate whether psiClass is a mixin.
+     *
+     * @param psiClass psi class to check.
+     * @return {@code true} if psiClass is a mixin, {@code false} otherwise.
+     */
+    public static boolean isAMixin( @NotNull PsiClass psiClass )
+    {
+        return !( psiClass.isInterface() || isAConcern( psiClass ) || isASideEffect( psiClass ) );
+    }
+
+    private PolygeneMixinUtil()
+    {
+    }
+}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/mixins/inspections/MixinImplementsMixinType.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/mixins/inspections/MixinImplementsMixinType.java
new file mode 100644
index 0000000..c74725b
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/mixins/inspections/MixinImplementsMixinType.java
@@ -0,0 +1,190 @@
+/*
+ *  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.polygene.ide.plugin.idea.mixins.inspections;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiAnnotationMemberValue;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiJavaCodeReferenceElement;
+import org.jetbrains.annotations.NotNull;
+import org.apache.polygene.ide.plugin.idea.common.inspections.AbstractFix;
+import org.apache.polygene.ide.plugin.idea.common.inspections.AbstractInspection;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
+import static org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle.message;
+import static org.apache.polygene.ide.plugin.idea.concerns.common.PolygeneConcernUtil.isAConcern;
+import static org.apache.polygene.ide.plugin.idea.mixins.common.PolygeneMixinUtil.*;
+import static org.apache.polygene.ide.plugin.idea.sideEffects.common.PolygeneSideEffectUtil.isASideEffect;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class MixinImplementsMixinType extends AbstractInspection
+{
+    @NotNull
+    protected final String resourceBundlePrefixId()
+    {
+        return "mixin.implements.mixin.type";
+    }
+
+    @NotNull
+    public final String getShortName()
+    {
+        return "MixinImplementsMixinType";
+    }
+
+    @Override
+    public final ProblemDescriptor[] checkClass( @NotNull PsiClass psiClass,
+                                                 @NotNull InspectionManager manager,
+                                                 boolean isOnTheFly )
+    {
+        // If psiClass is not an interface, ignore
+        if( !psiClass.isInterface() )
+        {
+            return null;
+        }
+
+        // If @Mixins annotation is empty, ignore
+        List<PsiAnnotationMemberValue> mixinAnnotationValues = getMixinsAnnotationValue( psiClass );
+        if( mixinAnnotationValues.isEmpty() )
+        {
+            return null;
+        }
+
+        // Get all valid mixin type
+        Set<PsiClass> validMixinsType = getAllValidMixinTypes( psiClass );
+        if( validMixinsType.isEmpty() )
+        {
+            return null;
+        }
+
+        // For each mixin
+        List<ProblemDescriptor> problems = new LinkedList<ProblemDescriptor>();
+        for( PsiAnnotationMemberValue mixinAnnotationValue : mixinAnnotationValues )
+        {
+            PsiJavaCodeReferenceElement mixinClassReference = getMixinClassReference( mixinAnnotationValue );
+
+            // If it's not a class reference, ignore
+            if( mixinClassReference == null )
+            {
+                continue;
+            }
+
+            // If class reference can't be resolved, ignore
+            PsiClass mixinClass = (PsiClass) mixinClassReference.resolve();
+            if( mixinClass == null )
+            {
+                continue;
+            }
+
+            String mixinQualifiedName = mixinClass.getQualifiedName();
+
+            boolean isMixinsDeclarationValid = false;
+            String message = "";
+            if( mixinClass.isInterface() )
+            {
+                // Mixin can't be an interface
+                message = message( "mixin.implements.mixin.type.error.mixin.is.an.interface", mixinQualifiedName );
+            }
+            else if( isAConcern( mixinClass ) )
+            {
+                // Mixin can't be a concern
+                message = message( "mixin.implements.mixin.type.error.mixin.is.a.concern", mixinQualifiedName );
+            }
+            else if( isASideEffect( mixinClass ) )
+            {
+                // Mixin can't be a side effect
+                message = message( "mixin.implements.mixin.type.error.mixin.is.a.side.effect", mixinQualifiedName );
+            }
+            else
+            {
+                // If doesn't implement any mixin type, it's a problem
+                if( !isImplementValidMixinType( mixinClass, validMixinsType ) )
+                {
+                    message = message(
+                        "mixin.implements.mixin.type.error.does.not.implement.any.mixin.type",
+                        mixinQualifiedName,
+                        psiClass.getQualifiedName()
+                    );
+                }
+                else
+                {
+                    isMixinsDeclarationValid = true;
+                }
+            }
+
+            if( !isMixinsDeclarationValid )
+            {
+                ProblemDescriptor problemDescriptor = createProblemDescriptor(
+                    manager, mixinAnnotationValue, mixinClassReference, message );
+                problems.add( problemDescriptor );
+            }
+        }
+
+        return problems.toArray( new ProblemDescriptor[problems.size()] );
+    }
+
+    private boolean isImplementValidMixinType( PsiClass mixinClass, Set<PsiClass> validMixinsType )
+    {
+        for( PsiClass validMixinTypeClass : validMixinsType )
+        {
+            if( mixinClass.isInheritor( validMixinTypeClass, true ) )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private ProblemDescriptor createProblemDescriptor( @NotNull InspectionManager manager,
+                                                       @NotNull PsiAnnotationMemberValue mixinAnnotationValue,
+                                                       @NotNull PsiJavaCodeReferenceElement mixinClassReference,
+                                                       @NotNull String message )
+    {
+        RemoveInvalidMixinClassReferenceFix fix = new RemoveInvalidMixinClassReferenceFix(
+            mixinAnnotationValue, mixinClassReference
+        );
+        return manager.createProblemDescriptor( mixinAnnotationValue, message, fix, GENERIC_ERROR_OR_WARNING );
+    }
+
+    private static class RemoveInvalidMixinClassReferenceFix extends AbstractFix
+    {
+        private final PsiAnnotationMemberValue mixinClassAnnotationValue;
+
+        public RemoveInvalidMixinClassReferenceFix( @NotNull PsiAnnotationMemberValue mixinClassAnnotationValue,
+                                                    @NotNull PsiJavaCodeReferenceElement mixinClassReference )
+        {
+            super( message( "mixin.implements.mixin.type.fix.remove.class.reference", mixinClassReference.getQualifiedName() ) );
+            this.mixinClassAnnotationValue = mixinClassAnnotationValue;
+        }
+
+        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
+        {
+            mixinClassAnnotationValue.delete();
+        }
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/mixins/inspections/MixinsAnnotationDeclaredOnMixinType.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/mixins/inspections/MixinsAnnotationDeclaredOnMixinType.java
new file mode 100644
index 0000000..914823d
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/mixins/inspections/MixinsAnnotationDeclaredOnMixinType.java
@@ -0,0 +1,92 @@
+/*
+ *  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.polygene.ide.plugin.idea.mixins.inspections;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiAnnotation;
+import com.intellij.psi.PsiAnnotationMemberValue;
+import com.intellij.psi.PsiClass;
+import org.jetbrains.annotations.NotNull;
+import org.apache.polygene.ide.plugin.idea.common.inspections.AbstractFix;
+import org.apache.polygene.ide.plugin.idea.common.inspections.AbstractInspection;
+
+import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
+import static org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle.message;
+import static org.apache.polygene.ide.plugin.idea.mixins.common.PolygeneMixinUtil.getMixinsAnnotation;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class MixinsAnnotationDeclaredOnMixinType extends AbstractInspection
+{
+    @NotNull
+    public final String getShortName()
+    {
+        return "MixinsAnnotationDeclaredOnMixinType";
+    }
+
+    @NotNull
+    protected final String resourceBundlePrefixId()
+    {
+        return "mixins.annotation.declared.on.mixin.type";
+    }
+
+    @Override
+    public ProblemDescriptor[] checkClass( @NotNull PsiClass psiClass,
+                                           @NotNull InspectionManager manager,
+                                           boolean isOnTheFly )
+    {
+        PsiAnnotation mixinsAnnotation = getMixinsAnnotation( psiClass );
+        if( mixinsAnnotation == null )
+        {
+            return null;
+        }
+
+        if( psiClass.isInterface() )
+        {
+            return null;
+        }
+
+        String message = message( "mixins.annotation.declared.on.mixin.type.error.declared.on.class" );
+        RemoveInvalidMixinClassReferenceFix fix = new RemoveInvalidMixinClassReferenceFix( mixinsAnnotation );
+        ProblemDescriptor problemDescriptor = manager.createProblemDescriptor( mixinsAnnotation, message, fix,
+                                                                               GENERIC_ERROR_OR_WARNING );
+        return new ProblemDescriptor[]{ problemDescriptor };
+
+    }
+
+    private static class RemoveInvalidMixinClassReferenceFix extends AbstractFix
+    {
+        private final PsiAnnotationMemberValue mixinsAnnotation;
+
+        public RemoveInvalidMixinClassReferenceFix( @NotNull PsiAnnotationMemberValue mixinsAnnotation )
+        {
+            super( message( "mixins.annotation.declared.on.mixin.type.fix.remove.mixins.annotation" ) );
+            this.mixinsAnnotation = mixinsAnnotation;
+        }
+
+        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
+        {
+            mixinsAnnotation.delete();
+        }
+    }
+}
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/sideEffects/common/PolygeneSideEffectConstants.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/sideEffects/common/PolygeneSideEffectConstants.java
new file mode 100644
index 0000000..d3c269f
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/sideEffects/common/PolygeneSideEffectConstants.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.ide.plugin.idea.sideEffects.common;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneSideEffectConstants
+{
+    public static final String QUALIFIED_NAME_SIDE_EFFECTS = "org.apache.polygene.api.sideeffect.SideEffects";
+
+    public static final String QUALIFIED_NAME_SIDE_EFFECT_OF = "org.apache.polygene.api.sideeffect.SideEffectOf";
+    public static final String QUALIFIED_NAME_GENERIC_SIDE_EFFECT = "org.apache.polygene.api.sideeffect.GenericSideEffect";
+
+    private PolygeneSideEffectConstants()
+    {
+    }
+}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/sideEffects/common/PolygeneSideEffectUtil.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/sideEffects/common/PolygeneSideEffectUtil.java
new file mode 100644
index 0000000..c1533fc
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/sideEffects/common/PolygeneSideEffectUtil.java
@@ -0,0 +1,188 @@
+/*
+ *  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.polygene.ide.plugin.idea.sideEffects.common;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+import java.util.List;
+
+import static com.intellij.codeInsight.AnnotationUtil.findAnnotation;
+import static java.util.Collections.emptyList;
+import static org.apache.polygene.ide.plugin.idea.common.psi.PsiAnnotationUtil.getAnnotationDefaultParameterValue;
+import static org.apache.polygene.ide.plugin.idea.common.psi.PsiAnnotationUtil.getClassReference;
+import static org.apache.polygene.ide.plugin.idea.common.psi.PsiClassUtil.getPSIClass;
+import static org.apache.polygene.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
+import static org.apache.polygene.ide.plugin.idea.sideEffects.common.PolygeneSideEffectConstants.*;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class PolygeneSideEffectUtil
+{
+    /**
+     * @param searchContext Search context.
+     * @return {@code GenericSideEffect} class given the search context. {@code null} if not found.
+     * @since 0.1
+     */
+    @Nullable
+    public static PsiClass getGenericSideEffectClass( @NotNull PsiElement searchContext )
+    {
+        Project project = searchContext.getProject();
+        GlobalSearchScope searchScope = determineSearchScope( searchContext );
+        return getGenericSideEffectClass( project, searchScope );
+    }
+
+    /**
+     * @param project project.
+     * @param scope   search scope.
+     * @return {@code GenericSideEffect} class given {@code project} and {@code scope} parameters.
+     *         Returns {@code null} if not found.
+     * @since 0.1
+     */
+    @Nullable
+    public static PsiClass getGenericSideEffectClass( @NotNull Project project,
+                                                      @Nullable GlobalSearchScope scope )
+    {
+        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( project );
+        return scope == null ? null : psiFacade.findClass( QUALIFIED_NAME_GENERIC_SIDE_EFFECT, scope );
+    }
+
+    /**
+     * @param searchContext Search context.
+     * @return {@code SideEffectOf} class given the search context. {@code null} if not found.
+     * @since 0.1
+     */
+    @Nullable
+    public static PsiClass getSideEffectOfClass( @NotNull PsiElement searchContext )
+    {
+        Project project = searchContext.getProject();
+        GlobalSearchScope searchScope = determineSearchScope( searchContext );
+        return getSideEffectOfClass( project, searchScope );
+    }
+
+
+    /**
+     * @param project project.
+     * @param scope   search scope.
+     * @return {@code SideEffectOf} class given {@code project} and {@code scope} parameters.
+     *         Returns {@code null} if not found.
+     * @since 0.1
+     */
+    @Nullable
+    public static PsiClass getSideEffectOfClass( @NotNull Project project,
+                                                 @Nullable GlobalSearchScope scope )
+    {
+        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( project );
+        return scope == null ? null : psiFacade.findClass( QUALIFIED_NAME_SIDE_EFFECT_OF, scope );
+    }
+
+    /**
+     * @param elementWithinJavaClass element within java class.
+     * @return {@code @SideEffects} annotation declaration of the class that contains the element.
+     *         Returns {@code null} if not found, or {@code element} is an invalid context.
+     * @since 0.1
+     */
+    @Nullable
+    public static PsiAnnotation getSideEffectsAnnotation( @NotNull PsiElement elementWithinJavaClass )
+    {
+        PsiClass psiClass = getPSIClass( elementWithinJavaClass );
+        return findAnnotation( psiClass, QUALIFIED_NAME_SIDE_EFFECTS );
+    }
+
+    /**
+     * @param annotation annotation to process.
+     * @return {@code @SideEffects} annotation value. Returns {@link Collections#emptyList()} if {@code annotation} is
+     *         {@code null} or annotation is not a {@code @SideEffects} annotation.
+     * @since 0.1
+     */
+    @NotNull
+    public static List<PsiAnnotationMemberValue> getSideEffectsAnnotationValue( @Nullable PsiAnnotation annotation )
+    {
+        if( annotation == null )
+        {
+            return emptyList();
+        }
+
+        String concernsQualifiedName = annotation.getQualifiedName();
+        if( !QUALIFIED_NAME_SIDE_EFFECTS.equals( concernsQualifiedName ) )
+        {
+            return emptyList();
+        }
+
+        return getAnnotationDefaultParameterValue( annotation );
+    }
+
+    /**
+     * @param value annotation member value.
+     * @return Side effect class reference given the {@code value} parameter. Returns {@code null} if it's not a
+     *         class reference.
+     * @since 0.1
+     */
+    @Nullable
+    public static PsiJavaCodeReferenceElement getSideEffectClassReference( @NotNull PsiAnnotationMemberValue value )
+    {
+        return getClassReference( value );
+    }
+
+    /**
+     * Returns a {@code boolean} indicator whether the specified {@code psiClass} is a side effect.
+     *
+     * @param psiClass class to check.
+     * @return {@code true} if {@code psiClass} is a side effect, {@code false} otherwise.
+     * @since 0.1
+     */
+    public static boolean isASideEffect( @NotNull PsiClass psiClass )
+    {
+        if( psiClass.isInterface() )
+        {
+            return false;
+        }
+
+        PsiClass sideEffectOfClass = getSideEffectOfClass( psiClass );
+        return sideEffectOfClass != null && psiClass.isInheritor( sideEffectOfClass, true );
+    }
+
+    /**
+     * @param psiClass psi class to check.
+     * @return {@code true} if {@code psiClass} inherits {@code GenericSideEffect} class, {@code false} if
+     *         {@code psiClass} does
+     *         not inherit {@code GenericSideEffect} or {@code GenericSideEffect} is not found.
+     * @since 0.1
+     */
+    public static boolean isAGenericSideEffect( @NotNull PsiClass psiClass )
+    {
+        if( psiClass.isInterface() )
+        {
+            return false;
+        }
+
+        PsiClass genericSideEffect = getGenericSideEffectClass( psiClass );
+        return genericSideEffect != null && psiClass.isInheritor( genericSideEffect, true );
+    }
+
+    private PolygeneSideEffectUtil()
+    {
+    }
+}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/sideEffects/inspections/SideEffectsAnnotationDeclaredCorrectlyInspection.java b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/sideEffects/inspections/SideEffectsAnnotationDeclaredCorrectlyInspection.java
new file mode 100644
index 0000000..bf46eb3
--- /dev/null
+++ b/tools/qidea/src/main/java/org/apache/polygene/ide/plugin/idea/sideEffects/inspections/SideEffectsAnnotationDeclaredCorrectlyInspection.java
@@ -0,0 +1,177 @@
+/*
+ *  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.polygene.ide.plugin.idea.sideEffects.inspections;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiAnnotation;
+import com.intellij.psi.PsiAnnotationMemberValue;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiJavaCodeReferenceElement;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
+import org.apache.polygene.ide.plugin.idea.common.inspections.AbstractFix;
+import org.apache.polygene.ide.plugin.idea.common.inspections.AbstractInspection;
+import org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle;
+import org.apache.polygene.ide.plugin.idea.sideEffects.common.PolygeneSideEffectUtil;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
+import static org.apache.polygene.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
+import static org.apache.polygene.ide.plugin.idea.common.resource.PolygeneResourceBundle.message;
+import static org.apache.polygene.ide.plugin.idea.sideEffects.common.PolygeneSideEffectUtil.*;
+
+/**
+ * @author edward.yakop@gmail.com
+ * @since 0.1
+ */
+public final class SideEffectsAnnotationDeclaredCorrectlyInspection extends AbstractInspection
+{
+    @NotNull
+    protected final String resourceBundlePrefixId()
+    {
+        return "side.effects.annotation.declared.correctly";
+    }
+
+    @NotNull
+    public final String getShortName()
+    {
+        return "SideEffectsAnnotationDeclaredCorrectlyInspection";
+    }
+
+    @Override
+    public final ProblemDescriptor[] checkClass( @NotNull PsiClass psiClass,
+                                                 @NotNull InspectionManager manager,
+                                                 boolean isOnTheFly )
+    {
+        // If class does not have @SideEffects, ignore
+        PsiAnnotation sideEffectsAnnotation = getSideEffectsAnnotation( psiClass );
+        if( sideEffectsAnnotation == null )
+        {
+            return null;
+        }
+
+        // If @SideEffects declared in class, suggest remove @SideEffects annotation
+        if( !psiClass.isInterface() )
+        {
+            String message = message( "side.effects.annotation.declared.correctly.error.annotation.declared.in.class" );
+            RemoveSideEffectsAnnotationFix fix = new RemoveSideEffectsAnnotationFix( sideEffectsAnnotation );
+            ProblemDescriptor problemDescriptor = manager.createProblemDescriptor( sideEffectsAnnotation, message, fix,
+                                                                                   GENERIC_ERROR_OR_WARNING );
+            return new ProblemDescriptor[]{ problemDescriptor };
+        }
+
+        // If @SideEffects annotation is empty, ignore
+        List<PsiAnnotationMemberValue> sideEffectsAnnotationValue =
+            getSideEffectsAnnotationValue( sideEffectsAnnotation );
+        if( sideEffectsAnnotationValue.isEmpty() )
+        {
+            return null;
+        }
+
+        // If SideEffectOf is not resolved, ignore
+        Project project = psiClass.getProject();
+        GlobalSearchScope searchScope = determineSearchScope( psiClass );
+        PsiClass sideEffectOfClass = PolygeneSideEffectUtil.getGenericSideEffectClass( project, searchScope );
+        if( sideEffectOfClass == null )
+        {
+            return null;
+        }
+
+        List<ProblemDescriptor> problems = new LinkedList<ProblemDescriptor>();
+        for( PsiAnnotationMemberValue sideEffectClassReferenceWrapper : sideEffectsAnnotationValue )
+        {
+            PsiJavaCodeReferenceElement sideEffectClassReference =
+                getSideEffectClassReference( sideEffectClassReferenceWrapper );
+
+            // If it's not a class reference, ignore
+            if( sideEffectClassReference == null )
+            {
+                continue;
+            }
+
+            // If class reference can't be resolved, ignore
+            PsiClass sideEffectClass = (PsiClass) sideEffectClassReference.resolve();
+            if( sideEffectClass == null )
+            {
+                continue;
+            }
+
+            // If side effect class does not inherit SideEffectOf class, suggest remove that reference.
+            if( !sideEffectClass.isInheritor( sideEffectOfClass, true ) )
+            {
+                String message = PolygeneResourceBundle.message(
+                    "side.effects.annotation.declared.correctly.error.side.effect.does.not.extend.side.effect.of",
+                    sideEffectClass.getQualifiedName()
+                );
+
+                RemoveAnnotationValueFix fix = new RemoveAnnotationValueFix(
+                    sideEffectClassReferenceWrapper, sideEffectClassReference
+                );
+                ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(
+                    sideEffectClassReferenceWrapper, message, fix, GENERIC_ERROR_OR_WARNING );
+                problems.add( problemDescriptor );
+            }
+            else
+            {
+                // TODO: Test whether it is a generic side effect
+                // TODO: Test whether it is a specific side effect
+            }
+        }
+
+        return problems.toArray( new ProblemDescriptor[problems.size()] );
+    }
+
+    private static class RemoveSideEffectsAnnotationFix extends AbstractFix
+    {
+        private final PsiAnnotation sideEffectsAnnotation;
+
+        private RemoveSideEffectsAnnotationFix( @NotNull PsiAnnotation sideEffectsAnnotation )
+        {
+            super( message( "side.effects.annotation.declared.correctly.fix.remove.annotation" ) );
+            this.sideEffectsAnnotation = sideEffectsAnnotation;
+        }
+
+        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
+        {
+            sideEffectsAnnotation.delete();
+        }
+    }
+
+    private static class RemoveAnnotationValueFix extends AbstractFix
+    {
+        private final PsiAnnotationMemberValue annotationValueToRemove;
+
+        private RemoveAnnotationValueFix( @NotNull PsiAnnotationMemberValue annotationValueToRemove,
+                                          @NotNull PsiJavaCodeReferenceElement sideEffectClassReference )
+        {
+            super( message( "side.effects.annotation.declared.correctly.fix.remove.class.reference",
+                            sideEffectClassReference.getQualifiedName() ) );
+            this.annotationValueToRemove = annotationValueToRemove;
+        }
+
+        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
+        {
+            annotationValueToRemove.delete();
+        }
+    }
+}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/Qi4jApplicationComponent.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/Qi4jApplicationComponent.java
deleted file mode 100644
index 8d1c37e..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/Qi4jApplicationComponent.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea;
-
-import com.intellij.codeInspection.InspectionToolProvider;
-import com.intellij.facet.FacetTypeRegistry;
-import com.intellij.ide.fileTemplates.FileTemplateDescriptor;
-import com.intellij.ide.fileTemplates.FileTemplateGroupDescriptor;
-import com.intellij.ide.fileTemplates.FileTemplateGroupDescriptorFactory;
-import com.intellij.openapi.components.ApplicationComponent;
-import com.intellij.openapi.fileTypes.FileTypeManager;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.qi4j.ide.plugin.idea.appliesTo.inspections.AppliesToAnnotationDeclaredCorrectlyInspection;
-import org.qi4j.ide.plugin.idea.common.facet.Qi4jFacetType;
-import org.qi4j.ide.plugin.idea.concerns.inspections.ConcernsAnnotationDeclaredCorrectlyInspection;
-import org.qi4j.ide.plugin.idea.injections.invocation.inspections.InvocationAnnotationDeclaredCorrectlyInspection;
-import org.qi4j.ide.plugin.idea.injections.service.inspections.ServiceAnnotationDeclaredCorrectlyInspection;
-import org.qi4j.ide.plugin.idea.injections.structure.inspections.StructureAnnotationDeclaredCorrectlyInspection;
-import org.qi4j.ide.plugin.idea.mixins.inspections.MixinImplementsMixinType;
-import org.qi4j.ide.plugin.idea.mixins.inspections.MixinsAnnotationDeclaredOnMixinType;
-import org.qi4j.ide.plugin.idea.sideEffects.inspections.SideEffectsAnnotationDeclaredCorrectlyInspection;
-
-import javax.swing.*;
-
-import static org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle.message;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jApplicationComponent
-    implements ApplicationComponent, InspectionToolProvider, FileTemplateGroupDescriptorFactory
-{
-    @NonNls
-    private static String[] FILE_TEMPLATES = {
-        "GenericConcernOf.java"
-    };
-
-    private final Qi4jFacetType qi4jFacetType;
-
-    public Qi4jApplicationComponent()
-    {
-        qi4jFacetType = new Qi4jFacetType();
-    }
-
-    @NotNull
-    public final String getComponentName()
-    {
-        return "Qi4jApplicationComponent";
-    }
-
-    public final void initComponent()
-    {
-        registerFacet();
-        registerIntentions();
-    }
-
-    private void registerFacet()
-    {
-        FacetTypeRegistry facetTypeRegistry = FacetTypeRegistry.getInstance();
-        facetTypeRegistry.registerFacetType( qi4jFacetType );
-    }
-
-    private void registerIntentions()
-    {
-//        IntentionManager intentionManager = IntentionManager.getInstance();
-//        intentionManager.registerIntentionAndMetaData( new AddConcernOnType(), "intention.category.control.flow" );
-    }
-
-    public final void disposeComponent()
-    {
-        unregisterFacet();
-    }
-
-    private void unregisterFacet()
-    {
-        FacetTypeRegistry facetTypeRegistry = FacetTypeRegistry.getInstance();
-        facetTypeRegistry.unregisterFacetType( qi4jFacetType );
-    }
-
-    public final Class[] getInspectionClasses()
-    {
-        return new Class[]{
-            // Concerns
-            ConcernsAnnotationDeclaredCorrectlyInspection.class,
-            // Mixins
-            MixinImplementsMixinType.class,
-            MixinsAnnotationDeclaredOnMixinType.class,
-            // Side effects
-            SideEffectsAnnotationDeclaredCorrectlyInspection.class,
-            // Injections
-            InvocationAnnotationDeclaredCorrectlyInspection.class,
-            ServiceAnnotationDeclaredCorrectlyInspection.class,
-            StructureAnnotationDeclaredCorrectlyInspection.class,
-            // AppliesTo
-            AppliesToAnnotationDeclaredCorrectlyInspection.class
-        };
-    }
-
-    public final FileTemplateGroupDescriptor getFileTemplatesDescriptor()
-    {
-        FileTemplateGroupDescriptor group = new FileTemplateGroupDescriptor(
-            message( "qi4j.file.template.group.title" ), null
-        );
-
-        FileTypeManager fileTypeManager = FileTypeManager.getInstance();
-        for( @NonNls String template : FILE_TEMPLATES )
-        {
-            Icon icon = fileTypeManager.getFileTypeByFileName( template ).getIcon();
-            group.addTemplate( new FileTemplateDescriptor( template, icon ) );
-        }
-
-        return group;
-    }
-
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/appliesTo/common/Qi4jAppliesToConstants.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/appliesTo/common/Qi4jAppliesToConstants.java
deleted file mode 100644
index 32949c5..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/appliesTo/common/Qi4jAppliesToConstants.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.appliesTo.common;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jAppliesToConstants
-{
-    public static final String QUALIFIED_NAME_APPLIES_TO = "org.qi4j.api.common.AppliesTo";
-    public static final String QUALIFIED_NAME_APPLIES_TO_FILTER = "org.qi4j.api.common.AppliesToFilter";
-
-    private Qi4jAppliesToConstants()
-    {
-    }
-}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/appliesTo/common/Qi4jAppliesToUtil.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/appliesTo/common/Qi4jAppliesToUtil.java
deleted file mode 100644
index 3500c6f..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/appliesTo/common/Qi4jAppliesToUtil.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.appliesTo.common;
-
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Collections;
-import java.util.List;
-
-import static com.intellij.codeInsight.AnnotationUtil.findAnnotation;
-import static java.util.Collections.emptyList;
-import static org.qi4j.ide.plugin.idea.appliesTo.common.Qi4jAppliesToConstants.QUALIFIED_NAME_APPLIES_TO;
-import static org.qi4j.ide.plugin.idea.appliesTo.common.Qi4jAppliesToConstants.QUALIFIED_NAME_APPLIES_TO_FILTER;
-import static org.qi4j.ide.plugin.idea.common.psi.PsiAnnotationUtil.getAnnotationDefaultParameterValue;
-import static org.qi4j.ide.plugin.idea.common.psi.PsiAnnotationUtil.getClassReference;
-import static org.qi4j.ide.plugin.idea.common.psi.PsiClassUtil.getPSIClass;
-import static org.qi4j.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jAppliesToUtil
-{
-    /**
-     * @param searchContext Search context.
-     * @return {@code AppliesToFilter} class given the search context. {@code null} if not found.
-     * @since 0.1
-     */
-    @Nullable
-    public static PsiClass getAppliesToFilterClass( @NotNull PsiElement searchContext )
-    {
-        Project project = searchContext.getProject();
-        GlobalSearchScope searchScope = determineSearchScope( searchContext );
-        return getAppliesToFilterClass( project, searchScope );
-    }
-
-    /**
-     * @param project project.
-     * @param scope   search scope.
-     * @return {@code AppliesToFilter} class given {@code project} and {@code scope} parameters.
-     *         Returns {@code null} if not found.
-     * @since 0.1
-     */
-    @Nullable
-    public static PsiClass getAppliesToFilterClass( @NotNull Project project,
-                                                    @Nullable GlobalSearchScope scope )
-    {
-        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( project );
-        return scope == null ? null : psiFacade.findClass( QUALIFIED_NAME_APPLIES_TO_FILTER, scope );
-    }
-
-    /**
-     * @param elementWithinJavaClass element within java class.
-     * @return {@code @AppliesTo} annotation declaration of the class that contains the element.
-     *         Returns {@code null} if not found, or {@code element} is an invalid context.
-     * @since 0.1
-     */
-    @Nullable
-    public static PsiAnnotation getAppliesToAnnotation( @NotNull PsiElement elementWithinJavaClass )
-    {
-        PsiClass psiClass = getPSIClass( elementWithinJavaClass );
-        return findAnnotation( psiClass, QUALIFIED_NAME_APPLIES_TO );
-    }
-
-    /**
-     * @param annotation annotation to process.
-     * @return {@code @AppliesTo} annotation value. Returns {@link Collections#emptyList()} if {@code annotation} is
-     *         {@code null} or annotation is not a {@code @AppliesTo} annotation.
-     * @since 0.1
-     */
-    @NotNull
-    public static List<PsiAnnotationMemberValue> getAppliesToAnnotationValue( @Nullable PsiAnnotation annotation )
-    {
-        if( annotation == null )
-        {
-            return emptyList();
-        }
-
-        String concernsQualifiedName = annotation.getQualifiedName();
-        if( !QUALIFIED_NAME_APPLIES_TO.equals( concernsQualifiedName ) )
-        {
-            return emptyList();
-        }
-
-        return getAnnotationDefaultParameterValue( annotation );
-    }
-
-    /**
-     * @param value annotation member value.
-     * @return Applies to class reference given the {@code value} parameter. Returns {@code null} if it's not a
-     *         class reference.
-     * @since 0.1
-     */
-    @Nullable
-    public static PsiJavaCodeReferenceElement getAppliesToValueClassReference( @NotNull PsiAnnotationMemberValue value )
-    {
-        return getClassReference( value );
-    }
-
-    /**
-     * Returns a {@code boolean} indicator whether the specified {@code psiClass} is implements
-     * {@code AppliesToFilter} class.
-     *
-     * @param psiClass             class to check.
-     * @param appliesToFilterClass {@code AppliesToFilter} class.
-     * @return {@code true} if {@code psiClass} implements {@code AppliesToFilter} class, {@code false} otherwise.
-     * @since 0.1
-     */
-    public static boolean isAnAppliesToFilter( @NotNull PsiClass psiClass, @NotNull PsiClass appliesToFilterClass )
-    {
-        return !psiClass.isInterface() && psiClass.isInheritor( appliesToFilterClass, true );
-    }
-
-    private Qi4jAppliesToUtil()
-    {
-    }
-}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/appliesTo/inspections/AppliesToAnnotationDeclaredCorrectlyInspection.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/appliesTo/inspections/AppliesToAnnotationDeclaredCorrectlyInspection.java
deleted file mode 100644
index e778c68..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/appliesTo/inspections/AppliesToAnnotationDeclaredCorrectlyInspection.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.appliesTo.inspections;
-
-import com.intellij.codeInspection.InspectionManager;
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import org.jetbrains.annotations.NotNull;
-import org.qi4j.ide.plugin.idea.common.inspections.AbstractFix;
-import org.qi4j.ide.plugin.idea.common.inspections.AbstractInspection;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
-import static org.qi4j.ide.plugin.idea.appliesTo.common.Qi4jAppliesToUtil.*;
-import static org.qi4j.ide.plugin.idea.common.psi.PsiClassUtil.isImplementsInvocationHandler;
-import static org.qi4j.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
-import static org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle.message;
-import static org.qi4j.ide.plugin.idea.concerns.common.Qi4jConcernUtil.isAConcern;
-import static org.qi4j.ide.plugin.idea.concerns.common.Qi4jConcernUtil.isAGenericConcern;
-import static org.qi4j.ide.plugin.idea.sideEffects.common.Qi4jSideEffectUtil.isAGenericSideEffect;
-import static org.qi4j.ide.plugin.idea.sideEffects.common.Qi4jSideEffectUtil.isASideEffect;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class AppliesToAnnotationDeclaredCorrectlyInspection extends AbstractInspection
-{
-    @NotNull
-    protected final String resourceBundlePrefixId()
-    {
-        return "applies.to.annotation.declared.correctly";
-    }
-
-    @NotNull
-    public final String getShortName()
-    {
-        return "AppliesToAnnotationDeclaredCorrectlyInspection";
-    }
-
-    @Override
-    public final ProblemDescriptor[] checkClass( @NotNull PsiClass psiClass,
-                                                 @NotNull InspectionManager manager,
-                                                 boolean isOnTheFly )
-    {
-        PsiAnnotation appliesToAnnotation = getAppliesToAnnotation( psiClass );
-        if( appliesToAnnotation == null )
-        {
-            // If class does not have @AppliesTo, ignore
-            return null;
-        }
-
-        String classQualifiedName = psiClass.getQualifiedName();
-        // @AppliesTo can only be declared on class
-        if( psiClass.isInterface() )
-        {
-            // Suggest remove applies to
-            String message = message(
-                "applies.to.annotation.declared.correctly.error.annotation.must.be.declared.on.class"
-            );
-            ProblemDescriptor problemDescriptor = createRemoveAppliesToFilterProblemDescriptor(
-                manager, message, appliesToAnnotation );
-            return new ProblemDescriptor[]{ problemDescriptor };
-        }
-
-        // If @AppliesTo annotation is empty, ignore
-        List<PsiAnnotationMemberValue> appliesToAnnotationValues = getAppliesToAnnotationValue( appliesToAnnotation );
-        if( appliesToAnnotationValues.isEmpty() )
-        {
-            return null;
-        }
-
-        // If AppliesToFilter is not resolved, ignore
-        Project project = psiClass.getProject();
-        GlobalSearchScope searchScope = determineSearchScope( psiClass );
-        PsiClass appliesToFilterClass = getAppliesToFilterClass( project, searchScope );
-        if( appliesToFilterClass == null )
-        {
-            return null;
-        }
-
-        boolean classIsAConcern = isAConcern( psiClass );
-        boolean classIsASideEffect = isASideEffect( psiClass );
-        boolean classIsAGenericConcern = classIsAConcern && isAGenericConcern( psiClass );
-        boolean classIsAGenericSideEffect = classIsASideEffect && isAGenericSideEffect( psiClass );
-        boolean classIsAMixin = !classIsAConcern && !classIsASideEffect;
-        boolean classIsAGenericMixin = classIsAMixin && isImplementsInvocationHandler( psiClass );
-
-        List<ProblemDescriptor> problems = new LinkedList<ProblemDescriptor>();
-        for( PsiAnnotationMemberValue appliesToAnnotationValue : appliesToAnnotationValues )
-        {
-            PsiJavaCodeReferenceElement appliesToValueClassReference =
-                getAppliesToValueClassReference( appliesToAnnotationValue );
-
-            // If it's not a class reference, ignore
-            if( appliesToValueClassReference == null )
-            {
-                continue;
-            }
-
-            // If class reference can't be resolved, ignore
-            PsiClass appliesToValueClass = (PsiClass) appliesToValueClassReference.resolve();
-            if( appliesToValueClass == null )
-            {
-                continue;
-            }
-
-            String appliesToValueQualifiedName = appliesToValueClass.getQualifiedName();
-            boolean appliesToValueIsAnAnnotation = appliesToValueClass.isAnnotationType();
-            boolean appliesToValueIsImplementingAppliesToFilter =
-                appliesToValueClass.isInheritor( appliesToFilterClass, true );
-
-            String message = null;
-            if( appliesToValueIsAnAnnotation && classIsAMixin )
-            {
-                // If Class is a mixin and appliesToValueClass is an annotation
-                message = message(
-                    "applies.to.annotation.declared.correctly.error.value.is.invalid.for.mixin",
-                    appliesToValueQualifiedName
-                );
-            }
-            else if( appliesToValueIsAnAnnotation || appliesToValueIsImplementingAppliesToFilter )
-            {
-                if( classIsAConcern && !classIsAGenericConcern )
-                {
-                    // If psiClass is a concern but not generic concern
-                    message = message(
-                        "applies.to.annotation.declared.correctly.error.value.requires.class.to.extends.GenericConcern",
-                        appliesToValueQualifiedName, classQualifiedName
-                    );
-                }
-                else if( classIsASideEffect && !classIsAGenericSideEffect )
-                {
-                    // If psiClass a side effect but not a generic side effect
-                    message = message(
-                        "applies.to.annotation.declared.correctly.error.value.requires.class.to.extends.GenericSideEffect",
-                        appliesToValueQualifiedName, classQualifiedName
-                    );
-                }
-                else if( appliesToValueIsImplementingAppliesToFilter && !classIsAGenericMixin )
-                {
-                    message = message(
-                        "applies.to.annotation.declared.correctly.error.value.requires.class.to.implements.InvocationHandler",
-                        appliesToValueQualifiedName, classQualifiedName
-                    );
-                }
-            }
-            else if( appliesToValueClass.isInterface() )
-            {
-                if( !psiClass.isInheritor( appliesToValueClass, true ) &&
-                    !( classIsAGenericConcern || classIsAGenericSideEffect ) )
-                {
-                    // If psiClass does not implement that interface and it's not a generic concern or generic side effect
-                    if( classIsAConcern )
-                    {
-                        message = message(
-                            "applies.to.annotation.declared.correctly.error.value.requires.class.to.implement.interface.or.extends.GenericConcern",
-                            appliesToValueQualifiedName, classQualifiedName );
-                    }
-                    else if( classIsASideEffect )
-                    {
-                        message = message(
-                            "applies.to.annotation.declared.correctly.error.value.requires.class.to.implement.interface.or.extends.GenericSideEffect",
-                            appliesToValueQualifiedName, classQualifiedName );
-                    }
-                    else
-                    {
-                        message = message(
-                            "applies.to.annotation.declared.correctly.error.value.requires.class.to.implement.value.interface.or.implements.InvocationHandler",
-                            appliesToValueQualifiedName, classQualifiedName );
-                    }
-                }
-            }
-            else
-            {
-                if( classIsAMixin )
-                {
-                    message = message(
-                        "applies.to.annotation.declared.correctly.error.value.is.invalid.for.mixin",
-                        appliesToValueQualifiedName
-                    );
-                }
-                else
-                {
-                    message = message(
-                        "applies.to.annotation.declared.correctly.error.annotation.value.is.invalid.for.non.mixin",
-                        appliesToValueQualifiedName
-                    );
-                }
-            }
-
-            if( message != null )
-            {
-                ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(
-                    appliesToAnnotationValue,
-                    message,
-                    new RemoveAnnotationValueFix( appliesToAnnotationValue, appliesToValueClassReference ),
-                    GENERIC_ERROR_OR_WARNING );
-                problems.add( problemDescriptor );
-            }
-        }
-
-        return problems.toArray( new ProblemDescriptor[problems.size()] );
-    }
-
-    @NotNull
-    private ProblemDescriptor createRemoveAppliesToFilterProblemDescriptor( @NotNull InspectionManager manager,
-                                                                            @NotNull String problemMessage,
-                                                                            @NotNull PsiAnnotation appliesToAnnotation )
-    {
-        RemoveAppliesToFilterAnnotationFix fix = new RemoveAppliesToFilterAnnotationFix( appliesToAnnotation );
-        return manager.createProblemDescriptor( appliesToAnnotation, problemMessage, fix, GENERIC_ERROR_OR_WARNING );
-    }
-
-    private static class RemoveAppliesToFilterAnnotationFix extends AbstractFix
-    {
-        private final PsiAnnotation appliesToFilterAnnotation;
-
-        private RemoveAppliesToFilterAnnotationFix( @NotNull PsiAnnotation appliesToFilterAnnotation )
-        {
-            super( message( "applies.to.annotation.declared.correctly.fix.remove.annotation" ) );
-            this.appliesToFilterAnnotation = appliesToFilterAnnotation;
-        }
-
-        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
-        {
-            appliesToFilterAnnotation.delete();
-        }
-    }
-
-    private static class RemoveAnnotationValueFix extends AbstractFix
-    {
-        private final PsiAnnotationMemberValue annotationValueToRemove;
-
-        private RemoveAnnotationValueFix( @NotNull PsiAnnotationMemberValue annotationValueToRemove,
-                                          @NotNull PsiJavaCodeReferenceElement appliesToValueClassReference )
-        {
-            super( message( "applies.to.annotation.declared.correctly.fix.remove.class.reference",
-                            appliesToValueClassReference.getQualifiedName() ) );
-            this.annotationValueToRemove = annotationValueToRemove;
-        }
-
-        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
-        {
-            annotationValueToRemove.delete();
-        }
-    }
-
-    private static class ClassImplementInterfaceFix extends AbstractFix
-    {
-        private final PsiClass psiClass;
-        private final PsiClass interfaceToImplement;
-
-        private ClassImplementInterfaceFix( @NotNull PsiClass psiClass,
-                                            @NotNull PsiClass interfaceToImplement )
-        {
-            super( message( "applies.to.annotation.declared.correctly.fix.remove.class.reference",
-                            interfaceToImplement.getQualifiedName() ) );
-            this.psiClass = psiClass;
-            this.interfaceToImplement = interfaceToImplement;
-        }
-
-        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
-        {
-            PsiReferenceList implementList = psiClass.getImplementsList();
-            if( implementList != null )
-            {
-
-                implementList.add( interfaceToImplement );
-            }
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/actions/AbstractCreateElementActionBase.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/actions/AbstractCreateElementActionBase.java
deleted file mode 100644
index 874fee9..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/actions/AbstractCreateElementActionBase.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.common.actions;
-
-import com.intellij.CommonBundle;
-import com.intellij.ide.actions.CreateElementActionBase;
-import com.intellij.ide.fileTemplates.FileTemplate;
-import com.intellij.ide.fileTemplates.FileTemplateManager;
-import com.intellij.ide.fileTemplates.JavaTemplateUtil;
-import com.intellij.openapi.fileTypes.StdFileTypes;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtil;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.psi.*;
-import com.intellij.psi.codeStyle.CodeStyleManager;
-import com.intellij.util.IncorrectOperationException;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Properties;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public abstract class AbstractCreateElementActionBase extends CreateElementActionBase
-{
-    @NonNls
-    private static final String NAME_TEMPLATE_PROPERTY = "NAME";
-
-    protected AbstractCreateElementActionBase( String text, String description )
-    {
-        super( text, description, null );
-    }
-
-    @NotNull
-    protected final PsiElement[] invokeDialog( Project project, PsiDirectory directory )
-    {
-        Module module = ModuleUtil.findModuleForFile( directory.getVirtualFile(), project );
-        if( module == null )
-        {
-            return PsiElement.EMPTY_ARRAY;
-        }
-
-        MyInputValidator validator = doInvokeDialog( project, directory );
-        return validator.getCreatedElements();
-    }
-
-    protected MyInputValidator doInvokeDialog( Project project, PsiDirectory directory )
-    {
-        MyInputValidator validator = new MyInputValidator( project, directory );
-        Messages.showInputDialog( project, getDialogPrompt(), getDialogTitle(), Messages.getQuestionIcon(), "", validator );
-        return validator;
-    }
-
-    /**
-     * @return Dialog prompt.
-     */
-    protected abstract String getDialogPrompt();
-
-    /**
-     * @return Dialog title.
-     */
-    protected abstract String getDialogTitle();
-
-    protected String getErrorTitle()
-    {
-        return CommonBundle.getErrorTitle();
-    }
-
-    protected final void checkBeforeCreate( String newName, PsiDirectory directory )
-        throws IncorrectOperationException
-    {
-        JavaDirectoryService javaDirectoryService = JavaDirectoryService.getInstance();
-        javaDirectoryService.checkCreateClass( directory, newName );
-    }
-
-    protected static PsiClass createClassFromTemplate( @NotNull PsiDirectory directory,
-                                                       @NotNull String className,
-                                                       @NotNull String templateName,
-                                                       @NonNls String... parameters )
-        throws IncorrectOperationException
-    {
-        String classFileName = className + "." + StdFileTypes.JAVA.getDefaultExtension();
-        PsiFile file = createFromTemplateInternal( directory, className, classFileName, templateName, parameters );
-        return ( (PsiJavaFile) file ).getClasses()[ 0 ];
-    }
-
-    protected static PsiFile createFromTemplateInternal( @NotNull PsiDirectory directory,
-                                                         @NotNull String name,
-                                                         @NotNull String fileName,
-                                                         @NotNull String templateName,
-                                                         @NonNls String... parameters )
-        throws IncorrectOperationException
-    {
-        // Load template
-        FileTemplateManager fileTemplateManager = FileTemplateManager.getInstance();
-        FileTemplate template = fileTemplateManager.getJ2eeTemplate( templateName );
-
-        // Process template properties
-        Properties properties = new Properties( fileTemplateManager.getDefaultProperties() );
-        JavaTemplateUtil.setPackageNameAttribute( properties, directory );
-        properties.setProperty( NAME_TEMPLATE_PROPERTY, name );
-
-        // Add parameters
-        for( int i = 0; i < parameters.length; i += 2 )
-        {
-            properties.setProperty( parameters[ i ], parameters[ i + 1 ] );
-        }
-
-        // Create text from template with specified properties
-        String text;
-        try
-        {
-            text = template.getText( properties );
-        }
-        catch( Exception e )
-        {
-            String message = "Unable to load template for " +
-                             fileTemplateManager.internalTemplateToSubject( templateName );
-            throw new RuntimeException( message, e );
-        }
-
-        // Serialized text to file
-        PsiManager psiManager = PsiManager.getInstance( directory.getProject() );
-        PsiFileFactory fileFactory = PsiFileFactory.getInstance( directory.getProject() );
-        PsiFile file = fileFactory.createFileFromText( fileName, text );
-
-        // Reformat the file according to project/default style
-        CodeStyleManager codeStyleManager = CodeStyleManager.getInstance( psiManager );
-        codeStyleManager.reformat( file );
-
-        // Add newly created file to directory
-        return (PsiFile) directory.add( file );
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/actions/Qi4jCreateActionGroup.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/actions/Qi4jCreateActionGroup.java
deleted file mode 100644
index 3b141a3..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/actions/Qi4jCreateActionGroup.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.common.actions;
-
-import com.intellij.ide.IdeView;
-import com.intellij.openapi.actionSystem.*;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ProjectFileIndex;
-import com.intellij.openapi.roots.ProjectRootManager;
-import com.intellij.psi.JavaDirectoryService;
-import com.intellij.psi.PsiDirectory;
-
-import static org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle.message;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jCreateActionGroup extends DefaultActionGroup
-{
-    public Qi4jCreateActionGroup()
-    {
-        super( message( "qi4j.action.group.title" ), true );
-        getTemplatePresentation().setDescription( message( "qi4j.action.group.description" ) );
-    }
-
-    public void update( AnActionEvent e )
-    {
-        Presentation presentation = e.getPresentation();
-        presentation.setVisible( shouldActionGroupVisible( e ) );
-    }
-
-    private boolean shouldActionGroupVisible( AnActionEvent e )
-    {
-        Module module = e.getData( LangDataKeys.MODULE );
-        if( module == null )
-        {
-            return false;
-        }
-
-        // TODO: Enable this once Qi4jFacet can be automatically added/removed
-//        if( Qi4jFacet.getInstance( module ) == null )
-//        {
-//            return false;
-//        }
-
-        // Are we on IDE View and under project source folder?
-        Project project = e.getData( PlatformDataKeys.PROJECT );
-        IdeView view = e.getData( LangDataKeys.IDE_VIEW );
-        if( view != null && project != null )
-        {
-            ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance( project ).getFileIndex();
-            PsiDirectory[] dirs = view.getDirectories();
-            for( PsiDirectory dir : dirs )
-            {
-                if( projectFileIndex.isInSourceContent( dir.getVirtualFile() ) && JavaDirectoryService.getInstance().getPackage( dir ) != null )
-                {
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/facet/Qi4jFacet.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/facet/Qi4jFacet.java
deleted file mode 100644
index d03dcb0..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/facet/Qi4jFacet.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.common.facet;
-
-import com.intellij.facet.Facet;
-import com.intellij.facet.FacetManager;
-import com.intellij.facet.FacetType;
-import com.intellij.openapi.module.Module;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jFacet extends Facet<Qi4jFacetConfiguration>
-{
-    public Qi4jFacet( @NotNull FacetType facetType,
-                      @NotNull Module module,
-                      String name,
-                      @NotNull Qi4jFacetConfiguration configuration,
-                      Facet underlyingFacet )
-    {
-        super( facetType, module, name, configuration, underlyingFacet );
-    }
-
-    @Nullable
-    public static Qi4jFacet getInstance( @NotNull Module module )
-    {
-        return FacetManager.getInstance( module ).getFacetByType( Qi4jFacetType.ID );
-    }
-
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/facet/Qi4jFacetConfiguration.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/facet/Qi4jFacetConfiguration.java
deleted file mode 100644
index d3172c7..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/facet/Qi4jFacetConfiguration.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.common.facet;
-
-import com.intellij.facet.FacetConfiguration;
-import com.intellij.facet.ui.FacetEditorContext;
-import com.intellij.facet.ui.FacetEditorTab;
-import com.intellij.facet.ui.FacetValidatorsManager;
-import com.intellij.openapi.util.InvalidDataException;
-import com.intellij.openapi.util.WriteExternalException;
-import org.jdom.Element;
-import org.qi4j.ide.plugin.idea.common.facet.ui.Qi4jFacetEditorTab;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jFacetConfiguration
-    implements FacetConfiguration
-{
-    public FacetEditorTab[] createEditorTabs( FacetEditorContext editorContext,
-                                              FacetValidatorsManager validatorsManager )
-    {
-        return new FacetEditorTab[]{
-            new Qi4jFacetEditorTab( editorContext )
-        };
-    }
-
-    public final void readExternal( Element element )
-        throws InvalidDataException
-    {
-        // Do nothing
-    }
-
-    public final void writeExternal( Element element )
-        throws WriteExternalException
-    {
-        // Do nothing
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/facet/Qi4jFacetType.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/facet/Qi4jFacetType.java
deleted file mode 100644
index a90ecec..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/facet/Qi4jFacetType.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.common.facet;
-
-import com.intellij.facet.Facet;
-import com.intellij.facet.FacetType;
-import com.intellij.facet.FacetTypeId;
-import com.intellij.facet.autodetecting.FacetDetector;
-import com.intellij.facet.autodetecting.FacetDetectorRegistry;
-import com.intellij.openapi.fileTypes.StdFileTypes;
-import com.intellij.openapi.module.JavaModuleType;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleType;
-import com.intellij.openapi.util.Condition;
-import com.intellij.openapi.vfs.VirtualFileFilter;
-import com.intellij.psi.JavaElementVisitor;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiImportStatement;
-import com.intellij.psi.PsiReferenceExpression;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Collection;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jFacetType extends FacetType<Qi4jFacet, Qi4jFacetConfiguration>
-{
-    public static final FacetTypeId<Qi4jFacet> ID = new FacetTypeId<Qi4jFacet>();
-
-    public Qi4jFacetType()
-    {
-        super( ID, "Qi4jFacet", "Zest Facet" );
-    }
-
-    public final Qi4jFacetConfiguration createDefaultConfiguration()
-    {
-        return new Qi4jFacetConfiguration();
-    }
-
-    public final Qi4jFacet createFacet( @NotNull Module module,
-                                        String name,
-                                        @NotNull Qi4jFacetConfiguration configuration,
-                                        @Nullable Facet underlyingFacet )
-    {
-        return new Qi4jFacet( this, module, name, configuration, underlyingFacet );
-    }
-
-    public final boolean isSuitableModuleType( ModuleType moduleType )
-    {
-        return moduleType instanceof JavaModuleType;
-    }
-
-    @Override
-    public final void registerDetectors( FacetDetectorRegistry<Qi4jFacetConfiguration> registry )
-    {
-        registry.registerOnTheFlyDetector(
-            StdFileTypes.JAVA, VirtualFileFilter.ALL, new HasQi4jImportPackageCondition(),
-            new FacetDetector<PsiFile, Qi4jFacetConfiguration>( "Qi4jFacetDetector" )
-            {
-                @Override
-                public Qi4jFacetConfiguration detectFacet( PsiFile source,
-                                                           Collection<Qi4jFacetConfiguration> existingConfigurations )
-                {
-                    if( !existingConfigurations.isEmpty() )
-                    {
-                        return existingConfigurations.iterator().next();
-                    }
-
-                    return createDefaultConfiguration();
-                }
-            }
-        );
-    }
-
-    private static class HasQi4jImportPackageCondition
-        implements Condition<PsiFile>
-    {
-        public final boolean value( PsiFile psiFile )
-        {
-            final boolean[] hasQi4jImportPackage = new boolean[]{ false };
-
-            psiFile.accept( new JavaElementVisitor()
-            {
-                @Override
-                public final void visitImportStatement( PsiImportStatement statement )
-                {
-                    String packageName = statement.getQualifiedName();
-                    if( packageName != null && packageName.startsWith( "org.qi4j" ) )
-                    {
-                        hasQi4jImportPackage[ 0 ] = true;
-                    }
-                }
-
-                @Override
-                public void visitReferenceExpression( PsiReferenceExpression expression )
-                {
-                    // Ignore
-                }
-            } );
-            return hasQi4jImportPackage[ 0 ];
-        }
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/facet/ui/Qi4jFacetEditorTab.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/facet/ui/Qi4jFacetEditorTab.java
deleted file mode 100644
index de96adf..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/facet/ui/Qi4jFacetEditorTab.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.common.facet.ui;
-
-import com.intellij.facet.ui.FacetEditorContext;
-import com.intellij.facet.ui.FacetEditorTab;
-import com.intellij.openapi.options.ConfigurationException;
-import org.jetbrains.annotations.Nls;
-
-import javax.swing.*;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jFacetEditorTab extends FacetEditorTab
-{
-    private final FacetEditorContext editorContext;
-
-    public Qi4jFacetEditorTab( FacetEditorContext aContext )
-    {
-        editorContext = aContext;
-    }
-
-    @Nls
-    public final String getDisplayName()
-    {
-        return "Zest";
-    }
-
-    public JComponent createComponent()
-    {
-        return new JPanel();
-    }
-
-    public final boolean isModified()
-    {
-        return false;
-    }
-
-    public final void apply()
-        throws ConfigurationException
-    {
-        // From UI to configuration
-    }
-
-    public final void reset()
-    {
-        // From Configuration to UI
-    }
-
-    public final void disposeUIResources()
-    {
-        // Do nothing for now
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/inspections/AbstractFix.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/inspections/AbstractFix.java
deleted file mode 100644
index 879cca1..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/inspections/AbstractFix.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.common.inspections;
-
-import com.intellij.codeInspection.LocalQuickFix;
-import org.jetbrains.annotations.NotNull;
-
-import static org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle.message;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public abstract class AbstractFix
-    implements LocalQuickFix
-{
-    private String fixName;
-
-    protected AbstractFix( @NotNull String name )
-    {
-        fixName = name;
-    }
-
-    @NotNull
-    public final String getName()
-    {
-        return fixName;
-    }
-
-    @NotNull
-    public final String getFamilyName()
-    {
-        return message( "qi4j.quick.fixes.family.name" );
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/inspections/AbstractInspection.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/inspections/AbstractInspection.java
deleted file mode 100644
index c268ce1..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/inspections/AbstractInspection.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.common.inspections;
-
-import com.intellij.codeHighlighting.HighlightDisplayLevel;
-import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
-import org.jetbrains.annotations.Nls;
-import org.jetbrains.annotations.NotNull;
-import org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle;
-
-import static com.intellij.codeHighlighting.HighlightDisplayLevel.ERROR;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public abstract class AbstractInspection extends BaseJavaLocalInspectionTool
-{
-    private static final String QI4J_IDEA_INSPECTIONS_NAME = "qi4j.inspections.name";
-
-    @Nls @NotNull public String getGroupDisplayName()
-    {
-        return Qi4jResourceBundle.message( QI4J_IDEA_INSPECTIONS_NAME );
-    }
-
-    @NotNull
-    protected abstract String resourceBundlePrefixId();
-
-    @Nls @NotNull
-    public final String getDisplayName()
-    {
-        return Qi4jResourceBundle.message( resourceBundlePrefixId() + ".name.display" );
-    }
-
-    @NotNull @Override
-    public HighlightDisplayLevel getDefaultLevel()
-    {
-        return ERROR;
-    }
-
-    @Override
-    public boolean isEnabledByDefault()
-    {
-        return true;
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/intentions/AbstractIntention.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/intentions/AbstractIntention.java
deleted file mode 100644
index c66bc9f..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/intentions/AbstractIntention.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.common.intentions;
-
-import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
-import com.intellij.openapi.editor.CaretModel;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.ReadonlyStatusHandler;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.util.IncorrectOperationException;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import static org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle.message;
-
-/**
- * This class is based from {@code com.siyeh.ipp.base.Intention}
- *
- * @author edward.yakop@gmail.com
- */
-public abstract class AbstractIntention extends PsiElementBaseIntentionAction
-{
-    protected abstract boolean isIntentionValidFor( PsiElement element );
-
-    protected abstract String resourceBundlePrefixId();
-
-    /**
-     * Implement this method to process intention.
-     *
-     * @param project The project in which the availability is checked.
-     * @param editor  The editor in which the intention will be invoked.
-     * @param element The element under caret.
-     */
-    protected abstract void processIntention( @NotNull Project project,
-                                              @NotNull Editor editor,
-                                              @NotNull PsiElement element );
-
-    public void invoke( @NotNull Project project, Editor editor, PsiFile file )
-        throws IncorrectOperationException
-    {
-        if( isFileReadOnly( project, file ) )
-        {
-            return;
-        }
-
-        final PsiElement element = findMatchingElement( file, editor );
-        if( element == null )
-        {
-            return;
-        }
-
-        processIntention( project, editor, element );
-    }
-
-    protected static boolean isFileReadOnly( @NotNull Project project, @NotNull PsiFile file )
-    {
-        VirtualFile virtualFile = file.getVirtualFile();
-        ReadonlyStatusHandler readonlyStatusHandler = ReadonlyStatusHandler.getInstance( project );
-        ReadonlyStatusHandler.OperationStatus operationStatus =
-            readonlyStatusHandler.ensureFilesWritable( virtualFile );
-        return operationStatus.hasReadonlyFiles();
-    }
-
-    @Nullable
-    private PsiElement findMatchingElement( @NotNull PsiFile file, @NotNull Editor editor )
-    {
-        CaretModel caretModel = editor.getCaretModel();
-        int position = caretModel.getOffset();
-        PsiElement element = file.findElementAt( position );
-        return findMatchingElement( element );
-    }
-
-    @Nullable
-    private PsiElement findMatchingElement( @Nullable PsiElement element )
-    {
-        while( element != null )
-        {
-            if( isIntentionValidFor( element ) )
-            {
-                return element;
-            }
-            else
-            {
-                element = element.getParent();
-                if( element instanceof PsiFile )
-                {
-                    break;
-                }
-            }
-        }
-
-        return null;
-    }
-
-    @Override
-    public boolean isAvailable( @NotNull Project project, Editor editor, @Nullable PsiElement element )
-    {
-        return isIntentionValidFor( element );
-    }
-
-    @NotNull
-    public final String getFamilyName()
-    {
-        return message( resourceBundlePrefixId() + ".family.name" );
-    }
-
-    @NotNull
-    @Override
-    public final String getText()
-    {
-        return message( resourceBundlePrefixId() + ".name" );
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/psi/PsiAnnotationUtil.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/psi/PsiAnnotationUtil.java
deleted file mode 100644
index c8006f2..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/psi/PsiAnnotationUtil.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.common.psi;
-
-import com.intellij.psi.*;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import static java.util.Collections.emptyList;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public class PsiAnnotationUtil
-{
-    @NotNull
-    public static List<PsiAnnotationMemberValue> getAnnotationDefaultParameterValue( @Nullable PsiAnnotation annotation )
-    {
-        if( annotation == null )
-        {
-            return emptyList();
-        }
-
-        List<PsiAnnotationMemberValue> defaultParameterValues = new LinkedList<PsiAnnotationMemberValue>();
-
-        PsiAnnotationParameterList list = annotation.getParameterList();
-        PsiNameValuePair[] attributes = list.getAttributes();
-        for( PsiNameValuePair valuePair : attributes )
-        {
-            String parameterName = valuePair.getName();
-            if( parameterName == null || PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.equals( parameterName ) )
-            {
-                PsiAnnotationMemberValue value = valuePair.getValue();
-                if( value == null )
-                {
-                    continue;
-                }
-
-                if( value instanceof PsiArrayInitializerMemberValue )
-                {
-                    // If It's an array
-                    PsiArrayInitializerMemberValue valueWrapper = (PsiArrayInitializerMemberValue) value;
-                    PsiAnnotationMemberValue[] values = valueWrapper.getInitializers();
-                    for( PsiAnnotationMemberValue psiAnnotationMemberValue : values )
-                    {
-                        if( psiAnnotationMemberValue != null )
-                        {
-                            defaultParameterValues.add( psiAnnotationMemberValue );
-                        }
-                    }
-                }
-                else
-                {
-                    // If there's only one value
-                    defaultParameterValues.add( value );
-                }
-
-                break;
-            }
-        }
-
-        return defaultParameterValues;
-    }
-
-    @Nullable
-    public static PsiJavaCodeReferenceElement getClassReference( @NotNull PsiAnnotationMemberValue value )
-    {
-        if( value instanceof PsiClassObjectAccessExpression )
-        {
-            PsiClassObjectAccessExpression objectAccessExpression = (PsiClassObjectAccessExpression) value;
-            PsiTypeElement typeElement = objectAccessExpression.getOperand();
-            return typeElement.getInnermostComponentReferenceElement();
-        }
-
-        return null;
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/psi/PsiClassUtil.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/psi/PsiClassUtil.java
deleted file mode 100644
index 685954a..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/psi/PsiClassUtil.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.common.psi;
-
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.lang.reflect.InvocationHandler;
-import java.util.HashSet;
-import java.util.Set;
-
-import static org.qi4j.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class PsiClassUtil
-{
-    @Nullable
-    public static PsiClass getPSIClass( @NotNull PsiElement element )
-    {
-        if( element instanceof PsiClass )
-        {
-            return (PsiClass) element;
-        }
-
-        if( element instanceof PsiTypeElement )
-        {
-            PsiTypeElement psiTypeElement = (PsiTypeElement) element;
-            PsiJavaCodeReferenceElement componentRef = psiTypeElement.getInnermostComponentReferenceElement();
-            if( componentRef == null )
-            {
-                return null;
-            }
-
-            return (PsiClass) componentRef.resolve();
-        }
-
-        PsiElement context = element.getContext();
-        if( context instanceof PsiClass )
-        {
-            return (PsiClass) context;
-        }
-
-        return null;
-    }
-
-    @NotNull
-    public static Set<PsiClass> getExtends( @NotNull PsiClass psiClass )
-    {
-        HashSet<PsiClass> extendsClasses = new HashSet<PsiClass>();
-        PsiClassType[] extendsClassTypes = psiClass.getExtendsListTypes();
-        for( PsiClassType extendClassType : extendsClassTypes )
-        {
-            PsiClass extendClass = extendClassType.resolve();
-            if( extendClass != null )
-            {
-                extendsClasses.add( extendClass );
-            }
-        }
-
-        return extendsClasses;
-    }
-
-    /**
-     * Returns all extends of the specified {@code psiClass}.
-     *
-     * @param psiClass class to process.
-     * @return all extends of the specified {@code psiClass}.
-     * @since 0.1
-     */
-    @NotNull
-    public static Set<PsiClass> getExtendsDeep( @NotNull PsiClass psiClass )
-    {
-        HashSet<PsiClass> extendsClasses = new HashSet<PsiClass>();
-        PsiClassType[] extendsClassTypes = psiClass.getExtendsListTypes();
-        for( PsiClassType extendClassType : extendsClassTypes )
-        {
-            PsiClass extendClass = extendClassType.resolve();
-            if( extendClass != null )
-            {
-                extendsClasses.add( extendClass );
-                extendsClasses.addAll( getExtendsDeep( extendClass ) );
-            }
-        }
-
-        return extendsClasses;
-    }
-
-    /**
-     * @param psiClass Psi class to check.
-     * @return {@code true} if psi class implements {@code InvocationHandler}, {@code false} otherwise.
-     * @see InvocationHandler
-     */
-    public static boolean isImplementsInvocationHandler( @NotNull PsiClass psiClass )
-    {
-        if( psiClass.isInterface() )
-        {
-            return false;
-        }
-
-        GlobalSearchScope searchScope = determineSearchScope( psiClass );
-        assert searchScope != null;
-
-        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( psiClass.getProject() );
-        PsiClass invocationHandler = psiFacade.findClass( "java.lang.reflect.InvocationHandler", searchScope );
-        assert invocationHandler != null;
-
-        return psiClass.isInheritor( invocationHandler, true );
-    }
-
-    private PsiClassUtil()
-    {
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/psi/search/GlobalSearchScopeUtil.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/psi/search/GlobalSearchScopeUtil.java
deleted file mode 100644
index f0437e2..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/psi/search/GlobalSearchScopeUtil.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.common.psi.search;
-
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ProjectRootManager;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.search.GlobalSearchScope;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import static com.intellij.openapi.module.ModuleUtil.findModuleForPsiElement;
-import static org.qi4j.ide.plugin.idea.common.vfs.VirtualFileUtil.getVirtualFile;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public class GlobalSearchScopeUtil
-{
-    /**
-     * Determine search scope given a psi element.
-     *
-     * @param psiElement context.
-     * @return Search scope given psi class.
-     * @since 0.1
-     */
-    @Nullable
-    public static GlobalSearchScope determineSearchScope( @NotNull PsiElement psiElement )
-    {
-        VirtualFile classVirtualFile = getVirtualFile( psiElement );
-        if( classVirtualFile == null )
-        {
-            return null;
-        }
-
-        Module module = findModuleForPsiElement( psiElement );
-        if( module == null )
-        {
-            return null;
-        }
-
-        Project project = psiElement.getProject();
-        ProjectRootManager projectRootManager = ProjectRootManager.getInstance( project );
-        boolean includeTestClasses = projectRootManager.getFileIndex().isInTestSourceContent( classVirtualFile );
-        return module.getModuleWithDependenciesAndLibrariesScope( includeTestClasses );
-    }
-
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/resource/Qi4jResourceBundle.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/resource/Qi4jResourceBundle.java
deleted file mode 100644
index 6827b23..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/resource/Qi4jResourceBundle.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.common.resource;
-
-import com.intellij.CommonBundle;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.PropertyKey;
-
-import java.lang.ref.Reference;
-import java.lang.ref.SoftReference;
-import java.util.ResourceBundle;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jResourceBundle
-{
-
-    @NonNls
-    private static final String RESOURCE_BUNDLE_NAME = "org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle";
-
-    private static Reference<ResourceBundle> BUNDLE_REF;
-
-    private Qi4jResourceBundle()
-    {
-    }
-
-    public static String message( @PropertyKey( resourceBundle = RESOURCE_BUNDLE_NAME ) String key,
-                                  Object... params )
-    {
-        ResourceBundle resourceBundle = getBundle();
-        return CommonBundle.message( resourceBundle, key, params );
-    }
-
-    private static ResourceBundle getBundle()
-    {
-        ResourceBundle bundle = null;
-        if( BUNDLE_REF != null )
-        {
-            bundle = BUNDLE_REF.get();
-        }
-
-        if( bundle == null )
-        {
-            bundle = ResourceBundle.getBundle( Qi4jResourceBundle.class.getName() );
-            BUNDLE_REF = new SoftReference<ResourceBundle>( bundle );
-        }
-
-        return bundle;
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/vfs/VirtualFileUtil.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/vfs/VirtualFileUtil.java
deleted file mode 100644
index 53b3bc4..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/common/vfs/VirtualFileUtil.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.common.vfs;
-
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiFileSystemItem;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class VirtualFileUtil
-{
-    /**
-     * @param element element to process.
-     * @return The containing virtual file of the element.
-     * @since 0.1
-     */
-    @Nullable
-    public static VirtualFile getVirtualFile( @NotNull PsiElement element )
-    {
-        if( element instanceof PsiFileSystemItem )
-        {
-            PsiFileSystemItem fileSystemItem = (PsiFileSystemItem) element;
-            return fileSystemItem.getVirtualFile();
-        }
-
-        // If it's not a file system, assume that this is an element within a file
-        PsiFile containingFile = element.getContainingFile();
-        if( containingFile == null )
-        {
-            return null;
-        }
-
-        VirtualFile virtualFile = containingFile.getVirtualFile();
-        if( virtualFile != null )
-        {
-            return virtualFile;
-        }
-
-        PsiFile originalFile = containingFile.getOriginalFile();
-        if( originalFile == null )
-        {
-            return null;
-        }
-
-        return originalFile.getVirtualFile();
-    }
-
-    private VirtualFileUtil()
-    {
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/actions/create/CreateConcernFromMixinTypeOrCompositeAction.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/actions/create/CreateConcernFromMixinTypeOrCompositeAction.java
deleted file mode 100644
index b762e3b..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/actions/create/CreateConcernFromMixinTypeOrCompositeAction.java
+++ /dev/null
@@ -1,62 +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.qi4j.ide.plugin.idea.concerns.actions.create;
-
-import com.intellij.psi.PsiDirectory;
-import com.intellij.psi.PsiElement;
-import org.jetbrains.annotations.NotNull;
-import org.qi4j.ide.plugin.idea.common.actions.AbstractCreateElementActionBase;
-
-/**
- * @author edward.yakop@gmail.com
- */
-public class CreateConcernFromMixinTypeOrCompositeAction extends AbstractCreateElementActionBase
-{
-    public CreateConcernFromMixinTypeOrCompositeAction()
-    {
-        super( "TODO", "TODO" );
-    }
-
-    protected String getCommandName()
-    {
-        return "CreateConcernFromMixinTypeOrCompositeAction";
-    }
-
-    protected String getActionName( PsiDirectory directory, String newName )
-    {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    protected String getDialogPrompt()
-    {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    protected String getDialogTitle()
-    {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
-    }
-
-    @NotNull
-    protected PsiElement[] create( String newName, PsiDirectory directory )
-        throws Exception
-    {
-        return new PsiElement[0];  //To change body of implemented methods use File | Settings | File Templates.
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/actions/create/inPackage/CreateConcernOfInPackageAction.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/actions/create/inPackage/CreateConcernOfInPackageAction.java
deleted file mode 100644
index a82dc07..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/actions/create/inPackage/CreateConcernOfInPackageAction.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.concerns.actions.create.inPackage;
-
-import com.intellij.ide.actions.CreateInPackageActionBase;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.psi.JavaDirectoryService;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiDirectory;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.util.IncorrectOperationException;
-import org.jetbrains.annotations.NotNull;
-
-import static com.intellij.openapi.actionSystem.DataKeys.PROJECT;
-import static com.intellij.openapi.actionSystem.DataKeys.PSI_ELEMENT;
-import static com.intellij.util.Icons.CLASS_ICON;
-import static org.qi4j.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
-import static org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle.message;
-import static org.qi4j.ide.plugin.idea.concerns.common.Qi4jConcernConstants.TEMPLATE_GENERIC_CONCERN_OF;
-import static org.qi4j.ide.plugin.idea.concerns.common.Qi4jConcernUtil.getConcernOfClass;
-
-/**
- * JAVADOC: Non generic concern
- *
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public class CreateConcernOfInPackageAction extends CreateInPackageActionBase
-{
-    protected CreateConcernOfInPackageAction()
-    {
-        super( message( "createConcernOfInPackage.menu.action.text" ),
-               message( "createConcernOfInPackage.menu.action.description" ),
-               CLASS_ICON );
-    }
-
-    @Override
-    protected final boolean isAvailable( DataContext dataContext )
-    {
-        boolean isAvailable = super.isAvailable( dataContext );
-        if( !isAvailable )
-        {
-            return false;
-        }
-
-        PsiElement psiElement = PSI_ELEMENT.getData( dataContext );
-        if( psiElement == null )
-        {
-            return false;
-        }
-
-        GlobalSearchScope searchScope = determineSearchScope( psiElement );
-        if( searchScope == null )
-        {
-            return false;
-        }
-
-        Project project = PROJECT.getData( dataContext );
-        PsiClass psiClass = getConcernOfClass( project, searchScope );
-        return psiClass != null;
-    }
-
-    @NotNull
-    protected final PsiElement[] invokeDialog( Project project, PsiDirectory directory )
-    {
-        MyInputValidator validator = new MyInputValidator( project, directory );
-        Messages.showInputDialog( project, message( "createConcernOfInPackage.dlg.prompt" ),
-                                  message( "createConcernOfInPackage.dlg.title" ),
-                                  Messages.getQuestionIcon(), "", validator );
-        return validator.getCreatedElements();
-    }
-
-    protected final String getCommandName()
-    {
-        return message( "createConcernOfInPackage.command.name" );
-    }
-
-    protected final String getErrorTitle()
-    {
-        return message( "createConcernOfInPackage.error.title" );
-    }
-
-    protected final String getActionName( PsiDirectory directory, String newName )
-    {
-        return message( "createConcernOfInPackage.progress.text", newName );
-    }
-
-    protected final void doCheckCreate( final PsiDirectory dir, final String className )
-        throws IncorrectOperationException
-    {
-        JavaDirectoryService javaDirectoryService = JavaDirectoryService.getInstance();
-        javaDirectoryService.checkCreateClass( dir, className );
-    }
-
-    @NotNull
-    protected PsiClass doCreate( final PsiDirectory dir, final String className )
-        throws IncorrectOperationException
-    {
-        JavaDirectoryService javaDirectoryService = JavaDirectoryService.getInstance();
-        return javaDirectoryService.createClass( dir, className, TEMPLATE_GENERIC_CONCERN_OF );
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/common/Qi4jConcernConstants.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/common/Qi4jConcernConstants.java
deleted file mode 100644
index 57199be..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/common/Qi4jConcernConstants.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.concerns.common;
-
-import org.jetbrains.annotations.NonNls;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jConcernConstants
-{
-    public static final String QUALIFIED_NAME_CONCERNS = "org.qi4j.api.concern.Concerns";
-
-    public static final String QUALIFIED_NAME_CONCERN_OF = "org.qi4j.api.concern.ConcernOf";
-    public static final String QUALIFIED_NAME_GENERIC_CONCERN = "org.qi4j.api.concern.GenericConcern";
-
-    @NonNls
-    public static final String TEMPLATE_GENERIC_CONCERN_OF = "GenericConcernOf.java";
-
-    private Qi4jConcernConstants()
-    {
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/common/Qi4jConcernUtil.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/common/Qi4jConcernUtil.java
deleted file mode 100644
index 0771228..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/common/Qi4jConcernUtil.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.concerns.common;
-
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.codeStyle.JavaCodeStyleManager;
-import com.intellij.psi.search.GlobalSearchScope;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.List;
-
-import static com.intellij.codeInsight.AnnotationUtil.findAnnotation;
-import static java.util.Collections.emptyList;
-import static org.qi4j.ide.plugin.idea.common.psi.PsiAnnotationUtil.getAnnotationDefaultParameterValue;
-import static org.qi4j.ide.plugin.idea.common.psi.PsiAnnotationUtil.getClassReference;
-import static org.qi4j.ide.plugin.idea.common.psi.PsiClassUtil.getPSIClass;
-import static org.qi4j.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
-import static org.qi4j.ide.plugin.idea.concerns.common.Qi4jConcernConstants.*;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jConcernUtil
-{
-
-
-    /**
-     * @param searchContext Search context.
-     * @return {@code GenericConcern} psi class if found, {@code null} otherwise.
-     * @since 0.1
-     */
-    @Nullable
-    public static PsiClass getGenericConcernClass( @NotNull PsiElement searchContext )
-    {
-        Project project = searchContext.getProject();
-        GlobalSearchScope searchScope = determineSearchScope( searchContext );
-        return getGenericConcernClass( project, searchScope );
-    }
-
-    /**
-     * @param project project.
-     * @param scope   search scope.
-     * @return {@code GenericConcern} psi class if found, {@code null} otherwise.
-     * @since 0.1
-     */
-    @Nullable
-    public static PsiClass getGenericConcernClass( @NotNull Project project,
-                                                   @Nullable GlobalSearchScope scope )
-    {
-        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( project );
-        return scope != null ? psiFacade.findClass( QUALIFIED_NAME_GENERIC_CONCERN, scope ) : null;
-    }
-
-    @Nullable
-    public static PsiClass getConcernOfClass( @NotNull PsiElement searchContext )
-    {
-        Project project = searchContext.getProject();
-        GlobalSearchScope searchScope = determineSearchScope( searchContext );
-        return getConcernOfClass( project, searchScope );
-    }
-
-    @Nullable
-    public static PsiClass getConcernOfClass( @NotNull Project project,
-                                              @Nullable GlobalSearchScope scope )
-    {
-        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( project );
-        return scope != null ? psiFacade.findClass( QUALIFIED_NAME_CONCERN_OF, scope ) : null;
-    }
-
-    @Nullable
-    public static PsiAnnotation getConcernsAnnotation( @NotNull PsiElement element )
-    {
-        PsiClass psiClass = getPSIClass( element );
-        return findAnnotation( psiClass, QUALIFIED_NAME_CONCERNS );
-    }
-
-    @NotNull
-    public static PsiAnnotation addOrReplaceConcernAnnotation( @NotNull PsiModifierListOwner modifierListOwner,
-                                                               @NotNull PsiClass concernClassToAdd )
-    {
-        Project project = modifierListOwner.getProject();
-        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( project );
-        PsiElementFactory factory = psiFacade.getElementFactory();
-        PsiAnnotation existingConcernsAnnotation = findAnnotation( modifierListOwner, QUALIFIED_NAME_CONCERNS );
-
-        boolean isReplace = false;
-        PsiAnnotation newConcernsAnnotation;
-        if( existingConcernsAnnotation != null )
-        {
-            // Check duplicate
-            List<PsiAnnotationMemberValue> concernsValues = getConcernsAnnotationValue( existingConcernsAnnotation );
-            for( PsiAnnotationMemberValue concernValue : concernsValues )
-            {
-                PsiJavaCodeReferenceElement concernClassReference = getConcernClassReference( concernValue );
-                if( concernClassReference == null )
-                {
-                    continue;
-                }
-
-                PsiElement concernClass = concernClassReference.resolve();
-                if( concernClassToAdd.equals( concernClass ) )
-                {
-                    return existingConcernsAnnotation;
-                }
-            }
-
-            isReplace = true;
-        }
-
-        String concernAnnotationText = createConcernAnnotationText( existingConcernsAnnotation, concernClassToAdd );
-        newConcernsAnnotation =
-            factory.createAnnotationFromText( concernAnnotationText, modifierListOwner );
-
-        if( isReplace )
-        {
-            // Replace @Concerns instead
-            existingConcernsAnnotation.replace( newConcernsAnnotation );
-        }
-        else
-        {
-            // @Concerns doesn't exists, add it as first child
-            PsiModifierList modifierList = modifierListOwner.getModifierList();
-            modifierList.addBefore( newConcernsAnnotation, modifierList.getFirstChild() );
-        }
-
-        // Shorten all class references if possible
-        JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance( project );
-        codeStyleManager.shortenClassReferences( newConcernsAnnotation );
-
-        return newConcernsAnnotation;
-    }
-
-    @NotNull
-    private static String createConcernAnnotationText( @Nullable PsiAnnotation concernAnnotationBase,
-                                                       @NotNull PsiClass concernClassToAdd )
-    {
-        StringBuilder annotationTextBuilder = new StringBuilder();
-        annotationTextBuilder.append( "@" ).append( QUALIFIED_NAME_CONCERNS ).append( "( {" );
-        List<PsiAnnotationMemberValue> concernsAnnotationValue = getConcernsAnnotationValue( concernAnnotationBase );
-        for( PsiAnnotationMemberValue concernValue : concernsAnnotationValue )
-        {
-            annotationTextBuilder.append( concernValue.getText() ).append( ", " );
-        }
-        annotationTextBuilder.append( concernClassToAdd.getQualifiedName() ).append( ".class" );
-        annotationTextBuilder.append( "} )" );
-        return annotationTextBuilder.toString();
-    }
-
-    @NotNull
-    public static List<PsiAnnotationMemberValue> getConcernsAnnotationValue( @Nullable PsiAnnotation concernsAnnotation )
-    {
-        if( concernsAnnotation == null )
-        {
-            return emptyList();
-        }
-
-        String concernsQualifiedName = concernsAnnotation.getQualifiedName();
-        if( !QUALIFIED_NAME_CONCERNS.equals( concernsQualifiedName ) )
-        {
-            return emptyList();
-        }
-
-        return getAnnotationDefaultParameterValue( concernsAnnotation );
-    }
-
-    @Nullable
-    public static PsiJavaCodeReferenceElement getConcernClassReference( @NotNull PsiAnnotationMemberValue value )
-    {
-        return getClassReference( value );
-    }
-
-    /**
-     * @param psiClass psi class to check.
-     * @return {@code true} if {@code psiClass} extends {@code ConcernOf}, {@code false} if {@code psiClass} does
-     *         not extends {@code ConcernOf} or {@code ConcernOf} is not found.
-     * @since 0.1
-     */
-    public static boolean isAConcern( @NotNull PsiClass psiClass )
-    {
-        if( psiClass.isInterface() )
-        {
-            return false;
-        }
-
-        PsiClass concernOfClass = getConcernOfClass( psiClass );
-        return concernOfClass != null && psiClass.isInheritor( concernOfClass, true );
-    }
-
-    /**
-     * @param psiClass psi class to check.
-     * @return {@code true} if {@code psiClass} extends {@code GenericConcern}, {@code false} if {@code psiClass} does
-     *         not extends {@code GenericConcern} or {@code GenericConcern} is not found.
-     * @since 0.1
-     */
-    public static boolean isAGenericConcern( @NotNull PsiClass psiClass )
-    {
-        if( psiClass.isInterface() )
-        {
-            return false;
-        }
-
-        PsiClass genericConcern = getGenericConcernClass( psiClass );
-        return genericConcern != null && psiClass.isInheritor( genericConcern, true );
-    }
-
-    private Qi4jConcernUtil()
-    {
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/inspections/ConcernsAnnotationDeclaredCorrectlyInspection.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/inspections/ConcernsAnnotationDeclaredCorrectlyInspection.java
deleted file mode 100644
index 5e74d9f..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/inspections/ConcernsAnnotationDeclaredCorrectlyInspection.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.concerns.inspections;
-
-import com.intellij.codeInspection.InspectionManager;
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiAnnotation;
-import com.intellij.psi.PsiAnnotationMemberValue;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiJavaCodeReferenceElement;
-import com.intellij.psi.search.GlobalSearchScope;
-import org.jetbrains.annotations.NotNull;
-import org.qi4j.ide.plugin.idea.common.inspections.AbstractFix;
-import org.qi4j.ide.plugin.idea.common.inspections.AbstractInspection;
-import org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
-import static org.qi4j.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
-import static org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle.message;
-import static org.qi4j.ide.plugin.idea.concerns.common.Qi4jConcernUtil.*;
-
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class ConcernsAnnotationDeclaredCorrectlyInspection extends AbstractInspection
-{
-    @NotNull
-    protected final String resourceBundlePrefixId()
-    {
-        return "concerns.annotation.declared.correctly";
-    }
-
-    @NotNull
-    public final String getShortName()
-    {
-        return "ConcernsAnnotationDeclaredCorrectlyInspection";
-    }
-
-    @Override
-    public final ProblemDescriptor[] checkClass( @NotNull PsiClass psiClass,
-                                                 @NotNull InspectionManager manager,
-                                                 boolean isOnTheFly )
-    {
-        // If class does not have @Concerns, ignore
-        PsiAnnotation concernsAnnotation = getConcernsAnnotation( psiClass );
-        if( concernsAnnotation == null )
-        {
-            return null;
-        }
-
-        // If @Concerns declared in class, suggest remove @Concerns annotation
-        if( !psiClass.isInterface() )
-        {
-            String message = message( "concerns.annotation.declared.correctly.error.annotation.declared.in.class" );
-            RemoveConcernsAnnotationFix fix = new RemoveConcernsAnnotationFix( concernsAnnotation );
-            ProblemDescriptor problemDescriptor = manager.createProblemDescriptor( concernsAnnotation, message, fix,
-                                                                                   GENERIC_ERROR_OR_WARNING );
-            return new ProblemDescriptor[]{ problemDescriptor };
-        }
-
-        // If @Concerns annotation is empty, ignore
-        List<PsiAnnotationMemberValue> concernsAnnotationValue = getConcernsAnnotationValue( concernsAnnotation );
-        if( concernsAnnotationValue.isEmpty() )
-        {
-            return null;
-        }
-
-        // If ConcernOfClass is not resolved, ignore
-        Project project = psiClass.getProject();
-        GlobalSearchScope searchScope = determineSearchScope( psiClass );
-        PsiClass concernOfClass = getConcernOfClass( project, searchScope );
-        if( concernOfClass == null )
-        {
-            return null;
-        }
-
-        List<ProblemDescriptor> problems = new LinkedList<ProblemDescriptor>();
-        for( PsiAnnotationMemberValue concernClassAnnotationValue : concernsAnnotationValue )
-        {
-            PsiJavaCodeReferenceElement concernClassReference = getConcernClassReference( concernClassAnnotationValue );
-
-            // If it's not a class reference, ignore
-            if( concernClassReference == null )
-            {
-                continue;
-            }
-
-            // If class reference can't be resolved, ignore
-            PsiClass concernClass = (PsiClass) concernClassReference.resolve();
-            if( concernClass == null )
-            {
-                continue;
-            }
-
-            // If concern class does not inherit concern class, suggest remove that reference.
-            if( !concernClass.isInheritor( concernOfClass, true ) )
-            {
-                String message = Qi4jResourceBundle.message(
-                    "concerns.annotation.declared.correctly.error.concern.class.does.not.extend.ConcernOf",
-                    concernClass.getQualifiedName()
-                );
-
-                RemoveInvalidConcernClassReferenceFix fix = new RemoveInvalidConcernClassReferenceFix(
-                    concernClassAnnotationValue, concernClassReference
-                );
-                ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(
-                    concernClassAnnotationValue, message, fix, GENERIC_ERROR_OR_WARNING );
-                problems.add( problemDescriptor );
-            }
-            else
-            {
-                // TODO: Test whether it is a generic concern
-                // TODO: Test whether it is a specific concern
-            }
-        }
-
-        return problems.toArray( new ProblemDescriptor[problems.size()] );
-    }
-
-    private static class RemoveConcernsAnnotationFix extends AbstractFix
-    {
-        private final PsiAnnotation annotationToRemove;
-
-        private RemoveConcernsAnnotationFix( @NotNull PsiAnnotation annotationToRemove )
-        {
-            super( message( "concerns.annotation.declared.correctly.fix.remove.annotation" ) );
-            this.annotationToRemove = annotationToRemove;
-        }
-
-        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
-        {
-            annotationToRemove.delete();
-        }
-    }
-
-    private static class RemoveInvalidConcernClassReferenceFix extends AbstractFix
-    {
-        private final PsiAnnotationMemberValue concernClassAnnotationValue;
-
-        public RemoveInvalidConcernClassReferenceFix( @NotNull PsiAnnotationMemberValue annotationValueToRemove,
-                                                      @NotNull PsiJavaCodeReferenceElement concernClassReference )
-        {
-            super( message( "concerns.annotation.declared.correctly.fix.remove.concern.class.reference",
-                            concernClassReference.getQualifiedName() ) );
-            this.concernClassAnnotationValue = annotationValueToRemove;
-        }
-
-        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
-        {
-            concernClassAnnotationValue.delete();
-        }
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/intentions/add/AddConcernOnType.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/intentions/add/AddConcernOnType.java
deleted file mode 100644
index 91517e4..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/concerns/intentions/add/AddConcernOnType.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.concerns.intentions.add;
-
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiMethod;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.util.Processor;
-import com.intellij.util.Query;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.qi4j.ide.plugin.idea.common.intentions.AbstractIntention;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static com.intellij.psi.search.searches.ClassInheritorsSearch.search;
-import static java.util.Collections.emptyList;
-import static org.qi4j.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
-import static org.qi4j.ide.plugin.idea.concerns.common.Qi4jConcernUtil.addOrReplaceConcernAnnotation;
-import static org.qi4j.ide.plugin.idea.concerns.common.Qi4jConcernUtil.getConcernOfClass;
-
-/**
- * JAVADOC: This is disabled in Qi4jApplicationComponent.
- *
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class AddConcernOnType
-    extends AbstractIntention
-{
-    protected boolean isIntentionValidFor( PsiElement element )
-    {
-        if( !( element instanceof PsiClass ) )
-        {
-            return false;
-        }
-
-        // If it's not interface, ignore it
-        PsiClass psiClass = (PsiClass) element;
-        if( !psiClass.isInterface() )
-        {
-            return false;
-        }
-
-        // Is @Concerns accesible within module
-        GlobalSearchScope searchScope = determineSearchScope( psiClass );
-        PsiClass concernOfClass = getConcernOfClass( psiClass.getProject(), searchScope );
-        return concernOfClass != null;
-    }
-
-    protected final String resourceBundlePrefixId()
-    {
-        return "add.concern";
-    }
-
-    @Override
-    public boolean isAvailable( @NotNull Project project, Editor editor, @Nullable PsiElement element )
-    {
-        while( element != null )
-        {
-            if( element instanceof PsiFile ||
-                element instanceof PsiMethod )
-            {
-                break;
-            }
-
-            if( isIntentionValidFor( element ) )
-            {
-                return true;
-            }
-
-            element = element.getParent();
-        }
-
-        return false;
-    }
-
-    @SuppressWarnings( "unchecked" )
-    protected void processIntention( @NotNull Project project, @NotNull Editor editor, @NotNull PsiElement element )
-    {
-        PsiClass psiClass = (PsiClass) element;
-        List<PsiClass> concernCandidates = findConcernsCandidates( psiClass );
-        if( concernCandidates.size() == 1 )
-        {
-            PsiClass concernCandidate = concernCandidates.get( 0 );
-            addOrReplaceConcernAnnotation( psiClass, concernCandidate );
-        }
-    }
-
-    private static List<PsiClass> findConcernsCandidates( final @NotNull PsiClass classToCheck )
-    {
-        GlobalSearchScope searchScope = determineSearchScope( classToCheck );
-        PsiClass concernOfClass = getConcernOfClass( classToCheck.getProject(), searchScope );
-        if( concernOfClass == null )
-        {
-            return emptyList();
-        }
-
-        Query<PsiClass> psiClassQuery = search( concernOfClass, searchScope, true, false );
-        final List<PsiClass> concernCandidates = new ArrayList<PsiClass>();
-        psiClassQuery.forEach( new Processor<PsiClass>()
-        {
-            public boolean process( PsiClass psiClass )
-            {
-                // TODO: Ideally search for all "extends" as well
-                boolean isInheritor = psiClass.isInheritor( classToCheck, true );
-                if( isInheritor )
-                {
-                    concernCandidates.add( psiClass );
-                }
-
-                return true;
-            }
-        } );
-
-        return concernCandidates;
-    }
-}
-
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/common/inspections/AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/common/inspections/AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection.java
deleted file mode 100644
index 8d601ab..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/common/inspections/AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.injections.common.inspections;
-
-import com.intellij.codeInspection.InspectionManager;
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.psi.PsiAnnotation;
-import com.intellij.psi.PsiMethod;
-import com.intellij.psi.PsiParameter;
-import com.intellij.psi.PsiParameterList;
-import org.jetbrains.annotations.NotNull;
-import org.qi4j.ide.plugin.idea.common.inspections.AbstractFix;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
-import static java.util.Arrays.asList;
-
-/**
- * {@code AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection} is a helper method to check whether
- * injection annotation are declared in either constructor or non static field.
- *
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public abstract class AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection
-    extends AbstractInjectionAnnotationDeclarationOnFieldInspection
-{
-    @Override
-    public final ProblemDescriptor[] checkMethod( @NotNull PsiMethod method,
-                                                  @NotNull InspectionManager manager,
-                                                  boolean isOnTheFly )
-    {
-        PsiParameterList parameterList = method.getParameterList();
-        PsiParameter[] parameters = parameterList.getParameters();
-        if( method.isConstructor() )
-        {
-            List<ProblemDescriptor> problems = new LinkedList<ProblemDescriptor>();
-            for( PsiParameter parameter : parameters )
-            {
-                PsiAnnotation annotation = getAnnotationToCheck( parameter );
-                if( annotation != null )
-                {
-                    ProblemDescriptor[] descriptors =
-                        verifyAnnotationDeclaredCorrectly( parameter, annotation, manager );
-                    if( descriptors != null )
-                    {
-                        problems.addAll( asList( descriptors ) );
-                    }
-                }
-            }
-
-            return problems.toArray( new ProblemDescriptor[problems.size()] );
-        }
-        else
-        {
-            List<ProblemDescriptor> problems = new LinkedList<ProblemDescriptor>();
-            for( PsiParameter parameter : parameters )
-            {
-                PsiAnnotation annotationToCheck = getAnnotationToCheck( parameter );
-                if( annotationToCheck != null )
-                {
-                    String message = getInjectionAnnotationValidDeclarationMessage();
-                    AbstractFix removeAnnotationFix = createRemoveAnnotationFix( annotationToCheck );
-                    ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(
-                        annotationToCheck, message, removeAnnotationFix, GENERIC_ERROR_OR_WARNING
-                    );
-                    problems.add( problemDescriptor );
-                }
-            }
-
-            return problems.toArray( new ProblemDescriptor[problems.size()] );
-        }
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/common/inspections/AbstractInjectionAnnotationDeclarationOnFieldInspection.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/common/inspections/AbstractInjectionAnnotationDeclarationOnFieldInspection.java
deleted file mode 100644
index cf2ffe9..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/common/inspections/AbstractInjectionAnnotationDeclarationOnFieldInspection.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.injections.common.inspections;
-
-import com.intellij.codeInspection.InspectionManager;
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiAnnotation;
-import com.intellij.psi.PsiField;
-import com.intellij.psi.PsiModifierList;
-import com.intellij.psi.PsiVariable;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.qi4j.ide.plugin.idea.common.inspections.AbstractFix;
-import org.qi4j.ide.plugin.idea.common.inspections.AbstractInspection;
-
-import static com.intellij.codeInsight.AnnotationUtil.findAnnotation;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public abstract class AbstractInjectionAnnotationDeclarationOnFieldInspection extends AbstractInspection
-{
-    /**
-     * @return Remove annotation message fix.
-     * @since 0.1
-     */
-    @NotNull
-    protected abstract String getRemoveAnnotationMessageFix();
-
-    /**
-     * @return Annotation to check qualified name.
-     * @since 0.1
-     */
-    @NotNull
-    protected abstract String getAnnotationToCheckQualifiedName();
-
-    /**
-     * Verified that {@link #getAnnotationToCheck(com.intellij.psi.PsiVariable)} is declared correctly.
-     *
-     * @param psiVariable       Variable to check. This could be class field member or constructor parameter.
-     * @param annotationToCheck annotation declared at variable to check.
-     * @param manager           Inspection manager to use to create problem descriptor.
-     * @return {@code null} if annotation is declared correctly, otherwise an array of problem descriptor.
-     * @since 0.1
-     */
-    @Nullable
-    protected abstract ProblemDescriptor[] verifyAnnotationDeclaredCorrectly( @NotNull PsiVariable psiVariable,
-                                                                              @NotNull PsiAnnotation annotationToCheck,
-                                                                              @NotNull InspectionManager manager );
-
-    @Override
-    public final ProblemDescriptor[] checkField( @NotNull PsiField field,
-                                                 @NotNull InspectionManager manager,
-                                                 boolean isOnTheFly )
-    {
-        PsiAnnotation annotationToCheck = getAnnotationToCheck( field );
-        if( annotationToCheck == null )
-        {
-            return null;
-        }
-
-        PsiModifierList modifierList = field.getModifierList();
-        if( modifierList != null )
-        {
-            if( modifierList.hasModifierProperty( com.intellij.psi.PsiModifier.STATIC ) )
-            {
-                String message = getInjectionAnnotationValidDeclarationMessage();
-                AbstractFix removeAnnotationFix = createRemoveAnnotationFix( annotationToCheck );
-                ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(
-                    annotationToCheck, message, removeAnnotationFix, com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING
-                );
-
-                return new ProblemDescriptor[]{ problemDescriptor };
-            }
-        }
-
-        return verifyAnnotationDeclaredCorrectly( field, annotationToCheck, manager );
-    }
-
-    /**
-     * @param variable variable to check.
-     * @return Annotation to check.
-     * @see #getAnnotationToCheckQualifiedName()
-     * @since 0.1
-     */
-    @Nullable
-    protected final PsiAnnotation getAnnotationToCheck( @NotNull PsiVariable variable )
-    {
-        String annotationQualifiedName = getAnnotationToCheckQualifiedName();
-        return findAnnotation( variable, annotationQualifiedName );
-    }
-
-    @NotNull protected String getInjectionAnnotationValidDeclarationMessage()
-    {
-        String annotationQualifiedName = getAnnotationToCheckQualifiedName();
-        return org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle.message( "abstract.injection.annotation.declaration.inspection.error.annotation.not.declared.correctly",
-                                                                                    annotationQualifiedName );
-    }
-
-    @NotNull
-    protected final AbstractFix createRemoveAnnotationFix( @NotNull PsiAnnotation annotationToRemove )
-    {
-        String fixMessage = getRemoveAnnotationMessageFix();
-        return new RemoveAnnotationFix( fixMessage, annotationToRemove );
-    }
-
-    private static class RemoveAnnotationFix extends AbstractFix
-    {
-        private final PsiAnnotation annotationToRemove;
-
-        public RemoveAnnotationFix( @NotNull String fixMessage, @NotNull PsiAnnotation annotationToRemove )
-        {
-            super( fixMessage );
-            this.annotationToRemove = annotationToRemove;
-        }
-
-        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
-        {
-            annotationToRemove.delete();
-        }
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/invocation/common/Qi4jInvocationAnnotationConstants.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/invocation/common/Qi4jInvocationAnnotationConstants.java
deleted file mode 100644
index d77d0c5..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/invocation/common/Qi4jInvocationAnnotationConstants.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.injections.invocation.common;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jInvocationAnnotationConstants
-{
-    public static final String QUALIFIED_NAME_INVOCATION_ANNOTATION = "org.qi4j.api.injection.scope.Invocation";
-
-    private Qi4jInvocationAnnotationConstants()
-    {
-    }
-}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/invocation/common/Qi4jInvocationAnnotationUtil.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/invocation/common/Qi4jInvocationAnnotationUtil.java
deleted file mode 100644
index 3417d2c..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/invocation/common/Qi4jInvocationAnnotationUtil.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.injections.invocation.common;
-
-import com.intellij.psi.*;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import static com.intellij.codeInsight.AnnotationUtil.findAnnotation;
-import static com.intellij.psi.PsiModifier.STATIC;
-import static org.qi4j.ide.plugin.idea.common.psi.PsiClassUtil.getPSIClass;
-import static org.qi4j.ide.plugin.idea.injections.invocation.common.Qi4jInvocationAnnotationConstants.QUALIFIED_NAME_INVOCATION_ANNOTATION;
-import static org.qi4j.ide.plugin.idea.injections.invocation.common.Qi4jInvocationAnnotationUtil.InvocationAnnotationDeclarationValidationResult.*;
-import static org.qi4j.ide.plugin.idea.injections.structure.common.Qi4jStructureAnnotationUtil.isInjecteableByStructureAnnotation;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jInvocationAnnotationUtil
-{
-    /**
-     * Returns {@code @Invocation} annotation if exists.
-     *
-     * @param modifierListOwner modifier list owner to process.
-     * @return {@code @Invocation} annotation if exists, {@code null} otherwise.
-     * @since 0.1
-     */
-    @Nullable
-    public static PsiAnnotation getInvocationAnnotation( @NotNull PsiModifierListOwner modifierListOwner )
-    {
-        return findAnnotation( modifierListOwner, QUALIFIED_NAME_INVOCATION_ANNOTATION );
-    }
-
-    /**
-     * @param psiClass psi class to check.
-     * @return {@code true} if the specified psiClass is injectable by invocation annotation, {@code false} otherwise.
-     */
-    public static boolean isInjectableByInvocationAnnotation( @NotNull PsiClass psiClass )
-    {
-        if( psiClass.isAnnotationType() )
-        {
-            return true;
-        }
-
-        String classQualifiedName = psiClass.getQualifiedName();
-        return "java.lang.reflect.Method".equals( classQualifiedName ) ||
-               "java.lang.reflect.AnnotatedElement".equals( classQualifiedName );
-    }
-
-    /**
-     * Validates whether the variable has {@code @Invocation} annotation declared correctly.
-     *
-     * @param variable variable to check.
-     * @return Look at {@link InvocationAnnotationDeclarationValidationResult}.
-     * @since 0.1
-     */
-    @NotNull
-    public static InvocationAnnotationDeclarationValidationResult isValidInvocationAnnotationDeclaration(
-        @NotNull PsiVariable variable )
-    {
-        PsiAnnotation invocationAnnotation = getInvocationAnnotation( variable );
-        if( invocationAnnotation == null )
-        {
-            return invalidInvocationAnnotationNotDeclared;
-        }
-
-        PsiModifierList modifierList = variable.getModifierList();
-        if( modifierList != null )
-        {
-            if( modifierList.hasModifierProperty( STATIC ) )
-            {
-                return invalidDeclaredOnStaticVariable;
-            }
-        }
-
-        // TODO: Check whether variable is either an instance of java.lang.reflect.Method or
-        // java.lang.reflect.AnnotatedElement or Annotation
-        PsiTypeElement typeElement = variable.getTypeElement();
-        if( typeElement != null )
-        {
-            PsiClass psiClass = getPSIClass( typeElement );
-            if( psiClass != null )
-            {
-                if( !isInjectableByInvocationAnnotation( psiClass ) )
-                {
-                    // Can't be type that is injected by @Structure
-                    if( isInjecteableByStructureAnnotation( variable ) )
-                    {
-                        return invalidTypeIsInjectedViaStructureAnnotation;
-                    }
-
-                    return invalidType;
-                }
-            }
-        }
-
-        return valid;
-    }
-
-    public enum InvocationAnnotationDeclarationValidationResult
-    {
-        invalidInvocationAnnotationNotDeclared,
-        invalidDeclaredOnStaticVariable,
-        invalidTypeIsInjectedViaStructureAnnotation,
-        invalidType,
-        valid,
-    }
-
-    private Qi4jInvocationAnnotationUtil()
-    {
-    }
-}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/invocation/inspections/InvocationAnnotationDeclaredCorrectlyInspection.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/invocation/inspections/InvocationAnnotationDeclaredCorrectlyInspection.java
deleted file mode 100644
index d445b95..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/invocation/inspections/InvocationAnnotationDeclaredCorrectlyInspection.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.injections.invocation.inspections;
-
-import com.intellij.codeInspection.InspectionManager;
-import com.intellij.codeInspection.LocalQuickFix;
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.psi.PsiAnnotation;
-import com.intellij.psi.PsiVariable;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.qi4j.ide.plugin.idea.injections.common.inspections.AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection;
-import org.qi4j.ide.plugin.idea.injections.structure.common.ReplaceWithStructureAnnotation;
-
-import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
-import static org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle.message;
-import static org.qi4j.ide.plugin.idea.injections.invocation.common.Qi4jInvocationAnnotationConstants.QUALIFIED_NAME_INVOCATION_ANNOTATION;
-import static org.qi4j.ide.plugin.idea.injections.invocation.common.Qi4jInvocationAnnotationUtil.InvocationAnnotationDeclarationValidationResult;
-import static org.qi4j.ide.plugin.idea.injections.invocation.common.Qi4jInvocationAnnotationUtil.isValidInvocationAnnotationDeclaration;
-import static org.qi4j.ide.plugin.idea.injections.structure.common.Qi4jStructureAnnotationUtil.getStructureAnnotation;
-
-/**
- * {@code InvocationAnnotationDeclaredCorrectlyInspection} validates {@code @Invocation} injection annotation
- * declaration.
- *
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public class InvocationAnnotationDeclaredCorrectlyInspection
-    extends AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection
-{
-    @NotNull
-    protected final String resourceBundlePrefixId()
-    {
-        return "injections.invocation.annotation.declared.correctly";
-    }
-
-    @NotNull
-    public final String getShortName()
-    {
-        return "InvocationAnnotationDeclaredCorrectlyInspection";
-    }
-
-    @NotNull
-    protected final String getRemoveAnnotationMessageFix()
-    {
-        return message( "injections.invocation.annotation.declared.correctly.fix.remove.annotation" );
-    }
-
-    @NotNull
-    protected final String getAnnotationToCheckQualifiedName()
-    {
-        return QUALIFIED_NAME_INVOCATION_ANNOTATION;
-    }
-
-    @Nullable
-    protected final ProblemDescriptor[] verifyAnnotationDeclaredCorrectly( @NotNull PsiVariable psiVariable,
-                                                                           @NotNull PsiAnnotation invocationAnnotation,
-                                                                           @NotNull InspectionManager manager )
-    {
-        LocalQuickFix fix = null;
-        String message = null;
-
-        String variableTypeQualifiedName = psiVariable.getType().getCanonicalText();
-
-        InvocationAnnotationDeclarationValidationResult validationResult =
-            isValidInvocationAnnotationDeclaration( psiVariable );
-        switch( validationResult )
-        {
-        case invalidTypeIsInjectedViaStructureAnnotation:
-            if( getStructureAnnotation( psiVariable ) == null )
-            {
-                fix = new ReplaceWithStructureAnnotation(
-                    message( "injections.invocation.annotation.declared.correctly.fix.replace.with.structure.annotation" ),
-                    invocationAnnotation );
-            }
-            message = message(
-                "injections.invocation.annotation.declared.correctly.error.type.is.injected.by.structure",
-                variableTypeQualifiedName
-            );
-            break;
-
-        case invalidType:
-            message = message( "injections.invocation.annotation.declared.correctly.error.type.is.not.injectable",
-                               variableTypeQualifiedName );
-            break;
-        }
-
-        // If it's not an error, return null
-        if( message == null )
-        {
-            return null;
-        }
-
-        // If Fix not defined, by default we remove it.
-        if( fix == null )
-        {
-            fix = createRemoveAnnotationFix( invocationAnnotation );
-        }
-
-        ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(
-            invocationAnnotation, message, fix, GENERIC_ERROR_OR_WARNING );
-        return new ProblemDescriptor[]{ problemDescriptor };
-    }
-}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/service/common/Qi4jServiceAnnotationConstants.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/service/common/Qi4jServiceAnnotationConstants.java
deleted file mode 100644
index a47d974..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/service/common/Qi4jServiceAnnotationConstants.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.injections.service.common;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jServiceAnnotationConstants
-{
-    public static final String QUALIFIED_NAME_SERVICE_ANNOTATION = "org.qi4j.api.injection.scope.Service";
-
-    private Qi4jServiceAnnotationConstants()
-    {
-    }
-}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/service/common/Qi4jServiceAnnotationUtil.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/service/common/Qi4jServiceAnnotationUtil.java
deleted file mode 100644
index dac9563..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/service/common/Qi4jServiceAnnotationUtil.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.injections.service.common;
-
-import com.intellij.psi.PsiAnnotation;
-import com.intellij.psi.PsiModifierList;
-import com.intellij.psi.PsiModifierListOwner;
-import com.intellij.psi.PsiVariable;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import static com.intellij.codeInsight.AnnotationUtil.findAnnotation;
-import static com.intellij.psi.PsiModifier.STATIC;
-import static org.qi4j.ide.plugin.idea.injections.service.common.Qi4jServiceAnnotationConstants.QUALIFIED_NAME_SERVICE_ANNOTATION;
-import static org.qi4j.ide.plugin.idea.injections.service.common.Qi4jServiceAnnotationUtil.ServiceAnnotationDeclarationValidationResult.*;
-import static org.qi4j.ide.plugin.idea.injections.structure.common.Qi4jStructureAnnotationUtil.isInjecteableByStructureAnnotation;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jServiceAnnotationUtil
-{
-    /**
-     * Returns {@code @Service} annotation if exists.
-     *
-     * @param modifierListOwner modifier list owner to process.
-     * @return {@code @Service} annotation if exists, {@code null} otherwise.
-     * @since 0.1
-     */
-    @Nullable
-    public static PsiAnnotation getServiceAnnotation( @NotNull PsiModifierListOwner modifierListOwner )
-    {
-        return findAnnotation( modifierListOwner, QUALIFIED_NAME_SERVICE_ANNOTATION );
-    }
-
-    /**
-     * Validates whether the variable has {@code @Service} annotation declared correctly.
-     *
-     * @param variable variable to check.
-     * @return Look at {@link ServiceAnnotationDeclarationValidationResult}.
-     * @since 0.1
-     */
-    @NotNull
-    public static ServiceAnnotationDeclarationValidationResult isValidServiceAnnotationDeclaration(
-        @NotNull PsiVariable variable )
-    {
-        PsiAnnotation serviceAnnotation = getServiceAnnotation( variable );
-        if( serviceAnnotation == null )
-        {
-            return invalidServiceAnnotationNotDeclared;
-        }
-
-        PsiModifierList modifierList = variable.getModifierList();
-        if( modifierList != null )
-        {
-            if( modifierList.hasModifierProperty( STATIC ) )
-            {
-                return invalidDeclaredOnStaticVariable;
-            }
-        }
-
-        // Can't be type that is injected by @Structure
-        if( isInjecteableByStructureAnnotation( variable ) )
-        {
-            return invalidTypeIsInjectedViaStructureAnnotation;
-        }
-
-        return valid;
-    }
-
-    public enum ServiceAnnotationDeclarationValidationResult
-    {
-        invalidServiceAnnotationNotDeclared,
-        invalidDeclaredOnStaticVariable,
-        invalidTypeIsInjectedViaStructureAnnotation,
-        valid,
-    }
-
-    private Qi4jServiceAnnotationUtil()
-    {
-    }
-}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/service/inspections/ServiceAnnotationDeclaredCorrectlyInspection.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/service/inspections/ServiceAnnotationDeclaredCorrectlyInspection.java
deleted file mode 100644
index 60e5bcd..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/service/inspections/ServiceAnnotationDeclaredCorrectlyInspection.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.injections.service.inspections;
-
-import com.intellij.codeInspection.InspectionManager;
-import com.intellij.codeInspection.LocalQuickFix;
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.psi.PsiAnnotation;
-import com.intellij.psi.PsiVariable;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.qi4j.ide.plugin.idea.injections.common.inspections.AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection;
-import org.qi4j.ide.plugin.idea.injections.structure.common.ReplaceWithStructureAnnotation;
-
-import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
-import static org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle.message;
-import static org.qi4j.ide.plugin.idea.injections.service.common.Qi4jServiceAnnotationConstants.QUALIFIED_NAME_SERVICE_ANNOTATION;
-import static org.qi4j.ide.plugin.idea.injections.service.common.Qi4jServiceAnnotationUtil.ServiceAnnotationDeclarationValidationResult;
-import static org.qi4j.ide.plugin.idea.injections.service.common.Qi4jServiceAnnotationUtil.isValidServiceAnnotationDeclaration;
-import static org.qi4j.ide.plugin.idea.injections.structure.common.Qi4jStructureAnnotationUtil.getStructureAnnotation;
-
-/**
- * {@code ServiceAnnotationDeclaredCorrectly} validates {@code @Service} injection annotation declaration.
- *
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public class ServiceAnnotationDeclaredCorrectlyInspection
-    extends AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection
-{
-    @NotNull
-    protected final String resourceBundlePrefixId()
-    {
-        return "injections.service.annotation.declared.correctly";
-    }
-
-    @NotNull
-    public final String getShortName()
-    {
-        return "ServiceAnnotationDeclaredCorrectlyInspection";
-    }
-
-    @NotNull
-    protected final String getRemoveAnnotationMessageFix()
-    {
-        return message( "injections.service.annotation.declared.correctly.fix.remove.annotation" );
-    }
-
-    @NotNull
-    protected final String getAnnotationToCheckQualifiedName()
-    {
-        return QUALIFIED_NAME_SERVICE_ANNOTATION;
-    }
-
-    @Nullable
-    protected final ProblemDescriptor[] verifyAnnotationDeclaredCorrectly( @NotNull PsiVariable psiVariable,
-                                                                           @NotNull PsiAnnotation serviceAnnotation,
-                                                                           @NotNull InspectionManager manager )
-    {
-        ServiceAnnotationDeclarationValidationResult annotationCheck =
-            isValidServiceAnnotationDeclaration( psiVariable );
-        String message = null;
-        LocalQuickFix fix = null;
-        switch( annotationCheck )
-        {
-        case invalidTypeIsInjectedViaStructureAnnotation:
-            if( getStructureAnnotation( psiVariable ) == null )
-            {
-                fix = new ReplaceWithStructureAnnotation(
-                    message( "injections.service.annotation.declared.correctly.fix.replace.with.structure.annotation" ),
-                    serviceAnnotation );
-            }
-            message = message(
-                "injections.service.annotation.declared.correctly.error.type.is.injected.by.structure",
-                psiVariable.getType().getCanonicalText()
-            );
-            break;
-        }
-
-        // If it's not an error, return null
-        if( message == null )
-        {
-            return null;
-        }
-
-        // Default behavior to remove @Service annotation
-        if( fix == null )
-        {
-            fix = createRemoveAnnotationFix( serviceAnnotation );
-        }
-
-        ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(
-            serviceAnnotation, message, fix, GENERIC_ERROR_OR_WARNING );
-        return new ProblemDescriptor[]{ problemDescriptor };
-    }
-}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/structure/common/Qi4jStructureAnnotationConstants.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/structure/common/Qi4jStructureAnnotationConstants.java
deleted file mode 100644
index bdaaa1b..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/structure/common/Qi4jStructureAnnotationConstants.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.injections.structure.common;
-
-import static java.util.Arrays.sort;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jStructureAnnotationConstants
-{
-    public static final String QUALIFIED_NAME_STRUCTURE_ANNOTATION = "org.qi4j.api.injection.scope.Structure";
-
-    public static final String[] VALID_STRUCTURE_INJECTION_TYPE;
-
-    static
-    {
-        VALID_STRUCTURE_INJECTION_TYPE = new String[]
-            {
-                "org.qi4j.composite.CompositeBuilderFactory",
-                "org.qi4j.object.ObjectBuilderFactory",
-                "org.qi4j.entity.UnitOfWorkFactory",
-                "org.qi4j.service.ServiceFinder",
-                "org.qi4j.structure.Module",
-                "org.qi4j.structure.Layer",
-                "org.qi4j.structure.Application",
-                "org.qi4j.Qi4j",
-                "org.qi4j.spi.Qi4jSPI"
-            };
-        sort( VALID_STRUCTURE_INJECTION_TYPE );
-    }
-
-    private Qi4jStructureAnnotationConstants()
-    {
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/structure/common/Qi4jStructureAnnotationUtil.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/structure/common/Qi4jStructureAnnotationUtil.java
deleted file mode 100644
index b762e5e..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/structure/common/Qi4jStructureAnnotationUtil.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.injections.structure.common;
-
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import static com.intellij.codeInsight.AnnotationUtil.findAnnotation;
-import static com.intellij.psi.PsiModifier.STATIC;
-import static org.qi4j.ide.plugin.idea.injections.structure.common.Qi4jStructureAnnotationConstants.QUALIFIED_NAME_STRUCTURE_ANNOTATION;
-import static org.qi4j.ide.plugin.idea.injections.structure.common.Qi4jStructureAnnotationConstants.VALID_STRUCTURE_INJECTION_TYPE;
-import static org.qi4j.ide.plugin.idea.injections.structure.common.Qi4jStructureAnnotationUtil.StructureAnnotationDeclarationValidationResult.*;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jStructureAnnotationUtil
-{
-    /**
-     * Returns {@code Structure} annotation if exists.
-     *
-     * @param modifierListOwner Modifier list owner.
-     * @return @Structure annotation if exists, {@code null} otherwise.
-     * @since 0.1
-     */
-    @Nullable
-    public static PsiAnnotation getStructureAnnotation( @NotNull PsiModifierListOwner modifierListOwner )
-    {
-        return findAnnotation( modifierListOwner, QUALIFIED_NAME_STRUCTURE_ANNOTATION );
-    }
-
-    /**
-     * Create structure annotation.
-     *
-     * @param project project to create structure annotation.
-     * @param context the context to create structure annotation.
-     * @return @Structure annotation.
-     */
-    @NotNull
-    public static PsiAnnotation createStructureAnnotation( @NotNull Project project,
-                                                           @NotNull PsiElement context )
-    {
-        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( project );
-        PsiElementFactory factory = psiFacade.getElementFactory();
-        return factory.createAnnotationFromText( "@" + QUALIFIED_NAME_STRUCTURE_ANNOTATION, context );
-    }
-
-    /**
-     * @param variable variable to check.
-     * @return Look at {@link StructureAnnotationDeclarationValidationResult}.
-     * @since 0.1
-     */
-    @NotNull
-    public static StructureAnnotationDeclarationValidationResult validateStructureAnnotationDeclaration(
-        @NotNull PsiVariable variable )
-    {
-        PsiAnnotation structureAnnotation = getStructureAnnotation( variable );
-        if( structureAnnotation == null )
-        {
-            return invalidStructureAnnotationNotDeclared;
-        }
-
-        PsiModifierList modifierList = variable.getModifierList();
-        if( modifierList != null )
-        {
-            if( modifierList.hasModifierProperty( STATIC ) )
-            {
-                return invalidDeclaredOnStaticVariable;
-            }
-        }
-
-        if( !isInjecteableByStructureAnnotation( variable ) )
-        {
-            return invalidInjectionType;
-        }
-
-        return valid;
-    }
-
-    /**
-     * Returns a {@code boolean} indicator whether variable type is injectable by @Structure annotation.
-     *
-     * @param variable variable to check.
-     * @return {@code true} if variable type is injecteable by @Structure annotation.
-     * @since 0.1
-     */
-    public static boolean isInjecteableByStructureAnnotation( @NotNull PsiVariable variable )
-    {
-        PsiType type = variable.getType();
-        String fieldClassQualifiedName = type.getCanonicalText();
-        return binarySearch( VALID_STRUCTURE_INJECTION_TYPE, fieldClassQualifiedName ) > -1;
-    }
-
-    private Qi4jStructureAnnotationUtil()
-    {
-    }
-
-    public enum StructureAnnotationDeclarationValidationResult
-    {
-        invalidStructureAnnotationNotDeclared,
-        invalidDeclaredOnStaticVariable,
-        invalidInjectionType,
-        valid,
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/structure/common/ReplaceWithStructureAnnotation.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/structure/common/ReplaceWithStructureAnnotation.java
deleted file mode 100644
index 03e9b3e..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/structure/common/ReplaceWithStructureAnnotation.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.injections.structure.common;
-
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiAnnotation;
-import org.jetbrains.annotations.NotNull;
-import org.qi4j.ide.plugin.idea.common.inspections.AbstractFix;
-
-import static org.qi4j.ide.plugin.idea.injections.structure.common.Qi4jStructureAnnotationUtil.createStructureAnnotation;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class ReplaceWithStructureAnnotation extends AbstractFix
-{
-    private final PsiAnnotation annotation;
-
-    public ReplaceWithStructureAnnotation( @NotNull String fixMessage,
-                                           @NotNull PsiAnnotation annotationToReplace )
-    {
-        super( fixMessage );
-        this.annotation = annotationToReplace;
-    }
-
-    public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
-    {
-        PsiAnnotation structureAnnotation = createStructureAnnotation( project, annotation );
-        annotation.replace( structureAnnotation );
-    }
-}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/structure/inspections/StructureAnnotationDeclaredCorrectlyInspection.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/structure/inspections/StructureAnnotationDeclaredCorrectlyInspection.java
deleted file mode 100644
index cf906d7..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/injections/structure/inspections/StructureAnnotationDeclaredCorrectlyInspection.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.injections.structure.inspections;
-
-import com.intellij.codeInspection.InspectionManager;
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.psi.PsiAnnotation;
-import com.intellij.psi.PsiVariable;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.qi4j.ide.plugin.idea.common.inspections.AbstractFix;
-import org.qi4j.ide.plugin.idea.injections.common.inspections.AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection;
-
-import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
-import static org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle.message;
-import static org.qi4j.ide.plugin.idea.injections.structure.common.Qi4jStructureAnnotationConstants.QUALIFIED_NAME_STRUCTURE_ANNOTATION;
-import static org.qi4j.ide.plugin.idea.injections.structure.common.Qi4jStructureAnnotationUtil.StructureAnnotationDeclarationValidationResult;
-import static org.qi4j.ide.plugin.idea.injections.structure.common.Qi4jStructureAnnotationUtil.validateStructureAnnotationDeclaration;
-
-/**
- * {@code StructureAnnotationUsedCorrectly} validates {@code @Structure} injection annotation declaration.
- *
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public class StructureAnnotationDeclaredCorrectlyInspection
-    extends AbstractInjectionAnnotationDeclarationOnFieldAndConstructorInspection
-{
-    @NotNull
-    protected final String resourceBundlePrefixId()
-    {
-        return "injections.structure.annotation.declared.correctly";
-    }
-
-    @NotNull
-    public final String getShortName()
-    {
-        return "StructureAnnotationDeclaredCorrectlyInspection";
-    }
-
-    @NotNull
-    protected final String getRemoveAnnotationMessageFix()
-    {
-        return message( "injections.structure.annotation.declared.correctly.fix.remove.annotation" );
-    }
-
-    @NotNull
-    protected final String getAnnotationToCheckQualifiedName()
-    {
-        return QUALIFIED_NAME_STRUCTURE_ANNOTATION;
-    }
-
-    @Nullable
-    protected final ProblemDescriptor[] verifyAnnotationDeclaredCorrectly( @NotNull PsiVariable psiVariable,
-                                                                           @NotNull PsiAnnotation structureAnnotation,
-                                                                           @NotNull InspectionManager manager )
-    {
-        StructureAnnotationDeclarationValidationResult annotationCheck =
-            validateStructureAnnotationDeclaration( psiVariable );
-        switch( annotationCheck )
-        {
-        case invalidInjectionType:
-            String message = message(
-                "injections.structure.annotation.declared.correctly.error.invalid.injection.type",
-                psiVariable.getType().getCanonicalText()
-            );
-            AbstractFix removeStructureAnnotationFix = createRemoveAnnotationFix( structureAnnotation );
-            ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(
-                structureAnnotation, message, removeStructureAnnotationFix, GENERIC_ERROR_OR_WARNING
-            );
-            return new ProblemDescriptor[]{ problemDescriptor };
-        }
-
-        return null;
-    }
-}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/mixins/common/Qi4jMixinConstants.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/mixins/common/Qi4jMixinConstants.java
deleted file mode 100644
index aefef58..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/mixins/common/Qi4jMixinConstants.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.mixins.common;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jMixinConstants
-{
-    public static final String QUALIFIED_NAME_MIXINS = "org.qi4j.api.mixin.Mixins";
-
-    private Qi4jMixinConstants()
-    {
-    }
-}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/mixins/common/Qi4jMixinUtil.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/mixins/common/Qi4jMixinUtil.java
deleted file mode 100644
index be08dde..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/mixins/common/Qi4jMixinUtil.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.mixins.common;
-
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.codeStyle.JavaCodeStyleManager;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.List;
-import java.util.Set;
-
-import static com.intellij.codeInsight.AnnotationUtil.findAnnotation;
-import static java.util.Collections.emptyList;
-import static java.util.Collections.emptySet;
-import static org.qi4j.ide.plugin.idea.common.psi.PsiAnnotationUtil.getAnnotationDefaultParameterValue;
-import static org.qi4j.ide.plugin.idea.common.psi.PsiAnnotationUtil.getClassReference;
-import static org.qi4j.ide.plugin.idea.common.psi.PsiClassUtil.getExtendsDeep;
-import static org.qi4j.ide.plugin.idea.common.psi.PsiClassUtil.getPSIClass;
-import static org.qi4j.ide.plugin.idea.concerns.common.Qi4jConcernUtil.isAConcern;
-import static org.qi4j.ide.plugin.idea.mixins.common.Qi4jMixinConstants.QUALIFIED_NAME_MIXINS;
-import static org.qi4j.ide.plugin.idea.sideEffects.common.Qi4jSideEffectUtil.isASideEffect;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jMixinUtil
-{
-    /**
-     * Get all valid mixin types of given the {@code psiClass} argument.
-     *
-     * @param psiClass The psi class to check.
-     * @return all vlaid mixin types of the given {@code psiClass} argument.
-     * @since 0.1
-     */
-    @NotNull
-    public static Set<PsiClass> getAllValidMixinTypes( @NotNull PsiClass psiClass )
-    {
-        PsiAnnotation mixinsAnnotation = getMixinsAnnotation( psiClass );
-        if( mixinsAnnotation == null )
-        {
-            return emptySet();
-        }
-
-        Set<PsiClass> validMixinsType = getExtendsDeep( psiClass );
-        validMixinsType.add( psiClass );
-        return validMixinsType;
-    }
-
-    @NotNull
-    public static List<PsiAnnotationMemberValue> getMixinsAnnotationValue( @NotNull PsiClass psiClass )
-    {
-        return getMixinsAnnotationValue( getMixinsAnnotation( psiClass ) );
-    }
-
-    @NotNull
-    public static List<PsiAnnotationMemberValue> getMixinsAnnotationValue( @Nullable PsiAnnotation mixinsAnnotation )
-    {
-        if( mixinsAnnotation == null )
-        {
-            return emptyList();
-        }
-
-        String mixinsQualifiedName = mixinsAnnotation.getQualifiedName();
-        if( !QUALIFIED_NAME_MIXINS.equals( mixinsQualifiedName ) )
-        {
-            return emptyList();
-        }
-
-        return getAnnotationDefaultParameterValue( mixinsAnnotation );
-    }
-
-    @Nullable
-    public static PsiAnnotation getMixinsAnnotation( PsiElement element )
-    {
-        PsiClass psiClass = getPSIClass( element );
-        if( psiClass == null )
-        {
-            return null;
-        }
-
-        return findAnnotation( psiClass, QUALIFIED_NAME_MIXINS );
-    }
-
-    @NotNull
-    public static PsiAnnotation addOrReplaceMixinAnnotation( @NotNull PsiModifierListOwner modifierListOwner,
-                                                             @NotNull PsiClass mixinClassToAdd )
-    {
-        Project project = modifierListOwner.getProject();
-        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( project );
-        PsiElementFactory factory = psiFacade.getElementFactory();
-        PsiAnnotation existingMixinsAnnotation = findAnnotation( modifierListOwner, QUALIFIED_NAME_MIXINS );
-
-        boolean isReplace = false;
-        PsiAnnotation newMixinsAnnotation;
-        if( existingMixinsAnnotation != null )
-        {
-            // Check duplicate
-            List<PsiAnnotationMemberValue> mixinsValues = getMixinsAnnotationValue( existingMixinsAnnotation );
-            for( PsiAnnotationMemberValue mixinValue : mixinsValues )
-            {
-                PsiJavaCodeReferenceElement mixinClassReference = getMixinClassReference( mixinValue );
-                if( mixinClassReference == null )
-                {
-                    continue;
-                }
-
-                PsiElement mixinClass = mixinClassReference.resolve();
-                if( mixinClassToAdd.equals( mixinClass ) )
-                {
-                    return existingMixinsAnnotation;
-                }
-            }
-
-            isReplace = true;
-        }
-
-        String mixinsAnnotationText = createMixinsAnnotationText( existingMixinsAnnotation, mixinClassToAdd );
-        newMixinsAnnotation = factory.createAnnotationFromText( mixinsAnnotationText, modifierListOwner );
-
-        if( isReplace )
-        {
-            // Replace @Mixins instead
-            existingMixinsAnnotation.replace( newMixinsAnnotation );
-        }
-        else
-        {
-            // @Mixins doesn't exists, add it as first child
-            PsiModifierList modifierList = modifierListOwner.getModifierList();
-            modifierList.addBefore( newMixinsAnnotation, modifierList.getFirstChild() );
-        }
-
-        // Shorten all class references if possible
-        JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance( project );
-        codeStyleManager.shortenClassReferences( newMixinsAnnotation );
-
-        return newMixinsAnnotation;
-    }
-
-    @NotNull
-    private static String createMixinsAnnotationText( @Nullable PsiAnnotation mixinsAnnotationBase,
-                                                      @NotNull PsiClass mixinClassToAdd )
-    {
-        StringBuilder annotationTextBuilder = new StringBuilder();
-        annotationTextBuilder.append( "@" ).append( QUALIFIED_NAME_MIXINS ).append( "( {" );
-        List<PsiAnnotationMemberValue> mixinsValues = getMixinsAnnotationValue( mixinsAnnotationBase );
-        for( PsiAnnotationMemberValue mixinValue : mixinsValues )
-        {
-            annotationTextBuilder.append( mixinValue.getText() ).append( ", " );
-        }
-        annotationTextBuilder.append( mixinClassToAdd.getQualifiedName() ).append( ".class" );
-        annotationTextBuilder.append( "} )" );
-
-        return annotationTextBuilder.toString();
-    }
-
-
-    @Nullable
-    public static PsiJavaCodeReferenceElement getMixinClassReference( @NotNull PsiAnnotationMemberValue value )
-    {
-        return getClassReference( value );
-    }
-
-    /**
-     * Validate whether psiClass is a mixin.
-     *
-     * @param psiClass psi class to check.
-     * @return {@code true} if psiClass is a mixin, {@code false} otherwise.
-     */
-    public static boolean isAMixin( @NotNull PsiClass psiClass )
-    {
-        return !( psiClass.isInterface() || isAConcern( psiClass ) || isASideEffect( psiClass ) );
-    }
-
-    private Qi4jMixinUtil()
-    {
-    }
-}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/mixins/inspections/MixinImplementsMixinType.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/mixins/inspections/MixinImplementsMixinType.java
deleted file mode 100644
index 2334cec..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/mixins/inspections/MixinImplementsMixinType.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.mixins.inspections;
-
-import com.intellij.codeInspection.InspectionManager;
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiAnnotationMemberValue;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiJavaCodeReferenceElement;
-import org.jetbrains.annotations.NotNull;
-import org.qi4j.ide.plugin.idea.common.inspections.AbstractFix;
-import org.qi4j.ide.plugin.idea.common.inspections.AbstractInspection;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
-import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
-import static org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle.message;
-import static org.qi4j.ide.plugin.idea.concerns.common.Qi4jConcernUtil.isAConcern;
-import static org.qi4j.ide.plugin.idea.mixins.common.Qi4jMixinUtil.*;
-import static org.qi4j.ide.plugin.idea.sideEffects.common.Qi4jSideEffectUtil.isASideEffect;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class MixinImplementsMixinType extends AbstractInspection
-{
-    @NotNull
-    protected final String resourceBundlePrefixId()
-    {
-        return "mixin.implements.mixin.type";
-    }
-
-    @NotNull
-    public final String getShortName()
-    {
-        return "MixinImplementsMixinType";
-    }
-
-    @Override
-    public final ProblemDescriptor[] checkClass( @NotNull PsiClass psiClass,
-                                                 @NotNull InspectionManager manager,
-                                                 boolean isOnTheFly )
-    {
-        // If psiClass is not an interface, ignore
-        if( !psiClass.isInterface() )
-        {
-            return null;
-        }
-
-        // If @Mixins annotation is empty, ignore
-        List<PsiAnnotationMemberValue> mixinAnnotationValues = getMixinsAnnotationValue( psiClass );
-        if( mixinAnnotationValues.isEmpty() )
-        {
-            return null;
-        }
-
-        // Get all valid mixin type
-        Set<PsiClass> validMixinsType = getAllValidMixinTypes( psiClass );
-        if( validMixinsType.isEmpty() )
-        {
-            return null;
-        }
-
-        // For each mixin
-        List<ProblemDescriptor> problems = new LinkedList<ProblemDescriptor>();
-        for( PsiAnnotationMemberValue mixinAnnotationValue : mixinAnnotationValues )
-        {
-            PsiJavaCodeReferenceElement mixinClassReference = getMixinClassReference( mixinAnnotationValue );
-
-            // If it's not a class reference, ignore
-            if( mixinClassReference == null )
-            {
-                continue;
-            }
-
-            // If class reference can't be resolved, ignore
-            PsiClass mixinClass = (PsiClass) mixinClassReference.resolve();
-            if( mixinClass == null )
-            {
-                continue;
-            }
-
-            String mixinQualifiedName = mixinClass.getQualifiedName();
-
-            boolean isMixinsDeclarationValid = false;
-            String message = "";
-            if( mixinClass.isInterface() )
-            {
-                // Mixin can't be an interface
-                message = message( "mixin.implements.mixin.type.error.mixin.is.an.interface", mixinQualifiedName );
-            }
-            else if( isAConcern( mixinClass ) )
-            {
-                // Mixin can't be a concern
-                message = message( "mixin.implements.mixin.type.error.mixin.is.a.concern", mixinQualifiedName );
-            }
-            else if( isASideEffect( mixinClass ) )
-            {
-                // Mixin can't be a side effect
-                message = message( "mixin.implements.mixin.type.error.mixin.is.a.side.effect", mixinQualifiedName );
-            }
-            else
-            {
-                // If doesn't implement any mixin type, it's a problem
-                if( !isImplementValidMixinType( mixinClass, validMixinsType ) )
-                {
-                    message = message(
-                        "mixin.implements.mixin.type.error.does.not.implement.any.mixin.type",
-                        mixinQualifiedName,
-                        psiClass.getQualifiedName()
-                    );
-                }
-                else
-                {
-                    isMixinsDeclarationValid = true;
-                }
-            }
-
-            if( !isMixinsDeclarationValid )
-            {
-                ProblemDescriptor problemDescriptor = createProblemDescriptor(
-                    manager, mixinAnnotationValue, mixinClassReference, message );
-                problems.add( problemDescriptor );
-            }
-        }
-
-        return problems.toArray( new ProblemDescriptor[problems.size()] );
-    }
-
-    private boolean isImplementValidMixinType( PsiClass mixinClass, Set<PsiClass> validMixinsType )
-    {
-        for( PsiClass validMixinTypeClass : validMixinsType )
-        {
-            if( mixinClass.isInheritor( validMixinTypeClass, true ) )
-            {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    private ProblemDescriptor createProblemDescriptor( @NotNull InspectionManager manager,
-                                                       @NotNull PsiAnnotationMemberValue mixinAnnotationValue,
-                                                       @NotNull PsiJavaCodeReferenceElement mixinClassReference,
-                                                       @NotNull String message )
-    {
-        RemoveInvalidMixinClassReferenceFix fix = new RemoveInvalidMixinClassReferenceFix(
-            mixinAnnotationValue, mixinClassReference
-        );
-        return manager.createProblemDescriptor( mixinAnnotationValue, message, fix, GENERIC_ERROR_OR_WARNING );
-    }
-
-    private static class RemoveInvalidMixinClassReferenceFix extends AbstractFix
-    {
-        private final PsiAnnotationMemberValue mixinClassAnnotationValue;
-
-        public RemoveInvalidMixinClassReferenceFix( @NotNull PsiAnnotationMemberValue mixinClassAnnotationValue,
-                                                    @NotNull PsiJavaCodeReferenceElement mixinClassReference )
-        {
-            super( message( "mixin.implements.mixin.type.fix.remove.class.reference", mixinClassReference.getQualifiedName() ) );
-            this.mixinClassAnnotationValue = mixinClassAnnotationValue;
-        }
-
-        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
-        {
-            mixinClassAnnotationValue.delete();
-        }
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/mixins/inspections/MixinsAnnotationDeclaredOnMixinType.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/mixins/inspections/MixinsAnnotationDeclaredOnMixinType.java
deleted file mode 100644
index 6339ce8..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/mixins/inspections/MixinsAnnotationDeclaredOnMixinType.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.mixins.inspections;
-
-import com.intellij.codeInspection.InspectionManager;
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiAnnotation;
-import com.intellij.psi.PsiAnnotationMemberValue;
-import com.intellij.psi.PsiClass;
-import org.jetbrains.annotations.NotNull;
-import org.qi4j.ide.plugin.idea.common.inspections.AbstractFix;
-import org.qi4j.ide.plugin.idea.common.inspections.AbstractInspection;
-
-import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
-import static org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle.message;
-import static org.qi4j.ide.plugin.idea.mixins.common.Qi4jMixinUtil.getMixinsAnnotation;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class MixinsAnnotationDeclaredOnMixinType extends AbstractInspection
-{
-    @NotNull
-    public final String getShortName()
-    {
-        return "MixinsAnnotationDeclaredOnMixinType";
-    }
-
-    @NotNull
-    protected final String resourceBundlePrefixId()
-    {
-        return "mixins.annotation.declared.on.mixin.type";
-    }
-
-    @Override
-    public ProblemDescriptor[] checkClass( @NotNull PsiClass psiClass,
-                                           @NotNull InspectionManager manager,
-                                           boolean isOnTheFly )
-    {
-        PsiAnnotation mixinsAnnotation = getMixinsAnnotation( psiClass );
-        if( mixinsAnnotation == null )
-        {
-            return null;
-        }
-
-        if( psiClass.isInterface() )
-        {
-            return null;
-        }
-
-        String message = message( "mixins.annotation.declared.on.mixin.type.error.declared.on.class" );
-        RemoveInvalidMixinClassReferenceFix fix = new RemoveInvalidMixinClassReferenceFix( mixinsAnnotation );
-        ProblemDescriptor problemDescriptor = manager.createProblemDescriptor( mixinsAnnotation, message, fix,
-                                                                               GENERIC_ERROR_OR_WARNING );
-        return new ProblemDescriptor[]{ problemDescriptor };
-
-    }
-
-    private static class RemoveInvalidMixinClassReferenceFix extends AbstractFix
-    {
-        private final PsiAnnotationMemberValue mixinsAnnotation;
-
-        public RemoveInvalidMixinClassReferenceFix( @NotNull PsiAnnotationMemberValue mixinsAnnotation )
-        {
-            super( message( "mixins.annotation.declared.on.mixin.type.fix.remove.mixins.annotation" ) );
-            this.mixinsAnnotation = mixinsAnnotation;
-        }
-
-        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
-        {
-            mixinsAnnotation.delete();
-        }
-    }
-}
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/sideEffects/common/Qi4jSideEffectConstants.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/sideEffects/common/Qi4jSideEffectConstants.java
deleted file mode 100644
index 5089f29..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/sideEffects/common/Qi4jSideEffectConstants.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.sideEffects.common;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jSideEffectConstants
-{
-    public static final String QUALIFIED_NAME_SIDE_EFFECTS = "org.qi4j.api.sideeffect.SideEffects";
-
-    public static final String QUALIFIED_NAME_SIDE_EFFECT_OF = "org.qi4j.api.sideeffect.SideEffectOf";
-    public static final String QUALIFIED_NAME_GENERIC_SIDE_EFFECT = "org.qi4j.api.sideeffect.GenericSideEffect";
-
-    private Qi4jSideEffectConstants()
-    {
-    }
-}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/sideEffects/common/Qi4jSideEffectUtil.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/sideEffects/common/Qi4jSideEffectUtil.java
deleted file mode 100644
index 43912d1..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/sideEffects/common/Qi4jSideEffectUtil.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.sideEffects.common;
-
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Collections;
-import java.util.List;
-
-import static com.intellij.codeInsight.AnnotationUtil.findAnnotation;
-import static java.util.Collections.emptyList;
-import static org.qi4j.ide.plugin.idea.common.psi.PsiAnnotationUtil.getAnnotationDefaultParameterValue;
-import static org.qi4j.ide.plugin.idea.common.psi.PsiAnnotationUtil.getClassReference;
-import static org.qi4j.ide.plugin.idea.common.psi.PsiClassUtil.getPSIClass;
-import static org.qi4j.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
-import static org.qi4j.ide.plugin.idea.sideEffects.common.Qi4jSideEffectConstants.*;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class Qi4jSideEffectUtil
-{
-    /**
-     * @param searchContext Search context.
-     * @return {@code GenericSideEffect} class given the search context. {@code null} if not found.
-     * @since 0.1
-     */
-    @Nullable
-    public static PsiClass getGenericSideEffectClass( @NotNull PsiElement searchContext )
-    {
-        Project project = searchContext.getProject();
-        GlobalSearchScope searchScope = determineSearchScope( searchContext );
-        return getGenericSideEffectClass( project, searchScope );
-    }
-
-    /**
-     * @param project project.
-     * @param scope   search scope.
-     * @return {@code GenericSideEffect} class given {@code project} and {@code scope} parameters.
-     *         Returns {@code null} if not found.
-     * @since 0.1
-     */
-    @Nullable
-    public static PsiClass getGenericSideEffectClass( @NotNull Project project,
-                                                      @Nullable GlobalSearchScope scope )
-    {
-        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( project );
-        return scope == null ? null : psiFacade.findClass( QUALIFIED_NAME_GENERIC_SIDE_EFFECT, scope );
-    }
-
-    /**
-     * @param searchContext Search context.
-     * @return {@code SideEffectOf} class given the search context. {@code null} if not found.
-     * @since 0.1
-     */
-    @Nullable
-    public static PsiClass getSideEffectOfClass( @NotNull PsiElement searchContext )
-    {
-        Project project = searchContext.getProject();
-        GlobalSearchScope searchScope = determineSearchScope( searchContext );
-        return getSideEffectOfClass( project, searchScope );
-    }
-
-
-    /**
-     * @param project project.
-     * @param scope   search scope.
-     * @return {@code SideEffectOf} class given {@code project} and {@code scope} parameters.
-     *         Returns {@code null} if not found.
-     * @since 0.1
-     */
-    @Nullable
-    public static PsiClass getSideEffectOfClass( @NotNull Project project,
-                                                 @Nullable GlobalSearchScope scope )
-    {
-        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( project );
-        return scope == null ? null : psiFacade.findClass( QUALIFIED_NAME_SIDE_EFFECT_OF, scope );
-    }
-
-    /**
-     * @param elementWithinJavaClass element within java class.
-     * @return {@code @SideEffects} annotation declaration of the class that contains the element.
-     *         Returns {@code null} if not found, or {@code element} is an invalid context.
-     * @since 0.1
-     */
-    @Nullable
-    public static PsiAnnotation getSideEffectsAnnotation( @NotNull PsiElement elementWithinJavaClass )
-    {
-        PsiClass psiClass = getPSIClass( elementWithinJavaClass );
-        return findAnnotation( psiClass, QUALIFIED_NAME_SIDE_EFFECTS );
-    }
-
-    /**
-     * @param annotation annotation to process.
-     * @return {@code @SideEffects} annotation value. Returns {@link Collections#emptyList()} if {@code annotation} is
-     *         {@code null} or annotation is not a {@code @SideEffects} annotation.
-     * @since 0.1
-     */
-    @NotNull
-    public static List<PsiAnnotationMemberValue> getSideEffectsAnnotationValue( @Nullable PsiAnnotation annotation )
-    {
-        if( annotation == null )
-        {
-            return emptyList();
-        }
-
-        String concernsQualifiedName = annotation.getQualifiedName();
-        if( !QUALIFIED_NAME_SIDE_EFFECTS.equals( concernsQualifiedName ) )
-        {
-            return emptyList();
-        }
-
-        return getAnnotationDefaultParameterValue( annotation );
-    }
-
-    /**
-     * @param value annotation member value.
-     * @return Side effect class reference given the {@code value} parameter. Returns {@code null} if it's not a
-     *         class reference.
-     * @since 0.1
-     */
-    @Nullable
-    public static PsiJavaCodeReferenceElement getSideEffectClassReference( @NotNull PsiAnnotationMemberValue value )
-    {
-        return getClassReference( value );
-    }
-
-    /**
-     * Returns a {@code boolean} indicator whether the specified {@code psiClass} is a side effect.
-     *
-     * @param psiClass class to check.
-     * @return {@code true} if {@code psiClass} is a side effect, {@code false} otherwise.
-     * @since 0.1
-     */
-    public static boolean isASideEffect( @NotNull PsiClass psiClass )
-    {
-        if( psiClass.isInterface() )
-        {
-            return false;
-        }
-
-        PsiClass sideEffectOfClass = getSideEffectOfClass( psiClass );
-        return sideEffectOfClass != null && psiClass.isInheritor( sideEffectOfClass, true );
-    }
-
-    /**
-     * @param psiClass psi class to check.
-     * @return {@code true} if {@code psiClass} inherits {@code GenericSideEffect} class, {@code false} if
-     *         {@code psiClass} does
-     *         not inherit {@code GenericSideEffect} or {@code GenericSideEffect} is not found.
-     * @since 0.1
-     */
-    public static boolean isAGenericSideEffect( @NotNull PsiClass psiClass )
-    {
-        if( psiClass.isInterface() )
-        {
-            return false;
-        }
-
-        PsiClass genericSideEffect = getGenericSideEffectClass( psiClass );
-        return genericSideEffect != null && psiClass.isInheritor( genericSideEffect, true );
-    }
-
-    private Qi4jSideEffectUtil()
-    {
-    }
-}
\ No newline at end of file
diff --git a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/sideEffects/inspections/SideEffectsAnnotationDeclaredCorrectlyInspection.java b/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/sideEffects/inspections/SideEffectsAnnotationDeclaredCorrectlyInspection.java
deleted file mode 100644
index ac4bb90..0000000
--- a/tools/qidea/src/main/java/org/qi4j/ide/plugin/idea/sideEffects/inspections/SideEffectsAnnotationDeclaredCorrectlyInspection.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*  Copyright 2008 Edward Yakop.
-*
-* Licensed 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.qi4j.ide.plugin.idea.sideEffects.inspections;
-
-import com.intellij.codeInspection.InspectionManager;
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiAnnotation;
-import com.intellij.psi.PsiAnnotationMemberValue;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiJavaCodeReferenceElement;
-import com.intellij.psi.search.GlobalSearchScope;
-import org.jetbrains.annotations.NotNull;
-import org.qi4j.ide.plugin.idea.common.inspections.AbstractFix;
-import org.qi4j.ide.plugin.idea.common.inspections.AbstractInspection;
-import org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle;
-import org.qi4j.ide.plugin.idea.sideEffects.common.Qi4jSideEffectUtil;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
-import static org.qi4j.ide.plugin.idea.common.psi.search.GlobalSearchScopeUtil.determineSearchScope;
-import static org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle.message;
-import static org.qi4j.ide.plugin.idea.sideEffects.common.Qi4jSideEffectUtil.*;
-
-/**
- * @author edward.yakop@gmail.com
- * @since 0.1
- */
-public final class SideEffectsAnnotationDeclaredCorrectlyInspection extends AbstractInspection
-{
-    @NotNull
-    protected final String resourceBundlePrefixId()
-    {
-        return "side.effects.annotation.declared.correctly";
-    }
-
-    @NotNull
-    public final String getShortName()
-    {
-        return "SideEffectsAnnotationDeclaredCorrectlyInspection";
-    }
-
-    @Override
-    public final ProblemDescriptor[] checkClass( @NotNull PsiClass psiClass,
-                                                 @NotNull InspectionManager manager,
-                                                 boolean isOnTheFly )
-    {
-        // If class does not have @SideEffects, ignore
-        PsiAnnotation sideEffectsAnnotation = getSideEffectsAnnotation( psiClass );
-        if( sideEffectsAnnotation == null )
-        {
-            return null;
-        }
-
-        // If @SideEffects declared in class, suggest remove @SideEffects annotation
-        if( !psiClass.isInterface() )
-        {
-            String message = message( "side.effects.annotation.declared.correctly.error.annotation.declared.in.class" );
-            RemoveSideEffectsAnnotationFix fix = new RemoveSideEffectsAnnotationFix( sideEffectsAnnotation );
-            ProblemDescriptor problemDescriptor = manager.createProblemDescriptor( sideEffectsAnnotation, message, fix,
-                                                                                   GENERIC_ERROR_OR_WARNING );
-            return new ProblemDescriptor[]{ problemDescriptor };
-        }
-
-        // If @SideEffects annotation is empty, ignore
-        List<PsiAnnotationMemberValue> sideEffectsAnnotationValue =
-            getSideEffectsAnnotationValue( sideEffectsAnnotation );
-        if( sideEffectsAnnotationValue.isEmpty() )
-        {
-            return null;
-        }
-
-        // If SideEffectOf is not resolved, ignore
-        Project project = psiClass.getProject();
-        GlobalSearchScope searchScope = determineSearchScope( psiClass );
-        PsiClass sideEffectOfClass = Qi4jSideEffectUtil.getGenericSideEffectClass( project, searchScope );
-        if( sideEffectOfClass == null )
-        {
-            return null;
-        }
-
-        List<ProblemDescriptor> problems = new LinkedList<ProblemDescriptor>();
-        for( PsiAnnotationMemberValue sideEffectClassReferenceWrapper : sideEffectsAnnotationValue )
-        {
-            PsiJavaCodeReferenceElement sideEffectClassReference =
-                getSideEffectClassReference( sideEffectClassReferenceWrapper );
-
-            // If it's not a class reference, ignore
-            if( sideEffectClassReference == null )
-            {
-                continue;
-            }
-
-            // If class reference can't be resolved, ignore
-            PsiClass sideEffectClass = (PsiClass) sideEffectClassReference.resolve();
-            if( sideEffectClass == null )
-            {
-                continue;
-            }
-
-            // If side effect class does not inherit SideEffectOf class, suggest remove that reference.
-            if( !sideEffectClass.isInheritor( sideEffectOfClass, true ) )
-            {
-                String message = Qi4jResourceBundle.message(
-                    "side.effects.annotation.declared.correctly.error.side.effect.does.not.extend.side.effect.of",
-                    sideEffectClass.getQualifiedName()
-                );
-
-                RemoveAnnotationValueFix fix = new RemoveAnnotationValueFix(
-                    sideEffectClassReferenceWrapper, sideEffectClassReference
-                );
-                ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(
-                    sideEffectClassReferenceWrapper, message, fix, GENERIC_ERROR_OR_WARNING );
-                problems.add( problemDescriptor );
-            }
-            else
-            {
-                // TODO: Test whether it is a generic side effect
-                // TODO: Test whether it is a specific side effect
-            }
-        }
-
-        return problems.toArray( new ProblemDescriptor[problems.size()] );
-    }
-
-    private static class RemoveSideEffectsAnnotationFix extends AbstractFix
-    {
-        private final PsiAnnotation sideEffectsAnnotation;
-
-        private RemoveSideEffectsAnnotationFix( @NotNull PsiAnnotation sideEffectsAnnotation )
-        {
-            super( message( "side.effects.annotation.declared.correctly.fix.remove.annotation" ) );
-            this.sideEffectsAnnotation = sideEffectsAnnotation;
-        }
-
-        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
-        {
-            sideEffectsAnnotation.delete();
-        }
-    }
-
-    private static class RemoveAnnotationValueFix extends AbstractFix
-    {
-        private final PsiAnnotationMemberValue annotationValueToRemove;
-
-        private RemoveAnnotationValueFix( @NotNull PsiAnnotationMemberValue annotationValueToRemove,
-                                          @NotNull PsiJavaCodeReferenceElement sideEffectClassReference )
-        {
-            super( message( "side.effects.annotation.declared.correctly.fix.remove.class.reference",
-                            sideEffectClassReference.getQualifiedName() ) );
-            this.annotationValueToRemove = annotationValueToRemove;
-        }
-
-        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
-        {
-            annotationValueToRemove.delete();
-        }
-    }
-}
\ No newline at end of file
diff --git a/tools/qidea/src/main/resources/META-INF/plugin.xml b/tools/qidea/src/main/resources/META-INF/plugin.xml
index 5a4a6e6..b8ec86e 100644
--- a/tools/qidea/src/main/resources/META-INF/plugin.xml
+++ b/tools/qidea/src/main/resources/META-INF/plugin.xml
@@ -1,24 +1,28 @@
-<!DOCTYPE idea-plugin PUBLIC "Plugin/DTD" "http://plugins.intellij.net/plugin.dtd">
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
+
+<!DOCTYPE idea-plugin PUBLIC "Plugin/DTD" "http://plugins.intellij.net/plugin.dtd">
 <idea-plugin>
-  <id>org.qi4j</id>
+  <id>org.apache.polygene</id>
   <name>qidea</name>
-  <description>Apache Zest™ idea plugin</description>
+  <description>Apache Polygene™ idea plugin</description>
   <version>0.1</version>
   <vendor>codedragons</vendor>
   <idea-version since-build="8000"/>
@@ -27,21 +31,21 @@
 
   <application-components>
     <component>
-      <implementation-class>org.qi4j.ide.plugin.idea.Qi4jApplicationComponent</implementation-class>
+      <implementation-class>org.apache.polygene.ide.plugin.idea.PolygeneApplicationComponent</implementation-class>
     </component>
   </application-components>
 
   <actions>
     <action id="CreateConcernFromMixinTypeOrCompositeAction"
-            class="org.qi4j.ide.plugin.idea.concerns.actions.create.CreateConcernFromMixinTypeOrCompositeAction"
-            text="New Concern" description="Create new Zest™ concern">
+            class="org.apache.polygene.ide.plugin.idea.concerns.actions.create.CreateConcernFromMixinTypeOrCompositeAction"
+            text="New Concern" description="Create new Polygene™ concern">
       <add-to-group group-id="CodeMenu" anchor="last"/>
     </action>
 
-    <group id="Zest" class="org.qi4j.ide.plugin.idea.common.actions.Qi4jCreateActionGroup" text="Zest™">
-      <action id="Zest.NewConcernOf"
-              class="org.qi4j.ide.plugin.idea.concerns.actions.create.inPackage.CreateConcernOfInPackageAction"
-              text="New Concern" description="Create new Zest concern">
+    <group id="Polygene" class="org.apache.polygene.ide.plugin.idea.common.actions.PolygeneCreateActionGroup" text="Polygene™">
+      <action id="Polygene.NewConcernOf"
+              class="org.apache.polygene.ide.plugin.idea.concerns.actions.create.inPackage.CreateConcernOfInPackageAction"
+              text="New Concern" description="Create new Polygene concern">
       </action>
       <add-to-group group-id="NewGroup" anchor="last"/>
     </group>
diff --git a/tools/qidea/src/main/resources/fileTemplates/j2ee/GenericConcernOf.java.ft b/tools/qidea/src/main/resources/fileTemplates/j2ee/GenericConcernOf.java.ft
index db707e7..3269aa5 100644
--- a/tools/qidea/src/main/resources/fileTemplates/j2ee/GenericConcernOf.java.ft
+++ b/tools/qidea/src/main/resources/fileTemplates/j2ee/GenericConcernOf.java.ft
@@ -1,7 +1,6 @@
 package ${PACKAGE_NAME};
 
-import java.lang.reflect.Method;
-import org.qi4j.api.concern.GenericConcern;
+import org.apache.polygene.api.concern.GenericConcern;
 
 #parse("File Header.java")
 public class ${NAME} extends GenericConcern
diff --git a/tools/qidea/src/main/resources/fileTemplates/j2ee/GenericConcernOf.java.html b/tools/qidea/src/main/resources/fileTemplates/j2ee/GenericConcernOf.java.html
index 10ea9e8..7ba8aee 100644
--- a/tools/qidea/src/main/resources/fileTemplates/j2ee/GenericConcernOf.java.html
+++ b/tools/qidea/src/main/resources/fileTemplates/j2ee/GenericConcernOf.java.html
@@ -1,3 +1,23 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
         "http://www.w3.org/TR/html4/loose.dtd">
 <html>
@@ -22,7 +42,7 @@
     <tr>
         <td colspan="3">
             <font face="verdana" size="-1">
-                This is a template used by <b>IDEA</b> each time you create Qi4j generic concern of.
+                This is a template used by <b>IDEA</b> each time you create Polygene generic concern of.
             </font>
         </td>
     </tr>
diff --git a/tools/qidea/src/main/resources/inspectionDescriptions/ConcernsAnnotationDeclaredCorrectlyInspection.html b/tools/qidea/src/main/resources/inspectionDescriptions/ConcernsAnnotationDeclaredCorrectlyInspection.html
index 5d85e6a..db2cda2 100644
--- a/tools/qidea/src/main/resources/inspectionDescriptions/ConcernsAnnotationDeclaredCorrectlyInspection.html
+++ b/tools/qidea/src/main/resources/inspectionDescriptions/ConcernsAnnotationDeclaredCorrectlyInspection.html
@@ -1,3 +1,23 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <html>
 <!--
   Licensed to the Apache Software Foundation (ASF) under one or more
@@ -17,7 +37,7 @@
 -->
 <body>
 <font face="verdana" size="-1">This inspection reports any @Concerns declarations value that does not implement
-    [org.qi4j.composite.ConcernOf] class.
+    [org.apache.polygene.composite.ConcernOf] class.
 </font>
 </body>
 </html>
diff --git a/tools/qidea/src/main/resources/intentionDescriptions/AddConcernOnType/description.html b/tools/qidea/src/main/resources/intentionDescriptions/AddConcernOnType/description.html
index 51f48f9..e744ef0 100644
--- a/tools/qidea/src/main/resources/intentionDescriptions/AddConcernOnType/description.html
+++ b/tools/qidea/src/main/resources/intentionDescriptions/AddConcernOnType/description.html
@@ -1,3 +1,23 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+
 <html>
 <!--
   Licensed to the Apache Software Foundation (ASF) under one or more
diff --git a/tools/qidea/src/main/resources/org/apache/polygene/ide/plugin/idea/common/resource/PolygeneResourceBundle.properties b/tools/qidea/src/main/resources/org/apache/polygene/ide/plugin/idea/common/resource/PolygeneResourceBundle.properties
new file mode 100644
index 0000000..8c5f29b
--- /dev/null
+++ b/tools/qidea/src/main/resources/org/apache/polygene/ide/plugin/idea/common/resource/PolygeneResourceBundle.properties
@@ -0,0 +1,164 @@
+#
+#  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.
+#
+#
+#
+
+# *****************************************************************************
+# Common
+# *****************************************************************************
+polygene.quick.fixes.family.name=Polygene
+polygene.action.group.title=Polygene
+polygene.action.group.description=Polygene
+polygene.inspections.name=Polygene issues
+polygene.file.template.group.title=Polygene
+
+# *****************************************************************************
+# Concern
+# *****************************************************************************
+
+# =========
+# Intention
+# =========
+add.concern.family.name=Add Polygene Concern
+add.concern.name=Add Polygene Concern
+
+# ==========
+# Inspection
+# ==========
+concerns.annotation.declared.correctly.name.display=Concern class extends ConcernOf abstract class
+concerns.annotation.declared.correctly.error.concern.class.does.not.extend.ConcernOf=Concern class ''{0}'' does not inherit ''org.apache.polygene.composite.ConcernOf'' class.
+concerns.annotation.declared.correctly.fix.remove.concern.class.reference=Remove ''{0}'' concern class reference.
+concerns.annotation.declared.correctly.error.annotation.declared.in.class=@Concerns annotation can only be declared at interface
+concerns.annotation.declared.correctly.fix.remove.annotation=Remove @Concerns annotation
+
+# =======
+# Actions
+# =======
+
+# -------------------------
+# Create concern in package
+# -------------------------
+createConcernOfInPackage.menu.action.text=Polygene Concern Of
+createConcernOfInPackage.menu.action.description=Creates new Polygene ConcernOf
+createConcernOfInPackage.dlg.title=New Polygene ConcernOf
+createConcernOfInPackage.dlg.prompt=Enter name for new ConcernOf
+createConcernOfInPackage.command.name=Create ConcernOf
+createConcernOfInPackage.progress.text=Creating ConcernOf ''{0}'' class
+createConcernOfInPackage.error.title=Create concern fail
+
+# *****************************************************************************
+# Mixin
+# *****************************************************************************
+
+# ==========
+# Inspection
+# ==========
+
+# ----------------------------
+# Mixins implements mixin type
+# ----------------------------
+mixin.implements.mixin.type.name.display=Mixin class implements Mixin type class
+mixin.implements.mixin.type.fix.remove.class.reference=Remove ''{0}'' mixin class reference.
+mixin.implements.mixin.type.error.does.not.implement.any.mixin.type=Mixin class ''{0}'' does not inherit any mixin type of ''{1}''
+mixin.implements.mixin.type.error.mixin.is.an.interface=Mixin class ''{0}'' is an interface
+mixin.implements.mixin.type.error.mixin.is.a.concern=''{0}'' class is a concern
+mixin.implements.mixin.type.error.mixin.is.a.side.effect=''{0}'' class is a side effect
+
+# ------------------------------------------
+# Mixins declared on mixin type or composite
+# ------------------------------------------
+mixins.annotation.declared.on.mixin.type.name.display=@Mixins must be declared on interface
+mixins.annotation.declared.on.mixin.type.error.declared.on.class=@Mixins can only be declared on interface
+mixins.annotation.declared.on.mixin.type.fix.remove.mixins.annotation=Remove @Mixins annotation
+
+# *****************************************************************************
+# Side Effect
+# *****************************************************************************
+
+# ==========
+# Inspection
+# ==========
+side.effects.annotation.declared.correctly.name.display=@SideEffects annotation declared correctly
+side.effects.annotation.declared.correctly.error.side.effect.does.not.extend.side.effect.of=Side Effect class ''{0}'' does not inherit ''org.apache.polygene.composite.SideEffectOf'' class.
+side.effects.annotation.declared.correctly.fix.remove.class.reference=Remove ''{0}'' class reference
+side.effects.annotation.declared.correctly.error.annotation.declared.in.class=@SideEffects annotation can only be declared at interface
+side.effects.annotation.declared.correctly.fix.remove.annotation=Remove @SideEffects annotation
+
+# *****************************************************************************
+# Injections
+# *****************************************************************************
+
+# -----------------
+# Common Inspection
+# -----------------
+abstract.injection.annotation.declaration.inspection.error.annotation.not.declared.correctly=''{0}'' can only be declared in constructor parameters or non static class field.
+
+# -------------------
+# @Structure injection
+# -------------------
+
+# ==========
+# Inspection
+# ==========
+injections.structure.annotation.declared.correctly.name.display=@Structure Injection
+injections.structure.annotation.declared.correctly.error.invalid.injection.type=@Structure does not inject ''{0}'' type.
+injections.structure.annotation.declared.correctly.fix.remove.annotation=Remove @Structure annotation
+
+# -----------------
+# @Service injection
+# -----------------
+
+# ==========
+# Inspection
+# ==========
+injections.service.annotation.declared.correctly.name.display=@Service Injection
+injections.service.annotation.declared.correctly.error.type.is.injected.by.structure=''{0}'' type is injected by @Structure
+injections.service.annotation.declared.correctly.fix.remove.annotation=Remove @Service annotation
+injections.service.annotation.declared.correctly.fix.replace.with.structure.annotation=Replace @Service with @Structure annotation
+
+# -----------------
+# @Invocation injection
+# -----------------
+
+# ==========
+# Inspection
+# ==========
+injections.invocation.annotation.declared.correctly.name.display=@Invocation Injection
+injections.invocation.annotation.declared.correctly.error.type.is.injected.by.structure=''{0}'' type is injected by @Structure
+injections.invocation.annotation.declared.correctly.error.type.is.not.injectable=''{0}'' type is not injectable by @Invocation
+injections.invocation.annotation.declared.correctly.fix.remove.annotation=Remove @Invocation annotation
+injections.invocation.annotation.declared.correctly.fix.replace.with.structure.annotation=Replace @Invocation with @Structure annotation
+
+# *****************************************************************************
+# Applies To
+# *****************************************************************************
+
+# ==========
+# Inspection
+# ==========
+applies.to.annotation.declared.correctly.error.annotation.must.be.declared.on.class=@AppliesTo must be declared on class
+applies.to.annotation.declared.correctly.error.value.is.invalid.for.mixin=''{0}'' is neither an interface or implements ''AppliesToFilter''
+applies.to.annotation.declared.correctly.error.value.requires.class.to.extends.GenericConcern=''{0}'' requires ''{1}'' to extends GenericConcern
+applies.to.annotation.declared.correctly.error.value.requires.class.to.extends.GenericSideEffect=''{0}'' requires ''{1}'' to extends GenericSideEffect
+applies.to.annotation.declared.correctly.error.value.requires.class.to.implements.InvocationHandler=''{0}'' requires ''{1}'' to implements InvocationHandler
+applies.to.annotation.declared.correctly.error.value.requires.class.to.implement.interface.or.extends.GenericConcern=''{0}'' requires ''{1}'' to implement ''{0}'' interface or to extends ''GenericConcern''
+applies.to.annotation.declared.correctly.error.value.requires.class.to.implement.interface.or.extends.GenericSideEffect=''{0}'' requires ''{1}'' to implement ''{0}'' interface or to extends ''GenericSideEffect''
+applies.to.annotation.declared.correctly.error.value.requires.class.to.implement.value.interface.or.implements.InvocationHandler=''{0}'' requires ''{1}'' to implement ''{0}'' or ''InvocationHandler'' interface
+applies.to.annotation.declared.correctly.error.annotation.value.is.invalid.for.non.mixin=''{0}'' is not an annotation or ''AppliesToFilter'' or an interface
+applies.to.annotation.declared.correctly.fix.remove.annotation=Remove ''@AppliesTo'' annotation
+applies.to.annotation.declared.correctly.fix.remove.class.reference=Remove ''{0}'' class reference
diff --git a/tools/qidea/src/main/resources/org/qi4j/ide/plugin/idea/common/resource/Qi4jResourceBundle.properties b/tools/qidea/src/main/resources/org/qi4j/ide/plugin/idea/common/resource/Qi4jResourceBundle.properties
deleted file mode 100644
index cd8c07c..0000000
--- a/tools/qidea/src/main/resources/org/qi4j/ide/plugin/idea/common/resource/Qi4jResourceBundle.properties
+++ /dev/null
@@ -1,159 +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.
-
-# *****************************************************************************
-# Common
-# *****************************************************************************
-qi4j.quick.fixes.family.name=Qi4j
-qi4j.action.group.title=Qi4j
-qi4j.action.group.description=Qi4j
-qi4j.inspections.name=Qi4j issues
-qi4j.file.template.group.title=Qi4j
-
-# *****************************************************************************
-# Concern
-# *****************************************************************************
-
-# =========
-# Intention
-# =========
-add.concern.family.name=Add Qi4j Concern
-add.concern.name=Add Qi4j Concern
-
-# ==========
-# Inspection
-# ==========
-concerns.annotation.declared.correctly.name.display=Concern class extends ConcernOf abstract class
-concerns.annotation.declared.correctly.error.concern.class.does.not.extend.ConcernOf=Concern class ''{0}'' does not inherit ''org.qi4j.composite.ConcernOf'' class.
-concerns.annotation.declared.correctly.fix.remove.concern.class.reference=Remove ''{0}'' concern class reference.
-concerns.annotation.declared.correctly.error.annotation.declared.in.class=@Concerns annotation can only be declared at interface
-concerns.annotation.declared.correctly.fix.remove.annotation=Remove @Concerns annotation
-
-# =======
-# Actions
-# =======
-
-# -------------------------
-# Create concern in package
-# -------------------------
-createConcernOfInPackage.menu.action.text=Qi4j Concern Of
-createConcernOfInPackage.menu.action.description=Creates new Qi4j ConcernOf
-createConcernOfInPackage.dlg.title=New Qi4j ConcernOf
-createConcernOfInPackage.dlg.prompt=Enter name for new ConcernOf
-createConcernOfInPackage.command.name=Create ConcernOf
-createConcernOfInPackage.progress.text=Creating ConcernOf ''{0}'' class
-createConcernOfInPackage.error.title=Create concern fail
-
-# *****************************************************************************
-# Mixin
-# *****************************************************************************
-
-# ==========
-# Inspection
-# ==========
-
-# ----------------------------
-# Mixins implements mixin type
-# ----------------------------
-mixin.implements.mixin.type.name.display=Mixin class implements Mixin type class
-mixin.implements.mixin.type.fix.remove.class.reference=Remove ''{0}'' mixin class reference.
-mixin.implements.mixin.type.error.does.not.implement.any.mixin.type=Mixin class ''{0}'' does not inherit any mixin type of ''{1}''
-mixin.implements.mixin.type.error.mixin.is.an.interface=Mixin class ''{0}'' is an interface
-mixin.implements.mixin.type.error.mixin.is.a.concern=''{0}'' class is a concern
-mixin.implements.mixin.type.error.mixin.is.a.side.effect=''{0}'' class is a side effect
-
-# ------------------------------------------
-# Mixins declared on mixin type or composite
-# ------------------------------------------
-mixins.annotation.declared.on.mixin.type.name.display=@Mixins must be declared on interface
-mixins.annotation.declared.on.mixin.type.error.declared.on.class=@Mixins can only be declared on interface
-mixins.annotation.declared.on.mixin.type.fix.remove.mixins.annotation=Remove @Mixins annotation
-
-# *****************************************************************************
-# Side Effect
-# *****************************************************************************
-
-# ==========
-# Inspection
-# ==========
-side.effects.annotation.declared.correctly.name.display=@SideEffects annotation declared correctly
-side.effects.annotation.declared.correctly.error.side.effect.does.not.extend.side.effect.of=Side Effect class ''{0}'' does not inherit ''org.qi4j.composite.SideEffectOf'' class.
-side.effects.annotation.declared.correctly.fix.remove.class.reference=Remove ''{0}'' class reference
-side.effects.annotation.declared.correctly.error.annotation.declared.in.class=@SideEffects annotation can only be declared at interface
-side.effects.annotation.declared.correctly.fix.remove.annotation=Remove @SideEffects annotation
-
-# *****************************************************************************
-# Injections
-# *****************************************************************************
-
-# -----------------
-# Common Inspection
-# -----------------
-abstract.injection.annotation.declaration.inspection.error.annotation.not.declared.correctly=''{0}'' can only be declared in constructor parameters or non static class field.
-
-# -------------------
-# @Structure injection
-# -------------------
-
-# ==========
-# Inspection
-# ==========
-injections.structure.annotation.declared.correctly.name.display=@Structure Injection
-injections.structure.annotation.declared.correctly.error.invalid.injection.type=@Structure does not inject ''{0}'' type.
-injections.structure.annotation.declared.correctly.fix.remove.annotation=Remove @Structure annotation
-
-# -----------------
-# @Service injection
-# -----------------
-
-# ==========
-# Inspection
-# ==========
-injections.service.annotation.declared.correctly.name.display=@Service Injection
-injections.service.annotation.declared.correctly.error.type.is.injected.by.structure=''{0}'' type is injected by @Structure
-injections.service.annotation.declared.correctly.fix.remove.annotation=Remove @Service annotation
-injections.service.annotation.declared.correctly.fix.replace.with.structure.annotation=Replace @Service with @Structure annotation
-
-# -----------------
-# @Invocation injection
-# -----------------
-
-# ==========
-# Inspection
-# ==========
-injections.invocation.annotation.declared.correctly.name.display=@Invocation Injection
-injections.invocation.annotation.declared.correctly.error.type.is.injected.by.structure=''{0}'' type is injected by @Structure
-injections.invocation.annotation.declared.correctly.error.type.is.not.injectable=''{0}'' type is not injectable by @Invocation
-injections.invocation.annotation.declared.correctly.fix.remove.annotation=Remove @Invocation annotation
-injections.invocation.annotation.declared.correctly.fix.replace.with.structure.annotation=Replace @Invocation with @Structure annotation
-
-# *****************************************************************************
-# Applies To
-# *****************************************************************************
-
-# ==========
-# Inspection
-# ==========
-applies.to.annotation.declared.correctly.error.annotation.must.be.declared.on.class=@AppliesTo must be declared on class
-applies.to.annotation.declared.correctly.error.value.is.invalid.for.mixin=''{0}'' is neither an interface or implements ''AppliesToFilter''
-applies.to.annotation.declared.correctly.error.value.requires.class.to.extends.GenericConcern=''{0}'' requires ''{1}'' to extends GenericConcern
-applies.to.annotation.declared.correctly.error.value.requires.class.to.extends.GenericSideEffect=''{0}'' requires ''{1}'' to extends GenericSideEffect
-applies.to.annotation.declared.correctly.error.value.requires.class.to.implements.InvocationHandler=''{0}'' requires ''{1}'' to implements InvocationHandler
-applies.to.annotation.declared.correctly.error.value.requires.class.to.implement.interface.or.extends.GenericConcern=''{0}'' requires ''{1}'' to implement ''{0}'' interface or to extends ''GenericConcern''
-applies.to.annotation.declared.correctly.error.value.requires.class.to.implement.interface.or.extends.GenericSideEffect=''{0}'' requires ''{1}'' to implement ''{0}'' interface or to extends ''GenericSideEffect''
-applies.to.annotation.declared.correctly.error.value.requires.class.to.implement.value.interface.or.implements.InvocationHandler=''{0}'' requires ''{1}'' to implement ''{0}'' or ''InvocationHandler'' interface
-applies.to.annotation.declared.correctly.error.annotation.value.is.invalid.for.non.mixin=''{0}'' is not an annotation or ''AppliesToFilter'' or an interface
-applies.to.annotation.declared.correctly.fix.remove.annotation=Remove ''@AppliesTo'' annotation
-applies.to.annotation.declared.correctly.fix.remove.class.reference=Remove ''{0}'' class reference
diff --git a/tools/shell/build.gradle b/tools/shell/build.gradle
deleted file mode 100644
index 19d1ed7..0000000
--- a/tools/shell/build.gradle
+++ /dev/null
@@ -1,31 +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.
- */
-
-apply plugin: 'application'
-
-description = "Command line tools for building Apache Zest™ applications."
-mainClassName = "org.qi4j.tools.shell.Main"
-
-jar { manifest { name = "Apache Zest™ Command Line" } }
-
-dependencies {
-  compile( project( ":org.qi4j.core:org.qi4j.core.bootstrap" ) )
-
-  testRuntime( libraries.logback )
-}
diff --git a/tools/shell/src/bin/qi4j b/tools/shell/src/bin/qi4j
deleted file mode 100644
index 544595b..0000000
--- a/tools/shell/src/bin/qi4j
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/sh
-
-# 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.
-
-java -jar org.qi4j.tools.shell-@@version@@.jar "$@"
-
diff --git a/tools/shell/src/etc/templates/defaultproject/project.properties b/tools/shell/src/etc/templates/defaultproject/project.properties
deleted file mode 100644
index a779d4f..0000000
--- a/tools/shell/src/etc/templates/defaultproject/project.properties
+++ /dev/null
@@ -1,15 +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.
-
diff --git a/tools/shell/src/main/java/org/qi4j/tools/shell/AbstractCommand.java b/tools/shell/src/main/java/org/qi4j/tools/shell/AbstractCommand.java
deleted file mode 100644
index 9b6441a..0000000
--- a/tools/shell/src/main/java/org/qi4j/tools/shell/AbstractCommand.java
+++ /dev/null
@@ -1,30 +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.qi4j.tools.shell;
-
-public abstract class AbstractCommand
-    implements Command, Comparable<Command>
-{
-
-    @Override
-    public int compareTo( Command o )
-    {
-        return getClass().getSimpleName().compareTo( o.getClass().getSimpleName() );
-    }
-}
diff --git a/tools/shell/src/main/java/org/qi4j/tools/shell/Command.java b/tools/shell/src/main/java/org/qi4j/tools/shell/Command.java
deleted file mode 100644
index a6f0cc5..0000000
--- a/tools/shell/src/main/java/org/qi4j/tools/shell/Command.java
+++ /dev/null
@@ -1,32 +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.qi4j.tools.shell;
-
-import java.io.BufferedReader;
-import java.io.PrintWriter;
-
-public interface Command
-{
-    void execute( String[] args, BufferedReader input, PrintWriter output )
-        throws HelpNeededException;
-
-    String description();
-
-    String name();
-}
diff --git a/tools/shell/src/main/java/org/qi4j/tools/shell/FileUtils.java b/tools/shell/src/main/java/org/qi4j/tools/shell/FileUtils.java
deleted file mode 100644
index ccd21fe..0000000
--- a/tools/shell/src/main/java/org/qi4j/tools/shell/FileUtils.java
+++ /dev/null
@@ -1,69 +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.qi4j.tools.shell;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
-public class FileUtils
-{
-    public static void createDir( String directoryName )
-    {
-        File dir = new File( directoryName ).getAbsoluteFile();
-        if( !dir.mkdirs() )
-        {
-            System.err.println( "Unable to create directory " + dir );
-            System.exit( 1 );
-        }
-    }
-
-    public static Map<String, String> readPropertiesResource( String resourceName )
-    {
-        ClassLoader cl = FileUtils.class.getClassLoader();
-        InputStream in = cl.getResourceAsStream( resourceName );
-        try
-        {
-            Properties properties = readProperties( in );
-            Map<String, String> result = new HashMap<String, String>();
-            for( Map.Entry prop : properties.entrySet() )
-            {
-                result.put( prop.getKey().toString(), prop.getValue().toString() );
-            }
-            return result;
-        }
-        catch( IOException e )
-        {
-            System.err.println( "Unable to read resource " + resourceName );
-            System.exit( 2 );
-            return null;
-        }
-    }
-
-    private static Properties readProperties( InputStream in )
-        throws IOException
-    {
-        Properties p = new Properties();
-        p.load( in );
-        return p;
-    }
-}
diff --git a/tools/shell/src/main/java/org/qi4j/tools/shell/HelpNeededException.java b/tools/shell/src/main/java/org/qi4j/tools/shell/HelpNeededException.java
deleted file mode 100644
index 7291121..0000000
--- a/tools/shell/src/main/java/org/qi4j/tools/shell/HelpNeededException.java
+++ /dev/null
@@ -1,23 +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.qi4j.tools.shell;
-
-public class HelpNeededException extends RuntimeException
-{
-}
diff --git a/tools/shell/src/main/java/org/qi4j/tools/shell/Main.java b/tools/shell/src/main/java/org/qi4j/tools/shell/Main.java
deleted file mode 100644
index be15e24..0000000
--- a/tools/shell/src/main/java/org/qi4j/tools/shell/Main.java
+++ /dev/null
@@ -1,79 +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.qi4j.tools.shell;
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.util.TreeSet;
-import org.qi4j.tools.shell.create.CreateProject;
-import org.qi4j.tools.shell.help.HelpCommand;
-
-public class Main
-{
-    private TreeSet<Command> commands = new TreeSet<Command>();
-
-    public static void main( String[] args )
-    {
-        new Main().run( args );
-    }
-
-    public Main()
-    {
-        this.commands.add( new HelpCommand() );
-        this.commands.add( new CreateProject() );
-    }
-
-    private void run( String[] args )
-    {
-        if( !contains( args, "-q" ) )
-        {
-            System.out.println( "Zest - Classes are Dead. Long Live Interfaces!" );
-            System.out.println( "----------------------------------------------\n" );
-        }
-        if( args.length == 0 )
-        {
-            HelpCommand helpCommand = new HelpCommand();
-            helpCommand.setCommands( commands );
-            helpCommand.execute( args, input(), output() );
-        }
-    }
-
-    private boolean contains( String[] args, String s )
-    {
-        for( String arg : args )
-        {
-            if( s.equals( arg ) )
-            {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private PrintWriter output()
-    {
-        return new PrintWriter( System.out );
-    }
-
-    private BufferedReader input()
-    {
-        return new BufferedReader( new InputStreamReader( System.in ) );
-    }
-}
diff --git a/tools/shell/src/main/java/org/qi4j/tools/shell/create/CreateProject.java b/tools/shell/src/main/java/org/qi4j/tools/shell/create/CreateProject.java
deleted file mode 100644
index 9660c42..0000000
--- a/tools/shell/src/main/java/org/qi4j/tools/shell/create/CreateProject.java
+++ /dev/null
@@ -1,61 +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.qi4j.tools.shell.create;
-
-import java.io.BufferedReader;
-import java.io.PrintWriter;
-import java.util.Map;
-import java.util.Properties;
-import org.qi4j.tools.shell.AbstractCommand;
-import org.qi4j.tools.shell.FileUtils;
-import org.qi4j.tools.shell.HelpNeededException;
-
-public class CreateProject extends AbstractCommand
-{
-
-    @Override
-    public void execute( String[] args, BufferedReader input, PrintWriter output )
-        throws HelpNeededException
-    {
-        if( args.length < 1 )
-            throw new HelpNeededException();
-        String projectName = args[0];
-        String template = "defaultproject";
-        if( args.length < 2 )
-            template = args[1];
-        FileUtils.createDir( projectName );
-        Map<String, String> props = FileUtils.readPropertiesResource( "templates/" + template + "/project.properties" );
-        for( Map.Entry<String,String> p: props.entrySet() )
-        {
-
-        }
-    }
-
-    @Override
-    public String description()
-    {
-        return "create-project";
-    }
-
-    @Override
-    public String name()
-    {
-        return "create-project";
-    }
-}
diff --git a/tools/shell/src/main/java/org/qi4j/tools/shell/help/HelpCommand.java b/tools/shell/src/main/java/org/qi4j/tools/shell/help/HelpCommand.java
deleted file mode 100644
index e5058fc..0000000
--- a/tools/shell/src/main/java/org/qi4j/tools/shell/help/HelpCommand.java
+++ /dev/null
@@ -1,59 +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.qi4j.tools.shell.help;
-
-import java.io.BufferedReader;
-import java.io.PrintWriter;
-import org.qi4j.tools.shell.AbstractCommand;
-import org.qi4j.tools.shell.Command;
-
-public class HelpCommand extends AbstractCommand
-{
-    private Iterable<Command> commands;
-
-    public HelpCommand()
-    {
-    }
-
-    public void setCommands( Iterable<Command> comands )
-    {
-        this.commands = commands;
-    }
-
-    @Override
-    public void execute( String[] args, BufferedReader input, PrintWriter output )
-    {
-        for( Command command : commands )
-        {
-            output.println( command.name() + "\t" + command.description() );
-        }
-    }
-
-    @Override
-    public String description()
-    {
-        return "help";
-    }
-
-    @Override
-    public String name()
-    {
-        return "Prints this help text.";
-    }
-}
diff --git a/tools/src/docs/envisage.txt b/tools/src/docs/envisage.txt
new file mode 100644
index 0000000..4aecf37
--- /dev/null
+++ b/tools/src/docs/envisage.txt
@@ -0,0 +1,55 @@
+///////////////////////////////////////////////////////////////
+ * 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.
+///////////////////////////////////////////////////////////////
+
+[[tools-envisage,Envisage Tool]]
+= Envisage =
+
+Envisage is a Swing based visualization tool for the Polygene™ Application model.
+Visualizations can be printed to PDFs.
+
+== Usage ==
+
+Envisage can be easily used directly and prior your Application activation:
+
+[snippet,java]
+----
+source=tools/envisage/src/test/java/org/apache/polygene/envisage/school/EnvisageSchoolSample.java
+tag=envisage
+----
+
+As you can see, Envisage operates on the ApplicationModel, this means that you
+can easily embed it in your own Applications too.
+
+From the sources you can run the `runEnvisageSample` or `runEnvisageSchoolSample` Gradle tasks
+to run interactive examples. See <<build-system>> if you need some guidance.
+
+== Screenshots ==
+
+image:tools-envisage-structure.png[width="800px"]
+
+image:tools-envisage-type.png[width="800px"]
+
+image:tools-envisage-stacked.png[width="800px"]
+
+image:tools-envisage-stacked-collapsed.png[width="800px"]
+
+== Embedd in your Application ==
+
+include::../../build/docs/buildinfo/artifact.txt[]
+
diff --git a/tools/src/docs/yeoman_polygene.txt b/tools/src/docs/yeoman_polygene.txt
new file mode 100644
index 0000000..0a9e779
--- /dev/null
+++ b/tools/src/docs/yeoman_polygene.txt
@@ -0,0 +1,388 @@
+///////////////////////////////////////////////////////////////
+ * 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.
+///////////////////////////////////////////////////////////////
+
+[[tools-shell,Command Line Shell]]
+= Polygene Generator =
+Apache Polygene comes with a Yeoman code generator, to quickly set up a development
+environment for Polygene applications.
+
+[source,shell]
+----
+mkdir projectdirname
+cd projectdirname
+yo polygene
+----
+
+It will ask a lot of questions. For choice questions, you operate up and down, and with multi-choice, you
+select with space bar.
+
+== First Trial ==
+
+=== Project Name ===
+It starts with the Project name. This will be the project name in Gradle and any gradle driven naming of the
+project such as in IDEs. It defaults to current directory with initial uppercase letter.
+
+[source,shell]
+----
+? Your project name
+----
+
+=== Java Package Name ===
+This is the root of the package names in the multi-module, multi-package project.
+
+[source,shell]
+----
+? Java package name
+----
+
+=== Application Type ===
+
+The Application Type that you want to create.
+
+NOTE: Command Line is currently not implemented correctly, and the Rest API is still not complete.
+
+[source,shell]
+----
+? what type of application do you want to create?
+  Command Line
+❯ Rest API
+----
+
+=== Entity Store ===
+Polygene has built-in persistence, and that is backed by entity store plugins. There are currently a fair
+number of implementations to choose from. Not that "memory" is not persistent, but looses the content on shutdown.
+
+[source,shell]
+----
+? Which entity store do you want to use?
+  Cassandra
+  File
+  DerbySQL
+  Geode
+  H2SQL
+  Hazelcast
+  JClouds
+  Jdbm
+  LevelDB
+> Memory
+  MongoDB
+  MySQL
+  Preferences
+  Redis
+  Riak
+  PostgreSQL
+  SQLite
+----
+
+=== Indexin/Query system ===
+Select of a pluggable Indexing and Query subsystem.
+
+In Polygene, the indexing/query system is separated from store and retrieve. This allows us to optimize direct
+fetches for navigating object graphs. In practical Polygene applications, we find that querying is not nearly as
+common as in, say, JPA applications. The query layout in the underlying indexing system is also very different
+from the document-oriented approach of most entity stores.
+
+NOTE: Not all indexing subsystems support all of the specified Indexing/Query SPI.
+
+[source,shell]
+----
+? Which indexing system do you want to use?
+> Rdf
+  ElasticSearch
+  Solr
+  SQL
+----
+
+=== Caching System ===
+Some of the entity stores rely on a Polygene level caching SPI. This caching subsystem is pluggable and
+will be used by any of the entity stores that uses the internal MapEntityStore SPI
+
+[source,shell]
+----
+? Which caching system do you want to use?
+> None
+  Memcache
+  EhCache
+----
+
+=== Serialization system ===
+Serialization is a key concept in business applications, and in Polygene that is a pluggable subsystem.
+
+? Which serialization system do you want to use?
+
+[source,shell]
+----
+> JavaxJson
+  JavaxXml
+  MessagePack
+----
+
+=== Metrics System ===
+Metrics is the SPI for measuring the performance and health of an Polygene application. Currently only
+one implementation is available.
+
+? Which metrics capturing system do you want to use?
+
+[source,shell]
+----
+> None
+  Codahale
+----
+
+=== Other Features ===
+
+JMX feature installs the MBean server and registers all Services with it, in the application structure defined.
+
+Mixin Scripting is allowing Mixin methods to be implemented in other languages parallel to Java.
+
+Security installs Apache Shiro and binds Users, Groups and Roles to entity store.
+
+[source,shell]
+----
+? Other features?
+ ◯ jmx
+ ◯ mixin scripting
+ ◯ security
+----
+
+
+=== Example ===
+
+[source,shell]
+----
+~/dev/sensetif/sink$ yo polygene
+? Your project name Sink
+? Java package name com.sensetif.sink
+? what type of application do you want to create? Rest API
+? Which entity store do you want to use? Cassandra
+? Which indexing system do you want to use? Rdf
+? Which caching system do you want to use? None
+? Which serialization system do you want to use? JavaxJson
+? Which metrics capturing system do you want to use? Codahale
+? Other features? jmx, security
+app name Sink
+Entity Stores: Cassandra
+Indexing: Rdf
+Caching: None
+Serialization: JavaxJson
+Features: [ 'jmx', 'security' ]
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/config/ConfigurationLayer.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/InfrastructureLayer.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/DomainLayer.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/connectivity/ConnectivityLayer.java
+   create app/src/main/webapp/WEB-INF/web.xml
+   create app/build.gradle
+   create bootstrap/build.gradle
+   create model/build.gradle
+   create rest/build.gradle
+   create build.gradle
+   create settings.gradle
+   create gradlew
+   create gradlew.bat
+   create gradle/wrapper/gradle-wrapper.jar
+   create gradle/wrapper/gradle-wrapper.properties
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/config/ConfigModule.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/FileConfigurationModule.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/RdfIndexingModule.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/CodahaleMetricsModule.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/JavaxJsonSerializationModule.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/CassandraStorageModule.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/CrudModule.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/JmxModule.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/SecurityModule.java
+   create model/src/main/java/com/sensetif/sink/model/security/CryptoConfiguration.java
+   create model/src/main/java/com/sensetif/sink/model/security/CryptoException.java
+   create model/src/main/java/com/sensetif/sink/model/security/CryptoService.java
+   create model/src/main/java/com/sensetif/sink/model/security/EncryptedStringPropertyConcern.java
+   create model/src/main/java/com/sensetif/sink/model/security/Group.java
+   create model/src/main/java/com/sensetif/sink/model/security/RealmService.java
+   create model/src/main/java/com/sensetif/sink/model/security/SecurityRepository.java
+   create model/src/main/java/com/sensetif/sink/model/security/User.java
+   create model/src/main/java/com/sensetif/sink/model/security/UserFactory.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/connectivity/RestApiModule.java
+   create rest/src/main/java/com/sensetif/sink/rest/security/DefaultEnroler.java
+   create rest/src/main/java/com/sensetif/sink/rest/security/DefaultVerifier.java
+----
+
+== Command Line Options ==
+
+[source,shell]
+----
+--import=<modelfile>   Imports the model from a JSON file and creates a project descibed therein.
+--export=<modelfile>   Exports the generated model to a JSON file in the same format as the import model.
+--noPrompt             If this option is not provided for --import-model, the user can still
+                       input answers, which will override the values in the imported model
+----
+
+=== Example ===
+
+If we run the following,
+
+[source,shell]
+----
+$ yo polygene --import=../model.json --noPrompt
+----
+
+where the content of the +../model.json+ is as follows,
+
+[source]
+----
+{
+  "name": "Sink",
+  "packageName": "com.sensetif.sink",
+  "applicationtype": "Rest API",
+  "features": [
+    "security"
+  ],
+  "entitystore": "MongoDB",
+  "indexing": "SQL",
+  "caching": "Memcache",
+  "serialization": "JavaxJson",
+  "metrics": "Codahale",
+  "modules": {
+    "user": {
+      "cruds": [
+        { "name": "Users" },
+        {"name": "Roles"},
+        {"name": "User"},
+        {"name": "Role"},
+        {"name": "Permission"},
+        {"name": "Group"},
+        {"name": "Groups"}
+      ],
+      "services": [
+        {
+          "name": "AuthService",
+          "visibility": "application",
+          "configuration" : [
+            { "name": "backend", "type": "java.lang.String" },
+            { "name": "connectString", "type": "java.lang.String" }
+          ]
+        }
+      ]
+    },
+    "organization": {
+      "cruds": [
+        {"name": "Organizations"},
+        {
+          "name": "Organization",
+          "properties": [
+            { "name": "name", "type": "java.lang.String" },
+            { "name": "created", "type": "java.time.Instant" }
+          ]
+        },
+        { "name": "Project" }
+      ],
+      "entities": [
+        { "name": "Invoice" }
+      ],
+      "values": [
+        {
+          "name": "CreditLimit",
+          "properties" : [
+            { "name" : "amount", "type" : "java.math.BigDecimal" },
+            { "name" : "currency", "type" : "java.lang.String" }
+          ]
+        }
+      ],
+      "transients": [
+        { "name": "OrderConfirmation" }
+      ],
+      "objects": [
+        { "name": "PaypalNotification" }
+      ]
+    },
+    "sensor": {
+      "cruds": [
+        { "name": "SensorData" }
+      ],
+      "entities": [
+        { "name": "Sensor" },
+        { "name": "PollSchedule" }
+      ]
+    }
+  }
+}
+----------------
+
+we will create a complete project, like this
+
+[source,shell]
+----
+  create bootstrap/src/main/java/com/sensetif/sink/bootstrap/config/ConfigurationLayer.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/InfrastructureLayer.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/DomainLayer.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/connectivity/ConnectivityLayer.java
+   create app/src/main/webapp/WEB-INF/web.xml
+   create app/build.gradle
+   create bootstrap/build.gradle
+   create model/build.gradle
+   create rest/build.gradle
+   create build.gradle
+   create settings.gradle
+   create gradlew
+   create gradlew.bat
+   create gradle/wrapper/gradle-wrapper.jar
+   create gradle/wrapper/gradle-wrapper.properties
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/config/ConfigModule.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/MemcacheCachingModule.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/FileConfigurationModule.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/SQLIndexingModule.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/CodahaleMetricsModule.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/JavaxJsonSerializationModule.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/infrastructure/CassandraStorageModule.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/CrudModule.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/UserModule.java
+   create model/src/main/java/com/sensetif/sink/model/user/Users.java
+   create model/src/main/java/com/sensetif/sink/model/user/Roles.java
+   create model/src/main/java/com/sensetif/sink/model/user/User.java
+   create model/src/main/java/com/sensetif/sink/model/user/Role.java
+   create model/src/main/java/com/sensetif/sink/model/user/Permission.java
+   create model/src/main/java/com/sensetif/sink/model/user/Group.java
+   create model/src/main/java/com/sensetif/sink/model/user/Groups.java
+   create model/src/main/java/com/sensetif/sink/model/user/AuthService.java
+   create model/src/main/java/com/sensetif/sink/model/user/AuthConfiguration.java
+   create model/src/main/resources/com/sensetif/sink/model/user/AuthConfiguration.yaml
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/OrganizationModule.java
+   create model/src/main/java/com/sensetif/sink/model/organization/Organizations.java
+   create model/src/main/java/com/sensetif/sink/model/organization/Organization.java
+   create model/src/main/java/com/sensetif/sink/model/organization/Project.java
+   create model/src/main/java/com/sensetif/sink/model/organization/Invoice.java
+   create model/src/main/java/com/sensetif/sink/model/organization/CreditLimit.java
+   create model/src/main/java/com/sensetif/sink/model/organization/OrderConfirmation.java
+   create model/src/main/java/com/sensetif/sink/model/organization/PaypalNotification.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/SensorModule.java
+   create model/src/main/java/com/sensetif/sink/model/sensor/SensorData.java
+   create model/src/main/java/com/sensetif/sink/model/sensor/Sensor.java
+   create model/src/main/java/com/sensetif/sink/model/sensor/PollSchedule.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/domain/SecurityModule.java
+   create model/src/main/java/com/sensetif/sink/model/security/CryptoConfiguration.java
+   create model/src/main/java/com/sensetif/sink/model/security/CryptoException.java
+   create model/src/main/java/com/sensetif/sink/model/security/CryptoService.java
+   create model/src/main/java/com/sensetif/sink/model/security/EncryptedStringPropertyConcern.java
+   create model/src/main/java/com/sensetif/sink/model/security/Group.java
+   create model/src/main/java/com/sensetif/sink/model/security/RealmService.java
+   create model/src/main/java/com/sensetif/sink/model/security/SecurityRepository.java
+   create model/src/main/java/com/sensetif/sink/model/security/User.java
+   create model/src/main/java/com/sensetif/sink/model/security/UserFactory.java
+   create bootstrap/src/main/java/com/sensetif/sink/bootstrap/connectivity/RestApiModule.java
+   create rest/src/main/java/com/sensetif/sink/rest/security/DefaultEnroler.java
+   create rest/src/main/java/com/sensetif/sink/rest/security/DefaultVerifier.java
+----
+
diff --git a/tutorials/cargo/build.gradle b/tutorials/cargo/build.gradle
index 9a301bb..6ccb67c 100644
--- a/tutorials/cargo/build.gradle
+++ b/tutorials/cargo/build.gradle
@@ -1,31 +1,36 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Tutorial on how to convert existing application into a Apache Zest™ one, step-by-step."
+apply plugin: 'polygene-tutorial'
 
-jar { manifest { name = "Apache Zest™ Tutorial - Cargo" }}
+description = "Tutorial on how to convert existing application into a Apache Polygene™ one, step-by-step."
+
+jar { manifest { name = "Apache Polygene™ Tutorial - Cargo" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile(project(":org.qi4j.core:org.qi4j.core.runtime"))  // TODO: Get rid of this dependency
+  implementation polygene.core.bootstrap
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-  testCompile(libraries.easymock)
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+  testImplementation libraries.easymock
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/package.html b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/package.html
new file mode 100644
index 0000000..15a5b7e
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/package.html
@@ -0,0 +1,46 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<body>
+<h1>Tutorial - Cargo</h1>
+
+<p>
+    In Eric Evans' book Domain Driven Design, ISBN 0-321-12521-5, we find a domain oriented discussion
+    around cargo making voyages from the starting point to a destination. The discussion in DDD is
+    not continuous, so we need to find the many snippets throughout the book. We will try to
+    address each piece found in the book as it appears, and how that is dealt with in Apache Polygene™.
+</p>
+
+<p>
+    We have chosen the Cargo example also due to the fact that Mr Evans uses this in presentations
+    about Domain Driven Design, and that it represents exactly the type of applications that we think
+    Polygene™ is made for.
+</p>
+
+<p>
+    In the tutorial text, I will be reference pages in the book, and it refers to my edition, i.e.
+    "First printing, August 2003", which I believe to be the only edition in circulation at the
+    time of this writing (Jan 2008). I will also try to reference the section in question, so if you
+    read this when other DDD editions are out, you will have a chance to find it.
+</p>
+
+<p>
+    Step 1 - Make a booking.
+</p>
+</body>
\ No newline at end of file
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/BookingPolicy.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/BookingPolicy.java
new file mode 100644
index 0000000..7107dd9
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/BookingPolicy.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.tutorials.cargo.step1;
+
+public interface BookingPolicy
+{
+    boolean isAllowed( Cargo cargo, Voyage voyage );
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/Cargo.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/Cargo.java
new file mode 100644
index 0000000..584aea0
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/Cargo.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.tutorials.cargo.step1;
+
+public interface Cargo
+{
+    double getSize();
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/OverbookingPolicy.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/OverbookingPolicy.java
new file mode 100644
index 0000000..d2d0f63
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/OverbookingPolicy.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.tutorials.cargo.step1;
+
+public class OverbookingPolicy
+    implements BookingPolicy
+{
+    @Override
+    public boolean isAllowed( Cargo cargo, Voyage voyage )
+    {
+        return cargo.getSize() + voyage.getBookedCargoSize() <= voyage.getCapacity() * 1.1;
+    }
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/SequenceGenerator.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/SequenceGenerator.java
new file mode 100644
index 0000000..7cf967f
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/SequenceGenerator.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.tutorials.cargo.step1;
+
+public interface SequenceGenerator
+{
+    int next();
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/ShippingService.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/ShippingService.java
new file mode 100644
index 0000000..dd8f433
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/ShippingService.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.tutorials.cargo.step1;
+
+public interface ShippingService
+{
+    int makeBooking( Cargo cargo, Voyage voyage );
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/Voyage.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/Voyage.java
new file mode 100644
index 0000000..8cd6b30
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/Voyage.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.tutorials.cargo.step1;
+
+public interface Voyage
+{
+    double getCapacity();
+
+    double getBookedCargoSize();
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/internal/CargoImpl.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/internal/CargoImpl.java
new file mode 100644
index 0000000..25f224b
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/internal/CargoImpl.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.tutorials.cargo.step1.internal;
+
+import org.apache.polygene.tutorials.cargo.step1.Cargo;
+
+public class CargoImpl
+    implements Cargo
+{
+    private double size;
+
+    public CargoImpl( double size )
+    {
+        this.size = size;
+    }
+
+    @Override
+    public double getSize()
+    {
+        return size;
+    }
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/internal/ShippingServiceImpl.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/internal/ShippingServiceImpl.java
new file mode 100644
index 0000000..1d88bbe
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/internal/ShippingServiceImpl.java
@@ -0,0 +1,57 @@
+/*
+ *  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.polygene.tutorials.cargo.step1.internal;
+
+import org.apache.polygene.tutorials.cargo.step1.BookingPolicy;
+import org.apache.polygene.tutorials.cargo.step1.Cargo;
+import org.apache.polygene.tutorials.cargo.step1.ShippingService;
+import org.apache.polygene.tutorials.cargo.step1.Voyage;
+
+public class ShippingServiceImpl
+    implements ShippingService
+{
+    private BookingPolicy bookingPolicy;
+    private SimpleSequenceImpl orderConfirmationSequence;
+
+    public ShippingServiceImpl( BookingPolicy bookingPolicy )
+    {
+        this.bookingPolicy = bookingPolicy;
+        orderConfirmationSequence = new SimpleSequenceImpl();
+    }
+
+    @Override
+    public int makeBooking( Cargo cargo, Voyage voyage )
+    {
+        if( !bookingPolicy.isAllowed( cargo, voyage ) )
+        {
+            return -1;
+        }
+        int confirmation = orderConfirmationSequence.next();
+        if( voyage instanceof VoyageImpl )
+        {
+            ( (VoyageImpl) voyage ).addCargo( cargo, confirmation );
+        }
+        else
+        {
+            return -1;
+        }
+        return confirmation;
+    }
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/internal/SimpleSequenceImpl.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/internal/SimpleSequenceImpl.java
new file mode 100644
index 0000000..9b41a70
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/internal/SimpleSequenceImpl.java
@@ -0,0 +1,34 @@
+/*
+ *  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.polygene.tutorials.cargo.step1.internal;
+
+import org.apache.polygene.tutorials.cargo.step1.SequenceGenerator;
+
+public class SimpleSequenceImpl
+    implements SequenceGenerator
+{
+    private int sequence = 1;
+
+    @Override
+    public int next()
+    {
+        return sequence++;
+    }
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/internal/VoyageImpl.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/internal/VoyageImpl.java
new file mode 100644
index 0000000..1bfb813
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/internal/VoyageImpl.java
@@ -0,0 +1,64 @@
+/*
+ *  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.polygene.tutorials.cargo.step1.internal;
+
+import java.util.HashMap;
+import org.apache.polygene.tutorials.cargo.step1.Cargo;
+import org.apache.polygene.tutorials.cargo.step1.Voyage;
+
+public class VoyageImpl
+    implements Voyage
+{
+    private double capacity;
+    private HashMap<Integer, Cargo> bookedCargo;
+
+    public VoyageImpl( int capacity )
+    {
+        this.capacity = capacity;
+        bookedCargo = new HashMap<Integer, Cargo>();
+    }
+
+    @Override
+    public double getCapacity()
+    {
+        return capacity;
+    }
+
+    @Override
+    public double getBookedCargoSize()
+    {
+        double bookedCargoSize = 0;
+        for( Cargo cargo : bookedCargo.values() )
+        {
+            bookedCargoSize = bookedCargoSize + cargo.getSize();
+        }
+        return bookedCargoSize;
+    }
+
+    public void addCargo( Cargo cargo, int confirmation )
+    {
+        bookedCargo.put( confirmation, cargo );
+    }
+
+    public Cargo removeCargo( int confirmation )
+    {
+        return bookedCargo.remove( confirmation );
+    }
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/package.html b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/package.html
new file mode 100644
index 0000000..3cbf474
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step1/package.html
@@ -0,0 +1,101 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<body>
+<h1>Step 1 - Evans "Making a booking."</h1>
+
+<p>
+    Location: Page 17, "Knowledge-Rich Design.
+</p>
+
+<p>
+    We start with a very simple domain design, consisting of a <i>Voyage</i> with <i>Cargo</i> items.
+    The booking system is responsible for matching as many <i>Cargo</i> items on to the <i>Voyage</i>
+    but not too many. Evans introduces a <i>capacity</i> property in the Voyage and a <i>size</i>
+    property to the Cargo.
+</p>
+
+<p>
+    Mr Evans continues to discuss that a <i>makeBooking( Cargo cargo, Voyage voyage )</i> method
+    (presumably in some service instance somewhere) becomes too complicated for the domain experts
+    and suggests breaking out the <b>policy</b> into a separate class.
+</p>
+
+<p>
+    Let's start with putting into the code that Mr Evans suggests, using so called POJO or JavaBeans
+    programming convention.
+</p>
+
+<p>
+    You will find the suggested code in this package. Take a look at it. You can also run the
+    testcase <b>step1</b> to see simple usage cases.
+</p>
+
+<p>
+    We have made this code more complex than the book is suggesting. First of all there is a separation
+    of interface from implementation. This is done to make the code more flexible for future change;
+</p>
+<ul>
+    <li>The <i>Voyage.addCargo()</i> <b>must</b> be hidden from the client code, so that it is forced to call
+        the <i>ShippingService.makeBooking()</i> and not bypassing it and call the <i>addCargo()</i> directly.
+    </li>
+    <li>DDD book doesn't mention the <i>ShippingService</i> in this section, but was introduced to make the
+        code executable. Making the ShippingService an interface is just following common practices, which
+        allows us to change the, or have multiple, implementations.
+    </li>
+    <li><i>Cargo</i> also has separated interface from the implementation for the same reason.</li>
+    <li><i>Sequence</i> is separated largely because in a real application, it is probably dependent on
+        the customer.
+    </li>
+    <li>Finally, the <i>OverbookingPolicy</i> is also separated since we want to be able to have many Policies
+        sooner or later.
+    </li>
+    <li>And with this separation, and hiding of the implementation from the client by putting all of the
+        implementation details in the <i>internal</i> package, we also need to add methods to create <i>Cargo</i>
+        and find <i>Voyage</i> instances.
+    </li>
+</ul>
+<p>
+    This could have been done utilizing Spring Framework, but we don't want to introduce a fairly large
+    dependency, and it wouldn't help us much in the domain aspect of this example.
+</p>
+
+<p>
+    Mr Evans then continues to discuss "Deep Models", where he correctly observes that the domain model
+    artifacts tend to change over time as we start to understand the domain better. The conclusion is that
+    the model will change a lot and the easier we make this process the faster we can move forward.
+</p>
+
+<p>
+    Now, what we have done so far is to just use plain Java to implement the discussion of Mr Evans' Cargo
+    example of domain-driven design. Before we move on to making the model more complex, and changing
+    the model as we understand it better, let's first refactor this into Polygene™ and discuss the immediate
+    differences.
+</p>
+
+<p>
+    Steps;
+</p>
+<ol>
+    <li>Cargo has a <i>size</i> property. We change that to use the <i>Property</i> feature in Polygene™.</li>
+    <li>Voyage likewise has the <i>capacity</i> and <i>bookedCargoSize</i> properties.</li>
+    <li>Polygene™ doesn't need implementations of the Cargo and Voyage implementations.</li>
+    <li>Cargo and Voyage are entities, so we create CargoEntity and VoyageEntity interfaces.</li>
+</ol>
+</body>
\ No newline at end of file
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/Cargo.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/Cargo.java
new file mode 100644
index 0000000..8f907a0
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/Cargo.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.tutorials.cargo.step2;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+public interface Cargo
+{
+    @UseDefaults
+    Property<Double> size();
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/CargoComposite.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/CargoComposite.java
new file mode 100644
index 0000000..b41a408
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/CargoComposite.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.tutorials.cargo.step2;
+
+import org.apache.polygene.api.composite.TransientComposite;
+
+public interface CargoComposite
+    extends Cargo, TransientComposite
+{
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/HasSequence.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/HasSequence.java
new file mode 100644
index 0000000..9c4bb8a
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/HasSequence.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.tutorials.cargo.step2;
+
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+
+public interface HasSequence
+{
+    @UseDefaults
+    Property<Integer> sequence();
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/OverbookingConcern.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/OverbookingConcern.java
new file mode 100644
index 0000000..54b9ddb
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/OverbookingConcern.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.tutorials.cargo.step2;
+
+import org.apache.polygene.api.concern.ConcernOf;
+
+public class OverbookingConcern
+    extends ConcernOf<ShippingService>
+    implements ShippingService
+{
+    @Override
+    public int makeBooking( Cargo cargo, Voyage voyage )
+    {
+        double cargoSize = cargo.size().get();
+        double aleadyBookedSize = voyage.bookedCargoSize().get();
+        double totalCapacity = voyage.capacity().get();
+
+        if( cargoSize + aleadyBookedSize > totalCapacity )
+        {
+            // Not allowed.
+            return -1;
+        }
+        return next.makeBooking( cargo, voyage );
+    }
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/SequencingConcern.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/SequencingConcern.java
new file mode 100644
index 0000000..8886648
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/SequencingConcern.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.tutorials.cargo.step2;
+
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.property.Property;
+
+public class SequencingConcern
+    extends ConcernOf<ShippingService>
+    implements ShippingService
+{
+    @This
+    private HasSequence generator;
+
+    @Override
+    public int makeBooking( Cargo cargo, Voyage voyage )
+    {
+        int ok = next.makeBooking( cargo, voyage );
+        if( ok < 0 )
+        {
+            return ok;
+        }
+        Property<Integer> gen = generator.sequence();
+        ok = gen.get();
+        generator.sequence().set( ok + 1 );
+        return ok;
+    }
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/ShippingService.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/ShippingService.java
new file mode 100644
index 0000000..9883ce4
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/ShippingService.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.tutorials.cargo.step2;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+@Mixins( ShippingServiceMixin.class )
+public interface ShippingService
+{
+    int makeBooking( Cargo cargo, Voyage voyage );
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/ShippingServiceComposite.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/ShippingServiceComposite.java
new file mode 100644
index 0000000..a849539
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/ShippingServiceComposite.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.tutorials.cargo.step2;
+
+import org.apache.polygene.api.composite.TransientComposite;
+import org.apache.polygene.api.concern.Concerns;
+
+@Concerns( { SequencingConcern.class, OverbookingConcern.class } )
+public interface ShippingServiceComposite
+    extends ShippingService, TransientComposite
+{
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/ShippingServiceMixin.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/ShippingServiceMixin.java
new file mode 100644
index 0000000..4b9ae2f
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/ShippingServiceMixin.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.tutorials.cargo.step2;
+
+/**
+ * JAVADOC
+ */
+public class ShippingServiceMixin
+    implements ShippingService
+{
+    @Override
+    public int makeBooking( Cargo cargo, Voyage voyage )
+    {
+        voyage.bookedCargoSize().set( voyage.bookedCargoSize().get() + cargo.size().get() );
+
+        return 0;
+    }
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/Voyage.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/Voyage.java
new file mode 100644
index 0000000..a450322
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/Voyage.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.tutorials.cargo.step2;
+
+import org.apache.polygene.api.property.Property;
+
+public interface Voyage
+{
+    Property<Double> capacity();
+
+    Property<Double> bookedCargoSize();
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/VoyageComposite.java b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/VoyageComposite.java
new file mode 100644
index 0000000..dce0aac
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/VoyageComposite.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.tutorials.cargo.step2;
+
+import org.apache.polygene.api.composite.TransientComposite;
+
+public interface VoyageComposite
+    extends Voyage, TransientComposite
+{
+}
diff --git a/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/package.html b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/package.html
new file mode 100644
index 0000000..7aaaf38
--- /dev/null
+++ b/tutorials/cargo/src/main/java/org/apache/polygene/tutorials/cargo/step2/package.html
@@ -0,0 +1,75 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<body>
+<h1>Step 2 - Polygene™ "Making a booking."</h1>
+
+<p>
+    Location: Page 17, "Knowledge-Rich Design.
+</p>
+
+<h2>Results from Step1</h2>
+<ul>
+    <li>For the Cargo and Voyage interfaces, we have introduced the <i>Property&lt;Double&gt;</i>.
+        <i>Property</i> is an explicitly supported type in Polygene™, which makes life a lot easier
+        for everyone involved.
+    </li>
+    <li>The SequenceGenerator has changed the name to "HasSequence", since it doesn't handle the
+        generation of new numbers. It is given <i>Property&lt;Integer&gt;</i> to hold the last
+        sequence number, but it doesn't handle the <i>next()</i> equivalent from Evans' code.
+    </li>
+    <li>
+        The increment of the sequence number is instead handled in the SequencingConcern. One
+        advantage is that the number will only be incremented if the policies are met, as we
+        will place this concern at the top of the call chain.
+    </li>
+    <li>
+        Overbooking is a concern (according to Mr Evans in this part of the book) for the
+        <i>makeBooking()</i> method. So, we create an <i>OverbookingConcern</i>, that implements
+        the ShippingService. See below for more details.
+    </li>
+    <li>
+        The ShippingService remains the same. But notice that there is <b>No Implementation!</b>
+    </li>
+    <li>
+        We introduce a new interface, ShippingServiceComposite. This interface binds together the
+        parts to form the Composite. It <b>extends</b> the <i>ShippingService</i> and the
+        <i>Composite</i> and has annotations about how it should be wire together.
+    </li>
+</ul>
+
+<h3>The ShippingServiceComposite</h3>
+
+<p>
+    The <i>ShippingServiceComposite</i> declares which concerns should be used, and the order is significant. The
+    <i>SequencingConcern</i> is placed first, that means it will be invoked before the <i>OverbookingConcern</i>,
+    but it performs its own work <b>after</b> the call to the <i>next.makeBooking()</i> method.
+</p>
+
+<h3>The OverbookingConcern</h3>
+
+<p>
+    It extends <i>ConcernOf</i> to show which MixinType it is chained into.
+</p>
+
+<h2>Moving on</h2>
+
+<p>
+</p>
+</body>
\ No newline at end of file
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/package.html b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/package.html
deleted file mode 100644
index 7dd1df5..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/package.html
+++ /dev/null
@@ -1,43 +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.
--->
-<body>
-<h1>Tutorial - Cargo</h1>
-
-<p>
-    In Eric Evans' book Domain Driven Design, ISBN 0-321-12521-5, we find a domain oriented discussion
-    around cargo making voyages from the starting point to a destination. The discussion in DDD is
-    not continuous, so we need to find the many snippets throughout the book. We will try to
-    address each piece found in the book as it appears, and how that is dealt with in Apache Zest™.
-</p>
-
-<p>
-    We have chosen the Cargo example also due to the fact that Mr Evans uses this in presentations
-    about Domain Driven Design, and that it represents exactly the type of applications that we think
-    Zest™ is made for.
-</p>
-
-<p>
-    In the tutorial text, I will be reference pages in the book, and it refers to my edition, i.e.
-    "First printing, August 2003", which I believe to be the only edition in circulation at the
-    time of this writing (Jan 2008). I will also try to reference the section in question, so if you
-    read this when other DDD editions are out, you will have a chance to find it.
-</p>
-
-<p>
-    Step 1 - Make a booking.
-</p>
-</body>
\ No newline at end of file
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/BookingPolicy.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/BookingPolicy.java
deleted file mode 100644
index 13526ae..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/BookingPolicy.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step1;
-
-public interface BookingPolicy
-{
-    boolean isAllowed( Cargo cargo, Voyage voyage );
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/Cargo.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/Cargo.java
deleted file mode 100644
index ab856ce..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/Cargo.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step1;
-
-public interface Cargo
-{
-    double getSize();
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/OverbookingPolicy.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/OverbookingPolicy.java
deleted file mode 100644
index 01b9ce0..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/OverbookingPolicy.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step1;
-
-public class OverbookingPolicy
-    implements BookingPolicy
-{
-    @Override
-    public boolean isAllowed( Cargo cargo, Voyage voyage )
-    {
-        return cargo.getSize() + voyage.getBookedCargoSize() <= voyage.getCapacity() * 1.1;
-    }
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/SequenceGenerator.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/SequenceGenerator.java
deleted file mode 100644
index b869c67..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/SequenceGenerator.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step1;
-
-public interface SequenceGenerator
-{
-    int next();
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/ShippingService.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/ShippingService.java
deleted file mode 100644
index 39bb449..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/ShippingService.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step1;
-
-public interface ShippingService
-{
-    int makeBooking( Cargo cargo, Voyage voyage );
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/Voyage.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/Voyage.java
deleted file mode 100644
index c624e91..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/Voyage.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step1;
-
-public interface Voyage
-{
-    double getCapacity();
-
-    double getBookedCargoSize();
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/internal/CargoImpl.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/internal/CargoImpl.java
deleted file mode 100644
index ed378e2f..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/internal/CargoImpl.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step1.internal;
-
-import org.qi4j.tutorials.cargo.step1.Cargo;
-
-public class CargoImpl
-    implements Cargo
-{
-    private double size;
-
-    public CargoImpl( double size )
-    {
-        this.size = size;
-    }
-
-    @Override
-    public double getSize()
-    {
-        return size;
-    }
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/internal/ShippingServiceImpl.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/internal/ShippingServiceImpl.java
deleted file mode 100644
index becb716..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/internal/ShippingServiceImpl.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step1.internal;
-
-import org.qi4j.tutorials.cargo.step1.BookingPolicy;
-import org.qi4j.tutorials.cargo.step1.Cargo;
-import org.qi4j.tutorials.cargo.step1.ShippingService;
-import org.qi4j.tutorials.cargo.step1.Voyage;
-
-public class ShippingServiceImpl
-    implements ShippingService
-{
-    private BookingPolicy bookingPolicy;
-    private SimpleSequenceImpl orderConfirmationSequence;
-
-    public ShippingServiceImpl( BookingPolicy bookingPolicy )
-    {
-        this.bookingPolicy = bookingPolicy;
-        orderConfirmationSequence = new SimpleSequenceImpl();
-    }
-
-    @Override
-    public int makeBooking( Cargo cargo, Voyage voyage )
-    {
-        if( !bookingPolicy.isAllowed( cargo, voyage ) )
-        {
-            return -1;
-        }
-        int confirmation = orderConfirmationSequence.next();
-        if( voyage instanceof VoyageImpl )
-        {
-            ( (VoyageImpl) voyage ).addCargo( cargo, confirmation );
-        }
-        else
-        {
-            return -1;
-        }
-        return confirmation;
-    }
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/internal/SimpleSequenceImpl.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/internal/SimpleSequenceImpl.java
deleted file mode 100644
index c0cd944..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/internal/SimpleSequenceImpl.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step1.internal;
-
-import org.qi4j.tutorials.cargo.step1.SequenceGenerator;
-
-public class SimpleSequenceImpl
-    implements SequenceGenerator
-{
-    private int sequence = 1;
-
-    @Override
-    public int next()
-    {
-        return sequence++;
-    }
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/internal/VoyageImpl.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/internal/VoyageImpl.java
deleted file mode 100644
index 0a65a37..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/internal/VoyageImpl.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step1.internal;
-
-import java.util.HashMap;
-import org.qi4j.tutorials.cargo.step1.Cargo;
-import org.qi4j.tutorials.cargo.step1.Voyage;
-
-public class VoyageImpl
-    implements Voyage
-{
-    private double capacity;
-    private HashMap<Integer, Cargo> bookedCargo;
-
-    public VoyageImpl( int capacity )
-    {
-        this.capacity = capacity;
-        bookedCargo = new HashMap<Integer, Cargo>();
-    }
-
-    @Override
-    public double getCapacity()
-    {
-        return capacity;
-    }
-
-    @Override
-    public double getBookedCargoSize()
-    {
-        double bookedCargoSize = 0;
-        for( Cargo cargo : bookedCargo.values() )
-        {
-            bookedCargoSize = bookedCargoSize + cargo.getSize();
-        }
-        return bookedCargoSize;
-    }
-
-    public void addCargo( Cargo cargo, int confirmation )
-    {
-        bookedCargo.put( confirmation, cargo );
-    }
-
-    public Cargo removeCargo( int confirmation )
-    {
-        return bookedCargo.remove( confirmation );
-    }
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/package.html b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/package.html
deleted file mode 100644
index c196e3f..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step1/package.html
+++ /dev/null
@@ -1,98 +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.
--->
-<body>
-<h1>Step 1 - Evans "Making a booking."</h1>
-
-<p>
-    Location: Page 17, "Knowledge-Rich Design.
-</p>
-
-<p>
-    We start with a very simple domain design, consisting of a <i>Voyage</i> with <i>Cargo</i> items.
-    The booking system is responsible for matching as many <i>Cargo</i> items on to the <i>Voyage</i>
-    but not too many. Evans introduces a <i>capacity</i> property in the Voyage and a <i>size</i>
-    property to the Cargo.
-</p>
-
-<p>
-    Mr Evans continues to discuss that a <i>makeBooking( Cargo cargo, Voyage voyage )</i> method
-    (presumably in some service instance somewhere) becomes too complicated for the domain experts
-    and suggests breaking out the <b>policy</b> into a separate class.
-</p>
-
-<p>
-    Let's start with putting into the code that Mr Evans suggests, using so called POJO or JavaBeans
-    programming convention.
-</p>
-
-<p>
-    You will find the suggested code in this package. Take a look at it. You can also run the
-    testcase <b>step1</b> to see simple usage cases.
-</p>
-
-<p>
-    We have made this code more complex than the book is suggesting. First of all there is a separation
-    of interface from implementation. This is done to make the code more flexible for future change;
-</p>
-<ul>
-    <li>The <i>Voyage.addCargo()</i> <b>must</b> be hidden from the client code, so that it is forced to call
-        the <i>ShippingService.makeBooking()</i> and not bypassing it and call the <i>addCargo()</i> directly.
-    </li>
-    <li>DDD book doesn't mention the <i>ShippingService</i> in this section, but was introduced to make the
-        code executable. Making the ShippingService an interface is just following common practices, which
-        allows us to change the, or have multiple, implementations.
-    </li>
-    <li><i>Cargo</i> also has separated interface from the implementation for the same reason.</li>
-    <li><i>Sequence</i> is separated largely because in a real application, it is probably dependent on
-        the customer.
-    </li>
-    <li>Finally, the <i>OverbookingPolicy</i> is also separated since we want to be able to have many Policies
-        sooner or later.
-    </li>
-    <li>And with this separation, and hiding of the implementation from the client by putting all of the
-        implementation details in the <i>internal</i> package, we also need to add methods to create <i>Cargo</i>
-        and find <i>Voyage</i> instances.
-    </li>
-</ul>
-<p>
-    This could have been done utilizing Spring Framework, but we don't want to introduce a fairly large
-    dependency, and it wouldn't help us much in the domain aspect of this example.
-</p>
-
-<p>
-    Mr Evans then continues to discuss "Deep Models", where he correctly observes that the domain model
-    artifacts tend to change over time as we start to understand the domain better. The conclusion is that
-    the model will change a lot and the easier we make this process the faster we can move forward.
-</p>
-
-<p>
-    Now, what we have done so far is to just use plain Java to implement the discussion of Mr Evans' Cargo
-    example of domain-driven design. Before we move on to making the model more complex, and changing
-    the model as we understand it better, let's first refactor this into Zest™ and discuss the immediate
-    differences.
-</p>
-
-<p>
-    Steps;
-</p>
-<ol>
-    <li>Cargo has a <i>size</i> property. We change that to use the <i>Property</i> feature in Zest™.</li>
-    <li>Voyage likewise has the <i>capacity</i> and <i>bookedCargoSize</i> properties.</li>
-    <li>Zest™ doesn't need implementations of the Cargo and Voyage implementations.</li>
-    <li>Cargo and Voyage are entities, so we create CargoEntity and VoyageEntity interfaces.</li>
-</ol>
-</body>
\ No newline at end of file
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/Cargo.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/Cargo.java
deleted file mode 100644
index 302e5a2..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/Cargo.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step2;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-
-public interface Cargo
-{
-    @UseDefaults
-    Property<Double> size();
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/CargoComposite.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/CargoComposite.java
deleted file mode 100644
index 212cdff..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/CargoComposite.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step2;
-
-import org.qi4j.api.composite.TransientComposite;
-
-public interface CargoComposite
-    extends Cargo, TransientComposite
-{
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/HasSequence.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/HasSequence.java
deleted file mode 100644
index 4a99fd7..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/HasSequence.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.tutorials.cargo.step2;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.property.Property;
-
-public interface HasSequence
-{
-    @UseDefaults
-    Property<Integer> sequence();
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/OverbookingConcern.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/OverbookingConcern.java
deleted file mode 100644
index 97c29fe..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/OverbookingConcern.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step2;
-
-import org.qi4j.api.concern.ConcernOf;
-
-public class OverbookingConcern
-    extends ConcernOf<ShippingService>
-    implements ShippingService
-{
-    @Override
-    public int makeBooking( Cargo cargo, Voyage voyage )
-    {
-        double cargoSize = cargo.size().get();
-        double aleadyBookedSize = voyage.bookedCargoSize().get();
-        double totalCapacity = voyage.capacity().get();
-
-        if( cargoSize + aleadyBookedSize > totalCapacity )
-        {
-            // Not allowed.
-            return -1;
-        }
-        return next.makeBooking( cargo, voyage );
-    }
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/SequencingConcern.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/SequencingConcern.java
deleted file mode 100644
index 200a6b8..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/SequencingConcern.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step2;
-
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.property.Property;
-
-public class SequencingConcern
-    extends ConcernOf<ShippingService>
-    implements ShippingService
-{
-    @This
-    private HasSequence generator;
-
-    @Override
-    public int makeBooking( Cargo cargo, Voyage voyage )
-    {
-        int ok = next.makeBooking( cargo, voyage );
-        if( ok < 0 )
-        {
-            return ok;
-        }
-        Property<Integer> gen = generator.sequence();
-        ok = gen.get();
-        generator.sequence().set( ok + 1 );
-        return ok;
-    }
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/ShippingService.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/ShippingService.java
deleted file mode 100644
index 6698f90..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/ShippingService.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step2;
-
-import org.qi4j.api.mixin.Mixins;
-
-@Mixins( ShippingServiceMixin.class )
-public interface ShippingService
-{
-    int makeBooking( Cargo cargo, Voyage voyage );
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/ShippingServiceComposite.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/ShippingServiceComposite.java
deleted file mode 100644
index 6f7f134..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/ShippingServiceComposite.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step2;
-
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.concern.Concerns;
-
-@Concerns( { SequencingConcern.class, OverbookingConcern.class } )
-public interface ShippingServiceComposite
-    extends ShippingService, TransientComposite
-{
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/ShippingServiceMixin.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/ShippingServiceMixin.java
deleted file mode 100644
index c649d41..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/ShippingServiceMixin.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.tutorials.cargo.step2;
-
-/**
- * JAVADOC
- */
-public class ShippingServiceMixin
-    implements ShippingService
-{
-    @Override
-    public int makeBooking( Cargo cargo, Voyage voyage )
-    {
-        voyage.bookedCargoSize().set( voyage.bookedCargoSize().get() + cargo.size().get() );
-
-        return 0;
-    }
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/Voyage.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/Voyage.java
deleted file mode 100644
index 69aa016..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/Voyage.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step2;
-
-import org.qi4j.api.property.Property;
-
-public interface Voyage
-{
-    Property<Double> capacity();
-
-    Property<Double> bookedCargoSize();
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/VoyageComposite.java b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/VoyageComposite.java
deleted file mode 100644
index 42d720a..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/VoyageComposite.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step2;
-
-import org.qi4j.api.composite.TransientComposite;
-
-public interface VoyageComposite
-    extends Voyage, TransientComposite
-{
-}
diff --git a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/package.html b/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/package.html
deleted file mode 100644
index cab1d68..0000000
--- a/tutorials/cargo/src/main/java/org/qi4j/tutorials/cargo/step2/package.html
+++ /dev/null
@@ -1,72 +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.
--->
-<body>
-<h1>Step 2 - Zest™ "Making a booking."</h1>
-
-<p>
-    Location: Page 17, "Knowledge-Rich Design.
-</p>
-
-<h2>Results from Step1</h2>
-<ul>
-    <li>For the Cargo and Voyage interfaces, we have introduced the <i>Property&lt;Double&gt;</i>.
-        <i>Property</i> is an explicitly supported type in Zest™, which makes life a lot easier
-        for everyone involved.
-    </li>
-    <li>The SequenceGenerator has changed the name to "HasSequence", since it doesn't handle the
-        generation of new numbers. It is given <i>Property&lt;Integer&gt;</i> to hold the last
-        sequence number, but it doesn't handle the <i>next()</i> equivalent from Evans' code.
-    </li>
-    <li>
-        The increment of the sequence number is instead handled in the SequencingConcern. One
-        advantage is that the number will only be incremented if the policies are met, as we
-        will place this concern at the top of the call chain.
-    </li>
-    <li>
-        Overbooking is a concern (according to Mr Evans in this part of the book) for the
-        <i>makeBooking()</i> method. So, we create an <i>OverbookingConcern</i>, that implements
-        the ShippingService. See below for more details.
-    </li>
-    <li>
-        The ShippingService remains the same. But notice that there is <b>No Implementation!</b>
-    </li>
-    <li>
-        We introduce a new interface, ShippingServiceComposite. This interface binds together the
-        parts to form the Composite. It <b>extends</b> the <i>ShippingService</i> and the
-        <i>Composite</i> and has annotations about how it should be wire together.
-    </li>
-</ul>
-
-<h3>The ShippingServiceComposite</h3>
-
-<p>
-    The <i>ShippingServiceComposite</i> declares which concerns should be used, and the order is significant. The
-    <i>SequencingConcern</i> is placed first, that means it will be invoked before the <i>OverbookingConcern</i>,
-    but it performs its own work <b>after</b> the call to the <i>next.makeBooking()</i> method.
-</p>
-
-<h3>The OverbookingConcern</h3>
-
-<p>
-    It extends <i>ConcernOf</i> to show which MixinType it is chained into.
-</p>
-
-<h2>Moving on</h2>
-
-<p>
-</p>
-</body>
\ No newline at end of file
diff --git a/tutorials/cargo/src/test/java/org/apache/polygene/tutorials/cargo/step1/Step1TestCase.java b/tutorials/cargo/src/test/java/org/apache/polygene/tutorials/cargo/step1/Step1TestCase.java
new file mode 100644
index 0000000..113f676
--- /dev/null
+++ b/tutorials/cargo/src/test/java/org/apache/polygene/tutorials/cargo/step1/Step1TestCase.java
@@ -0,0 +1,87 @@
+/*
+ *  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.polygene.tutorials.cargo.step1;
+
+import junit.framework.TestCase;
+import org.apache.polygene.tutorials.cargo.step1.internal.CargoImpl;
+import org.apache.polygene.tutorials.cargo.step1.internal.ShippingServiceImpl;
+import org.apache.polygene.tutorials.cargo.step1.internal.VoyageImpl;
+
+public class Step1TestCase
+    extends TestCase
+{
+    private ShippingService shippingService;
+    private Voyage voyage;
+
+    @Override
+    protected void setUp()
+        throws Exception
+    {
+        BookingPolicy policy = new OverbookingPolicy();
+        shippingService = new ShippingServiceImpl( policy );
+        voyage = newVoyage( "Singapore", "New York" );
+    }
+
+    public void testOrdinaryBooking()
+    {
+        Cargo cargo1 = newCargo( 40 );
+        Cargo cargo2 = newCargo( 40 );
+        Cargo cargo3 = newCargo( 20 );
+        int code = shippingService.makeBooking( cargo1, voyage );
+        assertEquals( 1, code );
+        code = shippingService.makeBooking( cargo2, voyage );
+        assertEquals( 2, code );
+        code = shippingService.makeBooking( cargo3, voyage );
+        assertEquals( 3, code );
+    }
+
+    public void testOverbooking()
+    {
+        Cargo cargo1 = newCargo( 100 );
+        Cargo cargo2 = newCargo( 9 );
+        int code = shippingService.makeBooking( cargo1, voyage );
+        assertEquals( 1, code );
+        code = shippingService.makeBooking( cargo2, voyage );
+        assertEquals( 2, code );
+    }
+
+    public void testTooMuch()
+    {
+        Cargo cargo1 = newCargo( 40 );
+        Cargo cargo2 = newCargo( 40 );
+        Cargo cargo3 = newCargo( 31 );
+        int code = shippingService.makeBooking( cargo1, voyage );
+        assertEquals( 1, code );
+        code = shippingService.makeBooking( cargo2, voyage );
+        assertEquals( 2, code );
+        code = shippingService.makeBooking( cargo3, voyage );
+        assertEquals( -1, code );
+    }
+
+    private Cargo newCargo( double size )
+    {
+        return new CargoImpl( size );
+    }
+
+    private Voyage newVoyage( String sourceCity, String destinationCity )
+    {
+        return new VoyageImpl( 100 );  // Fake the finder to just return a new Voyage for the demonstration purpose.
+    }
+}
diff --git a/tutorials/cargo/src/test/java/org/apache/polygene/tutorials/cargo/step2/SequencingConcernTest.java b/tutorials/cargo/src/test/java/org/apache/polygene/tutorials/cargo/step2/SequencingConcernTest.java
new file mode 100644
index 0000000..84cf70b
--- /dev/null
+++ b/tutorials/cargo/src/test/java/org/apache/polygene/tutorials/cargo/step2/SequencingConcernTest.java
@@ -0,0 +1,124 @@
+/*
+ *  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.polygene.tutorials.cargo.step2;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+import org.apache.polygene.test.mock.MockComposite;
+import org.apache.polygene.test.mock.MockPlayerMixin;
+
+import static org.easymock.EasyMock.*;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Unit tests for SequencingConcern.
+ *
+ * @author Alin Dreghiciu
+ */
+public class SequencingConcernTest
+{
+    /**
+     * Tests that when shipping service fails to make the booking generator is not called and booking failure code is
+     * returned.
+     */
+    @Test
+    @Ignore( "Expectations need to be figured out." )
+    public void failingBooking()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( ShippingServiceTestComposite.class );
+            }
+        };
+        ShippingService shippingService = createMock( ShippingService.class );
+        Cargo cargo = createMock( Cargo.class );
+        Voyage voyage = createMock( Voyage.class );
+        HasSequence sequence = createMock( HasSequence.class );
+        expect( shippingService.makeBooking( cargo, voyage ) ).andReturn( -1000 );
+        expect( voyage.bookedCargoSize().get() ).andReturn( 0.0 )
+            .atLeastOnce();
+        expect( cargo.size().get() ).andReturn( 0.0 )
+            .atLeastOnce();
+        expect( sequence.sequence().get() ).andReturn( 0 )
+            .atLeastOnce();
+        replay( shippingService, cargo, voyage );
+        ShippingServiceTestComposite underTest =
+            assembler.module().newTransient( ShippingServiceTestComposite.class );
+        underTest.useMock( shippingService ).forClass( ShippingService.class );
+        assertThat( "Booking result", underTest.makeBooking( cargo, voyage ), is( equalTo( -1000 ) ) );
+        verify( shippingService, cargo, voyage );
+    }
+
+    /**
+     * Tests that when shipping service succeeds to make the booking generator gets called and generated value is
+     * returned.
+     */
+    @Test
+    @Ignore( "Expectations need to be figured out." )
+    public void successfulBooking()
+        throws ActivationException, AssemblyException
+    {
+        SingletonAssembler assembler = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( ShippingServiceTestComposite.class );
+            }
+        };
+        ShippingService shippingService = createMock( ShippingService.class );
+        Cargo cargo = createMock( Cargo.class );
+        Voyage voyage = createMock( Voyage.class );
+        HasSequence generator = createMock( HasSequence.class );
+        Property<Integer> sequence = createMock( Property.class );
+        expect( shippingService.makeBooking( cargo, voyage ) ).andReturn( 100 );
+        expect( generator.sequence() ).andReturn( sequence ).anyTimes();
+        expect( sequence.get() ).andReturn( 1000 );
+        replay( shippingService, cargo, voyage, generator, sequence );
+        ShippingServiceTestComposite underTest =
+            assembler.module().newTransient( ShippingServiceTestComposite.class );
+        underTest.useMock( shippingService ).forClass( ShippingService.class );
+        underTest.useMock( generator ).forClass( HasSequence.class );
+        assertThat( "Booking result", underTest.makeBooking( cargo, voyage ), is( equalTo( 1000 ) ) );
+        verify( shippingService, cargo, voyage, generator, sequence );
+    }
+
+    @Mixins( MockPlayerMixin.class )
+    @Concerns( SequencingConcern.class )
+    public static interface ShippingServiceTestComposite
+        extends ShippingService, HasSequence, MockComposite
+    {
+    }
+}
diff --git a/tutorials/cargo/src/test/java/org/apache/polygene/tutorials/cargo/step2/Step2TestCase.java b/tutorials/cargo/src/test/java/org/apache/polygene/tutorials/cargo/step2/Step2TestCase.java
new file mode 100644
index 0000000..ac71082
--- /dev/null
+++ b/tutorials/cargo/src/test/java/org/apache/polygene/tutorials/cargo/step2/Step2TestCase.java
@@ -0,0 +1,103 @@
+/*
+ *  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.polygene.tutorials.cargo.step2;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.junit.Assert.assertEquals;
+
+public class Step2TestCase
+    extends AbstractPolygeneTest
+{
+    private Voyage voyage;
+    private ShippingService shippingService;
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        TransientBuilder<VoyageComposite> voyageBuilder = transientBuilderFactory.newTransientBuilder( VoyageComposite.class );
+        voyageBuilder.prototypeFor( Voyage.class ).bookedCargoSize().set( 0.0 );
+        voyageBuilder.prototypeFor( Voyage.class ).capacity().set( 100.0 );
+        voyage = voyageBuilder.newInstance();
+
+        TransientBuilder<ShippingServiceComposite> shippingBuilder =
+            transientBuilderFactory.newTransientBuilder( ShippingServiceComposite.class );
+        shippingService = shippingBuilder.newInstance();
+    }
+
+    @Test
+    public void testOrdinaryBooking()
+    {
+        Cargo cargo1 = newCargo( 40 );
+        Cargo cargo2 = newCargo( 40 );
+        Cargo cargo3 = newCargo( 20 );
+        int code = shippingService.makeBooking( cargo1, voyage );
+        assertEquals( 0, code );
+        code = shippingService.makeBooking( cargo2, voyage );
+        assertEquals( 1, code );
+        code = shippingService.makeBooking( cargo3, voyage );
+        assertEquals( 2, code );
+    }
+
+    @Test
+    public void testOverbooking()
+    {
+        Cargo cargo1 = newCargo( 100 );
+        Cargo cargo2 = newCargo( 9 );
+        int code = shippingService.makeBooking( cargo1, voyage );
+        assertEquals( 0, code );
+        code = shippingService.makeBooking( cargo2, voyage );
+        assertEquals( -1, code );
+    }
+
+    @Test
+    public void testTooMuch()
+    {
+        Cargo cargo1 = newCargo( 40 );
+        Cargo cargo2 = newCargo( 40 );
+        Cargo cargo3 = newCargo( 31 );
+        int code = shippingService.makeBooking( cargo1, voyage );
+        assertEquals( 0, code );
+        code = shippingService.makeBooking( cargo2, voyage );
+        assertEquals( 1, code );
+        code = shippingService.makeBooking( cargo3, voyage );
+        assertEquals( -1, code );
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( VoyageComposite.class, CargoComposite.class, ShippingServiceComposite.class );
+    }
+
+    private Cargo newCargo( double size )
+    {
+        TransientBuilder<CargoComposite> builder = transientBuilderFactory.newTransientBuilder( CargoComposite.class );
+        builder.prototypeFor( Cargo.class ).size().set( size );
+        return builder.newInstance();
+    }
+}
diff --git a/tutorials/cargo/src/test/java/org/qi4j/tutorials/cargo/step1/Step1TestCase.java b/tutorials/cargo/src/test/java/org/qi4j/tutorials/cargo/step1/Step1TestCase.java
deleted file mode 100644
index 17d49aa..0000000
--- a/tutorials/cargo/src/test/java/org/qi4j/tutorials/cargo/step1/Step1TestCase.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step1;
-
-import junit.framework.TestCase;
-import org.qi4j.tutorials.cargo.step1.internal.CargoImpl;
-import org.qi4j.tutorials.cargo.step1.internal.ShippingServiceImpl;
-import org.qi4j.tutorials.cargo.step1.internal.VoyageImpl;
-
-public class Step1TestCase
-    extends TestCase
-{
-    private ShippingService shippingService;
-    private Voyage voyage;
-
-    @Override
-    protected void setUp()
-        throws Exception
-    {
-        BookingPolicy policy = new OverbookingPolicy();
-        shippingService = new ShippingServiceImpl( policy );
-        voyage = newVoyage( "Singapore", "New York" );
-    }
-
-    public void testOrdinaryBooking()
-    {
-        Cargo cargo1 = newCargo( 40 );
-        Cargo cargo2 = newCargo( 40 );
-        Cargo cargo3 = newCargo( 20 );
-        int code = shippingService.makeBooking( cargo1, voyage );
-        assertEquals( 1, code );
-        code = shippingService.makeBooking( cargo2, voyage );
-        assertEquals( 2, code );
-        code = shippingService.makeBooking( cargo3, voyage );
-        assertEquals( 3, code );
-    }
-
-    public void testOverbooking()
-    {
-        Cargo cargo1 = newCargo( 100 );
-        Cargo cargo2 = newCargo( 9 );
-        int code = shippingService.makeBooking( cargo1, voyage );
-        assertEquals( 1, code );
-        code = shippingService.makeBooking( cargo2, voyage );
-        assertEquals( 2, code );
-    }
-
-    public void testTooMuch()
-    {
-        Cargo cargo1 = newCargo( 40 );
-        Cargo cargo2 = newCargo( 40 );
-        Cargo cargo3 = newCargo( 31 );
-        int code = shippingService.makeBooking( cargo1, voyage );
-        assertEquals( 1, code );
-        code = shippingService.makeBooking( cargo2, voyage );
-        assertEquals( 2, code );
-        code = shippingService.makeBooking( cargo3, voyage );
-        assertEquals( -1, code );
-    }
-
-    private Cargo newCargo( double size )
-    {
-        return new CargoImpl( size );
-    }
-
-    private Voyage newVoyage( String sourceCity, String destinationCity )
-    {
-        return new VoyageImpl( 100 );  // Fake the finder to just return a new Voyage for the demonstration purpose.
-    }
-}
diff --git a/tutorials/cargo/src/test/java/org/qi4j/tutorials/cargo/step2/SequencingConcernTest.java b/tutorials/cargo/src/test/java/org/qi4j/tutorials/cargo/step2/SequencingConcernTest.java
deleted file mode 100644
index a8ba2d9..0000000
--- a/tutorials/cargo/src/test/java/org/qi4j/tutorials/cargo/step2/SequencingConcernTest.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2008 Alin Dreghiciu.
- *
- * Licensed  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.qi4j.tutorials.cargo.step2;
-
-import org.junit.Ignore;
-import org.junit.Test;
-import org.qi4j.api.activation.ActivationException;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-import org.qi4j.test.mock.MockComposite;
-import org.qi4j.test.mock.MockPlayerMixin;
-
-import static org.easymock.EasyMock.*;
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-/**
- * Unit tests for SequencingConcern.
- *
- * @author Alin Dreghiciu
- */
-public class SequencingConcernTest
-{
-    /**
-     * Tests that when shipping service fails to make the booking generator is not called and booking failure code is
-     * returned.
-     */
-    @Test
-    @Ignore( "Expectations need to be figured out." )
-    public void failingBooking()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( ShippingServiceTestComposite.class );
-            }
-        };
-        ShippingService shippingService = createMock( ShippingService.class );
-        Cargo cargo = createMock( Cargo.class );
-        Voyage voyage = createMock( Voyage.class );
-        HasSequence sequence = createMock( HasSequence.class );
-        expect( shippingService.makeBooking( cargo, voyage ) ).andReturn( -1000 );
-        expect( voyage.bookedCargoSize().get() ).andReturn( 0.0 )
-            .atLeastOnce();
-        expect( cargo.size().get() ).andReturn( 0.0 )
-            .atLeastOnce();
-        expect( sequence.sequence().get() ).andReturn( 0 )
-            .atLeastOnce();
-        replay( shippingService, cargo, voyage );
-        ShippingServiceTestComposite underTest =
-            assembler.module().newTransient( ShippingServiceTestComposite.class );
-        underTest.useMock( shippingService ).forClass( ShippingService.class );
-        assertThat( "Booking result", underTest.makeBooking( cargo, voyage ), is( equalTo( -1000 ) ) );
-        verify( shippingService, cargo, voyage );
-    }
-
-    /**
-     * Tests that when shipping service succeeds to make the booking generator gets called and generated value is
-     * returned.
-     */
-    @Test
-    @Ignore( "Expectations need to be figured out." )
-    public void successfulBooking()
-        throws ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( ShippingServiceTestComposite.class );
-            }
-        };
-        ShippingService shippingService = createMock( ShippingService.class );
-        Cargo cargo = createMock( Cargo.class );
-        Voyage voyage = createMock( Voyage.class );
-        HasSequence generator = createMock( HasSequence.class );
-        Property<Integer> sequence = createMock( Property.class );
-        expect( shippingService.makeBooking( cargo, voyage ) ).andReturn( 100 );
-        expect( generator.sequence() ).andReturn( sequence ).anyTimes();
-        expect( sequence.get() ).andReturn( 1000 );
-        replay( shippingService, cargo, voyage, generator, sequence );
-        ShippingServiceTestComposite underTest =
-            assembler.module().newTransient( ShippingServiceTestComposite.class );
-        underTest.useMock( shippingService ).forClass( ShippingService.class );
-        underTest.useMock( generator ).forClass( HasSequence.class );
-        assertThat( "Booking result", underTest.makeBooking( cargo, voyage ), is( equalTo( 1000 ) ) );
-        verify( shippingService, cargo, voyage, generator, sequence );
-    }
-
-    @Mixins( MockPlayerMixin.class )
-    @Concerns( SequencingConcern.class )
-    public static interface ShippingServiceTestComposite
-        extends ShippingService, HasSequence, MockComposite
-    {
-    }
-}
diff --git a/tutorials/cargo/src/test/java/org/qi4j/tutorials/cargo/step2/Step2TestCase.java b/tutorials/cargo/src/test/java/org/qi4j/tutorials/cargo/step2/Step2TestCase.java
deleted file mode 100644
index 0c746ee..0000000
--- a/tutorials/cargo/src/test/java/org/qi4j/tutorials/cargo/step2/Step2TestCase.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2007, 2008 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.cargo.step2;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.junit.Assert.assertEquals;
-
-public class Step2TestCase
-    extends AbstractQi4jTest
-{
-    private Voyage voyage;
-    private ShippingService shippingService;
-
-    @Override
-    public void setUp()
-        throws Exception
-    {
-        super.setUp();
-        TransientBuilder<VoyageComposite> voyageBuilder = module.newTransientBuilder( VoyageComposite.class );
-        voyageBuilder.prototypeFor( Voyage.class ).bookedCargoSize().set( 0.0 );
-        voyageBuilder.prototypeFor( Voyage.class ).capacity().set( 100.0 );
-        voyage = voyageBuilder.newInstance();
-
-        TransientBuilder<ShippingServiceComposite> shippingBuilder =
-            module.newTransientBuilder( ShippingServiceComposite.class );
-        shippingService = shippingBuilder.newInstance();
-    }
-
-    @Test
-    public void testOrdinaryBooking()
-    {
-        Cargo cargo1 = newCargo( 40 );
-        Cargo cargo2 = newCargo( 40 );
-        Cargo cargo3 = newCargo( 20 );
-        int code = shippingService.makeBooking( cargo1, voyage );
-        assertEquals( 0, code );
-        code = shippingService.makeBooking( cargo2, voyage );
-        assertEquals( 1, code );
-        code = shippingService.makeBooking( cargo3, voyage );
-        assertEquals( 2, code );
-    }
-
-    @Test
-    public void testOverbooking()
-    {
-        Cargo cargo1 = newCargo( 100 );
-        Cargo cargo2 = newCargo( 9 );
-        int code = shippingService.makeBooking( cargo1, voyage );
-        assertEquals( 0, code );
-        code = shippingService.makeBooking( cargo2, voyage );
-        assertEquals( -1, code );
-    }
-
-    @Test
-    public void testTooMuch()
-    {
-        Cargo cargo1 = newCargo( 40 );
-        Cargo cargo2 = newCargo( 40 );
-        Cargo cargo3 = newCargo( 31 );
-        int code = shippingService.makeBooking( cargo1, voyage );
-        assertEquals( 0, code );
-        code = shippingService.makeBooking( cargo2, voyage );
-        assertEquals( 1, code );
-        code = shippingService.makeBooking( cargo3, voyage );
-        assertEquals( -1, code );
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( VoyageComposite.class, CargoComposite.class, ShippingServiceComposite.class );
-    }
-
-    private Cargo newCargo( double size )
-    {
-        TransientBuilder<CargoComposite> builder = module.newTransientBuilder( CargoComposite.class );
-        builder.prototypeFor( Cargo.class ).size().set( size );
-        return builder.newInstance();
-    }
-}
diff --git a/tutorials/composites/build.gradle b/tutorials/composites/build.gradle
index 534848a..579836f 100644
--- a/tutorials/composites/build.gradle
+++ b/tutorials/composites/build.gradle
@@ -1,31 +1,36 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Basic tutorial on how to covert a simple 'Hello World' application to Apache Zest™, using more and more features for each step."
+apply plugin: 'polygene-tutorial'
 
-jar { manifest { name = "Apache Zest™ Tutorial - Composites" }}
+description = "Basic tutorial on how to covert a simple 'Hello World' application to Apache Polygene™, using more and more features for each step."
+
+jar { manifest { name = "Apache Polygene™ Tutorial - Composites" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile(project(":org.qi4j.libraries:org.qi4j.library.constraints"))
+  implementation polygene.core.bootstrap
+  implementation polygene.library( 'constraints' )
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
 }
diff --git a/tutorials/composites/src/docs/step1.txt b/tutorials/composites/src/docs/step1.txt
index df8ce5c..251e9c1 100644
--- a/tutorials/composites/src/docs/step1.txt
+++ b/tutorials/composites/src/docs/step1.txt
@@ -22,12 +22,12 @@
 
 == Initial Hello World ==
 
-This whole tutorial describes how to step-by-step modify a typical HelloWorld "application" into a full-fledged Zest™
+This whole tutorial describes how to step-by-step modify a typical HelloWorld "application" into a full-fledged Polygene™
 Composite Oriented application. Here is the initial code of HelloWorld.
 
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial1/HelloWorld.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial1/HelloWorld.java
 tag=initial
 ----
 
@@ -36,7 +36,7 @@
 In this step we start with a basic Java class, which when invoked will concatenate the two properties "phrase" 
 and "name". If invoked with the properties set to "Hello" and "World" respectively it will hence return "Hello World".
 
-Zest™ relies heavily on the use of interfaces. This makes it possible for an object to externally implement a number of
+Polygene™ relies heavily on the use of interfaces. This makes it possible for an object to externally implement a number of
 interfaces which internally is backed by a number of Mixins, some of which you may have written yourself, and some of 
 which may have been reused. This also makes it easy to introduce Modifiers (aka "interceptors", aka "advice"), which 
 are Fragments which execute before and/or after the method on the Mixin is invoked.
@@ -57,28 +57,28 @@
 *HelloWorld.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/HelloWorld.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorld.java
 tag=solution
 ----
 
 *HelloWorldState.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/HelloWorldState.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorldState.java
 tag=solution
 ----
 
 *HelloWorldBehaviour.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/HelloWorldBehaviour.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorldBehaviour.java
 tag=solution
 ----
 
 *HelloWorldMixin.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/HelloWorldMixin.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorldMixin.java
 tag=solution
 ----
 
diff --git a/tutorials/composites/src/docs/step2.txt b/tutorials/composites/src/docs/step2.txt
index 1268ce1..a05c22e 100644
--- a/tutorials/composites/src/docs/step2.txt
+++ b/tutorials/composites/src/docs/step2.txt
@@ -29,12 +29,12 @@
 framework will inspect the interface to determine what the TransientComposite instance should look like in terms of 
 used Fragments.
 
-In Zest™ all method parameters are considered mandatory unless marked as @Optional. Therefore you can remove the null
-checks in the Mixin. If a null value is passed in an exception will be thrown by Zest™.
+In Polygene™ all method parameters are considered mandatory unless marked as @Optional. Therefore you can remove the null
+checks in the Mixin. If a null value is passed in an exception will be thrown by Polygene™.
 
 Steps for this tutorial:
 
-- Create an interface that extends the domain interface HelloWorld and org.qi4j.api.composite.TransientComposite.
+- Create an interface that extends the domain interface +HelloWorld+.
 - Add a @Mixins annotation to it with the name of the Mixin as argument.
 
 == Solution ==
@@ -48,14 +48,14 @@
 *HelloWorldComposite.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/HelloWorldComposite.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorldComposite.java
 tag=solution
 ----
 
 *HelloWorldMixin.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/HelloWorldMixin.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorldMixin.java
 tag=solution
 ----
 
diff --git a/tutorials/composites/src/docs/step3.txt b/tutorials/composites/src/docs/step3.txt
index 3522898..214ba47 100644
--- a/tutorials/composites/src/docs/step3.txt
+++ b/tutorials/composites/src/docs/step3.txt
@@ -31,7 +31,7 @@
 
 - Refactor the Mixin into one which implement the behaviour interface and one which implements the state interface. Use the @This injection annotation to allow the behaviour to access the state.
 - Add a @Mixins annotations on the behaviour and state interfaces which declare the Mixins as default implementations.
-- Remove the @Mixins annotation from the TransientComposite interface.
+- Remove the @Mixins annotation from the HelloWorldComposite interface.
 
 == Solution ==
 
@@ -40,35 +40,35 @@
 *HelloWorldComposite.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldComposite.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldComposite.java
 tag=solution
 ----
 
 *HelloWorldBehaviour.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldBehaviour.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldBehaviour.java
 tag=solution
 ----
 
 *HelloWorldBehaviourMixin.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldBehaviourMixin.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldBehaviourMixin.java
 tag=solution
 ----
 
 *HelloWorldState.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldState.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldState.java
 tag=solution
 ----
 
 *HelloWorldStateMixin.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldStateMixin.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldStateMixin.java
 tag=solution
 ----
 
diff --git a/tutorials/composites/src/docs/step4.txt b/tutorials/composites/src/docs/step4.txt
index d940443..c5d3333 100644
--- a/tutorials/composites/src/docs/step4.txt
+++ b/tutorials/composites/src/docs/step4.txt
@@ -63,14 +63,14 @@
 *HelloWorldBehaviourMixin.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldBehaviourMixin.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldBehaviourMixin.java
 tag=solution
 ----
 
 *HelloWorldBehaviourConcern.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldBehaviourConcern.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldBehaviourConcern.java
 tag=solution
 ----
 
diff --git a/tutorials/composites/src/docs/step5.txt b/tutorials/composites/src/docs/step5.txt
index 054d1ad..022cc50 100644
--- a/tutorials/composites/src/docs/step5.txt
+++ b/tutorials/composites/src/docs/step5.txt
@@ -27,7 +27,7 @@
 optional, integer ranges, string regular expressions, and so on, cannot be expressed, and so we have to put this into
 Javadoc, and then manually add these checks in the implementation class.
 
-In Zest™ there is the option to use Constraints, which are further restrictions on the parameters. This is implemented
+In Polygene™ there is the option to use Constraints, which are further restrictions on the parameters. This is implemented
 by having an annotation that describes what the Constraint does, and then an implementation class that checks whether a
 specific value fulfills the Constraint or not.
 
@@ -35,8 +35,8 @@
 introduce a new dependency to the <<library-constraints>>, where all the constraint related classes reside. So
 update your classpath settings accordingly.
 
-There are a number of pre-written constraints in Zest™ which you can use. The null check of the original HelloWorld
-version is already handled by default since Zest™ considers method parameters to be mandatory if not explicitly marked
+There are a number of pre-written constraints in Polygene™ which you can use. The null check of the original HelloWorld
+version is already handled by default since Polygene™ considers method parameters to be mandatory if not explicitly marked
 with the @Optional annotation. So, instead of doing that check we will add other checks that are useful to make, such
 as ensuring that the passed in string is not empty.
 
@@ -66,28 +66,28 @@
 *HelloWorldBehaviour.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldBehaviour.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldBehaviour.java
 tag=solution
 ----
 
 *HelloWorldBehaviourMixin.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldBehaviourMixin.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldBehaviourMixin.java
 tag=solution
 ----
 
 *HelloWorldBehaviourConcern.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldBehaviourConcern.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldBehaviourConcern.java
 tag=solution
 ----
 
 *HelloWorldState.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldState.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldState.java
 tag=solution
 ----
 
diff --git a/tutorials/composites/src/docs/step6.txt b/tutorials/composites/src/docs/step6.txt
index 4ba88e5..675dd36 100644
--- a/tutorials/composites/src/docs/step6.txt
+++ b/tutorials/composites/src/docs/step6.txt
@@ -62,28 +62,28 @@
 *HelloWorldBehaviour.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldBehaviour.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldBehaviour.java
 tag=solution
 ----
 
 *HelloWorldBehaviourSideEffect.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldBehaviourSideEffect.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldBehaviourSideEffect.java
 tag=solution
 ----
 
 *HelloWorldComposite.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldComposite.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldComposite.java
 tag=solution
 ----
 
 *HelloWorldState.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldState.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldState.java
 tag=solution
 ----
 
diff --git a/tutorials/composites/src/docs/step7.txt b/tutorials/composites/src/docs/step7.txt
index bdec58a..4c5a5d2 100644
--- a/tutorials/composites/src/docs/step7.txt
+++ b/tutorials/composites/src/docs/step7.txt
@@ -22,11 +22,11 @@
 
 Previous step was <<tut-composites-step6>>.
 
-One of the goals of Zest™ is to give you domain modeling tools that allow you to more concisely use domain concepts in
+One of the goals of Polygene™ is to give you domain modeling tools that allow you to more concisely use domain concepts in
 code. One of the things we do rather often is model Properties of objects as getters and setters. But this is a very 
 weak model, and does not give you any access to metadata about the property, and also makes common tasks like UI binding
 non-trivial. There is also a lot of repetition of code, which is unnecessary. Using JavaBeans conventions one typically 
-have to have code in five places for one property, whereas in Zest™ the same thing can be achieved with one line of code.
+have to have code in five places for one property, whereas in Polygene™ the same thing can be achieved with one line of code.
 
 But lets start out easy. To declare a property you have to make a method in a mixin type that returns a value of the 
 type Property, and which does not take any parameters. Here's a simple example:
@@ -43,14 +43,14 @@
 reducing Properties to one-liners!
 
 In the Mixin implementation of the interface with the Property declaration you should have an injection of the Property, 
-which is created for you by Zest™. The injection can be done in a field like this:
+which is created for you by Polygene™. The injection can be done in a field like this:
 
 [source,java]
 ----
 @State Property<String> name;
 ----
 
-The State dependency injection annotation means that Zest™ will inject the Property for you. The field has the name
+The State dependency injection annotation means that Polygene™ will inject the Property for you. The field has the name
 "name", which matches the name in the interface, and therefore that Property is injected. You can then implement the 
 method trivially by just returning the "name" field.
 
@@ -80,28 +80,28 @@
 *HelloWorldBehaviourMixin.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldBehaviourMixin.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldBehaviourMixin.java
 tag=solution
 ----
 
 *HelloWorldComposite.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldComposite.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldComposite.java
 tag=solution
 ----
 
 *HelloWorldState.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldState.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldState.java
 tag=solution
 ----
 
 *HelloWorldStateMixin.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldStateMixin.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldStateMixin.java
 tag=solution
 ----
 
diff --git a/tutorials/composites/src/docs/step8.txt b/tutorials/composites/src/docs/step8.txt
index 90225ce..ac26edd 100644
--- a/tutorials/composites/src/docs/step8.txt
+++ b/tutorials/composites/src/docs/step8.txt
@@ -33,7 +33,7 @@
 TransientComposite in this case), the method, and the arguments. The Fragment is then allowed to implement the method 
 any way it wants.
 
-Since interfaces with only Properties is such a common case Zest™ already has a generic Mixin that implements the
+Since interfaces with only Properties is such a common case Polygene™ already has a generic Mixin that implements the
 Properties management described above, but for the builtin Property type instead of the getter/setter variant. The 
 class is aptly named PropertyMixin.
 
@@ -43,7 +43,7 @@
 
 - Remove the HelloWorldStateMixin
 - Add a GenericPropertyMixin, and have it implement InvocationHandler
-- Inject "@State StateHolder state" in the mixin. The StateHolder interface will give you access to the Properties for the TransientComposite which Zest™ manages for you
+- Inject "@State StateHolder state" in the mixin. The StateHolder interface will give you access to the Properties for the TransientComposite which Polygene™ manages for you
 - On call to invoke(), delegate to the StateHolder interface to get the Property for the invoked method
 - Add an @AppliesTo annotation to the Mixin and implement the AppliesToFilter with a rule that matches only methods that return Property values.
 - Add the mixin to the TransientComposite.
@@ -60,21 +60,21 @@
 *GenericPropertyMixin.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/GenericPropertyMixin.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/GenericPropertyMixin.java
 tag=solution
 ----
 
 *HelloWorldBehaviourMixin.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldBehaviourMixin.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/HelloWorldBehaviourMixin.java
 tag=solution
 ----
 
 *HelloWorldComposite.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldComposite.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/HelloWorldComposite.java
 tag=solution
 ----
 
diff --git a/tutorials/composites/src/docs/step9.txt b/tutorials/composites/src/docs/step9.txt
index 6e6047f..ce9268b 100644
--- a/tutorials/composites/src/docs/step9.txt
+++ b/tutorials/composites/src/docs/step9.txt
@@ -31,7 +31,7 @@
 implement all methods, including those found in the TransientComposite interface. However, since we are only really 
 interested in implementing the say() method we will mark this by declaring that the Mixin "implements" the 
 TransientComposite type, but is also "abstract". This, using pure Java semantics, makes it possible to avoid having to 
-implement all methods. Zest™ will during the initialization phase detect that the Mixin only handles the say() method,
+implement all methods. Polygene™ will during the initialization phase detect that the Mixin only handles the say() method,
 and therefore only map it to that specific method. In order to instantiate the Mixin it will generate a subclass which 
 implements the remaining methods in the TransientComposite type, as no-ops. These will never be called however, and is 
 there purely for the purpose of being able to instantiate the Mixin. The Mixin is considered to be an Abstract Fragment.
@@ -39,7 +39,7 @@
 To hide the state from the client we need to use what is called Private Mixins. A Private Mixin is any mixin that is 
 referenced by another Mixin by using the @This injection, but which is not included in the TransientComposite type. As 
 long as there is a Mixin implementation declared for the interface specified by the @This injection it will work, since 
-Zest™ can know how to implement the interface. But since it is not extended by the TransientComposite type there is no
+Polygene™ can know how to implement the interface. But since it is not extended by the TransientComposite type there is no
 way for a user of the TransientComposite to access it. That Mixin becomes an implementation detail. This can be used 
 either for encapsulation purposes, or for referencing utility mixins that help the rest of the code implement some 
 interface, but which itself should not be exposed.
@@ -65,20 +65,20 @@
 *HelloWorldComposite.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial10/HelloWorldComposite.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial10/HelloWorldComposite.java
 tag=solution
 ----
 
 *HelloWorldMixin.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial10/HelloWorldMixin.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial10/HelloWorldMixin.java
 tag=solution
 ----
 
 *HelloWorldState.java*
 [snippet,java]
 ----
-source=tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial10/HelloWorldState.java
+source=tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial10/HelloWorldState.java
 tag=solution
 ----
diff --git a/tutorials/composites/src/docs/tut-composites.txt b/tutorials/composites/src/docs/tut-composites.txt
index 6077467..8e9cff2 100644
--- a/tutorials/composites/src/docs/tut-composites.txt
+++ b/tutorials/composites/src/docs/tut-composites.txt
@@ -21,14 +21,14 @@
 = Transient Composites Tutorial =
 
 TIP: Theses tutorials are based on actual code found in the `tutorials/` directory of the
-https://zest.apache.org/download.html[Zest™ SDK sources]. You should start your favorite editor and find the code related to
+https://polygene.apache.org/download.html[Polygene™ SDK sources]. You should start your favorite editor and find the code related to
 this tutorial, run it and play with it.
 
 Throughout this set of tutorials it will be shown how to create and work with Composites, which
-is the basic element in Zest™. We will refactor one HelloWorld class to take advantage of the various
-features in Zest™. These refactorings will make it easier to reuse parts of the class,
+is the basic element in Polygene™. We will refactor one HelloWorld class to take advantage of the various
+features in Polygene™. These refactorings will make it easier to reuse parts of the class,
 and introduce new features without having to change existing code. We will also look
-at some of the existing classes, or Fragments, available in Zest™ that you can reuse
+at some of the existing classes, or Fragments, available in Polygene™ that you can reuse
 so that you don't have to write everything yourself.
 
 - <<tut-composites-step1>>
@@ -48,11 +48,11 @@
 have followed the instructions.
 
 If you want to reproduce what's explained in this tutorial, remember to depend on the Core Runtime artifact that depends
-on Core API, Core SPI, Core Bootstrap and Core Functional & I/O APIs:
+on Core API, Core SPI, and Core Bootstrap:
 
 include::../../../../core/runtime/build/docs/buildinfo/artifact.txt[]
 
-See the <<howto-depend-on-zest>> tutorial for details.
+See the <<howto-depend-on-polygene>> tutorial for details.
 
 :leveloffset: 3
 
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/package.html b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/package.html
new file mode 100644
index 0000000..af7cb1a
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/package.html
@@ -0,0 +1,51 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+<head>
+</head>
+<body>
+Description of TransientComposite tutorials.
+
+<h2>TransientComposite tutorials</h2>
+<p>
+Throughout this set of tutorials it will be shown how to create and work with TransientComposites, which
+is the basic element in Apache Polygene™. We will refactor one HelloWorld class to take advantage of the various
+features in Polygene™. These refactorings will make it easier to reuse parts of the class,
+and introduce new features without having to change existing code. We will also look
+at some of the existing classes, or Fragments, available in Polygene™ that you can reuse
+so that you don't have to write everything yourself.
+</p>
+<p>
+Each tutorial in this series starts with the result from the previous tutorial, so you can
+always look at the next tutorial step for guidance on what to do. Here are the steps:
+</p>
+<ol>
+    <li>Interface refactoring</li>
+    <li>Creating a TransientComposite</li>
+    <li>Mixins</li>
+    <li>Concerns</li>
+    <li>Constraints</li>
+    <li>SideEffects</li>
+    <li>Properties</li>
+    <li>Generic mixins</li>
+    <li>Private and abstract mixins</li>
+</ol>
+</body>
+</html>
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial1/HelloWorld.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial1/HelloWorld.java
new file mode 100644
index 0000000..859f56b
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial1/HelloWorld.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial1;
+
+// START SNIPPET: initial
+
+/**
+ * Initial HelloWorld implementation. Everything is mixed up
+ * into one class, and no interface is used.
+ */
+public class HelloWorld
+{
+    String phrase;
+    String name;
+
+    public String getPhrase()
+    {
+        return phrase;
+    }
+
+    public void setPhrase( String phrase )
+        throws IllegalArgumentException
+    {
+        if( phrase == null )
+        {
+            throw new IllegalArgumentException( "Phrase may not be null " );
+        }
+
+        this.phrase = phrase;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName( String name )
+        throws IllegalArgumentException
+    {
+        if( name == null )
+        {
+            throw new IllegalArgumentException( "Name may not be null " );
+        }
+
+        this.name = name;
+    }
+
+    public String say()
+    {
+        return phrase + " " + name;
+    }
+}
+// END SNIPPET: initial
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial1/package.html b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial1/package.html
new file mode 100644
index 0000000..c5ab767
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial1/package.html
@@ -0,0 +1,49 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<body>
+<h1>Tutorial 1 - Interface refactoring</h1>
+<p>
+In this tutorial we start with a basic Java class, which when invoked will concatenate
+the two properties "phrase" and "name". If invoked with the properties set to "Hello"
+and "World" respectively it will hence return "Hello World".
+</p>
+<p>
+Polygene™ relies heavily on the use of interfaces. This makes it possible for an object
+to externally implement a number of interfaces which internally is backed by a number
+of Mixins, some of which you may have written yourself, and some of which may have been
+reused. This also makes it easy to introduce Modifiers (aka "interceptors", aka "advice"),
+which are Fragments which execute before and/or after the method on the Mixin is invoked.
+</p>
+<p>
+The first task is therefore to refactor the code so that the method is implemented from an
+interface instead. We should then also separate the state into one interface and the behaviour
+into another. This will make things easier for us later when state and behaviour becomes
+implemented by separate Mixins.
+</p>
+<p>
+Steps for this tutorial:
+</p>
+<ol>
+    <li>Refactor the class into interface and implementation.</li>
+    <li>Refactor the interface so that it extends one interface called HelloWorldBehaviour with behaviour and one called
+        HelloWorldState with state (get/set methods).
+    </li>
+</ol>
+</body>
\ No newline at end of file
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial10/HelloWorldComposite.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial10/HelloWorldComposite.java
new file mode 100644
index 0000000..fe5a838
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial10/HelloWorldComposite.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial10;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+// START SNIPPET: solution
+
+/**
+ * This Composite interface declares transitively all the Fragments of the HelloWorld composite.
+ * <p>
+ * The Fragments are all abstract, so it's ok to
+ * put the domain methods here. Otherwise the Fragments
+ * would have to implement all methods, including those in Composite.
+ * </p>
+ */
+@Mixins( { HelloWorldMixin.class } )
+public interface HelloWorldComposite
+{
+    String say();
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial10/HelloWorldMixin.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial10/HelloWorldMixin.java
new file mode 100644
index 0000000..bfa1cfd
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial10/HelloWorldMixin.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial10;
+
+import org.apache.polygene.api.injection.scope.This;
+
+// START SNIPPET: solution
+
+/**
+ * This is the implementation of the say() method. The mixin
+ * is abstract so it doesn't have to implement all methods
+ * from the Composite interface.
+ */
+public abstract class HelloWorldMixin
+    implements HelloWorldComposite
+{
+    @This
+    HelloWorldState state;
+
+    @Override
+    public String say()
+    {
+        return state.phrase().get() + " " + state.name().get();
+    }
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial10/HelloWorldState.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial10/HelloWorldState.java
new file mode 100644
index 0000000..5b50034
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial10/HelloWorldState.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial10;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.constraints.annotation.NotEmpty;
+
+// START SNIPPET: solution
+
+/**
+ * This interface contains only the state
+ * of the HelloWorld object.
+ */
+public interface HelloWorldState
+{
+    @NotEmpty
+    Property<String> phrase();
+
+    @NotEmpty
+    Property<String> name();
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorld.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorld.java
new file mode 100644
index 0000000..d7b682d
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorld.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial2;
+
+// START SNIPPET: solution
+
+/**
+ * This interface aggregates the behaviour and state
+ * of the HelloWorld sub-interfaces. To a client
+ * this is the same as before though, since it only
+ * has to deal with this interface instead of the
+ * two sub-interfaces.
+ */
+public interface HelloWorld
+    extends HelloWorldBehaviour, HelloWorldState
+{
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorldBehaviour.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorldBehaviour.java
new file mode 100644
index 0000000..03a38f6
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorldBehaviour.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial2;
+
+// START SNIPPET: solution
+
+/**
+ * This interface contains only the behaviour
+ * of the HelloWorld object.
+ */
+public interface HelloWorldBehaviour
+{
+    String say();
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorldMixin.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorldMixin.java
new file mode 100644
index 0000000..60bc8e5
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorldMixin.java
@@ -0,0 +1,76 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial2;
+
+// START SNIPPET: solution
+
+/**
+ * This is the implementation of the HelloWorld
+ * interface. The behaviour and state is mixed.
+ */
+public class HelloWorldMixin
+    implements HelloWorld
+{
+    String phrase;
+    String name;
+
+    @Override
+    public String say()
+    {
+        return getPhrase() + " " + getName();
+    }
+
+    @Override
+    public void setPhrase( String phrase )
+        throws IllegalArgumentException
+    {
+        if( phrase == null )
+        {
+            throw new IllegalArgumentException( "Phrase may not be null" );
+        }
+
+        this.phrase = phrase;
+    }
+
+    @Override
+    public String getPhrase()
+    {
+        return phrase;
+    }
+
+    @Override
+    public void setName( String name )
+        throws IllegalArgumentException
+    {
+        if( name == null )
+        {
+            throw new IllegalArgumentException( "Name may not be null" );
+        }
+
+        this.name = name;
+    }
+
+    @Override
+    public String getName()
+    {
+        return name;
+    }
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorldState.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorldState.java
new file mode 100644
index 0000000..fe810a1
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorldState.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial2;
+
+// START SNIPPET: solution
+
+/**
+ * This interface contains only the state
+ * of the HelloWorld object.
+ * The exceptions will be thrown by Polygene automatically if
+ * null is sent in as values. The parameters would have to be declared
+ * as @Optional if null is allowed.
+ */
+public interface HelloWorldState
+{
+    void setPhrase( String phrase )
+        throws IllegalArgumentException;
+
+    String getPhrase();
+
+    void setName( String name )
+        throws IllegalArgumentException;
+
+    String getName();
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/package.html b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/package.html
new file mode 100644
index 0000000..7d12bef
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial2/package.html
@@ -0,0 +1,44 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<body>
+<h1>Tutorial 2 - Creating a Composite</h1>
+<p>
+In this tutorial we will create a TransientComposite interface that ties all pieces together.
+The TransientComposite interface is a regular Java interface which extends the interfaces you
+want to expose from your domain model, and which uses various annotations to declare
+what Fragments to include. Fragments include Mixins, Concerns, SideEffects and Constraints.
+In this tutorial we will only use Mixins. When a TransientComposite is instantiated at runtime
+the framework will inspect the interface to determine what the TransientComposite instance should
+look like in terms of used Fragments.
+</p>
+<p>
+In Polygene™ all method parameters are considered mandatory unless marked as @Optional. Therefore you can
+remove the null checks in the Mixin. If a null value is passed in an exception will be thrown by Polygene™.
+</p>
+<p>
+Steps for this tutorial:
+</p>
+<ol>
+    <li>Create an interface that extends the domain interface HelloWorld and
+        org.apache.polygene.api.composite.TransientComposite.
+    </li>
+    <li>Add a @Mixins annotation to it with the name of the Mixin as argument.</li>
+</ol>
+</body>
\ No newline at end of file
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorld.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorld.java
new file mode 100644
index 0000000..0a89b5a
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorld.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial3;
+
+/**
+ * This interface aggregates the behaviour and state
+ * of the HelloWorld sub-interfaces. To a client
+ * this is the same as before though, since it only
+ * has to deal with this interface instead of the
+ * two sub-interfaces.
+ */
+public interface HelloWorld
+    extends HelloWorldBehaviour, HelloWorldState
+{
+}
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorldBehaviour.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorldBehaviour.java
new file mode 100644
index 0000000..5dace3a
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorldBehaviour.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial3;
+
+/**
+ * This interface contains only the behaviour
+ * of the HelloWorld object.
+ */
+public interface HelloWorldBehaviour
+{
+    String say();
+}
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorldComposite.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorldComposite.java
new file mode 100644
index 0000000..a8031b0
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorldComposite.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial3;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+// START SNIPPET: solution
+
+/**
+ * This Composite interface declares all the Fragments of the HelloWorld composite.
+ * <p>
+ * Currently it only declares one Mixin.
+ * </p>
+ */
+@Mixins( HelloWorldMixin.class )
+public interface HelloWorldComposite
+    extends HelloWorld
+{
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorldMixin.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorldMixin.java
new file mode 100644
index 0000000..187bcf3
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorldMixin.java
@@ -0,0 +1,65 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial3;
+
+// START SNIPPET: solution
+
+/**
+ * This is the implementation of the HelloWorld
+ * interface. The behaviour and state is mixed. Since parameters
+ * are mandatory as default in Polygene there's no need to do null checks.
+ */
+public class HelloWorldMixin
+    implements HelloWorld
+{
+    String phrase;
+    String name;
+
+    @Override
+    public String say()
+    {
+        return phrase + " " + name;
+    }
+
+    @Override
+    public String getPhrase()
+    {
+        return phrase;
+    }
+
+    @Override
+    public void setPhrase( String phrase )
+    {
+        this.phrase = phrase;
+    }
+
+    @Override
+    public String getName()
+    {
+        return name;
+    }
+
+    @Override
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorldState.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorldState.java
new file mode 100644
index 0000000..b093565
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorldState.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial3;
+
+/**
+ * This interface contains only the state
+ * of the HelloWorld Composite.
+ * The exceptions will be thrown by Polygene automatically if
+ * null is sent in as values. The parameters would have to be declared
+ * as @Optional if null is allowed.
+ */
+public interface HelloWorldState
+{
+    void setPhrase( String phrase )
+        throws IllegalArgumentException;
+
+    String getPhrase();
+
+    void setName( String name )
+        throws IllegalArgumentException;
+
+    String getName();
+}
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/package.html b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/package.html
new file mode 100644
index 0000000..91114cc
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial3/package.html
@@ -0,0 +1,41 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<body>
+<h1>Tutorial 3 - Mixins</h1>
+<p>
+In this tutorial we refactor the Mixin from the previous steps into two, one which serves
+the behaviour interface and one which serves the state interface. This makes it possible to
+reuse the interfaces independently and also makes it easier to exchange one interface implementation
+with another. This also allows us to specify the new Mixins as default implementations of
+the interfaces by adding @Mixins annotations on them.
+</p>
+<p>
+Steps for this tutorial:
+</p>
+<ol>
+    <li>Refactor the Mixin into one which implement the behaviour interface and one which implements the state
+        interface. Use the @This injection annotation to allow the behaviour to access the state.
+    </li>
+    <li>Add a @Mixins annotations on the behaviour and state interfaces which declare the Mixins as default
+        implementations.
+    </li>
+    <li>Remove the @Mixins annotation from the TransientComposite interface.</li>
+</ol>
+</body>
\ No newline at end of file
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorld.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorld.java
new file mode 100644
index 0000000..378c916
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorld.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial4;
+
+/**
+ * This interface aggregates the behaviour and state
+ * of the HelloWorld sub-interfaces. To a client
+ * this is the same as before though, since it only
+ * has to deal with this interface instead of the
+ * two sub-interfaces.
+ */
+public interface HelloWorld
+    extends HelloWorldBehaviour, HelloWorldState
+{
+}
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldBehaviour.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldBehaviour.java
new file mode 100644
index 0000000..28aa151
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldBehaviour.java
@@ -0,0 +1,37 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial4;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+// START SNIPPET: solution
+
+/**
+ * This interface contains only the behaviour of the HelloWorld object.
+ * <p>
+ * It declares what Mixin to use as default implementation.
+ * </p>
+ */
+@Mixins( HelloWorldBehaviourMixin.class )
+public interface HelloWorldBehaviour
+{
+    String say();
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldBehaviourMixin.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldBehaviourMixin.java
new file mode 100644
index 0000000..38d6b30
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldBehaviourMixin.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial4;
+
+import org.apache.polygene.api.injection.scope.This;
+
+// START SNIPPET: solution
+
+/**
+ * This is the implementation of the HelloWorld behaviour interface.
+ * <p>
+ * It uses a @This Dependency Injection
+ * annotation to access the state of the Composite. The field
+ * will be automatically injected when the Composite
+ * is instantiated. Injections of resources or references
+ * can be provided either to fields, constructor parameters or method parameters.
+ * </p>
+ */
+public class HelloWorldBehaviourMixin
+    implements HelloWorldBehaviour
+{
+    @This
+    HelloWorldState state;
+
+    @Override
+    public String say()
+    {
+        return state.getPhrase() + " " + state.getName();
+    }
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldComposite.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldComposite.java
new file mode 100644
index 0000000..4dcdfc7
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldComposite.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial4;
+
+// START SNIPPET: solution
+
+/**
+ * This Composite interface declares all the Fragments
+ * of the HelloWorld composite.
+ * <p>
+ * The Mixins annotation has been moved to the respective sub-interfaces.
+ * The sub-interfaces therefore declare themselves what mixin implementation
+ * is preferred. This interface could still have its own Mixins annotation
+ * with overrides of those defaults however.
+ * </p>
+ */
+public interface HelloWorldComposite
+    extends HelloWorld
+{
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldState.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldState.java
new file mode 100644
index 0000000..5c116a7
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldState.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial4;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+// START SNIPPET: solution
+
+/**
+ * This interface contains only the state
+ * of the HelloWorld object.
+ * The exceptions will be thrown by Polygene automatically if
+ * null is sent in as values. The parameters would have to be declared
+ * as @Optional if null is allowed.
+ */
+@Mixins( HelloWorldStateMixin.class )
+public interface HelloWorldState
+{
+    void setPhrase( String phrase )
+        throws IllegalArgumentException;
+
+    String getPhrase();
+
+    void setName( String name )
+        throws IllegalArgumentException;
+
+    String getName();
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldStateMixin.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldStateMixin.java
new file mode 100644
index 0000000..c69da60
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldStateMixin.java
@@ -0,0 +1,58 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial4;
+
+// START SNIPPET: solution
+
+/**
+ * This is the implementation of the HelloWorld
+ * state interface.
+ */
+public class HelloWorldStateMixin
+    implements HelloWorldState
+{
+    String phrase;
+    String name;
+
+    @Override
+    public String getPhrase()
+    {
+        return phrase;
+    }
+
+    @Override
+    public void setPhrase( String phrase )
+    {
+        this.phrase = phrase;
+    }
+
+    @Override
+    public String getName()
+    {
+        return name;
+    }
+
+    @Override
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/package.html b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/package.html
new file mode 100644
index 0000000..6cf913f
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial4/package.html
@@ -0,0 +1,59 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<body>
+<h1>Tutorial 4 - Concerns</h1>
+<p>
+In this tutorial we refactor the mixin from the previous steps so that the result of the say() method
+is modified to be prefixed with "Simon says:". To do this we need to implement a Concern for
+the say() method. Concerns are a type of Modifier which modify the behaviour of
+the methods in Mixins. They do this by intercepting the invocation of the TransientComposite. This allows
+them to change the invocation parameters, return their own values or throw their own exceptions,
+and do other things which directly affect the invocation of the method.
+</p>
+<p>
+Concerns should not perform any side-effects, such as updating state in another TransientComposite, Mixin
+or similar. Any side-effects are done in SideEffects, which is another type of Modifier, which are
+allowed to perform side-effects but, in contrast to Concerns, cannot change the parameters or
+in any other way change the result of the invocation.
+</p>
+<p>
+Concerns are implemented in one of two ways: either create a class which directly implements
+the interface whose methods should be modified, or create a generic Modifier by implementing
+the InvocationHandler interface (or subclass GenericConcern which does this for you).
+Add an @ConcernFor dependency injection, as a field, constructor parameter or method parameter,
+which has the same type as the interface the Concern implements. When the TransientComposite is invoked
+the Concern will be called, allowing it to perform it's work. If the call should proceed, then
+invoke the method again on the injected object. The preferred way to do all of this is to subclass
+ConcernOf which does all of this for you.
+</p>
+<p>
+Concerns are applied by adding an @Concerns annotation on the TransientComposite, the domain interface,
+or the Mixin implementation. Any of these works, and where to put it is a matter of design choice.
+</p>
+<p>
+Steps for this tutorial:
+</p>
+<ol>
+    <li>Create a typed concern, implement the HelloWorldBehaviour and let it modify the result
+        of the base method by prefix the result with "Simon says:".
+    </li>
+    <li>Add an @Concerns annotation on the HelloWorldBehaviourMixin which references the Concern class.</li>
+</ol>
+</body>
\ No newline at end of file
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorld.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorld.java
new file mode 100644
index 0000000..4e5b818
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorld.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial5;
+
+/**
+ * This interface aggregates the behaviour and state
+ * of the HelloWorld sub-interfaces. To a client
+ * this is the same as before though, since it only
+ * has to deal with this interface instead of the
+ * two sub-interfaces.
+ */
+public interface HelloWorld
+    extends HelloWorldBehaviour, HelloWorldState
+{
+}
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldBehaviour.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldBehaviour.java
new file mode 100644
index 0000000..9f4c122
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldBehaviour.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial5;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+/**
+ * This interface contains only the behaviour
+ * of the HelloWorld object.
+ * <p>
+ * It declares what Mixin to use as default implementation.
+ * </p>
+ */
+@Mixins( HelloWorldBehaviourMixin.class )
+public interface HelloWorldBehaviour
+{
+    String say();
+}
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldBehaviourConcern.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldBehaviourConcern.java
new file mode 100644
index 0000000..7ccd00e
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldBehaviourConcern.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial5;
+
+import org.apache.polygene.api.concern.ConcernOf;
+
+// START SNIPPET: solution
+
+/**
+ * This is a concern that modifies the mixin behaviour.
+ */
+public class HelloWorldBehaviourConcern
+    extends ConcernOf<HelloWorldBehaviour>
+    implements HelloWorldBehaviour
+{
+    @Override
+    public String say()
+    {
+        return "Simon says:" + next.say();
+    }
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldBehaviourMixin.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldBehaviourMixin.java
new file mode 100644
index 0000000..dc8f268
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldBehaviourMixin.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial5;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.injection.scope.This;
+
+// START SNIPPET: solution
+
+/**
+ * This is the implementation of the HelloWorld
+ * behaviour interface.
+ * <p>
+ * It uses a @This Dependency Injection
+ * annotation to access the state of the Composite. The field
+ * will be automatically injected when the Composite
+ * is instantiated. Injections of resources or references
+ * can be provided either to fields, constructor parameters or method parameters.
+ * </p>
+ */
+@Concerns( HelloWorldBehaviourConcern.class )
+public class HelloWorldBehaviourMixin
+    implements HelloWorldBehaviour
+{
+    @This
+    HelloWorldState state;
+
+    @Override
+    public String say()
+    {
+        return state.getPhrase() + " " + state.getName();
+    }
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldComposite.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldComposite.java
new file mode 100644
index 0000000..6ba4066
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldComposite.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial5;
+
+/**
+ * This Composite interface declares transitively
+ * all the Fragments of the HelloWorld composite.
+ * <p>
+ * What Mixins to use and what Assertions should
+ * apply to the methods can be found by exploring
+ * the interfaces extended by this Composite interface,
+ * and by looking at the declared Mixins.
+ * </p>
+ */
+public interface HelloWorldComposite
+    extends HelloWorld
+{
+}
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldState.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldState.java
new file mode 100644
index 0000000..0a7a5c9
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldState.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial5;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+/**
+ * This interface contains only the state
+ * of the HelloWorld object.
+ * <p>
+ * It declares what Mixin to use as default implementation.
+ * </p>
+ */
+@Mixins( HelloWorldStateMixin.class )
+public interface HelloWorldState
+{
+    void setPhrase( String phrase )
+        throws IllegalArgumentException;
+
+    String getPhrase();
+
+    void setName( String name )
+        throws IllegalArgumentException;
+
+    String getName();
+}
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldStateMixin.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldStateMixin.java
new file mode 100644
index 0000000..5881cec
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldStateMixin.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial5;
+
+/**
+ * This is the implementation of the HelloWorld
+ * state interface.
+ */
+public class HelloWorldStateMixin
+    implements HelloWorldState
+{
+    String phrase;
+    String name;
+
+    @Override
+    public String getPhrase()
+    {
+        return phrase;
+    }
+
+    @Override
+    public void setPhrase( String phrase )
+    {
+        this.phrase = phrase;
+    }
+
+    @Override
+    public String getName()
+    {
+        return name;
+    }
+
+    @Override
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+}
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/package.html b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/package.html
new file mode 100644
index 0000000..c0ca4c9
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial5/package.html
@@ -0,0 +1,63 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<body>
+<h1>Tutorial 5 - Constraints</h1>
+<p>
+In this tutorial we will look at how to use Constraints. When we pass parameters to
+methods in regular Java code the only restriction we can make is to denote a type.
+Any other constraints on the input value, such as whether the parameter is optional, integer ranges,
+string regular expressions, and so on, cannot be expressed, and so we have to put this into Javadoc, and
+then manually add these checks in the implementation class.
+</p>
+<p>
+In Polygene™ there is the option to use Constraints, which are further restrictions on the parameters.
+This is implemented by having an annotation that describes what the Constraint does, and then
+an implementation class that checks whether a specific value fulfills the Constraint or not.
+</p>
+<p>
+There are a number of pre-written constraints in Polygene™ which you can use. The null check of the original
+HelloWorld version is already handled by default since Polygene™ considers method parameters to be mandatory if not
+explicitly marked with the @Optional annotation. So, instead of doing that check we will add
+other checks that are useful to make, such as ensuring that the passed in string is not empty.
+</p>
+<p>
+The only thing you have to do is add the annotation @NotEmpty to the method parameters you want to
+constrain in this way. The annotation has a default implementation declared in it by using the @Constraints
+annotation. You can either just use this, which is the common case, or override it by declaring your
+own @Constraints annotation in the TransientComposite type.
+</p>
+<p>
+You can add as many Constraint annotations you want to a parameter. All of them will be checked whenever a method is
+called.
+</p>
+<p>
+Steps for this tutorial:
+</p>
+<ol>
+    <li>Add @NotEmpty to the state parameters.</li>
+</ol>
+<p><em>Note:</em></p>
+<p>
+    The previous steps had a dependency to the <code>org.apache.polygene.core.api</code> only. The constraints
+    you've used in this step, introduce a new dependency to the <code>org.apache.polygene.library.constraints</code>
+    library, where all the constraint related classes reside. So update your classpath settings
+    accordingly.
+</p>
+</body>
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorld.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorld.java
new file mode 100644
index 0000000..e6d2ce1
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorld.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial6;
+
+/**
+ * This interface aggregates the behaviour and state
+ * of the HelloWorld sub-interfaces. To a client
+ * this is the same as before though, since it only
+ * has to deal with this interface instead of the
+ * two sub-interfaces.
+ */
+public interface HelloWorld
+    extends HelloWorldBehaviour, HelloWorldState
+{
+}
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldBehaviour.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldBehaviour.java
new file mode 100644
index 0000000..86b3f96
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldBehaviour.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial6;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.mixin.Mixins;
+
+// START SNIPPET: solution
+
+/**
+ * This interface contains only the behaviour
+ * of the HelloWorld object.
+ * <p>
+ * It declares what Mixin to use as default implementation, and also the extra
+ * concern to be applied.
+ * </p>
+ */
+@Concerns( HelloWorldBehaviourConcern.class )
+@Mixins( HelloWorldBehaviourMixin.class )
+public interface HelloWorldBehaviour
+{
+    String say();
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldBehaviourConcern.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldBehaviourConcern.java
new file mode 100644
index 0000000..afeafd7
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldBehaviourConcern.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial6;
+
+import org.apache.polygene.api.concern.ConcernOf;
+
+// START SNIPPET: solution
+
+/**
+ * This Concern validates the parameters
+ * to the HelloWorldState interface.
+ */
+public class HelloWorldBehaviourConcern
+    extends ConcernOf<HelloWorldBehaviour>
+    implements HelloWorldBehaviour
+{
+    @Override
+    public String say()
+    {
+        return "Simon says:" + next.say();
+    }
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldBehaviourMixin.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldBehaviourMixin.java
new file mode 100644
index 0000000..ecfbdd9
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldBehaviourMixin.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial6;
+
+import org.apache.polygene.api.injection.scope.This;
+
+// START SNIPPET: solution
+
+/**
+ * This is the implementation of the HelloWorld
+ * behaviour interface.
+ * <p>
+ * It uses a @This DependencyModel Injection
+ * annotation to access the state of the Composite. The field
+ * will be automatically injected when the Composite
+ * is instantiated. Injections of resources or references
+ * can be provided either to fields, constructor parameters or method parameters.
+ * </p>
+ */
+public class HelloWorldBehaviourMixin
+    implements HelloWorldBehaviour
+{
+    @This
+    HelloWorldState state;
+
+    @Override
+    public String say()
+    {
+        return state.getPhrase() + " " + state.getName();
+    }
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldComposite.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldComposite.java
new file mode 100644
index 0000000..7a1ee5a
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldComposite.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial6;
+
+/**
+ * This Composite interface declares transitively
+ * all the Fragments of the HelloWorld composite.
+ * <p>
+ * What Mixins to use and what Concerns should
+ * apply to the methods can be found by exploring
+ * the interfaces extended by this Composite interface,
+ * and by looking at the declared @Mixins annotations.
+ * </p>
+ */
+public interface HelloWorldComposite
+    extends HelloWorld
+{
+}
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldState.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldState.java
new file mode 100644
index 0000000..89129fc
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldState.java
@@ -0,0 +1,48 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial6;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.library.constraints.annotation.NotEmpty;
+
+// START SNIPPET: solution
+
+/**
+ * This interface contains only the state
+ * of the HelloWorld object.
+ * <p>
+ * The parameters are declared as @NotEmpty, so the client cannot pass in empty strings
+ * as values.
+ * </p>
+ */
+@Mixins( HelloWorldStateMixin.class )
+public interface HelloWorldState
+{
+    void setPhrase( @NotEmpty String phrase )
+        throws IllegalArgumentException;
+
+    String getPhrase();
+
+    void setName( @NotEmpty String name )
+        throws IllegalArgumentException;
+
+    String getName();
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldStateMixin.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldStateMixin.java
new file mode 100644
index 0000000..4c80478
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldStateMixin.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial6;
+
+/**
+ * This is the implementation of the HelloWorld
+ * state interface.
+ */
+public class HelloWorldStateMixin
+    implements HelloWorldState
+{
+    String phrase;
+    String name;
+
+    @Override
+    public String getPhrase()
+    {
+        return phrase;
+    }
+
+    @Override
+    public void setPhrase( String phrase )
+    {
+        this.phrase = phrase;
+    }
+
+    @Override
+    public String getName()
+    {
+        return name;
+    }
+
+    @Override
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+}
\ No newline at end of file
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/package.html b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/package.html
new file mode 100644
index 0000000..66dc491
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial6/package.html
@@ -0,0 +1,58 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<body>
+<h1>Tutorial 6 - SideEffects</h1>
+<p>
+The current say() method has a Concern that modifies its value. What if we instead want
+the value to be intact, but log that value to System.out? That would be considered a side-effect
+of the say() method, and should hence not be done in a Concern. It would be better to implement
+this in a SideEffect. SideEffects are executed after the Mixin and all Concerns for a method are done,
+which means that the final result has been computed. A SideEffect can access this result value, and
+then use that for further computation, but it should not change the value or throw an exception.
+</p>
+<p>
+SideEffects can be either typed or generic, just like Concerns. In the typed case we are
+interested in specifying SideEffects for one or more particular methods, whereas in the generic
+case the SideEffect is not really relying on what method is being invoked. Both are useful
+in different scenarios.
+</p>
+<p>
+The easiest way to implement a typed SideEffect is to subclass the SideEffectOf class. This gives
+you access to the result of the real method invocation by using the "result" field, which has the same
+type as the interface of the method you want the code to be a side-effect of. Note that calling "result"
+does not actually do anything, it only returns the value (or throws the exception, if one was thrown
+from the original method) that has already been computed. Similarly, since the method is already done,
+you can return anything from the SideEffect method. The framework will simply throw it away, and also
+ignore any exceptions that you throw in your code.
+</p>
+<p>
+To declare that the SideEffect should be used you add the @SideEffects annotation to either the
+TransientComposite type, the Mixin type, or the Mixin implementation. Either works.
+</p>
+<p>
+Steps for this tutorial:
+</p>
+<ol>
+    <li>Create the SideEffect class that logs the result of say() to System.out.</li>
+    <li>Add a @SideEffects annotation with the SideEffect to the HelloWorldComposite interface.</li>
+    <li>Remove the Concern from the previous step.</li>
+    <li>Move the HelloWorldStateMixin from the HelloWorldState to the HelloWorldComposite interface.</li>
+</ol>
+</body>
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorld.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorld.java
new file mode 100644
index 0000000..c7ae399
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorld.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial7;
+
+/**
+ * This interface aggregates the behaviour and state
+ * of the HelloWorld sub-interfaces. To a client
+ * this is the same as before though, since it only
+ * has to deal with this interface instead of the
+ * two sub-interfaces.
+ */
+public interface HelloWorld
+    extends HelloWorldBehaviour, HelloWorldState
+{
+}
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldBehaviour.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldBehaviour.java
new file mode 100644
index 0000000..cf75ab8
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldBehaviour.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial7;
+
+// START SNIPPET: solution
+
+/**
+ * This interface contains only the behaviour
+ * of the HelloWorld object.
+ */
+public interface HelloWorldBehaviour
+{
+    String say();
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldBehaviourMixin.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldBehaviourMixin.java
new file mode 100644
index 0000000..95a8cf5
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldBehaviourMixin.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial7;
+
+import org.apache.polygene.api.injection.scope.This;
+
+/**
+ * This is the implementation of the HelloWorld
+ * behaviour interface.
+ * <p>
+ * It uses a @This DependencyModel Injection
+ * annotation to access the state of the Composite. The field
+ * will be automatically injected when the Composite
+ * is instantiated. Injections of resources or references
+ * can be provided either to fields, constructor parameters or method parameters.
+ * </p>
+ */
+public class HelloWorldBehaviourMixin
+    implements HelloWorldBehaviour
+{
+    @This
+    HelloWorldState state;
+
+    @Override
+    public String say()
+    {
+        return state.getPhrase() + " " + state.getName();
+    }
+}
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldBehaviourSideEffect.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldBehaviourSideEffect.java
new file mode 100644
index 0000000..8e5c237
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldBehaviourSideEffect.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial7;
+
+import org.apache.polygene.api.sideeffect.SideEffectOf;
+
+// START SNIPPET: solution
+
+/**
+ * As a side-effect of calling say, output the result.
+ */
+public class HelloWorldBehaviourSideEffect
+    extends SideEffectOf<HelloWorldBehaviour>
+    implements HelloWorldBehaviour
+{
+    @Override
+    public String say()
+    {
+        System.out.println( result.say() );
+        return null;
+    }
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldComposite.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldComposite.java
new file mode 100644
index 0000000..0366986
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldComposite.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial7;
+
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.sideeffect.SideEffects;
+
+// START SNIPPET: solution
+
+/**
+ * This Composite interface declares transitively
+ * all the Fragments of the HelloWorld composite.
+ * <p>
+ * It declares that the HelloWorldBehaviourSideEffect should be applied.
+ * </p>
+ */
+@Mixins( { HelloWorldBehaviourMixin.class, HelloWorldStateMixin.class } )
+@SideEffects( HelloWorldBehaviourSideEffect.class )
+public interface HelloWorldComposite
+    extends HelloWorld
+{
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldState.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldState.java
new file mode 100644
index 0000000..3c0795c
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldState.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial7;
+
+import org.apache.polygene.library.constraints.annotation.NotEmpty;
+
+// START SNIPPET: solution
+
+/**
+ * This interface contains only the state
+ * of the HelloWorld object.
+ * <p>
+ * The parameters are declared as @NotEmpty, so the client cannot pass in empty strings
+ * as values.
+ * </p>
+ */
+public interface HelloWorldState
+{
+    void setPhrase( @NotEmpty String phrase )
+        throws IllegalArgumentException;
+
+    String getPhrase();
+
+    void setName( @NotEmpty String name )
+        throws IllegalArgumentException;
+
+    String getName();
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldStateMixin.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldStateMixin.java
new file mode 100644
index 0000000..5325708
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldStateMixin.java
@@ -0,0 +1,55 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial7;
+
+/**
+ * This is the implementation of the HelloWorld
+ * state interface.
+ */
+public class HelloWorldStateMixin
+    implements HelloWorldState
+{
+    String phrase;
+    String name;
+
+    @Override
+    public String getPhrase()
+    {
+        return phrase;
+    }
+
+    @Override
+    public void setPhrase( String phrase )
+    {
+        this.phrase = phrase;
+    }
+
+    @Override
+    public String getName()
+    {
+        return name;
+    }
+
+    @Override
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+}
\ No newline at end of file
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/package.html b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/package.html
new file mode 100644
index 0000000..9096033
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial7/package.html
@@ -0,0 +1,72 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<body>
+<h1>Tutorial 7 - Properties</h1>
+<p>
+One of the goals of Apache Polygene™ is to give you domain modeling tools that allow you to more concisely use
+domain concepts in code. One of the things we do rather often is model Properties of objects as getters
+and setters. But this is a very weak model, and does not give you any access to metadata about the property,
+and also makes common tasks like UI binding non-trivial. There is also a lot of repetition of code, which
+is unnecessary. Using JavaBeans conventions one typically have to have code in five places for one property,
+whereas in Polygene™ the same thing can be achieved with one line of code.
+</p>
+<p>
+But lets start out easy. To declare a property you have to make a method in a mixin type that returns a value
+of the type Property, and which does not take any parameters. Here's a simple example:
+</p>
+<pre>
+    Property&lt;String&gt; name();
+</pre>
+<p>
+This declares a Property of type String with the name "name". The Property interface has methods "get" and "set"
+to access and mutate the value, respectively.
+</p>
+<p>
+For now you will be responsible for implementing these methods, but later on these will be handled automatically,
+thus reducing Properties to one-liners!
+</p>
+<p>
+In the Mixin implementation of the interface with the Property declaration you should have an injection
+of the Property, which is created for you by Polygene™. The injection can be done in a field like this:
+</p>
+<pre>
+    &#64;State Property&lt;String&gt; name;
+</pre>
+<p>
+The State dependency injection annotation means that Polygene™ will inject the Property for you. The field
+has the name "name", which matches the name in the interface, and therefore that Property is injected. You can
+then implement the method trivially by just returning the "name" field.
+</p>
+<p>
+Properties can have Constraints just like method parameters. Simply set them on the Property method instead,
+and they will be applied just as before when you call "set".
+</p>
+<p>
+Steps for this tutorial:
+</p>
+<ol>
+    <li>Remove JavaBeans properties from HelloWorldState.</li>
+    <li>Remove HelloWorld and add the HelloWorldState and HelloWorldBehavior to the HelloWorldComposite interface.</li>
+    <li>Remove the HelloWorldBehaviourSideEffect.</li>
+    <li>Update the behaviour mixin to use the state interface accordingly.</li>
+    <li>Add Property methods with the correct type and the @NotEmpty annotation.</li>
+    <li>Update the state mixin to inject and return the properties as described above.</li>
+</ol>
+</body>
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldBehaviour.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldBehaviour.java
new file mode 100644
index 0000000..509fc66
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldBehaviour.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial8;
+
+/**
+ * This interface contains only the behaviour
+ * of the HelloWorld object.
+ */
+public interface HelloWorldBehaviour
+{
+    String say();
+}
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldBehaviourMixin.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldBehaviourMixin.java
new file mode 100644
index 0000000..caafd71
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldBehaviourMixin.java
@@ -0,0 +1,45 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial8;
+
+import org.apache.polygene.api.injection.scope.This;
+
+// START SNIPPET: solution
+
+/**
+ * This is the implementation of the HelloWorld
+ * behaviour interface.
+ * <p>
+ * This version access the state using Polygene Properties.
+ * </p>
+ */
+public class HelloWorldBehaviourMixin
+    implements HelloWorldBehaviour
+{
+    @This
+    HelloWorldState state;
+
+    @Override
+    public String say()
+    {
+        return state.phrase().get() + " " + state.name().get();
+    }
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldComposite.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldComposite.java
new file mode 100644
index 0000000..fa58aa7
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldComposite.java
@@ -0,0 +1,35 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial8;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+// START SNIPPET: solution
+
+/**
+ * This Composite interface declares transitively
+ * all the Fragments of the HelloWorld composite.
+ */
+@Mixins( { HelloWorldBehaviourMixin.class, HelloWorldStateMixin.class } )
+public interface HelloWorldComposite
+    extends HelloWorldBehaviour, HelloWorldState
+{
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldState.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldState.java
new file mode 100644
index 0000000..b937e78
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldState.java
@@ -0,0 +1,43 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial8;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.constraints.annotation.NotEmpty;
+
+// START SNIPPET: solution
+
+/**
+ * This interface contains only the state
+ * of the HelloWorld object.
+ * <p>
+ * The state is now declared using Properties. The @NotEmpty annotation is applied to the
+ * method instead, and has the same meaning as before.
+ * </p>
+ */
+public interface HelloWorldState
+{
+    @NotEmpty
+    Property<String> phrase();
+
+    @NotEmpty
+    Property<String> name();
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldStateMixin.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldStateMixin.java
new file mode 100644
index 0000000..cf04d38
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldStateMixin.java
@@ -0,0 +1,51 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial8;
+
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.property.Property;
+
+// START SNIPPET: solution
+
+/**
+ * This is the implementation of the HelloWorld
+ * state interface.
+ */
+public class HelloWorldStateMixin
+    implements HelloWorldState
+{
+    @State
+    private Property<String> phrase;
+    @State
+    private Property<String> name;
+
+    @Override
+    public Property<String> phrase()
+    {
+        return phrase;
+    }
+
+    @Override
+    public Property<String> name()
+    {
+        return name;
+    }
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/package.html b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/package.html
new file mode 100644
index 0000000..2953cf6
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial8/package.html
@@ -0,0 +1,60 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<body>
+<h1>Tutorial 8 - Generic mixins</h1>
+<p>
+In this tutorial we will look at how to use generic Fragments. So far all Fragments, i.e.
+the Concerns, SideEffects, and Mixins, have directly implemented the domain interface. But sometimes it is
+useful to be able to provide a generic implementation of an interface. An example of this is
+the HelloWorldState interface. Since it only handles properties, and the old version used the JavaBean rules
+for naming getters and setters we could create a mixin that handles invocations of such methods
+automatically for us by storing the properties in a map and use the methods
+to look them up.
+</p>
+<p>
+Implementing a generic Fragment is done by creating a class that implements the interface
+java.lang.proxy.InvocationHandler. This has a single "invoke" method which is passed the
+object that was invoked (the TransientComposite in this case), the method, and the arguments. The
+Fragment is then allowed to implement the method any way it wants.
+</p>
+<p>
+Since interfaces with only Properties is such a common case Polygene™ already has a generic Mixin
+that implements the Properties management described above, but for the builtin Property type instead
+of the getter/setter variant. The class is aptly named PropertyMixin.
+</p>
+<p>
+While we could use it, for now we will implement it ourselves to get a feel for how generic Mixins work.
+</p>
+<p>
+Steps for this tutorial:
+</p>
+<ol>
+    <li>Remove the HelloWorldStateMixin</li>
+    <li>Add a GenericPropertyMixin, and have it implement InvocationHandler</li>
+    <li>Inject "@State StateHolder state" in the mixin. The StateHolder interface will give
+        you access to the Properties for the TransientComposite which Polygene™ manages for you
+    </li>
+    <li>On call to invoke(), delegate to the StateHolder interface to get the Property for the invoked method</li>
+    <li>Add an @AppliesTo annotation to the Mixin and implement the AppliesToFilter with a rule that
+        matches only methods that return Property values.
+    </li>
+    <li>Add the mixin to the TransientComposite.</li>
+</ol>
+</body>
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/GenericPropertyMixin.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/GenericPropertyMixin.java
new file mode 100644
index 0000000..ce8fa70
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/GenericPropertyMixin.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial9;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.AppliesToFilter;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.StateHolder;
+
+/**
+ * JAVADOC
+ */
+// START SNIPPET: solution
+@AppliesTo( { GenericPropertyMixin.PropertyFilter.class } )
+public class GenericPropertyMixin
+    implements InvocationHandler
+{
+    @State
+    private StateHolder state;
+
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        return state.propertyFor( method );
+    }
+
+    public static class PropertyFilter
+        implements AppliesToFilter
+    {
+        @Override
+        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> modifierClass )
+        {
+            return Property.class.isAssignableFrom( method.getReturnType() );
+        }
+    }
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/HelloWorldBehaviour.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/HelloWorldBehaviour.java
new file mode 100644
index 0000000..4be255f
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/HelloWorldBehaviour.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial9;
+
+/**
+ * This interface contains only the behaviour
+ * of the HelloWorld object.
+ */
+public interface HelloWorldBehaviour
+{
+    String say();
+}
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/HelloWorldBehaviourMixin.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/HelloWorldBehaviourMixin.java
new file mode 100644
index 0000000..07be4be
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/HelloWorldBehaviourMixin.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial9;
+
+import org.apache.polygene.api.injection.scope.This;
+
+// START SNIPPET: solution
+
+/**
+ * This is the implementation of the HelloWorld
+ * behaviour interface.
+ */
+public class HelloWorldBehaviourMixin
+    implements HelloWorldBehaviour
+{
+    @This
+    HelloWorldState state;
+
+    @Override
+    public String say()
+    {
+        return state.phrase().get() + " " + state.name().get();
+    }
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/HelloWorldComposite.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/HelloWorldComposite.java
new file mode 100644
index 0000000..7654316
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/HelloWorldComposite.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial9;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+// START SNIPPET: solution
+
+/**
+ * This Composite interface declares transitively
+ * all the Fragments of the HelloWorld composite.
+ * <p>
+ * All standard declarations have been moved to
+ * the StandardAbstractEntityComposite so we don't have to repeat
+ * them in all Composites.
+ * </p>
+ */
+@Mixins( { HelloWorldBehaviourMixin.class, GenericPropertyMixin.class } )
+public interface HelloWorldComposite
+    extends HelloWorldBehaviour, HelloWorldState
+{
+}
+// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/HelloWorldState.java b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/HelloWorldState.java
new file mode 100644
index 0000000..eca4ac1
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/HelloWorldState.java
@@ -0,0 +1,40 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial9;
+
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.constraints.annotation.NotEmpty;
+
+/**
+ * This interface contains only the state
+ * of the HelloWorld object.
+ * <p>
+ * The state is declared using Properties. The @NotEmpty annotation is applied to the
+ * method to check that the properties are not set to empty strings.
+ * </p>
+ */
+public interface HelloWorldState
+{
+    @NotEmpty
+    Property<String> phrase();
+
+    @NotEmpty
+    Property<String> name();
+}
diff --git a/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/package.html b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/package.html
new file mode 100644
index 0000000..34d78a2
--- /dev/null
+++ b/tutorials/composites/src/main/java/org/apache/polygene/tutorials/composites/tutorial9/package.html
@@ -0,0 +1,73 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<body>
+<h1>Tutorial 9 - Private and abstract mixins</h1>
+<p>
+Now we're going to turn around and see how we can reduce the code needed to implement the
+HelloWorld example. We will also look at how to hide the Properties from the client code,
+since Properties are often considered to be implementation details that should not be exposed
+to clients.
+</p>
+<p>
+The first thing we will do is remove the behaviour interface, and move the say() method
+to the TransientComposite type. This forces the mixin to implement the TransientComposite type, which would
+normally mean that it would have to implement all methods, including those found in the TransientComposite
+interface. However, since we are only really interested in implementing the say() method we
+will mark this by declaring that the Mixin "implements" the TransientComposite type, but is also "abstract".
+This, using pure Java semantics, makes it possible to avoid having to implement all methods. Polygene™
+will during the initialization phase detect that the Mixin only handles the say() method, and therefore
+only map it to that specific method. In order to instantiate the Mixin it will generate a subclass
+which implements the remaining methods in the TransientComposite type, as no-ops. These will never be called however,
+and is there purely for the purpose of being able to instantiate the Mixin. The Mixin is considered
+to be an Abstract Fragment.
+</p>
+<p>
+To hide the state from the client we need to use what is called Private Mixins. A Private Mixin is
+any mixin that is referenced by another Mixin by using the @This injection, but which is not included
+in the TransientComposite type. As long as there is a Mixin implementation declared for the interface specified
+by the @This injection it will work, since Polygene™ can know how to implement the interface. But since
+it is not extended by the TransientComposite type there is no way for a user of the TransientComposite to access it.
+That
+Mixin becomes an implementation detail. This can be used either for encapsulation purposes, or for referencing
+utility mixins that help the rest of the code implement some interface, but which itself should not be exposed.
+</p>
+<p>
+Since the state is now hidden the initialization of the TransientComposite is a bit more tricky. Instead of just
+instantiating it you have to create a TransientBuilder first, then set the state using .prototypeFor(), and then
+call newInstance(). This ensures that the state can be set during construction, but not at any later point, other
+than through publicly exposed methods.
+</p>
+<p>
+Steps for this tutorial:
+</p>
+<ol>
+    <li>Move the say() method into the TransientComposite interface.</li>
+    <li>Remove the behaviour interface.</li>
+    <li>Remove the HelloWorldBehaviourMixin, create a HelloWorldMixin and
+        let the HelloWorldMixin implement the TransientComposite directly.
+    </li>
+    <li>Mark the HelloWorldMixin as abstract and implement only the say() method.</li>
+    <li>Remove the HelloWorldState from the TransientComposite "extends" declaration.</li>
+    <li>Remove the GenericPropertyMixin. The Property methods will be implemented by the
+        standard PropertyMixin declared in the TransientComposite interface instead.
+    </li>
+</ol>
+</body>
+        
\ No newline at end of file
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/package.html b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/package.html
deleted file mode 100644
index eb0be63..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/package.html
+++ /dev/null
@@ -1,48 +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.
--->
-<html>
-<head>
-</head>
-<body>
-Description of TransientComposite tutorials.
-
-<h2>TransientComposite tutorials</h2>
-<p>
-Throughout this set of tutorials it will be shown how to create and work with TransientComposites, which
-is the basic element in Apache Zest™. We will refactor one HelloWorld class to take advantage of the various
-features in Zest™. These refactorings will make it easier to reuse parts of the class,
-and introduce new features without having to change existing code. We will also look
-at some of the existing classes, or Fragments, available in Zest™ that you can reuse
-so that you don't have to write everything yourself.
-</p>
-<p>
-Each tutorial in this series starts with the result from the previous tutorial, so you can
-always look at the next tutorial step for guidance on what to do. Here are the steps:
-</p>
-<ol>
-    <li>Interface refactoring</li>
-    <li>Creating a TransientComposite</li>
-    <li>Mixins</li>
-    <li>Concerns</li>
-    <li>Constraints</li>
-    <li>SideEffects</li>
-    <li>Properties</li>
-    <li>Generic mixins</li>
-    <li>Private and abstract mixins</li>
-</ol>
-</body>
-</html>
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial1/HelloWorld.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial1/HelloWorld.java
deleted file mode 100644
index 9e9aa7f..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial1/HelloWorld.java
+++ /dev/null
@@ -1,69 +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.qi4j.tutorials.composites.tutorial1;
-
-// START SNIPPET: initial
-
-/**
- * Initial HelloWorld implementation. Everything is mixed up
- * into one class, and no interface is used.
- */
-public class HelloWorld
-{
-    String phrase;
-    String name;
-
-    public String getPhrase()
-    {
-        return phrase;
-    }
-
-    public void setPhrase( String phrase )
-        throws IllegalArgumentException
-    {
-        if( phrase == null )
-        {
-            throw new IllegalArgumentException( "Phrase may not be null " );
-        }
-
-        this.phrase = phrase;
-    }
-
-    public String getName()
-    {
-        return name;
-    }
-
-    public void setName( String name )
-        throws IllegalArgumentException
-    {
-        if( name == null )
-        {
-            throw new IllegalArgumentException( "Name may not be null " );
-        }
-
-        this.name = name;
-    }
-
-    public String say()
-    {
-        return phrase + " " + name;
-    }
-}
-// END SNIPPET: initial
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial1/package.html b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial1/package.html
deleted file mode 100644
index f3465b8..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial1/package.html
+++ /dev/null
@@ -1,46 +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.
--->
-<body>
-<h1>Tutorial 1 - Interface refactoring</h1>
-<p>
-In this tutorial we start with a basic Java class, which when invoked will concatenate
-the two properties "phrase" and "name". If invoked with the properties set to "Hello"
-and "World" respectively it will hence return "Hello World".
-</p>
-<p>
-Zest™ relies heavily on the use of interfaces. This makes it possible for an object
-to externally implement a number of interfaces which internally is backed by a number
-of Mixins, some of which you may have written yourself, and some of which may have been
-reused. This also makes it easy to introduce Modifiers (aka "interceptors", aka "advice"),
-which are Fragments which execute before and/or after the method on the Mixin is invoked.
-</p>
-<p>
-The first task is therefore to refactor the code so that the method is implemented from an
-interface instead. We should then also separate the state into one interface and the behaviour
-into another. This will make things easier for us later when state and behaviour becomes
-implemented by separate Mixins.
-</p>
-<p>
-Steps for this tutorial:
-</p>
-<ol>
-    <li>Refactor the class into interface and implementation.</li>
-    <li>Refactor the interface so that it extends one interface called HelloWorldBehaviour with behaviour and one called
-        HelloWorldState with state (get/set methods).
-    </li>
-</ol>
-</body>
\ No newline at end of file
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial10/HelloWorldComposite.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial10/HelloWorldComposite.java
deleted file mode 100644
index d8e5416..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial10/HelloWorldComposite.java
+++ /dev/null
@@ -1,40 +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.qi4j.tutorials.composites.tutorial10;
-
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-
-// START SNIPPET: solution
-
-/**
- * This Composite interface declares transitively all the Fragments of the HelloWorld composite.
- * <p>
- * The Fragments are all abstract, so it's ok to
- * put the domain methods here. Otherwise the Fragments
- * would have to implement all methods, including those in Composite.
- * </p>
- */
-@Mixins( { HelloWorldMixin.class } )
-public interface HelloWorldComposite
-    extends TransientComposite
-{
-    String say();
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial10/HelloWorldMixin.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial10/HelloWorldMixin.java
deleted file mode 100644
index fc0003c..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial10/HelloWorldMixin.java
+++ /dev/null
@@ -1,42 +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.qi4j.tutorials.composites.tutorial10;
-
-import org.qi4j.api.injection.scope.This;
-
-// START SNIPPET: solution
-
-/**
- * This is the implementation of the say() method. The mixin
- * is abstract so it doesn't have to implement all methods
- * from the Composite interface.
- */
-public abstract class HelloWorldMixin
-    implements HelloWorldComposite
-{
-    @This
-    HelloWorldState state;
-
-    @Override
-    public String say()
-    {
-        return state.phrase().get() + " " + state.name().get();
-    }
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial10/HelloWorldState.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial10/HelloWorldState.java
deleted file mode 100644
index 7d2ba78..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial10/HelloWorldState.java
+++ /dev/null
@@ -1,38 +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.qi4j.tutorials.composites.tutorial10;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.library.constraints.annotation.NotEmpty;
-
-// START SNIPPET: solution
-
-/**
- * This interface contains only the state
- * of the HelloWorld object.
- */
-public interface HelloWorldState
-{
-    @NotEmpty
-    Property<String> phrase();
-
-    @NotEmpty
-    Property<String> name();
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/HelloWorld.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/HelloWorld.java
deleted file mode 100644
index 4970bf8..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/HelloWorld.java
+++ /dev/null
@@ -1,34 +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.qi4j.tutorials.composites.tutorial2;
-
-// START SNIPPET: solution
-
-/**
- * This interface aggregates the behaviour and state
- * of the HelloWorld sub-interfaces. To a client
- * this is the same as before though, since it only
- * has to deal with this interface instead of the
- * two sub-interfaces.
- */
-public interface HelloWorld
-    extends HelloWorldBehaviour, HelloWorldState
-{
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/HelloWorldBehaviour.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/HelloWorldBehaviour.java
deleted file mode 100644
index a9db8c4..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/HelloWorldBehaviour.java
+++ /dev/null
@@ -1,31 +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.qi4j.tutorials.composites.tutorial2;
-
-// START SNIPPET: solution
-
-/**
- * This interface contains only the behaviour
- * of the HelloWorld object.
- */
-public interface HelloWorldBehaviour
-{
-    String say();
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/HelloWorldMixin.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/HelloWorldMixin.java
deleted file mode 100644
index d6f463c..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/HelloWorldMixin.java
+++ /dev/null
@@ -1,75 +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.qi4j.tutorials.composites.tutorial2;
-
-// START SNIPPET: solution
-
-/**
- * This is the implementation of the HelloWorld
- * interface. The behaviour and state is mixed.
- */
-public class HelloWorldMixin
-    implements HelloWorld
-{
-    String phrase;
-    String name;
-
-    @Override
-    public String say()
-    {
-        return getPhrase() + " " + getName();
-    }
-
-    @Override
-    public void setPhrase( String phrase )
-        throws IllegalArgumentException
-    {
-        if( phrase == null )
-        {
-            throw new IllegalArgumentException( "Phrase may not be null" );
-        }
-
-        this.phrase = phrase;
-    }
-
-    @Override
-    public String getPhrase()
-    {
-        return phrase;
-    }
-
-    @Override
-    public void setName( String name )
-        throws IllegalArgumentException
-    {
-        if( name == null )
-        {
-            throw new IllegalArgumentException( "Name may not be null" );
-        }
-
-        this.name = name;
-    }
-
-    @Override
-    public String getName()
-    {
-        return name;
-    }
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/HelloWorldState.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/HelloWorldState.java
deleted file mode 100644
index 32789b8..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/HelloWorldState.java
+++ /dev/null
@@ -1,42 +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.qi4j.tutorials.composites.tutorial2;
-
-// START SNIPPET: solution
-
-/**
- * This interface contains only the state
- * of the HelloWorld object.
- * The exceptions will be thrown by Zest automatically if
- * null is sent in as values. The parameters would have to be declared
- * as @Optional if null is allowed.
- */
-public interface HelloWorldState
-{
-    void setPhrase( String phrase )
-        throws IllegalArgumentException;
-
-    String getPhrase();
-
-    void setName( String name )
-        throws IllegalArgumentException;
-
-    String getName();
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/package.html b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/package.html
deleted file mode 100644
index cded1fe..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial2/package.html
+++ /dev/null
@@ -1,41 +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.
--->
-<body>
-<h1>Tutorial 2 - Creating a Composite</h1>
-<p>
-In this tutorial we will create a TransientComposite interface that ties all pieces together.
-The TransientComposite interface is a regular Java interface which extends the interfaces you
-want to expose from your domain model, and which uses various annotations to declare
-what Fragments to include. Fragments include Mixins, Concerns, SideEffects and Constraints.
-In this tutorial we will only use Mixins. When a TransientComposite is instantiated at runtime
-the framework will inspect the interface to determine what the TransientComposite instance should
-look like in terms of used Fragments.
-</p>
-<p>
-In Zest™ all method parameters are considered mandatory unless marked as @Optional. Therefore you can
-remove the null checks in the Mixin. If a null value is passed in an exception will be thrown by Zest™.
-</p>
-<p>
-Steps for this tutorial:
-</p>
-<ol>
-    <li>Create an interface that extends the domain interface HelloWorld and
-        org.qi4j.api.composite.TransientComposite.
-    </li>
-    <li>Add a @Mixins annotation to it with the name of the Mixin as argument.</li>
-</ol>
-</body>
\ No newline at end of file
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/HelloWorld.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/HelloWorld.java
deleted file mode 100644
index 4c435ae..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/HelloWorld.java
+++ /dev/null
@@ -1,31 +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.qi4j.tutorials.composites.tutorial3;
-
-/**
- * This interface aggregates the behaviour and state
- * of the HelloWorld sub-interfaces. To a client
- * this is the same as before though, since it only
- * has to deal with this interface instead of the
- * two sub-interfaces.
- */
-public interface HelloWorld
-    extends HelloWorldBehaviour, HelloWorldState
-{
-}
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/HelloWorldBehaviour.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/HelloWorldBehaviour.java
deleted file mode 100644
index 7c3e58c..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/HelloWorldBehaviour.java
+++ /dev/null
@@ -1,28 +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.qi4j.tutorials.composites.tutorial3;
-
-/**
- * This interface contains only the behaviour
- * of the HelloWorld object.
- */
-public interface HelloWorldBehaviour
-{
-    String say();
-}
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/HelloWorldComposite.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/HelloWorldComposite.java
deleted file mode 100644
index 813a82a..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/HelloWorldComposite.java
+++ /dev/null
@@ -1,37 +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.qi4j.tutorials.composites.tutorial3;
-
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-
-// START SNIPPET: solution
-
-/**
- * This Composite interface declares all the Fragments of the HelloWorld composite.
- * <p>
- * Currently it only declares one Mixin.
- * </p>
- */
-@Mixins( HelloWorldMixin.class )
-public interface HelloWorldComposite
-    extends HelloWorld, TransientComposite
-{
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/HelloWorldMixin.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/HelloWorldMixin.java
deleted file mode 100644
index ad01382..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/HelloWorldMixin.java
+++ /dev/null
@@ -1,64 +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.qi4j.tutorials.composites.tutorial3;
-
-// START SNIPPET: solution
-
-/**
- * This is the implementation of the HelloWorld
- * interface. The behaviour and state is mixed. Since parameters
- * are mandatory as default in Zest there's no need to do null checks.
- */
-public class HelloWorldMixin
-    implements HelloWorld
-{
-    String phrase;
-    String name;
-
-    @Override
-    public String say()
-    {
-        return phrase + " " + name;
-    }
-
-    @Override
-    public String getPhrase()
-    {
-        return phrase;
-    }
-
-    @Override
-    public void setPhrase( String phrase )
-    {
-        this.phrase = phrase;
-    }
-
-    @Override
-    public String getName()
-    {
-        return name;
-    }
-
-    @Override
-    public void setName( String name )
-    {
-        this.name = name;
-    }
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/HelloWorldState.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/HelloWorldState.java
deleted file mode 100644
index 68a7e38..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/HelloWorldState.java
+++ /dev/null
@@ -1,39 +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.qi4j.tutorials.composites.tutorial3;
-
-/**
- * This interface contains only the state
- * of the HelloWorld Composite.
- * The exceptions will be thrown by Zest automatically if
- * null is sent in as values. The parameters would have to be declared
- * as @Optional if null is allowed.
- */
-public interface HelloWorldState
-{
-    void setPhrase( String phrase )
-        throws IllegalArgumentException;
-
-    String getPhrase();
-
-    void setName( String name )
-        throws IllegalArgumentException;
-
-    String getName();
-}
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/package.html b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/package.html
deleted file mode 100644
index 267142b..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial3/package.html
+++ /dev/null
@@ -1,38 +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.
--->
-<body>
-<h1>Tutorial 3 - Mixins</h1>
-<p>
-In this tutorial we refactor the Mixin from the previous steps into two, one which serves
-the behaviour interface and one which serves the state interface. This makes it possible to
-reuse the interfaces independently and also makes it easier to exchange one interface implementation
-with another. This also allows us to specify the new Mixins as default implementations of
-the interfaces by adding @Mixins annotations on them.
-</p>
-<p>
-Steps for this tutorial:
-</p>
-<ol>
-    <li>Refactor the Mixin into one which implement the behaviour interface and one which implements the state
-        interface. Use the @This injection annotation to allow the behaviour to access the state.
-    </li>
-    <li>Add a @Mixins annotations on the behaviour and state interfaces which declare the Mixins as default
-        implementations.
-    </li>
-    <li>Remove the @Mixins annotation from the TransientComposite interface.</li>
-</ol>
-</body>
\ No newline at end of file
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorld.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorld.java
deleted file mode 100644
index e9b2a64..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorld.java
+++ /dev/null
@@ -1,31 +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.qi4j.tutorials.composites.tutorial4;
-
-/**
- * This interface aggregates the behaviour and state
- * of the HelloWorld sub-interfaces. To a client
- * this is the same as before though, since it only
- * has to deal with this interface instead of the
- * two sub-interfaces.
- */
-public interface HelloWorld
-    extends HelloWorldBehaviour, HelloWorldState
-{
-}
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldBehaviour.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldBehaviour.java
deleted file mode 100644
index b72c4fc..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldBehaviour.java
+++ /dev/null
@@ -1,36 +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.qi4j.tutorials.composites.tutorial4;
-
-import org.qi4j.api.mixin.Mixins;
-
-// START SNIPPET: solution
-
-/**
- * This interface contains only the behaviour of the HelloWorld object.
- * <p>
- * It declares what Mixin to use as default implementation.
- * </p>
- */
-@Mixins( HelloWorldBehaviourMixin.class )
-public interface HelloWorldBehaviour
-{
-    String say();
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldBehaviourMixin.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldBehaviourMixin.java
deleted file mode 100644
index abeead2..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldBehaviourMixin.java
+++ /dev/null
@@ -1,47 +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.qi4j.tutorials.composites.tutorial4;
-
-import org.qi4j.api.injection.scope.This;
-
-// START SNIPPET: solution
-
-/**
- * This is the implementation of the HelloWorld behaviour interface.
- * <p>
- * It uses a @This Dependency Injection
- * annotation to access the state of the Composite. The field
- * will be automatically injected when the Composite
- * is instantiated. Injections of resources or references
- * can be provided either to fields, constructor parameters or method parameters.
- * </p>
- */
-public class HelloWorldBehaviourMixin
-    implements HelloWorldBehaviour
-{
-    @This
-    HelloWorldState state;
-
-    @Override
-    public String say()
-    {
-        return state.getPhrase() + " " + state.getName();
-    }
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldComposite.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldComposite.java
deleted file mode 100644
index e377adf..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldComposite.java
+++ /dev/null
@@ -1,39 +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.qi4j.tutorials.composites.tutorial4;
-
-import org.qi4j.api.composite.TransientComposite;
-
-// START SNIPPET: solution
-
-/**
- * This Composite interface declares all the Fragments
- * of the HelloWorld composite.
- * <p>
- * The Mixins annotation has been moved to the respective sub-interfaces.
- * The sub-interfaces therefore declare themselves what mixin implementation
- * is preferred. This interface could still have its own Mixins annotation
- * with overrides of those defaults however.
- * </p>
- */
-public interface HelloWorldComposite
-    extends HelloWorld, TransientComposite
-{
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldState.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldState.java
deleted file mode 100644
index d013ed1..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldState.java
+++ /dev/null
@@ -1,45 +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.qi4j.tutorials.composites.tutorial4;
-
-import org.qi4j.api.mixin.Mixins;
-
-// START SNIPPET: solution
-
-/**
- * This interface contains only the state
- * of the HelloWorld object.
- * The exceptions will be thrown by Zest automatically if
- * null is sent in as values. The parameters would have to be declared
- * as @Optional if null is allowed.
- */
-@Mixins( HelloWorldStateMixin.class )
-public interface HelloWorldState
-{
-    void setPhrase( String phrase )
-        throws IllegalArgumentException;
-
-    String getPhrase();
-
-    void setName( String name )
-        throws IllegalArgumentException;
-
-    String getName();
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldStateMixin.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldStateMixin.java
deleted file mode 100644
index da69b31..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldStateMixin.java
+++ /dev/null
@@ -1,57 +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.qi4j.tutorials.composites.tutorial4;
-
-// START SNIPPET: solution
-
-/**
- * This is the implementation of the HelloWorld
- * state interface.
- */
-public class HelloWorldStateMixin
-    implements HelloWorldState
-{
-    String phrase;
-    String name;
-
-    @Override
-    public String getPhrase()
-    {
-        return phrase;
-    }
-
-    @Override
-    public void setPhrase( String phrase )
-    {
-        this.phrase = phrase;
-    }
-
-    @Override
-    public String getName()
-    {
-        return name;
-    }
-
-    @Override
-    public void setName( String name )
-    {
-        this.name = name;
-    }
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/package.html b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/package.html
deleted file mode 100644
index 7a8f1c8..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial4/package.html
+++ /dev/null
@@ -1,56 +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.
--->
-<body>
-<h1>Tutorial 4 - Concerns</h1>
-<p>
-In this tutorial we refactor the mixin from the previous steps so that the result of the say() method
-is modified to be prefixed with "Simon says:". To do this we need to implement a Concern for
-the say() method. Concerns are a type of Modifier which modify the behaviour of
-the methods in Mixins. They do this by intercepting the invocation of the TransientComposite. This allows
-them to change the invocation parameters, return their own values or throw their own exceptions,
-and do other things which directly affect the invocation of the method.
-</p>
-<p>
-Concerns should not perform any side-effects, such as updating state in another TransientComposite, Mixin
-or similar. Any side-effects are done in SideEffects, which is another type of Modifier, which are
-allowed to perform side-effects but, in contrast to Concerns, cannot change the parameters or
-in any other way change the result of the invocation.
-</p>
-<p>
-Concerns are implemented in one of two ways: either create a class which directly implements
-the interface whose methods should be modified, or create a generic Modifier by implementing
-the InvocationHandler interface (or subclass GenericConcern which does this for you).
-Add an @ConcernFor dependency injection, as a field, constructor parameter or method parameter,
-which has the same type as the interface the Concern implements. When the TransientComposite is invoked
-the Concern will be called, allowing it to perform it's work. If the call should proceed, then
-invoke the method again on the injected object. The preferred way to do all of this is to subclass
-ConcernOf which does all of this for you.
-</p>
-<p>
-Concerns are applied by adding an @Concerns annotation on the TransientComposite, the domain interface,
-or the Mixin implementation. Any of these works, and where to put it is a matter of design choice.
-</p>
-<p>
-Steps for this tutorial:
-</p>
-<ol>
-    <li>Create a typed concern, implement the HelloWorldBehaviour and let it modify the result
-        of the base method by prefix the result with "Simon says:".
-    </li>
-    <li>Add an @Concerns annotation on the HelloWorldBehaviourMixin which references the Concern class.</li>
-</ol>
-</body>
\ No newline at end of file
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorld.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorld.java
deleted file mode 100644
index 2fcaa2c..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorld.java
+++ /dev/null
@@ -1,31 +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.qi4j.tutorials.composites.tutorial5;
-
-/**
- * This interface aggregates the behaviour and state
- * of the HelloWorld sub-interfaces. To a client
- * this is the same as before though, since it only
- * has to deal with this interface instead of the
- * two sub-interfaces.
- */
-public interface HelloWorld
-    extends HelloWorldBehaviour, HelloWorldState
-{
-}
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldBehaviour.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldBehaviour.java
deleted file mode 100644
index 7d88d1c..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldBehaviour.java
+++ /dev/null
@@ -1,34 +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.qi4j.tutorials.composites.tutorial5;
-
-import org.qi4j.api.mixin.Mixins;
-
-/**
- * This interface contains only the behaviour
- * of the HelloWorld object.
- * <p>
- * It declares what Mixin to use as default implementation.
- * </p>
- */
-@Mixins( HelloWorldBehaviourMixin.class )
-public interface HelloWorldBehaviour
-{
-    String say();
-}
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldBehaviourConcern.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldBehaviourConcern.java
deleted file mode 100644
index dd98fde..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldBehaviourConcern.java
+++ /dev/null
@@ -1,38 +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.qi4j.tutorials.composites.tutorial5;
-
-import org.qi4j.api.concern.ConcernOf;
-
-// START SNIPPET: solution
-
-/**
- * This is a concern that modifies the mixin behaviour.
- */
-public class HelloWorldBehaviourConcern
-    extends ConcernOf<HelloWorldBehaviour>
-    implements HelloWorldBehaviour
-{
-    @Override
-    public String say()
-    {
-        return "Simon says:" + next.say();
-    }
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldBehaviourMixin.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldBehaviourMixin.java
deleted file mode 100644
index 60e950d..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldBehaviourMixin.java
+++ /dev/null
@@ -1,50 +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.qi4j.tutorials.composites.tutorial5;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.injection.scope.This;
-
-// START SNIPPET: solution
-
-/**
- * This is the implementation of the HelloWorld
- * behaviour interface.
- * <p>
- * It uses a @This Dependency Injection
- * annotation to access the state of the Composite. The field
- * will be automatically injected when the Composite
- * is instantiated. Injections of resources or references
- * can be provided either to fields, constructor parameters or method parameters.
- * </p>
- */
-@Concerns( HelloWorldBehaviourConcern.class )
-public class HelloWorldBehaviourMixin
-    implements HelloWorldBehaviour
-{
-    @This
-    HelloWorldState state;
-
-    @Override
-    public String say()
-    {
-        return state.getPhrase() + " " + state.getName();
-    }
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldComposite.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldComposite.java
deleted file mode 100644
index 3df90d0..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldComposite.java
+++ /dev/null
@@ -1,36 +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.qi4j.tutorials.composites.tutorial5;
-
-import org.qi4j.api.composite.TransientComposite;
-
-/**
- * This Composite interface declares transitively
- * all the Fragments of the HelloWorld composite.
- * <p>
- * What Mixins to use and what Assertions should
- * apply to the methods can be found by exploring
- * the interfaces extended by this Composite interface,
- * and by looking at the declared Mixins.
- * </p>
- */
-public interface HelloWorldComposite
-    extends HelloWorld, TransientComposite
-{
-}
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldState.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldState.java
deleted file mode 100644
index b7031ff..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldState.java
+++ /dev/null
@@ -1,42 +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.qi4j.tutorials.composites.tutorial5;
-
-import org.qi4j.api.mixin.Mixins;
-
-/**
- * This interface contains only the state
- * of the HelloWorld object.
- * <p>
- * It declares what Mixin to use as default implementation.
- * </p>
- */
-@Mixins( HelloWorldStateMixin.class )
-public interface HelloWorldState
-{
-    void setPhrase( String phrase )
-        throws IllegalArgumentException;
-
-    String getPhrase();
-
-    void setName( String name )
-        throws IllegalArgumentException;
-
-    String getName();
-}
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldStateMixin.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldStateMixin.java
deleted file mode 100644
index 76787fb..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldStateMixin.java
+++ /dev/null
@@ -1,54 +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.qi4j.tutorials.composites.tutorial5;
-
-/**
- * This is the implementation of the HelloWorld
- * state interface.
- */
-public class HelloWorldStateMixin
-    implements HelloWorldState
-{
-    String phrase;
-    String name;
-
-    @Override
-    public String getPhrase()
-    {
-        return phrase;
-    }
-
-    @Override
-    public void setPhrase( String phrase )
-    {
-        this.phrase = phrase;
-    }
-
-    @Override
-    public String getName()
-    {
-        return name;
-    }
-
-    @Override
-    public void setName( String name )
-    {
-        this.name = name;
-    }
-}
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/package.html b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/package.html
deleted file mode 100644
index c5b40c8..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial5/package.html
+++ /dev/null
@@ -1,60 +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.
--->
-<body>
-<h1>Tutorial 5 - Constraints</h1>
-<p>
-In this tutorial we will look at how to use Constraints. When we pass parameters to
-methods in regular Java code the only restriction we can make is to denote a type.
-Any other constraints on the input value, such as whether the parameter is optional, integer ranges,
-string regular expressions, and so on, cannot be expressed, and so we have to put this into Javadoc, and
-then manually add these checks in the implementation class.
-</p>
-<p>
-In Zest™ there is the option to use Constraints, which are further restrictions on the parameters.
-This is implemented by having an annotation that describes what the Constraint does, and then
-an implementation class that checks whether a specific value fulfills the Constraint or not.
-</p>
-<p>
-There are a number of pre-written constraints in Zest™ which you can use. The null check of the original
-HelloWorld version is already handled by default since Zest™ considers method parameters to be mandatory if not
-explicitly marked with the @Optional annotation. So, instead of doing that check we will add
-other checks that are useful to make, such as ensuring that the passed in string is not empty.
-</p>
-<p>
-The only thing you have to do is add the annotation @NotEmpty to the method parameters you want to
-constrain in this way. The annotation has a default implementation declared in it by using the @Constraints
-annotation. You can either just use this, which is the common case, or override it by declaring your
-own @Constraints annotation in the TransientComposite type.
-</p>
-<p>
-You can add as many Constraint annotations you want to a parameter. All of them will be checked whenever a method is
-called.
-</p>
-<p>
-Steps for this tutorial:
-</p>
-<ol>
-    <li>Add @NotEmpty to the state parameters.</li>
-</ol>
-<p><em>Note:</em></p>
-<p>
-    The previous steps had a dependency to the <code>org.qi4j.core.api</code> only. The constraints
-    you've used in this step, introduce a new dependency to the <code>org.qi4j.library.constraints</code>
-    library, where all the constraint related classes reside. So update your classpath settings
-    accordingly.
-</p>
-</body>
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorld.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorld.java
deleted file mode 100644
index a08d071..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorld.java
+++ /dev/null
@@ -1,31 +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.qi4j.tutorials.composites.tutorial6;
-
-/**
- * This interface aggregates the behaviour and state
- * of the HelloWorld sub-interfaces. To a client
- * this is the same as before though, since it only
- * has to deal with this interface instead of the
- * two sub-interfaces.
- */
-public interface HelloWorld
-    extends HelloWorldBehaviour, HelloWorldState
-{
-}
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldBehaviour.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldBehaviour.java
deleted file mode 100644
index befdbf7..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldBehaviour.java
+++ /dev/null
@@ -1,40 +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.qi4j.tutorials.composites.tutorial6;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.mixin.Mixins;
-
-// START SNIPPET: solution
-
-/**
- * This interface contains only the behaviour
- * of the HelloWorld object.
- * <p>
- * It declares what Mixin to use as default implementation, and also the extra
- * concern to be applied.
- * </p>
- */
-@Concerns( HelloWorldBehaviourConcern.class )
-@Mixins( HelloWorldBehaviourMixin.class )
-public interface HelloWorldBehaviour
-{
-    String say();
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldBehaviourConcern.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldBehaviourConcern.java
deleted file mode 100644
index dffb5c1..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldBehaviourConcern.java
+++ /dev/null
@@ -1,39 +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.qi4j.tutorials.composites.tutorial6;
-
-import org.qi4j.api.concern.ConcernOf;
-
-// START SNIPPET: solution
-
-/**
- * This Concern validates the parameters
- * to the HelloWorldState interface.
- */
-public class HelloWorldBehaviourConcern
-    extends ConcernOf<HelloWorldBehaviour>
-    implements HelloWorldBehaviour
-{
-    @Override
-    public String say()
-    {
-        return "Simon says:" + next.say();
-    }
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldBehaviourMixin.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldBehaviourMixin.java
deleted file mode 100644
index 9e154d1..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldBehaviourMixin.java
+++ /dev/null
@@ -1,48 +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.qi4j.tutorials.composites.tutorial6;
-
-import org.qi4j.api.injection.scope.This;
-
-// START SNIPPET: solution
-
-/**
- * This is the implementation of the HelloWorld
- * behaviour interface.
- * <p>
- * It uses a @This DependencyModel Injection
- * annotation to access the state of the Composite. The field
- * will be automatically injected when the Composite
- * is instantiated. Injections of resources or references
- * can be provided either to fields, constructor parameters or method parameters.
- * </p>
- */
-public class HelloWorldBehaviourMixin
-    implements HelloWorldBehaviour
-{
-    @This
-    HelloWorldState state;
-
-    @Override
-    public String say()
-    {
-        return state.getPhrase() + " " + state.getName();
-    }
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldComposite.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldComposite.java
deleted file mode 100644
index 4fd031f..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldComposite.java
+++ /dev/null
@@ -1,36 +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.qi4j.tutorials.composites.tutorial6;
-
-import org.qi4j.api.composite.TransientComposite;
-
-/**
- * This Composite interface declares transitively
- * all the Fragments of the HelloWorld composite.
- * <p>
- * What Mixins to use and what Concerns should
- * apply to the methods can be found by exploring
- * the interfaces extended by this Composite interface,
- * and by looking at the declared @Mixins annotations.
- * </p>
- */
-public interface HelloWorldComposite
-    extends HelloWorld, TransientComposite
-{
-}
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldState.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldState.java
deleted file mode 100644
index 8290ad0..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldState.java
+++ /dev/null
@@ -1,47 +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.qi4j.tutorials.composites.tutorial6;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.library.constraints.annotation.NotEmpty;
-
-// START SNIPPET: solution
-
-/**
- * This interface contains only the state
- * of the HelloWorld object.
- * <p>
- * The parameters are declared as @NotEmpty, so the client cannot pass in empty strings
- * as values.
- * </p>
- */
-@Mixins( HelloWorldStateMixin.class )
-public interface HelloWorldState
-{
-    void setPhrase( @NotEmpty String phrase )
-        throws IllegalArgumentException;
-
-    String getPhrase();
-
-    void setName( @NotEmpty String name )
-        throws IllegalArgumentException;
-
-    String getName();
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldStateMixin.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldStateMixin.java
deleted file mode 100644
index c5ae4cf..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldStateMixin.java
+++ /dev/null
@@ -1,54 +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.qi4j.tutorials.composites.tutorial6;
-
-/**
- * This is the implementation of the HelloWorld
- * state interface.
- */
-public class HelloWorldStateMixin
-    implements HelloWorldState
-{
-    String phrase;
-    String name;
-
-    @Override
-    public String getPhrase()
-    {
-        return phrase;
-    }
-
-    @Override
-    public void setPhrase( String phrase )
-    {
-        this.phrase = phrase;
-    }
-
-    @Override
-    public String getName()
-    {
-        return name;
-    }
-
-    @Override
-    public void setName( String name )
-    {
-        this.name = name;
-    }
-}
\ No newline at end of file
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/package.html b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/package.html
deleted file mode 100644
index c2ba7b5..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial6/package.html
+++ /dev/null
@@ -1,55 +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.
--->
-<body>
-<h1>Tutorial 6 - SideEffects</h1>
-<p>
-The current say() method has a Concern that modifies its value. What if we instead want
-the value to be intact, but log that value to System.out? That would be considered a side-effect
-of the say() method, and should hence not be done in a Concern. It would be better to implement
-this in a SideEffect. SideEffects are executed after the Mixin and all Concerns for a method are done,
-which means that the final result has been computed. A SideEffect can access this result value, and
-then use that for further computation, but it should not change the value or throw an exception.
-</p>
-<p>
-SideEffects can be either typed or generic, just like Concerns. In the typed case we are
-interested in specifying SideEffects for one or more particular methods, whereas in the generic
-case the SideEffect is not really relying on what method is being invoked. Both are useful
-in different scenarios.
-</p>
-<p>
-The easiest way to implement a typed SideEffect is to subclass the SideEffectOf class. This gives
-you access to the result of the real method invocation by using the "result" field, which has the same
-type as the interface of the method you want the code to be a side-effect of. Note that calling "result"
-does not actually do anything, it only returns the value (or throws the exception, if one was thrown
-from the original method) that has already been computed. Similarly, since the method is already done,
-you can return anything from the SideEffect method. The framework will simply throw it away, and also
-ignore any exceptions that you throw in your code.
-</p>
-<p>
-To declare that the SideEffect should be used you add the @SideEffects annotation to either the
-TransientComposite type, the Mixin type, or the Mixin implementation. Either works.
-</p>
-<p>
-Steps for this tutorial:
-</p>
-<ol>
-    <li>Create the SideEffect class that logs the result of say() to System.out.</li>
-    <li>Add a @SideEffects annotation with the SideEffect to the HelloWorldComposite interface.</li>
-    <li>Remove the Concern from the previous step.</li>
-    <li>Move the HelloWorldStateMixin from the HelloWorldState to the HelloWorldComposite interface.</li>
-</ol>
-</body>
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorld.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorld.java
deleted file mode 100644
index 75a6b77..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorld.java
+++ /dev/null
@@ -1,31 +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.qi4j.tutorials.composites.tutorial7;
-
-/**
- * This interface aggregates the behaviour and state
- * of the HelloWorld sub-interfaces. To a client
- * this is the same as before though, since it only
- * has to deal with this interface instead of the
- * two sub-interfaces.
- */
-public interface HelloWorld
-    extends HelloWorldBehaviour, HelloWorldState
-{
-}
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldBehaviour.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldBehaviour.java
deleted file mode 100644
index 34bde3e..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldBehaviour.java
+++ /dev/null
@@ -1,31 +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.qi4j.tutorials.composites.tutorial7;
-
-// START SNIPPET: solution
-
-/**
- * This interface contains only the behaviour
- * of the HelloWorld object.
- */
-public interface HelloWorldBehaviour
-{
-    String say();
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldBehaviourMixin.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldBehaviourMixin.java
deleted file mode 100644
index 31135f6..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldBehaviourMixin.java
+++ /dev/null
@@ -1,45 +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.qi4j.tutorials.composites.tutorial7;
-
-import org.qi4j.api.injection.scope.This;
-
-/**
- * This is the implementation of the HelloWorld
- * behaviour interface.
- * <p>
- * It uses a @This DependencyModel Injection
- * annotation to access the state of the Composite. The field
- * will be automatically injected when the Composite
- * is instantiated. Injections of resources or references
- * can be provided either to fields, constructor parameters or method parameters.
- * </p>
- */
-public class HelloWorldBehaviourMixin
-    implements HelloWorldBehaviour
-{
-    @This
-    HelloWorldState state;
-
-    @Override
-    public String say()
-    {
-        return state.getPhrase() + " " + state.getName();
-    }
-}
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldBehaviourSideEffect.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldBehaviourSideEffect.java
deleted file mode 100644
index 5b28c1f..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldBehaviourSideEffect.java
+++ /dev/null
@@ -1,39 +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.qi4j.tutorials.composites.tutorial7;
-
-import org.qi4j.api.sideeffect.SideEffectOf;
-
-// START SNIPPET: solution
-
-/**
- * As a side-effect of calling say, output the result.
- */
-public class HelloWorldBehaviourSideEffect
-    extends SideEffectOf<HelloWorldBehaviour>
-    implements HelloWorldBehaviour
-{
-    @Override
-    public String say()
-    {
-        System.out.println( result.say() );
-        return null;
-    }
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldComposite.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldComposite.java
deleted file mode 100644
index db3a009..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldComposite.java
+++ /dev/null
@@ -1,40 +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.qi4j.tutorials.composites.tutorial7;
-
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.sideeffect.SideEffects;
-
-// START SNIPPET: solution
-
-/**
- * This Composite interface declares transitively
- * all the Fragments of the HelloWorld composite.
- * <p>
- * It declares that the HelloWorldBehaviourSideEffect should be applied.
- * </p>
- */
-@Mixins( { HelloWorldBehaviourMixin.class, HelloWorldStateMixin.class } )
-@SideEffects( HelloWorldBehaviourSideEffect.class )
-public interface HelloWorldComposite
-    extends HelloWorld, TransientComposite
-{
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldState.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldState.java
deleted file mode 100644
index 2e30060..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldState.java
+++ /dev/null
@@ -1,45 +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.qi4j.tutorials.composites.tutorial7;
-
-import org.qi4j.library.constraints.annotation.NotEmpty;
-
-// START SNIPPET: solution
-
-/**
- * This interface contains only the state
- * of the HelloWorld object.
- * <p>
- * The parameters are declared as @NotEmpty, so the client cannot pass in empty strings
- * as values.
- * </p>
- */
-public interface HelloWorldState
-{
-    void setPhrase( @NotEmpty String phrase )
-        throws IllegalArgumentException;
-
-    String getPhrase();
-
-    void setName( @NotEmpty String name )
-        throws IllegalArgumentException;
-
-    String getName();
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldStateMixin.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldStateMixin.java
deleted file mode 100644
index 5c9089a..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldStateMixin.java
+++ /dev/null
@@ -1,54 +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.qi4j.tutorials.composites.tutorial7;
-
-/**
- * This is the implementation of the HelloWorld
- * state interface.
- */
-public class HelloWorldStateMixin
-    implements HelloWorldState
-{
-    String phrase;
-    String name;
-
-    @Override
-    public String getPhrase()
-    {
-        return phrase;
-    }
-
-    @Override
-    public void setPhrase( String phrase )
-    {
-        this.phrase = phrase;
-    }
-
-    @Override
-    public String getName()
-    {
-        return name;
-    }
-
-    @Override
-    public void setName( String name )
-    {
-        this.name = name;
-    }
-}
\ No newline at end of file
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/package.html b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/package.html
deleted file mode 100644
index 41156c1..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial7/package.html
+++ /dev/null
@@ -1,69 +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.
--->
-<body>
-<h1>Tutorial 7 - Properties</h1>
-<p>
-One of the goals of Apache Zest™ is to give you domain modeling tools that allow you to more concisely use
-domain concepts in code. One of the things we do rather often is model Properties of objects as getters
-and setters. But this is a very weak model, and does not give you any access to metadata about the property,
-and also makes common tasks like UI binding non-trivial. There is also a lot of repetition of code, which
-is unnecessary. Using JavaBeans conventions one typically have to have code in five places for one property,
-whereas in Zest™ the same thing can be achieved with one line of code.
-</p>
-<p>
-But lets start out easy. To declare a property you have to make a method in a mixin type that returns a value
-of the type Property, and which does not take any parameters. Here's a simple example:
-</p>
-<pre>
-    Property&lt;String&gt; name();
-</pre>
-<p>
-This declares a Property of type String with the name "name". The Property interface has methods "get" and "set"
-to access and mutate the value, respectively.
-</p>
-<p>
-For now you will be responsible for implementing these methods, but later on these will be handled automatically,
-thus reducing Properties to one-liners!
-</p>
-<p>
-In the Mixin implementation of the interface with the Property declaration you should have an injection
-of the Property, which is created for you by Zest™. The injection can be done in a field like this:
-</p>
-<pre>
-    &#64;State Property&lt;String&gt; name;
-</pre>
-<p>
-The State dependency injection annotation means that Zest™ will inject the Property for you. The field
-has the name "name", which matches the name in the interface, and therefore that Property is injected. You can
-then implement the method trivially by just returning the "name" field.
-</p>
-<p>
-Properties can have Constraints just like method parameters. Simply set them on the Property method instead,
-and they will be applied just as before when you call "set".
-</p>
-<p>
-Steps for this tutorial:
-</p>
-<ol>
-    <li>Remove JavaBeans properties from HelloWorldState.</li>
-    <li>Remove HelloWorld and add the HelloWorldState and HelloWorldBehavior to the HelloWorldComposite interface.</li>
-    <li>Remove the HelloWorldBehaviourSideEffect.</li>
-    <li>Update the behaviour mixin to use the state interface accordingly.</li>
-    <li>Add Property methods with the correct type and the @NotEmpty annotation.</li>
-    <li>Update the state mixin to inject and return the properties as described above.</li>
-</ol>
-</body>
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldBehaviour.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldBehaviour.java
deleted file mode 100644
index 0c7b1b1..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldBehaviour.java
+++ /dev/null
@@ -1,28 +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.qi4j.tutorials.composites.tutorial8;
-
-/**
- * This interface contains only the behaviour
- * of the HelloWorld object.
- */
-public interface HelloWorldBehaviour
-{
-    String say();
-}
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldBehaviourMixin.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldBehaviourMixin.java
deleted file mode 100644
index 5585bef..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldBehaviourMixin.java
+++ /dev/null
@@ -1,44 +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.qi4j.tutorials.composites.tutorial8;
-
-import org.qi4j.api.injection.scope.This;
-
-// START SNIPPET: solution
-
-/**
- * This is the implementation of the HelloWorld
- * behaviour interface.
- * <p>
- * This version access the state using Zest Properties.
- * </p>
- */
-public class HelloWorldBehaviourMixin
-    implements HelloWorldBehaviour
-{
-    @This
-    HelloWorldState state;
-
-    @Override
-    public String say()
-    {
-        return state.phrase().get() + " " + state.name().get();
-    }
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldComposite.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldComposite.java
deleted file mode 100644
index a6b1951..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldComposite.java
+++ /dev/null
@@ -1,35 +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.qi4j.tutorials.composites.tutorial8;
-
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-
-// START SNIPPET: solution
-
-/**
- * This Composite interface declares transitively
- * all the Fragments of the HelloWorld composite.
- */
-@Mixins( { HelloWorldBehaviourMixin.class, HelloWorldStateMixin.class } )
-public interface HelloWorldComposite
-    extends HelloWorldBehaviour, HelloWorldState, TransientComposite
-{
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldState.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldState.java
deleted file mode 100644
index 0979ecf..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldState.java
+++ /dev/null
@@ -1,42 +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.qi4j.tutorials.composites.tutorial8;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.library.constraints.annotation.NotEmpty;
-
-// START SNIPPET: solution
-
-/**
- * This interface contains only the state
- * of the HelloWorld object.
- * <p>
- * The state is now declared using Properties. The @NotEmpty annotation is applied to the
- * method instead, and has the same meaning as before.
- * </p>
- */
-public interface HelloWorldState
-{
-    @NotEmpty
-    Property<String> phrase();
-
-    @NotEmpty
-    Property<String> name();
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldStateMixin.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldStateMixin.java
deleted file mode 100644
index b40e8fa..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldStateMixin.java
+++ /dev/null
@@ -1,50 +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.qi4j.tutorials.composites.tutorial8;
-
-import org.qi4j.api.injection.scope.State;
-import org.qi4j.api.property.Property;
-
-// START SNIPPET: solution
-
-/**
- * This is the implementation of the HelloWorld
- * state interface.
- */
-public class HelloWorldStateMixin
-    implements HelloWorldState
-{
-    @State
-    private Property<String> phrase;
-    @State
-    private Property<String> name;
-
-    @Override
-    public Property<String> phrase()
-    {
-        return phrase;
-    }
-
-    @Override
-    public Property<String> name()
-    {
-        return name;
-    }
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/package.html b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/package.html
deleted file mode 100644
index c9a5781..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial8/package.html
+++ /dev/null
@@ -1,57 +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.
--->
-<body>
-<h1>Tutorial 8 - Generic mixins</h1>
-<p>
-In this tutorial we will look at how to use generic Fragments. So far all Fragments, i.e.
-the Concerns, SideEffects, and Mixins, have directly implemented the domain interface. But sometimes it is
-useful to be able to provide a generic implementation of an interface. An example of this is
-the HelloWorldState interface. Since it only handles properties, and the old version used the JavaBean rules
-for naming getters and setters we could create a mixin that handles invocations of such methods
-automatically for us by storing the properties in a map and use the methods
-to look them up.
-</p>
-<p>
-Implementing a generic Fragment is done by creating a class that implements the interface
-java.lang.proxy.InvocationHandler. This has a single "invoke" method which is passed the
-object that was invoked (the TransientComposite in this case), the method, and the arguments. The
-Fragment is then allowed to implement the method any way it wants.
-</p>
-<p>
-Since interfaces with only Properties is such a common case Zest™ already has a generic Mixin
-that implements the Properties management described above, but for the builtin Property type instead
-of the getter/setter variant. The class is aptly named PropertyMixin.
-</p>
-<p>
-While we could use it, for now we will implement it ourselves to get a feel for how generic Mixins work.
-</p>
-<p>
-Steps for this tutorial:
-</p>
-<ol>
-    <li>Remove the HelloWorldStateMixin</li>
-    <li>Add a GenericPropertyMixin, and have it implement InvocationHandler</li>
-    <li>Inject "@State StateHolder state" in the mixin. The StateHolder interface will give
-        you access to the Properties for the TransientComposite which Zest™ manages for you
-    </li>
-    <li>On call to invoke(), delegate to the StateHolder interface to get the Property for the invoked method</li>
-    <li>Add an @AppliesTo annotation to the Mixin and implement the AppliesToFilter with a rule that
-        matches only methods that return Property values.
-    </li>
-    <li>Add the mixin to the TransientComposite.</li>
-</ol>
-</body>
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/GenericPropertyMixin.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/GenericPropertyMixin.java
deleted file mode 100644
index 7c9fe9e..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/GenericPropertyMixin.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Oberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.tutorials.composites.tutorial9;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import org.qi4j.api.common.AppliesTo;
-import org.qi4j.api.common.AppliesToFilter;
-import org.qi4j.api.injection.scope.State;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.property.StateHolder;
-
-/**
- * JAVADOC
- */
-// START SNIPPET: solution
-@AppliesTo( { GenericPropertyMixin.PropertyFilter.class } )
-public class GenericPropertyMixin
-    implements InvocationHandler
-{
-    @State
-    private StateHolder state;
-
-    @Override
-    public Object invoke( Object proxy, Method method, Object[] args )
-        throws Throwable
-    {
-        return state.propertyFor( method );
-    }
-
-    public static class PropertyFilter
-        implements AppliesToFilter
-    {
-        @Override
-        public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> modifierClass )
-        {
-            return Property.class.isAssignableFrom( method.getReturnType() );
-        }
-    }
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldBehaviour.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldBehaviour.java
deleted file mode 100644
index bf82ff1..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldBehaviour.java
+++ /dev/null
@@ -1,28 +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.qi4j.tutorials.composites.tutorial9;
-
-/**
- * This interface contains only the behaviour
- * of the HelloWorld object.
- */
-public interface HelloWorldBehaviour
-{
-    String say();
-}
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldBehaviourMixin.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldBehaviourMixin.java
deleted file mode 100644
index d676bc6..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldBehaviourMixin.java
+++ /dev/null
@@ -1,41 +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.qi4j.tutorials.composites.tutorial9;
-
-import org.qi4j.api.injection.scope.This;
-
-// START SNIPPET: solution
-
-/**
- * This is the implementation of the HelloWorld
- * behaviour interface.
- */
-public class HelloWorldBehaviourMixin
-    implements HelloWorldBehaviour
-{
-    @This
-    HelloWorldState state;
-
-    @Override
-    public String say()
-    {
-        return state.phrase().get() + " " + state.name().get();
-    }
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldComposite.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldComposite.java
deleted file mode 100644
index 73587d2..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldComposite.java
+++ /dev/null
@@ -1,40 +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.qi4j.tutorials.composites.tutorial9;
-
-import org.qi4j.api.composite.TransientComposite;
-import org.qi4j.api.mixin.Mixins;
-
-// START SNIPPET: solution
-
-/**
- * This Composite interface declares transitively
- * all the Fragments of the HelloWorld composite.
- * <p>
- * All standard declarations have been moved to
- * the StandardAbstractEntityComposite so we don't have to repeat
- * them in all Composites.
- * </p>
- */
-@Mixins( { HelloWorldBehaviourMixin.class, GenericPropertyMixin.class } )
-public interface HelloWorldComposite
-    extends HelloWorldBehaviour, HelloWorldState, TransientComposite
-{
-}
-// END SNIPPET: solution
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldState.java b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldState.java
deleted file mode 100644
index e6fbd69..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldState.java
+++ /dev/null
@@ -1,39 +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.qi4j.tutorials.composites.tutorial9;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.library.constraints.annotation.NotEmpty;
-
-/**
- * This interface contains only the state
- * of the HelloWorld object.
- * <p>
- * The state is declared using Properties. The @NotEmpty annotation is applied to the
- * method to check that the properties are not set to empty strings.
- * </p>
- */
-public interface HelloWorldState
-{
-    @NotEmpty
-    Property<String> phrase();
-
-    @NotEmpty
-    Property<String> name();
-}
diff --git a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/package.html b/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/package.html
deleted file mode 100644
index 5ebed41..0000000
--- a/tutorials/composites/src/main/java/org/qi4j/tutorials/composites/tutorial9/package.html
+++ /dev/null
@@ -1,70 +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.
--->
-<body>
-<h1>Tutorial 9 - Private and abstract mixins</h1>
-<p>
-Now we're going to turn around and see how we can reduce the code needed to implement the
-HelloWorld example. We will also look at how to hide the Properties from the client code,
-since Properties are often considered to be implementation details that should not be exposed
-to clients.
-</p>
-<p>
-The first thing we will do is remove the behaviour interface, and move the say() method
-to the TransientComposite type. This forces the mixin to implement the TransientComposite type, which would
-normally mean that it would have to implement all methods, including those found in the TransientComposite
-interface. However, since we are only really interested in implementing the say() method we
-will mark this by declaring that the Mixin "implements" the TransientComposite type, but is also "abstract".
-This, using pure Java semantics, makes it possible to avoid having to implement all methods. Zest™
-will during the initialization phase detect that the Mixin only handles the say() method, and therefore
-only map it to that specific method. In order to instantiate the Mixin it will generate a subclass
-which implements the remaining methods in the TransientComposite type, as no-ops. These will never be called however,
-and is there purely for the purpose of being able to instantiate the Mixin. The Mixin is considered
-to be an Abstract Fragment.
-</p>
-<p>
-To hide the state from the client we need to use what is called Private Mixins. A Private Mixin is
-any mixin that is referenced by another Mixin by using the @This injection, but which is not included
-in the TransientComposite type. As long as there is a Mixin implementation declared for the interface specified
-by the @This injection it will work, since Zest™ can know how to implement the interface. But since
-it is not extended by the TransientComposite type there is no way for a user of the TransientComposite to access it.
-That
-Mixin becomes an implementation detail. This can be used either for encapsulation purposes, or for referencing
-utility mixins that help the rest of the code implement some interface, but which itself should not be exposed.
-</p>
-<p>
-Since the state is now hidden the initialization of the TransientComposite is a bit more tricky. Instead of just
-instantiating it you have to create a TransientBuilder first, then set the state using .prototypeFor(), and then
-call newInstance(). This ensures that the state can be set during construction, but not at any later point, other
-than through publicly exposed methods.
-</p>
-<p>
-Steps for this tutorial:
-</p>
-<ol>
-    <li>Move the say() method into the TransientComposite interface.</li>
-    <li>Remove the behaviour interface.</li>
-    <li>Remove the HelloWorldBehaviourMixin, create a HelloWorldMixin and
-        let the HelloWorldMixin implement the TransientComposite directly.
-    </li>
-    <li>Mark the HelloWorldMixin as abstract and implement only the say() method.</li>
-    <li>Remove the HelloWorldState from the TransientComposite "extends" declaration.</li>
-    <li>Remove the GenericPropertyMixin. The Property methods will be implemented by the
-        standard PropertyMixin declared in the TransientComposite interface instead.
-    </li>
-</ol>
-</body>
-        
\ No newline at end of file
diff --git a/tutorials/composites/src/main/javadoc/overview.html b/tutorials/composites/src/main/javadoc/overview.html
index 1b98252..8eb2213 100644
--- a/tutorials/composites/src/main/javadoc/overview.html
+++ b/tutorials/composites/src/main/javadoc/overview.html
@@ -1,35 +1,39 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
 <!--
-  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.
--->
+  ~  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.
+  ~
+  ~
+  -->
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
 <html>
 <head>
 </head>
 <body>
 Description of tutorials.
 
-<h2>Apache Zest™ tutorials</h2>
+<h2>Apache Polygene™ tutorials</h2>
 
 <h3>Composite tutorials</h3>
 <p>
 Throughout this set of tutorials it will be shown how to create and work with Composites, which
-is the basic element in Zest™. We will refactor one HelloWorld class to take advantage of the various
-features in Zest™. These refactorings will make it easier to reuse parts of the class,
+is the basic element in Polygene™. We will refactor one HelloWorld class to take advantage of the various
+features in Polygene™. These refactorings will make it easier to reuse parts of the class,
 and introduce new features without having to change existing code. We will also look
-at some of the existing classes, or Fragments, available in Zest™ that you can reuse
+at some of the existing classes, or Fragments, available in Polygene™ that you can reuse
 so that you don't have to write everything yourself.
 </p>
 <p>
@@ -38,7 +42,7 @@
 </p>
 <h2>Related Documentation</h2>
 <p>
-For more information on Zest™ see <a target="_blank" href="http://zest.apache.org">the website</a>.
+For more information on Polygene™ see <a target="_blank" href="http://polygene.apache.org">the website</a>.
 </p>
 </body>
 </html>
diff --git a/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial1/HelloWorldTest.java b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial1/HelloWorldTest.java
new file mode 100644
index 0000000..a685602
--- /dev/null
+++ b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial1/HelloWorldTest.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial1;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class HelloWorldTest
+{
+    HelloWorld helloWorld;
+
+    @Before
+    public void setUp()
+        throws Exception
+    {
+        helloWorld = new HelloWorld();
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
+    {
+        {
+            helloWorld.setPhrase( "Hello" );
+            helloWorld.setName( "World" );
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Hello World" ) );
+        }
+
+        {
+            helloWorld.setPhrase( "Hey" );
+            helloWorld.setName( "Universe" );
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Hey Universe" ) );
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
+    {
+        try
+        {
+            helloWorld.setPhrase( null );
+            fail( "Should not be allowed to set phrase to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
+    {
+        try
+        {
+            helloWorld.setName( null );
+            fail( "Should not be allowed to set name to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+}
\ No newline at end of file
diff --git a/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial10/HelloWorldTest.java b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial10/HelloWorldTest.java
new file mode 100644
index 0000000..4cc74e2
--- /dev/null
+++ b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial10/HelloWorldTest.java
@@ -0,0 +1,139 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial10;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class HelloWorldTest
+{
+    private SingletonAssembler assembly;
+
+    @Before
+    public void setUp()
+        throws Exception
+    {
+        assembly = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( HelloWorldComposite.class );
+            }
+        };
+    }
+
+    @Test
+    public void givenAssemblyWhenBuildInstanceAndSayThenReturnCorrectResult()
+    {
+        {
+            TransientBuilder<HelloWorldComposite> builder =
+                assembly.module().newTransientBuilder( HelloWorldComposite.class );
+            builder.prototypeFor( HelloWorldState.class ).phrase().set( "Hello" );
+            builder.prototypeFor( HelloWorldState.class ).name().set( "World" );
+            HelloWorldComposite helloWorld = builder.newInstance();
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Hello World" ) );
+        }
+
+        {
+            TransientBuilder<HelloWorldComposite> builder =
+                assembly.module().newTransientBuilder( HelloWorldComposite.class );
+            builder.prototypeFor( HelloWorldState.class ).phrase().set( "Hey" );
+            builder.prototypeFor( HelloWorldState.class ).name().set( "Universe" );
+            HelloWorldComposite helloWorld = builder.newInstance();
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Hey Universe" ) );
+        }
+    }
+
+    @Test
+    public void givenAssemblyWhenSetInvalidPhraseThenThrowException()
+    {
+        try
+        {
+            TransientBuilder<HelloWorldComposite> builder =
+                assembly.module().newTransientBuilder( HelloWorldComposite.class );
+            builder.prototypeFor( HelloWorldState.class ).phrase().set( null );
+            HelloWorldComposite helloWorld = builder.newInstance();
+
+            fail( "Should not be allowed to set phrase to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+
+        try
+        {
+            TransientBuilder<HelloWorldComposite> builder =
+                assembly.module().newTransientBuilder( HelloWorldComposite.class );
+            builder.prototypeFor( HelloWorldState.class ).phrase().set( "" );
+            HelloWorldComposite helloWorld = builder.newInstance();
+
+            fail( "Should not be allowed to set phrase to empty string" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+
+    @Test
+    public void givenAssemblyWhenSetInvalidNameThenThrowException()
+    {
+        try
+        {
+            TransientBuilder<HelloWorldComposite> builder =
+                assembly.module().newTransientBuilder( HelloWorldComposite.class );
+            builder.prototypeFor( HelloWorldState.class ).name().set( null );
+            HelloWorldComposite helloWorld = builder.newInstance();
+
+            fail( "Should not be allowed to set phrase to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+
+        try
+        {
+            TransientBuilder<HelloWorldComposite> builder =
+                assembly.module().newTransientBuilder( HelloWorldComposite.class );
+            builder.prototypeFor( HelloWorldState.class ).name().set( "" );
+            HelloWorldComposite helloWorld = builder.newInstance();
+
+            fail( "Should not be allowed to set phrase to empty string" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+}
\ No newline at end of file
diff --git a/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorldTest.java b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorldTest.java
new file mode 100644
index 0000000..02ce5c2
--- /dev/null
+++ b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial2/HelloWorldTest.java
@@ -0,0 +1,85 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial2;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class HelloWorldTest
+{
+    HelloWorld helloWorld;
+
+    @Before
+    public void setUp()
+        throws Exception
+    {
+        helloWorld = new HelloWorldMixin();
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
+    {
+        {
+            helloWorld.setPhrase( "Hello" );
+            helloWorld.setName( "World" );
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Hello World" ) );
+        }
+
+        {
+            helloWorld.setPhrase( "Hey" );
+            helloWorld.setName( "Universe" );
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Hey Universe" ) );
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
+    {
+        try
+        {
+            helloWorld.setPhrase( null );
+            fail( "Should not be allowed to set phrase to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
+    {
+        try
+        {
+            helloWorld.setName( null );
+            fail( "Should not be allowed to set name to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+}
diff --git a/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorldTest.java b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorldTest.java
new file mode 100644
index 0000000..acd4533
--- /dev/null
+++ b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial3/HelloWorldTest.java
@@ -0,0 +1,98 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial3;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class HelloWorldTest
+{
+    HelloWorld helloWorld;
+
+    @Before
+    public void setUp()
+        throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( HelloWorldComposite.class );
+            }
+        };
+
+        helloWorld = assembly.module().newTransient( HelloWorldComposite.class );
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
+    {
+        {
+            helloWorld.setPhrase( "Hello" );
+            helloWorld.setName( "World" );
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Hello World" ) );
+        }
+
+        {
+            helloWorld.setPhrase( "Hey" );
+            helloWorld.setName( "Universe" );
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Hey Universe" ) );
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
+    {
+        try
+        {
+            helloWorld.setPhrase( null );
+            fail( "Should not be allowed to set phrase to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
+    {
+        try
+        {
+            helloWorld.setName( null );
+            fail( "Should not be allowed to set name to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+}
diff --git a/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldTest.java b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldTest.java
new file mode 100644
index 0000000..3cf3bf2
--- /dev/null
+++ b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial4/HelloWorldTest.java
@@ -0,0 +1,97 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class HelloWorldTest
+{
+    HelloWorld helloWorld;
+
+    @Before
+    public void setUp()
+        throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( HelloWorldComposite.class );
+            }
+        };
+        helloWorld = assembly.module().newTransientBuilder( HelloWorldComposite.class ).newInstance();
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
+    {
+        {
+            helloWorld.setPhrase( "Hello" );
+            helloWorld.setName( "World" );
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Hello World" ) );
+        }
+
+        {
+            helloWorld.setPhrase( "Hey" );
+            helloWorld.setName( "Universe" );
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Hey Universe" ) );
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
+    {
+        try
+        {
+            helloWorld.setPhrase( null );
+            fail( "Should not be allowed to set phrase to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
+    {
+        try
+        {
+            helloWorld.setName( null );
+            fail( "Should not be allowed to set name to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+}
diff --git a/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldTest.java b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldTest.java
new file mode 100644
index 0000000..526f738
--- /dev/null
+++ b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial5/HelloWorldTest.java
@@ -0,0 +1,97 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial5;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class HelloWorldTest
+{
+    HelloWorld helloWorld;
+
+    @Before
+    public void setUp()
+        throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( HelloWorldComposite.class );
+            }
+        };
+        helloWorld = assembly.module().newTransientBuilder( HelloWorldComposite.class ).newInstance();
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
+    {
+        {
+            helloWorld.setPhrase( "Hello" );
+            helloWorld.setName( "World" );
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Simon says:Hello World" ) );
+        }
+
+        {
+            helloWorld.setPhrase( "Hey" );
+            helloWorld.setName( "Universe" );
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Simon says:Hey Universe" ) );
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
+    {
+        try
+        {
+            helloWorld.setPhrase( null );
+            fail( "Should not be allowed to set phrase to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
+    {
+        try
+        {
+            helloWorld.setName( null );
+            fail( "Should not be allowed to set name to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+}
diff --git a/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldTest.java b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldTest.java
new file mode 100644
index 0000000..0330bc6
--- /dev/null
+++ b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial6/HelloWorldTest.java
@@ -0,0 +1,117 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial6;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class HelloWorldTest
+{
+    HelloWorld helloWorld;
+
+    @Before
+    public void setUp()
+        throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( HelloWorldComposite.class );
+            }
+        };
+        helloWorld = assembly.module().newTransient(HelloWorldComposite.class );
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
+    {
+        {
+            helloWorld.setPhrase( "Hello" );
+            helloWorld.setName( "World" );
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Simon says:Hello World" ) );
+        }
+
+        {
+            helloWorld.setPhrase( "Hey" );
+            helloWorld.setName( "Universe" );
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Simon says:Hey Universe" ) );
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
+    {
+        try
+        {
+            helloWorld.setPhrase( null );
+            fail( "Should not be allowed to set phrase to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+
+        try
+        {
+            helloWorld.setPhrase( "" );
+            fail( "Should not be allowed to set phrase to empty string" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
+    {
+        try
+        {
+            helloWorld.setName( null );
+            fail( "Should not be allowed to set name to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+
+        try
+        {
+            helloWorld.setName( "" );
+            fail( "Should not be allowed to set name to empty string" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+}
diff --git a/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldTest.java b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldTest.java
new file mode 100644
index 0000000..7592313
--- /dev/null
+++ b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial7/HelloWorldTest.java
@@ -0,0 +1,117 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial7;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class HelloWorldTest
+{
+    HelloWorld helloWorld;
+
+    @Before
+    public void setUp()
+        throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( HelloWorldComposite.class );
+            }
+        };
+        helloWorld = assembly.module().newTransientBuilder( HelloWorldComposite.class ).newInstance();
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
+    {
+        {
+            helloWorld.setPhrase( "Hello" );
+            helloWorld.setName( "World" );
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Hello World" ) );
+        }
+
+        {
+            helloWorld.setPhrase( "Hey" );
+            helloWorld.setName( "Universe" );
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Hey Universe" ) );
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
+    {
+        try
+        {
+            helloWorld.setPhrase( null );
+            fail( "Should not be allowed to set phrase to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+
+        try
+        {
+            helloWorld.setPhrase( "" );
+            fail( "Should not be allowed to set phrase to empty string" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
+    {
+        try
+        {
+            helloWorld.setName( null );
+            fail( "Should not be allowed to set name to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+
+        try
+        {
+            helloWorld.setName( "" );
+            fail( "Should not be allowed to set name to empty string" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+}
diff --git a/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldTest.java b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldTest.java
new file mode 100644
index 0000000..e8a753b
--- /dev/null
+++ b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial8/HelloWorldTest.java
@@ -0,0 +1,116 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial8;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class HelloWorldTest
+{
+    HelloWorldComposite helloWorld;
+
+    @Before
+    public void setUp()
+        throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( HelloWorldComposite.class );
+            }
+        };
+        TransientBuilderFactory builderFactory = assembly.module();
+        TransientBuilder<HelloWorldComposite> builder = builderFactory.newTransientBuilder( HelloWorldComposite.class );
+        builder.prototype().name().set( "Hello" );
+        builder.prototype().phrase().set( "World" );
+        helloWorld = builder.newInstance();
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
+    {
+        {
+            helloWorld.phrase().set( "Hey" );
+            helloWorld.name().set( "Universe" );
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Hey Universe" ) );
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
+    {
+        try
+        {
+            helloWorld.phrase().set( null );
+            fail( "Should not be allowed to set phrase to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+
+        try
+        {
+            helloWorld.phrase().set( "" );
+            fail( "Should not be allowed to set phrase to empty string" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
+    {
+        try
+        {
+            helloWorld.name().set( null );
+            fail( "Should not be allowed to set name to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+
+        try
+        {
+            helloWorld.name().set( "" );
+            fail( "Should not be allowed to set name to empty string" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+}
diff --git a/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial9/HelloWorldTest.java b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial9/HelloWorldTest.java
new file mode 100644
index 0000000..37384f9
--- /dev/null
+++ b/tutorials/composites/src/test/java/org/apache/polygene/tutorials/composites/tutorial9/HelloWorldTest.java
@@ -0,0 +1,116 @@
+/*
+ *  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.polygene.tutorials.composites.tutorial9;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class HelloWorldTest
+{
+    HelloWorldComposite helloWorld;
+
+    @Before
+    public void setUp()
+        throws Exception
+    {
+        SingletonAssembler assembly = new SingletonAssembler()
+        {
+            @Override
+            public void assemble( ModuleAssembly module )
+                throws AssemblyException
+            {
+                module.transients( HelloWorldComposite.class );
+            }
+        };
+        TransientBuilderFactory builderFactory = assembly.module();
+        TransientBuilder<HelloWorldComposite> builder = builderFactory.newTransientBuilder( HelloWorldComposite.class );
+        builder.prototype().name().set( "Hello" );
+        builder.prototype().phrase().set( "World" );
+        helloWorld = builder.newInstance();
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
+    {
+        {
+            helloWorld.phrase().set( "Hey" );
+            helloWorld.name().set( "Universe" );
+            String result = helloWorld.say();
+            assertThat( result, equalTo( "Hey Universe" ) );
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
+    {
+        try
+        {
+            helloWorld.phrase().set( null );
+            fail( "Should not be allowed to set phrase to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+
+        try
+        {
+            helloWorld.phrase().set( "" );
+            fail( "Should not be allowed to set phrase to empty string" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+
+    @Test
+    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
+    {
+        try
+        {
+            helloWorld.name().set( null );
+            fail( "Should not be allowed to set name to null" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+
+        try
+        {
+            helloWorld.name().set( "" );
+            fail( "Should not be allowed to set name to empty string" );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // Ok
+        }
+    }
+}
diff --git a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial1/HelloWorldTest.java b/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial1/HelloWorldTest.java
deleted file mode 100644
index 7a3252e..0000000
--- a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial1/HelloWorldTest.java
+++ /dev/null
@@ -1,84 +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.qi4j.tutorials.composites.tutorial1;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-public class HelloWorldTest
-{
-    HelloWorld helloWorld;
-
-    @Before
-    public void setUp()
-        throws Exception
-    {
-        helloWorld = new HelloWorld();
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
-    {
-        {
-            helloWorld.setPhrase( "Hello" );
-            helloWorld.setName( "World" );
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Hello World" ) );
-        }
-
-        {
-            helloWorld.setPhrase( "Hey" );
-            helloWorld.setName( "Universe" );
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Hey Universe" ) );
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
-    {
-        try
-        {
-            helloWorld.setPhrase( null );
-            fail( "Should not be allowed to set phrase to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
-    {
-        try
-        {
-            helloWorld.setName( null );
-            fail( "Should not be allowed to set name to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-}
\ No newline at end of file
diff --git a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial10/HelloWorldTest.java b/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial10/HelloWorldTest.java
deleted file mode 100644
index 100b921..0000000
--- a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial10/HelloWorldTest.java
+++ /dev/null
@@ -1,138 +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.qi4j.tutorials.composites.tutorial10;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-public class HelloWorldTest
-{
-    private SingletonAssembler assembly;
-
-    @Before
-    public void setUp()
-        throws Exception
-    {
-        assembly = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( HelloWorldComposite.class );
-            }
-        };
-    }
-
-    @Test
-    public void givenAssemblyWhenBuildInstanceAndSayThenReturnCorrectResult()
-    {
-        {
-            TransientBuilder<HelloWorldComposite> builder =
-                assembly.module().newTransientBuilder( HelloWorldComposite.class );
-            builder.prototypeFor( HelloWorldState.class ).phrase().set( "Hello" );
-            builder.prototypeFor( HelloWorldState.class ).name().set( "World" );
-            HelloWorldComposite helloWorld = builder.newInstance();
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Hello World" ) );
-        }
-
-        {
-            TransientBuilder<HelloWorldComposite> builder =
-                assembly.module().newTransientBuilder( HelloWorldComposite.class );
-            builder.prototypeFor( HelloWorldState.class ).phrase().set( "Hey" );
-            builder.prototypeFor( HelloWorldState.class ).name().set( "Universe" );
-            HelloWorldComposite helloWorld = builder.newInstance();
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Hey Universe" ) );
-        }
-    }
-
-    @Test
-    public void givenAssemblyWhenSetInvalidPhraseThenThrowException()
-    {
-        try
-        {
-            TransientBuilder<HelloWorldComposite> builder =
-                assembly.module().newTransientBuilder( HelloWorldComposite.class );
-            builder.prototypeFor( HelloWorldState.class ).phrase().set( null );
-            HelloWorldComposite helloWorld = builder.newInstance();
-
-            fail( "Should not be allowed to set phrase to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-
-        try
-        {
-            TransientBuilder<HelloWorldComposite> builder =
-                assembly.module().newTransientBuilder( HelloWorldComposite.class );
-            builder.prototypeFor( HelloWorldState.class ).phrase().set( "" );
-            HelloWorldComposite helloWorld = builder.newInstance();
-
-            fail( "Should not be allowed to set phrase to empty string" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-
-    @Test
-    public void givenAssemblyWhenSetInvalidNameThenThrowException()
-    {
-        try
-        {
-            TransientBuilder<HelloWorldComposite> builder =
-                assembly.module().newTransientBuilder( HelloWorldComposite.class );
-            builder.prototypeFor( HelloWorldState.class ).name().set( null );
-            HelloWorldComposite helloWorld = builder.newInstance();
-
-            fail( "Should not be allowed to set phrase to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-
-        try
-        {
-            TransientBuilder<HelloWorldComposite> builder =
-                assembly.module().newTransientBuilder( HelloWorldComposite.class );
-            builder.prototypeFor( HelloWorldState.class ).name().set( "" );
-            HelloWorldComposite helloWorld = builder.newInstance();
-
-            fail( "Should not be allowed to set phrase to empty string" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-}
\ No newline at end of file
diff --git a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial2/HelloWorldTest.java b/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial2/HelloWorldTest.java
deleted file mode 100644
index 97bd4bf..0000000
--- a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial2/HelloWorldTest.java
+++ /dev/null
@@ -1,84 +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.qi4j.tutorials.composites.tutorial2;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-public class HelloWorldTest
-{
-    HelloWorld helloWorld;
-
-    @Before
-    public void setUp()
-        throws Exception
-    {
-        helloWorld = new HelloWorldMixin();
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
-    {
-        {
-            helloWorld.setPhrase( "Hello" );
-            helloWorld.setName( "World" );
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Hello World" ) );
-        }
-
-        {
-            helloWorld.setPhrase( "Hey" );
-            helloWorld.setName( "Universe" );
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Hey Universe" ) );
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
-    {
-        try
-        {
-            helloWorld.setPhrase( null );
-            fail( "Should not be allowed to set phrase to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
-    {
-        try
-        {
-            helloWorld.setName( null );
-            fail( "Should not be allowed to set name to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-}
diff --git a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial3/HelloWorldTest.java b/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial3/HelloWorldTest.java
deleted file mode 100644
index 74f9c00..0000000
--- a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial3/HelloWorldTest.java
+++ /dev/null
@@ -1,97 +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.qi4j.tutorials.composites.tutorial3;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-public class HelloWorldTest
-{
-    HelloWorld helloWorld;
-
-    @Before
-    public void setUp()
-        throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( HelloWorldComposite.class );
-            }
-        };
-
-        helloWorld = assembly.module().newTransient( HelloWorldComposite.class );
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
-    {
-        {
-            helloWorld.setPhrase( "Hello" );
-            helloWorld.setName( "World" );
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Hello World" ) );
-        }
-
-        {
-            helloWorld.setPhrase( "Hey" );
-            helloWorld.setName( "Universe" );
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Hey Universe" ) );
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
-    {
-        try
-        {
-            helloWorld.setPhrase( null );
-            fail( "Should not be allowed to set phrase to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
-    {
-        try
-        {
-            helloWorld.setName( null );
-            fail( "Should not be allowed to set name to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-}
diff --git a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldTest.java b/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldTest.java
deleted file mode 100644
index 100228c..0000000
--- a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial4/HelloWorldTest.java
+++ /dev/null
@@ -1,96 +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.qi4j.tutorials.composites.tutorial4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-public class HelloWorldTest
-{
-    HelloWorld helloWorld;
-
-    @Before
-    public void setUp()
-        throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( HelloWorldComposite.class );
-            }
-        };
-        helloWorld = assembly.module().newTransientBuilder( HelloWorldComposite.class ).newInstance();
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
-    {
-        {
-            helloWorld.setPhrase( "Hello" );
-            helloWorld.setName( "World" );
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Hello World" ) );
-        }
-
-        {
-            helloWorld.setPhrase( "Hey" );
-            helloWorld.setName( "Universe" );
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Hey Universe" ) );
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
-    {
-        try
-        {
-            helloWorld.setPhrase( null );
-            fail( "Should not be allowed to set phrase to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
-    {
-        try
-        {
-            helloWorld.setName( null );
-            fail( "Should not be allowed to set name to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-}
diff --git a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldTest.java b/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldTest.java
deleted file mode 100644
index e9786fc..0000000
--- a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial5/HelloWorldTest.java
+++ /dev/null
@@ -1,96 +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.qi4j.tutorials.composites.tutorial5;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-public class HelloWorldTest
-{
-    HelloWorld helloWorld;
-
-    @Before
-    public void setUp()
-        throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( HelloWorldComposite.class );
-            }
-        };
-        helloWorld = assembly.module().newTransientBuilder( HelloWorldComposite.class ).newInstance();
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
-    {
-        {
-            helloWorld.setPhrase( "Hello" );
-            helloWorld.setName( "World" );
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Simon says:Hello World" ) );
-        }
-
-        {
-            helloWorld.setPhrase( "Hey" );
-            helloWorld.setName( "Universe" );
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Simon says:Hey Universe" ) );
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
-    {
-        try
-        {
-            helloWorld.setPhrase( null );
-            fail( "Should not be allowed to set phrase to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
-    {
-        try
-        {
-            helloWorld.setName( null );
-            fail( "Should not be allowed to set name to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-}
diff --git a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldTest.java b/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldTest.java
deleted file mode 100644
index 8496a86..0000000
--- a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial6/HelloWorldTest.java
+++ /dev/null
@@ -1,116 +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.qi4j.tutorials.composites.tutorial6;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-public class HelloWorldTest
-{
-    HelloWorld helloWorld;
-
-    @Before
-    public void setUp()
-        throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( HelloWorldComposite.class );
-            }
-        };
-        helloWorld = assembly.module().newTransient(HelloWorldComposite.class );
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
-    {
-        {
-            helloWorld.setPhrase( "Hello" );
-            helloWorld.setName( "World" );
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Simon says:Hello World" ) );
-        }
-
-        {
-            helloWorld.setPhrase( "Hey" );
-            helloWorld.setName( "Universe" );
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Simon says:Hey Universe" ) );
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
-    {
-        try
-        {
-            helloWorld.setPhrase( null );
-            fail( "Should not be allowed to set phrase to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-
-        try
-        {
-            helloWorld.setPhrase( "" );
-            fail( "Should not be allowed to set phrase to empty string" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
-    {
-        try
-        {
-            helloWorld.setName( null );
-            fail( "Should not be allowed to set name to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-
-        try
-        {
-            helloWorld.setName( "" );
-            fail( "Should not be allowed to set name to empty string" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-}
diff --git a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldTest.java b/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldTest.java
deleted file mode 100644
index 785bc3e..0000000
--- a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial7/HelloWorldTest.java
+++ /dev/null
@@ -1,116 +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.qi4j.tutorials.composites.tutorial7;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-public class HelloWorldTest
-{
-    HelloWorld helloWorld;
-
-    @Before
-    public void setUp()
-        throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( HelloWorldComposite.class );
-            }
-        };
-        helloWorld = assembly.module().newTransientBuilder( HelloWorldComposite.class ).newInstance();
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
-    {
-        {
-            helloWorld.setPhrase( "Hello" );
-            helloWorld.setName( "World" );
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Hello World" ) );
-        }
-
-        {
-            helloWorld.setPhrase( "Hey" );
-            helloWorld.setName( "Universe" );
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Hey Universe" ) );
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
-    {
-        try
-        {
-            helloWorld.setPhrase( null );
-            fail( "Should not be allowed to set phrase to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-
-        try
-        {
-            helloWorld.setPhrase( "" );
-            fail( "Should not be allowed to set phrase to empty string" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
-    {
-        try
-        {
-            helloWorld.setName( null );
-            fail( "Should not be allowed to set name to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-
-        try
-        {
-            helloWorld.setName( "" );
-            fail( "Should not be allowed to set name to empty string" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-}
diff --git a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldTest.java b/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldTest.java
deleted file mode 100644
index 3eeff1a..0000000
--- a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial8/HelloWorldTest.java
+++ /dev/null
@@ -1,115 +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.qi4j.tutorials.composites.tutorial8;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientBuilderFactory;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-public class HelloWorldTest
-{
-    HelloWorldComposite helloWorld;
-
-    @Before
-    public void setUp()
-        throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( HelloWorldComposite.class );
-            }
-        };
-        TransientBuilderFactory builderFactory = assembly.module();
-        TransientBuilder<HelloWorldComposite> builder = builderFactory.newTransientBuilder( HelloWorldComposite.class );
-        builder.prototype().name().set( "Hello" );
-        builder.prototype().phrase().set( "World" );
-        helloWorld = builder.newInstance();
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
-    {
-        {
-            helloWorld.phrase().set( "Hey" );
-            helloWorld.name().set( "Universe" );
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Hey Universe" ) );
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
-    {
-        try
-        {
-            helloWorld.phrase().set( null );
-            fail( "Should not be allowed to set phrase to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-
-        try
-        {
-            helloWorld.phrase().set( "" );
-            fail( "Should not be allowed to set phrase to empty string" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
-    {
-        try
-        {
-            helloWorld.name().set( null );
-            fail( "Should not be allowed to set name to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-
-        try
-        {
-            helloWorld.name().set( "" );
-            fail( "Should not be allowed to set name to empty string" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-}
diff --git a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldTest.java b/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldTest.java
deleted file mode 100644
index a5aaf0f..0000000
--- a/tutorials/composites/src/test/java/org/qi4j/tutorials/composites/tutorial9/HelloWorldTest.java
+++ /dev/null
@@ -1,115 +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.qi4j.tutorials.composites.tutorial9;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.api.composite.TransientBuilderFactory;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-public class HelloWorldTest
-{
-    HelloWorldComposite helloWorld;
-
-    @Before
-    public void setUp()
-        throws Exception
-    {
-        SingletonAssembler assembly = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                module.transients( HelloWorldComposite.class );
-            }
-        };
-        TransientBuilderFactory builderFactory = assembly.module();
-        TransientBuilder<HelloWorldComposite> builder = builderFactory.newTransientBuilder( HelloWorldComposite.class );
-        builder.prototype().name().set( "Hello" );
-        builder.prototype().phrase().set( "World" );
-        helloWorld = builder.newInstance();
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetPropertiesAndSayThenReturnCorrectResult()
-    {
-        {
-            helloWorld.phrase().set( "Hey" );
-            helloWorld.name().set( "Universe" );
-            String result = helloWorld.say();
-            assertThat( result, equalTo( "Hey Universe" ) );
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidPhraseThenThrowException()
-    {
-        try
-        {
-            helloWorld.phrase().set( null );
-            fail( "Should not be allowed to set phrase to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-
-        try
-        {
-            helloWorld.phrase().set( "" );
-            fail( "Should not be allowed to set phrase to empty string" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-
-    @Test
-    public void givenHelloWorldWhenSetInvalidNameThenThrowException()
-    {
-        try
-        {
-            helloWorld.name().set( null );
-            fail( "Should not be allowed to set name to null" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-
-        try
-        {
-            helloWorld.name().set( "" );
-            fail( "Should not be allowed to set name to empty string" );
-        }
-        catch( IllegalArgumentException e )
-        {
-            // Ok
-        }
-    }
-}
diff --git a/tutorials/hello/build.gradle b/tutorials/hello/build.gradle
index 2547c08..579836f 100644
--- a/tutorials/hello/build.gradle
+++ b/tutorials/hello/build.gradle
@@ -1,29 +1,36 @@
 /*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
+ *  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
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
+ *       http://www.apache.org/licenses/LICENSE-2.0
  *
- *     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.
  *
- * 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.
+ *
  */
 
-description = "Basic tutorial on how to covert a simple 'Hello World' application to Apache Zest™, using more and more features for each step."
+apply plugin: 'polygene-tutorial'
 
-jar { manifest { name = "Apache Zest™ Tutorial - Composites" }}
+description = "Basic tutorial on how to covert a simple 'Hello World' application to Apache Polygene™, using more and more features for each step."
+
+jar { manifest { name = "Apache Polygene™ Tutorial - Composites" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile(project(":org.qi4j.libraries:org.qi4j.library.constraints"))
+  implementation polygene.core.bootstrap
+  implementation polygene.library( 'constraints' )
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
+  runtimeOnly polygene.core.runtime
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/tutorials/hello/src/main/java/org/apache/polygene/tutorials/hello/Hello.java b/tutorials/hello/src/main/java/org/apache/polygene/tutorials/hello/Hello.java
new file mode 100644
index 0000000..f0fd7e4
--- /dev/null
+++ b/tutorials/hello/src/main/java/org/apache/polygene/tutorials/hello/Hello.java
@@ -0,0 +1,69 @@
+/*
+ *  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.polygene.tutorials.hello;
+
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.library.constraints.annotation.NotEmpty;
+
+// START SNIPPET: body
+
+/**
+ * This Composite interface declares a simple "Hello World" interface with a single say() method.
+ * What is being said is defined in the HelloWorldState interface, which is a private mixin.
+ */
+@Mixins( Hello.HelloWorldMixin.class )
+public interface Hello
+{
+    String say();
+
+    /**
+     * This is the implementation of the say() method.
+     */
+    class HelloWorldMixin
+        implements Hello
+    {
+        // @This reference the composite itself,
+        // and since HelloWorldState is not part of the public interface,
+        // it is a private mixin.
+        @This
+        private State state;
+
+        @Override
+        public String say()
+        {
+            return state.phrase().get() + " " + state.name().get();
+        }
+    }
+
+    /**
+     * This interface contains only the state of the HelloWorld object.
+     */
+    interface State
+    {
+        @NotEmpty
+        Property<String> phrase();
+
+        @NotEmpty
+        Property<String> name();
+    }
+}
+// END SNIPPET: body
diff --git a/tutorials/hello/src/main/java/org/qi4j/tutorials/hello/Hello.java b/tutorials/hello/src/main/java/org/qi4j/tutorials/hello/Hello.java
deleted file mode 100644
index 6a716a7..0000000
--- a/tutorials/hello/src/main/java/org/qi4j/tutorials/hello/Hello.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.tutorials.hello;
-
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.library.constraints.annotation.NotEmpty;
-
-// START SNIPPET: body
-
-/**
- * This Composite interface declares a simple "Hello World" interface with a single say() method. What is being
- * said is defined in the HelloWorldState interface, which is a private mixin.
- */
-@Mixins( { Hello.HelloWorldMixin.class } )
-public interface Hello
-{
-    String say();
-
-    /**
-     * This is the implementation of the say() method.
-     */
-    public abstract class HelloWorldMixin
-        implements Hello
-    {
-        // @This reference the composite itself, and since HelloWorldState is not part of the public interface,
-        // it is a private mixin.
-        @This
-        private State state;
-
-        @Override
-        public String say()
-        {
-            return state.phrase().get() + " " + state.name().get();
-        }
-    }
-
-    /**
-     * This interface contains only the state of the HelloWorld object.
-     */
-    public interface State
-    {
-        @NotEmpty
-        @UseDefaults
-        Property<String> phrase();
-
-        @NotEmpty
-        @UseDefaults
-        Property<String> name();
-    }
-}
-// END SNIPPET: body
diff --git a/tutorials/hello/src/test/java/org/apache/polygene/tutorials/hello/HelloTest.java b/tutorials/hello/src/test/java/org/apache/polygene/tutorials/hello/HelloTest.java
new file mode 100644
index 0000000..4a2453f
--- /dev/null
+++ b/tutorials/hello/src/test/java/org/apache/polygene/tutorials/hello/HelloTest.java
@@ -0,0 +1,58 @@
+/*
+ *  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.polygene.tutorials.hello;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+// START SNIPPET: step1
+public class HelloTest extends AbstractPolygeneTest
+{
+// END SNIPPET: step1
+
+    // START SNIPPET: step2
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+        module.values( Hello.class );
+    }
+    // END SNIPPET: step2
+
+    // START SNIPPET: step3
+    @Test
+    public void givenHelloValueInitializedToHelloWorldWhenCallingSayExpectHelloWorld()
+    {
+        ValueBuilder<Hello> builder = valueBuilderFactory.newValueBuilder( Hello.class );
+        builder.prototypeFor( Hello.State.class ).phrase().set( "Hello" );
+        builder.prototypeFor( Hello.State.class ).name().set( "World" );
+        Hello underTest = builder.newInstance();
+        String result = underTest.say();
+        assertThat( result, equalTo( "Hello World" ) );
+    }
+    // END SNIPPET: step3
+
+// START SNIPPET: step1
+}
+// END SNIPPET: step1
diff --git a/tutorials/hello/src/test/java/org/apache/polygene/tutorials/hello/HelloTest2.java b/tutorials/hello/src/test/java/org/apache/polygene/tutorials/hello/HelloTest2.java
new file mode 100644
index 0000000..5e05f34
--- /dev/null
+++ b/tutorials/hello/src/test/java/org/apache/polygene/tutorials/hello/HelloTest2.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.tutorials.hello;
+
+import org.junit.Test;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class HelloTest2 extends AbstractPolygeneTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.transients( Hello.class );
+    }
+
+    @Test
+    public void givenHelloValueInitializedToHelloWorldWhenCallingSayExpectHelloWorld()
+    {
+        TransientBuilder<Hello> builder = transientBuilderFactory.newTransientBuilder( Hello.class );
+        builder.prototypeFor( Hello.State.class ).phrase().set( "Hello" );
+        builder.prototypeFor( Hello.State.class ).name().set( "World" );
+        Hello underTest = builder.newInstance();
+        String result = underTest.say();
+        assertThat( result, equalTo( "Hello World" ) );
+    }
+}
diff --git a/tutorials/hello/src/test/java/org/apache/polygene/tutorials/hello/HelloTest3.java b/tutorials/hello/src/test/java/org/apache/polygene/tutorials/hello/HelloTest3.java
new file mode 100644
index 0000000..cbabcf3
--- /dev/null
+++ b/tutorials/hello/src/test/java/org/apache/polygene/tutorials/hello/HelloTest3.java
@@ -0,0 +1,50 @@
+/*
+ *  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.polygene.tutorials.hello;
+
+import org.junit.Test;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class HelloTest3 extends AbstractPolygeneTest
+{
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( Hello.class );
+        module.forMixin( Hello.State.class ).declareDefaults().phrase().set( "Hello" );
+        module.forMixin( Hello.State.class ).declareDefaults().name().set( "World" );
+    }
+
+    @Test
+    public void givenHelloValueInitializedToHelloWorldWhenCallingSayExpectHelloWorld()
+    {
+        ServiceReference<Hello> service = serviceFinder.findService( Hello.class );
+        String result = service.get().say();
+        assertThat( result, equalTo( "Hello World" ) );
+    }
+}
diff --git a/tutorials/hello/src/test/java/org/apache/polygene/tutorials/hello/HelloTest4.java b/tutorials/hello/src/test/java/org/apache/polygene/tutorials/hello/HelloTest4.java
new file mode 100644
index 0000000..1ff59eb
--- /dev/null
+++ b/tutorials/hello/src/test/java/org/apache/polygene/tutorials/hello/HelloTest4.java
@@ -0,0 +1,70 @@
+/*
+ *  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.polygene.tutorials.hello;
+
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.entitystore.memory.MemoryEntityStoreService;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class HelloTest4 extends AbstractPolygeneTest
+{
+
+    public static final Identity TEST_IDENTITY = new StringIdentity( "123" );
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( Hello.class );
+        module.services( MemoryEntityStoreService.class );
+    }
+
+    @Test
+    public void givenHelloValueInitializedToHelloWorldWhenCallingSayExpectHelloWorld()
+    {
+        UnitOfWork uow = unitOfWorkFactory.newUnitOfWork();
+        try
+        {
+            EntityBuilder<Hello> builder = uow.newEntityBuilder( Hello.class, TEST_IDENTITY);
+            builder.instanceFor( Hello.State.class ).phrase().set( "Hello" );
+            builder.instanceFor( Hello.State.class ).name().set( "World" );
+            builder.newInstance();
+            uow.complete();
+            uow = unitOfWorkFactory.newUnitOfWork();
+            Hello underTest = uow.get( Hello.class, TEST_IDENTITY);
+            String result = underTest.say();
+            uow.complete();
+            assertThat( result, equalTo( "Hello World" ) );
+        }
+        catch( Exception e )
+        {
+            uow.discard();
+        }
+    }
+}
diff --git a/tutorials/hello/src/test/java/org/qi4j/tutorials/hello/HelloTest.java b/tutorials/hello/src/test/java/org/qi4j/tutorials/hello/HelloTest.java
deleted file mode 100644
index f835213..0000000
--- a/tutorials/hello/src/test/java/org/qi4j/tutorials/hello/HelloTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.tutorials.hello;
-
-import org.junit.Test;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-// START SNIPPET: step1
-public class HelloTest extends AbstractQi4jTest
-{
-// END SNIPPET: step1
-
-    // START SNIPPET: step2
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.values( Hello.class );
-    }
-    // END SNIPPET: step2
-
-    // START SNIPPET: step3
-    @Test
-    public void givenHelloValueInitializedToHelloWorldWhenCallingSayExpectHelloWorld()
-    {
-        ValueBuilder<Hello> builder = module.newValueBuilder( Hello.class );
-        builder.prototypeFor( Hello.State.class ).phrase().set( "Hello" );
-        builder.prototypeFor( Hello.State.class ).name().set( "World" );
-        Hello underTest = builder.newInstance();
-        String result = underTest.say();
-        assertThat( result, equalTo( "Hello World" ) );
-    }
-    // END SNIPPET: step3
-
-// START SNIPPET: step1
-}
-// END SNIPPET: step1
diff --git a/tutorials/hello/src/test/java/org/qi4j/tutorials/hello/HelloTest2.java b/tutorials/hello/src/test/java/org/qi4j/tutorials/hello/HelloTest2.java
deleted file mode 100644
index 7d6e926..0000000
--- a/tutorials/hello/src/test/java/org/qi4j/tutorials/hello/HelloTest2.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.tutorials.hello;
-
-import org.junit.Test;
-import org.qi4j.api.composite.TransientBuilder;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-public class HelloTest2 extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.transients( Hello.class );
-    }
-
-    @Test
-    public void givenHelloValueInitializedToHelloWorldWhenCallingSayExpectHelloWorld()
-    {
-        TransientBuilder<Hello> builder = module.newTransientBuilder( Hello.class );
-        builder.prototypeFor( Hello.State.class ).phrase().set( "Hello" );
-        builder.prototypeFor( Hello.State.class ).name().set( "World" );
-        Hello underTest = builder.newInstance();
-        String result = underTest.say();
-        assertThat( result, equalTo( "Hello World" ) );
-    }
-}
diff --git a/tutorials/hello/src/test/java/org/qi4j/tutorials/hello/HelloTest3.java b/tutorials/hello/src/test/java/org/qi4j/tutorials/hello/HelloTest3.java
deleted file mode 100644
index fe6b105..0000000
--- a/tutorials/hello/src/test/java/org/qi4j/tutorials/hello/HelloTest3.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.tutorials.hello;
-
-import org.junit.Test;
-import org.qi4j.api.service.ServiceReference;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-public class HelloTest3 extends AbstractQi4jTest
-{
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( Hello.class );
-        module.forMixin( Hello.State.class ).declareDefaults().phrase().set( "Hello" );
-        module.forMixin( Hello.State.class ).declareDefaults().name().set( "World" );
-    }
-
-    @Test
-    public void givenHelloValueInitializedToHelloWorldWhenCallingSayExpectHelloWorld()
-    {
-        ServiceReference<Hello> service = module.findService( Hello.class );
-        String result = service.get().say();
-        assertThat( result, equalTo( "Hello World" ) );
-    }
-}
diff --git a/tutorials/hello/src/test/java/org/qi4j/tutorials/hello/HelloTest4.java b/tutorials/hello/src/test/java/org/qi4j/tutorials/hello/HelloTest4.java
deleted file mode 100644
index 04d1867..0000000
--- a/tutorials/hello/src/test/java/org/qi4j/tutorials/hello/HelloTest4.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.tutorials.hello;
-
-import org.junit.Test;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.entitystore.memory.MemoryEntityStoreService;
-import org.qi4j.test.AbstractQi4jTest;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.Assert.assertThat;
-
-public class HelloTest4 extends AbstractQi4jTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.entities( Hello.class );
-        module.services( MemoryEntityStoreService.class );
-    }
-
-    @Test
-    public void givenHelloValueInitializedToHelloWorldWhenCallingSayExpectHelloWorld()
-    {
-        UnitOfWork uow = module.newUnitOfWork();
-        try
-        {
-            EntityBuilder<Hello> builder = uow.newEntityBuilder( Hello.class, "123" );
-            builder.instanceFor( Hello.State.class ).phrase().set( "Hello" );
-            builder.instanceFor( Hello.State.class ).name().set( "World" );
-            builder.newInstance();
-            uow.complete();
-            uow = module.newUnitOfWork();
-            Hello underTest = uow.get( Hello.class, "123" );
-            String result = underTest.say();
-            uow.complete();
-            assertThat( result, equalTo( "Hello World" ) );
-        }
-        catch( Exception e )
-        {
-            uow.discard();
-        }
-    }
-}
diff --git a/tutorials/introduction/build.gradle b/tutorials/introduction/build.gradle
index 730b370..48a3248 100644
--- a/tutorials/introduction/build.gradle
+++ b/tutorials/introduction/build.gradle
@@ -1,31 +1,35 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "An Introduction to Apache Zest™ in its simplest form."
+apply plugin: 'polygene-tutorial'
 
-jar { manifest { name = "Apache Zest™ Tutorial - Introduction" }}
+description = "An Introduction to Apache Polygene™ in its simplest form."
+
+jar { manifest { name = "Apache Polygene™ Tutorial - Introduction" } }
 
 dependencies {
-    compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
+  implementation polygene.core.bootstrap
 
-    testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
+  runtimeOnly polygene.core.runtime
 
-    testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-    testRuntime(libraries.logback)
-}
\ No newline at end of file
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/tutorials/introduction/src/docs/background.txt b/tutorials/introduction/src/docs/background.txt
index 96fcb5f..cf226d9 100644
--- a/tutorials/introduction/src/docs/background.txt
+++ b/tutorials/introduction/src/docs/background.txt
@@ -19,22 +19,22 @@
 
 [[introduction-background,Background]]
 = Background =
-Zest™ is the first Composite Oriented Programming implementation leveraging the Java 5 platform, so that everything you
-know from Java 5 still applies. You can mix Zest™ with your ordinary Java code as much as you want. All your existing
-Java tools works just like before, and Zest™ does not introduce any new programming language, no special development
+Polygene™ is the first Composite Oriented Programming implementation leveraging the Java 5 platform, so that everything you
+know from Java 5 still applies. You can mix Polygene™ with your ordinary Java code as much as you want. All your existing
+Java tools works just like before, and Polygene™ does not introduce any new programming language, no special development
 tools needed and no XML is required.
 
 == Purpose ==
-Zest™ addresses the programming problems from the top-down, starting with the Domain Model and Business Rules needs,
+Polygene™ addresses the programming problems from the top-down, starting with the Domain Model and Business Rules needs,
 and let those requirements flow downwards in the software stack and dictate the requirements for underlying layers
 such as persistence, messaging, querying and more. This means that the business value developer is left to
 concentrate on the domain models and the actual application bringing the value, instead of creating massive amounts
 of glue code to tie underlying technologies together.
 
 == Problem Descriptions ==
-Zest™ didn't appear out of the blue, when the founders of the project had nothing better to do. It is the result of
+Polygene™ didn't appear out of the blue, when the founders of the project had nothing better to do. It is the result of
 observation of problems in real applications, and the experience from previous attempts to address or correct these
-problems, that has led to the Zest™ vision.
+problems, that has led to the Polygene™ vision.
 
 == Object Oriented Programming (OOP) ==
 How can OOP be a problem? We and others have observed that there is a fundamental flaw in the OOP model. In fact, we
@@ -117,4 +117,4 @@
 Composite Oriented Programming is heavily influenced by the book "Domain Driven Design" by Eric Evans. And we are
 trying to use his analysis of the problem to provide the mechanisms needed to get the job done quicker and more
 reliably. Mr Evans talks about Applications, Layers, Modules, Specifications, SideEffects and so forth, and all of
-these should be present in a Composite Oriented Programming implementation, and to a large extent it is in Zest™.
+these should be present in a Composite Oriented Programming implementation, and to a large extent it is in Polygene™.
diff --git a/tutorials/introduction/src/docs/highlights.txt b/tutorials/introduction/src/docs/highlights.txt
index 263096b..cee3d78 100644
--- a/tutorials/introduction/src/docs/highlights.txt
+++ b/tutorials/introduction/src/docs/highlights.txt
@@ -18,7 +18,7 @@
 ///////////////////////////////////////////////////////////////
 
 [[highlights,Highlights]]
-= Highligts =
+= Highlights =
 
 == Principles ==
 
@@ -83,11 +83,11 @@
 
 image:classes-are-dead.gif[]
 
-Zest™ is trying to address the flaws of OOP and introduce Composite Oriented Programming to the world, without
+Polygene™ is trying to address the flaws of OOP and introduce Composite Oriented Programming to the world, without
 introducing new programming languages, or awkward constructs. Heck, we don't even use any XML.
 
-Zest™ is not a framework. It is a new way to write code. Other people might create frameworks using Zest™, or create a
-framework optimized for Zest™, but here at Zest™ we concentrate to make Zest™ behave well in existing frameworks,
+Polygene™ is not a framework. It is a new way to write code. Other people might create frameworks using Polygene™, or create a
+framework optimized for Polygene™, but here at Polygene™ we concentrate to make Polygene™ behave well in existing frameworks,
 application servers, platforms and environments.
 
 You are to embark on a new journey. Enjoy!
diff --git a/tutorials/introduction/src/docs/polygene-cop.txt b/tutorials/introduction/src/docs/polygene-cop.txt
new file mode 100644
index 0000000..2de1ed9
--- /dev/null
+++ b/tutorials/introduction/src/docs/polygene-cop.txt
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////
+ * 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.
+///////////////////////////////////////////////////////////////
+
+[[polygene-cop,COP with Java and Polygene™]]
+= COP with Java and Polygene™ =
+
diff --git a/tutorials/introduction/src/docs/qi4j-cop.txt b/tutorials/introduction/src/docs/qi4j-cop.txt
deleted file mode 100644
index 0726ab8..0000000
--- a/tutorials/introduction/src/docs/qi4j-cop.txt
+++ /dev/null
@@ -1,22 +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.
-///////////////////////////////////////////////////////////////
-
-[[qi4j-cop,COP with Java and Zest™]]
-= COP with Java and Zest™ =
-
diff --git a/tutorials/introduction/src/docs/state-modeling.txt b/tutorials/introduction/src/docs/state-modeling.txt
index 0c5ec82..dd44066 100644
--- a/tutorials/introduction/src/docs/state-modeling.txt
+++ b/tutorials/introduction/src/docs/state-modeling.txt
@@ -18,11 +18,11 @@
 ///////////////////////////////////////////////////////////////
 
 [[state-modeling,State Modeling]]
-= Zest™ and state modeling =
+= Polygene™ and state modeling =
 
 (From Rickard Oberg's blog, http://www.jroller.com/rickard/entry/qi4j_and_state_modeling, 2009-02-19)
 
-In the Zest™ project we strive to being able to express our domain as directly as possible, with as little translation
+In the Polygene™ project we strive to being able to express our domain as directly as possible, with as little translation
 as possible between how we think about a domain and how it is actually coded.
 This then affects our entire view of how application frameworks should be constructed, and what we consider good and
 bad ways of implementing certain features.
@@ -36,7 +36,7 @@
 
 From a DDD perspective we want to talk about Entities and Values, Properties and Associations.
 If our code does not reflect this, then there is translation going on, and translation inevitably leads to information loss.
-In Zest™, where Composites and not Objects, are the basic construct, we have created specialized forms to model these
+In Polygene™, where Composites and not Objects, are the basic construct, we have created specialized forms to model these
 concepts more explicitly.
 We have EntityComposites and ValueComposites, each with different ways of creating them and managing them.
 Both EntityComposites and ValueComposites can then have Properties, as first-class objects, but Properties in
@@ -48,7 +48,7 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/src/main/java/org/qi4j/demo/intro/StateModelingDocs.java
+source=tutorials/introduction/src/main/java/org/apache/polygene/demo/intro/StateModelingDocs.java
 tag=intro1
 -----------
 
@@ -57,7 +57,7 @@
 To define a property you would have had to write a field and two accessors, and if you use interfaces then those
 accessors would have to be duplicated.
 
-The EntityComposite base interface also includes an identity property for you, as that's an intrinsic feature of
+The `HasIdentity` base interface also includes an identity property for you, as that's an intrinsic feature of
 Entities, so that's all taken care of.
 So if you speak about Entities in your domain discussions, each having Properties, then you can put that down in
 code pretty much as-is.
@@ -72,7 +72,7 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/src/main/java/org/qi4j/demo/intro/StateModelingDocs.java
+source=tutorials/introduction/src/main/java/org/apache/polygene/demo/intro/StateModelingDocs.java
 tag=roles
 -----------
 
@@ -93,7 +93,7 @@
 "@UseDefaults Property<List<String>> addresses();" would be initialized to an empty ArrayList, for example.
 
 In addition I have set surName() to be @Optional.
-In Zest™ we have defined all properties to be not-null as the default, and the same goes for all parameters in method
+In Polygene™ we have defined all properties to be not-null as the default, and the same goes for all parameters in method
 invocations.
 If you explicitly want to allow properties to be null, so that for example "Madonna" would be an acceptable name,
 then you can mark it as @Optional.
@@ -108,14 +108,14 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/src/main/java/org/qi4j/demo/intro/StateModelingDocs.java
+source=tutorials/introduction/src/main/java/org/apache/polygene/demo/intro/StateModelingDocs.java
 tag=values
 -----------
 
 Normally if you want a property to be immutable, meaning, you can set an initial value but not change it later, you
 would have to mark the Property as @Immutable.
-But since NameValue extends ValueComposite, which itself is marked with @Immutable, this is implicit for all subtypes
-of ValueComposite, and there's no way to "opt out" of it.
+But since NameValue will be assembled as a ValueComposite, which itself is marked with @Immutable, this is implicit
+for all ValueComposites, and there's no way to "opt out" of it.
 
 By introducing one more level in the state model you have created an easy way to access the name as a whole and hand
 it around the system, instead of as two separate properties.
@@ -134,7 +134,7 @@
 around your code, looking all soggy and unappetizing.
 
 What to do about this?
-One of the great inventions of Zest™, I believe, is the notion of private mixins.
+One of the great inventions of Polygene™, I believe, is the notion of private mixins.
 That we can have mixins in an object which are explicitly HIDDEN from usage outside of it.
 How can we use this for state modeling?
 What you'd want to do is to model the state of an Entity as a private mixin, which is hidden from clients, and then
@@ -142,7 +142,7 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/src/main/java/org/qi4j/demo/intro/StateModelingDocs.java
+source=tutorials/introduction/src/main/java/org/apache/polygene/demo/intro/StateModelingDocs.java
 tag=private
 -----------
 
@@ -164,18 +164,18 @@
 
 And so much more...
 
-The above is just a small taste of what you can do with state modeling in Zest™.
+The above is just a small taste of what you can do with state modeling in Polygene™.
 There is also support for associations and many-associations, the notion of aggregates, and a complete pluggable
 system for persistence and indexing/querying of data.
-To end with, here's a sample of how some other state modeling concepts can be expressed in Zest™:
+To end with, here's a sample of how some other state modeling concepts can be expressed in Polygene™:
 
 [snippet,java]
 -----------
-source=tutorials/introduction/src/main/java/org/qi4j/demo/intro/StateModelingDocs.java
+source=tutorials/introduction/src/main/java/org/apache/polygene/demo/intro/StateModelingDocs.java
 tag=more
 -----------
 
 I hope they are self-explanatory.
 
-My hope is that with Composite Oriented Programming and Zest™ we can come one step closer to being able to express our
+My hope is that with Composite Oriented Programming and Polygene™ we can come one step closer to being able to express our
 domain as clearly as possible in code.
diff --git a/tutorials/introduction/src/docs/what-is-composite-oriented-programming.txt b/tutorials/introduction/src/docs/what-is-composite-oriented-programming.txt
index f1493c3..24338d8 100644
--- a/tutorials/introduction/src/docs/what-is-composite-oriented-programming.txt
+++ b/tutorials/introduction/src/docs/what-is-composite-oriented-programming.txt
@@ -24,7 +24,7 @@
 Programming really is.
 
 The article uses C# and a "show by example" approach to explaining COP, and this shows clearly that COP is not
-Java specific, and although Zest™ was (to our knowledge) first to introduce the name, it applies across languages and
+Java specific, and although Polygene™ was (to our knowledge) first to introduce the name, it applies across languages and
 potentially deserves one or more languages on its own.
 
 
@@ -36,12 +36,19 @@
 
 We would like to thank Fredrik Kalseth for his explicit approval as well.
 
+Since then, this article went offline but can be found on the
+https://web.archive.org/web/20130414005509/http://iridescence.no/post/composite-oriented-programming.aspx[Internet Archive].
+
 
 == http://iridescence.no/post/composite-oriented-programming.aspx[Composite Oriented Programming] ==
 
-I've written a series of post on AOP lately (here, here and here), and in the last part I promised to tackle mixins
-and introductions in a future post. When I was doing my research for just that, I came cross a Java framework (just
-humor me :p) called Zest™ (that's 'chee for jay'), written by Swedish Richard Öberg, pioneering the idea of Composite
+I've written a series of post on AOP lately
+(https://web.archive.org/web/20090417052136/http://www.iridescence.no/post/Aspect-Oriented-Programming---A-Primer.aspx[here],
+https://web.archive.org/web/20091222150653/http://www.iridescence.no/post/Implementing-an-AOP-Framework-Part-1.aspx[here]
+and https://web.archive.org/web/20130417090819/http://www.iridescence.no/post/Implementing-an-AOP-Framework-Part-2.aspx[here]),
+and in the last part I promised to tackle mixins and introductions in a future post.
+When I was doing my research for just that, I came cross a Java framework (just
+humor me :p) called Apache Polygene™, written by Swedish Richard Öberg, pioneering the idea of Composite
 Oriented Programming, which instantly put a spell on me. Essentially, it takes the concepts from Aspect Oriented
 Programming to the extreme, and for the past week I’ve dug into it with a passion. This post is the first fruits of
 my labor.
@@ -49,7 +56,7 @@
 === OOP is Not Object Oriented! ===
 
 One of the things that Richard Öberg argues, is that OOP is not really object oriented at all, but rather class
-oriented. As the Zest™ website proclaims, "class is the first class citizen that objects are derived from. Not objects
+oriented. As the Polygene™ website proclaims, "class is the first class citizen that objects are derived from. Not objects
 being the first-class citizen to which one or many classes are assigned". Composite oriented programming (COP) then,
 tries to work around this limitation by building on a set of core principles; that behavior depends on context, that
 decoupling is a virtue, and that business rules matter more. For a short and abstract explanation of COP,
@@ -324,5 +331,5 @@
 posts. I’ve already implemented a prototype framework that supports the above examples, which builds on my
 http://www.iridescence.no/Posts/Implementing-an-AOP-Framework-Part-2.aspx[previously posted AOP framework], and I’ll
 post the source code for that soon. If you want to dig deeper right now (and don’t mind
-a bit of Java), then I suggest you head over to the Zest™ website and poke about there.
+a bit of Java), then I suggest you head over to the Polygene™ website and poke about there.
 http://rickardoberg.wordpress.com/[Richard Öbergs blog] also provides great insight.
diff --git a/tutorials/introduction/src/docs/whats-an-object.txt b/tutorials/introduction/src/docs/whats-an-object.txt
index 11bb20d..470e400 100644
--- a/tutorials/introduction/src/docs/whats-an-object.txt
+++ b/tutorials/introduction/src/docs/whats-an-object.txt
@@ -47,7 +47,7 @@
 
 This is the same in real life. I don't get to decide how I communicate with you. I have to use english, and I have to
 use email, and I have to send it to a specific mailing list. It is the algorithm of the interaction between us, the
-Zest™ dev mailing list, that has set these rules, not *I* as a participant in this interaction. The same should,
+Polygene™ dev mailing list, that has set these rules, not *I* as a participant in this interaction. The same should,
 obviously, be the case for objects.
 
 So, with the understanding that algorithms should define roles for collaborating objects, and objects should then
@@ -63,7 +63,7 @@
 causes a number of other problems, such as the "self schizophrenia" problem, whereby there is no way to tell where the
 object really is. There is no "this" pointer that has any relevant meaning.
 
-The Composite pattern, as implemented in COP and Zest™, gets around this by simply saying that the composite, as a
+The Composite pattern, as implemented in COP and Polygene™, gets around this by simply saying that the composite, as a
 whole, is an object. Tada, we now have a "this" pointer, and a coherent way to deal with the object graph as though it
 was a single object. We are now able to get back to the strengths of the procedural approach, which allows the
 implementer of the algorithm to define the roles needed for the algorithm. The roles can either be specific to an
@@ -77,7 +77,7 @@
 more algorithms than composites, therefore it has to be easy to ready algorithms, and only when necessary dive down into
 composite code.
 
-When talking about Composites as Objects in Zest™ it is most relevant to look at Entities, since these represent physical
+When talking about Composites as Objects in Polygene™ it is most relevant to look at Entities, since these represent physical
 objects in a model, rather than algorithms or services, or other non-instance-oriented things.
 
 If Entities should implement roles, via mixins, in order to interact with each other through algorithms, then the
@@ -90,7 +90,7 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/src/main/java/org/qi4j/demo/intro/WhatsAnObjectDocs.java
+source=tutorials/introduction/src/main/java/org/apache/polygene/demo/intro/WhatsAnObjectDocs.java
 tag=wo1
 -----------
 
@@ -102,7 +102,7 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/src/main/java/org/qi4j/demo/intro/WhatsAnObjectDocs.java
+source=tutorials/introduction/src/main/java/org/apache/polygene/demo/intro/WhatsAnObjectDocs.java
 tag=wo2
 -----------
 
@@ -114,7 +114,7 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/src/main/java/org/qi4j/demo/intro/WhatsAnObjectDocs.java
+source=tutorials/introduction/src/main/java/org/apache/polygene/demo/intro/WhatsAnObjectDocs.java
 tag=wo3
 -----------
 
@@ -122,7 +122,7 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/src/main/java/org/qi4j/demo/intro/WhatsAnObjectDocs.java
+source=tutorials/introduction/src/main/java/org/apache/polygene/demo/intro/WhatsAnObjectDocs.java
 tag=wo4
 -----------
 
@@ -134,7 +134,7 @@
 it easier for us to understand it the next time we see it being used in another algorithm.
 
 To summarize thus far, we have looked at why OOP so far has not worked out, why this is the case, and how COP deals
-with it, and how we can implement a better solution of Entities using Zest™. All is well!
+with it, and how we can implement a better solution of Entities using Polygene™. All is well!
 
 The next step is to start using these Entities in algorithms. Algorithms are usually stateless, or at least they don't
 have any state that survives the execution of the algorithm. There is input, some calculation, and then output. In
@@ -189,15 +189,15 @@
 roles. The implementations are also testable, and if the same mixin is used over and over for the implementation, then
 only one set of tests is needed for each role interface.
 
-To summarize we have in COP/Zest™ a way to get the best from procedural and object-oriented programming. As we have seen
+To summarize we have in COP/Polygene™ a way to get the best from procedural and object-oriented programming. As we have seen
 the functionality falls into three categories, the entities implementing objects, the services implementing
 interactions, and the user interface implementing the context. This also maps well to the ideas of ModelViewController,
 which in turn maps well to the new ideas from Mr Reenskaug (inventor of MVC) called DCI: Data-Context-Interaction. As a
-side-effect of this discussion we have therefore also seen how COP/Zest™ can be used to implement DCI, which is an
+side-effect of this discussion we have therefore also seen how COP/Polygene™ can be used to implement DCI, which is an
 important next step in understanding objects and their interactions, the fundamentals of which (I believe) are captured
 on this page.
 
 That's it. Well done if you've read this far :-)
 
-Comments and thoughts to qi4j-dev forum at Google Groups on this are highly appreciated. This is very very important topics,
-and crucial to understanding/explaining why COP/Zest™ is so great! :-)
+Comments and thoughts to dev@polygene.apache.org mailing list on this are highly appreciated. This is very very important
+topics, and crucial to understanding/explaining why COP/Polygene™ is so great! :-)
diff --git a/tutorials/introduction/src/main/java/org/apache/polygene/demo/intro/StateModelingDocs.java b/tutorials/introduction/src/main/java/org/apache/polygene/demo/intro/StateModelingDocs.java
new file mode 100644
index 0000000..ae8e7ee
--- /dev/null
+++ b/tutorials/introduction/src/main/java/org/apache/polygene/demo/intro/StateModelingDocs.java
@@ -0,0 +1,126 @@
+/*
+ *  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.polygene.demo.intro;
+
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.entity.Aggregated;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueComposite;
+
+public class StateModelingDocs
+{
+
+    // START SNIPPET: intro1
+    interface PersonEntity extends HasIdentity
+    {
+        Property<String> givenName();
+        Property<String> surName();
+    }
+    // END SNIPPET: intro1
+
+
+
+
+    static class Roles {
+
+        // START SNIPPET: roles
+        interface Nameable
+        {
+            @UseDefaults Property<String> givenName();
+            @UseDefaults @Optional Property<String> surName();
+        }
+
+        interface PersonEntity extends Nameable, HasIdentity {}
+        // END SNIPPET: roles
+    }
+
+    static class Values {
+
+        // START SNIPPET: values
+        interface NameValue
+        {
+            @UseDefaults Property<String> givenName();
+            @UseDefaults @Optional Property<String> surName();
+        }
+
+        interface Nameable
+        {
+            Property<NameValue> name();
+        }
+        // END SNIPPET: values
+
+
+        // START SNIPPET: private
+        @Mixins( ListablePersonMixin.class )
+        interface PersonEntity extends Listable, HasIdentity {}
+
+        interface PersonState extends Nameable {}
+
+        public class ListablePersonMixin implements Listable
+        {
+            @This PersonState person;
+
+            @Override
+            public String listName()
+            {
+                String fullName = person.name().get().givenName().get();
+                String sn = person.name().get().surName().get();
+                if (sn != null) fullName += " "+sn;
+                return fullName;
+            }
+        }
+
+        interface Listable
+        {
+            String listName();
+        }
+        // END SNIPPET: private
+
+    }
+
+
+    static class More {
+        // START SNIPPET: more
+        interface PersonEntity extends HasIdentity
+        {
+            Association<PersonEntity> father();
+            @Optional Association<PersonEntity> spouse();
+            ManyAssociation<PersonEntity> children();
+            @Aggregated ManyAssociation<BookNoteEntity> favouriteBooks();
+        }
+
+        interface BookNoteEntity extends HasIdentity
+        {
+            Property<String> note();
+            Association<BookEntity> book();
+        }
+
+        // END SNIPPET: more
+        interface BookEntity extends HasIdentity {}
+    }
+
+}
diff --git a/tutorials/introduction/src/main/java/org/apache/polygene/demo/intro/WhatsAnObjectDocs.java b/tutorials/introduction/src/main/java/org/apache/polygene/demo/intro/WhatsAnObjectDocs.java
new file mode 100644
index 0000000..ee09196
--- /dev/null
+++ b/tutorials/introduction/src/main/java/org/apache/polygene/demo/intro/WhatsAnObjectDocs.java
@@ -0,0 +1,72 @@
+/*
+ *  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.polygene.demo.intro;
+
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+
+public class WhatsAnObjectDocs
+{
+        // START SNIPPET: wo1
+        @Mixins( SomeMixin.class )
+        interface MyEntity extends Some, Other, HasIdentity {}
+        // END SNIPPET: wo1
+
+        // START SNIPPET: wo2
+        interface SomeState
+        {
+            Property<String> someProperty();
+        }
+        // END SNIPPET: wo2
+
+        // START SNIPPET: wo3
+        interface MyState extends SomeState, OtherState //, ...
+        {}
+        // END SNIPPET: wo3
+
+
+        abstract class SomeMixin implements Some
+        {}
+
+        interface Some
+        {}
+
+        interface Other
+        {}
+
+        interface OtherState
+        {}
+
+        {
+            UnitOfWork uow = null;
+            // START SNIPPET: wo4
+            EntityBuilder<MyEntity> builder = uow.newEntityBuilder(MyEntity.class);
+            MyState state = builder.instanceFor(MyState.class);
+
+            //... init state ...
+
+            MyEntity instance = builder.newInstance();
+            // END SNIPPET: wo4
+        }
+
+    }
diff --git a/tutorials/introduction/src/main/java/org/qi4j/demo/intro/StateModelingDocs.java b/tutorials/introduction/src/main/java/org/qi4j/demo/intro/StateModelingDocs.java
deleted file mode 100644
index 3d68918..0000000
--- a/tutorials/introduction/src/main/java/org/qi4j/demo/intro/StateModelingDocs.java
+++ /dev/null
@@ -1,138 +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.qi4j.demo.intro;
-
-import org.qi4j.api.association.Association;
-import org.qi4j.api.association.ManyAssociation;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.common.UseDefaults;
-import org.qi4j.api.entity.Aggregated;
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.value.ValueComposite;
-
-public class StateModelingDocs
-{
-
-// START SNIPPET: intro1
-    interface PersonEntity
-            extends EntityComposite
-    {
-        Property<String> givenName();
-        Property<String> surName();
-    }
-
-// END SNIPPET: intro1
-
-
-
-
-    static class Roles {
-
-// START SNIPPET: roles
-        interface Nameable
-        {
-            @UseDefaults Property<String> givenName();
-            @UseDefaults @Optional Property<String> surName();
-        }
-
-        interface PersonEntity
-                extends Nameable, EntityComposite
-        {}
-// END SNIPPET: roles
-    }
-
-    static class Values {
-
-// START SNIPPET: values
-        interface NameValue
-                extends ValueComposite
-        {
-            @UseDefaults Property<String> givenName();
-            @UseDefaults @Optional Property<String> surName();
-        }
-
-        interface Nameable
-        {
-            Property<NameValue> name();
-        }
-// END SNIPPET: values
-
-
-// START SNIPPET: private
-        @Mixins(ListablePersonMixin.class)
-        interface PersonEntity
-                extends Listable, EntityComposite {}
-
-        interface PersonState
-                extends Nameable {}
-
-        public class ListablePersonMixin
-                implements Listable
-        {
-            @This PersonState person;
-
-            @Override
-            public String listName()
-            {
-                String fullName = person.name().get().givenName().get();
-                String sn = person.name().get().surName().get();
-                if (sn != null) fullName += " "+sn;
-                return fullName;
-            }
-        }
-
-        interface Listable
-        {
-            public String listName();
-        }
-// END SNIPPET: private
-
-    }
-
-
-    static class More {
-// START SNIPPET: more
-        interface PersonEntity
-                extends EntityComposite
-        {
-            Association<PersonEntity> father();
-            @Optional Association<PersonEntity> spouse();
-            ManyAssociation<PersonEntity> children();
-            @Aggregated ManyAssociation<BookNoteEntity> favouriteBooks();
-        }
-
-        interface BookNoteEntity
-                extends EntityComposite
-        {
-            Property<String> note();
-            Association<BookEntity> book();
-        }
-
-// END SNIPPET: more
-        interface BookEntity
-                extends EntityComposite
-        {}
-    }
-
-}
diff --git a/tutorials/introduction/src/main/java/org/qi4j/demo/intro/WhatsAnObjectDocs.java b/tutorials/introduction/src/main/java/org/qi4j/demo/intro/WhatsAnObjectDocs.java
deleted file mode 100644
index 50be0c4..0000000
--- a/tutorials/introduction/src/main/java/org/qi4j/demo/intro/WhatsAnObjectDocs.java
+++ /dev/null
@@ -1,77 +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.qi4j.demo.intro;
-
-import org.qi4j.api.entity.EntityBuilder;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.unitofwork.UnitOfWork;
-
-public class WhatsAnObjectDocs
-{
-        // START SNIPPET: wo1
-        @Mixins(SomeMixin.class)
-        interface MyEntity
-                extends Some, Other, EntityComposite
-        {}
-// END SNIPPET: wo1
-
-        // START SNIPPET: wo2
-        interface SomeState
-        {
-            Property<String> someProperty();
-        }
-// END SNIPPET: wo2
-
-        // START SNIPPET: wo3
-        interface MyState
-                extends SomeState, OtherState //, ...
-        {}
-// END SNIPPET: wo3
-
-
-        abstract class SomeMixin implements Some
-        {}
-
-        interface Some
-        {}
-
-        interface Other
-        {}
-
-        interface OtherState
-        {}
-
-        {
-
-            UnitOfWork uow = null;
-// START SNIPPET: wo4
-            EntityBuilder<MyEntity> builder = uow.newEntityBuilder(MyEntity.class);
-            MyState state = builder.instanceFor(MyState.class);
-
-            //... init state ...
-
-            MyEntity instance = builder.newInstance();
-// END SNIPPET: wo4        }
-
-
-        }
-
-    }
diff --git a/tutorials/introduction/tenminutes/build.gradle b/tutorials/introduction/tenminutes/build.gradle
index aa44049..68b850e 100644
--- a/tutorials/introduction/tenminutes/build.gradle
+++ b/tutorials/introduction/tenminutes/build.gradle
@@ -1,31 +1,35 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "A 10-minute Introduction Tutorial to Apache Zest™ in its simplest form."
+apply plugin: 'polygene-tutorial'
 
-jar { manifest { name = "Apache Zest™ Tutorial - 10 minute Introduction" }}
+description = "A 10-minute Introduction Tutorial to Apache Polygene™ in its simplest form."
+
+jar { manifest { name = "Apache Polygene™ Tutorial - 10 minute Introduction" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
+  implementation polygene.core.bootstrap
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-  
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/tutorials/introduction/tenminutes/src/docs/ten-minutes.txt b/tutorials/introduction/tenminutes/src/docs/ten-minutes.txt
index dc86b5f..7aa14ba 100644
--- a/tutorials/introduction/tenminutes/src/docs/ten-minutes.txt
+++ b/tutorials/introduction/tenminutes/src/docs/ten-minutes.txt
@@ -17,36 +17,36 @@
  * under the License.
 ///////////////////////////////////////////////////////////////
 
-[[ten-minutes-intro,Zest™ in 10 minutes]]
-= Zest™ in 10 minutes =
+[[ten-minutes-intro,Polygene™ in 10 minutes]]
+= Polygene™ in 10 minutes =
 
 TIP: Theses tutorials are based on actual code found in the `tutorials/` directory of the
-https://zest.apache.org/download.html[Zest™ SDK sources]. You should start your favorite editor and find the code related to
+https://polygene.apache.org/download.html[Polygene™ SDK sources]. You should start your favorite editor and find the code related to
 this tutorial, run it and play with it.
 
 
-    * Zest™ does not introduce any new programming language, no additional compilers needed and all your existing tools
+    * Polygene™ does not introduce any new programming language, no additional compilers needed and all your existing tools
       work just like before. It is pure Java.
-    * Zest™ works with Composites.
-    * The equivalent of an Object instance in OOP, is a Composite instance in Zest™.
+    * Polygene™ works with Composites.
+    * The equivalent of an Object instance in OOP, is a Composite instance in Polygene™.
     * Composites are constructed from Fragments.
     * Fragments are Mixins, Concerns, Constraints and SideEffects.
     * Only Mixins carry Composite state. The others are shared between Composite instances.
 
 If you want to reproduce what's explained in this tutorial, remember to depend on the Core Runtime artifact that depends
-on Core API, Core SPI, Core Bootstrap and Core Functional & I/O APIs:
+on Core API, Core SPI, and Core Bootstrap:
 
 include::../../../../../core/runtime/build/docs/buildinfo/artifact.txt[]
 
 Moreover, you'll need an EntityStore for persistence and an Indexing engine for querying. Choose among the available
 implementations listed in the <<extensions>> section.
 
-See the <<howto-depend-on-zest>> tutorial for details.
+See the <<howto-depend-on-polygene>> tutorial for details.
 
 Composition is done with Java interfaces and Annotations. Example;
 [snippet,java]
 -----------
-source=tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/OrderEntity.java
+source=tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/OrderEntity.java
 tag=mainClass
 -----------
 
@@ -56,21 +56,20 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/InventoryConcern.java
+source=tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/InventoryConcern.java
 tag=allClass
 -----------
 
 Extending the ConcernOf is a convenience mechanism, instead of an explicit @ConcernFor annotation on a private field,
 which can be used in rare occasions when you are not able to extend. This base class defines the `next` field, which is
-set up by the Zest™ runtime and points to the next fragment in the call stack.
+set up by the Polygene™ runtime and points to the next fragment in the call stack.
 
-We can also see that the InventoryService is provided to the concern, which is done with dependency injection. Zest™
+We can also see that the InventoryService is provided to the concern, which is done with dependency injection. Polygene™
 also supports dependency injection via constructors and methods.
 
-The above example is obviously doing persistence, and we have no code handling this. But Zest™ supports persistence
-directly in its Core, and it is taken care of by Zest™, since it is declared as an EntityComposite.
-Nothing else is needed, provided that the Zest™ Runtime has been setup with one or more persisted EntityStores. But
-we have a naming convention that EntityComposites have "Entity" as the suffix in its name.
+The above example is obviously doing persistence, and we have no code handling this. But Polygene™ supports persistence
+directly in its Core, and it is taken care of by Polygene™.
+Nothing else is needed, provided that the Polygene™ Runtime has been setup with one or more persisted EntityStores.
 
 There are other built-in Composite subtypes as well, such as ValueComposite and ServiceComposite. This distinction helps
 both to communicate intent as well as having more precisely defined functionality.
@@ -80,7 +79,7 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/OrderEntity.java
+source=tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/OrderEntity.java
 tag=sideEffect
 -----------
 
@@ -88,15 +87,15 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/MailNotifySideEffect.java
+source=tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/MailNotifySideEffect.java
 tag=allClass
 -----------
 The MailService is dependency injected, as we have seen before.
 
-@This is telling Zest™ that the SideEffect needs a reference to the Composite instance that it belongs to.
+@This is telling Polygene™ that the SideEffect needs a reference to the Composite instance that it belongs to.
 
 By asking for both the HasCustomer and the HasLineItems types, we get type-safety and don't need to bother with casts.
-In fact, Zest™ will ensure that you can't even cast the `hasCustomer` instance to the HasLineItems type.
+In fact, Polygene™ will ensure that you can't even cast the `hasCustomer` instance to the HasLineItems type.
 
 By not referencing the aggregated interface OrderEntity, we reduce the coupling of this SideEffect and it can be used
 in any other Composite where the HasCustomer and HasLineItems combination is used, for instance in an InvoiceEntity.
@@ -105,5 +104,7 @@
 
 == Conclusion ==
 
-In this short introduction, we have covered the essence of Zest™. We have looked at what is a Composite, seen some of the
+In this short introduction, we have covered the essence of Polygene™. We have looked at what is a Composite, seen some of the
 Fragments in action, and how simple it is to turn a Composite into a persisted Composite, known as an EntityComposite.
+
+Next step, <<thirty-minutes-intro>>.
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/Confirmable.java b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/Confirmable.java
new file mode 100644
index 0000000..480e6c5
--- /dev/null
+++ b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/Confirmable.java
@@ -0,0 +1,26 @@
+/*
+ *  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.polygene.demo.tenminute;
+
+public interface Confirmable
+{
+    void confirm();
+}
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/HasCustomer.java b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/HasCustomer.java
new file mode 100644
index 0000000..a644915
--- /dev/null
+++ b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/HasCustomer.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.demo.tenminute;
+
+import org.apache.polygene.api.property.Property;
+
+public interface HasCustomer
+{
+    Property<String> name();
+}
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/HasLineItems.java b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/HasLineItems.java
new file mode 100644
index 0000000..7087886
--- /dev/null
+++ b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/HasLineItems.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.demo.tenminute;
+
+import java.util.List;
+import org.apache.polygene.api.property.Property;
+
+public interface HasLineItems
+{
+    Property<List<LineItem>> lineItems();
+}
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/HasSequenceNumber.java b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/HasSequenceNumber.java
new file mode 100644
index 0000000..1dbaad5
--- /dev/null
+++ b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/HasSequenceNumber.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.demo.tenminute;
+
+import org.apache.polygene.api.property.Property;
+
+public interface HasSequenceNumber
+{
+    Property<String> number();
+}
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/InventoryConcern.java b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/InventoryConcern.java
new file mode 100644
index 0000000..e0427a5
--- /dev/null
+++ b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/InventoryConcern.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.polygene.demo.tenminute;
+
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.elsewhere.inventory.InventoryService;
+
+// START SNIPPET: allClass
+public class InventoryConcern extends ConcernOf<Order>
+    implements Order
+{
+    @Service
+    private InventoryService inventory;
+
+    @Override
+    public void addLineItem( LineItem item )
+    {
+        String productCode = item.productCode().get();
+        int quantity = item.quantity().get();
+        inventory.remove( productCode, quantity );
+        next.addLineItem( item );
+    }
+
+    @Override
+    public void removeLineItem( LineItem item )
+    {
+        String productCode = item.productCode().get();
+        int quantity = item.quantity().get();
+        inventory.add( productCode, quantity );
+        next.removeLineItem( item );
+    }
+}
+// END SNIPPET: allClass
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/LineItem.java b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/LineItem.java
new file mode 100644
index 0000000..1e9c8e7
--- /dev/null
+++ b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/LineItem.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.demo.tenminute;
+
+import org.apache.polygene.api.property.Property;
+
+public interface LineItem
+{
+    Property<String> name();
+
+    Property<String> productCode();
+
+    Property<Integer> quantity();
+}
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/MailNotifySideEffect.java b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/MailNotifySideEffect.java
new file mode 100644
index 0000000..9d485ec
--- /dev/null
+++ b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/MailNotifySideEffect.java
@@ -0,0 +1,59 @@
+/*
+ *  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.polygene.demo.tenminute;
+
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.sideeffect.SideEffectOf;
+import org.apache.polygene.elsewhere.mail.MailService;
+
+// START SNIPPET: allClass
+public abstract class MailNotifySideEffect extends SideEffectOf<Confirmable>
+    implements Confirmable
+{
+    @Service
+    private MailService mailer;
+
+    @This
+    private HasLineItems hasItems;
+
+    @This
+    private HasCustomer hasCustomer;
+
+    @Override
+    public void confirm()
+    {
+        StringBuilder builder = new StringBuilder();
+        builder.append( "An Order has been made.\n\n\n" );
+        builder.append( "Customer:" );
+        builder.append( hasCustomer.name().get() );
+        builder.append( "\n\nItems ordered:\n" );
+        for( LineItem item : hasItems.lineItems().get() )
+        {
+            builder.append( item.name().get() );
+            builder.append( " : " );
+            builder.append( item.quantity().get() );
+            builder.append( "\n" );
+        }
+        mailer.send( "sales@mycompany.com", builder.toString() );
+    }
+}
+// END SNIPPET: allClass
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/Order.java b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/Order.java
new file mode 100644
index 0000000..e74fa57
--- /dev/null
+++ b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/Order.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.demo.tenminute;
+
+public interface Order
+{
+    void addLineItem( LineItem item );
+
+    void removeLineItem( LineItem item );
+
+}
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/OrderEntity.java b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/OrderEntity.java
new file mode 100644
index 0000000..b1ab55f
--- /dev/null
+++ b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/OrderEntity.java
@@ -0,0 +1,38 @@
+/*
+ *  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.polygene.demo.tenminute;
+
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.sideeffect.SideEffects;
+
+// START SNIPPET: sideEffect
+@SideEffects( MailNotifySideEffect.class )
+// START SNIPPET: mainClass
+@Concerns( { PurchaseLimitConcern.class, InventoryConcern.class } )
+public interface OrderEntity
+    extends Order, Confirmable,
+            HasSequenceNumber, HasCustomer, HasLineItems,
+            HasIdentity
+{
+}
+// END SNIPPET: sideEffect
+// END SNIPPET: mainClass
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/PurchaseLimitConcern.java b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/PurchaseLimitConcern.java
new file mode 100644
index 0000000..df0e675
--- /dev/null
+++ b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/PurchaseLimitConcern.java
@@ -0,0 +1,25 @@
+/*
+ *  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.polygene.demo.tenminute;
+
+public class PurchaseLimitConcern
+{
+}
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/elsewhere/inventory/InventoryService.java b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/elsewhere/inventory/InventoryService.java
new file mode 100644
index 0000000..8b7af3a
--- /dev/null
+++ b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/elsewhere/inventory/InventoryService.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.elsewhere.inventory;
+
+public interface InventoryService
+{
+    void add( String productCode, int quantity );
+
+    void remove( String productCode, int quantity );
+}
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/elsewhere/mail/MailService.java b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/elsewhere/mail/MailService.java
new file mode 100644
index 0000000..03a9dcf
--- /dev/null
+++ b/tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/elsewhere/mail/MailService.java
@@ -0,0 +1,26 @@
+/*
+ *  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.polygene.elsewhere.mail;
+
+public interface MailService
+{
+    void send( String recipient, String message );
+}
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/Confirmable.java b/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/Confirmable.java
deleted file mode 100644
index 24bfe46..0000000
--- a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/Confirmable.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.demo.tenminute;
-
-public interface Confirmable
-{
-    void confirm();
-}
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/HasCustomer.java b/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/HasCustomer.java
deleted file mode 100644
index 2589b4b..0000000
--- a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/HasCustomer.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.demo.tenminute;
-
-import org.qi4j.api.property.Property;
-
-public interface HasCustomer
-{
-    Property<String> name();
-}
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/HasLineItems.java b/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/HasLineItems.java
deleted file mode 100644
index 10bb5ed..0000000
--- a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/HasLineItems.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.demo.tenminute;
-
-import java.util.List;
-import org.qi4j.api.property.Property;
-
-public interface HasLineItems
-{
-    Property<List<LineItem>> lineItems();
-}
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/HasSequenceNumber.java b/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/HasSequenceNumber.java
deleted file mode 100644
index 5b07424..0000000
--- a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/HasSequenceNumber.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.demo.tenminute;
-
-import org.qi4j.api.property.Property;
-
-public interface HasSequenceNumber
-{
-    Property<String> number();
-}
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/InventoryConcern.java b/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/InventoryConcern.java
deleted file mode 100644
index e9ad00c..0000000
--- a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/InventoryConcern.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.demo.tenminute;
-
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.elsewhere.inventory.InventoryService;
-
-// START SNIPPET: allClass
-public class InventoryConcern extends ConcernOf<Order>
-    implements Order
-{
-    @Service
-    private InventoryService inventory;
-
-    @Override
-    public void addLineItem( LineItem item )
-    {
-        String productCode = item.productCode().get();
-        int quantity = item.quantity().get();
-        inventory.remove( productCode, quantity );
-        next.addLineItem( item );
-    }
-
-    @Override
-    public void removeLineItem( LineItem item )
-    {
-        String productCode = item.productCode().get();
-        int quantity = item.quantity().get();
-        inventory.add( productCode, quantity );
-        next.removeLineItem( item );
-    }
-}
-// END SNIPPET: allClass
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/LineItem.java b/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/LineItem.java
deleted file mode 100644
index 323ba16..0000000
--- a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/LineItem.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.demo.tenminute;
-
-import org.qi4j.api.property.Property;
-
-public interface LineItem
-{
-    Property<String> name();
-
-    Property<String> productCode();
-
-    Property<Integer> quantity();
-}
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/MailNotifySideEffect.java b/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/MailNotifySideEffect.java
deleted file mode 100644
index 02ce374..0000000
--- a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/MailNotifySideEffect.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.demo.tenminute;
-
-import org.qi4j.api.injection.scope.Service;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.sideeffect.SideEffectOf;
-import org.qi4j.elsewhere.mail.MailService;
-
-// START SNIPPET: allClass
-public abstract class MailNotifySideEffect extends SideEffectOf<Confirmable>
-    implements Confirmable
-{
-    @Service
-    private MailService mailer;
-
-    @This
-    private HasLineItems hasItems;
-
-    @This
-    private HasCustomer hasCustomer;
-
-    @Override
-    public void confirm()
-    {
-        StringBuilder builder = new StringBuilder();
-        builder.append( "An Order has been made.\n\n\n" );
-        builder.append( "Customer:" );
-        builder.append( hasCustomer.name().get() );
-        builder.append( "\n\nItems ordered:\n" );
-        for( LineItem item : hasItems.lineItems().get() )
-        {
-            builder.append( item.name().get() );
-            builder.append( " : " );
-            builder.append( item.quantity().get() );
-            builder.append( "\n" );
-        }
-        mailer.send( "sales@mycompany.com", builder.toString() );
-    }
-}
-// END SNIPPET: allClass
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/Order.java b/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/Order.java
deleted file mode 100644
index ee14935..0000000
--- a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/Order.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.demo.tenminute;
-
-public interface Order
-{
-    void addLineItem( LineItem item );
-
-    void removeLineItem( LineItem item );
-
-}
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/OrderEntity.java b/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/OrderEntity.java
deleted file mode 100644
index 98d7529..0000000
--- a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/OrderEntity.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.demo.tenminute;
-
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.sideeffect.SideEffects;
-
-// START SNIPPET: sideEffect
-@SideEffects( MailNotifySideEffect.class )
-// START SNIPPET: mainClass
-@Concerns( { PurchaseLimitConcern.class, InventoryConcern.class } )
-public interface OrderEntity
-    extends Order, Confirmable,
-            HasSequenceNumber, HasCustomer, HasLineItems,
-            EntityComposite
-{
-// END SNIPPET: sideEffect
-}
-// END SNIPPET: mainClass
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/PurchaseLimitConcern.java b/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/PurchaseLimitConcern.java
deleted file mode 100644
index 9ed6f39..0000000
--- a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/PurchaseLimitConcern.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.demo.tenminute;
-
-public class PurchaseLimitConcern
-{
-}
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/elsewhere/inventory/InventoryService.java b/tutorials/introduction/tenminutes/src/main/java/org/qi4j/elsewhere/inventory/InventoryService.java
deleted file mode 100644
index 64bd972..0000000
--- a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/elsewhere/inventory/InventoryService.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.elsewhere.inventory;
-
-public interface InventoryService
-{
-    void add( String productCode, int quantity );
-
-    void remove( String productCode, int quantity );
-}
diff --git a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/elsewhere/mail/MailService.java b/tutorials/introduction/tenminutes/src/main/java/org/qi4j/elsewhere/mail/MailService.java
deleted file mode 100644
index cf93f75..0000000
--- a/tutorials/introduction/tenminutes/src/main/java/org/qi4j/elsewhere/mail/MailService.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * Licensed 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.qi4j.elsewhere.mail;
-
-public interface MailService
-{
-    void send( String recipient, String message );
-}
diff --git a/tutorials/introduction/thirtyminutes/build.gradle b/tutorials/introduction/thirtyminutes/build.gradle
index 83bcbc5..6e2a751 100644
--- a/tutorials/introduction/thirtyminutes/build.gradle
+++ b/tutorials/introduction/thirtyminutes/build.gradle
@@ -1,32 +1,36 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "A 30-minute Introduction Tutorial to Apache Zest™ in its simplest form."
+apply plugin: 'polygene-tutorial'
 
-jar { manifest { name = "Apache Zest™ Tutorial - 30 minute Introduction" }}
+description = "A 30-minute Introduction Tutorial to Apache Polygene™ in its simplest form."
+
+jar { manifest { name = "Apache Polygene™ Tutorial - 30 minute Introduction" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
-  compile(project(":org.qi4j.tutorials:org.qi4j.tutorial.introduction:org.qi4j.tutorial.introduction.tenminutes"))
+  implementation polygene.core.bootstrap
+  implementation project( ':tutorials:introduction:tenminutes' )
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
-  
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  runtimeOnly polygene.core.runtime
+
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/tutorials/introduction/thirtyminutes/src/docs/thirty-minutes.txt b/tutorials/introduction/thirtyminutes/src/docs/thirty-minutes.txt
index 3913a9f..b8124ab 100644
--- a/tutorials/introduction/thirtyminutes/src/docs/thirty-minutes.txt
+++ b/tutorials/introduction/thirtyminutes/src/docs/thirty-minutes.txt
@@ -17,31 +17,31 @@
  * under the License.
 ///////////////////////////////////////////////////////////////
 
-[[thirty-minutes-intro,Zest™ in 30 minutes]]
-= Zest™ in 30 minutes =
+[[thirty-minutes-intro,Polygene™ in 30 minutes]]
+= Polygene™ in 30 minutes =
 
 TIP: Theses tutorials are based on actual code found in the `tutorials/` directory of the
-https://zest.apache.org/download.html[Zest™ SDK sources]. You should start your favorite editor and find the code related to
+https://polygene.apache.org/download.html[Polygene™ SDK sources]. You should start your favorite editor and find the code related to
 this tutorial, run it and play with it.
 
 
-This introduction will deepen your understanding of Zest™, as we touches on a couple of the common features of Zest™. It
-is expected that you have gone through and understood the "Zest™ in 10 minutes" introduction.
+This introduction will deepen your understanding of Polygene™, as we touches on a couple of the common features of Polygene™. It
+is expected that you have gone through and understood the "Polygene™ in 10 minutes" introduction.
 
 If you want to reproduce what's explained in this tutorial, remember to depend on the Core Runtime artifact that depends
-on Core API, Core SPI, Core Bootstrap and Core Functional & I/O APIs:
+on Core API, Core SPI, and Core Bootstrap:
 
 include::../../../../../core/runtime/build/docs/buildinfo/artifact.txt[]
 
 Moreover, you'll need an EntityStore for persistence and an Indexing engine for querying. Choose among the available
 implementations listed in the <<extensions>> section.
 
-See the <<howto-depend-on-zest>> tutorial for details.
+See the <<howto-depend-on-polygene>> tutorial for details.
 
 We will go back to the OrderEntity example;
 [snippet,java]
 -----------
-source=tutorials/introduction/tenminutes/src/main/java/org/qi4j/demo/tenminute/OrderEntity.java
+source=tutorials/introduction/tenminutes/src/main/java/org/apache/polygene/demo/tenminute/OrderEntity.java
 tag=mainClass
 -----------
 
@@ -52,12 +52,12 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/thirtyminutes/src/main/java/org/qi4j/demo/thirtyminutes/ThirtyMinutesDocs.java
+source=tutorials/introduction/thirtyminutes/src/main/java/org/apache/polygene/demo/thirtyminutes/ThirtyMinutesDocs.java
 tag=2
 -----------
 
-Quite a lot of Zest™ features are leveraged above;
-[1] Property is a first class citizen in Zest™, instead of getters/setters naming convention to declare properties.
+Quite a lot of Polygene™ features are leveraged above;
+[1] Property is a first class citizen in Polygene™, instead of getters/setters naming convention to declare properties.
 [2] ValueComposite for Action means that it is among other things Immutable.
 [3] The Action extends a Property. We call that Property subtyping and highly recommended.
 [4] The CompositeBuilder creates Immutable Action instances.
@@ -66,7 +66,7 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/thirtyminutes/src/main/java/org/qi4j/demo/thirtyminutes/ThirtyMinutesDocs.java
+source=tutorials/introduction/thirtyminutes/src/main/java/org/apache/polygene/demo/thirtyminutes/ThirtyMinutesDocs.java
 tag=3
 -----------
 
@@ -81,19 +81,19 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/thirtyminutes/src/main/java/org/qi4j/demo/thirtyminutes/ThirtyMinutesDocs.java
+source=tutorials/introduction/thirtyminutes/src/main/java/org/apache/polygene/demo/thirtyminutes/ThirtyMinutesDocs.java
 tag=4
 -----------
 
 The above construct is called a Generic Concern, since it implements java.lang.reflect.InvocationHandler instead of the
 interface of the domain model. The ConcernOf baseclass will also need to be of InvocationHandler type, and the
-Zest™ Runtime will handle the chaining between domain model style and this generic style of interceptor call chain.
+Polygene™ Runtime will handle the chaining between domain model style and this generic style of interceptor call chain.
 
 Finally, we need to declare the Concern in the OrderEntity;
 
 [snippet,java]
 -----------
-source=tutorials/introduction/thirtyminutes/src/main/java/org/qi4j/demo/thirtyminutes/ThirtyMinutesDocs.java
+source=tutorials/introduction/thirtyminutes/src/main/java/org/apache/polygene/demo/thirtyminutes/ThirtyMinutesDocs.java
 tag=5
 -----------
 
@@ -109,13 +109,13 @@
 the persistence concern of storage and retrieval. This enables many performance optimization opportunities as well as a
 more flexible Indexing strategy. The other thing to understand is that the Query API is using the domain model, in Java,
 and not some String based query language. We have made this choice to ensure refactoring safety. In rare cases, the
-Query API is not capable enough, in which case Zest™ still provides the ability to look up and execute native queries.
+Query API is not capable enough, in which case Polygene™ still provides the ability to look up and execute native queries.
 
 Let's say that we want to find a particular Order from its SequenceNumber.
 
 [snippet,java]
 -----------
-source=tutorials/introduction/thirtyminutes/src/main/java/org/qi4j/demo/thirtyminutes/ThirtyMinutesDocs.java
+source=tutorials/introduction/thirtyminutes/src/main/java/org/apache/polygene/demo/thirtyminutes/ThirtyMinutesDocs.java
 tag=6
 -----------
 
@@ -132,7 +132,7 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/thirtyminutes/src/main/java/org/qi4j/demo/thirtyminutes/ThirtyMinutesDocs.java
+source=tutorials/introduction/thirtyminutes/src/main/java/org/apache/polygene/demo/thirtyminutes/ThirtyMinutesDocs.java
 tag=7
 -----------
 
@@ -144,7 +144,7 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/thirtyminutes/src/main/java/org/qi4j/demo/thirtyminutes/ThirtyMinutesDocs.java
+source=tutorials/introduction/thirtyminutes/src/main/java/org/apache/polygene/demo/thirtyminutes/ThirtyMinutesDocs.java
 tag=8
 -----------
 
@@ -152,13 +152,15 @@
 assembled during bootstrap. At the time of this writing, only an RDF indexing subsystem exist, and is added most easily
 by assembly.addAssembler( new RdfNativeSesameStoreAssembler() ).
 
-It can be a bit confusing to see Zest™ use Java itself as a Query language, but since we have practically killed the
+It can be a bit confusing to see Polygene™ use Java itself as a Query language, but since we have practically killed the
 classes and only operate with interfaces, it is possible to do a lot of seemingly magic stuff. Just keep in mind that
 it is pure Java, albeit heavy use of dynamic proxies to capture the intent of the query.
 
 == Conclusion ==
 
-We have now explored a couple more intricate features of Zest™, hopefully without being overwhelmed with details on how
-to create applications from scratch, how to structure applications, and how the entire Zest™ Extension system works.
+We have now explored a couple more intricate features of Polygene™, hopefully without being overwhelmed with details on how
+to create applications from scratch, how to structure applications, and how the entire Polygene™ Extension system works.
 We have looked at how to add a Concern that uses a private Mixin, we have touched a bit on Generic Concerns, and
 finally a short introduction to the Query API.
+
+// Next step, <<two-hours-intro>>.
diff --git a/tutorials/introduction/thirtyminutes/src/main/java/org/apache/polygene/demo/thirtyminutes/ThirtyMinutesDocs.java b/tutorials/introduction/thirtyminutes/src/main/java/org/apache/polygene/demo/thirtyminutes/ThirtyMinutesDocs.java
new file mode 100644
index 0000000..c7f2b44
--- /dev/null
+++ b/tutorials/introduction/thirtyminutes/src/main/java/org/apache/polygene/demo/thirtyminutes/ThirtyMinutesDocs.java
@@ -0,0 +1,289 @@
+/*
+ *  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.polygene.demo.thirtyminutes;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.time.LocalDate;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.concern.ConcernOf;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.demo.tenminute.Confirmable;
+import org.apache.polygene.demo.tenminute.HasCustomer;
+import org.apache.polygene.demo.tenminute.HasLineItems;
+import org.apache.polygene.demo.tenminute.HasSequenceNumber;
+import org.apache.polygene.demo.tenminute.InventoryConcern;
+import org.apache.polygene.demo.tenminute.LineItem;
+import org.apache.polygene.demo.tenminute.PurchaseLimitConcern;
+
+// START SNIPPET: 6
+import static org.apache.polygene.api.query.QueryExpressions.eq;
+import static org.apache.polygene.api.query.QueryExpressions.gt;
+import static org.apache.polygene.api.query.QueryExpressions.templateFor;
+
+import org.apache.polygene.api.query.QueryBuilder;
+
+// END SNIPPET: 6
+public class ThirtyMinutesDocs
+{
+    private QueryBuilderFactory queryBuilderFactory;
+    private ValueBuilderFactory valueBuilderFactory;
+    private UnitOfWorkFactory unitOfWorkFactory;
+
+// START SNIPPET: 6
+    @Structure private UnitOfWorkFactory uowFactory; //Injected
+// END SNIPPET: 6
+
+    {
+// START SNIPPET: 6
+        UnitOfWork uow = uowFactory.currentUnitOfWork();
+        QueryBuilder<Order> builder = queryBuilderFactory.newQueryBuilder( Order.class );
+
+        String orderNumber = "12345";
+        HasSequenceNumber template = templateFor( HasSequenceNumber.class );
+        builder.where( eq( template.number(), orderNumber ) );
+        Query<Order> query = uow.newQuery( builder);
+
+        Iterator<Order> result = query.iterator();
+
+        if( result.hasNext() )
+        {
+            Order order = result.next();
+        }
+        else
+        {
+            // Deal with it wasn't found.
+        }
+// END SNIPPET: 6
+    }
+
+    interface Report {
+        void addOrderToReport(Order order);
+        void addCustomerToReport(String customerName);
+    }
+
+
+
+    {
+        Report report = null;
+        UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+
+// START SNIPPET: 7
+        QueryBuilder<Order> builder = queryBuilderFactory.newQueryBuilder( Order.class );
+
+        LocalDate last90days = LocalDate.now().minusDays( 90 );
+        Order template = templateFor( Order.class );
+        builder.where( gt( template.createdDate(), last90days ) );
+        Query<Order> query = uow.newQuery(builder);
+
+        for( Order order : query )
+        {
+            report.addOrderToReport( order );
+        }
+// END SNIPPET: 7
+    }
+
+    {
+        Report report = null;
+        UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+
+// START SNIPPET: 8
+        QueryBuilder<HasCustomer> builder = queryBuilderFactory.newQueryBuilder( HasCustomer.class );
+
+        LocalDate lastMonth = LocalDate.now().minusMonths( 1 );
+        Order template1 = templateFor( Order.class );
+        builder.where( gt( template1.createdDate(), lastMonth ) );
+        Query<HasCustomer> query = uow.newQuery(builder);
+
+        for( HasCustomer hasCustomer : query )
+        {
+            report.addCustomerToReport( hasCustomer.name().get() );
+        }
+// END SNIPPET: 8
+
+    }
+
+    public interface Order
+    {
+        void addLineItem( LineItem item );
+
+        void removeLineItem( LineItem item );
+
+        void completed();
+
+        Property<LocalDate> createdDate();
+    }
+
+
+    // START SNIPPET: 2
+    public interface HasAuditTrail<M>
+    {
+        AuditTrail<M> auditTrail();
+    }
+
+    public interface AuditTrail<M> extends Property<List<Action<M>>>
+    {}
+
+    public interface Action<T> extends ValueComposite          // [2][3]
+    {
+        enum Type { added, removed, completed };
+
+        @Optional Property<T> item();                          // [1]
+
+        Property<Type> action();                               // [1]
+    }
+
+    public interface Trailable<M>
+    {
+        void itemAdded( M item );
+        void itemRemoved( M item );
+        void completed();
+    }
+
+    public class TrailableMixin<M>
+            implements Trailable<M>
+    {
+        private @This HasAuditTrail<M> hasTrail;
+
+        @Override
+        public void itemAdded( M item )
+        {
+            addAction( item, Action.Type.added );
+        }
+
+        @Override
+        public void itemRemoved( M item )
+        {
+            addAction( item, Action.Type.removed );
+        }
+
+        @Override
+        public void completed()
+        {
+            addAction( null, Action.Type.completed );
+        }
+
+        private Action<M> addAction( M item, Action.Type type )
+        {
+            ValueBuilder<Action> builder =
+                    valueBuilderFactory.newValueBuilder( Action.class);       // [4]
+            Action<M> prototype = builder.prototypeFor( Action.class );
+            prototype.item().set( item );
+            prototype.action().set( type );
+            Action instance = builder.newInstance();
+            hasTrail.auditTrail().get().add( instance );
+            return instance;
+        }
+    }
+// END SNIPPET: 2
+
+// START SNIPPET: 3
+    public abstract class OrderAuditTrailConcern
+            extends ConcernOf<Order>
+            implements Order
+    {
+        @This Trailable<LineItem> trail;
+
+        @Override
+        public void addLineItem( LineItem item )
+        {
+            next.addLineItem( item );
+            trail.itemAdded( item );
+        }
+
+        @Override
+        public void removeLineItem( LineItem item )
+        {
+            next.removeLineItem( item );
+            trail.itemRemoved( item );
+        }
+
+        @Override
+        public void completed()
+        {
+            next.completed();
+            trail.completed();
+        }
+    }
+// END SNIPPET: 3
+
+// START SNIPPET: 4
+    public class AuditTrailConcern
+            extends ConcernOf<InvocationHandler>
+            implements InvocationHandler
+    {
+        @This Trailable trail;
+
+        @Override
+        public Object invoke( Object proxy, Method m, Object[] args )
+                throws Throwable
+        {
+            Object retValue = next.invoke(proxy, m, args);
+            String methodName = m.getName();
+            if( methodName.startsWith( "add" ) )
+            {
+                trail.itemAdded( args[0] );
+            }
+            else if( methodName.startsWith( "remove" ) )
+            {
+                trail.itemRemoved( args[0] );
+            }
+            else if( methodName.startsWith( "complete" ) ||
+                    methodName.startsWith( "commit" ) )
+            {
+                trail.completed();
+            }
+
+            return retValue;
+        }
+    }
+// END SNIPPET: 4
+
+
+// START SNIPPET: 5
+    @Concerns({
+            AuditTrailConcern.class,
+            PurchaseLimitConcern.class,
+            InventoryConcern.class
+    })
+
+    @Mixins( TrailableMixin.class )
+    public interface OrderEntity
+        extends Order, Confirmable,
+                HasSequenceNumber, HasCustomer, HasLineItems,
+                HasIdentity
+    {
+    }
+// END SNIPPET: 5
+}
\ No newline at end of file
diff --git a/tutorials/introduction/thirtyminutes/src/main/java/org/qi4j/demo/thirtyminutes/ThirtyMinutesDocs.java b/tutorials/introduction/thirtyminutes/src/main/java/org/qi4j/demo/thirtyminutes/ThirtyMinutesDocs.java
deleted file mode 100644
index d172077..0000000
--- a/tutorials/introduction/thirtyminutes/src/main/java/org/qi4j/demo/thirtyminutes/ThirtyMinutesDocs.java
+++ /dev/null
@@ -1,292 +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.qi4j.demo.thirtyminutes;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import org.qi4j.api.common.Optional;
-import org.qi4j.api.concern.ConcernOf;
-import org.qi4j.api.concern.Concerns;
-import org.qi4j.api.entity.EntityComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.query.Query;
-import org.qi4j.api.structure.Module;
-import org.qi4j.api.unitofwork.UnitOfWork;
-import org.qi4j.api.unitofwork.UnitOfWorkFactory;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueComposite;
-import org.qi4j.demo.tenminute.Confirmable;
-import org.qi4j.demo.tenminute.HasCustomer;
-import org.qi4j.demo.tenminute.HasLineItems;
-import org.qi4j.demo.tenminute.HasSequenceNumber;
-import org.qi4j.demo.tenminute.InventoryConcern;
-import org.qi4j.demo.tenminute.LineItem;
-import org.qi4j.demo.tenminute.PurchaseLimitConcern;
-
-// START SNIPPET: 6
-import static org.qi4j.api.query.QueryExpressions.eq;
-import static org.qi4j.api.query.QueryExpressions.gt;
-import static org.qi4j.api.query.QueryExpressions.templateFor;
-
-import org.qi4j.api.query.QueryBuilder;
-
-// END SNIPPET: 6
-public class ThirtyMinutesDocs
-{
-    Module module;
-
-// START SNIPPET: 6
-    @Structure private UnitOfWorkFactory uowFactory; //Injected
-// END SNIPPET: 6
-
-    {
-// START SNIPPET: 6
-        UnitOfWork uow = uowFactory.currentUnitOfWork();
-        QueryBuilder<Order> builder = module.newQueryBuilder( Order.class );
-
-        String orderNumber = "12345";
-        HasSequenceNumber template = templateFor( HasSequenceNumber.class );
-        builder.where( eq( template.number(), orderNumber ) );
-        Query<Order> query = uow.newQuery( builder);
-
-        Iterator<Order> result = query.iterator();
-
-        if( result.hasNext() )
-        {
-            Order order = result.next();
-        }
-        else
-        {
-            // Deal with it wasn't found.
-        }
-// END SNIPPET: 6
-    }
-
-    interface Report {
-        void addOrderToReport(Order order);
-        void addCustomerToReport(String customerName);
-    }
-
-
-
-    {
-        Report report = null;
-        UnitOfWork uow = module.currentUnitOfWork();
-
-// START SNIPPET: 7
-        QueryBuilder<Order> builder = module.newQueryBuilder( Order.class );
-
-        Calendar cal = Calendar.getInstance();
-        cal.setTime( new Date() );
-        cal.roll( Calendar.DAY_OF_MONTH, -90 );
-        Date last90days = cal.getTime();
-        Order template = templateFor( Order.class );
-        builder.where( gt( template.createdDate(), last90days ) );
-        Query<Order> query = uow.newQuery(builder);
-
-        for( Order order : query )
-        {
-            report.addOrderToReport( order );
-        }
-// END SNIPPET: 7
-    }
-
-    {
-        Report report = null;
-        UnitOfWork uow = module.currentUnitOfWork();
-
-// START SNIPPET: 8
-        QueryBuilder<HasCustomer> builder = module.newQueryBuilder( HasCustomer.class );
-
-        Calendar cal = Calendar.getInstance();
-        cal.setTime( new Date() );
-        cal.roll( Calendar.MONTH, -1 );
-        Date lastMonth = cal.getTime();
-        Order template1 = templateFor( Order.class );
-        builder.where( gt( template1.createdDate(), lastMonth ) );
-        Query<HasCustomer> query = uow.newQuery(builder);
-
-        for( HasCustomer hasCustomer : query )
-        {
-            report.addCustomerToReport( hasCustomer.name().get() );
-        }
-// END SNIPPET: 8
-
-    }
-
-    public interface Order
-    {
-        void addLineItem( LineItem item );
-
-        void removeLineItem( LineItem item );
-
-        void completed();
-
-        Property<Date> createdDate();
-    }
-
-
-    // START SNIPPET: 2
-    public interface HasAuditTrail<M>
-    {
-        AuditTrail<M> auditTrail();
-    }
-
-    public interface AuditTrail<M> extends Property<List<Action<M>>>
-    {}
-
-    public interface Action<T> extends ValueComposite          // [2][3]
-    {
-        enum Type { added, removed, completed };
-
-        @Optional Property<T> item();                          // [1]
-
-        Property<Type> action();                               // [1]
-    }
-
-    public interface Trailable<M>
-    {
-        void itemAdded( M item );
-        void itemRemoved( M item );
-        void completed();
-    }
-
-    public class TrailableMixin<M>
-            implements Trailable<M>
-    {
-        private @This HasAuditTrail<M> hasTrail;
-
-        @Override
-        public void itemAdded( M item )
-        {
-            addAction( item, Action.Type.added );
-        }
-
-        @Override
-        public void itemRemoved( M item )
-        {
-            addAction( item, Action.Type.removed );
-        }
-
-        @Override
-        public void completed()
-        {
-            addAction( null, Action.Type.completed );
-        }
-
-        private Action<M> addAction( M item, Action.Type type )
-        {
-            ValueBuilder<Action> builder =
-                    module.newValueBuilder(Action.class);       // [4]
-            Action<M> prototype = builder.prototypeFor( Action.class );
-            prototype.item().set( item );
-            prototype.action().set( type );
-            Action instance = builder.newInstance();
-            hasTrail.auditTrail().get().add( instance );
-            return instance;
-        }
-    }
-// END SNIPPET: 2
-
-// START SNIPPET: 3
-    public abstract class OrderAuditTrailConcern
-            extends ConcernOf<Order>
-            implements Order
-    {
-        @This Trailable<LineItem> trail;
-
-        @Override
-        public void addLineItem( LineItem item )
-        {
-            next.addLineItem( item );
-            trail.itemAdded( item );
-        }
-
-        @Override
-        public void removeLineItem( LineItem item )
-        {
-            next.removeLineItem( item );
-            trail.itemRemoved( item );
-        }
-
-        @Override
-        public void completed()
-        {
-            next.completed();
-            trail.completed();
-        }
-    }
-// END SNIPPET: 3
-
-// START SNIPPET: 4
-    public class AuditTrailConcern
-            extends ConcernOf<InvocationHandler>
-            implements InvocationHandler
-    {
-        @This Trailable trail;
-
-        @Override
-        public Object invoke( Object proxy, Method m, Object[] args )
-                throws Throwable
-        {
-            Object retValue = next.invoke(proxy, m, args);
-            String methodName = m.getName();
-            if( methodName.startsWith( "add" ) )
-            {
-                trail.itemAdded( args[0] );
-            }
-            else if( methodName.startsWith( "remove" ) )
-            {
-                trail.itemRemoved( args[0] );
-            }
-            else if( methodName.startsWith( "complete" ) ||
-                    methodName.startsWith( "commit" ) )
-            {
-                trail.completed();
-            }
-
-            return retValue;
-        }
-    }
-// END SNIPPET: 4
-
-
-// START SNIPPET: 5
-    @Concerns({
-            AuditTrailConcern.class,
-            PurchaseLimitConcern.class,
-            InventoryConcern.class
-    })
-
-    @Mixins( TrailableMixin.class )
-    public interface OrderEntity
-            extends Order, Confirmable,
-            HasSequenceNumber, HasCustomer, HasLineItems,
-            EntityComposite
-    {
-    }
-// END SNIPPET: 5
-}
\ No newline at end of file
diff --git a/tutorials/introduction/twohours/src/docs/two-hours.txt b/tutorials/introduction/twohours/src/docs/two-hours.txt
index 5a6d066..8ce2b2a 100644
--- a/tutorials/introduction/twohours/src/docs/two-hours.txt
+++ b/tutorials/introduction/twohours/src/docs/two-hours.txt
@@ -17,12 +17,12 @@
  * under the License.
 ///////////////////////////////////////////////////////////////
 
-[[two-hours-intro,Zest™ in 2 hours]]
-= Zest™ in 2 hours =
+[[two-hours-intro,Polygene™ in 2 hours]]
+= Polygene™ in 2 hours =
 
 NOTE: This tutorial is not written yet. Learn how to contribute in <<community-docs>>.
 
-This introduction assumes that the "Zest™ in 10 minutes" and "Zest™ in 30 minutes" introductions has been read and
+This introduction assumes that the "Polygene™ in 10 minutes" and "Polygene™ in 30 minutes" introductions has been read and
 understood.
 
 In this introduction we will touch on the core concepts of UnitOfWork, Application structure and Bootstrap API.
@@ -34,7 +34,7 @@
 
 - Application Structure -
 
-    * There are one Application per Zest™ instance.
+    * There are one Application per Polygene™ instance.
 
     * An Application consists of one or more Layers.
 
diff --git a/tutorials/introduction/twominutes/build.gradle b/tutorials/introduction/twominutes/build.gradle
index 25a9ab5..ce71ed3 100644
--- a/tutorials/introduction/twominutes/build.gradle
+++ b/tutorials/introduction/twominutes/build.gradle
@@ -1,32 +1,35 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "A 2-minute Introduction Tutorial to Apache Zest™ in its simplest form."
+apply plugin: 'polygene-tutorial'
 
-jar { manifest { name = "Apache Zest™ Tutorial - 2 minute Introduction" }}
+description = "A 2-minute Introduction Tutorial to Apache Polygene™ in its simplest form."
+
+jar { manifest { name = "Apache Polygene™ Tutorial - 2 minute Introduction" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
+  implementation polygene.core.bootstrap
 
-  runtime(project(":org.qi4j.core:org.qi4j.core.runtime"))
+  runtimeOnly polygene.core.runtime
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
+  testImplementation polygene.core.testsupport
 
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  testRuntimeOnly libraries.logback
+}
diff --git a/tutorials/introduction/twominutes/src/docs/two-minutes.txt b/tutorials/introduction/twominutes/src/docs/two-minutes.txt
index be502d2..c8e3a41 100644
--- a/tutorials/introduction/twominutes/src/docs/two-minutes.txt
+++ b/tutorials/introduction/twominutes/src/docs/two-minutes.txt
@@ -17,22 +17,22 @@
  * under the License.
 ///////////////////////////////////////////////////////////////
 
-[[two-minutes-intro,Zest™ in 2 minutes]]
-= Zest™ in 2 minutes =
+[[two-minutes-intro,Polygene™ in 2 minutes]]
+= Polygene™ in 2 minutes =
 
 TIP: Theses tutorials are based on actual code found in the `tutorials/` directory of the
-https://zest.apache.org/download.html[Zest™ SDK sources]. You should start your favorite editor and find the code related to
+https://polygene.apache.org/download.html[Polygene™ SDK sources]. You should start your favorite editor and find the code related to
 this tutorial, run it and play with it.
 
-To show that Zest™ is not necessarily complex, not hard to get going with and easy to deploy, we are first showing the
+To show that Polygene™ is not necessarily complex, not hard to get going with and easy to deploy, we are first showing the
 classic HelloWorld, as small as it can get and still be Composite Oriented Programming and not only standard OOP.
 
 If you want to reproduce what's explained in this tutorial, remember to depend on the Core Runtime artifact that depends
-on Core API, Core SPI, Core Bootstrap and Core Functional & I/O APIs:
+on Core API, Core SPI, and Core Bootstrap:
 
 include::../../../../../core/runtime/build/docs/buildinfo/artifact.txt[]
 
-See the <<howto-depend-on-zest>> tutorial for details.
+See the <<howto-depend-on-polygene>> tutorial for details.
 
 Ready, Set, Go!
 
@@ -43,7 +43,7 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/twominutes/src/main/java/org/qi4j/demo/twominute/Speaker.java
+source=tutorials/introduction/twominutes/src/main/java/org/apache/polygene/demo/twominute/Speaker.java
 tag=documentation
 -----------
 
@@ -52,7 +52,7 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/twominutes/src/main/java/org/qi4j/demo/twominute/SpeakerMixin.java
+source=tutorials/introduction/twominutes/src/main/java/org/apache/polygene/demo/twominute/SpeakerMixin.java
 tag=documentation
 -----------
 
@@ -60,11 +60,11 @@
 
 [snippet,java]
 -----------
-source=tutorials/introduction/twominutes/src/main/java/org/qi4j/demo/twominute/Main.java
+source=tutorials/introduction/twominutes/src/main/java/org/apache/polygene/demo/twominute/Main.java
 tag=documentation
 -----------
 
-. The SingletonAssembler is a convenience class that creates a Zest™ Runtime instance and an application with one layer
+. The SingletonAssembler is a convenience class that creates a Polygene™ Runtime instance and an application with one layer
   and one module in it.
 
 . We declare a TransientComposite of type `Speaker`.
@@ -72,3 +72,5 @@
 . We create the Composite instance from the Module.
 
 *Done!*
+
+Next step, <<ten-minutes-intro>>.
diff --git a/tutorials/introduction/twominutes/src/main/java/org/apache/polygene/demo/twominute/Main.java b/tutorials/introduction/twominutes/src/main/java/org/apache/polygene/demo/twominute/Main.java
new file mode 100644
index 0000000..4ac39c9
--- /dev/null
+++ b/tutorials/introduction/twominutes/src/main/java/org/apache/polygene/demo/twominute/Main.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.demo.twominute;
+
+import org.apache.polygene.bootstrap.SingletonAssembler;
+
+// START SNIPPET: documentation
+public class Main
+{
+    public static void main( String[] args )
+        throws Exception
+    {
+        SingletonAssembler assembler = new SingletonAssembler(              // <1>
+            module -> module.transients( Speaker.class ) );                 // <2>
+        Speaker speaker = assembler.module().newTransient( Speaker.class ); // <3>
+        System.out.println( speaker.sayHello() );
+    }
+}
+// END SNIPPET: documentation
diff --git a/tutorials/introduction/twominutes/src/main/java/org/apache/polygene/demo/twominute/Speaker.java b/tutorials/introduction/twominutes/src/main/java/org/apache/polygene/demo/twominute/Speaker.java
new file mode 100644
index 0000000..f4d5d3e
--- /dev/null
+++ b/tutorials/introduction/twominutes/src/main/java/org/apache/polygene/demo/twominute/Speaker.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.demo.twominute;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+// START SNIPPET: documentation
+@Mixins( SpeakerMixin.class )
+public interface Speaker
+{
+    String sayHello();
+}
+// END SNIPPET: documentation
diff --git a/tutorials/introduction/twominutes/src/main/java/org/apache/polygene/demo/twominute/SpeakerMixin.java b/tutorials/introduction/twominutes/src/main/java/org/apache/polygene/demo/twominute/SpeakerMixin.java
new file mode 100644
index 0000000..59d6358
--- /dev/null
+++ b/tutorials/introduction/twominutes/src/main/java/org/apache/polygene/demo/twominute/SpeakerMixin.java
@@ -0,0 +1,32 @@
+/*
+ *  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.polygene.demo.twominute;
+
+// START SNIPPET: documentation
+public class SpeakerMixin
+    implements Speaker
+{
+    @Override
+    public String sayHello()
+    {
+        return "Hello, World!";
+    }
+}
+// END SNIPPET: documentation
diff --git a/tutorials/introduction/twominutes/src/main/java/org/qi4j/demo/twominute/Main.java b/tutorials/introduction/twominutes/src/main/java/org/qi4j/demo/twominute/Main.java
deleted file mode 100644
index 2de363a..0000000
--- a/tutorials/introduction/twominutes/src/main/java/org/qi4j/demo/twominute/Main.java
+++ /dev/null
@@ -1,44 +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.qi4j.demo.twominute;
-
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.bootstrap.SingletonAssembler;
-
-// START SNIPPET: documentation
-public class Main
-{
-    public static void main( String[] args )
-        throws Exception
-    {
-        SingletonAssembler assembler = new SingletonAssembler() // <1>
-        {
-            @Override
-            public void assemble( ModuleAssembly assembly )
-                throws AssemblyException
-            {
-                assembly.transients( Speaker.class );           // <2>
-            }
-        };
-        Speaker speaker = assembler.module().newTransient( Speaker.class ); // <3>
-        System.out.println( speaker.sayHello() );
-    }
-}
-// END SNIPPET: documentation
diff --git a/tutorials/introduction/twominutes/src/main/java/org/qi4j/demo/twominute/Speaker.java b/tutorials/introduction/twominutes/src/main/java/org/qi4j/demo/twominute/Speaker.java
deleted file mode 100644
index c1ac5c3..0000000
--- a/tutorials/introduction/twominutes/src/main/java/org/qi4j/demo/twominute/Speaker.java
+++ /dev/null
@@ -1,29 +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.qi4j.demo.twominute;
-
-import org.qi4j.api.mixin.Mixins;
-
-// START SNIPPET: documentation
-@Mixins( SpeakerMixin.class )
-public interface Speaker
-{
-    String sayHello();
-}
-// END SNIPPET: documentation
diff --git a/tutorials/introduction/twominutes/src/main/java/org/qi4j/demo/twominute/SpeakerMixin.java b/tutorials/introduction/twominutes/src/main/java/org/qi4j/demo/twominute/SpeakerMixin.java
deleted file mode 100644
index 1459619..0000000
--- a/tutorials/introduction/twominutes/src/main/java/org/qi4j/demo/twominute/SpeakerMixin.java
+++ /dev/null
@@ -1,31 +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.qi4j.demo.twominute;
-
-// START SNIPPET: documentation
-public class SpeakerMixin
-    implements Speaker
-{
-    @Override
-    public String sayHello()
-    {
-        return "Hello, World!";
-    }
-}
-// END SNIPPET: documentation
diff --git a/tutorials/services/build.gradle b/tutorials/services/build.gradle
index 5f8e4e6..6f7a084 100644
--- a/tutorials/services/build.gradle
+++ b/tutorials/services/build.gradle
@@ -1,31 +1,35 @@
 /*
- * 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
+ *  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
+ *       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.
+ *  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.
+ *
+ *
  */
 
-description = "Tutorial on how to use Apache Zest™ service concept."
+apply plugin: 'polygene-tutorial'
 
-jar { manifest { name = "Apache Zest™ Tutorial - Services" }}
+description = "Tutorial on how to use Apache Polygene™ service concept."
+
+jar { manifest { name = "Apache Polygene™ Tutorial - Services" } }
 
 dependencies {
-  compile(project(":org.qi4j.core:org.qi4j.core.bootstrap"))
+  implementation polygene.core.bootstrap
 
-  testCompile(project(":org.qi4j.core:org.qi4j.core.testsupport"))
+  runtimeOnly polygene.core.runtime
 
-  testRuntime(project(":org.qi4j.core:org.qi4j.core.runtime"))
-  testRuntime(libraries.logback)
-}
\ No newline at end of file
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}
diff --git a/tutorials/services/src/docs/step1.txt b/tutorials/services/src/docs/step1.txt
index 761d324..a048f3a 100644
--- a/tutorials/services/src/docs/step1.txt
+++ b/tutorials/services/src/docs/step1.txt
@@ -23,13 +23,13 @@
 In this tutorial we start with basic Java classes, to simulate a very simple Library where you can borrow
 and return books.
 
-Zest™ relies heavily on the use of interfaces. This makes it possible for an object
+Polygene™ relies heavily on the use of interfaces. This makes it possible for an object
 to externally implement a number of interfaces which internally is backed by a number
 of Mixins, some of which you may have written yourself, and some of which may have been
 reused. This is also true for services, which we are to cover in this tutorial.
 
 The first task is therefore to refactor the code so that the methods are implemented from an
-interface instead, and to essentially make the identical "application" into a Zest™ application.
+interface instead, and to essentially make the identical "application" into a Polygene™ application.
 We also want the Book to be a ValueComposite.
     
 Steps for this tutorial:
diff --git a/tutorials/services/src/docs/step2.txt b/tutorials/services/src/docs/step2.txt
index b3b9079..ad0e93c 100644
--- a/tutorials/services/src/docs/step2.txt
+++ b/tutorials/services/src/docs/step2.txt
@@ -21,7 +21,7 @@
 = Step 2 - Hooking into the Service Activation =
 
 Services can be "activated" and "passivated". Applications can be notified of this occurring
-by Zest™ runtime by assembling them with an Activator.
+by Polygene™ runtime by assembling them with an Activator.
 
 Activators methods are called around "activation" and "passivation": beforeActivation,
 afterActivation, beforeActivation, afterPassivation. The
diff --git a/tutorials/services/src/docs/step3.txt b/tutorials/services/src/docs/step3.txt
index f81f3e1..8516054 100644
--- a/tutorials/services/src/docs/step3.txt
+++ b/tutorials/services/src/docs/step3.txt
@@ -20,13 +20,13 @@
 [[tut-services-step3,Step 3 - Reading the Service Configuration]]
 = Step 3 - Reading the Service Configuration =
 
-Services typically have configuration. Configurations are directly supported in Zest™. A
+Services typically have configuration. Configurations are directly supported in Polygene™. A
 ConfigurationComposite is a subtype of EntityComposite. That is because
 configurations are stored in EntityStores, can be modified in runtime by client code and has
 the same semantics as regular entities.
 
-Zest™ also handles the bootstrapping of configuration for the services. If the ConfigurationComposite is
-not found in the configured entity store, then Zest™ will automatically locate a properties file for each
+Polygene™ also handles the bootstrapping of configuration for the services. If the ConfigurationComposite is
+not found in the configured entity store, then Polygene™ will automatically locate a properties file for each
 service instance, read those properties into a ConfigurationComposite instance, save that to the
 entity store and provide the values to the service. The properties file must be with the same name as
 the service instance with the extension "properties" in the same package as the service.
@@ -41,7 +41,7 @@
 - Delete the LibraryActivator and remove the @Activators annotation from the LibraryService and the corresponding createInitialData method.
 - In the LibraryMixin remove the member injection of the ValueBuilderFactory, and instead inject the ValueBuilderFactory in the constructor.
 - Inject the LibraryConfiguration via the constructor. The injection scope is @This.
-- Create a resource called LibraryService.properties and place it in the directory org/qi4j/tutorials/services/step4 in the classpath (for instance, src/main/resources ). Put something like this in:
+- Create a resource called LibraryService.properties and place it in the directory +org/apache/polygene/tutorials/services/step4+ in the classpath (for instance, src/main/resources ). Put something like this in:
     titles=Domain Driven Design, Pragmatic Programmer, Extreme Programming Explained
     authors=Eric Evans, Andy Hunt, Kent Beck
     #Number of copies of each book.
diff --git a/tutorials/services/src/docs/tut-services.txt b/tutorials/services/src/docs/tut-services.txt
index 8c85271..b8daf0c 100644
--- a/tutorials/services/src/docs/tut-services.txt
+++ b/tutorials/services/src/docs/tut-services.txt
@@ -21,13 +21,13 @@
 = Services Composites Tutorial =
 
 TIP: Theses tutorials are based on actual code found in the `tutorials/` directory of the
-http://zest.apache.org/download.html[Zest™ SDK sources]. You should start your favorite editor and find the code related to
+http://polygene.apache.org/download.html[Polygene™ SDK sources]. You should start your favorite editor and find the code related to
 this tutorial, run it and play with it.
 
 
 In this other set of tutorials it will be shown how to create and work with Service Composites, which are composites
 that extends from the ServiceComposite class. We will refactor one a very simple Library where you can borrow and
-return books to take advantage of the various features in Zest™. These refactorings will benefit from automatic Service
+return books to take advantage of the various features in Polygene™. These refactorings will benefit from automatic Service
 activation and Configuration Entities management.
 
 - <<tut-services-step1>>
@@ -41,11 +41,11 @@
 have followed the instructions.
 
 If you want to reproduce what's explained in this tutorial, remember to depend on the Core Runtime artifact that depends
-on Core API, Core SPI, Core Bootstrap and Core Functional & I/O APIs:
+on Core API, Core SPI, and Core Bootstrap:
 
 include::../../../../core/runtime/build/docs/buildinfo/artifact.txt[]
 
-See the <<howto-depend-on-zest>> tutorial for details.
+See the <<howto-depend-on-polygene>> tutorial for details.
 
 :leveloffset: 3
 
@@ -58,4 +58,3 @@
 :leveloffset: 3
 
 include::step3.txt[]
-
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step1/Book.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step1/Book.java
new file mode 100644
index 0000000..9a7597a
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step1/Book.java
@@ -0,0 +1,42 @@
+/*
+ *  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.polygene.tutorials.services.step1;
+
+public class Book
+{
+    private String title;
+    private String author;
+
+    public Book( String title, String author )
+    {
+        this.title = title;
+        this.author = author;
+    }
+
+    public String getTitle()
+    {
+        return title;
+    }
+
+    public String getAuthor()
+    {
+        return author;
+    }
+}
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step1/Consumer.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step1/Consumer.java
new file mode 100644
index 0000000..76e2231
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step1/Consumer.java
@@ -0,0 +1,41 @@
+/*
+ *  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.polygene.tutorials.services.step1;
+
+/**
+ * Simple service consumer
+ */
+public class Consumer
+{
+    Library library;
+
+    public Consumer( Library library )
+    {
+        this.library = library;
+    }
+
+    public void run()
+    {
+        Book book = library.borrowBook( "Eric Evans", "Domain-Driven Design" );
+        System.out.println( "Consumer got book: " + book.getTitle() );
+        library.returnBook( book );
+    }
+}
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step1/Library.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step1/Library.java
new file mode 100644
index 0000000..271f330
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step1/Library.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.tutorials.services.step1;
+
+/**
+ * Simple POJO service
+ */
+public class Library
+{
+    public Book borrowBook( String author, String title )
+    {
+        Book book = new Book( title, author );
+        System.out.println( "Book borrowed: " + book.getTitle() + " by " + book.getAuthor() );
+        return book;
+    }
+
+    public void returnBook( Book book )
+    {
+        System.out.println( "Book returned: " + book.getTitle() + " by " + book.getAuthor() );
+    }
+}
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step1/package.html b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step1/package.html
new file mode 100644
index 0000000..ccc52dd
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step1/package.html
@@ -0,0 +1,50 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<body>
+    <h1>Step 1 - Creating a ServiceComposite</h1>
+
+    <p>
+        In this tutorial we start with basic Java classes, to simulate a very simple Library where you can borrow
+        and return books.
+    </p>
+    <p>
+        Apache Polygene™ relies heavily on the use of interfaces. This makes it possible for an object
+        to externally implement a number of interfaces which internally is backed by a number
+        of Mixins, some of which you may have written yourself, and some of which may have been
+        reused. This is also true for services, which we are to cover in this tutorial.
+    </p>
+    <p>
+        The first task is therefore to refactor the code so that the methods are implemented from an
+        interface instead, and to essentially make the identical "application" into a Polygene™ application.
+        We also want the Book to be a ValueComposite.
+    </p>
+    
+    <p>Steps for this tutorial:</p>
+    <ol>
+        <li>Make the Book into a ValueComposite.</li>
+        <li>Make the Library an interface with the same methods. We call this a <i>Mixin Type</i></li>
+        <li>Create a LibraryMixin class, which implements the Library interface.</li>
+        <li>Create a LibraryService that binds the LibraryMixin.</li>
+        <li>The LibraryMixin will need to be injected with the <code>ValueBuilderFactory</code> in the
+            <code>@Structure</code> scope.
+        </li>
+    </ol>
+    
+</body>
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/Book.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/Book.java
new file mode 100644
index 0000000..a4367cf
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/Book.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.tutorials.services.step2;
+
+import org.apache.polygene.api.property.Property;
+
+public interface Book
+{
+    Property<String> title();
+
+    Property<String> author();
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/Consumer.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/Consumer.java
new file mode 100644
index 0000000..ad4c0dd
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/Consumer.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.tutorials.services.step2;
+
+import org.apache.polygene.api.injection.scope.Service;
+
+/**
+ * Simple service consumer. The service is injected using the @Service annotation.
+ */
+public class Consumer
+{
+    @Service
+    Library library;
+
+    public void run()
+    {
+        Book book = library.borrowBook( "Eric Evans", "Domain-Driven Design" );
+        System.out.println( "Consumer got book: " + book.title().get() + " by " + book.author().get() );
+        library.returnBook( book );
+    }
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/Library.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/Library.java
new file mode 100644
index 0000000..e749471
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/Library.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.tutorials.services.step2;
+
+public interface Library
+{
+    Book borrowBook( String author, String title );
+
+    void returnBook( Book book );
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/LibraryMixin.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/LibraryMixin.java
new file mode 100644
index 0000000..8249a85
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/LibraryMixin.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.tutorials.services.step2;
+
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+public class LibraryMixin
+    implements Library
+{
+    @Structure
+    ValueBuilderFactory factory;
+
+    @Override
+    public Book borrowBook( String author, String title )
+    {
+        ValueBuilder<Book> builder = factory.newValueBuilder( Book.class );
+        Book prototype = builder.prototype();
+        prototype.author().set( author );
+        prototype.title().set( title );
+        Book book = builder.newInstance();
+        System.out.println( "Book borrowed: " + book.title().get() + " by " + book.author().get() );
+        return book;
+    }
+
+    @Override
+    public void returnBook( Book book )
+    {
+        System.out.println( "Book returned: " + book.title().get() + " by " + book.author().get() );
+    }
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/LibraryService.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/LibraryService.java
new file mode 100644
index 0000000..70fdca7
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/LibraryService.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.tutorials.services.step2;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+@Mixins( LibraryMixin.class )
+public interface LibraryService
+    extends Library
+{
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/package.html b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/package.html
new file mode 100644
index 0000000..16945e5
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step2/package.html
@@ -0,0 +1,61 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<body>
+    <h1>Step 2 - Hooking into the Service Activation</h1>
+
+    <p>
+        Services can be "<i>activated</i>" and "<i>passivated</i>". Applications can be notified of this occurring
+        by Polygene™ runtime by assembling them with an <code>Activator</code>.
+    </p>
+    <p>
+        Activators methods are called around "<i>activation</i>" and "<i>passivation</i>": <code>beforeActivation</code>,
+        <code>afterActivation</code>, <code>beforeActivation</code>, <code>afterPassivation</code>. The
+        <code>ActivatorAdapter</code> class help you keeping your code short when you only need one or two hooks.
+    </p>
+    <p>
+        To showcase how this works, we refactor the code to create a number of copies of the books, to be lend out
+        upon call to the <code>borrowBook</code> method, which will return null if no copy is available. The book
+        copies are created in the <code>activate</code> method.
+    </p>
+
+    <p>Steps to do.</p>
+    <ol>
+        <li>
+            Add a <code>createInitialData</code> method to <code>Library</code>.
+        </li>
+        <li>
+            In the implementation, create a couple of books of each title and store each copy in a
+            <code>HashMap&lt;String,ArrayList&lt;Book&gt;&gt;</code>.
+        </li>
+        <li>
+            Write an <code>Activator&lt;ServiceReference&lt;Library&gt;&gt;</code> class extending
+            <code>ActivatorAdapter</code>.
+        </li>
+        <li>
+            Override the <code>afterActivation</code> method, use the <code>ServiceReference</code> to get a
+            handle on the <code>Library</code> and call its <code>createInitialData</code> method.
+        </li>
+        <li>
+            Add the <code>@Activators</code> annotation to the <code>LibraryService</code> declaring the new
+            <code>LibraryActivator</code>.
+        </li>
+    </ol>
+
+</body>
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/Book.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/Book.java
new file mode 100644
index 0000000..ff8e1e2
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/Book.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.tutorials.services.step3;
+
+import org.apache.polygene.api.property.Property;
+
+public interface Book
+{
+    Property<String> title();
+
+    Property<String> author();
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/Consumer.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/Consumer.java
new file mode 100644
index 0000000..07fa471
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/Consumer.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.tutorials.services.step3;
+
+import org.apache.polygene.api.injection.scope.Service;
+
+/**
+ * Simple service consumer. The service is injected using the @Service annotation.
+ */
+public class Consumer
+{
+    @Service
+    Library library;
+
+    public void run()
+    {
+        Book book = library.borrowBook( "Eric Evans", "Domain Driven Design" );
+        System.out.println( "Consumer got book: " + book.title().get() + " by " + book.author().get() );
+        library.returnBook( book );
+    }
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/Library.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/Library.java
new file mode 100644
index 0000000..33e85e9
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/Library.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.tutorials.services.step3;
+
+public interface Library
+{
+    void createInitialData();
+    
+    Book borrowBook( String author, String title );
+
+    void returnBook( Book book );
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/LibraryActivator.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/LibraryActivator.java
new file mode 100644
index 0000000..80253ce
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/LibraryActivator.java
@@ -0,0 +1,36 @@
+/*
+ *  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.polygene.tutorials.services.step3;
+
+import org.apache.polygene.api.activation.ActivatorAdapter;
+import org.apache.polygene.api.service.ServiceReference;
+
+public class LibraryActivator
+        extends ActivatorAdapter<ServiceReference<Library>>
+{
+
+    @Override
+    public void afterActivation( ServiceReference<Library> activated )
+            throws Exception
+    {
+        activated.get().createInitialData();
+    }
+
+}
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/LibraryMixin.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/LibraryMixin.java
new file mode 100644
index 0000000..f1ea6e2
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/LibraryMixin.java
@@ -0,0 +1,103 @@
+/*
+ *  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.polygene.tutorials.services.step3;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+public class LibraryMixin
+    implements Library
+{
+    @Structure
+    ValueBuilderFactory factory;
+    private HashMap<String, ArrayList<Book>> books;
+
+    public LibraryMixin()
+    {
+        books = new HashMap<>();
+    }
+
+    @Override
+    public void createInitialData()
+    {
+        createBook( "Eric Evans", "Domain Driven Design", 2 );
+        createBook( "Andy Hunt", "Pragmatic Programmer", 3 );
+        createBook( "Kent Beck", "Extreme Programming Explained", 5 );
+    }
+
+    @Override
+    public Book borrowBook( String author, String title )
+    {
+        String key = constructKey( author, title );
+        ArrayList<Book> copies = books.get( key );
+        if( copies == null )
+        {
+            System.out.println( "Book not available." );
+            return null; // Indicate that book is not available.
+        }
+        Book book = copies.remove( 0 );
+        if( book == null )
+        {
+            System.out.println( "Book not available." );
+            return null; // Indicate that book is not available.
+        }
+        System.out.println( "Book borrowed: " + book.title().get() + " by " + book.author().get() );
+        return book;
+    }
+
+    @Override
+    public void returnBook( Book book )
+    {
+        System.out.println( "Book returned: " + book.title().get() + " by " + book.author().get() );
+        String key = constructKey( book.author().get(), book.title().get() );
+        ArrayList<Book> copies = books.get( key );
+        if( copies == null )
+        {
+            throw new IllegalStateException( "Book " + book + " was not borrowed here." );
+        }
+        copies.add( book );
+    }
+
+    private void createBook( String author, String title, int copies )
+    {
+        ArrayList<Book> bookCopies = new ArrayList<>();
+        String key = constructKey( author, title );
+        books.put( key, bookCopies );
+
+        for( int i = 0; i < copies; i++ )
+        {
+            ValueBuilder<Book> builder = factory.newValueBuilder( Book.class );
+            Book prototype = builder.prototype();
+            prototype.author().set( author );
+            prototype.title().set( title );
+
+            Book book = builder.newInstance();
+            bookCopies.add( book );
+        }
+    }
+
+    private String constructKey( String author, String title )
+    {
+        return author + "::" + title;
+    }
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/LibraryService.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/LibraryService.java
new file mode 100644
index 0000000..d91ad88
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/LibraryService.java
@@ -0,0 +1,30 @@
+/*
+ *  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.polygene.tutorials.services.step3;
+
+import org.apache.polygene.api.activation.Activators;
+import org.apache.polygene.api.mixin.Mixins;
+
+@Mixins( LibraryMixin.class )
+@Activators( LibraryActivator.class )
+public interface LibraryService
+    extends Library
+{
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/package.html b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/package.html
new file mode 100644
index 0000000..288d2ae
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step3/package.html
@@ -0,0 +1,77 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<body>
+    <h1>Step 3 - Reading the Service Configuration</h1>
+
+    <p>
+        Services typically have configuration. Configurations are directly supported in Polygene™. A
+        <code>ConfigurationComposite</code> is a subtype of <code>EntityComposite</code>. That is because
+        configurations are stored in EntityStores, can be modified in runtime by client code and has
+        the same semantics as regular entities.
+    </p>
+    <p>
+        Polygene™ also handles the bootstrapping of configuration for the services. If the ConfigurationComposite is
+        not found in the configured entity store, then Polygene™ will automatically locate a properties file for each
+        service instance, read those properties into a ConfigurationComposite instance, save that to the
+        entity store and provide the values to the service. The properties file must be with the same name as
+        the service instance with the extension <code>"properties"</code> in the same package as the service.
+    </p>
+    <p>
+        For this exercise, create a <code>LibraryConfiguration</code> that contains "titles", "authors" and "copies".
+        The first two are a string with a comma separated list, and the "copies" is just an Integer with how many
+        copies are made of each title.
+    </p>
+
+    <p>Steps to do.</p>
+    <ol>
+        <li>Create a <code>LibraryConfiguration</code> interface that extends <code>ConfigurationComposite</code>,
+            and has three <code>Property</code> instances named <code>"titles"</code>, <code>"authors"</code> and
+            <code>"copies"</code>, where the first two are of <code>String</code> type and the last is of
+            <code>Integer</code> type.
+        </li>
+        <li>Delete the <code>LibraryActivator</code> and remove the <code>@Activators</code> annotation from the
+            <code>LibraryService</code> and the corresponding <code>createInitialData</code> method.
+        </li>
+        <li>
+            In the <code>LibraryMixin</code> remove the member injection of the <code>ValueBuilderFactory</code>, and
+            instead inject the <code>ValueBuilderFactory</code> in the constructor.
+        </li>
+        <li>
+            Inject the <code>LibraryConfiguration</code> via the constructor. The injection scope is <code>@This</code>.
+        </li>
+        <li>
+            Create a resource called <code>LibraryService.properties</code> and place it in the directory
+            <code>org/apache/polygene/tutorials/services/step4</code> in the classpath (for instance, <code>src/main/resources</code>
+            ).
+            Put something like;
+            <span class="javaxcode"><pre>titles=Domain Driven Design, Pragmatic Programmer, Extreme Programming Explained
+authors=Eric Evans, Andy Hunt, Kent Beck
+
+#Number of copies of each book.
+copies=3
+                </pre>
+            </span>
+            in this file.
+        </li>
+        <li>
+            Load initial data from the <code>LibraryConfiguration</code> in the <code>LibraryMixin</code> constructor.
+        </li>
+    </ol>
+</body>
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/Book.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/Book.java
new file mode 100644
index 0000000..ae73bd3
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/Book.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.tutorials.services.step4;
+
+import org.apache.polygene.api.property.Property;
+
+public interface Book
+{
+    Property<String> title();
+
+    Property<String> author();
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/Consumer.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/Consumer.java
new file mode 100644
index 0000000..d39e740
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/Consumer.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.tutorials.services.step4;
+
+import org.apache.polygene.api.injection.scope.Service;
+
+/**
+ * Simple service consumer. The service is injected using the @Service annotation.
+ */
+public class Consumer
+{
+    @Service
+    Library library;
+
+    public void run()
+    {
+        Book book = library.borrowBook( "Eric Evans", "Domain Driven Design" );
+        System.out.println( "Consumer got book: " + book.title().get() + " by " + book.author().get() );
+        library.returnBook( book );
+    }
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/Library.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/Library.java
new file mode 100644
index 0000000..1451a29
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/Library.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.tutorials.services.step4;
+
+public interface Library
+{
+    Book borrowBook( String author, String title );
+
+    void returnBook( Book book );
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/LibraryConfiguration.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/LibraryConfiguration.java
new file mode 100644
index 0000000..65a81c0
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/LibraryConfiguration.java
@@ -0,0 +1,31 @@
+/*
+ *  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.polygene.tutorials.services.step4;
+
+import org.apache.polygene.api.property.Property;
+
+public interface LibraryConfiguration
+{
+    Property<String> titles();
+
+    Property<String> authors();
+
+    Property<Integer> copies();
+}
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/LibraryMixin.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/LibraryMixin.java
new file mode 100644
index 0000000..27389a5
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/LibraryMixin.java
@@ -0,0 +1,108 @@
+/*
+ *  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.polygene.tutorials.services.step4;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+public class LibraryMixin
+    implements Library
+{
+    private HashMap<String, ArrayList<Book>> books;
+
+    public LibraryMixin( @This Configuration<LibraryConfiguration> config, @Structure ValueBuilderFactory factory )
+    {
+        books = new HashMap<>();
+        String titles = config.get().titles().get();
+        String authors = config.get().authors().get();
+        int copies = config.get().copies().get();
+        StringTokenizer titlesSt = new StringTokenizer( titles, ",", false );
+        StringTokenizer authorSt = new StringTokenizer( authors, ",", false );
+        while( titlesSt.hasMoreTokens() )
+        {
+            String title = titlesSt.nextToken();
+            String author = authorSt.nextToken();
+            createBook( factory, author, title, copies );
+        }
+    }
+
+    @Override
+    public Book borrowBook( String author, String title )
+    {
+        String key = constructKey( author, title );
+        ArrayList<Book> copies = books.get( key );
+        if( copies == null )
+        {
+            System.out.println( "Book not available." );
+            return null; // Indicate that book is not available.
+        }
+        Book book = copies.remove( 0 );
+        if( book == null )
+        {
+            System.out.println( "Book not available." );
+            return null; // Indicate that book is not available.
+        }
+        System.out.println( "Book borrowed: " + book.title().get() + " by " + book.author().get() );
+        return book;
+    }
+
+    @Override
+    public void returnBook( Book book )
+    {
+        System.out.println( "Book returned: " + book.title().get() + " by " + book.author().get() );
+        String key = constructKey( book.author().get(), book.title().get() );
+        ArrayList<Book> copies = books.get( key );
+        if( copies == null )
+        {
+            throw new IllegalStateException( "Book " + book + " was not borrowed here." );
+        }
+        copies.add( book );
+    }
+
+    private void createBook( ValueBuilderFactory factory, String author, String title, int copies )
+    {
+        ArrayList<Book> bookCopies = new ArrayList<>();
+        String key = constructKey( author, title );
+        books.put( key, bookCopies );
+
+        for( int i = 0; i < copies; i++ )
+        {
+            ValueBuilder<Book> builder = factory.newValueBuilder( Book.class );
+            Book prototype = builder.prototype();
+            prototype.author().set( author );
+            prototype.title().set( title );
+
+            Book book = builder.newInstance();
+            System.out.println( "Book created: " + book );
+            bookCopies.add( book );
+        }
+    }
+
+    private String constructKey( String author, String title )
+    {
+        return author + "::" + title;
+    }
+}
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/LibraryService.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/LibraryService.java
new file mode 100644
index 0000000..c9d6855
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step4/LibraryService.java
@@ -0,0 +1,28 @@
+/*
+ *  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.polygene.tutorials.services.step4;
+
+import org.apache.polygene.api.mixin.Mixins;
+
+@Mixins( LibraryMixin.class )
+public interface LibraryService
+    extends Library
+{
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step5/Book.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step5/Book.java
new file mode 100644
index 0000000..ae958f9
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step5/Book.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.tutorials.services.step5;
+
+import org.apache.polygene.api.property.Property;
+
+public interface Book
+{
+    Property<String> title();
+
+    Property<String> author();
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step5/Consumer.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step5/Consumer.java
new file mode 100644
index 0000000..817e9c3
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step5/Consumer.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.tutorials.services.step5;
+
+import org.apache.polygene.api.injection.scope.Service;
+
+/**
+ * Simple service consumer. The service is injected using the @Service annotation.
+ */
+public class Consumer
+{
+    @Service
+    Library library;
+
+    public void run()
+    {
+        Book book = library.borrowBook( "Eric Evans", "Domain Driven Design" );
+        System.out.println( "Consumer got book: " + book.title().get() + " by " + book.author().get() );
+        library.returnBook( book );
+    }
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step5/Library.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step5/Library.java
new file mode 100644
index 0000000..db43b77
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step5/Library.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.tutorials.services.step5;
+
+public interface Library
+{
+    Book borrowBook( String author, String title );
+
+    void returnBook( Book book );
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step5/LibraryService.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step5/LibraryService.java
new file mode 100644
index 0000000..e1d102e
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step5/LibraryService.java
@@ -0,0 +1,127 @@
+/*
+ *  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.polygene.tutorials.services.step5;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+@Mixins( LibraryService.LibraryMixin.class )
+public interface LibraryService
+    extends Library
+{
+    interface LibraryConfiguration
+    {
+        Property<String> titles();
+
+        Property<String> authors();
+
+        Property<Integer> copies();
+    }
+
+    class LibraryMixin
+        implements Library
+    {
+
+        private HashMap<String, ArrayList<Book>> books;
+
+        public LibraryMixin( @This Configuration<LibraryConfiguration> config,
+                             @Structure ValueBuilderFactory factory
+        )
+        {
+            books = new HashMap<>();
+            String titles = config.get().titles().get();
+            String authors = config.get().authors().get();
+            int copies = config.get().copies().get();
+            StringTokenizer titlesSt = new StringTokenizer( titles, ",", false );
+            StringTokenizer authorSt = new StringTokenizer( authors, ",", false );
+            while( titlesSt.hasMoreTokens() )
+            {
+                String title = titlesSt.nextToken();
+                String author = authorSt.nextToken();
+                createBook( factory, author, title, copies );
+            }
+        }
+
+        @Override
+        public Book borrowBook( String author, String title )
+        {
+            String key = constructKey( author, title );
+            ArrayList<Book> copies = books.get( key );
+            if( copies == null )
+            {
+                System.out.println( "Book not available." );
+                return null; // Indicate that book is not available.
+            }
+            Book book = copies.remove( 0 );
+            if( book == null )
+            {
+                System.out.println( "Book not available." );
+                return null; // Indicate that book is not available.
+            }
+            System.out.println( "Book borrowed: " + book.title().get() + " by " + book.author().get() );
+            return book;
+        }
+
+        @Override
+        public void returnBook( Book book )
+        {
+            System.out.println( "Book returned: " + book.title().get() + " by " + book.author().get() );
+            String key = constructKey( book.author().get(), book.title().get() );
+            ArrayList<Book> copies = books.get( key );
+            if( copies == null )
+            {
+                throw new IllegalStateException( "Book " + book + " was not borrowed here." );
+            }
+            copies.add( book );
+        }
+
+        private void createBook( ValueBuilderFactory factory, String author, String title, int copies )
+        {
+            ArrayList<Book> bookCopies = new ArrayList<>();
+            String key = constructKey( author, title );
+            books.put( key, bookCopies );
+
+            for( int i = 0; i < copies; i++ )
+            {
+                ValueBuilder<Book> builder = factory.newValueBuilder( Book.class );
+                Book prototype = builder.prototype();
+                prototype.author().set( author );
+                prototype.title().set( title );
+
+                Book book = builder.newInstance();
+                System.out.println( "Book created: " + book );
+                bookCopies.add( book );
+            }
+        }
+
+        private String constructKey( String author, String title )
+        {
+            return author + "::" + title;
+        }
+    }
+}
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step6/Book.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step6/Book.java
new file mode 100644
index 0000000..964ccb7
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step6/Book.java
@@ -0,0 +1,29 @@
+/*
+ *  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.polygene.tutorials.services.step6;
+
+import org.apache.polygene.api.property.Property;
+
+public interface Book
+{
+    Property<String> title();
+
+    Property<String> author();
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step6/Consumer.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step6/Consumer.java
new file mode 100644
index 0000000..b01a3fd
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step6/Consumer.java
@@ -0,0 +1,39 @@
+/*
+ *  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.polygene.tutorials.services.step6;
+
+import org.apache.polygene.api.injection.scope.Service;
+
+/**
+ * Simple service consumer. The service is injected using the @Service annotation.
+ */
+public class Consumer
+{
+    @Service
+    Library library;
+
+    public void run()
+    {
+        Book book = library.borrowBook( "Eric Evans", "Domain Driven Design" );
+        System.out.println( "Consumer got book: " + book.title().get() + " by " + book.author().get() );
+        library.returnBook( book );
+    }
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step6/Library.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step6/Library.java
new file mode 100644
index 0000000..6a1c4af
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step6/Library.java
@@ -0,0 +1,27 @@
+/*
+ *  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.polygene.tutorials.services.step6;
+
+public interface Library
+{
+    Book borrowBook( String author, String title );
+
+    void returnBook( Book book );
+}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step6/LibraryService.java b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step6/LibraryService.java
new file mode 100644
index 0000000..e926427
--- /dev/null
+++ b/tutorials/services/src/main/java/org/apache/polygene/tutorials/services/step6/LibraryService.java
@@ -0,0 +1,120 @@
+/*
+ *  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.polygene.tutorials.services.step6;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+
+public class LibraryService
+    implements Library
+{
+    public interface LibraryConfiguration
+    {
+        Property<String> titles();
+
+        Property<String> authors();
+
+        Property<Integer> copies();
+    }
+
+    private HashMap<String, ArrayList<Book>> books;
+
+    public LibraryService( @This Configuration<LibraryConfiguration> config,
+                         @Structure ValueBuilderFactory factory
+    )
+    {
+        books = new HashMap<>();
+        String titles = config.get().titles().get();
+        String authors = config.get().authors().get();
+        int copies = config.get().copies().get();
+        StringTokenizer titlesSt = new StringTokenizer( titles, ",", false );
+        StringTokenizer authorSt = new StringTokenizer( authors, ",", false );
+        while( titlesSt.hasMoreTokens() )
+        {
+            String title = titlesSt.nextToken();
+            String author = authorSt.nextToken();
+            createBook( factory, author, title, copies );
+        }
+    }
+
+    @Override
+    public Book borrowBook( String author, String title )
+    {
+        String key = constructKey( author, title );
+        ArrayList<Book> copies = books.get( key );
+        if( copies == null )
+        {
+            System.out.println( "Book not available." );
+            return null; // Indicate that book is not available.
+        }
+        Book book = copies.remove( 0 );
+        if( book == null )
+        {
+            System.out.println( "Book not available." );
+            return null; // Indicate that book is not available.
+        }
+        System.out.println( "Book borrowed: " + book.title().get() + " by " + book.author().get() );
+        return book;
+    }
+
+    @Override
+    public void returnBook( Book book )
+    {
+        System.out.println( "Book returned: " + book.title().get() + " by " + book.author().get() );
+        String key = constructKey( book.author().get(), book.title().get() );
+        ArrayList<Book> copies = books.get( key );
+        if( copies == null )
+        {
+            throw new IllegalStateException( "Book " + book + " was not borrowed here." );
+        }
+        copies.add( book );
+    }
+
+    private void createBook( ValueBuilderFactory factory, String author, String title, int copies )
+    {
+        ArrayList<Book> bookCopies = new ArrayList<>();
+        String key = constructKey( author, title );
+        books.put( key, bookCopies );
+
+        for( int i = 0; i < copies; i++ )
+        {
+            ValueBuilder<Book> builder = factory.newValueBuilder( Book.class );
+            Book prototype = builder.prototype();
+            prototype.author().set( author );
+            prototype.title().set( title );
+
+            Book book = builder.newInstance();
+            System.out.println( "Book created: " + book );
+            bookCopies.add( book );
+        }
+    }
+
+    private String constructKey( String author, String title )
+    {
+        return author + "::" + title;
+    }
+}
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step1/Book.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step1/Book.java
deleted file mode 100644
index 69cbde3..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step1/Book.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.services.step1;
-
-public class Book
-{
-    private String title;
-    private String author;
-
-    public Book( String title, String author )
-    {
-        this.title = title;
-        this.author = author;
-    }
-
-    public String getTitle()
-    {
-        return title;
-    }
-
-    public String getAuthor()
-    {
-        return author;
-    }
-}
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step1/Consumer.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step1/Consumer.java
deleted file mode 100644
index 83a22dc..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step1/Consumer.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.tutorials.services.step1;
-
-/**
- * Simple service consumer
- */
-public class Consumer
-{
-    Library library;
-
-    public Consumer( Library library )
-    {
-        this.library = library;
-    }
-
-    public void run()
-    {
-        Book book = library.borrowBook( "Eric Evans", "Domain-Driven Design" );
-        System.out.println( "Consumer got book: " + book.getTitle() );
-        library.returnBook( book );
-    }
-}
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step1/Library.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step1/Library.java
deleted file mode 100644
index 24d9f65..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step1/Library.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.tutorials.services.step1;
-
-/**
- * Simple POJO service
- */
-public class Library
-{
-    public Book borrowBook( String author, String title )
-    {
-        Book book = new Book( title, author );
-        System.out.println( "Book borrowed: " + book.getTitle() + " by " + book.getAuthor() );
-        return book;
-    }
-
-    public void returnBook( Book book )
-    {
-        System.out.println( "Book returned: " + book.getTitle() + " by " + book.getAuthor() );
-    }
-}
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step1/package.html b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step1/package.html
deleted file mode 100644
index a7b7805..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step1/package.html
+++ /dev/null
@@ -1,47 +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.
--->
-<body>
-    <h1>Step 1 - Creating a ServiceComposite</h1>
-
-    <p>
-        In this tutorial we start with basic Java classes, to simulate a very simple Library where you can borrow
-        and return books.
-    </p>
-    <p>
-        Apache Zest™ relies heavily on the use of interfaces. This makes it possible for an object
-        to externally implement a number of interfaces which internally is backed by a number
-        of Mixins, some of which you may have written yourself, and some of which may have been
-        reused. This is also true for services, which we are to cover in this tutorial.
-    </p>
-    <p>
-        The first task is therefore to refactor the code so that the methods are implemented from an
-        interface instead, and to essentially make the identical "application" into a Zest™ application.
-        We also want the Book to be a ValueComposite.
-    </p>
-    
-    <p>Steps for this tutorial:</p>
-    <ol>
-        <li>Make the Book into a ValueComposite.</li>
-        <li>Make the Library an interface with the same methods. We call this a <i>Mixin Type</i></li>
-        <li>Create a LibraryMixin class, which implements the Library interface.</li>
-        <li>Create a LibraryService that binds the LibraryMixin.</li>
-        <li>The LibraryMixin will need to be injected with the <code>ValueBuilderFactory</code> in the
-            <code>@Structure</code> scope.
-        </li>
-    </ol>
-    
-</body>
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/Book.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/Book.java
deleted file mode 100644
index 38780e3..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/Book.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.services.step2;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-public interface Book
-    extends ValueComposite
-{
-    Property<String> title();
-
-    Property<String> author();
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/Consumer.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/Consumer.java
deleted file mode 100644
index f1a9e43..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/Consumer.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.tutorials.services.step2;
-
-import org.qi4j.api.injection.scope.Service;
-
-/**
- * Simple service consumer. The service is injected using the @Service annotation.
- */
-public class Consumer
-{
-    @Service
-    Library library;
-
-    public void run()
-    {
-        Book book = library.borrowBook( "Eric Evans", "Domain-Driven Design" );
-        System.out.println( "Consumer got book: " + book.title().get() + " by " + book.author().get() );
-        library.returnBook( book );
-    }
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/Library.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/Library.java
deleted file mode 100644
index 6a13bb4..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/Library.java
+++ /dev/null
@@ -1,26 +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.qi4j.tutorials.services.step2;
-
-public interface Library
-{
-    Book borrowBook( String author, String title );
-
-    void returnBook( Book book );
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/LibraryMixin.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/LibraryMixin.java
deleted file mode 100644
index 2160dc9..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/LibraryMixin.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.services.step2;
-
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-
-public class LibraryMixin
-    implements Library
-{
-    @Structure
-    ValueBuilderFactory factory;
-
-    @Override
-    public Book borrowBook( String author, String title )
-    {
-        ValueBuilder<Book> builder = factory.newValueBuilder( Book.class );
-        Book prototype = builder.prototype();
-        prototype.author().set( author );
-        prototype.title().set( title );
-        Book book = builder.newInstance();
-        System.out.println( "Book borrowed: " + book.title().get() + " by " + book.author().get() );
-        return book;
-    }
-
-    @Override
-    public void returnBook( Book book )
-    {
-        System.out.println( "Book returned: " + book.title().get() + " by " + book.author().get() );
-    }
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/LibraryService.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/LibraryService.java
deleted file mode 100644
index d92c0d8..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/LibraryService.java
+++ /dev/null
@@ -1,28 +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.qi4j.tutorials.services.step2;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-@Mixins( LibraryMixin.class )
-public interface LibraryService
-    extends Library, ServiceComposite
-{
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/package.html b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/package.html
deleted file mode 100644
index 860150a..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step2/package.html
+++ /dev/null
@@ -1,58 +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.
--->
-<body>
-    <h1>Step 2 - Hooking into the Service Activation</h1>
-
-    <p>
-        Services can be "<i>activated</i>" and "<i>passivated</i>". Applications can be notified of this occurring
-        by Zest™ runtime by assembling them with an <code>Activator</code>.
-    </p>
-    <p>
-        Activators methods are called around "<i>activation</i>" and "<i>passivation</i>": <code>beforeActivation</code>,
-        <code>afterActivation</code>, <code>beforeActivation</code>, <code>afterPassivation</code>. The
-        <code>ActivatorAdapter</code> class help you keeping your code short when you only need one or two hooks.
-    </p>
-    <p>
-        To showcase how this works, we refactor the code to create a number of copies of the books, to be lend out
-        upon call to the <code>borrowBook</code> method, which will return null if no copy is available. The book
-        copies are created in the <code>activate</code> method.
-    </p>
-
-    <p>Steps to do.</p>
-    <ol>
-        <li>
-            Add a <code>createInitialData</code> method to <code>Library</code>.
-        </li>
-        <li>
-            In the implementation, create a couple of books of each title and store each copy in a
-            <code>HashMap&lt;String,ArrayList&lt;Book&gt;&gt;</code>.
-        </li>
-        <li>
-            Write an <code>Activator&lt;ServiceReference&lt;Library&gt;&gt;</code> class extending
-            <code>ActivatorAdapter</code>.
-        </li>
-        <li>
-            Override the <code>afterActivation</code> method, use the <code>ServiceReference</code> to get a
-            handle on the <code>Library</code> and call its <code>createInitialData</code> method.
-        </li>
-        <li>
-            Add the <code>@Activators</code> annotation to the <code>LibraryService</code> declaring the new
-            <code>LibraryActivator</code>.
-        </li>
-    </ol>
-
-</body>
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/Book.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/Book.java
deleted file mode 100644
index a693bfb..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/Book.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.services.step3;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-public interface Book
-    extends ValueComposite
-{
-    Property<String> title();
-
-    Property<String> author();
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/Consumer.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/Consumer.java
deleted file mode 100644
index 95c5264..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/Consumer.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
- *
- * Licensed 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.qi4j.tutorials.services.step3;
-
-import org.qi4j.api.injection.scope.Service;
-
-/**
- * Simple service consumer. The service is injected using the @Service annotation.
- */
-public class Consumer
-{
-    @Service
-    Library library;
-
-    public void run()
-    {
-        Book book = library.borrowBook( "Eric Evans", "Domain Driven Design" );
-        System.out.println( "Consumer got book: " + book.title().get() + " by " + book.author().get() );
-        library.returnBook( book );
-    }
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/Library.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/Library.java
deleted file mode 100644
index b9516db..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/Library.java
+++ /dev/null
@@ -1,28 +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.qi4j.tutorials.services.step3;
-
-public interface Library
-{
-    void createInitialData();
-    
-    Book borrowBook( String author, String title );
-
-    void returnBook( Book book );
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/LibraryActivator.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/LibraryActivator.java
deleted file mode 100644
index 5fe165c..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/LibraryActivator.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.tutorials.services.step3;
-
-import org.qi4j.api.activation.ActivatorAdapter;
-import org.qi4j.api.service.ServiceReference;
-
-public class LibraryActivator
-        extends ActivatorAdapter<ServiceReference<Library>>
-{
-
-    @Override
-    public void afterActivation( ServiceReference<Library> activated )
-            throws Exception
-    {
-        activated.get().createInitialData();
-    }
-
-}
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/LibraryMixin.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/LibraryMixin.java
deleted file mode 100644
index cdac424..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/LibraryMixin.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- * Copyright 2012 Paul Merlin.
- *
- * Licensed  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.qi4j.tutorials.services.step3;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-
-public class LibraryMixin
-    implements Library
-{
-    @Structure
-    ValueBuilderFactory factory;
-    private HashMap<String, ArrayList<Book>> books;
-
-    public LibraryMixin()
-    {
-        books = new HashMap<String, ArrayList<Book>>();
-    }
-
-    @Override
-    public void createInitialData()
-    {
-        createBook( "Eric Evans", "Domain Driven Design", 2 );
-        createBook( "Andy Hunt", "Pragmatic Programmer", 3 );
-        createBook( "Kent Beck", "Extreme Programming Explained", 5 );
-    }
-
-    @Override
-    public Book borrowBook( String author, String title )
-    {
-        String key = constructKey( author, title );
-        ArrayList<Book> copies = books.get( key );
-        if( copies == null )
-        {
-            System.out.println( "Book not available." );
-            return null; // Indicate that book is not available.
-        }
-        Book book = copies.remove( 0 );
-        if( book == null )
-        {
-            System.out.println( "Book not available." );
-            return null; // Indicate that book is not available.
-        }
-        System.out.println( "Book borrowed: " + book.title().get() + " by " + book.author().get() );
-        return book;
-    }
-
-    @Override
-    public void returnBook( Book book )
-    {
-        System.out.println( "Book returned: " + book.title().get() + " by " + book.author().get() );
-        String key = constructKey( book.author().get(), book.title().get() );
-        ArrayList<Book> copies = books.get( key );
-        if( copies == null )
-        {
-            throw new IllegalStateException( "Book " + book + " was not borrowed here." );
-        }
-        copies.add( book );
-    }
-
-    private void createBook( String author, String title, int copies )
-    {
-        ArrayList<Book> bookCopies = new ArrayList<Book>();
-        String key = constructKey( author, title );
-        books.put( key, bookCopies );
-
-        for( int i = 0; i < copies; i++ )
-        {
-            ValueBuilder<Book> builder = factory.newValueBuilder( Book.class );
-            Book prototype = builder.prototype();
-            prototype.author().set( author );
-            prototype.title().set( title );
-
-            Book book = builder.newInstance();
-            bookCopies.add( book );
-        }
-    }
-
-    private String constructKey( String author, String title )
-    {
-        return author + "::" + title;
-    }
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/LibraryService.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/LibraryService.java
deleted file mode 100644
index ba03666..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/LibraryService.java
+++ /dev/null
@@ -1,30 +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.qi4j.tutorials.services.step3;
-
-import org.qi4j.api.activation.Activators;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-@Mixins( LibraryMixin.class )
-@Activators( LibraryActivator.class )
-public interface LibraryService
-    extends Library, ServiceComposite
-{
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/package.html b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/package.html
deleted file mode 100644
index 37436d9..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step3/package.html
+++ /dev/null
@@ -1,74 +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.
--->
-<body>
-    <h1>Step 3 - Reading the Service Configuration</h1>
-
-    <p>
-        Services typically have configuration. Configurations are directly supported in Zest™. A
-        <code>ConfigurationComposite</code> is a subtype of <code>EntityComposite</code>. That is because
-        configurations are stored in EntityStores, can be modified in runtime by client code and has
-        the same semantics as regular entities.
-    </p>
-    <p>
-        Zest™ also handles the bootstrapping of configuration for the services. If the ConfigurationComposite is
-        not found in the configured entity store, then Zest™ will automatically locate a properties file for each
-        service instance, read those properties into a ConfigurationComposite instance, save that to the
-        entity store and provide the values to the service. The properties file must be with the same name as
-        the service instance with the extension <code>"properties"</code> in the same package as the service.
-    </p>
-    <p>
-        For this exercise, create a <code>LibraryConfiguration</code> that contains "titles", "authors" and "copies".
-        The first two are a string with a comma separated list, and the "copies" is just an Integer with how many
-        copies are made of each title.
-    </p>
-
-    <p>Steps to do.</p>
-    <ol>
-        <li>Create a <code>LibraryConfiguration</code> interface that extends <code>ConfigurationComposite</code>,
-            and has three <code>Property</code> instances named <code>"titles"</code>, <code>"authors"</code> and
-            <code>"copies"</code>, where the first two are of <code>String</code> type and the last is of
-            <code>Integer</code> type.
-        </li>
-        <li>Delete the <code>LibraryActivator</code> and remove the <code>@Activators</code> annotation from the
-            <code>LibraryService</code> and the corresponding <code>createInitialData</code> method.
-        </li>
-        <li>
-            In the <code>LibraryMixin</code> remove the member injection of the <code>ValueBuilderFactory</code>, and
-            instead inject the <code>ValueBuilderFactory</code> in the constructor.
-        </li>
-        <li>
-            Inject the <code>LibraryConfiguration</code> via the constructor. The injection scope is <code>@This</code>.
-        </li>
-        <li>
-            Create a resource called <code>LibraryService.properties</code> and place it in the directory
-            <code>org/qi4j/tutorials/services/step4</code> in the classpath (for instance, <code>src/main/resources</code>
-            ).
-            Put something like;
-            <span class="javaxcode"><pre>titles=Domain Driven Design, Pragmatic Programmer, Extreme Programming Explained
-authors=Eric Evans, Andy Hunt, Kent Beck
-
-#Number of copies of each book.
-copies=3
-                </pre>
-            </span>
-            in this file.
-        </li>
-        <li>
-            Load initial data from the <code>LibraryConfiguration</code> in the <code>LibraryMixin</code> constructor.
-        </li>
-    </ol>
-</body>
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/Book.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/Book.java
deleted file mode 100644
index 851e89d..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/Book.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.services.step4;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-public interface Book
-    extends ValueComposite
-{
-    Property<String> title();
-
-    Property<String> author();
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/Consumer.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/Consumer.java
deleted file mode 100644
index 8d61ca2..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/Consumer.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard �berg. All Rights Reserved.
- *
- * Licensed 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.qi4j.tutorials.services.step4;
-
-import org.qi4j.api.injection.scope.Service;
-
-/**
- * Simple service consumer. The service is injected using the @Service annotation.
- */
-public class Consumer
-{
-    @Service
-    Library library;
-
-    public void run()
-    {
-        Book book = library.borrowBook( "Eric Evans", "Domain Driven Design" );
-        System.out.println( "Consumer got book: " + book.title().get() + " by " + book.author().get() );
-        library.returnBook( book );
-    }
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/Library.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/Library.java
deleted file mode 100644
index e62c4a9..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/Library.java
+++ /dev/null
@@ -1,26 +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.qi4j.tutorials.services.step4;
-
-public interface Library
-{
-    Book borrowBook( String author, String title );
-
-    void returnBook( Book book );
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/LibraryConfiguration.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/LibraryConfiguration.java
deleted file mode 100644
index 267c801..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/LibraryConfiguration.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.services.step4;
-
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.property.Property;
-
-public interface LibraryConfiguration
-    extends ConfigurationComposite
-{
-    Property<String> titles();
-
-    Property<String> authors();
-
-    Property<Integer> copies();
-}
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/LibraryMixin.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/LibraryMixin.java
deleted file mode 100644
index bd6b989..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/LibraryMixin.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.services.step4;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.StringTokenizer;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-
-public class LibraryMixin
-    implements Library
-{
-    private HashMap<String, ArrayList<Book>> books;
-
-    public LibraryMixin( @This Configuration<LibraryConfiguration> config, @Structure ValueBuilderFactory factory )
-    {
-        books = new HashMap<String, ArrayList<Book>>();
-        String titles = config.get().titles().get();
-        String authors = config.get().authors().get();
-        int copies = config.get().copies().get();
-        StringTokenizer titlesSt = new StringTokenizer( titles, ",", false );
-        StringTokenizer authorSt = new StringTokenizer( authors, ",", false );
-        while( titlesSt.hasMoreTokens() )
-        {
-            String title = titlesSt.nextToken();
-            String author = authorSt.nextToken();
-            createBook( factory, author, title, copies );
-        }
-    }
-
-    @Override
-    public Book borrowBook( String author, String title )
-    {
-        String key = constructKey( author, title );
-        ArrayList<Book> copies = books.get( key );
-        if( copies == null )
-        {
-            System.out.println( "Book not available." );
-            return null; // Indicate that book is not available.
-        }
-        Book book = copies.remove( 0 );
-        if( book == null )
-        {
-            System.out.println( "Book not available." );
-            return null; // Indicate that book is not available.
-        }
-        System.out.println( "Book borrowed: " + book.title().get() + " by " + book.author().get() );
-        return book;
-    }
-
-    @Override
-    public void returnBook( Book book )
-    {
-        System.out.println( "Book returned: " + book.title().get() + " by " + book.author().get() );
-        String key = constructKey( book.author().get(), book.title().get() );
-        ArrayList<Book> copies = books.get( key );
-        if( copies == null )
-        {
-            throw new IllegalStateException( "Book " + book + " was not borrowed here." );
-        }
-        copies.add( book );
-    }
-
-    private void createBook( ValueBuilderFactory factory, String author, String title, int copies )
-    {
-        ArrayList<Book> bookCopies = new ArrayList<Book>();
-        String key = constructKey( author, title );
-        books.put( key, bookCopies );
-
-        for( int i = 0; i < copies; i++ )
-        {
-            ValueBuilder<Book> builder = factory.newValueBuilder( Book.class );
-            Book prototype = builder.prototype();
-            prototype.author().set( author );
-            prototype.title().set( title );
-
-            Book book = builder.newInstance();
-            System.out.println( "Book created: " + book );
-            bookCopies.add( book );
-        }
-    }
-
-    private String constructKey( String author, String title )
-    {
-        return author + "::" + title;
-    }
-}
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/LibraryService.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/LibraryService.java
deleted file mode 100644
index be696c5..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step4/LibraryService.java
+++ /dev/null
@@ -1,28 +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.qi4j.tutorials.services.step4;
-
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.service.ServiceComposite;
-
-@Mixins( LibraryMixin.class )
-public interface LibraryService
-    extends Library, ServiceComposite
-{
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step5/Book.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step5/Book.java
deleted file mode 100644
index 7cbab92..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step5/Book.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.services.step5;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-public interface Book
-    extends ValueComposite
-{
-    Property<String> title();
-
-    Property<String> author();
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step5/Consumer.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step5/Consumer.java
deleted file mode 100644
index 4f8bc7b..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step5/Consumer.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard �berg. All Rights Reserved.
- *
- * Licensed 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.qi4j.tutorials.services.step5;
-
-import org.qi4j.api.injection.scope.Service;
-
-/**
- * Simple service consumer. The service is injected using the @Service annotation.
- */
-public class Consumer
-{
-    @Service
-    Library library;
-
-    public void run()
-    {
-        Book book = library.borrowBook( "Eric Evans", "Domain Driven Design" );
-        System.out.println( "Consumer got book: " + book.title().get() + " by " + book.author().get() );
-        library.returnBook( book );
-    }
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step5/Library.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step5/Library.java
deleted file mode 100644
index bd7e534..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step5/Library.java
+++ /dev/null
@@ -1,26 +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.qi4j.tutorials.services.step5;
-
-public interface Library
-{
-    Book borrowBook( String author, String title );
-
-    void returnBook( Book book );
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step5/LibraryService.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step5/LibraryService.java
deleted file mode 100644
index 6f40aba..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step5/LibraryService.java
+++ /dev/null
@@ -1,129 +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.qi4j.tutorials.services.step5;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.StringTokenizer;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.mixin.Mixins;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.service.ServiceComposite;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-
-@Mixins( LibraryService.LibraryMixin.class )
-public interface LibraryService
-    extends Library, ServiceComposite
-{
-    public static interface LibraryConfiguration
-        extends ConfigurationComposite
-    {
-        Property<String> titles();
-
-        Property<String> authors();
-
-        Property<Integer> copies();
-    }
-
-    public static class LibraryMixin
-        implements Library
-    {
-
-        private HashMap<String, ArrayList<Book>> books;
-
-        public LibraryMixin( @This Configuration<LibraryConfiguration> config,
-                             @Structure ValueBuilderFactory factory
-        )
-        {
-            books = new HashMap<String, ArrayList<Book>>();
-            String titles = config.get().titles().get();
-            String authors = config.get().authors().get();
-            int copies = config.get().copies().get();
-            StringTokenizer titlesSt = new StringTokenizer( titles, ",", false );
-            StringTokenizer authorSt = new StringTokenizer( authors, ",", false );
-            while( titlesSt.hasMoreTokens() )
-            {
-                String title = titlesSt.nextToken();
-                String author = authorSt.nextToken();
-                createBook( factory, author, title, copies );
-            }
-        }
-
-        @Override
-        public Book borrowBook( String author, String title )
-        {
-            String key = constructKey( author, title );
-            ArrayList<Book> copies = books.get( key );
-            if( copies == null )
-            {
-                System.out.println( "Book not available." );
-                return null; // Indicate that book is not available.
-            }
-            Book book = copies.remove( 0 );
-            if( book == null )
-            {
-                System.out.println( "Book not available." );
-                return null; // Indicate that book is not available.
-            }
-            System.out.println( "Book borrowed: " + book.title().get() + " by " + book.author().get() );
-            return book;
-        }
-
-        @Override
-        public void returnBook( Book book )
-        {
-            System.out.println( "Book returned: " + book.title().get() + " by " + book.author().get() );
-            String key = constructKey( book.author().get(), book.title().get() );
-            ArrayList<Book> copies = books.get( key );
-            if( copies == null )
-            {
-                throw new IllegalStateException( "Book " + book + " was not borrowed here." );
-            }
-            copies.add( book );
-        }
-
-        private void createBook( ValueBuilderFactory factory, String author, String title, int copies )
-        {
-            ArrayList<Book> bookCopies = new ArrayList<Book>();
-            String key = constructKey( author, title );
-            books.put( key, bookCopies );
-
-            for( int i = 0; i < copies; i++ )
-            {
-                ValueBuilder<Book> builder = factory.newValueBuilder( Book.class );
-                Book prototype = builder.prototype();
-                prototype.author().set( author );
-                prototype.title().set( title );
-
-                Book book = builder.newInstance();
-                System.out.println( "Book created: " + book );
-                bookCopies.add( book );
-            }
-        }
-
-        private String constructKey( String author, String title )
-        {
-            return author + "::" + title;
-        }
-    }
-}
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step6/Book.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step6/Book.java
deleted file mode 100644
index 567e01c..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step6/Book.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.services.step6;
-
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueComposite;
-
-public interface Book
-    extends ValueComposite
-{
-    Property<String> title();
-
-    Property<String> author();
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step6/Consumer.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step6/Consumer.java
deleted file mode 100644
index 5f569aa..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step6/Consumer.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2008, Rickard �berg. All Rights Reserved.
- *
- * Licensed 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.qi4j.tutorials.services.step6;
-
-import org.qi4j.api.injection.scope.Service;
-
-/**
- * Simple service consumer. The service is injected using the @Service annotation.
- */
-public class Consumer
-{
-    @Service
-    Library library;
-
-    public void run()
-    {
-        Book book = library.borrowBook( "Eric Evans", "Domain Driven Design" );
-        System.out.println( "Consumer got book: " + book.title().get() + " by " + book.author().get() );
-        library.returnBook( book );
-    }
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step6/Library.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step6/Library.java
deleted file mode 100644
index 537a0a3..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step6/Library.java
+++ /dev/null
@@ -1,26 +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.qi4j.tutorials.services.step6;
-
-public interface Library
-{
-    Book borrowBook( String author, String title );
-
-    void returnBook( Book book );
-}
\ No newline at end of file
diff --git a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step6/LibraryService.java b/tutorials/services/src/main/java/org/qi4j/tutorials/services/step6/LibraryService.java
deleted file mode 100644
index 5c6c854..0000000
--- a/tutorials/services/src/main/java/org/qi4j/tutorials/services/step6/LibraryService.java
+++ /dev/null
@@ -1,121 +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.qi4j.tutorials.services.step6;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.StringTokenizer;
-import org.qi4j.api.configuration.Configuration;
-import org.qi4j.api.configuration.ConfigurationComposite;
-import org.qi4j.api.injection.scope.Structure;
-import org.qi4j.api.injection.scope.This;
-import org.qi4j.api.property.Property;
-import org.qi4j.api.value.ValueBuilder;
-import org.qi4j.api.value.ValueBuilderFactory;
-
-public class LibraryService
-    implements Library
-{
-    public static interface LibraryConfiguration
-        extends ConfigurationComposite
-    {
-        Property<String> titles();
-
-        Property<String> authors();
-
-        Property<Integer> copies();
-    }
-
-    private HashMap<String, ArrayList<Book>> books;
-
-    public LibraryService( @This Configuration<LibraryConfiguration> config,
-                         @Structure ValueBuilderFactory factory
-    )
-    {
-        books = new HashMap<String, ArrayList<Book>>();
-        String titles = config.get().titles().get();
-        String authors = config.get().authors().get();
-        int copies = config.get().copies().get();
-        StringTokenizer titlesSt = new StringTokenizer( titles, ",", false );
-        StringTokenizer authorSt = new StringTokenizer( authors, ",", false );
-        while( titlesSt.hasMoreTokens() )
-        {
-            String title = titlesSt.nextToken();
-            String author = authorSt.nextToken();
-            createBook( factory, author, title, copies );
-        }
-    }
-
-    @Override
-    public Book borrowBook( String author, String title )
-    {
-        String key = constructKey( author, title );
-        ArrayList<Book> copies = books.get( key );
-        if( copies == null )
-        {
-            System.out.println( "Book not available." );
-            return null; // Indicate that book is not available.
-        }
-        Book book = copies.remove( 0 );
-        if( book == null )
-        {
-            System.out.println( "Book not available." );
-            return null; // Indicate that book is not available.
-        }
-        System.out.println( "Book borrowed: " + book.title().get() + " by " + book.author().get() );
-        return book;
-    }
-
-    @Override
-    public void returnBook( Book book )
-    {
-        System.out.println( "Book returned: " + book.title().get() + " by " + book.author().get() );
-        String key = constructKey( book.author().get(), book.title().get() );
-        ArrayList<Book> copies = books.get( key );
-        if( copies == null )
-        {
-            throw new IllegalStateException( "Book " + book + " was not borrowed here." );
-        }
-        copies.add( book );
-    }
-
-    private void createBook( ValueBuilderFactory factory, String author, String title, int copies )
-    {
-        ArrayList<Book> bookCopies = new ArrayList<Book>();
-        String key = constructKey( author, title );
-        books.put( key, bookCopies );
-
-        for( int i = 0; i < copies; i++ )
-        {
-            ValueBuilder<Book> builder = factory.newValueBuilder( Book.class );
-            Book prototype = builder.prototype();
-            prototype.author().set( author );
-            prototype.title().set( title );
-
-            Book book = builder.newInstance();
-            System.out.println( "Book created: " + book );
-            bookCopies.add( book );
-        }
-    }
-
-    private String constructKey( String author, String title )
-    {
-        return author + "::" + title;
-    }
-}
diff --git a/tutorials/services/src/main/resources/org/apache/polygene/tutorials/services/step4/LibraryService.properties b/tutorials/services/src/main/resources/org/apache/polygene/tutorials/services/step4/LibraryService.properties
new file mode 100644
index 0000000..2accb55
--- /dev/null
+++ b/tutorials/services/src/main/resources/org/apache/polygene/tutorials/services/step4/LibraryService.properties
@@ -0,0 +1,25 @@
+#
+#  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.
+#
+#
+#
+
+titles=Domain Driven Design, Pragmatic Programmer, Extreme Programming Explained
+authors=Eric Evans, Andy Hunt, Kent Beck
+
+#Number of copies of each book.
+copies=3
\ No newline at end of file
diff --git a/tutorials/services/src/main/resources/org/apache/polygene/tutorials/services/step5/LibraryService.properties b/tutorials/services/src/main/resources/org/apache/polygene/tutorials/services/step5/LibraryService.properties
new file mode 100644
index 0000000..2accb55
--- /dev/null
+++ b/tutorials/services/src/main/resources/org/apache/polygene/tutorials/services/step5/LibraryService.properties
@@ -0,0 +1,25 @@
+#
+#  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.
+#
+#
+#
+
+titles=Domain Driven Design, Pragmatic Programmer, Extreme Programming Explained
+authors=Eric Evans, Andy Hunt, Kent Beck
+
+#Number of copies of each book.
+copies=3
\ No newline at end of file
diff --git a/tutorials/services/src/main/resources/org/apache/polygene/tutorials/services/step6/Library.properties b/tutorials/services/src/main/resources/org/apache/polygene/tutorials/services/step6/Library.properties
new file mode 100644
index 0000000..2accb55
--- /dev/null
+++ b/tutorials/services/src/main/resources/org/apache/polygene/tutorials/services/step6/Library.properties
@@ -0,0 +1,25 @@
+#
+#  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.
+#
+#
+#
+
+titles=Domain Driven Design, Pragmatic Programmer, Extreme Programming Explained
+authors=Eric Evans, Andy Hunt, Kent Beck
+
+#Number of copies of each book.
+copies=3
\ No newline at end of file
diff --git a/tutorials/services/src/main/resources/org/qi4j/tutorials/services/step4/LibraryService.properties b/tutorials/services/src/main/resources/org/qi4j/tutorials/services/step4/LibraryService.properties
deleted file mode 100644
index 90f349c..0000000
--- a/tutorials/services/src/main/resources/org/qi4j/tutorials/services/step4/LibraryService.properties
+++ /dev/null
@@ -1,20 +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.
-
-titles=Domain Driven Design, Pragmatic Programmer, Extreme Programming Explained
-authors=Eric Evans, Andy Hunt, Kent Beck
-
-#Number of copies of each book.
-copies=3
\ No newline at end of file
diff --git a/tutorials/services/src/main/resources/org/qi4j/tutorials/services/step5/LibraryService.properties b/tutorials/services/src/main/resources/org/qi4j/tutorials/services/step5/LibraryService.properties
deleted file mode 100644
index 90f349c..0000000
--- a/tutorials/services/src/main/resources/org/qi4j/tutorials/services/step5/LibraryService.properties
+++ /dev/null
@@ -1,20 +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.
-
-titles=Domain Driven Design, Pragmatic Programmer, Extreme Programming Explained
-authors=Eric Evans, Andy Hunt, Kent Beck
-
-#Number of copies of each book.
-copies=3
\ No newline at end of file
diff --git a/tutorials/services/src/main/resources/org/qi4j/tutorials/services/step6/Library.properties b/tutorials/services/src/main/resources/org/qi4j/tutorials/services/step6/Library.properties
deleted file mode 100644
index 90f349c..0000000
--- a/tutorials/services/src/main/resources/org/qi4j/tutorials/services/step6/Library.properties
+++ /dev/null
@@ -1,20 +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.
-
-titles=Domain Driven Design, Pragmatic Programmer, Extreme Programming Explained
-authors=Eric Evans, Andy Hunt, Kent Beck
-
-#Number of copies of each book.
-copies=3
\ No newline at end of file
diff --git a/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step1/LibraryTest.java b/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step1/LibraryTest.java
new file mode 100644
index 0000000..0928f95
--- /dev/null
+++ b/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step1/LibraryTest.java
@@ -0,0 +1,33 @@
+/*
+ *  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.polygene.tutorials.services.step1;
+
+import org.junit.Test;
+
+public class LibraryTest
+{
+    @Test
+    public void testLibrary()
+        throws Exception
+    {
+        Consumer consumer = new Consumer( new Library() );
+        consumer.run();
+    }
+}
diff --git a/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step2/LibraryTest.java b/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step2/LibraryTest.java
new file mode 100644
index 0000000..440b9bb
--- /dev/null
+++ b/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step2/LibraryTest.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.tutorials.services.step2;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+public class LibraryTest
+    extends AbstractPolygeneTest
+{
+    @Test
+    public void testLibrary()
+        throws Exception
+    {
+        Consumer consumer = objectFactory.newObject( Consumer.class );
+        consumer.run();
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( LibraryService.class );
+        module.values( Book.class );
+        module.objects( Consumer.class );
+    }
+}
diff --git a/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step3/LibraryTest.java b/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step3/LibraryTest.java
new file mode 100644
index 0000000..f3c0197
--- /dev/null
+++ b/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step3/LibraryTest.java
@@ -0,0 +1,46 @@
+/*
+ *  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.polygene.tutorials.services.step3;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+public class LibraryTest
+    extends AbstractPolygeneTest
+{
+    @Test
+    public void testLibrary()
+        throws Exception
+    {
+        Consumer consumer = objectFactory.newObject( Consumer.class );
+        consumer.run();
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( LibraryService.class );
+        module.values( Book.class );
+        module.objects( Consumer.class );
+    }
+}
diff --git a/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step4/LibraryTest.java b/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step4/LibraryTest.java
new file mode 100644
index 0000000..c62d14d
--- /dev/null
+++ b/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step4/LibraryTest.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.tutorials.services.step4;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+public class LibraryTest
+    extends AbstractPolygeneTest
+{
+    @Test
+    public void testLibrary()
+        throws Exception
+    {
+        Consumer consumer = objectFactory.newObject( Consumer.class );
+        consumer.run();
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( LibraryService.class );
+        module.values( Book.class );
+        module.objects( Consumer.class );
+        module.entities( LibraryConfiguration.class );
+        new EntityTestAssembler().assemble( module );
+    }
+}
diff --git a/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step5/LibraryTest.java b/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step5/LibraryTest.java
new file mode 100644
index 0000000..64f74d8
--- /dev/null
+++ b/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step5/LibraryTest.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.tutorials.services.step5;
+
+import org.junit.Test;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.apache.polygene.test.EntityTestAssembler;
+
+public class LibraryTest
+    extends AbstractPolygeneTest
+{
+    @Test
+    public void testLibrary()
+        throws Exception
+    {
+        Consumer consumer = objectFactory.newObject( Consumer.class );
+        consumer.run();
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( LibraryService.class );
+        module.values( Book.class );
+        module.objects( Consumer.class );
+        module.entities( LibraryService.LibraryConfiguration.class );
+        new EntityTestAssembler().assemble( module );
+    }
+}
\ No newline at end of file
diff --git a/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step6/LibraryTest.java b/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step6/LibraryTest.java
new file mode 100644
index 0000000..b13b7da
--- /dev/null
+++ b/tutorials/services/src/test/java/org/apache/polygene/tutorials/services/step6/LibraryTest.java
@@ -0,0 +1,49 @@
+/*
+ *  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.polygene.tutorials.services.step6;
+
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Test;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.test.EntityTestAssembler;
+
+public class LibraryTest
+    extends AbstractPolygeneTest
+{
+    @Test
+    public void testLibrary()
+        throws Exception
+    {
+        Consumer consumer = objectFactory.newObject( Consumer.class );
+        consumer.run();
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.services( Library.class ).withMixins( LibraryService.class );
+        module.values( Book.class );
+        module.objects( Consumer.class );
+        module.entities( LibraryService.LibraryConfiguration.class );
+        new EntityTestAssembler().assemble( module );
+    }
+}
\ No newline at end of file
diff --git a/tutorials/services/src/test/java/org/qi4j/tutorials/services/step1/LibraryTest.java b/tutorials/services/src/test/java/org/qi4j/tutorials/services/step1/LibraryTest.java
deleted file mode 100644
index 4cd8c7c..0000000
--- a/tutorials/services/src/test/java/org/qi4j/tutorials/services/step1/LibraryTest.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.services.step1;
-
-import org.junit.Test;
-
-public class LibraryTest
-{
-    @Test
-    public void testLibrary()
-        throws Exception
-    {
-        Consumer consumer = new Consumer( new Library() );
-        consumer.run();
-    }
-}
diff --git a/tutorials/services/src/test/java/org/qi4j/tutorials/services/step2/LibraryTest.java b/tutorials/services/src/test/java/org/qi4j/tutorials/services/step2/LibraryTest.java
deleted file mode 100644
index db9de90..0000000
--- a/tutorials/services/src/test/java/org/qi4j/tutorials/services/step2/LibraryTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.services.step2;
-
-import org.junit.Test;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-public class LibraryTest
-    extends AbstractQi4jTest
-{
-    @Test
-    public void testLibrary()
-        throws Exception
-    {
-        Consumer consumer = module.newObject( Consumer.class );
-        consumer.run();
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( LibraryService.class );
-        module.values( Book.class );
-        module.objects( Consumer.class );
-    }
-}
diff --git a/tutorials/services/src/test/java/org/qi4j/tutorials/services/step3/LibraryTest.java b/tutorials/services/src/test/java/org/qi4j/tutorials/services/step3/LibraryTest.java
deleted file mode 100644
index 0b934b2..0000000
--- a/tutorials/services/src/test/java/org/qi4j/tutorials/services/step3/LibraryTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.services.step3;
-
-import org.junit.Test;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-
-public class LibraryTest
-    extends AbstractQi4jTest
-{
-    @Test
-    public void testLibrary()
-        throws Exception
-    {
-        Consumer consumer = module.newObject( Consumer.class );
-        consumer.run();
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( LibraryService.class );
-        module.values( Book.class );
-        module.objects( Consumer.class );
-    }
-}
diff --git a/tutorials/services/src/test/java/org/qi4j/tutorials/services/step4/LibraryTest.java b/tutorials/services/src/test/java/org/qi4j/tutorials/services/step4/LibraryTest.java
deleted file mode 100644
index d7609ce..0000000
--- a/tutorials/services/src/test/java/org/qi4j/tutorials/services/step4/LibraryTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.services.step4;
-
-import org.junit.Test;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-public class LibraryTest
-    extends AbstractQi4jTest
-{
-    @Test
-    public void testLibrary()
-        throws Exception
-    {
-        Consumer consumer = module.newObject( Consumer.class );
-        consumer.run();
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( LibraryService.class );
-        module.values( Book.class );
-        module.objects( Consumer.class );
-        module.entities( LibraryConfiguration.class );
-        new EntityTestAssembler().assemble( module );
-    }
-}
diff --git a/tutorials/services/src/test/java/org/qi4j/tutorials/services/step5/LibraryTest.java b/tutorials/services/src/test/java/org/qi4j/tutorials/services/step5/LibraryTest.java
deleted file mode 100644
index 08f2bd0..0000000
--- a/tutorials/services/src/test/java/org/qi4j/tutorials/services/step5/LibraryTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.services.step5;
-
-import org.junit.Test;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-public class LibraryTest
-    extends AbstractQi4jTest
-{
-    @Test
-    public void testLibrary()
-        throws Exception
-    {
-        Consumer consumer = module.newObject( Consumer.class );
-        consumer.run();
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( LibraryService.class );
-        module.values( Book.class );
-        module.objects( Consumer.class );
-        module.entities( LibraryService.LibraryConfiguration.class );
-        new EntityTestAssembler().assemble( module );
-    }
-}
\ No newline at end of file
diff --git a/tutorials/services/src/test/java/org/qi4j/tutorials/services/step6/LibraryTest.java b/tutorials/services/src/test/java/org/qi4j/tutorials/services/step6/LibraryTest.java
deleted file mode 100644
index f008383..0000000
--- a/tutorials/services/src/test/java/org/qi4j/tutorials/services/step6/LibraryTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2009 Niclas Hedhman.
- *
- * Licensed  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.qi4j.tutorials.services.step6;
-
-import org.junit.Test;
-import org.qi4j.bootstrap.AssemblyException;
-import org.qi4j.bootstrap.ModuleAssembly;
-import org.qi4j.test.AbstractQi4jTest;
-import org.qi4j.test.EntityTestAssembler;
-
-public class LibraryTest
-    extends AbstractQi4jTest
-{
-    @Test
-    public void testLibrary()
-        throws Exception
-    {
-        Consumer consumer = module.newObject( Consumer.class );
-        consumer.run();
-    }
-
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( Library.class ).withMixins( LibraryService.class );
-        module.values( Book.class );
-        module.objects( Consumer.class );
-        module.entities( LibraryService.LibraryConfiguration.class );
-        new EntityTestAssembler().assemble( module );
-    }
-}
\ No newline at end of file